// // Perspective view of a color cube using LookAt() and Frustum() // // Colors are assigned to each vertex and then the rasterizer interpolates // those colors across the triangles. // #include #include "Angel.h" #include #include using namespace std; // lizard data structures. vector verticies; vector colors; vector triangles; GLuint lizardVAO, axisVAO; GLuint vPosition, vColor; mat4 LizardTransform; const int AXIS_POINTS = 6; vec4 axis[AXIS_POINTS] = { vec4( -1.0, 0.0, 0.0, 1.0 ), vec4( 1.0, 0.0, 0.0, 1.0 ), vec4( 0.0, -1.0, 0.0, 1.0 ), vec4( 0.0, 1.0, 0.0, 1.0 ), vec4( 0.0, 0.0, -1.0, 1.0 ), vec4( 0.0, 0.0, 1.0, 1.0 ) }; vec4 axisColor[AXIS_POINTS] = { vec4( 0.0, 0.0, 0.0, 1.0 ), vec4( 1.0, 0.0, 0.0, 1.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ), vec4( 0.0, 1.0, 0.0, 1.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ), vec4( 0.0, 0.0, 1.0, 1.0 ), }; // Viewing transformation parameters GLfloat radius = 1.0; GLfloat theta = 0.0; GLfloat phi = 0.0; bool axisOn = true; bool lizardOn = true; const GLfloat dr = 5.0 * DegreesToRadians; GLfloat angelLeft = -1.0, angelRight = 1.0; GLfloat bottom = -1.0, top = 1.0; GLfloat zNear = 0.5, zFar = 3.0; GLuint model_view; GLuint projection; GLuint objectMatrix; void Reset() { angelLeft = -1.0; angelRight = 1.0; bottom = -1.0; top = 1.0; zNear = 0.5; zFar = 3.0; radius = 1.0; theta = 0.0; phi = 0.0; return; } void DoMax(vec3 p, vec3 & m) { if (p.x > m.x) m.x = p.x; if (p.y > m.y) m.y = p.y; if (p.z > m.z) m.z = p.z; }; void DoMin(vec3 p, vec3 & m) { if (p.x < m.x) m.x = p.x; if (p.y < m.y) m.y = p.y; if (p.z < m.z) m.z = p.z; } void LoadLizard(){ vec3 max,min; int points, i; int p1, p2, p3, sides; vec3 point; ifstream inFile; inFile.open("lizard.off"); inFile >> points; for(i=0;i> point.x >> point.y >> point.z; if (i==0) { max = point; min = point; } DoMax(point, max); DoMin(point,min); verticies.push_back(point); colors.push_back(vec4(0.0, 0.0,1.0, 1.0)); } inFile >> sides; while(inFile) { if (sides != 3) { // really should step through and triangalize the sides. // (a b c) (a d d) (a d e) ... cout << "Bad side list "; cout << "There are " << sides << " sides, not 3"; cout << endl; inFile.ignore(100,'\n'); } else { inFile >> p1 >> p2 >> p3; triangles.push_back(p1); triangles.push_back(p2); triangles.push_back(p3); } inFile >> sides; } inFile.close(); cout << "Points: " << verticies.size() << endl; cout << "Triangles: " << triangles.size() << endl; vec3 t1; float sa; t1 = max-min; sa = t1.x; if (t1.y > sa) { sa = t1.y; } if (t1.z > sa) { sa = t1.z; } LizardTransform = Scale(1.0/sa,1.0/sa,1.0/sa)* Translate(-min); return; } void init() { Reset(); LoadLizard(); // Load shaders and use the resulting shader program GLuint program = InitShader( "vshader42.glsl", "fshader42.glsl" ); glUseProgram( program ); // Create a vertex array object glGenVertexArrays( 1, &lizardVAO ); glBindVertexArray( lizardVAO ); GLuint lizardBuffer[3]; glGenBuffers( 3, lizardBuffer ); glBindBuffer(GL_ARRAY_BUFFER, lizardBuffer[0] ); glBufferData(GL_ARRAY_BUFFER, verticies.size()*sizeof(vec3), verticies.data(), GL_STATIC_DRAW); vPosition = glGetAttribLocation( program, "vPosition"); glEnableVertexAttribArray(vPosition); glVertexAttribPointer(vPosition, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lizardBuffer[1]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, triangles.size()*sizeof(int), triangles.data(), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, lizardBuffer[2] ); glBufferData(GL_ARRAY_BUFFER, colors.size()*sizeof(vec4), colors.data(), GL_STATIC_DRAW); vColor = glGetAttribLocation( program, "vColor"); glEnableVertexAttribArray(vColor); glVertexAttribPointer(vColor, 4, GL_FLOAT, GL_FALSE, 0, 0); glBindVertexArray(0); // now set up the axis glGenVertexArrays( 1, &axisVAO ); glBindVertexArray( axisVAO ); GLuint axisBuffer[2]; glGenBuffers( 2, axisBuffer ); glBindBuffer( GL_ARRAY_BUFFER, axisBuffer[0] ); glBufferData( GL_ARRAY_BUFFER, sizeof(axis), axis, GL_STATIC_DRAW ); glEnableVertexAttribArray( vPosition ); glVertexAttribPointer(vPosition,4,GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); glBindBuffer( GL_ARRAY_BUFFER, axisBuffer[1] ); glBufferData( GL_ARRAY_BUFFER,sizeof(axisColor),axisColor,GL_STATIC_DRAW ); glEnableVertexAttribArray( vColor ); glVertexAttribPointer(vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); model_view = glGetUniformLocation( program, "model_view" ); projection = glGetUniformLocation( program, "projection" ); objectMatrix = glGetUniformLocation( program,"object"); glEnable( GL_DEPTH_TEST ); glClearColor( 1.0, 1.0, 1.0, 1.0 ); } //---------------------------------------------------------------------------- void display( void ) { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); cout << "Camera Position : "; cout << radius*sin(theta)*cos(phi) << ", "; cout << radius*sin(theta)*sin(phi) << ", "; cout << radius*cos(theta) << endl; vec4 eye( radius*sin(theta)*cos(phi), radius*sin(theta)*sin(phi), radius*cos(theta), 1.0 ); vec4 at( 0.0, 0.0, 0.0, 1.0 ); vec4 up( 0.0, 1.0, 0.0, 0.0 ); mat4 mv = LookAt( eye, at, up ); glUniformMatrix4fv( model_view, 1, GL_TRUE, mv ); mat4 p = Frustum( angelLeft, angelRight, bottom, top, zNear, zFar ); glUniformMatrix4fv( projection, 1, GL_TRUE, p ); cout << "************************************" << endl; cout << "The eye is at " << eye << endl; cout << "Left = " << angelLeft << endl; cout << "Right = " << angelRight << endl; cout << "Bottom = " << top << endl; cout << "Top = " << bottom << endl; cout << "Near = " << zNear << endl; cout << "Far = " << zFar << endl; cout << "************************************" << endl; cout << endl; if (lizardOn) { glBindVertexArray( lizardVAO ); glUniformMatrix4fv( objectMatrix, 1, GL_TRUE, LizardTransform); glDrawElements(GL_TRIANGLES, triangles.size(), GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); glBindVertexArray(0); } if (axisOn) { mat4 object; glUniformMatrix4fv( objectMatrix, 1, GL_TRUE, object ); glBindVertexArray( axisVAO ); glDrawArrays( GL_LINES, 0, AXIS_POINTS ); glBindVertexArray(0); } glutSwapBuffers(); return; } void keyboard( unsigned char key, int x, int y ) { switch( key ) { case 'a': axisOn = !axisOn; break; case 'l': lizardOn = !lizardOn; break; case 'q': case 'Q': exit( EXIT_SUCCESS ); break; case 'x': angelLeft *= 1.1; angelRight *= 1.1; break; case 'X': angelLeft *= 0.9; angelRight *= 0.9; break; case 'y': bottom *= 1.1; top *= 1.1; break; case 'Y': bottom *= 0.9; top *= 0.9; break; case 'z': zNear *= 1.1; zFar *= 1.1; break; case 'Z': zNear *= 0.9; zFar *= 0.9; break; case 'r': radius *= 2.0; break; case 'R': radius *= 0.5; break; case 'o': theta += dr; break; case 'O': theta -= dr; break; case 'p': phi += dr; break; case 'P': phi -= dr; break; case ' ': // reset values to their defaults Reset(); break; } glutPostRedisplay(); } void reshape( int width, int height ) { glViewport( 0, 0, width, height ); } int main( int argc, char **argv ) { glutInit( &argc, argv ); glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH ); glutInitWindowSize( 512, 512 ); glutCreateWindow( "Triangle Lizard" ); GLenum err = glewInit(); if (GLEW_OK != err) { cout << "glewInit failed, aborting." << endl; exit (1); } init(); glutDisplayFunc( display ); glutKeyboardFunc( keyboard ); glutReshapeFunc( reshape ); glutMainLoop(); return 0; }