1 // FGAICarrier - FGAIShip-derived class creates an AI aircraft carrier
3 // Written by David Culp, started October 2004.
4 // - davidculp2@comcast.net
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License as
8 // published by the Free Software Foundation; either version 2 of the
9 // License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "AICarrier.hxx"
30 FGAICarrier::FGAICarrier(FGAIManager* mgr) : FGAIShip(mgr) {
33 FGAICarrier::~FGAICarrier() {
36 void FGAICarrier::setSolidObjects(const list<string>& so) {
40 void FGAICarrier::setWireObjects(const list<string>& wo) {
44 void FGAICarrier::setCatapultObjects(const list<string>& co) {
45 catapult_objects = co;
48 void FGAICarrier::getVelocityWrtEarth(sgVec3 v) {
49 sgCopyVec3(v, vel_wrt_earth );
52 void FGAICarrier::update(double dt) {
55 // Update the velocity information stored in those nodes.
56 double v_north = 0.51444444*speed*cos(hdg * SGD_DEGREES_TO_RADIANS);
57 double v_east = 0.51444444*speed*sin(hdg * SGD_DEGREES_TO_RADIANS);
59 double sin_lat = sin(pos.lat() * SGD_DEGREES_TO_RADIANS);
60 double cos_lat = cos(pos.lat() * SGD_DEGREES_TO_RADIANS);
61 double sin_lon = sin(pos.lon() * SGD_DEGREES_TO_RADIANS);
62 double cos_lon = cos(pos.lon() * SGD_DEGREES_TO_RADIANS);
63 sgSetVec3( vel_wrt_earth,
64 - cos_lon*sin_lat*v_north - sin_lon*v_east,
65 - sin_lon*sin_lat*v_north + cos_lon*v_east,
70 bool FGAICarrier::init() {
71 if (!FGAIShip::init())
74 // process the 3d model here
75 // mark some objects solid, mark the wires ...
77 // The model should be used for altitude computations.
78 // To avoid that every detail in a carrier 3D model will end into
79 // the aircraft local cache, only set the HOT traversal bit on
81 ssgEntity *sel = aip.getSceneGraph();
82 // Clear the HOT traversal flag
84 // Selectively set that flag again for wires/cats/solid objects.
85 // Attach a pointer to this carrier class to those objects.
86 mark_wires(sel, wire_objects);
87 mark_cat(sel, catapult_objects);
88 mark_solid(sel, solid_objects);
93 void FGAICarrier::mark_nohot(ssgEntity* e) {
94 if (e->isAKindOf(ssgTypeBranch())) {
95 ssgBranch* br = (ssgBranch*)e;
97 for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
100 br->clrTraversalMaskBits(SSGTRAV_HOT);
102 } else if (e->isAKindOf(ssgTypeLeaf())) {
104 e->clrTraversalMaskBits(SSGTRAV_HOT);
109 bool FGAICarrier::mark_wires(ssgEntity* e, const list<string>& wire_objects) {
111 if (e->isAKindOf(ssgTypeBranch())) {
113 ssgBranch* br = (ssgBranch*)e;
115 for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
116 found = mark_wires(kid, wire_objects) || found;
119 br->setTraversalMaskBits(SSGTRAV_HOT);
121 } else if (e->isAKindOf(ssgTypeLeaf())) {
122 list<string>::const_iterator it;
123 for (it = wire_objects.begin(); it != wire_objects.end(); ++it) {
124 if (e->getName() && (*it) == e->getName()) {
125 e->setTraversalMaskBits(SSGTRAV_HOT);
126 e->setUserData( FGAICarrierHardware::newWire( this ) );
127 ssgLeaf *l = (ssgLeaf*)e;
128 if ( l->getNumLines() != 1 ) {
129 SG_LOG(SG_GENERAL, SG_ALERT,
130 "AICarrier: Found wires not modelled with exactly one line!");
140 bool FGAICarrier::mark_solid(ssgEntity* e, const list<string>& solid_objects) {
142 if (e->isAKindOf(ssgTypeBranch())) {
143 ssgBranch* br = (ssgBranch*)e;
145 for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
146 found = mark_solid(kid, solid_objects) || found;
149 br->setTraversalMaskBits(SSGTRAV_HOT);
151 } else if (e->isAKindOf(ssgTypeLeaf())) {
152 list<string>::const_iterator it;
153 for (it = solid_objects.begin(); it != solid_objects.end(); ++it) {
154 if (e->getName() && (*it) == e->getName()) {
155 e->setTraversalMaskBits(SSGTRAV_HOT);
156 e->setUserData( FGAICarrierHardware::newSolid( this ) );
164 bool FGAICarrier::mark_cat(ssgEntity* e, const list<string>& cat_objects) {
166 if (e->isAKindOf(ssgTypeBranch())) {
167 ssgBranch* br = (ssgBranch*)e;
169 for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
170 found = mark_cat(kid, cat_objects) || found;
173 br->setTraversalMaskBits(SSGTRAV_HOT);
175 } else if (e->isAKindOf(ssgTypeLeaf())) {
176 list<string>::const_iterator it;
177 for (it = cat_objects.begin(); it != cat_objects.end(); ++it) {
178 if (e->getName() && (*it) == e->getName()) {
179 e->setTraversalMaskBits(SSGTRAV_HOT);
180 e->setUserData( FGAICarrierHardware::newCatapult( this ) );
181 ssgLeaf *l = (ssgLeaf*)e;
182 if ( l->getNumLines() != 1 ) {
183 SG_LOG(SG_GENERAL, SG_ALERT,
184 "AICarrier: Found a cat not modelled with exactly one line!");
186 // Now some special code to make shure the cat points in the right
187 // direction. The 0 index must be the backward end, the 1 index
189 // Forward is positive x-direction in our 3D model, also the model
190 // as such is flattened when it is loaded, so we do not need to care
191 // for transforms ...
193 l->getLine(0, v, v+1 );
195 for (int k=0; k<2; ++k)
196 sgCopyVec3( ends[k], l->getVertex( v[k] ) );
198 // When the 1 end is behind the 0 end, swap the coordinates.
199 if (ends[0][0] < ends[1][0]) {
200 sgCopyVec3( l->getVertex( v[0] ), ends[1] );
201 sgCopyVec3( l->getVertex( v[1] ), ends[0] );
211 int FGAICarrierHardware::unique_id = 1;