Particle Emitter Confusion

There are no stupid questions, just stupid answers.
7 posts Page 1 of 1
Steve_Yorkshire
Posts: 205
Joined: Tue Feb 03, 2015 10:30 pm
 
  by Steve_Yorkshire » Mon May 22, 2017 3:56 pm
I've got a little confused with particleEmitters - especially the usefulness of phiVariance and phiReferenceVel.

What I want is to create a ring on the vertical, but only seem to be able to do this on the horizontal.

Here is what I've got. A ring on the horizontal when creating an emitter with ThetaMin/Max set to 90. When spawning it via an explosion it aligns to the impact vector (as expected).

Image

What I want is the opposite, so that the emitter particle is a vertical ring (and thus a horizontal ring when it hits a vertical surface in an 90 degree angled explosion).

Setting thetaMin/Max to 0-180 gives a full sphere, and there seems no way to "flatten" it or limit vertical angle of discharge.

I did some playing around with phiVariance (aka DEPTH in the particle Editor) and phiReferenceVel (which is not in the particle Editor but is an emitter value but god knows what it does) but that just cuts off some of the particle spawning. So setting depth/phiVariance to 180 gives half a circle on one side.

Image

Phi not terribly helpful here ...

So, any thoughts, insights or ideas would be appreciated. I'm thinking I might have to add a new value in particleEmitter.cpp/h to limit the thetaMin/Max over X (Y? Z?) ejection.

Here's my particle data if anyone is interested.

datablock ParticleData(aTestBits)
{
textureName = "art/particles/firefly.png";
inheritedVelFactor = "0";
constantAcceleration = "0";
lifetimeMS = "2000";
lifetimeVarianceMS = "0";
useInvAlpha = true;
spinSpeed = "0";
spinRandomMin = "0";
spinRandomMax = "1";
colors[0] = "1 0 1 1";
colors[1] = "1 0 1 0.5";
colors[2] = "1 0 1 0";
sizes[0] = "1";
sizes[1] = "1";
sizes[2] = "1";
times[0] = 0;
times[1] = "0.5";
times[2] = 1;
animTexName = "art/particles/firefly.png";
dragCoefficient = "2";
};

datablock ParticleEmitterData(aTestBitsEmitter)
{
ejectionPeriodMS = "1";
periodVarianceMS = "0";
ejectionVelocity = "5";
velocityVariance = "0";
ejectionOffset = "1";
thetaMin = "90";
thetaMax = "90";
phiReferenceVel = 0;
phiVariance = "360";
overrideAdvances = 0;
orientParticles = "0";
lifetimeMS = "200";
particles = "aTestBits";
blendStyle = "ADDITIVE";
glow = "0";
lifetimeVarianceMS = "0";
ejectionOffsetVariance = "0";
alignDirection = "0 0 1";
};
Duion
Posts: 813
Joined: Sun Feb 08, 2015 1:51 am
 
by Duion » Mon May 22, 2017 5:18 pm
Rotate the particle effect, for example the default grenade explosion does a ring and when it explodes on a wall the ring is vertical, but may be just a stupid workaround.
Steve_Yorkshire
Posts: 205
Joined: Tue Feb 03, 2015 10:30 pm
 
by Steve_Yorkshire » Mon May 22, 2017 6:02 pm
So I added a flag in ParticleEmitterData to check for rotation around the Y(?) axis and then use that for aligning the normal at (0, 1, 0) on the ParticleEmitterNodeData.
Fine for particleEmitters ... except it turns out explosionData particles don't use the ParticleEmitterNodeData object ... (fuuuu-).
Steve_Yorkshire
Posts: 205
Joined: Tue Feb 03, 2015 10:30 pm
 
by Steve_Yorkshire » Mon May 22, 2017 6:09 pm
@
User avatar
Duion
Exact same problem. Stock grenade explodes when it stops and is thus pointing upwards, so the smoke ring is ALWAYS horizontal to Z. So using it as a normal impact projectile gives the vertical orientated explosion against a vertical surface.
Steve_Yorkshire
Posts: 205
Joined: Tue Feb 03, 2015 10:30 pm
 
by Steve_Yorkshire » Mon May 22, 2017 10:08 pm
Okay, after much sniffing up the wrong tree I eventually got what I wanted.

Initially I managed to make particleEmitterNode rotate on the Z axis.

So then it turns out explosionData particles do not use particleEmitterNodes --- and I didn't have much success rotating the axis of the emitter for ejecting particles in ParticleEmitter.cpp.

So I had to make my changes inside explosion.cpp itself, with a reference to particleEmitterData to check whether the spawned particle should be flat (eg: face upwards).

First up, the flag to check for flat particles the emitter.

In particleEmitter.h
//*****************************************************************************
// Particle Emitter Data
//*****************************************************************************
class ParticleEmitterData : public GameBaseData
{
typedef GameBaseData Parent;
//...
bool glow; ///< Renders this emitter into the glow buffer.

bool reload();

F32 RotateY;//yorks in new!
};


