From: curt Date: Fri, 9 May 2003 20:19:36 +0000 (+0000) Subject: Moved loader.[ch]xx and model.[ch]xx from fgfs/src/Model/ to X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=16dd841ce5cbdcd7b7a8bd1cfa4f99ab7d17c44e;p=simgear.git Moved loader.[ch]xx and model.[ch]xx from fgfs/src/Model/ to simgear/scene/model. --- diff --git a/simgear/scene/model/Makefile.am b/simgear/scene/model/Makefile.am index f0dcd8e5..360d6c60 100644 --- a/simgear/scene/model/Makefile.am +++ b/simgear/scene/model/Makefile.am @@ -4,8 +4,18 @@ lib_LIBRARIES = libsgmodel.a noinst_HEADERS = -include_HEADERS = animation.hxx location.hxx placement.hxx +include_HEADERS = \ + animation.hxx \ + loader.hxx \ + location.hxx \ + model.hxx \ + placement.hxx -libsgmodel_a_SOURCES = animation.cxx location.cxx placement.cxx +libsgmodel_a_SOURCES = \ + animation.cxx \ + loader.cxx \ + location.cxx \ + model.cxx \ + placement.cxx INCLUDES = -I$(top_srcdir) diff --git a/simgear/scene/model/loader.cxx b/simgear/scene/model/loader.cxx new file mode 100644 index 00000000..e43b02f3 --- /dev/null +++ b/simgear/scene/model/loader.cxx @@ -0,0 +1,77 @@ +// loader.cxx - implement SSG model and texture loaders. + +#include +#include + +#include "loader.hxx" +#include "model.hxx" + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGSSGLoader. +//////////////////////////////////////////////////////////////////////// + +FGSSGLoader::FGSSGLoader () +{ + // no op +} + +FGSSGLoader::~FGSSGLoader () +{ + std::map::iterator it = _table.begin(); + while (it != _table.end()) { + it->second->deRef(); + _table.erase(it); + } +} + +void +FGSSGLoader::flush () +{ + std::map::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 &fg_root, + const string &path, + SGPropertyNode *prop_root, + double sim_time_sec ) +{ + // FIXME: normalize path to + // avoid duplicates. + std::map::iterator it = _table.find(path); + if (it == _table.end()) { + _table[path] = fgLoad3DModel( fg_root, path, prop_root, sim_time_sec ); + it = _table.find(path); + it->second->ref(); // add one reference to keep it around + } + return (ssgEntity *)it->second; +} + + +// end of loader.cxx diff --git a/simgear/scene/model/loader.hxx b/simgear/scene/model/loader.hxx new file mode 100644 index 00000000..293d651f --- /dev/null +++ b/simgear/scene/model/loader.hxx @@ -0,0 +1,51 @@ +#ifndef __MODEL_LOADER_HXX +#define __MODEL_LOADER_HXX 1 + +#ifndef __cplusplus +# error This library requires C++ +#endif + +#include // for SG_USING_STD + +#include +#include STL_STRING + +#include + +#include + +SG_USING_STD(map); +SG_USING_STD(string); + + +/** + * Base class for loading and managing SSG things. + */ +class FGSSGLoader +{ +public: + FGSSGLoader (); + virtual ~FGSSGLoader (); + virtual void flush (); +protected: + std::map _table; +}; + + +/** + * Class for loading and managing models with XML wrappers. + */ +class FGModelLoader : public FGSSGLoader +{ +public: + FGModelLoader (); + virtual ~FGModelLoader (); + + virtual ssgEntity *load_model( const string &fg_root, + const string &path, + SGPropertyNode *prop_root, + double sim_time_sec ); +}; + + +#endif diff --git a/simgear/scene/model/model.cxx b/simgear/scene/model/model.cxx new file mode 100644 index 00000000..b3678efb --- /dev/null +++ b/simgear/scene/model/model.cxx @@ -0,0 +1,258 @@ +// model.cxx - manage a 3D aircraft model. +// Written by David Megginson, started 2002. +// +// This file is in the Public Domain, and comes with no warranty. + +#include + +#include // for strcmp() + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "model.hxx" + +SG_USING_STD(vector); + + + +//////////////////////////////////////////////////////////////////////// +// 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. + */ +static ssgEntity * +find_named_node (ssgEntity * node, const char * name) +{ + char * node_name = node->getName(); + if (node_name != 0 && !strcmp(name, node_name)) + return node; + else if (node->isAKindOf(ssgTypeBranch())) { + int nKids = node->getNumKids(); + for (int i = 0; i < nKids; i++) { + ssgEntity * result = + find_named_node(((ssgBranch*)node)->getKid(i), name); + if (result != 0) + return result; + } + } + return 0; +} + +/** + * Splice a branch in between all child nodes and their parents. + */ +static void +splice_branch (ssgBranch * branch, ssgEntity * child) +{ + int nParents = child->getNumParents(); + branch->addKid(child); + for (int i = 0; i < nParents; i++) { + ssgBranch * parent = child->getParent(i); + parent->replaceKid(child, branch); + } +} + +/** + * Make an offset matrix from rotations and position offset. + */ +void +fgMakeOffsetsMatrix( sgMat4 * result, double h_rot, double p_rot, double r_rot, + double x_off, double y_off, double z_off ) +{ + sgMat4 rot_matrix; + sgMat4 pos_matrix; + sgMakeRotMat4(rot_matrix, h_rot, p_rot, r_rot); + sgMakeTransMat4(pos_matrix, x_off, y_off, z_off); + sgMultMat4(*result, pos_matrix, rot_matrix); +} + + +void +fgMakeAnimation( ssgBranch * model, + const char * name, + vector &name_nodes, + SGPropertyNode *prop_root, + SGPropertyNode_ptr node, + double sim_time_sec ) +{ + Animation * animation = 0; + const char * type = node->getStringValue("type", "none"); + 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(prop_root, node); + } else if (!strcmp("spin", type)) { + animation = new SpinAnimation(prop_root, node, sim_time_sec ); + } else if (!strcmp("timed", type)) { + animation = new TimedAnimation(node); + } else if (!strcmp("rotate", type)) { + animation = new RotateAnimation(prop_root, node); + } else if (!strcmp("translate", type)) { + animation = new TranslateAnimation(prop_root, node); + } else { + animation = new NullAnimation(node); + SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); + } + + if (name != 0) + animation->setName((char *)name); + + ssgEntity * object; + if (name_nodes.size() > 0) { + object = find_named_node(model, name_nodes[0]->getStringValue()); + if (object == 0) { + SG_LOG(SG_INPUT, SG_WARN, "Object " << name_nodes[0]->getStringValue() + << " not found"); + delete animation; + animation = 0; + } + } else { + object = model; + } + + ssgBranch * branch = animation->getBranch(); + splice_branch(branch, object); + + for (unsigned int i = 1; i < name_nodes.size(); i++) { + const char * name = name_nodes[i]->getStringValue(); + object = find_named_node(model, name); + if (object == 0) { + SG_LOG(SG_INPUT, SG_WARN, "Object " << name << " not found"); + delete animation; + animation = 0; + } + ssgBranch * oldParent = object->getParent(0); + branch->addKid(object); + oldParent->removeKid(object); + } + + animation->init(); + branch->setUserData(animation); + branch->setTravCallback(SSG_CALLBACK_PRETRAV, animation_callback); +} + + + + +//////////////////////////////////////////////////////////////////////// +// Global functions. +//////////////////////////////////////////////////////////////////////// + +ssgBranch * +fgLoad3DModel( const string &fg_root, const string &path, + SGPropertyNode *prop_root, + double sim_time_sec ) +{ + ssgBranch * model = 0; + SGPropertyNode props; + + // Load the 3D aircraft object itself + SGPath xmlpath; + SGPath modelpath = path; + if ( ulIsAbsolutePathName( path.c_str() ) ) { + xmlpath = modelpath; + } + else { + xmlpath = fg_root; + xmlpath.append(modelpath.str()); + } + + // Check for an XML wrapper + if (xmlpath.str().substr(xmlpath.str().size() - 4, 4) == ".xml") { + readProperties(xmlpath.str(), &props); + if (props.hasValue("/path")) { + modelpath = modelpath.dir(); + modelpath.append(props.getStringValue("/path")); + } else { + if (model == 0) + model = new ssgBranch; + } + } + + // Assume that textures are in + // the same location as the XML file. + if (model == 0) { + ssgTexturePath((char *)xmlpath.dir().c_str()); + model = (ssgBranch *)ssgLoad((char *)modelpath.c_str()); + if (model == 0) + throw sg_exception("Failed to load 3D model"); + } + + // Set up the alignment node + ssgTransform * alignmainmodel = new ssgTransform; + alignmainmodel->addKid(model); + sgMat4 res_matrix; + fgMakeOffsetsMatrix(&res_matrix, + props.getFloatValue("/offsets/heading-deg", 0.0), + props.getFloatValue("/offsets/roll-deg", 0.0), + props.getFloatValue("/offsets/pitch-deg", 0.0), + props.getFloatValue("/offsets/x-m", 0.0), + props.getFloatValue("/offsets/y-m", 0.0), + props.getFloatValue("/offsets/z-m", 0.0)); + alignmainmodel->setTransform(res_matrix); + + unsigned int i; + + // Load animations + vector animation_nodes = props.getChildren("animation"); + for (i = 0; i < animation_nodes.size(); i++) { + const char * name = animation_nodes[i]->getStringValue("name", 0); + vector name_nodes = + animation_nodes[i]->getChildren("object-name"); + fgMakeAnimation( model, name, name_nodes, prop_root, animation_nodes[i], + sim_time_sec); + } + + // Load sub-models + vector model_nodes = props.getChildren("model"); + for (i = 0; i < model_nodes.size(); i++) { + SGPropertyNode_ptr node = model_nodes[i]; + ssgTransform * align = new ssgTransform; + sgMat4 res_matrix; + fgMakeOffsetsMatrix(&res_matrix, + node->getFloatValue("offsets/heading-deg", 0.0), + node->getFloatValue("offsets/roll-deg", 0.0), + node->getFloatValue("offsets/pitch-deg", 0.0), + node->getFloatValue("offsets/x-m", 0.0), + node->getFloatValue("offsets/y-m", 0.0), + node->getFloatValue("offsets/z-m", 0.0)); + align->setTransform(res_matrix); + + ssgBranch * kid = fgLoad3DModel( fg_root, node->getStringValue("path"), + prop_root, sim_time_sec ); + align->addKid(kid); + model->addKid(align); + } + + return alignmainmodel; +} + + +// end of model.cxx diff --git a/simgear/scene/model/model.hxx b/simgear/scene/model/model.hxx new file mode 100644 index 00000000..4102460d --- /dev/null +++ b/simgear/scene/model/model.hxx @@ -0,0 +1,67 @@ +// model.hxx - manage a 3D aircraft model. +// Written by David Megginson, started 2002. +// +// This file is in the Public Domain, and comes with no warranty. + +#ifndef __MODEL_HXX +#define __MODEL_HXX 1 + +#ifndef __cplusplus +# error This library requires C++ +#endif + +#include + +SG_USING_STD(vector); + +#include +#include + +#include + + +// Has anyone done anything *really* stupid, like making min and max macros? +#ifdef min +#undef min +#endif +#ifdef max +#undef max +#endif + + +/** + * Load a 3D model with or without XML wrapper. Note, this version + * Does not know about or load the panel/cockpit information. Use the + * "model_panel.hxx" version if you want to load an aircraft + * (i.e. ownship) with a panel. + * + * 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& fg_root, const string &path, + SGPropertyNode *prop_root, double sim_time_sec ); + + +/** + * Make an offset matrix from rotations and position offset. + */ +void +fgMakeOffsetsMatrix( sgMat4 * result, double h_rot, double p_rot, double r_rot, + double x_off, double y_off, double z_off ); + +/** + * Make the animation + */ +void +fgMakeAnimation( ssgBranch * model, + const char * name, + vector &name_nodes, + SGPropertyNode *prop_root, + SGPropertyNode_ptr node, + double sim_time_sec ); + + +#endif // __MODEL_HXX