gKit2 light
Loading...
Searching...
No Matches
tuto_rayons.cpp
Go to the documentation of this file.
1
3
4#include <vector>
5#include <cfloat>
6#include <chrono>
7
8#include "vec.h"
9#include "mat.h"
10#include "color.h"
11#include "image.h"
12#include "image_io.h"
13#include "image_hdr.h"
14#include "orbiter.h"
15#include "mesh.h"
16#include "wavefront.h"
17
18struct Ray
19{
20 Point o; // origine
21 Vector d; // direction
22 float tmax; // position de l'extremite, si elle existe. le rayon est un intervalle [0 tmax]
23
24 // le rayon est un segment, on connait origine et extremite, et tmax= 1
25 Ray( const Point& origine, const Point& extremite ) : o(origine), d(Vector(origine, extremite)), tmax(1) {}
26
27 // le rayon est une demi droite, on connait origine et direction, et tmax= \inf
28 Ray( const Point& origine, const Vector& direction ) : o(origine), d(direction), tmax(FLT_MAX) {}
29
30 // renvoie le point sur le rayon pour t
31 Point point( const float t ) const { return o + t * d; }
32};
33
34
35struct Hit
36{
37 float t; // p(t)= o + td, position du point d'intersection sur le rayon
38 float u, v; // p(u, v), position du point d'intersection sur le triangle
39 int triangle_id; // indice du triangle dans le mesh
40
41 Hit( ) : t(FLT_MAX), u(), v(), triangle_id(-1) {}
42 Hit( const float _t, const float _u, const float _v, const int _id ) : t(_t), u(_u), v(_v), triangle_id(_id) {}
43
44 // renvoie vrai si intersection
45 operator bool ( ) { return (triangle_id != -1); }
46};
47
48struct Triangle
49{
50 Point p; // sommet a du triangle
51 Vector e1, e2; // aretes ab, ac du triangle
52 int id; // indice du triangle
53
54 Triangle( const TriangleData& data, const int _id ) : p(data.a), e1(Vector(data.a, data.b)), e2(Vector(data.a, data.c)), id(_id) {}
55
56 /* calcule l'intersection ray/triangle
57 cf "fast, minimum storage ray-triangle intersection"
58
59 renvoie faux s'il n'y a pas d'intersection valide (une intersection peut exister mais peut ne pas se trouver dans l'intervalle [0 tmax] du rayon.)
60 renvoie vrai + les coordonnees barycentriques (u, v) du point d'intersection + sa position le long du rayon (t).
61 convention barycentrique : p(u, v)= (1 - u - v) * a + u * b + v * c
62 */
63 Hit intersect( const Ray &ray, const float tmax ) const
64 {
65 Vector pvec= cross(ray.d, e2);
66 float det= dot(e1, pvec);
67
68 float inv_det= 1 / det;
69 Vector tvec(p, ray.o);
70
71 float u= dot(tvec, pvec) * inv_det;
72 if(u < 0 || u > 1) return Hit(); // pas d'intersection
73
74 Vector qvec= cross(tvec, e1);
75 float v= dot(ray.d, qvec) * inv_det;
76 if(v < 0 || u + v > 1) return Hit(); // pas d'intersection
77
78 float t= dot(e2, qvec) * inv_det;
79 if(t > tmax || t < 0) return Hit(); // pas d'intersection
80
81 return Hit(t, u, v, id); // p(u, v)= (1 - u - v) * a + u * b + v * c
82 }
83};
84
85// renvoie la normale au point d'intersection
86Vector normal( const Mesh& mesh, const Hit& hit )
87{
88 // recuperer le triangle du mesh
89 const TriangleData& data= mesh.triangle(hit.triangle_id);
90
91 // interpoler la normale avec les coordonnées barycentriques du point d'intersection
92 float w= 1 - hit.u - hit.v;
93 Vector n= w * Vector(data.na) + hit.u * Vector(data.nb) + hit.v * Vector(data.nc);
94 return normalize(n);
95}
96
97int main( const int argc, const char **argv )
98{
99 const char *mesh_filename= "data/cornell.obj";
100 if(argc > 1)
101 mesh_filename= argv[1];
102
103 const char *orbiter_filename= "data/cornell_orbiter.txt";
104 if(argc > 2)
105 orbiter_filename= argv[2];
106
107 Orbiter camera;
108 if(camera.read_orbiter(orbiter_filename) < 0)
109 return 1;
110
111 Mesh mesh= read_mesh(mesh_filename);
112
113 // recupere les triangles dans le mesh
114 std::vector<Triangle> triangles;
115 {
116 int n= mesh.triangle_count();
117 for(int i= 0; i < n; i++)
118 triangles.emplace_back(mesh.triangle(i), i);
119 }
120
121 //
122 Image image(1024, 768);
123
124 // recupere les transformations pour generer les rayons
125 camera.projection(image.width(), image.height(), 45);
126 Transform model= Identity();
127 Transform view= camera.view();
128 Transform projection= camera.projection();
129 Transform viewport= camera.viewport();
130 Transform inv= Inverse(viewport * projection * view * model);
131
132auto start= std::chrono::high_resolution_clock::now();
133
134 // parcours tous les pixels de l'image
135 for(unsigned y= 0; y < image.height(); y++)
136 for(unsigned x= 0; x < image.width(); x++)
137 {
138 // generer le rayon au centre du pixel
139 Point origine= inv(Point(x + float(0.5), y + float(0.5), 0));
140 Point extremite= inv(Point(x + float(0.5), y + float(0.5), 1));
141 Ray ray(origine, extremite);
142
143 // calculer les intersections avec tous les triangles
144 Hit hit; // proprietes de l'intersection
145 float tmax= ray.tmax; // extremite du rayon
146 for(int i= 0; i < int(triangles.size()); i++)
147 {
148 if(Hit h= triangles[i].intersect(ray, tmax))
149 {
150 // ne conserve que l'intersection *valide* la plus proche de l'origine du rayon
151 assert(h.t > 0);
152 hit= h;
153 tmax= h.t;
154 }
155 }
156
157 #if 0
158 if(hit)
159 // coordonnees barycentriques de l'intersection
160 image(x, y)= Color(1 - hit.u - hit.v, hit.u, hit.v);
161 #endif
162
163 #if 1
164 if(hit)
165 {
166 Vector n= normal(mesh, hit);
167 // normale interpolee a l'intersection
168 image(x, y)= Color(std::abs(n.x), std::abs(n.y), std::abs(n.z));
169 }
170 #endif
171 }
172
173auto stop= std::chrono::high_resolution_clock::now();
174 int cpu= std::chrono::duration_cast<std::chrono::milliseconds>(stop - start).count();
175 printf("%dms\n", cpu);
176
177 write_image(image, "render.png");
178 write_image_hdr(image, "render.hdr");
179 return 0;
180}
representation d'une image.
Definition image.h:21
representation d'un objet / maillage.
Definition mesh.h:121
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet.
Definition orbiter.h:17
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition text.cpp:140
bool write_image_hdr(const Image &image, const char *filename, const bool flipY)
enregistre une image au format .hdr
Definition image_io.cpp:249
bool write_image(const Image &image, const char *filename, const bool flipY)
enregistre une image au format .png
Definition image_io.cpp:225
Transform Inverse(const Transform &m)
renvoie l'inverse de la matrice.
Definition mat.cpp:197
Transform Identity()
construit la transformation identite.
Definition mat.cpp:187
float dot(const Vector &u, const Vector &v)
renvoie le produit scalaire de 2 vecteurs.
Definition vec.cpp:181
Vector normalize(const Vector &v)
renvoie un vecteur unitaire / longueur == 1.
Definition vec.cpp:167
Vector cross(const Vector &u, const Vector &v)
renvoie le produit vectoriel de 2 vecteurs.
Definition vec.cpp:173
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes....
Definition wavefront.cpp:14
representation d'une couleur (rgba) transparente ou opaque.
Definition color.h:14
intersection avec un triangle.
Definition tuto_bvh2.cpp:33
representation d'un point 3d.
Definition vec.h:21
rayon.
Definition tuto_bvh2.cpp:20
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition mat.h:21
representation d'un triangle.
Definition mesh.h:95
vec3 c
positions
Definition mesh.h:96
triangle pour le bvh, cf fonction bounds() et intersect().
Definition tuto_bvh.cpp:84
representation d'un vecteur 3d.
Definition vec.h:67