1. 程式人生 > >基於WebGL架構的3D視覺化平臺—小區水,電,燃氣管線演示

基於WebGL架構的3D視覺化平臺—小區水,電,燃氣管線演示

地下的管線錯綜複雜如何,圖紙並不能完全滿足實際需求,我們就用ThingJS平臺來模擬一個小區水,電,天然氣管線演示。
第一步,利用CampusBuilder搭建模擬場景。CampusBuilder的模型庫有各種各樣的模型,使我們搭建出的場景更逼真。使用CampusBuilde建立層級,之後再給層級加外立面就出現了當前的效果。詳情移步:CampusBuilder3D場景製作工具
演示地址:http://www.thingjs.com/guide/sampleindex.html?name=/uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/水電燃氣管線演示.js?n=0.968666194169896


場景演示

//載入場景程式碼
var app = new THING.App({
    // 場景地址
    "url": "http://www.thingjs.com/./uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/scene/管線演示2",
    //背景設定
    "skyBox": "BlueSky"
});

第二步, 初始化攝像機位置,新增四個按鈕,並建立四個方法。

app.on('load', function () {
    //攝像機位置初始化
    app.camera.position = [0.4374202706634094, 101.92917348318593
, 97.06808820543526]; app.camera.target = [52.75056074670042, -18.885239034825123, -20.619558480451797]; new THING.widget.Button('水管演示', water); new THING.widget.Button('電線演示', electric); new THING.widget.Button('燃氣演示', gas); }); function water() { } function electric() { } function gas() { }

第三步,建立管線,我們這裡寫水管線以後的電線,燃氣管線同理。這裡簡單說一下PolygonLine,它繼承THING.LineBase,同樣有貼圖屬性,可以自己從本地上傳圖片至頁面資源後使用。

var line = null;
function buildLine(points, color) {
    line = app.create({
        type: 'PolygonLine',
        points: points,
        style: {
            color: color,
        }
    });
    line.scrollUV = true;
}

function water() {
    var waterUnderPoints = []; 
    buildingOpacity(0.3);
    app.query(/building_0/).forEach(
        function (parentObj) {
            var points = [];
            points.push(parentObj.selfToWorld([5, -0.8, 0]));
            waterUnderPoints.push(points[0]);
            for (var i = 3; i <= 24; i += 3) {
                points.push(parentObj.selfToWorld([5, i, 0]));
                points.push(parentObj.selfToWorld([5, i, 3]));
                points.push(parentObj.selfToWorld([-5, i, 3]));
                points.push(parentObj.selfToWorld([-5, i, -3]));
                points.push(parentObj.selfToWorld([5, i, -3]));
                points.push(parentObj.selfToWorld([5, i, 0]));
            }
            points.push(parentObj.selfToWorld([5, 24, 0]));
            buildLine(points, '#0000FF');
        }
    );
    waterUnderPoints.push([15.32711, -0.79, -55.655339999999999]);
    buildLine(waterUnderPoints, '#0000FF');
    //renderOrder();
}

function buildingOpacity(num) {
    app.query("*").forEach(function (obj) {
        obj.style.opacity = num;
    });
}

function renderOrder(){
    app.query('.PolygonLine').forEach(
        function (obj) {
            obj.renderOrder = -10000;
        }
    );
}

這裡用到了兩個方法:
1) buildingOpacity(num);
這個方法的主要作用就是為了將場景虛化,更好的展示我們的管線。
2)renderOrder();
下圖是我在程式碼中先註釋掉了renderOrder(),我們先看一下現在的效果。
前

下圖是我在程式碼中加入renderOrder(),再看一下效果
後
起初以為是模型的問題換了模型還是沒解決,之後求助了225986500這個交流群裡的大神們,告訴了我renderOrder這個設定/獲取渲染排序值。

最後一步,創建出電線以及燃氣線就完成了。

function electric() {
    var electricUnderPoints = [];
    buildingOpacity(0.3);
    app.query(/building_0/).forEach(
        function (parentObj) {
            var points = [];
            points.push(parentObj.selfToWorld([3, -0.8, 0]));
            electricUnderPoints.push(points[0]);
            for (var i = 3; i <= 24; i += 2.5) {
                points.push(parentObj.selfToWorld([3, i, 0]));
                points.push(parentObj.selfToWorld([-3, i, 2]));
            }
            points.push(parentObj.selfToWorld([3, 24, 0]));
            buildLine(points, '#00FF00');
            console.log(points);
        }
    );
    electricUnderPoints.push([16.690666, -0.79, -55.115203999999999]);
    buildLine(electricUnderPoints, '#00FF00');
    renderOrder();
}

function gas() {
    var gasUnderPoints = [];
    buildingOpacity(0.3);
    app.query(/building_0/).forEach(
        function (parentObj) {
            var points = [];
            points.push(parentObj.selfToWorld([-6.2, -0.3, 0]));
            gasUnderPoints.unshift(points[0]);
            for (var i = 3; i <= 24; i += 3) {
                points.push(parentObj.selfToWorld([-6.2, i, 0]));
                points.push(parentObj.selfToWorld([-6.2, i, 2]));
                points.push(parentObj.selfToWorld([6.2, i, 2]));
                points.push(parentObj.selfToWorld([6.2, i, -2]));
                points.push(parentObj.selfToWorld([-6.2, i, -2]));
                points.push(parentObj.selfToWorld([-6.2, i, 0]));
            }
            points.push(parentObj.selfToWorld([-6.2, 24, 0]));
            buildLine(points, '#FF0000');
            console.log(points);
        }
    );
    gasUnderPoints.unshift([22.963023600000003, -0.3, 57.8305784]);
    buildLine(gasUnderPoints, '#FF0000');
    renderOrder();
}

最後附上完整程式碼:

//載入場景程式碼
var app = new THING.App({
    // 場景地址
    "url": "http://www.thingjs.com/./uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/scene/管線演示2",
    //背景設定
    "skyBox": "BlueSky"
});

app.on('load', function () {
    //攝像機位置初始化
    app.camera.position = [0.4374202706634094, 101.92917348318593, 97.06808820543526];
    app.camera.target = [52.75056074670042, -18.885239034825123, -20.619558480451797];

    new THING.widget.Button('水管演示', water);
    new THING.widget.Button('電線演示', electric);
    new THING.widget.Button('燃氣演示', gas);

});

function water() {
    var waterUnderPoints = []; 
    buildingOpacity(0.3);
    app.query(/building_0/).forEach(
        function (parentObj) {
            var points = [];
            points.push(parentObj.selfToWorld([5, -0.8, 0]));
            waterUnderPoints.push(points[0]);
            for (var i = 3; i <= 24; i += 3) {
                points.push(parentObj.selfToWorld([5, i, 0]));
                points.push(parentObj.selfToWorld([5, i, 3]));
                points.push(parentObj.selfToWorld([-5, i, 3]));
                points.push(parentObj.selfToWorld([-5, i, -3]));
                points.push(parentObj.selfToWorld([5, i, -3]));
                points.push(parentObj.selfToWorld([5, i, 0]));
            }
            points.push(parentObj.selfToWorld([5, 24, 0]));
            buildLine(points, '#0000FF');
        }
    );
    waterUnderPoints.push([15.32711, -0.79, -55.655339999999999]);
    buildLine(waterUnderPoints, '#0000FF');
    renderOrder();
}

function electric() {
    var electricUnderPoints = [];
    buildingOpacity(0.3);
    app.query(/building_0/).forEach(
        function (parentObj) {
            var points = [];
            points.push(parentObj.selfToWorld([3, -0.8, 0]));
            electricUnderPoints.push(points[0]);
            for (var i = 3; i <= 24; i += 2.5) {
                points.push(parentObj.selfToWorld([3, i, 0]));
                points.push(parentObj.selfToWorld([-3, i, 2]));
            }
            points.push(parentObj.selfToWorld([3, 24, 0]));
            buildLine(points, '#00FF00');
            console.log(points);
        }
    );
    electricUnderPoints.push([16.690666, -0.79, -55.115203999999999]);
    buildLine(electricUnderPoints, '#00FF00');
    renderOrder();
}

function gas() {
    var gasUnderPoints = [];
    buildingOpacity(0.3);
    app.query(/building_0/).forEach(
        function (parentObj) {
            var points = [];
            points.push(parentObj.selfToWorld([-6.2, -0.3, 0]));
            gasUnderPoints.unshift(points[0]);
            for (var i = 3; i <= 24; i += 3) {
                points.push(parentObj.selfToWorld([-6.2, i, 0]));
                points.push(parentObj.selfToWorld([-6.2, i, 2]));
                points.push(parentObj.selfToWorld([6.2, i, 2]));
                points.push(parentObj.selfToWorld([6.2, i, -2]));
                points.push(parentObj.selfToWorld([-6.2, i, -2]));
                points.push(parentObj.selfToWorld([-6.2, i, 0]));
            }
            points.push(parentObj.selfToWorld([-6.2, 24, 0]));
            buildLine(points, '#FF0000');
            console.log(points);
        }
    );
    gasUnderPoints.unshift([22.963023600000003, -0.3, 57.8305784]);
    buildLine(gasUnderPoints, '#FF0000');
    renderOrder();
}

/************************************************************************
 * common
*/

function buildingOpacity(num) {
    app.query("*"