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

Val*_*tin 12 opengl 3d vector projection ray-picking

所以基本上我已经使用OpenGL创建了一个可以执行3D Ray Picking的程序.如果Camera View Direction Ray触摸/交叉任何东西(不是空气),那么将在交叉点/点处渲染一个小的紫色框.

如果光线与任何"红色框"相交,那么与光线相交的光线将变为绿色.地面和墙壁根本不会改变颜色或纹理.

例子:

我目前进行3D射线拾取的方法是获取相机的视线方向光线,然后只计算交叉点.我计算交叉点的函数不作为布尔值返回,它作为3D矢量返回(交集本身的坐标)

问题

所以我想要实现的是计算拾取雷,但是当它没有锁定到屏幕时根据鼠标.

示例 - 所以在这里你可以看到紫色的盒子在十字准线上,但是如果我要解锁鼠标并移动它(在屏幕顶部,正常情况下)并将其移动到绿色X标记的中心我'我画了,然后我想计算从摄像机中心到屏幕顶部鼠标坐标的光线.

目前的测试和想法

这应该只是一个数学问题.这里只是我目前用来计算雷的一些简短列表(并试图计算第二条射线)

  • Cameara X,Y,Z
  • 相机间距偏转辊(现在不使用辊)
  • 相机近远(距离)
  • 相机Fov
  • 相机方面
  • 鼠标X,Y(在屏幕顶部)
  • Sceen Width,Height

鼠标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);
Run Code Online (Sandbox Code Playgroud)

这就是我计算主要拾取光线本身的方式(锁定鼠标的拾取光线).我做出了自己的类,但他们应该感(Vector3D,Ray3D,等)和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;
}
Run Code Online (Sandbox Code Playgroud)

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

我猜我需要根据音高,偏航和滚动来转换鼠标坐标.虽然我不知道,但我会怎么做.

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

额外

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

答案 - 感谢

我现在最终使用了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)));
Run Code Online (Sandbox Code Playgroud)

fen*_*fen 10

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

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
Run Code Online (Sandbox Code Playgroud)

OpenGL 2.0,但希望你明白这个想法.

一些链接:选择+鼠标+ OpenGL