GLCamera.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 <math.h>
00022 #include <stdlib.h>
00023 #include <common/Defines.h>
00024 #include <GLEXT/GLState.h>
00025 #include <GLEXT/GLCamera.h>
00026 #include <GLEXT/GLViewPort.h>
00027 
00028 GLCamera *GLCamera::currentCamera_ = 0;
00029 
00030 GLCamera::GLCamera(GLsizei windowWidth, GLsizei windowHeight) :
00031         rotationXY_(0.0f), rotationYZ_(PI / 4), zoom_(150.0f),
00032         useHeightFunc_(false), minHeightFunc_(0), maxHeightFunc_(0), 
00033         totalTime_(0.0f), 
00034         shake_(0.0f), minHeightData_(0), maxHeightData_(0)
00035 {
00036         currentCamera_ = this;
00037         setWindowOffset(0, 0);
00038         setWindowSize(windowWidth, windowHeight);
00039         calculateWantedOffset();
00040         currentPosition_ = wantedOffset_ + lookAt_;
00041 }
00042 
00043 GLCamera::~GLCamera()
00044 {
00045 
00046 }
00047 
00048 void GLCamera::setUseHeightFunc(bool toggle)
00049 {
00050         useHeightFunc_ = toggle;
00051 }
00052 
00053 void GLCamera::setMinHeightFunc(MinHeightFunc func, void *data)
00054 {
00055         minHeightFunc_ = func;
00056         minHeightData_ = data;
00057         if (func)
00058         {
00059                 useHeightFunc_ = true;
00060         }
00061 }
00062 
00063 void GLCamera::setMaxHeightFunc(MaxHeightFunc func, void *data)
00064 {
00065         maxHeightFunc_ = func;
00066         maxHeightData_ = data;
00067         if (func)
00068         {
00069                 useHeightFunc_ = true;
00070         }
00071 }
00072 
00073 void GLCamera::setLookAt(Vector &lookAt, bool instant)
00074 {
00075         wantedLookAt_ = lookAt;
00076         if (instant)
00077         {
00078                 lookAt_ = lookAt;
00079         }
00080 }
00081 
00082 void GLCamera::setCurrentPos(Vector &pos)
00083 {
00084         currentPosition_ = pos;
00085 }
00086 
00087 void GLCamera::setOffSet(Vector &offSet, bool instant)
00088 {
00089         wantedOffset_ = offSet;
00090         if (instant)
00091         {
00092                 currentPosition_ = wantedOffset_ + lookAt_;
00093         }
00094 }
00095 
00096 void GLCamera::setWindowSize(GLsizei windowWidth, GLsizei windowHeight)
00097 {
00098         windowW_ = windowWidth;
00099         windowH_ = windowHeight;
00100         windowAspect_ = float(windowWidth) / float(windowHeight?windowHeight:0.0001);
00101 }
00102 
00103 void GLCamera::setWindowOffset(GLsizei windowLeft, GLsizei windowTop)
00104 {
00105         windowL_ = windowLeft;
00106         windowT_ = windowTop;
00107 }
00108 
00109 void GLCamera::calculateWantedOffset()
00110 {
00111         wantedOffset_[0] =  zoom_ * float(sin(rotationXY_) * sin(rotationYZ_));
00112         wantedOffset_[1] =  zoom_ * float(cos(rotationXY_) * sin(rotationYZ_));
00113         wantedOffset_[2] =  zoom_ * float(cos(rotationYZ_));
00114 }
00115 
00116 void GLCamera::moveViewport(Vector &lookFrom, Vector &lookAt)
00117 {
00118         GLfloat lz(lookFrom[2]);
00119 
00120         Vector direction = lookAt - lookFrom;
00121         direction[2] = 0.0f;
00122         direction.StoreNormalize();
00123         direction *= 3.0f;
00124         if (minHeightFunc_ && useHeightFunc_)
00125         {
00126                 lz = MAX(lz, (*minHeightFunc_)(int(lookFrom[0]), 
00127                         int(lookFrom[1]), minHeightData_));
00128                 lz = MAX(lz, (*minHeightFunc_)(int(lookFrom[0] + direction[0]), 
00129                         int(lookFrom[1] + direction[1]), minHeightData_));
00130         }
00131         if (maxHeightFunc_ && useHeightFunc_)
00132         {
00133                 lz = MIN(lz, (*maxHeightFunc_)(int(lookFrom[0]),
00134                         int(lookFrom[1]), maxHeightData_));
00135                 lz = MIN(lz, (*maxHeightFunc_)(int(lookFrom[0] + direction[0]),
00136                         int(lookFrom[1] + direction[1]), maxHeightData_));
00137         }
00138 
00139         glMatrixMode(GL_PROJECTION);
00140         glLoadIdentity();       
00141         glViewport(windowL_, windowT_, windowW_, windowH_);
00142         gluPerspective(60.0f, windowAspect_, 1.0f, 2500.0f);
00143         glMatrixMode(GL_MODELVIEW);
00144         glLoadIdentity();
00145         gluLookAt(lookFrom[0], lookFrom[1], lz, lookAt[0], lookAt[1], lookAt[2] ,0.0f, 0.0f, 1.0f);
00146 }
00147 
00148 void GLCamera::simulate(float frameTime)
00149 {
00150         const float SecondsToReachTarget = 0.15f;
00151         const float ShakeDecrease = 0.06f;
00152 
00153         // Make some constant changes, regardless of framerate
00154         totalTime_ += frameTime;
00155         while (totalTime_ > 0.03f)
00156         {
00157                 totalTime_ -= 0.03f;
00158 
00159                 // Calculate any camera shake
00160                 shake_ -= ShakeDecrease;
00161                 if (shake_ > 0.0f)
00162                 {
00163                         shakeV_[0] = RAND * shake_;
00164                         shakeV_[1] = RAND * shake_;
00165                         shakeV_[2] = RAND * shake_;
00166                 }
00167                 else 
00168                 {
00169                         shake_ = 0.0f;
00170                         shakeV_.zero();
00171                 }
00172 
00173                 // Calculate the new look at value
00174                 Vector directionLookAt = wantedLookAt_ - lookAt_;
00175                 directionLookAt *= SecondsToReachTarget;
00176                 lookAt_ += directionLookAt;
00177 
00178                 // Calculate the new look from value
00179                 Vector wantedPosition = wantedOffset_ + lookAt_;
00180                 Vector directionPosition = wantedPosition - currentPosition_;
00181                 directionPosition *= SecondsToReachTarget;
00182                 currentPosition_ += directionPosition;
00183                 velocity_ = directionPosition;
00184         }
00185 }
00186 
00187 void GLCamera::draw()
00188 {
00189         static Vector look;
00190         currentCamera_ = this;
00191         look = lookAt_;
00192         look += shakeV_;
00193         moveViewport(currentPosition_, look);
00194 }
00195 
00196 void GLCamera::addShake(float shake)
00197 {
00198         shake_ += shake;
00199         if (shake_ > 5.0f) shake_ = 5.0f;
00200 }
00201 
00202 void GLCamera::movePosition(float XY, float YZ, float Z)
00203 {
00204         rotationXY_ = XY;
00205         rotationYZ_ = YZ;
00206         zoom_ = Z;
00207 
00208         calculateWantedOffset();
00209 }
00210 
00211 void GLCamera::movePositionDelta(float XY, float YZ, float Z)
00212 {
00213         XY += rotationXY_;
00214         YZ += rotationYZ_;
00215         Z += zoom_;
00216 
00217         if (YZ < 0.17f) YZ = 0.17f;
00218         if (YZ > 1.91f) YZ = 1.91f;
00219         if (Z < 5.0) Z = 5.0f;
00220         if (Z > 250.0f) Z = 250.0f;
00221 
00222         movePosition(XY, YZ, Z);
00223 }
00224 
00225 bool GLCamera::getDirectionFromPt(GLfloat winX, GLfloat winY, Line &direction)
00226 {
00227         static GLdouble modelMatrix[16];
00228         static GLdouble projMatrix[16];
00229         static GLint viewport[4];
00230 
00231         glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
00232         glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
00233         glGetIntegerv(GL_VIEWPORT, viewport);
00234 
00235         float realX = winX / GLViewPort::getWidthMult();
00236         float realY = GLViewPort::getActualHeight() - 
00237                 ((GLViewPort::getHeight() - winY) / GLViewPort::getHeightMult());
00238 
00239         GLdouble x,y,z;
00240         gluUnProject(
00241                 realX,
00242                 realY,
00243                 0.0f,
00244                 modelMatrix,
00245                 projMatrix,
00246                 viewport,
00247                 &x,
00248                 &y,
00249                 &z);
00250         Vector pos1((float) x, (float) y, (float) z);
00251 
00252         gluUnProject(
00253                 realX,
00254                 realY,
00255                 100.0f,
00256                 modelMatrix,
00257                 projMatrix,
00258                 viewport,
00259                 &x,
00260                 &y,
00261                 &z);
00262 
00263         Vector pos2((float) x, (float) y, (float) z);
00264 
00265         Vector dir = pos2 - pos1;
00266 
00267         float dist = dir[2];
00268         if (dist == 0.0f)
00269         {
00270                 dist = 0.000001f;
00271         }
00272         float number = (float) fabs(pos2[2] / dist);
00273 
00274         Vector groundPos = pos2 - dir * number;
00275         direction.setStart(groundPos);
00276         direction.setEnd(pos2);
00277 
00278         return true;
00279 }
00280 
00281 void GLCamera::scroll(ScrollDir direction, 
00282         float minWidth, float minHeight,
00283         float maxWidth, float maxHeight, 
00284         float amount)
00285 {
00286         float x = 0.0f, y = 0.0f;
00287         switch (direction)
00288         {
00289         case eScrollLeft:
00290                 x = -amount;
00291                 break;
00292         case eScrollRight:
00293                 x = amount;
00294                 break;
00295         case eScrollUp:
00296                 y = -amount;
00297                 break;
00298         case eScrollDown:
00299                 y = amount;
00300                 break;
00301         }
00302         scroll(x, y, minWidth, minHeight, maxWidth, maxHeight);
00303 }
00304 
00305 void GLCamera::scroll(float x, float y,
00306         float minWidth, float minHeight,
00307         float maxWidth, float maxHeight)
00308 {
00309         static Vector zvec(0.0f, 0.0f, 1.0f);
00310         Vector dir = lookAt_ - currentPosition_;
00311         dir.StoreNormalize();
00312 
00313         x *= zoom_ / 225.0f;
00314         y *= zoom_ / 225.0f;
00315 
00316         Vector left = dir * zvec;
00317         left.StoreNormalize();
00318         Vector up = left * zvec;
00319         left *= x;
00320         up *= y;
00321         
00322         wantedLookAt_ += left + up;
00323         lookAt_ = wantedLookAt_;
00324         currentPosition_ += left + up;
00325 
00326         if (wantedLookAt_[0] < minWidth) wantedLookAt_[0] = minWidth;
00327         else if (wantedLookAt_[0] > maxWidth) wantedLookAt_[0] = maxWidth;
00328 
00329         if (wantedLookAt_[1] < minHeight) wantedLookAt_[1] = minHeight;
00330         else if (wantedLookAt_[1] > maxHeight) wantedLookAt_[1] = maxHeight;
00331 }
00332 

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