POV-Ray : Newsgroups : povray.advanced-users : Re: Infinite cone bug Server Time
27 Dec 2024 23:11:11 EST (-0500)
  Re: Infinite cone bug (Message 1 to 1 of 1)  
From: smellenbergh
Subject: Re: Infinite cone bug
Date: 21 Jul 1999 07:23:29
Message: <1dvam7l.bwt99hcd748wN@dialup361.leuven.skynet.be>
Gilles Tran <tra### [at] inapginrafr> wrote:

> Infinite cone bug
> ---------------------------------
> Description
> ---------------------------------
> Some cones appear to be infinite objects while they should be finite
> ones.
> 
> - When they appear in large numbers in a scene (when they are produced
> by a macro, for instance), they tend to slow the rendering down, even in
> the empty parts of the scene. They have appeared in branches of
> macro-generated trees (several cones in a same branch, for instance).
> 
> - These cones have in common to have a base and a top radius very close
> to each other relatively to the length of the cone (making the cone
> looking like a cylinder).
> 
> - Cones with parameters very close to the "offending" ones appear as
> finite cones but also slow down the rendering.
> 
> ---------------------------------
> Workarounds
> - Manually bounding the cone by a cylinder of the same maximum radius
> removes the problem at least in the empty zones of the image (and
> provided that automatic bounding is turned off). Unions of cones can be
> bounded too.
> - Using cylinders instead of cones...
> 
We discovered this a long time ago and reported it to the POV-Ray Team.
You will notice this bug easely when you use the draw vista buffer
option.

We have a solution for it (and it is implemented in our unofficial
compile for the Macintosh) but it is a workaround and certainly not a
bug fix. (but it works and decreases rendering time a lot).

Replace the following functions in the source files (you can use
3.1a,d,e or g sources) and make sure you define QUICK_CONES somewhere so
your compiler use the changes:

1)Cones.c
********
static void Transform_Cone(OBJECT *Object, TRANSFORM *Trans)
{
  CONE *Cone = (CONE *)Object;
  
  Compose_Transforms(Cone->Trans, Trans);
#ifdef QUICK_CONES
  if ( Cone->Trans->next != 0)
        Compose_Transforms(Cone->Trans->next,Trans);
#endif
  Compute_Cone_BBox(Cone);
}

void Compute_Cone_Data(OBJECT *Object)
{
  DBL tlen, len, tmpf;
  VECTOR tmpv, axis, origin;
  CONE *Cone = (CONE *)Object;

  /* Process the primitive specific information */
  if (fabs(Cone->apex_radius - Cone->base_radius) < EPSILON)
  {
    /* What we are dealing with here is really a cylinder */
    Set_Flag(Cone, CYLINDER_FLAG);
    Compute_Cylinder_Data(Object);
    return;
  }

  if (Cone->apex_radius < Cone->base_radius)
  {
    /* Want the bigger end at the top */
    Assign_Vector(tmpv,Cone->base);
    Assign_Vector(Cone->base,Cone->apex);
    Assign_Vector(Cone->apex,tmpv);
    tmpf = Cone->base_radius;
    Cone->base_radius = Cone->apex_radius;
    Cone->apex_radius = tmpf;
  }
#ifdef QUICK_CONES
        Cone->Trans->next=Create_Transform();
#endif

  /* Find the axis and axis length */
  VSub(axis, Cone->apex, Cone->base);
  VLength(len, axis);
  if (len < EPSILON)
  {
    Error("Degenerate cone/cylinder.\n");
  }
  else
  {
    VInverseScaleEq(axis, len)
  }
#ifdef QUICK_CONES
        Compute_Coordinate_Transform(Cone->Trans->next,Cone->base, axis,
Cone->apex_radius, len);
#endif

  /* Determine alignment */
  tmpf = Cone->base_radius * len / (Cone->apex_radius -
Cone->base_radius);
  VScale(origin, axis, tmpf);
  VSub(origin, Cone->base, origin);
  tlen = tmpf + len;
  Cone->dist = tmpf / tlen;
  Compute_Coordinate_Transform(Cone->Trans, origin, axis,
Cone->apex_radius, tlen);
  /* Recalculate the bounds */
  Compute_Cone_BBox(Cone);
}
static void Destroy_Cone(OBJECT *Object)
{
  #ifdef QUICK_CONES
        TRANSFORM *trans;
        trans= ((CONE*)Object)->Trans;
        if ( trans!= 0 && trans->next != 0)
                POV_FREE(trans->next);
#endif
  Destroy_Transform(((CONE *)Object)->Trans);

  POV_FREE (Object);
}
void Compute_Cone_BBox(CONE *Cone)
{
  Make_BBox(Cone->BBox, -1.0, -1.0, 0.0, 2.0, 2.0, 1.0);
#ifdef QUICK_CONES
        if ( Cone->Trans->next)
                Recompute_BBox(&Cone->BBox, Cone->Trans->next);
        else
                Recompute_BBox(&Cone->BBox, Cone->Trans);
#else
  Recompute_BBox(&Cone->BBox, Cone->Trans);
#endif
}

2)frame.h
********
typedef struct Transform_Struct TRANSFORM;

struct Transform_Struct
{
  MATRIX matrix;
  MATRIX inverse;
#ifdef QUICK_CONES
        TRANSFORM *next;
#endif
  
};

3)Matrices.c
**********
TRANSFORM *Create_Transform()
{
  TRANSFORM *New;

  New = (TRANSFORM *)POV_MALLOC(sizeof (TRANSFORM), "transform");

  MIdentity (New->matrix);
  MIdentity (New->inverse);
#ifdef QUICK_CONES
        New->next=0l;
#endif
  return (New);
}
TRANSFORM *Copy_Transform (TRANSFORM *Old)
{
  TRANSFORM *New;
  if (Old != NULL)
  {
    New  = Create_Transform ();
    *New = *Old;
#ifdef QUICK_CONES
        if ( Old->next != 0)
        {
                New->next=Create_Transform();
                *New->next=*Old->next;
        } 
#endif 

  }
  else
  {
    New = NULL;
  }

  return (New);
}

And that is all. Please notice that the memory requirements will
increase for every cone. 
Perhaps there is someone out there who can fix this bug and send it on
to the POV-Ray Team.
Everyone generating scenes with utilities like CTDS or some of our older
utilities will benefit from this fix.


-- 
e-mail:sme### [at] skynetbe

http://users.skynet.be/smellenbergh


Post a reply to this message

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