@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
106 lines (75 loc) • 2.74 kB
JavaScript
import { BufferGeometry, Float32BufferAttribute, Group, Line, LineBasicMaterial } from "three";
import Vector3 from "../../../src/core/geom/Vector3.js";
import { min2 } from "../../../src/core/math/min2.js";
import Renderable from "../../../src/engine/ecs/renderable/Renderable.js";
import { buildThreeJSHelperEntity } from "./buildThreeJSHelperEntity.js";
import { make3DSymbolicDisplay } from "./make3DSymbolicDisplay.js";
import Path from "../../../src/engine/navigation/ecs/components/Path.js";
/**
*
* @return {ComponentSymbolicDisplay}
* @param {Engine} engine
*/
export function makePathSymbolicDisplay(engine) {
/**
*
* @param {Path} path
* @param {number} q
* @returns {BufferGeometry}
*/
function buildPathGeometry(path, q) {
const geometry = new BufferGeometry();
const vertices = [];
const v3 = new Vector3();
const length = path.computeLength();
const minStep = (length / path.getPointCount()) / 10;
const step = min2(q, minStep);
const p = path;
let i = 0;
for (let c = 0; c < length; c += step) {
p.sample(v3, c);
vertices[i++] = v3.x;
vertices[i++] = v3.y;
vertices[i++] = v3.z;
}
geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
return geometry;
}
/**
*
* @param {Path} path
* @param entity
* @param {SymbolicDisplayInternalAPI} api
* @return {Entity}
*/
function factory([path, entity], api) {
const pathObjectMaterial = new LineBasicMaterial({ color: 0xFF0000, opacity: 0.4 });
pathObjectMaterial.depthTest = false;
const q = 0.01;
const pathObject = new Line(buildPathGeometry(path, q), pathObjectMaterial);
pathObject.castShadow = true;
function update() {
pathObject.geometry = buildPathGeometry(path, q);
b.getComponent(Renderable).computeBoundsFromObject();
}
for (let i = 0; i < path.getPointCount(); i++) {
const p = new Vector3();
path.getPosition(i, p);
api.bind(p.onChanged, () => {
update();
});
}
const group = new Group();
group.frustumCulled = false;
group.add(pathObject);
const b = buildThreeJSHelperEntity(group);
const r = b.getComponent(Renderable);
r.matrixAutoUpdate = false;
api.emit(b);
}
return make3DSymbolicDisplay({
engine,
components: [Path],
factory
})
}