PlacementTypeTree.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 <placement/PlacementTypeTree.h>
00022 #include <landscapemap/LandscapeMaps.h>
00023 #include <engine/ScorchedContext.h>
00024 #include <common/ProgressCounter.h>
00025 #include <common/RandomGenerator.h>
00026 #include <common/Defines.h>
00027 #include <XML/XMLParser.h>
00028 #include <image/ImageBitmap.h>
00029 #include <image/ImageFactory.h>
00030 
00031 PlacementTypeTree::PlacementTypeTree() : 
00032         mincloseness(0), maxobjects(2000)
00033 {
00034 }
00035 
00036 PlacementTypeTree::~PlacementTypeTree()
00037 {
00038 }
00039 
00040 bool PlacementTypeTree::readXML(XMLNode *node)
00041 {
00042         node->getNamedChild("mask", mask, false);
00043         if (!node->getNamedChild("numobjects", numobjects)) return false;
00044         if (!node->getNamedChild("numclusters", numclusters)) return false;
00045         if (!node->getNamedChild("minheight", minheight)) return false;
00046         if (!node->getNamedChild("maxheight", maxheight)) return false;
00047         node->getNamedChild("mincloseness", mincloseness, false);
00048         node->getNamedChild("maxobjects", maxobjects, false);
00049         return PlacementType::readXML(node);
00050 }
00051 
00052 void PlacementTypeTree::getPositions(ScorchedContext &context,
00053         RandomGenerator &generator,
00054         std::list<Position> &returnPositions,
00055         ProgressCounter *counter)
00056 {
00057         ImageBitmap bmap(256, 256);
00058         ImageHandle map = bmap;
00059         if (mask.c_str()[0])
00060         {       
00061                 map = ImageFactory::loadImageHandle(S3D::getDataFile(mask.c_str()));
00062                 if (!map.getBits())
00063                 {
00064                         S3D::dialogExit("PlacementTypeTree",
00065                                 S3D::formatStringBuffer("Error: failed to find mask \"%s\"",
00066                                 mask.c_str()));
00067                 }
00068         }
00069 
00070         // Generate a map of where the trees should go
00071         unsigned char objectMap[64 * 64];
00072         memset(objectMap, 0, sizeof(unsigned char) * 64 * 64);
00073 
00074         int groundMapWidth = context.getLandscapeMaps().getGroundMaps().getLandscapeWidth();
00075         int groundMapHeight = context.getLandscapeMaps().getGroundMaps().getLandscapeHeight();
00076 
00077         // A few points where trees will be clustered around
00078         int treeMapMultWidth  = groundMapWidth / 64;
00079         int treeMapMultHeight = groundMapHeight / 64;
00080         for (int i=0; i<numclusters; i++)
00081         {
00082                 // Get a random point
00083                 int x = (generator.getRandFixed() * 64).asInt();
00084                 int y = (generator.getRandFixed() * 64).asInt();
00085 
00086                 // Check point is in the correct height band
00087                 fixed height = 
00088                         context.getLandscapeMaps().
00089                                 getGroundMaps().getHeight(
00090                                         x * treeMapMultWidth, y * treeMapMultHeight);
00091                 FixedVector &normal =
00092                         context.getLandscapeMaps().
00093                                 getGroundMaps().getNormal(
00094                                         x * treeMapMultWidth, y * treeMapMultHeight);
00095 
00096                 int mx = int(map.getWidth() * (fixed(x) / 64).asInt());
00097                 int my = int(map.getHeight() * (fixed(y) / 64).asInt());
00098                 unsigned char *bits = map.getBits() +
00099                         mx * 3 + my * map.getWidth() * 3;
00100                 if (bits[0] > 127 &&
00101                         height > minheight && 
00102                         height < maxheight && 
00103                         normal[2] > fixed(true, 7000))
00104                 {
00105                         // Group other areas around this point that are likely to get trees
00106                         // Do a few groups
00107                         int n = (generator.getRandFixed() * 10).asInt() + 5;
00108                         for (int j=0; j<n; j++)
00109                         {
00110                                 // Check groups is within bounds
00111                                 int newX = x + (generator.getRandFixed() * 8).asInt() - 4;
00112                                 int newY = y + (generator.getRandFixed() * 8).asInt() - 4;
00113                                 if (newX >= 0 && newX < 64 &&
00114                                         newY >= 0 && newY < 64)
00115                                 {
00116                                         FixedVector &normal =
00117                                                 context.getLandscapeMaps().
00118                                                 getGroundMaps().getNormal(
00119                                                         newX * treeMapMultWidth, newY * treeMapMultHeight);
00120                                         height = 
00121                                                 context.getLandscapeMaps().
00122                                                 getGroundMaps().getHeight(
00123                                                         newX * treeMapMultWidth, newY * treeMapMultHeight);
00124                                         if (height > minheight && 
00125                                                 height < maxheight && 
00126                                                 normal[2] > fixed(true, 7000))
00127                                         {
00128                                                 objectMap[newX + 64 * newY] = 64;
00129                                         }
00130                                 }
00131                         }
00132 
00133                         // Add the original point
00134                         objectMap[x + 64 * y] = 255;
00135                 }
00136         }
00137 
00138         // Smooth the treemap
00139         unsigned char objectMapCopy[64 * 64];
00140         memcpy(objectMapCopy, objectMap, sizeof(unsigned char) * 64 * 64);
00141         fixed matrix[3][3];
00142         for (int i=0; i<3; i++)
00143         {
00144                 for (int j=0; j<3; j++)
00145                 {
00146                         matrix[i][j] = fixed(true, 7000); // How much smoothing is done (> is more)
00147                         if (i==1 && j==1) matrix[i][j] = 4;
00148                 }
00149         }
00150         for (int y=0; y<64; y++)
00151         {
00152                 for (int x=0; x<64; x++)
00153                 {
00154                         // Total is used to catch corner cases
00155                         fixed total = 0;
00156                         fixed inc = 0;
00157                         for (int i=0; i<3; i++)
00158                         {
00159                                 for (int j=0; j<3; j++)
00160                                 {
00161                                         int newX = i + x - 1;
00162                                         int newY = j + y - 1;
00163                                         
00164                                         if (newX >= 0 && newX < 64 &&
00165                                                 newY >= 0 && newY < 64)
00166                                         {
00167                                                 inc += objectMapCopy[newX + 64 * newY];
00168                                                 total += matrix[i][j];
00169                                         }
00170                                 }
00171                         }
00172          
00173                         objectMap[x + 64 * y] = (unsigned char)(inc/total).asInt();
00174                 }
00175         }
00176 
00177         // Add lots of trees, more chance of adding a tree where
00178         // the map is stongest
00179         int objectCount = 0;
00180         const int NoIterations = numobjects;
00181         for (int i=0; i<NoIterations && objectCount < maxobjects; i++)
00182         {
00183                 if (i % 1000 == 0) if (counter) 
00184                         counter->setNewPercentage(
00185                                 MAX(float(i)/float(NoIterations), float(objectCount) / float(maxobjects)) *100.0f);
00186 
00187                 fixed lx = generator.getRandFixed() * fixed(groundMapWidth);
00188                 fixed ly = generator.getRandFixed() * fixed(groundMapHeight);
00189                 int rx = (lx.asInt());
00190                 int ry = (ly.asInt());
00191                 int nx = rx / treeMapMultWidth;
00192                 int ny = ry / treeMapMultHeight;
00193                 int r = objectMap[nx + 64 * ny];
00194                 int nr = (generator.getRandFixed() * 512).asInt();
00195 
00196                 if (nr < r)
00197                 {
00198                         fixed height = 
00199                                 context.getLandscapeMaps().
00200                                         getGroundMaps().getInterpHeight(lx, ly);
00201 
00202                         if (height > minheight + fixed(true, 5000))
00203                         {
00204                                 objectCount ++;
00205                                 Position position;
00206                                 position.position[0] = lx;
00207                                 position.position[1] = ly;
00208                                 position.position[2] = height;
00209                                 if (checkCloseness(position.position, context, 
00210                                         returnPositions, mincloseness))
00211                                 {
00212                                         returnPositions.push_back(position);
00213                                 }
00214                         }
00215                 }
00216         }
00217 }

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