Stretch Bitmap at specific corner - android

Is it possible to stretch a Bitmap at a specific corner? The picture below shows my intention:
I shoot a picture with the camera, detect the corners in the image and want to transform the content. As far as I know this can't be achieved with the Matrix class alone. The Camera class should help, but I would need to calculate the camera's position. Is there an algorithm for this purpose? How would you do this?

You made me look into this very interesting problem and it seems easy to do it in Android. Use absolute coordinates for the four points of the Mesh:
float[] mVerts = {
topLeftX, topLeftY,
topRightX, topRightY,
bottomLeftX, bottomLeftY,
bottomRightX, bottomRightY
};
canvas.drawBitmapMesh(myImage, 1, 1, mVerts, 0, null, 0, null);
You would have to figure out how to get these points but drawBitmapMesh will stretch it for you.

I guess the easiest way of doing such transformation on Android is to use OpenGL. You can treat your bitmap as a texture. Then you can use the detected corners as texture coordinates. Assign each of them as texture coordinate to the corresponding vertex of a simple rectangular shape. Then ask OpenGL to draw it on your canvas. Pseudocode:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, pictureId);
glBegin(GL_QUAD);
glVertex(0,0); // left upper corner
glTexCoord(corners[0].x/picture.getWidth(), corners[0].y/picture.getHeight());
glVertex(1,0); // right upper corner
glTexCoord(corners[1].x/picture.getWidth(), corners[1].y/picture.getHeight());
glVertex(1,1); // right lower corner
glTexCoord(corners[2].x/picture.getWidth(), corners[2].y/picture.getHeight());
glVertex(0,1); // left lower corner
glTexCoord(corners[3].x/picture.getWidth(), corners[3].y/picture.getHeight());
glEnd();
You don't need any Camera nor complicated transforms. Of course it's not very convenient as using OpenGL for such easy task is quite an overkill. But, there's not really an easier way except writing such texturing by yourself. If you wish, you can start reading from wiki and go to external links and look for example software implementation of texturing methods:
http://en.wikipedia.org/wiki/Texture_mapping
You can also try to use any of OpenGL effect views, it will simplify setup, but also ask you for a shader or two:
http://code.google.com/p/effect-view/

Related

Android OpenGL2.0 intersection between two textures

I'm making game in OpenGL2.0 and I want to check are two sprites have intersection but i don't need to check intersection between two rectangles.I have two sprites with texture,some part of texture is transparent,some not. I need to check intersection between sprites only on not trasnparent part.
Example: http://i.stack.imgur.com/ywGN5.png
The easiest way to determine intersection between two sprites is by Bounding Box method.
Object 1 Bounding Box:
vec3 min1 = {Xmin, Ymin, Zmin}
vec3 max1 = {Xmax, Ymax, Zmax}
Object 2 Bounding Box:
vec3 min2 = {Xmin, Ymin, Zmin}
vec3 max2 = {Xmax, Ymax, Zmax}
You must precompute the bounding box by traversing through the vertex buffer array for your sprites.
http://en.wikibooks.org/wiki/OpenGL_Programming/Bounding_box
Then during each render frame check if the bounding boxes overlap (compute on CPU).
a) First convert the Mins & Maxs to world space.
min1WorldSpace = modelViewMatrix * min1
b) Then check their overlap.
I need to check intersection between sprites only on not trasnparent part.
Checking this test case maybe complicated depending on your scene. You may have to segment your transparent sprites into a separate sprite and compute their bounding box.
In your example it looks like the transparent object is encapsulate inside an opaque object so it's easy. Just compute two bounding boxes.
I don't think there's a very elegant way of doing this with ES 2.0. ES 2.0 is a very minimal version of OpenGL, and you're starting to push the boundaries of what it can do. For example in ES 3.0, you could use queries, which would be very helpful in solving this nicely and efficiently.
What can be done in ES 2.0 is draw the sprites in a way so that only pixels in the intersection of the two end up producing color. This can be achieved with either using a stencil buffer, or with blending (see details below). But then you need to find out if any pixels were rendered, and there's no good mechanism in ES 2.0 that I can think of to do this. I believe you're pretty much stuck with reading back the result, using glReadPixels(), and then checking for non-black pixels on the CPU.
One idea I had to avoid reading back the whole image was to repeatedly downsample it until it reaches a size of 1x1. It would originally render to a texture, and then in each step, sample the current texture with linear sampling, rendering to a texture of half the size. I believe this would work, but I'm not sure if it would be more efficient than just reading back the whole image.
I won't provide full code for the proposed solution, but the outline looks like this. This is using blending for drawing only the pixels in the intersection.
Set up an FBO with an RGBA texture attached as a color buffer. The size does not necessarily have to be the same as your screen resolution. It just needs to be big enough to give you enough precision for your intersection.
Clear FBO with black clear color.
Render first sprite with only alpha output, and no blending.
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glDisable(GL_BLEND);
// draw sprite 1
This leaves the alpha values of sprite 1 in the alpha of the framebuffer.
Render the second sprite with destination alpha blending. The transparent pixels will need to have black in their RGB components for this to work correctly. If that's not already the case, change the fragment shader to create pre-multiplied colors (multiply rgb of the output by a).
glColorMask(GL_TRUE GL_TRUE, GL_TRUE, GL_TRUE);
glBlendFunc(GL_DST_ALPHA, GL_ZERO);
glEnable(GL_BLEND);
// draw sprite 2
This renders sprite 2 with color output only where the alpha of sprite 1 was non-zero.
Read back the result using glReadPixels(). The region being read needs to cover at least the bounding box of the two sprites.
Add up all the RGB values of the pixels that were read.
There was overlap between the two sprites if the resulting color is not black.

Moving image on OpenGl using px?

I am using OpenGl to draw an image. Now when i try to move the image, it moves by too much. So if i say the following:
gl.glTranslatef(0, 1, -5.0f);
squirrel.draw(gl);
If i out one as a parameter, the image is now located half way of screen. How do i make it so i can say things like:
gl.glTranslatef(screen_width - image_width , 0);
Is there an alternative method for drawing images in OpenGl?
I previously used canvas to draw images, and i had no problem positioning images on the screen. However with openGl i'm experiencing issues.
All you need to remember is, the screen space in OpenGL ranges from -1,-1 (top left), and 1,1 (bottom right). So you need to provide normalized values to OpenGL. To move a point along x direction from one end of the screen (-1.0) to another (1.0), left to right, you will have to Translate by 2.0 by using glTranslatef(2.0, 0, 0). This point is on the border, so you will have to adjust depending on the actual size of your object and its location.

OpenGL coordinates to match screen coordinates?

Android opengl-es view question. So in openGL, the default position of the camera and view is at 0,0. How do you set the view and camera so that it acts basically the same as computer screen coordinates with 0,0 at the top. I've called gl.glOrthof(-screenWidth/2, ScreenWidth/2, -ScreenHeight/2, ScreenHeight/2). But I think this is wrong. I also need to set the camera to view the entire field. I'm not sure how to use gl.glFrustumf to accomplish this task.
To use your vertex coordinates as screen coordinates, just use glOrtho(0, width, height, 0, -1, 1) on the projection matrix and keep your modelview matrix identity (which is the default). Note that I flipped bottom and top, as in GL (0,0) is at the lower left and you want it at the top (but keep in mind that this also flips every object and therefore the triangle ordering). You also forgot to set the near and far planes (everything with a z out of this interval won't get displayed). But when you now draw all your objects with z=0 (which is the default, when drawing only 2d vertices), all should be fine.
glFrustum is just an alternative to glOrtho. Where glOrtho constrcuts an orthographic (parallel) view, glFrustum constructs a perspective view. So you don't need glFrustum.

Problems rotating a sprite using drawtexture (OpenGl ES Android)

I´m trying to rotate a sprite using drawtexture but nothing happens. I´m using the following code:
gl.glRotatef(90, 0, 0, 1.0f);
gl.glBindTexture(GL10.GL_TEXTURE_2D, TextureID);
(GL11Ext) gl).glDrawTexfOES(x, y, z, width, height);
The texture is drawn to the screen but it is not rotated... Anyone? :)
From the OES_draw_texture extension:
Xs and Ys are given directly in window (viewport) coordinates.
So the passed in coordinates are not transformed by the modelview and projection matrices, which is what glRotatef changes. In short, this extension does not support rotated sprites.
If you want those, the simplest is to draw standard rotated quads instead.
After testing quite a bit og different ways to do this, I found the answer was right in front of me the whole time... I was using the SpriteMethodTest example as my codebase, but I ignored the VBO extension part there, wich basically has all the needed functionality.
SpriteMethodTest: http://code.google.com/p/apps-for-android/source/browse/trunk/#trunk/SpriteMethodTest

How to move a particular texture around screen in android using opengl es?

I am very new to OpenGL ES. I am implementing some demo app to load multiple textures on the screen. For demo purpose I have loaded 2 textures in 2 different locations on the screen using glTranslatef() and glBindTextures() twice.
Now I am able to see 2 different images on the screen. Now I want to move one particular texture across the screen using mouse.
I know it may be silly topic, but please help me in this..
Thanks in advance..
As mentioned above you will need to translate the coordinates of the surface.
If you are using orthagonal (2D) projection, the pixel/coord ratio can be set to 1:1 easily by defining the projection to be the same size as the screen. For example:
glOrthof(0.0f, screenWidth, -screenHeight, 0.0f, -1.0f, 1.0f);
should define a projection with (0,0) in the top left and the same size as your screen.
If you are using 3D projection, you may find this link helpful:
http://www.mvps.org/directx/articles/rayproj.htm
You don't actually want to move the texture, but either you move your Scene point of view ( gluortho2d / glulookat / gltranslatef - or anything else ), or you move the vertices of the shape you're applying your texture to.
this is how im doing it in my 2D game :
gl.glTranslatef(-cameraPosX % 32, -cameraPosY % 32, 0);

Categories

Resources