在Android中使用open GL ES实现3D对象旋转

时间:2014-01-29 09:24:07

标签: android opengl-es surfaceview

我在android中使用open GL ES实现了3D对象旋转。图像显示在模拟器中,并且工作正常。但在设备中,图像不可见。

提出任何建议继续。

 import android.os.Bundle;
 import android.view.Window;
 import android.view.WindowManager;

public class MainActivity extends Activity {

 private GLSurfaceView glView;  // Use subclass of GLSurfaceView (NEW)

   @Override
   protected void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);
      requestWindowFeature(Window.FEATURE_NO_TITLE); 
      getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
              WindowManager.LayoutParams.FLAG_FULLSCREEN);
      // Allocate a custom subclass of GLSurfaceView (NEW)


    glView = new MyGLSurfaceView(this);
      setContentView(glView);  // Set View (NEW)
   }

   @Override
   protected void onPause() {
      super.onPause();
    //  glView = (MyGLSurfaceView)findViewById(R.id.glSurfaceViewID);

      glView.onPause();
   }

   @Override



protected void onResume() {
      super.onResume();
   //   glView = (MyGLSurfaceView)findViewById(R.id.glSurfaceViewID);
      glView.onResume();
   }
}

这是我的GLSurfaceView类

 package com.example.object_rotation;

import android.opengl.GLSurfaceView;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.KeyEvent;
import android.view.MotionEvent;
/*
 * Custom GL view by extending GLSurfaceView so as
 * to override event handlers such as onKeyUp(), onTouchEvent()
 */
public class MyGLSurfaceView extends GLSurfaceView {
       MyGLRenderer renderer;    // Custom GL Renderer

   // For touch event
   private final float TOUCH_SCALE_FACTOR = 180.0f / 320.0f;
   private float previousX;
   private float previousY;

   // Constructor - Allocate and set the renderer
   public MyGLSurfaceView(Context context) {
      super(context);
      renderer = new MyGLRenderer(context);
      this.setRenderer(renderer);
      // Request focus, otherwise key/button won't react
      this.requestFocus();  
      this.setFocusableInTouchMode(true);
   }

   // Handler for key event
   @Override
   public boolean onKeyUp(int keyCode, KeyEvent evt) {
      switch(keyCode) {
         case KeyEvent.KEYCODE_DPAD_LEFT:   // Decrease Y-rotational speed
            renderer.speedY -= 0.1f;
            break;
         case KeyEvent.KEYCODE_DPAD_RIGHT:  // Increase Y-rotational speed
            renderer.speedY += 0.1f;
            break;
         case KeyEvent.KEYCODE_DPAD_UP:     // Decrease X-rotational speed
            renderer.speedX -= 0.1f;
            break;
         case KeyEvent.KEYCODE_DPAD_DOWN:   // Increase X-rotational speed 
            renderer.speedX += 0.1f;
            break;
         case KeyEvent.KEYCODE_A:           // Zoom out (decrease z)
            renderer.z -= 0.2f;
            break;
         case KeyEvent.KEYCODE_Z:           // Zoom in (increase z)
            renderer.z += 0.2f;
            break;
         case KeyEvent.KEYCODE_DPAD_CENTER:  // Select texture filter (NEW)
                renderer.currentTextureFilter = (renderer.currentTextureFilter + 1) % 3;
                break;
      }
      return true;  // Event handled
   }

   // Handler for touch event
   @Override
   public boolean onTouchEvent(final MotionEvent evt) {
      float currentX = evt.getX();
      float currentY = evt.getY();
      float deltaX, deltaY;
      switch (evt.getAction()) {
         case MotionEvent.ACTION_MOVE:
            // Modify rotational angles according to movement
            deltaX = currentX - previousX;
            deltaY = currentY - previousY;
            renderer.angleX += deltaY * TOUCH_SCALE_FACTOR;
            renderer.angleY += deltaX * TOUCH_SCALE_FACTOR;
      }
      // Save current x, y
      previousX = currentX;
      previousY = currentY;
      return true;  // Event handled
   }


 }

这是我的GLRenderer类

package com.example.object_rotation;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;

public class MyGLRenderer implements GLSurfaceView.Renderer {

   private Context context;
   private TextureCube cube;
   int currentTextureFilter = 0;  // Texture filter (NEW)
   // For controlling cube's z-position, x and y angles and speeds (NEW)
   float angleX = 0;   // (NEW)
   float angleY = 0;   // (NEW)
   float speedX = 0;   // (NEW)
   float speedY = 0;   // (NEW)
   float z = -6.0f;    // (NEW)

   // Constructor
   public MyGLRenderer(Context context) {
      this.context = context;
      cube = new TextureCube();
   }

   // Call back when the surface is first created or re-created.
   @Override
   public void onSurfaceCreated(GL10 gl, EGLConfig config) {
      gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);  // Set color's clear-value to black
      gl.glClearDepthf(1.0f);            // Set depth's clear-value to farthest
      gl.glEnable(GL10.GL_DEPTH_TEST);   // Enables depth-buffer for hidden surface removal
      gl.glDepthFunc(GL10.GL_LEQUAL);    // The type of depth testing to do
      gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);  // nice perspective view
      gl.glShadeModel(GL10.GL_SMOOTH);   // Enable smooth shading of color
      gl.glDisable(GL10.GL_DITHER);      // Disable dithering for better performance

      // Setup Texture, each time the surface is created
      cube.loadTexture(gl, context);    // Load image into Texture
      gl.glEnable(GL10.GL_TEXTURE_2D);  // Enable texture
   }

   // Call back after onSurfaceCreated() or whenever the window's size changes.
   @Override
   public void onSurfaceChanged(GL10 gl, int width, int height) {
      // NO CHANGE - SKIP
     // ......
   }

   // Call back to draw the current frame.
   @Override
   public void onDrawFrame(GL10 gl) {
      // Clear color and depth buffers
      gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

      // ----- Render the Cube -----
      gl.glLoadIdentity();              // Reset the model-view matrix
      gl.glTranslatef(0.0f, -2.0f, z);   // Translate into the screen (NEW)
      gl.glScalef(0.5f, 0.5f, 0.5f);
      gl.glRotatef(angleX, 1.0f, 0.0f, 0.0f); // Rotate (NEW)
      gl.glRotatef(angleY, 0.0f, 1.0f, 0.0f); // Rotate (NEW)
      cube.draw(gl, currentTextureFilter);

      // Update the rotational angle after each refresh (NEW)
      angleX += speedX;  // (NEW)
      angleY += speedY;  // (NEW)
   }
}

