00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00154 totalTime_ += frameTime;
00155 while (totalTime_ > 0.03f)
00156 {
00157 totalTime_ -= 0.03f;
00158
00159
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
00174 Vector directionLookAt = wantedLookAt_ - lookAt_;
00175 directionLookAt *= SecondsToReachTarget;
00176 lookAt_ += directionLookAt;
00177
00178
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