charge un fichier .gltf et construit un mesh statique, sans animation.
21 printf(
"loading glTF mesh '%s'...\n", filename);
25 cgltf_result code= cgltf_parse_file(&options, filename, &data);
26 if(code != cgltf_result_success)
28 printf(
"[error] loading glTF mesh '%s'...\n", filename);
32 if(cgltf_validate(data) != cgltf_result_success)
34 printf(
"[error] invalid glTF mesh '%s'...\n", filename);
38 code= cgltf_load_buffers(&options, data, filename);
39 if(code != cgltf_result_success)
41 printf(
"[error] loading glTF buffers...\n");
46 std::vector<unsigned> indices;
47 std::vector<int> material_indices;
48 std::vector<vec3> positions;
49 std::vector<vec2> texcoords;
51 std::vector<vec4> colors;
56 for(
unsigned i= 0; i < data->images_count; i++)
58 if(data->images[i].uri)
60 printf(
"texture '%s'...\n", data->images[i].uri);
63 else if(data->images[i].buffer_view)
78 if(!view->buffer->uri)
81 if(data->images[i].name && data->images[i].name[0])
82 sprintf(tmp,
"%s%s",
pathname(filename).c_str(), data->images[i].name);
84 sprintf(tmp,
"%stexture%d.png",
pathname(filename).c_str(), i);
86 printf(
"packed texture '%s'...\n", tmp);
90 if(strcmp(data->images[i].mime_type,
"image/png") == 0)
92 else if(strcmp(data->images[i].mime_type,
"image/jpg") == 0)
97 printf(
"unpacking glb texture '%s' to '%s'...\n", data->images[i].name, tmp);
99 FILE *out= fopen(tmp,
"wb");
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);
113 if(
char *ext= strrchr(tmp,
'.'))
114 strcpy(ext,
"_flip.png");
116 printf(
"writing flipped texture '%s'...\n", tmp);
120 assert(data->images[i].uri ==
nullptr);
121 data->images[i].uri= strdup(tmp);
128 for(
unsigned i= 0; i < data->materials_count; i++)
134 if(material->has_pbr_metallic_roughness)
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;
150 m.diffuse= color * (1 - metallic) + metallic *
Black();
151 m.specular=
Color(0.04) * (1 - metallic) + color * metallic;
154 m.ns= 2 / (roughness * roughness * roughness * roughness) - 2;
155 if(m.ns <
float(1.1))
164 if(pbr->base_color_texture.texture && pbr->base_color_texture.texture->image)
171 sprintf(tmp,
"material%d", i);
172 material->name= strdup(tmp);
175 materials.
insert(m, material->name);
178 bool mesh_has_texcoords=
false;
179 bool mesh_has_normals=
false;
180 bool mesh_has_colors=
false;
182 std::vector<float> buffer;
184 for(
unsigned node_id= 0; node_id < data->nodes_count; node_id++)
187 if(node->mesh==
nullptr)
192 float model_matrix[16];
193 cgltf_node_transform_world(node, model_matrix);
202 for(
unsigned primitive_id= 0; primitive_id < mesh->primitives_count; primitive_id++)
205 assert(primitives->type == cgltf_primitive_type_triangles);
207 bool primitive_has_texcoords=
false;
208 bool primitive_has_normals=
false;
209 bool primitive_has_colors=
false;
210 unsigned offset= positions.size();
214 if(primitives->material)
216 assert(material_id < materials.
count());
217 assert(materials.
find(primitives->material->name) != -1);
218 material_id= materials.
find(primitives->material->name);
222 if(primitives->indices)
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);
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());
235 for(
unsigned attribute_id= 0; attribute_id < primitives->attributes_count; attribute_id++)
239 if(attribute->type == cgltf_attribute_type_position)
241 assert(attribute->data->type == cgltf_type_vec3);
243 buffer.resize(cgltf_accessor_unpack_floats(attribute->data,
nullptr, 0));
244 cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
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])) );
251 if(attribute->type == cgltf_attribute_type_normal)
253 assert(attribute->data->type == cgltf_type_vec3);
255 primitive_has_normals=
true;
256 if(mesh_has_normals ==
false)
258 mesh_has_normals=
true;
260 for(
unsigned i= 0; i < offset; i++)
264 buffer.resize(cgltf_accessor_unpack_floats(attribute->data,
nullptr, 0));
265 cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
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])) );
273 if(attribute->type == cgltf_attribute_type_texcoord)
275 assert(attribute->data->type == cgltf_type_vec2);
277 primitive_has_texcoords=
true;
278 if(mesh_has_texcoords ==
false)
280 mesh_has_texcoords=
true;
282 for(
unsigned i= 0; i < offset; i++)
283 texcoords.push_back(
vec2() );
286 buffer.resize(cgltf_accessor_unpack_floats(attribute->data,
nullptr, 0));
287 cgltf_accessor_unpack_floats(attribute->data, buffer.data(), buffer.size());
289 for(
unsigned i= 0; i+1 < buffer.size(); i+= 2)
290 texcoords.push_back(
vec2(buffer[i], buffer[i+1]) );
294 if(attribute->type == cgltf_attribute_type_color)
296 assert(attribute->data->type == cgltf_type_vec4);
298 primitive_has_colors=
true;
299 if(mesh_has_colors ==
false)
301 mesh_has_colors=
true;
303 for(
unsigned i= 0; i < offset; i++)
304 colors.push_back(
vec4(1, 1, 1, 1) );
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());
316 if(mesh_has_texcoords && primitive_has_texcoords ==
false)
317 for(
unsigned i= offset; i < positions.size(); i++)
318 texcoords.push_back(
vec2() );
320 if(mesh_has_normals && primitive_has_normals ==
false)
321 for(
unsigned i= offset; i < positions.size(); i++)
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) );
333 Mesh mesh(GL_TRIANGLES);
338 bool has_colors= (colors.size() == positions.size());
340 printf(
"gltf %d positions, %d texcoords, %d normals\n",
int(positions.size()),
int(texcoords.size()),
int(
normals.size()));
342 for(
unsigned i= 0; i < positions.size(); i++)
346 if(has_colors) mesh.
color(colors[i]);
348 mesh.
vertex(positions[i]);
353 bool has_materials= (materials.
count() > 0) && (indices.size() / 3 == material_indices.size());
354 for(
unsigned i= 0; i+2 < indices.size(); i+= 3)
356 if(has_materials) mesh.
material(material_indices[i / 3]);
358 mesh.
triangle(indices[i], indices[i+1], indices[i+2]);
representation d'un objet / maillage.
unsigned int vertex(const vec3 &p)
insere un sommet de position p, et ses attributs (s'ils sont definis par color(), texcoord(),...
Mesh & texcoord(const vec2 &uv)
definit les coordonnees de texture du prochain sommet.
Mesh & material(const unsigned int id)
definit la matiere du prochain triangle. id est l'indice d'une matiere ajoutee dans materials(),...
Mesh & triangle(const unsigned int a, const unsigned int b, const unsigned int c)
Mesh & normal(const vec3 &n)
definit la normale du prochain sommet.
GLenum primitives() const
renvoie le type de primitives.
Mesh & color(const vec4 &c)
definit la couleur du prochain sommet.
const Materials & materials() const
renvoie la description des matieres.
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().
ImageData read_image_data(const char *filename)
charge les donnees d'un fichier png. renvoie une image initialisee par defaut en cas d'echec.
int write_image_data(ImageData &image, const char *filename)
enregistre des donnees dans un fichier png.
Color Black()
utilitaire. renvoie une couleur noire.
Image flipY(const Image &image)
retourne l'image
float distance(const Point &a, const Point &b)
renvoie la distance etre 2 points.
void normals(MeshData &data)
(re-) calcule les normales des sommets. utiliser avant les reindexations, cf indices() et vertices().
std::string pathname(const std::string &filename)
representation d'une couleur (rgba) transparente ou opaque.
stockage temporaire des donnees d'une image.
int diffuse_texture
indice de la texture de la couleur de base, ou -1.
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...