forked from HaloMods/SparkEdit
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCamera.cpp
649 lines (521 loc) · 22.2 KB
/
Camera.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
//***********************************************************************//
// //
// - "Talk to me like I'm a 3 year old!" Programming Lessons - //
// //
// $Author: DigiBen DigiBen@GameTutorials.com //
// //
// $Program: Camera5 (strafing) //
// //
// $Description: Demonstrates camera strafing right and left //
// //
// $Date: 1/1/02 //
// //
//***********************************************************************//
#include "stdafx.h"
#include "math.h"
#include "Camera.h"
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
// This is how fast our camera moves (Sped up a bit due to normalizing our vectors)
#define kSpeed 0.1f
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
/////////////////////////////////////// CROSS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This returns a perpendicular vector from 2 given vectors by taking the cross product.
/////
/////////////////////////////////////// CROSS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
CVector3 Cross(CVector3 vVector1, CVector3 vVector2)
{
CVector3 vNormal;
// Calculate the cross product with the non communitive equation
vNormal.x = ((vVector1.y * vVector2.z) - (vVector1.z * vVector2.y));
vNormal.y = ((vVector1.z * vVector2.x) - (vVector1.x * vVector2.z));
vNormal.z = ((vVector1.x * vVector2.y) - (vVector1.y * vVector2.x));
// Return the cross product
return vNormal;
}
/////////////////////////////////////// MAGNITUDE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This returns the magnitude of a vector
/////
/////////////////////////////////////// MAGNITUDE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
float Magnitude(CVector3 vNormal)
{
// Here is the equation: magnitude = sqrt(V.x^2 + V.y^2 + V.z^2) : Where V is the vector
return (float)sqrt( (vNormal.x * vNormal.x) +
(vNormal.y * vNormal.y) +
(vNormal.z * vNormal.z) );
}
/////////////////////////////////////// NORMALIZE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This returns a normalize vector (A vector exactly of length 1)
/////
/////////////////////////////////////// NORMALIZE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
CVector3 Normalize(CVector3 vVector)
{
// Get the magnitude of our normal
float magnitude = Magnitude(vVector);
// Now that we have the magnitude, we can divide our vector by that magnitude.
// That will make our vector a total length of 1.
vVector = vVector / magnitude;
// Finally, return our normalized vector
return vVector;
}
///////////////////////////////// CCAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This is the class constructor
/////
///////////////////////////////// CCAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
CCamera::CCamera()
{
CVector3 vZero = CVector3(0.0, 0.0, 0.0); // Init a vVector to 0 0 0 for our position
CVector3 vView = CVector3(0.0, 1.0, 0.5); // Init a starting view vVector (looking up and out the screen)
CVector3 vUp = CVector3(1.0, 0.0, 0.0); // Init a standard up vVector (Rarely ever changes)
m_vPosition = vZero; // Init the position to zero
m_vView = vView; // Init the view to a std starting view
m_vUpVector = vUp; // Init the UpVector
m_LastMouseX = -1;
m_LastMouseY = -1;
m_Speed = 0.1f;
}
///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function sets the camera's position and view and up vVector.
/////
///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CCamera::PositionCamera(float positionX, float positionY, float positionZ,
float viewX, float viewY, float viewZ,
float upVectorX, float upVectorY, float upVectorZ)
{
CVector3 vPosition = CVector3(positionX, positionY, positionZ);
CVector3 vView = CVector3(viewX, viewY, viewZ);
CVector3 vUpVector = CVector3(upVectorX, upVectorY, upVectorZ);
// The code above just makes it cleaner to set the variables.
// Otherwise we would have to set each variable x y and z.
m_vPosition = vPosition; // Assign the position
m_vView = vView; // Assign the view
m_vUpVector = vUpVector; // Assign the up vector
//TRACE("View = (%.2f %.2f %.2f)\n", m_vView.x, m_vView.y, m_vView.z);
m_CurrentRotX = 0;
}
///////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This allows us to look around using the mouse, like in most first person games.
/////
///////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CCamera::CheckMouse()
{
POINT mousePos; // This is a window structure that holds an X and Y
int middleX = 640 >> 1; // This is a binary shift to get half the width
int middleY = 480 >> 1; // This is a binary shift to get half the height
// int middleX = SCREEN_WIDTH >> 1; // This is a binary shift to get half the width
// int middleY = SCREEN_HEIGHT >> 1; // This is a binary shift to get half the height
float angleY = 0.0f; // This is the direction for looking up or down
float angleZ = 0.0f; // This will be the value we need to rotate around the Y axis (Left and Right)
static float currentRotX = 0.0f;
// Get the mouse's current X,Y position
GetCursorPos(&mousePos);
// If our cursor is still in the middle, we never moved... so don't update the screen
if( (mousePos.x == middleX) && (mousePos.y == middleY) ) return;
// Set the mouse position to the middle of our window
SetCursorPos(middleX, middleY);
// Get the direction the mouse moved in, but bring the number down to a reasonable amount
angleY = (float)( (middleX - mousePos.x) ) / 500.0f;
angleZ = (float)( (middleY - mousePos.y) ) / 500.0f;
// Here we keep track of the current rotation (for up and down) so that
// we can restrict the camera from doing a full 360 loop.
currentRotX -= angleZ;
// If the current rotation (in radians) is greater than 1.0, we want to cap it.
if(currentRotX > 0.3f)
currentRotX = 0.3f;
// Check if the rotation is below -1.0, if so we want to make sure it doesn't continue
else if(currentRotX < -0.3f)
currentRotX = -0.3f;
// Otherwise, we can rotate the view around our position
else
{
// To find the axis we need to rotate around for up and down
// movements, we need to get a perpendicular vector from the
// camera's view vector and up vector. This will be the axis.
CVector3 vAxis = Cross(m_vView - m_vPosition, m_vUpVector);
vAxis = Normalize(vAxis);
// Rotate around our perpendicular axis and along the y-axis
RotateView(angleZ, vAxis.x, vAxis.y, vAxis.z);
RotateView(angleY, 0, 1, 0);
}
}
void CCamera::UpdateMouseMove(int DeltaX, int DeltaY)
{
float angleY = 0.0f; // This is the direction for looking up or down
float angleZ = 0.0f; // This will be the value we need to rotate around the Y axis (Left and Right)
// static float currentRotX = 0.0f;
if((DeltaX == 0)&&(DeltaY == 0))
return;
// TRACE("DX = %d DY = %d\n", DeltaX, DeltaY);
// Get the direction the mouse moved in, but bring the number down to a reasonable amount
angleY = (float)(DeltaX) / -200.0f;
angleZ = (float)(DeltaY) / -200.0f;
// Here we keep track of the current rotation (for up and down) so that
// we can restrict the camera from doing a full 360 loop.
m_CurrentRotX -= angleZ;
// If the current rotation (in radians) is greater than 1.0, we want to cap it.
if(m_CurrentRotX > 0.5f)
m_CurrentRotX = 0.5f;
// Check if the rotation is below -1.0, if so we want to make sure it doesn't continue
else if(m_CurrentRotX < -1.5f)
m_CurrentRotX = -1.5f;
else
{
// To find the axis we need to rotate around for up and down
// movements, we need to get a perpendicular vector from the
// camera's view vector and up vector. This will be the axis.
CVector3 vAxis = Cross(m_vView - m_vPosition, m_vUpVector);
vAxis = Normalize(vAxis);
// Rotate around our perpendicular axis and along the y-axis
//RotateView(angleZ, vAxis.x, vAxis.y, vAxis.z);
//RotateView(angleY, 0, 1, 0);
RotateView(angleZ, vAxis.x, vAxis.y, vAxis.z);
RotateView(angleY, 0, 0, 1);
}
//TRACE("ROTX = %.3f\n", m_CurrentRotX);
}
///////////////////////////////// ROTATE VIEW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This rotates the view around the position using an axis-angle rotation
/////
///////////////////////////////// ROTATE VIEW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CCamera::RotateView(float angle, float x, float y, float z)
{
CVector3 vNewView;
// Get the view vector (The direction we are facing)
CVector3 vView = m_vView - m_vPosition;
// Calculate the sine and cosine of the angle once
float cosTheta = (float)cos(angle);
float sinTheta = (float)sin(angle);
// Find the new x position for the new rotated point
vNewView.x = (cosTheta + (1 - cosTheta) * x * x) * vView.x;
vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta) * vView.y;
vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta) * vView.z;
// Find the new y position for the new rotated point
vNewView.y = ((1 - cosTheta) * x * y + z * sinTheta) * vView.x;
vNewView.y += (cosTheta + (1 - cosTheta) * y * y) * vView.y;
vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta) * vView.z;
// Find the new z position for the new rotated point
vNewView.z = ((1 - cosTheta) * x * z - y * sinTheta) * vView.x;
vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta) * vView.y;
vNewView.z += (cosTheta + (1 - cosTheta) * z * z) * vView.z;
// Now we just add the newly rotated vector to our position to set
// our new rotated view of our camera.
m_vView = m_vPosition + vNewView;
}
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
///////////////////////////////// STRAFE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This strafes the camera left and right depending on the speed (-/+)
/////
///////////////////////////////// STRAFE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CCamera::StrafeCamera(float speed)
{
// Strafing is quite simple if you understand what the cross product is.
// If you have 2 vectors (say the up vVector and the view vVector) you can
// use the cross product formula to get a vVector that is 90 degrees from the 2 vectors.
// For a better explanation on how this works, check out the OpenGL "Normals" tutorial at our site.
// In our new Update() function, we set the strafing vector (m_vStrafe). Due
// to the fact that we need this vector for many things including the strafing
// movement and camera rotation (up and down), we just calculate it once.
//
// Like our MoveCamera() function, we add the strafing vector to our current position
// and view. It's as simple as that. It has already been calculated in Update().
// Add the strafe vector to our position
//m_vPosition.x += m_vStrafe.x * speed;
//m_vPosition.z += m_vStrafe.z * speed;
// Add the strafe vector to our view
//m_vView.x += m_vStrafe.x * speed;
//m_vView.z += m_vStrafe.z * speed;
m_vPosition.x += m_vStrafe.x * speed;
m_vPosition.y += m_vStrafe.y * speed;
m_vView.x += m_vStrafe.x * speed;
m_vView.y += m_vStrafe.y * speed;
}
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This will move the camera forward or backward depending on the speed
/////
///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CCamera::MoveCamera(float speed)
{
// Get the current view vector (the direction we are looking)
CVector3 vVector = m_vView - m_vPosition;
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
// I snuck this change in here! We now normalize our view vector when
// moving throughout the world. This is a MUST that needs to be done.
// That way you don't move faster than you strafe, since the strafe vector
// is normalized too.
vVector = Normalize(vVector);
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
//m_vPosition.x += vVector.x * speed; // Add our acceleration to our position's X
//m_vPosition.z += vVector.z * speed; // Add our acceleration to our position's Z
//m_vView.x += vVector.x * speed; // Add our acceleration to our view's X
//m_vView.z += vVector.z * speed; // Add our acceleration to our view's Z
m_vPosition.x += vVector.x * speed; // Add our acceleration to our position's X
m_vPosition.y += vVector.y * speed; // Add our acceleration to our position's Z
m_vView.x += vVector.x * speed; // Add our acceleration to our view's X
m_vView.y += vVector.y * speed; // Add our acceleration to our view's Z
}
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
// The next 3 functions were added to our camera class. The less code in
// Main.cpp the better.
//////////////////////////// CHECK FOR MOVEMENT \\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function handles the input faster than in the WinProc()
/////
//////////////////////////// CHECK FOR MOVEMENT \\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CCamera::CheckKeyboard()
{
// Check if we hit the Up arrow or the 'w' key
if(GetKeyState(VK_UP) & 0x80 || GetKeyState('W') & 0x80) {
// Move our camera forward by a positive SPEED
MoveCamera(m_Speed);
}
// Check if we hit the Down arrow or the 's' key
if(GetKeyState(VK_DOWN) & 0x80 || GetKeyState('S') & 0x80) {
// Move our camera backward by a negative SPEED
MoveCamera(-m_Speed);
}
// Check if we hit the Left arrow or the 'a' key
if(GetKeyState(VK_LEFT) & 0x80 || GetKeyState('A') & 0x80) {
// Strafe the camera left
StrafeCamera(-m_Speed);
}
// Check if we hit the Right arrow or the 'd' key
if(GetKeyState(VK_RIGHT) & 0x80 || GetKeyState('D') & 0x80) {
// Strafe the camera right
StrafeCamera(m_Speed);
}
}
///////////////////////////////// UPDATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This updates the camera's view and strafe vector
/////
///////////////////////////////// UPDATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CCamera::Update()
{
// Below we calculate the strafe vector every time we update
// the camera. This is because many functions use it so we might
// as well calculate it only once.
// Initialize a variable for the cross product result
CVector3 vCross = Cross(m_vView - m_vPosition, m_vUpVector);
// Normalize the strafe vector
m_vStrafe = Normalize(vCross);
//CheckKeyboard();
//CheckMouse();
}
///////////////////////////////// LOOK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This updates the camera according to the
/////
///////////////////////////////// LOOK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CCamera::Look()
{
// Give openGL our camera position, then camera view, then camera up vector
gluLookAt(m_vPosition.x, m_vPosition.y, m_vPosition.z,
m_vView.x, m_vView.y, m_vView.z,
m_vUpVector.x, m_vUpVector.y, m_vUpVector.z);
//gluLookAt(100, 100, 0,
// 0, 0, 0,
// 0, 0, 0);
}
/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *
/////////////////////////////////////////////////////////////////////////////////
//
// * QUICK NOTES *
//
// This file should now be close to complete. Now that we have all the basic camera
// functionality you can use this file in your projects and not have to cut and paste code.
// I created a camera.h for this purpose as well.
//
// We added strafing to this file. 3 other functions were added to our camera class
// so that it would clean up main.cpp a bit more. In Camera.h you will find some
// new changes as well, which include the move of our camera data to private. We now
// will use data access functions to get camera data.
//
// Here are the notes from main.cpp about the concept and application:
//
// This tutorial was taken from the Camera4 tutorial. This is our last camera tutorial.
// We might create a bezier curve camera tutorial though in the future. This tutorial
// shows how to strafe the camera right or left. This might seem easy when you think to
// attempt it, but if you don't know your linear algebra it can be tricky. Strafing the
// camera is moving the camera 90 degrees left or right from the current view. In other
// words, it's as if you were side stepping while you look forward. This is used in most
// first person shooters games, and comes in handy when peering around corners or running
// past a hallway while firing off some rounds. It's also a great way to move diagonal
// while doing a shootout at close ranges to avoid being hit.
//
// Since we understand what strafing is and what it does, let me actually explain how it works.
// We know that we want to walk in the direction that is 90 degrees from the view vVector (with
// the view vVector being m_vView - m_vPosition). So how do we then get the vVector that is 90
// degrees from our view vVector? If you know what the cross product is, you can easily see how
// this would be done. The cross product is a mathematical formula that takes 2 vectors and
// returns the vVector 90 degrees from those 2 vectors. This is how you find the normal to a plane.
// Well, we have a view vVector, but what would the other vVector be? Does the up vVector come to mind?
// That's it! We want to take the cross product between the up vVector and the view vVector. This
// will return the vVector (or direction) that we want to strafe in. In games like Descent, the
// up vVector will change because you can go upside down and spin in crazy directions. The cross
// product will ensure that we will always strafe correctly no matter what orientation the camera is in.
// Once we have the strafe vVector, we need to add it to the position and view points.
// Here are the controls for this tutorial:
//
// w, s, UP_ARROW, DOWN_ARROW - Move the camera forward and backward
// a, d, RIGHT_ARROW, LEFT_ARROW - Strafe the camera left and right
// Mouse movement - Moves the view for first person mode
// ESCAPE - Quits the program
//
// You may notice that we don't use all the methods in the camera class. I decided to leave
// them in there because since this is the last camera tutorial it would be nice to just use
// this in your projects without having to cut and paste code. That's also why I finally
// added a camera.h so you don't have the camera class in main.h.
//
// Enjoy!
//
//
// Ben Humphrey (DigiBen)
// Game Programmer
// DigiBen@GameTutorials.com
// Co-Web Host of www.GameTutorials.com
//
//
void CCamera::SetCamSpeed(float speed)
{
m_Speed = speed;
}
void CCamera::LevitateCamera(float speed)
{
// Get the current view vector (the direction we are looking)
//CVector3 vVector = m_vView - m_vPosition;
//vVector = Normalize(vVector);
//m_vPosition.y += speed;
//m_vView.y += speed;
m_vPosition.z += speed;
m_vView.z += speed;
}
void CCamera::GetCameraPosition(float *pPosition)
{
pPosition[0] = m_vPosition.x;
pPosition[1] = m_vPosition.y;
pPosition[2] = m_vPosition.z;
}
void CCamera::GetCameraAltAzimuth(float *pAlt, float *pAzimuth, float *pCamX, float *pCamY)
{
float xy_mag;
float dx,dy,dz;
dx = m_vPosition.x - m_vView.x;
dy = m_vView.y - m_vPosition.y;
dz = m_vPosition.z - m_vView.z;
xy_mag = sqrt(dx*dx + dy*dy);
*pCamX = dx/xy_mag;
*pCamY = dy/xy_mag;
TRACE("camx=%.1f camy = %.1f\n", *pCamX, *pCamY);
if(dx != 0)
{
*pAzimuth = atan(dy/dx);
if(dx>0)
{
if(dy>0)
*pAzimuth += 0;
else
{
*pAzimuth *= -1;
*pAzimuth += 0.78539816f*2;
}
}
else
{
if(dy>0)
{
// *pAzimuth *= -1;
// *pAzimuth += 0.78539816f*2;
}
//se
//*pAzimuth += 0.78539816f*2;
}
}
else
{
}
//TRACE("dx = %.2f dy=%.2f az=%f.2\n", dx, dy, *pAzimuth);
if(xy_mag != 0) //this should never happen because of camera restrictions
{
*pAlt = atan(dz/xy_mag);
}
else
{
*pAlt = 0;
}
}
void CCamera::DoUnProject(float ifX, float ifY, float *ofObjX, float *ofObjY, float *ofObjZ, float ifZ, bool ibUseZ)
{
//this function is basically just a wrapper for gluUnProject.
//It does all of the getting of the projection and modelview
//matrices, and if you pass true in the parameter ibUseZ,
//it will use the ifZ parameter you passed in, otherwise it
//will use glReadPixels to calculate it.
//
//ifX and ifY are expected to be relative to the upper-left
//corner of the OpenGL context. The calls to ReadPixels
//and UnProject expect coordinates relative to the *lower*
//left corner, so we will convert them here.
float fMouseX, fMouseY, fMouseZ;
fMouseX = ifX;
fMouseY = ifY;
fMouseZ = 0.0f;
//now, fMouseX and fMouseY are relative to the *upper* left
//corner of the OpenGL context, but OpenGL expects
//coordinates relative to the *lower* left corner of the
//screen, so we need to reverse Y.
int anViewport[4];
glGetIntegerv(GL_VIEWPORT, anViewport);
//height is the fourth element
fMouseY = (float)anViewport[3] - fMouseY;
if (ibUseZ)
{
fMouseZ = ifZ;
}
else
{
glReadPixels(fMouseX, fMouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &fMouseZ);
}
//get the matrices for their passing to gluUnProject
double afModelviewMatrix[16];
double afProjectionMatrix[16];
glGetDoublev(GL_MODELVIEW_MATRIX, afModelviewMatrix);
glGetDoublev(GL_PROJECTION_MATRIX, afProjectionMatrix);
double dTempX, dTempY, dTempZ;
gluUnProject(fMouseX, fMouseY, fMouseZ, afModelviewMatrix, afProjectionMatrix, anViewport, &dTempX, &dTempY, &dTempZ);
//ofObjX, Y and Z should be populated and returned now
*ofObjX = (float)dTempX;
*ofObjY = (float)dTempY;
*ofObjZ = (float)dTempZ;
}
void CCamera::SaveCurrentPosition()
{
m_vSavePosition = m_vPosition;
m_vSaveView = m_vView;
m_vSaveUpVector = m_vUpVector;
}
void CCamera::RestoreSavedPosition()
{
m_vPosition = m_vSavePosition;
m_vView = m_vSaveView;
m_vUpVector = m_vSaveUpVector;
}
void CCamera::GetCameraFrontCoord(float *pCoord)
{
float dx, dy, dz, mag;
dx = m_vView.x - m_vPosition.x;
dy = m_vView.y - m_vPosition.y;
dz = m_vView.z - m_vPosition.z;
mag = sqrt(dx*dx + dy*dy + dz*dz);
pCoord[0] = m_vPosition.x + ((m_vView.x - m_vPosition.x)/mag)*2;
pCoord[1] = m_vPosition.y + ((m_vView.y - m_vPosition.y)/mag)*2;
pCoord[2] = m_vPosition.z + ((m_vView.z - m_vPosition.z)/mag)*2;
}