【问题标题】:KD-Tree traversal (raytracing) - am I missing a case?KD-Tree 遍历(光线追踪)——我错过了一个案例吗?
【发布时间】:2010-12-23 13:40:02
【问题描述】:

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

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

这是我的遍历算法:

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
        }
    }
}
}

我创建了一个包含所有不同情况的图形:


(来源:cycovery.com

我错过了一个案例吗?

感谢您的帮助!

【问题讨论】:

    标签: tree traversal raytracing


    【解决方案1】:

    我对这个问题采取了不同的方法,这就是我所做的:

    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
    }
    

    您看到我没有使用射线的原点来选择左/右孩子中的哪一个是近/远,并且我考虑到您使用 tsplit

    【讨论】:

    • 嗨!但例如,如果 C 遍历错误的孩子,因为 'near' 将是左孩子,但你应该遍历右孩子。
    • @Mat 因为它应该是 ray.direction(current_node.split_axis)&gt;=0 ?或者你的意思是什么?
    【解决方案2】:

    以防万一有人感兴趣-我犯的错误是没有考虑本文中描述的特殊情况

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

    如果一个多边形位于分割平面上,就会发生这种情况,它是两个单元的一部分,并且光线穿过两个单元。如果测试了近小区,但实际相交发生在远小区的空间中(这是可能的,因为相交的多边形是两个小区的一部分),那么仍然有可能在远小区中找到一个相交实际上比已经找到的更接近。因此 - 如果找到的交点 t 大于 tSplit,那么 farCell 已经被测试了

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-28
    • 2019-03-20
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多