Particle Systems and Rotation Vectors

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Particle Systems and Rotation Vectors

Post by killthesand »

I actually solved my own problem while typing this up, so I'm going to leave my post as it was, then answer it myself. I guess that's a little bit strange but hopefully someone else can benefit from it.
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Post by killthesand »

I've been playing with particle systems and ran into a problem with rotation. Sorry if this is a long post, I'm going to try to explain everything. There's a large sphere in my scene, a planet. I've set up my particle system with a disk emitter around the planet. The particles are acting like the rings around Saturn. I added a rotation affector so the particles slowly orbit the planet. I would like them to orbit on a tilted axis but I run in to lots of trouble when I rotate the particle system.

Here's the code that I have that works where they orbit, flat on the XZ plane.

Code: Select all

	IParticleSystemSceneNode *ps0 = smgr->addParticleSystemSceneNode(false);
	ps0->setEmitter(ps0->createRingEmitter(vector3df(0, 0, 0), 65, 15, vector3df(0, 0, 0), 1, 500));
	ps0->addAffector(ps0->createRotationAffector(vector3df(0, -2, 0), vector3df(0, 0, 0)));
	ps0->setParticleSize(dimension2df(1, 1));
	ps0->setMaterialFlag(EMF_LIGHTING, false);
These are the things that I have tried to do:

I started with pso->setRotation(vector3df(40, 0, 0)); This changes the ring's axis but the particles still rotate around the global Y axis only. I tried playing with the numbers in the rotation affector's vector3df(0, -2, 0) but I didn't have any luck. The entire ring just spins out of control. Is there any math I could do to convert the vector3df(0, -2, 0) into the ring's local coordinate system?

Then I got rid of the rotation affector. I tried manually rotating the scene node. In the main loop I added:

Code: Select all

ps0->setRotation(ps0->getRotation() - vector3df(40, 0, 0));
ps0->setRotation(ps0->getRotation() + vector3df(0, .5, 0));
ps0->setRotation(ps0->getRotation() - vector3df(40, 0, 0));
I thought that I could flatten the axis, rotate around Y, then restore the axis. This didn't work; it gave me the same results as the rotation affector where the tilted ring rotated about the global Y axis.

I tried using rotation animators on the particle system, I run into the same problem as the affector, using one rotation vector, how do you adjust for a local axis?

I tried using a dummy transformation scene node as a parent node. I angled the parent and rotated the child, trying all of the rotation methods above. I still couldn't get it to work.
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Post by killthesand »

It is very easy to shift the axis of a rotation vector. In this case use:

vector3df rot(0, -2, 0);
rot.rotateYZBy(-40, vector3df(0, 0, 0));
...
ps0->addAffector(ps0->createRotationAffector(rot, vector3df(0, 0, 0)));

the vector3d rotate methods are very helpful. Is there any chance of adding a get rotate by method, that returns the rotated vector? such as

Code: Select all

ps0->addAffector(ps0->createRotationAffector(vector3df(0, -2, 0).getRotateYZBy(-40, vector3df(0, 0, 0)), vector3df(0, 0, 0)));
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Post by killthesand »

More comments about Irrlicht's particles:

I learned something in this process.

One time, whilst using a parent and child setup, I didn't have the parent node rotated at all. I was rotating the particle system around Y. I ran the program and it appeared that no rotation was happening at all. I checked the code several times. Then I tried rotating around a different axis. It did rotate the whole ring that way. But I noticed that the individual particles weren't rotating, only the emitter was. The only thing that actually makes the particles rotate is the rotation affector. Rotating the scene node only rotates the emitter.

I did some checking on the forum. A long time ago, people were complaining about the opposite of this. It seems that the engine was updated to accommodate them.
http://irrlicht.sourceforge.net/phpBB2/ ... .php?t=838
They moved the scene node and all of the particles moved with it. Of course that isn't what you want to have happen when smoke is shooting out of a moving torpedo, but you may want to move all of the particles sometimes. For example, if your character has a magical sword and it's has glittery shards of energy surrounding it. You might not want the sword to leave behind a trial of particles, but rather keep those shards parented to the sword so they help cut apart your enemies.

The particle system has a method called setParticlesAreGlobal(bool). As far as I can tell this switches whether or not the emitter is parented to the scene node. If true (default), transforming the scene node will transform the emitter but any existing particles are unaffected. If false, the scene node's transformations are completely ignored by the particle system. I think there should be a setting to allow all particles to move at once.

I've been spoiled by having used Houdini Master, probably by far the world's most powerful particle simulation software, but I think that Irrlicht could provide more control over individual particles. (Warning: Here comes the non-devolper about hand out his suggestions.) I don't know how particles are being implemented, (and I'm not about to dig through the source and find out) but if each particle is a separate object, somewhere along the way you have to iterate through them all to update their movement. Some sort of macro could be implemented to expose individual particle data.

For example, in Houdini I can create a wind force. The wind node has X Y and Z values so you can set the direction of the wind. So 0, 1, 0 would blow all the particles up. The cool part is, yuo could use 0, $TX, 0. What this does is takes each particle's X position and uses it as the wind's Y strength. So the further along the x axis the particle goes, the faster it will move up and if the particle's x value is negative, it will move down. That isn't the most useful example but if we could do this in Irrlicht it would be great.

Here's an example using my rings orbiting around a planet. It would be sweet if instead of vector3df(0, -2, 0), I could make the rotation vector be vector3df(0, -200 + vector3df($TX, $TY, $TZ).getDistanceFrom(vector3df(0, 0, 0)), 0). Each particle would rotate based upon it's distance to the center. Particles closer to the center would rotate faster than particles further away.

It would be nice, but it's kind of a minor feature compared to other things and since I'm not creating the 3d engine I'll let the developers decide what to spend their precious time on.
Post Reply