Improved particle system for Torque 3D
by Lukas Joergensen · 05/20/2012 (7:08 pm) · 36 comments
Download it here
I wrote a pdf which is included in the download. The pdf should document the code decently so i will use this page mostly for credits and showcase!Showoff thread!
Torque CE wiki page
(Some differences may apply)What is this resource?
This resource extends the particleEmitter class and adds a new graphEmitter class.The change to the regular particleEmitter class lies in the ability to change values on a per emitter basis rather than a per datablock basis. Read more about this here
The change that this resource will focus on tho is the graphEmitter class. The graphEmitter class is basing the position of the particles on 3 functions, one for each coordinate.
So if the function for x is x=1 it would be placed 1 meter from the graphEmitter along the x-axis.
Combined with the powerful muParser, it is very easy to create nice looking effects like the ones above.
To do list:
- Better documentation and commenting of the code
- Bugfixes & cleanup of the code
- Possibly benchmark
Please do confirm that the documentation is OK and nothing needs clarified. And do tell me if i need to upload some files!
And you are always welcome to ask all the questions you want!
A video showing almost all features of 2.0.0
An environmental example
Composite functions
If you want to do composite functions you can do it via the muParser syntax!
Here is an example of the spiralNode with a variable function!
datablock GraphEmitterNodeData(g_compSpiralNode : g_DefaultNode)
{
xFunc = "t<500 ? cos(t/50)*t*0.02 : t<1000 ? cos(t/50)*t*0.1 : t<1500 ? cos(t/50)*t*0.02 : cos(t/50)*t*0.1";
yFunc = "t<500 ? sin(t/50)*t*0.02 : t<1000 ? sin(t/50)*t*0.1 : t<1500 ? sin(t/50)*t*0.02 : sin(t/50)*t*0.1";
zFunc = "t/20";
};Oh almost forgot!
I got all changes to the particleEmitter files written here:
http://nakednerd.clan-net.dk/tutorials/read?tut=t3d1
Changelog
Hotfix 04/06-2012Hotfix 01/06-2012
Update v1.0.2
Update v1.0.1
Credits
Thanks to Ingo Berg for releasing this powerful tool (muParser)! [MIT license]Thanks to Charlie Patterson, hes Twillex engine is what inspired me to all of this, and i ensure you that if you combine the Twillex engine with this resource you will have some vastly powerful tools at your hands!
Thanks to everyone who downloads this resource! If you create something magnificent please show it off in the comments below!
About the author
IPS Bundle available at: https://www.winterleafentertainment.com/Products/IPS.aspx
#22
BTW if you have any wishes for improvements
(features as well as bug fixes) just write the suggestions here and I will look into it.
05/28/2012 (1:00 am)
Added a donation link to the post, donating is not must but it allows me to spend more time on improving the resource and documentation.BTW if you have any wishes for improvements
(features as well as bug fixes) just write the suggestions here and I will look into it.
#23
05/29/2012 (12:46 pm)
Lukas, you commit the resource to the repository of the community edition? Or did i do?
#24
05/29/2012 (12:49 pm)
Oh you are welcome to do it! I wanted to do it today but when I had a look at it I was unsure of where to put it so I chose to procastinate it :)
#25
05/30/2012 (1:11 pm)
Dropping the donation idea, have something else in mind.
#26
05/30/2012 (4:42 pm)
There was a GarageGames programmer who posted a bunch of particle tricks a couple of years ago - I think you may have exceeded what he did!
#27
so:
and call the Parent where required.
Unfortunately I have no time to do it O_o
05/31/2012 (12:00 am)
@Lukas, i just had to commit to the shared version of t3d. But i had some problems, and i have had to modify the code a bit. Make changes to how you have published, impedes the correct functioning of the old particle system. I have also better integrated with the editor.I suggest you to inherit classes of T3D, instead of copying them like you did. so:
class GraphEmitterData : public ParticleEmitterDatainstead:
class GraphEmitterData : public GameBaseData
and call the Parent where required.
Unfortunately I have no time to do it O_o
#28
In my code GraphEmitterData is inheriting the GameBaseData not the ParticleEmitterData.
And the stock ParticleEmitters is working just as they are supposed to.
06/01/2012 (6:36 am)
@Alfio, I don't understand...In my code GraphEmitterData is inheriting the GameBaseData not the ParticleEmitterData.
And the stock ParticleEmitters is working just as they are supposed to.
#29
I hope you have subscribed to this resource :)
In graphEmitter.cpp
Put this
Being a noob and all at c++ and programming in general I did not even give it a thought that I would have to free the memory after using it.
This will fix a memory leak caused by this resource. I will update the resource files aswell.
Edit:
I wanted to make sure there wasn't anymore memory leaks so I made a stress test:
http://www.youtube.com/watch?v=B51bHCHCBZM&feature=relmfu
And it seemed to run just fine ( around 20-30 emitters, can't remember the exact amount )
06/01/2012 (12:55 pm)
GUYS I am terribly sorry! Clearly it shows that I am a noob at this programming thing.I hope you have subscribed to this resource :)
In graphEmitter.cpp
Put this
delete(*funcPos); delete(*p);After
pNew->pos = pos + (*p * nodeDat->sa_ejectionOffset); pNew->relPos = *p * nodeDat->sa_ejectionOffset;And you might get rid of a lot headaches.
Being a noob and all at c++ and programming in general I did not even give it a thought that I would have to free the memory after using it.
This will fix a memory leak caused by this resource. I will update the resource files aswell.
Edit:
I wanted to make sure there wasn't anymore memory leaks so I made a stress test:
http://www.youtube.com/watch?v=B51bHCHCBZM&feature=relmfu
And it seemed to run just fine ( around 20-30 emitters, can't remember the exact amount )
#30
Are no one experiencing these errors or are you simply not telling me about them? :P
To fix paste this in between the emitParticles functions:
In the particleEmitter.h file:
06/03/2012 (4:29 pm)
Hey guys! Seems like I have made another mistake and accidentally overridden the emitParticles function which the projectile class uses!Are no one experiencing these errors or are you simply not telling me about them? :P
To fix paste this in between the emitParticles functions:
In the particleEmitter.h file:
void emitParticles(const Point3F& start,
const Point3F& end,
const Point3F& axis,
const Point3F& velocity,
const U32 numMilliseconds);In the particleEmitter.cpp file:
#31
06/03/2012 (4:33 pm)
void ParticleEmitter::emitParticles(const Point3F& start,
const Point3F& end,
const Point3F& axis,
const Point3F& velocity,
const U32 numMilliseconds)
{
if( mDead ) return;
if( mDataBlock->particleDataBlocks.empty() )
return;
// lifetime over - no more particles
if( mLifetimeMS > 0 && mElapsedTimeMS > mLifetimeMS )
{
return;
}
U32 currTime = 0;
bool particlesAdded = false;
Point3F axisx;
if( mFabs(axis.z) < 0.9f )
mCross(axis, Point3F(0, 0, 1), &axisx);
else
mCross(axis, Point3F(0, 1, 0), &axisx);
axisx.normalize();
if( mNextParticleTime != 0 )
{
// Need to handle next particle
//
if( mNextParticleTime > numMilliseconds )
{
// Defer to next update
// (Note that this introduces a potential spatial irregularity if the owning
// object is accelerating, and updating at a low frequency)
//
mNextParticleTime -= numMilliseconds;
mInternalClock += numMilliseconds;
mLastPosition = end;
mHasLastPosition = true;
return;
}
else
{
currTime += mNextParticleTime;
mInternalClock += mNextParticleTime;
// Emit particle at curr time
// Create particle at the correct position
Point3F pos;
pos.interpolate(start, end, F32(currTime) / F32(numMilliseconds));
addParticle(pos, axis, velocity, axisx);
particlesAdded = true;
mNextParticleTime = 0;
}
}
while( currTime < numMilliseconds )
{
S32 nextTime = mDataBlock->ejectionPeriodMS;
if( mDataBlock->periodVarianceMS != 0 )
{
nextTime += S32(gRandGen.randI() % (2 * mDataBlock->periodVarianceMS + 1)) -
S32(mDataBlock->periodVarianceMS);
}
AssertFatal(nextTime > 0, "Error, next particle ejection time must always be greater than 0");
if( currTime + nextTime > numMilliseconds )
{
mNextParticleTime = (currTime + nextTime) - numMilliseconds;
mInternalClock += numMilliseconds - currTime;
AssertFatal(mNextParticleTime > 0, "Error, should not have deferred this particle!");
break;
}
currTime += nextTime;
mInternalClock += nextTime;
// Create particle at the correct position
Point3F pos;
pos.interpolate(start, end, F32(currTime) / F32(numMilliseconds));
addParticle(pos, axis, velocity, axisx);
particlesAdded = true;
// This override-advance code is restored in order to correctly adjust
// animated parameters of particles allocated within the same frame
// update. Note that ordering is important and this code correctly
// adds particles in the same newest-to-oldest ordering of the link-list.
//
// NOTE: We are assuming that the just added particle is at the head of our
// list. If that changes, so must this...
U32 advanceMS = numMilliseconds - currTime;
if (mDataBlock->overrideAdvance == false && advanceMS != 0)
{
Particle* last_part = part_list_head.next;
if (advanceMS > last_part->totalLifetime)
{
part_list_head.next = last_part->next;
n_parts--;
last_part->next = part_freelist;
part_freelist = last_part;
}
else
{
if (advanceMS != 0)
{
F32 t = F32(advanceMS) / 1000.0;
Point3F a = last_part->acc;
a -= last_part->vel * last_part->dataBlock->dragCoefficient;
a -= mWindVelocity * last_part->dataBlock->windCoefficient;
a += Point3F(0.0f, 0.0f, -9.81f) * last_part->dataBlock->gravityCoefficient;
last_part->vel += a * t;
last_part->pos += last_part->vel * t;
updateKeyData( last_part );
}
}
}
}
// DMMFIX: Lame and slow...
if( particlesAdded == true )
updateBBox();
if( n_parts > 0 && getSceneManager() == NULL )
{
gClientSceneGraph->addObjectToScene(this);
ClientProcessList::get()->addObject(this);
}
mLastPosition = end;
mHasLastPosition = true;
}
#32
Improved Particle System showoff thread
I would love to see what you have come up with!
06/04/2012 (10:50 am)
Hey guys if you create something nice with this resource please post it in this thread:Improved Particle System showoff thread
I would love to see what you have come up with!
#33
06/21/2012 (4:34 pm)
This is excellent Lukas. Nice work! I still haven't really had the time to implement this yet, but as soon as I do I'll post something in the showoff thread. I have to get those jets sorted at some stage. :)
#34
02/27/2014 (6:29 pm)
Id love to see how you did the afterburner??
#35
I believe I did it by making a lot of short-lived particles, and interpolate the ejection settings over time (using Twillex) such that they would be ejected in a new pattern all the time.
02/27/2014 (11:42 pm)
@Donnie can't remember the exact code, but the key is to create an emitter that looks like an afterburner while it's static so you can make the particles "sticky" (that is, make them use object-space coordinates) so that they wont get spread out when the ship is flying around.I believe I did it by making a lot of short-lived particles, and interpolate the ejection settings over time (using Twillex) such that they would be ejected in a new pattern all the time.
#36
03/03/2014 (6:58 pm)
Cool Lukas and thank you very much for this and the advice.... 
Torque Owner Kevin Mitchell
12 CatBlack Studios