之前三节都没涉及到机房,只是一些零零散散的知识点,这一节我们就开始正式画外墙。

首先我了明显理解以下啥是墙?其实说白了就是一个长方体,长不确定,宽一般也就是40cm,高也就是两米,这就是一个简单的墙,当然很多墙上都有窗户、门啥的,其实也就是在长方体的固定的位置掏个洞,然后放上我们需要方的东西,比如门,窗户。

在画墙之前我们需要对一个机房的俯视图进行分析,就比如下面这张机房的图片

(图片来自网络)

就像图片中显示的一样,这个机房非常标准,是个很标准的长方形机房,长900cm, 宽600cm,左侧的墙体是玻璃隔断,还有一扇门,

那好,我们就可以开干了,首先我们要初始化一个机房的结构布局的Json,注意门不能和窗户重合,有门的地方窗户需要分成门左边和门右边两个数组(当然你也可以写多个判断进行操作,但是比较麻烦)。

{
  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}]}}
  ]
},

  接下来我们开始画地板,我们目前就将地板和机房大小做一样:

    createFloor() {
let _self = this;
this.imgRendering.load("地板的图片", texture => {
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; _self.scene.add(floor);
})
}

  执行效果如下图:

紫色是我加给整个Html的颜色,主要是方便观看地板,接下来我们就开始画墙了,在画墙之前我们先初始化一个画长方体(窗宽高均默认为1)的函数:

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

封装好之后我们在画墙的时候就不用每画一道墙就新建一个几何体和材质,我们只需要克隆我们刚才初始化的墙体就好了

之后我们正式封装具有具体长度、角度和位置在的墙

/**
* 画长方体
* @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;
};

  这样我们就将一个具有长宽高、方向、位置的长方体就画出来了,

只是画出来还不行,我们需要将数据和模型关联起来,我们先对 this.data.wall 进行遍历得到这道墙的具体信息,是否有门窗,墙的起始点和结束点,知道了起始点和结束点,我们就能算出这道墙具体有多长,还有这道墙的角度

如上图,有以上两个点我们能得出该条线的信息

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

  角度:Math.asin((300- 0) / (0 - 300)) / Math.PI

这样我们就知道了该条线的具体信息,下面我们就能画墙了:

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);
      this.scene.add(code);
    }
  });
};

 执行完我们就能看到如下图这样的结果了

还差一面墙,上面既有门又有窗户,那我们就先作既有门又有窗户的,献上一张图爽一下

要实现这样,那我们首先要封装一个几何ti裁切函数:

/**
* 几何体裁切函数
* @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.material.flatshading = THREE.FlatShading;
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;
};

  之后我们就开始对有门或者有窗户的墙面开始处理,先整理数据,将数据整理成我么能够最简单就能处理的

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);
      this.scene.add(code);
    }
  });
};

  整理完成之后我们就要开始对以上数据进行操作了,此时我们就需要创建函数cerateWallHadDoorOrGlass来开始画有玻璃和门的墙了

//画有门和有窗子的墙(工具函数)
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);
this.scene.add(code);
});
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;
this.scene.add(door);
});
} 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;
this.scene.add(door);
} });
this.scene.add(wall);
};

  如此,大功告成,我们在放一面没有门但有玻璃的墙看看

画墙这块就到这儿,这篇文章整整花费了我一下午的时间,项目是直接从vue init webpack dome 开始的,各位看客如果觉得还行,麻烦给个“推荐”,哈哈哈,全当我一下午的辛苦没白费! * _ *

Three.js 开发机房(三)的更多相关文章

  1. Three.js 开发机房(四)

    这一节我们讲讲怎么画机柜,其实机柜如果作的复杂一点.逼真一点可以用3D建模工具,不过一般的项目中也不用做的那么麻烦,那我们就可以将机柜抽象以下,首先它是一块具有长宽高的立方体铁块,然后我们从中间在掏掉 ...

  2. JS开发HTML5游戏《神奇的六边形》(三)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  3. Node.js学习笔记——Node.js开发Web后台服务

    一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...

  4. JS开发HTML5游戏《神奇的六边形》(一)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  5. heX——基于 HTML5 和 Node.JS 开发桌面应用

    heX 是网易有道团队的一个开源项目,允许你采用前端技术(HTML,CSS,JavaScript)开发桌面应用软件的跨平台解决方案.heX 是你开发桌面应用的一种新的选择,意在解决传统桌面应用开发中繁 ...

  6. JS开发HTML5游戏《神奇的六边形》(二)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  7. atitit js 开发工具 ide的代码结构显示(func list) outline总结

    atitit js 开发工具 ide的代码结构显示(func list) outline总结 eclips环境::4.3.1 #-------需要一个js开发工具,可以显示outline或者代码结构显 ...

  8. JS开发HTML5游戏《神奇的六边形》(四)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  9. EXT.NET高效开发(三)——使用Chrome浏览器的开发人员工具

    这篇帖子老少皆宜,不分男女,不分种族,不分职业.俗话说:“磨刀不误砍柴工”.掌握一些开发工具的使用,对自己帮助是很大的(无论是用于分析问题,还是提高生产力).本篇就讲述如何利用Chrome浏览器(这里 ...

随机推荐

  1. MyBatis 核心配置综述之 ParameterHandler

    目录 ParameterHandler 简介 ParameterHandler 创建 ParameterHandler 中的参数从何而来 ParameterHandler 解析 MyBatis 四大核 ...

  2. Samba:基于公网 IP 的服务访问

    写在前面的话 由于使用过程中,发现如果 Samba 只用于内网访问,同事在外面甚至其它不是一个网段的同事就无法访问了.这显然不符合我们最终的需求,最后没法,只能把访问部署到云服务器上面去,此时问题来了 ...

  3. centOS 如何查看知道自己的版本号

    今天遇到一个尴尬的问题 , 竟然找不到centOS7x这个版本系统 然后我就问大佬们,大佬们1810 是哪哪哪个版本说的我还是懵逼 然后我就发挥我那不要脸的精神 问:'这是有什算发算的吗'  很是尴尬 ...

  4. DDOS浅谈

    一.DDOS攻击的来源 任何攻击都不会凭空产生,DDOS也有特定的来源.绝大多数的DDOS攻击都来自于僵尸网络.僵尸网络就是由数量庞大的可联网僵尸主机组成,而僵尸主机可以是任何电子设备(不仅是X86架 ...

  5. 给debian的docker容器添加crontab定时任务

    现在大部分的docke镜像是基于debian # cat /etc/issue Debian GNU/Linux 9 \n \l Docker容器是不支持后台服务的,像systemctl servic ...

  6. vs2013 在按F5调试时,总是提示 “项目已经过期”的解决方案

    这个是由于缺少某些文件(如.h,xxx.icon),或者文件时间不对 引起的. 如图在工具选项设置 最小为 “诊断”. 然后编译一下,会提示 xxx过期,确认下即可.

  7. 拼写单词[哈希表]----leetcode周赛150_1001

    题目描述: 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars. 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我 ...

  8. 多线程之NSThread

    关于多线程会有一系列如下:多线程之概念解析 多线程之pthread, NSThread, NSOperation, GCD 多线程之NSThread 多线程之NSOperation 多线程之GCD一, ...

  9. DBUtils框架的使用(下)

    刚才讲了使用QueryRunner插入.修改.更新数据,现在来学习一下使用QueryRunner进行数据库表查询. 通过QueryRunner类的query()方法即可完成数据库表的查询操作,但是在查 ...

  10. vector function trmplate

    /* vector function template programmer:qpz */ #include <iostream> #include <vector> #def ...