C++ 如何找到从一个向量到另一个向量的正确旋转?
我有两个对象,每个对象有两个向量:C++ 如何找到从一个向量到另一个向量的正确旋转?,c++,opengl,rotation,quaternions,C++,Opengl,Rotation,Quaternions,我有两个对象,每个对象有两个向量: 法向量 上向量 如图所示: 上方向向量垂直于法向量。现在我想找到从一个物体到另一个物体的唯一旋转,怎么做 我有一种方法可以找到一个向量到另一个向量之间的旋转,它是有效的。问题是我需要考虑两个向量:法向量和上向量。如果我使用这种方法将法向量从对象1旋转到对象2的法向量,上向量可能指向错误的方向,它们需要平行 以下是查找最短旋转的代码: GE::Quat GE::Quat::fromTo(const Vector3 &v1, const Vector
- 法向量
- 上向量
GE::Quat GE::Quat::fromTo(const Vector3 &v1, const Vector3 &v2)
{
Vector3 a = Vector3::cross(v1, v2);
Quat q;
float dot = Vector3::dot(v1, v2);
if ( dot >= 1 )
{
q = Quat(0,0,0,1);
}
else if ( dot < -0.999999 )
{
Vector3 axis = Vector3::cross(Vector3(1,0,0),v2);
if (axis.length() == 0) // pick another if colinear
axis = Vector3::cross(Vector3(0,1,0),v2);
axis.normalize();
q = Quat::axisToQuat(axis,180);
}
else
{
float s = sqrt( (1+dot)*2 );
float invs = 1 / s;
Vector3 c = Vector3::cross(v1, v2);
q.x = c.x * invs;
q.y = c.y * invs;
q.z = c.z * invs;
q.w = s * 0.5f;
}
q.normalize();
return q;
}
GE::Quat GE::Quat::fromTo(常量向量3和v1,常量向量3和v2)
{
向量3 a=向量3::交叉(v1,v2);
quatq;
浮点点=矢量3::点(v1,v2);
如果(点>=1)
{
q=Quat(0,0,0,1);
}
否则如果(dot<-0.999999)
{
向量3轴=向量3::交叉(向量3(1,0,0),v2);
if(axis.length()==0)//选择另一个if共线
轴=向量3::交叉(向量3(0,1,0),v2);
axis.normalize();
q=Quat::axisToQuat(轴,180);
}
其他的
{
浮点数s=sqrt((1+点)*2);
浮动库存=1/s;
向量3 c=向量3::交叉(v1,v2);
q、 x=c.x*invs;
q、 y=c.y*invs;
q、 z=c.z*invs;
q、 w=s*0.5f;
}
q、 规范化();
返回q;
}
为了找到正确的旋转方向,我应该对该代码进行哪些更改/添加?在开始之前,我将假设上向量和法向量都是标准化的和正交的(点积为零) 假设您希望旋转黄色盘子,使其与玫瑰色(红色?)盘子对齐。所以,我们的参考是来自黄色板块的向量,我们将坐标系称为XYZ,其中Z->法线黄色向量,Y->向上黄色向量和X->YxZ(叉积) 同样,对于玫瑰盘,旋转坐标系将被称为X'Y'Z',其中Z'->法向玫瑰矢量,Y'->向上玫瑰矢量和X'->Y'xZ'(叉积) 好的,为了找到旋转矩阵,我们只需要确保我们的法向黄色向量将成为法向玫瑰向量;我们的向上黄色向量将在向上玫瑰向量中变换,以此类推,即:
RyellowTOrose = |X'x Y'x Z'x|
|X'y Y'y Z'y|
|X'z Y'z Z'z|
换句话说,在将任何基本体转换为黄色系统的坐标后,应用此转换将旋转它,使其与玫瑰坐标系对齐
如果上方向向量和法向量不正交,可以很容易地纠正其中一个。只需在法线和法线之间做叉积(为了方便起见,生成一个称为C的向量),然后再做一次C和法线之间的叉积,以纠正上向量。首先,我声明只有一个这样的变换可以对齐两个对象的方向。所以我们不必担心找到最短的 将要旋转的对象称为
a
,并将保持静止的对象称为b
。设x
和y
分别为a
的法向量和上向量,同样地,设u
和v
为b
的向量。我将假定x
,y
,u
和v
是单位长度,也就是说x
与y
正交,u
与v
正交。如果其中任何一个不是这样,可以编写案例代码来纠正这一点(通过平面投影和标准化)
现在,让我们构造定义“世界空间”的矩阵,即a
和b
的方向。(让^
表示叉积)将z
构造为x^y
,将c
构造为a^b
。将x
,y
,z
和a
,b
,c
写入每个矩阵的列,我们就得到了这两个矩阵,分别称它们为a
和b
。(这里的叉积给出了单位长度和相互正交的向量,因为操作数也是如此)
根据A
获得B
的坐标系变换的变化是A^-1
(矩阵A
的逆,其中^
表示指数的泛化),在这种情况下A^-1
可计算为A^T
,转置,因为A
是构造的正交矩阵。然后到B
的物理转换就是矩阵B
本身。因此,通过A^-1
,然后通过B
变换对象将得到所需的结果。但是,通过将右侧的B
乘以左侧的A^-1
,可以将这些转换连接为一个转换
最终得到该矩阵(假设没有算术错误):
四元数代码只将一个矢量旋转到另一个矢量,而不使用“向上”矢量 在您的例子中,只需从3个正交向量构建旋转矩阵
R1_to_R2 = R2 * R1.inversed()
矩阵R1到R2是从一个方向到另一个方向的变换矩阵。注意:这里的R1.inversed()可以替换为R1.transposed()如果这是一个愚蠢的问题,很抱歉,但是“最短旋转”和“唯一旋转”之间的区别是什么?也许我没有说清楚,很抱歉。我只想把法向量旋转到另一个法向量,但上方向向量也必须是正确的。如果我使用这个方法,
R1_to_R2 = R2 * R1.inversed()