Threejs制作服务器机房冷却结构

        这节再绘制一个机房的结构,因为内容比较简单,就只使用一个章节来介绍,

先来一张效果图,

需要两个模型:一个冷却设备,一个服务器机箱,我这里是从网上找来的,首先我们搭建一个场景,

 initScene(){
      this.scene = new THREE.Scene();
    },
    initCamera(){
      this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
      this.camera.position.set(200,-100,200);
      this.camera.lookAt(200,200,0);
      this.camera.up.set(0, 0, 1);   // <=== spin // around Z-axis
    },
    initLight(){
      //添加两个平行光
      const directionalLight1 = new THREE.DirectionalLight(0xffffff, 1.5);
      directionalLight1.position.set(-300,-300,600)
      this.scene.add(directionalLight1);
      const directionalLight2 = new THREE.DirectionalLight(0xffffff, 1.5);
      directionalLight2.position.set(600,200,600)
      this.scene.add(directionalLight2);
    },
 initRenderer(){
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.container = document.getElementById("container")
      this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
      this.renderer.setClearColor('#FFFFFF', 1.0);
      this.container.appendChild(this.renderer.domElement);
    },
    initControl(){
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);

      this.controls.enableDamping = true;
      this.controls.maxPolarAngle = Math.PI / 2.2;      // // 最大角度
      this.controls.target = new THREE.Vector3(200, 200, 0);
      this.camera.position.set(200, -100, 200);
      this.camera.lookAt(200, 200, 0);
    },
    initAnimate() {
    
      requestAnimationFrame(this.initAnimate);
      this.renderer.render(this.scene, this.camera);
    },

        然后添加房间,为了效果更真实,我们会创建一个房间,把服务器放在房间里,把冷却塔放在外面,创建方法和mes中的类似,只不过这个不用设计门了,可以直接搭建四堵墙和地板

 floor:{floorWidth:600, floorLength:600,depth:1},
      wall:{wallWidth:150, wallLength:300,wallHeight:20},
      offsetValue:200,
 
initFloor(){
      let floorGeometry = new THREE.BoxGeometry( this.floor.floorWidth,this.floor.floorLength,this.floor.depth);
      let floorMaterial = new THREE.MeshPhysicalMaterial({color:'#FFFFFF'});
      let textureFloor = new THREE.TextureLoader().load('/static/images/floor.jpg', function (texture) {
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
      })
      floorMaterial.map = textureFloor
      let floor = new THREE.Mesh( floorGeometry, floorMaterial );
      floor.name = '地板';
      floor.position.set(this.floor.floorWidth/2,this.floor.floorLength/2,0)
      this.scene.add(floor)
    },
    //初始化墙壁
    createCubeWall() {
      let materialTie = new THREE.MeshPhysicalMaterial({color: '#BBBBBB'});  //前  0xafc0ca :灰色
      let textureWall = new THREE.TextureLoader().load('/static/images/wall.jpg', function (texture) {
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
      })
      materialTie.map = textureWall
      let wallList = []
      let wall1 = {width:this.wall.wallLength, height:2, depth:this.wall.wallHeight, angle:0, matArrayB:materialTie, x:this.wall.wallLength/2+this.offsetValue, y:+this.offsetValue, z:this.wall.wallHeight/2, name:"墙面"};
      let wall2 = {width:this.wall.wallLength, height:2, depth:this.wall.wallHeight, angle:1, matArrayB:materialTie, x:this.wall.wallLength/2+200, y:this.wall.wallWidth+this.offsetValue, z:(this.wall.wallHeight/2), name:"墙面"};
      let wall3 = {width:this.wall.wallWidth, height:2, depth:this.wall.wallHeight, angle:1.5, matArrayB:materialTie, x:this.offsetValue, y:this.wall.wallWidth/2+this.offsetValue, z:(this.wall.wallHeight/2), name:"墙面"};
      let wall4 = {width:this.wall.wallWidth, height:2, depth:this.wall.wallHeight, angle:1.5, matArrayB:materialTie, x:this.wall.wallLength+this.offsetValue, y:(this.wall.wallWidth/2)+this.offsetValue, z:(this.wall.wallHeight/2), name:"墙面"};
      wallList.push(wall1);wallList.push(wall2);wallList.push(wall3);wallList.push(wall4);
      for(let i=0;i<wallList.length;i++){
        let cubeGeometry = new THREE.BoxGeometry(wallList[i].width, wallList[i].height, wallList[i].depth);
        let cube = new THREE.Mesh(cubeGeometry, wallList[i].matArrayB);
        cube.position.x = wallList[i].x;
        cube.position.y = wallList[i].y;
        cube.position.z = wallList[i].z;
        cube.rotation.z += wallList[i].angle * Math.PI; //-逆时针旋转,+顺时针
        cube.name = wallList[i].name;
        this.scene.add(cube);
      }
    },

        然后添加两个设备,一个冷却设备,一个服务器主机柜,要注意调整位置,保持一个在房间内一个在房间外,后续会通过冷凝管连接两个设备

initDevice(){
      const loader = new GLTFLoader()
      loader.load("/static/models/server.glb", (gltf) => {
        this.server = gltf.scene;
        this.server.scale.set(0.3,0.3,0.3);
        this.server.position.set(300,300,0);
        this.server.rotation.x = Math.PI/2
        this.server.rotation.y = Math.PI/2
        this.scene.add(this.server)   // 加入场景
      })
      loader.load("/static/models/tower.glb", (gltf) => {
        this.tower = gltf.scene;
        this.tower.scale.set(20,20,20);
        this.tower.position.set(300,400,30);
        this.tower.rotation.x = Math.PI/2
        this.scene.add(this.tower)   // 加入场景
      })
    },

添加好设备后,我们就得到这样的场景,

        然后需要添加管道给这两个设备连接起来,并且其中一个为蓝色一个为红色,之前有讲过Threejs绘制管道效果,可以就把那部分拿过来使用,配置好每个坐标点,这里用两个方法一个绘制冷水,一个绘制热水,并且让水流动起来,这部分开发可以参考之前的章节,不过要调整水管的接入点,如果想要直角管,可以在点数组中添加两个拐弯点的坐标,就可以避免后续的点的影响,以达到直角管道的效果。

代码如下:

initColdTube(){
      const path = new THREE.CatmullRomCurve3([
        new THREE.Vector3(350, 300, 10),
        new THREE.Vector3(380, 300, 10),
        new THREE.Vector3(380, 300, 10),
        new THREE.Vector3(380, 400, 10),
        new THREE.Vector3(380, 400, 10),
        new THREE.Vector3(320, 400, 7),
      ]);
      let geometry1 = new THREE.TubeGeometry(path, 100, 1, 25, false);
      let textureLoader = new THREE.TextureLoader();
      let texture = textureLoader.load('/static/images/cold.png')
      texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
      this.coldMaterial = new THREE.MeshBasicMaterial({
        map:texture,
        transparent: false,
      }); //材质对象Material
      let mesh1 = new THREE.Mesh(geometry1, this.coldMaterial); //网格模型对象Mesh
      this.scene.add(mesh1); //网格模型添加到场景
      let tubeGeometry2 = new THREE.TubeGeometry(path, 100, 2, 25, false);
      let tubeMaterial2 = new THREE.MeshPhongMaterial({
        color: 0xaaaaaa,
        transparent: true,
        opacity: 0.5,
      });
      let tube2 = new THREE.Mesh(tubeGeometry2, tubeMaterial2);
      this.scene.add(tube2);
    },
    initHotTube(){
      const path = new THREE.CatmullRomCurve3([
        new THREE.Vector3(300, 300, 10),
        new THREE.Vector3(230, 300, 10),
        new THREE.Vector3(230, 300, 10),
        new THREE.Vector3(230, 300, 53),
        new THREE.Vector3(230, 300, 53),
        new THREE.Vector3(230, 400, 53),
        new THREE.Vector3(230, 400, 53),
        new THREE.Vector3(270, 400, 53),
      ]);
      let geometry1 = new THREE.TubeGeometry(path, 100, 1, 25, false);
      let textureLoader = new THREE.TextureLoader();
      let texture = textureLoader.load('/static/images/hot.png')
      texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
      this.hotMaterial = new THREE.MeshBasicMaterial({
        map:texture,
        transparent: false,
      }); //材质对象Material
      let mesh1 = new THREE.Mesh(geometry1, this.hotMaterial); //网格模型对象Mesh
      this.scene.add(mesh1); //网格模型添加到场景
      let tubeGeometry2 = new THREE.TubeGeometry(path, 100, 2, 25, false);
      let tubeMaterial2 = new THREE.MeshPhongMaterial({
        color: 0xaaaaaa,
        transparent: true,
        opacity: 0.5,
      });
      let tube2 = new THREE.Mesh(tubeGeometry2, tubeMaterial2);
      this.scene.add(tube2);
    },

然后再给服务器和冷却设备添加状态和名字,用上个章节中给产线设备添加名字的方式:

initMachineName(x,y,z,name){//创建设备信息
      const earthDiv = document.createElement('div');
      earthDiv.className = "label";
      earthDiv.innerHTML = "<div style='border:1px #FFFFFF solid;border-radius: 5px;width:90px;padding-left:10px'>" +
          "<span style='font-size: 12px;color:#FFFFFF'>"+name+"</span><br/>" +
          "<span style='font-size: 12px;color:#FFFFFF'>运行正常</span><br/>" +
          "<span style='color:green;font-size: 12px;'>温度18℃</span>" +
          "</div>";
      const earthLabel = new CSS2DObject(earthDiv);
      earthLabel.position.set(x,y,z);//相对于父级元素的位置
      this.scene.add(earthLabel);

      this.labelRenderer = new CSS2DRenderer();
      this.labelRenderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(this.labelRenderer.domElement)
      //设置样式
      this.labelRenderer.domElement.style.position = 'fixed';
      this.labelRenderer.domElement.style.top = '0px';
      this.labelRenderer.domElement.style.left = '0px';
      this.labelRenderer.domElement.style.zIndex = '10';//设置层级
    },

最终效果如下:

机房冷却

这样一共不到250代码,一个简单的机房数字孪生场景就做好了,如果需要源码可以在评论区留下邮箱,也可以私信一起交流学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/585594.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

solidworks出现slderrresu.dll错误如何解决?亲测有效

通过近来给客户安装SolidWorks发现&#xff0c;SolidWorks2010、SolidWorks2012、SolidWorks2014、SolidWorks2015、SolidWorks2016、SolidWorks2017都会出现这个slderrresu.dll安装错误问题&#xff1a; 其实这个错误很好解决,主要是因為安裝中文版solidworks沒有選擇安裝中文…

.NET操作 Access (MSAccess)

注意&#xff1a;新项目推荐 Sqlite &#xff0c;Access需要注意的东西太多了&#xff0c;比如OFFICE版本&#xff0c;是X86还是X64 连接字符串 ProviderMicrosoft.ACE.OleDB.15.0;Data Source"GetCurrentProjectPath"\\test.accdb//不同的office版本 连接字符串有…

Linux 虚拟主机切换php版本及参数

我使用的Hostease的Linux虚拟主机产品,由于网站程序需要支持高版本的PHP,程序已经上传到主机&#xff0c;但是没有找到切换PHP以及查看PHP有哪些版本的位置&#xff0c;因此咨询了Hostease的技术支持&#xff0c;寻求帮助了解到可以实现在cPanel面板上找到此切换PHP版本的按钮&…

亚马逊商品详情API接口:解锁亚马逊商品信息的全面视野

亚马逊商品详情API接口&#xff1a;解锁亚马逊商品信息的全面视野 在跨境电商和电商数据分析领域&#xff0c;亚马逊作为全球领先的电商平台&#xff0c;其商品信息对商家、开发者以及市场分析师来说至关重要。为了更高效地获取亚马逊平台上的商品详情&#xff0c;亚马逊商品详…

哨兵-1A与DInSAR技术监测尼泊尔地震前后地表形变

辽宁抚顺是一座以煤而兴的重工业城市&#xff0c;建国初期抚顺被誉为“煤都”&#xff0c;这里有闻名全国享誉世界的亚洲最大的露天煤矿——抚顺西露天矿。抚顺西露天矿地处抚顺煤田西部&#xff0c;矿坑东西长6.6公里&#xff0c;南北宽2.2公里&#xff0c;最终开采垂直深度47…

释放人工智能潜力,Polkadot 再掀区块链技术革命

来源&#xff1a;https://polkadot.network/blog/unleashing-the-potential-of-ai-with-polkadot/ 编译&#xff1a;OneBlock 区块链技术开辟了一个充满可能性的世界&#xff0c;这一点在新兴崛起的人工智能&#xff08;AI&#xff09;领域最为明显。 Polkadot 生态处于这场…

Go Web开发【xorm 框架】

1、xorm 1.1、xorm 简介 xorm 是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。 特性 支持 struct 和数据库表之间的灵活映射&#xff0c;并支持自动同步事务支持同时支持原始SQL语句和ORM操作的混合执行使用连写来简化调用支持使用ID, In, Where, Limit,…

【JavaWeb Day 2 - JS 】

JavaWeb Day 2 - JS JS背景故事1. JS 引入方式2. JS 基本语法2.2 变量2.3 数据类型2.4 运算符 3. JS 函数4. JS 对象4.1 Array对象4.2 String对象4.3 JSON对象4.4 BOM对象4.4.1 windows 对象4.4.2 location 对象 4.5 DOM 对象DOM 案例 5. JS 事件监听5.1 JS 事件绑定 及 常见事…

