Two questions about SOIL, OpenGL and GLUT - c

Two questions about these three:
How can you load only a PART of an image in a texture (GLuint) using SOIL. I can load a full PNG picture but I can't figure out how to load only a PART of it. As in animations. for example HERE which is an animation of a shooting catapult. How do I load only a part of it ? (With known location of pixels needed for that part).
How to do Pixel-per-pixel collision detection using glReadPixels();? I succeeded using the function to read pixels off the screen but I'm not sure when to use it. First I thought about when loading a texture, analyze its limits (the pixels that might collide and not all the pixels) into a certain pattern and then when a grid of a certain PNG crosses another - analyze if the pixels of both textures in the certain X and Y are meant to be touching each other and colliding. I'm not sure how to do that (using glReadPixels or any other function to read pixels off of the PNG texture which ISN'T on screen yet). Any idea to make Pixel-per-pixel 2D collision ? OR a better 2D collision detection algorithm ?

1) To read only part of an image as a texture, one method is to read the entire image and load it into a texture. You can then create a new texture using the glTexSubImage2D() call. This is particularly convenient for sprites because you can call it repeatedly, changing the x and y offset to pull out the different frames of your animation.
2) Collision detection is a big topic and too broad to answer in a single question like this. You should look up QuadTrees (or if you're working in 3D, KdTrees). They partition the space so you can compare the bounding boxes of your various sprites efficiently. Once you find 2 sprites whose bounding boxes overlap, you can test them more closely to see if they overlap. Usually you can use some trick such as blitting their 1-bit masks to the same small texture (with the proper relative offsets) using an AND-like blend mode (where the output is 1 only when both inputs are 1) and seeing if any pixels in the resulting texture are turned on. That way you're only scanning an area that is at most the size of the 2 textures, and not the entire window.
To expand on what I'm trying to describe above with the AND-like blend mode, you have the following scenario:
2 1-bit sprite masks where each pixel is 0 if the sprite does not cover that pixel and 1 if it does. These are the input textures.
1 1-bit output texture where the 2 sprites will be drawn
For each pixel of the output, you have 4 possibilities for the inputs:
0-0 : both sprites are transparent at this output pixel, so they
don't touch here
1-0, 0-1: One sprite is transparent at this pixel,
the other is not. Hence, they don't overlap
1-1 : Both sprites are solid at this output pixel, so there's a
collision
If you write it as a truth table, it's the same as ANDing the 2 masks:
| 0 | 1 |
--+---+---+-
0 | 0 | 0 |
--+---+---+-
1 | 0 | 1 |
--+---+---+-

Related

Finding max-min pixel luminance on screen/in texture without GLSL support

In my 2D map application, I have 16-bit heightmap textures containing altitudes in meters associated to a point on the map.
When I draw these textures on the screen, I would like to display an analysis such that the pixel referring to the highest altitude on the screen is white, the pixel referring to the lowest altitude in the screen is black and the values in-between are interpolated between those two.
I'm using an older OpenGL version and thus do not have access to modern pipeline functionality like GLSL or PBO (Which somehow can make getting color buffer contents to CPU side much more efficient than glReadPixels, as I've heard).
I have access to ATI_fragment_shader extension which makes possible to use a basic fragment shader to merge R and G channels in these textures and get a single float grayscale luminance value.
Then I would've been able to re-color these pixels again inside shader (Map them to 0-1 range) based on maximum and minimum pixel luminance values but I don't know what they are.
My question is, between the pixels currently on the screen, how do I find the pixels with maximum and minimum luminance values? Or as an alternative, how do I find these values inside a texture? (Because I could make a glCopyTexImage2D call after drawing the texture with grayscale luminance values on the screen and retrieve the data as a texture).
Stuff I've tried or read about so far:
-If I could somehow get current pixel RGB values in the color buffer to CPU side, I could find what I need manually and then use them. However, reading color buffer contents with glReadPixels is unacceptably slow. It's no use even if I set it up so that it completes one read operation over multiple frames.
-Downsampling the texture to 1x1 size until the last standing pixel is either minimum or maximum value and then using this 1x1 texture inside shader. I have no idea how to achieve this without GLSL and texel fetching support since I would have to look up the pixel which is to the right, up and up-right of the current one and find a min/max value between them.

How to superimpose a small bitmap onto a larger bitmap in C at a certain x, y position?

