1
\$\begingroup\$

I want to be able to create Entities from different Component sets. I want to call Entity entity(new StaticObject(modelpath, position)); I have an EntityTypes Header:

struct EntityType
{
public:
    std::vector<Component*> components;

};

struct StaticObject :public EntityType {
    StaticObject(std::string meshPath, glm::vec3 Position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 Orientation = glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3 scale = glm::vec3(1.0f, 1.0f, 1.0f));
    Mesh mesh;
    Space space;
};

In its constructor I initialize the members Mesh and Space and push their address to the back of std::vector<Component*> components;

My Entity then takes the pointer to the StaticObject type (with the member vector components) and inserts the pointers to the components into a multimap, together with its unique entity ID (std::multimap<unsigned int, Component*> entityComponents contains all component instances in my game and I can access them with the entity IDs).

In my loadMesh() function I find the mesh of entityID I want to load, create a vaoID and give it to the component (together with the number of vertices and indices). But when I try to render the mesh using that data from my entityComponents multimap, my mesh won't render. I checked with debugging breakpoints and the vao id and number of indices are being initialized correctly.

void Graphic::loadMesh()
{
    for (unsigned int c = 0; c < Component::entityComponents.size(); ++c) {
        std::multimap<unsigned int, Component*>::iterator cItr = Component::entityComponents.find(c);
        std::multimap<unsigned int, Component*>::iterator lastC = Component::entityComponents.upper_bound(c);
        if(cItr != Component::entityComponents.end())
        for (; cItr != lastC; ++cItr) {
            Component& curCom = *cItr->second;

            if (curCom.getComType() == ComType::Mesh) {
                GLuint vaoID;
                GLuint vboID;
                GLuint iboID;
                Vertex* vertexArray = nullptr;
                unsigned int* indexArray = nullptr;
                unsigned int vertexNum = 0;
                unsigned int indexNum = 0;


                if (curCom.getPath() == "cube" || curCom.getPath() == "Cube") {
                    vertexNum = 8;
                    indexNum = 36;
                    vertexArray = new Vertex[vertexNum];
                    indexArray = new unsigned int[indexNum];

                    vertexArray[0].position.x = -1.0f;
                    ....
                    vertexArray[7].position.z = +1.0f;

                    for (int i = 0; i < 8; i++) {
                        vertexArray[i].color.r = 1.0f
                        ...
                        vertexArray[i].color.a = 1.0f;
                        vertexArray[i].position.w = 1.0f;
                    }



                    indexArray[0] = 2;
                    ...
                    indexArray[35] = 2;
                }
            }

                glCreateVertexArrays(1, &vaoID);
                glGenBuffers(1, &vboID);
                glGenBuffers(1, &iboID);


                //associate vertexArray with vboID and indexArray with iboID
                glNamedBufferStorage(vboID, sizeof(Vertex)*vertexNum, &vertexArray[0], 0);
                glNamedBufferStorage(iboID, sizeof(unsigned int)*indexNum, &indexArray[0], 0);
                glVertexArrayElementBuffer(vaoID, iboID);
                //vaoID vertex attrib array binding location 0 -> vboID
                glVertexArrayVertexBuffer(vaoID, 0, vboID, 0, sizeof(Vertex));

                //vao binding location 0 -> attribute 0
                glVertexArrayAttribBinding(vaoID, 0, 0);
                glVertexArrayAttribFormat(vaoID, 0, 4, GL_FLOAT, GL_FALSE, offsetof(Vertex, position));

                glVertexArrayAttribBinding(vaoID, 1, 0);
                glVertexArrayAttribFormat(vaoID, 1, 4, GL_FLOAT, GL_FALSE, offsetof(Vertex, color));


                cItr->second->setVAO(vaoID);
                cItr->second->setVertexNum(vertexNum);
                cItr->second->setIndexNum(indexNum);
            }
        }
    }
}

void Graphic::render()
{
    for (unsigned int c = 0; c < Component::entityComponents.size(); ++c) {
        std::multimap<unsigned int, Component*>::iterator cItr = Component::entityComponents.find(c);
        std::multimap<unsigned int, Component*>::iterator lastC = Component::entityComponents.upper_bound(c);

        if(cItr != Component::entityComponents.end()){


            for (; cItr != lastC; ++cItr) {
                if (cItr->second->getComType() == ComType::Space) {
                    glm::vec3 position = cItr->second->getPos();
                    glm::mat4 translate = glm::translate(Camera::camMatrix(), position);
                    glm::mat4 rotate = glm::rotate(translate, 2.0f, glm::vec3(1.0f, 0.0f, 0.0f));
                    glm::mat4 fullMatrix = glm::scale(rotate, glm::vec3(1.0f, 1.0f, 1.0f));
                    currentShader.addUniform("transformationMatrix", fullMatrix);
                }
                if (cItr->second->getComType() == ComType::Mesh) {
                    GLuint vaoID = cItr->second->getVAO();
                    unsigned int indexNum = cItr->second->getIndexNum();
                    glBindVertexArray(vaoID);
                    glEnableVertexArrayAttrib(vaoID, 0);
                    glEnableVertexArrayAttrib(vaoID, 1);
                    glDrawElements(GL_TRIANGLES, indexNum, GL_UNSIGNED_INT, nullptr);
                    glBindVertexArray(0);
                }
            }
        }
    }
}

one thing that might be causing it is my Component implementation. Though this would be weird because when I check the values of the vaos and index numbers, everything is correct. But as you can see my component implementation is kind of whacky, because I need to be able to access the member functions of the sub-structs through a Component*:

    enum class ComType {
    Space,
    Movement,
    Mesh
};

///OPTIMIZE POLYMORPHISM
struct Component
{

    static std::multimap<unsigned int, Component*> entityComponents;
    virtual ComType getComType() = 0;
    //SPACE
    virtual glm::vec3 getPos() = 0;
    virtual glm::vec3 getFront() = 0;
    virtual glm::vec3 getScale() = 0;
    //MOVEMENT
    virtual glm::vec3 getDir() = 0;
    virtual float getSpeed() = 0;
    //MESH
    virtual std::string getPath() = 0;
    virtual GLuint getVAO() = 0;
    virtual unsigned int getVertexNum() = 0;
    virtual unsigned int getIndexNum() = 0;

    //SETTERS
    virtual void setVAO(GLuint& VAO) {};
    virtual void setVertexNum(unsigned int VertexNum) {}
    virtual void setIndexNum(unsigned int IndexNum) {}
};

struct Space :public Component{
    const ComType type = ComType::Space;
    glm::vec3 position;
    glm::vec3 orientation;
    glm::vec3 scale;

    //GETTERS
    ComType getComType() { return type; }
    glm::vec3 getPos() { return position; }
    glm::vec3 getFront() { return orientation; }
    glm::vec3 getScale() { return scale; }

    glm::vec3 getDir() { return glm::vec3(); }
    float getSpeed() { return 0.0f; }
    std::string getPath() { return ""; }
    GLuint getVAO() { return 0; }
    unsigned int getVertexNum() { return 0; }
    unsigned int getIndexNum() { return 0; }
};

struct Movement :public Component {
    const ComType type = ComType::Movement;
    glm::vec3 direction;
    float speed;

    //GETTERS
    ComType getComType() { return type; }
    glm::vec3 getDir() { return direction; }
    float getSpeed() { return speed; }

    glm::vec3 getPos() { return glm::vec3(); }
    glm::vec3 getFront() { return glm::vec3(); }
    glm::vec3 getScale() { return glm::vec3(); }
    std::string getPath() { return ""; }
    GLuint getVAO() { return 0; }
    unsigned int getVertexNum() { return 0; }
    unsigned int getIndexNum() { return 0; }

};

struct Mesh :public Component {
    const ComType type = ComType::Mesh;
    std::string filePath = "";
    GLuint vaoID = 0;
    GLuint textureID = 0;
    Vertex* vertexArray = nullptr;
    unsigned int* indexArray = nullptr;
    unsigned int vertexNum = 0;
    unsigned int indexNum = 0;

    //GETTERS
    ComType getComType() { return type; }
    std::string getPath() { return filePath; }
    GLuint getVAO() { return vaoID; }
    unsigned int getVertexNum() { return vertexNum; }
    unsigned int getIndexNum() { return indexNum; }



    glm::vec3 getDir() { return glm::vec3(); }
    float getSpeed() { return 0.0f; }
    glm::vec3 getPos() { return glm::vec3(); }
    glm::vec3 getFront() { return glm::vec3(); }
    glm::vec3 getScale() { return glm::vec3(); }

    //SETTERS
    void setVAO(GLuint& VAO) { vaoID = VAO; }
    virtual void setVertexNum(unsigned int VertexNum) { vertexNum = VertexNum; }
    virtual void setIndexNum(unsigned int IndexNum) { indexNum = IndexNum; }
};

I hope these snippets are enough.

\$\endgroup\$
  • \$\begingroup\$ For this issue and all the ones that will follow, you should really add error checking to all of your OpenGL calls. \$\endgroup\$ – Quentin Nov 18 '16 at 11:10
0
\$\begingroup\$

Okay its fixed now, but i dont know why. I played around and started copying the rendering in the loading function and then i called the loading function every frame (together with my other rendering function). i got 2 cubes, which had me wondering because i expected one (from the loadMesh function). when i erased the rendering part from the loadMesh function the one cube from the render() function stayed there! i dont know what happened, but it just works now. it might be because i called

    glEnableVertexArrayAttrib(vaoID, 0); 
    glEnableVertexArrayAttrib(vaoID, 1); 

when i copied the rendering part but i am not calling it anymore now and it still works! really weird.

EDIT: it looks like i HAVE to use glCreateBuffers instead of glGenBuffers. that was literally it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.