OpenGL ES Androidmatrix转换

我有一个实现GLSurfaceView.Renderer接口的渲染器; GLSurfaceView的子类和一些代表我想要绘制的对象的类。 我有来自http://developer.android.com/training/graphics/opengl/motion.html的代码我想扩大这个,并添加一些沿轴移动,不能pipe理它。 该对象只是旋转。 这里是我的代码:

public class NotMyCoolRenderer implements GLSurfaceView.Renderer { public GLShip mTriangle; private GLBackgroundStar mSquare; private final float[] mMVPMatrix = new float[16]; private final float[] mProjMatrix = new float[16]; private final float[] mVMatrix = new float[16]; private final float[] mModelMatrix = new float[16]; private final float[] tempMatrix = new float[16]; public void onDrawFrame(GL10 unused) { // Draw background color GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); // 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); // Draw square mSquare.draw(mMVPMatrix); // Now moving on to triangle aka ship Matrix.setIdentityM(mModelMatrix, 0); Matrix.translateM(mModelMatrix, 0, 0.1f, 0f, 0); Matrix.rotateM(mModelMatrix, 0, mTriangle.mAngle, 0, 0, -1.0f); Matrix.multiplyMM(tempMatrix, 0, mVMatrix, 0, mProjMatrix, 0); Matrix.multiplyMM(mMVPMatrix, 0, mModelMatrix , 0, tempMatrix , 0); // Draw triangle mTriangle.draw(mMVPMatrix); } public void onSurfaceChanged(GL10 unused, int width, int height) { // Adjust the viewport based on geometry changes, // such as screen rotation GLES20.glViewport(0, 0, width, height); float ratio = (float) width / height; // this projection matrix is applied to object coordinates // in the onDrawFrame() method Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); } public class GLShip { public volatile float mAngle; private final String vertexShaderCode = // This matrix member variable provides a hook to manipulate // the coordinates of the objects that use this vertex shader "uniform mat4 uMVPMatrix;" + "attribute vec4 vPosition;" + "void main() {" + // the matrix must be included as a modifier of gl_Position " gl_Position = uMVPMatrix * vPosition;" + "}"; public void draw(float[] mvpMatrix) { // Add program to OpenGL environment GLES20.glUseProgram(mProgram); // get handle to vertex shader's vPosition member mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); // Enable a handle to the triangle vertices GLES20.glEnableVertexAttribArray(mPositionHandle); // Prepare the triangle coordinate data GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); // get handle to fragment shader's vColor member mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); // Set color for drawing the triangle GLES20.glUniform4fv(mColorHandle, 1, color, 0); // get handle to shape's transformation matrix mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); NotMyCoolRenderer.checkGlError("glGetUniformLocation"); // Apply the projection and view transformation GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); NotMyCoolRenderer.checkGlError("glUniformMatrix4fv"); // Draw the triangle GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); // Disable vertex array GLES20.glDisableVertexAttribArray(mPositionHandle); } } 

我的期望是在每次重绘时,对象将被mAngle旋转,并沿着Y轴拖动1f。 虽然我只能看到旋转(也有点投影)。 其实我有一些问题:如何应用我的翻译matrix,以及分割openglfunction的最佳做法是什么? 模型matrix不应该存储在对象本身而不是渲染器中? matrix操作是否应该在渲染器类中执行? 我把它们分组在一起,因为我想它们都是相关的。

Solutions Collecting From Web of "OpenGL ES Androidmatrix转换"

我一直在从Android培训的例子,下面的方法终于为我工作。 (基于Android培训>使用OpenGL ES显示graphics>添加动作 )

  1. 使用正确的顶点着色器:

     private final String vertexShaderCode = // This matrix member variable provides a hook to manipulate // the coordinates of the objects that use this vertex shader "uniform mat4 uMVPMatrix;" + "attribute vec4 vPosition;" + "void main() {" + // the matrix must be included as a modifier of gl_Position " gl_Position = uMVPMatrix * vPosition;" + "}"; 
  2. 在渲染器类中:

     public class MyGL20Renderer implements GLSurfaceView.Renderer { [...] // create a model matrix for the triangle private final float[] mModelMatrix = new float[16]; // create a temporary matrix for calculation purposes, // to avoid the same matrix on the right and left side of multiplyMM later // see https://stackoverflow.com/questions/13480043/opengl-es-android-matrix-transformations#comment18443759_13480364 private float[] mTempMatrix = new float[16]; [...] 
  3. onDrawFrame中应用转换,从翻译开始:

     public void onDrawFrame(GL10 unused) { [...] Matrix.setIdentityM(mModelMatrix, 0); // initialize to identity matrix Matrix.translateM(mModelMatrix, 0, -0.5f, 0, 0); // translation to the left 
  4. 然后旋转

     // Create a rotation transformation for the triangle long time = SystemClock.uptimeMillis() % 4000L; float mAngle = 0.090f * ((int) time); Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f); 
  5. 结合旋转和平移, 避免使用mModelMatrix

    “作为multiplyMM的右侧和左侧的相同matrix”(见2 )

     // Combine Rotation and Translation matrices mTempMatrix = mModelMatrix.clone(); Matrix.multiplyMM(mModelMatrix, 0, mTempMatrix, 0, mRotationMatrix, 0); 
  6. 将模型matrix与投影和摄像机视图组合在一起; 再次避免使用mModelMatrix

    “作为multiplyMM的右侧和左侧的相同matrix”(见2 )

     // Combine the model matrix with the projection and camera view mTempMatrix = mMVPMatrix.clone(); Matrix.multiplyMM(mMVPMatrix, 0, mTempMatrix, 0, mModelMatrix, 0); 
  7. 绘制形状

     // Draw shape mTriangle.draw(mMVPMatrix); 

谢谢大家,我可以从这个线程中得到所有有用的信息。

如果你想看到移动,你应该更新mTriangle.mAngle每个帧(最好作为时间的函数来对抗速度差异或由其他进程造成的延迟…)。

请注意Matrix.setIdentityM(mModelMatrix,0); 将所有累积的旋转和翻译恢复为“零”或实际上恢复到标识matrix…相同的惯例适用于所有设置的function。 为了积累所有的转化,必须

  • setIdentity(模型);
  • 翻译(反式); //获取旋转的原点
  • 旋转(rotmatrix); //积累旋转
  • 翻译(T2); //再次翻译成更好的位置

还应该在每次调用之间保留对象翻译向量[ox,oy,oz]的值,并将它们传送给Matrix.translateM(mModelMatrix,ox,oy,oz,0)。

通常,尽可能早地连接所有的“翻译,旋转,缩放”等matrix,并将其caching在每个对象中,或者按照具有多个对象并具有边界框的复杂容器分层次地caching,以便在后面可以剔除多个对象相机(或通常在观看平截头体之外)。

通常还有一个移动摄像机保存在一个matrix中,每帧将其与投影matrix相乘。

你可以从这样的事情开始:

 float Time = System.currentTimeMillis() * 0.01f; // 10 radians / second == fast! Matrix.translateM(mModelMatrix, Math.sin(Time)*2.0f, 0, 1f, 0); ... 

正如Tim所注意到的那样,没有涉及到投影matrix,这意味着所有的z值在这个代码中的行为是正确的,尽pipe改变x和y值会有所作为。

我试图说,MVPmatrix将意味着以M * V * P =(M * V)* P = M *(V * P)的顺序相乘。

请注意,您没有将投影matrix应用于您正在绘制的三angular形,这可能会导致问题。

应该可能是:

 Matrix.multiplyMM(mMVMatrix, 0, mVMatrix, 0, mModelMatrix, 0); Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVMatrix, 0);