DeformLandscape.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 <landscapemap/DeformLandscape.h>
00022 #include <landscapemap/LandscapeMaps.h>
00023 #include <landscapedef/LandscapeTex.h>
00024 #include <landscapedef/LandscapeDefinition.h>
00025 #include <target/TargetContainer.h>
00026 #include <target/TargetLife.h>
00027 #include <target/TargetSpace.h>
00028 #include <target/TargetState.h>
00029 #include <engine/ScorchedContext.h>
00030 #include <engine/ActionController.h>
00031 #include <common/OptionsScorched.h>
00032 #include <common/Defines.h>
00033 #include <common/ProgressCounter.h>
00034 #include <lang/LangResource.h>
00035 #include <math.h>
00036 
00037 std::vector<DeformLandscape::DeformInfo> DeformLandscape::deformInfos_;
00038 
00039 bool DeformLandscape::deformLandscape(
00040         ScorchedContext &context,
00041         FixedVector &pos, fixed radius, bool down, DeformPoints &map)
00042 {
00043         if (context.getOptionsGame().getActionSyncCheck())
00044         {
00045                 context.getActionController().addSyncCheck(
00046                         S3D::formatStringBuffer("Deform : %i,%i,%i %i %s", 
00047                                 pos[0].getInternal(), pos[1].getInternal(), pos[2].getInternal(), 
00048                                 radius.getInternal(), (down?"Down":"Up")));
00049         }
00050 
00051         bool hits = deformLandscapeInternal(context, pos, radius, down, map, true);
00052         if (hits && context.getServerMode())
00053         {
00054                 DeformInfo deformInfo;
00055                 deformInfo.type = down?eDeformLandscapeDown:eDeformLandscapeUp;
00056                 deformInfo.pos = pos;
00057                 deformInfo.radius = radius;
00058                 deformInfos_.push_back(deformInfo);
00059         }
00060 
00061         return hits;
00062 }
00063 
00064 bool DeformLandscape::deformLandscapeInternal(
00065         ScorchedContext &context,
00066         FixedVector &pos, fixed radius, bool down, DeformPoints &map, 
00067         bool setNormals)
00068 {
00069         HeightMap &hmap = context.getLandscapeMaps().getGroundMaps().getHeightMap();
00070 
00071         bool hits = false;
00072         int iradius = (int) radius.asInt() + 1;
00073         if (iradius > 49) iradius = 49;
00074 
00075         fixed lowestHeight = fixed(0);
00076 
00077         // Take out or add a chunk into the landsacpe
00078         for (int x=-iradius; x<=iradius; x++)
00079         {
00080                 for (int y=-iradius; y<=iradius; y++)
00081                 {
00082                         DIALOG_ASSERT(x+iradius<100 && y+iradius<100);
00083                         map.map[x+iradius][y+iradius] = fixed(-1);
00084 
00085                         FixedVector newPos(pos[0] + x, pos[1] + y, pos[2]);
00086                         if ((newPos[0] >= fixed(0)) && (newPos[0] < hmap.getMapWidth()) &&
00087                                 (newPos[1] >= fixed(0)) && (newPos[1] < hmap.getMapHeight()))
00088                         {
00089                                 fixed dist = (pos - newPos).Magnitude();
00090 
00091                                 if (dist < radius)
00092                                 {
00093                                         fixed distToRadius = radius - dist;
00094                                         fixed currentHeight = hmap.getHeight(newPos[0].asInt(), newPos[1].asInt());
00095                                         fixed explosionDepth = ((distToRadius / radius) * fixed::XPIO2).sin() * radius;
00096 
00097                                         fixed newHeight = currentHeight;
00098                                         fixed newMap = fixed(-1);
00099                                         if (down)
00100                                         {
00101                                                 if (currentHeight > newPos[2] - explosionDepth)
00102                                                 {
00103                                                         newMap = fixed(1) - (dist / radius);
00104                                                         newMap *= fixed(3);
00105                                                         if (newMap > fixed(1)) newMap = fixed(1);
00106 
00107                                                         if (currentHeight > newPos[2] + explosionDepth)
00108                                                         {
00109                                                                 newHeight -= explosionDepth + explosionDepth;
00110                                                         }
00111                                                         else
00112                                                         {
00113                                                                 newHeight = newPos[2] - explosionDepth;
00114                                                         }
00115 
00116                                                         if (newHeight < lowestHeight)
00117                                                         {
00118                                                                 if (currentHeight < lowestHeight)
00119                                                                 {
00120                                                                         newHeight = currentHeight;
00121                                                                 }
00122                                                                 else
00123                                                                 {
00124                                                                         newHeight = lowestHeight;
00125                                                                 }
00126                                                         }
00127                                                 }
00128                                         }
00129                                         else
00130                                         {
00131                                                 newMap = fixed(1) - (dist / radius);
00132                                                 newMap *= fixed(3);
00133                                                 if (newMap > fixed(1)) newMap = fixed(1);
00134 
00135                                                 if (currentHeight < newPos[2] + explosionDepth)
00136                                                 {
00137                                                         if (newPos[0] == 0 || newPos[1] == 0 ||
00138                                                                 newPos[0] == hmap.getMapWidth() -1 ||
00139                                                                 newPos[1] == hmap.getMapHeight() -1)
00140                                                         {
00141                                                         }
00142                                                         else
00143                                                         {
00144                                                                 newHeight = newPos[2] + explosionDepth;
00145                                                         }
00146                                                 }
00147                                         }
00148 
00149                                         if (newHeight != currentHeight)
00150                                         {
00151                                                 hits = true;
00152                                                 hmap.setHeight(newPos[0].asInt(), newPos[1].asInt(), newHeight);
00153                                         }
00154                                         map.map[x+iradius][y+iradius] = newMap;
00155                                 }
00156                         }
00157                 }
00158         }
00159 
00160         if (hits && setNormals)
00161         {
00162                 // Take out or add a chunk into the landsacpe
00163                 for (int x=-iradius-3; x<=iradius+3; x++)
00164                 {
00165                         for (int y=-iradius-3; y<=iradius+3; y++)
00166                         {
00167                                 FixedVector newPos(pos[0] + x, pos[1] + y, pos[2]);
00168                                 if ((newPos[0] >= fixed(0)) && (newPos[0] < hmap.getMapWidth()) &&
00169                                         (newPos[1] >= fixed(0)) && (newPos[1] < hmap.getMapHeight()))
00170                                 {
00171                                         hmap.getNormal(newPos[0].asInt(), newPos[1].asInt());
00172                                 }
00173                         }
00174                 }
00175         }
00176 
00177         return hits;
00178 }
00179 
00180 void DeformLandscape::flattenArea(
00181         ScorchedContext &context, FixedVector &tankPos, 
00182         bool removeObjects, fixed size)
00183 {
00184         if (context.getOptionsGame().getActionSyncCheck())
00185         {
00186                 context.getActionController().addSyncCheck(
00187                         S3D::formatStringBuffer("Flatten : %i,%i,%i %i", 
00188                         tankPos[0].getInternal(), tankPos[1].getInternal(), tankPos[2].getInternal(), 
00189                         size.getInternal()));
00190         }
00191 
00192         flattenAreaInternal(context, tankPos, removeObjects, size, true);
00193         if (context.getServerMode())
00194         {
00195                 DeformInfo deformInfo;
00196                 deformInfo.type = eFlattenArea;
00197                 deformInfo.pos = tankPos;
00198                 deformInfo.radius = size;
00199                 deformInfos_.push_back(deformInfo);
00200         }
00201 
00202         if (removeObjects)
00203         {
00204                 // Remove any targets in this location
00205                 std::map<unsigned int, Target *> collisionTargets;
00206                 context.getTargetSpace().getCollisionSet(tankPos, size * fixed(true, 15000), collisionTargets);
00207                 std::map<unsigned int, Target *>::iterator itor;
00208                 for (itor = collisionTargets.begin();
00209                         itor != collisionTargets.end();
00210                         itor++)
00211                 {
00212                         Target *target = (*itor).second;
00213                         if (target->isTarget() &&
00214                                 target->getTargetState().getFlattenDestroy())
00215                         {
00216                                 Target *removedTarget = 
00217                                         context.getTargetContainer().removeTarget(target->getPlayerId());
00218                                 delete removedTarget;
00219                         }
00220                 }
00221         }
00222 }
00223 
00224 
00225 void DeformLandscape::flattenAreaInternal(
00226         ScorchedContext &context, FixedVector &tankPos, 
00227         bool removeObjects, fixed size, bool setNormals)
00228 {
00229         int iSize = size.asInt();
00230         HeightMap &hmap = context.getLandscapeMaps().getGroundMaps().getHeightMap();
00231         int posX = tankPos[0].asInt();
00232         int posY = tankPos[1].asInt();
00233 
00234         // Flatten a small area around the tank
00235         for (int x=-iSize; x<=iSize; x++)
00236         {
00237                 for (int y=-iSize; y<=iSize; y++)
00238                 {
00239                         int ix = posX + x;
00240                         int iy = posY + y;
00241                         if (ix >= 0 && iy >= 0 &&
00242                                 ix < hmap.getMapWidth() &&
00243                                 iy < hmap.getMapHeight())
00244                         {
00245                                 hmap.setHeight(ix, iy, tankPos[2]);
00246                         }
00247                 }
00248         }
00249 
00250         if (setNormals)
00251         {
00252                 for (int x=-iSize-3; x<=iSize+3; x++)
00253                 {
00254                         for (int y=-iSize-3; y<=iSize+3; y++)
00255                         {
00256                                 int ix = posX + x;
00257                                 int iy = posY + y;
00258                                 if (ix >= 0 && iy >= 0 &&
00259                                         ix < hmap.getMapWidth() &&
00260                                         iy < hmap.getMapHeight())
00261                                 {
00262                                         hmap.getNormal(ix, iy);
00263                                 }
00264                         }
00265                 }
00266         }
00267 }
00268 
00269 void DeformLandscape::clearInfos()
00270 {
00271         deformInfos_.clear();
00272 }
00273 
00274 void DeformLandscape::applyInfos(ScorchedContext &context, 
00275         std::vector<DeformInfo> &infos,
00276         ProgressCounter *counter)
00277 {
00278         DeformPoints map;
00279 
00280         if (counter) counter->setNewOp(LANG_RESOURCE("LANDSCAPE_DIFFS", "Landscape Diffs"));
00281 
00282         deformInfos_.clear();
00283         int count = (int) infos.size();
00284         int i = 0;
00285         std::vector<DeformInfo>::iterator itor;
00286         for (itor = infos.begin();
00287                 itor != infos.end();
00288                 itor++, i++)
00289         {
00290                 if (counter) counter->setNewPercentage((100.0f * float(i)) / float(count));
00291 
00292                 DeformInfo &info = *itor;
00293                 switch (info.type)
00294                 {
00295                 case eDeformLandscapeUp:
00296                         deformLandscapeInternal(context, info.pos, info.radius, false, map, false);
00297                         break;
00298                 case eDeformLandscapeDown:
00299                         deformLandscapeInternal(context, info.pos, info.radius, true, map, false);
00300                         break;
00301                 case eFlattenArea:
00302                         flattenAreaInternal(context, info.pos, false, info.radius, false);
00303                 }
00304         }
00305 
00306         if (counter) counter->setNewOp(LANG_RESOURCE("LANDSCAPE_NORMALS", "Landscape Normals"));
00307         HeightMap &hmap = context.getLandscapeMaps().getGroundMaps().getHeightMap();
00308         for (int x=0; x<=hmap.getMapWidth(); x++)
00309         {
00310                 if (counter) counter->setNewPercentage((100.0f * float(x)) / float(hmap.getMapWidth()));
00311                 for (int y=0; y<=hmap.getMapHeight(); y++)
00312                 {
00313                         hmap.getNormal(x, y);
00314                 }
00315         }
00316 }

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