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

首先我了明显理解以下啥是墙?其实说白了就是一个长方体,长不确定,宽一般也就是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. 从JavaScript到Python之异常

    不少前端工程师看到这个标题可能会产生质问: 我js用得好好的,能后端能APP,为什么还要学习Python? 至少有下面两个理由: 学习曲线.ES6之后的JavaScript(TypeScript)的在 ...

  2. JWT详解

    目录 1.前言 2.JWT的数据结构 2.1 Header 2.2 Payload 2.3 Signature 2.4 Base64URL 3. JWT的实现   1.前言 定义:JSON Web T ...

  3. POI通用导出Excel数据(包括样式设计)

    前言 前一段时间我写过通用的导入Excel,前几天也写了导出pdf格式的,还有我之前搞得导出Word,我在之前的博客也都介绍了导出和导入是一个道理,无非是一个获取一个是赋值.昨天有一位同仁看了我的Ex ...

  4. 8.15 day33 进程池与线程池_协程_IO模型(了解)

    进程池和线程池 开进程开线程都需要消耗资源,只不过两者比较的情况线程消耗的资源比较少 在计算机能够承受范围之内最大限度的利用计算机 什么是池? ​ 在保证计算机硬件安全的情况下最大限度地利用计算机 ​ ...

  5. [Spring cloud 一步步实现广告系统] 21. 系统错误汇总

    广告系统学习过程中问题答疑 博客园 Eureka集群启动报错 Answer 因为Eureka在集群启动过程中,会连接集群中其他的机器进行数据同步,在这个过程中,如果别的服务还没有启动完成,就会出现Co ...

  6. 简单了解一下事件循环(Event Loop)

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  7. c语言和c++的交换函数

    #include<iostream> using namespace std; namespace LiuGang{//在命名空间中写函数 void swap(int&aa,int ...

  8. 06 css选择器

    选择器的作用:选中标签 1.基本选择器  标签选择器 id选择器 class选择器 *通配符选择器 权重:行内样式 1000 > id选择器 100 > 类选择器10 > 标签选择器 ...

  9. 启xin宝app的token算法破解——逆向篇(二)

    启xin宝app的token算法破解--抓包分析篇(一)文章已经对该app进行了抓包分析,现在继续对它进行逆向. 对于一个app而言,我们要逆向app,需要知道什么呢? 逆向工具 Java基础,甚至c ...

  10. Servlet 获取 数组id进行批量删除

    把获取的复选框选中的 id(一般来说都是根据id 进行批量删除的) 从jsp页面 传值到Servlet中 jsp点击事件中: var array=[];  //先声明一个数组变量 var ids=$( ...