root/OpenSceneGraph/trunk/src/osgPlugins/3ds/WriterNodeVisitor.h @ 10853

Revision 10853, 8.4 kB (checked in by robert, 5 years ago)

From Sukender,
"Here is our freshly baked 3DS reader/writer (named 'v0.5' to differentiate from previous one). Changes are against trunk rev. 10819.
Short changelog (from rev 10819):
- Added 3DS writer
- Sync'd with latest lib3DS
- Added options, especially "flattenMatrixTransforms" to get the "old" behaviour (else the reader correctly maps to OSG the transforms from the 3DS file).

What should be done:
- Check with pivot points, with and without "flattenMatrixTransforms" option.
- We ran tests on it, but we can never be 100% sure there is no bug. Testing from the community would of course be helpful."

RevLine 
[10853]1// -*-c++-*-
2
3/*
4* 3DS reader/writer for Open Scene Graph
5*
6* Copyright (C) ???
7*
8* Writing support added 2007 by Sukender (Benoit Neil), http://sukender.free.fr,
9* strongly inspired by the OBJ writer object by Stephan Huber
10*
11* The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
12* real-time rendering of large 3D photo-realistic models.
13* The OSG homepage is http://www.openscenegraph.org/
14*/
15
16#ifndef _3DS_WRITER_NODE_VISITOR_HEADER__
17#define _3DS_WRITER_NODE_VISITOR_HEADER__
18
19#include <string>
20#include <stack>
21#include <sstream>
22
23#include <osg/Notify>
24#include <osg/Node>
25#include <osg/MatrixTransform>
26#include <osg/Geode>
27
28#include <osg/Geometry>
29#include <osg/StateSet>
30#include <osg/Material>
31#include <osg/Texture2D>
32#include <osg/TexGen>
33#include <osg/TexMat>
34
35#include <osgDB/Registry>
36#include <osgDB/ReadFile>
37#include <osgDB/FileUtils>
38#include <osgDB/FileNameUtils>
39
40#include <map>
41
42#include "lib3ds/lib3ds.h"
43#include "WriterCompareTriangle.h"
44
45void copyOsgMatrixToLib3dsMatrix(Lib3dsMatrix lib3ds_matrix, const osg::Matrix& osg_matrix);
46
47typedef std::map<std::pair<unsigned int, unsigned int>, unsigned int> MapIndices;
48typedef std::vector<std::pair<Triangle, int> > ListTriangle; //the int is the drawable of the triangle
49
50class WriterNodeVisitor: public osg::NodeVisitor {
51
52    public:
53        static const unsigned int MAX_VERTICES = 65000;
54        static const unsigned int MAX_FACES    = MAX_VERTICES;
55
56        WriterNodeVisitor(Lib3dsFile * file3ds, const std::string & fileName,
57                        const osgDB::ReaderWriter::Options* options,
58                        const std::string & srcDirectory) :
59            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
60            _suceedLastApply(true),
61            _srcDirectory(srcDirectory),
62            file3ds(file3ds),
63            _currentStateSet(new osg::StateSet()),
64            _lastGeneratedNumberedName(0),
65            _lastMaterialIndex(0),
66            _lastMeshIndex(0),
67            _cur3dsNode(NULL),
68            options(options),
69            _imageCount(0)
70        {
71            //supportsOption("flipTexture", "flip texture upside-down");
72            if (!fileName.empty())
73                _directory = options->getDatabasePathList().empty() ? osgDB::getFilePath(fileName) : options->getDatabasePathList().front();
74        }
75
76        bool        suceedLastApply() const;
77        void        failedApply();
78        virtual void apply(osg::Geode &node);
79
80        virtual void apply(osg::Group &node);
81        virtual void apply(osg::MatrixTransform &node);
82
83        void traverse (osg::Node &node)
84        {
85            pushStateSet(node.getStateSet());
86            osg::NodeVisitor::traverse( node );
87            popStateSet(node.getStateSet());
88        }
89
90        void pushStateSet(osg::StateSet* ss)
91        {
92        if (NULL!=ss) {
93            // Save our current stateset
94            _stateSetStack.push(_currentStateSet.get());
95
96            // merge with node stateset
97            _currentStateSet = static_cast<osg::StateSet*>(_currentStateSet->clone(osg::CopyOp::SHALLOW_COPY));
98            _currentStateSet->merge(*ss);
99        }
100        }
101
102
103        void popStateSet(osg::StateSet* ss)
104        {
105            if (NULL!=ss) {
106            // restore the previous stateset
107            _currentStateSet = _stateSetStack.top();
108            _stateSetStack.pop();
109            }
110        }
111
112
113        void writeMaterials();
114
115
116
117        ///\todo Add support for 2nd texture, opacity_map, bump_map, specular_map, shininess_map, self_illum_map, reflection_map.
118        class Material {
119            public:
120                Material(WriterNodeVisitor & writerNodeVisitor, osg::StateSet * stateset, osg::Material* mat, osg::Texture* tex, int index=-1);
121
122                int index;            ///< Index in the 3DS file
123                osg::Vec4 diffuse, ambient, specular;
124                float shininess;
125                float transparency;
126                bool  double_sided;
127                std::string name;
128                osg::ref_ptr<osg::Image> image;
129                bool texture_transparency;
130                bool texture_no_tile;
131            protected:
132                Material() : index(-1) {}
133
134        };
135
136    protected:
137        struct CompareStateSet
138        {
139            bool operator()(const osg::ref_ptr<osg::StateSet>& ss1, const osg::ref_ptr<osg::StateSet>& ss2) const
140            {
141                                return *ss1 < *ss2;
142            }
143        };
144
145
146    private:
147        WriterNodeVisitor& operator = (const WriterNodeVisitor&) { return *this; }
148
149        /**
150        *  Fill the faces field of the mesh and call buildMesh().
151        *  \param geo is the geode who contain vertice and faces.
152        *  \param listTriangles contain all the meshs faces.
153        *  \param texcoords tell us if we have to treat texture coord.
154        */
155        void buildFaces(osg::Geode & geo, ListTriangle & listTriangles, bool texcoords);
156
157        /**
158        *  Calculate the number of vertices in the geode.
159        *  \return the number of vertices in the geode.
160        */
161        unsigned int 
162        calcVertices(osg::Geode & geo);
163
164        /**
165        *  Build a mesh
166        *  \param geo is the geode who contain vertice and faces
167        *  \param index_vert is the index used to build the new mesh
168        *  \param texcoords tell us if we have to treat texture coord
169        *  \param mesh is the mesh with faces filled
170        *  \return the place of the box in the vector.
171        *  \sa See cutScene() about the definition of the boxes for faces sorting.
172        */
173        void
174        buildMesh(osg::Geode        &    geo,
175                  MapIndices        &    index_vert,
176                  bool                   texcoords,       
177                  Lib3dsMesh             *mesh);
178
179        /**
180        *  Add a vertice to the index and link him with the Triangle index and the drawable.
181        *  \param index_vert is the map where the vertice are stored.
182        *  \param index is the indice of the vertice's position in the vec3.
183        *  \param drawable_n is the number of the drawable.
184        *  \return the position of the vertice in the final mesh.
185        */
186        unsigned int
187        getMeshIndexForGeometryIndex(MapIndices & index_vert,
188                                     unsigned int index,
189                                     unsigned int drawable_n);
190        /**
191        *  Create the list of faces from the geode.
192        *  \param geo is the geode to study.
193        *  \param listTriangles is the list to fill.
194        *  \param texcoords tell us if we have to treat texture coord.
195        *  \param drawable_n tell us which drawable we are building.
196        */ 
197        void createListTriangle(osg::Geometry       *    geo,
198                                ListTriangle        &    listTriangles,
199                                bool                &    texcoords,
200                                unsigned int        &    drawable_n);
201
202        int processStateSet(osg::StateSet* stateset);
203
204        std::string getUniqueName(const std::string& defaultvalue="", const std::string & defaultPrefix = "", bool nameIsPath = false);
205        std::string export3DSTexture(const osg::Image * image, const std::string & fileName);
206
207        typedef std::stack<osg::ref_ptr<osg::StateSet> > StateSetStack;
208        typedef std::map< osg::ref_ptr<osg::StateSet>, Material, CompareStateSet> MaterialMap;
209
210
211        bool                                _suceedLastApply;
212        std::string                         _directory;
213        std::string                         _srcDirectory;
214        Lib3dsFile *                        file3ds;
215        StateSetStack                       _stateSetStack;
216        osg::ref_ptr<osg::StateSet>         _currentStateSet;
217        std::map<std::string, unsigned int> _mapPrefix;
218        std::set<std::string>                _nameMap;
219        MaterialMap                         _materialMap;
220        unsigned int                        _lastGeneratedNumberedName;
221        unsigned int                        _lastMaterialIndex;
222        unsigned int                        _lastMeshIndex;
223        Lib3dsMeshInstanceNode *            _cur3dsNode;
224        const osgDB::ReaderWriter::Options* options;
225        unsigned int                        _imageCount;
226};
227
228#endif
Note: See TracBrowser for help on using the browser.