41 lines
1.7 KiB
TypeScript
41 lines
1.7 KiB
TypeScript
import { NodeIO } from "@gltf-transform/core";
|
|
import { BufferAttribute, BufferGeometry } from "three";
|
|
import { describe, expect, it } from "vitest";
|
|
import {
|
|
buildPartyNavigationGraph,
|
|
findNearestPartyNavigationSurface,
|
|
findPartyNavigationPath,
|
|
} from "./partyNavigation";
|
|
|
|
const PASPERS_ENTRANCE = [-0.181739, 0.349067, -11.472769] as const;
|
|
const BLACKHORN_NISORN = [80.518555, 0.448065, -115.173169] as const;
|
|
|
|
describe("shipping Pasper's Shrine party navigation", () => {
|
|
it("routes from the entrance to the first source-authored boss", async () => {
|
|
const document = await new NodeIO().read(
|
|
"src/assets/game/dungeons/paspers-shrine/paspers-shrine-navigation.glb",
|
|
);
|
|
const primitive = document.getRoot().listMeshes()[0]?.listPrimitives()[0];
|
|
const positions = primitive?.getAttribute("POSITION")?.getArray();
|
|
const indices = primitive?.getIndices()?.getArray();
|
|
if (!positions || !indices) throw new Error("Pasper navigation asset is not indexed.");
|
|
|
|
const geometry = new BufferGeometry();
|
|
geometry.setAttribute("position", new BufferAttribute(new Float32Array(positions), 3));
|
|
geometry.setIndex(new BufferAttribute(new Uint32Array(indices), 1));
|
|
const graph = buildPartyNavigationGraph(geometry);
|
|
const approach = findNearestPartyNavigationSurface(graph, BLACKHORN_NISORN, 6);
|
|
expect(approach?.distance).toBeGreaterThan(5);
|
|
expect(approach?.distance).toBeLessThan(6);
|
|
const route = findPartyNavigationPath(graph, PASPERS_ENTRANCE, approach!.position, {
|
|
maxStartSnapDistance: 3,
|
|
maxEndSnapDistance: 5,
|
|
simplifyTolerance: 0.01,
|
|
});
|
|
geometry.dispose();
|
|
|
|
expect(route).not.toBeNull();
|
|
expect(route!.length).toBeGreaterThan(1);
|
|
});
|
|
});
|