Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

Cameras.cpp

Go to the documentation of this file.
00001 /*
00002  * Cameras.cpp
00003  *
00004  * Part of Fly! Legacy project
00005  *
00006  * Copyright 2003 Chris Wallace
00007  *
00008  * Fly! Legacy is free software; you can redistribute it and/or modify
00009  *   it under the terms of the GNU General Public License as published by
00010  *   the Free Software Foundation; either version 2 of the License, or
00011  *   (at your option) any later version.
00012  *
00013  * Fly! Legacy is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  *   along with Fly! Legacy; if not, write to the Free Software
00020  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00035 #include "../Include/WorldObjects.h"
00036 #include "../Include/Cameras.h"
00037 #include "../Include/Utility.h"
00038 #include "../Include/Ui.h"
00039 #include "../Include/Globals.h"
00040 
00041 using namespace std;
00042 
00043 
00044 //
00045 // CCamera base class methods
00046 //
00047 CCamera::CCamera (void)
00048 {
00049   fov = 60; // Degrees
00050   r = 50;   // Feet?
00051 
00052   // Set min/max bounds for range
00053   
00059   rmin = 50;
00060   rmax = 500;
00061 
00062   // Initialize heading, pitch
00063   h = p = 0;
00064 }
00065 
00066 
00067 inline float CCamera::GetFOV (void)
00068 {
00069   return fov;
00070 }
00071 
00072 //
00073 // Decrease camera FOV by 5 degrees
00074 //
00075 void CCamera::ZoomRatioIn (void)
00076 {
00077   fov -= 5;
00078   if (fov < 20) fov = 20;
00079 }
00080 
00081 //
00082 // Increase camera FOV by 5 degrees
00083 //
00084 void CCamera::ZoomRatioOut (void)
00085 {
00086   fov += 5;
00087   if (fov > 90) fov = 90;
00088 }
00089 
00090 
00091 //
00092 // Zoom in by 10% of current range
00093 //
00094 void CCamera::ZoomIn (void)
00095 {
00096   r /= 1.10;
00097   if (r < rmin) r = rmin;
00098 }
00099 
00100 //
00101 // Zoom in by 5% of current range
00102 //
00103 void CCamera::ZoomInSlow (void)
00104 {
00105   r /= 1.05;
00106   if (r < rmin) r = rmin;
00107 }
00108 
00109 //
00110 // Zoom in by 25% of current range
00111 //
00112 void CCamera::ZoomInFast (void)
00113 {
00114   r /= 1.25;
00115   if (r < rmin) r = rmin;
00116 }
00117 
00118 //
00119 // Zoom out by 10% of current range
00120 //
00121 void CCamera::ZoomOut (void)
00122 {
00123   r *= 1.10;
00124   if (r > rmax) r = rmax;
00125 }
00126 
00127 //
00128 // Zoom out by 5% of current range
00129 //
00130 void CCamera::ZoomOutSlow (void)
00131 {
00132   r *= 1.05;
00133   if (r > rmax) r = rmax;
00134 }
00135 
00136 //
00137 // Zoom out by 25% of current range
00138 //
00139 void CCamera::ZoomOutFast (void)
00140 {
00141   r *= 1.25;
00142   if (r > rmax) r = rmax;
00143 }
00144 
00145 
00146 //
00147 // Reset zoom range to default
00148 //
00149 void CCamera::ZoomReset (void)
00150 {
00151   r = 50;   // Feet
00152 }
00153 
00154 //
00155 // Calculate offset of camera from target origin
00156 //
00157 void CCamera::GetCameraOffset (SVector *v)
00158 {
00159   v->x = r;
00160   v->y = 0;
00161   v->z = r;
00162 }
00163 
00164 
00165 //
00166 // Calculate Euler angle orientation of camera
00167 //
00168 void CCamera::GetCameraOrientation (SVector *v)
00169 {
00170   v->h = h;
00171   v->p = p;
00172   v->r = r;
00173 }
00174 
00175 void CCamera::UpdateCamera (SPosition *targetPosition, SVector *targetOrientation,
00176                             SPosition *eyePosition, SVector *eyeOrientation,
00177                             const float dT)
00178 {
00179   // Get offset, add to target position
00180   SVector v;
00181   GetCameraOffset (&v);
00182   *eyePosition = AddVector (*targetPosition, v);
00183 
00184   // Get orientation, add to target orientation
00185   SVector orient;
00186   GetCameraOrientation (&orient);
00187   eyeOrientation->h = WrapTwoPi (targetOrientation->h + orient.h);
00188   eyeOrientation->p = WrapTwoPi (targetOrientation->p + orient.p);
00189   eyeOrientation->r = WrapTwoPi (targetOrientation->r + orient.r);
00190 }
00191 
00192 
00193 /*
00194  * CCockpitPanel class represents one node in the graph of interconnected
00195  *   cockpit panels encapsulated within the CCockpitCamera object.
00196  *
00197  * Each node is identified by the unique panel ID (which is passed to
00198  *   CCockpitManager to activate the current panel) and the IDs of
00199  *   the four panels to the left, right, up and down.
00200  */
00201 
00202 typedef enum {
00203   PANEL_LEFT    = 0,
00204   PANEL_RIGHT   = 1,
00205   PANEL_UP      = 2,
00206   PANEL_DOWN    = 3
00207 } EPanelScrollDirection;
00208 
00209 
00210 CCockpitPanel::CCockpitPanel (void) :
00211   id (0),
00212   main (false),
00213   hdg (0.0f),
00214   pitch (0.0f)
00215 {
00216   pnls[0] = pnls[1] = pnls[2] = pnls[3] = StringToTag ("NONE");
00217   ofst_x = ofst_y = ofst_z = 0;
00218   xscr_x = xscr_y = 0;
00219   umdl = 0;
00220 }
00221 
00222 int CCockpitPanel::Read (SStream *stream, Tag tag)
00223 {
00224   int rc = TAG_IGNORED;
00225 
00226   switch (tag) {
00227   case 'id__':
00228     ReadTag (&id, stream);
00229     rc = TAG_READ;
00230     break;
00231 
00232   case 'main':
00233     main = true;
00234     rc = TAG_READ;
00235     break;
00236 
00237   case 'hdg_':
00238     ReadFloat (&hdg, stream);
00239     rc = TAG_READ;
00240     break;
00241 
00242   case 'ptch':
00243     ReadFloat (&pitch, stream);
00244     rc = TAG_READ;
00245     break;
00246 
00247   case 'pnls':
00248     // Read four panel ID tags corresponding to the panels to the L, R, U and D
00249     ReadTag (&pnls[0], stream);
00250     ReadTag (&pnls[1], stream);
00251     ReadTag (&pnls[2], stream);
00252     ReadTag (&pnls[3], stream);
00253     rc = TAG_READ;
00254     break;
00255 
00256   case 'ofst':
00257     ReadFloat (&ofst_x, stream);
00258     ReadFloat (&ofst_y, stream);
00259     ReadFloat (&ofst_z, stream);
00260     rc = TAG_READ;
00261     break;
00262 
00263   case 'xscr':
00264     ReadFloat (&xscr_x, stream);
00265     ReadFloat (&xscr_y, stream);
00266     rc = TAG_READ;
00267     break;
00268 
00269   case 'umdl':
00270     ReadInt (&umdl, stream);
00271     rc = TAG_READ;
00272     break;
00273   }
00274 
00275   if (rc == TAG_IGNORED) {
00276     char s[16];
00277     TagToString (s, tag);
00278     globals->logWarning->Write ("CCockpitPanel::Read : Unknown tag %s", s);
00279   }
00280 
00281   return rc;
00282 }
00283 
00284 
00285 //
00286 // Cockpit (vehicle interior) camera
00287 //
00288 CCameraCockpit::CCameraCockpit (void)
00289 {
00290   seat_hpr.h = seat_hpr.p = seat_hpr.r = 0;
00291   seat_xyz.x = seat_xyz.y = seat_xyz.z = 0;
00292 
00293   // Initialize active panel to none
00294   pCockpitPanel = NULL;
00295 }
00296 
00297 CCameraCockpit::~CCameraCockpit (void)
00298 {
00299   // Delete panels
00300   map<Tag,CCockpitPanel*>::iterator iter;
00301   for (iter=panl.begin(); iter!=panl.end(); iter++) {
00302     CCockpitPanel *p = iter->second;
00303     delete p;
00304   }
00305 }
00306 
00307 int CCameraCockpit::Read (SStream *stream, Tag tag)
00308 {
00309   int rc = TAG_IGNORED;
00310 
00311   switch (tag) {
00312   case 'seat':
00313     // Read seat orientation (in degrees relative to straight ahead)
00314     ReadDouble (&seat_hpr.h, stream);
00315     ReadDouble (&seat_hpr.p, stream);
00316     ReadDouble (&seat_hpr.r, stream);
00317 
00318     // Convert orientation angles to radians
00319     seat_hpr.h = DegToRad (seat_hpr.h);
00320     seat_hpr.p = DegToRad (seat_hpr.p);
00321     seat_hpr.r = DegToRad (seat_hpr.r);
00322 
00323     // Read seat offset (in feet from model center)
00324     ReadDouble (&seat_xyz.x, stream);
00325     ReadDouble (&seat_xyz.y, stream);
00326     ReadDouble (&seat_xyz.z, stream);
00327     rc = TAG_READ;
00328     break;
00329 
00330   case 'panl':
00331     {
00332       CCockpitPanel *cock_panel = new CCockpitPanel;
00333       ReadFrom (cock_panel, stream);
00334       Tag tag = cock_panel->id;
00335       panl[tag] = cock_panel;
00336     }
00337     rc = TAG_READ;
00338     break;
00339   }
00340 
00341   if (rc == TAG_IGNORED) {
00342     char s[16];
00343     TagToString (s, tag);
00344     globals->logWarning->Write ("CCockpitPanel::Read : Unknown tag %s", s);
00345   }
00346 
00347   return rc;
00348 }
00349 
00350 void CCameraCockpit::ReadFinished (void)
00351 {
00352   // Set the default panel ID to the first with the <main> tag present
00353   map<Tag,CCockpitPanel*>::iterator iter;
00354   for (iter=panl.begin(); iter!=panl.end(); iter++) {
00355     CCockpitPanel *p = iter->second;
00356     if (p->main) {
00357       if (pCockpitPanel == NULL) {
00358         // This is the first <main> panel...assign it as the default
00359         pCockpitPanel = p;
00360       } else {
00361         // There should be only one <main> panel, generate a warning
00362         globals->logWarning->Write ("CCameraCockpit : Multiple <main> panels");
00363       }
00364     }
00365   }
00366 }
00367 
00368 //
00369 // Calculate offset of camera from target origin
00370 //
00371 
00381 void CCameraCockpit::GetCameraOffset (SVector *v)
00382 {
00383   v->x = 0;
00384   v->y = 0;
00385   v->z = -5.0;
00386 
00387   // Offsets must be converted from LHS->RHS system (swap y and z coords)
00388 //  v->x = seat_xyz.x;
00389 //  v->y = seat_xyz.z;
00390 //  v->z = seat_xyz.y;
00391 }
00392 
00393 //
00394 // Calculate Euler angle orientation of camera
00395 //
00396 void CCameraCockpit::GetCameraOrientation (SVector *v)
00397 {
00398   v->h = seat_hpr.h;
00399   v->p = seat_hpr.r;
00400   v->r = seat_hpr.p;
00401 }
00402 
00403 CCockpitPanel*  CCameraCockpit::FindCockpitPanel (Tag tag)
00404 {
00405   CCockpitPanel* rc = NULL;
00406 
00407   map<Tag,CCockpitPanel*>::iterator iter = panl.find(tag);
00408   if (iter != panl.end()) {
00409     rc = iter->second;
00410   }
00411 
00412   return rc;
00413 }
00414 
00415 void CCameraCockpit::ActivateCockpitPanel (Tag tag)
00416 {
00417   CCockpitPanel *p = FindCockpitPanel(tag);
00418   if (p != NULL) {
00419     pCockpitPanel = p;
00420     seat_hpr.h = p->hdg;
00421     seat_hpr.p = p->pitch;
00422   } else {
00423     globals->logWarning->Write ("CCameraCockpit::ActivateCockpitPanel : NULL cockpit panel");
00424   }
00425 }
00426 
00427 Tag  CCameraCockpit::GetCockpitPanel (void)
00428 {
00429   Tag rc = 0;
00430 
00431   if (pCockpitPanel) rc = pCockpitPanel->id;
00432 
00433   return rc;
00434 }
00435 
00436 //
00437 // Pan Left - switch panels to the one to the left
00438 //
00439 void CCameraCockpit::PanLeft (void)
00440 {
00441   if (pCockpitPanel) {
00442     Tag tag = pCockpitPanel->pnls[PANEL_LEFT];
00443     if (tag != StringToTag ("NONE")) {
00444       ActivateCockpitPanel (tag);
00445     }
00446   }
00447 }
00448 
00449 //
00450 // Pan Right - switch panels to the one to the right
00451 //
00452 void CCameraCockpit::PanRight (void)
00453 {
00454   if (pCockpitPanel) {
00455     Tag tag = pCockpitPanel->pnls[PANEL_RIGHT];
00456     if (tag != StringToTag ("NONE")) {
00457       ActivateCockpitPanel (tag);
00458     }
00459   }
00460 }
00461 
00462 //
00463 // Pan Up
00464 //
00465 void CCameraCockpit::PanUp (void)
00466 {
00467   if (pCockpitPanel) {
00468     Tag tag = pCockpitPanel->pnls[PANEL_UP];
00469     if (tag != StringToTag ("NONE")) {
00470       ActivateCockpitPanel (tag);
00471     }
00472   }
00473 }
00474 
00475 //
00476 // Pan Down
00477 //
00478 void CCameraCockpit::PanDown (void)
00479 {
00480   if (pCockpitPanel) {
00481     Tag tag = pCockpitPanel->pnls[PANEL_DOWN];
00482     if (tag != StringToTag ("NONE")) {
00483       ActivateCockpitPanel (tag);
00484     }
00485   }
00486 }
00487 
00488 //
00489 // User preset positions
00490 //
00491 void CCameraCockpit::User1 (void)
00492 {
00493   DrawNoticeToUser ("User Position 1", 5);
00494 }
00495 
00496 void CCameraCockpit::DefineUser1 (void)
00497 {
00498   DrawNoticeToUser ("Defined User Position 1", 5);
00499 }
00500 
00501 void CCameraCockpit::User2 (void)
00502 {
00503   DrawNoticeToUser ("User Position 2", 5);
00504 }
00505 
00506 void CCameraCockpit::DefineUser2 (void)
00507 {
00508   DrawNoticeToUser ("Defined User Position 2", 5);
00509 }
00510 
00511 void CCameraCockpit::User3 (void)
00512 {
00513   DrawNoticeToUser ("User Position 3", 5);
00514 }
00515 
00516 void CCameraCockpit::DefineUser3 (void)
00517 {
00518   DrawNoticeToUser ("Defined User Position 3", 5);
00519 }
00520 
00521 void CCameraCockpit::User4 (void)
00522 {
00523   DrawNoticeToUser ("User Position 4", 5);
00524 }
00525 
00526 void CCameraCockpit::DefineUser4 (void)
00527 {
00528   DrawNoticeToUser ("Defined User Position 4", 5);
00529 }
00530 
00531 void CCameraCockpit::User5 (void)
00532 {
00533   DrawNoticeToUser ("User Position 5", 5);
00534 }
00535 
00536 void CCameraCockpit::DefineUser5 (void)
00537 {
00538   DrawNoticeToUser ("Defined User Position 5", 5);
00539 }
00540 
00541 void CCameraCockpit::User6 (void)
00542 {
00543   DrawNoticeToUser ("User Position 6", 5);
00544 }
00545 
00546 void CCameraCockpit::DefineUser6 (void)
00547 {
00548   DrawNoticeToUser ("Defined User Position 6", 5);
00549 }
00550 
00551 void CCameraCockpit::User7 (void)
00552 {
00553   DrawNoticeToUser ("User Position 7", 5);
00554 }
00555 
00556 void CCameraCockpit::DefineUser7 (void)
00557 {
00558   DrawNoticeToUser ("Defined User Position 7", 5);
00559 }
00560 
00561 void CCameraCockpit::User8 (void)
00562 {
00563   DrawNoticeToUser ("User Position 8", 5);
00564 }
00565 
00566 void CCameraCockpit::DefineUser8 (void)
00567 {
00568   DrawNoticeToUser ("Defined User Position 8", 5);
00569 }
00570 
00571 void CCameraCockpit::HeadPitchUp (void)
00572 {
00573   DrawNoticeToUser ("Head Up", 5);
00574 }
00575 
00576 void CCameraCockpit::HeadPitchDown (void)
00577 {
00578   DrawNoticeToUser ("Head Down", 5);
00579 }
00580 
00581 
00582 //
00583 // CCameraSpot
00584 //
00585 // External spot camera, fixed orientation with user vehicle
00586 //
00587 
00588 CCameraSpot::CCameraSpot (void)
00589 : CCamera()
00590 {
00591   theta = DegToRad (-30.0f);
00592   phi = DegToRad (15.0f);
00593 }
00594 
00595 //
00596 // Calculate offset of camera from target origin
00597 //
00598 void CCameraSpot::GetCameraOffset (SVector *v)
00599 {
00600   CVehicleObject *vehicle = globals->sit->GetUserVehicle();
00601   SVector orient = vehicle->GetOrientation();
00602 
00603   float camTheta = orient.h + theta;
00604   float camPhi = orient.p + phi;
00605   v->x = r * sin (camTheta) * cos (camPhi);
00606   v->y = -r * cos (camTheta) * cos (camPhi);
00607   v->z = r * sin (camPhi);
00608 }
00609 
00610 //
00611 // Calculate Euler angle orientation of camera
00612 //
00613 void CCameraSpot::GetCameraOrientation (SVector *v)
00614 {
00615   CVehicleObject *vehicle = globals->sit->GetUserVehicle();
00616   SVector orient = vehicle->GetOrientation();
00617   v->h = orient.h + theta;
00618   v->p = orient.p + phi;
00619   v->r = orient.r;
00620 }
00621 
00622 //
00623 // Pan Left - rotate clockwise
00624 //
00625 void CCameraSpot::PanLeft (void)
00626 {
00627   theta = WrapTwoPi (theta - DegToRad (1.0f));
00628 }
00629 
00630 //
00631 // Pan Right - rotate counterclockwise
00632 //
00633 void CCameraSpot::PanRight (void)
00634 {
00635   theta = WrapTwoPi (theta + DegToRad (1.0f));
00636 }
00637 
00638 //
00639 // Pan Up - rotate towards top of model, clamping at 90 degrees
00640 //
00641 void CCameraSpot::PanUp (void)
00642 {
00643   phi += DegToRad (1.0f);
00644   if (phi > (PI/2)) phi = PI/2;
00645 }
00646 
00647 //
00648 // Pan Down - rotate towards bottom of model, clamping at 90 degrees
00649 //
00650 void CCameraSpot::PanDown (void)
00651 {
00652   phi -= DegToRad (1.0f);
00653   if (phi < (-PI/2)) phi = -PI/2;
00654 }
00655 
00656 
00657 //
00658 // CCameraObserver
00659 //
00660 // External spot camera, fixed orientation with ground
00661 //
00662 
00663 CCameraObserver::CCameraObserver (void)
00664 : CCamera()
00665 {
00666   theta = DegToRad (-30.0f);
00667   phi = DegToRad (15.0f);
00668 }
00669 
00670 //
00671 // Calculate offset of camera from target origin
00672 //
00673 void CCameraObserver::GetCameraOffset (SVector *v)
00674 {
00675   v->x = r * sin (theta) * cos (phi);
00676   v->y = r * sin (phi);
00677   v->z = -r * cos (theta) * cos (phi);
00678 }
00679 
00680 //
00681 // Calculate Euler angle orientation of camera
00682 //
00683 void CCameraObserver::GetCameraOrientation (SVector *v)
00684 {
00685   v->h = theta;
00686   v->p = phi;
00687   v->r = 0;
00688 }
00689 
00690 //
00691 // Pan Left - rotate clockwise
00692 //
00693 void CCameraObserver::PanLeft (void)
00694 {
00695   theta = WrapTwoPi (theta - DegToRad (1.0f));
00696 }
00697 
00698 //
00699 // Pan Right - rotate counterclockwise
00700 //
00701 void CCameraObserver::PanRight (void)
00702 {
00703   theta = WrapTwoPi (theta + DegToRad (1.0f));
00704 }
00705 
00706 //
00707 // Pan Up - rotate towards top of model, clamping at 90 degrees
00708 //
00709 void CCameraObserver::PanUp (void)
00710 {
00711   phi += DegToRad (1.0f);
00712   if (phi > (PI/2)) phi = PI/2;
00713 }
00714 
00715 //
00716 // Pan Down - rotate towards bottom of model, clamping at 90 degrees
00717 //
00718 void CCameraObserver::PanDown (void)
00719 {
00720   phi -= DegToRad (1.0f);
00721   if (phi < (-PI/2)) phi = -PI/2;
00722 }
00723 
00724 
00725 //
00726 // Flyby Camera
00727 //
00728 
00729 //
00730 // Calculate offset of camera from target origin
00731 //
00732 void CCameraFlyby::GetCameraOffset (SVector *v)
00733 {
00734   v->x = r * 0.5;
00735   v->y = r;
00736   v->z = 0;
00737 }
00738 
00739 
00740 //
00741 // Calculate Euler angle orientation of camera
00742 //
00743 void CCameraFlyby::GetCameraOrientation (SVector *v)
00744 {
00745   v->h = 5 * PI / 4;
00746   v->p = 0;
00747   v->r = 0;
00748 }
00749 
00750 
00751 //
00752 // External tower camera
00753 //
00754 
00755 //
00756 // Calculate offset of camera from target origin
00757 //
00758 void CCameraTower::GetCameraOffset (SVector *v)
00759 {
00760   v->x = r * 10;
00761   v->y = r * 10;
00762   v->z = 0;
00763 }
00764 
00765 
00766 //
00767 // Calculate Euler angle orientation of camera
00768 //
00769 void CCameraTower::GetCameraOrientation (SVector *v)
00770 {
00771   v->h = 5 * PI / 4;
00772   v->p = 0;
00773   v->r = 0;
00774 }
00775 
00776 
00777 
00778 //
00779 // Overhead camera
00780 //
00781 // When selected, the eyepoint for this camera is placed above the aircraft
00782 //   looking down towards the ground.
00783 //
00784 
00785 //
00786 // Calculate offset of camera from target origin
00787 //
00788 void CCameraOverhead::GetCameraOffset (SVector *v)
00789 {
00790   v->x = 0;
00791   v->y = 0;
00792   v->z = r;
00793 }
00794 
00795 //
00796 // Calculate Euler angle orientation of camera
00797 //
00798 void CCameraOverhead::GetCameraOrientation (SVector *v)
00799 {
00800   v->h = 0;
00801   v->p = -PI/2;
00802   v->r = 0;
00803 }
00804 
SourceForge.net Logo Documentation generated by doxygen