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)
Related
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.
I'm new to GL and wanted to create a tiled map as a self tuorial. I want to create a small (maybe 7 hexes wide / tall) hex map. My first thought was to just create a method to draw one hex and then just translate the appropriate offset and place the new hex. But this doesn't seem effcient. Any Idea's? Alos as a side question, how do I determine if a MotionEvent is with in the are of a given hex?
Extensive hex grid information.
To determine if a MotionEvent is within a certain hex you have to convert the coords passed in via the motion event to your OpenGL World coords. Its just like a unit conversion, you know the screen goes from 0 - WIDTH and your GL world lets say goes from -1 to 1.
(xCoord / (Width - 0)) * (1 - (-1)) = xCoordWorld
will give you the xCoord from 0 to 2, then subtract 1 to get it in -1 to 1.
As far as the hexes go I've always used 'art' hexes. Draw the hex out in paint then render a bunch of squares with that piece of art on them, fast and easy to swap a hex out for another hex.
I need to draw a gridded image using opengl. I've read that images created using grids allows to do various effects on images, like the famous wave effect, or a ripple effect from this link:
http://www.soulstorm-creations.com/index.php?option=com_content&view=article&id=111:opengl-making-a-2d-grid-image&catid=18:programming-articles&Itemid=39
I've also gone through lesson 6 android port from NEHE Tutorials:
http://insanitydesign.com/wp/projects/nehe-android-ports/
I can convert it from cube to rectangle, but I need help in understanding
1) why we are using vertex coordinates in terms of 0 and 1? Why have they not used coordinates according to image width and height?
2) How can we divide the texture region in small grids as explained in tutorial above? If some one can guide on 1), I guess I can work on point 2).
Any help would be really appreciated.
The vertex coordinates are from 0 to 1 so that you can use vertex data with many different textures without worrying about the dimensions of the image.
That said, for pixel perfect operations you often have to often the texture coordinates by a fraction the image's pixel width (say 0.5f * (float) image->width()) and height in order to make sure OpenGl (or d3D) samples from the correct place.
As for dividing the grid, straight forward simple linear interpolation. If you have a grid going from pixel coordinates 0 to 100 and you want 10 steps in your grid, you start at 0 and increment in steps of 10 pixels :
vertex_xi = (start_x + ((end_x - start_x) / 10) * i));
vertex_yi = (start_y + ((end_y - start_y) / 10) * i));
similarly,, for texture coordinates, you'd do the same thing only you usually name them like this:
vertex_ui = (start_u + ((end_u - start_u) / 10) * i));
vertex_vi = (start_v + ((end_v - start_v) / 10) * i));
where 'start_u' and 'start_v' are '1.0f +/- offset and end 'end_u' and 'end_v' are '1.0f +/- offset'. Put those in your vertex array and you should be good to go.
HTH.
I'm using Matrix to scale and rotate Bitmaps. Now I'm wondering what the difference between preconcat & postconcat is, or more precisely the difference between:
postRotate
preRotate
setRotate
From what I could figure out so far setRotate always overwrites the whole matrix, while with preRotate and postRotate I can apply multiple changes to a matrix (e.g. scaling + rotation). However, either using postRotate or preRotate didn't cause any different results for the cases I used them.
The answer to your question isn't really specific to Android; it's a graphics and math question. There's lots of theory in this answer--you've been warned! For a superficial answer to your question, skip to the bottom. Also, because this is such a long-winded tirade, I might have a typo or two making things unclear. I apologize in advance if that's the case.
In computer graphics, we can represent pixels (or in 3D, vertices) as vectors. If your screen is 640x480, here's a 2D vector for the point in the middle of your screen (forgive my shoddy markup):
[320]
[240]
[ 1]
I'll explain why the 1 is important later. Transformations are often represented using matrices because it's then very simple (and very efficient) to chain them together, like you mentioned. To scale the point above by a factor of 1.5, you can left-multiply it by the following matrix:
[1.5 0 0]
[ 0 1.5 0]
[ 0 0 1]
You'll get this new point:
[480]
[360]
[ 1]
Which represents the original point, scaled by 1.5 relative to the corner of your screen (0, 0). This is important: scaling is always done with respect to the origin. If you want to scale with some other point as your center (such as the middle of a sprite), you need to "wrap" the scale in translations to and from the origin. Here's the matrix to translate our original point to the origin:
[1 0 -320]
[0 1 -240]
[0 0 1]
Which yields:
[320*1 + 1*-320] [0]
[240*1 + 1*-240] = [0]
[ 1*1 ] [1]
You'll recognize the above as the identity matrix with the displacement coordinates slapped in the upper-right corner. That's why the 1 (the "homogenous coordinate") is necessary: to make room for these coordinates, thus making it possible to translate using multiplication. Otherwise it would have to be represented by matrix addition, which is more intuitive to humans, but would make graphics cards even more complicated than they already are.
Now, matrix multiplication generally isn't commutative, so when "adding" a transformation (by multiplying your matrix) you need to specify whether you're left-multiplying or right-multiplying. The difference it makes is what order your transformations are chained in. By right-multiplying your matrix (using preRotate()) you're indicating that the rotation step should happen before all the other transformations that you've just asked for. This might be what you want, but it usually isn't.
Often, it doesn't matter. If you only have one transformation, for example, it never matters :) Sometimes, your transformations can happen in either order with the same effect, such as scaling and rotation--my linear algebra is rusty, but I believe that in this case the matrix multiplication actually is commutative because the scale matrix is symmetric, that is, it mirrors itself across the diagonal. But really, just think about it: If I rotate some picture 10 degrees clockwise and then scale it to 200%, it looks the same as if I scaled it first, then rotated it.
If you were doing some weirder compound transformations, you'd begin to notice a discrepancy. My advice is to stick with postRotate().
I answered the question yesterday, but I feel sometiong wrong today ,So I correct the answer here:
matrix: float[] values ={1.2f,0.5f,30,0.5f,1.2f,30,0,0,1};
//as we all know, the basic value in matrix,means no transformation added
matrix2: float[] values2 ={1f,0,0,0,1f,0,0,0,1};
Let's say our matrix values are the values above.
1、 when we do the transformation like below:
matrix.preTranslate(-50, -50);
is equals to do sequence transformation to matrix2 above like below:
matrix2.postTranslate(-50, -50);
matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);// note here
matrix2.postScale(1.2f, 1.2f);
matrix2.postTranslate(30, 30);
2、 when we do the transformation like below :
matrix.preRotate(50);
is equals to do sequence transformation to matrix2 like below:
matrix2.postRotate(50);
matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);
matrix2.postScale(1.2f, 1.2f);
matrix2.postTranslate(30, 30);
3、 when we do the transformation like below :
matrix.preScale(1.3f,1.3f);
is equals to do sequence transformation to matrix2 like below:
matrix2.postScale(1.3f,1.3f);
matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);
matrix2.postScale(1.2f, 1.2f);
matrix2.postTranslate(30, 30);
4、 when we do the transformation like below :
matrix.preSkew(0.4f,0.4f);
is equals to do sequence transformation to matrix2 like below:
matrix2.postSkew(0.4f,0.4f);
matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);
matrix2.postScale(1.2f, 1.2f);
matrix2.postTranslate(30, 30);
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);