19

关于任意点的旋转和平移

为了旋转/平移对象(仅围绕 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];

即使进行了以下更改,沿 +Y 的不良翻译仍然存在:

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

  2. zAngle = 0;

  3. ds = 0;

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

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

我需要帮助来理解为什么会发生这种不希望的翻译,转换到底出了什么问题,或者是算法有问题。

万向节锁在这里会成为问题吗?

请不要要求我执行/练习更简单的示例,因为我已经准备好了 Renderer 类,用于关于全局 z 轴的旋转/平移,而我所从事的这个新任务使用相同的类,并在updateModel()

(请注意,所需的旋转仅围绕 z 轴,平移仅在 xy 平面上)

[API 10->15]

实际的 Renderer 类有两个对象: tank turret(nozzle) 和 tank body,而 turret(nozzle) 有不想要的向前平移,body 有不想要的向后平移

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

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

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

对象的一部分(喷嘴/炮塔,主体)当前围绕它们自己的中心而不是对象的中心(即_playerCentre)旋转,稍后我将对其进行修改。

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

4

4 回答 4

5

看起来问题是:

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

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

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

我假设“_ModelMatrixBody”是一个 4x4 矩阵,“_uBodyCentre”是一个 4 元素向量,否则这些也可能有问题。

于 2012-08-24T07:05:26.150 回答
4

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

M = T * I * T[inv]

没有导致单位矩阵,所以而不是使用 Matrix.MultiplyMM

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

于 2012-11-25T10:31:14.877 回答
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]);
}

这就是我的看法,至少,我把你留给实施。我收集您的代码不会遭受万向节锁定。

于 2012-08-22T17:30:35.117 回答
3

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

我发现这是最简单的旋转方式,无需任何形式的万向节锁定或奇怪的平移。它是一个 iOS 示例,但我确信可以轻松应用于 android。它也用于 3d 旋转,但只需不绕其中一个轴旋转即可轻松应用于 2d。

于 2012-08-23T15:07:09.860 回答