【问题标题】:Create ray from mouse coordinates for 3D picking从鼠标坐标创建射线以进行 3D 拾取
【发布时间】:2014-11-13 03:46:35
【问题描述】:

我的问题

有人可以链接一篇好文章/教程/任何东西,甚至可以解释如何正确从鼠标坐标投射光线以选择 3D 对象
我已经有了射线和交叉点的作品,现在我只需要通过鼠标点击来创建射线。

我只是想要一些我知道实际上应该工作的东西,这就是为什么我在这里问专业人士,而不是首先我不确定它是否正确。


现在状态

我有一个射线类,如果我将原点和方向设置为与相机相同,它实际上可以工作并检测相交,所以当我移动相机时它实际上选择了正确的东西。

现在我想用鼠标实际进行 3D 拾取,而不是相机移动。
我已经阅读了很多关于此的其他问题、2 个教程,尤其是许多不同的数学内容,因为我真的不擅长它。
但这对我没有多大帮助,因为那里的人经常使用一些“取消项目”功能,这些功能似乎实际上已被弃用,我不知道如何使用,也无权访问。

现在我将光线原点设置为相机位置,然后尝试从this tutorial 中的计算中获取光线的方向。
而且它有点作用,这意味着当相机指向对象并且有时沿着整个y轴时,选择会起作用,我不知道发生了什么.

如果有人想立即查看我的代码:

public Ray2(Camera cam, float mouseX, float mouseY) {
    origin = cam.getEye();
    float height = 600;
    float width = 600;
    float aspect = (float) width / (float) height;


    float x = (2.0f * mouseX) / width - 1.0f;
    float y = 1.0f - (2.0f * mouseX) / height;
    float z = 1.0f;
    Vector ray_nds = vecmath.vector(x, y, z);

    Vector4f clip = new Vector4f(ray_nds.x(), ray_nds.y(), -1.0f, 1.0f);
    Matrix proj = vecmath.perspectiveMatrix(60f, aspect, 0.1f, 100f);
    proj = proj.invertRigid();
    float tempX = proj.get(0, 0) * clip.x + proj.get(1, 0) * clip.y
            + proj.get(2, 0) * clip.z + proj.get(3, 0) * clip.w;
    float tempY = proj.get(0, 1) * clip.x + proj.get(1, 1) * clip.y
            + proj.get(2, 1) * clip.z + proj.get(3, 1) * clip.w;
    float tempZ = proj.get(0, 2) * clip.x + proj.get(1, 2) * clip.y
            + proj.get(2, 2) * clip.z + proj.get(3, 2) * clip.w;
    float tempW = proj.get(0, 3) * clip.x + proj.get(1, 3) * clip.y
            + proj.get(2, 3) * clip.z + proj.get(3, 3) * clip.w;


    Vector4f ray_eye = new Vector4f(tempX, tempY, tempZ, tempW);
    ray_eye = new Vector4f(ray_eye.x, ray_eye.y, -1.0f, 0.0f);

    Matrix view = cam.getTransformation();
    view = view.invertRigid();

    tempX = view.get(0, 0) * ray_eye.x + view.get(1, 0) * ray_eye.y
            + view.get(2, 0) * ray_eye.z + view.get(3, 0) * ray_eye.w;
    tempY = view.get(0, 1) * ray_eye.x + view.get(1, 1) * ray_eye.y
            + view.get(2, 1) * ray_eye.z + view.get(3, 1) * ray_eye.w;
    tempZ = view.get(0, 2) * ray_eye.x + view.get(1, 2) * ray_eye.y
            + view.get(2, 2) * ray_eye.z + view.get(3, 2) * ray_eye.w;
    tempW = view.get(0, 3) * ray_eye.x + view.get(1, 3) * ray_eye.y
            + view.get(2, 3) * ray_eye.z + view.get(3, 3) * ray_eye.w;

    Vector ray_wor = vecmath.vector(tempX, tempY, tempZ);
    // don't forget to normalise the vector at some point
    ray_wor = ray_wor.normalize();
    direction = ray_wor;
}

【问题讨论】:

    标签: opengl camera ray-picking mouse-picking


    【解决方案1】:

    首先,unproject() 方法是要走的路。它根本没有被弃用。你可以在GLM math library 中找到它的实现。这是我基于 Ray 的 3D 拾取的实现:

        // let's check if this renderable's AABB is clicked:
        const glm::ivec2& mCoords = _inputManager->GetMouseCoords();
    
        int mouseY = _viewportHeight - mCoords.y;
    
        //unproject twice to build a ray from near to far plane"
        glm::vec3 v0 = glm::unProject(glm::vec3(float(mCoords.x), float(mouseY), 0.0f),_camera->Transform().GetView(),_camera->Transform().GetProjection(), _viewport);
        glm::vec3 v1 = glm::unProject(glm::vec3(float(mCoords.x), float(mouseY), 1.0f),_camera->Transform().GetView(),_camera->Transform().GetProjection(), _viewport);
    
        glm::vec3 dir  = (v1 - v0); 
    
        Ray r(_camera->Transform().GetPosition(),dir);
    
        float ishit ;
    
         //construct AABB:
        glm::mat4 aabbMatr = glm::translate(glm::mat4(1.0),renderable->Transform().GetPosition());
    
        aabbMatr = glm::scale(aabbMatr,renderable->Transform().GetScale());
    
        //transforms AABB vertices(need it if the origianl bbox is not axis aligned as in this case)
        renderable->GetBoundBox()->RecalcVertices(aabbMatr);
    
         //this method makes typical Ray-AABB intersection test:
        if(r.CheckIntersectAABB(*renderable->GetBoundBox().get(),&ishit)){
    
            printf("HIT!\n");
    
        }
    

    但我建议您也看看color based 3d picking,它像素完美,甚至更容易实现。

    【讨论】:

    • 好的,谢谢你澄清这一点,但我真的很想坚持光线投射。另外,你还有什么其他的吗,我可以通过某种方式在没有额外的数学库的情况下做到这一点?还是您认为使用这是唯一的好方法?
    • lool 抱歉,我没有意识到 glu 包含在 LWJGL 中,所以我将尝试使用 gluunproject
    猜你喜欢
    • 2013-08-17
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    相关资源
    最近更新 更多