1
0
Fork 0
flightgear/src/FDM/groundcache.cxx

1025 lines
32 KiB
C++
Raw Normal View History

// groundcache.cxx -- carries a small subset of the scenegraph near the vehicle
//
// Written by Mathias Froehlich, started Nov 2004.
//
// Copyright (C) 2004, 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// 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, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// 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
2006-02-21 01:16:04 +00:00
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "groundcache.hxx"
#include <utility>
Modified Files: configure.ac src/AIModel/AIAircraft.cxx src/AIModel/AIBase.cxx src/AIModel/AIBase.hxx src/AIModel/AICarrier.cxx src/AIModel/AICarrier.hxx src/AIModel/AIManager.cxx src/AIModel/AIManager.hxx src/ATC/AIEntity.cxx src/ATC/AIEntity.hxx src/ATC/AIMgr.cxx src/ATC/AIMgr.hxx src/ATC/ATCdisplay.cxx src/ATC/ATCdisplay.hxx src/Cockpit/cockpit.cxx src/Cockpit/cockpit.hxx src/Cockpit/hud.cxx src/Cockpit/hud.hxx src/Cockpit/hud_rwy.cxx src/Cockpit/panel.cxx src/Cockpit/panel.hxx src/Cockpit/built_in/FGMagRibbon.cxx src/Cockpit/built_in/FGMagRibbon.hxx src/FDM/flight.cxx src/FDM/groundcache.cxx src/FDM/groundcache.hxx src/GUI/gui_funcs.cxx src/Input/input.cxx src/Instrumentation/od_gauge.cxx src/Instrumentation/od_gauge.hxx src/Instrumentation/render_area_2d.cxx src/Instrumentation/render_area_2d.hxx src/Instrumentation/wxradar.cxx src/Instrumentation/wxradar.hxx src/Instrumentation/HUD/HUD.cxx src/Instrumentation/HUD/HUD.hxx src/Instrumentation/HUD/HUD_runway.cxx src/Main/Makefile.am src/Main/main.cxx src/Main/renderer.cxx src/Main/renderer.hxx src/Main/viewmgr.cxx src/Model/acmodel.cxx src/Model/acmodel.hxx src/Model/model_panel.cxx src/Model/model_panel.hxx src/Model/modelmgr.cxx src/Model/modelmgr.hxx src/Model/panelnode.cxx src/Model/panelnode.hxx src/Navaids/awynet.cxx src/Scenery/Makefile.am src/Scenery/hitlist.cxx src/Scenery/hitlist.hxx src/Scenery/newcache.cxx src/Scenery/scenery.cxx src/Scenery/scenery.hxx src/Scenery/tileentry.cxx src/Scenery/tileentry.hxx src/Scenery/tilemgr.cxx src/Scripting/NasalSys.cxx src/Scripting/NasalSys.hxx src/Time/light.cxx Big BLOB on the way to OSG.
2006-10-29 19:30:21 +00:00
#include <osg/Drawable>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Camera>
#include <osg/Transform>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/CameraView>
Mathias Fröhlich: 2. I made YASim query the the ground cache at the wrong place. This one fixed this, one can now land the bo105 on top of the oracle buildings :) 3. Is a followup of the scenery center update code: Register the scenery center transform at the time it is put into the scene graph not at creation time. 4. I held that part back from the past hitlist patch, because I hoped that it will be sufficient (and the last one was in fact the biggest part) without. As some test cases from Melchior showed me, it is not. We have additionally to the wrong computed transform from the prevous patch some roundoff problems. This patch adds some small tolerance to for the point in triangle test. ... may be one even needs to increase the eps value further if starting at some tile boundaries still fails. 5. That is a big chunk. Tested now for two days while hunting the second patch :) . That is a partial rewrite of the groundcache to use its own datastructures for that flat scenegraph in the cache. The basic advantage is, what Erik suggested, to precompute some often used values of these triangles. Also allmost all computations are now in double precision which should decrease (hopefully fix), together with a similar tolerance for some point in triangle tests, the problems with 'no ground below aircraft'. I am playing with octrees for the groundcache, that will finally solve the performance problem when high triangular count models end up in the groundcache. This patch is also some prework for those octrees ...
2005-05-30 08:48:27 +00:00
#include <simgear/sg_inlines.h>
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/math/SGMisc.hxx>
Modified Files: configure.ac src/AIModel/AIAircraft.cxx src/AIModel/AIBase.cxx src/AIModel/AIBase.hxx src/AIModel/AICarrier.cxx src/AIModel/AICarrier.hxx src/AIModel/AIManager.cxx src/AIModel/AIManager.hxx src/ATC/AIEntity.cxx src/ATC/AIEntity.hxx src/ATC/AIMgr.cxx src/ATC/AIMgr.hxx src/ATC/ATCdisplay.cxx src/ATC/ATCdisplay.hxx src/Cockpit/cockpit.cxx src/Cockpit/cockpit.hxx src/Cockpit/hud.cxx src/Cockpit/hud.hxx src/Cockpit/hud_rwy.cxx src/Cockpit/panel.cxx src/Cockpit/panel.hxx src/Cockpit/built_in/FGMagRibbon.cxx src/Cockpit/built_in/FGMagRibbon.hxx src/FDM/flight.cxx src/FDM/groundcache.cxx src/FDM/groundcache.hxx src/GUI/gui_funcs.cxx src/Input/input.cxx src/Instrumentation/od_gauge.cxx src/Instrumentation/od_gauge.hxx src/Instrumentation/render_area_2d.cxx src/Instrumentation/render_area_2d.hxx src/Instrumentation/wxradar.cxx src/Instrumentation/wxradar.hxx src/Instrumentation/HUD/HUD.cxx src/Instrumentation/HUD/HUD.hxx src/Instrumentation/HUD/HUD_runway.cxx src/Main/Makefile.am src/Main/main.cxx src/Main/renderer.cxx src/Main/renderer.hxx src/Main/viewmgr.cxx src/Model/acmodel.cxx src/Model/acmodel.hxx src/Model/model_panel.cxx src/Model/model_panel.hxx src/Model/modelmgr.cxx src/Model/modelmgr.hxx src/Model/panelnode.cxx src/Model/panelnode.hxx src/Navaids/awynet.cxx src/Scenery/Makefile.am src/Scenery/hitlist.cxx src/Scenery/hitlist.hxx src/Scenery/newcache.cxx src/Scenery/scenery.cxx src/Scenery/scenery.hxx src/Scenery/tileentry.cxx src/Scenery/tileentry.hxx src/Scenery/tilemgr.cxx src/Scripting/NasalSys.cxx src/Scripting/NasalSys.hxx src/Time/light.cxx Big BLOB on the way to OSG.
2006-10-29 19:30:21 +00:00
#include <simgear/scene/util/SGNodeMasks.hxx>
#include <simgear/scene/util/SGSceneUserData.hxx>
#include <simgear/scene/bvh/BVHNode.hxx>
#include <simgear/scene/bvh/BVHGroup.hxx>
#include <simgear/scene/bvh/BVHTransform.hxx>
#include <simgear/scene/bvh/BVHMotionTransform.hxx>
#include <simgear/scene/bvh/BVHLineGeometry.hxx>
#include <simgear/scene/bvh/BVHStaticGeometry.hxx>
#include <simgear/scene/bvh/BVHStaticData.hxx>
#include <simgear/scene/bvh/BVHStaticNode.hxx>
#include <simgear/scene/bvh/BVHStaticTriangle.hxx>
#include <simgear/scene/bvh/BVHStaticBinary.hxx>
#include <simgear/scene/bvh/BVHSubTreeCollector.hxx>
#include <simgear/scene/bvh/BVHLineSegmentVisitor.hxx>
#include <simgear/scene/bvh/BVHNearestPointVisitor.hxx>
#ifdef GROUNDCACHE_DEBUG
#include <simgear/scene/bvh/BVHDebugCollectVisitor.hxx>
#include <Main/fg_props.hxx>
#endif
#include <Main/globals.hxx>
#include <Scenery/scenery.hxx>
#include <Scenery/tilemgr.hxx>
#include "flight.hxx"
using namespace simgear;
Mathias Fröhlich: 2. I made YASim query the the ground cache at the wrong place. This one fixed this, one can now land the bo105 on top of the oracle buildings :) 3. Is a followup of the scenery center update code: Register the scenery center transform at the time it is put into the scene graph not at creation time. 4. I held that part back from the past hitlist patch, because I hoped that it will be sufficient (and the last one was in fact the biggest part) without. As some test cases from Melchior showed me, it is not. We have additionally to the wrong computed transform from the prevous patch some roundoff problems. This patch adds some small tolerance to for the point in triangle test. ... may be one even needs to increase the eps value further if starting at some tile boundaries still fails. 5. That is a big chunk. Tested now for two days while hunting the second patch :) . That is a partial rewrite of the groundcache to use its own datastructures for that flat scenegraph in the cache. The basic advantage is, what Erik suggested, to precompute some often used values of these triangles. Also allmost all computations are now in double precision which should decrease (hopefully fix), together with a similar tolerance for some point in triangle tests, the problems with 'no ground below aircraft'. I am playing with octrees for the groundcache, that will finally solve the performance problem when high triangular count models end up in the groundcache. This patch is also some prework for those octrees ...
2005-05-30 08:48:27 +00:00
class FGGroundCache::CacheFill : public osg::NodeVisitor {
public:
CacheFill(const SGVec3d& center, const SGVec3d& down, const double& radius,
const double& startTime, const double& endTime) :
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
_center(center),
_down(down),
_radius(radius),
_startTime(startTime),
_endTime(endTime),
_sceneryHit(0, 0, 0),
_maxDown(SGGeod::fromCart(center).getElevationM() + 9999),
_material(0),
_haveHit(false)
{
setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
}
virtual void apply(osg::Node& node)
{
if (!testBoundingSphere(node.getBound()))
return;
addBoundingVolume(node);
}
virtual void apply(osg::Group& group)
{
if (!testBoundingSphere(group.getBound()))
return;
simgear::BVHSubTreeCollector::NodeList parentNodeList;
mSubTreeCollector.pushNodeList(parentNodeList);
traverse(group);
addBoundingVolume(group);
mSubTreeCollector.popNodeList(parentNodeList);
}
virtual void apply(osg::Transform& transform)
{ handleTransform(transform); }
virtual void apply(osg::Camera& camera)
{
if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
return;
handleTransform(camera);
}
virtual void apply(osg::CameraView& transform)
{ handleTransform(transform); }
virtual void apply(osg::MatrixTransform& transform)
{ handleTransform(transform); }
virtual void apply(osg::PositionAttitudeTransform& transform)
{ handleTransform(transform); }
void handleTransform(osg::Transform& transform)
{
// Hmm, may be this needs to be refined somehow ...
if (transform.getReferenceFrame() != osg::Transform::RELATIVE_RF)
return;
if (!testBoundingSphere(transform.getBound()))
return;
osg::Matrix inverseMatrix;
if (!transform.computeWorldToLocalMatrix(inverseMatrix, this))
return;
osg::Matrix matrix;
if (!transform.computeLocalToWorldMatrix(matrix, this))
return;
// Look for a velocity note
const SGSceneUserData::Velocity* velocity = getVelocity(transform);
SGVec3d center = _center;
SGVec3d down = _down;
double radius = _radius;
bool haveHit = _haveHit;
const SGMaterial* material = _material;
_haveHit = false;
_center = toSG(inverseMatrix.preMult(toOsg(_center)));
_down = toSG(osg::Matrix::transform3x3(toOsg(_down), inverseMatrix));
if (velocity) {
SGVec3d staticCenter(_center);
double dtStart = velocity->referenceTime - _startTime;
SGVec3d startCenter = staticCenter + dtStart*velocity->linear;
SGQuatd startOr(SGQuatd::fromAngleAxis(dtStart*velocity->angular));
startCenter = startOr.transform(startCenter);
double dtEnd = velocity->referenceTime - _endTime;
SGVec3d endCenter = staticCenter + dtEnd*velocity->linear;
SGQuatd endOr(SGQuatd::fromAngleAxis(dtEnd*velocity->angular));
endCenter = endOr.transform(endCenter);
_center = 0.5*(startCenter + endCenter);
_down = startOr.transform(_down);
_radius += 0.5*dist(startCenter, endCenter);
}
simgear::BVHSubTreeCollector::NodeList parentNodeList;
mSubTreeCollector.pushNodeList(parentNodeList);
addBoundingVolume(transform);
traverse(transform);
if (mSubTreeCollector.haveChildren()) {
if (velocity) {
simgear::BVHMotionTransform* bvhTransform;
bvhTransform = new simgear::BVHMotionTransform;
bvhTransform->setToWorldTransform(SGMatrixd(matrix.ptr()));
bvhTransform->setLinearVelocity(velocity->linear);
bvhTransform->setAngularVelocity(velocity->angular);
bvhTransform->setReferenceTime(velocity->referenceTime);
bvhTransform->setStartTime(_startTime);
bvhTransform->setEndTime(_endTime);
bvhTransform->setId(velocity->id);
mSubTreeCollector.popNodeList(parentNodeList, bvhTransform);
} else {
simgear::BVHTransform* bvhTransform;
bvhTransform = new simgear::BVHTransform;
bvhTransform->setToWorldTransform(SGMatrixd(matrix.ptr()));
mSubTreeCollector.popNodeList(parentNodeList, bvhTransform);
}
} else {
mSubTreeCollector.popNodeList(parentNodeList);
}
if (_haveHit) {
if (velocity) {
double dt = _startTime - velocity->referenceTime;
SGQuatd ori(SGQuatd::fromAngleAxis(dt*velocity->angular));
_sceneryHit = ori.transform(_sceneryHit);
_sceneryHit += dt*velocity->linear;
}
_sceneryHit = toSG(matrix.preMult(toOsg(_sceneryHit)));
} else {
_material = material;
_haveHit = haveHit;
}
_center = center;
_down = down;
_radius = radius;
}
const SGSceneUserData::Velocity* getVelocity(osg::Node& node)
{
SGSceneUserData* userData = SGSceneUserData::getSceneUserData(&node);
if (!userData)
return 0;
return userData->getVelocity();
}
simgear::BVHNode* getNodeBoundingVolume(osg::Node& node)
{
SGSceneUserData* userData = SGSceneUserData::getSceneUserData(&node);
if (!userData)
return 0;
return userData->getBVHNode();
Modified Files: configure.ac src/AIModel/AIAircraft.cxx src/AIModel/AIBase.cxx src/AIModel/AIBase.hxx src/AIModel/AICarrier.cxx src/AIModel/AICarrier.hxx src/AIModel/AIManager.cxx src/AIModel/AIManager.hxx src/ATC/AIEntity.cxx src/ATC/AIEntity.hxx src/ATC/AIMgr.cxx src/ATC/AIMgr.hxx src/ATC/ATCdisplay.cxx src/ATC/ATCdisplay.hxx src/Cockpit/cockpit.cxx src/Cockpit/cockpit.hxx src/Cockpit/hud.cxx src/Cockpit/hud.hxx src/Cockpit/hud_rwy.cxx src/Cockpit/panel.cxx src/Cockpit/panel.hxx src/Cockpit/built_in/FGMagRibbon.cxx src/Cockpit/built_in/FGMagRibbon.hxx src/FDM/flight.cxx src/FDM/groundcache.cxx src/FDM/groundcache.hxx src/GUI/gui_funcs.cxx src/Input/input.cxx src/Instrumentation/od_gauge.cxx src/Instrumentation/od_gauge.hxx src/Instrumentation/render_area_2d.cxx src/Instrumentation/render_area_2d.hxx src/Instrumentation/wxradar.cxx src/Instrumentation/wxradar.hxx src/Instrumentation/HUD/HUD.cxx src/Instrumentation/HUD/HUD.hxx src/Instrumentation/HUD/HUD_runway.cxx src/Main/Makefile.am src/Main/main.cxx src/Main/renderer.cxx src/Main/renderer.hxx src/Main/viewmgr.cxx src/Model/acmodel.cxx src/Model/acmodel.hxx src/Model/model_panel.cxx src/Model/model_panel.hxx src/Model/modelmgr.cxx src/Model/modelmgr.hxx src/Model/panelnode.cxx src/Model/panelnode.hxx src/Navaids/awynet.cxx src/Scenery/Makefile.am src/Scenery/hitlist.cxx src/Scenery/hitlist.hxx src/Scenery/newcache.cxx src/Scenery/scenery.cxx src/Scenery/scenery.hxx src/Scenery/tileentry.cxx src/Scenery/tileentry.hxx src/Scenery/tilemgr.cxx src/Scripting/NasalSys.cxx src/Scripting/NasalSys.hxx src/Time/light.cxx Big BLOB on the way to OSG.
2006-10-29 19:30:21 +00:00
}
void addBoundingVolume(osg::Node& node)
{
simgear::BVHNode* bvNode = getNodeBoundingVolume(node);
if (!bvNode)
return;
Modified Files: configure.ac src/AIModel/AIAircraft.cxx src/AIModel/AIBase.cxx src/AIModel/AIBase.hxx src/AIModel/AICarrier.cxx src/AIModel/AICarrier.hxx src/AIModel/AIManager.cxx src/AIModel/AIManager.hxx src/ATC/AIEntity.cxx src/ATC/AIEntity.hxx src/ATC/AIMgr.cxx src/ATC/AIMgr.hxx src/ATC/ATCdisplay.cxx src/ATC/ATCdisplay.hxx src/Cockpit/cockpit.cxx src/Cockpit/cockpit.hxx src/Cockpit/hud.cxx src/Cockpit/hud.hxx src/Cockpit/hud_rwy.cxx src/Cockpit/panel.cxx src/Cockpit/panel.hxx src/Cockpit/built_in/FGMagRibbon.cxx src/Cockpit/built_in/FGMagRibbon.hxx src/FDM/flight.cxx src/FDM/groundcache.cxx src/FDM/groundcache.hxx src/GUI/gui_funcs.cxx src/Input/input.cxx src/Instrumentation/od_gauge.cxx src/Instrumentation/od_gauge.hxx src/Instrumentation/render_area_2d.cxx src/Instrumentation/render_area_2d.hxx src/Instrumentation/wxradar.cxx src/Instrumentation/wxradar.hxx src/Instrumentation/HUD/HUD.cxx src/Instrumentation/HUD/HUD.hxx src/Instrumentation/HUD/HUD_runway.cxx src/Main/Makefile.am src/Main/main.cxx src/Main/renderer.cxx src/Main/renderer.hxx src/Main/viewmgr.cxx src/Model/acmodel.cxx src/Model/acmodel.hxx src/Model/model_panel.cxx src/Model/model_panel.hxx src/Model/modelmgr.cxx src/Model/modelmgr.hxx src/Model/panelnode.cxx src/Model/panelnode.hxx src/Navaids/awynet.cxx src/Scenery/Makefile.am src/Scenery/hitlist.cxx src/Scenery/hitlist.hxx src/Scenery/newcache.cxx src/Scenery/scenery.cxx src/Scenery/scenery.hxx src/Scenery/tileentry.cxx src/Scenery/tileentry.hxx src/Scenery/tilemgr.cxx src/Scripting/NasalSys.cxx src/Scripting/NasalSys.hxx src/Time/light.cxx Big BLOB on the way to OSG.
2006-10-29 19:30:21 +00:00
// Find a croase ground intersection
SGLineSegmentd line(_center + _radius*_down, _center + _maxDown*_down);
simgear::BVHLineSegmentVisitor lineSegmentVisitor(line, _startTime);
bvNode->accept(lineSegmentVisitor);
if (!lineSegmentVisitor.empty()) {
_sceneryHit = lineSegmentVisitor.getPoint();
_material = lineSegmentVisitor.getMaterial();
_maxDown = SGMiscd::max(_radius, dot(_down, _sceneryHit - _center));
_haveHit = true;
}
// Get that part of the local bv tree that intersects our sphere
// of interrest.
mSubTreeCollector.setSphere(SGSphered(_center, _radius));
bvNode->accept(mSubTreeCollector);
}
bool testBoundingSphere(const osg::BoundingSphere& bound) const
{
if (!bound.valid())
return false;
SGLineSegmentd downSeg(_center, _center + _maxDown*_down);
double maxDist = bound._radius + _radius;
SGVec3d boundCenter(toVec3d(toSG(bound._center)));
return distSqr(downSeg, boundCenter) <= maxDist*maxDist;
}
SGSharedPtr<simgear::BVHNode> getBVHNode() const
{ return mSubTreeCollector.getNode(); }
bool getHaveElevationBelowCache() const
{ return _haveHit; }
double getElevationBelowCache() const
{ return SGGeod::fromCart(_sceneryHit).getElevationM(); }
const SGMaterial* getMaterialBelowCache() const
{ return _material; }
private:
SGVec3d _center;
SGVec3d _down;
double _radius;
double _startTime;
double _endTime;
Modified Files: configure.ac src/AIModel/AIAircraft.cxx src/AIModel/AIBase.cxx src/AIModel/AIBase.hxx src/AIModel/AICarrier.cxx src/AIModel/AICarrier.hxx src/AIModel/AIManager.cxx src/AIModel/AIManager.hxx src/ATC/AIEntity.cxx src/ATC/AIEntity.hxx src/ATC/AIMgr.cxx src/ATC/AIMgr.hxx src/ATC/ATCdisplay.cxx src/ATC/ATCdisplay.hxx src/Cockpit/cockpit.cxx src/Cockpit/cockpit.hxx src/Cockpit/hud.cxx src/Cockpit/hud.hxx src/Cockpit/hud_rwy.cxx src/Cockpit/panel.cxx src/Cockpit/panel.hxx src/Cockpit/built_in/FGMagRibbon.cxx src/Cockpit/built_in/FGMagRibbon.hxx src/FDM/flight.cxx src/FDM/groundcache.cxx src/FDM/groundcache.hxx src/GUI/gui_funcs.cxx src/Input/input.cxx src/Instrumentation/od_gauge.cxx src/Instrumentation/od_gauge.hxx src/Instrumentation/render_area_2d.cxx src/Instrumentation/render_area_2d.hxx src/Instrumentation/wxradar.cxx src/Instrumentation/wxradar.hxx src/Instrumentation/HUD/HUD.cxx src/Instrumentation/HUD/HUD.hxx src/Instrumentation/HUD/HUD_runway.cxx src/Main/Makefile.am src/Main/main.cxx src/Main/renderer.cxx src/Main/renderer.hxx src/Main/viewmgr.cxx src/Model/acmodel.cxx src/Model/acmodel.hxx src/Model/model_panel.cxx src/Model/model_panel.hxx src/Model/modelmgr.cxx src/Model/modelmgr.hxx src/Model/panelnode.cxx src/Model/panelnode.hxx src/Navaids/awynet.cxx src/Scenery/Makefile.am src/Scenery/hitlist.cxx src/Scenery/hitlist.hxx src/Scenery/newcache.cxx src/Scenery/scenery.cxx src/Scenery/scenery.hxx src/Scenery/tileentry.cxx src/Scenery/tileentry.hxx src/Scenery/tilemgr.cxx src/Scripting/NasalSys.cxx src/Scripting/NasalSys.hxx src/Time/light.cxx Big BLOB on the way to OSG.
2006-10-29 19:30:21 +00:00
simgear::BVHSubTreeCollector mSubTreeCollector;
SGVec3d _sceneryHit;
double _maxDown;
const SGMaterial* _material;
bool _haveHit;
};
FGGroundCache::FGGroundCache() :
_altitude(0),
_material(0),
cache_ref_time(0),
cache_time_offset(0),
_wire(0),
reference_wgs84_point(SGVec3d(0, 0, 0)),
reference_vehicle_radius(0),
down(0.0, 0.0, 0.0),
found_ground(false)
Modified Files: configure.ac src/AIModel/AIAircraft.cxx src/AIModel/AIBase.cxx src/AIModel/AIBase.hxx src/AIModel/AICarrier.cxx src/AIModel/AICarrier.hxx src/AIModel/AIManager.cxx src/AIModel/AIManager.hxx src/ATC/AIEntity.cxx src/ATC/AIEntity.hxx src/ATC/AIMgr.cxx src/ATC/AIMgr.hxx src/ATC/ATCdisplay.cxx src/ATC/ATCdisplay.hxx src/Cockpit/cockpit.cxx src/Cockpit/cockpit.hxx src/Cockpit/hud.cxx src/Cockpit/hud.hxx src/Cockpit/hud_rwy.cxx src/Cockpit/panel.cxx src/Cockpit/panel.hxx src/Cockpit/built_in/FGMagRibbon.cxx src/Cockpit/built_in/FGMagRibbon.hxx src/FDM/flight.cxx src/FDM/groundcache.cxx src/FDM/groundcache.hxx src/GUI/gui_funcs.cxx src/Input/input.cxx src/Instrumentation/od_gauge.cxx src/Instrumentation/od_gauge.hxx src/Instrumentation/render_area_2d.cxx src/Instrumentation/render_area_2d.hxx src/Instrumentation/wxradar.cxx src/Instrumentation/wxradar.hxx src/Instrumentation/HUD/HUD.cxx src/Instrumentation/HUD/HUD.hxx src/Instrumentation/HUD/HUD_runway.cxx src/Main/Makefile.am src/Main/main.cxx src/Main/renderer.cxx src/Main/renderer.hxx src/Main/viewmgr.cxx src/Model/acmodel.cxx src/Model/acmodel.hxx src/Model/model_panel.cxx src/Model/model_panel.hxx src/Model/modelmgr.cxx src/Model/modelmgr.hxx src/Model/panelnode.cxx src/Model/panelnode.hxx src/Navaids/awynet.cxx src/Scenery/Makefile.am src/Scenery/hitlist.cxx src/Scenery/hitlist.hxx src/Scenery/newcache.cxx src/Scenery/scenery.cxx src/Scenery/scenery.hxx src/Scenery/tileentry.cxx src/Scenery/tileentry.hxx src/Scenery/tilemgr.cxx src/Scripting/NasalSys.cxx src/Scripting/NasalSys.hxx src/Time/light.cxx Big BLOB on the way to OSG.
2006-10-29 19:30:21 +00:00
{
#ifdef GROUNDCACHE_DEBUG
_lookupTime = SGTimeStamp::fromSec(0.0);
_lookupCount = 0;
_buildTime = SGTimeStamp::fromSec(0.0);
_buildCount = 0;
#endif
Modified Files: configure.ac src/AIModel/AIAircraft.cxx src/AIModel/AIBase.cxx src/AIModel/AIBase.hxx src/AIModel/AICarrier.cxx src/AIModel/AICarrier.hxx src/AIModel/AIManager.cxx src/AIModel/AIManager.hxx src/ATC/AIEntity.cxx src/ATC/AIEntity.hxx src/ATC/AIMgr.cxx src/ATC/AIMgr.hxx src/ATC/ATCdisplay.cxx src/ATC/ATCdisplay.hxx src/Cockpit/cockpit.cxx src/Cockpit/cockpit.hxx src/Cockpit/hud.cxx src/Cockpit/hud.hxx src/Cockpit/hud_rwy.cxx src/Cockpit/panel.cxx src/Cockpit/panel.hxx src/Cockpit/built_in/FGMagRibbon.cxx src/Cockpit/built_in/FGMagRibbon.hxx src/FDM/flight.cxx src/FDM/groundcache.cxx src/FDM/groundcache.hxx src/GUI/gui_funcs.cxx src/Input/input.cxx src/Instrumentation/od_gauge.cxx src/Instrumentation/od_gauge.hxx src/Instrumentation/render_area_2d.cxx src/Instrumentation/render_area_2d.hxx src/Instrumentation/wxradar.cxx src/Instrumentation/wxradar.hxx src/Instrumentation/HUD/HUD.cxx src/Instrumentation/HUD/HUD.hxx src/Instrumentation/HUD/HUD_runway.cxx src/Main/Makefile.am src/Main/main.cxx src/Main/renderer.cxx src/Main/renderer.hxx src/Main/viewmgr.cxx src/Model/acmodel.cxx src/Model/acmodel.hxx src/Model/model_panel.cxx src/Model/model_panel.hxx src/Model/modelmgr.cxx src/Model/modelmgr.hxx src/Model/panelnode.cxx src/Model/panelnode.hxx src/Navaids/awynet.cxx src/Scenery/Makefile.am src/Scenery/hitlist.cxx src/Scenery/hitlist.hxx src/Scenery/newcache.cxx src/Scenery/scenery.cxx src/Scenery/scenery.hxx src/Scenery/tileentry.cxx src/Scenery/tileentry.hxx src/Scenery/tilemgr.cxx src/Scripting/NasalSys.cxx src/Scripting/NasalSys.hxx src/Time/light.cxx Big BLOB on the way to OSG.
2006-10-29 19:30:21 +00:00
}
FGGroundCache::~FGGroundCache()
{
}
bool
FGGroundCache::prepare_ground_cache(double startSimTime, double endSimTime,
const SGVec3d& pt, double rad)
{
#ifdef GROUNDCACHE_DEBUG
SGTimeStamp t0 = SGTimeStamp::now();
#endif
// Empty cache.
found_ground = false;
SGGeod geodPt = SGGeod::fromCart(pt);
// Don't blow away the cache ground_radius and stuff if there's no
// scenery
if (!globals->get_tile_mgr()->scenery_available(geodPt, rad)) {
SG_LOG(SG_FLIGHT, SG_WARN, "prepare_ground_cache(): scenery_available "
"returns false at " << geodPt << " " << pt << " " << rad);
return false;
}
_material = 0;
// If we have an active wire, get some more area into the groundcache
if (_wire)
rad = SGMiscd::max(200, rad);
// Store the parameters we used to build up that cache.
reference_wgs84_point = pt;
reference_vehicle_radius = rad;
// Store the time reference used to compute movements of moving triangles.
cache_ref_time = startSimTime;
// Get a normalized down vector valid for the whole cache
SGQuatd hlToEc = SGQuatd::fromLonLat(geodPt);
down = hlToEc.rotate(SGVec3d(0, 0, 1));
// Get the ground cache, that is a local collision tree of the environment
startSimTime += cache_time_offset;
endSimTime += cache_time_offset;
CacheFill subtreeCollector(pt, down, rad, startSimTime, endSimTime);
globals->get_scenery()->get_scene_graph()->accept(subtreeCollector);
_localBvhTree = subtreeCollector.getBVHNode();
if (subtreeCollector.getHaveElevationBelowCache()) {
// Use the altitude value below the cache that we gathered during
// cache collection
_altitude = subtreeCollector.getElevationBelowCache();
_material = subtreeCollector.getMaterialBelowCache();
found_ground = true;
} else if (_localBvhTree) {
// We have nothing below us, so try starting with the lowest point
// upwards for a croase altitude value
SGLineSegmentd line(pt + reference_vehicle_radius*down, pt - 1e3*down);
simgear::BVHLineSegmentVisitor lineSegmentVisitor(line, startSimTime);
_localBvhTree->accept(lineSegmentVisitor);
if (!lineSegmentVisitor.empty()) {
SGGeod geodPt = SGGeod::fromCart(lineSegmentVisitor.getPoint());
_altitude = geodPt.getElevationM();
_material = lineSegmentVisitor.getMaterial();
found_ground = true;
}
}
if (!found_ground) {
// Ok, still nothing here?? Last resort ...
double alt = 0;
found_ground = globals->get_scenery()->
get_elevation_m(SGGeod::fromGeodM(geodPt, 10000), alt, &_material);
if (found_ground)
_altitude = alt;
}
// Still not sucessful??
if (!found_ground)
SG_LOG(SG_FLIGHT, SG_WARN, "prepare_ground_cache(): trying to build "
"cache without any scenery below the aircraft");
#ifdef GROUNDCACHE_DEBUG
t0 = SGTimeStamp::now() - t0;
_buildTime += t0;
_buildCount++;
if (_buildCount > 60) {
double buildTime = 0;
if (_buildCount)
buildTime = _buildTime.toSecs()/_buildCount;
double lookupTime = 0;
if (_lookupCount)
lookupTime = _lookupTime.toSecs()/_lookupCount;
_buildTime = SGTimeStamp::fromSec(0.0);
_buildCount = 0;
_lookupTime = SGTimeStamp::fromSec(0.0);
_lookupCount = 0;
SG_LOG(SG_FLIGHT, SG_ALERT, "build time = " << buildTime
<< ", lookup Time = " << lookupTime);
}
if (!_group.valid()) {
_group = new osg::Group;
globals->get_scenery()->get_scene_graph()->addChild(_group);
fgSetInt("/fdm/groundcache-debug-level", -3);
}
_group->removeChildren(0, _group->getNumChildren());
if (_localBvhTree) {
int level = fgGetInt("/fdm/groundcache-debug-level");
if (-2 <= level) {
simgear::BVHDebugCollectVisitor debug(endSimTime, level);
_localBvhTree->accept(debug);
_group->addChild(debug.getNode());
}
}
#endif
return found_ground;
}
bool
FGGroundCache::is_valid(double& ref_time, SGVec3d& pt, double& rad)
{
pt = reference_wgs84_point;
rad = reference_vehicle_radius;
ref_time = cache_ref_time;
return found_ground;
}
class FGGroundCache::BodyFinder : public BVHVisitor {
public:
BodyFinder(BVHNode::Id id, const double& t) :
_id(id),
_bodyToWorld(SGMatrixd::unit()),
_linearVelocity(0, 0, 0),
_angularVelocity(0, 0, 0),
_time(t)
{ }
virtual void apply(BVHGroup& leaf)
{
if (_foundId)
return;
leaf.traverse(*this);
}
virtual void apply(BVHTransform& transform)
{
if (_foundId)
return;
transform.traverse(*this);
if (_foundId) {
_linearVelocity = transform.vecToWorld(_linearVelocity);
_angularVelocity = transform.vecToWorld(_angularVelocity);
_bodyToWorld = transform.getToWorldTransform()*_bodyToWorld;
}
}
virtual void apply(BVHMotionTransform& transform)
{
if (_foundId)
return;
if (_id == transform.getId()) {
_foundId = true;
} else {
transform.traverse(*this);
}
if (_foundId) {
SGMatrixd toWorld = transform.getToWorldTransform(_time);
SGVec3d referencePoint = _bodyToWorld.xformPt(SGVec3d::zeros());
_linearVelocity += transform.getLinearVelocityAt(referencePoint);
_angularVelocity += transform.getAngularVelocity();
_linearVelocity = toWorld.xformVec(_linearVelocity);
_angularVelocity = toWorld.xformVec(_angularVelocity);
_bodyToWorld = toWorld*_bodyToWorld;
}
}
virtual void apply(BVHLineGeometry& node) { }
virtual void apply(BVHStaticGeometry& node) { }
virtual void apply(const BVHStaticBinary&, const BVHStaticData&) { }
virtual void apply(const BVHStaticTriangle&, const BVHStaticData&) { }
const SGMatrixd& getBodyToWorld() const
{ return _bodyToWorld; }
const SGVec3d& getLinearVelocity() const
{ return _linearVelocity; }
const SGVec3d& getAngularVelocity() const
{ return _angularVelocity; }
bool empty() const
{ return !_foundId; }
protected:
simgear::BVHNode::Id _id;
SGMatrixd _bodyToWorld;
SGVec3d _linearVelocity;
SGVec3d _angularVelocity;
bool _foundId;
double _time;
};
bool
FGGroundCache::get_body(double t, SGMatrixd& bodyToWorld, SGVec3d& linearVel,
SGVec3d& angularVel, simgear::BVHNode::Id id)
{
// Get the transform matrix and velocities of a moving body with id at t.
if (!_localBvhTree)
return false;
t += cache_time_offset;
BodyFinder bodyFinder(id, t);
_localBvhTree->accept(bodyFinder);
if (bodyFinder.empty())
return false;
bodyToWorld = bodyFinder.getBodyToWorld();
linearVel = bodyFinder.getLinearVelocity();
angularVel = bodyFinder.getAngularVelocity();
return true;
}
class FGGroundCache::CatapultFinder : public BVHVisitor {
public:
CatapultFinder(const SGSphered& sphere, const double& t) :
_haveLineSegment(false),
_sphere(sphere),
_time(t)
{ }
virtual void apply(BVHGroup& leaf)
{
if (!intersects(_sphere, leaf.getBoundingSphere()))
return;
leaf.traverse(*this);
}
virtual void apply(BVHTransform& transform)
{
if (!intersects(_sphere, transform.getBoundingSphere()))
return;
SGSphered sphere = _sphere;
_sphere = transform.sphereToLocal(sphere);
bool haveLineSegment = _haveLineSegment;
_haveLineSegment = false;
transform.traverse(*this);
if (_haveLineSegment) {
_lineSegment = transform.lineSegmentToWorld(_lineSegment);
_linearVelocity = transform.vecToWorld(_linearVelocity);
_angularVelocity = transform.vecToWorld(_angularVelocity);
}
_haveLineSegment |= haveLineSegment;
_sphere.setCenter(sphere.getCenter());
}
virtual void apply(BVHMotionTransform& transform)
{
if (!intersects(_sphere, transform.getBoundingSphere()))
return;
SGSphered sphere = _sphere;
_sphere = transform.sphereToLocal(sphere, _time);
bool haveLineSegment = _haveLineSegment;
_haveLineSegment = false;
transform.traverse(*this);
if (_haveLineSegment) {
SGMatrixd toWorld = transform.getToWorldTransform(_time);
_linearVelocity
+= transform.getLinearVelocityAt(_lineSegment.getStart());
_angularVelocity += transform.getAngularVelocity();
_linearVelocity = toWorld.xformVec(_linearVelocity);
_angularVelocity = toWorld.xformVec(_angularVelocity);
_lineSegment = _lineSegment.transform(toWorld);
}
_haveLineSegment |= haveLineSegment;
_sphere.setCenter(sphere.getCenter());
}
virtual void apply(BVHLineGeometry& node)
{
if (node.getType() != BVHLineGeometry::CarrierCatapult)
return;
SGLineSegmentd lineSegment(node.getLineSegment());
if (!intersects(_sphere, lineSegment))
return;
_lineSegment = lineSegment;
double dist = distSqr(lineSegment, getSphere().getCenter());
_sphere.setRadius(sqrt(dist));
_linearVelocity = SGVec3d::zeros();
_angularVelocity = SGVec3d::zeros();
_haveLineSegment = true;
}
virtual void apply(BVHStaticGeometry& node)
{ }
virtual void apply(const BVHStaticBinary&, const BVHStaticData&) { }
virtual void apply(const BVHStaticTriangle&, const BVHStaticData&) { }
void setSphere(const SGSphered& sphere)
{ _sphere = sphere; }
const SGSphered& getSphere() const
{ return _sphere; }
const SGLineSegmentd& getLineSegment() const
{ return _lineSegment; }
const SGVec3d& getLinearVelocity() const
{ return _linearVelocity; }
const SGVec3d& getAngularVelocity() const
{ return _angularVelocity; }
bool getHaveLineSegment() const
{ return _haveLineSegment; }
protected:
SGLineSegmentd _lineSegment;
SGVec3d _linearVelocity;
SGVec3d _angularVelocity;
bool _haveLineSegment;
SGSphered _sphere;
double _time;
};
double
FGGroundCache::get_cat(double t, const SGVec3d& pt,
Modified Files: configure.ac src/AIModel/AIAircraft.cxx src/AIModel/AIBase.cxx src/AIModel/AIBase.hxx src/AIModel/AICarrier.cxx src/AIModel/AICarrier.hxx src/AIModel/AIManager.cxx src/AIModel/AIManager.hxx src/ATC/AIEntity.cxx src/ATC/AIEntity.hxx src/ATC/AIMgr.cxx src/ATC/AIMgr.hxx src/ATC/ATCdisplay.cxx src/ATC/ATCdisplay.hxx src/Cockpit/cockpit.cxx src/Cockpit/cockpit.hxx src/Cockpit/hud.cxx src/Cockpit/hud.hxx src/Cockpit/hud_rwy.cxx src/Cockpit/panel.cxx src/Cockpit/panel.hxx src/Cockpit/built_in/FGMagRibbon.cxx src/Cockpit/built_in/FGMagRibbon.hxx src/FDM/flight.cxx src/FDM/groundcache.cxx src/FDM/groundcache.hxx src/GUI/gui_funcs.cxx src/Input/input.cxx src/Instrumentation/od_gauge.cxx src/Instrumentation/od_gauge.hxx src/Instrumentation/render_area_2d.cxx src/Instrumentation/render_area_2d.hxx src/Instrumentation/wxradar.cxx src/Instrumentation/wxradar.hxx src/Instrumentation/HUD/HUD.cxx src/Instrumentation/HUD/HUD.hxx src/Instrumentation/HUD/HUD_runway.cxx src/Main/Makefile.am src/Main/main.cxx src/Main/renderer.cxx src/Main/renderer.hxx src/Main/viewmgr.cxx src/Model/acmodel.cxx src/Model/acmodel.hxx src/Model/model_panel.cxx src/Model/model_panel.hxx src/Model/modelmgr.cxx src/Model/modelmgr.hxx src/Model/panelnode.cxx src/Model/panelnode.hxx src/Navaids/awynet.cxx src/Scenery/Makefile.am src/Scenery/hitlist.cxx src/Scenery/hitlist.hxx src/Scenery/newcache.cxx src/Scenery/scenery.cxx src/Scenery/scenery.hxx src/Scenery/tileentry.cxx src/Scenery/tileentry.hxx src/Scenery/tilemgr.cxx src/Scripting/NasalSys.cxx src/Scripting/NasalSys.hxx src/Time/light.cxx Big BLOB on the way to OSG.
2006-10-29 19:30:21 +00:00
SGVec3d end[2], SGVec3d vel[2])
{
double maxDistance = 1000;
// Get the wire in question
t += cache_time_offset;
CatapultFinder catapultFinder(SGSphered(pt, maxDistance), t);
if (_localBvhTree)
_localBvhTree->accept(catapultFinder);
if (!catapultFinder.getHaveLineSegment())
return maxDistance;
// prepare the returns
end[0] = catapultFinder.getLineSegment().getStart();
end[1] = catapultFinder.getLineSegment().getEnd();
// The linear velocity is the one at the start of the line segment ...
vel[0] = catapultFinder.getLinearVelocity();
// ... so the end point has the additional cross product.
vel[1] = catapultFinder.getLinearVelocity();
vel[1] += cross(catapultFinder.getAngularVelocity(),
catapultFinder.getLineSegment().getDirection());
// Return the distance to the cat
return sqrt(distSqr(catapultFinder.getLineSegment(), pt));
}
bool
FGGroundCache::get_agl(double t, const SGVec3d& pt, SGVec3d& contact,
SGVec3d& normal, SGVec3d& linearVel, SGVec3d& angularVel,
simgear::BVHNode::Id& id, const SGMaterial*& material)
{
#ifdef GROUNDCACHE_DEBUG
SGTimeStamp t0 = SGTimeStamp::now();
#endif
// Just set up a ground intersection query for the given point
SGLineSegmentd line(pt, pt + 10*reference_vehicle_radius*down);
t += cache_time_offset;
simgear::BVHLineSegmentVisitor lineSegmentVisitor(line, t);
if (_localBvhTree)
_localBvhTree->accept(lineSegmentVisitor);
#ifdef GROUNDCACHE_DEBUG
t0 = SGTimeStamp::now() - t0;
_lookupTime += t0;
_lookupCount++;
#endif
if (!lineSegmentVisitor.empty()) {
// Have an intersection
contact = lineSegmentVisitor.getPoint();
normal = lineSegmentVisitor.getNormal();
if (0 < dot(normal, down))
normal = -normal;
linearVel = lineSegmentVisitor.getLinearVelocity();
angularVel = lineSegmentVisitor.getAngularVelocity();
material = lineSegmentVisitor.getMaterial();
id = lineSegmentVisitor.getId();
return true;
} else {
// Whenever we did not have a ground triangle for the requested point,
// take the ground level we found during the current cache build.
// This is as good as what we had before for agl.
SGGeod geodPt = SGGeod::fromCart(pt);
geodPt.setElevationM(_altitude);
contact = SGVec3d::fromGeod(geodPt);
normal = -down;
linearVel = SGVec3d(0, 0, 0);
angularVel = SGVec3d(0, 0, 0);
material = _material;
id = 0;
return found_ground;
}
}
bool
FGGroundCache::get_nearest(double t, const SGVec3d& pt, double maxDist,
SGVec3d& contact, SGVec3d& linearVel,
SGVec3d& angularVel, simgear::BVHNode::Id& id,
const SGMaterial*& material)
{
if (!_localBvhTree)
return false;
#ifdef GROUNDCACHE_DEBUG
SGTimeStamp t0 = SGTimeStamp::now();
#endif
// Just set up a ground intersection query for the given point
SGSphered sphere(pt, maxDist);
t += cache_time_offset;
simgear::BVHNearestPointVisitor nearestPointVisitor(sphere, t);
_localBvhTree->accept(nearestPointVisitor);
#ifdef GROUNDCACHE_DEBUG
t0 = SGTimeStamp::now() - t0;
_lookupTime += t0;
_lookupCount++;
#endif
if (nearestPointVisitor.empty())
return false;
// Have geometry in the range of maxDist
contact = nearestPointVisitor.getPoint();
linearVel = nearestPointVisitor.getLinearVelocity();
angularVel = nearestPointVisitor.getAngularVelocity();
material = nearestPointVisitor.getMaterial();
id = nearestPointVisitor.getId();
return true;
}
class FGGroundCache::WireIntersector : public BVHVisitor {
public:
WireIntersector(const SGVec3d pt[4], const double& t) :
_linearVelocity(SGVec3d::zeros()),
_angularVelocity(SGVec3d::zeros()),
_wire(0),
_time(t)
{
// Build the two triangles spanning the area where the hook has moved
// during the past step.
_triangles[0].set(pt[0], pt[1], pt[2]);
_triangles[1].set(pt[0], pt[2], pt[3]);
}
virtual void apply(BVHGroup& leaf)
{
if (!_intersects(leaf.getBoundingSphere()))
return;
leaf.traverse(*this);
}
virtual void apply(BVHTransform& transform)
{
if (!_intersects(transform.getBoundingSphere()))
return;
SGTriangled triangles[2] = { _triangles[0], _triangles[1] };
_triangles[0] = triangles[0].transform(transform.getToLocalTransform());
_triangles[1] = triangles[1].transform(transform.getToLocalTransform());
transform.traverse(*this);
if (_wire) {
_lineSegment = transform.lineSegmentToWorld(_lineSegment);
_linearVelocity = transform.vecToWorld(_linearVelocity);
_angularVelocity = transform.vecToWorld(_angularVelocity);
}
_triangles[0] = triangles[0];
_triangles[1] = triangles[1];
}
virtual void apply(BVHMotionTransform& transform)
{
if (!_intersects(transform.getBoundingSphere()))
return;
SGMatrixd toLocal = transform.getToLocalTransform(_time);
SGTriangled triangles[2] = { _triangles[0], _triangles[1] };
_triangles[0] = triangles[0].transform(toLocal);
_triangles[1] = triangles[1].transform(toLocal);
transform.traverse(*this);
if (_wire) {
SGMatrixd toWorld = transform.getToWorldTransform(_time);
_linearVelocity
+= transform.getLinearVelocityAt(_lineSegment.getStart());
_angularVelocity += transform.getAngularVelocity();
_linearVelocity = toWorld.xformVec(_linearVelocity);
_angularVelocity = toWorld.xformVec(_angularVelocity);
_lineSegment = _lineSegment.transform(toWorld);
}
_triangles[0] = triangles[0];
_triangles[1] = triangles[1];
}
virtual void apply(BVHLineGeometry& node)
{
if (node.getType() != BVHLineGeometry::CarrierWire)
return;
SGLineSegmentd lineSegment(node.getLineSegment());
if (!_intersects(lineSegment))
return;
_lineSegment = lineSegment;
_linearVelocity = SGVec3d::zeros();
_angularVelocity = SGVec3d::zeros();
_wire = &node;
}
virtual void apply(BVHStaticGeometry& node)
{ }
virtual void apply(const BVHStaticBinary&, const BVHStaticData&) { }
virtual void apply(const BVHStaticTriangle&, const BVHStaticData&) { }
bool _intersects(const SGSphered& sphere) const
{
if (_wire)
return false;
if (intersects(_triangles[0], sphere))
return true;
if (intersects(_triangles[1], sphere))
return true;
return false;
}
bool _intersects(const SGLineSegmentd& lineSegment) const
{
if (_wire)
return false;
if (intersects(_triangles[0], lineSegment))
return true;
if (intersects(_triangles[1], lineSegment))
return true;
return false;
}
const SGLineSegmentd& getLineSegment() const
{ return _lineSegment; }
const SGVec3d& getLinearVelocity() const
{ return _linearVelocity; }
const SGVec3d& getAngularVelocity() const
{ return _angularVelocity; }
const BVHLineGeometry* getWire() const
{ return _wire; }
private:
SGLineSegmentd _lineSegment;
SGVec3d _linearVelocity;
SGVec3d _angularVelocity;
const BVHLineGeometry* _wire;
SGTriangled _triangles[2];
double _time;
};
bool FGGroundCache::caught_wire(double t, const SGVec3d pt[4])
{
// Get the wire in question
t += cache_time_offset;
WireIntersector wireIntersector(pt, t);
if (_localBvhTree)
_localBvhTree->accept(wireIntersector);
_wire = wireIntersector.getWire();
return _wire;
}
class FGGroundCache::WireFinder : public BVHVisitor {
public:
WireFinder(const BVHLineGeometry* wire, const double& t) :
_wire(wire),
_time(t),
_lineSegment(SGVec3d::zeros(), SGVec3d::zeros()),
_linearVelocity(SGVec3d::zeros()),
_angularVelocity(SGVec3d::zeros()),
_haveLineSegment(false)
{ }
virtual void apply(BVHGroup& leaf)
{
if (_haveLineSegment)
return;
leaf.traverse(*this);
}
virtual void apply(BVHTransform& transform)
{
if (_haveLineSegment)
return;
transform.traverse(*this);
if (_haveLineSegment) {
_linearVelocity = transform.vecToWorld(_linearVelocity);
_angularVelocity = transform.vecToWorld(_angularVelocity);
_lineSegment = transform.lineSegmentToWorld(_lineSegment);
}
}
virtual void apply(BVHMotionTransform& transform)
{
if (_haveLineSegment)
return;
transform.traverse(*this);
if (_haveLineSegment) {
SGMatrixd toWorld = transform.getToWorldTransform(_time);
_linearVelocity
+= transform.getLinearVelocityAt(_lineSegment.getStart());
_angularVelocity += transform.getAngularVelocity();
_linearVelocity = toWorld.xformVec(_linearVelocity);
_angularVelocity = toWorld.xformVec(_angularVelocity);
_lineSegment = _lineSegment.transform(toWorld);
}
}
virtual void apply(BVHLineGeometry& node)
{
if (_haveLineSegment)
return;
if (_wire != &node)
return;
if (node.getType() != BVHLineGeometry::CarrierWire)
return;
_lineSegment = SGLineSegmentd(node.getLineSegment());
_linearVelocity = SGVec3d::zeros();
_angularVelocity = SGVec3d::zeros();
_haveLineSegment = true;
}
virtual void apply(BVHStaticGeometry&) { }
virtual void apply(const BVHStaticBinary&, const BVHStaticData&) { }
virtual void apply(const BVHStaticTriangle&, const BVHStaticData&) { }
const SGLineSegmentd& getLineSegment() const
{ return _lineSegment; }
bool getHaveLineSegment() const
{ return _haveLineSegment; }
const SGVec3d& getLinearVelocity() const
{ return _linearVelocity; }
const SGVec3d& getAngularVelocity() const
{ return _angularVelocity; }
private:
const BVHLineGeometry* _wire;
double _time;
SGLineSegmentd _lineSegment;
SGVec3d _linearVelocity;
SGVec3d _angularVelocity;
bool _haveLineSegment;
};
Modified Files: configure.ac src/AIModel/AIAircraft.cxx src/AIModel/AIBase.cxx src/AIModel/AIBase.hxx src/AIModel/AICarrier.cxx src/AIModel/AICarrier.hxx src/AIModel/AIManager.cxx src/AIModel/AIManager.hxx src/ATC/AIEntity.cxx src/ATC/AIEntity.hxx src/ATC/AIMgr.cxx src/ATC/AIMgr.hxx src/ATC/ATCdisplay.cxx src/ATC/ATCdisplay.hxx src/Cockpit/cockpit.cxx src/Cockpit/cockpit.hxx src/Cockpit/hud.cxx src/Cockpit/hud.hxx src/Cockpit/hud_rwy.cxx src/Cockpit/panel.cxx src/Cockpit/panel.hxx src/Cockpit/built_in/FGMagRibbon.cxx src/Cockpit/built_in/FGMagRibbon.hxx src/FDM/flight.cxx src/FDM/groundcache.cxx src/FDM/groundcache.hxx src/GUI/gui_funcs.cxx src/Input/input.cxx src/Instrumentation/od_gauge.cxx src/Instrumentation/od_gauge.hxx src/Instrumentation/render_area_2d.cxx src/Instrumentation/render_area_2d.hxx src/Instrumentation/wxradar.cxx src/Instrumentation/wxradar.hxx src/Instrumentation/HUD/HUD.cxx src/Instrumentation/HUD/HUD.hxx src/Instrumentation/HUD/HUD_runway.cxx src/Main/Makefile.am src/Main/main.cxx src/Main/renderer.cxx src/Main/renderer.hxx src/Main/viewmgr.cxx src/Model/acmodel.cxx src/Model/acmodel.hxx src/Model/model_panel.cxx src/Model/model_panel.hxx src/Model/modelmgr.cxx src/Model/modelmgr.hxx src/Model/panelnode.cxx src/Model/panelnode.hxx src/Navaids/awynet.cxx src/Scenery/Makefile.am src/Scenery/hitlist.cxx src/Scenery/hitlist.hxx src/Scenery/newcache.cxx src/Scenery/scenery.cxx src/Scenery/scenery.hxx src/Scenery/tileentry.cxx src/Scenery/tileentry.hxx src/Scenery/tilemgr.cxx src/Scripting/NasalSys.cxx src/Scripting/NasalSys.hxx src/Time/light.cxx Big BLOB on the way to OSG.
2006-10-29 19:30:21 +00:00
bool FGGroundCache::get_wire_ends(double t, SGVec3d end[2], SGVec3d vel[2])
{
// Fast return if we do not have an active wire.
if (!_wire)
return false;
// Get the wire in question
t += cache_time_offset;
WireFinder wireFinder(_wire, t);
if (_localBvhTree)
_localBvhTree->accept(wireFinder);
if (!wireFinder.getHaveLineSegment())
return false;
// prepare the returns
end[0] = wireFinder.getLineSegment().getStart();
end[1] = wireFinder.getLineSegment().getEnd();
// The linear velocity is the one at the start of the line segment ...
vel[0] = wireFinder.getLinearVelocity();
// ... so the end point has the additional cross product.
vel[1] = wireFinder.getLinearVelocity();
vel[1] += cross(wireFinder.getAngularVelocity(),
wireFinder.getLineSegment().getDirection());
return true;
}
void FGGroundCache::release_wire(void)
{
_wire = 0;
}