X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmodel%2Fmodel.cxx;h=4a2349be603cac35bf1aa7153c83d789577647fa;hb=7aa6fd479da920a6eb95f4b7da2010906928b619;hp=8db5b8e0042f44b65652f7aa0e95b708326a456d;hpb=b94a98fc90f9d98e39c31ef3763f3f360da509bf;p=simgear.git diff --git a/simgear/scene/model/model.cxx b/simgear/scene/model/model.cxx index 8db5b8e0..4a2349be 100644 --- a/simgear/scene/model/model.cxx +++ b/simgear/scene/model/model.cxx @@ -7,8 +7,6 @@ #include #endif -#include // for strcmp() - #include #include #include @@ -19,10 +17,12 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -37,18 +37,6 @@ SG_USING_STD(vector); SG_USING_STD(set); -static inline -int nMipMaps(int s) -{ - s = s >> 2; - int n = 0; - do { - ++n; - s = s >> 1; - } while(s); - return n; -} - // Little helper class that holds an extra reference to a // loaded 3d model. // Since we clone all structural nodes from our 3d models, @@ -77,9 +65,11 @@ public: SGTextureUpdateVisitor(const osgDB::FilePathList& pathList) : mPathList(pathList) { } - osg::Texture2D* textureReplace(int unit, osg::StateSet::RefAttributePair& refAttr) + osg::Texture2D* textureReplace(int unit, + osg::StateSet::RefAttributePair& refAttr) { - osg::Texture2D* texture = dynamic_cast(refAttr.first.get()); + osg::Texture2D* texture; + texture = dynamic_cast(refAttr.first.get()); if (!texture) return 0; @@ -125,7 +115,8 @@ public: if (texture) { stateSet->removeTextureAttribute(unit, i->second.first.get()); stateSet->setTextureAttribute(unit, texture, i->second.second); - stateSet->setTextureMode(unit, GL_TEXTURE_2D, osg::StateAttribute::ON); + stateSet->setTextureMode(unit, GL_TEXTURE_2D, + osg::StateAttribute::ON); } ++i; } @@ -138,13 +129,10 @@ private: class SGTexCompressionVisitor : public SGTextureStateAttributeVisitor { public: - SGTexCompressionVisitor(osg::Texture::InternalFormatMode formatMode) : - mFormatMode(formatMode) - { } - virtual void apply(int, osg::StateSet::RefAttributePair& refAttr) { - osg::Texture2D* texture = dynamic_cast(refAttr.first.get()); + osg::Texture2D* texture; + texture = dynamic_cast(refAttr.first.get()); if (!texture) return; @@ -155,30 +143,33 @@ public: int s = image->s(); int t = image->t(); - int mipmaplevels = 0; - if (s < t) { - mipmaplevels = nMipMaps(s); - } else { - mipmaplevels = nMipMaps(t); - } - texture->setNumMipmapLevels(mipmaplevels); - if (s <= t && 32 <= s) { - texture->setInternalFormatMode(mFormatMode); + SGSceneFeatures::instance()->setTextureCompression(texture); } else if (t < s && 32 <= t) { - texture->setInternalFormatMode(mFormatMode); + SGSceneFeatures::instance()->setTextureCompression(texture); } } +}; -private: - osg::Texture::InternalFormatMode mFormatMode; +class SGTexDataVarianceVisitor : public SGTextureStateAttributeVisitor { +public: + virtual void apply(int, osg::StateSet::RefAttributePair& refAttr) + { + osg::Texture* texture; + texture = dynamic_cast(refAttr.first.get()); + if (!texture) + return; + + texture->setDataVariance(osg::Object::STATIC); + } }; class SGAcMaterialCrippleVisitor : public SGStateAttributeVisitor { public: virtual void apply(osg::StateSet::RefAttributePair& refAttr) { - osg::Material* material = dynamic_cast(refAttr.first.get()); + osg::Material* material; + material = dynamic_cast(refAttr.first.get()); if (!material) return; material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); @@ -189,7 +180,8 @@ class SGReadFileCallback : public osgDB::Registry::ReadFileCallback { public: virtual osgDB::ReaderWriter::ReadResult - readImage(const std::string& fileName, const osgDB::ReaderWriter::Options* opt) + readImage(const std::string& fileName, + const osgDB::ReaderWriter::Options* opt) { std::string absFileName = osgDB::findDataFile(fileName); if (!osgDB::fileExists(absFileName)) { @@ -199,7 +191,8 @@ public: } osgDB::Registry* registry = osgDB::Registry::instance(); - osgDB::ReaderWriter::ReadResult res = registry->readImageImplementation(absFileName, opt); + osgDB::ReaderWriter::ReadResult res; + res = registry->readImageImplementation(absFileName, opt); if (res.loadedFromCache()) SG_LOG(SG_IO, SG_INFO, "Returning cached image \"" << res.getImage()->getFileName() << "\""); @@ -211,8 +204,18 @@ public: } virtual osgDB::ReaderWriter::ReadResult - readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* opt) + readNode(const std::string& fileName, + const osgDB::ReaderWriter::Options* opt) { + osgDB::Registry* registry = osgDB::Registry::instance(); + osgDB::ReaderWriter::ReadResult res; + // The BTG loader automatically looks for ".btg.gz" if a file with + // the .btg extension doesn't exist. Also, we don't want to add + // nodes, run the optimizer, etc. on the btg model.So, let it do + // its thing. + if (osgDB::equalCaseInsensitive(osgDB::getFileExtension(fileName), "btg")) { + return registry->readNodeImplementation(fileName, opt); + } std::string absFileName = osgDB::findDataFile(fileName); if (!osgDB::fileExists(absFileName)) { SG_LOG(SG_IO, SG_ALERT, "Cannot find model file \"" @@ -220,8 +223,6 @@ public: return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND; } - osgDB::Registry* registry = osgDB::Registry::instance(); - osgDB::ReaderWriter::ReadResult res; res = registry->readNodeImplementation(absFileName, opt); if (!res.validNode()) return res; @@ -233,7 +234,10 @@ public: SG_LOG(SG_IO, SG_INFO, "Reading model \"" << absFileName << "\""); + bool needTristrip = true; if (osgDB::getLowerCaseFileExtension(absFileName) == "ac") { + // we get optimal geometry from the loader. + needTristrip = false; osg::Matrix m(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, @@ -252,26 +256,30 @@ public: osgUtil::Optimizer optimizer; unsigned opts = osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS; optimizer.optimize(root.get(), opts); + + // strip away unneeded groups + if (root->getNumChildren() == 1 && root->getName().empty()) { + res = osgDB::ReaderWriter::ReadResult(root->getChild(0)); + } else + res = osgDB::ReaderWriter::ReadResult(root.get()); // Ok, this step is questionable. // It is there to have the same visual appearance of ac objects for the // first cut. Osg's ac3d loader will correctly set materials from the // ac file. But the old plib loader used GL_AMBIENT_AND_DIFFUSE for the // materials that in effect igored the ambient part specified in the - // file. We emulate that for the first cut here by changing all ac models - // here. But in the long term we should use the unchanged model and fix - // the input files instead ... + // file. We emulate that for the first cut here by changing all + // ac models here. But in the long term we should use the + // unchanged model and fix the input files instead ... SGAcMaterialCrippleVisitor matCriple; - root->accept(matCriple); - - res = osgDB::ReaderWriter::ReadResult(root.get()); + res.getNode()->accept(matCriple); } osgUtil::Optimizer optimizer; unsigned opts = 0; // Don't use this one. It will break animation names ... // opts |= osgUtil::Optimizer::REMOVE_REDUNDANT_NODES; - + // opts |= osgUtil::Optimizer::REMOVE_LOADED_PROXY_NODES; // opts |= osgUtil::Optimizer::COMBINE_ADJACENT_LODS; // opts |= osgUtil::Optimizer::SHARE_DUPLICATE_STATE; @@ -279,32 +287,30 @@ public: // opts |= osgUtil::Optimizer::CHECK_GEOMETRY; // opts |= osgUtil::Optimizer::SPATIALIZE_GROUPS; // opts |= osgUtil::Optimizer::COPY_SHARED_NODES; - opts |= osgUtil::Optimizer::TRISTRIP_GEOMETRY; + opts |= osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS; + if (needTristrip) + opts |= osgUtil::Optimizer::TRISTRIP_GEOMETRY; // opts |= osgUtil::Optimizer::TESSELATE_GEOMETRY; // opts |= osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS; optimizer.optimize(res.getNode(), opts); - // OSGFIXME + // Make sure the data variance of sharable objects is set to STATIC ... + SGTexDataVarianceVisitor dataVarianceVisitor; + res.getNode()->accept(dataVarianceVisitor); + // ... so that textures are now globally shared registry->getSharedStateManager()->share(res.getNode()); - // OSGFIXME: guard that with a flag - // OSGFIXME: in the long term it is unclear if we have an OpenGL context here... - osg::Texture::Extensions* e = osg::Texture::getExtensions(0, true); - if (e->isTextureCompressionARBSupported()) { - SGTexCompressionVisitor texComp(osg::Texture::USE_ARB_COMPRESSION); - res.getNode()->accept(texComp); - } else if (e->isTextureCompressionS3TCSupported()) { - SGTexCompressionVisitor texComp(osg::Texture::USE_S3TC_DXT5_COMPRESSION); - res.getNode()->accept(texComp); - } + SGTexCompressionVisitor texComp; + res.getNode()->accept(texComp); } // Add an extra reference to the model stored in the database. // That it to avoid expiring the object from the cache even if it is still - // in use. Note that the object cache will think that a model is unused if the - // reference count is 1. If we clone all structural nodes here we need that extra - // reference to the original object - SGDatabaseReference* databaseReference = new SGDatabaseReference(res.getNode()); + // in use. Note that the object cache will think that a model is unused + // if the reference count is 1. If we clone all structural nodes here + // we need that extra reference to the original object + SGDatabaseReference* databaseReference; + databaseReference = new SGDatabaseReference(res.getNode()); osg::CopyOp::CopyFlags flags = osg::CopyOp::DEEP_COPY_ALL; flags &= ~osg::CopyOp::DEEP_COPY_TEXTURES; flags &= ~osg::CopyOp::DEEP_COPY_IMAGES; @@ -316,10 +322,14 @@ public: res = osgDB::ReaderWriter::ReadResult(osg::CopyOp(flags)(res.getNode())); res.getNode()->addObserver(databaseReference); + // Update liveries SGTextureUpdateVisitor liveryUpdate(osgDB::getDataFilePathList()); res.getNode()->accept(liveryUpdate); - // OSGFIXME: don't forget that mutex here + // Make sure the data variance of sharable objects is set to STATIC ... + SGTexDataVarianceVisitor dataVarianceVisitor; + res.getNode()->accept(dataVarianceVisitor); + // ... so that textures are now globally shared registry->getOrCreateSharedStateManager()->share(res.getNode(), 0); return res; @@ -344,11 +354,10 @@ public: static SGReadCallbackInstaller readCallbackInstaller; osg::Texture2D* -SGLoadTexture2D(const std::string& path, bool wrapu, bool wrapv, - int mipmaplevels) +SGLoadTexture2D(const std::string& path, bool wrapu, bool wrapv, int) { osg::Image* image = osgDB::readImageFile(path); - osg::Texture2D* texture = new osg::Texture2D; + osg::ref_ptr texture = new osg::Texture2D; texture->setImage(image); if (wrapu) texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); @@ -363,31 +372,34 @@ SGLoadTexture2D(const std::string& path, bool wrapu, bool wrapv, int s = image->s(); int t = image->t(); - if (mipmaplevels < 0) { - if (s < t) { - mipmaplevels = nMipMaps(s); - } else { - mipmaplevels = nMipMaps(t); - } - } - texture->setNumMipmapLevels(mipmaplevels); - - // OSGFIXME: guard with a flag - if (osg::Texture::getExtensions(0, true)->isTextureCompressionARBSupported()) { - if (s <= t && 32 <= s) { - texture->setInternalFormatMode(osg::Texture::USE_ARB_COMPRESSION); - } else if (t < s && 32 <= t) { - texture->setInternalFormatMode(osg::Texture::USE_ARB_COMPRESSION); - } - } else if (osg::Texture::getExtensions(0, true)->isTextureCompressionS3TCSupported()) { - if (s <= t && 32 <= s) { - texture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT5_COMPRESSION); - } else if (t < s && 32 <= t) { - texture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT5_COMPRESSION); - } + if (s <= t && 32 <= s) { + SGSceneFeatures::instance()->setTextureCompression(texture.get()); + } else if (t < s && 32 <= t) { + SGSceneFeatures::instance()->setTextureCompression(texture.get()); } } - return texture; + + // Make sure the texture is shared if we already have the same texture + // somewhere ... + { + osg::ref_ptr tmpNode = new osg::Node; + osg::StateSet* stateSet = tmpNode->getOrCreateStateSet(); + stateSet->setTextureAttribute(0, texture.get()); + + // OSGFIXME: don't forget that mutex here + osgDB::Registry* registry = osgDB::Registry::instance(); + registry->getOrCreateSharedStateManager()->share(tmpNode.get(), 0); + + // should be the same, but be paranoid ... + stateSet = tmpNode->getStateSet(); + osg::StateAttribute* stateAttr; + stateAttr = stateSet->getTextureAttribute(0, osg::StateAttribute::TEXTURE); + osg::Texture2D* texture2D = dynamic_cast(stateAttr); + if (texture2D) + texture = texture2D; + } + + return texture.release(); } class SGSwitchUpdateCallback : public osg::NodeCallback { @@ -410,157 +422,9 @@ public: } private: - SGCondition* mCondition; + SGSharedPtr mCondition; }; -/** - * Locate a named node in a branch. - */ -class NodeFinder : public osg::NodeVisitor { -public: - NodeFinder(const std::string& nameToFind) : - osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR, - osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - mName(nameToFind), - mNode(0) - { } - virtual void apply(osg::Node& node) - { - if (mNode) - return; - if (mName == node.getName()) { - mNode = &node; - return; - } - traverse(node); - } - - osg::Node* getNode() const - { return mNode; } -private: - std::string mName; - osg::Node* mNode; -}; - -/** - * Splice a branch in between all child nodes and their parents. - */ -static void -splice_branch(osg::Group* group, osg::Node* child) -{ - osg::Node::ParentList parents = child->getParents(); - group->addChild(child); - osg::Node::ParentList::iterator i; - for (i = parents.begin(); i != parents.end(); ++i) - (*i)->replaceChild(child, group); -} - -void -sgMakeAnimation( osg::Node * model, - const char * name, - vector &name_nodes, - SGPropertyNode *prop_root, - SGPropertyNode_ptr node, - double sim_time_sec, - SGPath &texture_path, - set &ignore_branches ) -{ - bool ignore = false; - SGAnimation * animation = 0; - const char * type = node->getStringValue("type", "none"); - if (!strcmp("none", type)) { - animation = new SGNullAnimation(node); - } else if (!strcmp("range", type)) { - animation = new SGRangeAnimation(prop_root, node); - } else if (!strcmp("billboard", type)) { - animation = new SGBillboardAnimation(node); - } else if (!strcmp("select", type)) { - animation = new SGSelectAnimation(prop_root, node); - } else if (!strcmp("spin", type)) { - animation = new SGSpinAnimation(prop_root, node, sim_time_sec ); - } else if (!strcmp("timed", type)) { - animation = new SGTimedAnimation(node); - } else if (!strcmp("rotate", type)) { - animation = new SGRotateAnimation(prop_root, node); - } else if (!strcmp("translate", type)) { - animation = new SGTranslateAnimation(prop_root, node); - } else if (!strcmp("scale", type)) { - animation = new SGScaleAnimation(prop_root, node); - } else if (!strcmp("texrotate", type)) { - animation = new SGTexRotateAnimation(prop_root, node); - } else if (!strcmp("textranslate", type)) { - animation = new SGTexTranslateAnimation(prop_root, node); - } else if (!strcmp("texmultiple", type)) { - animation = new SGTexMultipleAnimation(prop_root, node); - } else if (!strcmp("blend", type)) { - animation = new SGBlendAnimation(prop_root, node); - ignore = true; - } else if (!strcmp("alpha-test", type)) { - animation = new SGAlphaTestAnimation(node); - } else if (!strcmp("material", type)) { - animation = new SGMaterialAnimation(prop_root, node, texture_path); - } else if (!strcmp("flash", type)) { - animation = new SGFlashAnimation(node); - } else if (!strcmp("dist-scale", type)) { - animation = new SGDistScaleAnimation(node); - } else if (!strcmp("noshadow", type)) { - animation = new SGShadowAnimation(prop_root, node); - } else if (!strcmp("shader", type)) { - animation = new SGShaderAnimation(prop_root, node); - } else { - animation = new SGNullAnimation(node); - SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); - } - - if (name != 0) - animation->setName(name); - - osg::Node * object = 0; - if (!name_nodes.empty()) { - const char * name = name_nodes[0]->getStringValue(); - NodeFinder nodeFinder(name); - model->accept(nodeFinder); - object = nodeFinder.getNode(); - if (object == 0) { - SG_LOG(SG_INPUT, SG_ALERT, "Object " << name << " not found"); - delete animation; - animation = 0; - } - } else { - object = model; - } - - if ( animation == 0 ) - return; - - osg::Group* branch = animation->getBranch(); - splice_branch(branch, object); - - for (unsigned int i = 1; i < name_nodes.size(); i++) { - const char * name = name_nodes[i]->getStringValue(); - NodeFinder nodeFinder(name); - model->accept(nodeFinder); - object = nodeFinder.getNode(); - if (object == 0) { - SG_LOG(SG_INPUT, SG_ALERT, "Object " << name << " not found"); - delete animation; - animation = 0; - } else { - osg::Group* oldParent = object->getParent(0); - branch->addChild(object); - oldParent->removeChild(object); - } - } - - if ( animation != 0 ) { - animation->init(); - branch->setUpdateCallback(animation); - if ( ignore ) { - ignore_branches.insert( branch ); - } - } -} - //////////////////////////////////////////////////////////////////////// // Global functions. @@ -573,10 +437,10 @@ sgLoad3DModel( const string &fg_root, const string &path, SGModelData *data, const SGPath& externalTexturePath ) { - osg::Switch* model = 0; + osg::ref_ptr model; SGPropertyNode props; - // Load the 3D aircraft object itself + // Load the 3D aircraft object itself SGPath modelpath = path, texturepath = path; if ( !ulIsAbsolutePathName( path.c_str() ) ) { SGPath tmp = fg_root; @@ -584,7 +448,7 @@ sgLoad3DModel( const string &fg_root, const string &path, modelpath = texturepath = tmp; } - // Check for an XML wrapper + // Check for an XML wrapper if (modelpath.str().substr(modelpath.str().size() - 4, 4) == ".xml") { readProperties(modelpath.str(), &props); if (props.hasValue("/path")) { @@ -595,7 +459,7 @@ sgLoad3DModel( const string &fg_root, const string &path, texturepath.append(props.getStringValue("/texture-path")); } } else { - if (model == 0) + if (!model) model = new osg::Switch; } } @@ -603,35 +467,33 @@ sgLoad3DModel( const string &fg_root, const string &path, osgDB::FilePathList pathList = osgDB::getDataFilePathList(); osgDB::Registry::instance()->initFilePathLists(); - // Assume that textures are in - // the same location as the XML file. - if (model == 0) { + // Assume that textures are in + // the same location as the XML file. + if (!model) { if (texturepath.extension() != "") texturepath = texturepath.dir(); osgDB::Registry::instance()->getDataFilePathList().push_front(texturepath.str()); - osg::Node* node = osgDB::readNodeFile(modelpath.str()); - if (node == 0) + model = osgDB::readNodeFile(modelpath.str()); + if (model == 0) throw sg_io_exception("Failed to load 3D model", sg_location(modelpath.str())); - model = new osg::Switch; - model->addChild(node, true); } osgDB::Registry::instance()->getDataFilePathList().push_front(externalTexturePath.str()); - // Set up the alignment node - osg::MatrixTransform* alignmainmodel = new osg::MatrixTransform; - alignmainmodel->addChild(model); + // Set up the alignment node + osg::ref_ptr alignmainmodel = new osg::MatrixTransform; + alignmainmodel->addChild(model.get()); osg::Matrix res_matrix; res_matrix.makeRotate( - props.getFloatValue("/offsets/heading-deg", 0.0)*SG_DEGREES_TO_RADIANS, - osg::Vec3(0, 0, 1), + props.getFloatValue("/offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS, + osg::Vec3(0, 1, 0), props.getFloatValue("/offsets/roll-deg", 0.0)*SG_DEGREES_TO_RADIANS, osg::Vec3(1, 0, 0), - props.getFloatValue("/offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS, - osg::Vec3(0, 1, 0)); + props.getFloatValue("/offsets/heading-deg", 0.0)*SG_DEGREES_TO_RADIANS, + osg::Vec3(0, 0, 1)); osg::Matrix tmat; tmat.makeTranslate(props.getFloatValue("/offsets/x-m", 0.0), @@ -639,30 +501,28 @@ sgLoad3DModel( const string &fg_root, const string &path, props.getFloatValue("/offsets/z-m", 0.0)); alignmainmodel->setMatrix(res_matrix*tmat); - unsigned int i; - - // Load sub-models + // Load sub-models vector model_nodes = props.getChildren("model"); - for (i = 0; i < model_nodes.size(); i++) { + for (unsigned i = 0; i < model_nodes.size(); i++) { SGPropertyNode_ptr node = model_nodes[i]; - osg::MatrixTransform* align = new osg::MatrixTransform; + osg::ref_ptr align = new osg::MatrixTransform; res_matrix.makeIdentity(); res_matrix.makeRotate( - node->getFloatValue("offsets/heading-deg", 0.0)*SG_DEGREES_TO_RADIANS, - osg::Vec3(0, 0, 1), - node->getFloatValue("offsets/roll-deg", 0.0)*SG_DEGREES_TO_RADIANS, + node->getDoubleValue("offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS, + osg::Vec3(0, 1, 0), + node->getDoubleValue("offsets/roll-deg", 0.0)*SG_DEGREES_TO_RADIANS, osg::Vec3(1, 0, 0), - node->getFloatValue("offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS, - osg::Vec3(0, 1, 0)); + node->getDoubleValue("offsets/heading-deg", 0.0)*SG_DEGREES_TO_RADIANS, + osg::Vec3(0, 0, 1)); tmat.makeIdentity(); - tmat.makeTranslate(node->getFloatValue("offsets/x-m", 0.0), - node->getFloatValue("offsets/y-m", 0.0), - node->getFloatValue("offsets/z-m", 0.0)); + tmat.makeTranslate(node->getDoubleValue("offsets/x-m", 0), + node->getDoubleValue("offsets/y-m", 0), + node->getDoubleValue("offsets/z-m", 0)); align->setMatrix(res_matrix*tmat); - osg::Node* kid; - const char * submodel = node->getStringValue("path"); + osg::ref_ptr kid; + const char* submodel = node->getStringValue("path"); try { kid = sgLoad3DModel( fg_root, submodel, prop_root, sim_time_sec, load_panel ); @@ -670,47 +530,55 @@ sgLoad3DModel( const string &fg_root, const string &path, SG_LOG(SG_INPUT, SG_ALERT, "Failed to load submodel: " << t.getFormattedMessage()); throw; } - align->addChild(kid); + align->addChild(kid.get()); align->setName(node->getStringValue("name", "")); - model->addChild(align); SGPropertyNode *cond = node->getNode("condition", false); - if (cond) - model->setUpdateCallback(new SGSwitchUpdateCallback(sgReadCondition(prop_root, cond))); + if (cond) { + osg::ref_ptr sw = new osg::Switch; + sw->setUpdateCallback(new SGSwitchUpdateCallback(sgReadCondition(prop_root, cond))); + alignmainmodel->addChild(sw.get()); + sw->addChild(align.get()); + sw->setName("submodel condition switch"); + } else { + alignmainmodel->addChild(align.get()); + } } - // restore old path list - osgDB::setDataFilePathList(pathList); - if ( load_panel ) { - // Load panels + // Load panels vector panel_nodes = props.getChildren("panel"); - for (i = 0; i < panel_nodes.size(); i++) { + for (unsigned i = 0; i < panel_nodes.size(); i++) { SG_LOG(SG_INPUT, SG_DEBUG, "Loading a panel"); - osg::Node * panel = load_panel(panel_nodes[i]); + osg::ref_ptr panel = load_panel(panel_nodes[i]); if (panel_nodes[i]->hasValue("name")) panel->setName((char *)panel_nodes[i]->getStringValue("name")); - model->addChild(panel); + alignmainmodel->addChild(panel.get()); } } if (data) { alignmainmodel->setUserData(data); - data->modelLoaded(path, &props, alignmainmodel); + data->modelLoaded(path, &props, alignmainmodel.get()); } - // Load animations - set ignore_branches; - 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"); - sgMakeAnimation( model, name, name_nodes, prop_root, animation_nodes[i], - sim_time_sec, texturepath, ignore_branches); + + std::vector animation_nodes; + animation_nodes = props.getChildren("animation"); + for (unsigned i = 0; i < animation_nodes.size(); ++i) + /// OSGFIXME: duh, why not only model????? + SGAnimation::animate(alignmainmodel.get(), animation_nodes[i], prop_root); + + // restore old path list + osgDB::setDataFilePathList(pathList); + + if (props.hasChild("debug-outfile")) { + std::string outputfile = props.getStringValue("debug-outfile", + "debug-model.osg"); + osgDB::writeNodeFile(*alignmainmodel, outputfile); } - return alignmainmodel; + return alignmainmodel.release(); } // end of model.cxx