Tree KD树遍历(光线跟踪)-我是否遗漏了一个案例?

Tree KD树遍历(光线跟踪)-我是否遗漏了一个案例?,tree,traversal,raytracing,Tree,Traversal,Raytracing,我正在尝试在我的光线跟踪器中遍历3D KD树。树是正确的,但我的遍历算法似乎有点问题,因为与使用蛮力方法相比,我得到了一些错误(一些小的表面区域似乎被忽略) 注意:所讨论的光线均不平行于任何轴 这是我的遍历算法: IntersectionData* intersectKDTree(const Ray &ray, KDTreeNode* node, double tMin, double tMax) const{ if (node->GetObjectCount()==0) ret

我正在尝试在我的光线跟踪器中遍历3D KD树。树是正确的,但我的遍历算法似乎有点问题,因为与使用蛮力方法相比,我得到了一些错误(一些小的表面区域似乎被忽略)

注意:所讨论的光线均不平行于任何轴

这是我的遍历算法:

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
        }
    }
}
}
IntersectionData*intersectKDTree(常数光线&光线,KDTreeNode*节点,双tMin,双tMax)常数{
如果(节点->GetObjectCount()==0)返回0;
相交数据*当前=0;
布尔相交=假;
如果(节点->m_岛){
…测试叶中的所有基元。。。
}
否则{
int轴=节点->m_轴;
双拆分位置=节点->m_拆分位置;
double tSplit=(splitPos射线点[轴])/射线方向[轴];
KDTreeNode*nearNode=ray.point[轴]m_leftnode:node->m_rightnode;
KDTreeNode*farNode=ray.point[轴]m_rightnode:node->m_leftnode;
如果(tSplit>tMax)
返回intersectKDTree(光线、近节点、tMin、tMax);//案例A
否则如果(tSplit0)
返回intersectKDTree(光线、farNode、tMin、tMax);//案例B

否则,如果(tSplit我对这个问题采取了不同的方法,我会这样做:

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
}
if(光线方向(当前节点分割轴)>0){
near=当前\节点。左\子节点
远=当前节点。右\u子节点
}否则{
near=当前\节点。右\子节点
远=当前节点。左子节点
}
tsplit=(当前节点.分割值-ray.origin[当前节点.分割轴])/ray.direction[当前节点.分割轴]

如果(TSPLC:Currth.StApp.tMax)tPult

只是有人感兴趣,我犯的错误是不考虑本文中描述的特殊情况

第12页


如果一个多边形位于分割平面上,即它是两个单元的一部分,光线穿过两个单元,则会发生这种情况。如果测试了近单元,但实际相交发生在远单元的空间中(这是可能的,因为相交的多边形是两个单元的一部分)然后仍然有可能,在远单元中,可以找到一个实际上比已经找到的交叉点更近的交叉点。因此,如果找到的交叉点t大于tSplit,则必须对远单元进行测试。

hi!但例如,在案例C中,您将遍历错误的子节点,因为“近”将被保留为child,但您应该遍历右子项。@Mat,因为它应该是
ray.direction(当前节点.分割轴)>=0 < /代码>?或者为什么?关于作者或名字的任何想法?链接似乎已经停止工作。当第二个链接也死了,我又追查了这篇文章。Donald Fussell,K.R.SuBrabaNIC得克萨斯大学奥斯汀分校计算机科学系1988年3月