我正在跟踪谷歌的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
Run Code Online (Sandbox Code Playgroud)
如果只绕一个轴旋转,它可以正常工作.
但是,如果围绕一个轴旋转,然后围绕另一个轴旋转,则旋转不公平.我的意思是旋转是围绕基础(全局)坐标系的轴而不是方形自己的坐标系完成的.
编辑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;
}
Run Code Online (Sandbox Code Playgroud)
平方的绘制:
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);
}
Run Code Online (Sandbox Code Playgroud)
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);
.
.
.
Run Code Online (Sandbox Code Playgroud)
Sha*_*baz 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);
Run Code Online (Sandbox Code Playgroud)
这意味着,首先,将对象移动到(0.0f, 0.0f, z).然后它绕Z旋转,然后绕Y旋转,然后绕X旋转,然后移动(0.0f, 0.0f, -z)并最终缩放.
你得到了正确的缩放.你把它放在第一位,所以最后应用它.你也有
gl.glTranslatef(0.0f, 0.0f, -z);
Run Code Online (Sandbox Code Playgroud)
在正确的地方,因为你首先想要旋转对象然后移动它.请注意,旋转对象时,它始终围绕基本坐标旋转,即(0,0,0).如果要围绕其自己的轴旋转对象,则对象本身应位于(0,0,0)中.
所以,就在你写作之前
square.draw(gl);
Run Code Online (Sandbox Code Playgroud)
你应该有轮换.你的代码现在的方式,你移动对象远(写作
gl.glTranslatef(0.0f, 0.0f, z);
Run Code Online (Sandbox Code Playgroud)
之前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);
Run Code Online (Sandbox Code Playgroud)
现在广场应该旋转到位.
注意:运行此操作后,您将看到方块的旋转相当笨拙.例如,如果绕z旋转90度,则围绕x旋转看起来像是因为前一次旋转而绕y旋转.现在,这对你来说可能没问题,但是如果你想看起来真的很好,你应该这样做:
想象一下,你不是在旋转物体,而是围绕物体旋转相机,看着物体.通过更改xrot,yrot并且zrot您将相机移动到围绕对象的球体上.然后,一旦找到相机的位置,您可以进行数学计算并获得正确的参数来调用glRotatef和/ glTranslatef或使用gluLookAt.
这需要对数学和3D想象有所了解.因此,如果您在第一天没有做到正确,请不要感到沮丧.
编辑:这是如何沿旋转的对象坐标旋转的想法;
首先,假设您在z周围进行旋转.所以你有
gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f); //Z
Run Code Online (Sandbox Code Playgroud)
现在,全局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 ]
Run Code Online (Sandbox Code Playgroud)
因此,你绕y旋转应该是这样的:
gl.glRotatef(yrot, -sin(zrot), cos(zrot), 0.0f); //Y-object
Run Code Online (Sandbox Code Playgroud)
你可以尝试这个到目前为止(禁用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 ]
Run Code Online (Sandbox Code Playgroud)
我们称这个向量(u_x,u_y,u_z).然后你的最终轮换(X周围的轮换)将是这样的:
gl.glRotatef(xrot, u_x, u_y, u_z); //X-object
Run Code Online (Sandbox Code Playgroud)
所以!如何找到矩阵Rot_around_new_y?请参阅此处有关围绕任意轴的旋转.转到第6.2节,第一个矩阵,得到3*3子矩阵旋转(即忽略与转换相关的最右边的列)并将其(-sin(zrot), cos(zrot), 0)作为(u, v, w)轴和thetaas yrot.
我不会在这里做数学,因为它需要付出很多努力,最终我会在那里的某个地方犯错误.但是,如果你非常小心并准备好多次检查它们,你可以把它写下来并进行矩阵乘法.
附加说明:一种计算方法Rot_around_new_y也可以使用四元数.四元数被定义为4D向量[xs, ys, zs, c],其对应于左右旋转[x, y, z]通过其的角度sin是s并且其cos是c.
这[x, y, z]是我们的"新Y",即[-sin(zrot), cos(zrot), 0].角度是yrot.因此,绕Y旋转的四元数为:
q_Y = [-sin(zrot)*sin(yrot), cos(zrot)*sin(yrot), 0, cos(yrot)]
Run Code Online (Sandbox Code Playgroud)
最后,如果你有一个四元数[a, b, c, d],相应的旋转矩阵给出如下:
[1 - 2b^2 - 2c^2 2ab + 2cd 2ac - 2bd ]
[ 2ab - 2cd 1 - 2a^2 - 2c^2 2bc - 2ad ]
[ 2ac - 2bd 2bc + 2ad 1 - 2a^2 - 2b^2]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
44366 次 |
| 最近记录: |