我遵循OpenGL es旋转示例从谷歌旋转一个简单的正方形(不是一个立方体)在我的Android应用程序,例如这个代码:
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);
}
顶点缓冲区值:
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);
.
.
.
5条答案
按热度按时间ljsrvy3e1#
首先你应该知道的是,在OpenGL中,变换矩阵是从右开始相乘的。这意味着什么?这意味着你最后写的变换首先应用到对象上。
让我们看看您的代码:
这意味着,首先将对象移动到
(0.0f, 0.0f, z)
,然后围绕Z旋转,再围绕Y旋转,再围绕X旋转,然后移动(0.0f, 0.0f, -z)
,最后缩放。你的缩放比例是对的。你把它放在第一位,所以它最后应用。你还得到了
在正确的位置,因为您首先要旋转对象,然后再移动它。请注意,当您旋转对象时,它总是绕着基准坐标旋转,即(0,0,0)。如果您要绕着它自己的轴旋转对象,对象本身应该在(0,0,0)中。
所以在你写之前
你应该有旋转。你的代码现在的方式,你移动对象远(通过写
在
square.draw(gl);
之前),然后旋转,这会把事情搞得一团糟。删除这一行会让你更接近你所需要的。所以,你的代码看起来像这样:现在,正方形应旋转到位。
**注意:**执行此程式后,您会发现正方形的旋转会相当不方便。例如,如果您绕z旋转90度,则绕x旋转会因为之前的旋转而看起来像绕y旋转。目前而言,这对您来说可能没问题,但如果您想让它看起来很好,您应该这样做:
想象一下,你不是在旋转物体,而是在物体周围旋转摄像机,看着物体。通过改变
xrot
,yrot
和zrot
,你是在物体周围的球体上移动摄像机。然后,一旦找到摄像机的位置,你可以做数学运算,得到正确的参数来调用glRotatef
和glTranslatef
,或者,请使用gluLookAt
。这需要一定的数学知识和3D想象力,所以如果你第一天没做好,不要沮丧。
**编辑:**这是如何沿着旋转对象坐标旋转的想法;
首先,假设你绕z旋转。因此你有
现在,全局Y单位向量显然是(0,1,0),但是对象已经旋转,因此其Y单位向量也已经旋转。
因此,你绕y的旋转,应该是这样的:
到目前为止,您可以尝试这种方法(禁用围绕x的旋转),并看到它看起来像您想要的方式(我这样做了,它的工作)。
现在对于x,它变得非常复杂,为什么呢?因为,X单位向量不仅首先绕z向量旋转,而且是在绕
(-sin(zrot), cos(zrot), 0)
向量旋转之后。所以现在物体坐标中的X单位向量是
我们把这个矢量叫做(u_x,u_y,u_z)。那么你的最终旋转(绕X的旋转)将是这样的:
那么!如何找到矩阵
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]
旋转一个Angular ,该Angular 的sin
是s
,并且其cos
是c
。这个
[x, y, z]
是我们的“新Y”,即[-sin(zrot), cos(zrot), 0]
。Angular 是yrot
。因此,绕Y旋转的四元数给出为:最后,如果您有四元数
[a, b, c, d]
,则相应的旋转矩阵如下:0qx6xfy62#
我对openGL几乎一无所知,但我想翻译成0,旋转,然后翻译回来应该工作...
pnwntuvh3#
我认为你需要四元数来做你想做的事情。使用绕坐标轴的旋转在某些时候是可行的,但最终会受到“万向节锁定”的困扰。当你想要的旋转经过坐标轴附近时,会发生这种情况,并在绕轴所需的旋转接近180度时产生不必要的回转。
四元数是一个数学对象,它表示围绕定义为3D矢量的任意轴的旋转。要在openGL中使用它,您可以从四元数生成一个矩阵,并将其乘以模型视图矩阵。这将转换您的世界坐标,以便旋转正方形。
您可以在这里获得更多信息http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation
我有一个四元数C++类,我可以发送给你,如果它有助于。
dz6r00yl4#
尝试添加
在要旋转的单个立方体的渲染代码之前,然后
它会给予你一个额外的视图矩阵来使用,而不会影响你的主模型视图矩阵。
本质上,这是创建一个新的模型视图摄影机,渲染,然后销毁它。
sdnqo3pr5#
我用的是opentk,不过还是一样的。首先移动对象的一半尺寸,然后旋转并移回来: