gKit2 light
Classes | Functions
gltf.h File Reference

scene glTF. More...

#include <vector>
#include "vec.h"
#include "color.h"
#include "mesh.h"
#include "image_io.h"

Go to the source code of this file.

Classes

struct  GLTFCamera
 description d'une camera. More...
 
struct  GLTFLight
 description d'une source de lumiere. More...
 
struct  GLTFMaterial
 
struct  GLTFPrimitives
 groupe de triangles d'un maillage. chaque groupe est associe a une matiere. More...
 
struct  GLTFMesh
 description d'un maillage. More...
 
struct  GLTFInstances
 instances d'un maillage. More...
 
struct  GLTFNode
 position et orientation d'un maillage dans la scene. More...
 
struct  GLTFScene
 

Functions

Mesh read_gltf_mesh (const char *filename)
 charge un fichier .gltf et construit un mesh statique, sans animation. More...
 
std::vector< GLTFCameraread_gltf_cameras (const char *filename)
 charge un fichier .gltf renvoie les cameras. More...
 
std::vector< GLTFLightread_gltf_lights (const char *filename)
 charge un fichier .gltf et renvoie les sources de lumiere ponctuelles. More...
 
std::vector< GLTFMaterialread_gltf_materials (const char *filename)
 charge un fichier .gltf et renvoie les matieres. More...
 
std::vector< ImageDataread_gltf_images (const char *filename)
 charge un fichier .gltf et charge les images referencees par les matieres. More...
 
GLTFScene read_gltf_scene (const char *filename)
 charge un fichier .gltf et construit une scene statique, sans animation. More...
 

Detailed Description

scene glTF.

Definition in file gltf.h.


Class Documentation

◆ GLTFCamera

struct GLTFCamera

description d'une camera.

Definition at line 19 of file gltf.h.

Class Members
float fov
float aspect
float znear
float zfar
Transform view
Transform projection

◆ GLTFLight

struct GLTFLight

description d'une source de lumiere.

Definition at line 34 of file gltf.h.

Class Members
Point position
Color emission
float intensity

◆ GLTFPrimitives

struct GLTFPrimitives

groupe de triangles d'un maillage. chaque groupe est associe a une matiere.

Definition at line 98 of file gltf.h.

Class Members
int primitives_mode triangles.
int primitives_index indice unique.
int material_index indice de la matiere des primitives.
Point pmin
Point pmax points extremes de l'englobant dans le repere objet
vector< unsigned > indices
vector< vec3 > positions
vector< vec2 > texcoords
vector< vec3 > normals

◆ GLTFMesh

struct GLTFMesh

description d'un maillage.

Definition at line 114 of file gltf.h.

Class Members
vector< GLTFPrimitives > primitives groupes de triangles associes a une matiere.
Point pmin
Point pmax points extremes de l'englobant dans le repere objet

◆ GLTFInstances

struct GLTFInstances

instances d'un maillage.

Definition at line 121 of file gltf.h.

Class Members
vector< Transform > transforms transformation model de chaque instance
int mesh_index indice du maillage instancie.

◆ GLTFNode

struct GLTFNode

position et orientation d'un maillage dans la scene.

Definition at line 128 of file gltf.h.

Class Members
Transform model transformation model pour dessiner le maillage.
int mesh_index indice du maillage.

Function Documentation

◆ read_gltf_mesh()

Mesh read_gltf_mesh ( const char *  filename)

charge un fichier .gltf et construit un mesh statique, sans animation.

Definition at line 19 of file gltf.cpp.

