LDraw.org Discussion Forums

Full Version: Regarding rendering of parts
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I am trying to write a renderer and so trying to understand the document http://www.ldraw.org/article/415.html.
My first question is does a reverse matrix (determinant < 0) perform a mirroring on the part as I have seen in some places or just changes the winding as the document suggests. I wish the pseudocode at the bottom of the document also included the negative determinant part of the drawing process.

Also regarding rendering. If I open the subpart box5.dat in ldview the backfacing polygons are not rendered. But If I create a file sample.dat and in it I put the line "1 16 0 0 0 1 0 0 0 1 0 0 0 1 box5.dat" and open sample.dat in ldview then the backfacing polygons are rendered. From reading the above document I do not understand why that is the case.

Thank you for any help.
That's because the second dat breaks the BFC chain. Without proper BFC information for every recursive file BFC supporting software doesn't know the current winding and therefore falls back to two sided lighting for the whole branch.

You can find information about the BFC (Back Face Culling) extension in the document section.
But from what I have seen model files almost never (90%) have BFC info in them. I have found BFC info in parts and subparts. Does that mean that model files are rendered always double-sided? So then what is the point of having BFC since I think most people render entire models. Am I missing something?
For the purposes of BFC, a "mirror matrix" reverses the windings, and so must be detected by the rendering engine and dealt with automatically. BFC doesn't care about the actual final geometry, so the fact that it also creates a mirror image doesn't apply to the BFC spec.

The following from the spec should answer your other question (emphasis added):

Quote:Marking a file as BFC-compliant only directly affects that file. In order for subfiles to be treated as compliant, they must also be marked as compliant. Additionally, with the exception of parts, a file is only treated as being BFC-compliant if it and all of its superfiles are compliant. The reason for this is that, while processing, there is no way to know the intended inversion state of a subfile when the file's superfile isn't BFC-compliant. The reason that part files can be excepted from this rule is that they are complex closed solids, so there is never a valid reason to invert them. Assuming part files are never inverted allows the rendering engine to apply BFC-processing on certified parts, even if the calling file(s) (for example, the main model file or sub-models of the main model) aren't certified.
You are right models usually don't have the BFC meta but most software assumes the bfc information only affects parts, so anything using the top level parts can be non bfc-ed, as-long it doesn't use mirroring (although you can compensate for that).

In the end it depends on how you set up your renderer, if the resulting mesh is at part level you'll need a fully bfced tree of dat's to make the whole mesh render with culling, but if you are writing a state renderer you could enable/disable culling while you go, it won't be fast though Smile

My post was assuming the mesh approach.
Top-level non-BFC models can contain mirroring, and BFC-compliant renderers will still render them properly, with BFC force-enabled for BFC-certified parts. Any software that supports BFC really needs to support enabling reset of BFC when rendering a BFC-certified part, because most user models don't specify BFC. Not doing this would result in BFC having no effect in most models. This also requires tracking the "matrix flip" state of all models, not just BFC-certified ones.

LDView keeps two sets of geometry: BFC-certified geometry, and non-BFC-certified geometry. The first set is rendered with back face culling enabled. The second set is rendered two-sided. An alternative (probably better) way would be to just create doubled up geometry (with opposite winding on the second copy) for all the non-certified geometry. Then, the rendering engine wouldn't have to care.
I am still confused. Roland's answer suggests that if a model file (my sample.dat) is not BFC compliant then all parts (the box5.dat file) in the model file will be rendered as non-BFC compliant geometry (ie double-sided), which is what ldview does. Yet the last sentence from the quote of the spec says that the rendering engine can apply BFC-processing on BFC certified parts (the box5.dat file) even when the superfile main mode file is not BFC-certified.
box5.dat is not a part. It's a primitive. So the rules do not apply.

I'm sorry for the confusion, bfc is quite tricky and how to use it is also somewhat up to the software reading it.

The BFC matas only supply you with winding information for a particular file. From such files you can create geometry with correct winding.

For uncertified files (non bfc meta) the winding is unknown, but in your example the file only contains references. This basically means winding information can be determent by examining the reference matrix. This usually goes for models.

The second an uncertified dat file includes type 3 or 4 lines this goes out the window and those poly's should be rendered with some sort of compensation (duplicate geo, two sides lighting).

Now how any recursion from such a uncertified file is to be handled is up to you, and the way you set up your rendering pipeline.

As on LDView's behaviour, I'm not sure (Travis?) but I think LDView is forcing the non culling based on the file being a .dat (models are usually .ldr or .mpd). This forces a visual mode that helps part authors checking the bfc state of a part.
As Tim already pointed out, box5.dat is a primitive, not a part. This is very important. As my quote from the spec says, parts are closed solids, and the knowledge that they are closed solids is the only reason that BFC can be re-activated for them when they are included in a file that's not BFC-certified. Primitives aren't closed solids.

LDView has various things it looks for to decide if a file it has loaded is a part. Any of the following will do the trick:
  • File contains !LDRAW_ORG {Uno|O}fficial_Part meta-statement.
  • File contains some other meta-statement that has been used historically, and that LDView recognizes as specifying that a file is a part.
  • File was loaded from the LDraw parts directory.
  • File was loaded from LDView's Unofficial LDraw parts directory.
  • File was loaded from a directory marked as a parts directory in ldraw.ini.
In addition to the above, a file that is a sub-file of a part isn't considered to be a part by LDView, even if it meets any of the above constraints.
Hi Guys,

Saki, one last thing to consider: do you -want- to implement BFC? If I understand the spec, it's not mandatory and renderers that simply ignore BFC and render everything two-sided do produce correct output.

I mention this because the win of BFC is to reduce the amount of fill needed to render a model (by eliminating rasterization of the backs of primitives). The cost of BFC (besides your development time :-) is some amount of additional state change being communicated to the driver. (The amount of state change will depend quite a bit on your renderer and how it optimizes and pre-proceses LDraw files.)

So if your renderer is CPU bound and not GPU bound and your renderer's code structure will require a lot of driver calls to keep BFC set up correctly, it may reduce and not improve performance to have it.

(I am assuming from the spec language that the goal of BFC is optimization and not 'clever rendering tricks' because the BFC spec is authored to "allow cross-compatible LDraw files.")

Ben Supnik Wrote:(I am assuming from the spec language that the goal of BFC is optimization and not 'clever rendering tricks' because the BFC spec is authored to "allow cross-compatible LDraw files.")


This is correct. Any authored part that exposes the back side of a BFC component is considered a bad part and will not be allowed into the library.

Well my renderer will be running in a browser (WebGL + Javascript) in real-time, so I am trying to squeeze as much performance as possible without using double-sided faces. Actually without BFC checking the renderer works fine.

I just tried rendering 5541_blue_fury.ldr model with BFC off and on my laptop (quite old) I get 30FPS (frames per second). When I enable my semi-correct BFC checking I get 35FPS. So BFC checking for real-time renderers is worth it.
What renderer is actually doing the rendering? E.g. is this hardware accelerated, and if so, what is the GPU?
Yes it is hardware accelerated on an NVIDIA 9800 card.
So I know precious little about WebGL, but does it give you the option to do vertex buffers? That model renders just fine even on my iPhone, so it seems the bottleneck is likely more in the preprocessing and not the GPU.
I did not say it does not render fine. I only said that it is almost always the case (99%) that enabling backface culling will be faster.
WebGL does have vertex buffers which was my next task after determining correct bfc rendering.

By the way with which software are you rendering on the iphone?
Ah sorry. I meant I have no fps issues (albeit I'm capped at 15 fps I believe). It's something I'm designing myself, but it's via OpenGL.