![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Hello
There seems to be a bug in the f_rounded_box function
when used with a zero radius. The documentation reads
for this case: "Zero gives square corners".
When used in an isosurface this appears to right only if
the bounding box exactly fits the now not more *rounded* box.
But if the bounding box is slightly increase there appears
a broken surface.
The first image shows an isosurface with exactly fitting bounding
box (means contained_by{ box{...} }) whereas the second one
shows the same isosurface with slightly increased bounding box.
The scene file is in p.b.scene-files.
Is this a known problem/bug?
I'm using POV-Ray 3.6.1
linux gcc (GCC) 3.3.5 (Debian 1:3.3.5-13).
Regards,
Sebastian
Post a reply to this message
Attachments:
Download 'frb_nobug.png' (5 KB)
Download 'frb_bug.png' (4 KB)
Preview of image 'frb_nobug.png'
![frb_nobug.png](/povray.binaries.images/attachment/%3C44100a10%40news.povray.org%3E/frb_nobug.png?ttop=441697&toff=4550&preview=1)
Preview of image 'frb_bug.png'
![frb_bug.png](/povray.binaries.images/attachment/%3C44100a10%40news.povray.org%3E/frb_bug.png?ttop=441697&toff=4550&preview=1)
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Sebastian H. wrote:
> problem/bug?
I dug a bit in the source code and found that a
change in fnintern.cpp fixes the problem.
In the f_rounded_box function there is an offset
of 1e-6 subtracted from the actual result.
return (... - 1e-6);
With an increased offset magnitude of 1e-3
the problem disappears and the isosurface looks correct.
Why this offset is there is beyond me but removing it
slows down the isosurface rendering a lot.
Sebastian
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Wasn't it Sebastian H. who wrote:
>Sebastian H. wrote:
>
>> problem/bug?
>
>I dug a bit in the source code and found that a
>change in fnintern.cpp fixes the problem.
>In the f_rounded_box function there is an offset
>of 1e-6 subtracted from the actual result.
>
>return (... - 1e-6);
>
>With an increased offset magnitude of 1e-3
>the problem disappears and the isosurface looks correct.
>Why this offset is there is beyond me but removing it
>slows down the isosurface rendering a lot.
I noticed that the slow down only seems to be happening with the
processing of shadows. If you add the no_shadow keyword, or move both
lights round to the front, then the isosurface renders quickly, but it
still has speckles.
--
Mike Williams
Gentleman of Leisure
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Sebastian H. wrote:
> Sebastian H. wrote:
>
>> problem/bug?
>
The docs are wrong, f_rounded_box() should only be used with radius > 0.
This is not a bug but simply a limitation (although it would of course
make sense to add an efficient handling of the case radius=0).
Note the current f_rounded_box() is not a very efficient solution anyway
(you don't need an sqrt() for every evaluation).
> I dug a bit in the source code and found that a
> change in fnintern.cpp fixes the problem.
> In the f_rounded_box function there is an offset
> of 1e-6 subtracted from the actual result.
>
> return (... - 1e-6);
>
> With an increased offset magnitude of 1e-3
> the problem disappears and the isosurface looks correct.
> Why this offset is there is beyond me but removing it
> slows down the isosurface rendering a lot.
To me it seems this offset is specifically for handling the degenerate
case. Choosing 1e-3 simply gets you beyond your accuracy limit.
Christoph
--
POV-Ray tutorials, include files, Landscape of the week:
http://www.imagico.de/ (Last updated 31 Oct. 2005)
MegaPOV with mechanics simulation: http://megapov.inetart.net/
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Mike Williams wrote:
> I noticed that the slow down only seems to be happening with the
> processing of shadows. If you add the no_shadow keyword, or move both
> lights round to the front, then the isosurface renders quickly, but it
> still has speckles.
>
I tried a scene with many isosurface with different parameters for
f_rounded_box and found that removing the offset reduces the overall
render time for the scene by about 2%. Though "a lot" slowdown is
overestimated it is noticeable.
I have a wip scene which uses f_rounded_box a lot and unfortunately
no shadow is not an option. But thank you for the hint anyway.
Sebastian
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Christoph Hormann wrote:
> The docs are wrong, f_rounded_box() should only be used with radius > 0.
> This is not a bug but simply a limitation (although it would of course
> make sense to add an efficient handling of the case radius=0).
>
> Note the current f_rounded_box() is not a very efficient solution anyway
> (you don't need an sqrt() for every evaluation).
Actually I tried the following expression.
return (PARAM_X * PARAM_X
+ PARAM_Y * PARAM_Y
+ PARAM_Z * PARAM_Z
- PARAM(0)*PARAM(0));
against
return (
sqrt(PARAM_X * PARAM_X
+ PARAM_Y * PARAM_Y
+ PARAM_Z * PARAM_Z)
- PARAM(0));
And found that the latter was always faster by about 30%.
I'm not exactly sure why it is that way but one problem
is that a the max_gradient needs higher values.
For the former version a max_gradient of 1.0 is always
suitable whereas for the latter one something
like
2.0*sqrt(3)*RADIUS
is neccessary.
There may be parameters for which the latter one is faster
but in the geral case the square root beats the square.
A least this is the result from the tests renders I did
on my pentium-m 1300MHz machine.
The most promissing solution I found looks like this.
DBL f_rounded_box(DBL *ptr, unsigned int) // 60
{
DBL x2, y2, z2, x3, y3, z3;
x2 = PARAM(1) - PARAM(0);
y2 = PARAM(2) - PARAM(0);
z2 = PARAM(3) - PARAM(0);
x3 = fabs(PARAM_X);
y3 = fabs(PARAM_Y);
z3 = fabs(PARAM_Z);
PARAM_X = (x3 < x2) ? 0 : (x3 - x2);
PARAM_Y = (y3 < y2) ? 0 : (y3 - y2);
PARAM_Z = (z3 < z2) ? 0 : (z3 - z2);
return (sqrt(PARAM_X * PARAM_X + PARAM_Y * PARAM_Y + PARAM_Z * PARAM_Z)
- PARAM(0));
}
Using fabs gave me approx. 2% speed increase in the test scene
(p.b.images).
>
> To me it seems this offset is specifically for handling the degenerate
> case. Choosing 1e-3 simply gets you beyond your accuracy limit.
This was my intention. And yes, this is very likely. I tried the
degenerated case without the offset and the render process stuck
on the first line until I aborted after some minutes.
Sebastian
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Here's the image of the test scene I used for comparing
the speed of different incarnations of f_rounded_box.
Actually I desired a more ordered scene but a typo ended
in this fractal beauty...
Sebastian
Post a reply to this message
Attachments:
Download 'frb_benchmark.jpg' (44 KB)
Preview of image 'frb_benchmark.jpg'
![frb_benchmark.jpg](/povray.binaries.images/attachment/%3C44149d8a%40news.povray.org%3E/frb_benchmark.jpg?ttop=441697&toff=4550&preview=1)
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Sebastian H. wrote:
>>
>> Note the current f_rounded_box() is not a very efficient solution
>> anyway (you don't need an sqrt() for every evaluation).
>
> Actually I tried the following expression.
>
> return (PARAM_X * PARAM_X
> + PARAM_Y * PARAM_Y
> + PARAM_Z * PARAM_Z
> - PARAM(0)*PARAM(0));
>
That's not what i meant. You don't need the sqrt() on the faces of the
rounded cube - there a simple plane function is sufficient.
Christoph
--
POV-Ray tutorials, include files, Landscape of the week:
http://www.imagico.de/ (Last updated 31 Oct. 2005)
MegaPOV with mechanics simulation: http://megapov.inetart.net/
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Christoph Hormann wrote:
> Sebastian H. wrote:
>
> That's not what i meant. You don't need the sqrt() on the faces of the
> rounded cube - there a simple plane function is sufficient.
Hmm, needs some "if" calls but gives another speed boost of
approx. 8% in the test image.
The function now looks like this.
DBL f_rounded_box(DBL *ptr, unsigned int) // 60
{
DBL x2, y2, z2, x3, y3, z3;
x2 = PARAM(1) - PARAM(0);
y2 = PARAM(2) - PARAM(0);
z2 = PARAM(3) - PARAM(0);
x3 = fabs(PARAM_X);
y3 = fabs(PARAM_Y);
z3 = fabs(PARAM_Z);
PARAM_X = (x3 < x2) ? 0 : (x3 - x2);
PARAM_Y = (y3 < y2) ? 0 : (y3 - y2);
PARAM_Z = (z3 < z2) ? 0 : (z3 - z2);
// With coitus interruptus
if(!PARAM_X)
{
if(!PARAM_Y)
{
return (z3 - PARAM(3));
}
if(!PARAM_Z)
{
return (y3 - PARAM(2));
}
}
if((!PARAM_Y) && (!PARAM_Z))
{
return (x3 - PARAM(1));
}
return (sqrt(PARAM_X * PARAM_X + PARAM_Y * PARAM_Y + PARAM_Z *
PARAM_Z) - PARAM(0));
}
Now there appear gradients above 1.0 but I could not find
any surface errors so I think a max_gradient of 1.0 is still fine.
If anyone wants to put this code or part of into the official source
feel free.
Sebastian
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Sebastian H. wrote:
>
>> Sebastian H. wrote:
>>
>> That's not what i meant. You don't need the sqrt() on the faces of
>> the rounded cube - there a simple plane function is sufficient.
>
>
> Hmm, needs some "if" calls
Yes, that's what i meant. I would however do it somewhat differently
(untested, based on what you wrote):
{
DBL x2, y2, z2, x3, y3, z3;
x2 = PARAM(1) - PARAM(0);
y2 = PARAM(2) - PARAM(0);
z2 = PARAM(3) - PARAM(0);
x3 = fabs(PARAM_X);
y3 = fabs(PARAM_Y);
z3 = fabs(PARAM_Z);
if (x3 < x2)
{
if (y3 < y2)
{
if (z3 < z2)
{
return -PARAM(0);
}
return (z3 - PARAM(3));
}
if (z3 < z2)
{
return (y3 - PARAM(2));
}
return (sqrt(PARAM_Y * PARAM_Y + PARAM_Z * PARAM_Z) - PARAM(0));
}
if (y3 < y2)
{
if (z3 < z2)
{
return (x3 - PARAM(1));
}
return (sqrt(PARAM_X * PARAM_X + PARAM_Z * PARAM_Z) - PARAM(0));
}
if (z3 < z2)
{
return (sqrt(PARAM_X * PARAM_X + PARAM_Y * PARAM_Y) - PARAM(0));
}
return (sqrt(PARAM_X * PARAM_X + PARAM_Y * PARAM_Y + PARAM_Z *
PARAM_Z) - PARAM(0));
}
It would BTW be easy to add a correct distance function for the interior
as well by replacing the 'return -PARAM(0);'. This would of course
break backwards compatibility so it might not be a good idea.
Christoph
--
POV-Ray tutorials, include files, Landscape of the week:
http://www.imagico.de/ (Last updated 31 Oct. 2005)
MegaPOV with mechanics simulation: http://megapov.inetart.net/
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |