The index property of a buffer geometry instance in threejs is a way to define an array of index values in a position attribute that will be used to draw triangles. Simply put it is a way to reuse points stored in the position attribute so that the over all length of the array in the position attribute is lower than it would otherwise have to be. The main reason why I might want to have a geometry indexed is to save memory when it comes to geometries with a lot of points in them. Also it would help to reduce the amount of overhead it would take to update geometry also a little as it is less points that have to be looped over in order to do so.
However there are also some draw backs with this as well that have to do with the state of the normal attribute the corresponds with the position attribute for example. Also because I am reusing points any kind of effect that has to do with exploding a geometry into a hole bunch of single triangles is not possible as the points are being reused. It is not so hard to convert an index geometry to a non indexed one though, doing so involves just calling the to non indexed method of the buffer geometry class. Things might be a little involved when it comes to the other way around though as it will involve creating a buffer attribute instance and using the set index method.
The index property if just one little feature of a buffer geometry object in threejs. There is a great deal more to be aware of when it comes to buffer geometry, so you might want to check out my main post on buffer geometry in general.
The examples that I write about in this post can also be found on my Github.
When I first wrote this post I was using r146 pf threejs.
This first section will be just a few quick basic examples that have to do with the index property of a buffer geometry centered around examples that involve a very simple custom geometry. The index property has to do with reusing points in the position attribute so then these examples will involve a very simple custom geometry that is just two triangles. There is then just understanding the difference between using 6 points with no index, and 4 points with an index if two points are at the same location.
For this example I am creating what might very well be the most basic form of an index geometry that is composed of just two triangles made from 4 points in the position attribute. I start out by making a new blank buffer geometry by calling the THREE.BufferGeometry with the new keyword and no arguments of any kind. The result is then a blank clean buffer geometry returned that I store to a variable. Now I can use the set attribute method of the buffer geometry class to set a position attribute. However first I will need an instance of THREE.BufferAttribute set up with the position data that I want to use to create my two triangles.
To create the position attribute I call the THREE.BufferAttribute constructor and pass a Float32Array that will contain the points in space that I want to use. Each three numbers in the array will be for x,y, and then z values for a single point in space. I want 4 points and 3 axis values for each point so that means the length of the array will be 12. After I pass the array as the first argument I will then pass the number 3 as the second argument as there are 3 values for each item in this buffer attribute. Now that I have the buffer attribute for the position attribute I can now call the set attribute method of that blank geometry, pass the string position as the first argument, and then the buffer attribute for position as the next.
So now I have a geometry with a position attribute, now I will want to add the index. For this it is more or less the same process as with making the custom position attribute. However I will be using a Uint8Array, and this time it is just 1 number per item as this is an array of index values for points in the position attribute that I just set. When I have my index buffer attribute instance I can then pass it as an argument when calling the set index method of the geometry.
One last thing with the geometry is that I will want to call the compute vertex normals method to quickly create a normals attribite for this geometry. The reason why is because I am going to use this geometry with a mesh object that will use the mesh normal material so I will need this.
When it comes to getting started with the index property of buffer geometry there is making a custom geometry that is just two triangles. With a non indexed geometry these two triangles will consist of 6 points in space stored in the position attribute, even if two of the points of each triangles are the same. When it comes to an indexed geometry however only 4 points can be defined in the position attribute, and then an index can be used to define 6 index values of points in the position attribute as a way to draw the triangles.
With both mesh objects In this example I am using the mesh normal material and if you look closely at the outcome of this you will notice that they both look a littler different. This is because for both geometries I am calling the compute vertex normals method to create the normal attribute of the geometries and with the indexed geometry the state of the normal attribute is not a typically desired outcome. This is because we have four points rather than sit which results in 4 normal vector rather than six, which in turn also effects the face normals sense vector normals are used to find that.
If you do want to pass a buffer attribute when calling the set index method just keep in mind that there are limits to these various data types. The numbers should be integers however it might still be best to go with a float option actually sense some of them have higher max safe integer values than the integer options for typed arrays. This is very true with the Uint8Array typed array that is just a single byte of course, and as such it will limit the usable point count of the geometry to 256.
2.1 - Custom Plane Geometry based on THREE.PlaneGeometry that just passes an array when calling setIndex
As always I like to work out at least one if not more animation loop example for my posts that help to give a better idea of what the subject of the post is all about. For the subject of indexed and none indexed geometry there is a whole lot of potential when it comes to this subject that involves changing the state of a position attribute over time for both and indexed and non indexed geometry to showcase a major difference between they two.
When using the THREE.BoxGeometry class to create a geometry it will have an index for it set up for me. If I want the box to not be indexed I can just call the to non index method to do so. For this example I create a geometry with the box geometry constructor function, and then another geometry that is just a clone of this. I then class the to non indexed method off of the clone of the box geometry to end up with an indexed and non indexed box geometry that I then use with two mesh objects. I then add both of these mesh objects to a group and loop over the children of the group in a main update method.
When updating the same points in each position attribute the result as one should expect is very different. When it comes to the non index geometry I can move a whole triangle by itself from the rest of the geometry, however of course when it comes to the indexed geometry there are shared points which effect the whole of the geometry.
Although the box geometry example shows what the deference is between index and non indexed geometry I have found that this example that involves the use of plane geometry does a better job of showing the difference. When it comes to the mesh that uses the geometry that does not have an index that breaks apart into a whole bunch of triangles, where the indexed geometry just turns into a bunch of peaks and values and starts to look like land.
In any case the index of a geometry is something to be aware of to say the least. There are situations in which I might want to create one in order to crunch down the size of the position array. Also there are situations in which I might want to create a non indexed geometry and recompute the normal and uv attributes for a geometry while I am at it.