使用three.js创建楼层布局图

       最近大半年一直在做三维部分的工作,之前做三维楼层都是外部加载使用建模工具创建的模型,但是渲染不够灵活、无法绑定房间信息,所以决定来使用three.js来创建楼层布局。

在线地址

《使用three.js创建楼层布局图》

CSDN下载地址《使用three.js创建楼层布局图》https://download.csdn.net/download/u014529917/85431289

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创建楼层布局图》

    原文作者:evomap
    原文地址: https://blog.csdn.net/u014529917/article/details/82836871
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