Browse Source

messing around with 'animations' compatibility with ThreeJS JSON export from Blender.

Ben Houston 10 years ago
parent
commit
0e66ebc5c4

+ 215 - 0
examples/webgl_animation_blendshapes.html

@@ -0,0 +1,215 @@
+<!doctype html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - blendshapes</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				color: #000;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+
+				background-color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px; width: 100%;
+				padding: 5px;
+			}
+
+			a {
+				color: #0af;
+			}
+
+			#stats { position: absolute; top:0; left: 0 }
+			#stats #fps { background: transparent !important }
+			#stats #fps #fpsText { color: #777 !important }
+			#stats #fps #fpsGraph { display: none }
+		</style>
+	</head>
+
+	<body>
+
+		<div id="container"></div>
+
+		<div id="info">
+		<a href="http://threejs.org" target="_blank">three.js</a> webgl - clip system
+		- blend shapes
+		</div>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+		<script src="js/libs/dat.gui.min.js"></script>
+
+		<script>
+
+			var SCREEN_WIDTH = window.innerWidth;
+			var SCREEN_HEIGHT = window.innerHeight;
+			var FLOOR = -250;
+
+			var container,stats;
+
+			var camera, scene, sceneAnimationClip;
+			var renderer;
+
+			var mesh, helper;
+
+			var mixer;
+		
+			var mouseX = 0, mouseY = 0;
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+
+			var clock = new THREE.Clock();
+
+			document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+
+			init();
+			animate();
+
+			function init() {
+
+				container = document.getElementById( 'container' );
+
+				camera = new THREE.PerspectiveCamera( 30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
+				camera.position.z = 150;
+
+				scene = new THREE.Scene();
+
+				scene.fog = new THREE.Fog( 0x000000, 2000, 10000 );
+
+				//scene.add( camera );
+
+				// GROUND
+
+				var geometry = new THREE.PlaneBufferGeometry( 16000, 16000 );
+				var material = new THREE.MeshPhongMaterial( { emissive: 0x000000 } );
+
+				var ground = new THREE.Mesh( geometry, material );
+				ground.position.set( 0, FLOOR, 0 );
+				ground.rotation.x = -Math.PI/2;
+				/*scene.add( ground );*/
+
+				ground.receiveShadow = true;
+
+
+				// RENDERER
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setClearColor( scene.fog.color );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+				renderer.domElement.style.position = "relative";
+
+				container.appendChild( renderer.domElement );
+
+				renderer.gammaInput = true;
+				renderer.gammaOutput = true;
+
+				renderer.shadowMap.enabled = true;
+
+
+				// STATS
+
+				stats = new Stats();
+				container.appendChild( stats.domElement );
+
+				//
+
+				var loader = new THREE.ObjectLoader();
+				loader.load( "models/json/blendshape-animation.json", function ( loadedScene ) {
+
+					scene = loadedScene;
+					scene.add( camera );
+				
+					mixer = new THREE.AnimationMixer( scene );
+			
+					mixer.addAction( new THREE.AnimationAction( sceneAnimationClip, 0, 1, 1, true ) );
+
+				} );
+
+				// GUI
+
+				initGUI();
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				windowHalfX = window.innerWidth / 2;
+				windowHalfY = window.innerHeight / 2;
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function initGUI() {
+
+				var API = {
+					'show model'    : true,
+					'show skeleton' : false
+				};
+
+				var gui = new dat.GUI();
+
+				gui.add( API, 'show model' ).onChange( function() { mesh.visible = API[ 'show model' ]; } );
+
+				gui.add( API, 'show skeleton' ).onChange( function() { helper.visible = API[ 'show skeleton' ]; } );
+
+			}
+
+			function onDocumentMouseMove( event ) {
+
+				mouseX = ( event.clientX - windowHalfX );
+				mouseY = ( event.clientY - windowHalfY );
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+
+				var delta = 0.75 * clock.getDelta();
+
+				camera.position.x += ( mouseX - camera.position.x ) * .05;
+				camera.position.y = THREE.Math.clamp( camera.position.y + ( - mouseY - camera.position.y ) * .05, 0, 1000 );
+
+				camera.lookAt( scene.position );
+
+				if( mixer ) {
+					//console.log( "updating mixer by " + delta );
+					mixer.update( delta );
+				}
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+
+	</body>
+</html>

+ 1 - 2
examples/webgl_animation_nodes.html

@@ -39,7 +39,7 @@
 
 		<div id="info">
 		<a href="http://threejs.org" target="_blank">three.js</a> webgl - clip system
-		- knight by <a href="http://vimeo.com/36113323">apendua</a>
+		- three gears
 		</div>
 
 		<script src="../build/three.min.js"></script>
@@ -127,7 +127,6 @@
 				var loader = new THREE.ObjectLoader();
 				loader.load( "models/json/three-gears-node-animation5.json", function ( loadedScene ) {
 
-					console.log( loadedScene );
 					sceneAnimationClip = loadedScene.animationClips[0];
 					scene = loadedScene;
 					scene.add( camera );

+ 32 - 6
src/animation/AnimationClip.js

@@ -175,7 +175,7 @@ THREE.AnimationClip.FromImplicitMorphTargetAnimations = function( morphTargets,
 
 };
 
-THREE.AnimationClip.FromJSONLoaderAnimation = function( animation, bones, nodeName ) {
+THREE.AnimationClip.FromGeometryAnimation = function( animation, bones, nodeName ) {
 
 	if( ! animation ) {
 		console.error( "  no animation in JSONLoader data" );
@@ -208,13 +208,30 @@ THREE.AnimationClip.FromJSONLoaderAnimation = function( animation, bones, nodeNa
 
 	};
 
-	var clipName = animation.name;
-	var duration = animation.length;
-	var fps = animation.fps;
-
 	var tracks = [];
 
-	var animationTracks = animation.hierarchy;
+	// new style morph animations
+	var re = /^morphTargets\[([\w\d\[\]\_. ]+)\]$/;
+	for( var name in animation ) {
+		// get any variables named morphTarget
+		var matches = re.exec(name);
+
+		if( ! matches ) continue;
+
+	    if (matches.index === re.lastIndex) {
+	        re.lastIndex++;
+	    }
+
+		var morphTargetName = matches[1];
+
+		tracks.push( new THREE.NumberKeyframeTrack( nodeName + '.morphTargetInfluence[' + morphTargetName + ']', animation[name] ) );
+
+	}
+
+	var clipName = animation.name || 'default';
+	var duration = animation.length || -1; // automatic length determination in AnimationClip.
+	var fps = animation.fps || 30;
+	var animationTracks = animation.hierarchy || [];
 
 	for ( var h = 0; h < animationTracks.length; h ++ ) {
 
@@ -297,6 +314,15 @@ THREE.AnimationClip.FromJSONLoaderAnimation = function( animation, bones, nodeNa
 		}
 	}
 
+
+	console.log( 'input animation', animation, 'resulting tracks', tracks );
+
+	if( tracks.length === 0 ) {
+
+		return null;
+
+	}
+
 	var clip = new THREE.AnimationClip( clipName, duration, tracks );
 
 	return clip;

+ 1 - 1
src/animation/KeyframeTrack.js

@@ -238,7 +238,7 @@ THREE.KeyframeTrack.prototype = {
 
 };
 
-THREE.KeyframeTrack.parse( json ) {
+THREE.KeyframeTrack.parse = function( json ) {
 
 	if( json.type === undefined ) throw new Error( "track type undefined, can not parse" );
 

+ 18 - 3
src/loaders/JSONLoader.js

@@ -422,11 +422,26 @@ THREE.JSONLoader.prototype = {
 
 			}
 
+			console.log( json );
 
-			// could change this to json.animations[0] or remove completely
+			var animations = [];
+			if( json.animations ) {
+				for( animationName in animations ) {
+					animations.push( animations[animationName] );
+				}
+			}
+			if( json.animation ) {
+				animations.push( json.animation );
+			}
+
+			for( var animation in animations ) {
 
-			geometry.animation = json.animation;
-			geometry.animations = json.animations;
+				var clip = THREE.AnimationClip.FromGeometryAnimation( animation );
+
+				if( clip ) {
+					geometry.animationClips.push( clip );		
+				}
+			}
 
 		};