# include # include # include # undef main # include struct Contact { float temp ; Uint32 y ; Uint32 x ; }; int main(int argc, char const *argv[]) { /// [0] Requête des informations std::cout << "LANCEMENT DIFFUSION CHALEUR" << std::endl << std::endl; // [0.1] Dimensions de la fenêtre bool changement(false); Uint32 w_cmd(400), h_cmd(300); float lambda( 0.2495 ); unsigned int iteration( 1 ); std::cout << "Changer les valeurs par défaut ? (0:non, 1:oui)" << std::endl << ">>>"; std::cin >> changement; if ( changement ) { std::cout << "Hauteur de la fenêtre ?" << std::endl << ">>>"; std::cin >> h_cmd; std::cout << "Longueur de la fenêtre ?" << std::endl << ">>>"; std::cin >> w_cmd; std::cout << "Conductivité thermique ?" << std::endl << ">>>"; std::cin >> lambda; std::cout << "Nombre d'itérations par frame ?" << std::endl << ">>>"; std::cin >> iteration; } const Uint32 w( w_cmd ); const Uint32 h( h_cmd ); /// [1] SDL // [1.1] Démarrages SDL if ( SDL_Init( SDL_INIT_VIDEO ) < 0) { std::cout << "Impossible d'initialiser la SDL: " << SDL_GetError() << std::endl; return 1; } // [1.2] Préparation de fermeture atexit(SDL_Quit); // [1.3] Para-fenêtre SDL_WM_SetCaption("Diffusion Chaleur", 0); /// [2] Préparation des composants SDL // [2.1] Préparation de la fenêtre SDL_Surface* screen = SDL_SetVideoMode(w, h, 32, SDL_HWSURFACE|SDL_DOUBLEBUF); if ( !screen ) { std::cout << "Bug à l'initialisation: " << SDL_GetError() << std::endl; return 1; } // [2.2] Préparation variables SDL_Rect mouse({ 400, 200, 0, 0 }); // [2.3] Préparation surfaces // [2.4] Préparation du temps Uint32 frameRate( 60 ); Uint32 tprev(0), twait( 1000 / frameRate ), total_frame(0); bool pause( false ); // [2.5] Préparation des messages std::string msg("Victor"); /// [3] Préparation de la chaleur // [3.1] Préparation des buffers float buffer[2][h][w]; // entre 0.0f et 1.0f int current_buffer(0), next_buffer(1); // [3.2] Liste des conditions aux limites std::vector limiteur; bool trigger( false ); float temp( 1.0f ); // [3.3] Conditions initiales for ( int k(0); k < 2; k++ ) for ( Uint32 i(0); i < h; i ++ ) for ( Uint32 j(0); j < w; j ++ ) { buffer[k][i][j] = 0.0f; } /// [4] Boucle principale bool done( false ); SDL_Event event; while (!done) { // [4.1] Gestion évènements while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: done = true; break; case SDL_KEYDOWN: switch( event.key.keysym.sym ) { case SDLK_ESCAPE : done = true; break; case SDLK_BACKSPACE : std::cout << std::endl << "Destruction des points de contact." << std::endl << std::endl; limiteur.clear(); break; case SDLK_SPACE : std::cout << std::endl << "Reinscription du cas initial." << std::endl << std::endl; for ( Uint32 i(0); i < h; i ++ ) for ( Uint32 j(0); j < w; j ++ ) { buffer[current_buffer][i][j] = 0.0f; }; break; case SDLK_a : temp = 1.0f ; break; case SDLK_z : temp = 0.5f ; break; case SDLK_e : temp = 0.0f ; break; } break; case SDL_KEYUP: switch( event.key.keysym.sym ) { case SDLK_LEFT : case SDLK_RIGHT : case SDLK_DOWN : break; } break; case SDL_MOUSEMOTION: mouse.x = event.motion.x ; mouse.y = event.motion.y ; if ( trigger ) limiteur.push_back( { temp, mouse.y, mouse.x } ); break; case SDL_MOUSEBUTTONDOWN: trigger = true ; break; case SDL_MOUSEBUTTONUP: trigger = false ; break; } // end switch event type } // end of message processing // [4.2] Calculs if ( !pause ) { for ( unsigned int c(0); c < iteration ; c++ ) { // Conditions initiales for ( unsigned int k(0); k < limiteur.size(); k++ ) buffer[current_buffer][ limiteur[k].y ][ limiteur[k].x ] = limiteur[k].temp ; // Calcul for ( Uint32 i(1); i < h - 1; i ++ ) for ( Uint32 j(1); j < w - 1; j ++ ) { buffer[next_buffer][i][j] = lambda * buffer[current_buffer][i + 1][j] + lambda * buffer[current_buffer][i][j + 1] + lambda * buffer[current_buffer][i - 1][j] + lambda * buffer[current_buffer][i][j - 1] + (1.0f - 4.0f * lambda ) * buffer[current_buffer][i][j] ; if ( buffer[current_buffer][i][j] > 1.0f ) buffer[current_buffer][i][j] = 1.0f ; else if ( buffer[current_buffer][i][j] < 0.0f ) buffer[current_buffer][i][j] = 0.0f ; } // Changement de buffer current_buffer = next_buffer ; next_buffer = 1 - current_buffer ; } } // [4.3] Affichage if ( !pause ) { // Calcul for ( Uint32 i(1); i < h - 1; i ++ ) for ( Uint32 j(1); j < w - 1; j ++ ) pixelRGBA( screen, j, i, (Uint8)( buffer[current_buffer][i][j] * 255 ), 0, 0, 255 ); } SDL_Flip(screen); // [4.4] Temps total_frame ++; while( SDL_GetTicks() - tprev < twait ) { if ( SDL_GetTicks() - tprev < twait/2 ) SDL_Delay( twait/3 ); } tprev = SDL_GetTicks(); } //fin bcl principale ///[5] Destruction des composants SDL_FreeSurface( screen ); ///[6] Affichage puissance de calcul std::cout << "Performances : " << std::endl; std::cout << "> Nombre de pixels : " << w*h << std::endl; std::cout << "> Nombre total d'images : " << total_frame << std::endl; std::cout << "> Temps total : " << SDL_GetTicks() << "ms." << std::endl; std::cout << "> Moyenne par frame : " << (float)SDL_GetTicks() / total_frame << std::endl; std::cout << "> Moyenne par frame et par pixel : " << (float)SDL_GetTicks() / total_frame / w / h << std::endl; ///[7] Tableau /*for ( Uint32 i(1); i < h - 1; i ++ ) { for ( Uint32 j(1); j < w - 1; j ++ ) { std::cout << (int)(buffer[next_buffer][i][j] * 255) << ":"; } std::cout << std::endl; }*/ return 0; }