我正在构建一个小型 Android 应用程序,它将在用户触摸时添加一个立方体。 z 深度始终为 -10,屏幕始终处于横向模式。这个问题好像被问过很多次了,但是我跑不起来,原谅我是opengl的新手。 我对与 gluUnproject 一起使用的屏幕坐标/窗口坐标/对象坐标感到很困惑。据我了解,屏幕是用户触摸时,我们甚至从运动中获得 x 和 y。窗口坐标是我们加载身份的时候,对象坐标是我们转换单位矩阵得到对象坐标的时候。是吗?
这是我的代码,矩阵堆叠来自 android api 示例。请指出我做错了什么。
绘图部分:
public void draw(GL10 gl) {
for (GLObject glObject : list) {
if (glObject != null) {
gl.glLoadIdentity();
glObject.draw(gl);
}
}
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
if (isTouching) {
boolean addObject = false;
for (GLObject glObject : list) {
addObject = glObject.checkTouch(gl, x, y);
}
if (!addObject) {
i++;
Log.d("i", i + "");
addGLObject(gl);
}
isTouching = false;
}
}
这是添加对象的代码
private void getMatrix(GL10 gl, int mode, float[] mat) {
GLView.matrixTrackingGL.glMatrixMode(mode);
GLView.matrixTrackingGL.getMatrix(mat, 0);
}
public void addGLObject(GL10 gl) {
float[] XY = getWorldCoordinate(gl, x, y);
if (XY != null) {
// XY[0] = (float) (x - Main.SCREEN_WIDTH / 2) / 10;
//
// XY[1] = (float) (Main.SCREEN_HEIGHT / 2 - y) / 10;
GLObject glObject = new GLObject(colors, XY[0], XY[1]);
Log.d("Object position", "X: " + XY[0] + " Y: " + XY[1]);
list.add(glObject);
}
}
private float[] getWorldCoordinate(GL10 gl, int x, int y) {
float[] modelMatrix = new float[16];
float[] projMatrix = new float[16];
int[] viewport = {0, 0, Main.SCREEN_WIDTH, Main.SCREEN_HEIGHT};
getMatrix(gl, GL10.GL_MODELVIEW, modelMatrix);
getMatrix(gl, GL10.GL_PROJECTION, projMatrix);
float[] output = new float[4];
GLU.gluUnProject(x, viewport[1] + viewport[3] - y, -10, modelMatrix, 0, projMatrix, 0, viewport, 0, output, 0);
return new float[] {output[0]/output[3], output[1]/output[3]};
}
public class GLObject {
private float[] vertices = { 1.000000f, 1.000000f, -1.000000f, 1.000000f,
-1.000000f, -1.000000f, -1.000000f, -1.000000f, -1.000000f,
-1.000000f, 1.000000f, -1.000000f, 1.000000f, 1.000000f, 1.000000f,
1.000000f, -1.000001f, 1.000000f, -1.000000f, -1.000000f,
1.000000f, -1.000000f, 1.000000f, 1.000000f, };
private short[] faces = { 0, 1, 2, 0, 2, 3, 4, 7, 6, 4, 6, 5, 0, 4, 5, 0,
5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 4, 0, 3, 4, 3, 7 };
private float[] colors;
private float[] rot = { 0.0f, 0.0f, 0.0f };
private Float positionX, positionY;
private int alpha = 0;
// Our vertex buffer.
private FloatBuffer vertexBuffer;
// Our index buffer.
private ShortBuffer faceBuffer;
public GLObject() {
init();
}
public GLObject(float[] colors, float x, float y) {
this.colors = colors.clone();
this.positionX = x;
this.positionY = y;
if (positionX.intValue() % 2 == 0) {
rot[0] = 1.0f;
} else {
if (positionY.intValue() % 2 == 0) {
rot[1] = 1.0f;
} else {
rot[2] = 1.0f;
}
}
init();
}
private void init() {
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer ibb = ByteBuffer.allocateDirect(faces.length * 2);
ibb.order(ByteOrder.nativeOrder());
faceBuffer = ibb.asShortBuffer();
faceBuffer.put(faces);
faceBuffer.position(0);
}
public boolean checkTouch(GL10 gl, int x, int y) {
boolean isTouched = false;
ByteBuffer pixels = ByteBuffer.allocate(4);
gl.glReadPixels(x, Main.SCREEN_HEIGHT - y, 1, 1, GL10.GL_RGBA,
GL10.GL_UNSIGNED_BYTE, pixels);
Log.d("COLOR",
pixels.get(0) + " " + pixels.get(1) + " " + pixels.get(2) + " "
+ pixels.get(3));
// isTouched always false to test always add object to screen
return isTouched;
}
public void draw(GL10 gl) {
// Counter-clockwise winding.
gl.glFrontFace(GL10.GL_CCW); // OpenGL docs
// Enable face culling.
gl.glEnable(GL10.GL_CULL_FACE); // OpenGL docs
// What faces to remove with the face culling.
gl.glCullFace(GL10.GL_BACK); // OpenGL docs
// Enabled the vertices buffer for writing and to be used during
// rendering.
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// OpenGL docs.
// Enable color
gl.glColor4f(colors[0], colors[1], colors[2], 1.0f);
// Specifies the location and data format of an array of vertex
// coordinates to use when rendering.
gl.glPushMatrix();
gl.glTranslatef(positionX, positionY, -10);
// rotate
alpha += 1;
gl.glRotatef(alpha, rot[0], rot[1], rot[2]);
// draw
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, // OpenGL docs
vertexBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, faces.length,// OpenGL docs
GL10.GL_UNSIGNED_SHORT, faceBuffer);
gl.glPopMatrix();
// Disable the vertices buffer.
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // OpenGL docs
// Disable face culling.
gl.glDisable(GL10.GL_CULL_FACE); // OpenGL docs
}
绘制:
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
// Clears the screen and depth buffer.
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | // OpenGL docs.
GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_PROJECTION);
// Reset the projection matrix
gl.glLoadIdentity();
GLU.gluPerspective(gl, 90.0f, Main.SCREEN_WIDTH/Main.SCREEN_HEIGHT, 3.0f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 4.0f, 2.0f, 1.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
// draw object
glObjectManager.draw(gl);
}
最佳答案
这与横向模式无关,问题是您在 z 轴上将立方体平移了 -10。尝试输入 -100 的值,所有立方体都将位于中心。然后尝试将 0 作为 z 值 (x, y, 0)。立方体将离屏幕中心更远,更接近您期望的位置。
看http://tle.tafevc.com.au/toolbox/file/9495cce8-17b5-a8a5-d9b3-47c0c142d88d/1/sketches_and_drawings_lo.zip/3204a_20_reading_drawings/images/brick_perspective.jpg透视投影的例子。当立方体位于 z=0 时,这就是图像中的内容。但是当 z=-10 时,它更靠近屏幕中心 (X) 并且更小,因为它沿着蓝线延伸到地平线。
关于Android OpenGL ES 触摸添加对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7943264/