diff --git a/src/AIModel/AIBase.hxx b/src/AIModel/AIBase.hxx index 7bb3b607c..bca2aea11 100644 --- a/src/AIModel/AIBase.hxx +++ b/src/AIModel/AIBase.hxx @@ -21,6 +21,7 @@ #define _FG_AIBASE_HXX #include +#include #include #include @@ -29,6 +30,7 @@ #include
SG_USING_STD(string); +SG_USING_STD(list); class FGAIManager; class FGAIFlightPlan; @@ -67,6 +69,9 @@ typedef struct { bool wind; // if true, model reacts to parent wind double mass; // in slugs bool aero_stabilised; // if true, ballistic object aligns with trajectory + list solid_objects; // List of solid object names + list wire_objects; // List of wire object names + list catapult_objects; // List of catapult object names double radius; // used by ship ojects, in feet } FGAIModelEntity; diff --git a/src/AIModel/AICarrier.cxx b/src/AIModel/AICarrier.cxx index bb5212818..d6e29b746 100644 --- a/src/AIModel/AICarrier.cxx +++ b/src/AIModel/AICarrier.cxx @@ -21,6 +21,9 @@ # include #endif +#include +#include + #include "AICarrier.hxx" @@ -30,10 +33,179 @@ FGAICarrier::FGAICarrier(FGAIManager* mgr) : FGAIShip(mgr) { FGAICarrier::~FGAICarrier() { } +void FGAICarrier::setSolidObjects(const list& so) { + solid_objects = so; +} + +void FGAICarrier::setWireObjects(const list& wo) { + wire_objects = wo; +} + +void FGAICarrier::setCatapultObjects(const list& co) { + catapult_objects = co; +} + +void FGAICarrier::getVelocityWrtEarth(sgVec3 v) { + sgCopyVec3(v, vel_wrt_earth ); +} void FGAICarrier::update(double dt) { FGAIShip::update(dt); + + // Update the velocity information stored in those nodes. + double v_north = 0.51444444*speed*cos(hdg * SGD_DEGREES_TO_RADIANS); + double v_east = 0.51444444*speed*sin(hdg * SGD_DEGREES_TO_RADIANS); + + double sin_lat = sin(pos.lat() * SGD_DEGREES_TO_RADIANS); + double cos_lat = cos(pos.lat() * SGD_DEGREES_TO_RADIANS); + double sin_lon = sin(pos.lon() * SGD_DEGREES_TO_RADIANS); + double cos_lon = cos(pos.lon() * SGD_DEGREES_TO_RADIANS); + sgSetVec3( vel_wrt_earth, + - cos_lon*sin_lat*v_north - sin_lon*v_east, + - sin_lon*sin_lat*v_north + cos_lon*v_east, + cos_lat*v_north ); + } +bool FGAICarrier::init() { + if (!FGAIShip::init()) + return false; + // process the 3d model here + // mark some objects solid, mark the wires ... + // The model should be used for altitude computations. + // To avoid that every detail in a carrier 3D model will end into + // the aircraft local cache, only set the HOT traversal bit on + // selected objects. + ssgEntity *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); + + return true; +} + +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 found = false; + if (e->isAKindOf(ssgTypeBranch())) { + + ssgBranch* br = (ssgBranch*)e; + ssgEntity* kid; + for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() ) + found = mark_wires(kid, wire_objects) || 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 (e->getName() && (*it) == e->getName()) { + e->setTraversalMaskBits(SSGTRAV_HOT); + e->setUserData( FGAICarrierHardware::newWire( this ) ); + ssgLeaf *l = (ssgLeaf*)e; + if ( l->getNumLines() != 1 ) { + SG_LOG(SG_GENERAL, SG_ALERT, + "AICarrier: Found wires not modelled with exactly one line!"); + } + + found = true; + } + } + } + return found; +} + +bool FGAICarrier::mark_solid(ssgEntity* e, const list& solid_objects) { + bool found = false; + if (e->isAKindOf(ssgTypeBranch())) { + ssgBranch* br = (ssgBranch*)e; + ssgEntity* kid; + for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() ) + found = mark_solid(kid, solid_objects) || 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 (e->getName() && (*it) == e->getName()) { + e->setTraversalMaskBits(SSGTRAV_HOT); + e->setUserData( FGAICarrierHardware::newSolid( this ) ); + found = true; + } + } + } + return found; +} + +bool FGAICarrier::mark_cat(ssgEntity* e, const list& cat_objects) { + bool found = false; + if (e->isAKindOf(ssgTypeBranch())) { + ssgBranch* br = (ssgBranch*)e; + ssgEntity* kid; + for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() ) + found = mark_cat(kid, cat_objects) || 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 (e->getName() && (*it) == e->getName()) { + e->setTraversalMaskBits(SSGTRAV_HOT); + e->setUserData( FGAICarrierHardware::newCatapult( this ) ); + ssgLeaf *l = (ssgLeaf*)e; + if ( l->getNumLines() != 1 ) { + SG_LOG(SG_GENERAL, SG_ALERT, + "AICarrier: Found a cat not modelled with exactly one line!"); + } + // Now some special code to make shure 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 ); + sgVec3 ends[2]; + for (int k=0; k<2; ++k) + sgCopyVec3( ends[k], 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] ); + sgCopyVec3( l->getVertex( v[1] ), ends[0] ); + } + + found = true; + } + } + } + return found; +} + +int FGAICarrierHardware::unique_id = 1; diff --git a/src/AIModel/AICarrier.hxx b/src/AIModel/AICarrier.hxx index c536c457e..32cea5983 100644 --- a/src/AIModel/AICarrier.hxx +++ b/src/AIModel/AICarrier.hxx @@ -21,8 +21,52 @@ #ifndef _FG_AICARRIER_HXX #define _FG_AICARRIER_HXX +#include +#include +#include +#include + +SG_USING_STD(string); +SG_USING_STD(list); + #include "AIShip.hxx" class FGAIManager; +class FGAICarrier; + +class FGAICarrierHardware : public ssgBase { +public: + + enum Type { Catapult, Wire, Solid }; + + FGAICarrier *carrier; + int id; + Type type; + + static FGAICarrierHardware* newCatapult(FGAICarrier *c) { + FGAICarrierHardware* ch = new FGAICarrierHardware; + ch->carrier = c; + ch->type = Catapult; + ch->id = unique_id++; + return ch; + } + static FGAICarrierHardware* newWire(FGAICarrier *c) { + FGAICarrierHardware* ch = new FGAICarrierHardware; + ch->carrier = c; + ch->type = Wire; + ch->id = unique_id++; + return ch; + } + static FGAICarrierHardware* newSolid(FGAICarrier *c) { + FGAICarrierHardware* ch = new FGAICarrierHardware; + ch->carrier = c; + ch->type = Solid; + ch->id = unique_id++; + return ch; + } + +private: + static int unique_id; +}; class FGAICarrier : public FGAIShip { @@ -30,10 +74,29 @@ public: FGAICarrier(FGAIManager* mgr); ~FGAICarrier(); + + void setSolidObjects(const list& solid_objects); + void setWireObjects(const list& wire_objects); + void setCatapultObjects(const list& catapult_objects); + + void getVelocityWrtEarth(sgVec3 v); + bool init(); + private: void update(double dt); + void mark_nohot(ssgEntity*); + bool mark_wires(ssgEntity*, const list&); + bool mark_cat(ssgEntity*, const list&); + bool mark_solid(ssgEntity*, const list&); + + list solid_objects; // List of solid object names + list wire_objects; // List of wire object names + list catapult_objects; // List of catapult object names + + // Velocity wrt earth. + sgVec3 vel_wrt_earth; }; #endif // _FG_AICARRIER_HXX diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index f9b641c4d..04919f7d3 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -192,7 +192,7 @@ FGAIManager::createCarrier( FGAIModelEntity *entity ) { //cout << "creating carrier" << endl; - FGAIShip* ai_carrier = new FGAICarrier(this); + FGAICarrier* ai_carrier = new FGAICarrier(this); ai_list.push_back(ai_carrier); ++numObjects[0]; ++numObjects[FGAIBase::otShip]; @@ -203,6 +203,9 @@ FGAIManager::createCarrier( FGAIModelEntity *entity ) { ai_carrier->setLongitude(entity->longitude); ai_carrier->setLatitude(entity->latitude); ai_carrier->setBank(entity->rudder); + ai_carrier->setSolidObjects(entity->solid_objects); + ai_carrier->setWireObjects(entity->wire_objects); + ai_carrier->setCatapultObjects(entity->catapult_objects); ai_carrier->setRadius(entity->radius); if ( entity->fp ) { diff --git a/src/AIModel/AIScenario.cxx b/src/AIModel/AIScenario.cxx index 37f5d8427..0e92bc7c1 100644 --- a/src/AIModel/AIScenario.cxx +++ b/src/AIModel/AIScenario.cxx @@ -16,6 +16,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +#include #include #include @@ -32,7 +33,8 @@ #include "AIScenario.hxx" #include "AIFlightPlan.hxx" - +static list +getAllNodeVals(const char* name, SGPropertyNode * entry_node); FGAIScenario::FGAIScenario(string &filename) { @@ -92,6 +94,10 @@ FGAIScenario::FGAIScenario(string &filename) en->y_pivot = entry_node->getDoubleValue("y-pivot", 0.0); en->z_pivot = entry_node->getDoubleValue("z-pivot", 0.0); */ + en->wire_objects = getAllNodeVals("wire", entry_node); + en->catapult_objects = getAllNodeVals("catapult", entry_node); + en->solid_objects = getAllNodeVals("solid", entry_node); + en->fp = NULL; if (en->flightplan != ""){ en->fp = new FGAIFlightPlan( en->flightplan ); @@ -126,5 +132,25 @@ int FGAIScenario::nEntries( void ) return entries.size(); } +static list +getAllNodeVals(const char* name, SGPropertyNode * entry_node) +{ + list retval; + int i=0; + do { + char nodename[100]; + snprintf(nodename, sizeof(nodename), "%s[%d]", name, i); + const char* objname = entry_node->getStringValue(nodename, 0); + if (objname == 0) + return retval; + + retval.push_back(string(objname)); + ++i; + } while (1); + + return retval; +} + + // end scenario.cxx diff --git a/src/FDM/groundcache.cxx b/src/FDM/groundcache.cxx index 50eee1e60..683bb27d1 100644 --- a/src/FDM/groundcache.cxx +++ b/src/FDM/groundcache.cxx @@ -49,31 +49,31 @@ FGGroundCache::extractGroundProperty( ssgLeaf* l ) GroundProperty *gp = new GroundProperty; gp->wire_id = -1; -// FGAICarrierHardware *ud = -// dynamic_cast(l->getUserData()); -// if (ud) { -// switch (ud->type) { -// case FGAICarrierHardware::Wire: -// gp->type = FGInterface::Wire; -// gp->wire_id = ud->id; -// break; -// case FGAICarrierHardware::Catapult: -// gp->type = FGInterface::Catapult; -// break; -// default: -// gp->type = FGInterface::Solid; -// break; -// } + FGAICarrierHardware *ud = + dynamic_cast(l->getUserData()); + if (ud) { + switch (ud->type) { + case FGAICarrierHardware::Wire: + gp->type = FGInterface::Wire; + gp->wire_id = ud->id; + break; + case FGAICarrierHardware::Catapult: + gp->type = FGInterface::Catapult; + break; + default: + gp->type = FGInterface::Solid; + break; + } -// // Copy the velocity from the carrier class. -// ud->carrier->getVelocityWrtEarth( gp->vel ); -// } + // Copy the velocity from the carrier class. + ud->carrier->getVelocityWrtEarth( gp->vel ); + } -// else { + else { // Initialize velocity field. sgSetVec3( gp->vel, 0.0, 0.0, 0.0 ); -// } + } // Get the texture name and decide what ground type we have. ssgState *st = l->getState();