使用ThreeJs从零开始构建3D智能仓库

您所在的位置:网站首页 3dmax场景建模教学楼 使用ThreeJs从零开始构建3D智能仓库

使用ThreeJs从零开始构建3D智能仓库

2024-06-24 17:10| 来源: 网络整理| 查看: 265

使用ThreeJs从零开始构建3D智能仓库——第一章 写在前面如何实现从最简单的开始,构建地面准备——浏览器跨域设置初始化场景、相机、灯光、渲染器创建地板创建控制器及其他完整的代码 结束语

写在前面

最近因为项目需求,需要构建一个3D仓库,能够显示整个仓库的布局以及库内货物的情况。于是刚入职两年的小白我毅然决然接下了这个沉重的任务(手动狗头),但是我并没有任何关于3D开发的经验,于是乎就各种翻书查百度,经过几个月孤独的开发与实践,已经能够初步的完成预期的设想了。 先来给大家看一下仓库的整体面貌 2019.11.26 更新:我最近建立了个人网站,大家可以访问下面的链接查看演示 3D仓库演示 2019.11.28 更新:代码和图片资源等已上传至GitHub https://github.com/xiao149/ThreeJsDemo 在这里插入图片描述 再来一些细节的,鼠标单击一个物体,可以在物体周围高亮一圈白光突出显示,可以显示一个标签做描述 在这里插入图片描述 每一个库位都是独立可选中的 在这里插入图片描述 更有趣的是双击画面上的箱子(也就是货物啦),可以弹出详细的货物信息,比如下图托盘上就叠了好几层箱子,选中某一个箱子还可以显示货物的详细详细,比如数量批号之类的 在这里插入图片描述 当然我还很闲地给门做了个动画,可以实现开门和关门的动作,kono下图哒(虽然只是张静态的) 在这里插入图片描述

如何实现

终于到了最关键的时候呢,既然展示完了,就当然地要给大家如何完成这一切的步骤啦。这是从零开始构建3D仓库的第一篇,所以我想从一个从未接触过ThreeJs的小白的角度来开始介绍。

ThreeJs是一个面向网页端的3D设计框架,借用这个Js你可以将精致的3D建模、特效、交互、物理系统统统搬到网页上,理论上,你可以在浏览器上开发一整个3D游戏,当然我只是个初学者,向来也只是自学的,能够教给大家的很有限,这是ThreeJs官网的地址,点此进入,上面有很多有用的示例和开发文档,不过英语水平可能得好点,国内也有中文的网站不过更新的比较慢我这就不给了,大家可以自行百度。

从最简单的开始,构建地面

无论怎样的高楼大厦都是从一砖一瓦一步步搭建的,我们的3D仓库也一样,虽然这是最简单的功能(如下图),但却包含了最基本的要素:场景,相机,光照,物体,渲染器,控制器。接下来我将一一为大家介绍。

准备——浏览器跨域设置

我们在本地开发的时候经常遇到跨域的问题,即在html中无法读取到本地存放的图片等等,下图展示了跨域问题出现的时候 在这里插入图片描述 可见门,窗户,地板等有贴图的地方全部变成了空白,F12调试模式下可以看到跨域错误的具体报错信息,解决方法很简单,就是在谷歌浏览器快捷方式下右键属性,在快捷方式的目标下,加入 --allow-file-access-from-files,注意最前面有一个空格,如下图所示 在这里插入图片描述 完成后重新打开浏览器,就可以看到跨域问题已经解决啦,门窗地板全部显示出来啦! 在这里插入图片描述

初始化场景、相机、灯光、渲染器

这部分代码比较简单,而且不同的项目基本都类似,所以我就直接放出代码了,不再做过多介绍。 完成之后能够显示背景为蓝色的一个场景,当然里面什么都没有,因为我们还没有添加物体。

var stats = initStats(); var scene, camera, renderer, light; // 初始化场景 function initScene() { scene = new THREE.Scene(); } // 初始化相机 function initCamera() { camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000); camera.position.set(0, 800, 1500); camera.lookAt(new THREE.Vector3(0, 0, 0)); } // 初始化灯光 function initLight() { var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.3 );//模拟远处类似太阳的光源 directionalLight.color.setHSL( 0.1, 1, 0.95 ); directionalLight.position.set( 0, 200, 0).normalize(); scene.add( directionalLight ); var ambient = new THREE.AmbientLight( 0xffffff, 1 ); //AmbientLight,影响整个场景的光源 ambient.position.set(0,0,0); scene.add( ambient ); } // 初始化性能插件 function initStats() { var stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.body.appendChild(stats.domElement); return stats; } // 初始化渲染器 function initRenderer() { renderer = new THREE.WebGLRenderer({antialias: true}); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearColor(0x4682B4,1.0); document.body.appendChild(renderer.domElement); } 创建地板

同样废话不多说,直接上代码!

