Salut
Un explorateur de l'ensemble de Mandelbrot, qui peut atteindre un zoom de 10^14,
et qui utilise le multithreading pour améliorer ses performances, tout en permettant
a l'utilisateur de choisir le niveau de details qu'il veut obtenir en plus du choix
de la resolution
N'hesitez pas a laissez vos critiques
Merci
/////////////////////////////////////////////////////
// //
// MANDELBROT SET EXPLORER //
// Crée par BELAID Hocine Anis, 03/08/2016 //
// //
/////////////////////////////////////////////////////
#include <omp.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <cmath>
#include <ctime>
#include "Configuration.h"
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include "Functions.h"
using namespace std;
//Fonction de la fenetre principale
int main_window(int& factor_image)
{
int res_x(factor_image*RATIO_X), res_y(factor_image*RATIO_Y);
double focus_x(-0.5), focus_y(0), zoom(1), actual_x(-0.5), actual_y(0), zoom_coefficient(pow(10,0.2));
double span_x(RATIO_X*0.25), span_y(RATIO_Y*0.25);
//Variables concernant les couleurs et leur proportions
double var_red(0.05), var_green(0.05), var_blue(0.1), cursor_red(0.55), cursor_green(0.45), cursor_blue(0.5);
int iter_max(256);
bool not_done(true), debug(true), actualize_time(true);
sf::Clock cl;
sf::Time render_time;
sf::Texture buffer;
buffer.create(res_x,res_y);
sf::RenderWindow window(sf::VideoMode(res_x,res_y,32), "Mandelbrot set explorer", sf::Style::Close);
//Buffer servant a manipuler l'image
sf::Uint8 *pixels = new sf::Uint8[res_x*res_y*4];
//Nuancier contenant les couleurs a rendre selon le nbr d'iterations
sf::Uint8 *colors = new sf::Uint8[1024];
//Tableau representant le nombre d'iterations de chaque pixel du buffer, avec en premiere case le nbr d'iterations max
int *iterations_table = new int[res_x*res_y+1];
//Remplissaque de nuancier
fill_colors(colors,var_red,var_green,var_blue,cursor_red,cursor_green,cursor_blue);
//remplissage des zones transparentes de l'image à l'avance
for(int i(3);i<res_x*res_y*4;i+=4)
pixels[i] = 255;
//Chargement de la police
sf::Font font;
if(!font.loadFromFile("courbd.ttf"))
{
cerr << "Unable to load fonts" << endl;
return 0;
}
//Remplissage du buffer
fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
window.setFramerateLimit(60);
//Boucle principale
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if(event.type == sf::Event::Closed)
window.close();
else if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
//Mise a jour de l'image en fonction de la position du clic
sf::Clock limit;
sf::Vector2i pos = sf::Mouse::getPosition(window);
if(pos.x>=0 && pos.x<res_x && pos.y>=0 && pos.y<res_y)
{
int x_l(0), x_r(res_x), y_u(0), y_d(res_y), pos_x(pos.x - (res_x+1)/2), pos_y((res_y+1)/2 - pos.y);
if(pos_x!=0 && pos_y!=0)
{
if(pos_x >= 0 && pos_y >= 0)
{
x_r -= pos_x;
y_u += pos_y;
}
else if(pos_x < 0 && pos_y > 0)
{
x_l -= pos_x;
y_u += pos_y;
}
else if(pos_x < 0 && pos_y < 0)
{
x_l -= pos_x;
y_d += pos_y;
}
else if(pos_x > 0 && pos_y < 0)
{
x_r -= pos_x;
y_d += pos_y;
}
focus_x += static_cast<double>(pos.x*span_x)/res_x - span_x/2;
focus_y += span_y/2 - static_cast<double>(pos.y*span_y)/res_y;
move_buffer(pixels,res_x,res_y,-pos_x,-pos_y, iterations_table);
not_done = true;
cl.restart();
fill_buffer(x_l,x_r,y_u,y_d,pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
}
}
}
else if (event.type == sf::Event::MouseMoved)
{
//Mise a jour puis affichage de la position de la souris
sf::Vector2i pos = sf::Mouse::getPosition(window);
if(pos.x>=0 && pos.x<res_x && pos.y>=0 && pos.y<res_y)
{
actual_x = static_cast<double>(pos.x*span_x)/res_x - span_x/2 + focus_x;
actual_y = span_y/2 - static_cast<double>(pos.y*span_y)/res_y + focus_y;
not_done = true;
actualize_time = false;
}
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Add) || sf::Keyboard::isKeyPressed(sf::Keyboard::F6))
{
//Zoom+
zoom*=zoom_coefficient;
span_x = RATIO_X/(4*zoom);
span_y= RATIO_Y/(4*zoom);
cl.restart();
if(iter_max > 512)
{
fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,512);
increase_iterations(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
}
else
fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
not_done = true;
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Subtract) || sf::Keyboard::isKeyPressed(sf::Keyboard::F5))
{
//Zoom-
zoom/=zoom_coefficient;
span_x = RATIO_X/(4*zoom);
span_y = RATIO_Y/(4*zoom);
cl.restart();
if(iter_max > 512)
{
fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,512);
increase_iterations(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
}
else
fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
not_done = true;
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::R))
{
//Reinitialisation de la vue
iter_max = 256;
zoom = 1;
span_x = RATIO_X*0.25;
span_y = RATIO_Y*0.25;
focus_x = -0.5;
focus_y = 0;
not_done = true;
cl.restart();
fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::F2))
{
//Double le nbr d'iterations
if(iter_max<ITER_MAX_MAX)
{
iter_max*=2;
cl.restart();
increase_iterations(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
not_done = true;
}
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::F1))
{
//Divise par 2 le nbr d'iterations
if(iter_max>=ITER_MIN)
{
iter_max/=2;
cl.restart();
decrease_iterations(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
not_done = true;
}
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::H) && debug)
{
//Cache le panneau d'informations
debug = false;
not_done = true;
actualize_time = false;
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) && !debug)
{
//Affiche les panneau d'informations
cl.restart();
debug = true;
not_done = true;
actualize_time = false;
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::P))
{
//Ouvre la fenetre de parametres, et teste si elle renvoie une demande de redimensionnement de la fenetre pricipale
if(set_configuration(factor_image,colors,var_red,var_green,var_blue,cursor_red,cursor_green,cursor_blue))
{
cl.restart();
fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
}
else
{
//Si oui, on ferme la fenentre et on retoure dans le main
window.close();
delete [] iterations_table;
delete [] colors;
delete [] pixels;
return factor_image;
}
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::C))
{
//Screenshot
stringstream ss;
ss << "( " << setprecision(20) << focus_x << " , " << setprecision(20) << focus_y << " )";
string title(ss.str());
sf::Image im;
im.create(res_x,res_y,pixels);
if(im.saveToFile(ss.str()+".bmp"))
cout << "Screenshot saved succesfully : " << title << endl;
else
cout << "Unable to save screenshot" << endl;
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
//Fermeture de la fenetre
window.close();
}
}
if(not_done)
{
//Mise a jour du buffer
buffer.update(pixels,res_x,res_y,0,0);
buffer.setSmooth(true);
sf::Sprite sp(buffer);
window.clear();
window.draw(sp);
if(debug)
{
if(actualize_time)
render_time = cl.getElapsedTime();
debugging(window,font,res_x,res_y,focus_x,focus_y,actual_x,actual_y,zoom,iter_max,render_time);
}
window.display();
not_done = false;
actualize_time = true;
}
}
return 0;
}
int main(void)
{
int factor_image(40), return_value;
return_value = main_window(factor_image);
//Si la fonction de la fenetre principale renvoie une demande de redimensionnement, on re-execute la fonction avec le parametre de reddimensionnement (return value)
while(return_value != 0)
{
return_value = main_window(return_value);
}
return 0;
}
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.