Sponza рэндэрлэх оролдлого 4, Mesh ачаалах, рэндэрлэх

Өмнөх постуудад материалуудыг нь ачаалж байсан бол одоо мэш буюу геометрийн өгөгдлүүдийг нь ачаалая.



Геометр өгөгдлийг хадгалах бүтцийн хувьд
typedef struct {
    GLuint vertexID;
    GLuint normalID;
    GLuint texcoordID;
    GLuint vaoID;
    int numFaces;
    int *faces;
    int material;
} Mesh;

Энд vertexID нь бүх геометрийн оройнуудыг агуулсан буфферийн ID-г төлөөлнө.
normalID нь геометрийн оройн нормалуудыг хадгалсан буфферийн ID-г төлөөлнө.
texcoordID нь текстур буулгалтын UV координатуудын буфферийн ID-г төлөөлнө.
vaoID нь vertex array object буюу эдгээр буфферүүдээ бүлэглэн авч явна.
faces нь зурагдах интексийн дарааллыг агуулна.
material нь энэ mesh-д хэрэглэгдэх өмнө тодорхойлсон материалын дугаарыг хадгална.

Одоогийн байдлаар зөвхөн diffuse текстуруудыг ашиглахаар байгаа. Shader ачаалах shader management талын функцүүдийг өмнө бичиж байсан RRC-TANK прожектоосоо авч ашиглалаа.

Vertex Shader
#version 330
layout(location=0) in vec4 in_position;
layout(location=1) in vec3 in_normal;
layout(location=2) in vec2 in_texcoord;
out vec2 varyingTexcoord;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
void main(void)
{
    gl_Position = (projectionMatrix * viewMatrix * modelMatrix) * in_position;
    varyingTexcoord = in_texcoord;
}


Fragment Shader
#version 330
uniform sampler2D material_diffuse_texture;
in vec2 varyingTexcoord;
out vec4 out_color;
void main(void)
{
    out_color = texture2D(material_diffuse_texture, vec2(varyingTexcoord.x,varyingTexcoord.y));
}




Main.cpp
#include <cstdlib>
#include <string>
#include <iostream>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/constants.hpp>
#include "MaterialManager.hpp"
#include "Material.hpp"
#include "ShaderManager.hpp"
#include "Shader.hpp"
#include "SceneObject.hpp"

using namespace std;


GLFWwindow *window;
int windowWidth = 1000;
int windowHeight = 800;

bool wKeyPressed;
bool sKeyPressed;
bool aKeyPressed;
bool dKeyPressed;
double mouseX, mouseY;
float speed = 150.09f;
float mouseSpeed = 0.04f;
glm::vec3 position = glm::vec3(0, 0, 5);
glm::vec3 direction;
//glm::vec3 right;
glm::vec3 up;
float horizontalAngle = 3.14159f;
float verticalAngle = 0.0f;
float fov = 60.0f;

glm::mat4 modelMatrix;
glm::mat4 viewMatrix;
glm::mat4 projectionMatrix;

void initWindow();
void disposeWindow();
void handleKeyboardInput(GLFWwindow *window, int key, int scancode, int action, int mods);
void processInput(float dt);

void processMaterial(aiMaterial* material, int index);
void processMesh(aiMesh* mesh, SceneObject *object);

/*
 * experiment with ASSIMP
 */
int main(int argc, char** argv) {
    initWindow();
    glfwSetKeyCallback(window, handleKeyboardInput);
    MaterialManager::getSingleton();
    ShaderManager* sm = ShaderManager::getSingleton();
    sm->CreateShaderProgram("phong");
    sm->AttachShader("phongVertex", VERTEX);
    sm->AttachShader("phongFragment", FRAGMENT);
    sm->LoadShaderSource("phongVertex", "shaders/phong.vert.glsl");
    sm->LoadShaderSource("phongFragment", "shaders/phong.frag.glsl");
    sm->CompileShader("phongVertex");
    sm->CompileShader("phongFragment");
    sm->AttachShaderToProgram("phong", "phongVertex");
    sm->AttachShaderToProgram("phong", "phongFragment");
    sm->LinkProgramObject("phong");
    std::cout << "ShaderProgram ID is " << (*sm)["phong"]->GetID() << std::endl;

    SceneObject *sceneObject = new SceneObject();

    std::string filePath = "sponza.obj";
    Assimp::Importer importer;
    const aiScene *scene = importer.ReadFile(
            filePath.c_str(),
            aiProcess_OptimizeGraph |
            aiProcess_OptimizeMeshes |
            aiProcess_ImproveCacheLocality |
            aiProcess_SplitLargeMeshes |
            aiProcess_Triangulate |
            aiProcess_JoinIdenticalVertices |
            aiProcess_SortByPType
            );
    if (!scene) {
        std::cout << "error in loading file : " << importer.GetErrorString() << std::endl;
        return 1;
    }
    std::cout << "number of meshes " << scene->mNumMeshes << std::endl;
    std::cout << "number of materials " << scene->mNumMaterials << std::endl;
    for (unsigned int i = 0; i < scene->mNumMaterials; i++) {
        processMaterial(scene->mMaterials[i], i);
    }
    for (unsigned int i = 0; i < scene->mNumMeshes; i++) {
        processMesh(scene->mMeshes[i], sceneObject);
    }

    projectionMatrix = glm::mat4(1.0f);
    viewMatrix = glm::mat4(1.0f);
    viewMatrix = glm::translate(viewMatrix, glm::vec3(0, 0, -2));
    glViewport(0, 0, (int) windowWidth, (int) windowHeight);
    projectionMatrix = glm::perspective(60.0f, (float) windowWidth / windowHeight, 1.0f, 10000.0f);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    glFrontFace(GL_CCW);

    GLuint programID = (*sm)["phong"]->GetID();
    float deltaTime = 0.0f;
    float startTime = glfwGetTime();
    float buffTime = 0.0;
    int counter = 0;
    while (!glfwWindowShouldClose(window)) {
        processInput(deltaTime);
        glClearColor(0.0f, 0.5f, 1.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUseProgram(programID);
        glUniformMatrix4fv(glGetUniformLocation(programID, "viewMatrix"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
        glUniformMatrix4fv(glGetUniformLocation(programID, "projectionMatrix"), 1, GL_FALSE, glm::value_ptr(projectionMatrix));
        sceneObject->render();
        glUseProgram(0);

        glfwSwapBuffers(window);
        glfwPollEvents();
        double lastTime = glfwGetTime();
        deltaTime = lastTime - startTime;
        startTime = lastTime;
        counter++;
        buffTime += deltaTime;
        if (buffTime > 1.0f) {
            buffTime = 0.0f;
            cout << "fps " << counter << endl;
            counter = 0;
        }
    }

    delete sceneObject;
    delete MaterialManager::getSingleton();
    delete ShaderManager::getSingleton();
    disposeWindow();
    return 0;
}

void processMesh(aiMesh* mesh, SceneObject *object) {
    if (mesh->mMaterialIndex == 5)
        return;
    float *normals, *textureCoordinates;
    float *vertices = (float *) malloc(4 * mesh->mNumVertices * sizeof (float));
    if (mesh->HasNormals())
        normals = (float *) malloc(3 * mesh->mNumVertices * sizeof (float));
    if (mesh->HasTextureCoords(0))
        textureCoordinates = (float *) malloc(2 * mesh->mNumVertices * sizeof (float));
    for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
        vertices[4 * i + 0] = mesh->mVertices[i].x;
        vertices[4 * i + 1] = mesh->mVertices[i].y;
        vertices[4 * i + 2] = mesh->mVertices[i].z;
        vertices[4 * i + 3] = 1.0f;
        if (mesh->HasNormals()) {
            normals[3 * i + 0] = mesh->mNormals[i].x;
            normals[3 * i + 1] = mesh->mNormals[i].y;
            normals[3 * i + 2] = mesh->mNormals[i].z;
        }
        if (mesh->HasTextureCoords(0)) {
            textureCoordinates[2 * i + 0] = mesh->mTextureCoords[0][i].x;
            textureCoordinates[2 * i + 1] = mesh->mTextureCoords[0][i].y;
        }
    }
    int *faces = (int *) malloc(3 * mesh->mNumFaces * sizeof (int));
    for (unsigned int i = 0; i < mesh->mNumFaces; i++) {
        faces[3 * i + 0] = mesh->mFaces[i].mIndices[0];
        faces[3 * i + 1] = mesh->mFaces[i].mIndices[1];
        faces[3 * i + 2] = mesh->mFaces[i].mIndices[2];
    }
    object->addMesh(vertices, mesh->mNumVertices, normals, mesh->mNumVertices, textureCoordinates, mesh->mNumVertices, faces, mesh->mNumFaces, mesh->mMaterialIndex);
}

void processMaterial(aiMaterial* material, int index) {
    MaterialManager *mm = MaterialManager::getSingleton();
    std::cout << "================ ID " << index << "====================" << std::endl;

    aiString materialName;

    // Get the name for managing purpose
    if (material->Get(AI_MATKEY_NAME, materialName) != AI_SUCCESS) {
        std::cout << "ERROR: while getting name of material" << std::endl;
    }

    aiString diffuseTexturePath, normalMapTexturePath, specularTexturePath;
    aiColor3D diffuseColor, ambientColor, specularColor, emissiveColor;
    float opacity, shininess;

    // Get diffuse color
    if (material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuseColor) != AI_SUCCESS) {
        std::cout << "ERROR: Could not get diffuse color for Material " << materialName.data << std::endl;
    }

    // Get ambient color
    if (material->Get(AI_MATKEY_COLOR_AMBIENT, ambientColor) != AI_SUCCESS) {
        std::cout << "ERROR: Could not get ambient color for Material " << materialName.data << std::endl;
    }

    // Get diffuse color
    if (material->Get(AI_MATKEY_COLOR_SPECULAR, specularColor) != AI_SUCCESS) {
        std::cout << "ERROR: Could not get specular color for Material " << materialName.data << std::endl;
    }

    // Get opacity
    if (material->Get(AI_MATKEY_OPACITY, opacity) != AI_SUCCESS) {
        std::cout << "ERROR: Could not get opacity for Material " << materialName.data << std::endl;
    }

    // Get emissive color
    if (material->Get(AI_MATKEY_COLOR_EMISSIVE, emissiveColor) != AI_SUCCESS)
        emissiveColor = aiColor3D(0);

    // Get shininess
    if (material->Get(AI_MATKEY_SHININESS, shininess) != AI_SUCCESS) {
        std::cout << "ERROR: Could not get Shininess for Material " << materialName.data << std::endl;
    }


    // material color parameters
    std::cout << "diffuse color [" << diffuseColor.r << "," << diffuseColor.g << "," << diffuseColor.b << "] opacity=" << opacity << std::endl;
    std::cout << "ambient color [" << ambientColor.r << "," << ambientColor.g << "," << ambientColor.b << "]" << std::endl;
    std::cout << "specular color [" << specularColor.r << "," << specularColor.g << "," << specularColor.b << "]" << std::endl;
    std::cout << "emissive color [" << emissiveColor.r << "," << emissiveColor.g << "," << emissiveColor.b << "]" << std::endl;


    Material *m = mm->createMaterial(std::string(materialName.data), index);
    m->setDiffuseColor(glm::vec4(diffuseColor.r, diffuseColor.g, diffuseColor.b, opacity));
    m->setAmbientColor(glm::vec3(ambientColor.r, ambientColor.g, ambientColor.b));
    m->setSpecularColor(glm::vec3(specularColor.r, specularColor.g, specularColor.b));
    m->setEmissiveColor(glm::vec3(emissiveColor.r, emissiveColor.g, emissiveColor.b));

    // Load diffuse texture if there is one
    if (material->GetTextureCount(aiTextureType_DIFFUSE) > 0) {
        if (material->Get(AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0), diffuseTexturePath) != AI_SUCCESS) {
            std::cout << "ERROR: Could not get Diffuse Texture for Material " << materialName.data << std::endl;
            return;
        }
        m->loadDiffuseTexture(diffuseTexturePath.data);
        std::cout << "diffuse texture path " << diffuseTexturePath.data << std::endl;
    }

    // Load height map texture if there is one
    if (material->GetTextureCount(aiTextureType_HEIGHT) > 0) {
        if (material->Get(AI_MATKEY_TEXTURE(aiTextureType_HEIGHT, 0), normalMapTexturePath) != AI_SUCCESS) {
            std::cout << "ERROR: Could not get Height Map Texture for Material " << materialName.data << std::endl;
            return;
        }
        m->loadNormalTexture(normalMapTexturePath.data);
        std::cout << "height map texture path " << normalMapTexturePath.data << std::endl;
    }

    // Load mask texture if there is one
    if (material->GetTextureCount(aiTextureType_SPECULAR) > 0) {
        if (material->Get(AI_MATKEY_TEXTURE(aiTextureType_SPECULAR, 0), specularTexturePath) != AI_SUCCESS) {
            std::cout << "ERROR: Could not get Mask Texture for Material " << materialName.data << std::endl;
            return;
        }
        m->loadSpecularTexture(specularTexturePath.data);
        std::cout << "specular texture path " << specularTexturePath.data << std::endl;
    }
    std::cout << "==========================================" << std::endl;
}

void initWindow() {
    if (!glfwInit()) {
        std::cout << "Error: GLFW failed to initialize.\n";
        return;
    }

    window = glfwCreateWindow(windowWidth, windowHeight, "OpenGL ASSIMP", NULL, NULL);
    if (!window) {
        std::cout << "Error: Failed to create window.\n";
        glfwTerminate();
        return;
    }
    glfwMakeContextCurrent(window);

    if (GLEW_OK != glewInit()) {
        std::cout << "Error: Failed to load OpenGL functions.\n";
        glfwTerminate();
        return;
    }
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
}

void disposeWindow() {
    glfwDestroyWindow(window);
    glfwTerminate();
}

void handleKeyboardInput(GLFWwindow *window, int key, int scancode, int action, int mods) {
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, 1);
    else if (key == GLFW_KEY_W && action == GLFW_PRESS)
        wKeyPressed = true;
    else if (key == GLFW_KEY_S && action == GLFW_PRESS)
        sKeyPressed = true;
    else if (key == GLFW_KEY_A && action == GLFW_PRESS)
        aKeyPressed = true;
    else if (key == GLFW_KEY_D && action == GLFW_PRESS)
        dKeyPressed = true;
    else if (key == GLFW_KEY_W && action == GLFW_RELEASE)
        wKeyPressed = false;
    else if (key == GLFW_KEY_S && action == GLFW_RELEASE)
        sKeyPressed = false;
    else if (key == GLFW_KEY_A && action == GLFW_RELEASE)
        aKeyPressed = false;
    else if (key == GLFW_KEY_D && action == GLFW_RELEASE)
        dKeyPressed = false;
}

