Sunday, December 6, 2009

Drawing Rotating Pyramids (Tutorial)

As promised, code with comments on how it works:

Step 1: Add the OpenGL framework to an empty cocoa application.

Step 2: Open the .xib file for the application and drag an NSOpenGLView into the window. Bring up the inspector and click on the identity tab. The Class name should be changed to 'MyOpenGLView'.

Step 3:
.h file:

#import

#include

#include

//Color Depth

#define BITS_PER_PIXEL 32.0

//Depth of Z Buffer

#define DEPTH_SIZE 32.0

//Frames per Second

#define DEFAULT_FRAME_RATE 60.0f


@interface MyOpenGLView : NSOpenGLView

{

//The timer that runs 60 times/second

NSTimer *renderTimer;

}


//Keep track of rotation angle

float rotTri = 0.0f;


//Initialization function for OpenGL

- (void)initGL;


//Function to draw a pyramid

static void drawAnObject();



@end


Step 4:
.m file:

//Run at start

-(void)awakeFromNib

{

NSOpenGLPixelFormat *nsglFormat;

//Specify Attributes to allow screen to use various buffers

NSOpenGLPixelFormatAttribute attr[] =

{

//Enable Z sorting (make sure that polygons in front will overlap those in back)

NSOpenGLPFADoubleBuffer,

//Use Hardware Acceleration for graphics

NSOpenGLPFAAccelerated,

//Specify color depth

NSOpenGLPFAColorSize, BITS_PER_PIXEL,

//Specify Z depth

NSOpenGLPFADepthSize, DEPTH_SIZE,

//Anti-Aliasing:

NSOpenGLPFASampleBuffers, 8,

NSOpenGLPFASamples, 32,

NSOpenGLPFAMultisample,

0

};

//Set pixel format to include the attributes specified in the array attr[]

nsglFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];

//Use the pixel format for the openGL view

[self setPixelFormat:nsglFormat];


//Initialize the view

[self initGL];

//Redraw view when window changes size

[self setPostsFrameChangedNotifications: YES];

//Update every 60 times a second

renderTimer = [NSTimer timerWithTimeInterval:1.0/60.0

target:self

selector:@selector(timerFired:)

userInfo:nil

repeats:YES];

//Activate timer to fire

[[NSRunLoop currentRunLoop] addTimer:renderTimer

forMode:NSDefaultRunLoopMode];

//Ensure timer fires during resize

[[NSRunLoop currentRunLoop] addTimer:renderTimer

forMode:NSEventTrackingRunLoopMode];

}


//Action to run when the timer is fired

- (void)timerFired:(id)sender

{

//Increase the rotation angle

rotTri += 1.0f;


//Tell the screen it needs to refresh

[self setNeedsDisplay:YES];

}


//Setup OpenGL view

- (void)initGL

{

printf("initGL\n");

// Synchronize buffer swaps with vertical refresh rate

GLint swapInt = 1;

[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];


//Apply Future Operations to The Projection Matrix

glMatrixMode(GL_PROJECTION);

//Reset The Projection Matrix

glLoadIdentity();

// Calculate The Aspect Ratio Of The Window

gluPerspective(45.0f,640.0f/480.0f,0.1f,100.0f);

//Select The Modelview Matrix

glMatrixMode(GL_MODELVIEW);

// Reset The Modelview Matrix

glLoadIdentity();

glShadeModel(GL_SMOOTH); //Smooth Shading

glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //set clear color to black

glClearDepth(1.0f); // Depth Buffer Setup

glEnable(GL_DEPTH_TEST); // Enables Depth Testing

glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do

glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations

}


//Function to draw a pyramid

static void drawAnObject()

