@@ -11,34 +11,7 @@ const poses = {
1111} ;
1212
1313class Rig {
14- constructor ( model , { boneMappings} ) {
15- const modelBones = {
16- Hips : null ,
17- Spine : null ,
18- Chest : null ,
19- Neck : null ,
20- Head : null ,
21- Eye_L : null ,
22- Eye_R : null ,
23-
24- Left_shoulder : null ,
25- Left_arm : null ,
26- Left_elbow : null ,
27- Left_wrist : null ,
28- Left_leg : null ,
29- Left_knee : null ,
30- Left_ankle : null ,
31-
32- Right_shoulder : null ,
33- Right_arm : null ,
34- Right_elbow : null ,
35- Right_wrist : null ,
36- Right_leg : null ,
37- Right_knee : null ,
38- Right_ankle : null ,
39- } ;
40- this . modelBones = modelBones ;
41-
14+ constructor ( model ) {
4215 model . updateMatrixWorld ( true ) ;
4316 let skeleton ;
4417 model . traverse ( o => {
@@ -50,7 +23,229 @@ class Rig {
5023 skeleton = o . skeleton ;
5124 }
5225 o . bind ( skeleton ) ;
26+ }
27+ } ) ;
5328
29+ const tailBones = skeleton . bones . filter ( bone => bone . children . length === 0 ) ;
30+ const _findClosestParentBone = ( bone , pred ) => {
31+ for ( ; bone ; bone = bone . parent ) {
32+ if ( pred ( bone ) ) {
33+ return bone ;
34+ }
35+ }
36+ return null ;
37+ } ;
38+ const _findFurthestParentBone = ( bone , pred ) => {
39+ let result = null ;
40+ for ( ; bone ; bone = bone . parent ) {
41+ if ( pred ( bone ) ) {
42+ result = bone ;
43+ }
44+ }
45+ return result ;
46+ } ;
47+ const _distanceToParentBone = ( bone , parentBone ) => {
48+ for ( let i = 0 ; bone ; bone = bone . parent , i ++ ) {
49+ if ( bone === parentBone ) {
50+ return i ;
51+ }
52+ }
53+ return Infinity ;
54+ } ;
55+ const _traverseChild = ( bone , distance ) => {
56+ if ( distance <= 0 ) {
57+ return bone ;
58+ } else {
59+ for ( let i = 0 ; i < bone . children . length ; i ++ ) {
60+ const child = bone . children [ i ] ;
61+ const subchild = _traverseChild ( child , distance - 1 ) ;
62+ if ( subchild !== null ) {
63+ return subchild ;
64+ }
65+ }
66+ return null ;
67+ }
68+ } ;
69+ const _countCharacters = ( name , regex ) => {
70+ let result = 0 ;
71+ for ( let i = 0 ; i < name . length ; i ++ ) {
72+ if ( regex . test ( name [ i ] ) ) {
73+ result ++ ;
74+ }
75+ }
76+ return result ;
77+ } ;
78+ const _findEye = left => {
79+ const regexp = left ? / l / i : / r / i;
80+ const eyeBones = tailBones . map ( tailBone => {
81+ const eyeBone = _findFurthestParentBone ( tailBone , bone => / e y e / i. test ( bone . name ) && regexp . test ( bone . name . replace ( / e y e / gi, '' ) ) ) ;
82+ if ( eyeBone ) {
83+ return eyeBone ;
84+ } else {
85+ return null ;
86+ }
87+ } ) . filter ( spec => spec ) . sort ( ( a , b ) => {
88+ const aName = a . name . replace ( / s h o u l d e r / gi, '' ) ;
89+ const aLeftBalance = _countCharacters ( aName , / l / i) - _countCharacters ( aName , / r / i) ;
90+ const bName = b . name . replace ( / s h o u l d e r / gi, '' ) ;
91+ const bLeftBalance = _countCharacters ( bName , / l / i) - _countCharacters ( bName , / r / i) ;
92+ if ( ! left ) {
93+ return aLeftBalance - bLeftBalance ;
94+ } else {
95+ return bLeftBalance - aLeftBalance ;
96+ }
97+ } ) ;
98+ const eyeBone = eyeBones . length > 0 ? eyeBones [ 0 ] : null ;
99+ if ( eyeBone ) {
100+ return eyeBone ;
101+ } else {
102+ return null ;
103+ }
104+ } ;
105+ const _findHips = ( ) => {
106+ return skeleton . bones . find ( bone => / h i p / i. test ( bone . name ) ) ;
107+ } ;
108+ const _findSpine = ( chest , hips ) => {
109+ for ( let bone = chest ; bone ; bone = bone . parent ) {
110+ if ( bone . parent === hips ) {
111+ return bone ;
112+ }
113+ }
114+ return null ;
115+ } ;
116+ const _findShoulder = left => {
117+ const regexp = left ? / l / i : / r / i;
118+ const shoulderBones = tailBones . map ( tailBone => {
119+ const shoulderBone = _findClosestParentBone ( tailBone , bone => / s h o u l d e r / i. test ( bone . name ) && regexp . test ( bone . name . replace ( / s h o u l d e r / gi, '' ) ) ) ;
120+ if ( shoulderBone ) {
121+ const distance = _distanceToParentBone ( tailBone , shoulderBone ) ;
122+ if ( distance >= 3 ) {
123+ return {
124+ bone : shoulderBone ,
125+ distance,
126+ } ;
127+ } else {
128+ return null ;
129+ }
130+ } else {
131+ return null ;
132+ }
133+ } ) . filter ( spec => spec ) . sort ( ( a , b ) => {
134+ const diff = b . distance - a . distance ;
135+ if ( diff !== 0 ) {
136+ return diff ;
137+ } else {
138+ const aName = a . bone . name . replace ( / s h o u l d e r / gi, '' ) ;
139+ const aLeftBalance = _countCharacters ( aName , / l / i) - _countCharacters ( aName , / r / i) ;
140+ const bName = b . bone . name . replace ( / s h o u l d e r / gi, '' ) ;
141+ const bLeftBalance = _countCharacters ( bName , / l / i) - _countCharacters ( bName , / r / i) ;
142+ if ( ! left ) {
143+ return aLeftBalance - bLeftBalance ;
144+ } else {
145+ return bLeftBalance - aLeftBalance ;
146+ }
147+ }
148+ } ) ;
149+ const shoulderBone = shoulderBones . length > 0 ? shoulderBones [ 0 ] . bone : null ;
150+ if ( shoulderBone ) {
151+ return shoulderBone ;
152+ } else {
153+ return null ;
154+ }
155+ } ;
156+ const _findHand = shoulderBone => _traverseChild ( shoulderBone , 3 ) ;
157+ const _findFoot = left => {
158+ const regexp = left ? / l / i : / r / i;
159+ const legBones = tailBones . map ( tailBone => {
160+ const legBone = _findFurthestParentBone ( tailBone , bone => / l e g / i. test ( bone . name ) && regexp . test ( bone . name . replace ( / l e g / gi, '' ) ) ) ;
161+ if ( legBone ) {
162+ const distance = _distanceToParentBone ( tailBone , legBone ) ;
163+ if ( distance >= 2 ) {
164+ return {
165+ bone : legBone ,
166+ distance,
167+ } ;
168+ } else {
169+ return null ;
170+ }
171+ } else {
172+ return null ;
173+ }
174+ } ) . filter ( spec => spec ) . sort ( ( a , b ) => {
175+ const diff = b . distance - a . distance ;
176+ if ( diff !== 0 ) {
177+ return diff ;
178+ } else {
179+ const aName = a . bone . name . replace ( / l e g / gi, '' ) ;
180+ const aLeftBalance = _countCharacters ( aName , / l / i) - _countCharacters ( aName , / r / i) ;
181+ const bName = b . bone . name . replace ( / l e g / gi, '' ) ;
182+ const bLeftBalance = _countCharacters ( bName , / l / i) - _countCharacters ( bName , / r / i) ;
183+ if ( ! left ) {
184+ return aLeftBalance - bLeftBalance ;
185+ } else {
186+ return bLeftBalance - aLeftBalance ;
187+ }
188+ }
189+ } ) ;
190+ const legBone = legBones . length > 0 ? legBones [ 0 ] . bone : null ;
191+ if ( legBone ) {
192+ const footBone = _traverseChild ( legBone , 2 ) ;
193+ return footBone ;
194+ } else {
195+ return null ;
196+ }
197+ } ;
198+ const Eye_L = _findEye ( true ) ;
199+ const Eye_R = _findEye ( false ) ;
200+ const Head = Eye_L . parent ;
201+ const Neck = Head . parent ;
202+ const Chest = Neck . parent ;
203+ const Hips = _findHips ( ) ;
204+ const Spine = _findSpine ( Chest , Hips ) ;
205+ const Left_shoulder = _findShoulder ( true ) ;
206+ const Left_wrist = _findHand ( Left_shoulder ) ;
207+ const Left_elbow = Left_wrist . parent ;
208+ const Left_arm = Left_elbow . parent ;
209+ const Right_shoulder = _findShoulder ( false ) ;
210+ const Right_wrist = _findHand ( Right_shoulder ) ;
211+ const Right_elbow = Right_wrist . parent ;
212+ const Right_arm = Right_elbow . parent ;
213+ const Left_ankle = _findFoot ( true ) ;
214+ const Left_knee = Left_ankle . parent ;
215+ const Left_leg = Left_knee . parent ;
216+ const Right_ankle = _findFoot ( false ) ;
217+ const Right_knee = Right_ankle . parent ;
218+ const Right_leg = Right_knee . parent ;
219+ // console.log('got left hand', {leftEye, rightEye, head, neck, chest, hips, leftHand, leftLowerArm, leftUpperArm, rightHand, rightLowerArm, rightUpperArm, leftFoot, leftKnee, leftLeg, rightFoot, rightKnee, rightLeg});
220+ const modelBones = {
221+ Hips,
222+ Spine,
223+ Chest,
224+ Neck,
225+ Head,
226+ Eye_L,
227+ Eye_R,
228+
229+ Left_shoulder,
230+ Left_arm,
231+ Left_elbow,
232+ Left_wrist,
233+ Left_leg,
234+ Left_knee,
235+ Left_ankle,
236+
237+ Right_shoulder,
238+ Right_arm,
239+ Right_elbow,
240+ Right_wrist,
241+ Right_leg,
242+ Right_knee,
243+ Right_ankle,
244+ } ;
245+ this . modelBones = modelBones ;
246+
247+ /* model.traverse(o => {
248+ if (o.isSkinnedMesh) {
54249 for (const k in modelBones) {
55250 if (!modelBones[k]) {
56251 const userlandBoneName = boneMappings[k];
@@ -59,7 +254,7 @@ class Rig {
59254 }
60255 }
61256 }
62- } ) ;
257+ }); */
63258
64259 const eyeDirection = modelBones . Eye_L . getWorldPosition ( new Vector3 ( ) ) . sub ( modelBones . Head . getWorldPosition ( new Vector3 ( ) ) ) ;
65260 const flipZ = eyeDirection . z < 0 ;
@@ -82,16 +277,16 @@ class Rig {
82277 } ) ;
83278 if ( ! flipZ ) {
84279 [ 'Left_arm' , 'Right_arm' ] . forEach ( ( name , i ) => {
85- const userlandBoneName = boneMappings [ name ] ;
86- const bone = skeleton . bones . find ( bone => bone . name === userlandBoneName ) ;
280+ // const userlandBoneName = boneMappings[name];
281+ const bone = modelBones [ name ] ; // skeleton.bones.find(bone => bone.name === userlandBoneName);
87282 if ( bone ) {
88283 bone . quaternion . premultiply ( new Quaternion ( ) . setFromAxisAngle ( new Vector3 ( 0 , 0 , 1 ) , ( i === 0 ? 1 : - 1 ) * Math . PI * 0.25 ) ) ;
89284 }
90285 } ) ;
91286 } else {
92287 [ 'Hips' ] . forEach ( name => {
93- const userlandBoneName = boneMappings [ name ] ;
94- const bone = skeleton . bones . find ( bone => bone . name === userlandBoneName ) ;
288+ // const userlandBoneName = boneMappings[name];
289+ const bone = modelBones [ name ] ; // skeleton.bones.find(bone => bone.name === userlandBoneName);
95290 if ( bone ) {
96291 bone . quaternion . premultiply ( new Quaternion ( ) . setFromAxisAngle ( new Vector3 ( 0 , 1 , 0 ) , Math . PI ) ) ;
97292 }
0 commit comments