Prechádzať zdrojové kódy

enhanced-particle -- Accounts for larger number of particle size keys.

Marc Chapman 8 rokov pred
rodič
commit
706d717ef6

+ 5 - 2
Engine/source/T3D/debris.cpp

@@ -24,6 +24,7 @@
 // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
 // Copyright (C) 2015 Faust Logic, Inc.
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
+
 #include "platform/platform.h"
 #include "T3D/debris.h"
 
@@ -633,7 +634,8 @@ bool Debris::onAdd()
    {
       sizeList[0] = mSize * 0.5;
       sizeList[1] = mSize;
-      sizeList[2] = mSize * 1.5;
+      for (U32 i = 2; i < ParticleData::PDC_NUM_KEYS; i++)
+         sizeList[i] = mSize * 1.5;
 
       mEmitterList[0]->setSizes( sizeList );
    }
@@ -642,7 +644,8 @@ bool Debris::onAdd()
    {
       sizeList[0] = 0.0;
       sizeList[1] = mSize * 0.5;
-      sizeList[2] = mSize;
+      for (U32 i = 2; i < ParticleData::PDC_NUM_KEYS; i++)
+         sizeList[i] = mSize;
 
       mEmitterList[1]->setSizes( sizeList );
    }

+ 101 - 20
Engine/source/T3D/fx/particle.cpp

@@ -24,6 +24,7 @@
 // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
 // Copyright (C) 2015 Faust Logic, Inc.
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
+
 #include "particle.h"
 #include "console/consoleTypes.h"
 #include "console/typeValidators.h"
@@ -77,6 +78,8 @@ static const F32 sgDefaultSpinSpeed = 1.f;
 static const F32 sgDefaultSpinRandomMin = 0.f;
 static const F32 sgDefaultSpinRandomMax = 0.f;
 
+static const F32 sgDefaultSpinBias = 1.0f;
+static const F32 sgDefaultSizeBias = 1.0f;
 
 //-----------------------------------------------------------------------------
 // Constructor
@@ -107,9 +110,9 @@ ParticleData::ParticleData()
    }
 
    times[0] = 0.0f;
-   times[1] = 0.33f;
-   times[2] = 0.66f;
-   times[3] = 1.0f;
+   times[1] = 1.0f;
+   for (i = 2; i < PDC_NUM_KEYS; i++)
+     times[i] = -1.0f;
 
    texCoords[0].set(0.0,0.0);   // texture coords at 4 corners
    texCoords[1].set(0.0,1.0);   // of particle quad
@@ -120,18 +123,20 @@ ParticleData::ParticleData()
    animTexUVs = NULL;           // array of tile vertex UVs
    textureName = NULL;          // texture filename
    textureHandle = NULL;        // loaded texture handle
+   textureExtName = NULL;
+   textureExtHandle = NULL;
+   constrain_pos = false;
+   start_angle = 0.0f;
+   angle_variance = 0.0f;
+   sizeBias = sgDefaultSizeBias;
+   spinBias = sgDefaultSpinBias;
+   randomizeSpinDir = false;
 }
 
 //-----------------------------------------------------------------------------
 // Destructor
 //-----------------------------------------------------------------------------
-ParticleData::~ParticleData()
-{
-   if (animTexUVs)
-   {
-      delete [] animTexUVs;
-   }
-}
+
 
 FRangeValidator dragCoefFValidator(0.f, 5.f);
 FRangeValidator gravCoefFValidator(-10.f, 10.f);
@@ -219,6 +224,15 @@ void ParticleData::initPersistFields()
       "@brief Time keys used with the colors and sizes keyframes.\n\n"
       "Values are from 0.0 (particle creation) to 1.0 (end of lifespace)." );
 
+   addGroup("AFX"); 
+   addField("textureExtName",       TypeFilename, Offset(textureExtName,     ParticleData));
+   addField("constrainPos",         TypeBool,     Offset(constrain_pos,      ParticleData));
+   addField("angle",                TypeF32,      Offset(start_angle,        ParticleData));
+   addField("angleVariance",        TypeF32,      Offset(angle_variance,     ParticleData));
+   addField("sizeBias",             TypeF32,      Offset(sizeBias,           ParticleData));
+   addField("spinBias",             TypeF32,      Offset(spinBias,           ParticleData));
+   addField("randomizeSpinDir",     TypeBool,     Offset(randomizeSpinDir,   ParticleData));
+   endGroup("AFX"); 
    Parent::initPersistFields();
 }
 
@@ -248,18 +262,22 @@ void ParticleData::packData(BitStream* stream)
       stream->writeInt((S32)(spinRandomMin + 1000), 11);
       stream->writeInt((S32)(spinRandomMax + 1000), 11);
    }
+   if(stream->writeFlag(spinBias != sgDefaultSpinBias))
+      stream->write(spinBias);
+   stream->writeFlag(randomizeSpinDir);
    stream->writeFlag(useInvAlpha);
 
    S32 i, count;
 
    // see how many frames there are:
-   for(count = 0; count < 3; count++)
+   for(count = 0; count < ParticleData::PDC_NUM_KEYS-1; count++)
       if(times[count] >= 1)
          break;
 
    count++;
 
-   stream->writeInt(count-1, 2);
+   // An extra bit is needed for 8 keys.
+   stream->writeInt(count-1, 3);
 
    for( i=0; i<count; i++ )
    {
@@ -267,7 +285,8 @@ void ParticleData::packData(BitStream* stream)
       stream->writeFloat( colors[i].green, 7);
       stream->writeFloat( colors[i].blue, 7);
       stream->writeFloat( colors[i].alpha, 7);
-      stream->writeFloat( sizes[i]/MaxParticleSize, 14);
+      // AFX bits raised from 14 to 16 to allow larger sizes
+      stream->writeFloat( sizes[i]/MaxParticleSize, 16);
       stream->writeFloat( times[i], 8);
    }
 
@@ -284,6 +303,13 @@ void ParticleData::packData(BitStream* stream)
       mathWrite(*stream, animTexTiling);
       stream->writeInt(framesPerSec, 8);
    }
+   if (stream->writeFlag(textureExtName && textureExtName[0]))
+     stream->writeString(textureExtName);
+   stream->writeFlag(constrain_pos);
+   stream->writeFloat(start_angle/360.0f, 11);
+   stream->writeFloat(angle_variance/180.0f, 10);
+   if(stream->writeFlag(sizeBias != sgDefaultSizeBias))
+      stream->write(sizeBias);
 }
 
 //-----------------------------------------------------------------------------
@@ -327,17 +353,24 @@ void ParticleData::unpackData(BitStream* stream)
       spinRandomMax = sgDefaultSpinRandomMax;
    }
 
+   if(stream->readFlag())
+      stream->read(&spinBias);
+   else
+      spinBias = sgDefaultSpinBias;
+   randomizeSpinDir = stream->readFlag();
    useInvAlpha = stream->readFlag();
 
    S32 i;
-   S32 count = stream->readInt(2) + 1;
+   // An extra bit is needed for 8 keys.
+   S32 count = stream->readInt(3) + 1;
    for(i = 0;i < count; i++)
    {
       colors[i].red = stream->readFloat(7);
       colors[i].green = stream->readFloat(7);
       colors[i].blue = stream->readFloat(7);
       colors[i].alpha = stream->readFloat(7);
-      sizes[i] = stream->readFloat(14) * MaxParticleSize;
+      // AFX bits raised from 14 to 16 to allow larger sizes
+      sizes[i] = stream->readFloat(16) * MaxParticleSize;
       times[i] = stream->readFloat(8);
    }
    textureName = (stream->readFlag()) ? stream->readSTString() : 0;
@@ -351,6 +384,14 @@ void ParticleData::unpackData(BitStream* stream)
      mathRead(*stream, &animTexTiling);
      framesPerSec = stream->readInt(8);
    }
+   textureExtName = (stream->readFlag()) ? stream->readSTString() : 0;
+   constrain_pos = stream->readFlag();
+   start_angle = 360.0f*stream->readFloat(11);
+   angle_variance = 180.0f*stream->readFloat(10);
+   if(stream->readFlag())
+      stream->read(&sizeBias);
+   else
+      sizeBias = sgDefaultSizeBias;
 }
 
 bool ParticleData::protectedSetSizes( void *object, const char *index, const char *data) 
@@ -432,11 +473,33 @@ bool ParticleData::onAdd()
    }
 
    times[0] = 0.0f;
-   for (U32 i = 1; i < 4; i++) {
-      if (times[i] < times[i-1]) {
-         Con::warnf(ConsoleLogEntry::General, "ParticleData(%s) times[%d] < times[%d]", getName(), i, i-1);
-         times[i] = times[i-1];
-      }
+   for (U32 i = 1; i < PDC_NUM_KEYS; i++) 
+   {
+     if (times[i] < 0.0f)
+       break;
+     if (times[i] < times[i-1]) 
+     {
+       Con::warnf(ConsoleLogEntry::General, "ParticleData(%s) times[%d] < times[%d]", getName(), i, i-1);
+       times[i] = times[i-1];
+     }
+   }
+
+   times[0] = 0.0f;
+
+   U32 last_idx = 0;
+   for (U32 i = 1; i < PDC_NUM_KEYS; i++)
+   {
+     if (times[i] < 0.0f)
+       break;
+     else
+       last_idx = i;
+   }
+
+   for (U32 i = last_idx+1; i < PDC_NUM_KEYS; i++) 
+   {
+      times[i] = times[last_idx];
+      colors[i] = colors[last_idx];
+      sizes[i] = sizes[last_idx];
    }
 
    // Here we validate parameters
@@ -475,6 +538,10 @@ bool ParticleData::onAdd()
      }
    }
 
+   start_angle = mFmod(start_angle, 360.0f);
+   if (start_angle < 0.0f)
+     start_angle += 360.0f;
+   angle_variance = mClampF(angle_variance, -180.0f, 180.0f);
    return true;
 }
 
@@ -500,6 +567,15 @@ bool ParticleData::preload(bool server, String &errorStr)
           error = true;
         }
       }
+      if (textureExtName && textureExtName[0])
+      {
+         textureExtHandle = GFXTexHandle(textureExtName, &GFXStaticTextureSRGBProfile, avar("%s() - textureExtHandle (line %d)", __FUNCTION__, __LINE__));
+         if (!textureExtHandle)
+         {
+            errorStr = String::ToString("Missing particle texture: %s", textureName);
+            error = true;
+         }
+      }
 
       if (animateTexture) 
       {
@@ -611,6 +687,11 @@ void ParticleData::initializeParticle(Particle* init, const Point3F& inheritVelo
 
    // assign spin amount
    init->spinSpeed = spinSpeed * gRandGen.randF( spinRandomMin, spinRandomMax );
+   // apply spin bias
+   init->spinSpeed *= spinBias;
+   // randomize spin direction
+   if (randomizeSpinDir && (gRandGen.randI( 0, 1 ) == 1))
+     init->spinSpeed = -init->spinSpeed;
 }
 
 bool ParticleData::reload(char errorBuffer[256])

+ 17 - 1
Engine/source/T3D/fx/particle.h

@@ -49,7 +49,9 @@ class ParticleData : public SimDataBlock
   public:
    enum PDConst
    {
-      PDC_NUM_KEYS = 4,
+      // This increase the keyframes from 4 to 8. Especially useful for premult-alpha blended particles
+      // for which 4 keyframes is often not enough.
+      PDC_NUM_KEYS = 8,
    };
 
    F32   dragCoefficient;
@@ -106,6 +108,16 @@ class ParticleData : public SimDataBlock
    /*C*/  ParticleData(const ParticleData&, bool = false);
    virtual void onPerformSubstitutions();
    virtual bool allowSubstitutions() const { return true; }
+  protected:
+   F32   spinBias;
+   bool  randomizeSpinDir;
+   StringTableEntry  textureExtName;
+  public:
+   GFXTexHandle      textureExtHandle;
+   bool   constrain_pos;
+   F32    start_angle;
+   F32    angle_variance;
+   F32    sizeBias; 
   public:
    bool loadParameters();  
    bool reload(String &errorStr);
@@ -135,6 +147,10 @@ struct Particle
 
    F32              spinSpeed;
    Particle *       next;
+   Point3F  pos_local;
+   F32      t_last;
+   Point3F  radial_v;   // radial vector for concentric effects
+   // note -- for non-oriented particles, we use orientDir.x to store the billboard start angle.
 };