mrkd
5/5/2012 - 9:31 PM

SEIS 750 Final Project - OutForADrive - iOS

SEIS 750 Final Project - OutForADrive - iOS

attribute vec4 Position; // 1
attribute vec4 SourceColor; // 2

varying vec4 DestinationColor; // 3

uniform mat4 Projection;
uniform mat4 Modelview;



void main(void) { // 4
    
    DestinationColor = SourceColor; // 5
    gl_Position = Projection * Modelview * Position;
}
varying lowp vec4 DestinationColor; // 1

void main(void) { // 2
    gl_FragColor = DestinationColor; // 3
}
//
//  OpenGLView.m
//  HelloOpenGL
//
//  Created by Ray Wenderlich on 5/24/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "OpenGLView.h"
#import "CC3GLMatrix.h"
#import "glUtil.h"

#define glBindVertexArray glBindVertexArrayOES
#define glGenVertexArrays glGenVertexArraysOES
#define glDeleteVertexArrays glDeleteVertexArraysOES

#define GetGLError()									\
{														\
GLenum err = glGetError();							\
while (err != GL_NO_ERROR) {						\
NSLog(@"GLError %s set in File:%s Line:%d\n",	\
GetGLErrorString(err),					\
__FILE__,								\
__LINE__);								\
err = glGetError();								\
}													\
}

@implementation OpenGLView

enum VAO_OBJECTS
{
CUBE,
CUBE2,
CAR,
HEADLIGHT,
POLICE_LIGHT,
POLICE_LIGHT2,
WHEEL,
TIRETREAD,
HUBCAP,
HEAD,
EYE,
STAGE,
NUMBER_OF_VAO_OBJECTS
};

enum VBO_OBJECTS
{
CUBE_VERTS,
CUBE_COLORS, //NOTE: THIS ORDER HAS TO STAY THE SAME FOR NOW VERTS - COLORS
CUBE_NORMALS,
CUBE_MATERIAL_AMBIENT,
CUBE_MATERIAL_DIFFUSE,
CUBE_SPECULAR,
CUBE_SHININESS,
CAR_VERTS,
CAR_COLORS,
CAR_NORMALS,
CAR_MATERIAL_AMBIENT,
CAR_MATERIAL_DIFFUSE,
CAR_SPECULAR,
CAR_SHININESS,
HEADLIGHT_VERTS,
HEADLIGHT_COLORS,
HEADLIGHT_NORMALS,
POLICE_LIGHT_VERTS,
POLICE_LIGHT_COLORS,
POLICE_LIGHT_NORMALS,
POLICE_LIGHT_VERTS2,
POLICE_LIGHT_COLORS2,
POLICE_LIGHT_NORMALS2,
WHEEL_VERTS,
WHEEL_COLORS,
WHEEL_NORMALS,
TIRETREAD_VERTS,
TIRETREAD_COLORS,
TIRETREAD_NORMALS,
HUBCAP_VERTS,
HUBCAP_COLORS,
HUBCAP_NORMALS,
HEAD_VERTS,
HEAD_COLORS,
HEAD_NORMALS,
EYE_VERTS,
EYE_COLORS,
EYE_NORMALS,
STAGE_VERTS,
STAGE_COLORS,
STAGE_NORMALS,
STAGE_MATERIAL_AMBIENT,
STAGE_MATERIAL_DIFFUSE,
STAGE_SPECULAR,
STAGE_SHININESS,
NUMBER_OF_VBO_OBJECTS
};

// LIGHTING
#define SHADER_ATTRIBS_PER_OBJECT 3

//shader program
GLuint programHandle;


GLuint model_view;
GLuint projection;
GLuint NormalMatrix;
GLuint vPosition;
GLuint vColor;

GLuint vAmbientDiffuseColor;
GLuint vSpecularColor;
GLuint vSpecularExponent;
GLuint vNormal;
GLuint vAmbient;
GLuint vDiffuse;
GLuint vSpecular;
GLuint ambient_light;
GLuint scene_light_color;

//need some arrays to store cube attributes
GLuint vao[NUMBER_OF_VAO_OBJECTS];
GLuint vbo[NUMBER_OF_VBO_OBJECTS];


