Skip to content

Instantly share code, notes, and snippets.

@lostintangent
Last active January 12, 2020 23:01
Show Gist options
  • Select an option

  • Save lostintangent/9ac5753b8abf8776ba7a7e40635d9592 to your computer and use it in GitHub Desktop.

Select an option

Save lostintangent/9ac5753b8abf8776ba7a7e40635d9592 to your computer and use it in GitHub Desktop.
Deep Sea Trench
<!-- Vertex Shader -->
<script id="vertexShader" type="x-shader/x-vertex">
varying vec2 vUv;
varying vec3 vNormal;
void main() {
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * mvPosition;
vNormal = normalize(normalMatrix * normal);
}
</script>
<!-- Fragment Shader -->
<script id="obliqueLineFragmentShader" type="x-shader/x-fragment">
#ifdef GL_ES
precision mediump float;
#endif
#define PI 3.14159265359
uniform float time;
uniform vec2 resolution;
uniform vec3 dirLightPos;
uniform vec3 dirLightColor;
uniform vec3 ambientLightColor;
varying vec2 vUv;
varying vec3 vNormal;
float map(float value, float beforeMin, float beforeMax, float afterMin, float afterMax) {
return afterMin + (afterMax - afterMin) * ((value - beforeMin) / (beforeMax - beforeMin));
}
mat2 rotate2d(float angle){
return mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
}
float obliqueLine(vec2 uv){
return step(0.6, fract((uv.x + uv.y + time * 0.8) * 2.0));
}
void main( void ) {
vec2 uv = 2.0 * vUv - 1.0;
float directionalLightWeighting = max(dot(normalize(vNormal), dirLightPos), 0.0);
vec3 lightWeighting = ambientLightColor + dirLightColor * directionalLightWeighting;
vec3 ballColor = vec3(0.139,0.000,0.426);
vec3 shadowColor = vec3(0.0, 1.0, 1.0);
vec3 color = mix(ballColor, shadowColor, directionalLightWeighting);
color += obliqueLine(uv * 4.0);
gl_FragColor = vec4(color, 1.0);
}
</script>
<script id="particleVertexShader" type="x-shader/x-vertex">
attribute vec3 color;
uniform float time;
uniform float size;
varying vec4 vMvPosition;
varying vec3 vColor;
float map(float value, float beforeMin, float beforeMax, float afterMin, float afterMax) {
return afterMin + (afterMax - afterMin) * ((value - beforeMin) / (beforeMax - beforeMin));
}
void main() {
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
vMvPosition = mvPosition;
vColor = color;
gl_PointSize = (size + map(sin(time * 0.05), -1.0, 1.0, 0.0, 100.0)) * (100.0 / length(mvPosition.xyz));
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script id="particleFragmentShader" type="x-shader/x-fragment">
uniform sampler2D texture;
uniform float time;
varying vec4 vMvPosition;
varying vec3 vColor;
void main() {
float opacity = 200.0 / length(vMvPosition.xyz);
vec2 uv = gl_PointCoord.xy * 2.0 - 1.0;
float orb = 0.1 / length(vec2(0.0) - uv) * step(0.5, 1.0 - length(uv));
orb = smoothstep(0.0, 1.0, orb);
vec3 color = vec3(orb) * vColor;
gl_FragColor = vec4(color, 1.0);
}
</script>
initMarchingCube();
const vertexShader = document.getElementById('vertexShader').textContent;
const obliqueLineFragmentShader = document.getElementById('obliqueLineFragmentShader').textContent;
const particleVertexShader = document.getElementById('particleVertexShader').textContent;
const particleFragmentShader = document.getElementById('particleFragmentShader').textContent;
let windowWidth = window.innerWidth;
let windowHeight = window.innerHeight;
let scene, camera, clock, marchingCubes, renderer, light, pointLight, ambientLight;
let groundGeometry, groundMesh;
let blobsCount = 30;
let updatingCubeSpeedOffset = 1.6;
let groundVertexOffset = 3;
let particlePoints;
let icosahedronGroup = new THREE.Group();
const uniform = {
time: {
type: 'f',
value: 1.0
},
resolution: {
type: "v2",
value: new THREE.Vector2()
},
dirLightPos: {
type: "v3",
value: new THREE.Vector3()
},
dirLightColor: {
type: "v3",
value: new THREE.Color(0xeeeeee)
},
ambientLightColor: {
type: "v3",
value: new THREE.Color(0x050505)
},
size: {
type: 'f',
value: 32.0
},
};
const init = () => {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xff0099);
scene.fog = new THREE.FogExp2(0xff0099, 0.0003);
clock = new THREE.Clock();
// Camera
camera = new THREE.PerspectiveCamera(45, windowWidth / windowHeight, 1, 10000);
camera.position.set(0, 100, 300);
// Light
light = new THREE.DirectionalLight(0xffffff);
light.position.set(0.0, 0.0, 0.0);
scene.add(light);
pointLight = new THREE.PointLight(0x00E4BB, 30, 150);
pointLight.position.set(0, -150, 0);
scene.add(pointLight);
ambientLight = new THREE.AmbientLight(0x00E4BB);
ambientLight.position.set(0, -1.0, 0);
scene.add(ambientLight);
// Ground
groundGeometry = new THREE.PlaneBufferGeometry(20000, 20000, 128, 128);
groundGeometry.rotateX(-Math.PI / 2);
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('https://s3-us-west-2.amazonaws.com/s.cdpn.io/64807/plastic.jpg'); // Refer to remote URL to access locally.
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(5, 5);
const groundMaterial = new THREE.MeshBasicMaterial({
color: 0x00E4BB,
map: texture,
});
groundMesh = new THREE.Mesh(groundGeometry, groundMaterial);
groundMesh.position.set(0, -500, 0);
scene.add(groundMesh);
// Blobs
uniform.resolution = new THREE.Vector2(windowWidth, windowHeight);
uniform.dirLightPos.value = light.position;
uniform.dirLightColor.value = light.color;
uniform.ambientLightColor.value = ambientLight.color;
const material = new THREE.ShaderMaterial({
uniforms: uniform,
vertexShader: vertexShader,
fragmentShader: obliqueLineFragmentShader,
});
const resolution = 48;
marchingCubes = new THREE.MarchingCubes(resolution, material, true, true);
marchingCubes.position.set(0, 0, 0);
marchingCubes.scale.set(100, 100, 100);
scene.add(marchingCubes);
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(windowWidth, windowHeight);
document.body.appendChild(renderer.domElement);
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.autoClear = false;
addParticles();
addIcosahedrons();
};
const updateCubes = (object, time) => {
object.reset();
let i, ballx, bally, ballz, subtract, strength;
subtract = 18;
strength = 1.2 / ((Math.sqrt(blobsCount) - 1) / 4 + 1);
for (i = 0; i < blobsCount; i++) {
ballx = Math.sin(i + 1.26 * time * (1.03 + 0.5 * Math.cos(0.21 * i))) * 0.27 + 0.5;
bally = Math.cos(i + 1.12 * time * Math.cos(1.22 + 0.1424 * i)) * 0.27 + 0.5;
ballz = Math.cos(i + 1.32 * time * 0.1 * Math.sin((0.92 + 0.53 * i))) * 0.27 + 0.5;
object.addBall(ballx, bally, ballz, strength, subtract);
}
};
const updateGround = (time) => {
const position = groundGeometry.attributes.position;
for (let i = 0, len = position.count; i < len; i++) {
let y = 30 * Math.sin(i / 2 + (time * 5 + i));
if (i % 14 === 0) {
y *= groundVertexOffset;
}
position.setY(i, y);
}
position.needsUpdate = true;
};
const render = (t) => {
TWEEN.update(t);
clock.getDelta();
const time = clock.elapsedTime;
updateGround(time);
updateCubes(marchingCubes, time * updatingCubeSpeedOffset);
const cubesRotationSpeed = time * 0.5;
marchingCubes.rotation.x = cubesRotationSpeed;
marchingCubes.rotation.y = cubesRotationSpeed;
marchingCubes.rotation.z = cubesRotationSpeed;
const speed = time * 30 * (Math.PI / 180);
const cameraX = 300 * Math.sin(speed);
const cameraZ = 300 * Math.cos(speed);
camera.position.x = cameraX;
camera.position.z = cameraZ;
camera.position.y = cameraX * 0.3;
camera.lookAt(new THREE.Vector3(0, 0, 0));
uniform.time.value = time;
let len = icosahedronGroup.children.length;
if (len > 0) {
for (let i = 0; i < len; i++) {
let object = icosahedronGroup.children[i];
let geometry = object.geometry;
geometry.verticesNeedUpdate = true;
let originalVertices = icosahedronOriginalVerticesArray[i];
for (let i = 0, len = geometry.vertices.length; i < len; i++) {
let t = time * 8 + i * 300;
let offset = 5;
geometry.vertices[i].x = originalVertices[i].x + Math.sin(t) * offset;
geometry.vertices[i].y = originalVertices[i].y + Math.sin(t * 0.8) * offset;
}
const t = time * 5 + (i % 4) * 80;
object.scale.x = 1.0 + Math.abs(Math.sin(t));
object.scale.y = 1.0 + Math.abs(Math.sin(t));
object.scale.z = 1.0 + Math.abs(Math.sin(t));
}
}
renderer.render(scene, camera);
requestAnimationFrame(render);
};
const addParticles = () => {
scene.remove(marchingCubes);
const material1 = new THREE.ShaderMaterial({
uniforms: uniform,
vertexShader: vertexShader,
fragmentShader: obliqueLineFragmentShader,
});
const resolution = 48;
marchingCubes = new THREE.MarchingCubes(resolution, material1, true, true);
marchingCubes.position.set(0, 0, 0);
marchingCubes.scale.set(100, 100, 100);
scene.add(marchingCubes);
scene.background = new THREE.Color(0x4623DE);
scene.fog = new THREE.FogExp2(0x4623DE, 0.0003);
let colorsPerFace = [
"#7BFFEF", "#6FE8B8", "#7FFFAC", "#6FE873", "#FFDEAA"
];
const hexToRgb = (hex) => {
let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return {
r: parseInt(result[1], 16) / 255,
g: parseInt(result[2], 16) / 255,
b: parseInt(result[3], 16) / 255
};
};
const vertices = [];
const colors = [];
const particleCount = 20000;
const geometry = new THREE.BufferGeometry();
const dist = window.innerWidth * 0.8;
for (let i = 0; i < particleCount; i++) {
const x = Math.floor(Math.random() * dist - dist / 2);
const y = Math.floor(Math.random() * dist - dist / 2);
const z = Math.floor(Math.random() * dist - dist / 2);
vertices.push(x, y, z);
const rgbColor = hexToRgb(colorsPerFace[Math.floor(Math.random() * colorsPerFace.length)]);
colors.push(rgbColor.r, rgbColor.g, rgbColor.b);
}
const verticesArray = new Float32Array(vertices);
geometry.addAttribute('position', new THREE.BufferAttribute(verticesArray, 3));
const colorsArray = new Float32Array(colors);
geometry.addAttribute('color', new THREE.BufferAttribute(colorsArray, 3));
const material2 = new THREE.ShaderMaterial({
uniforms: uniform,
vertexShader: particleVertexShader,
fragmentShader: particleFragmentShader,
transparent: true,
depthWrite: false,
blending: THREE.AdditiveBlending
});
particlePoints = new THREE.Points(geometry, material2);
scene.add(particlePoints);
};
/**
* Show icosahedron.
*/
const addIcosahedrons = () => {
const objectRadius = 30;
const count = 18;
const dist = 600;
for (let i = 0; i < count; i++) {
const angle = 360 / count * Math.PI / 180 * i;
icosahedronGroup.add(createIcosahedron(objectRadius, {
x: Math.cos(angle) * dist,
y: 0,
z: Math.sin(angle) * dist
}));
}
scene.add(icosahedronGroup);
};
let colorsPerFace = [
0x20D8D6, 0x31A3A2, 0x53B9B8, 0x71BCBB, 0xA3DAD9
];
const icosahedronOriginalVerticesArray = [];
const createIcosahedron = (radius, position) => {
let originalVertices = [];
let geometry = new THREE.IcosahedronGeometry(radius);
for (let i = 0, len = geometry.faces.length; i < len; i++) {
let face = geometry.faces[i];
face.color.setHex(colorsPerFace[Math.floor(Math.random() * colorsPerFace.length)]);
}
for (let i = 0, len = geometry.vertices.length; i < len; i++) {
let vertex = geometry.vertices[i];
originalVertices.push({
x: vertex.x,
y: vertex.y
});
}
let material = new THREE.MeshBasicMaterial({
vertexColors: THREE.FaceColors
});
let obj = new THREE.Mesh(geometry, material);
obj.position.x = position.x;
obj.position.y = position.y;
obj.position.z = position.z;
obj.castShadow = true;
icosahedronOriginalVerticesArray.push(originalVertices);
return obj;
};
const onResize = () => {
windowWidth = window.innerWidth;
windowHeight = window.innerHeight;
camera.aspect = windowWidth / windowHeight;
camera.updateProjectionMatrix();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(windowWidth, windowHeight);
};
window.addEventListener("resize", onResize);
init();
onResize();
render();
function initMarchingCube() {
/**
* @author alteredq / http://alteredqualia.com/
* @author mrdoob / http://mrdoob.com
* Port of http://webglsamples.org/blob/blob.html
*/
THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors ) {
THREE.ImmediateRenderObject.call( this, material );
var scope = this;
// temp buffers used in polygonize
var vlist = new Float32Array( 12 * 3 );
var nlist = new Float32Array( 12 * 3 );
this.enableUvs = enableUvs !== undefined ? enableUvs : false;
this.enableColors = enableColors !== undefined ? enableColors : false;
// functions have to be object properties
// prototype functions kill performance
// (tested and it was 4x slower !!!)
this.init = function ( resolution ) {
this.resolution = resolution;
// parameters
this.isolation = 80.0;
// size of field, 32 is pushing it in Javascript :)
this.size = resolution;
this.size2 = this.size * this.size;
this.size3 = this.size2 * this.size;
this.halfsize = this.size / 2.0;
// deltas
this.delta = 2.0 / this.size;
this.yd = this.size;
this.zd = this.size2;
this.field = new Float32Array( this.size3 );
this.normal_cache = new Float32Array( this.size3 * 3 );
// immediate render mode simulator
this.maxCount = 4096; // TODO: find the fastest size for this buffer
this.count = 0;
this.hasPositions = false;
this.hasNormals = false;
this.hasColors = false;
this.hasUvs = false;
this.positionArray = new Float32Array( this.maxCount * 3 );
this.normalArray = new Float32Array( this.maxCount * 3 );
if ( this.enableUvs ) {
this.uvArray = new Float32Array( this.maxCount * 2 );
}
if ( this.enableColors ) {
this.colorArray = new Float32Array( this.maxCount * 3 );
}
};
///////////////////////
// Polygonization
///////////////////////
function lerp( a, b, t ) {
return a + ( b - a ) * t;
}
function VIntX( q, offset, isol, x, y, z, valp1, valp2 ) {
var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
nc = scope.normal_cache;
vlist[ offset + 0 ] = x + mu * scope.delta;
vlist[ offset + 1 ] = y;
vlist[ offset + 2 ] = z;
nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q + 3 ], mu );
nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q + 4 ], mu );
nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q + 5 ], mu );
}
function VIntY( q, offset, isol, x, y, z, valp1, valp2 ) {
var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
nc = scope.normal_cache;
vlist[ offset + 0 ] = x;
vlist[ offset + 1 ] = y + mu * scope.delta;
vlist[ offset + 2 ] = z;
var q2 = q + scope.yd * 3;
nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q2 + 0 ], mu );
nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu );
nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu );
}
function VIntZ( q, offset, isol, x, y, z, valp1, valp2 ) {
var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
nc = scope.normal_cache;
vlist[ offset + 0 ] = x;
vlist[ offset + 1 ] = y;
vlist[ offset + 2 ] = z + mu * scope.delta;
var q2 = q + scope.zd * 3;
nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q2 + 0 ], mu );
nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu );
nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu );
}
function compNorm( q ) {
var q3 = q * 3;
if ( scope.normal_cache[ q3 ] === 0.0 ) {
scope.normal_cache[ q3 + 0 ] = scope.field[ q - 1 ] - scope.field[ q + 1 ];
scope.normal_cache[ q3 + 1 ] = scope.field[ q - scope.yd ] - scope.field[ q + scope.yd ];
scope.normal_cache[ q3 + 2 ] = scope.field[ q - scope.zd ] - scope.field[ q + scope.zd ];
}
}
// Returns total number of triangles. Fills triangles.
// (this is where most of time is spent - it's inner work of O(n3) loop )
function polygonize( fx, fy, fz, q, isol, renderCallback ) {
// cache indices
var q1 = q + 1,
qy = q + scope.yd,
qz = q + scope.zd,
q1y = q1 + scope.yd,
q1z = q1 + scope.zd,
qyz = q + scope.yd + scope.zd,
q1yz = q1 + scope.yd + scope.zd;
var cubeindex = 0,
field0 = scope.field[ q ],
field1 = scope.field[ q1 ],
field2 = scope.field[ qy ],
field3 = scope.field[ q1y ],
field4 = scope.field[ qz ],
field5 = scope.field[ q1z ],
field6 = scope.field[ qyz ],
field7 = scope.field[ q1yz ];
if ( field0 < isol ) cubeindex |= 1;
if ( field1 < isol ) cubeindex |= 2;
if ( field2 < isol ) cubeindex |= 8;
if ( field3 < isol ) cubeindex |= 4;
if ( field4 < isol ) cubeindex |= 16;
if ( field5 < isol ) cubeindex |= 32;
if ( field6 < isol ) cubeindex |= 128;
if ( field7 < isol ) cubeindex |= 64;
// if cube is entirely in/out of the surface - bail, nothing to draw
var bits = THREE.edgeTable[ cubeindex ];
if ( bits === 0 ) return 0;
var d = scope.delta,
fx2 = fx + d,
fy2 = fy + d,
fz2 = fz + d;
// top of the cube
if ( bits & 1 ) {
compNorm( q );
compNorm( q1 );
VIntX( q * 3, 0, isol, fx, fy, fz, field0, field1 );
}
if ( bits & 2 ) {
compNorm( q1 );
compNorm( q1y );
VIntY( q1 * 3, 3, isol, fx2, fy, fz, field1, field3 );
}
if ( bits & 4 ) {
compNorm( qy );
compNorm( q1y );
VIntX( qy * 3, 6, isol, fx, fy2, fz, field2, field3 );
}
if ( bits & 8 ) {
compNorm( q );
compNorm( qy );
VIntY( q * 3, 9, isol, fx, fy, fz, field0, field2 );
}
// bottom of the cube
if ( bits & 16 ) {
compNorm( qz );
compNorm( q1z );
VIntX( qz * 3, 12, isol, fx, fy, fz2, field4, field5 );
}
if ( bits & 32 ) {
compNorm( q1z );
compNorm( q1yz );
VIntY( q1z * 3, 15, isol, fx2, fy, fz2, field5, field7 );
}
if ( bits & 64 ) {
compNorm( qyz );
compNorm( q1yz );
VIntX( qyz * 3, 18, isol, fx, fy2, fz2, field6, field7 );
}
if ( bits & 128 ) {
compNorm( qz );
compNorm( qyz );
VIntY( qz * 3, 21, isol, fx, fy, fz2, field4, field6 );
}
// vertical lines of the cube
if ( bits & 256 ) {
compNorm( q );
compNorm( qz );
VIntZ( q * 3, 24, isol, fx, fy, fz, field0, field4 );
}
if ( bits & 512 ) {
compNorm( q1 );
compNorm( q1z );
VIntZ( q1 * 3, 27, isol, fx2, fy, fz, field1, field5 );
}
if ( bits & 1024 ) {
compNorm( q1y );
compNorm( q1yz );
VIntZ( q1y * 3, 30, isol, fx2, fy2, fz, field3, field7 );
}
if ( bits & 2048 ) {
compNorm( qy );
compNorm( qyz );
VIntZ( qy * 3, 33, isol, fx, fy2, fz, field2, field6 );
}
cubeindex <<= 4; // re-purpose cubeindex into an offset into triTable
var o1, o2, o3, numtris = 0, i = 0;
// here is where triangles are created
while ( THREE.triTable[ cubeindex + i ] != - 1 ) {
o1 = cubeindex + i;
o2 = o1 + 1;
o3 = o1 + 2;
posnormtriv( vlist, nlist,
3 * THREE.triTable[ o1 ],
3 * THREE.triTable[ o2 ],
3 * THREE.triTable[ o3 ],
renderCallback );
i += 3;
numtris ++;
}
return numtris;
}
/////////////////////////////////////
// Immediate render mode simulator
/////////////////////////////////////
function posnormtriv( pos, norm, o1, o2, o3, renderCallback ) {
var c = scope.count * 3;
// positions
scope.positionArray[ c + 0 ] = pos[ o1 ];
scope.positionArray[ c + 1 ] = pos[ o1 + 1 ];
scope.positionArray[ c + 2 ] = pos[ o1 + 2 ];
scope.positionArray[ c + 3 ] = pos[ o2 ];
scope.positionArray[ c + 4 ] = pos[ o2 + 1 ];
scope.positionArray[ c + 5 ] = pos[ o2 + 2 ];
scope.positionArray[ c + 6 ] = pos[ o3 ];
scope.positionArray[ c + 7 ] = pos[ o3 + 1 ];
scope.positionArray[ c + 8 ] = pos[ o3 + 2 ];
// normals
if ( scope.material.flatShading === true ) {
var nx = ( norm[ o1 + 0 ] + norm[ o2 + 0 ] + norm[ o3 + 0 ] ) / 3;
var ny = ( norm[ o1 + 1 ] + norm[ o2 + 1 ] + norm[ o3 + 1 ] ) / 3;
var nz = ( norm[ o1 + 2 ] + norm[ o2 + 2 ] + norm[ o3 + 2 ] ) / 3;
scope.normalArray[ c + 0 ] = nx;
scope.normalArray[ c + 1 ] = ny;
scope.normalArray[ c + 2 ] = nz;
scope.normalArray[ c + 3 ] = nx;
scope.normalArray[ c + 4 ] = ny;
scope.normalArray[ c + 5 ] = nz;
scope.normalArray[ c + 6 ] = nx;
scope.normalArray[ c + 7 ] = ny;
scope.normalArray[ c + 8 ] = nz;
} else {
scope.normalArray[ c + 0 ] = norm[ o1 + 0 ];
scope.normalArray[ c + 1 ] = norm[ o1 + 1 ];
scope.normalArray[ c + 2 ] = norm[ o1 + 2 ];
scope.normalArray[ c + 3 ] = norm[ o2 + 0 ];
scope.normalArray[ c + 4 ] = norm[ o2 + 1 ];
scope.normalArray[ c + 5 ] = norm[ o2 + 2 ];
scope.normalArray[ c + 6 ] = norm[ o3 + 0 ];
scope.normalArray[ c + 7 ] = norm[ o3 + 1 ];
scope.normalArray[ c + 8 ] = norm[ o3 + 2 ];
}
// uvs
if ( scope.enableUvs ) {
var d = scope.count * 2;
scope.uvArray[ d + 0 ] = pos[ o1 + 0 ];
scope.uvArray[ d + 1 ] = pos[ o1 + 2 ];
scope.uvArray[ d + 2 ] = pos[ o2 + 0 ];
scope.uvArray[ d + 3 ] = pos[ o2 + 2 ];
scope.uvArray[ d + 4 ] = pos[ o3 + 0 ];
scope.uvArray[ d + 5 ] = pos[ o3 + 2 ];
}
// colors
if ( scope.enableColors ) {
scope.colorArray[ c + 0 ] = pos[ o1 + 0 ];
scope.colorArray[ c + 1 ] = pos[ o1 + 1 ];
scope.colorArray[ c + 2 ] = pos[ o1 + 2 ];
scope.colorArray[ c + 3 ] = pos[ o2 + 0 ];
scope.colorArray[ c + 4 ] = pos[ o2 + 1 ];
scope.colorArray[ c + 5 ] = pos[ o2 + 2 ];
scope.colorArray[ c + 6 ] = pos[ o3 + 0 ];
scope.colorArray[ c + 7 ] = pos[ o3 + 1 ];
scope.colorArray[ c + 8 ] = pos[ o3 + 2 ];
}
scope.count += 3;
if ( scope.count >= scope.maxCount - 3 ) {
scope.hasPositions = true;
scope.hasNormals = true;
if ( scope.enableUvs ) {
scope.hasUvs = true;
}
if ( scope.enableColors ) {
scope.hasColors = true;
}
renderCallback( scope );
}
}
this.begin = function () {
this.count = 0;
this.hasPositions = false;
this.hasNormals = false;
this.hasUvs = false;
this.hasColors = false;
};
this.end = function ( renderCallback ) {
if ( this.count === 0 ) return;
for ( var i = this.count * 3; i < this.positionArray.length; i ++ ) {
this.positionArray[ i ] = 0.0;
}
this.hasPositions = true;
this.hasNormals = true;
if ( this.enableUvs && this.material.map ) {
this.hasUvs = true;
}
if ( this.enableColors && this.material.vertexColors !== THREE.NoColors ) {
this.hasColors = true;
}
renderCallback( this );
};
/////////////////////////////////////
// Metaballs
/////////////////////////////////////
// Adds a reciprocal ball (nice and blobby) that, to be fast, fades to zero after
// a fixed distance, determined by strength and subtract.
this.addBall = function ( ballx, bally, ballz, strength, subtract ) {
var sign = Math.sign( strength );
strength = Math.abs( strength );
// Let's solve the equation to find the radius:
// 1.0 / (0.000001 + radius^2) * strength - subtract = 0
// strength / (radius^2) = subtract
// strength = subtract * radius^2
// radius^2 = strength / subtract
// radius = sqrt(strength / subtract)
var radius = this.size * Math.sqrt( strength / subtract ),
zs = ballz * this.size,
ys = bally * this.size,
xs = ballx * this.size;
var min_z = Math.floor( zs - radius ); if ( min_z < 1 ) min_z = 1;
var max_z = Math.floor( zs + radius ); if ( max_z > this.size - 1 ) max_z = this.size - 1;
var min_y = Math.floor( ys - radius ); if ( min_y < 1 ) min_y = 1;
var max_y = Math.floor( ys + radius ); if ( max_y > this.size - 1 ) max_y = this.size - 1;
var min_x = Math.floor( xs - radius ); if ( min_x < 1 ) min_x = 1;
var max_x = Math.floor( xs + radius ); if ( max_x > this.size - 1 ) max_x = this.size - 1;
// Don't polygonize in the outer layer because normals aren't
// well-defined there.
var x, y, z, y_offset, z_offset, fx, fy, fz, fz2, fy2, val;
for ( z = min_z; z < max_z; z ++ ) {
z_offset = this.size2 * z;
fz = z / this.size - ballz;
fz2 = fz * fz;
for ( y = min_y; y < max_y; y ++ ) {
y_offset = z_offset + this.size * y;
fy = y / this.size - bally;
fy2 = fy * fy;
for ( x = min_x; x < max_x; x ++ ) {
fx = x / this.size - ballx;
val = strength / ( 0.000001 + fx * fx + fy2 + fz2 ) - subtract;
if ( val > 0.0 ) this.field[ y_offset + x ] += val * sign;
}
}
}
};
this.addPlaneX = function ( strength, subtract ) {
var x, y, z, xx, val, xdiv, cxy,
// cache attribute lookups
size = this.size,
yd = this.yd,
zd = this.zd,
field = this.field,
dist = size * Math.sqrt( strength / subtract );
if ( dist > size ) dist = size;
for ( x = 0; x < dist; x ++ ) {
xdiv = x / size;
xx = xdiv * xdiv;
val = strength / ( 0.0001 + xx ) - subtract;
if ( val > 0.0 ) {
for ( y = 0; y < size; y ++ ) {
cxy = x + y * yd;
for ( z = 0; z < size; z ++ ) {
field[ zd * z + cxy ] += val;
}
}
}
}
};
this.addPlaneY = function ( strength, subtract ) {
var x, y, z, yy, val, ydiv, cy, cxy,
// cache attribute lookups
size = this.size,
yd = this.yd,
zd = this.zd,
field = this.field,
dist = size * Math.sqrt( strength / subtract );
if ( dist > size ) dist = size;
for ( y = 0; y < dist; y ++ ) {
ydiv = y / size;
yy = ydiv * ydiv;
val = strength / ( 0.0001 + yy ) - subtract;
if ( val > 0.0 ) {
cy = y * yd;
for ( x = 0; x < size; x ++ ) {
cxy = cy + x;
for ( z = 0; z < size; z ++ )
field[ zd * z + cxy ] += val;
}
}
}
};
this.addPlaneZ = function ( strength, subtract ) {
var x, y, z, zz, val, zdiv, cz, cyz,
// cache attribute lookups
size = this.size,
yd = this.yd,
zd = this.zd,
field = this.field,
dist = size * Math.sqrt( strength / subtract );
if ( dist > size ) dist = size;
for ( z = 0; z < dist; z ++ ) {
zdiv = z / size;
zz = zdiv * zdiv;
val = strength / ( 0.0001 + zz ) - subtract;
if ( val > 0.0 ) {
cz = zd * z;
for ( y = 0; y < size; y ++ ) {
cyz = cz + y * yd;
for ( x = 0; x < size; x ++ )
field[ cyz + x ] += val;
}
}
}
};
/////////////////////////////////////
// Updates
/////////////////////////////////////
this.reset = function () {
var i;
// wipe the normal cache
for ( i = 0; i < this.size3; i ++ ) {
this.normal_cache[ i * 3 ] = 0.0;
this.field[ i ] = 0.0;
}
};
this.render = function ( renderCallback ) {
this.begin();
// Triangulate. Yeah, this is slow.
var smin2 = this.size - 2;
for ( var z = 1; z < smin2; z ++ ) {
var z_offset = this.size2 * z;
var fz = ( z - this.halfsize ) / this.halfsize; //+ 1
for ( var y = 1; y < smin2; y ++ ) {
var y_offset = z_offset + this.size * y;
var fy = ( y - this.halfsize ) / this.halfsize; //+ 1
for ( var x = 1; x < smin2; x ++ ) {
var fx = ( x - this.halfsize ) / this.halfsize; //+ 1
var q = y_offset + x;
polygonize( fx, fy, fz, q, this.isolation, renderCallback );
}
}
}
this.end( renderCallback );
};
this.generateGeometry = function () {
console.warn( 'THREE.MarchingCubes: generateGeometry() now returns THREE.BufferGeometry' );
return this.generateBufferGeometry();
};
function concatenate( a, b, length ) {
var result = new Float32Array( a.length + length );
result.set( a, 0 );
result.set( b.slice( 0, length ), a.length );
return result;
}
this.generateBufferGeometry = function () {
var geo = new THREE.BufferGeometry();
var posArray = new Float32Array();
var normArray = new Float32Array();
var colorArray = new Float32Array();
var uvArray = new Float32Array();
var scope = this;
var geo_callback = function ( object ) {
if ( scope.hasPositions ) posArray = concatenate( posArray, object.positionArray, object.count * 3 );
if ( scope.hasNormals ) normArray = concatenate( normArray, object.normalArray, object.count * 3 );
if ( scope.hasColors ) colorArray = concatenate( colorArray, object.colorArray, object.count * 3 );
if ( scope.hasUvs ) uvArray = concatenate( uvArray, object.uvArray, object.count * 2 );
object.count = 0;
};
this.render( geo_callback );
if ( this.hasPositions ) geo.addAttribute( 'position', new THREE.BufferAttribute( posArray, 3 ) );
if ( this.hasNormals ) geo.addAttribute( 'normal', new THREE.BufferAttribute( normArray, 3 ) );
if ( this.hasColors ) geo.addAttribute( 'color', new THREE.BufferAttribute( colorArray, 3 ) );
if ( this.hasUvs ) geo.addAttribute( 'uv', new THREE.BufferAttribute( uvArray, 2 ) );
return geo;
};
this.init( resolution );
};
THREE.MarchingCubes.prototype = Object.create( THREE.ImmediateRenderObject.prototype );
THREE.MarchingCubes.prototype.constructor = THREE.MarchingCubes;
/////////////////////////////////////
// Marching cubes lookup tables
/////////////////////////////////////
// These tables are straight from Paul Bourke's page:
// http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/
// who in turn got them from Cory Gene Bloyd.
THREE.edgeTable = new Int32Array( [
0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
0x230, 0x339, 0x33, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
0x460, 0x569, 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c,
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, 0x3f5, 0x2fc,
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c,
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc,
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
0x2fc, 0x3f5, 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663, 0x569, 0x460,
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0,
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230,
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190,
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ] );
THREE.triTable = new Int32Array( [
- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 8, 3, 9, 8, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 8, 3, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 2, 10, 0, 2, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
2, 8, 3, 2, 10, 8, 10, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 11, 2, 8, 11, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 9, 0, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 11, 2, 1, 9, 11, 9, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 10, 1, 11, 10, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 10, 1, 0, 8, 10, 8, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 9, 0, 3, 11, 9, 11, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 3, 0, 7, 3, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 1, 9, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 1, 9, 4, 7, 1, 7, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 2, 10, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 4, 7, 3, 0, 4, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 2, 10, 9, 0, 2, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1,
8, 4, 7, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
11, 4, 7, 11, 2, 4, 2, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 0, 1, 8, 4, 7, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, - 1, - 1, - 1, - 1,
3, 10, 1, 3, 11, 10, 7, 8, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, - 1, - 1, - 1, - 1,
4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1,
4, 7, 11, 4, 11, 9, 9, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 5, 4, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 5, 4, 1, 5, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
8, 5, 4, 8, 3, 5, 3, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 2, 10, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 0, 8, 1, 2, 10, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
5, 2, 10, 5, 4, 2, 4, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, - 1, - 1, - 1, - 1,
9, 5, 4, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 11, 2, 0, 8, 11, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 5, 4, 0, 1, 5, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, - 1, - 1, - 1, - 1,
10, 3, 11, 10, 1, 3, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, - 1, - 1, - 1, - 1,
5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1,
5, 4, 8, 5, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 7, 8, 5, 7, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 3, 0, 9, 5, 3, 5, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 7, 8, 0, 1, 7, 1, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 7, 8, 9, 5, 7, 10, 1, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, - 1, - 1, - 1, - 1,
8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, - 1, - 1, - 1, - 1,
2, 10, 5, 2, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
7, 9, 5, 7, 8, 9, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1,
2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, - 1, - 1, - 1, - 1,
11, 2, 1, 11, 1, 7, 7, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, - 1, - 1, - 1, - 1,
5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, - 1,
11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, - 1,
11, 10, 5, 7, 11, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 8, 3, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 0, 1, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 8, 3, 1, 9, 8, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 6, 5, 2, 6, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 6, 5, 1, 2, 6, 3, 0, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 6, 5, 9, 0, 6, 0, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, - 1, - 1, - 1, - 1,
2, 3, 11, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
11, 0, 8, 11, 2, 0, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 1, 9, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, - 1, - 1, - 1, - 1,
6, 3, 11, 6, 5, 3, 5, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1,
3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, - 1, - 1, - 1, - 1,
6, 5, 9, 6, 9, 11, 11, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
5, 10, 6, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 3, 0, 4, 7, 3, 6, 5, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 9, 0, 5, 10, 6, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1,
6, 1, 2, 6, 5, 1, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, - 1, - 1, - 1, - 1,
8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, - 1, - 1, - 1, - 1,
7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, - 1,
3, 11, 2, 7, 8, 4, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1,
0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1,
9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, - 1,
8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1,
5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, - 1,
0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, - 1,
6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, - 1, - 1, - 1, - 1,
10, 4, 9, 6, 4, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 10, 6, 4, 9, 10, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
10, 0, 1, 10, 6, 0, 6, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1,
1, 4, 9, 1, 2, 4, 2, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, - 1, - 1, - 1, - 1,
0, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
8, 3, 2, 8, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
10, 4, 9, 10, 6, 4, 11, 2, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, - 1, - 1, - 1, - 1,
3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1,
6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, - 1,
9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, - 1, - 1, - 1, - 1,
8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, - 1,
3, 11, 6, 3, 6, 0, 0, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
6, 4, 8, 11, 6, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
7, 10, 6, 7, 8, 10, 8, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, - 1, - 1, - 1, - 1,
10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, - 1, - 1, - 1, - 1,
10, 6, 7, 10, 7, 1, 1, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1,
2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, - 1,
7, 8, 0, 7, 0, 6, 6, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
7, 3, 2, 6, 7, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1,
2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, - 1,
1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, - 1,
11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, - 1, - 1, - 1, - 1,
8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, - 1,
0, 9, 1, 11, 6, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, - 1, - 1, - 1, - 1,
7, 11, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 0, 8, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 1, 9, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
8, 1, 9, 8, 3, 1, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
10, 1, 2, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 2, 10, 3, 0, 8, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
2, 9, 0, 2, 10, 9, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, - 1, - 1, - 1, - 1,
7, 2, 3, 6, 2, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
7, 0, 8, 7, 6, 0, 6, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
2, 7, 6, 2, 3, 7, 0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, - 1, - 1, - 1, - 1,
10, 7, 6, 10, 1, 7, 1, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, - 1, - 1, - 1, - 1,
0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, - 1, - 1, - 1, - 1,
7, 6, 10, 7, 10, 8, 8, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
6, 8, 4, 11, 8, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 6, 11, 3, 0, 6, 0, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
8, 6, 11, 8, 4, 6, 9, 0, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, - 1, - 1, - 1, - 1,
6, 8, 4, 6, 11, 8, 2, 10, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, - 1, - 1, - 1, - 1,
4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, - 1, - 1, - 1, - 1,
10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, - 1,
8, 2, 3, 8, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, - 1, - 1, - 1, - 1,
1, 9, 4, 1, 4, 2, 2, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, - 1, - 1, - 1, - 1,
10, 1, 0, 10, 0, 6, 6, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, - 1,
10, 9, 4, 6, 10, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 9, 5, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 8, 3, 4, 9, 5, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
5, 0, 1, 5, 4, 0, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, - 1, - 1, - 1, - 1,
9, 5, 4, 10, 1, 2, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, - 1, - 1, - 1, - 1,
7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, - 1, - 1, - 1, - 1,
3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, - 1,
7, 2, 3, 7, 6, 2, 5, 4, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, - 1, - 1, - 1, - 1,
3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, - 1, - 1, - 1, - 1,
6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, - 1,
9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, - 1, - 1, - 1, - 1,
1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, - 1,
4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, - 1,
7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, - 1, - 1, - 1, - 1,
6, 9, 5, 6, 11, 9, 11, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, - 1, - 1, - 1, - 1,
0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, - 1, - 1, - 1, - 1,
6, 11, 3, 6, 3, 5, 5, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, - 1, - 1, - 1, - 1,
0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, - 1,
11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, - 1,
6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, - 1, - 1, - 1, - 1,
5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, - 1, - 1, - 1, - 1,
9, 5, 6, 9, 6, 0, 0, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, - 1,
1, 5, 6, 2, 1, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, - 1,
10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, - 1, - 1, - 1, - 1,
0, 3, 8, 5, 6, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
10, 5, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
11, 5, 10, 7, 5, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
11, 5, 10, 11, 7, 5, 8, 3, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
5, 11, 7, 5, 10, 11, 1, 9, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, - 1, - 1, - 1, - 1,
11, 1, 2, 11, 7, 1, 7, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, - 1, - 1, - 1, - 1,
9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, - 1, - 1, - 1, - 1,
7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, - 1,
2, 5, 10, 2, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, - 1, - 1, - 1, - 1,
9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, - 1, - 1, - 1, - 1,
9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, - 1,
1, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 8, 7, 0, 7, 1, 1, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 0, 3, 9, 3, 5, 5, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 8, 7, 5, 9, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
5, 8, 4, 5, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, - 1, - 1, - 1, - 1,
0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, - 1, - 1, - 1, - 1,
10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, - 1,
2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, - 1, - 1, - 1, - 1,
0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, - 1,
0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, - 1,
9, 4, 5, 2, 11, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, - 1, - 1, - 1, - 1,
5, 10, 2, 5, 2, 4, 4, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, - 1,
5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, - 1, - 1, - 1, - 1,
8, 4, 5, 8, 5, 3, 3, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 4, 5, 1, 0, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, - 1, - 1, - 1, - 1,
9, 4, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 11, 7, 4, 9, 11, 9, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, - 1, - 1, - 1, - 1,
1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, - 1, - 1, - 1, - 1,
3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, - 1,
4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, - 1, - 1, - 1, - 1,
9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, - 1,
11, 7, 4, 11, 4, 2, 2, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, - 1, - 1, - 1, - 1,
2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, - 1, - 1, - 1, - 1,
9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, - 1,
3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, - 1,
1, 10, 2, 8, 7, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 9, 1, 4, 1, 7, 7, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, - 1, - 1, - 1, - 1,
4, 0, 3, 7, 4, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
4, 8, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 0, 9, 3, 9, 11, 11, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 1, 10, 0, 10, 8, 8, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 1, 10, 11, 3, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 2, 11, 1, 11, 9, 9, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, - 1, - 1, - 1, - 1,
0, 2, 11, 8, 0, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
3, 2, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
2, 3, 8, 2, 8, 10, 10, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
9, 10, 2, 0, 9, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, - 1, - 1, - 1, - 1,
1, 10, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
1, 3, 8, 9, 1, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 9, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
0, 3, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 ] );
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.min.js"></script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment