@@ -38,12 +38,32 @@ THREE.CCDIKSolver = ( function () {
3838 constructor : CCDIKSolver ,
3939
4040 /**
41- * Update IK bones.
41+ * Update all IK bones.
4242 *
43- * @return {THREE. CCDIKSolver }
43+ * @return {CCDIKSolver }
4444 */
4545 update : function ( ) {
4646
47+ var iks = this . iks ;
48+
49+ for ( var i = 0 , il = iks . length ; i < il ; i ++ ) {
50+
51+ this . updateOne ( iks [ i ] ) ;
52+
53+ }
54+
55+ return this ;
56+
57+ } ,
58+
59+ /**
60+ * Update one IK bone
61+ *
62+ * @param {Object } ik parameter
63+ * @return {THREE.CCDIKSolver }
64+ */
65+ updateOne : function ( ) {
66+
4767 var q = new THREE . Quaternion ( ) ;
4868 var targetPos = new THREE . Vector3 ( ) ;
4969 var targetVec = new THREE . Vector3 ( ) ;
@@ -55,137 +75,131 @@ THREE.CCDIKSolver = ( function () {
5575 var axis = new THREE . Vector3 ( ) ;
5676 var vector = new THREE . Vector3 ( ) ;
5777
58- return function update ( ) {
78+ return function update ( ik ) {
5979
6080 var bones = this . mesh . skeleton . bones ;
61- var iks = this . iks ;
6281
6382 // for reference overhead reduction in loop
6483 var math = Math ;
6584
66- for ( var i = 0 , il = iks . length ; i < il ; i ++ ) {
67-
68- var ik = iks [ i ] ;
69- var effector = bones [ ik . effector ] ;
70- var target = bones [ ik . target ] ;
71-
72- // don't use getWorldPosition() here for the performance
73- // because it calls updateMatrixWorld( true ) inside.
74- targetPos . setFromMatrixPosition ( target . matrixWorld ) ;
75-
76- var links = ik . links ;
77- var iteration = ik . iteration !== undefined ? ik . iteration : 1 ;
78-
79- for ( var j = 0 ; j < iteration ; j ++ ) {
85+ var effector = bones [ ik . effector ] ;
86+ var target = bones [ ik . target ] ;
8087
81- var rotated = false ;
88+ // don't use getWorldPosition() here for the performance
89+ // because it calls updateMatrixWorld( true ) inside.
90+ targetPos . setFromMatrixPosition ( target . matrixWorld ) ;
8291
83- for ( var k = 0 , kl = links . length ; k < kl ; k ++ ) {
92+ var links = ik . links ;
93+ var iteration = ik . iteration !== undefined ? ik . iteration : 1 ;
8494
85- var link = bones [ links [ k ] . index ] ;
95+ for ( var i = 0 ; i < iteration ; i ++ ) {
8696
87- // skip this link and following links.
88- // this skip is used for MMD performance optimization.
89- if ( links [ k ] . enabled === false ) break ;
97+ var rotated = false ;
9098
91- var limitation = links [ k ] . limitation ;
92- var rotationMin = links [ k ] . rotationMin ;
93- var rotationMax = links [ k ] . rotationMax ;
99+ for ( var j = 0 , jl = links . length ; j < jl ; j ++ ) {
94100
95- // don't use getWorldPosition/Quaternion() here for the performance
96- // because they call updateMatrixWorld( true ) inside.
97- link . matrixWorld . decompose ( linkPos , invLinkQ , linkScale ) ;
98- invLinkQ . invert ( ) ;
99- effectorPos . setFromMatrixPosition ( effector . matrixWorld ) ;
101+ var link = bones [ links [ j ] . index ] ;
100102
101- // work in link world
102- effectorVec . subVectors ( effectorPos , linkPos ) ;
103- effectorVec . applyQuaternion ( invLinkQ ) ;
104- effectorVec . normalize ( ) ;
103+ // skip this link and following links.
104+ // this skip is used for MMD performance optimization.
105+ if ( links [ j ] . enabled === false ) break ;
105106
106- targetVec . subVectors ( targetPos , linkPos ) ;
107- targetVec . applyQuaternion ( invLinkQ ) ;
108- targetVec . normalize ( ) ;
107+ var limitation = links [ j ] . limitation ;
108+ var rotationMin = links [ j ] . rotationMin ;
109+ var rotationMax = links [ j ] . rotationMax ;
109110
110- var angle = targetVec . dot ( effectorVec ) ;
111+ // don't use getWorldPosition/Quaternion() here for the performance
112+ // because they call updateMatrixWorld( true ) inside.
113+ link . matrixWorld . decompose ( linkPos , invLinkQ , linkScale ) ;
114+ invLinkQ . invert ( ) ;
115+ effectorPos . setFromMatrixPosition ( effector . matrixWorld ) ;
111116
112- if ( angle > 1.0 ) {
117+ // work in link world
118+ effectorVec . subVectors ( effectorPos , linkPos ) ;
119+ effectorVec . applyQuaternion ( invLinkQ ) ;
120+ effectorVec . normalize ( ) ;
113121
114- angle = 1.0 ;
122+ targetVec . subVectors ( targetPos , linkPos ) ;
123+ targetVec . applyQuaternion ( invLinkQ ) ;
124+ targetVec . normalize ( ) ;
115125
116- } else if ( angle < - 1.0 ) {
126+ var angle = targetVec . dot ( effectorVec ) ;
117127
118- angle = - 1.0 ;
128+ if ( angle > 1.0 ) {
119129
120- }
130+ angle = 1.0 ;
121131
122- angle = math . acos ( angle ) ;
132+ } else if ( angle < - 1.0 ) {
123133
124- // skip if changing angle is too small to prevent vibration of bone
125- // Refer to http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js
126- if ( angle < 1e-5 ) continue ;
134+ angle = - 1.0 ;
127135
128- if ( ik . minAngle !== undefined && angle < ik . minAngle ) {
136+ }
129137
130- angle = ik . minAngle ;
138+ angle = math . acos ( angle ) ;
131139
132- }
140+ // skip if changing angle is too small to prevent vibration of bone
141+ // Refer to http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js
142+ if ( angle < 1e-5 ) continue ;
133143
134- if ( ik . maxAngle !== undefined && angle > ik . maxAngle ) {
144+ if ( ik . minAngle !== undefined && angle < ik . minAngle ) {
135145
136- angle = ik . maxAngle ;
146+ angle = ik . minAngle ;
137147
138- }
148+ }
139149
140- axis . crossVectors ( effectorVec , targetVec ) ;
141- axis . normalize ( ) ;
150+ if ( ik . maxAngle !== undefined && angle > ik . maxAngle ) {
142151
143- q . setFromAxisAngle ( axis , angle ) ;
144- link . quaternion . multiply ( q ) ;
152+ angle = ik . maxAngle ;
145153
146- // TODO: re-consider the limitation specification
147- if ( limitation !== undefined ) {
154+ }
148155
149- var c = link . quaternion . w ;
156+ axis . crossVectors ( effectorVec , targetVec ) ;
157+ axis . normalize ( ) ;
150158
151- if ( c > 1.0 ) c = 1.0 ;
159+ q . setFromAxisAngle ( axis , angle ) ;
160+ link . quaternion . multiply ( q ) ;
152161
153- var c2 = math . sqrt ( 1 - c * c ) ;
154- link . quaternion . set ( limitation . x * c2 ,
155- limitation . y * c2 ,
156- limitation . z * c2 ,
157- c ) ;
162+ // TODO: re-consider the limitation specification
163+ if ( limitation !== undefined ) {
158164
159- }
165+ var c = link . quaternion . w ;
160166
161- if ( rotationMin !== undefined ) {
167+ if ( c > 1.0 ) c = 1.0 ;
162168
163- link . rotation . setFromVector3 (
164- link . rotation
165- . toVector3 ( vector )
166- . max ( rotationMin ) ) ;
169+ var c2 = math . sqrt ( 1 - c * c ) ;
170+ link . quaternion . set ( limitation . x * c2 ,
171+ limitation . y * c2 ,
172+ limitation . z * c2 ,
173+ c ) ;
167174
168- }
175+ }
169176
170- if ( rotationMax !== undefined ) {
177+ if ( rotationMin !== undefined ) {
171178
172- link . rotation . setFromVector3 (
173- link . rotation
174- . toVector3 ( vector )
175- . min ( rotationMax ) ) ;
179+ link . rotation . setFromVector3 (
180+ link . rotation
181+ . toVector3 ( vector )
182+ . max ( rotationMin ) ) ;
176183
177- }
184+ }
178185
179- link . updateMatrixWorld ( true ) ;
186+ if ( rotationMax !== undefined ) {
180187
181- rotated = true ;
188+ link . rotation . setFromVector3 (
189+ link . rotation
190+ . toVector3 ( vector )
191+ . min ( rotationMax ) ) ;
182192
183193 }
184194
185- if ( ! rotated ) break ;
195+ link . updateMatrixWorld ( true ) ;
196+
197+ rotated = true ;
186198
187199 }
188200
201+ if ( ! rotated ) break ;
202+
189203 }
190204
191205 return this ;
0 commit comments