14

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

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

例子:

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

问题

所以我想要实现的是计算Picking Ray ,但在鼠标锁定到屏幕时根据鼠标。

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

当前的测试和想法

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

  • 相机 X、Y、Z
  • 相机俯仰偏航滚动(目前未使用滚动)
  • 相机近远(距离)
  • 相机视野
  • 相机方面
  • 鼠标 X、Y(在屏幕顶部)
  • 画面宽度、高度

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

计算主Picking Ray本身

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);

这就是我计算主拾取射线本身(锁定鼠标的拾取射线)的方式。我自己制作了这些类,尽管它们应该有意义(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;
}

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

我猜我需要根据俯仰、偏航和滚动来翻译鼠标坐标。虽然我没有任何想法,我将如何去做。

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

额外的

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

答案 - 感谢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)));
4

2 回答 2

11

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

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,但希望你明白。

一些链接选择+鼠标+ OpenGL

于 2013-08-15T06:45:23.987 回答
3

All you need to do is shoot a ray out from the camera's origin that passes through the screen space point (x,y). The problem here is that to get from your camera's origin to a point in screen space there are a number of transformations that usually occur (2 matrices and a viewport mapping in fact). The other problem is that this throws everything on its head, usually you start with a world space position and wind up with screen space in the OpenGL pipeline -- you want to go the other way :)

You cannot solve this problem with the camera's orientation alone. You need to know how the scene is projected onto your viewing plane, hence the need for the projection matrix. You also need to know the viewport dimensions and the camera's origin. The entire problem can be solved if you know the viewport dimensions, the projection matrix and the modelview matrix.

I would suggest you look into gluUnProject (...), it does everything you need. A quick search on Google resulted in this, which looks pretty helpful: http://myweb.lmu.edu/dondi/share/cg/unproject-explained.pdf

于 2013-08-15T02:41:38.657 回答