3D旋转矩阵在Processing / Java中随时间变形

时间:2011-04-26 18:43:25

标签: matrix rotation processing transformation

我正在开发一个项目,我想生成一个3D网格来表示一定数量的数据。

要创建这个网格我想使用转换矩阵,所以我根据几个网站上的数学算法创建了一个类。

一切似乎都有效,缩放/平移但是只要我在其x轴上旋转网格,它就会在2到3次完整旋转后开始变形。感觉我的比例值正在增加,这会改变我的网格。我正在努力解决这个问题几天,但我无法弄清楚出了什么问题。

为了更清楚,您可以下载我的完整设置here

我定义了一个框的坐标,并在将它们写入屏幕之前将它们放入变换矩阵

这是旋转对象的公式

    void appendRotation(float inXAngle, float inYAngle, float inZAngle, PVector inPivot ) {

    boolean setPivot = false;

    if (inPivot.x != 0 || inPivot.y != 0 || inPivot.z != 0) {
        setPivot = true;
    }

    // If a setPivot = true, translate the position
    if (setPivot) {

        // Translations for the different axises need to be set different
        if (inPivot.x != 0) { this.appendTranslation(inPivot.x,0,0); }
        if (inPivot.y != 0) { this.appendTranslation(0,inPivot.y,0); }
        if (inPivot.z != 0) { this.appendTranslation(0,0,inPivot.z); }

    }

    // Create a rotationmatrix
    Matrix3D rotationMatrix = new Matrix3D();

    // xsin en xcos
    float xSinCal = sin(radians(inXAngle));
    float xCosCal = cos(radians(inXAngle));      
    // ysin en ycos
    float ySinCal = sin(radians(inYAngle));
    float yCosCal = cos(radians(inYAngle));     
    // zsin en zcos
    float zSinCal = sin(radians(inZAngle));
    float zCosCal = cos(radians(inZAngle));           

    // Rotate around x
    rotationMatrix.setIdentity();
    // --
    rotationMatrix.matrix[1][1] = xCosCal;
    rotationMatrix.matrix[1][2] = xSinCal;
    rotationMatrix.matrix[2][1] = -xSinCal;
    rotationMatrix.matrix[2][2] = xCosCal;
    // Add rotation to the basis matrix
    this.multiplyWith(rotationMatrix);

    // Rotate around y
    rotationMatrix.setIdentity();
    // --
    rotationMatrix.matrix[0][0] = yCosCal;
    rotationMatrix.matrix[0][2] = -ySinCal;
    rotationMatrix.matrix[2][0] = ySinCal;
    rotationMatrix.matrix[2][2] = yCosCal;
    // Add rotation to the basis matrix
    this.multiplyWith(rotationMatrix);

    // Rotate around z
    rotationMatrix.setIdentity();
    // --
    rotationMatrix.matrix[0][0] = zCosCal;
    rotationMatrix.matrix[0][1] = zSinCal;
    rotationMatrix.matrix[1][0] = -zSinCal;
    rotationMatrix.matrix[1][1] = zCosCal;
    // Add rotation to the basis matrix
    this.multiplyWith(rotationMatrix);

    // Untranslate the position
    if (setPivot) {

        // Translations for the different axises need to be set different
        if (inPivot.x != 0) { this.appendTranslation(-inPivot.x,0,0); }
        if (inPivot.y != 0) { this.appendTranslation(0,-inPivot.y,0); }
        if (inPivot.z != 0) { this.appendTranslation(0,0,-inPivot.z); }

    }

}

有没有人有线索?

5 个答案:

答案 0 :(得分:2)

你永远不想累积变换矩阵。这会在您的矩阵中引入错误,并导致诸如缩放或偏斜正交分量等问题。

正确的方法是跟踪累积俯仰,偏航,滚转角度。然后在每次更新时从这些角度重建变换矩阵。

答案 1 :(得分:1)

如果有机会:避免乘以旋转矩阵。跟踪累积旋转并在每一步计算新的旋转矩阵。

如果无法避免乘以旋转矩阵,则renormalize(第16页)。它对我来说很适合超过1万次乘法。

但是,我怀疑它不会帮助你,数字错误通常需要超过2个步骤来表现自己。在我看来,你的问题的原因是在其他地方。

偏航,俯仰和滚转不利于任意旋转。欧拉角受到奇点和不稳定性的影响。请看38:25(David Sachs的演讲)

http://www.youtube.com/watch?v=C7JQ7Rpwn2k

祝你好运!

答案 2 :(得分:1)

正如@don提到的那样,尽量避免累积转换,因为你可能遇到各种各样的问题。一次旋转一个轴可能会导致Gimbal Lock问题。尝试一次完成所有轮换。

另外,请记住,Processing附带了它自己的名为PMatrix3D的Matrix3D类,它有一个rotate()方法,它采用一个角度(弧度)和旋转轴的x,y,z值

这是一个旋转一堆PVectors的示例函数:

PVector[] rotateVerts(PVector[] verts,float angle,PVector axis){
  int vl = verts.length;
  PVector[] clone = new PVector[vl];
  for(int i = 0; i<vl;i++) clone[i] = verts[i].get();
  //rotate using a matrix
  PMatrix3D rMat = new PMatrix3D();
  rMat.rotate(angle,axis.x,axis.y,axis.z);
  PVector[] dst = new PVector[vl];
  for(int i = 0; i<vl;i++) {
    dst[i] = new PVector();
    rMat.mult(clone[i],dst[i]);
  }
  return dst;
}

这是使用它的example

rotation matrix

HTH

答案 3 :(得分:0)

在黑暗中拍摄:我不知道您正在使用的编程语言的规则或名称,但此过程看起来很可疑:

void setIdentity() {  
    this.matrix = identityMatrix;
}

您确定要复印identityMatrix吗?如果它只是您正在复制的引用,那么identityMatrix将在以后的操作中被修改,很快就没有任何意义。

答案 4 :(得分:0)

尽管建议的矩阵重整化可能在实践中运行良好,但从数学的角度来看,它有点特殊。更好的方法是使用四元数表示累积旋转,四元数仅在应用时转换为旋转矩阵。四元数也会从正交性缓慢漂移(虽然速度较慢),但重要的是它们具有明确定义的重整化。

实现这一目标的良好开端信息可以是:

有用的学术参考可以是:

  • ķ。 Shoemake,“用四元数曲线制作旋转动画”,ACM SIGGRAPH Comput。图。,卷。 19,没有。 3,pp.245-254,1985。DOI:10.1145 / 325165.325242