Hi,
I've been looking at the OpenGL library trying to understand why the pixels[] things didn't work.
I think it must be that the modelview and projection matrices are not right. But there is also a small conception problem in the updatePixels() function.
The problem is that glRasterPos() is a position in a 3D space which is treated as any other glVertex, this means it is transformed by the modelview and projection matrices. This is obviously not what the users expects. In P3D when we transform the pixels[] and we updatePixels() these are not painted in a position depending on the camera, they are painted directly to the screen.
To fix it, the MODELVIEW must be set to the Identity matrix and the PROJECTION must be set to the orthogonal matrix right before the glRasterPos().
All the buffers must be cleared aswell. Since what the user is doing by updatePixels() is forgetting any alpha values and printing a completely redesigned frame.
I'm not that great in programming, but I did a small crappy modification that looks like this:
Code:
public void updatePixels() {
// flip vertically (opengl stores images upside down),
int index = 0;
int yindex = (height - 1) * width;
for (int y = 0; y < height/2; y++) {
if (BIG_ENDIAN) {
// and convert ARGB back to opengl RGBA components (big endian)
for (int x = 0; x < width; x++) {
int temp = pixels[index];
/*
pixels[index] =
((pixels[yindex] >> 24) & 0xff) |
((pixels[yindex] << 8) & 0xffffff00);
pixels[yindex] =
((temp >> 24) & 0xff) |
((temp << 8) & 0xffffff00);
*/
pixels[index] = ((pixels[yindex] << 8) & 0xffffff00) | 0xff;
pixels[yindex] = ((temp << 8) & 0xffffff00) | 0xff;
index++;
yindex++;
}
} else {
// convert ARGB back to native little endian ABGR
for (int x = 0; x < width; x++) {
int temp = pixels[index];
pixels[index] = 0xff000000 |
((pixels[yindex] << 16) & 0xff0000) |
(pixels[yindex] & 0xff00) |
((pixels[yindex] >> 16) & 0xff);
pixels[yindex] = 0xff000000 |
((temp << 16) & 0xff0000) |
(temp & 0xff00) |
((temp >> 16) & 0xff);
index++;
yindex++;
}
}
yindex -= width*2;
}
// re-pack ARGB data into RGBA for opengl (big endian)
/*
for (int i = 0; i < pixels.length; i++) {
pixels[i] = ((pixels[i] >> 24) & 0xff) |
((pixels[i] << 8) & 0xffffff00);
}
*/
//System.out.println("running glDrawPixels");
//gl.glRasterPos2i(width/2, height/2);
//gl.glRasterPos2i(width/2, 1); //height/3);
//gl.glRasterPos2i(1, height - 1); //1, 1);
// for some reason, glRasterPos(0, height) won't draw anything.
// my guess is that it's getting "clipped", so adding an epsilon
// makes it work. also, height-1 would be the logical start,
// but apparently that's not how opengl coordinates work
/////// MODIFICATIONS //////
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT | GL.GL_ACCUM_BUFFER_BIT);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glOrtho( 0, width, 0, height, 0, 1 );
/////// END OF MODIFICATIONS //////
gl.glRasterPos2f(0.0f,0.0f); // I put (0,0) since we have rechanged the projection matrix and forgot the glScalef(1,-1,1) of before
/////// SOME DEBUGGING CODE /////
float[] buff = new float[4];
byte[] bufb = new byte[1];
gl.glGetBooleanv(GL.GL_CURRENT_RASTER_POSITION_VALID,bufb);
gl.glGetFloatv(GL.GL_CURRENT_RASTER_POSITION,buff);
System.out.println("Current raster pos validity = ("+bufb[0]+")");
System.out.println("Current raster pos = ("+buff[0]+","+buff[1]+","+buff[2]+";"+buff[3]+")");
/////// END OF DEBUGGING CODE //////
gl.glDrawPixels(width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixels);
/////// MODIFICATIONS //////
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPopMatrix();
/////// END OF MODIFICATIONS //////
}
Note: this only works for me in some runs, NOT all the time. I find it wierd, but I'm guessing it has to do with some threading desync or something.
Here is a test applet (run it several times to find a good result). Compare it to the result using P3D:
Code:
import processing.opengl.*;
void setup()
{
size(100, 100, OPENGL);
background(255,255,255);
color azul = color(0, 0, 125);
loadPixels();
for (int i=0; i<(width*height/2)-width/2; i++) {
pixels[i] = azul;
}
updatePixels();
}
PS: I do think the OpenGL library needs a cleaning and structuring. But I have not time at all at this point. I would be willing to help to who's willing to do it though.