root/OpenSceneGraph/trunk/src/osgPlugins/fbx/WriterNodeVisitor.h @ 13466

Revision 13466, 9.2 kB (checked in by robert, 19 minutes ago)

Removed checks against Drawable as these are no longer required.

  • Property svn:eol-style set to native
Line 
1// -*-c++-*-
2
3/*
4 * FBX writer for Open Scene Graph
5 *
6 * Copyright (C) 2009
7 *
8 * Writing support added 2009 by Thibault Caporal and Sukender (Benoit Neil - http://sukender.free.fr)
9 *
10 * The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
11 * real-time rendering of large 3D photo-realistic models.
12 * The OSG homepage is http://www.openscenegraph.org/
13 */
14
15#ifndef _FBX_WRITER_NODE_VISITOR_HEADER__
16#define _FBX_WRITER_NODE_VISITOR_HEADER__
17
18#include <map>
19#include <set>
20#include <stack>
21#include <osg/Geometry>
22#include <osg/Material>
23#include <osg/NodeVisitor>
24#include <osg/PrimitiveSet>
25#include <osgDB/FileNameUtils>
26#include <osgDB/ReaderWriter>
27#include <osgDB/ExternalFileWriter>
28
29#if defined(_MSC_VER)
30#pragma warning( disable : 4505 )
31#pragma warning( default : 4996 )
32#endif
33#include <fbxsdk.h>
34
35struct Triangle
36{
37    unsigned int t1;
38    unsigned int t2;
39    unsigned int t3;
40    unsigned int normalIndex1;        ///< Normal index for all bindings except BIND_PER_VERTEX and BIND_OFF.
41    unsigned int normalIndex2;
42    unsigned int normalIndex3;
43    int material;
44};
45
46struct VertexIndex
47{
48    VertexIndex(unsigned int vertexIndex, unsigned int drawableIndex, unsigned int normalIndex)
49        : vertexIndex(vertexIndex), drawableIndex(drawableIndex), normalIndex(normalIndex)
50    {}
51    VertexIndex(const VertexIndex & v) : vertexIndex(v.vertexIndex), drawableIndex(v.drawableIndex), normalIndex(v.normalIndex) {}
52
53    unsigned int vertexIndex;        ///< Index of the vertice position in the vec3 array
54    unsigned int drawableIndex;
55    unsigned int normalIndex;        ///< Normal index for all bindings except BIND_PER_VERTEX and BIND_OFF.
56
57    bool operator<(const VertexIndex & v) const {
58        if (drawableIndex!=v.drawableIndex) return drawableIndex<v.drawableIndex;
59        return vertexIndex<v.vertexIndex;
60    }
61};
62
63typedef std::vector<std::pair<Triangle, int> > ListTriangle; //the int is the drawable of the triangle
64typedef std::map<VertexIndex, unsigned int> MapIndices;        ///< Map OSG indices to FBX mesh indices
65
66namespace pluginfbx
67{
68
69///\author Capo (Thibault Caporal), Sukender (Benoit Neil)
70class WriterNodeVisitor: public osg::NodeVisitor
71{
72    public:
73        WriterNodeVisitor(FbxScene* pScene,
74                          FbxManager* pSdkManager,
75                          const std::string& fileName,
76                          const osgDB::ReaderWriter::Options* options,
77                          const std::string& srcDirectory) :
78            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
79            _pSdkManager(pSdkManager),
80            _succeedLastApply(true),
81            _pScene(pScene),
82            _curFbxNode(pScene->GetRootNode()),
83            _currentStateSet(new osg::StateSet()),
84            _lastMaterialIndex(0),
85            _lastMeshIndex(0),
86            _options(options),
87            _externalWriter(srcDirectory, osgDB::getFilePath(fileName), true, 0)
88        {}
89
90        ///Tell us if last Node succeed traversing.
91        bool succeedLastApply() const { return _succeedLastApply; }
92
93        ///Set the flag _succeedLastApply to false.
94        void failedApply() { _succeedLastApply = false; }
95
96        virtual void apply(osg::Geode& node);
97        virtual void apply(osg::Group& node);
98        virtual void apply(osg::MatrixTransform& node);
99
100        void traverse (osg::Node& node)
101        {
102            pushStateSet(node.getStateSet());
103            osg::NodeVisitor::traverse(node);
104            popStateSet(node.getStateSet());
105        }
106
107        void pushStateSet(const osg::StateSet* ss)
108        {
109            if (ss)
110            {
111                // Save our current stateset
112                _stateSetStack.push(_currentStateSet.get());
113
114                // merge with node stateset
115                _currentStateSet = static_cast<osg::StateSet*>(
116                    _currentStateSet->clone(osg::CopyOp::SHALLOW_COPY));
117                _currentStateSet->merge(*ss);
118            }
119        }
120
121
122        void popStateSet(const osg::StateSet* ss)
123        {
124            if (ss)
125            {
126                // restore the previous stateset
127                _currentStateSet = _stateSetStack.top();
128                _stateSetStack.pop();
129            }
130        }
131
132        /// Copy the texture file in current path.
133        void copyTexture();
134        typedef std::map<const osg::Image*, std::string> ImageSet;
135        typedef std::set<std::string> ImageFilenameSet;        // Sub-optimal because strings are doubled (in ImageSet). Moreover, an unordered_set (= hashset) would be more efficient (Waiting for unordered_set to be included in C++ standard ;) ).
136
137        ///\todo Add support for 2nd texture, opacity_map, bump_map, specular_map, shininess_map, self_illum_map, reflection_map.
138        class Material
139        {
140        public:
141            ///Create a KfbxMaterial and KfbxTexture from osg::Texture and osg::Material.
142            Material(WriterNodeVisitor&   writerNodeVisitor,
143                     osgDB::ExternalFileWriter & externalWriter,
144                     const osg::StateSet* stateset,
145                     const osg::Material* mat,
146                     const osg::Texture*  tex,
147                     FbxManager*      pSdkManager,
148                     const osgDB::ReaderWriter::Options * options,
149                     int                  index = -1);
150
151            FbxFileTexture* getFbxTexture() const
152            {
153                return _fbxTexture;
154            }
155
156            FbxSurfaceMaterial* getFbxMaterial() const
157            {
158                return _fbxMaterial;
159            }
160
161            const osg::Image* getOsgImage() const
162            {
163                return _osgImage;
164            }
165
166            const int getIndex() const
167            {
168                return _index;
169            }
170
171            void setIndex(int index)
172            {
173                _index = index;
174            }
175
176        private:
177            FbxSurfacePhong*  _fbxMaterial;
178            FbxFileTexture*   _fbxTexture;
179            int                _index;///< Index in the Map
180            const osg::Image*  _osgImage;
181        };
182
183    protected:
184        /// Compares StateSets.
185        ///\todo It may be useful to compare stack of pointers (see pushStateset()) in order to keep the same number of FBX materials when doing reading and then writing without further processing.
186        struct CompareStateSet
187        {
188            bool operator () (const osg::ref_ptr<const osg::StateSet>& ss1, const osg::ref_ptr<const osg::StateSet>& ss2) const
189            {
190                return *ss1 < *ss2;
191            }
192        };
193
194    private:
195        /**
196        *  Fill the faces field of the mesh and call buildMesh().
197        *  \param geo is the geode which contains the vertices and faces.
198        *  \param listTriangles contain all the mesh's faces.
199        *  \param texcoords tell us if we have to handle texture coordinates.
200        */
201        void buildFaces(const osg::Geode&   geo,
202                        ListTriangle&       listTriangles,
203                        bool                texcoords);
204
205        /// Set the layer for texture and Material in layer 0.
206        void setLayerTextureAndMaterial(FbxMesh* mesh);
207
208        /// Set Vertices, normals, and UVs
209        void setControlPointAndNormalsAndUV(const osg::Geode& geo,
210                                            MapIndices&       index_vert,
211                                            bool              texcoords,
212                                            FbxMesh*         fbxMesh);
213
214        /**
215        *  Create the list of faces from the geode.
216        *  \param geo is the geode to study.
217        *  \param listTriangles is the list to fill.
218        *  \param texcoords tell us if we have to treat texture coord.
219        *  \param drawable_n tell us which drawable we are building.
220        */
221        void createListTriangle(const osg::Geometry* geo,
222                                ListTriangle&        listTriangles,
223                                bool&                texcoords,
224                                unsigned int&        drawable_n);
225
226        ///Store the material of the stateset in the MaterialMap.
227        int processStateSet(const osg::StateSet* stateset);
228
229        typedef std::stack<osg::ref_ptr<osg::StateSet> > StateSetStack;
230        typedef std::map<osg::ref_ptr<const osg::StateSet>, Material, CompareStateSet> MaterialMap;
231
232        ///We need this for every new Node we create.
233        FbxManager* _pSdkManager;
234
235        ///Tell us if the last apply succeed, useful to stop going through the graph.
236        bool _succeedLastApply;
237
238        ///The current directory.
239        std::string _directory;
240
241        ///The Scene to save.
242        FbxScene* _pScene;
243
244        ///The current Fbx Node.
245        FbxNode* _curFbxNode;
246
247        ///The Stack of different stateSet.
248        StateSetStack _stateSetStack;
249
250        ///The current stateSet.
251        osg::ref_ptr<osg::StateSet> _currentStateSet;
252
253        ///We store the fbx Materials and Textures in this map.
254        MaterialMap                         _materialMap;
255        unsigned int                        _lastMaterialIndex;
256        unsigned int                        _lastMeshIndex;
257        const osgDB::ReaderWriter::Options* _options;
258        osgDB::ExternalFileWriter           _externalWriter;
259};
260
261// end namespace pluginfbx
262}
263
264#endif // _FBX_WRITER_NODE_VISITOR_HEADER__
Note: See TracBrowser for help on using the browser.