In particleEmitter.cpp
//-----------------------------------------------------------------------------
// ParticleEmitterData
//-----------------------------------------------------------------------------
ParticleEmitterData::ParticleEmitterData()
{
VECTOR_SET_ASSOCIATION(particleDataBlocks);
VECTOR_SET_ASSOCIATION(dataBlockIds);

//...
alignParticles = false;
alignDirection = Point3F(0.0f, 1.0f, 0.0f);

RotateY = 0.0f;//yorks in new!
}

//...

//-----------------------------------------------------------------------------
// initPersistFields
//-----------------------------------------------------------------------------
void ParticleEmitterData::initPersistFields()
{
addGroup( "ParticleEmitterData" );

addFieldV("ejectionPeriodMS", TYPEID< S32 >(), Offset(ejectionPeriodMS, ParticleEmitterData), &ejectPeriodIValidator,
"Time (in milliseconds) between each particle ejection." );

//...

addField("glow", TYPEID< bool >(), Offset(glow, ParticleEmitterData),
"If true, the particles are rendered to the glow buffer as well.");

//yorks
addField("RotateY", TYPEID< F32 >(), Offset(RotateY, ParticleEmitterData),
"If >0.0f, the first particle spawns on Y axis not Z.");
//@}

endGroup( "ParticleEmitterData" );

Parent::initPersistFields();
}


And the particleEmitter datablock in Torquescript:
datablock ParticleEmitterData(aTestBitsEmitter)
{
ejectionPeriodMS = "1";
periodVarianceMS = "0";
ejectionVelocity = "5";
velocityVariance = "0";
ejectionOffset = "1";
thetaMin = "90";
thetaMax = "90";
phiReferenceVel = 0;
phiVariance = "360";
overrideAdvances = 0;
orientParticles = "0";
lifetimeMS = "200";
particles = "aTestBits";
blendStyle = "ADDITIVE";
glow = "0";
lifetimeVarianceMS = "0";
ejectionOffsetVariance = "0";
alignDirection = "0 0 1";
RotateY = "1";
};


And finally in explosion.cpp:
//----------------------------------------------------------------------------
// Update emitters
//----------------------------------------------------------------------------
void Explosion::updateEmitters( F32 dt )
{
Point3F pos = getPosition();

for( S32 i=0; i<ExplosionData::EC_NUM_EMITTERS; i++ )
{
if( mEmitterList[i] )
{
//yorks start
F32 mRotate = mEmitterList[i]->getDataBlock()->RotateY;
//Con::printf("mRotate = %g", mRotate);
if (mRotate > 0.0f)
{
//Con::printf("YES = %g", mRotate);
mInitialNormal = Point3F(0, 0, 1);
}//yorks end

mEmitterList[i]->emitParticles( pos, pos, mInitialNormal, Point3F( 0.0f, 0.0f, 0.0f ), (U32)(dt * 1000));
}
}
}


And hey-presto it works. Currently the F32 RotateY is only acting as a bool, and this could be expanded to merge the math of the original mInitialNormal to give a true relative position, or a cut-off angle could be used: eg; if mInitialNormal.z < RotateY (say 0.8) use RotateY instead, etc, etc.

Image
Steve_Yorkshire
Posts: 205
Joined: Tue Feb 03, 2015 10:30 pm
 
by Steve_Yorkshire » Tue May 23, 2017 12:04 am
Okay, found a problem.

All the particles in the explosion get the modification passed to them because mInitiialNormal gets reset. So here's the fix. Leave Britney/mInitialNormal Alone!!!! ;)

explosion.cpp
//----------------------------------------------------------------------------
// Update emitters
//----------------------------------------------------------------------------
void Explosion::updateEmitters( F32 dt )
{
Point3F pos = getPosition();

for( S32 i=0; i<ExplosionData::EC_NUM_EMITTERS; i++ )
{
if( mEmitterList[i] )
{
F32 mRotate = mEmitterList[i]->getDataBlock()->RotateY;
//Con::printf("mRotate = %g", mRotate);
if (mRotate > 0.0f)
{
//mInitialNormal = Point3F(0.0f, 0.0f, 1.0f);//yorks no no no!
mEmitterList[i]->emitParticles(pos, pos, Point3F(0.0f, 0.0f, 1.0f), Point3F(0.0f, 0.0f, 0.0f), (U32)(dt * 1000));
}
else
mEmitterList[i]->emitParticles( pos, pos, mInitialNormal, Point3F( 0.0f, 0.0f, 0.0f ), (U32)(dt * 1000));
}
}

}


Behold 2 emitters, 1 using RotateY and the other without!
Image

:mrgreen:
JeffR
Steering Committee
Steering Committee
Posts: 750
Joined: Tue Feb 03, 2015 9:49 pm
 
by JeffR » Tue May 23, 2017 3:55 pm
Very slick :D
7 posts Page 1 of 1

Who is online

Users browsing this forum: No registered users and 2 guests