@zephyr3d/scene 0.9.4 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation/animationmask.js +224 -0
- package/dist/animation/animationmask.js.map +1 -0
- package/dist/animation/animationset.js +268 -67
- package/dist/animation/animationset.js.map +1 -1
- package/dist/animation/animationtrack.js.map +1 -1
- package/dist/animation/eulerrotationtrack.js +3 -0
- package/dist/animation/eulerrotationtrack.js.map +1 -1
- package/dist/animation/fixed_geometry_cache_track.js +7 -0
- package/dist/animation/fixed_geometry_cache_track.js.map +1 -1
- package/dist/animation/ik_modifier.js.map +1 -1
- package/dist/animation/joint_dynamics/collision.js +6 -4
- package/dist/animation/joint_dynamics/collision.js.map +1 -1
- package/dist/animation/joint_dynamics/controller.js +390 -43
- package/dist/animation/joint_dynamics/controller.js.map +1 -1
- package/dist/animation/joint_dynamics/joint_dynamics_system.js +62 -3
- package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
- package/dist/animation/joint_dynamics/solver.js +4 -3
- package/dist/animation/joint_dynamics/solver.js.map +1 -1
- package/dist/animation/joint_dynamics/types.js.map +1 -1
- package/dist/animation/joint_dynamics_modifier.js +2 -0
- package/dist/animation/joint_dynamics_modifier.js.map +1 -1
- package/dist/animation/morphtarget.js +3 -72
- package/dist/animation/morphtarget.js.map +1 -1
- package/dist/animation/morphtrack.js +3 -0
- package/dist/animation/morphtrack.js.map +1 -1
- package/dist/animation/pca_geometry_cache_track.js +3 -0
- package/dist/animation/pca_geometry_cache_track.js.map +1 -1
- package/dist/animation/proptrack.js +3 -0
- package/dist/animation/proptrack.js.map +1 -1
- package/dist/animation/rotationtrack.js +3 -0
- package/dist/animation/rotationtrack.js.map +1 -1
- package/dist/animation/scaletrack.js +3 -0
- package/dist/animation/scaletrack.js.map +1 -1
- package/dist/animation/skeleton.js +254 -79
- package/dist/animation/skeleton.js.map +1 -1
- package/dist/animation/skeleton_modifier.js.map +1 -1
- package/dist/animation/spring_modifier.js.map +1 -1
- package/dist/animation/translationtrack.js +3 -0
- package/dist/animation/translationtrack.js.map +1 -1
- package/dist/app/engine.js +171 -107
- package/dist/app/engine.js.map +1 -1
- package/dist/app/scriptregistry.js +251 -80
- package/dist/app/scriptregistry.js.map +1 -1
- package/dist/asset/assetmanager.js +344 -365
- package/dist/asset/assetmanager.js.map +1 -1
- package/dist/asset/loaders/gltf/gltf_loader.js +17 -14
- package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -1
- package/dist/asset/loaders/loader.js +1 -6
- package/dist/asset/loaders/loader.js.map +1 -1
- package/dist/asset/loaders/zabc/zabc_loader.js.map +1 -1
- package/dist/asset/model.js +1000 -131
- package/dist/asset/model.js.map +1 -1
- package/dist/avatar/wardrobe.js +474 -0
- package/dist/avatar/wardrobe.js.map +1 -0
- package/dist/index.d.ts +1125 -199
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +6 -3
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
- package/dist/material/mixins/pbr/common.js +72 -15
- package/dist/material/mixins/pbr/common.js.map +1 -1
- package/dist/material/msdf_text_sprite.js +4 -4
- package/dist/material/msdf_text_sprite.js.map +1 -1
- package/dist/material/pbrblueprint.js +102 -102
- package/dist/material/pbrblueprint.js.map +1 -1
- package/dist/render/envlight.js +54 -1
- package/dist/render/envlight.js.map +1 -1
- package/dist/render/sky.js +9 -0
- package/dist/render/sky.js.map +1 -1
- package/dist/scene/batchgroup.js +11 -13
- package/dist/scene/batchgroup.js.map +1 -1
- package/dist/scene/environment.js +15 -2
- package/dist/scene/environment.js.map +1 -1
- package/dist/scene/mesh.js +79 -16
- package/dist/scene/mesh.js.map +1 -1
- package/dist/scene/scene.js +1 -0
- package/dist/scene/scene.js.map +1 -1
- package/dist/scene/scene_node.js +203 -2
- package/dist/scene/scene_node.js.map +1 -1
- package/dist/text/font/font_asset.js.map +1 -1
- package/dist/text/msdf/generator.js.map +1 -1
- package/dist/text/msdf/shape.js +4 -1
- package/dist/text/msdf/shape.js.map +1 -1
- package/dist/text/runtime/msdf_text_atlas_manager.js +4 -1
- package/dist/text/runtime/msdf_text_atlas_manager.js.map +1 -1
- package/dist/utility/blueprint/material/inputs.js +1157 -1154
- package/dist/utility/blueprint/material/inputs.js.map +1 -1
- package/dist/utility/bounding_volume.js.map +1 -1
- package/dist/utility/pmrem.js +34 -8
- package/dist/utility/pmrem.js.map +1 -1
- package/dist/utility/serialization/manager.js +22 -9
- package/dist/utility/serialization/manager.js.map +1 -1
- package/dist/utility/serialization/scene/animation.js +700 -7
- package/dist/utility/serialization/scene/animation.js.map +1 -1
- package/dist/utility/serialization/scene/mesh.js +64 -4
- package/dist/utility/serialization/scene/mesh.js.map +1 -1
- package/dist/utility/serialization/scene/node.js +187 -8
- package/dist/utility/serialization/scene/node.js.map +1 -1
- package/dist/utility/serialization/types.js.map +1 -1
- package/dist/utility/textures/sheenlut.js +138 -0
- package/dist/utility/textures/sheenlut.js.map +1 -0
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EPSILON } from './types.js';
|
|
2
2
|
import { buildConstraints, buildSurfaceFaces } from './constraints.js';
|
|
3
3
|
import { simulate, applyAngleLimits, applyResult } from './solver.js';
|
|
4
|
-
import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
4
|
+
import { Vector3, Quaternion, Matrix4x4, clamp01, InterpolatorScalar } from '@zephyr3d/base';
|
|
5
5
|
|
|
6
6
|
// High-level orchestrator - SPCRJointDynamicsController API
|
|
7
7
|
/**
|
|
@@ -33,6 +33,10 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
33
33
|
_previousRootPosition = Vector3.zero();
|
|
34
34
|
_previousRootRotation = Quaternion.identity();
|
|
35
35
|
_rootTransform = null;
|
|
36
|
+
_rootPoints = [];
|
|
37
|
+
_allPoints = [];
|
|
38
|
+
_parentMap = new Map();
|
|
39
|
+
_maxPointDepth = 0;
|
|
36
40
|
_pointTransforms = [];
|
|
37
41
|
_colliderTransforms = [];
|
|
38
42
|
_grabberTransforms = [];
|
|
@@ -42,6 +46,10 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
42
46
|
_colliderHandleToIndex = new Map();
|
|
43
47
|
_flatPlaneHandleToIndex = new Map();
|
|
44
48
|
_grabberHandleToIndex = new Map();
|
|
49
|
+
_baseSystemScale = 1;
|
|
50
|
+
_currentSystemScale = 1;
|
|
51
|
+
_basePointParentLengths = [];
|
|
52
|
+
_baseConstraintLengths = [];
|
|
45
53
|
_nextColliderHandleId = 1;
|
|
46
54
|
_nextFlatPlaneHandleId = 1;
|
|
47
55
|
_nextGrabberHandleId = 1;
|
|
@@ -51,7 +59,7 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
51
59
|
_fadeTimer = 0;
|
|
52
60
|
_fadeDuration = 0;
|
|
53
61
|
constructor(config){
|
|
54
|
-
this._config = config;
|
|
62
|
+
this._config = this._sanitizeControllerConfig(this._cloneControllerConfig(config));
|
|
55
63
|
}
|
|
56
64
|
/**
|
|
57
65
|
* Initializes the physics system.
|
|
@@ -63,32 +71,34 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
63
71
|
* @param flatPlanes - Plane limiters such as the floor to prevent penetration.
|
|
64
72
|
*/ initialize(rootTransform, rootPoints, pointTransforms, colliders, grabbers, flatPlanes) {
|
|
65
73
|
this._rootTransform = rootTransform;
|
|
74
|
+
this._baseSystemScale = this._getSystemUniformScale();
|
|
75
|
+
this._currentSystemScale = this._baseSystemScale;
|
|
76
|
+
this._rootPoints = [
|
|
77
|
+
...rootPoints
|
|
78
|
+
];
|
|
66
79
|
this._pointTransforms = pointTransforms;
|
|
67
80
|
this._colliderTransforms = colliders.map((c)=>c.transform);
|
|
68
81
|
this._grabberTransforms = grabbers.map((g)=>g.transform);
|
|
69
82
|
// Build constraints
|
|
70
|
-
this.
|
|
71
|
-
this.
|
|
83
|
+
this._rebuildConstraints();
|
|
84
|
+
this._baseConstraintLengths = this._constraints.map((constraint)=>constraint.length);
|
|
72
85
|
// Flatten bone hierarchy to point list, build parent map
|
|
73
86
|
const allPoints = [];
|
|
74
|
-
|
|
75
|
-
|
|
87
|
+
this._parentMap = new Map(); // child index -> parent index
|
|
88
|
+
const walk = (node)=>{
|
|
76
89
|
allPoints.push(node);
|
|
77
90
|
for (const c of node.children){
|
|
78
|
-
|
|
91
|
+
this._parentMap.set(c.index, node.index);
|
|
79
92
|
walk(c);
|
|
80
93
|
}
|
|
81
|
-
}
|
|
94
|
+
};
|
|
82
95
|
for (const r of rootPoints){
|
|
83
96
|
walk(r);
|
|
84
97
|
}
|
|
85
|
-
|
|
98
|
+
this._allPoints = allPoints;
|
|
99
|
+
this._maxPointDepth = allPoints.length > 0 ? Math.max(...allPoints.map((p)=>p.depth)) : 0;
|
|
86
100
|
// Compute boneAxis from transforms: local-space direction to first child
|
|
87
101
|
// This is critical for correct bone rotation in skinned meshes
|
|
88
|
-
const indexToNode = new Map();
|
|
89
|
-
for (const p of allPoints){
|
|
90
|
-
indexToNode.set(p.index, p);
|
|
91
|
-
}
|
|
92
102
|
for (const p of allPoints){
|
|
93
103
|
if (!p.boneAxis && p.children.length > 0) {
|
|
94
104
|
const childPos = pointTransforms[p.children[0].index].getWorldPosition();
|
|
@@ -105,7 +115,8 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
105
115
|
}
|
|
106
116
|
}
|
|
107
117
|
// Build PointR/RW arrays
|
|
108
|
-
this._pointsR = allPoints.map((p)=>this._createPointR(p
|
|
118
|
+
this._pointsR = allPoints.map((p)=>this._createPointR(p));
|
|
119
|
+
this._basePointParentLengths = this._pointsR.map((point)=>point.parentLength);
|
|
109
120
|
this._pointsRW = allPoints.map(()=>this._createPointRW());
|
|
110
121
|
this._positionsToTransform = new Array(allPoints.length).fill(Vector3.zero());
|
|
111
122
|
// Initialize colliders
|
|
@@ -168,6 +179,7 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
168
179
|
}
|
|
169
180
|
}
|
|
170
181
|
const blendRatio = this._computeBlendRatio();
|
|
182
|
+
this._updateScaleDependentParameters();
|
|
171
183
|
// Capture current transforms
|
|
172
184
|
const rootPos = this._rootTransform.getWorldPosition();
|
|
173
185
|
const rootRot = this._rootTransform.getWorldRotation();
|
|
@@ -243,6 +255,189 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
243
255
|
}));
|
|
244
256
|
}
|
|
245
257
|
/**
|
|
258
|
+
* Returns a detached snapshot of the current runtime configuration.
|
|
259
|
+
*/ getConfig() {
|
|
260
|
+
return this._cloneControllerConfig(this._config);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Returns detached collider snapshots for persistence.
|
|
264
|
+
*/ getColliderSnapshots() {
|
|
265
|
+
return this._collidersR.map((r, index)=>({
|
|
266
|
+
r: {
|
|
267
|
+
...r
|
|
268
|
+
},
|
|
269
|
+
transform: this._colliderTransforms[index]?.node ?? null,
|
|
270
|
+
enabled: this._collidersRW[index]?.enabled !== 0
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Returns detached flat-plane snapshots for persistence.
|
|
275
|
+
*/ getFlatPlaneSnapshots() {
|
|
276
|
+
return this._flatPlaneAll.map((plane, index)=>({
|
|
277
|
+
up: plane.normal.clone(),
|
|
278
|
+
position: Vector3.scale(plane.normal, -plane.distance),
|
|
279
|
+
enabled: this._flatPlaneEnabled[index] ?? true
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Returns detached grabber snapshots for persistence.
|
|
284
|
+
*/ getGrabberSnapshots() {
|
|
285
|
+
return this._grabbersR.map((r, index)=>({
|
|
286
|
+
r: {
|
|
287
|
+
...r
|
|
288
|
+
},
|
|
289
|
+
transform: this._grabberTransforms[index]?.node ?? null,
|
|
290
|
+
enabled: this._grabbersRW[index]?.enabled !== 0
|
|
291
|
+
}));
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Replaces the runtime configuration.
|
|
295
|
+
*
|
|
296
|
+
* If the controller is already initialized, cached per-point parameters and generated
|
|
297
|
+
* constraints are refreshed immediately so editor-driven changes take effect in the next step.
|
|
298
|
+
*
|
|
299
|
+
* @param config - Complete controller configuration to apply.
|
|
300
|
+
*/ setConfig(config) {
|
|
301
|
+
this._config = this._sanitizeControllerConfig(this._cloneControllerConfig(config));
|
|
302
|
+
this._refreshCachedSimulationConfig();
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Applies a partial runtime configuration update.
|
|
306
|
+
*
|
|
307
|
+
* This is intended for editor workflows that tweak one or more simulation parameters live.
|
|
308
|
+
* The controller updates only the affected caches: global step parameters are applied directly,
|
|
309
|
+
* per-point curve/gravity changes rebuild cached point coefficients, and constraint option
|
|
310
|
+
* changes rebuild the generated constraints.
|
|
311
|
+
*
|
|
312
|
+
* @param config - Partial configuration update.
|
|
313
|
+
*/ updateConfig(config) {
|
|
314
|
+
let refreshPoints = false;
|
|
315
|
+
let refreshConstraints = false;
|
|
316
|
+
if (config.gravity) {
|
|
317
|
+
this._config.gravity = config.gravity.clone();
|
|
318
|
+
refreshPoints = true;
|
|
319
|
+
}
|
|
320
|
+
if (config.windForce) {
|
|
321
|
+
this._config.windForce = config.windForce.clone();
|
|
322
|
+
}
|
|
323
|
+
if (typeof config.relaxation === 'number') {
|
|
324
|
+
this._config.relaxation = Math.max(0, Math.trunc(config.relaxation));
|
|
325
|
+
}
|
|
326
|
+
if (typeof config.subSteps === 'number') {
|
|
327
|
+
this._config.subSteps = Math.max(1, Math.trunc(config.subSteps));
|
|
328
|
+
}
|
|
329
|
+
if (typeof config.rootSlideLimit === 'number') {
|
|
330
|
+
this._config.rootSlideLimit = config.rootSlideLimit;
|
|
331
|
+
}
|
|
332
|
+
if (typeof config.rootRotateLimit === 'number') {
|
|
333
|
+
this._config.rootRotateLimit = config.rootRotateLimit;
|
|
334
|
+
}
|
|
335
|
+
if (typeof config.constraintShrinkLimit === 'number') {
|
|
336
|
+
this._config.constraintShrinkLimit = Math.max(0, config.constraintShrinkLimit);
|
|
337
|
+
}
|
|
338
|
+
if (typeof config.blendRatio === 'number') {
|
|
339
|
+
this._config.blendRatio = clamp01(config.blendRatio);
|
|
340
|
+
}
|
|
341
|
+
if (typeof config.stabilizationFrameRate === 'number') {
|
|
342
|
+
this._config.stabilizationFrameRate = config.stabilizationFrameRate;
|
|
343
|
+
}
|
|
344
|
+
if (typeof config.isFakeWave === 'boolean') {
|
|
345
|
+
this._config.isFakeWave = config.isFakeWave;
|
|
346
|
+
}
|
|
347
|
+
if (typeof config.fakeWaveSpeed === 'number') {
|
|
348
|
+
this._config.fakeWaveSpeed = config.fakeWaveSpeed;
|
|
349
|
+
}
|
|
350
|
+
if (typeof config.fakeWavePower === 'number') {
|
|
351
|
+
this._config.fakeWavePower = config.fakeWavePower;
|
|
352
|
+
}
|
|
353
|
+
if (typeof config.enableSurfaceCollision === 'boolean') {
|
|
354
|
+
this._config.enableSurfaceCollision = config.enableSurfaceCollision;
|
|
355
|
+
if (!config.constraintOptions || config.constraintOptions.enableSurfaceCollision === undefined) {
|
|
356
|
+
this._config.constraintOptions.enableSurfaceCollision = config.enableSurfaceCollision;
|
|
357
|
+
refreshConstraints = true;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (typeof config.enableBroadPhase === 'boolean') {
|
|
361
|
+
this._config.enableBroadPhase = config.enableBroadPhase;
|
|
362
|
+
}
|
|
363
|
+
if (typeof config.preserveTwist === 'boolean') {
|
|
364
|
+
this._config.preserveTwist = config.preserveTwist;
|
|
365
|
+
}
|
|
366
|
+
if (config.angleLimitConfig) {
|
|
367
|
+
if (typeof config.angleLimitConfig.angleLimit === 'number') {
|
|
368
|
+
this._config.angleLimitConfig.angleLimit = config.angleLimitConfig.angleLimit;
|
|
369
|
+
}
|
|
370
|
+
if (typeof config.angleLimitConfig.limitFromRoot === 'boolean') {
|
|
371
|
+
this._config.angleLimitConfig.limitFromRoot = config.angleLimitConfig.limitFromRoot;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (config.curves) {
|
|
375
|
+
const curveKeys = [
|
|
376
|
+
'massScale',
|
|
377
|
+
'gravityScale',
|
|
378
|
+
'windForceScale',
|
|
379
|
+
'resistance',
|
|
380
|
+
'hardness',
|
|
381
|
+
'friction',
|
|
382
|
+
'pointRadius',
|
|
383
|
+
'sliderJointLength',
|
|
384
|
+
'allShrinkScale',
|
|
385
|
+
'allStretchScale',
|
|
386
|
+
'structuralShrinkVertical',
|
|
387
|
+
'structuralStretchVertical',
|
|
388
|
+
'structuralShrinkHorizontal',
|
|
389
|
+
'structuralStretchHorizontal',
|
|
390
|
+
'shearShrink',
|
|
391
|
+
'shearStretch',
|
|
392
|
+
'bendingShrinkVertical',
|
|
393
|
+
'bendingStretchVertical',
|
|
394
|
+
'bendingShrinkHorizontal',
|
|
395
|
+
'bendingStretchHorizontal',
|
|
396
|
+
'fakeWavePower',
|
|
397
|
+
'fakeWaveFreq'
|
|
398
|
+
];
|
|
399
|
+
for (const key of curveKeys){
|
|
400
|
+
const curve = config.curves[key];
|
|
401
|
+
if (curve !== undefined) {
|
|
402
|
+
this._config.curves[key] = this._cloneInterpolatorScalar(curve);
|
|
403
|
+
refreshPoints = true;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (config.constraintOptions) {
|
|
408
|
+
const optionKeys = [
|
|
409
|
+
'structuralVertical',
|
|
410
|
+
'structuralHorizontal',
|
|
411
|
+
'shear',
|
|
412
|
+
'bendingVertical',
|
|
413
|
+
'bendingHorizontal',
|
|
414
|
+
'isLoop',
|
|
415
|
+
'collideStructuralVertical',
|
|
416
|
+
'collideStructuralHorizontal',
|
|
417
|
+
'collideShear',
|
|
418
|
+
'enableSurfaceCollision'
|
|
419
|
+
];
|
|
420
|
+
for (const key of optionKeys){
|
|
421
|
+
const value = config.constraintOptions[key];
|
|
422
|
+
if (value !== undefined) {
|
|
423
|
+
this._config.constraintOptions[key] = value;
|
|
424
|
+
if (key === 'enableSurfaceCollision' && config.enableSurfaceCollision === undefined) {
|
|
425
|
+
this._config.enableSurfaceCollision = value;
|
|
426
|
+
}
|
|
427
|
+
refreshConstraints = true;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (refreshConstraints) {
|
|
432
|
+
this._rebuildConstraints();
|
|
433
|
+
this._baseConstraintLengths = this._constraints.map((constraint)=>constraint.length);
|
|
434
|
+
this._updateScaleDependentParameters(true);
|
|
435
|
+
}
|
|
436
|
+
if (refreshPoints) {
|
|
437
|
+
this._refreshPointParameters();
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
246
441
|
* Compensates for teleportation by resetting the previous root transform to the current one.
|
|
247
442
|
* Call this after a character warp or teleport to avoid a large root-motion impulse on the
|
|
248
443
|
* next simulation step.
|
|
@@ -326,7 +521,7 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
326
521
|
* The final wind contribution is still scaled per point by `windForceScale` and mass.
|
|
327
522
|
* @param wind - Wind vector in world space.
|
|
328
523
|
*/ setWindForce(wind) {
|
|
329
|
-
this._config.windForce = wind;
|
|
524
|
+
this._config.windForce = wind.clone();
|
|
330
525
|
}
|
|
331
526
|
/**
|
|
332
527
|
* Enable/disable broad-phase pruning for runtime performance comparison
|
|
@@ -595,6 +790,10 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
595
790
|
}
|
|
596
791
|
return this._config.blendRatio;
|
|
597
792
|
}
|
|
793
|
+
_refreshCachedSimulationConfig() {
|
|
794
|
+
this._rebuildConstraints();
|
|
795
|
+
this._refreshPointParameters();
|
|
796
|
+
}
|
|
598
797
|
_getColliderIndex(handle) {
|
|
599
798
|
if (handle.type !== 'collider') {
|
|
600
799
|
return -1;
|
|
@@ -647,13 +846,61 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
647
846
|
this._grabberHandleToIndex.set(this._grabberHandleIds[i], i);
|
|
648
847
|
}
|
|
649
848
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
849
|
+
_rebuildConstraints() {
|
|
850
|
+
if (this._rootPoints.length === 0) {
|
|
851
|
+
this._constraints = [];
|
|
852
|
+
this._surfaceConstraints = [];
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
this._constraints = buildConstraints(this._rootPoints, this._config.constraintOptions);
|
|
856
|
+
this._surfaceConstraints = buildSurfaceFaces(this._rootPoints, this._config.constraintOptions.isLoop);
|
|
857
|
+
}
|
|
858
|
+
_getSystemUniformScale() {
|
|
859
|
+
if (!this._rootTransform) {
|
|
860
|
+
return 1;
|
|
861
|
+
}
|
|
862
|
+
const scale = this._rootTransform.getWorldScale();
|
|
863
|
+
return Math.max((Math.abs(scale.x) + Math.abs(scale.y) + Math.abs(scale.z)) / 3, EPSILON);
|
|
864
|
+
}
|
|
865
|
+
_updateScaleDependentParameters(force = false) {
|
|
866
|
+
const systemScale = this._getSystemUniformScale();
|
|
867
|
+
const scaleChanged = Math.abs(systemScale - this._currentSystemScale) > EPSILON;
|
|
868
|
+
if (!force && !scaleChanged) {
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
this._currentSystemScale = systemScale;
|
|
872
|
+
const ratio = this._baseSystemScale > EPSILON ? systemScale / this._baseSystemScale : 1;
|
|
873
|
+
for(let i = 0; i < this._pointsR.length; i++){
|
|
874
|
+
this._pointsR[i].parentLength = (this._basePointParentLengths[i] ?? this._pointsR[i].parentLength) * ratio;
|
|
875
|
+
}
|
|
876
|
+
for(let i = 0; i < this._constraints.length; i++){
|
|
877
|
+
this._constraints[i].length = (this._baseConstraintLengths[i] ?? this._constraints[i].length) * ratio;
|
|
878
|
+
}
|
|
879
|
+
this._refreshPointParameters();
|
|
880
|
+
if (scaleChanged) {
|
|
881
|
+
for(let i = 0; i < this._pointsRW.length; i++){
|
|
882
|
+
const pos = this._pointTransforms[i].getWorldPosition();
|
|
883
|
+
this._pointsRW[i].positionCurrent = pos.clone();
|
|
884
|
+
this._pointsRW[i].positionPrevious = pos.clone();
|
|
885
|
+
this._pointsRW[i].positionCurrentTransform = pos.clone();
|
|
886
|
+
this._pointsRW[i].positionPreviousTransform = pos.clone();
|
|
887
|
+
}
|
|
888
|
+
this.warp();
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
_refreshPointParameters() {
|
|
892
|
+
if (!this._initialized) {
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
for(let i = 0; i < this._allPoints.length; i++){
|
|
896
|
+
this._applyConfigToPoint(this._pointsR[i], this._allPoints[i]);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
_createPointR(node) {
|
|
900
|
+
const parentIdx = this._parentMap.get(node.index) ?? -1;
|
|
654
901
|
const childIdx = node.children.length > 0 ? node.children[0].index : -1;
|
|
655
902
|
// Capture initial local transform for rotation blending
|
|
656
|
-
const t =
|
|
903
|
+
const t = this._pointTransforms[node.index];
|
|
657
904
|
const initLocalPos = t.getLocalPosition();
|
|
658
905
|
const initLocalRot = t.getLocalRotation();
|
|
659
906
|
const initLocalScale = t.getLocalScale();
|
|
@@ -662,39 +909,39 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
662
909
|
// ParentLength: distance to parent
|
|
663
910
|
let parentLength = 0;
|
|
664
911
|
if (parentIdx !== -1) {
|
|
665
|
-
const pPos =
|
|
666
|
-
const cPos =
|
|
912
|
+
const pPos = this._pointTransforms[parentIdx].getWorldPosition();
|
|
913
|
+
const cPos = this._pointTransforms[node.index].getWorldPosition();
|
|
667
914
|
parentLength = Vector3.distance(pPos, cPos);
|
|
668
915
|
}
|
|
669
|
-
|
|
916
|
+
const point = {
|
|
670
917
|
parent: parentIdx,
|
|
671
918
|
child: childIdx,
|
|
672
919
|
applyInvertCollision: 0,
|
|
673
920
|
movableLimitIndex: -1,
|
|
674
921
|
movableLimitRadius: 0,
|
|
675
922
|
weight: node.isFixed ? 0 : 1,
|
|
676
|
-
mass:
|
|
677
|
-
resistance:
|
|
678
|
-
hardness:
|
|
679
|
-
frictionScale:
|
|
680
|
-
sliderJointLength:
|
|
923
|
+
mass: 0,
|
|
924
|
+
resistance: 0,
|
|
925
|
+
hardness: 0,
|
|
926
|
+
frictionScale: 0,
|
|
927
|
+
sliderJointLength: 0,
|
|
681
928
|
parentLength,
|
|
682
|
-
structuralShrinkVertical:
|
|
683
|
-
structuralStretchVertical:
|
|
684
|
-
structuralShrinkHorizontal:
|
|
685
|
-
structuralStretchHorizontal:
|
|
686
|
-
shearShrink:
|
|
687
|
-
shearStretch:
|
|
688
|
-
bendingShrinkVertical:
|
|
689
|
-
bendingStretchVertical:
|
|
690
|
-
bendingShrinkHorizontal:
|
|
691
|
-
bendingStretchHorizontal:
|
|
692
|
-
windForceScale:
|
|
693
|
-
fakeWavePower:
|
|
694
|
-
fakeWaveFreq:
|
|
929
|
+
structuralShrinkVertical: 0,
|
|
930
|
+
structuralStretchVertical: 0,
|
|
931
|
+
structuralShrinkHorizontal: 0,
|
|
932
|
+
structuralStretchHorizontal: 0,
|
|
933
|
+
shearShrink: 0,
|
|
934
|
+
shearStretch: 0,
|
|
935
|
+
bendingShrinkVertical: 0,
|
|
936
|
+
bendingStretchVertical: 0,
|
|
937
|
+
bendingShrinkHorizontal: 0,
|
|
938
|
+
bendingStretchHorizontal: 0,
|
|
939
|
+
windForceScale: 0,
|
|
940
|
+
fakeWavePower: 0,
|
|
941
|
+
fakeWaveFreq: 0,
|
|
695
942
|
forceFadeRatio: 0,
|
|
696
|
-
pointRadius:
|
|
697
|
-
gravity: Vector3.
|
|
943
|
+
pointRadius: 0,
|
|
944
|
+
gravity: Vector3.zero(),
|
|
698
945
|
boneAxis,
|
|
699
946
|
initialLocalScale: initLocalScale,
|
|
700
947
|
initialLocalRotation: initLocalRot,
|
|
@@ -705,6 +952,35 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
705
952
|
})(),
|
|
706
953
|
initialLocalPosition: initLocalPos
|
|
707
954
|
};
|
|
955
|
+
this._applyConfigToPoint(point, node);
|
|
956
|
+
return point;
|
|
957
|
+
}
|
|
958
|
+
_applyConfigToPoint(point, node) {
|
|
959
|
+
const rate = this._maxPointDepth > 0 ? node.depth / this._maxPointDepth : 0;
|
|
960
|
+
const c = this._config.curves;
|
|
961
|
+
const allShrinkScale = c.allShrinkScale.evaluate(rate);
|
|
962
|
+
const allStretchScale = c.allStretchScale.evaluate(rate);
|
|
963
|
+
point.mass = c.massScale.evaluate(rate);
|
|
964
|
+
point.resistance = clamp01(c.resistance.evaluate(rate));
|
|
965
|
+
point.hardness = clamp01(c.hardness.evaluate(rate));
|
|
966
|
+
point.frictionScale = c.friction.evaluate(rate);
|
|
967
|
+
point.sliderJointLength = c.sliderJointLength.evaluate(rate);
|
|
968
|
+
point.structuralShrinkVertical = c.structuralShrinkVertical.evaluate(rate) * allShrinkScale * 0.5;
|
|
969
|
+
point.structuralStretchVertical = c.structuralStretchVertical.evaluate(rate) * allStretchScale * 0.5;
|
|
970
|
+
point.structuralShrinkHorizontal = c.structuralShrinkHorizontal.evaluate(rate) * allShrinkScale * 0.5;
|
|
971
|
+
point.structuralStretchHorizontal = c.structuralStretchHorizontal.evaluate(rate) * allStretchScale * 0.5;
|
|
972
|
+
point.shearShrink = c.shearShrink.evaluate(rate) * allShrinkScale * 0.5;
|
|
973
|
+
point.shearStretch = c.shearStretch.evaluate(rate) * allStretchScale * 0.5;
|
|
974
|
+
point.bendingShrinkVertical = c.bendingShrinkVertical.evaluate(rate) * allShrinkScale * 0.5;
|
|
975
|
+
point.bendingStretchVertical = c.bendingStretchVertical.evaluate(rate) * allStretchScale * 0.5;
|
|
976
|
+
point.bendingShrinkHorizontal = c.bendingShrinkHorizontal.evaluate(rate) * allShrinkScale * 0.5;
|
|
977
|
+
point.bendingStretchHorizontal = c.bendingStretchHorizontal.evaluate(rate) * allStretchScale * 0.5;
|
|
978
|
+
point.windForceScale = c.windForceScale.evaluate(rate) * rate;
|
|
979
|
+
point.fakeWavePower = c.fakeWavePower.evaluate(rate);
|
|
980
|
+
point.fakeWaveFreq = c.fakeWaveFreq.evaluate(rate);
|
|
981
|
+
const systemScale = this._currentSystemScale;
|
|
982
|
+
point.pointRadius = Math.max(0, c.pointRadius.evaluate(rate) * systemScale);
|
|
983
|
+
point.gravity = Vector3.scale(this._config.gravity, c.gravityScale.evaluate(rate) * systemScale);
|
|
708
984
|
}
|
|
709
985
|
_createPointRW() {
|
|
710
986
|
return {
|
|
@@ -738,9 +1014,80 @@ import { Vector3, Quaternion, Matrix4x4, clamp01 } from '@zephyr3d/base';
|
|
|
738
1014
|
localBoundsMin: Vector3.zero(),
|
|
739
1015
|
localBoundsMax: Vector3.zero(),
|
|
740
1016
|
radius: 0,
|
|
1017
|
+
height: 0,
|
|
741
1018
|
enabled: 1
|
|
742
1019
|
};
|
|
743
1020
|
}
|
|
1021
|
+
_cloneControllerConfig(config) {
|
|
1022
|
+
const curves = {
|
|
1023
|
+
massScale: this._cloneInterpolatorScalar(config.curves.massScale),
|
|
1024
|
+
gravityScale: this._cloneInterpolatorScalar(config.curves.gravityScale),
|
|
1025
|
+
windForceScale: this._cloneInterpolatorScalar(config.curves.windForceScale),
|
|
1026
|
+
resistance: this._cloneInterpolatorScalar(config.curves.resistance),
|
|
1027
|
+
hardness: this._cloneInterpolatorScalar(config.curves.hardness),
|
|
1028
|
+
friction: this._cloneInterpolatorScalar(config.curves.friction),
|
|
1029
|
+
pointRadius: this._cloneInterpolatorScalar(config.curves.pointRadius),
|
|
1030
|
+
sliderJointLength: this._cloneInterpolatorScalar(config.curves.sliderJointLength),
|
|
1031
|
+
allShrinkScale: this._cloneInterpolatorScalar(config.curves.allShrinkScale),
|
|
1032
|
+
allStretchScale: this._cloneInterpolatorScalar(config.curves.allStretchScale),
|
|
1033
|
+
structuralShrinkVertical: this._cloneInterpolatorScalar(config.curves.structuralShrinkVertical),
|
|
1034
|
+
structuralStretchVertical: this._cloneInterpolatorScalar(config.curves.structuralStretchVertical),
|
|
1035
|
+
structuralShrinkHorizontal: this._cloneInterpolatorScalar(config.curves.structuralShrinkHorizontal),
|
|
1036
|
+
structuralStretchHorizontal: this._cloneInterpolatorScalar(config.curves.structuralStretchHorizontal),
|
|
1037
|
+
shearShrink: this._cloneInterpolatorScalar(config.curves.shearShrink),
|
|
1038
|
+
shearStretch: this._cloneInterpolatorScalar(config.curves.shearStretch),
|
|
1039
|
+
bendingShrinkVertical: this._cloneInterpolatorScalar(config.curves.bendingShrinkVertical),
|
|
1040
|
+
bendingStretchVertical: this._cloneInterpolatorScalar(config.curves.bendingStretchVertical),
|
|
1041
|
+
bendingShrinkHorizontal: this._cloneInterpolatorScalar(config.curves.bendingShrinkHorizontal),
|
|
1042
|
+
bendingStretchHorizontal: this._cloneInterpolatorScalar(config.curves.bendingStretchHorizontal),
|
|
1043
|
+
fakeWavePower: this._cloneInterpolatorScalar(config.curves.fakeWavePower),
|
|
1044
|
+
fakeWaveFreq: this._cloneInterpolatorScalar(config.curves.fakeWaveFreq)
|
|
1045
|
+
};
|
|
1046
|
+
return {
|
|
1047
|
+
gravity: config.gravity.clone(),
|
|
1048
|
+
windForce: config.windForce.clone(),
|
|
1049
|
+
relaxation: config.relaxation,
|
|
1050
|
+
subSteps: config.subSteps,
|
|
1051
|
+
rootSlideLimit: config.rootSlideLimit,
|
|
1052
|
+
rootRotateLimit: config.rootRotateLimit,
|
|
1053
|
+
constraintShrinkLimit: config.constraintShrinkLimit,
|
|
1054
|
+
blendRatio: config.blendRatio,
|
|
1055
|
+
stabilizationFrameRate: config.stabilizationFrameRate,
|
|
1056
|
+
isFakeWave: config.isFakeWave,
|
|
1057
|
+
fakeWaveSpeed: config.fakeWaveSpeed,
|
|
1058
|
+
fakeWavePower: config.fakeWavePower,
|
|
1059
|
+
enableSurfaceCollision: config.enableSurfaceCollision,
|
|
1060
|
+
enableBroadPhase: config.enableBroadPhase,
|
|
1061
|
+
preserveTwist: config.preserveTwist,
|
|
1062
|
+
angleLimitConfig: {
|
|
1063
|
+
angleLimit: config.angleLimitConfig.angleLimit,
|
|
1064
|
+
limitFromRoot: config.angleLimitConfig.limitFromRoot
|
|
1065
|
+
},
|
|
1066
|
+
curves,
|
|
1067
|
+
constraintOptions: {
|
|
1068
|
+
structuralVertical: config.constraintOptions.structuralVertical,
|
|
1069
|
+
structuralHorizontal: config.constraintOptions.structuralHorizontal,
|
|
1070
|
+
shear: config.constraintOptions.shear,
|
|
1071
|
+
bendingVertical: config.constraintOptions.bendingVertical,
|
|
1072
|
+
bendingHorizontal: config.constraintOptions.bendingHorizontal,
|
|
1073
|
+
isLoop: config.constraintOptions.isLoop,
|
|
1074
|
+
collideStructuralVertical: config.constraintOptions.collideStructuralVertical,
|
|
1075
|
+
collideStructuralHorizontal: config.constraintOptions.collideStructuralHorizontal,
|
|
1076
|
+
collideShear: config.constraintOptions.collideShear,
|
|
1077
|
+
enableSurfaceCollision: config.constraintOptions.enableSurfaceCollision
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
_cloneInterpolatorScalar(curve) {
|
|
1082
|
+
return new InterpolatorScalar(curve.mode, new Float32Array(curve.inputs), new Float32Array(curve.outputs));
|
|
1083
|
+
}
|
|
1084
|
+
_sanitizeControllerConfig(config) {
|
|
1085
|
+
config.relaxation = Math.max(0, Math.trunc(config.relaxation));
|
|
1086
|
+
config.subSteps = Math.max(1, Math.trunc(config.subSteps));
|
|
1087
|
+
config.constraintShrinkLimit = Math.max(0, config.constraintShrinkLimit);
|
|
1088
|
+
config.blendRatio = clamp01(config.blendRatio);
|
|
1089
|
+
return config;
|
|
1090
|
+
}
|
|
744
1091
|
}
|
|
745
1092
|
|
|
746
1093
|
export { JointDynamicsSystemController };
|