kitchen-simulator
Version:
It is a kitchen simulator (self-contained micro-frontend).
181 lines (173 loc) • 6.38 kB
JavaScript
import * as Three from 'three';
import { Box3, Mesh, MeshBasicMaterial, MeshPhysicalMaterial, RepeatWrapping, Shape, TextureLoader, Vector2 } from 'three';
import * as SharedStyle from "../../shared-style";
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader';
var params = {
envMap: 'HDR',
roughness: 0.9,
metalness: 0.8,
exposure: 1.0
// debug: false
};
/**
* 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 TextureLoader();
if (texture) {
material.map = loader.load(texture.uri);
material.map.colorSpace = Three.SRGBColorSpace;
material.needsUpdate = true;
material.map.wrapS = RepeatWrapping;
material.map.wrapT = RepeatWrapping;
material.map.repeat.set(length * texture.lengthRepeatScale, height * texture.heightRepeatScale);
if (texture.normal) {
material.normalMap = loader.load(texture.normal.uri);
material.normalScale = new Vector2(texture.normal.normalScaleX, texture.normal.normalScaleY);
material.normalMap.wrapS = RepeatWrapping;
material.normalMap.wrapT = RepeatWrapping;
material.normalMap.repeat.set(length * texture.normal.lengthRepeatScale, height * texture.normal.heightRepeatScale);
}
}
};
/**
* Function that assign UV coordinates to a geometry
* @param geometry
*/
var assignUVs = function assignUVs(geometry) {
geometry.computeBoundingBox();
var _geometry$boundingBox = geometry.boundingBox,
min = _geometry$boundingBox.min,
max = _geometry$boundingBox.max;
var offset = new Vector2(0 - min.x, 0 - min.y);
var range = new Vector2(max.x - min.x, max.y - min.y);
var uvArray = [];
var position = geometry.attributes.position;
for (var i = 0; i < position.count; i += 3) {
var x1 = position.getX(i);
var y1 = position.getY(i);
var x2 = position.getX(i + 1);
var y2 = position.getY(i + 1);
var x3 = position.getX(i + 2);
var y3 = position.getY(i + 2);
uvArray.push((x1 + offset.x) / range.x, (y1 + offset.y) / range.y, (x2 + offset.x) / range.x, (y2 + offset.y) / range.y, (x3 + offset.x) / range.x, (y3 + offset.y) / range.y);
}
geometry.setAttribute('uv', new Three.BufferAttribute(new Float32Array(uvArray), 2));
geometry.needsUpdate = true;
};
export function createArea(element, layer, scene, textures) {
var vertices = [];
element.vertices.forEach(function (vertexID) {
vertices.push(layer.vertices.get(vertexID));
});
var texture = element.texture;
texture.lengthRepeatScale = 0.01;
texture.heightRepeatScale = 0.01;
var color = element.properties.get('patternColor');
if (element.selected) {
color = SharedStyle.AREA_MESH_COLOR.selected;
} else {
color = SharedStyle.AREA_MESH_COLOR.unselected;
}
if (texture.uri === undefined || texture.uri == '') {
texture.uri = layer.floorStyle.uri;
}
var shape = new Shape();
shape.moveTo(vertices[0].x, vertices[0].y);
for (var i = 1; i < vertices.length; i++) {
shape.lineTo(vertices[i].x, vertices[i].y);
}
function loadFloorENV() {
return new RGBELoader().load('/assets/Window.hdr', function (texture) {
texture.mapping = Three.EquirectangularReflectionMapping;
return texture;
});
}
var floorENV = loadFloorENV();
var loader = new TextureLoader();
var areaMaterial = new MeshPhysicalMaterial({
side: Three.DoubleSide,
metalness: texture.metalness,
roughness: 0.3,
envMap: floorENV,
envMapIntensity: 1.8,
specularIntensity: 0.4,
map: loader.load(texture.uri)
});
/* Create holes for the area */
element.holes.forEach(function (holeID) {
var holeCoords = [];
layer.getIn(['areas', holeID, 'vertices']).forEach(function (vertexID) {
var _layer$getIn = layer.getIn(['vertices', vertexID]),
x = _layer$getIn.x,
y = _layer$getIn.y;
holeCoords.push([x, y]);
});
holeCoords = holeCoords.reverse();
var holeShape = createShape(holeCoords);
shape.holes.push(holeShape);
});
// This is extrude floor mesh
var extrudeSettings = {
depth: -3,
bevelEnabled: false
};
var shapeGeometry = new Three.ExtrudeGeometry(shape, extrudeSettings);
assignUVs(shapeGeometry);
var boundingBox = new Box3().setFromObject(new Mesh(shapeGeometry, new MeshBasicMaterial()));
var width = boundingBox.max.x - boundingBox.min.x;
var height = boundingBox.max.y - boundingBox.min.y;
var texture_unit = 70 * 2.54; // 70 inch
applyTexture(areaMaterial, texture, width / texture_unit * 100, height / texture_unit * 100);
var area = new Mesh(shapeGeometry, areaMaterial);
area.rotation.x -= Math.PI / 2;
area.receiveShadow = true;
area.name = 'floor';
// This mesh is use for creating ceiling mesh
var shapeGeometry2 = new Three.ShapeGeometry(shape);
var area2 = new Mesh(shapeGeometry2, new MeshBasicMaterial({
transparent: true,
opacity: 0.0
}));
area2.castShadow = true;
area2.rotation.x -= Math.PI / 2;
area2.receiveShadow = true;
area2.name = 'floorSupport';
var floorSupport = area2.clone();
area.userData.floorSupport = floorSupport;
return Promise.resolve(area);
}
export function updatedArea(element, layer, scene, textures, mesh, oldElement, differences, selfDestroy, selfBuild) {
var noPerf = function noPerf() {
selfDestroy();
return selfBuild();
};
var floor = mesh.getObjectByName('floor');
floor.receiveShadow = true;
if (differences[0] == 'selected') {
var color = element.selected ? SharedStyle.AREA_MESH_COLOR.selected : SharedStyle.AREA_MESH_COLOR.unselected;
floor.material.color.set(color);
} else if (differences[0] == 'properties') {
if (differences[1] === 'texture') {
return noPerf();
}
} else return noPerf();
return Promise.resolve(mesh);
}
/**
* This function will create a shape given a list of coordinates
* @param shapeCoords
* @returns {Shape}
*/
var createShape = function createShape(shapeCoords) {
var shape = new Shape();
shape.moveTo(shapeCoords[0][0], shapeCoords[0][1]);
for (var i = 1; i < shapeCoords.length; i++) {
shape.lineTo(shapeCoords[i][0], shapeCoords[i][1]);
}
return shape;
};