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

news2024/11/23 22:03:33

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

先来一张效果图,

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

 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.coloradmin.cn/o/1635093.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AWTK 集成 OGRE 3D 图形引擎

本项目演示了如何在 AWTK 中集成 OGRE3D。 0. 准备 先编译 AWTK, 并在 env.sh 中设置 awtk 的路径。需要安装 cmake 1. 生成资源 python scripts/update_res.py all2. 编译 设置环境变量 source env.sh source env_rt.sh编译 ogre 库 cd 3rd build_assimp.sh build_ogre.…

我们自己的芯片指令集架构——龙芯架构简介

CPU指令集架构&#xff08;ISA, Instruction Set Architecture&#xff09; CPU指令集架构是处理器硬件与软件之间的接口规范&#xff0c;它定义了一组基本指令&#xff0c;以及这些指令的操作格式、编码方式、寻址模式、寄存器组织、中断机制、异常处理等各个方面。ISA是计算…

uniApp+Vue3+vite+Element UI或者Element Plus开发学习,使用vite构建管理项目,HBuilderX做为开发者工具

我们通常给小程序或者app开发后台时&#xff0c;不可避免的要用到可视化的数据管理后台&#xff0c;而vue和Element是我们目前比较主流的开发管理后台的主流搭配。所以今天石头哥就带大家来一起学习下vue3和Element plus的开发。 准备工作 1&#xff0c;下载HBuilderX 开发者…

Camera设备上晶体晶振的应用

IPC行业现状的分析 IP Camera起源于20世纪90年代&#xff0c;最早应用于监控系统中。 随着AI技术、云服务以及IoT技术的发展&#xff0c;IPC已经从安防监控向智慧城市、智能家居、自动驾驶、智能医疗等行业领域拓展&#xff0c;不单单传统地应用于工业&#xff0c;个人和家庭的…

《QT实用小工具·四十八》趣味开关

1、概述 源码放在文章末尾 该项目实现了各种样式的趣味开关&#xff1a; 1、爱心形状的switch开关&#xff0c;支持手势拖动、按压效果 2、线条样式的3种开关 项目demo演示如下所示&#xff1a; 使用方式&#xff1a; 1、sapid_switch文件夹加入工程&#xff0c;.pro文件中…

ActiveMQ 反序列化漏洞 (CVE-2015-5254)

一、漏洞描述 Apache ActiveMQ 是由美国阿帕奇&#xff08;Apache&#xff09;软件基金会开发的开源消息中间件&#xff0c;支持 Java 消息服务、集群、Spring 框架等。属于消息队列组件(消息队列组件&#xff1a;分布式系统中的重要组件&#xff0c;主要解决应用耦合、异步消息…

基于SpringBoot+Vue大学生兼职管理系统的设计与实现

目录 一、前言介绍 二、功能需求 三、功能结构设计 四、管理员功能实现 招聘单位管理 用户管理 论坛管理 公告信息管理 五、招聘单位功能实现 职位招聘管理 职位留言管理 简历投递管理 六、用户功能实现 在线论坛 职位招聘信息 简历投递 简历 七、部分核心代码 …

深入Rust标准库:必备的Rust语言高级指南

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

windows rabbitMq安装

一、Erlang 环境准备 下载安装包 跟我们跑java项目&#xff0c;要装jdk类似。rabbitMQ是基于Erlang开发的&#xff0c;因此安装rabbitMQ服务器之前&#xff0c;需要先安装Erlang环境。 官网直接下载windows直装版本&#xff1a;https://www.erlang.org/downloads 无脑安装&a…

用自然语言来编程GitHub Copilot;提高代码质量开源工具GPTLint;LLMs开源医学Meditron

✨ 1: GitHub Copilot Workspace 以Copilot 为中心的创新开发者环境&#xff0c;让开发者能用自然语言从构思到编码再到软件开发。 GitHub Copilot Workspace是一个以Copilot为中心的开发者环境&#xff0c;旨在使用自然语言从构思、编码到软件开发的全过程中提供帮助。它标志…

一、OSPF基础

目录 1.路由协议的优先级 2.转发原则&#xff1a;最长匹配原则 3.负载分担 4.路由备份&#xff08;浮动路由&#xff09; 5.路由协议的分类 6.动态路由 7.距离矢量路由协议&#xff08;BGP&#xff0c;RIP&#xff09; 8.链路状态路由协议&#xff08;OSPF&#xff0c;I…

指纹浏览器:网络安全与隐私的新工具

在互联网时代&#xff0c;隐私和网络安全成为人们越来越关注的话题。随着数字化的发展&#xff0c;个人信息的泄露和在线追踪的问题愈发严峻。在这个背景下&#xff0c;"指纹浏览器"作为一种新型工具&#xff0c;开始受到关注。撸空投需要了解指纹浏览器。本文将深入…

计算机丢失d3dx9_42.dll怎么解决,最新的5种修复教程来了

在我们日常频繁地使用电脑进行工作或是享受电子游戏带来的乐趣时&#xff0c;偶尔会遇到一个令人稍感困扰的问题&#xff0c;其中之一就是“d3dx942.dll丢失”。这个错误通常出现在运行某些游戏或应用程序时&#xff0c;它会导致程序无法正常运行。为了解决这个问题&#xff0c…

【无标题】场外个股期权多少钱才能做?个人能做吗?

场外个股期权的交易门槛相对较高&#xff0c;主要面向符合特定条件的机构投资者。一般来说&#xff0c;法人或合伙企业等组织参与的&#xff0c;需要满足最近1年末净资产不低于5000万元人民币、金融资产不低于2000万元人民币的条件&#xff0c;并具备3年以上证券、基金、期货、…

《欢乐钓鱼大师》攻略:新手小白如何快速上手?

欢迎来到《钓乐乐》世界&#xff01;这是一个充满乐趣和挑战的钓鱼游戏&#xff0c;本指南将为您提供一系列宝贵的技巧和建议&#xff0c;帮助您成为一名优秀的钓手。无论您是初次尝试还是已经有一定经验&#xff0c;都将从中获益匪浅。 一、精打细算金币 刚开始时金币总是紧缺…

关闭powertoy自启动

Other methods like task manager, start up program folder, they do not work because you can not even find powertoy at these places

【c++】优先级队列与仿函数:C++编程的强大组合

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章我们来讲解优先级队列priority_queue 目录 1.priority_queue的介绍和使用函数使用仿函数的使用与介绍greater和less 2.priority_queue的模拟实现基本框架…

arthas如何排除CPU使用率过高问题

1、首先启动arthas java -jar arthas-boot.jar 2、使用thread查看各线程CPU使用率 thread 可以看到CPU使用率最高的有2个线程&#xff0c;以线程ID为19的为例子&#xff1a; 输入thread 19查看线程19的堆栈信息&#xff1a; thread 19 可以看到是(CpuController.java:78行…

Git Tag:为你的代码版本打上优雅的标签

为你的代码版本打上优雅的标签 在软件开发过程中&#xff0c;版本控制是项目管理的重要一环。Git 作为最流行的版本控制系统之一&#xff0c;为我们提供了强大的工具来管理代码版本。其中&#xff0c;git tag 命令允许我们为代码仓库中的特定提交打上标签&#xff0c;这些标签…

【面试经典 150 | 数组】找出字符串中第一个匹配项的下标

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;find方法二&#xff1a;暴力匹配方法三&#xff1a;KMP 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;…