tutorial 6

In this tutorial, we'll start out by learning another way to load a picture. The picture will be star.bmp, located one level below our running directory. First we declare an NSURL to hold the location of the star. Our initial location is going to be "../star.bmp". We try to open the default location, then ask the user for a location if we don't find star.bmp there (more on that method later). We can the name the star so that it is accessible in the same way that our NIB dice were accessible.


NSURL *starURL; NSImage *starimage; NSLog(@"get the image");
// get the URL for the star image // the application is in the build directory, one level up from our star
starURL = [[NSURL alloc] initFileURLWithPath: @"../star.bmp"]; if( starURL != nil ) NSLog(@"NSURL != nil");
// load the star from the file
starimage = [[NSImage alloc] initWithContentsOfURL: starURL ];
// if we didn't load the image, then we try to get the user to give the image
if( starimage == nil ) starimage = [self findImage: @"star.bmp"];
// name the image
[starimage setName:@"star"];
// generate the texture objects references
glGenTextures( NUMTEXTURES, texture );
// these were described in the previous tutorial
glBindTexture( GL_TEXTURE_2D, texture[0] ); [self loadPicture: @"star"];
// release the memory that was allocated
[starURL release]; [starimage release];

Here's the code for the findImage method. It takes a string and looks for any bmp files that are named that string. It asks the user to input the string.


- (NSImage *) findImage: (NSString *)resource { NSOpenPanel *oPanel = [NSOpenPanel openPanel]; NSArray *fileTypes = [NSArray arrayWithObject:@"bmp"]; NSImage *image; int result;
// this forces the open panel to allow the selection of only one file at a time
[oPanel setAllowsMultipleSelection:NO];
// now we call the open panel to get the resource //The NSHomeDirectory() function will get the home directory
result = [oPanel runModalForDirectory:NSHomeDirectory() file:resource types:fileTypes]; if( result == NSOKButton ) { NSString *aFile = [[oPanel filenames] objectAtIndex:0]; image = [[NSImage alloc] initWithContentsOfFile:aFile]; }
// image will be nil if the user pressed cancel or if the image failed to load for some other reason
if( image != nil ) return image; else {
//Here's the interface for the next command we will use // //APPKIT_EXTERN int NSRunCriticalAlertPanel( // NSString *title, NSString *msg, // NSString *defaultButton, NSString *alternateButton, // NSString *otherButton, ...); // // Here we call for an alert panel. As shown above, the title bar will // display "Can't find a resource". A string informing the user that the resource was not found // will appear in the text of the box. Finally, we will have a button for "Okay", the other // buttons being nil as there is nothing the user can do to let me continue running this program
NSRunCriticalAlertPanel(@"Can't find a resource", [resource stringByAppendingString:@" was not found"], @"OK",nil,nil); exit(-1); } }

Here's the definition for the star structure. We'll want many different stars, each with a different red, green and blue value, a different distance and angle, and a possibly different spin and tilt. The tilt will in fact be simply 90°.


typedef struct _star { int r; int g; int b; float i; GLfloat distance; GLfloat angle; GLfloat tilt; GLfloat spin; } Star;

In this method, we define each of the stars. We are using an unchanging C array, so there is no need to allocate memory in this method. Not much to this, but note that we get a random number (0 <= RV <= MAX_FLOAT ) and then convert it to a number 0 <= RV <= 256. We lose some of the randomness by doing this because we are discarding some of the bits, but we aren't concerned with true pseudo-randomness so much as we are concerned with the fact that the stars are different colors.


int i; for( i = 0; i < NUMSTARS; i++ ) { StarArray[i].distance = ((float)i/(float)NUMSTARS)*20.0f; StarArray[i].angle = (float)i/(float)NUMSTARS; StarArray[i].r = rand()%256; StarArray[i].g = rand()%256; StarArray[i].b = rand()%256; StarArray[i].tilt = 90; StarArray[i].i = i;
// print out the information for debugging purposes
NSLog(@"star %i: d=%f, a=%f", i, StarArray[i].distance, StarArray[i].angle); }

In this method, we define each of the stars. We are using an unchanging C array, so there is no need to allocate memory in this method. Not much to this, but note that we get a random number (0 <= RV <= MAX_FLOAT ) and then convert it to a number 0 <= RV <= 256. We lose some of the randomness by doing this because we are discarding some of the bits, but we aren't concerned with true pseudo-randomness so much as we are concerned with the fact that the stars are different colors.


for( i = 0; i < NUMSTARS; i++ ) { Star s = StarArray[i];
// remember to load your identity // or your results will be very odd
glLoadIdentity(); glTranslatef(0,0,-40);
// tilt the star
glRotatef(s.tilt,1.0f,1.0f,0.0f);
// rotate the star so that we are turning on the proper angle
glRotatef(s.angle,0.0,1.0,0.0);
// move the star away from the center of the screen
glTranslatef(s.distance,0,0);
// unangle the world (so that the star is on our sight line)
glRotatef(-s.angle,0.0,1.0,0.0); glRotatef(-s.tilt,1.0f,1.0f,0.0f);
// This is another form of color that uses unsigned bytes to determine the color
glColor4ub(s.r,s.g,s.b,255); glBindTexture( GL_TEXTURE_2D, texture[0] ); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f); glEnd();
// move the star closer to the center and change the angle
StarArray[i].distance-=0.05f; StarArray[i].angle+=(StarArray[i].i/(float)NUMSTARS);
// if the star is in the middle, we give it a new red, green and blue value // then move it 20 units away from the center of the screen
if (StarArray[i].distance<0.0f) { StarArray[i].distance+=20.0f; StarArray[i].r=rand()%256; StarArray[i].g=rand()%256; StarArray[i].b=rand()%256; } }




     Download the project builder files

 

return to deep cocoa / cocoagl tutorials