天天看點

記一次three.js 布局3D室内簡易地圖

随着html5 canvas的流行,酷炫的web端效果層出不窮,搭載基于webgl 的three.js的圖形庫可以做出基于web的3D效果。最近應對客戶需求,2D平面地圖已經不太滿足客戶的口味,3D的效果更讓人接受,先看一下成果圖。

記一次three.js 布局3D室内簡易地圖

對應室内地圖CAD圖紙 進行3D立體效果拉伸,再加上一些實景模型的搭配,使得整體效果更好。

地圖地闆牆體的依據cad 尺寸制定的json資料協定:

{
        title: '',
        x: 480,
        y: 80,
        z: 0,
        width: 2,
        height: 866,
        color: "#30B2BB",
        textcolor: "black",
        bordercolor: "rgba(76, 181, 216, 0.85)",
        bspMesh: [

            // 小房子的牆
            {
                type: 'union',
                geometryType: 'box', color: '#fff',

                x: 0,
                y: 80,
                z: 82,
                width: 38,
                height: 2,
                positionY: 0,
            }]
}
           

3D坐标軸對應2D多了一個高度 ,這裡高度設定為Y軸,2D.Y=>3D.Z  2D.X=>3D.X 。3D場景新增的幾何體都是模型的中心在原點,而2D的原點是從螢幕左上角開始(0,0),是以這裡需要一個轉換,首先确認地圖的最大長寬尺寸,然後通過計算得到2D坐标轉換3D時基于地圖的位置設定其position,

   data.x = data.width / 2 - MapXLength / 2 + data.x;

    data.z = data.height / 2 - MapZLength / 2 + data.z;

正常的地面牆面,以及柱子,牆面門通過,ThreeBSP庫進行模型的組合,打孔,完成。

地圖區域的說明通過DIV+css來完成,實時計算3D坐标系固定位置對于2D螢幕的位置來實作引導性的連接配接:

function worldPointToScreen(point) {
    let vec2 = point.project(camera);
    let halfWidth = window.innerWidth / 2;
    let halfHeight = window.innerHeight / 2;
    return {
        x: vec2.x * halfWidth + halfWidth,
        y: -vec2.y * halfHeight + halfHeight
    };
}
           

轉換公式如上。

地圖操作控制器是OrbitControls。