如果我使用malloc()而不是堆栈数组,OpenGL不会渲染对象

OpenGL does not render objects if I use malloc() instead of stack arrays?

本文关键字:OpenGL 数组 对象 堆栈 malloc 如果      更新时间:2023-10-16

在C++中的2D OpenGL游戏项目中,我现在正试图从文件中读取"敌人数量",然后渲染这些敌人。每个敌人由2个具有纹理的三角形组成(2D精灵(。

我可以为保存单个"敌人"数据(例如每个敌人的位置(的结构体使用数组声明来实现渲染,但如果我尝试使用malloc根据从文件中读取的数字动态分配内存,则不会渲染任何内容。

我做错了什么?我真的很想使用malloc,因为敌人的数量会有所不同,我不想使用固定大小的数组。

关于下面的代码:基本上,一个名为"gameEnemies"的类包含一个称为"Enemy"的结构;每次创建"gameEnemies"类的对象时,该对象都应该分配足够的内存,以便根据外部文件中的定义创建尽可能多的敌人。

  1. 这是一个具有固定大小数组声明的结构-这个正在工作。

    struct Enemy {
    
    Point3D center; //object attributes
    Vector3D direction; //gets updated with current direction after rotations to show where object is facing at
    Vector3D collDir; //which direction collided
    float deltaX;
    float deltaY;
    float prevDeltaX;
    float prevDeltaY;
    float deltaA;
    float prevDeltaA;
    float speed;
    bool collided;
    int qtyCollided; //with how many other objects it collided
    bool alive;
    //matrices below passed as uniforms to shader
    //rotation
    Transform4D rotateTransf{ 1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f };
    //moves to world position after being drawn with center at origin (0,0)
    Transform4D modelTransf{  1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f };
    //translation of texture (animation), passed as uniform to shader
    Transform4D transformTex{ 1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f };
    }enemies[MAX_TMX_ENEMIES];
    
  2. 这是一个不起作用的结构,与上面的相同,只是声明了指针。

    struct Enemy {
    
    Point3D center; //object attributes
    Vector3D direction; //gets updated with current direction after rotations to show where object is facing at
    Vector3D collDir; //which direction collided
    float deltaX;
    float deltaY;
    float prevDeltaX;
    float prevDeltaY;
    float deltaA;
    float prevDeltaA;
    float speed;
    bool collided;
    int qtyCollided; //with how many other objects it collided
    bool alive;
    //matrices below passed as uniforms to shader
    //rotation
    Transform4D rotateTransf{ 1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f };
    //moves to world position after being drawn with center at origin (0,0)
    Transform4D modelTransf{  1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f };
    //translation of texture (animation), passed as uniform to shader
    Transform4D transformTex{ 1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f };
    }*enemies;
    
  3. 下面是分配内存加初始化值的循环-似乎可以工作,因为我可以访问数据,并且在编译时和运行时都没有错误:

    enemies = (Enemy*)malloc(sizeof(Enemy) * totalObj);
    for (int j = 0; j < totalObj; j++) //loop objects in the group
    {
    enemies[j].center = mapObj.getObjects(i)[j].center;
    enemies[j].direction = Vector3D{1.0f, 0.0f, 0.0f};
    enemies[j].deltaX = 0.0f;
    enemies[j].deltaY = 0.0f;
    enemies[j].prevDeltaX = 0.0f;
    enemies[j].prevDeltaY = 0.0f;
    enemies[j].deltaA = 0.0f;
    enemies[j].prevDeltaA = 0.0f;
    enemies[j].speed = 6.0f;
    enemies[j].collided = false;
    enemies[j].collDir = Vector3D{ 0.0f, 0.0f, 0.f };
    enemies[j].qtyCollided = 0;
    enemies[j].alive = true;
    enemies[j].modelTransf.SetTranslation(Point3D{ enemies[j].center.x, enemies[j].center.y, 0.0f }); //initial translation to world position
    enemies[j].rotateTransf.SetRotationZ(enemies[j].deltaA); //initial rotation = 0
    enemies[j].transformTex.SetTranslation(Point3D{ 0.0f, 0.0f, 0.0f }); //no transform on texture upon object creation
    }
    
  4. 下面是使用数组声明时初始化值的循环-唯一的变化是没有预设malloc:

    /*EXCLUDED: enemies = (Enemy*)malloc(sizeof(Enemy) * totalObj);*/
    for (int j = 0; j < totalObj; j++) //loop objects in the group
    {
    enemies[j].center = mapObj.getObjects(i)[j].center;
    enemies[j].direction = Vector3D{1.0f, 0.0f, 0.0f};
    enemies[j].deltaX = 0.0f;
    enemies[j].deltaY = 0.0f;
    enemies[j].prevDeltaX = 0.0f;
    enemies[j].prevDeltaY = 0.0f;
    enemies[j].deltaA = 0.0f;
    enemies[j].prevDeltaA = 0.0f;
    enemies[j].speed = 6.0f;
    enemies[j].collided = false;
    enemies[j].collDir = Vector3D{ 0.0f, 0.0f, 0.f };
    enemies[j].qtyCollided = 0;
    enemies[j].alive = true;
    enemies[j].modelTransf.SetTranslation(Point3D{ enemies[j].center.x, enemies[j].center.y, 0.0f }); //initial translation to world position
    enemies[j].rotateTransf.SetRotationZ(enemies[j].deltaA); //initial rotation = 0
    enemies[j].transformTex.SetTranslation(Point3D{ 0.0f, 0.0f, 0.0f }); //no transform on texture upon object creation
    }
    
  5. 下面的通用渲染函数:与数组配合良好,如果我使用malloc:,则不会渲染单个对象

    void render()
    {
    // shader to use
    objShader.use();
    objShader.setVec4("orthoTex", orthoTex); //common to all instances
    //for texture
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glBindTexture(GL_TEXTURE_2D, texture);
    glBindVertexArray(VAO);
    for(int i = 0; i< totalEnemies; i++)
    {
    //pass relevant uniforms to shader before drawing each instance
    objShader.setVec4("transfTex", enemies[i].transformTex);
    objShader.setVec4("modelTransf", enemies[i].modelTransf);
    objShader.setVec4("rotateTransf", enemies[i].rotateTransf);
    //draw
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    }
    glBindVertexArray(0);
    }
    
  6. Enemy结构位于一个名为"gameEnemies"的结构中——不确定这是否会改变什么,只是以防万一。这是因为所有"敌人"都将共享通用属性,如OpenGL缓冲区、顶点、着色器等。

    struct gameEnemies {
    protected:
    //arrays with vertex data and indices
    float vertices[16]; //holds vertex + texture coordinates for VBO (order: obj.x, obj.y, tex.x, tex.y, obj.x...)
    unsigned int indices[6]; //holds triangle indices for the EBO
    //the OpenGL buffers
    unsigned int VBO, VAO, EBO;
    //object shader
    Shader objShader;
    //texture ID
    unsigned int texture;
    float width;
    float height;
    int totalEnemies;
    int enemyMapPos; //position in the MAP OBJECT (which group) where enemies of specicif "label" for this handler are
    //transform texture coordinates to world (png file) coordinates (0,0 //bottom left to 1,1//top right)
    Transform4D orthoTex;
    struct Enemy {
    
    Point3D center; //object attributes
    Vector3D direction; //gets updated with current direction after rotations to show where object is facing at
    Vector3D collDir; //which direction collided
    float deltaX;
    float deltaY;
    float prevDeltaX;
    

    等等。。。

在C++中使用malloc是错误的,除非在非常特殊的情况下。

malloc分配内存,但不在内存中构造任何对象。试图使用内存,就像在内存中创建了Enemy的实例一样,会导致未定义的行为。

您需要使用new[]。它分配内存并构造对象:

enemies = new Enemy[totalObj];

您可以销毁这些对象,然后使用delete[] enemies释放内存。


但是,您不应该使用手动动态内存管理。改为使用std::vector

std::vector<Enemy> enemies;
enemies.resize(totalObj);

也不清楚为什么用默认的成员初始化器初始化类定义中的一些成员,而用外部循环初始化其他成员。

为所有成员使用默认的成员初始值设定项,或者为执行所有初始化的struct编写适当的构造函数。

由于内存必须迭代两次,因此您当前的方法令人困惑且效率较低。

这也是危险的,因为如果在构造Enemys后忘记设置一个未初始化的成员,那么在使用它时就会出现未定义的行为。