1
1
import * as THREE from 'three' ;
2
- import { mat4InvertCompat } from './utils/mat4InvertCompat' ;
3
2
import { Matrix4InverseCache } from './utils/Matrix4InverseCache' ;
4
3
import type { VRMSpringBoneColliderGroup } from './VRMSpringBoneColliderGroup' ;
5
4
import type { VRMSpringBoneJointSettings } from './VRMSpringBoneJointSettings' ;
@@ -13,26 +12,18 @@ const IDENTITY_MATRIX4 = new THREE.Matrix4();
13
12
// 計算中の一時保存用変数(一度インスタンスを作ったらあとは使い回す)
14
13
const _v3A = new THREE . Vector3 ( ) ;
15
14
const _v3B = new THREE . Vector3 ( ) ;
16
- const _v3C = new THREE . Vector3 ( ) ;
17
15
18
16
/**
19
17
* A temporary variable which is used in `update`
20
18
*/
21
19
const _worldSpacePosition = new THREE . Vector3 ( ) ;
22
20
23
- /**
24
- * A temporary variable which is used in `update`
25
- */
26
- const _centerSpacePosition = new THREE . Vector3 ( ) ;
27
-
28
21
/**
29
22
* A temporary variable which is used in `update`
30
23
*/
31
24
const _nextTail = new THREE . Vector3 ( ) ;
32
25
33
- const _quatA = new THREE . Quaternion ( ) ;
34
26
const _matA = new THREE . Matrix4 ( ) ;
35
- const _matB = new THREE . Matrix4 ( ) ;
36
27
37
28
/**
38
29
* A class represents a single joint of a spring bone.
@@ -204,7 +195,7 @@ export class VRMSpringBoneJoint {
204
195
}
205
196
206
197
// copy the child position to tails
207
- const matrixWorldToCenter = this . _getMatrixWorldToCenter ( _matA ) ;
198
+ const matrixWorldToCenter = this . _getMatrixWorldToCenter ( ) ;
208
199
this . bone . localToWorld ( this . _currentTail . copy ( this . _initialLocalChildPosition ) ) . applyMatrix4 ( matrixWorldToCenter ) ;
209
200
this . _prevTail . copy ( this . _currentTail ) ;
210
201
@@ -224,7 +215,7 @@ export class VRMSpringBoneJoint {
224
215
this . bone . matrixWorld . multiplyMatrices ( this . _parentMatrixWorld , this . bone . matrix ) ;
225
216
226
217
// Apply updated position to tail states
227
- const matrixWorldToCenter = this . _getMatrixWorldToCenter ( _matA ) ;
218
+ const matrixWorldToCenter = this . _getMatrixWorldToCenter ( ) ;
228
219
this . bone . localToWorld ( this . _currentTail . copy ( this . _initialLocalChildPosition ) ) . applyMatrix4 ( matrixWorldToCenter ) ;
229
220
this . _prevTail . copy ( this . _currentTail ) ;
230
221
}
@@ -241,64 +232,42 @@ export class VRMSpringBoneJoint {
241
232
// Update the _worldSpaceBoneLength
242
233
this . _calcWorldSpaceBoneLength ( ) ;
243
234
244
- // Get bone position in center space
245
- _worldSpacePosition . setFromMatrixPosition ( this . bone . matrixWorld ) ;
246
- let matrixWorldToCenter = this . _getMatrixWorldToCenter ( _matA ) ;
247
- _centerSpacePosition . copy ( _worldSpacePosition ) . applyMatrix4 ( matrixWorldToCenter ) ;
248
- const quatWorldToCenter = _quatA . setFromRotationMatrix ( matrixWorldToCenter ) ;
249
-
250
- // Get parent matrix in center space
251
- const centerSpaceParentMatrix = _matB . copy ( matrixWorldToCenter ) . multiply ( this . _parentMatrixWorld ) ;
252
-
253
- // Get boneAxis in center space
254
- const centerSpaceBoneAxis = _v3B
235
+ // Get boneAxis in world space
236
+ const worldSpaceBoneAxis = _v3B
255
237
. copy ( this . _boneAxis )
256
- . applyMatrix4 ( this . _initialLocalMatrix )
257
- . applyMatrix4 ( centerSpaceParentMatrix )
258
- . sub ( _centerSpacePosition )
259
- . normalize ( ) ;
260
-
261
- // gravity in center space
262
- const centerSpaceGravity = _v3C . copy ( this . settings . gravityDir ) . applyQuaternion ( quatWorldToCenter ) . normalize ( ) ;
263
-
264
- const matrixCenterToWorld = this . _getMatrixCenterToWorld ( _matA ) ;
238
+ . transformDirection ( this . _initialLocalMatrix )
239
+ . transformDirection ( this . _parentMatrixWorld ) ;
265
240
266
241
// verlet積分で次の位置を計算
267
242
_nextTail
243
+ // Determine inertia in center space
268
244
. copy ( this . _currentTail )
269
- . add (
270
- _v3A
271
- . copy ( this . _currentTail )
272
- . sub ( this . _prevTail )
273
- . multiplyScalar ( 1 - this . settings . dragForce ) ,
274
- ) // 前フレームの移動を継続する(減衰もあるよ)
275
- . add ( _v3A . copy ( centerSpaceBoneAxis ) . multiplyScalar ( this . settings . stiffness * delta ) ) // 親の回転による子ボーンの移動目標
276
- . add ( _v3A . copy ( centerSpaceGravity ) . multiplyScalar ( this . settings . gravityPower * delta ) ) // 外力による移動量
277
- . applyMatrix4 ( matrixCenterToWorld ) ; // tailをworld spaceに戻す
245
+ . add ( _v3A . subVectors ( this . _currentTail , this . _prevTail ) . multiplyScalar ( 1 - this . settings . dragForce ) ) // 前フレームの移動を継続する(減衰もあるよ)
246
+ // Convert center space to world space
247
+ . applyMatrix4 ( this . _getMatrixCenterToWorld ( ) ) // tailをworld spaceに戻す
248
+ // Apply stiffness and gravity in world space
249
+ . addScaledVector ( worldSpaceBoneAxis , this . settings . stiffness * delta ) // 親の回転による子ボーンの移動目標
250
+ . addScaledVector ( this . settings . gravityDir , this . settings . gravityPower * delta ) ; // 外力による移動量
278
251
279
252
// normalize bone length
253
+ _worldSpacePosition . setFromMatrixPosition ( this . bone . matrixWorld ) ;
280
254
_nextTail . sub ( _worldSpacePosition ) . normalize ( ) . multiplyScalar ( this . _worldSpaceBoneLength ) . add ( _worldSpacePosition ) ;
281
255
282
256
// Collisionで移動
283
257
this . _collision ( _nextTail ) ;
284
258
285
259
// update prevTail and currentTail
286
- matrixWorldToCenter = this . _getMatrixWorldToCenter ( _matA ) ;
287
-
288
260
this . _prevTail . copy ( this . _currentTail ) ;
289
- this . _currentTail . copy ( _v3A . copy ( _nextTail ) . applyMatrix4 ( matrixWorldToCenter ) ) ;
261
+ this . _currentTail . copy ( _nextTail ) . applyMatrix4 ( this . _getMatrixWorldToCenter ( ) ) ;
290
262
291
263
// Apply rotation, convert vector3 thing into actual quaternion
292
264
// Original UniVRM is doing center unit calculus at here but we're gonna do this on local unit
293
- const worldSpaceInitialMatrixInv = mat4InvertCompat (
294
- _matA . copy ( this . _parentMatrixWorld ) . multiply ( this . _initialLocalMatrix ) ,
295
- ) ;
296
- const applyRotation = _quatA . setFromUnitVectors (
297
- this . _boneAxis ,
298
- _v3A . copy ( _nextTail ) . applyMatrix4 ( worldSpaceInitialMatrixInv ) . normalize ( ) ,
299
- ) ;
300
-
301
- this . bone . quaternion . copy ( this . _initialLocalRotation ) . multiply ( applyRotation ) ;
265
+ const worldSpaceInitialMatrixInv = _matA
266
+ . multiplyMatrices ( this . _parentMatrixWorld , this . _initialLocalMatrix )
267
+ . invert ( ) ;
268
+ this . bone . quaternion
269
+ . setFromUnitVectors ( this . _boneAxis , _v3A . copy ( _nextTail ) . applyMatrix4 ( worldSpaceInitialMatrixInv ) . normalize ( ) )
270
+ . premultiply ( this . _initialLocalRotation ) ;
302
271
303
272
// We need to update its matrixWorld manually, since we tweaked the bone by our hand
304
273
this . bone . updateMatrix ( ) ;
@@ -311,19 +280,22 @@ export class VRMSpringBoneJoint {
311
280
* @param tail The tail you want to process
312
281
*/
313
282
private _collision ( tail : THREE . Vector3 ) : void {
314
- this . colliderGroups . forEach ( ( colliderGroup ) => {
315
- colliderGroup . colliders . forEach ( ( collider ) => {
283
+ for ( let cg = 0 ; cg < this . colliderGroups . length ; cg ++ ) {
284
+ for ( let c = 0 ; c < this . colliderGroups [ cg ] . colliders . length ; c ++ ) {
285
+ const collider = this . colliderGroups [ cg ] . colliders [ c ] ;
316
286
const dist = collider . shape . calculateCollision ( collider . matrixWorld , tail , this . settings . hitRadius , _v3A ) ;
317
287
318
288
if ( dist < 0.0 ) {
319
289
// hit
320
- tail . add ( _v3A . multiplyScalar ( - dist ) ) ;
290
+ tail . addScaledVector ( _v3A , - dist ) ;
321
291
322
292
// normalize bone length
323
- tail . sub ( _worldSpacePosition ) . normalize ( ) . multiplyScalar ( this . _worldSpaceBoneLength ) . add ( _worldSpacePosition ) ;
293
+ tail . sub ( _worldSpacePosition ) ;
294
+ const length = tail . length ( ) ;
295
+ tail . multiplyScalar ( this . _worldSpaceBoneLength / length ) . add ( _worldSpacePosition ) ;
324
296
}
325
- } ) ;
326
- } ) ;
297
+ }
298
+ }
327
299
}
328
300
329
301
/**
@@ -345,29 +317,15 @@ export class VRMSpringBoneJoint {
345
317
346
318
/**
347
319
* Create a matrix that converts center space into world space.
348
- * @param target Target matrix
349
320
*/
350
- private _getMatrixCenterToWorld ( target : THREE . Matrix4 ) : THREE . Matrix4 {
351
- if ( this . _center ) {
352
- target . copy ( this . _center . matrixWorld ) ;
353
- } else {
354
- target . identity ( ) ;
355
- }
356
-
357
- return target ;
321
+ private _getMatrixCenterToWorld ( ) : THREE . Matrix4 {
322
+ return this . _center ? this . _center . matrixWorld : IDENTITY_MATRIX4 ;
358
323
}
359
324
360
325
/**
361
326
* Create a matrix that converts world space into center space.
362
- * @param target Target matrix
363
327
*/
364
- private _getMatrixWorldToCenter ( target : THREE . Matrix4 ) : THREE . Matrix4 {
365
- if ( this . _center ) {
366
- target . copy ( ( this . _center . userData . inverseCacheProxy as Matrix4InverseCache ) . inverse ) ;
367
- } else {
368
- target . identity ( ) ;
369
- }
370
-
371
- return target ;
328
+ private _getMatrixWorldToCenter ( ) : THREE . Matrix4 {
329
+ return this . _center ? ( this . _center . userData . inverseCacheProxy as Matrix4InverseCache ) . inverse : IDENTITY_MATRIX4 ;
372
330
}
373
331
}
0 commit comments