鼠标未锁定时,3D 光线拾取使用鼠标坐标
所以基本上我已经使用 OpenGL 制作了一个可以执行 3D 光线拾取的程序.如果 Camera View Direction Ray
接触/相交任何东西(不是空气),那么在交点/点处会呈现一个紫色的小框.
So basically I've made a program using OpenGL which can perform 3D Ray Picking. If the Camera View Direction Ray
touches/intersects anything (which isn't air) then a little purple box will get rendered at the intersection point/points.
如果光线与任何红色框"相交,与光线相交的一次将变为绿色.地面和墙壁根本不会改变颜色或纹理.
If the ray intersects with any of the "Red Boxes" the once that are intersecting with the ray will turn green. The ground and walls won't change color or texture at all.
示例:
我目前进行 3D 光线拾取的方法是获取相机的视图方向光线,然后只计算交点.我用于计算交点的函数不是作为布尔值返回,而是作为 3D 矢量(交点本身的坐标)返回
The current way I do the 3D Ray Picking, is getting the camera's view direction ray, and then just calculating for intersections. My function for calculating intersections doesn't return as a boolean, it returns as a 3D Vector (the coordinates of the intersection itself)
所以我想要实现的是计算Picking Ray,但是根据鼠标未锁定在屏幕上.
So what I'm trying to achieve is to calculate the Picking Ray, but according to the mouse when it's not locked to the screen.
示例 - 所以在这里您可以看到紫色框位于十字准线处,但如果我要解锁鼠标并将其移动(在屏幕顶部,像往常一样)并将其移过到我绘制的绿色 X 标记的中心,然后我想计算从相机中心到屏幕顶部鼠标坐标的光线.
Example - So here you can see the purple box is at the crosshair, though if I were to unlocked the mouse and move it (on top of the screen, like normally) and move it over to the center of the green X mark I've draw, then I want to calculate the ray from the camera center to the mouse coordinate on top of the screen.
这应该只是一个数学问题.这只是我目前用来计算光线(并尝试计算第二条光线)的简短列表
This should just be a mathematical problem. Here is just a short list of the things I currently use to calculate the Ray (and trying to calculate the second ray)
- 相机 X、Y、Z
- Camera Pitch Yaw Roll(目前未使用 Roll)
- 远近相机(距离)
- 相机视野
- 相机方面
- 鼠标 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);
这就是我如何计算主拾取射线本身(锁定鼠标的拾取射线).我自己制作了这些类,尽管它们应该有意义(Vector3D
、Ray3D
等)并且 normalize()
方法完全符合它所说的,归一化向量.
That is how I calculate the main picking ray itself (the picking ray for the locked mouse). I made the classes myself, though they should make sense (Vector3D
, Ray3D
, etc) and the normalize()
methods does exactly what it says, normalizes the vector.
因此,当我尝试使用鼠标坐标进行计算时,我在调用 direction.normalize();
之前插入了以下代码,因此在创建 Vector3D 方向后立即
代码>.
So when I tried to calculate using the mouse coordinates I inserted the following code right before I'm calling direction.normalize();
, so right after creating the 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;
}
当鼠标没有被锁定/抓取时,这给了我一个奇怪的结果.这是有道理的,因为我只是在胡思乱想并尝试一些我首先想到的事情.
That gives me a weird result, when the mouse isn't locked/grabbed. It makes sense since I was just messing around and trying some of the things that came first in my mind.
我猜我需要根据俯仰、偏航和滚转来转换鼠标坐标.虽然我不知道我会怎么做.
I'm guessing that I need to translate the mouse coordinates according to the pitch, yaw and roll. Though I don't have any idea, how I would go about doing that.
所以我希望有人可以帮助我实现这一目标和/或给我一些资源,以便我了解如何做我想做的事情.
So I'm hoping that there is somebody that can help me achieving this and/or give me some sort of resource so I can understand how to do what I'm trying to do.
如果您需要更多关于此的信息,请写评论,我会尽力而为.
If you need more info about this, just write a comment and I will do my best.
我暂时使用了 fen 的方法,因为它比计算所有内容要简单得多!
I ended up using fen's way for now, since it was a lot simpler than having to calculate everything!
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)));
这是我创建鼠标射线的代码:
here is my code for creating a mouse ray:
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 2.0, but hope you get the idea.
一些链接:选择+鼠标+OpenGL