react-planner-electron
Version:
react-planner-electron is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.
233 lines (179 loc) • 6.38 kB
JSX
import * as Three from 'three';
import React from 'react';
const WIDTH=30;
const DEPTH=40;
const HEIGHT=70;
const textureLoader = new Three.TextureLoader();
const Image = textureLoader.load(require('./bronze-texture.jpg'));
const material = new Three.MeshLambertMaterial( {map:Image} );
const objectMaxLOD = makeObjectMaxLOD();
const objectMinLOD = makeObjectMinLOD();
function makeObjectMaxLOD() {
let umbrellaStand = new Three.Mesh();
let roundedRectShape = new Three.Shape();
let x=0;
let y=0;
let width=.45;
let height=.7;
roundedRectShape.moveTo( x, y );
roundedRectShape.lineTo( x + width, y);
roundedRectShape.lineTo( x + width, y+height );
roundedRectShape.lineTo( x, y + height) ;
let holePath = new Three.Path();
holePath.moveTo( width/2, height/2 );
holePath.absellipse( .225, .15, .100, .025, .025, Math.PI*2, false );
roundedRectShape.holes.push( holePath );
let extrudeSettings = {
steps: 2,
depth: .05,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1
};
let SideGeometry = new Three.ExtrudeGeometry( roundedRectShape, extrudeSettings );
let Side1 = new Three.Mesh( SideGeometry, material ) ;
Side1.position.set(.05,1.2,0);
Side1.rotation.z+=Math.PI;
umbrellaStand.add(Side1);
let Side2 = new Three.Mesh( SideGeometry, material ) ;
Side2.position.set(.05,1.2,-.4);
Side2.rotation.z+=Math.PI;
umbrellaStand.add(Side2);
let Side3 = new Three.Mesh( SideGeometry, material ) ;
Side3.position.set(.05,1.2,-.4);
Side3.rotation.z+=Math.PI;
Side3.rotation.y+=Math.PI/2;
umbrellaStand.add(Side3);
let Side4 = new Three.Mesh( SideGeometry, material ) ;
Side4.position.set(-.45,1.2,-.4);
Side4.rotation.z+=Math.PI;
Side4.rotation.y+=Math.PI/2;
umbrellaStand.add(Side4);
let geometryBox = new Three.BoxGeometry(.55, .45, .05 );
let downPlane = new Three.Mesh( geometryBox, material );
downPlane.rotation.x+=Math.PI/2;
downPlane.position.set(-.175,.475,-.175);
umbrellaStand.add(downPlane);
return umbrellaStand
}
function makeObjectMinLOD() {
let umbrellaStand = new Three.Mesh();
let roundedRectShape = new Three.Shape();
let x=0;
let y=0;
let width=.45;
let height=.7;
roundedRectShape.moveTo( x, y );
roundedRectShape.lineTo( x + width, y);
roundedRectShape.lineTo( x + width, y+height );
roundedRectShape.lineTo( x, y + height) ;
let extrudeSettings = {
steps: 2,
depth: .05,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1
};
let SideGeometry = new Three.ExtrudeGeometry( roundedRectShape, extrudeSettings );
let Side1 = new Three.Mesh( SideGeometry, material ) ;
Side1.position.set(.05,1.2,0);
Side1.rotation.z+=Math.PI;
umbrellaStand.add(Side1);
let Side2 = new Three.Mesh( SideGeometry, material ) ;
Side2.position.set(.05,1.2,-.4);
Side2.rotation.z+=Math.PI;
umbrellaStand.add(Side2);
let Side3 = new Three.Mesh( SideGeometry, material ) ;
Side3.position.set(.05,1.2,-.4);
Side3.rotation.z+=Math.PI;
Side3.rotation.y+=Math.PI/2;
umbrellaStand.add(Side3);
let Side4 = new Three.Mesh( SideGeometry, material ) ;
Side4.position.set(-.45,1.2,-.4);
Side4.rotation.z+=Math.PI;
Side4.rotation.y+=Math.PI/2;
umbrellaStand.add(Side4);
let geometryBox = new Three.BoxGeometry(.55, .45, .05 );
let downPlane = new Three.Mesh( geometryBox, material );
downPlane.rotation.x+=Math.PI/2;
downPlane.position.set(-.175,.475,-.175);
umbrellaStand.add(downPlane);
return umbrellaStand
}
export default {
name: "umbrella-stand",
prototype: "items",
info: {
tag: ['furnishings', 'metal'],
title: "umbrella stand",
description: "umbrella stand",
image: require('./umbrellaStand.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 umbrellaStandMaxLOD = new Three.Object3D();
umbrellaStandMaxLOD.add(objectMaxLOD.clone());
let value = new Three.Box3().setFromObject(umbrellaStandMaxLOD);
let deltaX = Math.abs(value.max.x - value.min.x);
let deltaY = Math.abs(value.max.y - value.min.y);
let deltaZ = Math.abs(value.max.z - value.min.z);
umbrellaStandMaxLOD.position.x+= -WIDTH/1.5;
umbrellaStandMaxLOD.position.z+= DEPTH/4;
umbrellaStandMaxLOD.position.y+= -HEIGHT/1.6 + newAltitude;
umbrellaStandMaxLOD.rotation.y+= -Math.PI/2;
umbrellaStandMaxLOD.scale.set(WIDTH / deltaZ, HEIGHT / deltaY, DEPTH / deltaX);
/**************** lod min *******************/
let umbrellaStandMinLOD = new Three.Object3D();
umbrellaStandMinLOD.add(objectMinLOD.clone());
umbrellaStandMinLOD.position.x+= -WIDTH/1.5;
umbrellaStandMinLOD.position.z+= DEPTH/4;
umbrellaStandMinLOD.position.y+= -HEIGHT/1.6 + newAltitude;
umbrellaStandMinLOD.rotation.y+= -Math.PI/2;
umbrellaStandMinLOD.scale.set(WIDTH / deltaZ, HEIGHT / deltaY, DEPTH / deltaX);
/**** all level of detail ***/
let lod = new Three.LOD();
lod.addLevel(umbrellaStandMaxLOD, 200);
lod.addLevel(umbrellaStandMinLOD, 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);
}
};