gluUnProject Android OpenGL ES 1.1用法

abd*_*nce 6 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]);

}
Run Code Online (Sandbox Code Playgroud)

Matrix4x4只是float []缓冲区的包装器;

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

例如,当我尝试运行translateScreenCoordsToWorld(new 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);
}
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)

相机配置以下坐标:

camera.position = { 0, 0, 65 };     
camera.target = { 0, 0, 0 }
camera.upAxis = { 0, 1, 0 }
Run Code Online (Sandbox Code Playgroud)

Dar*_*ner 3

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

  1. 绘制一帧,这样所有的深度缓冲区信息就准备好了。
  2. 抓取视口/矩阵/屏幕坐标
  3. 反转屏幕 y 坐标。
  4. 读取给定像素处的深度值。这实际上是一个标准化的 z 坐标。
  5. 将 x、y 和 z 输入到 glUnProject 中。

这最终给出了给定像素片段的世界空间坐标。可以在这里找到更详细的指南。无论如何,我可以在您的代码中看到两个可能的错误。第一个是通常您必须反转 y 屏幕坐标(链接上的教程详细说明了原因),第二个是您始终将 0 作为 z 值传递给 gluUnProject。执行此操作会取消顶点的投影,就好像它位于近平面上一样。这是你想要的吗?

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

  • 你是对的,我可能应该记住这一点。有两种解决方法,第一种是在近平面和远平面之间创建一条射线并运行手动相交测试,(这可能非常棘手),[此处](http://softwareprodigy.blogspot.com/2009 /08/gluunproject-for-iphone-opengl-es.html),第二个是创建一个帧缓冲区对象,并从中读取深度缓冲区值。或者,您可以跳过 gluUnProject 并尝试实现拾取。[参见此处](http://stackoverflow.com/questions/7364693/how-to-get-object-in-webgl-3d-space-from-a-mouse-click-cooperative) (3认同)