@zephyr3d/editor 0.3.7 → 0.3.8
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/assets/{index-ySiLtSxz.js → index-BZ1L8ggE.js} +43 -3
- package/dist/assistant/zephyr-types-index.json +13230 -9488
- package/dist/images/icon1024.png +0 -0
- package/dist/index.html +1 -1
- package/dist/modules/zephyr3d_backend-webgl.js +2 -0
- package/dist/modules/zephyr3d_backend-webgl.js.map +1 -1
- package/dist/modules/zephyr3d_backend-webgpu.js +457 -16
- package/dist/modules/zephyr3d_backend-webgpu.js.map +1 -1
- package/dist/modules/zephyr3d_device.js +27 -0
- package/dist/modules/zephyr3d_device.js.map +1 -1
- package/dist/modules/zephyr3d_loaders.js +208 -1
- package/dist/modules/zephyr3d_loaders.js.map +1 -1
- package/dist/modules/zephyr3d_scene.js +774 -80
- package/dist/modules/zephyr3d_scene.js.map +1 -1
- package/dist/vendor/zephyr3d/backend-webgl/dist/capabilities_webgl.js +2 -0
- package/dist/vendor/zephyr3d/backend-webgl/dist/capabilities_webgl.js.map +1 -1
- package/dist/vendor/zephyr3d/backend-webgpu/dist/capabilities_webgpu.js +2 -0
- package/dist/vendor/zephyr3d/backend-webgpu/dist/capabilities_webgpu.js.map +1 -1
- package/dist/vendor/zephyr3d/backend-webgpu/dist/commandqueue.js +55 -10
- package/dist/vendor/zephyr3d/backend-webgpu/dist/commandqueue.js.map +1 -1
- package/dist/vendor/zephyr3d/backend-webgpu/dist/computepass_webgpu.js +4 -0
- package/dist/vendor/zephyr3d/backend-webgpu/dist/computepass_webgpu.js.map +1 -1
- package/dist/vendor/zephyr3d/backend-webgpu/dist/device.js +44 -1
- package/dist/vendor/zephyr3d/backend-webgpu/dist/device.js.map +1 -1
- package/dist/vendor/zephyr3d/backend-webgpu/dist/renderpass_webgpu.js +58 -5
- package/dist/vendor/zephyr3d/backend-webgpu/dist/renderpass_webgpu.js.map +1 -1
- package/dist/vendor/zephyr3d/backend-webgpu/dist/timestamp_query.js +297 -0
- package/dist/vendor/zephyr3d/backend-webgpu/dist/timestamp_query.js.map +1 -0
- package/dist/vendor/zephyr3d/device/dist/base_types.js.map +1 -1
- package/dist/vendor/zephyr3d/device/dist/device.js +27 -0
- package/dist/vendor/zephyr3d/device/dist/device.js.map +1 -1
- package/dist/vendor/zephyr3d/device/dist/index.d.ts +81 -1
- package/dist/vendor/zephyr3d/loaders/dist/gltf/gltf_importer.js +208 -1
- package/dist/vendor/zephyr3d/loaders/dist/gltf/gltf_importer.js.map +1 -1
- package/dist/vendor/zephyr3d/loaders/dist/index.d.ts +8 -0
- package/dist/vendor/zephyr3d/scene/dist/animation/animationset.js +334 -63
- package/dist/vendor/zephyr3d/scene/dist/animation/animationset.js.map +1 -1
- package/dist/vendor/zephyr3d/scene/dist/animation/morphtargetgrouptrack.js +66 -0
- package/dist/vendor/zephyr3d/scene/dist/animation/morphtargetgrouptrack.js.map +1 -0
- package/dist/vendor/zephyr3d/scene/dist/asset/model.js +9 -0
- package/dist/vendor/zephyr3d/scene/dist/asset/model.js.map +1 -1
- package/dist/vendor/zephyr3d/scene/dist/index.d.ts +260 -4
- package/dist/vendor/zephyr3d/scene/dist/index.js +7 -0
- package/dist/vendor/zephyr3d/scene/dist/index.js.map +1 -1
- package/dist/vendor/zephyr3d/scene/dist/posteffect/sao.js +1 -1
- package/dist/vendor/zephyr3d/scene/dist/posteffect/sao.js.map +1 -1
- package/dist/vendor/zephyr3d/scene/dist/render/rendergraph/executor.js +270 -1
- package/dist/vendor/zephyr3d/scene/dist/render/rendergraph/executor.js.map +1 -1
- package/dist/vendor/zephyr3d/scene/dist/render/rendergraph/forward_plus_builder.js +19 -1
- package/dist/vendor/zephyr3d/scene/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
- package/dist/vendor/zephyr3d/scene/dist/render/rendergraph/types.js.map +1 -1
- package/dist/vendor/zephyr3d/scene/dist/scene/scene.js +1 -0
- package/dist/vendor/zephyr3d/scene/dist/scene/scene.js.map +1 -1
- package/dist/vendor/zephyr3d/scene/dist/utility/serialization/manager.js +2 -1
- package/dist/vendor/zephyr3d/scene/dist/utility/serialization/manager.js.map +1 -1
- package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/animation.js +70 -1
- package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/animation.js.map +1 -1
- package/dist/vendor/zephyr3d/scene/dist/utility/serialization/scene/camera.js.map +1 -1
- package/package.json +6 -6
- package/dist/vendor/zephyr3d/scene/dist/animation/joint_dynamics/convex_collider.js +0 -320
- package/dist/vendor/zephyr3d/scene/dist/animation/joint_dynamics/convex_collider.js.map +0 -1
|
@@ -44,10 +44,18 @@ declare class GLTFImporter extends AbstractModelImporter {
|
|
|
44
44
|
private _numberKey;
|
|
45
45
|
private _toJointDynamicsCollider;
|
|
46
46
|
private _toJointDynamicsFlatPlane;
|
|
47
|
+
private _loadVRMHumanoidSkeletonMappings;
|
|
48
|
+
private _getVRMC1HumanoidMapping;
|
|
49
|
+
private _getVRMC0HumanoidMapping;
|
|
47
50
|
private _setAssetSkeletonHumanoidMapping;
|
|
48
51
|
private _getVRMAHumanoidMapping;
|
|
52
|
+
private _getVRMC0HumanoidMappingFromBones;
|
|
53
|
+
private _filterHumanoidMappingToSkeleton;
|
|
49
54
|
private _getVRMAHumanBoneNode;
|
|
50
55
|
private _getVRMAHumanoidNodes;
|
|
56
|
+
private _getVRMAExpressionMapping;
|
|
57
|
+
private _addVRMAExpressionMapping;
|
|
58
|
+
private _createVRMAExpressionInterpolator;
|
|
51
59
|
private _findCommonRoot;
|
|
52
60
|
private _sortSkeletonJoints;
|
|
53
61
|
private _shouldGenerateMToonOutlineNormals;
|
|
@@ -4,6 +4,7 @@ import { NodeRotationTrack } from './rotationtrack.js';
|
|
|
4
4
|
import { NodeEulerRotationTrack } from './eulerrotationtrack.js';
|
|
5
5
|
import { NodeTranslationTrack } from './translationtrack.js';
|
|
6
6
|
import { NodeScaleTrack } from './scaletrack.js';
|
|
7
|
+
import { MorphTargetGroupTrack } from './morphtargetgrouptrack.js';
|
|
7
8
|
import { HumanoidBodyRig } from './skeleton.js';
|
|
8
9
|
import { createSkeletalMaskedAnimationClip } from './animationmask.js';
|
|
9
10
|
|
|
@@ -232,7 +233,7 @@ function cloneInterpolator(src) {
|
|
|
232
233
|
...src.outputs
|
|
233
234
|
]);
|
|
234
235
|
}
|
|
235
|
-
function createJointRetargetRemap(srcSkeleton, dstSkeleton, srcJoint, dstJoint, translationRotation, translationScale, translationAxisLocks) {
|
|
236
|
+
function createJointRetargetRemap(srcSkeleton, dstSkeleton, srcJoint, dstJoint, translationRotation, translationScale, translationCorrection, translationAxisLocks, rotationCorrection) {
|
|
236
237
|
const si = srcSkeleton.joints.indexOf(srcJoint);
|
|
237
238
|
const di = dstSkeleton.joints.indexOf(dstJoint);
|
|
238
239
|
const srcBindPose = srcSkeleton.bindPose[si];
|
|
@@ -245,24 +246,28 @@ function createJointRetargetRemap(srcSkeleton, dstSkeleton, srcJoint, dstJoint,
|
|
|
245
246
|
srcNode: srcJoint,
|
|
246
247
|
srcBindRotInv: Quaternion.inverse(srcBindPose.rotation),
|
|
247
248
|
dstBindRot: dstBindPose.rotation.clone(),
|
|
249
|
+
rotationCorrection,
|
|
248
250
|
srcBindPos: srcBindPose.position.clone(),
|
|
249
251
|
dstBindPos: dstBindPose.position.clone(),
|
|
250
|
-
translationScale: (srcLen > 1e-6 ? dstLen / srcLen : 1),
|
|
252
|
+
translationScale: translationScale ?? (srcLen > 1e-6 ? dstLen / srcLen : 1),
|
|
251
253
|
translationRotation,
|
|
254
|
+
translationCorrection,
|
|
252
255
|
translationAxisLocks
|
|
253
256
|
};
|
|
254
257
|
}
|
|
255
|
-
function createTranslationRetargetRemap(srcNode, dstNode, srcBindPos, dstBindPos, dstJointIndex, translationScale, translationRotation, translationAxisLocks) {
|
|
258
|
+
function createTranslationRetargetRemap(srcNode, dstNode, srcBindPos, dstBindPos, dstJointIndex, translationScale, translationRotation, translationCorrection, translationAxisLocks, rotationCorrection) {
|
|
256
259
|
return {
|
|
257
260
|
dstNode,
|
|
258
261
|
dstJointIndex,
|
|
259
262
|
srcNode,
|
|
260
263
|
srcBindRotInv: Quaternion.identity(),
|
|
261
264
|
dstBindRot: Quaternion.identity(),
|
|
265
|
+
rotationCorrection,
|
|
262
266
|
srcBindPos: srcBindPos.clone(),
|
|
263
267
|
dstBindPos: dstBindPos.clone(),
|
|
264
268
|
translationScale,
|
|
265
269
|
translationRotation,
|
|
270
|
+
translationCorrection,
|
|
266
271
|
translationAxisLocks
|
|
267
272
|
};
|
|
268
273
|
}
|
|
@@ -270,6 +275,151 @@ function getBindPosition(skeleton, joint) {
|
|
|
270
275
|
const index = skeleton.joints.indexOf(joint);
|
|
271
276
|
return index >= 0 ? skeleton.bindPose[index].position : null;
|
|
272
277
|
}
|
|
278
|
+
function getSkeletonLocalBindTransform(skeleton, node, jointSet, cache) {
|
|
279
|
+
let transform = cache.get(node);
|
|
280
|
+
if (!transform) {
|
|
281
|
+
const bindPose = getRigBindPoseForNode(skeleton, node);
|
|
282
|
+
const position = bindPose.position.clone();
|
|
283
|
+
const rotation = bindPose.rotation.clone();
|
|
284
|
+
const parent = node.parent;
|
|
285
|
+
if (parent && jointSet.has(parent)) {
|
|
286
|
+
const parentTransform = getSkeletonLocalBindTransform(skeleton, parent, jointSet, cache);
|
|
287
|
+
parentTransform.rotation.transform(position, position);
|
|
288
|
+
position.addBy(parentTransform.position);
|
|
289
|
+
Quaternion.multiply(parentTransform.rotation, rotation, rotation);
|
|
290
|
+
}
|
|
291
|
+
transform = {
|
|
292
|
+
position,
|
|
293
|
+
rotation
|
|
294
|
+
};
|
|
295
|
+
cache.set(node, transform);
|
|
296
|
+
}
|
|
297
|
+
return transform;
|
|
298
|
+
}
|
|
299
|
+
function getHumanoidLateralXSign(skeleton) {
|
|
300
|
+
const mapping = skeleton.humanoidJointMapping;
|
|
301
|
+
if (!mapping) {
|
|
302
|
+
return 0;
|
|
303
|
+
}
|
|
304
|
+
const pairs = [
|
|
305
|
+
[
|
|
306
|
+
HumanoidBodyRig.LeftShoulder,
|
|
307
|
+
HumanoidBodyRig.RightShoulder
|
|
308
|
+
],
|
|
309
|
+
[
|
|
310
|
+
HumanoidBodyRig.LeftUpperArm,
|
|
311
|
+
HumanoidBodyRig.RightUpperArm
|
|
312
|
+
],
|
|
313
|
+
[
|
|
314
|
+
HumanoidBodyRig.LeftLowerArm,
|
|
315
|
+
HumanoidBodyRig.RightLowerArm
|
|
316
|
+
],
|
|
317
|
+
[
|
|
318
|
+
HumanoidBodyRig.LeftHand,
|
|
319
|
+
HumanoidBodyRig.RightHand
|
|
320
|
+
],
|
|
321
|
+
[
|
|
322
|
+
HumanoidBodyRig.LeftUpperLeg,
|
|
323
|
+
HumanoidBodyRig.RightUpperLeg
|
|
324
|
+
],
|
|
325
|
+
[
|
|
326
|
+
HumanoidBodyRig.LeftLowerLeg,
|
|
327
|
+
HumanoidBodyRig.RightLowerLeg
|
|
328
|
+
],
|
|
329
|
+
[
|
|
330
|
+
HumanoidBodyRig.LeftFoot,
|
|
331
|
+
HumanoidBodyRig.RightFoot
|
|
332
|
+
],
|
|
333
|
+
[
|
|
334
|
+
HumanoidBodyRig.LeftToes,
|
|
335
|
+
HumanoidBodyRig.RightToes
|
|
336
|
+
]
|
|
337
|
+
];
|
|
338
|
+
const jointSet = new Set(skeleton.joints);
|
|
339
|
+
const cache = new Map();
|
|
340
|
+
let score = 0;
|
|
341
|
+
let weight = 0;
|
|
342
|
+
for (const [leftKey, rightKey] of pairs){
|
|
343
|
+
const left = mapping.body[leftKey];
|
|
344
|
+
const right = mapping.body[rightKey];
|
|
345
|
+
if (!left || !right || !jointSet.has(left) || !jointSet.has(right)) {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
const dx = getSkeletonLocalBindTransform(skeleton, left, jointSet, cache).position.x - getSkeletonLocalBindTransform(skeleton, right, jointSet, cache).position.x;
|
|
349
|
+
if (Math.abs(dx) > 1e-5) {
|
|
350
|
+
score += dx;
|
|
351
|
+
weight++;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (weight === 0 || Math.abs(score) < 1e-5) {
|
|
355
|
+
return 0;
|
|
356
|
+
}
|
|
357
|
+
return score > 0 ? 1 : -1;
|
|
358
|
+
}
|
|
359
|
+
function getHumanoidForwardZSign(skeleton) {
|
|
360
|
+
const mapping = skeleton.humanoidJointMapping;
|
|
361
|
+
if (!mapping) {
|
|
362
|
+
return 0;
|
|
363
|
+
}
|
|
364
|
+
const pairs = [
|
|
365
|
+
[
|
|
366
|
+
HumanoidBodyRig.LeftFoot,
|
|
367
|
+
HumanoidBodyRig.LeftToes
|
|
368
|
+
],
|
|
369
|
+
[
|
|
370
|
+
HumanoidBodyRig.RightFoot,
|
|
371
|
+
HumanoidBodyRig.RightToes
|
|
372
|
+
]
|
|
373
|
+
];
|
|
374
|
+
const jointSet = new Set(skeleton.joints);
|
|
375
|
+
const cache = new Map();
|
|
376
|
+
let score = 0;
|
|
377
|
+
let weight = 0;
|
|
378
|
+
for (const [footKey, toesKey] of pairs){
|
|
379
|
+
const foot = mapping.body[footKey];
|
|
380
|
+
const toes = mapping.body[toesKey];
|
|
381
|
+
if (!foot || !toes || !jointSet.has(foot) || !jointSet.has(toes)) {
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
const dz = getSkeletonLocalBindTransform(skeleton, toes, jointSet, cache).position.z - getSkeletonLocalBindTransform(skeleton, foot, jointSet, cache).position.z;
|
|
385
|
+
if (Math.abs(dz) > 1e-5) {
|
|
386
|
+
score += dz;
|
|
387
|
+
weight++;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if (weight === 0 || Math.abs(score) < 1e-5) {
|
|
391
|
+
return 0;
|
|
392
|
+
}
|
|
393
|
+
return score > 0 ? 1 : -1;
|
|
394
|
+
}
|
|
395
|
+
function getHumanoidSignFromSkeletons(skeletons, getSign) {
|
|
396
|
+
let score = 0;
|
|
397
|
+
for (const skeleton of skeletons){
|
|
398
|
+
score += getSign(skeleton);
|
|
399
|
+
}
|
|
400
|
+
return score > 0 ? 1 : score < 0 ? -1 : 0;
|
|
401
|
+
}
|
|
402
|
+
function getHumanoidRotationCorrection(srcSkeleton, dstSkeleton, srcSignSkeletons = [
|
|
403
|
+
srcSkeleton
|
|
404
|
+
], dstSignSkeletons = [
|
|
405
|
+
dstSkeleton
|
|
406
|
+
]) {
|
|
407
|
+
const srcLateralXSign = getHumanoidLateralXSign(srcSkeleton) || getHumanoidSignFromSkeletons(srcSignSkeletons, getHumanoidLateralXSign);
|
|
408
|
+
const dstLateralXSign = getHumanoidLateralXSign(dstSkeleton) || getHumanoidSignFromSkeletons(dstSignSkeletons, getHumanoidLateralXSign);
|
|
409
|
+
const srcForwardZSign = getHumanoidForwardZSign(srcSkeleton) || getHumanoidSignFromSkeletons(srcSignSkeletons, getHumanoidForwardZSign);
|
|
410
|
+
const dstForwardZSign = getHumanoidForwardZSign(dstSkeleton) || getHumanoidSignFromSkeletons(dstSignSkeletons, getHumanoidForwardZSign);
|
|
411
|
+
const axisXSign = srcLateralXSign && dstLateralXSign && srcLateralXSign !== dstLateralXSign ? -1 : 1;
|
|
412
|
+
const axisZSign = srcForwardZSign && dstForwardZSign && srcForwardZSign !== dstForwardZSign ? -1 : 1;
|
|
413
|
+
if (axisXSign === 1 && axisZSign === 1) {
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
const determinant = axisXSign * axisZSign;
|
|
417
|
+
return {
|
|
418
|
+
x: determinant * axisXSign,
|
|
419
|
+
y: determinant,
|
|
420
|
+
z: determinant * axisZSign
|
|
421
|
+
};
|
|
422
|
+
}
|
|
273
423
|
function getRigBindPoseForNode(skeleton, node) {
|
|
274
424
|
return skeleton.getBindPoseForJoint(node) ?? (node === skeleton.rootJoint ? skeleton.rootBindPose : {
|
|
275
425
|
position: node.position,
|
|
@@ -313,6 +463,35 @@ function getHumanoidRootMotionScale(srcSkeleton, dstSkeleton) {
|
|
|
313
463
|
function findTranslationTrack(tracks) {
|
|
314
464
|
return tracks?.find((track)=>track instanceof NodeTranslationTrack) ?? null;
|
|
315
465
|
}
|
|
466
|
+
function findAncestorTranslationTrack(clip, node, modelRoot) {
|
|
467
|
+
let current = node.parent;
|
|
468
|
+
while(current){
|
|
469
|
+
const track = findTranslationTrack(clip.tracks.get(current));
|
|
470
|
+
if (track) {
|
|
471
|
+
return {
|
|
472
|
+
node: current,
|
|
473
|
+
track
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
if (current === modelRoot) {
|
|
477
|
+
break;
|
|
478
|
+
}
|
|
479
|
+
current = current.parent;
|
|
480
|
+
}
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
function copyMorphTargetGroupTracks(sourceClip, targetClip, target) {
|
|
484
|
+
for (const tracks of sourceClip.tracks.values()){
|
|
485
|
+
for (const track of tracks){
|
|
486
|
+
if (track instanceof MorphTargetGroupTrack) {
|
|
487
|
+
const cloned = track.clone();
|
|
488
|
+
cloned.name = track.name;
|
|
489
|
+
cloned.target = target.persistentId;
|
|
490
|
+
targetClip.addTrack(target, cloned);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
316
495
|
function applyTranslationAxisLocks(value, bindValue, locks) {
|
|
317
496
|
if (locks?.x) {
|
|
318
497
|
value.x = bindValue.x;
|
|
@@ -338,13 +517,25 @@ function applyTranslationTangentAxisLocks(value, locks) {
|
|
|
338
517
|
function retargetRotation(qSrcAnim, remap, out) {
|
|
339
518
|
Quaternion.multiply(remap.srcBindRotInv, qSrcAnim, out);
|
|
340
519
|
Quaternion.multiply(remap.dstBindRot, out, out);
|
|
520
|
+
if (remap.rotationCorrection) {
|
|
521
|
+
applyHumanoidRotationCorrection(out, remap.rotationCorrection, out);
|
|
522
|
+
}
|
|
341
523
|
return out.inplaceNormalize();
|
|
342
524
|
}
|
|
343
525
|
function retargetRotationTangent(qSrcTangent, remap, out) {
|
|
344
526
|
Quaternion.multiply(remap.srcBindRotInv, qSrcTangent, out);
|
|
345
527
|
Quaternion.multiply(remap.dstBindRot, out, out);
|
|
528
|
+
if (remap.rotationCorrection) {
|
|
529
|
+
applyHumanoidRotationCorrection(out, remap.rotationCorrection, out);
|
|
530
|
+
}
|
|
346
531
|
return out;
|
|
347
532
|
}
|
|
533
|
+
function applyHumanoidRotationCorrection(q, correction, out) {
|
|
534
|
+
return out.setXYZW(q.x * correction.x, q.y * correction.y, q.z * correction.z, q.w);
|
|
535
|
+
}
|
|
536
|
+
function applyHumanoidTranslationCorrection(value, correction, out) {
|
|
537
|
+
return out.setXYZ(value.x * correction.x, value.y * correction.y, value.z * correction.z);
|
|
538
|
+
}
|
|
348
539
|
function retargetTranslationValue(srcValue, remap, out) {
|
|
349
540
|
out.setXYZ(srcValue.x, srcValue.y, srcValue.z);
|
|
350
541
|
out.subBy(remap.srcBindPos);
|
|
@@ -352,6 +543,9 @@ function retargetTranslationValue(srcValue, remap, out) {
|
|
|
352
543
|
if (remap.translationRotation) {
|
|
353
544
|
remap.translationRotation.transform(out, out);
|
|
354
545
|
}
|
|
546
|
+
if (remap.translationCorrection) {
|
|
547
|
+
applyHumanoidTranslationCorrection(out, remap.translationCorrection, out);
|
|
548
|
+
}
|
|
355
549
|
out.addBy(remap.dstBindPos);
|
|
356
550
|
applyTranslationAxisLocks(out, remap.dstBindPos, remap.translationAxisLocks);
|
|
357
551
|
return out;
|
|
@@ -362,6 +556,9 @@ function retargetTranslationTangent(srcValue, remap, out) {
|
|
|
362
556
|
if (remap.translationRotation) {
|
|
363
557
|
remap.translationRotation.transform(out, out);
|
|
364
558
|
}
|
|
559
|
+
if (remap.translationCorrection) {
|
|
560
|
+
applyHumanoidTranslationCorrection(out, remap.translationCorrection, out);
|
|
561
|
+
}
|
|
365
562
|
applyTranslationTangentAxisLocks(out, remap.translationAxisLocks);
|
|
366
563
|
return out;
|
|
367
564
|
}
|
|
@@ -461,7 +658,7 @@ function sampleRotationTrack(track, time, fallback, out) {
|
|
|
461
658
|
out.set(state);
|
|
462
659
|
return out;
|
|
463
660
|
}
|
|
464
|
-
function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRootRotation, dstRootRotation, dstClip, remaps) {
|
|
661
|
+
function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRootRotation, dstRootRotation, dstClip, remaps, rotationCorrection) {
|
|
465
662
|
const rotationTracksByRemap = new Map();
|
|
466
663
|
const times = new Set([
|
|
467
664
|
0,
|
|
@@ -498,7 +695,10 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
|
|
|
498
695
|
const outputsByRemap = new Map();
|
|
499
696
|
const tmpLocalRot = new Quaternion();
|
|
500
697
|
const tmpWorldDelta = new Quaternion();
|
|
698
|
+
const tmpRootDelta = new Quaternion();
|
|
501
699
|
const tmpParentInv = new Quaternion();
|
|
700
|
+
const srcRootRotationInv = Quaternion.inverse(srcRootRotation);
|
|
701
|
+
const dstRootRotationInv = Quaternion.inverse(dstRootRotation);
|
|
502
702
|
for (const remap of remaps){
|
|
503
703
|
outputsByRemap.set(remap, new Float32Array(inputs.length * 4));
|
|
504
704
|
}
|
|
@@ -555,6 +755,13 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
|
|
|
555
755
|
const srcBindWorldRot = getSrcBindWorldRot(remap.srcNode);
|
|
556
756
|
const srcAnimWorldRot = getSrcAnimWorldRot(remap.srcNode, time);
|
|
557
757
|
Quaternion.multiply(srcAnimWorldRot, Quaternion.inverse(srcBindWorldRot, tmpWorldDelta), tmpWorldDelta);
|
|
758
|
+
if (rotationCorrection) {
|
|
759
|
+
Quaternion.multiply(srcRootRotationInv, tmpWorldDelta, tmpRootDelta);
|
|
760
|
+
Quaternion.multiply(tmpRootDelta, srcRootRotation, tmpRootDelta);
|
|
761
|
+
applyHumanoidRotationCorrection(tmpRootDelta, rotationCorrection, tmpRootDelta);
|
|
762
|
+
Quaternion.multiply(dstRootRotation, tmpRootDelta, tmpWorldDelta);
|
|
763
|
+
Quaternion.multiply(tmpWorldDelta, dstRootRotationInv, tmpWorldDelta);
|
|
764
|
+
}
|
|
558
765
|
Quaternion.multiply(tmpWorldDelta, getDstBindWorldRot(remap.dstNode), rot);
|
|
559
766
|
return rot;
|
|
560
767
|
}
|
|
@@ -1449,8 +1656,7 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
|
|
|
1449
1656
|
console.error(`copyHumanoidAnimationFrom: source skeleton does not have a humanoid joint mapping`);
|
|
1450
1657
|
return null;
|
|
1451
1658
|
}
|
|
1452
|
-
const
|
|
1453
|
-
const jointRemapBySrcNode = new Map();
|
|
1659
|
+
const jointRemapsBySrcNode = new Map();
|
|
1454
1660
|
// Find a destination skeleton that has a humanoid mapping and share at least the body rig keys
|
|
1455
1661
|
let srcJointsFiltered = [];
|
|
1456
1662
|
let dstJointsFiltered = [];
|
|
@@ -1463,38 +1669,34 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
|
|
|
1463
1669
|
if (!dstHumanoidMapping) {
|
|
1464
1670
|
return false;
|
|
1465
1671
|
}
|
|
1672
|
+
const srcHips = srcHumanoidMapping.body[HumanoidBodyRig.Hips];
|
|
1673
|
+
const dstHips = dstHumanoidMapping.body[HumanoidBodyRig.Hips];
|
|
1674
|
+
if (!srcHips || !dstHips || !srcSkeleton.joints.includes(srcHips) || !sk.joints.includes(dstHips)) {
|
|
1675
|
+
return false;
|
|
1676
|
+
}
|
|
1466
1677
|
// Collect matched (srcJoint, dstJoint) pairs via shared humanoid rig keys
|
|
1467
1678
|
const srcMatched = [];
|
|
1468
1679
|
const dstMatched = [];
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
const srcJoint = srcHumanoidMapping.body[key];
|
|
1472
|
-
const dstJoint = dstHumanoidMapping.body[key];
|
|
1473
|
-
if (srcJoint && dstJoint) {
|
|
1680
|
+
const addMatch = (srcJoint, dstJoint)=>{
|
|
1681
|
+
if (srcJoint && dstJoint && srcSkeleton.joints.includes(srcJoint) && sk.joints.includes(dstJoint)) {
|
|
1474
1682
|
srcMatched.push(srcJoint);
|
|
1475
1683
|
dstMatched.push(dstJoint);
|
|
1476
1684
|
}
|
|
1685
|
+
};
|
|
1686
|
+
// Match body rig joints
|
|
1687
|
+
for (const key of Object.keys(srcHumanoidMapping.body)){
|
|
1688
|
+
addMatch(srcHumanoidMapping.body[key], dstHumanoidMapping.body[key]);
|
|
1477
1689
|
}
|
|
1478
1690
|
// Match left hand rig joints only when both sides define them; skip silently if either is absent
|
|
1479
1691
|
if (srcHumanoidMapping.leftHand && dstHumanoidMapping.leftHand) {
|
|
1480
1692
|
for (const key of Object.keys(srcHumanoidMapping.leftHand)){
|
|
1481
|
-
|
|
1482
|
-
const dstJoint = dstHumanoidMapping.leftHand[key];
|
|
1483
|
-
if (srcJoint && dstJoint) {
|
|
1484
|
-
srcMatched.push(srcJoint);
|
|
1485
|
-
dstMatched.push(dstJoint);
|
|
1486
|
-
}
|
|
1693
|
+
addMatch(srcHumanoidMapping.leftHand[key], dstHumanoidMapping.leftHand[key]);
|
|
1487
1694
|
}
|
|
1488
1695
|
}
|
|
1489
1696
|
// Match right hand rig joints only when both sides define them; skip silently if either is absent
|
|
1490
1697
|
if (srcHumanoidMapping.rightHand && dstHumanoidMapping.rightHand) {
|
|
1491
1698
|
for (const key of Object.keys(srcHumanoidMapping.rightHand)){
|
|
1492
|
-
|
|
1493
|
-
const dstJoint = dstHumanoidMapping.rightHand[key];
|
|
1494
|
-
if (srcJoint && dstJoint) {
|
|
1495
|
-
srcMatched.push(srcJoint);
|
|
1496
|
-
dstMatched.push(dstJoint);
|
|
1497
|
-
}
|
|
1699
|
+
addMatch(srcHumanoidMapping.rightHand[key], dstHumanoidMapping.rightHand[key]);
|
|
1498
1700
|
}
|
|
1499
1701
|
}
|
|
1500
1702
|
if (srcMatched.length === 0) {
|
|
@@ -1532,28 +1734,69 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
|
|
|
1532
1734
|
const srcRootRot = computeParentChainRotation(srcRootNode, sourceSet.model, srcSkeleton);
|
|
1533
1735
|
const dstRootRot = computeParentChainRotation(dstRootNode, this._model, dstSkeleton);
|
|
1534
1736
|
const srcRootTranslationTrack = findTranslationTrack(sourceClip.tracks.get(srcRootNode));
|
|
1535
|
-
const
|
|
1536
|
-
const
|
|
1537
|
-
const
|
|
1737
|
+
const srcAncestorTranslationTrackInfo = !srcRootTranslationTrack ? findAncestorTranslationTrack(sourceClip, srcRootNode, sourceSet.model) : null;
|
|
1738
|
+
const srcFallbackHipsTranslationTrack = !srcRootTranslationTrack && !srcAncestorTranslationTrackInfo && srcRootNode !== srcHipsNode ? findTranslationTrack(sourceClip.tracks.get(srcHipsNode)) : null;
|
|
1739
|
+
const srcMotionTrack = srcRootTranslationTrack ?? srcAncestorTranslationTrackInfo?.track ?? srcFallbackHipsTranslationTrack;
|
|
1740
|
+
const srcMotionNode = srcRootTranslationTrack ? srcRootNode : srcAncestorTranslationTrackInfo ? srcAncestorTranslationTrackInfo.node : srcFallbackHipsTranslationTrack ? srcHipsNode : null;
|
|
1538
1741
|
const srcMotionParentRot = srcMotionNode ? computeParentChainRotation(srcMotionNode, sourceSet.model, srcSkeleton) : srcRootRot;
|
|
1539
1742
|
const rootTranslationRotation = Quaternion.multiply(Quaternion.inverse(dstRootRot), srcMotionParentRot);
|
|
1540
1743
|
const rootTranslationScale = rootMotion === 'scaled' ? typeof options.rootMotionScale === 'number' ? options.rootMotionScale : options.rootMotionScale === 'none' ? 1 : getHumanoidRootMotionScale(srcSkeleton, dstSkeleton) : 1;
|
|
1541
1744
|
const jointRemaps = [];
|
|
1542
|
-
const
|
|
1543
|
-
|
|
1745
|
+
const jointRemapsByDstSkeleton = new Map([
|
|
1746
|
+
[
|
|
1747
|
+
dstSkeleton,
|
|
1748
|
+
jointRemaps
|
|
1749
|
+
]
|
|
1750
|
+
]);
|
|
1751
|
+
const srcSignSkeletons = sourceSet._rigs.map((ref)=>ref.get()).filter((sk)=>!!sk);
|
|
1752
|
+
const dstSignSkeletons = this._rigs.map((ref)=>ref.get()).filter((sk)=>!!sk);
|
|
1753
|
+
const humanoidRotationCorrection = getHumanoidRotationCorrection(srcSkeleton, dstSkeleton, srcSignSkeletons, dstSignSkeletons);
|
|
1754
|
+
const addJointRemap = (targetSkeleton, srcJoint, dstJoint, applyRotationCorrection = true)=>{
|
|
1755
|
+
if (!srcJoint || !dstJoint || !srcSkeleton.joints.includes(srcJoint) || !targetSkeleton.joints.includes(dstJoint)) {
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1758
|
+
const remap = createJointRetargetRemap(srcSkeleton, targetSkeleton, srcJoint, dstJoint, undefined, undefined, humanoidRotationCorrection ?? undefined, undefined, applyRotationCorrection ? humanoidRotationCorrection ?? undefined : undefined);
|
|
1759
|
+
let targetRemaps = jointRemapsByDstSkeleton.get(targetSkeleton);
|
|
1760
|
+
if (!targetRemaps) {
|
|
1761
|
+
targetRemaps = [];
|
|
1762
|
+
jointRemapsByDstSkeleton.set(targetSkeleton, targetRemaps);
|
|
1763
|
+
}
|
|
1764
|
+
targetRemaps.push(remap);
|
|
1765
|
+
let srcRemaps = jointRemapsBySrcNode.get(srcJoint);
|
|
1766
|
+
if (!srcRemaps) {
|
|
1767
|
+
srcRemaps = [];
|
|
1768
|
+
jointRemapsBySrcNode.set(srcJoint, srcRemaps);
|
|
1769
|
+
}
|
|
1770
|
+
srcRemaps.push(remap);
|
|
1771
|
+
};
|
|
1772
|
+
const addHumanoidMappingRemaps = (targetSkeleton)=>{
|
|
1773
|
+
const targetMapping = targetSkeleton.humanoidJointMapping;
|
|
1774
|
+
if (!targetMapping) {
|
|
1775
|
+
return;
|
|
1776
|
+
}
|
|
1777
|
+
const applyRotationCorrection = targetSkeleton === dstSkeleton;
|
|
1778
|
+
for (const key of Object.keys(srcHumanoidMapping.body)){
|
|
1779
|
+
addJointRemap(targetSkeleton, srcHumanoidMapping.body[key], targetMapping.body[key], applyRotationCorrection);
|
|
1780
|
+
}
|
|
1781
|
+
if (srcHumanoidMapping.leftHand && targetMapping.leftHand) {
|
|
1782
|
+
for (const key of Object.keys(srcHumanoidMapping.leftHand)){
|
|
1783
|
+
addJointRemap(targetSkeleton, srcHumanoidMapping.leftHand[key], targetMapping.leftHand[key], applyRotationCorrection);
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
if (srcHumanoidMapping.rightHand && targetMapping.rightHand) {
|
|
1787
|
+
for (const key of Object.keys(srcHumanoidMapping.rightHand)){
|
|
1788
|
+
addJointRemap(targetSkeleton, srcHumanoidMapping.rightHand[key], targetMapping.rightHand[key], applyRotationCorrection);
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
};
|
|
1544
1792
|
// Build remap for matched joint pairs
|
|
1545
1793
|
for(let fi = 0; fi < srcJointsFiltered.length; fi++){
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1794
|
+
addJointRemap(dstSkeleton, srcJointsFiltered[fi], dstJointsFiltered[fi], true);
|
|
1795
|
+
}
|
|
1796
|
+
for (const targetSkeleton of dstSignSkeletons){
|
|
1797
|
+
if (targetSkeleton !== dstSkeleton) {
|
|
1798
|
+
addHumanoidMappingRemaps(targetSkeleton);
|
|
1550
1799
|
}
|
|
1551
|
-
mappedSrcNodes.add(srcJoint);
|
|
1552
|
-
mappedDstNodes.add(dstJoint);
|
|
1553
|
-
nodeMap.set(srcJoint, dstJoint);
|
|
1554
|
-
const remap = createJointRetargetRemap(srcSkeleton, dstSkeleton, srcJoint, dstJoint);
|
|
1555
|
-
jointRemaps.push(remap);
|
|
1556
|
-
jointRemapBySrcNode.set(srcJoint, remap);
|
|
1557
1800
|
}
|
|
1558
1801
|
const dstClip = this.createAnimation(destName);
|
|
1559
1802
|
if (!dstClip) {
|
|
@@ -1562,9 +1805,37 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
|
|
|
1562
1805
|
dstClip.timeDuration = sourceClip.timeDuration;
|
|
1563
1806
|
dstClip.weight = sourceClip.weight;
|
|
1564
1807
|
dstClip.autoPlay = sourceClip.autoPlay;
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1808
|
+
copyMorphTargetGroupTracks(sourceClip, dstClip, this._model);
|
|
1809
|
+
for (const [targetSkeleton, targetRemaps] of jointRemapsByDstSkeleton){
|
|
1810
|
+
if (targetRemaps.length === 0) {
|
|
1811
|
+
continue;
|
|
1812
|
+
}
|
|
1813
|
+
const hasCopyableTrack = targetSkeleton === dstSkeleton || targetRemaps.some((remap)=>{
|
|
1814
|
+
const srcTracks = sourceClip.tracks.get(remap.srcNode);
|
|
1815
|
+
if (!srcTracks) {
|
|
1816
|
+
return false;
|
|
1817
|
+
}
|
|
1818
|
+
for (const srcTrack of srcTracks){
|
|
1819
|
+
if (srcTrack instanceof NodeRotationTrack || srcTrack instanceof NodeEulerRotationTrack) {
|
|
1820
|
+
return true;
|
|
1821
|
+
}
|
|
1822
|
+
if (srcTrack instanceof NodeTranslationTrack && remap.srcNode !== srcRootNode && srcTrack !== srcMotionTrack && jointTranslations === 'preserve') {
|
|
1823
|
+
return true;
|
|
1824
|
+
}
|
|
1825
|
+
if (srcTrack instanceof NodeScaleTrack) {
|
|
1826
|
+
return true;
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
return false;
|
|
1830
|
+
});
|
|
1831
|
+
if (!hasCopyableTrack) {
|
|
1832
|
+
continue;
|
|
1833
|
+
}
|
|
1834
|
+
dstClip.addSkeleton(targetSkeleton.persistentId);
|
|
1835
|
+
const targetRootNode = targetSkeleton.rootJoint ?? targetSkeleton.humanoidJointMapping?.body[HumanoidBodyRig.Hips] ?? targetRemaps[0].dstNode;
|
|
1836
|
+
const targetRootRot = targetRootNode === dstRootNode ? dstRootRot : computeParentChainRotation(targetRootNode, this._model, targetSkeleton);
|
|
1837
|
+
bakeHumanoidRotationTracks(sourceClip, srcSkeleton, targetSkeleton, srcRootRot, targetRootRot, dstClip, targetRemaps, humanoidRotationCorrection);
|
|
1838
|
+
}
|
|
1568
1839
|
if (rootMotion !== 'none') {
|
|
1569
1840
|
const dstRootBindPose = getRigBindPoseForNode(dstSkeleton, dstRootNode);
|
|
1570
1841
|
let dstRootTrack = null;
|
|
@@ -1572,7 +1843,7 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
|
|
|
1572
1843
|
dstRootTrack = createConstantTranslationTrack(dstRootBindPose.position);
|
|
1573
1844
|
} else if (srcMotionTrack && srcMotionNode) {
|
|
1574
1845
|
const srcMotionBindPose = getRigBindPoseForNode(srcSkeleton, srcMotionNode);
|
|
1575
|
-
const rootRemap = createTranslationRetargetRemap(srcMotionNode, dstRootNode, srcMotionBindPose.position, dstRootBindPose.position, dstSkeleton.joints.indexOf(dstRootNode), rootTranslationScale, rootTranslationRotation, options.lockRootMotionAxes);
|
|
1846
|
+
const rootRemap = createTranslationRetargetRemap(srcMotionNode, dstRootNode, srcMotionBindPose.position, dstRootBindPose.position, dstSkeleton.joints.indexOf(dstRootNode), rootTranslationScale, rootTranslationRotation, humanoidRotationCorrection ?? undefined, options.lockRootMotionAxes, humanoidRotationCorrection ?? undefined);
|
|
1576
1847
|
dstRootTrack = retargetTranslationTrack(srcMotionTrack, rootRemap);
|
|
1577
1848
|
}
|
|
1578
1849
|
if (dstRootTrack) {
|
|
@@ -1582,34 +1853,33 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
|
|
|
1582
1853
|
dstClip.addTrack(dstRootNode, dstRootTrack);
|
|
1583
1854
|
}
|
|
1584
1855
|
}
|
|
1585
|
-
for (const srcNode of
|
|
1856
|
+
for (const [srcNode, srcRemaps] of jointRemapsBySrcNode){
|
|
1586
1857
|
const srcTracks = sourceClip.tracks.get(srcNode);
|
|
1587
1858
|
if (!srcTracks) {
|
|
1588
1859
|
continue;
|
|
1589
1860
|
}
|
|
1590
|
-
const
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1861
|
+
for (const remap of srcRemaps){
|
|
1862
|
+
const dstNode = remap.dstNode;
|
|
1863
|
+
for (const srcTrack of srcTracks){
|
|
1864
|
+
let dstTrack;
|
|
1865
|
+
if (srcTrack instanceof NodeRotationTrack || srcTrack instanceof NodeEulerRotationTrack) {
|
|
1866
|
+
continue;
|
|
1867
|
+
} else if (srcTrack instanceof NodeTranslationTrack) {
|
|
1868
|
+
if (srcNode === srcRootNode || srcTrack === srcMotionTrack || jointTranslations !== 'preserve') {
|
|
1869
|
+
continue;
|
|
1870
|
+
}
|
|
1871
|
+
dstTrack = retargetTranslationTrack(srcTrack, remap);
|
|
1872
|
+
} else if (srcTrack instanceof NodeScaleTrack) {
|
|
1873
|
+
dstTrack = new NodeScaleTrack(cloneInterpolator(srcTrack.interpolator));
|
|
1874
|
+
} else {
|
|
1875
|
+
console.warn(`copyHumanoidAnimationFrom: unsupported track type '${srcTrack.constructor.name}', skipping`);
|
|
1600
1876
|
continue;
|
|
1601
1877
|
}
|
|
1602
|
-
dstTrack =
|
|
1603
|
-
|
|
1604
|
-
dstTrack =
|
|
1605
|
-
|
|
1606
|
-
console.warn(`copyHumanoidAnimationFrom: unsupported track type '${srcTrack.constructor.name}', skipping`);
|
|
1607
|
-
continue;
|
|
1878
|
+
dstTrack.name = srcTrack.name;
|
|
1879
|
+
dstTrack.target = dstNode.persistentId;
|
|
1880
|
+
dstTrack.jointIndex = remap.dstJointIndex;
|
|
1881
|
+
dstClip.addTrack(dstNode, dstTrack);
|
|
1608
1882
|
}
|
|
1609
|
-
dstTrack.name = srcTrack.name;
|
|
1610
|
-
dstTrack.target = dstNode.persistentId;
|
|
1611
|
-
dstTrack.jointIndex = remap.dstJointIndex;
|
|
1612
|
-
dstClip.addTrack(dstNode, dstTrack);
|
|
1613
1883
|
}
|
|
1614
1884
|
}
|
|
1615
1885
|
return dstClip;
|
|
@@ -1702,6 +1972,7 @@ function bakeHumanoidRotationTracks(sourceClip, srcSkeleton, dstSkeleton, srcRoo
|
|
|
1702
1972
|
dstClip.autoPlay = sourceClip.autoPlay;
|
|
1703
1973
|
// Register destination skeleton
|
|
1704
1974
|
dstClip.addSkeleton(dstSkeleton.persistentId);
|
|
1975
|
+
copyMorphTargetGroupTracks(sourceClip, dstClip, this._model);
|
|
1705
1976
|
for (const srcNode of srcJointsFiltered){
|
|
1706
1977
|
const srcTracks = sourceClip.tracks.get(srcNode);
|
|
1707
1978
|
if (!srcTracks) {
|