Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

KD-Tree traversal (raytracing) - am I missing a case?

I'm trying to traverse a 3D KD-Tree in my raytracer. The Tree is correct, but there seems to be something wrong with my traversal algorithm since I'm getting some errors compared to using a brute-force approach (some small surface areas seem to get ignored).

Note: none of the rays in question is parallel to any axis.

This is my traversal algorithm:

IntersectionData* intersectKDTree(const Ray &ray, KDTreeNode* node, double tMin, double tMax) const{

if (node->GetObjectCount()==0) return 0;

IntersectionData* current = 0;
bool intersected = false;

if (node->m_isLeaf){
        ...test all primitives in the leaf...
}
else{
    int axis = node->m_splitAxis;
    double splitPos = node->m_splitPos;
    double tSplit = (splitPos-ray.point[axis])/ray.direction[axis];
    KDTreeNode* nearNode = ray.point[axis]<splitPos?node->m_leftnode:node->m_rightnode;
    KDTreeNode* farNode = ray.point[axis]<splitPos?node->m_rightnode:node->m_leftnode;

    if (tSplit > tMax)
        return intersectKDTree(ray, nearNode , tMin, tMax);//case A
    else if (tSplit < tMin){
        if(tSplit>0)
            return intersectKDTree(ray, farNode, tMin, tMax);//case B
        else if(tSplit<0)
            return intersectKDTree(ray, nearNode, tMin,tMax);//case C
        else{//tSplit==0
            if(ray.direction[axis]<0)
                return intersectKDTree(ray, farNode, tMin, tMax);//case D
            else
                return intersectKDTree(ray, nearNode, tMin, tMax);//case E
        }
    }
    else{
        if(tSplit>0){//case F
            current = intersectKDTree(ray, nearNode, tMin, tSplit);
            if (current != 0)
                return current;
            else
                return intersectKDTree(ray, farNode, tSplit, tMax);
        }
        else{
            return intersectKDTree(ray,nearNode,tSplit, tMax);//case G
        }
    }
}
}

I created a graphic with all different cases:

alt text
(source: cycovery.com)

Am I missing a case?

thank you for the help!

like image 677
Mat Avatar asked Dec 05 '09 14:12

Mat


1 Answers

Just in case someone's interested - the mistake i did was to not consider a special case described in this paper

http://www.cs.utexas.edu/ftp/pub/techreports/tr88-07.pdf page 12

It happens if one polygon lies on the splitting plane, such that it's part of both cells and the ray goes through both cells. if the nearcell is tested, but the actual intersection happens in the space of the farcell (this is possible because the polygon that intersects is part of both cells) then there is still the possibility, that in the far cell a intersection could be found which is actually closer than the already found one. Therefore - if the found t for the intersection is larger than tSplit, then already the farCell has to be tested

like image 119
Mat Avatar answered Nov 17 '22 19:11

Mat