How to track particles?

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
insomniac1
Posts: 21
Joined: Wed Jan 10, 2018 8:45 pm

How to track particles?

Post by insomniac1 »

Hello this is my first post here and I am not sure if this topic should be in the newb section or here in advanced help so please move if needed!

I am working on a weather system for my FPS open world game,I set up weather types and variable winds for each type etc. I am currently working on rain useing the particle system I set up my IParticleSystemSceneNode,IParticleEmitter,IParticleAffector,ISceneNodeAnimator it works fine etc. To make a long story short how can I track the particles and check for collisions? I am trying to track the particles like this but its only tracking the particle nodes not all the particles that have been emitted.

Code: Select all

 
 core::array<scene::ISceneNode *> particle_nodes;
    world->smgr->getSceneNodesFromType(scene::ESNT_PARTICLE_SYSTEM, particle_nodes);
    Console::Out("total particles %i ",(int)particle_nodes.size());
 
    for(int i = 0; i < particle_nodes.size(); ++i)
    {
        if(std::string(particle_nodes[i]->getName()) != "rain") continue;
        vector3df dir(((IParticleSystemSceneNode*)particle_nodes[i])->getEmitter()->getDirection());
 
        matrix4 m;
        m.setRotationDegrees(particle_nodes[i]->getRotation());
        m.transformVect(dir);
 
        vector3df new_pos(particle_nodes[i]->getPosition()-10 + -dir);
 
        core::line3d<f32> ray;
        ray.start = particle_nodes[i]->getPosition();
        ray.end = ray.start + new_pos;
 
        core::vector3df intersection;
        core::triangle3df tri;
 
        ISceneNode *selected_node = world->collision_manager->getSceneNodeAndCollisionPointFromRay(
                                        ray,intersection,tri,0 | IDFlag_IsPickable| IDFlag_IsHighlightable,0);
 
        // Add water spot to map  
        if(selected_node == this->node)
    {
        ISceneNode *node = world->smgr->addSphereSceneNode(5.0,16,0,IDFlag_IsPickable | IDFlag_IsHighlightable);//world->smgr->addWaterSurfaceSceneNode(weather_mesh);
            node->setPosition(intersection);
 
            //node->setMaterialTexture(0, world->driver->getTexture("data/graphics/stones.jpg"));
            node->setMaterialFlag(EMF_NORMALIZE_NORMALS, true);
            node->setMaterialTexture(0, world->driver->getTexture("data/graphics/water.jpg"));
            //node->setMaterialType(EMT_REFLECTION_2_LAYER);
            //node->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);
            node->setScale(vector3df(10,100.5,10));
            world->smgr->addToDeletionQueue(particle_nodes[i]);
        }
        /*
        else if (selected_node == nextcase)
        {
 
        }
        */
    }
}

I seen the different emitter's have a private array of particles but I can't seem to access them?
error: 'class irr::scene::IParticleEmitter' has no member named 'Particles'
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: How to track particles?

Post by CuteAlien »

I've not done that before. But I suppose the idea is that you write your own IParticleAffector class where you get the array by overloading the affect function.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
insomniac1
Posts: 21
Joined: Wed Jan 10, 2018 8:45 pm

Re: How to track particles?

Post by insomniac1 »

CuteAlien wrote:I've not done that before. But I suppose the idea is that you write your own IParticleAffector class where you get the array by overloading the affect function.
Thank you for your quick response you pushed me in the correct direction! At this point I dont feel that it is necesary to create a new affector class so I can uptain the particle array. After creating a couple affector classes I realized all I have to do is move core::array<SParticle> Particles; from the CParticleSystemSceneNode class into IParticleSystemSceneNode class. I will post my conclusion after I run some tests... Thank you for your time!
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: How to track particles?

Post by CuteAlien »

OK, but I don't really recommend changing the engine if you can do it without that. You want to affect particle positions and likely want to do that each frame - that's exactly what affectors are there for.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
insomniac1
Posts: 21
Joined: Wed Jan 10, 2018 8:45 pm

Re: How to track particles?

Post by insomniac1 »

CuteAlien wrote:OK, but I don't really recommend changing the engine if you can do it without that. You want to affect particle positions and likely want to do that each frame - that's exactly what affectors are there for.
In all reality I just want to check my precip particles for collisions so I can get a more realistic effect. I am going to try a few more methods as you suggest so I dont have to modify the engine. Last night after moving the particle array into the IParticleSystemSceneNode class I was able to track them in my weather::Update() function I did not notice any adverse effects.

