|
|
The listed script yields erronious results with or without
the "open" keyword in the prism commented out.
What is expected is a closed truncated prism. What is
observed is an open truncated prism with a misplaced face.
This has been checked on 3.1r1 and a patched 3.02 code so
far with identical results. For 3.1r1 it was checked
against the official POV for W95 and on the SuperPatch.
I realize only the official version is supported here,
but I report these facts for completeness -- it fails
on the official version. Thus it appears the bug
is in the core rendering code for this primitive.
Dan
==============================
#declare V0 = <0, -3, 0>;
#declare V1 = V0 + <-5, 9, -8>;
camera {
location V1
look_at V0
}
light_source {
V1
color rgb 0.5
}
light_source {
V1 * <-1, 1, 1>
color rgb 0.5
}
prism {
linear_spline
conic_sweep
-4, -3,
4,
<1, 1>, <-1, 1>, <-1, -1>, <1, -1>
//open
pigment { color rgb 1 }
finish { diffuse 0.5 ambient 0.5 }
}
--
http://www.flash.net/~djconnel/
Post a reply to this message
|
|
|
|
Dan Connelly wrote:
> The listed script yields erronious results with or without
> the "open" keyword in the prism commented out.
>
> What is expected is a closed truncated prism. What is
> observed is an open truncated prism with a misplaced face.
Hi Dan & other readers,
I have found two bugs in the code for cubic sweep prisms - firstly, the
'open' parameter does not work, and secondly, there is a mistake in the
bounding calculations that is causing the appearance of faulty end-caps
on some shapes.
To make the 'open' parameter function, insert the following code (marked
'*') at line 534 of PRISM.C:
else
{
* if (Test_Flag(Prism, CLOSED_FLAG))
* {
/* Intersect ray with the cap-plane. */
k = (Prism->Height2 - P[Y]) / D[Y];
if ((k > DEPTH_TOLERANCE) && (k < Max_Distance))
and close the braces at the appropriate place (after the base-plane
intersection test). That's really a pretty trivial bug & fix (unless I
overlooked something...).
I have not yet found a 'clean' fix for the bounding problem, but it can
be bypassed by changing the following lines (marked "*") in function
"in_curve", PRISM.C line 1317:
/* First test overall bounding rectangle. */
* if (((u >= Prism->x1) && (u <= Prism->x2) &&
* (v >= Prism->y1) && (v <= Prism->y2)) || (Prism->Sweep_Type ==
CONIC_SWEEP))
{
for (i = 0; i < Prism->Number; i++)
{
Entry = Prism->Spline->Entry[i];
/* Test if current segment can be hit. */
* if (((v >= Entry.y1) && (v <= Entry.y2) && (u <= Entry.x2))
* || (Prism->Sweep_Type == CONIC_SWEEP))
{
This will completely bypass bounds-checking for the end caps of conic
sweep prisms, which will probably degrade performance significantly, but
will produce the correct image. I have determined the cause of this
problem, and I am still working on producing a better fix for this
problem.
For the interested (few, very few I'd say...) the bug is caused by the
following: When the end-caps of a conic spline are tested, POV-Ray
determines the point at which the ray intersects the plane of the
end-cap, and then determines the <u, v> coordinates (in the plane of the
defined spline) which this point represents and calls in_curve to
determine whether this point is within the end-cap. The <u, v> value is
then erroneously compared against the calculated shape & segment bounds
for the conic sweep prism object itself rather than the bounds of the
*spline*, which are quite different. This is the cause of the errors.
The problem is demonstrated by many conic_sweep prisms for which the
interval HEIGHT1..HEIGHT2 does not include the value +1.0
I will pass these fixes onto the POV-Team once I have found a better way
of fixing the bounds problem.
Cheers,
Darius Davis
Post a reply to this message
|
|
|
|
Hi all,
I have forwarded this on to the POV-Team. All of the problems that
these bugs except one can be bypassed by changing the scaling of the
object or making other changes to the scene, so I dont think it's a
particularly urgent fix.
Cheers,
Darius
--------------------------------------
I have tracked down several bugs in conic_sweep prisms, for which fixes
are supplied below:
- End caps may be traced incorrectly if HEIGHT1..HEIGHT2 does not
include the value +1.0,
- the 'open' parameter doesn't work at all, regardless of the other
parameters, and
- the bottom face of a conic_sweep prism doesn't trace if the height of
the bottom face is negative.
There are two other minor problems in Inside_Prism and Prism_Normal,
from which it seems likely that the original code was not intended to
cope with negative values of HEIGHT1 or HEIGHT2. Fixes for those
problems are also included below, and (as far as I can tell) these will
allow conic_sweep prisms to trace correctly for all values of HEIGHT1
and HEIGHT2.
Also, the comment block at the top of PRISM.C says 'cubic_sweep' instead
of 'conic_sweep' (on line 74)... I don't think that'll cause any
rendering problems, though, just a brief moment of confusion for me :)
The following sample scene demonstrates all of the problems:
-------------------------------------------
camera {location <-5, 2, -8> direction z*5 look_at 0.5*y}
light_source {<1, 0, -3> color rgb 1}
// only use one of these prism objects at once!
prism { // demonstrates end-cap problem, 'open' problem
linear_spline
conic_sweep
0.4, 0.5,
5,
<1,1>, <1,-1>, <-1,-1>, <-1,1>, <1,1>
// open
texture {pigment {checker color rgb 1 color rgb 0.5 scale <0.2, 0.4,
0.2>} finish {ambient 0.5}}
}
prism { // demonstrates Prism_Normal problem. Put camera at <0.1, 0.45,
0.1> to
// see Inside_Prism problem - no warning is given.
linear_spline
conic_sweep
-0.4, -0.5,
5,
<1,1>, <1,-1>, <-1,-1>, <-1,1>, <1,1>
texture {pigment {checker color rgb 1 color rgb 0.5 scale <0.2, 0.4,
0.2>} finish {ambient 0.5}}
scale <1, -1, 1>
}
-------------------------------------------
The end-cap problem is caused by intersect_prism passing *spline*
coordinates (ie. <u, v> coordinates) to in_curve, which then compares
the <u, v> coordinates against the bounding boxes for the spline
segments in the <x, z> plane. This causes it to incorrectly eliminate
spline segments from its calculations, and hence traces incorrectly. I
have fixed this by adding bounding information for the <u, v>
coordinates to the structures for the prism & spline segments, and using
this new bounding information in in_curve. This uses a bit more memory,
but is speed-efficient and traces correctly.
All of the other problems are simple omissions, errors or oversights,
and are quite self-explanatory.
Here's a complete fix for all of the prism problems I know of at the
moment. Changes are required in PRISM.H and PRISM.C. Line numbers are
for 3.1r1.
---------------------------------------------------------------------------
PRISM.H:
Add to definition of Prism_Spline_Entry_Struct:
DBL v1, u2, v2; /* Min./Max. coordinates of segment in <u,v>, u1
not needed */
Add to definition of Prism_Struct:
DBL u1, v1, u2, v2; /* Overall <u,v> bounding rectangle of
spline */
PRISM.C:
Replace lines 532-570 (function intersect_prism) with
532 else
{
if (Test_Flag(Prism, CLOSED_FLAG))
{
/* Intersect ray with the cap-plane. */
if (fabs(Prism->Height2) > EPSILON)
{
k = (Prism->Height2 - P[Y]) / D[Y];
if ((k > DEPTH_TOLERANCE) && (k < Max_Distance))
{
u = (P[X] + k * D[X]) / Prism->Height2;
v = (P[Z] + k * D[Z]) / Prism->Height2;
if (in_curve(Prism, u, v))
{
Intersection[i].t = CAP_HIT;
Intersection[i++].d = k / len;
}
}
}
/* Intersect ray with the base-plane. */
if (fabs(Prism->Height1) > EPSILON)
{
k = (Prism->Height1 - P[Y]) / D[Y];
if ((k > DEPTH_TOLERANCE) && (k < Max_Distance))
{
u = (P[X] + k * D[X]) / Prism->Height1;
v = (P[Z] + k * D[Z]) / Prism->Height1;
if (in_curve(Prism, u, v))
{
Intersection[i].t = BASE_HIT;
Intersection[i++].d = k / len;
}
}
}
}
}
570 /* Precompute ray-only dependant constants. */
Change line 761 (function Inside_Prism) to read:
/* Scale x and z coordinate. */
if (fabs(P[Y]) > EPSILON)
(fixes Inside_Prism for region below x-z plane)
Change line 846 (function Prism_Normal) to match:
case CONIC_SWEEP:
/* Transform the point into the prism space. */
MInvTransPoint(P, Inter->IPoint, Prism->Trans);
if (fabs(P[Y]) > EPSILON)
(fixes normals for region below x-z plane)
Insert the following between lines 1102 and 1103 (function
Create_Prism):
1102 New->y2 =
New->u1 =
New->u2 =
New->v1 =
New->v2 =
1103 New->Height1 =
Replace lines 1317-1329 (function in_curve) with the following:
/* First test overall bounding rectangle. */
if ((u >= Prism->u1) && (u <= Prism->u2) &&
(v >= Prism->v1) && (v <= Prism->v2))
{
for (i = 0; i < Prism->Number; i++)
{
Entry = Prism->Spline->Entry[i];
/* Test if current segment can be hit. */
if ((v >= Entry.v1) && (v <= Entry.v2) && (u <= Entry.u2))
{
Replace lines 1771-1775 (function Compute_Prism) with the following:
/* Set current segment's bounding rectangle. */
Prism->Spline->Entry[number_of_splines].x1 = min(min(x[0], x[1]),
min(x[2], x[3]));
Prism->Spline->Entry[number_of_splines].x2 =
Prism->Spline->Entry[number_of_splines].u2 = max(max(x[0], x[1]),
max(x[2], x[3]));
Prism->Spline->Entry[number_of_splines].y1 =
Prism->Spline->Entry[number_of_splines].v1 = min(min(y[0], y[1]),
min(y[2], y[3]));
Prism->Spline->Entry[number_of_splines].y2 =
Prism->Spline->Entry[number_of_splines].v2 = max(max(y[0], y[1]),
max(y[2], y[3]));
Replace lines 1848-1852 (function Compute_Prism) with the following:
/* Set overall bounding rectangle. */
Prism->x1 =
Prism->u1 = xmin;
Prism->x2 =
Prism->u2 = xmax;
Prism->y1 =
Prism->v1 = ymin;
Prism->y2 =
Prism->v2 = ymax;
---------------------------------------------------------------------------
Post a reply to this message
|
|