2

我正在为android制作一个应用程序,我画了一个三角形,我可以旋转它但不能移动它!我的问题为什么?

如果您需要更多信息,请说!

源代码:

package com.uraniumdevs.projectx;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;

public class MyGL20Renderer implements GLSurfaceView.Renderer {

        private static final String TAG = "MyGLRenderer";
        private Triangle mTriangle;
        private Square 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[] mRotationMatrix = new float[16];
        private final float[] mTranslationMatrix = new float[16];

        // Declare as volatile because we are updating it from another thread
        public volatile float Angle;
        public volatile float Tempx;
        public volatile float Tempy;

        @Override
        public void onSurfaceCreated(GL10 unused, EGLConfig config) {

                // Set the background frame color
                GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
                mTriangle = new Triangle();
                mSquare = new Square();
        }

        @Override
        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);

                // Create a rotation for the triangle
                Matrix.setRotateM(mRotationMatrix, 0, Angle, 0, 0, -1.0f);
                Matrix.translateM(mTranslationMatrix, 0, Tempx, Tempy, 0);

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

                mTriangle.draw(mMVPMatrix);
        }

        @Override
        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 static int loadShader(int type, String shaderCode) {

                // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
                // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
                int shader = GLES20.glCreateShader(type);

                // add the source code to the shader and compile it
                GLES20.glShaderSource(shader, shaderCode);
                GLES20.glCompileShader(shader);

                return shader;
        }

        /**
         * Utility method for debugging OpenGL calls. Provide the name of the call
         * just after making it:
         *
         * <pre>
         * mColorHandle = GLES20.glGetUniformLocation(mProgram, &quot;vColor&quot;);
         * MyGLRenderer.checkGlError(&quot;glGetUniformLocation&quot;);
         * </pre>
         *
         * If the operation is not successful, the check throws an error.
         *
         * @param glOperation
         *            - Name of the OpenGL call to check.
         */
        public static void checkGlError(String glOperation) {
                int error;
                while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
                        Log.e(TAG, glOperation + ": glError " + error);
                        throw new RuntimeException(glOperation + ": glError " + error);
                }
        }
}

class Triangle {

        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 = vPosition * uMVPMatrix;" + "}";

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

        private final FloatBuffer vertexBuffer;
        private final int mProgram;
        private int mPositionHandle;
        private int mColorHandle;
        private int mMVPMatrixHandle;

        // number of coordinates per vertex in this array
        static final int COORDS_PER_VERTEX = 3;
        public static float triangleCoords[] = { // in counterclockwise order:
        0.0f, 0.1f, 0.0f, // top
                        -0.1f, -0.1f, 0.0f, // bottom left
                        0.1f, -0.1f, 0.0f // bottom right
        };
        private final int vertexCount;
        private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per
                                                                                                                        // vertex

        // Set color with red, green, blue and alpha (opacity) values
        float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };

        public Triangle() {
                vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
                // initialize vertex byte buffer for shape coordinates
                ByteBuffer bb = ByteBuffer.allocateDirect(
                // (number of coordinate values * 4 bytes per float)
                                triangleCoords.length * 4);
                // use the device hardware's native byte order
                bb.order(ByteOrder.nativeOrder());

                // create a floating point buffer from the ByteBuffer
                vertexBuffer = bb.asFloatBuffer();
                // add the coordinates to the FloatBuffer
                vertexBuffer.put(triangleCoords);
                // set the buffer to read the first coordinate
                vertexBuffer.position(0);

                // prepare shaders and OpenGL program
                int vertexShader = MyGL20Renderer.loadShader(GLES20.GL_VERTEX_SHADER,
                                vertexShaderCode);
                int fragmentShader = MyGL20Renderer.loadShader(
                                GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

                mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
                GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader
                                                                                                                // to program
                GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment
                                                                                                                        // shader to program
                GLES20.glLinkProgram(mProgram); // create OpenGL program executables

        }

        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");
                MyGL20Renderer.checkGlError("glGetUniformLocation");

                // Apply the projection and view transformation
                GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
                MyGL20Renderer.checkGlError("glUniformMatrix4fv");

                // Draw the triangle
                GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

                // Disable vertex array
                GLES20.glDisableVertexAttribArray(mPositionHandle);
        }
}

class Square {

        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 = vPosition * uMVPMatrix;" + "}";

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

        private final FloatBuffer vertexBuffer;
        private final ShortBuffer drawListBuffer;
        private final int mProgram;
        private int mPositionHandle;
        private int mColorHandle;
        private int mMVPMatrixHandle;

        // number of coordinates per vertex in this array
        static final int COORDS_PER_VERTEX = 3;
        static float squareCoords[] = { -0.5f, 0.5f, 0.0f, // top left
                        -0.5f, -0.5f, 0.0f, // bottom left
                        0.5f, -0.5f, 0.0f, // bottom right
                        0.5f, 0.5f, 0.0f }; // top right

        private final short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw
                                                                                                                        // vertices

        private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per
                                                                                                                        // vertex

        // Set color with red, green, blue and alpha (opacity) values
        float color[] = { 0.2f, 0.709803922f, 0.898039216f, 1.0f };

        public Square() {
                // initialize vertex byte buffer for shape coordinates
                ByteBuffer bb = ByteBuffer.allocateDirect(
                // (# of coordinate values * 4 bytes per float)
                                squareCoords.length * 4);
                bb.order(ByteOrder.nativeOrder());
                vertexBuffer = bb.asFloatBuffer();
                vertexBuffer.put(squareCoords);
                vertexBuffer.position(0);

                // initialize byte buffer for the draw list
                ByteBuffer dlb = ByteBuffer.allocateDirect(
                // (# of coordinate values * 2 bytes per short)
                                drawOrder.length * 2);
                dlb.order(ByteOrder.nativeOrder());
                drawListBuffer = dlb.asShortBuffer();
                drawListBuffer.put(drawOrder);
                drawListBuffer.position(0);

                // prepare shaders and OpenGL program
                int vertexShader = MyGL20Renderer.loadShader(GLES20.GL_VERTEX_SHADER,
                                vertexShaderCode);
                int fragmentShader = MyGL20Renderer.loadShader(
                                GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

                mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
                GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader
                                                                                                                // to program
                GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment
                                                                                                                        // shader to program
                GLES20.glLinkProgram(mProgram); // create OpenGL program executables
        }

        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");
                MyGL20Renderer.checkGlError("glGetUniformLocation");

                // Apply the projection and view transformation
                GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
                MyGL20Renderer.checkGlError("glUniformMatrix4fv");

                // Draw the square
                GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
                                GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

                // Disable vertex array
                GLES20.glDisableVertexAttribArray(mPositionHandle);
        }
}
4

2 回答 2

12

我认为我们正在从 Android 开发人员培训指南中修改相同的 OpenGLES20Activity

http://developer.android.com/training/graphics/opengl/environment.html

为了移动和旋转三角形,你可以这样做:

(为了使变量可以从其他类对象访问,我将它们公开。)

  1. 为 Triangle 对象添加一个 mModelMatrix。这用于设置三角形的位置和方向。在构造函数中初始化它。
public class Triangle {
    ...
    public float[] mModelMatrix = new float[16];
    ...
    
    public Triangle() {
        ...
        Matrix.setIdentityM(mModelMatrix, 0);
        ...
    }
  1. 使用 Matrix.translateM 和 Matrix.rotateM(不是 Matrix.setRotateM)来移动和旋转三角形。您可以根据需要多次执行这些操作。
Matrix.translateM(mTriangle.mModelMatrix, 0, 0.5f, 0f, 0f);
Matrix.rotateM(mTriangle.mModelMatrix, 0, -45f, 0, 0, -1.0f);
  1. 将 mViewMatrix 和 mProjectMatrix 相乘以创建 mMVPMatrix,与示例中相同。然后将 mMVPMatrix 与三角形的 mModelMatrix 相乘。
public void onSurfaceChanged(GL10 unused, int width, int height) {
    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(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 1, 10);
}

public void onDrawFrame(GL10 unused) {
    float[] scratch = new float[16];
    // Draw background color
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    
    // Set the camera position (View matrix)
    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
    
    // Calculate the projection and view transformation
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
    
    // Combine the model's translation & rotation matrix 
    // with the projection and camera view
    // Note that the mMVPMatrix factor *must be first* in order
    // for the matrix multiplication product to be correct.
    Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mTriangle.mModelMatrix, 0);
    
    // Draw triangle
    mTriangle.draw(scratch);
}
于 2014-03-27T12:48:28.170 回答
2

我很惊讶这完全有效。在 OpenGL 中,如果你使用正确的列主矩阵,你应该乘以:ModelViewProjectionMatrix * VertexPosition来转换你的顶点。

这很可能是您的问题的原因。


换句话说,在你的两个着色器中

gl_Position = vPosition * uMVPMatrix;

应该是:

gl_Position = uMVPMatrix * vPosition;


您的原始矩阵乘法将在 Direct3D 中工作,因为它使用行优先矩阵。如果您要从 HLSL 移植代码,请记住这一点。

于 2013-09-13T23:44:11.370 回答