POV-Ray : Newsgroups : povray.bugreports : prism, linear spline, conic sweep bug : Re: prism, linear spline, conic sweep bug - FIX Server Time
18 Jun 2024 09:19:11 EDT (-0400)
  Re: prism, linear spline, conic sweep bug - FIX  
From: Darius Davis
Date: 7 Dec 1998 04:47:20
Message: <366C9F7B.7B83@acm.org>
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

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