D:/simple_rts/src/FogOfWar.cpp

Go to the documentation of this file.
00001 #include "FogOfWar.h"
00002 
00003 #include "Level.h"
00004 #include "Unit.h"
00005 
00006 #include <memory>
00007 
00008 #include "OgreHardwareBuffer.h"
00009 #include "OgreString.h"
00010 #include "OgreStringConverter.h"
00011 #include "OgreTextureManager.h"
00012 #include "OgreVector3.h"
00013 
00014 #include "OgreMaterialManager.h"
00015 #include "OgreMaterial.h"
00016 #include "OgreTechnique.h"
00017 #include "OgrePass.h"
00018 #include "OgreTextureUnitState.h"
00019 using namespace Ogre;
00020 
00021 using Ogre::HardwareBuffer;
00022 using Ogre::String;
00023 using Ogre::StringConverter;
00024 using Ogre::TextureManager;
00025 
00026 
00027 namespace ASR
00028 {
00029         int FogOfWar::mNumFogs = 0;
00030 
00031         // ----------------------------------------------------------------------------
00032         FogOfWar::FogOfWar ( int width, int height )
00033                 : mWidth ( width ), mHeight ( height )
00034         {
00035                 mBuffer = new unsigned int[ width * height ];
00036                 memset ( mBuffer, 0x00000000, width * height * sizeof(unsigned int) );
00037 
00038 
00039                 String name = "fogOfWar_" + StringConverter::toString ( mNumFogs );
00040                 mFogTexture = TextureManager::getSingleton().createManual ( name, "General", Ogre::TEX_TYPE_2D, width, height, 1, Ogre::PF_A8R8G8B8, Ogre::TU_DYNAMIC_WRITE_ONLY );
00041                 mPixBuffer = mFogTexture->getBuffer ();
00042 
00043                 // HACK
00044                 //              This should create a copy of the terrain material and only modify that
00045                 //              locally (for network support)
00046                 if ( mNumFogs == 0 )
00047                 {
00048                         MaterialPtr mat = MaterialManager::getSingleton ().getByName ( "ASR/Terrain" );
00049                         Technique* tech = mat->getSupportedTechnique ( 0 );
00050                         Pass* pass = tech->getPass ( 0 );
00051                         TextureUnitState* state = pass->createTextureUnitState ( name, 0 );
00052                         state->setColourOperationEx ( Ogre::LBX_MODULATE );
00053                 }
00054 
00055 
00056                 mNumFogs++;
00057         }
00058 
00059 
00060         // ----------------------------------------------------------------------------
00061         FogOfWar::~FogOfWar ()
00062         {
00063                 mFogTexture.setNull ();
00064                 mPixBuffer.setNull ();
00065 
00066                 delete[] mBuffer;
00067         }
00068 
00069 
00070         // ----------------------------------------------------------------------------
00071         void FogOfWar::blackOut ()
00072         {
00073                 memset ( mBuffer, 0, mWidth * mHeight * sizeof(unsigned int) );
00074         }
00075 
00076 
00077         // ----------------------------------------------------------------------------
00078         void FogOfWar::fadeOut ()
00079         {
00080                 for ( int y = 0; y < mHeight; y++ )
00081                 {
00082                         for ( int x = 0; x < mWidth; x++ )
00083                         {
00084                                 if ( mBuffer[y * mWidth + x] > 0x88888888 )
00085                                 {
00086                                         mBuffer[y * mWidth + x] -= 0x05050505;
00087                                 }
00088                         }
00089                 }
00090         }
00091 
00092 
00093         // ----------------------------------------------------------------------------
00094         void FogOfWar::updateTexture ()
00095         {
00096                 mPixBuffer->lock ( HardwareBuffer::HBL_DISCARD );
00097 
00098                 const PixelBox& pb = mPixBuffer->getCurrentLock ();
00099                 for ( unsigned int y = 0; y < pb.getHeight (); y++ )
00100                 {
00101                         unsigned int *data = static_cast<unsigned int*>(pb.data) + y*pb.rowPitch;
00102                         unsigned int *src = mBuffer + (y * mWidth);
00103                         memcpy ( data, src, pb.getWidth() * sizeof(unsigned int) );
00104                 }
00105 
00106                 mPixBuffer->unlock ();
00107         }
00108 
00109 
00110         // ----------------------------------------------------------------------------
00111         void FogOfWar::setVisible ( int x, int y, int radius )
00112         {
00113                 // Draw a filled circle using Bresenham's Circle Algorithm
00114 
00115                 x = (float)x / ( Level::getSingleton ().getWorldWidth () / Level::getSingleton ().getNumNodesWide () );
00116                 y = (float)y / ( Level::getSingleton ().getWorldHeight () / Level::getSingleton ().getNumNodesHigh () );
00117 
00118                 // TODO
00119                 //              How do we scale a radius in a non-rectangular grid (use ellipses)
00120                 radius = (float)radius / (Level::getSingleton ().getWorldHeight () / Level::getSingleton ().getNumNodesHigh ());
00121 
00122                 int p = 1 - radius;
00123 
00124                 // Start at the top position
00125                 int x0 = 0;
00126                 int y0 = radius;
00127 
00128 
00129                 _drawHorizontalLine ( x - radius, x + radius, y );
00130 
00131                 while ( x0 < y0 )
00132                 {
00133                         x0++;
00134 
00135                         _drawHorizontalLine ( x - y0, x + y0, y + x0 );
00136                         _drawHorizontalLine ( x - y0, x + y0, y - x0 );
00137 
00138                         if ( p < 0 )
00139                         {
00140                                 p += 2 * x0 + 1;
00141                         }
00142                         else
00143                         {
00144                                 _drawHorizontalLine ( x - x0, x + x0, y + y0 );
00145                                 _drawHorizontalLine ( x - x0, x + x0, y - y0 );
00146 
00147                                 y0--;
00148                                 p += 2 * ( x0 - y0 ) + 1;
00149                         }
00150                 }
00151         }
00152 
00153 
00154         // ----------------------------------------------------------------------------
00155         void FogOfWar::_drawHorizontalLine ( int xStart, int xEnd, int y )
00156         {
00157                 if ( xStart > xEnd )
00158                 {
00159                         int temp = xStart;
00160                         xStart = xEnd;
00161                         xEnd = temp;
00162                 }
00163 
00164                 // Clamping
00165                 if ( y < 0 )
00166                         return;
00167                 if ( y >= mHeight )
00168                         return;
00169                 if ( xStart >= mWidth )
00170                         return;
00171                 if ( xEnd < 0 )
00172                         return;
00173 
00174                 if ( xStart < 0 )
00175                         xStart = 0;
00176                 if ( xEnd >= mWidth )
00177                         xEnd = mWidth - 1;
00178                 // End Clamping
00179 
00180                 memset ( mBuffer + (y*mWidth) + xStart, 0xFFFFFFFF, (xEnd - xStart + 1) * sizeof(unsigned int) );
00181         }
00182 
00183 
00184         // ----------------------------------------------------------------------------
00185         bool FogOfWar::isUnitVisible ( const Unit* unit ) const
00186         {
00187                 // TODO
00188                 //              Implement a more robust check consisting of the entire
00189                 //              bounding region of the unit, not just its center point
00190 
00191                 Vector3 pos = unit->getPosition ();
00192                 pos.x /= ( Level::getSingleton ().getWorldWidth () / Level::getSingleton ().getNumNodesWide () );
00193                 pos.z /= ( Level::getSingleton ().getWorldHeight () / Level::getSingleton ().getNumNodesHigh () );
00194 
00195                 return ( mBuffer[ int(pos.z) * mWidth + int(pos.x) ] == 0xFFFFFFFF );
00196         }
00197 }

Generated on Sun Jun 25 19:23:43 2006 for Valors End by  doxygen 1.4.7