【问题标题】:Making an object/shape rotate in place with OpenGL ES on Android在 Android 上使用 OpenGL ES 使对象/形状就地旋转
【发布时间】:2014-02-10 20:16:21
【问题描述】:

我开始在 android 上学习 OpenGL,现在我正在尝试弄一个简单的三角形。
我想做的是让它在原地旋转(旋转枢轴是形状的中心),尽管我只设法让它围绕一个轴旋转(我的意思是它在指定的轴上做圆周运动)。

这是我的代码:

@Override
public void onDrawFrame(GL10 gl) {
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -10, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    long time = SystemClock.uptimeMillis() % 4000L;
    float angle = 0.090f * ((int) time);

    Matrix.setIdentityM(mModelMatrix, 0); // initialize to identity matrix
    Matrix.rotateM(mModelMatrix, 0, angle, 0, 1.0f, 0);

    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);

    mPlayerCharacter.draw(mMVPMatrix);
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    GLES20.glViewport(0, 0, width, height);

    float ratio = (float) width / height;
    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    mPlayerCharacter = new PlayerCharacter();
}

----- PlayerCharacter.draw() -----

public void draw(float[] mvpMatrix) {
    // Add program to OpenGL ES 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");

    // Pass the projection and view transformation to the shader
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

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

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

三角形坐标是顶部 (0, 0.622, 0)、左下角 (-0.5, -0.311, 0) 和右下角 (0.5, -0.311, 0)。

我尝试寻找类似的问题或相关指南,但没有找到适合我的答案。

如果是这样,实现我正在寻找的结果的正确方法是什么?

【问题讨论】:

    标签: java android opengl-es


    【解决方案1】:

    假设你有你的对象变换矩阵:

        protected final float[] mTransformMatrix = new float[16];
    

    创建对象时只需使用Matrix.setIdentityM(mTransformMatrix, 0);

    要旋转,您需要:

    Matrix.rotateM(mTransformMatrix, 0, angle, 0, 0, 1.0f);
    

    以下是对象定位、大小和旋转的一些方法:

        public Sprite setSize(float sizeX, float sizeY) {
        setCenterSizeRotation(this.mPositionX, this.mPositionY, sizeX, sizeY,
                this.mAngle);
        this.mSpriteWidth = sizeX;
        this.mSpriteHeight = sizeY;
    
        return this;
    }
    
    public Sprite setCenter(float posX, float posY) {
        setCenterSizeRotation(posX, posY, this.mSpriteWidth,
                this.mSpriteHeight, this.mAngle);
        this.mPositionX = posX;
        this.mPositionY = posY;
    
        return this;
    }
    
    public Sprite setRotation(float angle) {
        setCenterSizeRotation(this.mPositionX, this.mPositionY,
                this.mSpriteWidth, this.mSpriteHeight, angle);
        this.mAngle = angle;
    
        return this;
    }
    
    public Sprite setCenterSizeRotation(float posX, float posY, float sizeX,
            float sizeY, float angle) {
    
        reset();
        float oX = UtilsGL.getStepX() * posX - 1.0f;
        float oY = UtilsGL.getStepY() * posY - 1.0f;
        float scaleX = sizeX / (UtilsGL.getSurfaceWidth());
        float scaleY = sizeY / (UtilsGL.getSurfaceHeight());
    
        translate(oX, oY);
        scale(scaleX, scaleY);
        rotate(angle);
    
        this.mSpriteWidth = sizeX;
        this.mSpriteHeight = sizeY;
        this.mPositionX = posX;
        this.mPositionY = posY;
        this.mAngle = angle;
    
        return this;
    }
    
    public Sprite translate(float x, float y) {
        Matrix.translateM(mTransformMatrix, 0, x, y, 0);
        return this;
    }
    
    public Sprite scale(float x, float y) {
        Matrix.scaleM(mTransformMatrix, 0, x, y, 1.0f);
        return this;
    }
    
    public Sprite rotate(float d) {
        Matrix.rotateM(mTransformMatrix, 0, d, 0, 0, 1.0f);
        return this;
    }
    
    public Sprite reset() {
        Matrix.setIdentityM(mTransformMatrix, 0);
        return this;
    }
    

    不要害怕返回,这只是我的 Sprite 类中的一些代码

    UtilsGL 部分:

        private static int mSurfaceWidth;
    private static int mSurfaceHeight;
    private static float mStepX;
    private static float mStepY;
    
        public static void setSurfaceWH(int width, int height) {
        mSurfaceWidth = width;
        mSurfaceHeight = height;
        mStepX = 2.0f / (float) mSurfaceWidth;
        mStepY = 2.0f / (float) mSurfaceHeight;
    }
    
    public static int getSurfaceWidth() {
        return mSurfaceWidth;
    }
    
    public static int getSurfaceHeight() {
        return mSurfaceHeight;
    }
    
    public static float getStepX() {
        return mStepX;
    }
    
    public static float getStepY() {
        return mStepY;
    }
    

    这里有很多代码,但都很有用。为什么是静态的?我不是 OOP 极客)我选择让它简单但实用

    【讨论】:

    • 谢谢。 Matrix.rotateM(mTransformMatrix, 0, angle, 0, 0, 1.0f); 不会导致在 z 轴内/周围旋转吗?我想要实现的是围绕 y 轴的旋转,但我只能围绕该轴进行圆周运动......
    • 哦,我只使用过 2D,所以我的代码就是为它准备的。你可以尝试rotateM()的不同参数来实现绕其他轴的旋转
    • 我也在使用 2D。我尝试了很多不同的参数和答案 - 似乎没有任何效果。 x.x 还是谢谢
    【解决方案2】:

    问题解决了! 我不敢相信它是这么小的东西!

    问题出在这一行:
    gl_Position = vPosition * uMVPMatrix;

    我不能完全解释为什么(所以如果有人可以 - 那太好了!)但是当我将其更改为:
    gl_Position = uMVPMatrix * vPosition; 它按预期工作!

    如果有人可以进一步解释为什么这样做而不是第一个选项,那就太棒了!我当然会将答案标记为已接受。

    谢谢。

    【讨论】:

    • 我相信这是因为矩阵乘法是不可交换的,所以你会根据矩阵乘法的顺序得到不同的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多