189 lines
7.4 KiB
JavaScript
189 lines
7.4 KiB
JavaScript
import { Group, Vector3, Matrix4, Mesh, Quaternion, PlaneGeometry, MeshStandardMaterial, DoubleSide } from 'three';
|
|
import { InteractiveObject } from '../InteractiveObject';
|
|
|
|
class MazeObject {
|
|
constructor(engine, def, params = {}){
|
|
let room = new Group();
|
|
let root = room;
|
|
this.object = room;
|
|
let context = {};
|
|
|
|
const bbox = {l:0, r:0, f:0}
|
|
|
|
const scale = 5;
|
|
|
|
context.wallSize = params.wallSize || 1.2*scale; //half
|
|
context.tubeSize = params.tubeSize || 1.2*scale;
|
|
context.wallDepth = params.wallDepth || 0*scale;
|
|
context.fontPath = params.fontPath || '/static/fonts/Montserrat-Regular.ttf';
|
|
context.scale = scale;
|
|
|
|
this.context = context;
|
|
let _tf = {
|
|
rotation: {
|
|
r: 3 * Math.PI / 2, f: 0, l: Math.PI / 2, b: 0
|
|
},
|
|
pNext: {
|
|
r: [-context.wallSize/2, context.wallSize/2],
|
|
f: [0, context.wallSize],
|
|
l: [context.wallSize/2, context.wallSize/2]
|
|
}
|
|
};
|
|
|
|
let o = {};
|
|
|
|
function addPhysics(matrix, position, size, placement = 'side'){
|
|
let quat = new Quaternion().setFromRotationMatrix(matrix);
|
|
let v = new Vector3(...position).applyMatrix4(matrix);
|
|
let po = engine.phy.add(
|
|
{position: v}, 'fixed', false, undefined, 'cuboid',{ width: 0.01, height:1, depth:size/2 }
|
|
)
|
|
if (placement == 'front') {
|
|
quat.multiply(new Quaternion(0, 0.7071068, 0, 0.7071068)) //rotate by 90deg
|
|
}
|
|
po.rigidBody.setRotation(quat, true)
|
|
}
|
|
|
|
function addRoom(elements, def, offsetZ){
|
|
// e = [
|
|
// o.floor.clone(),
|
|
// o.door.clone(),
|
|
// o[def.r ? 'door' : 'wall'].clone(),
|
|
// o[def.f ? 'door' : 'wall'].clone(),
|
|
// o[def.l ? 'door' : 'wall'].clone()
|
|
// ];
|
|
|
|
let e = elements.map(e=>o[e].clone())
|
|
|
|
e[0].position.set(0, 0, offsetZ + context.wallSize/2);
|
|
|
|
e[1].rotateY(_tf.rotation.b);
|
|
|
|
e[2].rotateY(_tf.rotation.r);
|
|
e[3].rotateY(_tf.rotation.f);
|
|
e[4].rotateY(_tf.rotation.l);
|
|
|
|
e[1].position.set(0, 0, offsetZ + 0);
|
|
e[2].position.set(-context.wallSize/2, 0, offsetZ + context.wallSize/2);
|
|
e[3].position.set(0, 0, offsetZ + context.wallSize);
|
|
e[4].position.set(context.wallSize/2, 0, offsetZ + context.wallSize/2);
|
|
|
|
if (elements[1] == 'wall'){
|
|
addPhysics(def.matrix, [0, 0, offsetZ], context.wallSize, 'front')
|
|
}
|
|
|
|
if (elements[2] == 'wall'){
|
|
addPhysics(def.matrix, [-context.wallSize/2, 0, offsetZ + context.wallSize/2], context.wallSize)
|
|
}
|
|
|
|
if (elements[3] == 'wall'){
|
|
addPhysics(def.matrix, [0, 0, offsetZ + context.wallSize], context.wallSize, 'front')
|
|
}
|
|
|
|
if (elements[4] == 'wall'){
|
|
addPhysics(def.matrix, [context.wallSize/2, 0, offsetZ + context.wallSize/2], context.wallSize)
|
|
}
|
|
|
|
e.forEach(g => {
|
|
g.applyMatrix4(def.matrix);
|
|
root.add(g);
|
|
bbox.l = Math.min(g.position.x, bbox.l)
|
|
bbox.r = Math.max(g.position.x, bbox.r)
|
|
bbox.f = Math.max(g.position.z, bbox.f)
|
|
});
|
|
}
|
|
|
|
this.mazeObject = function(def, room, step = 0) {
|
|
if (!def.matrix){
|
|
def.matrix = new Matrix4();
|
|
}
|
|
let offsetZ = 0, e;
|
|
def.len = def.len || 0;
|
|
if (step == 0) {
|
|
// e = o.door.clone();
|
|
// e.rotateY(_tf.rotation.f);
|
|
// mazeMeshes.push(e);
|
|
addRoom(['floor', 'wall', 'wall', 'door', 'wall'], def, -context.wallSize)
|
|
}
|
|
for (let i = 0; i < def.len; i++) {
|
|
let t = o.tunnel.clone();
|
|
t.position.set(0, 0, i * context.tubeSize);
|
|
def.matrix && t.applyMatrix4(def.matrix);
|
|
root.add(t);
|
|
}
|
|
offsetZ = def.len * context.tubeSize;
|
|
//if (!def.len) offsetZ = -.275;
|
|
//room.getWorldQuaternion(quat);
|
|
// const geometry = new BoxGeometry(2, 2, offsetZ);
|
|
// const cube = new Mesh(geometry, o.tunnel.material)
|
|
// cube.position.set(context.tubeSize / 2, 0.6, offsetZ/2)
|
|
// root.add(cube);
|
|
|
|
// console.log(offsetZ, room.localToWorld(new Vector3(context.tubeSize / 2, 0.6, offsetZ/2)))
|
|
|
|
addPhysics(def.matrix, [context.tubeSize / 2, 0.6, offsetZ/2], offsetZ)
|
|
addPhysics(def.matrix, [-context.tubeSize / 2, 0.6, offsetZ/2], offsetZ)
|
|
|
|
addRoom(['floor', 'door', def.r ? 'door' : 'wall', def.f ? 'door' : 'wall', def.l ? 'door' : 'wall'], def, offsetZ)
|
|
|
|
console.log('loadingggg', def.objects)
|
|
def.objects?.forEach(async obj => {
|
|
obj.room = room;
|
|
// let go = new GameObject(obj, context);
|
|
let go = new InteractiveObject(obj, context)
|
|
await go.ready;
|
|
go.object.scale.multiplyScalar(context.wallSize)
|
|
go.object.position.multiplyScalar(context.wallSize)
|
|
go.object.applyMatrix4(def.matrix);
|
|
root.add(go.object);
|
|
// go.ready.then(mesh => {
|
|
// room.add(mesh);
|
|
// });
|
|
});
|
|
|
|
def.room = room;
|
|
['r', 'f', 'l'].forEach((d, i) => {
|
|
if (!def[d]) return;
|
|
let mtx = new Matrix4();
|
|
mtx.makeRotationY(_tf.rotation[d]);
|
|
mtx.setPosition(_tf.pNext[d][0], 0, _tf.pNext[d][1] + offsetZ);
|
|
let rr = new Group();
|
|
root.add(rr);
|
|
def[d].matrix = mtx.premultiply(def.matrix);
|
|
rr.applyMatrix4(def[d].matrix);
|
|
rr.updateMatrixWorld();
|
|
this.mazeObject(def[d], rr, step + 1);
|
|
});
|
|
};
|
|
|
|
this.load = async function(){
|
|
let mazeAsset = await engine.load('/static/meshes/quiz.gltf');
|
|
['tunnel', 'wall', 'door', 'floor'].forEach(e => {
|
|
o[e] = mazeAsset.scene.getObjectByName(e);
|
|
//o[e].frustumCulled = false;
|
|
o[e].scale.set(scale, scale, scale)
|
|
// o[e].geometry.computeBoundingBox();
|
|
// console.log(e, o[e].geometry.boundingBox)
|
|
});
|
|
this.mazeObject(def, room);
|
|
// mazeMeshes.forEach(mesh=>{
|
|
// //let mesh = new Mesh(mg, o.tunnel.material)
|
|
// root.add(mesh);
|
|
// //engine.phy.add(mesh, 'fixed')
|
|
// })
|
|
|
|
console.log(bbox, 'bbox')
|
|
const floorGeometry = new PlaneGeometry(bbox.r - bbox.l + 10*scale, bbox.f + 10*scale);
|
|
const floor = new Mesh(floorGeometry,new MeshStandardMaterial({
|
|
roughness: 0, metalness:1, color: 0x00ffff, side: DoubleSide
|
|
}))
|
|
floor.rotation.set(Math.PI/2, 0, 0)
|
|
floor.position.set((bbox.l + bbox.r)/2, 0.3, bbox.f/2);
|
|
root.add(floor);
|
|
//scene.add(new Mesh(BufferGeometryUtils.mergeGeometries(mazeGeometries, false), o.tunnel.material));
|
|
//console.log(room);
|
|
}
|
|
}
|
|
}
|
|
|
|
export { MazeObject } |