Ejemplo n.º 1
0
  void KDTree::calcCostOfPlane( unsigned Nl, unsigned Nr, unsigned Nc, AABB& parentBox, float pos )
  {
    //Split this AABB into two boxes at this point in the axis.
    AABB l, r;

    //Split the box at this plane
    splitBoxAtPos(l, r, parentBox, pos);

    //Calculate the surface area of the left, right, and parent boxes
    float SAP, SAR, SAL;

    SAP = SurfaceArea(parentBox);
    SAL = SurfaceArea(l);
    SAR = SurfaceArea(r);

    //The current cost of this plane is now going to be the minimum of adding the coplanar 
    //triangles to each child box
    float lHeuristic, rHeuristic;

    lHeuristic = (SAL / SAP);
    rHeuristic = (SAR / SAP);

    float coLeft =  lHeuristic * (Nl + Nc) + rHeuristic * Nr;
    float coRight = lHeuristic * Nl + rHeuristic * (Nr + Nc);

    curCost = min( coLeft, coRight );
  }
Ejemplo n.º 2
0
// This function adds an object to an existing bounding volume hierarchy.
// It first constructs a bounding box for the new object, then finds the
// optimal place to insert it into the hierachy using branch-and-bound, and
// finally inserts it at the determined location, updating all the costs
// associated with the nodes in the hierarchy as a side-effect.
void abvh::Insert( const Object *obj, double relative_cost )
    {
    AABB box( GetBox( *obj ) );
    double bound = 0.0;
    node *n   = new node;
    n->bbox   = box;
    n->object = obj;
    n->SA     = SurfaceArea( box );
    n->EC     = 1.0;
    n->SEC_   = relative_cost;
    n->AIC    = relative_cost * n->SA;
    n->SAIC   = 0.0; // There are no child volumes yet.

    // If this is the first node being added to the hierarchy,
    // it becomes the root.
    if( root == NULL ) { root = n; return; }

    // Look for the optimal place to add the new node.
    // The branch-and-bound procedure will figure out where
    // to put it so as to cause the smallest increase in the
    // estimated cost of the tree.
    bound = Infinity;
    node *insert_here = NULL;
    Branch_and_Bound( root, n, insert_here, bound );
    // Now actually insert the node in the optimal place.
    insert_here->AddChild( n );
    }
Ejemplo n.º 3
0
// sample a ray from light
void Square::sample_l( const LightSample& ls , Ray& r , Vector& n , float* pdf ) const
{
	float u = 2 * ls.u - 1.0f;
	float v = 2 * ls.v - 1.0f;
	r.m_fMin = 0.0f;
	r.m_fMax = FLT_MAX;
	r.m_Ori = transform( Point( radius * u , 0.0f , radius * v ) );
	r.m_Dir = transform( UniformSampleHemisphere( sort_canonical() , sort_canonical() ) );
	n = transform.invMatrix.Transpose()( Vector( 0.0f , 1.0f , 0.0f ) );

	if( pdf ) *pdf = 1.0f / ( SurfaceArea() * TWO_PI );
}
Ejemplo n.º 4
0
// sample a point on shape
Point Square::sample_l( const LightSample& ls , const Point& p , Vector& wi , Vector& n , float* pdf ) const
{
	float u = 2 * ls.u - 1.0f;
	float v = 2 * ls.v - 1.0f;
	Point lp = transform( Point( radius * u , 0.0f , radius * v ) );
	n = transform( Vector( 0 , 1 , 0 ) );
	Vector delta = lp - p;
	wi = Normalize( delta );

	float dot = Dot( -wi , n );
	if( pdf ) 
	{
		if( dot <= 0 )
			*pdf = 0.0f;
		else
			*pdf = delta.SquaredLength() / ( SurfaceArea() * dot );
	}

	return lp;
}
Ejemplo n.º 5
0
// This function inserts the given child node into the bounding volume
// hierarchy and adjusts all the associated costs that are stored in
// the tree.
void node::AddChild( node *new_child )
    {
    double old_AIC;
    double increment;
    AABB new_volume( new_child->bbox );

    if( child == NULL ) 
        {
        // The current node is a leaf, so we must convert it into
        // an internal node.  To do this, copy its current contents into
        // a new node, which will become a child of this one.
        child         = new node;
        child->bbox   = bbox;
        child->object = object;
        child->parent = this;
 
        // Fill in all the fields of the current node, which has just changed
        // into an internal node with a single child.
        EC   = 1;
        SA   = child->SA;
        SEC_ = child->EC;  // There is only one child.
        SAIC = child->AIC; // There is only one child.
        AIC  = SA * SEC_ + SAIC;
        }

    // Splice the new child into the linked list of children.
    new_child->sibling = child;
    new_child->parent  = this;
    child = new_child;
    
    // Update the summed external cost and the summed AIC as a result
    // of adding the new child node.  These do not depend on surface
    // area, so we needn't consider any expansion of the bounding volume.
    SEC_ += new_child->EC;
    SAIC += new_child->AIC;

    // Now take bounding volume expansion into account due to the new child.
    bool expanded = false;
    if( bbox.Expand( new_volume ) )
        {
        expanded = true;
        SA = SurfaceArea( bbox );
        }

    // Compute new area cost & how much it increased due to new child.
    old_AIC = AIC;
    AIC = SA * SEC_ + SAIC;
    increment = AIC - old_AIC;

    // Propagate the information upward, in two phases.  The first phase
    // deals with volumes that get expanded.  Once a volume is reached that does
    // not expand, there will be no more expansion all the way to the root.
    node *n = this;
    while( expanded )
        {
        expanded = false;
        node *prev = n;
        n = n->parent;
        if( n != NULL && n->bbox.Expand( new_volume ) )
            {
            expanded  = true;
            old_AIC   = n->AIC;
            n->SA     = SurfaceArea( n->bbox );
            n->SAIC  += increment;
            n->AIC    = n->SA * n->SEC_ + n->SAIC;
            increment = n->AIC - old_AIC;
            }
        }

    // From this point up to the root there will be no more expansion.
    // However, we must still propagate information upward.
    while( n != NULL )
        {
        n->SAIC += increment;
        n->AIC  += increment;
        n = n->parent;
        }
    }
