gKit2 light
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 
18 struct 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 
35 struct 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 
48 struct 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
86 Vector 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 
97 int 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 
132 auto start= std::chrono::high_resolution_clock::now();
133 
134  // parcours tous les pixels de l'image
135  for(int y= 0; y < image.height(); y++)
136  for(int 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 
173 auto 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:112
Mesh & triangle(const unsigned int a, const unsigned int b, const unsigned int c)
Definition: mesh.cpp:192
int triangle_count() const
renvoie le nombre de triangles.
Definition: mesh.cpp:435
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet.
Definition: orbiter.h:17
int read_orbiter(const char *filename)
relit la position de l'orbiter depuis un fichier texte.
Definition: orbiter.cpp:116
Transform viewport() const
renvoie la transformation viewport actuelle. doit etre initialise par projection(width,...
Definition: orbiter.cpp:83
Transform projection(const int width, const int height, const float fov)
fixe la projection reglee pour une image d'aspect width / height, et une demi ouverture de fov degres...
Definition: orbiter.cpp:47
Transform view() const
renvoie la transformation vue.
Definition: orbiter.cpp:40
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
int write_image(const Image &image, const char *filename)
enregistre une image dans un fichier png.
Definition: image_io.cpp:85
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:137
Vector normalize(const Vector &v)
renvoie un vecteur unitaire / longueur == 1.
Definition: vec.cpp:123
Vector cross(const Vector &u, const Vector &v)
renvoie le produit vectoriel de 2 vecteurs.
Definition: vec.cpp:129
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes....
Definition: wavefront.cpp:14
int write_image_hdr(const Image &image, const char *filename)
enregistre une image dans un fichier .hdr.
Definition: image_hdr.cpp:56
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
vec3 nc
normales
Definition: mesh.h:97
triangle pour le bvh, cf fonction bounds() et intersect().
Definition: tuto_bvh.cpp:84
representation d'un vecteur 3d.
Definition: vec.h:59