Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Camera.cpp
Go to the documentation of this file.
1 /* Project nGenEx
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: nGenEx.lib
6  FILE: Camera.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Camera Class - Position and Point of View
13 */
14 
15 #include "MemDebug.h"
16 #include "Camera.h"
17 
18 // +--------------------------------------------------------------------+
19 
20 Camera::Camera(double x, double y, double z)
21 : pos(x,y,z)
22 { }
23 
25 { }
26 
27 // +--------------------------------------------------------------------+
28 
29 void
30 Camera::MoveTo(double x, double y, double z)
31 {
32  pos.x = x;
33  pos.y = y;
34  pos.z = z;
35 }
36 
37 void
39 {
40  pos.x = p.x;
41  pos.y = p.y;
42  pos.z = p.z;
43 }
44 
45 // +--------------------------------------------------------------------+
46 
47 void
48 Camera::MoveBy(double dx, double dy, double dz)
49 {
50  pos.x += dx;
51  pos.y += dz;
52  pos.z += dy;
53 }
54 
55 void
57 {
58  pos.x += p.x;
59  pos.y += p.y;
60  pos.z += p.z;
61 }
62 
63 // +--------------------------------------------------------------------+
64 
65 void
66 Camera::Clone(const Camera& cam)
67 {
68  pos = cam.pos;
70 }
71 
72 // +--------------------------------------------------------------------+
73 
74 void
75 Camera::LookAt(const Point& target, const Point& eye, const Point& up)
76 {
77  Point zaxis = target - eye; zaxis.Normalize();
78  Point xaxis = up.cross(zaxis); xaxis.Normalize();
79  Point yaxis = zaxis.cross(xaxis); yaxis.Normalize();
80 
81  orientation(0,0) = xaxis.x;
82  orientation(0,1) = xaxis.y;
83  orientation(0,2) = xaxis.z;
84 
85  orientation(1,0) = yaxis.x;
86  orientation(1,1) = yaxis.y;
87  orientation(1,2) = yaxis.z;
88 
89  orientation(2,0) = zaxis.x;
90  orientation(2,1) = zaxis.y;
91  orientation(2,2) = zaxis.z;
92 
93  pos = eye;
94 }
95 
96 // +--------------------------------------------------------------------+
97 
98 void
99 Camera::LookAt(const Point& target)
100 {
101  // No navel gazing:
102  if (target == Pos())
103  return;
104 
105  Point tgt, tmp = target - Pos();
106 
107  // Rotate into the view orientation:
108  tgt.x = (tmp * vrt());
109  tgt.y = (tmp * vup());
110  tgt.z = (tmp * vpn());
111 
112  if (tgt.z == 0) {
113  Pitch(0.5);
114  Yaw(0.5);
115  LookAt(target);
116  return;
117  }
118 
119  double az = atan(tgt.x/tgt.z);
120  double el = atan(tgt.y/tgt.z);
121 
122  // if target is behind, offset by 180 degrees:
123  if (tgt.z < 0)
124  az -= PI;
125 
126  Pitch(-el);
127  Yaw(az);
128 
129  // roll to upright position:
130  double deflection = vrt().y;
131  while (fabs(deflection) > 0.001) {
132  double theta = asin(deflection/vrt().length());
133  Roll(-theta);
134 
135  deflection = vrt().y;
136  }
137 }
138 
139 
140 // +--------------------------------------------------------------------+
141 
142 bool
143 Camera::Padlock(const Point& target, double alimit, double e_lo, double e_hi)
144 {
145  // No navel gazing:
146  if (target == Pos())
147  return false;
148 
149  Point tgt, tmp = target - Pos();
150 
151  // Rotate into the view orientation:
152  tgt.x = (tmp * vrt());
153  tgt.y = (tmp * vup());
154  tgt.z = (tmp * vpn());
155 
156  if (tgt.z == 0) {
157  Yaw(0.1);
158 
159  tgt.x = (tmp * vrt());
160  tgt.y = (tmp * vup());
161  tgt.z = (tmp * vpn());
162 
163  if (tgt.z == 0)
164  return false;
165  }
166 
167  bool locked = true;
168  double az = atan(tgt.x/tgt.z);
169  double orig = az;
170 
171  // if target is behind, offset by 180 degrees:
172  if (tgt.z < 0)
173  az -= PI;
174 
175  while (az > PI) az -= 2*PI;
176  while (az < -PI) az += 2*PI;
177 
178  if (alimit > 0) {
179  if (az < -alimit) {
180  az = -alimit;
181  locked = false;
182  }
183  else if (az > alimit) {
184  az = alimit;
185  locked = false;
186  }
187  }
188 
189  Yaw(az);
190 
191  // Rotate into the new view orientation:
192  tgt.x = (tmp * vrt());
193  tgt.y = (tmp * vup());
194  tgt.z = (tmp * vpn());
195 
196  double el = atan(tgt.y/tgt.z);
197 
198  if (e_lo > 0 && el < -e_lo) {
199  el = -e_lo;
200  locked = false;
201  }
202 
203  else if (e_hi > 0 && el > e_hi) {
204  el = e_hi;
205  locked = false;
206  }
207 
208  Pitch(-el);
209 
210  return locked;
211 }
212