Plain port of particles example to GLFW 3.

This commit is contained in:
Camilla Berglund 2014-01-11 19:37:33 +01:00
parent e38740d6ef
commit d9f53c78a0
2 changed files with 58 additions and 35 deletions

View File

@ -18,17 +18,21 @@ endif()
set(GETOPT ${GLFW_SOURCE_DIR}/deps/getopt.h set(GETOPT ${GLFW_SOURCE_DIR}/deps/getopt.h
${GLFW_SOURCE_DIR}/deps/getopt.c) ${GLFW_SOURCE_DIR}/deps/getopt.c)
set(TINYCTHREAD ${GLFW_SOURCE_DIR}/deps/tinycthread.h
${GLFW_SOURCE_DIR}/deps/tinycthread.c)
if (APPLE) if (APPLE)
# Set fancy names for bundles # Set fancy names for bundles
add_executable(Boing MACOSX_BUNDLE boing.c) add_executable(Boing MACOSX_BUNDLE boing.c)
add_executable(Gears MACOSX_BUNDLE gears.c) add_executable(Gears MACOSX_BUNDLE gears.c)
add_executable(Particles MACOSX_BUNDLE particles.c ${TINYCTHREAD})
add_executable(Simple MACOSX_BUNDLE simple.c) add_executable(Simple MACOSX_BUNDLE simple.c)
add_executable("Split View" MACOSX_BUNDLE splitview.c) add_executable("Split View" MACOSX_BUNDLE splitview.c)
add_executable(Wave MACOSX_BUNDLE wave.c) add_executable(Wave MACOSX_BUNDLE wave.c)
set_target_properties(Boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing") set_target_properties(Boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing")
set_target_properties(Gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears") set_target_properties(Gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears")
set_target_properties(Particles PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Particles")
set_target_properties(Simple PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Simple") set_target_properties(Simple PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Simple")
set_target_properties("Split View" PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Split View") set_target_properties("Split View" PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Split View")
set_target_properties(Wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave") set_target_properties(Wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
@ -37,13 +41,14 @@ else()
add_executable(boing WIN32 boing.c) add_executable(boing WIN32 boing.c)
add_executable(gears WIN32 gears.c) add_executable(gears WIN32 gears.c)
add_executable(heightmap WIN32 heightmap.c ${GETOPT}) add_executable(heightmap WIN32 heightmap.c ${GETOPT})
add_executable(particles WIN32 particles.c ${TINYCTHREAD})
add_executable(simple WIN32 simple.c) add_executable(simple WIN32 simple.c)
add_executable(splitview WIN32 splitview.c) add_executable(splitview WIN32 splitview.c)
add_executable(wave WIN32 wave.c) add_executable(wave WIN32 wave.c)
endif() endif()
if (MSVC) if (MSVC)
set(WINDOWS_BINARIES boing gears heightmap simple splitview wave) set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave)
# Tell MSVC to use main instead of WinMain for Windows subsystem executables # Tell MSVC to use main instead of WinMain for Windows subsystem executables
set_target_properties(${WINDOWS_BINARIES} PROPERTIES set_target_properties(${WINDOWS_BINARIES} PROPERTIES
@ -51,7 +56,7 @@ if (MSVC)
endif() endif()
if (APPLE) if (APPLE)
set(BUNDLE_BINARIES Boing Gears Simple "Split View" Wave) set(BUNDLE_BINARIES Boing Gears Particles Simple "Split View" Wave)
set_target_properties(${BUNDLE_BINARIES} PROPERTIES set_target_properties(${BUNDLE_BINARIES} PROPERTIES
MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}

View File

@ -41,7 +41,11 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <GL/glfw.h>
#define GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>
#include <tinycthread.h>
// Define tokens for GL_EXT_separate_specular_color if not already defined // Define tokens for GL_EXT_separate_specular_color if not already defined
#ifndef GL_EXT_separate_specular_color #ifndef GL_EXT_separate_specular_color
@ -100,9 +104,9 @@ struct {
float dt; // Time since last frame (s) float dt; // Time since last frame (s)
int p_frame; // Particle physics frame number int p_frame; // Particle physics frame number
int d_frame; // Particle draw frame number int d_frame; // Particle draw frame number
GLFWcond p_done; // Condition: particle physics done cnd_t p_done; // Condition: particle physics done
GLFWcond d_done; // Condition: particle draw done cnd_t d_done; // Condition: particle draw done
GLFWmutex particles_lock; // Particles data sharing mutex mtx_t particles_lock; // Particles data sharing mutex
} thread_sync; } thread_sync;
@ -456,11 +460,12 @@ void DrawParticles( double t, float dt )
if( multithreading ) if( multithreading )
{ {
// Wait for particle physics thread to be done // Wait for particle physics thread to be done
glfwLockMutex( thread_sync.particles_lock ); mtx_lock( &thread_sync.particles_lock );
while( running && thread_sync.p_frame <= thread_sync.d_frame ) while( running && thread_sync.p_frame <= thread_sync.d_frame )
{ {
glfwWaitCond( thread_sync.p_done, thread_sync.particles_lock, struct timespec ts = { 0, 100000000 };
0.1 ); cnd_timedwait( &thread_sync.p_done, &thread_sync.particles_lock,
&ts );
} }
// Store the frame time and delta time for the physics thread // Store the frame time and delta time for the physics thread
@ -563,8 +568,8 @@ void DrawParticles( double t, float dt )
// thread // thread
if( multithreading ) if( multithreading )
{ {
glfwUnlockMutex( thread_sync.particles_lock ); mtx_unlock( &thread_sync.particles_lock );
glfwSignalCond( thread_sync.d_done ); cnd_signal( &thread_sync.d_done );
} }
// Draw final batch of particles (if any) // Draw final batch of particles (if any)
@ -897,7 +902,7 @@ void Draw( double t )
// Resize() - GLFW window resize callback function // Resize() - GLFW window resize callback function
//======================================================================== //========================================================================
void GLFWCALL Resize( int x, int y ) void Resize( GLFWwindow* window, int x, int y )
{ {
width = x; width = x;
height = y > 0 ? y : 1; // Prevent division by zero in aspect calc. height = y > 0 ? y : 1; // Prevent division by zero in aspect calc.
@ -908,16 +913,16 @@ void GLFWCALL Resize( int x, int y )
// Input callback functions // Input callback functions
//======================================================================== //========================================================================
void GLFWCALL KeyFun( int key, int action ) void KeyFun( 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_ESC: case GLFW_KEY_ESCAPE:
running = 0; running = 0;
break; break;
case 'W': case GLFW_KEY_W:
wireframe = !wireframe; wireframe = !wireframe;
glPolygonMode( GL_FRONT_AND_BACK, glPolygonMode( GL_FRONT_AND_BACK,
wireframe ? GL_LINE : GL_FILL ); wireframe ? GL_LINE : GL_FILL );
@ -933,18 +938,19 @@ void GLFWCALL KeyFun( int key, int action )
// PhysicsThreadFun() - Thread for updating particle physics // PhysicsThreadFun() - Thread for updating particle physics
//======================================================================== //========================================================================
void GLFWCALL PhysicsThreadFun( void *arg ) int PhysicsThreadFun( void *arg )
{ {
while( running ) while( running )
{ {
// Lock mutex // Lock mutex
glfwLockMutex( thread_sync.particles_lock ); mtx_lock( &thread_sync.particles_lock );
// Wait for particle drawing to be done // 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 )
{ {
glfwWaitCond( thread_sync.d_done, thread_sync.particles_lock, struct timespec ts = { 0, 100000000 };
0.1 ); cnd_timedwait( &thread_sync.d_done, &thread_sync.particles_lock,
&ts );
} }
// No longer running? // No longer running?
@ -960,9 +966,11 @@ void GLFWCALL PhysicsThreadFun( void *arg )
thread_sync.p_frame ++; thread_sync.p_frame ++;
// Unlock mutex and signal drawing thread // Unlock mutex and signal drawing thread
glfwUnlockMutex( thread_sync.particles_lock ); mtx_unlock( &thread_sync.particles_lock );
glfwSignalCond( thread_sync.p_done ); cnd_signal( &thread_sync.p_done );
} }
return 0;
} }
@ -974,7 +982,8 @@ int main( int argc, char **argv )
{ {
int i, frames, benchmark; int i, frames, benchmark;
double t0, t; double t0, t;
GLFWthread physics_thread = 0; thrd_t physics_thread = 0;
GLFWwindow* window;
// Use multithreading by default, but don't benchmark // Use multithreading by default, but don't benchmark
multithreading = 1; multithreading = 1;
@ -1028,24 +1037,25 @@ int main( int argc, char **argv )
} }
// Open OpenGL fullscreen window // Open OpenGL fullscreen window
if( !glfwOpenWindow( WIDTH, HEIGHT, 0,0,0,0, 16,0, GLFW_FULLSCREEN ) ) 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(); glfwTerminate();
exit( EXIT_FAILURE ); exit( EXIT_FAILURE );
} }
// Set window title glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetWindowTitle( "Particle engine" );
// Disable VSync (we want to get as high FPS as possible!) glfwMakeContextCurrent(window);
glfwSwapInterval( 0 ); glfwSwapInterval( 0 );
// Window resize callback function // Window resize callback function
glfwSetWindowSizeCallback( Resize ); glfwSetWindowSizeCallback( window, Resize );
// Set keyboard input callback function // Set keyboard input callback function
glfwSetKeyCallback( KeyFun ); glfwSetKeyCallback( window, KeyFun );
// Upload particle texture // Upload particle texture
glGenTextures( 1, &particle_tex_id ); glGenTextures( 1, &particle_tex_id );
@ -1099,10 +1109,15 @@ int main( int argc, char **argv )
{ {
thread_sync.p_frame = 0; thread_sync.p_frame = 0;
thread_sync.d_frame = 0; thread_sync.d_frame = 0;
thread_sync.particles_lock = glfwCreateMutex(); mtx_init(&thread_sync.particles_lock, mtx_timed);
thread_sync.p_done = glfwCreateCond(); cnd_init(&thread_sync.p_done);
thread_sync.d_done = glfwCreateCond(); cnd_init(&thread_sync.d_done);
physics_thread = glfwCreateThread( PhysicsThreadFun, NULL );
if (thrd_create( &physics_thread, PhysicsThreadFun, NULL ) != thrd_success)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
} }
// Main loop // Main loop
@ -1117,10 +1132,11 @@ int main( int argc, char **argv )
Draw( t ); Draw( t );
// Swap buffers // Swap buffers
glfwSwapBuffers(); glfwSwapBuffers(window);
glfwPollEvents();
// Check if window was closed // Check if window was closed
running = running && glfwGetWindowParam( GLFW_OPENED ); running = running && !glfwWindowShouldClose( window );
// Increase frame count // Increase frame count
frames ++; frames ++;
@ -1136,7 +1152,7 @@ int main( int argc, char **argv )
// Wait for particle physics thread to die // Wait for particle physics thread to die
if( multithreading ) if( multithreading )
{ {
glfwWaitThread( physics_thread, GLFW_WAIT ); thrd_join( physics_thread, NULL );
} }
// Display profiling information // Display profiling information
@ -1144,6 +1160,8 @@ int main( int argc, char **argv )
(double)frames / t ); (double)frames / t );
printf( " (multithreading %s)\n", multithreading ? "on" : "off" ); printf( " (multithreading %s)\n", multithreading ? "on" : "off" );
glfwDestroyWindow(window);
// Terminate OpenGL // Terminate OpenGL
glfwTerminate(); glfwTerminate();