{

//Draw a 3-sided pyramid

glBegin(GL_TRIANGLES);

//DAC (counterclockwise points)

glColor3f(1.0f, 0.0f,0.0f); //RED

glVertex3f(1.0f, -1.0f,-0.798f); //D

glColor3f(0.0f, 1.0f,0.0f); //GREEN

glVertex3f(0.0f, -0.333f,0.798f); //A

glColor3f(0.0f, 0.0f,1.0f); //BLUE

glVertex3f(-1.0f, -1.0f,-0.798f); //C

//DCB

glColor3f(1.0f, 0.0f,0.0f); //RED

glVertex3f(1.0f, -1.0f,-0.798f); //D

glColor3f(0.0f, 0.0f,1.0f); //BLUE

glVertex3f(-1.0f, -1.0f,-0.798f); //C

glColor3f(1.0f, 0.0f,1.0f); //Violet

glVertex3f(0.0f,1.0f,-0.798f); //B

//CAB

glColor3f(0.0f, 0.0f,1.0f); //BLUE

glVertex3f(-1.0f, -1.0f,-0.798f); //C

glColor3f(0.0f, 1.0f,0.0f); //GREEN

glVertex3f(0.0f, -0.333f,0.798f); //A

glColor3f(1.0f, 0.0f,1.0f); //Violet

glVertex3f(0.0f,1.0f,-0.798f); //B

//BAD

glColor3f(1.0f, 0.0f,1.0f); //Violet

glVertex3f(0.0f,1.0f,-0.798f); //B

glColor3f(0.0f, 1.0f,0.0f); //GREEN

glVertex3f(0.0f, -0.333f,0.798f); //A

glColor3f(1.0f, 0.0f,0.0f); //RED

glVertex3f(1.0f, -1.0f,-0.798f); //D

glEnd();


}


//Draw Loop

- (void) drawRect: (NSRect) bounds

{

//Clear the screen and depth buffer

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

//Reset the current modelview matrix

glLoadIdentity();


//Move along the x and z axis

glTranslatef( -1.0f, 0.0f, -5.0f );

//rotate the modelview matrix by an angle of rotTri around the vector <1,>

glRotatef( rotTri,1.0f, 1.0f, 1.0f );

//Draw a pyramid to the buffers

drawAnObject();

//Reset Modelview

glLoadIdentity();

glTranslatef( 1.2f, 0.5f, -5.0f );

glRotatef( -5.0f*rotTri,0.0f, 1.0f, 0.0f );

drawAnObject();

//Display the buffer content to the screen

[ [ self openGLContext ] flushBuffer ];

}

Sunday, November 29, 2009

First Steps into 3D

Making a rotating 3d mesh proved much more difficult than I had expected. While I was able to make and display a shape, it took me a long time to figure out how to enable depth sorting so that polygons would be drawn in the correct order. Then, I needed to enable perspective mode in order to give the illusion of moving the camera. Just for fun, I looked up how to enable anti-aliasing for smoother edges. Enjoy!


video

I made the pyramids in Blender 3D and looked at the local point coordinates in order to bring them into OpenGL.:

//Draw a 3-sided pyramid

glBegin(GL_TRIANGLES);

//DAC (points must be listed in counterclockwise order)

glColor3f(1.0f, 0.0f,0.0f); //RED

glVertex3f(1.0f, -1.0f,-0.798f); //D

glColor3f(0.0f, 1.0f,0.0f); //GREEN

glVertex3f(0.0f, -0.333f,0.798f); //A

glColor3f(0.0f, 0.0f,1.0f); //BLUE

glVertex3f(-1.0f, -1.0f,-0.798f); //C

//DCB

glColor3f(1.0f, 0.0f,0.0f); //RED

glVertex3f(1.0f, -1.0f,-0.798f); //D

glColor3f(0.0f, 0.0f,1.0f); //BLUE

glVertex3f(-1.0f, -1.0f,-0.798f); //C

glColor3f(1.0f, 0.0f,1.0f); //Violet

glVertex3f(0.0f,1.0f,-0.798f); //B

//CAB

glColor3f(0.0f, 0.0f,1.0f); //BLUE

glVertex3f(-1.0f, -1.0f,-0.798f); //C

glColor3f(0.0f, 1.0f,0.0f); //GREEN

glVertex3f(0.0f, -0.333f,0.798f); //A

glColor3f(1.0f, 0.0f,1.0f); //Violet

glVertex3f(0.0f,1.0f,-0.798f); //B

//BAD

glColor3f(1.0f, 0.0f,1.0f); //Violet

glVertex3f(0.0f,1.0f,-0.798f); //B

glColor3f(0.0f, 1.0f,0.0f); //GREEN

glVertex3f(0.0f, -0.333f,0.798f); //A

glColor3f(1.0f, 0.0f,0.0f); //RED

glVertex3f(1.0f, -1.0f,-0.798f); //D

glEnd();


Next week, I plan to look through the code I hacked together in order to truly understand how it works. I will post an explanation so that anyone getting started with OpenGL and Cocoa will not have the same problems I did.

Beginning OpenGL

It has been a long time since my last update, but I have finally found the time to start learning OpenGL. There seems to be very few online tutorials directed at Objective-C specifically, so I have had to cobble together information from many different sources. However, I have now managed to create a very simple application that draws an OpenGL scene and updates it 60 times a second. Behold the rotating triangle:

video

Using this framework, I can now use general OpenGL tutorials. Soon, I hope to post experiments with more complicated meshes.

Saturday, April 18, 2009

CINGO! Version 1.0 is in the App Store!

Hurrah! CINGO! was released on the App Store this morning. Sadly, it does not show up in the App Store under new releases since its "release date" is April 3, but it can still be found by searching for "cingo."


Visit http://cingothegame.blogspot.com/ for an iTunes link to the application and to post any questions and problems/bugs.

Friday, April 10, 2009

Post Immersion Update sqrt(9)

Guess what I found in my inbox today when I checked my email:
"Dear True Star Design,

At this time, CINGO! cannot be posted to the App Store because it is crashing on iPhone OS 2.2.1 and Mac OS X 10.5.6.

Steps to Reproduce:

1. Launch App
2. Press "Change Game Lock" and the app crashes

In order for your application to be reconsidered for the App Store, please resolve this issue and upload your new binary to iTunes Connect."
As you can see, my application was rejected from the App Store. When I tested my application, I found nothing wrong with it. Then, I deleted it from my iPhone Simulator and was able to produce the error instantly. It turns out that the file responsible for displaying the "Change Game Look" button had somehow moved to a sub-directory of my main project folder, and the OS could not locate it. I had not detected this error because the file had been present in an earlier version and was not cleared whenever I simply rebuilt the code for the application. Other than that I now probably have to wait for another week for my application to be approved, no harm done: I uploaded a new binary with the file moved to the correct folder.

Note to Self: Always delete applications and rebuild them before submitting them.


Wednesday, April 8, 2009

Post Immersion Update 0002

As I explained in my previous post, there was a presentation of all of my school's (Miami Valley School, Dayton OH) "Immersion" projects, including my own iPhone Immersion. Some images from the event are shown below:

My gigantic iPhone poster (made in Photoshop Elements). It consists of two stacked trifold boards:

My laptop running the iPhone Simulator and displaying my game's website (cingothegame.blogspot.com):

(Left to Right) Me and Mr. Collias, one of my programming advisors:

Here I am explaining my project to a younger student:

I submitted CINGO! to the App Store on the 3rd of April with the description/support website cingothegame.blogspot.com. I hope that it will become available soon. Its current price is $0.00!

Sunday, March 29, 2009

Post Immersion Update 0001

CINGO! has exited the Pre-Alpha stage, passed Alpha testing, and is now called 'Imp' Beta 0.1 (Each future release will be named after a mythical creature).

Below are some screenshots of the final product for your enjoyment:

The Game Screen (Note that pieces about to be captured are clearly denoted with a red X for the turn duration):

The Change Appearance Screen now has support for the legacy 'Alpha' look from my old version:

New Instructions View (Note the helpful images at the bottom of the screen are much clearer than in the old version):

When I present my project on the 7th of April, I will try to post some images from the event. Today, I used Photoshop Elements to create a 2ft wide iPhone that I then pasted onto two stacked poster boards. I am certain that this will draw enough attention that people will actually come to see what I did; technology-based immersion projects are generally not viewed by many people because the projects have a lack of visual appeal in comparison to those involving pictures of journeys and artistic creations.

Monday, March 23, 2009

Post Immersion Update 0000

Ladies and Gentlemen......

After days of struggling, I have finally added Data Persistence to Cingo. After asking a question on a programming forum called Stack Overflow, I realized that I had to re-engineer my entire application. For the past few days, I spent much of my time recoding Cingo from scratch. Doing so has allowed me to make a much more intuitive interface, to make my code more compact and understandable, and to add data persistence.

I have also begun making a nicer icon-set, have found a way to get rid of the annoying 'Execute Move' button, and have produced a beautiful logo using Blender 3D.

Here is a quick preview of the new main menu:


...and some of the new pieces in the change appearance screen:

Friday, March 13, 2009

Today, I planned to finish data persistence and finalize my application. After many hours of coding and debugging, I was still unable to save and load data effectively. While the data appears fine after loading, my program throws random memory access errors no matter what I do, and locating these errors is practically impossible because they are not reproducible. I also met with Mr.Collias for the last time during this project, but he was unable to help me discover how to fix the errors. He suggested that I should ask questions on programming forums. I will see what I can do on the weekend, but I still have to finish an essay and take the SAT.
My application works very well, it just loses undo functionality when the view is changed and does not save games when terminated.


Quick Update (9:59):
The "Tie" functionality was broken, and I just fixed it.

