Last active
August 29, 2015 14:14
-
-
Save gregtatum/58c5bbad7b2a4a4660f2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ringFunction = function( geometry, radius, segments ) { | |
var rStep = 2 * Math.PI / segments; | |
return { | |
create : function( height, skinIndex, skinWeight ) { | |
for( var i=0; i < segments; i++ ) { | |
geometry.vertices.push( new THREE.Vector3( | |
Math.sin( i * rStep ) * radius, | |
height, | |
Math.cos( i * rStep ) * radius | |
) ); | |
geometry.skinIndices.push( new THREE.Vector4( skinIndex, skinIndex+1, 0, 0 ) ); | |
geometry.skinWeights.push( new THREE.Vector4( 1-skinWeight, skinWeight, 0, 0 ) ); | |
// geometry.skinWeights.push( new THREE.Vector4( 1, 0, 0, 0 ) ); | |
} | |
}, | |
radius : radius, | |
segments : segments | |
}; | |
}; | |
var tubeFunction = function( geometry, segments, ring ) { | |
return function tube( height, skinIndex, prevRingVerts, baseHeight ) { | |
var offset, a, b, c, d, r2; | |
var hStep = height / segments; | |
var skinWeight1, skinWeight2; | |
var baseOffset = geometry.vertices.length; | |
//Create the first segment | |
ring.create( | |
baseHeight + hStep * 1, //height | |
skinIndex, //skinIndex | |
(1) / (segments) //skinWeight | |
); | |
//Connect the previous ring to the this first segment | |
for( var r=0; r < ring.segments; r++ ) { | |
offset = baseOffset; | |
r2 = (r + 1) % ring.segments; // wrap around the last face | |
a = geometry.vertices.indexOf( prevRingVerts[r] ); | |
b = geometry.vertices.indexOf( prevRingVerts[r2] ); | |
c = baseOffset + r; | |
d = baseOffset + r2; | |
geometry.faces.push( new THREE.Face3( a, b, c ) ); | |
geometry.faces.push( new THREE.Face3( d, c, b ) ); | |
} | |
//Create the rest of the segments | |
for( var h=2; h <= segments; h++ ) { | |
ring.create( | |
baseHeight + h * hStep, //height | |
skinIndex, //skinIndex | |
(h) / (segments) //skinWeight | |
); | |
for( r=0; r < ring.segments; r++ ) { | |
// c___d | |
// / / | |
// / / ^ | |
// a___b / direction | |
offset = baseOffset + (h-2) * ring.segments; | |
r2 = (r + 1) % ring.segments; // wrap around the last face | |
a = offset + r; | |
b = offset + r2; | |
c = offset + r + ring.segments; | |
d = offset + r2 + ring.segments; | |
geometry.faces.push( new THREE.Face3( a, b, c ) ); | |
geometry.faces.push( new THREE.Face3( d, c, a ) ); | |
} | |
} | |
}; | |
}; | |
var recursiveTubes = function( tube, ring, height, geometry, depth, targetDepth, ringSlice ) { | |
if( depth === targetDepth ) return; | |
tube( | |
height, //tube length | |
depth, //skinIndex | |
ringSlice, //base slice vertices | |
height * depth //base height | |
); | |
geometry.bones.push({ | |
"parent":depth, | |
"name":"segment", | |
"pos":[0,height,0], | |
"rotq":[0,0,0,1] | |
}) | |
var nextRingSlice = geometry.vertices.slice(geometry.vertices.length - ring.segments, geometry.vertices.length); | |
for( var i=0; i < 3; i++ ) { | |
console.log(depth, i); | |
recursiveTubes( tube, ring, height, geometry, depth + 1, targetDepth, nextRingSlice ); | |
} | |
} | |
var createInitialSegment = function( geometry ) { | |
var height = 50; | |
var radius = 10; | |
var rSegments = 12; | |
var hSegments = 3; | |
var depth = 3; | |
var ring = ringFunction( geometry, radius, rSegments ); | |
//Create a base ring | |
ring.create( | |
0, //height | |
0, //skinIndex | |
0 //skinWeight | |
); | |
var ringSlice = geometry.vertices.slice(0, ring.segments); | |
var tube = tubeFunction( geometry, hSegments, ring ); | |
geometry.bones = [ | |
{ | |
"parent":-1, | |
"name":"root", | |
"pos":[0,0,0], | |
"rotq":[0,0,0,1] | |
} | |
]; | |
recursiveTubes( tube, ring, height, geometry, 0, depth, ringSlice ); | |
geometry.computeFaceNormals(); | |
}; | |
var createMesh = function( config, geometry ) { | |
var mat = new THREE.MeshLambertMaterial({ | |
skinning : true, | |
emissive : 0xff0000, | |
wireframe : true | |
}); | |
mat.side = THREE.DoubleSide; | |
var mesh = new THREE.SkinnedMesh( | |
geometry, | |
mat, | |
true | |
); | |
mesh.skeletonHelper = new THREE.SkeletonHelper( mesh ); | |
mesh.skeletonHelper.material.linewidth = 3; | |
mesh.add( mesh.skeletonHelper ); | |
return mesh; | |
}; | |
function recursiveRandom( bone, array, depth ) { | |
array[depth] = [ | |
Math.random(), | |
Math.random(), | |
Math.random() | |
]; | |
bone.scale.multiplyScalar( 0.8 ); | |
if(bone.children[0]) { | |
return recursiveRandom( bone.children[0], array, depth + 1 ); | |
} else { | |
return array; | |
} | |
} | |
function recursiveWriggle( bone, now, depth, ortho, randoms ) { | |
var r1 = 753.1294 * depth; | |
var r2 = 255.5854 * ortho; | |
// bone.rotation.x = Math.sin( (now + r1 + r2 ) ) * 0.5; | |
// bone.rotation.z = Math.sin( (now + r1 + r2 ) * 0.3 ) * 0.3; | |
bone.rotation.z = Math.sin( ortho + randoms[depth][0] * now * 0.05 ); | |
bone.rotation.y = Math.sin( ortho + randoms[depth][1] * now * 0.0066 ); | |
bone.rotation.x = Math.sin( ortho + randoms[depth][2] * now * 0.02 ); | |
for( var i=0; i < bone.children.length; i++ ) { | |
recursiveWriggle( bone.children[i], now, depth + 1, ortho + i, randoms ); | |
} | |
} | |
var update = function( mesh ) { | |
var randoms = recursiveRandom( mesh, [], 0 ); | |
return function( e ) { | |
var bone = mesh; | |
mesh.skeletonHelper.update(); | |
var now = e.now * 0.005; | |
recursiveWriggle( mesh.children[0], now, 0, 0, randoms ); | |
}; | |
}; | |
module.exports = function treeGrowth( poem, properties ) { | |
var config = _.extend({ | |
speed : 0.5, | |
subdivideRate : 1 / ( 60 * 3 ), | |
pinch : 1, | |
stretch : 10 | |
}, properties ); | |
var geometry = new THREE.Geometry(); | |
var segments = createInitialSegment( geometry ); | |
var mesh = createMesh( config, geometry ); | |
// mesh.scale.multiplyScalar( 1 ); | |
poem.scene.add( mesh ); | |
poem.emitter.on( 'update', update( mesh ) ); | |
return { | |
mesh : mesh | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment