@lovelace_lol/embody 0.0.5 → 0.0.7

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/three.cjs CHANGED
@@ -3511,410 +3511,6 @@ function getBlendingName(value) {
3511
3511
  return "Normal";
3512
3512
  }
3513
3513
 
3514
- // src/core/TsRuntimeCore.ts
3515
- var identityQuat = { x: 0, y: 0, z: 0, w: 1 };
3516
- function isRotationBoneBinding2(binding) {
3517
- return binding?.channel === "rx" || binding?.channel === "ry" || binding?.channel === "rz";
3518
- }
3519
- var TsRuntimeCore = class {
3520
- constructor(options) {
3521
- __publicField(this, "profile");
3522
- __publicField(this, "model");
3523
- __publicField(this, "auValues", {});
3524
- __publicField(this, "auBalances", {});
3525
- __publicField(this, "visemeValues");
3526
- __publicField(this, "visemeJawScales");
3527
- __publicField(this, "mixWeights");
3528
- this.profile = options.profile;
3529
- this.model = options.model;
3530
- this.visemeValues = new Array(getProfileVisemeSlots(this.profile).length).fill(0);
3531
- this.visemeJawScales = new Array(this.visemeValues.length).fill(1);
3532
- this.mixWeights = { ...this.profile.auMixDefaults };
3533
- }
3534
- setProfile(profile) {
3535
- this.profile = profile;
3536
- this.visemeValues = new Array(getProfileVisemeSlots(this.profile).length).fill(0);
3537
- this.visemeJawScales = new Array(this.visemeValues.length).fill(1);
3538
- this.mixWeights = { ...this.profile.auMixDefaults };
3539
- }
3540
- setModelDescriptor(model) {
3541
- this.model = model;
3542
- }
3543
- setAU(id, value, balance) {
3544
- if (value < 0 && this.profile.continuumPairs) {
3545
- const pairInfo = this.profile.continuumPairs[id];
3546
- if (pairInfo) {
3547
- const negAU = pairInfo.isNegative ? id : pairInfo.pairId;
3548
- const posAU = pairInfo.isNegative ? pairInfo.pairId : id;
3549
- this.setContinuum(negAU, posAU, pairInfo.isNegative ? -value : value, balance);
3550
- return;
3551
- }
3552
- }
3553
- this.auValues[id] = clamp01(value);
3554
- if (balance !== void 0) {
3555
- this.auBalances[id] = clampBalance2(balance);
3556
- }
3557
- }
3558
- getAU(id) {
3559
- return this.auValues[id] ?? 0;
3560
- }
3561
- setContinuum(negAU, posAU, continuumValue, balance) {
3562
- const value = Math.max(-1, Math.min(1, continuumValue));
3563
- if (value < 0) {
3564
- this.setAU(posAU, 0, balance);
3565
- this.setAU(negAU, Math.abs(value), balance);
3566
- return;
3567
- }
3568
- if (value > 0) {
3569
- this.setAU(negAU, 0, balance);
3570
- this.setAU(posAU, value, balance);
3571
- return;
3572
- }
3573
- this.setAU(negAU, 0, balance);
3574
- this.setAU(posAU, 0, balance);
3575
- }
3576
- setViseme(visemeIndex, value, jawScale = 1) {
3577
- if (visemeIndex < 0 || visemeIndex >= this.visemeValues.length) return;
3578
- this.visemeValues[visemeIndex] = clamp01(value);
3579
- this.visemeJawScales[visemeIndex] = jawScale;
3580
- }
3581
- setVisemeById(slotId, value, jawScale = 1) {
3582
- const index = getVisemeSlotIndex(this.profile, slotId);
3583
- if (index < 0) return;
3584
- this.setViseme(index, value, jawScale);
3585
- }
3586
- setAUMixWeight(id, weight) {
3587
- this.mixWeights[id] = clamp01(weight);
3588
- }
3589
- evaluateFrameDelta(deltaSeconds) {
3590
- const morphWrites = /* @__PURE__ */ new Map();
3591
- this.collectAUWrites(morphWrites);
3592
- this.collectVisemeWrites(morphWrites);
3593
- return {
3594
- deltaSeconds,
3595
- morphTargets: Array.from(morphWrites.values()),
3596
- bones: this.collectBoneWrites()
3597
- };
3598
- }
3599
- collectAUWrites(morphWrites) {
3600
- for (const [auIdText, entry] of Object.entries(this.profile.auToMorphs || {})) {
3601
- const auId = Number(auIdText);
3602
- if (Number.isNaN(auId) || !entry) continue;
3603
- const mixWeight = this.isMixedAU(auId) ? this.getAUMixWeight(auId) : 1;
3604
- const base = clamp01(this.auValues[auId] ?? 0) * mixWeight;
3605
- const { left, right } = computeSideValues(base, this.auBalances[auId]);
3606
- const meshNames = getMeshNamesForAUProfile(this.profile, auId);
3607
- for (const morph of entry.left || []) {
3608
- this.addMorphWrites(morphWrites, morph, meshNames, left);
3609
- }
3610
- for (const morph of entry.right || []) {
3611
- this.addMorphWrites(morphWrites, morph, meshNames, right);
3612
- }
3613
- for (const morph of entry.center || []) {
3614
- this.addMorphWrites(morphWrites, morph, meshNames, base);
3615
- }
3616
- }
3617
- }
3618
- collectVisemeWrites(morphWrites) {
3619
- const meshNames = getMeshNamesForVisemeProfile(this.profile);
3620
- const localMax = /* @__PURE__ */ new Map();
3621
- for (let index = 0; index < this.visemeValues.length; index += 1) {
3622
- const value = clamp01(this.visemeValues[index] ?? 0);
3623
- for (const bindingTarget of getVisemeBindingTargets(this.profile, index)) {
3624
- const weighted = clamp01(value * bindingTarget.weight);
3625
- for (const resolved of this.resolveMorphTargets(bindingTarget.morph, meshNames)) {
3626
- const key = morphWriteKey(resolved.mesh.id, resolved.morphTarget.id);
3627
- const existing = localMax.get(key);
3628
- if (!existing || weighted > existing.value) {
3629
- localMax.set(key, {
3630
- meshId: resolved.mesh.id,
3631
- morphTargetId: resolved.morphTarget.id,
3632
- value: weighted,
3633
- mode: "absolute"
3634
- });
3635
- }
3636
- }
3637
- }
3638
- }
3639
- for (const [key, write] of localMax) {
3640
- const existing = morphWrites.get(key);
3641
- if (!existing || write.value > existing.value) {
3642
- morphWrites.set(key, write);
3643
- }
3644
- }
3645
- }
3646
- collectBoneWrites() {
3647
- const writes = [];
3648
- const rotations = this.computeRotationState();
3649
- for (const composite of this.profile.compositeRotations || []) {
3650
- const bone = this.findBoneDescriptor(composite.node);
3651
- if (!bone) continue;
3652
- const transform = this.evaluateCompositeTransform(bone, composite, rotations[composite.node]);
3653
- if (transform) {
3654
- writes.push({
3655
- boneId: bone.id,
3656
- transform,
3657
- mode: "absolute",
3658
- space: "local"
3659
- });
3660
- }
3661
- }
3662
- for (const [nodeKey, translation] of Object.entries(this.computeTranslations())) {
3663
- const bone = this.findBoneDescriptor(nodeKey);
3664
- if (!bone) continue;
3665
- const position = addVec3(bone.restTransform?.position, translation);
3666
- upsertBoneWrite(writes, bone.id, { position });
3667
- }
3668
- const jawAmount = this.getActiveVisemeJawAmount();
3669
- const jawBinding = this.findAutoVisemeJawBinding();
3670
- const jawBone = jawBinding ? this.findBoneDescriptor(jawBinding.node) : void 0;
3671
- if (jawBone && jawBinding?.maxDegrees && jawBinding.channel) {
3672
- const current = writes.find((write) => write.boneId === jawBone.id);
3673
- if (jawAmount > 1e-6 || !current?.transform.rotation) {
3674
- const rest = jawBone.restTransform?.rotation ?? identityQuat;
3675
- const rotation = jawAmount > 1e-6 ? multiplyQuat(
3676
- rest,
3677
- quatFromChannel(jawBinding.channel, deg2rad(jawBinding.maxDegrees) * jawAmount * jawBinding.scale)
3678
- ) : rest;
3679
- upsertBoneWrite(writes, jawBone.id, { rotation });
3680
- }
3681
- }
3682
- return writes;
3683
- }
3684
- computeRotationState() {
3685
- const rotations = {};
3686
- for (const composite of this.profile.compositeRotations || []) {
3687
- rotations[composite.node] = {
3688
- pitch: this.getCompositeAxisValueForNode(composite.node, composite.pitch),
3689
- yaw: this.getCompositeAxisValueForNode(composite.node, composite.yaw),
3690
- roll: this.getCompositeAxisValueForNode(composite.node, composite.roll)
3691
- };
3692
- }
3693
- return rotations;
3694
- }
3695
- evaluateCompositeTransform(bone, composite, state) {
3696
- if (!state) return null;
3697
- let rotation = bone.restTransform?.rotation ?? identityQuat;
3698
- const applyAxis = (axisConfig, direction) => {
3699
- if (!axisConfig || Math.abs(direction) <= 1e-6) return;
3700
- const binding = getCompositeAxisBinding(
3701
- composite.node,
3702
- axisConfig,
3703
- direction,
3704
- (auId) => this.getEffectiveBoneAUValue(auId, composite.node),
3705
- this.profile.auToBones
3706
- );
3707
- if (!binding?.maxDegrees || !binding.channel) return;
3708
- rotation = multiplyQuat(
3709
- rotation,
3710
- quatFromChannel(binding.channel, deg2rad(binding.maxDegrees) * Math.abs(direction) * binding.scale)
3711
- );
3712
- };
3713
- applyAxis(composite.yaw, state.yaw);
3714
- applyAxis(composite.pitch, state.pitch);
3715
- applyAxis(composite.roll, state.roll);
3716
- return { rotation };
3717
- }
3718
- computeTranslations() {
3719
- const translations = {};
3720
- for (const [auIdText, bindings] of Object.entries(this.profile.auToBones || {})) {
3721
- const auId = Number(auIdText);
3722
- if (Number.isNaN(auId)) continue;
3723
- const value = clamp01(this.auValues[auId] ?? 0);
3724
- for (const binding of bindings || []) {
3725
- if (binding.channel !== "tx" && binding.channel !== "ty" && binding.channel !== "tz") continue;
3726
- if (binding.maxUnits === void 0) continue;
3727
- const current = translations[binding.node] ?? { x: 0, y: 0, z: 0 };
3728
- translations[binding.node] = current;
3729
- if (value <= 1e-6) continue;
3730
- const offset = clampSigned(value * binding.scale) * binding.maxUnits;
3731
- translations[binding.node] = {
3732
- x: binding.channel === "tx" ? offset : current.x,
3733
- y: binding.channel === "ty" ? offset : current.y,
3734
- z: binding.channel === "tz" ? offset : current.z
3735
- };
3736
- }
3737
- }
3738
- return translations;
3739
- }
3740
- addMorphWrites(morphWrites, morph, meshNames, value) {
3741
- for (const resolved of this.resolveMorphTargets(morph, meshNames)) {
3742
- const key = morphWriteKey(resolved.mesh.id, resolved.morphTarget.id);
3743
- const existing = morphWrites.get(key);
3744
- if (existing && existing.value >= value) continue;
3745
- morphWrites.set(key, {
3746
- meshId: resolved.mesh.id,
3747
- morphTargetId: resolved.morphTarget.id,
3748
- value,
3749
- mode: "absolute"
3750
- });
3751
- }
3752
- }
3753
- resolveMorphTargets(morph, meshNames) {
3754
- const result = [];
3755
- for (const meshName of meshNames) {
3756
- const mesh = this.model.meshes.find((candidate) => candidate.name === meshName);
3757
- if (!mesh) continue;
3758
- const morphTargets = mesh.morphTargetIds.map((id) => this.model.morphTargets.find((candidate) => candidate.id === id)).filter((target2) => !!target2);
3759
- const target = typeof morph === "number" ? morphTargets.find((candidate) => candidate.hostIndex === morph) : resolveMorphTargetByName(morphTargets, morph, this.profile);
3760
- if (target) {
3761
- result.push({ mesh, morphTarget: target });
3762
- }
3763
- }
3764
- return result;
3765
- }
3766
- findBoneDescriptor(nodeKey) {
3767
- const configuredName = this.profile.boneNodes[nodeKey] || nodeKey;
3768
- const prefix = this.profile.bonePrefix ?? "";
3769
- const suffix = this.profile.boneSuffix ?? "";
3770
- const prefixedName = prefix && !configuredName.startsWith(prefix) ? `${prefix}${configuredName}` : configuredName;
3771
- const fullName = suffix && !prefixedName.endsWith(suffix) ? `${prefixedName}${suffix}` : prefixedName;
3772
- const candidates = /* @__PURE__ */ new Set([nodeKey, configuredName, fullName]);
3773
- return this.model.bones.find((bone) => candidates.has(bone.name));
3774
- }
3775
- findAutoVisemeJawBinding() {
3776
- const candidates = [
3777
- this.profile.auToBones[103]?.find(isRotationBoneBinding2),
3778
- this.profile.auToBones[26]?.find(isRotationBoneBinding2)
3779
- ].filter((binding) => !!binding);
3780
- return candidates.find((binding) => !!this.findBoneDescriptor(binding.node)) ?? candidates[0] ?? null;
3781
- }
3782
- getActiveVisemeJawAmount() {
3783
- const jawAmounts = getVisemeJawAmounts(this.profile) ?? [];
3784
- let jawAmount = 0;
3785
- for (let index = 0; index < this.visemeValues.length; index += 1) {
3786
- const value = clamp01(this.visemeValues[index] ?? 0);
3787
- if (value <= 1e-6) continue;
3788
- const jawScale = this.visemeJawScales[index] ?? 1;
3789
- if (Math.abs(jawScale) <= 1e-6) continue;
3790
- jawAmount = Math.max(jawAmount, (jawAmounts[index] ?? 0) * value * jawScale);
3791
- }
3792
- return jawAmount;
3793
- }
3794
- getCompositeAxisValueForNode(nodeKey, axisConfig) {
3795
- return getCompositeAxisValue(axisConfig, (auId) => this.getEffectiveBoneAUValue(auId, nodeKey));
3796
- }
3797
- getEffectiveBoneAUValue(auId, nodeKey) {
3798
- const rawValue = clamp01(this.auValues[auId] ?? 0);
3799
- if (rawValue <= 1e-6) return 0;
3800
- const binding = this.profile.auToBones[auId]?.find((candidate) => candidate.node === nodeKey) ?? null;
3801
- if (!binding?.side) return rawValue;
3802
- return rawValue * getSideScale2(this.auBalances[auId] ?? 0, binding.side);
3803
- }
3804
- getAUMixWeight(auId) {
3805
- return this.mixWeights[auId] ?? this.profile.auMixDefaults?.[auId] ?? 1;
3806
- }
3807
- isMixedAU(auId) {
3808
- const morphs = this.profile.auToMorphs[auId];
3809
- const hasMorphs = !!(morphs?.left?.length || morphs?.right?.length || morphs?.center?.length);
3810
- return !!(hasMorphs && this.profile.auToBones[auId]?.length);
3811
- }
3812
- };
3813
- function resolveMorphTargetByName(targets, key, profile) {
3814
- const prefix = profile.morphPrefix || "";
3815
- const suffix = profile.morphSuffix || "";
3816
- const fullName = prefix + key + suffix;
3817
- const exact = targets.find((target) => target.name === fullName);
3818
- if (exact) return exact;
3819
- const suffixRegex = profile.suffixPattern ? new RegExp(profile.suffixPattern) : null;
3820
- if (!suffixRegex) return void 0;
3821
- return targets.find((target) => {
3822
- if (!target.name.startsWith(fullName)) return false;
3823
- const candidateSuffix = target.name.slice(fullName.length);
3824
- return candidateSuffix === "" || suffixRegex.test(candidateSuffix);
3825
- });
3826
- }
3827
- function computeSideValues(base, balance) {
3828
- const b = clampBalance2(balance ?? 0);
3829
- if (b === 0) return { left: base, right: base };
3830
- if (b < 0) return { left: base, right: base * (1 + b) };
3831
- return { left: base * (1 - b), right: base };
3832
- }
3833
- function getSideScale2(balance, side) {
3834
- if (side !== "left" && side !== "right") return 1;
3835
- const b = clampBalance2(balance);
3836
- if (side === "left") return b > 0 ? 1 - b : 1;
3837
- return b < 0 ? 1 + b : 1;
3838
- }
3839
- function addVec3(base, offset) {
3840
- return {
3841
- x: (base?.x ?? 0) + offset.x,
3842
- y: (base?.y ?? 0) + offset.y,
3843
- z: (base?.z ?? 0) + offset.z
3844
- };
3845
- }
3846
- function upsertBoneWrite(writes, boneId2, transform) {
3847
- const existingIndex = writes.findIndex((write) => write.boneId === boneId2);
3848
- if (existingIndex >= 0) {
3849
- const existing = writes[existingIndex];
3850
- writes[existingIndex] = {
3851
- ...existing,
3852
- transform: {
3853
- ...existing.transform,
3854
- ...transform
3855
- }
3856
- };
3857
- return;
3858
- }
3859
- writes.push({
3860
- boneId: boneId2,
3861
- transform,
3862
- mode: "absolute",
3863
- space: "local"
3864
- });
3865
- }
3866
- function quatFromChannel(channel, radians) {
3867
- if (channel === "rx") return quatFromAxis({ x: 1, y: 0, z: 0 }, radians);
3868
- if (channel === "ry") return quatFromAxis({ x: 0, y: 1, z: 0 }, radians);
3869
- return quatFromAxis({ x: 0, y: 0, z: 1 }, radians);
3870
- }
3871
- function quatFromAxis(axis, radians) {
3872
- const half = radians / 2;
3873
- const s = Math.sin(half);
3874
- return normalizeQuat({
3875
- x: axis.x * s,
3876
- y: axis.y * s,
3877
- z: axis.z * s,
3878
- w: Math.cos(half)
3879
- });
3880
- }
3881
- function multiplyQuat(a, b) {
3882
- return normalizeQuat({
3883
- x: a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
3884
- y: a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
3885
- z: a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,
3886
- w: a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z
3887
- });
3888
- }
3889
- function normalizeQuat(q) {
3890
- const len = Math.hypot(q.x, q.y, q.z, q.w);
3891
- if (len <= 1e-12) return identityQuat;
3892
- return {
3893
- x: q.x / len,
3894
- y: q.y / len,
3895
- z: q.z / len,
3896
- w: q.w / len
3897
- };
3898
- }
3899
- function deg2rad(degrees) {
3900
- return degrees * Math.PI / 180;
3901
- }
3902
- function clamp01(value) {
3903
- if (!Number.isFinite(value)) return 0;
3904
- return value < 0 ? 0 : value > 1 ? 1 : value;
3905
- }
3906
- function clampSigned(value) {
3907
- if (!Number.isFinite(value)) return 0;
3908
- return value < -1 ? -1 : value > 1 ? 1 : value;
3909
- }
3910
- function clampBalance2(value) {
3911
- if (!Number.isFinite(value)) return 0;
3912
- return Math.max(-1, Math.min(1, value));
3913
- }
3914
- function morphWriteKey(meshId2, morphTargetId2) {
3915
- return `${meshId2}:${morphTargetId2}`;
3916
- }
3917
-
3918
3514
  // src/core/contracts/abi.ts
