我正在关注Android上的OpenGL es旋转示例,以便在我的Android App上旋转一个简单的方块(不是多维数据集),例如此代码:
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y
gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f); //Z
如果只围绕一个轴旋转,它可以正常工作。
但是如果围绕一个轴旋转,之后,围绕另一个轴旋转,则旋转不公平。我的意思是旋转是围绕基础(全局)坐标系的轴而不是方形自己的坐标系完成的。
编辑 Shahbaz
的代码public void onDrawFrame(GL10 gl) {
//Limpiamos pantalla y Depth Buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
//Dibujado
gl.glTranslatef(0.0f, 0.0f, z); //Move z units into the screen
gl.glScalef(0.8f, 0.8f, 0.8f); //Escalamos para que quepa en la pantalla
//Rotamos sobre los ejes.
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y
gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f); //Z
//Dibujamos el cuadrado
square.draw(gl);
//Factores de rotación.
xrot += xspeed;
yrot += yspeed;
}
广场的绘制:
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW);
//gl.glEnable(GL10.GL_BLEND);
//Bind our only previously generated texture in this case
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
//Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
//Enable vertex buffer
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//gl.glDisable(GL10.GL_BLEND);
}
VERTEX BUFFER VALUES:
private FloatBuffer vertexBuffer;
private float vertices[] =
{
-1.0f, -1.0f, 0.0f, //Bottom Left
1.0f, -1.0f, 0.0f, //Bottom Right
-1.0f, 1.0f, 0.0f, //Top Left
1.0f, 1.0f, 0.0f //Top Right
};
.
.
.
public Square(int resourceId) {
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
.
.
.
答案 0 :(得分:24)
首先你应该知道的是,在OpenGL中,转换矩阵是从右边乘以的。这是什么意思?这意味着您编写的最后一个转换首先应用于对象。
让我们来看看你的代码:
gl.glScalef(0.8f, 0.8f, 0.8f);
gl.glTranslatef(0.0f, 0.0f, -z);
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y
gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f); //Z
gl.glTranslatef(0.0f, 0.0f, z);
square.draw(gl);
这意味着,首先,对象被移动到(0.0f, 0.0f, z)
。然后它围绕Z旋转,然后围绕Y旋转,然后围绕X旋转,然后移动(0.0f, 0.0f, -z)
并最终缩放。
你有正确的缩放比例。你把它放在第一位,所以最后应用它。你也有了
gl.glTranslatef(0.0f, 0.0f, -z);
在正确的位置,因为您首先想要旋转对象然后移动它。请注意,旋转对象时,它始终围绕基本坐标旋转,即(0,0,0)。如果要围绕自己的轴旋转对象,则对象本身应该在(0,0,0)中。
所以,就在你写
之前square.draw(gl);
你应该有轮换。你的代码现在的方式,你移动对象远(通过写
gl.glTranslatef(0.0f, 0.0f, z);
在square.draw(gl);
之前然后旋转会让事情变得混乱。删除该行可以让您更接近您的需求。所以,你的代码看起来像这样:
gl.glScalef(0.8f, 0.8f, 0.8f);
gl.glTranslatef(0.0f, 0.0f, -z);
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y
gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f); //Z
square.draw(gl);
现在广场应该旋转到位。
注意:运行此操作后,您将看到方块的旋转相当笨拙。例如,如果绕z旋转90度,则围绕x旋转看起来像是因为前一次旋转而绕y旋转。现在,这对你来说可能没问题,但是如果你想让它看起来真的很好,你应该这样做:
想象一下,你不是在旋转物体,而是围绕物体旋转相机,看着物体。通过更改xrot
,yrot
和zrot
,您可以将相机移动到围绕对象的球体上。然后,一旦找到相机的位置,您可以进行数学计算并获得正确的参数来调用glRotatef
和glTranslatef
,或使用gluLookAt
。
这需要对数学和3d想象力有所了解。因此,如果你在第一天没有做好,不要感到沮丧。
编辑:这是如何沿旋转的对象坐标旋转的想法;
首先,假设您围绕z进行旋转。因此你有
gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f); //Z
现在,全局Y单位向量显然是(0,1,0),但是对象已经旋转,因此其 Y单位向量也已旋转。该向量由下式给出:
[cos(zrot) -sin(zrot) 0] [0] [-sin(zrot)]
[sin(zrot) cos(zrot) 0] x [1] = [ cos(zrot)]
[0 0 1] [0] [ 0 ]
因此,你在y周围的旋转应该是这样的:
gl.glRotatef(yrot, -sin(zrot), cos(zrot), 0.0f); //Y-object
到目前为止你可以尝试这个(禁用x周围的旋转)并看到它看起来像你想要它的方式(我做了,它工作)。
现在对于x来说,它变得非常复杂。为什么?因为,X单位向量不仅首先围绕z向量旋转,而且在围绕(-sin(zrot), cos(zrot), 0)
向量旋转之后旋转。
所以现在对象的cooridnate中的X单位向量是
[cos(zrot) -sin(zrot) 0] [1] [cos(zrot)]
Rot_around_new_y * [sin(zrot) cos(zrot) 0] x [0] = Rot_around_new_y * [sin(zrot)]
[0 0 1] [0] [0 ]
让我们调用这个向量(u_x,u_y,u_z)。然后你的最终轮换(X周围的轮换)将是这样的:
gl.glRotatef(xrot, u_x, u_y, u_z); //X-object
原来如此!如何找到矩阵Rot_around_new_y
?有关围绕任意轴的旋转,请参阅here。转到6.2节,第一个矩阵,得到3 * 3子矩阵旋转(忽略与翻译有关的最右边的列)并将(-sin(zrot), cos(zrot), 0)
作为(u, v, w)
轴并theta
} yrot
。
我不会在这里做数学,因为它需要付出很多努力,最终我会在那里的某个地方犯错误。但是,如果你非常小心并准备好多次检查它们,你可以把它写下来并进行矩阵乘法。
附加说明:计算Rot_around_new_y
的一种方法也可能是使用Quaternions。四元数定义为4d向量[xs, ys, zs, c]
,对应于[x, y, z]
周围的sin
为s
且其cos
为{{1}的角度}}
此c
是我们的“新Y”,即[x, y, z]
。角度为[-sin(zrot), cos(zrot), 0]
。因此围绕Y旋转的四元数为:
yrot
最后,如果您有四元数q_Y = [-sin(zrot)*sin(yrot), cos(zrot)*sin(yrot), 0, cos(yrot)]
,则相应的旋转矩阵is given as:
[a, b, c, d]
答案 1 :(得分:3)
我对openGL几乎一无所知,但我想转换为0,旋转然后翻译应该有效......
gl.glTranslatef(-x, -y, -z);
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y
gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f); //Z
gl.glTranslatef(x, y, z);
答案 2 :(得分:3)
我认为你需要四元数才能做你想做的事。使用关于坐标轴的旋转在某些时候起作用,但最终会受到“万向节锁定”的影响。当您想要的旋转靠近坐标轴时会发生这种情况,并且当轴周围所需的旋转接近180度时会产生不必要的回转。
四元数是一个数学对象,表示围绕定义为3D矢量的任意轴的旋转。要在openGL中使用它,您可以从四元数生成矩阵并将其乘以模型视图矩阵。这将转换您的世界坐标,以便旋转方形。
您可以在此处获取更多信息http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation
我有一个Quaternion C ++类,如果有帮助我可以发给你。
答案 3 :(得分:0)
尝试添加
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
在旋转的单个多维数据集的渲染代码之前,然后
glPopMatrix();
渲染完成后。它将为您提供额外的视图矩阵,而不会影响您的主要模型视图矩阵。
基本上它的作用是创建一个新的模型视图相机,渲染,然后销毁它。