Ejemplo n.º 6
0
// This method determines the optimal location to insert a new node
// into the hierarchy; that is, the place that will create the smallest
// increase in the expected cost of intersecting a random ray with the
// new hierarchy.  This is accomplished with branch-and-bound, which finds
// the same solution as a brute-force search (i.e. attempting to insert
// the new object at *each* possible location in the hierarchy), but
// does so efficiently by pruning large portions of the tree.
bool abvh::Branch_and_Bound( 
    node  *the_root,     // Root of the tree to be modified.
    node  *the_node,     // The node to add to the hierarchy.
    node  *&best_parent, // The best node to add it to.
    double &bound )      // Smallest bound achieved thus far.

    {
    double a_delta;  // AIC increase due to Root bbox expansion. 
    double r_delta;  // AIC increase due to new child of Root.   
    double c_bound;  // bound - a_delta, or less.               

    // Compute the increase in the bounding box of the root due 
    // to adding the new object.  This is used in computing     
    // the new area cost no matter where it ends up.            
    AABB root_box( the_root->bbox );
    bool expanded = root_box.Expand( the_node->bbox );

    // Compute the common sub-expression of the new area cost  
    // and the increment over this that would occur if we     
    // made the new object a child of the_root.                    
    if( expanded )
        {
        double new_area = SurfaceArea( root_box );
        a_delta  = ( new_area - the_root->SA ) * the_root->SEC_;
        c_bound  = bound - a_delta;
        if( c_bound <= 0.0 ) return false; // Early cutoff. 
        r_delta  = new_area * the_node->EC + the_node->AIC;
        }
    else
        {
        a_delta = 0.0;
        c_bound = bound;
        r_delta = the_root->SA * the_node->EC + the_node->AIC;
        }

    // See if adding the new node directly to the root of this tree
    // achieves a better bound than has thus far been obtained (via
    // previous searches).  If so, update all the parameters to reflect
    // this better choice.
    bool improved = false;
    if( r_delta < c_bound )
        {
        bound       = a_delta + r_delta;  // This is < *bound. 
        best_parent = the_root;
        c_bound     = r_delta;
        improved    = true;
        }

    // Compute the smallest increment in total area cost (over 
    // "common") which would result from adding the new node 
    // to one of the children of the_root.  If any of them obtains
    // a better bound than achieved previously, then the "best_parent"
    // and "bound" parameters will be updated as a side effect.
    for( node *c = the_root->child; c != NULL; c = c->sibling )
        {
        if( Branch_and_Bound( c, the_node, best_parent, c_bound ) )
            {
            bound   = c_bound + a_delta;
            improved = true;
            }
        }
    return improved;
    }