Assimp texturing mal placé
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)
http://qnop.free.fr/bug.png
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.
Code:
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;
}; |
Voilà tout d'abord la fonction load
Elle crée les shaders, ouvre le fichier, appelle les fonctions servant à construire le modèle
Code:
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;
} |
Ainsi que la fonction loadAllColorTexture.
Elle permet de récupérer chaque texture, et les couleurs diffuse et ambiante si il y a pour chaque mesh
Code:
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);
}
} |
Maintenant, la fonction getData
Pour chaque mesh, cette fonction récupère un IBO, un VBO, et l'index du matériel utilisé par ce mesh
Code:
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);
}
} |
La fonction getIbo
Cette fonction récupère les indices de toutes les faces et les met dans un IBO
Code:
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;
} |
La fonction getVbo
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
Code:
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
} |
Et enfin, même si je pense que ce n'est pas le plus important, la fonction d'affichage
Code:
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);
} |
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 '-' )...
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.