Iphone 使用NinevehGL或OpenGL i-phone进行三维光线跟踪拾取
我找不到光线追踪法在3D中拾取的正确和可理解的表达式。有人用任何语言实现过这个算法吗?直接共享工作代码,因为伪代码无法编译,所以它们通常是用缺少的部分编写的。您拥有的是屏幕上2D中的一个位置。首先要做的是将该点从像素转换为标准化的设备坐标——1到1。然后,需要在三维空间中找到点所代表的直线。为此,您需要3D应用程序用于创建投影和相机的变换矩阵/ces 通常有3个矩阵:投影、视图和模型。为对象指定顶点时,它们位于“对象空间”中。乘以模型矩阵得到“世界空间”中的顶点。再次乘以视图矩阵可得到“眼睛/相机空间”。再乘以投影即可得到“剪辑空间”。剪辑空间具有非线性深度。将Z组件添加到鼠标坐标会将其放置在剪辑空间中。可以在任何线性空间中执行线/对象相交测试,因此必须至少将鼠标坐标移动到眼睛空间,但在世界空间(或对象空间,取决于场景图形)中执行相交测试更方便 要将鼠标坐标从剪辑空间移动到世界空间,请添加一个Z分量,然后乘以逆投影矩阵和逆摄影机/视图矩阵。要创建直线,将沿Z方向计算两个点-Iphone 使用NinevehGL或OpenGL i-phone进行三维光线跟踪拾取,iphone,opengl-es,3d,ray-picking,Iphone,Opengl Es,3d,Ray Picking,我找不到光线追踪法在3D中拾取的正确和可理解的表达式。有人用任何语言实现过这个算法吗?直接共享工作代码,因为伪代码无法编译,所以它们通常是用缺少的部分编写的。您拥有的是屏幕上2D中的一个位置。首先要做的是将该点从像素转换为标准化的设备坐标——1到1。然后,需要在三维空间中找到点所代表的直线。为此,您需要3D应用程序用于创建投影和相机的变换矩阵/ces 通常有3个矩阵:投影、视图和模型。为对象指定顶点时,它们位于“对象空间”中。乘以模型矩阵得到“世界空间”中的顶点。再次乘以视图矩阵可得到“眼睛/相
从
和到
在下面的示例中,我有一个对象列表,每个对象都有一个位置和边界半径。交叉点当然永远不会完美匹配,但现在已经足够好了。这不是伪代码,但它使用我自己的向量/矩阵库。你将不得不替换你自己的位置
vec2f mouse = (vec2f(mousePosition) / vec2f(windowSize)) * 2.0f - 1.0f;
mouse.y = -mouse.y; //origin is top-left and +y mouse is down
mat44 toWorld = (camera.projection * camera.transform).inverse();
//equivalent to camera.transform.inverse() * camera.projection.inverse() but faster
vec4f from = toWorld * vec4f(mouse, -1.0f, 1.0f);
vec4f to = toWorld * vec4f(mouse, 1.0f, 1.0f);
from /= from.w; //perspective divide ("normalize" homogeneous coordinates)
to /= to.w;
int clickedObject = -1;
float minDist = 99999.0f;
for (size_t i = 0; i < objects.size(); ++i)
{
float t1, t2;
vec3f direction = to.xyz() - from.xyz();
if (intersectSphere(from.xyz(), direction, objects[i].position, objects[i].radius, t1, t2))
{
//object i has been clicked. probably best to find the minimum t1 (front-most object)
if (t1 < minDist)
{
minDist = t1;
clickedObject = (int)i;
}
}
}
//clicked object is objects[clickedObject]
我假设“from”是鼠标光标的位置?如果是这样,那么如果我们假设openGL坐标,为什么它的z是负的呢
同样,通过这种方式,我们是否假设此时的深度为-1到+1,对吗?这是一个很好的解释,谢谢你讲了这么长时间。我会试试这个方法。您能否也分享一下函数的实现:
intersectSphere()
?mat44 toWorld=(camera.projection*camera.transform).inverse()我不明白什么是camera.projection和camera.transform矩阵。你能解释一下吗,或者在ninevehgl框架中编写等价的矩阵?这两个矩阵你都需要自己构建或者从你的框架/库中获取。一个快速的谷歌让我想到了。看起来您可以使用matrixViewProjection
,它是projection*视图
(同上),我假设该类有一个inverse()
函数。这是我的代码,但结果是这样的:从:0.056349-0.0000000.000000-0.000000到:0.056349-0.0000000.000000-0.000000你说过用w除法会正常化,但这里的w=0。怎么了?如果w
为零,则矩阵可能不正确。两个向量也是相同的。我会打印出矩阵,确保它们不都是零。可能需要更多初始化或更新camera类。
//ray at position p with direction d intersects sphere at (0,0,0) with radius r. returns intersection times along ray t1 and t2
bool intersectSphere(const vec3f& p, const vec3f& d, float r, float& t1, float& t2)
{
//http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
float A = d.dot(d);
float B = 2.0f * d.dot(p);
float C = p.dot(p) - r * r;
float dis = B * B - 4.0f * A * C;
if (dis < 0.0f)
return false;
float S = sqrt(dis);
t1 = (-B - S) / (2.0f * A);
t2 = (-B + S) / (2.0f * A);
return true;
}
vec4f from = toWorld * vec4f(mouse, -1.0f, 1.0f);
vec4f to = toWorld * vec4f(mouse, 1.0f, 1.0f);