AlexKempton
AlexKempton

Reputation: 1698

Three.js: Updating Geometries vs Replacing

I have a scene with lots of objects using ExtrudeGeometry. Each of these need to update each frame, where the shape that is being extruded is changing, along with the amount of extrusion. The shapes are being generated using d3's voronoi algorithm.

See example.

Right now I am achieving this by removing every object from the scene and redrawing them each frame. This is very costly and causing performance issues. Is there a way to edit each mesh/geometry instead of removing from the scene? Would this help with performance? Or is there a more efficient way of redrawing the scene?

I'd need to edit both the shape of the extrusion and the amount of extrusion.

Thanks for taking a look!

Upvotes: 4

Views: 2130

Answers (2)

AlexKempton
AlexKempton

Reputation: 1698

So I managed to come up with a way of not having to redraw the scene every time and it massively improved performance.

http://jsfiddle.net/x00xsdrt/4/

This is how I did it:

  1. Created a "template geometry" with ExtrudeGeometry using a dummy 10 sided polygon.

  2. As before, created a bunch of "points", this time assigning each point one of these template geometries.

  3. On each frame, iterated through each geometry, updating each vertex to that of the new one (using the voronoi alg as before).

  4. If there are extra vertices left over, "bunch" them up into a single point. (see http://github.com/mrdoob/three.js/wiki/Updates.)

Looking at it now, it's quite a simple process. Before, the thought of manipulating each vertex seemed otherworldly to me, but it's not actually too tricky with simple shapes!

Here's how I did the iteration, polycColumn is just a 2 item array with the same polygon in each item:

// Set the vertex index
var v = 0;

// Iterate over both top and bottom of poly
for (var p=0;p<polyColumn.length;p++) {

    // Iterate over half the vertices
    for (var j=0;j<verts.length/2;j++) {

        // create correct z-index depending on top/bottom
        if (p == 1) {
            var z = point.extrudeAmount;
        } else {
            var z = 0;
        }

        // If there are still legitimate verts
        if (j < poly.length) {

            verts[v].x = poly[j][0];
            verts[v].y = poly[j][1];
            verts[v].z = z;

        // If we've got extra verts, bunch them up in the same place
        } else {

            verts[v].x = verts[v - 1].x;
            verts[v].y = verts[v - 1].y;
            verts[v].z = z;
        }

        v++;
    }
}

point.mesh.geometry.verticesNeedUpdate = true;

Upvotes: 2

Flux
Flux

Reputation: 666

If you're not changing the number of faces, you can use morph targets http://threejs.org/examples/webgl_morphtargets.html

You should

  1. Create your geometry
  2. Clone the geometry and make your modifications to it, such as the maximum length of your geometry pillar
  3. Set both geometries as morph targets to your base geometry, for example

    baseGeo.morphTargets.push( { name: "targetName", vertices: [ modifiedVertexArray ] } );

After that, you can animate the mesh this using mesh.updateMorphTargets()

See http://threejs.org/examples/webgl_morphtargets.html

Upvotes: 3

Related Questions