2
0
Эх сурвалжийг харах

remove MorphAnimMesh from MD2Character and MD2Loader while retaining all functionality.

Ben Houston 10 жил өмнө
parent
commit
f89af19112

+ 52 - 33
examples/js/MD2Character.js

@@ -21,6 +21,8 @@ THREE.MD2Character = function () {
 
 	this.activeAnimation = null;
 
+	this.mixer = null;
+
 	this.onLoadComplete = function () {};
 
 	this.loadCounter = 0;
@@ -52,7 +54,11 @@ THREE.MD2Character = function () {
 			scope.root.add( mesh );
 
 			scope.meshBody = mesh;
-			scope.activeAnimationClipName = mesh.firstAnimationClip.name;
+
+			scope.meshBody.clipOffset = 0;
+			scope.activeAnimationClipName = mesh.geometry.clips[0].name;
+
+			scope.mixer = new THREE.AnimationMixer( mesh );
 
 			checkLoadingComplete();
 
@@ -91,8 +97,12 @@ THREE.MD2Character = function () {
 
 	this.setPlaybackRate = function ( rate ) {
 
-		if ( this.meshBody ) this.meshBody.duration = this.meshBody.baseDuration / rate;
-		if ( this.meshWeapon ) this.meshWeapon.duration = this.meshWeapon.baseDuration / rate;
+		if( rate !== 0 ) {
+			this.mixer.timeScale = 1 / rate;
+		}
+		else {
+			this.mixer.timeScale = 0;
+		}
 
 	};
 
@@ -133,51 +143,67 @@ THREE.MD2Character = function () {
 			activeWeapon.visible = true;
 			this.meshWeapon = activeWeapon;
 
-			activeWeapon.playAnimation( this.activeAnimationClipName, this.animationFPS );
-
-			this.meshWeapon.baseDuration = this.meshWeapon.duration;
-
-			this.meshWeapon.time = this.meshBody.time;
-			this.meshWeapon.duration = this.meshBody.duration;
+			scope.syncWeaponAnimation();
 
 		}
 
 	};
 
-	this.setAnimation = function ( animationName ) {
+	this.setAnimation = function ( clipName ) {
 
 		if ( this.meshBody ) {
 
-			this.meshBody.playAnimation( animationName, this.animationFPS );
-			this.meshBody.baseDuration = this.meshBody.duration;
+			if( this.meshBody.activeAction ) {
+				scope.mixer.removeAction( this.meshBody.activeAction );
+				this.meshBody.activeAction = null;
+			}
 
-		}
+			var clip = THREE.AnimationClip.findByName( this.meshBody.geometry.clips, clipName );
+			if( clip ) {
 
-		if ( this.meshWeapon ) {
+				var action = new THREE.AnimationAction( clip, this.mixer.time ).setLocalRoot( this.meshBody );
+				scope.mixer.addAction( action );
 
-			this.meshWeapon.playAnimation( animationName, this.animationFPS );
-			this.meshWeapon.baseDuration = this.meshWeapon.duration;
-			this.meshWeapon.time = this.meshBody.time;
+				this.meshBody.activeAction = action;
+
+			}
 
 		}
 
-		this.activeAnimation = animationName;
+		scope.activeClipName = clipName;
+
+		scope.syncWeaponAnimation();
 
 	};
 
-	this.update = function ( delta ) {
+	this.syncWeaponAnimation = function() {
 
-		if ( this.meshBody ) {
+		var clipName = scope.activeClipName;
 
-			this.meshBody.updateAnimation( 1000 * delta );
+		if ( scope.meshWeapon ) {
 
-		}
+			if( this.meshWeapon.activeAction ) {
+				scope.mixer.removeAction( this.meshWeapon.activeAction );
+				this.meshWeapon.activeAction = null;
+			}
 
-		if ( this.meshWeapon ) {
+			var clip = THREE.AnimationClip.findByName( this.meshWeapon.geometry.clips, clipName );
+			if( clip ) {
 
-			this.meshWeapon.updateAnimation( 1000 * delta );
+				var action = new THREE.AnimationAction( clip, this.meshBody.activeAction.startTime ).setLocalRoot( this.meshWeapon );
+				scope.mixer.addAction( action );
+
+				this.meshWeapon.activeAction = action;
+
+			}
 
 		}
+			
+	}
+
+	this.update = function ( delta ) {
+
+		if( this.mixer ) this.mixer.update( delta );
 
 	};
 
@@ -204,7 +230,7 @@ THREE.MD2Character = function () {
 
 		//
 
-		var mesh = new THREE.MorphAnimMesh( geometry, materialTexture );
+		var mesh = new THREE.Mesh( geometry, materialTexture );
 		mesh.rotation.y = - Math.PI / 2;
 
 		mesh.castShadow = true;
@@ -214,14 +240,7 @@ THREE.MD2Character = function () {
 
 		mesh.materialTexture = materialTexture;
 		mesh.materialWireframe = materialWireframe;
-
-		//
-
-		mesh.parseAnimations();
-
-		mesh.playAnimation( mesh.firstAnimationClip.name, scope.animationFPS );
-		mesh.baseDuration = mesh.duration;
-
+	
 		return mesh;
 
 	}

+ 6 - 1
examples/js/loaders/MD2Loader.js

@@ -224,7 +224,10 @@ THREE.MD2Loader.prototype = {
 
 				for ( var j = 0; j < 16; j ++ ) {
 
-					string[ j ] = data.getUint8( offset + j, true );
+					var character = data.getUint8( offset + j, true );
+					if( character === 0 ) break;
+					
+					string[ j ] = character;
 
 				}
 
@@ -302,6 +305,8 @@ THREE.MD2Loader.prototype = {
 
 			}
 
+			geometry.clips = THREE.AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 )
+
 			console.timeEnd( 'MD2Loader' );
 
 			return geometry;

+ 5 - 5
examples/webgl_loader_md2.html

@@ -309,14 +309,14 @@
 				};
 
 				var i = 0, guiItems = [];
-				var animationClips = character.meshBody.animationClips;
+				var clips = character.meshBody.geometry.clips;
 
-				for ( var i = 0; i < animationClips.length; i ++ ) {
+				for ( var i = 0; i < clips.length; i ++ ) {
 
-					var animationClip = animationClips[i];
+					var clip = clips[i];
 
-					playbackConfig[ animationClip.name ] = generateCallback( animationClip );
-					guiItems[ i ] = folder.add( playbackConfig, animationClip.name, animationClip.name );
+					playbackConfig[ clip.name ] = generateCallback( clip );
+					guiItems[ i ] = folder.add( playbackConfig, clip.name, clip.name );
 
 					i ++;
 

+ 18 - 3
src/animation/AnimationClip.js

@@ -106,19 +106,34 @@ THREE.AnimationClip.CreateFromMorphTargetSequence = function( name, morphTargetS
 
 };
 
+THREE.AnimationClip.findByName = function( clipArray, name ) {
+
+	for( var i = 0; i < clipArray.length; i ++ ) {
+
+		if( clipArray[i].name === name ) {
+
+			return clipArray[i];
+
+		}
+	}
+
+	return null;
+
+};
+
 THREE.AnimationClip.CreateClipsFromMorphTargetSequences = function( morphTargets, fps ) {
 	
 	var animationToMorphTargets = {};
 
-	// tested with https://regex101.com/ on trick sequences such flamingo_flyA_003 and flamingo_run1_003
-	var pattern = /^([\w-]*[a-zA-Z-_]+)([\d]+)$/;
+	// tested with https://regex101.com/ on trick sequences such flamingo_flyA_003, flamingo_run1_003, crdeath0059
+	var pattern = /^([\w-]*?)([\d]+)$/;
 
 	// sort morph target names into animation groups based patterns like Walk_001, Walk_002, Run_001, Run_002
 	for ( var i = 0, il = morphTargets.length; i < il; i ++ ) {
 
 		var morphTarget = morphTargets[ i ];
 		var parts = morphTarget.name.match( pattern );
-
+	
 		if ( parts && parts.length > 1 ) {
 
 			var name = parts[ 1 ];

+ 4 - 2
src/animation/AnimationMixer.js

@@ -36,7 +36,7 @@ THREE.AnimationMixer.prototype = {
 
 			var track = tracks[ i ];
 
-			var j = this.getPropertyBindingIndex( track.name )
+			var j = this.getPropertyBindingIndex( root, track.name )
 
 			var propertyBinding;
 
@@ -127,13 +127,15 @@ THREE.AnimationMixer.prototype = {
 
 		}
 
+
 		// remove unused property bindings because if we leave them around the mixer can get slow
+		var root = action.localRoot || this.root;
 		var tracks = action.clip.tracks;
 
 		for( var i = 0; i < tracks.length; i ++ ) {
 		
 			var track = tracks[ i ];
-			var propertyBindingIndex = this.getPropertyBindingIndex( track.name );
+			var propertyBindingIndex = this.getPropertyBindingIndex( root, track.name );
 			var propertyBinding = this.propertyBindings[ propertyBindingIndex ];
 
 			propertyBinding.referenceCount -= 1;

+ 9 - 24
src/objects/MorphAnimMesh.js

@@ -9,7 +9,7 @@ THREE.MorphAnimMesh = function ( geometry, material ) {
 	this.type = 'MorphAnimMesh';
 
 	this.mixer = new THREE.AnimationMixer( this );
-
+	this.activeAction = null;
 };
 
 THREE.MorphAnimMesh.prototype = Object.create( THREE.Mesh.prototype );
@@ -29,21 +29,21 @@ THREE.MorphAnimMesh.prototype.setDirectionBackward = function () {
 
 THREE.MorphAnimMesh.prototype.playAnimation = function ( label, fps ) {
 
-	this.mixer.removeAllActions();
+	if( this.activeAction ) {
 
-	var clip = null;
-	for( var i = 0; i < this.geometry.clips.length; i ++ ) {
-		if( this.geometry.clips[ i ].name === label ) {
-			clip = this.geometry.clips[ i ];
-			break;
-		}
+		this.mixer.removeAction( this.activeAction );
+		this.activeAction = null;
+		
 	}
-	
+
+	var clip = THREE.AnimationClip.findByName( this.geometry.clips, label );
+
 	if ( clip ) {
 
 		var action = new THREE.AnimationAction( clip, 0, 1, 1, true );
 		action.timeScale = ( clip.tracks.length * fps ) / clip.duration;
 		this.mixer.addAction( action );
+		this.activeAction = action;
 
 	} else {
 
@@ -59,21 +59,6 @@ THREE.MorphAnimMesh.prototype.updateAnimation = function ( delta ) {
 
 };
 
-THREE.MorphAnimMesh.prototype.interpolateTargets = function ( a, b, t ) {
-
-	var influences = this.morphTargetInfluences;
-
-	for ( var i = 0, l = influences.length; i < l; i ++ ) {
-
-		influences[ i ] = 0;
-
-	}
-
-	if ( a > - 1 ) influences[ a ] = 1 - t;
-	if ( b > - 1 ) influences[ b ] = t;
-
-};
-
 THREE.MorphAnimMesh.prototype.copy = function ( source ) {
 
 	THREE.Mesh.prototype.copy.call( this, source );