00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <target/TargetLife.h>
00022 #include <target/TargetRenderer.h>
00023 #include <target/TargetSpace.h>
00024 #include <target/TargetState.h>
00025 #include <target/TargetGroup.h>
00026 #include <target/Target.h>
00027 #include <tank/TankType.h>
00028 #include <engine/ScorchedContext.h>
00029 #include <engine/ActionController.h>
00030 #include <tankai/TankAIAdder.h>
00031 #include <common/Defines.h>
00032 #include <common/Logger.h>
00033
00034 TargetLife::TargetLife(ScorchedContext &context, unsigned int playerId) :
00035 context_(context), sphereGeom_(true),
00036 life_(0), maxLife_(1), target_(0),
00037 size_(2, 2, 2), floatBoundingSize_(0.0f)
00038 {
00039 }
00040
00041 TargetLife::~TargetLife()
00042 {
00043 life_ = 0;
00044 updateSpace();
00045 }
00046
00047 void TargetLife::newGame()
00048 {
00049 setLife(maxLife_);
00050 }
00051
00052 void TargetLife::setLife(fixed life)
00053 {
00054 life_ = life;
00055
00056 if (life_ >= maxLife_) life_ = maxLife_;
00057 if (life_ < 1)
00058 {
00059 life_ = 0;
00060 setRotation(0);
00061 target_->getGroup().removeFromAllGroups();
00062 }
00063 else
00064 {
00065 updateAABB();
00066 updateSpace();
00067 }
00068 }
00069
00070 void TargetLife::setSize(FixedVector &size)
00071 {
00072 size_ = size;
00073
00074 updateAABB();
00075 updateSpace();
00076 }
00077
00078 void TargetLife::setTargetPositionAndRotation(FixedVector &pos, fixed rotation)
00079 {
00080 targetPosition_ = pos;
00081 if (!context_.getServerMode()) targetPosition_.asVector(floatPosition_);
00082
00083 FixedVector zaxis(0, 0, 1);
00084 quaternion_.setQuatFromAxisAndAngle(zaxis, rotation / 180 * fixed::XPI);
00085 if (!context_.getServerMode()) quaternion_.getOpenGLRotationMatrix(floatRotMatrix_);
00086
00087 updateAABB();
00088 updateSpace();
00089 }
00090
00091 void TargetLife::setTargetPosition(FixedVector &pos)
00092 {
00093 targetPosition_ = pos;
00094 if (!context_.getServerMode()) targetPosition_.asVector(floatPosition_);
00095
00096 updateSpace();
00097 }
00098
00099 void TargetLife::setRotation(fixed rotation)
00100 {
00101 FixedVector zaxis(0, 0, 1);
00102 quaternion_.setQuatFromAxisAndAngle(zaxis, rotation / 180 * fixed::XPI);
00103 if (!context_.getServerMode()) quaternion_.getOpenGLRotationMatrix(floatRotMatrix_);
00104
00105 updateAABB();
00106 updateSpace();
00107 }
00108
00109 FixedVector &TargetLife::getCenterPosition()
00110 {
00111 static FixedVector result;
00112 result = getTargetPosition();
00113 result[2] += getSize()[2] / 2;
00114 return result;
00115 }
00116
00117 Vector &TargetLife::getFloatCenterPosition()
00118 {
00119 static Vector result;
00120 result = getFloatPosition();
00121 result[2] += getFloatAabbSize()[2] / 2.0f;
00122 return result;
00123 }
00124
00125 fixed TargetLife::collisionDistance(FixedVector &position)
00126 {
00127 FixedVector ¤tPosition = getCenterPosition();
00128 FixedVector direction = position - currentPosition;
00129 fixed dist = 0;
00130
00131
00132 if (getBoundingSphere())
00133 {
00134
00135
00136 fixed sphereRadius = MAX(MAX(size_[0], size_[1]), size_[2]) / 2;
00137 dist = direction.Magnitude() - sphereRadius;
00138 if (dist < 0) dist = 0;
00139 }
00140 else
00141 {
00142
00143
00144 FixedVector relativeDirection;
00145 quaternion_.getRelativeVector(relativeDirection, direction);
00146
00147
00148
00149 FixedVector touchPosition = relativeDirection;
00150
00151
00152
00153
00154 int inner = 0;
00155 for (int i=0; i<3; i++)
00156 {
00157 fixed halfSize = size_[i] / 2;
00158 if (touchPosition[i] < -halfSize)
00159 {
00160
00161 fixed diff = -halfSize / touchPosition[i];
00162 touchPosition *= diff;
00163 }
00164 else if (touchPosition[i] > halfSize)
00165 {
00166
00167 fixed diff = halfSize / touchPosition[i];
00168 touchPosition *= diff;
00169 }
00170 else inner++;
00171 }
00172
00173 if (inner == 3)
00174 {
00175
00176 dist = 0;
00177 }
00178 else
00179 {
00180
00181 relativeDirection -= touchPosition;
00182 dist = relativeDirection.Magnitude();
00183 }
00184 }
00185
00186 return dist;
00187 }
00188
00189 bool TargetLife::collision(FixedVector &position)
00190 {
00191 FixedVector ¤tPosition = getCenterPosition();
00192 FixedVector direction = position - currentPosition;
00193
00194
00195 if (direction[0] < -aabbSize_[0] ||
00196 direction[0] > aabbSize_[0] ||
00197 direction[1] < -aabbSize_[1] ||
00198 direction[1] > aabbSize_[1] ||
00199 direction[2] < -aabbSize_[2] ||
00200 direction[2] > aabbSize_[2])
00201 {
00202 return false;
00203 }
00204
00205
00206 if (sphereGeom_)
00207 {
00208 fixed radius = MAX(MAX(size_[0], size_[1]), size_[2]) / 2;
00209 if (direction.Magnitude() > radius) return false;
00210 }
00211 else
00212 {
00213
00214
00215 FixedVector relativeDirection;
00216 quaternion_.getRelativeVector(relativeDirection, direction);
00217
00218
00219 int inner = 0;
00220 for (int i=0; i<3; i++)
00221 {
00222 fixed halfSize = size_[i] / 2;
00223 if (-halfSize < relativeDirection[i] &&
00224 relativeDirection[i] < halfSize)
00225 {
00226 inner++;
00227 }
00228 }
00229
00230
00231 if (inner < 3) return false;
00232 }
00233
00234 return true;
00235 }
00236
00237 void TargetLife::setBoundingSphere(bool sphereGeom)
00238 {
00239 sphereGeom_ = sphereGeom;
00240
00241 updateAABB();
00242 updateSpace();
00243 }
00244
00245 void TargetLife::updateSpace()
00246 {
00247 if (target_->getRenderer()) target_->getRenderer()->moved();
00248 context_.getTargetSpace().updateTarget(target_);
00249 }
00250
00251 bool TargetLife::writeMessage(NetBuffer &buffer)
00252 {
00253 buffer.addToBuffer(maxLife_);
00254 buffer.addToBuffer(life_);
00255 buffer.addToBuffer(size_);
00256 buffer.addToBuffer(velocity_);
00257 buffer.addToBuffer(targetPosition_);
00258 buffer.addToBuffer(quaternion_);
00259 return true;
00260 }
00261
00262 bool TargetLife::readMessage(NetBufferReader &reader)
00263 {
00264 life_ = 0;
00265
00266 fixed newLife;
00267 if (!reader.getFromBuffer(maxLife_))
00268 {
00269 Logger::log("TargetLife::maxLife_ read failed");
00270 return false;
00271 }
00272 if (!reader.getFromBuffer(newLife))
00273 {
00274 Logger::log("TargetLife::life_ read failed");
00275 return false;
00276 }
00277
00278 FixedVector newSize;
00279 if (!reader.getFromBuffer(newSize))
00280 {
00281 Logger::log("TargetLife::size_ read failed");
00282 return false;
00283 }
00284 setSize(newSize);
00285
00286 if (!reader.getFromBuffer(velocity_))
00287 {
00288 Logger::log("TargetLife::velocity_ read failed");
00289 return false;
00290 }
00291
00292 FixedVector newPosition;
00293 if (!reader.getFromBuffer(newPosition))
00294 {
00295 Logger::log("TargetLife::targetPosition_ read failed");
00296 return false;
00297 }
00298 setTargetPosition(newPosition);
00299
00300 if (!reader.getFromBuffer(quaternion_))
00301 {
00302 Logger::log("TargetLife::quaternion_ read failed");
00303 return false;
00304 }
00305
00306
00307 setLife(newLife);
00308
00309 return true;
00310 }
00311
00312 void TargetLife::updateAABB()
00313 {
00314 if (sphereGeom_)
00315 {
00316 fixed radius = MAX(MAX(size_[0], size_[1]), size_[2]) / 2;
00317 aabbSize_ = FixedVector(radius * 2, radius * 2, radius * 2);
00318 }
00319 else
00320 {
00321 for (int i=0; i<8; i++)
00322 {
00323 FixedVector position;
00324 switch (i)
00325 {
00326 case 0:
00327 position = FixedVector(size_[0], size_[1], size_[2]);
00328 break;
00329 case 1:
00330 position = FixedVector(-size_[0], size_[1], size_[2]);
00331 break;
00332 case 2:
00333 position = FixedVector(size_[0], -size_[1], size_[2]);
00334 break;
00335 case 3:
00336 position = FixedVector(-size_[0], -size_[1], size_[2]);
00337 break;
00338 case 4:
00339 position = FixedVector(size_[0], size_[1], -size_[2]);
00340 break;
00341 case 5:
00342 position = FixedVector(-size_[0], size_[1], -size_[2]);
00343 break;
00344 case 6:
00345 position = FixedVector(size_[0], -size_[1], -size_[2]);
00346 break;
00347 case 7:
00348 position = FixedVector(-size_[0], -size_[1], -size_[2]);
00349 break;
00350 }
00351
00352 FixedVector result;
00353 quaternion_.getRelativeVector(result, position);
00354
00355 if (i == 0) aabbSize_ = result;
00356 else
00357 {
00358 aabbSize_[0] = MAX(aabbSize_[0], result[0]);
00359 aabbSize_[1] = MAX(aabbSize_[1], result[1]);
00360 aabbSize_[2] = MAX(aabbSize_[2], result[2]);
00361 }
00362 }
00363 }
00364 if (!context_.getServerMode())
00365 {
00366 aabbSize_.asVector(floatAabbSize_);
00367 floatBoundingSize_ = floatAabbSize_.Max();
00368 }
00369 }