1
0
Fork 0

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:
david 2002-08-07 01:34:49 +00:00
parent c3f4b63258
commit 0ebe8ec8f0
13 changed files with 543 additions and 529 deletions

View 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 {

View 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)

View 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 ) {

View 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

View 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();
}

104
src/Model/loader.cxx Normal file
View 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
View 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

View file

@ -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 );

View 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
/**
* 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;
};

View 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();
}
}

View 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 );

View 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"
////////////////////////////////////////////////////////////////////////
// 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]);
}
}
}

View 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 );
}