Вопрос

I am attempting to create a native array of objects which I have to reiterate through over and over again for OpenGL.

So performance is key.

The problem is that it seems like either my array of objects ends up being pointers to nowhere or the array is never created.

Anyway, here is the relevant class in question:

    class ItemToDraw {
        public:

        ItemToDraw();
        ~ItemToDraw();

        GLuint Vertex_VBO;
        GLuint Normal_VBO;
        GLuint UV_VBO;
        GLuint Index_VBO;
        GLuint Material_VBO;
        GLuint Pointer_VAO;

        GLuint ElementCount;
        GLuint Offset;

        GLfloat ObjectColor[4];
        GLfloat AmbientColor[4];
        GLfloat EmissiveColor[4];
        GLfloat DiffuseColor[4];
        GLfloat SpecularColor[4];
        GLfloat Shininess;

        glm::mat4 ModelMatrix;

        void DrawMe(GlManagerClass* CurrentOpenGLController);
    };

My constructor/deconstructor:

    ItemToDraw::ItemToDraw(){
        Vertex_VBO = 0;
        Normal_VBO = 0;
        UV_VBO = 0;
        Index_VBO = 0;
        Material_VBO = 0;
        Pointer_VAO = 0;

        ElementCount = 0;
        Offset = 0;

        for (int i = 0; i < 4; i++) {
            ObjectColor[i] = 0.0f;
            AmbientColor[i] = 0.0f;
            EmissiveColor[i] = 0.0f;
            DiffuseColor[i] = 0.0f;
            SpecularColor[i] = 0.0f;
        }

        Shininess = 0.0f;
        float initializer[16];

        for (int i = 0; i < 16; i++) {
            initializer[i] = 0.0f;
        }

        ModelMatrix = glm::make_mat4x4(initializer);
        }

        ItemToDraw::~ItemToDraw() {

        }

    void ItemToDraw::DrawMe(GlManagerClass* CurrentOpenGLController) {
        glm::mat4 ModelViewMatrix = CurrentOpenGLController->GetViewMatrix() * ModelMatrix;
        glm::mat3 NormalMatrix = glm::transpose(glm::inverse(glm::mat3(ModelViewMatrix)));
        glm::mat4 ModelViewProjectionMatrix = CurrentOpenGLController->GetProjectionViewMatrix() * ModelMatrix;
        glBindVertexArray(Pointer_VAO);
        glUniformMatrix3fv(CurrentOpenGLController->GetObjectOffsetPositionID(), 1, GL_FALSE,
            glm::value_ptr(NormalMatrix));
        glUniformMatrix4fv(CurrentOpenGLController->GetUniformGlobalPositionID(), 1, GL_FALSE, glm::value_ptr(ModelViewProjectionMatrix));
        glUniform4fv(CurrentOpenGLController->GetEmmissiveMeshColorID(), 1, EmissiveColor);
        glUniform4fv(CurrentOpenGLController->GetAmbientMeshColorID(), 1, AmbientColor);
        glUniform4fv(CurrentOpenGLController->GetDiffuseMeshColorID(), 1, DiffuseColor);
        glUniform4fv(CurrentOpenGLController->GetSpecularMeshColorID(), 1, SpecularColor);
        glUniform4fv(CurrentOpenGLController->GetMaterialColorID(), 1, ObjectColor);
        glUniform1f(CurrentOpenGLController->GetMeshShininessID(), Shininess);
        glDrawElements(GL_TRIANGLES, ElementCount, GL_UNSIGNED_INT, reinterpret_cast<const GLvoid *>(Offset));
    }

In the "manager" class, here is how I instantiated the array as well as defined functions for controlling the collection:

    /*

    Variables

    */

    ItemToDraw* CollectionOfItemsToDraw;
    GLuint NumberOfItemsToDraw;
    GLuint CurrentIndexOfItemToDraw;
    bool IsNumberOfItemsToDrawAmountComplete;

    /*

    EDIT: My constructor for the GlManagerClass have these lines:

    */

    NumberOfItemsToDraw = 0;
    CurrentIndexOfItemToDraw = 0;
    IsNumberOfItemsToDrawAmountComplete = false;


    /*

    Function Prototypes

    */

    void IterateItemToDraw();
    bool CreateItemToDraw();
    ItemToDraw* GetItemToDraw(GLuint IndexOfItemToRetrieve);
    GLuint GetCurrentItemNumber();
    void MoveToNextItem();

    /*

    Functions

    */

    void GlManagerClass::IterateItemToDraw() {
        CurrentIndexOfItemToDraw += 1;
    }

    bool GlManagerClass::CreateCollectionOfItemsToDraw() {
        if (IsCollectionOfItemToDrawComplete == true) {
            CollectionOfItemsToDraw = new ItemToDraw[NumberOfItemsToDraw];
            for (int i = 0; i < NumberOfItemsToDraw; i++) {
                ItemToDraw NewItem;
                CollectionOfItemsToDraw[i] = NewItem;
            }
            return true;
        }
        else {
            return false;
        }
    }

    ItemToDraw* GlManagerClass::GetItemToDraw(GLuint IndexOfElementToRetrieve) {
        if (IndexOfElementToRetrieve> (NumberOfItemsToDraw - 1) || IndexOfElementToRetrieve < 0) {
            return NULL;
        }
        else {
            return &CollectionOfItemsToDraw[IndexOfElementToRetrieve];
        }
    }

    bool GlManagerClass::SaveItemToDraw(ItemToDraw* ItemToSave, GLuint IndexOfElementToSave) {
        if (IndexOfElementToSave > (NumberOfItemsToDraw - 1) || IndexOfElementToSave < 0) {
            return false;
        }
        else {
            CollectionOfItemsToDraw[IndexOfElementToSave] = (*ItemToSave);
            return true;
        }
    }

    void GlManagerClass::MoveToNextItem() {
        CurrentIndexOfItemToDraw += 1;
        if (CurrentIndexOfItemToDraw == NumberOfItemsToDraw) {
            CurrentIndexOfItemToDraw = 0;
        }
    }

    GLuint GlManagerClass::GetCurrentItemNumber() {
        return CurrentIndexOfItemToDraw;
    }

The problem arises when I try to use the array.

    /*

    Inside a draw call function in the GlManagerClass.

    */

    for (GLuint i = 0; i < NumberOfItemsToDraw; i++) {
        CollectionOfItemsToDraw[i].DrawMe(this);
    }

I get one element out of the list and then the rest is garbage data.

Is there something missing that I am not doing?

Thank you for your time.

EDIT

Maybe I should explain a little about how this is supposed to work.

My OpenGL program has a standard workflow and the workflow you are seeing above.

The standard workflow works fine; what I am trying to create is an extremely fast high speed "cache" of the important elements for the draw calls of OpenGL (Index Vertex Attribute ID's and Material ID's) so that I can create an extremely fast "OnDisplay" or OnDraw loop.

Especially for things that do not change much.

Therefore, the program runs for the first time in one workflow and then populates the array I am trying to build above.

On the second and subsequent run, I want my program to shifts gears and use the high speed loop you see above so that I am JUST looping through the array you see above and drawing based on the IDs.

In theory that should be must faster.

That is why I wish to use native arrays, all of the "vector" and other arrays from libraries will add that extra overhead, especially on the iteration loop, such that the extra milliseconds add up.

Hope this makes sense.

Это было полезно?

Решение

I could not find any bug that would cause the problem you mentioned. But there are some silly bugs in your code. Two of them where pointed out by @Mat. Here is another one

bool GlManagerClass::CreateCollectionOfItemsToDraw() {
    if (IsCollectionOfItemToDrawComplete == true) {
        CollectionOfItemsToDraw = new ItemToDraw[NumberOfItemsToDraw]; // The objects are already created
        for (int i = 0; i < NumberOfItemsToDraw; i++) {
            ItemToDraw NewItem; // Here you are creating one object
            CollectionOfItemsToDraw[i] = NewItem; // and here assigning again
        }
        return true;
    }
    else {
        return false;
    }
}

As the comment points out, the array of object is populated when you are allocating memory. So in the loop creating and assigning again is redundant.

So I suspect there can be other similar bugs in your full code, which are causing the error you get. I find GlManagerClass::SaveItemToDraw suspicious, are you really passing valid object pointer or corrupting it?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top