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\$
1
  • \$\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, 2016 at 11:10

1 Answer 1

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\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .