Revision Notes
|
revision 13:
|
Changes following adoption by the LSC as the draft BFC standard.
|
|
revision 12:
|
Moved Current issues section down.
|
|
revision 11:
|
All lines in the file that were greater than 80 columns were re-
formatted to fit in 80 columns. This re-formatting is NOT
reflected in the revision numbers at the beginning of each line.
All references to NOWIND (other than this one) were removed.
Any first-person references in this revision came from Travis
Cobbs.
|
|
revision 10:
|
All lines that are indicated as being revision 10 are actually
from revisions 0 through 10. Given the nearly 3 years between
revision 10 and revision 11, I felt that it was easier to read
this way.
|
Current issues
-
Strictly speaking, the CERTIFY option is redundant. Its function can be
performed by CLIP, NOCLIP, CW, CCW. Using 0 BFC CCW at the start of a
file clearly states that the file uses counter-clockwise winding, and
implies that the file is BFC-ready. However, only CERTIFY clearly
states that the file is BFC-ready, as the other statements only address part of compliance, but it is still perfectly valid to skip the CERTIFY option.
-
The authors guidelines section is completely undeveloped. Some items for
this section:
- How to write double-sided and decoration sections
- Default values
- 0 BFC CERTIFY == 0 BFC CLIP CCW
-
The specification of the INVERTNEXT option needs to be re-written.
-
In Rendering Engine Guidelines, there is some discussion of transform
matrices and inversion and what an engine needs to do to adjust for
negations. The subfile inversion part should probably be redone. Since
inversion produces exactly the same result as reversed winding, the fact is
that when the matrix has a negative determinant the inversion flag needs to
be logically flipped, which is exactly what INVERTNEXT does. The
difference is that INVERTNEXT is done IN ADDITION TO this automatic
inversion.
-
It has been suggested that the CLIP and WIND settings should be stated
explicitly in each file.
Purpose
Establish a standard for backface-culling (ie, clipping) processing
in LDraw-compatible rendering programs. This standard will include language
extensions, definitions and expected processing effects.
In this document, this standard will be called the BFC extension.
The standard must allow cross-compatible DAT files. That is, LDraw-
compatible rendering programs must render clipping-enabled DAT files
correctly, and renderers which include the BFC extensions must render non-
clippable DAT files correctly.
To make this standard useful and effective, the LDraw parts library must be
updated to follow the new standard. Since it would be difficult to rewrite
the entire library in one update, the standard will allow for a mix of
extended and unextended files in one rendering.
Definitions
Certified. A DAT file is certified if it complies with the specifications
in this document, includes a 0 BFC statement before the first operational
command, and does not contain a no 0 BFC NOCERTIFY statement.
Clipping. In this document, the term clipping refers to the process of
performing back-face culling. It should be noted that clipping has other
meanings in other graphics contexts.
Invert. Turning a subfile inside out, usually performed on geometric
primitives. When backface culling is used, inversion is needed, or interior
surfaces will never be rendered. Because polygons are one-sided, interior
primitives need to have their surfaces face inward, rather than outward.
Operational Command-Line. Any statement in a DAT file with linetype 1
through 5. In other words, the Subfile, Line, Triangle, Quad, and
Conditional Line statements.
Part. A DAT file which represents a complete real-world building element.
These files are stored in the ldraw\parts\ directory.
Polygon. A 2D surface created by LDraw's linetype 3 (triangle) or 4
(quadrilateral) command.
Primitive. A DAT file, typically small, which models a geometric shape or
a standard attribute of building elements, such as studs or the cross-axle
shape. These files are kept in ldraw\p\. In other graphics contexts,
the term primitive refers to the basic geometric shapes provided by the
rendering environment.
Subfile. A DAT file referenced from another file, via a linetype 1 command.
Or any file which is lower in the file-reference tree than the current file.
Or any file which is the subfile of the current file (or thus of any of its
subfiles).
Subpart. A DAT file which is only a portion of a complete element. Does
not necessarily correspond to a discrete portion of a real-world building
element. These files are kept in the ldraw\parts\s\ directory.
Superfile. The file which referenced the current file. More generally, any
file which is higher in the current file-reference branch than the current
file.
Winding. This is the order vertices are specified in a polygon command. The
order by be either clockwise or counter-clockwise (AKA anti-clockwise), and
is based on viewing the polygon from its front side.
Clockwise winding (vertices numbered 0 through 3):
0 -> 1
^ |
| v
3 <- 2
Counter-clockwise winding:
0 <- 3
| ^
v |
1 -> 2
Language Extension Functionality
The BFC language extension allows DAT files to specify and control the
following conditions:
Compliance. DAT files which follow the BFC extension must be clearly and
unambiguously marked. It is also useful to allow non-compliant files to
be marked as well. Having the compliancy stated plainly simplifies the task
of the rendering program, and makes it easier for humans to read files later.
Control of the compliance/non-compliance state will only affect the current
file. Subfiles will be affected indirectly, because it is not possible to
clip subfiles of non-BFC files, but the compliancy of the subfiles will not
be affected. That is, it is not possible to clip a BFC subfile when it is
referenced by a non-BFC superfile, but the same BFC subfile may be clipped
when referenced from a BFC superfile.
Winding. It must be possible for a file to specify the winding order of the
polygon commands in that file, clockwise, counterclockwise, or unknown.
Allowing the winding to be set at the file level is primarily a convenience
for file authors. Setting winding to unknown is one way to prevent specific
polygons from being clipped.
Changing the winding setting will only affect the current file. It will not
alter the winding for super- or sub-files, and it will not modify the
clipping for subfiles.
Clipping. It must be possible to enable and disable clipping during the
processing of a file. But even when clipping is currently enabled, it may not
be possible to actually clip on polygons. Polygons can be tested for
clipping only when the following conditions apply:
- All superfiles (in the current reference branch) are certified.
- The current file is certified.
- No superfile has disabled clipping prior to referencing this
subfile.
Unless all of these conditions are met at the time a subfile is rendered,
no clipping is possible.
If the clipping state is modified, it affects all lines following the
CLIP/NOCLIP statement, until the end of the current file or another
CLIP/NOCLIP statement is encountered. When subfiles are referenced, they
will receive a flag indicating the accumulated clipping state, but there is
no sense of a global clipping mode.
Inversion. Sometimes, it is desireable to reverse the surfaces of a subfile;
to turn the subfile 'inside out'.
One common example of inversion is the cylinder primitive. Cylinder
primitives are designed so the surfaces face outward from the center. In 3D
tubes, a pair of cylinder primitives are used to model the tube; one outer
cylinder is oriented normally, and the inside cylinder, scaled slightly
smaller, is required to face inward. This is accomplished by flagging the
inner cylinder as being inverted.
Inversion accumulates down the reference branch. If the current
file is being rendered inverted, then any subfiles of the current file are
also rendered as inverted.
Inversion is a boolean operation--inverting a file that is already inverted
will give the file the normal orientation. So if the current file is
inverted, and a subfile is flagged as inverted, the subfile will be rendered
with normal orientation, that is, right-side-out.
As a practical matter, rendering engines can accomplish inversion simply by
switching the order of winding -- treat CCW files as as CW, and vice versa.
This must happen in conjunction with the other settings, of course.
Language extensions
There is a single meta-statement in the BFC language extension, the 0 BFC
statement. The statement includes options to specify BFC-related operations.
Syntax:
0 BFC [CERTIFY|NOCERTIFY] [CLIP|NOCLIP] [CW|CCW] [INVERTNEXT]
Only one option in each pair of brackets [ ] may be specified in a single BFC
statement, any number of the options may be specified in one statement,
and the options may be specified in any order on the statement.
The BFC meta-statement (along with all of its options) is case-sensitive, and
must always be in all caps.
The BFC meta-statement shall ignore repeating whitespace, and accept any
number of spaces or tabs as equivalent to a single space.
All BFC commands that act on succeeding lines in the file shall ignore empty
lines.
In order for a file to be processed with back-face culling, there must be at
least one 0 BFC meta-statement before the first operational command line. If
there is no such 0 BFC statement in the file, BFC processing will be disabled
for that file.
CERTIFY
This tag indicates the DAT file is compatible with the
backface-culling extension. Every DAT file must be clearly labeled if it is
compliant. One way to accomplish is to place 0 BFC CERTIFY at the beginning
of the file, before the first operational command-line.
A second way to specify a file as compliant is to use any option, except for
the NOCERTIFY option, on a 0 BFC meta-statement, before the first operational
command-line. This is an acceptable alternative, but the 0 BFC CERTIFY
method is recommended and prefered.
Files in the LDraw.org Parts Library, if they are BFC compliant, are required
to have an explicit 0 BFC CERTIFY line in their header.
If a file has no 0 BFC statement at the beginning, then BFC processing will
be disabled for that file, and any files referenced from that file.
NOCERTIFY
This BFC tag specifies that the file containing the tag is not compliant with
the BFC specification--the polygons are not wound correctly, or the subfile
references are not properly inverted. Hopefully, this tag will appear
rarely. If the NOCERTIFY option is used, it must appear before any
operational line-commands, and no other BFC tags may be specified on the
same line. Any other BFC statements in the same file will be ignored.
CLIP
This option sets the clip-mode to enabled. This allows clipping, if all
other conditions for clipping are met.
NOCLIP
This option sets the clip-mode to disabled. Any subfiles referenced with
clip-mode disabled will not be eligible for clipping.
There may be any number of changes to the clip-state in a file, although it
is recommended that such changes be kept to a minimum.
If neither the CLIP nor NOCLIP option is specified in a file's leading 0 BFC
statement, then that file's local clip-state is initially set to enabled
(CLIP).
CW
This option sets polygon winding to clockwise.
CCW
This option sets polygon winding to counter-clockwise.
There may be any number of changes to the winding direction
in a file, although it is recommended that changes to winding
be kept to a minimum.
If no winding tag is specified for a file, the local winding state will be
defaulted to counter-clockwise (CCW).
INVERTNEXT
This option inverts a subfile. It may only be used immediately before a
subfile command line (intervening blank lines are allowed), and it only
influences the immediately following subfile command.
Example:
0 BFC INVERTNEXT
1 16 0 0 0 1 0 0 0 1 0 0 0 1 somefile.dat
1 16 0 0 0 1 0 0 0 1 0 0 0 1 another.dat
In this example, somefile.dat would be rendered as inverted. Another.dat
would not be inverted.
For further information, see "Inversion" in the Language Extension
Functionality section.
Rendering Engine Guidelines
This section gives some suggestions for the design of rendering programs,
in order to achieve correct renderings. Any program may violate
these guidelines, if there is another way to achieve a valid rendering.
Matrix Reversals. Rendering engines will need to correct for orientation
matrices which inadvertently or deliberately reverse a subfile.
Normal transformation:
1 16 0 0 0 1 0 0 0 1 0 0 0 1 somefile.dat
'Reversed' transformation:
1 16 0 0 0 1 0 0 0 -1 0 0 0 1 somefile.dat
If the rendering engine does not detect and adjust for reversed matrices,
the winding of all polygons in the subfile will be switched, causing
the subfile to be rendered incorrectly.
The typical method of determining that an orientation matrix is reversed is
to calculate the determinant of the matrix. If the determinant
is negative, then the matrix has been reversed.
The typical way to adjust for matrix reversals is to switch the expected
winding of the polygon vertices. That is, if the DAT specifies the winding
as CW, and the orientation matrix is reversed, the rendering program would
proceed as if the winding is CCW.
Inverted Subfiles. Generally, it is not possible to determine that a subfile
reference is inverted or normal (which is the reason for the 0 BFC INVERTNEXT
meta-statement). In particular, the rendering engine should *not* use the
determinant of the orientation matrix to determine if the subfile is intended
to be inverted (see 'Matrix Reversals', above).
One important special case is this: part files are never inverted.
Parts are complex files which would be essentially useless if
they were inverted. Assuming part files are never inverted allows
the rendering engine to apply BFC-processing on certified parts, even if the
calling files (i.e., the main model file(s)) aren't certified.
No assumptions can be made about models which make direct use of primitives
or polygon commands, so a rendering engine should not simply treat
uncertified model files as certified.
Clipping State. The rendering engine can default to either allow or disable
clipping at the start of processing. Presumably, the user will be given the
ability to control this state.
Degenerate Matrices. Some orientation matrices do not allow calculation of
a determinate. This calculation is central to BFC processing. If an
orientation matrix for a subfile is degenerate, then clipping will not be
possible for that subfile (or its subfiles).
Parts Library Guidelines
The LDraw Parts Library includes all parts, primitives, and subparts
distributed with LDraw or in an ldraw.org parts update.
New parts will not be required to be compliant with this extension. They
will be required to carry a 0 BFC tag, indicating either compliance
or non-compliance.
New primitives will be required to be certified before being accepted for
release.
It is desirable for all files to use the same winding. When possible, files
should use counter-clockwise winding. The actual winding for any part is
left to the file author. Primitives should always use CCW winding.
Primitives should generally be written so that polygons face outward, or
upward. Exceptions are allowed for polygons which model inward- or
downward-facing surfaces.
As noted in the Language extensions section, all BFC compliant files in the
parts library will have an explicit 0 BFC CERTIFY line in their header.
Rendering Processing
This section presents a possible model for writing the core processing loop
in an LDraw/BFC rendering program. BFC-relevant logic is included, as much
other logic (as possible) is excluded. It should not be assumed that this
pseudo-code represents the most effecient way to implement BFC.
The function BFC() returns a boolean value, indicating whether a polygon
should be rendered or culled. As the nature of this routine does not
impact the BFC standard, the logic for BFC() is not included in the following
pseudo-code. There is information about BFC processing available from many
locations, including lugnet.cad.dev
Recursive Procedure RenderFile
Parameters:
ModelFile string // File to render
AccumClip boolean // global clipping value yes/no
AccumInvert boolean // current inversion normal/inverted
AccumTransformMatrix matrix // current transformation
Colour integer // current colour
Declare
LocalClip boolean Initial TRUE
Winding bivalue(CCW, CW) Initial CCW
Certified trivalue(TRUE, FALSE, UNKNOWN) Initial UNKNOWN
InvertNext boolean Initial FALSE
Command DATCommandLine // Structure containing parameters from a single
// DAT command-line.
OpenFile(ModelFile)
Do Until EOF(ModelFile)
Get Next Command
If Command.Colour = 16 Then
Command.Colour = Colour
ElseIf Command.Colour = 24 Then
Command.Colour = EdgeColour(Colour)
End If
Case Command.LineType
BFC
If Certified is UNKNOWN and no Option in Command is NOCERTIFY Then
Certified = TRUE
End If
Do for each Option in Command
Case Option
CERTIFY
Assert Certified != FALSE
// Triggers error if file has been NOCERTIFY'ed
Certified = TRUE
NOCERTIFY
Assert Certified != TRUE
// Triggers error if file has been CERTIFY'ed
Certified = FALSE
CLIP: LocalClip = TRUE
NOCLIP: LocalClip = FALSE
CCW
If AccumInvert Then
Winding = CW
Else
Winding = CCW
CW
If AccumInvert Then
Winding = CCW
Else
Winding = CW
INVERTNEXT
InvertNext = TRUE
End Case
End Do
SUBFILE
If Certified is UNKNOWN Then
Certified = FALSE
Case Certified
TRUE
RenderFile Command.Subfile,
(AccumClip and LocalClip),
(AccumInvert xor InvertNext),
Command.TransformMatrix * AccumTransformMatrix,
Command.Colour
FALSE, UNKNOWN
RenderFile Command.Subfile,
FALSE,
(AccumInvert xor InvertNext),
Command.TransformMatrix * AccumTransformMatrix,
Command.Colour
LINE, CONDITIONAL_LINE
If Certified is UNKNOWN Then
Certified = FALSE
Deal with primitive command
TRIANGLE, QUAD
If Certified is UNKNOWN Then
Certified = FALSE
End If
If AccumClip and LocalClip And (Certified is TRUE) Then
If BFC(Command, AccumTransformMatrix, Winding) Then
Render Command
Else
Don't render Command
Else
Render Command
End If
End Case
If Command.LineType != BFC Then
InvertNext = FALSE
ElseIf No Option in Command is INVERTNEXT Then
InvertNext = FALSE
End If
Loop
End Procedure
Guidelines for Part and Primitives authors
(Section to be developed)