@@ -38,12 +38,32 @@ THREE.CCDIKSolver = ( function () {
38
38
constructor : CCDIKSolver ,
39
39
40
40
/**
41
- * Update IK bones.
41
+ * Update all IK bones.
42
42
*
43
- * @return {THREE. CCDIKSolver }
43
+ * @return {CCDIKSolver }
44
44
*/
45
45
update : function ( ) {
46
46
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
+
47
67
var q = new THREE . Quaternion ( ) ;
48
68
var targetPos = new THREE . Vector3 ( ) ;
49
69
var targetVec = new THREE . Vector3 ( ) ;
@@ -55,137 +75,131 @@ THREE.CCDIKSolver = ( function () {
55
75
var axis = new THREE . Vector3 ( ) ;
56
76
var vector = new THREE . Vector3 ( ) ;
57
77
58
- return function update ( ) {
78
+ return function update ( ik ) {
59
79
60
80
var bones = this . mesh . skeleton . bones ;
61
- var iks = this . iks ;
62
81
63
82
// for reference overhead reduction in loop
64
83
var math = Math ;
65
84
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 ] ;
80
87
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 ) ;
82
91
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 ;
84
94
85
- var link = bones [ links [ k ] . index ] ;
95
+ for ( var i = 0 ; i < iteration ; i ++ ) {
86
96
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 ;
90
98
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 ++ ) {
94
100
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 ] ;
100
102
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 ;
105
106
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 ;
109
110
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 ) ;
111
116
112
- if ( angle > 1.0 ) {
117
+ // work in link world
118
+ effectorVec . subVectors ( effectorPos , linkPos ) ;
119
+ effectorVec . applyQuaternion ( invLinkQ ) ;
120
+ effectorVec . normalize ( ) ;
113
121
114
- angle = 1.0 ;
122
+ targetVec . subVectors ( targetPos , linkPos ) ;
123
+ targetVec . applyQuaternion ( invLinkQ ) ;
124
+ targetVec . normalize ( ) ;
115
125
116
- } else if ( angle < - 1.0 ) {
126
+ var angle = targetVec . dot ( effectorVec ) ;
117
127
118
- angle = - 1.0 ;
128
+ if ( angle > 1.0 ) {
119
129
120
- }
130
+ angle = 1.0 ;
121
131
122
- angle = math . acos ( angle ) ;
132
+ } else if ( angle < - 1.0 ) {
123
133
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 ;
127
135
128
- if ( ik . minAngle !== undefined && angle < ik . minAngle ) {
136
+ }
129
137
130
- angle = ik . minAngle ;
138
+ angle = math . acos ( angle ) ;
131
139
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 ;
133
143
134
- if ( ik . maxAngle !== undefined && angle > ik . maxAngle ) {
144
+ if ( ik . minAngle !== undefined && angle < ik . minAngle ) {
135
145
136
- angle = ik . maxAngle ;
146
+ angle = ik . minAngle ;
137
147
138
- }
148
+ }
139
149
140
- axis . crossVectors ( effectorVec , targetVec ) ;
141
- axis . normalize ( ) ;
150
+ if ( ik . maxAngle !== undefined && angle > ik . maxAngle ) {
142
151
143
- q . setFromAxisAngle ( axis , angle ) ;
144
- link . quaternion . multiply ( q ) ;
152
+ angle = ik . maxAngle ;
145
153
146
- // TODO: re-consider the limitation specification
147
- if ( limitation !== undefined ) {
154
+ }
148
155
149
- var c = link . quaternion . w ;
156
+ axis . crossVectors ( effectorVec , targetVec ) ;
157
+ axis . normalize ( ) ;
150
158
151
- if ( c > 1.0 ) c = 1.0 ;
159
+ q . setFromAxisAngle ( axis , angle ) ;
160
+ link . quaternion . multiply ( q ) ;
152
161
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 ) {
158
164
159
- }
165
+ var c = link . quaternion . w ;
160
166
161
- if ( rotationMin !== undefined ) {
167
+ if ( c > 1.0 ) c = 1.0 ;
162
168
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 ) ;
167
174
168
- }
175
+ }
169
176
170
- if ( rotationMax !== undefined ) {
177
+ if ( rotationMin !== undefined ) {
171
178
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 ) ) ;
176
183
177
- }
184
+ }
178
185
179
- link . updateMatrixWorld ( true ) ;
186
+ if ( rotationMax !== undefined ) {
180
187
181
- rotated = true ;
188
+ link . rotation . setFromVector3 (
189
+ link . rotation
190
+ . toVector3 ( vector )
191
+ . min ( rotationMax ) ) ;
182
192
183
193
}
184
194
185
- if ( ! rotated ) break ;
195
+ link . updateMatrixWorld ( true ) ;
196
+
197
+ rotated = true ;
186
198
187
199
}
188
200
201
+ if ( ! rotated ) break ;
202
+
189
203
}
190
204
191
205
return this ;
0 commit comments