基本上,我使用OpenGL制作了一个程序,可以执行3D Ray Picking。如果相机视线方向光线
与任何实体(不是空气)相交/触碰,则会在相交点/点处呈现一个小紫色框。
如果光线与任何“红色框”相交,则与光线相交的那些框将变为绿色。地面和墙壁不会改变颜色或纹理。
示例:
我目前进行3D Ray Picking的方式是获取相机的视线方向光线,然后计算相交点。 我的计算相交函数返回的不是布尔值,而是一个3D向量(相交点的坐标)
问题
因此,我想要实现的是计算Picking Ray,但根据鼠标在屏幕上未锁定时的位置进行计算。
示例 - 在这里,您可以看到紫色框位于十字准线上,但是,如果我解锁鼠标并将其移动(在屏幕上方,像通常一样),并将其移动到我绘制的绿色X标记的中心,则希望从相机中心到屏幕上的鼠标坐标计算射线。
当前测试和想法
这应该只是一个数学问题。以下是我目前用于计算光线(和尝试计算第二条光线)的简短清单:
- 相机X、Y、Z
- 相机俯仰偏航滚转(当前未使用滚转)
- 相机近远距离(距离)
- 相机Fov
- 相机Aspect
- 鼠标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()
方法确切地执行了它所说的操作,即将向量归一化。
思路
所以,当我尝试使用鼠标坐标进行计算时,我在创建Vector3D direction
之后、调用direction.normalize();
之前插入了以下代码。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)));
winY
,但无论如何还是谢谢! - vallentinviewport
大小为4,但实际需要16。:) 另外,我不需要反转Y坐标,所以我删除了那部分代码(这不是一个缺陷)。如果你还没有看到,我已经在帖子中发布了我的结果,并附上了我现在使用的代码。 :) - vallentin