Is there any specific reason the Particle array's were not in the IParticleSystemSceneNode class to begin with?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: How to track particles?

Post by CuteAlien »

Well, it's already accessible - with affectors. And that way you also have control over when exactly you get the position (defined by order of affectors), while with IParticleSystemSceneNode you can access it only before or after animation.
Not sure if that was the reason, maybe author simply wanted to hide implementation details (for example to avoid assumption about order of particles or stuff like that). Or was lazy. Sorry, not sure - was coded years before I joined Irrlicht :-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
insomniac1
Posts: 21
Joined: Wed Jan 10, 2018 8:45 pm

Re: How to track particles?[solved]

Post by insomniac1 »

CuteAlien wrote:Well, it's already accessible - with affectors. And that way you also have control over when exactly you get the position (defined by order of affectors), while with IParticleSystemSceneNode you can access it only before or after animation.
Not sure if that was the reason, maybe author simply wanted to hide implementation details (for example to avoid assumption about order of particles or stuff like that). Or was lazy. Sorry, not sure - was coded years before I joined Irrlicht :-)
I created a few more affectors and mods for the particle system but I could not get a result I was happy with useing the particle system ect. I created my own rain effect useing SphereSceneNodes here is what I did incase anyone wants to take a look

Code: Select all

 
std::tuple<double,double,unsigned int> Map::UpdateWind()
{
    std::tuple<double,double,unsigned int> update;
 
    switch(this->weather->type)
    {
    case WeatherType_Clear:
    {
        update = std::make_tuple(util::rand(-0.250,0.250),util::rand(-0.250,0.250),(int)Timer::GetTime());
    }
    break;
 
    case WeatherType_Rain:
    {
        update = std::make_tuple(util::rand(-0.500,0.500),util::rand(-0.500,0.500),(int)Timer::GetTime());
    }
    break;
 
    case WeatherType_Storm:
    {
        update = std::make_tuple(util::rand(-5.000,5.000),util::rand(-5.000,5.000),(int)Timer::GetTime());
    }
    break;
 
    default :
        update = std::make_tuple(util::rand(-0.0010,0.0010),util::rand(-0.0010,0.0010),(int)Timer::GetTime());
        break;
    }
 
    return update;
 
}
 
void Map::UpdateWeather()
{
    if(!this->world) return;
    if(!this->world->smgr) return;
    if(!this->world->player) return;
    if(!this->world->player->camera) return;
 
    if(this->weather->duration < Timer::GetTime())
    {
        delete this->weather;
        this->weather = 0;
 
        this->weather = new Weather();
 
        Console::Wrn("Gen new weather and weather type %i", (int)this->weather->type);
    }
 
    if(Timer::GetTime() > this->weather->lastWindUpdate + 5.0)
    {
        //can add WEATHER_TYPES AND SET THE RAND accordingly :D WEATHER_TYPE_RAIN-STORM
        std::tuple<double,double,unsigned int> update = this->UpdateWind();
 
        this->weather->xWind = std::get<0>(update);
        this->weather->zWind = std::get<1>(update);
        this->weather->lastWindUpdate = std::get<2>(update);
    }
 
    core::array<scene::ISceneNode *> rain_nodes;
    world->smgr->getSceneNodesFromType(scene::ESNT_ANY, rain_nodes);
 
    for(int i = 0; i < rain_nodes.size(); ++i)
    {
        if(std::string(rain_nodes[i]->getName()) != "rain") continue;
 
        vector3df new_pos(vector3df(rain_nodes[i]->getPosition().X - this->weather->xWind,rain_nodes[i]->getPosition().Y- 10.0,rain_nodes[i]->getPosition().Z-this->weather->zWind));
        const aabbox3d<f32>& box = rain_nodes[i]->getTransformedBoundingBox();
        vector3df radius = box.MaxEdge - box.getCenter();
 
        core::line3d<f32> ray;
        ray.start = rain_nodes[i]->getPosition();
        ray.end = ray.start + new_pos;
 
        core::vector3df intersection;
        core::triangle3df hitTriangle;
 
        ISceneNode *selected_node = world->collision_manager->getSceneNodeAndCollisionPointFromRay(ray,
                                    intersection,hitTriangle,IDFlag_IsPickable | IDFlag_IsHighlightable,0);
 
        if(selected_node == this->node)
        {
           /*IBillboardSceneNode *billboard = world->smgr->addBillboardSceneNode(selected_node);
           billboard->setMaterialType(EMT_TRANSPARENT_ADD_COLOR );
           billboard->setMaterialType(EMT_REFLECTION_2_LAYER);
           billboard->setMaterialTexture(0, world->driver->getTexture("data/graphics/water.jpg"));
           billboard->setMaterialFlag(EMF_LIGHTING, false);
           billboard->setMaterialFlag(EMF_ZBUFFER, false);
           billboard->setSize(dimension2d<f32>(0.3f, 0.1f));
           billboard->setID(ID_IsNotPickable);
           billboard->setPosition(intersection);
           billboard->setRotation(selected_node->getRotation());
 
           ISceneNodeAnimator* anim = this->world->smgr->createDeleteAnimator(5000);
           billboard->addAnimator(anim);
           anim->drop();
           */
            world->smgr->addToDeletionQueue(rain_nodes[i]);
        }
        else
        rain_nodes[i]->setPosition(new_pos);
 
    }
 
    if(this->weather->type == WeatherType(0)) return;
 
    for(int i = 0; i < (int)this->weather->type*2; ++i)
    {
        ISceneNode *node = world->device->getSceneManager()->addSphereSceneNode(5.0,16,0,IDFlag_IsPickable | IDFlag_IsHighlightable);
 
        node->setScale({0.1,1.0,0.1});
        node->setName("rain");
 
        node->setMaterialFlag(EMF_LIGHTING, false);
        node->setMaterialFlag(EMF_NORMALIZE_NORMALS, true);
        node->setMaterialTexture(0,world->driver->getTexture("data/graphics/raindrop.png"));
        node->setMaterialType(EMT_REFLECTION_2_LAYER);
        node->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);
 
        node->setPosition(vector3df(util::rand(this->world->player->camera->getAbsolutePosition().X-500,this->world->player->camera->getAbsolutePosition().X+500),this->world->player->camera->getAbsolutePosition().Y+600,util::rand(this->world->player->camera->getAbsolutePosition().Z-500,this->world->player->camera->getAbsolutePosition().Z+500)));
 
        ISceneNodeAnimator* anim = this->world->smgr->createDeleteAnimator(4000);
        node->addAnimator(anim);
        anim->drop();
    }
}
 
Useing those functions insead of the particle system I maintain a stable frame rate fps(60) and can easily test for collisions and manage the nodes etc! Thankyou for all the help @CuteAlien !!
insomniac1
Posts: 21
Joined: Wed Jan 10, 2018 8:45 pm

Re: How to track particles?

Post by insomniac1 »

I am still having some trouble with the positioning I think the problem is here in this line

vector3df new_pos(vector3df(rain_nodes->getPosition().X - this->weather->xWind,rain_nodes->getPosition().Y- 10.0,rain_nodes->getPosition().Z-this->weather->zWind));

if X Y or Z is negative and then I subtract a negative it is going positive?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: How to track particles?

Post by CuteAlien »

