2012-03-09 85 views
0

我想在我的游戏中的3D模型上叠加一个图标。我使用gluProject得到模型的中心点的屏幕坐标,然后利用这些数据来绘制一个自定义视图图标:android OpenGL-Es gluProject结果不准确?

在我的渲染器类:

private void projectScreenCoords(GLSurfaceView view, GraphicsEntity ge, GL10 gl){ 

    MatrixGrabber matrixGrabber = new MatrixGrabber(); 
    matrixGrabber.getCurrentModelView(gl); 
    float[] modelMat = matrixGrabber.mModelView; 
    matrixGrabber.getCurrentProjection(gl); 
    float[] projMat = matrixGrabber.mProjection; 
    gl.glMatrixMode(GL10.GL_MODELVIEW); 

    // view port 
    int[] viewport = new int[]{view.getTop(),view.getLeft(),view.getWidth(),view.getHeight()}; 


    float[] vector = new float[4];  
    GLU.gluProject(ge.getTransform().tx, ge.getTransform().ty, ge.getTransform().tz, modelMat, 0, projMat, 0, viewport, 0, vector, 0); 

    ge.setScreenCoords(vector[0], viewport[3] - vector[1]); 

} 

和我的自定义视图:

protected void onDraw (Canvas canvas){ 
    Vector<GraphicsEntity> scene = renderer.getForegroundScene(); 

    for(int i = 0;i<scene.size();i++){ 
     GraphicsEntity ge = scene.get(i); 
     float[] xy = ge.getScreenCoords(); 
     if(xy[0]>-1 && xy[1]>-1){ 
      canvas.drawBitmap(bitmap, xy[0]-bitmapWidth/2, xy[1]-bitmapHeight/2, null); 
     } 
     invalidate(); 
    } 

} 

并且其中设置我投影矩阵:

protected void setProjectionMatrix(GL10 gl){ 

     float ratio = (float) viewportWidth/viewportHeight; 
     gl.glMatrixMode(GL10.GL_PROJECTION); 
     gl.glLoadIdentity(); 
     gl.glFrustumf(-ratio*zoom, ratio*zoom, -1*zoom, 1*zoom, nearPlane, farPlane); 

} 

然而,第Ë进一步从屏幕的中心,进一步关闭模型中心的图标绘制:

enter image description here

显然,如果这只是视口大小,这是不正确的(由于在酒吧顶部/底部),那么图标只会在y轴上关闭,但它们也在x轴上关闭。我错过了什么/做错了什么?此外,我还没有使用gluProject返回的第三个值,但它总是有0.7的值,所以我不太确定它将如何使用?

使用SDK版本7,我已经在多个设备(运行Android 2.1的ZTE Blade和运行2.3.4的Kindle Fire)上测试了这一结果。 viewportWidth/Height和view.getWidth/Height()是相同的,而view.getTop/Left()返回0. MatrixGrabber代码适用于gluUnProject,所以我相当有信心不是问题


编辑:这里是我的GL相关的绘制代码的其余部分:

在渲染:

// camera variables 
protected float FOV = 60.0f; 
protected float nearPlane = 3; 
protected float farPlane = 7; 

protected float eyeX = 0; 
protected float eyeY = 0; 
protected float eyeZ = 0; 

protected float centreX = 0; 
protected float centreY = 0; 
protected float centreZ = ((farPlane - nearPlane)/2) + nearPlane; 

protected float upX = 0; 
protected float upY = 1; 
protected float upZ = 0; 

protected float viewportWidth; 
protected float viewportHeight; 

// user camera control variables 
protected float zoom = 1; 
protected float rotatedX = 0; 
protected float rotatedY = 0; 
protected boolean zoomed = true; 
protected TrackingTransform tracking; 

protected void setWorldTransform(GL10 gl){ 

    gl.glMatrixMode(GL10.GL_MODELVIEW); 
    gl.glLoadIdentity(); 

    // transforms the centre position to 0,0,0 
    gl.glTranslatef(-centreX, -centreY, -centreZ); 

} 

protected void setModelRotation(GL10 gl, GraphicsEntity ge){ 

    if(ge.isTrackerball()){ 

     gl.glRotatef(rotatedX, 1.0f, 0, 0); 
     gl.glRotatef(rotatedY, 0, -1.0f, 0); 

     if(tracking!=null){ 
      synchronized(tracking){ 
       tracking.transform(gl); 
      } 
     } 


    } else if(ge.isBackground()){ 

     gl.glTranslatef(centreX, centreY, centreZ); 

     gl.glRotatef(rotatedX, 1.0f, 0, 0); 
     gl.glRotatef(rotatedY, 0, -1.0f, 0); 

     if(ge.isSkybox()==true){ 

      ge.getTransform().sx = nearPlane + 1.0f; 
      ge.getTransform().sy = nearPlane + 1.0f; 
      ge.getTransform().sz = nearPlane + 1.0f; 

      ge.getTransform().tx = 0; 
      ge.getTransform().ty = 0; 
      ge.getTransform().tz = 0; 

     } 

    }   

} 

protected void setModelViewMatrix(GL10 gl){ 
    gl.glMatrixMode(GL10.GL_MODELVIEW); 
    gl.glLoadIdentity(); 

    // not used: 
    //GLU.gluLookAt(gl, eyeX, eyeY, eyeZ, centreX, centreY, centreZ, upX, upY, upZ);   
} 

@Override 
public void onDrawFrame(GL10 gl) { 

    // Set up various things before drawing 
    gl.glFrontFace(GL10.GL_CW); 
    gl.glEnable(GL10.GL_CULL_FACE); 
    gl.glCullFace(GL10.GL_FRONT); 
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 
    gl.glEnable(GL10.GL_DEPTH_TEST); 

    // change projection matrix  
    float oldzoom = zoom; 
    zoom = 1.0f; 
    setProjectionMatrix(gl); 
    zoom = oldzoom; 

    // set global world transform (also changes to modelview) 
    setWorldTransform(gl); 

    // loop through and draw background models 
    for(int i = 0;i<backgroundGraphicsEntities.size();i++){ 

     GraphicsEntity ge = backgroundGraphicsEntities.get(i); 

     SimpleTransform t = ge.getTransform(); 
     int modelIndex = ge.getModelIndex(); 

     if(modelIndex>=0){ 

      gl.glPushMatrix(); 

      setModelRotation(gl, ge); 

      t.transform(gl); 

      if(ge.isSprite() && gl11flag){ 

       Sprite s = sprites.get(modelIndex); 
       s.draw((GL11) gl, ge); 

      } else { 

       Model m = models.get(modelIndex); 
       if(m!=null){ 
        m.draw(gl); 
       } 

      } 

      gl.glPopMatrix(); 

     } 

     if(i==0 && ge.isSkybox()){ 
      // if skybox, reset depth bit 
      gl.glClear(GL10.GL_DEPTH_BUFFER_BIT); 
     } 

    } 

    gl.glClear(GL10.GL_DEPTH_BUFFER_BIT); 

    // change projection matrix (if zoomed)  
    setProjectionMatrix(gl); 

    // change back to modelview 
    gl.glMatrixMode(GL10.GL_MODELVIEW); 

    // loop through and draw models 
    for(int i = 0;i<graphicsEntities.size();i++){ 

     GraphicsEntity ge = graphicsEntities.get(i); 

     SimpleTransform t = ge.getTransform(); 
     int modelIndex = ge.getModelIndex(); 

     if(modelIndex>=0){ 

      gl.glPushMatrix(); 

      setModelRotation(gl, ge); 

      t.transform(gl); 

      if(ge.isSprite() && gl11flag){ 

       Sprite s = sprites.get(modelIndex); 
       s.draw((GL11) gl, ge); 

      } else { 

       Model m = models.get(modelIndex); 
       if(m!=null){ 
        m.draw(gl); 
       } 

       if(projectScreenCoords){ 
        projectScreenCoords(glSurfaceView, ge, gl); 
       } 

      } 

      gl.glPopMatrix(); 

     } 
    } 

@Override 
public void onSurfaceChanged(GL10 gl, int width, int height) { 

    viewportWidth = width; 
    viewportHeight = height; 

    gl.glViewport(0, 0, width, height); 

    setProjectionMatrix(gl); 

} 

@Override 
public void onSurfaceCreated(GL10 gl, EGLConfig config) { 

    if(gl instanceof GL11){ 
     gl11flag = true; 
    } 

    gl.glClearColor(0, 0, 0, 1); 
    gl.glShadeModel(GL10.GL_SMOOTH); 
    gl.glEnable(GL10.GL_DEPTH_TEST); 
    gl.glDepthMask(true); 
    //gl.glClearDepthf(1.0f); 
    gl.glDepthFunc(GL10.GL_LEQUAL);   
    //gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); 

    setProjectionMatrix(gl); 

} 

,然后在SimpleTransform(即什么被调用时ge.getTransform()变换(GL)被称为):

public void transform(GL10 gl) { 
    gl.glTranslatef(tx, ty, tz);   
    gl.glRotatef(rz, 0, 0, 1); 
    gl.glRotatef(ry, 0, 1, 0); 
    gl.glRotatef(rx, 1, 0, 0); 
    gl.glScalef(sx, sy, sz); 
} 

和TrackingTransform:

@Override 
public void transform(GL10 gl) { 
    gl.glTranslatef(-tx, -ty, -tz);  
} 

终于在model.draw():

public void draw(GL10 gl){ 

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 

    // Pass the vertex buffer in 
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, 
          vertices); 

    int textureID = material.getTexture().getTextureID(); 

    if(textureID>=0){ 

     // Enable Textures 
     gl.glEnable(GL10.GL_TEXTURE_2D); 

     // Get specific texture. 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID); 

     // Use UV coordinates. 
     gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 

     // Pass in texture coordinates   
     gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureCoordinates); 

    } 

    // Pass in vertex normals 
    gl.glNormalPointer(GL10.GL_FLOAT, 0, normals); 

    gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); 

    gl.glDrawElements(GL10.GL_TRIANGLES, numindices,GL10.GL_UNSIGNED_SHORT, indices); 

    gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); 

    if(textureID>=0){ 
     // Disable buffers   
     gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
    } 

    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 

} 
+0

你能告诉你的GL绘图代码? – 2012-03-09 14:46:55

+0

添加我的绘图代码 – 2012-03-09 17:08:04

回答

0

的问题是不是在gluProject代码在所有。事实上,这是做翻译打电话gluProject之前完成:

在onDrawFrame:

   Model m = models.get(modelIndex); 
       if(m!=null){ 
        m.draw(gl); 

        gl.glTranslatef(-tracking.getTransform().tx, -tracking.getTransform().ty, -tracking.getTransform().tz); 

        if(tickcount % projectFrequency == 0){ 
         projectScreenCoords(glSurfaceView, ge, gl); 
        } 

       }