Page 1 of 1

ExplosionShape Improvement

Posted: Wed Jan 18, 2017 8:44 pm
by Steve_Yorkshire
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

class ExplosionData : public GameBaseData {
StringTableEntry dtsFileName;

bool faceViewer;
bool faceZ;//yorks in ~line 62

S32 particleDensity;


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->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);
faceViewer = stream->readFlag();
faceZ = stream->readFlag();//yorks in ~line 666 MAIDEN MAIDEN :P

// 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();

// rotate explosion each time so it's a little different
rotMatrix.set( EulerF( 0.0f, mRandAngle, 0.0f ) );
/* //yorks out ~line 1039
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 = mInitialNormal;//yorks new end ~line 1052

MatrixF explOrient = MathUtils::createOrientFromDir( targetVector );
explOrient.mul( rotMatrix );
explOrient.setPosition( getPosition() );

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!