2011-09-15 18 views
5

Sto provando a usare gluUnProject per convertire Windows Coords in World Coord. Non sto cercando di ottenere un campione funzionante in emulatore o sistemi Android precedenti (con OpenGL ES v1.0) e questa non è una domanda sulla disponibilità della funzione GL. Sto provando a lavorare sul dispositivo reale con OpenGL ES 1.1 e le funzioni glGet restituiscono risultati diversi da zero.gluUnProject Android OpenGL ES 1.1 Uso

C'è campione:

public Vector3 translateScreenCoordsToWorld(Vector2 screenCoords) { 
gl.glLoadIdentity(); 

final Matrix4x4 modelViewMatrix = new Matrix4x4(); 
final Matrix4x4 projectMatrix = new Matrix4x4(); 

int[] viewVectorParams = new int[4]; 
gl.glGetIntegerv(GL11.GL_VIEWPORT,viewVectorParams,0); 
gl.glGetFloatv(GL11.GL_MODELVIEW_MATRIX,modelViewMatrix.buffer,0); 
gl.glGetFloatv(GL11.GL_PROJECTION_MATRIX,projectMatrix.buffer,0); 

float[] output = new float[4]; 
GLU.gluUnProject(
    screenCoords.x, screenCoords.y, 0, 
    modelViewMatrix.buffer, 0, 
    projectMatrix.buffer, 0, 
    viewVectorParams, 0, 
    output, 0);    

return new Vector3(output[0],output[1],output[2]); 

} 

Matrix4x4 è solo un involucro per float [] tampone;

Con questa funzione sto provando a creare un piano per riempire tutto lo schermo o rilevare le coordinate mondiali massime per la matrice di proiezione corrente, ma non funziona affatto perché non sono sicuro di utilizzare correttamente queste funzioni.

Per esempio, quando sto cercando run translateScreenCoordsToWorld (nuova Vector2 (480.800)) restituisce molto piccoli coordinate valori Vector3 (0.27f, 0.42f, -1.0f).

Qualcuno può fornire un buon esempio di utilizzo gluUnProject per la modalità GL_PROJECTION con una telecamera posizionata.

Aggiornamento Grazie per i buoni collegamenti. Ma e' ancora non funziona per me :( Ora la mia funzione è simile:

public Vector3 translateScreenCoordsToWorld(Vector2 screenCoords) { 

float winX = screenCoords.x, winY = screenCoords.y, winZ = 0; 
winY = (float)currentViewVectorParams[3] - winY; 

float[] output = new float[4]; 
GLU.gluUnProject(
    winX, winY, winZ, 
    currentModelViewMatrix.buffer, 0, 
    currentProjectMatrix.buffer, 0, 
    currentViewVectorParams, 0, 
    output, 0 
);    

Vector3 nearPlane = new Vector3(output[0],output[1],output[2]); 
winZ = 1.0f;   
GLU.gluUnProject(
    winX, winY, winZ, 
    currentModelViewMatrix.buffer, 0, 
    currentProjectMatrix.buffer, 0, 
    currentViewVectorParams, 0, 
    output, 0 
);    
Vector3 farPlane = new Vector3(output[0],output[1],output[2]); 

farPlane.sub(nearPlane); 
farPlane.div(nearPlane.length()); 

float dot1, dot2; 

Vector3 pointInPlane = new Vector3(), pointPlaneNormal = new Vector3(0,0,-1); 
pointInPlane.sub(nearPlane); 

dot1 = (pointPlaneNormal.x * pointInPlane.x) + (pointPlaneNormal.y * pointInPlane.y) + (pointPlaneNormal.z * pointInPlane.z); 
dot2 = (pointPlaneNormal.x * farPlane.x) + (pointPlaneNormal.y * farPlane.y) +(pointPlaneNormal.z * farPlane.z); 

float t = dot1/dot2; 
farPlane.mul(t); 

return farPlane.add(nearPlane); 
} 

e questo è dove la mia macchina fotografica configurazione:

public void updateCamera() { 
Camera camera = scene.getCamera(); 
GLU.gluLookAt(gl, 
    camera.position.x, camera.position.y, camera.position.z, 
    camera.target.x, camera.target.y, camera.target.z, 
    camera.upAxis.x, camera.upAxis.y, camera.upAxis.z 
); 

    gl.glGetIntegerv(GL11.GL_VIEWPORT,currentViewVectorParams,0);  
    gl.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, currentModelViewMatrix.buffer,0); 
    gl.glGetFloatv(GL11.GL_PROJECTION_MATRIX,currentProjectMatrix.buffer,0); 
} 

La fotocamera configurato con le seguenti coordinate:

camera.position = { 0, 0, 65 };  
camera.target = { 0, 0, 0 } 
camera.upAxis = { 0, 1, 0 } 

risposta

3

Ok, normalmente quando si usa gluUnProject si sta tentando di ottenere la coordinata dello spazio mondiale di un pixel sullo schermo. Sono necessarie tre informazioni (diverse dalle matrici) per inserire int o glUnProject, una coordinata x dello schermo, una coordinata y dello schermo e il valore del buffer di profondità corrispondente a quel pixel. Il processo normalmente funziona in questo modo:

  1. Disegna un frame, quindi tutte le informazioni del buffer di profondità sono pronte.
  2. Grab viewport/matrici/coordini
  3. Invertire la coordinata y dello schermo.
  4. Legge il valore di profondità di un dato pixel. Questa è effettivamente una coordinata z normalizzata.
  5. Immettere x, yez in glUnProject.

Questo finisce per dare la coordinata dello spazio mondiale del frammento di un pixel dato. Una guida molto più dettagliata può essere trovata here. Ad ogni modo, posso vedere due possibili errori nel tuo codice. La prima è che normalmente devi invertire la coordina dello schermo y (il tutorial sul collegamento spiega perché), il secondo è che stai sempre passando 0 come valore z a gluUnProject. Facendo questo un-proietta il vertice come se fosse sul piano vicino. È questo che vuoi?

In ogni caso, perdonami se ho letto male la tua domanda.

+0

Grazie! È un buon articolo di NeHe. Ma non esiste un supporto GL_DEPTH_COMPONENT in OpenGL ES (Android).Non posso chiamare glReadPixels (Winx, vinoso, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ); :( C'è qualche soluzione alternativa? – abdolence

+3

Hai ragione, probabilmente avrei dovuto ricordare che. Ci sono due arounds di lavoro, la in primo luogo è di creare un raggio tra il vicino e il lontano piano ed eseguire un test di intersezione manuale, (che potrebbe essere piuttosto complicato), [qui] (http://softwareprodigy.blogspot.com/2009/08/gluunproject-for- iphone-opengl-es.html), il secondo è quello di creare un oggetto frame buffer e leggere i valori del buffer di profondità da questo, in alternativa puoi saltare gluUnProject e provare a implementare il picking. [Vedi qui] (http: // stackoverflow. it/questions/7364693/how-to-get-object-in-webgl-3d-space-from-a-mouse-click-coordinate) –

+0

Interessati ancora. Grazie! Ho provato a implementare l'intersezione manuale, ma non è ancora funzionante :(Si prega di guardare l'aggiornamento e – abdolence