UNPKG

react-planner

Version:

react-planner is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.

289 lines (227 loc) 8.42 kB
import * as Three from 'three'; import React from 'react'; const WIDTH = 80; const DEPTH = 80; const HEIGHT = 180; const textureLoader = new Three.TextureLoader(); const logoTexture = textureLoader.load(require('./logo.jpg')); const steelTexture = textureLoader.load(require('./steel.jpg')); const logoMaterial = new Three.MeshLambertMaterial({map:logoTexture}); const steel = new Three.MeshLambertMaterial({map:steelTexture}); const objectMaxLOD = makeObjectMaxLOD(); const objectMinLOD = makeObjectMinLOD(); function makeObjectMaxLOD() { let fridge = new Three.Mesh(); //base let base = new Three.Mesh(new Three.BoxGeometry(1,0.05,1), steel); base.position.set(0,0.15,0); fridge.add(base); //foot for(let gx=-0.45;gx<=0.45;gx+=0.9){ for(let gz=-0.45;gz<=0.45;gz+=0.9){ let foot = new Three.Mesh(new Three.CylinderGeometry(0.05, 0.05, 0.05, 4), steel); foot.position.set(gx,-0.05,gz); foot.rotation.y=0.25*Math.PI; base.add(foot) } } //back let back = new Three.Mesh(new Three.BoxGeometry(0.05,1.8,1), steel); back.position.set(0.475,0.925,0); base.add(back); //side let side1 = new Three.Mesh(new Three.BoxGeometry(1,1.8,0.05), steel); side1.position.set(0,0.925,0.475); base.add(side1); let side2 = new Three.Mesh(new Three.BoxGeometry(1,1.8,0.05), steel); side2.position.set(0,0.925,-0.475); base.add(side2); //top let top = new Three.Mesh(new Three.BoxGeometry(1,0.20,1), steel); top.position.set(0,1.85,0); base.add(top); //logo let logo = new Three.Mesh(new Three.PlaneGeometry(0.2,0.1),logoMaterial); logo.position.set(-0.51,1.85,0); logo.rotation.y=-0.5*Math.PI; base.add(logo); //up door let door1 = new Three.Mesh(new Three.BoxGeometry(0.05,0.9,0.95), steel); door1.position.set(-0.5,1.30,0); base.add(door1); //down door let door2 = new Three.Mesh(new Three.BoxGeometry(0.05,0.8,0.95), steel); door2.position.set(-0.5,0.425,0); base.add(door2); //middle plane let middlePlane = new Three.Mesh(new Three.BoxGeometry(1,0.05,1), steel); middlePlane.position.set(0,0.845,0); base.add(middlePlane); //handle let handle1_p1 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.8),steel); handle1_p1.position.set(-0.56,1.30,-0.4); base.add(handle1_p1); let handle1_p2 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.06),steel); handle1_p2.position.set(-0.53,1.60,-0.4); handle1_p2.rotation.z=0.5*Math.PI; base.add(handle1_p2); let handle1_p3 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.06),steel); handle1_p3.position.set(-0.53,1,-0.4); handle1_p3.rotation.z=0.5*Math.PI; base.add(handle1_p3); //handle let handle2_p1 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.7),steel); handle2_p1.position.set(-0.56,0.425,-0.4); base.add(handle2_p1); let handle2_p2 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.06),steel); handle2_p2.position.set(-0.53,0.7,-0.4); handle2_p2.rotation.z=0.5*Math.PI; base.add(handle2_p2); let handle2_p3 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.06),steel); handle2_p3.position.set(-0.53,0.15,-0.4); handle2_p3.rotation.z=0.5*Math.PI; base.add(handle2_p3); return fridge } function makeObjectMinLOD() { let fridge = new Three.Mesh(); //base let base = new Three.Mesh(new Three.BoxGeometry(1,0.05,1), steel); base.position.set(0,0.15,0); fridge.add(base); //foot for(let gx=-0.45;gx<=0.45;gx+=0.9){ for(let gz=-0.45;gz<=0.45;gz+=0.9){ let foot = new Three.Mesh(new Three.CylinderGeometry(0.05, 0.05, 0.05, 4), steel); foot.position.set(gx,-0.05,gz); foot.rotation.y=0.25*Math.PI; base.add(foot) } } //back let back = new Three.Mesh(new Three.BoxGeometry(0.05,1.8,1), steel); back.position.set(0.475,0.925,0); base.add(back); //side let side1 = new Three.Mesh(new Three.BoxGeometry(1,1.8,0.05), steel); side1.position.set(0,0.925,0.475); base.add(side1); let side2 = new Three.Mesh(new Three.BoxGeometry(1,1.8,0.05), steel); side2.position.set(0,0.925,-0.475); base.add(side2); //top let top = new Three.Mesh(new Three.BoxGeometry(1,0.20,1), steel); top.position.set(0,1.85,0); base.add(top); //logo let logo = new Three.Mesh(new Three.PlaneGeometry(0.2,0.1),logoMaterial); logo.position.set(-0.51,1.85,0); logo.rotation.y=-0.5*Math.PI; base.add(logo); //up door let door1 = new Three.Mesh(new Three.BoxGeometry(0.05,0.9,0.95), steel); door1.position.set(-0.5,1.30,0); base.add(door1); //down door let door2 = new Three.Mesh(new Three.BoxGeometry(0.05,0.8,0.95), steel); door2.position.set(-0.5,0.425,0); base.add(door2); //middle plane let middlePlane = new Three.Mesh(new Three.BoxGeometry(1,0.05,1), steel); middlePlane.position.set(0,0.845,0); base.add(middlePlane); //handle let handle1_p1 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.8),steel); handle1_p1.position.set(-0.56,1.30,-0.4); base.add(handle1_p1); let handle1_p2 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.06),steel); handle1_p2.position.set(-0.53,1.60,-0.4); handle1_p2.rotation.z=0.5*Math.PI; base.add(handle1_p2); let handle1_p3 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.06),steel); handle1_p3.position.set(-0.53,1,-0.4); handle1_p3.rotation.z=0.5*Math.PI; base.add(handle1_p3); //handle let handle2_p1 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.7),steel); handle2_p1.position.set(-0.56,0.425,-0.4); base.add(handle2_p1); let handle2_p2 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.06),steel); handle2_p2.position.set(-0.53,0.7,-0.4); handle2_p2.rotation.z=0.5*Math.PI; base.add(handle2_p2); let handle2_p3 = new Three.Mesh(new Three.CylinderGeometry(0.02,0.02,0.06),steel); handle2_p3.position.set(-0.53,0.15,-0.4); handle2_p3.rotation.z=0.5*Math.PI; base.add(handle2_p3); return fridge } export default { name: "fridge", prototype: "items", info: { tag: ['furnishings', 'metal'], title: "fridge", description: "fridge", image: require('./fridge.png') }, properties: { altitude: { label: "altitude", type: "length-measure", defaultValue: { length: 0, unit: 'cm' } } }, render2D: function (element, layer, scene) { let angle = element.rotation + 90; let textRotation = 0; if (Math.sin(angle * Math.PI / 180) < 0) { textRotation = 180; } return ( <g transform={`translate(${-WIDTH / 2},${-DEPTH / 2})`}> <rect key="1" x="0" y="0" width={WIDTH} height={DEPTH} style={{stroke: element.selected ? '#0096fd' : '#000', strokeWidth: "2px", fill: "#84e1ce"}}/> <text key="2" x="0" y="0" transform={`translate(${WIDTH / 2}, ${DEPTH / 2}) scale(1,-1) rotate(${textRotation})`} style={{textAnchor: "middle", fontSize: "11px"}}> {element.type} </text> </g> ) }, render3D: function (element, layer, scene) { let newAltitude = element.properties.get('altitude').get('length'); /**************** lod max *******************/ let fridgeMaxLOD = new Three.Object3D(); fridgeMaxLOD.add(objectMaxLOD.clone()); let valuePosition = new Three.Box3().setFromObject(fridgeMaxLOD); let deltaX = Math.abs(valuePosition.max.x - valuePosition.min.x); let deltaY = Math.abs(valuePosition.max.y - valuePosition.min.y); let deltaZ = Math.abs(valuePosition.max.z - valuePosition.min.z); fridgeMaxLOD.position.y += newAltitude; fridgeMaxLOD.scale.set(WIDTH / deltaX, HEIGHT / deltaY, DEPTH / deltaZ); /**************** lod min *******************/ let fridgeMinLOD = new Three.Object3D(); fridgeMinLOD.add(objectMinLOD.clone()); fridgeMinLOD.position.y += newAltitude; fridgeMinLOD.scale.set(WIDTH / deltaX, HEIGHT / deltaY, DEPTH / deltaZ); /**** all level of detail ***/ let lod = new Three.LOD(); lod.addLevel(fridgeMaxLOD, 200); lod.addLevel(fridgeMinLOD, 900); lod.updateMatrix(); lod.matrixAutoUpdate = false; if (element.selected) { let bbox = new Three.BoxHelper(lod, 0x99c3fb); bbox.material.linewidth = 5; bbox.renderOrder = 1000; bbox.material.depthTest = false; lod.add(bbox); } return Promise.resolve(lod); } };