|
@@ -1,12 +1,10 @@
|
|
|
import {
|
|
|
AnimationClip,
|
|
|
AnimationMixer,
|
|
|
- Euler,
|
|
|
Matrix4,
|
|
|
Quaternion,
|
|
|
QuaternionKeyframeTrack,
|
|
|
SkeletonHelper,
|
|
|
- Vector2,
|
|
|
Vector3,
|
|
|
VectorKeyframeTrack
|
|
|
} from 'three';
|
|
@@ -367,206 +365,6 @@ function retargetClip( target, source, clip, options = {} ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
-function getHelperFromSkeleton( skeleton ) {
|
|
|
-
|
|
|
- const source = new SkeletonHelper( skeleton.bones[ 0 ] );
|
|
|
- source.skeleton = skeleton;
|
|
|
-
|
|
|
- return source;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-function getSkeletonOffsets( target, source, options = {} ) {
|
|
|
-
|
|
|
- const targetParentPos = new Vector3(),
|
|
|
- targetPos = new Vector3(),
|
|
|
- sourceParentPos = new Vector3(),
|
|
|
- sourcePos = new Vector3(),
|
|
|
- targetDir = new Vector2(),
|
|
|
- sourceDir = new Vector2();
|
|
|
-
|
|
|
- options.hip = options.hip !== undefined ? options.hip : 'hip';
|
|
|
- options.names = options.names || {};
|
|
|
-
|
|
|
- if ( ! source.isObject3D ) {
|
|
|
-
|
|
|
- source = getHelperFromSkeleton( source );
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- const nameKeys = Object.keys( options.names ),
|
|
|
- nameValues = Object.values( options.names ),
|
|
|
- sourceBones = source.isObject3D ? source.skeleton.bones : getBones( source ),
|
|
|
- bones = target.isObject3D ? target.skeleton.bones : getBones( target ),
|
|
|
- offsets = [];
|
|
|
-
|
|
|
- let bone, boneTo,
|
|
|
- name, i;
|
|
|
-
|
|
|
- target.skeleton.pose();
|
|
|
-
|
|
|
- for ( i = 0; i < bones.length; ++ i ) {
|
|
|
-
|
|
|
- bone = bones[ i ];
|
|
|
- name = options.names[ bone.name ] || bone.name;
|
|
|
-
|
|
|
- boneTo = getBoneByName( name, sourceBones );
|
|
|
-
|
|
|
- if ( boneTo && name !== options.hip ) {
|
|
|
-
|
|
|
- const boneParent = getNearestBone( bone.parent, nameKeys ),
|
|
|
- boneToParent = getNearestBone( boneTo.parent, nameValues );
|
|
|
-
|
|
|
- boneParent.updateMatrixWorld();
|
|
|
- boneToParent.updateMatrixWorld();
|
|
|
-
|
|
|
- targetParentPos.setFromMatrixPosition( boneParent.matrixWorld );
|
|
|
- targetPos.setFromMatrixPosition( bone.matrixWorld );
|
|
|
-
|
|
|
- sourceParentPos.setFromMatrixPosition( boneToParent.matrixWorld );
|
|
|
- sourcePos.setFromMatrixPosition( boneTo.matrixWorld );
|
|
|
-
|
|
|
- targetDir.subVectors(
|
|
|
- new Vector2( targetPos.x, targetPos.y ),
|
|
|
- new Vector2( targetParentPos.x, targetParentPos.y )
|
|
|
- ).normalize();
|
|
|
-
|
|
|
- sourceDir.subVectors(
|
|
|
- new Vector2( sourcePos.x, sourcePos.y ),
|
|
|
- new Vector2( sourceParentPos.x, sourceParentPos.y )
|
|
|
- ).normalize();
|
|
|
-
|
|
|
- const laterialAngle = targetDir.angle() - sourceDir.angle();
|
|
|
-
|
|
|
- const offset = new Matrix4().makeRotationFromEuler(
|
|
|
- new Euler(
|
|
|
- 0,
|
|
|
- 0,
|
|
|
- laterialAngle
|
|
|
- )
|
|
|
- );
|
|
|
-
|
|
|
- bone.matrix.multiply( offset );
|
|
|
-
|
|
|
- bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
|
|
|
-
|
|
|
- bone.updateMatrixWorld();
|
|
|
-
|
|
|
- offsets[ name ] = offset;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return offsets;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-function renameBones( skeleton, names ) {
|
|
|
-
|
|
|
- const bones = getBones( skeleton );
|
|
|
-
|
|
|
- for ( let i = 0; i < bones.length; ++ i ) {
|
|
|
-
|
|
|
- const bone = bones[ i ];
|
|
|
-
|
|
|
- if ( names[ bone.name ] ) {
|
|
|
-
|
|
|
- bone.name = names[ bone.name ];
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return this;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-function getBones( skeleton ) {
|
|
|
-
|
|
|
- return Array.isArray( skeleton ) ? skeleton : skeleton.bones;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-function getBoneByName( name, skeleton ) {
|
|
|
-
|
|
|
- for ( let i = 0, bones = getBones( skeleton ); i < bones.length; i ++ ) {
|
|
|
-
|
|
|
- if ( name === bones[ i ].name )
|
|
|
-
|
|
|
- return bones[ i ];
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-function getNearestBone( bone, names ) {
|
|
|
-
|
|
|
- while ( bone.isBone ) {
|
|
|
-
|
|
|
- if ( names.indexOf( bone.name ) !== - 1 ) {
|
|
|
-
|
|
|
- return bone;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- bone = bone.parent;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-function findBoneTrackData( name, tracks ) {
|
|
|
-
|
|
|
- const regexp = /\[(.*)\]\.(.*)/,
|
|
|
- result = { name: name };
|
|
|
-
|
|
|
- for ( let i = 0; i < tracks.length; ++ i ) {
|
|
|
-
|
|
|
- // 1 is track name
|
|
|
- // 2 is track type
|
|
|
- const trackData = regexp.exec( tracks[ i ].name );
|
|
|
-
|
|
|
- if ( trackData && name === trackData[ 1 ] ) {
|
|
|
-
|
|
|
- result[ trackData[ 2 ] ] = i;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return result;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-function getEqualsBonesNames( skeleton, targetSkeleton ) {
|
|
|
-
|
|
|
- const sourceBones = getBones( skeleton ),
|
|
|
- targetBones = getBones( targetSkeleton ),
|
|
|
- bones = [];
|
|
|
-
|
|
|
- search : for ( let i = 0; i < sourceBones.length; i ++ ) {
|
|
|
-
|
|
|
- const boneName = sourceBones[ i ].name;
|
|
|
-
|
|
|
- for ( let j = 0; j < targetBones.length; j ++ ) {
|
|
|
-
|
|
|
- if ( boneName === targetBones[ j ].name ) {
|
|
|
-
|
|
|
- bones.push( boneName );
|
|
|
-
|
|
|
- continue search;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- return bones;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
function clone( source ) {
|
|
|
|
|
|
const sourceLookup = new Map();
|
|
@@ -606,8 +404,35 @@ function clone( source ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
+// internal helper
|
|
|
|
|
|
+function getBoneByName( name, skeleton ) {
|
|
|
|
|
|
+ for ( let i = 0, bones = getBones( skeleton ); i < bones.length; i ++ ) {
|
|
|
+
|
|
|
+ if ( name === bones[ i ].name )
|
|
|
+
|
|
|
+ return bones[ i ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+function getBones( skeleton ) {
|
|
|
+
|
|
|
+ return Array.isArray( skeleton ) ? skeleton : skeleton.bones;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+function getHelperFromSkeleton( skeleton ) {
|
|
|
+
|
|
|
+ const source = new SkeletonHelper( skeleton.bones[ 0 ] );
|
|
|
+ source.skeleton = skeleton;
|
|
|
+
|
|
|
+ return source;
|
|
|
+
|
|
|
+}
|
|
|
|
|
|
function parallelTraverse( a, b, callback ) {
|
|
|
|
|
@@ -624,13 +449,5 @@ function parallelTraverse( a, b, callback ) {
|
|
|
export {
|
|
|
retarget,
|
|
|
retargetClip,
|
|
|
- getHelperFromSkeleton,
|
|
|
- getSkeletonOffsets,
|
|
|
- renameBones,
|
|
|
- getBones,
|
|
|
- getBoneByName,
|
|
|
- getNearestBone,
|
|
|
- findBoneTrackData,
|
|
|
- getEqualsBonesNames,
|
|
|
clone,
|
|
|
};
|