UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

150 lines (111 loc) 3.96 kB
import Vector3 from "../../../../../core/geom/Vector3.js"; import Entity from "../../../../ecs/Entity.js"; import { EventType } from "../../../../ecs/EventType.js"; import Renderable from "../../../../ecs/renderable/Renderable.js"; import { RenderableFlags } from "../../../../ecs/renderable/RenderableFlags.js"; import { Transform } from "../../../../ecs/transform/Transform.js"; import ThreeFactory from "../../../three/ThreeFactory.js"; import { RIBBON_ATTRIBUTE_ADDRESS_AGE, RIBBON_ATTRIBUTE_ADDRESS_UV_OFFSET } from "../../../trail/x/ribbon_attributes_spec.js"; import { RibbonX } from "../../../trail/x/RibbonX.js"; export class RibbonPathBuilder { constructor() { /** * * @type {RibbonPathStyle|null} */ this.style = null; /** * * @type {Path|null} */ this.path = null; /** * * @type {RibbonXPlugin|null} */ this.plugin = null; } /** * * @param {RibbonPathStyle} style */ setStyle(style) { this.style = style; } /** * * @param {Path} path */ setPath(path) { this.path = path; } /** * * @param {RibbonXPlugin} plugin */ setPlugin(plugin) { this.plugin = plugin; } /** * * @param {Entity[]} destination */ build(destination) { const path = this.path; const pointCount = path.getPointCount(); /** * * @type {RibbonPathStyle|null} */ const style = this.style; const ribbon_count_count = pointCount * style.resolution; const ribbon = new RibbonX(); ribbon.buildGeometry(); ribbon.setCount(ribbon_count_count); const v3 = new Vector3(); const path_total_length = path.computeLength(); for (let i = 0; i < ribbon_count_count; i++) { const f = i / (ribbon_count_count - 1); path.sample(v3, f * path_total_length); ribbon.setPointColor(i, 255, 255, 255); ribbon.setPointPosition(i, v3.x, v3.y, v3.z); ribbon.setPointThickness(i, style.thickness); ribbon.setPointAttribute_Scalar(i, RIBBON_ATTRIBUTE_ADDRESS_UV_OFFSET, f); ribbon.setPointAlpha(i, 0.5); ribbon.setPointAttribute_Scalar(i, RIBBON_ATTRIBUTE_ADDRESS_AGE, 0); } if (pointCount > 0) { // write first position again to ensure all segments have correct direction path.sample(v3, 0); ribbon.setPointPosition(0, v3.x, v3.y, v3.z); } const plugin = this.plugin; const engine = plugin.engine; const graphics = engine.graphics; const geometry = ribbon.getGeometry(); const material = plugin.obtain_material_x(style.material); const mesh = ThreeFactory.createMesh(geometry, material); const renderable = new Renderable(mesh); renderable.clearFlag(RenderableFlags.BoundingBoxNeedsUpdate); ribbon.computeBoundingBox(renderable.boundingBox); const entityBuilder = new Entity() .add(renderable) .add(new Transform()); function setResolution() { material.uniforms.resolution.value.copy(graphics.viewport.size); } function handleEntityRemoved() { graphics.viewport.size.onChanged.remove(setResolution); } entityBuilder.on.built.add(() => { // set resolution setResolution(); graphics.viewport.size.onChanged.add(setResolution); entityBuilder.addEventListener(EventType.EntityRemoved, handleEntityRemoved); }); destination.push(entityBuilder); } }