git-svn-id: https://scorched3d.svn.sourceforge.net/svnroot/scorched3d/trunk/scorched...
[scorched3d/parasti.git] / src / client / GLEXT / GLCamera.cpp
blobf892a0ad9f0b7936eab5797c448bef627cb76a43
1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <math.h>
22 #include <stdlib.h>
23 #include <common/Defines.h>
24 #include <GLEXT/GLState.h>
25 #include <GLEXT/GLCamera.h>
26 #include <GLEXT/GLViewPort.h>
28 GLCamera *GLCamera::currentCamera_ = 0;
30 GLCamera::GLCamera(GLsizei windowWidth, GLsizei windowHeight) :
31 rotationXY_(0.0f), rotationYZ_(PI / 4), zoom_(150.0f),
32 useHeightFunc_(false), minHeightFunc_(0), maxHeightFunc_(0),
33 totalTime_(0.0f),
34 shake_(0.0f), minHeightData_(0), maxHeightData_(0)
36 currentCamera_ = this;
37 setWindowOffset(0, 0);
38 setWindowSize(windowWidth, windowHeight);
39 calculateWantedOffset();
40 currentPosition_ = wantedOffset_ + lookAt_;
43 GLCamera::~GLCamera()
48 void GLCamera::setUseHeightFunc(bool toggle)
50 useHeightFunc_ = toggle;
53 void GLCamera::setMinHeightFunc(MinHeightFunc func, void *data)
55 minHeightFunc_ = func;
56 minHeightData_ = data;
57 if (func)
59 useHeightFunc_ = true;
63 void GLCamera::setMaxHeightFunc(MaxHeightFunc func, void *data)
65 maxHeightFunc_ = func;
66 maxHeightData_ = data;
67 if (func)
69 useHeightFunc_ = true;
73 void GLCamera::setLookAt(Vector &lookAt, bool instant)
75 wantedLookAt_ = lookAt;
76 if (instant)
78 lookAt_ = lookAt;
82 void GLCamera::setCurrentPos(Vector &pos)
84 currentPosition_ = pos;
87 void GLCamera::setOffSet(Vector &offSet, bool instant)
89 wantedOffset_ = offSet;
90 if (instant)
92 currentPosition_ = wantedOffset_ + lookAt_;
96 void GLCamera::setWindowSize(GLsizei windowWidth, GLsizei windowHeight)
98 windowW_ = windowWidth;
99 windowH_ = windowHeight;
100 windowAspect_ = float(windowWidth) / float(windowHeight?windowHeight:0.0001);
103 void GLCamera::setWindowOffset(GLsizei windowLeft, GLsizei windowTop)
105 windowL_ = windowLeft;
106 windowT_ = windowTop;
109 void GLCamera::calculateWantedOffset()
111 wantedOffset_[0] = zoom_ * float(sin(rotationXY_) * sin(rotationYZ_));
112 wantedOffset_[1] = zoom_ * float(cos(rotationXY_) * sin(rotationYZ_));
113 wantedOffset_[2] = zoom_ * float(cos(rotationYZ_));
116 void GLCamera::moveViewport(Vector &lookFrom, Vector &lookAt)
118 GLfloat lz(lookFrom[2]);
120 Vector direction = lookAt - lookFrom;
121 direction[2] = 0.0f;
122 direction.StoreNormalize();
123 direction *= 3.0f;
124 if (minHeightFunc_ && useHeightFunc_)
126 lz = MAX(lz, (*minHeightFunc_)(int(lookFrom[0]),
127 int(lookFrom[1]), minHeightData_));
128 lz = MAX(lz, (*minHeightFunc_)(int(lookFrom[0] + direction[0]),
129 int(lookFrom[1] + direction[1]), minHeightData_));
131 if (maxHeightFunc_ && useHeightFunc_)
133 lz = MIN(lz, (*maxHeightFunc_)(int(lookFrom[0]),
134 int(lookFrom[1]), maxHeightData_));
135 lz = MIN(lz, (*maxHeightFunc_)(int(lookFrom[0] + direction[0]),
136 int(lookFrom[1] + direction[1]), maxHeightData_));
139 glMatrixMode(GL_PROJECTION);
140 glLoadIdentity();
141 glViewport(windowL_, windowT_, windowW_, windowH_);
142 gluPerspective(60.0f, windowAspect_, 1.0f, 2500.0f);
143 glMatrixMode(GL_MODELVIEW);
144 glLoadIdentity();
145 gluLookAt(lookFrom[0], lookFrom[1], lz, lookAt[0], lookAt[1], lookAt[2] ,0.0f, 0.0f, 1.0f);
148 void GLCamera::simulate(float frameTime)
150 const float SecondsToReachTarget = 0.15f;
151 const float ShakeDecrease = 0.06f;
153 // Make some constant changes, regardless of framerate
154 totalTime_ += frameTime;
155 while (totalTime_ > 0.03f)
157 totalTime_ -= 0.03f;
159 // Calculate any camera shake
160 shake_ -= ShakeDecrease;
161 if (shake_ > 0.0f)
163 shakeV_[0] = RAND * shake_;
164 shakeV_[1] = RAND * shake_;
165 shakeV_[2] = RAND * shake_;
167 else
169 shake_ = 0.0f;
170 shakeV_.zero();
173 // Calculate the new look at value
174 Vector directionLookAt = wantedLookAt_ - lookAt_;
175 directionLookAt *= SecondsToReachTarget;
176 lookAt_ += directionLookAt;
178 // Calculate the new look from value
179 Vector wantedPosition = wantedOffset_ + lookAt_;
180 Vector directionPosition = wantedPosition - currentPosition_;
181 directionPosition *= SecondsToReachTarget;
182 currentPosition_ += directionPosition;
183 velocity_ = directionPosition;
187 void GLCamera::draw()
189 static Vector look;
190 currentCamera_ = this;
191 look = lookAt_;
192 look += shakeV_;
193 moveViewport(currentPosition_, look);
196 void GLCamera::addShake(float shake)
198 shake_ += shake;
199 if (shake_ > 5.0f) shake_ = 5.0f;
202 void GLCamera::movePosition(float XY, float YZ, float Z)
204 rotationXY_ = XY;
205 rotationYZ_ = YZ;
206 zoom_ = Z;
208 calculateWantedOffset();
211 void GLCamera::movePositionDelta(float XY, float YZ, float Z)
213 XY += rotationXY_;
214 YZ += rotationYZ_;
215 Z += zoom_;
217 if (YZ < 0.17f) YZ = 0.17f;
218 if (YZ > 1.91f) YZ = 1.91f;
219 if (Z < 5.0) Z = 5.0f;
220 if (Z > 250.0f) Z = 250.0f;
222 movePosition(XY, YZ, Z);
225 bool GLCamera::getDirectionFromPt(GLfloat winX, GLfloat winY, Line &direction)
227 static GLdouble modelMatrix[16];
228 static GLdouble projMatrix[16];
229 static GLint viewport[4];
231 glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
232 glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
233 glGetIntegerv(GL_VIEWPORT, viewport);
235 float realX = winX / GLViewPort::getWidthMult();
236 float realY = GLViewPort::getActualHeight() -
237 ((GLViewPort::getHeight() - winY) / GLViewPort::getHeightMult());
239 GLdouble x,y,z;
240 gluUnProject(
241 realX,
242 realY,
243 0.0f,
244 modelMatrix,
245 projMatrix,
246 viewport,
249 &z);
250 Vector pos1((float) x, (float) y, (float) z);
252 gluUnProject(
253 realX,
254 realY,
255 100.0f,
256 modelMatrix,
257 projMatrix,
258 viewport,
261 &z);
263 Vector pos2((float) x, (float) y, (float) z);
265 Vector dir = pos2 - pos1;
267 float dist = dir[2];
268 if (dist == 0.0f)
270 dist = 0.000001f;
272 float number = (float) fabs(pos2[2] / dist);
274 Vector groundPos = pos2 - dir * number;
275 direction.setStart(groundPos);
276 direction.setEnd(pos2);
278 return true;
281 void GLCamera::scroll(ScrollDir direction,
282 float minWidth, float minHeight,
283 float maxWidth, float maxHeight)
285 float x = 0.0f, y = 0.0f;
286 switch (direction)
288 case eScrollLeft:
289 x = -5.0f;
290 break;
291 case eScrollRight:
292 x = 5.0f;
293 break;
294 case eScrollUp:
295 y = -5.0f;
296 break;
297 case eScrollDown:
298 y = 5.0f;
299 break;
301 scroll(x, y, minWidth, minHeight, maxWidth, maxHeight);
304 void GLCamera::scroll(float x, float y,
305 float minWidth, float minHeight,
306 float maxWidth, float maxHeight)
308 static Vector zvec(0.0f, 0.0f, 1.0f);
309 Vector dir = lookAt_ - currentPosition_;
310 dir.StoreNormalize();
312 x *= zoom_ / 225.0f;
313 y *= zoom_ / 225.0f;
315 Vector left = dir * zvec;
316 left.StoreNormalize();
317 Vector up = left * zvec;
318 left *= x;
319 up *= y;
321 wantedLookAt_ += left + up;
322 lookAt_ = wantedLookAt_;
323 currentPosition_ += left + up;
325 if (wantedLookAt_[0] < minWidth) wantedLookAt_[0] = minWidth;
326 else if (wantedLookAt_[0] > maxWidth) wantedLookAt_[0] = maxWidth;
328 if (wantedLookAt_[1] < minHeight) wantedLookAt_[1] = minHeight;
329 else if (wantedLookAt_[1] > maxHeight) wantedLookAt_[1] = maxHeight;