1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
4 // This file is part of Scorched3D.
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 ////////////////////////////////////////////////////////////////////////////////
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),
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_
;
48 void GLCamera::setUseHeightFunc(bool toggle
)
50 useHeightFunc_
= toggle
;
53 void GLCamera::setMinHeightFunc(MinHeightFunc func
, void *data
)
55 minHeightFunc_
= func
;
56 minHeightData_
= data
;
59 useHeightFunc_
= true;
63 void GLCamera::setMaxHeightFunc(MaxHeightFunc func
, void *data
)
65 maxHeightFunc_
= func
;
66 maxHeightData_
= data
;
69 useHeightFunc_
= true;
73 void GLCamera::setLookAt(Vector
&lookAt
, bool instant
)
75 wantedLookAt_
= lookAt
;
82 void GLCamera::setCurrentPos(Vector
&pos
)
84 currentPosition_
= pos
;
87 void GLCamera::setOffSet(Vector
&offSet
, bool instant
)
89 wantedOffset_
= offSet
;
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
;
122 direction
.StoreNormalize();
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
);
141 glViewport(windowL_
, windowT_
, windowW_
, windowH_
);
142 gluPerspective(60.0f
, windowAspect_
, 1.0f
, 2500.0f
);
143 glMatrixMode(GL_MODELVIEW
);
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
)
159 // Calculate any camera shake
160 shake_
-= ShakeDecrease
;
163 shakeV_
[0] = RAND
* shake_
;
164 shakeV_
[1] = RAND
* shake_
;
165 shakeV_
[2] = RAND
* shake_
;
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()
190 currentCamera_
= this;
193 moveViewport(currentPosition_
, look
);
196 void GLCamera::addShake(float shake
)
199 if (shake_
> 5.0f
) shake_
= 5.0f
;
202 void GLCamera::movePosition(float XY
, float YZ
, float Z
)
208 calculateWantedOffset();
211 void GLCamera::movePositionDelta(float XY
, float YZ
, float Z
)
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());
250 Vector
pos1((float) x
, (float) y
, (float) z
);
263 Vector
pos2((float) x
, (float) y
, (float) z
);
265 Vector dir
= pos2
- pos1
;
272 float number
= (float) fabs(pos2
[2] / dist
);
274 Vector groundPos
= pos2
- dir
* number
;
275 direction
.setStart(groundPos
);
276 direction
.setEnd(pos2
);
281 void GLCamera::scroll(ScrollDir direction
,
282 float minWidth
, float minHeight
,
283 float maxWidth
, float maxHeight
)
285 float x
= 0.0f
, y
= 0.0f
;
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();
315 Vector left
= dir
* zvec
;
316 left
.StoreNormalize();
317 Vector up
= left
* zvec
;
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
;