void processInput(float dt) {
    static glm::vec3 right;
    if (wKeyPressed)
        position += direction * speed * dt;
    if (sKeyPressed)
        position -= direction * speed * dt;
    if (aKeyPressed)
        position -= right * speed * dt;
    if (dKeyPressed)
        position += right * speed * dt;

    direction = glm::vec3
            (
            std::cos(verticalAngle) * std::sin(horizontalAngle),
            std::sin(verticalAngle),
            std::cos(verticalAngle) * std::cos(horizontalAngle)
            );
    right = glm::vec3
            (
            std::sin(horizontalAngle - 3.14159f / 2.0f),
            0.0f,
            std::cos(horizontalAngle - 3.14159f / 2.0f)
            );
    up = glm::cross(right, direction);

    glfwGetCursorPos(window, &mouseX, &mouseY);
    glfwSetCursorPos(window, windowWidth / 2, windowHeight / 2);
    horizontalAngle += mouseSpeed * dt * float(windowWidth / 2 - mouseX);
    if (!up.y >= -0.5f)
        verticalAngle += mouseSpeed * dt * float(windowHeight / 2 - mouseY);
    else if (up.y == -1.0f)
        up = glm::vec3(up.x, 1, up.z);

    viewMatrix = glm::lookAt(position, position + direction, up);
}


