<Filter
Name="Lib_sgutil"
Filter="">
+ <File
+ RelativePath="..\..\simgear\scene\util\CopyOp.cxx">
+ </File>
+ <File
+ RelativePath="..\..\simgear\scene\util\CopyOp.hxx">
+ </File>
<File
RelativePath="..\..\simgear\scene\util\NodeAndDrawableVisitor.cxx">
</File>
<Filter
Name="Lib_sgutil"
>
+ <File
+ RelativePath="..\..\simgear\scene\util\CopyOp.cxx"
+ >
+ </File>
+ <File
+ RelativePath="..\..\simgear\scene\util\CopyOp.hxx"
+ >
+ </File>
<File
RelativePath="..\..\simgear\scene\util\NodeAndDrawableVisitor.cxx"
>
#include <map>
#include <utility>
-#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tuple/tuple.hpp>
Effect::Effect(const Effect& rhs, const CopyOp& copyop)
: root(rhs.root), parametersProp(rhs.parametersProp)
{
- using namespace boost;
- transform(rhs.techniques.begin(), rhs.techniques.end(),
- back_inserter(techniques),
- bind(simgear::clone_ref<Technique>, _1, copyop));
+ typedef vector<ref_ptr<Technique> > TechniqueList;
+ for (TechniqueList::const_iterator itr = rhs.techniques.begin(),
+ end = rhs.techniques.end();
+ itr != end;
+ ++itr)
+ techniques.push_back(static_cast<Technique*>(copyop(itr->get())));
}
// Assume that the last technique is always valid.
}
}
+// The description of an attribute may exist in a pass' XML, but a
+// derived effect might want to disable the attribute altogether. So,
+// some attributes have an "active" property; if it exists and is
+// false, the OSG attribute is not built at all. This is different
+// from any OSG mode settings that might be around.
+
+bool isAttributeActive(Effect* effect, const SGPropertyNode* prop)
+{
+ const SGPropertyNode* activeProp
+ = getEffectPropertyChild(effect, prop, "active");
+ return !activeProp || activeProp->getValue<bool>();
+}
+
struct LightingBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
InstallAttributeBuilder<CullFaceBuilder> installCullFace("cull-face");
+EffectNameValue<StateSet::RenderingHint> renderingHintInit[] =
+{
+ { "default", StateSet::DEFAULT_BIN },
+ { "opaque", StateSet::OPAQUE_BIN },
+ { "transparent", StateSet::TRANSPARENT_BIN }
+};
+
+EffectPropertyMap<StateSet::RenderingHint> renderingHints(renderingHintInit);
+
struct HintBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
if (!realProp)
return;
- string propVal = realProp->getStringValue();
- if (propVal == "opaque")
- pass->setRenderingHint(StateSet::OPAQUE_BIN);
- else if (propVal == "transparent")
- pass->setRenderingHint(StateSet::TRANSPARENT_BIN);
+ StateSet::RenderingHint renderingHint = StateSet::DEFAULT_BIN;
+ findAttr(renderingHints, realProp, renderingHint);
+ pass->setRenderingHint(renderingHint);
}
};
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
{
+ if (!isAttributeActive(effect, prop))
+ return;
const SGPropertyNode* binProp = prop->getChild("bin-number");
binProp = getEffectPropertyNode(effect, binProp);
const SGPropertyNode* nameProp = prop->getChild("bin-name");
const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
{
+ if (!isAttributeActive(effect, prop))
+ return;
Material* mat = new Material;
const SGPropertyNode* color = 0;
if ((color = getEffectPropertyChild(effect, prop, "ambient")))
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
{
+ if (!isAttributeActive(effect, prop))
+ return;
// XXX Compatibility with early <blend> syntax; should go away
// before a release
const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
pass->setMode(GL_BLEND, StateAttribute::OFF);
return;
}
- const SGPropertyNode* psource = getEffectPropertyChild(effect, prop,
- "source");
+ const SGPropertyNode* psource
+ = getEffectPropertyChild(effect, prop, "source");
const SGPropertyNode* pdestination
= getEffectPropertyChild(effect, prop, "destination");
const SGPropertyNode* psourceRGB
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
{
+ if (!isAttributeActive(effect, prop))
+ return;
// XXX Compatibility with early <alpha-test> syntax; should go away
// before a release
const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
{
-
+ if (!isAttributeActive(effect, prop))
+ return;
// Decode the texture unit
int unit = 0;
const SGPropertyNode* pUnit = prop->getChild("unit");
<< lex.what());
}
}
- const SGPropertyNode* pType = prop->getChild("type");
+ const SGPropertyNode* pType = getEffectPropertyChild(effect, prop, "type");
string type;
if (!pType)
type = "2d";
const osgDB::ReaderWriter::Options*
options)
{
+ if (!isAttributeActive(effect, prop))
+ return;
PropertyList pVertShaders = prop->getChildren("vertex-shader");
PropertyList pFragShaders = prop->getChildren("fragment-shader");
string programKey;
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
{
+ if (!isAttributeActive(effect, prop))
+ return;
const SGPropertyNode* nameProp = prop->getChild("name");
const SGPropertyNode* typeProp = prop->getChild("type");
const SGPropertyNode* valProp
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
{
+ if (!isAttributeActive(effect, prop))
+ return;
const SGPropertyNode* frontProp
= getEffectPropertyChild(effect, prop, "front");
const SGPropertyNode* backProp
}
// Specifically for .ac files...
-bool makeParametersFromStateSet(SGPropertyNode* paramRoot, const StateSet* ss)
+bool makeParametersFromStateSet(SGPropertyNode* effectRoot, const StateSet* ss)
{
+ SGPropertyNode* paramRoot = makeChild(effectRoot, "parameters");
SGPropertyNode* matNode = paramRoot->getChild("material", 0, true);
Vec4f ambVal, difVal, specVal, emisVal;
float shininess = 0.0f;
specVal = mat->getSpecular(Material::FRONT_AND_BACK);
emisVal = mat->getEmission(Material::FRONT_AND_BACK);
shininess = mat->getShininess(Material::FRONT_AND_BACK);
+ makeChild(matNode, "active")->setValue(true);
+ makeChild(matNode, "ambient")->setValue(toVec4d(toSG(ambVal)));
+ makeChild(matNode, "diffuse")->setValue(toVec4d(toSG(difVal)));
+ makeChild(matNode, "specular")->setValue(toVec4d(toSG(specVal)));
+ makeChild(matNode, "emissive")->setValue(toVec4d(toSG(emisVal)));
+ makeChild(matNode, "shininess")->setValue(shininess);
+ matNode->getChild("color-mode", 0, true)->setStringValue("diffuse");
+ } else {
+ makeChild(matNode, "active")->setValue(false);
}
- matNode->getChild("ambient", 0, true)->setValue(toVec4d(toSG(ambVal)));
- matNode->getChild("diffuse", 0, true)->setValue(toVec4d(toSG(difVal)));
- matNode->getChild("specular", 0, true)->setValue(toVec4d(toSG(specVal)));
- matNode->getChild("emissive", 0, true)->setValue(toVec4d(toSG(emisVal)));
- matNode->getChild("shininess", 0, true)->setValue(shininess);
- matNode->getChild("color-mode", 0, true)->setStringValue("diffuse");
const ShadeModel* sm = getStateAttribute<ShadeModel>(ss);
string shadeModelString("smooth");
if (sm) {
if (smMode == ShadeModel::FLAT)
shadeModelString = "flat";
}
- paramRoot->getChild("shade-model", 0, true)
- ->setStringValue(shadeModelString);
+ makeChild(paramRoot, "shade-model")->setStringValue(shadeModelString);
string cullFaceString("off");
const CullFace* cullFace = getStateAttribute<CullFace>(ss);
if (cullFace) {
break;
}
}
- paramRoot->getChild("cull-face", 0, true)->setStringValue(cullFaceString);
+ makeChild(paramRoot, "cull-face")->setStringValue(cullFaceString);
const BlendFunc* blendFunc = getStateAttribute<BlendFunc>(ss);
+ SGPropertyNode* blendNode = makeChild(paramRoot, "blend");
if (blendFunc) {
string sourceMode = findName(blendFuncModes, blendFunc->getSource());
string destMode = findName(blendFuncModes, blendFunc->getDestination());
- SGPropertyNode* blendNode = paramRoot->getChild("blend", 0, true);
- blendNode->getChild("source", 0, true)->setStringValue(sourceMode);
- blendNode->getChild("destination", 0, true)->setStringValue(destMode);
- blendNode->getChild("mode", 0, true)->setValue(true);
+ makeChild(blendNode, "active")->setValue(true);
+ makeChild(blendNode, "source")->setStringValue(sourceMode);
+ makeChild(blendNode, "destination")->setStringValue(destMode);
+ makeChild(blendNode, "mode")->setValue(true);
+ } else {
+ makeChild(blendNode, "active")->setValue(false);
}
makeTextureParameters(paramRoot, ss);
return true;
bool makeParametersFromStateSet(SGPropertyNode* paramRoot,
const osg::StateSet* ss);
+
+namespace effect
+{
+/**
+ * The function that implements effect property tree inheritance.
+ */
+void mergePropertyTrees(SGPropertyNode* resultNode,
+ const SGPropertyNode* left,
+ const SGPropertyNode* right);
+}
}
#endif
{
}
-EffectGeode::EffectGeode(const EffectGeode& rhs, const CopyOp& copyop) :
- Geode(rhs, copyop)
+EffectGeode::EffectGeode(const EffectGeode& rhs, const osg::CopyOp& copyop) :
+ Geode(rhs, copyop),
+ _effect(static_cast<Effect*>(copyop(rhs._effect.get())))
{
- _effect = static_cast<Effect*>(rhs._effect->clone(copyop));
}
void EffectGeode::resizeGLObjectBuffers(unsigned int maxSize)
#include "Technique.hxx"
#include "Pass.hxx"
-#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <iterator>
Technique::Technique(const Technique& rhs, const osg::CopyOp& copyop) :
_contextMap(rhs._contextMap), _alwaysValid(rhs._alwaysValid),
- _shadowingStateSet(rhs._shadowingStateSet),
+ _shadowingStateSet(copyop(rhs._shadowingStateSet)),
_validExpression(rhs._validExpression),
_contextIdLocation(rhs._contextIdLocation)
{
- using namespace std;
- using namespace boost;
- transform(rhs.passes.begin(), rhs.passes.end(),
- back_inserter(passes),
- bind(simgear::clone_ref<Pass>, _1, copyop));
-
+ for (std::vector<ref_ptr<Pass> >::const_iterator itr = rhs.passes.begin(),
+ end = rhs.passes.end();
+ itr != end;
+ ++itr)
+ passes.push_back(static_cast<Pass*>(copyop(itr->get())));
}
Technique::~Technique()
bool makeTextureParameters(SGPropertyNode* paramRoot, const StateSet* ss)
{
+ SGPropertyNode* texUnit = makeChild(paramRoot, "texture");
const Texture* tex = getStateAttribute<Texture>(0, ss);
const Texture2D* texture = dynamic_cast<const Texture2D*>(tex);
- if (!tex)
+ makeChild(texUnit, "unit")->setValue(0);
+ if (!tex) {
+ makeChild(texUnit, "active")->setValue(false);
+ makeChild(texUnit, "type")->setValue("white");
return false;
+ }
const Image* image = texture->getImage();
string imageName;
- if (image)
+ if (image) {
imageName = image->getFileName();
+ } else {
+ makeChild(texUnit, "active")->setValue(false);
+ makeChild(texUnit, "type")->setValue("white");
+ return false;
+ }
+ makeChild(texUnit, "active")->setValue(true);
+ makeChild(texUnit, "type")->setValue("2d");
string wrapS = findName(wrapModes, texture->getWrap(Texture::WRAP_S));
string wrapT = findName(wrapModes, texture->getWrap(Texture::WRAP_T));
string wrapR = findName(wrapModes, texture->getWrap(Texture::WRAP_R));
- SGPropertyNode* texUnit = makeChild(paramRoot, "texture-unit");
- makeChild(texUnit, "unit")->setValue(0);
makeChild(texUnit, "image")->setStringValue(imageName);
makeChild(texUnit, "wrap-s")->setStringValue(wrapS);
makeChild(texUnit, "wrap-t")->setStringValue(wrapT);
{
using namespace std;
using namespace osg;
+using namespace effect;
typedef vector<const SGPropertyNode*> RawPropVector;
typedef map<const string, ref_ptr<Effect> > EffectMap;
const SGPropertyNode* node;
};
+namespace effect
+{
void mergePropertyTrees(SGPropertyNode* resultNode,
const SGPropertyNode* left, const SGPropertyNode* right)
{
copyProperties(*itr, newChild);
}
}
+}
Effect* makeEffect(const string& name,
bool realizeTechniques,
# include <simgear_config.h>
#endif
+#include <osg/Geode>
#include <osg/MatrixTransform>
#include <osgDB/WriteFile>
#include <osgDB/Registry>
#include "model.hxx"
#include "SGText.hxx"
+using namespace std;
using namespace simgear;
+using namespace osg;
static osg::Node *
sgLoad3DModel_internal(const std::string& path,
texturepath = texturepath.dir();
options->setDatabasePath(texturepath.str());
- osg::Node* origModel
- = osgDB::readNodeFile(modelpath.str(), options.get());
-
- if (!origModel)
+ osgDB::ReaderWriter::ReadResult modelResult
+ = osgDB::Registry::instance()->readNode(modelpath.str(),
+ options.get());
+ if (!modelResult.validNode())
throw sg_io_exception("Failed to load 3D model",
sg_location(modelpath.str()));
- model = copyModel(origModel);
+ model = copyModel(modelResult.getNode());
// Add an extra reference to the model stored in the database.
// That is to avoid expiring the object from the cache even if
// it is still in use. Note that the object cache will think
// clone all structural nodes here we need that extra
// reference to the original object
SGDatabaseReference* databaseReference;
- databaseReference = new SGDatabaseReference(origModel);
+ databaseReference = new SGDatabaseReference(modelResult.getNode());
model->addObserver(databaseReference);
// Update liveries
SGPath submodelpath;
osg::ref_ptr<osg::Node> submodel;
string submodelFileName = sub_props->getStringValue("path");
- if ( submodelFileName.size() > 2 && submodelFileName.substr( 0, 2 ) == "./" ) {
+ if (submodelFileName.size() > 2
+ && !submodelFileName.compare(0, 2, "./" )) {
submodelpath = modelpath.dir();
submodelpath.append( submodelFileName.substr( 2 ) );
} else {
throw;
}
- osg::ref_ptr<osg::Node> submodel_final=submodel.get();
+ osg::ref_ptr<osg::Node> submodel_final = submodel;
SGPropertyNode *offs = sub_props->getNode("offsets", false);
if (offs) {
osg::Matrix res_matrix;
offs->getDoubleValue("z-m", 0));
align->setMatrix(res_matrix*tmat);
align->addChild(submodel.get());
- submodel_final=align.get();
+ submodel_final = align;
}
submodel_final->setName(sub_props->getStringValue("name", ""));
prop_root,
options.get()));
}
-
+ PropertyList effect_nodes = props->getChildren("effect");
+ {
+ ref_ptr<Node> modelWithEffects
+ = instantiateEffects(group.get(), effect_nodes, options.get());
+ group = static_cast<Group*>(modelWithEffects.get());
+ }
std::vector<SGPropertyNode_ptr> animation_nodes;
animation_nodes = props->getChildren("animation");
for (unsigned i = 0; i < animation_nodes.size(); ++i)
#include <utility>
+#include <boost/foreach.hpp>
+
#include <osg/ref_ptr>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/ReadFile>
#include <osgDB/SharedStateManager>
+#include <simgear/scene/material/Effect.hxx>
+#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/SGSceneUserData.hxx>
+#include <simgear/scene/util/CopyOp.hxx>
+#include <simgear/scene/util/SplicingVisitor.hxx>
+
#include <simgear/structure/exception.hxx>
+#include <simgear/structure/Singleton.hxx>
#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx>
namespace simgear
{
+using namespace std;
using namespace osg;
+using simgear::CopyOp;
Node* copyModel(Node* model)
{
- CopyOp::CopyFlags flags = CopyOp::DEEP_COPY_ALL;
- flags &= ~CopyOp::DEEP_COPY_TEXTURES;
- flags &= ~CopyOp::DEEP_COPY_IMAGES;
- flags &= ~CopyOp::DEEP_COPY_STATESETS;
- flags &= ~CopyOp::DEEP_COPY_STATEATTRIBUTES;
- flags &= ~CopyOp::DEEP_COPY_ARRAYS;
- flags &= ~CopyOp::DEEP_COPY_PRIMITIVES;
- // This will preserve display lists ...
- flags &= ~CopyOp::DEEP_COPY_DRAWABLES;
- flags &= ~CopyOp::DEEP_COPY_SHAPES;
- return static_cast<Node*>(model->clone(CopyOp(flags)));
+ const CopyOp::CopyFlags flags = (CopyOp::DEEP_COPY_ALL
+ & ~CopyOp::DEEP_COPY_TEXTURES
+ & ~CopyOp::DEEP_COPY_IMAGES
+ & ~CopyOp::DEEP_COPY_STATESETS
+ & ~CopyOp::DEEP_COPY_STATEATTRIBUTES
+ & ~CopyOp::DEEP_COPY_ARRAYS
+ & ~CopyOp::DEEP_COPY_PRIMITIVES
+ // This will preserve display lists ...
+ & ~CopyOp::DEEP_COPY_DRAWABLES
+ & ~CopyOp::DEEP_COPY_SHAPES);
+ return (CopyOp(flags))(model);
}
TextureUpdateVisitor::TextureUpdateVisitor(const osgDB::FilePathList& pathList) :
node.traverse(*this);
}
+namespace
+{
+class MakeEffectVisitor : public SplicingVisitor
+{
+public:
+ typedef std::map<string, SGPropertyNode_ptr> EffectMap;
+ using SplicingVisitor::apply;
+ MakeEffectVisitor(const osgDB::ReaderWriter::Options* options = 0)
+ : _options(options)
+ {
+ }
+ virtual void apply(osg::Node& node);
+ virtual void apply(osg::Geode& geode);
+ EffectMap& getEffectMap() { return _effectMap; }
+ const EffectMap& getEffectMap() const { return _effectMap; }
+ void setDefaultEffect(SGPropertyNode* effect)
+ {
+ _currentEffectParent = effect;
+ }
+ SGPropertyNode* getDefaultEffect() { return _currentEffectParent; }
+protected:
+ EffectMap _effectMap;
+ SGPropertyNode_ptr _currentEffectParent;
+ osg::ref_ptr<const osgDB::ReaderWriter::Options> _options;
+};
+
+void MakeEffectVisitor::apply(osg::Node& node)
+{
+ SGPropertyNode_ptr savedEffectRoot;
+ const string& nodeName = node.getName();
+ bool restoreEffect = false;
+ if (!nodeName.empty()) {
+ EffectMap::iterator eitr = _effectMap.find(nodeName);
+ if (eitr != _effectMap.end()) {
+ savedEffectRoot = _currentEffectParent;
+ _currentEffectParent = eitr->second;
+ restoreEffect = true;
+ }
+ }
+ SplicingVisitor::apply(node);
+ if (restoreEffect)
+ _currentEffectParent = savedEffectRoot;
+}
+
+void MakeEffectVisitor::apply(osg::Geode& geode)
+{
+ if (pushNode(getNewNode(geode)))
+ return;
+ osg::StateSet* ss = geode.getStateSet();
+ if (!ss) {
+ pushNode(&geode);
+ return;
+ }
+ SGPropertyNode_ptr ssRoot = new SGPropertyNode;
+ makeParametersFromStateSet(ssRoot, ss);
+ SGPropertyNode_ptr effectRoot = new SGPropertyNode;
+ effect::mergePropertyTrees(effectRoot, ssRoot, _currentEffectParent);
+ Effect* effect = makeEffect(effectRoot, true, _options);
+ EffectGeode* eg = dynamic_cast<EffectGeode*>(&geode);
+ if (eg) {
+ eg->setEffect(effect);
+ } else {
+ eg = new EffectGeode;
+ eg->setEffect(effect);
+ for (int i = 0; i < geode.getNumDrawables(); ++i)
+ eg->addDrawable(geode.getDrawable(i));
+ }
+ pushResultNode(&geode, eg);
+
+}
+
+}
+
+namespace
+{
+class DefaultEffect : public simgear::Singleton<DefaultEffect>
+{
+public:
+ DefaultEffect()
+ {
+ _effect = new SGPropertyNode;
+ makeChild(_effect.ptr(), "inherits-from")
+ ->setStringValue("Effects/model-default");
+ }
+ virtual ~DefaultEffect() {}
+ SGPropertyNode* getEffect() { return _effect.ptr(); }
+protected:
+ SGPropertyNode_ptr _effect;
+};
+}
+
+ref_ptr<Node> instantiateEffects(osg::Node* modelGroup,
+ PropertyList& effectProps,
+ const osgDB::ReaderWriter::Options* options)
+{
+ SGPropertyNode_ptr defaultEffectPropRoot;
+ MakeEffectVisitor visitor(options);
+ MakeEffectVisitor::EffectMap& emap = visitor.getEffectMap();
+ for (PropertyList::iterator itr = effectProps.begin(),
+ end = effectProps.end();
+ itr != end;
+ ++itr)
+ {
+ SGPropertyNode_ptr configNode = *itr;
+ std::vector<SGPropertyNode_ptr> objectNames =
+ configNode->getChildren("object-name");
+ SGPropertyNode* defaultNode = configNode->getChild("default");
+ if (defaultNode && defaultNode->getValue<bool>())
+ defaultEffectPropRoot = configNode;
+ BOOST_FOREACH(SGPropertyNode_ptr objNameNode, objectNames) {
+ emap.insert(make_pair(objNameNode->getStringValue(), configNode));
+ }
+ configNode->removeChild("default");
+ configNode->removeChildren("object-name");
+ }
+ if (!defaultEffectPropRoot)
+ defaultEffectPropRoot = DefaultEffect::instance()->getEffect();
+ visitor.setDefaultEffect(defaultEffectPropRoot.ptr());
+ modelGroup->accept(visitor);
+ osg::NodeList& result = visitor.getResults();
+ return ref_ptr<Node>(result[0].get());
+}
}
// end of model.cxx
#include <osgDB/ReaderWriter>
#include <simgear/misc/sg_path.hxx>
+#include <simgear/props/props.hxx>
#include <simgear/scene/util/NodeAndDrawableVisitor.hxx>
osg::Texture2D*
virtual void apply(osg::Node& node);
};
+/**
+ * Transform an OSG subgraph by substituting Effects and EffectGeodes
+ * for osg::Geodes with osg::StateSets. This is only guaranteed to
+ * work for models prouced by the .ac loader.
+ *
+ * returns a copy if any nodes are changed
+ */
+osg::ref_ptr<osg::Node>
+instantiateEffects(osg::Node* model,
+ PropertyList& effectProps,
+ const osgDB::ReaderWriter::Options* options);
+
+/**
+ * Transform an OSG subgraph by substituting the Effects and
+ * EffectGeodes for osg::Geodes with osg::StateSets, inheriting from
+ * the default model effect. This is only guaranteed to work for
+ * models prouced by the .ac loader.
+ *
+ * returns a copy if any nodes are changed
+ */
+
+inline osg::ref_ptr<osg::Node>
+instantiateEffects(osg::Node* model,
+ const osgDB::ReaderWriter::Options* options)
+{
+ PropertyList effectProps;
+ return instantiateEffects(model, effectProps, options);
+}
}
#endif // __MODEL_HXX
# include <simgear_config.h>
#endif
+#include <boost/algorithm/string.hpp>
+
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgDB/Registry>
#include <simgear/constants.h>
#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
+#include <simgear/scene/model/model.hxx>
#include <simgear/scene/model/ModelRegistry.hxx>
#include "SGPagedLOD.hxx"
{
}
+namespace
+{
+osg::Node* loadFile(const string& path, osgDB::ReaderWriter::Options* options)
+{
+ using namespace osg;
+ using namespace osgDB;
+ ref_ptr<Node> model = readRefNodeFile(path, options);
+ if (!model)
+ return 0;
+ if (boost::iends_with(path, ".ac"))
+ model = instantiateEffects(model.get(), options);
+ return model.release();
+}
+}
+
osg::Node*
SGModelLib::loadModel(const string &path,
SGPropertyNode *prop_root,
osg::ref_ptr<SGReaderWriterXMLOptions> opt = new SGReaderWriterXMLOptions(*(osgDB::Registry::instance()->getOptions()));
opt->setPropRoot(prop_root);
opt->setModelData(data);
- osg::Node *n = readNodeFile(path, opt.get());
+ osg::Node *n = loadFile(path, opt.get());
if (n && n->getName().empty())
n->setName("Direct loaded model \"" + path + "\"");
return n;
osg::ref_ptr<SGReaderWriterXMLOptions> opt = new SGReaderWriterXMLOptions(*(osgDB::Registry::instance()->getOptions()));
opt->setPropRoot(prop_root);
opt->setLoadPanel(pf);
- return readNodeFile(path, opt.get());
+ return loadFile(path, opt.get());
}
osg::Node*
--- /dev/null
+// CopyOp.cxx - Simgear CopyOp for copying our own classes
+//
+// Copyright (C) 2009 Tim Moore timoore@redhat.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+#include "CopyOp.hxx"
+
+#include <simgear/scene/material/Effect.hxx>
+#include <simgear/scene/material/Technique.hxx>
+
+namespace simgear
+{
+osg::Object* CopyOp::operator()(const osg::Object* obj) const
+{
+ if (dynamic_cast<const Effect*>(obj)
+ || dynamic_cast<const Technique*>(obj)) {
+ if (_flags & DEEP_COPY_STATESETS)
+ return obj->clone(*this);
+ else
+ return const_cast<osg::Object*>(obj);
+ }
+ else {
+ return osg::CopyOp::operator()(obj);
+ }
+}
+}
--- /dev/null
+// CopyOp.hxx - Simgear CopyOp for copying our own classes
+//
+// Copyright (C) 2009 Tim Moore timoore@redhat.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+#ifndef SIMGEAR_COPYOP_HXX
+#define SIMGEAR_COPYOP_HXX 1
+#include <osg/CopyOp>
+
+namespace simgear
+{
+class CopyOp : public osg::CopyOp
+{
+public:
+ CopyOp(osg::CopyOp::CopyFlags flags = osg::CopyOp::SHALLOW_COPY)
+ : osg::CopyOp(flags)
+ {
+ }
+ using osg::CopyOp::operator();
+ virtual osg::Object* operator()(const osg::Object* obj) const;
+};
+}
+#endif
SGStateAttributeVisitor.hxx \
SGTextureStateAttributeVisitor.hxx \
SGUpdateVisitor.hxx \
+ CopyOp.hxx \
NodeAndDrawableVisitor.hxx \
PrimitiveUtils.hxx \
QuadTreeBuilder.hxx \
SGSceneUserData.cxx \
SGStateAttributeVisitor.cxx \
SGTextureStateAttributeVisitor.cxx \
+ CopyOp.cxx \
NodeAndDrawableVisitor.cxx \
PrimitiveUtils.cxx \
SplicingVisitor.cxx \