View Full Version : Cocoa OpenGL
Before anybody even thinks it: I searched the forums with multiple phrases and could not find this answer. I also searched google and came up with nothing of use.
I'm trying to learn how to use Cocoa with OpenGL. I can already use OpenGL with SDL and C++ but I want to learn and expand my knowledge. I know a decent amount of Objective-C (after quite a bit of reading and testing) and figured I'd give this a shot. I looked at a site called Deep Cocoa but found the tutorials rather worthless in explaining what was going on. I also downloaded NeHe's base code but I can't figure it out without explanation (unless it's hiding somewhere I can't find).
I don't expect anybody to provide me with a lecture on the subject (as I figure that would take a while), I'm simply wondering if there are any websites better than Deep Cocoa and NeHe's base code for learning OpenGL in Cocoa? Or do I just have to tough it out and do it myself? :shock:
I'm simply wondering if there are any websites better than Deep Cocoa and NeHe's base code for learning OpenGL in Cocoa?In a word: no. Try to figure out the flow of the programs, and then ask any specific questions here. :)
arekkusu
2004.09.30, 12:58 AM
Start with Apple's sample code (http://developer.apple.com/samplecode/GraphicsImaging/idxOpenGL-date.html).
Vertizor
2004.09.30, 01:45 AM
If you understand how to use Interface Builder and make a subclass of widgets you drag n drop, then that's half the battle.
There are methods of NSOpenGLView for you to overload to make things work.
- (void) reshape:
This is where you put your code that handles resizing the viewport, and resetting the projection.
- (void) drawRect:
This is where you put your OpenGL rendering code. The framework will call it for you whenever it's needed. If you need to manually redraw the scene (like based on a timer or mouse/keyboard input) some sample code tells us to call NSView's setNeedsDisplay: YES
- (void) prepareOpenGL:
This was added in OSX 10.3, it's called by the framework after the opengl context is created and attached to the view widget. This is where you do all your setup, like your glEnable() calls.
Hope this is enough to get your started. Like arekkusu said, just look at Apple's sample projects.
Taxxodium
2004.09.30, 04:03 AM
Try this little tutorial: OpenGL in Cocoa (http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL/chap4/chapter_4_section_1.html#//apple_ref/doc/uid/TP30000163)
Cool. That OpenGL in Cocoa link looks useful. I'll take a look at it later when I get home and see if that helps.
skyhawk
2004.09.30, 11:00 AM
- (void) prepareOpenGL:
This was added in OSX 10.3, it's called by the framework after the opengl context is created and attached to the view widget. This is where you do all your setup, like your glEnable() calls.
any advantage to this over awakeFromNib?
Taxxodium
2004.09.30, 11:02 AM
any advantage to this over awakeFromNib?
not really, but if you wanna keep compatibility with non Mac OS X 10.3 users, I recommend doing your OpenGL initialization in:
- (id)initWithCoder:(NSCoder*)coder {
//setup NSOpenGLView with a pixelFormat
//init OpenGL
//init everything else you need
}
That's how do it :)
edit: smileys and code don't work well together
That tutorial helped a lot. Got that all set up. Played around with it a bit. Made a rectangle move instead of one point of a triangle.
One thing I'd like to know is setting up the resolution of the view. If I use (0,0) I'm in one corner and (1,0) is the other corner. How can I change this so that it's like (0,0) is the top left and (800,0) is the top right? I can do this in SDL but my code (from the tutorial) doesn't have any of the projection matrix setting or the glViewport code so I'm at a loss for how to do this.
Would this fit into the prepareOpenGL function (or similarly named) from one of the above posts? If I override that function what else am I going to have to put in it to have it still work (seeing as none of the code from the original function will get called)?
Taxxodium
2004.09.30, 02:13 PM
You can set the resolution using the glViewPort function. Do this in the reshape method of the NSOpenGLView. Like this:
- (void)reshape {
float ratio;
NSSize bounds = [self bounds].size;
ratio = bounds.width / bounds.height;
glViewport(0, 0, [self frame].size.width, [self frame].size.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//set your other stuff here (glPerspective of glOrtho)
}
Now if you want get the mouse position in that view you'll need convert the point into OpenGL units.
I've found that temporarily switching to orthographic mode is the best way to get the mouse coordinates, since glPerspective will give you some odd values.
Vertizor
2004.09.30, 03:00 PM
Now if you want get the mouse position in that view you'll need convert the point into OpenGL units.
I've found that temporarily switching to orthographic mode is the best way to get the mouse coordinates, since glPerspective will give you some odd values.
Do a search (either in this forum or Google) for gluUnproject.
If you're using glOrtho, here's a code snippet to reorient the coordinate system so that the top/left corner is (0,0) this would go in your -reshape: method.
glViewport(0, 0, w, h); // Establish viewing area to cover entire window.
glMatrixMode(GL_PROJECTION); // Start modifying the projection matrix.
glLoadIdentity(); // Reset project matrix.
glOrtho(0, w, 0, h, -1, 1); // Map abstract coords directly to window coords.
glScalef(1, -1, 1); // Invert Y axis so increasing Y goes down.
glTranslatef(0.0f, (float)-h, 0.0f);
I haven't tried this but I think if you omit the last 2 lines of code (glScalef() and glTranslatef()) then (0,0) will be in the lower right corner of the viewport, which is more OSX centric.
Taxxodium
2004.09.30, 03:08 PM
Do a search (either in this forum or Google) for gluUnproject.
I do use gluUnProject, mainly to convert local mouse coordinates to OpenGL coordinates.
Perhaps some code might be useful on how to use this:
- (TWVector)convertFromWindowCoords:(NSPoint)localPo int {
GLint viewport[4];
GLdouble mvmatrix[16], projmatrix[16];
GLdouble wx, wy, wz;
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
gluUnProject((GLdouble)localPoint.x, (GLdouble)localPoint.y, 0.0, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
return TWVectorMake(wx, wy, 0.0);
}
TWVector is a simple 3D vector, so what this does is convert a point from your window to a vector in OpenGL, keeping the z-axis as zero.
I use this method in my method to get the OpenGL mouse coordinates:
- (NSPoint)mouseLocationInUnits {
NSPoint localPoint = [[self window] convertScreenToBase:[NSEvent mouseLocation]];
NSPoint unitPoint;
unitPoint = NSMakePoint([self convertFromWindowCoords:localPoint].x, [self convertFromWindowCoords:localPoint].y);
return unitPoint;
}
Perhaps there is a better method to do this, but this works for me.
I'm getting a couple errors building this right now (line 1 is just the #import "MyOpenGLView.h" line):
MyOpenGLView.m:1: fatal error: method definition not in class context
MyOpenGLView.m:1: error: parse error before "TWVector"
I've tried a few things but I haven't gotten it yet. Any advice?
Taxxodium
2004.09.30, 05:12 PM
Any advice?
Yes, don't copy/paste the code above. You need create a vector structure and replace that with TWVector, same for the function TWVectorMake, those are things from me, not from Cocoa.
I see. I'll get right on that. :)
I'm having some trouble. The program's getting the values from the sliders, but when I move them the box doesn't change colors until I click on MyOpenGLView. Here's the code from the drawing (some OpenGL).
- (void)drawRect: (NSRect)aRect
{
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
{
glColor3ub([redAmount intValue],
[greenAmount intValue],
[blueAmount intValue]);
glVertex2f(50,50);
glVertex2f(250,50);
glVertex2f(250,250);
glVertex2f(50,250);
glEnd();
}
glFinish();
glFlush();
}
skyhawk
2004.09.30, 10:27 PM
one thing you might want to add:
[[self openGLContext] makeCurrentContext];
I put it in but it didn't solve my problem. What does that do then?
Zwilnik
2004.09.30, 11:24 PM
In the method where you're getting the slider input, remember to do
[self setNeedsDisplay:YES];
to tell your view to update.
Also, doing
[[self openGLContext] flushBuffer];
rather than glFinish() and glFlush() should be faster
(use [myFullScreenContext flushBuffer]; if you're in fullscreen mode)
kelvin
2004.10.01, 07:33 PM
any advantage to this over awakeFromNib? -prepareOpenGL gets called when a context is attached to a view. So this is good for setting up a view's context if you are creating the views in your code rather than in IB. -awakeFromNib is a one time thing for the IB instanciated object; not so hot if you're creating multiple views in code.
I do all my gl client state setup in prepareOpenGL. it makes things a little more organized and easy to edit.
webwarrior
2004.10.02, 03:44 PM
Hmm I've chosen a different approach. Creating the NSApp and adding a delegate. The delegate will then be notified when the app has finished starting and before it terminates. You can the do your init and your cleanup stuff at the correct time.
I don't know, but I had lots of troubles the whole last week when I was trying to port my stuff from SDL to Cocoa. For some stupid reasons awakeFromNib got called two times and I couldn't figure out why.
I do all my gl client state setup in prepareOpenGL. it makes things a little more organized and easy to edit.
That's fine, but your program will not even run on all OS X then.
Taxxodium
2004.10.02, 04:04 PM
I do all my gl client state setup in prepareOpenGL. it makes things a little more organized and easy to edit.
Or you can use initWithCoder if you want your code to be compatible with all versions of OS X
kelvin
2004.10.03, 02:33 AM
That's fine, but your program will not even run on all OS X then. I guess you haven't had the lecture from Travis B about why its a good idea to target the latest OS for new projects. In any case, you only really have to worry about supporting prior systems if you already have an prior installed userbase.
vBulletin® v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.