#android #opengl-es
#Android #opengl-es
Вопрос:
У меня есть простой квадрат с OpenGL es 1 и Android 1.5. Квадрат нарисован в центре экрана.
Я хочу, чтобы при нажатии пользователем на экран или перемещении пальца по экрану квадрат перемещался в это положение. Для этого я попробовал использовать gluUnProject, я попытался получить координату opengl, которая совпадает с координатой window XY, к которой прикасаются пальцем (чтобы в будущем преобразовать полигон в эту координату), и я записываю координаты в LogCat.
Координаты, которые я получаю, не являются истинными координатами, это неправильные координаты. Например, этот logcat представляет собой горизонтальное перемещение справа от экрана:
11-07 15:54:37.221: DEBUG/XXXXXXXXX(213): X: -0.003236022
11-07 15:54:37.221: DEBUG/XXXXXXXXX(213): Y: -0.047979668
11-07 15:54:37.241: DEBUG/XXXXXXXXX(213): X: -0.003236022
11-07 15:54:37.251: DEBUG/XXXXXXXXX(213): Y: -0.047807075
11-07 15:54:39.110: DEBUG/XXXXXXXXX(213): X: 0.03469036
11-07 15:54:39.110: DEBUG/XXXXXXXXX(213): Y: 0.04418271
11-07 15:54:43.021: DEBUG/XXXXXXXXX(213): X: -0.029469538
11-07 15:54:43.021: DEBUG/XXXXXXXXX(213): Y: -0.034172554
11-07 15:54:43.051: DEBUG/XXXXXXXXX(213): X: -0.026708115
11-07 15:54:43.051: DEBUG/XXXXXXXXX(213): Y: -0.034172554
11-07 15:54:43.081: DEBUG/XXXXXXXXX(213): X: -0.018596433
11-07 15:54:43.081: DEBUG/XXXXXXXXX(213): Y: -0.034172554
11-07 15:54:43.111: DEBUG/XXXXXXXXX(213): X: -0.013073588
11-07 15:54:43.111: DEBUG/XXXXXXXXX(213): Y: -0.034172554
11-07 15:54:43.141: DEBUG/XXXXXXXXX(213): X: -0.0039263717
11-07 15:54:43.141: DEBUG/XXXXXXXXX(213): Y: -0.033999965
11-07 15:54:43.162: DEBUG/XXXXXXXXX(213): X: -0.0011649576
11-07 15:54:43.162: DEBUG/XXXXXXXXX(213): Y: -0.033827372
11-07 15:54:43.191: DEBUG/XXXXXXXXX(213): X: 7.335304E-4
11-07 15:54:43.191: DEBUG/XXXXXXXXX(213): Y: -0.033654787
Это исходный код:
public class MySurfaceView extends GLSurfaceView implements Renderer {
private float INITIAL_Z = -35.0f;
private Context context;
private Square square;
private float xrot; //X Rotation
private float yrot; //Y Rotation
private float zrot; //Z Rotation
private float z = INITIAL_Z; //Profundidad en el eje Z
private float x = 0.0f; //eje X
private float y = 0.0f; //eje Y
private MatrixGrabber mg = new MatrixGrabber(); //create the matrix grabber object in your initialization code
byte horizontal=-1; //0: LEFT 1:CENTER 2:RIGHT
byte vertical=-1; //0: TOP 1:CENTER 2:BOTTOM
float startX=-1;
float startY=-1;
float xMovement=0.0f;
float yMovement=0.0f;
private boolean movement_mode=false;
public MySurfaceView(Context context, Bitmap image, int width, byte horizontal, byte vertical) {
super(context);
this.context = context;
setEGLConfigChooser(8, 8, 8, 8, 16, 0); //fondo transparente
getHolder().setFormat(PixelFormat.TRANSLUCENT); //fondo transparente
//Transformamos esta clase en renderizadora
this.setRenderer(this);
//Request focus, para que los botones reaccionen
this.requestFocus();
this.setFocusableInTouchMode(true);
square = new Square(image);
this.horizontal=horizontal;
this.vertical=vertical;
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
MyGl=gl;
gl.glDisable(GL10.GL_DITHER); //dithering OFF
gl.glEnable(GL10.GL_TEXTURE_2D); //Texture Mapping ON
gl.glShadeModel(GL10.GL_SMOOTH); //Smooth Shading
gl.glClearDepthf(1.0f); //Depth Buffer Setup
gl.glEnable(GL10.GL_DEPTH_TEST); //Depth Testing ON
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glClearColor(0,0,0,0); //fondo transparente
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
//Cargamos la textura del cubo.
square.loadGLTexture(gl, this.context);
}
public void onDrawFrame(GL10 gl) {
//Limpiamos pantalla y Depth Buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
//Dibujado
gl.glTranslatef(x, y, z); //Move z units into the screen
//gl.glScalef(0.8f, 0.8f, 0.8f); //Escalamos para que quepa en la pantalla
//Rotamos sobre los ejes.
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y
gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f); //Z
//Dibujamos el cuadrado
square.draw(gl);
mg.getCurrentProjection(gl);
mg.getCurrentModelView(gl);
}
//si el surface cambia, resetea la vista, imagino que esto pasa cuando cambias de modo portrait/landscape o sacas el teclado físico en móviles tipo Droid.
public void onSurfaceChanged(GL10 gl, int width, int height) {
if(height == 0) {
height = 1;
}
gl.glViewport(0, 0, width, height); //Reset Viewport
gl.glMatrixMode(GL10.GL_PROJECTION); //Select Projection Matrix
gl.glLoadIdentity(); //Reset Projection Matrix
//Aspect Ratio de la ventana
GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW); //Select Modelview Matrix
gl.glLoadIdentity(); //Reset Modelview Matrix
}
public boolean onTouchEvent(MotionEvent event) {
float [] outputCoords=getOpenGLCoords(event.getX(), event.getY(), 0);
x=(outputCoords[0]/outputCoords[3]);
y=(outputCoords[1]/outputCoords[3]);
//z=outputCoords[2]/outputCoords[3];
Log.d("XXXXXXXXX", "X: " x);
Log.d("XXXXXXXXX", "Y: " y);
return true; //El evento ha sido manejado
}
public float[] getOpenGLCoords(float xWin,float yWin,float zWin)
{
int screenW=SectionManager.instance.getDisplayWidth();
int screenH=SectionManager.instance.getDisplayHeight();
//CODE FOR TRANSLATING FROM SCREEN COORDINATES TO OPENGL COORDINATES
float [] modelMatrix = new float[16];
float [] projMatrix = new float[16];
modelMatrix=mg.mModelView;
projMatrix=mg.mProjection;
int [] mView = new int[4];
mView[0] = 0;
mView[1] = 0;
mView[2] = screenW; //width
mView[3] = screenH; //height
float [] outputCoords = new float[4];
GLU.gluUnProject(xWin, ((float)screenH)-yWin, zWin, modelMatrix, 0, projMatrix, 0, mView, 0, outputCoords, 0);
return outputCoords;
}
}
Комментарии:
1. Каково значение
z
(то, которое вы передаетеglTranslatef
)? И какие значенияoutputCoords[2]/outputCoords[3]
принимает (если вы раскомментируете строку вonTouchEvent
)? С начальным z и без поворота это должно быть что-то вроде -35.1.2. Значение z равно -4.800247, мне нужно использовать z в этом классе, потому что расстояние до объекта должно быть расстоянием, представленным этим значением Z. Также я должен сказать, что outputCoords [2] / outputCoords [3] = 4.7002473 alwawys. Я передаю 0 как значение winZ в gluUnProject, потому что я не знаю, какое значение имеет winZ: S
3. Есть ли у вас поворот в нем (например, ненулевое значение для
yrot
), потому что без поворота результат скорее должен быть-4.9
вместо4.7
. Ах, забудьте, что я сказал,4.7
все в порядке.4. я не применяю никакого поворота для получения этих значений
5. Я думаю, проблема в том, что я присваиваю значение 0 winZ в gluUnProject, потому что я не знаю, как получить значение winZ: S. я могу получить X и Y только при касании экрана
Ответ №1:
Ваши значения кажутся вполне разумными. Вы получаете значение x, которое становится все больше и больше (отрицательные значения с уменьшением абсолютного значения), и значение y, которое остается примерно таким же, что соответствует перемещению вправо (при условии, что у вас нет ненулевого поворота в вашем конвейере преобразования).
И результирующая координата z 4.7
также является разумной, учитывая z-перевод -4.8
и близкое значение 0.1
. И при таком z-переводе и поле зрения в 45 градусов ваши результирующие значения x и y действительно должны быть довольно маленькими (примерно около [-1,1], я думаю).
Итак, я думаю, что ваш код работает именно так, как должен. Какие координаты вы ожидали? Пожалуйста, не говорите что-то о порядке пикселей.
Комментарии:
1. тогда моя проблема заключается в значении Z как вы сказали в комментариях к вопросу, я знаю, что что-то идет не так, потому что, если я переведу полигон в заданные координаты, полигон не будет переведен правильно. У меня действительно проблема со значением winZ … мне действительно нужно знать, как его получить, вы знали, как это сделать?
2. @AndroidUser99 Это уже рассматривалось в другом вашем вопросе. Если я узнаю ответ, я опубликую его. Но в ES это кажется не таким простым, особенно в ES 1, где вы не можете использовать фрагментные шейдеры.
3. @AndroidUser99 Если вы переведете его, используя результирующее значение (x, y, z) (вместо уже существующего перевода, а не дополнительно, конечно), полигон должен находиться в заданном местоположении. Но это, конечно, будет внутри ближней плоскости и может быть просто обрезано из-за проблем с точностью. Если это не обрезано, оно должно охватывать весь экран, что также не то, что вы хотите. Как уже говорилось, определение правильной глубины — это другой вопрос, и ответ на этот вопрос здесь («почему
glUnProject
работает некорректно?») таков: «это действительно работает правильно, просто не так, как вы ожидаете».4. я думаю, что у меня с этим очень большая проблема, я не знаю, как ее решить: (