Проблема загрузки текстур ASSIMP Qt6
Проблема в неверном наложении текстур, в течении 2 дней так и ненашёл решения проблемы.
Все действия вроде последовательные. Вопрос, где при работе с библиотекой assimp, я возможно выполняю не верное подгрузку либо бинд текстур?
Реализация создания mesh:
#ifndef MESH_H
#define MESH_H
#include <QString>
#include <QVector>
#include <QVector2D>
#include <QVector3D>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLExtraFunctions>
#include <QOpenGLFunctions>
#include <QOpenGLTexture>
#include <QOpenGLWidget>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#define MAX_BONE_INFLUENCE 4
struct Vertex {
QVector3D Position;
QVector3D Normal;
QVector2D TexCoords;
QVector3D Tangent;
QVector3D Bitangent;
int m_BoneIDs[MAX_BONE_INFLUENCE];
float m_Weights[MAX_BONE_INFLUENCE];
};
struct Texture {
QOpenGLTexture texture;
QString type;
QString path;
Texture() : texture(QOpenGLTexture::Target2D) {
texture.create();
texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
texture.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
texture.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
}
};
class Mesh {
public:
QVector<Vertex> vertices;
QVector<unsigned int> indices;
QVector<Texture *> textures;
QOpenGLShaderProgram * ShaderProgram;
Mesh(QOpenGLShaderProgram* shaderProgram);
~Mesh();
void Draw();
void setupMesh();
private:
QOpenGLVertexArrayObject VAO;
QOpenGLBuffer VBO,EBO;
};
#endif // MESH_H
#include "mesh.h"
Mesh::Mesh(QOpenGLShaderProgram* shaderProgram)
: ShaderProgram(shaderProgram)
, VBO(QOpenGLBuffer::VertexBuffer)
, EBO(QOpenGLBuffer::IndexBuffer) {
}
Mesh::~Mesh() {
VAO.destroy();
EBO.destroy();
VBO.destroy();
}
void Mesh::Draw() {
unsigned int diffuseNr = 1;
unsigned int specularNr = 1;
unsigned int normalNr = 1;
unsigned int heightNr = 1;
for(unsigned int i = 0; i < textures.size(); i++) {
QString number;
QString name = textures[i]->type;
if(name == "texture_diffuse")
number = QString::number(diffuseNr++);
else if(name == "texture_specular")
number = QString::number(specularNr++);
else if(name == "texture_normal")
number = QString::number(normalNr++);
else if(name == "texture_height")
number = QString::number(heightNr++);
ShaderProgram->setUniformValue((name + number).toStdString().c_str(), i);
textures[i]->texture.bind(i);
}
VAO.bind();
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
}
void Mesh::setupMesh() {
VAO.create();
VAO.bind();
VBO.create();
VBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
EBO.create();
EBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
VBO.bind();
VBO.allocate(vertices.data(), vertices.size() * sizeof(Vertex));
EBO.bind();
EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int));
ShaderProgram->enableAttributeArray(0);
ShaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Vertex));
ShaderProgram->enableAttributeArray(1);
ShaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, Normal), 3, sizeof(Vertex));
ShaderProgram->enableAttributeArray(2);
ShaderProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, TexCoords), 2, sizeof(Vertex));
ShaderProgram->enableAttributeArray(3);
ShaderProgram->setAttributeBuffer(3, GL_FLOAT, offsetof(Vertex, Tangent), 3, sizeof(Vertex));
ShaderProgram->enableAttributeArray(4);
ShaderProgram->setAttributeBuffer(4, GL_FLOAT, offsetof(Vertex, Bitangent), 3, sizeof(Vertex));
ShaderProgram->enableAttributeArray(5);
ShaderProgram->setAttributeBuffer(5, GL_INT, offsetof(Vertex, m_BoneIDs), 4, sizeof(Vertex));
ShaderProgram->enableAttributeArray(6);
ShaderProgram->setAttributeBuffer(6, GL_FLOAT, offsetof(Vertex, m_Weights), 4, sizeof(Vertex));
VAO.release();
}
#ifndef MODEL_H
#define MODEL_H
#include "mesh.h"
#include <QDir>
class Model {
public:
void draw();
void destroy();
static Model* createModel(QString path, QOpenGLShaderProgram* shaderProgram);
private:
Model(QString path, QOpenGLShaderProgram* shaderProgram);
~Model();
QOpenGLShaderProgram * ShaderProgram;
QVector <Texture *> Textures_loaded;
QVector <Mesh *> Meshes;
QDir directory;
void processNode(aiNode *node, const aiScene *scene);
Mesh* processMesh(aiMesh *mesh, const aiScene *scene);
QVector<Texture*> loadMaterialTextures(aiMaterial *mat, aiTextureType type,QString typeName);
};
#endif // MODEL_H
#include "model.h"
#include <QOpenGLTexture>
#include <QOpenGLContext>
Model::Model(QString path, QOpenGLShaderProgram * shaderProgram)
: ShaderProgram(shaderProgram)
, directory(path) {
Assimp::Importer import;
const aiScene *scene = import.ReadFile(directory.absolutePath().toLocal8Bit(), aiProcess_Triangulate | aiProcess_FlipUVs);
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
qDebug() << "ERROR::ASSIMP::"<< import.GetErrorString();
return;
}
directory.cdUp();
processNode(scene->mRootNode, scene);
}
Model::~Model () {
for(auto &it : Textures_loaded){
it->texture.destroy();
delete it;
}
for(auto &it : Meshes){
delete it;
}
}
void Model::draw() {
ShaderProgram->bind();
for(Mesh* mesh : Meshes){
mesh->Draw();
}
}
void Model::destroy() {
delete this;
}
Model *Model::createModel(QString path, QOpenGLShaderProgram *shaderProgram) {
return new Model(path, shaderProgram);
}
void Model::processNode(aiNode *node, const aiScene *scene) {
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
Meshes.push_back(processMesh(mesh, scene));
}
for (unsigned int i = 0; i < node->mNumChildren; i++) {
processNode(node->mChildren[i], scene);
}
}
Mesh* Model::processMesh(aiMesh *mesh,const aiScene *scene) {
Mesh* m_mesh = new Mesh(ShaderProgram);
for(unsigned int i = 0; i < mesh->mNumVertices; i++) {
Vertex vertex;
QVector3D vector;
vector.setX(mesh->mVertices[i].x) ;
vector.setY(mesh->mVertices[i].y) ;
vector.setZ(mesh->mVertices[i].z) ;
vertex.Position = vector;
if(mesh->mNormals) {
vector.setX(mesh->mNormals[i].x);
vector.setY(mesh->mNormals[i].y);
vector.setZ(mesh->mNormals[i].z);
vertex.Normal = vector;
}
if(mesh->mTextureCoords[0]) {
QVector2D vec;
vec.setX(mesh->mTextureCoords[0][i].x);
vec.setY(mesh->mTextureCoords[0][i].y);
vertex.TexCoords = vec;
} else{
vertex.TexCoords = QVector2D(0,0);
}
if(mesh->mTangents){
vector.setX(mesh->mTangents[i].x);
vector.setY(mesh->mTangents[i].y);
vector.setZ(mesh->mTangents[i].z);
vertex.Tangent = vector;
}
if(mesh->mBitangents){
vector.setX(mesh->mBitangents[i].x);
vector.setY(mesh->mBitangents[i].y);
vector.setZ(mesh->mBitangents[i].z);
vertex.Bitangent = vector;
}
m_mesh->vertices.push_back(vertex);
}
for(unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace face = mesh->mFaces[i];
for(unsigned int j = 0; j < face.mNumIndices; j++) {
m_mesh->indices.push_back(face.mIndices[j]);
}
}
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
QVector<Texture*> diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");
for(auto &it:diffuseMaps)
m_mesh->textures.push_back(it);
QVector<Texture*> specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
for(auto &it:specularMaps)
m_mesh->textures.push_back(it);
QVector<Texture*> normalMaps = loadMaterialTextures(material, aiTextureType_HEIGHT, "texture_normal");
for(auto &it:normalMaps)
m_mesh->textures.push_back(it);
QVector<Texture*> heightMaps = loadMaterialTextures(material, aiTextureType_AMBIENT, "texture_height");
for(auto &it:heightMaps)
m_mesh->textures.push_back(it);
m_mesh->setupMesh();
return m_mesh;
}
QVector<Texture*> Model::loadMaterialTextures(aiMaterial *mat, aiTextureType type, QString typeName) {
QVector<Texture*> textures;
for(unsigned int i = 0; i < mat->GetTextureCount(type); i++) {
aiString str;
mat->GetTexture(type, i, &str);
bool skip = false;
for(unsigned int j = 0; j < Textures_loaded.size(); j++) {
if(std::strcmp(Textures_loaded[j]->path.toStdString().c_str(), str.C_Str()) == 0) {
textures.push_back(Textures_loaded[j]);
skip = true;
break;
}
}
if(!skip) {
Texture* texture = new Texture;
QImage data(directory.filePath(str.C_Str()));
if(!data.isNull()){
texture->texture.setData(data);
texture->type = typeName;
texture->path = str.C_Str();
textures.push_back(texture);
Textures_loaded.push_back(texture);
} else{
qDebug () << "Не удалось успешно загружать текстуру:" << directory.filePath(str.C_Str());
}
}
}
return textures;
}
