Take screenshot with openGL and save it as png - c

I'm trying to take a screenshot of full screen and save it as a png. I found a code here and modified it a bit. For the screenshot I use openGL and Glut and for the saving in png the gd library for c. All I'm getting is a black png and I can't figure out why. I searched in stackoverflow and found some posts, but unfortunately they didn't help. One of them was to use glReadBuffer( GL_FRONT); instead of glReadBuffer(GL_BACK); I tryed with both of them with no success. Here is my code:
int SVimage2file(char *filename){
int width = glutGet(GLUT_SCREEN_WIDTH);
int height = glutGet( GLUT_SCREEN_HEIGHT);
FILE *png;
GLubyte *OpenGLimage, *p;
gdImagePtr image;
unsigned int r, g, b;
int i,j,rgb;
png = fopen(filename, "wb");
if (png == NULL) {
printf("*** warning: unable to write to %s\n",filename);
return 1;
}
OpenGLimage = (GLubyte *) malloc(width * height * sizeof(GLubyte) * 3);
if(OpenGLimage == NULL){
printf("error allocating image:%s\n",filename);
exit(1);
}
printf("Saving to: %s .\n",filename);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadBuffer( GL_FRONT);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, OpenGLimage);
p = OpenGLimage;
image = gdImageCreateTrueColor(width,height);
for (i = height-1 ; i>=0; i--) {
for(j=0;j<width;j++){
r=*p++; g=*p++; b=*p++;
rgb = (r<<16)|(g<<8)|b;
//printf("the rgb color %d\n", rgb );
gdImageSetPixel(image,j,i,rgb);
}
}
gdImagePng(image,png);
fclose(png);
gdImageDestroy(image);
}
What is it that I'm missing?

You could use the devil image library and take a screeshot with:
void takeScreenshot(const char* screenshotFile)
{
ILuint imageID = ilGenImage();
ilBindImage(imageID);
ilutGLScreen();
ilEnable(IL_FILE_OVERWRITE);
ilSaveImage(screenshotFile);
ilDeleteImage(imageID);
printf("Screenshot saved to: %s\n", screenshotFile);
}
takeScreenshot("screenshot.png");

If you don't reject to use C++ library, you should try PNGwriter! It write the picture pixel by pixel and their RGB values. Since the PNGwriter start form left-up corner while the glReadPixels() start from left-bottom, your code while like:
GLfloat* OpenGLimage = new GLfloat[nPixels];
glReadPixels(0.0, 0.0, width, height,GL_RGB, GL_FLOAT, OpenGLimage);
pngwriter PNG(width, height, 1.0, fileName);
size_t x = 1; // start the top and leftmost point of the window
size_t y = 1;
double R, G, B;
for(size_t i=0; i<npixels; i++)
{
switch(i%3) //the OpenGLimage array look like [R1, G1, B1, R2, G2, B2,...]
{
case 2:
B = (double) pixels[i]; break;
case 1:
G = (double) pixels[i]; break;
case 0:
R = (double) pixels[i];
PNG.plot(x, y, R, G, B);
if( x == width )
{
x=1;
y++;
}
else
{ x++; }
break;
}
}
PNG.close();
PS. I had also try libgd, but it seems only convert one image file (in the hard disk or in memory) to another format of image. But I think it still useful while you want to convert many PNG file to GIF format to create a GIF animate.

Related

Swscale - image patch (NV12) color conversion - invalid border

The goal is to convert NV12 to BGR24 image, more exactly an image patch (x:0, y:0, w:220, h:220).
The issue is the undefined pixel column on the right of the converted patch as shown:
The question is why is this happening (even though the coordinates and the dimensions of the patch have even values) ?
(Interestingly enough for an odd width value, that issue is not present)
The patch has the following bounding box: (x:0, y:0, w:220, h:220).
The behavior should be reproducible with any image. Conversion can be done using the ppm conversion page.
The following code creates a nv12 image from a bgr24 image and then converts a nv12 patch back to bgr24 patch. If everything worked properly the output should have been identical to a source image.
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
void readPPM(const char* filename, uint8_t** bgrData, int* stride, int* w, int* h)
{
FILE* fp = fopen(filename, "rb");
fscanf(fp, "%*s\n"); //skip format check
fscanf(fp, "%d %d\n", w, h);
fscanf(fp, "%*d\n"); //skip max value check
*stride = *w * 3;
*bgrData = av_malloc(*h * *stride);
for (int r = 0; r < *h; r++)
{
uint8_t* rowData = *bgrData + r * *stride;
for (int c = 0; c < *w; c++)
{
//rgb -> bgr
fread(&rowData[2], 1, 1, fp);
fread(&rowData[1], 1, 1, fp);
fread(&rowData[0], 1, 1, fp);
rowData += 3;
}
}
fclose(fp);
}
void writePPM(const char* filename, uint8_t* bgrData, int stride, int w, int h)
{
FILE* fp = fopen(filename, "wb");
fprintf(fp, "P6\n");
fprintf(fp, "%d %d\n", w, h);
fprintf(fp, "%d\n", 255);
for (int r = 0; r < h; r++)
{
uint8_t* rowData = bgrData + r * stride;
for (int c = 0; c < w; c++)
{
//bgr -> rgb
fwrite(&rowData[2], 1, 1, fp);
fwrite(&rowData[1], 1, 1, fp);
fwrite(&rowData[0], 1, 1, fp);
rowData += 3;
}
}
fclose(fp);
}
void bgrToNV12(uint8_t* srcData[4], int srcStride[4],
uint8_t* tgtData[4], int tgtStride[4],
int w, int h)
{
struct SwsContext* context = sws_getContext(w, h, AV_PIX_FMT_BGR24,
w, h, AV_PIX_FMT_NV12, SWS_POINT, NULL, NULL, NULL);
{
sws_scale(context,
srcData, srcStride, 0, h,
tgtData, tgtStride);
}
sws_freeContext(context);
}
void nv12ToBgr(uint8_t* srcData[4], int srcStride[4],
uint8_t* tgtData[4], int tgtStride[4],
int w, int h)
{
struct SwsContext* context = sws_getContext(w, h, AV_PIX_FMT_NV12,
w, h, AV_PIX_FMT_BGR24, SWS_POINT, NULL, NULL, NULL);
{
sws_scale(context,
srcData, srcStride, 0, h,
tgtData, tgtStride);
}
sws_freeContext(context);
}
int main()
{
//load BGR image
uint8_t* bgrData[4]; int bgrStride[4]; int bgrW, bgrH;
readPPM("sample.ppm", &bgrData[0], &bgrStride[0], &bgrW, &bgrH);
//create NV12 image from the BGR image
uint8_t* nv12Data[4]; int nv12Stride[4];
av_image_alloc(nv12Data, nv12Stride, bgrW, bgrH, AV_PIX_FMT_NV12, 16);
bgrToNV12(bgrData, bgrStride, nv12Data, nv12Stride, bgrW, bgrH);
//convert nv12 patch to bgr patch
nv12ToBgr(nv12Data, nv12Stride, bgrData, bgrStride, 220, 220); //invalid result (random column stripe)
//nv12ToBgr(nv12Data, nv12Stride, bgrData, bgrStride, 221, 220); //valid result
//save bgr image (should be exactly as original BGR image)
writePPM("sample-out.ppm", bgrData[0], bgrStride[0], bgrW, bgrH);
//cleanup
av_freep(bgrData);
av_freep(nv12Data);
return 0;
}
sws_scale makes a color conversion and scaling at the same time.
Most of the used algorithms need to include neighboring pixels in the calculation of a target pixel. Of course, this could lead to problems at the edges if the image dimensions are not a multiple of x. Where x depends on the used algorithms.
If you set the image dimensions here to a multiple of 8 (next multiple of 8 = 224), then it works without artifacts.
nv12ToBgr(nv12Data, nv12Stride, bgrData, bgrStride, 224, 224);
Demo
Using image dimensions 220 x 220 on the left, gives an artifact on the right edge of the converted patch.
If one chooses 224 x 224 it does not give an artifact, see the right image in the screenshot comparing both procedures.
Theoretically Required Minimum Alignment
Let's take a look at the YVU420 format:
The luma values are determined for each pixel. The color information, which is divided into Cb and Cr, is calculated from a 2x2 pixel block. The minimum image size would therefore be a 2 x 2 image block resulting in 6 bytes (i.e. 12 pixels per byte = 12 * 4 = 48bit = 6 bytes), see graphic here:
The minimum technical requirement is therefore an even width and height of the image.
You have defined the SWS_POINT flag for scaling, i.e. the nearest neighbor method is used. So theoretically for each output pixel the nearest input pixel is determined and used, which does not cause any alignment restrictions.
Performance
But an important aspect of the actual implementations of algorithms, however, is often performance. In this case, e.g. several adjacent pixels could be processed at once. Also do not forget the possibility of hardware-accelerated operations.
Alternative solution
If for some reason you need to stick to a 220x220 format, you can alternatively use the SWS_BITEXACT flag.
It does:
Enable bitexact output.
see https://ffmpeg.org/ffmpeg-scaler.html#scaler_005foptions
So in nv12ToBgr you would use something like:
struct SwsContext* context = sws_getContext(w, h, AV_PIX_FMT_NV12,
w, h, AV_PIX_FMT_BGR24, SWS_POINT | SWS_BITEXACT, NULL, NULL, NULL);
This doesn't give any artifacts either. If you have to convert a lot of frames, I would take a look at the performance.

C: Best way to make a buffer copy of an Image Map

I have a struct that basically has these contents:
typedef struct {
unsigned int width, height;
float *r, *g, *b;
} image;
Using the FreeImage.h library I am able to open a certain image and associate the pixels with its RGB colours. So the code is as follows:
imagem open_image(char *name_of_file) {
FIBITMAP *bitmapIn;
int x, y;
RGBQUAD color;
image I;
bitmapIn = FreeImage_Load(FIF_JPEG, name_of_file, 0);
if (bitmapIn == 0) {
printf("Error! File not found - %s\n", name_of_file);
} else {
printf("File found!\n");
}
x = FreeImage_GetWidth(bitmapIn);
y = FreeImage_GetHeight(bitmapIn);
I.width = x;
I.height = y;
I.r = malloc(sizeof(float) * x * y);
I.g = malloc(sizeof(float) * x * y);
I.b = malloc(sizeof(float) * x * y);
for (int i=0; i<x; i++) {
for (int j=0; j <y; j++) {
int idx;
FreeImage_GetPixelColor(bitmapIn, i, j, &color);
idx = i + (j*x);
I.r[idx] = color.rgbRed;
I.g[idx] = color.rgbGreen;
I.b[idx] = color.rgbBlue;
}
}
return I;
}
So now when I call the function in my main file like:
image img = open_image("file_name");
I have my image "map" in my reference named img.
Basically what I want to know is what is the best way to make a copy of this img so that I can apply a filter in this buffer img, for exemple a blur filter. That way when I get the surrounding pixels values to write to the central one, it is always the original pixels so get the pixels from "img" and write them with the filter to the "img_buffer".
I guess I could just make another reference named img_buff and call the open_image function again but that takes to much real and user time.
So how would you suggest I made the copy? From my research I found that memcpy() maybe won't do the trick since it gives me a shallow copy but not to sure about it.
Any suggestion that won't take to much more real/user time is welcome!
If you want to improve performances,you should try to avoid copies which are time-consuming specially for large arrays.
But I assume you can't, so there is a solution :
Image imgCopy;
imgCopy.width = img.width
imgCopy.height = img.height
In a first time you allocate memory :
imgCopy.r = (float*)malloc(sizeof(float) * imgCopy.width * imgCopy.height );
imgCopy.g = (float*)malloc(sizeof(float) * imgCopy.width * imgCopy.height );
imgCopy.b = (float*)malloc(sizeof(float) * imgCopy.width * imgCopy.height );
Then you can copy the pointer's content :
*(imgCopy.r) = *(img.r);
*(imgCopy.g) = *(img.r);
*(imgCopy.b) = *(img.r);

Enlarging bitmap in c

The following code takes in a bmp and enlarges it, rotates it or flips it. Everything is working properly except when i call the enlarge command line. the pictures comes up but it does not look any bigger.
This is the enlarge funtions:
int enlarge(PIXEL* original, int rows, int cols, int scale,
PIXEL** new, int* newrows, int* newcols)
{
int row, col, i, j;
if((rows<=0)|| (cols<=0))
{
return -1;
}
*newrows=rows * scale;
*newcols=cols * scale;
*new=(PIXEL*)malloc((scale*rows)*(scale*cols)*sizeof(PIXEL));
for(row=0;row<rows;row++)
{
for(col=0;col<cols;col++)
{
PIXEL *o=original + row*cols +col;
for(j=0; j<scale;j++)
{
for(i=0; i<scale;i++)
{
PIXEL *n=(*new)+(row*scale+i)*(*newcols)+(col*scale+j);
*n=*o;
}
}
}
}
/* THIS IS THE METHOD THAT YOU SHOULD WRITE */
return 0;
}
and this is the main function:
int degree, scale;
int is_rotate=0, is_scale=0, is_flip=0;
char *inputFile=NULL, *outputFile=NULL;
int r, c, check;
PIXEL *b, *nb;
int nr,nc;
int error;
//readFile("example.bmp",&r,&c,&b);
while((check=getopt(argc,argv,"s:r:o:f")) != -1)
{
switch (check)
{
case 's':
is_scale=is_scale+1;
//enlarge(nb,nr,nc,optarg,&nb,&nr,&nc);
scale=atoi(optarg);
if(is_scale==2)
{
printf("bmptool: -s: scale can only be called once in commmand line");
error=1;
}
if(scale<0)
{
printf("bmptool: -s : the scale must be a positive integer");
error=1;
}
//printf("This is working s");
break;
case 'r':
is_rotate= is_rotate+1;
//rotate(b,r,c,optarg,&b,&r,&c);
degree=atoi(optarg);
if(is_rotate==2)
{
printf("bmptool: -r: rotation can only be called once in commmand line");
error=1;
}
if(degree%90 != 0)
{
printf("bmptool: -r: the degree of rotation must be a multiple of 90");
error=1;
}
//printf("this is working r");
break;
case 'f':
is_flip=is_flip+1;
if(is_flip==2)
{
printf("bmptool: -f: flip can only be called once in command line");
}
break;
case 'o':
outputFile=(optarg);
//printf(outputFile);
//readFile(outputFile,&r,&c,&b);
break;
}
}
if(error==1)
{
return 0;
}
if(is_rotate==0 && is_scale==1 && is_flip==0)
{
enlarge(nb,nr,nc,scale,&nb,&nr,&nc);
writeFile(inputFile,r,c,b);
}
I only added the if statement that contains the enlarge. Thanks in advance for the help.
Try this:
int enlarge(PIXEL* original, int rows, int cols, float scale,
PIXEL** enlarged, int* newrows, int* newcols)
{
int row, col;
if((rows<=0)|| (cols<=0))
{
return -1;
}
(*newrows)=(int)((float)rows * scale);
(*newcols)=(int)((float)cols * scale);
*enlarged=(PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));
for(row=0;row<(*newrows);row++)
{
for(col=0;col<(*newcols);col++)
{
(*enlarged)[row * (*newcols) + col] = original[(row * rows / (*newrows)) * cols + col * cols / (*newcols)];
}
}
/* THIS IS THE METHOD THAT YOU SHOULD WRITE */
return 0;
}
NOTE: i change scale type to float in order to you could scale in any factor, but you could change to int with any problem
You must pass newrows and newcols by ref (not pointer)
EDIT: function usage
scale = 2.0f;
readFile("example.bmp",&r,&c,&b);
enlarge(b,r,c,scale,&nb,&nr,&nc);
writeFile("enlarge.bmp",nr,nc,nb);
free(nb);
If this is a standard Windows bitmap, then newrows must be of a scanline size. A bitmap image consists of scanlines. A scanline consists of pixels. A pixel consists of one or more components (colors).
A scanline must be a multiple of 4 bytes. So after the last component of the last pixel of a scanline, there may follow some unused bytes.
So your scaled bitmap must have scanlines of the appropriate size. See also
Dealing with padding in a BMP file in C of how to calculate scanline sizes and iterate over an image.
Note also that if you just "scale" with an integer, you can scale 1, 2, 3... integer times (100%, 200%,...). Scaling with non-integers requires smearing the pixels out over the new width and hight. Numerous algorithms and ready-to-use code are available on the internet.

Weird results when implementing Sobel Filter [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have been learning about computer vision and wanted to implement some simple techniques in C. For the first technique, I am doing the Sobel edge detection filter. I understand how it works and so I thought it should be fairly easy to code, but I am getting very weird results.
I am using the following image:
and getting this as a result
New Results!:
It should be noted that I am using the .ppm image format (the links are to jpgs since I could not find an image host that supports .ppm)
Anyways, here is the section of my code that implements Sobel:
/**********************************************************
This program takes in an image file and applies the Sobel
Filter edge detection technique to it.
**********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "ppmReader.h"
void sobelFilter(){
//Sobel kernels dx (horizontal) and dy (vertical)
int horizFilter[3][3] = {{ 1, 0, -1},
{ 2, 0, -2},
{ 1, 0, -1}};
int vertFilter[3][3] = {{ 1, 2, 1},
{ 0, 0, 0},
{-1, -2, -1}};
int pixVal = 0;
int horizPixVal = 0;
int vertPixVal = 0;
int x, y, i, j;
//Quick check to make sure dimensions are correct
printf("Using a Width of: %d\n", width);
printf("Using a Height of: %d\n\n", height);
//Start filtering process here
for(x = 0; x < width; x++){
for(y = 0; y < height; y++){
pixVal = 0;
horizPixVal = 0;
vertPixVal = 0;
if(!((x == 0) || (x == width-1) || (y == 0) || (y == height-1))){ //If the current pixel is along the border, ignore it and set to zero
for(i = -1; i <= 1; i++){ //because the kernel does not align to it
for(j = -1; j <= 1; j++){
horizPixVal += (int)(image[y + j][x + i][0]) * horizFilter[i + 1][j + 1]; //Only need to focus on one of the RGB values since the output is
vertPixVal += (int)(image[y + j][x + i][0]) * vertFilter[i + 1][j + 1]; //greyscale and all three values are the same
}
}
}
pixVal = sqrt((horizPixVal * horizPixVal) + (vertPixVal * vertPixVal)); //Calculate magnitude
pixVal = sqrt(horizPixVal * horizPixVal);
if(pixVal > 255) pixVal = 255; //Clamp value within 8-bit range
filteredImage[y][x][0] = (unsigned char)pixVal;
}
}
}
Here is the code that reads the .ppm file:
unsigned char image[MAX_IMAGE_HEIGHT][MAX_IMAGE_WIDTH][3];
unsigned char filteredImage[MAX_IMAGE_HEIGHT][MAX_IMAGE_WIDTH][3];
void readPPMImageData(){
char fileName[MAX_NAME];
char imageBuff[MAX_BUFF];
width = 0;
height = 0;
maxColor = 0;
int x;
int y;
FILE* file;
printf("------------------------------------------------------------\n");
printf("Now attempting to read in the .ppm image file data...\n");
printf("------------------------------------------------------------\n\n");
printf("What is the image file name (*.ppm)? : ");
scanf("%s", fileName);
file = fopen(fileName, "rb"); //open the file specified by the user in binary read mode
if(file == NULL){ //but if the file was not found, terminate program
printf("\nThe file %s could not be found! Terminating program...\n", fileName);
exit(1);
}
//The first step is to read in the file type and check it agains P6 (file type of .ppm images)
fgets(imageBuff, MAX_BUFF, file);
if(imageBuff[0] != 'P' || imageBuff[1] != '6'){
printf("\nInvalid image type! Acceptable type is: %s --- Received type is: %c%c\n\n", "P6", imageBuff[0], imageBuff[1]);
}
printf("Magic Number is: %c%c\n", imageBuff[0], imageBuff[1]);
while(width == 0 || height == 0){
fgets(imageBuff, MAX_BUFF, file);
if(imageBuff[0] != '#') {
sscanf(imageBuff, "%d %d", &width, &height);
}
}
printf("Width is: %d\n", width);
printf("Height is: %d\n", height);
//if(feof(file)){
//
//}
while(maxColor == 0){
fgets(imageBuff, MAX_BUFF, file);
if(imageBuff[0] != '#') {
sscanf(imageBuff, "%d", &maxColor);
}
}
printf("Maximum color value is: %d\n", maxColor);
for(x = 0; x < width; x++){
for(y = 0; y < height; y++){
image[y][x][0] = (unsigned char)fgetc(file); //Get Red value
image[y][x][1] = (unsigned char)fgetc(file); //Get Green value
image[y][x][2] = (unsigned char)fgetc(file); //Get Blue value
}
}
printf("Finished reading image data!\n\n");
fclose(file);
}
And here is the code that creates the new .ppm file after filtering:
void createPPMImage(){
char fileName[MAX_NAME];
FILE* file;
int x;
int y;
printf("------------------------------------------------------------\n");
printf("Now attempting to create new .ppm image file...\n");
printf("------------------------------------------------------------\n\n");
printf("What is the name of the output image file (*.ppm)? : ");
scanf("%s", fileName);
printf("Width is: %d\n", width);
printf("Height is: %d\n", height);
printf("Maximum color value is: %d\n", maxColor);
file = fopen(fileName, "wb");
fputs("P6\n", file);
fprintf(file, "%d %d\n", width, height);
fprintf(file, "%d\n", maxColor);
for(x = 0; x < width; x++){
for(y = 0; y < height; y++){
fputc(filteredImage[y][x][0], file); //Write Red value
fputc(filteredImage[y][x][0], file); //Write Green value
fputc(filteredImage[y][x][0], file); //Write Blue value
}
}
printf("Finished creating new filtered image!\n\n");
fclose(file);
}
I'm 100% sure the issue isn't with the reading or writing of the image as I tested those functions without the filter applied and only get issues once I use the above function.
Any help is appreciated because as far as I can see, the indexing/formula seems to be correctly implemented but that is obviously not true.
EDIT: As Dave and others have pointed out, I am no longer 100% sure that the error is within the Sobel function and it appears this is just some indexing mistake I have made when using the .ppm format. I went ahead and posted the code for my .ppm reader/writer functions and the new results I am getting after applying the [y][x][color] scheme propsed by anatolyg below. I am sorry if my post is way too long and if it is please let me know as this is my first post and I am not entirely sure what is proper yet.
Images are usually indexed with y coordinate first and x second, like this:
... image[y + j][x + i] ...
This is a convention that keeps people from getting confused when dealing with images in C. Unfortunately, it kinda contradicts the one that Matlab uses, so I just hope you are doing it all in C.
In addition, PPM format specification says that the red/green/blue values are interleaved, so the "colour plane" must be the last index:
... image[y + j][x + i][0] ...
unless there was some reordering of the input file while loading it into memory. You didn't show code that reads from the file, so it's hard to know whether it did any reordering.
Addition: reading and writing the file should follow raster ordering, that is, finish pixels of one line before proceeding to next line:
for(y = 0; y < height; y++){
for(x = 0; x < width; x++){
...
}
}
It is also recommended to do processing in this manner; this is not an absolute must, but it will reduce confusion, and might make your processing faster in addition (by using CPU cache more effectively).

Selection of primitives when clicked by mouse not working

I'm developing a solitary board game, which has a piece per square, and each piece can be of two colors. If I click a piece, the four adjacent ones (top, bottom, left and right) all change to the next color.
I'm having problems with detecting in which piece the mouse was clicked on.
I have the following code for the mouse callback:
GLuint selectBuf[BUFSIZE]; // BUFSIZE is defined to be 512
GLint hits;
GLint viewport[4];
if( ( state != GLUT_DOWN ) && ( button != GLUT_LEFT_BUTTON ) )
return;
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (BUFSIZE, selectBuf);
(void) glRenderMode (GL_SELECT);
glInitNames();
glPushName(0);
gluPickMatrix ((GLdouble) x, (GLdouble) y, 20.0,20.0, viewport);
draw(GL_SELECT); // the function that does the rendering of the pieces
hits = glRenderMode(GL_RENDER);
processHits (hits, selectBuf); // a function that displays the hits obtained
Now, the problem I have is that I don't quite know how to process the hits occurred which are on selectBuf. I have the following code for processHits:
void processHits (GLint hits, GLuint buffer[])
{
unsigned int i, j;
GLuint ii, jj, names, *ptr;
printf ("hits = %d\n", hits);
ptr = (GLuint *) buffer;
for(i = 0; i < hits; i++) {
printf("hit n. %d ---> %d",i, *(buffer+i));
}
}
Finally, in the draw function I have:
void draw(GLenum mode) {
glClear (GL_COLOR_BUFFER_BIT);
GLuint x,y;
int corPeca; //colourpiece in english
int corCasa; //colourHouse (each square has a diferent color, like checkers)
for (x =0; x < colunas; x++) { //columns
for(y=0; y < colunas; y++) {
if ( (tabuleiro[y*colunas+x].peca) == 1) //board
corPeca = 1;
else
corPeca = 2;
if((tabuleiro[y*colunas+x].quadrado)==1) //square
corCasa = 1;
else
corCasa = 2;
if (mode == GL_SELECT){
GLuint name = 4;
glLoadName(name);
}
desenhaCasa(x,y,corCasa); //draws square
desenhaPeca(x,y,corPeca, mode); //draws piece
}
}
}
Now, has you can see, I've just put 4 into the buffer with glLoadName. However when I pull the number out in processHits I always get 1. I know that's because of the structure of the buffer that gets the hits, but what is that structure and how can I access the number 4?
Thank you very much for helping me.
The structure of the selection buffer is a bit more complex than that. For each hit, a "hit record" consisting of several values is appended to the selection buffer. You can look at Question 20.020 in the OpenGL FAQ for details. In your case, where there is only one name on the stack at a time, the hit record will consist 4 values, with the name being the fourth one. So, in your processHits function, you should write
for(i = 0; i < hits; i++) {
printf("hit n. %d ---> %d",i, *(buffer+4*i+3));
}
Also, the size of your name buffer should probably be 4 times longer as well.

Resources