UNPKG

react-planner

Version:

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

272 lines (204 loc) 7.24 kB
import * as Three from 'three'; import React from 'react'; const WIDTH = 50; const DEPTH = 50; const HEIGHT = 180; const blackMaterial = new Three.MeshLambertMaterial({color: 0x4B4B4B}); const greyMaterial = new Three.MeshLambertMaterial({color: 0xC0C0C0}); const blueMaterial = new Three.MeshLambertMaterial({color: 0x3399FF, transparent: true, opacity: 0.8}); const objectMaxLOD = makeObjectMaxLOD(); const objectMinLOD = makeObjectMinLOD(); function makeObjectMaxLOD() { let hanger = new Three.Mesh(); //base let base_geom = new Three.CylinderGeometry(0.09, 0.25, 0.08, 20, 2, true); blackMaterial.side = Three.DoubleSide; let base = new Three.Mesh(base_geom, blackMaterial); base.position.set(0, 0.04, 0); let base2_geom = new Three.CylinderGeometry(0.09, 0.01, 0.03, 20, 2, true); let base2 = new Three.Mesh(base2_geom, blackMaterial); base2.position.set(0, 0.015+0.05, 0); //central body let body_geom = new Three.CylinderGeometry(0.03, 0.03, 2, 32, 32); let body = new Three.Mesh(body_geom, greyMaterial); body.position.set(0, 1, 0); //umbrella base let g_umbrella_base = new Three.TorusGeometry(0.045, 0.02, 32, 32); let umbrella_base = new Three.Mesh(g_umbrella_base, blueMaterial); umbrella_base.rotation.x = Math.PI/2; umbrella_base.position.set(0, 0.7, 0); let g_umbrella = new Three.TorusGeometry(0.06, 0.015, 32, 32); let umbrella = []; for (let i = 0; i < 4; i++) { umbrella[i] = new Three.Mesh(g_umbrella, blueMaterial); umbrella[i].rotation.x = Math.PI/2; umbrella[i].position.y = 0.7; } umbrella[0].position.x = 0.1; umbrella[1].position.z = 0.1; umbrella[2].position.x = -0.1; umbrella[3].position.z = -0.1; //hooks let g_hook_body = new Three.CylinderGeometry(0.015, 0.015, 0.17, 32, 32); let g_hook = new Three.CylinderGeometry(0.05, 0.05, 0.02, 32, 32); let hooks = []; for (let i = 0; i < 8; i++) { hooks[i] = new Three.Object3D(); hooks[i].rotation.x = Math.PI/2; hooks[i].position.set(0, 1.7, 0); let hook_body = new Three.Mesh(g_hook_body, greyMaterial); hooks[i].add(hook_body); let hook = new Three.Mesh(g_hook, blueMaterial); hook_body.add(hook); hook.position.y = 0.085; hooks[i].rotation.z = 45 * i * Math.PI/180; hook_body.position.y = 0.115; if ((i % 2) === 1) hooks[i].position.y += 0.2; } hanger.add(base); hanger.add(base2); hanger.add(body); hanger.add(umbrella_base); for (let i = 0; i < 4; i++) { hanger.add(umbrella[i]); } for (let i = 0; i < 8; i++) { hanger.add(hooks[i]); } return hanger; } function makeObjectMinLOD() { let hanger = new Three.Mesh(); //base let base_geom = new Three.CylinderGeometry(0.09, 0.25, 0.08, 20, 2, true); blackMaterial.side = Three.DoubleSide; let base = new Three.Mesh(base_geom, blackMaterial); base.position.set(0, 0.04, 0); let base2_geom = new Three.CylinderGeometry(0.09, 0.01, 0.03, 20, 2, true); let base2 = new Three.Mesh(base2_geom, blackMaterial); base2.position.set(0, 0.015+0.05, 0); //central body let body_geom = new Three.CylinderGeometry(0.03, 0.03, 2, 8, 8); let body = new Three.Mesh(body_geom, greyMaterial); body.position.set(0, 1, 0); //umbrella support let g_umbrella_base = new Three.TorusGeometry(0.045, 0.02, 8, 8); let m_umbrella = new Three.MeshLambertMaterial({ color: 0x3399FF, transparent: true, opacity: 0.8 }); let umbrella_base = new Three.Mesh(g_umbrella_base, m_umbrella); umbrella_base.rotation.x = Math.PI/2; umbrella_base.position.set(0, 0.7, 0); let g_umbrella = new Three.TorusGeometry(0.06, 0.015, 8, 8); let umbrella = []; for (let i = 0; i < 4; i++) { umbrella[i] = new Three.Mesh(g_umbrella, m_umbrella); umbrella[i].rotation.x = Math.PI/2; umbrella[i].position.y = 0.7; } umbrella[0].position.x = 0.1; umbrella[1].position.z = 0.1; umbrella[2].position.x = -0.1; umbrella[3].position.z = -0.1; //hooks let g_hook_body = new Three.CylinderGeometry(0.015, 0.015, 0.17, 8, 8); let g_hook = new Three.CylinderGeometry(0.05, 0.05, 0.02, 8, 8); let hooks = []; for (let i = 0; i < 8; i++) { hooks[i] = new Three.Object3D(); hooks[i].rotation.x = Math.PI/2; hooks[i].position.set(0, 1.7, 0); let hook_body = new Three.Mesh(g_hook_body, greyMaterial); hooks[i].add(hook_body); let hook = new Three.Mesh(g_hook, m_umbrella); hook_body.add(hook); hook.position.y = 0.085; hooks[i].rotation.z = 45 * i * Math.PI/180; hook_body.position.y = 0.115; if (i % 2 === 1) hooks[i].position.y += 0.2; } hanger.add(base); hanger.add(base2); hanger.add(body); hanger.add(umbrella_base); for (let i = 0; i < 4; i++) { hanger.add(umbrella[i]); } for (let i = 0; i < 8; i++) { hanger.add(hooks[i]); } return hanger; } export default { name: "hanger", prototype: "items", info: { tag: ['furnishings', 'metallo','plastic'], title: "hanger", description: "hanger", image: require('./hanger.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 hangerMaxLOD = new Three.Object3D(); hangerMaxLOD.add(objectMaxLOD.clone()); let aa = new Three.Box3().setFromObject(hangerMaxLOD); let deltaX = Math.abs(aa.max.x - aa.min.x); let deltaY = Math.abs(aa.max.y - aa.min.y); let deltaZ = Math.abs(aa.max.z - aa.min.z); hangerMaxLOD.position.y+= newAltitude; hangerMaxLOD.scale.set(WIDTH / deltaX, HEIGHT / deltaY, DEPTH / deltaZ); /************* lod min ******************/ let hangerMinLOD = new Three.Object3D(); hangerMinLOD.add(objectMinLOD.clone()); hangerMinLOD.position.y+= newAltitude; hangerMinLOD.scale.set(WIDTH / deltaX, HEIGHT / deltaY, DEPTH / deltaZ); /**** all level of detail ***/ let lod = new Three.LOD(); lod.addLevel(hangerMaxLOD, 200); lod.addLevel(hangerMinLOD, 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); } };