Make initial use of the boundingvolumes for the ground cache.
Modified Files: src/AIModel/AICarrier.cxx src/AIModel/AICarrier.hxx src/FDM/flight.hxx src/FDM/groundcache.cxx src/FDM/groundcache.hxx
This commit is contained in:
parent
ff2e5d5999
commit
1708e43a39
5 changed files with 801 additions and 755 deletions
|
@ -25,12 +25,19 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/Drawable>
|
||||
#include <osg/Transform>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/TemplatePrimitiveFunctor>
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/scene/util/SGNodeMasks.hxx>
|
||||
#include <simgear/scene/util/SGSceneUserData.hxx>
|
||||
#include <simgear/scene/bvh/BVHGroup.hxx>
|
||||
#include <simgear/scene/bvh/BVHLineGeometry.hxx>
|
||||
|
||||
#include <math.h>
|
||||
#include <Main/util.hxx>
|
||||
|
@ -38,63 +45,133 @@
|
|||
|
||||
#include "AICarrier.hxx"
|
||||
|
||||
/// Hmm: move that kind of configuration into the model file???
|
||||
class LineCollector : public osg::NodeVisitor {
|
||||
struct LinePrimitiveFunctor {
|
||||
LinePrimitiveFunctor() : _lineCollector(0)
|
||||
{ }
|
||||
void operator() (const osg::Vec3&, bool)
|
||||
{ }
|
||||
void operator() (const osg::Vec3& v1, const osg::Vec3& v2, bool)
|
||||
{ if (_lineCollector) _lineCollector->addLine(v1, v2); }
|
||||
void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&,
|
||||
bool)
|
||||
{ }
|
||||
void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&,
|
||||
const osg::Vec3&, bool)
|
||||
{ }
|
||||
LineCollector* _lineCollector;
|
||||
};
|
||||
|
||||
public:
|
||||
LineCollector() :
|
||||
osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
|
||||
osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{ }
|
||||
virtual void apply(osg::Geode& geode)
|
||||
{
|
||||
osg::TemplatePrimitiveFunctor<LinePrimitiveFunctor> pf;
|
||||
pf._lineCollector = this;
|
||||
for (unsigned i = 0; i < geode.getNumDrawables(); ++i) {
|
||||
geode.getDrawable(i)->accept(pf);
|
||||
}
|
||||
}
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
traverse(node);
|
||||
}
|
||||
virtual void apply(osg::Transform& transform)
|
||||
{
|
||||
osg::Matrix matrix = _matrix;
|
||||
if (transform.computeLocalToWorldMatrix(_matrix, this))
|
||||
traverse(transform);
|
||||
_matrix = matrix;
|
||||
}
|
||||
|
||||
const std::vector<SGLineSegmentf>& getLineSegments() const
|
||||
{ return _lineSegments; }
|
||||
|
||||
void addLine(const osg::Vec3& v1, const osg::Vec3& v2)
|
||||
{
|
||||
// Trick to get the ends in the right order.
|
||||
// Use the x axis in the original coordinate system. Choose the
|
||||
// most negative x-axis as the one pointing forward
|
||||
SGVec3f tv1(_matrix.preMult(v1));
|
||||
SGVec3f tv2(_matrix.preMult(v2));
|
||||
if (tv1[0] > tv2[0])
|
||||
_lineSegments.push_back(SGLineSegmentf(tv1, tv2));
|
||||
else
|
||||
_lineSegments.push_back(SGLineSegmentf(tv2, tv1));
|
||||
}
|
||||
|
||||
void addBVHElements(osg::Node& node, simgear::BVHLineGeometry::Type type)
|
||||
{
|
||||
if (_lineSegments.empty())
|
||||
return;
|
||||
|
||||
SGSceneUserData* userData;
|
||||
userData = SGSceneUserData::getOrCreateSceneUserData(&node);
|
||||
|
||||
simgear::BVHNode* bvNode = userData->getBVHNode();
|
||||
if (!bvNode && _lineSegments.size() == 1) {
|
||||
simgear::BVHLineGeometry* bvLine;
|
||||
bvLine = new simgear::BVHLineGeometry(_lineSegments.front(), type);
|
||||
userData->setBVHNode(bvLine);
|
||||
return;
|
||||
}
|
||||
|
||||
simgear::BVHGroup* group = new simgear::BVHGroup;
|
||||
if (bvNode)
|
||||
group->addChild(bvNode);
|
||||
|
||||
for (unsigned i = 0; i < _lineSegments.size(); ++i) {
|
||||
simgear::BVHLineGeometry* bvLine;
|
||||
bvLine = new simgear::BVHLineGeometry(_lineSegments[i], type);
|
||||
group->addChild(bvLine);
|
||||
}
|
||||
userData->setBVHNode(group);
|
||||
}
|
||||
|
||||
private:
|
||||
osg::Matrix _matrix;
|
||||
std::vector<SGLineSegmentf> _lineSegments;
|
||||
};
|
||||
|
||||
class FGCarrierVisitor : public osg::NodeVisitor {
|
||||
public:
|
||||
FGCarrierVisitor(FGAICarrier* carrier,
|
||||
const std::list<std::string>& wireObjects,
|
||||
const std::list<std::string>& catapultObjects,
|
||||
const std::list<std::string>& solidObjects) :
|
||||
osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
|
||||
osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
mWireObjects(wireObjects),
|
||||
mCatapultObjects(catapultObjects),
|
||||
mSolidObjects(solidObjects),
|
||||
mFoundHot(false),
|
||||
mCarrier(carrier)
|
||||
{ }
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
osg::ref_ptr<osg::Referenced> oldUserData = mUserData;
|
||||
bool oldFoundHot = mFoundHot;
|
||||
mFoundHot = false;
|
||||
|
||||
if (std::find(mWireObjects.begin(), mWireObjects.end(), node.getName())
|
||||
!= mWireObjects.end()) {
|
||||
mFoundHot = true;
|
||||
mUserData = FGAICarrierHardware::newWire(mCarrier);
|
||||
FGCarrierVisitor(FGAICarrier* carrier,
|
||||
const std::list<std::string>& wireObjects,
|
||||
const std::list<std::string>& catapultObjects) :
|
||||
osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
|
||||
osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
mWireObjects(wireObjects),
|
||||
mCatapultObjects(catapultObjects)
|
||||
{ }
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
if (std::find(mWireObjects.begin(), mWireObjects.end(), node.getName())
|
||||
!= mWireObjects.end()) {
|
||||
LineCollector lineCollector;
|
||||
node.accept(lineCollector);
|
||||
simgear::BVHLineGeometry::Type type;
|
||||
type = simgear::BVHLineGeometry::CarrierWire;
|
||||
lineCollector.addBVHElements(node, type);
|
||||
}
|
||||
if (std::find(mCatapultObjects.begin(), mCatapultObjects.end(),
|
||||
node.getName()) != mCatapultObjects.end()) {
|
||||
LineCollector lineCollector;
|
||||
node.accept(lineCollector);
|
||||
simgear::BVHLineGeometry::Type type;
|
||||
type = simgear::BVHLineGeometry::CarrierCatapult;
|
||||
lineCollector.addBVHElements(node, type);
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
if (std::find(mCatapultObjects.begin(), mCatapultObjects.end(), node.getName())
|
||||
!= mCatapultObjects.end()) {
|
||||
mFoundHot = true;
|
||||
mUserData = FGAICarrierHardware::newCatapult(mCarrier);
|
||||
}
|
||||
if (std::find(mSolidObjects.begin(), mSolidObjects.end(), node.getName())
|
||||
!= mSolidObjects.end()) {
|
||||
mFoundHot = true;
|
||||
mUserData = FGAICarrierHardware::newSolid(mCarrier);
|
||||
//SG_LOG(SG_GENERAL, SG_ALERT, "AICarrierVisitor::apply() solidObject" );
|
||||
}
|
||||
node.setUserData(mUserData.get());
|
||||
|
||||
traverse(node);
|
||||
|
||||
mFoundHot = oldFoundHot || mFoundHot;
|
||||
|
||||
if (mFoundHot) {
|
||||
node.setNodeMask(node.getNodeMask() | SG_NODEMASK_TERRAIN_BIT);
|
||||
} else
|
||||
node.setNodeMask(node.getNodeMask() & ~SG_NODEMASK_TERRAIN_BIT);
|
||||
|
||||
mUserData = oldUserData;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::list<std::string> mWireObjects;
|
||||
std::list<std::string> mCatapultObjects;
|
||||
std::list<std::string> mSolidObjects;
|
||||
bool mFoundHot;
|
||||
FGAICarrier* mCarrier;
|
||||
osg::ref_ptr<osg::Referenced> mUserData;
|
||||
std::list<std::string> mWireObjects;
|
||||
std::list<std::string> mCatapultObjects;
|
||||
};
|
||||
|
||||
FGAICarrier::FGAICarrier() : FGAIShip(otCarrier) {
|
||||
|
@ -145,13 +222,6 @@ void FGAICarrier::readFromScenario(SGPropertyNode* scFileNode) {
|
|||
catapult_objects.push_back(s);
|
||||
}
|
||||
|
||||
props = scFileNode->getChildren("solid");
|
||||
for (it = props.begin(); it != props.end(); ++it) {
|
||||
std::string s = (*it)->getStringValue();
|
||||
if (!s.empty())
|
||||
solid_objects.push_back(s);
|
||||
}
|
||||
|
||||
props = scFileNode->getChildren("parking-pos");
|
||||
for (it = props.begin(); it != props.end(); ++it) {
|
||||
string name = (*it)->getStringValue("name", "unnamed");
|
||||
|
@ -199,12 +269,6 @@ void FGAICarrier::setTACANChannelID(const string& id) {
|
|||
TACAN_channel_id = id;
|
||||
}
|
||||
|
||||
void FGAICarrier::getVelocityWrtEarth(SGVec3d& v, SGVec3d& omega, SGVec3d& pivot) {
|
||||
v = vel_wrt_earth;
|
||||
omega = rot_wrt_earth;
|
||||
pivot = rot_pivot_wrt_earth;
|
||||
}
|
||||
|
||||
void FGAICarrier::update(double dt) {
|
||||
// For computation of rotation speeds we just use finite differences here.
|
||||
// That is perfectly valid since this thing is not driven by accelerations
|
||||
|
@ -219,13 +283,9 @@ void FGAICarrier::update(double dt) {
|
|||
SGQuatd ec2body = ec2hl*hl2body;
|
||||
// The cartesian position of the carrier in the wgs84 world
|
||||
SGVec3d cartPos = SGVec3d::fromGeod(pos);
|
||||
// Store for later use by the groundcache
|
||||
rot_pivot_wrt_earth = cartPos;
|
||||
|
||||
// Compute the velocity in m/s in the earth centered coordinate system axis
|
||||
double v_north = 0.51444444*speed*cos(hdg * SGD_DEGREES_TO_RADIANS);
|
||||
double v_east = 0.51444444*speed*sin(hdg * SGD_DEGREES_TO_RADIANS);
|
||||
vel_wrt_earth = ec2hl.backTransform(SGVec3d(v_north, v_east, 0));
|
||||
// Compute the velocity in m/s in the body frame
|
||||
aip.setBodyLinearVelocity(SGVec3d(0.51444444*speed, 0, 0));
|
||||
|
||||
// Now update the position and heading. This will compute new hdg and
|
||||
// roll values required for the rotation speed computation.
|
||||
|
@ -242,9 +302,7 @@ void FGAICarrier::update(double dt) {
|
|||
}
|
||||
|
||||
// Only change these values if we are able to compute them safely
|
||||
if (dt < DBL_MIN)
|
||||
rot_wrt_earth = SGVec3d::zeros();
|
||||
else {
|
||||
if (SGLimits<double>::min() < dt) {
|
||||
// Now here is the finite difference ...
|
||||
|
||||
// Transform that one to the horizontal local coordinate system.
|
||||
|
@ -258,13 +316,7 @@ void FGAICarrier::update(double dt) {
|
|||
// divided by the time difference provides a rotation speed vector
|
||||
dOrAngleAxis /= dt;
|
||||
|
||||
// now rotate the rotation speed vector back into the
|
||||
// earth centered frames coordinates
|
||||
dOrAngleAxis = ec2body.backTransform(dOrAngleAxis);
|
||||
// dOrAngleAxis = hl2body.backTransform(dOrAngleAxis);
|
||||
// dOrAngleAxis(1) = 0;
|
||||
// dOrAngleAxis = ec2hl.backTransform(dOrAngleAxis);
|
||||
rot_wrt_earth = dOrAngleAxis;
|
||||
aip.setBodyAngularVelocity(dOrAngleAxis);
|
||||
}
|
||||
|
||||
UpdateWind(dt);
|
||||
|
@ -351,19 +403,9 @@ void FGAICarrier::initModel(osg::Node *node)
|
|||
FGAIShip::initModel(node);
|
||||
// process the 3d model here
|
||||
// mark some objects solid, mark the wires ...
|
||||
|
||||
// The model should be used for altitude computations.
|
||||
// To avoid that every detail in a carrier 3D model will end into
|
||||
// the aircraft local cache, only set the HOT traversal bit on
|
||||
// selected objects.
|
||||
|
||||
// Clear the HOT traversal flag
|
||||
// Selectively set that flag again for wires/cats/solid objects.
|
||||
// Attach a pointer to this carrier class to those objects.
|
||||
// SG_LOG(SG_GENERAL, SG_BULK, "AICarrier::initModel() visit" );
|
||||
FGCarrierVisitor carrierVisitor(this, wire_objects, catapult_objects, solid_objects);
|
||||
FGCarrierVisitor carrierVisitor(this, wire_objects, catapult_objects);
|
||||
model->accept(carrierVisitor);
|
||||
// model->setNodeMask(node->getNodeMask() & SG_NODEMASK_TERRAIN_BIT | model->getNodeMask());
|
||||
model->setNodeMask(model->getNodeMask() | SG_NODEMASK_TERRAIN_BIT);
|
||||
}
|
||||
|
||||
void FGAICarrier::bind() {
|
||||
|
@ -694,7 +736,3 @@ void FGAICarrier::UpdateJBD(double dt, double jbd_transition_time) {
|
|||
return;
|
||||
|
||||
} // end UpdateJBD
|
||||
|
||||
|
||||
int FGAICarrierHardware::unique_id = 1;
|
||||
|
||||
|
|
|
@ -40,42 +40,6 @@ using std::list;
|
|||
class FGAIManager;
|
||||
class FGAICarrier;
|
||||
|
||||
class FGAICarrierHardware : public osg::Referenced {
|
||||
public:
|
||||
|
||||
enum Type { Catapult, Wire, Solid };
|
||||
|
||||
FGAICarrier *carrier;
|
||||
int id;
|
||||
Type type;
|
||||
|
||||
static FGAICarrierHardware* newCatapult(FGAICarrier *c) {
|
||||
FGAICarrierHardware* ch = new FGAICarrierHardware;
|
||||
ch->carrier = c;
|
||||
ch->type = Catapult;
|
||||
ch->id = unique_id++;
|
||||
return ch;
|
||||
}
|
||||
static FGAICarrierHardware* newWire(FGAICarrier *c) {
|
||||
FGAICarrierHardware* ch = new FGAICarrierHardware;
|
||||
ch->carrier = c;
|
||||
ch->type = Wire;
|
||||
ch->id = unique_id++;
|
||||
return ch;
|
||||
}
|
||||
static FGAICarrierHardware* newSolid(FGAICarrier *c) {
|
||||
FGAICarrierHardware* ch = new FGAICarrierHardware;
|
||||
ch->carrier = c;
|
||||
ch->type = Solid;
|
||||
ch->id = unique_id++;
|
||||
return ch;
|
||||
}
|
||||
|
||||
private:
|
||||
static int unique_id;
|
||||
};
|
||||
|
||||
|
||||
class FGAICarrier : public FGAIShip {
|
||||
public:
|
||||
|
||||
|
@ -87,7 +51,6 @@ public:
|
|||
void setSign(const string& );
|
||||
void setTACANChannelID(const string &);
|
||||
|
||||
void getVelocityWrtEarth(SGVec3d& v, SGVec3d& omega, SGVec3d& pivot);
|
||||
virtual void bind();
|
||||
virtual void unbind();
|
||||
void UpdateWind ( double dt );
|
||||
|
@ -133,17 +96,11 @@ private:
|
|||
double rel_wind_from_deg;
|
||||
|
||||
|
||||
list<string> solid_objects; // List of solid object names
|
||||
list<string> wire_objects; // List of wire object names
|
||||
list<string> catapult_objects; // List of catapult object names
|
||||
list<ParkPosition> ppositions; // List of positions where an aircraft can start.
|
||||
string sign; // The sign of this carrier.
|
||||
|
||||
// Velocity wrt earth.
|
||||
SGVec3d vel_wrt_earth;
|
||||
SGVec3d rot_wrt_earth;
|
||||
SGVec3d rot_pivot_wrt_earth;
|
||||
|
||||
// these describe the flols
|
||||
SGVec3d flols_off;
|
||||
|
||||
|
|
|
@ -601,11 +601,11 @@ public:
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum GroundType {
|
||||
/// I sused at least in YAsim. Deprecate this ad get it from the
|
||||
/// Material instead
|
||||
Unknown = 0, //??
|
||||
Solid, // Whatever we will roll on with infinite load factor.
|
||||
Water, // For the beaver ...
|
||||
Catapult, // Carrier cats.
|
||||
Wire // Carrier wires.
|
||||
Water // For the beaver ...
|
||||
};
|
||||
|
||||
// Prepare the ground cache for the wgs84 position pt_*.
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,20 +23,20 @@
|
|||
#ifndef _GROUNDCACHE_HXX
|
||||
#define _GROUNDCACHE_HXX
|
||||
|
||||
#include <osg/Node>
|
||||
|
||||
namespace osgUtil
|
||||
{
|
||||
class PolytopeIntersector;
|
||||
}
|
||||
#include <osg/Group>
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/math/SGGeometry.hxx>
|
||||
#include <simgear/scene/bvh/BVHNode.hxx>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
|
||||
class SGMaterial;
|
||||
class WireIntersector;
|
||||
namespace simgear {
|
||||
class BVHLineGeometry;
|
||||
}
|
||||
|
||||
class FGGroundCache {
|
||||
public:
|
||||
|
@ -89,42 +89,14 @@ public:
|
|||
void release_wire(void);
|
||||
|
||||
private:
|
||||
friend class GroundCacheFillVisitor;
|
||||
|
||||
|
||||
// Helper class to hold some properties of the ground triangle.
|
||||
struct GroundProperty {
|
||||
GroundProperty() : type(0), wire_id(0), material(0) {}
|
||||
int type;
|
||||
int wire_id;
|
||||
// The linear and angular velocity.
|
||||
SGVec3d vel;
|
||||
SGVec3d rot;
|
||||
SGVec3d pivot;
|
||||
// the simgear material reference, contains friction coeficients ...
|
||||
const SGMaterial* material;
|
||||
};
|
||||
|
||||
struct Triangle {
|
||||
GroundProperty gp;
|
||||
// The triangle we represent
|
||||
SGTriangled triangle;
|
||||
SGSphered sphere;
|
||||
};
|
||||
struct Catapult {
|
||||
GroundProperty gp;
|
||||
SGVec3d start;
|
||||
SGVec3d end;
|
||||
};
|
||||
struct Wire {
|
||||
GroundProperty gp;
|
||||
SGVec3d ends[2];
|
||||
};
|
||||
|
||||
class CacheFill;
|
||||
class CatapultFinder;
|
||||
class WireIntersector;
|
||||
class WireFinder;
|
||||
|
||||
// Approximate ground radius.
|
||||
// In case the aircraft is too high above ground.
|
||||
double ground_radius;
|
||||
double _altitude;
|
||||
// Ground type
|
||||
int _type;
|
||||
// the simgear material reference, contains friction coeficients ...
|
||||
|
@ -132,13 +104,8 @@ private:
|
|||
// The time reference for later call to intersection test routines.
|
||||
// Is required since we will have moving triangles in carriers.
|
||||
double cache_ref_time;
|
||||
// The wire identifier to track.
|
||||
int wire_id;
|
||||
|
||||
// Containers which hold all the essential information about this cache.
|
||||
std::vector<Triangle> triangles;
|
||||
std::vector<Catapult> catapults;
|
||||
std::vector<Wire> wires;
|
||||
// The wire to track.
|
||||
const simgear::BVHLineGeometry* _wire;
|
||||
|
||||
// The point and radius where the cache is built around.
|
||||
// That are the arguments that were given to prepare_ground_cache.
|
||||
|
@ -147,14 +114,7 @@ private:
|
|||
SGVec3d down;
|
||||
bool found_ground;
|
||||
|
||||
void getGroundProperty(osg::Drawable* drawable,
|
||||
const osg::NodePath& nodePath,
|
||||
GroundProperty& gp, bool& backfaceCulling);
|
||||
static void velocityTransformTriangle(double dt, SGTriangled& dst,
|
||||
SGSphered& sdst, const Triangle& src);
|
||||
void getTriIntersectorResults(osgUtil::PolytopeIntersector* triInt);
|
||||
void getWireIntersectorResults(WireIntersector* wireInt,
|
||||
double wireCacheRadius);
|
||||
SGSharedPtr<simgear::BVHNode> _localBvhTree;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue