From: <sv...@ww...> - 2004-08-07 01:39:04
|
Author: mkrose Date: 2004-08-06 18:38:55 -0700 (Fri, 06 Aug 2004) New Revision: 1200 Modified: trunk/CSP/CSPSim/CHANGES.current trunk/CSP/CSPSim/Source/Views/CameraAgent.cpp Log: Fixed camera panning limit calculation that keeps the camera above ground in external views. Browse at: https://www.zerobar.net/viewcvs/viewcvs.cgi?view=rev&rev=1200 Modified: trunk/CSP/CSPSim/CHANGES.current =================================================================== --- trunk/CSP/CSPSim/CHANGES.current 2004-08-07 01:35:17 UTC (rev 1199) +++ trunk/CSP/CSPSim/CHANGES.current 2004-08-07 01:38:55 UTC (rev 1200) @@ -14,6 +14,9 @@ * Cleaned up formatting, copyright notices, and logging in some of the network code. + * Fixed camera panning limit calculation that keeps the camera above + ground in external views. + 2004-07-29: onsight * Removed a couple obsolete files from the Makefile, and added InputEvent. Modified: trunk/CSP/CSPSim/Source/Views/CameraAgent.cpp =================================================================== --- trunk/CSP/CSPSim/Source/Views/CameraAgent.cpp 2004-08-07 01:35:17 UTC (rev 1199) +++ trunk/CSP/CSPSim/Source/Views/CameraAgent.cpp 2004-08-07 01:38:55 UTC (rev 1200) @@ -1,20 +1,20 @@ -// Combat Simulator Project - FlightSim Demo +// Combat Simulator Project - FlightSim Demo // Copyright (C) 2004 The Combat Simulator Project // http://csp.sourceforge.net -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, +// +// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /** @@ -30,6 +30,7 @@ #include "VirtualScene.h" #include "Views/CameraCommand.h" + CameraAgent::CameraAgent(const ViewFactory& vf): m_ViewMode(0) { vf.attachAllView(this); @@ -50,6 +51,8 @@ TerrainObject::IntersectionHint camera_hint = 0; double const SAFETY = 3.0; float h = SAFETY + terrain->getGroundElevation(m_EyePoint.x(),m_EyePoint.y(),camera_hint); + // if the eyepoint is near the ground, check more carefully that the terrain isn't + // clipped by the near-clipping plane. if (m_EyePoint.z() < h) { double alpha_2 = simdata::toRadians(0.5*scene->getViewAngle()); double near_dist = scene->getNearPlane(); @@ -60,26 +63,49 @@ double tan_alpha_2 = tan(alpha_2); simdata::Vector3 right_unit = eye_look_unit^up_vec_unit; - double min_elev = 0.0; - // iterate on the pyramide edges + simdata::Vector3 min_edge; + double min_elev = 1.0; + // iterate over the corners of the rectangle defined by the intersection + // of the near clipping plane and the view frustum; find the lowest + // corner. for (double i = -1.0; i <= 1.0; i += 2.0) for (double j = -1.0;j <= 1.0; j += 2.0) { - simdata::Vector3 edge_vector = near_dist * (eye_look_unit + simdata::Vector3 edge_vector = near_dist * (eye_look_unit + tan_alpha_2 * ( i * up_vec_unit + j * aspect * right_unit)); simdata::Vector3 edge = m_EyePoint + edge_vector; double edge_elev = edge.z()-terrain->getGroundElevation(edge.x(),edge.y(),camera_hint); - if (min_elev > edge_elev) + if (min_elev > edge_elev) { min_elev = edge_elev; + min_edge = edge; + } } - double dh = abs(h - m_LookPoint.z() - min_elev); - double angle_x = std::max(simdata::toRadians(1.0),asin(dh/m_CameraKinematics.getDistance())); - // XXX: transform to Fresnet frame - if (abs(m_CameraKinematics.getPhi()) < simdata::PI_2) - m_CameraKinematics.setPhi(angle_x); - else - m_CameraKinematics.setPhi(simdata::PI-angle_x); - m_CameraKinematics.panUpDownStop(); - m_ViewList[m_ViewMode]->recalculate(m_EyePoint,m_LookPoint,m_UpVector,dt); + // if the lowest corner is near or below the terrain, the terrain may be + // clipped (revealing the void underneath); rotate the view up to prevent + // this from happening. + if (min_elev < 0.1) { + simdata::Vector3 rotvec = m_LookPoint - min_edge; + // project back onto the plane defined by L-E and Up + rotvec -= dot(rotvec, right_unit) * right_unit; + double R = rotvec.normalize(); + // distance to raise the lowest clip point (to 10cm above the terrain). + double dh = 0.1 - min_elev; + // angle from the lookpoint to the lowest clip point, relative to x-y plane. + double phi = asin(-rotvec.z()); + // angle to rotate the view in order to bring the lowest clip point up to + // the terrain height (+10cm). + double alpha = std::max(0.0, acos(rotvec.z() - dh/R) - simdata::PI_2 - phi); + if (alpha > 0.0) { + phi = m_CameraKinematics.getPhi(); + // first bring phi into the range -pi..pi + if (dot(rotvec ^ simdata::Vector3::ZAXIS, right_unit) > 0) { + m_CameraKinematics.setPhi(phi + alpha); + } else { + m_CameraKinematics.setPhi(phi - alpha); + } + m_CameraKinematics.panUpDownStop(); + m_ViewList[m_ViewMode]->recalculate(m_EyePoint,m_LookPoint,m_UpVector,dt); + } + } } } @@ -99,8 +125,9 @@ if (view != m_ViewList.end()) { m_CameraKinematics.update(dt); view->second->update(m_EyePoint,m_LookPoint,m_UpVector,dt); - if (!view->second->isInternal()) + if (!view->second->isInternal()) { validate(dt); + } view->second->cull(); } } |