From d9f53c78a081c0f43966ea414c4544ae888dc86d Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sat, 11 Jan 2014 19:37:33 +0100 Subject: [PATCH] Plain port of particles example to GLFW 3. --- examples/CMakeLists.txt | 9 ++++- examples/particles.c | 84 +++++++++++++++++++++++++---------------- 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 01998196..7a31f98e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -18,17 +18,21 @@ endif() set(GETOPT ${GLFW_SOURCE_DIR}/deps/getopt.h ${GLFW_SOURCE_DIR}/deps/getopt.c) +set(TINYCTHREAD ${GLFW_SOURCE_DIR}/deps/tinycthread.h + ${GLFW_SOURCE_DIR}/deps/tinycthread.c) if (APPLE) # Set fancy names for bundles add_executable(Boing MACOSX_BUNDLE boing.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("Split View" MACOSX_BUNDLE splitview.c) add_executable(Wave MACOSX_BUNDLE wave.c) set_target_properties(Boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing") 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("Split View" PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Split View") set_target_properties(Wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave") @@ -37,13 +41,14 @@ else() add_executable(boing WIN32 boing.c) add_executable(gears WIN32 gears.c) add_executable(heightmap WIN32 heightmap.c ${GETOPT}) + add_executable(particles WIN32 particles.c ${TINYCTHREAD}) add_executable(simple WIN32 simple.c) add_executable(splitview WIN32 splitview.c) add_executable(wave WIN32 wave.c) endif() 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 set_target_properties(${WINDOWS_BINARIES} PROPERTIES @@ -51,7 +56,7 @@ if (MSVC) endif() 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 MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION} diff --git a/examples/particles.c b/examples/particles.c index 403a9997..570dbddb 100644 --- a/examples/particles.c +++ b/examples/particles.c @@ -41,7 +41,11 @@ #include #include #include -#include + +#define GLFW_INCLUDE_GLU +#include + +#include // Define tokens for GL_EXT_separate_specular_color if not already defined #ifndef GL_EXT_separate_specular_color @@ -100,9 +104,9 @@ struct { float dt; // Time since last frame (s) int p_frame; // Particle physics frame number int d_frame; // Particle draw frame number - GLFWcond p_done; // Condition: particle physics done - GLFWcond d_done; // Condition: particle draw done - GLFWmutex particles_lock; // Particles data sharing mutex + cnd_t p_done; // Condition: particle physics done + cnd_t d_done; // Condition: particle draw done + mtx_t particles_lock; // Particles data sharing mutex } thread_sync; @@ -456,11 +460,12 @@ void DrawParticles( double t, float dt ) if( multithreading ) { // 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 ) { - glfwWaitCond( thread_sync.p_done, thread_sync.particles_lock, - 0.1 ); + struct timespec ts = { 0, 100000000 }; + cnd_timedwait( &thread_sync.p_done, &thread_sync.particles_lock, + &ts ); } // Store the frame time and delta time for the physics thread @@ -563,8 +568,8 @@ void DrawParticles( double t, float dt ) // thread if( multithreading ) { - glfwUnlockMutex( thread_sync.particles_lock ); - glfwSignalCond( thread_sync.d_done ); + mtx_unlock( &thread_sync.particles_lock ); + cnd_signal( &thread_sync.d_done ); } // Draw final batch of particles (if any) @@ -897,7 +902,7 @@ void Draw( double t ) // Resize() - GLFW window resize callback function //======================================================================== -void GLFWCALL Resize( int x, int y ) +void Resize( GLFWwindow* window, int x, int y ) { width = x; 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 //======================================================================== -void GLFWCALL KeyFun( int key, int action ) +void KeyFun( GLFWwindow* window, int key, int scancode, int action, int mods ) { if( action == GLFW_PRESS ) { switch( key ) { - case GLFW_KEY_ESC: + case GLFW_KEY_ESCAPE: running = 0; break; - case 'W': + case GLFW_KEY_W: wireframe = !wireframe; glPolygonMode( GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL ); @@ -933,18 +938,19 @@ void GLFWCALL KeyFun( int key, int action ) // PhysicsThreadFun() - Thread for updating particle physics //======================================================================== -void GLFWCALL PhysicsThreadFun( void *arg ) +int PhysicsThreadFun( void *arg ) { while( running ) { // Lock mutex - glfwLockMutex( 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 ) { - glfwWaitCond( thread_sync.d_done, thread_sync.particles_lock, - 0.1 ); + struct timespec ts = { 0, 100000000 }; + cnd_timedwait( &thread_sync.d_done, &thread_sync.particles_lock, + &ts ); } // No longer running? @@ -960,9 +966,11 @@ void GLFWCALL PhysicsThreadFun( void *arg ) thread_sync.p_frame ++; // Unlock mutex and signal drawing thread - glfwUnlockMutex( thread_sync.particles_lock ); - glfwSignalCond( thread_sync.p_done ); + mtx_unlock( &thread_sync.particles_lock ); + cnd_signal( &thread_sync.p_done ); } + + return 0; } @@ -974,7 +982,8 @@ int main( int argc, char **argv ) { int i, frames, benchmark; double t0, t; - GLFWthread physics_thread = 0; + thrd_t physics_thread = 0; + GLFWwindow* window; // Use multithreading by default, but don't benchmark multithreading = 1; @@ -1028,24 +1037,25 @@ int main( int argc, char **argv ) } // 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" ); glfwTerminate(); exit( EXIT_FAILURE ); } - // Set window title - glfwSetWindowTitle( "Particle engine" ); + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - // Disable VSync (we want to get as high FPS as possible!) + glfwMakeContextCurrent(window); glfwSwapInterval( 0 ); // Window resize callback function - glfwSetWindowSizeCallback( Resize ); + glfwSetWindowSizeCallback( window, Resize ); // Set keyboard input callback function - glfwSetKeyCallback( KeyFun ); + glfwSetKeyCallback( window, KeyFun ); // Upload particle texture glGenTextures( 1, &particle_tex_id ); @@ -1099,10 +1109,15 @@ int main( int argc, char **argv ) { thread_sync.p_frame = 0; thread_sync.d_frame = 0; - thread_sync.particles_lock = glfwCreateMutex(); - thread_sync.p_done = glfwCreateCond(); - thread_sync.d_done = glfwCreateCond(); - physics_thread = glfwCreateThread( PhysicsThreadFun, NULL ); + mtx_init(&thread_sync.particles_lock, mtx_timed); + cnd_init(&thread_sync.p_done); + cnd_init(&thread_sync.d_done); + + if (thrd_create( &physics_thread, PhysicsThreadFun, NULL ) != thrd_success) + { + glfwTerminate(); + exit(EXIT_FAILURE); + } } // Main loop @@ -1117,10 +1132,11 @@ int main( int argc, char **argv ) Draw( t ); // Swap buffers - glfwSwapBuffers(); + glfwSwapBuffers(window); + glfwPollEvents(); // Check if window was closed - running = running && glfwGetWindowParam( GLFW_OPENED ); + running = running && !glfwWindowShouldClose( window ); // Increase frame count frames ++; @@ -1136,7 +1152,7 @@ int main( int argc, char **argv ) // Wait for particle physics thread to die if( multithreading ) { - glfwWaitThread( physics_thread, GLFW_WAIT ); + thrd_join( physics_thread, NULL ); } // Display profiling information @@ -1144,6 +1160,8 @@ int main( int argc, char **argv ) (double)frames / t ); printf( " (multithreading %s)\n", multithreading ? "on" : "off" ); + glfwDestroyWindow(window); + // Terminate OpenGL glfwTerminate();