Categories

# Three.js development room (three)

The first three did not relate to the engine room, just a few fragmented knowledge, this section we began formal painting exterior walls.

First, I obviously understand what is the wall? In fact, that white is a rectangular, long uncertain, wide general is 40cm, which is two meters high, which is a simple wall, of course, a lot of the walls are windows, doors what, in fact, that is fixed in the cuboid location dig a hole, then put what we need parties, such as doors, windows.

We need a top view of a room for analysis before painting the wall, like on the picture below this room

(Picture from the network)

As shown in the picture, like, this room is very standard, is a very standard rectangular room, length 900cm, width 600cm, is the wall on the left side of the glass partition, there is a door,

Well, we can start to dry, we need to initialize a room Json structure and layout, pay attention to doors and windows can not overlap, there is a door where the door windows need to be divided into left and right door two arrays (of course, you can also write determining a plurality of operating, but more troublesome).

```{
houseWidth: 900,   // 房间长度
houseHeight: 600,  // 房间宽
angle: 45,         // 房间朝向
wall: [
{position:{x: 0, y: 0, endX: 900, endY: 0}, door: {isDoor: false}, windows: {isWindows:false}},
{position:{x: 900, y: 0, endX: 900, endY: 600}, door: {isDoor: false},  windows: {isWindows: false}},
{position:{x: 0, y: 600, endX: 900, endY: 600}, door: {isDoor: false}, windows: {isWindows:false}},
{position:{x: 0, y: 0, endX: 0, endY: 600}, door: {isDoor: true, doorNum: 2, door_PointL [{x: 0, y: 200, endX: 0, endY: 400, doorDirection: 2}]},  windows: {isWindows: true, windows__Point: [{x: 0, y: 0, endX: 0, endY: 150}, {x: 0, y: 450, endX: 0, endY: 600}]}}
]
},
```

Then we started painting the floor, we will present to do the same floor and room size:

```    createFloor() {
let _self = this;
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(8, 8);
var floorGeometry = new THREE.BoxGeometry(this.houseWidth, this.houseHeight, 1);
var floorMaterial = new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide
});
floorMaterial.opacity = 1;
floorMaterial.transparent = true;
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = 0;
floor.rotation.x = Math.PI / 2;

})
}
```

FIG execution results are as follows:

Purple is the color I added to the entire Html, mainly easy viewing floor, then we started painting the wall, before we initialize a painted wall painted rectangular (window width and height are by default 1) function:

```initLambert() {
var cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
this.initLambertMod = new THREE.Mesh(cubeGeometry, this.wallMatArray);
};
```

After a good package when we would not have painted wall painting a wall to create a new geometry and material of each, we only need to clone we have just initiated the wall like

After we formally package having a specific length, angle and position on wall

```/**
* 画长方体
* @param { 长方体的长度 } width
* @param { 长方体的高度 } height
* @param { 长方体的厚度 } depth
* @param { 长方体旋转的角度 } angle
* @param { 长方体的材质 } material
* @param { 长方体的X轴坐标 } x
* @param { 长方体的Y轴坐标 } y
* @param { 长方体的Z轴坐标 } z
*/
createLambert(width, height, depth, angle, material, x, y, z) {
var code = this.initLambertMod.clone();
code.scale.set(width, height, depth)
code.position.set(x, y, z);
code.rotation.set(0, angle * Math.PI, 0); //-逆时针旋转,+顺时针
return code;
};
```

In this way we will have a length and breadth, rectangular direction, position to draw out,

Just drawn is not enough, we need to link up data and models, we first this.data.wall specific information to traverse to get it the way it is, whether there are windows and doors, walls start and end points, and know the starting point end point, we can calculate how long this wall specifically, there is this wall angle

Above, we can have more than two points to derive information that line

Length: Math.sqrt (Math.pow (Math.abs (300 -0), 2) + Math.pow (Math.abs (0 -300), 2));

Angle: Math.asin ((300- 0) / (0 – 300)) / Math.PI

So that we know the specific information on that line, here we can draw a wall:

