所以基本上我已经使用 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)));