ShadowMap.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <math.h>
00022 #include <string.h>
00023 #include <GLEXT/GLStateExtension.h>
00024 #include <landscape/ShadowMap.h>
00025 #include <landscapemap/LandscapeMaps.h>
00026 #include <client/ScorchedClient.h>
00027 #include <common/Defines.h>
00028 #include <graph/OptionsDisplay.h>
00029 
00030 ShadowMap::ShadowMap() : size_(256), sizeSq_(256 *256), shadowCount_(0)
00031 {
00032         shadowBytes_ = new GLubyte[sizeSq_];
00033         memset(shadowBytes_, 255, sizeSq_);
00034         shadowTexture_.create(shadowBytes_, size_, size_, 1, 4, GL_LUMINANCE, false);
00035 }
00036 
00037 ShadowMap::~ShadowMap()
00038 {
00039         delete [] shadowBytes_;
00040 }
00041 
00042 void ShadowMap::setTexture()
00043 {
00044         shadowCount_ = 0;
00045 
00046         // Set the shadow map texture
00047         shadowTexture_.draw(true);
00048 
00049         if (!GLStateExtension::getNoTexSubImage())
00050         {
00051                 // Update with the contents from the stored bytes
00052                 glTexSubImage2D(GL_TEXTURE_2D, 0, 
00053                                                 0, 0, 
00054                                                 size_, size_, 
00055                                                 GL_LUMINANCE, GL_UNSIGNED_BYTE, 
00056                                                 shadowBytes_);
00057 
00058                 // Reset the stored bytes
00059                 memset(shadowBytes_, 255, sizeSq_);
00060 
00061                 // Debuging stripe
00062                 //for (int i=0; i<size_; i++) shadowBytes_[i + i * size_] = 0;
00063         }
00064 }
00065 
00066 void ShadowMap::addSquare(float sx, float sy, float sw, float opacity)
00067 {
00068         addShadow(sx, sy, sw, opacity, false);
00069 }
00070 
00071 void ShadowMap::addCircle(float sx, float sy, float sw, float opacity)
00072 {
00073         addShadow(sx, sy, sw, opacity, true);
00074 }
00075 
00076 bool ShadowMap::shouldAddShadow()
00077 {
00078         if (!GLStateExtension::hasMultiTex() ||
00079                 GLStateExtension::getNoTexSubImage() ||
00080                 OptionsDisplay::instance()->getNoShadows() ||
00081                 GLStateExtension::hasHardwareShadows()) return false;
00082         return true;
00083 }
00084 
00085 void ShadowMap::addShadow(float mapx, float mapy, float mapw, float opacity, bool circle)
00086 {
00087         if (!shouldAddShadow()) return;
00088 
00089         if (mapw > 10.0f) return; // Sanity check
00090 
00091         int mapWidth = 
00092                 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeWidth();
00093         int mapHeight = 
00094                 ScorchedClient::instance()->getLandscapeMaps().getGroundMaps().getLandscapeHeight();
00095 
00096         float sx = mapx * size_ / float(mapWidth);
00097         float sy = mapy * size_ / float(mapHeight);
00098         float sw = mapw * size_ / float(mapWidth); // Make sure the size is scaled
00099         if (sx < 0 || sx >= size_ || sy < 0 || sy >= size_)
00100         {
00101                 return;
00102         }
00103 
00104         shadowCount_++;
00105         const GLubyte minNum = 64;
00106         int decrement = int(opacity * 200.0f);
00107         float halfW = sw / 2.0f;
00108 
00109         float minX = sx - halfW;
00110         float minY = sy - halfW;
00111         float maxX = sx + halfW;
00112         float maxY = sy + halfW;
00113 
00114         minX = MAX(minX, 0.0f);
00115         minY = MAX(minY, 0.0f);
00116         maxX = MIN(maxX, size_ - 1.0f);
00117         maxY = MIN(maxY, size_ - 1.0f);
00118 
00119         int iSize = int(size_);
00120         int xStart = int(minX);
00121         int yStart = int(minY);
00122         int xWidth = int(maxX - minX);
00123         int yWidth = int(maxY - minY);
00124         int yInc = size_ - xWidth;
00125         if (xWidth <= 0 || yWidth <= 0) return;
00126 
00127         if (circle)
00128         {
00129                 static float sintable[100];
00130                 static bool sintablemade = false;
00131                 if (!sintablemade)
00132                 {
00133                         sintablemade = true;
00134                         float degMult = 0.0314f;
00135                         for (int i=0; i<100; i++)
00136                         {
00137                                 float deg = float(i) * degMult;
00138                                 sintable[i] = sinf(deg);
00139                         }
00140                 }
00141                 GLubyte *start = &shadowBytes_[(yStart * iSize) + xStart];
00142                 for (int y=0; y<yWidth; y++, start += yInc)
00143                 {
00144                         int deg = (y * 90) / yWidth;
00145                         int realXSize = int(sintable[deg] * xWidth);
00146                         int halfSize = (xWidth - realXSize) / 2;
00147 
00148                         start+=halfSize;
00149                         int x;
00150                         for (x=0; x<realXSize; x++, start++)
00151                         {
00152                                 if (*start > decrement + minNum) (*start) -= (GLubyte) (decrement);
00153                                 else (*start = minNum);
00154                         }
00155                         start+=xWidth - (halfSize + x);
00156                 }
00157         }
00158         else
00159         {
00160                 GLubyte *start = &shadowBytes_[(yStart * iSize) + xStart];
00161                 for (int y=0; y<yWidth; y++, start += yInc)
00162                 {
00163                         for (int x=0; x<xWidth; x++, start++)
00164                         {
00165                                 if (*start > decrement + minNum) (*start) -= (GLubyte) decrement;
00166                                 else (*start = minNum);
00167                         }
00168                 }
00169         }
00170 }

Generated on Mon Feb 16 15:14:47 2009 for Scorched3D by  doxygen 1.5.3