/** CUBE OBJECT **/
CC3Vector4 cubeVerts[36];
CC3Vector4 cubeColors[36];
CC3Vector cubeNormals[36];
- (void) generateCube {
    GetGLError();
	for(int i=0; i<6; i++){
		cubeColors[i] = CC3Vector4Make(0.0, 1.0, 1.0, 1.0); //front
		cubeNormals[i] = CC3VectorMake(0.0,0.0,1.0);
	}
    GetGLError();
	cubeVerts[0] = CC3Vector4Make(1.0f, -1.0f, 1.0f, 1.0);
	cubeVerts[1] = CC3Vector4Make(1.0f, 1.0f, 1.0f, 1.0);
	cubeVerts[2] = CC3Vector4Make(-1.0f, 1.0f, 1.0f, 1.0);
	cubeVerts[3] = CC3Vector4Make(-1.0f, 1.0f, 1.0f, 1.0);
	cubeVerts[4] = CC3Vector4Make(-1.0f, -1.0f, 1.0f, 1.0);
	cubeVerts[5] = CC3Vector4Make(1.0f, -1.0f, 1.0f, 1.0);
    GetGLError();
    
	for(int i=6; i<12; i++){
		cubeColors[i] = CC3Vector4Make(1.0, 0.0, 1.0, 1.0); //back
		cubeNormals[i] = CC3VectorMake(0.0,0.0,-1.0);
	}
    GetGLError();
	cubeVerts[6] = CC3Vector4Make(-1.0f, -1.0f, -1.0f, 1.0);
	cubeVerts[7] = CC3Vector4Make(-1.0f, 1.0f, -1.0f, 1.0);
	cubeVerts[8] = CC3Vector4Make(1.0f, 1.0f, -1.0f, 1.0);
	cubeVerts[9] = CC3Vector4Make(1.0f, 1.0f, -1.0f, 1.0);
	cubeVerts[10] = CC3Vector4Make(1.0f, -1.0f, -1.0f, 1.0);
	cubeVerts[11] = CC3Vector4Make(-1.0f, -1.0f, -1.0f, 1.0);
    
	for(int i=12; i<18; i++){
		cubeColors[i] = CC3Vector4Make(1.0, 1.0, 0.0, 1.0); //left
		cubeNormals[i] = CC3VectorMake(1.0,0.0,0.0);
	}
	cubeVerts[12] = CC3Vector4Make(1.0f, 1.0f, 1.0f, 1.0);
	cubeVerts[13] = CC3Vector4Make(1.0f, -1.0f, 1.0f, 1.0);
	cubeVerts[14] = CC3Vector4Make(1.0f, -1.0f, -1.0f, 1.0);
	cubeVerts[15] = CC3Vector4Make(1.0f, -1.0f, -1.0f, 1.0);
	cubeVerts[16] = CC3Vector4Make(1.0f, 1.0f, -1.0f, 1.0);
	cubeVerts[17] = CC3Vector4Make(1.0f, 1.0f, 1.0f, 1.0);
    
	for(int i=18; i<24; i++){
		cubeColors[i] = CC3Vector4Make(1.0, 0.0, 0.0, 1.0); //right
		cubeNormals[i] = CC3VectorMake(-1.0,0.0,0.0);
	}
	cubeVerts[18] = CC3Vector4Make(-1.0f, 1.0f, -1.0f, 1.0);
	cubeVerts[19] = CC3Vector4Make(-1.0f, -1.0f, -1.0f, 1.0);
	cubeVerts[20] = CC3Vector4Make(-1.0f, -1.0f, 1.0f, 1.0);
	cubeVerts[21] = CC3Vector4Make(-1.0f, -1.0f, 1.0f, 1.0);
	cubeVerts[22] = CC3Vector4Make(-1.0f, 1.0f, 1.0f, 1.0);
	cubeVerts[23] = CC3Vector4Make(-1.0f, 1.0f, -1.0f, 1.0);
    
	for(int i=24; i<30; i++){
		cubeColors[i] = CC3Vector4Make(0.0, 0.0, 1.0, 1.0); //top
		cubeNormals[i] = CC3VectorMake(0.0,1.0,0.0);
	}
	cubeVerts[24] = CC3Vector4Make(1.0f, 1.0f, 1.0f, 1.0);
	cubeVerts[25] = CC3Vector4Make(1.0f, 1.0f, -1.0f, 1.0);
	cubeVerts[26] = CC3Vector4Make(-1.0f, 1.0f, -1.0f, 1.0);
	cubeVerts[27] = CC3Vector4Make(-1.0f, 1.0f, -1.0f, 1.0);
	cubeVerts[28] = CC3Vector4Make(-1.0f, 1.0f, 1.0f, 1.0);
	cubeVerts[29] = CC3Vector4Make(1.0f, 1.0f, 1.0f, 1.0);
    
	for(int i=30; i<36; i++){
		cubeColors[i] = CC3Vector4Make(0.0, 1.0, 0.0, 1.0); //bottom
		cubeNormals[i] =CC3VectorMake(0.0,-1.0,0.0);
	}
	cubeVerts[30] = CC3Vector4Make(1.0f, -1.0f, -1.0f, 1.0);
	cubeVerts[31] = CC3Vector4Make(1.0f, -1.0f, 1.0f, 1.0);
	cubeVerts[32] = CC3Vector4Make(-1.0f, -1.0f, 1.0f, 1.0);
	cubeVerts[33] = CC3Vector4Make(-1.0f, -1.0f, 1.0f, 1.0);
	cubeVerts[34] = CC3Vector4Make(-1.0f, -1.0f, -1.0f, 1.0);
	cubeVerts[35] = CC3Vector4Make(1.0f, -1.0f, -1.0f, 1.0);
}

+ (Class)layerClass {
    return [CAEAGLLayer class];
}

- (void)setupLayer {
    _eaglLayer = (CAEAGLLayer*) self.layer;
    _eaglLayer.opaque = YES;
}

- (void)setupContext {   
    EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES2;
    _context = [[EAGLContext alloc] initWithAPI:api];
    if (!_context) {
        NSLog(@"Failed to initialize OpenGLES 2.0 context");
        exit(1);
    }
    
    if (![EAGLContext setCurrentContext:_context]) {
        NSLog(@"Failed to set current OpenGL context");
        exit(1);
    }
}

- (void)setupRenderBuffer {
    glGenRenderbuffers(1, &_colorRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);        
    [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];    
}

- (void)setupDepthBuffer {
    glGenRenderbuffers(1, &_depthRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, self.frame.size.width, self.frame.size.height);    
}

- (void)setupFrameBuffer {    
    GLuint framebuffer;
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);   
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBuffer);
}

- (GLuint)compileShader:(NSString*)shaderName withType:(GLenum)shaderType {
    
    // 1
    NSString* shaderPath = [[NSBundle mainBundle] pathForResource:shaderName ofType:@"glsl"];
    NSError* error;
    NSString* shaderString = [NSString stringWithContentsOfFile:shaderPath encoding:NSUTF8StringEncoding error:&error];
    if (!shaderString) {
        NSLog(@"Error loading shader: %@", error.localizedDescription);
        exit(1);
    }
    
    // 2
    GLuint shaderHandle = glCreateShader(shaderType);    
    
    // 3
    const char * shaderStringUTF8 = [shaderString UTF8String];    
    int shaderStringLength = [shaderString length];
    glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength);
    
    // 4
    glCompileShader(shaderHandle);
    
    // 5
    GLint compileSuccess;
    glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
    if (compileSuccess == GL_FALSE) {
        GLchar messages[256];
        glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"%@", messageString);
        exit(1);
    }
    
    return shaderHandle;
    
}

- (void)compileShaders {
    NSLog(@"comileShaders");
    GetGLError();
    // 1
    GLuint vertexShader = [self compileShader:@"SimpleVertex" withType:GL_VERTEX_SHADER];
    GLuint fragmentShader = [self compileShader:@"SimpleFragment" withType:GL_FRAGMENT_SHADER];
    GetGLError();
    // 2
    programHandle = glCreateProgram();
    glAttachShader(programHandle, vertexShader);
    glAttachShader(programHandle, fragmentShader);
    glLinkProgram(programHandle);
    GetGLError();
    // 3
    GLint linkSuccess;
    glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
    if (linkSuccess == GL_FALSE) {
        GLchar messages[256];
        glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"%@", messageString);
        exit(1);
    }
    glUseProgram(programHandle);

}

- (void)setupVBOs {
    
    NSLog(@"sizeOf cubeVerts: %lu", sizeof(cubeVerts));
    
    // Create a vertex array object
    glGenVertexArrays( 1, &vao[0] );
    glBindVertexArray( vao[CUBE] );
	// CUBE
	// Create and initialize any buffer objects
    GetGLError();
	glGenBuffers( 3, &vbo[CUBE_VERTS] );
	glBindBuffer( GL_ARRAY_BUFFER, vbo[CUBE_VERTS] );
	glBufferData( GL_ARRAY_BUFFER, sizeof(cubeVerts), cubeVerts, GL_STATIC_DRAW);
    _positionSlot = glGetAttribLocation(programHandle, "Position");
    glEnableVertexAttribArray(_positionSlot);
    glVertexAttribPointer(_positionSlot, 4, GL_FLOAT, GL_FALSE, 0, 0);

    GetGLError();
    //and now our colors for each vertex
	glBindBuffer( GL_ARRAY_BUFFER, vbo[CUBE_COLORS] );
	glBufferData( GL_ARRAY_BUFFER, sizeof(cubeColors), cubeColors, GL_STATIC_DRAW );
    _colorSlot = glGetAttribLocation(programHandle, "SourceColor");
    GetGLError();
    glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, 0, 0);
    GetGLError();
    glEnableVertexAttribArray(_colorSlot);

    GetGLError();
	//vertex normals
	glBindBuffer( GL_ARRAY_BUFFER, vbo[CUBE_NORMALS] );
	glBufferData( GL_ARRAY_BUFFER, sizeof(cubeNormals), cubeNormals, GL_STATIC_DRAW );

    GetGLError();
}

