The Face3 constructor in three.js
The Face3 constructor has been removed in three.js as of revision 126. Before that change the Face3 Constructor was used to define a Face when making a custom geometry with the Geometry Constructor which has also been removed as of revision 125. It might still be possible to get the old geometry constructor working on new versions of threejs, but it would be best to make custom geometries with the Buffered Geometry constructor when it comes to making use of late versions of threejs.
When using any kind of built in geometry, instances of Face3 are created automatically, or at least they where, and still are if you are using an older version of threejs. So whenever making a custom geometry from code, or trying to figure out some problems that may exist with how faces are being rendered it is necessary to understand a few things about Face3 when using the old Geometry Constructor. One of the main properties of interest with an instance of Face3 is the material index property, this comes into play when it comes to working with an array of materials, rather than just a single material when using a geometry with a Mesh Object.
In new versions of threejs it is now the groups array of a geometry that would seem to be where these kinds of objects are now, and the use of the add group method is how to create them. This is still an old post on the face3 constructor, but when it comes to this edit, as well as many future edits this is what I am gong to start to write about at the top of the post, and start to push the older face3 stuff to the bottom of this content piece.
The face3 constructor, and what to know before you continue reading
Other posts on related topics ( material index )
One of the main reasons I would bother with the Face3 constructor has to do with creating faces to begin with if they are not there. However even when using a built in geometry constrictor with the face3 objects in place to begin with, I might still want to change the material index value. So the Face3 class is closely related to working with an array of materials for a mesh rather than just one. In my post on Mesh objects and working with an array of materials I have got around to touching base on how to use an array of materials with late versions of threejs using the groups array of a buffer geometry.
MANY OF THE CODE EXAMPELS IN THIS POST BREAK IF YOU ARE USING A NEW VERSION OF THREEJS (r125+)
I will be looking into making some new examples where I am doing the same things that I wanted to get done when working with face3 but with the new versions of threejs where this class is no longer part of the core of the library. As I work out those examples I am sure I will get around to editing this post with new examples to do those things without Face3.
Still I might leave this post up for the sake of historical reasons, if you are still using older versions of threejs, or have found a way to add the Geometry and Face3 constructors back to three.js by way of some additional plug ins then the examples here should still work.
The source code examples here are on github
The source code examples here are in my test threejs github repository. When it comes to making a pull request that would be where to do so, there is also the comments of this post that can also be used as a way to bring something up.
Version numbers Matter
As of this writing three.js is a project that is still being developed fairly fast, so version numbers are of great concern. In this post I was using three.js 0.91.0 aka r91 when I first make the source code examples, and the last version that I tested the threejs examples of face4 constructor with was r111. The last time I came around to doing some editing of this post I included one example that has to do with the groups property of a buffer geometry instance that would be the modern replacement for this, and with that example I was using r135.
1 - Example of using Groups in r125+ (face3 replacement )
Now that the face3 constructor is a really old feature of threejs that only applies to revisions of threejs that are fairly out of date now I am thinking that I should have at least one example of the groups array that is what I am using as a replacement for the face3 class now. To get an index of what this is about one quick way to do so would be to use an array of materials for a mesh object and play around with the material index values of a box geometry that is used with the mesh.
2 - Basic Example of Face3
For a basic demo of face3 I put together an example where I am just making a single triangle from an array of just three vertices. The Geometry constructor is used to create an instance of geometry, once I have that I will want to populate the instance of geometry with vertices by adding an array of Vector3 instances. Vector3 of course is another constructor that is used in three.js to create a point in space.
Once I have an array of vertices I will want a way to define faces that exist between them, this is where Face3 comes into play. The first three arguments given to Face3 are the index values in the vertices array that I want to make a triangular face with. The order of the index values does matter as it is used to determine the orientation of the face when it comes to rendering a texture to the face, more on that later.
So for now I have something like this:
3 - The order of indexes with face3
To some extent when making faces I am just playing connect the dots with vertices, but it is not always just that simple, as the order of index values does matter. When creating a mesh with the geometry, I also give a material. When it comes to materials there is the side property of a material which is used to set which side of a face3 instance that is to be rendered with the material. This property expects an integer value the default of which is stored in the constant THREE.FrontSide which as of this writing is a value of zero.
What I am driving at here is that the order of the indexes is what is used to find out what side of the face is the front side. If you are running into some kind of weird issue where some of your faces are rendering and others are not it could be because you are not getting the index order right.
There are two ways of fixing this one is to just make it so both sides are always rendered no matter what by setting the side value of your material to THREE.DoubleSide. This will make it so that both sides of the face are always rendered with the material, but the best way of fixing this would be to just get the index order right.
3.1 - Setting Three.DoubleSide for the side property of the material
One way to address this problem is to just make it so that both side of a face will be rendered rater than just the front side of the face. However one major draw back of this is that it will eat up more overhead of course, so it really is best to just know how to set what side of a face is the front side.
This is also just a useful property to be aware of for use with certain Models anyway, for example if I have a plane and I want a material rendered on both sides.
3.2 - Just getting the vertex index order right for the Face3 instances
The other way is to just get the index values right in which case the default THREE.FrontSide is not a problem when rendering. So it is a good idea to just figure out what the proper order is for the index values to given the the Face3 constructor.
Consider the following:
Notice that with the first instance of Face3 I am starting with index 0 then counting up, while with the other instance I am staring with the last index and counting backwards. This results in the Front side of both faces being on opposite sides relative to each other.
4 - The Material index property
If in case you did not know, it is possible to give an array of materials to the mesh constructor, rather than just one. In this case there should be some way to set which material should be used for which insistence of face3. For this there is the material index property of a face3 instance. So the process of having control over this is to just loop over the array of face3 objects, and set the desired material index value for each face.
Say for example I want to have a cube with three different materials that will each be used for three of the six sides of the cube. To pull that off I might do something like this:
The value that I give to material index should be the index value of the material I want to use in the array of materials.
The Face3 constructor is something that I might not need to bother with anymore, at least when it comes to using newer versions of threejs. There are only so many things that I might need to do when it comes to working with a geometry, or a mesh, and one of which is to set the material index values to use with each face of an object. The way to do that might have been to set the material index of face3 instances, but now with newer versions of threejs there is no Geometry of Face3 constructor, at least not in the core of the library. So a modern way of doing that must be followed in place of continuing to bother with older versions of threejs which would be to create or change the same values but now in this groups array of a buffer geometry.