3dsloader:ObjetBlocChunk
Un article de Games Creators Network.
suite du tuto sur le loader 3ds : OpenGL:3dsloader
Sommaire |
[modifier] les opcodes
nous allons voir maintenant les opcodes suivants :
0x4100 : opcode pour créer un mesh triangulaire 0x4110 : opcode qui contient la liste des vertex 0x4120 : opcode qui contient la liste des faces 0x4130 : opcode qui donne les infos sur le material a appliquer 0x4140 : opcode qui contient la liste des coordonées de texture
[modifier] les fonctions supplémentaires
une fonction pour initialiser les vectrices(mesh->num_vectrices est le nombre de vectrices)
void initvectrice(mesh3ds *mesh){ mesh->vectrices = (vectrice3ds*)malloc(sizeof(vectrice3ds)*mesh->num_vectrices); }
une fonction pour initialiser les faces(mesh->num_faces est le nombre de faces) :
void initface(mesh3ds *mesh){ mesh->faces = (face3ds*)malloc(sizeof(face3ds)*mesh->num_faces); }
[modifier] la fonction ObjetBlocChunk()
on commence la fonction :
int ObjetBlockChunk(object3ds *objet3d, FILE *fichier, unsigned int lenght) { int start = ftell(fichier); unsigned short chunk_id; unsigned int chunk_lenght; while (ftell(fichier) < start + lenght){ fread (&chunk_id, 2, 1, fichier); fread (&chunk_lenght, 4, 1, fichier); switch(chunk_id){
si on a 0x4100, on ouvre la fonction pour les mesh triangulaires :
case 0x4100:{ TriangularMeshChunk(objet3d, fichier, chunk_lenght-6); break; }
sinon,
default:{ fseek(fichier, chunk_lenght-6, SEEK_CUR); }
et on ferme la fonction :
} } fseek(fichier, start+lenght, SEEK_SET); return 1; }
[modifier] la fonction TriangularMeshChunk()
on commence la fonction :
int TriangularMeshChunk(object3ds *objet3d, FILE *fichier, unsigned int lenght) { int start = ftell(fichier); unsigned short chunk_id; unsigned int chunk_lenght; while (ftell(fichier) < start + lenght){ fread (&chunk_id, 2, 1, fichier); fread (&chunk_lenght, 4, 1, fichier); switch(chunk_id){
- on va gérer le opcode 0x4110(liste de vertex) :
case 0x4110:{ int i; int num=objet3d->num_mesh-1;
on recupère le nombre de vectrices
fread (&objet3d->mesh[num].num_vectrices, sizeof (unsigned short), 1, fichier);
on initialise ensuite les vectrices du mesh :
initvectrice(&objet3d->mesh[num]);
on va ensuite lire tous les vertex :
for (i=0; i<objet3d->mesh[num].num_vectrices; i++) { fread (&objet3d->mesh[num].vectrices[i].x, sizeof(float), 1, fichier); fread (&objet3d->mesh[num].vectrices[i].y, sizeof(float), 1, fichier); fread (&objet3d->mesh[num].vectrices[i].z, sizeof(float), 1, fichier); }
et on ferme :
break; }
voila, vous avez obtenu la liste des vertex d'un objet .3ds
- on va gerer le opcode 0x4120(liste des faces) :
case 0x4120:{ int i; int num=objet3d->num_mesh-1;
on lit le nombre de faces :
fread (&objet3d->mesh[num].num_faces, sizeof (unsigned short), 1, fichier);
on initialise les faces :
initface(&objet3d->mesh[num]);
on lit les faces :
unsigned short flag; for (i=0; i<objet3d->mesh[num].num_faces; i++) { fread (&objet3d->mesh[num].faces[i].a, sizeof (unsigned short), 1, fichier); fread (&objet3d->mesh[num].faces[i].b, sizeof (unsigned short), 1, fichier); fread (&objet3d->mesh[num].faces[i].c, sizeof (unsigned short), 1, fichier); fread (&flag, sizeof (unsigned short), 1, fichier); }
ensuite, il y a une sous fonction a appeler :
FaceDescriptionChunk(objet3d,fichier,chunk_lenght-6-8*objet3d->mesh[num].num_faces-2);
et on ferme :
break; }
- on va lire le opcode 0x4140(coordonnées de texure) :
d'abord, il faut ajouter une nouvelle structure :
typedef struct mapping_face3ds{ float u,v; }mapping_face3ds;
il faut aussi rajouter
unsigned short num_mapping_face; mapping_face3ds *mapping_faces;
dans la structure mesh3ds
et creer une fonction pour les initialiser :
void init_mapping_face(mesh3ds *mesh){ mesh->mapping_faces = (mapping_face3ds*)malloc(sizeof(mapping_face3ds)*mesh->num_mapping_face); }
ensuite, on peux revenir a la fonction Triangular Mesh et ajouter :
case 0x4140:{ int i; int num=objet3d->num_mesh-1;
on récupère le nombre de coordonnées de textures :
fread (&objet3d->mesh[num].num_mapping_face, sizeof (unsigned short), 1, fichier);
puis initialiser les coordonées de texture :
init_mapping_face(&objet3d->mesh[num]);
ensuite lire la liste de coordonnées de texture :
for (i=0; i<objet3d->mesh[num].num_mapping_face; i++) { fread (&objet3d->mesh[num].mapping_faces[i].u, sizeof (float), 1, fichier); fread (&objet3d->mesh[num].mapping_faces[i].v, sizeof (float), 1, fichier); }
et fermer :
break; }
et finir la fonction Triangular Mesh
default: { fseek(fichier, chunk_lenght-6, SEEK_CUR); } } } fseek(fichier, start+lenght, SEEK_SET); return 1; }
[modifier] la sous fonction FaceDescriptionChunk
- on gère le opcode 0x4130 :
nous allons recevoir le nom du material à appliquer ainsi que les faces sur lesquels ils faut les appliquer(en general, sur toutes les faces)
il faut donc rajouter de quoi stocker le nom et les faces: on ajoute
char material_name[20]; unsigned short num_material_face; unsigned short *material_face;
dans la structure mesh3ds
ensuite, on code la fonction :
on commence comme d'habitude :
int FaceDescriptionChunk(object3ds *objet3d, FILE *fichier, unsigned int lenght) { int start = ftell(fichier); unsigned short chunk_id; unsigned int chunk_lenght; while (ftell(fichier) < start + lenght){ fread (&chunk_id, 2, 1, fichier); fread (&chunk_lenght, 4, 1, fichier); switch(chunk_id){
on lit le opcode 0x4130 :
case 0x4130 :{ int num=objet3d->num_mesh-1; char temp; int i = 0;
on lit le nom du material :
do { fread (&temp, 1, 1, fichier); objet3d->mesh[num].material_name[i] = temp; i++; }while(temp != '\0');
on lit le nombres de faces où il faut appliquer le material:
fread (&objet3d->mesh[num].num_material_face, 2, 1, fichier);
on initialise les material_faces :
objet3d->mesh[num].material_face = (unsigned short*)malloc(sizeof(unsigned short)*objet3d->mesh[num].num_material_face);
et on lit les material_faces :
for(i=0;i<objet3d->mesh[num].num_material_face;i++){ fread (&objet3d->mesh[num].material_face[i], sizeof (unsigned short), 1, fichier);
on ferme :
} break; }
et on ferme la fonction :
default: { fseek(fichier, chunk_lenght-6, SEEK_CUR); } } } fseek(fichier, start+lenght, SEEK_SET); }