Thursday, March 12, 2009

iPhone Journal (asc(Q)-63)

I only have one day of my uninterrupted programming experience left. Today, I planned to complete the views of my application and to begin working on saving data. I started out by filling the New Game screen, without which the application would be basically useless. Then, I met several people who fall within the target age group and asked them to test the application. It was very useful to observe their interactions with the menu systems and controls, and I was then able to change the interface to more closely match what people expect. For example, none of my test subjects was able to locate the way to view the instructions without searching for several seconds. Instead of using the arrows on the screen to move on, they clicked on the white section of the screen where the word "Instructions" appears. I thus placed an invisible button on this section and moved all of the arrows away from the toolbar onto the individual instruction pages.
I also caused the change appearance view to function mechanically (it still needs some aesthetic improvements such as a piece and board appearance browser) and started to rearrange my code for ease of saving key variables. In the process, I was able to fix large amounts of memory leaks and managed to discover that the >100 unused variable messages that I had been receiving were due to some variable declarations that were being imported into almost every file in my project. Finally, I began implementing data persistence itself by creating an object meant to house the data for one of the views and to save half of my data to it. The important steps now are to create a new object for storing the rest of my data and to actually save to/load from the hard drive on the iPhone.


(Note the red background squares. These result from a board appearance setting - the only one other than the default so far)

(This message is displayed when New Game is pressed and a game is in progress. Yes, I realized I misspelled "want." I fixed it in the latest Debug Build)

(The switch in this view is for controlling whether the controls are described in the game view once Begin Game is pressed. I noticed that none of my test subjects pressed the help button purposefully. The default setting is ON to make sure people know how to use the controls.)


Quick Update (12:22):

Just wanted to finish this view really quickly. Goodnight!

Wednesday, March 11, 2009

iPhone Journal (asc(R)-65)


Today, I planned to finish the undo functionality, add instructions, and to reduce memory leaks. I was able to accomplish all this and more. I finished the undo button much more rapidly than I had hoped and reduced some of the memory problems at the same time. I then created the instructions view. I soon discovered that the instructions cannot all be displayed on the same page, and so I modified the view controller for the instructions to handle multiple pages. During this process, I discovered a much simpler way to add and remove views than I had been using previously. I also fixed a major error present in the game view in regard to promoting a diamond to a mixed "power" piece.
Finally, I met with Mr. Collias in order to discuss final changes. He taught me methods of assessing the usability of a user interface and then provided several suggestions about my project's interface and about the gameplay element.
I followed almost all of these suggestions with minor adjustments and now have the following images to demonstrate my progress:

(note the red X on the piece surrounded by diamonds and the dot in the center of the X indicating the final destination of the jump.)

Mr. Collias noted that the score display was confusing and that the execute move button was unclear. Also, it was previously difficult to determine what pieces were removed by a CINGO move and what the destination of a given move is. All of these problems have now been addressed. Note that I also added a question mark icon to the game view that, when pressed, discloses information about how to use the controls.
Tomorrow, I will attempt to finish the "Change Appearance" and "New Game..." views and to begin working on saving the state of the application on view switch/exit.

Quick Update (11:32):
Just added a picker with some randomly named components.

iPhone Journal 0x10

Today (3/10/09), I managed to implement 90% of the "Undo" functionality of Cingo and to fix all of yesterday's bugs after hours of troubleshooting. I was, however, unable to work on any of the other views.
The special move for which the game is named took the longest time to add undo functionality to because the data size is variable - it is possible to surround more than one piece in a single slide or jump. I was also able to take the undo button beyond my early expectations such that it may be pressed until the game looks like it did at the very start. The only move that still needs to be able to be undone is upgrading a diamond to a mixed piece. This can be accomplished with a simple BOOL value, and I used a similar method for allowing jumps to be undone, so this should be a relatively painless process.
I still need to work on removing several memory leaks (see the spikes in the image below) that were introduced due to some strange allocation problems. Tomorrow, I will begin by finishing the undo button, fill the instructions view with information, and see if I can figure out how to remove the leaks. The latter is probably not very important at the moment because of the small quantity of leaks, and I may leave this for later.
I will then work on the change appearance view and new game view if time permits. After that, all that will be left is saving on view switch/exit and adding some other ways to win than capturing all opponent pieces. Everything seems to be coming together nicely at the moment.

(Note: the final spike is from killing the process, not from a lack of deallocation on program exit)

I would post more images, but the application has not changed in appearance, just functionality, since yesterday.