POV-Ray : Newsgroups : povray.binaries.scene-files : Wrong normal direction on triangle{ }s : Re: Wrong normal direction on triangle{ }s Server Time
28 Apr 2024 18:43:15 EDT (-0400)
  Re: Wrong normal direction on triangle{ }s  
From: clipka
Date: 18 Aug 2016 18:31:29
Message: <57b63741$1@news.povray.org>
Am 18.08.2016 um 22:30 schrieb Le_Forgeron:

> Nicely spotted, and it applies only to triangle outside a mesh.

Evidently, since meshes don't manipulate their data for transformations;
they just store a transformation matrix.

> Nevertheless, aside from passing the swapped status during computation of data, do
we really need to store that bit in each triangle ?
> (moreover, in something not "unsigned int :1", which might actually extend the size
of the Triangle structure)

I could have chosen from a host of approaches:

(A) Keep the original order of the points, and store the potentially
rearranged points as separate variables. This probably qualifies as the
most straightforward solution, and would be virtually(*) neutral to
rendering speed, but would require 24 extra bytes of data.

(*The only mechanism that could lead to a slight decrease in rendering
performance would be an increase in cache misses due to the larger
memory footprint.)

(B) Keep the original order of the points, and modify the intersection
test to cope with arbitrary ordering of the points. This undoubtedly
qualifies as one of the most memory-efficient solutions, but would also
undoubtedly be the heaviest on rendering performance. It would also
require some thought to be put into the intersection testing.

(C) Allow the order of points to be rearranged, but keep track of this
fact with a single flag, and fix the surface normal computation
accordingly. This is also a relatively straightforward to implement,
virtually neutral to rendering speed, and in theory costs only a single
bit of memory.

(D) Allow the order of points to be rearranged, identifying this fact
from /some/ properties of the underlying data wherever it is relevant.
This also undoubtedly qualifies as one of the most memory-efficient
solutions, and it can probably be implemented in a performance-neutral
manner (as far as rendering is concerned; parsing would be slowed down a
bit), but it would require some thought and care to be put into the
implementation, to make sure the properties we're basing the test on
actually hold true. It may also turn out to require either non-trivial
changes to the architecture of the Triangle's pre-computation mechanism,
hence resulting in a comparatively high implementation effort; or
changes spread across various methods, that would make the solution
non-trivial to understand, thereby degrading maintainability.

Weighing all the pros and cons, I decided that (C) was a reasonable
solution.


As for chosing a `bool:1`, I am a passionate advocate of storing data in
adequate data types, and booleans /are not integers/, period. I'm using
a `bool:1` as oppsoed to a regular `bool` in hopes that some modern
compilers make use of the freedom given by the C++ standard and cram it
into the same byte as the preceding `unsigned int:2` fields, but if they
don't -- well, too bad. I won't sacrifice clean programming for such a
tiny bit of memory.

As a matter of fact...

- On Linux systems, http://stackoverflow.com/a/308393 suggests that at
least GCC 4.2.4 will indeed pack `[unsigned] int` and `bool` bit fields
snugly together, so no memory lost there.

- On Windows systems, my own tests indicate that Visual Studio 2010 will
refuse to pack the two bit fields together. However, thanks to the
preceding `double` field the `unsigned int` bit field will be aligned to
an 8-byte boundary, and effectively occupy a multiple of 8 bytes in
memory; and since `int` is only 4 bytes on Windows machines, that still
leaves enough room afzer the `unsigned int` bit field to accomodate the
`bool:1` without any loss.

Also, if you were that worried about memory consumption, you should be
more bothered by the `unsigned int:2` where `unsigned char:2` would
suffice; while the difference is only 3 bytes on Windows or 32-bit Linux
machines, on 64-bit Linux machines it is a waste of 7 bytes. (BTW, it so
happens that Visual Studio 2010 apparently /will/ happily pack `unsigned
char` and `bool` bit fields together.)


> And did you check the SmoothTriangle::Compute_Triangle ?
> Similar code with extra swapping of normal at vertices, yet the Normal_Vector is the
same old way as Triangle::Compute_Triangle.

For `SmoothTriangle`, the direction of `Normal_Vector` is irrelevant,
since it is only used in the intersection computations, where a
distinction between front and back side is of no concern. The only
important thing is that the direction of `Normal_Vector` matches the
sign of `Distance`.


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.