@lovelace_lol/embody 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +42 -6
- package/dist/index.js.map +1 -1
- package/dist/three/clipBindings.d.ts +5 -0
- package/dist/three.js +42 -6
- package/dist/three.js.map +1 -1
- package/dist/wasm/embody_wasm.d.ts +46 -46
- package/dist/wasm/embody_wasm_bg.wasm +0 -0
- package/dist/wasm/embody_wasm_bg.wasm.d.ts +46 -46
- package/package.json +4 -4
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { AnimationClip } from 'three';
|
|
2
2
|
import type { ClipIRTrack, ThreeModelInspection } from './index';
|
|
3
|
+
/**
|
|
4
|
+
* Packed morphs must share PropertyMixers with indexed compiled tracks. Euler
|
|
5
|
+
* components avoid Euler.fromArray's incompatible mixer-buffer offset/order.
|
|
6
|
+
*/
|
|
7
|
+
export declare function withComponentTracks(clip: AnimationClip): AnimationClip;
|
|
3
8
|
/** One PropertyMixer cache key for every concrete renderer destination. */
|
|
4
9
|
export declare function concreteTrackName(target: ClipIRTrack['target'] | undefined, inspection: ThreeModelInspection): string | undefined;
|
|
5
10
|
/** Retain authored samples and interpolants; normalize only cloned binding names. */
|
package/dist/three.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as THREE3 from 'three';
|
|
2
|
-
import { NoBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NormalBlending, Vector3, Box3, Timer, Matrix4, AnimationMixer, AdditiveAnimationBlendMode, NormalAnimationBlendMode, LoopOnce, LoopRepeat, LoopPingPong, PropertyBinding, Quaternion, AnimationUtils, InterpolateDiscrete, InterpolateLinear, MathUtils, Mesh, PlaneGeometry, ShadowMaterial, HemisphereLight, DirectionalLight, SRGBColorSpace, ACESFilmicToneMapping, WebGLRenderer, Scene, Color, PerspectiveCamera, PCFShadowMap, PCFSoftShadowMap, NumberKeyframeTrack, QuaternionKeyframeTrack, VectorKeyframeTrack, AnimationClip, PMREMGenerator, FloatType, Float32BufferAttribute,
|
|
2
|
+
import { NoBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NormalBlending, Vector3, Box3, Timer, Matrix4, AnimationMixer, AdditiveAnimationBlendMode, NormalAnimationBlendMode, LoopOnce, LoopRepeat, LoopPingPong, PropertyBinding, Euler, Quaternion, AnimationUtils, InterpolateDiscrete, InterpolateLinear, MathUtils, Mesh, PlaneGeometry, ShadowMaterial, HemisphereLight, DirectionalLight, SRGBColorSpace, ACESFilmicToneMapping, WebGLRenderer, Scene, Color, PerspectiveCamera, PCFShadowMap, PCFSoftShadowMap, NumberKeyframeTrack, QuaternionKeyframeTrack, VectorKeyframeTrack, AnimationClip, PMREMGenerator, FloatType, Float32BufferAttribute, BufferAttribute, WebGPUCoordinateSystem, WebGLCoordinateSystem } from 'three';
|
|
3
3
|
import { CC4_HUMANOID_SKELETON_TEMPLATE, HUMANOID_SKELETON_TEMPLATES, DEFAULT_HAIR_COLOR_APPEARANCE, initEmbodyCore, requireInitializedEmbodyCore } from '@lovelace_lol/embody/wasm';
|
|
4
4
|
export { CC4_HUMANOID_SKELETON_TEMPLATE, DEFAULT_AXIS_TO_CHANNEL, DEFAULT_BONE_MAX_DEGREES, DEFAULT_HAIR_COLOR_APPEARANCE, HAIR_COLOR_PRESETS, HUMANOID_SKELETON_TEMPLATES, JOINT_CONTROL_SECTION, VISEME_KEYS } from '@lovelace_lol/embody/wasm';
|
|
5
5
|
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
|
|
@@ -6732,8 +6732,30 @@ function bindModelReferencePose(model, referencePose) {
|
|
|
6732
6732
|
if (index !== referencePose.nodes.length) throw new Error("Incompatible reference pose hierarchy: extra captured nodes");
|
|
6733
6733
|
return bindings2;
|
|
6734
6734
|
}
|
|
6735
|
-
|
|
6736
|
-
|
|
6735
|
+
function withComponentTracks(clip) {
|
|
6736
|
+
let expanded = false;
|
|
6737
|
+
const tracks = clip.tracks.flatMap((track) => {
|
|
6738
|
+
const parsed = PropertyBinding.parseTrackName(track.name);
|
|
6739
|
+
const euler = parsed.propertyName === "rotation";
|
|
6740
|
+
if (!euler && !["morphTargetInfluences", "weights"].includes(parsed.propertyName) || parsed.propertyIndex !== void 0) return [track];
|
|
6741
|
+
const cubic = track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true;
|
|
6742
|
+
const parts = cubic ? 3 : 1;
|
|
6743
|
+
const width = track.getValueSize() / parts;
|
|
6744
|
+
if (!Number.isInteger(width) || width < 1 || euler && width !== 3) throw new Error(`Invalid component track ${JSON.stringify(track.name)}.`);
|
|
6745
|
+
expanded = true;
|
|
6746
|
+
return Array.from({ length: width }, (_, component) => {
|
|
6747
|
+
const scalar = track.clone();
|
|
6748
|
+
scalar.name = `${track.name}[${euler ? ["x", "y", "z"][component] : component}]`;
|
|
6749
|
+
scalar.values = track.values.slice(0, track.times.length * parts);
|
|
6750
|
+
for (let sample = 0; sample < scalar.values.length; sample += 1) scalar.values[sample] = track.values[sample * width + component];
|
|
6751
|
+
return scalar;
|
|
6752
|
+
});
|
|
6753
|
+
});
|
|
6754
|
+
if (!expanded) return clip;
|
|
6755
|
+
const indexed = clip.clone();
|
|
6756
|
+
indexed.tracks = tracks;
|
|
6757
|
+
return indexed;
|
|
6758
|
+
}
|
|
6737
6759
|
function concreteTrackName(target, inspection) {
|
|
6738
6760
|
if (!target) return void 0;
|
|
6739
6761
|
if (target.kind === "morphTarget") {
|
|
@@ -6745,6 +6767,7 @@ function concreteTrackName(target, inspection) {
|
|
|
6745
6767
|
const property = target.property ?? "rotation";
|
|
6746
6768
|
if (!object) return void 0;
|
|
6747
6769
|
if (property === "rotation" || property === "quaternion") return `${object.uuid}.quaternion`;
|
|
6770
|
+
if (property === "eulerX" || property === "eulerY" || property === "eulerZ") return `${object.uuid}.rotation[${property.slice(-1).toLowerCase()}]`;
|
|
6748
6771
|
if (property === "position" || property === "scale") return `${object.uuid}.${property}`;
|
|
6749
6772
|
}
|
|
6750
6773
|
if (target.kind === "meshVisibility") {
|
|
@@ -6855,6 +6878,7 @@ var ThreeNativePlaybackConnector = class {
|
|
|
6855
6878
|
*/
|
|
6856
6879
|
playNativeClip(clip, options = {}) {
|
|
6857
6880
|
this.beforeOperation();
|
|
6881
|
+
clip = withComponentTracks(clip);
|
|
6858
6882
|
const [ir] = serializeAnimationClips(this.binding.model, [clip], this.binding.inspection);
|
|
6859
6883
|
if (ir.tracks.length !== clip.tracks.length) {
|
|
6860
6884
|
throw new Error("Every native playback track must serialize against the bound model.");
|
|
@@ -6902,6 +6926,7 @@ var ThreeNativePlaybackConnector = class {
|
|
|
6902
6926
|
/** Edit authored samples, retaining the native action and its loop/fade progress. */
|
|
6903
6927
|
replaceClip(handle, clip) {
|
|
6904
6928
|
this.beforeOperation();
|
|
6929
|
+
clip = withComponentTracks(clip);
|
|
6905
6930
|
const resource = this.resources.get(handle);
|
|
6906
6931
|
if (!resource) throw new Error("Unknown, foreign or stale playback handle.");
|
|
6907
6932
|
const [ir] = serializeAnimationClips(this.binding.model, [clip], this.binding.inspection);
|
|
@@ -7410,10 +7435,17 @@ var Embody = class _Embody {
|
|
|
7410
7435
|
switch (parsed.propertyName) {
|
|
7411
7436
|
case "quaternion":
|
|
7412
7437
|
return Object.values(reference.transform.rotation);
|
|
7438
|
+
case "rotation": {
|
|
7439
|
+
const rotation = reference.transform.rotation;
|
|
7440
|
+
const euler = reference.rotationEuler ?? new Euler().setFromQuaternion(new Quaternion(rotation.x, rotation.y, rotation.z, rotation.w), reference.rotationOrder);
|
|
7441
|
+
const axis = parsed.propertyIndex;
|
|
7442
|
+
return axis === "x" || axis === "y" || axis === "z" ? [euler[axis]] : [euler.x, euler.y, euler.z];
|
|
7443
|
+
}
|
|
7413
7444
|
case "position":
|
|
7414
7445
|
return Object.values(reference.transform.position);
|
|
7415
7446
|
case "scale":
|
|
7416
7447
|
return Object.values(reference.transform.scale);
|
|
7448
|
+
case "weights":
|
|
7417
7449
|
case "morphTargetInfluences": {
|
|
7418
7450
|
const mesh = object;
|
|
7419
7451
|
const index = typeof parsed.propertyIndex === "string" && !/^\d+$/.test(parsed.propertyIndex) ? mesh.morphTargetDictionary?.[parsed.propertyIndex] : Number(parsed.propertyIndex);
|
|
@@ -7430,7 +7462,7 @@ var Embody = class _Embody {
|
|
|
7430
7462
|
if (!nativeSource) {
|
|
7431
7463
|
ir = this.compile(source, options);
|
|
7432
7464
|
}
|
|
7433
|
-
const clip = nativeSource ? source.clip.clone() : createAnimationClipFromClipIR(ir, this.inspection);
|
|
7465
|
+
const clip = nativeSource ? withComponentTracks(source.clip).clone() : createAnimationClipFromClipIR(ir, this.inspection);
|
|
7434
7466
|
if (ir) {
|
|
7435
7467
|
const predecessor = this.current.get(source.name);
|
|
7436
7468
|
const outgoing = predecessor?.connector.getAction(predecessor.id);
|
|
@@ -9589,6 +9621,10 @@ function createAnimationClipFromClipIR(clip, inspection) {
|
|
|
9589
9621
|
if (property === "rotation" || property === "quaternion") {
|
|
9590
9622
|
if (track.inheritStart) object.quaternion.toArray(values, 0);
|
|
9591
9623
|
tracks.push(new QuaternionKeyframeTrack(trackName, times, values, interpolation));
|
|
9624
|
+
} else if (property === "eulerX" || property === "eulerY" || property === "eulerZ") {
|
|
9625
|
+
const axis = property.slice(-1).toLowerCase();
|
|
9626
|
+
if (track.inheritStart) values[0] = object.rotation[axis];
|
|
9627
|
+
tracks.push(new NumberKeyframeTrack(trackName, times, values, interpolation));
|
|
9592
9628
|
} else if (property === "position") {
|
|
9593
9629
|
if (track.inheritStart) object.position.toArray(values, 0);
|
|
9594
9630
|
tracks.push(new VectorKeyframeTrack(trackName, times, values, interpolation));
|
|
@@ -9622,7 +9658,7 @@ function serializeAnimationClips(model, clips, inspection) {
|
|
|
9622
9658
|
channelKinds.set(kind, id);
|
|
9623
9659
|
return id;
|
|
9624
9660
|
};
|
|
9625
|
-
clip.tracks.forEach((track, index) => {
|
|
9661
|
+
withComponentTracks(clip).tracks.forEach((track, index) => {
|
|
9626
9662
|
const found = findTrackTarget(model, track);
|
|
9627
9663
|
if (!found?.object) return;
|
|
9628
9664
|
const { parsed, object } = found;
|
|
@@ -9637,7 +9673,7 @@ function serializeAnimationClips(model, clips, inspection) {
|
|
|
9637
9673
|
} else if (property === "visible" && object.isMesh) {
|
|
9638
9674
|
target = { kind: "meshVisibility", meshId: meshIds.get(object) };
|
|
9639
9675
|
} else {
|
|
9640
|
-
const transformProperty = property === "
|
|
9676
|
+
const transformProperty = property === "rotation" && ["x", "y", "z"].includes(String(parsed.propertyIndex)) ? `euler${String(parsed.propertyIndex).toUpperCase()}` : property === "quaternion" ? "rotation" : property === "position" ? "position" : property === "scale" ? "scale" : null;
|
|
9641
9677
|
if (transformProperty) {
|
|
9642
9678
|
const boneId = boneIds.get(object);
|
|
9643
9679
|
target = boneId ? { kind: "boneTransform", boneId, property: transformProperty } : { kind: "objectTransform", objectId: objectIds.get(object), property: transformProperty };
|