Hi Guys
I'm doing a project at the moment trying to impliment a BOIDS (flocking behavior) techniques.
I need to use the glReadPixels method to look either side of the current object to see what is next to it.
Is there any simple examples i can follow about? (of course in LWJGL ;) )
Cheers
So i've created a Buffer
ByteBuffer imageBuffer = BufferUtils.createByteBuffer(length);
and called the glReadPixels
GL11.glReadPixels(x, y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBuffer);
But seen as i need to have 2 image buffer looking at opposite sides of the object, eg fish eyes, how can this be done?
Cheers
Sounds like you're going about it the wrong way - why don't you use logic to work it out, rather than whether you've drawn to the screen at any given point?
Well, i could quite easily know (which i do) the points of the other fish, however to get the best out of this project as its for a uni project i need to use this function. Been told i wont get the marks i need if i dont interpret what the scene can see.
Help appreciated :)
If I'm understanding you correctly, could you not simply:
a) make a larger buffer and capture a larger area of the screen that includes both sides of the fish, or
b) use two byte buffers, or
c) use the same buffer twice?
// method a)
// where width is 2x the size of the area to one side of the fish,
// and x,y are the coordinates of the fish on the screen
ByteBuffer imageBuffer = BufferUtils.createByteBuffer(width*height);
GL11.glReadPixels(x - (width/2), y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBuffer);
// method b)
// where width and height are the normal size of one
// area on the side of a fish to scan
ByteBuffer imageBufferLeft = BufferUtils.createByteBuffer(width*height);
ByteBuffer imageBufferRight = BufferUtils.createByteBuffer(width*height);
GL11.glReadPixels(x - width, y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBufferLeft);
GL11.glReadPixels(x, y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBufferRight);
// method c)
ByteBuffer imageBuffer = BufferUtils.createByteBuffer(width*height);
GL11.glReadPixels(x - width, y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBuffer);
// do your analysis on the buffer here
GL11.glReadPixels(x, y, width, height, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, imageBuffer);
// do your analysis on the buffer again here
Forgive me if I've misunderstood you.
Hi mate
it does need to be 2 seperate buffers like you said but i cant work out how to point them in 2 seperate directions, i would be nice to be able to use one buffer of the whole image but its kind of cheating for what i need to do.
so thats question 1) how do you aim 2 buffers in different directions, i possibly assume you have to create 2 windows, but i'm not sure.
2nd question 2) is i've got a small screen buffer working, i'm getting the data out of it with this code.
for (int row = 0; row< height; row++){
firstElement -= bytesPerRow;
bufferIndex = firstElement;
for(int column = 0; column <width; column ++){
int red = imageBuffer.get(bufferIndex ++);
int green = imageBuffer.get(bufferIndex ++);
int blue = imageBuffer.get(bufferIndex ++);
bufferRGBArray[bufferArrayIndex ++] = 0xFF000000 | ((red & 0x000000FF) << 16) | ((green & 0x000000FF) << 8) | (blue & 0x000000FF);
System.out.println("BA =" + 0xFF000000 + "RED" + ((red & 0x000000FF) << 16)+ "green" + ((green & 0x000000FF) << 8)+ "blue"+ (blue & 0x000000FF));
}
}
}
when it prints out i get mostly -16777216 Red0 green0 blue0
however when it does detect colour it gets -16777216 Red16711680 green65280 blue255
blue is obvous but how so you interpret the Red and Green
Thanks
Quote from: "Mattbooth"1) how do you aim 2 buffers in different directions, i possibly assume you have to create 2 windows, but i'm not sure.
Not quite sure what you mean by this - surely you can just input different X and Y coordinates into the first two parameters of glReadPixels so that you are looking at different areas of the screen?
Quote from: "Mattbooth"2) i've got a small screen buffer working, i'm getting the data out of it with this code.
/snip
Not sure quite what you're doing there: I can see you're getting the colours out but then you appear to be squashing them into an int and stashing them in a different byte buffer?
In any case you probably just need to be removing the shifts for your println. You don't need to shift the values if you're just gettin gthe raw value and printing it out.
System.out.println("red " + red + " green " + green + " blue "+ blue);
Try that
hi mate
Thanks again, question i have my head around thank god, just my brain trying to make it more complicated than it really is.
Do you actually need to draw a buffer on the screen for the glReadPixels to work?
Now back to question 2) of above
i need to extract the R G B of each pixel so that simple analysis can be done on it, is the way that i'm doing it above the easiest way, the above was taken from an example i found and i not 100% what it does and how its stored.
Any easier way to get the RGB and store them seperatly and easily would be appreciated :)
Thanks
glReadPixels will work, but you have to have drawn stuff to the screen first, either using primitivevs such as triangles or by using one of the many gl###Pixels commands, or glBitmap, or whatever else.
To be honest I haven't worked with glReadPixels a lot, but you can find reference here (http://rush3d.com/reference/opengl-bluebook-1.0/ch05.html#id5527285) which may help you. It sounds and looks like you're getting the correct values out of the buffer once you've read them in. I assume you want to copy the data from the byte buffer over to something where you can easily get at the data? If you wanted to do it easily, you could do it like this:
int redArray[width][height]; // or however you declare useable 2D arrays in Java
int blueArray[width][height];
int greenArray[width][height];
for (int row = 0; row< height; row++) {
// I assume these are here because OpenGL reads data in from the screen upside-down
firstElement -= bytesPerRow;
bufferIndex = firstElement;
for(int column = 0; column <width; column ++){
redArray[column][row] = imageBuffer.get(bufferIndex ++);
greenArray[column][row] = imageBuffer.get(bufferIndex ++);
blueArray[column][row] = imageBuffer.get(bufferIndex ++);
// print out the value if you like
// System.out.println("red " + red + " green " + green + " blue "+ blue);
}
}
// now you can find out the red, green or blue value of a location using the x,y coordinates
Not sure if that's what you want and it certainly isn't "optimal" but it's readable and easy to use I guess.
I'll have a play tomorow mate thanks for your help :)
Has anyone else had any success with using glReadPixels without actually drawing to screen?
I need to get the pixels, interpret them, then move onto the next, however the interpretation is a different angle on the screen which i dont really need to see..
Any thoughts?
Cheers
Okay now i am stumped....
so apprently you can use glReadBuffer and so longs you are using double buffering you can get the pixels, however i want to get them from a seperate camera angle withough moving the main camera, which is what i think the readbuffer is for....
Anyone give me a hand...
Cheers
What you need to do is, set up the camera for the particular viewpoint you're interested in, draw the entire scene, then call glReadPixels on the backbuffer. Then move the camera to where you actually want people to see things and draw the entire scene again, and swap the buffers.
Basically - you're drawing it all twice.
Cas :)
Hi Cas,
Thats what i have been trying to do mate, but unsuccesfully, i'll attach the code but in simple terms...
main camera angel - GLU.gluLookAt(0.5f,0.5f, 0.0f, 0.6f,0.5f, 0.0f, 0.0f,1.0f,0.0f);
call draw object
get back buffer with GL11.glReadBuffer(GL11.GL_BACK);
change view to GLU.gluLookAt(0.5f,0.5f, 0.0f, 0.5f,0.5f, 1.0f, 0.0f,1.0f,0.0f);
call method to get pixels using glReadPixels
change view back to main view
RGB values still read 0, 0, 0
code @ http://www.booth123.pwp.blueyonder.co.uk/zViewTEST.java
god this is depressing :roll: any further help appreciated :)
glReadBuffer doesn't do any reading, it just tells glReadPixels which buffer it's going to read from.
Cas :)
Hi caz, forgive my ignorance, just a bit of bad wording...
Even if glReadBuffer sets the buffer to read the front or the back buffer, how do you set the camera angle's in the different buffers?
still cant get anywhere :oops:
You don't! You always render to the backbuffer.
What exactly is the effect you're trying to do? I've got a funny feeling you're going sort of the wrong way about it.
Cas :)
quite possibly caz :)
Okay i have a shoal of fish that you can see from the main window
I need to get the RGB values from either side of the fish (in effect what they can see) and interpret it.
So i thought i would have to use the back buffer to change the camera angle get the RGB, same on the other side of the fish, this can then be interpreted, however in the mean time the camera angel is changed back to the main shot of the shoal.
The aim is to calculate in the background without the main image being any different
Anything you can do to save me will be fab :)
Erk, ok. Pretty strange way of going about it! It's going to be pretty bloody slow I think.
For every fish you'll need to clear the buffer, render the scene from the fish's left eye, read the backbuffer; then clear the buffer again, render the scene from the fish's right eye, then read the backbuffer again. Repeat for each fish. Then plonk the camera somewhere interesting and render the scene you want to actually see, and swap the buffers.
Cas :)
Caz your the man lol
Yep that worked, i agree its going to be rather slow, i cant think of any other way to do it though.
One last question if you dont mind, when i call the update of hte scene to get all the info it updates the back buffer with the next sequence, so they way its being done at the moment with calling update twice in the same scene, its going to jump a frame.
Is there anyway to avoid this my making a copy of the pixels or something?
Thanks mate :)
slow isnt the word for this, i can make a cuppa between each frame :roll:
hi guys,
Well i've tried for the last couple of days to swop the model i got working to my actual program. As i said its slow but its returning the wrong values. Instead of getting the camerea view of the fish's eye its still returning the value of hte main screen. Quite a bit of code below. The get pixels method words fine as it works on the model.
Method that passes the co-ords of the camera
public void vision(){
int numFish = cFB.getNumOfFish(); // gets number of fish to draw
for (int i = 0; i<numFish; i++){
fish currFish = cFB.getFish(i);
threePointHolder poss = currFish.getCameraPos(); // gets the x,y,z position of the fish
getSideView(poss, true); //sends the xyz to the camera position for left side
getSideView(poss, false); //sends the xyz to the camera position for left side
}
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
initGL(); // resets the camera angle
}
method that clears buffer, sets camera and gets RGB
public void getSideView(threePointHolder newPos, boolean leftP){
eyex = newPos.getX();
eyey = newPos.getY();
eyez = newPos.getZ();
left = leftP;
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
GL11.glShadeModel(GL11.GL_SMOOTH); // Enable Smooth Shading
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
GL11.glClearDepth(1.0); // Depth Buffer Setup
GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Testing To Do
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
//GL11.glScalef(0.2f, 0.2f, 0.2f);
GLU.gluPerspective(10.0f, (float) displayMode.getWidth() / (float) displayMode.getHeight(), 0.1f, 200.0f);
if (left == false){
System.out.println("right");
GLU.gluLookAt(eyex, eyey, eyez, eyex, eyey, (eyez+0.1f), 0.0f,1.0f,0.0f);
left = true;
}
else{
System.out.println("left");
GLU.gluLookAt(eyex, eyey, eyez, eyex, eyey, (eyez-0.1f), 0.0f,1.0f,0.0f);
left = false;
}
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
// Really Nice Perspective Calculations
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
drawAll();
try{
getShot();
}
catch(Exception e){
System.exit(0);
System.out.println("ERROR");
}
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
}
Now i know its passing the right values across from testing but the getting of the RGB from these positions isnt right. It still gets it from the main screen
and after this code is executed i call
drawAll() // draws everything again
Display.update() //swop buffers.
going out my mind now, all things say it should work, but it gets the RGB of the main screen :roll: [/code]