00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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
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 }