コード例 #1
0
ファイル: bezier.cpp プロジェクト: dickbalaska/povray
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);
}
コード例 #2
0
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);
}
コード例 #3
0
ファイル: bezier.cpp プロジェクト: dickbalaska/povray
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);
}
コード例 #4
0
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);
}