bon j'ai toujours pas fini, mais je montre quand même ou j'en suis ;)
j'ai des problème avec les vector<>, je n'arrive pas à faire de pointeur sur un vector, et quand je l'utilise sans pointeur ça plombe les performances :( donc j'ai laissé la méthode bidon pour l'instant.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | #include <iostream> #include "time.h" #include "dispositif.h" #include "raytracer.h" #include "scene.cpp" LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); void EnableOpenGL(HWND hwnd, HDC*, HGLRC*); void DisableOpenGL(HWND, HDC, HGLRC); using namespace std; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wcex; HWND hwnd; HDC hDC; HGLRC hRC; MSG msg; BOOL bQuit = FALSE; float theta = 0.0f; /* register window class */ wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_OWNDC; wcex.lpfnWndProc = WindowProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wcex.lpszMenuName = NULL; wcex.lpszClassName = "GLSample"; wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);; if (!RegisterClassEx(&wcex)) return 0; /* create main window */ hwnd = CreateWindowEx(0, "GLSample", "Raytracer", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, nCmdShow); /* enable OpenGL for the window */ EnableOpenGL(hwnd, &hDC, &hRC); PerfChrono chrono; Ecran* lcd = new Ecran(800,600); scene *scene = new scene(); lancerDeRayon* rayTracer=new lancerDeRayon(800,600); Animation *animation; Camera* macamera = scene->ajouterCamera((Position3f){0.0f, 1.0f, -10000.0f}); macamera->cibler((Vecteur){0.0f, 0.0f, 1.0f}); Lumiere* soleil = scene->ajouterLumiere((Position3f){ 0.0, 240.0, -1000.0}); soleil->colorer(1.f, 1.f, 1.f); Lumiere* lumiere = scene->ajouterLumiere((Position3f){640.0, 240.0 ,-100.0}); lumiere->colorer(0.3f, 0.3f, 0.3f); Sphere* lune = scene->ajouterSphere((Position3f){ 50.0, 290.0, 0.0}); lune->redimensionner(40); lune->indexMateriau(0); Sphere* planeteTerre = scene->ajouterSphere((Position3f){ 350.0, 290.0, 0.0}); planeteTerre->redimensionner(100); planeteTerre->indexMateriau(1); /* program main loop */ while (!bQuit) { /* check for messages */ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { /* handle or dispatch messages */ if (msg.message == WM_QUIT) { bQuit = TRUE; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } else { /* OpenGL animation code goes here */ cout<<"Frequence de l'horloge : "<<chrono.GetFreq()<<" Hz."<<endl; chrono.Start(); lune->positioner(animation->orbite(planeteTerre->Position())); lcd->diffuser(rayTracer->trace(scene)); cout<<(chrono.GetDiffNs()/1000000)<<endl; SwapBuffers(hDC); } } /* shutdown OpenGL */ DisableOpenGL(hwnd, hDC, hRC); /* destroy the window explicitly */ DestroyWindow(hwnd); return msg.wParam; } LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CLOSE: PostQuitMessage(0); break; case WM_DESTROY: return 0; case WM_KEYDOWN: { switch (wParam) { case VK_ESCAPE: PostQuitMessage(0); break; } } break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC) { PIXELFORMATDESCRIPTOR pfd; int iFormat; /* get the device context (DC) */ *hDC = GetDC(hwnd); /* set the pixel format for the DC */ ZeroMemory(&pfd, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.cDepthBits = 16; pfd.iLayerType = PFD_MAIN_PLANE; iFormat = ChoosePixelFormat(*hDC, &pfd); SetPixelFormat(*hDC, iFormat, &pfd); /* create and enable the render context (RC) */ *hRC = wglCreateContext(*hDC); wglMakeCurrent(*hDC, *hRC); } void DisableOpenGL (HWND hwnd, HDC hDC, HGLRC hRC) { wglMakeCurrent(NULL, NULL); wglDeleteContext(hRC); ReleaseDC(hwnd, hDC); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #ifndef Dispositif_loaded #define Dispositif_loaded #include <gl/gl.h> class Ecran { protected: unsigned int largeur, hauteur; public: Ecran(int Largeur, int Hauteur):largeur(Largeur), hauteur(Hauteur) { } void diffuser(unsigned char* cellulesRVB) { glDrawPixels( largeur, hauteur, GL_RGB, GL_UNSIGNED_BYTE, cellulesRVB); } }; #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | #ifndef Raytracer_loaded #define Raytracer_loaded #include "geometrie.h" #include "collision.h" #include "scene.h" class lancerDeRayon { private: unsigned int largeur, hauteur; unsigned char* cellulesRVB; float profondeur; float rouge , vert , bleu ; float coef ; int niveau ; Collision *collision; public: lancerDeRayon(unsigned int Largeur,unsigned int Hauteur): largeur(Largeur), hauteur(Hauteur), cellulesRVB((unsigned char *) malloc( Largeur * Hauteur * 3 )) { } unsigned char* trace(scene* scene) { int z=-1; for (int y = 0; y <hauteur; ++y)//on parcours chaque ligne { for (int x = 0; x < largeur; ++x)//pour chaque ligne, on parcours toutes ses colonnes {// on traite le pixel rouge = 0, vert = 0, bleu = 0; coef = 1.0f; niveau = 0; profondeur = 20000.0f; // on initialise le rayon en fonction de la position de la camera et de sa direction Rayon rayonActuel = { scene->positionCamera()+ (Vecteur){ float(x), float(y), 0.f } , scene->directionCamera()}; do { // on cherche si un objet se trouve dans le champ du rayon int indexSphere= -1; for (unsigned int i = 0; i < scene->nbSpheres(); ++i) if (collision->sphere(rayonActuel, scene->sphereId(i), profondeur))//en cas d'intersection on definit sa distance dans "profondeur" indexSphere = i; if (indexSphere == -1)// si aucun objet n'est trouver on arrete le traitement et on passe au pixel suivant break; //en cas d'intersection avec un objet, on va defininir un nouveau rayon partant de cet objet Position3f nouveauDepart = rayonActuel.depart + profondeur * rayonActuel.direction; //on calcule la normale au point d'intersection Vecteur normale = calculerNormale(nouveauDepart,scene->positionSphereId(indexSphere)); if( normale == 0)break; //on recupere le materiau Materiau materiauActuel = *scene->materiauId(scene->materiauSphere(indexSphere)); // calcul de la valeur d'éclairement au point for (unsigned int j = 0; j < scene->nbLumieres(); ++j) { Lumiere lumiereActuel = *scene->lumiereId(j); Vecteur distance = lumiereActuel.Position() - nouveauDepart; if (normale * distance <= 0.0f) continue; float profondeur = sqrtf(distance * distance); if ( profondeur <= 0.0f ) continue; Rayon rayonDeLumiere; rayonDeLumiere.depart = nouveauDepart; rayonDeLumiere.direction = (1/profondeur) * distance; // calcul des ombres bool ombre = false; for (unsigned int i = 0; i < scene->nbLumieres(); ++i) { if (collision->sphere(rayonDeLumiere, scene->sphereId(i), profondeur)) { ombre = true; break; } } if (!ombre) { // lambert float lambert = (rayonDeLumiere.direction * normale) * coef; rouge += lambert * lumiereActuel.Rouge() * materiauActuel.rouge; vert += lambert * lumiereActuel.Vert() * materiauActuel.vert; bleu += lambert * lumiereActuel.Bleu() * materiauActuel.bleu; } } // on itére sur la prochaine reflexion coef *= materiauActuel.reflection; float reflet = 2.0f * (rayonActuel.direction * normale); rayonActuel.depart = nouveauDepart; rayonActuel.direction = rayonActuel.direction - reflet * normale; niveau++; } while ((coef > 0.0f) && (niveau < 10)); cellulesRVB[z++]=((unsigned char)min(rouge*255.0f,255.0f)); cellulesRVB[z++]=((unsigned char)min(vert*255.0f, 255.0f)); cellulesRVB[z++]=((unsigned char)min(bleu*255.0f, 255.0f)); } } return cellulesRVB; } }; #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #ifndef Scene_loaded #define Scene_loaded #include "materiau.h" #include "lumiere.h" #include "animation.h" #include "camera.h" class scene { private: unsigned int nbmateriaux, nbspheres, nblumieres, nbcameras, CameraActuel; Materiau listeMateriaux[3]; Sphere listeSpheres[3]; Lumiere listeLumieres[3]; Camera listecameras[3]; public: scene(); Camera* ajouterCamera(Position3f position); Sphere* ajouterSphere(Position3f position); Lumiere* ajouterLumiere(Position3f position); //pour le raytracer Position3f positionCamera()const; Vecteur directionCamera()const; int nbMateriaux()const; int nbSpheres()const; int nbLumieres()const; Sphere* sphereId(unsigned int i); Materiau* materiauId(unsigned int i); Lumiere* lumiereId(unsigned int i); unsigned int materiauSphere(unsigned int id)const; Position3f positionSphereId(unsigned int id)const; }; #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #include "scene.h" scene::scene() { nbcameras=0; nbmateriaux=3, nbspheres=0, nblumieres=0; CameraActuel=0; listeMateriaux[0].rouge=0.0; listeMateriaux[0].vert=1.0; listeMateriaux[0].bleu=1.0; listeMateriaux[0].reflection=0.5; listeMateriaux[1].rouge=1.0; listeMateriaux[1].vert=0.0; listeMateriaux[1].bleu=1.0; listeMateriaux[1].reflection=0.5; } Camera* scene::ajouterCamera(Position3f position) { nbcameras++; listecameras[nbcameras-1].positioner(position); return &listecameras[nbcameras-1]; } Sphere* scene::ajouterSphere(Position3f position) { nbspheres++; listeSpheres[nbspheres-1].positioner(position); return &listeSpheres[nbspheres-1]; } Lumiere* scene::ajouterLumiere(Position3f position) { nblumieres++; listeLumieres[nblumieres-1].positioner(position); return &listeLumieres[nblumieres-1]; } Position3f scene::positionCamera()const { return listecameras[CameraActuel].Position(); } Vecteur scene::directionCamera()const { return listecameras[CameraActuel].direction(); } int scene::nbMateriaux()const { return nbmateriaux; } int scene::nbSpheres()const { return nbspheres; } int scene::nbLumieres()const { return nblumieres; } Sphere* scene::sphereId(unsigned int i) { return &listeSpheres[i]; } Materiau* scene::materiauId(unsigned int i) { return &listeMateriaux[i]; } Lumiere* scene::lumiereId(unsigned int i) { return &listeLumieres[i]; } unsigned int scene::materiauSphere(unsigned int id)const { return listeSpheres[id].Materiau(); } Position3f scene::positionSphereId(unsigned int id)const { return listeSpheres[id].Position(); } |
1 2 3 4 5 6 7 8 9 10 | #ifndef Materiau_loaded #define Materiau_loaded struct Materiau { float rouge, vert, bleu, reflection; }; #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #ifndef Lumiere_loaded #define Lumiere_loaded class Lumiere { private: Position3f position; float rouge, vert, bleu; public: void positioner(Position3f Position) { position = Position; } void colorer( float Rouge,float Vert,float Bleu) { rouge=Rouge; vert=Vert; bleu=Bleu; } Position3f Position()const { return position; } float Rouge()const { return rouge; } float Vert()const { return vert; } float Bleu()const { return bleu; } }; #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #ifndef Animation_loaded #define Animation_loaded class Animation { public: Animation(); Position3f orbite(Position3f centre) { static float alpha=0; alpha+=0.01; if(alpha>360)alpha=0; float distance = 200.0f; return (Position3f){distance * cos(alpha)+centre.x, centre.y, distance * sin(alpha)+centre.z}; } }; #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #ifndef Camera_loaded #define Camera_loaded class Camera { private: Position3f position; Vecteur cible; public: void positioner(Position3f Position) { position = Position; } void cibler(Vecteur Cible) { cible = Cible; } Vecteur direction()const { return cible; } Position3f Position()const { return position; } }; #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #ifndef Collision_loaded #define Collision_loaded class Collision { public: Collision(); bool sphere(const Rayon rayon, const Sphere* sphere, float &profondeur) { // intersection rayon/sphere Vecteur distance = sphere->Position() - rayon.depart; float B = rayon.direction * distance; float delta = B*B - distance * distance + sphere->Taille() * sphere->Taille(); if (delta < 0.0f) return false; float profondeur0 = B - sqrtf(delta); float profondeur1 = B + sqrtf(delta); bool colision = false; if ((profondeur0 > 0.1f) && (profondeur0 < profondeur)) { profondeur = profondeur0; colision = true; } if ((profondeur1 > 0.1f) && (profondeur1 < profondeur)) { profondeur = profondeur1; colision = true; } return colision; } }; #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | #ifndef Geometrie_loaded #define Geometrie_loaded #include <vector> #include <cmath> #include <limits> #include <algorithm> #define min(a,b) ((a)<(b)?(a):(b)) struct Position3f { float x, y, z;}; struct Vecteur {float x, y, z;}; struct Rayon { Position3f depart; Vecteur direction; }; class Sphere { private: Position3f position; float taille; int materiau; public: void positioner(Position3f Position) { position = Position; } void redimensionner (float Taille) { taille=Taille; } void indexMateriau(int index) { materiau=index; } Position3f Position()const { return position; } int Materiau()const { return materiau; } float Taille()const { return taille; } }; Position3f operator + (const Position3f&p, const Vecteur &v){return (Position3f){p.x + v.x, p.y + v.y, p.z + v.z };} Position3f operator - (const Position3f&p, const Vecteur &v){return (Position3f){p.x - v.x, p.y - v.y, p.z - v.z };} Vecteur operator - (const Position3f&p1, const Position3f &p2){return (Vecteur){p1.x - p2.x, p1.y - p2.y, p1.z - p2.z };} Vecteur operator * (float c, const Vecteur &v){ return (Vecteur) {v.x *c, v.y * c, v.z * c };} Vecteur operator - (const Vecteur&v1, const Vecteur &v2){return (Vecteur){v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };} bool operator == (const Vecteur&v1, int null) { if(v1.x==0 && v1.y==0 && v1.z==0)return true; else return false; } float operator * (const Vecteur&v1, const Vecteur &v2 ) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;} Vecteur calculerNormale(Position3f depart,Position3f direction) { Vecteur normale= depart - direction; float temp = normale * normale; if (temp == 0.0f)return (Vecteur){0,0,0}; temp = 1.0f / sqrtf(temp); return temp * normale; } #endif |