20 {
21  printf("loading glTF mesh '%s'...\n", filename);
22 
23  cgltf_options options= { };
24  cgltf_data *data= nullptr;
25  cgltf_result code= cgltf_parse_file(&options, filename, &data);
26  if(code != cgltf_result_success)
27  {
28  printf("[error] loading glTF mesh '%s'...\n", filename);
29  return Mesh::error();
30  }
31 
32  if(cgltf_validate(data) != cgltf_result_success)
33  {
34  printf("[error] invalid glTF mesh '%s'...\n", filename);
35  return Mesh::error();
36  }
37 
38  code= cgltf_load_buffers(&options, data, filename);
39  if(code != cgltf_result_success)
40  {
41  printf("[error] loading glTF buffers...\n");
42  return Mesh::error();
43  }
44 
45  //
46  std::vector<unsigned> indices;
47  std::vector<int> material_indices;
48  std::vector<vec3> positions;
49  std::vector<vec2> texcoords;
50  std::vector<vec3> normals;
51  std::vector<vec4> colors;
52 
53  Materials materials;
54 
55  // textures
56  for(unsigned i= 0; i < data->images_count; i++)
57  {
58  if(data->images[i].uri)
59  {
60  printf("texture '%s'...\n", data->images[i].uri);
61  materials.insert_texture(data->images[i].uri);
62  }
63  else if(data->images[i].buffer_view)
64  {
65  //~ cgltf_buffer_view *view= data->images[i].buffer_view;
66  //~ assert(view->buffer->data);
67  //~ printf(" [%u] %s offset %lu size %lu, type '%s'\n", i, data->images[i].name, view->offset, view->size, data->images[i].mime_type);
68 
69  //~ SDL_RWops *read= SDL_RWFromConstMem((uint8_t *) view->buffer->data + view->offset, view->size);
70  //~ assert(read);
71 
72  // extraire la texture du glb...
73 
74  cgltf_buffer_view *view= data->images[i].buffer_view;
75  //~ printf("buffer %d/%d, offset %lu size %lu\n", int(std::distance(data->buffers, view->buffer)), int(data->buffers_count), view->offset, view->size);
76  //~ printf(" type '%s'\n", data->images[i].mime_type);
77 
78  if(!view->buffer->uri)
79  {
80  char tmp[1024];
81  if(data->images[i].name && data->images[i].name[0])
82  sprintf(tmp, "%s%s", pathname(filename).c_str(), data->images[i].name);
83  else
84  sprintf(tmp, "%stexture%d.png", pathname(filename).c_str(), i);
85 
86  printf("packed texture '%s'...\n", tmp);
87  materials.insert_texture(tmp);
88 
89  #if 0
90  if(strcmp(data->images[i].mime_type, "image/png") == 0)
91  strcat(tmp, ".png");
92  else if(strcmp(data->images[i].mime_type, "image/jpg") == 0)
93  strcat(tmp, ".jpg");
94  else
95  strcat(tmp, ".raw"); // ??
96 
97  printf("unpacking glb texture '%s' to '%s'...\n", data->images[i].name, tmp);
98 
99  FILE *out= fopen(tmp, "wb");
100  if(out)
101  {
102  if(fwrite((char *) view->buffer->data + view->offset, view->size, 1, out) != 1)
103  printf("[error] unpacking glb texture '%s' to '%s'...\n", data->images[i].name, tmp);
104 
105  fclose(out);
106  }
107 
108  // ultra moche, utiliser les RWops de sdl... pour lire l'image directement en memoire...
109  // retourner l'image, origine en bas a gauche pour opengl
110  ImageData image= read_image_data(tmp);
111  image= flipY(image);
112 
113  if(char *ext= strrchr(tmp, '.'))
114  strcpy(ext, "_flip.png");
115 
116  printf("writing flipped texture '%s'...\n", tmp);
117  write_image_data(image, tmp);
118 
119  materials.insert_texture(tmp);
120  assert(data->images[i].uri == nullptr);
121  data->images[i].uri= strdup(tmp); // nomme la texture / cf analyse des matieres
122  #endif
123  }
124  }
125  }
126 
127  // materials
128  for(unsigned i= 0; i < data->materials_count; i++)
129  {
130  cgltf_material *material= &data->materials[i];
131  //~ printf("materials[%u]: '%s'\n", i, material->name);
132 
133  Material m(Color(0.8));
134  if(material->has_pbr_metallic_roughness)
135  {
136  cgltf_pbr_metallic_roughness *pbr= &material->pbr_metallic_roughness;
137  //~ printf(" pbr metallic roughness\n");
138  //~ printf(" base color %f %f %f %f\n", pbr->base_color_factor[0], pbr->base_color_factor[1], pbr->base_color_factor[2], pbr->base_color_factor[3]);
139  //~ printf(" texture %d\n", pbr->base_color_texture.texture ? int(std::distance(data->images, pbr->base_color_texture.texture->image)) : -1);
140  //~ printf(" metallic %f, roughness %f\n", pbr->metallic_factor, pbr->roughness_factor);
141  //~ printf(" texture %d\n", pbr->metallic_roughness_texture.texture ? int(std::distance(data->images, pbr->metallic_roughness_texture.texture->image)) : -1);
142 
143  Color color= Color(pbr->base_color_factor[0], pbr->base_color_factor[1], pbr->base_color_factor[2], pbr->base_color_factor[3]);
144  float metallic= pbr->metallic_factor;
145  float roughness= pbr->roughness_factor;
146 
147  // conversion metallic-roughness vers diffuse-specular + Blinn-Phong
148  // metaux { diffuse= black, specular= color }
149  // non - metaux { diffuse= color, specular= 0.04 }
150  m.diffuse= color * (1 - metallic) + metallic * Black();
151  m.specular= Color(0.04) * (1 - metallic) + color * metallic;
152 
153  // conversion roughness vers exposant Blinn-Phong
154  m.ns= 2 / (roughness * roughness * roughness * roughness) - 2;
155  if(m.ns < float(1.1))
156  m= Material(m.diffuse);
157  // les valeurs sont habituellement dans les textures metallic_roughness... utiliser une matiere diffuse + texture...
158 
159  //~ printf(" | diffuse %f %f %f, specular %f %f %f, ns %f\n",
160  //~ m.diffuse.r, m.diffuse.g, m.diffuse.b,
161  //~ m.specular.r, m.specular.g, m.specular.b,
162  //~ m.ns);
163 
164  if(pbr->base_color_texture.texture && pbr->base_color_texture.texture->image)
165  m.diffuse_texture= int(std::distance(data->images, pbr->base_color_texture.texture->image));
166  }
167 
168  if(!material->name)
169  {
170  char tmp[1024];
171  sprintf(tmp, "material%d", i);
172  material->name= strdup(tmp);
173  }
174 
175  materials.insert(m, material->name);
176  }
177 
178  bool mesh_has_texcoords= false;
179  bool mesh_has_normals= false;
180  bool mesh_has_colors= false;
181 
182  std::vector<float> buffer;
183  // parcourir les noeuds de la scene et transformer les meshs associes aux noeuds...
184  for(unsigned node_id= 0; node_id < data->nodes_count; node_id++)
185  {
186  cgltf_node *node= &data->nodes[node_id];
187  if(node->mesh== nullptr)
188  // pas de mesh associe
189  continue;
190 
191  // transformation vers la scene
192  float model_matrix[16];
193  cgltf_node_transform_world(node, model_matrix); // transformation globale
194 
195  Transform model;
196  model.column_major(model_matrix); // gltf organise les 16 floats par colonne...
197  Transform normal= model.normal(); // transformation pour les normales
198  //~ Transform normal= model; // transformation pour les normales
199 
200  cgltf_mesh *mesh= node->mesh;
201  // parcourir les groupes de triangles du mesh...
202  for(unsigned primitive_id= 0; primitive_id < mesh->primitives_count; primitive_id++)
203  {
204  cgltf_primitive *primitives= &mesh->primitives[primitive_id];
205  assert(primitives->type == cgltf_primitive_type_triangles);
206 
207  bool primitive_has_texcoords= false;
208  bool primitive_has_normals= false;
209  bool primitive_has_colors= false;
210  unsigned offset= positions.size();
211 
212  // matiere associee au groupe de triangles
213  int material_id= -1;
214  if(primitives->material)
215  {
216  assert(material_id < materials.count());
217  assert(materials.find(primitives->material->name) != -1);
218  material_id= materials.find(primitives->material->name);
219  }
220 
221  // indices
222  if(primitives->indices)
223  {
224  for(unsigned i= 0; i < primitives->indices->count; i++)
225  indices.push_back(offset + cgltf_accessor_read_index(primitives->indices, i));
226  assert(indices.size() % 3 == 0);
227 
228  // un indice de matiere par triplet d'indices / par triangle
229  for(unsigned i= 0; i+2 < primitives->indices->count; i+= 3)
230  material_indices.push_back(material_id);
231  assert(indices.size() / 3 == material_indices.size());
232  }
233 
234  // attributs
235  for(unsigned attribute_id= 0; attribute_id < primitives->attributes_count; attribute_id++)
236  {
237  cgltf_attribute *attribute= &primitives->attributes[attribute_id];
238 
239  if(attribute->type == cgltf_attribute_type_position)
240  {
241  assert(attribute->data->type == cgltf_type_vec3);
242 
243  buffer.resize(cgltf_accessor_unpack_floats(attribute->data, nullptr, 0));
244  cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
245 
246  // transforme les positions des sommets
247  for(unsigned i= 0; i+2 < buffer.size(); i+= 3)
248  positions.push_back( model(Point(buffer[i], buffer[i+1], buffer[i+2])) );
249  }
250 
251  if(attribute->type == cgltf_attribute_type_normal)
252  {
253  assert(attribute->data->type == cgltf_type_vec3);
254 
255  primitive_has_normals= true;
256  if(mesh_has_normals == false)
257  {
258  mesh_has_normals= true;
259  // insere une normale par defaut pour tous les sommets precedents...
260  for(unsigned i= 0; i < offset; i++)
261  normals.push_back( vec3() );
262  }
263 
264  buffer.resize(cgltf_accessor_unpack_floats(attribute->data, nullptr, 0));
265  cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
266 
267  // transforme les normales des sommets
268  for(unsigned i= 0; i+2 < buffer.size(); i+= 3)
269  normals.push_back( normal(Vector(buffer[i], buffer[i+1], buffer[i+2])) );
270  //~ assert(normals.size() == positions.size());
271  }
272 
273  if(attribute->type == cgltf_attribute_type_texcoord)
274  {
275  assert(attribute->data->type == cgltf_type_vec2);
276 
277  primitive_has_texcoords= true;
278  if(mesh_has_texcoords == false)
279  {
280  mesh_has_texcoords= true;
281  // insere des texcoords par defaut pour tous les sommets precedents
282  for(unsigned i= 0; i < offset; i++)
283  texcoords.push_back( vec2() );
284  }
285 
286  buffer.resize(cgltf_accessor_unpack_floats(attribute->data, nullptr, 0));
287  cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
288 
289  for(unsigned i= 0; i+1 < buffer.size(); i+= 2)
290  texcoords.push_back( vec2(buffer[i], buffer[i+1]) );
291  //~ assert(texcoords.size() == positions.size());
292  }
293 
294  if(attribute->type == cgltf_attribute_type_color)
295  {
296  assert(attribute->data->type == cgltf_type_vec4);
297 
298  primitive_has_colors= true;
299  if(mesh_has_colors == false)
300  {
301  mesh_has_colors= true;
302  // insere une couleur par defaut pour tous les sommtes precedents
303  for(unsigned i= 0; i < offset; i++)
304  colors.push_back( vec4(1, 1, 1, 1) );
305  }
306 
307  buffer.resize(cgltf_accessor_unpack_floats(attribute->data, nullptr, 0));
308  cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
309  for(unsigned i= 0; i+3 < buffer.size(); i+= 4)
310  colors.push_back( vec4(buffer[i], buffer[i+1], buffer[i+2], buffer[i+3]) );
311  assert(colors.size() == positions.size());
312  }
313  }
314 
315  // complete la description des attributs par defaut...
316  if(mesh_has_texcoords && primitive_has_texcoords == false)
317  for(unsigned i= offset; i < positions.size(); i++)
318  texcoords.push_back( vec2() );
319 
320  if(mesh_has_normals && primitive_has_normals == false)
321  for(unsigned i= offset; i < positions.size(); i++)
322  normals.push_back( vec3() );
323 
324  if(mesh_has_colors && primitive_has_colors == false)
325  for(unsigned i= offset; i < positions.size(); i++)
326  colors.push_back( vec4(1, 1, 1, 1) );
327  }
328  }
329 
330  cgltf_free(data);
331 
332  // reconstruit le mesh...
333  Mesh mesh(GL_TRIANGLES);
334 
335  // 1. les sommets et les attributs, si necessaire...
336  bool has_texcoords= (texcoords.size() == positions.size());
337  bool has_normals= (normals.size() == positions.size());
338  bool has_colors= (colors.size() == positions.size());
339 
340  printf("gltf %d positions, %d texcoords, %d normals\n", int(positions.size()), int(texcoords.size()), int(normals.size()));
341 
342  for(unsigned i= 0; i < positions.size(); i++)
343  {
344  if(has_texcoords) mesh.texcoord(texcoords[i]);
345  if(has_normals) mesh.normal(normals[i]);
346  if(has_colors) mesh.color(colors[i]);
347 
348  mesh.vertex(positions[i]);
349  }
350 
351  // 2. les triangles et leurs matieres, si necessaire...
352  mesh.materials(materials);
353  bool has_materials= (materials.count() > 0) && (indices.size() / 3 == material_indices.size());
354  for(unsigned i= 0; i+2 < indices.size(); i+= 3)
355  {
356  if(has_materials) mesh.material(material_indices[i / 3]);
357 
358  mesh.triangle(indices[i], indices[i+1], indices[i+2]);
359  }
360  // \bug si les triangles ne sont pas indexes, pas de matieres dans le mesh...
361 
362  return mesh;
363 }
representation d'un objet / maillage.
Definition: mesh.h:112
unsigned int vertex(const vec3 &p)
insere un sommet de position p, et ses attributs (s'ils sont definis par color(), texcoord(),...
Definition: mesh.cpp:109
Mesh & texcoord(const vec2 &uv)
definit les coordonnees de texture du prochain sommet.
Definition: mesh.cpp:98
static Mesh & error()
Definition: mesh.h:348
Mesh & material(const unsigned int id)
definit la matiere du prochain triangle. id est l'indice d'une matiere ajoutee dans materials(),...
Definition: mesh.cpp:275
Mesh & triangle(const unsigned int a, const unsigned int b, const unsigned int c)
Definition: mesh.cpp:190
Mesh & normal(const vec3 &n)
definit la normale du prochain sommet.
Definition: mesh.cpp:88
GLenum primitives() const
renvoie le type de primitives.
Definition: mesh.h:336
Mesh & color(const vec4 &c)
definit la couleur du prochain sommet.
Definition: mesh.cpp:78
const Materials & materials() const
renvoie la description des matieres.
Definition: mesh.cpp:265
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
ImageData read_image_data(const char *filename)
charge les donnees d'un fichier png. renvoie une image initialisee par defaut en cas d'echec.
Definition: image_io.cpp:216
int write_image_data(ImageData &image, const char *filename)
enregistre des donnees dans un fichier png.
Definition: image_io.cpp:229
Color Black()
utilitaire. renvoie une couleur noire.
Definition: color.cpp:31
Image flipY(const Image &image)
retourne l'image
Definition: image_io.cpp:295
float distance(const Point &a, const Point &b)
renvoie la distance etre 2 points.
Definition: vec.cpp:14
void normals(MeshData &data)
(re-) calcule les normales des sommets. utiliser avant les reindexations, cf indices() et vertices().
Definition: mesh_data.cpp:307
std::string pathname(const std::string &filename)
Definition: files.cpp:68
representation d'une couleur (rgba) transparente ou opaque.
Definition: color.h:14
stockage temporaire des donnees d'une image.
Definition: image_io.h:38
int diffuse_texture
indice de la texture de la couleur de base, ou -1.
Definition: materials.h:21
int insert(const Material &material, const char *name)
ajoute une matiere.
Definition: materials.h:54
int find(const char *name)
recherche une matiere avec son nom. renvoie son indice dans materials, ou -1.
Definition: materials.h:80
int insert_texture(const char *filename)
ajoute une texture / nom du fichier.
Definition: materials.h:68
int count() const
nombre de matieres.
Definition: materials.h:94
representation d'un point 3d.
Definition: vec.h:21
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:21
Transform & column_major(const float matrix[16])
initialise la matrice avec 16 floats organises par colonne.
Definition: mat.cpp:76
Transform normal() const
renvoie la transformation a appliquer aux normales d'un objet transforme par la matrice m.
Definition: mat.cpp:181
representation d'un vecteur 3d.
Definition: vec.h:59
vecteur generique, utilitaire.
Definition: vec.h:131
vecteur generique, utilitaire.
Definition: vec.h:146
vecteur generique 4d, ou 3d homogene, utilitaire.
Definition: vec.h:168
bool has_normals(const Hit &hit, const GLTFScene &scene)
verifie la presence des normales par sommet.
bool has_texcoords(const Hit &hit, const GLTFScene &scene)
verifie la presence des coordonnees de texture...

◆ read_gltf_cameras()

std::vector<GLTFCamera> read_gltf_cameras ( const char *  filename)

charge un fichier .gltf renvoie les cameras.

Definition at line 402 of file gltf.cpp.

403 {
404  printf("loading glTF camera '%s'...\n", filename);
405 
406  cgltf_options options= { };
407  cgltf_data *data= nullptr;
408  cgltf_result code= cgltf_parse_file(&options, filename, &data);
409  if(code != cgltf_result_success)
410  {
411  printf("[error] loading glTF mesh '%s'...\n", filename);
412  return {};
413  }
414 
415  if(cgltf_validate(data) != cgltf_result_success)
416  {
417  printf("[error] invalid glTF mesh '%s'...\n", filename);
418  return {};
419  }
420 
421  if(data->cameras_count == 0)
422  {
423  printf("[warning] no camera...\n");
424  return {};
425  }
426 
427  std::vector<GLTFCamera> cameras= read_cameras(data);
428  cgltf_free(data);
429  return cameras;
430 }

◆ read_gltf_lights()

std::vector<GLTFLight> read_gltf_lights ( const char *  filename)

charge un fichier .gltf et renvoie les sources de lumiere ponctuelles.

Definition at line 467 of file gltf.cpp.

468 {
469  printf("loading glTF lights '%s'...\n", filename);
470 
471  cgltf_options options= { };
472  cgltf_data *data= nullptr;
473  cgltf_result code= cgltf_parse_file(&options, filename, &data);
474  if(code != cgltf_result_success)
475  {
476  printf("[error] loading glTF mesh '%s'...\n", filename);
477  return {};
478  }
479 
480  if(cgltf_validate(data) != cgltf_result_success)
481  {
482  printf("[error] invalid glTF mesh '%s'...\n", filename);
483  return {};
484  }
485 
486  if(data->lights_count == 0)
487  {
488  printf("[warning] no lights...\n");
489  return {};
490  }
491 
492  std::vector<GLTFLight> lights= read_lights(data);
493  cgltf_free(data);
494  return lights;
495 }

◆ read_gltf_materials()

std::vector<GLTFMaterial> read_gltf_materials ( const char *  filename)

charge un fichier .gltf et renvoie les matieres.

Definition at line 624 of file gltf.cpp.

625 {
626  printf("loading glTF materials '%s'...\n", filename);
627 
628  cgltf_options options= { };
629  cgltf_data *data= nullptr;
630  cgltf_result code= cgltf_parse_file(&options, filename, &data);
631  if(code != cgltf_result_success)
632  {
633  printf("[error] loading glTF mesh '%s'...\n", filename);
634  return {};
635  }
636 
637  if(cgltf_validate(data) != cgltf_result_success)
638  {
639  printf("[error] invalid glTF mesh '%s'...\n", filename);
640  return {};
641  }
642 
643  if(data->materials_count ==0)
644  {
645  printf("[warning] no materials...\n");
646  return {};
647  }
648 
649  std::vector<GLTFMaterial> materials= read_materials(data);
650  cgltf_free(data);
651  return materials;
652 }
Materials read_materials(const char *filename)
charge une description de matieres, utilise par read_mesh.
Definition: wavefront.cpp:454

◆ read_gltf_images()

std::vector<ImageData> read_gltf_images ( const char *  filename)

charge un fichier .gltf et charge les images referencees par les matieres.

Definition at line 655 of file gltf.cpp.

656 {
657  printf("loading glTF images '%s'...\n", filename);
658 
659  cgltf_options options= { };
660  cgltf_data *data= nullptr;
661  cgltf_result code= cgltf_parse_file(&options, filename, &data);
662  if(code != cgltf_result_success)
663  {
664  printf("[error] loading glTF mesh '%s'...\n", filename);
665  return {};
666  }
667 
668  if(cgltf_validate(data) != cgltf_result_success)
669  {
670  printf("[error] invalid glTF mesh '%s'...\n", filename);
671  return {};
672  }
673 
674  if(data->images_count == 0)
675  {
676  printf("[warning] no images...\n");
677  return {};
678  }
679 
680  // detecte s'il faut charger aussi les buffers...
681  for(unsigned i= 0; i < data->images_count; i++)
682  if(!data->images[i].uri)
683  {
684  code= cgltf_load_buffers(&options, data, filename);
685  if(code != cgltf_result_success)
686  {
687  printf("[error] loading glTF internal images...\n");
688  cgltf_free(data);
689  return {};
690  }
691 
692  break;
693  }
694 
695 
696  std::vector<ImageData> images(data->images_count);
697 
698 #pragma omp parallel for schedule(dynamic, 1)
699  for(unsigned i= 0; i < data->images_count; i++)
700  {
701  if(data->images[i].uri)
702  {
703  //~ printf(" [%u] %s\n", i, data->images[i].uri);
704  std::string image_filename= pathname(filename) + std::string(data->images[i].uri);
705  images[i]= read_image_data(image_filename.c_str());
706  }
707  else if(data->images[i].buffer_view)
708  {
709  // extraire l'image du glb...
710  cgltf_buffer_view *view= data->images[i].buffer_view;
711  assert(view->buffer->data);
712  //~ printf(" [%u] %s offset %lu size %lu, type '%s'\n", i, data->images[i].name, view->offset, view->size, data->images[i].mime_type);
713 
714  SDL_RWops *read= SDL_RWFromConstMem((uint8_t *) view->buffer->data + view->offset, view->size);
715  assert(read);
716 
717  images[i]= image_data( IMG_Load_RW(read, /* free RWops */ 1) );
718  }
719  }
720 
721  cgltf_free(data);
722  return images;
723 }
ImageData image_data(SDL_Surface *surface)
converti une surface SDL en imageData, cf RWops pour charger les images deja en memoire.
Definition: image_io.cpp:141

◆ read_gltf_scene()

GLTFScene read_gltf_scene ( const char *  filename)

charge un fichier .gltf et construit une scene statique, sans animation.

Definition at line 726 of file gltf.cpp.

727 {
728  printf("loading glTF scene '%s'...\n", filename);
729 
730  cgltf_options options= { };
731  cgltf_data *data= nullptr;
732  cgltf_result code= cgltf_parse_file(&options, filename, &data);
733  if(code != cgltf_result_success)
734  {
735  printf("[error] loading glTF mesh '%s'...\n", filename);
736  return { };
737  }
738 
739  if(cgltf_validate(data) != cgltf_result_success)
740  {
741  printf("[error] invalid glTF mesh '%s'...\n", filename);
742  return { };
743  }
744 
745  code= cgltf_load_buffers(&options, data, filename);
746  if(code != cgltf_result_success)
747  {
748  printf("[error] loading glTF buffers...\n");
749  return { };
750  }
751 
752  //
753  GLTFScene scene;
754 
755 // etape 1 : construire les meshs et les groupes de triangles / primitives
756  int primitives_index= 0;
757  std::vector<float> buffer;
758 
759  // parcourir tous les meshs de la scene
760  for(unsigned mesh_id= 0; mesh_id < data->meshes_count; mesh_id++)
761  {
762  GLTFMesh m= { };
763  m.pmin= Point(FLT_MAX, FLT_MAX, FLT_MAX);
764  m.pmax= Point(-FLT_MAX, -FLT_MAX, -FLT_MAX);
765 
766  cgltf_mesh *mesh= &data->meshes[mesh_id];
767  // parcourir les groupes de triangles du mesh...
768  for(unsigned primitive_id= 0; primitive_id < mesh->primitives_count; primitive_id++)
769  {
770  cgltf_primitive *primitives= &mesh->primitives[primitive_id];
771  assert(primitives->type == cgltf_primitive_type_triangles);
772 
773  GLTFPrimitives p= { };
774 
775  // matiere associee au groupe de triangles
776  p.material_index= -1;
777  if(primitives->material)
778  p.material_index= std::distance(data->materials, primitives->material);
779 
780  // indices
781  if(primitives->indices)
782  {
783  for(unsigned i= 0; i < primitives->indices->count; i++)
784  p.indices.push_back(cgltf_accessor_read_index(primitives->indices, i));
785  assert(p.indices.size() % 3 == 0);
786  }
787 
788  // attributs
789  for(unsigned attribute_id= 0; attribute_id < primitives->attributes_count; attribute_id++)
790  {
791  cgltf_attribute *attribute= &primitives->attributes[attribute_id];
792 
793  if(attribute->type == cgltf_attribute_type_position)
794  {
795  assert(attribute->data->type == cgltf_type_vec3);
796 
797  buffer.resize(cgltf_accessor_unpack_floats(attribute->data, nullptr, 0));
798  cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
799 
800  // transforme les positions des sommets
801  for(unsigned i= 0; i+2 < buffer.size(); i+= 3)
802  p.positions.push_back( vec3(buffer[i], buffer[i+1], buffer[i+2]) );
803 
804  #if 0
805  assert(attribute->data->has_min);
806  assert(attribute->data->has_max);
807  p.pmin= vec3(attribute->data->min[0], attribute->data->min[1], attribute->data->min[2]);
808  p.pmax= vec3(attribute->data->max[0], attribute->data->max[1], attribute->data->max[2]);
809  #else
810  p.pmin= p.positions[0];
811  p.pmax= p.positions[0];
812  for(unsigned i= 1; i < p.positions.size(); i++)
813  {
814  p.pmin= min(p.pmin, p.positions[i]);
815  p.pmax= max(p.pmax, p.positions[i]);
816  }
817  #endif
818  m.pmin= min(m.pmin, p.pmin);
819  m.pmax= max(m.pmax, p.pmax);
820  }
821 
822  if(attribute->type == cgltf_attribute_type_normal)
823  {
824  assert(attribute->data->type == cgltf_type_vec3);
825 
826  buffer.resize(cgltf_accessor_unpack_floats(attribute->data, nullptr, 0));
827  cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
828 
829  // transforme les normales des sommets
830  for(unsigned i= 0; i+2 < buffer.size(); i+= 3)
831  p.normals.push_back( vec3(buffer[i], buffer[i+1], buffer[i+2]) );
832  }
833 
834  if(attribute->type == cgltf_attribute_type_texcoord)
835  {
836  assert(attribute->data->type == cgltf_type_vec2);
837 
838  buffer.resize(cgltf_accessor_unpack_floats(attribute->data, nullptr, 0));
839  cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
840 
841  for(unsigned i= 0; i+1 < buffer.size(); i+= 2)
842  p.texcoords.push_back( vec2(buffer[i], buffer[i+1]) );
843  }
844  }
845 
846  p.primitives_index= primitives_index++;
847  m.primitives.push_back(p);
848  }
849 
850  scene.meshes.push_back(m);
851  }
852 
853 // etape 2 : parcourir les noeuds, retrouver les transforms pour placer les meshes
854  for(unsigned node_id= 0; node_id < data->nodes_count; node_id++)
855  {
856  cgltf_node *node= &data->nodes[node_id];
857  if(node->mesh== nullptr)
858  // pas de mesh associe, rien a dessiner
859  continue;
860 
861  // recuperer la transformation pour placer le mesh dans la scene
862  float model_matrix[16];
863  cgltf_node_transform_world(node, model_matrix);
864 
865  Transform model;
866  model.column_major(model_matrix); // gltf organise les 16 floats par colonne...
867  //~ Transform normal= model.normal(); // transformation pour les normales
868 
869  int mesh_index= std::distance(data->meshes, node->mesh);
870  scene.nodes.push_back( {model, mesh_index} );
871  }
872 
873 // etape 3 : recuperer les autres infos...
874  scene.materials= read_materials(data);
875  scene.lights= read_lights(data);
876  scene.cameras= read_cameras(data);
877 
878 // etape : nettoyage...
879  cgltf_free(data);
880 
881  return scene;
882 }
Point pmax
points extremes de l'englobant dans le repere objet
Definition: gltf.h:117
int material_index
indice de la matiere des primitives.
Definition: gltf.h:102
int primitives_index
indice unique.
Definition: gltf.h:101
Point pmax
points extremes de l'englobant dans le repere objet
Definition: gltf.h:104
std::vector< GLTFPrimitives > primitives
groupes de triangles associes a une matiere.
Definition: gltf.h:116
description d'un maillage.
Definition: gltf.h:115
groupe de triangles d'un maillage. chaque groupe est associe a une matiere.
Definition: gltf.h:99
Point max(const Point &a, const Point &b)
renvoie la plus grande composante de chaque point. x, y, z= max(a.x, b.x), max(a.y,...
Definition: vec.cpp:35
Point min(const Point &a, const Point &b)
renvoie la plus petite composante de chaque point. x, y, z= min(a.x, b.x), min(a.y,...
Definition: vec.cpp:30
std::vector< GLTFMaterial > materials
matieres.
Definition: gltf.h:153
std::vector< GLTFLight > lights
lumieres.
Definition: gltf.h:154
std::vector< GLTFNode > nodes
noeuds / position et orientation des maillages dans la scene.
Definition: gltf.h:151
std::vector< GLTFMesh > meshes
ensemble de maillages.
Definition: gltf.h:150
std::vector< GLTFCamera > cameras
cameras.
Definition: gltf.h:155