Jump to content

Particle Emitter Confusion


Steve_Yorkshire

Recommended Posts

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).


http://i.imgur.com/bLrQcq7.jpg


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.


http://i.imgur.com/GSXgOG5.jpg


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";
};
Link to comment
Share on other sites

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-).

Link to comment
Share on other sites

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
   {
      if( mEmitterList )
      {
		  //yorks start
		  F32 mRotate = mEmitterList->getDataBlock()->RotateY;
		  //Con::printf("mRotate = %g", mRotate);
		  if (mRotate > 0.0f)
		  {
			  //Con::printf("YES = %g", mRotate);
			  mInitialNormal = Point3F(0, 0, 1);
		  }//yorks end
 
         mEmitterList->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.


http://i.imgur.com/1Z6PPJA.jpg

Link to comment
Share on other sites

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
   {
      if( mEmitterList )
      {
		  F32 mRotate = mEmitterList->getDataBlock()->RotateY;
		  //Con::printf("mRotate = %g", mRotate);
		  if (mRotate > 0.0f)
		  {
			//mInitialNormal = Point3F(0.0f, 0.0f, 1.0f);//yorks no no no!
			mEmitterList->emitParticles(pos, pos, Point3F(0.0f, 0.0f, 1.0f), Point3F(0.0f, 0.0f, 0.0f), (U32)(dt * 1000));
		  }
		  else
			mEmitterList->emitParticles( pos, pos, mInitialNormal, Point3F( 0.0f, 0.0f, 0.0f ), (U32)(dt * 1000));
      }
   }
 
}


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

http://i.imgur.com/sLKrmPQ.jpg


:mrgreen:

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...