适当的矩阵乘法用于旋转/平移

时间:2012-08-15 07:33:56

标签: android opengl-es opengl-es-2.0 linear-algebra

Rotation and Translation about arbitrary point

为了旋转/平移物体(仅绕z轴旋转和仅在xy平面上平移)不仅仅是到全局中心(设备中心)而且还有其他任意点,我创建了一个算法,这是正确的(因为我讨论过的所有高级编码器都认为它是正确的,需要花费大量时间来删除实现中的不需要的翻译(算法是在8月4日创建的并在同一天实施,从那以后代码已经修改了15次。

以下是实施 http://www.pixdip.com/opengles/transform.php#ALGO1

产生不需要的翻译的代码行在里面:

private static void updateModel(int upDown, float xAngle, float yAngle, float zAngle) {

并列出如下:

  1. Matrix.multiplyMV(GLES20Renderer._uBodyCentreMatrix, 0, GLES20Renderer._ModelMatrixBody, 0, GLES20Renderer._uBodyCentre, 0);

  2. objX = GLES20Renderer._uBodyCentreMatrix[0];

  3. objY = GLES20Renderer._uBodyCentreMatrix[1];

  4. 即使进行了以下更改,+ Y上的非意外翻译仍然存在:

    1. objY = _uBodyCentreMatrix[1] - _uBodyCentre[1];

    2. zAngle = 0;

    3. ds = 0;

    4. 由于Renderer类的这些字段,每次调用-0.545867f时,值onDrawFrame()都会添加到Y坐标:

      private static final float[] _uBodyCentre = new float[]{-0.019683f, -0.545867f, -0.000409f, 1.0f};

      protected static float[] _uBodyCentreMatrix = new float[4];

      http://www.pixdip.com/opengles/transform.php#FIELDS

      中的

      我需要帮助才能理解为什么会发生不受欢迎的翻译,转换的确切错误,或者算法是错误的。

      Gimbal锁定会成为问题吗?

      请不要让我执行/练习更简单的示例,因为我已经为全局z轴准备了旋转/翻译的Renderer类,而我所进入的这个新任务使用了同一个类,稍加修改{ {1}}

      (请注意,所需的旋转仅约为z轴,仅在xy平面内平移)

      [API 10-> 15]

      实际的渲染器类有两个对象:坦克炮塔(喷嘴)和坦克身体,而炮塔(喷嘴)有不希望的向前平移,身体有不受欢迎的向后翻译

      关于设备中心翻译/轮换的Apk(在opengles 2.0中很容易制作): http://www.pixdip.com/opengles/global.php

      Apk用于关于任意点的平移/旋转(沿+ Y有不希望的平移): http://www.pixdip.com/opengles/local.php

      关于任意点的转换/旋转的Apk,其中up​​dateModel()仅被调用4次: http://www.pixdip.com/opengles/limited.php 和所需的代码(应该足够)在这里:http://www.pixdip.com/opengles/code.php

      物体的一部分(喷嘴/炮塔,车身)当前正在围绕它们自己的中心而不是物体的中心(即_playerCentre)旋转,我稍后会修改它。

      我试图演示逻辑 http://www.pixdip.com/opengles/images.php

4 个答案:

答案 0 :(得分:5)

看起来问题是:

Matrix.multiplyMV(GLES20Renderer._uBodyCentreMatrix, 0, GLES20Renderer._ModelMatrixBody, 0, GLES20Renderer._uBodyCentre, 0);

Matrix.multiplyMV是一种将4元素向量乘以4x4矩阵并将结果存储在4元素列向量中的方法。在矩阵表示法中:result = lhs x rhs。如果resultVector元素与lhsMatrix或rhsVector元素重叠,则resultVector元素值是未定义的。

我认为你没有发布所有代码所以我无法确认,但是根据你的'_BodyCentreMatrix'的命名来判断你可能遇到错误,因为它不是4元素列向量。

我假设'_ModelMatrixBody'是4x4矩阵而'_uBodyCentre'是4元素矢量,否则这些也可能有问题。

答案 1 :(得分:4)

[解决] java浮点错误是唯一的原因

M = T * I * T [inv]

没有导致身份矩阵, 所以不要使用Matrix.MultiplyMM

我输入矩阵之间的所有乘法

答案 2 :(得分:3)

你可以使用这样的方法:

public void rotateToAbritrary(float[] arbitraryPoint, float xAngle, float yAngle, float zAngle) {
    Matrix.translateM(modelMatrix, 0, arbitraryPoint[0], arbitraryPoint[1], arbitraryPoint[2]);
    float max = Math.max(xAngle, Math.max(yAngle, zAngle));
    if(max != 0.0f) Matrix.rotateM(modelMatrix, 0, max, xAngle / max, yAngle / max, zAngle / max);
    Matrix.translateM(modelMatrix, 0, -arbitraryPoint[0], -arbitraryPoint[1], -arbitraryPoint[2]);
}

这就是我看到它的方式,至少,我让你参与实施。我收集你的代码并没有遭受万向节的锁定。

答案 3 :(得分:3)

http://tutorialrandom.blogspot.com/2012/08/how-to-rotate-in-3d-using-opengl-proper.html

我发现这是进行旋转的最简单方法,而不会获得任何类型的万向节锁定或奇怪的翻译。它是一个iOS示例,但我肯定可以很容易地应用到Android。它也适用于3d旋转,但只需不旋转一个轴即可轻松应用于2d。