2011-10-31 130 views
0

我想顯示一個100%的寬度的屏幕正方形,然後,我認爲我必須放大它(與Z軸),直到多邊形邊框正在屏幕邊界。縮放多邊形:我可以知道多邊形邊框是否到達屏幕邊框嗎?

但我怎麼能檢測到?

感謝

MySurfaceView

public class MySurfaceView extends GLSurfaceView implements Renderer { 
private Context context; 
private Square square; 
private float xrot;     //X Rotation 
private float yrot;     //Y Rotation 
private float zrot;     //Z Rotation 
private float xspeed;    //X Rotation Speed 
private float yspeed;    //Y Rotation Speed 
private float z = -1.15f;   //Profundidad en el eje Z 
private float oldX; //valor anterior de X, para rotación 
private float oldY; //valor anterior de Y, para rotación 
private final float TOUCH_SCALE = 0.2f;  //necesario para la rotación 

public MySurfaceView(Context context, Bitmap image) { 
    super(context); 
    this.context = context; 
    setEGLConfigChooser(8, 8, 8, 8, 16, 0); //fondo transparente 
    getHolder().setFormat(PixelFormat.TRANSLUCENT); //fondo transparente 
    //Transformamos esta clase en renderizadora 
    this.setRenderer(this); 
    //Request focus, para que los botones reaccionen 
    this.requestFocus(); 
    this.setFocusableInTouchMode(true); 
    square = new Square(image); 
} 

public void onSurfaceCreated(GL10 gl, EGLConfig config) {  
    gl.glDisable(GL10.GL_DITHER);    //dithering OFF 
    gl.glEnable(GL10.GL_TEXTURE_2D);   //Texture Mapping ON 
    gl.glShadeModel(GL10.GL_SMOOTH);   //Smooth Shading 
    gl.glClearDepthf(1.0f);      //Depth Buffer Setup 
    gl.glEnable(GL10.GL_DEPTH_TEST);   //Depth Testing ON 
    gl.glDepthFunc(GL10.GL_LEQUAL); 
    gl.glClearColor(0,0,0,0); //fondo transparente 
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);   
    //Cargamos la textura del cubo. 
    square.loadGLTexture(gl, this.context); 
} 

public void onDrawFrame(GL10 gl) { 
    //Limpiamos pantalla y Depth Buffer 
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 
    gl.glLoadIdentity(); 
    //Dibujado 
    gl.glTranslatef(0.0f, 0.0f, z);   //Move z units into the screen 
    gl.glScalef(0.8f, 0.8f, 0.8f);   //Escalamos para que quepa en la pantalla 
    //Rotamos sobre los ejes. 
    gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X 
    gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y 
    gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f); //Z 
    //Dibujamos el cuadrado 
    square.draw(gl);  
    //Factores de rotación. 
    xrot += xspeed; 
    yrot += yspeed; 
} 

//si el surface cambia, resetea la vista, imagino que esto pasa cuando cambias de modo portrait/landscape o sacas el teclado físico en móviles tipo Droid. 
public void onSurfaceChanged(GL10 gl, int width, int height) { 
    if(height == 0) {      
     height = 1;       
    } 
    gl.glViewport(0, 0, width, height);  //Reset Viewport 
    gl.glMatrixMode(GL10.GL_PROJECTION); //Select Projection Matrix 
    gl.glLoadIdentity();     //Reset Projection Matrix 
    //Aspect Ratio de la ventana 
    GLU.gluPerspective(gl, 45.0f, (float)width/(float)height, 0.1f, 100.0f); 
    gl.glMatrixMode(GL10.GL_MODELVIEW);  //Select Modelview Matrix 
    gl.glLoadIdentity();     //Reset Modelview Matrix 
} 

public boolean onTouchEvent(MotionEvent event) { 
    float x = event.getX(); 
    float y = event.getY(); 
    switch (event.getAction()) 
    { 
     case MotionEvent.ACTION_MOVE: 
      //Calculamos el cambio 
      float dx = x - oldX; 
      float dy = y - oldY; 
      xrot += dy * TOUCH_SCALE; 
      yrot += dx * TOUCH_SCALE; 
      //Log.w("XXXXXX", "ACTION_MOVE_NO_ZOOM"); 
      break; 
    } 
    oldX = x; 
    oldY = y; 
    return true; //El evento ha sido manejado 
} 

public void zoomIn(){ 
    z=z+0.2f; 
    if (z>-1.0f) 
     z=-1.0f; 
} 
public void zoomOut(){ 
    z=z-0.2f; 
    if (z<-20.0f) 
     z=-20.0f; 
} 
public void rotateL(){ 
    zrot=zrot+3.0f; 
} 
public void rotateR(){ 
    zrot=zrot-3.0f; 
} 
public void reset() 
{ 
    xrot=0; 
    yrot=0; 
    zrot=0; 
    xspeed=0; 
    yspeed=0; 
    z = -5.0f; 
} 
} 

Square類:

public class Square { 
//Buffer de vertices 
private FloatBuffer vertexBuffer; 
//Buffer de coordenadas de texturas 
private FloatBuffer textureBuffer; 
//Puntero de texturas 
private int[] textures = new int[3]; 
//El item a representar 
private Bitmap image; 
//Definición de vertices 

private float vertices[] = 
{ 
    -1.0f, -1.0f, 0.0f,  //Bottom Left 
    1.0f, -1.0f, 0.0f,  //Bottom Right 
    -1.0f, 1.0f, 0.0f,  //Top Left 
    1.0f, 1.0f, 0.0f  //Top Right 
}; 
/* 
private float vertices[] = 
{ 
-0.8f, -0.8f, 0.0f,  //Bottom Left 
0.8f, -0.8f, 0.0f,  //Bottom Right 
-0.8f, 0.8f, 0.0f,  //Top Left 
0.8f, 0.8f, 0.0f 
}; 
*/ 
//Coordenadas (u, v) de las texturas  
/* 
private float texture[] = 
{   
    //Mapping coordinates for the vertices 
    0.0f, 0.0f, 
    0.0f, 1.0f, 
    1.0f, 0.0f, 
    1.0f, 1.0f 
}; 
*/ 
private float texture[] = 
{ 
    //Mapping coordinates for the vertices 
    0.0f, 1.0f, 
    1.0f, 1.0f, 
    0.0f, 0.0f, 
    1.0f, 0.0f 
}; 
//Inicializamos los buffers 
public Square(Bitmap image) { 
    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4); 
    byteBuf.order(ByteOrder.nativeOrder()); 
    vertexBuffer = byteBuf.asFloatBuffer(); 
    vertexBuffer.put(vertices); 
    vertexBuffer.position(0); 

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

    this.image=image; 
} 
//Funcion de dibujado 
public void draw(GL10 gl) { 
    gl.glFrontFace(GL10.GL_CCW); 
    //gl.glEnable(GL10.GL_BLEND); 
    //Bind our only previously generated texture in this case 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); 
    //Point to our vertex buffer 
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); 
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); 
    //Enable vertex buffer 
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
    //Draw the vertices as triangle strip 
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length/3); 
    //Disable the client state before leaving 
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
    //gl.glDisable(GL10.GL_BLEND);  
} 
//Carga de texturas 
public void loadGLTexture(GL10 gl, Context context) { 
    //Generamos un puntero de texturas 
    gl.glGenTextures(1, textures, 0);  
    //y se lo asignamos a nuestro array 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); 
    //Creamos filtros de texturas 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 
    //Diferentes parametros de textura posibles GL10.GL_CLAMP_TO_EDGE 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT); 
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);  
    /* 
    String imagePath = "radiocd5.png"; 
    AssetManager mngr = context.getAssets(); 
    InputStream is=null; 
    try { 
     is = mngr.open(imagePath); 
    } catch (IOException e1) { e1.printStackTrace(); } 
    */ 
    //Get the texture from the Android resource directory 
    InputStream is=null; 
    /* 
    if (item.equals("rim")) 
     is = context.getResources().openRawResource(R.drawable.rueda); 
    else if (item.equals("selector")) 
     is = context.getResources().openRawResource(R.drawable.selector); 
    */  
    /* 
    is = context.getResources().openRawResource(resourceId); 
    Bitmap bitmap = null; 
    try { 
     bitmap = BitmapFactory.decodeStream(is); 
    } finally { 
     try { 
      is.close(); 
      is = null; 
     } catch (IOException e) { 
     } 
    } 
    */ 
    Bitmap bitmap =image;  
    //con el siguiente código redimensionamos las imágenes que sean mas grandes de 256x256. 
    int newW=bitmap.getWidth(); 
    int newH=bitmap.getHeight(); 
    float fact; 
    if (newH>256 || newW>256) 
    { 
     if (newH>256) 
     { 
      fact=(float)255/(float)newH; //porcentaje por el que multiplicar para ser tamaño 256 
      newH=(int)(newH*fact); //altura reducida al porcentaje necesario 
      newW=(int)(newW*fact); //anchura reducida al porcentaje necesario 
     } 
     if (newW>256) 
     { 
      fact=(float)255/(float)newW; //porcentaje por el que multiplicar para ser tamaño 256 
      newH=(int)(newH*fact); //altura reducida al porcentaje necesario 
      newW=(int)(newW*fact); //anchura reducida al porcentaje necesario 
     } 
     bitmap=Bitmap.createScaledBitmap(bitmap, newW, newH, true); 
    }  
    //con el siguiente código transformamos imágenes no potencia de 2 en imágenes potencia de 2 (pot) 
    //meto el bitmap NOPOT en un bitmap POT para que no aparezcan texturas blancas. 
    int nextPot=256; 
    int h = bitmap.getHeight(); 
    int w = bitmap.getWidth(); 
    int offx=(nextPot-w)/2; //distancia respecto a la izquierda, para que la imagen quede centrada en la nueva imagen POT 
    int offy=(nextPot-h)/2; //distancia respecto a arriba, para que la imagen quede centrada en la nueva imagen POT 
    Bitmap bitmap2 = Bitmap.createBitmap(nextPot, nextPot, Bitmap.Config.ARGB_8888); //crea un bitmap transparente gracias al ARGB_8888 
    Canvas comboImage = new Canvas(bitmap2); 
    comboImage.drawBitmap(bitmap, offx, offy, null); 
    comboImage.save(); 

    //Usamos Android GLUtils para espcificar una textura de 2 dimensiones para nuestro bitmap 
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap2, 0); 

    //Checkeamos si el GL context es versión 1.1 y generamos los Mipmaps por Flag. Si no, llamamos a nuestra propia implementación 
    if(gl instanceof GL11) { 
     gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE); 
     GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap2, 0); 
    } else { 
     buildMipmap(gl, bitmap2); 
    } 
    //Limpiamos los bitmaps 
    bitmap.recycle(); 
    bitmap2.recycle(); 
} 
//Nuestra implementación de MipMap. Escalamos el bitmap original hacia abajo por factor de 2 y lo asignamos como nuevo nivel de mipmap 
private void buildMipmap(GL10 gl, Bitmap bitmap) { 
    int level = 0; 
    int height = bitmap.getHeight(); 
    int width = bitmap.getWidth(); 
    while(height >= 1 || width >= 1) { 
     GLUtils.texImage2D(GL10.GL_TEXTURE_2D, level, bitmap, 0); 
     if(height == 1 || width == 1) { 
      break; 
     } 
     level++; 
     height /= 2; 
     width /= 2; 
     Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true); 
     bitmap.recycle(); 
     bitmap = bitmap2; 
    } 
} 
} 

更新的代碼:

/////////////// NEW CODE FOR SCALING THE AR IMAGE TO THE DESIRED WIDTH ///////////////// 

     //and them, call the getCurrentModelView() for the ModelView matrix: 
     mg.getCurrentModelView(gl); 
     //values are stored at the mg.mModelView array, so: 
     //Log.i("Translation Z value", Float.toString(mg.mModelView[14]));//prints the current translation z value    
     //to get the current Projection matrix: 
     mg.getCurrentProjection(gl); 
     //values are stored at the mProjection, so: 
     //Log.i("First projection matrix value", Float.toString(mg.mProjection[0]));//prints the first projection matrix value 

     float [] modelMatrix = new float[16]; 
     float [] projMatrix = new float[16];   
     modelMatrix=mg.mModelView; 
     projMatrix=mg.mProjection; 
     // Now I am going to assume you set the model and projection matrices correctly 
     // so I won't show that here. 
     int [] mView = new int[4]; 
     // Fill this with your window width and height 
     mView[0] = 0; 
     mView[1] = 0; 
     mView[2] = 800; //width 
     mView[3] = 480; //height 
     // Make sure you have 3 components in this array even if the screen only needs 2 
     float [] outputCoords = new float[3]; 
     // Now I also assume that objX, objY, objZ are the coordinates of one of your borders 
     GLU.gluProject(-1.0f, -1.0f, 0.0f, modelMatrix, 0, projMatrix, 0, mView, 0, outputCoords, 0); 

回答

1

使用gluProject項目在三維座標到2D屏幕合作縱座標。如果屏幕座標爲0或與您的寬度或高度相匹配,則它將觸摸屏幕邊框。

編輯的詳細資料:

只看定義:http://developer.android.com/reference/android/opengl/GLU.html。 基本上你把它的頂點的三個座標作爲objX objY objZ傳遞給它。您還將模型視圖矩陣和投影矩陣以及視圖作爲包含窗口大小的浮點數組傳遞給它。然後在win變量中得到結果窗口座標。下面是一個簡單的例子:

float [] modelMatrix = new float[16]; 
float [] projMatrix = new float[16]; 

// Now I am going to assume you set the model and projection matrices correctly 
// so I won't show that here. 

float [] mView = new float[4]; 
// Fill this with your window width and height 
view[0] = 0; 
view[1] = 0; 
view[2] = width; 
view[3] = height; 

// Make sure you have 3 components in this array even if the screen only needs 2 
float [] outputCoords = new float[3] 

// Now I also assume that objX, objY, objZ are the coordinates of one of your borders 
gluProject(objX, objY, objZ, modelMatrix, 0, projMatrix, 0, view, 0, outputCoords, 0); 

您還需要保持跟蹤你的矩陣,因爲Android遊戲不這樣做的OpenGL的一些版本。看到矩陣跟蹤的例子:http://www.41post.com/1540/programming/android-opengl-get-the-modelview-matrix-on-15-cupcake

+0

你能解釋一下嗎?也許有一個簡單的代碼示例?我的技能與OpenGl只是新手技能,我試圖找到谷歌的例子做你的意思,但我找不到他們 – NullPointerException

+0

謝謝你的更新,在那裏我必須做的代碼,在方形課?或在MyGLsurfaceVIew類? – NullPointerException

+0

我不知道你的代碼是如何構造的,所以我不知道它應該放在哪裏。 – NickLH