So I've been trying to use Assimp to load models, I want to render them using triangles. So far I've tried loading the test models that come with assimp and if I load an already triangulated model everything works fine. However whenever I try to make assimp triangulate everything it just breaks the mesh completely. Here's the output if I just render a mesh without any settings using triangles, obviously its broken.
https://i.stack.imgur.com/8ituT.png
And if I triangulate it and merge the vertices it ends up looking like this
https://i.stack.imgur.com/N7m9v.png
Finally, calculating bitangents just destroys the mesh completely
Here's the code, I've commented out some of the postprocess settings I've tried
#ifndef MESH_H
#define MESH_H
#include "assimp\scene.h"
#include "assimp\mesh.h"
#include <vector>
#include "main.h"
static enum BUFFER_TYPES
{
VERTEX_BUFFER,
TEXCOORD_BUFFER,
NORMAL_BUFFER,
INDEX_BUFFER,
BITANGENT_BUFFER,
TANGENT_BUFFER
};
//A mesh can have several entries, this struct is used to store them properly
struct Entry
{
Entry(aiMesh *mesh);
~Entry();
void load(aiMesh *mesh);
void render();
//Vertex Array Object
unsigned int mVAO;
//Vertex, Normal, Texture, Index Buffer, TODO: add support for more buffers
unsigned int mVBOs[4];
//The amount of vertices
unsigned int mVerticesCount;
};
//The Mesh class
class Mesh
{
public:
Mesh(const char* fileName);
~Mesh();
void render();
//All the meshes in the array
std::vector<Entry*> mEntries;
private:
};
#endif
and the .cpp file
#include "Mesh.h"
#include <assimp\Importer.hpp>
#include <assimp\postprocess.h>
Entry::Entry(aiMesh *mesh)
{
mVBOs[VERTEX_BUFFER] = NULL;
mVBOs[TEXCOORD_BUFFER] = NULL;
mVBOs[NORMAL_BUFFER] = NULL;
mVBOs[INDEX_BUFFER] = NULL;
mVBOs[BITANGENT_BUFFER] = NULL;
mVBOs[TANGENT_BUFFER] = NULL;
//Generate our vertex arrays
glGenVertexArrays(1, &mVAO);
//Bind our vertex arrays
glBindVertexArray(mVAO);
//Each face has 3 vertices
//mVerticesCount = mesh->mNumFaces * 3;
mVerticesCount = mesh->mNumVertices;
//Check whether the mesh has any positions
if (mesh->HasPositions())
{
float *vertices = new float[mesh->mNumVertices * 3];
for (int i = 0; i < mesh->mNumVertices; ++i)
{
vertices[i * 3] = mesh->mVertices[i].x;
vertices[i * 3 + 1] = mesh->mVertices[i].y;
vertices[i * 3 + 2] = mesh->mVertices[i].z;
}
glGenBuffers(1, &mVBOs[VERTEX_BUFFER]);
glBindBuffer(GL_ARRAY_BUFFER, mVBOs[VERTEX_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, 3 * mesh->mNumVertices * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
delete vertices;
}
if (mesh->HasTextureCoords(0))
{
float *texCoords = new float[mesh->mNumVertices * 2];
for (int i = 0; i < mesh->mNumVertices; ++i)
{
texCoords[i * 2] = mesh->mTextureCoords[0][i].x;
texCoords[i * 2 + 1] = mesh->mTextureCoords[0][i].y;
}
glGenBuffers(1, &mVBOs[TEXCOORD_BUFFER]);
glBindBuffer(GL_ARRAY_BUFFER, mVBOs[TEXCOORD_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, 2 * mesh->mNumVertices * sizeof(GLfloat), texCoords, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1);
delete texCoords;
}
if (mesh->HasNormals())
{
float *normals = new float[mesh->mNumVertices * 3];
for (int i = 0; i < mesh->mNumVertices; ++i)
{
normals[i * 3] = mesh->mNormals[i].x;
normals[i * 3 + 1] = mesh->mNormals[i].y;
normals[i * 3 + 2] = mesh->mNormals[i].z;
}
glGenBuffers(1, &mVBOs[NORMAL_BUFFER]);
glBindBuffer(GL_ARRAY_BUFFER, mVBOs[NORMAL_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, 3 * mesh->mNumVertices * sizeof(GLfloat), normals, GL_STATIC_DRAW);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(2);
delete normals;
}
if (mesh->HasFaces())
{
unsigned int *indices = new unsigned int[mesh->mNumFaces * 3];
for (int i = 0; i < mesh->mNumFaces; ++i)
{
indices[i * 3] = mesh->mFaces[i].mIndices[0];
indices[i * 3 + 1] = mesh->mFaces[i].mIndices[1];
indices[i * 3 + 2] = mesh->mFaces[i].mIndices[2];
}
glGenBuffers(1, &mVBOs[INDEX_BUFFER]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mVBOs[INDEX_BUFFER]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * mesh->mNumFaces * sizeof(GLuint), indices, GL_STATIC_DRAW);
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(3);
delete indices;
}
if (mesh->HasTangentsAndBitangents())
{
float *bitangents = new float[mesh->mNumVertices * 3];
for (int i = 0; i < mesh->mNumVertices; ++i)
{
bitangents[i * 3] = mesh->mBitangents[i].x;
bitangents[i * 3 + 1] = mesh->mBitangents[i].y;
bitangents[i * 3 + 2] = mesh->mBitangents[i].z;
}
glGenBuffers(1, &mVBOs[BITANGENT_BUFFER]);
glBindBuffer(GL_ARRAY_BUFFER, mVBOs[BITANGENT_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, 3 * mesh->mNumVertices * sizeof(GLfloat), bitangents, GL_STATIC_DRAW);
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(4);
delete bitangents;
float *tangents = new float[mesh->mNumVertices * 3];
for (int i = 0; i < mesh->mNumVertices; ++i)
{
tangents[i * 3] = mesh->mTangents[i].x;
tangents[i * 3 + 1] = mesh->mTangents[i].y;
tangents[i * 3 + 2] = mesh->mTangents[i].z;
}
glGenBuffers(1, &mVBOs[TANGENT_BUFFER]);
glBindBuffer(GL_ARRAY_BUFFER, mVBOs[TANGENT_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, 3 * mesh->mNumVertices * sizeof(GLfloat), tangents, GL_STATIC_DRAW);
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(5);
delete tangents;
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
Entry::~Entry()
{
if (mVBOs[VERTEX_BUFFER])
glDeleteBuffers(1, &mVBOs[VERTEX_BUFFER]);
if (mVBOs[TEXCOORD_BUFFER])
glDeleteBuffers(1, &mVBOs[TEXCOORD_BUFFER]);
if (mVBOs[NORMAL_BUFFER])
glDeleteBuffers(1, &mVBOs[NORMAL_BUFFER]);
if (mVBOs[INDEX_BUFFER])
glDeleteBuffers(1, &mVBOs[INDEX_BUFFER]);
if (mVBOs[BITANGENT_BUFFER])
glDeleteBuffers(1, &mVBOs[BITANGENT_BUFFER]);
if (mVBOs[TANGENT_BUFFER])
glDeleteBuffers(1, &mVBOs[TANGENT_BUFFER]);
glDeleteVertexArrays(1, &mVAO);
}
void Entry::render()
{
/*glBindVertexArray(mVAO);
glDrawElements(GL_TRIANGLES, mVerticesCount, GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);*/
glBindVertexArray(mVAO);
glDrawArrays(GL_TRIANGLES, 0, mVerticesCount);
glBindVertexArray(0);
}
Mesh::Mesh(const char* fileName)
{
Assimp::Importer importer;
//const aiScene* scene = importer.ReadFile(fileName,aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType);
//const aiScene* scene = importer.ReadFile(fileName, aiProcessPreset_TargetRealtime_Quality);
const aiScene* scene = importer.ReadFile(fileName, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices);
//importer.ApplyPostProcessing()
/*ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene * pScene,
unsigned int pFlags);*/
//aiApplyPostProcessing
if (!scene)
printf("There was an error loading mesh: %s\n", importer.GetErrorString());
for (int i = 0; i < scene->mNumMeshes; ++i)
mEntries.push_back(new Entry(scene->mMeshes[i]));
}
Mesh::~Mesh()
{
for (int i = 0; i < mEntries.size(); ++i)
delete mEntries.at(i);
mEntries.clear();
}
void Mesh::render()
{
for (int i = 0; i < mEntries.size(); ++i)
mEntries.at(i)->render();
}
You have to check our delete-ops by the way. For instance you creates indoces with new[] and deleted it with delete indices.