- (void)render:(CADisplayLink*)displayLink {
    
    
    glClearColor(1, 1, 1, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    GetGLError();
    
    CC3GLMatrix *projection = [CC3GLMatrix matrix];
    [projection populateFromFrustumLeft:-5 andRight:5 andBottom:-5 andTop:5 andNear:1 andFar:50];
    glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);
    GetGLError();
    
    CC3GLMatrix *modelView = [CC3GLMatrix matrix];

    [modelView populateFromTranslation:CC3VectorMake(sin(CACurrentMediaTime()), 0, -7)];
    _currentRotation += displayLink.duration * 90;
    [modelView rotateBy:CC3VectorMake(_currentRotation, _currentRotation, 0)];
    glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);
    GetGLError();
	
    GetGLError();
	glBindVertexArray( vao[CUBE] );
	glDrawArrays( GL_TRIANGLES, 0, 36 );    // draw the cube
    GetGLError();
    
    
    [_context presentRenderbuffer:GL_RENDERBUFFER];
    GetGLError();
}

- (void)setupDisplayLink {
    CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render:)];
    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];    
}

- (void) setupShader
{
    glUseProgram(programHandle);
    _projectionUniform = glGetUniformLocation(programHandle, "Projection");
    _modelViewUniform = glGetUniformLocation(programHandle, "Modelview");
    
    
	glBindVertexArray( vao[CUBE] );
    GetGLError();
	glBindBuffer( GL_ARRAY_BUFFER, vbo[CUBE_VERTS] );
	_positionSlot = glGetAttribLocation(programHandle, "Position");
    glEnableVertexAttribArray(_positionSlot);
    glVertexAttribPointer(_positionSlot, 4, GL_FLOAT, GL_FALSE, 0, 0);
    
    NSLog(@"max: %d", GL_MAX_VERTEX_ATTRIBS);
    GetGLError();
    glBindBuffer( GL_ARRAY_BUFFER, vbo[CUBE_COLORS] );
	_colorSlot = glGetAttribLocation(programHandle, "SourceColor");
    GetGLError();
    glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, 0, 0);
    GetGLError();
    glEnableVertexAttribArray(_colorSlot);
    GetGLError();
    
    NSLog(@"\nLocations of the shader variables:\n Position:%i\n Color:%i\n", _positionSlot, _colorSlot); //Prints out the values of 1, 0, 0

}

- (void) initOpenGL
{
    [self generateCube];
     NSLog(@"generateCube complete");
    
    // init shader
    [self compileShaders];
    NSLog(@"compileShaders complete");
    GetGLError();
    
    /*
    // create and initialize several buffer objects
    glGenVertexArrays( NUMBER_OF_VAO_OBJECTS, &vao[0] );
	glBindVertexArray( vao[CUBE] );
    GetGLError();
	glGenBuffers( 3, &vbo[CUBE_VERTS] );
	glBindBuffer( GL_ARRAY_BUFFER, vbo[CUBE_VERTS] );
	glBufferData( GL_ARRAY_BUFFER, sizeof(cubeVerts), cubeVerts, GL_STATIC_DRAW);
    
    GetGLError();
    //and now our colors for each vertex
	glBindBuffer( GL_ARRAY_BUFFER, vbo[CUBE_COLORS] );
	glBufferData( GL_ARRAY_BUFFER, sizeof(cubeColors), cubeColors, GL_STATIC_DRAW );

    GetGLError();
	//vertex normals
	glBindBuffer( GL_ARRAY_BUFFER, vbo[CUBE_NORMALS] );
	glBufferData( GL_ARRAY_BUFFER, sizeof(cubeNormals), cubeNormals, GL_STATIC_DRAW );
     */
    GetGLError();
}


/* main starting point */
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {        
        [self setupLayer];        
        [self setupContext];    
        [self setupDepthBuffer];
        [self setupRenderBuffer];        
        [self setupFrameBuffer];     
        
        //comiles shaders
        [self initOpenGL];
        
        GetGLError();
        [self setupVBOs];
        NSLog(@"setupVBOs complete");

        //setup shader
        [self setupShader];
        GetGLError();
        
        [self setupDisplayLink];      
        NSLog(@"setupDisplayLink complete");
        
        GetGLError();
    }
    return self;
}

- (void)dealloc
{
    [_context release];
    _context = nil;
    [super dealloc];
}

@end