Note that there are some explanatory texts on larger screens.

plurals
  1. POandroid OpenGL-Es gluProject results not accurate?
    primarykey
    data
    text
    <p>I want to overlay an icon on top of 3D models in my game. I'm using gluProject to get the screen coordinates of the centre point of the models, and then using that data to draw icons on a custom view:</p> <p>In my renderer class:</p> <pre><code>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]); } </code></pre> <p>and my custom view:</p> <pre><code>protected void onDraw (Canvas canvas){ Vector&lt;GraphicsEntity&gt; scene = renderer.getForegroundScene(); for(int i = 0;i&lt;scene.size();i++){ GraphicsEntity ge = scene.get(i); float[] xy = ge.getScreenCoords(); if(xy[0]&gt;-1 &amp;&amp; xy[1]&gt;-1){ canvas.drawBitmap(bitmap, xy[0]-bitmapWidth/2, xy[1]-bitmapHeight/2, null); } invalidate(); } } </code></pre> <p>and where I set my projection matrix:</p> <pre><code> 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); } </code></pre> <p>However, the further from the centre of the screen, the further off the centre of the model the icon is drawn:</p> <p><img src="https://i.stack.imgur.com/TX7WC.png" alt="enter image description here"></p> <p>Clearly, if it was just the viewport size that was incorrect (due to the bars at the top/bottom) then the icons would be off just in the y-axis, but they are off in the x-axis as well. What am I missing / doing wrong? Also I haven't used the 3rd value returned by gluProject, but this always has a value of 0.7 so I'm not quite sure how it would be used if at all?</p> <p>Using SDK version 7, I've tested this on multiple devices (ZTE Blade running android 2.1 and Kindle Fire running 2.3.4) with the same results. viewportWidth/Height and view.getWidth/Height() are the same, and view.getTop/Left() returns 0. The MatrixGrabber code works for gluUnProject, so I'm reasonably confident that isn't the problem</p> <hr> <p>EDIT: here is the rest of my GL-related drawing code:</p> <p>In renderer:</p> <pre><code> // 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&lt;backgroundGraphicsEntities.size();i++){ GraphicsEntity ge = backgroundGraphicsEntities.get(i); SimpleTransform t = ge.getTransform(); int modelIndex = ge.getModelIndex(); if(modelIndex&gt;=0){ gl.glPushMatrix(); setModelRotation(gl, ge); t.transform(gl); if(ge.isSprite() &amp;&amp; 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 &amp;&amp; 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&lt;graphicsEntities.size();i++){ GraphicsEntity ge = graphicsEntities.get(i); SimpleTransform t = ge.getTransform(); int modelIndex = ge.getModelIndex(); if(modelIndex&gt;=0){ gl.glPushMatrix(); setModelRotation(gl, ge); t.transform(gl); if(ge.isSprite() &amp;&amp; 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); } </code></pre> <p>and then in SimpleTransform (i.e. what gets called when ge.getTransform().transform(gl) is called):</p> <pre><code>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); } </code></pre> <p>and for TrackingTransform:</p> <pre><code>@Override public void transform(GL10 gl) { gl.glTranslatef(-tx, -ty, -tz); } </code></pre> <p>and finally in model.draw():</p> <pre><code>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&gt;=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&gt;=0){ // Disable buffers gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); } gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload