root/OpenSceneGraph/trunk/src/osgPlugins/dxf/DXFWriterNodeVisitor.h @ 13041

Revision 13041, 7.7 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1// -*-c++-*-
2
3/*
4 * Wavefront DXF loader for Open Scene Graph
5 *
6 * Copyright (C) 2001 Ulrich Hertlein <u.hertlein@web.de>
7 *
8 * Modified by Robert Osfield to support per Drawable coord, normal and
9 * texture coord arrays, bug fixes, and support for texture mapping.
10 *
11 * Writing support added 2007 by Stephan Huber, http://digitalmind.de,
12 * some ideas taken from the dae-plugin
13 *
14 * The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
15 * real-time rendering of large 3D photo-realistic models.
16 * The OSG homepage is http://www.openscenegraph.org/
17 */
18
19 #ifndef DXF_WRITER_NODE_VISITOR_HEADER__
20 #define DXF_WRITER_NODE_VISITOR_HEADER__
21
22
23#include <string>
24#include <stack>
25#include <sstream>
26
27#include <osg/Notify>
28#include <osg/Node>
29#include <osg/MatrixTransform>
30#include <osg/Geode>
31
32#include <osg/Geometry>
33#include <osg/StateSet>
34#include <osg/Material>
35#include <osg/Texture2D>
36#include <osg/TexGen>
37#include <osg/TexMat>
38
39#include <osgDB/Registry>
40#include <osgDB/ReadFile>
41#include <osgDB/FileUtils>
42#include <osgDB/FileNameUtils>
43
44
45#include <map>
46#include <set>
47#include <iostream>
48struct Layer
49{
50public:
51    Layer(const std::string name="",unsigned int color=7) : _name(name),_color(color)  { }
52    std::string _name;
53    unsigned int _color;
54};
55
56// reuse aci class for autocad colors, see http://bitsy.sub-atomic.com/~moses/acadcolors.html for samples
57#include "aci.h"
58class AcadColor
59{
60public:
61    AcadColor()
62    {
63        int index=10;
64        for (int ii=10*3;ii<256*3; ) {
65            // find RGB for each Autocad index colour
66            unsigned int red = (int)floor(aci::table[ii++]*255.0f);
67            unsigned int green = (int)floor(aci::table[ii++]*255.0f);
68            unsigned int blue = (int)floor(aci::table[ii++]*255.0f);
69            unsigned int rgb = (red<<16) + (green<<8) + blue;
70            _indexColors[rgb]=index++;
71        }
72        //
73    }
74
75    // returns Autocad index color for supplied RGB.
76    // if no exact match is found returns nearest color based on hue
77    //  also adds match to cache for future lookups.
78    int findColor(unsigned int rgb)
79    {
80        int aci = 255;
81        ColorMap::const_iterator itr = _indexColors.find(rgb);
82        if (itr != _indexColors.end() ) {
83            aci = itr->second;
84        } else {
85            // not found - match based on hue
86            aci = nearestColor(rgb);
87
88            // add matching colour to list to cache
89            _indexColors[rgb]=aci;
90        }
91        return aci;
92    }
93
94protected:
95    // returns hue as an angle in range 0-360, saturation and value as 0-1
96    void hsv(unsigned int rgb,float &hue,float &sat,float &value)
97    {
98        int red = rgb>>16;
99        int green = (0x0000ff00&rgb)>>8;
100        int blue = 0x000000ff&rgb;
101        int H=std::max(std::max(red,green),blue);
102        int L=std::min(std::min(red,green),blue);
103
104        value = (float)H/255.0f;  // note hsv and hsl define v differently!
105        sat=(float)(H-L)/(float)H;
106
107        if (H==L) {
108            hue=0.0;
109        }else if (H==red) {
110            hue=360.0 + (60.0 * (float)(green-blue)/(float)(H-L));
111            if ( hue > 360 ) { hue-=360; }
112        } else if (H==green) {
113            hue=120.0 + (60.0 * (float)(blue-red)/(float)(H-L));
114        } else if (H==blue) {
115            hue=240.0 + (60.0 * (float)(red-green)/(float)(H-L));
116        } else {
117            hue = 0.0;
118        }
119    }
120
121    int  nearestColor(unsigned int rgb)
122    {
123        //- match based on hue
124        float h;
125        float s;
126        float v;
127        hsv(rgb,h,s,v);
128
129        // aci index format is
130        // last digit odd = 50% sat, even=100%
131        // last digit 0,1 = 100% value, 2,3=80%, 4,5=60% 6,7=50%, 8,9=30%
132        //  first two sigits are hue angle /1.5 but count starts at 10, first 9 values are dummy named colours
133        int aci=10 + (int)(h/1.5);
134        aci -= (aci%10); // ensure last digit is zero
135
136        if ( v < 0.3 ) {
137            aci += 9;
138        } else if ( v < 0.5 ) {
139            aci += 6;
140        } else if ( v < 0.6 ) {
141            aci += 4;
142        } else if ( v < 0.8 ) {
143            aci += 2;
144        } else {
145            // last digit=0;
146        }
147
148        if ( s<0.5 ) {
149            aci += 1;
150        }
151
152        return aci;
153    }
154
155
156
157protected:
158
159    typedef std::map<unsigned int, unsigned char> ColorMap;
160    ColorMap _indexColors; // maps RGB to autocad index colour
161    ColorMap _hueColors; // maps hue angle to autocad index colour
162};
163
164class DXFWriterNodeVisitor: public osg::NodeVisitor {
165
166    public:
167        DXFWriterNodeVisitor(std::ostream& fout) :
168            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
169            _fout(fout),
170            _currentStateSet(new osg::StateSet()),
171            _firstPass(true),
172            _writeTriangleAs3DFace(true)
173        {
174
175
176        }
177
178        static unsigned int getNodeRGB(osg::Geometry *geo,unsigned int index=0)
179        {
180            osg::Vec4Array* data=static_cast<osg::Vec4Array*>(geo->getColorArray());
181            if ( data && index<data->size() ) {
182                return (data->at(index).asABGR())>>8;
183            }
184            return 0;
185        }
186
187
188        bool writeHeader(const osg::BoundingSphere &bound);// call after first pass to trigger draw pass
189        void writeFooter();
190
191        void buildColorMap();
192
193        virtual void apply(osg::Geode &node);
194
195         virtual void apply(osg::Group &node)
196        {
197            osg::NodeVisitor::traverse( node );
198
199        }
200
201        void traverse (osg::Node &node)
202        {
203            pushStateSet(node.getStateSet());
204
205            osg::NodeVisitor::traverse( node );
206
207            popStateSet(node.getStateSet());
208        }
209
210        void pushStateSet(osg::StateSet* ss)
211        {
212          if (NULL!=ss) {
213            // Save our current stateset
214            _stateSetStack.push(_currentStateSet.get());
215
216            // merge with node stateset
217            _currentStateSet = static_cast<osg::StateSet*>(_currentStateSet->clone(osg::CopyOp::SHALLOW_COPY));
218            _currentStateSet->merge(*ss);
219          }
220        }
221
222
223        void popStateSet(osg::StateSet* ss)
224        {
225            if (NULL!=ss) {
226              // restore the previous stateset
227              _currentStateSet = _stateSetStack.top();
228              _stateSetStack.pop();
229            }
230        }
231
232        int getNodeAcadColor(osg::Geometry *geo,int index=0) { return 0;}
233
234    protected:
235        struct CompareStateSet
236        {
237            bool operator()(const osg::ref_ptr<osg::StateSet>& ss1, const osg::ref_ptr<osg::StateSet>& ss2) const
238            {
239                return ss1->compare(*ss2, true) < 0;
240            }
241        };
242
243
244    private:
245
246        DXFWriterNodeVisitor& operator = (const DXFWriterNodeVisitor&) { return *this; }
247
248        // first pass get layer names and draw types
249        void makeGeometryLayer(osg::Geometry* geo);
250
251        // second pass - output data
252        void processGeometry(osg::Geometry* geo, osg::Matrix& m);
253
254
255        void processArray(osg::Array* array, const Layer& layer,const osg::Matrix& m = osg::Matrix::identity());
256
257        void processStateSet(osg::StateSet* stateset);
258
259        std::string getLayerName(const std::string& defaultValue = "");
260
261        typedef std::stack<osg::ref_ptr<osg::StateSet> > StateSetStack;
262
263
264
265
266        std::ostream&                            _fout;
267        std::list<std::string>                    _nameStack;
268        StateSetStack                            _stateSetStack;
269        osg::ref_ptr<osg::StateSet>                _currentStateSet;
270
271        unsigned int             _count;
272        std::vector<Layer>       _layers;
273        bool                     _firstPass;
274        Layer                    _layer;
275
276        bool                     _writeTriangleAs3DFace;
277
278        AcadColor                _acadColor;
279
280
281};
282
283#endif
Note: See TracBrowser for help on using the browser.