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
00044
00045
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
00114
00115 x = (float)x / ( Level::getSingleton ().getWorldWidth () / Level::getSingleton ().getNumNodesWide () );
00116 y = (float)y / ( Level::getSingleton ().getWorldHeight () / Level::getSingleton ().getNumNodesHigh () );
00117
00118
00119
00120 radius = (float)radius / (Level::getSingleton ().getWorldHeight () / Level::getSingleton ().getNumNodesHigh ());
00121
00122 int p = 1 - radius;
00123
00124
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
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
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
00188
00189
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 }