Opengl 如何从参考';零';四元数与全局旋转四元数

Opengl 如何从参考';零';四元数与全局旋转四元数,opengl,math,rotation,tracking,quaternions,Opengl,Math,Rotation,Tracking,Quaternions,我在连接到flystick(3D跟踪对象)的屏幕上显示字符。我的目标是根据设备输入移动字符 我注意到设备的“零”(对应于默认位置)与我的字符的未旋转四元数不对应。移动设备时,我的角色会围绕设备以外的其他轴(可能是世界轴)移动。因此,我添加了一个同步功能,当我的设备应处于默认位置时,该功能会注册设备的四元数旋转,但现在我不知道如何将此参考四元数与设备移动时收到的实际四元数相结合,以便按照我的意愿旋转我的角色 以下是我如何在OpenGL中使用四元数: glm::quat rotation = QAc

我在连接到flystick(3D跟踪对象)的屏幕上显示字符。我的目标是根据设备输入移动字符

我注意到设备的“零”(对应于默认位置)与我的字符的未旋转四元数不对应。移动设备时,我的角色会围绕设备以外的其他轴(可能是世界轴)移动。因此,我添加了一个同步功能,当我的设备应处于默认位置时,该功能会注册设备的四元数旋转,但现在我不知道如何将此参考四元数与设备移动时收到的实际四元数相结合,以便按照我的意愿旋转我的角色

以下是我如何在OpenGL中使用四元数:

glm::quat rotation = QAccumulative.getQuat(); 
glm::mat4 matrix_rotation = glm::mat4_cast(rotation);
object_transform *= matrix_rotation;
Model *= object_transform;
glm::mat4 MVP = Projection * View * Model;  
如果使用此方法旋转对象,键盘和鼠标可以正常工作:

rotate(float angleX,float angleY,float angleZ) {
  Quaternion worldRotationx( 1.0,0,0, angleZ);   
  Quaternion worldRotationy( 0,1.0,0, angleX);      
  Quaternion worldRotationz( 0,0,1.0, angleY);        
  QAccumulative = worldRotationx * worldRotationy * worldRotationz * QAccumulative;
  QAccumulative.normalise();
}
这里是主循环,我在这里计算来自跟踪设备的数据:

void VRPN_CALLBACK handle_tracker(void* userData, const vrpn_TRACKERCB t ) {
  Vrpn_tracker* current = Vrpn_tracker::current_vrpn_device;
  if (current->calibrating == true) {
    current->reference = Quaternion(t.quat[0],t.quat[1],t.quat[2],t.quat[3]);
    current->reference.normalise();
  } else {
    // translation :
    current->newPosition = sf::Vector3f(t.pos[0],t.pos[1],t.pos[2]);
    current->world->current_object->translate(
      current->newPosition.x - current->oldPosition.x,
      current->newPosition.y - current->oldPosition.y,
      current->newPosition.z - current->oldPosition.z);
    current->oldPosition = current->newPosition;

    // rotation:
    current->newQuat = Quaternion(t.quat[0],t.quat[1],t.quat[2],t.quat[3]);
    current->newQuat.normalise();
    current->world->current_object->QAccumulative = 
      (current->reference.getConjugate() * current->newQuat);
    Quaternion result = current->world->current_object->QAccumulative;
    cout << "result? : " << result.x << result.y << result.z << result.w << endl; 
    // prints something like:
    // x : -0.00207066 y : 0.00186546 z : -0.00165524 w : 0.999995 
    // when position of flystick = default position
  }
}
void VRPN\u回调句柄\u跟踪器(void*userData,const VRPN\u TRACKERCB t){
Vrpn_跟踪器*电流=Vrpn_跟踪器::电流Vrpn_设备;
如果(当前->校准==真){
当前->参考=四元数(t.quat[0],t.quat[1],t.quat[2],t.quat[3]);
当前->参考.标准化();
}否则{
//翻译:
current->newPosition=sf::Vector3f(t.pos[0],t.pos[1],t.pos[2]);
当前->世界->当前对象->翻译(
当前->新位置.x-当前->旧位置.x,
当前->新位置.y-当前->旧位置.y,
当前->新位置.z-当前->旧位置.z);
当前->旧位置=当前->新位置;
//轮换:
当前->新四元数=四元数(t.quat[0],t.quat[1],t.quat[2],t.quat[3]);
当前->newQuat.normalise();
当前->世界->当前对象->QAccumulative=
(current->reference.getConjugate()*current->newQuat);
四元数结果=当前->世界->当前对象->累积;

不能改变乘法顺序。如果你先旋转,比最后旋转,比先旋转

您问题的隐藏问题,我们不知道您的转换符号


您的旋转可以从世界到对象帧或从对象到世界。根据符号的不同,精确的变换会有所不同。

您可能会对飞杆进行不同的校准,这可能符合您的预期,但是我建议您仔细阅读关于飞杆的文档,您的答案是:我不在那里。
如果您使用的是艺术追踪,用户手册第124页将为您提供帮助。

人们没有回答是因为我的问题不清楚还是因为没有明显的答案?请让我知道我应该添加哪些内容以获得帮助。嗯,我不是100%确定。但让我大声思考。您以您认为合适的方向握住飞行杆对于默认方向,跟踪系统报告方向R。您希望获得这种情况下的身份转换,因此您应该将R的倒数,即R^-1,应用于所有跟踪方向输入X,即X'=R^-1*X,以便对于X=R=>X'=i。@derhass我不确定如何计算R^-1,wikipedia article似乎告诉我应该组合几个结构,但是没有一个通用的公式吗?四元数的逆是非常简单的。参见.GLM还有一个
逆()
method for quaternions.@derhass所以我尝试了你所说的,我做了ref-1*newQuat,但结果quat看起来不像identity,我发布了相应的代码。我试图围绕对象的轴旋转,所以这就是你从世界到对象的调用。我确实在使用艺术,让我看看这个。