@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
222 lines (179 loc) • 6.18 kB
JavaScript
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;