UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

222 lines (179 loc) • 6.18 kB
import { BVH } from "../../../core/bvh2/bvh3/BVH.js"; import { SignalBinding } from "../../../core/events/signal/SignalBinding.js"; import { ResourceAccessKind } from "../../../core/model/ResourceAccessKind.js"; import { ResourceAccessSpecification } from "../../../core/model/ResourceAccessSpecification.js"; import { copy_transform_to_threejs_object } from "../../graphics/copy_transform_to_threejs_object.js"; import { rootObject3DFastMatrixUpdate } from "../../graphics/ecs/mesh/rootObject3DFastMatrixUpdate.js"; import { updateNodeByTransformAndBBB } from "../../graphics/ecs/mesh/updateNodeByTransformAndBBB.js"; import { make_bvh_visibility_builder } from "../../graphics/render/make_bvh_visibility_builder.js"; import { System } from '../System.js'; import { Transform } from '../transform/Transform.js'; import Renderable from './Renderable.js'; import { RenderableFlags } from "./RenderableFlags.js"; /** * @deprecated use {@link ShadedGeometry} instead */ class RenderSystem extends System { dependencies = [Renderable, Transform]; components_used = [ ResourceAccessSpecification.from(Renderable, ResourceAccessKind.Read | ResourceAccessKind.Write) ]; entityData = []; /** * * @type {RenderLayer|null} */ renderLayer = null; /** * * @type {BVH} */ bvh = new BVH(); /** * * @param {GraphicsEngine} graphicsEngine * @constructor */ constructor(graphicsEngine) { super(); /** * @type {GraphicsEngine} */ this.graphics = graphicsEngine; } async startup(entityManager) { this.entityManager = entityManager; this.renderLayer = this.graphics.layers.create('render-system'); this.renderLayer.buildVisibleSet = make_bvh_visibility_builder( this.entityManager, this.bvh, (destination, offset, entity, ecd) => { const component = ecd.getComponent(entity, Renderable); if (component.object === null) { return 0; } destination[offset] = component.object; return 1; } ) const visibleSet = this.renderLayer.visibleSet; visibleSet.onAdded.add(m => { /** * * @type {Renderable} */ const component = m.__meep_ecs_component; component.setFlag(RenderableFlags.InView); }); visibleSet.onRemoved.add(m => { /** * * @type {Renderable} */ const component = m.__meep_ecs_component; if (m !== component.object) { //object does not match current component mesh, skip this event return; } component.clearFlag(RenderableFlags.InView); }); } async shutdown(entityManager) { this.graphics.layers.remove(this.renderLayer); } /** * * @param {Renderable} renderable * @param {Transform} transform * @param {int} entity */ link(renderable, transform, entity) { // create back-links to ECS renderable.object.__meep_ecs_component = renderable; renderable.object.__meep_ecs_entity = entity; if (renderable.getFlag(RenderableFlags.BoundingBoxNeedsUpdate)) { // compute bounding box renderable.computeBoundsFromObject(); } function handle_transform_change() { copy_transform_to_threejs_object(renderable.object, transform); updateMeshTransform(renderable); updateNodeByTransformAndBBB(renderable.bvh, renderable.boundingBox, transform); } const position = transform.position; const scale = transform.scale; const bPosition = new SignalBinding(position.onChanged, handle_transform_change); const bRotation = new SignalBinding(transform.rotation.onChanged, handle_transform_change); const bScale = new SignalBinding(scale.onChanged, handle_transform_change); bPosition.link(); bRotation.link(); bScale.link(); this.entityData[entity] = [ bPosition, bRotation, bScale ]; handle_transform_change(); renderable.bvh.link(this.bvh, entity); } /** * * @param {Renderable} renderable * @param {Transform} transform * @param {int} entity */ unlink(renderable, transform, entity) { const list = this.entityData[entity]; for (let i = 0; i < list.length; i++) { const binding = list[i]; binding.unlink(); } delete this.entityData[entity]; renderable.bvh.unlink(); // cleanup resources renderable.dispose(); } /** * * @param {SurfacePoint3} result * @param {number} origin_x * @param {number} origin_y * @param {number} origin_z * @param {number} direction_x * @param {number} direction_y * @param {number} direction_z * @param {function(number, Renderable, EntityComponentDataset):boolean} [filter] * @param {*} [filterContext] * @returns {number} Entity ID, or -1 if no hit found */ query_geometry_raycast_nearest( result, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z, filter, filterContext ) { // TODO implement throw new Error(`Not Implemented`); } } /** * * @param {Renderable} component */ function updateMeshTransform(component) { if (!component.matrixAutoUpdate) { //don't update matrix return; } /** * * @type {THREE.Object3D} */ const m = component.object; rootObject3DFastMatrixUpdate(m); } export default RenderSystem;