UNPKG

kitchen-simulator

Version:

It is a kitchen simulator (self-contained micro-frontend).

1,119 lines (1,091 loc) 65 kB
import _typeof from "@babel/runtime/helpers/esm/typeof"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import { convert } from "../../utils/convert-units-lite"; import { fromJS, Map } from 'immutable'; import React, { useState } from 'react'; import * as Three from 'three'; import * as SceneCreator from "../../components/viewer3d/scene-creator"; import { ARROW_COLOR, BASE_CABINET_LAYOUTPOS, OBJTYPE_GROUP, OBJTYPE_MESH, SHADE_DARK_PURPLE_COLOR, SHAPE_SVG_DEPTH, SHAPE_SVG_PADDING, SHAPE_SVG_WIDTH, STATUS_WARNING_COLOR, STATUS_WARNING_LIGHT_COLOR, TALL_CABINET_LAYOUTPOS, UNIT_CENTIMETER, UNIT_INCH, WALL_CABINET_LAYOUTPOS } from "../../constants"; import { Item } from "../../models"; import * as GeomUtils from "./geom-utils"; import { loadGLTF } from "./load-obj"; import { animateDoor, translateDrawer } from "../../utils/helper"; // env Map /////////////// // env Map /////////////// var paramsCounter = { envMap: 'HDR', roughness: 0.6, metalness: 0.3, exposure: 1 // debug: true }; var params = { envMap: 'HDR', roughness: 0.9, metalness: 0.1, metalness_glossy: 0.2, exposure: 1.0 // debug: false }; var paramsModel = { envMap: 'HDR', roughness: 0.9, metalness: 0.2, exposure: 1.0 // debug: false }; // ///////////////////////// var cachedObject = {}; // cached Object for quickly load-3d // render 2d function////// export function render2DItem(element, layer, scene, sizeinfo, layoutpos, is_corner, shape_svg) { var _useState = useState(false), _useState2 = _slicedToArray(_useState, 2), hover = _useState2[0], setHover = _useState2[1]; var x = element.x, y = element.y, rotation = element.rotation; var el_DSN = 'el_DSN', doorStylesKeys = []; var _element = element.toJS(); if (_element.doorStyle !== undefined) { if (_element.doorStyle.doorStyles !== undefined) { doorStylesKeys = Object.keys(_element.doorStyle.doorStyles); } } if ((doorStylesKeys.includes('euro_length') || doorStylesKeys.includes('euro_width') || doorStylesKeys.includes('euro_shape_svg')) && _element.doorStyle.doorStyles.is_euro_cds) { el_DSN = _element.doorStyle.door_style_name; } else { el_DSN = 'el_DSN'; } var width, depth, el_euro_length, el_euro_width, el_euro_length_unit, el_euro_width_unit, el_is_euro_cds, el_euro_shape_svg; if (doorStylesKeys.length > 0) { el_euro_length = _element.doorStyle.doorStyles.euro_length; el_euro_width = _element.doorStyle.doorStyles.euro_width; el_is_euro_cds = _element.doorStyle.doorStyles.is_euro_cds; el_euro_shape_svg = _element.doorStyle.doorStyles.euro_shape_svg; } if (el_euro_length === undefined && el_euro_width === undefined) { el_DSN = 'el_DSN'; } if (el_DSN === 'Euro & Frameless') { // sizeinfo["depth"] = el_euro_length; // sizeinfo["width"] = el_euro_width; } var tempWidth = element.properties.get('width'); var tempDepth = element.properties.get('depth'); width = tempWidth && { length: tempWidth.get('_length'), unit: tempWidth.get('_unit') }; depth = tempDepth && { length: tempDepth.get('_length'), unit: tempDepth.get('_unit') }; var originalWidth = convert(sizeinfo.width).from('in').to('cm'); var originalDepth = convert(sizeinfo.depth).from('in').to('cm'); var newWidth = convert(width.length).from(width.unit).to('cm'); var newDepth = convert(depth.length).from(depth.unit).to('cm'); var padding = convert(SHAPE_SVG_PADDING).from(UNIT_INCH).to(UNIT_CENTIMETER); var angle = element.rotation + 90; var textRotation = 0; if (Math.sin(angle * Math.PI / 180) < 0) { textRotation = 180; } var color = '#eee'; if (layoutpos == BASE_CABINET_LAYOUTPOS) { color = '#3f8db3'; } if (layoutpos == TALL_CABINET_LAYOUTPOS) { color = '#93b3be'; } if (layoutpos == WALL_CABINET_LAYOUTPOS) { color = '#48b08dcc'; } var splitStr = []; var txtContent = []; var lineCount = 0; //parseInt(((newWidth) / 8 - 0.51).toFixed(), 10) - 1; var rowCount = 0; //parseInt((element.type.length / lineCount - 0.51).toFixed(), 10); // Get type var type = element.type; var objSKU = this.obj.sku_number; if (objSKU.length !== 0) { var dcId, doorStyle = element.doorStyle; if (doorStyle instanceof Map) { dcId = doorStyle.get('id'); } else { dcId = doorStyle.id; } var skuItem = this.obj.skuArray.find(function (el) { return el.door_color_id === dcId; }); if (skuItem !== undefined) { type = skuItem.sku; } } if (rowCount > 0) { for (var _x = 0; _x < rowCount; _x++) { splitStr.push(type.slice(lineCount * _x, lineCount * (_x + 1))); } } splitStr.push(type.slice(lineCount * rowCount)); splitStr.forEach(function (el, key) { txtContent.push(/*#__PURE__*/React.createElement("text", { key: 'text' + key, x: "0", y: newDepth / 2 - 12, dy: 16 * key, transform: "translate(".concat(newWidth / 2, ", ").concat(newDepth / 2 + 5, ") scale(1,-1) rotate(").concat(textRotation, ")") // textLength={newWidth - 10} // lengthAdjust="spacingAndGlyphs" , style: { fontWeight: 500, fontSize: '7px', textAnchor: 'middle', fill: '#FFF', display: 'block' } }, el)); }); var style = { stroke: element.selected ? '#565658' : '#565658', strokeWidth: '2px', fill: color }; // let arrow_style = { stroke: element.selected ? '#0096fd' : null, strokeWidth: "2px", fill: "#84e1ce" }; var rendered = null; if (shape_svg || el_euro_shape_svg) { var svg_url, svg_width, svg_depth; if (typeof shape_svg == 'string' || typeof el_euro_shape_svg == 'string') { if (el_DSN === 'Euro & Frameless' && el_is_euro_cds) { svg_url = el_euro_shape_svg; svg_width = newWidth; svg_depth = newDepth; } else { svg_url = shape_svg; svg_width = originalWidth; svg_depth = originalDepth; } } else { // if (el_DSN === "Euro & Frameless" && el_is_euro_cds) { // // svg_url = el_euro_shape_svg.url; // } else { // } svg_url = shape_svg.url; svg_width = convert(SHAPE_SVG_WIDTH).from(UNIT_INCH).to(UNIT_CENTIMETER); svg_depth = convert(SHAPE_SVG_DEPTH).from(UNIT_INCH).to(UNIT_CENTIMETER); } var padding_width = padding * newWidth / svg_width; var padding_depth = padding * newDepth / svg_depth; rendered = /*#__PURE__*/React.createElement("g", { onMouseOver: function onMouseOver(event) { setHover(true); }, onMouseOut: function onMouseOut(event) { setHover(false); }, transform: "translate(".concat(x, ",").concat(y, ")") }, /*#__PURE__*/React.createElement("g", { transform: "rotate(".concat(rotation, ")") }, /*#__PURE__*/React.createElement("g", { transform: "translate(".concat(-newWidth / 2 - padding_width, ",").concat(-newDepth / 2 - padding_depth, ")") }, /*#__PURE__*/React.createElement("image", { preserveAspectRatio: "none", style: { pointerEvents: 'none' }, href: svg_url, width: "".concat(newWidth + 2 * padding_width), height: "".concat(newDepth + 2 * padding_depth), transform: "scale(1, -1)", x: "0", y: "".concat(-newDepth - 2 * padding_depth) }), /*#__PURE__*/React.createElement("rect", { x: "".concat(padding_width), y: "".concat(padding_depth), width: "".concat(newWidth), height: "".concat(newDepth), visibility: element.toJS().doorStyle.doorStyles !== undefined ? element.toJS().doorStyle.doorStyles && element.toJS().doorStyle.doorStyles.cds && element.toJS().doorStyle.doorStyles.cds.length != 0 && element.toJS().doorStyle.doorStyles.cds.filter(function (cd) { return cd.itemID == element.getIn(['itemID']); }) ? 'hidden' : 'visible' : 'hidden', style: { pointerEvents: 'all', opacity: 0.7, postion: 'relative' }, fill: STATUS_WARNING_LIGHT_COLOR, stroke: STATUS_WARNING_COLOR, strokeWidth: "2px" }), /*#__PURE__*/React.createElement("g", { transform: "translate(".concat(padding_width, ",").concat(padding_depth, ")") }, txtContent)))); } else { rendered = /*#__PURE__*/React.createElement("g", { onMouseOver: function onMouseOver(event) { setHover(true); }, onMouseOut: function onMouseOut(event) { setHover(false); }, transform: "translate(".concat(x, ",").concat(y, ")") }, /*#__PURE__*/React.createElement("g", { transform: "rotate(".concat(rotation, ")") }, /*#__PURE__*/React.createElement("g", { transform: "translate(".concat(-newWidth / 2, ",").concat(-newDepth / 2, ")") }, newDepth > 15 ? [/*#__PURE__*/React.createElement("rect", { key: "base", x: "0", y: "12", width: newWidth, height: newDepth - 12, style: style }), /*#__PURE__*/React.createElement("polygon", { key: "door", style: style, points: "0,9 ".concat(newWidth, ",9 ").concat(newWidth, ",6 ").concat(newWidth - 5, ",6 ").concat(newWidth - 5, ",3 ").concat(newWidth - 2, ",3 ").concat(newWidth - 2, " 0 ").concat(newWidth - 10, " 0 ").concat(newWidth - 10, ",3 ").concat(newWidth - 7, ",3 ").concat(newWidth - 7, ",6 0 6") })] : /*#__PURE__*/React.createElement("rect", { key: "base", x: "0", y: "0", width: newWidth, height: newDepth, style: style }), txtContent))); } return rendered; } // end of render 2d function ///////////////////////// export function loadTexture(url) { var texture = new Three.TextureLoader().load(url); texture.colorSpace = Three.SRGBColorSpace; texture.wrapS = Three.MirroredRepeatWrapping; texture.wrapT = Three.MirroredRepeatWrapping; return texture; } var applyTexture = function applyTexture(material, texture, length, height) { if (texture) { material.map = texture; material.needsUpdate = true; material.map.wrapS = Three.RepeatWrapping; material.map.wrapT = Three.RepeatWrapping; material.map.repeat.set(length * 0.01, height * 0.01); if (texture.normal) { material.normalMap = loadTexture(texture.normal.uri); material.normalScale = new 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); } } }; var assignUVs = function assignUVs(geometry) { geometry.computeBoundingBox(); var _geometry$boundingBox = geometry.boundingBox, min = _geometry$boundingBox.min, max = _geometry$boundingBox.max; var offset = new Three.Vector3(0 - min.x, 0 - min.y, 0 - min.z); var range = new Three.Vector3(max.x - min.x, max.y - min.y, max.z - min.z); geometry.faceVertexUvs[0] = geometry.faces.map(function (face) { var v1 = geometry.vertices[face.a]; var v2 = geometry.vertices[face.b]; var v3 = geometry.vertices[face.c]; return [new Three.Vector3((v1.x + offset.x) / range.x, (v1.y + offset.y) / range.y, (v1.z + offset.z) / range.z), new Three.Vector3((v2.x + offset.x) / range.x, (v2.y + offset.y) / range.y, (v1.z + offset.z) / range.z), new Three.Vector3((v3.x + offset.x) / range.x, (v3.y + offset.y) / range.y, (v1.z + offset.z) / range.z)]; }); geometry.uvsNeedUpdate = true; }; /** * Render 3D Item * @param {Item} element Rendering item * @param sizeinfo Dimesion of the item * @param structure_json Structure of the item such as place holders and meshes, etc */ export function render3DItem(element, layer, scene, sizeinfo, structure_json, is_corner) { var mode = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; if (element.doorStyle.constructor !== Map) { element = element.set('doorStyle', fromJS(element.doorStyle)); } if (element.doorStyle.toJS().handle_gltf !== '') { // Check element has doorHandle for (var i = 1; i < 10; i++) { element = element.setIn(['doorStyle', 'doorStyles', 'door_handle_' + i + '_gltf'], element.doorStyle.toJS().handle_gltf); element = element.setIn(['doorStyle', 'doorStyles', 'fixed_drawer_door_handle_' + i + '_gltf'], element.doorStyle.toJS().handle_gltf); element = element.setIn(['doorStyle', 'doorStyles', 'drawer_door_handle_' + i + '_gltf'], element.doorStyle.toJS().handle_gltf); } } var width = { length: sizeinfo.width, unit: 'in' }; var depth = { length: sizeinfo.depth, unit: 'in' }; var height = { length: sizeinfo.height, unit: 'in' }; var newWidth = convert(width.length).from(width.unit).to('in'); var newDepth = convert(depth.length).from(depth.unit).to('in'); var newHeight = convert(height.length).from(height.unit).to('in'); var mainName = ''; // to get name structure// if (element.properties.get('width')) newWidth = element.getIn(['properties', 'width', '_length']); if (element.properties.get('depth')) newDepth = element.getIn(['properties', 'depth', '_length']); if (element.properties.get('height')) newHeight = element.getIn(['properties', 'height', '_length']); var structure = structure_json; // structure.push({name:'model', url: '/assets/model/DCM.gltf'}); structure.model = '/assets/model/DCM.gltf'; var placeholders = structure.placeholders; var doorStyles = null; var color = 0xffffff, glossness = 1, handleMaterial = {}; var counterTop = element.counterTop; if (layer.toJS().counterTop.uri) { counterTop.uri = layer.toJS().counterTop.uri; } if ('name' in element.doorStyle) { doorStyles = new Map(element.doorStyle.doorStyles); color = element.doorStyle.color; glossness = element.doorStyle.glossness; handleMaterial.metalness = element.doorStyle.metalness; handleMaterial.roughness = element.doorStyle.roughness; } else if (element.doorStyle != null && element.doorStyle) { doorStyles = element.doorStyle.get('doorStyles'); color = element.doorStyle.get('color'); glossness = element.doorStyle.get('glossness'); handleMaterial.metalness = element.doorStyle.get('metalness'); handleMaterial.roughness = element.doorStyle.get('roughness'); } if (color === undefined) color = '#ffffff'; if (glossness === undefined) glossness = 1; var tempDoorStyles = doorStyles.toJS(); var tempPlaceholders = structure.tempPlaceholders; var tPlaceholders = tempPlaceholders.find(function (el) { return el.id === tempDoorStyles.cabinet_door_style_id; }); if (tPlaceholders !== undefined) { placeholders = tPlaceholders.placeholders; var tempStructure = _objectSpread(_objectSpread({}, tPlaceholders.structure), {}, { animation: structure.animation, placeholders: structure.placeholders, tempPlaceholders: structure.tempPlaceholders, model: structure.model }); structure = tempStructure; } var userData = structure.animation; // /////////////////////////// var onLoadItem = function onLoadItem(object) { var areaMaterial = new Three.MeshStandardMaterial(); areaMaterial.side = Three.DoubleSide; // areaMaterial.envMap = textureCube; if (doorStyles != null) if (doorStyles.get('base') != undefined) { var normalMap = doorStyles.get('base'); var interiortexture = loadTexture(normalMap); applyTexture(areaMaterial, interiortexture, 100, 100); } var object1 = object; var newAltitude = element.properties.get('altitude').get('_length'); var newUnit = element.properties.get('altitude').get('_unit') || 'in'; newAltitude = convert(newAltitude).from(newUnit).to(scene.unit); var _element = element.toJS(); if (!_element.doorStyle.doorStyles.is_euro_cds) { object1.scale.set(100 * newWidth / sizeinfo.width, 100 * newHeight / sizeinfo.height, 100 * newDepth / sizeinfo.depth); } else { object1.scale.set(100, 100, 100); } // Normalize the origin of the object var boundingBox = GeomUtils.baseBox3FromObject(object1); object1.userData = boundingBox; var door_animate_offset = {}; var matchStr = /\d_(door[^LR1-9]*)(_[LR])?(_[1-9])?$/; object1.children.forEach(function (child) { var door_match = child.name.match(matchStr); if (door_match && door_match.length > 2) { var _child$children$; var rotate_match_text = element.properties.toJS().flip_doorhandle ? 'rotate_L' : 'rotate_R'; if (door_match[2] === '_L') { rotate_match_text = element.properties.toJS().flip_doorhandle ? 'rotate_R' : 'rotate_L'; } var isDoubleDoor = door_match && door_match[2] !== undefined; (_child$children$ = child.children[0]) === null || _child$children$ === void 0 || _child$children$.children.forEach(function (it) { var _it$name, _it$children; if (it !== null && it !== void 0 && (_it$name = it.name) !== null && _it$name !== void 0 && _it$name.includes('handle') && (_it$children = it.children) !== null && _it$children !== void 0 && _it$children.length && is_corner === 1 && isDoubleDoor) { var _child$name, _child$name2, _object1$children, _t0$name, _t0$children; var tname = child !== null && child !== void 0 && (_child$name = child.name) !== null && _child$name !== void 0 && _child$name.endsWith('_L') ? child.name.replace('_L', '_R') : child === null || child === void 0 || (_child$name2 = child.name) === null || _child$name2 === void 0 ? void 0 : _child$name2.replace('_R', '_L'); var tmp = (object1 === null || object1 === void 0 || (_object1$children = object1.children) === null || _object1$children === void 0 ? void 0 : _object1$children.filter(function (item) { return (item === null || item === void 0 ? void 0 : item.name) === tname; })) || []; var t0 = tmp[0]; var filterStr = t0 !== null && t0 !== void 0 && (_t0$name = t0.name) !== null && _t0$name !== void 0 && _t0$name.endsWith('_L') ? 'rotate_L' : 'rotate_R'; var tposArr = (t0 === null || t0 === void 0 || (_t0$children = t0.children) === null || _t0$children === void 0 || (_t0$children = _t0$children[0]) === null || _t0$children === void 0 || (_t0$children = _t0$children.children) === null || _t0$children === void 0 ? void 0 : _t0$children.filter(function (item) { var _item$name; return item === null || item === void 0 || (_item$name = item.name) === null || _item$name === void 0 ? void 0 : _item$name.endsWith(filterStr); })) || []; var tpos0 = tposArr[0]; if (it.name.includes('base_end')) { var _it$position$x, _it$position, _it$position$y, _it$position2, _tpos0$position$x, _tpos0$position; door_animate_offset[child.name] = { x: -2 * ((_it$position$x = (_it$position = it.position) === null || _it$position === void 0 ? void 0 : _it$position.x) !== null && _it$position$x !== void 0 ? _it$position$x : 0) - 0.12, y: (_it$position$y = (_it$position2 = it.position) === null || _it$position2 === void 0 ? void 0 : _it$position2.y) !== null && _it$position$y !== void 0 ? _it$position$y : 0, z: -((_tpos0$position$x = tpos0 === null || tpos0 === void 0 || (_tpos0$position = tpos0.position) === null || _tpos0$position === void 0 ? void 0 : _tpos0$position.x) !== null && _tpos0$position$x !== void 0 ? _tpos0$position$x : 0) + 0.12, isCorner: true }; } else { var _it$position$x2, _it$position3, _it$position$y2, _it$position4, _tpos0$position$x2, _tpos0$position2; door_animate_offset[child.name] = { x: -((_it$position$x2 = (_it$position3 = it.position) === null || _it$position3 === void 0 ? void 0 : _it$position3.x) !== null && _it$position$x2 !== void 0 ? _it$position$x2 : 0) - 0.04, y: (_it$position$y2 = (_it$position4 = it.position) === null || _it$position4 === void 0 ? void 0 : _it$position4.y) !== null && _it$position$y2 !== void 0 ? _it$position$y2 : 0, z: 2 * ((_tpos0$position$x2 = tpos0 === null || tpos0 === void 0 || (_tpos0$position2 = tpos0.position) === null || _tpos0$position2 === void 0 ? void 0 : _tpos0$position2.x) !== null && _tpos0$position$x2 !== void 0 ? _tpos0$position$x2 : 0) - 0.01, isCorner: true }; } } else if (it.name.endsWith(rotate_match_text) && door_animate_offset[child.name] == undefined) { door_animate_offset[child.name] = { x: it.position.x, y: it.position.y, z: it.position.z, isCorner: false }; } }); } }); object1.userData.door_animate_offset = door_animate_offset; object1.userData.animation = userData; var center = [(boundingBox.max.x - boundingBox.min.x) / 2 + boundingBox.min.x, (boundingBox.max.y - boundingBox.min.y) / 2 + boundingBox.min.y, (boundingBox.max.z - boundingBox.min.z) / 2 + boundingBox.min.z]; object1.position.x -= center[0]; object1.position.y -= center[1] - (boundingBox.max.y - boundingBox.min.y) / 2; object1.position.z -= center[2]; object1.position.y += newAltitude; if (element.selected) { // if object is selected // save object transform info/// var scalevec = new Three.Vector3(object1.scale.x, object1.scale.y, object1.scale.z); var posVec = new Three.Vector3(object1.position.x, object1.position.y, object1.position.z); object.scale.set(1 * newWidth / sizeinfo.width, 1 * newHeight / sizeinfo.height, 1 * newDepth / sizeinfo.depth); object1.position.set(0, 0, 0); object1.rotation.set(0, 0, 0); //let box = new Three.BoxHelper(object, 0xffffff); //box.material.lineWidth = 5; //box.renderOrder = 1000; //box.material.depthTest = false; //object.add(box); var _boundingBox = GeomUtils.baseBox3FromObject(object); var max = _boundingBox.max; var min = _boundingBox.min; var radius = Math.sqrt((_boundingBox.max.x - _boundingBox.min.x) * (_boundingBox.max.x - _boundingBox.min.x) + (_boundingBox.max.z - _boundingBox.min.z) * (_boundingBox.max.z - _boundingBox.min.z)) / 2; var moveBox = new Three.BoxGeometry(max.x - min.x, max.y - min.y, max.z - min.z); // translate Object var controlGeom = GeomUtils.controlGeom(); // rotate Object ////////// var rotGeom = GeomUtils.rotGeoms(radius + 0.05); // ////////////////////////////////// // upwards Geometry/////////// Move up Object var upwardsGeom = GeomUtils.upwardsGeom(); // vertical line - 4 lines around object////////////////////////// var vLineGeom = new Three.BufferGeometry(); var vertices = [(max.x - min.x) / 2 + min.x, 0, max.z, (max.x - min.x) / 2 + min.x, 0, max.z + 1.3]; vLineGeom.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices), 3)); var vLineGeom1 = new Three.BufferGeometry(); var vertices1 = [(max.x - min.x) / 2 + min.x, 0, min.z, (max.x - min.x) / 2 + min.x, 0, min.z - 1.3]; vLineGeom1.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices1), 3)); var vLineGeom2 = new Three.BufferGeometry(); var vertices2 = [max.x, 0, max.z - (max.z - min.z) / 2, max.x + 1.3, 0, max.z - (max.z - min.z) / 2]; vLineGeom2.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices2), 3)); var vLineGeom3 = new Three.BufferGeometry(); var vertices3 = [min.x, 0, max.z - (max.z - min.z) / 2, min.x - 1.3, 0, max.z - (max.z - min.z) / 2]; vLineGeom3.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices3), 3)); // /////////////////////////////////////// // set names of transform object var rotFillObj = new Three.Mesh(rotGeom.rotFill, new Three.MeshPhongMaterial({ color: new Three.Color(0x000000).convertLinearToSRGB(), side: Three.DoubleSide, colorWrite: true })); var rotStrokeObj = new Three.Line(rotGeom.rotStroke, new Three.LineBasicMaterial({ color: new Three.Color(0xffffff).convertLinearToSRGB(), colorWrite: true })); rotFillObj.name = 'rotate'; var upObj = new Three.Mesh(upwardsGeom, new Three.MeshBasicMaterial({ color: new Three.Color(0xffffff).convertLinearToSRGB(), side: Three.DoubleSide })); upObj.name = 'transUp'; var mBox = new Three.Mesh(moveBox, new Three.MeshBasicMaterial({ color: new Three.Color(0xdd6699).convertLinearToSRGB(), side: Three.DoubleSide, transparent: true, opacity: 0.4 })); var _color = new Three.Color(SHADE_DARK_PURPLE_COLOR).convertLinearToSRGB(); var vLine = new Three.Line(vLineGeom, new Three.LineBasicMaterial({ color: _color })); var vLine1 = new Three.Line(vLineGeom1, new Three.LineBasicMaterial({ color: _color })); var vLine2 = new Three.Line(vLineGeom2, new Three.LineBasicMaterial({ color: _color })); var vLine3 = new Three.Line(vLineGeom3, new Three.LineBasicMaterial({ color: _color })); vLine.renderOrder = 1; vLine1.renderOrder = 1; vLine2.renderOrder = 1; vLine3.renderOrder = 1; vLine.material.transparent = true; vLine1.material.transparent = true; vLine2.material.transparent = true; vLine3.material.transparent = true; vLine.material.depthTest = false; vLine1.material.depthTest = false; vLine2.material.depthTest = false; vLine3.material.depthTest = false; // translate vector to center of object var uVec = new Three.Vector3(-posVec.x / scalevec.x, -posVec.y / scalevec.y, -posVec.z / scalevec.z); vLine.translateY(0.1); vLine1.translateY(0.1); vLine2.translateY(0.1); vLine3.translateY(0.1); //rotObj.translateOnAxis(uVec, 1); upObj.translateOnAxis(uVec, 1); upObj.translateY(max.y - min.y); mBox.name = 'TransformBox'; mBox.translateOnAxis(new Three.Vector3(uVec.x, uVec.y + (max.y - min.y) / 2, uVec.z), 1); mBox.scale.set(1.01, 1.01, 1.01); // other side rotate object var rotFillObj1 = rotFillObj.clone(); var rotStrokeObj1 = rotStrokeObj.clone(); rotFillObj1.rotateY(Math.PI); rotStrokeObj1.rotateY(Math.PI); rotFillObj.translateY(0.1); rotFillObj1.translateY(0.1); rotStrokeObj.translateY(0.1); rotStrokeObj1.translateY(0.1); // assets Objects group includes rotate objects... var asrtObj = new Three.Group(); // asrtObj.add(rotFillObj); // asrtObj.add(rotFillObj1); // asrtObj.add(rotStrokeObj); // asrtObj.add(rotStrokeObj1); //asrtObj.add(upObj); asrtObj.add(vLine); asrtObj.add(vLine1); asrtObj.add(vLine2); asrtObj.add(vLine3); mBox.visible = false; asrtObj.add(mBox); asrtObj.scale.set(1 / object.scale.x, object.scale.y, 1 / object.scale.z); //asrtObj.translateY(newAltitude / scalevec.y); asrtObj.name = 'TransformGizmo'; // add assets Objects Group object1.add(asrtObj); // recover objects transform object1.position.x = posVec.x; object1.position.y = posVec.y; object1.position.z = posVec.z; object1.scale.set(scalevec.x, scalevec.y, scalevec.z); setTimeout(function () { SceneCreator.getDistances(layer); }, 100); } var flip_doorhandle = element.properties.get('flip_doorhandle'); if (flip_doorhandle) { SceneCreator.updateDoorHandleMesh(element, object1, true); } object1.traverse(function (obj) { if (obj.type === OBJTYPE_MESH) { var name = obj.name; if (name.match(/_door_.*_glass_/)) { var material = new Three.MeshPhysicalMaterial({ roughness: 0, transmission: 1, thickness: 0.5, // Add refraction! transparency: 0.8 }); obj.material = material; } else if (name.startsWith('sink_')) { // texture = loadTexture('/assets/img/texture/steel.jpg'); var _material; // Get color from name if (name.includes('black') || name.includes('white')) { var _color2; if (name.includes('black')) { _color2 = new Three.Color(0x555555).convertLinearToSRGB(); } else { _color2 = 0xffffff; } _material = new Three.MeshPhysicalMaterial({ roughness: 0.5, metalness: 0, // transmission: 1, transparent: true, opacity: 1, thickness: 0.5, // Add refraction! // transparency: 0.8, color: _color2, side: Three.DoubleSide }); } else { // if (name.includes('chrome')) { _material = new Three.MeshPhysicalMaterial({ roughness: 0.2, metalness: 1, reflectivity: 0.5, color: new Three.Color(0xdddddd).convertLinearToSRGB() }); } obj.material = _material; } } if (element.toJS().properties.open_doors) { var open_doors = element.toJS().properties.open_doors; var object_match = obj.name.match(/\d_(interior_drawer[^LR1-9]*)(_[LR1-9])?$/) || obj.name.match(matchStr); if (object_match && object_match.length > 2) { var isDoor = object_match[1] === 'door'; if (isDoor) { var offsetData = object1.userData.door_animate_offset[obj.name]; // Open Door animateDoor(offsetData, obj, open_doors, element.toJS(), is_corner, 'Opened2D'); } else { // Open Drawer translateDrawer(element.toJS(), obj, open_doors, 'Opened2D'); } } } }); return object1; }; // keys in structure var keys = Object.keys(structure); // if exist in cached Objects if (element.type + color + 'doorStyle' + JSON.stringify(doorStyles.toJS()) + element.counterTop.uri in cachedObject) { var _objGroup = cachedObject[element.type + color + 'doorStyle' + JSON.stringify(doorStyles.toJS())].clone(); return Promise.resolve(onLoadItem(_objGroup.clone())); } // base Object///// var objGroup = null; var _loadGLTFs = function loadGLTFs(i) { if (keys[i] === 'animation') { // if animation info i++; return _loadGLTFs(i); } if (keys[i] === 'placeholders') { // if placeholders group i++; return _loadGLTFs(i); } if (i === keys.length) { // if end of keys cachedObject[element.type + color + 'doorStyle' + JSON.stringify(doorStyles.toJS())] = objGroup.clone(); //register to cachedObject return onLoadItem(cachedObject[element.type + color + 'doorStyle' + JSON.stringify(doorStyles.toJS())].clone()); } if (keys[i] === 'base') { // if base Objects i++; return _loadGLTFs(i); } var phsArray = []; var placeholderStructure = placeholders[keys[i]]; if (placeholderStructure == undefined || placeholderStructure.length == 0) { i++; return _loadGLTFs(i); } for (var j = 0; j < placeholderStructure.length; j++) { var phData = placeholderStructure[j]; var phs = phData.split('/'); var temp = phData.split('/'); // placeholder remake//////////////// for (var k = 0; k < phs.length; k++) { if (phs[k] in placeholders) { var placeholderphs = placeholders[phs[k]]; var key = placeholderStructure.length / placeholderphs.length; phs[k] = placeholderphs[Math.floor(j / key)]; var splitedData = phs[k].split('/'); if (splitedData.length > 1) { phs[k] = splitedData[splitedData.length - 1]; for (var m = splitedData.length - 2; m >= 0; m--) { phs.unshift(splitedData[m]); temp.unshift(splitedData[m]); } } k = -1; continue; } if (phs[k].indexOf('ph') == -1) { var _url = structure[temp[k - 1]]; if (temp[k - 1] + '_doorStyle' + element.type + 'doorStyle' + JSON.stringify(doorStyles.toJS()) in structure) { if (structure[temp[k - 1] + '_doorStyle' + element.type + 'doorStyle' + JSON.stringify(doorStyles.toJS())] != null) { _url = structure[temp[k - 1] + '_doorStyle' + element.type + 'doorStyle' + JSON.stringify(doorStyles.toJS())]; } } if (_typeof(_url) == Array) _url = _url[0]; var uData = _url.split('/'); uData = uData[uData.length - 1]; uData = uData.slice(0, -5); var datas = uData.split('_'); uData = datas[1]; for (var _i = 2; _i < datas.length; _i++) { uData += '_'; uData += datas[_i]; } uData = mainName.replace('main', uData); phs[k] = 'ph_' + uData + '_' + phs[k]; } } phsArray.push(phs); } var url = structure[keys[i]]; var normalMap = ''; var urlData = url.split('/'); for (var _j = 0; _j < element.submodule.size; _j++) { var replaceUrlData = element.submodule.get(_j).split('/'); if (urlData.includes(replaceUrlData[replaceUrlData.length - 2])) { url = element.submodule.get(_j); break; } } for (var _j2 = 0; _j2 < element.normalMap.size; _j2++) { var normalMapData = element.normalMap.get(_j2).split('/'); if (urlData.includes(normalMapData[normalMapData.length - 2])) { normalMap = element.normalMap.get(_j2); break; } } // replace submodule gltf file // if (placeholderTree.length > 0) { if (phsArray.length > 0) { // let loadUrl = dirName + url; var loadUrl = url; if (doorStyles.get(keys[i] + '_gltf') != undefined) { loadUrl = doorStyles.get(keys[i] + '_gltf'); structure[keys[i] + '_doorStyle' + element.type + 'doorStyle' + JSON.stringify(doorStyles.toJS())] = loadUrl; } else { structure[keys[i] + '_doorStyle' + element.type + 'doorStyle' + JSON.stringify(doorStyles.toJS())] = null; } return loadGLTF(loadUrl).then(function (object) { if (normalMap !== '') { var normalUrl = normalMap.split('.')[0] + '-normal.' + normalMap.split('.')[1]; var t = loadTexture(normalMap); var _m = loadTexture(normalUrl); var mat2 = new Three.MeshStandardMaterial({ metalness: glossness === 1 ? params.metalness : params.metalness_glossy, roughness: glossness || params.roughness }); mat2.map = t; mat2.normalMap = _m; // mat2.envMap = textureCube; for (var _j3 = 0; _j3 < object.children.length; _j3++) { if (object.children[_j3].type === OBJTYPE_MESH) { object.children[_j3].material = mat2; object.children[_j3].receiveShadow = true; } } } // set Door Style//// if (doorStyles != null) if (doorStyles.get(keys[i]) != undefined) { // let normalMap = "catalog/items/doorstyle/" + doorStyles.get(keys[i]); var _normalMap = doorStyles.get(keys[i]); var _mat; if (_normalMap === '') { var examplecolor = new Three.Color(parseInt(color.slice(1), 16)).convertLinearToSRGB(); _mat = new Three.MeshStandardMaterial({ color: examplecolor, metalness: glossness === 1 ? params.metalness : params.metalness_glossy, roughness: glossness || params.roughness }); } else { var _t = loadTexture(_normalMap); _mat = new Three.MeshStandardMaterial({ // NOTE : this is for cabinets (wood) frontface metalness: 0.1, roughness: 0.5 // metalness: glossness === 1 ? params.metalness : params.metalness_glossy, // roughness: glossness || params.roughness }); _mat.map = _t; } // mat2.envMap = textureCube; for (var _j4 = 0; _j4 < object.children.length; _j4++) { if (object.children[_j4].type === OBJTYPE_MESH) { object.children[_j4].material = _mat; object.children[_j4].receiveShadow = true; object.children[_j4].castShadow = true; !object.children[_j4].name.includes('handle') && addEdgesToMesh(object.children[_j4]); } else if (!object.children[_j4].name.startsWith('ph_') && object.children[_j4].type === OBJTYPE_GROUP) { object.children[_j4].traverse(function (prim) { prim.material = _mat; prim.receiveShadow = true; }); } } } else { var _mat2 = new Three.MeshStandardMaterial({ metalness: glossness === 1 ? params.metalness : params.metalness_glossy, roughness: glossness || params.roughness }); // mat2.envMap = textureCube; for (var _j5 = 0; _j5 < object.children.length; _j5++) { if (object.children[_j5].type === OBJTYPE_MESH) { object.children[_j5].material = _mat2; object.children[_j5].receiveShadow = true; } } } for (var _i2 = 0; _i2 < phsArray.length; _i2++) { var _phs = phsArray[_i2]; var parent = objGroup; for (var _j6 = 0; _j6 < _phs.length; _j6++) { var placeholder = _phs[_j6]; for (var _k = 0; _k < ((_parent = parent) === null || _parent === void 0 ? void 0 : _parent.children.length); _k++) { var _parent; if (_j6 != _phs.length - 1) { if (parent.children[_k].name == placeholder) { parent = parent.children[_k].children[0]; break; } } else { if (parent.children[_k].name == placeholder) { var tmp = object.clone(); if (placeholder.includes('drawer_door') && placeholder.includes('_handle')) { tmp.rotateZ(Math.PI / 2); } if (placeholder.includes('_handle') && tmp.children[0].type === OBJTYPE_MESH) { // NOTE: change metalness of handle tmp.children[0].material.metalness = 1; // handleMaterial.metalness || 0.2; tmp.children[0].material.roughness = handleMaterial.roughness || 0.1; //tmp.children[0].material.map = loadTexture('catalog/areas/area/textures/grass.jpg'); } parent.children[_k].add(tmp); } } } } } }, function (reason) { console.log('loadGLTF failed for reason:', reason); }).then(function () { i++; return _loadGLTFs(i); }); } }; return loadGLTF(structure['base']).then(function (object) { object.name = 'MainObject'; object.receiveShadow = true; objGroup = object; if (doorStyles != null) if (doorStyles.get('base') != undefined) { var normalMap = doorStyles.get('base'); if (counterTop.uri === undefined) { try { counterTop = counterTop.toJS(); } catch (error) { console.log(error); } } if (counterTop.uri === undefined && layer.toJS().counterTop.uri !== undefined) { counterTop.uri = layer.toJS().counterTop.uri; } var countTopMap = counterTop.uri; var interiorMap = doorStyles.get('interior'); var countT = loadTexture(countTopMap); countT.wrapS = Three.RepeatWrapping; countT.wrapT = Three.RepeatWrapping; countT.repeat.set(1, 1); var examplecolor = new Three.Color(parseInt(color.slice(1), 16)).convertLinearToSRGB(); var mat2 = null, mat3 = null, mat4 = null; if (normalMap === '') { mat2 = new Three.MeshStandardMaterial({ color: examplecolor, metalness: glossness === 1 ? params.metalness : params.metalness_glossy, roughness: glossness || params.roughness }); } else { mat2 = new Three.MeshStandardMaterial({ // TODO: changes in metalness and roughness of base_main (cabinet wood) metalness: 0.1, roughness: 0.5 // metalness: glossness === 1 ? params.metalness : params.metalness_glossy, // roughness: glossness || params.roughness }); } // mat2.envMap = textureCube; if (normalMap !== '') { var t = loadTexture(normalMap); mat2.map = t; } if (normalMap === '') { mat3 = new Three.MeshStandardMaterial({ // color: examplecolor, metalness: counterTop.metalness, roughness: counterTop.roughness }); } else { mat3 = new Three.MeshStandardMaterial({ // metalness: counterTop.metalness, // roughness: counterTop.roughness metalness: 0.3, roughness: 0.8 }); } mat3.map = countT; // mat3.envMap = textureCube; mat4 = new Three.MeshStandardMaterial({ metalness: params.metalness, roughness: params.roughness }); mat4.map = loadTexture(interiorMap); for (var j = 0; j < object.children.length; j++) { if (object.children[j].name.includes('main')) {} if (object.children[j].name.includes('countertop')) { object.children[j].material = mat3; object.children[j].receiveShadow = true; object.children[j].castShadow = true; addEdgesToMesh(object.children[j]); } else if (object.children[j].name.includes('_interior_')) { object.children[j].material = mat4; } else if (object.children[j].type === OBJTYPE_MESH) { object.children[j].material = mat2; object.children[j].receiveShadow = true; object.children[j].castShadow = true; } } } }, function (reason) { console.log('loadGLTF failed for reason:', reason); objGroup = GeomUtils.emptyBoxHolder(newWidth, newHeight, newDepth); }).then(function () { return _loadGLTFs(0); }); } // render 3d appliance function //////////////////////////////// export function render3DApplianceItem(element, layer, scene, sizeinfo, structure_json) { var mode = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null; var structure = structure_json; var applianceMaterial = element.applianceMaterial; if (applianceMaterial.metalness == undefined) applianceMaterial = applianceMaterial.toJS(); var onLoadItem = function onLoadItem(object) { var newAltitude = element.properties.get('altitude').get('_length'); var newUnit = element.properties.get('altitude').get('_unit') || 'in'; newAltitude = convert(newAltitude).from(newUnit).to(scene.unit); var newWidth = element.properties.get('width').get('_length'); var newWidthUnit = element.properties.get('width').get('_unit') || 'in'; newWidth = convert(newWidth).from(newWidthUnit).to('in'); var newHeight = element.properties.get('height').get('_length'); var newHeightUnit = element.properties.get('height').get('_unit') || 'in'; newHeight = convert(newHeight).from(newHeightUnit).to('in'); var newDepth = element.properties.get('depth').get('_length'); var newDepthUnit = element.properties.get('depth').get('_unit') || 'in'; newDepth = convert(newDepth).from(newDepthUnit).to('in'); object.scale.set(100 * newWidth / sizeinfo.width, 100 * newHeight / sizeinfo.height, 100 * newDepth / sizeinfo.depth); // Normalize the origin of the object var boundingBox = new Three.Box3().setFromObject(object); object.userData = boundingBox; var center = [(boundingBox.max.x - boundingBox.min.x) / 2 + boundingBox.min.x, (boundingBox.max.y - boundingBox.min.y) / 2 + boundingBox.min.y, (boundingBox.max.z - boundingBox.min.z) / 2 + boundingBox.min.z]; object.position.x -= center[0]; object.position.y -= center[1] - (boundingBox.max.y - boundingBox.min.y) / 2; object.position.z -= center[2]; object.position.y += newAltitude; object.traverse(function (obj) { if (obj.type === OBJTYPE_MESH) { var name = obj.name; var texture, textureLoader = new Three.TextureLoader(); if (name.includes('_black')) { obj.material.roughness = 0.4; obj.material.metalness = 1.0; obj.material.color = new Three.Color(0, 0, 0); obj.castShadow = true; obj.receiveShadow = true; return object; } else if (name.includes('_wood')) { texture = loadTexture('/assets/img/texture/wood.jpg'); } else if (name.includes('_glass')) { // texture = loadTexture('/assets/img/texture/glass.jpg'); var material = new Three.MeshPhysicalMaterial({ transparent: true, opacity: 0.5, roughness: 0, transmission: 1, thickness: 0.5, // Add refraction! transparency: 0.8 }); obj.material = material; obj.castShadow = true; obj.receiveShadow = true; return object; } else if (name.includes('_steel')) { // texture = loadTexture('/assets/img/texture/steel.jpg'); var _material2 = new Three.MeshPhysicalMaterial({ roughness: 0.2, metalness: 0.5, reflectivity: 0.5, color: new Three.Color(0xdddddd).convertLinearToSRGB() }); obj.material = _material2; obj.castShadow = true; obj.receiveShadow = true; return object; } var mat = new Three.MeshStandardMaterial({ metalness: 0.1, roughness: 0.9, map: texture }); obj.material = mat; } }); if (element.selected) { // if object is selected // save object transform info/// var scalevec = new Three.Vector3(object.scale.x, object.scale.y, object.scale.z); var posVec = new Three.Vector3(object.position.x, object.position.y, object.position.z); object.scale.set(1 * newWidth / sizeinfo.width, 1 * newHeight / sizeinfo.height, 1 * newDepth / sizeinfo.depth); object.position.set(0, 0, 0); object.rotation.set(0, 0, 0); var _boundingBox2 = new Three.Box3().setFromObject(object); var max = _boundingBox2.max; var min = _boundingBox2.min; var radius = Math.sqrt((_boundingBox2.max.x - _boundingBox2.min.x) * (_boundingBox2.max.x - _boundingBox2.min.x) + (_boundingBox2.max.z - _boundingBox2.min.z) * (_boundingBox2.max.z - _boundingBox2.min.z)) / 2; var moveBox = new Three.BoxGeometry(max.x - min.x, max.y - min.y, max.z - min.z); // translate Object var controlGeom = GeomUtils.controlGeom(); // //////////////////////// // rotate Object ////////// var rotGeom = GeomUtils.rotGeoms(radius + 0.05); // ////////////////////////////////// // upwards Geometry/////////// Move up Object var upwardsGeom = GeomUtils.upwardsGeom(); // /////////////////////////////////////// // vertical line - 4 lines around object////////////////////////// var vLineGeom = new Three.BufferGeometry(); var vertices = [(max.x - min.x) / 2 + min.x, 0, min.z, (max.x - min.x) / 2 + min.x, 0, min.z + 1.3]; vLineGeom.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices), 3)); var vLineGeom1 = new Three.BufferGeometry(); var vertices1 = [(max.x - min.x) / 2 + min.x, 0, min.z, (max.x - min.x) / 2 + min.x, 0, min.z - 1.3]; vLineGeom1.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices1), 3)); var vLineGeom2 = new Three.BufferGeometry(); var vertices2 = [max.x, 0, max.z - (max.z - min.z) / 2, max.x + 1.3, 0, max.z - (max.z - min.z) / 2]; vLineGeom1.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices2), 3)); var vLineGeom3 = new Three.BufferGeometry(); var vertices3 = [min.x, 0, max.z - (max.z - min.z) / 2, min.x - 1.3, 0, max.z - (max.z - min.z) / 2]; vLineGeom1.setAttribute('position', new Three.BufferAttribute(new Float32Array(vertices3), 3)); // /////////////////////////////////////// // set names of transform object var rotFillObj = new Three.Mesh(rotGeom.rotFill, new Three.MeshPhongMaterial({ color: 0x000000, side: Three.DoubleSide