OpenGL中的Ray Sphere交点

时间:2015-12-13 13:46:27

标签: c++ opengl graphics geometry mouse-picking

我尝试使用光线球体交叉点在OpenGL中执行鼠标拾取。我在网上找到了一些公式,我尝试的最后一个是Stack Exchange上的用户建议的:

Ray-Sphere intersection

根据我对这个答案的理解,我要检查二次方程是否具有正根。我并不十分关心交叉点发生的位置,就像光线完全与球体相交一样。我的代码如下,但似乎不起作用。

bool Mesh::useObject(vec3 camera, vec3 direction) {

    // a = (xB-xA)²+(yB-yA)²+(zB-zA)²
    float a = ((direction.v[0] - camera.v[0])*(direction.v[0] - camera.v[0])
        + (direction.v[1] - camera.v[1])*(direction.v[1] - camera.v[1])
        + (direction.v[2] - camera.v[2])*(direction.v[2] - camera.v[2]));

    // b = 2*((xB-xA)(xA-xC)+(yB-yA)(yA-yC)+(zB-zA)(zA-zC))
    float b = 2 * ((direction.v[0] - camera.v[0])*(camera.v[0] - mOrigin.v[0])
        + (direction.v[1] - camera.v[1])*(camera.v[1] - mOrigin.v[1])
        + (direction.v[2] - camera.v[2])*(camera.v[2] - mOrigin.v[2]));

    // c = (xA-xC)²+(yA-yC)²+(zA-zC)²-r²
    float c = ((camera.v[0] - mOrigin.v[0])*(camera.v[0] - mOrigin.v[0])
        + (camera.v[1] - mOrigin.v[1])*(camera.v[1] - mOrigin.v[1])
        + (camera.v[2] - mOrigin.v[2])*(camera.v[2] - mOrigin.v[2])
        - (mRadius)*(mRadius));

    float delta = (b*b) - (4 * a*c);

    if (delta < 0)
        return false;

    else {
        std::cout << "Object " << mMesh << " is at postion (" <<
            mOrigin.v[0] << ", " <<
            mOrigin.v[1] << ", " <<
            mOrigin.v[2] << ")\n" <<
            "Size: " << mRadius << std::endl;
        return true;
    }
}

我的C ++技能非常生疏,所以如果这是一种可怕的做法,我会道歉。这个方法需要两个三个浮点数的矢量,摄像机的位置,以及我在摄像机前面1个单位中的一个点的坐标(我称之为这个方向)。

当我面对一个物体并按下一个键时,我想得到物体的位置及其半径,但只有当我站在场景中的一个物体上时我才会得到输出,或者如果我站在另一个大物体附近。显然我的计算有些不对劲(或者更糟糕的是,我的代码),但我无法弄清楚那是什么。 :(

如果您需要更多代码,或者有任何不清楚的地方,请告诉我们。这是我对SO的第一个问题,所以如果这个问题措辞严厉,我很抱歉。

编辑:我不应该使用鼠标坐标作为我的光线上的一个点。稍微编辑了我的问题。

1 个答案:

答案 0 :(得分:1)

该代码看起来很混乱。用于检查直线(direction, origin)与球面(centerradius)的交点的一般公式应为:

length(cross(direction, center-origin)) / length(direction) < radius

检查是否正确实现了该功能,也许将某些操作分解为单独的功能。