PDA

View Full Version : OpenGl, Cocoa, 2D image



Gandolf
07-20-2008, 12:17 AM
Hey, I'm new to Xcode and OpenGl, but I have been doing a lot of research and have realized that OpenGl is perfect or possibly overkill for the rpg I am trying to create.

Though, I ran into a problem that is so painstakingly simple that it isn't in any of the Opengl manuals I could find.

I need to know how to stick a 2D image onto the OpenGl canvas from the image resources.

Any ideas?


Thanks,
-Gandolf

ZbuffeR
07-20-2008, 07:08 AM
In fact it is very easy, but there is no real distinction between 3d and 2d stuff, that is why it may be hard to search for this :-)

In summary :
Use glOrtho with appropriate coordinates ranges (choose ranges which are easy for you to work with, typically same as window pixel coordinates). Draw a textured quad with appropriate dimensions.
If your image is power of two (like 128*256) or if your hardware supports the extension GL_ARB_texture_non_power_of_two, the texture coordinates will simply be in the [0,0 1,1] range. Otherwise see this post here for more details : http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=241773#Post241773

This tutorial is quite detailed, it may help too :
http://gpwiki.org/index.php/OpenGL:Tutorials:Tutorial_Framework:Ortho_and_Alph a

Don't hesitate to ask for details if some parts are unclear or seem too complex.

Gandolf
07-20-2008, 08:32 AM
I've noticed that it didn't say the name of the sprite image in the wiki tut.

Does it name each image by a resource number? Like 128-Infinite?


-Gandolf

ZbuffeR
07-20-2008, 09:24 AM
To clear up your confusion :
- texture "names" are in fact unique identifiers, typically each is a 32bits unsigned integer (range is 0 to 4.2billions). So it is more like an id than a name.
- in the above tutorial, a pool of 128 different textures identifiers is generated :


GLuint Texture[128];
glGenTextures(128,Texture);
// now, Texture[i] contains the id for texture number i
// ...
// use it :
glBindTexture(GL_TEXTURE_2D,Texture[Spr[index].Tex]);

- have a read at the official manual page : http://www.opengl.org/sdk/docs/man/xhtml/glGenTextures.xml
- the glGenTexture stuff is optional in practice. I could safely skip it, and simply use glBindTexture(GL_TEXTURE_2D,1); for my first texture, glBindTexture(GL_TEXTURE_2D,2) for the second, etc.

zeoverlord
07-20-2008, 10:04 AM
As a tip, go to http//nehe.gamedev.net (http://nehe.gamedev.net) and you will find tutorials on a lot of things openGL related.

Gandolf
07-20-2008, 11:49 AM
Thanks, I hope I will catch onto this. It's like trying to grasp a frictionless object. I will eventually understand it.


-Gandolf

Gandolf
07-20-2008, 07:07 PM
I'm doing way better now. I found this great tut that just stooped down to my low knowledge of OpenGl.

So far I have created a triangle, set it in the middle of the screen, and added some movement buttons. And I am trying to make the up button work. After it works, I will add texture.

So here is my problem, I'm trying to get the triangle to redraw further along the y axis when I press the up arrow. Here is the code:


#import "MyOpenGLView.h"
#include <OpenGL/gl.h>

@implementation MyOpenGLView
static void drawAnObject ()
{
glColor3f(1.0f, 0.85f, 0.35f);
glBegin(GL_TRIANGLES);
{
glVertex3f( (movex+0.0), (movey+0.6), 0.0);
glVertex3f( (movex+0.2), (movey-0.3), 0.0);
glVertex3f( (movex-0.2), (movey-0.3) ,0.0);
}
glEnd();
}
-(void) drawRect: (NSRect) bounds
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
drawAnObject();
glFlush();
}
- (IBAction)up:(id)sender
{
movey=movey+.2;
[button setStringValue:@"Pressed Up!"];
[movextext setFloatValue: movex];
[moveytext setFloatValue: movey];
// drawRect: (NSRect) bounds ;
drawAnObject ();
}
@end

