BFC
TODOs for this article:
- add illustrative images
- further elaborate the text
- add a section which explains the effect of 0 BFC INVERTNEXT onto a referenced primitive in the next line
____________________________________________________
BFC is the abbreviation for Back Face Culling.
That is a term from computer graphics: It describes a mechanism which assigns an orientation to a surface, i.e., which side is "front" and which side is "back".
A software for 3D rendering can use that information to speed up its computations and renderings.
Read on to understand the details.
Orientation of Triangles and Quads: Which Side is "Front", and Which is "Back"?
In our LDRAW world, we have triangles and quads. Imagine such a triangle or quad in 3D space. It is infinitely thin, but has 1 front side and 1 back side. The question is: which side is front, and which is back? The choice is arbitrary, we just have to make a clear definition. The one chosen in LDRAW is: follow the sequence of corner points in the order they are written in the LDRAW files and let the 4 fingers of your right hand follow these points in 3D space. Then your erect thumb points to a certain direction. That side of the surface shall be called "front", the other side "back". (We could have chosen just the opposite definition - as said, the choice is arbitrary.) By using this simple definition, a clear and unique "side naming" is applied to such a triangle (or quad). If you reverse the sequence of corner points, then your thumb will point to the opposite direction. Thus, by reversing that sequence, the orientation of such a surface can be "flipped", meaning that the former "front" becomes "back", and the former "back" becomes "front".
Counter-Clockwise and Clockwise
The above description of the definition of a "front" and "back" side is difficult to remember without a clear name. LDRAW historically has found 2 easy-to-remember names for the orientation definition of "front" and "back": If you take an example triangle, put it into the X/Y plane, look at it from -Z direction to Z direction, and follow its points in COUNTER CLOCKWISE order, then by the above definition you will be looking at the FRONT of that triangle. That's why LDRAW chose the name "COUNTER CLOCKWISE BFC ORIENTATION" for that mechanism of defining FRONT and BACK of triangles. Of course, if you want the definition to be opposite, i.e., run through the points in CLOCKWISE order to see the front, then your definition will be called "CLOCKWISE BFC ORIENTATION". Every LDRAW file can choose which definition of FRONT and BACK it wants to use. It does so by writing a statement into its header:
0 BFC CERTIFY CCW
tells the consumer of this file that its contained triangles and quads follow the "COUNTER CLOCKWISE" definition for "front" and "back". Opposite to that, writing
0 BFC CERTIFY CW
into the header tells the consumer of this file that its contained triangles and quads follow the "CLOCKWISE" definition for "front" and "back".
Why is "Front" and "Back" Information of Surfaces Useful for Renderers?
If a renderer knows which side of a face is "front" and which is "back", and if a 3D geometric object made of such faces is looked at in 3D space, then a renderer can profit from that: it can know that those faces, of which only the rear can be seen, can be left out from rendering, if desired by the user. You can see an example image showing that mechanism in action in the Wikipedia: back-face culling. Leaving away these faces from the render can speed it up significantly.
"BFCing" an LDRAW File
"BFCing" an LDRAW file means to do 2 things with it:
- Adding a 0 BFC CERTIFY CCW or 0 BFC CERTIFY CW statement to its header, and thereby stating that all its faces are (intended to be) properly oriented.
- Checking that all faces are oriented in the file in the way that all part "outside" is formed by "front" faces and all "inside" is formed by "back" faces only.
Achieving this requires that a part author corrects the sequence of points of the surfaces inside the file.
So, making an LDRAW file properly oriented will usually be an iterative process of
- looking at a rendering of the file and check that no "back" sides can be seen
- if some "back" sides can be seen, change their orientation
- repeat this until everything is properly oriented.
Using LDView
If done manually, this of course needs tooling support for a human. A good means is using the program LDView. It offers a nice mechanism of coloring surfaces, depending on their orientation. To use it, customize its toolbar so that that toolbar has the "BFC" button. When that button is enabled, the colors shown in a rendering of a part will be assigned as follows:
- the FRONT sides of surfaces will be colored GREEN
- the BACK sides of surfaces will be colored RED
- if that orientation cannot be computed (either because a file does not properly state that it has oriented surfaces, or if the surface itself is de-generated), then that surface will be shown in BLUE
Here is an image of the famous 2x4 brick, rendered in LDView without BFC coloring applied:
When turning on BFC coloring, a properly BFCed part will be shown like this:
Here is an example, where 1 surface intentionally has been wrongly oriented, for illustration purposes:
0 BFC INVERTNEXT
By writing the line
0 BFC INVERTNEXT
into a file, a part author states that the orientation of the next line shall be flipped, i.e., its "front" and "back" sides shall be swapped. This is the most trivial way to "flip" a surface. Of course, this "costs" writing 2 lines, so the preferred way instead is to reverse the order of corner points of a surface instead. Doing that by hand is quite tedious and error-prone, therefore using a program to do that is easier:
LDraw Design Pad
LDraw Design Pad is a text editor for editing LDRAW files. It offers the usual text editor features (edit, cut, copy and paste, etc.pp). Additionally, it offers the "reverse the sequence of corner points of a triangle or quad" button, which has been added exactly for the process of orienting the surfaces of a file properly.
WINDZ
Some attempts have been made to automate the manual surface orientation process described above. One of the results is the program WINDZ. It does repeated renders of a file and checks if a "back side" is visible. If yes, it inverts that surface and tries again. After some attempts it gives up. In many cases, WINDZ produces quite useful results already, and only minor manual corrections are necessary after that.
History
In its early days, LDRAW parts were developed without caring for BFC. Later, the BFC mechanism was added, to allow a speedup of renderers. That required to add the syntax elements described above to the LDRAW file syntax. The syntax elements are:
- the prefix "0 BFC" for all commands that deal with BFC.
- after that, the individual command follows. The set of possible commands are
- 0 BFC CERTIFY - this command states that the file intends to only have properly oriented faces
- 0 BFC CCW - this command states that from here on all surfaces are oriented following the COUNTER CLOCKWISE definition described above
- 0 BFC CW - this command states that from here on all surfaces are oriented following the CLOCKWISE definition described above
- 0 BFC INVERTNEXT - this command states that the orientation of the 1 next surface shall be vice-versa, i.e., front shall be back, and back shall be front
Best Practices
To keep things simple and efficient, LDRAW has adopted some best practices for its parts:
- there must be only 1 BFC CERTIFY statement in the file, and it has to be at the beginning of the file (in its header)
- in the same line, the CCW or CW orientation must be defined. This boils down to the simple rule that each properly BFCed file must either have the line
0 BFC CERTIFY CCW
or
0 BFC CERTIFY CW
in its header. CCW is preferred.
- Within the file, no switching between CCW and CW should occur.
- Writing 0 BFC INVERTNEXT should be avoided where possible, and only changing the sequence of corner points of triangles and quads should be preferred.
- Therefore, the only really useful purpose of the 0 BFC INVERTNEXT statement is to invert a primitive (for example, a torus segment).