No, if you subtract from a negative it becomes more negative. Vector subtraction/addition work just as you expect (only it's multiplication rules are a little special).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
insomniac1
Posts: 21
Joined: Wed Jan 10, 2018 8:45 pm

Re: How to track particles?

Post by insomniac1 »

CuteAlien wrote:No, if you subtract from a negative it becomes more negative. Vector subtraction/addition work just as you expect (only it's multiplication rules are a little special).
Hmm.. Do you see anything that would make the rain nodes positioning code break? I'm wondering if it has to do with useing the camera's absolute position!
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: How to track particles?

Post by MartinVee »

What exactly is the problem with the position? What is breaking exactly? Does your rain nodes need to be created relative to the camera position? Do you have a screenshot of the problem, and a description of what you wish to achieve?

Also, as a side comment, you may wish to create an EmptyNode for your meteorological effect, attach all rain nodes to this empty one, and only process the childs of the EmptyNode. Or perhaps keep a list of all rain nodes in an array in your weather manager. The way you did this, as I understand the code, each UpdateWeather call iterates over all the nodes of the scene, make a string comparison, and process it as rain if the names match. I'm seeing three problems with this approach :
  • String comparison is inherently much slower than keeping a list of nodes pointer somewhere.
  • Left that way, the more you add nodes to the scene, the more processing it will take, as all these new nodes (wether they're rain or not) will be picked up for processing by your weather system.
  • If you copy this approach for other systems in your game engine, you'll exponentially add complexity. For example, if you have 15,000 nodes in your scene, and you have a weather system, a bullet system, a NPC system and a player system (for example), each of your update calls will process a total of 60,000 nodes (with 60,000 string comparison for each update). It will slow down.
insomniac1
Posts: 21
Joined: Wed Jan 10, 2018 8:45 pm

Re: How to track particles?

Post by insomniac1 »

MartinVee wrote:What exactly is the problem with the position? What is breaking exactly? Does your rain nodes need to be created relative to the camera position? Do you have a screenshot of the problem, and a description of what you wish to achieve?

Also, as a side comment, you may wish to create an EmptyNode for your meteorological effect, attach all rain nodes to this empty one, and only process the childs of the EmptyNode. Or perhaps keep a list of all rain nodes in an array in your weather manager. The way you did this, as I understand the code, each UpdateWeather call iterates over all the nodes of the scene, make a string comparison, and process it as rain if the names match. I'm seeing three problems with this approach :
  • String comparison is inherently much slower than keeping a list of nodes pointer somewhere.
  • Left that way, the more you add nodes to the scene, the more processing it will take, as all these new nodes (wether they're rain or not) will be picked up for processing by your weather system.
  • If you copy this approach for other systems in your game engine, you'll exponentially add complexity. For example, if you have 15,000 nodes in your scene, and you have a weather system, a bullet system, a NPC system and a player system (for example), each of your update calls will process a total of 60,000 nodes (with 60,000 string comparison for each update). It will slow down.
So what I think is happening after a little more debugging is when I approach the x or z position of est 2000 the rain nodes are no longer falling they begin to slide horizonal across the top of the window. The rain nodes don't have to be created relative to the camera position. Once I get the rain effect to function correctly I will create a container for it.. "I'm getting irritated and slapping together ugly code". The reason I am making this so complicated :D is so the weather effects are realistic like puddles,ripples and collision detection so it doesnt go through the enviroment Image.you can see their position

I have the rain drops size increased so you can see the positions.. all the drops rendered arround pos x or z 2000 the y position dosent seem to change the just slide across at the same plane.

Maybe I can try a flystrait animator?
Thankyou!
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: How to track particles?

Post by MartinVee »

Can't run your code, but here's food for thoughts...

1) If your rain is going sideways, could it be a cumulative effect of the wind? Try commenting out the wind effect and see what it does.
2) I can see that in your new_pos vector, you are already taking the object position and adding the translation vector. Is there a reason why you're adding it again when you set ray.end?
insomniac1
Posts: 21
Joined: Wed Jan 10, 2018 8:45 pm

Re: How to track particles?

Post by insomniac1 »

MartinVee wrote:Can't run your code, but here's food for thoughts...

1) If your rain is going sideways, could it be a cumulative effect of the wind? Try commenting out the wind effect and see what it does.
2) I can see that in your new_pos vector, you are already taking the object position and adding the translation vector. Is there a reason why you're adding it again when you set ray.end?
I tested the new_pos vector like this

Code: Select all

 new_pos(node->getPosition() + vector3df(0,-10,0));
and got a similar result, I also tested a FlyStraitAnimator and for some reason it has a similar result. I am starting to wonder if this is just a rendering error.
In calculating the ray for collision i create the ray..

Code: Select all

 
ray.start = rain_nodes[i]->getPosition(); // start point
ray.end = ray.start + new_pos;// end point apply the new_pos vector to get the line length right?
 
I only apply the new_pos to the rain node if there is no collision.
insomniac1
Posts: 21
Joined: Wed Jan 10, 2018 8:45 pm

Re: How to track particles?

Post by insomniac1 »

Thankyou very much @MartinVee

vector3df new_pos(rain_nodes->getPosition() + vector3df(this->weather->xWind,-10.0,this->weather->zWind));

core::line3d<f32> ray;
ray.start = rain_nodes->getPosition();
ray.end = new_pos; // YOU WERE CORRECT LOL
Image

I guess I will test as is for a bit then add the modifications for performance.
Post Reply