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

首先我了明显理解以下啥是墙?其实说白了就是一个长方体,长不确定,宽一般也就是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. java并发笔记之四synchronized 锁的膨胀过程(锁的升级过程)深入剖析

    警告⚠️:本文耗时很长,先做好心理准备,建议PC端浏览器浏览效果更佳. 本篇我们讲通过大量实例代码及hotspot源码分析偏向锁(批量重偏向.批量撤销).轻量级锁.重量级锁及锁的膨胀过程(也就是锁的升 ...

  2. Kubernetes容器集群管理环境 - 完整部署(上篇)

    Kubernetes(通常称为"K8S")是Google开源的容器集群管理系统.其设计目标是在主机集群之间提供一个能够自动化部署.可拓展.应用容器可运营的平台.Kubernetes ...

  3. Java课堂 动手动脑5

    1.了解棋盘打印:利用二维数组输出一个15*15的棋盘,棋盘的原素为“+”,就是输出一个横纵都是15个“+”的二维数组,然后再以坐标形式输入棋子“●”,替换掉原来棋盘里的“+”.再编写代码. 电脑随机 ...

  4. java订单生成工具类

    欢迎来到付宗乐个人博客网站.本个人博客网站提供最新的站长新闻,各种互联网资讯. 还提供个人博客模板,最新最全的java教程,java面试题.在此我将尽我最大所能将此个人博客网站做的最好! 谢谢大家,愿 ...

  5. mybatis学习笔记(三)

    mybatis增删改 概念: 功能:从应用程序角度出发,软件具有哪些功能: 业务:完成功能时的逻辑,对应service的一个方法: 事务:从数据库角度出发,完成业务时需要执行的SQL集合,统称一个事务 ...

  6. [实践]activemq安全设置 设置admin的用户名和密码

    (1)打开/opt/app/amq/apache-activemq-5.9.0/conf/jetty.xml 找到 将property name为authenticate的属性value=" ...

  7. android ——Intent

    Intent是android程序中各组件之间进行交互的重要方式,它可以用于指明当前组件想要执行的动作,也可以在不同组件之间传递数据,Intent一般被用于启动活动,启动服务以及发送广播. 一.显式的使 ...

  8. mybatis一对多双向映射

    连表查询 select   id  resultType  resultMap resultType和resultMap不能同时使用 association 属性  映射到多对一中的“一”方的“复杂类 ...

  9. Java 安全之:csrf攻击总结

    最近在维护一些老项目,调试时发现请求屡屡被拒绝,仔细看了一下项目的源码,发现有csrf token校验,借这个机会把csrf攻击学习了一下,总结成文.本文主要总结什么是csrf攻击以及有哪些方法来防范 ...

  10. docker-compose 综合训练

    Docker-compose综合训练 一. 实验目的: 熟悉Docker-compose的基本工作原理: 熟悉Docker-compose安装 熟悉Docker compose命令基础 熟悉Docke ...