]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/model.cxx
remove CopyPolicy from ModelRegistry
[simgear.git] / simgear / scene / model / model.cxx
1 // model.cxx - manage a 3D aircraft model.
2 // Written by David Megginson, started 2002.
3 //
4 // This file is in the Public Domain, and comes with no warranty.
5
6 #ifdef HAVE_CONFIG_H
7 #include <simgear_config.h>
8 #endif
9
10 #include <utility>
11
12 #include <osg/ref_ptr>
13 #include <osgDB/FileNameUtils>
14 #include <osgDB/FileUtils>
15 #include <osgDB/ReaderWriter>
16 #include <osgDB/ReadFile>
17 #include <osgDB/SharedStateManager>
18
19 #include <simgear/scene/util/SGSceneFeatures.hxx>
20 #include <simgear/scene/util/SGSceneUserData.hxx>
21
22 #include <simgear/structure/exception.hxx>
23 #include <simgear/props/props.hxx>
24 #include <simgear/props/props_io.hxx>
25 #include <simgear/props/condition.hxx>
26
27 #include "model.hxx"
28
29 using std::vector;
30
31 osg::Texture2D*
32 SGLoadTexture2D(bool staticTexture, const std::string& path,
33                 const osgDB::ReaderWriter::Options* options,
34                 bool wrapu, bool wrapv, int)
35 {
36   osg::Image* image;
37   if (options)
38     image = osgDB::readImageFile(path, options);
39   else
40     image = osgDB::readImageFile(path);
41   osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
42   texture->setImage(image);
43   if (staticTexture)
44     texture->setDataVariance(osg::Object::STATIC);
45   if (wrapu)
46     texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
47   else
48     texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);
49   if (wrapv)
50     texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
51   else
52     texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);
53
54   if (image) {
55     int s = image->s();
56     int t = image->t();
57
58     if (s <= t && 32 <= s) {
59       SGSceneFeatures::instance()->setTextureCompression(texture.get());
60     } else if (t < s && 32 <= t) {
61       SGSceneFeatures::instance()->setTextureCompression(texture.get());
62     }
63   }
64
65   return texture.release();
66 }
67
68 namespace simgear
69 {
70 using namespace osg;
71
72 Node* copyModel(Node* model)
73 {
74     CopyOp::CopyFlags flags = CopyOp::DEEP_COPY_ALL;
75     flags &= ~CopyOp::DEEP_COPY_TEXTURES;
76     flags &= ~CopyOp::DEEP_COPY_IMAGES;
77     flags &= ~CopyOp::DEEP_COPY_STATESETS;
78     flags &= ~CopyOp::DEEP_COPY_STATEATTRIBUTES;
79     flags &= ~CopyOp::DEEP_COPY_ARRAYS;
80     flags &= ~CopyOp::DEEP_COPY_PRIMITIVES;
81     // This will preserve display lists ...
82     flags &= ~CopyOp::DEEP_COPY_DRAWABLES;
83     flags &= ~CopyOp::DEEP_COPY_SHAPES;
84     return static_cast<Node*>(model->clone(CopyOp(flags)));
85 }
86
87 TextureUpdateVisitor::TextureUpdateVisitor(const osgDB::FilePathList& pathList) :
88     NodeAndDrawableVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN),
89     _pathList(pathList)
90 {
91 }
92
93 void TextureUpdateVisitor::apply(Node& node)
94 {
95     StateSet* stateSet = cloneStateSet(node.getStateSet());
96     if (stateSet)
97         node.setStateSet(stateSet);
98     traverse(node);
99 }
100
101 void TextureUpdateVisitor::apply(Drawable& drawable)
102 {
103     StateSet* stateSet = cloneStateSet(drawable.getStateSet());
104     if (stateSet)
105         drawable.setStateSet(stateSet);
106 }
107
108 Texture2D* TextureUpdateVisitor::textureReplace(int unit, const StateAttribute* attr)
109 {
110     using namespace osgDB;
111     const Texture2D* texture = dynamic_cast<const Texture2D*>(attr);
112
113     if (!texture)
114         return 0;
115
116     const Image* image = texture->getImage();
117     const string* fullFilePath = 0;
118     if (image) {
119         // The currently loaded file name
120         fullFilePath = &image->getFileName();
121
122     } else {
123         fullFilePath = &texture->getName();
124     }
125     // The short name
126     string fileName = getSimpleFileName(*fullFilePath);
127     if (fileName.empty())
128         return 0;
129     // The name that should be found with the current database path
130     string fullLiveryFile = findFileInPath(fileName, _pathList);
131     // If it is empty or they are identical then there is nothing to do
132     if (fullLiveryFile.empty() || fullLiveryFile == *fullFilePath)
133         return 0;
134     Image* newImage = readImageFile(fullLiveryFile);
135     if (!newImage)
136         return 0;
137     CopyOp copyOp(CopyOp::DEEP_COPY_ALL & ~CopyOp::DEEP_COPY_IMAGES);
138     Texture2D* newTexture = static_cast<Texture2D*>(copyOp(texture));
139     if (!newTexture) {
140         return 0;
141     } else {
142         newTexture->setImage(newImage);
143         return newTexture;
144     }
145 }
146
147 StateSet* TextureUpdateVisitor::cloneStateSet(const StateSet* stateSet)
148 {
149     typedef std::pair<int, Texture2D*> Tex2D;
150     vector<Tex2D> newTextures;
151     StateSet* result = 0;
152
153     if (!stateSet)
154         return 0;
155     int numUnits = stateSet->getTextureAttributeList().size();
156     if (numUnits > 0) {
157         for (int i = 0; i < numUnits; ++i) {
158             const StateAttribute* attr
159                 = stateSet->getTextureAttribute(i, StateAttribute::TEXTURE);
160             Texture2D* newTexture = textureReplace(i, attr);
161             if (newTexture)
162                 newTextures.push_back(Tex2D(i, newTexture));
163         }
164         if (!newTextures.empty()) {
165             result = static_cast<StateSet*>(stateSet->clone(CopyOp()));
166             for (vector<Tex2D>::iterator i = newTextures.begin();
167                  i != newTextures.end();
168                  ++i) {
169                 result->setTextureAttribute(i->first, i->second);
170             }
171         }
172     }
173     return result;
174 }
175
176 UserDataCopyVisitor::UserDataCopyVisitor() :
177     NodeVisitor(NodeVisitor::NODE_VISITOR,
178                 NodeVisitor::TRAVERSE_ALL_CHILDREN)
179 {
180 }
181
182 void UserDataCopyVisitor::apply(Node& node)
183 {
184     ref_ptr<SGSceneUserData> userData;
185     userData = SGSceneUserData::getSceneUserData(&node);
186     if (userData.valid()) {
187         SGSceneUserData* newUserData  = new SGSceneUserData(*userData);
188         newUserData->setVelocity(0);
189         node.setUserData(newUserData);
190     }
191     node.traverse(*this);
192 }
193
194 }
195 // end of model.cxx