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

📄 waterblock.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "terrain/waterBlock.h"
#include "console/consoleTypes.h"
#include "sceneGraph/sceneGraph.h"
#include "sceneGraph/sceneState.h"
#include "core/bitStream.h"
#include "math/mBox.h"
#include "dgl/dgl.h"
#include "core/color.h"
#include "terrain/terrData.h"
#include "terrain/terrRender.h"
#include "math/mathIO.h"
#include "sceneGraph/sgUtil.h"
#include "audio/audioDataBlock.h"

//==============================================================================

IMPLEMENT_CO_NETOBJECT_V1(WaterBlock);

//==============================================================================

bool           WaterBlock::mCameraSubmerged = false;
U32            WaterBlock::mSubmergedType   = 0;
TextureHandle  WaterBlock::mSubmergeTexture[WC_NUM_SUBMERGE_TEX];

//==============================================================================
// I know this is a bit of a hack.  I've done this in order to avoid a coupling
// between the fluid and the rest of the system.
//
static SceneState* pSceneState = NULL;

static F32 FogFunction( F32 Distance, F32 DeltaZ )
{
   return( pSceneState->getHazeAndFog( Distance, DeltaZ ) );
}

//==============================================================================

WaterBlock::WaterBlock()
{
   mNetFlags.set(Ghostable | ScopeAlways);
   mTypeMask = WaterObjectType;

   mObjBox.min.set( 0, 0, 0 );
   mObjBox.max.set( 1, 1, 1 );

   mTile                = true;
   mLiquidType          = eOceanWater;
   mDensity             = 1;
   mViscosity           = 15;
   mWaveMagnitude       = 1.0f;
   mSurfaceTexture      = TextureHandle();
   mSpecMaskTex         = TextureHandle();
   mSurfaceOpacity      = 0.75f;
   mEnvMapOverTexture   = TextureHandle();
   mEnvMapUnderTexture  = TextureHandle();
   mEnvMapIntensity     = 0.4f;
   mShoreTexture        = TextureHandle();
   mRemoveWetEdges      = false;
   mAudioEnvironment    = 0;

   // lets be good little programmers and initialize our data!
   mSurfaceName      = NULL;
   mSpecMaskName     = NULL;
   mEnvMapOverName   = NULL;
   mEnvMapUnderName  = NULL;
   mShoreName        = NULL;

   dMemset( mSubmergeName, 0, sizeof( mSubmergeName ) );

   mpTerrain        = NULL;
   mSurfaceZ        = 0.0f;

   mEditorApplied       = false;
   mShoreDepth          = 20.0f;
   mMinAlpha            = 0.03f;
   mMaxAlpha            = 1.0f;
   mDepthGradient       = 1.0f;
   mUseDepthMap         = true;
   mTessellationSurface = 50;
   mTessellationShore   = 60;
   mSurfaceParallax     = 0.5f;
   mFlowAngle           = 0.0f;
   mFlowRate            = 0.0f;
   mDistortGridScale    = 0.1f;
   mDistortMagnitude    = 0.05f;
   mDistortTime         = 0.5f;

   mFluid.SetFogFn( FogFunction );
   mSpecColor.set( 1.0, 1.0, 1.0, 1.0 );
   mSpecPower = 6;
}

//==============================================================================

WaterBlock::~WaterBlock()
{
}

//==============================================================================

void WaterBlock::SnagTerrain( SceneObject* sceneObj, void * key )
{
    WaterBlock* pWater = (WaterBlock*)key;
    pWater->mpTerrain  = dynamic_cast<TerrainBlock*>(sceneObj);
}

//==============================================================================

void WaterBlock::UpdateFluidRegion( void )
{
    MatrixF M;
    Point3F P;

    P    = mObjToWorld.getPosition();
    P.x += 1024.0f;
    P.y += 1024.0f;

    mSurfaceZ = P.z + mObjScale.z;

    mFluid.SetInfo( P.x,
               P.y,
               mObjScale.x, mObjScale.y,
               mSurfaceZ,
               mWaveMagnitude,
               mSurfaceOpacity,
               mEnvMapIntensity,
               mRemoveWetEdges,
               mUseDepthMap,
               mTessellationSurface,
               mTessellationShore,
               mSurfaceParallax,
               mFlowAngle,
               mFlowRate,
               mDistortGridScale,
               mDistortMagnitude,
               mDistortTime,
               mSpecColor,
               mSpecPower,
               mTile);

    P.x -= 1024.0f;
    P.y -= 1024.0f;

    M.identity();
    M.setPosition( P );

    Parent::setTransform( M );

    resetWorldBox();

    if( isServerObject() )
        setMaskBits(1);
}

//==============================================================================

void WaterBlock::CalculateDepthMaps(void)
{
   // Generate Depth Textures.
   GenerateDepthTextures(mDepthBitmap, mDepthTexture, false);
   GenerateDepthTextures(mShoreDepthBitmap, mShoreDepthTexture, true);
}

//==============================================================================

