Android OpenGL ES - Very Weird Pixel Color from glReadPixels - Switched Image? - android

I am trying to return the pixel color by TouchEvents in OpenGL ES on Android. I created 2 Triangles as a rectangle. So I put the shown Image on it. The black area is not a part of the Triangles.
If I click on the black area, it always gives me the correct number 0 0 0 -1 (black). If i click on the white area it also gives me always the correct number -1 -1 -1 -1 (white). But when I click on the green rectangle, it gives me 0 0 0 -1 (black). After that I am clicking on the black rectangle next to him and it gives me the color of the neighbor(green).
The image switched in the "background", but I don't know how this is possible
Used this Tut: http://androidblog.reindustries.com/a-real-open-gl-es-2-0-2d-tutorial-part-1/
My Code for Color Picking:
public void onDrawFrame(GL10 gl) {
if (clicked) {
gl.glDisable(GL10.GL_TEXTURE_2D);
gl.glDisable(GL10.GL_FOG);
gl.glDisable(GL10.GL_BLEND);
ByteBuffer ss = ByteBuffer.allocate(4);
ss.order(ByteOrder.nativeOrder());
gl.glFlush();
gl.glReadPixels(touchXint, touchYint, 1, 1, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, ss);
byte b[] = new byte[4];
ss.get(b);
String key = "" + b[0] + " " + b[1] + " " + b[2] + " " + b[3];
Log.d("Color: ", key);
clicked = false;
ss.rewind();
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnable(GL10.GL_FOG);
gl.glEnable(GL10.GL_BLEND);
}
}

You appear to have a problem with coordinate systems. In many window/UI systems, including Android, the coordinates you receive as part of events are relative to the top/left corner of the window.
On the other hand, the window coordinate system used by OpenGL for specifying the pixel rectangle for glReadPixels() has its origin in the bottom/left corner. You can see that in the documentation, where x and y are described by:
Specify the window coordinates of the first pixel that is read from the frame buffer. This location is the lower left corner of a rectangular block of pixels.
To accommodate for these different coordinate systems, you have to invert the y-coordinate of your touch input before passing it to glReadPixels(). Instead of touchYint, use windowHeight - 1 - touchYint.

It's not the real answer, why your problem is occuring, but it seems like your X coordinate is inverted. I mean, the horizontal 0 is swapped with screenWidth. Just to confirm it you can try something like
gl.glReadPixels(screenWidth - touchXint, touchYint, 1, 1, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, ss);
If it works, then you should search the problem in obtaining you touchXint coordinate.
Edit:
In this case the screen is oriented horizontally, so the horizontal axis is Y. The direction of Y axis in OpenGL coordinate system and Android coordinate system is inverted. Therefore, to get the right Y coordinate for the glReadPixels call, the following transform needs to be applied: y = (screenHeight-touchYint).

Related

Warp texture with opengles

I'm making an Android app using opengles 2.0 and I have camera preview like this :
and using this as a texture.
But I want simply warp in side of the red donut shape. So I'm trying to crop that part from the texture and mapping to a shape like a rectangular. But I don't know how exactly crop that part is there any ways to do that efficiently?
Lets assume we have a rectangle R with uv coordinages (s, t) where s,t element [0,1]. And we have the ring given by a center C, a inner radius ri and an outer radius ro.
If we want to map the uv coordinates (s,t) to coordinates in the ring texture (s_tex, t_tex), then this can be done by using the following formulas:
//alpha: angle
alpha = t * 2 * PI //maps the [0,1] range of t to [0, 2*PI] (circle)
//r: distance from the center
r = ir + s * (or - ir) //maps s=[0,1] to [ir, or]
//d: direction from the center c
d = [sin(alpha), cos(alpha)]
//final coordinates
[s_tex, t_tex] = C + d * r
Note, that C, ri, ro have to be given in texture coordinates of the ring texture.
Depending on where you want to have the cut in the ring (location where start/end of the rectangle are mapped to), it can be necessary to add a constant factor to alpha. At the moment this factor is 0, which means that the cut goes from C horizontally to the right.

Movement along circle around a given point 2D

I want to move an object on a circle around a given point. I am using OpenGL on Android and my viewport is the screen resolution in landscape mode (1280 * 800). The point I want to rotate an object around is e.g (500, 300) and this is where the user pressed. I also have the radius of the desired circle r.
To sum it up, I've the center of the circle, the radius, and the angle (amount I want to move the object with each iteration of the game loop)
So far I tried this:
this.setPosX(((float)Math.cos(angle)*radius + center.x) * width);
this.setPosY(((float)Math.sin(angle)*radius + center.y) * height);
This will create a movement along an ellipsis, not a circle...
Can anyone please help me?
It produces an ellipse cause circles DON'T have heights. Try this instead
this.setPosX(((float)Math.cos(angle)*radius ) + center.x);
this.setPosY(((float)Math.sin(angle)*radius ) +center.y);
Just remove the width and height factors at the end. If you want a circle you cannot multiply the coordinates with different factors.
The formula is not correct because you are multiplying the correct value for a point around a circle by other different values which are not meaningful.
Think about the fact that you have c(x,y) which is the center and you need to move around by a value which is given by r(cos(angle)*radius, sin(angle)*radius).
What you obtain is p(x + cos(angle)*radius, y + sin(angle)*radius).
If you multiply these two coordinates by two other values (width and height in your formula) you are changing the factor either for the circle either for the center so you end up with not only an ellipse but an ellipse which changes its center.
So:
circle: p(c.x + cos(angle)*r, y + sin(angle)*r)
ellipse: p(c.x + cos(angle)*w, y + sin(angle)*h)
your formula: p((c.x + cos(angle)*r)*w, (c.y + sin(angle)*r)*h) (which makes no sense)

OpenGL ES texture mapping

I need to draw circles in my Android application. Actually it is a Pacman game and I need to draw tablets. Since there are many tablets on field I decided to draw each tablet with a single polygon.
Here is the illustration of my idea:
http://www.advancedigital.ru/ideal_circle_with_only_one_polygon.jpg
Vertex coordrs:
// (x, y)
0 : -R, R * (Math.sqrt(2) + 1)
1 : -R, -R
2 : R * (Math.sqrt(2) + 1), -R
Vertex coords are calculated relative to circle center to place circles with ease later.
The problem is in texture mapping, according to my calculations UVs should be like this
0 : 0, -(Math.sqrt(2) + 0.5)
1 : 0, 1
2 : 1, (Math.sqrt(2) + 0.5)
But negative V value causes application to show only black screen. That is why I think that I'm missing something or I'm going the wrong way…
My question is: Is it possible to render the texture in that way or not? If it isn't possible, what is the best way to draw small dots?
P.S: I'm working with OpenGL ES 2.0 on Android.
Seems to me, that this guy is trying to do the same.
The GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T texture parameters are set to GL_REPEAT by default. Set them to GL_CLAMP_TO_EDGE instead to get the effect you're looking for (see the glTexParameter documentation)

Reverse projecting screenspace coordinate to modelspace coordinates

I am working on an Android Application in which a 3d scene is displayed and the user should be able to select an area by clicking/tapping the screen. The scene is pretty much a planar (game) board on which different objects are placed.
Now, the problem is how do I get the clicked area on the board from the actual screen-space coordinates?
I was planning on using gluUnProject(), as I have access to (almost) all the necessary parameters. Unfortunately I am missing the winZ param, and cannot get the current depth as the touch event is occurring in a different thread than the GL-thread.
My new plan is to still use gluUnProject, but with a winZ of 0, and then project the resulting point onto the board (the board stretches from 0,0,0 to 10,0,10 in model space), However, I can't seem to figure out how to do this?
I would be very happy if anyone could help me out with the maths needed to do this (matrices were never my strongest side), or perhaps find a better solution.
To clarify; here is an image of what I want to do:
The red rectangle represent the device screen, the green x is the touch event and the black square is the board (grey subdivisions represent a square of one unit). I need to figure out where on the board the touch has happened (in this case it is in square 1,1).
As you are working in 2D basically already, (I presume you mean your 3D board stretches from 0,0,0 to 10,10,0 (x,y,z).) you could translate and interpolate/extrapolate the 2D/3D space coordinates from your screen space coordinates without the gluUnProject(). You will need your screen resolution, and to pick the resolution of the 3D space grid you wish to convert to. If both the screen and 3D space origins are aligned (0,0 screen space is at 0,0,0 3D space), and your screen dimensions are 320x240, using your existing 10x10 3D grid, then 320/10 = 32, and 240/10 = 24, thus the screen space size of a single 1x1 area is 32x24. So if the user presses on 162, 40, then the user is pressing within ( 5, 1, 0) (162/32 >= 5 but < 6, 40/24 >= 1 but < 2 ) in the 3D space. If you need greater resolution than this you can select a higher 3D space grid resolution (i.e. using 20 instead of 10). You don't need to update the GL matrix to use this factor. Though it may make it simpler in some ways, I'm sure from a modeling perspective you would have additional work to do. Just be aware for a factor like 20, 1,3 would be at (.5, 1.5, 0). If your screen and 3D space origins are not already aligned will need to translate the screen space coord prior to this. If 0,0 screen space is 10,10,0, you will need to take your screen resolution and subtract the current point from it, making 0,0 into 320, 240 in this example, our example point of 162, 40, would be 158 (320-158 == 162), 200 (240-200 == 40).
If you'd like an overview of the projection matrix and how that all works, which could help you understand where to put the screen space dimensions in the unproject matrix, read this chapter of the OpenGL red book. http://www.glprogramming.com/red/chapter03.html
Hope this helps, and good luck!
So, I managed to solve this by doing the following:
float[] clipPoint = new float[4];
int[] viewport = new int[]{0, 0, width, height};
//screenY/screenX are the screen-coordinates, y should be flipped:
screenY = viewport[3] - screenY;
//Calculate a z-value appropriate for the far clip:
float dist = 1.0f;
float z = (1.0f/clip[0] - 1.0f/dist)/(1.0f/clip[0]-1.0f/clip[1]);
//Use gluUnProject to create a 3d point in the far clip plane:
GLU.gluUnProject(screenX, screenY, z, vMatrix, 0, pMatrix, 0, viewport, 0, clipPoint, 0);
//Get a point representing the 'camera':
float eyeX = lookat[0] + eyeOffset[0];
float eyeY = lookat[1] + eyeOffset[1];
float eyeZ = lookat[2] + eyeOffset[2];
//Do some magic to calculate where the line between clipPoint and eye/camera would intersect the y-plane:
float dX = eyeX - clipPoint[0];
float dY = eyeY - clipPoint[1];
float dZ = eyeZ - clipPoint[2];
float resX = glu[0] - (dX/dY)*glu[1];
float resZ = glu[2] - (dZ/dY)*glu[1];
//resX and resZ is the wanted result.

Camera movement. How do I move camera?

I currently have an open gl renderer set up which displays a 2d square and another 2d shape. By using the keys the user is able to move the square up down left and right. This is done through translating the square based on values altered by whether the user presses up down left right eg if the user presses right it would mean a translation of gl.glTranslatef(rightdisplacement, 0, 0); etc. The movement works fine but I cant figure out how to get the camera to follow the square as it continues moving. I would like to move the square and have the camera move in the same direction.
If you're doing 2D rendering you are probably making a call to glOrtho somewhere to define your coordinate system. Total speculation, but your code might look something like:
glOrtho( 0, screenWidth, 0, screenHeight, -1, 1 );
This is where you define your camera position. Create camera position x and y position variables and instead call
glOrtho( camX - screenWidth/2, camX + screenWidth/2, camY - screenHeight/2, camY + screenHeight/2, -1, 1 );
Make sure that this is called every frame as the camera position will obviously change. Your render code might look something like
// clear framebuffer
glMatrixMode( GLES10.GL_PROJECTION );
glLoadIdentity();
glOrtho( camX - screenWidth/2, camX + screenWidth/2, camY - screenHeight/2, camY + screenHeight/2, -1, 1 );
glMatrixMode( GLES10.GL_MODELVIEW );
glLoadIdentity();
// draw your stuff

Categories

Resources