为金字塔中的每张脸赋予不同的纹理

时间:2014-06-05 11:25:45

标签: java android opengl-es 3d

我是openGL的初学者。 我在android中使用openGL库创建了一个棱镜(每个面都是等边三角形),我能够成功旋转棱镜。 但我的要求是在棱镜的每个面上放三个不同的图像,我无法放置图像。当我放置图像时,它会缩放并映射到所有面部。

MyRenderer Class

public class MyRenderer implements Renderer {

/** Cube instance */

/* Rotation values for all axis */
private float xrot;             //X Rotation ( NEW )
private float yrot;             //Y Rotation ( NEW )
private float zrot;             //Z Rotation ( NEW )

/** The Activity Context ( NEW ) */
private Context context;
private Pyramid pyramid;
/**
 * Instance the Cube object and set 
 * the Activity Context handed over
 */

public MyRenderer(Context context) {
    this.context = context;

    pyramid = new Pyramid(this.context);

}

/**
 * The Surface is created/init()
 */
public void onSurfaceCreated(GL10 gl, EGLConfig config) {       
    //Load the texture for the cube once during Surface creation


    gl.glEnable(GL10.GL_TEXTURE_2D);            //Enable Texture Mapping ( NEW )
    gl.glShadeModel(GL10.GL_SMOOTH);            //Enable Smooth Shading
    gl.glClearColor(1.0f, 1.0f, 1.0f, 0.5f);    //Black Background
    gl.glClearDepthf(1.0f);                     //Depth Buffer Setup
    gl.glEnable(GL10.GL_DEPTH_TEST);            //Enables Depth Testing
    gl.glDepthFunc(GL10.GL_LEQUAL);             //The Type Of Depth Testing To Do

    //Really Nice Perspective Calculations
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 
}

/**
 * Here we do our drawing
 */

public void onDrawFrame(GL10 gl) {

    //Clear Screen And Depth Buffer
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);    
    gl.glLoadIdentity();                    //Reset The Current Modelview Matrix

    //Drawing
    gl.glTranslatef(0.0f, -1.0f, -5.0f);        //Move 5 units into the screen
    gl.glScalef(1.0f, 1.0f, 1.0f);          //Scale the Cube to 80 percent, otherwise it would be too large for the screen

    //Rotate around the axis based on the rotation matrix (rotation, x, y, z)
     gl.glRotatef(yrot, 0.0f, 1.65f, 0.0f); //X

     pyramid.draw(gl, context);

     yrot += 1.0f;

}

/**
 * If the surface changes, reset the view
 */

public void onSurfaceChanged(GL10 gl, int width, int height) {
    if(height == 0) {                       //Prevent A Divide By Zero By
        height = 1;                         //Making Height Equal One
    }

    gl.glViewport(0, 0, width, height);     //Reset The Current Viewport
    gl.glMatrixMode(GL10.GL_PROJECTION);    //Select The Projection Matrix
    gl.glLoadIdentity();                    //Reset The Projection Matrix

    //Calculate The Aspect Ratio Of The Window
    GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);

    gl.glMatrixMode(GL10.GL_MODELVIEW);     //Select The Modelview Matrix
    gl.glLoadIdentity();                    //Reset The Modelview Matrix
}

}

MyPyramid类

public class Pyramid {

/** The buffer holding the vertices */
private FloatBuffer vertexBuffer;
/** The buffer holding the color values */
private FloatBuffer colorBuffer;

private ByteBuffer indexBuffer;

private FloatBuffer textureBuffer;

private int noOfFaces = 3;

private int[] texturesID = new int[3];

private float PyramidVertices [] = {

                                          0.0f, 1.65f, 0.0f,
                                         -1.3f, 0.0f, 1.0f, 
                                          1.3f, 0.0f, 1.0f, 
                                          0.0f, 0.0f, -1.65f, 

};


 private float textures[] = {           
            //Mapping coordinates for the vertices
            0.0f, 1.65f,
            0.0f, 1.65f,
            -1.3f, 0.0f,
            1.3f, 0.0f,

    };



 private float colors[] = {
    1.0f, 0.0f, 0.0f, 1.0f, //Red
    0.0f, 1.0f, 0.0f, 1.0f, //Green
    0.0f, 0.0f, 1.0f, 1.0f, //Blue
    1.0f, 0.0f, 0.0f, 1.0f, //Red

 };


 private byte indices [] =  {   0, 2, 1,
          0, 2, 3,
          0, 1, 3,
        };

/**
 * The Pyramid constructor.
 * 
 * Initiate the buffers.
 */
public Pyramid( Context context) {
    //
    ByteBuffer byteBuf = ByteBuffer.allocateDirect(PyramidVertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(PyramidVertices);
    vertexBuffer.position(0);

    byteBuf = ByteBuffer.allocateDirect(colors.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    colorBuffer = byteBuf.asFloatBuffer();
    colorBuffer.put(colors);
    colorBuffer.position(0);

    indexBuffer = ByteBuffer.allocateDirect(indices.length);
    indexBuffer.put(indices);
    indexBuffer.position(0);

    byteBuf = ByteBuffer.allocateDirect(textures.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    textureBuffer = byteBuf.asFloatBuffer();
    textureBuffer.put(textures);
    textureBuffer.position(0);
}

/**
 * The object own drawing function.
 * Called from the renderer to redraw this instance
 * with possible changes in values.
 * 
 * @param gl - The GL Context
 */


public void draw(GL10 gl, Context context) {    
    //Set the face rotation
//  gl.glFrontFace(GL10.GL_CW);
    gl.glCullFace(GL10.GL_CCW);

     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    // gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);

        loadTexture(gl, context);

        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

        gl.glEnable(GL10.GL_TEXTURE_2D);

        // Enable the texture state
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        // Point to our buffers
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);


        gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);

    //Disable the client state before leaving
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);


}

      public void loadTexture(GL10 gl, Context context) {

          Bitmap bitmap;

          gl.glGenTextures(3, texturesID, 0); // Generate texture-ID array for 6 IDs

          gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesID[2]);

          InputStream is = context.getResources().openRawResource(R.drawable.forward);

          try {
                //BitmapFactory is an Android graphics utility for images

                bitmap = BitmapFactory.decodeStream(is);

            } finally {
                //Always clear and close
                try {
                    is.close();
                    is = null;
                } catch (IOException e) {
                }
            }


          // Generate OpenGL texture images

       // Create Nearest Filtered Texture
          gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
                  GL10.GL_LINEAR);
          gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
                  GL10.GL_LINEAR);

          // Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
          gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
                  GL10.GL_CLAMP_TO_EDGE);
          gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
                  GL10.GL_REPEAT);

             // Build Texture from loaded bitmap for the currently-bind texture ID

          GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);



      }

我接受了帮助 http://www3.ntu.edu.sg/home/ehchua/programming/android/Android_3D.html http://nehe.gamedev.net/

如何在每张脸上提供不同的图像?

2 个答案:

答案 0 :(得分:0)

有几种方法可以做到这一点,但这里有最简单的两种方法:

根据需要修改对象

一次使用少量纹理并按面部选择它们非常棘手,但简单的解决方案是将金字塔分成几个对象。然后,您可以根据需要为每个对象指定不同的纹理。

根据需要修改纹理

您可以使用称为Texture Atlas的技术。在这个解决方案中,您可以采用少量纹理并将它们拼接成一个更大的位图。然后使用此位图作为主要纹理。您还需要修改顶点UVs,因此您的一个三角形使用较大纹理的某些部分,而另一个三角形使用纹理的不同部分。使用这种技术,您可以获得一个外观,即不同的三角形使用完全不同的图像作为其纹理(即使在渲染过程中只有一个真实的texture)。

如果您需要更多详细信息,请告诉我们。

答案 1 :(得分:0)

感谢您的回复。

我找到了解决问题的方法。我创建了一个等边三角形,然后通过给出正确的旋转角度我能够旋转它以及我在每个面上放置不同的纹理。

MyPyramid类

public class PyramidNew {

   int []texturesID = new int[3];

   Bitmap []bitmap = new Bitmap[3];

  private FloatBuffer textureBuffer;

   private FloatBuffer vertexBuffer;  // Buffer for vertex-array

