【发布时间】:2012-11-21 00:30:18
【问题描述】:
我正在尝试通过来自this website 的指令实现拾取射线。
现在我基本上只希望能够点击地面,命令我的小人向这个点走。 由于我的地平面是平面的、非旋转的和非平移的,所以当 y 达到 0 时,我必须找到我的拾取射线的 x 和 z 坐标。
到目前为止一切顺利,这就是我想出的:
//some constants
float HEIGHT = 768.f;
float LENGTH = 1024.f;
float fovy = 45.f;
float nearClip = 0.1f;
//mouse position on screen
float x = MouseX;
float y = HEIGHT - MouseY;
//GetView() returns the viewing direction, not the lookAt point.
glm::vec3 view = cam->GetView();
glm::normalize(view);
glm::vec3 h = glm::cross(view, glm::vec3(0,1,0) ); //cameraUp
glm::normalize(h);
glm::vec3 v = glm::cross(h, view);
glm::normalize(v);
// convert fovy to radians
float rad = fovy * 3.14 / 180.f;
float vLength = tan(rad/2) * nearClip; //nearClippingPlaneDistance
float hLength = vLength * (LENGTH/HEIGHT);
v *= vLength;
h *= hLength;
// translate mouse coordinates so that the origin lies in the center
// of the view port
x -= LENGTH / 2.f;
y -= HEIGHT / 2.f;
// scale mouse coordinates so that half the view port width and height
// becomes 1
x /= (LENGTH/2.f);
y /= (HEIGHT/2.f);
glm::vec3 cameraPos = cam->GetPosition();
// linear combination to compute intersection of picking ray with
// view port plane
glm::vec3 pos = cameraPos + (view*nearClip) + (h*x) + (v*y);
// compute direction of picking ray by subtracting intersection point
// with camera position
glm::vec3 dir = pos - cameraPos;
//Get intersection between ray and the ground plane
pos -= (dir * (pos.y/dir.y));
在这一点上,我希望pos 是我的拾取射线击中我的地平面的点。
然而,当我尝试它时,我得到了这样的东西:
(未记录鼠标光标)
由于地面没有纹理,因此很难看清,但相机是倾斜的,就像大多数 RTS 游戏一样。
根据我的计算,我在 Blender 中模拟一个看起来很远的人的可怜尝试标志着交叉点发生。
所以看来view 和dir 之间的转换在某处搞砸了,我的光线最终指向了错误的方向。
鼠标离屏幕中心越远,计算出的位置和实际位置之间的差距就会越大。
我发现:
- 高度和长度不准确。由于 Windows 为边框切掉了几个像素,因此使用 1006,728 作为窗口分辨率会更准确。我想这可能会造成一些小的差异。
- 如果我将 fovy 从 45 增加到大约 78,我会得到相当准确的光线。所以也许我用作fovy的东西有问题。我明确地打电话给
glm::perspective(45.f, 1.38f, 0.1f, 500.f)(分别为fovy、纵横比、fNear、fFar)。
所以这就是我迷路的地方。为了获得准确的光线,我必须做什么?
PS:我知道有一些函数和库已经实现了这个,但为了学习目的,我尽量远离这些东西。
【问题讨论】:
-
“调试我的代码”这类问题几乎不适合 SO 格式。
-
@KromStern 这不像“哦,我的代码不起作用,让我们请 SO 为我修复它”。我试图让这个工作几个小时,并通过谷歌和 SO 没有找到对我有帮助的东西(部分原因是我的数学知识薄弱)。提供 SSCCE 也非常困难,因为所有相机/渲染/winapi 的东西对于拾取射线实际做某事都是必不可少的。而且因为我自己写的,它远不止几十行。老实说,我不知道如何在这里帮助自己,这就是我问的原因。谁知道——也许这只是算法中的一个小错误。
-
@KromStern PS:浏览 opengl 标记的问题,我觉得至少有三分之一的问题符合“调试我的代码”之类的问题。他们都说“这是我的代码,x 不起作用,怎么了?”。我的有什么不同?
-
您的代码不起作用,您确实要求 SO 为您修复它。我建议你在谷歌上搜索一个工作教程并从中学习。
标签: c++ windows opengl picking ray-picking