From 3f9117ef85e7791a770d98a8b8f43a99740ffe62 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sat, 11 Jan 2014 20:30:37 +0100 Subject: [PATCH] Formatted particles example. --- examples/particles.c | 816 ++++++++++++++++++++----------------------- 1 file changed, 376 insertions(+), 440 deletions(-) diff --git a/examples/particles.c b/examples/particles.c index 570dbddb..66e698a2 100644 --- a/examples/particles.c +++ b/examples/particles.c @@ -68,18 +68,24 @@ // Type definitions //======================================================================== -typedef struct { float x,y,z; } VEC; +typedef struct +{ + float x, y, z; +} Vec3; // This structure is used for interleaved vertex arrays (see the -// DrawParticles function) - Note: This structure SHOULD be packed on most -// systems. It uses 32-bit fields on 32-bit boundaries, and is a multiple -// of 64 bits in total (6x32=3x64). If it does not work, try using pragmas -// or whatever to force the structure to be packed. -typedef struct { +// draw_particles function) +// +// NOTE: This structure SHOULD be packed on most systems. It uses 32-bit fields +// on 32-bit boundaries, and is a multiple of 64 bits in total (6x32=3x64). If +// it does not work, try using pragmas or whatever to force the structure to be +// packed. +typedef struct +{ GLfloat s, t; // Texture coordinates GLuint rgba; // Color (four ubytes packed into an uint) GLfloat x, y, z; // Vertex coordinates -} VERTEX; +} Vertex; //======================================================================== @@ -165,7 +171,7 @@ const unsigned char floor_texture[ F_TEX_WIDTH * F_TEX_HEIGHT ] = { #define MAX_PARTICLES 3000 // Life span of a particle (in seconds) -#define LIFE_SPAN 8.0f +#define LIFE_SPAN 8.f // A new particle is born every [BIRTH_INTERVAL] second #define BIRTH_INTERVAL (LIFE_SPAN/(float)MAX_PARTICLES) @@ -177,13 +183,13 @@ const unsigned char floor_texture[ F_TEX_WIDTH * F_TEX_HEIGHT ] = { #define GRAVITY 9.8f // Base initial velocity (m/s) -#define VELOCITY 8.0f +#define VELOCITY 8.f // Bounce friction (1.0 = no friction, 0.0 = maximum friction) #define FRICTION 0.75f // "Fountain" height (m) -#define FOUNTAIN_HEIGHT 3.0f +#define FOUNTAIN_HEIGHT 3.f // Fountain radius (m) #define FOUNTAIN_RADIUS 1.6f @@ -207,7 +213,7 @@ typedef struct { // Global vectors holding all particles. We use two vectors for double // buffering. -static PARTICLE particles[ MAX_PARTICLES ]; +static PARTICLE particles[MAX_PARTICLES]; // Global variable holding the age of the youngest particle static float min_age; @@ -223,88 +229,86 @@ static float glow_pos[4]; // Object material and fog configuration constants //======================================================================== -const GLfloat fountain_diffuse[4] = {0.7f,1.0f,1.0f,1.0f}; -const GLfloat fountain_specular[4] = {1.0f,1.0f,1.0f,1.0f}; -const GLfloat fountain_shininess = 12.0f; -const GLfloat floor_diffuse[4] = {1.0f,0.6f,0.6f,1.0f}; -const GLfloat floor_specular[4] = {0.6f,0.6f,0.6f,1.0f}; -const GLfloat floor_shininess = 18.0f; -const GLfloat fog_color[4] = {0.1f, 0.1f, 0.1f, 1.0f}; +const GLfloat fountain_diffuse[4] = { 0.7f, 1.f, 1.f, 1.f }; +const GLfloat fountain_specular[4] = { 1.f, 1.f, 1.f, 1.f }; +const GLfloat fountain_shininess = 12.f; +const GLfloat floor_diffuse[4] = { 1.f, 0.6f, 0.6f, 1.f }; +const GLfloat floor_specular[4] = { 0.6f, 0.6f, 0.6f, 1.f }; +const GLfloat floor_shininess = 18.f; +const GLfloat fog_color[4] = { 0.1f, 0.1f, 0.1f, 1.f }; //======================================================================== -// InitParticle() - Initialize a new particle +// Initialize a new particle //======================================================================== -void InitParticle( PARTICLE *p, double t ) +static void init_particle(PARTICLE *p, double t) { - float xy_angle, velocity; + float xy_angle, velocity; // Start position of particle is at the fountain blow-out - p->x = 0.0f; - p->y = 0.0f; + p->x = 0.f; + p->y = 0.f; p->z = FOUNTAIN_HEIGHT; // Start velocity is up (Z)... - p->vz = 0.7f + (0.3f/4096.f) * (float) (rand() & 4095); + p->vz = 0.7f + (0.3f / 4096.f) * (float) (rand() & 4095); // ...and a randomly chosen X/Y direction - xy_angle = (2.f * (float)M_PI / 4096.f) * (float) (rand() & 4095); - p->vx = 0.4f * (float) cos( xy_angle ); - p->vy = 0.4f * (float) sin( xy_angle ); + xy_angle = (2.f * (float) M_PI / 4096.f) * (float) (rand() & 4095); + p->vx = 0.4f * (float) cos(xy_angle); + p->vy = 0.4f * (float) sin(xy_angle); // Scale velocity vector according to a time-varying velocity - velocity = VELOCITY*(0.8f + 0.1f*(float)(sin( 0.5*t )+sin( 1.31*t ))); + velocity = VELOCITY * (0.8f + 0.1f * (float) (sin(0.5 * t) + sin(1.31 * t))); p->vx *= velocity; p->vy *= velocity; p->vz *= velocity; // Color is time-varying - p->r = 0.7f + 0.3f * (float) sin( 0.34*t + 0.1 ); - p->g = 0.6f + 0.4f * (float) sin( 0.63*t + 1.1 ); - p->b = 0.6f + 0.4f * (float) sin( 0.91*t + 2.1 ); + p->r = 0.7f + 0.3f * (float) sin(0.34 * t + 0.1); + p->g = 0.6f + 0.4f * (float) sin(0.63 * t + 1.1); + p->b = 0.6f + 0.4f * (float) sin(0.91 * t + 2.1); // Store settings for fountain glow lighting - glow_pos[0] = 0.4f * (float) sin( 1.34*t ); - glow_pos[1] = 0.4f * (float) sin( 3.11*t ); - glow_pos[2] = FOUNTAIN_HEIGHT + 1.0f; - glow_pos[3] = 1.0f; + glow_pos[0] = 0.4f * (float) sin(1.34 * t); + glow_pos[1] = 0.4f * (float) sin(3.11 * t); + glow_pos[2] = FOUNTAIN_HEIGHT + 1.f; + glow_pos[3] = 1.f; glow_color[0] = p->r; glow_color[1] = p->g; glow_color[2] = p->b; - glow_color[3] = 1.0f; + glow_color[3] = 1.f; // The particle is new-born and active - p->life = 1.0f; + p->life = 1.f; p->active = 1; } //======================================================================== -// UpdateParticle() - Update a particle +// Update a particle //======================================================================== #define FOUNTAIN_R2 (FOUNTAIN_RADIUS+PARTICLE_SIZE/2)*(FOUNTAIN_RADIUS+PARTICLE_SIZE/2) -void UpdateParticle( PARTICLE *p, float dt ) +static void update_particle(PARTICLE *p, float dt) { // If the particle is not active, we need not do anything - if( !p->active ) - { + if (!p->active) return; - } // The particle is getting older... - p->life = p->life - dt * (1.0f / LIFE_SPAN); + p->life -= dt * (1.f / LIFE_SPAN); // Did the particle die? - if( p->life <= 0.0f ) + if (p->life <= 0.f) { p->active = 0; return; } - // Update particle velocity (apply gravity) + // Apply gravity p->vz = p->vz - GRAVITY * dt; // Update particle position @@ -313,81 +317,73 @@ void UpdateParticle( PARTICLE *p, float dt ) p->z = p->z + p->vz * dt; // Simple collision detection + response - if( p->vz < 0.0f ) + if (p->vz < 0.f) { // Particles should bounce on the fountain (with friction) - if( (p->x*p->x + p->y*p->y) < FOUNTAIN_R2 && - p->z < (FOUNTAIN_HEIGHT + PARTICLE_SIZE/2) ) + if ((p->x * p->x + p->y * p->y) < FOUNTAIN_R2 && + p->z < (FOUNTAIN_HEIGHT + PARTICLE_SIZE / 2)) { p->vz = -FRICTION * p->vz; - p->z = FOUNTAIN_HEIGHT + PARTICLE_SIZE/2 + - FRICTION * (FOUNTAIN_HEIGHT + - PARTICLE_SIZE/2 - p->z); + p->z = FOUNTAIN_HEIGHT + PARTICLE_SIZE / 2 + + FRICTION * (FOUNTAIN_HEIGHT + + PARTICLE_SIZE / 2 - p->z); } // Particles should bounce on the floor (with friction) - else if( p->z < PARTICLE_SIZE/2 ) + else if (p->z < PARTICLE_SIZE / 2) { p->vz = -FRICTION * p->vz; - p->z = PARTICLE_SIZE/2 + - FRICTION * (PARTICLE_SIZE/2 - p->z); + p->z = PARTICLE_SIZE / 2 + + FRICTION * (PARTICLE_SIZE / 2 - p->z); } - } } //======================================================================== -// ParticleEngine() - The main frame for the particle engine. Called once -// per frame. +// The main frame for the particle engine. Called once per frame. //======================================================================== -void ParticleEngine( double t, float dt ) +static void particle_engine(double t, float dt) { - int i; - float dt2; + int i; + float dt2; - // Update particles (iterated several times per frame if dt is too - // large) - while( dt > 0.0f ) + // Update particles (iterated several times per frame if dt is too large) + while (dt > 0.f) { // Calculate delta time for this iteration dt2 = dt < MIN_DELTA_T ? dt : MIN_DELTA_T; - // Update particles - for( i = 0; i < MAX_PARTICLES; i ++ ) - { - UpdateParticle( &particles[ i ], dt2 ); - } + for (i = 0; i < MAX_PARTICLES; i++) + update_particle(&particles[i], dt2); - // Increase minimum age min_age += dt2; // Should we create any new particle(s)? - while( min_age >= BIRTH_INTERVAL ) + while (min_age >= BIRTH_INTERVAL) { min_age -= BIRTH_INTERVAL; // Find a dead particle to replace with a new one - for( i = 0; i < MAX_PARTICLES; i ++ ) + for (i = 0; i < MAX_PARTICLES; i++) { - if( !particles[ i ].active ) + if (!particles[i].active) { - InitParticle( &particles[ i ], t + min_age ); - UpdateParticle( &particles[ i ], min_age ); + init_particle(&particles[i], t + min_age); + update_particle(&particles[i], min_age); break; } } } - // Decrease frame delta time dt -= dt2; } } //======================================================================== -// DrawParticles() - Draw all active particles. We use OpenGL 1.1 vertex +// Draw all active particles. We use OpenGL 1.1 vertex // arrays for this in order to accelerate the drawing. //======================================================================== @@ -396,15 +392,16 @@ void ParticleEngine( double t, float dt ) // the L1 data cache on most CPUs) #define PARTICLE_VERTS 4 // Number of vertices per particle -void DrawParticles( double t, float dt ) +static void draw_particles(double t, float dt) { - int i, particle_count; - VERTEX vertex_array[ BATCH_PARTICLES * PARTICLE_VERTS ], *vptr; - float alpha; - GLuint rgba; - VEC quad_lower_left, quad_lower_right; - GLfloat mat[ 16 ]; - PARTICLE *pptr; + int i, particle_count; + Vertex vertex_array[BATCH_PARTICLES * PARTICLE_VERTS]; + Vertex* vptr; + float alpha; + GLuint rgba; + Vec3 quad_lower_left, quad_lower_right; + GLfloat mat[16]; + PARTICLE* pptr; // Here comes the real trick with flat single primitive objects (s.c. // "billboards"): We must rotate the textured primitive so that it @@ -417,7 +414,7 @@ void DrawParticles( double t, float dt ) // Get modelview matrix. We will only use the upper left 3x3 part of // the matrix, which represents the rotation. - glGetFloatv( GL_MODELVIEW_MATRIX, mat ); + glGetFloatv(GL_MODELVIEW_MATRIX, mat); // 1) & 2) We do it in one swift step: // Although not obvious, the following six lines represent two matrix/ @@ -427,25 +424,24 @@ void DrawParticles( double t, float dt ) // (-1,-1,0), and the lower right corner, PARTICLE_SIZE/2 * (1,-1,0). // The upper left/right corners of the quad is always the negative of // the opposite corners (regardless of rotation). - quad_lower_left.x = (-PARTICLE_SIZE/2) * (mat[0] + mat[1]); - quad_lower_left.y = (-PARTICLE_SIZE/2) * (mat[4] + mat[5]); - quad_lower_left.z = (-PARTICLE_SIZE/2) * (mat[8] + mat[9]); - quad_lower_right.x = (PARTICLE_SIZE/2) * (mat[0] - mat[1]); - quad_lower_right.y = (PARTICLE_SIZE/2) * (mat[4] - mat[5]); - quad_lower_right.z = (PARTICLE_SIZE/2) * (mat[8] - mat[9]); + quad_lower_left.x = (-PARTICLE_SIZE / 2) * (mat[0] + mat[1]); + quad_lower_left.y = (-PARTICLE_SIZE / 2) * (mat[4] + mat[5]); + quad_lower_left.z = (-PARTICLE_SIZE / 2) * (mat[8] + mat[9]); + quad_lower_right.x = (PARTICLE_SIZE / 2) * (mat[0] - mat[1]); + quad_lower_right.y = (PARTICLE_SIZE / 2) * (mat[4] - mat[5]); + quad_lower_right.z = (PARTICLE_SIZE / 2) * (mat[8] - mat[9]); // Don't update z-buffer, since all particles are transparent! - glDepthMask( GL_FALSE ); + glDepthMask(GL_FALSE); - // Enable blending - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE ); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Select particle texture - if( !wireframe ) + if (!wireframe) { - glEnable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, particle_tex_id ); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, particle_tex_id); } // Set up vertex arrays. We use interleaved arrays, which is easier to @@ -454,63 +450,61 @@ void DrawParticles( double t, float dt ) // situations). GL_T2F_C4UB_V3F means: 2 floats for texture coords, // 4 ubytes for color and 3 floats for vertex coord (in that order). // Most OpenGL cards / drivers are optimized for this format. - glInterleavedArrays( GL_T2F_C4UB_V3F, 0, vertex_array ); + glInterleavedArrays(GL_T2F_C4UB_V3F, 0, vertex_array); // Is particle physics carried out in a separate thread? - if( multithreading ) + if (multithreading) { // Wait for particle physics thread to be done - mtx_lock( &thread_sync.particles_lock ); - while( running && thread_sync.p_frame <= thread_sync.d_frame ) + mtx_lock(&thread_sync.particles_lock); + while (running && thread_sync.p_frame <= thread_sync.d_frame) { struct timespec ts = { 0, 100000000 }; - cnd_timedwait( &thread_sync.p_done, &thread_sync.particles_lock, - &ts ); + cnd_timedwait(&thread_sync.p_done, &thread_sync.particles_lock, &ts); } // Store the frame time and delta time for the physics thread - thread_sync.t = t; + thread_sync.t = t; thread_sync.dt = dt; // Update frame counter - thread_sync.d_frame ++; + thread_sync.d_frame++; } else { // Perform particle physics in this thread - ParticleEngine( t, dt ); + particle_engine(t, dt); } // Loop through all particles and build vertex arrays. particle_count = 0; vptr = vertex_array; pptr = particles; - for( i = 0; i < MAX_PARTICLES; i ++ ) + + for (i = 0; i < MAX_PARTICLES; i++) { - if( pptr->active ) + if (pptr->active) { // Calculate particle intensity (we set it to max during 75% // of its life, then it fades out) - alpha = 4.0f * pptr->life; - if( alpha > 1.0f ) - { - alpha = 1.0f; - } + alpha = 4.f * pptr->life; + if (alpha > 1.f) + alpha = 1.f; // Convert color from float to 8-bit (store it in a 32-bit // integer using endian independent type casting) - ((GLubyte *)&rgba)[0] = (GLubyte)(pptr->r * 255.0f); - ((GLubyte *)&rgba)[1] = (GLubyte)(pptr->g * 255.0f); - ((GLubyte *)&rgba)[2] = (GLubyte)(pptr->b * 255.0f); - ((GLubyte *)&rgba)[3] = (GLubyte)(alpha * 255.0f); + ((GLubyte*) &rgba)[0] = (GLubyte)(pptr->r * 255.f); + ((GLubyte*) &rgba)[1] = (GLubyte)(pptr->g * 255.f); + ((GLubyte*) &rgba)[2] = (GLubyte)(pptr->b * 255.f); + ((GLubyte*) &rgba)[3] = (GLubyte)(alpha * 255.f); // 3) Translate the quad to the correct position in modelview // space and store its parameters in vertex arrays (we also // store texture coord and color information for each vertex). // Lower left corner - vptr->s = 0.0f; - vptr->t = 0.0f; + vptr->s = 0.f; + vptr->t = 0.f; vptr->rgba = rgba; vptr->x = pptr->x + quad_lower_left.x; vptr->y = pptr->y + quad_lower_left.y; @@ -518,8 +512,8 @@ void DrawParticles( double t, float dt ) vptr ++; // Lower right corner - vptr->s = 1.0f; - vptr->t = 0.0f; + vptr->s = 1.f; + vptr->t = 0.f; vptr->rgba = rgba; vptr->x = pptr->x + quad_lower_right.x; vptr->y = pptr->y + quad_lower_right.y; @@ -527,8 +521,8 @@ void DrawParticles( double t, float dt ) vptr ++; // Upper right corner - vptr->s = 1.0f; - vptr->t = 1.0f; + vptr->s = 1.f; + vptr->t = 1.f; vptr->rgba = rgba; vptr->x = pptr->x - quad_lower_left.x; vptr->y = pptr->y - quad_lower_left.y; @@ -536,8 +530,8 @@ void DrawParticles( double t, float dt ) vptr ++; // Upper left corner - vptr->s = 0.0f; - vptr->t = 1.0f; + vptr->s = 0.f; + vptr->t = 1.f; vptr->rgba = rgba; vptr->x = pptr->x - quad_lower_right.x; vptr->y = pptr->y - quad_lower_right.y; @@ -550,43 +544,41 @@ void DrawParticles( double t, float dt ) // If we have filled up one batch of particles, draw it as a set // of quads using glDrawArrays. - if( particle_count >= BATCH_PARTICLES ) + if (particle_count >= BATCH_PARTICLES) { // The first argument tells which primitive type we use (QUAD) // The second argument tells the index of the first vertex (0) // The last argument is the vertex count - glDrawArrays( GL_QUADS, 0, PARTICLE_VERTS * particle_count ); + glDrawArrays(GL_QUADS, 0, PARTICLE_VERTS * particle_count); particle_count = 0; vptr = vertex_array; } // Next particle - pptr ++; + pptr++; } // We are done with the particle data: Unlock mutex and signal physics // thread - if( multithreading ) + if (multithreading) { - mtx_unlock( &thread_sync.particles_lock ); - cnd_signal( &thread_sync.d_done ); + mtx_unlock(&thread_sync.particles_lock); + cnd_signal(&thread_sync.d_done); } // Draw final batch of particles (if any) - glDrawArrays( GL_QUADS, 0, PARTICLE_VERTS * particle_count ); + glDrawArrays(GL_QUADS, 0, PARTICLE_VERTS * particle_count); // Disable vertex arrays (Note: glInterleavedArrays implicitly called // glEnableClientState for vertex, texture coord and color arrays) - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - glDisableClientState( GL_COLOR_ARRAY ); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); - // Disable texturing and blending - glDisable( GL_TEXTURE_2D ); - glDisable( GL_BLEND ); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); - // Allow Z-buffer updates again - glDepthMask( GL_TRUE ); + glDepthMask(GL_TRUE); } @@ -597,14 +589,16 @@ void DrawParticles( double t, float dt ) #define FOUNTAIN_SIDE_POINTS 14 #define FOUNTAIN_SWEEP_STEPS 32 -static const float fountain_side[ FOUNTAIN_SIDE_POINTS*2 ] = { - 1.2f, 0.0f, 1.0f, 0.2f, 0.41f, 0.3f, 0.4f, 0.35f, - 0.4f, 1.95f, 0.41f, 2.0f, 0.8f, 2.2f, 1.2f, 2.4f, - 1.5f, 2.7f, 1.55f,2.95f, 1.6f, 3.0f, 1.0f, 3.0f, - 0.5f, 3.0f, 0.0f, 3.0f +static const float fountain_side[FOUNTAIN_SIDE_POINTS * 2] = +{ + 1.2f, 0.f, 1.f, 0.2f, 0.41f, 0.3f, 0.4f, 0.35f, + 0.4f, 1.95f, 0.41f, 2.f, 0.8f, 2.2f, 1.2f, 2.4f, + 1.5f, 2.7f, 1.55f,2.95f, 1.6f, 3.f, 1.f, 3.f, + 0.5f, 3.f, 0.f, 3.f }; -static const float fountain_normal[ FOUNTAIN_SIDE_POINTS*2 ] = { +static const float fountain_normal[FOUNTAIN_SIDE_POINTS * 2] = +{ 1.0000f, 0.0000f, 0.6428f, 0.7660f, 0.3420f, 0.9397f, 1.0000f, 0.0000f, 1.0000f, 0.0000f, 0.3420f,-0.9397f, 0.4226f,-0.9063f, 0.5000f,-0.8660f, 0.7660f,-0.6428f, 0.9063f,-0.4226f, 0.0000f,1.00000f, 0.0000f,1.00000f, @@ -613,10 +607,10 @@ static const float fountain_normal[ FOUNTAIN_SIDE_POINTS*2 ] = { //======================================================================== -// DrawFountain() - Draw a fountain +// Draw a fountain //======================================================================== -void DrawFountain( void ) +static void draw_fountain(void) { static GLuint fountain_list = 0; double angle; @@ -624,70 +618,61 @@ void DrawFountain( void ) int m, n; // The first time, we build the fountain display list - if( !fountain_list ) + if (!fountain_list) { - // Start recording of a new display list - fountain_list = glGenLists( 1 ); - glNewList( fountain_list, GL_COMPILE_AND_EXECUTE ); + fountain_list = glGenLists(1); + glNewList(fountain_list, GL_COMPILE_AND_EXECUTE); - // Set fountain material - glMaterialfv( GL_FRONT, GL_DIFFUSE, fountain_diffuse ); - glMaterialfv( GL_FRONT, GL_SPECULAR, fountain_specular ); - glMaterialf( GL_FRONT, GL_SHININESS, fountain_shininess ); + glMaterialfv(GL_FRONT, GL_DIFFUSE, fountain_diffuse); + glMaterialfv(GL_FRONT, GL_SPECULAR, fountain_specular); + glMaterialf(GL_FRONT, GL_SHININESS, fountain_shininess); // Build fountain using triangle strips - for( n = 0; n < FOUNTAIN_SIDE_POINTS-1; n ++ ) + for (n = 0; n < FOUNTAIN_SIDE_POINTS - 1; n++) { - glBegin( GL_TRIANGLE_STRIP ); - for( m = 0; m <= FOUNTAIN_SWEEP_STEPS; m ++ ) + glBegin(GL_TRIANGLE_STRIP); + for (m = 0; m <= FOUNTAIN_SWEEP_STEPS; m++) { - angle = (double) m * (2.0*M_PI/(double)FOUNTAIN_SWEEP_STEPS); - x = (float) cos( angle ); - y = (float) sin( angle ); + angle = (double) m * (2.0 * M_PI / (double) FOUNTAIN_SWEEP_STEPS); + x = (float) cos(angle); + y = (float) sin(angle); // Draw triangle strip - glNormal3f( x * fountain_normal[ n*2+2 ], - y * fountain_normal[ n*2+2 ], - fountain_normal[ n*2+3 ] ); - glVertex3f( x * fountain_side[ n*2+2 ], - y * fountain_side[ n*2+2 ], - fountain_side[ n*2+3 ] ); - glNormal3f( x * fountain_normal[ n*2 ], - y * fountain_normal[ n*2 ], - fountain_normal[ n*2+1 ] ); - glVertex3f( x * fountain_side[ n*2 ], - y * fountain_side[ n*2 ], - fountain_side[ n*2+1 ] ); + glNormal3f(x * fountain_normal[n * 2 + 2], + y * fountain_normal[n * 2 + 2], + fountain_normal[n * 2 + 3]); + glVertex3f(x * fountain_side[n * 2 + 2], + y * fountain_side[n * 2 + 2], + fountain_side[n * 2 +3 ]); + glNormal3f(x * fountain_normal[n * 2], + y * fountain_normal[n * 2], + fountain_normal[n * 2 + 1]); + glVertex3f(x * fountain_side[n * 2], + y * fountain_side[n * 2], + fountain_side[n * 2 + 1]); } + glEnd(); } - // End recording of display list glEndList(); } else - { - // Playback display list - glCallList( fountain_list ); - } + glCallList(fountain_list); } //======================================================================== -// TesselateFloor() - Recursive function for building variable tesselated -// floor +// Recursive function for building variable tesselated floor //======================================================================== -void TesselateFloor( float x1, float y1, float x2, float y2, - int recursion ) +static void tessellate_floor(float x1, float y1, float x2, float y2, int depth) { float delta, x, y; // Last recursion? - if( recursion >= 5 ) - { - delta = 999999.0f; - } + if (depth >= 5) + delta = 999999.f; else { x = (float) (fabs(x1) < fabs(x2) ? fabs(x1) : fabs(x2)); @@ -696,278 +681,253 @@ void TesselateFloor( float x1, float y1, float x2, float y2, } // Recurse further? - if( delta < 0.1f ) + if (delta < 0.1f) { - x = (x1+x2) * 0.5f; - y = (y1+y2) * 0.5f; - TesselateFloor( x1,y1, x, y, recursion + 1 ); - TesselateFloor( x,y1, x2, y, recursion + 1 ); - TesselateFloor( x1, y, x,y2, recursion + 1 ); - TesselateFloor( x, y, x2,y2, recursion + 1 ); + x = (x1 + x2) * 0.5f; + y = (y1 + y2) * 0.5f; + tessellate_floor(x1, y1, x, y, depth + 1); + tessellate_floor(x, y1, x2, y, depth + 1); + tessellate_floor(x1, y, x, y2, depth + 1); + tessellate_floor(x, y, x2, y2, depth + 1); } else { - glTexCoord2f( x1*30.0f, y1*30.0f ); - glVertex3f( x1*80.0f, y1*80.0f , 0.0f ); - glTexCoord2f( x2*30.0f, y1*30.0f ); - glVertex3f( x2*80.0f, y1*80.0f , 0.0f ); - glTexCoord2f( x2*30.0f, y2*30.0f ); - glVertex3f( x2*80.0f, y2*80.0f , 0.0f ); - glTexCoord2f( x1*30.0f, y2*30.0f ); - glVertex3f( x1*80.0f, y2*80.0f , 0.0f ); + glTexCoord2f(x1 * 30.f, y1 * 30.f); + glVertex3f( x1 * 80.f, y1 * 80.f, 0.f); + glTexCoord2f(x2 * 30.f, y1 * 30.f); + glVertex3f( x2 * 80.f, y1 * 80.f, 0.f); + glTexCoord2f(x2 * 30.f, y2 * 30.f); + glVertex3f( x2 * 80.f, y2 * 80.f, 0.f); + glTexCoord2f(x1 * 30.f, y2 * 30.f); + glVertex3f( x1 * 80.f, y2 * 80.f, 0.f); } } //======================================================================== -// DrawFloor() - Draw floor. We builde the floor recursively, and let the -// tesselation in the centre (near x,y=0,0) be high, while the selleation -// around the edges be low. +// Draw floor. We build the floor recursively and let the tessellation in the +// center (near x,y=0,0) be high, while the tessellation around the edges be +// low. //======================================================================== -void DrawFloor( void ) +static void draw_floor(void) { static GLuint floor_list = 0; - // Select floor texture - if( !wireframe ) + if (!wireframe) { - glEnable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, floor_tex_id ); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, floor_tex_id); } // The first time, we build the floor display list - if( !floor_list ) + if (!floor_list) { - // Start recording of a new display list - floor_list = glGenLists( 1 ); - glNewList( floor_list, GL_COMPILE_AND_EXECUTE ); + floor_list = glGenLists(1); + glNewList(floor_list, GL_COMPILE_AND_EXECUTE); - // Set floor material - glMaterialfv( GL_FRONT, GL_DIFFUSE, floor_diffuse ); - glMaterialfv( GL_FRONT, GL_SPECULAR, floor_specular ); - glMaterialf( GL_FRONT, GL_SHININESS, floor_shininess ); + glMaterialfv(GL_FRONT, GL_DIFFUSE, floor_diffuse); + glMaterialfv(GL_FRONT, GL_SPECULAR, floor_specular); + glMaterialf(GL_FRONT, GL_SHININESS, floor_shininess); // Draw floor as a bunch of triangle strips (high tesselation // improves lighting) - glNormal3f( 0.0f, 0.0f, 1.0f ); - glBegin( GL_QUADS ); - TesselateFloor( -1.0f,-1.0f, 0.0f,0.0f, 0 ); - TesselateFloor( 0.0f,-1.0f, 1.0f,0.0f, 0 ); - TesselateFloor( 0.0f, 0.0f, 1.0f,1.0f, 0 ); - TesselateFloor( -1.0f, 0.0f, 0.0f,1.0f, 0 ); + glNormal3f(0.f, 0.f, 1.f); + glBegin(GL_QUADS); + tessellate_floor(-1.f, -1.f, 0.f, 0.f, 0); + tessellate_floor( 0.f, -1.f, 1.f, 0.f, 0); + tessellate_floor( 0.f, 0.f, 1.f, 1.f, 0); + tessellate_floor(-1.f, 0.f, 0.f, 1.f, 0); glEnd(); - // End recording of display list glEndList(); } else - { - // Playback display list - glCallList( floor_list ); - } + glCallList(floor_list); - glDisable( GL_TEXTURE_2D ); + glDisable(GL_TEXTURE_2D); } //======================================================================== -// SetupLights() - Position and configure light sources +// Position and configure light sources //======================================================================== -void SetupLights( void ) +static void setup_lights(void) { float l1pos[4], l1amb[4], l1dif[4], l1spec[4]; float l2pos[4], l2amb[4], l2dif[4], l2spec[4]; // Set light source 1 parameters - l1pos[0] = 0.0f; l1pos[1] = -9.0f; l1pos[2] = 8.0f; l1pos[3] = 1.0f; - l1amb[0] = 0.2f; l1amb[1] = 0.2f; l1amb[2] = 0.2f; l1amb[3] = 1.0f; - l1dif[0] = 0.8f; l1dif[1] = 0.4f; l1dif[2] = 0.2f; l1dif[3] = 1.0f; - l1spec[0] = 1.0f; l1spec[1] = 0.6f; l1spec[2] = 0.2f; l1spec[3] = 0.0f; + l1pos[0] = 0.f; l1pos[1] = -9.f; l1pos[2] = 8.f; l1pos[3] = 1.f; + l1amb[0] = 0.2f; l1amb[1] = 0.2f; l1amb[2] = 0.2f; l1amb[3] = 1.f; + l1dif[0] = 0.8f; l1dif[1] = 0.4f; l1dif[2] = 0.2f; l1dif[3] = 1.f; + l1spec[0] = 1.f; l1spec[1] = 0.6f; l1spec[2] = 0.2f; l1spec[3] = 0.f; // Set light source 2 parameters - l2pos[0] = -15.0f; l2pos[1] = 12.0f; l2pos[2] = 1.5f; l2pos[3] = 1.0f; - l2amb[0] = 0.0f; l2amb[1] = 0.0f; l2amb[2] = 0.0f; l2amb[3] = 1.0f; - l2dif[0] = 0.2f; l2dif[1] = 0.4f; l2dif[2] = 0.8f; l2dif[3] = 1.0f; - l2spec[0] = 0.2f; l2spec[1] = 0.6f; l2spec[2] = 1.0f; l2spec[3] = 0.0f; + l2pos[0] = -15.f; l2pos[1] = 12.f; l2pos[2] = 1.5f; l2pos[3] = 1.f; + l2amb[0] = 0.f; l2amb[1] = 0.f; l2amb[2] = 0.f; l2amb[3] = 1.f; + l2dif[0] = 0.2f; l2dif[1] = 0.4f; l2dif[2] = 0.8f; l2dif[3] = 1.f; + l2spec[0] = 0.2f; l2spec[1] = 0.6f; l2spec[2] = 1.f; l2spec[3] = 0.f; - // Configure light sources in OpenGL - glLightfv( GL_LIGHT1, GL_POSITION, l1pos ); - glLightfv( GL_LIGHT1, GL_AMBIENT, l1amb ); - glLightfv( GL_LIGHT1, GL_DIFFUSE, l1dif ); - glLightfv( GL_LIGHT1, GL_SPECULAR, l1spec ); - glLightfv( GL_LIGHT2, GL_POSITION, l2pos ); - glLightfv( GL_LIGHT2, GL_AMBIENT, l2amb ); - glLightfv( GL_LIGHT2, GL_DIFFUSE, l2dif ); - glLightfv( GL_LIGHT2, GL_SPECULAR, l2spec ); - glLightfv( GL_LIGHT3, GL_POSITION, glow_pos ); - glLightfv( GL_LIGHT3, GL_DIFFUSE, glow_color ); - glLightfv( GL_LIGHT3, GL_SPECULAR, glow_color ); + glLightfv(GL_LIGHT1, GL_POSITION, l1pos); + glLightfv(GL_LIGHT1, GL_AMBIENT, l1amb); + glLightfv(GL_LIGHT1, GL_DIFFUSE, l1dif); + glLightfv(GL_LIGHT1, GL_SPECULAR, l1spec); + glLightfv(GL_LIGHT2, GL_POSITION, l2pos); + glLightfv(GL_LIGHT2, GL_AMBIENT, l2amb); + glLightfv(GL_LIGHT2, GL_DIFFUSE, l2dif); + glLightfv(GL_LIGHT2, GL_SPECULAR, l2spec); + glLightfv(GL_LIGHT3, GL_POSITION, glow_pos); + glLightfv(GL_LIGHT3, GL_DIFFUSE, glow_color); + glLightfv(GL_LIGHT3, GL_SPECULAR, glow_color); - // Enable light sources - glEnable( GL_LIGHT1 ); - glEnable( GL_LIGHT2 ); - glEnable( GL_LIGHT3 ); + glEnable(GL_LIGHT1); + glEnable(GL_LIGHT2); + glEnable(GL_LIGHT3); } //======================================================================== -// Draw() - Main rendering function +// Main rendering function //======================================================================== -void Draw( double t ) +static void draw_scene(double t) { double xpos, ypos, zpos, angle_x, angle_y, angle_z; static double t_old = 0.0; - float dt; + float dt; // Calculate frame-to-frame delta time - dt = (float)(t-t_old); + dt = (float) (t - t_old); t_old = t; - // Setup viewport - glViewport( 0, 0, width, height ); + glViewport(0, 0, width, height); - // Clear color and Z-buffer - glClearColor( 0.1f, 0.1f, 0.1f, 1.0f ); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + glClearColor(0.1f, 0.1f, 0.1f, 1.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // Setup projection - glMatrixMode( GL_PROJECTION ); + glMatrixMode(GL_PROJECTION); glLoadIdentity(); - gluPerspective( 65.0, (double)width/(double)height, 1.0, 60.0 ); + gluPerspective(65.0, (double) width / (double) height, 1.0, 60.0); // Setup camera - glMatrixMode( GL_MODELVIEW ); + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Rotate camera angle_x = 90.0 - 10.0; - angle_y = 10.0 * sin( 0.3 * t ); + angle_y = 10.0 * sin(0.3 * t); angle_z = 10.0 * t; - glRotated( -angle_x, 1.0, 0.0, 0.0 ); - glRotated( -angle_y, 0.0, 1.0, 0.0 ); - glRotated( -angle_z, 0.0, 0.0, 1.0 ); + glRotated(-angle_x, 1.0, 0.0, 0.0); + glRotated(-angle_y, 0.0, 1.0, 0.0); + glRotated(-angle_z, 0.0, 0.0, 1.0); // Translate camera - xpos = 15.0 * sin( (M_PI/180.0) * angle_z ) + - 2.0 * sin( (M_PI/180.0) * 3.1 * t ); - ypos = -15.0 * cos( (M_PI/180.0) * angle_z ) + - 2.0 * cos( (M_PI/180.0) * 2.9 * t ); - zpos = 4.0 + 2.0 * cos( (M_PI/180.0) * 4.9 * t ); - glTranslated( -xpos, -ypos, -zpos ); + xpos = 15.0 * sin((M_PI / 180.0) * angle_z) + + 2.0 * sin((M_PI / 180.0) * 3.1 * t); + ypos = -15.0 * cos((M_PI / 180.0) * angle_z) + + 2.0 * cos((M_PI / 180.0) * 2.9 * t); + zpos = 4.0 + 2.0 * cos((M_PI / 180.0) * 4.9 * t); + glTranslated(-xpos, -ypos, -zpos); - // Enable face culling - glFrontFace( GL_CCW ); - glCullFace( GL_BACK ); - glEnable( GL_CULL_FACE ); + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); - // Enable lighting - SetupLights(); - glEnable( GL_LIGHTING ); + setup_lights(); + glEnable(GL_LIGHTING); - // Enable fog (dim details far away) - glEnable( GL_FOG ); - glFogi( GL_FOG_MODE, GL_EXP ); - glFogf( GL_FOG_DENSITY, 0.05f ); - glFogfv( GL_FOG_COLOR, fog_color ); + glEnable(GL_FOG); + glFogi(GL_FOG_MODE, GL_EXP); + glFogf(GL_FOG_DENSITY, 0.05f); + glFogfv(GL_FOG_COLOR, fog_color); - // Draw floor - DrawFloor(); + draw_floor(); - // Enable Z-buffering - glEnable( GL_DEPTH_TEST ); - glDepthFunc( GL_LEQUAL ); - glDepthMask( GL_TRUE ); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glDepthMask(GL_TRUE); - // Draw fountain - DrawFountain(); + draw_fountain(); - // Disable fog & lighting - glDisable( GL_LIGHTING ); - glDisable( GL_FOG ); + glDisable(GL_LIGHTING); + glDisable(GL_FOG); - // Draw all particles (must be drawn after all solid objects have been - // drawn!) - DrawParticles( t, dt ); + // Particles must be drawn after all solid objects have been drawn + draw_particles(t, dt); // Z-buffer not needed anymore - glDisable( GL_DEPTH_TEST ); + glDisable(GL_DEPTH_TEST); } //======================================================================== -// Resize() - GLFW window resize callback function +// Window resize callback function //======================================================================== -void Resize( GLFWwindow* window, int x, int y ) +static void resize_callback(GLFWwindow* window, int w, int h) { - width = x; - height = y > 0 ? y : 1; // Prevent division by zero in aspect calc. + width = w; + height = h > 0 ? h : 1; // Prevent division by zero in aspect calc. } //======================================================================== -// Input callback functions +// Key callback functions //======================================================================== -void KeyFun( GLFWwindow* window, int key, int scancode, int action, int mods ) +static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { - if( action == GLFW_PRESS ) + if (action == GLFW_PRESS) { - switch( key ) + switch (key) { - case GLFW_KEY_ESCAPE: - running = 0; - break; - case GLFW_KEY_W: - wireframe = !wireframe; - glPolygonMode( GL_FRONT_AND_BACK, - wireframe ? GL_LINE : GL_FILL ); - break; - default: - break; + case GLFW_KEY_ESCAPE: + running = 0; + break; + case GLFW_KEY_W: + wireframe = !wireframe; + glPolygonMode(GL_FRONT_AND_BACK, + wireframe ? GL_LINE : GL_FILL); + break; + default: + break; } } } //======================================================================== -// PhysicsThreadFun() - Thread for updating particle physics +// Thread for updating particle physics //======================================================================== -int PhysicsThreadFun( void *arg ) +static int physics_thread_main(void* arg) { - while( running ) + for (;;) { - // Lock mutex - mtx_lock( &thread_sync.particles_lock ); + mtx_lock(&thread_sync.particles_lock); // Wait for particle drawing to be done - while( running && thread_sync.p_frame > thread_sync.d_frame ) + while (running && thread_sync.p_frame > thread_sync.d_frame) { struct timespec ts = { 0, 100000000 }; - cnd_timedwait( &thread_sync.d_done, &thread_sync.particles_lock, - &ts ); + cnd_timedwait(&thread_sync.d_done, &thread_sync.particles_lock, &ts); } - // No longer running? - if( !running ) - { + if (!running) break; - } // Update particles - ParticleEngine( thread_sync.t, thread_sync.dt ); + particle_engine(thread_sync.t, thread_sync.dt); // Update frame counter - thread_sync.p_frame ++; + thread_sync.p_frame++; // Unlock mutex and signal drawing thread - mtx_unlock( &thread_sync.particles_lock ); - cnd_signal( &thread_sync.p_done ); + mtx_unlock(&thread_sync.particles_lock); + cnd_signal(&thread_sync.p_done); } return 0; @@ -975,137 +935,123 @@ int PhysicsThreadFun( void *arg ) //======================================================================== -// main() +// main //======================================================================== -int main( int argc, char **argv ) +int main(int argc, char** argv) { - int i, frames, benchmark; - double t0, t; - thrd_t physics_thread = 0; + int i, frames, benchmark; + double t0, t; + thrd_t physics_thread = 0; GLFWwindow* window; // Use multithreading by default, but don't benchmark multithreading = 1; benchmark = 0; - // Check command line arguments - for( i = 1; i < argc; i ++ ) + for (i = 1; i < argc; i++) { // Use benchmarking? - if( strcmp( argv[i], "-b" ) == 0 ) - { + if (strcmp(argv[i], "-b") == 0) benchmark = 1; - } // Force multithreading off? - else if( strcmp( argv[i], "-s" ) == 0 ) - { + else if (strcmp(argv[i], "-s") == 0) multithreading = 0; - } // With a Finder launch on Mac OS X we get a bogus -psn_0_46268417 // kind of argument (actual numbers vary). Ignore it. - else if( strncmp( argv[i], "-psn_", 5) == 0 ); + else if (strncmp(argv[i], "-psn_", 5) == 0) + ; // Usage else { - if( strcmp( argv[i], "-?" ) != 0 ) - { - printf( "Unknonwn option %s\n\n", argv[ i ] ); - } - printf( "Usage: %s [options]\n", argv[ 0 ] ); - printf( "\n"); - printf( "Options:\n" ); - printf( " -b Benchmark (run program for 60 s)\n" ); - printf( " -s Run program as single thread (default is to use two threads)\n" ); - printf( " -? Display this text\n" ); - printf( "\n"); - printf( "Program runtime controls:\n" ); - printf( " w Toggle wireframe mode\n" ); - printf( " ESC Exit program\n" ); - exit( 0 ); + if (strcmp(argv[i], "-?") != 0) + printf("Unknonwn option %s\n\n", argv[i]); + + printf("Usage: %s [options]\n", argv[0]); + printf("\n"); + printf("Options:\n"); + printf(" -b Benchmark (run program for 60 s)\n"); + printf(" -s Run program as single thread (default is to use two threads)\n"); + printf(" -? Display this text\n"); + printf("\n"); + printf("Program runtime controls:\n"); + printf(" w Toggle wireframe mode\n"); + printf(" ESC Exit program\n"); + exit(EXIT_FAILURE); } } - // Initialize GLFW - if( !glfwInit() ) + if (!glfwInit()) { - fprintf( stderr, "Failed to initialize GLFW\n" ); - exit( EXIT_FAILURE ); + fprintf(stderr, "Failed to initialize GLFW\n"); + exit(EXIT_FAILURE); } - // Open OpenGL fullscreen window - window = glfwCreateWindow( WIDTH, HEIGHT, "Particle Engine", - glfwGetPrimaryMonitor(), NULL); - if( !window ) + window = glfwCreateWindow(WIDTH, HEIGHT, "Particle Engine", + glfwGetPrimaryMonitor(), NULL); + if (!window) { - fprintf( stderr, "Failed to open GLFW window\n" ); + fprintf(stderr, "Failed to open GLFW window\n"); glfwTerminate(); - exit( EXIT_FAILURE ); + exit(EXIT_FAILURE); } glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwMakeContextCurrent(window); - glfwSwapInterval( 0 ); + glfwSwapInterval(0); - // Window resize callback function - glfwSetWindowSizeCallback( window, Resize ); - - // Set keyboard input callback function - glfwSetKeyCallback( window, KeyFun ); + glfwSetWindowSizeCallback(window, resize_callback); + glfwSetKeyCallback(window, key_callback); // Upload particle texture - glGenTextures( 1, &particle_tex_id ); - glBindTexture( GL_TEXTURE_2D, particle_tex_id ); - glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, P_TEX_WIDTH, P_TEX_HEIGHT, - 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, particle_texture ); + glGenTextures(1, &particle_tex_id); + glBindTexture(GL_TEXTURE_2D, particle_tex_id); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, P_TEX_WIDTH, P_TEX_HEIGHT, + 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, particle_texture); // Upload floor texture - glGenTextures( 1, &floor_tex_id ); - glBindTexture( GL_TEXTURE_2D, floor_tex_id ); - glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, F_TEX_WIDTH, F_TEX_HEIGHT, - 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, floor_texture ); + glGenTextures(1, &floor_tex_id); + glBindTexture(GL_TEXTURE_2D, floor_tex_id); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, F_TEX_WIDTH, F_TEX_HEIGHT, + 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, floor_texture); - // Check if we have GL_EXT_separate_specular_color, and if so use it - if( glfwExtensionSupported( "GL_EXT_separate_specular_color" ) ) + if (glfwExtensionSupported("GL_EXT_separate_specular_color")) { - glLightModeli( GL_LIGHT_MODEL_COLOR_CONTROL_EXT, - GL_SEPARATE_SPECULAR_COLOR_EXT ); + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, + GL_SEPARATE_SPECULAR_COLOR_EXT); } // Set filled polygon mode as default (not wireframe) - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); wireframe = 0; // Clear particle system - for( i = 0; i < MAX_PARTICLES; i ++ ) - { - particles[ i ].active = 0; - } - min_age = 0.0f; + for (i = 0; i < MAX_PARTICLES; i++) + particles[i].active = 0; + + min_age = 0.f; - // Set "running" flag running = 1; // Set initial times thread_sync.t = 0.0; thread_sync.dt = 0.001f; - // Init threading - if( multithreading ) + if (multithreading) { thread_sync.p_frame = 0; thread_sync.d_frame = 0; @@ -1113,58 +1059,48 @@ int main( int argc, char **argv ) cnd_init(&thread_sync.p_done); cnd_init(&thread_sync.d_done); - if (thrd_create( &physics_thread, PhysicsThreadFun, NULL ) != thrd_success) + if (thrd_create(&physics_thread, physics_thread_main, NULL) != thrd_success) { glfwTerminate(); exit(EXIT_FAILURE); } } - // Main loop t0 = glfwGetTime(); frames = 0; - while( running ) + + while (running) { // Get frame time t = glfwGetTime() - t0; - // Draw... - Draw( t ); + draw_scene(t); - // Swap buffers glfwSwapBuffers(window); glfwPollEvents(); - // Check if window was closed - running = running && !glfwWindowShouldClose( window ); + running = running && !glfwWindowShouldClose(window); - // Increase frame count - frames ++; + frames++; // End of benchmark? - if( benchmark && t >= 60.0 ) - { + if (benchmark && t >= 60.0) running = 0; - } } + t = glfwGetTime() - t0; // Wait for particle physics thread to die - if( multithreading ) - { - thrd_join( physics_thread, NULL ); - } + if (multithreading) + thrd_join(physics_thread, NULL); // Display profiling information - printf( "%d frames in %.2f seconds = %.1f FPS", frames, t, - (double)frames / t ); - printf( " (multithreading %s)\n", multithreading ? "on" : "off" ); + printf("%d frames in %.2f seconds = %.1f FPS", frames, t, (double) frames / t); + printf(" (multithreading %s)\n", multithreading ? "on" : "off"); glfwDestroyWindow(window); - - // Terminate OpenGL glfwTerminate(); - exit( EXIT_SUCCESS ); + exit(EXIT_SUCCESS); }