C++ / OpenGL Particle Generator help

Started by
14 comments, last by alx119 6 years, 10 months ago

Ok, I figured that instead of particles.size() - 1 I must write particles.size() at the drawing function and the differences are <= and <. I corrected them to be honestly before you to reply so my code is: < particles.size() in all functions. :P
But still not drawing. :D.Just print the "couts". I'm so frustrated. :D

Advertisement

You said it works if you create a single particle instance, but not if you spawn a single particle instance from the emitter. Correct?

If so, create a single particle instance manually, and spawn a single particle instance from the emitter. Using breakpoints and/or debug printing, compare the states of the one you created manually vs the one that was spawned from the emitter.

Hello to all my stalkers.

Ok, so in main.cpp I instantiated a particle with position.x = 1 and another particle from emitter with position.x = 0. I drew and from emitter and from particle and updated as well. Because I was so confuse after don't know how many changes, I don't remember if it was drawing from emitter. I've changed a few things on the emitter constructor but it didn't work. So I came back to my old code from constructor. When I run the application both particles were drawn at 1 and 0 position <_<. If I delete the instantiated particle from main it doesn't work that from emitter.I'm so confused.

Edit:I forgot to say, when it's working, it works even with more particles in the same position. :wacko:

Indeed, most programmers would write "i < N" for loops that should run N times, rather than i <= N - 1. It would be a good idea to do this consistently from now on, to prevent such bugs.

Now, it sounds like you've discovered something very interesting from a debugging perspective, which is you have two versions of the program, one of which behaves as expected and another which does not.

As Lactose says, you can start running the two versions and comparing the various variables involved. Keep the number of particles small and it might be easier to debug.

I've made 2 projects.One for instantiated particle and one for instantiated emitter. I've debugged and I've played a little(or more :D) and then I saw that on the emitter project, after I insert the particle objects into the vector, the constructors are destroyed (which is normal, because are going out of scope). But the objects shouldn't be kept with them variables and all stuff inside the vector ?

What I saw more was that with the Emitter Project, the bindings with the Vao's, Vbo's and Ebo's are destroyed as well, to say like that... they don't have the same values like in Particle Project.
For 1st particle I should have VaoID = 1, VboID = 1, EboID = 2 and for the other: VaoID = 2, VboID = 3, and Ebo = 4.

Here is what the buffers contain:

[attachment=36250:emitterER.png]

I tried to create a copy constructor (for the first time). I'm not sure is good how I did it. The new code is:

For Constructor:


Particle::Particle(const Particle &particle)
{
this->m_Position = particle.m_Position;
this->m_Velocity = particle.m_Velocity;
this->m_Life = particle.m_Life;
}

For creating particle objects and inserting them into the vector:


Emitter::Emitter(GLuint nrParticles, glm::vec3 position, GLfloat radius, GLchar *imgName)
{
this->m_Position = position;
this->m_radius = radius;
 
for (int i = 0; i < nrParticles; i++)
{
this->particles.push_back(Particle(Particle(glm::vec3(0.0f), glm::vec3(0.0f), 0.0f, imgName)));
}
}

Although I've made this change, still doesn't work. The values of Vao, Vbo, Ebo are the ones from the picture. If Is still because of the copy constructor, please let me know because is the first time when I'm working with it and I'm not sure if it's ok.

Edit: I debugged and I saw that it does't create the copy constructor.

Excellent observation, that is indeed the sequence of IDs that you might expect, that you see a deviation is significant. 3452816845 is an interesting number, not by itself but rather because many of your variables seem to have this value.

Googling it gives me https://stackoverflow.com/questions/18673913/why-variables-are-initialized-with-max-value-instead-of-zero, which reveals that the value has a special meaning:

3452816845 = 0xcdcdcdcd, the value used to initialize memory allocated from the heap.

(I knew about this already, but this shows how you might investigate yourself).

So what is happening? This example program might illustrate:

#include <iostream>
#include <vector>
 
struct Foo {
 
  Foo() {
    std::cout << "Constructor for " << this << std::endl;
  }
 
  ~Foo() {
    std::cout << "Destructor for " << this << std::endl;
  }
 
  Foo(const Foo &other) {
    std::cout << "Copying " << &other << " into " << this << std::endl;
  }
 
  Foo &operator=(const Foo &other) {
    std::cout << "Assigning " << &other << " to " << this << std::endl;
    return *this;
  }
 
};
 
int main() {
  std::vector<Foo> v;
  std::cout << "Before insertion" << std::endl;
  v.push_back(Foo());
  std::cout << "End of main" << std::endl;
}

If you run this, you'll see something like:


Before insertion
Constructor for 0x7fff8957a718
Copying 0x7fff8957a718 into 0xfdd030
Destructor for 0x7fff8957a718
End of main
Destructor for 0xfdd030

Note that a Foo object was created, copied and destroyed during the "push_back". This is the lifecycle of the temporary Foo() instance. The copy lives on in the vector, and is destroyed after the last line of main().

It looks like your Particle class is more complex than it seems at first, it has complex inner types. The question is really whether these complex inner types can be copied and / or assigned. Remember the rule of three, which is that any class that has a destructor should probably have a copy constructor and assignment operator (leaving aside move for the moment), or be "non-copyable", which can be done (in modern C++) by deleting the problematic functions (to prevent them being automatically generated), or simulated in older C++ by declaring the functions private and leaving them unimplemented.

Generally you do not want to implement copying semantics for external resources, such as textures that reside on the graphics card. Not only is it tricky, but also it is likely to have performance issues. You don't generally want to have lots of distinct copies of the same texture on the GPU, that is just wasting memory and wasting time switching between textures. I'd recommend changing your Texture, Vbo and Ebo classes to be non-copyable.

Once you do this, code that attempts to insert Particles into the container should stop compiling. I was never much of a graphics programmer, and it has been a long while since I've dabbled, but my guess would be to think about managing the textures and related objects at a higher level than the particles, for example the emitter could manage these resources. Particles should be as lightweight as possible, managing GPU resources is the opposite of this.

Thank you very much for your help guys. Every time I had problems, people from this forum helped me always.
@rip-off: Thank you so much. I will make some changes to my code. :P Thanks again. :)

This topic is closed to new replies.

Advertisement