gluUnProject Android OpenGL ES 1.1用法

时间:2011-09-15 21:10:14

标签: android opengl-es

我正在尝试使用gluUnProject将Windows coords转换为世界坐标。 我不是试图在模拟器或较旧的Android系统(使用OpenGL ES v1.0)中获取工作样本,这不是关于GL功能可用性的问题。我正在尝试使用OpenGL ES 1.1处理真实设备,glGet函数返回非零结果。

有样本:

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只是float []缓冲区的包装器;

使用此功能我正在尝试创建一个平面来填充所有屏幕或检测当前投影矩阵的最大世界坐标,但它根本不起作用,因为我不确定我是否正确使用这些功能。

例如,当我尝试运行 translateScreenCoordsToWorld (新的Vector2(480,800))时,它返回非常小的坐标值Vector3(0.27f,0.42f,-1.0f)。

任何人都可以使用一个定位相机为GL_PROJECTION模式提供良好的样本用量gluUnProject。

更新 感谢您的良好链接。但它仍然不适合我:( 现在我的功能看起来像:

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);
}

这是我的相机配置的地方:

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);
}

配置了以下坐标的相机:

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

1 个答案:

答案 0 :(得分:3)

好的,通常在使用gluUnProject时,您试图获取屏幕上像素的世界空间坐标。您需要将三条信息(除了矩阵之外)放入glUnProject,屏幕x坐标,屏幕y坐标以及与该像素对应的深度缓冲区值。这个过程通常是这样的:

  1. 绘制一个框架,以便所有深度缓冲区信息都准备就绪。
  2. 抓住视口/矩阵/屏幕坐标
  3. 反转屏幕y坐标。
  4. 读取给定像素的深度值。这实际上是一个标准化的z坐标。
  5. 将x,y和z输入glUnProject。
  6. 这最终给出了像素的给定片段的世界空间坐标。可以找到更详细的指南here。无论如何,我可以在你的代码中看到两个可能的错误。第一个是通常你必须反转y屏幕坐标,(链接上的教程详细说明原因),第二个是你总是将0作为z值传递给gluUnProject。这样做会将顶点取消投影,就像它在近平面上一样。这是你想要的吗?

    无论如何,如果我误解你的问题,请原谅我。