three.js创建楼层布局图的示例代码
作者:evomap
本文主要介绍了three.js创建楼层布局图的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
最近大半年一直在做三维部分的工作,之前做三维楼层都是外部加载使用建模工具创建的模型,但是渲染不够灵活、无法绑定房间信息,所以决定来使用three.js来创建楼层布局。
1.调整光源
灯光有SpotLight、AmbientLight、DirectionalLight等、实际项目一般都是多个灯光组合的方式来创建光源。这里我使用的是DirectionalLight+AmbientLight的方式。
var ambientLight = new THREE.AmbientLight( 0xffffff, 0.8 ); //环境光 scene.add( ambientLight ); var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.3 ); //直射光 directionalLight.position.set( 1, 1, 0 ).normalize(); scene.add( directionalLight );
2.创建地板、房间
网络上查的资料,别人都是以boxGeometry的方式创建房间和地板,但实际中这些不一定是盒子形状,所以我根据底部顶点+高度获取顶部顶点,再根据各顶点计算和指定三角面,最终创建任意形状的盒子模型。
Floor.prototype.getGeometry = function(points,height){ var topPoints = []; for(var i=0;i<points.length;i++){ var vertice = points[i]; topPoints.push([vertice[0],vertice[1]+height,vertice[2]]); } var totalPoints = points.concat(topPoints); var vertices =[]; //所有的顶点 for(var i=0;i<totalPoints.length;i++){ vertices.push(new THREE.Vector3(totalPoints[i][0],totalPoints[i][1],totalPoints[i][2])) } var length = points.length; var faces = []; for(var j=0;j<length;j++){ //侧面生成三角形 if(j!=length-1){ faces.push(new THREE.Face3(j,j+1,length+j+1)); faces.push(new THREE.Face3(length+j+1,length+j,j)); }else{ faces.push(new THREE.Face3(j,0,length)); faces.push(new THREE.Face3(length,length+j,j)); } } var data=[]; for(var i=0;i<length;i++){ data.push(points[i][0],points[i][2]); } var triangles = Earcut.triangulate(data); if(triangles && triangles.length != 0){ for(var i=0;i<triangles.length;i++){ var tlength = triangles.length; if(i%3==0 && i < tlength-2){ faces.push(new THREE.Face3(triangles[i],triangles[i+1],triangles[i+2])); //底部的三角面 faces.push(new THREE.Face3(triangles[i]+length,triangles[i+1]+length,triangles[i+2]+length)); //顶部的三角面 } } } var geometry = new THREE.Geometry(); geometry.vertices = vertices; geometry.faces = faces; geometry.computeFaceNormals(); //自动计算法向量 return geometry; }
3.指定材质
为了使房间看起来更清晰一点,我们顶部指定材质不受光照影响,侧面加入光源变化效果。于是创建两种材质,创建三角面的时候指定面的材质。
var material = [ new THREE.MeshLambertMaterial({color:colorConst[colorIndex].fill,side:THREE.DoubleSide}), //受光照影响 new THREE.MeshBasicMaterial({color:colorConst[colorIndex].fill,side:THREE.DoubleSide}) //不受光照影响 ]; topface.materialIndex = 1; //顶部的三角面 指定材质序号为1,其他默认为0
4.创建盒子顶部的边界线
我们需要添加顶部面界线,来使各个盒子之间分界看起来清晰一点,于是我们根据顶部的坐标创建一条线,添加盒子的同时添加这条线。
//生成顶部的线 Floor.prototype.getBorderGeometry = function(points,color){ var geometry = new THREE.Geometry(); for(var i=0;i<points.length;i++){ var point = points[i]; geometry.vertices.push(new THREE.Vector3(point[0],point[1],point[2])); if(i== point.length-1){ geometry.vertices.push(new THREE.Vector3(point[0][0],point[0][1],point[0][2])); } } return geometry; }
5.创建标注
见我的另一篇笔记:使用three.js开发3d地图初探_凡事有果必有因-CSDN博客 第3、4点。
6.选中效果
raycaster类用于在3d中被鼠标选中的物体,这同样可以选中mesh对象,于是用此方法模拟设备的点击。其中floorGroup是保存所有楼层mesh的object3d对象。
function onDocumentMouseClick(event){ var vector = new THREE.Vector3();//三维坐标对象 vector.set( ( event.clientX / container.clientWidth ) * 2 - 1, - ( event.clientY / container.clientHeight ) * 2 + 1, 0.5 ); vector.unproject( camera ); var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); var intersects = raycaster.intersectObjects(floorGroup.children); //楼层中的元素 if (intersects.length > 0) { var item = intersects[0].object; item.material = new THREE.MeshBasicMaterial({color: "#f86332",side:THREE.DoubleSide}); //选中的样式 } }
到此这篇关于three.js创建楼层布局图的示例代码的文章就介绍到这了,更多相关three.js 楼层布局图内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!