⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 precipitation.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, 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"
#include "core/bitStream.h"
#include "platform/profiler.h"

static const U32 dropHitMask = TerrainObjectType |
                               InteriorObjectType |
                               WaterObjectType |
                               StaticShapeObjectType |
                               StaticTSObjectType;

IMPLEMENT_CO_NETOBJECT_V1(Precipitation);
IMPLEMENT_CO_DATABLOCK_V1(PrecipitationData);

//----------------------------------------------------------
// PrecipitationData
//----------------------------------------------------------
PrecipitationData::PrecipitationData()
{
   soundProfile      = NULL;
   soundProfileId    = 0;

   mDropName = StringTable->insert("");
   mSplashName = StringTable->insert("");

   mDropSize          = 0.5;
   mSplashSize        = 0.5;
   mUseTrueBillboards = true;
   mSplashMS          = 250;
}
IMPLEMENT_CONSOLETYPE(PrecipitationData)
IMPLEMENT_GETDATATYPE(PrecipitationData)
IMPLEMENT_SETDATATYPE(PrecipitationData)

void PrecipitationData::initPersistFields()
{
   Parent::initPersistFields();

   addField("soundProfile",      TypeAudioProfilePtr, Offset(soundProfile,       PrecipitationData));
   addField("dropTexture",       TypeFilename,        Offset(mDropName,          PrecipitationData));
   addField("splashTexture",     TypeFilename,        Offset(mSplashName,        PrecipitationData));
   addField("dropSize",          TypeF32,             Offset(mDropSize,          PrecipitationData));
   addField("splashSize",        TypeF32,             Offset(mSplashSize,        PrecipitationData));
   addField("splashMS",          TypeS32,             Offset(mSplashMS,          PrecipitationData));
   addField("useTrueBillboards", TypeBool,            Offset(mUseTrueBillboards, 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");

   return true;
}

void PrecipitationData::packData(BitStream* stream)
{
   Parent::packData(stream);

   if (stream->writeFlag(soundProfile != NULL))
      stream->writeRangedU32(soundProfile->getId(), DataBlockObjectIdFirst,
                             DataBlockObjectIdLast);

   stream->writeString(mDropName);
   stream->writeString(mSplashName);
   stream->write(mDropSize);
   stream->write(mSplashSize);
   stream->write(mSplashMS);
   stream->writeFlag(mUseTrueBillboards);
}

void PrecipitationData::unpackData(BitStream* stream)
{
   Parent::unpackData(stream);

   if (stream->readFlag())
      soundProfileId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
   else
      soundProfileId = 0;

   mDropName = stream->readSTString();
   mSplashName = stream->readSTString();

   stream->read(&mDropSize);
   stream->read(&mSplashSize);
   stream->read(&mSplashMS);
   mUseTrueBillboards = stream->readFlag();
}

//----------------------------------------------------------
// Precipitation!
//----------------------------------------------------------
Precipitation::Precipitation()
{
   mTypeMask |= ProjectileObjectType;
   mNetFlags.set(Ghostable|ScopeAlways);

   mDropHead = NULL;
   mSplashHead = NULL;
   mNumDrops = 5000;
   mPercentage = 1.0;

   mMinSpeed = 1.5;
   mMaxSpeed = 2.0;

   mBoxWidth = 200;
   mBoxHeight = 100;

   mMinMass = 0.75;
   mMaxMass = 0.85;

   mMaxTurbulence = 0.1;
   mTurbulenceSpeed = 0.2;
   mUseTurbulence = false;

   mRotateWithCamVel = true;

   mDoCollision = true;

   mStormData.valid = false;
   mStormData.startPct = 0;
   mStormData.endPct = 0;
   mStormData.startTime = 0;
   mStormData.totalTime = 0;

   mAudioHandle = 0;
   mDropHandle = TextureHandle();
   mSplashHandle = TextureHandle();

   U32 count = 0;
   for (U32 v = 0; v < DROPS_PER_SIDE; v++)
   {
      const F32 y1 = (F32) v / DROPS_PER_SIDE;
      const F32 y2 = (F32)(v+1) / DROPS_PER_SIDE;

      for (U32 u = 0; u < DROPS_PER_SIDE; u++)
      {
         const F32 x1 = (F32) u / DROPS_PER_SIDE;
         const F32 x2 = (F32)(u+1) / DROPS_PER_SIDE;

         texCoords[4*count+0].x = x1;
         texCoords[4*count+0].y = y1;

         texCoords[4*count+1].x = x2;
         texCoords[4*count+1].y = y1;

         texCoords[4*count+2].x = x2;
         texCoords[4*count+2].y = y2;

         texCoords[4*count+3].x = x1;
         texCoords[4*count+3].y = y2;
         count++;
      }
   }

   count = 0;
   for (U32 v = 0; v < FRAMES_PER_SIDE; v++)
   {
      const F32 y1 = (F32) v / FRAMES_PER_SIDE;
      const F32 y2 = (F32)(v+1) / FRAMES_PER_SIDE;

      for (U32 u = 0; u < FRAMES_PER_SIDE; u++)
      {
         const F32 x1 = (F32) u / FRAMES_PER_SIDE;
         const F32 x2 = (F32)(u+1) / FRAMES_PER_SIDE;

         splashCoords[4*count+0].x = x1;
         splashCoords[4*count+0].y = y1;

         splashCoords[4*count+1].x = x2;
         splashCoords[4*count+1].y = y1;

         splashCoords[4*count+2].x = x2;
         splashCoords[4*count+2].y = y2;

         splashCoords[4*count+3].x = x1;
         splashCoords[4*count+3].y = y2;
         count++;
      }
   }
}

Precipitation::~Precipitation()
{
}

void Precipitation::inspectPostApply()
{
   if (isClientObject())
      fillDropList();

   setMaskBits(DataMask);
}

//--------------------------------------------------------------------------
// Console stuff...
//--------------------------------------------------------------------------
void Precipitation::initPersistFields()
{
   Parent::initPersistFields();

   addGroup("Movement");
   addField("minSpeed", TypeF32, Offset(mMinSpeed, Precipitation));
   addField("maxSpeed", TypeF32, Offset(mMaxSpeed, Precipitation));

   addField("minMass", TypeF32, Offset(mMinMass, Precipitation));
   addField("maxMass", TypeF32, Offset(mMaxMass, Precipitation));
   endGroup("Movement");

   addGroup("Turbulence");
   addField("maxTurbulence", TypeF32, Offset(mMaxTurbulence, Precipitation));
   addField("turbulenceSpeed", TypeF32, Offset(mTurbulenceSpeed, Precipitation));

   addField("rotateWithCamVel", TypeBool, Offset(mRotateWithCamVel, Precipitation));
   addField("useTurbulence", TypeBool, Offset(mUseTurbulence, Precipitation));
   endGroup("Turbulence");

   addField("numDrops", TypeS32, Offset(mNumDrops, Precipitation));
   addField("boxWidth", TypeF32, Offset(mBoxWidth, Precipitation));
   addField("boxHeight", TypeF32, Offset(mBoxHeight, Precipitation));

   addField("doCollision", TypeBool, Offset(mDoCollision, Precipitation));
}

//-----------------------------------
// Console methods...
ConsoleMethod(Precipitation, setPercentange, void, 3, 3, "precipitation.setPercentage(percentage <0.0 to 1.0>)")
{
   object->setPercentage(dAtof(argv[2]));
}

ConsoleMethod(Precipitation, modifyStorm, void, 4, 4, "precipitation.modifyStorm(Percentage <0 to 1>, Time<sec>)")
{
   object->modifyStorm(dAtof(argv[2]), dAtof(argv[3]) * 1000);
}

//--------------------------------------------------------------------------
// Backend
//--------------------------------------------------------------------------
bool Precipitation::onAdd()
{
   if(!Parent::onAdd())
      return false;

   if (isClientObject())
   {
      if (mDataBlock->soundProfile)
         mAudioHandle = alxPlay(mDataBlock->soundProfile, &getTransform() );

      fillDropList();
   }

   mObjBox.min.set(-1e6, -1e6, -1e6);
   mObjBox.max.set( 1e6,  1e6,  1e6);

   if (isClientObject())
   {
      mDropHandle = TextureHandle(((PrecipitationData*)mDataBlock)->mDropName, MeshTexture);
      mSplashHandle = TextureHandle(((PrecipitationData*)mDataBlock)->mSplashName, MeshTexture);
   }

   resetWorldBox();
   addToScene();

   return true;
}

void Precipitation::onRemove()
{
   removeFromScene();
   Parent::onRemove();

   if (mAudioHandle)
      alxStop(mAudioHandle);
   mAudioHandle = 0;

   if (isClientObject())
      killDropList();
}

bool Precipitation::onNewDataBlock(GameBaseData* dptr)
{
   mDataBlock = dynamic_cast<PrecipitationData*>(dptr);
   if (!mDataBlock || !Parent::onNewDataBlock(dptr))
      return false;

   if (isClientObject())
   {
      mDropHandle = TextureHandle(((PrecipitationData*)mDataBlock)->mDropName, MeshTexture);
      mSplashHandle = TextureHandle(((PrecipitationData*)mDataBlock)->mSplashName, MeshTexture);
   }

   scriptOnNewDataBlock();
   return true;
}

U32 Precipitation::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
{
   Parent::packUpdate(con, mask, stream);

   if (stream->writeFlag(mask & DataMask))
   {
      stream->write(mNumDrops);
      stream->write(mMinSpeed);
      stream->write(mMaxSpeed);
      stream->write(mBoxWidth);
      stream->write(mBoxHeight);
      stream->write(mMinMass);
      stream->write(mMaxMass);
      stream->write(mMaxTurbulence);
      stream->write(mTurbulenceSpeed);
      stream->writeFlag(mUseTurbulence);
      stream->writeFlag(mRotateWithCamVel);
      stream->writeFlag(mDoCollision);
   }

   if (stream->writeFlag(mask & PercentageMask))
   {
      stream->write(mPercentage);
   }

   if (stream->writeFlag(!(mask & ~(DataMask | PercentageMask | StormMask)) && (mask & StormMask)))
   {
      stream->write(mStormData.endPct);
      stream->write(mStormData.totalTime);
   }

   return 0;
}

void Precipitation::unpackUpdate(NetConnection* con, BitStream* stream)
{
   Parent::unpackUpdate(con, stream);

   U32 oldDrops = mNumDrops * mPercentage;
   if (stream->readFlag())
   {
      stream->read(&mNumDrops);
      stream->read(&mMinSpeed);
      stream->read(&mMaxSpeed);
      stream->read(&mBoxWidth);
      stream->read(&mBoxHeight);
      stream->read(&mMinMass);
      stream->read(&mMaxMass);
      stream->read(&mMaxTurbulence);
      stream->read(&mTurbulenceSpeed);
      mUseTurbulence = stream->readFlag();
      mRotateWithCamVel = stream->readFlag();
      mDoCollision = stream->readFlag();
   }

   if (stream->readFlag())
   {
      stream->read(&mPercentage);
   }

   if (stream->readFlag())
   {
      F32 pct;
      U32 time;
      stream->read(&pct);
      stream->read(&time);
      modifyStorm(pct, time);
   }

   U32 newDrops = mNumDrops * mPercentage;
   if (isClientObject() && oldDrops != newDrops)
      fillDropList();
}

//--------------------------------------------------------------------------
// Support functions
//--------------------------------------------------------------------------
VectorF Precipitation::getWindVelocity()
{
   Sky* sky = gClientSceneGraph->getCurrentSky();
   return (sky && sky->mEffectPrecip) ? -sky->getWindVelocity() : VectorF(0,0,0);
}

void Precipitation::fillDropList()
{
   AssertFatal(isClientObject(), "Precipitation is doing stuff on the server - BAD!");

   F32 density = Con::getFloatVariable("$pref::precipitationDensity", 1.0f);
   U32 newDropCount = (U32)(mNumDrops * mPercentage * density);
   U32 dropCount = 0;
   if (mDropHead)
   {
      Raindrop* curr = mDropHead;
      while (curr)
      {
         dropCount++;
         curr = curr->next;
         if (dropCount == newDropCount && curr)
         {
            //delete the remaining drops
            Raindrop* next = curr->next;
            curr->next = NULL;
            while (next)
            {
               Raindrop* last = next;
               next = next->next;
               last->next = NULL;
               destroySplash(last);
               delete last;
            }
            break;
         }
      }
   }

   if (dropCount < newDropCount)
   {
      //move to the end
      Raindrop* curr = mDropHead;
      if (curr)
      {
         while (curr->next)
            curr = curr->next;
      }
      else
      {
         mDropHead = curr = new Raindrop;
         spawnNewDrop(curr);
         dropCount++;
      }

      //and add onto it
      while (dropCount < newDropCount)
      {
         curr->next = new Raindrop;
         curr = curr->next;
         spawnNewDrop(curr);
         dropCount++;
      }
   }
}

void Precipitation::killDropList()
{
   AssertFatal(isClientObject(), "Precipitation is doing stuff on the server - BAD!");

   Raindrop* curr = mDropHead;
   while (curr)
   {
      Raindrop* next = curr->next;
      delete curr;
      curr = next;
   }
   mDropHead = NULL;
}

void Precipitation::spawnDrop(Raindrop *drop)
{
   PROFILE_START(PrecipSpawnDrop);
   AssertFatal(isClientObject(), "Precipitation is doing stuff on the server - BAD!");

   drop->velocity = Platform::getRandom() * (mMaxSpeed - mMinSpeed) + mMinSpeed;

   drop->position.x = Platform::getRandom() * mBoxWidth - (mBoxWidth / 2);
   drop->position.y = Platform::getRandom() * mBoxWidth - (mBoxWidth / 2);

   drop->texCoordIndex = (U32)(Platform::getRandom() * ((F32)DROPS_PER_SIDE*DROPS_PER_SIDE - 0.5));
   drop->valid = true;
   drop->time = Platform::getRandom() * M_2PI;
   drop->mass = Platform::getRandom() * (mMaxMass - mMinMass) + mMinMass;
   PROFILE_END();
}

void Precipitation::spawnNewDrop(Raindrop *drop)
{
   AssertFatal(isClientObject(), "Precipitation is doing stuff on the server - BAD!");

   spawnDrop(drop);
   drop->position.z = Platform::getRandom() * mBoxHeight - (mBoxHeight / 2);
}

void Precipitation::findDropCutoff(Raindrop *drop)
{
   PROFILE_START(PrecipFindDropCutoff);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -