00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00078 int treeMapMultWidth = groundMapWidth / 64;
00079 int treeMapMultHeight = groundMapHeight / 64;
00080 for (int i=0; i<numclusters; i++)
00081 {
00082
00083 int x = (generator.getRandFixed() * 64).asInt();
00084 int y = (generator.getRandFixed() * 64).asInt();
00085
00086
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
00106
00107 int n = (generator.getRandFixed() * 10).asInt() + 5;
00108 for (int j=0; j<n; j++)
00109 {
00110
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
00134 objectMap[x + 64 * y] = 255;
00135 }
00136 }
00137
00138
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);
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
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
00178
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 }