Formatted particles example.
diff --git a/examples/particles.c b/examples/particles.c
index 570dbdd..66e698a 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 @@
#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 @@
#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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
// (-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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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 @@
#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 @@
//========================================================================
-// 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 @@
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 @@
}
// 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 @@
//========================================================================
-// 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;
- // Set "running" flag
+ min_age = 0.f;
+
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 @@
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);
}