static int intersect_poylgon(RAY *Ray, POLYGON *Polyg, DBL *Depth) { DBL x, y, len; VECTOR p, d; /* Don't test degenerate polygons. */ if (Test_Flag(Polyg, DEGENERATE_FLAG)) { return(false); } Increase_Counter(stats[Ray_Polygon_Tests]); /* Transform the ray into the polygon space. */ MInvTransPoint(p, Ray->Initial, Polyg->Trans); MInvTransDirection(d, Ray->Direction, Polyg->Trans); VLength(len, d); VInverseScaleEq(d, len); /* Intersect ray with the plane in which the polygon lies. */ if (fabs(d[Z]) < ZERO_TOLERANCE) { return(false); } *Depth = -p[Z] / d[Z]; if ((*Depth < DEPTH_TOLERANCE) || (*Depth > Max_Distance)) { return(false); } /* Does the intersection point lie inside the polygon? */ x = p[X] + *Depth * d[X]; y = p[Y] + *Depth * d[Y]; if (in_polygon(Polyg->Data->Number, Polyg->Data->Points, x, y)) { Increase_Counter(stats[Ray_Polygon_Tests_Succeeded]); *Depth /= len; return (true); } else { return (false); } }
static int Intersect_Quadric(RAY *Ray, QUADRIC *Quadric, DBL *Depth1, DBL *Depth2) { register DBL a, b, c, d; Increase_Counter(stats[Ray_Quadric_Tests]); a = Xd * (QA * Xd + QB * Yd + QC * Zd) + Yd * (QE * Yd + QF * Zd) + QH * Zd * Zd; b = Xd * (QA * Xo + 0.5 * (QB * Yo + QC * Zo + QD)) + Yd * (QE * Yo + 0.5 * (QB * Xo + QF * Zo + QG)) + Zd * (QH * Zo + 0.5 * (QC * Xo + QF * Yo + QI)); c = Xo * (QA * Xo + QB * Yo + QC * Zo + QD) + Yo * (QE * Yo + QF * Zo + QG) + Zo * (QH * Zo + QI) + QJ; if (a != 0.0) { /* The equation is quadratic - find its roots */ d = Sqr(b) - a * c; if (d <= 0.0) { return(false); } d = sqrt (d); *Depth1 = (-b + d) / (a); *Depth2 = (-b - d) / (a); } else { /* There are no quadratic terms. Solve the linear equation instead. */ if (b == 0.0) { return(false); } *Depth1 = - 0.5 * c / b; *Depth2 = Max_Distance; } Increase_Counter(stats[Ray_Quadric_Tests_Succeeded]); return(true); }
static void priority_queue_insert(PRIORITY_QUEUE *Queue, DBL Depth, BBOX_TREE *Node) { unsigned size; int i; QELEM tmp; QELEM *List; #ifdef BBOX_EXTRA_STATS Increase_Counter(stats[totalQueues]); #endif Queue->QSize++; size = Queue->QSize; /* Reallocate priority queue if it's too small. */ if (size >= Queue->Max_QSize) { if (size >= INT_MAX/2) { Error("Priority queue overflow."); } #ifdef BBOX_EXTRA_STATS Increase_Counter(stats[totalQueueResizes]); #endif Queue->Max_QSize *= 2; Queue->Queue = (QELEM *)POV_REALLOC(Queue->Queue, Queue->Max_QSize*sizeof(QELEM), "priority queue"); } List = Queue->Queue; List[size].Depth = Depth; List[size].Node = Node; i = size; while (i > 1 && List[i].Depth < List[i / 2].Depth) { tmp = List[i]; List[i] = List[i / 2]; List[i / 2] = tmp; i = i / 2; } }
static int Intersect_Plane (RAY *Ray, PLANE *Plane, DBL *Depth) { DBL NormalDotOrigin, NormalDotDirection; VECTOR P, D; Increase_Counter(stats[Ray_Plane_Tests]); if (Plane->Trans == NULL) { VDot(NormalDotDirection, Plane->Normal_Vector, Ray->Direction); if (fabs(NormalDotDirection) < EPSILON) { return(false); } VDot(NormalDotOrigin, Plane->Normal_Vector, Ray->Initial); } else { MInvTransPoint(P, Ray->Initial, Plane->Trans); MInvTransDirection(D, Ray->Direction, Plane->Trans); VDot(NormalDotDirection, Plane->Normal_Vector, D); if (fabs(NormalDotDirection) < EPSILON) { return(false); } VDot(NormalDotOrigin, Plane->Normal_Vector, P); } *Depth = -(NormalDotOrigin + Plane->Distance) / NormalDotDirection; if ((*Depth >= DEPTH_TOLERANCE) && (*Depth <= Max_Distance)) { Increase_Counter(stats[Ray_Plane_Tests_Succeeded]); return (true); } else { return (false); } }
void incstack(ISTACK *istk) { if(++istk->top_entry >= istk->max_entries) { istk->top_entry--; Increase_Counter(stats[Istack_overflows]); } }
bool Point_In_Clip (VECTOR IPoint, OBJECT *Clip) { OBJECT *Local_Clip; for (Local_Clip = Clip; Local_Clip != NULL; Local_Clip = Local_Clip->Sibling) { Increase_Counter(stats[Clipping_Region_Tests]); if (!Inside_Object(IPoint, Local_Clip)) { return (false); } Increase_Counter(stats[Clipping_Region_Tests_Succeeded]); } return (true); }
static int All_Box_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack) { int Intersection_Found; int Side1, Side2; DBL Depth1, Depth2; VECTOR IPoint; Increase_Counter(stats[Ray_Box_Tests]); Intersection_Found = false; if (Intersect_Box(Ray, ((BOX *)Object)->Trans, ((BOX *)Object)->bounds[0], ((BOX *)Object)->bounds[1], &Depth1, &Depth2, &Side1, &Side2)) { if (Depth1 > DEPTH_TOLERANCE) { VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction); if (Point_In_Clip(IPoint, Object->Clip)) { push_entry_i1(Depth1,IPoint,Object,Side1,Depth_Stack); Intersection_Found = true; } } VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction); if (Point_In_Clip(IPoint, Object->Clip)) { push_entry_i1(Depth2,IPoint,Object,Side2,Depth_Stack); Intersection_Found = true; } } if (Intersection_Found) { Increase_Counter(stats[Ray_Box_Tests_Succeeded]); } return (Intersection_Found); }
static int Intersect_Disc (RAY *Ray, DISC *disc, DBL *Depth) { DBL t, u, v, r2, len; VECTOR P, D; Increase_Counter(stats[Ray_Disc_Tests]); /* Transform the point into the discs space */ MInvTransPoint(P, Ray->Initial, disc->Trans); MInvTransDirection(D, Ray->Direction, disc->Trans); VLength(len, D); VInverseScaleEq(D, len); if (fabs(D[Z]) > EPSILON) { t = -P[Z] / D[Z]; if (t >= 0.0) { u = P[X] + t * D[X]; v = P[Y] + t * D[Y]; r2 = Sqr(u) + Sqr(v); if ((r2 >= disc->iradius2) && (r2 <= disc->oradius2)) { *Depth = t / len; if ((*Depth > Small_Tolerance) && (*Depth < Max_Distance)) { Increase_Counter(stats[Ray_Disc_Tests_Succeeded]); return (true); } } } } return (false); }
bool Ray_In_Bound (RAY *Ray, OBJECT *Bounding_Object) { OBJECT *Bound; INTERSECTION Local; for (Bound = Bounding_Object; Bound != NULL; Bound = Bound->Sibling) { Increase_Counter(stats[Bounding_Region_Tests]); if (!Intersection (&Local, Bound, Ray)) { if (!Inside_Object(Ray->Initial, Bound)) { return (false); } } Increase_Counter(stats[Bounding_Region_Tests_Succeeded]); } return (true); }
static int All_Bicubic_Patch_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack) { int Found, cnt = 0; Found = false; Increase_Counter(stats[Ray_Bicubic_Tests]); switch (((BICUBIC_PATCH *)Object)->Patch_Type) { case 0: cnt = intersect_bicubic_patch0(Ray, ((BICUBIC_PATCH *)Object), Depth_Stack); break; case 1: cnt = bezier_tree_walker(Ray, (BICUBIC_PATCH *)Object, ((BICUBIC_PATCH *)Object)->Node_Tree, Depth_Stack); break; default: Error("Bad patch type in All_Bicubic_Patch_Intersections."); } if (cnt > 0) { Increase_Counter(stats[Ray_Bicubic_Tests_Succeeded]); Found = true; } return (Found); }
int Intersect_Light_Tree(RAY *Ray, PROJECT_TREE_NODE *Tree, int x, int y, INTERSECTION *Best_Intersection, OBJECT **Best_Object, LIGHT_SOURCE * /*Light_Source*/) { INTERSECTION New_Intersection; unsigned short i; int Found; RAYINFO rayinfo; DBL key; BBOX_TREE *BBox_Node; PROJECT_TREE_NODE *Node; /* If there's no vista tree then return. */ if (Tree == NULL) { return(false); } /* Start with an empty priority queue */ New_Intersection.Object = NULL; VLBuffer_Queue->QSize = 0; Found = false; #ifdef BBOX_EXTRA_STATS Increase_Counter(stats[totalQueueResets]); #endif /* Traverse the tree. */ Node_Queue->QSize = 0; /* Create the direction vectors for this ray */ Create_Rayinfo(Ray, &rayinfo); /* Fill the priority queue with all possible candidates */ /* Check root */ Increase_Counter(stats[LBuffer_Tests]); if ((x >= Tree->Project.x1) && (x <= Tree->Project.x2) && (y >= Tree->Project.y1) && (y <= Tree->Project.y2)) { Increase_Counter(stats[LBuffer_Tests_Succeeded]); Node_Queue->Queue[(Node_Queue->QSize)++] = Tree; } /* Loop until queue is empty. */ while (Node_Queue->QSize > 0) { Tree = Node_Queue->Queue[--(Node_Queue->QSize)]; if (Tree->is_leaf) { /* Leaf --> test object's bounding box in 3d */ Check_And_Enqueue(VLBuffer_Queue, ((PROJECT_TREE_LEAF *)Tree)->Node, &((PROJECT_TREE_LEAF *)Tree)->Node->BBox, &rayinfo); } else { /* Check siblings of the node in 2d */ for (i = 0; i < Tree->Entries; i++) { Node = Tree->Entry[i]; Increase_Counter(stats[LBuffer_Tests]); if ((x >= Node->Project.x1) && (x <= Node->Project.x2) && (y >= Node->Project.y1) && (y <= Node->Project.y2)) { Increase_Counter(stats[LBuffer_Tests_Succeeded]); /* Reallocate queues if they're too small. */ Reinitialize_VLBuffer_Code(); /* Add node to node queue */ Node_Queue->Queue[(Node_Queue->QSize)++] = Node; } } } } /* Now test the candidates in the priority queue */ while (VLBuffer_Queue->QSize > 0) { Priority_Queue_Delete(VLBuffer_Queue, &key, &BBox_Node); if (key > Best_Intersection->Depth) { break; } if (Intersection(&New_Intersection, (OBJECT *)BBox_Node->Node, Ray)) { if (New_Intersection.Depth < Best_Intersection->Depth && /* NK Feb 6, 2000 - bugfix */ New_Intersection.Depth > Small_Tolerance) { *Best_Intersection = New_Intersection; *Best_Object = (OBJECT *)BBox_Node->Node; Found = true; } } } return(Found); }
bool Intersect_BBox_Tree(BBOX_TREE *Root, RAY *Ray, INTERSECTION *Best_Intersection, OBJECT **Best_Object, bool shadow_flag) { int i, found; DBL Depth; BBOX_TREE *Node; RAYINFO rayinfo; INTERSECTION New_Intersection; /* Create the direction vectors for this ray. */ Create_Rayinfo(Ray, &rayinfo); /* Start with an empty priority queue. */ New_Intersection.Object = NULL; found = false; Frame_Queue->QSize = 0; #ifdef BBOX_EXTRA_STATS Increase_Counter(stats[totalQueueResets]); #endif /* Check top node. */ Check_And_Enqueue(Frame_Queue, Root, &Root->BBox, &rayinfo); /* Check elements in the priority queue. */ while (Frame_Queue->QSize) { Priority_Queue_Delete(Frame_Queue, &Depth, &Node); /* * If current intersection is larger than the best intersection found * so far our task is finished, because all other bounding boxes in * the priority queue are further away. */ if (Depth > Best_Intersection->Depth) { break; } /* Check current node. */ if (Node->Entries) { /* This is a node containing leaves to be checked. */ for (i = 0; i < Node->Entries; i++) { Check_And_Enqueue(Frame_Queue, Node->Node[i], &Node->Node[i]->BBox, &rayinfo); } } else { /* This is a leaf so test contained object. */ /* Add Object-Ray options [ENB 9/97] */ if ( TEST_RAY_FLAGS_SHADOW((OBJECT *)Node->Node) ) { if (Intersection(&New_Intersection, (OBJECT *)Node->Node, Ray)) { if (New_Intersection.Depth < Best_Intersection->Depth) { *Best_Intersection = New_Intersection; *Best_Object = (OBJECT *)Node->Node; found = true; } } } } } return (found); }
void Check_And_Enqueue(PRIORITY_QUEUE *Queue, BBOX_TREE *Node, BBOX *BBox, RAYINFO *rayinfo) { DBL tmin, tmax; DBL dmin, dmax; if (Node->Infinite) { /* Set intersection depth to -Max_Distance. */ dmin = -Max_Distance; } else { Increase_Counter(stats[nChecked]); if (rayinfo->nonzero[X]) { if (rayinfo->positive[X]) { dmin = (BBox->Lower_Left[X] - rayinfo->slab_num[X]) * rayinfo->slab_den[X]; dmax = dmin + (BBox->Lengths[X] * rayinfo->slab_den[X]); if (dmax < EPSILON) return; } else { dmax = (BBox->Lower_Left[X] - rayinfo->slab_num[X]) * rayinfo->slab_den[X]; if (dmax < EPSILON) return; dmin = dmax + (BBox->Lengths[X] * rayinfo->slab_den[X]); } if (dmin > dmax) return; } else { if ((rayinfo->slab_num[X] < BBox->Lower_Left[X]) || (rayinfo->slab_num[X] > BBox->Lengths[X] + BBox->Lower_Left[X])) { return; } dmin = -BOUND_HUGE; dmax = BOUND_HUGE; } if (rayinfo->nonzero[Y]) { if (rayinfo->positive[Y]) { tmin = (BBox->Lower_Left[Y] - rayinfo->slab_num[Y]) * rayinfo->slab_den[Y]; tmax = tmin + (BBox->Lengths[Y] * rayinfo->slab_den[Y]); } else { tmax = (BBox->Lower_Left[Y] - rayinfo->slab_num[Y]) * rayinfo->slab_den[Y]; tmin = tmax + (BBox->Lengths[Y] * rayinfo->slab_den[Y]); } /* * Unwrap the logic - do the dmin and dmax checks only when tmin and * tmax actually affect anything, also try to escape ASAP. Better * yet, fold the logic below into the two branches above so as to * compute only what is needed. */ /* * You might even try tmax < EPSILON first (instead of second) for an * early quick out. */ if (tmax < dmax) { if (tmax < EPSILON) return; /* check bbox only if tmax changes dmax */ if (tmin > dmin) { if (tmin > tmax) return; /* do this last in case it's not needed! */ dmin = tmin; } else { if (dmin > tmax) return; } /* do this last in case it's not needed! */ dmax = tmax; } else { if (tmin > dmin) { if (tmin > dmax) return; /* do this last in case it's not needed! */ dmin = tmin; } /* else nothing needs to happen, since dmin and dmax did not change! */ } } else { if ((rayinfo->slab_num[Y] < BBox->Lower_Left[Y]) || (rayinfo->slab_num[Y] > BBox->Lengths[Y] + BBox->Lower_Left[Y])) { return; } } if (rayinfo->nonzero[Z]) { if (rayinfo->positive[Z]) { tmin = (BBox->Lower_Left[Z] - rayinfo->slab_num[Z]) * rayinfo->slab_den[Z]; tmax = tmin + (BBox->Lengths[Z] * rayinfo->slab_den[Z]); } else { tmax = (BBox->Lower_Left[Z] - rayinfo->slab_num[Z]) * rayinfo->slab_den[Z]; tmin = tmax + (BBox->Lengths[Z] * rayinfo->slab_den[Z]); } if (tmax < dmax) { if (tmax < EPSILON) return; /* check bbox only if tmax changes dmax */ if (tmin > dmin) { if (tmin > tmax) return; /* do this last in case it's not needed! */ dmin = tmin; } else { if (dmin > tmax) return; } } else { if (tmin > dmin) { if (tmin > dmax) return; /* do this last in case it's not needed! */ dmin = tmin; } /* else nothing needs to happen, since dmin and dmax did not change! */ } } else { if ((rayinfo->slab_num[Z] < BBox->Lower_Left[Z]) || (rayinfo->slab_num[Z] > BBox->Lengths[Z] + BBox->Lower_Left[Z])) { return; } } Increase_Counter(stats[nEnqueued]); } priority_queue_insert(Queue, dmin, Node); }
static int intersect_cone(RAY *Ray, CONE *Cone, CONE_INT *Intersection) { int i = 0; DBL a, b, c, z, t1, t2, len; DBL d; VECTOR P, D; Increase_Counter(stats[Ray_Cone_Tests]); /* Transform the ray into the cones space */ MInvTransPoint(P, Ray->Initial, Cone->Trans); MInvTransDirection(D, Ray->Direction, Cone->Trans); VLength(len, D); VInverseScaleEq(D, len); if (Test_Flag(Cone, CYLINDER_FLAG)) { /* Solve intersections with a cylinder */ a = D[X] * D[X] + D[Y] * D[Y]; if (a > EPSILON) { b = P[X] * D[X] + P[Y] * D[Y]; c = P[X] * P[X] + P[Y] * P[Y] - 1.0; d = b * b - a * c; if (d >= 0.0) { d = sqrt(d); t1 = (-b + d) / a; t2 = (-b - d) / a; z = P[Z] + t1 * D[Z]; if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0)) { Intersection[i].d = t1 / len; Intersection[i++].t = SIDE_HIT; } z = P[Z] + t2 * D[Z]; if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0)) { Intersection[i].d = t2 / len; Intersection[i++].t = SIDE_HIT; } } } } else { /* Solve intersections with a cone */ a = D[X] * D[X] + D[Y] * D[Y] - D[Z] * D[Z]; b = D[X] * P[X] + D[Y] * P[Y] - D[Z] * P[Z]; c = P[X] * P[X] + P[Y] * P[Y] - P[Z] * P[Z]; if (fabs(a) < EPSILON) { if (fabs(b) > EPSILON) { /* One intersection */ t1 = -0.5 * c / b; z = P[Z] + t1 * D[Z]; if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0)) { Intersection[i].d = t1 / len; Intersection[i++].t = SIDE_HIT; } } } else { /* Check hits against the side of the cone */ d = b * b - a * c; if (d >= 0.0) { d = sqrt(d); t1 = (-b - d) / a; t2 = (-b + d) / a; z = P[Z] + t1 * D[Z]; if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0)) { Intersection[i].d = t1 / len; Intersection[i++].t = SIDE_HIT; } z = P[Z] + t2 * D[Z]; if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0)) { Intersection[i].d = t2 / len; Intersection[i++].t = SIDE_HIT; } } } } if (Test_Flag(Cone, CLOSED_FLAG) && (fabs(D[Z]) > EPSILON)) { d = (1.0 - P[Z]) / D[Z]; a = (P[X] + d * D[X]); b = (P[Y] + d * D[Y]); if (((Sqr(a) + Sqr(b)) <= 1.0) && (d > Cone_Tolerance) && (d < Max_Distance)) { Intersection[i].d = d / len; Intersection[i++].t = CAP_HIT; } d = (Cone->dist - P[Z]) / D[Z]; a = (P[X] + d * D[X]); b = (P[Y] + d * D[Y]); if ((Sqr(a) + Sqr(b)) <= (Test_Flag(Cone, CYLINDER_FLAG) ? 1.0 : Sqr(Cone->dist)) && (d > Cone_Tolerance) && (d < Max_Distance)) { Intersection[i].d = d / len; Intersection[i++].t = BASE_HIT; } } if (i) { Increase_Counter(stats[Ray_Cone_Tests_Succeeded]); } return (i); }
int Solve_Polynomial(int n, DBL *c0, DBL *r, int sturm, DBL epsilon) { int roots, i; DBL *c; Increase_Counter(stats[Polynomials_Tested]); roots = 0; /* * Determine the "real" order of the polynomial, i.e. * eliminate small leading coefficients. */ i = 0; while ((fabs(c0[i]) < SMALL_ENOUGH) && (i < n)) { i++; } n -= i; c = &c0[i]; switch (n) { case 0: break; case 1: /* Solve linear polynomial. */ if (c[0] != 0.0) { r[roots++] = -c[1] / c[0]; } break; case 2: /* Solve quadratic polynomial. */ roots = solve_quadratic(c, r); break; case 3: /* Root elimination? */ if (epsilon > 0.0) { if ((c[2] != 0.0) && (fabs(c[3]/c[2]) < epsilon)) { Increase_Counter(stats[Roots_Eliminated]); roots = solve_quadratic(c, r); break; } } /* Solve cubic polynomial. */ if (sturm) { roots = polysolve(3, c, r); } else { roots = solve_cubic(c, r); } break; case 4: /* Root elimination? */ if (epsilon > 0.0) { if ((c[3] != 0.0) && (fabs(c[4]/c[3]) < epsilon)) { Increase_Counter(stats[Roots_Eliminated]); if (sturm) { roots = polysolve(3, c, r); } else { roots = solve_cubic(c, r); } break; } } /* Test for difficult coeffs. */ if (difficult_coeffs(4, c)) { sturm = true; } /* Solve quartic polynomial. */ if (sturm) { roots = polysolve(4, c, r); } else { roots = solve_quartic(c, r); } break; default: if (epsilon > 0.0) { if ((c[n-1] != 0.0) && (fabs(c[n]/c[n-1]) < epsilon)) { Increase_Counter(stats[Roots_Eliminated]); roots = polysolve(n-1, c, r); } } /* Solve n-th order polynomial. */ roots = polysolve(n, c, r); break; } return(roots); }
int All_Parametric_Intersections(OBJECT* Object, RAY* Ray, ISTACK* Depth_Stack) { PARAMETRIC * Par = (PARAMETRIC *)Object; PRECOMP_PAR_DATA * PData = ((PARAMETRIC *)Object)->PData; VECTOR P, D, IPoint; UV_VECT low_vect, hi_vect; RAY New_Ray; DBL XRayMin, XRayMax, YRayMin, YRayMax, ZRayMin, ZRayMax, TPotRes, TLen; DBL Depth1, Depth2, temp, Len, UResult, VResult, TResult = HUGE_VAL; DBL low, hi, len; int MaxPrecompX, MaxPrecompY, MaxPrecompZ; int split, i = 0, Side1, Side2; int parX, parY; int i_flg; Increase_Counter(stats[Ray_Par_Bound_Tests]); if(Par->container_shape) { if(Par->Trans != NULL) { MInvTransPoint(New_Ray.Initial, Ray->Initial, Par->Trans); MInvTransDirection(New_Ray.Direction, Ray->Direction, Par->Trans); VLength(len, New_Ray.Direction); VInverseScaleEq(New_Ray.Direction, len); i_flg = Intersect_Sphere(&New_Ray, Par->container.sphere.center, (Par->container.sphere.radius) * (Par->container.sphere.radius), &Depth1, &Depth2); Depth1 = Depth1 / len; Depth2 = Depth2 / len; } else { i_flg = Intersect_Sphere(Ray, Par->container.sphere.center, (Par->container.sphere.radius) * (Par->container.sphere.radius), &Depth1, &Depth2); } Decrease_Counter(stats[Ray_Sphere_Tests]); if(i_flg) Decrease_Counter(stats[Ray_Sphere_Tests_Succeeded]); } else { i_flg = Intersect_Box(Ray, Par->Trans, Par->container.box.corner1, Par->container.box.corner2, &Depth1, &Depth2, &Side1, &Side2); } if(!i_flg) return false; Increase_Counter(stats[Ray_Par_Bound_Tests_Succeeded]); Increase_Counter(stats[Ray_Parametric_Tests]); if (Par->Trans != NULL) { MInvTransPoint(P, Ray->Initial, Par->Trans); MInvTransDirection(D, Ray->Direction, Par->Trans); } else { P[X] = Ray->Initial[X]; P[Y] = Ray->Initial[Y]; P[Z] = Ray->Initial[Z]; D[X] = Ray->Direction[X]; D[Y] = Ray->Direction[Y]; D[Z] = Ray->Direction[Z]; } if (Depth1 == Depth2) Depth1 = 0; if ((Depth1 += 4 * Par->accuracy) > Depth2) return false; Intervals_Low[INDEX_U][0] = Par->umin; Intervals_Hi[INDEX_U][0] = Par->umax; Intervals_Low[INDEX_V][0] = Par->vmin; Intervals_Hi[INDEX_V][0] = Par->vmax; /* Fri 09-27-1996 0. */ SectorNum[0] = 1; MaxPrecompX = MaxPrecompY = MaxPrecompZ = 0; if (PData != NULL) { if (((PData->flags) & OK_X) != 0) MaxPrecompX = 1 << (PData->depth); if (((PData->flags) & OK_Y) != 0) MaxPrecompY = 1 << (PData->depth); if (((PData->flags) & OK_Z) != 0) MaxPrecompZ = 1 << (PData->depth); } /* 0 */ while (i >= 0) { low_vect[U] = Intervals_Low[INDEX_U][i]; hi_vect[U] = Intervals_Hi[INDEX_U][i]; Len = hi_vect[U] - low_vect[U]; split = INDEX_U; low_vect[V] = Intervals_Low[INDEX_V][i]; hi_vect[V] = Intervals_Hi[INDEX_V][i]; temp = hi_vect[V] - low_vect[V]; if (temp > Len) { Len = temp; split = INDEX_V; } parX = parY = 0; TLen = 0; /* X */ if (SectorNum[i] < MaxPrecompX) { low = PData->Low[0][SectorNum[i]]; hi = PData->Hi[0][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[0]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); /* fabs(D[X] *(T2-T1)) is not OK with new method */ if (close(D[0], 0)) { parX = 1; if ((hi < P[0]) || (low > P[0])) { i--; continue; } } else { XRayMin = (hi - P[0]) / D[0]; XRayMax = (low - P[0]) / D[0]; if (XRayMin > XRayMax) { temp = XRayMin; XRayMin = XRayMax; XRayMax = temp; } if ((XRayMin > Depth2) || (XRayMax < Depth1)) { i--; continue; } if ((TPotRes = XRayMin) > TResult) { i--; continue; } TLen = XRayMax - XRayMin; } /* Y */ if (SectorNum[i] < MaxPrecompY) { low = PData->Low[1][SectorNum[i]]; hi = PData->Hi[1][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[1]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); if (close(D[1], 0)) { parY = 1; if ((hi < P[1]) || (low > P[1])) { i--; continue; } } else { YRayMin = (hi - P[1]) / D[1]; YRayMax = (low - P[1]) / D[1]; if (YRayMin > YRayMax) { temp = YRayMin; YRayMin = YRayMax; YRayMax = temp; } if ((YRayMin > Depth2) || (YRayMax < Depth1)) { i--; continue; } if ((TPotRes = YRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((YRayMin > XRayMax) || (YRayMax < XRayMin)) { i--; continue; } } if ((temp = YRayMax - YRayMin) > TLen) TLen = temp; } /* Z */ if ((SectorNum[i] < MaxPrecompZ) && (0 < SectorNum[i])) { low = PData->Low[2][SectorNum[i]]; hi = PData->Hi[2][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[2]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); if (close(D[2], 0)) { if ((hi < P[2]) || (low > P[2])) { i--; continue; } } else { ZRayMin = (hi - P[2]) / D[2]; ZRayMax = (low - P[2]) / D[2]; if (ZRayMin > ZRayMax) { temp = ZRayMin; ZRayMin = ZRayMax; ZRayMax = temp; } if ((ZRayMin > Depth2) || (ZRayMax < Depth1)) { i--; continue; } if ((TPotRes = ZRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((ZRayMin > XRayMax) || (ZRayMax < XRayMin)) { i--; continue; } } if (parY == 0) { if ((ZRayMin > YRayMax) || (ZRayMax < YRayMin)) { i--; continue; } } if ((temp = ZRayMax - ZRayMin) > TLen) TLen = temp; } if (Len > TLen) Len = TLen; if (Len < Par->accuracy) { if ((TResult > TPotRes) && (TPotRes > Depth1)) { TResult = TPotRes; Par->last_u = UResult = low_vect[U]; Par->last_v = VResult = low_vect[V]; } i--; } else { /* 1 copy */ if ((SectorNum[i] *= 2) >= Max_intNumber) SectorNum[i] = Max_intNumber; SectorNum[i + 1] = SectorNum[i]; SectorNum[i]++; i++; Intervals_Low[INDEX_U][i] = low_vect[U]; Intervals_Hi[INDEX_U][i] = hi_vect[U]; Intervals_Low[INDEX_V][i] = low_vect[V]; Intervals_Hi[INDEX_V][i] = hi_vect[V]; /* 2 split */ temp = (Intervals_Hi[split][i] + Intervals_Low[split][i]) / 2.0; Intervals_Hi[split][i] = temp; Intervals_Low[split][i - 1] = temp; } } if (TResult < Depth2) { Increase_Counter(stats[Ray_Parametric_Tests_Succeeded]); VScale(IPoint, Ray->Direction, TResult); VAddEq(IPoint, Ray->Initial); if (Point_In_Clip(IPoint, Par->Clip)) { /* compute_param_normal( Par, UResult, VResult , &N); push_normal_entry( TResult ,IPoint, N, (OBJECT *) Object, Depth_Stack); */ // UV_VECT uv; // Make_UV_Vector(uv, UResult, VResult); // push_uv_entry(TResult, IPoint, uv, (OBJECT *)Object, Depth_Stack); push_entry(TResult, IPoint, (OBJECT *)Object, Depth_Stack); return true; } } return false; }
static int All_IsoSurface_Intersections(OBJECT* Object, RAY* Ray, ISTACK* Depth_Stack) { ISOSURFACE * Isosrf = (ISOSURFACE *)Object; int Side1 = 0, Side2 = 0, itrace = 0, i_flg = 0; DBL Depth1 = 0.0, Depth2 = 0.0, len = 0.0; RAY New_Ray; VECTOR IPoint; VECTOR P, D; DBL tmax = 0.0, tmin = 0.0, tmp = 0.0; int i = 0 ; /* count of intervals in stack - 1 */ int IFound = false; int begin = 0, end = 0; bool in_shadow_test = false; VECTOR VTmp; Increase_Counter(stats[Ray_IsoSurface_Bound_Tests]); in_shadow_test = ((Ray->Optimisiation_Flags & OPTIMISE_SHADOW_TEST) == OPTIMISE_SHADOW_TEST); if(Isosrf->container_shape) { if(Isosrf->Trans != NULL) { MInvTransPoint(New_Ray.Initial, Ray->Initial, Isosrf->Trans); MInvTransDirection(New_Ray.Direction, Ray->Direction, Isosrf->Trans); VLength(len, New_Ray.Direction); VInverseScaleEq(New_Ray.Direction, len); i_flg = Intersect_Sphere(&New_Ray, Isosrf->container.sphere.center, (Isosrf->container.sphere.radius) * (Isosrf->container.sphere.radius), &Depth1, &Depth2); Depth1 = Depth1 / len; Depth2 = Depth2 / len; } else { i_flg = Intersect_Sphere(Ray, Isosrf->container.sphere.center, (Isosrf->container.sphere.radius) * (Isosrf->container.sphere.radius), &Depth1, &Depth2); } Decrease_Counter(stats[Ray_Sphere_Tests]); if(i_flg) Decrease_Counter(stats[Ray_Sphere_Tests_Succeeded]); } else { i_flg = Intersect_Box(Ray, Isosrf->Trans, Isosrf->container.box.corner1, Isosrf->container.box.corner2, &Depth1, &Depth2, &Side1, &Side2); } if(Depth1 < 0.0) Depth1 = 0.0; if(i_flg) /* IsoSurface_Bound_Tests */ { Increase_Counter(stats[Ray_IsoSurface_Bound_Tests_Succeeded]); if(Isosrf->Trans != NULL) { MInvTransPoint(P, Ray->Initial, Isosrf->Trans); MInvTransDirection(D, Ray->Direction, Isosrf->Trans); } else { Assign_Vector(P, Ray->Initial); Assign_Vector(D, Ray->Direction); } Isosrf->Inv3 = 1; if(Isosrf->closed != false) { VEvaluateRay(VTmp, P, Depth1, D); tmp = Vector_IsoSurface_Function(Isosrf, VTmp); if(Depth1 > Isosrf->accuracy) { if(tmp < 0.0) /* The ray hits the bounding shape */ { VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction); if(Point_In_Clip(IPoint, Object->Clip)) { push_entry_i1(Depth1, IPoint, Object, Side1, Depth_Stack); IFound = true; itrace++; Isosrf->Inv3 *= -1; } } } else { if(tmp < (Isosrf->max_gradient * Isosrf->accuracy * 4.0)) { Depth1 = Isosrf->accuracy * 5.0; VEvaluateRay(VTmp, P, Depth1, D); if(Vector_IsoSurface_Function(Isosrf, VTmp) < 0) Isosrf->Inv3 = -1; /* Change the sign of the function (IPoint is in the bounding shpae.)*/ } VEvaluateRay(VTmp, P, Depth2, D); if(Vector_IsoSurface_Function(Isosrf, VTmp) < 0.0) { VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction); if(Point_In_Clip(IPoint, Object->Clip)) { push_entry_i1(Depth2, IPoint, Object, Side2, Depth_Stack); IFound = true; } } } } /* METHOD 2 by R. Suzuki */ tmax = Depth2 = min(Depth2, BOUND_HUGE); tmin = Depth1 = min(Depth2, Depth1); if((tmax - tmin) < Isosrf->accuracy) return (false); Increase_Counter(stats[Ray_IsoSurface_Tests]); if((Depth1 < Isosrf->accuracy) && (Isosrf->Inv3 == 1)) { /* IPoint is on the isosurface */ VEvaluateRay(VTmp, P, tmin, D); if(fabs(Vector_IsoSurface_Function(Isosrf, VTmp)) < (Isosrf->max_gradient * Isosrf->accuracy * 4.0)) { tmin = Isosrf->accuracy * 5.0; VEvaluateRay(VTmp, P, tmin, D); if(Vector_IsoSurface_Function(Isosrf, VTmp) < 0) Isosrf->Inv3 = -1; /* change the sign and go into the isosurface */ } } for (; itrace < Isosrf->max_trace; itrace++) { if(IsoSurface_Function_Find_Root(Isosrf, P, D, &tmin, &tmax, in_shadow_test) == false) break; else { VEvaluateRay(IPoint, Ray->Initial, tmin, Ray->Direction); if(Point_In_Clip(IPoint, Object->Clip)) { push_entry_i1(tmin, IPoint, Object, 0 /*Side1*/, Depth_Stack); IFound = true; } } tmin += Isosrf->accuracy * 5.0; if((tmax - tmin) < Isosrf->accuracy) break; Isosrf->Inv3 *= -1; } if(IFound) Increase_Counter(stats[Ray_IsoSurface_Tests_Succeeded]); } return (IFound); }
int IsoSurface_Function_Find_Root(ISOSURFACE* ISOSRF, VECTOR P, VECTOR D, DBL* Depth1, DBL* Depth2, bool in_shadow_test) { DBL dt, t21, l_b, l_e, oldmg; ISO_Pair EP1, EP2; VECTOR VTmp; Increase_Counter(stats[Ray_IsoSurface_Find_Root]); VLength(ISOSRF->Vlength, D); if(ISOSRF->cache) { Increase_Counter(stats[Ray_IsoSurface_Cache]); VEvaluateRay(VTmp, P, *Depth1, D); VSubEq(VTmp, ISOSRF->P); VLength(l_b, VTmp); VEvaluateRay(VTmp, P, *Depth2, D); VSubEq(VTmp, ISOSRF->D); VLength(l_e, VTmp); if((ISOSRF->fmax - ISOSRF->max_gradient * max(l_b, l_e)) > 0.0) { Increase_Counter(stats[Ray_IsoSurface_Cache_Succeeded]); return false; } } Assign_Vector(ISOSRF->P, P); Assign_Vector(ISOSRF->D, D); ISOSRF->cache = false; EP1.t = *Depth1; EP1.f = Float_IsoSurface_Function(ISOSRF, Depth1); ISOSRF->fmax = EP1.f; if((ISOSRF->closed == false) && (EP1.f < 0.0)) { ISOSRF->Inv3 *= -1; EP1.f *= -1; } EP2.t = *Depth2; EP2.f = Float_IsoSurface_Function(ISOSRF, Depth2); ISOSRF->fmax = min(EP2.f, ISOSRF->fmax); oldmg = ISOSRF->max_gradient; t21 = (*Depth2 - *Depth1); if((ISOSRF->eval == true) && (ISOSRF->max_gradient > ISOSRF->eval_param[0])) ISOSRF->max_gradient *= ISOSRF->eval_param[2]; dt = ISOSRF->max_gradient * ISOSRF->Vlength * t21; if(IsoSurface_Function_Find_Root_R(ISOSRF, &EP1, &EP2, dt, t21, 1.0 / (ISOSRF->Vlength * t21), in_shadow_test)) { if(ISOSRF->eval == true) { DBL curvar = fabs(ISOSRF->max_gradient - oldmg); if(curvar > ISOSRF->mginfo->eval_var) ISOSRF->mginfo->eval_var = curvar; ISOSRF->mginfo->eval_cnt++; ISOSRF->mginfo->eval_gradient_sum += ISOSRF->max_gradient; if(ISOSRF->max_gradient > ISOSRF->mginfo->eval_max) ISOSRF->mginfo->eval_max = ISOSRF->max_gradient; } *Depth1 = ISOSRF->tl; return true; } else if(!in_shadow_test) { ISOSRF->cache = true; VEvaluateRay(ISOSRF->P, P, EP1.t, D); VEvaluateRay(ISOSRF->D, P, EP2.t, D); return false; } return false; }
DBL POVFPU_RunDefault(FUNCTION fn) { StackFrame *pstack = POVFPU_Current_Context->pstackbase; DBL *dblstack = POVFPU_Current_Context->dblstackbase; unsigned int maxdblstacksize = POVFPU_Current_Context->maxdblstacksize; DBL r0, r1, r2, r3, r4, r5, r6, r7; Instruction *program = NULL; unsigned int k = 0; unsigned int pc = 0; unsigned int ccr = 0; unsigned int sp = 0; unsigned int psp = 0; #if (SUPPORT_INTEGER_INSTRUCTIONS == 1) POV_LONG iA, iB, itemp; #endif #if (DEBUG_DEFAULTCPU == 1) COUNTER instr; Long_To_Counter(POVFPU_Functions[fn].fn.program_size, instr); Add_Counter(stats[Ray_Function_VM_Instruction_Est], stats[Ray_Function_VM_Instruction_Est], instr); #endif Increase_Counter(stats[Ray_Function_VM_Calls]); program = POVFPU_Functions[fn].fn.program; while(true) { k = GET_K(program[pc]); switch(GET_OP(program[pc])) { OP_MATH_AOP(0,+); // add Rs, Rd OP_MATH_AOP(1,-); // sub Rs, Rd OP_MATH_AOP(2,*); // mul Rs, Rd OP_MATH_AOP(3,/); // div Rs, Rd OP_MOD_A(4); // mod Rs, Rd OP_ASSIGN_ABOP(5,0,r0); // move R0, Rd OP_ASSIGN_ABOP(5,1,r1); // move R1, Rd OP_ASSIGN_ABOP(5,2,r2); // move R2, Rd OP_ASSIGN_ABOP(5,3,r3); // move R3, Rd OP_ASSIGN_ABOP(5,4,r4); // move R4, Rd OP_ASSIGN_ABOP(5,5,r5); // move R5, Rd OP_ASSIGN_ABOP(5,6,r6); // move R6, Rd OP_ASSIGN_ABOP(5,7,r7); // move R7, Rd OP_CMP_ABC(6,0,r0); // cmp R0, Rd OP_CMP_ABC(6,1,r1); // cmp R1, Rd OP_CMP_ABC(6,2,r2); // cmp R2, Rd OP_CMP_ABC(6,3,r3); // cmp R3, Rd OP_CMP_ABC(6,4,r4); // cmp R4, Rd OP_CMP_ABC(6,5,r5); // cmp R5, Rd OP_CMP_ABC(6,6,r6); // cmp R6, Rd OP_CMP_ABC(6,7,r7); // cmp R7, Rd OP_ASSIGN_ABOP(7,0,-r0); // neg R0, Rd OP_ASSIGN_ABOP(7,1,-r1); // neg R1, Rd OP_ASSIGN_ABOP(7,2,-r2); // neg R2, Rd OP_ASSIGN_ABOP(7,3,-r3); // neg R3, Rd OP_ASSIGN_ABOP(7,4,-r4); // neg R4, Rd OP_ASSIGN_ABOP(7,5,-r5); // neg R5, Rd OP_ASSIGN_ABOP(7,6,-r6); // neg R6, Rd OP_ASSIGN_ABOP(7,7,-r7); // neg R7, Rd OP_ABS_A(8); // abs Rs, Rd OP_MATH_ABCOP(9,0,POVFPU_Consts[k],+); // addi k, Rd OP_MATH_ABCOP(9,1,POVFPU_Consts[k],-); // subi k, Rd OP_MATH_ABCOP(9,2,POVFPU_Consts[k],*); // muli k, Rd OP_MATH_ABCOP(9,3,POVFPU_Consts[k],/); // divi k, Rd OP_MOD_ABC(9,4,POVFPU_Consts[k]); // modi k, Rd OP_ASSIGN_ABOP(9,5,POVFPU_Consts[k]); // loadi k, Rd OP_CMP_ABC(9,6,POVFPU_Consts[k]); // cmpi k, Rs OP_ASSIGN_ABOP(10,0,ccr == 1); // seq Rd OP_ASSIGN_ABOP(10,1,ccr != 1); // sne Rd OP_ASSIGN_ABOP(10,2,ccr == 2); // slt Rd OP_ASSIGN_ABOP(10,3,ccr >= 1); // sle Rd OP_ASSIGN_ABOP(10,4,ccr == 0); // sgt Rd OP_ASSIGN_ABOP(10,5,ccr <= 1); // sge Rd OP_MATH_ABCOP(10,6,0.0,==); // teq Rd OP_MATH_ABCOP(10,7,0.0,!=); // tne Rd OP_ASSIGN_ABOP(11,0,POVFPU_Globals[k]); // load 0(k), Rd OP_ASSIGN_ABOP(11,1,dblstack[sp+k]); // load SP(k), Rd OP_REVASSIGN_ABOP(12,0,POVFPU_Globals[k]); // store Rs, 0(k) OP_REVASSIGN_ABOP(12,1,dblstack[sp+k]); // store Rs, SP(k) OP_SPECIAL(13,0,0,if(ccr == 1) pc = k - 1); // beq k OP_SPECIAL(13,1,0,if(ccr != 1) pc = k - 1); // bne k OP_SPECIAL(13,2,0,if(ccr == 2) pc = k - 1); // blt k OP_SPECIAL(13,3,0,if(ccr >= 1) pc = k - 1); // ble k OP_SPECIAL(13,4,0,if(ccr == 0) pc = k - 1); // bgt k OP_SPECIAL(13,5,0,if(ccr <= 1) pc = k - 1); // bge k OP_XCC_ABOP(14,0,==); // xeq Rd OP_XCC_ABOP(14,1,!=); // xne Rd OP_XCC_ABOP(14,2,<); // xlt Rd OP_XCC_ABOP(14,3,<=); // xle Rd OP_XCC_ABOP(14,4,>); // xgt Rd OP_XCC_ABOP(14,5,>=); // xge Rd OP_SPECIAL(14,6,0,if((r0 == 0.0) && (r0 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R0 OP_SPECIAL(14,6,1,if((r0 == 0.0) && (r1 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R1 OP_SPECIAL(14,6,2,if((r0 == 0.0) && (r2 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R2 OP_SPECIAL(14,6,3,if((r0 == 0.0) && (r3 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R3 OP_SPECIAL(14,6,4,if((r0 == 0.0) && (r4 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R4 OP_SPECIAL(14,6,5,if((r0 == 0.0) && (r5 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R5 OP_SPECIAL(14,6,6,if((r0 == 0.0) && (r6 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R6 OP_SPECIAL(14,6,7,if((r0 == 0.0) && (r7 == 0.0)) POVFPU_Exception(fn)); // xdz R0, R7 OP_SPECIAL_CASE(15,0,0) // jsr k pstack[psp].pc = pc; pstack[psp].fn = fn; psp++; if(psp >= MAX_CALL_STACK_SIZE) POVFPU_Exception(fn, "Maximum function evaluation recursion level reached."); pc = k; continue; // prevent increment of pc OP_SPECIAL_CASE(15,0,1) // jmp k pc = k; continue; // prevent increment of pc OP_SPECIAL_CASE(15,0,2) // rts if(psp == 0) return r0; psp--; pc = pstack[psp].pc; // old position, will be incremented fn = pstack[psp].fn; program = POVFPU_Functions[fn].fn.program; break; OP_SPECIAL_CASE(15,0,3) // call k pstack[psp].pc = pc; pstack[psp].fn = fn; psp++; if(psp >= MAX_CALL_STACK_SIZE) POVFPU_Exception(fn, "Maximum function evaluation recursion level reached."); fn = k; program = POVFPU_Functions[fn].fn.program; pc = 0; continue; // prevent increment of pc OP_SPECIAL_CASE(15,0,4) // sys1 k r0 = POVFPU_Sys1Table[k](r0); break; OP_SPECIAL_CASE(15,0,5) // sys2 k r0 = POVFPU_Sys2Table[k](r0,r1); break; OP_SPECIAL_CASE(15,0,6) // trap k r0 = POVFPU_TrapTable[k].fn(&dblstack[sp], fn); maxdblstacksize = POVFPU_Current_Context->maxdblstacksize; dblstack = POVFPU_Current_Context->dblstackbase; break; OP_SPECIAL_CASE(15,0,7) // traps k POVFPU_TrapSTable[k].fn(&dblstack[sp], fn, sp); maxdblstacksize = POVFPU_Current_Context->maxdblstacksize; dblstack = POVFPU_Current_Context->dblstackbase; break; OP_SPECIAL_CASE(15,1,0) // grow k if((unsigned int)((unsigned int)sp + (unsigned int)k) >= (unsigned int)MAX_K) { POVFPU_Exception(fn, "Stack full. Possible infinite recursive function call."); } else if(sp + k >= maxdblstacksize) { maxdblstacksize = POVFPU_Current_Context->maxdblstacksize = POVFPU_Current_Context->maxdblstacksize + max(k + 1, (unsigned int)256); dblstack = POVFPU_Current_Context->dblstackbase = (DBL *)POV_REALLOC(dblstack, sizeof(DBL) * maxdblstacksize, "fn: stack"); } break; OP_SPECIAL_CASE(15,1,1) // push k if(sp + k >= maxdblstacksize) POVFPU_Exception(fn, "Function evaluation stack overflow."); sp += k; break; OP_SPECIAL_CASE(15,1,2) // pop k if(k > sp) POVFPU_Exception(fn, "Function evaluation stack underflow."); sp -= k; break; #if (SUPPORT_INTEGER_INSTRUCTIONS == 1) OP_SPECIAL_CASE(15,1,3) // iconv iA = POV_LONG(r0); break; OP_SPECIAL_CASE(15,1,4) // fconv r0 = DBL(iA); break; OP_SPECIAL_CASE(15,1,5) // reserved POVFPU_Exception(fn, "Internal error - reserved function VM opcode found!"); break; OP_INT_MATH_ABOP(15,32,+); // add s, d OP_INT_MATH_ABOP(15,33,-); // sub s, d OP_INT_MATH_ABOP(15,34,*); // mul s, d OP_INT_SPECIAL(15,35,0,iA = iA / iB); // div B, A OP_INT_SPECIAL(15,35,1,iB = iB / iA); // div A, B OP_INT_SPECIAL(15,35,2,iA = iA % iB); // mod B, A OP_INT_SPECIAL(15,35,3,iB = iB % iA); // mod A, B OP_INT_SPECIAL(15,36,0,ccr = (((iB > iA) & 1) << 1) | ((iB == iA) & 1)); // cmp B, A OP_INT_SPECIAL(15,36,1,ccr = (((iA > iB) & 1) << 1) | ((iA == iB) & 1)); // cmp A, B OP_INT_SPECIAL(15,36,2,itemp = iA; iA = iB; iB = itemp); // exg A, B OP_INT_SPECIAL(15,36,3,iA = iB = 0); // clr A, B OP_INT_SPECIAL(15,37,0,iA = 0); // clr A OP_INT_SPECIAL(15,37,1,iB = 0); // clr B OP_INT_SPECIAL(15,37,2,iA = iB); // move B, A OP_INT_SPECIAL(15,37,3,iB = iA); // move A, B OP_INT_SPECIAL(15,38,0,iA = -iA); // neg A OP_INT_SPECIAL(15,38,1,iB = -iB); // neg B OP_INT_SPECIAL(15,38,2,iA = abs(iA)); // abs A OP_INT_SPECIAL(15,38,3,iB = abs(iB)); // abs B OP_INT_SPECIAL(15,39,0,iA = iA + k); // addi k, A OP_INT_SPECIAL(15,39,1,iB = iB + k); // addi k, B OP_INT_SPECIAL(15,39,2,iA = iA - k); // subi k, A OP_INT_SPECIAL(15,39,3,iB = iB - k); // subi k, B OP_INT_MATH_SHIFT_ABOP(15,40,<<,POV_LONG); // asl s, d OP_INT_MATH_SHIFT_ABOP(15,41,>>,POV_LONG); // asr s, d OP_INT_MATH_SHIFT_ABOP(15,42,<<,POV_ULONG); // lsl s, d OP_INT_MATH_SHIFT_ABOP(15,43,>>,POV_ULONG); // lsr s, d OP_INT_MATH_ABOP(15,44,&); // and s, d OP_INT_MATH_ABOP(15,45,|); // or s, d OP_INT_MATH_ABOP(15,46,^); // xor s, d OP_INT_SPECIAL(15,47,0,iA = !iA); // not A, A OP_INT_SPECIAL(15,47,1,iA = !iB); // not B, A OP_INT_SPECIAL(15,47,2,iB = !iA); // not A, B OP_INT_SPECIAL(15,47,3,iB = !iB); // not B, B OP_INT_SPECIAL(15,48,0,iA = k); // loadi A OP_INT_SPECIAL(15,48,1,iB = k); // loadi B OP_INT_SPECIAL(15,48,2,iA = (iA << 16) | k);// ldhi A OP_INT_SPECIAL(15,48,3,iB = (iB << 16) | k);// ldhi B OP_INT_SPECIAL(15,49,0,iA = max(POV_LONG(k), iA)); // max k, A OP_INT_SPECIAL(15,49,1,iB = max(POV_LONG(k), iB)); // max k, B OP_INT_SPECIAL(15,49,2,iA = min(POV_LONG(k), iA)); // min k, A OP_INT_SPECIAL(15,49,3,iB = min(POV_LONG(k), iB)); // min k, B OP_INT_SPECIAL(15,50,0,iA = (POV_LONG(iA) << k)); // asl k, A OP_INT_SPECIAL(15,50,1,iB = (POV_LONG(iB) >> k)); // asr k, B OP_INT_SPECIAL(15,50,2,iA = (POV_ULONG(iA) << k)); // lsl k, A OP_INT_SPECIAL(15,50,3,iB = (POV_ULONG(iB) >> k)); // lsr k, B #endif default: // nop break; } pc++; } #if (DEBUG_DEFAULTCPU == 1) printf("Registers\n"); printf("=========\n"); printf("PC = %d\n", (int)pc); printf("CCR = %x\n", (int)ccr); printf("R0 = %8f R4 = %8f\n", (float)r0, (float)r4); printf("R1 = %8f R5 = %8f\n", (float)r1, (float)r5); printf("R2 = %8f R6 = %8f\n", (float)r2, (float)r6); printf("R3 = %8f R7 = %8f\n", (float)r3, (float)r7); #endif }
static int Intersect_Triangle(RAY *Ray, TRIANGLE *Triangle, DBL *Depth) { DBL NormalDotOrigin, NormalDotDirection; DBL s, t; Increase_Counter(stats[Ray_Triangle_Tests]); if (Test_Flag(Triangle, DEGENERATE_FLAG)) { return(false); } VDot(NormalDotDirection, Triangle->Normal_Vector, Ray->Direction); if (fabs(NormalDotDirection) < EPSILON) { return(false); } VDot(NormalDotOrigin, Triangle->Normal_Vector, Ray->Initial); *Depth = -(Triangle->Distance + NormalDotOrigin) / NormalDotDirection; if ((*Depth < DEPTH_TOLERANCE) || (*Depth > Max_Distance)) { return(false); } switch (Triangle->Dominant_Axis) { case X: s = Ray->Initial[Y] + *Depth * Ray->Direction[Y]; t = Ray->Initial[Z] + *Depth * Ray->Direction[Z]; if ((Triangle->P2[Y] - s) * (Triangle->P2[Z] - Triangle->P1[Z]) < (Triangle->P2[Z] - t) * (Triangle->P2[Y] - Triangle->P1[Y])) { return(false); } if ((Triangle->P3[Y] - s) * (Triangle->P3[Z] - Triangle->P2[Z]) < (Triangle->P3[Z] - t) * (Triangle->P3[Y] - Triangle->P2[Y])) { return(false); } if ((Triangle->P1[Y] - s) * (Triangle->P1[Z] - Triangle->P3[Z]) < (Triangle->P1[Z] - t) * (Triangle->P1[Y] - Triangle->P3[Y])) { return(false); } Increase_Counter(stats[Ray_Triangle_Tests_Succeeded]); return(true); case Y: s = Ray->Initial[X] + *Depth * Ray->Direction[X]; t = Ray->Initial[Z] + *Depth * Ray->Direction[Z]; if ((Triangle->P2[X] - s) * (Triangle->P2[Z] - Triangle->P1[Z]) < (Triangle->P2[Z] - t) * (Triangle->P2[X] - Triangle->P1[X])) { return(false); } if ((Triangle->P3[X] - s) * (Triangle->P3[Z] - Triangle->P2[Z]) < (Triangle->P3[Z] - t) * (Triangle->P3[X] - Triangle->P2[X])) { return(false); } if ((Triangle->P1[X] - s) * (Triangle->P1[Z] - Triangle->P3[Z]) < (Triangle->P1[Z] - t) * (Triangle->P1[X] - Triangle->P3[X])) { return(false); } Increase_Counter(stats[Ray_Triangle_Tests_Succeeded]); return(true); case Z: s = Ray->Initial[X] + *Depth * Ray->Direction[X]; t = Ray->Initial[Y] + *Depth * Ray->Direction[Y]; if ((Triangle->P2[X] - s) * (Triangle->P2[Y] - Triangle->P1[Y]) < (Triangle->P2[Y] - t) * (Triangle->P2[X] - Triangle->P1[X])) { return(false); } if ((Triangle->P3[X] - s) * (Triangle->P3[Y] - Triangle->P2[Y]) < (Triangle->P3[Y] - t) * (Triangle->P3[X] - Triangle->P2[X])) { return(false); } if ((Triangle->P1[X] - s) * (Triangle->P1[Y] - Triangle->P3[Y]) < (Triangle->P1[Y] - t) * (Triangle->P1[X] - Triangle->P3[X])) { return(false); } Increase_Counter(stats[Ray_Triangle_Tests_Succeeded]); return(true); } return(false); }