# include <config.h>
#endif
+#include <string>
+#include <vector>
+
#include "AICarrier.hxx"
FGAICarrier::~FGAICarrier() {
}
+void FGAICarrier::setSolidObjects(const list<string>& so) {
+ solid_objects = so;
+}
+
+void FGAICarrier::setWireObjects(const list<string>& wo) {
+ wire_objects = wo;
+}
+
+void FGAICarrier::setCatapultObjects(const list<string>& 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<string>& 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<string>::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<string>& 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<string>::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<string>& 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<string>::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;
#ifndef _FG_AICARRIER_HXX
#define _FG_AICARRIER_HXX
+#include <string>
+#include <list>
+#include <plib/ssg.h>
+#include <simgear/compiler.h>
+
+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 {
FGAICarrier(FGAIManager* mgr);
~FGAICarrier();
+
+ void setSolidObjects(const list<string>& solid_objects);
+ void setWireObjects(const list<string>& wire_objects);
+ void setCatapultObjects(const list<string>& catapult_objects);
+
+ void getVelocityWrtEarth(sgVec3 v);
+ bool init();
+
private:
void update(double dt);
+ void mark_nohot(ssgEntity*);
+ bool mark_wires(ssgEntity*, const list<string>&);
+ bool mark_cat(ssgEntity*, const list<string>&);
+ bool mark_solid(ssgEntity*, const list<string>&);
+
+ list<string> solid_objects; // List of solid object names
+ list<string> wire_objects; // List of wire object names
+ list<string> catapult_objects; // List of catapult object names
+
+ // Velocity wrt earth.
+ sgVec3 vel_wrt_earth;
};
#endif // _FG_AICARRIER_HXX
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#include <cstdio>
#include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx>
#include "AIScenario.hxx"
#include "AIFlightPlan.hxx"
-
+static list<string>
+getAllNodeVals(const char* name, SGPropertyNode * entry_node);
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 );
return entries.size();
}
+static list<string>
+getAllNodeVals(const char* name, SGPropertyNode * entry_node)
+{
+ list<string> 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
GroundProperty *gp = new GroundProperty;
gp->wire_id = -1;
-// FGAICarrierHardware *ud =
-// dynamic_cast<FGAICarrierHardware*>(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 );
-// }
-
-// else {
+ FGAICarrierHardware *ud =
+ dynamic_cast<FGAICarrierHardware*>(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 );
+ }
+
+ 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();