浏览代码

Addressing PR feedback from https://github.com/mrdoob/three.js/pull/18822#pullrequestreview-386940541 and https://github.com/mrdoob/three.js/pull/18822#issuecomment-608196773

- Updated blend mode constant names to 'NormalAnimationBlendMode' and 'AdditiveAnimationBlendMode'
- Removed clone options from AnimationUtils.makeClipAdditive
- Added blendMode as a serialized property to AnimationClip, defaulting to NormalAnimationBlendMode
- Added reference clip input to AnimationUtils.makeClipAdditive and set blendMode on the target clip to AdditiveAnimationBlendMode
- Updated example script to not pass AnimationBlendMode to mixer.clipAction since the property gets set during makeClipAdditive
Christine Morten 5 年之前
父节点
当前提交
ac8823c639

+ 3 - 2
examples/webgl_animation_skinning_additive_blending.html

@@ -117,7 +117,7 @@
 
 						if ( baseActions[ name ] ) {
 
-							const action = mixer.clipAction( clip, undefined, THREE.OverrideBlendMode );
+							const action = mixer.clipAction( clip );
 							activateAction( action );
 							baseActions[ name ].action = action;
 							allActions.push( action );
@@ -127,6 +127,7 @@
 							// Make the clip additive and remove the reference frame
 
 							THREE.AnimationUtils.makeClipAdditive( clip );
+							console.log( clip );
 
 							if ( clip.name.endsWith( '_pose' ) ) {
 
@@ -134,7 +135,7 @@
 
 							}
 
-							const action = mixer.clipAction( clip, undefined, THREE.AdditiveBlendMode );
+							const action = mixer.clipAction( clip );
 							activateAction( action );
 							additiveActions[ name ].action = action;
 							allActions.push( action );

+ 5 - 5
src/animation/AnimationAction.js

@@ -1,4 +1,4 @@
-import { WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, LoopPingPong, LoopOnce, LoopRepeat, OverrideBlendMode, AdditiveBlendMode } from '../constants.js';
+import { WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, LoopPingPong, LoopOnce, LoopRepeat, NormalAnimationBlendMode, AdditiveAnimationBlendMode } from '../constants.js';
 
 /**
  *
@@ -11,12 +11,12 @@ import { WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, LoopPingPong, L
  *
  */
 
-function AnimationAction( mixer, clip, localRoot, blendMode = OverrideBlendMode ) {
+function AnimationAction( mixer, clip, localRoot, blendMode ) {
 
 	this._mixer = mixer;
 	this._clip = clip;
 	this._localRoot = localRoot || null;
-	this.blendMode = blendMode;
+	this.blendMode = blendMode || clip.blendMode;
 
 	var tracks = clip.tracks,
 		nTracks = tracks.length,
@@ -377,7 +377,7 @@ Object.assign( AnimationAction.prototype, {
 
 			switch ( this.blendMode ) {
 
-				case AdditiveBlendMode:
+				case AdditiveAnimationBlendMode:
 
 					for ( var j = 0, m = interpolants.length; j !== m; ++ j ) {
 
@@ -388,7 +388,7 @@ Object.assign( AnimationAction.prototype, {
 
 					break;
 
-				case OverrideBlendMode:
+				case NormalAnimationBlendMode:
 				default:
 
 					for ( var j = 0, m = interpolants.length; j !== m; ++ j ) {

+ 3 - 1
src/animation/AnimationClip.d.ts

@@ -1,13 +1,15 @@
 import { KeyframeTrack } from './KeyframeTrack';
 import { Bone } from './../objects/Bone';
 import { MorphTarget } from '../core/Geometry';
+import { AnimationBlendMode } from '../constants';
 
 export class AnimationClip {
 
-	constructor( name?: string, duration?: number, tracks?: KeyframeTrack[] );
+	constructor( name?: string, duration?: number, tracks?: KeyframeTrack[], blendMode?: AnimationBlendMode );
 
 	name: string;
 	tracks: KeyframeTrack[];
+	blendMode: AnimationBlendMode;
 	duration: number;
 	uuid: string;
 	results: any[];

+ 9 - 5
src/animation/AnimationClip.js

@@ -7,6 +7,7 @@ import { QuaternionKeyframeTrack } from './tracks/QuaternionKeyframeTrack.js';
 import { StringKeyframeTrack } from './tracks/StringKeyframeTrack.js';
 import { VectorKeyframeTrack } from './tracks/VectorKeyframeTrack.js';
 import { MathUtils } from '../math/MathUtils.js';
+import { NormalAnimationBlendMode } from '../constants.js';
 
 /**
  *
@@ -16,11 +17,12 @@ import { MathUtils } from '../math/MathUtils.js';
  * @author David Sarno / http://lighthaus.us/
  */
 
-function AnimationClip( name, duration, tracks ) {
+function AnimationClip( name, duration, tracks, blendMode = NormalAnimationBlendMode ) {
 
 	this.name = name;
 	this.tracks = tracks;
 	this.duration = ( duration !== undefined ) ? duration : - 1;
+	this.blendMode = blendMode;
 
 	this.uuid = MathUtils.generateUUID();
 
@@ -124,7 +126,7 @@ Object.assign( AnimationClip, {
 
 		}
 
-		return new AnimationClip( json.name, json.duration, tracks );
+		return new AnimationClip( json.name, json.duration, tracks, json.blendMode );
 
 	},
 
@@ -138,7 +140,8 @@ Object.assign( AnimationClip, {
 			'name': clip.name,
 			'duration': clip.duration,
 			'tracks': tracks,
-			'uuid': clip.uuid
+			'uuid': clip.uuid,
+			'blendMode': clip.blendMode
 
 		};
 
@@ -300,6 +303,7 @@ Object.assign( AnimationClip, {
 		// automatic length determination in AnimationClip.
 		var duration = animation.length || - 1;
 		var fps = animation.fps || 30;
+		var blendMode = animation.blendMode;
 
 		var hierarchyTracks = animation.hierarchy || [];
 
@@ -381,7 +385,7 @@ Object.assign( AnimationClip, {
 
 		}
 
-		var clip = new AnimationClip( clipName, duration, tracks );
+		var clip = new AnimationClip( clipName, duration, tracks, blendMode );
 
 		return clip;
 
@@ -457,7 +461,7 @@ Object.assign( AnimationClip.prototype, {
 
 		}
 
-		return new AnimationClip( this.name, this.duration, tracks );
+		return new AnimationClip( this.name, this.duration, tracks, this.blendMode );
 
 	}
 

+ 16 - 2
src/animation/AnimationMixer.js

@@ -4,7 +4,7 @@ import { LinearInterpolant } from '../math/interpolants/LinearInterpolant.js';
 import { PropertyBinding } from './PropertyBinding.js';
 import { PropertyMixer } from './PropertyMixer.js';
 import { AnimationClip } from './AnimationClip.js';
-import { OverrideBlendMode } from '../constants.js';
+import { NormalAnimationBlendMode } from '../constants';
 
 /**
  *
@@ -517,7 +517,7 @@ AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototy
 	// return an action for a clip optionally using a custom root target
 	// object (this method allocates a lot of dynamic memory in case a
 	// previously unknown clip/root combination is specified)
-	clipAction: function ( clip, optionalRoot, blendMode = OverrideBlendMode ) {
+	clipAction: function ( clip, optionalRoot, blendMode ) {
 
 		var root = optionalRoot || this._root,
 			rootUuid = root.uuid,
@@ -530,6 +530,20 @@ AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototy
 			actionsForClip = this._actionsByClip[ clipUuid ],
 			prototypeAction = null;
 
+		if ( blendMode === undefined ) {
+
+			if ( clipObject !== null ) {
+
+				blendMode = clipObject.blendMode;
+
+			} else {
+
+				blendMode = NormalAnimationBlendMode;
+
+			}
+
+		}
+
 		if ( actionsForClip !== undefined ) {
 
 			var existingAction =

+ 2 - 3
src/animation/AnimationUtils.d.ts

@@ -24,10 +24,9 @@ export namespace AnimationUtils {
 		fps?: number
 	): AnimationClip;
 	export function makeClipAdditive(
-		sourceClip: AnimationClip,
+		targetClip: AnimationClip,
 		referenceFrame?: number,
-		cloneOriginal?: boolean,
-		clonedName?: string,
+		referenceClip?: AnimationClip,
 		fps?: number
 	): AnimationClip;
 }

+ 35 - 23
src/animation/AnimationUtils.js

@@ -5,6 +5,7 @@
  */
 
 import { Quaternion } from '../math/Quaternion.js';
+import { AdditiveAnimationBlendMode } from '../constants.js';
 
 var AnimationUtils = {
 
@@ -235,16 +236,15 @@ var AnimationUtils = {
 
 	},
 
-	makeClipAdditive: function ( sourceClip, referenceFrame = 0, cloneOriginal = false, clonedName, fps = 30 ) {
+	makeClipAdditive: function ( targetClip, referenceFrame = 0, referenceClip, fps = 30 ) {
 
-		let clip = sourceClip;
-		if ( cloneOriginal ) {
+		if ( referenceClip === undefined ) {
 
-			clip = sourceClip.clone();
-			clip.name = clonedName || clip.name;
+			referenceClip = targetClip;
 
 		}
-		const numTracks = clip.tracks.length;
+
+		const numTracks = targetClip.tracks.length;
 
 		fps = fps > 0 ? fps : 30;
 		const referenceTime = referenceFrame / fps;
@@ -252,40 +252,49 @@ var AnimationUtils = {
 		// Make each track's values relative to the values at the reference frame
 		for ( let i = 0; i < numTracks; ++ i ) {
 
-			const track = clip.tracks[ i ];
-			const trackType = track.ValueTypeName;
+			const referenceTrack = referenceClip.tracks[ i ];
+			const referenceTrackType = referenceTrack.ValueTypeName;
 
 			// Skip this track if it's non-numeric
-			if ( trackType === 'bool' || trackType === 'string' ) continue;
+			if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
+
+			// Find the track in the target clip whose name and type matches the reference track
+			const targetTrack = targetClip.tracks.find( track => {
+
+				return track.name === referenceTrack.name
+				&& track.ValueTypeName === referenceTrackType;
+
+			} );
 
-			const valueSize = track.getValueSize();
-			const lastIndex = track.times.length - 1;
-			const numTimes = track.times.length;
+			if ( targetTrack === undefined ) continue;
+
+			const valueSize = referenceTrack.getValueSize();
+			const lastIndex = referenceTrack.times.length - 1;
 			let referenceValue;
 
 			// Find the value to subtract out of the track
-			if ( referenceTime <= track.times[ 0 ] ) {
+			if ( referenceTime <= referenceTrack.times[ 0 ] ) {
 
 				// Reference frame is earlier than the first keyframe, so just use the first keyframe
-				referenceValue = AnimationUtils.arraySlice( track.values, 0, track.valueSize );
+				referenceValue = AnimationUtils.arraySlice( referenceTrack.values, 0, referenceTrack.valueSize );
 
-			} else if ( referenceTime >= track.times[ lastIndex ] ) {
+			} else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
 
 				// Reference frame is after the last keyframe, so just use the last keyframe
 				const startIndex = lastIndex * valueSize;
-				referenceValue = AnimationUtils.arraySlice( track.values, startIndex );
+				referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex );
 
 			} else {
 
 				// Interpolate to the reference value
-				const interpolant = track.createInterpolant();
+				const interpolant = referenceTrack.createInterpolant();
 				interpolant.evaluate( referenceTime );
 				referenceValue = interpolant.resultBuffer;
 
 			}
 
 			// Conjugate the quaternion
-			if ( trackType === 'quaternion' ) {
+			if ( referenceTrackType === 'quaternion' ) {
 
 				const referenceQuat = new Quaternion(
 					referenceValue[ 0 ],
@@ -299,19 +308,20 @@ var AnimationUtils = {
 
 			// Subtract the reference value from all of the track values
 
+			const numTimes = targetTrack.times.length;
 			for ( let j = 0; j < numTimes; ++ j ) {
 
 				const valueStart = j * valueSize;
 
-				if ( trackType === 'quaternion' ) {
+				if ( referenceTrackType === 'quaternion' ) {
 
 					// Multiply the conjugate for quaternion track types
 					Quaternion.multiplyQuaternionsFlat(
-						track.values,
+						targetTrack.values,
 						valueStart,
 						referenceValue,
 						0,
-						track.values,
+						targetTrack.values,
 						valueStart
 					);
 
@@ -320,7 +330,7 @@ var AnimationUtils = {
 					// Subtract each value for all other numeric track types
 					for ( let k = 0; k < valueSize; ++ k ) {
 
-						track.values[ valueStart + k ] -= referenceValue[ k ];
+						targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
 
 					}
 
@@ -330,7 +340,9 @@ var AnimationUtils = {
 
 		}
 
-		return clip;
+		targetClip.blendMode = AdditiveAnimationBlendMode;
+
+		return targetClip;
 
 	}
 

+ 2 - 2
src/constants.d.ts

@@ -305,8 +305,8 @@ export const WrapAroundEnding: InterpolationEndingModes;
 
 // Animation blending modes
 export enum AnimationBlendMode { }
-export const OverrideBlendMode: AnimationBlendMode;
-export const AdditiveBlendMode: AnimationBlendMode;
+export const NormalAnimationBlendMode: AnimationBlendMode;
+export const AdditiveAnimationBlendMode: AnimationBlendMode;
 
 // Triangle Draw modes
 export enum TrianglesDrawModes {}

+ 2 - 2
src/constants.js

@@ -152,8 +152,8 @@ export var InterpolateSmooth = 2302;
 export var ZeroCurvatureEnding = 2400;
 export var ZeroSlopeEnding = 2401;
 export var WrapAroundEnding = 2402;
-export var OverrideBlendMode = 2500;
-export var AdditiveBlendMode = 2501;
+export var NormalAnimationBlendMode = 2500;
+export var AdditiveAnimationBlendMode = 2501;
 export var TrianglesDrawMode = 0;
 export var TriangleStripDrawMode = 1;
 export var TriangleFanDrawMode = 2;