- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
首先,如果您想了解 GLM lookAt 算法的解释,请查看针对此问题提供的答案:https://stackoverflow.com/a/19740748/1525061
mat4x4 lookAt(vec3 const & eye, vec3 const & center, vec3 const & up)
{
vec3 f = normalize(center - eye);
vec3 u = normalize(up);
vec3 s = normalize(cross(f, u));
u = cross(s, f);
mat4x4 Result(1);
Result[0][0] = s.x;
Result[1][0] = s.y;
Result[2][0] = s.z;
Result[0][1] = u.x;
Result[1][1] = u.y;
Result[2][1] = u.z;
Result[0][2] =-f.x;
Result[1][2] =-f.y;
Result[2][2] =-f.z;
Result[3][0] =-dot(s, eye);
Result[3][1] =-dot(u, eye);
Result[3][2] = dot(f, eye);
return Result;
}
现在我要告诉你为什么我似乎对这个算法有概念上的问题。这个 View 矩阵有两个部分,平移和旋转。平移进行正确的逆变换,将相机位置带到原点,而不是相机的原点位置。同样,您希望相机定义的旋转在被放入此 View 矩阵之前也被反转。我在这里看不到这种情况,这是我的问题。
考虑前向 vector ,这是您的相机所注视的位置。因此,这个前向 vector 需要映射到 -Z 轴,这是 openGL 使用的前向方向。这个 View 矩阵的工作方式是通过在 View 矩阵的列中创建一个正交基,所以当你在这个矩阵的右侧乘以一个顶点时,你实际上只是将它的坐标转换为不同轴的坐标.
当我在脑海中播放由于这种变换而发生的旋转时,我看到的旋转不是相机的反向旋转,就像假设发生的那样,而是我看到的是非反向旋转。也就是说,我没有找到映射到 -Z 轴的前向相机,而是发现映射到前向相机的 -Z 轴。
如果您不明白我的意思,请考虑此处发生的同一类型事物的二维示例。假设正向 vector 是 (sqr(2)/2 , sqr(2)/2) 或 45 度的 sin/cos,我们还假设此 2D 相机的侧向 vector 是 -45 度的 sin/cos。我们想将这个前向 vector 映射到 (0,1),即正 Y 轴。正 Y 轴可以被认为是 openGL 空间中的 -Z 轴的类比。让我们考虑一个与前向 vector 方向相同的顶点,即 (1,1)。通过使用 GLM.lookAt 的逻辑,我们应该能够通过使用由第一列中的前向 vector 和第二列中的侧向 vector 组成的 2x2 矩阵将 (1,1) 映射到 Y 轴。这是该计算的等效计算 http://www.wolframalpha.com/input/?i=%28sqr%282%29%2F2+%2C+sqr%282%29%2F2%29++1+%2B+%28sqr%282%29%2F2%2C+-sqr%282%29%2F2+%29+1 .
请注意,您没有像您希望的那样将 (1,1) 顶点映射到正 Y 轴,而是将它映射到正 X 轴。如果应用此变换,您可能还会考虑正 Y 轴上的顶点发生了什么。果然转化为前向 vector 。
因此,GLM 算法似乎发生了一些非常可疑的事情。但是,我怀疑这个算法是不正确的,因为它是如此流行。我错过了什么?
最佳答案
查看 Mesa 中的 GLU 源代码:http://cgit.freedesktop.org/mesa/glu/tree/src/libutil/project.c
首先在 gluPerspective 的实现中,注意 -1
使用索引 [2][3]
和 -2 * zNear * zFar/(zFar - zNear)
正在使用 [3][2]
。这意味着索引是 [column][row]
。
现在在gluLookAt
的实现中,第一行设置为side
,下一行设置为up
,最后一行设置为-转发
。这将为您提供旋转矩阵,该矩阵乘以将眼睛带到原点的平移。
GLM 似乎使用相同的 [column][row]
索引(来自代码)。您刚刚为 lookAt
发布的文章与更标准的 gluLookAt
一致(包括翻译部分)。所以至少 GLM 和 GLU 同意。
然后让我们逐步推导完整的构造。注意 C
中心位置和 E
眼睛位置。
移动整个场景以将眼睛位置放在原点,即应用 -E
的平移。
旋转场景以将相机的轴与标准的(x, y, z)
轴对齐。
2.1 计算相机的正正交基:
f = normalize(C - E) (pointing towards the center)
s = normalize(f x u) (pointing to the right side of the eye)
u = s x f (pointing up)
据此,(s, u, -f)
是相机的正正交基。
2.2 找到将 (s, u, -f)
轴与标准轴 (x, y, z) 对齐的旋转矩阵
。逆旋转矩阵 R
R^-1
做相反的事情,将标准轴与相机轴对齐,根据定义,这意味着:
(sx ux -fx)
R^-1 = (sy uy -fy)
(sz uz -fz)
因为 R^-1 = R^T
,我们有:
( sx sy sz)
R = ( ux uy uz)
(-fx -fy -fz)
将平移与旋转相结合。点 M
通过“查看”变换映射到 R (M - E) = R M - R E = R M + t
。所以最终“看”的 4x4 变换矩阵确实是:
( sx sy sz tx ) ( sx sy sz -s.E )
L = ( ux uy uz ty ) = ( ux uy uz -u.E )
(-fx -fy -fz tz ) (-fx -fy -fz f.E )
( 0 0 0 1 ) ( 0 0 0 1 )
所以当你写的时候:
That is, instead of finding the camera forward being mapped to the -Z axis, I find the -Z axis being mapped to the camera forward.
这非常令人惊讶,因为根据构造,“观察”变换将相机前向轴映射到 -z 轴。这种“观察”变换应该被认为是移动整个场景以将相机与标准原点/轴对齐,它确实是这样做的。
使用您的 2D 示例:
By using the logic of GLM.lookAt, we should be able to map (1,1) to the Y axis by using a 2x2 matrix that consists of the forward vector in the first column and the side vector in the second column.
相反,按照我描述的构造,您需要一个 2x2 矩阵,其中正向和行 vector 作为 rows 而不是列来映射 (1, 1) 和另一个 vector 到 y和 x 轴。要使用矩阵系数的定义,您需要通过变换获得标准基 vector 的图像。这直接给出了矩阵的列。但是由于您要寻找的是相反的(将 vector 映射到标准基 vector ),因此您必须反转转换(转置,因为它是旋转)。然后你的引用 vector 变成行而不是列。
关于c++ - 我对 GLM lookAt 函数的理解不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21152556/
如何将 glm::vec4 转换为 glm::vec3? 仅需要 x、y、z - 可以删除 w 组件。 在 GLSL 中,这可以通过 .xyz[1] 完成,但在 glm 中,这会导致编译错误: err
我正在使用 R 中的 h2o 包通过 h2o.glm() 函数来适应 GLM。在具有 l1 正则化惩罚的 GLM 中评估特征重要性的一种合理方法是监视参数进入线性预测器(即模型)的顺序,因为 l1 惩
我在从最新版本的 R 中的 glm 计算 OR 置信区间时遇到问题,但我以前没有遇到过这个问题。与任何 glm 在哪里 family="binomial" ,无论模型多么简单,我都可以轻松提取摘要和
我需要在我的 glm 图上添加 95% 的置信区间。 当我执行 multiline=T 时(因为我需要在同一个地 block 上进行 2 次处理,所以我这样做了),间隔消失了。我怎样才能让他们回来?
对于上下文,我一直在学习 OpenGL,并且学习了透视投影。花了整整一个小时试图弄清楚为什么我的三角金字塔没有正确显示,直到我注意到我的一个矩阵乘法(使用 operator* for glm::mat
你能告诉我 返回了什么吗? glm$残差和 残留物(glm)其中 glm 是一个准泊松对象。例如我将如何使用 glm$y 和 glm$linear.predictors 创建它们。 glm$残差
这是关于理解 glm 源码的。我想知道 glm 是否对它的类进行了零初始化并进行了尝试。是的,glm::vec3 和 glm::mat4 被初始化,即使没有提供构造函数值。然后我想了解它是如何完成的并
我正在尝试使用 probit 模型重现其他人的工作。不幸的是,我没有太多关于他们方法的信息,只有他们的起始数据和他们的模型图。 当我在 ggplot 中绘制数据并使用 geom_smooth(meth
我有一个 ModelMatrix 类,其中我有一个 glm::vec3 定义为 glm::vec3 *position = nullptr; 然后我得到了一个setter方法 void ModelMa
我想标准化生物数据集的变量。我需要使用不同的响应变量运行 glm、glm.nb 和 lm。 该数据集包含按地块划分的给定树种的数量(所有地块大小相同)和一系列定性变量:植被类型、土壤类型和牛的存在/不
我正在使用著名的 OpenGL 框架创建一个漂亮的图形引擎,但突然遇到了一个意想不到的问题(就像所有问题一样)。 我必须创建一个函数来修改 glm::mat3 中的特定值。为此,我创建了一个简单的函数
其他答案似乎有一些相关信息,但没有解决我遇到的问题。 从我在 Xcode 中的项目中,我选择了“将文件添加到项目”并选择了整个 glm 子文件夹(我被告知这是使用 glm 所需的全部)。然后,在我的
像下面这样计算四元数时, 你能解释一下 1.0f means.. 是什么意思吗? 我认为它可能是 x 轴的 90 度。 glm::angleAxis(3.141592... / 2, glm::dv
这可能真的很简单,但我已经下载了 glm 的正确软件包 glm-0.9.9-a2,但我不知道如何安装。说明要么太复杂,要么太简单。 我无法通过使用包管理器或将存储库添加到 aptitude 或 Ana
我无法理解使用 glm 的效果编码。举个例子: data('mpg') mpg$trans = as.factor(mpg$trans) levels(mpg$trans) [1] "auto(av)
我正在尝试在 R 中重现二项式 glm 的结果。 考虑来自此处的数据 http://www.ats.ucla.edu/stat/r/dae/logit.htm mydata <- read.csv("
ChatGPT已经火了一段时间了,国内也出现了一些平替,其中比较容易使用的是ChatGLM-6B: https://github.com/THUDM/ChatGLM-6B ,主要是能够让我们基于
我一直在阅读code R 使用它来拟合广义线性模型 (GLM),因为 R 的源代码是免费提供的。使用的算法称为迭代重新加权最小二乘法 (IRLS),这是一种有据可查的算法。对于每次迭代,都会调用 Fo
我读过 glmnet 可以在没有正则化的情况下使用,即它可以用作常规 glm。我正在写一篇论文并试图避免使用许多不同的包,因此使用 glmnet 进行常规的 glm 逻辑回归拟合会很方便。谁能帮我?
我正在尝试使用 glm( family='binomial') 来拟合逻辑回归. 这是模型: model<-glm(f_ocur~altitud+UTM_X+UTM_Y+j_sin+j_cos+tem
我是一名优秀的程序员,十分优秀!