#include "OBJ.h"

OBJ::OBJ()
{
    //ctor
}

OBJ::~OBJ()
{
    //destructor
}

void OBJ::charger( std::string const src, GLuint samplerID, float vertMulti, float textMulti )
{
    // Attribution texture
    m_textID = samplerID;

    /// Chargement du fichier obj
    // Variables
    std::vector<float> v_coord(0); // Coordonnées des vertices
    std::vector<float> v_norm(0); // Normales
    std::vector<float> v_text(0); // Coordonnées de texture des vertices
    std::vector<uint32_t> v_face(0); // Stocke les faces

    std::ifstream fichier( src.c_str() );
    int taille;
    float nb;
    uint32_t id;
    std::string mot;

    // Test flux
    if ( !fichier ) {
        std::cout << "Erreur lors du chargement du fichier : " << src << std::endl;
        return;
    }

    // Connaître la taille du fichier
    fichier.seekg(0, std::ios::end);
    taille = fichier.tellg();
    fichier.seekg(0, std::ios::beg);

    // Lecture du fichier
    while ( fichier.tellg() < taille && fichier.tellg()!=-1 )
    {
        fichier >> mot;

        if ( mot == "v" ) { // Coordonnées des vertices
            for ( int i(0); i<3; i++ ) {
                fichier >> nb;
                v_coord.push_back(nb);
            }
        } else if ( mot == "vt" ) { // Coordonnées de texture des vertices
            for ( int i(0); i<2; i++ ) {
                fichier >> nb;
                v_text.push_back( nb );
            }
        } else if ( mot == "vn" ) { // Coordonnées des normales
            for ( int i(0); i<3; i++ ) {
                fichier >> nb;
                v_norm.push_back(nb);
            }
        } else if ( mot == "f" ) { // Réalisation d'une face
            for ( int i(0); i<9; i++ ) {
                fichier >> id;
                v_face.push_back(id);
            }
        }
        mot = "rien";
    }

    // Création des tableaux openGL
    int nbFaces( v_face.size() / 9 ); // Contient le nombre de triangles
    m_nbVec = nbFaces * 3; // Contient le nombre de vertices à afficher

    uint32_t tailleVertices( nbFaces*3*3 ); // 3 vertices de 3 coordonnées par face
    m_tailleVerticesBytes = tailleVertices * sizeof(float);
    m_vertices = new float[tailleVertices];

    uint32_t tailleNormales( nbFaces*3*3 ); // 3 normales de 3 coordonnées par face
    m_tailleNormalesBytes = tailleNormales * sizeof(float);
    m_normales = new float[tailleNormales];

    uint32_t tailleCoordText( nbFaces*3*2 ); // 3 vertices de 2 coordonnées par face
    m_tailleCoordTextureBytes = tailleCoordText * sizeof(float);
    m_coordTexture = new float[tailleCoordText];

    // Remplissage des tableaux openGL
    uint32_t i(0), j(0), k(0);
    for ( i = 0; i<v_face.size(); i+=3) // Remplissage des vertices
    {
        for ( j = 0; j<3; j++) {
            m_vertices[i+j] = v_coord[ (v_face[i]-1)*3+j ] * vertMulti;
            m_normales[i+j] = v_norm[ (v_face[i+2]-1)*3+j ];
        }
    }
    for ( i = 1; i<v_face.size(); i+=3) // Remplissage des coordonnées de texture
    {
        for ( j = 0; j<2; j++)
            m_coordTexture[k+j] = v_text[ (v_face[i]-1)*2+j ] * textMulti;
        k += 2;
    }

    /// Chargement Vertex Buffer Object
    // Destruction d'un éventuel ancien VBO
    if(glIsBuffer(m_vboID) == GL_TRUE)
        glDeleteBuffers(1, &m_vboID);

    // Génération de l'ID
    glGenBuffers(1, &m_vboID);

    // Verrouillage du VBO
    glBindBuffer(GL_ARRAY_BUFFER, m_vboID);

        // Allocation de la mémoire vidéo
        glBufferData(GL_ARRAY_BUFFER, m_tailleVerticesBytes + m_tailleNormalesBytes + m_tailleCoordTextureBytes, 0, GL_STATIC_DRAW);

        // Transfert des données
        glBufferSubData(GL_ARRAY_BUFFER, 0, m_tailleVerticesBytes, m_vertices);
        glBufferSubData(GL_ARRAY_BUFFER, m_tailleVerticesBytes, m_tailleNormalesBytes, m_normales);
        glBufferSubData(GL_ARRAY_BUFFER, m_tailleVerticesBytes+m_tailleNormalesBytes, m_tailleCoordTextureBytes, m_coordTexture);

    // Déverrouillage de l'objet
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    /// Chargement Vertex Array Object
    // Destruction d'un éventuel ancien VAO
    if(glIsVertexArray(m_vaoID) == GL_TRUE)
        glDeleteVertexArrays(1, &m_vaoID);

    // Génération de l'ID du VAO
    glGenVertexArrays(1, &m_vaoID);

    // Verrouillage du VAO
    glBindVertexArray(m_vaoID);

        // Verrouillage du VBO
        glBindBuffer(GL_ARRAY_BUFFER, m_vboID);

            // Accès aux vertices dans la mémoire vidéo
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
            glEnableVertexAttribArray(0);

            // Accès aux normales dans la mémoire vidéo
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(m_tailleVerticesBytes));
            glEnableVertexAttribArray(1);

            // Accès aux coordonnées de texture dans la mémoire vidéo
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(m_tailleVerticesBytes+m_tailleNormalesBytes));
            glEnableVertexAttribArray(2);

        // Déverrouillage du VBO
        glBindBuffer(GL_ARRAY_BUFFER, 0);

    // Déverrouillage du VAO
    glBindVertexArray(0);
}
