react-planner-electron
Version:
react-planner-electron is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.
183 lines (137 loc) • 6.74 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.buildWall = buildWall;
exports.updatedWall = updatedWall;
var _three = require('three');
var _threeCSG = require('../../utils/threeCSG.es6');
var _threeCSG2 = _interopRequireDefault(_threeCSG);
var _geometry = require('../../utils/geometry');
var _sharedStyle = require('../../shared-style');
var SharedStyle = _interopRequireWildcard(_sharedStyle);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var halfPI = Math.PI / 2;
/**
* Apply a texture to a wall face
* @param material: The material of the face
* @param texture: The texture to load
* @param length: The lenght of the face
* @param height: The height of the face
*/
var applyTexture = function applyTexture(material, texture, length, height) {
var loader = new _three.TextureLoader();
if (texture) {
material.map = loader.load(texture.uri);
material.needsUpdate = true;
material.map.wrapS = _three.RepeatWrapping;
material.map.wrapT = _three.RepeatWrapping;
material.map.repeat.set(length * texture.lengthRepeatScale, height * texture.heightRepeatScale);
if (texture.normal) {
material.normalMap = loader.load(texture.normal.uri);
material.normalScale = new _three.Vector2(texture.normal.normalScaleX, texture.normal.normalScaleY);
material.normalMap.wrapS = _three.RepeatWrapping;
material.normalMap.wrapT = _three.RepeatWrapping;
material.normalMap.repeat.set(length * texture.normal.lengthRepeatScale, height * texture.normal.heightRepeatScale);
}
}
};
function buildWall(element, layer, scene, textures) {
// Get the two vertices of the wall
var vertex0 = layer.vertices.get(element.vertices.get(0));
var vertex1 = layer.vertices.get(element.vertices.get(1));
var inverted = false;
// The first vertex is the smaller one
if (vertex0.x > vertex1.x) {
var app = vertex0;
vertex0 = vertex1;
vertex1 = app;
inverted = true;
}
// Get height and thickness of the wall converting them into the current scene units
var height = element.properties.getIn(['height', 'length']);
var thickness = element.properties.getIn(['thickness', 'length']);
var halfThickness = thickness / 2;
var faceThickness = 0.2;
var faceDistance = 1;
var distance = (0, _geometry.verticesDistance)(vertex0, vertex1);
var halfDistance = distance / 2;
var soulMaterial = new _three.MeshBasicMaterial({ color: element.selected ? SharedStyle.MESH_SELECTED : 0xD3D3D3 });
var soul = new _three.Mesh(new _three.BoxGeometry(distance, height, thickness), soulMaterial);
var alpha = Math.asin((vertex1.y - vertex0.y) / distance);
var sinAlpha = Math.sin(alpha);
var cosAlpha = Math.cos(alpha);
soul.position.y += height / 2;
soul.position.x += halfDistance * cosAlpha;
soul.position.z -= halfDistance * sinAlpha;
soul.rotation.y = alpha;
element.holes.forEach(function (holeID) {
var holeData = layer.holes.get(holeID);
var holeWidth = holeData.properties.getIn(['width', 'length']);
var holeHeight = holeData.properties.getIn(['height', 'length']);
var holeAltitude = holeData.properties.getIn(['altitude', 'length']);
var offset = inverted ? 1 - holeData.offset : holeData.offset;
var holeDistance = offset * distance;
var holeGeometry = new _three.BoxGeometry(holeWidth, holeHeight, thickness);
var holeMesh = new _three.Mesh(holeGeometry);
holeMesh.position.y += holeHeight / 2 + holeAltitude;
holeMesh.position.x += holeDistance * cosAlpha;
holeMesh.position.z -= holeDistance * sinAlpha;
holeMesh.rotation.y = alpha;
var wallBSP = new _threeCSG2.default(soul);
var holeBSP = new _threeCSG2.default(holeMesh);
var wallWithHoleBSP = wallBSP.subtract(holeBSP);
soul = wallWithHoleBSP.toMesh(soulMaterial);
});
soul.name = 'soul';
var frontMaterial = new _three.MeshBasicMaterial();
var backMaterial = new _three.MeshBasicMaterial();
applyTexture(frontMaterial, textures[element.properties.get('textureB')], distance, height);
applyTexture(backMaterial, textures[element.properties.get('textureA')], distance, height);
var scaleFactor = faceThickness / thickness;
var texturedFaceDistance = halfThickness + faceDistance;
var frontFace = soul.clone();
frontFace.material = frontMaterial;
frontFace.scale.set(1, 1, scaleFactor);
frontFace.position.x += texturedFaceDistance * Math.cos(alpha - halfPI);
frontFace.position.z -= texturedFaceDistance * Math.sin(alpha - halfPI);
frontFace.name = 'frontFace';
var backFace = soul.clone();
backFace.material = backMaterial;
backFace.scale.set(1, 1, scaleFactor);
backFace.position.x += texturedFaceDistance * Math.cos(alpha + halfPI);
backFace.position.z -= texturedFaceDistance * Math.sin(alpha + halfPI);
backFace.name = 'backFace';
var merged = new _three.Group();
merged.add(soul, frontFace, backFace);
return Promise.resolve(merged);
}
function updatedWall(element, layer, scene, textures, mesh, oldElement, differences, selfDestroy, selfBuild) {
var noPerf = function noPerf() {
selfDestroy();return selfBuild();
};
var soul = mesh.getObjectByName('soul');
var frontFace = mesh.getObjectByName('frontFace');
var backFace = mesh.getObjectByName('backFace');
if (differences[0] == 'selected') {
soul.material = new _three.MeshBasicMaterial({ color: element.selected ? SharedStyle.MESH_SELECTED : 0xD3D3D3 });
} else if (differences[0] == 'properties') {
if (differences[1] == 'thickness') {
var newThickness = element.getIn(['properties', 'thickness', 'length']);
var oldThickness = oldElement.getIn(['properties', 'thickness', 'length']);
var halfNewThickness = newThickness / 2;
var texturedFaceDistance = halfNewThickness + 1;
var originalThickness = oldThickness / soul.scale.z;
var alpha = soul.rotation.y;
var xTemp = texturedFaceDistance * Math.cos(alpha - halfPI);
var zTemp = texturedFaceDistance * Math.sin(alpha - halfPI);
soul.scale.set(1, 1, newThickness / originalThickness);
frontFace.position.x = soul.position.x + xTemp;
frontFace.position.z = soul.position.z + zTemp;
backFace.position.x = soul.position.x - xTemp;
backFace.position.z = soul.position.z - zTemp;
} else return noPerf();
} else return noPerf();
return Promise.resolve(mesh);
}