```createHouseWall() {
this.data.wall.map((item) => {
var position = item.position;
var w = position.endX - position.x;
var h = position.endY - position.y;
var x = (position.x + w / 2) - (this.houseWidth / 2);
var z = (position.y + h / 2) - (this.houseHeight / 2);
var width = Math.sqrt(Math.pow(w, 2) + Math.pow(h, 2));
var angle = Math.asin(h / width) / Math.PI;

if (item.windows.isWindows || item.door.isDoor) {
// 有窗户或有门或都有
} else {
// 没门、没窗户
let code = this.createLambert(width, 200, 10, angle, this.matArrayB, x, 100, z);
}
});
};
```

We can see the complete implementation of such results the following figure

Short of a wall, above both doors have windows, then we have to make both door windows, offer a picture look cool

To achieve this, we must first package a geometric ti cutting function:

```/**
* 几何体裁切函数
* @param { 被采裁切的集合体 } bsp
* @param { 要裁掉的集合体 } less_bsp
* @param { 区分是机房的墙还是机柜裁切的 } mat
*/
returnResultBsp(bsp, less_bsp, mat) {
switch (mat) {
case 1:
var material = new THREE.MeshPhongMaterial({
color: 0x9cb2d1,
specular: 0x9cb2d1,
shininess: 30,
transparent: true,
opacity: 1
});
break;
case 2:
var material = new THREE.MeshPhongMaterial({
color: 0x42474c,
specular: 0xafc0ca,
shininess: 30,
transparent: true,
opacity: 1
});
break;
default:
}

var sphere1BSP = new ThreeBSP(bsp);
var cube2BSP = new ThreeBSP(less_bsp); //0x9cb2d1 淡紫,0xC3C3C3 白灰 , 0xafc0ca灰
var resultBSP = sphere1BSP.subtract(cube2BSP);
var result = resultBSP.toMesh(material);
result.geometry.computeFaceNormals(); //重新计算几何体侧面法向量
result.geometry.computeVertexNormals();
result.material.needsUpdate = true; //更新纹理
result.geometry.buffersNeedUpdate = true;
result.geometry.uvsNeedUpdate = true;
if (mat == 2) {
result.nature = "Cabinet";
}
return result;
};
```

After we started to have a wall with a door or window begins processing, finishing first data, the data can be organized into what I can handle the simplest of

```createHouseWall() {
this.data.wall.map((item) => {
var position = item.position;
var w = position.endX - position.x;
var h = position.endY - position.y;
var x = (position.x + w / 2) - (this.houseWidth / 2);
var z = (position.y + h / 2) - (this.houseHeight / 2);
var width = Math.sqrt(Math.pow(w, 2) + Math.pow(h, 2));
var angle = Math.asin(h / width) / Math.PI;

if (item.windows.isWindows || item.door.isDoor) {
// 有窗户或有门或都有
// 当然判断里面还是分开成有门或者有窗户，但互不干涉
var window__List = [];   // 盛放窗户的数组
var door__List = [];       // 盛放门的数组
if (item.windows.isWindows) {
item.windows.windows__Point.map((windows__Point, window__index) => {
let window__Json = {};
let windows__w = windows__Point.endX - windows__Point.x;                 let windows__h = windows__Point.endY - windows__Point.y;
window__Json.window__x = (windows__Point.x + windows__w / 2) - (this.houseWidth / 2);
window__Json.window__z = (windows__Point.y + windows__h / 2) - (this.houseHeight / 2);
window__Json.window__width = Math.sqrt(Math.pow(windows__w, 2) + Math.pow(windows__h, 2));
window__Json.w_Height = 120;
window__Json.window__y = 100;
window__List.push(window__Json);
});
}
if (item.door.isDoor) {
var door__num = item.door.doorNum || 1;
item.door.door_Point.map((door__Point, door__index) => {
var door__Json = {};
var windows__w = door__Point.endX - door__Point.x;
var windows__h = door__Point.endY - door__Point.y;
if (door__num == 2) {
let doubleDoorList = [];
for (var i = 0; i < 2; i++) {
door__Json = {};
door__Json.door__x = (door__Point.x + windows__w / 2) - (this.houseWidth / 2) + (door__Point.endX - door__Point.x) / 2 * i;
door__Json.door__z = (door__Point.y + windows__h / 2) - (this.houseHeight / 2) + (door__Point.endY - door__Point.y) / 2 * i;
door__Json.door__width = (Math.sqrt(Math.pow(windows__w, 2) + Math.pow(windows__h, 2))) / 2;
door__Json.door__height = 180;
door__Json.door__y = 100;
door__Json.doorDirection = door__Point.doorDirection;
if (door__Point.doorDirection < 2) {
doubleDoorList.unshift(door__Json);
} else {
doubleDoorList.push(door__Json);
}
}
door__List.push(doubleDoorList);
} else {
door__Json.door__x = (door__Point.x + windows__w / 2) - (this.houseWidth / 2);
door__Json.door__z = (door__Point.y + windows__h / 2) - (this.houseHeight / 2);
door__Json.door__width = Math.sqrt(Math.pow(windows__w, 2) + Math.pow(windows__h, 2));
door__Json.door__height = 180;
door__Json.door__y = 100;
door__Json.doorDirection = door__Point.doorDirection;
door__List.push(door__Json);
}
});
}
} else {
// 没门、没窗户
let code = this.createLambert(width, 200, 10, angle, this.matArrayB, x, 100, z);
}
});
};
```

