使用这里给出的四元数旋转的定义:
因此,上述公式的GLM中的等效代码如下:
glm::quat q;
glm::vec3 v;
glm::vec3 rotated_vector = q * v;
上述rotated_vector
是将Lq
变换应用于矢量v
的结果。
我说得对吗?
下面是我编写的测试代码(并非详尽无遗):
for (size_t number_of_conducted_testing = 0; number_of_conducted_testing < 10000; number_of_conducted_testing++)
{
//axis to rotate around
glm::vec3 axis = glm::sphericalRand(1.0);
//vector to be rotated
glm::vec3 v = glm::sphericalRand(1.0);
//quaternion
glm::quat q;
for (auto degree = 0.f; degree < 370.f; degree += 0.0001f)
{
q = glm::angleAxis(glm::radians(degree), axis);
glm::vec3 q_vector = glm::vec3(q.x, q.y, q.z);
const glm::vec3 rotated_vector = q * v;
const glm::vec3 rotated_vector_0 = ((q.w) * (q.w) - glm::length2(q_vector)) * v + 2 * (glm::dot(q_vector, v)) * q_vector + 2 * q.w * (glm::cross(q_vector, v));
float difference = 0.0f;
if (!test_similarity(rotated_vector, rotated_vector_0, difference))
{
throw std::runtime_error("two vectors are different!");
}
}
}
bool App::test_similarity(glm::vec3 a, glm::vec3 b,float& difference)
{
const auto difference = glm::length((a - b));
return difference < 1e-5f;
}
而且它没有为这个案子抛出任何例外,difference < 0.00001
。
发布于 2022-07-14 09:49:33
最后,我在Kavan,Ladislav等,几何蒙皮与近似双四元数混合中找到了GLM '*‘操作符的实现“图形上的ACM事务处理”27.4 (2008年):105:
Lemma 4.设
\textbf{q} = a + \textbf{r}
是具有标量部分a
和向量部分\textbf{r}
__的单位正则四元数。由正则四元数\textbf{v} = v_0i + v_1j + v_2k
表示的向量D5
的旋转可以计算为\textbf{v}' = \textbf{v} + 2\textbf{r} \times (\textbf{r} \times \textbf{v} + a\textbf{v})\tag{15}
,其中\textbf{v}′
是由\textbf{q}
旋转的向量\textbf{v}
。证据。该证明包括重新排列众所周知的表达式\textbf{v}′ = \textbf{qvq}^∗
。利用方程(14),我们可以展开\begin{align} \textbf{v}′ &= \textbf{qvq}^∗ = (a + \textbf{r})\textbf{v}(a − \textbf{r}) = (−\langle\textbf{r}, \textbf{v}\rangle + a\textbf{v} + \textbf{r} \times \textbf{v})(a − \textbf{r}) = \\ &= −a\langle\textbf{r}, \textbf{v}\rangle + a\langle\textbf{v}, \textbf{r}\rangle + \langle\textbf{r}, \textbf{v}\rangle\textbf{r} + a^2\textbf{v} + a(\textbf{r} \times \textbf{v}) − a(\textbf{v} \times \textbf{r}) − (\textbf{r} \times \textbf{v}) \times \textbf{r} = \\ &= \langle\textbf{r}, \textbf{v}\rangle\textbf{r} + a^2\textbf{v} + 2a(\textbf{r} \times \textbf{v}) + \textbf{r} \times (\textbf{r} \times \textbf{v}) \end{align}
回忆拉格朗日公式\textbf{r} \times (\textbf{r} \times \textbf{v}) = \textbf{r}\langle\textbf{r}, \textbf{v}\rangle − \textbf{v}\langle\textbf{r}, \textbf{r}\rangle
,该公式加到以前的方程中,得到了\begin{align} \textbf{v}′ &= \langle\textbf{r}, \textbf{v}\rangle\textbf{r} + a^2\textbf{v} + 2a(\textbf{r} \times \textbf{v}) + 2\textbf{r} \times (\textbf{r} \times \textbf{v}) − \textbf{r}\langle\textbf{r}, \textbf{v}\rangle + \textbf{v}\langle\textbf{r}, \textbf{r}\rangle = \\ &= \textbf{v}(a^2 + \Vert\textbf{r}\Vert^2 ) + 2a(\textbf{r} \times \textbf{v}) + 2\textbf{r} \times (\textbf{r} \times \textbf{v}) \end{align}
方程(15)。
这正是GLM在四元数和vec3上实现其“*”运算符的方式:
template
GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(qua const& q, vec<3, T, Q> const& v)
{
vec<3, T, Q> const QuatVector(q.x, q.y, q.z);
vec<3, T, Q> const uv(glm::cross(QuatVector, v));
vec<3, T, Q> const uuv(glm::cross(QuatVector, uv));
return v + ((uv * q.w) + uuv) * static_cast(2);
}
https://gamedev.stackexchange.com/questions/201644
复制相似问题