My app uses an NSOpenGLView to draw complex height maps as a shaded polygon mesh.
I’ve written code to save my 3D view to disk as a JPEG or TIFF image. I use FBOs to do the save so I can generate the output at higher resolution than the current view.
I want the user to be able to draw a “crop rectangle” on top of the 3D image so that the file save saves a cropped portion of the current view. This will also let the user create output at an arbitrary aspect ratio.
Based on a discussion in the beginner’s board (I am an OpenGL neophyte) I’m using XOR logic operations to draw to the screen.
Here’s what I do. The user selects “crop mode.” In crop mode, when i get a mousedown, I do some setup to draw directly to the front buffer, switch to orthographic projection, with the coordinates matching the view coordinates. I then go into a while loop, drawing the selection rectangle as the user drags the mouse around, and un-drawing the old selection rect before drawing the new one.
The selection rectangles are drawing with colors that tell me the color values are being XORed. However, the call to erase the old rectangle before drawing a new one isn’t working.
Interestingly, if I draw my rectangle twice in a row, the two draw calls DO cancel out. However, If I draw the rectangle once, do a glFlush(), and wait for the mouse to move before re-drawing it, it doesn’t cancel the old drawing.
Am I getting into trouble because my app is set up for double-buffered drawing, and OS X plays games with buffers in order to handle all the OpenGL activity to draw all the rest of the windowing system?
Here is an extract of the code I’m using. First, the routine to set up for 2D XORed drawing: (called once in my mousedown method)
-
(void) ortho_setup
{
GLsizei w,h;
NSRect rectView = [self bounds]; //Get bounds of OpenGL vieww = rectView.size.width;
h = rectView.size.height;
[[self openGLContext] makeCurrentContext];
glViewport(0, 0, w, h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, 1, -1);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();glDisable(GL_LIGHTING); //turn off lighting effects
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_XOR);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
Then the code to draw the rectangles:
-(void) drawSelectionRect: (NSRect) theSelectionRect
{
if (!NSEqualRects(theSelectionRect, NSZeroRect) )
{
GLint x1 = theSelectionRect.origin.x;
GLint y1 = theSelectionRect.origin.y;
GLint x2 = theSelectionRect.origin.x +
theSelectionRect.size.width;
GLint y2 = theSelectionRect.origin.y +
theSelectionRect.size.height;
glRecti(x1, y1, x2, y2);
//glRecti(x1, y1, x2, y2);//Double call DOES cancel out.
glFlush ();
}
}