3

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();
}
Johan
  • 121
  • 1
  • 11
  • Indices supposed to be used as index buffer, not vertex attribute. You cannot use `DrawArrays` here without unrolling vertex data; use index buffer and `DrawElements` instead. – keltar Jun 24 '15 at 17:14
  • Thanks, I tried switching it back and got better results now by using drawelements and aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType however, it still doesn't work when I try to use aiProcess_CalcTangentSpace it still destroys the mesh for some reason, and i know it has normals and it loads them into arrays successfully so I'm not sure what's wrong there – Johan Jun 24 '15 at 17:29
  • 1
    Other thing I've noticed is that you using vertex count as number of indices to draw. It may be incorrect if vertex arrays are deduplicated (i.e. the same vertex used multiple times by adjacent triangles). It should be `num_faces * 3`. – keltar Jun 24 '15 at 17:44

1 Answers1

0

You have to check our delete-ops by the way. For instance you creates indoces with new[] and deleted it with delete indices.

KimKulling
  • 2,654
  • 1
  • 15
  • 26