通过设备旋转旋转简单的3d对象

时间:2015-11-30 12:39:36

标签: android opengl-es

我试图在屏幕上绘制一个简单的矩形,并在我物理旋转设备时看到它旋转。我设法获得了一些旋转,但没有任何意义,它似乎不随着设备的方向旋转。

我的主要活动:

public class MainActivity extends Activity implements SensorEventListener {
    public static final double RAD2DEG=57.2957795;
    private static final String SENSOR_TAG = "SENSOR";
    private GLSurfaceView glSurfaceView;
    private boolean rendererSet = false;
    private SensorManager sensorManager;
    private Sensor rotationSensor;
    private float[] rotationVector;
    private float[] rotatinMatrix = new float[16];
    private float[] orientationVals = new float[3];
    public Renderer renderer;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        renderer = new Renderer(this);
        createGLsurface();
        getSensors();

    }

    protected void createGLsurface(){
        glSurfaceView = new GLSurfaceView(this);
        glSurfaceView.setEGLContextClientVersion(2);
        glSurfaceView.setRenderer(renderer);
        rendererSet=true;
        setContentView(glSurfaceView);
    }

    protected void getSensors(){
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        rotationSensor=sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (rendererSet)
            glSurfaceView.onPause();
        sensorManager.unregisterListener(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (rendererSet)
            glSurfaceView.onResume();
        sensorManager.registerListener(this,rotationSensor,SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {

        SensorManager.getRotationMatrixFromVector(rotatinMatrix, event.values);


        renderer.setRotationMatrix(rotatinMatrix);

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}

我的渲染器:

public class Renderer implements GLSurfaceView.Renderer {

    private static final String A_COLOR = "a_Color";
    private static final String U_MATRIX = "u_Matrix";
    private static final String A_POSITION = "a_Position";
    private static final int BYTES_PER_FLOAT = 4 ;
    private static final int POSITION_COMPONENT_COUNT = 2;
    private static final int COLOR_COMPONENT_COUNT = 3;
    private static final int STRIDE = (POSITION_COMPONENT_COUNT+COLOR_COMPONENT_COUNT)*BYTES_PER_FLOAT;
    private final Context context;
    private final FloatBuffer vertexData;
    private int program;
    private int uColorLocation ;
    private int aPositionLocation;
    private int aColorLocation;
    private int uMatrixLocation;
    private float[] projectionMatrix = new float[16];
    private float[] mViewMatrix = new float[16];
    private float[] mMVPMatrix = new float[16];
    private float[] rotationMatrix = new float[16];
    private float[] rotated = new float[16];

    public Renderer(Context context) {
        this.context = context ;
        float[] table = {
                //triangle fan
                // X  ,     Y ,    R  ,   G  ,   B
                   0  ,     0 ,     1f ,   1f ,   1f ,
                -0.5f ,  -0.5f , 0.7f , 0.2f , 0.2f ,
                 0.5f ,  -0.5f , 0.7f , 0.2f , 0.2f ,
                 0.5f ,   0.5f , 0.7f , 0.2f , 0.2f ,
                -0.5f ,   0.5f , 0f   , 0f   , 0.7f ,
                -0.5f ,  -0.5f , 0f   , 0f   , 0.7f
        };

        vertexData = ByteBuffer.allocateDirect(table.length * BYTES_PER_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
        vertexData.put(table);

    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glClearColor(0f,0f,0f,0f);
        String vertexShaderSource = TextResourceReader.readTextFileFromResource(context,R.raw.simple_vertex_shader); //read simple_vertex_shader.glsl
        String fragmentShaderSource = TextResourceReader.readTextFileFromResource(context, R.raw.simple_fragment_shader); //read simple_fragment_shader.glsl
        int vertexShader = ShaderHelper.compileVertexShader(vertexShaderSource); //compile the vertex shader
        int fragmentShader = ShaderHelper.compileFragmentShader(fragmentShaderSource); //compile the fragment shader
        program=ShaderHelper.linkProgram(vertexShader,fragmentShader); //link the shaders into a program object
        if (Logger.logging)
            ShaderHelper.validateProgram(program);

        GLES20.glUseProgram(program); //enable the program we just created

        uMatrixLocation = GLES20.glGetUniformLocation(program,U_MATRIX);
        aPositionLocation=GLES20.glGetAttribLocation(program,A_POSITION); //get attribute for position
        aColorLocation = GLES20.glGetAttribLocation(program,A_COLOR); //get attribute for color

        //tell openGL where to find the attribute location
        vertexData.position(0);
        GLES20.glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GLES20.GL_FLOAT, false, STRIDE, vertexData);
        GLES20.glEnableVertexAttribArray(aPositionLocation); //enable the vertex array


        //tell openGL where to find the attribute for color
        vertexData.position(POSITION_COMPONENT_COUNT);
        GLES20.glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GLES20.GL_FLOAT, false, STRIDE, vertexData);
        GLES20.glEnableVertexAttribArray(aColorLocation);







    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
        float ratio = (float)width/height;
        Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);

    }

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -4.0f, 0f, 0f, 0f, 0f, 6.0f, 0.0f);
        Matrix.multiplyMM(mMVPMatrix, 0, projectionMatrix, 0, mViewMatrix, 0);
        Matrix.multiplyMM(rotated,0,mMVPMatrix,0,rotationMatrix,0);



        GLES20.glUniformMatrix4fv(uMatrixLocation,1,false,mMVPMatrix,0);


        GLES20.glUniform4f(uColorLocation,1.0f,1.0f,1.0f,1.0f);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN,0,6);

    }

    public void setRotationMatrix(float[] rotationMatrix) {
        this.rotationMatrix = rotationMatrix;
    }
}

1 个答案:

答案 0 :(得分:0)

如果不通过代码,似乎您没有将旋转的矩阵传递给着色器。

  

GLES20.glUniformMatrix4fv(uMatrixLocation,1,假,mMVPMatrix,0);

上述代码应替换为:

GLES20.glUniformMatrix4fv(uMatrixLocation,1,false,rotated,0);

顺便说一句,由于您的渲染器工作在与接收屏幕方向的活动不同的线程中,您应该使用queueEvent在onSensorChanged中发布移动:

@Override
public void onSensorChanged(SensorEvent event) {

    SensorManager.getRotationMatrixFromVector(rotatinMatrix, event.values);

    final ConditionVariable syncObj = new ConditionVariable();
    glSurfaceView.queueEvent(new Runnable() {       
        @Override
        public void run() {
            renderer.setRotationMatrix(rotatinMatrix, syncObj);
        }
    });

    syncObj.block();
};

不要忘记在渲染器中打开syncObj:

public void setRotationMatrix(float[] rotationMatrix, ConditionVariable syncObj) {
    this.rotationMatrix = rotationMatrix;
    syncObj.open();
}

希望这有帮助!