From 8898ad9b25fca6afe2374d293a981db02a83d7e9 Mon Sep 17 00:00:00 2001 From: "FWoltermann@gmail.com" Date: Thu, 31 May 2012 14:46:27 +0000 Subject: Committing the documentation to svn to have it accessible online --- Doc/doxygen/html/_camera_director_8cpp_source.html | 1313 ++++++++++++++++++++ 1 file changed, 1313 insertions(+) create mode 100644 Doc/doxygen/html/_camera_director_8cpp_source.html (limited to 'Doc/doxygen/html/_camera_director_8cpp_source.html') diff --git a/Doc/doxygen/html/_camera_director_8cpp_source.html b/Doc/doxygen/html/_camera_director_8cpp_source.html new file mode 100644 index 0000000..5e60a73 --- /dev/null +++ b/Doc/doxygen/html/_camera_director_8cpp_source.html @@ -0,0 +1,1313 @@ + + + + + +Starshatter_Open: D:/SRC/StarshatterSVN/Stars45/CameraDirector.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
Starshatter_Open +
+
Open source Starshatter engine
+
+
+ + + + + +
+
+ +
+
+
+ +
+ + + + +
+ +
+ +
+
+
CameraDirector.cpp
+
+
+Go to the documentation of this file.
1 /* Project Starshatter 4.5
+
2  Destroyer Studios LLC
+
3  Copyright © 1997-2004. All Rights Reserved.
+
4 
+
5  SUBSYSTEM: Stars.exe
+
6  FILE: CameraDirector.cpp
+
7  AUTHOR: John DiCamillo
+
8 
+
9 
+
10  OVERVIEW
+
11  ========
+
12  Camera Director singleton manages the main view camera based on the current ship
+
13 */
+
14 
+
15 #include "MemDebug.h"
+
16 #include "CameraDirector.h"
+
17 #include "Ship.h"
+
18 #include "FlightDeck.h"
+
19 #include "Contact.h"
+
20 #include "Sim.h"
+
21 #include "StarSystem.h"
+
22 #include "Terrain.h"
+
23 #include "HUDView.h"
+
24 #include "DetailSet.h"
+
25 #include "Starshatter.h"
+
26 
+
27 #include "Game.h"
+
28 
+
29 // +----------------------------------------------------------------------+
+
30 
+ +
32 
+
33 static double range_max_limit = 300e3;
+
34 
+
35 // +----------------------------------------------------------------------+
+
36 
+ + +
39 {
+
40  if (!instance)
+
41  instance = new(__FILE__,__LINE__) CameraDirector;
+
42 
+
43  return instance;
+
44 }
+
45 
+
46 // +----------------------------------------------------------------------+
+
47 
+ +
49 : mode(MODE_COCKPIT), requested_mode(MODE_NONE), old_mode(MODE_NONE),
+
50 sim(0), ship(0), region(0), external_ship(0), external_body(0),
+
51 virt_az(0), virt_el(0), virt_x(0), virt_y(0), virt_z(0),
+
52 azimuth(PI/4), elevation(PI/4), az_rate(0), el_rate(0), range_rate(0),
+
53 range(0), range_min(100), range_max(range_max_limit),
+
54 base_range(0), transition(0), hud(0)
+
55 {
+
56  instance = this;
+
57 }
+
58 
+
59 // +--------------------------------------------------------------------+
+
60 
+ +
62 {
+
63  if (instance == this)
+
64  instance = 0;
+
65 }
+
66 
+
67 // +--------------------------------------------------------------------+
+
68 
+
69 void
+ +
71 {
+ + + +
75 
+
76  sim = 0;
+
77  ship = 0;
+
78  region = 0;
+
79  external_ship = 0;
+
80  external_body = 0;
+
81  transition = 0;
+
82  hud = 0;
+
83 }
+
84 
+
85 // +--------------------------------------------------------------------+
+
86 
+
87 void
+ +
89 {
+
90  sim = Sim::GetSim();
+ +
92 
+
93  // can't take control of a dead ship:
+
94  if (s && (s->Life() == 0 || s->IsDying() || s->IsDead()))
+
95  return;
+
96 
+
97  // leaving the old ship, so make sure it is visible:
+
98  if (ship && ship != s) {
+
99  ship->ShowRep();
+
100  ship->HideCockpit();
+
101  }
+
102 
+
103  // taking control of the new ship:
+
104  ship = s;
+
105 
+
106  if (ship) {
+
107  Observe(ship);
+
108  region = ship->GetRegion();
+
109 
+
110  if (sim && ship->GetRegion() != sim->GetActiveRegion())
+ +
112 
+
113  range = ship->Radius() * 4;
+
114 
+
115  if (mode == MODE_COCKPIT)
+
116  mode = MODE_CHASE;
+
117 
+ +
119  ExecFrame(0);
+
120  }
+
121 }
+
122 
+
123 // +--------------------------------------------------------------------+
+
124 
+
125 void
+
126 CameraDirector::SetMode(int m, double t)
+
127 {
+
128  if (requested_mode == m)
+
129  return;
+
130 
+
131  external_point = Point();
+
132 
+
133  // save current mode for after transition:
+
134  if (m == MODE_DROP && mode != MODE_DROP)
+
135  old_mode = mode;
+
136 
+
137  // if manually leaving drop mode, forget about
+
138  // restoring the previous mode when the drop
+
139  // expires...
+
140  else if (m != MODE_DROP && mode == MODE_DROP)
+ +
142 
+
143  if (m == MODE_VIRTUAL && ship && !ship->Cockpit())
+
144  return;
+
145 
+
146  if (mode == m) {
+
147  if (mode == MODE_TARGET || mode == MODE_ORBIT)
+
148  CycleViewObject();
+
149 
+
150  return;
+
151  }
+
152 
+
153  if (m > MODE_NONE && m < MODE_LAST) {
+
154  if (m <= MODE_VIRTUAL) {
+
155  requested_mode = m;
+
156  transition = t;
+
157  external_ship = 0;
+
158  ClearGroup();
+
159 
+
160  // no easy way to do a smooth transition between
+
161  // certain modes, so just go immediately:
+
162  if ((mode == MODE_TARGET && m == MODE_CHASE) ||
+
163  (mode == MODE_COCKPIT && m == MODE_VIRTUAL) ||
+
164  (mode == MODE_VIRTUAL && m == MODE_COCKPIT))
+
165  {
+
166  mode = m;
+
167  requested_mode = 0;
+
168  transition = 0;
+
169  }
+
170  }
+
171 
+
172  else if (m == MODE_TRANSLATE || m == MODE_ZOOM) {
+
173  requested_mode = m;
+
174  transition = t;
+
175  base_range = range;
+
176  }
+
177 
+
178  else if (m >= MODE_DOCKING) {
+
179  mode = m;
+
180  transition = 0;
+
181  external_ship = 0;
+
182  ClearGroup();
+
183  }
+
184 
+
185  virt_az = 0;
+
186  virt_el = 0;
+
187  virt_x = 0;
+
188  virt_y = 0;
+
189  virt_z = 0;
+
190  }
+
191 }
+
192 
+
193 // +--------------------------------------------------------------------+
+
194 
+
195 static const char* get_camera_mode_name(int m)
+
196 {
+
197  switch (m) {
+
198  default:
+
199  case CameraDirector::MODE_NONE: return ""; break;
+
200  case CameraDirector::MODE_COCKPIT: return ""; break;
+
201  case CameraDirector::MODE_CHASE: return "Chase Cam"; break;
+
202  case CameraDirector::MODE_TARGET: return "Padlock"; break;
+
203  case CameraDirector::MODE_THREAT: return "Threatlock"; break;
+
204  case CameraDirector::MODE_VIRTUAL: return "Virtual"; break;
+ + +
207  case CameraDirector::MODE_ZOOM: return "Orbit Cam"; break;
+
208  case CameraDirector::MODE_DOCKING: return "Dock Cam"; break;
+
209  case CameraDirector::MODE_DROP: return ""; break;
+
210  }
+
211 }
+
212 
+
213 const char*
+ +
215 {
+
216  int m = GetCameraMode();
+
217 
+
218  if (m != CameraDirector::MODE_VIRTUAL) {
+
219  return get_camera_mode_name(m);
+
220  }
+
221  else if (instance) {
+
222  if (instance->virt_az > 30*DEGREES && instance->virt_az < 100*DEGREES)
+
223  return "RIGHT";
+
224 
+
225  else if (instance->virt_az >= 100*DEGREES)
+
226  return "RIGHT-AFT";
+
227 
+
228  else if (instance->virt_az < -30*DEGREES && instance->virt_az > -100*DEGREES)
+
229  return "LEFT";
+
230 
+
231  else if (instance->virt_az <= -100*DEGREES)
+
232  return "LEFT-AFT";
+
233 
+
234  else if (instance->virt_el > 15*DEGREES)
+
235  return "UP";
+
236 
+
237  else if (instance->virt_el < -15*DEGREES)
+
238  return "DOWN";
+
239 
+
240  return get_camera_mode_name(m);
+
241  }
+
242 
+
243  return "";
+
244 }
+
245 
+
246 int
+ +
248 {
+
249  if (instance) {
+
250  int op_mode = instance->mode;
+ +
252  op_mode = instance->requested_mode;
+
253  return op_mode;
+
254  }
+
255 
+
256  return 0;
+
257 }
+
258 
+
259 void
+ +
261 {
+
262  if (instance)
+
263  instance->SetMode(m, t);
+
264 }
+
265 
+
266 // +--------------------------------------------------------------------+
+
267 
+
268 double
+ +
270 {
+
271  return range_max_limit;
+
272 }
+
273 
+
274 void
+ +
276 {
+
277  if (r >= 1e3)
+
278  range_max_limit = r;
+
279 }
+
280 
+
281 void
+
282 CameraDirector::SetRangeLimits(double min, double max)
+
283 {
+
284  if (instance) {
+
285  instance->range_min = min;
+
286  instance->range_max = max;
+
287  }
+
288 }
+
289 
+
290 // +--------------------------------------------------------------------+
+
291 
+
292 void
+ +
294 {
+ +
296 }
+
297 
+
298 // +--------------------------------------------------------------------+
+
299 
+
300 void
+ +
302 {
+
303  if (!ship) return;
+
304 
+
305  Ship* current = external_ship;
+
306  external_ship = 0;
+
307 
+ +
309  while (++iter && !external_ship) {
+
310  Contact* c = iter.value();
+
311  Ship* c_ship = c->GetShip();
+
312 
+
313  if (c_ship && !current) {
+
314  external_ship = c_ship;
+
315  }
+
316 
+
317  else if (current && c_ship == current) {
+
318  while (++iter && !external_ship) {
+
319  c = iter.value();
+
320  if (c->ActLock())
+
321  external_ship = c->GetShip();
+
322  }
+
323  }
+
324  }
+
325 
+
326  if (external_ship != current) {
+
327  if (external_ship) {
+
328  if (external_ship->Life() == 0 || external_ship->IsDying() || external_ship->IsDead()) {
+ +
330  external_ship = 0;
+
331  }
+
332  else {
+ +
334  }
+
335  }
+
336 
+
337  if (mode == MODE_ORBIT) {
+ +
339  ExternalRange(1);
+
340  }
+
341  }
+
342 }
+
343 
+
344 // +--------------------------------------------------------------------+
+
345 
+
346 void
+ +
348 {
+
349  external_body = orb;
+
350 
+
351  if (external_body) {
+
352  range_min = external_body->Radius() * 2.5;
+
353  ClearGroup();
+
354  external_ship = 0;
+
355 
+
356  if (sim) {
+ +
358  if (region)
+ +
360  }
+
361 
+
362  if (ship && !region)
+
363  region = ship->GetRegion();
+
364  }
+
365 }
+
366 
+
367 // +--------------------------------------------------------------------+
+
368 
+
369 void
+ +
371 {
+
372  if (!ship) return;
+
373  if (!obj) {
+
374  obj = ship;
+
375  region = ship->GetRegion();
+
376  }
+
377 
+
378  external_body = 0;
+
379  external_point = Point();
+
380 
+ +
382 
+
383  if (obj->GetIFF() != ship->GetIFF() && !stars->InCutscene()) {
+
384  // only view solid contacts:
+
385  Contact* c = ship->FindContact(obj);
+
386  if (!c || !c->ActLock())
+
387  return;
+
388  }
+
389 
+
390  if (mode == MODE_TARGET) {
+
391  ClearGroup();
+
392  if (external_ship) {
+
393  external_ship = 0;
+
394  }
+
395  }
+
396  else if (mode >= MODE_ORBIT) {
+
397  if (quick) {
+
398  mode = MODE_ORBIT;
+
399  transition = 0;
+
400  }
+
401  else {
+ +
403  }
+
404 
+
405  if (external_group.size()) {
+
406  ClearGroup();
+
407 
+
408  if (external_ship) {
+
409  external_ship = 0;
+
410  }
+
411  }
+
412 
+
413  else {
+
414  if ((obj == external_ship) || (obj==ship && external_ship==0)) {
+
415  if (!quick)
+ +
417  }
+
418 
+
419  else if (external_ship) {
+
420  external_ship = 0;
+
421  }
+
422  }
+
423  }
+
424 
+
425  if (external_ship != obj) {
+
426  external_ship = obj;
+
427 
+
428  if (external_ship) {
+ +
430 
+
431  if (external_ship->Life() == 0 || external_ship->IsDying() || external_ship->IsDead()) {
+
432  external_ship = 0;
+
433  range_min = 100;
+
434  }
+
435  else {
+ +
437 
+
438  if (sim)
+ +
440 
+
441  range_min = external_ship->Radius() * 1.5;
+
442  }
+
443  }
+
444 
+ +
446  ExternalRange(1);
+
447  }
+
448 }
+
449 
+
450 // +--------------------------------------------------------------------+
+
451 
+
452 void
+ +
454 {
+
455  if (!ship) return;
+
456 
+ +
458 
+
459  if (!stars->InCutscene()) {
+
460  // only view solid contacts:
+
461  while (++group) {
+
462  Ship* s = group.value();
+
463 
+
464  if (s->GetIFF() != ship->GetIFF()) {
+
465  Contact* c = ship->FindContact(s);
+
466  if (!c || !c->ActLock())
+
467  return;
+
468  }
+
469 
+
470  if (s->Life() == 0 || s->IsDying() || s->IsDead())
+
471  return;
+
472  }
+
473  }
+
474 
+
475  group.reset();
+
476 
+
477  if (external_group.size() > 1 &&
+
478  external_group.size() == group.size()) {
+
479 
+
480  bool same = true;
+
481 
+
482  for (int i = 0; same && i < external_group.size(); i++) {
+
483  if (external_group[i] != group.container()[i])
+
484  same = false;
+
485  }
+
486 
+
487  if (same) {
+ +
489  return;
+
490  }
+
491  }
+
492 
+
493  ClearGroup();
+
494 
+
495  if (quick) {
+
496  mode = MODE_ORBIT;
+
497  transition = 0;
+
498  }
+
499  else {
+ +
501  }
+
502 
+ +
504 
+ +
506  while (++iter) {
+
507  Ship* s = iter.value();
+
508  region = s->GetRegion();
+
509  Observe(s);
+
510  }
+
511 }
+
512 
+
513 // +--------------------------------------------------------------------+
+
514 
+
515 void
+
516 CameraDirector::VirtualHead(double az, double el)
+
517 {
+
518  if (mode == MODE_VIRTUAL || mode == MODE_TARGET || mode == MODE_COCKPIT) {
+
519  const double alimit = 3*PI/4;
+
520  const double e_lo = PI/8;
+
521  const double e_hi = PI/3;
+
522  const double escale = e_hi;
+
523 
+
524  virt_az = az * alimit;
+
525  virt_el = el * escale;
+
526 
+
527  if (virt_az > alimit)
+
528  virt_az = alimit;
+
529 
+
530  else if (virt_az < -alimit)
+
531  virt_az = -alimit;
+
532 
+
533  if (virt_el > e_hi)
+
534  virt_el = e_hi;
+
535 
+
536  else if (virt_el < -e_lo)
+
537  virt_el = -e_lo;
+
538  }
+
539 }
+
540 
+
541 void
+
542 CameraDirector::VirtualHeadOffset(double x, double y, double z)
+
543 {
+
544  if (mode == MODE_VIRTUAL || mode == MODE_TARGET || mode == MODE_COCKPIT) {
+
545  virt_x = x;
+
546  virt_y = y;
+
547  virt_z = z;
+
548  }
+
549 }
+
550 
+
551 void
+ +
553 {
+
554  if (mode == MODE_VIRTUAL || mode == MODE_TARGET || mode == MODE_COCKPIT) {
+
555  virt_az += delta;
+
556 
+
557  const double alimit = 3*PI/4;
+
558 
+
559  if (virt_az > alimit)
+
560  virt_az = alimit;
+
561 
+
562  else if (virt_az < -alimit)
+
563  virt_az = -alimit;
+
564  }
+
565 }
+
566 
+
567 void
+ +
569 {
+
570  if (mode == MODE_VIRTUAL || mode == MODE_TARGET || mode == MODE_COCKPIT) {
+
571  virt_el += delta;
+
572 
+
573  const double e_lo = PI/8;
+
574  const double e_hi = PI/3;
+
575 
+
576  if (virt_el > e_hi)
+
577  virt_el = e_hi;
+
578 
+
579  else if (virt_el < -e_lo)
+
580  virt_el = -e_lo;
+
581  }
+
582 }
+
583 
+
584 // +--------------------------------------------------------------------+
+
585 
+
586 void
+ +
588 {
+
589  azimuth += delta;
+
590 
+
591  if (azimuth > PI)
+
592  azimuth = -2*PI + azimuth;
+
593 
+
594  else if (azimuth < -PI)
+
595  azimuth = 2*PI + azimuth;
+
596 }
+
597 
+
598 void
+ +
600 {
+
601  elevation += delta;
+
602 
+
603  const double limit = (0.43 * PI);
+
604 
+
605  if (elevation > limit)
+
606  elevation = limit;
+
607  else if (elevation < -limit)
+
608  elevation = -limit;
+
609 }
+
610 
+
611 void
+ +
613 {
+
614  range *= delta;
+
615 
+
616  if (ship && ship->IsAirborne())
+
617  range_max = 30e3;
+
618  else
+
619  range_max = range_max_limit;
+
620 
+
621  if (range < range_min)
+
622  range = range_min;
+
623 
+
624  else if (range > range_max)
+
625  range = range_max;
+
626 }
+
627 
+
628 // +--------------------------------------------------------------------+
+
629 
+
630 void
+
631 CameraDirector::SetOrbitPoint(double a, double e, double r)
+
632 {
+
633  azimuth = a;
+
634  elevation = e;
+
635  range = r;
+
636 
+
637  if (external_body) {
+
638  if (range < external_body->Radius() * 2)
+
639  range = external_body->Radius() * 2;
+
640 
+
641  else if (range > external_body->Radius() * 6)
+
642  range = external_body->Radius() * 6;
+
643  }
+
644 
+
645  else {
+
646  if (range < range_min)
+
647  range = range_min;
+
648 
+
649  else if (range > range_max)
+
650  range = range_max;
+
651  }
+
652 }
+
653 
+
654 void
+
655 CameraDirector::SetOrbitRates(double ar, double er, double rr)
+
656 {
+
657  az_rate = ar;
+
658  el_rate = er;
+
659 
+
660  range_rate = rr;
+
661 }
+
662 
+
663 // +--------------------------------------------------------------------+
+
664 
+
665 bool
+ +
667 {
+
668  if (obj->Type() == SimObject::SIM_SHIP) {
+
669  Ship* s = (Ship*) obj;
+
670  if (ship == s)
+
671  ship = 0;
+
672 
+
673  if (external_ship == s) {
+
674  external_point = s->Location();
+
675  external_ship = 0;
+
676  }
+
677 
+
678  if (external_group.contains(s))
+ +
680  }
+
681 
+
682  return SimObserver::Update(obj);
+
683 }
+
684 
+
685 const char*
+ +
687 {
+
688  return "CameraDirector";
+
689 }
+
690 
+
691 // +--------------------------------------------------------------------+
+
692 
+
693 void
+ +
695 {
+
696  if (!ship)
+
697  return;
+
698 
+ +
700 
+
701  int flight_phase = ship->GetFlightPhase();
+
702 
+
703  if (flight_phase < Ship::LOCKED)
+ +
705 
+
706  if (ship->IsAirborne()) {
+
707  if (flight_phase >= Ship::DOCKING)
+ +
709  }
+
710  else {
+
711  if (flight_phase >= Ship::RECOVERY)
+ +
713  }
+
714 
+
715  if (flight_phase >= Ship::LOCKED && flight_phase < Ship::ACTIVE) {
+
716  int m = GetMode();
+
717  if (m != MODE_COCKPIT && m != MODE_VIRTUAL)
+ +
719  }
+
720 
+
721  if (ship->InTransition()) {
+ +
723  }
+
724  // automatically restore mode after transition:
+
725  else if (old_mode != MODE_NONE) {
+
726  mode = old_mode;
+ + +
729  }
+
730 
+
731  int op_mode = mode;
+
732  if (requested_mode > mode)
+
733  op_mode = requested_mode;
+
734 
+ +
736 
+
737  // if we are in padlock, and have not locked a ship
+
738  // try to padlock the current target:
+
739  if (op_mode == MODE_TARGET && !external_ship) {
+
740  SimObject* tgt = ship->GetTarget();
+
741  if (tgt && tgt->Type() == SimObject::SIM_SHIP)
+
742  SetViewObject((Ship*) tgt);
+
743  }
+
744 
+
745  // if in an external mode, check the external ship:
+
746  else if (op_mode >= MODE_TARGET && op_mode <= MODE_ZOOM) {
+
747  if (external_ship && external_ship != ship && !stars->InCutscene()) {
+ +
749  if (!c || !c->ActLock()) {
+ +
751  }
+
752  }
+
753  }
+
754 
+
755  if (ship->Rep()) {
+
756  if (op_mode == MODE_COCKPIT) {
+
757  ship->HideRep();
+
758  ship->HideCockpit();
+
759  }
+
760  else if (op_mode == MODE_VIRTUAL || op_mode == MODE_TARGET) {
+
761  if (ship->Cockpit()) {
+
762  ship->HideRep();
+
763  ship->ShowCockpit();
+
764  }
+
765  else {
+
766  ship->ShowRep();
+
767  }
+
768  }
+
769  else {
+
770  ship->Rep()->SetForeground(op_mode == MODE_DOCKING);
+
771  ship->ShowRep();
+
772  ship->HideCockpit();
+
773  }
+
774  }
+
775 
+
776  if (hud && hud->Ambient() != Color::Black)
+
777  sim->GetScene()->SetAmbient( hud->Ambient() );
+
778  else
+ +
780 
+
781  switch (op_mode) {
+
782  default:
+
783  case MODE_COCKPIT: Cockpit(seconds); break;
+
784  case MODE_CHASE: Chase(seconds); break;
+
785  case MODE_TARGET: Target(seconds); break;
+
786  case MODE_THREAT: Threat(seconds); break;
+
787  case MODE_VIRTUAL: Virtual(seconds); break;
+
788  case MODE_ORBIT:
+
789  case MODE_TRANSLATE:
+
790  case MODE_ZOOM: Orbit(seconds); break;
+
791  case MODE_DOCKING: Docking(seconds); break;
+
792  case MODE_DROP: Drop(seconds); break;
+
793  }
+
794 
+
795  if (ship->Shake() > 0 &&
+
796  (op_mode < MODE_ORBIT ||
+
797  (op_mode == MODE_VIRTUAL && ship->Cockpit()))) {
+
798 
+
799  Point vib = ship->Vibration() * 0.2;
+
800  camera.MoveBy(vib);
+
801  camera.Aim(0, vib.y, vib.z);
+
802  }
+
803 
+
804  Transition(seconds);
+ +
806 }
+
807 
+
808 // +--------------------------------------------------------------------+
+
809 
+
810 void
+ +
812 {
+
813  if (transition > 0)
+
814  transition -= seconds * 1.5;
+
815 
+
816  if (transition <= 0) {
+
817  transition = 0;
+
818 
+ + +
821 
+
822  requested_mode = 0;
+
823 
+
824  if (mode == MODE_TRANSLATE || mode == MODE_ZOOM) {
+
825  if (mode == MODE_ZOOM)
+
826  range = range_min;
+
827 
+
828  mode = MODE_ORBIT;
+
829  }
+
830  }
+
831 }
+
832 
+
833 // +--------------------------------------------------------------------+
+
834 
+
835 bool
+ +
837 {
+
838  if (instance) {
+
839  double fvaz = fabs(instance->virt_az);
+
840  double fvel = fabs(instance->virt_el);
+
841 
+
842  return fvaz < 15*DEGREES && fvel < 15*DEGREES;
+
843  }
+
844 
+
845  return true;
+
846 }
+
847 
+
848 // +--------------------------------------------------------------------+
+
849 
+
850 void
+
851 CameraDirector::Cockpit(double seconds)
+
852 {
+
853  camera.Clone(ship->Cam());
+
854 
+
855  Point bridge = ship->BridgeLocation();
+
856  Point cpos = camera.Pos() +
+
857  camera.vrt() * bridge.x +
+
858  camera.vpn() * bridge.y +
+
859  camera.vup() * bridge.z;
+
860 
+
861  camera.MoveTo(cpos);
+
862 }
+
863 
+
864 // +--------------------------------------------------------------------+
+
865 
+
866 void
+
867 CameraDirector::Virtual(double seconds)
+
868 {
+
869  camera.Clone(ship->Cam());
+
870 
+
871  Point bridge = ship->BridgeLocation();
+
872  Point cpos = camera.Pos() +
+
873  camera.vrt() * (bridge.x + virt_x) +
+
874  camera.vpn() * (bridge.y + virt_z) +
+
875  camera.vup() * (bridge.z + virt_y);
+
876 
+
877  camera.MoveTo(cpos);
+
878 
+
879  camera.Yaw(virt_az);
+
880  camera.Pitch(-virt_el);
+
881 
+
882  double fvaz = fabs(virt_az);
+
883  double fvel = fabs(virt_el);
+
884 
+
885  if (fvaz > 0.01*DEGREES && fvaz < 15*DEGREES) {
+
886  double bleed = fvaz * 2;
+
887 
+
888  if (virt_az > 0)
+
889  virt_az -= bleed * seconds;
+
890  else
+
891  virt_az += bleed * seconds;
+
892  }
+
893 
+
894  if (fvel > 0.01*DEGREES && fvel < 15*DEGREES) {
+
895  double bleed = fvel;
+
896 
+
897  if (virt_el > 0)
+
898  virt_el -= bleed * seconds;
+
899  else
+
900  virt_el += bleed * seconds;
+
901  }
+
902 }
+
903 
+
904 // +--------------------------------------------------------------------+
+
905 
+
906 void
+
907 CameraDirector::Chase(double seconds)
+
908 {
+
909  double step = 1;
+
910 
+ +
912  step = transition;
+
913 
+
914  else if (requested_mode == MODE_CHASE)
+
915  step = 1 - transition;
+
916 
+
917  camera.Clone(ship->Cam());
+
918  Point velocity = camera.vpn();
+
919 
+
920  if (ship->Velocity().length() > 10) {
+
921  velocity = ship->Velocity();
+
922  velocity.Normalize();
+
923  velocity *= 0.25;
+
924  velocity += camera.vpn() * 2;
+
925  velocity.Normalize();
+
926  }
+
927 
+
928  Point chase = ship->ChaseLocation();
+
929  Point bridge = ship->BridgeLocation();
+
930  Point cpos = camera.Pos() +
+
931  camera.vrt() * bridge.x * (1-step) +
+
932  camera.vpn() * bridge.y * (1-step) +
+
933  camera.vup() * bridge.z * (1-step) +
+
934  velocity * chase.y * step +
+
935  camera.vup() * chase.z * step;
+
936 
+
937  camera.MoveTo(cpos);
+
938 }
+
939 
+
940 // +--------------------------------------------------------------------+
+
941 
+
942 void
+
943 CameraDirector::Target(double seconds)
+
944 {
+
945  Point target_loc = external_point;
+
946 
+
947  if (external_ship)
+
948  target_loc = external_ship->Location();
+
949 
+
950  if (!external_ship || external_ship == ship) {
+
951  if (!external_point) {
+
952  if (ship->Cockpit())
+
953  Virtual(seconds);
+
954  else
+
955  Orbit(seconds);
+
956 
+
957  return;
+
958  }
+
959  }
+
960 
+
961  double step = 1;
+
962 
+ +
964  step = transition;
+
965 
+
966  else if (requested_mode == MODE_TARGET)
+
967  step = 1 - transition;
+
968 
+
969  if (ship->Cockpit()) {
+
970  // internal padlock:
+
971  Cockpit(seconds);
+
972  camera.Padlock(target_loc, 3*PI/4, PI/8, PI/3);
+
973  }
+
974  else {
+
975  // external padlock:
+
976  Point delta = target_loc - ship->Location();
+
977  delta.Normalize();
+
978  delta *= -5 * ship->Radius() * step;
+
979  delta.y += ship->Radius() * step;
+
980 
+
981  camera.MoveTo(ship->Location() + delta);
+
982  camera.LookAt(target_loc);
+
983  }
+
984 }
+
985 
+
986 // +--------------------------------------------------------------------+
+
987 
+
988 void
+
989 CameraDirector::Threat(double seconds)
+
990 {
+
991  Chase(seconds);
+
992 }
+
993 
+
994 // +--------------------------------------------------------------------+
+
995 
+
996 void
+
997 CameraDirector::Orbit(double seconds)
+
998 {
+
999  Point cpos = ship->Location();
+
1000  int op_mode = GetCameraMode();
+
1001 
+
1002  if (seconds < 0) seconds = 0;
+
1003  else if (seconds > 0.2) seconds = 0.2;
+
1004 
+
1005  // auto rotate
+
1006  azimuth += az_rate * seconds;
+
1007  elevation += el_rate * seconds;
+
1008  range *= 1 + range_rate * seconds;
+
1009 
+
1010  if (external_body && external_body->Rep()) {
+
1011  range_min = external_body->Radius() * 2.5;
+
1012  cpos = external_body->Rep()->Location();
+
1013  }
+
1014 
+
1015  else if (external_group.size()) {
+
1016  Point neg(1e9, 1e9, 1e9);
+
1017  Point pos(-1e9, -1e9, -1e9);
+
1018 
+ +
1020  while (++iter) {
+
1021  Point loc = iter->Location();
+
1022 
+
1023  if (loc.x < neg.x) neg.x = loc.x;
+
1024  if (loc.x > pos.x) pos.x = loc.x;
+
1025  if (loc.y < neg.y) neg.y = loc.y;
+
1026  if (loc.y > pos.y) pos.y = loc.y;
+
1027  if (loc.z < neg.z) neg.z = loc.z;
+
1028  if (loc.z > pos.z) pos.z = loc.z;
+
1029  }
+
1030 
+
1031  double dx = pos.x - neg.x;
+
1032  double dy = pos.y - neg.y;
+
1033  double dz = pos.z - neg.z;
+
1034 
+
1035  if (dx > dy) {
+
1036  if (dx > dz) range_min = dx * 1.2;
+
1037  else range_min = dz * 1.2;
+
1038  }
+
1039  else {
+
1040  if (dy > dz) range_min = dy * 1.2;
+
1041  else range_min = dz * 1.2;
+
1042  }
+
1043 
+
1044  // focus on median location:
+
1045  cpos = neg + Point(dx/2, dy/2, dz/2);
+
1046  }
+
1047  else if (external_ship) {
+
1048  range_min = external_ship->Radius() * 1.5;
+
1049  cpos = external_ship->Location();
+
1050  }
+
1051  else {
+
1052  range_min = ship->Radius() * 1.5;
+
1053  cpos = ship->Location();
+
1054  }
+
1055 
+
1056  if (range < range_min)
+
1057  range = range_min;
+
1058 
+
1059  double er = range;
+
1060  double az = azimuth;
+
1061  double el = elevation;
+
1062 
+
1063  if (requested_mode == MODE_TRANSLATE) {
+
1064  cpos = cpos*(1-transition) + base_loc*(transition);
+
1065  }
+
1066 
+
1067  else if (requested_mode == MODE_ZOOM) {
+
1068  er = base_range * transition;
+
1069 
+
1070  if (er < range_min) {
+
1071  er = range_min;
+
1072  range = range_min;
+
1073  transition = 0;
+
1074  requested_mode = 0;
+
1075  }
+
1076  }
+
1077 
+
1078  // transitions:
+
1079  else if (mode < MODE_ORBIT || requested_mode > 0 && requested_mode < MODE_ORBIT) {
+
1080  double az0 = ship->CompassHeading();
+
1081  if (fabs(az-az0) > PI) az0 -= 2*PI;
+
1082 
+
1083  double r0 = 0;
+
1084  double z0 = 0;
+
1085 
+
1086  if (mode == MODE_CHASE || requested_mode == MODE_CHASE ||
+ +
1088  r0 = ship->ChaseLocation().length();
+
1089  z0 = 20 * DEGREES;
+
1090  }
+
1091 
+
1092  // pull out:
+
1093  if (mode < MODE_ORBIT) {
+
1094  er *= (1-transition);
+
1095  az *= (1-transition);
+
1096  el *= (1-transition);
+
1097 
+
1098  er += r0 * transition;
+
1099  az += az0 * transition;
+
1100  el += z0 * transition;
+
1101  }
+
1102 
+
1103  // push in:
+
1104  else {
+
1105  er *= transition;
+
1106  az *= transition;
+
1107  el *= transition;
+
1108 
+
1109  er += r0 * (1-transition);
+
1110  az += az0 * (1-transition);
+
1111  el += z0 * (1-transition);
+
1112  }
+
1113  }
+
1114 
+
1115  else {
+
1116  // save base location for next time we re-focus
+
1117  base_loc = cpos;
+
1118  }
+
1119 
+
1120  double dx = er * sin(az) * cos(el);
+
1121  double dy = er * cos(az) * cos(el);
+
1122  double dz = er * sin(el);
+
1123 
+
1124  Point cloc = cpos + Point(dx,dz,dy);
+
1125 
+
1126  Terrain* terrain = ship->GetRegion()->GetTerrain();
+
1127 
+
1128  if (terrain) {
+
1129  double cam_agl = cloc.y - terrain->Height(cloc.x, cloc.z);
+
1130 
+
1131  if (cam_agl < 100)
+
1132  cloc.y = terrain->Height(cloc.x, cloc.z) + 100;
+
1133  }
+
1134 
+
1135  if (external_ship == 0 && er < 0.5 * ship->Radius())
+
1136  ship->Rep()->Hide();
+
1137 
+
1138  camera.MoveTo(cloc.x, cloc.y, cloc.z);
+
1139  camera.LookAt(cpos);
+
1140 }
+
1141 
+
1142 // +--------------------------------------------------------------------+
+
1143 
+
1144 void
+ +
1146 {
+
1147  FlightDeck* dock = ship->GetDock();
+
1148 
+
1149  if (!dock) {
+
1150  Cockpit(seconds);
+
1151  return;
+
1152  }
+
1153 
+
1154  if (!ship->IsAirborne())
+
1155  sim->GetScene()->SetAmbient(Color(120,130,140));
+
1156  int flight_phase = ship->GetFlightPhase();
+
1157 
+
1158  Point bridge = ship->BridgeLocation();
+
1159  Point cloc = ship->Location() +
+
1160  ship->Cam().vrt() * bridge.x +
+
1161  ship->Cam().vpn() * bridge.y +
+
1162  ship->Cam().vup() * bridge.z;
+
1163 
+
1164  Point cpos = dock->CamLoc();
+
1165 
+
1166  // preflight:
+
1167  if (flight_phase < Ship::LOCKED) {
+
1168  base_loc = cpos;
+
1169  }
+
1170 
+
1171  else if (flight_phase == Ship::LOCKED) {
+
1172  if (hud)
+ +
1174  cpos = base_loc * transition +
+
1175  cloc * (1-transition);
+
1176  }
+
1177 
+
1178  // recovery:
+
1179  else if (flight_phase > Ship::APPROACH) {
+
1180  if (hud)
+
1181  hud->SetTacticalMode(1);
+
1182  }
+
1183 
+
1184  camera.MoveTo(cpos);
+
1185  camera.LookAt(cloc);
+
1186 }
+
1187 
+
1188 // +--------------------------------------------------------------------+
+
1189 
+
1190 void
+
1191 CameraDirector::Drop(double seconds)
+
1192 {
+
1193  // orbital transitions use "drop cam" at transition_loc
+ +
1195  camera.LookAt(ship->Location());
+
1196 }
+
+
+ + + + -- cgit v1.1