开发者

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 开发者_StackOverflow社区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:

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

(source: cycovery.com)

Am I missing a case?

thank you for the help!


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


I've taken a different approach to the problem, here's what I do:

if(ray.direction(current_node.split_axis)>0) {
  near=current_node.left_child
  far=current_node.right_child
} else {
  near=current_node.right_child
  far=current_node.left_child
}
tsplit=(current_node.split_value-ray.origin[current_node.split_axis])/ray.direction[current_node.split_axis]
if(tsplit>current_stack.tmax||tsplit<0) {
  only near child
} else if(tsplit<tmin) {
  only far child
} else {
  both childs
}

You see that I don't use the origin of the ray for choosing which of the left/right child is near/far, and I take in account the case you named C by using the tsplit<0 condition

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