diff --git a/2.png b/2.png index 4ed86d8537c100c777481be7d82f8d453965eb80..a4930f70c5490e930d75e078e8eea0d619046e44 100644 Binary files a/2.png and b/2.png differ diff --git a/0.png b/Rapport/0.png similarity index 100% rename from 0.png rename to Rapport/0.png diff --git a/1.png b/Rapport/1.png similarity index 100% rename from 1.png rename to Rapport/1.png diff --git a/Rapport/2.png b/Rapport/2.png new file mode 100644 index 0000000000000000000000000000000000000000..4ed86d8537c100c777481be7d82f8d453965eb80 Binary files /dev/null and b/Rapport/2.png differ diff --git a/main b/main old mode 100644 new mode 100755 index c248d48d4ff0cc9440be85d18a0ca9445982a5b2..5595c74b405ef063a25f4cc3473dd2b77208437f Binary files a/main and b/main differ diff --git a/main.cpp b/main.cpp index 4b2dd71393fbaab3d4ad90b9efef769bc966087c..ccea6f982cc04d275c7727b271b51ae1a2d07a8a 100644 --- a/main.cpp +++ b/main.cpp @@ -150,7 +150,7 @@ int main() Material white(255, 255, 255, 0); Material grey(122, 122, 122, 0); Material black(0, 0, 0, 0); - Material mirror(0, 0, 0, 1); + Material mirror(255, 255, 255, 0.9); int nb_shapes = 7; float width = 100; //x @@ -168,8 +168,8 @@ int main() shapes[2] = new Quad(white, Vector3f(width/2, height, depth/2), width, 0, depth); //plafond shapes[3] = new Quad(cyan, Vector3f(0, height/2, depth/2), 0, height, depth); //mur droit shapes[4] = new Quad(green, Vector3f(width/2, 0, depth/2), width, 0, depth); //sol - shapes[5] = new Quad(red, Vector3f(20, 15, 15), 10, 10, 10); //cube - shapes[6] = new Sphere(blue, Vector3f(75, 20, 70), 20); //sphere + shapes[5] = new Quad(mirror, Vector3f(15, 25, 20), 10, 10, 10); //cube + shapes[6] = new Sphere(mirror, Vector3f(75, 20, 70), 20); //sphere Camera camera(Vector3f(width/2, height/2, -50), Vector3f(0, 0, 1)); //on met la caméra un peu en recul Ray3f source(Vector3f(width/2, height-1, depth/3), Vector3f(0, -1, 0)); //lumière au plafond @@ -187,9 +187,6 @@ int main() std::cout<<"direction "<<shapes[0]->reflect(light).direction()<<std::endl; }*/ - - - //----------CALCUL ET SAUVEGARDE DE L'IMAGE---------- std::cout << "Création de l'image..." << std::endl; std::string filename = "2.png"; @@ -199,6 +196,8 @@ int main() //----------LIBERATION DE LA MEMOIRE---------- for (int i=0; i<nb_shapes; i++) delete [] shapes[i]; + + } catch (const char* s) diff --git a/scene.cpp b/scene.cpp index f324f8fa7222fca69160cc67a3148c537f10cf0d..f8c584d252f37bad24161708687db13bfbe89b59 100644 --- a/scene.cpp +++ b/scene.cpp @@ -2,6 +2,8 @@ #include <png.h> #include <math.h> //fmin +#include <iostream> + Scene::Scene(Camera camera, Shape* *shapes, Ray3f source) : camera_(camera), shapes_(shapes), source_(source) @@ -47,11 +49,10 @@ Ray3f Scene::source() const return source_; } - - +/* void Scene::render(int width, int height, int nb_pixel_row, int nb_pixel_col, int nb_shapes, char* filename) { - /*--------------------------------Copié de la doc de libpng-------------------------------------*/ + /*--------------------------------Copié de la doc de libpng-------------------------------------*//* FILE *f = fopen(filename, "wb"); if (!f) throw "Echec de la création du fichier"; @@ -71,7 +72,7 @@ void Scene::render(int width, int height, int nb_pixel_row, int nb_pixel_col, in } png_init_io(png_ptr, f); - /*----------------------------------------------------------------------------------------------*/ + /*----------------------------------------------------------------------------------------------*//* //Set header @@ -175,10 +176,216 @@ void Scene::render(int width, int height, int nb_pixel_row, int nb_pixel_col, in png_write_end(png_ptr, NULL); + fclose(f); +}*/ + + +void Scene::render(int width, int height, int nb_pixel_row, int nb_pixel_col, int nb_shapes, char* filename) +{ + /*--------------------------------Copié de la doc de libpng-------------------------------------*/ + FILE *f = fopen(filename, "wb"); + if (!f) throw "Echec de la création du fichier"; + + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + fclose(f); + throw "Echec allocation png_ptr"; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + fclose(f); + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + throw "Echec allocation info_ptr"; + } + + png_init_io(png_ptr, f); + /*----------------------------------------------------------------------------------------------*/ + + + //Set header + png_set_IHDR(png_ptr, info_ptr, nb_pixel_row, nb_pixel_col, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + //Set text + png_text title_text; + title_text.compression = PNG_TEXT_COMPRESSION_NONE; + title_text.text = filename; + png_set_text(png_ptr, info_ptr, &title_text, 0); + + png_write_info(png_ptr, info_ptr); + + + //Mémoire allouée pour une ligne de pixels (rgb => 3 bytes par pixel) + png_bytep row = (png_bytep) png_malloc(png_ptr, 3*nb_pixel_row*sizeof(png_byte)); + + + float pw = (float) width / (float) nb_pixel_col; //largeur d'un pixel + float ph = (float) height / (float) nb_pixel_row; //hauteur d'un pixel + float min_dist; + float hit_dist; + + int ref_max=3; + Ray3f *ray[ref_max]; + float shine[ref_max-1]; + float coef[ref_max-1]; + + + for (int i=nb_pixel_col-1; i>=0; i--) //on remplit l'image par le bas à droite + { + for (int j=0; j<nb_pixel_row; j++) + { + min_dist = 1000; + Vector3f Pij(j*pw, i*ph, 0); //point de la grille par laquelle on regarde + Ray3f camera_to_grid(camera_.position(), Pij-camera_.position()); + ray[0]=new Ray3f(camera_to_grid); + + nb_reflected(ray, nb_shapes, ref_max, shine); + coeff(shine, coef, ref_max); + + + + row[3*(nb_pixel_row-1-j)] = 0; + row[3*(nb_pixel_row-1-j) + 1] = 0; + row[3*(nb_pixel_row-1-j) + 2] = 0; + + for(int r=0;r<ref_max-1;r++) + { + for (int k=0; k<nb_shapes; k++) + { + if (shapes_[k]->is_hit(*ray[r])) + { + Ray3f reflected(shapes_[k]->reflect(*ray[r])); + hit_dist = dist(reflected.origin() , camera_.position()); + + if ( hit_dist < min_dist ) //on regarde l'objet le plus proche de la caméra + { + min_dist = hit_dist; + + bool shadow = false; + Ray3f reflect_to_source(reflected.origin(), source_.origin()-reflected.origin()); + + + for (int l=0; l<nb_shapes; l++) + { + if (l != k) //pour éviter que l'objet se cache lui-même + if (shapes_[l]->is_hit(reflect_to_source)) + if ( dist(reflected.origin() , shapes_[l]->reflect(reflect_to_source).origin()) + < dist(reflected.origin() , source_.origin()) ) + { + shadow = true; + break; + } + } + + //intensité pour harmoniser les ombres selon la distance + float intensity = dist(reflected.origin(), source_.origin()); + intensity = 5000/(intensity*intensity); + + if (shadow) + { + row[3*(nb_pixel_row-1-j)] = row[3*(nb_pixel_row-1-j)] + coef[r]*fmin(50, 50*intensity); + row[3*(nb_pixel_row-1-j) + 1] = row[3*(nb_pixel_row-1-j) + 1] + coef[r]*fmin(50, 50*intensity); + row[3*(nb_pixel_row-1-j) + 2] = row[3*(nb_pixel_row-1-j) + 2] + coef[r]*fmin(50, 50*intensity); + } + + else + { + Ray3f source_to_reflect(source_.origin(), reflected.origin()-source_.origin()); + + //self_shadow + //au lieu de diviser par une constante (2.) diviser par l'angle ? + if ( dist(reflect_to_source.origin() , shapes_[k]->reflect(source_to_reflect).origin()) > 0.05 ) + { + row[3*(nb_pixel_row-1-j)] = row[3*(nb_pixel_row-1-j)] + coef[r]*fmin(shapes_[k]->matter().r()/2. * intensity, shapes_[k]->matter().r()/2.); + row[3*(nb_pixel_row-1-j) + 1] =row[3*(nb_pixel_row-1-j) + 1] + coef[r]*fmin(shapes_[k]->matter().g()/2. * intensity, shapes_[k]->matter().g()/2.); + row[3*(nb_pixel_row-1-j) + 2] =row[3*(nb_pixel_row-1-j) + 2] + coef[r]*fmin(shapes_[k]->matter().b()/2. * intensity, shapes_[k]->matter().b()/2.); + } + + else //il faut rajouter la réflexion et l'angle + { + row[3*(nb_pixel_row-1-j)] = row[3*(nb_pixel_row-1-j)] + coef[r]*fmin(shapes_[k]->matter().r() * intensity, 255.); + row[3*(nb_pixel_row-1-j) + 1] = row[3*(nb_pixel_row-1-j) + 1] + coef[r]*fmin(shapes_[k]->matter().g() * intensity, 255.); + row[3*(nb_pixel_row-1-j) + 2] = row[3*(nb_pixel_row-1-j) + 2] + coef[r]*fmin(shapes_[k]->matter().b() * intensity, 255.); + } + } + } + } + } + } + } + + png_write_row(png_ptr, row); + } + + png_write_end(png_ptr, NULL); + + for (int r=0; r<ref_max;r++) + delete[] ray[r]; + + fclose(f); } + +int Scene::nb_reflected(Ray3f **ray, int nb_shapes, int ref_max, float* shine){ + + bool vide=false; + + float min_dist; + float hit_dist; + + for(int r=0;r<(ref_max-1);r++) + { + shine[r]=0.0; + } + + + for(int r=0;r<(ref_max-1);r++) + { + min_dist=1000; + for (int k=0; k<nb_shapes; k++) + { + + if (shapes_[k]->is_hit(*ray[r])) + { + Ray3f reflected(shapes_[k]->reflect(*ray[r])); + hit_dist = dist(reflected.origin() , camera_.position()); + + + if ( hit_dist < min_dist ) //on regarde l'objet le plus proche de la caméra + { + min_dist = hit_dist; + + ray[r+1]=new Ray3f(reflected); + + shine[r]=shapes_[k]->matter().shiness(); + + } + } + } + } +} + + +void Scene::coeff(float* shine, float* coef, int ref_max) +{ + + for(int r=0;r<ref_max;r++) + { + coef[r]=1; + for(int i=0;i<r;i++) + { + coef[r]=coef[r]*shine[i]; + } + coef[r]=coef[r]*(1-shine[r]); + } +} + + + /*std::ostream & operator<<(std::ostream & st, const Scene & s) { st << "camera" << std::endl << s.camera() << std::endl; diff --git a/scene.h b/scene.h index b8e62d810db0c4eb3a9d41c0918d364d44629da0..a05bc5429c269629460add5403f7278181952a5f 100644 --- a/scene.h +++ b/scene.h @@ -33,6 +33,8 @@ class Scene Ray3f source() const; void render(int width, int height, int nb_pixel_row, int nb_pixel_col, int nb_shapes, char* filename); + int nb_reflected(Ray3f **ray, int nb_shapes, int ref_max, float* shine); + void coeff(float* shine, float* coef, int ref_max); };