Sword on fire
by Matthew Langley · in Torque Game Engine · 12/14/2004 (6:41 am) · 25 replies
What would be the best way to make fire particles spawn on a sword to make it look as though it were on fire...
been scanning through posts and been seeing the complications of this... any advice ?
been scanning through posts and been seeing the complications of this... any advice ?
About the author
Was a GG Associate and then joined GG in 2005. Lead tool dev for T2D and T3D. In 2011 joined mobile company ngmoco/DeNA and spent about 4 years working game and server tech. 2014 joined startup Merigo Games developing server technology.
#2
I made a stateEmitter on Activate and use a really large StateEmitterTime.
Dont have a spawn function but i should use the reload state or something to spawn the fire.
12/14/2004 (7:03 am)
I use fire on the sword when the weapon is activated.I made a stateEmitter on Activate and use a really large StateEmitterTime.
Dont have a spawn function but i should use the reload state or something to spawn the fire.
#3
preferably in script, but I don't mind getting my hands a little dirty in code and adding something a little more efficient and robust. Have tried unscuccesfully to add mounting functions to particles.
@Billy: very cool... stateemitter... how do I spawn the fire... any examples. sorry if I sound a bit stupid, lol trying to figure out particles =/
12/14/2004 (7:14 am)
@Brett: is there a way to attache particle emitters to weapon nodes ? preferably in script, but I don't mind getting my hands a little dirty in code and adding something a little more efficient and robust. Have tried unscuccesfully to add mounting functions to particles.
@Billy: very cool... stateemitter... how do I spawn the fire... any examples. sorry if I sound a bit stupid, lol trying to figure out particles =/
#4
what about
StateEmitterNode...
know what this is used for..
btw thanks for the help
12/14/2004 (7:21 am)
So if I load a particle emitter on the StateEmitter the particles should initiate on activate (if thats the state I load it into)... and then I can modify a long time...what about
StateEmitterNode...
know what this is used for..
btw thanks for the help
#5
But this works with the firestate to .
12/14/2004 (7:23 am)
I dont have a spawn function , the activate state starts the emitter when you mount the weapon.But this works with the firestate to .
#6
since particle emitter derives from GameBase and not ShapeBase is it still possible to mount a particle Emitter to a weapon node ?
if I'm completely wrong tell me, lol just trying to understand this a little more :)
12/14/2004 (7:24 am)
@Brett:since particle emitter derives from GameBase and not ShapeBase is it still possible to mount a particle Emitter to a weapon node ?
if I'm completely wrong tell me, lol just trying to understand this a little more :)
#7
stateName[1] = "Activate";
stateTransitionOnTimeout[1] = "Ready";
stateTimeoutValue[1] = 0.6;
stateSequence[1] = "Activate";
stateEmitter[1] = flameEmitter;
stateEmitterTime[1] = 1000000;
btw time is in ms ?
12/14/2004 (7:31 am)
So something like this should work if I set it up right...stateName[1] = "Activate";
stateTransitionOnTimeout[1] = "Ready";
stateTimeoutValue[1] = 0.6;
stateSequence[1] = "Activate";
stateEmitter[1] = flameEmitter;
stateEmitterTime[1] = 1000000;
btw time is in ms ?
#8
First, you need a particle emitter. I stole the spark stuff from crossbow.cs; there are some datablocks named "CrossbowDebrisSparkEmitter" and "CrossbowDebrisSpark" that are a good place to start. I copied these over to my sword.cs and renamed them "SwordSparkEmitter" etc.
Then add some stateEmitterXXX stuff for the states where you want the particle effect to go off. I have the sparks go off whenever the guy attacks with the sword:
The stateEmitterTime is how long the particles occur in milliseconds, but keep in mind that the ParticleEmitterData datablock usually has a "lifetimeMS" parameter that may cut it short. If your particles are not getting displayed long enough, it may by that the "lifetimeMS" stuff in your ParticleEmitterData datablock is really small (100 milliseconds).
Finally, stateEmitterNode tells which node to use. If you don't specify a node, it defaults to the muzzle point (for guns). The 1.3 version of TGE I downloaded seems to have a bug, in that stateEmitterNode is described wrong in initPersistFields (it should be a TypeString instead of TypeS32) but if you build and export the sword model with a muzzle point you don't have to worry about this. I dunno if this is a problem with the copy of HEAD in CVS.
12/14/2004 (7:45 am)
I did stick a fire emitter on the end of my guys sword. I'm still tweaking stuff, but it mostly works....First, you need a particle emitter. I stole the spark stuff from crossbow.cs; there are some datablocks named "CrossbowDebrisSparkEmitter" and "CrossbowDebrisSpark" that are a good place to start. I copied these over to my sword.cs and renamed them "SwordSparkEmitter" etc.
Then add some stateEmitterXXX stuff for the states where you want the particle effect to go off. I have the sparks go off whenever the guy attacks with the sword:
data ShapeBaseImage(SwordImage)
{
[...]
stateName[3] = "Fire";
stateFire[3] = true;
[... more stuff for state 3...]
stateEmitter[3] = SwordSparkEmitter;
stateEmitterNode[3] = "DamageStart";
stateEmitterTime[3] = 2000;
[...]
};The stateEmitterTime is how long the particles occur in milliseconds, but keep in mind that the ParticleEmitterData datablock usually has a "lifetimeMS" parameter that may cut it short. If your particles are not getting displayed long enough, it may by that the "lifetimeMS" stuff in your ParticleEmitterData datablock is really small (100 milliseconds).
Finally, stateEmitterNode tells which node to use. If you don't specify a node, it defaults to the muzzle point (for guns). The 1.3 version of TGE I downloaded seems to have a bug, in that stateEmitterNode is described wrong in initPersistFields (it should be a TypeString instead of TypeS32) but if you build and export the sword model with a muzzle point you don't have to worry about this. I dunno if this is a problem with the copy of HEAD in CVS.
#9
So a bug in 1.3... currently using version 1.3 myself... any info on if I change it in the source code and compile it will fix it ?
though thanks again, for now I will just use a muzzlepoint
12/14/2004 (8:04 am)
Thanks greatly... explains a lot of what I was thinking...So a bug in 1.3... currently using version 1.3 myself... any info on if I change it in the source code and compile it will fix it ?
though thanks again, for now I will just use a muzzlepoint
#10
stateEmitter[3] = CrossbowExplosionSmokeEmitter;
stateEmitterTime[3] = 2000;
on the crossbow.. to test it ( on work pc so dont have full objects etc)...
it works the first time, the crossbow muzzlepoint explodes... but beyond the first time nothing happens... is it the particle effect itself that is causing this
12/14/2004 (8:17 am)
Ok just didstateEmitter[3] = CrossbowExplosionSmokeEmitter;
stateEmitterTime[3] = 2000;
on the crossbow.. to test it ( on work pc so dont have full objects etc)...
it works the first time, the crossbow muzzlepoint explodes... but beyond the first time nothing happens... is it the particle effect itself that is causing this
#11
http://www.stanford.edu/~scodary/tkam.htm
12/14/2004 (9:10 am)
For some reason the title of this thread reminded me of:http://www.stanford.edu/~scodary/tkam.htm
#12
12/14/2004 (12:39 pm)
Thx Pat... that's very silly and quite funny.
#13
Try a smokeemitter or something then you know its the emitter or not.
Or make a new fire emitter with the particle editor.
12/14/2004 (2:04 pm)
@Matthew Try a smokeemitter or something then you know its the emitter or not.
Or make a new fire emitter with the particle editor.
#14
it still doesn't re-initiate the particle after I've attacked already, but right now I just increase the lifetime numbers and it works well..
One other thing I've been trying to do is modify the particle code so I can place four emitter nodes in the state system, even if all the nodes point to muzzleNode, then just have each fire effect do different things...
well after a few hours of messing with that (learning a lot about the state / particle system)... I get it to compile, load the new nodes, and if I only load one at a time in the sword.cs then it shows each unique effect; however, if I load them all it just shows the last effect...
so going through the code some more found the
startImageEmitter function...
now this whole time I've done pretty sloppy code, just created three new duplications of most of the node code... at first I was trying to be efficient, but I gave up on that to try and just get it working at all, I can clean the code up after it works...
now I created three new startImageEmitter functions
you pass (image, state) to it...
it errors out on the duplications of this when I use
state.emitter2
or state.emitterNode2... .emitterTime2.. etc
specifically on the
new ParticleEmitter
onNewDatablock()
it compiles, but in runtime when it tries to start all the emitters it exits with ... an error ending with
NOT reentrant
traced that back to a reentrant event... to anyone that might know what I'm running into, is it that I'm duplicating a proccess that adds the event incorrectly... or is it a specific limit to one particleEmitter... the onDatablock part maybe...
was up till 2 am last night trying to get this to work
12/15/2004 (5:29 am)
Ok got it working, thanks everyone...it still doesn't re-initiate the particle after I've attacked already, but right now I just increase the lifetime numbers and it works well..
One other thing I've been trying to do is modify the particle code so I can place four emitter nodes in the state system, even if all the nodes point to muzzleNode, then just have each fire effect do different things...
well after a few hours of messing with that (learning a lot about the state / particle system)... I get it to compile, load the new nodes, and if I only load one at a time in the sword.cs then it shows each unique effect; however, if I load them all it just shows the last effect...
so going through the code some more found the
startImageEmitter function...
now this whole time I've done pretty sloppy code, just created three new duplications of most of the node code... at first I was trying to be efficient, but I gave up on that to try and just get it working at all, I can clean the code up after it works...
now I created three new startImageEmitter functions
you pass (image, state) to it...
it errors out on the duplications of this when I use
state.emitter2
or state.emitterNode2... .emitterTime2.. etc
specifically on the
new ParticleEmitter
onNewDatablock()
it compiles, but in runtime when it tries to start all the emitters it exits with ... an error ending with
NOT reentrant
traced that back to a reentrant event... to anyone that might know what I'm running into, is it that I'm duplicating a proccess that adds the event incorrectly... or is it a specific limit to one particleEmitter... the onDatablock part maybe...
was up till 2 am last night trying to get this to work
#15
and here is the function
here is an example of what I did (very hacky and sloppy i know lol)
the call
the function
seems to stall up at
bem->emitter = new ParticleEmitter;
bem->emitter->onNewDataBlock(state.emitter2);
bem->emitter->registerObject();
with "NOT reentrant"...
12/15/2004 (5:33 am)
Heres the call to startImageEmitterif (isGhost())
startImageEmitter(image,stateData);and here is the function
void ShapeBase::startImageEmitter(MountedImage& image,ShapeBaseImageData::StateData& state)
{
MountedImage::ImageEmitter* bem = 0;
MountedImage::ImageEmitter* em = image.emitter;
MountedImage::ImageEmitter* ee = &image.emitter[MaxImageEmitters];
// If we are already emitting the same particles from the same
// node, then simply extend the time. Otherwise, find an empty
// emitter slot, or grab the one with the least amount of time left.
for (; em != ee; em++) {
if (bool(em->emitter)) {
if (state.emitter == em->emitter->getDataBlock() && state.emitterNode == em->node) {
if (state.emitterTime > em->time)
em->time = state.emitterTime;
return;
}
if (!bem || (bool(bem->emitter) && bem->time > em->time))
bem = em;
}
else
bem = em;
}
bem->time = state.emitterTime;
bem->node = state.emitterNode;
bem->emitter = new ParticleEmitter;
bem->emitter->onNewDataBlock(state.emitter);
bem->emitter->registerObject();
}here is an example of what I did (very hacky and sloppy i know lol)
the call
startImageEmitterTwo(image,stateData);
the function
void ShapeBase::startImageEmitterTwo(MountedImage& image,ShapeBaseImageData::StateData& state)
{
MountedImage::ImageEmitter* bem = 0;
MountedImage::ImageEmitter* em = image.emitter2;
MountedImage::ImageEmitter* ee = &image.emitter2[MaxImageEmitters];
// If we are already emitting the same particles from the same
// node, then simply extend the time. Otherwise, find an empty
// emitter slot, or grab the one with the least amount of time left.
for (; em != ee; em++) {
if (bool(em->emitter)) {
if (state.emitter2 == em->emitter->getDataBlock() && state.emitterNode2 == em->node) {
if (state.emitterTime2 > em->time)
em->time = state.emitterTime2;
return;
}
if (!bem || (bool(bem->emitter) && bem->time > em->time))
bem = em;
}
else
bem = em;
}
bem->time = state.emitterTime2;
bem->node = state.emitterNode2;
bem->emitter = new ParticleEmitter;
bem->emitter->onNewDataBlock(state.emitter2);
bem->emitter->registerObject();
}and again no compile errors, and using one version of this function it works correctly, just only starts one actual node.. the last one loaded I beleiveseems to stall up at
bem->emitter = new ParticleEmitter;
bem->emitter->onNewDataBlock(state.emitter2);
bem->emitter->registerObject();
with "NOT reentrant"...
#16
12/15/2004 (5:33 am)
Why not do the majority of the fire with geometry and texture animation (IFL?) then use an emitter for smoke.
#17
EDIT: plus trying to learn the particle system /state sytem so I can make modifications
12/15/2004 (5:34 am)
Thanks for the tip, though using blender so exporting is limitedEDIT: plus trying to learn the particle system /state sytem so I can make modifications
#18
The startImageEmitter can handle up to "MaxImageEmitters" at once, so if you try to create multiple emitters it shouldn't be a problem unless all the emitters use the same emitter node and datablock. Note that MaxImageEmitters is only set to 3 by default, so you may need to crank that up as well.
Also, you can also dump two particles into one emitter I think. Just separate the particle names with a tab. This might be easier than hacking up C++ code.
12/15/2004 (1:15 pm)
Matthew, I've tried all sorts of code hackery in shapeimage.cc and can't get the "NOT reentrant" jobbers to appear as they did in yours post.The startImageEmitter can handle up to "MaxImageEmitters" at once, so if you try to create multiple emitters it shouldn't be a problem unless all the emitters use the same emitter node and datablock. Note that MaxImageEmitters is only set to 3 by default, so you may need to crank that up as well.
Also, you can also dump two particles into one emitter I think. Just separate the particle names with a tab. This might be easier than hacking up C++ code.
datablock ParticleEmitterData(SomeEmitter)
{
ejectionPeriodMS = 15;
periodVarianceMS = 5;
ejectionVelocity = 0.25;
velocityVariance = 0.1;
thetaMin = 0.0;
thetaMax = 90.0;
particles = "SomeAParticle" TAB "SomeBParticle";
};
#19
also looked back over my code, seems I missed it in one area...
my code is pretty hacky... for example
is there any more efficient way to load multiple emitters such as this... btw with the TAB then I now have the possibility of up to 8 particle effects on a weapon
12/15/2004 (9:26 pm)
Thanks... very very useful... I tried the tab method, works well..also looked back over my code, seems I missed it in one area...
bool ShapeBaseImageData::preload(bool server, char errorBuffer[256])
my code is pretty hacky... for example
for (U32 i = 0; i < MaxStates; i++) {
if (state[i].emitter)
if (!Sim::findObject(SimObjectId(state[i].emitter), state[i].emitter))
Con::errorf(ConsoleLogEntry::General, "Error, unable to load emitter for image datablock");
if (state[i].emitter2)
if (!Sim::findObject(SimObjectId(state[i].emitter2), state[i].emitter2))
Con::errorf(ConsoleLogEntry::General, "Error, unable to load emitter for image datablock");
if (state[i].emitter3)
if (!Sim::findObject(SimObjectId(state[i].emitter3), state[i].emitter3))
Con::errorf(ConsoleLogEntry::General, "Error, unable to load emitter for image datablock");
if (state[i].emitter4)
if (!Sim::findObject(SimObjectId(state[i].emitter4), state[i].emitter4))
Con::errorf(ConsoleLogEntry::General, "Error, unable to load emitter for image datablock");is there any more efficient way to load multiple emitters such as this... btw with the TAB then I now have the possibility of up to 8 particle effects on a weapon
#20
12/20/2004 (1:27 pm)
That doesn't look very inefficient to me... Just a bunch of object lookups. And datablocks are only init'ed once, so you're not liable to have to need to optimize this stuff, either.
Torque Owner Brett Fattori
First, make your sword have some nodes to attach fire to. Then attach particle emitters to those nodes. Best I can think of.
- Brett