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
JSX
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);
}
};