]> git.mxchange.org Git - flightgear.git/blob - src/Model/acmodel.cxx
don't destroy iterated map entries; delete _menubar; restore closed
[flightgear.git] / src / Model / acmodel.cxx
1 // model.cxx - manage a 3D aircraft model.
2 // Written by David Megginson, started 2002.
3 //
4 // This file is in the Public Domain, and comes with no warranty.
5
6 #ifdef HAVE_CONFIG_H
7 #  include <config.h>
8 #endif
9
10 #include <string.h>             // for strcmp()
11
12 #include <plib/sg.h>
13 #include <plib/ssg.h>
14
15 #include <simgear/compiler.h>
16 #include <simgear/debug/logstream.hxx>
17 #include <simgear/structure/exception.hxx>
18 #include <simgear/misc/sg_path.hxx>
19 #include <simgear/scene/model/placement.hxx>
20 #include <simgear/scene/model/shadowvolume.hxx>
21
22 #include <Main/globals.hxx>
23 #include <Main/fg_props.hxx>
24 #include <Main/renderer.hxx>
25 #include <Main/viewmgr.hxx>
26 #include <Main/viewer.hxx>
27 #include <Scenery/scenery.hxx>
28
29 #include "model_panel.hxx"
30
31 #include "acmodel.hxx"
32
33
34 class fgLoaderOptions : ssgLoaderOptions {
35
36 public:
37     virtual void makeTexturePath ( char* path, const char *fname ) const ;
38     string livery_path;
39
40 };
41
42 void fgLoaderOptions::makeTexturePath ( char *path, const char *fname ) const
43 {
44   /* Remove all leading path information. */
45   const char* seps = "\\/" ;
46   const char* fn = & fname [ strlen ( fname ) - 1 ] ;
47   for ( ; fn != fname && strchr(seps,*fn) == NULL ; fn-- )
48     /* Search back for a seperator */ ;
49   if ( strchr(seps,*fn) != NULL )
50     fn++ ;
51   fname = fn ;
52   // if we have a livery path and the texture is found there then we use that
53   // path in priority, if the texture was not found or we add no additional 
54   // livery path then we use the current model path or model/texture-path
55   if( livery_path.size() ) {
56       make_path( path, livery_path.c_str(), fname );
57       if( ulFileExists( path ) )
58           return;
59   }
60   make_path ( path, texture_dir, fname ) ;
61 }
62
63 static fgLoaderOptions _fgLoaderOptions;
64
65 \f
66 ////////////////////////////////////////////////////////////////////////
67 // Implementation of FGAircraftModel
68 ////////////////////////////////////////////////////////////////////////
69
70 FGAircraftModel::FGAircraftModel ()
71   : _aircraft(0),
72     _selector(new ssgSelector),
73     _scene(new ssgRoot),
74     _nearplane(0.10f),
75     _farplane(1000.0f)
76 {
77 }
78
79 FGAircraftModel::~FGAircraftModel ()
80 {
81   // Unregister that one at the scenery manager
82   if (_aircraft)
83     globals->get_scenery()->unregister_placement_transform(_aircraft->getTransform());
84
85   delete _aircraft;
86   delete _scene;
87                                 // SSG will delete it
88   globals->get_scenery()->get_aircraft_branch()->removeKid(_selector);
89 }
90
91 void 
92 FGAircraftModel::init ()
93 {
94   ssgLoaderOptions *currLoaderOptions = ssgGetCurrentOptions();
95   ssgSetCurrentOptions( (ssgLoaderOptions*)&_fgLoaderOptions );
96   _aircraft = new SGModelPlacement;
97   string path = fgGetString("/sim/model/path", "Models/Geometry/glider.ac");
98   string texture_path = fgGetString("/sim/model/texture-path");
99   if( texture_path.size() ) {
100       SGPath temp_path;
101       if ( !ulIsAbsolutePathName( texture_path.c_str() ) ) {
102           temp_path = globals->get_fg_root();
103           temp_path.append( SGPath( path ).dir() );
104           temp_path.append( texture_path );
105           _fgLoaderOptions.livery_path = temp_path.str();
106       } else
107           _fgLoaderOptions.livery_path = texture_path;
108   }
109   try {
110     ssgBranch *model = fgLoad3DModelPanel( globals->get_fg_root(),
111                                            path,
112                                            globals->get_props(),
113                                            globals->get_sim_time_sec() );
114     _aircraft->init( model );
115   } catch (const sg_exception &ex) {
116     SG_LOG(SG_GENERAL, SG_ALERT, "Failed to load aircraft from " << path);
117     SG_LOG(SG_GENERAL, SG_ALERT, "(Falling back to glider.ac.)");
118     ssgBranch *model = fgLoad3DModelPanel( globals->get_fg_root(),
119                                            "Models/Geometry/glider.ac",
120                                            globals->get_props(),
121                                            globals->get_sim_time_sec() );
122     _aircraft->init( model );
123   }
124   _scene->addKid(_aircraft->getSceneGraph());
125   _selector->addKid(_aircraft->getSceneGraph());
126   globals->get_scenery()->get_aircraft_branch()->addKid(_selector);
127
128   // Register that one at the scenery manager
129   globals->get_scenery()->register_placement_transform(_aircraft->getTransform());
130   ssgSetCurrentOptions( currLoaderOptions );
131 }
132
133 void 
134 FGAircraftModel::bind ()
135 {
136   // No-op
137 }
138
139 void 
140 FGAircraftModel::unbind ()
141 {
142   // No-op
143 }
144
145 void
146 FGAircraftModel::update (double dt)
147 {
148   int view_number = globals->get_viewmgr()->get_current();
149   int is_internal = fgGetBool("/sim/current-view/internal");
150
151   if (view_number == 0 && !is_internal) {
152     _aircraft->setVisible(false);
153   } else {
154     _aircraft->setVisible(true);
155   }
156
157   _aircraft->setPosition(fgGetDouble("/position/longitude-deg"),
158                          fgGetDouble("/position/latitude-deg"),
159                          fgGetDouble("/position/altitude-ft"));
160   _aircraft->setOrientation(fgGetDouble("/orientation/roll-deg"),
161                             fgGetDouble("/orientation/pitch-deg"),
162                             fgGetDouble("/orientation/heading-deg"));
163   _aircraft->update();
164 }
165
166 void
167 FGAircraftModel::draw ()
168 {
169                                 // OK, now adjust the clip planes and draw
170                                 // FIXME: view number shouldn't be 
171                                 // hard-coded.
172   bool is_internal = globals->get_current_view()->getInternal();
173   if (_aircraft->getVisible() && is_internal) {
174     glClearDepth(1);
175     glClear(GL_DEPTH_BUFFER_BIT);
176     FGRenderer::setNearFar(_nearplane, _farplane);
177     ssgCullAndDraw(_scene);
178     _selector->select(0);
179   } else {
180     _selector->select(1);
181     // in external view the shadows are drawn before the transparent parts of the ac
182     _scene->setTravCallback( SSG_CALLBACK_POSTTRAV, SGShadowVolume::ACpostTravCB);
183     ssgCullAndDraw(_scene);
184     _scene->setTravCallback( SSG_CALLBACK_POSTTRAV, 0);
185   }
186
187 }
188
189 // end of model.cxx