Шинээр нэмсэн классууд
SceneObject.hpp
#ifndef SCENEOBJECT_HPP
#define SCENEOBJECT_HPP

#include <GL/glew.h>
#include <glm/glm.hpp>
#include <string>
#include <vector>

typedef struct {
    GLuint vertexID;
    GLuint normalID;
    GLuint texcoordID;
    GLuint vaoID;
    int numFaces;
    int *faces;
    int material;
    glm::vec3 boundingBoxMin;
    glm::vec3 boundingBoxMax;
} Mesh;

class SceneObject {
public:
    SceneObject();
    virtual ~SceneObject();
    void render();
    void update(float dt);
    void addMesh(float *vertices, int numVertices, float *normals, int numNormals, float *textureCoordinates, int numTextureCoordinates, int *faces, int numFaces, int materialIndex);
    void addMesh(float *vertices, int numVertices, float *normals, int numNormals, float *textureCoordinates, int numTextureCoordinates, int *faces, int numFaces, const std::string &materialName);
    glm::vec3 getBoundingBoxMin();
    glm::vec3 getBoundingBoxMax();
protected:
    std::vector<Mesh> meshes;
    glm::mat4 modelMatrix;
    glm::mat4 parentMatrix;
    glm::vec3 boundingBoxMin;
    glm::vec3 boundingBoxMax;
};

#endif /* SCENEOBJECT_HPP */

SceneObject.cpp
#include "SceneObject.hpp"
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include "MaterialManager.hpp"
#include "ShaderManager.hpp"

SceneObject::SceneObject() {
    this->modelMatrix = glm::mat4(1.0f);
    this->boundingBoxMin = glm::vec3(FLT_MAX);
    this->boundingBoxMax = glm::vec3(FLT_MIN);
}

SceneObject::~SceneObject() {
    std::cout << "desctructor function of the SceneObject" << std::endl;
    for (std::vector<Mesh>::iterator it = this->meshes.begin(); it != this->meshes.end(); it++) {
        Mesh mesh = (*it);
        glDeleteBuffers(1, &mesh.vertexID);
        glDeleteBuffers(1, &mesh.normalID);
        glDeleteBuffers(1, &mesh.texcoordID);
        glDeleteVertexArrays(1, &mesh.vaoID);
    }
}

void SceneObject::addMesh(float *vertices, int numVertices, float *normals, int numNormals, float *textureCoordinates, int numTextureCoordinates, int *faces, int numFaces, const std::string &materialName) {
    MaterialManager *mm = MaterialManager::getSingleton();
    int idx = mm->getMaterialIndex(materialName);

    this->addMesh(vertices, numVertices, normals, numNormals, textureCoordinates, numTextureCoordinates, faces, numFaces, idx);
}

