]> git.mxchange.org Git - flightgear.git/commitdiff
Removed the FG3DModel class and replaced it with fgLoad3DModel.
authordavid <david>
Wed, 7 Aug 2002 01:34:49 +0000 (01:34 +0000)
committerdavid <david>
Wed, 7 Aug 2002 01:34:49 +0000 (01:34 +0000)
Animations are now contained within the scene graph itself and are
updated whenever the graph is traversed -- that saves time by not
updating animations not currently in sight, and it allows animations
to be used for static objects and random objects as well.

Added new FGModelLoader and FGTextureLoader classes.  These are intern
tables for models, to guarantee (mostly) that no model is loaded more
than once.  FGTextureLoader is not yet used anywhere, but
FGModelLoader is now in place everywhere that ssgLoad* used to be
used (thus adding the ability to use animations).

In the future, FGModelLoader will add some interesting functionality,
including the ability to reload 3D models on the fly.

13 files changed:
src/ATC/AILocalTraffic.cxx
src/Main/globals.hxx
src/Main/main.cxx
src/Model/Makefile.am
src/Model/acmodel.cxx
src/Model/loader.cxx [new file with mode: 0644]
src/Model/loader.hxx [new file with mode: 0644]
src/Model/model.cxx
src/Model/model.hxx
src/Model/modelmgr.cxx
src/NetworkOLK/net_send.cxx
src/Objects/newmat.cxx
src/Scenery/tilemgr.cxx

index d95d929d65c54d9f1c48651da06562076b403c42..a705d753dea9575cf037ea4592cbf9476796b88f 100644 (file)
@@ -28,6 +28,7 @@
 ******************************************************************/
 
 #include <Main/globals.hxx>
+#include <Model/loader.hxx>
 //#include <simgear/constants.h>
 #include <simgear/math/point3d.hxx>
 #include <simgear/math/sg_geodesy.hxx>