//创建地板 function createFloor(){ var loader = new THREE.TextureLoader(); loader.load("./ThreeJs/images/floor.jpg",function(texture){ texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.repeat.set( 10, 10 ); var floorGeometry = new THREE.BoxGeometry(2600, 1400, 1); var floorMaterial = new THREE.MeshBasicMaterial( { map: texture, side: THREE.DoubleSide } ); var floor = new THREE.Mesh(floorGeometry, floorMaterial); floor.position.y = -0.5; floor.rotation.x = Math.PI / 2; floor.name = "地面"; scene.add(floor); }); }

这里使用了本地的图片作为地板的贴图素材,大家可以自定义自己需要的图片。完成之后大概是这个样子 在这里插入图片描述 光秃秃的背景上出现了一个光秃秃的地面。(我变秃了也变强了)

创建控制器及其他

完成上面的步骤,我们发现场景还无法旋转、平移、放大缩小等。这些就要依赖我们的控制器了,ThreeJs官网上有很多类型的控制器,我们这里选用比较常用的轨道球控制器,代码很简单。

// 初始化轨迹球控件 function initControls() { controls = new THREE.OrbitControls( camera, renderer.domElement ); controls.enableDamping = true; controls.dampingFactor = 0.5; // 视角最小距离 controls.minDistance = 100; // 视角最远距离 controls.maxDistance = 5000; // 最大角度 controls.maxPolarAngle = Math.PI/2.2; }

这里设置了最大的旋转角度,防止某些绅士看到人家下面呢!

完整的代码

之前我们分模块或者功能讲解了每一部分的代码,这一节里我贴出全部的代码,是可以直接运行的哦,相关引入的JS在ThreeJS官网上都有。

3D库图显示 body { margin: 0; overflow: hidden; } var stats = initStats(); var scene, camera, renderer, controls, light; // 初始化场景 function initScene() { scene = new THREE.Scene(); scene.fog = new THREE.Fog( scene.background, 3000, 5000 ); } // 初始化相机 function initCamera() { camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000); camera.position.set(0, 800, 1500); camera.lookAt(new THREE.Vector3(0, 0, 0)); } // 初始化灯光 function initLight() { var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.3 );//模拟远处类似太阳的光源 directionalLight.color.setHSL( 0.1, 1, 0.95 ); directionalLight.position.set( 0, 200, 0).normalize(); scene.add( directionalLight ); var ambient = new THREE.AmbientLight( 0xffffff, 1 ); //AmbientLight,影响整个场景的光源 ambient.position.set(0,0,0); scene.add( ambient ); } // 初始化性能插件 function initStats() { var stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.body.appendChild(stats.domElement); return stats; } // 初始化渲染器 function initRenderer() { renderer = new THREE.WebGLRenderer({antialias: true}); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearColor(0x4682B4,1.0); document.body.appendChild(renderer.domElement); } //创建地板 function createFloor(){ var loader = new THREE.TextureLoader(); loader.load("./ThreeJs/images/floor.jpg",function(texture){ texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.repeat.set( 10, 10 ); var floorGeometry = new THREE.BoxGeometry(2600, 1400, 1); var floorMaterial = new THREE.MeshBasicMaterial( { map: texture, side: THREE.DoubleSide } ); var floor = new THREE.Mesh(floorGeometry, floorMaterial); floor.position.y = -0.5; floor.rotation.x = Math.PI / 2; floor.name = "地面"; scene.add(floor); }); } // 初始化模型 function initContent() { createFloor(); } // 初始化轨迹球控件 function initControls() { controls = new THREE.OrbitControls( camera, renderer.domElement ); controls.enableDamping = true; controls.dampingFactor = 0.5; // 视角最小距离 controls.minDistance = 100; // 视角最远距离 controls.maxDistance = 5000; // 最大角度 controls.maxPolarAngle = Math.PI/2.2; } // 更新控件 function update() { stats.update(); controls.update(); } // 初始化 function init() { initScene(); initCamera(); initRenderer(); initContent(); initLight(); initControls(); document.addEventListener('resize', onWindowResize, false); } // 窗口变动触发的方法 function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); update(); } init(); animate();

完成之后就可以看到一个可以随意转动移动缩放的地面啦!

结束语

第一章我们涉及的内容都比较简单,但也是最为基础关键的,致此我们创建好了一个可以控制的地面,下一章我们将创建墙面,门,窗户,以及选中物体的交互事件。 我跟广大学习ThreeJs的初学者一样,仍带着懵懂的心去探索这片新大陆,CSDN上的许多前辈都给了我很多关键的灵感和技术方法,如果大家有兴趣,也可以互相交流成长,欢迎大家指导咨询。PS:大家有兴趣可以点进去我的头像,陆陆续续也写了十来篇了。 链接:使用ThreeJs从零开始构建3D智能仓库——第一章: 点我跳转. 链接:使用ThreeJs从零开始构建3D智能仓库——第二章: 点我跳转. 链接:使用ThreeJs从零开始构建3D智能仓库——第三章: 点我跳转. 链接:使用ThreeJs从零开始构建3D智能仓库——第四章: 点我跳转. 链接:使用ThreeJs从零开始构建3D智能仓库——第五章: 点我跳转.



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3