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