Bonjour à vous tous, et oui, c'est encore moi, et j'ai encore un problème.
Je pensais me servir comme il faut de la lib Assimp, mais en fait non ^^
Mon problème est que les coordonnées de textures (normales je ne sais pas) sont mauvaises, mais pas les vertex, ce n'est pas un problème de (1 - y)
Vous voyez, c'est pas très beau.
Voici mon code, j’espère qu'il est assez commenté.
Je résonne par "un tableau / mesh", c'est pour ça qu'il y a beaucoup de vector.
Voilà tout d'abord la fonction load
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 class Model { public : Model(void); Model(string const &filePath); Model(Model const &model); Model &operator=(Model const &model); void load(string const &filePath); void draw(ModelViewStackMatrix const &projModelview); bool isInit(void) const {return m_IsInit;} void drop(void); ~Model(void); private : bool m_IsInit; // Chaque mesh possède son propre VBO indicé vector<VBO> m_Vbo; vector<VBO> m_Ibo; unsigned m_NMesh; // Nombre de Mesh vector<unsigned> m_NVertices; // Nombres de sommets // Contient la taille des différentes données par VBO vector<unsigned> m_SizeVertex; vector<unsigned> m_SizeNormal; vector<unsigned> m_SizeCoordTexture; vector<unsigned> m_SizeIndex; // Contient l'index du material par VBO vector<unsigned> m_IndexMaterial; vector<bool> m_UseNormal; // Est ce que le mesh utilise des normals? vector<bool> m_UseTexture; // Est ce que le mesh utilise une texture? string m_FilePath; // Chemin du fichier const aiScene *m_Scene; // Ce qui permet de gérer la scène // Map : Key : index du matériel, Value : Texture / Color map<unsigned, Texture> m_Texture; map<unsigned, vec4> m_ColorDiffuse; // Couleur diffuse map<unsigned, vec4> m_ColorAmbient; // Couleur ambiante /*********************************************************************/ string m_GetDir(string const &str); // Récupère le dossier du fichier void m_LoadAllColorTexture(void); // Récupère toutes les textures void m_GetData(void); // Récupère les IBO, VBO // Le i ici permet de savoir à quel mesh on se trouve void m_GetIbo(aiMesh const *mesh, int const &i); // Recupère les IBO void m_GetVbo(aiMesh const *mesh, int const &i); // Récupère les VBO static Assimp::Importer importer; static Shader shader; };
Elle crée les shaders, ouvre le fichier, appelle les fonctions servant à construire le modèle
Ainsi que la fonction loadAllColorTexture.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 void Model::load(string const &filePath) { // Première chose, si il n'est pas créer, on créer le shader if(shader.isInit() == false) shader.load("Shaders/Model.vert", "Shaders/Model.frag"); m_Scene = importer.ReadFile(filePath, aiProcessPreset_TargetRealtime_MaxQuality); if(m_Scene == NULL) return; m_FilePath = filePath; m_LoadAllColorTexture(); m_GetData(); m_IsInit = true; }
Elle permet de récupérer chaque texture, et les couleurs diffuse et ambiante si il y a pour chaque mesh
Maintenant, la fonction getData
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 string Model::m_GetDir(string const &str) { string res = str; // Supprime la partie situé après le dernier '/' res.erase(res.begin() + res.find_last_of('/') + 1, res.end()); return res; } void Model::m_LoadAllColorTexture(void) { for(unsigned i = 0; i != m_Scene->mNumMaterials; ++i) { aiReturn texFound = AI_SUCCESS; aiString pathTex; // pathTexture // On récupère le nom de la texture. texFound = m_Scene->mMaterials[i]->GetTexture(aiTextureType_DIFFUSE, 0, &pathTex); /* Le m_GetDir permet de retrouver l'adresse complète du dossier où se trouve le fichier 3D */ if(texFound == AI_SUCCESS) // On ajoute la texture si elle existe m_Texture[i] = Texture(m_GetDir(m_FilePath) + pathTex.data); // On récupère notre couleur diffuse aiColor4D c; if(aiGetMaterialColor(m_Scene->mMaterials[i], AI_MATKEY_COLOR_DIFFUSE, &c) == AI_SUCCESS) m_ColorDiffuse[i] = vec4(c.r, c.g, c.b, c.a); // On récupère notre couleur ambiente if(aiGetMaterialColor(m_Scene->mMaterials[i], AI_MATKEY_COLOR_AMBIENT, &c) == AI_SUCCESS) m_ColorAmbient[i] = vec4(c.r, c.g, c.b, c.a); } }
Pour chaque mesh, cette fonction récupère un IBO, un VBO, et l'index du matériel utilisé par ce mesh
La fonction getIbo
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 void Model::m_GetData(void) { m_NMesh = m_Scene->mNumMeshes; VBO vbo; // Pour chaque mesh for(unsigned i = 0; i < m_NMesh; ++i) { aiMesh *mesh = m_Scene->mMeshes[i]; m_GetIbo(mesh, i); m_GetVbo(mesh, i); //L'index du materiel afin de pouvoir afficher la bonne texture m_IndexMaterial.push_back(mesh->mMaterialIndex); } }
Cette fonction récupère les indices de toutes les faces et les met dans un IBO
La fonction getVbo
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 void Model::m_GetIbo(aiMesh const *mesh, int const &i) { VBO ibo; // On multiplie par 3 car 3 sommets dans une face (triangle) m_NVertices.push_back(mesh->mNumFaces * 3); // Nombre de sommets unsigned *index = new unsigned[m_NVertices[i]]; // donnée de l'IBO // Multiplication par sizeof unsigned pour avoir le nombre de byte m_SizeIndex.push_back(m_NVertices[i] * sizeof(unsigned)); // Pour chaque face for(unsigned t = 0; t < mesh->mNumFaces; ++t) { // On récupère la face. aiFace *faceActu = &mesh->mFaces[t]; // On copie les indices de la face dans notre tableau d'index // Toujours une multiplication par trois car 3 indices = une face memcpy(&index[t * 3], faceActu->mIndices, 3 * sizeof(unsigned)); } // On crée l'IBO ibo.allocate(m_SizeIndex[i], INDEX_BUFFER, NEVER_MODIFY); ibo.sendData(index, m_SizeIndex[i], 0); m_Ibo.push_back(ibo); // Copie de l'ibo // Libère de la mémoire ibo.drop(); delete[] index; }
Elle récupère le nombre de sommet, ajuste en conséquence la taille des normales, coordonnée de texture et des vertex et les envoie dans le VBO
en ajustant les offset
Et enfin, même si je pense que ce n'est pas le plus important, la fonction d'affichage
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 void Model::m_GetVbo(aiMesh const *mesh, int const &i) { VBO vbo; // On récupère les tailles des différentes composantes m_SizeVertex.push_back(mesh->mNumVertices * 3 * sizeof(float)); // Si il y a des normales if(mesh->HasNormals()) { m_SizeNormal.push_back(mesh->mNumVertices * 3 * sizeof(float)); m_UseNormal.push_back(true); } else { m_SizeNormal.push_back(0); m_UseNormal.push_back(false); } // Si il y a une texture if(mesh->HasTextureCoords(0)) { // 2 coordonnée pour une coordonnée de texture m_SizeCoordTexture.push_back(mesh->mNumVertices * 2 * sizeof(float)); m_UseTexture.push_back(true); } else { m_SizeCoordTexture.push_back(0); m_UseTexture.push_back(false); } // Maintenant que l'on a toutes les tailles, on créer le VBO vbo.allocate(m_SizeVertex[i] + m_SizeNormal[i] + m_SizeCoordTexture[i], ARRAY_BUFFER, NEVER_MODIFY); // On envoie les données une par une en utilisant l'offset vbo.sendData(mesh->mVertices, m_SizeVertex[i], 0); // vertex vbo.sendData(mesh->mNormals, m_SizeNormal[i], m_SizeVertex[i]); // normal vbo.sendData(mesh->mTextureCoords[0], m_SizeCoordTexture[i], m_SizeVertex[i] + m_SizeNormal[i]); // coordTexture m_Vbo.push_back(vbo); // On copie notre vbo vbo.drop(); // On le supprime }
Voilà, merci de votre aide, et désolé pour la taille du code que je viens de vous envoyer(mais ça pourra éventuellement servir à quelqu'un d'autre '-' )...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 void Model::draw(ModelViewStackMatrix const &mat) { shader.use(true); // Pour chaque mesh for(unsigned i = 0; i < m_NMesh; ++i) { m_Vbo[i].use(true); m_Ibo[i].use(true); shader.sendVar("in_Vertex", 3, BUFFER_OFFSET(0)); if(m_UseNormal[i]) { shader.sendVar("in_Normal", 3, BUFFER_OFFSET(m_SizeVertex[i])); } if(m_UseTexture[i]) { shader.sendVar("in_TexCoord", 2, BUFFER_OFFSET(m_SizeVertex[i] + m_SizeNormal[i])); } // Si il y a utilisation de texture, on recupère l'index du matériel if(m_UseTexture[i]) m_Texture[m_IndexMaterial[i]].use(); else // Sinon, on désactive la texture Texture::noUse(); shader.sendInt("useTex", m_UseTexture[i] ? 1 : 0); shader.sendVec4("colorDiffuse", m_ColorDiffuse[m_IndexMaterial[i]]); shader.sendVec4("colorAmbient", m_ColorAmbient[m_IndexMaterial[i]]); shader.sendMatrix4("projectionModelView", mat.getMatrix()); glDrawElements(GL_TRIANGLES, m_NVertices[i], GL_UNSIGNED_INT, 0); } shader.use(false); }
EDIT : Trouver l'erreur en lisant mieux la documentation, pour les coordonnées de texture, c'est un vecteur3D aussi, pas un vecteur2D, donc c'est normal que ça ne marchait pas ^^ Désolé du dérangement.
Partager