java - 在 Android 上使用 OpenGL ES 使对象/形状原地旋转

标签 java android opengl-es

我开始在 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)。

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

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

最佳答案

假设您有对象转换矩阵:

    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 极客)我选择让它简单但实用

关于java - 在 Android 上使用 OpenGL ES 使对象/形状原地旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21687044/

相关文章:

android - 从 Android Studio 导出 Android Lint 的 html 报告?

java - 具有 onclick 功能的动态复选框列表

java - Clojure 与 Var.intern 和 RT.var 的怪异

java - 这段java代码是做什么的?

java - 将 X 小时添加到日期和时间

android - 如何在 openGL ES 2.0 中执行 2 遍以获得模糊效果

android - opengl对象在移动一段距离后振动

java - 在 JLabel 中刷新同一图像

Android 在返回按钮上关闭应用程序

performance - OpenGL ES 2.0 : The most efficient setup for a VBO with GL_STREAM_DRAW?