root/OpenSceneGraph/trunk/src/osgPlugins/normals/Normals.cpp @ 13041

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

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include "Normals.h"
2
3using namespace osg;
4
5Normals::Normals( Node *node, float scale, Mode mode )
6{
7    setName(mode == VertexNormals ? "VertexNormals" : "SurfaceNormals");
8
9    MakeNormalsVisitor mnv(scale,mode);
10    node->accept( mnv );
11
12    ref_ptr<Vec3Array> coords = mnv.getCoords();
13    ref_ptr<Vec4Array> colors = new Vec4Array;
14    if( mode == SurfaceNormals )
15        colors->push_back( Vec4( 0, 1, 0, 1 ));
16    else if( mode == VertexNormals )
17        colors->push_back( Vec4( 1, 0, 0, 1 ));
18
19    ref_ptr<Geometry> geom = new Geometry;
20    geom->setVertexArray( coords.get() );
21    geom->setColorArray( colors.get() );
22    geom->setColorBinding( Geometry::BIND_OVERALL );
23
24    geom->addPrimitiveSet( new DrawArrays( PrimitiveSet::LINES, 0, coords->size()));
25
26    StateSet *sset = new StateSet;
27    sset->setMode( GL_LIGHTING,   StateAttribute::OFF);
28    geom->setStateSet( sset );
29    addDrawable( geom.get() );
30}
31
32
33
34Normals::MakeNormalsVisitor::MakeNormalsVisitor( float normalScale, Mode mode):
35            NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN),
36            _normal_scale(normalScale),
37            _mode(mode)
38{
39    _local_coords = new Vec3Array;
40    _mat = osg::Matrix::identity();
41}
42
43
44void Normals::MakeNormalsVisitor::apply(osg::MatrixTransform& tx)
45{
46    _matStack.push( _mat );
47    _mat = _mat * tx.getMatrix();
48
49    traverse( tx );
50
51    _mat = _matStack.top();
52    _matStack.pop();
53}
54
55void Normals::MakeNormalsVisitor::apply( Geode &geode )
56{
57    for( unsigned int i = 0; i < geode.getNumDrawables(); i++ )
58    {
59        Geometry *geom = dynamic_cast<Geometry *>(geode.getDrawable(i));
60        if( geom )
61        {
62            Vec3Array *coords   = dynamic_cast<Vec3Array*>(geom->getVertexArray());
63            if( coords == 0L )
64                continue;
65
66            Vec3Array *normals  = dynamic_cast<Vec3Array*>(geom->getNormalArray());
67            if( normals == 0L )
68                continue;
69
70            Geometry::AttributeBinding binding = geom->getNormalBinding();
71            if( binding == Geometry::BIND_OFF )
72                continue;
73
74            if( binding == Geometry::BIND_OVERALL )
75            {
76                Vec3 v(0,0,0);
77                Vec3 n = normals->front();
78
79                Vec3Array::iterator coord_index = coords->begin();
80                while( coord_index != coords->end() )
81                  v += *(coord_index++) * _mat;
82                v /= (float)(coords->size());
83
84                n *= _normal_scale;
85                _local_coords->push_back( v );
86                _local_coords->push_back( (v + n));
87            }
88            else // BIND_PER_PRIMITIVE_SET, BIND_PER_PRIMITIVE, BIND_PER_VERTEX
89            {
90                Geometry::PrimitiveSetList& primitiveSets = geom->getPrimitiveSetList();
91                Geometry::PrimitiveSetList::iterator itr;
92
93                Vec3Array::iterator coord_index   = coords->begin();
94                Vec3Array::iterator normals_index = normals->begin();
95
96                for(itr=primitiveSets.begin(); itr!=primitiveSets.end(); ++itr)
97                {
98#ifdef DEBUG
99                    _printPrimitiveType( (*itr).get() );
100#endif
101                    if( binding == Geometry::BIND_PER_PRIMITIVE_SET )
102                    {
103                        Vec3 v(0,0,0);
104                        Vec3 n = *(normals_index++);
105                        int ni = (*itr)->getNumIndices();
106                        for( int i = 0; i < ni; i++ )
107                            v += *(coord_index++) * _mat;
108                        v /= (float)(ni);
109
110                        n *= _normal_scale;
111                        _local_coords->push_back( v );
112                        _local_coords->push_back( (v + n));
113                    }
114                    else
115                    {
116                        switch((*itr)->getMode())
117                        {
118                            case(PrimitiveSet::TRIANGLES):
119                            {
120                                for( unsigned int j = 0; j < (*itr)->getNumPrimitives(); j++ )
121                                {
122                                    _processPrimitive( 3, coord_index, normals_index, binding );
123                                    coord_index += 3;
124                                    if( binding == Geometry::BIND_PER_PRIMITIVE )
125                                        normals_index++;
126                                    else
127                                        normals_index+=3;
128                                }
129                                break;
130                            }
131                            case(PrimitiveSet::TRIANGLE_STRIP):
132                            {
133                                for( unsigned int j = 0; j < (*itr)->getNumIndices()-2; j++ )
134                                {
135                                    _processPrimitive( 3, coord_index, normals_index, binding );
136                                    coord_index++;
137                                    normals_index++;
138                                }
139                                coord_index += 2;
140                                if( binding == Geometry::BIND_PER_VERTEX )
141                                    normals_index += 2;
142                                break;
143                            }
144                            case(PrimitiveSet::TRIANGLE_FAN):
145                                break;
146
147                            case(PrimitiveSet::QUADS):
148                            {
149                                for( unsigned int j = 0; j < (*itr)->getNumPrimitives(); j++ )
150                                {
151                                    _processPrimitive( 4, coord_index, normals_index, binding );
152                                    coord_index += 4;
153                                    if( binding == Geometry::BIND_PER_PRIMITIVE )
154                                        normals_index++;
155                                    else
156                                        normals_index+=4;
157                                }
158                                break;
159                            }
160                            case(PrimitiveSet::QUAD_STRIP):
161                                break;
162
163                            case(PrimitiveSet::POLYGON):
164                            {
165                                DrawArrayLengths* dal = dynamic_cast<DrawArrayLengths*>((*itr).get());
166                                if (dal) {
167                                    for (unsigned int j = 0; j < dal->size(); ++j) {
168                                        unsigned int num_prim = (*dal)[j];
169                                        //OSG_WARN << "j=" << j << " num_prim=" << num_prim << std::endl;
170                                        _processPrimitive(num_prim, coord_index, normals_index, binding);
171                                        coord_index += num_prim;
172                                        if (binding == Geometry::BIND_PER_PRIMITIVE) {
173                                            ++normals_index;
174                                        } else {
175                                            normals_index += num_prim;
176                                        }
177                                    }
178                                }
179                                break;
180                            }
181
182                            default:
183                                break;
184                        }
185                    }
186                }
187            }
188        }
189    }
190    traverse( geode );
191}
192
193
194void Normals::MakeNormalsVisitor::_processPrimitiveunsigned int nv,
195                        Vec3Array::iterator coords,
196                        Vec3Array::iterator normals,
197                        Geometry::AttributeBinding binding )
198{
199    Vec3 v(0,0,0);
200    Vec3 n(0,0,0);
201    if( _mode == SurfaceNormals || binding == Geometry::BIND_PER_PRIMITIVE )
202    {
203        if( binding == Geometry::BIND_PER_PRIMITIVE )
204        {
205            n = *(normals++);
206        }
207        else if( binding == Geometry::BIND_PER_VERTEX )
208        {
209            for( unsigned int i = 0; i < nv; i++ )
210                n += *(normals++);
211            n /= (float)(nv);
212        }
213
214        for( unsigned int i = 0; i < nv; i++ )
215            v += *(coords++) * _mat;
216        v /= (float)(nv);
217
218        n *= _normal_scale;
219        _local_coords->push_back( v );
220        _local_coords->push_back( (v + n));
221    }
222    else if( _mode == VertexNormals )
223    {
224        for( unsigned int i = 0; i < nv; i++ )
225        {
226            v = *(coords++) * _mat;
227            n = *(normals++);
228            n *= _normal_scale;
229            _local_coords->push_back( v );
230            _local_coords->push_back( (v + n));
231        }
232    }
233}
234
235#ifdef DEBUG
236void Normals::_printPrimitiveType( osg::PrimitiveSet *pset )
237{
238    std::cout << (
239            pset->getMode() == PrimitiveSet::POINTS ? "POINTS" :
240            pset->getMode() == PrimitiveSet::LINES ? "LINES" :
241            pset->getMode() == PrimitiveSet::LINE_STRIP ? "LINE_STRIP" :
242            pset->getMode() == PrimitiveSet::LINE_LOOP ? "LINE_LOOP" :
243            pset->getMode() == PrimitiveSet::TRIANGLES ? "TRIANGLES" :
244            pset->getMode() == PrimitiveSet::TRIANGLE_STRIP ? "TRIANGLE_STRIP" :
245            pset->getMode() == PrimitiveSet::TRIANGLE_FAN ? "TRIANGLE_FAN" :
246            pset->getMode() == PrimitiveSet::QUADS ? "QUADS" :
247            pset->getMode() == PrimitiveSet::QUAD_STRIP ? "QUAD_STRIP" :
248            pset->getMode() == PrimitiveSet::POLYGON ? "POLYGON" : "Dunno" )  << std::endl;
249}
250#endif
Note: See TracBrowser for help on using the browser.