Skip to content

Instantly share code, notes, and snippets.

@shshaw
Last active December 3, 2016 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shshaw/f39b56638d23f16f6cbaff32e2d844dd to your computer and use it in GitHub Desktop.
Save shshaw/f39b56638d23f16f6cbaff32e2d844dd to your computer and use it in GitHub Desktop.
Waving Hairs (#3December - Day 3)
console.clear();
var gui, scene, camera, renderer, orbit, lights;
function initScene () {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 400 );
camera.position.x = -20;
camera.position.z = 30;
camera.position.y = 19;
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x000000, 1 );
document.body.appendChild( renderer.domElement );
orbit = new THREE.OrbitControls( camera, renderer.domElement );
orbit.enableZoom = true;
orbit.enablePan = true;
lights = [];
lights[ 0 ] = new THREE.PointLight( 0xffffff, 0.4, 0 );
lights[ 1 ] = new THREE.PointLight( 0xffffff, 0.4, 0 );
lights[ 2 ] = new THREE.PointLight( 0xffffff, 0.4, 0 );
lights[ 0 ].position.set( 0, 200, 0 );
lights[ 1 ].position.set( 100, 200, 100 );
lights[ 2 ].position.set( - 100, - 200, - 100 );
scene.add( lights[ 0 ] );
scene.add( lights[ 1 ] );
scene.add( lights[ 2 ] );
window.addEventListener( 'resize', function () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}, false );
initHairs();
}
function createGeometry ( sizing ) {
var geometry = new THREE.CylinderGeometry(
0, // radiusTop
3, // radiusBottom
sizing.height, // height
8, // radiusSegments
sizing.segmentCount * 3, // heightSegments
true // openEnded
);
for ( var i = 0; i < geometry.vertices.length; i ++ ) {
var vertex = geometry.vertices[ i ];
var y = ( vertex.y + sizing.halfHeight );
var skinIndex = Math.floor( y / sizing.segmentHeight );
var skinWeight = ( y % sizing.segmentHeight ) / sizing.segmentHeight;
geometry.skinIndices.push( new THREE.Vector4( skinIndex, skinIndex + 1, 0, 0 ) );
geometry.skinWeights.push( new THREE.Vector4( 1 - skinWeight, skinWeight, 0, 0 ) );
}
return geometry;
};
function createBones ( sizing ) {
bones = [];
var prevBone = new THREE.Bone();
bones.push( prevBone );
prevBone.position.y = - sizing.halfHeight;
for ( var i = 0; i < sizing.segmentCount; i ++ ) {
var bone = new THREE.Bone();
bone.position.y = sizing.segmentHeight;
bones.push( bone );
prevBone.add( bone );
prevBone = bone;
}
return bones;
};
function createMesh ( geometry, bones ) {
var material = new THREE.MeshPhongMaterial( {
skinning : true,
color: 0xBC3D2D,
emissive: 0x8F341A,
side: THREE.DoubleSide,
shading: THREE.FlatShading
} );
var mesh = new THREE.SkinnedMesh( geometry, material );
var skeleton = new THREE.Skeleton( bones );
mesh.add( bones[ 0 ] );
mesh.bind( skeleton );
//skeletonHelper = new THREE.SkeletonHelper( mesh );
//skeletonHelper.material.linewidth = 2;
//mesh.add( skeletonHelper );
return mesh;
};
function Hair() {
THREE.Object3D.apply(this);
this.height = this.segmentHeight * this.segmentCount;
this.halfHeight = this.height * 0.5;
this.offset = Math.random();
var sizing = {
segmentHeight : this.segmentHeight,
segmentCount : this.segmentCount,
height : this.height,
halfHeight : this.halfHeight
};
this.geometry = createGeometry( sizing );
this.bones = createBones( sizing );
this.mesh = createMesh( this.geometry, this.bones );
this.mesh.scale.multiplyScalar( 1 );
this.add( this.mesh );
};
Hair.prototype = Object.assign(THREE.Object3D.prototype,
{
constructor: Hair,
segmentHeight: 5,
segmentCount: 6,
animating: true,
animate(count){
if ( this.animating) {
let len = this.mesh.skeleton.bones.length
for ( var i = 0; i < len; i++){//; i ++ ) {
this.mesh.skeleton.bones[ i ].rotation.z =
Math[ i < len/2 ? 'cos' : 'sin' ]( count + this.offset ) * 2 / this.mesh.skeleton.bones.length;
}
}
//skeletonHelper.update();
}
});
let hairs = [];
function initHairs(){
var hairCount = 10;
for ( let i = 0; i < hairCount; i++){
let hair = new Hair;
hair.position.x += (hairCount/2 - i) * 10;
hair.position.z += 10 * Math.random();
hair.offset = hairCount - i * 0.15 * Math.random();
hairs.push(hair);
scene.add(hair);
}
}
let count = 0;
function render () {
requestAnimationFrame( render );
count += 0.02;
for ( var i = 0; i < hairs.length; i++){
hairs[i].animate(count);
}
renderer.render( scene, camera );
};
initScene();
render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment