mirror of
https://github.com/tribes2/engine.git
synced 2026-07-12 15:04:37 +00:00
t2 engine svn checkout
This commit is contained in:
commit
ff569bd2ae
988 changed files with 394180 additions and 0 deletions
156
game/fx/cameraFXMgr.cc
Normal file
156
game/fx/cameraFXMgr.cc
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "game/fx/cameraFXMgr.h"
|
||||
|
||||
#include "math/mRandom.h"
|
||||
#include "math/mMatrix.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
// global cam fx
|
||||
CameraFXManager gCamFXMgr;
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// Camera effect
|
||||
//**************************************************************************
|
||||
CameraFX::CameraFX()
|
||||
{
|
||||
mElapsedTime = 0.0;
|
||||
mDuration = 1.0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Update
|
||||
//--------------------------------------------------------------------------
|
||||
void CameraFX::update( F32 dt )
|
||||
{
|
||||
mElapsedTime += dt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// Camera shake effect
|
||||
//**************************************************************************
|
||||
CameraShake::CameraShake()
|
||||
{
|
||||
mFreq.zero();
|
||||
mAmp.zero();
|
||||
mStartAmp.zero();
|
||||
mTimeOffset.zero();
|
||||
mCamFXTrans.identity();
|
||||
mFalloff = 10.0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Update
|
||||
//--------------------------------------------------------------------------
|
||||
void CameraShake::update( F32 dt )
|
||||
{
|
||||
Parent::update( dt );
|
||||
|
||||
fadeAmplitude();
|
||||
|
||||
VectorF camOffset;
|
||||
camOffset.x = mAmp.x * sin( M_2PI * (mTimeOffset.x + mElapsedTime) * mFreq.x );
|
||||
camOffset.y = mAmp.y * sin( M_2PI * (mTimeOffset.y + mElapsedTime) * mFreq.y );
|
||||
camOffset.z = mAmp.z * sin( M_2PI * (mTimeOffset.z + mElapsedTime) * mFreq.z );
|
||||
|
||||
VectorF rotAngles;
|
||||
rotAngles.x = camOffset.x * 10.0 * M_PI/180.0;
|
||||
rotAngles.y = camOffset.y * 10.0 * M_PI/180.0;
|
||||
rotAngles.z = camOffset.z * 10.0 * M_PI/180.0;
|
||||
MatrixF rotMatrix( EulerF( rotAngles.x, rotAngles.y, rotAngles.z ) );
|
||||
|
||||
mCamFXTrans = rotMatrix;
|
||||
mCamFXTrans.setPosition( camOffset );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Fade out the amplitude over time
|
||||
//--------------------------------------------------------------------------
|
||||
void CameraShake::fadeAmplitude()
|
||||
{
|
||||
F32 percentDone = (mElapsedTime / mDuration);
|
||||
if( percentDone > 1.0 ) percentDone = 1.0;
|
||||
|
||||
F32 time = 1 + percentDone * mFalloff;
|
||||
time = 1 / (time * time);
|
||||
|
||||
mAmp = mStartAmp * time;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Initialize
|
||||
//--------------------------------------------------------------------------
|
||||
void CameraShake::init()
|
||||
{
|
||||
mTimeOffset.x = 0.0;
|
||||
mTimeOffset.y = gRandGen.randF();
|
||||
mTimeOffset.z = gRandGen.randF();
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// CameraFXManager
|
||||
//**************************************************************************
|
||||
CameraFXManager::CameraFXManager()
|
||||
{
|
||||
mCamFXTrans.identity();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
CameraFXManager::~CameraFXManager()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Add new effect to currently running list
|
||||
//--------------------------------------------------------------------------
|
||||
void CameraFXManager::addFX( CameraFX *newFX )
|
||||
{
|
||||
mFXList.link( newFX );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Clear all currently running camera effects
|
||||
//--------------------------------------------------------------------------
|
||||
void CameraFXManager::clear()
|
||||
{
|
||||
mFXList.free();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Update camera effects
|
||||
//--------------------------------------------------------------------------
|
||||
void CameraFXManager::update( F32 dt )
|
||||
{
|
||||
CameraFXPtr *cur = NULL;
|
||||
mCamFXTrans.identity();
|
||||
|
||||
for( cur = mFXList.next( cur ); cur; cur = mFXList.next( cur ) )
|
||||
{
|
||||
CameraFX * curFX = *cur;
|
||||
curFX->update( dt );
|
||||
MatrixF fxTrans = curFX->getTrans();
|
||||
|
||||
mCamFXTrans.mul( fxTrans );
|
||||
|
||||
if( curFX->isExpired() )
|
||||
{
|
||||
CameraFXPtr *prev = mFXList.prev( cur );
|
||||
mFXList.free( cur );
|
||||
cur = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
91
game/fx/cameraFXMgr.h
Normal file
91
game/fx/cameraFXMgr.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _CAMERAFXMGR_H_
|
||||
#define _CAMERAFXMGR_H_
|
||||
|
||||
#ifndef _LLIST_H_
|
||||
#include "core/llist.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "math/mPoint.h"
|
||||
#endif
|
||||
#ifndef _MMATRIX_H_
|
||||
#include "math/mMatrix.h"
|
||||
#endif
|
||||
|
||||
//**************************************************************************
|
||||
// Abstract camera effect template
|
||||
//**************************************************************************
|
||||
class CameraFX
|
||||
{
|
||||
protected:
|
||||
F32 mElapsedTime;
|
||||
F32 mDuration;
|
||||
MatrixF mCamFXTrans;
|
||||
|
||||
public:
|
||||
CameraFX();
|
||||
|
||||
MatrixF & getTrans(){ return mCamFXTrans; }
|
||||
bool isExpired(){ return mElapsedTime >= mDuration; }
|
||||
void setDuration( F32 duration ){ mDuration = duration; }
|
||||
|
||||
virtual void update( F32 dt );
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Camera shake effect
|
||||
//--------------------------------------------------------------------------
|
||||
class CameraShake : public CameraFX
|
||||
{
|
||||
typedef CameraFX Parent;
|
||||
|
||||
VectorF mFreq; // these are vectors to represent these values in 3D
|
||||
VectorF mStartAmp;
|
||||
VectorF mAmp;
|
||||
VectorF mTimeOffset;
|
||||
F32 mFalloff;
|
||||
|
||||
public:
|
||||
CameraShake();
|
||||
|
||||
void init();
|
||||
void fadeAmplitude();
|
||||
void setFalloff( F32 falloff ){ mFalloff = falloff; }
|
||||
void setFrequency( VectorF &freq ){ mFreq = freq; }
|
||||
void setAmplitude( VectorF & ){ mStartAmp = amp; }
|
||||
|
||||
virtual void update( F32 dt );
|
||||
};
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CameraFXManager
|
||||
//**************************************************************************
|
||||
class CameraFXManager
|
||||
{
|
||||
typedef CameraFX * CameraFXPtr;
|
||||
|
||||
LList< CameraFXPtr > mFXList;
|
||||
MatrixF mCamFXTrans;
|
||||
|
||||
public:
|
||||
void addFX( CameraFX *newFX );
|
||||
void clear();
|
||||
MatrixF & getTrans(){ return mCamFXTrans; }
|
||||
void update( F32 dt );
|
||||
|
||||
CameraFXManager();
|
||||
~CameraFXManager();
|
||||
|
||||
};
|
||||
|
||||
extern CameraFXManager gCamFXMgr;
|
||||
|
||||
|
||||
#endif
|
||||
1022
game/fx/explosion.cc
Normal file
1022
game/fx/explosion.cc
Normal file
File diff suppressed because it is too large
Load diff
166
game/fx/explosion.h
Normal file
166
game/fx/explosion.h
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _EXPLOSION_H_
|
||||
#define _EXPLOSION_H_
|
||||
|
||||
#ifndef _GAMEBASE_H_
|
||||
#include "game/gameBase.h"
|
||||
#endif
|
||||
#ifndef _TSSHAPE_H_
|
||||
#include "ts/tsShape.h"
|
||||
#endif
|
||||
|
||||
class ParticleEmitter;
|
||||
class ParticleEmitterData;
|
||||
class TSThread;
|
||||
class AudioProfile;
|
||||
struct DebrisData;
|
||||
class ShockwaveData;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
class ExplosionData : public GameBaseData {
|
||||
public:
|
||||
typedef GameBaseData Parent;
|
||||
|
||||
enum ExplosionConsts
|
||||
{
|
||||
EC_NUM_DEBRIS_TYPES = 1,
|
||||
EC_NUM_EMITTERS = 4,
|
||||
EC_MAX_SUB_EXPLOSIONS = 5,
|
||||
EC_NUM_TIME_KEYS = 4,
|
||||
};
|
||||
|
||||
public:
|
||||
StringTableEntry dtsFileName;
|
||||
|
||||
bool faceViewer;
|
||||
|
||||
S32 particleDensity;
|
||||
F32 particleRadius;
|
||||
|
||||
AudioProfile* soundProfile;
|
||||
ParticleEmitterData* particleEmitter;
|
||||
S32 soundProfileId;
|
||||
S32 particleEmitterId;
|
||||
|
||||
Point3F explosionScale;
|
||||
F32 playSpeed;
|
||||
|
||||
Resource<TSShape> explosionShape;
|
||||
S32 explosionAnimation;
|
||||
|
||||
ParticleEmitterData* emitterList[EC_NUM_EMITTERS];
|
||||
S32 emitterIDList[EC_NUM_EMITTERS];
|
||||
|
||||
ShockwaveData * shockwave;
|
||||
S32 shockwaveID;
|
||||
bool shockwaveOnTerrain;
|
||||
|
||||
DebrisData * debrisList[EC_NUM_DEBRIS_TYPES];
|
||||
S32 debrisIDList[EC_NUM_DEBRIS_TYPES];
|
||||
|
||||
F32 debrisThetaMin;
|
||||
F32 debrisThetaMax;
|
||||
F32 debrisPhiMin;
|
||||
F32 debrisPhiMax;
|
||||
S32 debrisNum;
|
||||
S32 debrisNumVariance;
|
||||
F32 debrisVelocity;
|
||||
F32 debrisVelocityVariance;
|
||||
|
||||
// sub - explosions
|
||||
ExplosionData* explosionList[EC_MAX_SUB_EXPLOSIONS];
|
||||
S32 explosionIDList[EC_MAX_SUB_EXPLOSIONS];
|
||||
|
||||
S32 delayMS;
|
||||
S32 delayVariance;
|
||||
S32 lifetimeMS;
|
||||
S32 lifetimeVariance;
|
||||
|
||||
F32 offset;
|
||||
Point3F sizes[ EC_NUM_TIME_KEYS ];
|
||||
F32 times[ EC_NUM_TIME_KEYS ];
|
||||
|
||||
// camera shake data
|
||||
bool shakeCamera;
|
||||
VectorF camShakeFreq;
|
||||
VectorF camShakeAmp;
|
||||
F32 camShakeDuration;
|
||||
F32 camShakeRadius;
|
||||
F32 camShakeFalloff;
|
||||
|
||||
ExplosionData();
|
||||
DECLARE_CONOBJECT(ExplosionData);
|
||||
bool onAdd();
|
||||
bool preload(bool server, char errorBuffer[256]);
|
||||
static void initPersistFields();
|
||||
virtual void packData(BitStream* stream);
|
||||
virtual void unpackData(BitStream* stream);
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
class Explosion : public GameBase
|
||||
{
|
||||
typedef GameBase Parent;
|
||||
|
||||
private:
|
||||
ExplosionData* mDataBlock;
|
||||
|
||||
TSShapeInstance* mExplosionInstance;
|
||||
TSThread* mExplosionThread;
|
||||
|
||||
ParticleEmitter * mEmitterList[ ExplosionData::EC_NUM_EMITTERS ];
|
||||
|
||||
U32 mCurrMS;
|
||||
U32 mEndingMS;
|
||||
F32 mRandAngle;
|
||||
|
||||
protected:
|
||||
Point3F mInitialPosition;
|
||||
Point3F mInitialNormal;
|
||||
F32 mFade;
|
||||
F32 mFog;
|
||||
bool mActive;
|
||||
S32 mDelayMS;
|
||||
F32 mRandomVal;
|
||||
U32 mCollideType;
|
||||
|
||||
protected:
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
bool explode();
|
||||
|
||||
void processTick(const Move*);
|
||||
void advanceTime(F32 dt);
|
||||
void updateEmitters( F32 dt );
|
||||
void launchDebris( Point3F &axis );
|
||||
void spawnSubExplosions();
|
||||
void setCurrentScale();
|
||||
|
||||
// Rendering
|
||||
protected:
|
||||
bool prepRenderImage(SceneState*, const U32, const U32, const bool);
|
||||
void renderObject(SceneState*, SceneRenderImage*);
|
||||
void prepModelView(SceneState*);
|
||||
|
||||
public:
|
||||
Explosion();
|
||||
~Explosion();
|
||||
void setInitialState(const Point3F& point, const Point3F& normal, const F32 fade = 1.0);
|
||||
|
||||
bool onNewDataBlock(GameBaseData* dptr);
|
||||
void setCollideType( U32 cType ){ mCollideType = cType; }
|
||||
|
||||
DECLARE_CONOBJECT(Explosion);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
};
|
||||
|
||||
#endif // _H_EXPLOSION
|
||||
|
||||
1228
game/fx/lightning.cc
Normal file
1228
game/fx/lightning.cc
Normal file
File diff suppressed because it is too large
Load diff
216
game/fx/lightning.h
Normal file
216
game/fx/lightning.h
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _LIGHTNING_H_
|
||||
#define _LIGHTNING_H_
|
||||
|
||||
#ifndef _GAMEBASE_H_
|
||||
#include "game/gameBase.h"
|
||||
#endif
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
#ifndef _LLIST_H_
|
||||
#include "core/llist.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "core/color.h"
|
||||
#endif
|
||||
|
||||
class ShapeBase;
|
||||
class LightningStrikeEvent;
|
||||
class AudioProfile;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
class LightningData : public GameBaseData
|
||||
{
|
||||
typedef GameBaseData Parent;
|
||||
|
||||
public:
|
||||
enum Constants {
|
||||
MaxThunders = 8,
|
||||
MaxTextures = 8
|
||||
};
|
||||
|
||||
//-------------------------------------- Console set variables
|
||||
public:
|
||||
AudioProfile* thunderSounds[MaxThunders];
|
||||
AudioProfile* strikeSound;
|
||||
StringTableEntry strikeTextureNames[MaxTextures];
|
||||
|
||||
//-------------------------------------- load set variables
|
||||
public:
|
||||
S32 thunderSoundIds[MaxThunders];
|
||||
S32 strikeSoundID;
|
||||
|
||||
TextureHandle strikeTextures[MaxTextures];
|
||||
U32 numThunders;
|
||||
|
||||
protected:
|
||||
bool onAdd();
|
||||
|
||||
|
||||
public:
|
||||
LightningData();
|
||||
~LightningData();
|
||||
|
||||
void packData(BitStream*);
|
||||
void unpackData(BitStream*);
|
||||
bool preload(bool server, char errorBuffer[256]);
|
||||
|
||||
DECLARE_CONOBJECT(LightningData);
|
||||
static void initPersistFields();
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
struct LightningBolt
|
||||
{
|
||||
|
||||
struct Node
|
||||
{
|
||||
Point3F point;
|
||||
VectorF dirToMainLine;
|
||||
};
|
||||
|
||||
struct NodeManager
|
||||
{
|
||||
Node nodeList[10];
|
||||
|
||||
Point3F startPoint;
|
||||
Point3F endPoint;
|
||||
U32 numNodes;
|
||||
F32 maxAngle;
|
||||
|
||||
void generateNodes();
|
||||
};
|
||||
|
||||
NodeManager mMajorNodes;
|
||||
Vector< NodeManager > mMinorNodes;
|
||||
LList< LightningBolt > splitList;
|
||||
|
||||
F32 lifetime;
|
||||
F32 elapsedTime;
|
||||
F32 fadeTime;
|
||||
bool isFading;
|
||||
F32 percentFade;
|
||||
bool startRender;
|
||||
F32 renderTime;
|
||||
|
||||
F32 width;
|
||||
F32 chanceOfSplit;
|
||||
Point3F startPoint;
|
||||
Point3F endPoint;
|
||||
|
||||
U32 numMajorNodes;
|
||||
F32 maxMajorAngle;
|
||||
U32 numMinorNodes;
|
||||
F32 maxMinorAngle;
|
||||
|
||||
LightningBolt();
|
||||
|
||||
void createSplit( Point3F startPoint, Point3F endPoint, U32 depth, F32 width );
|
||||
F32 findHeight( Point3F &point, SceneGraph* sceneManager );
|
||||
void render( const Point3F &camPos );
|
||||
void renderSegment( NodeManager &segment, const Point3F &camPos, bool renderLastPoint );
|
||||
void generate();
|
||||
void generateMinorNodes();
|
||||
void startSplits();
|
||||
void update( F32 dt );
|
||||
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
class Lightning : public GameBase
|
||||
{
|
||||
typedef GameBase Parent;
|
||||
|
||||
protected:
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
bool onNewDataBlock(GameBaseData* dptr);
|
||||
|
||||
struct Strike {
|
||||
F32 xVal; // Position in cloud layer of strike
|
||||
F32 yVal; // top
|
||||
|
||||
bool targetedStrike; // Is this a targeted strike?
|
||||
U32 targetGID;
|
||||
|
||||
F32 deathAge; // Age at which this strike expires
|
||||
F32 currentAge; // Current age of this strike (updated by advanceTime)
|
||||
|
||||
LightningBolt bolt[3];
|
||||
|
||||
Strike* next;
|
||||
};
|
||||
struct Thunder {
|
||||
F32 tRemaining;
|
||||
Thunder* next;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//-------------------------------------- Console set variables
|
||||
public:
|
||||
|
||||
U32 strikesPerMinute;
|
||||
F32 strikeWidth;
|
||||
F32 chanceToHitTarget;
|
||||
F32 strikeRadius;
|
||||
F32 boltStartRadius;
|
||||
ColorF color;
|
||||
ColorF fadeColor;
|
||||
bool useFog;
|
||||
|
||||
// Rendering
|
||||
protected:
|
||||
bool prepRenderImage(SceneState*, const U32, const U32, const bool);
|
||||
void renderObject(SceneState*, SceneRenderImage*);
|
||||
|
||||
// Time management
|
||||
void processTick(const Move*);
|
||||
void interpolateTick(F32);
|
||||
void advanceTime(F32);
|
||||
|
||||
// Strike management
|
||||
void scheduleThunder(Strike*);
|
||||
|
||||
// Data members
|
||||
private:
|
||||
LightningData* mDataBlock;
|
||||
|
||||
protected:
|
||||
U32 mLastThink; // Valid only on server
|
||||
|
||||
Strike* mStrikeListHead; // Valid on on the client
|
||||
Thunder* mThunderListHead;
|
||||
|
||||
static const U32 csmTargetMask;
|
||||
|
||||
public:
|
||||
Lightning();
|
||||
~Lightning();
|
||||
|
||||
void applyDamage( const Point3F& hitPosition, const Point3F& hitNormal, SceneObject* hitObject );
|
||||
void warningFlashes();
|
||||
void strikeRandomPoint();
|
||||
void strikeObject(ShapeBase*);
|
||||
void processEvent(LightningStrikeEvent*);
|
||||
|
||||
DECLARE_CONOBJECT(Lightning);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
U32 packUpdate(NetConnection*, U32 mask, BitStream* stream);
|
||||
void unpackUpdate(NetConnection*, BitStream* stream);
|
||||
};
|
||||
|
||||
#endif // _H_LIGHTNING
|
||||
|
||||
226
game/fx/particleEmitter.cc
Normal file
226
game/fx/particleEmitter.cc
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "game/fx/particleEmitter.h"
|
||||
#include "game/fx/particleEngine.h"
|
||||
#include "core/bitStream.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/objectTypes.h"
|
||||
#include "math/mathIO.h"
|
||||
|
||||
IMPLEMENT_CO_DATABLOCK_V1(ParticleEmissionDummyData);
|
||||
IMPLEMENT_CO_NETOBJECT_V1(ParticleEmissionDummy);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//--------------------------------------
|
||||
//
|
||||
ParticleEmissionDummyData::ParticleEmissionDummyData()
|
||||
{
|
||||
timeMultiple = 1.0;
|
||||
}
|
||||
|
||||
ParticleEmissionDummyData::~ParticleEmissionDummyData()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void ParticleEmissionDummyData::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("timeMultiple", TypeF32, Offset(timeMultiple, ParticleEmissionDummyData));
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool ParticleEmissionDummyData::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
if (timeMultiple < 0.01 || timeMultiple > 100) {
|
||||
Con::warnf("ParticleEmissionDummyData::onAdd(%s): timeMultiple must be between 0.01 and 100", getName());
|
||||
timeMultiple = timeMultiple < 0.01 ? 0.01 : 100;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ParticleEmissionDummyData::preload(bool server, char errorBuffer[256])
|
||||
{
|
||||
if (Parent::preload(server, errorBuffer) == false)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void ParticleEmissionDummyData::packData(BitStream* stream)
|
||||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
stream->write(timeMultiple);
|
||||
}
|
||||
|
||||
void ParticleEmissionDummyData::unpackData(BitStream* stream)
|
||||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
stream->read(&timeMultiple);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//--------------------------------------
|
||||
//
|
||||
ParticleEmissionDummy::ParticleEmissionDummy()
|
||||
{
|
||||
// Todo: ScopeAlways?
|
||||
mNetFlags.set(Ghostable);
|
||||
mTypeMask |= EnvironmentObjectType;
|
||||
|
||||
mEmitterDatablock = NULL;
|
||||
mEmitterDatablockId = 0;
|
||||
mEmitter = NULL;
|
||||
mVelocity = 1.0;
|
||||
}
|
||||
|
||||
ParticleEmissionDummy::~ParticleEmissionDummy()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void ParticleEmissionDummy::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("emitter", TypeParticleEmitterDataPtr, Offset(mEmitterDatablock, ParticleEmissionDummy));
|
||||
addField("velocity", TypeF32, Offset(mVelocity, ParticleEmissionDummy));
|
||||
}
|
||||
|
||||
|
||||
void ParticleEmissionDummy::consoleInit()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool ParticleEmissionDummy::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
if (!mEmitterDatablock && mEmitterDatablockId != 0) {
|
||||
if (Sim::findObject(mEmitterDatablockId, mEmitterDatablock) == false)
|
||||
Con::errorf(ConsoleLogEntry::General, "ParticleEmissionDummy::onAdd: Invalid packet, bad datablockId(mEmitterDatablock): %d", mEmitterDatablockId);
|
||||
}
|
||||
|
||||
if (mEmitterDatablock == NULL)
|
||||
return false;
|
||||
|
||||
if (isClientObject()) {
|
||||
ParticleEmitter* pEmitter = new ParticleEmitter;
|
||||
pEmitter->onNewDataBlock(mEmitterDatablock);
|
||||
if (pEmitter->registerObject() == false) {
|
||||
Con::warnf(ConsoleLogEntry::General, "Could not register base emitter for particle of class: %s", mDataBlock->getName());
|
||||
delete pEmitter;
|
||||
return false;
|
||||
}
|
||||
mEmitter = pEmitter;
|
||||
}
|
||||
|
||||
mObjBox.min.set(-0.5, -0.5, -0.5);
|
||||
mObjBox.max.set( 0.5, 0.5, 0.5);
|
||||
resetWorldBox();
|
||||
addToScene();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ParticleEmissionDummy::onRemove()
|
||||
{
|
||||
removeFromScene();
|
||||
if (isClientObject()) {
|
||||
mEmitter->deleteWhenEmpty();
|
||||
mEmitter = NULL;
|
||||
}
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
|
||||
bool ParticleEmissionDummy::onNewDataBlock(GameBaseData* dptr)
|
||||
{
|
||||
mDataBlock = dynamic_cast<ParticleEmissionDummyData*>(dptr);
|
||||
if (!mDataBlock || !Parent::onNewDataBlock(dptr))
|
||||
return false;
|
||||
|
||||
// Todo: Uncomment if this is a "leaf" class
|
||||
scriptOnNewDataBlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void ParticleEmissionDummy::advanceTime(F32 dt)
|
||||
{
|
||||
Parent::advanceTime(dt);
|
||||
|
||||
Point3F emitPoint, emitVelocity;
|
||||
Point3F emitAxis(0, 0, 1);
|
||||
getTransform().mulV(emitAxis);
|
||||
getTransform().getColumn(3, &emitPoint);
|
||||
emitVelocity = emitAxis * mVelocity;
|
||||
|
||||
mEmitter->emitParticles(emitPoint, emitPoint,
|
||||
emitAxis,
|
||||
emitVelocity, (dt * mDataBlock->timeMultiple * 1000.0f));
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
U32 ParticleEmissionDummy::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
|
||||
{
|
||||
U32 retMask = Parent::packUpdate(con, mask, stream);
|
||||
|
||||
mathWrite(*stream, getTransform());
|
||||
mathWrite(*stream, getScale());
|
||||
if (stream->writeFlag(mEmitterDatablock != NULL)) {
|
||||
stream->writeRangedU32(mEmitterDatablock->getId(), DataBlockObjectIdFirst,
|
||||
DataBlockObjectIdLast);
|
||||
}
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
||||
void ParticleEmissionDummy::unpackUpdate(NetConnection* con, BitStream* stream)
|
||||
{
|
||||
Parent::unpackUpdate(con, stream);
|
||||
|
||||
MatrixF temp;
|
||||
Point3F tempScale;
|
||||
mathRead(*stream, &temp);
|
||||
mathRead(*stream, &tempScale);
|
||||
|
||||
if (stream->readFlag()) {
|
||||
mEmitterDatablockId = stream->readRangedU32(DataBlockObjectIdFirst,
|
||||
DataBlockObjectIdLast);
|
||||
} else {
|
||||
mEmitterDatablockId = 0;
|
||||
}
|
||||
|
||||
setScale(tempScale);
|
||||
setTransform(temp);
|
||||
}
|
||||
|
||||
82
game/fx/particleEmitter.h
Normal file
82
game/fx/particleEmitter.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _H_PARTICLEEMISSIONDUMMY
|
||||
#define _H_PARTICLEEMISSIONDUMMY
|
||||
|
||||
#ifndef _GAMEBASE_H_
|
||||
#include "game/gameBase.h"
|
||||
#endif
|
||||
|
||||
class ParticleEmitterData;
|
||||
class ParticleEmitter;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
class ParticleEmissionDummyData : public GameBaseData
|
||||
{
|
||||
typedef GameBaseData Parent;
|
||||
|
||||
protected:
|
||||
bool onAdd();
|
||||
|
||||
//-------------------------------------- Console set variables
|
||||
public:
|
||||
F32 timeMultiple;
|
||||
|
||||
//-------------------------------------- load set variables
|
||||
public:
|
||||
|
||||
public:
|
||||
ParticleEmissionDummyData();
|
||||
~ParticleEmissionDummyData();
|
||||
|
||||
void packData(BitStream*);
|
||||
void unpackData(BitStream*);
|
||||
bool preload(bool server, char errorBuffer[256]);
|
||||
|
||||
DECLARE_CONOBJECT(ParticleEmissionDummyData);
|
||||
static void initPersistFields();
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
class ParticleEmissionDummy : public GameBase
|
||||
{
|
||||
typedef GameBase Parent;
|
||||
|
||||
private:
|
||||
ParticleEmissionDummyData* mDataBlock;
|
||||
|
||||
protected:
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
bool onNewDataBlock(GameBaseData*);
|
||||
|
||||
ParticleEmitterData* mEmitterDatablock;
|
||||
S32 mEmitterDatablockId;
|
||||
|
||||
ParticleEmitter* mEmitter;
|
||||
F32 mVelocity;
|
||||
|
||||
public:
|
||||
ParticleEmissionDummy();
|
||||
~ParticleEmissionDummy();
|
||||
|
||||
// Time/Move Management
|
||||
public:
|
||||
void advanceTime(F32);
|
||||
|
||||
DECLARE_CONOBJECT(ParticleEmissionDummy);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
U32 packUpdate(NetConnection*, U32 mask, BitStream* stream);
|
||||
void unpackUpdate(NetConnection*, BitStream* stream);
|
||||
};
|
||||
|
||||
#endif // _H_PARTICLEEMISSIONDUMMY
|
||||
|
||||
1477
game/fx/particleEngine.cc
Normal file
1477
game/fx/particleEngine.cc
Normal file
File diff suppressed because it is too large
Load diff
178
game/fx/particleEngine.h
Normal file
178
game/fx/particleEngine.h
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _H_PARTICLEEMITTER
|
||||
#define _H_PARTICLEEMITTER
|
||||
|
||||
#ifndef _GAMEBASE_H_
|
||||
#include "game/gameBase.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "core/color.h"
|
||||
#endif
|
||||
|
||||
//-------------------------------------- Engine initialization...
|
||||
//
|
||||
namespace ParticleEngine {
|
||||
|
||||
enum ParticleConsts
|
||||
{
|
||||
PC_COLOR_KEYS = 4,
|
||||
PC_SIZE_KEYS = 4,
|
||||
};
|
||||
|
||||
void init();
|
||||
void destroy();
|
||||
|
||||
extern Point3F windVelocity;
|
||||
inline void setWindVelocity(const Point3F & vel) { windVelocity = vel; }
|
||||
inline Point3F getWindVelocity() { return windVelocity; }
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-------------------------------------- The data and the Emitter class
|
||||
// are all that the game should deal
|
||||
// with (other than initializing the
|
||||
// global engine pointer of course)
|
||||
//
|
||||
struct Particle;
|
||||
class ParticleData;
|
||||
|
||||
//--------------------------------------
|
||||
class ParticleEmitterData : public GameBaseData {
|
||||
typedef GameBaseData Parent;
|
||||
|
||||
public:
|
||||
ParticleEmitterData();
|
||||
DECLARE_CONOBJECT(ParticleEmitterData);
|
||||
static void initPersistFields();
|
||||
void packData(BitStream* stream);
|
||||
void unpackData(BitStream* stream);
|
||||
bool preload(bool server, char errorBuffer[256]);
|
||||
|
||||
bool onAdd();
|
||||
|
||||
public:
|
||||
S32 ejectionPeriodMS;
|
||||
S32 periodVarianceMS;
|
||||
|
||||
F32 ejectionVelocity;
|
||||
F32 velocityVariance;
|
||||
F32 ejectionOffset;
|
||||
|
||||
F32 thetaMin;
|
||||
F32 thetaMax;
|
||||
|
||||
F32 phiReferenceVel;
|
||||
F32 phiVariance;
|
||||
|
||||
U32 lifetimeMS;
|
||||
U32 lifetimeVarianceMS;
|
||||
|
||||
bool overrideAdvance;
|
||||
bool orientParticles;
|
||||
bool orientOnVelocity;
|
||||
bool useEmitterSizes;
|
||||
bool useEmitterColors;
|
||||
|
||||
StringTableEntry particleString;
|
||||
Vector<ParticleData*> particleDataBlocks;
|
||||
Vector<U32> dataBlockIds;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
class ParticleEmitter : public GameBase
|
||||
{
|
||||
typedef GameBase Parent;
|
||||
friend class PEngine;
|
||||
|
||||
public:
|
||||
ParticleEmitter();
|
||||
~ParticleEmitter();
|
||||
|
||||
void setSizes( F32 *sizeList );
|
||||
void setColors( ColorF *colorList );
|
||||
ParticleEmitterData *getDataBlock(){ return mDataBlock; }
|
||||
bool onNewDataBlock(GameBaseData* dptr);
|
||||
|
||||
// By default, a particle renderer will wait for it's owner to delete it. When this
|
||||
// is turned on, it will delete itself as soon as it's particle count drops to zero.
|
||||
void deleteWhenEmpty();
|
||||
|
||||
// Main interface for creating particles. The emitter does _not_ track changes
|
||||
// in axis or velocity over the course of a single update, so this should be called
|
||||
// at a fairly fine grain. The emitter will potentially track the last particle
|
||||
// to be created into the next call to this function in order to create a uniformly
|
||||
// random time distribution of the particles. If the object to which the emitter is
|
||||
// attached is in motion, it should try to ensure that for call (n+1) to this
|
||||
// function, start is equal to the end from call (n). This will ensure a uniform
|
||||
// spatial distribution.
|
||||
void emitParticles(const Point3F& start,
|
||||
const Point3F& end,
|
||||
const Point3F& axis,
|
||||
const Point3F& velocity,
|
||||
const U32 numMilliseconds);
|
||||
void emitParticles(const Point3F& point,
|
||||
const bool useLastPosition,
|
||||
const Point3F& axis,
|
||||
const Point3F& velocity,
|
||||
const U32 numMilliseconds);
|
||||
void emitParticles(const Point3F& rCenter,
|
||||
const Point3F& rNormal,
|
||||
const F32 radius,
|
||||
const Point3F& velocity,
|
||||
S32 count);
|
||||
|
||||
// Internal interface
|
||||
protected:
|
||||
void addParticle(const Point3F&, const Point3F&, const Point3F&, const Point3F&);
|
||||
void renderBillboardParticle( Particle &part, Point3F *basePnts, MatrixF &camView, F32 spinFactor );
|
||||
void renderOrientedParticle( Particle &part, const Point3F &camPos );
|
||||
void updateBBox();
|
||||
|
||||
protected:
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
|
||||
void processTick(const Move*);
|
||||
void advanceTime(F32);
|
||||
|
||||
// Rendering
|
||||
protected:
|
||||
bool prepRenderImage(SceneState*, const U32, const U32, const bool);
|
||||
void renderObject(SceneState*, SceneRenderImage*);
|
||||
|
||||
// PEngine interface
|
||||
private:
|
||||
void stealParticle(Particle*);
|
||||
|
||||
private:
|
||||
ParticleEmitterData* mDataBlock;
|
||||
|
||||
Particle* mParticleListHead;
|
||||
|
||||
U32 mInternalClock;
|
||||
|
||||
U32 mNextParticleTime;
|
||||
|
||||
Point3F mLastPosition;
|
||||
bool mHasLastPosition;
|
||||
|
||||
bool mDeleteWhenEmpty;
|
||||
bool mDeleteOnTick;
|
||||
|
||||
S32 mLifetimeMS;
|
||||
S32 mElapsedTimeMS;
|
||||
|
||||
F32 sizes[ParticleEngine::PC_SIZE_KEYS];
|
||||
ColorF colors[ParticleEngine::PC_COLOR_KEYS];
|
||||
};
|
||||
|
||||
#endif // _H_PARTICLEEMITTER
|
||||
|
||||
976
game/fx/precipitation.cc
Normal file
976
game/fx/precipitation.cc
Normal file
|
|
@ -0,0 +1,976 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "game/fx/precipitation.h"
|
||||
|
||||
#include "dgl/dgl.h"
|
||||
#include "math/mathIO.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "sceneGraph/sceneGraph.h"
|
||||
#include "sceneGraph/sceneState.h"
|
||||
#include "terrain/sky.h"
|
||||
#include "game/gameConnection.h"
|
||||
#include "game/player.h"
|
||||
|
||||
#define COLOR_OFFSET 0.25
|
||||
|
||||
bool Precipitation::smPrecipitationOn = true;
|
||||
bool Precipitation::smPrecipitationPause = false;
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1(Precipitation);
|
||||
IMPLEMENT_CO_DATABLOCK_V1(PrecipitationData);
|
||||
|
||||
namespace {
|
||||
|
||||
MRandomLCG sgRandom(0xdeadbeef);
|
||||
|
||||
|
||||
} // namespace {}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//--------------------------------------
|
||||
|
||||
|
||||
PrecipitationData::PrecipitationData()
|
||||
{
|
||||
soundProfile = NULL;
|
||||
soundProfileId = 0;
|
||||
mType = 0;
|
||||
mMaxSize = 1.0f;
|
||||
mMaterialListName = NULL;
|
||||
mSizeX = 1.0;
|
||||
mSizeY = 1.0;
|
||||
}
|
||||
|
||||
IMPLEMENT_GETDATATYPE(PrecipitationData)
|
||||
IMPLEMENT_SETDATATYPE(PrecipitationData)
|
||||
|
||||
void PrecipitationData::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
Con::registerType("GameBaseDataPtr", TypeGameBaseDataPtr, sizeof(PrecipitationData*),
|
||||
REF_GETDATATYPE(PrecipitationData),
|
||||
REF_SETDATATYPE(PrecipitationData));
|
||||
|
||||
addField("soundProfile", TypeAudioProfilePtr, Offset(soundProfile, PrecipitationData));
|
||||
addField("type", TypeS32, Offset(mType, PrecipitationData));
|
||||
addField("maxSize", TypeF32, Offset(mMaxSize, PrecipitationData));
|
||||
addField("materialList", TypeString, Offset(mMaterialListName,PrecipitationData));
|
||||
addField("sizeX", TypeF32, Offset(mSizeX, PrecipitationData));
|
||||
addField("sizeY", TypeF32, Offset(mSizeY, PrecipitationData));
|
||||
|
||||
/////////////////////////
|
||||
//JohnA Will remove
|
||||
// Used to tweak the precipitation
|
||||
/////////////////////////
|
||||
addField("movingBoxPer", TypeF32, Offset(tMoveingBoxPer, PrecipitationData));
|
||||
addField("divHeightVal", TypeF32, Offset(tDivHeightVal, PrecipitationData));
|
||||
addField("sizeBigBox", TypeF32, Offset(tSizeBigBox, PrecipitationData));
|
||||
addField("topBoxSpeed", TypeF32, Offset(tTopBoxSpeed, PrecipitationData));
|
||||
addField("frontBoxSpeed", TypeF32, Offset(tFrontBoxSpeed, PrecipitationData));
|
||||
addField("topBoxDrawPer", TypeF32, Offset(tTopBoxDrawPer, PrecipitationData));
|
||||
addField("bottomDrawHeight", TypeF32, Offset(tBottomDrawHeight, PrecipitationData));
|
||||
addField("skipIfPer", TypeF32, Offset(tSkipIfPer, PrecipitationData));
|
||||
addField("bottomSpeedPer", TypeF32, Offset(tBottomSpeedPer, PrecipitationData));
|
||||
addField("FrontSpeedPer", TypeF32, Offset(tFrontSpeedPer, PrecipitationData));
|
||||
addField("FrontRadiusPer", TypeF32, Offset(tFrontRadiusPer, PrecipitationData));
|
||||
/////////////////////////
|
||||
|
||||
}
|
||||
|
||||
bool PrecipitationData::onAdd()
|
||||
{
|
||||
if (Parent::onAdd() == false)
|
||||
return false;
|
||||
|
||||
if (!soundProfile && soundProfileId != 0)
|
||||
if (Sim::findObject(soundProfileId, soundProfile) == false)
|
||||
Con::errorf(ConsoleLogEntry::General, "Error, unable to load sound profile for precipitation datablock");
|
||||
|
||||
if (mSizeX <= 0.0f || mSizeX > 20.0f) {
|
||||
Con::warnf(ConsoleLogEntry::General, "PrecipitationData(%s)::onAdd: sizeX must be in the range [0 >, 20]", getName());
|
||||
mSizeX = 1.0;
|
||||
}
|
||||
|
||||
if (mSizeY <= 0.0f || mSizeY > 20.0f) {
|
||||
Con::warnf(ConsoleLogEntry::General, "PrecipitationData(%s)::onAdd: sizeY must be in the range [0 >, 20]", getName());
|
||||
mSizeY = 1.0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrecipitationData::packData(BitStream* stream)
|
||||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
if (stream->writeFlag(soundProfile != NULL))
|
||||
stream->writeRangedU32(soundProfile->getId(), DataBlockObjectIdFirst,
|
||||
DataBlockObjectIdLast);
|
||||
stream->write(mType);
|
||||
stream->write(mMaxSize);
|
||||
stream->writeString(mMaterialListName);
|
||||
stream->write(mSizeX);
|
||||
stream->write(mSizeY);
|
||||
|
||||
/////////////////////////
|
||||
//JohnA Will remove
|
||||
// Used to tweak the precipitation
|
||||
/////////////////////////
|
||||
stream->write(tMoveingBoxPer);
|
||||
stream->write(tDivHeightVal);
|
||||
stream->write(tSizeBigBox);
|
||||
stream->write(tTopBoxSpeed);
|
||||
stream->write(tFrontBoxSpeed);
|
||||
stream->write(tTopBoxDrawPer);
|
||||
stream->write(tBottomDrawHeight);
|
||||
stream->write(tSkipIfPer);
|
||||
stream->write(tBottomSpeedPer);
|
||||
stream->write(tFrontSpeedPer);
|
||||
stream->write(tFrontRadiusPer);
|
||||
/////////////////////////
|
||||
|
||||
}
|
||||
|
||||
void PrecipitationData::unpackData(BitStream* stream)
|
||||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
if (stream->readFlag())
|
||||
soundProfileId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
|
||||
else
|
||||
soundProfileId = 0;
|
||||
|
||||
stream->read(&mType);
|
||||
stream->read(&mMaxSize);
|
||||
mMaterialListName = stream->readSTString();
|
||||
stream->read(&mSizeX);
|
||||
stream->read(&mSizeY);
|
||||
|
||||
/////////////////////////
|
||||
//JohnA Will remove
|
||||
// Used to tweak the precipitation
|
||||
/////////////////////////
|
||||
stream->read(&tMoveingBoxPer);
|
||||
stream->read(&tDivHeightVal);
|
||||
stream->read(&tSizeBigBox);
|
||||
stream->read(&tTopBoxSpeed);
|
||||
stream->read(&tFrontBoxSpeed);
|
||||
stream->read(&tTopBoxDrawPer);
|
||||
stream->read(&tBottomDrawHeight);
|
||||
stream->read(&tSkipIfPer);
|
||||
stream->read(&tBottomSpeedPer);
|
||||
stream->read(&tFrontSpeedPer);
|
||||
stream->read(&tFrontRadiusPer);
|
||||
/////////////////////////
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//--------------------------------------
|
||||
|
||||
Precipitation::Precipitation()
|
||||
{
|
||||
mTypeMask |= ProjectileObjectType;
|
||||
|
||||
mNetFlags.set(ScopeAlways);
|
||||
mNumDrops = 0;
|
||||
mCurrentTime = 0;
|
||||
mAudioHandle = 0;
|
||||
mPercentage = 1.0f;
|
||||
mFirstTime = true;
|
||||
mStormData.lastTime = 0.0f;
|
||||
mStormData.endPercentage = -1.0f;
|
||||
mStormData.time = 0.0f;
|
||||
mStormData.speed = 0.0f;
|
||||
mStormData.state = done;
|
||||
mStormData.numDrops = 0.0f;
|
||||
mStormData.currentTime = 0.0f;
|
||||
mStormPrecipitationOn = true;
|
||||
mLastPos.set(0.0f, 0.0f, 0.0f);
|
||||
mRandomHeight = false;
|
||||
mAverageSpeed = 0.0f;
|
||||
mLastHeight = 0.0f;
|
||||
mShiftPrecip.set(0.0f, 0.0f, 0.0f);
|
||||
mColorCount = 0;
|
||||
for(S32 x = 0; x < MAX_NUM_COLOR; ++x)
|
||||
mColor[x].set(-1.0f, 0.0f, 0.0f);
|
||||
|
||||
mMinVelocity = -1.0f;
|
||||
mMaxVelocity = -1.0f;
|
||||
mOffset.set(0.0f, 0.0f, 1.0f);
|
||||
mOffsetSpeed = 0.25f;
|
||||
mMaxDrops = -1;
|
||||
mRadius = -1;
|
||||
}
|
||||
|
||||
Precipitation::~Precipitation()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Precipitation::inspectPostApply()
|
||||
{
|
||||
setMaskBits(InitMask);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void Precipitation::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("percentage", TypeF32, Offset(mPercentage, Precipitation));
|
||||
addField("color1", TypeColorF, Offset(mColor[0], Precipitation));
|
||||
addField("color2", TypeColorF, Offset(mColor[1], Precipitation));
|
||||
addField("color3", TypeColorF, Offset(mColor[2], Precipitation));
|
||||
addField("offsetSpeed", TypeF32, Offset(mOffsetSpeed, Precipitation));
|
||||
addField("minVelocity", TypeF32, Offset(mMinVelocity, Precipitation));
|
||||
addField("maxVelocity", TypeF32, Offset(mMaxVelocity, Precipitation));
|
||||
addField("maxNumDrops", TypeS32, Offset(mMaxDrops, Precipitation));
|
||||
addField("maxRadius", TypeS32, Offset(mRadius, Precipitation));
|
||||
}
|
||||
|
||||
void cSetPercentage(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
Precipitation *ctrl = static_cast<Precipitation*>(obj);
|
||||
ctrl->setPercentage(dAtof(argv[2]));
|
||||
}
|
||||
|
||||
static void cSetupStorm(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
Precipitation *ctrl = static_cast<Precipitation*>(obj);
|
||||
ctrl->setupStorm(dAtof(argv[2]), dAtof(argv[3]));
|
||||
}
|
||||
|
||||
static void cStormShow(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
Precipitation *ctrl = static_cast<Precipitation*>(obj);
|
||||
ctrl->stormShow(dAtob(argv[2]));
|
||||
}
|
||||
|
||||
void Precipitation::consoleInit()
|
||||
{
|
||||
Con::addVariable("$pref::precipitationOn", TypeBool, &smPrecipitationOn);
|
||||
Con::addVariable("$pref::prePause", TypeBool, &smPrecipitationPause);
|
||||
Con::addCommand("Precipitation", "setPercentage", cSetPercentage, "precipitation.setPercentage(percentage <1.0 to 0.0>)", 3, 3);
|
||||
Con::addCommand("Precipitation", "stormPrecipitation", cSetupStorm, "precipitation.stormPrecipitation(Percentage <0 to 1>, Time<sec>)", 4, 4);
|
||||
Con::addCommand("Precipitation", "stormShow", cStormShow, "precipitation.stormShow(bool)",3, 3);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool Precipitation::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
if (mPercentage > 1.0f || mPercentage < 0.0f) {
|
||||
Con::warnf(ConsoleLogEntry::General, "Precipitation::onAdd - Percentage is invalid. <= 1.0 or >= 0.0 ");
|
||||
mPercentage = 1.0f;
|
||||
}
|
||||
|
||||
if (isClientObject()) {
|
||||
mRandomHeight = true;
|
||||
for (U32 i = 0; i < mMaxDrops; i++)
|
||||
mFallingObj[i].notValid = true;
|
||||
|
||||
if(mDataBlock->mMaterialListName[0])
|
||||
loadDml();
|
||||
|
||||
if (mDataBlock->soundProfile && smPrecipitationOn)
|
||||
mAudioHandle = alxPlay(mDataBlock->soundProfile, &getTransform() );
|
||||
mNumDrops = mMaxDrops * mPercentage;
|
||||
mStormData.numDrops = mNumDrops;
|
||||
setupTexCoords();
|
||||
}
|
||||
else
|
||||
assignName("Precipitation");
|
||||
|
||||
mObjBox.min.set(-1e6, -1e6, -1e6);
|
||||
mObjBox.max.set( 1e6, 1e6, 1e6);
|
||||
|
||||
resetWorldBox();
|
||||
addToScene();
|
||||
setDefaultValues();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Precipitation::setDefaultValues()
|
||||
{
|
||||
mColorCount = 0;
|
||||
for(S32 x = 0; x < MAX_NUM_COLOR; ++x)
|
||||
if(mColor[x].red >= 0.0f)
|
||||
mColorCount++;
|
||||
else
|
||||
break;
|
||||
if(mColorCount == 0)
|
||||
{
|
||||
if(mDataBlock->mType == 0)
|
||||
mColor[0].set(0.6, 0.6, 0.6);
|
||||
else if(mDataBlock->mType == 1)
|
||||
mColor[0].set(1.0, 1.0, 1.0);
|
||||
else
|
||||
mColor[0].set(0.9, 0.8, 0.5);
|
||||
mColorCount = 1;
|
||||
}
|
||||
if(mMinVelocity == -1.0f)
|
||||
{
|
||||
if(mDataBlock->mType == 0)
|
||||
mMinVelocity = 1.25f;
|
||||
else if(mDataBlock->mType == 1)
|
||||
mMinVelocity = 0.25f;
|
||||
else
|
||||
mMinVelocity = 0.25f;
|
||||
}
|
||||
if(mMaxVelocity == -1.0f)
|
||||
{
|
||||
if(mDataBlock->mType == 0)
|
||||
mMaxVelocity = 4.0f;
|
||||
else if(mDataBlock->mType == 1)
|
||||
mMaxVelocity = 1.5f;
|
||||
else
|
||||
mMaxVelocity = 1.0f;
|
||||
}
|
||||
|
||||
if(mRadius == -1.0f)
|
||||
{
|
||||
if(mDataBlock->mType == 0)
|
||||
mRadius = 80;
|
||||
else if(mDataBlock->mType == 1)
|
||||
mRadius = 125;
|
||||
else
|
||||
mRadius = 80;
|
||||
}
|
||||
|
||||
if(mMaxDrops > MAX_NUM_DROPS || mMaxDrops < 0)
|
||||
mMaxDrops = MAX_NUM_DROPS;
|
||||
}
|
||||
|
||||
U32 Precipitation::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
|
||||
{
|
||||
Parent::packUpdate(con, mask, stream);
|
||||
|
||||
if(stream->writeFlag(mask & InitMask))
|
||||
{
|
||||
stream->write(mPercentage);
|
||||
stream->write(mColorCount);
|
||||
for(S32 x = 0; x < mColorCount; ++x)
|
||||
stream->write(mColor[x]);
|
||||
stream->write(mOffsetSpeed);
|
||||
stream->write(mMinVelocity);
|
||||
stream->write(mMaxVelocity);
|
||||
stream->write(mMaxDrops);
|
||||
stream->write(mRadius);
|
||||
|
||||
if(stream->writeFlag((mStormData.currentTime / 32.0f) < mStormData.time))
|
||||
{
|
||||
stream->write(mStormData.currentTime);
|
||||
stream->write(mStormData.endPercentage);
|
||||
stream->write(mStormData.time);
|
||||
}
|
||||
}
|
||||
|
||||
if(stream->writeFlag(mask & StormShowMask))
|
||||
stream->write(mStormPrecipitationOn);
|
||||
|
||||
if(stream->writeFlag(mask & StormMask))
|
||||
{
|
||||
stream->write(mStormData.endPercentage);
|
||||
stream->write(mStormData.time);
|
||||
mStormData.currentTime = 0.0f;
|
||||
}
|
||||
|
||||
if(stream->writeFlag(mask & PercentageMask))
|
||||
stream->write(mPercentage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Precipitation::unpackUpdate(NetConnection* con, BitStream* stream)
|
||||
{
|
||||
Parent::unpackUpdate(con, stream);
|
||||
|
||||
if(stream->readFlag())
|
||||
{
|
||||
stream->read(&mPercentage);
|
||||
stream->read(&mColorCount);
|
||||
for(S32 x = 0; x < mColorCount; ++x)
|
||||
stream->read(&mColor[x]);
|
||||
stream->read(&mOffsetSpeed);
|
||||
stream->read(&mMinVelocity);
|
||||
stream->read(&mMaxVelocity);
|
||||
stream->read(&mMaxDrops);
|
||||
stream->read(&mRadius);
|
||||
|
||||
if(stream->readFlag())
|
||||
{
|
||||
stream->read(&mStormData.currentTime);
|
||||
stream->read(&mStormData.endPercentage);
|
||||
stream->read(&mStormData.time);
|
||||
|
||||
F32 percentage = mStormData.endPercentage;
|
||||
|
||||
mStormData.speed = (percentage - mPercentage) / (mStormData.time * 32.0f);
|
||||
mStormData.endPercentage = percentage;
|
||||
mStormData.state = (mPercentage > percentage) ? out : in;
|
||||
mPercentage += (mStormData.state == in) ? mStormData.speed * mStormData.currentTime :
|
||||
-mStormData.speed * mStormData.currentTime;
|
||||
mStormPrecipitationOn = true;
|
||||
|
||||
}
|
||||
}
|
||||
if(stream->readFlag())
|
||||
{
|
||||
stream->read(&mStormPrecipitationOn);
|
||||
if(!mStormPrecipitationOn)
|
||||
mPercentage = 0.0f;
|
||||
}
|
||||
|
||||
if(stream->readFlag())
|
||||
{
|
||||
stream->read(&mStormData.endPercentage);
|
||||
stream->read(&mStormData.time);
|
||||
|
||||
if(mStormData.time)
|
||||
startStorm();
|
||||
}
|
||||
|
||||
if(stream->readFlag())
|
||||
{
|
||||
stream->read(&mPercentage);
|
||||
mNumDrops = mMaxDrops * mPercentage;
|
||||
}
|
||||
}
|
||||
|
||||
void Precipitation::onRemove()
|
||||
{
|
||||
removeFromScene();
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
bool Precipitation::onNewDataBlock(GameBaseData* dptr)
|
||||
{
|
||||
mDataBlock = dynamic_cast<PrecipitationData*>(dptr);
|
||||
if (!mDataBlock || !Parent::onNewDataBlock(dptr))
|
||||
return false;
|
||||
|
||||
setDefaultValues();
|
||||
|
||||
mAverageSpeed = ((mMinVelocity + mMaxVelocity) / 2.0f) * 0.65f;
|
||||
scriptOnNewDataBlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Precipitation::loadDml()
|
||||
{
|
||||
S32 x;
|
||||
mNumTextures = 0;
|
||||
Stream *stream = ResourceManager->openStream(mDataBlock->mMaterialListName);
|
||||
if(stream)
|
||||
{
|
||||
mMaterialList.read(*stream);
|
||||
ResourceManager->closeStream(stream);
|
||||
mMaterialList.load();
|
||||
for(x = 0; x < mMaterialList.size(); ++x, ++mNumTextures)
|
||||
mTextures[x] = mMaterialList.getMaterial(x);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool Precipitation::prepRenderImage(SceneState* state, const U32 stateKey,
|
||||
const U32 /*startZone*/, const bool /*modifyBaseState*/)
|
||||
{
|
||||
if (!smPrecipitationOn)
|
||||
{
|
||||
if (mAudioHandle)
|
||||
{
|
||||
alxStop(mAudioHandle);
|
||||
mAudioHandle = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!mStormPrecipitationOn)
|
||||
return false;
|
||||
if (!mAudioHandle && mDataBlock->soundProfile)
|
||||
mAudioHandle = alxPlay(mDataBlock->soundProfile, &getTransform());
|
||||
}
|
||||
|
||||
if (isLastState(state, stateKey))
|
||||
return false;
|
||||
setLastState(state, stateKey);
|
||||
|
||||
// This should be sufficient for most objects that don't manage zones, and
|
||||
// don't need to return a specialized RenderImage...
|
||||
if (state->isObjectRendered(this)) {
|
||||
SceneRenderImage* image = new SceneRenderImage;
|
||||
image->obj = this;
|
||||
image->isTranslucent = true;
|
||||
image->sortType = SceneRenderImage::EndSort;
|
||||
state->insertRenderImage(image);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Precipitation::renderObject(SceneState* state, SceneRenderImage*)
|
||||
{
|
||||
if(smPrecipitationOn)
|
||||
{
|
||||
if(!mStormPrecipitationOn)
|
||||
return;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");
|
||||
|
||||
state->mModelview.getRow(0,&mRotX);
|
||||
state->mModelview.getRow(2,&mRotZ);
|
||||
|
||||
RectI viewport;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
dglGetViewport(&viewport);
|
||||
|
||||
// Uncomment this if this is a "simple" (non-zone managing) object
|
||||
state->setupObjectProjection(this);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
if(mStormData.state != done)
|
||||
updateStorm();
|
||||
if(mDataBlock->mType == 0 || mDataBlock->mType == 1)
|
||||
renderPrecip(state->getCameraPosition());
|
||||
else if(mDataBlock->mType == 2)
|
||||
renderSand();
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
dglSetViewport(viewport);
|
||||
|
||||
mFirstTime = false;
|
||||
|
||||
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void Precipitation::advanceTime(F32 dt)
|
||||
{
|
||||
if(!mFirstTime)
|
||||
mCurrentTime += dt;
|
||||
}
|
||||
|
||||
void Precipitation::renderPrecip(Point3F camPos)
|
||||
{
|
||||
Point3F point[4];
|
||||
F32 coordX, coordY;
|
||||
F32 xRadius, yRadius;
|
||||
mRotX *= mDataBlock->mSizeX;
|
||||
mRotZ *= mDataBlock->mSizeY;
|
||||
Point2F value;
|
||||
F32 renderPer = 1.0f, minSpeed = 0.0f;
|
||||
F32 theRadius, curZVelocity = 0.0f;
|
||||
F32 height, speed, radVal;
|
||||
F32 random1, random2, random3;
|
||||
mOffsetVal.set(0.0f, 0.0f);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glAlphaFunc(GL_GREATER, 0.1f);
|
||||
glBindTexture(GL_TEXTURE_2D,mTextures[0].getGLName());
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
||||
calcVelocityBox(camPos, curZVelocity, renderPer);
|
||||
if(curZVelocity < 0.0f)
|
||||
{
|
||||
if(mDataBlock->mType == 0)
|
||||
minSpeed = ((mCurrentTime - mLastRenderTime) / (1.0f / curZVelocity)) - mMinVelocity;
|
||||
}
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
for(S32 x=0; x < mNumDrops; ++x)
|
||||
{
|
||||
if(mStormData.numDrops > x || mFallingObj[x].stillFalling)
|
||||
{
|
||||
speed = mFallingObj[x].speed;
|
||||
if(smPrecipitationPause)
|
||||
speed = 0;
|
||||
else if(minSpeed < 0.0f)
|
||||
speed = (mFallingObj[x].speed > minSpeed) ? minSpeed : mFallingObj[x].speed;
|
||||
|
||||
mFallingObj[x].curPos.set((mFallingObj[x].curPos.x + mShiftPrecip.x) + (mFallingObj[x].offset.x * speed),
|
||||
(mFallingObj[x].curPos.y + mShiftPrecip.y) + (mFallingObj[x].offset.y * speed),
|
||||
(mFallingObj[x].curPos.z + mShiftPrecip.z) + speed);
|
||||
|
||||
if(mFallingObj[x].notValid || !mBox.isContained(mFallingObj[x].curPos))
|
||||
{
|
||||
if(mStormData.numDrops > x)
|
||||
{
|
||||
xRadius = mRadius * ((mOffsetVal.x > 0.0f) ? 1.0f - mOffsetVal.x : 1.0f + mOffsetVal.x);
|
||||
yRadius = mRadius * ((mOffsetVal.y > 0.0f) ? 1.0f - mOffsetVal.y : 1.0f + mOffsetVal.y);
|
||||
|
||||
theRadius = (xRadius > yRadius) ? yRadius : xRadius;
|
||||
|
||||
random1 = Platform::getRandom();
|
||||
random2 = Platform::getRandom();
|
||||
random3 = Platform::getRandom();
|
||||
|
||||
value.set( Platform::getRandom() * 2.0f - 1.0f, Platform::getRandom() * 2.0f - 1.0f);
|
||||
value.normalize();
|
||||
|
||||
mFallingObj[x].speed = -mMinVelocity + (-(mMaxVelocity - mMinVelocity) * random3);
|
||||
if(random1 > (1.0f - renderPer) || (Platform::getRandom() < mDataBlock->tTopBoxDrawPer && renderPer < - 0.4))
|
||||
{
|
||||
//Start Drop on top of box
|
||||
if(renderPer < -0.4)
|
||||
mFallingObj[x].speed *= mDataBlock->tFrontSpeedPer * 2.5f;
|
||||
if(mRandomHeight)
|
||||
height = (mBox.max.z - 5.0f) * (Platform::getRandom() * 2.0f - 1.0f);// + Platform::getRandom() * 30;
|
||||
else
|
||||
height = mBox.max.z - 5.0f;
|
||||
mFallingObj[x].dropType = 1;
|
||||
radVal = theRadius * mClampF(((random2 < 0.2f) ? random3 : random2),
|
||||
0.01f, 1.0f);
|
||||
}
|
||||
else if(random1 > (0.0f - renderPer))
|
||||
{
|
||||
//Start Drop on side of box
|
||||
height = random3 * mBox.max.z;
|
||||
radVal = theRadius * mDataBlock->tFrontRadiusPer;
|
||||
mFallingObj[x].speed *= mDataBlock->tFrontSpeedPer;
|
||||
mFallingObj[x].dropType = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Start Drop on bottom of box
|
||||
height = mBox.min.z + mDataBlock->tBottomDrawHeight;
|
||||
mFallingObj[x].dropType = 3;
|
||||
radVal = theRadius * random3;
|
||||
mFallingObj[x].speed *= mDataBlock->tBottomSpeedPer;
|
||||
}
|
||||
value *= radVal;
|
||||
mFallingObj[x].colorIndex = (S32)(mCeil(mColorCount * random2) - 1.0f);
|
||||
mFallingObj[x].startPos.set(camPos.x + mNewCenter.x + value.x, camPos.y + mNewCenter.y + value.y, height);
|
||||
mFallingObj[x].curPos = mFallingObj[x].startPos;
|
||||
mFallingObj[x].startDiff = mFallingObj[x].startPos.z - camPos.z + 20;
|
||||
mFallingObj[x].offset = mOffset;
|
||||
mFallingObj[x].texIndex = (S32)(mCeil((NUM_TEXTURES - 1) * getRandomVal()) - 1.0f);
|
||||
mFallingObj[x].stillFalling = true;
|
||||
mFallingObj[x].notValid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mFallingObj[x].stillFalling = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(mFallingObj[x].stillFalling)// && mBox.isContained(mFallingObj[x].curPos))
|
||||
{
|
||||
coordX = mTexCoord[mFallingObj[x].texIndex].x;
|
||||
coordY = mTexCoord[mFallingObj[x].texIndex].y;
|
||||
|
||||
point[1] = mFallingObj[x].curPos + mRotX - mRotZ;
|
||||
point[2] = mFallingObj[x].curPos - mRotX - mRotZ;
|
||||
if( mDataBlock->mType == 1 )
|
||||
{
|
||||
point[0] = mFallingObj[x].curPos + mRotX + mRotZ;
|
||||
point[3] = mFallingObj[x].curPos - mRotX + mRotZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
point[0].set(point[1].x + (mFallingObj[x].offset.x * mDataBlock->mSizeY * 2), point[1].y + (mFallingObj[x].offset.y * mDataBlock->mSizeY * 2), point[1].z + (mFallingObj[x].offset.z * mDataBlock->mSizeY * 2));
|
||||
point[3].set(point[2].x + (mFallingObj[x].offset.x * mDataBlock->mSizeY * 2), point[2].y + (mFallingObj[x].offset.y * mDataBlock->mSizeY * 2), point[2].z + (mFallingObj[x].offset.z * mDataBlock->mSizeY * 2));
|
||||
}
|
||||
|
||||
if(mFallingObj[x].dropType == 1)
|
||||
{
|
||||
F32 alphaVal = 1.0f - ((mFallingObj[x].curPos.z - camPos.z) / mFallingObj[x].startDiff);
|
||||
glColor4f(mColor[mFallingObj[x].colorIndex].red,
|
||||
mColor[mFallingObj[x].colorIndex].green,
|
||||
mColor[mFallingObj[x].colorIndex].blue,
|
||||
alphaVal);
|
||||
}
|
||||
else
|
||||
glColor4f(mColor[mFallingObj[x].colorIndex].red,
|
||||
mColor[mFallingObj[x].colorIndex].green,
|
||||
mColor[mFallingObj[x].colorIndex].blue,
|
||||
1.0f);
|
||||
|
||||
glTexCoord2f(coordX, coordY);
|
||||
glVertex3f(point[0].x, point[0].y, point[0].z);
|
||||
glTexCoord2f(coordX, coordY + 0.25);
|
||||
glVertex3f(point[1].x, point[1].y, point[1].z);
|
||||
glTexCoord2f(coordX + 0.25, coordY + 0.25);
|
||||
glVertex3f(point[2].x, point[2].y, point[2].z);
|
||||
glTexCoord2f(coordX + 0.25, coordY);
|
||||
glVertex3f(point[3].x, point[3].y, point[3].z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
mLastRenderTime = mCurrentTime;
|
||||
mRandomHeight = false;
|
||||
}
|
||||
|
||||
void Precipitation::renderSand()
|
||||
{
|
||||
Point3F objPos;
|
||||
F32 dt, modVal;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
for(S32 x=0; x < mNumDrops; ++x)
|
||||
{
|
||||
if(mStormData.numDrops > x || mFallingObj[x].stillFalling)
|
||||
{
|
||||
mFallingObj[x].offset.x += mOffset.x;
|
||||
mFallingObj[x].offset.y += mOffset.y;
|
||||
if(mFallingObj[x].endTime < mCurrentTime)
|
||||
{
|
||||
if(mStormData.numDrops > x)
|
||||
{
|
||||
modVal = mFmod(mCurrentTime - mFallingObj[x].endTime, mFallingObj[x].endTime - mFallingObj[x].startTime);
|
||||
mFallingObj[x].startTime = mCurrentTime - modVal;
|
||||
mFallingObj[x].endTime = (mCurrentTime + ((mMinVelocity * Platform::getRandom())+mMaxVelocity)) - modVal;
|
||||
mFallingObj[x].size = (mDataBlock->mMaxSize * Platform::getRandom());
|
||||
mFallingObj[x].offset.set(0.0, 0.0, 0.0);
|
||||
mFallingObj[x].colorIndex = (S32)(mCeil(mColorCount * Platform::getRandom()) - 1.0f);
|
||||
mFallingObj[x].stillFalling = true;
|
||||
}
|
||||
else
|
||||
mFallingObj[x].stillFalling = false;
|
||||
}
|
||||
dt = (mFallingObj[x].endTime - mCurrentTime) /
|
||||
(mFallingObj[x].endTime - mFallingObj[x].startTime);
|
||||
|
||||
glPointSize(mFallingObj[x].size);
|
||||
glColor4f(mColor[mFallingObj[x].colorIndex].red, mColor[mFallingObj[x].colorIndex].green, mColor[mFallingObj[x].colorIndex].blue, 1.0f - dt);
|
||||
objPos = Point3F((mFallingObj[x].startPos.x * mRadius)+mFallingObj[x].offset.x,
|
||||
(mFallingObj[x].startPos.y * mRadius)+mFallingObj[x].offset.y,
|
||||
(mFallingObj[x].startPos.z * (dt * mRadius)) - mRadius);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3f(objPos.x, objPos.y, objPos.z);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void Precipitation::calcVelocityBox(Point3F camPos, F32 &curZVelocity, F32 &renderPer)
|
||||
{
|
||||
GameConnection * con = GameConnection::getServerConnection();
|
||||
if(!con)
|
||||
return;
|
||||
|
||||
Sky* pSky = mSceneManager->getCurrentSky();
|
||||
mOffset.set(0.0f, 0.0f, 1.0f);
|
||||
if (pSky)
|
||||
if(pSky->mEffectPrecip)
|
||||
mOffset.set(pSky->mWindDir.x * mOffsetSpeed, pSky->mWindDir.y * mOffsetSpeed, 1.0f);
|
||||
|
||||
F32 radZ, speed;
|
||||
F32 randomVal, bottomHeight;
|
||||
Player *player = NULL;
|
||||
|
||||
mNewCenter.set(mOffset.x * mRadius, mOffset.y * mRadius, 0.0f);
|
||||
mShiftPrecip.set(0.0f, 0.0f, 0.0f);
|
||||
if((camPos - mLastPos).len() > mRadius / 2.0f)
|
||||
mShiftPrecip = camPos - mLastPos;
|
||||
|
||||
mLastPos = camPos;
|
||||
bottomHeight = (camPos.z - (mRadius / mDataBlock->tDivHeightVal));
|
||||
|
||||
ShapeBase * conObj = con->getControlObject();
|
||||
if(conObj->getWaterCoverage())
|
||||
bottomHeight = conObj->getLiquidHeight() + mDataBlock->mSizeY;
|
||||
|
||||
player = dynamic_cast<Player*>(conObj);
|
||||
if(!player)
|
||||
{
|
||||
mBox.min.set(camPos.x - mRadius, camPos.y - mRadius, bottomHeight);
|
||||
mBox.max.set(camPos.x + mRadius, camPos.y + mRadius, camPos.z + (mRadius / mDataBlock->tDivHeightVal));
|
||||
return;
|
||||
}
|
||||
Point3F curVel(player->getVelocity());
|
||||
F32 percentage = 0.0f;
|
||||
F32 movePer = mDataBlock->tMoveingBoxPer;
|
||||
|
||||
//Calc the offset of the inner box along x and y
|
||||
if(curVel.x)
|
||||
{
|
||||
percentage = curVel.x / 40.0f;
|
||||
mOffsetVal.x = (curVel.x > 0.0f) ?
|
||||
(percentage > movePer) ? movePer : percentage :
|
||||
(percentage < -movePer) ? -movePer : percentage;
|
||||
}
|
||||
if(curVel.y)
|
||||
{
|
||||
percentage = curVel.y / 40.0f;
|
||||
mOffsetVal.y = (curVel.y > 0.0f) ?
|
||||
(percentage > movePer) ? movePer : percentage :
|
||||
(percentage < -movePer) ? -movePer : percentage;
|
||||
}
|
||||
|
||||
curZVelocity = curVel.z;
|
||||
speed = Point2F(curVel.x, curVel.y).len();
|
||||
radZ = mRadius;
|
||||
if(speed > 1.0f)
|
||||
{
|
||||
F32 val = 40.0f / speed;
|
||||
radZ *= (val > 1.0f) ? 1.0f : (val < MIN_ZRADIUS) ? MIN_ZRADIUS : val;
|
||||
}
|
||||
//Move the box up slow... Helps keep snow around the player...
|
||||
F32 topHeight = (radZ / mDataBlock->tDivHeightVal);
|
||||
if(topHeight > mLastHeight && (topHeight - mLastHeight) > 5.0f)
|
||||
topHeight += 5.0f;
|
||||
mLastHeight = topHeight;
|
||||
|
||||
if(mDataBlock->tSizeBigBox)
|
||||
{
|
||||
mBox.min.set(camPos.x - (mRadius - (mRadius * mOffsetVal.x)),
|
||||
camPos.y - (mRadius - (mRadius * mOffsetVal.y)), bottomHeight);
|
||||
mBox.max.set(camPos.x + (mRadius + (mRadius * mOffsetVal.x)),
|
||||
camPos.y + (mRadius + (mRadius * mOffsetVal.y)), camPos.z + topHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
mBox.min.set(camPos.x - mRadius, camPos.y - mRadius, camPos.z - (mRadius / mDataBlock->tDivHeightVal));
|
||||
mBox.max.set(camPos.x + mRadius, camPos.y + mRadius, camPos.z + (mRadius / mDataBlock->tDivHeightVal));
|
||||
}
|
||||
|
||||
speed = Point3F(curVel.x, curVel.y, curVel.z).len();
|
||||
randomVal = Platform::getRandom();
|
||||
if(speed < mDataBlock->tTopBoxSpeed)
|
||||
renderPer = 1.0f;
|
||||
else if ( speed < mDataBlock->tFrontBoxSpeed )
|
||||
{
|
||||
if(randomVal < 0.25)
|
||||
renderPer = 1.0f;
|
||||
else
|
||||
renderPer = (curVel.z / speed) + (1.0f - ((speed - mDataBlock->tTopBoxSpeed)/ (mDataBlock->tFrontBoxSpeed - mDataBlock->tTopBoxSpeed)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(randomVal < 0.25)
|
||||
renderPer = 1.0f;
|
||||
else
|
||||
renderPer = curVel.z / speed;
|
||||
}
|
||||
|
||||
if(speed)
|
||||
curVel.normalize();
|
||||
else
|
||||
curVel.set(0.0f, 0.0f, 0.0f);
|
||||
|
||||
mNewCenter.set(curVel.x * mAbs(mOffsetVal.x * mRadius), curVel.y * mAbs(mOffsetVal.y * mRadius), curVel.z * mRadius);
|
||||
|
||||
if(mAverageSpeed && mOffset.z && (mOffset.x || mOffset.y))
|
||||
mNewCenter.set(mNewCenter.x + ((mRadius / (mAverageSpeed * mOffset.z)) * mOffset.x),
|
||||
mNewCenter.y + ((mRadius / (mAverageSpeed * mOffset.z)) * mOffset.y),
|
||||
0.0f);
|
||||
}
|
||||
|
||||
void Precipitation::setPercentage(F32 newPer)
|
||||
{
|
||||
if(newPer <= 1.0f && newPer >= 0.0f)
|
||||
{
|
||||
mPercentage = newPer;
|
||||
mNumDrops = mMaxDrops * mPercentage;
|
||||
setMaskBits(PercentageMask);
|
||||
}
|
||||
}
|
||||
|
||||
void Precipitation::stormShow(bool show)
|
||||
{
|
||||
mStormPrecipitationOn = show;
|
||||
setMaskBits(StormShowMask);
|
||||
}
|
||||
|
||||
void Precipitation::setupStorm(F32 percentage, F32 time)
|
||||
{
|
||||
mStormData.time = time;
|
||||
if(mStormData.endPercentage >= 0.0f)
|
||||
{
|
||||
mStormData.state = (mStormData.endPercentage > percentage) ? out : in;
|
||||
mPercentage = mStormData.endPercentage;
|
||||
}
|
||||
else
|
||||
mStormData.state = (mPercentage > percentage) ? out : in;
|
||||
mStormData.endPercentage = percentage;
|
||||
|
||||
setMaskBits(StormMask);
|
||||
}
|
||||
|
||||
void Precipitation::startStorm()
|
||||
{
|
||||
F32 percentage = mStormData.endPercentage;
|
||||
|
||||
mStormData.speed = (percentage - mPercentage) / (mStormData.time * 32.0f);
|
||||
mStormData.endPercentage = percentage;
|
||||
mStormData.state = (mPercentage > percentage) ? out : in;
|
||||
mStormPrecipitationOn = true;
|
||||
}
|
||||
|
||||
void Precipitation::updateStorm()
|
||||
{
|
||||
F32 offset = 1.0f;
|
||||
U32 currentTime = Sim::getCurrentTime();
|
||||
if(mStormData.lastTime != 0)
|
||||
offset = (currentTime - mStormData.lastTime) / 32.0f;
|
||||
|
||||
mStormData.lastTime = currentTime;
|
||||
|
||||
mPercentage += (mStormData.speed * offset);
|
||||
if((mStormData.state == in && mPercentage >= mStormData.endPercentage) ||
|
||||
(mStormData.state == out && mPercentage <= mStormData.endPercentage))
|
||||
{
|
||||
mPercentage = mStormData.endPercentage;
|
||||
mStormData.state = done;
|
||||
mStormData.lastTime = 0.0f;
|
||||
}
|
||||
mStormData.numDrops = mMaxDrops * mPercentage;
|
||||
}
|
||||
|
||||
void Precipitation::processTick(const Move* move)
|
||||
{
|
||||
Parent::processTick(move);
|
||||
mStormData.currentTime++;
|
||||
}
|
||||
|
||||
void Precipitation::setupTexCoords()
|
||||
{
|
||||
S32 x, y, numTimes = NUM_TEXTURES / 4;
|
||||
|
||||
for(y = 0; y < numTimes ; ++y)
|
||||
for(x = 0; x < numTimes ; ++x)
|
||||
mTexCoord[y * numTimes + x].set(x * 0.25f, y * 0.25f);
|
||||
}
|
||||
|
||||
F32 Precipitation::getRandomVal()
|
||||
{
|
||||
F32 randVal = Platform::getRandom();
|
||||
if(randVal > 0.99995f && randVal < 0.99999f)
|
||||
randVal = 1.01f;
|
||||
return randVal;
|
||||
}
|
||||
193
game/fx/precipitation.h
Normal file
193
game/fx/precipitation.h
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _H_precipitation
|
||||
#define _H_precipitation
|
||||
|
||||
#ifndef _GAMEBASE_H_
|
||||
#include "game/gameBase.h"
|
||||
#endif
|
||||
#ifndef _TSSHAPE_H_
|
||||
#include "ts/tsShape.h"
|
||||
#endif
|
||||
#ifndef _AUDIODATABLOCK_H_
|
||||
#include "audio/audioDataBlock.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define MAX_NUM_DROPS 2000
|
||||
#define MAX_NUM_COLOR 3
|
||||
#define NUM_TEXTURES 16
|
||||
#define MIN_ZRADIUS 0.01f
|
||||
|
||||
class AudioProfile;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
class PrecipitationData : public GameBaseData {
|
||||
typedef GameBaseData Parent;
|
||||
|
||||
public:
|
||||
AudioProfile* soundProfile;
|
||||
S32 soundProfileId;
|
||||
S32 mType;
|
||||
F32 mMaxSize;
|
||||
F32 mSizeX;
|
||||
F32 mSizeY;
|
||||
StringTableEntry mMaterialListName;
|
||||
|
||||
/////////////////////////
|
||||
//JohnA Will remove
|
||||
// Used to tweak the precipitation
|
||||
/////////////////////////
|
||||
F32 tMoveingBoxPer;
|
||||
F32 tDivHeightVal;
|
||||
F32 tSizeBigBox;
|
||||
F32 tTopBoxSpeed;
|
||||
F32 tFrontBoxSpeed;
|
||||
F32 tTopBoxDrawPer;
|
||||
F32 tBottomDrawHeight;
|
||||
F32 tSkipIfPer;
|
||||
F32 tBottomSpeedPer;
|
||||
F32 tFrontSpeedPer;
|
||||
F32 tFrontRadiusPer;
|
||||
/////////////////////////
|
||||
|
||||
PrecipitationData();
|
||||
DECLARE_CONOBJECT(PrecipitationData);
|
||||
bool onAdd();
|
||||
static void initPersistFields();
|
||||
virtual void packData(BitStream* stream);
|
||||
virtual void unpackData(BitStream* stream);
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
F32 speed;
|
||||
Point3F curPos;
|
||||
F32 startTime;
|
||||
F32 endTime;
|
||||
Point3F startPos;
|
||||
Point3F sPosOffset;
|
||||
F32 size;
|
||||
Point3F offset;
|
||||
S32 colorIndex;
|
||||
S32 texIndex;
|
||||
ColorF colorOffset;
|
||||
F32 rotation;
|
||||
bool stillFalling;
|
||||
F32 startDiff;
|
||||
S32 dropType;
|
||||
bool notValid;
|
||||
}FallingInfo;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
enum State
|
||||
{
|
||||
done = 0,
|
||||
in = 1,
|
||||
out = 2
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
F32 lastTime;
|
||||
F32 endPercentage;
|
||||
F32 time;
|
||||
F32 speed;
|
||||
S32 numDrops;
|
||||
State state;
|
||||
F32 currentTime;
|
||||
}PrecipStormData;
|
||||
|
||||
class Precipitation : public GameBase
|
||||
{
|
||||
private:
|
||||
typedef GameBase Parent;
|
||||
PrecipitationData* mDataBlock;
|
||||
|
||||
FallingInfo mFallingObj[MAX_NUM_DROPS];
|
||||
Point2F mTexCoord[NUM_TEXTURES];
|
||||
F32 mCurrentTime;
|
||||
F32 mLastRenderTime;
|
||||
Point3F mRotX, mRotZ;
|
||||
Point2F mOffsetVal;
|
||||
Point3F mNewCenter;
|
||||
Point3F mLastPos;
|
||||
bool mRandomHeight;
|
||||
TextureHandle mTextures[20];
|
||||
MaterialList mMaterialList;
|
||||
S32 mNumTextures;
|
||||
bool mFirstTime;
|
||||
AUDIOHANDLE mAudioHandle;
|
||||
F32 mPercentage;
|
||||
S32 mNumDrops;
|
||||
PrecipStormData mStormData;
|
||||
bool mStormPrecipitationOn;
|
||||
Box3F mBox;
|
||||
F32 mAverageSpeed;
|
||||
F32 mLastHeight;
|
||||
Point3F mOffset;
|
||||
Point3F mShiftPrecip;
|
||||
S32 mColorCount;
|
||||
ColorF mColor[MAX_NUM_COLOR];
|
||||
F32 mMinVelocity;
|
||||
F32 mMaxVelocity;
|
||||
S32 mMaxDrops;
|
||||
S32 mRadius;
|
||||
F32 mOffsetSpeed;
|
||||
|
||||
void processTick(const Move*);
|
||||
protected:
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
|
||||
void advanceTime(F32 dt);
|
||||
|
||||
// Rendering
|
||||
bool prepRenderImage(SceneState*, const U32, const U32, const bool);
|
||||
void renderObject(SceneState*, SceneRenderImage*);
|
||||
void renderPrecip(Point3F camPos);
|
||||
void renderSand();
|
||||
void calcVelocityBox(Point3F camPos, F32 &curZVelocity, F32 &renderPer);
|
||||
void loadDml();
|
||||
void setupTexCoords();
|
||||
F32 getRandomVal();
|
||||
public:
|
||||
enum NetMaskBits {
|
||||
InitMask = BIT(0),
|
||||
PercentageMask = BIT(1),
|
||||
StormMask = BIT(2),
|
||||
StormShowMask = BIT(3)
|
||||
};
|
||||
|
||||
Precipitation();
|
||||
~Precipitation();
|
||||
void inspectPostApply();
|
||||
void setInitialState(const Point3F& point, const Point3F& normal, const F32 fade = 1.0);
|
||||
void setPercentage(F32);
|
||||
|
||||
bool onNewDataBlock(GameBaseData* dptr);
|
||||
DECLARE_CONOBJECT(Precipitation);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
static bool smPrecipitationOn;
|
||||
static bool smPrecipitationPause;
|
||||
|
||||
void setDefaultValues();
|
||||
void stormShow(bool show);
|
||||
void setupStorm(F32 percentage, F32 time);
|
||||
void startStorm();
|
||||
void updateStorm();
|
||||
|
||||
U32 packUpdate(NetConnection*, U32 mask, BitStream* stream);
|
||||
void unpackUpdate(NetConnection*, BitStream* stream);
|
||||
};
|
||||
|
||||
#endif // _H_precipitation
|
||||
|
||||
834
game/fx/splash.cc
Normal file
834
game/fx/splash.cc
Normal file
|
|
@ -0,0 +1,834 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "game/fx/splash.h"
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "platform/platformAudio.h"
|
||||
#include "audio/audioDataBlock.h"
|
||||
#include "sceneGraph/sceneGraph.h"
|
||||
#include "sceneGraph/sceneState.h"
|
||||
#include "core/bitStream.h"
|
||||
#include "math/mathIO.h"
|
||||
#include "terrain/terrData.h"
|
||||
#include "game/fx/explosion.h"
|
||||
#include "game/fx/particleEngine.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
MRandomLCG sgRandom(0xdeadbeef);
|
||||
|
||||
} // namespace {}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//--------------------------------------
|
||||
//
|
||||
IMPLEMENT_CO_DATABLOCK_V1(SplashData);
|
||||
IMPLEMENT_CO_NETOBJECT_V1(Splash);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Splash Data
|
||||
//--------------------------------------------------------------------------
|
||||
SplashData::SplashData()
|
||||
{
|
||||
soundProfile = NULL;
|
||||
soundProfileId = 0;
|
||||
|
||||
scale.set(1, 1, 1);
|
||||
|
||||
dMemset( emitterList, 0, sizeof( emitterList ) );
|
||||
dMemset( emitterIDList, 0, sizeof( emitterIDList ) );
|
||||
|
||||
delayMS = 0;
|
||||
delayVariance = 0;
|
||||
lifetimeMS = 1000;
|
||||
lifetimeVariance = 0;
|
||||
width = 4.0;
|
||||
numSegments = 10;
|
||||
velocity = 5.0;
|
||||
height = 0.0;
|
||||
acceleration = 0.0;
|
||||
texWrap = 1.0;
|
||||
texFactor = 3.0;
|
||||
ejectionFreq = 5;
|
||||
ejectionAngle = 45.0;
|
||||
ringLifetime = 1.0;
|
||||
startRadius = 0.5;
|
||||
explosion = NULL;
|
||||
explosionId = 0;
|
||||
|
||||
dMemset( textureName, 0, sizeof( textureName ) );
|
||||
|
||||
U32 i;
|
||||
for( i=0; i<NUM_TIME_KEYS; i++ )
|
||||
{
|
||||
times[i] = 1.0;
|
||||
}
|
||||
times[0] = 0.0;
|
||||
|
||||
for( i=0; i<NUM_TIME_KEYS; i++ )
|
||||
{
|
||||
colors[i].set( 1.0, 1.0, 1.0, 1.0 );
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_SETDATATYPE(SplashData)
|
||||
IMPLEMENT_GETDATATYPE(SplashData)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Init fields
|
||||
//--------------------------------------------------------------------------
|
||||
void SplashData::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
Con::registerType("SplashDataPtr", TypeSplashDataPtr, sizeof(SplashData*),
|
||||
REF_GETDATATYPE(SplashData),
|
||||
REF_SETDATATYPE(SplashData));
|
||||
|
||||
|
||||
addField("soundProfile", TypeAudioProfilePtr, Offset(soundProfile, SplashData));
|
||||
addField("scale", TypePoint3F, Offset(scale, SplashData));
|
||||
addField("emitter", TypeParticleEmitterDataPtr, Offset(emitterList, SplashData), NUM_EMITTERS);
|
||||
addField("delayMS", TypeS32, Offset(delayMS, SplashData));
|
||||
addField("delayVariance", TypeS32, Offset(delayVariance, SplashData));
|
||||
addField("lifetimeMS", TypeS32, Offset(lifetimeMS, SplashData));
|
||||
addField("lifetimeVariance", TypeS32, Offset(lifetimeVariance, SplashData));
|
||||
addField("width", TypeF32, Offset(width, SplashData));
|
||||
addField("numSegments", TypeS32, Offset(numSegments, SplashData));
|
||||
addField("velocity", TypeF32, Offset(velocity, SplashData));
|
||||
addField("height", TypeF32, Offset(height, SplashData));
|
||||
addField("acceleration", TypeF32, Offset(acceleration, SplashData));
|
||||
addField("times", TypeF32, Offset(times, SplashData), NUM_TIME_KEYS);
|
||||
addField("colors", TypeColorF, Offset(colors, SplashData), NUM_TIME_KEYS);
|
||||
addField("texture", TypeString, Offset(textureName, SplashData), NUM_TEX);
|
||||
addField("texWrap", TypeF32, Offset(texWrap, SplashData));
|
||||
addField("texFactor", TypeF32, Offset(texFactor, SplashData));
|
||||
addField("ejectionFreq", TypeF32, Offset(ejectionFreq, SplashData));
|
||||
addField("ejectionAngle", TypeF32, Offset(ejectionAngle, SplashData));
|
||||
addField("ringLifetime", TypeF32, Offset(ringLifetime, SplashData));
|
||||
addField("startRadius", TypeF32, Offset(startRadius, SplashData));
|
||||
addField("explosion", TypeExplosionDataPtr, Offset(explosion, SplashData));
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// On add - verify data settings
|
||||
//--------------------------------------------------------------------------
|
||||
bool SplashData::onAdd()
|
||||
{
|
||||
if (Parent::onAdd() == false)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Pack data
|
||||
//--------------------------------------------------------------------------
|
||||
void SplashData::packData(BitStream* stream)
|
||||
{
|
||||
Parent::packData(stream);
|
||||
|
||||
mathWrite(*stream, scale);
|
||||
stream->write(delayMS);
|
||||
stream->write(delayVariance);
|
||||
stream->write(lifetimeMS);
|
||||
stream->write(lifetimeVariance);
|
||||
stream->write(width);
|
||||
stream->write(numSegments);
|
||||
stream->write(velocity);
|
||||
stream->write(height);
|
||||
stream->write(acceleration);
|
||||
stream->write(texWrap);
|
||||
stream->write(texFactor);
|
||||
stream->write(ejectionFreq);
|
||||
stream->write(ejectionAngle);
|
||||
stream->write(ringLifetime);
|
||||
stream->write(startRadius);
|
||||
|
||||
if( stream->writeFlag( explosion ) )
|
||||
{
|
||||
stream->writeRangedU32(explosion->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast);
|
||||
}
|
||||
|
||||
S32 i;
|
||||
for( i=0; i<NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( stream->writeFlag( emitterList[i] != NULL ) )
|
||||
{
|
||||
stream->writeRangedU32( emitterList[i]->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast );
|
||||
}
|
||||
}
|
||||
|
||||
for( i=0; i<NUM_TIME_KEYS; i++ )
|
||||
{
|
||||
stream->write( colors[i] );
|
||||
}
|
||||
|
||||
for( i=0; i<NUM_TIME_KEYS; i++ )
|
||||
{
|
||||
stream->write( times[i] );
|
||||
}
|
||||
|
||||
for( i=0; i<NUM_TEX; i++ )
|
||||
{
|
||||
stream->writeString(textureName[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Unpack data
|
||||
//--------------------------------------------------------------------------
|
||||
void SplashData::unpackData(BitStream* stream)
|
||||
{
|
||||
Parent::unpackData(stream);
|
||||
|
||||
mathRead(*stream, &scale);
|
||||
stream->read(&delayMS);
|
||||
stream->read(&delayVariance);
|
||||
stream->read(&lifetimeMS);
|
||||
stream->read(&lifetimeVariance);
|
||||
stream->read(&width);
|
||||
stream->read(&numSegments);
|
||||
stream->read(&velocity);
|
||||
stream->read(&height);
|
||||
stream->read(&acceleration);
|
||||
stream->read(&texWrap);
|
||||
stream->read(&texFactor);
|
||||
stream->read(&ejectionFreq);
|
||||
stream->read(&ejectionAngle);
|
||||
stream->read(&ringLifetime);
|
||||
stream->read(&startRadius);
|
||||
|
||||
if( stream->readFlag() )
|
||||
{
|
||||
explosionId = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
|
||||
}
|
||||
|
||||
U32 i;
|
||||
for( i=0; i<NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( stream->readFlag() )
|
||||
{
|
||||
emitterIDList[i] = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
|
||||
}
|
||||
}
|
||||
|
||||
for( i=0; i<NUM_TIME_KEYS; i++ )
|
||||
{
|
||||
stream->read( &colors[i] );
|
||||
}
|
||||
|
||||
for( i=0; i<NUM_TIME_KEYS; i++ )
|
||||
{
|
||||
stream->read( ×[i] );
|
||||
}
|
||||
|
||||
for( i=0; i<NUM_TEX; i++ )
|
||||
{
|
||||
textureName[i] = stream->readSTString();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Preload data - load resources
|
||||
//--------------------------------------------------------------------------
|
||||
bool SplashData::preload(bool server, char errorBuffer[256])
|
||||
{
|
||||
if (Parent::preload(server, errorBuffer) == false)
|
||||
return false;
|
||||
|
||||
if (!server) {
|
||||
S32 i;
|
||||
for( i=0; i<NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( !emitterList[i] && emitterIDList[i] != 0 )
|
||||
{
|
||||
if( Sim::findObject( emitterIDList[i], emitterList[i] ) == false)
|
||||
{
|
||||
Con::errorf( ConsoleLogEntry::General, "SplashData::onAdd: Invalid packet, bad datablockId(particle emitter): 0x%x", emitterIDList[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( i=0; i<NUM_TEX; i++ )
|
||||
{
|
||||
if (textureName[i] && textureName[i][0])
|
||||
{
|
||||
textureHandle[i] = TextureHandle(textureName[i], MeshTexture );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !explosion && explosionId != 0 )
|
||||
{
|
||||
if( !Sim::findObject(explosionId, explosion) )
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::General, "SplashData::preload: Invalid packet, bad datablockId(explosion): %d", explosionId);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Splash
|
||||
//--------------------------------------------------------------------------
|
||||
Splash::Splash()
|
||||
{
|
||||
dMemset( mEmitterList, 0, sizeof( mEmitterList ) );
|
||||
|
||||
mDelayMS = 0;
|
||||
mCurrMS = 0;
|
||||
mEndingMS = 1000;
|
||||
mActive = false;
|
||||
mRadius = 0.0;
|
||||
mVelocity = 1.0;
|
||||
mHeight = 0.0;
|
||||
mTimeSinceLastRing = 0.0;
|
||||
mDead = false;
|
||||
mElapsedTime = 0.0;
|
||||
|
||||
mInitialNormal.set( 0.0, 0.0, 1.0 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Destructor
|
||||
//--------------------------------------------------------------------------
|
||||
Splash::~Splash()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Set initial state
|
||||
//--------------------------------------------------------------------------
|
||||
void Splash::setInitialState(const Point3F& point, const Point3F& normal, const F32 fade)
|
||||
{
|
||||
mInitialPosition = point;
|
||||
mInitialNormal = normal;
|
||||
mFade = fade;
|
||||
mFog = 0.0f;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Init persist fields
|
||||
//--------------------------------------------------------------------------
|
||||
void Splash::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnAdd
|
||||
//--------------------------------------------------------------------------
|
||||
bool Splash::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
mDelayMS = mDataBlock->delayMS + sgRandom.randI( -mDataBlock->delayVariance, mDataBlock->delayVariance );
|
||||
mEndingMS = mDataBlock->lifetimeMS + sgRandom.randI( -mDataBlock->lifetimeVariance, mDataBlock->lifetimeVariance );
|
||||
|
||||
mVelocity = mDataBlock->velocity;
|
||||
mHeight = mDataBlock->height;
|
||||
mTimeSinceLastRing = 1.0 / mDataBlock->ejectionFreq;
|
||||
|
||||
|
||||
if( isClientObject() )
|
||||
{
|
||||
for( U32 i=0; i<SplashData::NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( mDataBlock->emitterList[i] != NULL )
|
||||
{
|
||||
ParticleEmitter * pEmitter = new ParticleEmitter;
|
||||
pEmitter->onNewDataBlock( mDataBlock->emitterList[i] );
|
||||
if( !pEmitter->registerObject() )
|
||||
{
|
||||
Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() );
|
||||
delete pEmitter;
|
||||
pEmitter = NULL;
|
||||
}
|
||||
mEmitterList[i] = pEmitter;
|
||||
}
|
||||
}
|
||||
|
||||
spawnExplosion();
|
||||
}
|
||||
|
||||
|
||||
mObjBox.min = Point3F( -1, -1, -1 );
|
||||
mObjBox.max = Point3F( 1, 1, 1 );
|
||||
resetWorldBox();
|
||||
|
||||
gClientContainer.addObject(this);
|
||||
gClientSceneGraph->addObjectToScene(this);
|
||||
|
||||
removeFromProcessList();
|
||||
gClientProcessList.addObject(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// OnRemove
|
||||
//--------------------------------------------------------------------------
|
||||
void Splash::onRemove()
|
||||
{
|
||||
for( U32 i=0; i<SplashData::NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( mEmitterList[i] )
|
||||
{
|
||||
mEmitterList[i]->deleteWhenEmpty();
|
||||
mEmitterList[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ringList.free();
|
||||
|
||||
mSceneManager->removeObjectFromScene(this);
|
||||
getContainer()->removeObject(this);
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// On New Data Block
|
||||
//--------------------------------------------------------------------------
|
||||
bool Splash::onNewDataBlock(GameBaseData* dptr)
|
||||
{
|
||||
mDataBlock = dynamic_cast<SplashData*>(dptr);
|
||||
if (!mDataBlock || !Parent::onNewDataBlock(dptr))
|
||||
return false;
|
||||
|
||||
scriptOnNewDataBlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Prep render image
|
||||
//--------------------------------------------------------------------------
|
||||
bool Splash::prepRenderImage(SceneState* state, const U32 stateKey,
|
||||
const U32 /*startZone*/, const bool /*modifyBaseState*/)
|
||||
{
|
||||
if (isLastState(state, stateKey))
|
||||
return false;
|
||||
setLastState(state, stateKey);
|
||||
|
||||
// This should be sufficient for most objects that don't manage zones, and
|
||||
// don't need to return a specialized RenderImage...
|
||||
if (state->isObjectRendered(this)) {
|
||||
mFog = 0.0;
|
||||
|
||||
SceneRenderImage* image = new SceneRenderImage;
|
||||
image->obj = this;
|
||||
image->isTranslucent = true;
|
||||
image->sortType = SceneRenderImage::Point;
|
||||
image->textureSortKey = U32(mDataBlock);
|
||||
state->setImageRefPoint(this, image);
|
||||
state->insertRenderImage(image);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Render
|
||||
//--------------------------------------------------------------------------
|
||||
void Splash::renderObject(SceneState* state, SceneRenderImage*)
|
||||
{
|
||||
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");
|
||||
|
||||
RectI viewport;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
dglGetViewport(&viewport);
|
||||
|
||||
state->setupObjectProjection(this);
|
||||
|
||||
render();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
dglSetViewport(viewport);
|
||||
|
||||
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Process tick
|
||||
//--------------------------------------------------------------------------
|
||||
void Splash::processTick(const Move*)
|
||||
{
|
||||
mCurrMS += TickMs;
|
||||
|
||||
if( isServerObject() )
|
||||
{
|
||||
if( mCurrMS >= mEndingMS )
|
||||
{
|
||||
mDead = true;
|
||||
if( mCurrMS >= (mEndingMS + mDataBlock->ringLifetime * 1000) )
|
||||
{
|
||||
deleteObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mCurrMS >= mEndingMS )
|
||||
{
|
||||
mDead = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Advance time
|
||||
//--------------------------------------------------------------------------
|
||||
void Splash::advanceTime(F32 dt)
|
||||
{
|
||||
if (dt == 0.0)
|
||||
return;
|
||||
|
||||
mElapsedTime += dt;
|
||||
|
||||
updateColor();
|
||||
updateWave( dt );
|
||||
updateEmitters( dt );
|
||||
updateRings( dt );
|
||||
|
||||
if( !mDead )
|
||||
{
|
||||
emitRings( dt );
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Update emitters
|
||||
//----------------------------------------------------------------------------
|
||||
void Splash::updateEmitters( F32 dt )
|
||||
{
|
||||
Point3F pos = getPosition();
|
||||
|
||||
for( U32 i=0; i<SplashData::NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( mEmitterList[i] )
|
||||
{
|
||||
mEmitterList[i]->emitParticles( pos, pos, mInitialNormal, Point3F( 0.0, 0.0, 0.0 ), dt * 1000 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Update wave
|
||||
//----------------------------------------------------------------------------
|
||||
void Splash::updateWave( F32 dt )
|
||||
{
|
||||
mVelocity += mDataBlock->acceleration * dt;
|
||||
mRadius += mVelocity * dt;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Render splash
|
||||
//----------------------------------------------------------------------------
|
||||
void Splash::render()
|
||||
{
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDepthMask(GL_FALSE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
|
||||
SplashRing *ring = NULL;
|
||||
|
||||
U32 i=0;
|
||||
while( bool( ring = ringList.next( ring ) ) )
|
||||
{
|
||||
SplashRing *next = ringList.next( ring );
|
||||
if( !next ) break;
|
||||
|
||||
renderSegment( *ring, *next );
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(GL_TRUE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Render horizontal segment created from 2 sets of points that are the
|
||||
// top and bottom rings of the segment.
|
||||
//----------------------------------------------------------------------------
|
||||
void Splash::renderSegment( SplashRing &top, SplashRing &bottom )
|
||||
{
|
||||
F32 texFactor = mDataBlock->texWrap;
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, mDataBlock->textureHandle[0].getGLName() );
|
||||
|
||||
|
||||
F32 topAlpha = top.elapsedTime / top.lifetime;
|
||||
F32 bottomAlpha = bottom.elapsedTime / bottom.lifetime;
|
||||
|
||||
if( topAlpha < 0.5 ) topAlpha *= 2.0;
|
||||
else topAlpha = 1.0 - topAlpha;
|
||||
|
||||
if( bottomAlpha < 0.5 ) bottomAlpha *= 2.0;
|
||||
else bottomAlpha = 1.0 - bottomAlpha;
|
||||
|
||||
top.color.alpha = topAlpha;
|
||||
bottom.color.alpha = bottomAlpha;
|
||||
|
||||
|
||||
glBegin( GL_QUAD_STRIP );
|
||||
{
|
||||
for( U32 i=0; i<top.points.size(); i++ )
|
||||
{
|
||||
F32 t = F32(i) / F32(top.points.size());
|
||||
|
||||
glTexCoord2f( t * texFactor, top.v );
|
||||
glColor4fv( top.color );
|
||||
glVertex3fv( top.points[i].position );
|
||||
|
||||
glTexCoord2f( t * texFactor, bottom.v );
|
||||
glColor4fv( bottom.color );
|
||||
glVertex3fv( bottom.points[i].position );
|
||||
}
|
||||
|
||||
glTexCoord2f( 1.0 * texFactor, top.v );
|
||||
glColor4fv( top.color );
|
||||
glVertex3fv( top.points[0].position );
|
||||
|
||||
glTexCoord2f( 1.0 * texFactor, bottom.v );
|
||||
glColor4fv( bottom.color );
|
||||
glVertex3fv( bottom.points[0].position );
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Update color
|
||||
//----------------------------------------------------------------------------
|
||||
void Splash::updateColor()
|
||||
{
|
||||
SplashRing *ring = NULL;
|
||||
|
||||
while( bool( ring = ringList.next( ring ) ) )
|
||||
{
|
||||
F32 t = F32(ring->elapsedTime) / F32(ring->lifetime);
|
||||
|
||||
for( U32 i = 1; i < SplashData::NUM_TIME_KEYS; i++ )
|
||||
{
|
||||
if( mDataBlock->times[i] >= t )
|
||||
{
|
||||
F32 firstPart = t - mDataBlock->times[i-1];
|
||||
F32 total = (mDataBlock->times[i] -
|
||||
mDataBlock->times[i-1]);
|
||||
|
||||
firstPart /= total;
|
||||
|
||||
ring->color.interpolate( mDataBlock->colors[i-1],
|
||||
mDataBlock->colors[i],
|
||||
firstPart);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Create ring
|
||||
//----------------------------------------------------------------------------
|
||||
SplashRing Splash::createRing()
|
||||
{
|
||||
|
||||
SplashRing ring;
|
||||
U32 numPoints = mDataBlock->numSegments + 1;
|
||||
|
||||
Point3F ejectionAxis( 0.0, 0.0, 1.0 );
|
||||
|
||||
Point3F axisx;
|
||||
if (mFabs(ejectionAxis.z) < 0.999f)
|
||||
mCross(ejectionAxis, Point3F(0, 0, 1), &axisx);
|
||||
else
|
||||
mCross(ejectionAxis, Point3F(0, 1, 0), &axisx);
|
||||
axisx.normalize();
|
||||
|
||||
|
||||
|
||||
for( U32 i=0; i<numPoints; i++ )
|
||||
{
|
||||
F32 t = F32(i) / F32(numPoints);
|
||||
|
||||
AngAxisF thetaRot( axisx, mDataBlock->ejectionAngle * (M_PI / 180.0));
|
||||
AngAxisF phiRot( ejectionAxis, t * (M_PI * 2.0));
|
||||
|
||||
Point3F pointAxis = ejectionAxis;
|
||||
|
||||
MatrixF temp;
|
||||
thetaRot.setMatrix(&temp);
|
||||
temp.mulP(pointAxis);
|
||||
phiRot.setMatrix(&temp);
|
||||
temp.mulP(pointAxis);
|
||||
|
||||
Point3F startOffset = axisx;
|
||||
temp.mulV( startOffset );
|
||||
startOffset *= mDataBlock->startRadius;
|
||||
|
||||
SplashRingPoint point;
|
||||
point.position = getPosition() + startOffset;
|
||||
point.velocity = pointAxis * mDataBlock->velocity;
|
||||
|
||||
ring.points.push_back( point );
|
||||
}
|
||||
|
||||
ring.color = mDataBlock->colors[0];
|
||||
ring.lifetime = mDataBlock->ringLifetime;
|
||||
ring.elapsedTime = 0.0;
|
||||
ring.v = mDataBlock->texFactor * mFmod( mElapsedTime, 1.0 );
|
||||
|
||||
return ring;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Emit rings
|
||||
//----------------------------------------------------------------------------
|
||||
void Splash::emitRings( F32 dt )
|
||||
{
|
||||
mTimeSinceLastRing += dt;
|
||||
|
||||
S32 numNewRings = mTimeSinceLastRing * F32(mDataBlock->ejectionFreq);
|
||||
|
||||
mTimeSinceLastRing -= numNewRings / mDataBlock->ejectionFreq;
|
||||
|
||||
|
||||
for( S32 i=numNewRings-1; i>=0; i-- )
|
||||
{
|
||||
F32 t = F32(i) / F32(numNewRings);
|
||||
t *= dt;
|
||||
t += mTimeSinceLastRing;
|
||||
|
||||
SplashRing ring = createRing();
|
||||
updateRing( &ring, t );
|
||||
|
||||
ringList.link( ring );
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Update rings
|
||||
//----------------------------------------------------------------------------
|
||||
void Splash::updateRings( F32 dt )
|
||||
{
|
||||
|
||||
SplashRing *ring = NULL;
|
||||
while( bool( ring = ringList.next( ring ) ) )
|
||||
{
|
||||
ring->elapsedTime += dt;
|
||||
|
||||
if( !ring->isActive() )
|
||||
{
|
||||
SplashRing *inactiveRing = ring;
|
||||
ring = ringList.prev( ring );
|
||||
ringList.free( inactiveRing );
|
||||
}
|
||||
else
|
||||
{
|
||||
updateRing( ring, dt );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Update ring
|
||||
//----------------------------------------------------------------------------
|
||||
void Splash::updateRing( SplashRing *ring, F32 dt )
|
||||
{
|
||||
|
||||
for( U32 i=0; i<ring->points.size(); i++ )
|
||||
{
|
||||
if( mDead )
|
||||
{
|
||||
Point3F vel = ring->points[i].velocity;
|
||||
vel.normalize();
|
||||
vel *= mDataBlock->acceleration;
|
||||
ring->points[i].velocity += vel * dt;
|
||||
}
|
||||
|
||||
ring->points[i].velocity += Point3F( 0.0, 0.0, -9.8 ) * dt;
|
||||
ring->points[i].position += ring->points[i].velocity * dt;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Explode
|
||||
//----------------------------------------------------------------------------
|
||||
void Splash::spawnExplosion()
|
||||
{
|
||||
if( !mDataBlock->explosion ) return;
|
||||
|
||||
Explosion* pExplosion = new Explosion;
|
||||
pExplosion->onNewDataBlock(mDataBlock->explosion);
|
||||
|
||||
MatrixF trans = getTransform();
|
||||
trans.setPosition( getPosition() );
|
||||
|
||||
pExplosion->setTransform( trans );
|
||||
pExplosion->setInitialState( trans.getPosition(), VectorF(0,0,1), 1);
|
||||
if (!pExplosion->registerObject())
|
||||
delete pExplosion;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// packUpdate
|
||||
//--------------------------------------------------------------------------
|
||||
U32 Splash::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
|
||||
{
|
||||
U32 retMask = Parent::packUpdate(con, mask, stream);
|
||||
|
||||
if( stream->writeFlag(mask & GameBase::InitialUpdateMask) )
|
||||
{
|
||||
mathWrite(*stream, mInitialPosition);
|
||||
}
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// unpackUpdate
|
||||
//--------------------------------------------------------------------------
|
||||
void Splash::unpackUpdate(NetConnection* con, BitStream* stream)
|
||||
{
|
||||
Parent::unpackUpdate(con, stream);
|
||||
|
||||
if( stream->readFlag() )
|
||||
{
|
||||
mathRead(*stream, &mInitialPosition);
|
||||
setPosition( mInitialPosition );
|
||||
}
|
||||
}
|
||||
185
game/fx/splash.h
Normal file
185
game/fx/splash.h
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _H_SPLASH
|
||||
#define _H_SPLASH
|
||||
|
||||
#ifndef _GAMEBASE_H_
|
||||
#include "game/gameBase.h"
|
||||
#endif
|
||||
#ifndef _LLIST_H_
|
||||
#include "core/llist.h"
|
||||
#endif
|
||||
|
||||
class ParticleEmitter;
|
||||
class ParticleEmitterData;
|
||||
class AudioProfile;
|
||||
class ExplosionData;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Ring Point
|
||||
//--------------------------------------------------------------------------
|
||||
struct SplashRingPoint
|
||||
{
|
||||
Point3F position;
|
||||
Point3F velocity;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Splash Ring
|
||||
//--------------------------------------------------------------------------
|
||||
struct SplashRing
|
||||
{
|
||||
Vector <SplashRingPoint> points;
|
||||
ColorF color;
|
||||
F32 lifetime;
|
||||
F32 elapsedTime;
|
||||
F32 v;
|
||||
|
||||
SplashRing()
|
||||
{
|
||||
color.set( 0.0, 0.0, 0.0, 1.0 );
|
||||
lifetime = 0.0;
|
||||
elapsedTime = 0.0;
|
||||
v = 0.0;
|
||||
}
|
||||
|
||||
bool isActive()
|
||||
{
|
||||
return elapsedTime < lifetime;
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Splash Data
|
||||
//--------------------------------------------------------------------------
|
||||
class SplashData : public GameBaseData {
|
||||
public:
|
||||
typedef GameBaseData Parent;
|
||||
|
||||
enum Constants
|
||||
{
|
||||
NUM_EMITTERS = 3,
|
||||
NUM_TIME_KEYS = 4,
|
||||
NUM_TEX = 2,
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
AudioProfile* soundProfile;
|
||||
S32 soundProfileId;
|
||||
|
||||
ParticleEmitterData* emitterList[NUM_EMITTERS];
|
||||
S32 emitterIDList[NUM_EMITTERS];
|
||||
|
||||
S32 delayMS;
|
||||
S32 delayVariance;
|
||||
S32 lifetimeMS;
|
||||
S32 lifetimeVariance;
|
||||
Point3F scale;
|
||||
F32 width;
|
||||
F32 height;
|
||||
U32 numSegments;
|
||||
F32 velocity;
|
||||
F32 acceleration;
|
||||
F32 texWrap;
|
||||
F32 texFactor;
|
||||
|
||||
F32 ejectionFreq;
|
||||
F32 ejectionAngle;
|
||||
F32 ringLifetime;
|
||||
F32 startRadius;
|
||||
|
||||
F32 times[ NUM_TIME_KEYS ];
|
||||
ColorF colors[ NUM_TIME_KEYS ];
|
||||
|
||||
StringTableEntry textureName[NUM_TEX];
|
||||
TextureHandle textureHandle[NUM_TEX];
|
||||
|
||||
ExplosionData* explosion;
|
||||
S32 explosionId;
|
||||
|
||||
SplashData();
|
||||
DECLARE_CONOBJECT(SplashData);
|
||||
bool onAdd();
|
||||
bool preload(bool server, char errorBuffer[256]);
|
||||
static void initPersistFields();
|
||||
virtual void packData(BitStream* stream);
|
||||
virtual void unpackData(BitStream* stream);
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Splash
|
||||
//--------------------------------------------------------------------------
|
||||
class Splash : public GameBase
|
||||
{
|
||||
typedef GameBase Parent;
|
||||
|
||||
private:
|
||||
SplashData* mDataBlock;
|
||||
|
||||
ParticleEmitter * mEmitterList[ SplashData::NUM_EMITTERS ];
|
||||
|
||||
LList <SplashRing> ringList;
|
||||
|
||||
U32 mCurrMS;
|
||||
U32 mEndingMS;
|
||||
F32 mRandAngle;
|
||||
F32 mRadius;
|
||||
F32 mVelocity;
|
||||
F32 mHeight;
|
||||
ColorF mColor;
|
||||
F32 mTimeSinceLastRing;
|
||||
bool mDead;
|
||||
F32 mElapsedTime;
|
||||
|
||||
protected:
|
||||
Point3F mInitialPosition;
|
||||
Point3F mInitialNormal;
|
||||
F32 mFade;
|
||||
F32 mFog;
|
||||
bool mActive;
|
||||
S32 mDelayMS;
|
||||
|
||||
protected:
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
void processTick(const Move*);
|
||||
void advanceTime(F32 dt);
|
||||
void updateEmitters( F32 dt );
|
||||
void updateWave( F32 dt );
|
||||
void updateColor();
|
||||
SplashRing createRing();
|
||||
void updateRings( F32 dt );
|
||||
void updateRing( SplashRing *ring, F32 dt );
|
||||
void emitRings( F32 dt );
|
||||
void render();
|
||||
void renderSegment( SplashRing &top, SplashRing &bottom );
|
||||
void spawnExplosion();
|
||||
|
||||
// Rendering
|
||||
protected:
|
||||
bool prepRenderImage(SceneState*, const U32, const U32, const bool);
|
||||
void renderObject(SceneState*, SceneRenderImage*);
|
||||
|
||||
public:
|
||||
Splash();
|
||||
~Splash();
|
||||
void setInitialState(const Point3F& point, const Point3F& normal, const F32 fade = 1.0);
|
||||
|
||||
U32 packUpdate(NetConnection*, U32 mask, BitStream* stream);
|
||||
void unpackUpdate(NetConnection*, BitStream* stream);
|
||||
|
||||
bool onNewDataBlock(GameBaseData* dptr);
|
||||
DECLARE_CONOBJECT(Splash);
|
||||
static void initPersistFields();
|
||||
};
|
||||
|
||||
|
||||
#endif // _H_SPLASH
|
||||
144
game/fx/underLava.cc
Normal file
144
game/fx/underLava.cc
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "game/fx/underLava.h"
|
||||
|
||||
#include "dgl/dgl.h"
|
||||
#include "math/mRect.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
#include "terrain/waterBlock.h"
|
||||
#include "math/mConstants.h"
|
||||
|
||||
UnderLavaFX gLavaFX;
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// Under lava FX - "Lava - With pumice!"
|
||||
//**************************************************************************
|
||||
UnderLavaFX::UnderLavaFX()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Init
|
||||
//--------------------------------------------------------------------------
|
||||
void UnderLavaFX::init()
|
||||
{
|
||||
RectI viewport;
|
||||
dglGetViewport( &viewport );
|
||||
|
||||
mViewSize = viewport.extent;
|
||||
|
||||
mTexFrequency.x = F32(viewport.extent.x / viewport.extent.y);
|
||||
mTexFrequency.y = 1.0;
|
||||
|
||||
mNumPoints.x = 50 * F32(viewport.extent.x / viewport.extent.y);
|
||||
mNumPoints.y = 50;
|
||||
|
||||
mWave[0].amplitude = 0.02;
|
||||
mWave[0].frequency = 2.0;
|
||||
mWave[0].velocity = Sim::getCurrentTime() / 1000.0 * 2.0;
|
||||
|
||||
mMoveSpeed = Sim::getCurrentTime() / 1000.0 * 0.025;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Render
|
||||
//--------------------------------------------------------------------------
|
||||
void UnderLavaFX::render()
|
||||
{
|
||||
init();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
// TextureHandle lavaTex = WaterBlock::getSubmergeTexture(0);
|
||||
glBindTexture(GL_TEXTURE_2D, WaterBlock::getSubmergeTexture(0).getGLName());
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthMask(GL_FALSE);
|
||||
glColor4f(1.0, 1.0, 1.0, 0.5);
|
||||
|
||||
if( WaterBlock::getSubmergeTexture(0) )
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
||||
// render layer 1
|
||||
for( U32 i=0; i<mNumPoints.y; i++ )
|
||||
{
|
||||
renderRow( i, mNumPoints.y-1, mNumPoints.x-1 );
|
||||
}
|
||||
}
|
||||
|
||||
// give second layer a different phase
|
||||
mWave[0].velocity += 10.0;
|
||||
|
||||
// lavaTex = WaterBlock::getSubmergeTexture(1);
|
||||
|
||||
if( WaterBlock::getSubmergeTexture(1) )
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, WaterBlock::getSubmergeTexture(1).getGLName());
|
||||
|
||||
// render layer 2
|
||||
for( U32 i=0; i<mNumPoints.y; i++ )
|
||||
{
|
||||
renderRow( i, mNumPoints.y-1, mNumPoints.x-1 );
|
||||
}
|
||||
}
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Render row (triangle strip)
|
||||
//--------------------------------------------------------------------------
|
||||
void UnderLavaFX::renderRow( U32 row, U32 numRows, U32 numColumns )
|
||||
{
|
||||
|
||||
F32 xMult = F32(2.0) / F32(numColumns);
|
||||
F32 yMult = F32(2.0) / F32(numRows);
|
||||
|
||||
glBegin( GL_TRIANGLE_STRIP );
|
||||
|
||||
for( U32 i=0; i<numColumns+1; i++ )
|
||||
{
|
||||
F32 u = F32(i) / F32(numColumns) * mTexFrequency.x;
|
||||
F32 v = F32(row) / F32(numRows) * mTexFrequency.y;
|
||||
|
||||
u += mMoveSpeed + mWave[0].amplitude * mSin( u * M_2PI * mWave[0].frequency + mWave[0].velocity );
|
||||
v += mMoveSpeed + mWave[0].amplitude * mSin( v * M_2PI * mWave[0].frequency + mWave[0].velocity );
|
||||
|
||||
glTexCoord2f( u, v );
|
||||
glVertex2f( -1.0 + i * xMult, -1.0 + row * yMult );
|
||||
|
||||
v = F32(row+1) / F32(numRows) * mTexFrequency.y;
|
||||
v += mMoveSpeed + mWave[0].amplitude * mSin( v * M_2PI * mWave[0].frequency + mWave[0].velocity );
|
||||
|
||||
glTexCoord2f( u, v );
|
||||
glVertex2f( -1.0 + i * xMult, -1.0 + (row+1) * yMult );
|
||||
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
}
|
||||
58
game/fx/underLava.h
Normal file
58
game/fx/underLava.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _UNDERLAVA_H_
|
||||
#define _UNDERLAVA_H_
|
||||
|
||||
#ifndef _MPOINT_H_
|
||||
#include "math/mPoint.h"
|
||||
#endif
|
||||
|
||||
//**************************************************************************
|
||||
// Data
|
||||
//**************************************************************************
|
||||
struct LavaVertex
|
||||
{
|
||||
Point2I pnt;
|
||||
Point2F texPnt;
|
||||
|
||||
};
|
||||
|
||||
struct LavaWave
|
||||
{
|
||||
F32 frequency;
|
||||
F32 amplitude;
|
||||
F32 velocity;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// Under lava FX
|
||||
//**************************************************************************
|
||||
class UnderLavaFX
|
||||
{
|
||||
private:
|
||||
Point2F mTexFrequency;
|
||||
Point2I mNumPoints;
|
||||
Point2I mViewSize;
|
||||
LavaWave mWave[2];
|
||||
F32 mMoveSpeed;
|
||||
|
||||
void renderRow( U32 row, U32 numRows, U32 numColumns );
|
||||
|
||||
public:
|
||||
UnderLavaFX();
|
||||
|
||||
void init();
|
||||
void render();
|
||||
|
||||
};
|
||||
|
||||
extern UnderLavaFX gLavaFX;
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue