Jump to content

ExplosionShape Improvement


Steve_Yorkshire

Recommended Posts

filename ExplosionData::explosionShape


Optional DTS or DAE shape to place at the center of the explosion.

The ambient animation of this model will be played automatically at the start of the explosion.


bool ExplosionData::faceViewer


Controls whether the visual effects of the explosion always face the camera.

 

I've been using explosionShape for a while and have come up with an improvement. :idea:


In stock T3D the model for an explosionShape spawns in game with the rotation of it's impact. This is fine for vertical collision but means that striking a horizontal contact flips the model 90 degrees. If you wanted to spawn an explosion by script - without an impact vector/rotation you would have to export the animated model facing the Y-axis for it's "up" - but then it would be bent 90 degrees if it was used for a standard collision impact.


But wait! There's more!


Using faceViewer=bool; was also funky as it would billboard it's rotation towards the camera, half the model would end up buried beneath the terrain and faceViewer had a random Y rotation in it's code.


Non of this is helpful if you want your animated mesh explosion to align upwards (Z axis) - for instance a nuclear mushroom cloud or a shockwave along the ground.


What would be useful is a faceZ(bool) variable which works like particleEmitter's alignDirection = "0 0 1"; and make the model always stand up along the z-axis. And here it is! :P


source/T3D/fx/explosion.h

class ExplosionData : public GameBaseData {
//...
  public:
   StringTableEntry dtsFileName;
 
   bool faceViewer;
   bool faceZ;//yorks in ~line 62
 
   S32 particleDensity;
//...

 

source/T3D/fx/explosion.cpp

ExplosionData::ExplosionData()
{
//...
 
   faceViewer   = false;
   faceZ		= false;//yorks in ~line 226
 
   soundProfile      = NULL;
//...
 
void ExplosionData::initPersistFields()
{
//...
      "Non-looping sound effect that will be played at the start of the explosion." );
   addField( "faceViewer", TypeBool, Offset(faceViewer, ExplosionData),
      "Controls whether the visual effects of the explosion always face the camera." );
   //yorks in ~line 300
   addField("faceZ", TypeBool, Offset(faceZ, ExplosionData),
	   "Controls whether the visual effects of the explosion always face Z axis/up axis.\n\n"
	   "Does not work with faceViewer as faceViewer takes precedent.");
   //yorks in end ~line 304
 
   addField( "particleEmitter", TYPEID< ParticleEmitterData >(), Offset(particleEmitter, ExplosionData),
//...
 
void ExplosionData::packData(BitStream* stream)
{
//...
   stream->write(particleRadius);
   stream->writeFlag(faceViewer);
   stream->writeFlag(faceZ);//yorks in ~line 559
   if(stream->writeFlag(explosionScale.x != 1 || explosionScale.y != 1 || explosionScale.z != 1))
//...
 
void ExplosionData::unpackData(BitStream* stream)
{
//...
   particleDensity = stream->readInt(14);
   stream->read(&particleRadius);
   faceViewer = stream->readFlag();
   faceZ = stream->readFlag();//yorks in ~line 666 MAIDEN MAIDEN :P
   if(stream->readFlag())
//...
 
//--------------------------------------------------------------------------
// Make the explosion face the viewer (if desired)
//--------------------------------------------------------------------------
void Explosion::prepModelView(SceneRenderState* state)
{
   MatrixF rotMatrix( true );
   Point3F targetVector;
 
   if( mDataBlock->faceViewer )
   {
      targetVector = getPosition() - state->getCameraPosition();
      targetVector.normalize();
 
      // rotate explosion each time so it's a little different
      rotMatrix.set( EulerF( 0.0f, mRandAngle, 0.0f ) );
   }
   /* //yorks out ~line 1039
   else
   {
	  targetVector = mInitialNormal;//yorks out end
   }
   */ //yorks out end
   else if (mDataBlock->faceZ)//yorks new in ~line 1045
   {
	  targetVector = state->getCameraPosition() - getPosition();
	  targetVector.z = 0.0f;
	  targetVector.normalize();
   }
   else
	   targetVector = mInitialNormal;//yorks new end ~line 1052
 
   MatrixF explOrient = MathUtils::createOrientFromDir( targetVector );
   explOrient.mul( rotMatrix );
   explOrient.setPosition( getPosition() );
 
   setCurrentScale();
   explOrient.scale( mObjScale );
   GFX->setWorldMatrix( explOrient );
}

 

Note: In the above code faceZ is overriden if faceViewer is set to true.


And in your explosion datablock add faceZ = true; to enable it.

 

datablock ExplosionData(smallExplosion)
{
   explosionShape = "art/shapes/yorks/mesh_explosions/distort_explo500.dts";//your animated mesh with z-axis for up
   faceZ = true;//no tilting!
 
   lifeTimeMS = 500; // Remember explosionShape Ambient animation length overrides this!!!
   lifetimeVariance = 0;
 
   // Point emission
   emitter[0] = smallDarkExpEmitter;
   emitter[1] = smallExpSparksEmitter;
   emitter[2] = smallExpDustEmitter;
};

 

Now if you want animated explosions to always face upright regardless of impact vector rotation - they will!

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