///   Generate depth textures for water interaction with terrain.
///
///   What we are doing here is sample the terrain height at it's own resolution over the area of the
///   defined waterblock.  With these height points we can calculate an appropriate alpha value for the
///   depth-map texture texel.  This results in a *very* coarse alpha-map but this is resolved by passing
///   the texture through an iterative blur-convolution.
///
///   The resultant texture is used to alpha-blend in the surfaces and environment map using multi-texturing.
///   @author Melv May
void WaterBlock::GenerateDepthTextures(GBitmap* pBitmap, TextureHandle& mTexture, bool ShoreFlag)
{
   // Is this a client object?
   if (isClientObject())
   {
      // Yes, so we should have a depth-map bitmap.
      AssertWarn(pBitmap != NULL, "Waterblock: We should have a depth-map bitmap!");

      // Do we have the terrain yet?
      if (mpTerrain)
      {
         F32      DepthPoint;
         U32      FluidPointColour;
         U32*     pTexelBlockOutput;

         // Fetch the Bitmaps Data.
         U32* pDepthBits = (U32*)pBitmap->getAddress(0,0,0);

         // Calculate Fluid Min/Max Colour-Alpha.
         const U32 mFluidColour   = 0xffffff;
         const U32 mMinColour   = (mFluidColour + (((U32)(mMinAlpha * 255)) << 24));
         const U32 mMaxColour   = (mFluidColour + (((U32)(mMaxAlpha * 255)) << 24));

         // Calculate the Depth Bitmap Resolutions.
         F32      DepthSqrResX = pBitmap->getWidth(0) / mFluid.m_SquaresInX;
         F32      DepthSqrResY = pBitmap->getHeight(0) / mFluid.m_SquaresInY;

         // Calculate the Inverse Depth Bitmap Resolutions.
         F32      InvDepthSqrResX = 1.0f / DepthSqrResX;
         F32      InvDepthSqrResY = 1.0f / DepthSqrResY;

         // Calculate the Depth Bitmap Texel Resolutions.
         F32 DepthTexResX = mObjScale.x / eDepthMapResolution;
         F32 DepthTexResY = mObjScale.y / eDepthMapResolution;


         // Calculate the Depth Bitmap Strides.
         U32      XStride = pBitmap->getWidth(0);
         U32      YStride = pBitmap->getHeight(0);

         // Calculate the FluidLevel.
         F32      FluidLevel = mSurfaceZ;
         F32      Height;

         // Fetch the Waterblock Position.
         Point3F   TerrainPos = mObjToWorld.getPosition();
         // Change Spaces.
         TerrainPos.x += 1024.0f;
         TerrainPos.y += 1024.0f;

         // Terrain Height Offsets.
         F32 TerrainOffsetX;
         F32 TerrainOffsetY = 0;

         // Calculate Alpha Range.
         F32 AlphaRange = mMaxAlpha - mMinAlpha;

         // Calculate depth Alpha-Texel Map.
         for (s32 t = 0; t < eDepthMapResolution; t++)
         {
            // Reset Terrain Height Offset X.
            TerrainOffsetX = 0;

            for (s32 s = 0; s < eDepthMapResolution; s++)
            {
               // Fetch Terrain Height at current position.
               if ( mpTerrain->getHeight(   Point2F(TerrainPos.x + TerrainOffsetX , TerrainPos.y + TerrainOffsetY),
                                    &Height) )
               {
                  // Got a valid height so ...

                  // Calculate Depth Point.
                  DepthPoint = FluidLevel - Height;

                  // Are we below the minimum depth?
                  if (DepthPoint <= 0)
                  {
                     // Yes, so set to minimum colour/alpha.
                     FluidPointColour = mMinColour;
                  }
                  // ... so are we below the maximum depth?
                  else if (DepthPoint < mShoreDepth)
                  {
                     // Normalise Range.
                     F32 NormRange = mClampF(DepthPoint / mShoreDepth, 0.0f, 1.0f);

                     // Calculate Depth Alpha.
                     F32 DepthAlpha = (AlphaRange * mPow(NormRange, 1.0f / mDepthGradient)) + mMinAlpha;

                     // Calculate Resultant Fluid Colour/Alpha.
                     FluidPointColour = ((U32)(DepthAlpha*255)) << 24 | mFluidColour;
                  }
                  // ... out of our depth range ...
                  else
                  {
                     // Are we doing a shoreline depth-map?
                     if (ShoreFlag)
                     {
                        // Yesm so normalise Range.
                        F32 NormRange = mClampF((DepthPoint-mShoreDepth) / mShoreDepth, 0.0f, 1.0f);

                        // Calculate Depth Alpha.
                        F32 DepthAlpha = mMaxAlpha - ((AlphaRange * mPow(NormRange, 1.0f / mDepthGradient)) + mMinAlpha);

                        // Calculate Resultant Fluid Colour/Alpha.
                        FluidPointColour = ((U32)(255*DepthAlpha)) << 24 | mFluidColour;
                     }
                     else
                     {
                        // No so clip to maximum colour/alpha.
                        FluidPointColour = mMaxColour;
                     }
                  }
               }
               else
               {
                  // Eeek, empty grid square ...
                  FluidPointColour = mFluidColour;
               }

               // Calculate Position of Texel Block Origin.
               pTexelBlockOutput = pDepthBits + (U32)(s + (t * YStride));

               // Write Point Height to Texel.
               *pTexelBlockOutput = convertLEndianToHost(FluidPointColour);

               // Move to next Terrain Height Point.
               TerrainOffsetX += DepthTexResX;
            }

            // Move to next Terrain Height Point.
            TerrainOffsetY += DepthTexResY;
         }

         // Update the texture.
         mTexture.refresh();
#if 0
         // --------------------------------------------------------------------------------------
         // DEBUG CODE:  Dump the Depth Alpha-Map as a PNG file.
         // --------------------------------------------------------------------------------------

         // Output file.
         FileStream fStream;
         if(!fStream.open("depthmap.png", FileStream::Write))
         {
           Con::printf("Waterblock: Failed to open debug depth-map file!");
           return;
         }
         else
         {
            mDepthTexture.getBitmap()->writePNG(fStream);
            fStream.close();
         }
#endif
         // --------------------------------------------------------------------------------------
      }
   }
}

//==============================================================================

bool WaterBlock::onAdd()
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
    if( !isClientObject() )
#endif
    {
        // Make sure that the Fluid has had a chance to tweak the values.
        UpdateFluidRegion();

⌨️ 快捷键说明

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