这是我在我创建立方体的TextureCube

package com.example.object_rotation;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
/*
 * A cube with texture.
 * Three texture filters are to be set up. 
 */
public class TextureCube {
   private FloatBuffer vertexBuffer; // Buffer for vertex-array
   private FloatBuffer texBuffer;    // Buffer for texture-coords-array

   private float[] vertices = { // Vertices for a face
      -1.0f, -1.0f, 0.0f,  // 0. left-bottom-front
       1.0f, -1.0f, 0.0f,  // 1. right-bottom-front
      -1.0f,  1.0f, 0.0f,  // 2. left-top-front
       1.0f,  1.0f, 0.0f   // 3. right-top-front
   };

   float[] texCoords = { // Texture coords for the above face
      0.0f, 1.0f,  // A. left-bottom
      1.0f, 1.0f,  // B. right-bottom
      0.0f, 0.0f,  // C. left-top
      1.0f, 0.0f   // D. right-top
   };
   int[] textureIDs = new int[3];  // Array for 3 texture-IDs (NEW)

   // Constructor - Set up the buffers
   public TextureCube() {
      // Setup vertex-array buffer. Vertices in float. An float has 4 bytes
      ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
      vbb.order(ByteOrder.nativeOrder()); // Use native byte order
      vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float
      vertexBuffer.put(vertices);         // Copy data into buffer
      vertexBuffer.position(0);           // Rewind

      // Setup texture-coords-array buffer, in float. An float has 4 bytes
      ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4);
      tbb.order(ByteOrder.nativeOrder());
      texBuffer = tbb.asFloatBuffer();
      texBuffer.put(texCoords);
      texBuffer.position(0);
   }

   // Draw the shape
   public void draw(GL10 gl, int textureFilter) {  // Select the filter (NEW)
      gl.glFrontFace(GL10.GL_CCW);    // Front face in counter-clockwise orientation
      gl.glEnable(GL10.GL_CULL_FACE); // Enable cull face 
      gl.glCullFace(GL10.GL_BACK);    // Cull the back face (don't display) 

      gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
      gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
      gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  // Enable texture-coords-array
      gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // Define texture-coords buffer

      // Select the texture filter to use via texture ID (NEW)
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[textureFilter]);

      // front
      gl.glPushMatrix();
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      // left
      gl.glPushMatrix();
      gl.glRotatef(270.0f, 0.0f, 1.0f, 0.0f);
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      // back
      gl.glPushMatrix();
      gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      // right
      gl.glPushMatrix();
      gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      // top
      gl.glPushMatrix();
      gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      // bottom
      gl.glPushMatrix();
      gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
      gl.glTranslatef(0.0f, 0.0f, 1.0f);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glPopMatrix();

      gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
      gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
      gl.glDisable(GL10.GL_CULL_FACE);
   }

   // Load an image and create 3 textures with different filters (NEW)
   public void loadTexture(GL10 gl, Context context) {
      // Construct an input stream to texture image "res\drawable\crate.png"
      InputStream istream = context.getResources().openRawResource(R.drawable.image17);
      Bitmap bitmap;
      try {
         // Read and decode input as bitmap
         bitmap = BitmapFactory.decodeStream(istream);
      } finally {
         try {
            istream.close();
         } catch(IOException e) { }
      }

      gl.glGenTextures(3, textureIDs, 0);  // Generate texture-ID array for 3 textures (NEW)

      // Create Nearest Filtered Texture and bind it to texture 0 (NEW)
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]);
      gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
      gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
      GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

      // Create Linear Filtered Texture and bind it to texture 1 (NEW)
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[1]);
      gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
      GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

      // Create mipmapped textures and bind it to texture 2 (NEW)
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[2]);
      gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
      gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
      GL10.GL_LINEAR_MIPMAP_NEAREST); 
      if(gl instanceof GL11) {
         gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
      }
      GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

      bitmap.recycle();
   }
}

1 个答案:

答案 0 :(得分:-1)

private float[] vertices = { // Vertices for a face
  -1.0f, -1.0f, 0.0f,  // 0. left-bottom-front
   1.0f, -1.0f, 0.0f,  // 1. right-bottom-front
  -1.0f,  1.0f, 0.0f,  // 2. left-top-front
   1.0f,  1.0f, 0.0f   // 3. right-top-front
};

我建议将其改为

private float[] vertices = { // Vertices for a face
  -1.0f, -1.0f, 0.0001f,  // 0. left-bottom-front
   1.0f, -1.0f, 0.0001f,  // 1. right-bottom-front
  -1.0f,  1.0f, 0.0001f,  // 2. left-top-front
   1.0f,  1.0f, 0.0001f   // 3. right-top-front
};

在某些设备中,如果摄像机位置与顶点具有相同的z值,则多边形将根本不显示。我认为这可能是问题所在。