void SceneObject::addMesh(float *vertices, int numVertices, float *normals, int numNormals, float *textureCoordinates, int numTextureCoordinates, int *faces, int numFaces, int materialIndex) {
    MaterialManager* mm = MaterialManager::getSingleton();
    GLuint programID = (*ShaderManager::getSingleton())["phong"]->GetID();

    GLuint positionAttrib = glGetAttribLocation(programID, "in_position");
    GLuint normalAttrib = glGetAttribLocation(programID, "in_normal");
    GLuint texcoordAttrib = glGetAttribLocation(programID, "in_texcoord");

    Mesh m;

    m.material = materialIndex;
    m.boundingBoxMin = glm::vec3(FLT_MAX);
    m.boundingBoxMax = glm::vec3(FLT_MIN);

    Material *mat = mm->getMaterial(materialIndex);

    glGenVertexArrays(1, &m.vaoID);
    glBindVertexArray(m.vaoID);

    if (numVertices > 0) {
        for (int i = 0; i < numVertices; i++) {
            if (vertices[4 * i + 0] < this->boundingBoxMin.x)
                this->boundingBoxMin.x = vertices[4 * i + 0];
            if (vertices[4 * i + 0] > this->boundingBoxMax.x)
                this->boundingBoxMax.x = vertices[4 * i + 0];

            if (vertices[4 * i + 1] < this->boundingBoxMin.y)
                this->boundingBoxMin.y = vertices[4 * i + 1];
            if (vertices[4 * i + 1] > this->boundingBoxMax.y)
                this->boundingBoxMax.y = vertices[4 * i + 1];

            if (vertices[4 * i + 2] < this->boundingBoxMin.z)
                this->boundingBoxMin.z = vertices[4 * i + 2];
            if (vertices[4 * i + 2] > this->boundingBoxMax.z)
                this->boundingBoxMax.z = vertices[4 * i + 2];

            if (vertices[4 * i + 0] < m.boundingBoxMin.x)
                m.boundingBoxMin.x = vertices[4 * i + 0];
            if (vertices[4 * i + 0] > m.boundingBoxMax.x)
                m.boundingBoxMax.x = vertices[4 * i + 0];

            if (vertices[4 * i + 1] < m.boundingBoxMin.y)
                m.boundingBoxMin.y = vertices[4 * i + 1];
            if (vertices[4 * i + 1] > m.boundingBoxMax.y)
                m.boundingBoxMax.y = vertices[4 * i + 1];

            if (vertices[4 * i + 2] < m.boundingBoxMin.z)
                m.boundingBoxMin.z = vertices[4 * i + 2];
            if (vertices[4 * i + 2] > m.boundingBoxMax.z)
                m.boundingBoxMax.z = vertices[4 * i + 2];

        }

        glGenBuffers(1, &m.vertexID);
        glBindBuffer(GL_ARRAY_BUFFER, m.vertexID);
        glBufferData(GL_ARRAY_BUFFER, numVertices * 4 * sizeof (GLfloat), vertices, GL_STATIC_DRAW);
        glEnableVertexAttribArray(positionAttrib);
        glVertexAttribPointer(positionAttrib, 4, GL_FLOAT, GL_FALSE, 0, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

    if (numNormals > 0) {
        glGenBuffers(1, &m.normalID);
        glBindBuffer(GL_ARRAY_BUFFER, m.normalID);
        glBufferData(GL_ARRAY_BUFFER, numNormals * 3 * sizeof (GLfloat), normals, GL_STATIC_DRAW);
        glEnableVertexAttribArray(normalAttrib);
        glVertexAttribPointer(normalAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

    if (numTextureCoordinates > 0) {
        glGenBuffers(1, &m.texcoordID);
        glBindBuffer(GL_ARRAY_BUFFER, m.texcoordID);
        glBufferData(GL_ARRAY_BUFFER, numTextureCoordinates * 2 * sizeof (GLfloat), textureCoordinates, GL_STATIC_DRAW);
        glEnableVertexAttribArray(texcoordAttrib);
        glVertexAttribPointer(texcoordAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

    m.faces = faces;
    m.numFaces = numFaces;

    glBindVertexArray(0);

    this->meshes.push_back(m);
}

void SceneObject::update(float dt) {

}

glm::vec3 SceneObject::getBoundingBoxMin() {
    return this->boundingBoxMin;
}

glm::vec3 SceneObject::getBoundingBoxMax() {
    return this->boundingBoxMax;
}

void SceneObject::render() {
    GLuint programID = (*ShaderManager::getSingleton())["phong"]->GetID();
    glUniformMatrix4fv(glGetUniformLocation(programID, "modelMatrix"), 1, GL_FALSE, glm::value_ptr(this->modelMatrix));
    MaterialManager *mm = MaterialManager::getSingleton();
    for (std::vector<Mesh>::iterator it = this->meshes.begin(); it != this->meshes.end(); it++) {
        Mesh m = (*it);
        Material *mat = mm->getMaterial(m.material);
        mat->bindMaterial(programID);
        glBindVertexArray(m.vaoID);
        glDrawElements(GL_TRIANGLES, 3 * m.numFaces, GL_UNSIGNED_INT, m.faces);
        glBindVertexArray(0);
        mat->unbindMaterial();
    }
}


Popular posts from this blog

Apache Spark + Cassandra. Hello World