|
|
Next try.
The version below isn't as fast as my C++ version as it doesn't use a
BBOX tree for the inverted children. Timing values for a level 4
menger sponge are:
Original Version: 2207 seconds
this C Version: 523 seconds
my C++ Version: 35 seconds
benchmark.pov, rendered with -w384 -h384 +a0.3 +v -d -f -x
Original Version: 5987 seconds
this C Version: 4280 seconds
Add this flag to objects.h:
#define CSG_SIBLING_IGNORE_FLAG 0x2000000L /*AKA: csg internal flag*/
/*****************************************************************************
*
* FUNCTION
*
* All_CSG_Intersection_Intersections
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* POV-Ray Team
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Sep 1994 : Added code to count intersection tests. [DB]
* Dec 2003 : Changes to enable early escape and reduce number of
* 'Inside_Object()' tests. [AKA]
*
******************************************************************************/
static int All_CSG_Intersect_Intersections (OBJECT *Object, RAY *Ray,
ISTACK *Depth_Stack)
{
int Maybe_Found, Found;
OBJECT *Current_Sib;
ISTACK *Local_Stack;
INTERSECTION *Sibling_Intersection;
Increase_Counter(stats[Ray_CSG_Intersection_Tests]);
/* To get an intersection for a CSG-Intersection object, it must be
inside of all siblings. If a ray misses one ore more siblings
completely, the CSG-Intersection isn't hit by this ray. */
Local_Stack = open_istack ();
/* 1st step: get intersection points of all children */
for (Current_Sib = ((CSG *)Object)->Children;
Current_Sib != NULL;
Current_Sib = Current_Sib->Sibling)
{
if (Ray_In_Bound (Ray, Current_Sib->Bound) &&
All_Intersections (Current_Sib, Ray, Local_Stack))
{
/* the child's intersection points have been added to
'Local_Stack', clear the 'ignore' flag. */
Clear_Flag(Current_Sib, CSG_SIBLING_IGNORE_FLAG);
continue; /* try the next one */
}
/* If we reach here, the ray was out-of-bounds and/or the child
wasn't hit. */
if (!Inside_Object(Ray->Initial, Current_Sib))
{
/* Ray's origin is outside of 'Current_Sib' and doesn't hit any
of it's boundaries ==> we can escape here. */
close_istack (Local_Stack);
return(false);
}
else
{
/* Ray's origin is inside of 'Current_Sib' and doesn't hit any
of it's boundaries, so the entire ray is inside of
'Current_Sib'.
==> this sibling can be ignored in the 2nd step as any
intersection is inside of it, so set the 'ignore' flag.*/
Set_Flag(Current_Sib, CSG_SIBLING_IGNORE_FLAG);
}
}
/* 2nd step: for each entry in 'Local_Stack' check whether the
intersection point is inside of each sibling */
Found = false;
while ((Sibling_Intersection = pop_entry(Local_Stack)) != NULL)
{
Maybe_Found = true;
for (Current_Sib = ((CSG *)Object)->Children;
Current_Sib != NULL;
Current_Sib = Current_Sib->Sibling)
{
if (Test_Flag(Current_Sib, CSG_SIBLING_IGNORE_FLAG) ||
(Current_Sib == Sibling_Intersection->Object))
continue; /* with the next sibling */
if (!(Current_Sib->Type & LIGHT_SOURCE_OBJECT) ||
((LIGHT_SOURCE *)Current_Sib)->Children)
{
if (!Inside_Object (Sibling_Intersection->IPoint,
Current_Sib))
{
Maybe_Found = false;
break; /* try the next intersection */
}
}
}
if (Maybe_Found)
{
if (Point_In_Clip (Sibling_Intersection->IPoint, Object->Clip))
{
if (Test_Flag(Object, MULTITEXTURE_FLAG))
{
Sibling_Intersection->Csg = Object;
}
push_copy(Depth_Stack, Sibling_Intersection);
Found = true;
}
}
}
close_istack (Local_Stack);
if (Found)
{
Increase_Counter(stats[Ray_CSG_Intersection_Tests_Succeeded]);
}
return (Found);
}
Post a reply to this message
|
|