   private float[][] colors = {  // Colors of the 6 faces
      {1.0f, 0.5f, 0.0f, 1.0f},  // 0. orange
      {1.0f, 0.0f, 1.0f, 1.0f},  // 1. violet
      {0.0f, 1.0f, 0.0f, 1.0f},  // 2. green
      {0.0f, 0.0f, 1.0f, 1.0f},  // 3. blue
      {1.0f, 0.0f, 0.0f, 1.0f},  // 4. red
      {1.0f, 1.0f, 0.0f, 1.0f}   // 5. yellow
   };

/*   private float[] vertices = {  // Vertices for the front face
      -1.5f,  0.0f, 0.86f,  // 0. left-bottom-front
       1.5f,  0.0f, 0.86f,  // 1. right-bottom-front
       0.0f,  1.86f, 0.0f,  // 2. left-top-front
         // 3. right-top-front
   };*/
   private float[] vertices = {  // Vertices for the front face
              -1.0f,  0.0f, 0.86f,  // 0. left-bottom-front
               1.0f,  0.0f, 0.86f,  // 1. right-bottom-front
               0.0f,  1.86f, 0.0f,  // 2. left-top-front
                 // 3. right-top-front
           };
   private float textures[] = {         
            //Mapping coordinates for the vertices
            0.0f, 0.0f,
            0.0f, 1.0f,
            1.0f, 1.0f,

    };

   // Constructor - Set up the buffers
   public PyramidNew( Context context) {
     // Setup vertex-array buffer. Vertices in float. An float has 4 bytes
      System.out.println("calling Pyramid:::::::::");
      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

    ByteBuffer byteBuf = ByteBuffer.allocateDirect(textures.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    textureBuffer = byteBuf.asFloatBuffer();
    textureBuffer.put(textures);
    textureBuffer.position(0);


     InputStream stream1 = context.getResources().openRawResource(R.drawable.splash_screen);
     InputStream stream2 = context.getResources().openRawResource(R.drawable.bg);
     InputStream stream3 = context.getResources().openRawResource(R.drawable.bg1);


      try {
            //BitmapFactory is an Android graphics utility for images

            bitmap[0] = BitmapFactory.decodeStream(stream1);
            bitmap[1] = BitmapFactory.decodeStream(stream2);
            bitmap[2] = BitmapFactory.decodeStream(stream3);

        } finally {
            //Always clear and close
            try {
                stream1.close();
                stream2.close();
                stream3.close();

                stream1 = stream2 = stream3 = null;
            } catch (IOException e) {
            }
        }


   }

   // Draw the color cube
   public void draw(GL10 gl, Context context) {
      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);


      //loading the first texture in first face
      loadTexture(gl, context, 0);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);

      // rotating the face and puting the second texture in face
      gl.glRotatef(120.0f, 0.0f, 1.0f, 0.0f);
      //gl.glColor4f(colors[1][0], colors[1][1], colors[1][2], colors[1][3]);
      loadTexture(gl, context, 1);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);

      // Back - Rotate another 120 degree about y-axis and then put different texture
      gl.glRotatef(120.0f, 0.0f, 1.0f, 0.0f);
      //gl.glColor4f(colors[2][0], colors[2][1], colors[2][2], colors[2][3]);
      loadTexture(gl, context, 2);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);

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


   public void loadTexture(GL10 gl, Context context, int currentImage) {

        //  Bitmap []bitmap = new Bitmap[3];

          gl.glGenTextures(3, texturesID, 0); // Generate texture-ID array for 6 IDs

          gl.glBindTexture(GL10.GL_TEXTURE_2D, texturesID[currentImage]);

          // Generate OpenGL texture images

       // Create Nearest Filtered Texture
          gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
                  GL10.GL_LINEAR);
          gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
                  GL10.GL_LINEAR);

          // Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
          gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
                  GL10.GL_CLAMP_TO_EDGE);
          gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
                  GL10.GL_REPEAT);

             // Build Texture from loaded bitmap for the currently-bind texture ID

          GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[currentImage], 0);

            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

            gl.glEnable(GL10.GL_TEXTURE_2D);

            // Enable the texture state
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

            // Point to our buffers
            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);



      }

}