diff --git a/configure.ac b/configure.ac index 6f828eac7..0afede1a4 100644 --- a/configure.ac +++ b/configure.ac @@ -38,6 +38,14 @@ if test "x$with_plib" != "x" ; then EXTRA_DIRS="${EXTRA_DIRS} $with_plib" fi +# specify the osg location +AC_ARG_WITH(osg, [ --with-osg=PREFIX Specify the prefix path to osg]) + +if test "x$with_osg" != "x" ; then + echo "osg prefix is $with_osg" + EXTRA_DIRS="${EXTRA_DIRS} $with_osg" +fi + dnl Determine an extra directories to add to include/lib search paths case "${host}" in *-apple-darwin* | *-*-mingw32*) diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index c6450677a..315bbdf6a 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -82,6 +82,11 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) : use_perf_vs = true; isTanker = false; + no_roll = false; + tgt_speed = 0; + speed = 0; + groundTargetSpeed = 0; + // set heading and altitude locks hdg_lock = false; alt_lock = false; diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx index 2c274cd37..11a3877d2 100644 --- a/src/AIModel/AIBase.cxx +++ b/src/AIModel/AIBase.cxx @@ -26,8 +26,8 @@ #include STL_STRING -#include -#include +#include +#include #include #include @@ -73,7 +73,7 @@ FGAIBase::~FGAIBase() { // Unregister that one at the scenery manager if (globals->get_scenery()) { globals->get_scenery()->unregister_placement_transform(aip.getTransform()); - globals->get_scenery()->get_scene_graph()->removeKid(aip.getSceneGraph()); + globals->get_scenery()->get_scene_graph()->removeChild(aip.getSceneGraph()); } if (props) { SGPropertyNode* parent = props->getParent(); @@ -135,11 +135,11 @@ bool FGAIBase::init() { model = NULL; } } - if (model) { - aip.init( model ); + if (model.get()) { + aip.init( model.get() ); aip.setVisible(true); invisible = false; - globals->get_scenery()->get_scene_graph()->addKid(aip.getSceneGraph()); + globals->get_scenery()->get_scene_graph()->addChild(aip.getSceneGraph()); // Register that one at the scenery manager globals->get_scenery()->register_placement_transform(aip.getTransform()); fgSetString("/ai/models/model-added", props->getPath()); @@ -155,15 +155,16 @@ bool FGAIBase::init() { } -ssgBranch * FGAIBase::load3DModel(const string& fg_root, - const string &path, - SGPropertyNode *prop_root, - double sim_time_sec) +osg::Node* +FGAIBase::load3DModel(const string& fg_root, + const string &path, + SGPropertyNode *prop_root, + double sim_time_sec) { // some more code here to check whether a model with this name has already been loaded // if not load it, otherwise, get the memory pointer and do something like // SetModel as in ATC/AIEntity.cxx - ssgBranch *personality_branch = new SGPersonalityBranch; + osg::Group* personality_branch = new SGPersonalityBranch; model = manager->getModel(path); if (!(model)) { @@ -171,9 +172,9 @@ ssgBranch * FGAIBase::load3DModel(const string& fg_root, path, prop_root, sim_time_sec); - manager->setModel(path, model); + manager->setModel(path, model.get()); } - personality_branch->addKid( model ); + personality_branch->addChild( model.get() ); return personality_branch; //return model; diff --git a/src/AIModel/AIBase.hxx b/src/AIModel/AIBase.hxx index 5fd191c87..83d7e2a20 100644 --- a/src/AIModel/AIBase.hxx +++ b/src/AIModel/AIBase.hxx @@ -118,7 +118,7 @@ protected: double ht_diff; // value used by radar display instrument string model_path; //Path to the 3D model - ssgSharedPtr model; //The 3D model object + osg::ref_ptr model; //The 3D model object SGModelPlacement aip; bool delete_me; bool invisible; @@ -173,7 +173,7 @@ public: static const double lbs_to_slugs; inline double _getRange() { return range; }; - ssgBranch * load3DModel(const string& fg_root, + osg::Node* load3DModel(const string& fg_root, const string &path, SGPropertyNode *prop_root, double sim_time_sec); diff --git a/src/AIModel/AICarrier.cxx b/src/AIModel/AICarrier.cxx index 7fa08422b..0ec684609 100644 --- a/src/AIModel/AICarrier.cxx +++ b/src/AIModel/AICarrier.cxx @@ -21,22 +21,79 @@ # include #endif +#include #include #include +#include + #include -#include #include +#include + #include #include
#include
#include "AICarrier.hxx" -/** Value of earth radius (meters) */ -#define RADIUS_M SG_EQUATORIAL_RADIUS_M +class FGCarrierVisitor : public osg::NodeVisitor { +public: + FGCarrierVisitor(FGAICarrier* carrier, + const std::list& wireObjects, + const std::list& catapultObjects, + const std::list& 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 oldUserData = mUserData; + bool oldFoundHot = mFoundHot; + mFoundHot = false; + if (std::find(mWireObjects.begin(), mWireObjects.end(), node.getName()) + != mWireObjects.end()) { + mFoundHot = true; + mUserData = FGAICarrierHardware::newWire(mCarrier); + } + 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); + } + 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 mWireObjects; + std::list mCatapultObjects; + std::list mSolidObjects; + bool mFoundHot; + FGAICarrier* mCarrier; + osg::ref_ptr mUserData; +}; FGAICarrier::FGAICarrier() : FGAIShip(otCarrier) { } @@ -140,10 +197,10 @@ void FGAICarrier::setTACANChannelID(const string& id) { TACAN_channel_id = id; } -void FGAICarrier::getVelocityWrtEarth(sgdVec3& v, sgdVec3& omega, sgdVec3& pivot) { - sgdCopyVec3(v, vel_wrt_earth.sg() ); - sgdCopyVec3(omega, rot_wrt_earth.sg() ); - sgdCopyVec3(pivot, rot_pivot_wrt_earth.sg() ); +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) { @@ -263,14 +320,12 @@ bool FGAICarrier::init() { // 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. - ssgEntity *sel = aip.getSceneGraph(); + osg::Node* sel = aip.getSceneGraph(); // Clear the HOT traversal flag - mark_nohot(sel); // Selectively set that flag again for wires/cats/solid objects. // Attach a pointer to this carrier class to those objects. - mark_wires(sel, wire_objects); - mark_cat(sel, catapult_objects); - mark_solid(sel, solid_objects); + FGCarrierVisitor carrierVisitor(this, wire_objects, catapult_objects, solid_objects); + sel->accept(carrierVisitor); _longitude_node = fgGetNode("/position/longitude-deg", true); _latitude_node = fgGetNode("/position/latitude-deg", true); @@ -416,187 +471,6 @@ bool FGAICarrier::getParkPosition(const string& id, SGGeod& geodPos, return false; } - -void FGAICarrier::mark_nohot(ssgEntity* e) { - if (e->isAKindOf(ssgTypeBranch())) { - ssgBranch* br = (ssgBranch*)e; - ssgEntity* kid; - for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() ) - mark_nohot(kid); - - br->clrTraversalMaskBits(SSGTRAV_HOT); - - } else if (e->isAKindOf(ssgTypeLeaf())) { - - e->clrTraversalMaskBits(SSGTRAV_HOT); - } -} - - -bool FGAICarrier::mark_wires(ssgEntity* e, const list& wire_objects, bool mark) { - bool found = false; - if (e->isAKindOf(ssgTypeBranch())) { - ssgBranch* br = (ssgBranch*)e; - ssgEntity* kid; - - list::const_iterator it; - for (it = wire_objects.begin(); it != wire_objects.end(); ++it) - mark = mark || (e->getName() && (*it) == e->getName()); - - for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() ) - found = mark_wires(kid, wire_objects, mark) || found; - - if (found) - br->setTraversalMaskBits(SSGTRAV_HOT); - - } else if (e->isAKindOf(ssgTypeLeaf())) { - list::const_iterator it; - for (it = wire_objects.begin(); it != wire_objects.end(); ++it) { - if (mark || (e->getName() && (*it) == e->getName())) { - e->setTraversalMaskBits(SSGTRAV_HOT); - ssgBase* ud = e->getUserData(); - if (ud) { - FGAICarrierHardware* ch = dynamic_cast(ud); - if (ch) { - SG_LOG(SG_GENERAL, SG_WARN, - "AICarrier: Carrier hardware gets marked twice!\n" - " You have probably a whole branch marked as" - " a wire which also includes other carrier hardware."); - } else { - SG_LOG(SG_GENERAL, SG_ALERT, - "AICarrier: Found user data attached to a leaf node which " - "should be marked as a wire!\n ****Skipping!****"); - } - } else { - e->setUserData( FGAICarrierHardware::newWire( this ) ); - ssgLeaf *l = (ssgLeaf*)e; - if ( l->getNumLines() != 1 ) { - SG_LOG(SG_GENERAL, SG_ALERT, - "AICarrier: Found wires not modeled with exactly one line!"); - } - found = true; - } - } - } - } - return found; -} - - -bool FGAICarrier::mark_solid(ssgEntity* e, const list& solid_objects, bool mark) { - bool found = false; - if (e->isAKindOf(ssgTypeBranch())) { - ssgBranch* br = (ssgBranch*)e; - ssgEntity* kid; - - list::const_iterator it; - for (it = solid_objects.begin(); it != solid_objects.end(); ++it) - mark = mark || (e->getName() && (*it) == e->getName()); - - for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() ) - found = mark_solid(kid, solid_objects, mark) || found; - - if (found) - br->setTraversalMaskBits(SSGTRAV_HOT); - - } else if (e->isAKindOf(ssgTypeLeaf())) { - list::const_iterator it; - for (it = solid_objects.begin(); it != solid_objects.end(); ++it) { - if (mark || (e->getName() && (*it) == e->getName())) { - e->setTraversalMaskBits(SSGTRAV_HOT); - ssgBase* ud = e->getUserData(); - - if (ud) { - FGAICarrierHardware* ch = dynamic_cast(ud); - if (ch) { - SG_LOG(SG_GENERAL, SG_WARN, - "AICarrier: Carrier hardware gets marked twice!\n" - " You have probably a whole branch marked solid" - " which also includes other carrier hardware."); - } else { - SG_LOG(SG_GENERAL, SG_ALERT, - "AICarrier: Found user data attached to a leaf node which " - "should be marked solid!\n ****Skipping!****"); - } - } else { - e->setUserData( FGAICarrierHardware::newSolid( this ) ); - found = true; - } - } - } - } - return found; -} - - -bool FGAICarrier::mark_cat(ssgEntity* e, const list& cat_objects, bool mark) { - bool found = false; - if (e->isAKindOf(ssgTypeBranch())) { - ssgBranch* br = (ssgBranch*)e; - ssgEntity* kid; - - list::const_iterator it; - for (it = cat_objects.begin(); it != cat_objects.end(); ++it) - mark = mark || (e->getName() && (*it) == e->getName()); - - for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() ) - found = mark_cat(kid, cat_objects, mark) || found; - - if (found) - br->setTraversalMaskBits(SSGTRAV_HOT); - - } else if (e->isAKindOf(ssgTypeLeaf())) { - list::const_iterator it; - for (it = cat_objects.begin(); it != cat_objects.end(); ++it) { - if (mark || (e->getName() && (*it) == e->getName())) { - e->setTraversalMaskBits(SSGTRAV_HOT); - ssgBase* ud = e->getUserData(); - if (ud) { - FGAICarrierHardware* ch = dynamic_cast(ud); - if (ch) { - SG_LOG(SG_GENERAL, SG_WARN, - "AICarrier: Carrier hardware gets marked twice!\n" - "You have probably a whole branch marked as" - "a catapult which also includes other carrier hardware."); - } else { - SG_LOG(SG_GENERAL, SG_ALERT, - "AICarrier: Found user data attached to a leaf node which " - "should be marked as a catapult!\n ****Skipping!****"); - } - } else { - e->setUserData( FGAICarrierHardware::newCatapult( this ) ); - ssgLeaf *l = (ssgLeaf*)e; - if ( l->getNumLines() != 1 ) { - SG_LOG(SG_GENERAL, SG_ALERT, - "AICarrier: Found a cat not modeled with exactly " - "one line!"); - } else { - // Now some special code to make sure the cat points in the right - // direction. The 0 index must be the backward end, the 1 index - // the forward end. - // Forward is positive x-direction in our 3D model, also the model - // as such is flattened when it is loaded, so we do not need to - // care for transforms ... - short v[2]; - l->getLine(0, v, v+1 ); - SGVec3f ends[2]; - for (int k=0; k<2; ++k) - sgCopyVec3( ends[k].sg(), l->getVertex( v[k] ) ); - - // When the 1 end is behind the 0 end, swap the coordinates. - if (ends[0][0] < ends[1][0]) { - sgCopyVec3( l->getVertex( v[0] ), ends[1].sg() ); - sgCopyVec3( l->getVertex( v[1] ), ends[0].sg() ); - } - found = true; - } - } - } - } - } - return found; -} - // find relative wind void FGAICarrier::UpdateWind( double dt) { @@ -746,12 +620,6 @@ bool FGAICarrier::OutsideBox() { //returns true if the carrier is outside operat } // end OutsideBox -// return the distance to the horizon, given the altitude and the radius of the earth -float FGAICarrier::Horizon(float h) { - return RADIUS_M * acos(RADIUS_M / (RADIUS_M + h)); -} - - bool FGAICarrier::InToWind() { if ( fabs(rel_wind) < 5 ) return true; diff --git a/src/AIModel/AICarrier.hxx b/src/AIModel/AICarrier.hxx index 9a3d52f41..d76e1ed0e 100644 --- a/src/AIModel/AICarrier.hxx +++ b/src/AIModel/AICarrier.hxx @@ -23,7 +23,10 @@ #include #include -#include + +#include +#include + #include SG_USING_STD(string); @@ -37,7 +40,7 @@ SG_USING_STD(list); class FGAIManager; class FGAICarrier; -class FGAICarrierHardware : public ssgBase { +class FGAICarrierHardware : public osg::Referenced { public: enum Type { Catapult, Wire, Solid }; @@ -84,7 +87,7 @@ public: void setSign(const string& ); void setTACANChannelID(const string &); - void getVelocityWrtEarth(sgdVec3& v, sgdVec3& omega, sgdVec3& pivot); + void getVelocityWrtEarth(SGVec3d& v, SGVec3d& omega, SGVec3d& pivot); virtual void bind(); virtual void unbind(); void UpdateWind ( double dt ); @@ -97,7 +100,6 @@ public: void TurnToLaunch(); void TurnToBase(); void ReturnToBox(); - float Horizon(float h); bool OutsideBox(); bool init(); @@ -124,11 +126,6 @@ private: void update(double dt); - void mark_nohot(ssgEntity*); - - bool mark_wires(ssgEntity*, const list&, bool = false); - bool mark_cat(ssgEntity*, const list&, bool = false); - bool mark_solid(ssgEntity*, const list&, bool = false); double wind_from_east; // fps double wind_from_north; // fps double rel_wind_speed_kts; diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index bdf9f5b36..c5decd5e3 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -259,7 +259,7 @@ FGAIManager::loadScenarioFile(const std::string& filename) // This code keeps track of models that have already been loaded // Eventually we'd prbably need to find a way to keep track of models // that are unloaded again -ssgBranch * FGAIManager::getModel(const string& path) +osg::Node* FGAIManager::getModel(const string& path) { ModelVecIterator i = loadedModels.begin(); //cerr << "Reference count summary " << endl; @@ -291,7 +291,7 @@ ssgBranch * FGAIManager::getModel(const string& path) return 0; } -void FGAIManager::setModel(const string& path, ssgBranch *model) +void FGAIManager::setModel(const string& path, osg::Node *model) { loadedModels.push_back(FGModelID(path,model)); } diff --git a/src/AIModel/AIManager.hxx b/src/AIModel/AIManager.hxx index 42b279bf2..4b6d4ef08 100644 --- a/src/AIModel/AIManager.hxx +++ b/src/AIModel/AIManager.hxx @@ -26,7 +26,6 @@ #include #include -#include #include #include
@@ -43,13 +42,13 @@ SG_USING_STD(vector); class FGModelID { private: - ssgSharedPtr model; + osg::ref_ptr model; string path; public: - FGModelID(const string& pth, ssgBranch * mdl) { path =pth; model=mdl;}; - ssgBranch * const getModelId() const { return model;}; + FGModelID(const string& pth, osg::Node* mdl) { path =pth; model=mdl;}; + osg::Node* const getModelId() const { return model.get();}; const string & getPath() const { return path;}; - int getNumRefs() const { return model.getNumRefs(); }; + int getNumRefs() const { return model->referenceCount(); }; }; typedef vector ModelVec; @@ -100,8 +99,8 @@ public: void processScenario( const string &filename ); - ssgBranch * getModel(const string& path); - void setModel(const string& path, ssgBranch *model); + osg::Node* getModel(const string& path); + void setModel(const string& path, osg::Node *model); static SGPropertyNode_ptr loadScenarioFile(const std::string& filename); diff --git a/src/ATC/AIEntity.cxx b/src/ATC/AIEntity.cxx index f4d58cd1d..7afbef1ba 100644 --- a/src/ATC/AIEntity.cxx +++ b/src/ATC/AIEntity.cxx @@ -46,18 +46,18 @@ FGAIEntity::FGAIEntity() { FGAIEntity::~FGAIEntity() { //cout << "FGAIEntity dtor called..." << endl; //cout << "Removing model from scene graph..." << endl; - globals->get_scenery()->get_scene_graph()->removeKid(_aip.getSceneGraph()); + globals->get_scenery()->get_scene_graph()->removeChild(_aip.getSceneGraph()); // Unregister that one at the scenery manager globals->get_scenery()->unregister_placement_transform(_aip.getTransform()); //cout << "Done!" << endl; } -void FGAIEntity::SetModel(ssgBranch* model) { +void FGAIEntity::SetModel(osg::Node* model) { _model = model; - _aip.init(_model); + _aip.init(_model.get()); _aip.setVisible(false); - globals->get_scenery()->get_scene_graph()->addKid(_aip.getSceneGraph()); + globals->get_scenery()->get_scene_graph()->addChild(_aip.getSceneGraph()); // Register that one at the scenery manager globals->get_scenery()->register_placement_transform(_aip.getTransform()); diff --git a/src/ATC/AIEntity.hxx b/src/ATC/AIEntity.hxx index 5c7f276bf..dc9070b8b 100644 --- a/src/ATC/AIEntity.hxx +++ b/src/ATC/AIEntity.hxx @@ -24,10 +24,6 @@ #include #include #include -#include - - -class ssgBase; /***************************************************************** @@ -46,7 +42,7 @@ public: virtual ~FGAIEntity(); // Set the 3D model to use (Must be called) - void SetModel(ssgBranch* model); + void SetModel(osg::Node* model); // Run the internal calculations virtual void Update(double dt)=0; @@ -67,7 +63,7 @@ protected: double _pitch; //degrees char* _model_path; //Path to the 3D model - ssgSharedPtr _model; // Pointer to the model + osg::ref_ptr _model; // Pointer to the model SGModelPlacement _aip; void Transform(); diff --git a/src/ATC/AIMgr.cxx b/src/ATC/AIMgr.cxx index 34527a79f..60519cc69 100644 --- a/src/ATC/AIMgr.cxx +++ b/src/ATC/AIMgr.cxx @@ -306,7 +306,7 @@ void FGAIMgr::ActivateAirport(const string& ident) { ATC->AIRegisterAirport(ident); // TODO - need to start the traffic more randomly FGAILocalTraffic* local_traffic = new FGAILocalTraffic; - local_traffic->SetModel(_defaultModel); // currently hardwired to cessna. + local_traffic->SetModel(_defaultModel.get()); // currently hardwired to cessna. //local_traffic->Init(ident, IN_PATTERN, TAKEOFF_ROLL); local_traffic->Init(GenerateShortForm(GenerateUniqueCallsign()), ident); local_traffic->FlyCircuits(1, true); // Fly 2 circuits with touch & go in between @@ -469,7 +469,7 @@ void FGAIMgr::GenerateSimpleAirportTraffic(const string& ident, double min_dist) else cessna = true; string s = GenerateShortForm(GenerateUniqueCallsign(), (cessna ? "Cessna-" : "Piper-")); FGAIGAVFRTraffic* t = new FGAIGAVFRTraffic(); - t->SetModel(cessna ? _defaultModel : (_havePiperModel ? _piperModel : _defaultModel)); + t->SetModel(cessna ? _defaultModel.get() : (_havePiperModel ? _piperModel.get() : _defaultModel.get())); //cout << "Generating VFR traffic " << s << " inbound to " << ident << " " << ad << " meters out from " << dir << " degrees\n"; Point3D tpos = dclUpdatePosition(aptpos, dir, 6.0, ad); if(tpos.elev() > (aptpos.elev() + 3000.0)) tpos.setelev(aptpos.elev() + 3000.0); // FEET yuk :-( diff --git a/src/ATC/AIMgr.hxx b/src/ATC/AIMgr.hxx index a1e3e6115..6bc81a10b 100644 --- a/src/ATC/AIMgr.hxx +++ b/src/ATC/AIMgr.hxx @@ -23,7 +23,6 @@ #define _FG_AIMGR_HXX #include -#include #include
@@ -110,8 +109,8 @@ public: private: - ssgSharedPtr _defaultModel; // Cessna 172! - ssgSharedPtr _piperModel; // pa28-161 + osg::ref_ptr _defaultModel; // Cessna 172! + osg::ref_ptr _piperModel; // pa28-161 bool initDone; // Hack - guard against update getting called before init diff --git a/src/ATC/ATCdisplay.cxx b/src/ATC/ATCdisplay.cxx index 89588e000..e554a4d78 100644 --- a/src/ATC/ATCdisplay.cxx +++ b/src/ATC/ATCdisplay.cxx @@ -61,8 +61,13 @@ void FGATCDisplay::bind() { void FGATCDisplay::unbind() { } +void FGATCDisplay::update(double dt) +{ + std::cout << "OSGFIXME" << std::endl; +} + // update - this actually draws the visuals and should be called from the main Flightgear rendering loop. -void FGATCDisplay::update(double dt) { +void FGATCDisplay::update(double dt, osg::State& state) { // These strings are used for temporary storage of the transmission string in order // that the string we view only changes when the next repetition starts scrolling diff --git a/src/ATC/ATCdisplay.hxx b/src/ATC/ATCdisplay.hxx index cc3818de9..bf94d0acd 100644 --- a/src/ATC/ATCdisplay.hxx +++ b/src/ATC/ATCdisplay.hxx @@ -27,6 +27,7 @@ # include #endif +#include #include #include @@ -72,6 +73,7 @@ public: void unbind(); // Display any registered messages + void update(double dt, osg::State&); void update(double dt); // Register a single message for display after a delay of delay seconds diff --git a/src/Cockpit/built_in/FGMagRibbon.cxx b/src/Cockpit/built_in/FGMagRibbon.cxx index 7f3f8ceb1..a05db18ae 100644 --- a/src/Cockpit/built_in/FGMagRibbon.cxx +++ b/src/Cockpit/built_in/FGMagRibbon.cxx @@ -36,7 +36,7 @@ FGMagRibbon::FGMagRibbon (int w, int h) } void -FGMagRibbon::draw () +FGMagRibbon::draw (osg::State& state) { double heading = _magcompass_node->getDoubleValue(); double xoffset, yoffset; @@ -71,10 +71,16 @@ FGMagRibbon::draw () FGCroppedTexture *t = getTexture(); t->setCrop(xoffset, yoffset, xoffset + 0.5, yoffset + 0.25); - glPushAttrib(GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); - FGTexturedLayer::draw(); - glPopAttrib(); + static osg::ref_ptr stateSet = new osg::StateSet; + stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); + + state.pushStateSet(stateSet.get()); + state.apply(); + + FGTexturedLayer::draw(state); + + state.popStateSet(); + state.apply(); } // end of FGMagRibbon.cxx diff --git a/src/Cockpit/built_in/FGMagRibbon.hxx b/src/Cockpit/built_in/FGMagRibbon.hxx index a430c6178..39c320df3 100644 --- a/src/Cockpit/built_in/FGMagRibbon.hxx +++ b/src/Cockpit/built_in/FGMagRibbon.hxx @@ -34,7 +34,7 @@ public: FGMagRibbon (int w, int h); virtual ~FGMagRibbon () {} - virtual void draw (); + virtual void draw (osg::State& state); private: SGPropertyNode_ptr _magcompass_node; diff --git a/src/Cockpit/cockpit.cxx b/src/Cockpit/cockpit.cxx index 74c1bde9a..e746f854f 100644 --- a/src/Cockpit/cockpit.cxx +++ b/src/Cockpit/cockpit.cxx @@ -550,7 +550,7 @@ bool fgCockpitInit( fgAIRCRAFT *cur_aircraft ) return true; } -void fgCockpitUpdate( void ) { +void fgCockpitUpdate( osg::State* state ) { SG_LOG( SG_COCKPIT, SG_DEBUG, "Cockpit: code " << ac_cockpit->code() << " status " @@ -568,7 +568,7 @@ void fgCockpitUpdate( void ) { if ( hud_visibility_node->getBoolValue() ) { // This will check the global hud linked list pointer. // If there is anything to draw it will. - fgUpdateHUD(); + fgUpdateHUD( state ); } glViewport( 0, 0, iwidth, iheight ); diff --git a/src/Cockpit/cockpit.hxx b/src/Cockpit/cockpit.hxx index b3d7b420e..5b8b7e632 100644 --- a/src/Cockpit/cockpit.hxx +++ b/src/Cockpit/cockpit.hxx @@ -31,8 +31,9 @@ # error This library requires C++ #endif +#include -#include +#include "Aircraft/aircraft.hxx" #include "panel.hxx" // Class fg_Cockpit This class is a holder for the heads up display @@ -53,7 +54,7 @@ class fg_Cockpit { typedef fg_Cockpit * pCockpit; bool fgCockpitInit( fgAIRCRAFT *cur_aircraft ); -void fgCockpitUpdate( void ); +void fgCockpitUpdate( osg::State* ); #endif /* _COCKPIT_HXX */ diff --git a/src/Cockpit/hud.cxx b/src/Cockpit/hud.cxx index 0d016b873..88597d5dc 100644 --- a/src/Cockpit/hud.cxx +++ b/src/Cockpit/hud.cxx @@ -79,8 +79,8 @@ float HUD_matrix[16]; int readHud( istream &input ); int readInstrument ( const SGPropertyNode * node); -static void drawHUD(); -static void fgUpdateHUDVirtual(); +static void drawHUD(osg::State*); +static void fgUpdateHUDVirtual(osg::State*); class locRECT { @@ -255,8 +255,6 @@ int fgHUDInit( fgAIRCRAFT * /* current_aircraft */ ) input.close(); } - fgHUDReshape(); - if ( HUDtext ) { // this chunk of code is not necessarily thread safe if the // compiler optimizer reorders these statements. Note that @@ -314,39 +312,17 @@ int fgHUDInit2( fgAIRCRAFT * /* current_aircraft */ ) //$$$ End - added, Neetha, 28 Nov 2k -void fgHUDReshape(void) { -#if 0 - if ( HUDtext ) { - // this chunk of code is not necessarily thread safe if the - // compiler optimizer reorders these statements. Note that - // "delete ptr" does not set "ptr = NULL". We have to do that - // ourselves. - fntRenderer *tmp = HUDtext; - HUDtext = NULL; - delete tmp; - } - - HUD_TextSize = fgGetInt("/sim/startup/xsize") / 60; - HUD_TextSize = 10; - HUDtext = new fntRenderer(); - HUDtext -> setFont ( guiFntHandle ) ; - HUDtext -> setPointSize ( HUD_TextSize ) ; - HUD_TextList.setFont( HUDtext ); -#endif -} - - // fgUpdateHUD // // Performs a once around the list of calls to instruments installed in // the HUD object with requests for redraw. Kinda. It will when this is // all C++. // -void fgUpdateHUD( void ) { +void fgUpdateHUD( osg::State* state ) { static const SGPropertyNode *enable3d_node = fgGetNode("/sim/hud/enable3d"); if ( HUD_style == 1 && enable3d_node->getBoolValue() ) { - fgUpdateHUDVirtual(); + fgUpdateHUDVirtual(state); return; } @@ -356,15 +332,15 @@ void fgUpdateHUD( void ) { if ( current_aspect > normal_aspect ) { float aspect_adjust = current_aspect / normal_aspect; float adjust = 320.0f*aspect_adjust - 320.0f; - fgUpdateHUD( -adjust, 0.0f, 640.0f+adjust, 480.0f ); + fgUpdateHUD( state, -adjust, 0.0f, 640.0f+adjust, 480.0f ); } else { float aspect_adjust = normal_aspect / current_aspect; float adjust = 240.0f*aspect_adjust - 240.0f; - fgUpdateHUD( 0.0f, -adjust, 640.0f, 480.0f+adjust ); + fgUpdateHUD( state, 0.0f, -adjust, 640.0f, 480.0f+adjust ); } } -void fgUpdateHUDVirtual() +void fgUpdateHUDVirtual(osg::State* state) { FGViewer* view = globals->get_current_view(); @@ -406,7 +382,7 @@ void fgUpdateHUDVirtual() glTranslatef(-320, -240, -1); // Do the deed - drawHUD(); + drawHUD(state); // Clean up our mess glMatrixMode(GL_PROJECTION); @@ -416,7 +392,7 @@ void fgUpdateHUDVirtual() } -void fgUpdateHUD( GLfloat x_start, GLfloat y_start, +void fgUpdateHUD( osg::State* state, GLfloat x_start, GLfloat y_start, GLfloat x_end, GLfloat y_end ) { glMatrixMode(GL_PROJECTION); @@ -428,7 +404,7 @@ void fgUpdateHUD( GLfloat x_start, GLfloat y_start, glPushMatrix(); glLoadIdentity(); - drawHUD(); + drawHUD(state); glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -437,7 +413,7 @@ void fgUpdateHUD( GLfloat x_start, GLfloat y_start, } -void drawHUD() +void drawHUD(osg::State* state) { if ( !HUD_deque.size() ) // Trust everyone, but ALWAYS cut the cards! return; diff --git a/src/Cockpit/hud.hxx b/src/Cockpit/hud.hxx index 3964bacd5..8556e4b24 100644 --- a/src/Cockpit/hud.hxx +++ b/src/Cockpit/hud.hxx @@ -41,15 +41,13 @@ #include #include -//#ifdef HAVE_VALUES_H -//# include // for MAXINT -//#endif - #include // for_each() #include // STL vector #include // STL double ended queue #include STL_FSTREAM +#include + #include #include @@ -106,32 +104,6 @@ enum fgLabelJust{ LEFT_JUST, CENTER_JUST, RIGHT_JUST } ; #define HUDS_DECITICS 0x0040 #define HUDS_NOTEXT 0x0080 -// Ladder orientaion -// #define HUD_VERTICAL 1 -// #define HUD_HORIZONTAL 2 -// #define HUD_FREEFLOAT 3 - -// Ladder orientation modes -// #define HUD_LEFT 1 -// #define HUD_RIGHT 2 -// #define HUD_TOP 1 -// #define HUD_BOTTOM 2 -// #define HUD_V_LEFT 1 -// #define HUD_V_RIGHT 2 -// #define HUD_H_TOP 1 -// #define HUD_H_BOTTOM 2 - - -// Ladder sub-types -// #define HUD_LIM 1 -// #define HUD_NOLIM 2 -// #define HUD_CIRC 3 - -// #define HUD_INSTR_LADDER 1 -// #define HUD_INSTR_CLADDER 2 -// #define HUD_INSTR_HORIZON 3 -// #define HUD_INSTR_LABEL 4 - // in cockpit.cxx extern float get_throttleval ( void ); extern float get_aileronval ( void ); @@ -161,10 +133,8 @@ extern float get_climb_rate ( void ); extern float get_mach( void ); extern char *coord_format_lat(float); extern char *coord_format_lon(float); -//extern char *coord_format_latlon(float latitude, float longitude); // cockpit.cxx // $$$ begin - added, VS Renganathan, 13 Oct 2K -// #define FIGHTER_HUD extern float get_anzg (void); extern float get_Vx (void); extern float get_Vy (void); @@ -205,7 +175,6 @@ extern float get_aux18(void); // $$$ end - added, VS Renganathan, 13 Oct 2K extern char *get_formated_gmt_time( void ); -extern void fgHUDReshape(void); enum hudinstype{ HUDno_instr, HUDscale, @@ -522,9 +491,7 @@ class HUDdraw { }; -extern deque< instr_item *> HUD_deque; extern int HUD_style; -//extern hud_deque_type HUD_deque; // instr_item This class has no other purpose than to maintain // a linked list of instrument and derived class @@ -788,27 +755,12 @@ public: }; -//using namespace std; -//deque * Hdeque_ptr; - extern int fgHUDInit( fgAIRCRAFT * /* current_aircraft */ ); extern int fgHUDInit2( fgAIRCRAFT * /* current_aircraft */ ); -extern void fgUpdateHUD( void ); -extern void fgUpdateHUD( GLfloat x_start, GLfloat y_start, +extern void fgUpdateHUD( osg::State* ); +extern void fgUpdateHUD( osg::State*, GLfloat x_start, GLfloat y_start, GLfloat x_end, GLfloat y_end ); -/* -bool AddHUDInstrument( instr_item *pBlackBox ); -void DrawHUD ( void ); -bool DamageInstrument( INSTR_HANDLE unit ); -bool RepairInstrument( INSTR_HANDLE unit ); - - -void fgUpdateHUD ( Hptr hud ); -void fgUpdateHUD2( Hptr hud ); // Future use? -void fgHUDSetTimeMode( Hptr hud, int time_of_day ); -*/ - diff --git a/src/Cockpit/hud_rwy.cxx b/src/Cockpit/hud_rwy.cxx index bb3e78c59..aac5e26e0 100644 --- a/src/Cockpit/hud_rwy.cxx +++ b/src/Cockpit/hud_rwy.cxx @@ -105,13 +105,16 @@ void runway_instr::draw() globals->get_viewmgr()->copyToCurrent(); } //Set the camera to the cockpit view to get the view of the runway from the cockpit - ssgSetCamera((sgVec4 *)cockpit_view->get_VIEW()); + // OSGFIXME +// ssgSetCamera((sgVec4 *)cockpit_view->get_VIEW()); get_rwy_points(points3d); //Get the current project matrix - ssgGetProjectionMatrix(projMat); + // OSGFIXME +// ssgGetProjectionMatrix(projMat); // const sgVec4 *viewMat = globals->get_current_view()->get_VIEW(); //Get the current model view matrix (cockpit view) - ssgGetModelviewMatrix(modelView); + // OSGFIXME +// ssgGetModelviewMatrix(modelView); //Create a rotation matrix to correct for any offsets (other than default offsets) to the model view matrix sgMat4 xy; //rotation about the Rxy, negate the sin's on Ry xy[0][0] = cYaw; xy[1][0] = 0.0f; xy[2][0] = -sYaw; xy[3][0] = 0.0f; @@ -164,7 +167,8 @@ void runway_instr::draw() curr_view->setGoalPitchOffset_deg(gpo); } //Set the camera back to the current view - ssgSetCamera((sgVec4 *)curr_view); + // OSGFIXME +// ssgSetCamera((sgVec4 *)curr_view); glPopAttrib(); }//if not broken } diff --git a/src/Cockpit/panel.cxx b/src/Cockpit/panel.cxx index 90c5e2000..b0f6db745 100644 --- a/src/Cockpit/panel.cxx +++ b/src/Cockpit/panel.cxx @@ -38,15 +38,21 @@ #include // sprintf #include +#include +#include +#include +#include +#include + #include #include SG_GLU_H -#include #include #include #include +#include #include
#include
@@ -109,23 +115,24 @@ fgPanelVisible () // Implementation of FGTextureManager. //////////////////////////////////////////////////////////////////////// -map FGTextureManager::_textureMap; +map > FGTextureManager::_textureMap; -ssgTexture * +osg::Texture2D* FGTextureManager::createTexture (const string &relativePath) { - ssgTexture * texture = _textureMap[relativePath]; + osg::Texture2D* texture = _textureMap[relativePath].get(); if (texture == 0) { SG_LOG( SG_COCKPIT, SG_DEBUG, "Texture " << relativePath << " does not yet exist" ); SGPath tpath(globals->get_fg_root()); tpath.append(relativePath); - texture = new ssgTexture((char *)tpath.c_str(), false, false); + + texture = SGLoadTexture2D(tpath); + _textureMap[relativePath] = texture; - if (_textureMap[relativePath] == 0) + if (!_textureMap[relativePath].valid()) SG_LOG( SG_COCKPIT, SG_ALERT, "Texture *still* doesn't exist" ); - SG_LOG( SG_COCKPIT, SG_DEBUG, "Created texture " << relativePath - << " handle=" << texture->getHandle() ); + SG_LOG( SG_COCKPIT, SG_DEBUG, "Created texture " << relativePath ); } return texture; @@ -160,13 +167,16 @@ FGCroppedTexture::~FGCroppedTexture () } -ssgTexture * +osg::StateSet* FGCroppedTexture::getTexture () { if (_texture == 0) { - _texture = FGTextureManager::createTexture(_path); + _texture = new osg::StateSet; + _texture->setTextureAttribute(0, FGTextureManager::createTexture(_path)); + _texture->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); + _texture->setTextureAttribute(0, new osg::TexEnv(osg::TexEnv::MODULATE)); } - return _texture; + return _texture.get(); } @@ -254,11 +264,52 @@ FGPanel::unbind () } +void +FGPanel::update (double dt) +{ + std::cout << "OSGFIXME" << std::endl; +} + +void +FGPanel::update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh) +{ + // Calculate accelerations + // and jiggle the panel accordingly + // The factors and bounds are just + // initial guesses; using sqrt smooths + // out the spikes. + double x_offset = _x_offset->getIntValue(); + double y_offset = _y_offset->getIntValue(); + + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + if ( _flipx->getBoolValue() ) { + gluOrtho2D(winx + winw, winx, winy + winh, winy); /* up side down */ + } else { + gluOrtho2D(winx, winx + winw, winy, winy + winh); /* right side up */ + } + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glTranslated(x_offset, y_offset, 0); + + draw(state); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + /** * Update the panel. */ void -FGPanel::update (double dt) +FGPanel::update (osg::State& state) { // Do nothing if the panel isn't visible. if ( !fgPanelVisible() ) { @@ -271,9 +322,9 @@ FGPanel::update (double dt) float aspect_adjust = get_aspect_adjust(_xsize_node->getIntValue(), _ysize_node->getIntValue()); if (aspect_adjust <1.0) - update(WIN_X, int(WIN_W * aspect_adjust), WIN_Y, WIN_H); + update(state, WIN_X, int(WIN_W * aspect_adjust), WIN_Y, WIN_H); else - update(WIN_X, WIN_W, WIN_Y, int(WIN_H / aspect_adjust)); + update(state, WIN_X, WIN_W, WIN_Y, int(WIN_H / aspect_adjust)); } /** @@ -294,87 +345,39 @@ void FGPanel::updateMouseDelay() void -FGPanel::update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh) -{ - // Calculate accelerations - // and jiggle the panel accordingly - // The factors and bounds are just - // initial guesses; using sqrt smooths - // out the spikes. - double x_offset = _x_offset->getIntValue(); - double y_offset = _y_offset->getIntValue(); - -#if 0 - if (_jitter->getFloatValue() != 0.0) { - double a_x_pilot = current_aircraft.fdm_state->get_A_X_pilot(); - double a_y_pilot = current_aircraft.fdm_state->get_A_Y_pilot(); - double a_z_pilot = current_aircraft.fdm_state->get_A_Z_pilot(); - - double a_zx_pilot = a_z_pilot - a_x_pilot; - - int x_adjust = int(sqrt(fabs(a_y_pilot) * _jitter->getFloatValue())) * - (a_y_pilot < 0 ? -1 : 1); - int y_adjust = int(sqrt(fabs(a_zx_pilot) * _jitter->getFloatValue())) * - (a_zx_pilot < 0 ? -1 : 1); - - // adjustments in screen coordinates - x_offset += x_adjust; - y_offset += y_adjust; - } -#endif - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - if ( _flipx->getBoolValue() ) { - gluOrtho2D(winx + winw, winx, winy + winh, winy); /* up side down */ - } else { - gluOrtho2D(winx, winx + winw, winy, winy + winh); /* right side up */ - } - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glTranslated(x_offset, y_offset, 0); - - draw(); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - ssgForceBasicState(); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -} - -void -FGPanel::draw() +FGPanel::draw(osg::State& state) { // In 3D mode, it's possible that we are being drawn exactly on top // of an existing polygon. Use an offset to prevent z-fighting. In // 2D mode, this is a no-op. - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1, -POFF_UNITS); + static osg::ref_ptr panelStateSet; + if (!panelStateSet.valid()) { + panelStateSet = new osg::StateSet; + panelStateSet->setAttributeAndModes(new osg::PolygonOffset(-1, -POFF_UNITS)); + panelStateSet->setTextureAttribute(0, new osg::TexEnv); - // save some state - glPushAttrib( GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT - | GL_TEXTURE_BIT | GL_PIXEL_MODE_BIT | GL_CULL_FACE - | GL_DEPTH_BUFFER_BIT ); - - // Draw the background - glEnable(GL_TEXTURE_2D); - glDisable(GL_LIGHTING); - glEnable(GL_BLEND); - glEnable(GL_ALPHA_TEST); - glEnable(GL_COLOR_MATERIAL); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - if ( _enable_depth_test ) - glDepthFunc(GL_ALWAYS); - else - glDisable(GL_DEPTH_TEST); + // Draw the background + panelStateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); + panelStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + panelStateSet->setMode(GL_BLEND, osg::StateAttribute::ON); + panelStateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON); + osg::Material* material = new osg::Material; + material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); + material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 1, 1, 1)); + material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 1, 1, 1)); + material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1)); + material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1)); + panelStateSet->setAttribute(material); + panelStateSet->setMode(GL_COLOR_MATERIAL, osg::StateAttribute::ON); + panelStateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON); + panelStateSet->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); + if ( _enable_depth_test ) + panelStateSet->setAttributeAndModes(new osg::Depth(osg::Depth::ALWAYS)); + else + panelStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); + } + state.pushStateSet(panelStateSet.get()); + state.apply(); FGLight *l = (FGLight *)(globals->get_subsystem("lighting")); sgCopyVec4( panel_color, l->scene_diffuse()); @@ -385,36 +388,40 @@ FGPanel::draw() } glColor4fv( panel_color ); if (_bg != 0) { - glBindTexture(GL_TEXTURE_2D, _bg->getHandle()); - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + state.pushStateSet(_bg.get()); + state.apply(); glBegin(GL_POLYGON); glTexCoord2f(0.0, 0.0); glVertex2f(WIN_X, WIN_Y); glTexCoord2f(1.0, 0.0); glVertex2f(WIN_X + _width, WIN_Y); glTexCoord2f(1.0, 1.0); glVertex2f(WIN_X + _width, WIN_Y + _height); glTexCoord2f(0.0, 1.0); glVertex2f(WIN_X, WIN_Y + _height); glEnd(); + state.popStateSet(); + state.apply(); } else { for (int i = 0; i < 4; i ++) { // top row of textures...(1,3,5,7) - glBindTexture(GL_TEXTURE_2D, _mbg[i*2]->getHandle()); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + state.pushStateSet(_mbg[i*2].get()); + state.apply(); glBegin(GL_POLYGON); glTexCoord2f(0.0, 0.0); glVertex2f(WIN_X + (_width/4) * i, WIN_Y + (_height/2)); glTexCoord2f(1.0, 0.0); glVertex2f(WIN_X + (_width/4) * (i+1), WIN_Y + (_height/2)); glTexCoord2f(1.0, 1.0); glVertex2f(WIN_X + (_width/4) * (i+1), WIN_Y + _height); glTexCoord2f(0.0, 1.0); glVertex2f(WIN_X + (_width/4) * i, WIN_Y + _height); glEnd(); + state.popStateSet(); + state.apply(); // bottom row of textures...(2,4,6,8) - glBindTexture(GL_TEXTURE_2D, _mbg[(i*2)+1]->getHandle()); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + state.pushStateSet(_mbg[i*2+1].get()); + state.apply(); glBegin(GL_POLYGON); glTexCoord2f(0.0, 0.0); glVertex2f(WIN_X + (_width/4) * i, WIN_Y); glTexCoord2f(1.0, 0.0); glVertex2f(WIN_X + (_width/4) * (i+1), WIN_Y); glTexCoord2f(1.0, 1.0); glVertex2f(WIN_X + (_width/4) * (i+1), WIN_Y + (_height/2)); glTexCoord2f(0.0, 1.0); glVertex2f(WIN_X + (_width/4) * i, WIN_Y + (_height/2)); glEnd(); + state.popStateSet(); + state.apply(); } } @@ -448,7 +455,7 @@ FGPanel::draw() glEnable(GL_CLIP_PLANE2); glEnable(GL_CLIP_PLANE3); glPopMatrix(); - instr->draw(); + instr->draw(state); glPopMatrix(); } @@ -458,24 +465,24 @@ FGPanel::draw() glDisable(GL_CLIP_PLANE2); glDisable(GL_CLIP_PLANE3); + state.popStateSet(); + state.apply(); // Draw yellow "hotspots" if directed to. This is a panel authoring // feature; not intended to be high performance or to look good. if ( fgGetBool("/sim/panel-hotspots") ) { - glDisable(GL_TEXTURE_2D); + static osg::ref_ptr hotspotStateSet = new osg::StateSet; + hotspotStateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF); + state.pushStateSet(hotspotStateSet.get()); + state.apply(); + glColor3f(1, 1, 0); for ( unsigned int i = 0; i < _instruments.size(); i++ ) - _instruments[i]->drawHotspots(); + _instruments[i]->drawHotspots(state); + state.popStateSet(); + state.apply(); } - - - // restore some original state - if ( _enable_depth_test ) - glDepthFunc(GL_LESS); - glPopAttrib(); - glPolygonOffset(0, 0); - glDisable(GL_POLYGON_OFFSET_FILL); } /** @@ -502,19 +509,28 @@ FGPanel::getVisibility () const * Set the panel's background texture. */ void -FGPanel::setBackground (ssgTexture * texture) +FGPanel::setBackground (osg::Texture2D* texture) { - _bg = texture; + osg::StateSet* stateSet = new osg::StateSet; + stateSet->setTextureAttribute(0, texture); + stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); + stateSet->setTextureAttribute(0, new osg::TexEnv(osg::TexEnv::MODULATE)); + _bg = stateSet; } /** * Set the panel's multiple background textures. */ void -FGPanel::setMultiBackground (ssgTexture * texture, int idx) +FGPanel::setMultiBackground (osg::Texture2D* texture, int idx) { _bg = 0; - _mbg[idx] = texture; + + osg::StateSet* stateSet = new osg::StateSet; + stateSet->setTextureAttribute(0, texture); + stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); + stateSet->setTextureAttribute(0, new osg::TexEnv(osg::TexEnv::MODULATE)); + _mbg[idx] = stateSet; } /** @@ -702,7 +718,7 @@ FGPanelInstrument::~FGPanelInstrument () } void -FGPanelInstrument::drawHotspots() +FGPanelInstrument::drawHotspots(osg::State& state) { for ( unsigned int i = 0; i < _actions.size(); i++ ) { FGPanelAction* a = _actions[i]; @@ -800,14 +816,14 @@ FGLayeredInstrument::~FGLayeredInstrument () } void -FGLayeredInstrument::draw () +FGLayeredInstrument::draw (osg::State& state) { if (!test()) return; for (int i = 0; i < (int)_layers.size(); i++) { glPushMatrix(); - _layers[i]->draw(); + _layers[i]->draw(state); glPopMatrix(); } } @@ -857,7 +873,7 @@ FGSpecialInstrument::~FGSpecialInstrument () } void -FGSpecialInstrument::draw () +FGSpecialInstrument::draw (osg::State& state) { complex->draw(); } @@ -947,13 +963,13 @@ FGGroupLayer::~FGGroupLayer () } void -FGGroupLayer::draw () +FGGroupLayer::draw (osg::State& state) { if (test()) { transform(); int nLayers = _layers.size(); for (int i = 0; i < nLayers; i++) - _layers[i]->draw(); + _layers[i]->draw(state); } } @@ -984,14 +1000,15 @@ FGTexturedLayer::~FGTexturedLayer () void -FGTexturedLayer::draw () +FGTexturedLayer::draw (osg::State& state) { if (test()) { int w2 = _w / 2; int h2 = _h / 2; transform(); - glBindTexture(GL_TEXTURE_2D, _texture.getTexture()->getHandle()); + state.pushStateSet(_texture.getTexture()); + state.apply(); glBegin(GL_POLYGON); if (_emissive) { @@ -1007,6 +1024,8 @@ FGTexturedLayer::draw () glTexCoord2f(_texture.getMaxX(), _texture.getMaxY()); glVertex2f(w2, h2); glTexCoord2f(_texture.getMinX(), _texture.getMaxY()); glVertex2f(-w2, h2); glEnd(); + state.popStateSet(); + state.apply(); } } @@ -1034,7 +1053,7 @@ FGTextLayer::~FGTextLayer () } void -FGTextLayer::draw () +FGTextLayer::draw (osg::State& state) { if (test()) { glColor4fv(_color); @@ -1187,14 +1206,14 @@ FGSwitchLayer::FGSwitchLayer () } void -FGSwitchLayer::draw () +FGSwitchLayer::draw (osg::State& state) { if (test()) { transform(); int nLayers = _layers.size(); for (int i = 0; i < nLayers; i++) { if (_layers[i]->test()) { - _layers[i]->draw(); + _layers[i]->draw(state); return; } } diff --git a/src/Cockpit/panel.hxx b/src/Cockpit/panel.hxx index 6be0dbfd7..81f7bc3a8 100644 --- a/src/Cockpit/panel.hxx +++ b/src/Cockpit/panel.hxx @@ -34,6 +34,10 @@ # include #endif +#include +#include +#include + #include #include @@ -54,7 +58,6 @@ SG_USING_STD(vector); SG_USING_STD(map); -class ssgTexture; class FGPanelInstrument; @@ -72,9 +75,9 @@ class FGPanelInstrument; class FGTextureManager { public: - static ssgTexture * createTexture(const string &relativePath); + static osg::Texture2D* createTexture(const string &relativePath); private: - static map _textureMap; + static map > _textureMap; }; @@ -97,7 +100,7 @@ public: virtual const string &getPath () const { return _path; } - virtual ssgTexture * getTexture (); + virtual osg::StateSet* getTexture (); virtual void setCrop (float minX, float minY, float maxX, float maxY) { _minX = minX; _minY = minY; _maxX = maxX; _maxY = maxY; @@ -111,7 +114,7 @@ public: private: string _path; - ssgTexture * _texture; + osg::ref_ptr _texture; float _minX, _minY, _maxX, _maxY; }; @@ -141,9 +144,10 @@ public: virtual void init (); virtual void bind (); virtual void unbind (); - virtual void draw (); - virtual void update (double dt); - virtual void update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh); + virtual void draw (osg::State& state); + virtual void update (double); + void update (osg::State& state); + virtual void update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh); virtual void updateMouseDelay(); @@ -151,10 +155,10 @@ public: virtual void addInstrument (FGPanelInstrument * instrument); // Background texture. - virtual void setBackground (ssgTexture * texture); + virtual void setBackground (osg::Texture2D* texture); // Background multiple textures. - virtual void setMultiBackground (ssgTexture * texture, int idx); + virtual void setMultiBackground (osg::Texture2D* texture, int idx); // Make the panel visible or invisible. virtual bool getVisibility () const; @@ -208,8 +212,8 @@ private: SGConstPropertyNode_ptr _xsize_node; SGConstPropertyNode_ptr _ysize_node; - ssgTexture * _bg; - ssgTexture * _mbg[8]; + osg::ref_ptr _bg; + osg::ref_ptr _mbg[8]; // List of instruments in panel. instrument_list_type _instruments; bool _enable_depth_test; @@ -335,7 +339,7 @@ public: FGInstrumentLayer (int w = -1, int h = -1); virtual ~FGInstrumentLayer (); - virtual void draw () = 0; + virtual void draw (osg::State& state) = 0; virtual void transform () const; virtual int getWidth () const { return _w; } @@ -377,8 +381,8 @@ public: FGPanelInstrument (int x, int y, int w, int h); virtual ~FGPanelInstrument (); - virtual void draw () = 0; - virtual void drawHotspots(); + virtual void draw (osg::State& state) = 0; + virtual void drawHotspots(osg::State& state); virtual void setPosition(int x, int y); virtual void setSize(int w, int h); @@ -414,7 +418,7 @@ public: FGLayeredInstrument (int x, int y, int w, int h); virtual ~FGLayeredInstrument (); - virtual void draw (); + virtual void draw (osg::State& state); // Transfer pointer ownership!! virtual int addLayer (FGInstrumentLayer *layer); @@ -444,7 +448,7 @@ public: //FGSpecialInstrument (int x, int y, int w, int h); virtual ~FGSpecialInstrument (); - virtual void draw (); + virtual void draw (osg::State& state); protected: DCLGPS* complex; @@ -463,7 +467,7 @@ class FGGroupLayer : public FGInstrumentLayer public: FGGroupLayer (); virtual ~FGGroupLayer (); - virtual void draw (); + virtual void draw (osg::State& state); // transfer pointer ownership virtual void addLayer (FGInstrumentLayer * layer); protected: @@ -485,7 +489,7 @@ public: FGTexturedLayer (const FGCroppedTexture &texture, int w = -1, int h = -1); virtual ~FGTexturedLayer (); - virtual void draw (); + virtual void draw (osg::State& state); virtual void setTexture (const FGCroppedTexture &texture) { _texture = texture; @@ -540,7 +544,7 @@ public: FGTextLayer (int w = -1, int h = -1); virtual ~FGTextLayer (); - virtual void draw (); + virtual void draw (osg::State& state); // Transfer pointer!! virtual void addChunk (Chunk * chunk); @@ -576,7 +580,7 @@ class FGSwitchLayer : public FGGroupLayer public: // Transfer pointers!! FGSwitchLayer (); - virtual void draw (); + virtual void draw (osg::State& state); }; diff --git a/src/FDM/flight.cxx b/src/FDM/flight.cxx index fd09210b7..08aa8fae7 100644 --- a/src/FDM/flight.cxx +++ b/src/FDM/flight.cxx @@ -800,29 +800,32 @@ bool FGInterface::prepare_ground_cache_m(double ref_time, const double pt[3], double rad) { - return ground_cache.prepare_ground_cache(ref_time, pt, rad); + return ground_cache.prepare_ground_cache(ref_time, SGVec3d(pt), rad); } bool FGInterface::prepare_ground_cache_ft(double ref_time, const double pt[3], double rad) { // Convert units and do the real work. - sgdVec3 pt_ft; - sgdScaleVec3( pt_ft, pt, SG_FEET_TO_METER ); + SGVec3d pt_ft = SG_FEET_TO_METER*SGVec3d(pt); return ground_cache.prepare_ground_cache(ref_time, pt_ft, rad*SG_FEET_TO_METER); } bool FGInterface::is_valid_m(double *ref_time, double pt[3], double *rad) { - return ground_cache.is_valid(ref_time, pt, rad); + SGVec3d _pt; + bool valid = ground_cache.is_valid(*ref_time, _pt, *rad); + sgdCopyVec3(pt, _pt.data()); + return valid; } bool FGInterface::is_valid_ft(double *ref_time, double pt[3], double *rad) { // Convert units and do the real work. - bool found_ground = ground_cache.is_valid(ref_time, pt, rad); - sgdScaleVec3(pt, SG_METER_TO_FEET); + SGVec3d _pt; + bool found_ground = ground_cache.is_valid(*ref_time, _pt, *rad); + sgdScaleVec3(pt, _pt.data(), SG_METER_TO_FEET); *rad *= SG_METER_TO_FEET; return found_ground; } @@ -831,7 +834,13 @@ double FGInterface::get_cat_m(double t, const double pt[3], double end[2][3], double vel[2][3]) { - return ground_cache.get_cat(t, pt, end, vel); + SGVec3d _end[2], _vel[2]; + double dist = ground_cache.get_cat(t, SGVec3d(pt), _end, _vel); + for (int k=0; k<2; ++k) { + sgdCopyVec3( end[k], _end[k].data() ); + sgdCopyVec3( vel[k], _vel[k].data() ); + } + return dist; } double @@ -839,12 +848,12 @@ FGInterface::get_cat_ft(double t, const double pt[3], double end[2][3], double vel[2][3]) { // Convert units and do the real work. - sgdVec3 pt_m; - sgdScaleVec3( pt_m, pt, SG_FEET_TO_METER ); - double dist = ground_cache.get_cat(t, pt_m, end, vel); + SGVec3d pt_m = SG_FEET_TO_METER*SGVec3d(pt); + SGVec3d _end[2], _vel[2]; + double dist = ground_cache.get_cat(t, pt_m, _end, _vel); for (int k=0; k<2; ++k) { - sgdScaleVec3( end[k], SG_METER_TO_FEET ); - sgdScaleVec3( vel[k], SG_METER_TO_FEET ); + sgdScaleVec3( end[k], _end[k].data(), SG_METER_TO_FEET ); + sgdScaleVec3( vel[k], _vel[k].data(), SG_METER_TO_FEET ); } return dist*SG_METER_TO_FEET; } @@ -857,8 +866,12 @@ FGInterface::get_agl_m(double t, const double pt[3], double *frictionFactor, double *agl) { const SGMaterial* material; - bool ret = ground_cache.get_agl(t, pt, 2.0, contact, normal, vel, type, - &material, agl); + SGVec3d _contact, _normal, _vel; + bool ret = ground_cache.get_agl(t, SGVec3d(pt), 2.0, _contact, _normal, + _vel, type, &material, agl); + sgdCopyVec3(contact, _contact.data()); + sgdCopyVec3(normal, _normal.data()); + sgdCopyVec3(vel, _vel.data()); if (material) { *loadCapacity = material->get_load_resistence(); *frictionFactor = material->get_friction_factor(); @@ -878,15 +891,16 @@ FGInterface::get_agl_ft(double t, const double pt[3], double *frictionFactor, double *agl) { // Convert units and do the real work. - sgdVec3 pt_m; - sgdScaleVec3( pt_m, pt, SG_FEET_TO_METER ); + SGVec3d pt_m = SG_FEET_TO_METER*SGVec3d(pt); const SGMaterial* material; - bool ret = ground_cache.get_agl(t, pt_m, 2.0, contact, normal, vel, + SGVec3d _contact, _normal, _vel; + bool ret = ground_cache.get_agl(t, pt_m, 2.0, _contact, _normal, _vel, type, &material, agl); // Convert units back ... - sgdScaleVec3( contact, SG_METER_TO_FEET ); - sgdScaleVec3( vel, SG_METER_TO_FEET ); + sgdScaleVec3( contact, _contact.data(), SG_METER_TO_FEET ); + sgdScaleVec3( vel, _vel.data(), SG_METER_TO_FEET ); + sgdCopyVec3( normal, _normal.data() ); *agl *= SG_METER_TO_FEET; // return material properties if available @@ -906,8 +920,13 @@ FGInterface::get_agl_m(double t, const double pt[3], double max_altoff, double contact[3], double normal[3], double vel[3], int *type, const SGMaterial** material, double *agl) { - return ground_cache.get_agl(t, pt, max_altoff, contact, normal, vel, type, - material, agl); + SGVec3d _contact, _normal, _vel; + bool found = ground_cache.get_agl(t, SGVec3d(pt), max_altoff, _contact, + _normal, _vel, type, material, agl); + sgdCopyVec3(contact, _contact.data()); + sgdCopyVec3(normal, _normal.data()); + sgdCopyVec3(vel, _vel.data()); + return found; } bool @@ -916,14 +935,15 @@ FGInterface::get_agl_ft(double t, const double pt[3], double max_altoff, int *type, const SGMaterial** material, double *agl) { // Convert units and do the real work. - sgdVec3 pt_m; - sgdScaleVec3( pt_m, pt, SG_FEET_TO_METER ); + SGVec3d pt_m = SG_FEET_TO_METER*SGVec3d(pt); + SGVec3d _contact, _normal, _vel; bool ret = ground_cache.get_agl(t, pt_m, SG_FEET_TO_METER * max_altoff, - contact, normal, vel, + _contact, _normal, _vel, type, material, agl); // Convert units back ... - sgdScaleVec3( contact, SG_METER_TO_FEET ); - sgdScaleVec3( vel, SG_METER_TO_FEET ); + sgdScaleVec3( contact, _contact.data(), SG_METER_TO_FEET ); + sgdScaleVec3( vel, _vel.data(), SG_METER_TO_FEET ); + sgdCopyVec3( normal, _normal.data() ); *agl *= SG_METER_TO_FEET; return ret; } @@ -932,37 +952,37 @@ FGInterface::get_agl_ft(double t, const double pt[3], double max_altoff, double FGInterface::get_groundlevel_m(double lat, double lon, double alt) { - sgdVec3 pos, cpos; // Compute the cartesian position of the given lat/lon/alt. - sgGeodToCart(lat, lon, alt, pos); + SGVec3d pos = SGVec3d::fromGeod(SGGeod::fromRadM(lon, lat, alt)); // FIXME: how to handle t - ref_time differences ??? + SGVec3d cpos; double ref_time, radius; // Prepare the ground cache for that position. - if (!is_valid_m(&ref_time, cpos, &radius)) { - bool ok = prepare_ground_cache_m(ref_time, pos, 10); + if (!is_valid_m(&ref_time, cpos.data(), &radius)) { + bool ok = prepare_ground_cache_m(ref_time, pos.data(), 10); /// This is most likely the case when the given altitude is /// too low, try with a new altitude of 10000m, that should be /// sufficient to find a ground level below everywhere on our planet if (!ok) { - sgGeodToCart(lat, lon, 10000, pos); + pos = SGVec3d::fromGeod(SGGeod::fromRadM(lon, lat, 10000)); /// If there is still no ground, return sea level radius - if (!prepare_ground_cache_m(ref_time, pos, 10)) + if (!prepare_ground_cache_m(ref_time, pos.data(), 10)) return 0; } - } else if (radius*radius <= sgdDistanceSquaredVec3(pos, cpos)) { + } else if (radius*radius <= distSqr(pos, cpos)) { /// We reuse the old radius value, but only if it is at least 10 Meters .. if (!(10 < radius)) // Well this strange compare is nan safe radius = 10; - bool ok = prepare_ground_cache_m(ref_time, pos, radius); + bool ok = prepare_ground_cache_m(ref_time, pos.data(), radius); /// This is most likely the case when the given altitude is /// too low, try with a new altitude of 10000m, that should be /// sufficient to find a ground level below everywhere on our planet if (!ok) { - sgGeodToCart(lat, lon, 10000, pos); + pos = SGVec3d::fromGeod(SGGeod::fromRadM(lon, lat, 10000)); /// If there is still no ground, return sea level radius - if (!prepare_ground_cache_m(ref_time, pos, radius)) + if (!prepare_ground_cache_m(ref_time, pos.data(), radius)) return 0; } } @@ -973,24 +993,28 @@ FGInterface::get_groundlevel_m(double lat, double lon, double alt) // the returns stem from the groundcache or from the coarse // computations below the groundcache. The contact point is still something // valid, the normals and the other returns just contain some defaults. - get_agl_m(ref_time, pos, 2.0, contact, normal, vel, &type, 0, &agl); - Point3D geodPos = sgCartToGeod(Point3D(contact[0], contact[1], contact[2])); - return geodPos.elev(); + get_agl_m(ref_time, pos.data(), 2.0, contact, normal, vel, &type, 0, &agl); + SGGeod geod = SGGeod::fromCart(SGVec3d(contact)); + return geod.getElevationM(); } bool FGInterface::caught_wire_m(double t, const double pt[4][3]) { - return ground_cache.caught_wire(t, pt); + SGVec3d pt_m[4]; + for (int i=0; i<4; ++i) + sgdCopyVec3(pt_m[i].data(), pt[i]); + + return ground_cache.caught_wire(t, pt_m); } bool FGInterface::caught_wire_ft(double t, const double pt[4][3]) { // Convert units and do the real work. - double pt_m[4][3]; + SGVec3d pt_m[4]; for (int i=0; i<4; ++i) - sgdScaleVec3(pt_m[i], pt[i], SG_FEET_TO_METER); + sgdScaleVec3(pt_m[i].data(), pt[i], SG_FEET_TO_METER); return ground_cache.caught_wire(t, pt_m); } @@ -998,17 +1022,24 @@ FGInterface::caught_wire_ft(double t, const double pt[4][3]) bool FGInterface::get_wire_ends_m(double t, double end[2][3], double vel[2][3]) { - return ground_cache.get_wire_ends(t, end, vel); + SGVec3d _end[2], _vel[2]; + bool ret = ground_cache.get_wire_ends(t, _end, _vel); + for (int k=0; k<2; ++k) { + sgdCopyVec3( end[k], _end[k].data() ); + sgdCopyVec3( vel[k], _vel[k].data() ); + } + return ret; } bool FGInterface::get_wire_ends_ft(double t, double end[2][3], double vel[2][3]) { // Convert units and do the real work. - bool ret = ground_cache.get_wire_ends(t, end, vel); + SGVec3d _end[2], _vel[2]; + bool ret = ground_cache.get_wire_ends(t, _end, _vel); for (int k=0; k<2; ++k) { - sgdScaleVec3( end[k], SG_METER_TO_FEET ); - sgdScaleVec3( vel[k], SG_METER_TO_FEET ); + sgdScaleVec3( end[k], _end[k].data(), SG_METER_TO_FEET ); + sgdScaleVec3( vel[k], _vel[k].data(), SG_METER_TO_FEET ); } return ret; } diff --git a/src/FDM/groundcache.cxx b/src/FDM/groundcache.cxx index dac41d515..2a9cde89c 100644 --- a/src/FDM/groundcache.cxx +++ b/src/FDM/groundcache.cxx @@ -27,6 +27,11 @@ #include #include +#include +#include +#include +#include +#include #include #include @@ -34,6 +39,7 @@ #include #include #include +#include #include
#include @@ -43,35 +49,10 @@ #include "flight.hxx" #include "groundcache.hxx" -// Specialized version of sgMultMat4 needed because of mixed matrix -// types -static inline void fgMultMat4(sgdMat4 dst, sgdMat4 m1, sgMat4 m2) { - for ( int j = 0 ; j < 4 ; j++ ) { - dst[0][j] = m2[0][0] * m1[0][j] + - m2[0][1] * m1[1][j] + - m2[0][2] * m1[2][j] + - m2[0][3] * m1[3][j] ; - - dst[1][j] = m2[1][0] * m1[0][j] + - m2[1][1] * m1[1][j] + - m2[1][2] * m1[2][j] + - m2[1][3] * m1[3][j] ; - - dst[2][j] = m2[2][0] * m1[0][j] + - m2[2][1] * m1[1][j] + - m2[2][2] * m1[2][j] + - m2[2][3] * m1[3][j] ; - - dst[3][j] = m2[3][0] * m1[0][j] + - m2[3][1] * m1[1][j] + - m2[3][2] * m1[2][j] + - m2[3][3] * m1[3][j] ; - } -} - -static inline bool fgdPointInTriangle( sgdVec3 point, sgdVec3 tri[3] ) +static inline bool +fgdPointInTriangle( const SGVec3d& point, const SGVec3d tri[3] ) { - sgdVec3 dif; + SGVec3d dif; // Some tolerance in meters we accept a point to be outside of the triangle // and still return that it is inside. @@ -172,51 +153,160 @@ static inline bool fgdPointInTriangle( sgdVec3 point, sgdVec3 tri[3] ) // line direction dir intersects the sphere sp. // Adapted from plib. static inline bool -fgdIsectSphereInfLine(const sgdSphere& sp, - const sgdVec3 pt_on_line, const sgdVec3 dir) +fgdIsectSphereInfLine(const SGVec3d& sphereCenter, double radius, + const SGVec3d& pt_on_line, const SGVec3d& dir) { - sgdVec3 r; - sgdSubVec3( r, sp.getCenter(), pt_on_line ) ; - - SGDfloat projectedDistance = sgdScalarProductVec3(r, dir); - - SGDfloat dist = sgdScalarProductVec3 ( r, r ) - - projectedDistance * projectedDistance; - - SGDfloat radius = sp.getRadius(); + SGVec3d r = sphereCenter - pt_on_line; + double projectedDistance = dot(r, dir); + double dist = dot(r, r) - projectedDistance * projectedDistance; return dist < radius*radius; } -FGGroundCache::FGGroundCache() -{ - sgdSetVec3(cache_center, 0.0, 0.0, 0.0); - ground_radius = 0.0; - cache_ref_time = 0.0; - wire_id = 0; - sgdSetVec3(reference_wgs84_point, 0.0, 0.0, 0.0); - reference_vehicle_radius = 0.0; - found_ground = false; -} +template +class SGExtendedTriangleFunctor : public osg::TriangleFunctor { +public: + // Ok, to be complete we should also implement the indexed variants + // For now this one appears to be enough ... + void drawArrays(GLenum mode, GLint first, GLsizei count) + { + if (_vertexArrayPtr==0 || count==0) return; -FGGroundCache::~FGGroundCache() -{ -} + const osg::Vec3* vlast; + const osg::Vec3* vptr; + switch(mode) { + case(GL_LINES): + vlast = &_vertexArrayPtr[first+count]; + for(vptr=&_vertexArrayPtr[first];vptroperator()(*(vptr),*(vptr+1),_treatVertexDataAsTemporary); + break; + case(GL_LINE_STRIP): + vlast = &_vertexArrayPtr[first+count-1]; + for(vptr=&_vertexArrayPtr[first];vptroperator()(*(vptr),*(vptr+1),_treatVertexDataAsTemporary); + break; + case(GL_LINE_LOOP): + vlast = &_vertexArrayPtr[first+count-1]; + for(vptr=&_vertexArrayPtr[first];vptroperator()(*(vptr),*(vptr+1),_treatVertexDataAsTemporary); + this->operator()(_vertexArrayPtr[first+count-1], + _vertexArrayPtr[first],_treatVertexDataAsTemporary); + break; + default: + osg::TriangleFunctor::drawArrays(mode, first, count); + break; + } + } +protected: + using osg::TriangleFunctor::_vertexArrayPtr; + using osg::TriangleFunctor::_treatVertexDataAsTemporary; +}; -FGGroundCache::GroundProperty -FGGroundCache::extractGroundProperty( ssgLeaf* l ) -{ - // FIXME: Do more ... - // Idea: have a get_globals() function which knows about that stuff. - // Or most probably read that from a configuration file, - // from property tree or whatever ... +class GroundCacheFillVisitor : public osg::NodeVisitor { +public: - // Get ground dependent data. - GroundProperty gp; - gp.wire_id = -1; - - FGAICarrierHardware *ud = - dynamic_cast(l->getUserData()); - if (ud) { + /// class to just redirect triangles to the GroundCacheFillVisitor + class GroundCacheFill { + public: + void setGroundCacheFillVisitor(GroundCacheFillVisitor* gcfv) + { mGroundCacheFillVisitor = gcfv; } + + void operator () (const osg::Vec3& v1, const osg::Vec3& v2, + const osg::Vec3& v3, bool) + { mGroundCacheFillVisitor->addTriangle(v1, v2, v3); } + + void operator () (const osg::Vec3& v1, const osg::Vec3& v2, bool) + { mGroundCacheFillVisitor->addLine(v1, v2); } + + private: + GroundCacheFillVisitor* mGroundCacheFillVisitor; + }; + + + GroundCacheFillVisitor(FGGroundCache* groundCache, + const SGVec3d& down, + const SGVec3d& cacheReference, + double cacheRadius, + double wireCacheRadius) : + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN), + mGroundCache(groundCache) + { + setTraversalMask(SG_NODEMASK_TERRAIN_BIT); + mDown = down; + sphIsec = true; + mBackfaceCulling = false; + mCacheReference = cacheReference; + mCacheRadius = cacheRadius; + mWireCacheRadius = wireCacheRadius; + + mTriangleFunctor.setGroundCacheFillVisitor(this); + + mGroundProperty.wire_id = -1; + mGroundProperty.vel = SGVec3d(0, 0, 0); + mGroundProperty.rot = SGVec3d(0, 0, 0); + mGroundProperty.pivot = SGVec3d(0, 0, 0); + } + + void updateCullMode(osg::StateSet* stateSet) + { + if (!stateSet) + return; + + osg::StateAttribute* stateAttribute; + stateAttribute = stateSet->getAttribute(osg::StateAttribute::CULLFACE); + if (!stateAttribute) + return; + osg::CullFace* cullFace = static_cast(stateAttribute); + mBackfaceCulling = cullFace->getMode() == osg::CullFace::BACK; + } + + bool enterBoundingSphere(const osg::BoundingSphere& bs) + { + if (!bs.valid()) + return false; + + SGVec3d cntr(osg::Vec3d(bs.center())*mLocalToGlobal); + double rc = bs.radius() + mCacheRadius; + // Ok, this node might intersect the cache. Visit it in depth. + double centerDist2 = distSqr(mCacheReference, cntr); + if (centerDist2 < rc*rc) { + sphIsec = true; + } else { + // Check if the down direction touches the bounding sphere of the node + // if so, do at least croase agl computations. + // Ther other thing is that we must check if we are in range of + // cats or wires + double rw = bs.radius() + mWireCacheRadius; + if (rw*rw < centerDist2 && + !fgdIsectSphereInfLine(cntr, bs.radius(), mCacheReference, mDown)) + return false; + sphIsec = false; + } + + return true; + } + + bool enterNode(osg::Node& node) + { + if (!enterBoundingSphere(node.getBound())) + return false; + + updateCullMode(node.getStateSet()); + + FGGroundCache::GroundProperty& gp = mGroundProperty; + // get some material information for use in the gear model + gp.material = globals->get_matlib()->findMaterial(&node); + if (gp.material) { + gp.type = gp.material->get_solid() ? FGInterface::Solid : FGInterface::Water; + return true; + } + osg::Referenced* base = node.getUserData(); + if (!base) + return true; + FGAICarrierHardware *ud = + dynamic_cast(base); + if (!ud) + return true; + switch (ud->type) { case FGAICarrierHardware::Wire: gp.type = FGInterface::Wire; @@ -229,137 +319,199 @@ FGGroundCache::extractGroundProperty( ssgLeaf* l ) gp.type = FGInterface::Solid; break; } - // Copy the velocity from the carrier class. ud->carrier->getVelocityWrtEarth( gp.vel, gp.rot, gp.pivot ); - } - - else { - // Initialize velocity field. - sgdSetVec3( gp.vel, 0.0, 0.0, 0.0 ); - sgdSetVec3( gp.rot, 0.0, 0.0, 0.0 ); - sgdSetVec3( gp.pivot, 0.0, 0.0, 0.0 ); - - // get some material information for use in the gear model - gp.material = globals->get_matlib()->findMaterial(l); - if (gp.material) - gp.type = gp.material->get_solid() ? FGInterface::Solid : FGInterface::Water; - } - return gp; -} - -void -FGGroundCache::putLineLeafIntoCache(const sgdSphere *wsp, const sgdMat4 xform, - ssgLeaf *l) -{ - GroundProperty gp = extractGroundProperty(l); - - // Lines must have special meanings. - // Wires and catapults are done with lines. - int nl = l->getNumLines(); - for (int i = 0; i < nl; ++i) { - sgdSphere sphere; - sphere.empty(); - sgdVec3 ends[2]; - short v[2]; - l->getLine(i, v, v+1 ); - for (int k=0; k<2; ++k) { - sgdSetVec3(ends[k], l->getVertex(v[k])); - sgdXformPnt3(ends[k], xform); - sphere.extend(ends[k]); - } - - if (wsp->intersects( &sphere )) { - if (gp.type == FGInterface::Wire) { - Wire wire; - sgdCopyVec3(wire.ends[0], ends[0]); - sgdCopyVec3(wire.ends[1], ends[1]); - sgdCopyVec3(wire.velocity, gp.vel); - sgdCopyVec3(wire.rotation, gp.rot); - sgdSubVec3(wire.rotation_pivot, gp.pivot, cache_center); - wire.wire_id = gp.wire_id; - - wires.push_back(wire); - } - if (gp.type == FGInterface::Catapult) { - Catapult cat; - sgdCopyVec3(cat.start, ends[0]); - sgdCopyVec3(cat.end, ends[1]); - sgdCopyVec3(cat.velocity, gp.vel); - sgdCopyVec3(cat.rotation, gp.rot); - sgdSubVec3(cat.rotation_pivot, gp.pivot, cache_center); - - catapults.push_back(cat); - } - } + return true; } -} -void -FGGroundCache::putSurfaceLeafIntoCache(const sgdSphere *sp, - const sgdMat4 xform, bool sphIsec, - sgdVec3 down, ssgLeaf *l) -{ - GroundProperty gp = extractGroundProperty(l); + void fillWith(osg::Drawable* drawable) + { + bool oldSphIsec = sphIsec; + if (!enterBoundingSphere(drawable->getBound())) + return; - int nt = l->getNumTriangles(); - for (int i = 0; i < nt; ++i) { - Triangle t; - t.sphere.empty(); - t.material = gp.material; - short v[3]; - l->getTriangle(i, &v[0], &v[1], &v[2]); - for (int k = 0; k < 3; ++k) { - sgdSetVec3(t.vertices[k], l->getVertex(v[k])); - sgdXformPnt3(t.vertices[k], xform); - t.sphere.extend(t.vertices[k]); + bool oldBackfaceCulling = mBackfaceCulling; + updateCullMode(drawable->getStateSet()); + + drawable->accept(mTriangleFunctor); + + mBackfaceCulling = oldBackfaceCulling; + sphIsec = oldSphIsec; + } + + virtual void apply(osg::Geode& geode) + { + bool oldBackfaceCulling = mBackfaceCulling; + bool oldSphIsec = sphIsec; + FGGroundCache::GroundProperty oldGp = mGroundProperty; + if (!enterNode(geode)) + return; + + for(unsigned i = 0; i < geode.getNumDrawables(); ++i) + fillWith(geode.getDrawable(i)); + sphIsec = oldSphIsec; + mGroundProperty = oldGp; + mBackfaceCulling = oldBackfaceCulling; + } + + virtual void apply(osg::Group& group) + { + bool oldBackfaceCulling = mBackfaceCulling; + bool oldSphIsec = sphIsec; + FGGroundCache::GroundProperty oldGp = mGroundProperty; + if (!enterNode(group)) + return; + traverse(group); + sphIsec = oldSphIsec; + mBackfaceCulling = oldBackfaceCulling; + mGroundProperty = oldGp; + } + + virtual void apply(osg::Transform& transform) + { + /// transform the caches center to local coords + osg::Matrix oldLocalToGlobal = mLocalToGlobal; + transform.computeLocalToWorldMatrix(mLocalToGlobal, this); + + // walk the children + apply((osg::Group&)transform); + + // Restore that one + mLocalToGlobal = oldLocalToGlobal; + } + + void addTriangle(const osg::Vec3& v1, const osg::Vec3& v2, + const osg::Vec3& v3) + { + FGGroundCache::Triangle t; + osg::Vec3d gv1 = osg::Vec3d(v1)*mLocalToGlobal; + osg::Vec3d gv2 = osg::Vec3d(v2)*mLocalToGlobal; + osg::Vec3d gv3 = osg::Vec3d(v3)*mLocalToGlobal; + for (unsigned i = 0; i < 3; ++i) { + t.vertices[0][i] = gv1[i]; + t.vertices[1][i] = gv2[i]; + t.vertices[2][i] = gv3[i]; } + // FIXME: can do better ... + t.boundCenter = (1.0/3)*(t.vertices[0] + t.vertices[1] + t.vertices[2]); + t.boundRadius = std::max(length(t.vertices[0] - t.boundCenter), + length(t.vertices[1] - t.boundCenter)); + t.boundRadius = std::max(t.boundRadius, + length(t.vertices[2] - t.boundCenter)); - sgdMakePlane(t.plane, t.vertices[0], t.vertices[1], t.vertices[2]); - SGDfloat dot = sgdScalarProductVec3(down, t.plane); - if (dot > 0) { - if (!l->getCullFace()) { + sgdMakePlane(t.plane.sg(), t.vertices[0].sg(), t.vertices[1].sg(), + t.vertices[2].sg()); + double d = sgdScalarProductVec3(mDown.sg(), t.plane.sg()); + if (d > 0) { + if (mBackfaceCulling) { // Surface points downwards, ignore for altitude computations. - continue; + return; } else - sgdScaleVec4( t.plane, -1 ); + t.plane = -t.plane; } // Check if the sphere around the vehicle intersects the sphere // around that triangle. If so, put that triangle into the cache. - if (sphIsec && sp->intersects(&t.sphere)) { - sgdCopyVec3(t.velocity, gp.vel); - sgdCopyVec3(t.rotation, gp.rot); - sgdSubVec3(t.rotation_pivot, gp.pivot, cache_center); - t.type = gp.type; - triangles.push_back(t); + if (sphIsec && + distSqr(t.boundCenter, mCacheReference) + < (t.boundRadius + mCacheRadius)*(t.boundRadius + mCacheRadius) ) { + t.velocity = mGroundProperty.vel; + t.rotation = mGroundProperty.rot; + t.rotation_pivot = mGroundProperty.pivot - mGroundCache->cache_center; + t.type = mGroundProperty.type; + mGroundCache->triangles.push_back(t); } // In case the cache is empty, we still provide agl computations. // But then we use the old way of having a fixed elevation value for // the whole lifetime of this cache. - if ( fgdIsectSphereInfLine(t.sphere, sp->getCenter(), down) ) { - sgdVec3 tmp; - sgdSetVec3(tmp, sp->center[0], sp->center[1], sp->center[2]); - sgdVec3 isectpoint; - if ( sgdIsectInfLinePlane( isectpoint, tmp, down, t.plane ) && + if ( fgdIsectSphereInfLine(t.boundCenter, t.boundRadius, + mCacheReference, mDown) ) { + SGVec3d isectpoint; + if ( sgdIsectInfLinePlane( isectpoint.sg(), mCacheReference.sg(), + mDown.sg(), t.plane.sg() ) && fgdPointInTriangle( isectpoint, t.vertices ) ) { - // Compute the offset to the ground cache midpoint - sgdVec3 off; - sgdSubVec3(off, isectpoint, tmp); // Only accept the altitude if the intersection point is below the // ground cache midpoint - if (0 < sgdScalarProductVec3( off, down )) { - found_ground = true; - sgdAddVec3(isectpoint, cache_center); - double this_radius = sgdLengthVec3(isectpoint); - if (ground_radius < this_radius) - ground_radius = this_radius; + if (0 < dot(isectpoint - mCacheReference, mDown)) { + mGroundCache->found_ground = true; + isectpoint += mGroundCache->cache_center; + double this_radius = length(isectpoint); + if (mGroundCache->ground_radius < this_radius) + mGroundCache->ground_radius = this_radius; } } } } + + void addLine(const osg::Vec3& v1, const osg::Vec3& v2) + { + SGVec3d gv1 = SGVec3d(osg::Vec3d(v1)*mLocalToGlobal); + SGVec3d gv2 = SGVec3d(osg::Vec3d(v2)*mLocalToGlobal); + + SGVec3d boundCenter = 0.5*(gv1 + gv2); + double boundRadius = length(gv1 - boundCenter); + + if (distSqr(boundCenter, mCacheReference) + < (boundRadius + mWireCacheRadius)*(boundRadius + mWireCacheRadius) ) { + if (mGroundProperty.type == FGInterface::Wire) { + FGGroundCache::Wire wire; + wire.ends[0] = gv1; + wire.ends[1] = gv2; + wire.velocity = mGroundProperty.vel; + wire.rotation = mGroundProperty.rot; + wire.rotation_pivot = mGroundProperty.pivot - mGroundCache->cache_center; + wire.wire_id = mGroundProperty.wire_id; + + mGroundCache->wires.push_back(wire); + } + if (mGroundProperty.type == FGInterface::Catapult) { + FGGroundCache::Catapult cat; + // 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 + if (v1[0] < v2[0]) { + cat.start = gv1; + cat.end = gv2; + } else { + cat.start = gv2; + cat.end = gv1; + } + cat.velocity = mGroundProperty.vel; + cat.rotation = mGroundProperty.rot; + cat.rotation_pivot = mGroundProperty.pivot - mGroundCache->cache_center; + + mGroundCache->catapults.push_back(cat); + } + } + } + + SGExtendedTriangleFunctor mTriangleFunctor; + FGGroundCache* mGroundCache; + SGVec3d mCacheReference; + double mCacheRadius; + double mWireCacheRadius; + osg::Matrix mLocalToGlobal; + SGVec3d mDown; + bool sphIsec; + bool mBackfaceCulling; + FGGroundCache::GroundProperty mGroundProperty; +}; + +FGGroundCache::FGGroundCache() +{ + cache_center = SGVec3d(0, 0, 0); + ground_radius = 0.0; + cache_ref_time = 0.0; + wire_id = 0; + reference_wgs84_point = SGVec3d(0, 0, 0); + reference_vehicle_radius = 0.0; + found_ground = false; +} + +FGGroundCache::~FGGroundCache() +{ } inline void @@ -367,104 +519,27 @@ FGGroundCache::velocityTransformTriangle(double dt, FGGroundCache::Triangle& dst, const FGGroundCache::Triangle& src) { - sgdCopyVec3(dst.vertices[0], src.vertices[0]); - sgdCopyVec3(dst.vertices[1], src.vertices[1]); - sgdCopyVec3(dst.vertices[2], src.vertices[2]); + dst = src; - sgdCopyVec4(dst.plane, src.plane); + if (fabs(dt*dot(src.velocity, src.velocity)) < SGLimitsd::epsilon()) + return; + + for (int i = 0; i < 3; ++i) { + SGVec3d pivotoff = src.vertices[i] - src.rotation_pivot; + dst.vertices[i] += dt*(src.velocity + cross(src.rotation, pivotoff)); + } - sgdCopyVec3(dst.sphere.center, src.sphere.center); - dst.sphere.radius = src.sphere.radius; - - sgdCopyVec3(dst.velocity, src.velocity); - sgdCopyVec3(dst.rotation, src.rotation); - sgdCopyVec3(dst.rotation_pivot, src.rotation_pivot); - - dst.type = src.type; - dst.material = src.material; - - if (dt*sgdLengthSquaredVec3(src.velocity) != 0) { - sgdVec3 pivotoff, vel; - for (int i = 0; i < 3; ++i) { - sgdSubVec3(pivotoff, src.vertices[i], src.rotation_pivot); - sgdVectorProductVec3(vel, src.rotation, pivotoff); - sgdAddVec3(vel, src.velocity); - sgdAddScaledVec3(dst.vertices[i], vel, dt); - } - - // Transform the plane equation - sgdSubVec3(pivotoff, dst.plane, src.rotation_pivot); - sgdVectorProductVec3(vel, src.rotation, pivotoff); - sgdAddVec3(vel, src.velocity); - dst.plane[3] += dt*sgdScalarProductVec3(dst.plane, vel); - - sgdAddScaledVec3(dst.sphere.center, src.velocity, dt); - } -} - -void -FGGroundCache::cache_fill(ssgBranch *branch, sgdMat4 xform, - sgdSphere* sp, sgdVec3 down, sgdSphere* wsp) -{ - // Travel through all kids. - ssgEntity *e; - for ( e = branch->getKid(0); e != NULL ; e = branch->getNextKid() ) { - if ( !(e->getTraversalMask() & SSGTRAV_HOT) ) - continue; - if ( e->getBSphere()->isEmpty() ) - continue; - - // We need to check further if either the sphere around the branch - // intersects the sphere around the aircraft or the line downwards from - // the aircraft intersects the branchs sphere. - sgdSphere esphere; - sgdSetVec3(esphere.center, e->getBSphere()->center); - esphere.radius = e->getBSphere()->radius; - esphere.orthoXform(xform); - bool wspIsec = wsp->intersects(&esphere); - bool downIsec = fgdIsectSphereInfLine(esphere, sp->getCenter(), down); - if (!wspIsec && !downIsec) - continue; - - // For branches collect up the transforms to reach that branch and - // call cache_fill recursively. - if ( e->isAKindOf( ssgTypeBranch() ) ) { - ssgBranch *b = (ssgBranch *)e; - if ( b->isAKindOf( ssgTypeTransform() ) ) { - // Collect up the transforms required to reach that part of - // the branch. - sgMat4 xform2; - sgMakeIdentMat4( xform2 ); - ssgTransform *t = (ssgTransform*)b; - t->getTransform( xform2 ); - sgdMat4 xform3; - fgMultMat4(xform3, xform, xform2); - cache_fill( b, xform3, sp, down, wsp ); - } else - cache_fill( b, xform, sp, down, wsp ); - } - - // For leafs, check each triangle for intersection. - // This will minimize the number of vertices/triangles in the cache. - else if (e->isAKindOf(ssgTypeLeaf())) { - // Since we reach that leaf if we have an intersection with the - // most probably bigger wire/catapult cache sphere, we need to check - // that here, if the smaller cache for the surface has a chance for hits. - // Also, if the spheres do not intersect compute a coarse agl value - // by following the line downwards originating at the aircraft. - bool spIsec = sp->intersects(&esphere); - putSurfaceLeafIntoCache(sp, xform, spIsec, down, (ssgLeaf *)e); - - // If we are here, we need to put all special hardware here into - // the cache. - if (wspIsec) - putLineLeafIntoCache(wsp, xform, (ssgLeaf *)e); - } - } + // Transform the plane equation + SGVec3d pivotoff, vel; + sgdSubVec3(pivotoff.sg(), dst.plane.sg(), src.rotation_pivot.sg()); + vel = src.velocity + cross(src.rotation, pivotoff); + dst.plane[3] += dt*sgdScalarProductVec3(dst.plane.sg(), vel.sg()); + + dst.boundCenter += dt*src.velocity; } bool -FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3], +FGGroundCache::prepare_ground_cache(double ref_time, const SGVec3d& pt, double rad) { // Empty cache. @@ -475,14 +550,18 @@ FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3], wires.resize(0); // Store the parameters we used to build up that cache. - sgdCopyVec3(reference_wgs84_point, pt); + reference_wgs84_point = pt; reference_vehicle_radius = rad; // Store the time reference used to compute movements of moving triangles. cache_ref_time = ref_time; + // Get a normalized down vector valid for the whole cache + SGQuatd hlToEc = SGQuatd::fromLonLat(SGGeod::fromCart(pt)); + down = hlToEc.rotate(SGVec3d(0, 0, 1)); + // Decide where we put the scenery center. SGVec3d old_cntr = globals->get_scenery()->get_center(); - SGVec3d cntr(pt[0], pt[1], pt[2]); + SGVec3d cntr(pt); // Only move the cache center if it is unacceptable far away. if (40*40 < distSqr(old_cntr, cntr)) globals->get_scenery()->set_center(cntr); @@ -490,43 +569,21 @@ FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3], cntr = old_cntr; // The center of the cache. - sgdSetVec3(cache_center, cntr[0], cntr[1], cntr[2]); + cache_center = cntr; - sgdVec3 ptoff; - sgdSubVec3(ptoff, pt, cache_center); // Prepare sphere around the aircraft. - sgdSphere acSphere; - acSphere.setRadius(rad); - acSphere.setCenter(ptoff); + SGVec3d ptoff = pt - cache_center; + double cacheRadius = rad; // Prepare bigger sphere around the aircraft. // This one is required for reliably finding wires we have caught but // have already left the hopefully smaller sphere for the ground reactions. const double max_wire_dist = 300.0; - sgdSphere wireSphere; - wireSphere.setRadius(max_wire_dist < rad ? rad : max_wire_dist); - wireSphere.setCenter(ptoff); - - // Down vector. Is used for croase agl computations when we are far enough - // from ground that we have an empty cache. - sgdVec3 down; - sgdSetVec3(down, -pt[0], -pt[1], -pt[2]); - sgdNormalizeVec3(down); - - // We collapse all transforms we need to reach a particular leaf. - // The leafs itself will be then transformed later. - // So our cache is just flat. - // For leafs which are moving (carriers surface, etc ...) - // we will later store a speed in the GroundType class. We can then apply - // some translations to that nodes according to the time which has passed - // compared to that snapshot. - sgdMat4 xform; - sgdMakeIdentMat4( xform ); - + double wireCacheRadius = max_wire_dist < rad ? rad : max_wire_dist; // Walk the scene graph and extract solid ground triangles and carrier data. - ssgBranch *terrain = globals->get_scenery()->get_scene_graph(); - cache_fill(terrain, xform, &acSphere, down, &wireSphere); + GroundCacheFillVisitor gcfv(this, down, ptoff, cacheRadius, wireCacheRadius); + globals->get_scenery()->get_scene_graph()->accept(gcfv); // some stats SG_LOG(SG_FLIGHT,SG_DEBUG, "prepare_ground_cache(): ac radius = " << rad @@ -549,17 +606,17 @@ FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3], } bool -FGGroundCache::is_valid(double *ref_time, double pt[3], double *rad) +FGGroundCache::is_valid(double& ref_time, SGVec3d& pt, double& rad) { - sgdCopyVec3(pt, reference_wgs84_point); - *rad = reference_vehicle_radius; - *ref_time = cache_ref_time; + pt = reference_wgs84_point; + rad = reference_vehicle_radius; + ref_time = cache_ref_time; return found_ground; } double -FGGroundCache::get_cat(double t, const double dpt[3], - double end[2][3], double vel[2][3]) +FGGroundCache::get_cat(double t, const SGVec3d& dpt, + SGVec3d end[2], SGVec3d vel[2]) { // start with a distance of 1e10 meters... double dist = 1e10; @@ -569,35 +626,30 @@ FGGroundCache::get_cat(double t, const double dpt[3], size_t sz = catapults.size(); for (size_t i = 0; i < sz; ++i) { - sgdVec3 pivotoff, rvel[2]; + SGVec3d pivotoff, rvel[2]; + pivotoff = catapults[i].start - catapults[i].rotation_pivot; + rvel[0] = catapults[i].velocity + cross(catapults[i].rotation, pivotoff); + pivotoff = catapults[i].end - catapults[i].rotation_pivot; + rvel[1] = catapults[i].velocity + cross(catapults[i].rotation, pivotoff); + + SGVec3d thisEnd[2]; + thisEnd[0] = cache_center + catapults[i].start + t*rvel[0]; + thisEnd[1] = cache_center + catapults[i].end + t*rvel[1]; + sgdLineSegment3 ls; - sgdCopyVec3(ls.a, catapults[i].start); - sgdCopyVec3(ls.b, catapults[i].end); + sgdCopyVec3(ls.a, thisEnd[0].sg()); + sgdCopyVec3(ls.b, thisEnd[1].sg()); + double this_dist = sgdDistSquaredToLineSegmentVec3( ls, dpt.sg() ); - sgdSubVec3(pivotoff, ls.a, catapults[i].rotation_pivot); - sgdVectorProductVec3(rvel[0], catapults[i].rotation, pivotoff); - sgdAddVec3(rvel[0], catapults[i].velocity); - sgdSubVec3(pivotoff, ls.b, catapults[i].rotation_pivot); - sgdVectorProductVec3(rvel[1], catapults[i].rotation, pivotoff); - sgdAddVec3(rvel[1], catapults[i].velocity); - - sgdAddVec3(ls.a, cache_center); - sgdAddVec3(ls.b, cache_center); - - sgdAddScaledVec3(ls.a, rvel[0], t); - sgdAddScaledVec3(ls.b, rvel[1], t); - - double this_dist = sgdDistSquaredToLineSegmentVec3( ls, dpt ); if (this_dist < dist) { SG_LOG(SG_FLIGHT,SG_INFO, "Found catapult " << this_dist << " meters away"); dist = this_dist; - // The carrier code takes care of that ordering. - sgdCopyVec3( end[0], ls.a ); - sgdCopyVec3( end[1], ls.b ); - sgdCopyVec3( vel[0], rvel[0] ); - sgdCopyVec3( vel[1], rvel[1] ); + end[0] = thisEnd[0]; + end[1] = thisEnd[1]; + vel[0] = rvel[0]; + vel[1] = rvel[1]; } } @@ -606,8 +658,8 @@ FGGroundCache::get_cat(double t, const double dpt[3], } bool -FGGroundCache::get_agl(double t, const double dpt[3], double max_altoff, - double contact[3], double normal[3], double vel[3], +FGGroundCache::get_agl(double t, const SGVec3d& dpt, double max_altoff, + SGVec3d& contact, SGVec3d& normal, SGVec3d& vel, int *type, const SGMaterial** material, double *agl) { bool ret = false; @@ -616,21 +668,15 @@ FGGroundCache::get_agl(double t, const double dpt[3], double max_altoff, // *agl = 0.0; if (material) *material = 0; - sgdSetVec3( vel, 0.0, 0.0, 0.0 ); - sgdSetVec3( contact, 0.0, 0.0, 0.0 ); - sgdSetVec3( normal, 0.0, 0.0, 0.0 ); + vel = SGVec3d(0, 0, 0); + contact = SGVec3d(0, 0, 0); + normal = SGVec3d(0, 0, 0); // Time difference to th reference time. t -= cache_ref_time; // The double valued point we start to search for intersection. - sgdVec3 pt; - sgdSubVec3( pt, dpt, cache_center ); - - // The search direction - sgdVec3 dir; - sgdSetVec3( dir, -dpt[0], -dpt[1], -dpt[2] ); - sgdNormaliseVec3( dir ); + SGVec3d pt = dpt - cache_center; // Initialize to something sensible double current_radius = 0.0; @@ -639,39 +685,34 @@ FGGroundCache::get_agl(double t, const double dpt[3], double max_altoff, for (size_t i = 0; i < sz; ++i) { Triangle triangle; velocityTransformTriangle(t, triangle, triangles[i]); - if (!fgdIsectSphereInfLine(triangle.sphere, pt, dir)) + if (!fgdIsectSphereInfLine(triangle.boundCenter, triangle.boundRadius, pt, down)) continue; // Check for intersection. - sgdVec3 isecpoint; - if ( sgdIsectInfLinePlane( isecpoint, pt, dir, triangle.plane ) && - sgdPointInTriangle( isecpoint, triangle.vertices ) ) { + SGVec3d isecpoint; + if ( sgdIsectInfLinePlane( isecpoint.sg(), pt.sg(), down.sg(), triangle.plane.sg() ) && + fgdPointInTriangle( isecpoint, triangle.vertices ) ) { // Compute the vector from pt to the intersection point ... - sgdVec3 off; - sgdSubVec3(off, isecpoint, pt); + SGVec3d off = isecpoint - pt; // ... and check if it is too high or not - if (-max_altoff < sgdScalarProductVec3( off, dir )) { + if (-max_altoff < dot(off, down)) { // Transform to the wgs system - sgdAddVec3( isecpoint, cache_center ); + isecpoint += cache_center; // compute the radius, good enough approximation to take the geocentric radius - SGDfloat radius = sgdLengthSquaredVec3(isecpoint); + double radius = dot(isecpoint, isecpoint); if (current_radius < radius) { current_radius = radius; ret = true; // Save the new potential intersection point. - sgdCopyVec3( contact, isecpoint ); + contact = isecpoint; // The first three values in the vector are the plane normal. - sgdCopyVec3( normal, triangle.plane ); + sgdCopyVec3( normal.sg(), triangle.plane.sg() ); // The velocity wrt earth. - sgdVec3 pivotoff; - sgdSubVec3(pivotoff, pt, triangle.rotation_pivot); - sgdVectorProductVec3(vel, triangle.rotation, pivotoff); - sgdAddVec3(vel, triangle.velocity); + SGVec3d pivotoff = pt - triangle.rotation_pivot; + vel = triangle.velocity + cross(triangle.rotation, pivotoff); // Save the ground type. *type = triangle.type; - sgdVec3 dstToContact; - sgdSubVec3(dstToContact, contact, dpt); - *agl = sgdScalarProductVec3(dir, dstToContact); + *agl = dot(down, contact - dpt); if (material) *material = triangle.material; } @@ -685,24 +726,21 @@ FGGroundCache::get_agl(double t, const double dpt[3], double max_altoff, // 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. - double r = sgdLengthVec3( dpt ); - sgdCopyVec3( contact, dpt ); - sgdScaleVec3( contact, ground_radius/r ); - sgdCopyVec3( normal, dpt ); - sgdNormaliseVec3( normal ); - sgdSetVec3( vel, 0.0, 0.0, 0.0 ); + double r = length(dpt); + contact = dpt; + contact *= ground_radius/r; + normal = -down; + vel = SGVec3d(0, 0, 0); // The altitude is the distance of the requested point from the // contact point. - sgdVec3 dstToContact; - sgdSubVec3(dstToContact, contact, dpt); - *agl = sgdScalarProductVec3(dir, dstToContact); + *agl = dot(down, contact - dpt); *type = FGInterface::Unknown; return ret; } -bool FGGroundCache::caught_wire(double t, const double pt[4][3]) +bool FGGroundCache::caught_wire(double t, const SGVec3d pt[4]) { size_t sz = wires.size(); if (sz == 0) @@ -713,36 +751,34 @@ bool FGGroundCache::caught_wire(double t, const double pt[4][3]) // Build the two triangles spanning the area where the hook has moved // during the past step. - sgdVec4 plane[2]; - sgdVec3 tri[2][3]; - sgdMakePlane( plane[0], pt[0], pt[1], pt[2] ); - sgdCopyVec3( tri[0][0], pt[0] ); - sgdCopyVec3( tri[0][1], pt[1] ); - sgdCopyVec3( tri[0][2], pt[2] ); - sgdMakePlane( plane[1], pt[0], pt[2], pt[3] ); - sgdCopyVec3( tri[1][0], pt[0] ); - sgdCopyVec3( tri[1][1], pt[2] ); - sgdCopyVec3( tri[1][2], pt[3] ); + SGVec4d plane[2]; + SGVec3d tri[2][3]; + sgdMakePlane( plane[0].sg(), pt[0].sg(), pt[1].sg(), pt[2].sg() ); + tri[0][0] = pt[0]; + tri[0][1] = pt[1]; + tri[0][2] = pt[2]; + sgdMakePlane( plane[1].sg(), pt[0].sg(), pt[2].sg(), pt[3].sg() ); + tri[1][0] = pt[0]; + tri[1][1] = pt[2]; + tri[1][2] = pt[3]; // Intersect the wire lines with each of these triangles. // You have caught a wire if they intersect. for (size_t i = 0; i < sz; ++i) { - sgdVec3 le[2]; + SGVec3d le[2]; for (int k = 0; k < 2; ++k) { - sgdVec3 pivotoff, vel; - sgdCopyVec3(le[k], wires[i].ends[k]); - sgdSubVec3(pivotoff, le[k], wires[i].rotation_pivot); - sgdVectorProductVec3(vel, wires[i].rotation, pivotoff); - sgdAddVec3(vel, wires[i].velocity); - sgdAddScaledVec3(le[k], vel, t); - sgdAddVec3(le[k], cache_center); + le[k] = wires[i].ends[k]; + SGVec3d pivotoff = le[k] - wires[i].rotation_pivot; + SGVec3d vel = wires[i].velocity + cross(wires[i].rotation, pivotoff); + le[k] += t*vel + cache_center; } for (int k=0; k<2; ++k) { - sgdVec3 isecpoint; - double isecval = sgdIsectLinesegPlane(isecpoint, le[0], le[1], plane[k]); + SGVec3d isecpoint; + double isecval = sgdIsectLinesegPlane(isecpoint.sg(), le[0].sg(), + le[1].sg(), plane[k].sg()); if ( 0.0 <= isecval && isecval <= 1.0 && - sgdPointInTriangle( isecpoint, tri[k] ) ) { + fgdPointInTriangle( isecpoint, tri[k] ) ) { SG_LOG(SG_FLIGHT,SG_INFO, "Caught wire"); // Store the wire id. wire_id = wires[i].wire_id; @@ -754,7 +790,7 @@ bool FGGroundCache::caught_wire(double t, const double pt[4][3]) return false; } -bool FGGroundCache::get_wire_ends(double t, double end[2][3], double vel[2][3]) +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_id < 0) @@ -768,13 +804,9 @@ bool FGGroundCache::get_wire_ends(double t, double end[2][3], double vel[2][3]) for (size_t i = 0; i < sz; ++i) { if (wires[i].wire_id == wire_id) { for (size_t k = 0; k < 2; ++k) { - sgdVec3 pivotoff; - sgdCopyVec3(end[k], wires[i].ends[k]); - sgdSubVec3(pivotoff, end[k], wires[i].rotation_pivot); - sgdVectorProductVec3(vel[k], wires[i].rotation, pivotoff); - sgdAddVec3(vel[k], wires[i].velocity); - sgdAddScaledVec3(end[k], vel[k], t); - sgdAddVec3(end[k], cache_center); + SGVec3d pivotoff = end[k] - wires[i].rotation_pivot; + vel[k] = wires[i].velocity + cross(wires[i].rotation, pivotoff); + end[k] = cache_center + wires[i].ends[k] + t*vel[k]; } return true; } diff --git a/src/FDM/groundcache.hxx b/src/FDM/groundcache.hxx index e91534a63..754d53921 100644 --- a/src/FDM/groundcache.hxx +++ b/src/FDM/groundcache.hxx @@ -23,12 +23,12 @@ #ifndef _GROUNDCACHE_HXX #define _GROUNDCACHE_HXX -#include -#include #include #include +#include class SGMaterial; +class GroundCacheFillVisitor; class FGGroundCache { public: @@ -42,19 +42,18 @@ public: // Prepare the ground cache for the wgs84 position pt_*. // That is take all vertices in the ball with radius rad around the // position given by the pt_* and store them in a local scene graph. - bool prepare_ground_cache(double ref_time, const double pt[3], + bool prepare_ground_cache(double ref_time, const SGVec3d& pt, double rad); // Returns true if the cache is valid. // Also the reference time, point and radius values where the cache // is valid for are returned. - bool is_valid(double *ref_time, double pt[3], double *rad); - + bool is_valid(double& ref_time, SGVec3d& pt, double& rad); // Return the nearest catapult to the given point // pt in wgs84 coordinates. - double get_cat(double t, const double pt[3], - double end[2][3], double vel[2][3]); + double get_cat(double t, const SGVec3d& pt, + SGVec3d end[2], SGVec3d vel[2]); // Return the altitude above ground below the wgs84 point pt @@ -63,8 +62,8 @@ public: // this kind kind of ground can carry, the friction factor between // 0 and 1 which can be used to model lower friction with wet runways // and finally the altitude above ground. - bool get_agl(double t, const double pt[3], double max_altoff, - double contact[3], double normal[3], double vel[3], + bool get_agl(double t, const SGVec3d& pt, double max_altoff, + SGVec3d& contact, SGVec3d& normal, SGVec3d& vel, int *type, const SGMaterial** material, double *agl); // Return 1 if the hook intersects with a wire. @@ -72,51 +71,54 @@ public: // intersects with the line representing the wire. // If the wire is caught, the cache will trace this wires endpoints until // the FDM calls release_wire(). - bool caught_wire(double t, const double pt[4][3]); + bool caught_wire(double t, const SGVec3d pt[4]); // Return the location and speed of the wire endpoints. - bool get_wire_ends(double t, double end[2][3], double vel[2][3]); + bool get_wire_ends(double t, SGVec3d end[2], SGVec3d vel[2]); // Tell the cache code that it does no longer need to care for // the wire end position. void release_wire(void); private: + friend class GroundCacheFillVisitor; + struct Triangle { Triangle() : material(0) {} // The edge vertices. - sgdVec3 vertices[3]; + SGVec3d vertices[3]; // The surface normal. - sgdVec4 plane; + SGVec4d plane; // The bounding shpere. - sgdSphere sphere; + SGVec3d boundCenter; + double boundRadius; // The linear and angular velocity. - sgdVec3 velocity; - sgdVec3 rotation; - sgdVec3 rotation_pivot; + SGVec3d velocity; + SGVec3d rotation; + SGVec3d rotation_pivot; // Ground type int type; // the simgear material reference, contains friction coeficients ... const SGMaterial* material; }; struct Catapult { - sgdVec3 start; - sgdVec3 end; - sgdVec3 velocity; - sgdVec3 rotation; - sgdVec3 rotation_pivot; + SGVec3d start; + SGVec3d end; + SGVec3d velocity; + SGVec3d rotation; + SGVec3d rotation_pivot; }; struct Wire { - sgdVec3 ends[2]; - sgdVec3 velocity; - sgdVec3 rotation; - sgdVec3 rotation_pivot; + SGVec3d ends[2]; + SGVec3d velocity; + SGVec3d rotation; + SGVec3d rotation_pivot; int wire_id; }; // The center of the cache. - sgdVec3 cache_center; + SGVec3d cache_center; // Approximate ground radius. // In case the aircraft is too high above ground. double ground_radius; @@ -133,37 +135,23 @@ private: // The point and radius where the cache is built around. // That are the arguments that were given to prepare_ground_cache. - sgdVec3 reference_wgs84_point; + SGVec3d reference_wgs84_point; double reference_vehicle_radius; + SGVec3d down; bool found_ground; - // Fills the environment cache with everything inside the sphere sp. - void cache_fill(ssgBranch *branch, sgdMat4 xform, - sgdSphere* sp, sgdVec3 down, sgdSphere* wsp); - - // compute the ground property of this leaf. - void putSurfaceLeafIntoCache(const sgdSphere *sp, const sgdMat4 xform, - bool sphIsec, sgdVec3 down, ssgLeaf *l); - - void putLineLeafIntoCache(const sgdSphere *wsp, const sgdMat4 xform, - ssgLeaf *l); - // Helper class to hold some properties of the ground triangle. struct GroundProperty { GroundProperty() : type(0), material(0) {} int type; int wire_id; - sgdVec3 vel; - sgdVec3 rot; - sgdVec3 pivot; + SGVec3d vel; + SGVec3d rot; + SGVec3d pivot; const SGMaterial* material; }; - // compute the ground property of this leaf. - static GroundProperty extractGroundProperty( ssgLeaf* leaf ); - - static void velocityTransformTriangle(double dt, Triangle& dst, const Triangle& src); }; diff --git a/src/GUI/gui_funcs.cxx b/src/GUI/gui_funcs.cxx index 8765aa017..03b042aae 100644 --- a/src/GUI/gui_funcs.cxx +++ b/src/GUI/gui_funcs.cxx @@ -60,8 +60,6 @@ # endif #endif -#include - #include #include #include @@ -283,7 +281,7 @@ void fgHiResDump() } FGRenderer *renderer = globals->get_renderer(); - renderer->init(); +// renderer->init(); renderer->resize( fgGetInt("/sim/startup/xsize"), fgGetInt("/sim/startup/ysize") ); @@ -325,11 +323,12 @@ void fgHiResDump() trTileBuffer(tr, GL_RGB, GL_UNSIGNED_BYTE, tile); trImageSize(tr, imageWidth, imageHeight); trRowOrder(tr, TR_TOP_TO_BOTTOM); - sgFrustum *frustum = ssgGetFrustum(); - trFrustum(tr, - frustum->getLeft(), frustum->getRight(), - frustum->getBot(), frustum->getTop(), - frustum->getNear(), frustum->getFar()); + // OSGFIXME +// sgFrustum *frustum = ssgGetFrustum(); +// trFrustum(tr, +// frustum->getLeft(), frustum->getRight(), +// frustum->getBot(), frustum->getTop(), +// frustum->getNear(), frustum->getFar()); /* Prepare ppm output file */ while (count < 1000) { @@ -380,13 +379,15 @@ void fgHiResDump() int curRow = trGet(tr, TR_CURRENT_ROW); renderer->update( false ); - if ( do_hud ) - fgUpdateHUD( curColumn*hud_col_step, curRow*hud_row_step, - (curColumn+1)*hud_col_step, (curRow+1)*hud_row_step ); - if (do_panel) - globals->get_current_panel()->update( - curColumn*panel_col_step, panel_col_step, - curRow*panel_row_step, panel_row_step ); + // OSGFIXME +// if ( do_hud ) +// fgUpdateHUD( curColumn*hud_col_step, curRow*hud_row_step, +// (curColumn+1)*hud_col_step, (curRow+1)*hud_row_step ); + // OSGFIXME +// if (do_panel) +// globals->get_current_panel()->update( +// curColumn*panel_col_step, panel_col_step, +// curRow*panel_row_step, panel_row_step ); more = trEndTile(tr); /* save tile into tile row buffer*/ @@ -472,7 +473,7 @@ GLubyte *hiResScreenCapture( int multiplier ) float fov = oldfov / multiplier; FGViewer *v = globals->get_current_view(); fgSetDouble("/sim/current-view/field-of-view", fov); - globals->get_renderer()->init(); +// globals->get_renderer()->init(); int cur_width = fgGetInt("/sim/startup/xsize"); int cur_height = fgGetInt("/sim/startup/ysize"); delete( b1 ); @@ -554,7 +555,7 @@ void fgDumpSnapShot () { fgSetBool("/sim/signals/screenshot", true); FGRenderer *renderer = globals->get_renderer(); - renderer->init(); +// renderer->init(); renderer->resize( fgGetInt("/sim/startup/xsize"), fgGetInt("/sim/startup/ysize") ); diff --git a/src/Input/input.cxx b/src/Input/input.cxx index d1b170f89..30639bc19 100644 --- a/src/Input/input.cxx +++ b/src/Input/input.cxx @@ -59,7 +59,6 @@ #include #include
-#include #include SG_USING_STD(ifstream); diff --git a/src/Instrumentation/HUD/HUD.cxx b/src/Instrumentation/HUD/HUD.cxx index a5b6a4f53..45e59754d 100644 --- a/src/Instrumentation/HUD/HUD.cxx +++ b/src/Instrumentation/HUD/HUD.cxx @@ -144,7 +144,7 @@ void HUD::update(double dt) } -void HUD::draw() +void HUD::draw(osg::State&) { if (!isVisible()) return; diff --git a/src/Instrumentation/HUD/HUD.hxx b/src/Instrumentation/HUD/HUD.hxx index bb0db7500..d1d987dbb 100644 --- a/src/Instrumentation/HUD/HUD.hxx +++ b/src/Instrumentation/HUD/HUD.hxx @@ -36,6 +36,8 @@ SG_USING_STD(deque); SG_USING_STD(vector); SG_USING_NAMESPACE(std); +#include + #include #include @@ -134,7 +136,7 @@ public: void update(double); // called from Main/renderer.cxx to draw 2D and 3D HUD - void draw(); + void draw(osg::State&); // listener callback to read various HUD related properties void valueChanged(SGPropertyNode *); diff --git a/src/Instrumentation/HUD/HUD_runway.cxx b/src/Instrumentation/HUD/HUD_runway.cxx index 5c525abd9..c2555eba9 100644 --- a/src/Instrumentation/HUD/HUD_runway.cxx +++ b/src/Instrumentation/HUD/HUD_runway.cxx @@ -98,13 +98,16 @@ void HUD::Runway::draw() globals->get_viewmgr()->copyToCurrent(); } //Set the camera to the cockpit view to get the view of the runway from the cockpit - ssgSetCamera((sgVec4 *)_cockpit_view->get_VIEW()); + // OSGFIXME +// ssgSetCamera((sgVec4 *)_cockpit_view->get_VIEW()); get_rwy_points(_points3d); //Get the current project matrix - ssgGetProjectionMatrix(projMat); + // OSGFIXME +// ssgGetProjectionMatrix(projMat); // const sgVec4 *viewMat = globals->get_current_view()->get_VIEW(); //Get the current model view matrix (cockpit view) - ssgGetModelviewMatrix(modelView); + // OSGFIXME +// ssgGetModelviewMatrix(modelView); //Create a rotation matrix to correct for any offsets (other than default offsets) to the model view matrix sgMat4 xy; //rotation about the Rxy, negate the sin's on Ry xy[0][0] = cYaw, xy[1][0] = 0.0f, xy[2][0] = -sYaw, xy[3][0] = 0.0f; @@ -157,7 +160,8 @@ void HUD::Runway::draw() curr_view->setGoalPitchOffset_deg(gpo); } //Set the camera back to the current view - ssgSetCamera((sgVec4 *)curr_view); + // OSGFIXME +// ssgSetCamera((sgVec4 *)curr_view); glPopAttrib(); } diff --git a/src/Instrumentation/od_gauge.cxx b/src/Instrumentation/od_gauge.cxx index d02cc354d..31607aa9c 100644 --- a/src/Instrumentation/od_gauge.cxx +++ b/src/Instrumentation/od_gauge.cxx @@ -24,7 +24,6 @@ # include "config.h" #endif -#include #include #include #include @@ -35,8 +34,8 @@ #include "od_gauge.hxx" FGODGauge::FGODGauge() : - rtAvailable( false ), - rt( 0 ) + rtAvailable( false )// , +// rt( 0 ) { } @@ -44,49 +43,49 @@ FGODGauge::FGODGauge() : // never used void FGODGauge::allocRT () { GLint colorBits = 0; - glGetIntegerv( GL_BLUE_BITS, &colorBits ); +// glGetIntegerv( GL_BLUE_BITS, &colorBits ); textureWH = 256; - rt = new RenderTexture(); - if( colorBits < 8 ) - rt->Reset("rgba=5,5,5,1 ctt"); - else - rt->Reset("rgba ctt"); +// rt = new RenderTexture(); +// if( colorBits < 8 ) +// rt->Reset("rgba=5,5,5,1 ctt"); +// else +// rt->Reset("rgba ctt"); - if( rt->Initialize(256, 256, true) ) { - SG_LOG(SG_ALL, SG_INFO, "FGODGauge:Initialize sucessfull"); - if (rt->BeginCapture()) - { - SG_LOG(SG_ALL, SG_INFO, "FGODGauge:BeginCapture sucessfull, RTT available"); - rtAvailable = true; - glViewport(0, 0, textureWH, textureWH); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D( -256.0, 256.0, -256.0, 256.0 ); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glDisable(GL_LIGHTING); - glEnable(GL_COLOR_MATERIAL); - glDisable(GL_CULL_FACE); - glDisable(GL_FOG); - glDisable(GL_DEPTH_TEST); - glClearColor(0.0, 0.0, 0.0, 0.0); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glBindTexture(GL_TEXTURE_2D, 0); - glEnable(GL_TEXTURE_2D); - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.0f); - glDisable(GL_SMOOTH); - glEnable(GL_BLEND); - glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); - rt->EndCapture(); - } else - SG_LOG(SG_ALL, SG_WARN, "FGODGauge:BeginCapture failed, RTT not available, using backbuffer"); - } else - SG_LOG(SG_ALL, SG_WARN, "FGODGauge:Initialize failed, RTT not available, using backbuffer"); +// if( rt->Initialize(256, 256, true) ) { +// SG_LOG(SG_ALL, SG_INFO, "FGODGauge:Initialize sucessfull"); +// if (rt->BeginCapture()) +// { +// SG_LOG(SG_ALL, SG_INFO, "FGODGauge:BeginCapture sucessfull, RTT available"); +// rtAvailable = true; +// glViewport(0, 0, textureWH, textureWH); +// glMatrixMode(GL_PROJECTION); +// glLoadIdentity(); +// gluOrtho2D( -256.0, 256.0, -256.0, 256.0 ); +// glMatrixMode(GL_MODELVIEW); +// glLoadIdentity(); +// glDisable(GL_LIGHTING); +// glEnable(GL_COLOR_MATERIAL); +// glDisable(GL_CULL_FACE); +// glDisable(GL_FOG); +// glDisable(GL_DEPTH_TEST); +// glClearColor(0.0, 0.0, 0.0, 0.0); +// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +// glBindTexture(GL_TEXTURE_2D, 0); +// glEnable(GL_TEXTURE_2D); +// glEnable(GL_ALPHA_TEST); +// glAlphaFunc(GL_GREATER, 0.0f); +// glDisable(GL_SMOOTH); +// glEnable(GL_BLEND); +// glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); +// rt->EndCapture(); +// } else +// SG_LOG(SG_ALL, SG_WARN, "FGODGauge:BeginCapture failed, RTT not available, using backbuffer"); +// } else +// SG_LOG(SG_ALL, SG_WARN, "FGODGauge:Initialize failed, RTT not available, using backbuffer"); } FGODGauge::~FGODGauge() { - delete rt; +// delete rt; } void FGODGauge::init () { @@ -96,58 +95,59 @@ void FGODGauge::update (double dt) { } void FGODGauge::beginCapture(int viewSize) { - if( ! rt ) - allocRT(); - if(rtAvailable) { - rt->BeginCapture(); - } - else - set2D(); - textureWH = viewSize; - glViewport(0, 0, textureWH, textureWH); +// if( ! rt ) +// allocRT(); +// if(rtAvailable) { +// rt->BeginCapture(); +// } +// else +// set2D(); +// textureWH = viewSize; +// glViewport(0, 0, textureWH, textureWH); } void FGODGauge::beginCapture(void) { - if( ! rt ) - allocRT(); - if(rtAvailable) { - rt->BeginCapture(); - } - else - set2D(); +// if( ! rt ) +// allocRT(); +// if(rtAvailable) { +// rt->BeginCapture(); +// } +// else +// set2D(); } void FGODGauge::Clear(void) { - if(rtAvailable) { - glClear(GL_COLOR_BUFFER_BIT); - } - else { - glDisable(GL_BLEND); - glDisable(GL_ALPHA_TEST); - glColor4f(0.0f, 0.0f, 0.0f, 0.0f); - glRectf(-256.0, -256.0, 256.0, 256.0); - glEnable(GL_BLEND); - glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); - glEnable(GL_ALPHA_TEST); - } +// if(rtAvailable) { +// glClear(GL_COLOR_BUFFER_BIT); +// } +// else { +// glDisable(GL_BLEND); +// glDisable(GL_ALPHA_TEST); +// glColor4f(0.0f, 0.0f, 0.0f, 0.0f); +// glRectf(-256.0, -256.0, 256.0, 256.0); +// glEnable(GL_BLEND); +// glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); +// glEnable(GL_ALPHA_TEST); +// } } -void FGODGauge::endCapture(GLuint texID) { - glBindTexture(GL_TEXTURE_2D, texID); - // don't use mimaps if we don't update them - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +void FGODGauge::endCapture(osg::Texture2D* texID) { + // OSGFIXME +// glBindTexture(GL_TEXTURE_2D, texID); +// // don't use mimaps if we don't update them +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, textureWH, textureWH); - if(rtAvailable) - rt->EndCapture(); - else - set3D(); - glBindTexture(GL_TEXTURE_2D, 0); +// glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, textureWH, textureWH); +// if(rtAvailable) +// rt->EndCapture(); +// else +// set3D(); +// glBindTexture(GL_TEXTURE_2D, 0); } void FGODGauge::setSize(int viewSize) { textureWH = viewSize; - glViewport(0, 0, textureWH, textureWH); +// glViewport(0, 0, textureWH, textureWH); } bool FGODGauge::serviceable(void) { @@ -168,9 +168,11 @@ static const char *strip_path(const char *name) { return fn ; } -static ssgSimpleState * -find_texture_node (ssgEntity * node, const char * name) +// OSGFIXME +static osg::StateSet* +find_texture_node(osg::Node* node, const char * name) { +#if 0 if( node->isAKindOf( ssgTypeLeaf() ) ) { ssgLeaf *leaf = (ssgLeaf *) node; ssgSimpleState *state = (ssgSimpleState *) leaf->getState(); @@ -195,49 +197,51 @@ find_texture_node (ssgEntity * node, const char * name) return result; } } +#endif return 0; } -void FGODGauge::set_texture(const char * name, GLuint new_texture) { - ssgEntity * root = globals->get_scenery()->get_aircraft_branch(); +void FGODGauge::set_texture(const char * name, osg::Texture2D* new_texture) { + osg::Group* root = globals->get_scenery()->get_aircraft_branch(); name = strip_path( name ); - ssgSimpleState * node = find_texture_node( root, name ); - if( node ) - node->setTexture( new_texture ); + // OSGFIXME +// osg::StateSet* node = find_texture_node( root, name ); +// if( node ) +// node->setTexture( new_texture ); } void FGODGauge::set2D() { - glPushAttrib ( GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_BIT ) ; +// glPushAttrib ( GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_BIT ) ; - glDisable(GL_LIGHTING); - glEnable(GL_COLOR_MATERIAL); - glDisable(GL_CULL_FACE); - glDisable(GL_FOG); - glDisable(GL_DEPTH_TEST); - glClearColor(0.0, 0.0, 0.0, 0.0); - glEnable(GL_TEXTURE_2D); - glDisable(GL_SMOOTH); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glBindTexture(GL_TEXTURE_2D, 0); +// glDisable(GL_LIGHTING); +// glEnable(GL_COLOR_MATERIAL); +// glDisable(GL_CULL_FACE); +// glDisable(GL_FOG); +// glDisable(GL_DEPTH_TEST); +// glClearColor(0.0, 0.0, 0.0, 0.0); +// glEnable(GL_TEXTURE_2D); +// glDisable(GL_SMOOTH); +// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +// glBindTexture(GL_TEXTURE_2D, 0); - glViewport ( 0, 0, textureWH, textureWH ) ; - glMatrixMode ( GL_PROJECTION ) ; - glPushMatrix () ; - glLoadIdentity () ; - gluOrtho2D( -256.0, 256.0, -256.0, 256.0 ); - glMatrixMode ( GL_MODELVIEW ) ; - glPushMatrix () ; - glLoadIdentity () ; +// glViewport ( 0, 0, textureWH, textureWH ) ; +// glMatrixMode ( GL_PROJECTION ) ; +// glPushMatrix () ; +// glLoadIdentity () ; +// gluOrtho2D( -256.0, 256.0, -256.0, 256.0 ); +// glMatrixMode ( GL_MODELVIEW ) ; +// glPushMatrix () ; +// glLoadIdentity () ; - glAlphaFunc(GL_GREATER, 0.0f); +// glAlphaFunc(GL_GREATER, 0.0f); } void FGODGauge::set3D() { - glMatrixMode ( GL_PROJECTION ) ; - glPopMatrix () ; - glMatrixMode ( GL_MODELVIEW ) ; - glPopMatrix () ; - glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; - glPopAttrib () ; +// glMatrixMode ( GL_PROJECTION ) ; +// glPopMatrix () ; +// glMatrixMode ( GL_MODELVIEW ) ; +// glPopMatrix () ; +// glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; +// glPopAttrib () ; } diff --git a/src/Instrumentation/od_gauge.hxx b/src/Instrumentation/od_gauge.hxx index f8a5f0e0a..caf18a41a 100644 --- a/src/Instrumentation/od_gauge.hxx +++ b/src/Instrumentation/od_gauge.hxx @@ -23,12 +23,10 @@ #ifndef _OD_GAUGE_HXX #define _OD_GAUGE_HXX +#include -#include #include -class RenderTexture; - /** * Owner Drawn Gauge helper class. */ @@ -58,7 +56,7 @@ public: * Finish rendering and save the buffer to a texture. * @param texID name of a gl texture */ - void endCapture(GLuint texID); + void endCapture(osg::Texture2D*); /** * Set the size of the destination texture. * @param viewSize size of the destination texture @@ -75,11 +73,10 @@ public: * @param name texture filename * @param new_texture dynamic texture to replace the old one */ - void set_texture(const char * name, GLuint new_texture); + void set_texture(const char * name, osg::Texture2D* new_texture); private: int textureWH; - RenderTexture *rt; bool rtAvailable; void allocRT(void); diff --git a/src/Instrumentation/render_area_2d.cxx b/src/Instrumentation/render_area_2d.cxx index 6338e3082..e1ebbeda4 100644 --- a/src/Instrumentation/render_area_2d.cxx +++ b/src/Instrumentation/render_area_2d.cxx @@ -21,13 +21,18 @@ // // $Id$ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_WINDOWS_H +# include +#endif + +#include + #include "render_area_2d.hxx" -//#include - -#include - -//using namespace std; - static const float dummy_normals[][3] = {{0.0f, 0.0f, 0.0f}, @@ -65,6 +70,7 @@ RenderArea2D::RenderArea2D(int logx, int logy, int sizex, int sizey, int posx, i } void RenderArea2D::draw() { +#if 0 glDisable(GL_TEXTURE_2D); /* glColor3f(1, 1, 0); @@ -103,6 +109,7 @@ void RenderArea2D::draw() { } glEnable(GL_TEXTURE_2D); +#endif } // Set clipping region in logical units @@ -336,25 +343,34 @@ void RenderArea2D::Flush() { // ----------------------------------------- void RenderArea2D::doSetColor( const float *rgba ) { + //OSGFIXME +#if 0 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, rgba); glColor4fv( rgba ); +#endif } void RenderArea2D::doDrawQuad( const sgVec2 *p, const sgVec3 *normals ) { //cout << "doDrawQuad: " << *p[0] << ", " << *(p[0]+1) << ", " << *p[1] << ", " << *(p[1]+1) << ", " << *p[2] << ", " << *p([2]+1) << ", " << *p[3] << ", " << *p([3]+1) <<'\n'; + //OSGFIXME +#if 0 glBegin(GL_QUADS); glNormal3fv( normals[0] ); glVertex2fv( p[0] ); glNormal3fv( normals[1] ); glVertex2fv( p[1] ); glNormal3fv( normals[2] ); glVertex2fv( p[2] ); glNormal3fv( normals[3] ); glVertex2fv( p[3] ); glEnd(); +#endif } void RenderArea2D::doDrawQuad( const sgVec2 *p, const sgVec3 *normals, const sgVec4 *color ) { + //OSGFIXME +#if 0 glBegin(GL_QUADS); glColor4fv( color[0] );glNormal3fv( normals[0] ); glVertex2fv( p[0] ); glColor4fv( color[1] );glNormal3fv( normals[1] ); glVertex2fv( p[1] ); glColor4fv( color[2] );glNormal3fv( normals[2] ); glVertex2fv( p[2] ); glColor4fv( color[3] );glNormal3fv( normals[3] ); glVertex2fv( p[3] ); glEnd(); +#endif } diff --git a/src/Instrumentation/render_area_2d.hxx b/src/Instrumentation/render_area_2d.hxx index 4b3b05938..de41798d0 100644 --- a/src/Instrumentation/render_area_2d.hxx +++ b/src/Instrumentation/render_area_2d.hxx @@ -28,9 +28,9 @@ # include #endif +#include #include -#include #include SG_USING_STD(vector); diff --git a/src/Instrumentation/wxradar.cxx b/src/Instrumentation/wxradar.cxx index 11aa71050..1a879ed5f 100644 --- a/src/Instrumentation/wxradar.cxx +++ b/src/Instrumentation/wxradar.cxx @@ -87,7 +87,10 @@ wxRadarBg::init () SGPath tpath(globals->get_fg_root()); tpath.append("Aircraft/Instruments/Textures/wxecho.rgb"); // no mipmap or else alpha will mix with pixels on the border of shapes, ruining the effect - wxEcho = new ssgTexture( tpath.c_str(), false, false, false); + + // OSGFIXME +// wxEcho = new ssgTexture( tpath.c_str(), false, false, false); + wxEcho = new osg::Texture2D; _Instrument->setFloatValue("trk", 0.0); _Instrument->setFloatValue("tilt", 0.0); @@ -110,6 +113,8 @@ wxRadarBg::init () void wxRadarBg::update (double delta_time_sec) { + //OSGFIXME +#if 0 if ( ! sim_init_done ) { if ( ! fgGetBool("sim/sceneryloaded", false) ) return; @@ -130,7 +135,7 @@ wxRadarBg::update (double delta_time_sec) // we must locate them and replace their handle by hand // only do that when the instrument is turned on if ( last_switchKnob == "off" ) - odg->set_texture( odgauge_name, resultTexture->getHandle()); + odg->set_texture( odgauge_name, resultTexture.get()); last_switchKnob = switchKnob; } FGViewer *current__view = globals->get_current_view(); @@ -189,7 +194,8 @@ wxRadarBg::update (double delta_time_sec) const float symbolSize = 1.0f / 8.0f ; // draw the radar echo, we do that in 3 passes, one for each color level // this is to 'merge' same colors together - glBindTexture(GL_TEXTURE_2D, wxEcho->getHandle() ); + // OSGFIXME +// glBindTexture(GL_TEXTURE_2D, wxEcho->getHandle() ); glColor3f(1.0f, 1.0f, 1.0f); glBegin( GL_QUADS ); @@ -335,5 +341,6 @@ wxRadarBg::update (double delta_time_sec) glEnable(GL_ALPHA_TEST); } glPopMatrix(); - odg->endCapture( resultTexture->getHandle() ); + odg->endCapture( resultTexture.get() ); +#endif } diff --git a/src/Instrumentation/wxradar.hxx b/src/Instrumentation/wxradar.hxx index b2f7139f8..acaa6680b 100644 --- a/src/Instrumentation/wxradar.hxx +++ b/src/Instrumentation/wxradar.hxx @@ -23,14 +23,13 @@ #ifndef _INST_WXRADAR_HXX #define _INST_WXRADAR_HXX -#include +#include +#include #include #include #include -#include -class ssgTexture; class FGODGauge; class wxRadarBg : public SGSubsystem { @@ -52,8 +51,8 @@ private: SGPropertyNode_ptr _serviceable_node; SGPropertyNode_ptr _Instrument; - ssgSharedPtr resultTexture; - ssgSharedPtr wxEcho; + osg::ref_ptr resultTexture; + osg::ref_ptr wxEcho; string last_switchKnob; bool sim_init_done; FGODGauge *odg; diff --git a/src/Main/Makefile.am b/src/Main/Makefile.am index 5ac0cf0b9..d8448015b 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -78,8 +78,8 @@ fgfs_LDADD = \ $(top_builddir)/src/Autopilot/libAutopilot.a \ $(top_builddir)/src/Input/libInput.a \ $(top_builddir)/src/Instrumentation/KLN89/libKLN89.a \ - $(top_builddir)/src/Instrumentation/HUD/libHUD.a \ $(top_builddir)/src/Instrumentation/libInstrumentation.a \ + $(top_builddir)/src/Instrumentation/HUD/libHUD.a \ $(top_builddir)/src/Model/libModel.a \ $(top_builddir)/src/Network/libNetwork.a \ $(top_builddir)/src/Navaids/libNavaids.a \ @@ -97,13 +97,17 @@ fgfs_LDADD = \ -lsgtiming -lsgio -lsgscreen -lsgmath -lsgbucket -lsgprops -lsgdebug \ -lsgmagvar -lsgmisc -lsgnasal -lsgxml -lsgsound -lsgserial \ -lsgstructure -lsgenvironment \ + -lplibpuaux -lplibpu -lplibfnt -lplibjs -lplibnet \ + -lplibsg -lplibul \ + -losgUtil -losgDB -losgSim -losg -lOpenThreads \ $(THREAD_LIBS) \ - -lplibpuaux -lplibpu -lplibfnt -lplibjs -lplibnet -lplibssgaux -lplibssg -lplibsg -lplibul \ $(network_LIBS) \ -lz \ $(opengl_LIBS) \ $(openal_LIBS) +# -lplibssgaux -lplibssg + metar_SOURCES = metar_main.cxx metar_LDADD = \ diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 03ba1711c..6f82ad883 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -614,13 +614,12 @@ static void fgMainLoop( void ) { globals->get_soundmgr()->set_volume(init_volume); } - if (fgGetBool("/sim/rendering/specular-highlight")) { - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); - // glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); - } else { - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); - // glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); - } + // OSGFIXME: with osg>1.2 remove this, osg::LightModel does the trick... +// if (fgGetBool("/sim/rendering/specular-highlight")) { +// glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); +// } else { +// glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); +// } fgRequestRedraw(); @@ -665,10 +664,6 @@ static void fgIdleFunction ( void ) { general.set_glDepthBits( tmp ); SG_LOG ( SG_GENERAL, SG_INFO, "Depth buffer bits = " << tmp ); - // Initialize ssg (from plib). Needs to come before we do any - // other ssg stuff, but after opengl has been initialized. - ssgInit(); - // Initialize the user interface (we need to do this before // passing off control to the OS main loop and before // fgInitGeneral to get our fonts !!! @@ -682,21 +677,21 @@ static void fgIdleFunction ( void ) { fgReadAircraft(); // get the address of our OpenGL extensions - if (SGIsOpenGLExtensionSupported("GL_EXT_point_parameters") ) { - glPointParameterIsSupported = true; - glPointParameterfPtr = (glPointParameterfProc) - SGLookupFunction("glPointParameterfEXT"); - glPointParameterfvPtr = (glPointParameterfvProc) - SGLookupFunction("glPointParameterfvEXT"); - } else if ( SGIsOpenGLExtensionSupported("GL_ARB_point_parameters") ) { - glPointParameterIsSupported = true; - glPointParameterfPtr = (glPointParameterfProc) - SGLookupFunction("glPointParameterfARB"); - glPointParameterfvPtr = (glPointParameterfvProc) - SGLookupFunction("glPointParameterfvARB"); - } else { - glPointParameterIsSupported = false; - } +// if (SGIsOpenGLExtensionSupported("GL_EXT_point_parameters") ) { +// glPointParameterIsSupported = true; +// glPointParameterfPtr = (glPointParameterfProc) +// SGLookupFunction("glPointParameterfEXT"); +// glPointParameterfvPtr = (glPointParameterfvProc) +// SGLookupFunction("glPointParameterfvEXT"); +// } else if ( SGIsOpenGLExtensionSupported("GL_ARB_point_parameters") ) { +// glPointParameterIsSupported = true; +// glPointParameterfPtr = (glPointParameterfProc) +// SGLookupFunction("glPointParameterfARB"); +// glPointParameterfvPtr = (glPointParameterfvProc) +// SGLookupFunction("glPointParameterfvARB"); +// } else { +// glPointParameterIsSupported = false; +// } fgSplashProgress("reading airport & navigation data"); @@ -838,7 +833,6 @@ static void fgIdleFunction ( void ) { // lighting->addKid( airport ); // build our custom render states - globals->get_renderer()->build_states(); fgSplashProgress("initializing subsystems"); @@ -993,7 +987,8 @@ bool fgMainInit( int argc, char **argv ) { exit(-1); } - sgUseDisplayList = fgGetBool( "/sim/rendering/use-display-list", true ); + //OSGFIXME +// sgUseDisplayList = fgGetBool( "/sim/rendering/use-display-list", true ); // Load the configuration parameters. (Command line options // override config file options. Config file options override diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index 0a6077bf9..21c66f260 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -32,15 +32,44 @@ # include #endif -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include #include #include #include #include #include #include +#include #include #include #include @@ -52,13 +81,10 @@ #include -#include - #include #include