three.js 制作机房(上)
three.js使用的人太少了,一个博文就几百个人看,之前发js基础哪怕是d3都会有几千的阅读量,看看以后考虑说一说d3了,哈哈。吐槽完毕回归正题。前几天郭先生看到网上有人开发了3D机房,正愁博客没什么写的,于是昨天熬夜也做了一个,今天就把大体的流程告诉萌新们,先说说主要功能模块。
- 墙体、地面、窗户以及门的实现(双击门禁门可开关)。
- 机柜实现(机柜门的开关、机箱的推拉以及开关推拉的条件)。
- 机箱存储占用比率(用颜色表示占用率,并附颜色谱图)。
- 监控摄像视角(包括监控摄像机的模型导入,和四视角监控)。
- 红外防控报警。
- 强弱电线的铺设。
- 以及风向。
下面对应这7个功能模块附图。
看图是不是感觉很好呢?不过细分下来每个点都是十分简单的。那么我们就按照模块分析一下。
1. 墙体、地面、窗户以及门的实现
这一块主要就是对于3d空间位置的理解,旋转的使用以及uv的使用。考虑到墙面和窗户代码的重复使用,这里封装一下。封装完以后,改变更加灵活方便,门的旋转参见之前发的博客模拟门转动。
1. 墙的实现
这里我们看下墙的数据,数组的每一项就是一面墙(这里我要求每一面墙最多只能有一个门位和窗户位,如果想两个窗户,那么就在原本的一面墙上设置两个数组),s表示墙的size,p表示墙的position(这里用不到选不考虑旋转),hasDoor表示有门,ds表示门的size,dp表示门的position,hasWindow表示是否有窗,ws表示窗的size,wp表示窗的position,是不是挺简单的(当然每个人设计的都不相同)。这样绘制出来的图,就如我上面发的图。下面上代码
var wallArr = [
{s: [1, 20, 61], p: [45, 10, 0], dir: 'z', hasDoor: true, ds: [1, 18, 18], dp: [45, 9, 15], hasWindow: true, ws: [1, 10, 24], wp: [45, 10, -13]},
{s: [1, 20, 61], p: [-45, 10, 0], dir: 'z', hasDoor: false, hasWindow: true, ws: [1.2, 10, 50], wp: [-45, 10, 0]},
// {s: [46, 20, 1], p: [22.5, 10, 30], dir: 'x', hasDoor: false, hasWindow: true, ws: [30, 10, 1], wp: [22.5, 10, 30]},
// {s: [46, 20, 1], p: [-22.5, 10, 30], dir: 'x', hasDoor: false, hasWindow: true, ws: [30, 10, 1], wp: [-22.5, 10, 30]},
// {s: [46, 20, 1], p: [22.5, 10, -30], dir: 'x', hasDoor: false, hasWindow: true, ws: [30, 10, 1], wp: [22.5, 10, -30]},
// {s: [46, 20, 1], p: [-22.5, 10, -30], dir: 'x', hasDoor: false, hasWindow: true, ws: [30, 10, 1], wp: [-22.5, 10, -30]},
{s: [91, 20, 1], p: [0, 10, 30], dir: 'x', hasDoor: false, hasWindow: true, ws: [80, 10, 1], wp: [0, 10, 30]},
{s: [91, 20, 1], p: [0, 10, -30], dir: 'x', hasDoor: false, hasWindow: true, ws: [80, 10, 1], wp: [0, 10, -30]}
];
就是一个这样的数组。我们将注释打开,并注释掉后两行,得到如图效果。
ok测试没有问题。
再说说墙的实现,这里使用了ThreeBSP,之前我也说过这个东西,它可以实现几何体的二元操作(A与B的和、A与B的差,A与B的交集)。这个东西我们用来在墙体中扣出窗户和门的位置。
2. 门的实现
接下来说一说门的纹理,ps一张门的图,记得将底图加上颜色和透明度,门把手不加透明,导出png,然后制作材质记得加上transparent。这里会有一个问题,那就是uv,因为boxGeometry各个面的uv都是[0,1],[1,1],[0,0],[1,0](如果没记错的话),多以这个门的反正面的把手肯定是不一样的方向,这样我们就改变一下uv
doorGeom1.faceVertexUvs[0][2] = [new THREE.Vector2(1,1), new THREE.Vector2(1,0), new THREE.Vector2(0,1)];
doorGeom1.faceVertexUvs[0][3] = [new THREE.Vector2(1,0), new THREE.Vector2(0,0), new THREE.Vector2(0,1)];
doorGeom2.faceVertexUvs[0][0] = [new THREE.Vector2(1,1), new THREE.Vector2(1,0), new THREE.Vector2(0,1)];
doorGeom2.faceVertexUvs[0][1] = [new THREE.Vector2(1,0), new THREE.Vector2(0,0), new THREE.Vector2(0,1)];
具体的旋转,之前博客有实现过。
3. 地面的实现
地面相信大家都会弄,主要是调整一个repeat和wrap,不多说。
floorT.wrapS = floorT.wrapT = THREE.RepeatWrapping;
floorT.repeat.x = floorT.repeat.y = 12;
2. 机柜的实现
这是里面对相对复杂的模块,不过里面还是用到了ThreeBSP,平移旋转、uv以及射线方面的知识,对于单个绘制来说,相信大家都能后信手拈来,不多对于大数量的机柜实现开关门、推拉服务器的点击操作逻辑(机柜关门是不允许推拉服务器操作,机柜中有服务器来出来是,不允许开关门操作),和机柜的隐藏显示。
1. 机柜架子的实现
机柜框架使用了ThreeBSP,将两个BoxGeometry相减既会出现一个没有门的框架,我们在加上门即可,门的旋转之前讲过了,
2. 服务器的实现
服务器的uv贴图只需要正面的即可,所以除了前两个三角形,其他的设置成这样就可以了。
for(let i=2; i<serGeom.faceVertexUvs[0].length; i++) {
serGeom.faceVertexUvs[0][i] = [new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2()];
}
3.服务器和柜门的点击事件
这里面我们考虑使用THREE.Raycaster类。
这是一个射线类,原理是鼠标在屏幕上点击的时候,得到二维坐标p(x, y),再加上深度坐标的范围(0, 1), 就可以形成两个三位坐标A(x1, y1, 0), B(x2, y, 1),这两个点的线穿过的Object3D由近及远返回一个数组,第一个便是我们点击到的对象。我们给之前的服务器机柜和服务器都加上名字方便我们知道点到的是哪一个。
let intersectFrameDoor = raycaster.intersectObjects(motorGroup.children, true);
let tempArr = intersectFrameDoor[0].object.name.split('-');//得到[机柜门/服务器名字,机柜编号,服务器编号[
if(tempArr[0] == 'mdoor') {
if(!this.motorServerFlag[tempArr[1]]) {
if(this.motorDoorFlag[tempArr[1]]) {
this.doAnimate(Math.PI * 3 / 5, 0, 500, intersectFrameDoor[0].object.parent, ['rotation', 'y'])
this.motorDoorFlag[tempArr[1]] = false;
} else {
this.doAnimate(0, Math.PI * 3 / 5, 500, intersectFrameDoor[0].object.parent, ['rotation', 'y'])
this.motorDoorFlag[tempArr[1]] = true;
}
}
} else if(tempArr[0] == 'mserver') {
if(this.motorDoorFlag[tempArr[1]]) {
let posx = intersectFrameDoor[0].object.position.x;
if(posx == 0) {
this.doAnimate(0, 2, 500, intersectFrameDoor[0].object, ['position', 'x']);
this.motorServerFlag[tempArr[1]] += 1;
} else {
this.doAnimate(2, 0, 500, intersectFrameDoor[0].object, ['position', 'x']);
this.motorServerFlag[tempArr[1]] -= 1;
}
}
}
4. 封装动画
这里面有很多动画,例如各种门的转动,服务器的平移,如果直接改变属性闲得很突兀,那么我们有几种选择,
- 关键帧动画
- Tween动画
- 自制动画
这里我们练习自己封装一个小动画,他虽然可能不够精确,但是十分实用。
doAnimate(s, e, t, o, a) { //开始的属性值、结束的属性值 时间 对象 属性
let temp = s;
let step = t / 20;
let stepLen = (e - s) / step;
let animationObj = setInterval(() => {
temp += stepLen;
if(stepLen > 0 && temp >= e) {
o[a[0]][a[1]] = e;
clearInterval(animationObj);
} else if(stepLen < 0 && temp <= e) {
o[a[0]][a[1]] = e;
clearInterval(animationObj);
} else {
o[a[0]][a[1]] = temp;
}
}, 20)
}
在fpx大于50的情况下,基本准确。
今天就先讲这两个模块,下一篇继续,觉得可以的话,点个赞吧。
转载请注明地址:郭先生的博客
three.js 制作机房(上)的更多相关文章
- three.js 制作机房(下)
这一篇书接上文,说一说剩下的一些模块. 1. 机箱存储占用比率 机箱存储占用比其实很简单,就是在机箱上新加一个组即可,然后根据比率值来设置颜色,这个颜色我们去HSL(0.4,0.8,0.5) ~ HS ...
- js制作带有遮罩弹出层实现登录小窗口
要实现的效果如下 点击“登录”按钮后,弹出登录小窗口,并且有遮罩层(这个名词还是百度知道的,以前只知道效果,却不知道名字) 在没有点击“登录”按钮之前登录小窗口不显示,点击“登录”按钮后小窗口显示,并 ...
- 用JS制作一个信息管理平台完整版
前 言 JRedu 在之前的文章中,介绍了如何用JS制作一个实用的信息管理平台. 但是那样的平台功能过于简陋了,我们今天来继续完善一下. 首先我们回顾一下之前的内容. 1.JSON的基础知识 ...
- 利用css+原生js制作简易钟表
利用css+原生js制作简单的钟表.效果如下所示 实现该效果,分三大块:html.javascript.css html部分html部分比较简单,定义一个clock的div,内部有原点.时分秒针.日期 ...
- JS制作图片切换
<!DOCTYPE html> <html> <head> <title>纯JS制作简单的图片切换</title> <meta cha ...
- 使用Vue.js制作仿Metronic高级表格(一)静态设计
Metronic高级表格是Metonic框架中自行实现的表格,其底层是Datatables.本教程将主要使用Vue实现交互部分,使用Bootstrap做样式库.jQuery做部分用户交互(弹窗). 使 ...
- D3.js 制作中国地图 .net 公共基础类
D3.js 制作中国地图 from: http://d3.decembercafe.org/pages/map/index.html GeoJSON is a format for encoding ...
- 使用WebGL + Three.js制作动画场景
使用WebGL + Three.js制作动画场景 3D图像,技术,打造产品,还有互联网:这些只是我爱好的一小部分. 现在,感谢WebGL的出现-一个新的JavaScriptAPI,它可以在不依赖任何插 ...
- HTML5 file API加canvas实现图片前端JS压缩并上传
一.图片上传前端压缩的现实意义 对于大尺寸图片的上传,在前端进行压缩除了省流量外,最大的意义是极大的提高了用户体验. 这种体验包括两方面: 由于上传图片尺寸比较小,因此上传速度会比较快,交互会更加流畅 ...
随机推荐
- C#中的类与对象
类:说白了就是类型,是对具体事物的一种抽象总结. 对象:一个具体的事物. 类与对象的关系,类实例化就会得到一个对象,同样一个对象也应该属于某一个类.例如张三这个人,他是一个对象,同时他属于人类,在程序 ...
- 利用tox打造自动自动化测试框架
什么是tox tox官方文档的第一句话 standardize testing in Python,意思就是说标准化python中的测试,那是不是很适合测试人员来使用呢,我们来看看他究竟是什么? 根据 ...
- DirectX11 With Windows SDK--35 粒子系统
前言 在这一章中,我们主要关注的是如何模拟一系列粒子,并控制它们运动.这些粒子的行为都是类似的,但它们也带有一定的随机性.这一堆粒子的几何我们叫它为粒子系统,它可以被用于模拟一些比较现象,如:火焰.雨 ...
- css 过渡样式 transition
过渡顾名思义就是就是样式改变的一个过程变化 简介 transition: property duration timing-function delay; 值 描述 transition-proper ...
- js JQ动态添加div标签
function renderList(data){ var str = ''; for(var i = 0; i < data.length; i++){ // 动态添加li str += ' ...
- 【原创】xenomai内核解析--同步互斥机制(一)--优先级倒置
版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 一.xenomai 资源管理简要 二.优先级倒 ...
- 将ip加入到防火墙
五分钟内访问次数最多的ip加入到防火墙 #!/bin/bash cat /etc/httpd/logs/access_log|grep `date -d '1-minute-ago' +%d/%b/% ...
- Elasticsearch必知必会的干货知识二:ES索引操作技巧
该系列上一篇文章<Elasticsearch必知必会的干货知识一:ES索引文档的CRUD> 讲了如何进行index的增删改查,本篇则侧重讲解说明如何对index进行创建.更改.迁移.查询配 ...
- 报错:invalid operands to binary - (have ‘int’ and ‘char *’)
//这个题是输入大写的一串字符,然后按A对应1...这个规律求乘积 char a[],b[]; scanf("%s",a); scanf("%s",b); in ...
- 02_HTML02
学于黑马和传智播客联合做的教学项目 感谢 黑马官网 传智播客官网 微信搜索"艺术行者",关注并回复关键词"软件测试"获取视频和教程资料! b站在线视频 HTML ...