We will begin after finishing the above data to complete the operation, this time we need to create a function cerateWallHadDoorOrGlass to start drawing a glass door and a wall

```//画有门和有窗子的墙（工具函数）
cerateWallHadDoorOrGlass(width, height, depth, angle, material, x, y, z, door__list, windows__List) {
//茶色：0x58ACFA   透明玻璃色：0XECF1F3
var glass_material = new THREE.MeshBasicMaterial({
color: 0XECF1F3
});
glass_material.opacity = 0.5;
glass_material.transparent = true;
var wall = this.returnLambertObject(width, height, depth, angle, material, x, y, z);
windows__List.map((item, index) => {
var window_cube = this.returnLambertObject(item.window__width, item.w_Height, depth, angle, material, item.window__x, item.window__y, item.window__z);
wall = this.returnResultBsp(wall, window_cube, 1);
let code = this.returnLambertObject(item.window__width, item.w_Height, 2, angle, glass_material, item.window__x, item.window__y, item.window__z);
});
var status__result = [0.5, 0.5, 0, 0, ]
door__list.map((item, index) => {
if (item.length == 2) {
item.map((c_item, c_index) => {
let door_cube = this.returnLambertObject(c_item.door__width, c_item.door__height, 10, angle, this.matArrayB, c_item.door__x, c_item.door__y, c_item.door__z);
wall = this.returnResultBsp(wall, door_cube, 1);
let doorgeometry = new THREE.BoxGeometry(100, 180, 2);
let door = "";
if (c_index == 0) {
door = new THREE.Mesh(doorgeometry, this.LeftDoorRenderingList);
} else {
door = new THREE.Mesh(doorgeometry, this.DoorRenderingList);
}
door.position.set(c_item.door__x, c_item.door__y, c_item.door__z);
door.rotation.y = status__result[c_item.doorDirection] * Math.PI;
door.nature = "door";
door.direction = c_item.doorDirection;
door.isClose = 1;
door.doorIndex = c_index;
});
} else {
let door_cube = this.returnLambertObject(item.door__width, item.door__height, 10, angle, this.matArrayB, item.door__x, item.door__y, item.door__z);
wall = this.returnResultBsp(wall, door_cube, 1);
let doorgeometry = new THREE.BoxGeometry(100, 180, 2);
let door = new THREE.Mesh(doorgeometry, this.DoorRenderingList);
door.position.set(item.door__x, item.door__y, item.door__z);
door.rotation.y = status__result[item.doorDirection] * Math.PI;
door.nature = "door";
door.direction = item.doorDirection;
door.isClose = 1;