TargetLife.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 <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); // Updates space too
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 &currentPosition = getCenterPosition();
00128         FixedVector direction = position - currentPosition;
00129         fixed dist = 0;
00130 
00131         // Get how close the explosion was
00132         if (getBoundingSphere())
00133         {
00134                 // Find how close the explosion was to the 
00135                 // outside of the sphere
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                 // Make the direction relative to the geom
00143                 // incase the geom has been rotated
00144                 FixedVector relativeDirection;
00145                 quaternion_.getRelativeVector(relativeDirection, direction);
00146 
00147                 // Find how close the explosion was to the 
00148                 // outside edge of the cube
00149                 FixedVector touchPosition = relativeDirection;
00150 
00151                 // Check each size of the cube to see if the point is outside.
00152                 // If it is, then scale it back until the point sits on the
00153                 // outside edge of the cube.
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                                 // Scale the point so it sits on this edge
00161                                 fixed diff = -halfSize / touchPosition[i];
00162                                 touchPosition *= diff;
00163                         }
00164                         else if (touchPosition[i] > halfSize)
00165                         {
00166                                 // Scale the point so it sits on this edge
00167                                 fixed diff = halfSize / touchPosition[i];
00168                                 touchPosition *= diff;
00169                         }
00170                         else inner++; // The point is inside this edge
00171                 }
00172 
00173                 if (inner == 3)
00174                 {
00175                         // We are inside the cube
00176                         dist = 0;
00177                 }
00178                 else
00179                 {
00180                         // We are outside the cube
00181                         relativeDirection -= touchPosition;
00182                         dist = relativeDirection.Magnitude();
00183                 }
00184         }
00185 
00186         return dist;
00187 }
00188 
00189 bool TargetLife::collision(FixedVector &position)
00190 {
00191         FixedVector &currentPosition = getCenterPosition();
00192         FixedVector direction = position - currentPosition;
00193 
00194         // Check against bounding box
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         // Check against actual bounds
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                 // Make the direction relative to the geom
00214                 // incase the geom has been rotated
00215                 FixedVector relativeDirection;
00216                 quaternion_.getRelativeVector(relativeDirection, direction);
00217 
00218                 // Check each side of the cube to see if the point is inside it
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++; // The point is inside this edge
00227                         }
00228                 }
00229 
00230                 // We need the point to be inside each of the 6 edges
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; // Suppress target space updates
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         // Update target space
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 }

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