@lovelace_lol/embody 0.0.4 → 0.0.6
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/core/WasmRuntimeCore.d.ts +10 -24
- package/dist/core/index.d.ts +2 -4
- package/dist/core.cjs +27 -739
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +28 -735
- package/dist/core.js.map +1 -1
- package/dist/engines/three/Embody.d.ts +1 -2
- package/dist/index.cjs +164 -729
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -4
- package/dist/index.js +166 -726
- package/dist/index.js.map +1 -1
- package/dist/three.cjs +162 -499
- package/dist/three.cjs.map +1 -1
- package/dist/three.js +163 -500
- package/dist/three.js.map +1 -1
- package/dist/wasm/embody_wasm.d.ts +3 -3
- package/dist/wasm/embody_wasm.js +3 -3
- package/dist/wasm/embody_wasm_bg.wasm +0 -0
- package/package.json +1 -1
- package/dist/core/TsRuntimeCore.d.ts +0 -40
package/dist/index.cjs
CHANGED
|
@@ -3696,410 +3696,6 @@ function getBlendingName(value) {
|
|
|
3696
3696
|
return "Normal";
|
|
3697
3697
|
}
|
|
3698
3698
|
|
|
3699
|
-
// src/core/TsRuntimeCore.ts
|
|
3700
|
-
var identityQuat = { x: 0, y: 0, z: 0, w: 1 };
|
|
3701
|
-
function isRotationBoneBinding2(binding) {
|
|
3702
|
-
return binding?.channel === "rx" || binding?.channel === "ry" || binding?.channel === "rz";
|
|
3703
|
-
}
|
|
3704
|
-
var TsRuntimeCore = class {
|
|
3705
|
-
constructor(options) {
|
|
3706
|
-
__publicField(this, "profile");
|
|
3707
|
-
__publicField(this, "model");
|
|
3708
|
-
__publicField(this, "auValues", {});
|
|
3709
|
-
__publicField(this, "auBalances", {});
|
|
3710
|
-
__publicField(this, "visemeValues");
|
|
3711
|
-
__publicField(this, "visemeJawScales");
|
|
3712
|
-
__publicField(this, "mixWeights");
|
|
3713
|
-
this.profile = options.profile;
|
|
3714
|
-
this.model = options.model;
|
|
3715
|
-
this.visemeValues = new Array(getProfileVisemeSlots(this.profile).length).fill(0);
|
|
3716
|
-
this.visemeJawScales = new Array(this.visemeValues.length).fill(1);
|
|
3717
|
-
this.mixWeights = { ...this.profile.auMixDefaults };
|
|
3718
|
-
}
|
|
3719
|
-
setProfile(profile) {
|
|
3720
|
-
this.profile = profile;
|
|
3721
|
-
this.visemeValues = new Array(getProfileVisemeSlots(this.profile).length).fill(0);
|
|
3722
|
-
this.visemeJawScales = new Array(this.visemeValues.length).fill(1);
|
|
3723
|
-
this.mixWeights = { ...this.profile.auMixDefaults };
|
|
3724
|
-
}
|
|
3725
|
-
setModelDescriptor(model) {
|
|
3726
|
-
this.model = model;
|
|
3727
|
-
}
|
|
3728
|
-
setAU(id, value, balance) {
|
|
3729
|
-
if (value < 0 && this.profile.continuumPairs) {
|
|
3730
|
-
const pairInfo = this.profile.continuumPairs[id];
|
|
3731
|
-
if (pairInfo) {
|
|
3732
|
-
const negAU = pairInfo.isNegative ? id : pairInfo.pairId;
|
|
3733
|
-
const posAU = pairInfo.isNegative ? pairInfo.pairId : id;
|
|
3734
|
-
this.setContinuum(negAU, posAU, pairInfo.isNegative ? -value : value, balance);
|
|
3735
|
-
return;
|
|
3736
|
-
}
|
|
3737
|
-
}
|
|
3738
|
-
this.auValues[id] = clamp01(value);
|
|
3739
|
-
if (balance !== void 0) {
|
|
3740
|
-
this.auBalances[id] = clampBalance2(balance);
|
|
3741
|
-
}
|
|
3742
|
-
}
|
|
3743
|
-
getAU(id) {
|
|
3744
|
-
return this.auValues[id] ?? 0;
|
|
3745
|
-
}
|
|
3746
|
-
setContinuum(negAU, posAU, continuumValue, balance) {
|
|
3747
|
-
const value = Math.max(-1, Math.min(1, continuumValue));
|
|
3748
|
-
if (value < 0) {
|
|
3749
|
-
this.setAU(posAU, 0, balance);
|
|
3750
|
-
this.setAU(negAU, Math.abs(value), balance);
|
|
3751
|
-
return;
|
|
3752
|
-
}
|
|
3753
|
-
if (value > 0) {
|
|
3754
|
-
this.setAU(negAU, 0, balance);
|
|
3755
|
-
this.setAU(posAU, value, balance);
|
|
3756
|
-
return;
|
|
3757
|
-
}
|
|
3758
|
-
this.setAU(negAU, 0, balance);
|
|
3759
|
-
this.setAU(posAU, 0, balance);
|
|
3760
|
-
}
|
|
3761
|
-
setViseme(visemeIndex, value, jawScale = 1) {
|
|
3762
|
-
if (visemeIndex < 0 || visemeIndex >= this.visemeValues.length) return;
|
|
3763
|
-
this.visemeValues[visemeIndex] = clamp01(value);
|
|
3764
|
-
this.visemeJawScales[visemeIndex] = jawScale;
|
|
3765
|
-
}
|
|
3766
|
-
setVisemeById(slotId, value, jawScale = 1) {
|
|
3767
|
-
const index = getVisemeSlotIndex(this.profile, slotId);
|
|
3768
|
-
if (index < 0) return;
|
|
3769
|
-
this.setViseme(index, value, jawScale);
|
|
3770
|
-
}
|
|
3771
|
-
setAUMixWeight(id, weight) {
|
|
3772
|
-
this.mixWeights[id] = clamp01(weight);
|
|
3773
|
-
}
|
|
3774
|
-
evaluateFrameDelta(deltaSeconds) {
|
|
3775
|
-
const morphWrites = /* @__PURE__ */ new Map();
|
|
3776
|
-
this.collectAUWrites(morphWrites);
|
|
3777
|
-
this.collectVisemeWrites(morphWrites);
|
|
3778
|
-
return {
|
|
3779
|
-
deltaSeconds,
|
|
3780
|
-
morphTargets: Array.from(morphWrites.values()),
|
|
3781
|
-
bones: this.collectBoneWrites()
|
|
3782
|
-
};
|
|
3783
|
-
}
|
|
3784
|
-
collectAUWrites(morphWrites) {
|
|
3785
|
-
for (const [auIdText, entry] of Object.entries(this.profile.auToMorphs || {})) {
|
|
3786
|
-
const auId = Number(auIdText);
|
|
3787
|
-
if (Number.isNaN(auId) || !entry) continue;
|
|
3788
|
-
const mixWeight = this.isMixedAU(auId) ? this.getAUMixWeight(auId) : 1;
|
|
3789
|
-
const base = clamp01(this.auValues[auId] ?? 0) * mixWeight;
|
|
3790
|
-
const { left, right } = computeSideValues(base, this.auBalances[auId]);
|
|
3791
|
-
const meshNames = getMeshNamesForAUProfile(this.profile, auId);
|
|
3792
|
-
for (const morph of entry.left || []) {
|
|
3793
|
-
this.addMorphWrites(morphWrites, morph, meshNames, left);
|
|
3794
|
-
}
|
|
3795
|
-
for (const morph of entry.right || []) {
|
|
3796
|
-
this.addMorphWrites(morphWrites, morph, meshNames, right);
|
|
3797
|
-
}
|
|
3798
|
-
for (const morph of entry.center || []) {
|
|
3799
|
-
this.addMorphWrites(morphWrites, morph, meshNames, base);
|
|
3800
|
-
}
|
|
3801
|
-
}
|
|
3802
|
-
}
|
|
3803
|
-
collectVisemeWrites(morphWrites) {
|
|
3804
|
-
const meshNames = getMeshNamesForVisemeProfile(this.profile);
|
|
3805
|
-
const localMax = /* @__PURE__ */ new Map();
|
|
3806
|
-
for (let index = 0; index < this.visemeValues.length; index += 1) {
|
|
3807
|
-
const value = clamp01(this.visemeValues[index] ?? 0);
|
|
3808
|
-
for (const bindingTarget of getVisemeBindingTargets(this.profile, index)) {
|
|
3809
|
-
const weighted = clamp01(value * bindingTarget.weight);
|
|
3810
|
-
for (const resolved of this.resolveMorphTargets(bindingTarget.morph, meshNames)) {
|
|
3811
|
-
const key = morphWriteKey(resolved.mesh.id, resolved.morphTarget.id);
|
|
3812
|
-
const existing = localMax.get(key);
|
|
3813
|
-
if (!existing || weighted > existing.value) {
|
|
3814
|
-
localMax.set(key, {
|
|
3815
|
-
meshId: resolved.mesh.id,
|
|
3816
|
-
morphTargetId: resolved.morphTarget.id,
|
|
3817
|
-
value: weighted,
|
|
3818
|
-
mode: "absolute"
|
|
3819
|
-
});
|
|
3820
|
-
}
|
|
3821
|
-
}
|
|
3822
|
-
}
|
|
3823
|
-
}
|
|
3824
|
-
for (const [key, write] of localMax) {
|
|
3825
|
-
const existing = morphWrites.get(key);
|
|
3826
|
-
if (!existing || write.value > existing.value) {
|
|
3827
|
-
morphWrites.set(key, write);
|
|
3828
|
-
}
|
|
3829
|
-
}
|
|
3830
|
-
}
|
|
3831
|
-
collectBoneWrites() {
|
|
3832
|
-
const writes = [];
|
|
3833
|
-
const rotations = this.computeRotationState();
|
|
3834
|
-
for (const composite of this.profile.compositeRotations || []) {
|
|
3835
|
-
const bone = this.findBoneDescriptor(composite.node);
|
|
3836
|
-
if (!bone) continue;
|
|
3837
|
-
const transform = this.evaluateCompositeTransform(bone, composite, rotations[composite.node]);
|
|
3838
|
-
if (transform) {
|
|
3839
|
-
writes.push({
|
|
3840
|
-
boneId: bone.id,
|
|
3841
|
-
transform,
|
|
3842
|
-
mode: "absolute",
|
|
3843
|
-
space: "local"
|
|
3844
|
-
});
|
|
3845
|
-
}
|
|
3846
|
-
}
|
|
3847
|
-
for (const [nodeKey, translation] of Object.entries(this.computeTranslations())) {
|
|
3848
|
-
const bone = this.findBoneDescriptor(nodeKey);
|
|
3849
|
-
if (!bone) continue;
|
|
3850
|
-
const position = addVec3(bone.restTransform?.position, translation);
|
|
3851
|
-
upsertBoneWrite(writes, bone.id, { position });
|
|
3852
|
-
}
|
|
3853
|
-
const jawAmount = this.getActiveVisemeJawAmount();
|
|
3854
|
-
const jawBinding = this.findAutoVisemeJawBinding();
|
|
3855
|
-
const jawBone = jawBinding ? this.findBoneDescriptor(jawBinding.node) : void 0;
|
|
3856
|
-
if (jawBone && jawBinding?.maxDegrees && jawBinding.channel) {
|
|
3857
|
-
const current = writes.find((write) => write.boneId === jawBone.id);
|
|
3858
|
-
if (jawAmount > 1e-6 || !current?.transform.rotation) {
|
|
3859
|
-
const rest = jawBone.restTransform?.rotation ?? identityQuat;
|
|
3860
|
-
const rotation = jawAmount > 1e-6 ? multiplyQuat(
|
|
3861
|
-
rest,
|
|
3862
|
-
quatFromChannel(jawBinding.channel, deg2rad(jawBinding.maxDegrees) * jawAmount * jawBinding.scale)
|
|
3863
|
-
) : rest;
|
|
3864
|
-
upsertBoneWrite(writes, jawBone.id, { rotation });
|
|
3865
|
-
}
|
|
3866
|
-
}
|
|
3867
|
-
return writes;
|
|
3868
|
-
}
|
|
3869
|
-
computeRotationState() {
|
|
3870
|
-
const rotations = {};
|
|
3871
|
-
for (const composite of this.profile.compositeRotations || []) {
|
|
3872
|
-
rotations[composite.node] = {
|
|
3873
|
-
pitch: this.getCompositeAxisValueForNode(composite.node, composite.pitch),
|
|
3874
|
-
yaw: this.getCompositeAxisValueForNode(composite.node, composite.yaw),
|
|
3875
|
-
roll: this.getCompositeAxisValueForNode(composite.node, composite.roll)
|
|
3876
|
-
};
|
|
3877
|
-
}
|
|
3878
|
-
return rotations;
|
|
3879
|
-
}
|
|
3880
|
-
evaluateCompositeTransform(bone, composite, state) {
|
|
3881
|
-
if (!state) return null;
|
|
3882
|
-
let rotation = bone.restTransform?.rotation ?? identityQuat;
|
|
3883
|
-
const applyAxis = (axisConfig, direction) => {
|
|
3884
|
-
if (!axisConfig || Math.abs(direction) <= 1e-6) return;
|
|
3885
|
-
const binding = getCompositeAxisBinding(
|
|
3886
|
-
composite.node,
|
|
3887
|
-
axisConfig,
|
|
3888
|
-
direction,
|
|
3889
|
-
(auId) => this.getEffectiveBoneAUValue(auId, composite.node),
|
|
3890
|
-
this.profile.auToBones
|
|
3891
|
-
);
|
|
3892
|
-
if (!binding?.maxDegrees || !binding.channel) return;
|
|
3893
|
-
rotation = multiplyQuat(
|
|
3894
|
-
rotation,
|
|
3895
|
-
quatFromChannel(binding.channel, deg2rad(binding.maxDegrees) * Math.abs(direction) * binding.scale)
|
|
3896
|
-
);
|
|
3897
|
-
};
|
|
3898
|
-
applyAxis(composite.yaw, state.yaw);
|
|
3899
|
-
applyAxis(composite.pitch, state.pitch);
|
|
3900
|
-
applyAxis(composite.roll, state.roll);
|
|
3901
|
-
return { rotation };
|
|
3902
|
-
}
|
|
3903
|
-
computeTranslations() {
|
|
3904
|
-
const translations = {};
|
|
3905
|
-
for (const [auIdText, bindings] of Object.entries(this.profile.auToBones || {})) {
|
|
3906
|
-
const auId = Number(auIdText);
|
|
3907
|
-
if (Number.isNaN(auId)) continue;
|
|
3908
|
-
const value = clamp01(this.auValues[auId] ?? 0);
|
|
3909
|
-
for (const binding of bindings || []) {
|
|
3910
|
-
if (binding.channel !== "tx" && binding.channel !== "ty" && binding.channel !== "tz") continue;
|
|
3911
|
-
if (binding.maxUnits === void 0) continue;
|
|
3912
|
-
const current = translations[binding.node] ?? { x: 0, y: 0, z: 0 };
|
|
3913
|
-
translations[binding.node] = current;
|
|
3914
|
-
if (value <= 1e-6) continue;
|
|
3915
|
-
const offset = clampSigned(value * binding.scale) * binding.maxUnits;
|
|
3916
|
-
translations[binding.node] = {
|
|
3917
|
-
x: binding.channel === "tx" ? offset : current.x,
|
|
3918
|
-
y: binding.channel === "ty" ? offset : current.y,
|
|
3919
|
-
z: binding.channel === "tz" ? offset : current.z
|
|
3920
|
-
};
|
|
3921
|
-
}
|
|
3922
|
-
}
|
|
3923
|
-
return translations;
|
|
3924
|
-
}
|
|
3925
|
-
addMorphWrites(morphWrites, morph, meshNames, value) {
|
|
3926
|
-
for (const resolved of this.resolveMorphTargets(morph, meshNames)) {
|
|
3927
|
-
const key = morphWriteKey(resolved.mesh.id, resolved.morphTarget.id);
|
|
3928
|
-
const existing = morphWrites.get(key);
|
|
3929
|
-
if (existing && existing.value >= value) continue;
|
|
3930
|
-
morphWrites.set(key, {
|
|
3931
|
-
meshId: resolved.mesh.id,
|
|
3932
|
-
morphTargetId: resolved.morphTarget.id,
|
|
3933
|
-
value,
|
|
3934
|
-
mode: "absolute"
|
|
3935
|
-
});
|
|
3936
|
-
}
|
|
3937
|
-
}
|
|
3938
|
-
resolveMorphTargets(morph, meshNames) {
|
|
3939
|
-
const result = [];
|
|
3940
|
-
for (const meshName of meshNames) {
|
|
3941
|
-
const mesh = this.model.meshes.find((candidate) => candidate.name === meshName);
|
|
3942
|
-
if (!mesh) continue;
|
|
3943
|
-
const morphTargets = mesh.morphTargetIds.map((id) => this.model.morphTargets.find((candidate) => candidate.id === id)).filter((target2) => !!target2);
|
|
3944
|
-
const target = typeof morph === "number" ? morphTargets.find((candidate) => candidate.hostIndex === morph) : resolveMorphTargetByName(morphTargets, morph, this.profile);
|
|
3945
|
-
if (target) {
|
|
3946
|
-
result.push({ mesh, morphTarget: target });
|
|
3947
|
-
}
|
|
3948
|
-
}
|
|
3949
|
-
return result;
|
|
3950
|
-
}
|
|
3951
|
-
findBoneDescriptor(nodeKey) {
|
|
3952
|
-
const configuredName = this.profile.boneNodes[nodeKey] || nodeKey;
|
|
3953
|
-
const prefix = this.profile.bonePrefix ?? "";
|
|
3954
|
-
const suffix = this.profile.boneSuffix ?? "";
|
|
3955
|
-
const prefixedName = prefix && !configuredName.startsWith(prefix) ? `${prefix}${configuredName}` : configuredName;
|
|
3956
|
-
const fullName = suffix && !prefixedName.endsWith(suffix) ? `${prefixedName}${suffix}` : prefixedName;
|
|
3957
|
-
const candidates = /* @__PURE__ */ new Set([nodeKey, configuredName, fullName]);
|
|
3958
|
-
return this.model.bones.find((bone) => candidates.has(bone.name));
|
|
3959
|
-
}
|
|
3960
|
-
findAutoVisemeJawBinding() {
|
|
3961
|
-
const candidates = [
|
|
3962
|
-
this.profile.auToBones[103]?.find(isRotationBoneBinding2),
|
|
3963
|
-
this.profile.auToBones[26]?.find(isRotationBoneBinding2)
|
|
3964
|
-
].filter((binding) => !!binding);
|
|
3965
|
-
return candidates.find((binding) => !!this.findBoneDescriptor(binding.node)) ?? candidates[0] ?? null;
|
|
3966
|
-
}
|
|
3967
|
-
getActiveVisemeJawAmount() {
|
|
3968
|
-
const jawAmounts = getVisemeJawAmounts(this.profile) ?? [];
|
|
3969
|
-
let jawAmount = 0;
|
|
3970
|
-
for (let index = 0; index < this.visemeValues.length; index += 1) {
|
|
3971
|
-
const value = clamp01(this.visemeValues[index] ?? 0);
|
|
3972
|
-
if (value <= 1e-6) continue;
|
|
3973
|
-
const jawScale = this.visemeJawScales[index] ?? 1;
|
|
3974
|
-
if (Math.abs(jawScale) <= 1e-6) continue;
|
|
3975
|
-
jawAmount = Math.max(jawAmount, (jawAmounts[index] ?? 0) * value * jawScale);
|
|
3976
|
-
}
|
|
3977
|
-
return jawAmount;
|
|
3978
|
-
}
|
|
3979
|
-
getCompositeAxisValueForNode(nodeKey, axisConfig) {
|
|
3980
|
-
return getCompositeAxisValue(axisConfig, (auId) => this.getEffectiveBoneAUValue(auId, nodeKey));
|
|
3981
|
-
}
|
|
3982
|
-
getEffectiveBoneAUValue(auId, nodeKey) {
|
|
3983
|
-
const rawValue = clamp01(this.auValues[auId] ?? 0);
|
|
3984
|
-
if (rawValue <= 1e-6) return 0;
|
|
3985
|
-
const binding = this.profile.auToBones[auId]?.find((candidate) => candidate.node === nodeKey) ?? null;
|
|
3986
|
-
if (!binding?.side) return rawValue;
|
|
3987
|
-
return rawValue * getSideScale2(this.auBalances[auId] ?? 0, binding.side);
|
|
3988
|
-
}
|
|
3989
|
-
getAUMixWeight(auId) {
|
|
3990
|
-
return this.mixWeights[auId] ?? this.profile.auMixDefaults?.[auId] ?? 1;
|
|
3991
|
-
}
|
|
3992
|
-
isMixedAU(auId) {
|
|
3993
|
-
const morphs = this.profile.auToMorphs[auId];
|
|
3994
|
-
const hasMorphs = !!(morphs?.left?.length || morphs?.right?.length || morphs?.center?.length);
|
|
3995
|
-
return !!(hasMorphs && this.profile.auToBones[auId]?.length);
|
|
3996
|
-
}
|
|
3997
|
-
};
|
|
3998
|
-
function resolveMorphTargetByName(targets, key, profile) {
|
|
3999
|
-
const prefix = profile.morphPrefix || "";
|
|
4000
|
-
const suffix = profile.morphSuffix || "";
|
|
4001
|
-
const fullName = prefix + key + suffix;
|
|
4002
|
-
const exact = targets.find((target) => target.name === fullName);
|
|
4003
|
-
if (exact) return exact;
|
|
4004
|
-
const suffixRegex = profile.suffixPattern ? new RegExp(profile.suffixPattern) : null;
|
|
4005
|
-
if (!suffixRegex) return void 0;
|
|
4006
|
-
return targets.find((target) => {
|
|
4007
|
-
if (!target.name.startsWith(fullName)) return false;
|
|
4008
|
-
const candidateSuffix = target.name.slice(fullName.length);
|
|
4009
|
-
return candidateSuffix === "" || suffixRegex.test(candidateSuffix);
|
|
4010
|
-
});
|
|
4011
|
-
}
|
|
4012
|
-
function computeSideValues(base, balance) {
|
|
4013
|
-
const b = clampBalance2(balance ?? 0);
|
|
4014
|
-
if (b === 0) return { left: base, right: base };
|
|
4015
|
-
if (b < 0) return { left: base, right: base * (1 + b) };
|
|
4016
|
-
return { left: base * (1 - b), right: base };
|
|
4017
|
-
}
|
|
4018
|
-
function getSideScale2(balance, side) {
|
|
4019
|
-
if (side !== "left" && side !== "right") return 1;
|
|
4020
|
-
const b = clampBalance2(balance);
|
|
4021
|
-
if (side === "left") return b > 0 ? 1 - b : 1;
|
|
4022
|
-
return b < 0 ? 1 + b : 1;
|
|
4023
|
-
}
|
|
4024
|
-
function addVec3(base, offset) {
|
|
4025
|
-
return {
|
|
4026
|
-
x: (base?.x ?? 0) + offset.x,
|
|
4027
|
-
y: (base?.y ?? 0) + offset.y,
|
|
4028
|
-
z: (base?.z ?? 0) + offset.z
|
|
4029
|
-
};
|
|
4030
|
-
}
|
|
4031
|
-
function upsertBoneWrite(writes, boneId2, transform) {
|
|
4032
|
-
const existingIndex = writes.findIndex((write) => write.boneId === boneId2);
|
|
4033
|
-
if (existingIndex >= 0) {
|
|
4034
|
-
const existing = writes[existingIndex];
|
|
4035
|
-
writes[existingIndex] = {
|
|
4036
|
-
...existing,
|
|
4037
|
-
transform: {
|
|
4038
|
-
...existing.transform,
|
|
4039
|
-
...transform
|
|
4040
|
-
}
|
|
4041
|
-
};
|
|
4042
|
-
return;
|
|
4043
|
-
}
|
|
4044
|
-
writes.push({
|
|
4045
|
-
boneId: boneId2,
|
|
4046
|
-
transform,
|
|
4047
|
-
mode: "absolute",
|
|
4048
|
-
space: "local"
|
|
4049
|
-
});
|
|
4050
|
-
}
|
|
4051
|
-
function quatFromChannel(channel, radians) {
|
|
4052
|
-
if (channel === "rx") return quatFromAxis({ x: 1, y: 0, z: 0 }, radians);
|
|
4053
|
-
if (channel === "ry") return quatFromAxis({ x: 0, y: 1, z: 0 }, radians);
|
|
4054
|
-
return quatFromAxis({ x: 0, y: 0, z: 1 }, radians);
|
|
4055
|
-
}
|
|
4056
|
-
function quatFromAxis(axis, radians) {
|
|
4057
|
-
const half = radians / 2;
|
|
4058
|
-
const s = Math.sin(half);
|
|
4059
|
-
return normalizeQuat({
|
|
4060
|
-
x: axis.x * s,
|
|
4061
|
-
y: axis.y * s,
|
|
4062
|
-
z: axis.z * s,
|
|
4063
|
-
w: Math.cos(half)
|
|
4064
|
-
});
|
|
4065
|
-
}
|
|
4066
|
-
function multiplyQuat(a, b) {
|
|
4067
|
-
return normalizeQuat({
|
|
4068
|
-
x: a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
|
|
4069
|
-
y: a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
|
|
4070
|
-
z: a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,
|
|
4071
|
-
w: a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z
|
|
4072
|
-
});
|
|
4073
|
-
}
|
|
4074
|
-
function normalizeQuat(q) {
|
|
4075
|
-
const len = Math.hypot(q.x, q.y, q.z, q.w);
|
|
4076
|
-
if (len <= 1e-12) return identityQuat;
|
|
4077
|
-
return {
|
|
4078
|
-
x: q.x / len,
|
|
4079
|
-
y: q.y / len,
|
|
4080
|
-
z: q.z / len,
|
|
4081
|
-
w: q.w / len
|
|
4082
|
-
};
|
|
4083
|
-
}
|
|
4084
|
-
function deg2rad(degrees) {
|
|
4085
|
-
return degrees * Math.PI / 180;
|
|
4086
|
-
}
|
|
4087
|
-
function clamp01(value) {
|
|
4088
|
-
if (!Number.isFinite(value)) return 0;
|
|
4089
|
-
return value < 0 ? 0 : value > 1 ? 1 : value;
|
|
4090
|
-
}
|
|
4091
|
-
function clampSigned(value) {
|
|
4092
|
-
if (!Number.isFinite(value)) return 0;
|
|
4093
|
-
return value < -1 ? -1 : value > 1 ? 1 : value;
|
|
4094
|
-
}
|
|
4095
|
-
function clampBalance2(value) {
|
|
4096
|
-
if (!Number.isFinite(value)) return 0;
|
|
4097
|
-
return Math.max(-1, Math.min(1, value));
|
|
4098
|
-
}
|
|
4099
|
-
function morphWriteKey(meshId2, morphTargetId2) {
|
|
4100
|
-
return `${meshId2}:${morphTargetId2}`;
|
|
4101
|
-
}
|
|
4102
|
-
|
|
4103
3699
|
// src/core/contracts/abi.ts
|
|
4104
3700
|
var PACKED_MORPH_FRAME_DELTA_STRIDE = 4;
|
|
4105
3701
|
var PACKED_BONE_FRAME_DELTA_STRIDE = 9;
|
|
@@ -4229,25 +3825,17 @@ function positiveFiniteOr(value, fallback) {
|
|
|
4229
3825
|
}
|
|
4230
3826
|
|
|
4231
3827
|
// src/core/WasmRuntimeCore.ts
|
|
4232
|
-
var AU_MORPH_BINDING_STRIDE = 5;
|
|
4233
|
-
var VISEME_MORPH_BINDING_STRIDE = 4;
|
|
4234
|
-
var AXIS_GROUP_NEGATIVE = 0;
|
|
4235
|
-
var AXIS_GROUP_POSITIVE = 1;
|
|
4236
|
-
var AXIS_GROUP_PLAIN = 2;
|
|
4237
|
-
var BONE_SIDE_NONE = 0;
|
|
4238
|
-
var BONE_SIDE_LEFT = 1;
|
|
4239
|
-
var BONE_SIDE_RIGHT = 2;
|
|
4240
|
-
var ROTATION_CHANNELS = { rx: 0, ry: 1, rz: 2 };
|
|
4241
|
-
var TRANSLATION_CHANNELS = { tx: 0, ty: 1, tz: 2 };
|
|
4242
3828
|
var WasmRuntimeCore = class {
|
|
4243
3829
|
constructor(options) {
|
|
4244
3830
|
__publicField(this, "wasm");
|
|
4245
3831
|
__publicField(this, "core");
|
|
3832
|
+
__publicField(this, "allowEmptyBindings");
|
|
4246
3833
|
__publicField(this, "profile");
|
|
4247
3834
|
__publicField(this, "model");
|
|
4248
3835
|
this.wasm = options.wasm;
|
|
4249
3836
|
this.profile = options.profile;
|
|
4250
3837
|
this.model = options.model;
|
|
3838
|
+
this.allowEmptyBindings = options.allowEmptyBindings ?? false;
|
|
4251
3839
|
const RuntimeCtor = options.wasm.RuntimeCore;
|
|
4252
3840
|
if (!RuntimeCtor) {
|
|
4253
3841
|
throw new Error("Embody Wasm module does not export RuntimeCore");
|
|
@@ -4266,6 +3854,24 @@ var WasmRuntimeCore = class {
|
|
|
4266
3854
|
setAU(id, value, balance = 0) {
|
|
4267
3855
|
this.core.set_au(id >>> 0, value, balance);
|
|
4268
3856
|
}
|
|
3857
|
+
setContinuum(negativeAU, positiveAU, value, balance = 0) {
|
|
3858
|
+
this.core.set_continuum(negativeAU >>> 0, positiveAU >>> 0, value, balance);
|
|
3859
|
+
}
|
|
3860
|
+
transitionAU(id, to, durationMs, balance = Number.NaN) {
|
|
3861
|
+
this.core.transition_au(id >>> 0, to, durationMs, balance);
|
|
3862
|
+
}
|
|
3863
|
+
transitionViseme(visemeIndex, to, durationMs, jawScale = 1) {
|
|
3864
|
+
this.core.transition_viseme(visemeIndex >>> 0, to, durationMs, jawScale);
|
|
3865
|
+
}
|
|
3866
|
+
update(deltaSeconds) {
|
|
3867
|
+
return this.core.update(deltaSeconds);
|
|
3868
|
+
}
|
|
3869
|
+
activeTransitionCount() {
|
|
3870
|
+
return this.core.active_transition_count();
|
|
3871
|
+
}
|
|
3872
|
+
clearTransitions() {
|
|
3873
|
+
this.core.clear_transitions();
|
|
3874
|
+
}
|
|
4269
3875
|
getAU(id) {
|
|
4270
3876
|
return this.core.get_au(id >>> 0);
|
|
4271
3877
|
}
|
|
@@ -4301,182 +3907,15 @@ var WasmRuntimeCore = class {
|
|
|
4301
3907
|
};
|
|
4302
3908
|
}
|
|
4303
3909
|
reloadBindings() {
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
for (const [auIdText, entry] of Object.entries(profile.auToMorphs || {})) {
|
|
4311
|
-
const auId = Number(auIdText);
|
|
4312
|
-
if (Number.isNaN(auId) || !entry) continue;
|
|
4313
|
-
const meshNames = getMeshNamesForAUProfile(profile, auId);
|
|
4314
|
-
const hasMorphs = !!(entry.left?.length || entry.right?.length || entry.center?.length);
|
|
4315
|
-
if (hasMorphs && profile.auToBones?.[auId]?.length) {
|
|
4316
|
-
mixed.push(auId);
|
|
4317
|
-
}
|
|
4318
|
-
pushAuSide(auRows, auId, 0, entry.left || [], meshNames, model, profile);
|
|
4319
|
-
pushAuSide(auRows, auId, 1, entry.right || [], meshNames, model, profile);
|
|
4320
|
-
pushAuSide(auRows, auId, 2, entry.center || [], meshNames, model, profile);
|
|
4321
|
-
}
|
|
4322
|
-
const visemeRows = [];
|
|
4323
|
-
const visemeMeshNames = getMeshNamesForVisemeProfile(profile);
|
|
4324
|
-
const slotCount = getProfileVisemeSlots(profile).length;
|
|
4325
|
-
for (let index = 0; index < slotCount; index += 1) {
|
|
4326
|
-
for (const bindingTarget of getVisemeBindingTargets(profile, index)) {
|
|
4327
|
-
for (const resolved of resolveMorphTargets(model, profile, bindingTarget.morph, visemeMeshNames)) {
|
|
4328
|
-
visemeRows.push(
|
|
4329
|
-
index,
|
|
4330
|
-
Number(resolved.mesh.id),
|
|
4331
|
-
Number(resolved.morphTarget.id),
|
|
4332
|
-
bindingTarget.weight
|
|
4333
|
-
);
|
|
4334
|
-
}
|
|
3910
|
+
const profileJson = JSON.stringify(this.profile);
|
|
3911
|
+
const modelJson = JSON.stringify(this.model);
|
|
3912
|
+
if (this.allowEmptyBindings) {
|
|
3913
|
+
this.core.configure(profileJson, modelJson);
|
|
3914
|
+
} else {
|
|
3915
|
+
this.core.configure_with_profile(profileJson, modelJson);
|
|
4335
3916
|
}
|
|
4336
3917
|
}
|
|
4337
|
-
|
|
4338
|
-
auBindings: Float32Array.from(auRows),
|
|
4339
|
-
visemeBindings: Float32Array.from(visemeRows),
|
|
4340
|
-
mixedAus: Uint32Array.from(mixed)
|
|
4341
|
-
};
|
|
4342
|
-
}
|
|
4343
|
-
function compileBoneBindings(profile, model) {
|
|
4344
|
-
const referencedBones = /* @__PURE__ */ new Map();
|
|
4345
|
-
const findBone = (nodeKey) => {
|
|
4346
|
-
const bone = findBoneDescriptor(profile, model, nodeKey);
|
|
4347
|
-
if (bone) referencedBones.set(bone.id, bone);
|
|
4348
|
-
return bone;
|
|
4349
|
-
};
|
|
4350
|
-
const boneSideForAU = (auId, nodeKey) => {
|
|
4351
|
-
const side = profile.auToBones?.[auId]?.find((candidate) => candidate.node === nodeKey)?.side;
|
|
4352
|
-
if (side === "left") return BONE_SIDE_LEFT;
|
|
4353
|
-
if (side === "right") return BONE_SIDE_RIGHT;
|
|
4354
|
-
return BONE_SIDE_NONE;
|
|
4355
|
-
};
|
|
4356
|
-
const compositeRows = [];
|
|
4357
|
-
for (const composite of profile.compositeRotations || []) {
|
|
4358
|
-
const bone = findBone(composite.node);
|
|
4359
|
-
if (!bone) continue;
|
|
4360
|
-
const axes = [
|
|
4361
|
-
{ axis: 1, config: composite.yaw },
|
|
4362
|
-
{ axis: 0, config: composite.pitch },
|
|
4363
|
-
{ axis: 2, config: composite.roll }
|
|
4364
|
-
];
|
|
4365
|
-
for (const { axis, config } of axes) {
|
|
4366
|
-
if (!config) continue;
|
|
4367
|
-
const negativeAUs = toAUList(config.negative);
|
|
4368
|
-
const positiveAUs = toAUList(config.positive);
|
|
4369
|
-
const hasDirectional = negativeAUs.length > 0 && positiveAUs.length > 0;
|
|
4370
|
-
const valueRows = [];
|
|
4371
|
-
if (hasDirectional) {
|
|
4372
|
-
for (const auId of negativeAUs) {
|
|
4373
|
-
valueRows.push([auId, AXIS_GROUP_NEGATIVE, boneSideForAU(auId, composite.node)]);
|
|
4374
|
-
}
|
|
4375
|
-
for (const auId of positiveAUs) {
|
|
4376
|
-
valueRows.push([auId, AXIS_GROUP_POSITIVE, boneSideForAU(auId, composite.node)]);
|
|
4377
|
-
}
|
|
4378
|
-
} else {
|
|
4379
|
-
for (const auId of config.aus) {
|
|
4380
|
-
valueRows.push([auId, AXIS_GROUP_PLAIN, boneSideForAU(auId, composite.node)]);
|
|
4381
|
-
}
|
|
4382
|
-
}
|
|
4383
|
-
const bindingRows = [];
|
|
4384
|
-
const pushBindingRows = (auIds, group) => {
|
|
4385
|
-
for (const auId of auIds) {
|
|
4386
|
-
const binding = profile.auToBones?.[auId]?.find(
|
|
4387
|
-
(candidate) => candidate.node === composite.node
|
|
4388
|
-
);
|
|
4389
|
-
if (!binding?.maxDegrees) continue;
|
|
4390
|
-
const channel = ROTATION_CHANNELS[binding.channel];
|
|
4391
|
-
if (channel === void 0) continue;
|
|
4392
|
-
bindingRows.push([
|
|
4393
|
-
auId,
|
|
4394
|
-
group,
|
|
4395
|
-
boneSideForAU(auId, composite.node),
|
|
4396
|
-
channel,
|
|
4397
|
-
binding.scale,
|
|
4398
|
-
binding.maxDegrees
|
|
4399
|
-
]);
|
|
4400
|
-
}
|
|
4401
|
-
};
|
|
4402
|
-
pushBindingRows(negativeAUs, AXIS_GROUP_NEGATIVE);
|
|
4403
|
-
pushBindingRows(positiveAUs, AXIS_GROUP_POSITIVE);
|
|
4404
|
-
pushBindingRows(config.aus, AXIS_GROUP_PLAIN);
|
|
4405
|
-
compositeRows.push(
|
|
4406
|
-
Number(bone.id),
|
|
4407
|
-
axis,
|
|
4408
|
-
hasDirectional ? 1 : 0,
|
|
4409
|
-
valueRows.length,
|
|
4410
|
-
bindingRows.length,
|
|
4411
|
-
0,
|
|
4412
|
-
0,
|
|
4413
|
-
0
|
|
4414
|
-
);
|
|
4415
|
-
for (const row of valueRows) compositeRows.push(...row);
|
|
4416
|
-
for (const row of bindingRows) compositeRows.push(...row);
|
|
4417
|
-
}
|
|
4418
|
-
}
|
|
4419
|
-
const translationRows = [];
|
|
4420
|
-
for (const [auIdText, bindings] of Object.entries(profile.auToBones || {})) {
|
|
4421
|
-
const auId = Number(auIdText);
|
|
4422
|
-
if (Number.isNaN(auId)) continue;
|
|
4423
|
-
for (const binding of bindings || []) {
|
|
4424
|
-
const channel = TRANSLATION_CHANNELS[binding.channel];
|
|
4425
|
-
if (channel === void 0 || binding.maxUnits === void 0) continue;
|
|
4426
|
-
const bone = findBone(binding.node);
|
|
4427
|
-
if (!bone) continue;
|
|
4428
|
-
translationRows.push(auId, Number(bone.id), channel, binding.scale, binding.maxUnits);
|
|
4429
|
-
}
|
|
4430
|
-
}
|
|
4431
|
-
const jawRow = [];
|
|
4432
|
-
const jawBinding = findAutoVisemeJawBinding(profile, model);
|
|
4433
|
-
if (jawBinding?.maxDegrees) {
|
|
4434
|
-
const bone = findBone(jawBinding.node);
|
|
4435
|
-
const channel = ROTATION_CHANNELS[jawBinding.channel];
|
|
4436
|
-
if (bone && channel !== void 0) {
|
|
4437
|
-
jawRow.push(Number(bone.id), channel, jawBinding.scale, jawBinding.maxDegrees);
|
|
4438
|
-
}
|
|
4439
|
-
}
|
|
4440
|
-
const restRows = [];
|
|
4441
|
-
for (const bone of referencedBones.values()) {
|
|
4442
|
-
const position = bone.restTransform?.position;
|
|
4443
|
-
const rotation = bone.restTransform?.rotation;
|
|
4444
|
-
restRows.push(
|
|
4445
|
-
Number(bone.id),
|
|
4446
|
-
position?.x ?? 0,
|
|
4447
|
-
position?.y ?? 0,
|
|
4448
|
-
position?.z ?? 0,
|
|
4449
|
-
rotation?.x ?? 0,
|
|
4450
|
-
rotation?.y ?? 0,
|
|
4451
|
-
rotation?.z ?? 0,
|
|
4452
|
-
rotation?.w ?? 1
|
|
4453
|
-
);
|
|
4454
|
-
}
|
|
4455
|
-
return {
|
|
4456
|
-
restTransforms: Float32Array.from(restRows),
|
|
4457
|
-
compositeAxes: Float32Array.from(compositeRows),
|
|
4458
|
-
translations: Float32Array.from(translationRows),
|
|
4459
|
-
jawBinding: Float32Array.from(jawRow),
|
|
4460
|
-
visemeJawAmounts: Float32Array.from(getVisemeJawAmounts(profile) ?? [])
|
|
4461
|
-
};
|
|
4462
|
-
}
|
|
4463
|
-
function findBoneDescriptor(profile, model, nodeKey) {
|
|
4464
|
-
const configuredName = profile.boneNodes?.[nodeKey] || nodeKey;
|
|
4465
|
-
const prefix = profile.bonePrefix ?? "";
|
|
4466
|
-
const suffix = profile.boneSuffix ?? "";
|
|
4467
|
-
const prefixedName = prefix && !configuredName.startsWith(prefix) ? `${prefix}${configuredName}` : configuredName;
|
|
4468
|
-
const fullName = suffix && !prefixedName.endsWith(suffix) ? `${prefixedName}${suffix}` : prefixedName;
|
|
4469
|
-
const candidates = /* @__PURE__ */ new Set([nodeKey, configuredName, fullName]);
|
|
4470
|
-
return model.bones.find((bone) => candidates.has(bone.name));
|
|
4471
|
-
}
|
|
4472
|
-
function findAutoVisemeJawBinding(profile, model) {
|
|
4473
|
-
const isRotation = (binding) => binding?.channel === "rx" || binding?.channel === "ry" || binding?.channel === "rz";
|
|
4474
|
-
const candidates = [
|
|
4475
|
-
profile.auToBones?.[103]?.find(isRotation),
|
|
4476
|
-
profile.auToBones?.[26]?.find(isRotation)
|
|
4477
|
-
].filter((binding) => !!binding);
|
|
4478
|
-
return candidates.find((binding) => !!findBoneDescriptor(profile, model, binding.node)) ?? candidates[0] ?? null;
|
|
4479
|
-
}
|
|
3918
|
+
};
|
|
4480
3919
|
function unpackBoneFrameDelta(values) {
|
|
4481
3920
|
const stride = PACKED_BONE_FRAME_DELTA_STRIDE;
|
|
4482
3921
|
const writes = [];
|
|
@@ -4517,46 +3956,6 @@ function unpackMorphFrameDelta(values) {
|
|
|
4517
3956
|
}
|
|
4518
3957
|
return writes;
|
|
4519
3958
|
}
|
|
4520
|
-
function pushAuSide(rows, auId, side, morphs, meshNames, model, profile) {
|
|
4521
|
-
for (const morph of morphs) {
|
|
4522
|
-
for (const resolved of resolveMorphTargets(model, profile, morph, meshNames)) {
|
|
4523
|
-
rows.push(
|
|
4524
|
-
auId,
|
|
4525
|
-
side,
|
|
4526
|
-
Number(resolved.mesh.id),
|
|
4527
|
-
Number(resolved.morphTarget.id),
|
|
4528
|
-
1
|
|
4529
|
-
);
|
|
4530
|
-
}
|
|
4531
|
-
}
|
|
4532
|
-
}
|
|
4533
|
-
function resolveMorphTargets(model, profile, morph, meshNames) {
|
|
4534
|
-
const result = [];
|
|
4535
|
-
for (const meshName of meshNames) {
|
|
4536
|
-
const mesh = model.meshes.find((candidate) => candidate.name === meshName);
|
|
4537
|
-
if (!mesh) continue;
|
|
4538
|
-
const morphTargets = mesh.morphTargetIds.map((id) => model.morphTargets.find((candidate) => candidate.id === id)).filter((target2) => !!target2);
|
|
4539
|
-
const target = typeof morph === "number" ? morphTargets.find((candidate) => candidate.hostIndex === morph) : resolveMorphTargetByName2(morphTargets, morph, profile);
|
|
4540
|
-
if (target) {
|
|
4541
|
-
result.push({ mesh, morphTarget: target });
|
|
4542
|
-
}
|
|
4543
|
-
}
|
|
4544
|
-
return result;
|
|
4545
|
-
}
|
|
4546
|
-
function resolveMorphTargetByName2(targets, key, profile) {
|
|
4547
|
-
const prefix = profile.morphPrefix || "";
|
|
4548
|
-
const suffix = profile.morphSuffix || "";
|
|
4549
|
-
const fullName = prefix + key + suffix;
|
|
4550
|
-
const exact = targets.find((target) => target.name === fullName);
|
|
4551
|
-
if (exact) return exact;
|
|
4552
|
-
const suffixRegex = profile.suffixPattern ? new RegExp(profile.suffixPattern) : null;
|
|
4553
|
-
if (!suffixRegex) return void 0;
|
|
4554
|
-
return targets.find((target) => {
|
|
4555
|
-
if (!target.name.startsWith(fullName)) return false;
|
|
4556
|
-
const candidateSuffix = target.name.slice(fullName.length);
|
|
4557
|
-
return candidateSuffix === "" || suffixRegex.test(candidateSuffix);
|
|
4558
|
-
});
|
|
4559
|
-
}
|
|
4560
3959
|
|
|
4561
3960
|
// src/hair/appearance.ts
|
|
4562
3961
|
var HAIR_COLOR_PRESETS = {
|
|
@@ -5872,7 +5271,7 @@ var CC4_PRESET = {
|
|
|
5872
5271
|
};
|
|
5873
5272
|
|
|
5874
5273
|
// src/engines/three/hair/HairPhysicsController.ts
|
|
5875
|
-
var
|
|
5274
|
+
var clamp01 = (value) => value < 0 ? 0 : value > 1 ? 1 : value;
|
|
5876
5275
|
var HairPhysicsController = class {
|
|
5877
5276
|
constructor(host) {
|
|
5878
5277
|
__publicField(this, "host");
|
|
@@ -6370,7 +5769,7 @@ var HairPhysicsController = class {
|
|
|
6370
5769
|
}
|
|
6371
5770
|
}
|
|
6372
5771
|
setMorphOnMeshes(meshNames, morphKey, value) {
|
|
6373
|
-
const val =
|
|
5772
|
+
const val = clamp01(value);
|
|
6374
5773
|
for (const name of meshNames) {
|
|
6375
5774
|
const mesh = this.registeredHairObjects.get(name) || this.host.getMeshByName(name);
|
|
6376
5775
|
if (!mesh) continue;
|
|
@@ -6614,9 +6013,9 @@ var HairPhysicsController = class {
|
|
|
6614
6013
|
const deltaVertical = vertical - this.lastHeadVertical;
|
|
6615
6014
|
this.lastHeadHorizontal = horizontal;
|
|
6616
6015
|
this.lastHeadVertical = vertical;
|
|
6617
|
-
const leftWeight =
|
|
6618
|
-
const rightWeight =
|
|
6619
|
-
const frontWeight =
|
|
6016
|
+
const leftWeight = clamp01(deltaHorizontal > 0 ? deltaHorizontal : 0);
|
|
6017
|
+
const rightWeight = clamp01(deltaHorizontal < 0 ? -deltaHorizontal : 0);
|
|
6018
|
+
const frontWeight = clamp01(deltaVertical > 0 ? deltaVertical : 0);
|
|
6620
6019
|
const minTrigger = 0.01;
|
|
6621
6020
|
if (leftWeight <= minTrigger && rightWeight <= minTrigger && frontWeight <= minTrigger) return;
|
|
6622
6021
|
if (this.impulseClipDirty) {
|
|
@@ -7586,7 +6985,7 @@ async function getPresetWithProfile(presetType, profile) {
|
|
|
7586
6985
|
var resolvePresetWithOverrides = getPresetWithProfile;
|
|
7587
6986
|
|
|
7588
6987
|
// src/engines/three/Embody.ts
|
|
7589
|
-
var
|
|
6988
|
+
var deg2rad = (d) => d * Math.PI / 180;
|
|
7590
6989
|
var X_AXIS2 = new THREE.Vector3(1, 0, 0);
|
|
7591
6990
|
var Y_AXIS2 = new THREE.Vector3(0, 1, 0);
|
|
7592
6991
|
var Z_AXIS2 = new THREE.Vector3(0, 0, 1);
|
|
@@ -7609,9 +7008,18 @@ function buildAUToCompositeMap(composites) {
|
|
|
7609
7008
|
});
|
|
7610
7009
|
return map;
|
|
7611
7010
|
}
|
|
7612
|
-
function
|
|
7011
|
+
function clamp012(x) {
|
|
7613
7012
|
return x < 0 ? 0 : x > 1 ? 1 : x;
|
|
7614
7013
|
}
|
|
7014
|
+
var RESOLVED_TRANSITION_HANDLE = {
|
|
7015
|
+
promise: Promise.resolve(),
|
|
7016
|
+
pause: () => {
|
|
7017
|
+
},
|
|
7018
|
+
resume: () => {
|
|
7019
|
+
},
|
|
7020
|
+
cancel: () => {
|
|
7021
|
+
}
|
|
7022
|
+
};
|
|
7615
7023
|
var _Embody = class _Embody {
|
|
7616
7024
|
constructor(config = {}, animation) {
|
|
7617
7025
|
// Optional hook for animation schedulers.
|
|
@@ -7655,7 +7063,6 @@ var _Embody = class _Embody {
|
|
|
7655
7063
|
__publicField(this, "modelInspector", new ThreeModelInspector());
|
|
7656
7064
|
__publicField(this, "frameApplier", new ThreeFrameApplier());
|
|
7657
7065
|
__publicField(this, "modelDescriptor", null);
|
|
7658
|
-
__publicField(this, "tsRuntimeCore", null);
|
|
7659
7066
|
__publicField(this, "wasmRuntimeCore", null);
|
|
7660
7067
|
__publicField(this, "framePathReady", false);
|
|
7661
7068
|
// Internal animation loop
|
|
@@ -7768,48 +7175,21 @@ var _Embody = class _Embody {
|
|
|
7768
7175
|
bindHostNeutralRuntime(inspection) {
|
|
7769
7176
|
this.modelDescriptor = inspection.descriptor;
|
|
7770
7177
|
this.frameApplier.setBindings(buildFrameApplierBindings(inspection));
|
|
7771
|
-
|
|
7178
|
+
const wasm$1 = wasm.requireInitializedEmbodyCore();
|
|
7179
|
+
this.attachWasmCore(wasm$1);
|
|
7180
|
+
this.wasmRuntimeCore = new WasmRuntimeCore({
|
|
7772
7181
|
profile: this.config,
|
|
7773
|
-
model: inspection.descriptor
|
|
7182
|
+
model: inspection.descriptor,
|
|
7183
|
+
wasm: wasm$1,
|
|
7184
|
+
allowEmptyBindings: true
|
|
7774
7185
|
});
|
|
7775
7186
|
this.syncRuntimeCoreState();
|
|
7776
7187
|
this.framePathReady = true;
|
|
7777
|
-
void wasm.initEmbodyCore().then((wasm) => {
|
|
7778
|
-
if (!this.modelDescriptor) return;
|
|
7779
|
-
this.attachWasmCore(wasm);
|
|
7780
|
-
this.wasmRuntimeCore = new WasmRuntimeCore({
|
|
7781
|
-
profile: this.config,
|
|
7782
|
-
model: this.modelDescriptor,
|
|
7783
|
-
wasm
|
|
7784
|
-
});
|
|
7785
|
-
this.syncRuntimeCoreState();
|
|
7786
|
-
}).catch(() => {
|
|
7787
|
-
this.wasmRuntimeCore = null;
|
|
7788
|
-
});
|
|
7789
7188
|
}
|
|
7790
7189
|
attachWasmCore(core) {
|
|
7791
7190
|
this.hairPhysics.setCore(core);
|
|
7792
7191
|
}
|
|
7793
7192
|
syncRuntimeCoreState() {
|
|
7794
|
-
if (this.tsRuntimeCore) {
|
|
7795
|
-
this.tsRuntimeCore.setProfile(this.config);
|
|
7796
|
-
if (this.modelDescriptor) {
|
|
7797
|
-
this.tsRuntimeCore.setModelDescriptor(this.modelDescriptor);
|
|
7798
|
-
}
|
|
7799
|
-
for (const [auIdText, value] of Object.entries(this.auValues)) {
|
|
7800
|
-
const auId = Number(auIdText);
|
|
7801
|
-
if (Number.isNaN(auId)) continue;
|
|
7802
|
-
this.tsRuntimeCore.setAU(auId, value, this.auBalances[auId]);
|
|
7803
|
-
}
|
|
7804
|
-
for (const [auIdText, weight] of Object.entries(this.mixWeights)) {
|
|
7805
|
-
const auId = Number(auIdText);
|
|
7806
|
-
if (Number.isNaN(auId)) continue;
|
|
7807
|
-
this.tsRuntimeCore.setAUMixWeight(auId, weight);
|
|
7808
|
-
}
|
|
7809
|
-
for (let index = 0; index < this.visemeValues.length; index += 1) {
|
|
7810
|
-
this.tsRuntimeCore.setViseme(index, this.visemeValues[index] ?? 0, this.visemeJawScales[index] ?? 1);
|
|
7811
|
-
}
|
|
7812
|
-
}
|
|
7813
7193
|
if (this.wasmRuntimeCore) {
|
|
7814
7194
|
this.wasmRuntimeCore.setProfile(this.config);
|
|
7815
7195
|
if (this.modelDescriptor) {
|
|
@@ -7827,7 +7207,7 @@ var _Embody = class _Embody {
|
|
|
7827
7207
|
this.wasmRuntimeCore.setAUMixWeight(auId, weight);
|
|
7828
7208
|
}
|
|
7829
7209
|
for (let index = 0; index < this.visemeValues.length; index += 1) {
|
|
7830
|
-
this.wasmRuntimeCore.setViseme(index, this.visemeValues[index] ?? 0);
|
|
7210
|
+
this.wasmRuntimeCore.setViseme(index, this.visemeValues[index] ?? 0, this.visemeJawScales[index] ?? 1);
|
|
7831
7211
|
}
|
|
7832
7212
|
}
|
|
7833
7213
|
}
|
|
@@ -7845,25 +7225,13 @@ var _Embody = class _Embody {
|
|
|
7845
7225
|
});
|
|
7846
7226
|
this.modelDescriptor = inspection.descriptor;
|
|
7847
7227
|
this.frameApplier.setBindings(buildFrameApplierBindings(inspection));
|
|
7848
|
-
this.tsRuntimeCore?.setModelDescriptor(inspection.descriptor);
|
|
7849
7228
|
this.wasmRuntimeCore?.setModelDescriptor(inspection.descriptor);
|
|
7850
7229
|
}
|
|
7851
|
-
|
|
7852
|
-
if (!this.framePathReady || !this.model) return false;
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
);
|
|
7857
|
-
return true;
|
|
7858
|
-
}
|
|
7859
|
-
if (this.tsRuntimeCore) {
|
|
7860
|
-
const frame = this.tsRuntimeCore.evaluateFrameDelta();
|
|
7861
|
-
this.frameApplier.applyFrameDelta(this.model, {
|
|
7862
|
-
morphTargets: frame.morphTargets
|
|
7863
|
-
});
|
|
7864
|
-
return true;
|
|
7865
|
-
}
|
|
7866
|
-
return false;
|
|
7230
|
+
applyLiveFrameDelta() {
|
|
7231
|
+
if (!this.framePathReady || !this.model || !this.wasmRuntimeCore) return false;
|
|
7232
|
+
this.frameApplier.applyFrameDelta(this.model, this.wasmRuntimeCore.evaluateFrameDelta());
|
|
7233
|
+
this.pendingCompositeNodes.clear();
|
|
7234
|
+
return true;
|
|
7867
7235
|
}
|
|
7868
7236
|
rebuildMorphTargetsCache() {
|
|
7869
7237
|
this.morphKeyCache.clear();
|
|
@@ -7965,6 +7333,11 @@ var _Embody = class _Embody {
|
|
|
7965
7333
|
const dtSeconds = Math.max(0, deltaSeconds || 0);
|
|
7966
7334
|
if (dtSeconds <= 0 || this.isPaused) return;
|
|
7967
7335
|
this.animation.tick(dtSeconds);
|
|
7336
|
+
const wasmTransitionCount = this.wasmRuntimeCore?.activeTransitionCount() ?? 0;
|
|
7337
|
+
const remainingWasmTransitions = this.wasmRuntimeCore?.update(dtSeconds) ?? 0;
|
|
7338
|
+
if (wasmTransitionCount > 0 || remainingWasmTransitions > 0) {
|
|
7339
|
+
this.applyLiveFrameDelta();
|
|
7340
|
+
}
|
|
7968
7341
|
this.flushPendingComposites();
|
|
7969
7342
|
this.animationController.update(dtSeconds);
|
|
7970
7343
|
this.hairPhysics.update(dtSeconds);
|
|
@@ -7999,7 +7372,6 @@ var _Embody = class _Embody {
|
|
|
7999
7372
|
this.model = null;
|
|
8000
7373
|
this.bones = {};
|
|
8001
7374
|
this.modelDescriptor = null;
|
|
8002
|
-
this.tsRuntimeCore = null;
|
|
8003
7375
|
this.wasmRuntimeCore = null;
|
|
8004
7376
|
this.framePathReady = false;
|
|
8005
7377
|
}
|
|
@@ -8036,15 +7408,14 @@ var _Embody = class _Embody {
|
|
|
8036
7408
|
if (balance !== void 0) {
|
|
8037
7409
|
this.auBalances[id] = balance;
|
|
8038
7410
|
}
|
|
8039
|
-
this.tsRuntimeCore?.setAU(id, v, balance);
|
|
8040
7411
|
this.wasmRuntimeCore?.setAU(id, v, balance ?? this.auBalances[id] ?? 0);
|
|
8041
|
-
const appliedViaFrame = this.
|
|
7412
|
+
const appliedViaFrame = this.applyLiveFrameDelta();
|
|
8042
7413
|
if (!appliedViaFrame) {
|
|
8043
7414
|
const resolvedMorphTargets = this.resolvedAUMorphTargets.get(id);
|
|
8044
7415
|
const { left: leftKeys, right: rightKeys, center: centerKeys } = this.getAUMorphsBySide(id);
|
|
8045
7416
|
if (resolvedMorphTargets) {
|
|
8046
7417
|
const mixWeight = this.isMixedAU(id) ? this.getAUMixWeight(id) : 1;
|
|
8047
|
-
const base =
|
|
7418
|
+
const base = clamp012(v) * mixWeight;
|
|
8048
7419
|
const { left: leftVal, right: rightVal } = this.computeSideValues(base, balance);
|
|
8049
7420
|
if (resolvedMorphTargets.left.length || resolvedMorphTargets.right.length) {
|
|
8050
7421
|
this.applyMorphTargets(resolvedMorphTargets.left, leftVal);
|
|
@@ -8053,7 +7424,7 @@ var _Embody = class _Embody {
|
|
|
8053
7424
|
this.applyMorphTargets(resolvedMorphTargets.center, base);
|
|
8054
7425
|
} else if (leftKeys.length || rightKeys.length || centerKeys.length) {
|
|
8055
7426
|
const mixWeight = this.isMixedAU(id) ? this.getAUMixWeight(id) : 1;
|
|
8056
|
-
const base =
|
|
7427
|
+
const base = clamp012(v) * mixWeight;
|
|
8057
7428
|
const meshNames = this.getMeshNamesForAU(id);
|
|
8058
7429
|
const { left: leftVal, right: rightVal } = this.computeSideValues(base, balance);
|
|
8059
7430
|
if (leftKeys.length || rightKeys.length) {
|
|
@@ -8072,6 +7443,7 @@ var _Embody = class _Embody {
|
|
|
8072
7443
|
}
|
|
8073
7444
|
}
|
|
8074
7445
|
}
|
|
7446
|
+
if (appliedViaFrame) return;
|
|
8075
7447
|
const compositeInfo = this.auToCompositeMap.get(id);
|
|
8076
7448
|
if (compositeInfo) {
|
|
8077
7449
|
for (const nodeKey of compositeInfo.nodes) {
|
|
@@ -8106,7 +7478,7 @@ var _Embody = class _Embody {
|
|
|
8106
7478
|
return this.transitionContinuum(negAU, posAU, continuumValue, durationMs, balance);
|
|
8107
7479
|
}
|
|
8108
7480
|
}
|
|
8109
|
-
const target =
|
|
7481
|
+
const target = clamp012(to);
|
|
8110
7482
|
if (balance !== void 0) {
|
|
8111
7483
|
this.auBalances[numId] = balance;
|
|
8112
7484
|
}
|
|
@@ -8117,6 +7489,19 @@ var _Embody = class _Embody {
|
|
|
8117
7489
|
const base = target * mixWeight;
|
|
8118
7490
|
const { left: leftVal, right: rightVal } = this.computeSideValues(base, storedBalance);
|
|
8119
7491
|
this.auValues[numId] = target;
|
|
7492
|
+
if (this.wasmRuntimeCore) {
|
|
7493
|
+
this.wasmRuntimeCore.transitionAU(
|
|
7494
|
+
numId,
|
|
7495
|
+
target,
|
|
7496
|
+
durationMs,
|
|
7497
|
+
balance ?? this.auBalances[numId] ?? Number.NaN
|
|
7498
|
+
);
|
|
7499
|
+
this.update(0);
|
|
7500
|
+
if (durationMs <= 0) {
|
|
7501
|
+
this.applyLiveFrameDelta();
|
|
7502
|
+
}
|
|
7503
|
+
return RESOLVED_TRANSITION_HANDLE;
|
|
7504
|
+
}
|
|
8120
7505
|
const handles = [];
|
|
8121
7506
|
const meshNames = this.getMeshNamesForAU(numId);
|
|
8122
7507
|
if (leftKeys.length || rightKeys.length) {
|
|
@@ -8179,6 +7564,17 @@ var _Embody = class _Embody {
|
|
|
8179
7564
|
*/
|
|
8180
7565
|
setContinuum(negAU, posAU, continuumValue, balance) {
|
|
8181
7566
|
const value = Math.max(-1, Math.min(1, continuumValue));
|
|
7567
|
+
this.auValues[negAU] = value < 0 ? Math.abs(value) : 0;
|
|
7568
|
+
this.auValues[posAU] = value > 0 ? value : 0;
|
|
7569
|
+
if (balance !== void 0) {
|
|
7570
|
+
this.auBalances[negAU] = balance;
|
|
7571
|
+
this.auBalances[posAU] = balance;
|
|
7572
|
+
}
|
|
7573
|
+
if (this.wasmRuntimeCore) {
|
|
7574
|
+
this.wasmRuntimeCore.setContinuum(negAU, posAU, value, balance ?? 0);
|
|
7575
|
+
this.applyLiveFrameDelta();
|
|
7576
|
+
return;
|
|
7577
|
+
}
|
|
8182
7578
|
if (value < 0) {
|
|
8183
7579
|
this.setAU(posAU, 0, balance);
|
|
8184
7580
|
this.setAU(negAU, Math.abs(value), balance);
|
|
@@ -8204,10 +7600,32 @@ var _Embody = class _Embody {
|
|
|
8204
7600
|
*/
|
|
8205
7601
|
transitionContinuum(negAU, posAU, continuumValue, durationMs = 200, balance) {
|
|
8206
7602
|
const target = Math.max(-1, Math.min(1, continuumValue));
|
|
8207
|
-
const driverKey = `continuum_${negAU}_${posAU}`;
|
|
8208
7603
|
const currentNeg = this.auValues[negAU] ?? 0;
|
|
8209
7604
|
const currentPos = this.auValues[posAU] ?? 0;
|
|
8210
7605
|
const currentContinuum = currentPos - currentNeg;
|
|
7606
|
+
this.auValues[negAU] = target < 0 ? Math.abs(target) : 0;
|
|
7607
|
+
this.auValues[posAU] = target > 0 ? target : 0;
|
|
7608
|
+
if (balance !== void 0) {
|
|
7609
|
+
this.auBalances[negAU] = balance;
|
|
7610
|
+
this.auBalances[posAU] = balance;
|
|
7611
|
+
}
|
|
7612
|
+
if (this.wasmRuntimeCore) {
|
|
7613
|
+
if (target < 0) {
|
|
7614
|
+
this.wasmRuntimeCore.transitionAU(posAU, 0, durationMs, balance ?? this.auBalances[posAU] ?? Number.NaN);
|
|
7615
|
+
this.wasmRuntimeCore.transitionAU(negAU, Math.abs(target), durationMs, balance ?? this.auBalances[negAU] ?? Number.NaN);
|
|
7616
|
+
} else if (target > 0) {
|
|
7617
|
+
this.wasmRuntimeCore.transitionAU(negAU, 0, durationMs, balance ?? this.auBalances[negAU] ?? Number.NaN);
|
|
7618
|
+
this.wasmRuntimeCore.transitionAU(posAU, target, durationMs, balance ?? this.auBalances[posAU] ?? Number.NaN);
|
|
7619
|
+
} else {
|
|
7620
|
+
this.wasmRuntimeCore.transitionAU(negAU, 0, durationMs, balance ?? this.auBalances[negAU] ?? Number.NaN);
|
|
7621
|
+
this.wasmRuntimeCore.transitionAU(posAU, 0, durationMs, balance ?? this.auBalances[posAU] ?? Number.NaN);
|
|
7622
|
+
}
|
|
7623
|
+
if (durationMs <= 0) {
|
|
7624
|
+
this.applyLiveFrameDelta();
|
|
7625
|
+
}
|
|
7626
|
+
return RESOLVED_TRANSITION_HANDLE;
|
|
7627
|
+
}
|
|
7628
|
+
const driverKey = `continuum_${negAU}_${posAU}`;
|
|
8211
7629
|
return this.animation.addTransition(driverKey, currentContinuum, target, durationMs, (value) => this.setContinuum(negAU, posAU, value, balance));
|
|
8212
7630
|
}
|
|
8213
7631
|
// ============================================================================
|
|
@@ -8289,7 +7707,7 @@ var _Embody = class _Embody {
|
|
|
8289
7707
|
this.hairPhysics.refreshMeshSelection();
|
|
8290
7708
|
}
|
|
8291
7709
|
setMorph(key, v, meshNamesOrTargets) {
|
|
8292
|
-
const val =
|
|
7710
|
+
const val = clamp012(v);
|
|
8293
7711
|
if (Array.isArray(meshNamesOrTargets) && meshNamesOrTargets.length > 0 && typeof meshNamesOrTargets[0] === "object" && "infl" in meshNamesOrTargets[0]) {
|
|
8294
7712
|
const targets2 = meshNamesOrTargets;
|
|
8295
7713
|
this.applyMorphTargets(targets2, val);
|
|
@@ -8301,7 +7719,7 @@ var _Embody = class _Embody {
|
|
|
8301
7719
|
this.applyMorphTargets(targets, val);
|
|
8302
7720
|
}
|
|
8303
7721
|
setMorphInfluence(index, v, meshNames) {
|
|
8304
|
-
const val =
|
|
7722
|
+
const val = clamp012(v);
|
|
8305
7723
|
const targets = this.resolveMorphTargetsByIndex(index, meshNames);
|
|
8306
7724
|
if (targets.length === 0) return;
|
|
8307
7725
|
this.applyMorphTargets(targets, val);
|
|
@@ -8376,21 +7794,21 @@ var _Embody = class _Embody {
|
|
|
8376
7794
|
}
|
|
8377
7795
|
transitionMorph(key, to, durationMs = 120, meshNames) {
|
|
8378
7796
|
const transitionKey = meshNames?.length ? `morph_${this.getMorphKeyCacheKey(key, meshNames)}` : `morph_${this.getMorphKeyCacheKey(key)}`;
|
|
8379
|
-
const target =
|
|
7797
|
+
const target = clamp012(to);
|
|
8380
7798
|
const targets = this.resolveMorphTargets(key, meshNames);
|
|
8381
7799
|
const from = targets.length > 0 ? targets[0].infl[targets[0].idx] ?? 0 : this.getMorphValue(key);
|
|
8382
7800
|
return this.animation.addTransition(transitionKey, from, target, durationMs, (value) => {
|
|
8383
|
-
const val =
|
|
7801
|
+
const val = clamp012(value);
|
|
8384
7802
|
this.applyMorphTargets(targets, val);
|
|
8385
7803
|
});
|
|
8386
7804
|
}
|
|
8387
7805
|
transitionMorphInfluence(index, to, durationMs = 120, meshNames) {
|
|
8388
7806
|
const transitionKey = meshNames?.length ? `morph_${this.getMorphIndexCacheKey(index, meshNames)}` : `morph_${this.getMorphIndexCacheKey(index)}`;
|
|
8389
|
-
const target =
|
|
7807
|
+
const target = clamp012(to);
|
|
8390
7808
|
const targets = this.resolveMorphTargetsByIndex(index, meshNames);
|
|
8391
7809
|
const from = targets.length > 0 ? targets[0].infl[targets[0].idx] ?? 0 : this.getMorphValueByIndex(index);
|
|
8392
7810
|
return this.animation.addTransition(transitionKey, from, target, durationMs, (value) => {
|
|
8393
|
-
const val =
|
|
7811
|
+
const val = clamp012(value);
|
|
8394
7812
|
this.applyMorphTargets(targets, val);
|
|
8395
7813
|
});
|
|
8396
7814
|
}
|
|
@@ -8399,7 +7817,7 @@ var _Embody = class _Embody {
|
|
|
8399
7817
|
// ============================================================================
|
|
8400
7818
|
setViseme(visemeIndex, value, jawScale = 1) {
|
|
8401
7819
|
if (visemeIndex < 0 || visemeIndex >= this.visemeValues.length) return;
|
|
8402
|
-
const val =
|
|
7820
|
+
const val = clamp012(value);
|
|
8403
7821
|
this.visemeValues[visemeIndex] = val;
|
|
8404
7822
|
this.visemeJawScales[visemeIndex] = jawScale;
|
|
8405
7823
|
this.applyVisemeRuntimeState();
|
|
@@ -8411,16 +7829,24 @@ var _Embody = class _Embody {
|
|
|
8411
7829
|
}, cancel: () => {
|
|
8412
7830
|
} };
|
|
8413
7831
|
}
|
|
8414
|
-
const target =
|
|
7832
|
+
const target = clamp012(to);
|
|
8415
7833
|
const from = this.visemeValues[visemeIndex] ?? 0;
|
|
8416
7834
|
this.visemeJawScales[visemeIndex] = jawScale;
|
|
7835
|
+
if (this.wasmRuntimeCore) {
|
|
7836
|
+
this.visemeValues[visemeIndex] = target;
|
|
7837
|
+
this.wasmRuntimeCore.transitionViseme(visemeIndex, target, durationMs, jawScale);
|
|
7838
|
+
if (durationMs <= 0) {
|
|
7839
|
+
this.applyLiveFrameDelta();
|
|
7840
|
+
}
|
|
7841
|
+
return RESOLVED_TRANSITION_HANDLE;
|
|
7842
|
+
}
|
|
8417
7843
|
return this.animation.addTransition(
|
|
8418
7844
|
`viseme_value_${visemeIndex}`,
|
|
8419
7845
|
from,
|
|
8420
7846
|
target,
|
|
8421
7847
|
durationMs,
|
|
8422
7848
|
(value) => {
|
|
8423
|
-
this.visemeValues[visemeIndex] =
|
|
7849
|
+
this.visemeValues[visemeIndex] = clamp012(value);
|
|
8424
7850
|
this.visemeJawScales[visemeIndex] = jawScale;
|
|
8425
7851
|
this.applyVisemeRuntimeState();
|
|
8426
7852
|
}
|
|
@@ -8445,8 +7871,7 @@ var _Embody = class _Embody {
|
|
|
8445
7871
|
// MIX WEIGHT CONTROL
|
|
8446
7872
|
// ============================================================================
|
|
8447
7873
|
setAUMixWeight(id, weight) {
|
|
8448
|
-
this.mixWeights[id] =
|
|
8449
|
-
this.tsRuntimeCore?.setAUMixWeight(id, weight);
|
|
7874
|
+
this.mixWeights[id] = clamp012(weight);
|
|
8450
7875
|
this.wasmRuntimeCore?.setAUMixWeight(id, weight);
|
|
8451
7876
|
const v = this.auValues[id] ?? 0;
|
|
8452
7877
|
if (v > 0) this.setAU(id, v);
|
|
@@ -8484,9 +7909,10 @@ var _Embody = class _Embody {
|
|
|
8484
7909
|
}
|
|
8485
7910
|
clearTransitions() {
|
|
8486
7911
|
this.animation.clearTransitions();
|
|
7912
|
+
this.wasmRuntimeCore?.clearTransitions();
|
|
8487
7913
|
}
|
|
8488
7914
|
getActiveTransitionCount() {
|
|
8489
|
-
return this.animation.getActiveTransitionCount();
|
|
7915
|
+
return this.animation.getActiveTransitionCount() + (this.wasmRuntimeCore?.activeTransitionCount() ?? 0);
|
|
8490
7916
|
}
|
|
8491
7917
|
resetToNeutral() {
|
|
8492
7918
|
this.auValues = {};
|
|
@@ -8496,6 +7922,7 @@ var _Embody = class _Embody {
|
|
|
8496
7922
|
this.translations = {};
|
|
8497
7923
|
this.initBoneRotations();
|
|
8498
7924
|
this.clearTransitions();
|
|
7925
|
+
this.wasmRuntimeCore?.clear();
|
|
8499
7926
|
const morphTargetsToReset = [];
|
|
8500
7927
|
for (const m of this.meshes) {
|
|
8501
7928
|
const infl = m.morphTargetInfluences;
|
|
@@ -8674,7 +8101,18 @@ var _Embody = class _Embody {
|
|
|
8674
8101
|
this.bones = this.resolveBones(this.model);
|
|
8675
8102
|
this.missingBoneWarnings.clear();
|
|
8676
8103
|
this.rebuildMorphTargetsCache();
|
|
8677
|
-
|
|
8104
|
+
Object.values(this.bones).forEach((entry) => {
|
|
8105
|
+
if (!entry) return;
|
|
8106
|
+
this.frameApplier.applyObjectTransform(entry.obj, {
|
|
8107
|
+
position: { x: entry.basePos.x, y: entry.basePos.y, z: entry.basePos.z },
|
|
8108
|
+
rotation: {
|
|
8109
|
+
x: entry.baseQuat.x,
|
|
8110
|
+
y: entry.baseQuat.y,
|
|
8111
|
+
z: entry.baseQuat.z,
|
|
8112
|
+
w: entry.baseQuat.w
|
|
8113
|
+
}
|
|
8114
|
+
});
|
|
8115
|
+
});
|
|
8678
8116
|
this.wasmRuntimeCore?.setProfile(this.config);
|
|
8679
8117
|
this.refreshHostNeutralModelDescriptor();
|
|
8680
8118
|
}
|
|
@@ -8791,20 +8229,20 @@ var _Embody = class _Embody {
|
|
|
8791
8229
|
}
|
|
8792
8230
|
applyVisemeRuntimeState() {
|
|
8793
8231
|
for (let index = 0; index < this.visemeValues.length; index += 1) {
|
|
8794
|
-
this.
|
|
8795
|
-
this.wasmRuntimeCore?.setViseme(index, this.visemeValues[index] ?? 0);
|
|
8232
|
+
this.wasmRuntimeCore?.setViseme(index, this.visemeValues[index] ?? 0, this.visemeJawScales[index] ?? 1);
|
|
8796
8233
|
}
|
|
8797
|
-
|
|
8234
|
+
const appliedViaFrame = this.applyLiveFrameDelta();
|
|
8235
|
+
if (!appliedViaFrame) {
|
|
8798
8236
|
for (const targets of this.resolvedVisemeTargets) {
|
|
8799
8237
|
this.frameApplier.resetMorphTargets(targets || []);
|
|
8800
8238
|
}
|
|
8801
8239
|
for (let index = 0; index < this.visemeValues.length; index += 1) {
|
|
8802
|
-
const value =
|
|
8240
|
+
const value = clamp012(this.visemeValues[index] ?? 0);
|
|
8803
8241
|
if (value <= 1e-6) continue;
|
|
8804
8242
|
const targets = this.resolvedVisemeTargets[index] || [];
|
|
8805
8243
|
for (const target of targets) {
|
|
8806
8244
|
if (target.idx >= target.infl.length) continue;
|
|
8807
|
-
const weighted =
|
|
8245
|
+
const weighted = clamp012(value * target.weight);
|
|
8808
8246
|
this.frameApplier.applyMorphTargets(
|
|
8809
8247
|
[target],
|
|
8810
8248
|
Math.max(target.infl[target.idx] ?? 0, weighted)
|
|
@@ -8812,7 +8250,9 @@ var _Embody = class _Embody {
|
|
|
8812
8250
|
}
|
|
8813
8251
|
}
|
|
8814
8252
|
}
|
|
8815
|
-
|
|
8253
|
+
if (!appliedViaFrame) {
|
|
8254
|
+
this.updateBoneRotation(this.getJawBoneNodeKey(), "pitch", this.getActiveVisemeJawAmount());
|
|
8255
|
+
}
|
|
8816
8256
|
}
|
|
8817
8257
|
getJawBoneNodeKey() {
|
|
8818
8258
|
const candidates = [
|
|
@@ -8834,7 +8274,7 @@ var _Embody = class _Embody {
|
|
|
8834
8274
|
getActiveVisemeJawAmount() {
|
|
8835
8275
|
let jawAmount = 0;
|
|
8836
8276
|
for (let index = 0; index < this.visemeValues.length; index += 1) {
|
|
8837
|
-
const value =
|
|
8277
|
+
const value = clamp012(this.visemeValues[index] ?? 0);
|
|
8838
8278
|
if (value <= 1e-6) continue;
|
|
8839
8279
|
const jawScale = this.visemeJawScales[index] ?? 1;
|
|
8840
8280
|
if (Math.abs(jawScale) <= 1e-6) continue;
|
|
@@ -9117,7 +8557,7 @@ var _Embody = class _Embody {
|
|
|
9117
8557
|
return !!(hasMorphs && this.config.auToBones[id]?.length);
|
|
9118
8558
|
}
|
|
9119
8559
|
getEffectiveBoneAUValue(auId, nodeKey) {
|
|
9120
|
-
const rawValue =
|
|
8560
|
+
const rawValue = clamp012(this.auValues[auId] ?? 0);
|
|
9121
8561
|
if (rawValue <= 1e-6) return 0;
|
|
9122
8562
|
const binding = this.config.auToBones[auId]?.find((candidate) => candidate.node === nodeKey) ?? null;
|
|
9123
8563
|
if (!binding?.side) return rawValue;
|
|
@@ -9217,7 +8657,7 @@ var _Embody = class _Embody {
|
|
|
9217
8657
|
if (config.yaw && rotState.yaw !== 0) {
|
|
9218
8658
|
const binding = this.getCompositeAxisBindingForNode(nodeKey, config.yaw, rotState.yaw);
|
|
9219
8659
|
if (binding?.maxDegrees && binding.channel) {
|
|
9220
|
-
const radians =
|
|
8660
|
+
const radians = deg2rad(binding.maxDegrees) * Math.abs(rotState.yaw) * binding.scale;
|
|
9221
8661
|
const axis = getAxis(binding.channel);
|
|
9222
8662
|
const deltaQ = new THREE.Quaternion().setFromAxisAngle(axis, radians);
|
|
9223
8663
|
compositeQ.multiply(deltaQ);
|
|
@@ -9226,7 +8666,7 @@ var _Embody = class _Embody {
|
|
|
9226
8666
|
if (config.pitch && rotState.pitch !== 0) {
|
|
9227
8667
|
const binding = this.getCompositeAxisBindingForNode(nodeKey, config.pitch, rotState.pitch);
|
|
9228
8668
|
if (binding?.maxDegrees && binding.channel) {
|
|
9229
|
-
const radians =
|
|
8669
|
+
const radians = deg2rad(binding.maxDegrees) * Math.abs(rotState.pitch) * binding.scale;
|
|
9230
8670
|
const axis = getAxis(binding.channel);
|
|
9231
8671
|
const deltaQ = new THREE.Quaternion().setFromAxisAngle(axis, radians);
|
|
9232
8672
|
compositeQ.multiply(deltaQ);
|
|
@@ -9235,7 +8675,7 @@ var _Embody = class _Embody {
|
|
|
9235
8675
|
if (config.roll && rotState.roll !== 0) {
|
|
9236
8676
|
const binding = this.getCompositeAxisBindingForNode(nodeKey, config.roll, rotState.roll);
|
|
9237
8677
|
if (binding?.maxDegrees && binding.channel) {
|
|
9238
|
-
const radians =
|
|
8678
|
+
const radians = deg2rad(binding.maxDegrees) * Math.abs(rotState.roll) * binding.scale;
|
|
9239
8679
|
const axis = getAxis(binding.channel);
|
|
9240
8680
|
const deltaQ = new THREE.Quaternion().setFromAxisAngle(axis, radians);
|
|
9241
8681
|
compositeQ.multiply(deltaQ);
|
|
@@ -10074,11 +9514,11 @@ function applyCharacterModelTransform(model, transform = {}) {
|
|
|
10074
9514
|
model.position.set(modelOffset.x ?? 0, modelOffset.y ?? 0, modelOffset.z ?? 0);
|
|
10075
9515
|
}
|
|
10076
9516
|
if (modelRotation) {
|
|
10077
|
-
const
|
|
9517
|
+
const deg2rad2 = Math.PI / 180;
|
|
10078
9518
|
model.rotation.set(
|
|
10079
|
-
(modelRotation.x ?? 0) *
|
|
10080
|
-
(modelRotation.y ?? 0) *
|
|
10081
|
-
(modelRotation.z ?? 0) *
|
|
9519
|
+
(modelRotation.x ?? 0) * deg2rad2,
|
|
9520
|
+
(modelRotation.y ?? 0) * deg2rad2,
|
|
9521
|
+
(modelRotation.z ?? 0) * deg2rad2
|
|
10082
9522
|
);
|
|
10083
9523
|
}
|
|
10084
9524
|
if (modelScale !== void 0 && Number.isFinite(modelScale) && modelScale > 0) {
|
|
@@ -15094,7 +14534,7 @@ function computeHumanoidSkeletonTemplateRestBounds(template) {
|
|
|
15094
14534
|
}
|
|
15095
14535
|
const parentPosition = worldPositions.get(bone.parent);
|
|
15096
14536
|
if (!parentPosition) continue;
|
|
15097
|
-
worldPositions.set(bone.name,
|
|
14537
|
+
worldPositions.set(bone.name, addVec3(parentPosition, bone.translation));
|
|
15098
14538
|
unresolved.delete(bone.name);
|
|
15099
14539
|
resolvedThisPass += 1;
|
|
15100
14540
|
}
|
|
@@ -15155,7 +14595,7 @@ function assertNonEmptyString(value, fieldName) {
|
|
|
15155
14595
|
throw new Error(`${fieldName} must be a non-empty string`);
|
|
15156
14596
|
}
|
|
15157
14597
|
}
|
|
15158
|
-
function
|
|
14598
|
+
function addVec3(a, b) {
|
|
15159
14599
|
return [a[0] + b[0], a[1] + b[1], a[2] + b[2]];
|
|
15160
14600
|
}
|
|
15161
14601
|
|
|
@@ -15254,7 +14694,6 @@ Object.defineProperty(exports, "resetEmbodyCoreForTests", {
|
|
|
15254
14694
|
exports.AU_INFO = AU_INFO;
|
|
15255
14695
|
exports.AU_MAPPING_CONFIG = AU_MAPPING_CONFIG;
|
|
15256
14696
|
exports.AU_MIX_DEFAULTS = AU_MIX_DEFAULTS;
|
|
15257
|
-
exports.AU_MORPH_BINDING_STRIDE = AU_MORPH_BINDING_STRIDE;
|
|
15258
14697
|
exports.AU_TO_MORPHS = AU_TO_MORPHS;
|
|
15259
14698
|
exports.AnimationController = ThreeAnimationSystem;
|
|
15260
14699
|
exports.BETTA_FISH_PRESET = BETTA_FISH_PRESET;
|
|
@@ -15312,10 +14751,8 @@ exports.ThreeClipAdapter = ThreeClipAdapter;
|
|
|
15312
14751
|
exports.ThreeFrameApplier = ThreeFrameApplier;
|
|
15313
14752
|
exports.ThreeModelInspector = ThreeModelInspector;
|
|
15314
14753
|
exports.TsClipCompiler = TsClipCompiler;
|
|
15315
|
-
exports.TsRuntimeCore = TsRuntimeCore;
|
|
15316
14754
|
exports.VISEME_JAW_AMOUNTS = VISEME_JAW_AMOUNTS;
|
|
15317
14755
|
exports.VISEME_KEYS = VISEME_KEYS;
|
|
15318
|
-
exports.VISEME_MORPH_BINDING_STRIDE = VISEME_MORPH_BINDING_STRIDE;
|
|
15319
14756
|
exports.WasmRuntimeCore = WasmRuntimeCore;
|
|
15320
14757
|
exports.analyzeModel = analyzeModel;
|
|
15321
14758
|
exports.applyAUBoneBindingUpdate = applyAUBoneBindingUpdate;
|
|
@@ -15328,8 +14765,6 @@ exports.buildFrameApplierBindings = buildFrameApplierBindings;
|
|
|
15328
14765
|
exports.buildMappingEditorModel = buildMappingEditorModel;
|
|
15329
14766
|
exports.classifyAuAsJointControl = classifyAuAsJointControl;
|
|
15330
14767
|
exports.collectMorphMeshes = collectMorphMeshes2;
|
|
15331
|
-
exports.compileBoneBindings = compileBoneBindings;
|
|
15332
|
-
exports.compileMorphBindings = compileMorphBindings;
|
|
15333
14768
|
exports.compileVisemeKeys = compileVisemeKeys;
|
|
15334
14769
|
exports.composeTemplateSkeletonFitTransform = composeTemplateSkeletonFitTransform;
|
|
15335
14770
|
exports.computeCameraRelativeGazeOffset = computeCameraRelativeGazeOffset;
|