3919
3515
  var PACKED_MORPH_FRAME_DELTA_STRIDE = 4;
3920
3516
  var PACKED_BONE_FRAME_DELTA_STRIDE = 9;
@@ -3926,11 +3522,13 @@ var WasmRuntimeCore = class {
3926
3522
  constructor(options) {
3927
3523
  __publicField(this, "wasm");
3928
3524
  __publicField(this, "core");
3525
+ __publicField(this, "allowEmptyBindings");
3929
3526
  __publicField(this, "profile");
3930
3527
  __publicField(this, "model");
3931
3528
  this.wasm = options.wasm;
3932
3529
  this.profile = options.profile;
3933
3530
  this.model = options.model;
3531
+ this.allowEmptyBindings = options.allowEmptyBindings ?? false;
3934
3532
  const RuntimeCtor = options.wasm.RuntimeCore;
3935
3533
  if (!RuntimeCtor) {
3936
3534
  throw new Error("Embody Wasm module does not export RuntimeCore");
@@ -3949,6 +3547,24 @@ var WasmRuntimeCore = class {
3949
3547
  setAU(id, value, balance = 0) {
3950
3548
  this.core.set_au(id >>> 0, value, balance);
3951
3549
  }
3550
+ setContinuum(negativeAU, positiveAU, value, balance = 0) {
3551
+ this.core.set_continuum(negativeAU >>> 0, positiveAU >>> 0, value, balance);
3552
+ }
3553
+ transitionAU(id, to, durationMs, balance = Number.NaN) {
3554
+ this.core.transition_au(id >>> 0, to, durationMs, balance);
3555
+ }
3556
+ transitionViseme(visemeIndex, to, durationMs, jawScale = 1) {
3557
+ this.core.transition_viseme(visemeIndex >>> 0, to, durationMs, jawScale);
3558
+ }
3559
+ update(deltaSeconds) {
3560
+ return this.core.update(deltaSeconds);
3561
+ }
3562
+ activeTransitionCount() {
3563
+ return this.core.active_transition_count();
3564
+ }
3565
+ clearTransitions() {
3566
+ this.core.clear_transitions();
3567
+ }
3952
3568
  getAU(id) {
3953
3569
  return this.core.get_au(id >>> 0);
3954
3570
  }
@@ -3984,7 +3600,13 @@ var WasmRuntimeCore = class {
3984
3600
  };
3985
3601
  }
3986
3602
  reloadBindings() {
3987
- this.core.configure_with_profile(JSON.stringify(this.profile), JSON.stringify(this.model));
3603
+ const profileJson = JSON.stringify(this.profile);
3604
+ const modelJson = JSON.stringify(this.model);
3605
+ if (this.allowEmptyBindings) {
3606
+ this.core.configure(profileJson, modelJson);
3607
+ } else {
3608
+ this.core.configure_with_profile(profileJson, modelJson);
3609
+ }
3988
3610
  }
3989
3611
  };
3990
3612
  function unpackBoneFrameDelta(values) {
@@ -5333,7 +4955,7 @@ var CC4_PRESET = {
5333
4955
  };
5334
4956
 
5335
4957
  // src/engines/three/hair/HairPhysicsController.ts
5336
- var clamp012 = (value) => value < 0 ? 0 : value > 1 ? 1 : value;
4958
+ var clamp01 = (value) => value < 0 ? 0 : value > 1 ? 1 : value;
5337
4959
  var HairPhysicsController = class {
5338
4960
  constructor(host) {
5339
4961
  __publicField(this, "host");
@@ -5831,7 +5453,7 @@ var HairPhysicsController = class {
5831
5453
  }
5832
5454
  }
5833
5455
  setMorphOnMeshes(meshNames, morphKey, value) {
5834
- const val = clamp012(value);
5456
+ const val = clamp01(value);
5835
5457
  for (const name of meshNames) {
5836
5458
  const mesh = this.registeredHairObjects.get(name) || this.host.getMeshByName(name);
5837
5459
  if (!mesh) continue;
@@ -6075,9 +5697,9 @@ var HairPhysicsController = class {
6075
5697
  const deltaVertical = vertical - this.lastHeadVertical;
6076
5698
  this.lastHeadHorizontal = horizontal;
6077
5699
  this.lastHeadVertical = vertical;
6078
- const leftWeight = clamp012(deltaHorizontal > 0 ? deltaHorizontal : 0);
6079
- const rightWeight = clamp012(deltaHorizontal < 0 ? -deltaHorizontal : 0);
6080
- const frontWeight = clamp012(deltaVertical > 0 ? deltaVertical : 0);
5700
+ const leftWeight = clamp01(deltaHorizontal > 0 ? deltaHorizontal : 0);
5701
+ const rightWeight = clamp01(deltaHorizontal < 0 ? -deltaHorizontal : 0);
5702
+ const frontWeight = clamp01(deltaVertical > 0 ? deltaVertical : 0);
6081
5703
  const minTrigger = 0.01;
6082
5704
  if (leftWeight <= minTrigger && rightWeight <= minTrigger && frontWeight <= minTrigger) return;
6083
5705
  if (this.impulseClipDirty) {
@@ -7043,7 +6665,7 @@ async function getPresetWithProfile(presetType, profile) {
7043
6665
  }
7044
6666
 
7045
6667
  // src/engines/three/Embody.ts
7046
- var deg2rad2 = (d) => d * Math.PI / 180;
6668
+ var deg2rad = (d) => d * Math.PI / 180;
7047
6669
  var X_AXIS2 = new three.Vector3(1, 0, 0);
7048
6670
  var Y_AXIS2 = new three.Vector3(0, 1, 0);
7049
6671
  var Z_AXIS2 = new three.Vector3(0, 0, 1);
@@ -7066,9 +6688,18 @@ function buildAUToCompositeMap(composites) {
7066
6688
  });
7067
6689
  return map;
7068
6690
  }
7069
- function clamp013(x) {
6691
+ function clamp012(x) {
7070
6692
  return x < 0 ? 0 : x > 1 ? 1 : x;
7071
6693
  }
6694
+ var RESOLVED_TRANSITION_HANDLE = {
6695
+ promise: Promise.resolve(),
6696
+ pause: () => {
6697
+ },
6698
+ resume: () => {
6699
+ },
6700
+ cancel: () => {
6701
+ }
6702
+ };
7072
6703
  var _Embody = class _Embody {
7073
6704
  constructor(config = {}, animation) {
7074
6705
  // Optional hook for animation schedulers.
@@ -7112,7 +6743,6 @@ var _Embody = class _Embody {
7112
6743
  __publicField(this, "modelInspector", new ThreeModelInspector());
7113
6744
  __publicField(this, "frameApplier", new ThreeFrameApplier());
7114
6745
  __publicField(this, "modelDescriptor", null);
7115
- __publicField(this, "tsRuntimeCore", null);
7116
6746
  __publicField(this, "wasmRuntimeCore", null);
7117
6747
  __publicField(this, "framePathReady", false);
7118
6748
  // Internal animation loop
@@ -7225,48 +6855,21 @@ var _Embody = class _Embody {
7225
6855
  bindHostNeutralRuntime(inspection) {
7226
6856
  this.modelDescriptor = inspection.descriptor;
7227
6857
  this.frameApplier.setBindings(buildFrameApplierBindings(inspection));
7228
- this.tsRuntimeCore = new TsRuntimeCore({
6858
+ const wasm$1 = wasm.requireInitializedEmbodyCore();
6859
+ this.attachWasmCore(wasm$1);
6860
+ this.wasmRuntimeCore = new WasmRuntimeCore({
7229
6861
  profile: this.config,
7230
- model: inspection.descriptor
6862
+ model: inspection.descriptor,
6863
+ wasm: wasm$1,
6864
+ allowEmptyBindings: true
7231
6865
  });
7232
6866
  this.syncRuntimeCoreState();
7233
6867
  this.framePathReady = true;
7234
- void wasm.initEmbodyCore().then((wasm) => {
7235
- if (!this.modelDescriptor) return;
7236
- this.attachWasmCore(wasm);
7237
- this.wasmRuntimeCore = new WasmRuntimeCore({
7238
- profile: this.config,
7239
- model: this.modelDescriptor,
7240
- wasm
7241
- });
7242
- this.syncRuntimeCoreState();
7243
- }).catch(() => {
7244
- this.wasmRuntimeCore = null;
7245
- });
7246
6868
  }
7247
6869
  attachWasmCore(core) {
7248
6870
  this.hairPhysics.setCore(core);
7249
6871
  }
7250
6872
  syncRuntimeCoreState() {
7251
- if (this.tsRuntimeCore) {
7252
- this.tsRuntimeCore.setProfile(this.config);
7253
- if (this.modelDescriptor) {
7254
- this.tsRuntimeCore.setModelDescriptor(this.modelDescriptor);
7255
- }
7256
- for (const [auIdText, value] of Object.entries(this.auValues)) {
7257
- const auId = Number(auIdText);
7258
- if (Number.isNaN(auId)) continue;
7259
- this.tsRuntimeCore.setAU(auId, value, this.auBalances[auId]);
7260
- }
7261
- for (const [auIdText, weight] of Object.entries(this.mixWeights)) {
7262
- const auId = Number(auIdText);
7263
- if (Number.isNaN(auId)) continue;
7264
- this.tsRuntimeCore.setAUMixWeight(auId, weight);
7265
- }
7266
- for (let index = 0; index < this.visemeValues.length; index += 1) {
7267
- this.tsRuntimeCore.setViseme(index, this.visemeValues[index] ?? 0, this.visemeJawScales[index] ?? 1);
7268
- }
7269
- }
7270
6873
  if (this.wasmRuntimeCore) {
7271
6874
  this.wasmRuntimeCore.setProfile(this.config);
7272
6875
  if (this.modelDescriptor) {
@@ -7284,7 +6887,7 @@ var _Embody = class _Embody {
7284
6887
  this.wasmRuntimeCore.setAUMixWeight(auId, weight);
7285
6888
  }
7286
6889
  for (let index = 0; index < this.visemeValues.length; index += 1) {
7287
- this.wasmRuntimeCore.setViseme(index, this.visemeValues[index] ?? 0);
6890
+ this.wasmRuntimeCore.setViseme(index, this.visemeValues[index] ?? 0, this.visemeJawScales[index] ?? 1);
7288
6891
  }
7289
6892
  }
7290
6893
  }
@@ -7302,25 +6905,13 @@ var _Embody = class _Embody {
7302
6905
  });
7303
6906
  this.modelDescriptor = inspection.descriptor;
7304
6907
  this.frameApplier.setBindings(buildFrameApplierBindings(inspection));
7305
- this.tsRuntimeCore?.setModelDescriptor(inspection.descriptor);
7306
6908
  this.wasmRuntimeCore?.setModelDescriptor(inspection.descriptor);
7307
6909
  }
7308
- applyLiveMorphFrameDelta() {
7309
- if (!this.framePathReady || !this.model) return false;
7310
- if (this.wasmRuntimeCore) {
7311
- this.frameApplier.applyPackedMorphFrameDelta(
7312
- this.wasmRuntimeCore.evaluatePackedMorphFrameDelta()
7313
- );
7314
- return true;
7315
- }
7316
- if (this.tsRuntimeCore) {
7317
- const frame = this.tsRuntimeCore.evaluateFrameDelta();
7318
- this.frameApplier.applyFrameDelta(this.model, {
7319
- morphTargets: frame.morphTargets
7320
- });
7321
- return true;
7322
- }
7323
- return false;
6910
+ applyLiveFrameDelta() {
6911
+ if (!this.framePathReady || !this.model || !this.wasmRuntimeCore) return false;
6912
+ this.frameApplier.applyFrameDelta(this.model, this.wasmRuntimeCore.evaluateFrameDelta());
6913
+ this.pendingCompositeNodes.clear();
6914
+ return true;
7324
6915
  }
7325
6916
  rebuildMorphTargetsCache() {
7326
6917
  this.morphKeyCache.clear();
@@ -7422,6 +7013,11 @@ var _Embody = class _Embody {
7422
7013
  const dtSeconds = Math.max(0, deltaSeconds || 0);
7423
7014
  if (dtSeconds <= 0 || this.isPaused) return;
7424
7015
  this.animation.tick(dtSeconds);
7016
+ const wasmTransitionCount = this.wasmRuntimeCore?.activeTransitionCount() ?? 0;
7017
+ const remainingWasmTransitions = this.wasmRuntimeCore?.update(dtSeconds) ?? 0;
7018
+ if (wasmTransitionCount > 0 || remainingWasmTransitions > 0) {
7019
+ this.applyLiveFrameDelta();
7020
+ }
7425
7021
  this.flushPendingComposites();
7426
7022
  this.animationController.update(dtSeconds);
7427
7023
  this.hairPhysics.update(dtSeconds);
@@ -7456,7 +7052,6 @@ var _Embody = class _Embody {
7456
7052
  this.model = null;
7457
7053
  this.bones = {};
7458
7054
  this.modelDescriptor = null;
7459
- this.tsRuntimeCore = null;
7460
7055
  this.wasmRuntimeCore = null;
7461
7056
  this.framePathReady = false;
7462
7057
  }
@@ -7493,15 +7088,14 @@ var _Embody = class _Embody {
7493
7088
  if (balance !== void 0) {
7494
7089
  this.auBalances[id] = balance;
7495
7090
  }
7496
- this.tsRuntimeCore?.setAU(id, v, balance);
7497
7091
  this.wasmRuntimeCore?.setAU(id, v, balance ?? this.auBalances[id] ?? 0);
7498
- const appliedViaFrame = this.applyLiveMorphFrameDelta();
7092
+ const appliedViaFrame = this.applyLiveFrameDelta();
7499
7093
  if (!appliedViaFrame) {
7500
7094
  const resolvedMorphTargets = this.resolvedAUMorphTargets.get(id);
7501
7095
  const { left: leftKeys, right: rightKeys, center: centerKeys } = this.getAUMorphsBySide(id);
7502
7096
  if (resolvedMorphTargets) {
7503
7097
  const mixWeight = this.isMixedAU(id) ? this.getAUMixWeight(id) : 1;
7504
- const base = clamp013(v) * mixWeight;
7098
+ const base = clamp012(v) * mixWeight;
7505
7099
  const { left: leftVal, right: rightVal } = this.computeSideValues(base, balance);
7506
7100
  if (resolvedMorphTargets.left.length || resolvedMorphTargets.right.length) {
7507
7101
  this.applyMorphTargets(resolvedMorphTargets.left, leftVal);
@@ -7510,7 +7104,7 @@ var _Embody = class _Embody {
7510
7104
  this.applyMorphTargets(resolvedMorphTargets.center, base);
7511
7105
  } else if (leftKeys.length || rightKeys.length || centerKeys.length) {
7512
7106
  const mixWeight = this.isMixedAU(id) ? this.getAUMixWeight(id) : 1;
7513
- const base = clamp013(v) * mixWeight;
7107
+ const base = clamp012(v) * mixWeight;
7514
7108
  const meshNames = this.getMeshNamesForAU(id);
7515
7109
  const { left: leftVal, right: rightVal } = this.computeSideValues(base, balance);
7516
7110
  if (leftKeys.length || rightKeys.length) {
@@ -7529,6 +7123,7 @@ var _Embody = class _Embody {
7529
7123
  }
7530
7124
  }
7531
7125
  }
7126
+ if (appliedViaFrame) return;
7532
7127
  const compositeInfo = this.auToCompositeMap.get(id);
7533
7128
  if (compositeInfo) {
7534
7129
  for (const nodeKey of compositeInfo.nodes) {
@@ -7563,7 +7158,7 @@ var _Embody = class _Embody {
7563
7158
  return this.transitionContinuum(negAU, posAU, continuumValue, durationMs, balance);
7564
7159
  }
7565
7160
  }
7566
- const target = clamp013(to);
7161
+ const target = clamp012(to);
7567
7162
  if (balance !== void 0) {
7568
7163
  this.auBalances[numId] = balance;
7569
7164
  }
@@ -7574,6 +7169,19 @@ var _Embody = class _Embody {
7574
7169
  const base = target * mixWeight;
7575
7170
  const { left: leftVal, right: rightVal } = this.computeSideValues(base, storedBalance);
7576
7171
  this.auValues[numId] = target;
7172
+ if (this.wasmRuntimeCore) {
7173
+ this.wasmRuntimeCore.transitionAU(
7174
+ numId,
7175
+ target,
7176
+ durationMs,
7177
+ balance ?? this.auBalances[numId] ?? Number.NaN
7178
+ );
7179
+ this.update(0);
7180
+ if (durationMs <= 0) {
7181
+ this.applyLiveFrameDelta();
7182
+ }
7183
+ return RESOLVED_TRANSITION_HANDLE;
7184
+ }
7577
7185
  const handles = [];
7578
7186
  const meshNames = this.getMeshNamesForAU(numId);
7579
7187
  if (leftKeys.length || rightKeys.length) {
@@ -7636,6 +7244,17 @@ var _Embody = class _Embody {
7636
7244
  */
7637
7245
  setContinuum(negAU, posAU, continuumValue, balance) {
7638
7246
  const value = Math.max(-1, Math.min(1, continuumValue));
7247
+ this.auValues[negAU] = value < 0 ? Math.abs(value) : 0;
7248
+ this.auValues[posAU] = value > 0 ? value : 0;
7249
+ if (balance !== void 0) {
7250
+ this.auBalances[negAU] = balance;
7251
+ this.auBalances[posAU] = balance;
7252
+ }
7253
+ if (this.wasmRuntimeCore) {
7254
+ this.wasmRuntimeCore.setContinuum(negAU, posAU, value, balance ?? 0);
7255
+ this.applyLiveFrameDelta();
7256
+ return;
7257
+ }
7639
7258
  if (value < 0) {
7640
7259
  this.setAU(posAU, 0, balance);
7641
7260
  this.setAU(negAU, Math.abs(value), balance);
@@ -7661,10 +7280,32 @@ var _Embody = class _Embody {
7661
7280
  */
7662
7281
  transitionContinuum(negAU, posAU, continuumValue, durationMs = 200, balance) {
7663
7282
  const target = Math.max(-1, Math.min(1, continuumValue));
7664
- const driverKey = `continuum_${negAU}_${posAU}`;
7665
7283
  const currentNeg = this.auValues[negAU] ?? 0;
7666
7284
  const currentPos = this.auValues[posAU] ?? 0;
7667
7285
  const currentContinuum = currentPos - currentNeg;
7286
+ this.auValues[negAU] = target < 0 ? Math.abs(target) : 0;
7287
+ this.auValues[posAU] = target > 0 ? target : 0;
7288
+ if (balance !== void 0) {
7289
+ this.auBalances[negAU] = balance;
7290
+ this.auBalances[posAU] = balance;
7291
+ }
7292
+ if (this.wasmRuntimeCore) {
7293
+ if (target < 0) {
7294
+ this.wasmRuntimeCore.transitionAU(posAU, 0, durationMs, balance ?? this.auBalances[posAU] ?? Number.NaN);
7295
+ this.wasmRuntimeCore.transitionAU(negAU, Math.abs(target), durationMs, balance ?? this.auBalances[negAU] ?? Number.NaN);
7296
+ } else if (target > 0) {
7297
+ this.wasmRuntimeCore.transitionAU(negAU, 0, durationMs, balance ?? this.auBalances[negAU] ?? Number.NaN);
7298
+ this.wasmRuntimeCore.transitionAU(posAU, target, durationMs, balance ?? this.auBalances[posAU] ?? Number.NaN);
7299
+ } else {
7300
+ this.wasmRuntimeCore.transitionAU(negAU, 0, durationMs, balance ?? this.auBalances[negAU] ?? Number.NaN);
7301
+ this.wasmRuntimeCore.transitionAU(posAU, 0, durationMs, balance ?? this.auBalances[posAU] ?? Number.NaN);
7302
+ }
7303
+ if (durationMs <= 0) {
7304
+ this.applyLiveFrameDelta();
7305
+ }
7306
+ return RESOLVED_TRANSITION_HANDLE;
7307
+ }
7308
+ const driverKey = `continuum_${negAU}_${posAU}`;
7668
7309
  return this.animation.addTransition(driverKey, currentContinuum, target, durationMs, (value) => this.setContinuum(negAU, posAU, value, balance));
7669
7310
  }
7670
7311
  // ============================================================================
@@ -7746,7 +7387,7 @@ var _Embody = class _Embody {
7746
7387
  this.hairPhysics.refreshMeshSelection();
7747
7388
  }
7748
7389
  setMorph(key, v, meshNamesOrTargets) {
7749
- const val = clamp013(v);
7390
+ const val = clamp012(v);
7750
7391
  if (Array.isArray(meshNamesOrTargets) && meshNamesOrTargets.length > 0 && typeof meshNamesOrTargets[0] === "object" && "infl" in meshNamesOrTargets[0]) {
7751
7392
  const targets2 = meshNamesOrTargets;
7752
7393
  this.applyMorphTargets(targets2, val);
@@ -7758,7 +7399,7 @@ var _Embody = class _Embody {
7758
7399
  this.applyMorphTargets(targets, val);
7759
7400
  }
7760
7401
  setMorphInfluence(index, v, meshNames) {
7761
- const val = clamp013(v);
7402
+ const val = clamp012(v);
7762
7403
  const targets = this.resolveMorphTargetsByIndex(index, meshNames);
7763
7404
  if (targets.length === 0) return;
7764
7405
  this.applyMorphTargets(targets, val);
@@ -7833,21 +7474,21 @@ var _Embody = class _Embody {
7833
7474
  }
7834
7475
  transitionMorph(key, to, durationMs = 120, meshNames) {
7835
7476
  const transitionKey = meshNames?.length ? `morph_${this.getMorphKeyCacheKey(key, meshNames)}` : `morph_${this.getMorphKeyCacheKey(key)}`;
7836
- const target = clamp013(to);
7477
+ const target = clamp012(to);
7837
7478
  const targets = this.resolveMorphTargets(key, meshNames);
7838
7479
  const from = targets.length > 0 ? targets[0].infl[targets[0].idx] ?? 0 : this.getMorphValue(key);
7839
7480
  return this.animation.addTransition(transitionKey, from, target, durationMs, (value) => {
7840
- const val = clamp013(value);
7481
+ const val = clamp012(value);
7841
7482
  this.applyMorphTargets(targets, val);
7842
7483
  });
7843
7484
  }
7844
7485
  transitionMorphInfluence(index, to, durationMs = 120, meshNames) {
7845
7486
  const transitionKey = meshNames?.length ? `morph_${this.getMorphIndexCacheKey(index, meshNames)}` : `morph_${this.getMorphIndexCacheKey(index)}`;
7846
- const target = clamp013(to);
7487
+ const target = clamp012(to);
7847
7488
  const targets = this.resolveMorphTargetsByIndex(index, meshNames);
7848
7489
  const from = targets.length > 0 ? targets[0].infl[targets[0].idx] ?? 0 : this.getMorphValueByIndex(index);
7849
7490
  return this.animation.addTransition(transitionKey, from, target, durationMs, (value) => {
7850
- const val = clamp013(value);
7491
+ const val = clamp012(value);
7851
7492
  this.applyMorphTargets(targets, val);
7852
7493
  });
7853
7494
  }
@@ -7856,7 +7497,7 @@ var _Embody = class _Embody {
7856
7497
  // ============================================================================
7857
7498
  setViseme(visemeIndex, value, jawScale = 1) {
7858
7499
  if (visemeIndex < 0 || visemeIndex >= this.visemeValues.length) return;
7859
- const val = clamp013(value);
7500
+ const val = clamp012(value);
7860
7501
  this.visemeValues[visemeIndex] = val;
7861
7502
  this.visemeJawScales[visemeIndex] = jawScale;
7862
7503
  this.applyVisemeRuntimeState();
@@ -7868,16 +7509,24 @@ var _Embody = class _Embody {
7868
7509
  }, cancel: () => {
7869
7510
  } };
7870
7511
  }
7871
- const target = clamp013(to);
7512
+ const target = clamp012(to);
7872
7513
  const from = this.visemeValues[visemeIndex] ?? 0;
7873
7514
  this.visemeJawScales[visemeIndex] = jawScale;
7515
+ if (this.wasmRuntimeCore) {
7516
+ this.visemeValues[visemeIndex] = target;
7517
+ this.wasmRuntimeCore.transitionViseme(visemeIndex, target, durationMs, jawScale);
7518
+ if (durationMs <= 0) {
7519
+ this.applyLiveFrameDelta();
7520
+ }
7521
+ return RESOLVED_TRANSITION_HANDLE;
7522
+ }
7874
7523
  return this.animation.addTransition(
7875
7524
  `viseme_value_${visemeIndex}`,
7876
7525
  from,
7877
7526
  target,
7878
7527
  durationMs,
7879
7528
  (value) => {
7880
- this.visemeValues[visemeIndex] = clamp013(value);
7529
+ this.visemeValues[visemeIndex] = clamp012(value);
7881
7530
  this.visemeJawScales[visemeIndex] = jawScale;
7882
7531
  this.applyVisemeRuntimeState();
7883
7532
  }
@@ -7902,8 +7551,7 @@ var _Embody = class _Embody {
7902
7551
  // MIX WEIGHT CONTROL
7903
7552
  // ============================================================================
7904
7553
  setAUMixWeight(id, weight) {
7905
- this.mixWeights[id] = clamp013(weight);
7906
- this.tsRuntimeCore?.setAUMixWeight(id, weight);
7554
+ this.mixWeights[id] = clamp012(weight);
7907
7555
  this.wasmRuntimeCore?.setAUMixWeight(id, weight);
7908
7556
  const v = this.auValues[id] ?? 0;
7909
7557
  if (v > 0) this.setAU(id, v);
@@ -7941,9 +7589,10 @@ var _Embody = class _Embody {
7941
7589
  }
7942
7590
  clearTransitions() {
7943
7591
  this.animation.clearTransitions();
7592
+ this.wasmRuntimeCore?.clearTransitions();
7944
7593
  }
7945
7594
  getActiveTransitionCount() {
7946
- return this.animation.getActiveTransitionCount();
7595
+ return this.animation.getActiveTransitionCount() + (this.wasmRuntimeCore?.activeTransitionCount() ?? 0);
7947
7596
  }
7948
7597
  resetToNeutral() {
7949
7598
  this.auValues = {};
@@ -7953,6 +7602,7 @@ var _Embody = class _Embody {
7953
7602
  this.translations = {};
7954
7603
  this.initBoneRotations();
7955
7604
  this.clearTransitions();
7605
+ this.wasmRuntimeCore?.clear();
7956
7606
  const morphTargetsToReset = [];
7957
7607
  for (const m of this.meshes) {
7958
7608
  const infl = m.morphTargetInfluences;
@@ -8131,7 +7781,18 @@ var _Embody = class _Embody {
8131
7781
  this.bones = this.resolveBones(this.model);
8132
7782
  this.missingBoneWarnings.clear();
8133
7783
  this.rebuildMorphTargetsCache();
8134
- this.tsRuntimeCore?.setProfile(this.config);
7784
+ Object.values(this.bones).forEach((entry) => {
7785
+ if (!entry) return;
7786
+ this.frameApplier.applyObjectTransform(entry.obj, {
7787
+ position: { x: entry.basePos.x, y: entry.basePos.y, z: entry.basePos.z },
7788
+ rotation: {
7789
+ x: entry.baseQuat.x,
7790
+ y: entry.baseQuat.y,
7791
+ z: entry.baseQuat.z,
7792
+ w: entry.baseQuat.w
7793
+ }
7794
+ });
7795
+ });
8135
7796
  this.wasmRuntimeCore?.setProfile(this.config);
8136
7797
  this.refreshHostNeutralModelDescriptor();
8137
7798
  }
@@ -8248,20 +7909,20 @@ var _Embody = class _Embody {
8248
7909
  }
8249
7910
  applyVisemeRuntimeState() {
8250
7911
  for (let index = 0; index < this.visemeValues.length; index += 1) {
8251
- this.tsRuntimeCore?.setViseme(index, this.visemeValues[index] ?? 0, this.visemeJawScales[index] ?? 1);
8252
- this.wasmRuntimeCore?.setViseme(index, this.visemeValues[index] ?? 0);
7912
+ this.wasmRuntimeCore?.setViseme(index, this.visemeValues[index] ?? 0, this.visemeJawScales[index] ?? 1);
8253
7913
  }
8254
- if (!this.applyLiveMorphFrameDelta()) {
7914
+ const appliedViaFrame = this.applyLiveFrameDelta();
7915
+ if (!appliedViaFrame) {
8255
7916
  for (const targets of this.resolvedVisemeTargets) {
8256
7917
  this.frameApplier.resetMorphTargets(targets || []);
8257
7918
  }
8258
7919
  for (let index = 0; index < this.visemeValues.length; index += 1) {
8259
- const value = clamp013(this.visemeValues[index] ?? 0);
7920
+ const value = clamp012(this.visemeValues[index] ?? 0);
8260
7921
  if (value <= 1e-6) continue;
8261
7922
  const targets = this.resolvedVisemeTargets[index] || [];
8262
7923
  for (const target of targets) {
8263
7924
  if (target.idx >= target.infl.length) continue;
8264
- const weighted = clamp013(value * target.weight);
7925
+ const weighted = clamp012(value * target.weight);
8265
7926
  this.frameApplier.applyMorphTargets(
8266
7927
  [target],
8267
7928
  Math.max(target.infl[target.idx] ?? 0, weighted)
@@ -8269,7 +7930,9 @@ var _Embody = class _Embody {
8269
7930
  }
8270
7931
  }
8271
7932
  }
8272
- this.updateBoneRotation(this.getJawBoneNodeKey(), "pitch", this.getActiveVisemeJawAmount());
7933
+ if (!appliedViaFrame) {
7934
+ this.updateBoneRotation(this.getJawBoneNodeKey(), "pitch", this.getActiveVisemeJawAmount());
7935
+ }
8273
7936
  }
8274
7937
  getJawBoneNodeKey() {
8275
7938
  const candidates = [
@@ -8291,7 +7954,7 @@ var _Embody = class _Embody {
8291
7954
  getActiveVisemeJawAmount() {
8292
7955
  let jawAmount = 0;
8293
7956
  for (let index = 0; index < this.visemeValues.length; index += 1) {
8294
- const value = clamp013(this.visemeValues[index] ?? 0);
7957
+ const value = clamp012(this.visemeValues[index] ?? 0);
8295
7958
  if (value <= 1e-6) continue;
8296
7959
  const jawScale = this.visemeJawScales[index] ?? 1;
8297
7960
  if (Math.abs(jawScale) <= 1e-6) continue;
@@ -8574,7 +8237,7 @@ var _Embody = class _Embody {
8574
8237
  return !!(hasMorphs && this.config.auToBones[id]?.length);
8575
8238
  }
8576
8239
  getEffectiveBoneAUValue(auId, nodeKey) {
8577
- const rawValue = clamp013(this.auValues[auId] ?? 0);
8240
+ const rawValue = clamp012(this.auValues[auId] ?? 0);
8578
8241
  if (rawValue <= 1e-6) return 0;
8579
8242
  const binding = this.config.auToBones[auId]?.find((candidate) => candidate.node === nodeKey) ?? null;
8580
8243
  if (!binding?.side) return rawValue;
@@ -8674,7 +8337,7 @@ var _Embody = class _Embody {
8674
8337
  if (config.yaw && rotState.yaw !== 0) {
8675
8338
  const binding = this.getCompositeAxisBindingForNode(nodeKey, config.yaw, rotState.yaw);
8676
8339
  if (binding?.maxDegrees && binding.channel) {
8677
- const radians = deg2rad2(binding.maxDegrees) * Math.abs(rotState.yaw) * binding.scale;
8340
+ const radians = deg2rad(binding.maxDegrees) * Math.abs(rotState.yaw) * binding.scale;
8678
8341
  const axis = getAxis(binding.channel);
8679
8342
  const deltaQ = new three.Quaternion().setFromAxisAngle(axis, radians);
8680
8343
  compositeQ.multiply(deltaQ);
@@ -8683,7 +8346,7 @@ var _Embody = class _Embody {
8683
8346
  if (config.pitch && rotState.pitch !== 0) {
8684
8347
  const binding = this.getCompositeAxisBindingForNode(nodeKey, config.pitch, rotState.pitch);
8685
8348
  if (binding?.maxDegrees && binding.channel) {
8686
- const radians = deg2rad2(binding.maxDegrees) * Math.abs(rotState.pitch) * binding.scale;
8349
+ const radians = deg2rad(binding.maxDegrees) * Math.abs(rotState.pitch) * binding.scale;
8687
8350
  const axis = getAxis(binding.channel);
8688
8351
  const deltaQ = new three.Quaternion().setFromAxisAngle(axis, radians);
8689
8352
  compositeQ.multiply(deltaQ);
@@ -8692,7 +8355,7 @@ var _Embody = class _Embody {
8692
8355
  if (config.roll && rotState.roll !== 0) {
8693
8356
  const binding = this.getCompositeAxisBindingForNode(nodeKey, config.roll, rotState.roll);
8694
8357
  if (binding?.maxDegrees && binding.channel) {
8695
- const radians = deg2rad2(binding.maxDegrees) * Math.abs(rotState.roll) * binding.scale;
8358
+ const radians = deg2rad(binding.maxDegrees) * Math.abs(rotState.roll) * binding.scale;
8696
8359
  const axis = getAxis(binding.channel);
8697
8360
  const deltaQ = new three.Quaternion().setFromAxisAngle(axis, radians);
8698
8361
  compositeQ.multiply(deltaQ);
@@ -9531,11 +9194,11 @@ function applyCharacterModelTransform(model, transform = {}) {
9531
9194
  model.position.set(modelOffset.x ?? 0, modelOffset.y ?? 0, modelOffset.z ?? 0);
9532
9195
  }
9533
9196
  if (modelRotation) {
9534
- const deg2rad3 = Math.PI / 180;
9197
+ const deg2rad2 = Math.PI / 180;
9535
9198
  model.rotation.set(
9536
- (modelRotation.x ?? 0) * deg2rad3,
9537
- (modelRotation.y ?? 0) * deg2rad3,
9538
- (modelRotation.z ?? 0) * deg2rad3
9199
+ (modelRotation.x ?? 0) * deg2rad2,
9200
+ (modelRotation.y ?? 0) * deg2rad2,
9201
+ (modelRotation.z ?? 0) * deg2rad2
9539
9202
  );
9540
9203
  }
9541
9204
  if (modelScale !== void 0 && Number.isFinite(modelScale) && modelScale > 0) {