@@ -48,12 +49,11 @@ FGAILocalTraffic::~FGAILocalTraffic() {
 void FGAILocalTraffic::Init() {
     // Hack alert - Hardwired path!!
     string planepath = "Aircraft/c172/Models/c172-dpm.ac";
-    SGPath path = globals->get_fg_root();
-    path.append(planepath);
-    ssgTexturePath((char*)path.dir().c_str());
-    model = ssgLoad((char*)planepath.c_str());
+    model = globals->get_model_loader()->load_model(planepath);
     if (model == 0) {
-       model = ssgLoad((char*)"Models/Geometry/glider.ac");
+       model =
+            globals->get_model_loader()
+            ->load_model("Models/Geometry/glider.ac");
        if (model == 0)
            cout << "Failed to load an aircraft model in AILocalTraffic\n";
     } else {
index 438c6ec65e73b0626d1d5caa70e6cfd7266dadb1..50123defc1a7acda5f1c6b37f3c6d508b4852411 100644 (file)
@@ -65,6 +65,8 @@ class FGViewer;
 class FGATCMgr;
 class FGATCDisplay;
 class FGAIMgr;
+class FGModelLoader;
+class FGTextureLoader;
 class FGAircraftModel;
 class FGModelMgr;
 class FGScenery;
@@ -156,6 +158,10 @@ private:
 
     SGCommandMgr *commands;
 
+    FGModelLoader * model_loader;
+
+    FGTextureLoader * texture_loader;
+
     FGAircraftModel *acmodel;
 
     FGModelMgr * model_mgr;
@@ -256,6 +262,18 @@ public:
 
     inline SGCommandMgr *get_commands () { return commands; }
 
+    inline FGModelLoader * get_model_loader () { return model_loader; }
+
+    inline void set_model_loader (FGModelLoader * loader) {
+        model_loader = loader;
+    }
+
+    inline FGTextureLoader * get_texture_loader () { return texture_loader; }
+
+    inline void set_texture_loader (FGTextureLoader * loader) {
+        texture_loader = loader;
+    }
+
     inline FGAircraftModel *get_aircraft_model () { return acmodel; }
 
     inline void set_aircraft_model (FGAircraftModel * model)
index 765997437fb01626852b486c909992212b1c8720..a28675965a4479d09e6dbe5a3a2dc5d71902fe86 100644 (file)
@@ -100,8 +100,9 @@ SG_USING_STD(endl);
 #include <FDM/UIUCModel/uiuc_aircraftdir.h>
 #include <GUI/gui.h>
 #include <Model/acmodel.hxx>
-#include <Model/modelmgr.hxx>
+#include <Model/loader.hxx>
 #include <Model/model.hxx>
+#include <Model/modelmgr.hxx>
 #include <Main/location.hxx>
 #ifdef FG_NETWORK_OLK
 #include <NetworkOLK/network.h>
@@ -1543,6 +1544,8 @@ int mainLoop( int argc, char **argv ) {
     // Initialize the general model subsystem.
     ////////////////////////////////////////////////////////////////////
 
+    globals->set_model_loader(new FGModelLoader);
+    globals->set_texture_loader(new FGTextureLoader);
     globals->set_model_mgr(new FGModelMgr);
     globals->get_model_mgr()->init();
     globals->get_model_mgr()->bind();
@@ -1744,7 +1747,8 @@ void fgLoadDCS(void) {
                 // instance of the last object.
 
                 if ( strcmp(obj_filename,"repeat") != 0) {
-                    ship_obj = ssgLoad( obj_filename );
+                    ship_obj =
+                        globals->get_model_loader()->load_model( obj_filename );
                 }
       
                 if ( ship_obj != NULL ) {
index e932518fef823e0811dbeed53db5ad0fc87d08b6..7ed105849690e9a244fd92c45d7ce435e0bc9386 100644 (file)
@@ -1,6 +1,7 @@
 noinst_LIBRARIES = libModel.a
 
-libModel_a_SOURCES = model.cxx model.hxx \
+libModel_a_SOURCES = loader.cxx loader.hxx \
+                    model.cxx model.hxx \
                      modelmgr.cxx modelmgr.hxx \
                      acmodel.cxx acmodel.hxx \
                      panelnode.cxx panelnode.hxx
index 9e9dd6dc0fc745c1164c2b143bbe80073e3409f0..786a6ba0775872ccbb6a08f5721f34a59c7f4f9f 100644 (file)
@@ -94,7 +94,7 @@ FGAircraftModel::update (double dt)
   _aircraft->setOrientation(fgGetDouble("/orientation/roll-deg"),
                            fgGetDouble("/orientation/pitch-deg"),
                            fgGetDouble("/orientation/heading-deg"));
-  _aircraft->update(dt);
+  _aircraft->update();
 
 }
 
diff --git a/src/Model/loader.cxx b/src/Model/loader.cxx
new file mode 100644 (file)
index 0000000..0e0ccf4
--- /dev/null
@@ -0,0 +1,104 @@
+// loader.cxx - implement SSG model and texture loaders.
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <simgear/compiler.h>
+#include <simgear/misc/props.hxx>
+
+#include "loader.hxx"
+#include "model.hxx"
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGSSGLoader.
+////////////////////////////////////////////////////////////////////////
+
+FGSSGLoader::FGSSGLoader ()
+{
+    // no op
+}
+
+FGSSGLoader::~FGSSGLoader ()
+{
+    map<string, ssgBase *>::iterator it = _table.begin();
+    while (it != _table.end()) {
+        it->second->deRef();
+        _table.erase(it);
+    }
+}
+
+void
+FGSSGLoader::flush ()
+{
+    map<string, ssgBase *>::iterator it = _table.begin();
+    while (it != _table.end()) {
+        ssgBase * item = it->second;
+                                // If there is only one reference, it's
+                                // ours; no one else is using the item.
+        if (item->getRef() == 1) {
+            item->deRef();
+            _table.erase(it);
+        }
+        it++;
+    }
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGModelLoader.
+////////////////////////////////////////////////////////////////////////
+
+FGModelLoader::FGModelLoader ()
+{
+}
+
+FGModelLoader::~FGModelLoader ()
+{
+}
+
+ssgEntity *
+FGModelLoader::load_model (const string &path)
+{
+                                // FIXME: normalize path to
+                                // avoid duplicates.
+    map<string, ssgBase *>::iterator it = _table.find(path);
+    if (it == _table.end()) {
+        _table[path] = fgLoad3DModel((char *)path.c_str());
+        it = _table.find(path);
+        it->second->ref();      // add one reference to keep it around
+    }
+    return (ssgEntity *)it->second;
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of FGTextureLoader.
+////////////////////////////////////////////////////////////////////////
+
+FGTextureLoader::FGTextureLoader ()
+{
+}
+
+FGTextureLoader::~FGTextureLoader ()
+{
+}
+
+ssgTexture *
+FGTextureLoader::load_texture (const string &path)
+{
+    map<string, ssgBase *>::iterator it = _table.find(path);
+    if (it == _table.end()) {
+        _table[path] = new ssgTexture((char *)path.c_str()); // FIXME wrapu/v
+        it = _table.find(path);
+        it->second->ref();      // add one reference to keep it around
+    }
+    return (ssgTexture *)it->second;
+}
+
+
+// end of loader.cxx
diff --git a/src/Model/loader.hxx b/src/Model/loader.hxx
new file mode 100644 (file)
index 0000000..bbacbec
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __MODEL_LOADER_HXX
+#define __MODEL_LOADER_HXX 1
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include <simgear/compiler.h>  // for SG_USING_STD
+
+#include <map>
+SG_USING_STD(map);
+
+#include <string>
+SG_USING_STD(string);
+
+#include <plib/ssg.h>
+
+
+/**
+ * Base class for loading and managing SSG things.
+ */
+class FGSSGLoader
+{
+public:
+    FGSSGLoader ();
+    virtual ~FGSSGLoader ();
+    virtual void flush ();
+protected:
+    map<string,ssgBase *> _table;
+};
+
+
+/**
+ * Class for loading and managing models with XML wrappers.
+ */
+class FGModelLoader : public FGSSGLoader
+{
+public:
+    FGModelLoader ();
+    virtual ~FGModelLoader ();
+
+    virtual ssgEntity * load_model (const string &path);
+};
+
+
+/**
+ * Class for loading and managing textures.
+ */
+class FGTextureLoader : public FGSSGLoader
+{
+public:
+    FGTextureLoader ();
+    virtual ~FGTextureLoader ();
+
+    virtual ssgTexture * load_texture (const string &path);
+};
+
+#endif
index 8e20a812adff8e32479835c6409a782d033c4117..84fdc229c2a84b98e69fae072895408a65d99613 100644 (file)
 // Static utility functions.
 ////////////////////////////////////////////////////////////////////////
 
+/**
+ * Callback to update an animation.
+ */
+static int
+animation_callback (ssgEntity * entity, int mask)
+{
+    ((Animation *)entity->getUserData())->update();
+    return true;
+}
+
+
 /**
  * Locate a named SSG node in a branch.
  */
@@ -161,29 +172,60 @@ read_interpolation_table (const SGPropertyNode * props)
 }
 
 
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of FG3DModel
-////////////////////////////////////////////////////////////////////////
-
-FG3DModel::FG3DModel ()
-  : _model(0)
+static void
+make_animation (ssgBranch * model,
+                const char * object_name,
+                SGPropertyNode * node)
 {
+  Animation * animation = 0;
+  const char * type = node->getStringValue("type");
+  if (!strcmp("none", type)) {
+    animation = new NullAnimation(node);
+  } else if (!strcmp("range", type)) {
+    animation = new RangeAnimation(node);
+  } else if (!strcmp("billboard", type)) {
+    animation = new BillboardAnimation(node);
+  } else if (!strcmp("select", type)) {
+    animation = new SelectAnimation(node);
+  } else if (!strcmp("spin", type)) {
+    animation = new SpinAnimation(node);
+  } else if (!strcmp("rotate", type)) {
+    animation = new RotateAnimation(node);
+  } else if (!strcmp("translate", type)) {
+    animation = new TranslateAnimation(node);
+  } else {
+    animation = new NullAnimation(node);
+    SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type);
+  }
+
+  ssgEntity * object;
+  if (object_name != 0) {
+    object = find_named_node(model, object_name);
+    if (object == 0) {
+      SG_LOG(SG_INPUT, SG_WARN, "Object " << object_name << " not found");
+      delete animation;
+      animation = 0;
+    }
+  } else {
+    object = model;
+  }
+  
+  ssgBranch * branch = animation->getBranch();
+  splice_branch(branch, object);
+  branch->setUserData(animation);
+  branch->setTravCallback(SSG_CALLBACK_PRETRAV, animation_callback);
 }
 
-FG3DModel::~FG3DModel ()
-{
-  // since the nodes are attached to the scene graph, they'll be
-  // deleted automatically
 
-  unsigned int i;
-  for (i = 0; i < _animations.size(); i++)
-    delete _animations[i];
-}
+\f
+////////////////////////////////////////////////////////////////////////
+// Global functions.
+////////////////////////////////////////////////////////////////////////
 
-void 
-FG3DModel::init (const string &path)
+ssgBranch *
+fgLoad3DModel (const string &path)
 {
+  ssgBranch * model = 0;
   SGPropertyNode props;
 
                                 // Load the 3D aircraft object itself
@@ -198,23 +240,23 @@ FG3DModel::init (const string &path)
       modelpath = modelpath.dir();
       modelpath.append(props.getStringValue("/path"));
     } else {
-      if (_model == 0)
-       _model = new ssgBranch;
+      if (model == 0)
+       model = new ssgBranch;
     }
   }
 
                                 // Assume that textures are in
                                 // the same location as the XML file.
-  if (_model == 0) {
+  if (model == 0) {
     ssgTexturePath((char *)xmlpath.dir().c_str());
-    _model = (ssgBranch *)ssgLoad((char *)modelpath.c_str());
-    if (_model == 0)
+    model = (ssgBranch *)ssgLoad((char *)modelpath.c_str());
+    if (model == 0)
       throw sg_exception("Failed to load 3D model");
   }
 
                                 // Set up the alignment node
   ssgTransform * align = new ssgTransform;
-  align->addKid(_model);
+  align->addKid(model);
   sgMat4 res_matrix;
   make_offsets_matrix(&res_matrix,
                      props.getFloatValue("/offsets/heading-deg", 0.0),
@@ -232,15 +274,10 @@ FG3DModel::init (const string &path)
     vector<SGPropertyNode_ptr> name_nodes =
       animation_nodes[i]->getChildren("object-name");
     if (name_nodes.size() < 1) {
-      Animation * animation = make_animation(0, animation_nodes[i]);
-      if (animation != 0)
-       _animations.push_back(animation);
+        make_animation(model, 0, animation_nodes[i]);
     } else {
       for (unsigned int j = 0; j < name_nodes.size(); j++) {
-        Animation * animation =
-          make_animation(name_nodes[j]->getStringValue(), animation_nodes[i]);
-        if (animation != 0)
-          _animations.push_back(animation);
+        make_animation(model, name_nodes[j]->getStringValue(), animation_nodes[i]);
       }
     }
   }
@@ -250,7 +287,7 @@ FG3DModel::init (const string &path)
   for (i = 0; i < panel_nodes.size(); i++) {
     printf("Reading a panel in model.cxx\n");
     FGPanelNode * panel = new FGPanelNode(panel_nodes[i]);
-    _model->addKid(panel);
+    model->addKid(panel);
   }
 
                                // Load sub-models
@@ -267,255 +304,157 @@ FG3DModel::init (const string &path)
                        node->getFloatValue("offsets/y-m", 0.0),
                        node->getFloatValue("offsets/z-m", 0.0));
     align->setTransform(res_matrix);
-    FG3DModel * kid = new FG3DModel;
-    kid->init(node->getStringValue("path"));
-    align->addKid(kid->getSceneGraph());
-    _model->addKid(align);
-    _children.push_back(kid);
-  }
-}
-
-void
-FG3DModel::update (double dt)
-{
-  unsigned int i;
-
-  for (i = 0; i < _children.size(); i++)
-    _children[i]->update(dt);
-  for (i = 0; i < _animations.size(); i++)
-    _animations[i]->update(dt);
-}
 
-FG3DModel::Animation *
-FG3DModel::make_animation (const char * object_name,
-                          SGPropertyNode * node)
-{
-  Animation * animation = 0;
-  const char * type = node->getStringValue("type");
-  if (!strcmp("none", type)) {
-    animation = new NullAnimation();
-  } else if (!strcmp("range", type)) {
-    animation = new RangeAnimation();
-  } else if (!strcmp("billboard", type)) {
-    animation = new BillboardAnimation();
-  } else if (!strcmp("select", type)) {
-    animation = new SelectAnimation();
-  } else if (!strcmp("spin", type)) {
-    animation = new SpinAnimation();
-  } else if (!strcmp("rotate", type)) {
-    animation = new RotateAnimation();
-  } else if (!strcmp("translate", type)) {
-    animation = new TranslateAnimation();
-  } else {
-    animation = new NullAnimation();
-    SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type);
+    ssgBranch * kid = fgLoad3DModel(node->getStringValue("path"));
+    align->addKid(kid);
+    model->addKid(align);
   }
 
-  ssgEntity * object;
-  if (object_name != 0) {
-    object = find_named_node(_model, object_name);
-    if (object == 0) {
-      SG_LOG(SG_INPUT, SG_WARN, "Object " << object_name << " not found");
-      delete animation;
-      animation = 0;
-    }
-  } else {
-    object = _model;
-  }
-
-  if (animation != 0)
-    animation->init(object, node);
-  return animation;
+  return model;
 }
 
 
 \f
 ////////////////////////////////////////////////////////////////////////
-// Implementation of FG3DModel::Animation
+// Implementation of Animation
 ////////////////////////////////////////////////////////////////////////
 
-FG3DModel::Animation::Animation ()
+Animation::Animation (SGPropertyNode_ptr props, ssgBranch * branch)
+    : _branch(branch)
 {
+    _branch->setName(props->getStringValue("name", 0));
 }
 
-FG3DModel::Animation::~Animation ()
+Animation::~Animation ()
 {
 }
 
 
 \f
 ////////////////////////////////////////////////////////////////////////
-// Implementation of FG3DModel::NullAnimation
+// Implementation of NullAnimation
 ////////////////////////////////////////////////////////////////////////
 
-FG3DModel::NullAnimation::NullAnimation ()
-  : _branch(new ssgBranch)
-{
-}
-
-FG3DModel::NullAnimation::~NullAnimation ()
+NullAnimation::NullAnimation (SGPropertyNode_ptr props)
+  : Animation(props, new ssgBranch)
 {
-  _branch = 0;
 }
 
-void
-FG3DModel::NullAnimation::init (ssgEntity * object,
-                                      SGPropertyNode * props)
+NullAnimation::~NullAnimation ()
 {
-  splice_branch(_branch, object);
-  _branch->setName(props->getStringValue("name", 0));
 }
 
 void
-FG3DModel::NullAnimation::update (double dt)
+NullAnimation::update ()
 {
 }
 
 
 \f
 ////////////////////////////////////////////////////////////////////////
-// Implementation of FG3DModel::RangeAnimation
+// Implementation of RangeAnimation
 ////////////////////////////////////////////////////////////////////////
 
-FG3DModel::RangeAnimation::RangeAnimation ()
-  : _branch(new ssgRangeSelector)
-{
-}
-
-FG3DModel::RangeAnimation::~RangeAnimation ()
+RangeAnimation::RangeAnimation (SGPropertyNode_ptr props)
+  : Animation(props, new ssgRangeSelector)
 {
-  _branch = 0;
+    float ranges[] = { props->getFloatValue("min-m", 0),
+                       props->getFloatValue("max-m", 5000) };
+    ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
+                       
 }
 
-void
-FG3DModel::RangeAnimation::init (ssgEntity * object,
-                                      SGPropertyNode * props)
+RangeAnimation::~RangeAnimation ()
 {
-  float ranges[2];
-  splice_branch(_branch, object);
-  _branch->setName(props->getStringValue("name", 0));
-  ranges[0] = props->getFloatValue("min-m", 0);
-  ranges[1] = props->getFloatValue("max-m", 5000);
-  _branch->setRanges(ranges, 2);
 }
 
 void
-FG3DModel::RangeAnimation::update (double dt)
+RangeAnimation::update ()
 {
 }
 
 
 \f
 ////////////////////////////////////////////////////////////////////////
-// Implementation of FG3DModel::BillboardAnimation
+// Implementation of BillboardAnimation
 ////////////////////////////////////////////////////////////////////////
 
-FG3DModel::BillboardAnimation::BillboardAnimation ()
-  : _branch(0)
-{
-  // Note: we cannot allocate the branch until we know whether
-  // it can rotate around the x axis as well as the z axis.
-}
-
-FG3DModel::BillboardAnimation::~BillboardAnimation ()
+BillboardAnimation::BillboardAnimation (SGPropertyNode_ptr props)
+    : Animation(props, new ssgCutout(props->getBoolValue("spherical", true)))
 {
-  _branch = 0;
 }
 
-void
-FG3DModel::BillboardAnimation::init (ssgEntity * object,
-                                    SGPropertyNode * props)
+BillboardAnimation::~BillboardAnimation ()
 {
-  _branch = new ssgCutout(props->getBoolValue("spherical", true));
-  splice_branch(_branch, object);
-  _branch->setName(props->getStringValue("name", 0));
 }
 
 void
-FG3DModel::BillboardAnimation::update (double dt)
+BillboardAnimation::update ()
 {
 }
 
 
 \f
 ////////////////////////////////////////////////////////////////////////
-// Implementation of FG3DModel::SelectAnimation
+// Implementation of SelectAnimation
 ////////////////////////////////////////////////////////////////////////
 
-FG3DModel::SelectAnimation::SelectAnimation ()
-  : _condition(0),
-    _selector(new ssgSelector)
+SelectAnimation::SelectAnimation (SGPropertyNode_ptr props)
+  : Animation(props, new ssgSelector),
+    _condition(0)
 {
+  SGPropertyNode * node = props->getChild("condition");
+  if (node != 0)
+    _condition = fgReadCondition(node);
 }
 
-FG3DModel::SelectAnimation::~SelectAnimation ()
+SelectAnimation::~SelectAnimation ()
 {
   delete _condition;
-  _selector = 0;
-}
-
-void
-FG3DModel::SelectAnimation::init (ssgEntity * object,
-                                      SGPropertyNode * props)
-{
-  splice_branch(_selector, object);
-  _selector->setName(props->getStringValue("name", 0));
-  SGPropertyNode * node = props->getChild("condition");
-  if (node != 0) {
-    _condition = fgReadCondition(node);
-  }
 }
 
 void
-FG3DModel::SelectAnimation::update (double dt)
+SelectAnimation::update ()
 {
   if (_condition != 0 && _condition->test()) 
-    _selector->select(0xffff);
+      ((ssgSelector *)_branch)->select(0xffff);
   else
-    _selector->select(0x0000);
+      ((ssgSelector *)_branch)->select(0x0000);
 }
 
 
 \f
 ////////////////////////////////////////////////////////////////////////
-// Implementation of FG3DModel::SpinAnimation
+// Implementation of SpinAnimation
 ////////////////////////////////////////////////////////////////////////
 
-FG3DModel::SpinAnimation::SpinAnimation ()
-  : _prop(0),
-    _factor(0),
-    _position_deg(0),
-    _transform(new ssgTransform)
+SpinAnimation::SpinAnimation (SGPropertyNode_ptr props)
+  : Animation(props, new ssgTransform),
+    _prop(fgGetNode(props->getStringValue("property", "/null"), true)),
+    _factor(props->getDoubleValue("factor", 1.0)),
+    _position_deg(props->getDoubleValue("starting-position-deg", 0)),
+    _last_time_sec(globals->get_sim_time_sec())
 {
+    _center[0] = props->getFloatValue("center/x-m", 0);
+    _center[1] = props->getFloatValue("center/y-m", 0);
+    _center[2] = props->getFloatValue("center/z-m", 0);
+    _axis[0] = props->getFloatValue("axis/x", 0);
+    _axis[1] = props->getFloatValue("axis/y", 0);
+    _axis[2] = props->getFloatValue("axis/z", 0);
+    sgNormalizeVec3(_axis);
 }
 
-FG3DModel::SpinAnimation::~SpinAnimation ()
+SpinAnimation::~SpinAnimation ()
 {
-  _transform = 0;
-}
-
-void
-FG3DModel::SpinAnimation::init (ssgEntity * object,
-                                      SGPropertyNode * props)
-{
-                                // Splice in the new transform node
-  splice_branch(_transform, object);
-  _transform->setName(props->getStringValue("name", 0));
-  _prop = fgGetNode(props->getStringValue("property", "/null"), true);
-  _factor = props->getDoubleValue("factor", 1.0);
-  _position_deg = props->getDoubleValue("starting-position-deg", 0);
-  _center[0] = props->getFloatValue("center/x-m", 0);
-  _center[1] = props->getFloatValue("center/y-m", 0);
-  _center[2] = props->getFloatValue("center/z-m", 0);
-  _axis[0] = props->getFloatValue("axis/x", 0);
-  _axis[1] = props->getFloatValue("axis/y", 0);
-  _axis[2] = props->getFloatValue("axis/z", 0);
-  sgNormalizeVec3(_axis);
 }
 
 void
-FG3DModel::SpinAnimation::update (double dt)
+SpinAnimation::update ()
 {
+  double sim_time = globals->get_sim_time_sec();
+  double dt = sim_time - _last_time_sec;
+  _last_time_sec = sim_time;
+
   float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
   _position_deg += (dt * velocity_rpms * 360);
   while (_position_deg < 0)
@@ -523,55 +462,27 @@ FG3DModel::SpinAnimation::update (double dt)
   while (_position_deg >= 360.0)
     _position_deg -= 360.0;
   set_rotation(_matrix, _position_deg, _center, _axis);
-  _transform->setTransform(_matrix);
+  ((ssgTransform *)_branch)->setTransform(_matrix);
 }
 
 
 \f
 ////////////////////////////////////////////////////////////////////////
-// Implementation of FG3DModel::RotateAnimation
+// Implementation of RotateAnimation
 ////////////////////////////////////////////////////////////////////////
 
-FG3DModel::RotateAnimation::RotateAnimation ()
-  : _prop(0),
-    _offset_deg(0.0),
-    _factor(1.0),
-    _table(0),
-    _has_min(false),
-    _min_deg(0.0),
-    _has_max(false),
-    _max_deg(1.0),
-    _position_deg(0.0),
-    _transform(new ssgTransform)
-{
-}
-
-FG3DModel::RotateAnimation::~RotateAnimation ()
+RotateAnimation::RotateAnimation (SGPropertyNode_ptr props)
+    : Animation(props, new ssgTransform),
+      _prop(fgGetNode(props->getStringValue("property", "/null"), true)),
+      _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
+      _factor(props->getDoubleValue("factor", 1.0)),
+      _table(read_interpolation_table(props)),
+      _has_min(props->hasValue("min-deg")),
+      _min_deg(props->getDoubleValue("min-deg")),
+      _has_max(props->hasValue("max-deg")),
+      _max_deg(props->getDoubleValue("max-deg")),
+      _position_deg(props->getDoubleValue("starting-position-deg", 0))
 {
-  delete _table;
-  _transform = 0;
-}
-
-void
-FG3DModel::RotateAnimation::init (ssgEntity * object,
-                                 SGPropertyNode * props)
-{
-                                // Splice in the new transform node
-  splice_branch(_transform, object);
-  _transform->setName(props->getStringValue("name", 0));
-  _prop = fgGetNode(props->getStringValue("property", "/null"), true);
-  _offset_deg = props->getDoubleValue("offset-deg", 0.0);
-  _factor = props->getDoubleValue("factor", 1.0);
-  _table = read_interpolation_table(props);
-  if (props->hasValue("min-deg")) {
-    _has_min = true;
-    _min_deg = props->getDoubleValue("min-deg");
-  }
-  if (props->hasValue("max-deg")) {
-    _has_max = true;
-    _max_deg = props->getDoubleValue("max-deg");
-  }
-  _position_deg = props->getDoubleValue("starting-position-deg", 0);
   _center[0] = props->getFloatValue("center/x-m", 0);
   _center[1] = props->getFloatValue("center/y-m", 0);
   _center[2] = props->getFloatValue("center/z-m", 0);
@@ -581,8 +492,13 @@ FG3DModel::RotateAnimation::init (ssgEntity * object,
   sgNormalizeVec3(_axis);
 }
 
+RotateAnimation::~RotateAnimation ()
+{
+  delete _table;
+}
+
 void
-FG3DModel::RotateAnimation::update (double dt)
+RotateAnimation::update ()
 {
   if (_table == 0) {
     _position_deg = (_prop->getDoubleValue() + _offset_deg) * _factor;
@@ -594,63 +510,40 @@ FG3DModel::RotateAnimation::update (double dt)
     _position_deg = _table->interpolate(_prop->getDoubleValue());
   }
   set_rotation(_matrix, _position_deg, _center, _axis);
-  _transform->setTransform(_matrix);
+  ((ssgTransform *)_branch)->setTransform(_matrix);
 }
 
 
 \f
 ////////////////////////////////////////////////////////////////////////
-// Implementation of FG3DModel::TranslateAnimation
+// Implementation of TranslateAnimation
 ////////////////////////////////////////////////////////////////////////
 
-FG3DModel::TranslateAnimation::TranslateAnimation ()
-  : _prop(0),
-    _offset_m(0.0),
-    _factor(1.0),
-    _table(0),
-    _has_min(false),
-    _min_m(0.0),
-    _has_max(false),
-    _max_m(1.0),
-    _position_m(0.0),
-    _transform(new ssgTransform)
-{
-}
-
-FG3DModel::TranslateAnimation::~TranslateAnimation ()
+TranslateAnimation::TranslateAnimation (SGPropertyNode_ptr props)
+  : Animation(props, new ssgTransform),
+    _prop(fgGetNode(props->getStringValue("property", "/null"), true)),
+    _offset_m(props->getDoubleValue("offset-m", 0.0)),
+    _factor(props->getDoubleValue("factor", 1.0)),
+    _table(read_interpolation_table(props)),
+    _has_min(props->hasValue("min-m")),
+    _min_m(props->getDoubleValue("min-m")),
+    _has_max(props->hasValue("max-m")),
+    _max_m(props->getDoubleValue("max-m")),
+    _position_m(props->getDoubleValue("starting-position-m", 0))
 {
-  delete _table;
-  _transform = 0;
-}
-
-void
-FG3DModel::TranslateAnimation::init (ssgEntity * object,
-                                    SGPropertyNode * props)
-{
-                                // Splice in the new transform node
-  splice_branch(_transform, object);
-  _transform->setName(props->getStringValue("name", 0));
-  _prop = fgGetNode(props->getStringValue("property", "/null"), true);
-  _offset_m = props->getDoubleValue("offset-m", 0.0);
-  _factor = props->getDoubleValue("factor", 1.0);
-  _table = read_interpolation_table(props);
-  if (props->hasValue("min-m")) {
-    _has_min = true;
-    _min_m = props->getDoubleValue("min-m");
-  }
-  if (props->hasValue("max-m")) {
-    _has_max = true;
-    _max_m = props->getDoubleValue("max-m");
-  }
-  _position_m = props->getDoubleValue("starting-position-m", 0);
   _axis[0] = props->getFloatValue("axis/x", 0);
   _axis[1] = props->getFloatValue("axis/y", 0);
   _axis[2] = props->getFloatValue("axis/z", 0);
   sgNormalizeVec3(_axis);
 }
 
+TranslateAnimation::~TranslateAnimation ()
+{
+  delete _table;
+}
+
 void
-FG3DModel::TranslateAnimation::update (double dt)
+TranslateAnimation::update ()
 {
   if (_table == 0) {
     _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
@@ -662,7 +555,7 @@ FG3DModel::TranslateAnimation::update (double dt)
     _position_m = _table->interpolate(_prop->getDoubleValue());
   }
   set_translation(_matrix, _position_m, _axis);
-  _transform->setTransform(_matrix);
+  ((ssgTransform *)_branch)->setTransform(_matrix);
 }
 
 
@@ -672,8 +565,7 @@ FG3DModel::TranslateAnimation::update (double dt)
 ////////////////////////////////////////////////////////////////////////
 
 FGModelPlacement::FGModelPlacement ()
-  : _model(new FG3DModel),
-    _lon_deg(0),
+  : _lon_deg(0),
     _lat_deg(0),
     _elev_ft(0),
     _roll_deg(0),
@@ -687,24 +579,21 @@ FGModelPlacement::FGModelPlacement ()
 
 FGModelPlacement::~FGModelPlacement ()
 {
-  delete _model;
-  delete _selector;
 }
 
 void
 FGModelPlacement::init (const string &path)
 {
-  _model->init(path);
-  _position->addKid(_model->getSceneGraph());
+  ssgBranch * model = fgLoad3DModel(path);
+  if (model != 0)
+      _position->addKid(model);
   _selector->addKid(_position);
   _selector->clrTraversalMaskBits(SSGTRAV_HOT);
 }
 
 void
-FGModelPlacement::update (double dt)
+FGModelPlacement::update ()
 {
-  _model->update(dt);
-
   _location->setPosition( _lon_deg, _lat_deg, _elev_ft );
   _location->setOrientation( _roll_deg, _pitch_deg, _heading_deg );
 
index cc5142519d7029adcacd476a60e18d8d1c7ef7e8..edfbfdae0d7d26751f80f2ae440f03b2e7c623cd 100644 (file)
@@ -15,6 +15,7 @@
 SG_USING_STD(vector);
 
 #include <plib/sg.h>
+#include <plib/ssg.h>
 
 
 // Don't pull in the headers, since we don't need them here.
@@ -40,210 +41,182 @@ class FGLocation;
 #endif
 
 
-class FG3DModel
-{
-public:
-
-  FG3DModel ();
-  virtual ~FG3DModel ();
-
-  virtual void init (const string &path);
-  virtual void update (double dt);
-
-  virtual ssgEntity * getSceneGraph () const { return (ssgEntity *)_model; }
-
-private:
+/**
+ * Load a 3D model with or without XML wrapper.
+ *
+ * If the path ends in ".xml", then it will be used as a property-
+ * list wrapper to add animations to the model.
+ *
+ * Subsystems should not normally invoke this function directly;
+ * instead, they should use the FGModelLoader declared in loader.hxx.
+ */
+ssgBranch * fgLoad3DModel (const string &path);
 
-  class Animation;
-  Animation * make_animation (const char * object_name, SGPropertyNode * node);
 
-                               // Child models.
-  vector<FG3DModel *> _children;
+\f
+//////////////////////////////////////////////////////////////////////
+// Animation classes
+//////////////////////////////////////////////////////////////////////
 
-                               // Animations
-  vector <Animation *> _animations;
-
-                               // Scene graph
-  ssgBranch * _model;
+/**
+ * Abstract base class for all animations.
+ */
+class Animation :  public ssgBase
+{
+public:
 
+  Animation (SGPropertyNode_ptr props, ssgBranch * branch);
 
-  \f
-  //////////////////////////////////////////////////////////////////////
-  // Internal classes for individual animations.
-  //////////////////////////////////////////////////////////////////////
+  virtual ~Animation ();
 
   /**
-   * Abstract base class for all animations.
+   * Get the SSG branch holding the animation.
    */
-  class Animation
-  {
-  public:
-
-    Animation ();
-
-    virtual ~Animation ();
-
-    /**
-     * Initialize the animation.
-     *
-     * @param object The object to animate.
-     * @param props The property node with configuration information.
-     */
-    virtual void init (ssgEntity * object, SGPropertyNode * props) = 0;
+  virtual ssgBranch * getBranch () { return _branch; }
 
+  /**
+   * Update the animation.
+   */
+  virtual void update () = 0;
 
-    /**
-     * Update the animation.
-     *
-     * @param dt The elapsed time in seconds since the last call.
-     */
-    virtual void update (double dt) = 0;
+protected:
 
-  };
+  ssgBranch * _branch;
 
+};
 
-  /**
-   * A no-op animation.
-   */
-  class NullAnimation : public Animation
-  {
-  public:
-    NullAnimation ();
-    virtual ~NullAnimation ();
-    virtual void init (ssgEntity * object, SGPropertyNode * props);
-    virtual void update (double dt);
-  private:
-    ssgBranch * _branch;
-  };
 
-  
-  /**
-   * A range, or level-of-detail (LOD) animation.
-   */
-  class RangeAnimation : public Animation
-  {
-  public:
-    RangeAnimation ();
-    virtual ~RangeAnimation ();
-    virtual void init (ssgEntity * object, SGPropertyNode * props);
-    virtual void update (double dt);
-  private:
-    ssgRangeSelector * _branch;
-  };
+/**
+ * A no-op animation.
+ */
+class NullAnimation : public Animation
+{
+public:
+  NullAnimation (SGPropertyNode_ptr props);
+  virtual ~NullAnimation ();
+  virtual void update ();
+};
 
 
-  /**
-   * Animation to turn and face the screen.
-   */
-  class BillboardAnimation : public Animation
-  {
-  public:
-    BillboardAnimation ();
-    virtual ~BillboardAnimation ();
-    virtual void init (ssgEntity * object, SGPropertyNode * props);
-    virtual void update (double dt);
-  private:
-    ssgCutout * _branch;
-  };
+/**
+ * A range, or level-of-detail (LOD) animation.
+ */
+class RangeAnimation : public Animation
+{
+public:
+  RangeAnimation (SGPropertyNode_ptr props);
+  virtual ~RangeAnimation ();
+  virtual void update ();
+};
 
 
-  /**
-   * Animation to select alternative versions of the same object.
-   */
-  class SelectAnimation : public Animation
-  {
-  public:
-    SelectAnimation ();
-    virtual ~SelectAnimation ();
-    virtual void init (ssgEntity * object, SGPropertyNode * props);
-    virtual void update (double dt);
-  private:
-    FGCondition * _condition;
-    ssgSelector * _selector;
-  };
+/**
+ * Animation to turn and face the screen.
+ */
+class BillboardAnimation : public Animation
+{
+public:
+  BillboardAnimation (SGPropertyNode_ptr props);
+  virtual ~BillboardAnimation ();
+  virtual void update ();
+};
 
 
-  /**
-   * Animation to spin an object around a center point.
-   *
-   * This animation rotates at a specific velocity.
-   */
-  class SpinAnimation : public Animation
-  {
-  public:
-    SpinAnimation ();
-    virtual ~SpinAnimation ();
-    virtual void init (ssgEntity * object, SGPropertyNode * props);
-    virtual void update (double dt);
-  private:
-    SGPropertyNode * _prop;
-    double _factor;
-    double _position_deg;
-    sgMat4 _matrix;
-    sgVec3 _center;
-    sgVec3 _axis;
-    ssgTransform * _transform;
-  };
+/**
+ * Animation to select alternative versions of the same object.
+ */
+class SelectAnimation : public Animation
+{
+public:
+  SelectAnimation (SGPropertyNode_ptr props);
+  virtual ~SelectAnimation ();
+  virtual void update ();
+private:
+  FGCondition * _condition;
+};
 
 
-  /**
-   * Animation to rotate an object around a center point.
-   *
-   * This animation rotates to a specific position.
-   */
-  class RotateAnimation : public Animation
-  {
-  public:
-    RotateAnimation ();
-    virtual ~RotateAnimation ();
-    virtual void init (ssgEntity * object, SGPropertyNode * props);
-    virtual void update (double dt);
-  private:
-    SGPropertyNode * _prop;
-    double _offset_deg;
-    double _factor;
-    SGInterpTable * _table;
-    bool _has_min;
-    double _min_deg;
-    bool _has_max;
-    double _max_deg;
-    double _position_deg;
-    sgMat4 _matrix;
-    sgVec3 _center;
-    sgVec3 _axis;
-    ssgTransform * _transform;
-  };
+/**
+ * Animation to spin an object around a center point.
+ *
+ * This animation rotates at a specific velocity.
+ */
+class SpinAnimation : public Animation
+{
+public:
+  SpinAnimation (SGPropertyNode_ptr props);
+  virtual ~SpinAnimation ();
+  virtual void update ();
+private:
+  SGPropertyNode * _prop;
+  double _factor;
+  double _position_deg;
+  double _last_time_sec;
+  sgMat4 _matrix;
+  sgVec3 _center;
+  sgVec3 _axis;
+};
 
 
-  /**
-   * Animation to slide along an axis.
-   */
-  class TranslateAnimation : public Animation
-  {
-  public:
-    TranslateAnimation ();
-    virtual ~TranslateAnimation ();
-    virtual void init (ssgEntity * object, SGPropertyNode * props);
-    virtual void update (double dt);
-  private:
-    SGPropertyNode * _prop;
-    double _offset_m;
-    double _factor;
-    SGInterpTable * _table;
-    bool _has_min;
-    double _min_m;
-    bool _has_max;
-    double _max_m;
-    double _position_m;
-    sgMat4 _matrix;
-    sgVec3 _axis;
-    ssgTransform * _transform;
-  };
+/**
+ * Animation to rotate an object around a center point.
+ *
+ * This animation rotates to a specific position.
+ */
+class RotateAnimation : public Animation
+{
+public:
+  RotateAnimation (SGPropertyNode_ptr props);
+  virtual ~RotateAnimation ();
+  virtual void update ();
+private:
+  SGPropertyNode * _prop;
+  double _offset_deg;
+  double _factor;
+  SGInterpTable * _table;
+  bool _has_min;
+  double _min_deg;
+  bool _has_max;
+  double _max_deg;
+  double _position_deg;
+  sgMat4 _matrix;
+  sgVec3 _center;
+  sgVec3 _axis;
+};
 
 
+/**
+ * Animation to slide along an axis.
+ */
+class TranslateAnimation : public Animation
+{
+public:
+  TranslateAnimation (SGPropertyNode_ptr props);
+  virtual ~TranslateAnimation ();
+  virtual void update ();
+private:
+  SGPropertyNode * _prop;
+  double _offset_m;
+  double _factor;
+  SGInterpTable * _table;
+  bool _has_min;
+  double _min_m;
+  bool _has_max;
+  double _max_m;
+  double _position_m;
+  sgMat4 _matrix;
+  sgVec3 _axis;
 };
 
 
+\f
+////////////////////////////////////////////////////////////////////////
+// Model placement.
+////////////////////////////////////////////////////////////////////////
+
+/**
+ * A wrapper for a model with a definite placement.
+ */
 class FGModelPlacement
 {
 public:
@@ -252,7 +225,7 @@ public:
   virtual ~FGModelPlacement ();
 
   virtual void init (const string &path);
-  virtual void update (double dt);
+  virtual void update ();
 
   virtual ssgEntity * getSceneGraph () { return (ssgEntity *)_selector; }
 
@@ -278,18 +251,16 @@ public:
   virtual void setPitchDeg (double pitch_deg);
   virtual void setHeadingDeg (double heading_deg);
   virtual void setOrientation (double roll_deg, double pitch_deg,
-                              double heading_deg);
+                               double heading_deg);
 
 private:
   
-  FG3DModel * _model;
-
-                               // Geodetic position
+                                // Geodetic position
   double _lon_deg;
   double _lat_deg;
   double _elev_ft;
 
-                               // Orientation
+                                // Orientation
   double _roll_deg;
   double _pitch_deg;
   double _heading_deg;
@@ -297,7 +268,7 @@ private:
   ssgSelector * _selector;
   ssgTransform * _position;
 
-                               // Location
+                                // Location
   FGLocation * _location;
 
 };
index ce15e6078c6b1a85ad659e98ca077d071cc92803..f3f7cc8e4f83468743796b888063a759354fa6f0 100644 (file)
@@ -120,7 +120,7 @@ FGModelMgr::update (double dt)
     if (instance->heading_deg_node != 0)
       model->setHeadingDeg(instance->heading_deg_node->getDoubleValue());
 
-    instance->model->update(dt);
+    instance->model->update();
   }
 }
 
index 2465d843ccdd069a40e205bae2cc898ca7fc1d02..78896882892bc705cbfbb964ecd44d821e428276 100644 (file)
@@ -42,6 +42,7 @@
 #include <plib/ssg.h>
 #include <Main/globals.hxx>
 #include <Main/viewmgr.hxx>
+#include <Model/loader.hxx>
 
 //#define printf //
 
@@ -162,7 +163,7 @@ struct list_ele *new_ele;
    new_ele->fgd_sel = new ssgSelector;
    new_ele->fgd_pos = new ssgTransform;
 
-   ssgEntity *fgd_obj = ssgLoadAC( "tuxcopter.ac" );
+   ssgEntity *fgd_obj = globals->get_model_loader()->load_model( "tuxcopter.ac" );
    fgd_obj->clrTraversalMaskBits( SSGTRAV_HOT );
    new_ele->fgd_pos->addKid( fgd_obj );
    new_ele->fgd_sel->addKid( new_ele->fgd_pos );
index 2700998303d460775b98d8bed5ead91417b01b8e..96288fe87a6b781ab5cd943d8796e1c4bbeb373a 100644 (file)
@@ -43,37 +43,15 @@ SG_USING_STD(map);
 
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
+#include <Model/loader.hxx>
 
 #include "newmat.hxx"
 
-\f
-////////////////////////////////////////////////////////////////////////
-// Local static variables.
-// FIXME: write a proper manager.
-////////////////////////////////////////////////////////////////////////
-
-// Objects already loaded (that can be reused).
-map<string,ssgEntity *> object_map;
-
-
 \f
 ////////////////////////////////////////////////////////////////////////
 // Local static functions.
 ////////////////////////////////////////////////////////////////////////
 
-// FIXME: this is totally evil and non-robust: it assumes that
-// entities will never be refcounted to 0 (which is safe for now).
-static ssgEntity *
-load_object (char * path)
-{
-  ssgEntity * object = object_map[path];
-  if (object == 0) {
-    object = ssgLoad(path);
-    object_map[path] = object;
-  }
-  return object;
-}
-
 /**
  * Internal method to test whether a file exists.
  *
@@ -154,28 +132,18 @@ FGNewMat::Object::load_models () const
                                // Load model only on demand
   if (!_models_loaded) {
     for (int i = 0; i < _paths.size(); i++) {
-
-// Original
-//      SGPath path = globals->get_fg_root();
-//      path.append(_paths[i]);
-//      ssgTexturePath((char *)path.dir().c_str());
-//      ssgEntity * entity = load_object((char *)path.c_str());
-
-// DCL
-      SGPath path = globals->get_fg_root();
-      SGPath modelPath = _paths[i];
-      path.append(_paths[i]);
-      ssgTexturePath((char *)path.dir().c_str());
-      ssgEntity * entity = load_object((char *)modelPath.c_str());
+      ssgEntity * entity = globals->get_model_loader()->load_model(_paths[i]);
       if (entity != 0) {
-        // entity->ref();
+                                // FIXME: this stuff can be handled
+                                // in the XML wrapper as well (at least,
+                                // the billboarding should be handled
+                                // there).
        float ranges[] = {0, _range_m};
        ssgRangeSelector * lod = new ssgRangeSelector;
         lod->ref();
         lod->setRanges(ranges, 2);
        if (_heading_type == HEADING_BILLBOARD) {
          ssgCutout * cutout = new ssgCutout(false);
-          // cutout->ref();
          cutout->addKid(entity);
          lod->addKid(cutout);
        } else {
@@ -183,7 +151,7 @@ FGNewMat::Object::load_models () const
        }
        _models.push_back(lod);
       } else {
-       SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << path.str());
+       SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << _paths[i]);
       }
     }
   }
index 767fcd8e57883da3074720a1d2e9c13ed2b407ac..8c3e6f548193543c1d32d5c5b664710d4653f482 100644 (file)
@@ -43,6 +43,7 @@
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
 #include <Main/viewer.hxx>
+#include <Model/loader.hxx>
 #include <Objects/obj.hxx>
 
 #include "newcache.hxx"
@@ -329,8 +330,7 @@ int FGTileMgr::update( double lon, double lat, double visibility_meters,
 #endif
        
        ssgTexturePath( (char *)(dm->get_texture_path().c_str()) );
-       ssgEntity *obj_model
-           = ssgLoad( (char *)(dm->get_model_path().c_str()) );
+       ssgEntity *obj_model = globals->get_model_loader()->load_model(dm->get_model_path());
         if ( obj_model != NULL ) {
             dm->get_obj_trans()->addKid( obj_model );
         }