@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
138 lines (103 loc) • 3.83 kB
JavaScript
import { Mesh, SkinnedMesh } from "three";
import { returnTrue } from "../../../../core/function/returnTrue.js";
const stack = [];
export class ThreeBypassRenderer {
constructor() {
/**
*
* @type {WeakMap<THREE.Object3D, THREE.Object3D>}
* @private
*/
this.__object_map = new WeakMap();
}
/**
*
* @param {Mesh|SkinnedMesh} source
* @return {Mesh|SkinnedMesh}
* @private
*/
__get_object_twin(source) {
const existing = this.__object_map.get(source);
if (existing !== undefined) {
return existing;
}
let mesh;
const geometry = source.geometry;
if (source.isSkinnedMesh) {
mesh = new SkinnedMesh(geometry, null);
} else {
mesh = new Mesh(geometry, null);
}
mesh.matrixAutoUpdate = false;
mesh.matrixWorldNeedsUpdate = false;
mesh.frustumCulled = false;
this.__object_map.set(source, mesh);
return mesh;
}
/**
*
* @param {THREE.Object3D} scene
* @param {THREE.Object3D[]} input
* @param {number} input_size
* @param {function(THREE.Object3D):boolean} input_filter
* @param {function(THREE.Object3D):boolean} object_filter
* @param {function(THREE.Object3D):THREE.Material} material_extractor
* @param {*} [material_extractor_context]
*/
build_scene({
scene,
input,
input_size,
input_filter = returnTrue,
object_filter,
material_extractor,
material_extractor_context
}) {
// prepare shadow scene
const scene_children = scene.children;
scene_children.length = 0;
let stack_top = 0;
let j = 0;
let i = 0;
for (; i < input_size; i++) {
const object3D = input[i];
if (input_filter(object3D)) {
stack[stack_top++] = object3D;
}
}
while (stack_top > 0) {
const object3D = stack[--stack_top];
if (
object_filter(object3D)
) {
if (object3D.isMesh) {
const geometry = object3D.geometry;
if (geometry !== null) {
const mesh = this.__get_object_twin(object3D);
const material = material_extractor.call(material_extractor_context, object3D);
mesh.geometry = geometry;
mesh.material = material;
if (object3D.isSkinnedMesh) {
mesh.bindMatrix.copy(object3D.bindMatrix);
mesh.bindMatrixInverse.copy(object3D.bindMatrixInverse);
mesh.skeleton = object3D.skeleton;
}
mesh.matrix.copy(object3D.matrix);
mesh.matrixWorld.copy(object3D.matrixWorld);
mesh.normalMatrix.copy(object3D.normalMatrix);
scene_children[j++] = mesh;
mesh.parent = scene;
}
}
}
const children = object3D.children;
const child_count = children.length;
for (i = 0; i < child_count; i++) {
const child = children[i];
stack[stack_top++] = child;
}
}
scene_children.length = j;
}
}
ThreeBypassRenderer.INSTANCE = new ThreeBypassRenderer();