Removed the FG3DModel class and replaced it with fgLoad3DModel.
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.
This commit is contained in:
parent
c3f4b63258
commit
0ebe8ec8f0
13 changed files with 543 additions and 529 deletions
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
|
|
104
src/Model/loader.cxx
Normal file
104
src/Model/loader.cxx
Normal file
|
@ -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"
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
58
src/Model/loader.hxx
Normal file
58
src/Model/loader.hxx
Normal file
|
@ -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
|
|
@ -34,6 +34,17 @@
|
|||
// 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)
|
|||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FG3DModel
|
||||
// Global functions.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FG3DModel::FG3DModel ()
|
||||
: _model(0)
|
||||
{
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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 ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FG3DModel::NullAnimation
|
||||
// Implementation of NullAnimation
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FG3DModel::NullAnimation::NullAnimation ()
|
||||
: _branch(new ssgBranch)
|
||||
NullAnimation::NullAnimation (SGPropertyNode_ptr props)
|
||||
: Animation(props, new ssgBranch)
|
||||
{
|
||||
}
|
||||
|
||||
FG3DModel::NullAnimation::~NullAnimation ()
|
||||
NullAnimation::~NullAnimation ()
|
||||
{
|
||||
_branch = 0;
|
||||
}
|
||||
|
||||
void
|
||||
FG3DModel::NullAnimation::init (ssgEntity * object,
|
||||
SGPropertyNode * props)
|
||||
{
|
||||
splice_branch(_branch, object);
|
||||
_branch->setName(props->getStringValue("name", 0));
|
||||
}
|
||||
|
||||
void
|
||||
FG3DModel::NullAnimation::update (double dt)
|
||||
NullAnimation::update ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FG3DModel::RangeAnimation
|
||||
// Implementation of RangeAnimation
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FG3DModel::RangeAnimation::RangeAnimation ()
|
||||
: _branch(new ssgRangeSelector)
|
||||
RangeAnimation::RangeAnimation (SGPropertyNode_ptr props)
|
||||
: Animation(props, new ssgRangeSelector)
|
||||
{
|
||||
float ranges[] = { props->getFloatValue("min-m", 0),
|
||||
props->getFloatValue("max-m", 5000) };
|
||||
((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
|
||||
|
||||
}
|
||||
|
||||
FG3DModel::RangeAnimation::~RangeAnimation ()
|
||||
RangeAnimation::~RangeAnimation ()
|
||||
{
|
||||
_branch = 0;
|
||||
}
|
||||
|
||||
void
|
||||
FG3DModel::RangeAnimation::init (ssgEntity * object,
|
||||
SGPropertyNode * props)
|
||||
{
|
||||
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 ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FG3DModel::BillboardAnimation
|
||||
// Implementation of BillboardAnimation
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FG3DModel::BillboardAnimation::BillboardAnimation ()
|
||||
: _branch(0)
|
||||
BillboardAnimation::BillboardAnimation (SGPropertyNode_ptr props)
|
||||
: Animation(props, new ssgCutout(props->getBoolValue("spherical", true)))
|
||||
{
|
||||
// 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 ()
|
||||
{
|
||||
_branch = 0;
|
||||
}
|
||||
|
||||
void
|
||||
FG3DModel::BillboardAnimation::init (ssgEntity * object,
|
||||
SGPropertyNode * props)
|
||||
{
|
||||
_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 ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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)
|
||||
SpinAnimation::update ()
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
double sim_time = globals->get_sim_time_sec();
|
||||
double dt = sim_time - _last_time_sec;
|
||||
_last_time_sec = sim_time;
|
||||
|
||||
void
|
||||
FG3DModel::SpinAnimation::update (double dt)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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)
|
||||
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))
|
||||
{
|
||||
}
|
||||
|
||||
FG3DModel::RotateAnimation::~RotateAnimation ()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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)
|
||||
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))
|
||||
{
|
||||
}
|
||||
|
||||
FG3DModel::TranslateAnimation::~TranslateAnimation ()
|
||||
{
|
||||
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 );
|
||||
|
||||
|
|
|
@ -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
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Animation classes
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Abstract base class for all animations.
|
||||
*/
|
||||
class Animation : public ssgBase
|
||||
{
|
||||
public:
|
||||
|
||||
FG3DModel ();
|
||||
virtual ~FG3DModel ();
|
||||
Animation (SGPropertyNode_ptr props, ssgBranch * branch);
|
||||
|
||||
virtual void init (const string &path);
|
||||
virtual void update (double dt);
|
||||
|
||||
virtual ssgEntity * getSceneGraph () const { return (ssgEntity *)_model; }
|
||||
|
||||
private:
|
||||
|
||||
class Animation;
|
||||
Animation * make_animation (const char * object_name, SGPropertyNode * node);
|
||||
|
||||
// Child models.
|
||||
vector<FG3DModel *> _children;
|
||||
|
||||
// Animations
|
||||
vector <Animation *> _animations;
|
||||
|
||||
// Scene graph
|
||||
ssgBranch * _model;
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
|
||||
|
||||
/**
|
||||
* Update the animation.
|
||||
*
|
||||
* @param dt The elapsed time in seconds since the last call.
|
||||
*/
|
||||
virtual void update (double dt) = 0;
|
||||
|
||||
};
|
||||
|
||||
virtual ssgBranch * getBranch () { return _branch; }
|
||||
|
||||
/**
|
||||
* A no-op animation.
|
||||
* Update the animation.
|
||||
*/
|
||||
class NullAnimation : public Animation
|
||||
{
|
||||
public:
|
||||
NullAnimation ();
|
||||
virtual ~NullAnimation ();
|
||||
virtual void init (ssgEntity * object, SGPropertyNode * props);
|
||||
virtual void update (double dt);
|
||||
private:
|
||||
ssgBranch * _branch;
|
||||
};
|
||||
virtual void update () = 0;
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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 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 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 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;
|
||||
};
|
||||
protected:
|
||||
|
||||
ssgBranch * _branch;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A no-op animation.
|
||||
*/
|
||||
class NullAnimation : public Animation
|
||||
{
|
||||
public:
|
||||
NullAnimation (SGPropertyNode_ptr props);
|
||||
virtual ~NullAnimation ();
|
||||
virtual void update ();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A range, or level-of-detail (LOD) animation.
|
||||
*/
|
||||
class RangeAnimation : public Animation
|
||||
{
|
||||
public:
|
||||
RangeAnimation (SGPropertyNode_ptr props);
|
||||
virtual ~RangeAnimation ();
|
||||
virtual void update ();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Animation to turn and face the screen.
|
||||
*/
|
||||
class BillboardAnimation : public Animation
|
||||
{
|
||||
public:
|
||||
BillboardAnimation (SGPropertyNode_ptr props);
|
||||
virtual ~BillboardAnimation ();
|
||||
virtual void update ();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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 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 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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -43,37 +43,15 @@ SG_USING_STD(map);
|
|||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Model/loader.hxx>
|
||||
|
||||
#include "newmat.hxx"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Local static variables.
|
||||
// FIXME: write a proper manager.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Objects already loaded (that can be reused).
|
||||
map<string,ssgEntity *> object_map;
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue