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 }