14Mesh read_gltf_mesh(
const char *filename )
16 printf(
"loading glTF mesh '%s'...\n", filename);
20 cgltf_result code= cgltf_parse_file(&options, filename, &data);
21 if(code != cgltf_result_success)
23 printf(
"[error] loading glTF mesh '%s'...\n", filename);
27 if(cgltf_validate(data) != cgltf_result_success)
29 printf(
"[error] invalid glTF mesh '%s'...\n", filename);
33 code= cgltf_load_buffers(&options, data, filename);
34 if(code != cgltf_result_success)
36 printf(
"[error] loading glTF buffers...\n");
41 std::vector<unsigned> indices;
42 std::vector<int> material_indices;
43 std::vector<vec3> positions;
44 std::vector<vec2> texcoords;
46 std::vector<vec4> colors;
51 for(
unsigned i= 0; i < data->images_count; i++)
53 if(data->images[i].uri)
55 printf(
"texture '%s'...\n", data->images[i].uri);
58 else if(data->images[i].buffer_view)
72 if(!view->buffer->uri)
75 if(data->images[i].name && data->images[i].name[0])
76 sprintf(tmp,
"%s%s", pathname(filename).c_str(), data->images[i].name);
78 sprintf(tmp,
"%stexture%d.png", pathname(filename).c_str(), i);
84 if(strcmp(data->images[i].mime_type,
"image/png") == 0)
86 else if(strcmp(data->images[i].mime_type,
"image/jpg") == 0)
91 printf(
"unpacking glb texture '%s' to '%s'...\n", data->images[i].name, tmp);
93 FILE *out= fopen(tmp,
"wb");
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);
107 if(
char *ext= strrchr(tmp,
'.'))
108 strcpy(ext,
"_flip.png");
110 printf(
"writing flipped texture '%s'...\n", tmp);
114 assert(data->images[i].uri ==
nullptr);
115 data->images[i].uri= strdup(tmp);
122 for(
unsigned i= 0; i < data->materials_count; i++)
128 if(material->has_pbr_metallic_roughness)
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;
148 m.
ns= 2 / (roughness * roughness * roughness * roughness) - 2;
149 if(m.
ns <
float(1.1))
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));
165 sprintf(tmp,
"material%d", i);
166 material->name= strdup(tmp);
169 materials.
insert(m, material->name);
172 bool mesh_has_texcoords=
false;
173 bool mesh_has_normals=
false;
174 bool mesh_has_colors=
false;
176 std::vector<float> buffer;
178 for(
unsigned node_id= 0; node_id < data->nodes_count; node_id++)
181 if(node->mesh==
nullptr)
186 float model_matrix[16];
187 cgltf_node_transform_world(node, model_matrix);
196 for(
unsigned primitive_id= 0; primitive_id < mesh->primitives_count; primitive_id++)
199 assert(primitives->type == cgltf_primitive_type_triangles);
201 bool primitive_has_texcoords=
false;
202 bool primitive_has_normals=
false;
203 bool primitive_has_colors=
false;
204 unsigned offset= positions.size();
208 if(primitives->material)
210 assert(material_id < materials.
count());
211 assert(materials.
find(primitives->material->name) != -1);
212 material_id= materials.
find(primitives->material->name);
216 if(primitives->indices)
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);
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());
229 for(
unsigned attribute_id= 0; attribute_id < primitives->attributes_count; attribute_id++)
233 if(attribute->type == cgltf_attribute_type_position)
235 assert(attribute->data->type == cgltf_type_vec3);
237 buffer.resize(cgltf_accessor_unpack_floats(attribute->data,
nullptr, 0));
238 cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
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])) );
245 if(attribute->type == cgltf_attribute_type_normal)
247 assert(attribute->data->type == cgltf_type_vec3);
249 primitive_has_normals=
true;
250 if(mesh_has_normals ==
false)
252 mesh_has_normals=
true;
254 for(
unsigned i= 0; i < offset; i++)
258 buffer.resize(cgltf_accessor_unpack_floats(attribute->data,
nullptr, 0));
259 cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
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])) );
267 if(attribute->type == cgltf_attribute_type_texcoord)
269 assert(attribute->data->type == cgltf_type_vec2);
271 primitive_has_texcoords=
true;
272 if(mesh_has_texcoords ==
false)
274 mesh_has_texcoords=
true;
276 for(
unsigned i= 0; i < offset; i++)
277 texcoords.push_back(
vec2() );
280 buffer.resize(cgltf_accessor_unpack_floats(attribute->data,
nullptr, 0));
281 cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
283 for(
unsigned i= 0; i+1 < buffer.size(); i+= 2)
284 texcoords.push_back(
vec2(buffer[i], buffer[i+1]) );
288 if(attribute->type == cgltf_attribute_type_color)
290 assert(attribute->data->type == cgltf_type_vec4);
292 primitive_has_colors=
true;
293 if(mesh_has_colors ==
false)
295 mesh_has_colors=
true;
297 for(
unsigned i= 0; i < offset; i++)
298 colors.push_back(
vec4(1, 1, 1, 1) );
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());
310 if(mesh_has_texcoords && primitive_has_texcoords ==
false)
311 for(
unsigned i= offset; i < positions.size(); i++)
312 texcoords.push_back(
vec2() );
314 if(mesh_has_normals && primitive_has_normals ==
false)
315 for(
unsigned i= offset; i < positions.size(); i++)
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) );
327 Mesh mesh(GL_TRIANGLES);
332 bool has_colors= (colors.size() == positions.size());
334 printf(
"gltf %d positions, %d texcoords, %d normals\n",
int(positions.size()),
int(texcoords.size()),
int(
normals.size()));
336 for(
unsigned i= 0; i < positions.size(); i++)
340 if(has_colors) mesh.color(colors[i]);
342 mesh.vertex(positions[i]);
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)
350 if(has_materials) mesh.material(material_indices[i / 3]);
352 mesh.triangle(indices[i], indices[i+1], indices[i+2]);
362std::vector<GLTFCamera> read_cameras(
cgltf_data *data )
364 std::vector<GLTFCamera> cameras;
365 for(
unsigned i= 0; i < data->nodes_count; i++)
368 if(node->camera ==
nullptr)
383 float model_matrix[16];
384 cgltf_node_transform_world(node, model_matrix);
390 cameras.push_back( {
degrees(perspective->yfov), perspective->aspect_ratio, perspective->znear, perspective->zfar, view, projection } );
396std::vector<GLTFCamera> read_gltf_cameras(
const char *filename )
398 printf(
"loading glTF camera '%s'...\n", filename);
402 cgltf_result code= cgltf_parse_file(&options, filename, &data);
403 if(code != cgltf_result_success)
405 printf(
"[error] loading glTF mesh '%s'...\n", filename);
409 if(cgltf_validate(data) != cgltf_result_success)
411 printf(
"[error] invalid glTF mesh '%s'...\n", filename);
415 if(data->cameras_count == 0)
417 printf(
"[warning] no camera...\n");
421 std::vector<GLTFCamera> cameras= read_cameras(data);
428std::vector<GLTFLight> read_lights(
cgltf_data *data )
430 std::vector<GLTFLight> lights;
432 for(
unsigned i= 0; i < data->nodes_count; i++)
435 if(node->light ==
nullptr)
442 float model_matrix[16];
443 cgltf_node_transform_world(node, model_matrix);
455 lights.push_back( { position,
Color(light->color[0], light->color[1], light->color[2]), light->intensity } );
461std::vector<GLTFLight> read_gltf_lights(
const char *filename )
463 printf(
"loading glTF lights '%s'...\n", filename);
467 cgltf_result code= cgltf_parse_file(&options, filename, &data);
468 if(code != cgltf_result_success)
470 printf(
"[error] loading glTF mesh '%s'...\n", filename);
474 if(cgltf_validate(data) != cgltf_result_success)
476 printf(
"[error] invalid glTF mesh '%s'...\n", filename);
480 if(data->lights_count == 0)
482 printf(
"[warning] no lights...\n");
486 std::vector<GLTFLight> lights= read_lights(data);
493std::vector<GLTFMaterial> read_materials(
cgltf_data *data )
495 std::vector<GLTFMaterial> materials;
496 for(
unsigned i= 0; i < data->materials_count; i++)
510 m.attenuation_distance= 0;
511 m.attenuation_color=
Black();
520 m.thickness_texture= -1;
522 if(material->has_pbr_metallic_roughness)
526 m.
color=
Color(pbr->base_color_factor[0], pbr->base_color_factor[1], pbr->base_color_factor[2], pbr->base_color_factor[3]);
527 if(pbr->base_color_texture.texture && pbr->base_color_texture.texture->image)
528 m.
color_texture= int(std::distance(data->images, pbr->base_color_texture.texture->image));
532 if(pbr->metallic_roughness_texture.texture && pbr->metallic_roughness_texture.texture->image)
535 printf(
" pbr metallic roughness\n");
539 if(material->has_clearcoat)
544 if(material->normal_texture.texture && material->normal_texture.texture->image)
547 m.
normal_texture= int(std::distance(data->images, material->normal_texture.texture->image));
551 m.
emission=
Color(material->emissive_factor[0], material->emissive_factor[1], material->emissive_factor[2]);
552 if(material->emissive_texture.texture && material->emissive_texture.texture->image)
555 m.
emission_texture= int(std::distance(data->images, material->emissive_texture.texture->image));
559 if(material->has_ior)
561 m.
ior= material->ior.ior;
562 if(m.
ior ==
float(1.5))
569 if(material->has_specular)
571 m.
specular= material->specular.specular_factor;
572 if(material->specular.specular_texture.texture && material->specular.specular_texture.texture->image)
573 m.
specular_texture= std::distance(data->images, material->specular.specular_texture.texture->image);
575 m.
specular_color=
Color(material->specular.specular_color_factor[0], material->specular.specular_color_factor[1], material->specular.specular_color_factor[2]);
576 if(material->specular.specular_color_texture.texture && material->specular.specular_color_texture.texture->image)
577 m.
specular_color_texture= std::distance(data->images, material->specular.specular_color_texture.texture->image);
590 if(material->has_transmission)
592 m.
transmission= material->transmission.transmission_factor;
593 if(material->transmission.transmission_texture.texture && material->transmission.transmission_texture.texture->image)
594 m.
transmission_texture= std::distance(data->images, material->transmission.transmission_texture.texture->image);
600 if(material->has_volume)
602 m.
thickness= material->volume.thickness_factor;
603 if(material->volume.thickness_texture.texture && material->volume.thickness_texture.texture->image)
604 m.thickness_texture= std::distance(data->images, material->volume.thickness_texture.texture->image);
606 m.attenuation_distance= material->volume.attenuation_distance;
607 m.attenuation_color=
Color(material->volume.attenuation_color[0], material->volume.attenuation_color[1], material->volume.attenuation_color[2]);
608 printf(
" volume thickness %f, texture %d\n",m.
thickness, m.thickness_texture);
609 printf(
" volume attenation distance %f, color %f %f %f\n", m.attenuation_distance, m.attenuation_color.r, m.attenuation_color.g, m.attenuation_color.b);
612 materials.push_back(m);
618std::vector<GLTFMaterial> read_gltf_materials(
const char *filename )
620 printf(
"loading glTF materials '%s'...\n", filename);
624 cgltf_result code= cgltf_parse_file(&options, filename, &data);
625 if(code != cgltf_result_success)
627 printf(
"[error] loading glTF mesh '%s'...\n", filename);
631 if(cgltf_validate(data) != cgltf_result_success)
633 printf(
"[error] invalid glTF mesh '%s'...\n", filename);
637 if(data->materials_count ==0)
639 printf(
"[warning] no materials...\n");
643 std::vector<GLTFMaterial> materials= read_materials(data);
649std::vector<ImageData> read_gltf_images(
const char *filename )
651 printf(
"loading glTF images '%s'...\n", filename);
655 cgltf_result code= cgltf_parse_file(&options, filename, &data);
656 if(code != cgltf_result_success)
658 printf(
"[error] loading glTF mesh '%s'...\n", filename);
662 if(cgltf_validate(data) != cgltf_result_success)
664 printf(
"[error] invalid glTF mesh '%s'...\n", filename);
668 if(data->images_count == 0)
670 printf(
"[warning] no images...\n");
675 for(
unsigned i= 0; i < data->images_count; i++)
676 if(!data->images[i].uri)
678 code= cgltf_load_buffers(&options, data, filename);
679 if(code != cgltf_result_success)
681 printf(
"[error] loading glTF internal images...\n");
690 std::vector<ImageData> images(data->images_count);
692#pragma omp parallel for schedule(dynamic, 1)
693 for(
unsigned i= 0; i < data->images_count; i++)
695 if(data->images[i].uri)
698 std::string image_filename= pathname(filename) + std::string(data->images[i].uri);
701 else if(data->images[i].buffer_view)
705 assert(view->buffer->data);
707 images[i]=
read_image_data((uint8_t *) view->buffer->data + view->offset, view->size);
718 printf(
"loading glTF scene '%s'...\n", filename);
722 cgltf_result code= cgltf_parse_file(&options, filename, &data);
723 if(code != cgltf_result_success)
725 printf(
"[error] loading glTF mesh '%s'...\n", filename);
729 if(cgltf_validate(data) != cgltf_result_success)
731 printf(
"[error] invalid glTF mesh '%s'...\n", filename);
735 code= cgltf_load_buffers(&options, data, filename);
736 if(code != cgltf_result_success)
738 printf(
"[error] loading glTF buffers...\n");
746 int primitives_index= 0;
747 std::vector<float> buffer;
750 for(
unsigned mesh_id= 0; mesh_id < data->meshes_count; mesh_id++)
753 m.pmin=
Point(FLT_MAX, FLT_MAX, FLT_MAX);
754 m.
pmax=
Point(-FLT_MAX, -FLT_MAX, -FLT_MAX);
758 for(
unsigned primitive_id= 0; primitive_id < mesh->primitives_count; primitive_id++)
761 assert(primitives->type == cgltf_primitive_type_triangles);
767 if(primitives->material)
768 p.
material_index= std::distance(data->materials, primitives->material);
771 if(primitives->indices)
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);
779 for(
unsigned attribute_id= 0; attribute_id < primitives->attributes_count; attribute_id++)
783 if(attribute->type == cgltf_attribute_type_position)
785 assert(attribute->data->type == cgltf_type_vec3);
787 buffer.resize(cgltf_accessor_unpack_floats(attribute->data,
nullptr, 0));
788 cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
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]) );
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]);
800 p.pmin= p.positions[0];
801 p.
pmax= p.positions[0];
802 for(
unsigned i= 1; i < p.positions.size(); i++)
804 p.pmin=
min(p.pmin, p.positions[i]);
808 m.pmin=
min(m.pmin, p.pmin);
812 if(attribute->type == cgltf_attribute_type_normal)
814 assert(attribute->data->type == cgltf_type_vec3);
816 buffer.resize(cgltf_accessor_unpack_floats(attribute->data,
nullptr, 0));
817 cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
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]) );
824 if(attribute->type == cgltf_attribute_type_texcoord)
826 assert(attribute->data->type == cgltf_type_vec2);
828 buffer.resize(cgltf_accessor_unpack_floats(attribute->data,
nullptr, 0));
829 cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
831 for(
unsigned i= 0; i+1 < buffer.size(); i+= 2)
832 p.texcoords.push_back(
vec2(buffer[i], buffer[i+1]) );
840 scene.meshes.push_back(m);
844 for(
unsigned node_id= 0; node_id < data->nodes_count; node_id++)
847 if(node->mesh==
nullptr)
852 float model_matrix[16];
853 cgltf_node_transform_world(node, model_matrix);
859 int mesh_index= std::distance(data->meshes, node->mesh);
860 scene.nodes.push_back( {model, mesh_index} );
865 scene.lights= read_lights(data);
866 scene.cameras= read_cameras(data);
877 for(
unsigned i= 0; i <
meshes.size(); i++)
880 for(
unsigned i= 0; i <
nodes.size(); i++)
882 int index=
nodes[i].mesh_index;
893 pmin=
Point(FLT_MAX, FLT_MAX, FLT_MAX);
894 pmax=
Point(-FLT_MAX, -FLT_MAX, -FLT_MAX);
895 for(
unsigned node_id= 0; node_id <
nodes.size(); node_id++)
899 for(
unsigned primitive_id= 0; primitive_id < mesh.primitives.size(); primitive_id++)
902 for(
unsigned i= 0; i < primitives.positions.size(); i++)
representation d'un objet / maillage.
Point pmax
points extremes de l'englobant dans le repere objet
int mesh_index
indice du maillage.
int material_index
indice de la matiere des primitives.
int primitives_index
indice unique.
Point pmax
points extremes de l'englobant dans le repere objet
std::vector< GLTFPrimitives > primitives
groupes de triangles associes a une matiere.
description d'un maillage.
position et orientation d'un maillage dans la scene.
groupe de triangles d'un maillage. chaque groupe est associe a une matiere.
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().
Color Black()
utilitaire. renvoie une couleur noire.
Image flipY(const Image &image)
retourne l'image
int write_image_data(ImageData &image, const char *filename, const bool flipY)
enregistre des donnees dans un fichier png.
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...
Transform Inverse(const Transform &m)
renvoie l'inverse de la matrice.
Point Origin()
renvoie le point origine (0, 0, 0)
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....
float degrees(const float angle)
conversion en degres.
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....
Transform Perspective(const float fov, const float aspect, const float znear, const float zfar)
renvoie la matrice representant une transformation projection perspective.
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.
float transmission
transmission, transparent ou pas (= 0)
int color_texture
indice de la texture ou -1. cf read_gltf_images() pour charger les textures dans le bon ordre....
float roughness
rugosite de la micro surface.
int metallic_roughness_texture
indice de la texture ou -1. les valeurs RGB representent les parametres du modele : B= metallic,...
int emission_texture
indice de la texture ou -1.
Color specular_color
modification de la reflexion speculaire des dielectriques ou pas (= 0)
Color emission
emission pour les sources de lumieres ou pas (= noir).
int normal_texture
indice de la texture ou -1.
float specular
modification de la reflexion speculaire des dielectriques ou pas (= 0)
int transmission_texture
indice de la texture ou -1.
float ior
indice de refraction des dielectriques ou pas (= 0)
float thickness
epaisseur des surfaces transparentes
int specular_color_texture
indice de la texture ou -1.
float metallic
metallic / dielectrique.
int specular_texture
indice de la texture ou -1.
int occlusion_texture
indice de la texture ou -1. //
void bounds(Point &pmin, Point &pmax) const
calcule les points extremes de la scene, utile pour regler un orbiter.
std::vector< GLTFMaterial > materials
matieres.
std::vector< GLTFInstances > instances() const
regroupe les instances de chaque maillage.
std::vector< GLTFNode > nodes
noeuds / position et orientation des maillages dans la scene.
std::vector< GLTFMesh > meshes
ensemble de maillages.
stockage temporaire des donnees d'une image.
int diffuse_texture
indice de la texture de la couleur de base, ou -1.
float ns
concentration des reflets, exposant pour les reflets blinn-phong.
Color diffuse
couleur diffuse / de base.
Color specular
couleur du reflet.
int insert(const Material &material, const char *name)
ajoute une matiere.
int find(const char *name)
recherche une matiere avec son nom. renvoie son indice dans materials, ou -1.
int insert_texture(const char *filename)
ajoute une texture / nom du fichier.
int count() const
nombre de matieres.
representation d'un point 3d.
representation d'un vecteur 3d.
vecteur generique, utilitaire.
vecteur generique, utilitaire.
vecteur generique 4d, ou 3d homogene, utilitaire.
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...