@lovelace_lol/embody 0.0.8 → 0.0.10
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/index.d.ts +1 -1
- package/dist/index.js +2085 -1466
- package/dist/index.js.map +1 -1
- package/dist/three/annotations/DPthreeCameraController.d.ts +1 -0
- package/dist/three/authoring.d.ts +95 -0
- package/dist/three/authoringTypes.d.ts +576 -0
- package/dist/three/character.d.ts +243 -0
- package/dist/three/characterHost.d.ts +48 -0
- package/dist/three/clipBindings.d.ts +11 -0
- package/dist/three/index.d.ts +28 -4
- package/dist/three/nativePlayback.d.ts +121 -0
- package/dist/three/playbackRendering.d.ts +14 -0
- package/dist/three.js +2020 -336
- package/dist/three.js.map +1 -1
- package/dist/wasm/compatibility.d.ts +14 -0
- package/dist/wasm/embody_wasm.d.ts +151 -206
- package/dist/wasm/embody_wasm.js +410 -576
- package/dist/wasm/embody_wasm_bg.wasm +0 -0
- package/dist/wasm/embody_wasm_bg.wasm.d.ts +78 -94
- package/dist/wasm/index.d.ts +7 -2
- package/dist/wasm.js +59 -2
- package/dist/wasm.js.map +1 -1
- package/package.json +5 -4
- package/dist/three/gaze.d.ts +0 -122
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as THREE3 from 'three';
|
|
2
|
-
import { NoBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NormalBlending, Vector3, Box3, Matrix4, Quaternion, MathUtils, Mesh, PlaneGeometry, ShadowMaterial, HemisphereLight, DirectionalLight, SRGBColorSpace, ACESFilmicToneMapping, WebGLRenderer, Scene, Color, PerspectiveCamera, PCFShadowMap, PCFSoftShadowMap,
|
|
3
|
-
import { initEmbodyCore, requireInitializedEmbodyCore } from '@lovelace_lol/embody/wasm';
|
|
2
|
+
import { NoBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NormalBlending, Vector3, Box3, Timer, Matrix4, AnimationMixer, AdditiveAnimationBlendMode, NormalAnimationBlendMode, LoopOnce, LoopRepeat, LoopPingPong, PropertyBinding, Euler, Quaternion, AnimationUtils, InterpolateDiscrete, InterpolateLinear, MathUtils, Mesh, PlaneGeometry, ShadowMaterial, HemisphereLight, DirectionalLight, SRGBColorSpace, ACESFilmicToneMapping, WebGLRenderer, Scene, Color, PerspectiveCamera, PCFShadowMap, PCFSoftShadowMap, NumberKeyframeTrack, QuaternionKeyframeTrack, VectorKeyframeTrack, AnimationClip, PMREMGenerator, FloatType, Float32BufferAttribute, BufferAttribute, WebGPUCoordinateSystem, WebGLCoordinateSystem } from 'three';
|
|
3
|
+
import { CC4_HUMANOID_SKELETON_TEMPLATE, HUMANOID_SKELETON_TEMPLATES, DEFAULT_HAIR_COLOR_APPEARANCE, initEmbodyCore, requireInitializedEmbodyCore } from '@lovelace_lol/embody/wasm';
|
|
4
|
+
export * from '@lovelace_lol/embody/wasm';
|
|
5
|
+
export { CC4_HUMANOID_SKELETON_TEMPLATE, DEFAULT_AXIS_TO_CHANNEL, DEFAULT_BONE_MAX_DEGREES, DEFAULT_HAIR_COLOR_APPEARANCE, HAIR_COLOR_PRESETS, HUMANOID_SKELETON_TEMPLATES, JOINT_CONTROL_SECTION, VISEME_KEYS } from '@lovelace_lol/embody/wasm';
|
|
4
6
|
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
|
|
5
7
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
6
8
|
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
|
|
@@ -449,6 +451,59 @@ function drawModelForRender(renderer, scene, camera, model) {
|
|
|
449
451
|
if (globalShadow && renderer.shadowMap.enabled) globalShadow.needsUpdate = true;
|
|
450
452
|
};
|
|
451
453
|
}
|
|
454
|
+
var bindings = /* @__PURE__ */ new WeakMap();
|
|
455
|
+
function bindPlaybackRendering(model, mixer, afterFrame) {
|
|
456
|
+
const binding = { mixer, enabled: true, afterFrame };
|
|
457
|
+
const entries = bindings.get(model) ?? /* @__PURE__ */ new Set();
|
|
458
|
+
entries.add(binding);
|
|
459
|
+
bindings.set(model, entries);
|
|
460
|
+
return {
|
|
461
|
+
setEnabled(enabled) {
|
|
462
|
+
binding.enabled = enabled;
|
|
463
|
+
},
|
|
464
|
+
dispose() {
|
|
465
|
+
entries.delete(binding);
|
|
466
|
+
if (!entries.size) bindings.delete(model);
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
function renderScenePlayback(scene, timer) {
|
|
471
|
+
const mixers = /* @__PURE__ */ new Set();
|
|
472
|
+
const active = [];
|
|
473
|
+
scene.traverse((object) => {
|
|
474
|
+
for (const binding of bindings.get(object) ?? []) {
|
|
475
|
+
if (binding.enabled) {
|
|
476
|
+
active.push(binding);
|
|
477
|
+
mixers.add(binding.mixer);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
for (const mixer of mixers) mixer.update(timer.getDelta());
|
|
482
|
+
for (const binding of active) binding.afterFrame();
|
|
483
|
+
}
|
|
484
|
+
function createScenePlaybackFrame(scene, document2) {
|
|
485
|
+
const timer = new Timer();
|
|
486
|
+
if (document2) timer.connect(document2);
|
|
487
|
+
let disposed = false;
|
|
488
|
+
let initialized = false;
|
|
489
|
+
return {
|
|
490
|
+
onFrame(timestamp) {
|
|
491
|
+
if (disposed) return;
|
|
492
|
+
timer.update(timestamp);
|
|
493
|
+
if (!initialized) {
|
|
494
|
+
initialized = true;
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
renderScenePlayback(scene, timer);
|
|
498
|
+
},
|
|
499
|
+
dispose() {
|
|
500
|
+
if (!disposed) {
|
|
501
|
+
disposed = true;
|
|
502
|
+
timer.dispose();
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
}
|
|
452
507
|
|
|
453
508
|
// three/annotations/DOMControls.ts
|
|
454
509
|
var RUNTIME_ANNOTATION_REGION_PREFIX = "runtime:annotation:";
|
|
@@ -1111,8 +1166,8 @@ function getAnnotationRegionLabel(region) {
|
|
|
1111
1166
|
const trimmed = label.trim();
|
|
1112
1167
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
1113
1168
|
}
|
|
1114
|
-
function isFiniteClipPoint(
|
|
1115
|
-
return Number.isFinite(
|
|
1169
|
+
function isFiniteClipPoint(point2) {
|
|
1170
|
+
return Number.isFinite(point2.x) && Number.isFinite(point2.y) && Number.isFinite(point2.z) && Number.isFinite(point2.w);
|
|
1116
1171
|
}
|
|
1117
1172
|
function resolveViewportSafeBounds(params) {
|
|
1118
1173
|
return requireAnnotationCameraCore().resolveViewportSafeBounds(params);
|
|
@@ -3913,9 +3968,9 @@ function resolveRuntimeAnnotationAUBoneTargets(auId, candidates, targetSide) {
|
|
|
3913
3968
|
const boneTargets = [];
|
|
3914
3969
|
for (const candidate of candidates) {
|
|
3915
3970
|
if (!isPlainRecord(candidate.auToBones)) continue;
|
|
3916
|
-
const
|
|
3917
|
-
if (!Array.isArray(
|
|
3918
|
-
for (const binding of
|
|
3971
|
+
const bindings2 = candidate.auToBones[auId];
|
|
3972
|
+
if (!Array.isArray(bindings2)) continue;
|
|
3973
|
+
for (const binding of bindings2) {
|
|
3919
3974
|
const target = readRuntimeAnnotationBoneTarget(binding);
|
|
3920
3975
|
if (!target || seen.has(target.boneName)) continue;
|
|
3921
3976
|
seen.add(target.boneName);
|
|
@@ -4079,6 +4134,7 @@ var DPthreeCameraController = class {
|
|
|
4079
4134
|
__publicField(this, "domElement");
|
|
4080
4135
|
// Renderer and render loop (when controller manages the render loop)
|
|
4081
4136
|
__publicField(this, "renderer", null);
|
|
4137
|
+
__publicField(this, "playbackTimer", new THREE3.Timer());
|
|
4082
4138
|
__publicField(this, "renderFrame");
|
|
4083
4139
|
__publicField(this, "resizeRenderer");
|
|
4084
4140
|
__publicField(this, "onRenderError");
|
|
@@ -4189,15 +4245,25 @@ var DPthreeCameraController = class {
|
|
|
4189
4245
|
startRenderLoop(propagateFailure = false) {
|
|
4190
4246
|
if (!this.renderer) return;
|
|
4191
4247
|
const renderer = this.renderer;
|
|
4248
|
+
this.playbackTimer.disconnect();
|
|
4249
|
+
const ownerDocument = renderer.domElement?.ownerDocument;
|
|
4250
|
+
if (ownerDocument) this.playbackTimer.connect(ownerDocument);
|
|
4251
|
+
this.playbackTimer.reset();
|
|
4252
|
+
let playbackStarted = false;
|
|
4192
4253
|
try {
|
|
4193
|
-
const started = renderer.setAnimationLoop(() => {
|
|
4194
|
-
if (this.disposed ||
|
|
4254
|
+
const started = renderer.setAnimationLoop((timestamp) => {
|
|
4255
|
+
if (this.disposed || renderer !== this.renderer) return;
|
|
4256
|
+
this.playbackTimer.update(timestamp);
|
|
4257
|
+
const samplePlayback = playbackStarted;
|
|
4258
|
+
playbackStarted = true;
|
|
4259
|
+
if (this.renderFailed || this.renderingSuspended || this.framePending) return;
|
|
4195
4260
|
try {
|
|
4196
4261
|
const preparationDraw = this.modelPreparation?.draw;
|
|
4197
4262
|
if (preparationDraw) {
|
|
4198
4263
|
preparationDraw();
|
|
4199
4264
|
return;
|
|
4200
4265
|
}
|
|
4266
|
+
if (samplePlayback) renderScenePlayback(this.scene, this.playbackTimer);
|
|
4201
4267
|
this.update();
|
|
4202
4268
|
const frame = this.renderFrame ? this.renderFrame(this.renderer, this.scene, this.camera) : this.renderer.render(this.scene, this.camera);
|
|
4203
4269
|
if (frame) {
|
|
@@ -4246,6 +4312,7 @@ var DPthreeCameraController = class {
|
|
|
4246
4312
|
* Stop the render loop
|
|
4247
4313
|
*/
|
|
4248
4314
|
stopRenderLoop() {
|
|
4315
|
+
this.playbackTimer.reset();
|
|
4249
4316
|
try {
|
|
4250
4317
|
const stopped = this.renderer?.setAnimationLoop(null);
|
|
4251
4318
|
if (stopped) void stopped.catch((error) => console.error("Character camera render loop stop failed.", error));
|
|
@@ -4331,18 +4398,18 @@ var DPthreeCameraController = class {
|
|
|
4331
4398
|
resolve = yes;
|
|
4332
4399
|
reject = no;
|
|
4333
4400
|
});
|
|
4334
|
-
const
|
|
4401
|
+
const request3 = {
|
|
4335
4402
|
promise,
|
|
4336
4403
|
draw: null,
|
|
4337
4404
|
cancel: (reason) => {
|
|
4338
4405
|
cancelled ?? (cancelled = reason);
|
|
4339
4406
|
invalidatePreparedShadows?.();
|
|
4340
|
-
|
|
4407
|
+
request3.draw = null;
|
|
4341
4408
|
rejectDraw?.(cancelled);
|
|
4342
4409
|
}
|
|
4343
4410
|
};
|
|
4344
|
-
this.modelPreparation =
|
|
4345
|
-
const abort = () =>
|
|
4411
|
+
this.modelPreparation = request3;
|
|
4412
|
+
const abort = () => request3.cancel(renderPreparationAborted());
|
|
4346
4413
|
options.signal?.addEventListener("abort", abort, { once: true });
|
|
4347
4414
|
const checkCancelled = () => {
|
|
4348
4415
|
if (cancelled) throw cancelled;
|
|
@@ -4361,8 +4428,8 @@ var DPthreeCameraController = class {
|
|
|
4361
4428
|
checkCancelled();
|
|
4362
4429
|
await new Promise((done, failed) => {
|
|
4363
4430
|
rejectDraw = failed;
|
|
4364
|
-
|
|
4365
|
-
|
|
4431
|
+
request3.draw = () => {
|
|
4432
|
+
request3.draw = null;
|
|
4366
4433
|
try {
|
|
4367
4434
|
checkCancelled();
|
|
4368
4435
|
invalidatePreparedShadows = drawModelForRender(renderer, this.scene, this.camera, model);
|
|
@@ -4377,7 +4444,7 @@ var DPthreeCameraController = class {
|
|
|
4377
4444
|
checkCancelled();
|
|
4378
4445
|
} finally {
|
|
4379
4446
|
options.signal?.removeEventListener("abort", abort);
|
|
4380
|
-
if (this.modelPreparation ===
|
|
4447
|
+
if (this.modelPreparation === request3) this.modelPreparation = null;
|
|
4381
4448
|
}
|
|
4382
4449
|
})().then(resolve, reject);
|
|
4383
4450
|
return promise;
|
|
@@ -4416,10 +4483,10 @@ var DPthreeCameraController = class {
|
|
|
4416
4483
|
*/
|
|
4417
4484
|
async loadRegions(config) {
|
|
4418
4485
|
if (this.disposed) return;
|
|
4419
|
-
const
|
|
4486
|
+
const request3 = ++this.regionLoadGeneration;
|
|
4420
4487
|
const model = this.model;
|
|
4421
4488
|
const runtimeConfig = await this.resolveCharacterConfig(config);
|
|
4422
|
-
if (!this.isRegionLoadCurrent(
|
|
4489
|
+
if (!this.isRegionLoadCurrent(request3, model)) return;
|
|
4423
4490
|
await this.prepareRegionsAndMarkersForReveal(runtimeConfig);
|
|
4424
4491
|
}
|
|
4425
4492
|
/**
|
|
@@ -4439,12 +4506,12 @@ var DPthreeCameraController = class {
|
|
|
4439
4506
|
async prepareRegionsAndMarkersForReveal(config, beforeReveal) {
|
|
4440
4507
|
if (this.disposed) return;
|
|
4441
4508
|
this.prepareRegionState(config);
|
|
4442
|
-
const
|
|
4509
|
+
const request3 = this.regionLoadGeneration;
|
|
4443
4510
|
const model = this.model;
|
|
4444
4511
|
await this.loadMarkersForCurrentRegions(true);
|
|
4445
|
-
if (!this.isRegionLoadCurrent(
|
|
4512
|
+
if (!this.isRegionLoadCurrent(request3, model) || this.characterConfig !== config) return;
|
|
4446
4513
|
if (beforeReveal && !await beforeReveal()) return;
|
|
4447
|
-
if (this.isRegionLoadCurrent(
|
|
4514
|
+
if (this.isRegionLoadCurrent(request3, model) && this.characterConfig === config) {
|
|
4448
4515
|
this.startPreparedCameraTransition(config);
|
|
4449
4516
|
}
|
|
4450
4517
|
}
|
|
@@ -4479,14 +4546,14 @@ var DPthreeCameraController = class {
|
|
|
4479
4546
|
return;
|
|
4480
4547
|
}
|
|
4481
4548
|
const characterConfig = this.characterConfig;
|
|
4482
|
-
const
|
|
4549
|
+
const request3 = this.regionLoadGeneration;
|
|
4483
4550
|
const model = this.model;
|
|
4484
4551
|
this.ensureMarkersForCurrentStyle();
|
|
4485
4552
|
const markers = this.markers;
|
|
4486
4553
|
if (!markers) return;
|
|
4487
4554
|
markers.setVisible(this.markersVisible);
|
|
4488
4555
|
await markers.loadRegions(characterConfig, { sliceSurfaceQueries });
|
|
4489
|
-
if (!this.isRegionLoadCurrent(
|
|
4556
|
+
if (!this.isRegionLoadCurrent(request3, model) || markers !== this.markers || characterConfig !== this.characterConfig) {
|
|
4490
4557
|
return;
|
|
4491
4558
|
}
|
|
4492
4559
|
if (this.currentRegion) {
|
|
@@ -4656,8 +4723,8 @@ var DPthreeCameraController = class {
|
|
|
4656
4723
|
* @param zoomDuration - Duration of the final zoom in ms (default: 1500)
|
|
4657
4724
|
*/
|
|
4658
4725
|
async playIntroAnimation(orbitDuration = 3e3, zoomDuration = 1500) {
|
|
4659
|
-
const
|
|
4660
|
-
if (
|
|
4726
|
+
const request3 = await this.beginCameraRequest();
|
|
4727
|
+
if (request3 === null) return;
|
|
4661
4728
|
if (!this.model) {
|
|
4662
4729
|
return;
|
|
4663
4730
|
}
|
|
@@ -4672,12 +4739,12 @@ var DPthreeCameraController = class {
|
|
|
4672
4739
|
const orbitRadius = Math.max(horizontalExtent, verticalExtent) * 1.8;
|
|
4673
4740
|
const orbitHeight = center.y;
|
|
4674
4741
|
await this.animateOrbit(center, orbitRadius, orbitHeight, orbitDuration);
|
|
4675
|
-
if (!this.isCameraRequestCurrent(
|
|
4742
|
+
if (!this.isCameraRequestCurrent(request3)) return;
|
|
4676
4743
|
const leftEyeRegion = this.findIntroLeftEyeRegion();
|
|
4677
4744
|
const leftEyeFocus = leftEyeRegion ? this.calculateIntroLeftEyeFocusPosition(leftEyeRegion) : null;
|
|
4678
4745
|
if (leftEyeFocus && leftEyeRegion) {
|
|
4679
4746
|
await this.animateCamera(leftEyeFocus.position, leftEyeFocus.target, zoomDuration);
|
|
4680
|
-
if (!this.isCameraRequestCurrent(
|
|
4747
|
+
if (!this.isCameraRequestCurrent(request3)) return;
|
|
4681
4748
|
this.currentRegion = leftEyeRegion.name;
|
|
4682
4749
|
this.notifyRegionChange(leftEyeRegion.name);
|
|
4683
4750
|
return;
|
|
@@ -4686,7 +4753,7 @@ var DPthreeCameraController = class {
|
|
|
4686
4753
|
const fullBodyRegion = this.regions.find((region) => this.isFullBodyRegion(region));
|
|
4687
4754
|
const focusPos = this.calculateFullBodyFocusPosition(fullBodyRegion?.paddingFactor, finalAngle, "world");
|
|
4688
4755
|
await this.animateCamera(focusPos.position, focusPos.target, zoomDuration);
|
|
4689
|
-
if (!this.isCameraRequestCurrent(
|
|
4756
|
+
if (!this.isCameraRequestCurrent(request3)) return;
|
|
4690
4757
|
if (fullBodyRegion) {
|
|
4691
4758
|
this.currentRegion = fullBodyRegion.name;
|
|
4692
4759
|
this.notifyRegionChange(fullBodyRegion.name);
|
|
@@ -5390,6 +5457,7 @@ var DPthreeCameraController = class {
|
|
|
5390
5457
|
this.regionLoadGeneration += 1;
|
|
5391
5458
|
this.cameraRequestGeneration += 1;
|
|
5392
5459
|
this.stopRenderLoop();
|
|
5460
|
+
this.playbackTimer.dispose();
|
|
5393
5461
|
const renderingSettled = this.unbindRendering?.();
|
|
5394
5462
|
this.unbindRendering = null;
|
|
5395
5463
|
this.cleanupResizeHandling();
|
|
@@ -5703,19 +5771,19 @@ var DPthreeCameraController = class {
|
|
|
5703
5771
|
this.laterality = detectAnnotationLaterality(this.model, this.regions, boneResolutionProfile(this.characterConfig));
|
|
5704
5772
|
}
|
|
5705
5773
|
/** Resolver and paint continuations belong to one model/configuration load. */
|
|
5706
|
-
isRegionLoadCurrent(
|
|
5707
|
-
return !this.disposed &&
|
|
5774
|
+
isRegionLoadCurrent(request3, model) {
|
|
5775
|
+
return !this.disposed && request3 === this.regionLoadGeneration && model === this.model;
|
|
5708
5776
|
}
|
|
5709
5777
|
/** Await Wasm once per request and abandon requests superseded during initialization. */
|
|
5710
5778
|
async beginCameraRequest() {
|
|
5711
|
-
const
|
|
5779
|
+
const request3 = ++this.cameraRequestGeneration;
|
|
5712
5780
|
this.cancelCameraAnimation();
|
|
5713
5781
|
if (this.disposed) return null;
|
|
5714
5782
|
await getAnnotationCameraCore();
|
|
5715
|
-
return this.isCameraRequestCurrent(
|
|
5783
|
+
return this.isCameraRequestCurrent(request3) ? request3 : null;
|
|
5716
5784
|
}
|
|
5717
|
-
isCameraRequestCurrent(
|
|
5718
|
-
return !this.disposed &&
|
|
5785
|
+
isCameraRequestCurrent(request3) {
|
|
5786
|
+
return !this.disposed && request3 === this.cameraRequestGeneration;
|
|
5719
5787
|
}
|
|
5720
5788
|
cancelCameraAnimation() {
|
|
5721
5789
|
this.timerAnimationFallbackToken += 1;
|
|
@@ -6448,6 +6516,99 @@ function pickContinuumAnnotationAuId(value, negId, posId, stickyId) {
|
|
|
6448
6516
|
if (value > 0) return posId;
|
|
6449
6517
|
return negId;
|
|
6450
6518
|
}
|
|
6519
|
+
var json = (value) => JSON.stringify(value ?? {});
|
|
6520
|
+
function request2(op, payload = {}) {
|
|
6521
|
+
return JSON.parse(requireInitializedEmbodyCore().embody_request(json({ op, payload })));
|
|
6522
|
+
}
|
|
6523
|
+
var getPreset = (id) => request2("preset.get", { id });
|
|
6524
|
+
var extendCharacterConfigWithPreset = (config) => request2("profile.extendConfig", { config });
|
|
6525
|
+
var extractProfileOverrides = (config) => request2("profile.extractOverrides", { config });
|
|
6526
|
+
var mergeCharacterRegionsByName = (base, override) => request2("profile.mergeRegions", { base, override });
|
|
6527
|
+
var getMeshNamesForAUProfile = (profile, auId) => request2("profile.getMeshNamesForAU", { profile, auId });
|
|
6528
|
+
var getHumanoidSpecification = () => request2("humanoid.getSpecification");
|
|
6529
|
+
var setAUMorphTargets = (profile, auId, side, targets) => request2("profile.setAUMorphTargets", { profile, auId, side, targets });
|
|
6530
|
+
var setHumanoidRoleBinding = (profile, role, boneName) => request2("profile.setHumanoidRoleBinding", { profile, role, boneName });
|
|
6531
|
+
var resolveHumanoidCharacterization = (profile) => request2("profile.resolveHumanoidCharacterization", { profile });
|
|
6532
|
+
var hasLeftRightMorphs = (profile, auId) => request2("profile.hasLeftRightMorphs", { profile, auId });
|
|
6533
|
+
var isMixedAU = (profile, auId) => request2("profile.isMixedAU", { profile, auId });
|
|
6534
|
+
var resolveVisemeProfile = (profile) => request2("profile.resolveVisemes", { profile });
|
|
6535
|
+
var isMaxDegreesOnlyAxisBindingUpdate = (update) => request2("bone.isMaxDegreesOnlyUpdate", { update });
|
|
6536
|
+
var findNodeKeyForBone = (boneName, profile) => profile ? request2("bone.findNodeKey", { profile, boneName }) : null;
|
|
6537
|
+
var ensureBoneNodeKey = (profile, boneName) => request2("bone.ensureNodeKey", { profile, boneName });
|
|
6538
|
+
var ensureBilateralBoneNodeKeys = (profile, leftBoneName, rightBoneName) => request2("bone.ensureBilateralNodeKeys", { profile, leftBoneName, rightBoneName });
|
|
6539
|
+
var resolveBoneNameForNodeKey = (profile, nodeKey) => request2("bone.resolveBoneName", { profile, nodeKey });
|
|
6540
|
+
var stripConfiguredBoneAffixes = (profile, boneName) => request2("bone.stripAffixes", { profile: profile ?? {}, boneName });
|
|
6541
|
+
var inferChiralBoneNamePair = (boneNames, selectedBoneName) => request2("bone.inferChiralPair", { boneNames, selectedBoneName });
|
|
6542
|
+
var formatAxisLabel = (axis) => request2("bone.formatAxisLabel", { axis });
|
|
6543
|
+
var formatAxisDirectionLabel = (axis, direction) => request2("bone.formatDirectionLabel", { axis, direction });
|
|
6544
|
+
var getAxisFromChannel = (channel) => channel ? request2("bone.getAxisFromChannel", { channel }) : null;
|
|
6545
|
+
var getBoneAxisBindingState = (profile, boneName, axis) => request2("bone.getAxisState", { profile, boneName, axis });
|
|
6546
|
+
var resolveBoneAxisChannel = (profile, boneName, axis) => request2("bone.resolveAxisChannel", { profile, boneName, axis });
|
|
6547
|
+
var getBilateralAxisBindingState = (profile, boneName, axis) => request2("bone.getBilateralAxisState", { profile, boneName, axis });
|
|
6548
|
+
var getAUBoneBindingState = (profile, auId) => request2("bone.getAUBindingState", { profile, auId });
|
|
6549
|
+
var inferEyeControlScope = (profile, binding) => request2("bone.inferEyeScope", { profile, binding });
|
|
6550
|
+
var inferEyeControlFamily = (binding) => request2("bone.inferEyeFamily", { binding });
|
|
6551
|
+
var applyBoneAxisBindingUpdate = (profile, boneName, axis, update) => request2("bone.applyAxisUpdate", { profile, boneName, axis, update });
|
|
6552
|
+
var applyBilateralAxisBindingUpdate = (profile, boneName, axis, scope, update) => request2("bone.applyBilateralAxisUpdate", { profile, boneName, axis, scope, update });
|
|
6553
|
+
var applyAUBoneBindingUpdate = (profile, auId, update) => request2("bone.applyAUBindingUpdate", { profile, auId, update });
|
|
6554
|
+
var createBoneAxisAu = (profile, boneName, axis, direction, options = {}) => request2("bone.createAxisAU", { profile, boneName, axis, direction, name: options.name });
|
|
6555
|
+
var createBilateralBoneAxisAu = (profile, boneName, axis, scope, direction, options = {}) => request2("bone.createBilateralAxisAU", { profile, boneName, axis, scope, direction, name: options.name });
|
|
6556
|
+
var buildBoneAuOptions = (profile) => request2("bone.buildAUOptions", { profile });
|
|
6557
|
+
var isJointControlAuInfo = (info) => request2("bone.isJointControlInfo", { info });
|
|
6558
|
+
var classifyAuAsJointControl = (profile, auId, options = {}) => request2("bone.classifyJointControl", { profile, auId, boneName: options.boneName, nodeKey: options.nodeKey });
|
|
6559
|
+
var resolveContinuumDisplayLabel = (profile, negativeAuId, positiveAuId) => request2("bone.resolveContinuumLabel", { profile, negativeAuId, positiveAuId }) ?? `AU ${negativeAuId} <-> AU ${positiveAuId}`;
|
|
6560
|
+
function inspectModel(model, meshes, profile) {
|
|
6561
|
+
return new ThreeModelInspector().inspectModel(model, { meshes, profile });
|
|
6562
|
+
}
|
|
6563
|
+
function getBodyControls(profile, model) {
|
|
6564
|
+
return request2("profile.getBodyControls", { profile, ...model ? { model: inspectModel(model, void 0, profile).descriptor } : {} });
|
|
6565
|
+
}
|
|
6566
|
+
function extractModelData(model, meshes, animations = []) {
|
|
6567
|
+
const inspection = inspectModel(model, meshes);
|
|
6568
|
+
return JSON.parse(requireInitializedEmbodyCore().extract_model_data_json(json(inspection.descriptor), json(serializeAnimationClips(model, animations, inspection))));
|
|
6569
|
+
}
|
|
6570
|
+
async function analyzeModel(options) {
|
|
6571
|
+
const source = options.source;
|
|
6572
|
+
const model = source.type === "gltf" ? source.gltf.scene ?? source.gltf.scenes[0] : source.model;
|
|
6573
|
+
const animations = source.type === "gltf" ? source.gltf.animations : source.animations ?? [];
|
|
6574
|
+
const inspection = inspectModel(model, source.type === "runtime" ? source.meshes : void 0);
|
|
6575
|
+
return JSON.parse(requireInitializedEmbodyCore().analyze_model_descriptor(json(inspection.descriptor), json(serializeAnimationClips(model, animations, inspection)), options.preset ? json(options.preset) : "", json({ suggestCorrections: Boolean(options.suggestCorrections) })));
|
|
6576
|
+
}
|
|
6577
|
+
function validateMappings(meshes, skeleton, profile, options = {}) {
|
|
6578
|
+
let nextMorphId = 1;
|
|
6579
|
+
const morphTargets = [];
|
|
6580
|
+
const descriptorMeshes = (meshes ?? []).map((value, index) => {
|
|
6581
|
+
const mesh = value;
|
|
6582
|
+
const id = index + 1;
|
|
6583
|
+
const morphTargetIds = Object.entries(mesh.morphTargetDictionary ?? mesh.geometry?.morphTargetDictionary ?? {}).map(([name, hostIndex]) => {
|
|
6584
|
+
const morphId = nextMorphId++;
|
|
6585
|
+
morphTargets.push({ id: morphId, meshId: id, name, hostIndex });
|
|
6586
|
+
return morphId;
|
|
6587
|
+
});
|
|
6588
|
+
return { id, name: mesh.name ?? "", morphTargetIds, visible: true };
|
|
6589
|
+
});
|
|
6590
|
+
const bones = (skeleton?.bones ?? []).map((bone, index) => ({ id: index + 1, name: typeof bone === "string" ? bone : bone.name ?? "" }));
|
|
6591
|
+
return JSON.parse(requireInitializedEmbodyCore().validate_profile_model(json(profile), json({ meshes: descriptorMeshes, morphTargets, bones, objects: [] }), json(options)));
|
|
6592
|
+
}
|
|
6593
|
+
function validateHumanoidCharacterization(model, profile) {
|
|
6594
|
+
return JSON.parse(requireInitializedEmbodyCore().validate_humanoid_characterization(json(profile), json(inspectModel(model, void 0, profile).descriptor)));
|
|
6595
|
+
}
|
|
6596
|
+
function normalizeHairColorAppearance(value, fallback = DEFAULT_HAIR_COLOR_APPEARANCE) {
|
|
6597
|
+
return JSON.parse(requireInitializedEmbodyCore().normalize_hair_color_appearance_json(json(value), json(fallback)));
|
|
6598
|
+
}
|
|
6599
|
+
var getHumanoidSkeletonTemplate = (id) => HUMANOID_SKELETON_TEMPLATES.find((template) => template.id === id) ?? null;
|
|
6600
|
+
function getHumanoidSkeletonTemplateBoneNames(template = CC4_HUMANOID_SKELETON_TEMPLATE) {
|
|
6601
|
+
return JSON.parse(requireInitializedEmbodyCore().humanoid_skeleton_template_bone_names(json(template)));
|
|
6602
|
+
}
|
|
6603
|
+
function createValidationSkeletonFromHumanoidTemplate(template = CC4_HUMANOID_SKELETON_TEMPLATE) {
|
|
6604
|
+
return JSON.parse(requireInitializedEmbodyCore().create_validation_skeleton_json(json(template)));
|
|
6605
|
+
}
|
|
6606
|
+
function computeHumanoidSkeletonTemplateRestBounds(template) {
|
|
6607
|
+
return Array.from(requireInitializedEmbodyCore().compute_humanoid_skeleton_template_rest_bounds(json(template)));
|
|
6608
|
+
}
|
|
6609
|
+
function extractHumanoidSkeletonTemplateFromModel(model, options) {
|
|
6610
|
+
return JSON.parse(requireInitializedEmbodyCore().extract_humanoid_skeleton_template_json(json(inspectModel(model).descriptor), json(options)));
|
|
6611
|
+
}
|
|
6451
6612
|
var isBone = (object) => !!(object.isBone || object.type === "Bone");
|
|
6452
6613
|
var finite = (values, description) => {
|
|
6453
6614
|
if (!values.every(Number.isFinite)) {
|
|
@@ -6558,387 +6719,1722 @@ function extendModelReferencePose(model, previous) {
|
|
|
6558
6719
|
}
|
|
6559
6720
|
function bindModelReferencePose(model, referencePose) {
|
|
6560
6721
|
if (referencePose.version !== 1) throw new Error("Unsupported model reference pose version");
|
|
6561
|
-
const
|
|
6722
|
+
const bindings2 = /* @__PURE__ */ new Map();
|
|
6562
6723
|
let index = 0;
|
|
6563
6724
|
const bind = (object, path, parentPath) => {
|
|
6564
6725
|
const node = referencePose.nodes[index++];
|
|
6565
6726
|
if (!matchesNode(object, node, path, parentPath) || node.childCount !== object.children.length) {
|
|
6566
6727
|
throw incompatible(object, path);
|
|
6567
6728
|
}
|
|
6568
|
-
|
|
6729
|
+
bindings2.set(object, node);
|
|
6569
6730
|
object.children.forEach((child, childIndex) => bind(child, `${path}/${childIndex}`, path));
|
|
6570
6731
|
};
|
|
6571
6732
|
bind(model, "", null);
|
|
6572
6733
|
if (index !== referencePose.nodes.length) throw new Error("Incompatible reference pose hierarchy: extra captured nodes");
|
|
6573
|
-
return
|
|
6574
|
-
}
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6734
|
+
return bindings2;
|
|
6735
|
+
}
|
|
6736
|
+
function withComponentTracks(clip) {
|
|
6737
|
+
let expanded = false;
|
|
6738
|
+
const tracks = clip.tracks.flatMap((track) => {
|
|
6739
|
+
const parsed = PropertyBinding.parseTrackName(track.name);
|
|
6740
|
+
const euler = parsed.propertyName === "rotation";
|
|
6741
|
+
if (!euler && !["morphTargetInfluences", "weights"].includes(parsed.propertyName) || parsed.propertyIndex !== void 0) return [track];
|
|
6742
|
+
const cubic = track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true;
|
|
6743
|
+
const parts = cubic ? 3 : 1;
|
|
6744
|
+
const width = track.getValueSize() / parts;
|
|
6745
|
+
if (!Number.isInteger(width) || width < 1 || euler && width !== 3) throw new Error(`Invalid component track ${JSON.stringify(track.name)}.`);
|
|
6746
|
+
expanded = true;
|
|
6747
|
+
return Array.from({ length: width }, (_, component) => {
|
|
6748
|
+
const scalar = track.clone();
|
|
6749
|
+
scalar.name = `${track.name}[${euler ? ["x", "y", "z"][component] : component}]`;
|
|
6750
|
+
scalar.values = track.values.slice(0, track.times.length * parts);
|
|
6751
|
+
for (let sample = 0; sample < scalar.values.length; sample += 1) scalar.values[sample] = track.values[sample * width + component];
|
|
6752
|
+
return scalar;
|
|
6753
|
+
});
|
|
6754
|
+
});
|
|
6755
|
+
if (!expanded) return clip;
|
|
6756
|
+
const indexed = clip.clone();
|
|
6757
|
+
indexed.tracks = tracks;
|
|
6758
|
+
return indexed;
|
|
6759
|
+
}
|
|
6760
|
+
function concreteTrackName(target, inspection) {
|
|
6761
|
+
if (!target) return void 0;
|
|
6762
|
+
if (target.kind === "morphTarget") {
|
|
6763
|
+
const binding = inspection.morphBindings.get(Number(target.morphTargetId));
|
|
6764
|
+
return binding && `${binding.mesh.uuid}.morphTargetInfluences[${binding.index}]`;
|
|
6765
|
+
}
|
|
6766
|
+
if (target.kind === "boneTransform" || target.kind === "objectTransform") {
|
|
6767
|
+
const object = target.kind === "boneTransform" ? inspection.boneBindings.get(Number(target.boneId)) : inspection.objectBindings.get(Number(target.objectId));
|
|
6768
|
+
const property = target.property ?? "rotation";
|
|
6769
|
+
if (!object) return void 0;
|
|
6770
|
+
if (property === "rotation" || property === "quaternion") return `${object.uuid}.quaternion`;
|
|
6771
|
+
if (property === "eulerX" || property === "eulerY" || property === "eulerZ") return `${object.uuid}.rotation[${property.slice(-1).toLowerCase()}]`;
|
|
6772
|
+
if (property === "position" || property === "scale") return `${object.uuid}.${property}`;
|
|
6603
6773
|
}
|
|
6604
|
-
|
|
6605
|
-
const
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
const
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6774
|
+
if (target.kind === "meshVisibility") {
|
|
6775
|
+
const mesh = inspection.meshBindings.get(Number(target.meshId));
|
|
6776
|
+
return mesh && `${mesh.uuid}.visible`;
|
|
6777
|
+
}
|
|
6778
|
+
return void 0;
|
|
6779
|
+
}
|
|
6780
|
+
function cloneWithConcreteTrackNames(clip, tracks, inspection) {
|
|
6781
|
+
const native = clip.clone();
|
|
6782
|
+
for (let index = 0; index < tracks.length; index += 1) {
|
|
6783
|
+
const name = concreteTrackName(tracks[index].target, inspection);
|
|
6784
|
+
if (!name) throw new Error("Every native playback track must resolve on the bound model.");
|
|
6785
|
+
native.tracks[index].name = name;
|
|
6786
|
+
}
|
|
6787
|
+
return native;
|
|
6788
|
+
}
|
|
6789
|
+
|
|
6790
|
+
// three/nativePlayback.ts
|
|
6791
|
+
var sampleSize = (track) => track.getValueSize() / (track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ? 3 : 1);
|
|
6792
|
+
var asError = (error) => error instanceof Error ? error : new Error(String(error));
|
|
6793
|
+
var blendMode = (mode) => mode === "additive" ? AdditiveAnimationBlendMode : NormalAnimationBlendMode;
|
|
6794
|
+
var loopMode = (mode) => mode === "once" ? LoopOnce : mode === "repeat" ? LoopRepeat : LoopPingPong;
|
|
6795
|
+
function validateBinding(binding) {
|
|
6796
|
+
if (!binding.model?.isObject3D || binding.mixer && binding.mixer.getRoot() !== binding.model) {
|
|
6797
|
+
throw new Error("Native playback requires a Three model and its render integration mixer.");
|
|
6798
|
+
}
|
|
6799
|
+
const objects = /* @__PURE__ */ new Set();
|
|
6800
|
+
binding.model.traverse((object) => objects.add(object));
|
|
6801
|
+
const { inspection } = binding;
|
|
6802
|
+
for (const object of [
|
|
6803
|
+
...inspection.meshBindings.values(),
|
|
6804
|
+
...inspection.boneBindings.values(),
|
|
6805
|
+
...inspection.objectBindings.values(),
|
|
6806
|
+
...Array.from(inspection.morphBindings.values(), (entry) => entry.mesh)
|
|
6807
|
+
]) {
|
|
6808
|
+
if (!objects.has(object)) throw new Error("Native playback inspection contains an object outside the bound model.");
|
|
6809
|
+
}
|
|
6810
|
+
}
|
|
6811
|
+
var ThreeNativePlaybackConnector = class {
|
|
6812
|
+
constructor(session, binding) {
|
|
6813
|
+
this.session = session;
|
|
6814
|
+
__publicField(this, "binding");
|
|
6815
|
+
__publicField(this, "rendering");
|
|
6816
|
+
__publicField(this, "renderingEnabled", true);
|
|
6817
|
+
__publicField(this, "resources", /* @__PURE__ */ new Map());
|
|
6818
|
+
__publicField(this, "actionHandles", /* @__PURE__ */ new Map());
|
|
6819
|
+
__publicField(this, "listeners", /* @__PURE__ */ new Set());
|
|
6820
|
+
__publicField(this, "pending", []);
|
|
6821
|
+
__publicField(this, "notifications", []);
|
|
6822
|
+
__publicField(this, "depth", 0);
|
|
6823
|
+
__publicField(this, "flushingNotifications", false);
|
|
6824
|
+
__publicField(this, "notificationScheduled", false);
|
|
6825
|
+
__publicField(this, "sessionDisposed", false);
|
|
6826
|
+
__publicField(this, "disposed", false);
|
|
6827
|
+
__publicField(this, "onError");
|
|
6828
|
+
__publicField(this, "onRelease");
|
|
6829
|
+
__publicField(this, "finished", (event) => {
|
|
6830
|
+
const handle = this.actionHandles.get(event.action);
|
|
6831
|
+
if (!handle || this.disposed) return;
|
|
6832
|
+
this.notifications.push({ type: this.resources.get(handle)?.fadingOut ? "cancelled" : "completed", handle });
|
|
6833
|
+
if (this.notificationScheduled) return;
|
|
6834
|
+
this.notificationScheduled = true;
|
|
6835
|
+
queueMicrotask(() => {
|
|
6836
|
+
this.notificationScheduled = false;
|
|
6837
|
+
if (this.disposed) return;
|
|
6838
|
+
try {
|
|
6839
|
+
this.flushNotifications();
|
|
6840
|
+
} catch (error) {
|
|
6841
|
+
const failure = asError(error);
|
|
6842
|
+
if (this.onError) this.onError(failure);
|
|
6843
|
+
else throw failure;
|
|
6844
|
+
}
|
|
6845
|
+
});
|
|
6846
|
+
});
|
|
6847
|
+
validateBinding(binding);
|
|
6848
|
+
this.binding = { ...binding, mixer: binding.mixer ?? new AnimationMixer(binding.model) };
|
|
6849
|
+
this.onError = binding.onError;
|
|
6850
|
+
this.onRelease = binding.onRelease;
|
|
6851
|
+
this.binding.mixer.addEventListener("finished", this.finished);
|
|
6852
|
+
this.rendering = bindPlaybackRendering(binding.model, this.binding.mixer, () => this.flushEvents());
|
|
6853
|
+
}
|
|
6854
|
+
/** Prepare bindings first; old actions are released before the new binding is exposed. */
|
|
6855
|
+
rebind(modelKey, profileKey, binding = this.binding) {
|
|
6856
|
+
validateBinding(binding);
|
|
6857
|
+
this.beforeOperation();
|
|
6858
|
+
this.dispatch(this.session.rebind(modelKey, profileKey), void 0, () => {
|
|
6859
|
+
this.binding.mixer.removeEventListener("finished", this.finished);
|
|
6860
|
+
this.rendering.dispose();
|
|
6861
|
+
this.binding = { ...binding, mixer: binding.mixer ?? new AnimationMixer(binding.model) };
|
|
6862
|
+
this.binding.mixer.addEventListener("finished", this.finished);
|
|
6863
|
+
this.rendering = bindPlaybackRendering(binding.model, this.binding.mixer, () => this.flushEvents());
|
|
6864
|
+
this.rendering.setEnabled(this.renderingEnabled);
|
|
6865
|
+
});
|
|
6866
|
+
}
|
|
6867
|
+
play(clip, options = {}) {
|
|
6868
|
+
this.beforeOperation();
|
|
6869
|
+
const native = createAnimationClipFromClipIR(clip, this.binding.inspection);
|
|
6870
|
+
if (native.tracks.length !== clip.tracks.length) {
|
|
6871
|
+
throw new Error("Every playback track must resolve on the bound model.");
|
|
6872
|
+
}
|
|
6873
|
+
return this.dispatch(this.session.play(JSON.stringify(clip), JSON.stringify(options)), native).handle;
|
|
6874
|
+
}
|
|
6875
|
+
/**
|
|
6876
|
+
* Validate native track bindings through the existing serializer, then retain
|
|
6877
|
+
* the native clone's interpolants and authored/additive sample values. Concrete
|
|
6878
|
+
* binding names match compiled tracks so Three shares their PropertyMixer.
|
|
6879
|
+
*/
|
|
6880
|
+
playNativeClip(clip, options = {}) {
|
|
6881
|
+
this.beforeOperation();
|
|
6882
|
+
clip = withComponentTracks(clip);
|
|
6883
|
+
const [ir] = serializeAnimationClips(this.binding.model, [clip], this.binding.inspection);
|
|
6884
|
+
if (ir.tracks.length !== clip.tracks.length) {
|
|
6885
|
+
throw new Error("Every native playback track must serialize against the bound model.");
|
|
6886
|
+
}
|
|
6887
|
+
const native = cloneWithConcreteTrackNames(clip, ir.tracks, this.binding.inspection);
|
|
6888
|
+
const settings = {
|
|
6889
|
+
...options,
|
|
6890
|
+
blendMode: options.blendMode ?? (clip.blendMode === AdditiveAnimationBlendMode ? "additive" : "normal")
|
|
6891
|
+
};
|
|
6892
|
+
return this.dispatch(this.session.play(JSON.stringify(ir), JSON.stringify(settings)), native).handle;
|
|
6893
|
+
}
|
|
6894
|
+
control(handle, control) {
|
|
6895
|
+
this.beforeOperation();
|
|
6896
|
+
this.dispatch(this.session.control(handle, JSON.stringify(control)));
|
|
6897
|
+
}
|
|
6898
|
+
setRendering(enabled) {
|
|
6899
|
+
this.beforeOperation();
|
|
6900
|
+
if (enabled === this.renderingEnabled) return;
|
|
6901
|
+
this.renderingEnabled = enabled;
|
|
6902
|
+
this.rendering.setEnabled(enabled);
|
|
6903
|
+
for (const resource of this.resources.values()) {
|
|
6904
|
+
if (!resource.action) continue;
|
|
6905
|
+
if (!enabled) {
|
|
6906
|
+
resource.suspendedPaused = resource.action.paused;
|
|
6907
|
+
this.pauseFade(resource);
|
|
6908
|
+
resource.action.paused = true;
|
|
6909
|
+
} else if (resource.suspendedPaused !== void 0) {
|
|
6910
|
+
resource.action.paused = resource.suspendedPaused;
|
|
6911
|
+
if (!resource.explicitlyPaused) this.resumeFade(resource);
|
|
6912
|
+
resource.suspendedPaused = void 0;
|
|
6913
|
+
}
|
|
6914
|
+
}
|
|
6915
|
+
}
|
|
6916
|
+
setTimeScale(value) {
|
|
6917
|
+
this.beforeOperation();
|
|
6918
|
+
if (!Number.isFinite(value)) throw new Error("Native mixer speed must be finite.");
|
|
6919
|
+
this.binding.mixer.timeScale = value;
|
|
6920
|
+
}
|
|
6921
|
+
fadeIn(handle, seconds) {
|
|
6922
|
+
this.control(handle, { type: "fadeIn", seconds });
|
|
6923
|
+
}
|
|
6924
|
+
fadeOut(handle, seconds) {
|
|
6925
|
+
this.control(handle, { type: "fadeOut", seconds });
|
|
6926
|
+
}
|
|
6927
|
+
/** Edit authored samples, retaining the native action and its loop/fade progress. */
|
|
6928
|
+
replaceClip(handle, clip) {
|
|
6929
|
+
this.beforeOperation();
|
|
6930
|
+
clip = withComponentTracks(clip);
|
|
6931
|
+
const resource = this.resources.get(handle);
|
|
6932
|
+
if (!resource) throw new Error("Unknown, foreign or stale playback handle.");
|
|
6933
|
+
const [ir] = serializeAnimationClips(this.binding.model, [clip], this.binding.inspection);
|
|
6934
|
+
if (ir.tracks.length !== clip.tracks.length) throw new Error("Every edited track must resolve on the bound model.");
|
|
6935
|
+
const native = cloneWithConcreteTrackNames(clip, ir.tracks, this.binding.inspection);
|
|
6936
|
+
if (native.tracks.length !== resource.clip.tracks.length || native.tracks.some((track, index) => {
|
|
6937
|
+
const old = resource.clip.tracks[index];
|
|
6938
|
+
return track.name !== old.name || track.ValueTypeName !== old.ValueTypeName || sampleSize(track) !== sampleSize(old);
|
|
6939
|
+
})) throw new Error("Editing samples must preserve track bindings; play a new clip to change its bindings.");
|
|
6940
|
+
const editable = resource.action;
|
|
6941
|
+
if (!editable || !Array.isArray(editable._interpolants) || editable._interpolants.length !== native.tracks.length) {
|
|
6942
|
+
throw new Error("This Three version does not support editing native action samples.");
|
|
6943
|
+
}
|
|
6944
|
+
this.dispatch(this.session.replace_clip(handle, JSON.stringify(ir)), native);
|
|
6945
|
+
}
|
|
6946
|
+
/** Native state for the owning adapter; never exposed through Polymer. */
|
|
6947
|
+
getAction(handle) {
|
|
6948
|
+
return this.resources.get(handle)?.action;
|
|
6949
|
+
}
|
|
6950
|
+
/** Deliver native completion after the borrowed mixer has finished sampling. */
|
|
6951
|
+
flushEvents() {
|
|
6952
|
+
if (this.disposed) return;
|
|
6953
|
+
this.notificationScheduled = false;
|
|
6954
|
+
for (const [handle, resource] of this.resources) {
|
|
6955
|
+
if (resource.fadingOut && resource.action?.getEffectiveWeight() === 0) {
|
|
6956
|
+
resource.fadingOut = false;
|
|
6957
|
+
this.notifications.push({ type: "cancelled", handle });
|
|
6625
6958
|
}
|
|
6626
|
-
|
|
6959
|
+
}
|
|
6960
|
+
this.flushNotifications();
|
|
6961
|
+
}
|
|
6962
|
+
subscribe(listener) {
|
|
6963
|
+
if (this.disposed) throw new Error("Native playback connector is disposed.");
|
|
6964
|
+
this.listeners.add(listener);
|
|
6965
|
+
return () => {
|
|
6966
|
+
this.listeners.delete(listener);
|
|
6627
6967
|
};
|
|
6628
|
-
return { positive: magnitude(positive), negative: magnitude(negative) };
|
|
6629
6968
|
}
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
const
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
yaw,
|
|
6655
|
-
pitch,
|
|
6656
|
-
roll,
|
|
6657
|
-
reference: new Quaternion(rotation.x, rotation.y, rotation.z, rotation.w),
|
|
6658
|
-
referenceParent,
|
|
6659
|
-
referenceScale: vector(reference.transform.scale)
|
|
6969
|
+
dispose() {
|
|
6970
|
+
if (this.disposed) return;
|
|
6971
|
+
this.retryPending();
|
|
6972
|
+
if (!this.sessionDisposed) {
|
|
6973
|
+
const batch = this.session.dispose();
|
|
6974
|
+
this.sessionDisposed = true;
|
|
6975
|
+
this.dispatch(batch);
|
|
6976
|
+
}
|
|
6977
|
+
this.binding.mixer.removeEventListener("finished", this.finished);
|
|
6978
|
+
this.rendering.dispose();
|
|
6979
|
+
this.notifications.length = 0;
|
|
6980
|
+
this.listeners.clear();
|
|
6981
|
+
this.session.free();
|
|
6982
|
+
this.disposed = true;
|
|
6983
|
+
}
|
|
6984
|
+
pauseFade(resource) {
|
|
6985
|
+
const action = resource.action;
|
|
6986
|
+
const fade = action?._weightInterpolant;
|
|
6987
|
+
if (!action || !fade) return;
|
|
6988
|
+
resource.pausedFade = {
|
|
6989
|
+
seconds: Math.max(0, fade.parameterPositions[1] - resource.binding.mixer.time),
|
|
6990
|
+
from: fade.evaluate(resource.binding.mixer.time)[0],
|
|
6991
|
+
to: fade.sampleValues[1],
|
|
6992
|
+
weight: action.weight
|
|
6660
6993
|
};
|
|
6994
|
+
action.stopFading();
|
|
6995
|
+
action.setEffectiveWeight(resource.pausedFade.weight * resource.pausedFade.from);
|
|
6996
|
+
}
|
|
6997
|
+
resumeFade(resource) {
|
|
6998
|
+
const action = resource.action;
|
|
6999
|
+
const fade = resource.pausedFade;
|
|
7000
|
+
if (!action || !fade) return;
|
|
7001
|
+
resource.pausedFade = void 0;
|
|
7002
|
+
action.setEffectiveWeight(fade.weight);
|
|
7003
|
+
action.fadeIn(fade.seconds);
|
|
7004
|
+
const interpolant = action._weightInterpolant;
|
|
7005
|
+
interpolant.sampleValues[0] = fade.from;
|
|
7006
|
+
interpolant.sampleValues[1] = fade.to;
|
|
7007
|
+
}
|
|
7008
|
+
beforeOperation() {
|
|
7009
|
+
if (this.disposed || this.sessionDisposed) throw new Error("Native playback connector is disposed.");
|
|
7010
|
+
this.retryPending();
|
|
7011
|
+
}
|
|
7012
|
+
retryPending() {
|
|
7013
|
+
if (this.pending.length) this.drain();
|
|
7014
|
+
}
|
|
7015
|
+
dispatch(serialized, clip, afterCommands) {
|
|
7016
|
+
const batch = JSON.parse(serialized);
|
|
7017
|
+
this.pending.push({ batch, nextCommand: 0, clip, afterCommands });
|
|
7018
|
+
this.drain();
|
|
7019
|
+
return batch;
|
|
7020
|
+
}
|
|
7021
|
+
drain() {
|
|
7022
|
+
const errors = [];
|
|
7023
|
+
this.depth += 1;
|
|
7024
|
+
try {
|
|
7025
|
+
while (this.pending.length) {
|
|
7026
|
+
const pending = this.pending[0];
|
|
7027
|
+
while (pending.nextCommand < pending.batch.commands.length) {
|
|
7028
|
+
const command = pending.batch.commands[pending.nextCommand];
|
|
7029
|
+
try {
|
|
7030
|
+
this.execute(command, pending.clip);
|
|
7031
|
+
} catch (error) {
|
|
7032
|
+
if (command.type === "release") throw asError(error);
|
|
7033
|
+
const failure = asError(error);
|
|
7034
|
+
errors.push(failure);
|
|
7035
|
+
this.notifications.push({ type: "error", handle: command.handle, message: failure.message || "Native operation failed." });
|
|
7036
|
+
}
|
|
7037
|
+
pending.nextCommand += 1;
|
|
7038
|
+
}
|
|
7039
|
+
pending.afterCommands?.();
|
|
7040
|
+
this.pending.shift();
|
|
7041
|
+
for (const event of pending.batch.events) {
|
|
7042
|
+
for (const listener of [...this.listeners]) {
|
|
7043
|
+
try {
|
|
7044
|
+
listener(event);
|
|
7045
|
+
} catch (error) {
|
|
7046
|
+
const failure = asError(error);
|
|
7047
|
+
queueMicrotask(() => {
|
|
7048
|
+
if (this.onError) this.onError(failure);
|
|
7049
|
+
else throw failure;
|
|
7050
|
+
});
|
|
7051
|
+
}
|
|
7052
|
+
}
|
|
7053
|
+
}
|
|
7054
|
+
}
|
|
7055
|
+
} finally {
|
|
7056
|
+
this.depth -= 1;
|
|
7057
|
+
}
|
|
7058
|
+
if (this.depth === 0 && !this.flushingNotifications) this.flushNotifications();
|
|
7059
|
+
if (errors.length) throw errors[0];
|
|
7060
|
+
}
|
|
7061
|
+
execute(command, preparedClip) {
|
|
7062
|
+
if (command.type === "release") {
|
|
7063
|
+
const resource2 = this.resources.get(command.handle);
|
|
7064
|
+
if (!resource2) return;
|
|
7065
|
+
resource2.action?.stop();
|
|
7066
|
+
resource2.binding.mixer.uncacheAction(resource2.clip, resource2.binding.model);
|
|
7067
|
+
resource2.binding.mixer.uncacheClip(resource2.clip);
|
|
7068
|
+
if (resource2.action) this.actionHandles.delete(resource2.action);
|
|
7069
|
+
this.resources.delete(command.handle);
|
|
7070
|
+
try {
|
|
7071
|
+
this.onRelease?.(command.handle);
|
|
7072
|
+
} catch (error) {
|
|
7073
|
+
const failure = asError(error);
|
|
7074
|
+
queueMicrotask(() => {
|
|
7075
|
+
if (this.onError) this.onError(failure);
|
|
7076
|
+
else throw failure;
|
|
7077
|
+
});
|
|
7078
|
+
}
|
|
7079
|
+
return;
|
|
7080
|
+
}
|
|
7081
|
+
if (command.type === "replaceClip") {
|
|
7082
|
+
const resource2 = this.resources.get(command.handle);
|
|
7083
|
+
if (!resource2 || !preparedClip) throw new Error("Native clip edit has no owned resource.");
|
|
7084
|
+
const action2 = resource2.action;
|
|
7085
|
+
const tracks = preparedClip.tracks.map((track) => track.clone());
|
|
7086
|
+
const interpolants = tracks.map((track, index) => {
|
|
7087
|
+
const interpolant = track.createInterpolant(action2._interpolants[index].resultBuffer);
|
|
7088
|
+
if (interpolant.settings) Object.assign(action2._interpolantSettings, interpolant.settings);
|
|
7089
|
+
interpolant.settings = action2._interpolantSettings;
|
|
7090
|
+
return interpolant;
|
|
7091
|
+
});
|
|
7092
|
+
resource2.clip.tracks = tracks;
|
|
7093
|
+
action2._interpolants = interpolants;
|
|
7094
|
+
return;
|
|
7095
|
+
}
|
|
7096
|
+
if (command.type === "play") {
|
|
7097
|
+
if (!preparedClip) throw new Error("Native playback has no prepared clip.");
|
|
7098
|
+
const resource2 = { clip: preparedClip, binding: this.binding };
|
|
7099
|
+
this.resources.set(command.handle, resource2);
|
|
7100
|
+
const settings = command.settings;
|
|
7101
|
+
const action2 = this.binding.mixer.clipAction(preparedClip, this.binding.model, blendMode(settings.blendMode));
|
|
7102
|
+
resource2.action = action2;
|
|
7103
|
+
this.actionHandles.set(action2, command.handle);
|
|
7104
|
+
action2.setLoop(loopMode(settings.loop.mode), settings.loop.count ?? Infinity);
|
|
7105
|
+
action2.clampWhenFinished = settings.finalPose === "hold";
|
|
7106
|
+
action2.setEffectiveTimeScale(settings.speed);
|
|
7107
|
+
action2.setEffectiveWeight(settings.weight);
|
|
7108
|
+
action2.time = settings.startSeconds;
|
|
7109
|
+
if (!this.renderingEnabled) {
|
|
7110
|
+
resource2.suspendedPaused = false;
|
|
7111
|
+
action2.paused = true;
|
|
7112
|
+
}
|
|
7113
|
+
action2.play();
|
|
7114
|
+
return;
|
|
7115
|
+
}
|
|
7116
|
+
const resource = this.resources.get(command.handle);
|
|
7117
|
+
const action = resource?.action;
|
|
7118
|
+
if (!resource || !action) throw new Error("Native playback action is unavailable.");
|
|
7119
|
+
const control = command.control;
|
|
7120
|
+
switch (control.type) {
|
|
7121
|
+
case "pause":
|
|
7122
|
+
resource.explicitlyPaused = true;
|
|
7123
|
+
this.pauseFade(resource);
|
|
7124
|
+
action.paused = true;
|
|
7125
|
+
if (!this.renderingEnabled) this.resources.get(command.handle).suspendedPaused = true;
|
|
7126
|
+
break;
|
|
7127
|
+
case "resume":
|
|
7128
|
+
resource.explicitlyPaused = false;
|
|
7129
|
+
if (this.renderingEnabled) {
|
|
7130
|
+
action.paused = false;
|
|
7131
|
+
this.resumeFade(resource);
|
|
7132
|
+
} else this.resources.get(command.handle).suspendedPaused = false;
|
|
7133
|
+
break;
|
|
7134
|
+
case "seek":
|
|
7135
|
+
action.time = control.seconds;
|
|
7136
|
+
break;
|
|
7137
|
+
case "setSpeed":
|
|
7138
|
+
action.setEffectiveTimeScale(control.speed);
|
|
7139
|
+
break;
|
|
7140
|
+
case "setWeight":
|
|
7141
|
+
resource.pausedFade = void 0;
|
|
7142
|
+
action.setEffectiveWeight(control.weight);
|
|
7143
|
+
this.resources.get(command.handle).fadingOut = false;
|
|
7144
|
+
break;
|
|
7145
|
+
case "setBlendMode":
|
|
7146
|
+
action.blendMode = blendMode(control.blendMode);
|
|
7147
|
+
break;
|
|
7148
|
+
case "setLoop":
|
|
7149
|
+
action.setLoop(loopMode(control.loop.mode), control.loop.count ?? Infinity);
|
|
7150
|
+
break;
|
|
7151
|
+
case "setFinalPose":
|
|
7152
|
+
action.clampWhenFinished = control.finalPose === "hold";
|
|
7153
|
+
break;
|
|
7154
|
+
case "fadeIn":
|
|
7155
|
+
resource.pausedFade = void 0;
|
|
7156
|
+
action.fadeIn(control.seconds);
|
|
7157
|
+
resource.fadingOut = false;
|
|
7158
|
+
if (resource.explicitlyPaused || !this.renderingEnabled) this.pauseFade(resource);
|
|
7159
|
+
break;
|
|
7160
|
+
case "fadeOut":
|
|
7161
|
+
resource.pausedFade = void 0;
|
|
7162
|
+
if (control.seconds === 0) this.notifications.push({ type: "cancelled", handle: command.handle });
|
|
7163
|
+
else {
|
|
7164
|
+
action.fadeOut(control.seconds);
|
|
7165
|
+
resource.fadingOut = true;
|
|
7166
|
+
if (resource.explicitlyPaused || !this.renderingEnabled) this.pauseFade(resource);
|
|
7167
|
+
}
|
|
7168
|
+
break;
|
|
7169
|
+
case "stop":
|
|
7170
|
+
throw new Error("Rust must translate stop into a resource release.");
|
|
7171
|
+
}
|
|
6661
7172
|
}
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
7173
|
+
flushNotifications() {
|
|
7174
|
+
if (this.flushingNotifications || this.depth > 0 || this.disposed || this.notificationScheduled) return;
|
|
7175
|
+
this.flushingNotifications = true;
|
|
7176
|
+
try {
|
|
7177
|
+
while (this.notifications.length) {
|
|
7178
|
+
const event = this.notifications.shift();
|
|
7179
|
+
this.dispatch(this.session.notify(JSON.stringify(event)));
|
|
6668
7180
|
}
|
|
7181
|
+
} finally {
|
|
7182
|
+
this.flushingNotifications = false;
|
|
6669
7183
|
}
|
|
6670
|
-
this.saved.clear();
|
|
6671
|
-
this.model.updateMatrixWorld(true);
|
|
6672
7184
|
}
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
7185
|
+
};
|
|
7186
|
+
|
|
7187
|
+
// three/character.ts
|
|
7188
|
+
var json2 = (value) => JSON.stringify(value ?? {});
|
|
7189
|
+
var targetKey = (target) => JSON.stringify([target.kind, target.meshId, target.morphTargetId, target.boneId, target.objectId, target.property]);
|
|
7190
|
+
var copy = (value) => JSON.parse(JSON.stringify(value));
|
|
7191
|
+
var parse = (value) => JSON.parse(value);
|
|
7192
|
+
var finite2 = (value) => typeof value === "number" && Number.isFinite(value);
|
|
7193
|
+
var intensity = (options, fallback = 1) => {
|
|
7194
|
+
const value = options.intensityScale ?? options.intensity ?? options.weight;
|
|
7195
|
+
return finite2(value) ? Math.max(0, Math.min(2, value)) : fallback;
|
|
7196
|
+
};
|
|
7197
|
+
var presetId = (value) => value?.trim().toLowerCase() || "cc4";
|
|
7198
|
+
function supportsRustEmbodyPreset(value) {
|
|
7199
|
+
return requireInitializedEmbodyCore().has_preset(presetId(value));
|
|
7200
|
+
}
|
|
7201
|
+
var Embody = class _Embody {
|
|
7202
|
+
constructor(config = {}) {
|
|
7203
|
+
this.config = config;
|
|
7204
|
+
__publicField(this, "meshes", []);
|
|
7205
|
+
__publicField(this, "meshByName", /* @__PURE__ */ new Map());
|
|
7206
|
+
__publicField(this, "bones", {});
|
|
7207
|
+
__publicField(this, "wasm", requireInitializedEmbodyCore());
|
|
7208
|
+
__publicField(this, "core");
|
|
7209
|
+
__publicField(this, "inspector", new ThreeModelInspector());
|
|
7210
|
+
__publicField(this, "applier", new ThreeFrameApplier());
|
|
7211
|
+
__publicField(this, "references", /* @__PURE__ */ new WeakMap());
|
|
7212
|
+
__publicField(this, "referenceBindings", /* @__PURE__ */ new Map());
|
|
7213
|
+
__publicField(this, "boundModel");
|
|
7214
|
+
__publicField(this, "inspection");
|
|
7215
|
+
__publicField(this, "connector");
|
|
7216
|
+
__publicField(this, "profile");
|
|
7217
|
+
__publicField(this, "profileSource");
|
|
7218
|
+
__publicField(this, "profileMode");
|
|
7219
|
+
__publicField(this, "preset");
|
|
7220
|
+
__publicField(this, "sources", /* @__PURE__ */ new Map());
|
|
7221
|
+
__publicField(this, "playbacks", /* @__PURE__ */ new Map());
|
|
7222
|
+
__publicField(this, "current", /* @__PURE__ */ new Map());
|
|
7223
|
+
__publicField(this, "playDepth", 0);
|
|
7224
|
+
__publicField(this, "pendingEvents", []);
|
|
7225
|
+
__publicField(this, "bindingGeneration", 0);
|
|
7226
|
+
__publicField(this, "disposed", false);
|
|
7227
|
+
__publicField(this, "rendering", true);
|
|
7228
|
+
__publicField(this, "timeScale", 1);
|
|
7229
|
+
__publicField(this, "nextLiveTarget", 0);
|
|
7230
|
+
__publicField(this, "liveTargets", /* @__PURE__ */ new Map());
|
|
7231
|
+
__publicField(this, "hairObjects", /* @__PURE__ */ new Map());
|
|
7232
|
+
__publicField(this, "hairConfig", {});
|
|
7233
|
+
__publicField(this, "hairAppearance", {
|
|
7234
|
+
hairColor: copy(DEFAULT_HAIR_COLOR_APPEARANCE),
|
|
7235
|
+
eyebrowColor: copy(DEFAULT_HAIR_COLOR_APPEARANCE),
|
|
7236
|
+
showOutline: false,
|
|
7237
|
+
outlineColor: "#000000",
|
|
7238
|
+
outlineOpacity: 1
|
|
6677
7239
|
});
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
7240
|
+
const mode = config.profileMode ?? "preset";
|
|
7241
|
+
if (mode !== "profile" && mode !== "preset") throw new Error(`Unknown profile mode: ${mode}`);
|
|
7242
|
+
if (mode === "profile" && !config.profile) throw new Error("Resolved profile mode requires a profile object.");
|
|
7243
|
+
this.profileMode = mode;
|
|
7244
|
+
this.preset = presetId(config.presetId ?? config.presetType);
|
|
7245
|
+
if (mode === "preset" && !this.wasm.has_preset(this.preset)) throw new Error(`Unknown Embody preset: ${this.preset}`);
|
|
7246
|
+
this.profileSource = this.validateProfile(config.profile ?? {});
|
|
7247
|
+
this.profile = this.resolveProfile(this.profileSource);
|
|
7248
|
+
this.core = new this.wasm.RuntimeCore(0);
|
|
7249
|
+
}
|
|
7250
|
+
get model() {
|
|
7251
|
+
return this.boundModel;
|
|
7252
|
+
}
|
|
7253
|
+
static async create(config = {}) {
|
|
7254
|
+
await initEmbodyCore();
|
|
7255
|
+
return new _Embody(config);
|
|
7256
|
+
}
|
|
7257
|
+
assertAlive() {
|
|
7258
|
+
if (this.disposed) throw new Error("Character is disposed.");
|
|
7259
|
+
}
|
|
7260
|
+
requireModel() {
|
|
7261
|
+
this.assertAlive();
|
|
7262
|
+
if (!this.boundModel) throw new Error("Bind a character model with onReady before using this operation.");
|
|
7263
|
+
return this.boundModel;
|
|
7264
|
+
}
|
|
7265
|
+
requireConnector() {
|
|
7266
|
+
this.requireModel();
|
|
7267
|
+
if (!this.connector) throw new Error("Character playback is not bound.");
|
|
7268
|
+
return this.connector;
|
|
7269
|
+
}
|
|
7270
|
+
validateProfile(value) {
|
|
7271
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Embody profile must be a JSON object.");
|
|
7272
|
+
return copy(value);
|
|
7273
|
+
}
|
|
7274
|
+
resolveProfile(value) {
|
|
7275
|
+
return this.profileMode === "profile" ? copy(value) : parse(this.wasm.merge_embedded_preset(this.preset, json2(value)));
|
|
7276
|
+
}
|
|
7277
|
+
onReady(options) {
|
|
7278
|
+
this.assertAlive();
|
|
7279
|
+
const model = options.model;
|
|
7280
|
+
if (!model?.isObject3D) throw new Error("onReady requires a Three Object3D model.");
|
|
7281
|
+
const reference = this.references.get(model) ?? options.referencePose ?? (!this.boundModel ? this.config.referencePose : void 0) ?? captureModelReferencePose(model);
|
|
7282
|
+
const inspection = this.inspector.inspectModel(model, { meshes: options.meshes, profile: this.profile, referencePose: reference });
|
|
7283
|
+
this.bind(model, reference, inspection, this.profileSource, this.profile);
|
|
7284
|
+
if (options.animations) this.loadAnimationClips(options.animations);
|
|
7285
|
+
}
|
|
7286
|
+
bind(model, reference, inspection, source, profile, preserveLiveState = true) {
|
|
7287
|
+
const referenceBindings = bindModelReferencePose(model, reference);
|
|
7288
|
+
const runtimeDescriptor = {
|
|
7289
|
+
...inspection.descriptor,
|
|
7290
|
+
morphTargets: inspection.descriptor.morphTargets.map((morph) => {
|
|
7291
|
+
const binding = inspection.morphBindings.get(morph.id);
|
|
7292
|
+
const baseline = binding && referenceBindings.get(binding.mesh)?.morphInfluences?.[binding.index];
|
|
7293
|
+
return { ...morph, initialValue: baseline ?? morph.initialValue };
|
|
7294
|
+
})
|
|
6685
7295
|
};
|
|
7296
|
+
const replacingModel = !!this.boundModel && this.boundModel !== model;
|
|
7297
|
+
const core2 = new this.wasm.RuntimeCore(0);
|
|
7298
|
+
try {
|
|
7299
|
+
if (this.profileMode === "profile") core2.configure_with_profile(json2(source), json2(runtimeDescriptor));
|
|
7300
|
+
else core2.configure_with_preset(this.preset, json2(source), json2(runtimeDescriptor));
|
|
7301
|
+
if (preserveLiveState && this.boundModel) core2.copy_live_state_from(this.core);
|
|
7302
|
+
for (const registered of replacingModel ? [] : this.sources.values()) {
|
|
7303
|
+
if (registered.kind === "native") {
|
|
7304
|
+
const [clip] = serializeAnimationClips(model, [registered.clip], inspection);
|
|
7305
|
+
core2.register_animation_clip(json2(clip), "baked");
|
|
7306
|
+
}
|
|
7307
|
+
}
|
|
7308
|
+
} catch (error) {
|
|
7309
|
+
core2.free();
|
|
7310
|
+
throw error;
|
|
7311
|
+
}
|
|
7312
|
+
try {
|
|
7313
|
+
this.connector?.dispose();
|
|
7314
|
+
} catch (error) {
|
|
7315
|
+
core2.free();
|
|
7316
|
+
throw error;
|
|
7317
|
+
}
|
|
7318
|
+
this.core.free();
|
|
7319
|
+
this.core = core2;
|
|
7320
|
+
if (replacingModel) this.sources.clear();
|
|
7321
|
+
this.boundModel = model;
|
|
7322
|
+
this.inspection = inspection;
|
|
7323
|
+
this.referenceBindings = referenceBindings;
|
|
7324
|
+
this.references.set(model, reference);
|
|
7325
|
+
this.profileSource = source;
|
|
7326
|
+
this.profile = profile;
|
|
7327
|
+
this.bindingGeneration += 1;
|
|
7328
|
+
this.playbacks.clear();
|
|
7329
|
+
this.current.clear();
|
|
7330
|
+
this.liveTargets.clear();
|
|
7331
|
+
this.meshes.splice(0, this.meshes.length, ...inspection.morphMeshes.length ? inspection.morphMeshes : inspection.allMeshes);
|
|
7332
|
+
this.meshByName = inspection.meshByName;
|
|
7333
|
+
this.bones = inspection.bones;
|
|
7334
|
+
this.applier.setBindings(inspection);
|
|
7335
|
+
this.applier.applyMeshMaterialConfigs(model, profile.meshes ?? {});
|
|
7336
|
+
const session = new this.wasm.NativePlaybackSession();
|
|
7337
|
+
try {
|
|
7338
|
+
this.connector = new ThreeNativePlaybackConnector(session, {
|
|
7339
|
+
model,
|
|
7340
|
+
inspection,
|
|
7341
|
+
onRelease: (id) => {
|
|
7342
|
+
const playback = this.playbacks.get(id);
|
|
7343
|
+
if (playback?.terminal) this.forget(playback);
|
|
7344
|
+
}
|
|
7345
|
+
});
|
|
7346
|
+
} catch (error) {
|
|
7347
|
+
session.free();
|
|
7348
|
+
throw error;
|
|
7349
|
+
}
|
|
7350
|
+
this.connector.rebind(model.uuid, String(this.bindingGeneration));
|
|
7351
|
+
this.connector.setRendering(this.rendering);
|
|
7352
|
+
this.connector.setTimeScale(this.timeScale);
|
|
7353
|
+
this.connector.subscribe((event) => this.onPlaybackEvent(event));
|
|
7354
|
+
this.hairConfig = parse(this.core.get_hair_config_json());
|
|
7355
|
+
this.registerHairObjects(inspection.allMeshes.filter((mesh) => ["hair", "eyebrow"].includes(this.meshCategory(mesh))));
|
|
7356
|
+
if (preserveLiveState) this.commitLive();
|
|
7357
|
+
}
|
|
7358
|
+
bindModel(meshes) {
|
|
7359
|
+
const model = this.requireModel();
|
|
7360
|
+
const reference = this.references.get(model);
|
|
7361
|
+
const inspection = this.inspector.inspectModel(model, { meshes, profile: this.profile, referencePose: reference });
|
|
7362
|
+
this.bind(model, reference, inspection, this.profileSource, this.profile);
|
|
7363
|
+
}
|
|
7364
|
+
extendReferencePose() {
|
|
7365
|
+
const model = this.requireModel();
|
|
7366
|
+
const reference = extendModelReferencePose(model, this.references.get(model));
|
|
7367
|
+
const inspection = this.inspector.inspectModel(model, { profile: this.profile, referencePose: reference });
|
|
7368
|
+
this.bind(model, reference, inspection, this.profileSource, this.profile);
|
|
7369
|
+
return reference;
|
|
7370
|
+
}
|
|
7371
|
+
setProfile(value) {
|
|
7372
|
+
this.assertAlive();
|
|
7373
|
+
const source = this.validateProfile(value);
|
|
7374
|
+
const profile = this.resolveProfile(source);
|
|
7375
|
+
if (!this.boundModel) {
|
|
7376
|
+
this.profileSource = source;
|
|
7377
|
+
this.profile = profile;
|
|
7378
|
+
return;
|
|
7379
|
+
}
|
|
7380
|
+
const reference = this.references.get(this.boundModel);
|
|
7381
|
+
const inspection = this.inspector.inspectModel(this.boundModel, { profile, referencePose: reference });
|
|
7382
|
+
this.bind(this.boundModel, reference, inspection, source, profile, false);
|
|
6686
7383
|
}
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
return capacity > EPSILON ? bounded(degrees / capacity) : 0;
|
|
7384
|
+
getProfile() {
|
|
7385
|
+
return this.profile;
|
|
6690
7386
|
}
|
|
6691
|
-
|
|
6692
|
-
return
|
|
7387
|
+
getProfileMode() {
|
|
7388
|
+
return this.profileMode;
|
|
6693
7389
|
}
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
const pitch = pitchDegrees * Math.PI / 180;
|
|
6697
|
-
return new Vector3(Math.sin(yaw) * Math.cos(pitch), Math.sin(pitch), Math.cos(yaw) * Math.cos(pitch)).applyQuaternion(this.model.getWorldQuaternion(new Quaternion())).normalize();
|
|
7390
|
+
getPresetId() {
|
|
7391
|
+
return this.profileMode === "preset" ? this.preset : null;
|
|
6698
7392
|
}
|
|
6699
|
-
|
|
6700
|
-
return
|
|
7393
|
+
supportsPreset(value) {
|
|
7394
|
+
return supportsRustEmbodyPreset(value);
|
|
6701
7395
|
}
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
const
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
7396
|
+
onPlaybackEvent(event) {
|
|
7397
|
+
if (this.playDepth) {
|
|
7398
|
+
this.pendingEvents.push(event);
|
|
7399
|
+
return;
|
|
7400
|
+
}
|
|
7401
|
+
const playback = this.playbacks.get(event.handle);
|
|
7402
|
+
if (!playback) return;
|
|
7403
|
+
playback.terminal = true;
|
|
7404
|
+
if (!playback.connector.getAction(playback.id)) {
|
|
7405
|
+
this.playbacks.delete(playback.id);
|
|
7406
|
+
if (this.current.get(playback.source.name) === playback) this.current.delete(playback.source.name);
|
|
7407
|
+
}
|
|
7408
|
+
playback.notify({ ...event, actionId: event.handle, clipName: playback.source.name });
|
|
7409
|
+
}
|
|
7410
|
+
compile(source, options) {
|
|
7411
|
+
const buildOptions = { ..."options" in source ? source.options : {}, ...options, intensityScale: intensity(options) };
|
|
7412
|
+
switch (source.kind) {
|
|
7413
|
+
case "curves":
|
|
7414
|
+
return parse(this.core.build_clip(source.name, json2(source.input), json2(buildOptions)));
|
|
7415
|
+
case "typed":
|
|
7416
|
+
return parse(this.core.build_typed_clip(source.name, json2(source.input), json2(buildOptions)));
|
|
7417
|
+
case "semantic":
|
|
7418
|
+
return parse(this.core.build_semantic_clip(source.name, json2(source.input), json2(buildOptions)));
|
|
7419
|
+
case "compiled":
|
|
7420
|
+
return source.clip;
|
|
7421
|
+
case "native":
|
|
7422
|
+
throw new Error("Native animation sources do not require semantic compilation.");
|
|
7423
|
+
}
|
|
7424
|
+
}
|
|
7425
|
+
restValues(track) {
|
|
7426
|
+
const model = this.requireModel();
|
|
7427
|
+
const parsed = PropertyBinding.parseTrackName(track.name);
|
|
7428
|
+
let object = PropertyBinding.findNode(model, parsed.nodeName);
|
|
7429
|
+
if (parsed.objectName === "bones" && object) {
|
|
7430
|
+
const skeleton = object.skeleton;
|
|
7431
|
+
object = skeleton?.bones.find((bone) => bone.name === String(parsed.objectIndex)) ?? skeleton?.bones[Number(parsed.objectIndex)];
|
|
7432
|
+
}
|
|
7433
|
+
if (!object) return void 0;
|
|
7434
|
+
const reference = this.referenceBindings.get(object);
|
|
7435
|
+
if (!reference) return void 0;
|
|
7436
|
+
switch (parsed.propertyName) {
|
|
7437
|
+
case "quaternion":
|
|
7438
|
+
return Object.values(reference.transform.rotation);
|
|
7439
|
+
case "rotation": {
|
|
7440
|
+
const rotation = reference.transform.rotation;
|
|
7441
|
+
const euler = reference.rotationEuler ?? new Euler().setFromQuaternion(new Quaternion(rotation.x, rotation.y, rotation.z, rotation.w), reference.rotationOrder);
|
|
7442
|
+
const axis = parsed.propertyIndex;
|
|
7443
|
+
return axis === "x" || axis === "y" || axis === "z" ? [euler[axis]] : [euler.x, euler.y, euler.z];
|
|
7444
|
+
}
|
|
7445
|
+
case "position":
|
|
7446
|
+
return Object.values(reference.transform.position);
|
|
7447
|
+
case "scale":
|
|
7448
|
+
return Object.values(reference.transform.scale);
|
|
7449
|
+
case "weights":
|
|
7450
|
+
case "morphTargetInfluences": {
|
|
7451
|
+
const mesh = object;
|
|
7452
|
+
const index = typeof parsed.propertyIndex === "string" && !/^\d+$/.test(parsed.propertyIndex) ? mesh.morphTargetDictionary?.[parsed.propertyIndex] : Number(parsed.propertyIndex);
|
|
7453
|
+
return [reference.morphInfluences?.[index ?? -1] ?? 0];
|
|
7454
|
+
}
|
|
7455
|
+
default:
|
|
7456
|
+
return void 0;
|
|
7457
|
+
}
|
|
7458
|
+
}
|
|
7459
|
+
materialize(source, options, inheritedStarts = /* @__PURE__ */ new Map()) {
|
|
7460
|
+
if (!this.inspection) throw new Error("Character has no model inspection.");
|
|
7461
|
+
const nativeSource = source.kind === "native";
|
|
7462
|
+
let ir;
|
|
7463
|
+
if (!nativeSource) {
|
|
7464
|
+
ir = this.compile(source, options);
|
|
7465
|
+
}
|
|
7466
|
+
const clip = nativeSource ? withComponentTracks(source.clip).clone() : createAnimationClipFromClipIR(ir, this.inspection);
|
|
7467
|
+
if (ir) {
|
|
7468
|
+
const predecessor = this.current.get(source.name);
|
|
7469
|
+
const outgoing = predecessor?.connector.getAction(predecessor.id);
|
|
7470
|
+
for (let index = 0; index < ir.tracks.length; index += 1) {
|
|
7471
|
+
if (!ir.tracks[index].inheritStart) continue;
|
|
7472
|
+
const track = clip.tracks[index];
|
|
7473
|
+
if (!track) throw new Error("Every inherited track must bind to the character.");
|
|
7474
|
+
const startKey = `${index}:${track.name}`;
|
|
7475
|
+
let previous = inheritedStarts.get(startKey);
|
|
7476
|
+
if (!previous && options.blendMode === "additive") {
|
|
7477
|
+
const rest = this.restValues(track);
|
|
7478
|
+
const candidates = outgoing?.getClip().tracks;
|
|
7479
|
+
const oldTrack = candidates?.[index]?.name === track.name ? candidates[index] : candidates?.find((candidate) => candidate.name === track.name);
|
|
7480
|
+
if (oldTrack && outgoing) {
|
|
7481
|
+
previous = Array.from(oldTrack.createInterpolant().evaluate(outgoing.time));
|
|
7482
|
+
if (outgoing.blendMode === AdditiveAnimationBlendMode && rest) {
|
|
7483
|
+
previous = track.ValueTypeName === "quaternion" ? new Quaternion().fromArray(rest).multiply(new Quaternion().fromArray(previous)).toArray() : previous.map((value, axis) => value + rest[axis]);
|
|
7484
|
+
}
|
|
7485
|
+
} else if (rest) previous = rest;
|
|
7486
|
+
}
|
|
7487
|
+
if (previous) track.values.set(previous, 0);
|
|
7488
|
+
inheritedStarts.set(startKey, previous ?? Array.from(track.values.subarray(0, track.getValueSize())));
|
|
7489
|
+
}
|
|
7490
|
+
}
|
|
7491
|
+
const authoredAdditive = clip.blendMode === AdditiveAnimationBlendMode;
|
|
7492
|
+
const scale = intensity(options);
|
|
7493
|
+
const additive = options.blendMode === "additive" || options.blendMode === void 0 && authoredAdditive;
|
|
7494
|
+
this.applyEasing(clip, options.easing ?? "linear", nativeSource && (scale !== 1 || additive !== authoredAdditive));
|
|
7495
|
+
if (nativeSource && scale !== 1) {
|
|
7496
|
+
for (const track of clip.tracks) {
|
|
7497
|
+
const rest = authoredAdditive ? track.ValueTypeName === "quaternion" ? [0, 0, 0, 1] : Array(track.getValueSize()).fill(0) : this.restValues(track);
|
|
7498
|
+
if (!rest) continue;
|
|
7499
|
+
const stride = track.getValueSize();
|
|
7500
|
+
const cubic = track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true;
|
|
7501
|
+
const width = cubic ? stride / 3 : stride;
|
|
7502
|
+
for (let offset = 0; offset < track.values.length; offset += stride) {
|
|
7503
|
+
const sample = offset + (cubic ? width : 0);
|
|
7504
|
+
if (track.ValueTypeName === "quaternion") {
|
|
7505
|
+
const neutral = new Quaternion().fromArray(rest);
|
|
7506
|
+
const value = new Quaternion().fromArray(track.values, sample);
|
|
7507
|
+
neutral.slerp(value, scale).toArray(track.values, sample);
|
|
7508
|
+
} else {
|
|
7509
|
+
for (let axis = 0; axis < width; axis += 1) {
|
|
7510
|
+
track.values[sample + axis] = rest[axis] + (track.values[sample + axis] - rest[axis]) * scale;
|
|
7511
|
+
if (cubic) {
|
|
7512
|
+
track.values[offset + axis] *= scale;
|
|
7513
|
+
track.values[offset + 2 * width + axis] *= scale;
|
|
7514
|
+
}
|
|
7515
|
+
}
|
|
7516
|
+
}
|
|
7517
|
+
}
|
|
7518
|
+
}
|
|
7519
|
+
}
|
|
7520
|
+
if (additive && !authoredAdditive) {
|
|
7521
|
+
const reference = clip.clone();
|
|
7522
|
+
for (const track of reference.tracks) {
|
|
7523
|
+
const rest = this.restValues(track);
|
|
7524
|
+
if (!rest) continue;
|
|
7525
|
+
const width = track.getValueSize();
|
|
7526
|
+
for (let offset = 0; offset < track.values.length; offset += width) track.values.set(rest, offset);
|
|
7527
|
+
}
|
|
7528
|
+
const explicitReference = options.additiveReferenceTimeSec;
|
|
7529
|
+
if (finite2(explicitReference)) AnimationUtils.makeClipAdditive(clip, explicitReference * 30, clip.clone(), 30);
|
|
7530
|
+
else AnimationUtils.makeClipAdditive(clip, 0, reference, 30);
|
|
7531
|
+
}
|
|
7532
|
+
if (!additive && authoredAdditive) {
|
|
7533
|
+
for (const track of clip.tracks) {
|
|
7534
|
+
const rest = this.restValues(track);
|
|
7535
|
+
if (!rest) continue;
|
|
7536
|
+
const width = track.getValueSize();
|
|
7537
|
+
for (let offset = 0; offset < track.values.length; offset += width) {
|
|
7538
|
+
if (track.ValueTypeName === "quaternion") new Quaternion().fromArray(rest).multiply(new Quaternion().fromArray(track.values, offset)).toArray(track.values, offset);
|
|
7539
|
+
else for (let axis = 0; axis < width; axis += 1) track.values[offset + axis] += rest[axis];
|
|
7540
|
+
}
|
|
7541
|
+
}
|
|
7542
|
+
}
|
|
7543
|
+
clip.blendMode = additive ? AdditiveAnimationBlendMode : NormalAnimationBlendMode;
|
|
7544
|
+
return clip;
|
|
7545
|
+
}
|
|
7546
|
+
applyEasing(clip, easing, resampleCustom = false) {
|
|
7547
|
+
if (easing === "linear" && !resampleCustom) return;
|
|
7548
|
+
const curve = (progress2) => {
|
|
7549
|
+
switch (easing) {
|
|
7550
|
+
case "easeIn":
|
|
7551
|
+
return progress2 * progress2;
|
|
7552
|
+
case "easeOut":
|
|
7553
|
+
return 1 - (1 - progress2) ** 2;
|
|
7554
|
+
case "easeInOut":
|
|
7555
|
+
return progress2 < 0.5 ? 2 * progress2 * progress2 : 1 - (-2 * progress2 + 2) ** 2 / 2;
|
|
7556
|
+
case "easeInOutCubic":
|
|
7557
|
+
return progress2 < 0.5 ? 4 * progress2 ** 3 : 1 - (-2 * progress2 + 2) ** 3 / 2;
|
|
7558
|
+
default:
|
|
7559
|
+
return progress2;
|
|
7560
|
+
}
|
|
6770
7561
|
};
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
const matrix = new Matrix4().multiplyMatrices(parent, new Matrix4().compose(object.position, quaternion, scale));
|
|
6791
|
-
return { quaternion, direction: joint.optical.clone().transformDirection(matrix) };
|
|
6792
|
-
}
|
|
6793
|
-
solveJoint(joint, desired, roll = 0, base = joint.object.quaternion.clone(), parent = joint.object.parent?.matrixWorld ?? new Matrix4(), scale = joint.object.scale) {
|
|
6794
|
-
const evaluate = (yaw2, pitch2) => this.jointPose(joint, base, yaw2, pitch2, roll, parent, scale);
|
|
6795
|
-
let yaw = 0;
|
|
6796
|
-
let pitch = 0;
|
|
6797
|
-
let best = evaluate(yaw, pitch);
|
|
6798
|
-
for (let iteration = 0; iteration < 24; iteration += 1) {
|
|
6799
|
-
const error = desired.clone().sub(best.direction);
|
|
6800
|
-
if (error.lengthSq() < 1e-14) break;
|
|
6801
|
-
const derivative = (axis) => {
|
|
6802
|
-
const value = axis === 0 ? yaw : pitch;
|
|
6803
|
-
const lo = Math.max(-1, value - 1e-4);
|
|
6804
|
-
const hi = Math.min(1, value + 1e-4);
|
|
6805
|
-
return evaluate(axis === 0 ? hi : yaw, axis === 1 ? hi : pitch).direction.sub(evaluate(axis === 0 ? lo : yaw, axis === 1 ? lo : pitch).direction).divideScalar(hi - lo);
|
|
7562
|
+
for (const track of clip.tracks) {
|
|
7563
|
+
if (track.getInterpolation() === InterpolateDiscrete || track.times.length === 0) continue;
|
|
7564
|
+
const customInterpolant = track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true;
|
|
7565
|
+
if (track.times.length === 1) {
|
|
7566
|
+
if (customInterpolant && resampleCustom) {
|
|
7567
|
+
track.values = new Float32Array(track.createInterpolant().evaluate(track.times[0]));
|
|
7568
|
+
track.setInterpolation(InterpolateLinear);
|
|
7569
|
+
}
|
|
7570
|
+
continue;
|
|
7571
|
+
}
|
|
7572
|
+
if ((customInterpolant || track.getInterpolation() !== InterpolateLinear) && easing === "linear" && !resampleCustom) continue;
|
|
7573
|
+
const stride = track.getValueSize();
|
|
7574
|
+
const width = customInterpolant ? stride / 3 : stride;
|
|
7575
|
+
const interpolant = track.createInterpolant();
|
|
7576
|
+
const times = [];
|
|
7577
|
+
const values = [];
|
|
7578
|
+
const append = (time, value) => {
|
|
7579
|
+
times.push(time);
|
|
7580
|
+
for (let axis = 0; axis < width; axis += 1) values.push(value[axis]);
|
|
6806
7581
|
};
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
const dy = Math.max(-0.5, Math.min(0.5, (ay * bb - by * ab) / determinant));
|
|
6817
|
-
const dp = Math.max(-0.5, Math.min(0.5, (by * aa - ay * ab) / determinant));
|
|
6818
|
-
let improved = false;
|
|
6819
|
-
for (const step of [1, 0.5, 0.25, 0.125]) {
|
|
6820
|
-
const nextYaw = bounded(yaw + dy * step);
|
|
6821
|
-
const nextPitch = bounded(pitch + dp * step);
|
|
6822
|
-
const next = evaluate(nextYaw, nextPitch);
|
|
6823
|
-
if (next.direction.distanceToSquared(desired) < error.lengthSq()) {
|
|
6824
|
-
yaw = nextYaw;
|
|
6825
|
-
pitch = nextPitch;
|
|
6826
|
-
best = next;
|
|
6827
|
-
improved = true;
|
|
6828
|
-
break;
|
|
7582
|
+
for (let index = 0; index < track.times.length - 1; index += 1) {
|
|
7583
|
+
const start = track.times[index];
|
|
7584
|
+
const end = track.times[index + 1];
|
|
7585
|
+
const offset = index * stride + (customInterpolant ? width : 0);
|
|
7586
|
+
append(start, track.values.subarray(offset, offset + width));
|
|
7587
|
+
if (end <= start) continue;
|
|
7588
|
+
for (let part = 1; part < 16; part += 1) {
|
|
7589
|
+
const progress2 = part / 16;
|
|
7590
|
+
append(start + (end - start) * progress2, interpolant.evaluate(start + (end - start) * curve(progress2)));
|
|
6829
7591
|
}
|
|
6830
7592
|
}
|
|
6831
|
-
|
|
7593
|
+
const lastOffset = (track.times.length - 1) * stride + (customInterpolant ? width : 0);
|
|
7594
|
+
append(track.times[track.times.length - 1], track.values.subarray(lastOffset, lastOffset + width));
|
|
7595
|
+
track.times = new Float32Array(times);
|
|
7596
|
+
track.values = new Float32Array(values);
|
|
7597
|
+
if (customInterpolant || track.getInterpolation() !== InterpolateLinear) track.setInterpolation(InterpolateLinear);
|
|
6832
7598
|
}
|
|
6833
|
-
return { ...best, limited: best.direction.angleTo(desired) > 1e-3, yaw, pitch };
|
|
6834
7599
|
}
|
|
6835
|
-
|
|
6836
|
-
const
|
|
6837
|
-
const
|
|
6838
|
-
|
|
6839
|
-
|
|
7600
|
+
nativeOptions(options, clip) {
|
|
7601
|
+
const mode = clip.duration === 0 ? "once" : options.loopMode ?? (options.loop === true ? "repeat" : "once");
|
|
7602
|
+
const count = finite2(options.repeatCount) && options.repeatCount > 0 ? options.repeatCount : null;
|
|
7603
|
+
let speed = options.speed ?? options.playbackRate ?? options.rate ?? options.timeScale ?? 1;
|
|
7604
|
+
if (options.reverse === true) speed = -Math.abs(speed);
|
|
7605
|
+
return {
|
|
7606
|
+
startSeconds: finite2(options.time) ? options.time : finite2(options.offsetSec) ? options.offsetSec : speed < 0 ? clip.duration : 0,
|
|
7607
|
+
speed,
|
|
7608
|
+
weight: finite2(options.mixerWeight) ? options.mixerWeight : 1,
|
|
7609
|
+
blendMode: clip.blendMode === AdditiveAnimationBlendMode ? "additive" : "normal",
|
|
7610
|
+
loop: { mode: mode === "once" ? "once" : mode === "pingpong" || mode === "pingPong" ? "pingPong" : "repeat", count: mode === "once" ? 1 : count },
|
|
7611
|
+
finalPose: options.finalPose === "release" || options.clampWhenFinished === false ? "release" : "hold"
|
|
7612
|
+
};
|
|
6840
7613
|
}
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
this.saved.set(joint.object, { base: joint.object.quaternion.clone(), applied: result.quaternion.clone() });
|
|
6844
|
-
joint.object.quaternion.copy(result.quaternion);
|
|
6845
|
-
joint.object.updateMatrixWorld(true);
|
|
6846
|
-
return result;
|
|
7614
|
+
validateEasing(options) {
|
|
7615
|
+
if (options.easing !== void 0 && !["linear", "easeIn", "easeOut", "easeInOut", "easeInOutCubic"].includes(options.easing)) throw new Error(`Unknown playback easing: ${options.easing}`);
|
|
6847
7616
|
}
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
const
|
|
6851
|
-
const
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
const
|
|
6856
|
-
|
|
6857
|
-
const
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
);
|
|
6861
|
-
let headLimited = false;
|
|
6862
|
-
const headControlsPresent = controls.headYaw !== void 0 || controls.headPitch !== void 0 || controls.headRoll !== void 0;
|
|
6863
|
-
const eyeControlsPresent = controls.eyeYaw !== void 0 || controls.eyePitch !== void 0;
|
|
6864
|
-
if (request2.headEnabled !== false && headControlsPresent && this.head) {
|
|
6865
|
-
headLimited = this.solve(this.head, this.direction(
|
|
6866
|
-
this.degrees(-finite2(controls.headYaw), this.limits.headYaw),
|
|
6867
|
-
this.degrees(finite2(controls.headPitch), this.limits.headPitch)
|
|
6868
|
-
), finite2(controls.headRoll), contribution(controls.headIntensity ?? request2.headIntensity), true).limited;
|
|
6869
|
-
}
|
|
6870
|
-
const eyes = [];
|
|
6871
|
-
for (const eye of this.eyes) {
|
|
6872
|
-
const eyeOrigin = eye.object.getWorldPosition(new Vector3());
|
|
6873
|
-
const desired = target.clone().sub(eyeOrigin).normalize();
|
|
6874
|
-
const solved = request2.eyesEnabled !== false && eyeControlsPresent ? this.solve(eye, desired, 0, contribution(controls.eyeIntensity ?? request2.eyeIntensity)) : { limited: false };
|
|
6875
|
-
const direction = this.ray(eye);
|
|
6876
|
-
eyes.push({
|
|
6877
|
-
name: eye.object.name,
|
|
6878
|
-
origin: point2(eyeOrigin),
|
|
6879
|
-
direction: point2(direction),
|
|
6880
|
-
errorDegrees: direction.angleTo(desired) * 180 / Math.PI,
|
|
6881
|
-
limited: solved.limited
|
|
7617
|
+
handle(source, options, autoPlay) {
|
|
7618
|
+
options = { ..."options" in source ? source.options : {}, ...options };
|
|
7619
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
7620
|
+
const generation = this.bindingGeneration;
|
|
7621
|
+
let current;
|
|
7622
|
+
let resolvePromise = () => {
|
|
7623
|
+
};
|
|
7624
|
+
const result = { name: source.name };
|
|
7625
|
+
Object.defineProperty(result, "finished", { get: () => result.promise, enumerable: true });
|
|
7626
|
+
const newPromise = () => {
|
|
7627
|
+
result.promise = new Promise((resolve) => {
|
|
7628
|
+
resolvePromise = resolve;
|
|
6882
7629
|
});
|
|
7630
|
+
};
|
|
7631
|
+
newPromise();
|
|
7632
|
+
result.subscribe = (listener) => {
|
|
7633
|
+
const callback = typeof listener === "function" ? listener : (event) => listener.next(event);
|
|
7634
|
+
listeners.add(callback);
|
|
7635
|
+
return () => {
|
|
7636
|
+
listeners.delete(callback);
|
|
7637
|
+
};
|
|
7638
|
+
};
|
|
7639
|
+
const start = () => {
|
|
7640
|
+
if (generation !== this.bindingGeneration) throw new Error("Playback handle belongs to an obsolete model binding.");
|
|
7641
|
+
this.validateEasing(options);
|
|
7642
|
+
const connector = this.requireConnector();
|
|
7643
|
+
const inheritedStarts = /* @__PURE__ */ new Map();
|
|
7644
|
+
const clip = this.materialize(source, options, inheritedStarts);
|
|
7645
|
+
const hairMotion = this.authoredHeadMotion(clip);
|
|
7646
|
+
const previous = this.current.get(source.name);
|
|
7647
|
+
const settings = this.nativeOptions(options, clip);
|
|
7648
|
+
if (previous && connector.getAction(previous.id)) settings.replace = previous.id;
|
|
7649
|
+
if (current) newPromise();
|
|
7650
|
+
const resolve = resolvePromise;
|
|
7651
|
+
let settled = false;
|
|
7652
|
+
this.playDepth += 1;
|
|
7653
|
+
let id;
|
|
7654
|
+
try {
|
|
7655
|
+
id = connector.playNativeClip(clip, settings);
|
|
7656
|
+
} catch (error) {
|
|
7657
|
+
this.playDepth -= 1;
|
|
7658
|
+
while (!this.playDepth && this.pendingEvents.length) this.onPlaybackEvent(this.pendingEvents.shift());
|
|
7659
|
+
throw error;
|
|
7660
|
+
}
|
|
7661
|
+
const playback = {
|
|
7662
|
+
id,
|
|
7663
|
+
source,
|
|
7664
|
+
options: { ...options, intensityScale: intensity(options) },
|
|
7665
|
+
connector,
|
|
7666
|
+
terminal: false,
|
|
7667
|
+
inheritedStarts,
|
|
7668
|
+
replay: (next) => {
|
|
7669
|
+
options = next;
|
|
7670
|
+
return start();
|
|
7671
|
+
},
|
|
7672
|
+
notify: (event) => {
|
|
7673
|
+
if (settled) return;
|
|
7674
|
+
settled = true;
|
|
7675
|
+
resolve(event);
|
|
7676
|
+
for (const listener of [...listeners]) {
|
|
7677
|
+
try {
|
|
7678
|
+
listener(event);
|
|
7679
|
+
} catch (error) {
|
|
7680
|
+
queueMicrotask(() => {
|
|
7681
|
+
throw error;
|
|
7682
|
+
});
|
|
7683
|
+
}
|
|
7684
|
+
}
|
|
7685
|
+
}
|
|
7686
|
+
};
|
|
7687
|
+
current = playback;
|
|
7688
|
+
result.actionId = id;
|
|
7689
|
+
this.playbacks.set(id, playback);
|
|
7690
|
+
this.current.set(source.name, playback);
|
|
7691
|
+
const ensure = () => {
|
|
7692
|
+
this.assertAlive();
|
|
7693
|
+
if (this.connector !== connector || !connector.getAction(id)) throw new Error("Unknown, released or obsolete playback handle.");
|
|
7694
|
+
};
|
|
7695
|
+
const control = (command) => {
|
|
7696
|
+
ensure();
|
|
7697
|
+
connector.control(id, command);
|
|
7698
|
+
if (command.type === "stop") this.forget(playback);
|
|
7699
|
+
return result;
|
|
7700
|
+
};
|
|
7701
|
+
result.stop = result.cancel = () => {
|
|
7702
|
+
if (this.connector !== connector || !connector.getAction(id)) return result;
|
|
7703
|
+
ensure();
|
|
7704
|
+
const seconds = finite2(playback.options.fadeOutSec) ? playback.options.fadeOutSec : 0;
|
|
7705
|
+
if (seconds > 0 && !playback.terminal) connector.fadeOut(id, seconds);
|
|
7706
|
+
else control({ type: "stop" });
|
|
7707
|
+
return result;
|
|
7708
|
+
};
|
|
7709
|
+
result.pause = () => control({ type: "pause" });
|
|
7710
|
+
result.resume = () => {
|
|
7711
|
+
ensure();
|
|
7712
|
+
if (playback.terminal) {
|
|
7713
|
+
options = { ...playback.options, time: connector.getAction(id).time };
|
|
7714
|
+
return start();
|
|
7715
|
+
}
|
|
7716
|
+
return control({ type: "resume" });
|
|
7717
|
+
};
|
|
7718
|
+
result.setSpeed = result.setPlaybackRate = (speed) => {
|
|
7719
|
+
ensure();
|
|
7720
|
+
this.updatePlayback(playback, { speed });
|
|
7721
|
+
return result;
|
|
7722
|
+
};
|
|
7723
|
+
result.setTime = result.seek = (seconds) => control({ type: "seek", seconds });
|
|
7724
|
+
result.setWeight = result.setIntensity = (value) => {
|
|
7725
|
+
ensure();
|
|
7726
|
+
this.updatePlayback(playback, { intensityScale: value });
|
|
7727
|
+
return result;
|
|
7728
|
+
};
|
|
7729
|
+
result.updateParams = result.setParams = (value) => {
|
|
7730
|
+
ensure();
|
|
7731
|
+
this.updatePlayback(playback, value);
|
|
7732
|
+
return result;
|
|
7733
|
+
};
|
|
7734
|
+
try {
|
|
7735
|
+
const fade = options.fadeInSec ?? options.crossfadeDuration;
|
|
7736
|
+
if (finite2(fade) && fade > 0) connector.fadeIn(id, fade);
|
|
7737
|
+
} finally {
|
|
7738
|
+
this.playDepth -= 1;
|
|
7739
|
+
while (!this.playDepth && this.pendingEvents.length) this.onPlaybackEvent(this.pendingEvents.shift());
|
|
7740
|
+
}
|
|
7741
|
+
if (hairMotion && connector.getAction(id)) {
|
|
7742
|
+
this.playHairImpulse(hairMotion.horizontal, hairMotion.vertical);
|
|
7743
|
+
this.setHairGravity(hairMotion.pitch, clip.duration);
|
|
7744
|
+
}
|
|
7745
|
+
return result;
|
|
7746
|
+
};
|
|
7747
|
+
result.play = () => {
|
|
7748
|
+
if (current) options = { ...current.options };
|
|
7749
|
+
return start();
|
|
7750
|
+
};
|
|
7751
|
+
const beforePlay = () => {
|
|
7752
|
+
throw new Error("Play this compiled clip before changing playback.");
|
|
7753
|
+
};
|
|
7754
|
+
result.stop = result.cancel = () => result;
|
|
7755
|
+
result.pause = result.resume = beforePlay;
|
|
7756
|
+
result.updateParams = result.setParams = (patch) => {
|
|
7757
|
+
this.assertAlive();
|
|
7758
|
+
this.validateEasing(patch);
|
|
7759
|
+
options = { ...options, ...patch };
|
|
7760
|
+
if ("finalPose" in patch && !("clampWhenFinished" in patch)) options.clampWhenFinished = patch.finalPose !== "release";
|
|
7761
|
+
if ("clampWhenFinished" in patch && !("finalPose" in patch)) options.finalPose = patch.clampWhenFinished === false ? "release" : "hold";
|
|
7762
|
+
if ("loop" in patch && !("loopMode" in patch)) options.loopMode = patch.loop ? "repeat" : "once";
|
|
7763
|
+
if ("loopMode" in patch && !("repeatCount" in patch)) delete options.repeatCount;
|
|
7764
|
+
if ("weight" in patch || "intensity" in patch || "intensityScale" in patch) options.intensityScale = intensity(patch);
|
|
7765
|
+
if ("time" in patch || "offsetSec" in patch) options.time = patch.time ?? patch.offsetSec;
|
|
7766
|
+
if ("speed" in patch || "playbackRate" in patch || "rate" in patch || "timeScale" in patch || "reverse" in patch) {
|
|
7767
|
+
let speed = patch.speed ?? patch.playbackRate ?? patch.rate ?? patch.timeScale ?? options.speed ?? options.playbackRate ?? options.rate ?? options.timeScale ?? 1;
|
|
7768
|
+
if ("reverse" in patch) speed = Math.abs(speed) * (patch.reverse ? -1 : 1);
|
|
7769
|
+
options.speed = speed;
|
|
7770
|
+
delete options.reverse;
|
|
7771
|
+
}
|
|
7772
|
+
return result;
|
|
7773
|
+
};
|
|
7774
|
+
result.setWeight = result.setIntensity = (value) => result.updateParams({ intensityScale: value });
|
|
7775
|
+
result.setSpeed = result.setPlaybackRate = (speed) => result.updateParams({ speed });
|
|
7776
|
+
result.setTime = result.seek = (time) => result.updateParams({ time });
|
|
7777
|
+
return autoPlay ? start() : result;
|
|
7778
|
+
}
|
|
7779
|
+
forget(playback) {
|
|
7780
|
+
this.playbacks.delete(playback.id);
|
|
7781
|
+
if (this.current.get(playback.source.name) === playback) this.current.delete(playback.source.name);
|
|
7782
|
+
}
|
|
7783
|
+
updatePlayback(playback, patch) {
|
|
7784
|
+
this.validateEasing(patch);
|
|
7785
|
+
const connector = playback.connector;
|
|
7786
|
+
const action = connector.getAction(playback.id);
|
|
7787
|
+
if (connector !== this.connector || !action) throw new Error("Unknown, released or obsolete playback handle.");
|
|
7788
|
+
const options = { ...playback.options, ...patch };
|
|
7789
|
+
if ("finalPose" in patch && !("clampWhenFinished" in patch)) options.clampWhenFinished = patch.finalPose !== "release";
|
|
7790
|
+
if ("clampWhenFinished" in patch && !("finalPose" in patch)) options.finalPose = patch.clampWhenFinished === false ? "release" : "hold";
|
|
7791
|
+
if ("loop" in patch && !("loopMode" in patch)) options.loopMode = patch.loop ? "repeat" : "once";
|
|
7792
|
+
if ("loopMode" in patch && !("repeatCount" in patch)) delete options.repeatCount;
|
|
7793
|
+
if ("weight" in patch || "intensity" in patch || "intensityScale" in patch) options.intensityScale = intensity(patch);
|
|
7794
|
+
if (["weight", "intensity", "intensityScale", "blendMode", "easing", "balance", "balanceMap", "mixWeights"].some((key) => key in patch)) {
|
|
7795
|
+
const clip = this.materialize(playback.source, options, playback.inheritedStarts);
|
|
7796
|
+
connector.replaceClip(playback.id, clip);
|
|
7797
|
+
if ("blendMode" in patch) connector.control(playback.id, { type: "setBlendMode", blendMode: clip.blendMode === AdditiveAnimationBlendMode ? "additive" : "normal" });
|
|
7798
|
+
}
|
|
7799
|
+
if ("mixerWeight" in patch) connector.control(playback.id, { type: "setWeight", weight: patch.mixerWeight });
|
|
7800
|
+
if ("speed" in patch || "playbackRate" in patch || "rate" in patch || "timeScale" in patch || "reverse" in patch) {
|
|
7801
|
+
let speed = patch.speed ?? patch.playbackRate ?? patch.rate ?? patch.timeScale ?? action.timeScale;
|
|
7802
|
+
if ("reverse" in patch) speed = Math.abs(speed) * (patch.reverse ? -1 : 1);
|
|
7803
|
+
connector.control(playback.id, { type: "setSpeed", speed });
|
|
7804
|
+
options.speed = speed;
|
|
7805
|
+
delete options.reverse;
|
|
7806
|
+
}
|
|
7807
|
+
if ("time" in patch || "offsetSec" in patch) {
|
|
7808
|
+
options.time = patch.time ?? patch.offsetSec;
|
|
7809
|
+
connector.control(playback.id, { type: "seek", seconds: options.time });
|
|
7810
|
+
}
|
|
7811
|
+
if ("loopMode" in patch || "loop" in patch || "repeatCount" in patch) {
|
|
7812
|
+
if (playback.terminal) {
|
|
7813
|
+
playback.replay({ ...options, time: action.time });
|
|
7814
|
+
return;
|
|
7815
|
+
}
|
|
7816
|
+
connector.control(playback.id, { type: "setLoop", loop: this.nativeOptions(options, action.getClip()).loop });
|
|
6883
7817
|
}
|
|
6884
|
-
|
|
7818
|
+
if ("clampWhenFinished" in patch || "finalPose" in patch) connector.control(playback.id, { type: "setFinalPose", finalPose: this.nativeOptions(options, action.getClip()).finalPose });
|
|
7819
|
+
playback.options = options;
|
|
7820
|
+
if (!connector.getAction(playback.id)) this.forget(playback);
|
|
6885
7821
|
}
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
const wantsDraco = typeof dracoDecoderPath === "string" && dracoDecoderPath.length > 0;
|
|
6894
|
-
const normalizedPath = wantsDraco ? dracoDecoderPath.endsWith("/") ? dracoDecoderPath : `${dracoDecoderPath}/` : "";
|
|
6895
|
-
if (!gltfLoader || gltfLoaderUsesDraco !== wantsDraco || wantsDraco && normalizedPath !== dracoPath) {
|
|
6896
|
-
draco?.dispose();
|
|
6897
|
-
draco = null;
|
|
6898
|
-
dracoPath = normalizedPath;
|
|
6899
|
-
gltfLoaderUsesDraco = wantsDraco;
|
|
6900
|
-
gltfLoader = new GLTFLoader();
|
|
6901
|
-
if (wantsDraco) {
|
|
6902
|
-
draco = new DRACOLoader().setDecoderPath(normalizedPath).setDecoderConfig({ type: "wasm" });
|
|
6903
|
-
gltfLoader.setDRACOLoader(draco);
|
|
7822
|
+
registerAnimationClips(clips) {
|
|
7823
|
+
const model = this.requireModel();
|
|
7824
|
+
for (const clip of clips) {
|
|
7825
|
+
if (this.sources.get(clip.name)?.kind === "native" && this.sources.get(clip.name).clip === clip) continue;
|
|
7826
|
+
const [ir] = serializeAnimationClips(model, [clip], this.inspection);
|
|
7827
|
+
this.core.register_animation_clip(json2(ir), "baked");
|
|
7828
|
+
this.sources.set(clip.name, { name: clip.name, kind: "native", clip });
|
|
6904
7829
|
}
|
|
6905
7830
|
}
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
if (!object.isMesh) return;
|
|
6912
|
-
if (castShadows) object.castShadow = true;
|
|
6913
|
-
if (object.morphTargetInfluences?.length) meshes.push(object);
|
|
6914
|
-
});
|
|
6915
|
-
return meshes;
|
|
6916
|
-
};
|
|
6917
|
-
var progress = (listener) => {
|
|
6918
|
-
let last = -1;
|
|
6919
|
-
return (event) => {
|
|
6920
|
-
if (!listener || !event.lengthComputable) return;
|
|
6921
|
-
const next = Math.min(100, Math.max(0, Math.round(event.loaded / event.total * 100)));
|
|
6922
|
-
if (next !== last) {
|
|
6923
|
-
last = next;
|
|
6924
|
-
listener(next);
|
|
7831
|
+
loadAnimationClips(clips) {
|
|
7832
|
+
this.stopAllAnimations();
|
|
7833
|
+
for (const source of [...this.sources.values()]) if (source.kind === "native") {
|
|
7834
|
+
this.sources.delete(source.name);
|
|
7835
|
+
this.core.remove_animation_clip(source.name);
|
|
6925
7836
|
}
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
function applyCharacterModelTransform(model, value = {}) {
|
|
6929
|
-
if (value.modelOffset) model.position.set(value.modelOffset.x ?? 0, value.modelOffset.y ?? 0, value.modelOffset.z ?? 0);
|
|
6930
|
-
if (value.modelRotation) model.rotation.set(...["x", "y", "z"].map((axis) => (value.modelRotation?.[axis] ?? 0) * Math.PI / 180));
|
|
6931
|
-
if (Number.isFinite(value.modelScale) && (value.modelScale ?? 0) > 0) model.scale.setScalar(value.modelScale);
|
|
6932
|
-
if (Number.isFinite(value.modelGroundClearance)) {
|
|
6933
|
-
model.updateMatrixWorld(true);
|
|
6934
|
-
const min = new Box3().setFromObject(model).min.y;
|
|
6935
|
-
if (Number.isFinite(min) && min < value.modelGroundClearance) model.position.y += value.modelGroundClearance - min;
|
|
7837
|
+
this.registerAnimationClips(clips ?? []);
|
|
7838
|
+
this.restartHair();
|
|
6936
7839
|
}
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
7840
|
+
removeAnimationClip(name) {
|
|
7841
|
+
this.stopAnimation(name);
|
|
7842
|
+
this.sources.delete(name);
|
|
7843
|
+
return this.core.remove_animation_clip(name);
|
|
7844
|
+
}
|
|
7845
|
+
getAnimationClips() {
|
|
7846
|
+
return parse(this.core.get_animation_clips());
|
|
7847
|
+
}
|
|
7848
|
+
playAnimation(name, options = {}) {
|
|
7849
|
+
const source = this.sources.get(name);
|
|
7850
|
+
if (!source) throw new Error(`Unknown animation clip: ${name}`);
|
|
7851
|
+
return this.handle(source, options, true);
|
|
7852
|
+
}
|
|
7853
|
+
build(source, options, play) {
|
|
7854
|
+
this.requireModel();
|
|
7855
|
+
this.validateEasing(options);
|
|
7856
|
+
this.compile(source, options);
|
|
7857
|
+
this.sources.set(source.name, source);
|
|
7858
|
+
return this.handle(source, options, play);
|
|
7859
|
+
}
|
|
7860
|
+
buildClip(name, curves, options = {}) {
|
|
7861
|
+
return options.semanticAnimation ? this.semanticAnimationToClip(name, options.semanticAnimation, { ...options, faceCurves: curves }) : this.build({ name, kind: "curves", input: copy(curves), options: copy(options) }, options, false);
|
|
7862
|
+
}
|
|
7863
|
+
snippetToClip(name, curves, options = {}) {
|
|
7864
|
+
return this.buildClip(name, curves, options);
|
|
7865
|
+
}
|
|
7866
|
+
buildTypedClip(name, channels, options = {}) {
|
|
7867
|
+
return this.build({ name, kind: "typed", input: copy(channels), options: copy(options) }, options, false);
|
|
7868
|
+
}
|
|
7869
|
+
typedSnippetToClip(name, channels, options = {}) {
|
|
7870
|
+
return this.buildTypedClip(name, channels, options);
|
|
7871
|
+
}
|
|
7872
|
+
semanticAnimationToClip(name, animation, options = {}) {
|
|
7873
|
+
return this.build({ name, kind: "semantic", input: copy(animation), options: copy(options) }, options, false);
|
|
7874
|
+
}
|
|
7875
|
+
playSnippet(snippet, curvesOrOptions = {}, options = {}) {
|
|
7876
|
+
return typeof snippet === "string" ? this.buildClip(snippet, curvesOrOptions, options).play() : this.buildClip(snippet.name, snippet.curves, curvesOrOptions).play();
|
|
7877
|
+
}
|
|
7878
|
+
playTypedSnippet(snippet, options = {}) {
|
|
7879
|
+
return this.buildTypedClip(snippet.name, snippet.channels, options).play();
|
|
7880
|
+
}
|
|
7881
|
+
playClip(value) {
|
|
7882
|
+
return typeof value === "string" ? this.playAnimation(value) : value.play();
|
|
7883
|
+
}
|
|
7884
|
+
supportsClipCurves() {
|
|
7885
|
+
return true;
|
|
7886
|
+
}
|
|
7887
|
+
cleanupSnippet(name) {
|
|
7888
|
+
this.stopAnimation(name);
|
|
7889
|
+
this.sources.delete(name);
|
|
7890
|
+
this.core.cleanup_snippet(name);
|
|
7891
|
+
}
|
|
7892
|
+
crossfadeTo(name, seconds, options = {}) {
|
|
7893
|
+
const outgoing = [...this.current.values()].filter((playback) => !playback.source.name.startsWith("__embody_"));
|
|
7894
|
+
const handle = this.playAnimation(name, { ...options, fadeInSec: seconds });
|
|
7895
|
+
for (const playback of outgoing) if (playback.connector.getAction(playback.id)) playback.connector.fadeOut(playback.id, seconds);
|
|
7896
|
+
return handle;
|
|
7897
|
+
}
|
|
7898
|
+
stopAnimation(name) {
|
|
7899
|
+
const playback = this.current.get(name);
|
|
7900
|
+
if (!playback) return;
|
|
7901
|
+
if (playback.connector.getAction(playback.id)) playback.connector.control(playback.id, { type: "stop" });
|
|
7902
|
+
this.forget(playback);
|
|
7903
|
+
}
|
|
7904
|
+
stopAllAnimations() {
|
|
7905
|
+
for (const playback of [...this.playbacks.values()]) {
|
|
7906
|
+
if (playback.source.kind === "compiled") continue;
|
|
7907
|
+
if (playback.connector.getAction(playback.id)) playback.connector.control(playback.id, { type: "stop" });
|
|
7908
|
+
this.forget(playback);
|
|
7909
|
+
}
|
|
7910
|
+
}
|
|
7911
|
+
pauseAnimation(name) {
|
|
7912
|
+
const p = this.current.get(name);
|
|
7913
|
+
if (p) p.connector.control(p.id, { type: "pause" });
|
|
7914
|
+
}
|
|
7915
|
+
resumeAnimation(name) {
|
|
7916
|
+
const p = this.current.get(name);
|
|
7917
|
+
if (!p) return;
|
|
7918
|
+
if (p.terminal) p.replay({ ...p.options, time: p.connector.getAction(p.id)?.time ?? 0 });
|
|
7919
|
+
else p.connector.control(p.id, { type: "resume" });
|
|
7920
|
+
}
|
|
7921
|
+
pauseAllAnimations() {
|
|
7922
|
+
for (const p of this.playbacks.values()) if (!p.terminal) p.connector.control(p.id, { type: "pause" });
|
|
7923
|
+
}
|
|
7924
|
+
resumeAllAnimations() {
|
|
7925
|
+
for (const name of [...this.current.keys()]) this.resumeAnimation(name);
|
|
7926
|
+
}
|
|
7927
|
+
updateClipParams(name, options) {
|
|
7928
|
+
const p = this.current.get(name);
|
|
7929
|
+
if (p) this.updatePlayback(p, options);
|
|
7930
|
+
}
|
|
7931
|
+
setAnimationSpeed(name, value) {
|
|
7932
|
+
this.updateClipParams(name, { speed: value });
|
|
7933
|
+
}
|
|
7934
|
+
setAnimationIntensity(name, value) {
|
|
7935
|
+
this.updateClipParams(name, { intensityScale: value });
|
|
7936
|
+
}
|
|
7937
|
+
setAnimationLoop(name, value) {
|
|
7938
|
+
this.updateClipParams(name, { loopMode: value ? "repeat" : "once" });
|
|
7939
|
+
}
|
|
7940
|
+
setAnimationLoopMode(name, value) {
|
|
7941
|
+
this.updateClipParams(name, { loopMode: value });
|
|
7942
|
+
}
|
|
7943
|
+
setAnimationRepeatCount(name, value) {
|
|
7944
|
+
this.updateClipParams(name, { loopMode: "repeat", repeatCount: value });
|
|
7945
|
+
}
|
|
7946
|
+
setAnimationReverse(name, value) {
|
|
7947
|
+
this.updateClipParams(name, { reverse: value });
|
|
7948
|
+
}
|
|
7949
|
+
setAnimationBlendMode(name, value) {
|
|
7950
|
+
this.updateClipParams(name, { blendMode: value });
|
|
7951
|
+
}
|
|
7952
|
+
setAnimationEasing(name, value) {
|
|
7953
|
+
this.validateEasing({ easing: value });
|
|
7954
|
+
this.updateClipParams(name, { easing: value });
|
|
7955
|
+
}
|
|
7956
|
+
seekAnimation(name, value) {
|
|
7957
|
+
this.updateClipParams(name, { time: value });
|
|
7958
|
+
}
|
|
7959
|
+
setAnimationTime(name, value) {
|
|
7960
|
+
this.seekAnimation(name, value);
|
|
7961
|
+
}
|
|
7962
|
+
setSnippetTime(name, value) {
|
|
7963
|
+
this.seekAnimation(name, value);
|
|
7964
|
+
}
|
|
7965
|
+
seekSnippet(name, value) {
|
|
7966
|
+
this.seekAnimation(name, value);
|
|
7967
|
+
}
|
|
7968
|
+
seek(name, value) {
|
|
7969
|
+
this.seekAnimation(name, value);
|
|
7970
|
+
}
|
|
7971
|
+
setAnimationTimeScale(value) {
|
|
7972
|
+
this.requireConnector().setTimeScale(value);
|
|
7973
|
+
this.timeScale = value;
|
|
7974
|
+
}
|
|
7975
|
+
getAnimationState(name) {
|
|
7976
|
+
const p = this.current.get(name);
|
|
7977
|
+
const action = p?.connector.getAction(p.id);
|
|
7978
|
+
if (!action || !p) {
|
|
7979
|
+
if (p) this.forget(p);
|
|
7980
|
+
return { name, playing: false, isPlaying: false };
|
|
7981
|
+
}
|
|
7982
|
+
const playing = action.isRunning();
|
|
7983
|
+
return {
|
|
7984
|
+
name,
|
|
7985
|
+
actionId: p.id,
|
|
7986
|
+
playing,
|
|
7987
|
+
isPlaying: playing,
|
|
7988
|
+
paused: action.paused,
|
|
7989
|
+
completed: p.terminal,
|
|
7990
|
+
time: action.time,
|
|
7991
|
+
duration: action.getClip().duration,
|
|
7992
|
+
speed: action.timeScale,
|
|
7993
|
+
intensityScale: intensity(p.options),
|
|
7994
|
+
mixerWeight: action.getEffectiveWeight(),
|
|
7995
|
+
loopMode: action.loop === LoopOnce ? "once" : action.loop === LoopPingPong ? "pingpong" : "repeat",
|
|
7996
|
+
repeatCount: Number.isFinite(action.repetitions) ? action.repetitions : null,
|
|
7997
|
+
blendMode: action.blendMode === AdditiveAnimationBlendMode ? "additive" : "replace"
|
|
7998
|
+
};
|
|
7999
|
+
}
|
|
8000
|
+
getPlayingAnimations() {
|
|
8001
|
+
return [...this.current.keys()].filter((name) => this.getAnimationState(name).playing);
|
|
8002
|
+
}
|
|
8003
|
+
commitLive(durationMs = 0) {
|
|
8004
|
+
const connector = this.requireConnector();
|
|
8005
|
+
const duration = Math.max(0, durationMs) / 1e3;
|
|
8006
|
+
const clip = parse(this.core.build_live_clip("__embody_live", duration));
|
|
8007
|
+
const touched = new Set(parse(this.core.live_command_targets_json()).map(targetKey));
|
|
8008
|
+
const tracks = new Map(clip.tracks.map((track) => [targetKey(track.target), track]));
|
|
8009
|
+
const handles = [];
|
|
8010
|
+
for (const [key, previous] of this.liveTargets) {
|
|
8011
|
+
if (tracks.has(key)) continue;
|
|
8012
|
+
if (previous.releasing && !touched.has(key)) continue;
|
|
8013
|
+
const action = previous.handle.actionId && connector.getAction(previous.handle.actionId);
|
|
8014
|
+
if (!action || duration === 0) {
|
|
8015
|
+
previous.handle.stop();
|
|
8016
|
+
this.liveTargets.delete(key);
|
|
8017
|
+
continue;
|
|
8018
|
+
}
|
|
8019
|
+
const nativeTrack = action.getClip().tracks[0];
|
|
8020
|
+
const sample = Array.from(nativeTrack.createInterpolant().evaluate(action.time));
|
|
8021
|
+
const released = { ...previous.track, times: [0, duration], values: [...sample, ...sample], inheritStart: false };
|
|
8022
|
+
const releaseClip = { ...clip, name: previous.handle.name, tracks: [released] };
|
|
8023
|
+
const handle = this.handle(
|
|
8024
|
+
{ name: releaseClip.name, kind: "compiled", clip: releaseClip },
|
|
8025
|
+
{ loopMode: "once", finalPose: "release", mixerWeight: action.getEffectiveWeight() },
|
|
8026
|
+
true
|
|
8027
|
+
);
|
|
8028
|
+
connector.fadeOut(handle.actionId, duration);
|
|
8029
|
+
const record = { track: released, handle, releasing: true };
|
|
8030
|
+
this.liveTargets.set(key, record);
|
|
8031
|
+
void handle.promise.then(() => {
|
|
8032
|
+
if (this.liveTargets.get(key) === record) this.liveTargets.delete(key);
|
|
8033
|
+
});
|
|
8034
|
+
handles.push(handle);
|
|
8035
|
+
}
|
|
8036
|
+
for (const [key, track] of tracks) {
|
|
8037
|
+
const previous = this.liveTargets.get(key);
|
|
8038
|
+
const endpoint = (value) => value.values.slice(value.values.length / value.times.length * (value.times.length - 1));
|
|
8039
|
+
if (previous && !previous.releasing && !touched.has(key) && json2(endpoint(previous.track)) === json2(endpoint(track))) continue;
|
|
8040
|
+
const name = previous?.handle.name ?? `__embody_live_${this.nextLiveTarget++}`;
|
|
8041
|
+
const outgoing = previous?.handle.actionId && connector.getAction(previous.handle.actionId);
|
|
8042
|
+
let nativeTrack = track;
|
|
8043
|
+
if (duration > 0 && outgoing) {
|
|
8044
|
+
const start = Array.from(outgoing.getClip().tracks[0].createInterpolant().evaluate(outgoing.time));
|
|
8045
|
+
nativeTrack = { ...track, values: [...start, ...endpoint(track)], inheritStart: false };
|
|
8046
|
+
}
|
|
8047
|
+
const targetClip = { ...clip, name, tracks: [nativeTrack] };
|
|
8048
|
+
const handle = this.handle({ name, kind: "compiled", clip: targetClip }, { loopMode: "once", finalPose: "hold" }, true);
|
|
8049
|
+
this.liveTargets.set(key, { track, handle, releasing: false });
|
|
8050
|
+
handles.push(handle);
|
|
8051
|
+
}
|
|
8052
|
+
return handles;
|
|
8053
|
+
}
|
|
8054
|
+
mutateLive(mutate, durationMs = 0) {
|
|
8055
|
+
this.requireModel();
|
|
8056
|
+
this.core.begin_live_command();
|
|
8057
|
+
mutate();
|
|
8058
|
+
return this.commitLive(durationMs);
|
|
8059
|
+
}
|
|
8060
|
+
transition(handles) {
|
|
8061
|
+
let settled = handles.length === 0;
|
|
8062
|
+
const promise = Promise.all(handles.map((handle) => handle.promise)).then(() => {
|
|
8063
|
+
settled = true;
|
|
8064
|
+
});
|
|
8065
|
+
const control = (command) => {
|
|
8066
|
+
if (settled) return;
|
|
8067
|
+
for (const handle of handles) {
|
|
8068
|
+
const playback = handle.actionId && this.playbacks.get(handle.actionId);
|
|
8069
|
+
if (!playback || !playback.connector.getAction(playback.id)) continue;
|
|
8070
|
+
if (command === "cancel" || !playback.terminal) handle[command]();
|
|
8071
|
+
}
|
|
8072
|
+
};
|
|
8073
|
+
return { promise, pause: () => control("pause"), resume: () => control("resume"), cancel: () => control("cancel") };
|
|
8074
|
+
}
|
|
8075
|
+
setAU(id, value, balance = this.core.get_au_balance(id)) {
|
|
8076
|
+
this.mutateLive(() => this.core.set_au_signed(id, value, balance));
|
|
8077
|
+
}
|
|
8078
|
+
getAU(id) {
|
|
8079
|
+
return this.core.get_au(id);
|
|
8080
|
+
}
|
|
8081
|
+
getAUBalance(id) {
|
|
8082
|
+
return this.core.get_au_balance(id);
|
|
8083
|
+
}
|
|
8084
|
+
getBodyControls() {
|
|
8085
|
+
return parse(this.core.get_body_controls_json());
|
|
8086
|
+
}
|
|
8087
|
+
getSemanticPoseCatalog() {
|
|
8088
|
+
return parse(this.core.get_semantic_pose_catalog_json());
|
|
8089
|
+
}
|
|
8090
|
+
captureSemanticPose() {
|
|
8091
|
+
return parse(this.core.capture_semantic_pose_json());
|
|
8092
|
+
}
|
|
8093
|
+
validateSemanticPose(pose) {
|
|
8094
|
+
return parse(this.core.validate_semantic_pose_json(json2(pose)));
|
|
8095
|
+
}
|
|
8096
|
+
applySemanticPose(pose) {
|
|
8097
|
+
this.mutateLive(() => this.core.apply_semantic_pose_json(json2(pose)));
|
|
8098
|
+
}
|
|
8099
|
+
validateSemanticAnimation(animation, options = {}) {
|
|
8100
|
+
this.core.validate_semantic_animation_json(json2(animation), json2(options));
|
|
8101
|
+
}
|
|
8102
|
+
resetBodyControls() {
|
|
8103
|
+
this.mutateLive(() => this.core.reset_body_controls());
|
|
8104
|
+
}
|
|
8105
|
+
setContinuum(negative, positive, value, balance = NaN) {
|
|
8106
|
+
this.mutateLive(() => this.core.set_continuum(negative, positive, value, balance));
|
|
8107
|
+
}
|
|
8108
|
+
getContinuum(negative, positive) {
|
|
8109
|
+
return this.core.get_continuum(negative, positive);
|
|
8110
|
+
}
|
|
8111
|
+
transitionAU(id, value, durationMs = 200, balance = this.core.get_au_balance(id)) {
|
|
8112
|
+
return this.transition(this.mutateLive(() => this.core.set_au_signed(id, value, balance), durationMs));
|
|
8113
|
+
}
|
|
8114
|
+
setViseme(index, value, jawScale = 1) {
|
|
8115
|
+
this.mutateLive(() => {
|
|
8116
|
+
this.core.set_viseme(index, value);
|
|
8117
|
+
this.core.set_viseme_jaw_scale(index, jawScale);
|
|
8118
|
+
});
|
|
8119
|
+
}
|
|
8120
|
+
getViseme(index) {
|
|
8121
|
+
return this.core.get_viseme(index);
|
|
8122
|
+
}
|
|
8123
|
+
getVisemeJawScale(index) {
|
|
8124
|
+
return this.core.get_viseme_jaw_scale(index);
|
|
8125
|
+
}
|
|
8126
|
+
setVisemeById(id, value, jawScale = 1) {
|
|
8127
|
+
const index = this.core.viseme_slot_index(id);
|
|
8128
|
+
if (index < 0) throw new Error(`Unknown viseme: ${id}`);
|
|
8129
|
+
this.setViseme(index, value, jawScale);
|
|
8130
|
+
}
|
|
8131
|
+
transitionViseme(index, value, durationMs = 80, jawScale = 1) {
|
|
8132
|
+
return this.transition(this.mutateLive(() => {
|
|
8133
|
+
this.core.set_viseme(index, value);
|
|
8134
|
+
this.core.set_viseme_jaw_scale(index, jawScale);
|
|
8135
|
+
}, durationMs));
|
|
8136
|
+
}
|
|
8137
|
+
transitionVisemeById(id, value, durationMs = 80, jawScale = 1) {
|
|
8138
|
+
const index = this.core.viseme_slot_index(id);
|
|
8139
|
+
if (index < 0) return this.transition([]);
|
|
8140
|
+
return this.transitionViseme(index, value, durationMs, jawScale);
|
|
8141
|
+
}
|
|
8142
|
+
setAUMixWeight(id, value) {
|
|
8143
|
+
var _a, _b;
|
|
8144
|
+
const weight = Math.max(0, Math.min(1, value));
|
|
8145
|
+
this.mutateLive(() => this.core.set_au_mix_weight(id, weight));
|
|
8146
|
+
((_a = this.profile).auMixDefaults ?? (_a.auMixDefaults = {}))[id] = weight;
|
|
8147
|
+
((_b = this.profileSource).auMixDefaults ?? (_b.auMixDefaults = {}))[id] = weight;
|
|
8148
|
+
}
|
|
8149
|
+
getAUMixWeight(id) {
|
|
8150
|
+
return this.core.get_au_mix_weight(id);
|
|
8151
|
+
}
|
|
8152
|
+
hasLeftRightBones(id) {
|
|
8153
|
+
return this.core.has_left_right_bones(id);
|
|
8154
|
+
}
|
|
8155
|
+
setMorph(key, value, meshNames = []) {
|
|
8156
|
+
this.mutateLive(() => {
|
|
8157
|
+
if (typeof key === "number") this.core.set_morph_index(key, value, json2(meshNames));
|
|
8158
|
+
else this.core.set_morph(key, value, json2(meshNames));
|
|
8159
|
+
});
|
|
8160
|
+
}
|
|
8161
|
+
setMorphOnMeshes(meshNames, key, value) {
|
|
8162
|
+
this.setMorph(key, value, meshNames);
|
|
8163
|
+
}
|
|
8164
|
+
releaseMorph(key, meshNames = []) {
|
|
8165
|
+
this.mutateLive(() => {
|
|
8166
|
+
if (typeof key === "number") this.core.release_morph_index(key, json2(meshNames));
|
|
8167
|
+
else this.core.release_morph(key, json2(meshNames));
|
|
8168
|
+
});
|
|
8169
|
+
}
|
|
8170
|
+
transitionMorph(key, value, durationMs = 120, meshNames = []) {
|
|
8171
|
+
return this.transition(this.mutateLive(() => {
|
|
8172
|
+
if (typeof key === "number") this.core.set_morph_index(key, value, json2(meshNames));
|
|
8173
|
+
else this.core.set_morph(key, value, json2(meshNames));
|
|
8174
|
+
}, durationMs));
|
|
8175
|
+
}
|
|
8176
|
+
getMorphTargets() {
|
|
8177
|
+
return Object.fromEntries(this.meshes.map((mesh) => [mesh.name, Object.keys(mesh.morphTargetDictionary ?? {}).sort()]));
|
|
8178
|
+
}
|
|
8179
|
+
getMorphTargetIndices() {
|
|
8180
|
+
return Object.fromEntries(this.meshes.map((mesh) => [mesh.name, Object.entries(mesh.morphTargetDictionary ?? {}).map(([name, index]) => ({ name, index })).sort((a, b) => a.index - b.index)]));
|
|
8181
|
+
}
|
|
8182
|
+
addMorphTarget(target, options) {
|
|
8183
|
+
const index = this.applier.addMorphTarget(this.requireModel(), target, options);
|
|
8184
|
+
this.bindModel();
|
|
8185
|
+
return index;
|
|
8186
|
+
}
|
|
8187
|
+
addMorphTargets(targets, options) {
|
|
8188
|
+
const result = this.applier.addMorphTargets(this.requireModel(), targets, options);
|
|
8189
|
+
this.bindModel();
|
|
8190
|
+
return result;
|
|
8191
|
+
}
|
|
8192
|
+
meshCategory(mesh) {
|
|
8193
|
+
return this.profile.meshes?.[mesh.name]?.category ?? "other";
|
|
8194
|
+
}
|
|
8195
|
+
getMeshList() {
|
|
8196
|
+
return (this.inspection?.allMeshes ?? []).map((mesh) => ({ name: mesh.name, visible: mesh.visible, morphCount: mesh.morphTargetInfluences?.length ?? 0, category: this.meshCategory(mesh) }));
|
|
8197
|
+
}
|
|
8198
|
+
getBones() {
|
|
8199
|
+
return this.bones;
|
|
8200
|
+
}
|
|
8201
|
+
meshProfile(name) {
|
|
8202
|
+
var _a, _b;
|
|
8203
|
+
return (_b = (_a = this.profile).meshes ?? (_a.meshes = {}))[name] ?? (_b[name] = { category: "other" });
|
|
8204
|
+
}
|
|
8205
|
+
setMeshVisible(name, visible) {
|
|
8206
|
+
this.applier.setMeshVisible(this.requireModel(), name, visible);
|
|
8207
|
+
this.meshProfile(name).visible = visible;
|
|
8208
|
+
}
|
|
8209
|
+
highlightMesh(name, color, value) {
|
|
8210
|
+
this.applier.highlightMesh(this.requireModel(), name, color, value);
|
|
8211
|
+
}
|
|
8212
|
+
getMeshMaterialConfig(name) {
|
|
8213
|
+
return this.applier.getMeshMaterialConfig(this.requireModel(), name);
|
|
8214
|
+
}
|
|
8215
|
+
setMeshMaterialConfig(name, value) {
|
|
8216
|
+
this.applier.setMeshMaterialConfig(this.requireModel(), name, value);
|
|
8217
|
+
const entry = this.meshProfile(name);
|
|
8218
|
+
entry.material = { ...entry.material, ...value };
|
|
8219
|
+
}
|
|
8220
|
+
registerHairObjects(objects) {
|
|
8221
|
+
this.hairObjects.clear();
|
|
8222
|
+
for (const object of objects) if (object.isMesh) this.hairObjects.set(object.name, object);
|
|
8223
|
+
for (const category of ["hair", "eyebrow"]) {
|
|
8224
|
+
const mesh = [...this.hairObjects.values()].find((object) => this.meshCategory(object) === category);
|
|
8225
|
+
const material = mesh && (Array.isArray(mesh.material) ? mesh.material[0] : mesh.material);
|
|
8226
|
+
if (material) this.hairAppearance[`${category}Color`] = { ...this.hairAppearance[`${category}Color`], baseColor: material.color ? `#${material.color.getHexString()}` : "#000000", emissive: material.emissive ? `#${material.emissive.getHexString()}` : "#000000", emissiveIntensity: material.emissiveIntensity ?? 0 };
|
|
8227
|
+
}
|
|
8228
|
+
this.restartHair();
|
|
8229
|
+
return [...this.hairObjects.values()].map((mesh) => ({ name: mesh.name, isMesh: true, isEyebrow: this.meshCategory(mesh) === "eyebrow" }));
|
|
8230
|
+
}
|
|
8231
|
+
getRegisteredHairObjects() {
|
|
8232
|
+
return [...this.hairObjects.values()];
|
|
8233
|
+
}
|
|
8234
|
+
getHairMorphTargets(name) {
|
|
8235
|
+
const meshes = name ? [this.hairObjects.get(name)] : [...this.hairObjects.values()];
|
|
8236
|
+
return [...new Set(meshes.flatMap((mesh) => Object.keys(mesh?.morphTargetDictionary ?? {})))].sort();
|
|
8237
|
+
}
|
|
8238
|
+
getHairAppearance() {
|
|
8239
|
+
return copy(this.hairAppearance);
|
|
8240
|
+
}
|
|
8241
|
+
setHairAppearance(category, value) {
|
|
8242
|
+
const key = `${category}Color`;
|
|
8243
|
+
const next = parse(this.wasm.normalize_hair_color_appearance_json(json2(value), json2(this.hairAppearance[key])));
|
|
8244
|
+
this.hairAppearance[key] = next;
|
|
8245
|
+
this.applier.applyHairAppearance([...this.hairObjects.values()].filter((mesh) => this.meshCategory(mesh) === category), next);
|
|
8246
|
+
}
|
|
8247
|
+
setHairColor(value) {
|
|
8248
|
+
this.setHairAppearance("hair", value);
|
|
8249
|
+
}
|
|
8250
|
+
setEyebrowColor(value) {
|
|
8251
|
+
this.setHairAppearance("eyebrow", value);
|
|
8252
|
+
}
|
|
8253
|
+
setHairBaseColor(value) {
|
|
8254
|
+
this.setHairColor({ baseColor: value });
|
|
8255
|
+
}
|
|
8256
|
+
setEyebrowBaseColor(value) {
|
|
8257
|
+
this.setEyebrowColor({ baseColor: value });
|
|
8258
|
+
}
|
|
8259
|
+
setHairGlow(color, value) {
|
|
8260
|
+
this.setHairColor({ emissive: color, emissiveIntensity: value });
|
|
8261
|
+
}
|
|
8262
|
+
setEyebrowGlow(color, value) {
|
|
8263
|
+
this.setEyebrowColor({ emissive: color, emissiveIntensity: value });
|
|
8264
|
+
}
|
|
8265
|
+
setHairOutline(value) {
|
|
8266
|
+
Object.assign(this.hairAppearance, { showOutline: value.show }, value.color ? { outlineColor: value.color } : {}, value.opacity !== void 0 ? { outlineOpacity: value.opacity } : {});
|
|
8267
|
+
}
|
|
8268
|
+
restartHair() {
|
|
8269
|
+
for (const name of [...this.current.keys()]) if (name.startsWith("__embody_hair")) this.stopAnimation(name);
|
|
8270
|
+
if (!this.hairConfig.enabled || !this.hairObjects.size || !this.connector) return;
|
|
8271
|
+
if (this.hairConfig.idleSwayAmount > 0 || this.hairConfig.windStrength > 0) {
|
|
8272
|
+
const curves = parse(this.wasm.build_hair_idle_curves(json2(this.hairConfig), this.hairConfig.idleClipDuration));
|
|
8273
|
+
if (Object.keys(curves).length) this.playSnippet("__embody_hair_idle", curves, { loopMode: "repeat", meshNames: [...this.hairObjects.keys()], source: "hair", blendMode: "additive" });
|
|
8274
|
+
}
|
|
8275
|
+
}
|
|
8276
|
+
setHairPhysicsEnabled(value) {
|
|
8277
|
+
this.setHairPhysicsConfig({ enabled: value });
|
|
8278
|
+
}
|
|
8279
|
+
isHairPhysicsEnabled() {
|
|
8280
|
+
return !!this.hairConfig.enabled;
|
|
8281
|
+
}
|
|
8282
|
+
setHairPhysicsConfig(value) {
|
|
8283
|
+
this.hairConfig = parse(this.core.set_hair_config_json(json2(value)));
|
|
8284
|
+
this.restartHair();
|
|
8285
|
+
}
|
|
8286
|
+
getHairPhysicsConfig() {
|
|
8287
|
+
return copy(this.hairConfig);
|
|
8288
|
+
}
|
|
8289
|
+
validateHairMorphTargets() {
|
|
8290
|
+
return parse(this.core.get_missing_hair_morph_targets_json(json2(this.getHairMorphTargets())));
|
|
8291
|
+
}
|
|
8292
|
+
applyHairStateToObject(name, state) {
|
|
8293
|
+
const mesh = this.hairObjects.get(name);
|
|
8294
|
+
if (!mesh) return;
|
|
8295
|
+
if (state.visible !== void 0) mesh.visible = state.visible;
|
|
8296
|
+
if (state.scale) mesh.scale.set(state.scale.x, state.scale.y, state.scale.z);
|
|
8297
|
+
if (state.position) mesh.position.set(state.position.x, state.position.y, state.position.z);
|
|
8298
|
+
if (state.color) this.applier.applyHairAppearance([mesh], state.color);
|
|
8299
|
+
}
|
|
8300
|
+
authoredHeadMotion(clip) {
|
|
8301
|
+
if (!this.hairConfig.enabled || clip.name.startsWith("__embody_hair") || !this.hairObjects.size) return void 0;
|
|
8302
|
+
const tracks = [];
|
|
8303
|
+
for (const track of clip.tracks) {
|
|
8304
|
+
if (track.ValueTypeName !== "quaternion") continue;
|
|
8305
|
+
const parsed = PropertyBinding.parseTrackName(track.name);
|
|
8306
|
+
let object = PropertyBinding.findNode(this.requireModel(), parsed.nodeName);
|
|
8307
|
+
if (parsed.objectName === "bones" && object) {
|
|
8308
|
+
const skeleton = object.skeleton;
|
|
8309
|
+
object = skeleton?.bones.find((bone) => bone.name === String(parsed.objectIndex)) ?? skeleton?.bones[Number(parsed.objectIndex)];
|
|
8310
|
+
}
|
|
8311
|
+
if (!object) continue;
|
|
8312
|
+
const cubic = track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true;
|
|
8313
|
+
const stride = track.getValueSize();
|
|
8314
|
+
const reference = this.restValues(track);
|
|
8315
|
+
if (!reference) continue;
|
|
8316
|
+
const samples = [];
|
|
8317
|
+
for (let index = 0; index < track.times.length; index += 1) {
|
|
8318
|
+
const offset = index * stride + (cubic ? 4 : 0);
|
|
8319
|
+
samples.push(Array.from(track.values.subarray(offset, offset + 4)));
|
|
8320
|
+
}
|
|
8321
|
+
tracks.push({ boneName: object.name, current: object.quaternion.toArray(), reference, samples });
|
|
8322
|
+
}
|
|
8323
|
+
return parse(this.core.resolve_hair_motion_json(json2(tracks), clip.blendMode === AdditiveAnimationBlendMode)) ?? void 0;
|
|
8324
|
+
}
|
|
8325
|
+
setHairGravity(pitch, durationSeconds) {
|
|
8326
|
+
const clip = parse(this.core.build_hair_gravity_clip("__embody_hair_gravity", pitch, durationSeconds, json2({ meshNames: [...this.hairObjects.keys()], source: "hair" })));
|
|
8327
|
+
if (!clip.tracks.length) return;
|
|
8328
|
+
this.handle({ name: clip.name, kind: "compiled", clip }, { loopMode: "once", finalPose: "hold", blendMode: "additive" }, true);
|
|
8329
|
+
}
|
|
8330
|
+
playHairImpulse(horizontal, vertical) {
|
|
8331
|
+
if (!this.hairConfig.enabled || !this.hairObjects.size) return void 0;
|
|
8332
|
+
const curves = parse(this.wasm.build_hair_impulse_curves(json2(this.hairConfig), this.hairConfig.impulseClipDuration, horizontal, vertical));
|
|
8333
|
+
if (!Object.keys(curves).length) return void 0;
|
|
8334
|
+
return this.playSnippet("__embody_hair_impulse", curves, { loopMode: "once", finalPose: "release", meshNames: [...this.hairObjects.keys()], source: "hair", blendMode: "additive" });
|
|
8335
|
+
}
|
|
8336
|
+
start() {
|
|
8337
|
+
this.assertAlive();
|
|
8338
|
+
this.rendering = true;
|
|
8339
|
+
this.connector?.setRendering(true);
|
|
8340
|
+
}
|
|
8341
|
+
stop() {
|
|
8342
|
+
this.assertAlive();
|
|
8343
|
+
this.rendering = false;
|
|
8344
|
+
this.connector?.setRendering(false);
|
|
8345
|
+
}
|
|
8346
|
+
clear() {
|
|
8347
|
+
this.mutateLive(() => this.core.clear());
|
|
8348
|
+
}
|
|
8349
|
+
resetToNeutral() {
|
|
8350
|
+
this.clear();
|
|
8351
|
+
}
|
|
8352
|
+
dispose() {
|
|
8353
|
+
if (this.disposed) return;
|
|
8354
|
+
this.connector?.dispose();
|
|
8355
|
+
this.core.free();
|
|
8356
|
+
this.playbacks.clear();
|
|
8357
|
+
this.current.clear();
|
|
8358
|
+
this.sources.clear();
|
|
8359
|
+
this.hairObjects.clear();
|
|
8360
|
+
this.meshes.length = 0;
|
|
8361
|
+
this.meshByName.clear();
|
|
8362
|
+
this.bones = {};
|
|
8363
|
+
this.liveTargets.clear();
|
|
8364
|
+
this.connector = void 0;
|
|
8365
|
+
this.inspection = void 0;
|
|
8366
|
+
this.boundModel = void 0;
|
|
8367
|
+
this.disposed = true;
|
|
8368
|
+
}
|
|
8369
|
+
};
|
|
8370
|
+
function createRustEmbodyHostUnbound(config = {}) {
|
|
8371
|
+
return new Embody(config);
|
|
8372
|
+
}
|
|
8373
|
+
async function createRustEmbodyHost(model, config = {}) {
|
|
8374
|
+
const character = await Embody.create(config);
|
|
8375
|
+
try {
|
|
8376
|
+
character.onReady({ model, meshes: config.meshes, referencePose: config.referencePose });
|
|
8377
|
+
return character;
|
|
8378
|
+
} catch (error) {
|
|
8379
|
+
character.dispose();
|
|
8380
|
+
throw error;
|
|
8381
|
+
}
|
|
8382
|
+
}
|
|
8383
|
+
var draco = null;
|
|
8384
|
+
var dracoPath = "";
|
|
8385
|
+
var gltfLoader = null;
|
|
8386
|
+
var gltfLoaderUsesDraco = false;
|
|
8387
|
+
var fbxLoader = null;
|
|
8388
|
+
var getGltfLoader = (dracoDecoderPath) => {
|
|
8389
|
+
const wantsDraco = typeof dracoDecoderPath === "string" && dracoDecoderPath.length > 0;
|
|
8390
|
+
const normalizedPath = wantsDraco ? dracoDecoderPath.endsWith("/") ? dracoDecoderPath : `${dracoDecoderPath}/` : "";
|
|
8391
|
+
if (!gltfLoader || gltfLoaderUsesDraco !== wantsDraco || wantsDraco && normalizedPath !== dracoPath) {
|
|
8392
|
+
draco?.dispose();
|
|
8393
|
+
draco = null;
|
|
8394
|
+
dracoPath = normalizedPath;
|
|
8395
|
+
gltfLoaderUsesDraco = wantsDraco;
|
|
8396
|
+
gltfLoader = new GLTFLoader();
|
|
8397
|
+
if (wantsDraco) {
|
|
8398
|
+
draco = new DRACOLoader().setDecoderPath(normalizedPath).setDecoderConfig({ type: "wasm" });
|
|
8399
|
+
gltfLoader.setDRACOLoader(draco);
|
|
8400
|
+
}
|
|
8401
|
+
}
|
|
8402
|
+
return gltfLoader;
|
|
8403
|
+
};
|
|
8404
|
+
var prepare = (model, castShadows = true) => {
|
|
8405
|
+
const meshes = [];
|
|
8406
|
+
model.traverse((object) => {
|
|
8407
|
+
if (!object.isMesh) return;
|
|
8408
|
+
if (castShadows) object.castShadow = true;
|
|
8409
|
+
if (object.morphTargetInfluences?.length) meshes.push(object);
|
|
8410
|
+
});
|
|
8411
|
+
return meshes;
|
|
8412
|
+
};
|
|
8413
|
+
var progress = (listener) => {
|
|
8414
|
+
let last = -1;
|
|
8415
|
+
return (event) => {
|
|
8416
|
+
if (!listener || !event.lengthComputable) return;
|
|
8417
|
+
const next = Math.min(100, Math.max(0, Math.round(event.loaded / event.total * 100)));
|
|
8418
|
+
if (next !== last) {
|
|
8419
|
+
last = next;
|
|
8420
|
+
listener(next);
|
|
8421
|
+
}
|
|
8422
|
+
};
|
|
8423
|
+
};
|
|
8424
|
+
function applyCharacterModelTransform(model, value = {}) {
|
|
8425
|
+
if (value.modelOffset) model.position.set(value.modelOffset.x ?? 0, value.modelOffset.y ?? 0, value.modelOffset.z ?? 0);
|
|
8426
|
+
if (value.modelRotation) model.rotation.set(...["x", "y", "z"].map((axis) => (value.modelRotation?.[axis] ?? 0) * Math.PI / 180));
|
|
8427
|
+
if (Number.isFinite(value.modelScale) && (value.modelScale ?? 0) > 0) model.scale.setScalar(value.modelScale);
|
|
8428
|
+
if (Number.isFinite(value.modelGroundClearance)) {
|
|
8429
|
+
model.updateMatrixWorld(true);
|
|
8430
|
+
const min = new Box3().setFromObject(model).min.y;
|
|
8431
|
+
if (Number.isFinite(min) && min < value.modelGroundClearance) model.position.y += value.modelGroundClearance - min;
|
|
8432
|
+
}
|
|
8433
|
+
}
|
|
8434
|
+
function disposeCharacterModel(scene, model) {
|
|
8435
|
+
scene?.remove(model);
|
|
8436
|
+
model.traverse((object) => {
|
|
8437
|
+
object.geometry?.dispose?.();
|
|
6942
8438
|
for (const material of object.material ? Array.isArray(object.material) ? object.material : [object.material] : []) {
|
|
6943
8439
|
for (const value of Object.values(material)) if (value?.isTexture) value.dispose?.();
|
|
6944
8440
|
material.dispose?.();
|
|
@@ -7375,7 +8871,7 @@ function createDefaultCharacterSceneRuntime(container, options = {}) {
|
|
|
7375
8871
|
let disposed = false;
|
|
7376
8872
|
let disposal = null;
|
|
7377
8873
|
let generation = 0;
|
|
7378
|
-
let
|
|
8874
|
+
let pending = null;
|
|
7379
8875
|
let pendingRendererChange = null;
|
|
7380
8876
|
let leaseCount = 0;
|
|
7381
8877
|
let pendingResourceReleases = 0;
|
|
@@ -7437,8 +8933,8 @@ function createDefaultCharacterSceneRuntime(container, options = {}) {
|
|
|
7437
8933
|
if (pendingRendererChange && preference === settings.preference && (status === "initializing" || status === "switching")) return pendingRendererChange;
|
|
7438
8934
|
if (status === "ready" && preference === settings.preference) return Promise.resolve(getSnapshot());
|
|
7439
8935
|
settings = { preference };
|
|
7440
|
-
const
|
|
7441
|
-
const previous =
|
|
8936
|
+
const request3 = ++generation;
|
|
8937
|
+
const previous = pending;
|
|
7442
8938
|
status = active ? "switching" : "initializing";
|
|
7443
8939
|
error = null;
|
|
7444
8940
|
const execute = async () => {
|
|
@@ -7451,7 +8947,7 @@ function createDefaultCharacterSceneRuntime(container, options = {}) {
|
|
|
7451
8947
|
let restoreModelSkinning = () => {
|
|
7452
8948
|
};
|
|
7453
8949
|
const check = () => {
|
|
7454
|
-
if (disposed || generation !==
|
|
8950
|
+
if (disposed || generation !== request3) throw renderingAborted();
|
|
7455
8951
|
if (!active) throwIfAborted(options.signal);
|
|
7456
8952
|
if (candidate?.lost) throw candidate.lost;
|
|
7457
8953
|
};
|
|
@@ -7534,7 +9030,7 @@ function createDefaultCharacterSceneRuntime(container, options = {}) {
|
|
|
7534
9030
|
if (attached && candidate?.renderer.domElement.parentElement === container) container.removeChild(candidate.renderer.domElement);
|
|
7535
9031
|
rollback(() => environment?.dispose());
|
|
7536
9032
|
rollback(() => candidate?.dispose());
|
|
7537
|
-
const canceled = disposed || generation !==
|
|
9033
|
+
const canceled = disposed || generation !== request3 || !active && options.signal?.aborted;
|
|
7538
9034
|
if (!disposed) {
|
|
7539
9035
|
rollback(restoreModelSkinning);
|
|
7540
9036
|
rollback(restoreCameraCoordinates);
|
|
@@ -7546,7 +9042,7 @@ function createDefaultCharacterSceneRuntime(container, options = {}) {
|
|
|
7546
9042
|
owner.reportFailure(resumeError, active.renderer);
|
|
7547
9043
|
}
|
|
7548
9044
|
}
|
|
7549
|
-
if (generation ===
|
|
9045
|
+
if (generation === request3) {
|
|
7550
9046
|
status = active?.lost ? "lost" : "error";
|
|
7551
9047
|
error = failure instanceof Error ? failure : new Error(String(failure));
|
|
7552
9048
|
notify();
|
|
@@ -7559,11 +9055,11 @@ function createDefaultCharacterSceneRuntime(container, options = {}) {
|
|
|
7559
9055
|
}
|
|
7560
9056
|
};
|
|
7561
9057
|
const operation = previous ? previous.catch(() => void 0).then(execute) : Promise.resolve().then(execute);
|
|
7562
|
-
|
|
9058
|
+
pending = operation;
|
|
7563
9059
|
pendingRendererChange = operation;
|
|
7564
9060
|
notify();
|
|
7565
9061
|
const settled = () => {
|
|
7566
|
-
if (
|
|
9062
|
+
if (pending === operation) pending = null;
|
|
7567
9063
|
if (pendingRendererChange === operation) pendingRendererChange = null;
|
|
7568
9064
|
};
|
|
7569
9065
|
void operation.then(settled, settled);
|
|
@@ -7603,7 +9099,7 @@ function createDefaultCharacterSceneRuntime(container, options = {}) {
|
|
|
7603
9099
|
},
|
|
7604
9100
|
releaseSceneResources: (release) => {
|
|
7605
9101
|
if (disposal) return disposal.then(release, release);
|
|
7606
|
-
const previous =
|
|
9102
|
+
const previous = pending;
|
|
7607
9103
|
pendingResourceReleases++;
|
|
7608
9104
|
const operation = Promise.resolve(previous).catch(() => void 0).then(async () => {
|
|
7609
9105
|
if (leaseCount) await leaseBarrier;
|
|
@@ -7622,16 +9118,16 @@ function createDefaultCharacterSceneRuntime(container, options = {}) {
|
|
|
7622
9118
|
}).finally(() => {
|
|
7623
9119
|
pendingResourceReleases--;
|
|
7624
9120
|
});
|
|
7625
|
-
|
|
9121
|
+
pending = operation;
|
|
7626
9122
|
void operation.then(() => {
|
|
7627
|
-
if (
|
|
9123
|
+
if (pending === operation) pending = null;
|
|
7628
9124
|
}, () => {
|
|
7629
|
-
if (
|
|
9125
|
+
if (pending === operation) pending = null;
|
|
7630
9126
|
});
|
|
7631
9127
|
return operation.then(() => void 0);
|
|
7632
9128
|
}
|
|
7633
9129
|
};
|
|
7634
|
-
const owner = registerSceneRendering(rendering, scene, camera, () =>
|
|
9130
|
+
const owner = registerSceneRendering(rendering, scene, camera, () => pending, (failure, renderer) => {
|
|
7635
9131
|
if (disposed) return;
|
|
7636
9132
|
const problem = failure instanceof Error ? failure : new Error(String(failure));
|
|
7637
9133
|
if (candidateInUse && renderer === candidateInUse.renderer && renderer !== active?.renderer) {
|
|
@@ -7674,7 +9170,7 @@ function createDefaultCharacterSceneRuntime(container, options = {}) {
|
|
|
7674
9170
|
reject(failure);
|
|
7675
9171
|
}
|
|
7676
9172
|
};
|
|
7677
|
-
if (
|
|
9173
|
+
if (pending || leaseCount || drain) void Promise.allSettled([pending, drain, leaseBarrier]).then(cleanup);
|
|
7678
9174
|
else cleanup();
|
|
7679
9175
|
return disposal;
|
|
7680
9176
|
};
|
|
@@ -7723,6 +9219,184 @@ async function createDefaultCharacterSceneAsync(container, options = {}) {
|
|
|
7723
9219
|
}
|
|
7724
9220
|
}
|
|
7725
9221
|
|
|
9222
|
+
// three/characterHost.ts
|
|
9223
|
+
async function createCharacterHost(options) {
|
|
9224
|
+
if (!options.container) throw new Error("createCharacterHost requires a container HTMLElement");
|
|
9225
|
+
if (!options.character?.modelUrl) throw new Error("createCharacterHost requires character.modelUrl");
|
|
9226
|
+
let loaded;
|
|
9227
|
+
let state;
|
|
9228
|
+
let engine;
|
|
9229
|
+
let controller;
|
|
9230
|
+
let disposed = false;
|
|
9231
|
+
let disposal;
|
|
9232
|
+
let switching = Promise.resolve();
|
|
9233
|
+
let mountedCanvas;
|
|
9234
|
+
const aborted = () => new DOMException("Character host creation was aborted", "AbortError");
|
|
9235
|
+
const checkCreation = () => {
|
|
9236
|
+
if (options.signal?.aborted) throw aborted();
|
|
9237
|
+
};
|
|
9238
|
+
const releaseModel = async (value) => {
|
|
9239
|
+
const release = () => disposeCharacterModel(state?.scene ?? null, value.model);
|
|
9240
|
+
if (state?.rendering) await state.rendering.releaseSceneResources(release);
|
|
9241
|
+
else release();
|
|
9242
|
+
};
|
|
9243
|
+
const makeEngine = (value, character) => {
|
|
9244
|
+
const next = new Embody({ ...options.embody, presetType: character.presetType ?? options.embody?.presetType, profile: character.profile ?? options.embody?.profile });
|
|
9245
|
+
try {
|
|
9246
|
+
next.onReady(value);
|
|
9247
|
+
return next;
|
|
9248
|
+
} catch (error) {
|
|
9249
|
+
try {
|
|
9250
|
+
next.dispose();
|
|
9251
|
+
} catch {
|
|
9252
|
+
}
|
|
9253
|
+
throw error;
|
|
9254
|
+
}
|
|
9255
|
+
};
|
|
9256
|
+
const dispose = () => {
|
|
9257
|
+
if (disposal) return disposal;
|
|
9258
|
+
disposed = true;
|
|
9259
|
+
disposal = (async () => {
|
|
9260
|
+
let failure;
|
|
9261
|
+
const attempt = async (release) => {
|
|
9262
|
+
try {
|
|
9263
|
+
await release();
|
|
9264
|
+
} catch (error) {
|
|
9265
|
+
failure ?? (failure = error);
|
|
9266
|
+
}
|
|
9267
|
+
};
|
|
9268
|
+
await attempt(() => controller?.dispose());
|
|
9269
|
+
await switching.catch(() => {
|
|
9270
|
+
});
|
|
9271
|
+
await attempt(() => engine?.dispose());
|
|
9272
|
+
const ownedScene = !options.external && state && "dispose" in state ? state : void 0;
|
|
9273
|
+
if (ownedScene) await attempt(() => ownedScene.dispose());
|
|
9274
|
+
const lastModel = loaded;
|
|
9275
|
+
if (lastModel) await attempt(() => releaseModel(lastModel));
|
|
9276
|
+
mountedCanvas?.remove();
|
|
9277
|
+
if (failure !== void 0) throw failure;
|
|
9278
|
+
})();
|
|
9279
|
+
return disposal;
|
|
9280
|
+
};
|
|
9281
|
+
try {
|
|
9282
|
+
checkCreation();
|
|
9283
|
+
loaded = await loadCharacterModel(options.character.modelUrl, options.loader);
|
|
9284
|
+
checkCreation();
|
|
9285
|
+
state = options.external ?? await createDefaultCharacterSceneAsync(options.container, { ...options.scene, signal: options.signal });
|
|
9286
|
+
checkCreation();
|
|
9287
|
+
await initEmbodyCore();
|
|
9288
|
+
checkCreation();
|
|
9289
|
+
applyCharacterModelTransform(loaded.model, options.character);
|
|
9290
|
+
state.scene.add(loaded.model);
|
|
9291
|
+
engine = makeEngine(loaded, options.character);
|
|
9292
|
+
if (options.external?.mountCanvas && !state.renderer.domElement.parentElement) {
|
|
9293
|
+
mountedCanvas = state.renderer.domElement;
|
|
9294
|
+
options.container.appendChild(mountedCanvas);
|
|
9295
|
+
}
|
|
9296
|
+
if (options.renderLoop ?? !options.external) {
|
|
9297
|
+
if (!(state.camera instanceof PerspectiveCamera)) throw new Error("Character host rendering requires a PerspectiveCamera");
|
|
9298
|
+
controller = new DPthreeCameraController({
|
|
9299
|
+
scene: state.scene,
|
|
9300
|
+
camera: state.camera,
|
|
9301
|
+
domElement: state.renderer.domElement,
|
|
9302
|
+
...state.rendering ? { rendering: state.rendering } : { renderer: state.renderer },
|
|
9303
|
+
showDOMControls: false
|
|
9304
|
+
});
|
|
9305
|
+
controller.setModel(loaded.model);
|
|
9306
|
+
await controller.prepareModelForRender(loaded.model, { signal: options.signal });
|
|
9307
|
+
if (options.autoFrame !== false) await controller.focusFullBody(0);
|
|
9308
|
+
}
|
|
9309
|
+
checkCreation();
|
|
9310
|
+
if (options.autoStart === false) engine.stop();
|
|
9311
|
+
else engine.start();
|
|
9312
|
+
const sceneState = state;
|
|
9313
|
+
const rendering = state.rendering ?? null;
|
|
9314
|
+
const host = {
|
|
9315
|
+
engine,
|
|
9316
|
+
scene: state.scene,
|
|
9317
|
+
camera: state.camera,
|
|
9318
|
+
get renderer() {
|
|
9319
|
+
return rendering ? rendering.getSnapshot().renderer : sceneState.renderer;
|
|
9320
|
+
},
|
|
9321
|
+
get backend() {
|
|
9322
|
+
return rendering ? rendering.getSnapshot().backend : sceneState.backend ?? null;
|
|
9323
|
+
},
|
|
9324
|
+
rendering,
|
|
9325
|
+
model: loaded.model,
|
|
9326
|
+
meshes: loaded.meshes,
|
|
9327
|
+
animations: loaded.animations,
|
|
9328
|
+
lighting: "lighting" in state ? state.lighting : null,
|
|
9329
|
+
ownsScene: !options.external,
|
|
9330
|
+
container: options.container,
|
|
9331
|
+
resize() {
|
|
9332
|
+
if ("resize" in sceneState) sceneState.resize();
|
|
9333
|
+
},
|
|
9334
|
+
setCharacter(character, loader = options.loader) {
|
|
9335
|
+
if (disposed) return Promise.reject(new Error("Character host is disposed"));
|
|
9336
|
+
const change = switching.catch(() => {
|
|
9337
|
+
}).then(async () => {
|
|
9338
|
+
if (disposed) throw new Error("Character host is disposed");
|
|
9339
|
+
const next = await loadCharacterModel(character.modelUrl, loader);
|
|
9340
|
+
let nextEngine;
|
|
9341
|
+
try {
|
|
9342
|
+
if (disposed) throw new Error("Character host is disposed");
|
|
9343
|
+
applyCharacterModelTransform(next.model, character);
|
|
9344
|
+
nextEngine = makeEngine(next, character);
|
|
9345
|
+
nextEngine.stop();
|
|
9346
|
+
sceneState.scene.add(next.model);
|
|
9347
|
+
if (controller) await controller.prepareModelForRender(next.model);
|
|
9348
|
+
if (disposed) throw new Error("Character host is disposed");
|
|
9349
|
+
} catch (error) {
|
|
9350
|
+
try {
|
|
9351
|
+
nextEngine?.dispose();
|
|
9352
|
+
} catch {
|
|
9353
|
+
}
|
|
9354
|
+
try {
|
|
9355
|
+
await releaseModel(next);
|
|
9356
|
+
} catch {
|
|
9357
|
+
}
|
|
9358
|
+
throw error;
|
|
9359
|
+
}
|
|
9360
|
+
const previous = loaded;
|
|
9361
|
+
try {
|
|
9362
|
+
engine.dispose();
|
|
9363
|
+
} catch (error) {
|
|
9364
|
+
try {
|
|
9365
|
+
nextEngine?.dispose();
|
|
9366
|
+
} catch {
|
|
9367
|
+
}
|
|
9368
|
+
try {
|
|
9369
|
+
await releaseModel(next);
|
|
9370
|
+
} catch {
|
|
9371
|
+
}
|
|
9372
|
+
throw error;
|
|
9373
|
+
}
|
|
9374
|
+
engine = nextEngine;
|
|
9375
|
+
loaded = next;
|
|
9376
|
+
host.engine = engine;
|
|
9377
|
+
host.model = next.model;
|
|
9378
|
+
host.meshes = next.meshes;
|
|
9379
|
+
host.animations = next.animations;
|
|
9380
|
+
controller?.setModel(next.model);
|
|
9381
|
+
if (options.autoStart !== false) engine.start();
|
|
9382
|
+
await releaseModel(previous);
|
|
9383
|
+
if (controller && options.autoFrame !== false) await controller.focusFullBody(0);
|
|
9384
|
+
});
|
|
9385
|
+
switching = change;
|
|
9386
|
+
return change;
|
|
9387
|
+
},
|
|
9388
|
+
dispose
|
|
9389
|
+
};
|
|
9390
|
+
return host;
|
|
9391
|
+
} catch (error) {
|
|
9392
|
+
try {
|
|
9393
|
+
await dispose();
|
|
9394
|
+
} catch {
|
|
9395
|
+
}
|
|
9396
|
+
throw error;
|
|
9397
|
+
}
|
|
9398
|
+
}
|
|
9399
|
+
|
|
7726
9400
|
// three/index.ts
|
|
7727
9401
|
var THREE_BLENDING_MODES = {
|
|
7728
9402
|
Normal: NormalBlending,
|
|
@@ -7731,6 +9405,7 @@ var THREE_BLENDING_MODES = {
|
|
|
7731
9405
|
Multiply: MultiplyBlending,
|
|
7732
9406
|
None: NoBlending
|
|
7733
9407
|
};
|
|
9408
|
+
var BLENDING_MODES = THREE_BLENDING_MODES;
|
|
7734
9409
|
var MORPH_ATTRIBUTE_SEMANTICS = ["position", "normal", "tangent", "color"];
|
|
7735
9410
|
var createNeutralMorphAttribute = (geometry, semantic, name) => {
|
|
7736
9411
|
const base = geometry.getAttribute(semantic);
|
|
@@ -7925,6 +9600,8 @@ function createAnimationClipFromClipIR(clip, inspection) {
|
|
|
7925
9600
|
const tracks = [];
|
|
7926
9601
|
for (const track of clip.tracks ?? []) {
|
|
7927
9602
|
const kind = track.target?.kind;
|
|
9603
|
+
const trackName = concreteTrackName(track.target, inspection);
|
|
9604
|
+
if (!trackName) continue;
|
|
7928
9605
|
const times = Array.from(track.times ?? []);
|
|
7929
9606
|
const values = Array.from(track.values ?? []);
|
|
7930
9607
|
if (!times.length || !values.length) continue;
|
|
@@ -7932,7 +9609,6 @@ function createAnimationClipFromClipIR(clip, inspection) {
|
|
|
7932
9609
|
if (kind === "morphTarget") {
|
|
7933
9610
|
const binding = inspection.morphBindings.get(Number(track.target.morphTargetId));
|
|
7934
9611
|
if (!binding?.mesh) continue;
|
|
7935
|
-
const trackName = `${binding.mesh.uuid}.morphTargetInfluences[${binding.index}]`;
|
|
7936
9612
|
if (track.inheritStart) {
|
|
7937
9613
|
values[0] = binding.mesh.morphTargetInfluences?.[binding.index] ?? 0;
|
|
7938
9614
|
}
|
|
@@ -7945,13 +9621,17 @@ function createAnimationClipFromClipIR(clip, inspection) {
|
|
|
7945
9621
|
const property = track.target.property ?? "rotation";
|
|
7946
9622
|
if (property === "rotation" || property === "quaternion") {
|
|
7947
9623
|
if (track.inheritStart) object.quaternion.toArray(values, 0);
|
|
7948
|
-
tracks.push(new QuaternionKeyframeTrack(
|
|
9624
|
+
tracks.push(new QuaternionKeyframeTrack(trackName, times, values, interpolation));
|
|
9625
|
+
} else if (property === "eulerX" || property === "eulerY" || property === "eulerZ") {
|
|
9626
|
+
const axis = property.slice(-1).toLowerCase();
|
|
9627
|
+
if (track.inheritStart) values[0] = object.rotation[axis];
|
|
9628
|
+
tracks.push(new NumberKeyframeTrack(trackName, times, values, interpolation));
|
|
7949
9629
|
} else if (property === "position") {
|
|
7950
9630
|
if (track.inheritStart) object.position.toArray(values, 0);
|
|
7951
|
-
tracks.push(new VectorKeyframeTrack(
|
|
9631
|
+
tracks.push(new VectorKeyframeTrack(trackName, times, values, interpolation));
|
|
7952
9632
|
} else if (property === "scale") {
|
|
7953
9633
|
if (track.inheritStart) object.scale.toArray(values, 0);
|
|
7954
|
-
tracks.push(new VectorKeyframeTrack(
|
|
9634
|
+
tracks.push(new VectorKeyframeTrack(trackName, times, values, interpolation));
|
|
7955
9635
|
}
|
|
7956
9636
|
continue;
|
|
7957
9637
|
}
|
|
@@ -7959,7 +9639,7 @@ function createAnimationClipFromClipIR(clip, inspection) {
|
|
|
7959
9639
|
const mesh = inspection.meshBindings.get(Number(track.target.meshId));
|
|
7960
9640
|
if (!mesh) continue;
|
|
7961
9641
|
if (track.inheritStart) values[0] = Number(mesh.visible);
|
|
7962
|
-
tracks.push(new NumberKeyframeTrack(
|
|
9642
|
+
tracks.push(new NumberKeyframeTrack(trackName, times, values, interpolation));
|
|
7963
9643
|
}
|
|
7964
9644
|
}
|
|
7965
9645
|
const duration = Number.isFinite(clip.durationSeconds) ? Number(clip.durationSeconds) : -1;
|
|
@@ -7979,7 +9659,7 @@ function serializeAnimationClips(model, clips, inspection) {
|
|
|
7979
9659
|
channelKinds.set(kind, id);
|
|
7980
9660
|
return id;
|
|
7981
9661
|
};
|
|
7982
|
-
clip.tracks.forEach((track, index) => {
|
|
9662
|
+
withComponentTracks(clip).tracks.forEach((track, index) => {
|
|
7983
9663
|
const found = findTrackTarget(model, track);
|
|
7984
9664
|
if (!found?.object) return;
|
|
7985
9665
|
const { parsed, object } = found;
|
|
@@ -7994,7 +9674,7 @@ function serializeAnimationClips(model, clips, inspection) {
|
|
|
7994
9674
|
} else if (property === "visible" && object.isMesh) {
|
|
7995
9675
|
target = { kind: "meshVisibility", meshId: meshIds.get(object) };
|
|
7996
9676
|
} else {
|
|
7997
|
-
const transformProperty = property === "
|
|
9677
|
+
const transformProperty = property === "rotation" && ["x", "y", "z"].includes(String(parsed.propertyIndex)) ? `euler${String(parsed.propertyIndex).toUpperCase()}` : property === "quaternion" ? "rotation" : property === "position" ? "position" : property === "scale" ? "scale" : null;
|
|
7998
9678
|
if (transformProperty) {
|
|
7999
9679
|
const boneId = boneIds.get(object);
|
|
8000
9680
|
target = boneId ? { kind: "boneTransform", boneId, property: transformProperty } : { kind: "objectTransform", objectId: objectIds.get(object), property: transformProperty };
|
|
@@ -8002,14 +9682,19 @@ function serializeAnimationClips(model, clips, inspection) {
|
|
|
8002
9682
|
}
|
|
8003
9683
|
if (!target) return;
|
|
8004
9684
|
const kind = target.kind === "morphTarget" ? "face" : target.kind === "boneTransform" ? "body" : "scene";
|
|
8005
|
-
const
|
|
9685
|
+
const cubic = !!track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline;
|
|
9686
|
+
const size = track.getValueSize() / (cubic ? 3 : 1);
|
|
9687
|
+
if (!Array.from(track.values).every(Number.isFinite)) {
|
|
9688
|
+
throw new Error(`Animation track ${JSON.stringify(track.name)} contains non-finite samples.`);
|
|
9689
|
+
}
|
|
9690
|
+
const values = cubic ? Array.from(track.times).flatMap((_, key) => Array.from(track.values.slice((key * 3 + 1) * size, (key * 3 + 2) * size))) : Array.from(track.values);
|
|
8006
9691
|
tracks.push({
|
|
8007
9692
|
id: index + 1,
|
|
8008
9693
|
channelId: channelId(kind),
|
|
8009
9694
|
target,
|
|
8010
9695
|
valueType: size === 4 ? "quat" : size === 3 ? "vec3" : "scalar",
|
|
8011
9696
|
times: Array.from(track.times),
|
|
8012
|
-
values
|
|
9697
|
+
values,
|
|
8013
9698
|
interpolation: track.getInterpolation() === InterpolateDiscrete ? "step" : "linear",
|
|
8014
9699
|
sourceName: track.name
|
|
8015
9700
|
});
|
|
@@ -8098,7 +9783,7 @@ var ThreeFrameApplier = class {
|
|
|
8098
9783
|
mesh.visible = visible;
|
|
8099
9784
|
});
|
|
8100
9785
|
}
|
|
8101
|
-
highlightMesh(root, name, color = 65535,
|
|
9786
|
+
highlightMesh(root, name, color = 65535, intensity2 = 0.5) {
|
|
8102
9787
|
root.traverse((object) => {
|
|
8103
9788
|
if (!object.isMesh) return;
|
|
8104
9789
|
for (const material of materials(object.material)) {
|
|
@@ -8107,7 +9792,7 @@ var ThreeFrameApplier = class {
|
|
|
8107
9792
|
if (name === object.name) {
|
|
8108
9793
|
if (!this.originalEmissive.has(key)) this.originalEmissive.set(key, { color: material.emissive.getHex(), intensity: material.emissiveIntensity ?? 0 });
|
|
8109
9794
|
material.emissive.setHex(color);
|
|
8110
|
-
material.emissiveIntensity =
|
|
9795
|
+
material.emissiveIntensity = intensity2;
|
|
8111
9796
|
} else {
|
|
8112
9797
|
const original = this.originalEmissive.get(key);
|
|
8113
9798
|
if (original) {
|
|
@@ -8276,1072 +9961,6 @@ var collectMorphMeshes = (root) => {
|
|
|
8276
9961
|
return meshes;
|
|
8277
9962
|
};
|
|
8278
9963
|
|
|
8279
|
-
|
|
8280
|
-
var cc4_default = {
|
|
8281
|
-
hairColorPresets: {
|
|
8282
|
-
natural_black: {
|
|
8283
|
-
name: "Natural Black",
|
|
8284
|
-
baseColor: "#1a1a1a",
|
|
8285
|
-
emissive: "#000000",
|
|
8286
|
-
emissiveIntensity: 0
|
|
8287
|
-
},
|
|
8288
|
-
natural_brown: {
|
|
8289
|
-
name: "Natural Brown",
|
|
8290
|
-
baseColor: "#4a3728",
|
|
8291
|
-
emissive: "#000000",
|
|
8292
|
-
emissiveIntensity: 0
|
|
8293
|
-
},
|
|
8294
|
-
natural_blonde: {
|
|
8295
|
-
name: "Natural Blonde",
|
|
8296
|
-
baseColor: "#e6c78a",
|
|
8297
|
-
emissive: "#000000",
|
|
8298
|
-
emissiveIntensity: 0
|
|
8299
|
-
},
|
|
8300
|
-
natural_red: {
|
|
8301
|
-
name: "Natural Red",
|
|
8302
|
-
baseColor: "#8b3a3a",
|
|
8303
|
-
emissive: "#000000",
|
|
8304
|
-
emissiveIntensity: 0
|
|
8305
|
-
},
|
|
8306
|
-
natural_gray: {
|
|
8307
|
-
name: "Natural Gray",
|
|
8308
|
-
baseColor: "#9e9e9e",
|
|
8309
|
-
emissive: "#000000",
|
|
8310
|
-
emissiveIntensity: 0
|
|
8311
|
-
},
|
|
8312
|
-
natural_white: {
|
|
8313
|
-
name: "Natural White",
|
|
8314
|
-
baseColor: "#f5f5f5",
|
|
8315
|
-
emissive: "#000000",
|
|
8316
|
-
emissiveIntensity: 0
|
|
8317
|
-
},
|
|
8318
|
-
neon_blue: {
|
|
8319
|
-
name: "Neon Blue",
|
|
8320
|
-
baseColor: "#00ffff",
|
|
8321
|
-
emissive: "#0000ff",
|
|
8322
|
-
emissiveIntensity: 0.8
|
|
8323
|
-
},
|
|
8324
|
-
neon_pink: {
|
|
8325
|
-
name: "Neon Pink",
|
|
8326
|
-
baseColor: "#ff00ff",
|
|
8327
|
-
emissive: "#ff1493",
|
|
8328
|
-
emissiveIntensity: 0.8
|
|
8329
|
-
},
|
|
8330
|
-
neon_green: {
|
|
8331
|
-
name: "Neon Green",
|
|
8332
|
-
baseColor: "#00ff00",
|
|
8333
|
-
emissive: "#00ff00",
|
|
8334
|
-
emissiveIntensity: 0.8
|
|
8335
|
-
},
|
|
8336
|
-
electric_purple: {
|
|
8337
|
-
name: "Electric Purple",
|
|
8338
|
-
baseColor: "#9d00ff",
|
|
8339
|
-
emissive: "#9d00ff",
|
|
8340
|
-
emissiveIntensity: 0.6
|
|
8341
|
-
},
|
|
8342
|
-
fire_orange: {
|
|
8343
|
-
name: "Fire Orange",
|
|
8344
|
-
baseColor: "#ff6600",
|
|
8345
|
-
emissive: "#ff3300",
|
|
8346
|
-
emissiveIntensity: 0.7
|
|
8347
|
-
}
|
|
8348
|
-
}
|
|
8349
|
-
};
|
|
8350
|
-
|
|
8351
|
-
// assets/templates/cc4-humanoid.json
|
|
8352
|
-
var cc4_humanoid_default = {
|
|
8353
|
-
id: "cc4-humanoid",
|
|
8354
|
-
sourceCharacterId: "cc4",
|
|
8355
|
-
sourceAsset: "assets/presets/cc4.json",
|
|
8356
|
-
sourceSkinName: "Armature",
|
|
8357
|
-
bones: [
|
|
8358
|
-
{
|
|
8359
|
-
name: "CC_Base_BoneRoot",
|
|
8360
|
-
parent: null,
|
|
8361
|
-
translation: [
|
|
8362
|
-
0,
|
|
8363
|
-
0,
|
|
8364
|
-
0
|
|
8365
|
-
]
|
|
8366
|
-
},
|
|
8367
|
-
{
|
|
8368
|
-
name: "CC_Base_Hip",
|
|
8369
|
-
parent: "CC_Base_BoneRoot",
|
|
8370
|
-
translation: [
|
|
8371
|
-
0,
|
|
8372
|
-
0,
|
|
8373
|
-
102.33650207519531
|
|
8374
|
-
]
|
|
8375
|
-
},
|
|
8376
|
-
{
|
|
8377
|
-
name: "CC_Base_Pelvis",
|
|
8378
|
-
parent: "CC_Base_Hip",
|
|
8379
|
-
translation: [
|
|
8380
|
-
-3790411029074318e-30,
|
|
8381
|
-
30517578125e-15,
|
|
8382
|
-
-7.908884072094224e-7
|
|
8383
|
-
]
|
|
8384
|
-
},
|
|
8385
|
-
{
|
|
8386
|
-
name: "CC_Base_L_Thigh",
|
|
8387
|
-
parent: "CC_Base_Pelvis",
|
|
8388
|
-
translation: [
|
|
8389
|
-
9.953155517578125,
|
|
8390
|
-
-1.789858102798462,
|
|
8391
|
-
-1.3750107288360596
|
|
8392
|
-
]
|
|
8393
|
-
},
|
|
8394
|
-
{
|
|
8395
|
-
name: "CC_Base_L_Calf",
|
|
8396
|
-
parent: "CC_Base_L_Thigh",
|
|
8397
|
-
translation: [
|
|
8398
|
-
0.0010912826983258128,
|
|
8399
|
-
47.572593688964844,
|
|
8400
|
-
-25631440803408623e-20
|
|
8401
|
-
]
|
|
8402
|
-
},
|
|
8403
|
-
{
|
|
8404
|
-
name: "CC_Base_L_Foot",
|
|
8405
|
-
parent: "CC_Base_L_Calf",
|
|
8406
|
-
translation: [
|
|
8407
|
-
0.012946736067533493,
|
|
8408
|
-
47.30466842651367,
|
|
8409
|
-
0.0028991601429879665
|
|
8410
|
-
]
|
|
8411
|
-
},
|
|
8412
|
-
{
|
|
8413
|
-
name: "CC_Base_L_ToeBaseShareBone",
|
|
8414
|
-
parent: "CC_Base_L_Foot",
|
|
8415
|
-
translation: [
|
|
8416
|
-
-15205750241875648e-20,
|
|
8417
|
-
15.384612083435059,
|
|
8418
|
-
8890032768249512e-20
|
|
8419
|
-
]
|
|
8420
|
-
},
|
|
8421
|
-
{
|
|
8422
|
-
name: "CC_Base_L_ToeBase",
|
|
8423
|
-
parent: "CC_Base_L_Foot",
|
|
8424
|
-
translation: [
|
|
8425
|
-
-15205750241875648e-20,
|
|
8426
|
-
15.384612083435059,
|
|
8427
|
-
8890032768249512e-20
|
|
8428
|
-
]
|
|
8429
|
-
},
|
|
8430
|
-
{
|
|
8431
|
-
name: "CC_Base_L_PinkyToe1",
|
|
8432
|
-
parent: "CC_Base_L_ToeBase",
|
|
8433
|
-
translation: [
|
|
8434
|
-
-2.8338863849639893,
|
|
8435
|
-
0.00474335253238678,
|
|
8436
|
-
-0.449185848236084
|
|
8437
|
-
]
|
|
8438
|
-
},
|
|
8439
|
-
{
|
|
8440
|
-
name: "CC_Base_L_RingToe1",
|
|
8441
|
-
parent: "CC_Base_L_ToeBase",
|
|
8442
|
-
translation: [
|
|
8443
|
-
-1.4594630002975464,
|
|
8444
|
-
1.165667176246643,
|
|
8445
|
-
-0.024081647396087646
|
|
8446
|
-
]
|
|
8447
|
-
},
|
|
8448
|
-
{
|
|
8449
|
-
name: "CC_Base_L_MidToe1",
|
|
8450
|
-
parent: "CC_Base_L_ToeBase",
|
|
8451
|
-
translation: [
|
|
8452
|
-
-5848705768585205e-21,
|
|
8453
|
-
2.3142271041870117,
|
|
8454
|
-
5245208740234375e-20
|
|
8455
|
-
]
|
|
8456
|
-
},
|
|
8457
|
-
{
|
|
8458
|
-
name: "CC_Base_L_IndexToe1",
|
|
8459
|
-
parent: "CC_Base_L_ToeBase",
|
|
8460
|
-
translation: [
|
|
8461
|
-
1.5948846340179443,
|
|
8462
|
-
2.64426851272583,
|
|
8463
|
-
0.3221862316131592
|
|
8464
|
-
]
|
|
8465
|
-
},
|
|
8466
|
-
{
|
|
8467
|
-
name: "CC_Base_L_BigToe1",
|
|
8468
|
-
parent: "CC_Base_L_ToeBase",
|
|
8469
|
-
translation: [
|
|
8470
|
-
3.8480422496795654,
|
|
8471
|
-
2.5877017974853516,
|
|
8472
|
-
0.018612831830978394
|
|
8473
|
-
]
|
|
8474
|
-
},
|
|
8475
|
-
{
|
|
8476
|
-
name: "CC_Base_L_CalfTwist01",
|
|
8477
|
-
parent: "CC_Base_L_Calf",
|
|
8478
|
-
translation: [
|
|
8479
|
-
-9258394129574299e-21,
|
|
8480
|
-
4678964614868164e-21,
|
|
8481
|
-
-3.073364496231079e-8
|
|
8482
|
-
]
|
|
8483
|
-
},
|
|
8484
|
-
{
|
|
8485
|
-
name: "CC_Base_L_CalfTwist02",
|
|
8486
|
-
parent: "CC_Base_L_CalfTwist01",
|
|
8487
|
-
translation: [
|
|
8488
|
-
0.008389605209231377,
|
|
8489
|
-
23.652305603027344,
|
|
8490
|
-
0.0010145818814635277
|
|
8491
|
-
]
|
|
8492
|
-
},
|
|
8493
|
-
{
|
|
8494
|
-
name: "CC_Base_L_KneeShareBone",
|
|
8495
|
-
parent: "CC_Base_L_Calf",
|
|
8496
|
-
translation: [
|
|
8497
|
-
-9258394129574299e-21,
|
|
8498
|
-
4678964614868164e-21,
|
|
8499
|
-
-3.073364496231079e-8
|
|
8500
|
-
]
|
|
8501
|
-
},
|
|
8502
|
-
{
|
|
8503
|
-
name: "CC_Base_L_ThighTwist01",
|
|
8504
|
-
parent: "CC_Base_L_Thigh",
|
|
8505
|
-
translation: [
|
|
8506
|
-
-5.249967216514051e-8,
|
|
8507
|
-
-446811318397522e-19,
|
|
8508
|
-
7050111889839172e-22
|
|
8509
|
-
]
|
|
8510
|
-
},
|
|
8511
|
-
{
|
|
8512
|
-
name: "CC_Base_L_ThighTwist02",
|
|
8513
|
-
parent: "CC_Base_L_ThighTwist01",
|
|
8514
|
-
translation: [
|
|
8515
|
-
5524034495465457e-19,
|
|
8516
|
-
23.786300659179688,
|
|
8517
|
-
3187847323715687e-20
|
|
8518
|
-
]
|
|
8519
|
-
},
|
|
8520
|
-
{
|
|
8521
|
-
name: "CC_Base_R_Thigh",
|
|
8522
|
-
parent: "CC_Base_Pelvis",
|
|
8523
|
-
translation: [
|
|
8524
|
-
-9.953006744384766,
|
|
8525
|
-
-1.7889251708984375,
|
|
8526
|
-
-1.3763487339019775
|
|
8527
|
-
]
|
|
8528
|
-
},
|
|
8529
|
-
{
|
|
8530
|
-
name: "CC_Base_R_Calf",
|
|
8531
|
-
parent: "CC_Base_R_Thigh",
|
|
8532
|
-
translation: [
|
|
8533
|
-
-0.001107644522562623,
|
|
8534
|
-
47.52029800415039,
|
|
8535
|
-
4845880903303623e-20
|
|
8536
|
-
]
|
|
8537
|
-
},
|
|
8538
|
-
{
|
|
8539
|
-
name: "CC_Base_R_KneeShareBone",
|
|
8540
|
-
parent: "CC_Base_R_Calf",
|
|
8541
|
-
translation: [
|
|
8542
|
-
-7073394954204559e-21,
|
|
8543
|
-
-2518296241760254e-21,
|
|
8544
|
-
19818544387817383e-22
|
|
8545
|
-
]
|
|
8546
|
-
},
|
|
8547
|
-
{
|
|
8548
|
-
name: "CC_Base_R_Foot",
|
|
8549
|
-
parent: "CC_Base_R_Calf",
|
|
8550
|
-
translation: [
|
|
8551
|
-
-0.011737369000911713,
|
|
8552
|
-
47.35129928588867,
|
|
8553
|
-
-0.0035943761467933655
|
|
8554
|
-
]
|
|
8555
|
-
},
|
|
8556
|
-
{
|
|
8557
|
-
name: "CC_Base_R_ToeBase",
|
|
8558
|
-
parent: "CC_Base_R_Foot",
|
|
8559
|
-
translation: [
|
|
8560
|
-
23105042055249214e-20,
|
|
8561
|
-
15.38337230682373,
|
|
8562
|
-
45359134674072266e-20
|
|
8563
|
-
]
|
|
8564
|
-
},
|
|
8565
|
-
{
|
|
8566
|
-
name: "CC_Base_R_BigToe1",
|
|
8567
|
-
parent: "CC_Base_R_ToeBase",
|
|
8568
|
-
translation: [
|
|
8569
|
-
-3.848090648651123,
|
|
8570
|
-
2.587796926498413,
|
|
8571
|
-
0.018401414155960083
|
|
8572
|
-
]
|
|
8573
|
-
},
|
|
8574
|
-
{
|
|
8575
|
-
name: "CC_Base_R_PinkyToe1",
|
|
8576
|
-
parent: "CC_Base_R_ToeBase",
|
|
8577
|
-
translation: [
|
|
8578
|
-
2.8339407444000244,
|
|
8579
|
-
0.005379915237426758,
|
|
8580
|
-
-0.4495028853416443
|
|
8581
|
-
]
|
|
8582
|
-
},
|
|
8583
|
-
{
|
|
8584
|
-
name: "CC_Base_R_RingToe1",
|
|
8585
|
-
parent: "CC_Base_R_ToeBase",
|
|
8586
|
-
translation: [
|
|
8587
|
-
1.4595259428024292,
|
|
8588
|
-
1.1659480333328247,
|
|
8589
|
-
-0.02425825595855713
|
|
8590
|
-
]
|
|
8591
|
-
},
|
|
8592
|
-
{
|
|
8593
|
-
name: "CC_Base_R_IndexToe1",
|
|
8594
|
-
parent: "CC_Base_R_ToeBase",
|
|
8595
|
-
translation: [
|
|
8596
|
-
-1.59493887424469,
|
|
8597
|
-
2.64436674118042,
|
|
8598
|
-
0.32200416922569275
|
|
8599
|
-
]
|
|
8600
|
-
},
|
|
8601
|
-
{
|
|
8602
|
-
name: "CC_Base_R_MidToe1",
|
|
8603
|
-
parent: "CC_Base_R_ToeBase",
|
|
8604
|
-
translation: [
|
|
8605
|
-
-912696123123169e-20,
|
|
8606
|
-
2.3142714500427246,
|
|
8607
|
-
1671910285949707e-20
|
|
8608
|
-
]
|
|
8609
|
-
},
|
|
8610
|
-
{
|
|
8611
|
-
name: "CC_Base_R_ToeBaseShareBone",
|
|
8612
|
-
parent: "CC_Base_R_Foot",
|
|
8613
|
-
translation: [
|
|
8614
|
-
23105042055249214e-20,
|
|
8615
|
-
15.38337230682373,
|
|
8616
|
-
45359134674072266e-20
|
|
8617
|
-
]
|
|
8618
|
-
},
|
|
8619
|
-
{
|
|
8620
|
-
name: "CC_Base_R_CalfTwist01",
|
|
8621
|
-
parent: "CC_Base_R_Calf",
|
|
8622
|
-
translation: [
|
|
8623
|
-
-7073394954204559e-21,
|
|
8624
|
-
-2518296241760254e-21,
|
|
8625
|
-
19818544387817383e-22
|
|
8626
|
-
]
|
|
8627
|
-
},
|
|
8628
|
-
{
|
|
8629
|
-
name: "CC_Base_R_CalfTwist02",
|
|
8630
|
-
parent: "CC_Base_R_CalfTwist01",
|
|
8631
|
-
translation: [
|
|
8632
|
-
-0.005310218781232834,
|
|
8633
|
-
23.675636291503906,
|
|
8634
|
-
-0.0015991628170013428
|
|
8635
|
-
]
|
|
8636
|
-
},
|
|
8637
|
-
{
|
|
8638
|
-
name: "CC_Base_R_ThighTwist01",
|
|
8639
|
-
parent: "CC_Base_R_Thigh",
|
|
8640
|
-
translation: [
|
|
8641
|
-
30152787076076493e-22,
|
|
8642
|
-
-12714415788650513e-21,
|
|
8643
|
-
-5.024485290050507e-7
|
|
8644
|
-
]
|
|
8645
|
-
},
|
|
8646
|
-
{
|
|
8647
|
-
name: "CC_Base_R_ThighTwist02",
|
|
8648
|
-
parent: "CC_Base_R_ThighTwist01",
|
|
8649
|
-
translation: [
|
|
8650
|
-
-532150617800653e-18,
|
|
8651
|
-
23.760181427001953,
|
|
8652
|
-
-5566661711782217e-19
|
|
8653
|
-
]
|
|
8654
|
-
},
|
|
8655
|
-
{
|
|
8656
|
-
name: "CC_Base_Waist",
|
|
8657
|
-
parent: "CC_Base_Hip",
|
|
8658
|
-
translation: [
|
|
8659
|
-
0,
|
|
8660
|
-
7.9917144775390625,
|
|
8661
|
-
1.035797119140625
|
|
8662
|
-
]
|
|
8663
|
-
},
|
|
8664
|
-
{
|
|
8665
|
-
name: "CC_Base_Spine01",
|
|
8666
|
-
parent: "CC_Base_Waist",
|
|
8667
|
-
translation: [
|
|
8668
|
-
12880583372901905e-29,
|
|
8669
|
-
4.44435453414917,
|
|
8670
|
-
36954879760742188e-22
|
|
8671
|
-
]
|
|
8672
|
-
},
|
|
8673
|
-
{
|
|
8674
|
-
name: "CC_Base_Spine02",
|
|
8675
|
-
parent: "CC_Base_Spine01",
|
|
8676
|
-
translation: [
|
|
8677
|
-
13552527156068805e-36,
|
|
8678
|
-
14.241397857666016,
|
|
8679
|
-
-852346420288086e-20
|
|
8680
|
-
]
|
|
8681
|
-
},
|
|
8682
|
-
{
|
|
8683
|
-
name: "CC_Base_NeckTwist01",
|
|
8684
|
-
parent: "CC_Base_Spine02",
|
|
8685
|
-
translation: [
|
|
8686
|
-
-1075023646990303e-21,
|
|
8687
|
-
29.157955169677734,
|
|
8688
|
-
44345855712890625e-21
|
|
8689
|
-
]
|
|
8690
|
-
},
|
|
8691
|
-
{
|
|
8692
|
-
name: "CC_Base_NeckTwist02",
|
|
8693
|
-
parent: "CC_Base_NeckTwist01",
|
|
8694
|
-
translation: [
|
|
8695
|
-
8672486728755757e-24,
|
|
8696
|
-
3.354764223098755,
|
|
8697
|
-
13446807861328125e-20
|
|
8698
|
-
]
|
|
8699
|
-
},
|
|
8700
|
-
{
|
|
8701
|
-
name: "CC_Base_Head",
|
|
8702
|
-
parent: "CC_Base_NeckTwist02",
|
|
8703
|
-
translation: [
|
|
8704
|
-
41776246507652104e-20,
|
|
8705
|
-
3.995985746383667,
|
|
8706
|
-
-1358989356958773e-20
|
|
8707
|
-
]
|
|
8708
|
-
},
|
|
8709
|
-
{
|
|
8710
|
-
name: "CC_Base_FacialBone",
|
|
8711
|
-
parent: "CC_Base_Head",
|
|
8712
|
-
translation: [
|
|
8713
|
-
5114753065527111e-26,
|
|
8714
|
-
15347271983046085e-21,
|
|
8715
|
-
-7390974587906385e-21
|
|
8716
|
-
]
|
|
8717
|
-
},
|
|
8718
|
-
{
|
|
8719
|
-
name: "CC_Base_JawRoot",
|
|
8720
|
-
parent: "CC_Base_FacialBone",
|
|
8721
|
-
translation: [
|
|
8722
|
-
1.856170654296875,
|
|
8723
|
-
2.3725814819335938,
|
|
8724
|
-
-0.026499934494495392
|
|
8725
|
-
]
|
|
8726
|
-
},
|
|
8727
|
-
{
|
|
8728
|
-
name: "CC_Base_Tongue01",
|
|
8729
|
-
parent: "CC_Base_JawRoot",
|
|
8730
|
-
translation: [
|
|
8731
|
-
3.4788222312927246,
|
|
8732
|
-
1.3013767004013062,
|
|
8733
|
-
0.001722173416055739
|
|
8734
|
-
]
|
|
8735
|
-
},
|
|
8736
|
-
{
|
|
8737
|
-
name: "CC_Base_Tongue02",
|
|
8738
|
-
parent: "CC_Base_Tongue01",
|
|
8739
|
-
translation: [
|
|
8740
|
-
1.211624026298523,
|
|
8741
|
-
7291115616681054e-20,
|
|
8742
|
-
23348256945610046e-22
|
|
8743
|
-
]
|
|
8744
|
-
},
|
|
8745
|
-
{
|
|
8746
|
-
name: "CC_Base_Tongue03",
|
|
8747
|
-
parent: "CC_Base_Tongue02",
|
|
8748
|
-
translation: [
|
|
8749
|
-
1.8075196743011475,
|
|
8750
|
-
4838673339691013e-19,
|
|
8751
|
-
1673889346420765e-20
|
|
8752
|
-
]
|
|
8753
|
-
},
|
|
8754
|
-
{
|
|
8755
|
-
name: "CC_Base_Teeth02",
|
|
8756
|
-
parent: "CC_Base_JawRoot",
|
|
8757
|
-
translation: [
|
|
8758
|
-
3.509425640106201,
|
|
8759
|
-
1.6364113092422485,
|
|
8760
|
-
0.025405975058674812
|
|
8761
|
-
]
|
|
8762
|
-
},
|
|
8763
|
-
{
|
|
8764
|
-
name: "CC_Base_R_Eye",
|
|
8765
|
-
parent: "CC_Base_FacialBone",
|
|
8766
|
-
translation: [
|
|
8767
|
-
7.916625499725342,
|
|
8768
|
-
8.004108428955078,
|
|
8769
|
-
-3.399050235748291
|
|
8770
|
-
]
|
|
8771
|
-
},
|
|
8772
|
-
{
|
|
8773
|
-
name: "CC_Base_L_Eye",
|
|
8774
|
-
parent: "CC_Base_FacialBone",
|
|
8775
|
-
translation: [
|
|
8776
|
-
7.864105701446533,
|
|
8777
|
-
7.835659027099609,
|
|
8778
|
-
3.473083019256592
|
|
8779
|
-
]
|
|
8780
|
-
},
|
|
8781
|
-
{
|
|
8782
|
-
name: "CC_Base_UpperJaw",
|
|
8783
|
-
parent: "CC_Base_FacialBone",
|
|
8784
|
-
translation: [
|
|
8785
|
-
3.261932373046875,
|
|
8786
|
-
6.942871570587158,
|
|
8787
|
-
-0.02468101494014263
|
|
8788
|
-
]
|
|
8789
|
-
},
|
|
8790
|
-
{
|
|
8791
|
-
name: "CC_Base_Teeth01",
|
|
8792
|
-
parent: "CC_Base_UpperJaw",
|
|
8793
|
-
translation: [
|
|
8794
|
-
0.09780752658843994,
|
|
8795
|
-
0.021660717204213142,
|
|
8796
|
-
0.023386476561427116
|
|
8797
|
-
]
|
|
8798
|
-
},
|
|
8799
|
-
{
|
|
8800
|
-
name: "CC_Base_L_Clavicle",
|
|
8801
|
-
parent: "CC_Base_Spine02",
|
|
8802
|
-
translation: [
|
|
8803
|
-
5.846743106842041,
|
|
8804
|
-
22.913326263427734,
|
|
8805
|
-
0.15851521492004395
|
|
8806
|
-
]
|
|
8807
|
-
},
|
|
8808
|
-
{
|
|
8809
|
-
name: "CC_Base_L_Upperarm",
|
|
8810
|
-
parent: "CC_Base_L_Clavicle",
|
|
8811
|
-
translation: [
|
|
8812
|
-
6332993507385254e-20,
|
|
8813
|
-
13.675213813781738,
|
|
8814
|
-
40340423583984375e-20
|
|
8815
|
-
]
|
|
8816
|
-
},
|
|
8817
|
-
{
|
|
8818
|
-
name: "CC_Base_L_Forearm",
|
|
8819
|
-
parent: "CC_Base_L_Upperarm",
|
|
8820
|
-
translation: [
|
|
8821
|
-
-0.0021000131964683533,
|
|
8822
|
-
29.648496627807617,
|
|
8823
|
-
5214959383010864e-19
|
|
8824
|
-
]
|
|
8825
|
-
},
|
|
8826
|
-
{
|
|
8827
|
-
name: "CC_Base_L_ForearmTwist01",
|
|
8828
|
-
parent: "CC_Base_L_Forearm",
|
|
8829
|
-
translation: [
|
|
8830
|
-
-2450495958328247e-20,
|
|
8831
|
-
-63749030232429504e-22,
|
|
8832
|
-
5811452865600586e-21
|
|
8833
|
-
]
|
|
8834
|
-
},
|
|
8835
|
-
{
|
|
8836
|
-
name: "CC_Base_L_ForearmTwist02",
|
|
8837
|
-
parent: "CC_Base_L_ForearmTwist01",
|
|
8838
|
-
translation: [
|
|
8839
|
-
-0.0017938688397407532,
|
|
8840
|
-
12.154339790344238,
|
|
8841
|
-
-0.0031246542930603027
|
|
8842
|
-
]
|
|
8843
|
-
},
|
|
8844
|
-
{
|
|
8845
|
-
name: "CC_Base_L_ElbowShareBone",
|
|
8846
|
-
parent: "CC_Base_L_Forearm",
|
|
8847
|
-
translation: [
|
|
8848
|
-
-2450495958328247e-20,
|
|
8849
|
-
-63749030232429504e-22,
|
|
8850
|
-
5811452865600586e-21
|
|
8851
|
-
]
|
|
8852
|
-
},
|
|
8853
|
-
{
|
|
8854
|
-
name: "CC_Base_L_Hand",
|
|
8855
|
-
parent: "CC_Base_L_Forearm",
|
|
8856
|
-
translation: [
|
|
8857
|
-
-0.0032659247517585754,
|
|
8858
|
-
24.308786392211914,
|
|
8859
|
-
-0.0040430426597595215
|
|
8860
|
-
]
|
|
8861
|
-
},
|
|
8862
|
-
{
|
|
8863
|
-
name: "CC_Base_L_Pinky1",
|
|
8864
|
-
parent: "CC_Base_L_Hand",
|
|
8865
|
-
translation: [
|
|
8866
|
-
0.8387796878814697,
|
|
8867
|
-
9.643739700317383,
|
|
8868
|
-
-1.8876361846923828
|
|
8869
|
-
]
|
|
8870
|
-
},
|
|
8871
|
-
{
|
|
8872
|
-
name: "CC_Base_L_Pinky2",
|
|
8873
|
-
parent: "CC_Base_L_Pinky1",
|
|
8874
|
-
translation: [
|
|
8875
|
-
396043062210083e-18,
|
|
8876
|
-
3.0504348278045654,
|
|
8877
|
-
-1811981201171875e-19
|
|
8878
|
-
]
|
|
8879
|
-
},
|
|
8880
|
-
{
|
|
8881
|
-
name: "CC_Base_L_Pinky3",
|
|
8882
|
-
parent: "CC_Base_L_Pinky2",
|
|
8883
|
-
translation: [
|
|
8884
|
-
38370490074157715e-21,
|
|
8885
|
-
1.9355652332305908,
|
|
8886
|
-
-3510713577270508e-20
|
|
8887
|
-
]
|
|
8888
|
-
},
|
|
8889
|
-
{
|
|
8890
|
-
name: "CC_Base_L_Ring1",
|
|
8891
|
-
parent: "CC_Base_L_Hand",
|
|
8892
|
-
translation: [
|
|
8893
|
-
0.0010117590427398682,
|
|
8894
|
-
9.706981658935547,
|
|
8895
|
-
0.0030269622802734375
|
|
8896
|
-
]
|
|
8897
|
-
},
|
|
8898
|
-
{
|
|
8899
|
-
name: "CC_Base_L_Ring2",
|
|
8900
|
-
parent: "CC_Base_L_Ring1",
|
|
8901
|
-
translation: [
|
|
8902
|
-
-1965165138244629e-19,
|
|
8903
|
-
4.398406982421875,
|
|
8904
|
-
-5393028259277344e-19
|
|
8905
|
-
]
|
|
8906
|
-
},
|
|
8907
|
-
{
|
|
8908
|
-
name: "CC_Base_L_Ring3",
|
|
8909
|
-
parent: "CC_Base_L_Ring2",
|
|
8910
|
-
translation: [
|
|
8911
|
-
-8174926042556763e-19,
|
|
8912
|
-
3.074361801147461,
|
|
8913
|
-
6477683782577515e-19
|
|
8914
|
-
]
|
|
8915
|
-
},
|
|
8916
|
-
{
|
|
8917
|
-
name: "CC_Base_L_Mid1",
|
|
8918
|
-
parent: "CC_Base_L_Hand",
|
|
8919
|
-
translation: [
|
|
8920
|
-
-0.6153436303138733,
|
|
8921
|
-
9.996679306030273,
|
|
8922
|
-
1.9597835540771484
|
|
8923
|
-
]
|
|
8924
|
-
},
|
|
8925
|
-
{
|
|
8926
|
-
name: "CC_Base_L_Mid2",
|
|
8927
|
-
parent: "CC_Base_L_Mid1",
|
|
8928
|
-
translation: [
|
|
8929
|
-
-2244412899017334e-19,
|
|
8930
|
-
4.767321586608887,
|
|
8931
|
-
-41157007217407227e-21
|
|
8932
|
-
]
|
|
8933
|
-
},
|
|
8934
|
-
{
|
|
8935
|
-
name: "CC_Base_L_Mid3",
|
|
8936
|
-
parent: "CC_Base_L_Mid2",
|
|
8937
|
-
translation: [
|
|
8938
|
-
-0.0010398924350738525,
|
|
8939
|
-
3.306338310241699,
|
|
8940
|
-
-8061528205871582e-19
|
|
8941
|
-
]
|
|
8942
|
-
},
|
|
8943
|
-
{
|
|
8944
|
-
name: "CC_Base_L_Index1",
|
|
8945
|
-
parent: "CC_Base_L_Hand",
|
|
8946
|
-
translation: [
|
|
8947
|
-
-0.4277152717113495,
|
|
8948
|
-
9.799840927124023,
|
|
8949
|
-
4.421895980834961
|
|
8950
|
-
]
|
|
8951
|
-
},
|
|
8952
|
-
{
|
|
8953
|
-
name: "CC_Base_L_Index2",
|
|
8954
|
-
parent: "CC_Base_L_Index1",
|
|
8955
|
-
translation: [
|
|
8956
|
-
-0.001440480351448059,
|
|
8957
|
-
4.649103164672852,
|
|
8958
|
-
0.001256398856639862
|
|
8959
|
-
]
|
|
8960
|
-
},
|
|
8961
|
-
{
|
|
8962
|
-
name: "CC_Base_L_Index3",
|
|
8963
|
-
parent: "CC_Base_L_Index2",
|
|
8964
|
-
translation: [
|
|
8965
|
-
-5395412445068359e-19,
|
|
8966
|
-
2.933397054672241,
|
|
8967
|
-
52034854888916016e-21
|
|
8968
|
-
]
|
|
8969
|
-
},
|
|
8970
|
-
{
|
|
8971
|
-
name: "CC_Base_L_Thumb1",
|
|
8972
|
-
parent: "CC_Base_L_Hand",
|
|
8973
|
-
translation: [
|
|
8974
|
-
0.4729442000389099,
|
|
8975
|
-
1.4073847532272339,
|
|
8976
|
-
2.9682064056396484
|
|
8977
|
-
]
|
|
8978
|
-
},
|
|
8979
|
-
{
|
|
8980
|
-
name: "CC_Base_L_Thumb2",
|
|
8981
|
-
parent: "CC_Base_L_Thumb1",
|
|
8982
|
-
translation: [
|
|
8983
|
-
-3701448440551758e-20,
|
|
8984
|
-
7.252772331237793,
|
|
8985
|
-
-34561753273010254e-20
|
|
8986
|
-
]
|
|
8987
|
-
},
|
|
8988
|
-
{
|
|
8989
|
-
name: "CC_Base_L_Thumb3",
|
|
8990
|
-
parent: "CC_Base_L_Thumb2",
|
|
8991
|
-
translation: [
|
|
8992
|
-
-9371936321258545e-19,
|
|
8993
|
-
3.2246363162994385,
|
|
8994
|
-
-3355741500854492e-19
|
|
8995
|
-
]
|
|
8996
|
-
},
|
|
8997
|
-
{
|
|
8998
|
-
name: "CC_Base_L_UpperarmTwist01",
|
|
8999
|
-
parent: "CC_Base_L_Upperarm",
|
|
9000
|
-
translation: [
|
|
9001
|
-
-24765729904174805e-21,
|
|
9002
|
-
-8791685104370117e-21,
|
|
9003
|
-
-4850327968597412e-21
|
|
9004
|
-
]
|
|
9005
|
-
},
|
|
9006
|
-
{
|
|
9007
|
-
name: "CC_Base_L_UpperarmTwist02",
|
|
9008
|
-
parent: "CC_Base_L_UpperarmTwist01",
|
|
9009
|
-
translation: [
|
|
9010
|
-
-5109608173370361e-20,
|
|
9011
|
-
14.824237823486328,
|
|
9012
|
-
-4093348979949951e-20
|
|
9013
|
-
]
|
|
9014
|
-
},
|
|
9015
|
-
{
|
|
9016
|
-
name: "CC_Base_L_RibsTwist",
|
|
9017
|
-
parent: "CC_Base_Spine02",
|
|
9018
|
-
translation: [
|
|
9019
|
-
12.37477970123291,
|
|
9020
|
-
4.240516662597656,
|
|
9021
|
-
11.340028762817383
|
|
9022
|
-
]
|
|
9023
|
-
},
|
|
9024
|
-
{
|
|
9025
|
-
name: "CC_Base_L_Breast",
|
|
9026
|
-
parent: "CC_Base_L_RibsTwist",
|
|
9027
|
-
translation: [
|
|
9028
|
-
15254845493473113e-21,
|
|
9029
|
-
1.999998688697815,
|
|
9030
|
-
8869566954672337e-20
|
|
9031
|
-
]
|
|
9032
|
-
},
|
|
9033
|
-
{
|
|
9034
|
-
name: "CC_Base_R_RibsTwist",
|
|
9035
|
-
parent: "CC_Base_Spine02",
|
|
9036
|
-
translation: [
|
|
9037
|
-
-12.366527557373047,
|
|
9038
|
-
4.255687236785889,
|
|
9039
|
-
11.342021942138672
|
|
9040
|
-
]
|
|
9041
|
-
},
|
|
9042
|
-
{
|
|
9043
|
-
name: "CC_Base_R_Breast",
|
|
9044
|
-
parent: "CC_Base_R_RibsTwist",
|
|
9045
|
-
translation: [
|
|
9046
|
-
-14992387150414288e-21,
|
|
9047
|
-
1.9999765157699585,
|
|
9048
|
-
698570511303842e-19
|
|
9049
|
-
]
|
|
9050
|
-
},
|
|
9051
|
-
{
|
|
9052
|
-
name: "CC_Base_R_Clavicle",
|
|
9053
|
-
parent: "CC_Base_Spine02",
|
|
9054
|
-
translation: [
|
|
9055
|
-
-5.847836017608643,
|
|
9056
|
-
22.913354873657227,
|
|
9057
|
-
0.158738374710083
|
|
9058
|
-
]
|
|
9059
|
-
},
|
|
9060
|
-
{
|
|
9061
|
-
name: "CC_Base_R_Upperarm",
|
|
9062
|
-
parent: "CC_Base_R_Clavicle",
|
|
9063
|
-
translation: [
|
|
9064
|
-
-38962066173553467e-20,
|
|
9065
|
-
13.675079345703125,
|
|
9066
|
-
13494491577148438e-20
|
|
9067
|
-
]
|
|
9068
|
-
},
|
|
9069
|
-
{
|
|
9070
|
-
name: "CC_Base_R_Forearm",
|
|
9071
|
-
parent: "CC_Base_R_Upperarm",
|
|
9072
|
-
translation: [
|
|
9073
|
-
0.0014372840523719788,
|
|
9074
|
-
29.647546768188477,
|
|
9075
|
-
-34911930561065674e-20
|
|
9076
|
-
]
|
|
9077
|
-
},
|
|
9078
|
-
{
|
|
9079
|
-
name: "CC_Base_R_ElbowShareBone",
|
|
9080
|
-
parent: "CC_Base_R_Forearm",
|
|
9081
|
-
translation: [
|
|
9082
|
-
4427880048751831e-20,
|
|
9083
|
-
-5062669515609741e-21,
|
|
9084
|
-
19073486328125e-19
|
|
9085
|
-
]
|
|
9086
|
-
},
|
|
9087
|
-
{
|
|
9088
|
-
name: "CC_Base_R_ForearmTwist01",
|
|
9089
|
-
parent: "CC_Base_R_Forearm",
|
|
9090
|
-
translation: [
|
|
9091
|
-
4427880048751831e-20,
|
|
9092
|
-
-5062669515609741e-21,
|
|
9093
|
-
19073486328125e-19
|
|
9094
|
-
]
|
|
9095
|
-
},
|
|
9096
|
-
{
|
|
9097
|
-
name: "CC_Base_R_ForearmTwist02",
|
|
9098
|
-
parent: "CC_Base_R_ForearmTwist01",
|
|
9099
|
-
translation: [
|
|
9100
|
-
0.0017296746373176575,
|
|
9101
|
-
12.154948234558105,
|
|
9102
|
-
-0.0021570324897766113
|
|
9103
|
-
]
|
|
9104
|
-
},
|
|
9105
|
-
{
|
|
9106
|
-
name: "CC_Base_R_Hand",
|
|
9107
|
-
parent: "CC_Base_R_Forearm",
|
|
9108
|
-
translation: [
|
|
9109
|
-
0.0013648197054862976,
|
|
9110
|
-
24.31002426147461,
|
|
9111
|
-
-3132820129394531e-19
|
|
9112
|
-
]
|
|
9113
|
-
},
|
|
9114
|
-
{
|
|
9115
|
-
name: "CC_Base_R_Ring1",
|
|
9116
|
-
parent: "CC_Base_R_Hand",
|
|
9117
|
-
translation: [
|
|
9118
|
-
73462724685668945e-22,
|
|
9119
|
-
9.707071304321289,
|
|
9120
|
-
-7748603820800781e-19
|
|
9121
|
-
]
|
|
9122
|
-
},
|
|
9123
|
-
{
|
|
9124
|
-
name: "CC_Base_R_Ring2",
|
|
9125
|
-
parent: "CC_Base_R_Ring1",
|
|
9126
|
-
translation: [
|
|
9127
|
-
15947222709655762e-20,
|
|
9128
|
-
4.398307800292969,
|
|
9129
|
-
-6395876407623291e-19
|
|
9130
|
-
]
|
|
9131
|
-
},
|
|
9132
|
-
{
|
|
9133
|
-
name: "CC_Base_R_Ring3",
|
|
9134
|
-
parent: "CC_Base_R_Ring2",
|
|
9135
|
-
translation: [
|
|
9136
|
-
-0.0010596513748168945,
|
|
9137
|
-
3.074486494064331,
|
|
9138
|
-
-25691837072372437e-20
|
|
9139
|
-
]
|
|
9140
|
-
},
|
|
9141
|
-
{
|
|
9142
|
-
name: "CC_Base_R_Mid1",
|
|
9143
|
-
parent: "CC_Base_R_Hand",
|
|
9144
|
-
translation: [
|
|
9145
|
-
0.6159845590591431,
|
|
9146
|
-
9.997448921203613,
|
|
9147
|
-
1.9559621810913086
|
|
9148
|
-
]
|
|
9149
|
-
},
|
|
9150
|
-
{
|
|
9151
|
-
name: "CC_Base_R_Mid2",
|
|
9152
|
-
parent: "CC_Base_R_Mid1",
|
|
9153
|
-
translation: [
|
|
9154
|
-
445440411567688e-18,
|
|
9155
|
-
4.767148494720459,
|
|
9156
|
-
-16441941261291504e-20
|
|
9157
|
-
]
|
|
9158
|
-
},
|
|
9159
|
-
{
|
|
9160
|
-
name: "CC_Base_R_Mid3",
|
|
9161
|
-
parent: "CC_Base_R_Mid2",
|
|
9162
|
-
translation: [
|
|
9163
|
-
12923777103424072e-20,
|
|
9164
|
-
3.306414842605591,
|
|
9165
|
-
5930662155151367e-20
|
|
9166
|
-
]
|
|
9167
|
-
},
|
|
9168
|
-
{
|
|
9169
|
-
name: "CC_Base_R_Thumb1",
|
|
9170
|
-
parent: "CC_Base_R_Hand",
|
|
9171
|
-
translation: [
|
|
9172
|
-
-0.4736732244491577,
|
|
9173
|
-
1.408708095550537,
|
|
9174
|
-
2.9675445556640625
|
|
9175
|
-
]
|
|
9176
|
-
},
|
|
9177
|
-
{
|
|
9178
|
-
name: "CC_Base_R_Thumb2",
|
|
9179
|
-
parent: "CC_Base_R_Thumb1",
|
|
9180
|
-
translation: [
|
|
9181
|
-
3608446568250656e-19,
|
|
9182
|
-
7.252943515777588,
|
|
9183
|
-
-981692224740982e-18
|
|
9184
|
-
]
|
|
9185
|
-
},
|
|
9186
|
-
{
|
|
9187
|
-
name: "CC_Base_R_Thumb3",
|
|
9188
|
-
parent: "CC_Base_R_Thumb2",
|
|
9189
|
-
translation: [
|
|
9190
|
-
-9268522262573242e-21,
|
|
9191
|
-
3.2248055934906006,
|
|
9192
|
-
4887580871582031e-20
|
|
9193
|
-
]
|
|
9194
|
-
},
|
|
9195
|
-
{
|
|
9196
|
-
name: "CC_Base_R_Index1",
|
|
9197
|
-
parent: "CC_Base_R_Hand",
|
|
9198
|
-
translation: [
|
|
9199
|
-
0.4276627004146576,
|
|
9200
|
-
9.801568984985352,
|
|
9201
|
-
4.418048858642578
|
|
9202
|
-
]
|
|
9203
|
-
},
|
|
9204
|
-
{
|
|
9205
|
-
name: "CC_Base_R_Index2",
|
|
9206
|
-
parent: "CC_Base_R_Index1",
|
|
9207
|
-
translation: [
|
|
9208
|
-
0.001061864197254181,
|
|
9209
|
-
4.648791790008545,
|
|
9210
|
-
6793588399887085e-19
|
|
9211
|
-
]
|
|
9212
|
-
},
|
|
9213
|
-
{
|
|
9214
|
-
name: "CC_Base_R_Index3",
|
|
9215
|
-
parent: "CC_Base_R_Index2",
|
|
9216
|
-
translation: [
|
|
9217
|
-
-6211921572685242e-19,
|
|
9218
|
-
2.9368622303009033,
|
|
9219
|
-
-16835331916809082e-20
|
|
9220
|
-
]
|
|
9221
|
-
},
|
|
9222
|
-
{
|
|
9223
|
-
name: "CC_Base_R_Pinky1",
|
|
9224
|
-
parent: "CC_Base_R_Hand",
|
|
9225
|
-
translation: [
|
|
9226
|
-
-0.837287962436676,
|
|
9227
|
-
9.643238067626953,
|
|
9228
|
-
-1.891557216644287
|
|
9229
|
-
]
|
|
9230
|
-
},
|
|
9231
|
-
{
|
|
9232
|
-
name: "CC_Base_R_Pinky2",
|
|
9233
|
-
parent: "CC_Base_R_Pinky1",
|
|
9234
|
-
translation: [
|
|
9235
|
-
-3053247928619385e-19,
|
|
9236
|
-
3.050346851348877,
|
|
9237
|
-
-22897124290466309e-20
|
|
9238
|
-
]
|
|
9239
|
-
},
|
|
9240
|
-
{
|
|
9241
|
-
name: "CC_Base_R_Pinky3",
|
|
9242
|
-
parent: "CC_Base_R_Pinky2",
|
|
9243
|
-
translation: [
|
|
9244
|
-
-6973743438720703e-21,
|
|
9245
|
-
1.9355270862579346,
|
|
9246
|
-
15944242477416992e-22
|
|
9247
|
-
]
|
|
9248
|
-
},
|
|
9249
|
-
{
|
|
9250
|
-
name: "CC_Base_R_UpperarmTwist01",
|
|
9251
|
-
parent: "CC_Base_R_Upperarm",
|
|
9252
|
-
translation: [
|
|
9253
|
-
4403293132781982e-21,
|
|
9254
|
-
33676624298095703e-22,
|
|
9255
|
-
-2473592758178711e-21
|
|
9256
|
-
]
|
|
9257
|
-
},
|
|
9258
|
-
{
|
|
9259
|
-
name: "CC_Base_R_UpperarmTwist02",
|
|
9260
|
-
parent: "CC_Base_R_UpperarmTwist01",
|
|
9261
|
-
translation: [
|
|
9262
|
-
-0.0015784502029418945,
|
|
9263
|
-
14.823780059814453,
|
|
9264
|
-
-3107339143753052e-19
|
|
9265
|
-
]
|
|
9266
|
-
}
|
|
9267
|
-
]
|
|
9268
|
-
};
|
|
9269
|
-
|
|
9270
|
-
// wasm/index.ts
|
|
9271
|
-
var EMBODY_CORE_ABI_VERSION = 1;
|
|
9272
|
-
var PACKED_MORPH_FRAME_DELTA_STRIDE = 4;
|
|
9273
|
-
var PACKED_BONE_FRAME_DELTA_STRIDE = 9;
|
|
9274
|
-
var HAIR_CONFIG_STRIDE = 11;
|
|
9275
|
-
var HAIR_STATE_STRIDE = 4;
|
|
9276
|
-
var HAIR_HEAD_STATE_STRIDE = 5;
|
|
9277
|
-
var HAIR_MORPH_OUTPUT_STRIDE = 6;
|
|
9278
|
-
var MESH_PROPORTIONS_STRIDE = 16;
|
|
9279
|
-
var TEMPLATE_SKELETON_FIT_SOLUTION_STRIDE = 10;
|
|
9280
|
-
var TEMPLATE_SKELETON_FIT_TRANSFORM_STRIDE = 4;
|
|
9281
|
-
var ANNOTATION_CAMERA_FRAMING_STRIDE = 7;
|
|
9282
|
-
var CAMERA_FLIGHT_SAMPLE_STRIDE = 7;
|
|
9283
|
-
var MARKER_VISIBILITY_FACTORS_STRIDE = 3;
|
|
9284
|
-
var MARKER_ENDPOINT_STRIDE = 3;
|
|
9285
|
-
var SCREEN_SPACE_GAZE_SOLUTION_STRIDE = 14;
|
|
9286
|
-
var HAIR_COLOR_PRESETS = cc4_default.hairColorPresets;
|
|
9287
|
-
var DEFAULT_HAIR_COLOR_APPEARANCE = HAIR_COLOR_PRESETS.natural_brown;
|
|
9288
|
-
var CC4_HUMANOID_SKELETON_TEMPLATE = cc4_humanoid_default;
|
|
9289
|
-
var HUMANOID_SKELETON_TEMPLATES = [CC4_HUMANOID_SKELETON_TEMPLATE];
|
|
9290
|
-
var pending = null;
|
|
9291
|
-
var loaded = null;
|
|
9292
|
-
async function initEmbodyCore3() {
|
|
9293
|
-
if (!pending) {
|
|
9294
|
-
pending = load().catch((error) => {
|
|
9295
|
-
pending = null;
|
|
9296
|
-
loaded = null;
|
|
9297
|
-
throw error;
|
|
9298
|
-
});
|
|
9299
|
-
}
|
|
9300
|
-
return pending;
|
|
9301
|
-
}
|
|
9302
|
-
var getEmbodyCore = initEmbodyCore3;
|
|
9303
|
-
function requireInitializedEmbodyCore2() {
|
|
9304
|
-
if (!loaded) throw new Error("Embody Wasm core is not initialized. Await initEmbodyCore() first.");
|
|
9305
|
-
return loaded;
|
|
9306
|
-
}
|
|
9307
|
-
function resetEmbodyCoreForTests() {
|
|
9308
|
-
pending = null;
|
|
9309
|
-
loaded = null;
|
|
9310
|
-
}
|
|
9311
|
-
async function load() {
|
|
9312
|
-
const resolveAsset = (path) => new URL(path, import.meta.url);
|
|
9313
|
-
const moduleUrl = resolveAsset("./wasm/embody_wasm.js").href;
|
|
9314
|
-
const binaryUrl = resolveAsset("./wasm/embody_wasm_bg.wasm");
|
|
9315
|
-
const core2 = await import(
|
|
9316
|
-
/* @vite-ignore */
|
|
9317
|
-
moduleUrl
|
|
9318
|
-
);
|
|
9319
|
-
if (typeof core2.default === "function") {
|
|
9320
|
-
let input = binaryUrl;
|
|
9321
|
-
if (globalThis.process?.versions?.node && binaryUrl.protocol === "file:") {
|
|
9322
|
-
const fsSpecifier = "node:fs/promises";
|
|
9323
|
-
const urlSpecifier = "node:url";
|
|
9324
|
-
const [{ readFile }, { fileURLToPath }] = await Promise.all([
|
|
9325
|
-
import(
|
|
9326
|
-
/* @vite-ignore */
|
|
9327
|
-
fsSpecifier
|
|
9328
|
-
),
|
|
9329
|
-
import(
|
|
9330
|
-
/* @vite-ignore */
|
|
9331
|
-
urlSpecifier
|
|
9332
|
-
)
|
|
9333
|
-
]);
|
|
9334
|
-
input = await readFile(fileURLToPath(binaryUrl));
|
|
9335
|
-
}
|
|
9336
|
-
await core2.default({ module_or_path: input });
|
|
9337
|
-
}
|
|
9338
|
-
if (core2.core_abi_version() !== EMBODY_CORE_ABI_VERSION) {
|
|
9339
|
-
throw new Error(`Unsupported Embody Wasm ABI version ${core2.core_abi_version()}.`);
|
|
9340
|
-
}
|
|
9341
|
-
loaded = core2;
|
|
9342
|
-
return core2;
|
|
9343
|
-
}
|
|
9344
|
-
|
|
9345
|
-
export { ANNOTATION_CAMERA_FRAMING_STRIDE, CAMERA_FLIGHT_SAMPLE_STRIDE, CC4_HUMANOID_SKELETON_TEMPLATE, CHARACTER_SCENE_TYPES, CHARACTER_SCENE_TYPE_IDS, DPthreeCameraController as CameraController, CameraDOMControls, CameraDOMControls as Controls, DEFAULT_CHARACTER_LIGHTING_PRESETS, DEFAULT_CHARACTER_LIGHTING_PRESET_ID, DEFAULT_CHARACTER_LIGHTING_PRESET_IDS, DEFAULT_CHARACTER_LIGHTING_SETTINGS, DEFAULT_CHARACTER_SCENE_TYPE_ID, DEFAULT_HAIR_COLOR_APPEARANCE, DEFAULT_MARKER_AUTO_HIDE_MS, DEFAULT_PREVIEW_AUTO_CLEAR_MS, DPthree, DPthree3DMarkers, DPthreeCameraController, DPthreeHTMLMarkers, DPthreeMarkers, EMBODY_CORE_ABI_VERSION, HAIR_COLOR_PRESETS, HAIR_CONFIG_STRIDE, HAIR_HEAD_STATE_STRIDE, HAIR_MORPH_OUTPUT_STRIDE, HAIR_STATE_STRIDE, HUMANOID_SKELETON_TEMPLATES, MARKER_ENDPOINT_STRIDE, MARKER_VISIBILITY_FACTORS_STRIDE, MESH_PROPORTIONS_STRIDE, DPthree3DMarkers as Markers3D, DPthreeHTMLMarkers as MarkersHTML, PACKED_BONE_FRAME_DELTA_STRIDE, PACKED_MORPH_FRAME_DELTA_STRIDE, RUNTIME_ANNOTATION_REGION_PREFIX, RustAnnotationCameraCore, SCREEN_SPACE_GAZE_SOLUTION_STRIDE, TEMPLATE_SKELETON_FIT_SOLUTION_STRIDE, TEMPLATE_SKELETON_FIT_TRANSFORM_STRIDE, THREE_BLENDING_MODES, ThreeFrameApplier, ThreeGazeFocus, ThreeModelInspector, applyCharacterModelTransform, bindModelReferencePose, boneResolutionProfile, buildRegionDisplayOptions, captureModelReferencePose, collectMorphMeshes, createAnimationClipFromClipIR, createDefaultCharacterLighting, createDefaultCharacterScene, createDefaultCharacterSceneAsync, createDefaultCharacterSceneRuntime, createMarkerLifecycleRevealOptions, createMarkerVisibilityLifecycle, createRuntimeAnnotationPreviewLifecycle, createRustAnnotationCameraCore, createShadowPlane, detectAnnotationLaterality, disposeCharacterModel, extendModelReferencePose, filterCameraViewRegions, getDefaultAnnotationLaterality, getEmbodyCore, getModelLocalOrbitAngle, getRuntimeAUMeshSideOffset, getRuntimeAUMorphAnchorPoint, getRuntimeAnnotationSide, getSemanticHorizontalSign, getSemanticHorizontalSignForSide, getWorldDirectionForCameraAngle, inferRuntimeAnnotationPreviewSide, initEmbodyCore3 as initEmbodyCore, isRuntimeAnnotationRegionName, loadCharacterModel, normalizeDefaultCharacterLightingSettings, parseCharacterModel, passesMarkerCameraAngleGate, pickContinuumAnnotationAuId, requireInitializedEmbodyCore2 as requireInitializedEmbodyCore, resetEmbodyCoreForTests, resolveAnnotationCharacterConfig, resolveFaceCenter, resolveMarkerAnchorRegion, resolveRegionCameraAngle, resolveRegionVisibilityCameraAngle, serializeAnimationClips, shouldProjectMarkerAnchorToSurface, shouldUseFaceCenterForMarkerAnchor, toWorldDirection };
|
|
9964
|
+
export { BLENDING_MODES, CHARACTER_SCENE_TYPES, CHARACTER_SCENE_TYPE_IDS, DPthreeCameraController as CameraController, CameraDOMControls, CameraDOMControls as Controls, DEFAULT_CHARACTER_LIGHTING_PRESETS, DEFAULT_CHARACTER_LIGHTING_PRESET_ID, DEFAULT_CHARACTER_LIGHTING_PRESET_IDS, DEFAULT_CHARACTER_LIGHTING_SETTINGS, DEFAULT_CHARACTER_SCENE_TYPE_ID, DEFAULT_MARKER_AUTO_HIDE_MS, DEFAULT_PREVIEW_AUTO_CLEAR_MS, DPthree, DPthree3DMarkers, DPthreeCameraController, DPthreeHTMLMarkers, DPthreeMarkers, Embody, DPthree3DMarkers as Markers3D, DPthreeHTMLMarkers as MarkersHTML, RUNTIME_ANNOTATION_REGION_PREFIX, RustAnnotationCameraCore, THREE_BLENDING_MODES, ThreeFrameApplier, ThreeModelInspector, ThreeNativePlaybackConnector, analyzeModel, applyAUBoneBindingUpdate, applyBilateralAxisBindingUpdate, applyBoneAxisBindingUpdate, applyCharacterModelTransform, bindModelReferencePose, boneResolutionProfile, buildBoneAuOptions, buildRegionDisplayOptions, captureModelReferencePose, classifyAuAsJointControl, collectMorphMeshes, computeHumanoidSkeletonTemplateRestBounds, createAnimationClipFromClipIR, createBilateralBoneAxisAu, createBoneAxisAu, createCharacterHost, createDefaultCharacterLighting, createDefaultCharacterScene, createDefaultCharacterSceneAsync, createDefaultCharacterSceneRuntime, createMarkerLifecycleRevealOptions, createMarkerVisibilityLifecycle, createRuntimeAnnotationPreviewLifecycle, createRustAnnotationCameraCore, createRustEmbodyHost, createRustEmbodyHostUnbound, createScenePlaybackFrame, createShadowPlane, createValidationSkeletonFromHumanoidTemplate, detectAnnotationLaterality, disposeCharacterModel, ensureBilateralBoneNodeKeys, ensureBoneNodeKey, extendCharacterConfigWithPreset, extendModelReferencePose, extractHumanoidSkeletonTemplateFromModel, extractModelData, extractProfileOverrides, filterCameraViewRegions, findNodeKeyForBone, formatAxisDirectionLabel, formatAxisLabel, fuzzyNameMatch, getAUBoneBindingState, getAxisFromChannel, getBilateralAxisBindingState, getBodyControls, getBoneAxisBindingState, getDefaultAnnotationLaterality, getHumanoidSkeletonTemplate, getHumanoidSkeletonTemplateBoneNames, getHumanoidSpecification, getMeshNamesForAUProfile, getModelLocalOrbitAngle, getPreset, getRuntimeAUMeshSideOffset, getRuntimeAUMorphAnchorPoint, getRuntimeAnnotationSide, getSemanticHorizontalSign, getSemanticHorizontalSignForSide, getWorldDirectionForCameraAngle, hasLeftRightMorphs, inferChiralBoneNamePair, inferEyeControlFamily, inferEyeControlScope, inferRuntimeAnnotationPreviewSide, isJointControlAuInfo, isMaxDegreesOnlyAxisBindingUpdate, isMixedAU, isRuntimeAnnotationRegionName, loadCharacterModel, mergeCharacterRegionsByName, normalizeDefaultCharacterLightingSettings, normalizeHairColorAppearance, parseCharacterModel, passesMarkerCameraAngleGate, pickContinuumAnnotationAuId, renderScenePlayback, resolveAnnotationCharacterConfig, resolveBoneAxisChannel, resolveBoneNameForNodeKey, resolveBoneNames, resolveContinuumDisplayLabel, resolveFaceCenter, resolveHumanoidCharacterization, resolveMarkerAnchorRegion, resolveRegionCameraAngle, resolveRegionVisibilityCameraAngle, resolveVisemeProfile, serializeAnimationClips, setAUMorphTargets, setHumanoidRoleBinding, shouldProjectMarkerAnchorToSurface, shouldUseFaceCenterForMarkerAnchor, stripConfiguredBoneAffixes, supportsRustEmbodyPreset, toWorldDirection, validateHumanoidCharacterization, validateMappings };
|
|
9346
9965
|
//# sourceMappingURL=index.js.map
|
|
9347
9966
|
//# sourceMappingURL=index.js.map
|