0

Say that I had generated a THREE.BufferGeometry from a THREE.Geometry named oldGeom like so:

// using WebGLRenderer
var geometry = new THREE.BufferGeometry();
var indices = new Uint16Array(oldGeom.vertices.length);
var vertices = new Float32Array(oldGeom.vertices.length * 3);
for (var i = 0; i < oldGeom.vertices.length; i++) {
    indices[i] = i;
    vertices[i * 3 + 0] = oldGeom.vertices[i].x;
    vertices[i * 3 + 1] = oldGeom.vertices[i].y;
    vertices[i * 3 + 2] = oldGeom.vertices[i].z;
}
geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
geometry.setIndex(new THREE.BufferAttribute(indices, 1));

Hopefully I have the indexing right. At this point, how could I add a face using the indices? I'm planning to loop through the faces of oldGeom to add them all here, but I can't find any documentation on this. Thanks!

Similar to this question, but with an indexed geometry.

Community
  • 1
  • 1
mostsquares
  • 834
  • 8
  • 27
  • Is there a reason you're using BufferGeometry? It should usually be reserved for when you're under serious performance constraints and need to squeeze out a bit of extra optimization, and even then you had better know what you're doing. Aside from that, I'm unclear of the question. Are you asking how to recreate the triangles of the original Geometry on the BufferGeometry? Or are you asking how to add entirely new faces to the BufferGeometry that did not exist in `oldGeom`? By the way, BufferGeometry has a convenience method for cloning from Geometry so why not use that? – jered Apr 19 '16 at 23:05
  • Thanks for the comment! Yeah -- I'm using BufferGeometry so that I can dynamically add new vertices by exploiting `.setDrawRange(...)`, per WestLangley's suggestions on [this question](http://stackoverflow.com/questions/36426139/incrementally-display-three-js-tubegeometry/36439563#36439563). That's also why I can't use `.fromGeometry(...)` to build this BufferGeometry -- I want to have buffers that are larger than the size of the original geometry (sorry, I didn't write the code above with larger buffers!) – mostsquares Apr 20 '16 at 00:10
  • Anyway, to rephrase my question: I'm just wondering how someone would define a triangle in an indexed BufferGeometry. Is there some array that I can populate with vertex indices to define my faces? – mostsquares Apr 20 '16 at 00:11
  • Thanks @JCD and let me know if I can clarify more – mostsquares Apr 20 '16 at 00:12
  • OK, I've been reading the source, and I gotta ask these two very dumb questions -- are the indices face indices, or vertex indices? And are the faces defined by adjacent trios in the position attribute? – mostsquares Apr 20 '16 at 01:15

1 Answers1

4

From the documentation for BufferGeometry:

index (itemSize: 3)

Allows for vertices to be re-used across multiple triangles; this is called using "indexed triangles," and works much the same as it does in Geometry: each triangle is associated with the index of three vertices. This attribute therefore stores the index of each vertex for each triangular face. If this attribute is not set, the renderer assumes that each three contiguous positions represent a single triangle.

The way "indexed triangles" work is that "position" is an array of numbers, with every consecutive set of 3 numbers representing one vertex (x, y, z). "Index" is an array of numbers, where every consecutive set of 3 numbers represents one face, by referring to the indices of vertices in the "position" array.

You might have an array of vertices like this:

var vertices = [0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0];

You can think of this array as sets of XYZ coordinates like this:

var vertices = [
    0, 0, 0, // vertex index 0
    1, 0, 0, // vertex index 1
    1, 1, 0, // vertex index 2
    0, 1, 0  // vertex index 3
];

Now if you have an index array like this:

var indices = [0, 1, 2, 1, 2, 3];

It represents two triangles:

var indices = [
    0, 1, 2, // face with vertices at indices 0, 1, 2
    1, 2, 3  // face with vertices at indices 1, 2, 3
];

So triangle #1 has vertices at XYZ (0, 0, 0), (1, 0, 0), (1, 1, 0) while triangle #2 has vertices at XYZ (1, 0, 0), (1, 1, 0), (0, 1, 0).

On the other hand you can define vertices without using an index. The power of indexing is that it lets you reuse vertices defined in the array instead of listing them redundantly every time they appear in a triangle. If you have a single array, vertices, then quite simply, every set of 9 numbers in the array is one triangle (three sets of consecutive vertices, each with three consecutive XYZ values).

Going back to your original question, if you want to add triangles to your BufferedGeometry, I see two basic options:

  1. Add the triangles to the original oldGeom object, and then convert it. It's a lot easier to add triangles to Geometry than it is BufferGeometry. Remember that the whole point of BufferGeometry is that it's not supposed to change! You would also be able to take advantage of .fromGeometry() because the new faces are already defined in oldGeom.
  2. Make an indices array that's larger than necessary for the original indices and manually define triangles there. If you're defining new vertices that don't exist in the vertices array then you'd have to add them in there too. What a pain in the butt.
dalyIsaac
  • 702
  • 8
  • 17
jered
  • 11,220
  • 2
  • 23
  • 34