JavaScript底层原理(栈、堆、主线程、任务队列、事件循环机制)

1. 栈(heap)和堆(stack) 栈是栈内存的简称&#xff0c;堆是堆内存的简称。顾名思义&#xff0c;内存是干啥的&#xff1f;内存就是用来存放数据的。 栈 栈只有一个入口&#xff0c;同时也是出口&#xff0c;数据遵循先进后出、后进先出的原则。 栈用于存放基本类型数据和引用…

vue 模板字符串

1.模板字符串换行问题 white-space: pre-wrap; 2. 鼠标移入 显示提示框 点击手动隐藏 myChart.on("mouseover", function (params) {myChart.dispatchAction({type: "downplay",}); }); tooltip: {show: true, //是否显示提示框组件&#xff0c;包括…

安卓获取SHA

1&#xff1a;安卓通过签名key获取SHA 方式有两种&#xff0c; 1、电脑上来存在eclipse的用户或正在使用此开发工具的用户就简单了&#xff0c;直接利用eclipse 走打包流程&#xff0c;再打包的时候选择相应的签名&#xff0c;那么在当前面板的下面便会出现签名的相关信息。 2、…

牛客热题:合并K个升序链表

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;合并K个升序链表题目链接&#…

【刷题篇】动态规划-完全背包问题(十一)

文章目录 1、完全背包2、零钱兑换3、零钱兑换 II4、完全平方数 1、完全背包 #include <iostream> #include<vector> using namespace std;int main() {int n,v;cin>>n>>v;vector<int> V(n1);vector<int> W(n1);for(int i1;i<n;i){cin&g…

【消息队列】延迟消息

延时消息 延迟消息死信交换机延迟消息的插件 延迟消息 生产者发送消息时指定一个时间&#xff0c;消费者不会立刻收到消息&#xff0c;而在指定时间之后才收到消息 比如说演唱会的票&#xff0c;抢上了但是迟迟未支付&#xff0c;但是库存已经占用&#xff0c;就需要用到延迟消…

【STM32】F405/407的模块总览图,记录查看

从STM32F405/407数据手册中提取&#xff0c;方便以后查看。主要是什么外设连接在什么总线上&#xff0c;时钟频率是多少。 TIM2、3、4、5、12、13、14在APB1上&#xff0c;最大频率84M TIM1、8、9、10、11在APB2上&#xff0c;最大频率168M

WEB攻防-PHP特性-piwigoCMS审计实例

前置知识&#xff1a;PHP函数缺陷 测试环境 &#xff1a;piwigo CMS 漏洞URL&#xff1a; 漏洞文件位置&#xff1a;\include \functions_rate.inc.php 漏洞产生入口文件&#xff1a;/picture.php picture.php中接受了一个GET方法action参数&#xff0c;作为switch...case.…

架设WebSocket的最后一环,如何设置好nginx反向代理

WebScoket都已经完工快一个月&#xff0c;经过一段时间的测试&#xff0c;公司还是准备把服务器换到鹅厂&#xff0c;用EO来解决CDN内容分发和DDOS防护问题&#xff0c;由于EO并不支持URL 路径转发&#xff0c;只支持转发到一个站点的80或则443端口&#xff0c;如果想做路径分发…

Python urllib 爬虫入门(2)

本文为Python urllib类库爬虫更入门的一些操作和爬虫实例及源码。 目录 模拟浏览器请求 简单模拟 设置随机user-agent 请求超时 HTTP请求类型 Get请求 Post请求 抓取网页动态请求 封装ajax请求 调用 循环调用 抓取小说 封装请求函数 把html写入本地分析 调用 正…

Arthas进阶

这里写自定义目录标题 六、class和classloader6、dump7、classloader 七、monitor/watch/trace/stack等核心命令的使用1、monitor2、watch3、trace4、stack5、tt6、option7、profiler 六、class和classloader 6、dump 将已加载类的字节码文件保存到特定目录&#xff1a;logs/…

【IR 论文】HyDE:让 LLM 对 query 做查询改写来改进 Dense Retrieval

论文&#xff1a;Precise Zero-Shot Dense Retrieval without Relevance Labels ⭐⭐⭐⭐ CMU, ACL 2023, arXiv:2212.10496 Code: github.com/texttron/hyde 文章目录 论文速读总结 论文速读 在以往的 dense retrieval 思路中&#xff0c;需要对 input query 做 encode 来得到…
最新文章