在OpenGL ES 2.0中使用矩阵旋转

7

编辑 - 添加更多的代码

尝试使用OpenGL ES 2.0正确旋转我的四边形时遇到了很多问题。

它似乎总是围绕屏幕坐标的中心旋转。 我正在尝试让它围绕自己的中心旋转(仅在z轴上,用于2D)。

我一直在使用Matrix.translate进行实验,如下所示。 但是,在此更改x或y位置仅会在屏幕上的不同位置绘制四边形,但当它旋转时,它再次围绕屏幕的中心旋转。 请问有人能解释一下如何使其围绕其自身的z轴旋转(像车轮一样)吗?

谢谢,这里是相关的代码行 - 如果需要更多,请询问,我会发布。(请注意,我查看了许多类似的SO和更广泛的互联网问题,但到目前为止我还没有找到答案。)

谢谢。

//Set rotation
Matrix.setRotateM(mRotationMatrix, 0, -angle, 0, 0, 1.0f);

//Testing translation
Matrix.translateM(mRotationMatrix, 0, -.5f, .5f, 0f);

// Combine the rotation matrix with the projection and camera view
Matrix.multiplyMM(mvpMatrix, 0, mRotationMatrix, 0, mvpMatrix, 0);

我的着色器(在类级别上声明)

private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +

"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";

private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";

从onSurfaceChanged开始

float ratio = (float) width / height;
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);

在我的onDrawFrame方法中

// Set the camera position (View matrix)
Matrix.setLookAtM(mVMatrix, 0, 0, 0, 3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

//Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
4个回答

5

我也遇到了同样的问题(看到了奇怪的扭曲和其他一切),我的解决方案基于下面的Android培训>使用OpenGL ES显示图形>添加动画

(如果需要,可以查看我的详细帖子:OpenGL ES Android矩阵变换。)

  1. mModelMatrix 设置为单位矩阵

    Matrix.setIdentityM(mModelMatrix, 0); // 初始化为单位矩阵
    
  2. mModelMatrix 应用平移变换

    Matrix.translateM(mModelMatrix, 0, -0.5f, 0, 0); // 向左平移
    
  3. mRotationMatrix 应用旋转变换(角度以度为单位)

    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
    
  4. 通过 Matrix.multiplyMM 结合旋转和平移变换

    mTempMatrix = mModelMatrix.clone();
    Matrix.multiplyMM(mModelMatrix, 0, mTempMatrix, 0, mRotationMatrix, 0);
    
  5. 将模型矩阵与投影矩阵和相机视图结合

    mTempMatrix = mMVPMatrix.clone();
    Matrix.multiplyMM(mMVPMatrix, 0, mTempMatrix, 0, mModelMatrix, 0);
    

区分运动和旋转(然后乘以两个矩阵)就可以解决问题。只需注意需要初始化旋转矩阵。 - Ruslan Yanchyshyn

4

这是一个演示。假设你要绘制一个茶壶...模型矩阵将从一个单位矩阵开始。形状以原点为中心,如下所示:

pre rotate and translate

在继续之前,请确认您所拥有的内容是否正确...

一旦您确认无误,应将旋转应用于模型矩阵,编译并运行 - 您将获得一个旋转后的副本...

rotated

一旦你有了这个,你就可以翻译:

rotated and translated

所以对于您来说,您需要做的只是验证旋转矩阵是否为单位矩阵,例如Matrix.setIdentityM(mRotationMatrix,0); ,如果形状不在中心,则将其移至中心。

一旦它在中心,应用旋转,例如:

    Matrix.setIdentityM( mRotationMatrix,0); 
    <as needed movement to center>

    Matrix.rotate(mRotationMatrix, 0, -angle, 0, 0, 1.0f);
    <any other translation you want>

分步骤操作可以让你的生活更轻松,这样你就能清楚地看到正在发生的事情。


嗨@paulczak - 谢谢你。问题是,当形状在中心时,它可以完美旋转(因为它的中心在屏幕中心)。但是,如果我将形状移动到左上角,那么它仍然会围绕中心旋转或“轨道”。我不确定如何翻译它,以使其保持在同一位置?所以当你说“一旦你有了这个,你就可以进行翻译” - 我想这就是我的问题所在,我不确定如何进行这种翻译?(代码顺序以及如何计算中心应该在哪里)。 - Zippy
你是否在每次调用onDrawFrame()时将旋转矩阵(用于模型变换)重置为单位矩阵? - paulczak
奇怪的是,如果我将翻译应用于mRotationMatrix并直接将该矩阵传递给着色器(在我的情况下声明为“uniform mat4 uRotate”,然后编辑我的着色器为“gl_Position = uRotate * a_position;\n”+(因此不使用uMVPMatrix),它似乎有点起作用。我说“有点”是因为我仍然会遇到我在其他问题中提到的扭曲问题(http://stackoverflow.com/questions/15836688/correct-vertex-shader-code-opengl-es-2-0),而且我不满意不使用uMVPMatrix,因为我知道它应该可以使用。我的代码肯定有问题!再次感谢任何帮助。 - Zippy
你可以将模型/视图/投影矩阵传递到着色器中,并像这样计算:gl_Position = ModelViewProjection*mVertex; 但是对于许多顶点(具有大量顶点的模型可能有数万个),这一系列乘法是相同的,因此通常将其作为MVP或M和VP提供给着色器,如果需要进行Phong光照,则会使用M和VP。因此,这是一个潜在的方法,运行速度较慢-是否在应用程序中看到它是另一个问题。 - paulczak
我将重新提出这个问题,因为我仍然有同样的问题 - 我会尝试更好地解决它。 - Zippy
显示剩余2条评论

0

通常旋转是围绕原点进行的,因此您希望在平移之前旋转四边形。如果您在平移后旋转,则四边形将首先从原点移开,然后围绕原点旋转。

如果不知道您的矩阵函数如何实现,我们无法建议您是否正确使用它们。您向我们展示的只是函数接口。

但一般来说,在平移之前旋转。


嗨@Sebby Johanns。感谢您的评论,我现在没有在翻译之前旋转吗?如果您能更详细地解释一下,我将不胜感激-我已经添加了一些代码-这足够了吗?如果您需要更多信息(以及您需要哪个部分),请告知-非常感谢! - Zippy
如果旋转的中心需要移动,而不是移动四边形,则需要先进行平移,然后旋转,最后再平移回来。 - mbeckish
@mbeckish感谢您的评论,我听过人们说“翻译并再翻译回来”,但我还没有完全理解它,我想您是指将x和y进行翻译,然后使用相反的值重新翻译(例如,1,1,然后是-1,-1) - 请编辑以展示一个例子?我尝试过这样做,但什么也没有。谢谢! - Zippy
是的,您想要将对象翻译成以原点为中心。如果您在0,0周围绘制了它,则可以从单位矩阵开始旋转,然后将旋转后的版本平移至所需位置。之后,您可以将模型、视图和投影矩阵相乘,以获得您将发送到着色器的统一变量(除非您正在进行光照,那么请分别发送MV和P,以便您可以正确计算阴影)。 - paulczak
translate到底应该做什么?是移动四边形的中心/枢轴点还是移动四边形本身?这是否是我需要的最佳方法?(基本上,我正在编写一个简单的2D游戏框架,所以只需要一种旋转精灵的方法) - Zippy
显示剩余3条评论

0

将您的操作向后应用:

第一步- Matrix.translateM(mRotationMatrix,0,-0.5f,0.5f,0f);

第二步- Matrix.setRotateM(mRotationMatrix,0,-angle,0,0,1.0f);

它将围绕自己的中心旋转


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接