Issue with merging objects by its geometries using mergeBufferGeometries()

buffergeometry

#1

In a scene I have a lot of equal static objects, only having a different position. So to have a better performance I want to merge the buffergeometries of these objects togetter into one large object (mergedObj).

So I’ve created a functon called mergeObjects() that merges a copy of a baseObjects geometry and its children geometries into the new mergedObjects geometry and its children geometries.

That is working as expected when having some objects, but if the count of objects expand, or the amount of vertices inside the different geometries rises, problems occur. Some of the geometries will get merged and others aren’t resulting in misformed objects. Sometimes geometries only get merged half.

I’m not sure if this is a problem in my code or that I’m hitting on some limitation of either the merge geometries functions of BufferGeometrieUtils, or some other limitiation of WebGL or memory I’m not aware of. Or maybe I’m missing something else here. But I could use some help at this point after a lot of debugging.

I’ve created a codePen to illustrate the problem:

The base-object in the example exists of an Object3D object with two children: a sphere and a cube. These are on the same x-location, stacked on top of each other.
In canvas you see only the cube gets copied and merged all the way, but the spere is not. If you lower the resolution of the sphere more instances of the spere get copied, so it has something to do with a limitiation somewhere about maximum buffer size of maximum amount of vertices or something like that.

After lot of debugging I’m kind of stuck on this. Anybody who can give me some clue or direction where to look to solve this strange issue? Thanks!


#2

Can you please try to refactor your code according to the following example: https://threejs.org/examples/#webgl_geometry_minecraft

The idea is to use BufferGeometryUtils.mergeBufferGeometries only once. All intermediate geometries are maintained in an array and provided as the parameter of the function. Your code feels a little bit complex right now since you are using stuff like recursive calls. Something like that makes it harder to debug the problem.


#3

Thanks for your response @Mugen87. I just turned the code into creating arrays of geometries first and than calling merge on them once, like you advised.

Here’s the updated codepen:


(Please don’t get intimidated by all the code from the bufferutils I put in there, for me that was just the fastest way of including the threejs utility file.)

The code about merging starts at line 437 and is basically only this:

    const count = 90;
    const mergedObj = baseObj.clone();
    let geometries = [];
    for (let c = 0; c < baseObj.children.length; c++) {
        geometries = [];
        for (let i = 0; i < count; i++) {
            geometries[i] = baseObj.children[c].geometry.clone();
            geometries[i].translate(i * 0.5, 0, 0);
        }
        const mergedGeo = THREE.BufferGeometryUtils.mergeBufferGeometries(geometries);
        mergedObj.children[c].geometry = mergedGeo;
    }

    this.scene.add(mergedObj);

BTW In this demo you can see clearly not only it skips merging the last spheres, it also truncates the last sphere it can handle.


#4

Really? Nobody can help me on this one, not even with this simplyfied version? @Mugen87 ?


#5

I’ve created a new fiddle with parts of your code: https://jsfiddle.net/f2Lommf5/6877/

The result of the merging looks now good.


#6

Thanks @Mugen87 for taking the time to setup a project. I understand just merging geometries work with the utils, but what I want and have in the codepen I created, is merge all geometries of equal Objects, including its childrens geometries. So the result I’m after should be one object with its geometry (or not if it’s just an Object3D, but not a mesh, to group children) and the same amount of children the base object has (also either an Object3D/noMesh with subchildren, or a Mesh with or without children).

The example I posted is very simplified. In the project however I have a big gltf scene full of objects. For all equal static (but complex) object, I only include 1 instance in the gltf file, that’s the baseObj. After importing the glft has finished, more ‘instances’ like the baseObj needs to be created on different positions in the scene. But instead of cloning the object, I clone the geometries of the baseObj instead and after that its childrens geometries, making one large object of merged geometries and also merged children geometries (with sub children geometries and so on). That should work, because I only merge objects having geometries (is mesh) and do the same with all children of the baseObj. That’s why I use recursive functions in my project.

But for some strange reason merging children seem to be a problem. I can’t find a reason why, 'cause to me it should work exactly the same as merging the geometry of the object itself. But I might miss something here.

I’d say puting the result of the merge inside the child.geometries should work the same way as putting a result of a merge in the geometry of the object itself. I can’t see a difference, and it looks like it’s doing what is expected for the first few objects too. But I must be missing something here, 'cause it’s getting broke the more meshes/vertices/larger buffers are involved.

So although nice to know merging is working fine with lots of objects, that’s not really the question I have. Basically I want to merge the geometries of objects AND all of its childrens geometries too. I still can’t figure out why this is only working for a limited amount of objects. Any help or pointing in a direction is highly appreciated!