ThreeJS:简单城市绩效问题

时间:2018-02-11 21:26:12

标签: javascript 3d three.js gis qgis

问题:
我遇到了关于使用 Three JS 渲染的场景的性能方面的主要问题。该问题涉及渲染大量简单几何(11,107)。

(编辑) 每个建筑物都有一个独特的高度,基于高程数据,基于轮廓的独特形状,以及5种可能选项的材料,具体取决于它们占据的区域大小。

隔离了下面第一个场景中的问题,第二个链接提供了上下文。关闭第二个链接中的多边形建筑物说明了图层导致的帧速率下降。

Preview Image


如何确定多边形属性:

  

每个多边形具有均匀高度,但基于建筑物足迹的独特形状。此外,为每个建筑物分配一种相对于其面积大小的渐变颜色(大黄色,中红色小紫色)。作为参考,这是在传递给ThreeJS(QGIS,带QGIStoTHREEJS插件)之前在地理信息系统中实现的。


尝试的解决方案:
我专注于尝试合并多边形几何体以减少渲染调用的数量。但是,因为每个多边形都有指定的颜色,所以我遇到了应用适当的材料和网格的问题。我正在努力解决如何在操作中的两个循环的上下文中执行此操作的问题。


相关代码段:
可以找到完整的源代码here,并且可以下载工作代码here。该片段来自1935年至1987年。
我已将ThreeJS来源修改为与我的问题相关的内容。

    ///////////////// WIP /////////////////
Q3D.PolygonLayer.prototype.build = function(parent) {
    var materials = this.materials,
        project = this.project;

    if (this.objType == "Extruded") {


        // (3) Function for creating the individual building polygons 
        var createSubObject = function(f, polygon, z) {
            var shape = new THREE.Shape(Q3D.Utils.arrayToVec2Array(polygon[0]));
            for (var i = 1, l = polygon.length; i < l; i++) {
                shape.holes.push(new THREE.Path(Q3D.Utils.arrayToVec2Array(polygon[i])));
            }

            // Where the problems start...

            // Here each geometry is created turned into a mesh with its unqiue material
            var geom = new THREE.ExtrudeGeometry(shape, {
                bevelEnabled: false,
                amount: f.h
            });
            var mesh = new THREE.Mesh(geom, materials[f.m].m);
            mesh.position.z = z;
            return mesh;

            //I am not sure how I can merge each polygons geometry with the others whilst allowing each polygon to hold onto its unique colouring...

        };

        // (2) Function for creating polygon layer
        var createObject = function(f) {
            if (f.polygons.length == 1) { // TRUE for building polygons
                return createSubObject(f, f.polygons[0], f.zs[0]); // calls function to create each building

            }
        };
    }


    // (1) function for manufacturing each layer
    this.f.forEach(function(f, fid) {
        f.objs = []; // create array of objects
        var obj = createObject(f); // call polygon creation method
        obj.userData.layerId = this.index;
        obj.userData.featureId = fid;
        this.addObject(obj);
        f.objs.push(obj);
    }, this);

    if (parent) parent.add(this.objectGroup);
};

///////////////// END OF WIP /////////////////



编辑:每个几何的结构如下(f)。

  

几何
   f [ A ] = { h m 多边形 ZS };
  鉴于 f 是11,000个几何中的一个, A 是一个索引(0到1106), h 是一个浮点数, m 是一个int(0到5),用作访问五种颜色类别之一的索引,多边形是构建足迹边缘的坐标列表, zs < / b>是挤出高度。

     

e.g。
  f [11106] = {h:0.0302738130622,m:1,多边形:[[[[ - 23.0863540568,-1.57556646762],[ - 23.1968547585,-1.56551240558],[ - 23.1928481251,-1.49924919288],[ - 23.0803253841,-1.50930323633] ,[ - 23.0863540568,-1.57556646762]]]],ZS:[0.0695352124961]};

     

材料
  有五种颜色类别。 索引充当给定几何体的参考,以找到其相关材料。

     

e.g。
  f [11106] .m指向
   m [ 1 ] = {c:0xcb4778,输入:0};

必须有人知道如何渲染这些建筑物而不会敲出如此多的抽奖电话。任何帮助都会非常感激。

1 个答案:

答案 0 :(得分:3)

您正在向场景中添加数千个拉伸网格,这会因绘制调用过多而导致性能问题。

一种解决方案是创建单个网格,这将导致单个绘制调用。您可以使用ExtrudeGeometry执行此操作,但ExtrudeBufferGeometry效率更高。

var shapes = [];
shapes.push( shape_1 );
...
shapes.push( shape_n );

var geometry = new THREE.ExtrudeBufferGeometry( shapes, extrudeSettings );

var mesh = new THREE.Mesh( geometry, material );

scene.add( mesh );

如果需要对形状应用不同的颜色,可以选择将顶点颜色添加到几何体中。如果没有太多不同的颜色,另一个选项是将groups添加到几何体。哪一个最好取决于您的使用案例。

编辑:实际上,在您的情况下,为每种颜色设置单独的挤压网格可能最简单。

编辑:Here is a fiddle,显示如何使用各种拉伸形状填充单个BufferGeometry

three.js r.89