00001
00002
00003
00004
00005
00006 #ifdef HAVE_CONFIG_H
00007 #include <simgear_config.h>
00008 #endif
00009
00010 #include <utility>
00011
00012 #include <boost/foreach.hpp>
00013
00014 #include <osg/ref_ptr>
00015 #include <osgDB/FileNameUtils>
00016 #include <osgDB/FileUtils>
00017 #include <osgDB/ReaderWriter>
00018 #include <osgDB/ReadFile>
00019 #include <osgDB/SharedStateManager>
00020
00021 #include <simgear/math/SGMath.hxx>
00022 #include <simgear/scene/material/Effect.hxx>
00023 #include <simgear/scene/material/EffectGeode.hxx>
00024 #include <simgear/scene/util/SGSceneFeatures.hxx>
00025 #include <simgear/scene/util/SGSceneUserData.hxx>
00026 #include <simgear/scene/util/CopyOp.hxx>
00027 #include <simgear/scene/util/SplicingVisitor.hxx>
00028
00029
00030 #include <simgear/structure/exception.hxx>
00031 #include <simgear/structure/Singleton.hxx>
00032 #include <simgear/props/props.hxx>
00033 #include <simgear/props/props_io.hxx>
00034 #include <simgear/props/condition.hxx>
00035
00036 #include "model.hxx"
00037
00038 using std::vector;
00039
00040 osg::Texture2D*
00041 SGLoadTexture2D(bool staticTexture, const std::string& path,
00042 const osgDB::ReaderWriter::Options* options,
00043 bool wrapu, bool wrapv, int)
00044 {
00045 osg::Image* image;
00046 if (options)
00047 image = osgDB::readImageFile(path, options);
00048 else
00049 image = osgDB::readImageFile(path);
00050 osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
00051 texture->setImage(image);
00052 if (staticTexture)
00053 texture->setDataVariance(osg::Object::STATIC);
00054 if (wrapu)
00055 texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
00056 else
00057 texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);
00058 if (wrapv)
00059 texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
00060 else
00061 texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);
00062
00063 if (image) {
00064 int s = image->s();
00065 int t = image->t();
00066
00067 if (s <= t && 32 <= s) {
00068 SGSceneFeatures::instance()->setTextureCompression(texture.get());
00069 } else if (t < s && 32 <= t) {
00070 SGSceneFeatures::instance()->setTextureCompression(texture.get());
00071 }
00072 }
00073
00074 return texture.release();
00075 }
00076
00077 namespace simgear
00078 {
00079 using namespace std;
00080 using namespace osg;
00081 using simgear::CopyOp;
00082
00083 Node* copyModel(Node* model)
00084 {
00085 const CopyOp::CopyFlags flags = (CopyOp::DEEP_COPY_ALL
00086 & ~CopyOp::DEEP_COPY_TEXTURES
00087 & ~CopyOp::DEEP_COPY_IMAGES
00088 & ~CopyOp::DEEP_COPY_STATESETS
00089 & ~CopyOp::DEEP_COPY_STATEATTRIBUTES
00090 & ~CopyOp::DEEP_COPY_ARRAYS
00091 & ~CopyOp::DEEP_COPY_PRIMITIVES
00092
00093 & ~CopyOp::DEEP_COPY_DRAWABLES
00094 & ~CopyOp::DEEP_COPY_SHAPES);
00095 return (CopyOp(flags))(model);
00096 }
00097
00098 TextureUpdateVisitor::TextureUpdateVisitor(const osgDB::FilePathList& pathList) :
00099 NodeAndDrawableVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN),
00100 _pathList(pathList)
00101 {
00102 }
00103
00104 void TextureUpdateVisitor::apply(Node& node)
00105 {
00106 StateSet* stateSet = cloneStateSet(node.getStateSet());
00107 if (stateSet)
00108 node.setStateSet(stateSet);
00109 traverse(node);
00110 }
00111
00112 void TextureUpdateVisitor::apply(Drawable& drawable)
00113 {
00114 StateSet* stateSet = cloneStateSet(drawable.getStateSet());
00115 if (stateSet)
00116 drawable.setStateSet(stateSet);
00117 }
00118
00119 Texture2D* TextureUpdateVisitor::textureReplace(int unit, const StateAttribute* attr)
00120 {
00121 using namespace osgDB;
00122 const Texture2D* texture = dynamic_cast<const Texture2D*>(attr);
00123
00124 if (!texture)
00125 return 0;
00126
00127 const Image* image = texture->getImage();
00128 const string* fullFilePath = 0;
00129 if (image) {
00130
00131 fullFilePath = &image->getFileName();
00132
00133 } else {
00134 fullFilePath = &texture->getName();
00135 }
00136
00137 string fileName = getSimpleFileName(*fullFilePath);
00138 if (fileName.empty())
00139 return 0;
00140
00141 string fullLiveryFile = findFileInPath(fileName, _pathList);
00142
00143 if (fullLiveryFile.empty() || fullLiveryFile == *fullFilePath)
00144 return 0;
00145 Image* newImage = readImageFile(fullLiveryFile);
00146 if (!newImage)
00147 return 0;
00148 CopyOp copyOp(CopyOp::DEEP_COPY_ALL & ~CopyOp::DEEP_COPY_IMAGES);
00149 Texture2D* newTexture = static_cast<Texture2D*>(copyOp(texture));
00150 if (!newTexture) {
00151 return 0;
00152 } else {
00153 newTexture->setImage(newImage);
00154 return newTexture;
00155 }
00156 }
00157
00158 StateSet* TextureUpdateVisitor::cloneStateSet(const StateSet* stateSet)
00159 {
00160 typedef std::pair<int, Texture2D*> Tex2D;
00161 vector<Tex2D> newTextures;
00162 StateSet* result = 0;
00163
00164 if (!stateSet)
00165 return 0;
00166 int numUnits = stateSet->getTextureAttributeList().size();
00167 if (numUnits > 0) {
00168 for (int i = 0; i < numUnits; ++i) {
00169 const StateAttribute* attr
00170 = stateSet->getTextureAttribute(i, StateAttribute::TEXTURE);
00171 Texture2D* newTexture = textureReplace(i, attr);
00172 if (newTexture)
00173 newTextures.push_back(Tex2D(i, newTexture));
00174 }
00175 if (!newTextures.empty()) {
00176 result = static_cast<StateSet*>(stateSet->clone(CopyOp()));
00177 for (vector<Tex2D>::iterator i = newTextures.begin();
00178 i != newTextures.end();
00179 ++i) {
00180 result->setTextureAttribute(i->first, i->second);
00181 }
00182 }
00183 }
00184 return result;
00185 }
00186
00187 UserDataCopyVisitor::UserDataCopyVisitor() :
00188 NodeVisitor(NodeVisitor::NODE_VISITOR,
00189 NodeVisitor::TRAVERSE_ALL_CHILDREN)
00190 {
00191 }
00192
00193 void UserDataCopyVisitor::apply(Node& node)
00194 {
00195 ref_ptr<SGSceneUserData> userData;
00196 userData = SGSceneUserData::getSceneUserData(&node);
00197 if (userData.valid()) {
00198 SGSceneUserData* newUserData = new SGSceneUserData(*userData);
00199 newUserData->setVelocity(0);
00200 node.setUserData(newUserData);
00201 }
00202 node.traverse(*this);
00203 }
00204
00205 namespace
00206 {
00207 class MakeEffectVisitor : public SplicingVisitor
00208 {
00209 public:
00210 typedef std::map<string, SGPropertyNode_ptr> EffectMap;
00211 using SplicingVisitor::apply;
00212 MakeEffectVisitor(const osgDB::ReaderWriter::Options* options = 0)
00213 : _options(options)
00214 {
00215 }
00216 virtual void apply(osg::Group& node);
00217 virtual void apply(osg::Geode& geode);
00218 EffectMap& getEffectMap() { return _effectMap; }
00219 const EffectMap& getEffectMap() const { return _effectMap; }
00220 void setDefaultEffect(SGPropertyNode* effect)
00221 {
00222 _currentEffectParent = effect;
00223 }
00224 SGPropertyNode* getDefaultEffect() { return _currentEffectParent; }
00225 protected:
00226 EffectMap _effectMap;
00227 SGPropertyNode_ptr _currentEffectParent;
00228 osg::ref_ptr<const osgDB::ReaderWriter::Options> _options;
00229 };
00230
00231 void MakeEffectVisitor::apply(osg::Group& node)
00232 {
00233 SGPropertyNode_ptr savedEffectRoot;
00234 const string& nodeName = node.getName();
00235 bool restoreEffect = false;
00236 if (!nodeName.empty()) {
00237 EffectMap::iterator eitr = _effectMap.find(nodeName);
00238 if (eitr != _effectMap.end()) {
00239 savedEffectRoot = _currentEffectParent;
00240 _currentEffectParent = eitr->second;
00241 restoreEffect = true;
00242 }
00243 }
00244 SplicingVisitor::apply(node);
00245
00246 ref_ptr<SGSceneUserData> userData = SGSceneUserData::getSceneUserData(&node);
00247 if (userData.valid() && _childStack.back().back().get() != &node)
00248 _childStack.back().back()->setUserData(new SGSceneUserData(*userData));
00249 if (restoreEffect)
00250 _currentEffectParent = savedEffectRoot;
00251 }
00252
00253 void MakeEffectVisitor::apply(osg::Geode& geode)
00254 {
00255 if (pushNode(getNewNode(geode)))
00256 return;
00257 osg::StateSet* ss = geode.getStateSet();
00258 if (!ss) {
00259 pushNode(&geode);
00260 return;
00261 }
00262 SGPropertyNode_ptr ssRoot = new SGPropertyNode;
00263 makeParametersFromStateSet(ssRoot, ss);
00264 SGPropertyNode_ptr effectRoot = new SGPropertyNode;
00265 effect::mergePropertyTrees(effectRoot, ssRoot, _currentEffectParent);
00266 Effect* effect = makeEffect(effectRoot, true, _options);
00267 EffectGeode* eg = dynamic_cast<EffectGeode*>(&geode);
00268 if (eg) {
00269 eg->setEffect(effect);
00270 } else {
00271 eg = new EffectGeode;
00272 eg->setEffect(effect);
00273 ref_ptr<SGSceneUserData> userData = SGSceneUserData::getSceneUserData(&geode);
00274 if (userData.valid())
00275 eg->setUserData(new SGSceneUserData(*userData));
00276 for (int i = 0; i < geode.getNumDrawables(); ++i)
00277 eg->addDrawable(geode.getDrawable(i));
00278 }
00279 pushResultNode(&geode, eg);
00280
00281 }
00282
00283 }
00284
00285 namespace
00286 {
00287 class DefaultEffect : public simgear::Singleton<DefaultEffect>
00288 {
00289 public:
00290 DefaultEffect()
00291 {
00292 _effect = new SGPropertyNode;
00293 makeChild(_effect.ptr(), "inherits-from")
00294 ->setStringValue("Effects/model-default");
00295 }
00296 virtual ~DefaultEffect() {}
00297 SGPropertyNode* getEffect() { return _effect.ptr(); }
00298 protected:
00299 SGPropertyNode_ptr _effect;
00300 };
00301 }
00302
00303 ref_ptr<Node> instantiateEffects(osg::Node* modelGroup,
00304 PropertyList& effectProps,
00305 const osgDB::ReaderWriter::Options* options)
00306 {
00307 SGPropertyNode_ptr defaultEffectPropRoot;
00308 MakeEffectVisitor visitor(options);
00309 MakeEffectVisitor::EffectMap& emap = visitor.getEffectMap();
00310 for (PropertyList::iterator itr = effectProps.begin(),
00311 end = effectProps.end();
00312 itr != end;
00313 ++itr)
00314 {
00315 SGPropertyNode_ptr configNode = *itr;
00316 std::vector<SGPropertyNode_ptr> objectNames =
00317 configNode->getChildren("object-name");
00318 SGPropertyNode* defaultNode = configNode->getChild("default");
00319 if (defaultNode && defaultNode->getValue<bool>())
00320 defaultEffectPropRoot = configNode;
00321 BOOST_FOREACH(SGPropertyNode_ptr objNameNode, objectNames) {
00322 emap.insert(make_pair(objNameNode->getStringValue(), configNode));
00323 }
00324 configNode->removeChild("default");
00325 configNode->removeChildren("object-name");
00326 }
00327 if (!defaultEffectPropRoot)
00328 defaultEffectPropRoot = DefaultEffect::instance()->getEffect();
00329 visitor.setDefaultEffect(defaultEffectPropRoot.ptr());
00330 modelGroup->accept(visitor);
00331 osg::NodeList& result = visitor.getResults();
00332 return ref_ptr<Node>(result[0].get());
00333 }
00334 }
00335