简体   繁体   中英

Error with global vector of object pointers c++

I am developing a 2D physics engine in c++, and one of the main structures I am using is name RigidBody. In order to easily iterate through all of the RigidBody objects in each time step, I attempted to create a global vector of RigidBody object pointers.

vector<RigidBody*> RigidBodies

As suggested in other StackOverflow answers, I declared the global variable in a header file, and defined it in one of the other project .cpp files. However, when I attempt to access member functions or variables, I get bogus values. Below are my source and header files. Could someone please let me know if there is an error with this or if I am doing something fundamentally wrong, as I have been trying to find an error for a few days, and have not been able to figure it out yet.

main.cpp:

#include <iostream>
#include <vector>
#include "polygon.h"
#include "rendering.h"

int test;

std::vector<RigidBody*> RigidBodies;
RigidBody * rigPtr;

void CreateBody() {
  Material m1;  // Settings for ROCK.
  m1.density = 0.6;
  m1.restitution = 0.1;
  float volume = 1;
  Vector p0 = {0,1};
  Vector p1 = {1,1};
  Vector p2 = {1,0};
  Vector p3 = {0,0};
  std::vector<Vector*> Points;
  Points.push_back(&p0);
  Points.push_back(&p1);
  Points.push_back(&p2);
  Points.push_back(&p3);
  //std::cout << Points.at(0)->y << '\n';
  Polygon pol1(Points, m1, volume);
  Polygon * polPtr  = &pol1; 
  //std::cout << pol1.Points.at(0)->y << '\n';
  std::cout << "polygon created" << '\n';
  Vector pos1;
  pos1.x = 10;
  pos1.y = 10;
  RigidBody r1(pos1, polPtr);
  rigPtr = &r1;
  std::cout << "rigid body created" << '\n';
 // std::cout << RigidBodies.at(0)->dt << '\n';

}

// MAIN
int main() {

  test = 3;
  //std::cout << test << '\n';
  test = 6;

  CreateBody();

  RigidBodies.push_back(rigPtr);

  //std::cout << test << '\n';

    unsigned int lastTime = SDL_GetTicks();
    unsigned int currentTime;

    SDL_Renderer* renderer = InitializeRender();

    while(1) {
    currentTime = SDL_GetTicks();
    if (currentTime - lastTime > 33) {
        //RigidBodies.at(0)->Step();
        Render(renderer, RigidBodies);
        lastTime = SDL_GetTicks();
    }
    }
  return(0);
}

rendering.cpp:

#include <iostream>
#include "polygon.h"
#include "rendering.h"



SDL_Renderer* InitializeRender() {
      SDL_Window * window = NULL;
    window = SDL_CreateWindow
    (
        "RIGID BODIES SIM", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        640,
        480,
        SDL_WINDOW_SHOWN
    );

    // Setup renderer
    SDL_Renderer * renderer = NULL;
    renderer =  SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    return(renderer);
}

void Render(SDL_Renderer * renderer, std::vector<RigidBody*> RigidBodies) {
    float scale = 10;  // METERS to PIXELS.
  SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);  // Clear screen.
  SDL_RenderClear(renderer);
  SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);  // Set polygon drawing color (GREEN)
  std::cout << RigidBodies.at(0)->dt << '\n';
  for (int j = 0; j < RigidBodies.size(); j++) {
    RigidBody * rPtr = RigidBodies.at(j);  // Not recognizing rigid body pointer correctly
    //std::cout << rPtr->dt << '\n';
    Polygon * polyPtr = rPtr->p;
    std::cout << "hey1" << '\n';
    int size = polyPtr->Points.size();  // ERROR HERE //
    std::cout << "hey2" << '\n';
  //  std::cout << polyPtr->Points.at(0)->y << '\n';
    for (int i = 0; i < size; i++) {
      std::cout << "hey3" << '\n';
        auto pointPtr1 = polyPtr->Points.at(i);
      int lastIndex = size - 1;
      //std::cout << i+1 << '\n';
        auto pointPtr2 = polyPtr->Points.at((i + 1) % (lastIndex));  // Modulo so last point links back up to first one.
      SDL_RenderDrawLine(renderer, (rPtr->position.x + pointPtr1->x) * scale, SCREEN_HEIGHT 
        - (rPtr->position.y + pointPtr1->y) * scale, (rPtr->position.x + pointPtr2->x) * scale,
        SCREEN_WIDTH - (rPtr->position.y + pointPtr2->y * scale));
    }
  }
  SDL_RenderPresent(renderer);
}