It makes movey+.2, shows up in the text field, but doesn't move the triangle. I'm trying to call "drawAnObject ();" to redraw it upwards, but it doesn't work.

Could anyone help?


Thanks,
-Gandolf

dletozeun
07-21-2008, 06:14 AM
you need to call glFlush too after the drawAnObject call of you want to refresh the screen.

Or call drawRect that do all the necessary job.

Gandolf
07-21-2008, 07:51 AM
Thanks :). I will try that now.


-Gandolf

Gandolf
07-21-2008, 09:09 AM
It works!:D

Thanks.

Though, now I'm going to try to put a texture on my object and make it move by pressing a arrow key.
Anyone have any tips or guides?


-Gandolf

arekkusu
07-21-2008, 11:15 AM
Look at this crufty old sample (http://developer.apple.com/samplecode/Red_Rocket/index.html). Ignore all the ancient AGL and image loading code. Look at the GL part that draws the sprites.

Gandolf
07-21-2008, 04:16 PM
Thanks.

I believe I got the drawing part down. I just need to add arrow key movement.

Anyone know how to detect if an arrow key is pressed?


-Gandolf

arekkusu
07-21-2008, 08:11 PM
You're using Cocoa, so go read about NSResponder (http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/Reference/Reference.html) and -sendEvent, -keyDown, -keyUp, -flagsChanged.

Gandolf
07-22-2008, 08:07 AM
I've been reading and ran into some trouble. Xcode's manual seems confusing and has no examples, but here is what I have so far.

I have to put this somewhere, do I put it in a NSWindow subclass?

keyEventWithType:location:modifierFlags:timestamp: windowNumber:context:characters:charactersIgnoring Modifiers:isARepeat:keyCode:

Then I have to identify the key pressed with this?

- (unsigned short)keyCode

Could anyone help clear up my confusion?


-Gandolf

P.S.I found an example where you put this code into a NSApplication subclass and when you hit the esc key, it would quit the app. If I stick it in, do you think it would work for me?


- (void) sendEvent:(NSEvent*)event
{
if(([event type] == NSKeyDown) &amp;&amp; ([event keyCode] == 0x35))
[NSApp terminate:nil];

if(_renderer &amp;&amp; (NSEventMaskFromType ([event type]) &amp;
kRendererEventMask))
[self renderWithEvent:event];
else
[ super sendEvent:event];
}

obirsoy
07-22-2008, 11:15 AM
This is how I'm doing it in my NSOpenGLView derived class:



- (BOOL)acceptsFirstResponder // required if you want to get keydown event in NSViews.
{
return YES;
}

- (void)keyDown:(NSEvent*)theEvent
{
NSString *chars = [theEvent characters];
unichar uchar = [chars characterAtIndex:0];

switch(uchar)
{
case 'A':
NSLog(@"A pressed!");
break;
case 'a':
NSLog(@"a pressed!");
break;
case NSUpArrowFunctionKey: // see NSEvent.h for other keys.
NSLog(@"Up pressed!");
break;
}
}

Gandolf
07-22-2008, 11:53 AM
<s>Thanks, though, where do you put this code and do you have to modify anything else?</s>

Hah, It works! Thank you!


-Gandolf

Gandolf
07-22-2008, 12:43 PM
Now that the keys work, I am moving on to adding a while loop that will update the NSOpenGLView 40 fps per second.

When I do a regular "while (quit=1) {" loop, it freezes my application. Is there a way to slow it down so that the loop won't go 200+ times per second? Just to 40 times per second?


-Gandolf

arekkusu
07-22-2008, 01:06 PM
Usually, you use an NSTimer for this.

This is no longer about OpenGL. You need to read the AppKit documentation, and look at the examples that come with XCode. Like /Developer/Examples/AppKit/BlastApp, which shows timers and keyboard controls.

http://idevgames.com is a good general resource for these questions.

Gandolf
07-22-2008, 01:45 PM
Thanks :)


-Gandolf

obirsoy
07-22-2008, 03:19 PM
You can also look at this

http://developer.apple.com/samplecode/glut/index.html

to see how apple did it.