I am trying to write a program that detects pixel collision (overlapping of bits that have a value of 1) between two bitmap images. I know the position of the left side, right side, top and bottom of each bitmap in x and y coordinates relative to the LCD screen. My thinking is that I could superimpose the first bitmap onto a large, blank (0's everywhere) bitmap that is the size of the screen, at its x and y position. Then do the same for the second on it's own canvas. After that I could do a binary & operation of the two bitmaps that are of the same size. If the result is greater than 1, I know some of the pixels have overlapped.
The problem with this is I don't know how to superimpose two bitmaps. Does anyone have experience with this who could offer some advice?
EDIT: We are expected to use bitwise and bit-shifting operations to detect pixel level collision, with a maximum of 1 for loop.

How to display the tiny triangles or recognize them quickly?

What I am doing is a pick program. There are many triangles and I want select the front and visible ones by a rectangular region. The main method is described below.
there are a lot of triangles and each triangle has its own color.
draw all the triangles to a frame buffer.
read the color of pixel in frame buffer and based on the color, we know which triangles are selected.
The problem is that there are some tiny triangles can not be displayed in the final frame buffer. Just like the green triangle in the picture. I think the triangle is too tiny and ignored by the graphic card.
My question is how to display the tiny triangles in the final frame buffer? or how to know which triangles are ignored by the graphic card?
Triangles are not skipped based on their size, but if a pixel center does not fall inside or lie on the top or left edge (this is referred to as coverage testing) they do not generate any fragments during rasterization.
That does mean that certain really small triangles are never rasterized, but it is not entirely because of their size, just that their position is such that they do not satisfy pixel coverage.
Take a moment to examine the following diagram from the DirectX API documentation. Because of the size and position of the the triangle I have circled in red, this triangle does not satisfy coverage for any pixels (I have illustrated the left edge of the triangle in green) and thus never shows up on screen despite having a tangible surface area.
If the triangle highlighted were moved about a half-pixel in any direction it would cover at least one pixel. You still would not know it was a triangle, because it would show up as a single pixel, but it would at least be pickable.
Solving this problem will require you to ditch color picking altogether. Multisample rasterization can fix the coverage issue for small triangles, but it will compute pixel colors as the average of all samples and that will break color picking.
Your only viable solution is to do point inside triangle testing instead of relying on rasterization. In fact, the typical alternative to color picking is to cast a ray from your eye position through the far clipping plane and test for intersection against all objects in the scene.
The usability aspect of what you seem to be doing seems somewhat questionable to me. I doubt that most users would expect a triangle to be pickable if it's so small that they can't even see it. The most obvious solution is that you let the user zoom in if they really need to selectively pick such small details.
On the part that can actually be answered on a technical level: To find out if triangles produced any visible pixels/fragments/samples, you can use queries. If you want to count the pixels for n "objects" (which can be triangles), you would first generate the necessary query object names:
GLuint queryIds[n]; // probably dynamically allocated in real code
glGenQueries(n, queryIds);
Then bracket the rendering of each object with glBeginQuery()/glEndQuery():
loop over objects
glBeginQuery(GL_SAMPLES_PASSED, queryIds[i]);
// draw object
glEndQuery(GL_SAMPLES_PASSED);
Then at the end, you can get all the results:
loop over objects
GLint pixelCount = 0;
glGetQueryObjectiv(queryIds[i], GL_QUERY_RESULT, &pixelCount);
if (pixelCount > 0) {
// object produced visible pixels
}
A couple more points to be aware of:
If you only want to know if any pixels were rendered, but don't care how many, you can use GL_ANY_SAMPLES_PASSED instead of GL_SAMPLES_PASSED.
The query counts samples that pass the depth test, as the rendering happens. So there is an order dependency. A triangle could have visible samples when it is rendered, but they could later be hidden by another triangle that is drawn in front of it. If you only want to count the pixels that are actually visible at the end of the rendering, you'll need a two-pass approach.

Determine chessboard dimensions in pixels

Similar to calibrating a single camera 2D image with a chessboard, I wish to determine the width/height of the chessboard (or of a single square) in pixels.
I have a camera aimed vertically at the ground, ensured to be perfectly level with the surface below. I am using the camera to determine the translation between consequtive frames (successfully achieved using fourier phase correlation), at the moment my result returns the translation in pixels, however I would like to use techniques similar to calibration, where I move the camera over the chessboard which is flat on the ground, to automatically determine the size of the chessboard in pixels, relative to my image height and width.
Knowing the size of the chessboard in millimetres, I can then convert a pixel unit to a real-world-unit in millimetres, ie, 1 pixel will represent a distance proportional to the height of the camera above the ground. This will allow me to convert a translation in pixels to a translation in millimetres, recalibrating every time I change the height of the camera.
What would be the recommended way of achieving this? Surely it must be simpler than single camera 2D calibration.
OpenCV can give you the position of the chessboard's corners with cv::findChessboardCorners().
I'm not sure if the perspective distortion will affect your calculations, but if the chessboard is perfectly aligned beneath the camera, it should work.
This is just an idea so don't hit me.. but maybe using the natural contrast of the chessboard?
"At some point it will switch from bright to dark pixels and that should happen (can't remember number of columns on chessboard) times." should be a doable algorithm.

transparency implementation in YUV422 using only Y

Lets say we have 2 images in YUV422 format and assume that the second image Y field of value 0x10 is being transparent and merged on to the first one with Cb and Cr overwritten.
The product of such merge results in ugly borders (divided pixel line efect) of solid shapes. Is there a way to produce a combination of values on borders, so the transition is smooth?
This problem is not specific to YUV4:2:2:, but occurs whenever binary transparency is used. The best solution is to use a four-channel image and include an alpha channel. Essentially, an alpha channel represents the "degree of opaque-ness" of each pixel. When two images with alpha-channels overlap, alpha blending produces a result that looks much better.
If you're stuck with YUV4:2:2 or can't add alpha channel, you could try smooth the transition the two images with a low-pass filter. This will hurt the definition of your edges, but might look better than doing nothing.

Resources