gKit2 light
Loading...
Searching...
No Matches
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.
std::vector< GLTFCameraread_gltf_cameras (const char *filename)
 charge un fichier .gltf renvoie les cameras.
std::vector< GLTFLightread_gltf_lights (const char *filename)
 charge un fichier .gltf et renvoie les sources de lumiere ponctuelles.
std::vector< GLTFMaterialread_gltf_materials (const char *filename)
 charge un fichier .gltf et renvoie les matieres.
std::vector< ImageDataread_gltf_images (const char *filename)
 charge un fichier .gltf et charge les images referencees par les matieres.
GLTFScene read_gltf_scene (const char *filename)
 charge un fichier .gltf et construit une scene statique, sans animation.

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 14 of file gltf.cpp.

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

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

◆ 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 461 of file gltf.cpp.

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

◆ read_gltf_materials()

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

charge un fichier .gltf et renvoie les matieres.

Definition at line 618 of file gltf.cpp.

619{
620 printf("loading glTF materials '%s'...\n", filename);
621
622 cgltf_options options= { };
623 cgltf_data *data= nullptr;
624 cgltf_result code= cgltf_parse_file(&options, filename, &data);
625 if(code != cgltf_result_success)
626 {
627 printf("[error] loading glTF mesh '%s'...\n", filename);
628 return {};
629 }
630
631 if(cgltf_validate(data) != cgltf_result_success)
632 {
633 printf("[error] invalid glTF mesh '%s'...\n", filename);
634 return {};
635 }
636
637 if(data->materials_count ==0)
638 {
639 printf("[warning] no materials...\n");
640 return {};
641 }
642
643 std::vector<GLTFMaterial> materials= read_materials(data);
644 cgltf_free(data);
645 return materials;
646}

◆ 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 649 of file gltf.cpp.

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

◆ read_gltf_scene()

GLTFScene read_gltf_scene ( const char * filename)

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

Definition at line 716 of file gltf.cpp.

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