Task 11: Figuren (Mannequin/Superhero Male/Female) mit auf ual.glb retargeteten Animationen, Frisuren, vier SUVs auf angehefteten Chunks, ein lil-gui-Debug-Panel (Figur/Frisur/Höhe/Hitbox/Chunk-Grenzen/ Kartenbild/Nebel/Wahrzeichen-Sprung) und die verpflichtende Namensnennung fürs HUD (Kartenkacheln, Wahrzeichen, SUV, Texturen, Palme, Figuren — jede Quelle mit ihrer eigenen Lizenz). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
39 lines
1.7 KiB
JavaScript
39 lines
1.7 KiB
JavaScript
import { describe, expect, it } from "vitest";
|
|
import { AnimationClip, Quaternion, QuaternionKeyframeTrack, VectorKeyframeTrack } from "three";
|
|
import { retargetClips, teleportTargets } from "../src/characters/index.js";
|
|
|
|
const rest = (q) => new Map([["arm", { position: { x: 0, y: 1, z: 0 }, quaternion: q }]]);
|
|
|
|
describe("retargetClips", () => {
|
|
it("wirft konstante Positionsspuren weg", () => {
|
|
const clip = new AnimationClip("a", 1, [
|
|
new VectorKeyframeTrack("arm.position", [0, 1], [0, 1, 0, 0, 1, 0]),
|
|
new QuaternionKeyframeTrack("arm.quaternion", [0], [0, 0, 0, 1]),
|
|
]);
|
|
const out = retargetClips([clip], rest(new Quaternion()), rest(new Quaternion()));
|
|
expect(out[0].tracks.map((t) => t.name)).toEqual(["arm.quaternion"]);
|
|
});
|
|
|
|
it("überträgt Rotationen relativ zur Ruhepose", () => {
|
|
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));
|
|
const v = out[0].tracks[0].values;
|
|
expect(new Quaternion(v[0], v[1], v[2], v[3]).angleTo(dst)).toBeLessThan(1e-6);
|
|
});
|
|
});
|
|
|
|
describe("teleportTargets", () => {
|
|
it("sortiert Wahrzeichen nach Höhe", () => {
|
|
const targets = teleportTargets([
|
|
{ name: "klein", xyz: [0, 0, 0], height: 30 },
|
|
{ name: "groß", xyz: [10, 20, 0], height: 200 },
|
|
]);
|
|
expect(targets[0].name).toBe("groß");
|
|
expect(targets[0].z).toBe(-20);
|
|
});
|
|
});
|