将旋转矩阵重新映射到不同的轴系统

时间:2011-05-01 03:27:09

标签: android matrix ogre3d remap

我在c ++程序中使用了android getRotationMatrix的改编版本,该程序通过网络读取手机的传感器数据并计算设备的矩阵。

该功能正常工作并计算设备的方向。不幸的是,Ogre3d的轴系统与设备不同。因此,即使围绕x轴的旋转工作正常,y轴和z轴也是错误的。保持设备级别并指向北(单位矩阵)。当我投球时,旋转是正确的。但是当我滚动和偏转时,旋转是交替的。滚动在Ogre3d中偏航,反之亦然。

    (Ogre3d)                         ([Device][5])

   ^ +y-axis                       ^ +z-axis                                  
   *                               *                                 
   *                               *                                 
   *                               *    ^ +y-axis                             
   *                               *   *                               
   *                               *  *                                
   *                               * *                                 
   ************> + x-axis          ************> +x-axis                      
  *                                                                   
 *                                                                    
v +z-axis                                                                     

快速浏览两轴系统看起来像Ogre的系统(左侧)基本上是设备的系统绕x轴逆时针旋转90度。

在计算矩阵之前,我尝试使用各种组合进行实验,但是没有任何组合可以正常工作。我如何确保旋转矩阵getRotationMatrix()在Ogre3D上正确显示?

For Reference这里是计算矩阵的函数:

bool getRotationMatrix() {
    //sensor data coming through the network are 
    //stored in accel(accelerometer) and mag(geomagnetic)
    //vars which the function has access to
    float Ax = accel[0]; float Ay = accel[1];   float Az = accel[2];
    float Ex = mag[0];   float Ey = mag[1];     float Ez = mag[2];

    float Hx = Ey * Az - Ez * Ay;
    float Hy = Ez * Ax - Ex * Az;
    float Hz = Ex * Ay - Ey * Ax;
    float normH = (float) Math::Sqrt(Hx * Hx + Hy * Hy + Hz * Hz);
    if (normH < 0.1f) {
        // device is close to free fall (or in space?), or close to
        // magnetic north pole. Typical values are  > 100.
        return false;
    }
    float invH = 1.0f / normH;
    Hx *= invH;
    Hy *= invH;
    Hz *= invH;
    float invA = 1.0f / (float) Math::Sqrt(Ax * Ax + Ay * Ay + Az * Az);
    Ax *= invA;
    Ay *= invA;
    Az *= invA;
    float Mx = Ay * Hz - Az * Hy;
    float My = Az * Hx - Ax * Hz;
    float Mz = Ax * Hy - Ay * Hx;

    //ogre3d's matrix3 is column-major whereas getrotatinomatrix produces
    //a row-major matrix thus i have tranposed it here
    orientation[0][0] = Hx; orientation[0][2] = Mx; orientation[0][2] = Ax;
    orientation[1][0] = Hy; orientation[1][3] = My; orientation[1][2] = Ay;
    orientation[2][0] = Hz; orientation[2][4] = Mz; orientation[2][2] = Az;

    return true;
}

3 个答案:

答案 0 :(得分:1)

为什么不在ogre中使用之前添加一个已经识别的额外旋转?

答案 1 :(得分:1)

我发现了问题。在我的函数中,单位向量在我将它们放在列中的交叉乘积之后计算,而我应该像往常一样将它们放入指定的matrix3单元格中的行中。虽然我指的是2d [] []中的元素,但关于行主和列主要的东西让我很困惑。

将矩阵计算函数的结果乘以该矩阵:

1 0 0

0 0 1

0 -1 0

然后用轴的另一个p / 2来调整整个结果解决了重映射问题,但我担心我的几何是倒置的。

答案 2 :(得分:0)

我对Matrix Rotation知之甚少,但是如果系统像您正在展示的那样旋转,我认为您应该执行以下操作:

X轴保持相同的方式,所以:

float Ax = accel[0];
float Ex = mag[0];

(Ogre3d)中的Y轴是([设备] [5])中的Z轴,所以:

float Ay = accel[2];
float Ey = mag[2];

(Ogre3d)中的Z轴是([Device] [5])中Y轴的对位,所以:

float Az = accel[1] * (-1);
float Ez = mag[1] * (-1);

试试