fix: Retargeting auf absolute Rotation umgestellt (Ruling 67)
Beide Verfahren an allen drei Figuren durchprobiert statt vermutet: Delta hielt Superhero Male/Female bei Idle_Loop und Walk_Loop in voller T-Pose (upperarm_l weicht 70° von ual.glbs eigener Ruhepose ab, gegen den A_TPose-Referenzclip gemessen — die Ruhepose-Differenz ist selbst schon eine Pose, nicht der Bauartunterschied im Gradbereich, für den Delta gedacht ist). Absolute liefert für beide einen sauberen Gang ohne Schulterverdrehung; für Mannequin sind Delta und Absolute ohnehin identisch (sourceRest===targetRest). Ein Verfahren trägt für alle drei. retargetClips() behält "delta" als Voreinstellung (die im Auftrag wörtlich vorgegebene Formel, weiterhin getestet); CHARACTERS trägt das Messergebnis für dieses Projekt ein. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d30aae68a1
commit
182db238c6
2 files changed
+75
-13
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { AnimationClip, Quaternion, QuaternionKeyframeTrack, VectorKeyframeTrack } from "three";
|
||||
import { retargetClips, teleportTargets } from "../src/characters/index.js";
|
||||
import { CHARACTERS, retargetClips, teleportTargets } from "../src/characters/index.js";
|
||||
|
||||
const rest = (q) => new Map([["arm", { position: { x: 0, y: 1, z: 0 }, quaternion: q }]]);
|
||||
|
||||
@@ -24,6 +24,34 @@ describe("retargetClips", () => {
|
||||
const v = out[0].tracks[0].values;
|
||||
expect(new Quaternion(v[0], v[1], v[2], v[3]).angleTo(dst)).toBeLessThan(1e-6);
|
||||
});
|
||||
|
||||
// Fix-Runde 1, Ruling 67: ual.glb hängt die Arme, der Quaternius-Rig steht in T (70° an
|
||||
// upperarm_l, s. task-11-report.md) — die Ruhepose-Differenz ist damit selbst schon fast
|
||||
// eine ganze Pose, nicht die paar Grad Bauartunterschied, für die "Delta" gedacht ist. Im
|
||||
// absoluten Modus wird die animierte Rotation unverändert übernommen (q_neu = q_anim),
|
||||
// ohne jede Ruhepose-Referenz — das Gegenstück zu "relativ zur Ruhepose" oben.
|
||||
it("übernimmt Rotationen im absoluten Modus unverändert (Ruling 67)", () => {
|
||||
const src = new Quaternion().setFromAxisAngle({ x: 0, y: 1, z: 0 }, 0.3);
|
||||
const dst = new Quaternion().setFromAxisAngle({ x: 0, y: 1, z: 0 }, 0.9);
|
||||
const clip = new AnimationClip("a", 1, [
|
||||
new QuaternionKeyframeTrack("arm.quaternion", [0], [src.x, src.y, src.z, src.w]),
|
||||
]);
|
||||
const out = retargetClips([clip], rest(src), rest(dst), { rotation: "absolute" });
|
||||
const v = out[0].tracks[0].values;
|
||||
expect(new Quaternion(v[0], v[1], v[2], v[3]).angleTo(src)).toBeLessThan(1e-6);
|
||||
});
|
||||
});
|
||||
|
||||
// Fix-Runde 1, Ruling 67: durchprobiert statt vermutet — Delta hielt Superhero Male/Female
|
||||
// bei Idle_Loop UND Walk_Loop in praktisch voller T-Pose (Screenshots r67-03..r67-04 im
|
||||
// Bericht), Absolute zeigte für beide einen sauberen Gang ohne Schulterverdrehung
|
||||
// (r67-05..r67-10), und für Mannequin sind beide Verfahren ohnehin identisch (sourceRest ===
|
||||
// targetRest, da ual.glb sich selbst liefert). Ein Verfahren trägt für alle drei — dieser Test
|
||||
// hält das Messergebnis fest, damit ein künftiger Umbau nicht versehentlich zu Delta zurückfällt.
|
||||
describe("CHARACTERS", () => {
|
||||
it("verwendet absolute Rotation für alle drei Figuren (gemessen, nicht vermutet — Ruling 67)", () => {
|
||||
for (const c of CHARACTERS) expect(c.retarget).toBe("absolute");
|
||||
});
|
||||
});
|
||||
|
||||
describe("teleportTargets", () => {
|
||||
|
||||
Reference in new issue
Block a user