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.