UNPKG

@soonspacejs/plugin-pathfinding

Version:

Pathfinding plugin for SoonSpace.js

100 lines (99 loc) 4.25 kB
import { Matrix4 as u, Mesh as p, InstancedMesh as l, MeshStandardMaterial as w } from "three"; import { Crowd as m } from "@recast-navigation/core"; import { generateSoloNavMesh as v, generateTiledNavMesh as f } from "@recast-navigation/generators"; import { DebugDrawer as g, CrowdHelper as M } from "@recast-navigation/three"; import b from "soonspacejs"; import { StaticGeometryGenerator as D } from "three-mesh-bvh"; function H(o) { const e = o.name, i = o.geometry, n = o.material, a = o.count, r = []; for (let h = 0; h < a; h++) { const s = new u(); o.getMatrixAt(h, s); const d = new p(i, n); d.name = `${e}_${h}`, r.push(d), s.premultiply(o.matrixWorld), d.matrix.copy(s), d.matrixWorld.copy(s), s.decompose(d.position, d.quaternion, d.scale); } return r; } function c(o) { const e = []; o.forEach((h) => { h.traverse((s) => { s instanceof p && s.geometry.index && (s instanceof l ? e.push(...H(s)) : e.push(s)); }); }); const i = new D(e); i.applyWorldTransforms = !0, i.attributes = ["position", "index"]; const n = i.generate(), a = n.attributes.position.array, r = n.index && n.index.array; return { positions: a, indices: r }; } const { warn: t } = b.utils; class G { constructor(e) { this.ssp = e; } navMesh = null; crowd = null; debugDrawer = null; crowdHelper = null; // solo navmesh createSoloNavMesh(e, i = {}) { if (this.navMesh) return t("navmesh 已经存在,请先调用 disposeNavMesh()"), this.navMesh; const { positions: n, indices: a } = c(e); if (!a) return t("生成 navmesh 失败,几何体不包含索引信息"), null; const r = v(n, a, i); return r.success ? (this.navMesh = r.navMesh, this.navMesh) : null; } // create tiled navmesh createTiledNavMesh(e, i = {}) { if (this.navMesh) return t("navmesh 已经存在,请先调用 disposeNavMesh()"), this.navMesh; const { positions: n, indices: a } = c(e); if (!a) return t("生成 navmesh 失败,几何体不包含索引信息"), null; const r = f(n, a, i); return r.success ? (this.navMesh = r.navMesh, this.navMesh) : null; } /** * @deprecated use disposeNavMesh() instead */ disposeSoloNavMesh() { this.disposeNavMesh(); } disposeNavMesh() { this.navMesh?.destroy(), this.navMesh = null; } // crowd _crowdUpdate = () => { this.crowd && (this.crowd.update(this.ssp.viewport.state.delta), this.crowdHelper?.update(), this.crowd.getActiveAgentCount() > 0 && this.ssp.render()); }; createCrowd(e) { return this.crowd ? (t("crowd 已经存在,请先调用 disposeCrowd()"), this.crowd) : this.navMesh ? (this.crowd = new m(this.navMesh, e), this.ssp.signals.beforeRender.add(this._crowdUpdate), this.crowd) : (t("navmesh 不存在,请先调用 createSoloNavMesh()"), null); } disposeCrowd() { this.crowd?.destroy(), this.crowd = null, this.ssp.signals.beforeRender.remove(this._crowdUpdate); } createDebugDrawer() { return this.debugDrawer ? (t("debug drawer 已经存在,请先调用 disposeDebugDrawer()"), this.debugDrawer) : this.navMesh ? (this.debugDrawer = new g(), this.debugDrawer.drawNavMesh(this.navMesh, 0), this.ssp.addObject(this.debugDrawer), this.debugDrawer) : (t("navmesh 不存在,请先调用 createSoloNavMesh()"), null); } disposeDebugDrawer() { this.debugDrawer && (this.debugDrawer.dispose(), this.ssp.removeObject(this.debugDrawer), this.debugDrawer = null); } createCrowdHelper(e = { agentMaterial: new w({ color: 65280 }) }) { return this.crowdHelper ? (t("crowd helper 已经存在,请先调用 disposeCrowdHelper()"), this.crowdHelper) : this.crowd ? (this.crowdHelper = new M(this.crowd, e), this.ssp.addObject(this.crowdHelper), this.crowdHelper) : (t("crowd 不存在,请先调用 createCrowd()"), null); } disposeCrowdHelper() { this.crowdHelper && (this.crowdHelper.agentMeshes.forEach((e) => { e.geometry.dispose(), e.material.dispose(); }), this.ssp.removeObject(this.crowdHelper)); } dispose() { this.disposeNavMesh(), this.disposeCrowd(), this.disposeDebugDrawer(), this.disposeCrowdHelper(); } } export { H as deInstancingMesh, G as default, c as getVertices };