/**************************************************************************** * 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 RAY *VP_Ray; 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); 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++; } }