Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //-----------------------------------------------------------------------------
- // Shogun3D's OpenGL Utility Toolkit framework.
- //
- // Disclamer: Use this code as you see fit, for both personal and/or commercial
- // usages. You don't exactly have to give me credit for using this
- // code in your own projects (although I would appreciate it if you
- // did), but you could at let me know that this has benefited you
- // in one way or another, because I didn't write this code just for
- // myself you know ^^
- //
- // File: main.c
- // Desc: This code will hopefully show you how easy it is to create a 3rd
- // person game :)
- // Date: August 20, 2010
- //-----------------------------------------------------------------------------
- // Include files
- #ifdef WIN32 // For windows builds
- #include <windows.h>
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <gl\glut.h>
- #include <gl\glext.h>
- //-----------------------------------------------------------------------------
- // 3D vector
- //-----------------------------------------------------------------------------
- struct Vector3
- {
- float x, y, z;
- };
- //-----------------------------------------------------------------------------
- // Third Person Camera structure
- //-----------------------------------------------------------------------------
- struct ThirdPersonCamera_t
- {
- struct Vector3 vecPos;
- struct Vector3 vecRot;
- float fRadius; // Distance between the camera and the object.
- float fLastX;
- float fLastY;
- };
- //-----------------------------------------------------------------------------
- // Sphere structure
- //-----------------------------------------------------------------------------
- struct Sphere_t
- {
- struct Vector3 position; // Position in 3D space
- int selected; // Did OpenGL select this one?
- int dead; // Is this sphere dead?
- unsigned int death_time; // How long has this sphere been dead?
- // Respawn after X milliseconds
- float distance; // Distance between you and the sphere.
- float size; // The size of the sphere. Decreases during
- // death phase.
- };
- //-----------------------------------------------------------------------------
- // Global variables
- //-----------------------------------------------------------------------------
- #define sphere_count 20 // Number of spheres in the game
- #define respawn_time 5000 // After a sphere is shot dead, respawn after this
- // amount of time.
- struct ThirdPersonCamera_t camera;
- struct Sphere_t spheres[sphere_count];
- GLuint floor_tex = 0;
- GLuint select_buffer[sphere_count*4] = {0};
- GLint hits = 0;
- float jump_height = 0.0f;
- GLboolean sniper_mode = GL_FALSE;
- GLint kills = 0;
- //-----------------------------------------------------------------------------
- // Name: glEnable2D
- // Desc: Enabled 2D primitive rendering by setting up the appropriate orthographic
- // perspectives and matrices.
- //-----------------------------------------------------------------------------
- void glEnable2D( void )
- {
- GLint iViewport[4];
- // Get a copy of the viewport
- glGetIntegerv( GL_VIEWPORT, iViewport );
- // Save a copy of the projection matrix so that we can restore it
- // when it's time to do 3D rendering again.
- glMatrixMode( GL_PROJECTION );
- glPushMatrix();
- glLoadIdentity();
- // Set up the orthographic projection
- glOrtho( iViewport[0], iViewport[0]+iViewport[2],
- iViewport[1]+iViewport[3], iViewport[1], -1, 1 );
- glMatrixMode( GL_MODELVIEW );
- glPushMatrix();
- glLoadIdentity();
- // Make sure depth testing and lighting are disabled for 2D rendering until
- // we are finished rendering in 2D
- glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT );
- glDisable( GL_DEPTH_TEST );
- glDisable( GL_LIGHTING );
- }
- //-----------------------------------------------------------------------------
- // Name: glDisable2D
- // Desc: Disables 2D rendering and restores the previous matrix and render states
- // before they were modified.
- //-----------------------------------------------------------------------------
- void glDisable2D( void )
- {
- glPopAttrib();
- glMatrixMode( GL_PROJECTION );
- glPopMatrix();
- glMatrixMode( GL_MODELVIEW );
- glPopMatrix();
- }
- //-----------------------------------------------------------------------------
- // Name: glPrintf
- // Desc: Prints a string of chars using GLUT's pre-defined char blitting API.
- //-----------------------------------------------------------------------------
- void glPrintf( int x, int y, void* font, char* string, ... )
- {
- char *c;
- char temp[256];
- va_list ap;
- va_start( ap, string );
- vsprintf( temp, string, ap );
- va_end( ap );
- glEnable2D();
- glRasterPos2i(x,y);
- for (c=temp; *c != '\0'; c++)
- {
- glutBitmapCharacter(font, *c);
- }
- glDisable2D();
- }
- //-----------------------------------------------------------------------------
- // Name: distance
- // Desc: Calculates the distance between two points.
- //-----------------------------------------------------------------------------
- float distance( const struct Vector3* v1, const struct Vector3* v2 )
- {
- float d = 0.0f;
- float x = v2->x - v1->x;
- float y = v2->y - v1->y;
- float z = v2->z - v1->z;
- x *= x;
- y *= y;
- z *= z;
- d = sqrt(x+y+z);
- return d;
- }
- //-----------------------------------------------------------------------------
- // Name: calculate_distances
- // Desc: Calulates the distance between each sphere and the camera.
- //-----------------------------------------------------------------------------
- void calculate_distances( void )
- {
- int i;
- struct Vector3 neg_camera;
- // In order to accurately calculate the distance between the spheres and
- // the camera, the x and z values should be converted to negatives, and
- // the y coordinate should be ignored. The camera updates the y value
- // still, but in a 3rd person shooter/adventure style game, the is calc-
- // lations are done seperately from the camera to compensate for jumping
- // and gravity, etc.
- neg_camera.x = camera.vecPos.x * -1.0f;
- neg_camera.y = 0.0f;
- neg_camera.z = camera.vecPos.z * -1.0f;
- for( i = 0; i < sphere_count; i++ )
- {
- spheres[i].distance = distance( &neg_camera, &spheres[i].position );
- }
- }
- //-----------------------------------------------------------------------------
- // Name: texture_create
- // Desc: Creates a simple black and white checker board style texture. Change it
- // to whatever you like :)
- //-----------------------------------------------------------------------------
- void texture_create( void )
- {
- GLubyte buffer[64][64][4];
- int s, t;
- for( t = 0; t < 64; t++ )
- {
- for( s = 0; s < 64; s++ )
- {
- GLubyte c = ((((t&0x8)==0)^((s&0x8))==0))*255;
- buffer[s][t][0] = c;
- buffer[s][t][1] = c;
- buffer[s][t][2] = c;
- buffer[s][t][3] = 255;
- }
- }
- // Set the pixel alignment to default
- glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
- // Generate 1 texture ID
- glGenTextures( 1, &floor_tex );
- // Bind this texture so that we can edit it
- glBindTexture( GL_TEXTURE_2D, floor_tex );
- // Create the actual texture with it's dimensions, format and texel data
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, buffer );
- // Enable bilinear filtering
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- }
- //-----------------------------------------------------------------------------
- // Name: floor_render
- // Desc: Renders the floor with the texture created above.
- //-----------------------------------------------------------------------------
- void floor_render( float size, float y )
- {
- // Render the floor at the given height on the Y axis.
- glPushAttrib( GL_ALL_ATTRIB_BITS );
- glPushMatrix();
- glTranslatef( 0.0f, y, 0.0f );
- glDisable( GL_LIGHTING );
- glEnable( GL_TEXTURE_2D );
- glBindTexture( GL_TEXTURE_2D, floor_tex );
- glBegin( GL_QUADS );
- glColor3f( 1.0f, 1.0f, 1.0f );
- glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -size, y, -size );
- glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -size, y, +size );
- glTexCoord2f( 1.0f, 1.0f ); glVertex3f( +size, y, +size );
- glTexCoord2f( 1.0f, 0.0f ); glVertex3f( +size, y, -size );
- glEnd();
- glPopMatrix();
- glPopAttrib();
- }
- //-----------------------------------------------------------------------------
- // Name: spheres_init
- // Desc: Gives each sphere a random position in 3D space.
- //-----------------------------------------------------------------------------
- void spheres_init( void )
- {
- int i;
- // Give each sphere a random position
- for( i = 0; i < sphere_count; i++ )
- {
- spheres[i].position.x = (float) ( ( rand() % 100 ) + 1 ) - 50;
- spheres[i].position.y = 0.0f;
- spheres[i].position.z = (float) ( ( rand() % 100 ) + 1 ) - 50;
- spheres[i].selected = 0;
- spheres[i].dead = 0;
- spheres[i].death_time = 0;
- spheres[i].distance = 0.0f;
- spheres[i].size = 2.0f;
- }
- }
- //-----------------------------------------------------------------------------
- // Name: spheres_render
- // Desc: Renders each sphere in it's random position
- //-----------------------------------------------------------------------------
- void spheres_render( void )
- {
- int i;
- // Render each sphere with a solid green colour
- glColor3f( 0.0f, 1.0f, 0.0f );
- for( i = 0; i < sphere_count; i++ )
- {
- // Is this sphere dead?
- if( spheres[i].dead )
- {
- unsigned int current_time;
- // Slowly decrease the size of the sphere when it's dying
- if( spheres[i].size > 0.0f )
- spheres[i].size -= 0.1f;
- // When time expires, bring the sphere back into play (respawn).
- // The sphere will fall from the sky after the respawn time expires.
- current_time = GetTickCount();
- if( (current_time - spheres[i].death_time) > respawn_time )
- {
- spheres[i].position.x = (float) ( ( rand() % 100 ) + 1 ) - 50;
- spheres[i].position.y = 50.0f;
- spheres[i].position.z = (float) ( ( rand() % 100 ) + 1 ) - 50;
- spheres[i].dead = 0;
- spheres[i].size = 2.0f;
- }
- }
- //if( !spheres[i].dead )
- if( spheres[i].size != 0.0f )
- {
- glPushMatrix();
- glTranslatef( -spheres[i].position.x, spheres[i].position.y, -spheres[i].position.z );
- glutSolidSphere( spheres[i].size, 20, 20 );
- // Render a slightly larger purple transparent sphere around
- // selected objects.
- if( spheres[i].selected )
- {
- glPushAttrib( GL_ALL_ATTRIB_BITS );
- glColor4ub( 128, 0, 255, 64 );
- glDisable( GL_COLOR_MATERIAL );
- glDisable( GL_LIGHTING );
- // glDisable( GL_DEPTH_TEST );
- glDepthMask( GL_FALSE );
- glDisable( GL_TEXTURE_2D );
- glEnable( GL_BLEND );
- glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
- glutSolidSphere( spheres[i].size * 1.5f, 20, 20 );
- glPopAttrib();
- }
- glPopMatrix();
- }
- // If the sphere is in the sky, let it fall back down to the ground
- if( spheres[i].position.y > 0.0f )
- {
- spheres[i].position.y -= 0.5f;
- }
- }
- }
- //-----------------------------------------------------------------------------
- // Name: draw_axes
- // Desc: Draws each axis using a line in the center of 3D space. Red is X,
- // green is Y, and blue is Z. This will help us make sure we are not
- // upside down.
- //-----------------------------------------------------------------------------
- void draw_axes( void )
- {
- glPushAttrib( GL_ALL_ATTRIB_BITS );
- glDisable( GL_LIGHTING );
- glEnable( GL_LINE_SMOOTH );
- glPushMatrix();
- glTranslatef( 0.0f, 0.0f, 0.0f );
- glBegin( GL_LINES );
- // X Axis (Red)
- glColor3f( 1.0f, 0.0f, 0.0f );
- glVertex3f( 0.0f, 0.0f, 0.0f );
- glVertex3f( 2.0f, 0.0f, 0.0f );
- // Y Axis (Green)
- glColor3f( 0.0f, 1.0f, 0.0f );
- glVertex3f( 0.0f, 0.0f, 0.0f );
- glVertex3f( 0.0f, 2.0f, 0.0f );
- // Z Axis (Blue)
- glColor3f( 0.0f, 0.0f, 1.0f );
- glVertex3f( 0.0f, 0.0f, 0.0f );
- glVertex3f( 0.0f, 0.0f, 2.0f );
- glEnd();
- glPopMatrix();
- glPopAttrib();
- }
- //-----------------------------------------------------------------------------
- // Name: draw_crosshair
- // Desc:
- //-----------------------------------------------------------------------------
- void draw_crosshair( void )
- {
- float fViewport[4];
- float w = 32.0f, h = 32.0f;
- // Get the current viewport. We want to make sure the crosshair
- // is in the center of the screen, even if the window is resized.
- glGetFloatv( GL_VIEWPORT, fViewport );
- // Enable 2D rendering
- glEnable2D();
- glBegin( GL_LINES );
- glColor3f( 1.0f, 1.0f, 0.0f );
- glVertex2f( (fViewport[2]/2.0f)-(w/2.0f), fViewport[3]/2.0f );
- glVertex2f( (fViewport[2]/2.0f)+(w/2.0f), fViewport[3]/2.0f );
- glVertex2f( fViewport[2]/2.0f, (fViewport[3]/2.0f)-(h/2.0f) );
- glVertex2f( fViewport[2]/2.0f, (fViewport[3]/2.0f)+(h/2.0f) );
- glEnd();
- // Disable 2D rendering
- glDisable2D();
- }
- //-----------------------------------------------------------------------------
- // Name: show_camera_stats
- // Desc:
- //-----------------------------------------------------------------------------
- void show_camera_stats( void )
- {
- char string[128];
- sprintf( string, "Camera <%f,%f,%f>", camera.vecPos.x, camera.vecPos.y, camera.vecPos.z );
- glPrintf( 30, 30, GLUT_BITMAP_9_BY_15, string );
- }
- //-----------------------------------------------------------------------------
- // Name: show_stats
- // Desc:
- //-----------------------------------------------------------------------------
- void show_stats( void )
- {
- char string[128];
- glColor3f( 0.0f, 0.5f, 1.0f );
- sprintf( string, "Kills: %d", kills );
- glPrintf( 450, 30, GLUT_BITMAP_9_BY_15, string );
- if( sniper_mode )
- sprintf( string, "Sniper Mode: On" );
- else
- sprintf( string, "Sniper Mode: Off" );
- glPrintf( 450, 45, GLUT_BITMAP_9_BY_15, string );
- }
- //-----------------------------------------------------------------------------
- // Name: print_selected_objects
- // Desc:
- //-----------------------------------------------------------------------------
- void print_selected_objects( void )
- {
- int i;
- // List the number of hits
- printf( "Number of hits: %d\n\n", hits );
- // List each the attributes of each object selected
- for( i = 0; i < hits; i++ )
- {
- GLubyte number = select_buffer[i*4];
- GLubyte min_z = select_buffer[i*4+1];
- GLubyte max_z = select_buffer[i*4+2];
- GLubyte name = select_buffer[i*4+3];
- printf( "Number: %d\nMin Z: %d\nMax Z: %d\nName: %d\n\n",
- number, min_z, max_z, name );
- }
- }
- //-----------------------------------------------------------------------------
- // Name: kill_selected_objects
- // Desc: Marks all selected objects as dead.
- //-----------------------------------------------------------------------------
- void kill_selected_objects( void )
- {
- int i;
- // Loop through the selection buffer and pick out the selected objects.
- // This effect should be similar to that of an armour piercing sniper rifle.
- for( i = 0; i < hits; i++ )
- {
- GLubyte name = select_buffer[i*4+3];
- spheres[name].dead = 1;
- spheres[name].death_time = GetTickCount();
- // Increment the kill counter
- kills++;
- }
- }
- //-----------------------------------------------------------------------------
- // Name: kill_closest_selected_object
- // Desc: Marks the closest selected object as dead.
- //-----------------------------------------------------------------------------
- void kill_closest_selected_object( void )
- {
- int i = 0;
- GLubyte name;
- // If we only have one object selected, just kill that one.
- if( hits == 1 )
- {
- name = select_buffer[i*4+3];
- spheres[name].dead = 1;
- spheres[name].death_time = GetTickCount();
- kills++;
- }
- else
- {
- float d = spheres[select_buffer[i*4+3]].distance;
- int closest = 0;
- // Find the object with the shortest distance
- /*for( i = 1; i < hits; i++ )
- {
- name = select_buffer[i*4+3];
- if( d > spheres[name].distance )
- {
- d = spheres[name].distance;
- closest = name;
- }
- }
- spheres[closest].dead = 1;
- spheres[closest].death_time = GetTickCount();*/
- for( i = 0; i < hits; i++ )
- {
- name = select_buffer[i*4+3];
- d = min( d, spheres[name].distance );
- }
- // Now set the closest sphere as dead
- for( i = 0; i < hits; i++ )
- {
- name = select_buffer[i*4+3];
- if( spheres[name].distance == d )
- {
- spheres[name].dead = 1;
- spheres[name].death_time = GetTickCount();
- kills++;
- break;
- }
- }
- }
- }
- //-----------------------------------------------------------------------------
- // Name: draw_lazer_from_player_to_nearest_target
- // Desc: Draws an orange antialiased line from the player to the nearest targeted
- // object.
- //-----------------------------------------------------------------------------
- void draw_lazer_from_player_to_nearest_target( void )
- {
- int i = 0;
- GLubyte name;
- struct Vector3 p1, p2;
- // Don't do anything if there is no target in the crosshair
- if( !hits )
- return;
- // Set the first point relative to the camera's position
- p1.x = camera.vecPos.x;
- p1.y = 0.0f; //camera.vecPos.y;
- p1.z = camera.vecPos.z;
- // If we only have one object selected, then we know where to aim
- // the lazer.
- if( hits == 1 )
- {
- name = select_buffer[i*4+3];
- p2.x = -spheres[name].position.x;
- p2.y = -spheres[name].position.y;
- p2.z = -spheres[name].position.z;
- }
- else
- {
- float d = spheres[select_buffer[i*4+3]].distance;
- for( i = 0; i < hits; i++ )
- {
- name = select_buffer[i*4+3];
- d = min( d, spheres[name].distance );
- }
- // Now target the closest sphere with the lazer
- for( i = 0; i < hits; i++ )
- {
- name = select_buffer[i*4+3];
- if( spheres[name].distance == d )
- {
- name = select_buffer[i*4+3];
- p2.x = -spheres[name].position.x;
- p2.y = -spheres[name].position.y;
- p2.z = -spheres[name].position.z;
- break;
- }
- }
- }
- // Draw the lazer as an orange line
- glPushAttrib( GL_ALL_ATTRIB_BITS );
- glDisable( GL_LIGHTING );
- glDisable( GL_BLEND );
- //glEnable( GL_LINE_SMOOTH );
- glLineWidth( 1.5f );
- glBegin( GL_LINES );
- glColor3f( 1.0f, 0.5f, 0.0f );
- glVertex3fv( (float*) &p1 );
- glVertex3fv( (float*) &p2 );
- glEnd();
- glPopAttrib();
- }
- //-----------------------------------------------------------------------------
- // Name: do_selection
- // Desc:
- //-----------------------------------------------------------------------------
- void do_selection( int select_x, int select_y, int preselect )
- {
- GLint iViewport[4];
- float fViewport[4];
- int i;
- // Set the selection buffer and specify it's size
- glSelectBuffer( sphere_count*4, select_buffer );
- // Get a copy of the current viewport
- glGetIntegerv( GL_VIEWPORT, iViewport );
- glGetFloatv( GL_VIEWPORT, fViewport );
- // Switch into selection mode
- glRenderMode( GL_SELECT );
- // Clear the name stack
- glInitNames();
- // Give the stack at least one name or else it will generate an error
- glPushName(0);
- // Save the projection matrix
- glMatrixMode( GL_PROJECTION );
- glPushMatrix();
- glLoadIdentity();
- // Restrict the rendering area to the given point using gluPickMatrix
- gluPickMatrix( select_x, select_y, 1.0f, 1.0f, iViewport );
- gluPerspective( 45.0f, (GLdouble) fViewport[2]/fViewport[3], 0.1f, 500.0f );
- // Now render selectable objects to the screen
- glMatrixMode( GL_MODELVIEW );
- // glutSwapBuffers();
- // Render each sphere with a solid green colour
- glColor3f( 0.0f, 1.0f, 0.0f );
- for( i = 0; i < sphere_count; i++ )
- {
- // if( !spheres[i].dead )
- if( spheres[i].size != 0.0f )
- {
- glPushMatrix();
- glLoadName(i);
- glTranslatef( -spheres[i].position.x, spheres[i].position.y, -spheres[i].position.z );
- glutSolidSphere( spheres[i].size, 20, 20 );
- glPopMatrix();
- }
- }
- glPopName();
- // Restore the projection matrix
- glMatrixMode( GL_PROJECTION );
- glPopMatrix();
- // Get the number of hits (the number of objects drawn within that
- // specified area) and return to render mode
- hits = glRenderMode( GL_RENDER );
- // Don't do anything except mark objects as selected in preselect mode
- if( preselect )
- {
- // Go through the list of objects and deselect them all
- for( i = 0; i < sphere_count; i++ )
- spheres[i].selected = 0;
- // Now mark all selected objects
- for( i = 0; i < hits; i++ )
- {
- GLubyte name = select_buffer[i*4+3];
- char string[64];
- spheres[name].selected = 1;
- // For debugging purposes, display the distance between you and
- // each selected object.
- sprintf( string, "Name: %d Distance %f", name, spheres[name].distance );
- glPrintf( 30, 45+(i*20), GLUT_BITMAP_9_BY_15, string );
- }
- draw_lazer_from_player_to_nearest_target();
- }
- else
- {
- // Show the number of selected objects in the console (optional)
- print_selected_objects();
- // Kill selected object(s)
- if( sniper_mode )
- kill_selected_objects();
- else
- kill_closest_selected_object();
- }
- // Return to the modelview matrix
- glMatrixMode( GL_MODELVIEW );
- }
- //-----------------------------------------------------------------------------
- // Name: glh_extension_supported
- // Desc: Checks the list of OpenGL extensions supported by this videocard/driver
- // to see if it's supported. This function was borrowed from the NVIDIA
- // SDK (v9.5). I was too lazy to write my own extension checking function :)
- // See glh_extensions.h
- //-----------------------------------------------------------------------------
- int glh_extension_supported( const char *extension )
- {
- static const GLubyte *extensions = NULL;
- const GLubyte *start;
- GLubyte *where, *terminator;
- // Extension names should not have spaces.
- where = (GLubyte *) strchr( extension, ' ');
- if ( where || *extension == '\0')
- return 0;
- if ( !extensions )
- extensions = glGetString( GL_EXTENSIONS );
- // It takes a bit of care to be fool-proof about parsing the
- // OpenGL extensions string. Don't be fooled by sub-strings,
- // etc.
- start = extensions;
- for (;;)
- {
- where = (GLubyte *) strstr( (const char *) start, extension );
- if ( !where )
- break;
- terminator = where + strlen( extension );
- if ( where == start || *(where - 1) == ' ' )
- {
- if ( *terminator == ' ' || *terminator == '\0' )
- {
- return 1;
- }
- }
- start = terminator;
- }
- return 0;
- }
- //-----------------------------------------------------------------------------
- // Name: InitScene
- // Desc: Initializes extensions, textures, render states, etc. before rendering
- //-----------------------------------------------------------------------------
- int InitScene( void )
- {
- //
- // Set default render states
- //
- // Enable depth testing
- glEnable( GL_DEPTH_TEST );
- glDepthFunc( GL_LEQUAL );
- glClearDepth( 1.0f );
- // Enable lighting
- glEnable( GL_LIGHTING );
- glEnable( GL_LIGHT0 );
- // Enable colour material
- glEnable( GL_COLOR_MATERIAL );
- // Disable texture mapping (for now)
- glDisable( GL_TEXTURE_2D );
- // Disable blending
- glDisable( GL_BLEND );
- // Disable dithering
- glDisable( GL_DITHER );
- // Enable culling (counter clock wise)
- glEnable( GL_CULL_FACE );
- glCullFace( GL_CCW );
- // Enable fog
- // glEnable( GL_FOG );
- // Enable perspective correction and polygon smoothing
- glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
- glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
- //
- // Initialize scene objects and geometry
- //
- texture_create();
- spheres_init();
- memset( &camera, 0, sizeof( struct ThirdPersonCamera_t ) );
- camera.fRadius = 10.0f;
- //
- // Misc
- //
- srand( time( NULL ) );
- return GL_TRUE;
- }
- //-----------------------------------------------------------------------------
- // Name: DisplayFunction
- // Desc: Our display function used to render our graphics in the main loop of
- // our GLUT application.
- //-----------------------------------------------------------------------------
- void DisplayFunction( void )
- {
- int iViewport[4];
- // Clear the screen and depth buffer
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
- // Reset matrices to default position, scale, and rotation
- glLoadIdentity();
- // Position the camera behind our character and render it
- glTranslatef( 0.0f, -2.0f, -camera.fRadius );
- glRotatef( camera.vecRot.x, 1.0f, 0.0f, 0.0f );
- glColor3f( 1.0f, 0.0f, 0.0f );
- glutSolidCube( 3.0f );
- // Rotate the camera as necessary
- glRotatef( camera.vecRot.y, 0.0f, 1.0f, 0.0f );
- glTranslatef( -camera.vecPos.x, 0.0f, -camera.vecPos.z );
- // Calculate distances
- calculate_distances();
- // Do pre-selection
- glGetIntegerv( GL_VIEWPORT, iViewport );
- do_selection( iViewport[2]/2, iViewport[3]/2, TRUE );
- // Render the floor
- floor_render( 50.0f, -0.75f );
- // Render spheres
- spheres_render();
- // Draw each axis
- draw_axes();
- // Draw the crosshair
- draw_crosshair();
- // Show camera's statistics
- glColor3f( 0.0f, 0.0f, 1.0f );
- show_camera_stats();
- // Show other stats
- show_stats();
- // Display graphics to the user
- glutSwapBuffers();
- }
- //-----------------------------------------------------------------------------
- // Name: IdleFunction
- // Desc: The function that is executed whenever the program is idle
- //-----------------------------------------------------------------------------
- void IdleFunction( void )
- {
- // Continue to display graphics even when messages aren't
- // being processed.
- glutPostRedisplay();
- }
- //-----------------------------------------------------------------------------
- // Name: KeyboardFunction
- // Desc: Handles keyboard input
- //-----------------------------------------------------------------------------
- void KeyboardFunction( GLubyte k, int x, int y )
- {
- static float fRotSpeed = 1.0f;
- if (k=='q')
- {
- camera.vecRot.x += fRotSpeed;
- if (camera.vecRot.x > 360) camera.vecRot.x -= 360;
- }
- if (k=='z')
- {
- camera.vecRot.x -= fRotSpeed;
- if (camera.vecRot.x < -360) camera.vecRot.x += 360;
- }
- if (k=='c')
- {
- camera.vecRot.y += fRotSpeed;
- if (camera.vecRot.y > 360) camera.vecRot.y -= 360;
- }
- if (k=='v')
- {
- camera.vecRot.y -= fRotSpeed;
- if (camera.vecRot.y < -360) camera.vecRot.y += 360;
- }
- if (k=='w')
- {
- float xrotrad, yrotrad;
- yrotrad = (camera.vecRot.y / 180.0f * 3.141592654f);
- xrotrad = (camera.vecRot.x / 180.0f * 3.141592654f);
- camera.vecPos.x += (float)(sin(yrotrad));
- camera.vecPos.z -= (float)(cos(yrotrad));
- camera.vecPos.y -= (float)(sin(xrotrad));
- }
- if (k=='s')
- {
- float xrotrad, yrotrad;
- yrotrad = (camera.vecRot.y / 180.0f * 3.141592654f);
- xrotrad = (camera.vecRot.x / 180.0f * 3.141592654f);
- camera.vecPos.x -= (float)(sin(yrotrad));
- camera.vecPos.z += (float)(cos(yrotrad));
- camera.vecPos.y += (float)(sin(xrotrad));
- }
- if (k=='d')
- {
- float yrotrad;
- yrotrad = (camera.vecRot.y / 180.0f * 3.141592654f);
- camera.vecPos.x += (float)(cos(yrotrad)) * 0.5f;
- camera.vecPos.z += (float)(sin(yrotrad)) * 0.5f;
- }
- if (k =='a')
- {
- float yrotrad;
- yrotrad = (camera.vecRot.y / 180.0f * 3.141592654f);
- camera.vecPos.x -= (float)(cos(yrotrad)) * 0.5f;
- camera.vecPos.z -= (float)(sin(yrotrad)) * 0.5f;
- }
- // Has escape been pressed?
- if( k == 27 )
- {
- exit(0);
- }
- // If not, then continue rendering
- glutPostRedisplay();
- }
- //-----------------------------------------------------------------------------
- // Name: MouseFunction
- // Desc: Handles mouse input (movement)
- //-----------------------------------------------------------------------------
- void MouseFunction( int x, int y )
- {
- int diffx = x - camera.fLastX;
- int diffy = y - camera.fLastY;
- camera.fLastX = x;
- camera.fLastY = y;
- camera.vecRot.x += (float) diffy;
- camera.vecRot.y += (float) diffx;
- if( camera.vecRot.x < -30.0f )
- camera.vecRot.x = -30.0f;
- if( camera.vecRot.x > 90.0f )
- camera.vecRot.x = 90.0f;
- }
- //-----------------------------------------------------------------------------
- // Name: MouseClickFunction
- // Desc: Handles mouse input (clicks)
- //-----------------------------------------------------------------------------
- void MouseClickFunction( int button, int state, int x, int y )
- {
- int iViewport[4];
- int center_x;
- int center_y;
- if( ( button == GLUT_LEFT_BUTTON ) && ( state == GLUT_DOWN ) )
- {
- glGetIntegerv( GL_VIEWPORT, iViewport );
- center_x = iViewport[2]/2;
- center_y = iViewport[3]/2;
- printf( "\nCenter X: %d\nCenter Y: %d\n\n", center_x, center_y );
- do_selection( center_x, center_y, FALSE );
- }
- if( ( button == GLUT_RIGHT_BUTTON ) && ( state == GLUT_DOWN ) )
- sniper_mode = !sniper_mode;
- }
- //-----------------------------------------------------------------------------
- // Name: ReshapeFunction
- // Desc: Changes the viewport when the window is resized
- //-----------------------------------------------------------------------------
- void ReshapeFunction( GLsizei width, GLsizei height )
- {
- // Prevent divide by zero exception
- if( !height ) height = 1;
- // Reset viewport
- glViewport( 0, 0, width, height );
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
- // Reset perspective
- gluPerspective( 45.0f, (GLdouble) width/height, 0.1f, 500.0f );
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity();
- }
- //-----------------------------------------------------------------------------
- // Name: main
- // Desc: Program entry point.
- //-----------------------------------------------------------------------------
- int main( int argc, char* argv[] )
- {
- // Initialize OpenGL via GLUT library
- glutInit( &argc, argv );
- glutInitWindowSize( 640, 480 );
- glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA );
- glutCreateWindow( "Meta-Balls!" );
- // glutFullScreen();
- // Initialize scene objects and properties
- InitScene();
- // Set our input/output functions and begin the main loop
- glutIdleFunc( IdleFunction );
- glutDisplayFunc( DisplayFunction );
- glutKeyboardFunc( KeyboardFunction );
- glutReshapeFunc( ReshapeFunction );
- glutMouseFunc( MouseClickFunction );
- glutPassiveMotionFunc( MouseFunction );
- glutMainLoop();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement