用Three.js实现简单布局的3D房间
废话不说了,直接上成果图。
代码如下
<!doctype html>
<html lang="en">
<head>
<title>房间布局</title>
<meta charset="utf-8">
<meta name="viewport"content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>
<body><script src="js/jquery-1.9.1.js"></script><script src="js/Three.min.js"></script><script src="js/OrbitControls.js"></script><script src="js/ThreeBSP.js"></script><script src="js/Detector.js"></script><script src="js/Stats.js"></script><script src="js/THREEx.KeyboardState.js"></script><script src="js/THREEx.FullScreen.js"></script><script src="js/THREEx.WindowResize.js"></script><!-- people --><script src="people/js/three.js"></script><script src="people/js/DDSLoader.js"></script><script src="people/js/MTLLoader.js"></script><script src="people/js/OBJLoader.js"></script><script src="people/js/Detector.js"></script><script src="people/js/stats.min.js"></script><script src="people/js/PathControls.js"></script><script src="people/js/Tween.js"></script><script src="people/js/RequestAnimationFrame.js"></script><div id="ThreeJS" style="position: absolute; left: 0px; top: 0px"></div><script>// 设置全局变量var scene, camera, renderer, controls, tween, door;var keyboard = new THREEx.KeyboardState();//保持键盘的当前状态,可以随时查询var clock = new THREE.Clock();var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;//var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;var VIEW_ANGLE = 75, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 10000;var materialArrayA = [];var materialArrayB = [];var matArrayA = [];//内墙var matArrayB = [];//外墙var dummy = new THREE.Object3D();//仿制品init();animate();//1.场景 function initScene() {scene = new THREE.Scene();}//2.相机function initCamera() {camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);camera.position.set(0, 1000, 1800);camera.lookAt(scene.position);camera.lookAt(0, 0, 0);scene.add(camera);}//3.渲染器function initRender() {if (Detector.webgl)renderer = new THREE.WebGLRenderer({antialias : true});elserenderer = new THREE.CanvasRenderer();//设置渲染器的大小为窗口的内宽度,也就是内容区的宽度。renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);container = document.getElementById('ThreeJS');container.appendChild(renderer.domElement);renderer.setClearColor(0x4682B4, 1.0);}//4.事件function initEvent() {THREEx.WindowResize(renderer, camera);THREEx.FullScreen.bindKey({charCode : 'm'.charCodeAt(0)});}//5.控制function initControls() {controls = new THREE.OrbitControls(camera, renderer.domElement);}//6.光源function initLight() {// 位置不同,方向光作用于物体的面也不同,看到的物体各个面的颜色也不同 // A start, 第二个参数是光源强度var directionalLight = new THREE.DirectionalLight(0xffffff, 1);//模拟远处类似太阳的光源directionalLight.position.set(0, 100, 0).normalize();scene.add(directionalLight);//A endvar ambient = new THREE.AmbientLight(0xffffff, 1); //AmbientLight,影响整个场景的光源ambient.position.set(0, 0, 0);scene.add(ambient);//var pointlight = new THREE.PointLight(0x000000,1.5,2000);//scene.add(pointlight); }//创建地板 function createFloor() {var loader = new THREE.TextureLoader();loader.load("images/floor.jpg", function(texture) {texture.wrapS = texture.wrapT = THREE.RepeatWrapping;texture.repeat.set(10, 10);var floorGeometry = new THREE.BoxGeometry(1600, 1100, 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;scene.add(floor);});//茶色:0x58ACFA 透明玻璃色:0XECF1F3var glass_material = new THREE.MeshBasicMaterial({color : 0XECF1F3});glass_material.opacity = 0.4;glass_material.transparent = true;var left_wall = returnWallObject(20, 200, 1100, 0, matArrayB, -801,100, 0);var left_cube = returnWallObject(20, 110, 1100, 0, matArrayB, -801,100, 0);createResultBsp(left_wall, left_cube, 1);createCubeWall(1, 110, 1100, 0, glass_material, -801, 100, 0);var right_wall = returnWallObject(20, 200, 1100, 1, matArrayB, 801,100, 0);var right_cube = returnWallObject(20, 110, 1100, 0, matArrayB, 801,100, 0);createResultBsp(right_wall, right_cube, 1);createCubeWall(1, 110, 1100, 0, glass_material, 801, 100, 0);}//墙上挖门,通过两个几何体生成BSP对象function createResultBsp(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 : 0xafc0ca,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;scene.add(result);}//创建墙function createCubeWall(width, height, depth, angle, material, x, y, z) {var cubeGeometry = new THREE.BoxGeometry(width, height, depth);var cube = new THREE.Mesh(cubeGeometry, material);cube.position.x = x;cube.position.y = y;cube.position.z = z;cube.rotation.y += angle * Math.PI; //-逆时针旋转,+顺时针scene.add(cube);}//返回墙对象function returnWallObject(width, height, depth, angle, material, x, y,z) {var cubeGeometry = new THREE.BoxGeometry(width, height, depth);var cube = new THREE.Mesh(cubeGeometry, material);cube.position.x = x;cube.position.y = y;cube.position.z = z;cube.rotation.y += angle * Math.PI;return cube;}//创建墙纹理function createWallMaterail() {matArrayA.push(new THREE.MeshPhongMaterial({color : 0xafc0ca})); //前 0xafc0ca :灰色matArrayA.push(new THREE.MeshPhongMaterial({color : 0xafc0ca})); //后 matArrayA.push(new THREE.MeshPhongMaterial({color : 0xd6e4ec})); //上 0xd6e4ec: 偏白色matArrayA.push(new THREE.MeshPhongMaterial({color : 0xd6e4ec})); //下 matArrayA.push(new THREE.MeshPhongMaterial({color : 0xafc0ca})); //左 0xafc0ca :灰色matArrayA.push(new THREE.MeshPhongMaterial({color : 0xafc0ca})); //右matArrayB.push(new THREE.MeshPhongMaterial({color : 0xafc0ca})); //前 0xafc0ca :灰色matArrayB.push(new THREE.MeshPhongMaterial({color : 0x9cb2d1})); //后 0x9cb2d1:淡紫matArrayB.push(new THREE.MeshPhongMaterial({color : 0xd6e4ec})); //上 0xd6e4ec: 偏白色matArrayB.push(new THREE.MeshPhongMaterial({color : 0xd6e4ec})); //下 matArrayB.push(new THREE.MeshPhongMaterial({color : 0xafc0ca})); //左 0xafc0ca :灰色matArrayB.push(new THREE.MeshPhongMaterial({color : 0xafc0ca})); //右}//创建房间布局function createLayout() {// 墙面1 立方体比较长的面 左一createCubeWall(10, 200, 900, 0, matArrayB, -651, 100, 0);// 墙面2 立方体比较长的面 右一createCubeWall(10, 200, 900, 1, matArrayB, 651, 100, 0);// 墙面3 门对面的墙 立方体比较短的面 createCubeWall(10, 200, 1310, 1.5, matArrayB, 0, 100, -451);// 墙面4 带门的面 var wall = returnWallObject(1310, 200, 10, 0, matArrayB, 0, 100,455);// 门框 var door_cube = returnWallObject(100, 180, 10, 0, matArrayB, 0, 90,455);createResultBsp(wall, door_cube, 1);//为墙面安装门,右门var loader = new THREE.TextureLoader();loader.load("images/door_right.png", function(texture) {var doorgeometry = new THREE.BoxGeometry(100, 180, 2);var doormaterial = new THREE.MeshBasicMaterial({map : texture,color : 0xffffff});doormaterial.opacity = 1.0;doormaterial.transparent = true;door = new THREE.Mesh(doorgeometry, doormaterial);door.position.set(-50, 0, 0);var door1 = door.clone();door1.position.set(50, 0, 0);door1.visible = false;dummy.add(door);dummy.add(door1);dummy.position.set(50, 90, 451)scene.add(dummy);});// 房间A:隔墙1 createCubeWall(10, 200, 250, 0, matArrayA, -151, 100, 325);//房间A:隔墙2 无门createCubeWall(10, 200, 220, 0.5, matArrayA, -256, 100, 201);// 厨房:隔墙3 createCubeWall(350, 200, 10, 0, matArrayA, 481, 100, 131);// 厨房:隔墙4 无门createCubeWall(10, 200, 200, 0, matArrayA, 301, 100, 225);// 房间B createCubeWall(350, 200, 10, 0, matArrayA, -471, 100, -50);//房间B 无门createCubeWall(200, 200, 10, 0.5, matArrayA, 0, 100, -350);// 房间CcreateCubeWall(220, 200, 10, 0, matArrayA, 540, 100, -50);//房间C 无门createCubeWall(200, 200, 10, 0.5, matArrayA, 250, 100, -350);//厕所var cube = returnWallObject(10, 200, 260, 0.5, matArrayA, 125, 100,-250);//厕所门框var door_cube1 = returnWallObject(10, 160, 80, 0.5, matArrayA, 155,90, -250);createResultBsp(cube, door_cube1, 2);//茶色:0x58ACFA 透明玻璃色:0XECF1F3var glass_material = new THREE.MeshBasicMaterial({color : 0x58ACFA});glass_material.opacity = 0.6;glass_material.transparent = true;createCubeWall(1, 180, 80, 0.5, glass_material, 155, 90, -250);}//7.初始化OBJ对象function initObject() {//墙纹理createWallMaterail();createFloor();createLayout();}//初始化函数function init() {initScene();initCamera();initRender();initEvent();initControls();initLight();initObject();//监听键盘按键document.addEventListener("keydown", onkeyDown, false);}var door_state = true;//默认是门是关闭的//Enter=13,Space=32;function onkeyDown(event) {switch (event.keyCode) {case 13:console.log(event.keyCode);if (door_state) {dummy.rotation.y += 0.5 * Math.PI;door_state = false;} else {dummy.rotation.y -= 0.5 * Math.PI;door_state = true;}break;default:console.log(event.keyCode);break;}}function animate() {requestAnimationFrame(animate);renderer.render(scene, camera);TWEEN.update();update();}function update() {var delta = clock.getDelta();var moveDistance = 200 * delta;var rotateAngle = Math.PI / 2 * delta;controls.update();}</script>
</body>
</html>
通过Enter键可控制开门和关门动作。门的旋转是通过,把门克隆一份,把克隆的那个设置为不可见,然后把两个门打个组 ,这个时候中旋转组就可以了。
此时的旋转中心实际是在组的中心,但设置一半不可见 ,看起来就像是门在旋转了。注意的是,组内的东西的坐标是相对于组的组内,两个门的坐标应该分别是x轴的正负轴上,整个组的位置应该是原来门应该在的位置。
(这也是我向一位大神请教的,真的很感谢他那么耐心的教我,O(∩_∩)O)
运行方式:
在支持webgl的浏览器上打开room.html,即可看到效果图。如果加载不出来,打开Chrome快捷方式的属性中设置:右击Chrome浏览器快捷方式, 选择“属性”,在“目标”中加上"--allow-file-access-from-files",注意前面有个空格。修改完成,点击应用,确定后,关闭所有chrome上的窗口,重启chrome。再找到该资源room.html文件,以Google Chrome浏览器方式打开即可。
错误解决。
如果出现地板和门的两张图片加载不出来时,提示已被跨源资源共享策略阻止加载。解决办法第一种是如上图所示在Chrome的属性加"--allow-file-access-from-files";第二种就是把图片位置的相对路径改成绝对路径。
原demo发邮件索取的太多了,都从网盘自取吧。就是个demo,不喜勿喷,渣渣博主很玻璃心。
链接:https://pan.baidu.com/s/1UmBcjFCQ5QzdLcfGp-gpug 密码:r5c8
用Three.js实现简单布局的3D房间相关推荐
- JS——实现简单的随机3D骰子
描述: JS--实现简单的随机3D骰子. 效果: 实现: html文件: <!DOCTYPE html> <html lang="en"><head& ...
- html制作3d筛子,JS实现简单随机3D骰子
本文实例为大家分享了JS实现简单随机3D骰子的具体代码,供大家参考,具体内容如下 描述: JS--实现简单的随机3D骰子. 效果: 实现: html文件: Document PLAY css文件: @ ...
- moment转换时间戳_酷炫时间轮盘:JS元素圆形布局制作时间轮盘动画效果
点击右上方红色按钮关注"web秀",让你真正秀起来 前言 前段时间看抖音,有人用时间轮盘作为动态的桌面壁纸,感觉很好玩,于是突发奇想,可以用JS来实现这个功能. 来来来,先看看成果 ...
- Three.js 绘图之不规则路径 3D 墙体生成算法
HTML5 是当前最流行的 Web 前端开发技术,其中最大的改变即是 Canvas 对象在各大浏览器平台中变得通用,在 HTML5 流行之前在 Web 端显示三维图形有很多种技术,但各种技术之间存在很 ...
- css画钟表_利用css+原生js制作简单的钟表
利用css+原生js制作简单的钟表.效果如下所示 实现该效果,分三大块:html.javascript.css html部分html部分比较简单,定义一个clock的div,内部有原点.时分秒针.日期 ...
- 记录--Three.js的简单使用,Three.js在vue3.x中导入.pcd三维模型文件
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 本文说明 本文主要简单介绍了,在Vue3.x项目中如何简单的使用Three.js,导入PCD三维模型文件. 模型显示 项目实现 第一步 首 ...
- 1、Three.js 实现元宇宙汽车 3D 模型(网络)
Three.js 实现元宇宙汽车 3D 模型 技术采用three.js+React实现. Step1:创建一个React项目 create-react-app your-app Step2:加载thr ...
- (转)使用Three.js制作一个基本的3D飞行游戏
今天,我们将使用Three.js创建一个简单的3D飞机,使WebGL更简单.由于GLSL的复杂性和语法,WebGL对许多开发人员来说是一个相当陌生的世界.但是通过Three.js,浏览器中的3D变得非 ...
- Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)
目录 一. Vue Grid Layout 简介 二.vue-grid-layout 的安装与使用 三. 属性 3.1 gridItem 的必须属性 3.2 框架元素的实际宽度高度计算方式 3.3 元 ...
最新文章
- sm2加密算法实例_实例说明加密算法
- 2014025630《嵌入式程序设计》第七周学习总结
- Android对话框dialog大全
- 探索Julia(part9)--字符串处理
- 使用JSTL视图探索Spring Controller
- JavaScript中DOM操作
- logstash mysql 准实时同步到 elasticsearch
- 汇编笔记1:debug
- NAT,PAT、OSPF的相关配置
- 开机LOGO与动画修改
- vscode代码对比功能
- 解决:启动springboot项目,Unable to start web server; nested exception is org.springframework.beans.factory
- Python练习题答案: 纳特拼音alaphabeta【难度:1级】--景越Python编程实例训练营,1000道上机题等你来挑战
- WinMerge文字重叠问题
- 31省市自治区农村居民消费价格指数(2010-2020年)
- 骨传导耳机是什么意思?骨传导耳机工作原理是什么
- 刚刚!微软又放大招!让草稿几秒钟变App!
- 令人愉快的 Nuxt3 教程 (二): 快速轻松地搭建博客
- pandas, dataframe获取最后一行的三种方法
- 视频监控网络传输计算方法