rendering.h:

#include <vector>
#include <SDL2/SDL.h>

#ifndef RENDERING_H
#define RENDERING_H

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

//SDL_Renderer * renderer; 

SDL_Renderer* InitializeRender();
void Render(SDL_Renderer*, std::vector<RigidBody*>);

#endif

rigid_bodies.cpp

// Joaquin Matias Giorgi jmgiorgi@bu.edu Impulse-Based Physics Engine 2D //
#include <iostream>
#include <math.h>
#include <SDL2/SDL.h>
#include <vector>
#include "polygon.h"

using namespace std;

vector<RigidBody*> RigidBodies;

// VECTOR STUFF //
  // Multiplication by scalar quantity.
  Vector Vector::operator*(const float scalar) {
      Vector vout;
      vout.x = this->x * scalar;
      vout.y = this->y * scalar;
      return(vout);
  }
  // Addition overload.
  Vector Vector::operator+=(const Vector vec) {
    Vector vout;
    vout.x = this->x + vec.x;
    vout.y = this->y + vec.y;
    return(vout);
  }

float dot (Vector vec1, Vector vec2) {
    float out = (vec1.x * vec2.x) + (vec1.y * vec2.y);
    return(out);
}

float cross2d (Vector vec1, Vector vec2) {
    // magnitude of perpendicular vector in 3d case.
    float out = (vec1.x * vec2.y) - (vec1.y * vec2.x);
    return(out);
}

// POLYGON Struct Methods //

Polygon::Polygon(vector< Vector* > Points1, Material m1, float volume1) {
    Points = Points1;
    m = m1;
    volume = volume1;
  }

 float Polygon::ComputeMass() {
    float mass = m.density * this->volume;
    return(mass);
 }
 // RIGID BODY Struct Methods //

    RigidBody::RigidBody(Vector position1, Polygon * p1) {

    std::cout << test << '\n';

    position = position1;
    p = p1;
    mass = p1->ComputeMass();
    orientation = 0;
    angularVelocity = 0;
    dt = .033;
    gravity.x = 0;
    gravity.y = -9.8;
    velocity.x = 0;
    velocity.y = 0;
    //RigidBodies.push_back(this); // Push to global vector of all RigidBodies.
    }

  // UPDATE at each iteration.  
    void RigidBody::Step() {
    this->velocity += this->gravity * this->dt;
    this->position += this->velocity * this->dt;
    this->orientation += this->angularVelocity * this->dt;
    }

polygon.h:

#include <vector>

#ifndef POLYGON_H
#define POLYGON_H

struct Vector {
    float x;
    float y;
  // Multiplication by scalar quantity.
  Vector operator*(const float);
  // Addition overload.
  Vector operator+=(const Vector);
};

struct Material {
    float density;
    float restitution;
};

struct Polygon {
  std::vector< Vector* > Points;
  float volume;
  Material m;

  Polygon(std::vector< Vector* >, Material, float);
  float ComputeMass();
};

struct RigidBody {
    float mass;
    float volume;
    float dt;
    // Linear
    Vector position;
    Vector gravity;
    Vector velocity;
    float acceleration;
    // Angular
    float orientation;
    float angularVelocity;
    float torque;
    Polygon * p;
  // Constructor
    RigidBody(Vector, Polygon*);
  // UPDATE at each iteration.  
    void Step();
};

// DECLARATION
extern std::vector<RigidBody*> RigidBodies;  // Global Vector of RigidBody Pointers.


#endif

Makefile:

sim: 
    g++ -std=c++11 main.cpp rigid_bodies.cpp rendering.cpp -I include -L lib -l SDL2-2.0.0

In your function CreateBody , RigidBody r1 is created on the stack and ceases to exist when the function returns. Your pointer rigPtr (and the pointers in Points and polPtr ) is no longer valid after the end of the function. If you call the CreateBody in a loop you will probably see that you get the same pointers for every call.

The simplest solution is to not use pointers at all, your objects are fairly small and shouldn't be too expensive to copy (or even cheaper to move).

If you really want to use pointers you need to allocate your objects on the heap rather than the stack using new . Note that these objects will then need to the deallocated using delete . A safer solution would be to wrap your pointers in std::shared_ptr or std::unique_ptr which takes care of deleting the objects automatically.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM