TargetRendererImpl.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 <tankgraph/TargetRendererImpl.h>
00022 #include <tankgraph/TargetParticleRenderer.h>
00023 #include <target/TargetShield.h>
00024 #include <target/TargetState.h>
00025 #include <target/TargetLife.h>
00026 #include <client/ScorchedClient.h>
00027 #include <graph/ParticleEngine.h>
00028 #include <graph/OptionsDisplay.h>
00029 #include <common/Defines.h>
00030 #include <sky/Hemisphere.h>
00031 #include <weapons/ShieldRound.h>
00032 #include <weapons/ShieldSquare.h>
00033 #include <weapons/Accessory.h>
00034 #include <actions/TankFalling.h>
00035 #include <GLEXT/GLState.h>
00036 #include <GLEXT/GLTexture.h>
00037 #include <image/ImageFactory.h>
00038 #include <GLEXT/GLViewPort.h>
00039 #include <GLEXT/GLCameraFrustum.h>
00040 #include <GLEXT/GLCamera.h>
00041 #include <land/VisibilityPatchGrid.h>
00042 
00043 TargetRendererImpl::HighlightType TargetRendererImpl::highlightType_ = 
00044         TargetRendererImpl::eNoHighlight;
00045 
00046 TargetRendererImpl::TargetRendererImpl(Target *target) : 
00047         target_(target),
00048         particleMade_(false), tree_(false), matrixCached_(false),
00049         posX_(0.0f), posY_(0.0f), posZ_(0.0f),
00050         currentVisibilityPatch_(0), patchEpoc_(-1)
00051 {
00052 
00053 }
00054 
00055 TargetRendererImpl::~TargetRendererImpl()
00056 {
00057         setMovedPatch(0);
00058 }
00059 
00060 void TargetRendererImpl::moved()
00061 {
00062         if (VisibilityPatchGrid::instance()->getEpocNumber() == 0) return;
00063 
00064         TargetVisibilityPatch *newPatch = 0;
00065         if (target_->getAlive())
00066         {
00067                 FixedVector &position = target_->getLife().getTargetPosition();
00068                 newPatch = VisibilityPatchGrid::instance()->getTargetVisibilityPatch(
00069                         position[0].asInt(), position[1].asInt());
00070         }
00071         setMovedPatch(newPatch);
00072         matrixCached_ = false;
00073 }
00074 
00075 void TargetRendererImpl::setMovedPatch(TargetVisibilityPatch *newPatch)
00076 {
00077         float boundingSize = target_->getLife().getFloatBoundingSize();
00078         if (boundingSize > 32.0f) // Landscape square size
00079         {
00080                 if (newPatch) TargetVisibilityPatch::addLargeTarget(target_);
00081                 else TargetVisibilityPatch::removeLargeTarget(target_);
00082 
00083                 return;
00084         }
00085 
00086         if (patchEpoc_ != VisibilityPatchGrid::instance()->getEpocNumber())
00087         {
00088                 currentVisibilityPatch_ = 0;
00089                 patchEpoc_ = VisibilityPatchGrid::instance()->getEpocNumber();
00090         }
00091         if (newPatch != currentVisibilityPatch_)
00092         {
00093                 if (currentVisibilityPatch_)
00094                 {
00095                         if (!tree_)
00096                         {
00097                                 currentVisibilityPatch_->removeTarget(target_);
00098                                 if (!target_->getTargetName().empty()) 
00099                                         currentVisibilityPatch_->removeTooltip(target_);
00100                         }
00101                         else 
00102                         {
00103                                 currentVisibilityPatch_->removeTree(target_);
00104                         }
00105                 }
00106                 if (newPatch)
00107                 {
00108                         if (!tree_)
00109                         {
00110                                 newPatch->addTarget(target_);
00111                                 if (!target_->getTargetName().empty()) 
00112                                         newPatch->addTooltip(target_);
00113                         }
00114                         else 
00115                         {
00116                                 newPatch->addTree(target_);
00117                         }
00118                 }
00119                 currentVisibilityPatch_ = newPatch;
00120         }
00121 }
00122 
00123 bool TargetRendererImpl::getVisible()
00124 {
00125         if (!currentVisibilityPatch_ || !currentVisibilityPatch_->getVisible()) return false;
00126         if (!target_->getAlive()) return false;
00127 
00128         return true;
00129 }
00130 
00131 void TargetRendererImpl::drawShield(float shieldHit, float totalTime)
00132 {
00133         // Create the shield textures
00134         static GLTexture *shieldtexture = 0;
00135         static GLTexture *texture = 0;
00136         static GLTexture *texture2 = 0;
00137         static GLTexture *magtexture = 0;
00138         static GLUquadric *obj = 0;
00139         if (!texture)
00140         {
00141                 std::string file1 = S3D::getDataFile("data/textures/bordershield/grid2.bmp");
00142                 ImageHandle map = ImageFactory::loadImageHandle(file1.c_str(), file1.c_str(), false);
00143                 texture = new GLTexture;
00144                 texture->create(map, true);
00145 
00146                 std::string file2 = S3D::getDataFile("data/textures/bordershield/grid22.bmp");
00147                 ImageHandle map2 = ImageFactory::loadImageHandle(file2.c_str(), file2.c_str(), false);
00148                 texture2 = new GLTexture;
00149                 texture2->create(map2, true);
00150 
00151                 std::string file3 = S3D::getDataFile("data/textures/shield2.bmp");
00152                 ImageHandle map3 = ImageFactory::loadImageHandle(file3.c_str(), file3.c_str(), false);
00153                 magtexture = new GLTexture;
00154                 magtexture->create(map3, true);
00155 
00156                 std::string file4 = S3D::getDataFile("data/textures/shield.bmp");
00157                 std::string file5 = S3D::getDataFile("data/textures/shielda.bmp");
00158                 ImageHandle map4 = ImageFactory::loadImageHandle(file4.c_str(), file5.c_str(), false);
00159                 //map4.alphaMult(4.0f);
00160                 shieldtexture = new GLTexture;
00161                 shieldtexture->create(map4, true);
00162 
00163                 obj = gluNewQuadric();
00164                 gluQuadricTexture(obj, GL_TRUE);
00165         }
00166 
00167         // Create the shield objects
00168         static unsigned int squareListNo = 0;
00169         static unsigned int smallListNo = 0;
00170         static unsigned int smallHalfListNo = 0;
00171         static unsigned int spiralListNo = 0;
00172         GLTexture magTexture;
00173         if (!smallListNo)
00174         {
00175                 glNewList(smallListNo = glGenLists(1), GL_COMPILE);
00176                         gluSphere(obj, 1.0f, 8, 8);
00177                 glEndList();
00178                 glNewList(squareListNo = glGenLists(1), GL_COMPILE);
00179                         glBegin(GL_QUADS);              // Draw The Cube Using quads
00180                                 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, 1.0f,-1.0f);        // Top Right Of The Quad (Top)
00181                                 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, 1.0f,-1.0f);        // Top Left Of The Quad (Top)
00182                                 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);        // Bottom Left Of The Quad (Top)
00183                                 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);        // Bottom Right Of The Quad (Top)
00184 
00185                                 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 1.0f);        // Top Right Of The Quad (Bottom)
00186                                 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 1.0f);        // Top Left Of The Quad (Bottom)
00187                                 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,-1.0f,-1.0f);        // Bottom Left Of The Quad (Bottom)
00188                                 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,-1.0f,-1.0f);        // Bottom Right Of The Quad (Bottom)
00189 
00190                                 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);        // Top Right Of The Quad (Front)
00191                                 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);        // Top Left Of The Quad (Front)
00192                                 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f);        // Bottom Left Of The Quad (Front)
00193                                 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f);        // Bottom Right Of The Quad (Front)
00194 
00195                                 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f,-1.0f,-1.0f);        // Top Right Of The Quad (Back)
00196                                 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f,-1.0f,-1.0f);        // Top Left Of The Quad (Back)
00197                                 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f,-1.0f);        // Bottom Left Of The Quad (Back)
00198                                 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f,-1.0f);        // Bottom Right Of The Quad (Back)
00199 
00200                                 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);        // Top Right Of The Quad (Left)
00201                                 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, 1.0f,-1.0f);        // Top Left Of The Quad (Left)
00202                                 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,-1.0f,-1.0f);        // Bottom Left Of The Quad (Left)
00203                                 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f);        // Bottom Right Of The Quad (Left)
00204 
00205                                 glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, 1.0f,-1.0f);        // Top Right Of The Quad (Right)
00206                                 glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);        // Top Left Of The Quad (Right)
00207                                 glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f);        // Bottom Left Of The Quad (Right)
00208                                 glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,-1.0f,-1.0f);        // Bottom Right Of The Quad (Right)
00209                         glEnd();
00210                 glEndList();
00211                 glNewList(smallHalfListNo = glGenLists(1), GL_COMPILE);
00212                         Hemisphere::draw(1.0f, 1.0f, 10, 10, 6, 0, 10, 10, true);
00213                         Hemisphere::draw(1.0f, 1.0f, 10, 10, 6, 0, 10, 10, false);
00214                 glEndList();
00215                 glNewList(spiralListNo = glGenLists(1), GL_COMPILE);
00216                         float height = 0.0f;
00217                         float width = 0.0f;
00218                         float totalA = 5.0f * PI;
00219                         float aInc = PI / 6.0f;
00220                         glBegin(GL_QUAD_STRIP);
00221                         for (float a=0.0f; a<totalA; a+=aInc)
00222                         {
00223                                 height += 0.05f;
00224                                 width += 0.05f;
00225                                 float x = getFastSin(a) * width;
00226                                 float y = getFastCos(a) * width;
00227                                 float z = height;
00228                                 glTexCoord2f(a / totalA, 0.0f);
00229                                 glVertex3f(x, y, z);
00230                                 glTexCoord2f(a / totalA, 1.0f);
00231                                 glVertex3f(x, y, z - 0.4f);
00232                         }
00233                         glEnd();
00234 
00235                         height = 0.0f;
00236                         width = 0.0f;
00237                         glBegin(GL_QUAD_STRIP);
00238                         for (float a=0.0f; a<5.0f * PI; a+=PI/6.0f)
00239                         {
00240                                 height += 0.05f;
00241                                 width += 0.05f;
00242                                 float x = getFastSin(a) * width;
00243                                 float y = getFastCos(a) * width;
00244                                 float z = height;
00245                                 glTexCoord2f(a / totalA, 0.0f);
00246                                 glVertex3f(x, y, z - 0.4f);
00247                                 glTexCoord2f(a / totalA, 1.0f);
00248                                 glVertex3f(x, y, z);
00249                         }
00250                         glEnd();
00251                 glEndList();
00252         }
00253 
00254         // Draw the actual shield
00255         Accessory *accessory = target_->getShield().getCurrentShield();
00256         if (!accessory) return;
00257         Shield *shield = (Shield *) accessory->getAction();
00258 
00259         GLState state(GLState::BLEND_ON | GLState::TEXTURE_ON); 
00260         Vector &position = target_->getLife().getFloatPosition();
00261         Vector &color = shield->getColor();
00262 
00263         if (shield->getRound())
00264         {
00265                 ShieldRound *round = (ShieldRound *) shield;
00266                 if (shield->getShieldType() == Shield::ShieldTypeRoundMag)
00267                 {
00268                         magtexture->draw();
00269 
00270                         glDepthMask(GL_FALSE);
00271                         glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00272                         glColor4f(color[0], color[1], color[2], 0.4f);
00273                         glPushMatrix();
00274                                 glTranslatef(position[0], position[1], position[2] + 1.0f);
00275                                 float scale = round->getActualRadius().asFloat() / 3.0f;
00276                                 glScalef(scale, scale, scale);
00277 
00278                                 glRotatef(totalTime * 800.0f, 0.0f, 0.0f, 1.0f);
00279                                 glCallList(spiralListNo);
00280                                 glRotatef(120.0f, 0.0f, 0.0f, 1.0f);
00281                                 glCallList(spiralListNo);
00282                                 glRotatef(120.0f, 0.0f, 0.0f, 1.0f);
00283                                 glCallList(spiralListNo);
00284                         glPopMatrix();
00285                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00286                         glDepthMask(GL_TRUE);
00287                 }
00288                 else if (round->getHalfShield())
00289                 {
00290                         texture->draw();
00291                         glPushMatrix();
00292                                 glColor4f(color[0], color[1], color[2], 0.5f + shieldHit);
00293                                 glTranslatef(position[0], position[1], position[2]);
00294                                 glScalef(
00295                                         round->getActualRadius().asFloat(), 
00296                                         round->getActualRadius().asFloat(), 
00297                                         round->getActualRadius().asFloat());
00298                                 glCallList(smallHalfListNo);
00299                         glPopMatrix();
00300                 }
00301                 else
00302                 {
00303                         texture->draw();
00304                         glPushMatrix();
00305                                 glColor4f(color[0], color[1], color[2], 0.5f + shieldHit);
00306                                 glTranslatef(position[0], position[1], position[2]);
00307                                 glScalef(
00308                                         round->getActualRadius().asFloat(), 
00309                                         round->getActualRadius().asFloat(), 
00310                                         round->getActualRadius().asFloat());
00311                                 glCallList(smallListNo);
00312                         glPopMatrix();
00313 
00314                         if (round->getGlow())
00315                         {
00316                                 shieldtexture->draw();
00317                                 GLCameraFrustum::instance()->drawBilboard(
00318                                         position,
00319                                         color,
00320                                         1.0f - shieldHit,
00321                                         round->getActualRadius().asFloat() * 0.95f, 
00322                                         round->getActualRadius().asFloat() * 0.95f,
00323                                         true, // Additive
00324                                         0); // texcoord
00325                         }
00326                 }
00327         }
00328         else
00329         {
00330                 ShieldSquare *square = (ShieldSquare *) shield;
00331 
00332                 texture->draw();
00333                 glPushMatrix();
00334                         glColor4f(color[0], color[1], color[2], 0.5f + shieldHit);
00335                         glTranslatef(position[0], position[1], position[2]);
00336                         glScalef(
00337                                 square->getSize()[0].asFloat(), 
00338                                 square->getSize()[1].asFloat(), 
00339                                 square->getSize()[2].asFloat());
00340                         glCallList(squareListNo);
00341                 glPopMatrix();
00342         }
00343 }
00344 
00345 void TargetRendererImpl::drawParachute()
00346 {
00347         static GLuint listNo = 0;
00348         if (!listNo)
00349         {
00350                 float a;
00351                 glNewList(listNo = glGenLists(1), GL_COMPILE);
00352                         glColor3f(1.0f, 1.0f, 1.0f);
00353                         glBegin(GL_LINES);
00354                                 for (a=0.0f; a< 3.14f*2.0f; a+=3.14f / 4.0f)
00355                                 {
00356                                         glVertex3f(0.0f, 0.0f, 0.0f);
00357                                         glVertex3f(sinf(a) * 2.0f, cosf(a) * 2.0f, 2.0f);
00358                                 }
00359                         glEnd();
00360                         glBegin(GL_TRIANGLE_FAN);
00361                                 glVertex3f(0.0f, 0.0f, 3.0f);
00362 
00363                                 glColor3f(0.5f, 0.5f, 0.5f);
00364                                 for (a=3.14f*2.0f; a> 0.0f; a-=3.14f / 4.0f)
00365                                 {
00366                                         glVertex3f(sinf(a) * 2.0f, cosf(a) * 2.0f, 2.0f);
00367                                 }                               
00368                         glEnd();
00369                 glEndList();
00370         }
00371 
00372         // Check this tank is falling
00373         if (!target_->getTargetState().getFalling()) return;
00374 
00375         // Check this tank has parachutes
00376         if (!target_->getTargetState().getFalling()->getParachute())
00377         {
00378                 return;
00379         }
00380 
00381         Vector &position = target_->getLife().getFloatPosition();
00382         GLState state(GLState::TEXTURE_OFF);
00383         glPushMatrix();
00384                 glTranslatef(position[0], position[1], position[2]);
00385                 glCallList(listNo);
00386         glPopMatrix();
00387 }
00388 
00389 void TargetRendererImpl::createParticle()
00390 {
00391         // Check if we have made the particle
00392         // We may not have if there were not enough to create the 
00393         // tank in the first place
00394         if (particleMade_) return;
00395 
00396         // If this is a target we only need the particle
00397         // if we have a shield or if we are falling
00398         if (target_->isTarget())
00399         {
00400                 if (!target_->getShield().getCurrentShield() &&
00401                         (tree_ || !target_->getTargetState().getFalling()))
00402                 {
00403                         return;
00404                 }
00405         }
00406 
00407         // Else we need the particle
00408         {
00409 
00410                 // Pretent the tank is actually a particle, this is so
00411                 // it gets rendered during the particle renderering phase
00412                 // and using the correct z ordering
00413                 Particle *particle = 
00414                         ScorchedClient::instance()->getParticleEngine().
00415                                 getNextAliveParticle();
00416                 if (particle)
00417                 {
00418                         particle->setParticle(
00419                                 1000.0f,  1.0f, 1.0f, //float life, float mass, float friction,
00420                                 Vector::getNullVector(), Vector::getNullVector(), //Vector &velocity, Vector &gravity,
00421                                 Vector::getNullVector(), Vector::getNullVector(), //Vector &color, Vector &colorCounter,
00422                                 Vector::getNullVector(), Vector::getNullVector(), //Vector &size, Vector &sizeCounter,
00423                                 1.0f, 0.0f, // float alpha, float alphaCounter,
00424                                 false, //bool additiveTexture,
00425                                 false); //bool windAffect);
00426 
00427                         particleMade_ = true;
00428                         particle->life_ = 1000.0f;
00429                         particle->renderer_ = TargetParticleRenderer::getInstance();
00430                         particle->userData_ = new TargetParticleUserData(target_->getPlayerId());
00431                 }
00432         }
00433 }
00434 
00435 float TargetRendererImpl::getTargetSize()
00436 {
00437         // Target size
00438         float targetSize = target_->getLife().getFloatBoundingSize();
00439         float shieldSize = target_->getShield().getShieldBoundingSize().asFloat();
00440         float size = MAX(targetSize, shieldSize);
00441         return size;
00442 }
00443 
00444 float TargetRendererImpl::getTargetFade(float distance, float size)
00445 {
00446         // Figure out the drawing distance
00447         float drawCullingDistance = OptionsDisplay::instance()->getDrawCullingDistance() * size;
00448         float drawFadeStartDistance =  OptionsDisplay::instance()->getDrawFadeStartDistance();
00449         float drawFadeDistance = drawCullingDistance - drawFadeStartDistance;
00450         float fade = 1.0f;
00451         if (distance > drawFadeStartDistance)
00452         {
00453                 fade = 1.0f - ((distance - drawFadeStartDistance) / drawFadeDistance);
00454         }
00455 
00456         return fade;
00457 }
00458 
00459 void TargetRendererImpl::storeTarget2DPos()
00460 {
00461         if (target_->getTargetName().empty()) return;
00462 
00463         Vector &tankTurretPos = 
00464                 target_->getLife().getFloatCenterPosition();
00465         Vector camDir = 
00466                 GLCamera::getCurrentCamera()->getLookAt() - 
00467                 GLCamera::getCurrentCamera()->getCurrentPos();
00468         Vector tankDir = tankTurretPos - 
00469                 GLCamera::getCurrentCamera()->getCurrentPos();
00470 
00471         if (camDir.dotP(tankDir) < 0.0f)
00472         {
00473                 posX_ = - 1000.0;
00474         }
00475         else
00476         {
00477                 static GLdouble modelMatrix[16];
00478                 static GLdouble projMatrix[16];
00479                 static GLint viewport[4];
00480 
00481                 glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
00482                 glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
00483                 glGetIntegerv(GL_VIEWPORT, viewport);
00484 
00485                 viewport[2] = GLViewPort::getWidth();
00486                 viewport[3] = GLViewPort::getHeight();
00487                 int result = gluProject(
00488                         tankTurretPos[0], 
00489                         tankTurretPos[1], 
00490                         tankTurretPos[2],
00491                         modelMatrix, projMatrix, viewport,
00492                         &posX_, 
00493                         &posY_,
00494                         &posZ_);
00495         }
00496 }

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