int BicubicPatch::bezier_tree_walker(const BasicRay &ray, const BEZIER_NODE *Node, IStack& Depth_Stack, TraceThreadData *Thread) { int i, cnt = 0; DBL Depth, u, v; DBL uu[3], vv[3]; Vector3d N, P; TripleVector3d V1; Vector2d UV; Vector2d uv_point, tpoint; const BEZIER_CHILDREN *Children; const BEZIER_VERTICES *Vertices; /* * Make sure the ray passes through a sphere bounding * the control points of the patch. */ if (!spherical_bounds_check(ray, Node->Center, Node->Radius_Squared)) { return (0); } /* * If this is an interior node then continue the descent, * else do a check against the vertices. */ if (Node->Node_Type == BEZIER_INTERIOR_NODE) { Children = reinterpret_cast<const BEZIER_CHILDREN *>(Node->Data_Ptr); for (i = 0; i < Node->Count; i++) { cnt += bezier_tree_walker(ray, Children->Children[i], Depth_Stack, Thread); } } else if (Node->Node_Type == BEZIER_LEAF_NODE) { Vertices = reinterpret_cast<const BEZIER_VERTICES *>(Node->Data_Ptr); V1[0] = Vertices->Vertices[0]; V1[1] = Vertices->Vertices[1]; V1[2] = Vertices->Vertices[2]; uu[0] = Vertices->uvbnds[0]; uu[1] = Vertices->uvbnds[0]; uu[2] = Vertices->uvbnds[1]; vv[0] = Vertices->uvbnds[2]; vv[1] = Vertices->uvbnds[3]; vv[2] = Vertices->uvbnds[3]; /* * Triangulate this subpatch, then check for * intersections in the triangles. */ if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v)) { if (Clip.empty() || Point_In_Clip(P, Clip, Thread)) { /* transform current point from uv space to texture space */ uv_point[0] = v; uv_point[1] = u; Compute_Texture_UV(uv_point, ST, tpoint); UV[U] = tpoint[0]; UV[V] = tpoint[1]; Depth_Stack->push(Intersection(Depth, P, N, UV, this)); cnt++; } } V1[1] = V1[2]; V1[2] = Vertices->Vertices[3]; uu[1] = uu[2]; uu[2] = Vertices->uvbnds[1]; vv[1] = vv[2]; vv[2] = Vertices->uvbnds[2]; if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v)) { if (Clip.empty() || Point_In_Clip(P, Clip, Thread)) { /* transform current point from object space to texture space */ uv_point[0] = v; uv_point[1] = u; Compute_Texture_UV(uv_point, ST, tpoint); UV[U] = tpoint[0]; UV[V] = tpoint[1]; Depth_Stack->push(Intersection(Depth, P, N, UV, this)); cnt++; } } } else { throw POV_EXCEPTION_STRING("Bad Node type in bezier_tree_walker()."); } return (cnt); }
static int bezier_tree_walker(RAY *Ray, BICUBIC_PATCH *Shape, BEZIER_NODE *Node, ISTACK *Depth_Stack) { int i, cnt = 0; DBL Depth, u, v; DBL uu[3], vv[3]; VECTOR N, P; VECTOR V1[3]; UV_VECT UV; DBL uv_point[2], tpoint[2]; BEZIER_CHILDREN *Children; BEZIER_VERTICES *Vertices; /* * Make sure the ray passes through a sphere bounding * the control points of the patch. */ if (!spherical_bounds_check(Ray, Node->Center, Node->Radius_Squared)) { return (0); } /* * If this is an interior node then continue the descent, * else do a check against the vertices. */ if (Node->Node_Type == BEZIER_INTERIOR_NODE) { Children = (BEZIER_CHILDREN *)Node->Data_Ptr; for (i = 0; i < Node->Count; i++) { cnt += bezier_tree_walker(Ray, Shape, Children->Children[i], Depth_Stack); } } else if (Node->Node_Type == BEZIER_LEAF_NODE) { Vertices = (BEZIER_VERTICES *)Node->Data_Ptr; Assign_Vector(V1[0], Vertices->Vertices[0]); Assign_Vector(V1[1], Vertices->Vertices[1]); Assign_Vector(V1[2], Vertices->Vertices[2]); uu[0] = Vertices->uvbnds[0]; uu[1] = Vertices->uvbnds[0]; uu[2] = Vertices->uvbnds[1]; vv[0] = Vertices->uvbnds[2]; vv[1] = Vertices->uvbnds[3]; vv[2] = Vertices->uvbnds[3]; /* * Triangulate this subpatch, then check for * intersections in the triangles. */ if (intersect_subpatch(Shape, Ray, V1, uu, vv, &Depth, P, N, &u, &v)) { /* transform current point from uv space to texture space */ uv_point[0] = v; uv_point[1] = u; Compute_Texture_UV(uv_point, Shape->ST, tpoint); UV[U] = tpoint[0]; UV[V] = tpoint[1]; push_normal_uv_entry(Depth, P, N, UV, (OBJECT *)Shape, Depth_Stack); cnt++; } Assign_Vector(V1[1], V1[2]); Assign_Vector(V1[2], Vertices->Vertices[3]); uu[1] = uu[2]; uu[2] = Vertices->uvbnds[1]; vv[1] = vv[2]; vv[2] = Vertices->uvbnds[2]; if (intersect_subpatch(Shape, Ray, V1, uu, vv, &Depth, P, N, &u, &v)) { /* transform current point from object space to texture space */ uv_point[0] = v; uv_point[1] = u; Compute_Texture_UV(uv_point, Shape->ST, tpoint); UV[U] = tpoint[0]; UV[V] = tpoint[1]; push_normal_uv_entry(Depth, P, N, UV, (OBJECT *)Shape, Depth_Stack); cnt++; } } else { Error("Bad Node type in bezier_tree_walker()."); } return (cnt); }
int BicubicPatch::bezier_subdivider(const BasicRay &ray, const ControlPoints *Patch, DBL u0, DBL u1, DBL v0, DBL v1, int recursion_depth, IStack& Depth_Stack, TraceThreadData *Thread) { int cnt = 0; DBL ut, vt, radiusSqr; ControlPoints Lower_Left, Lower_Right; ControlPoints Upper_Left, Upper_Right; Vector3d center; /* * Make sure the ray passes through a sphere bounding * the control points of the patch. */ bezier_bounding_sphere(Patch, center, &radiusSqr); if (!spherical_bounds_check(ray, center, radiusSqr)) { return (0); } /* * If the patch is close to being flat, then just * perform a ray-plane intersection test. */ if (flat_enough(Patch)) return bezier_subpatch_intersect(ray, Patch, u0, u1, v0, v1, Depth_Stack, Thread); if (recursion_depth >= U_Steps) { if (recursion_depth >= V_Steps) { return bezier_subpatch_intersect(ray, Patch, u0, u1, v0, v1, Depth_Stack, Thread); } else { bezier_split_up_down(Patch, &Lower_Left, &Upper_Left); vt = (v1 + v0) / 2.0; cnt += bezier_subdivider(ray, &Lower_Left, u0, u1, v0, vt, recursion_depth + 1, Depth_Stack, Thread); cnt += bezier_subdivider(ray, &Upper_Left, u0, u1, vt, v1, recursion_depth + 1, Depth_Stack, Thread); } } else { if (recursion_depth >= V_Steps) { bezier_split_left_right(Patch, &Lower_Left, &Lower_Right); ut = (u1 + u0) / 2.0; cnt += bezier_subdivider(ray, &Lower_Left, u0, ut, v0, v1, recursion_depth + 1, Depth_Stack, Thread); cnt += bezier_subdivider(ray, &Lower_Right, ut, u1, v0, v1, recursion_depth + 1, Depth_Stack, Thread); } else { ut = (u1 + u0) / 2.0; vt = (v1 + v0) / 2.0; bezier_split_left_right(Patch, &Lower_Left, &Lower_Right); bezier_split_up_down(&Lower_Left, &Lower_Left, &Upper_Left) ; bezier_split_up_down(&Lower_Right, &Lower_Right, &Upper_Right); cnt += bezier_subdivider(ray, &Lower_Left, u0, ut, v0, vt, recursion_depth + 1, Depth_Stack, Thread); cnt += bezier_subdivider(ray, &Upper_Left, u0, ut, vt, v1, recursion_depth + 1, Depth_Stack, Thread); cnt += bezier_subdivider(ray, &Lower_Right, ut, u1, v0, vt, recursion_depth + 1, Depth_Stack, Thread); cnt += bezier_subdivider(ray, &Upper_Right, ut, u1, vt, v1, recursion_depth + 1, Depth_Stack, Thread); } } return (cnt); }
static int bezier_subdivider(RAY *Ray, BICUBIC_PATCH *Object, VECTOR (*Patch)[4][4], DBL u0, DBL u1, DBL v0, DBL v1, int recursion_depth, ISTACK *Depth_Stack) { int cnt = 0; DBL ut, vt, radius; VECTOR Lower_Left[4][4], Lower_Right[4][4]; VECTOR Upper_Left[4][4], Upper_Right[4][4]; VECTOR center; /* * Make sure the ray passes through a sphere bounding * the control points of the patch. */ bezier_bounding_sphere(Patch, center, &radius); if (!spherical_bounds_check(Ray, center, radius)) { return (0); } /* * If the patch is close to being flat, then just * perform a ray-plane intersection test. */ if (flat_enough(Object, Patch)) { return bezier_subpatch_intersect(Ray, Object, Patch, u0, u1, v0, v1, Depth_Stack); } if (recursion_depth >= Object->U_Steps) { if (recursion_depth >= Object->V_Steps) { return bezier_subpatch_intersect(Ray, Object, Patch, u0, u1, v0, v1, Depth_Stack); } else { bezier_split_up_down(Patch, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Upper_Left); vt = (v1 + v0) / 2.0; cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Lower_Left, u0, u1, v0, vt, recursion_depth + 1, Depth_Stack); cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Upper_Left, u0, u1, vt, v1, recursion_depth + 1, Depth_Stack); } } else { if (recursion_depth >= Object->V_Steps) { bezier_split_left_right(Patch, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Lower_Right); ut = (u1 + u0) / 2.0; cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Lower_Left, u0, ut, v0, v1, recursion_depth + 1, Depth_Stack); cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Lower_Right, ut, u1, v0, v1, recursion_depth + 1, Depth_Stack); } else { ut = (u1 + u0) / 2.0; vt = (v1 + v0) / 2.0; bezier_split_left_right(Patch, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Lower_Right); bezier_split_up_down((VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Upper_Left) ; bezier_split_up_down((VECTOR(*)[4][4])Lower_Right, (VECTOR(*)[4][4])Lower_Right, (VECTOR(*)[4][4])Upper_Right); cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Lower_Left, u0, ut, v0, vt, recursion_depth + 1, Depth_Stack); cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Upper_Left, u0, ut, vt, v1, recursion_depth + 1, Depth_Stack); cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Lower_Right, ut, u1, v0, vt, recursion_depth + 1, Depth_Stack); cnt += bezier_subdivider(Ray, Object, (VECTOR(*)[4][4])Upper_Right, ut, u1, vt, v1, recursion_depth + 1, Depth_Stack); } } return (cnt); }