How to merge cone geometries to one mesh?

I have a large number of cone geometries, that I would like to merge together to be part of one mesh, was hoping this could increase performance. First of all, does it even make sense to do this? The amount of cones can be very large, as in 10-100k or (wishful thinking) one million. Each cone is an object with properties radius, height, segments, x y and z.

At first I tried this, I got no errors but nothing was shown on the scene:

  cones.forEach((cone) => {
    const geometry = new THREE.ConeGeometry(
      cone.radius,
      cone.height,
      cone.segments
    );

    const vertices = new Float32Array([cone.x, cone.y, cone.z]);
    geometry.setAttribute(
      "position",
      new THREE.Float32BufferAttribute(vertices, 3)
    );
    geometry.rotateX(Math.PI);
    geometries.push(geometry);
  });

  const material = new THREE.MeshStandardMaterial({
    color: "#e666ed",
    roughness: 0.2
  });

  const merged = BufferGeometryUtils.mergeGeometries(geometries, true);
  const mergedMesh = new THREE.Mesh(merged, material);
  scene.add(mergedMesh);

Another version I tried is to set x, y and z position like this instead:

    geometry.attributes.position.setX(cone.x);
    geometry.attributes.position.setY(cone.y);
    geometry.attributes.position.setZ(cone.z);

Now I got the error: THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The “position” attribute is likely to have NaN values.

I checked that the cones have correct properties for radius, height, and so on, and they do, so I don’t understand where this problem comes from. Any ideas what to do?

Take a look at InstancedMesh.

three.js docs

From the Collection of examples from discourse.threejs.org see

UpdateInstancedMesh-GeometryMaterial
InstancedMeshIndividualSize

1 Like

You overwrite the whole position attribute with just coordinates of one vertex.

If you want to move the geometry, use .translate() method.
Thus, instead of the using of .setAttribute, do something like this:

geometry.rotateX(Math.PI);
geometry.translate(cone.x, cone.y, cone.z);

Another option is to try to use InstancedMesh :thinking:

1 Like

Thank you!

Thanks for explaining! Indeed it seems like InstancedMesh is what I was looking for