Я использую AssImp для загрузки модели, созданной в Blender и экспортированной в формат файла .obj. И GLFW, GLEW и GLM для рендеринга загруженной модели. Моя проблема в том, что сейчас AssImp даже не загружает модель, и я просто получаю сообщение об ошибке ERROR::ASSIMP::Unable to open file "MyFile.obj"
. Это класс, который я использую, чтобы импортировать модель и позже нарисовать ее.
#pragma once
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <SOIL2/SOIL2.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include "MeinMesh.h"
using namespace std;
GLint TextureFromFile(const char* path, string directory);
class Model
{
public:
//Konstruktor mit pfad zum Model aufrufen
Model(const GLchar* path)
{
this->loadModel(path);
}
// Modell zeichnen
void Draw(Shader shader)
{
for (GLuint i = 0; i < this->meshes.size(); i++)
{
this->meshes[i].Draw(shader);
}
}
private:
//Daten für das Modell
vector<Mesh> meshes;
string directory;
vector<Texture> textures_loaded;
void loadModel(string path)
{
//Datei mit Assimp auslesen
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
cout << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
return;
}
this->directory = path.substr(0, path.find_last_of('/'));
this->processNode(scene->mRootNode, scene);
}
void processNode(aiNode* node, const aiScene* scene)
{
for (GLuint i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
this->meshes.push_back(this->processMesh(mesh, scene));
}
for (GLuint i = 0; i < node->mNumChildren; i++)
{
this->processNode(node->mChildren[i], scene);
}
}
Mesh processMesh(aiMesh* mesh, const aiScene* scene)
{
vector<Vertex> vertices;
vector<GLuint> indices;
vector<Texture> textures;
for (GLuint i = 0; i < mesh->mNumVertices; i++)
{
Vertex vertex;
glm::vec3 vector;
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
if (mesh->mTextureCoords[0])
{
glm::vec2 vec;
vec.x = mesh->mTextureCoords[0][i].x;
vec.y = mesh->mTextureCoords[0][i].y;
vertex.TexCoords = vec;
}
else
{
vertex.TexCoords = glm::vec2(0.0f, 0.0f);
}
vertices.push_back( vertex );
}
for (GLuint i = 0; i < mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
for (GLuint j = 0; j < face.mNumIndices; j++)
{
indices.push_back( face.mIndices[j] );
}
}
if (mesh->mMaterialIndex >= 0)
{
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
vector<Texture> specularMaps = this->loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
}
return Mesh(vertices, indices, textures);
}
vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName)
{
vector<Texture> textures;
for ( GLuint i=0; i < mat->GetTextureCount(type); i++ )
{
aiString str;
mat->GetTexture(type, i, &str);
GLboolean skip = false;
//Textur wurde bereits geladen => überspringen
for (GLuint j = 0; j < textures_loaded.size(); j++)
{
if (textures_loaded[j].path == str)
{
textures.push_back(textures_loaded[j]);
skip = true;
break;
}
}
//Texture wurde noch nicht geladen
if (!skip)
{
Texture texture;
texture.id = TextureFromFile(str.C_Str(), this->directory);
texture.type = typeName;
texture.path = str;
textures.push_back(texture);
this->textures_loaded.push_back(texture);
}
}
return textures;
}
};
GLint TextureFromFile(const char* path, string directory)
{
string filename = string(path);
filename = directory + '/' + filename;
GLuint textureID;
glGenTextures( 1, &textureID );
int width, height;
unsigned char* image = SOIL_load_image(filename.c_str(), &width, &height, 0, SOIL_LOAD_RGB);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
SOIL_free_image_data(image);
return textureID;
}
Это код, который я использую для настройки Me sh, составляющего мои Модели. Хотя я получаю предупреждение из этого файла, в котором говорится, что переменная «Texture :: id» не инициализируется, хотя она явно.
#pragma once
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <vector>
#include "Shader.h"
#include <gl/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <assimp/types.h>
using namespace std;
struct Vertex
{
glm::vec3 Position;
glm::vec3 Normal;
glm::vec2 TexCoords;
};
struct Texture
{
GLuint id;
string type;
aiString path;
};
class Mesh
{
public:
vector<Vertex> vertices;
vector<GLuint> indices;
vector<Texture> textures;
Mesh(vector<Vertex> vertices, vector<GLuint> indices, vector<Texture> textures)
{
this->vertices = vertices;
this->indices = indices;
this->textures = textures;
this->SetupMesh();
}
void Draw(Shader shader)
{
GLuint diffuseNr = 1;
GLuint specularNr = 1;
for (GLuint i = 0; i < this->textures.size(); i++)
{
glActiveTexture(GL_TEXTURE + i);
stringstream ss;
string number;
string name = this->textures[i].type;
if ("texture_diffuse" == name)
{
ss << diffuseNr++;
}
else if ("texture_specular" == name)
{
ss << specularNr++;
}
number = ss.str();
glUniform1i(glGetUniformLocation(shader.Program, (name + number).c_str()), i);
glBindTexture(GL_TEXTURE_2D, this->textures[i].id);
}
//Draw the Mesh
glBindVertexArray(this->VAO);
glDrawElements(GL_TRIANGLES, this->indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
for ( GLuint i = 0; i < this-> textures.size(); i++)
{
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
private:
GLuint VAO, VBO, EBO;
void SetupMesh()
{
glGenVertexArrays( 1, &this->VAO);
glGenBuffers( 1, &this->VBO);
glGenBuffers(1, &this->EBO);
glBindVertexArray(this->VAO);
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(Vertex), &this->vertices[0], GL_STATIC_DRAW);
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, this->EBO );
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(GLuint), &this->indices[0], GL_STATIC_DRAW);
//Vertex Positionen
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0);
//Vertex Normals
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof( Vertex, Normal));
//Vertex Texture coordinates
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof( Vertex,TexCoords ));
glBindVertexArray(0);
}
};
И это класс, который я использую для открытия и позже Заполните окно, вызвав его из моего главного окна. cpp
#include "MeinMesh.h"
#include "Shader.h"
#include "Model.h"
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
OpenWindow::OpenWindow(const std::string& title, unsigned int width, unsigned int height)
:m_Title(title), m_Width(width), m_Height(height), m_Window(nullptr)
{
/* GLFW initialisieren */
if (!glfwInit())
return;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
/* Erschaffen des des Windows und Context */
m_Window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);
if (!m_Window)
{
glfwTerminate();
return;
}
glfwMakeContextCurrent(m_Window);
/* Initialiesieren der GLEW Lib*/
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
/*Glew konnte nicht initialisiert werden*/
fprintf(stderr, "error: %s\n", glewGetErrorString(err));
std::cout << "GLEW konnte nicht gestartet werden";
}
//Viewport einrichten
glViewport(0, 0, width, height);
//Depth enable
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << std::endl;
std::cout << glGetString(GL_VENDOR) << std::endl;
}
/* Getting Infos about the Window*/
std::string OpenWindow::GetTitle() const
{
return m_Title;
}
unsigned int OpenWindow::GetWidth() const
{
return m_Width;
}
unsigned int OpenWindow::GetHeight()const
{
return m_Height;
}
// Drawing in the Window
void OpenWindow::Show()
{ //Setup Shader
glm::mat4 projection;
projection = glm::perspective(45.0f, (GLfloat)m_Width / (GLfloat)m_Height, 0.1f, 1000.0f);
Shader myShader("core.vs", "core.frag");
Model Castle("Burg und Rammbock.obj");
Model ram("Rammbock.obj");
bool close = false;
while (!glfwWindowShouldClose(m_Window) )
{
//Render
// Colourbuffer leeren
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
myShader.StartShader();
//Projection Matrix
glm::mat4 model;
glm::mat4 view;
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
GLint modelLoc = glGetUniformLocation(myShader.Program, "model");
GLint viewLoc = glGetUniformLocation(myShader.Program, "view");
GLint projectionLoc = glGetUniformLocation(myShader.Program, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
// Zeichnen der Modelle
Castle.Draw(myShader);
ram.Draw(myShader);
//Screen Buffer wechseln
glfwSwapBuffers(m_Window);
}
glfwTerminate();
}
Я добавил файлы для моделей в проект, и AssImp правильно скомпилирован. Я пытался использовать разные форматы файлов и UTF8 и UTF16, я исключил файлы .obj из сборки, но независимо от того, что я сделал, AssImp не может загрузить файлы.