简体   繁体   English

在Android上使用OpenGL ES使对象/形状旋转到位

[英]Making an object/shape rotate in place with OpenGL ES on Android

I started learning OpenGL on android, and now I'm trying to mess around with a simple triangle. 我开始在android上学习OpenGL,现在我想弄个简单的三角形。
What I'm trying to do is make it rotate in place (the rotation pivot being the shape's center), although I only managed to make it rotate around an axis (By that I mean it makes a circular motion in the axis specified). 我想做的是使它就位旋转(旋转枢轴是形状的中心),尽管我只设法使其绕轴旋转(因为我是说它在指定的轴上作圆周运动)。

Here's my code: 这是我的代码:

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

The triangles coordinates are top (0, 0.622, 0), bottom left ( -0.5, -0.311, 0), and bottom right (0.5, -0.311, 0). 三角形的坐标为上(0,0.622,0),左下(-0.5,-0.311、0)和右下(0.5,-0.311、0)。

I tried looking for similar questions or related guides, but none of the answers I found worked for me. 我曾尝试寻找类似的问题或相关指南,但没有找到对我有用的答案。

If so, what is the right way to achieve the result I'm looking for? 如果是这样,什么是达到我想要的结果的正确方法?

Assume you have your object transformation matrix: 假设您有对象转换矩阵:

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

When you create object you just use Matrix.setIdentityM(mTransformMatrix, 0); 创建对象时,只需使用Matrix.setIdentityM(mTransformMatrix, 0);

To rotate you need: 要旋转,您需要:

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

Here are some methods for object positioning, sizeing and rotating: 以下是一些用于对象定位,调整大小和旋转的方法:

    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;
}

Don't be afraid of returns, that's just a bit of code from my Sprite class 不要害怕返回,这只是我的Sprite类中的一些代码

UtilsGL part: 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;
}

A lot of code down here but it's all useful. 这里有很多代码,但它们都很有用。 Why static? 为什么是静态的? I'm not a OOP geek) I chose to make it simple but functional 我不是OOP怪胎)我选择使其简单但实用

Problem solved! 问题解决了! I can't believe it was something so small! 我简直不敢相信它是如此之小!

The problem was this line: 问题是这一行:
gl_Position = vPosition * uMVPMatrix;

I can't quite explain why (so if someone could - that'd be great!) but when I changed it to: 我无法完全解释原因(如果有人可以,那就太好了!),但是当我将其更改为:
gl_Position = uMVPMatrix * vPosition; it worked as expected! 它按预期工作!

If someone can further explain why this works instead of the first option, that'd be awesome! 如果有人可以进一步解释为什么它能代替第一个选择起作用,那就太好了! I will of course mark the answer as accepted. 我当然会将答案标记为已接受。

Thanks. 谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM