在c++中创建自定义类的原生数组

Creating Native Array of Custom Class in C++

本文关键字:原生 数组 自定义 c++ 创建      更新时间:2023-10-16

我正在尝试创建一个本机对象数组,我必须一遍又一遍地重申OpenGL。

所以性能是关键。

问题是,似乎我的对象数组最终是指向任何地方的指针,或者数组从未创建。

无论如何,这里是相关类的问题:

    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);
    };

我的构造函数/拆解:

    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));
    }

在"manager"类中,我是如何实例化数组以及定义用于控制集合的函数的:

    /*
    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;
    }

当我尝试使用数组时,问题出现了。

    /*
    Inside a draw call function in the GlManagerClass.
    */
    for (GLuint i = 0; i < NumberOfItemsToDraw; i++) {
        CollectionOfItemsToDraw[i].DrawMe(this);
    }

我从列表中取出一个元素,然后其余的都是垃圾数据。

是不是缺少了什么我没有做的事情?

感谢您的宝贵时间。

编辑

也许我应该解释一下这应该是如何工作的。

我的OpenGL程序有一个标准的工作流和你在上面看到的工作流。

标准的工作流工作得很好;我想要创建的是一个非常快的高速"缓存"OpenGL(索引顶点属性ID和材料ID)的绘制调用的重要元素,这样我就可以创建一个非常快的"OnDisplay"或OnDraw循环。

尤其是对于那些变化不大的东西。

因此,程序第一次在一个工作流中运行,然后填充我试图在上面构建的数组。

在第二次和随后的运行中,我希望我的程序换档并使用上面看到的高速循环,这样我就可以循环遍历上面看到的数组并根据id进行绘制。

理论上应该更快。

这就是为什么我希望使用本机数组,所有的"vector"和其他来自库的数组都会增加额外的开销,特别是在迭代循环上,这样额外的毫秒加起来。

我找不到任何会导致您提到的问题的bug。但是你的代码中有一些愚蠢的错误。其中两个是@Mat指出的。这是另一个

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;
    }
}

正如注释所指出的,对象数组是在分配内存时填充的。因此,在循环中再次创建和赋值是多余的。

因此,我怀疑在您的完整代码中可能存在其他类似的错误,这导致了您得到的错误。我发现GlManagerClass::SaveItemToDraw可疑,你真的传递有效的对象指针或破坏它?