home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * objects.c
- *
- * This module implements the methods for objects and composite objects.
- *
- * from Persistence of Vision Raytracer
- * Copyright 1993 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file. If
- * POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- * Forum. The latest version of POV-Ray may be found there as well.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
-
- #include "frame.h"
- #include "vector.h"
- #include "povproto.h"
-
- extern long Bounding_Region_Tests, Bounding_Region_Tests_Succeeded;
- extern long Clipping_Region_Tests, Clipping_Region_Tests_Succeeded;
- extern unsigned int Options;
- extern long Istack_overflows;
- extern int Number_of_istacks;
- extern int Max_Intersections;
- extern ISTACK *free_istack;
-
- int Intersection (Ray_Intersection, Object, Ray)
- INTERSECTION *Ray_Intersection;
- OBJECT *Object;
- RAY *Ray;
- {
- ISTACK *Depth_Stack;
- INTERSECTION *Local;
- DBL Closest = HUGE_VAL;
-
- if (Object == NULL)
- return (FALSE);
-
- if(!Ray_In_Bounds (Ray,Object->Bound))
- return (FALSE);
-
- Depth_Stack = open_istack ();
-
- if (All_Intersections (Object, Ray, Depth_Stack))
- {
- while ((Local = pop_entry(Depth_Stack)) != NULL)
- if (Local->Depth < Closest)
- {
- *Ray_Intersection = *Local;
- Closest = Local->Depth;
- }
- close_istack (Depth_Stack);
- return (TRUE);
- }
- else
- {
- close_istack (Depth_Stack);
- return (FALSE);
- }
- }
-
- int Ray_In_Bounds (Ray,Bounds)
- RAY *Ray;
- OBJECT *Bounds;
- {
- OBJECT *Bound;
- INTERSECTION Local;
-
- for (Bound = Bounds;
- Bound != NULL;
- Bound = Bound->Sibling)
- {
- Bounding_Region_Tests++;
-
- if (!Intersection (&Local, Bound, Ray))
- if (!Inside_Object(&Ray->Initial,Bound))
- return (FALSE);
-
- Bounding_Region_Tests_Succeeded++;
- }
-
- return (TRUE);
- }
-
- int Point_In_Clip (IPoint, Clip)
- VECTOR *IPoint;
- OBJECT *Clip;
- {
- OBJECT *Local_Clip;
-
- for (Local_Clip = Clip;
- Local_Clip != NULL;
- Local_Clip = Local_Clip->Sibling)
- {
- Clipping_Region_Tests++;
- if (!Inside_Object(IPoint, Local_Clip))
- return (FALSE);
-
- Clipping_Region_Tests_Succeeded++;
- }
- return (TRUE);
- }
-
- OBJECT *Copy_Bound_Clip (Old)
- OBJECT *Old;
- {
- OBJECT *Current, *New, *Prev, *First;
-
- First = Prev = NULL;
-
- for (Current = Old;
- Current != NULL ;
- Current = Current->Sibling)
- {
- New = Copy_Object (Current);
- if (First == NULL)
- First = New;
- if (Prev != NULL)
- Prev->Sibling = New;
- Prev = New;
- }
- return (First);
- }
-
- OBJECT *Copy_Object (Old)
- OBJECT *Old;
- {
- OBJECT *New;
-
- if (Old == NULL)
- return (NULL);
-
- New = Copy (Old);
-
- /* The following copying of OBJECT_FIELDS is redundant if Copy
- did *New = *Old but we cannot assume it did.
- It is safe for Copy to do *New = *Old but it should not otherwise
- touch OBJECT_FIELDS. */
-
- New->Methods = Old->Methods;
- New->Type = Old->Type;
- New->Sibling = Old->Sibling;
- New->Texture = Old->Texture;
- New->Bound = Old->Bound;
- New->Clip = Old->Clip;
- New->Bounds = Old->Bounds;
- New->No_Shadow_Flag = Old->No_Shadow_Flag;
-
- New->Sibling = NULL; /* Important */
-
- New->Texture = Copy_Textures (Old->Texture);
- New->Bound = Copy_Bound_Clip (Old->Bound);
- if (Old->Bound != Old->Clip)
- New->Clip = Copy_Bound_Clip (Old->Clip);
- else
- New->Clip = New->Bound;
-
- return (New);
- }
-
- void Translate_Object (Object, Vector)
- OBJECT *Object;
- VECTOR *Vector;
- {
- OBJECT *Sib;
-
- if (Object == NULL)
- return;
-
- for (Sib = Object->Bound;
- Sib != NULL;
- Sib = Sib->Sibling)
- Translate_Object (Sib, Vector);
-
- if (Object->Clip != Object->Bound)
- for (Sib = Object->Clip;
- Sib != NULL;
- Sib = Sib->Sibling)
- Translate_Object (Sib, Vector);
-
- Translate_Textures (Object->Texture,Vector);
-
- Translate (Object,Vector);
- }
-
- void Rotate_Object (Object, Vector)
- OBJECT *Object;
- VECTOR *Vector;
- {
- OBJECT *Sib;
-
- if (Object == NULL)
- return;
-
- for (Sib = Object->Bound;
- Sib != NULL;
- Sib = Sib->Sibling)
- Rotate_Object (Sib, Vector);
-
- if (Object->Clip != Object->Bound)
- for (Sib = Object->Clip;
- Sib != NULL;
- Sib = Sib->Sibling)
- Rotate_Object (Sib, Vector);
-
- Rotate_Textures (Object->Texture,Vector);
-
- Rotate (Object,Vector);
- }
-
- void Scale_Object (Object, Vector)
- OBJECT *Object;
- VECTOR *Vector;
- {
- OBJECT *Sib;
-
- if (Object == NULL)
- return;
-
- for (Sib = Object->Bound;
- Sib != NULL;
- Sib = Sib->Sibling)
- Scale_Object (Sib, Vector);
-
- if (Object->Clip != Object->Bound)
- for (Sib = Object->Clip;
- Sib != NULL;
- Sib = Sib->Sibling)
- Scale_Object (Sib, Vector);
-
- Scale_Textures (Object->Texture,Vector);
-
- Scale (Object,Vector);
- }
-
- int Inside_Object (IPoint, Object)
- VECTOR *IPoint;
- OBJECT *Object;
- {
- OBJECT *Sib;
-
- /* removed 7/19/92 CEY
- for (Sib = Object->Bound;
- Sib != NULL;
- Sib = Sib->Sibling)
- if (!Inside_Object(IPoint, Sib))
- return(FALSE);
- */
- for (Sib = Object->Clip;
- Sib != NULL;
- Sib = Sib->Sibling)
- if (!Inside_Object(IPoint, Sib))
- return(FALSE);
-
- return (Inside(IPoint,Object));
- }
-
- void Invert_Object (Object)
- OBJECT *Object;
- {
- /* OBJECT *Sib; */
-
- if (Object == NULL)
- return;
-
- /* removed 3/29/93 CEY
- for (Sib = Object->Clip;
- Sib != NULL;
- Sib = Sib->Sibling)
- Invert_Object (Sib);
- */
- Invert (Object);
- }
-
- void Destroy_Object (Object)
- OBJECT *Object;
- {
- OBJECT *Sib;
-
- while (Object != NULL)
- {
- Destroy_Textures (Object->Texture);
- Destroy_Object (Object->Bound);
- if (Object->Bound != Object->Clip)
- Destroy_Object (Object->Clip);
- Sib = Object->Sibling;
- Destroy(Object);
- Object = Sib;
- }
- }
-
- void Transform_Object (Object, Trans)
- OBJECT *Object;
- TRANSFORM *Trans;
- {
- OBJECT *Sib;
-
- if (Object == NULL)
- return;
-
- for (Sib = Object->Bound;
- Sib != NULL;
- Sib = Sib->Sibling)
- Transform_Object (Sib, Trans);
-
- if (Object->Clip != Object->Bound)
- for (Sib = Object->Clip;
- Sib != NULL;
- Sib = Sib->Sibling)
- Transform_Object (Sib, Trans);
-
- Transform_Textures (Object->Texture,Trans);
-
- Transform (Object,Trans);
- }
-
- void create_istack ()
- {
- ISTACK *New;
-
- if ((New = (ISTACK *) malloc (sizeof (ISTACK))) == NULL)
- {
- fprintf (stderr, "\nOut of memory. Cannot allocate istack");
- close_all();
- exit(1);
- }
-
- New->next = free_istack;
- free_istack = New;
-
- if ((New->istack = (INTERSECTION *)
- malloc (Max_Intersections * sizeof (INTERSECTION))) == NULL)
- {
- fprintf (stderr, "\nOut of memory. Cannot allocate istack entries");
- close_all();
- exit(1);
- }
- Number_of_istacks++;
- }
-
- ISTACK *open_istack()
- {
- ISTACK *istk;
-
- if (free_istack == NULL)
- create_istack ();
-
- istk = free_istack;
- free_istack = istk->next;
- istk->top_entry = 0;
-
- return (istk);
- }
-
- void close_istack (istk)
- ISTACK *istk;
- {
- istk->next = free_istack;
- free_istack = istk;
- }
-
- void incstack(istk)
- ISTACK *istk;
- {
- if (++istk->top_entry >= (unsigned int)Max_Intersections)
- {
- istk->top_entry--;
- Istack_overflows++;
- }
- }
-