我正在开发一个项目,我想生成一个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); }
}
}
有没有人有线索?
答案 0 :(得分:2)
你永远不想累积变换矩阵。这会在您的矩阵中引入错误,并导致诸如缩放或偏斜正交分量等问题。
正确的方法是跟踪累积俯仰,偏航,滚转角度。然后在每次更新时从这些角度重建变换矩阵。
答案 1 :(得分:1)
如果有机会:避免乘以旋转矩阵。跟踪累积旋转并在每一步计算新的旋转矩阵。
如果无法避免乘以旋转矩阵,则renormalize(第16页)。它对我来说很适合超过1万次乘法。
但是,我怀疑它不会帮助你,数字错误通常需要超过2个步骤来表现自己。在我看来,你的问题的原因是在其他地方。
偏航,俯仰和滚转不利于任意旋转。欧拉角受到奇点和不稳定性的影响。请看38:25(David Sachs的演讲)
祝你好运!答案 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。
HTH
答案 3 :(得分:0)
在黑暗中拍摄:我不知道您正在使用的编程语言的规则或名称,但此过程看起来很可疑:
void setIdentity() {
this.matrix = identityMatrix;
}
您确定要复印identityMatrix
吗?如果它只是您正在复制的引用,那么identityMatrix
将在以后的操作中被修改,很快就没有任何意义。
答案 4 :(得分:0)
尽管建议的矩阵重整化可能在实践中运行良好,但从数学的角度来看,它有点特殊。更好的方法是使用四元数表示累积旋转,四元数仅在应用时转换为旋转矩阵。四元数也会从正交性缓慢漂移(虽然速度较慢),但重要的是它们具有明确定义的重整化。
实现这一目标的良好开端信息可以是:
有用的学术参考可以是: