BEZIER_NODE *BicubicPatch::bezier_tree_builder(const ControlPoints *Patch, DBL u0, DBL u1, DBL v0, DBL v1, int depth, int& max_depth_reached) { ControlPoints Lower_Left, Lower_Right; ControlPoints Upper_Left, Upper_Right; BEZIER_CHILDREN *Children; BEZIER_VERTICES *Vertices; BEZIER_NODE *Node = create_new_bezier_node(); if (depth > max_depth_reached) { max_depth_reached = depth; } /* Build the bounding sphere for this subpatch. */ bezier_bounding_sphere(Patch, Node->Center, &(Node->Radius_Squared)); /* * If the patch is close to being flat, then just perform * a ray-plane intersection test. */ if (flat_enough(Patch)) { /* The patch is now flat enough to simply store the corners. */ Node->Node_Type = BEZIER_LEAF_NODE; Vertices = create_bezier_vertex_block(); Vertices->Vertices[0] = (*Patch)[0][0]; Vertices->Vertices[1] = (*Patch)[0][3]; Vertices->Vertices[2] = (*Patch)[3][3]; Vertices->Vertices[3] = (*Patch)[3][0]; Vertices->uvbnds[0] = u0; Vertices->uvbnds[1] = u1; Vertices->uvbnds[2] = v0; Vertices->uvbnds[3] = v1; Node->Data_Ptr = reinterpret_cast<void *>(Vertices); } else { if (depth >= U_Steps) { if (depth >= V_Steps) { /* We are at the max recursion depth. Just store corners. */ Node->Node_Type = BEZIER_LEAF_NODE; Vertices = create_bezier_vertex_block(); Vertices->Vertices[0] = (*Patch)[0][0]; Vertices->Vertices[1] = (*Patch)[0][3]; Vertices->Vertices[2] = (*Patch)[3][3]; Vertices->Vertices[3] = (*Patch)[3][0]; Vertices->uvbnds[0] = u0; Vertices->uvbnds[1] = u1; Vertices->uvbnds[2] = v0; Vertices->uvbnds[3] = v1; Node->Count = 0; Node->Data_Ptr = reinterpret_cast<void *>(Vertices); } else { bezier_split_up_down(Patch, &Lower_Left, &Upper_Left); Node->Node_Type = BEZIER_INTERIOR_NODE; Children = create_bezier_child_block(); Children->Children[0] = bezier_tree_builder(&Lower_Left, u0, u1, v0, (v0 + v1) / 2.0, depth + 1, max_depth_reached); Children->Children[1] = bezier_tree_builder(&Upper_Left, u0, u1, (v0 + v1) / 2.0, v1, depth + 1, max_depth_reached); Node->Count = 2; Node->Data_Ptr = reinterpret_cast<void *>(Children); } } else { if (depth >= V_Steps) { bezier_split_left_right(Patch, &Lower_Left, &Lower_Right); Node->Node_Type = BEZIER_INTERIOR_NODE; Children = create_bezier_child_block(); Children->Children[0] = bezier_tree_builder(&Lower_Left, u0, (u0 + u1) / 2.0, v0, v1, depth + 1, max_depth_reached); Children->Children[1] = bezier_tree_builder(&Lower_Right, (u0 + u1) / 2.0, u1, v0, v1, depth + 1, max_depth_reached); Node->Count = 2; Node->Data_Ptr = reinterpret_cast<void *>(Children); } else { 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); Node->Node_Type = BEZIER_INTERIOR_NODE; Children = create_bezier_child_block(); Children->Children[0] = bezier_tree_builder(&Lower_Left, u0, (u0 + u1) / 2.0, v0, (v0 + v1) / 2.0, depth + 1, max_depth_reached); Children->Children[1] = bezier_tree_builder(&Upper_Left, u0, (u0 + u1) / 2.0, (v0 + v1) / 2.0, v1, depth + 1, max_depth_reached); Children->Children[2] = bezier_tree_builder(&Lower_Right, (u0 + u1) / 2.0, u1, v0, (v0 + v1) / 2.0, depth + 1, max_depth_reached); Children->Children[3] = bezier_tree_builder(&Upper_Right, (u0 + u1) / 2.0, u1, (v0 + v1) / 2.0, v1, depth + 1, max_depth_reached); Node->Count = 4; Node->Data_Ptr = reinterpret_cast<void *>(Children); } } } return (Node); }
static BEZIER_NODE *bezier_tree_builder(BICUBIC_PATCH *Object, VECTOR (*Patch)[4][4], DBL u0, DBL u1, DBL v0, DBL v1, int depth, int& max_depth_reached) { VECTOR Lower_Left[4][4], Lower_Right[4][4]; VECTOR Upper_Left[4][4], Upper_Right[4][4]; BEZIER_CHILDREN *Children; BEZIER_VERTICES *Vertices; BEZIER_NODE *Node = create_new_bezier_node(); if (depth > max_depth_reached) { max_depth_reached = depth; } /* Build the bounding sphere for this subpatch. */ bezier_bounding_sphere(Patch, Node->Center, &(Node->Radius_Squared)); /* * If the patch is close to being flat, then just perform * a ray-plane intersection test. */ if (flat_enough(Object, Patch)) { /* The patch is now flat enough to simply store the corners. */ Node->Node_Type = BEZIER_LEAF_NODE; Vertices = create_bezier_vertex_block(); Assign_Vector(Vertices->Vertices[0], (*Patch)[0][0]); Assign_Vector(Vertices->Vertices[1], (*Patch)[0][3]); Assign_Vector(Vertices->Vertices[2], (*Patch)[3][3]); Assign_Vector(Vertices->Vertices[3], (*Patch)[3][0]); Vertices->uvbnds[0] = u0; Vertices->uvbnds[1] = u1; Vertices->uvbnds[2] = v0; Vertices->uvbnds[3] = v1; Node->Data_Ptr = (void *)Vertices; } else { if (depth >= Object->U_Steps) { if (depth >= Object->V_Steps) { /* We are at the max recursion depth. Just store corners. */ Node->Node_Type = BEZIER_LEAF_NODE; Vertices = create_bezier_vertex_block(); Assign_Vector(Vertices->Vertices[0], (*Patch)[0][0]); Assign_Vector(Vertices->Vertices[1], (*Patch)[0][3]); Assign_Vector(Vertices->Vertices[2], (*Patch)[3][3]); Assign_Vector(Vertices->Vertices[3], (*Patch)[3][0]); Vertices->uvbnds[0] = u0; Vertices->uvbnds[1] = u1; Vertices->uvbnds[2] = v0; Vertices->uvbnds[3] = v1; Node->Data_Ptr = (void *)Vertices; } else { bezier_split_up_down(Patch, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Upper_Left); Node->Node_Type = BEZIER_INTERIOR_NODE; Children = create_bezier_child_block(); Children->Children[0] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Lower_Left, u0, u1, v0, (v0 + v1) / 2.0, depth + 1, max_depth_reached); Children->Children[1] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Upper_Left, u0, u1, (v0 + v1) / 2.0, v1, depth + 1, max_depth_reached); Node->Count = 2; Node->Data_Ptr = (void *)Children; } } else { if (depth >= Object->V_Steps) { bezier_split_left_right(Patch, (VECTOR(*)[4][4])Lower_Left, (VECTOR(*)[4][4])Lower_Right); Node->Node_Type = BEZIER_INTERIOR_NODE; Children = create_bezier_child_block(); Children->Children[0] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Lower_Left, u0, (u0 + u1) / 2.0, v0, v1, depth + 1, max_depth_reached); Children->Children[1] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Lower_Right, (u0 + u1) / 2.0, u1, v0, v1, depth + 1, max_depth_reached); Node->Count = 2; Node->Data_Ptr = (void *)Children; } else { 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); Node->Node_Type = BEZIER_INTERIOR_NODE; Children = create_bezier_child_block(); Children->Children[0] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Lower_Left, u0, (u0 + u1) / 2.0, v0, (v0 + v1) / 2.0, depth + 1, max_depth_reached); Children->Children[1] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Upper_Left, u0, (u0 + u1) / 2.0, (v0 + v1) / 2.0, v1, depth + 1, max_depth_reached); Children->Children[2] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Lower_Right, (u0 + u1) / 2.0, u1, v0, (v0 + v1) / 2.0, depth + 1, max_depth_reached); Children->Children[3] = bezier_tree_builder(Object, (VECTOR(*)[4][4])Upper_Right, (u0 + u1) / 2.0, u1, (v0 + v1) / 2.0, v1, depth + 1, max_depth_reached); Node->Count = 4; Node->Data_Ptr = (void *)Children; } } } return (Node); }
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); }