react-planner-electron
Version:
react-planner-electron is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.
162 lines (126 loc) • 4.5 kB
JSX
import * as Three from 'three';
import React from 'react';
const textureLoader = new Three.TextureLoader();
const front = textureLoader.load(require('./front.png'));
const blackMaterial = new Three.MeshLambertMaterial({color: 0x3d3d3d});
function makeObjectMaxLOD(newWidth,newHeight,newDepth) {
let hub = new Three.Mesh();
let cubeGeometryBase = new Three.BoxGeometry(newWidth,newHeight,newDepth);
let body = new Three.Mesh(cubeGeometryBase,blackMaterial);
body.position.set(0,1,0);
hub.add(body);
for (let i = -newHeight/2+newHeight/32; i < newHeight/2; i+=newHeight/16) {
let planeGeometry = new Three.PlaneGeometry(newWidth,newHeight/16);
let planeMaterial = new Three.MeshLambertMaterial({map:front});
let plane_texture = new Three.Mesh(planeGeometry,planeMaterial);
plane_texture.position.set(0,i,newDepth/3+newDepth/5.9);
body.add(plane_texture);
}
return hub
}
function makeObjectMinLOD(newWidth,newHeight,newDepth) {
let hub = new Three.Mesh();
let cubeGeometryBase = new Three.BoxGeometry(newWidth,newHeight,newDepth);
let body = new Three.Mesh(cubeGeometryBase,blackMaterial);
body.position.set(0,1,0);
hub.add(body);
return hub
}
export default {
name: "hub",
prototype: "items",
info: {
tag: ['furnishings', 'metal'],
title: "hub",
description: "hub",
image: require('./hub.png')
},
properties: {
width: {
label: "width",
type: "length-measure",
defaultValue: {
length: 60,
unit: 'cm'
}
},
depth: {
label: "depth",
type: "length-measure",
defaultValue: {
length: 30,
unit: 'cm'
}
},
height: {
label: "height",
type: "length-measure",
defaultValue: {
length: 200,
unit: 'cm'
}
},
altitude: {
label: "altitude",
type: "length-measure",
defaultValue: {
length: 0,
unit: 'cm'
}
}
},
render2D: function (element, layer, scene) {
let newWidth = element.properties.get('width').get('length');
let newDepth = element.properties.get('depth').get('length');
let angle = element.rotation + 90;
let textRotation = 0;
if (Math.sin(angle * Math.PI / 180) < 0) {
textRotation = 180;
}
return (
<g transform={`translate(${-newWidth / 2},${-newDepth / 2})`}>
<rect key="1" x="0" y="0" width={newWidth} height={newDepth}
style={{stroke: element.selected ? '#0096fd' : '#000', strokeWidth: "2px", fill: "#84e1ce"}}/>
<text key="2" x="0" y="0"
transform={`translate(${newWidth / 2}, ${newDepth / 2}) scale(1,-1) rotate(${textRotation})`}
style={{textAnchor: "middle", fontSize: "11px"}}>
{element.type}
</text>
</g>
)
},
render3D: function (element, layer, scene) {
let newWidth = element.properties.get('width').get('length');
let newDepth = element.properties.get('depth').get('length');
let newHeight = element.properties.get('height').get('length');
let newAltitude = element.properties.get('altitude').get('length');
/*************** lod max ******************/
let hubMaxLOD = new Three.Object3D();
hubMaxLOD.add(makeObjectMaxLOD(newWidth,newHeight,newDepth).clone());
let valuePosition = new Three.Box3().setFromObject(hubMaxLOD);
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);
hubMaxLOD.position.y+= newHeight/2 +newAltitude;
hubMaxLOD.scale.set(newWidth / deltaX, newHeight / deltaY, newDepth / deltaZ);
/*************** lod min ******************/
let hubMinLOD = new Three.Object3D();
hubMinLOD.add(makeObjectMinLOD(newWidth,newHeight,newDepth).clone());
hubMinLOD.position.y+= newHeight/2 +newAltitude;
hubMinLOD.scale.set(newWidth / deltaX, newHeight / deltaY, newDepth / deltaZ);
/**** all level of detail ***/
let lod = new Three.LOD();
lod.addLevel(hubMaxLOD, 200);
lod.addLevel(hubMinLOD, 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);
}
};