opengl - 3D 光线拾取在鼠标未锁定时使用鼠标坐标

标签 opengl vector 3d projection ray-picking

所以基本上我已经使用OpenGL制作了一个可以执行3D光线拾取的程序。如果Camera View Direction Ray接触/相交任何东西(不是空气),然后在交点/点处会呈现一个紫色的小盒子。

如果光线与任何“红色框”相交,与光线相交的一次将变为绿色。地面和墙壁根本不会改变颜色或纹理。

例子:



我目前进行 3D 光线拾取的方法是获取相机的 View 方向光线,然后仅计算交点。我用于计算交点的函数不会作为 bool 值返回,而是作为 3D 向量(交点本身的坐标)返回

问题

所以我想要实现的是计算采摘射线,但是根据鼠标当它是不是 锁定在屏幕上。

示例 - 所以在这里你可以看到紫色框位于十字准线处,但如果我要解锁鼠标并移动它(在屏幕顶部,像往常一样)并将其移动到绿色 X 标记的中心我已经绘制,然后我想计算从相机中心到屏幕顶部鼠标坐标的光线。



当前的测试和想法

这应该只是一个数学问题。这只是我目前用来计算光线(并尝试计算第二条光线)的简短列表

  • 相机 X、Y、Z
  • Camera Pitch Yaw Roll(Roll 目前未使用)
  • 远近相机(距离)
  • 相机 Fov
  • 相机方面
  • 鼠标 X、Y(在屏幕本身的顶部)
  • 屏幕宽度、高度

  • 鼠标 X 和 Y 原点 (0x0) 位于窗口/框架的左下角。

    计算主采摘射线本身
    Vector3D position = new Vector3D(
            camera.x,
            camera.y,
            camera.z);
    
    Vector3D direction = new Vector3D(
            Math.cos(Math.toRadians(camera.pitch)) * -Math.sin(Math.toRadians(-camera.yaw)) * camera.far,
            Math.cos(Math.toRadians(camera.pitch)) * cameara.far,
            Math.cos(Math.toRadians(camera.pitch)) * -Math.sin(Math.toRadians(-camera.yaw)) * camera.far);
    
    direction.normalize();
    
    Ray3D ray = new Ray(position, direction);
    

    这就是我如何计算主拾取射线本身(锁定鼠标的拾取射线)。我自己制作了类(class),尽管它们应该有意义( Vector3DRay3D 等)和 normalize()方法完全按照它所说的去做,将向量归一化。

    主意

    因此,当我尝试使用鼠标坐标进行计算时,我在调用 direction.normalize(); 之前插入了以下代码,所以在创建 Vector3D direction 之后.
    if (!Mouse.isGrabbed())
    {
        float mx = Mouse.getX() / (float) scene.width - 0.5f;
        float my = Mouse.getY() / (float) scene.height - 0.5f;
    
        mx *= camera.far;
        my *= camera.far;
    
        line.b.x += mx;
        line.b.y += my;
        line.b.z += mz;
    }
    

    当鼠标没有被锁定/抓取时,这给了我一个奇怪的结果。这是有道理的,因为我只是在胡思乱想并尝试一些首先出现在我脑海中的事情。

    我猜我需要根据俯仰、偏航和滚转来转换鼠标坐标。虽然我不知道,我将如何去做。

    所以我希望有人可以帮助我实现这一目标和/或给我一些资源,这样我就可以了解如何做我想做的事情。

    额外的

    如果您需要更多关于此的信息,请写评论,我会尽力而为。

    答案 - 感谢 fen

    我最终使用了 fen现在的方式,因为它比必须计算所有内容简单得多!
    FloatBuffer projection = BufferTools.createFloatBuffer(16);
    FloatBuffer modelview = BufferTools.createFloatBuffer(16);
    IntBuffer viewport = BufferTools.createIntBuffer(16);
    
    glGetFloat(GL_PROJECTION_MATRIX, projection);
    glGetFloat(GL_MODELVIEW_MATRIX, modelview);
    glGetInteger(GL_VIEWPORT, viewport);
    
    float win_x = Mouse.getX();
    float win_y = Mouse.getY();
    
    FloatBuffer position_near = BufferTools.createFloatBuffer(3);
    FloatBuffer position_far = BufferTools.createFloatBuffer(3);
    
    gluUnProject(win_x, win_y, 0f, modelview, projection, viewport, position_near);
    gluUnProject(win_x, win_y, 1f, modelview, projection, viewport, position_far);
    
    Ray3D ray = new Ray3D(
        new Vector3D(
            position_near.get(0),
            position_near.get(1),
            position_near.get(2)),
        new Vector3D(
            position_far.get(0),
            position_far.get(1),
            position_far.get(2)));
    

    最佳答案

    这是我创建鼠标射线的代码:

    double matModelView[16], matProjection[16]; 
    int viewport[4]; 
    
    // get matrix and viewport:
    glGetDoublev( GL_MODELVIEW_MATRIX, matModelView ); 
    glGetDoublev( GL_PROJECTION_MATRIX, matProjection ); 
    glGetIntegerv( GL_VIEWPORT, viewport ); 
    
    // window pos of mouse, Y is inverted on Windows
    double winX = (double)mouseX; 
    double winY = viewport[3] - (double)mouseY; 
    
    // get point on the 'near' plane (third param is set to 0.0)
    gluUnProject(winX, winY, 0.0, matModelView, matProjection, 
             viewport, m_start.x, &m_start.y, &m_start.z); 
    
    // get point on the 'far' plane (third param is set to 1.0)
    gluUnProject(winX, winY, 1.0, matModelView, matProjection, 
             viewport, m_end.x, &m_end.y, &m_end.z); 
    
    // now you can create a ray from m_start to m_end
    

    OpenGL 2.0,但希望你能明白。

    部分链接 :Select + Mouse + OpenGL

    关于opengl - 3D 光线拾取在鼠标未锁定时使用鼠标坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18244678/

    相关文章:

    c++ - 在 OpenGL C++ 中旋转子对象

    c++ - openGL如何使用unsigned int顶点数据进行绘制

    c++ - 禁用 Qt 3d 中的所有光源

    matrix - 使用 glm::perspective 关于 zFar 和 zNear 平面偏移的混淆

    macos - OSX 10.8 OpenGL扩展

    c++ - 使用 reference_wrappers 初始化 vector

    c# - 将 vector<unsigned char> {1,2,3} 转换为字符串 "1-2-3"AS DIGITS

    c++ - 从 vector 中删除对象

    javascript - D3 强制布局 - 如何实现节点的 3D 外观?

    opengl - libgdx如何在3D中使用着色器