root/OpenSceneGraph/trunk/src/osgPlugins/OpenFlight/GeometryRecords.cpp @ 13041

Revision 13041, 45.2 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/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14//
15// OpenFlight® loader for OpenSceneGraph
16//
17//  Copyright (C) 2005-2007  Brede Johansen
18//
19
20#include <assert.h>
21#include <osg/Geode>
22#include <osg/Billboard>
23#include <osg/Geometry>
24#include <osg/Texture2D>
25#include <osg/CullFace>
26#include <osg/BlendFunc>
27#include <osgUtil/TransformAttributeFunctor>
28#include "Registry.h"
29#include "Document.h"
30#include "RecordInputStream.h"
31
32#include <algorithm>
33
34namespace flt {
35
36template<class ARRAY>
37void reverseWindingOrder( ARRAY* data, GLenum mode, GLint first, GLint last )
38{
39    switch( mode )
40    {
41    case osg::PrimitiveSet::TRIANGLES:
42    case osg::PrimitiveSet::QUADS:
43    case osg::PrimitiveSet::POLYGON:
44        // reverse all the vertices.
45        std::reverse(data->begin()+first, data->begin()+last);
46        break;
47    case osg::PrimitiveSet::TRIANGLE_STRIP:
48    case osg::PrimitiveSet::QUAD_STRIP:
49        // reverse only the shared edges.
50        for( GLint i = first; i < last-1; i+=2 )
51        {
52            std::swap( (*data)[i], (*data)[i+1] );
53        }
54        break;
55    case osg::PrimitiveSet::TRIANGLE_FAN:
56        // reverse all vertices except the first vertex.
57        std::reverse(data->begin()+first+1, data->begin()+last);
58        break;
59    }
60}
61
62void addDrawableAndReverseWindingOrder( osg::Geode* geode )
63{
64    // Replace double sided polygons by duplicating the drawables and inverting the normals.
65    std::vector<osg::Geometry*> new_drawables;
66
67    for (size_t i=0; i<geode->getNumDrawables(); ++i)
68    {
69        const osg::Geometry* geometry = dynamic_cast<const osg::Geometry*>(geode->getDrawable(i));
70        if(geometry)
71        {
72            osg::Geometry* geom = new osg::Geometry(*geometry
73                , osg::CopyOp::DEEP_COPY_ARRAYS | osg::CopyOp::DEEP_COPY_PRIMITIVES);
74            new_drawables.push_back(geom);
75
76            for( size_t i = 0; i < geom->getNumPrimitiveSets( ); ++i )
77            {
78                osg::DrawArrays* drawarray = dynamic_cast<osg::DrawArrays*>( geom->getPrimitiveSet( i ) );
79                if( drawarray )
80                {
81                    GLint first = drawarray->getFirst();
82                    GLint last  = drawarray->getFirst()+drawarray->getCount();
83
84                    // Invert vertex order.
85                    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom->getVertexArray());
86                    if( vertices )
87                    {
88                        reverseWindingOrder( vertices, drawarray->getMode(), first, last );
89                    }
90
91                    if( geom->getNormalBinding( ) == osg::Geometry::BIND_PER_VERTEX )
92                    {
93                        osg::Vec3Array* normals = dynamic_cast<osg::Vec3Array*>(geom->getNormalArray());
94                        if( normals )
95                        {
96                            // First, invert the direction of the normals.
97                            for( GLint i = first; i < last; ++i )
98                            {
99                                (*normals)[i] = -(*normals)[i];
100                            }
101                            reverseWindingOrder( normals, drawarray->getMode(), first, last );
102                        }
103                    }
104
105                    if( geom->getColorBinding( ) == osg::Geometry::BIND_PER_VERTEX )
106                    {
107                        osg::Vec4Array* colors = dynamic_cast<osg::Vec4Array*>(geom->getColorArray());
108                        if( colors )
109                        {
110                            reverseWindingOrder( colors, drawarray->getMode(), first, last );
111                        }
112                    }
113
114                    for( size_t i = 0; i < geom->getNumTexCoordArrays(); ++i )
115                    {
116                        osg::Vec2Array* UVs = dynamic_cast<osg::Vec2Array*>(geom->getTexCoordArray(i));
117                        if( UVs )
118                        {
119                            reverseWindingOrder( UVs, drawarray->getMode(), first, last );
120                        }
121                    }
122                }
123            }
124        }
125    }
126
127    // Now add the new geometry drawable.
128    for( size_t i = 0; i < new_drawables.size( ); ++i )
129    {
130        geode->addDrawable( new_drawables[i] );
131    }
132}
133
134/* Face record
135 */
136class Face : public PrimaryRecord
137{
138    // flags
139    static const unsigned int TERRAIN_BIT      = 0x80000000u >> 0;
140    static const unsigned int NO_COLOR_BIT     = 0x80000000u >> 1;
141    static const unsigned int NO_ALT_COLOR_BIT = 0x80000000u >> 2;
142    static const unsigned int PACKED_COLOR_BIT = 0x80000000u >> 3;
143    static const unsigned int FOOTPRINT_BIT    = 0x80000000u >> 4;    // Terrain culture cutout
144    static const unsigned int HIDDEN_BIT       = 0x80000000u >> 5;
145    static const unsigned int ROOFLINE_BIT     = 0x80000000u >> 6;
146
147    osg::Vec4   _primaryColor;
148    uint8       _drawFlag;
149    uint8       _template;
150    uint16      _transparency;
151    uint32      _flags;
152    uint8       _lightMode;
153
154    osg::ref_ptr<osg::Geode> _geode;
155    osg::ref_ptr<osg::Geometry> _geometry;
156
157public:
158
159    Face() :
160        _primaryColor(1,1,1,1),
161        _drawFlag(SOLID_NO_BACKFACE),
162        _template(FIXED_NO_ALPHA_BLENDING),
163        _transparency(0),
164        _flags(0),
165        _lightMode(FACE_COLOR)
166    {
167    }
168
169    META_Record(Face)
170
171    META_setID(_geode)
172    META_setComment(_geode)
173    META_setMultitexture(_geode)
174
175    // draw mode
176    enum DrawMode
177    {
178        SOLID_BACKFACED = 0,
179        SOLID_NO_BACKFACE = 1,
180        WIREFRAME_CLOSED = 2,
181        WIREFRAME_NOT_CLOSED = 3,
182        SURROUND_ALTERNATE_COLOR = 4,
183        OMNIDIRECTIONAL_LIGHT = 8,
184        UNIDIRECTIONAL_LIGHT = 9,
185        BIDIRECTIONAL_LIGHT = 10
186    };
187
188    inline DrawMode getDrawMode() const { return (DrawMode)_drawFlag; }
189
190    // lighting
191    enum LightMode
192    {
193        FACE_COLOR = 0,
194        VERTEX_COLOR = 1,
195        FACE_COLOR_LIGHTING = 2,
196        VERTEX_COLOR_LIGHTING = 3
197    };
198
199    inline LightMode getLightMode() const { return (LightMode)_lightMode; }
200    inline bool isLit() const { return (_lightMode==FACE_COLOR_LIGHTING) || (_lightMode==VERTEX_COLOR_LIGHTING); }
201    inline bool isGouraud() const { return (_lightMode==VERTEX_COLOR) || (_lightMode==VERTEX_COLOR_LIGHTING); }
202
203    // flags
204    inline bool noColor()         const { return (_flags & NO_COLOR_BIT)!=0; }
205    inline bool isHidden()        const { return (_flags & HIDDEN_BIT)!=0; }
206    inline bool isTerrain()       const { return (_flags & TERRAIN_BIT)!=0; }
207    inline bool isFootprint()     const { return (_flags & FOOTPRINT_BIT)!=0; }
208    inline bool isRoofline()      const { return (_flags & ROOFLINE_BIT)!=0; }
209    inline bool packedColorMode() const { return (_flags & PACKED_COLOR_BIT)!=0; }
210
211    // billboard
212    enum TemplateMode
213    {
214        FIXED_NO_ALPHA_BLENDING = 0,
215        FIXED_ALPHA_BLENDING = 1,
216        AXIAL_ROTATE_WITH_ALPHA_BLENDING = 2,
217        POINT_ROTATE_WITH_ALPHA_BLENDING = 4
218    };
219
220    inline TemplateMode getTemplateMode() const { return (TemplateMode)_template; }
221
222    // transparency & alpha
223    inline bool isAlphaBlend() const
224    {
225        return (_template==FIXED_ALPHA_BLENDING) ||
226               (_template==AXIAL_ROTATE_WITH_ALPHA_BLENDING) ||
227               (_template==POINT_ROTATE_WITH_ALPHA_BLENDING);
228    }
229
230    inline osg::Vec4 getPrimaryColor() const { return _primaryColor; }
231    inline float getTransparency() const { return (float)_transparency / 65535.0f; }
232    inline bool isTransparent() const { return _transparency > 0; }
233
234    virtual void addChild(osg::Node& child)
235    {
236        // Add subface to parent.
237        if (_parent.valid())
238            _parent->addChild(child);
239    }
240
241    virtual void addVertex(Vertex& vertex)
242    {
243        osg::Vec3Array* vertices = getOrCreateVertexArray(*_geometry);
244        vertices->push_back(vertex._coord);
245
246        if (isGouraud())
247        {
248            osg::Vec4Array* colors = getOrCreateColorArray(*_geometry);
249            if (vertex.validColor())
250            {
251                colors->push_back(vertex._color);
252            }
253            else
254            {
255                // Use face color if vertex color is -1 in a gouraud polygon.
256                // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000967.html
257                // Incorporate Face transparency per osg-users thread "Open Flight
258                // characteristic not reflected in the current OSG" (Sept/Oct 2011)
259                colors->push_back(osg::Vec4(_primaryColor.r(), _primaryColor.g(),
260                    _primaryColor.b(), ( 1.0 - getTransparency() ) ));
261            }
262        }
263
264        bool strict = false; // prepare for "strict" reader option.
265        if (strict)
266        {
267            if (vertex.validNormal())
268            {
269                osg::Vec3Array* normals = getOrCreateNormalArray(*_geometry);
270                normals->push_back(vertex._normal);
271            }
272        }
273        else
274        {
275            // Add normal only if lit.
276            if (isLit())
277            {
278                osg::Vec3Array* normals = getOrCreateNormalArray(*_geometry);
279
280                if (vertex.validNormal())
281                    normals->push_back(vertex._normal);
282                else // if lit and no normal in Vertex
283                {
284                    // Use previous normal if available.
285                    if (normals->empty())
286                        normals->push_back(osg::Vec3(0,0,1));
287                    else
288                        normals->push_back(normals->back());
289                }
290            }
291        }
292
293        for (int layer=0; layer<Vertex::MAX_LAYERS; layer++)
294        {
295            if (vertex.validUV(layer))
296            {
297                osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,layer);
298                UVs->push_back(vertex._uv[layer]);
299            }
300        }
301    }
302
303    virtual void addVertexUV(int unit, const osg::Vec2& uv)
304    {
305        osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,unit);
306        UVs->push_back(uv);
307    }
308
309    virtual void addMorphVertex(Vertex& vertex0, Vertex& /*vertex100*/)
310    {
311        osg::Vec3Array* vertices = getOrCreateVertexArray(*_geometry);
312        vertices->push_back(vertex0._coord);
313
314        if (isGouraud())
315        {
316            osg::Vec4Array* colors = getOrCreateColorArray(*_geometry);
317            if (vertex0.validColor())
318            {
319                colors->push_back(vertex0._color);
320            }
321            else
322            {
323                // Use face color if vertex color is -1 in a gouraud polygon.
324                // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000967.html
325                colors->push_back(_primaryColor);
326            }
327        }
328
329        if (vertex0.validNormal())
330        {
331            osg::Vec3Array* normals = getOrCreateNormalArray(*_geometry);
332            normals->push_back(vertex0._normal);
333        }
334
335        for (int layer=0; layer<Vertex::MAX_LAYERS; layer++)
336        {
337            if (vertex0.validUV(layer))
338            {
339                osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,layer);
340                UVs->push_back(vertex0._uv[layer]);
341            }
342        }
343    }
344
345protected:
346
347    virtual void readRecord(RecordInputStream& in, Document& document)
348    {
349        std::string id = in.readString(8);
350        /*int32 IRColor =*/ in.readInt32();
351        /*int16 relativePriority =*/ in.readInt16();
352        _drawFlag = in.readUInt8(SOLID_NO_BACKFACE);
353        uint8 texturedWhite = in.readUInt8();
354        int16 primaryNameIndex = in.readInt16(-1);
355        /*int16 secondaryNameIndex =*/ in.readInt16(-1);
356        in.forward(1);
357        _template = in.readUInt8(FIXED_NO_ALPHA_BLENDING);
358        /*int detailTexture =*/ in.readInt16(-1);
359        int textureIndex = in.readInt16(-1);
360        int materialIndex = in.readInt16(-1);
361        /*int16 surface =*/ in.readInt16();
362        /*int16 feature =*/ in.readInt16();
363        /*int32 IRMaterial =*/ in.readInt32(-1);
364        _transparency = in.readUInt16(0);
365        // version > 13
366        /*uint8 influenceLOD =*/ in.readUInt8();
367        /*uint8 linestyle =*/ in.readUInt8();
368        _flags = in.readUInt32(0);
369        _lightMode = in.readUInt8(FACE_COLOR);
370        in.forward(7);
371        osg::Vec4 primaryPackedColor = in.readColor32();
372        /*osg::Vec4 secondaryPackedColor =*/ in.readColor32();
373        // version >= VERSION_15_1
374        /*int textureMappingIndex =*/ in.readInt16(-1);
375        in.forward(2);
376        int primaryColorIndex = in.readInt32(-1);
377        /*int alternateColorIndex =*/ in.readInt32(-1);
378        // version >= 16
379        in.forward(2);
380        int shaderIndex = in.readInt16(-1);
381
382        // Create Geode or Billboard.
383        switch (_template)
384        {
385        case AXIAL_ROTATE_WITH_ALPHA_BLENDING:
386            {
387                osg::Billboard* billboard = new osg::Billboard;
388                billboard->setMode(osg::Billboard::AXIAL_ROT);
389                _geode = billboard;
390            }
391            break;
392        case POINT_ROTATE_WITH_ALPHA_BLENDING:
393            {
394                osg::Billboard* billboard = new osg::Billboard;
395                billboard->setMode(osg::Billboard::POINT_ROT_WORLD);
396                _geode = billboard;
397            }
398            break;
399        default:
400            _geode = new osg::Geode;
401        }
402
403        _geode->setDataVariance(osg::Object::STATIC);
404        _geode->setName(id);
405
406        _geometry = new osg::Geometry;
407        _geometry->setDataVariance(osg::Object::STATIC);
408        _geode->addDrawable(_geometry.get());
409
410        // StateSet
411        osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
412
413        // Hidden
414        if (isHidden())
415            _geode->setNodeMask(0);
416
417        // Face color
418        if (texturedWhite!=0 && textureIndex>=0)
419        {
420            _primaryColor = osg::Vec4(1,1,1,1);
421        }
422        else
423        {
424            if (packedColorMode())
425            {
426                _primaryColor = primaryPackedColor;
427            }
428            else
429            {
430                if (document.version() < VERSION_15_1)
431                    _primaryColor = document.getColorPool()->getColor(primaryNameIndex);
432
433                else // >= VERSION_15_1
434                    _primaryColor = document.getColorPool()->getColor(primaryColorIndex);
435            }
436        }
437
438        // Lighting
439        stateset->setMode(GL_LIGHTING, isLit() ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
440
441        // Material
442        if (isLit() || materialIndex>=0)
443        {
444            // MaterialPool will return a "default" material if no material is defined for materialIndex.
445            // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000228.html
446            osg::Vec4 col = _primaryColor;
447            col.a() = 1.0f - getTransparency();
448            osg::Material* material = document.getOrCreateMaterialPool()->getOrCreateMaterial(materialIndex,col);
449            stateset->setAttribute(material);
450        }
451
452        // Shaders
453        if (shaderIndex >= 0)
454        {
455            ShaderPool* sp = document.getOrCreateShaderPool();
456            osg::Program* program = sp->get(shaderIndex);
457            if (program)
458                stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
459        }
460
461         // Texture
462        TexturePool* tp = document.getOrCreateTexturePool();
463        osg::StateSet* textureStateSet = tp->get(textureIndex);
464        if (textureStateSet)
465        {
466            // Merge face stateset with texture stateset
467            stateset->merge(*textureStateSet);
468        }
469
470        // Cull face
471        switch(_drawFlag)
472        {
473        case SOLID_BACKFACED:     // Enable backface culling
474        {
475            static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
476            stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
477            break;
478        }
479        case SOLID_NO_BACKFACE:   // Disable backface culling
480            if( document.getReplaceDoubleSidedPolys( ) )
481            {
482                static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
483                stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
484            }
485            else
486            {
487                stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
488            }
489            break;
490        }
491
492        // Subface
493        if (document.subfaceLevel() > 0)
494        {
495            stateset->setAttributeAndModes(document.getSubSurfacePolygonOffset(document.subfaceLevel()), osg::StateAttribute::ON);
496            stateset->setAttribute(document.getSubSurfaceDepth());
497
498            stateset->setRenderBinDetails(document.subfaceLevel(),"RenderBin");
499        }
500
501        _geode->setStateSet(stateset.get());
502
503        // Add to parent.
504        if (_parent.valid())
505            _parent->addChild(*_geode);
506    }
507
508    osg::PrimitiveSet::Mode getPrimitiveSetMode(int numVertices)
509    {
510        switch(getDrawMode())
511        {
512            case WIREFRAME_NOT_CLOSED:
513                return osg::PrimitiveSet::LINE_STRIP;
514            case WIREFRAME_CLOSED:
515                return osg::PrimitiveSet::LINE_LOOP;
516            case OMNIDIRECTIONAL_LIGHT:
517            case UNIDIRECTIONAL_LIGHT:
518            case BIDIRECTIONAL_LIGHT:
519                return osg::PrimitiveSet::POINTS;
520            default: break;
521        }
522
523        switch (numVertices)
524        {
525            case 1: return osg::PrimitiveSet::POINTS;
526            case 2: return osg::PrimitiveSet::LINES;
527            case 3: return osg::PrimitiveSet::TRIANGLES;
528            case 4: return osg::PrimitiveSet::QUADS;
529            default: break;
530        }
531
532        return osg::PrimitiveSet::POLYGON;
533    }
534
535    virtual void dispose(Document& document)
536    {
537        if (_geode.valid())
538        {
539            // Insert transform(s)
540            if (_matrix.valid())
541            {
542                insertMatrixTransform(*_geode,*_matrix,_numberOfReplications);
543            }
544
545            // Add primitives, set bindings etc.
546            for (unsigned int i=0; i<_geode->getNumDrawables(); ++i)
547            {
548                osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(_geode->getDrawable(i));
549                if (geometry)
550                {
551                    osg::Array* vertices = geometry->getVertexArray();
552                    if (vertices)
553                    {
554                        GLint first = 0;
555                        GLsizei count = vertices->getNumElements();
556                        osg::PrimitiveSet::Mode mode = getPrimitiveSetMode(count);
557                        geometry->addPrimitiveSet(new osg::DrawArrays(mode,first,count));
558                    }
559
560                    // Color binding
561                    if (isGouraud())
562                    {
563                        // Color per vertex
564                        geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
565                    }
566                    else
567                    {
568                        // Color per face
569                        osg::Vec4 col = getPrimaryColor();
570                        col[3] = 1.0f - getTransparency();
571
572                        geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
573                        osg::Vec4Array* colors = new osg::Vec4Array(1);
574                        (*colors)[0] = col;
575                        geometry->setColorArray(colors);
576                    }
577
578                    // Normal binding
579                    if (isLit())
580                    {
581                        geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX );
582                    }
583                    else
584                    {
585                        geometry->setNormalBinding(osg::Geometry::BIND_OFF);
586                        geometry->setNormalArray(NULL);
587                    }
588                }
589            }
590
591            if( getDrawMode( ) == SOLID_NO_BACKFACE && document.getReplaceDoubleSidedPolys( ) )
592            {
593                addDrawableAndReverseWindingOrder( _geode.get() );
594            }
595
596            osg::StateSet* stateset =  _geode->getOrCreateStateSet();
597
598            // Translucent image?
599            bool isImageTranslucent = false;
600            if (document.getUseTextureAlphaForTransparancyBinning())
601            {
602                for (unsigned int i=0; i<stateset->getTextureAttributeList().size(); ++i)
603                {
604                    osg::StateAttribute* sa = stateset->getTextureAttribute(i,osg::StateAttribute::TEXTURE);
605                    osg::Texture2D* texture = dynamic_cast<osg::Texture2D*>(sa);
606                    if (texture)
607                    {
608                        osg::Image* image = texture->getImage();
609                        if (image && image->isImageTranslucent())
610                            isImageTranslucent = true;
611                    }
612                }
613            }
614
615            // Transparent Material?
616            bool isMaterialTransparent = false;
617            osg::Material* material = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
618            if (material)
619            {
620                isMaterialTransparent = material->getDiffuse(osg::Material::FRONT).a() < 0.99f;
621            }
622
623            // Enable alpha blend?
624            if (isAlphaBlend() || isTransparent() || isImageTranslucent || isMaterialTransparent)
625            {
626                static osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
627                stateset->setAttributeAndModes(blendFunc.get(), osg::StateAttribute::ON);
628                stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
629            }
630
631            if (document.getUseBillboardCenter())
632            {
633                // Set billboard rotation point to center of face.
634                osg::Billboard* billboard = dynamic_cast<osg::Billboard*>(_geode.get());
635                if (billboard)
636                {
637                    for (unsigned int i=0; i<billboard->getNumDrawables(); ++i)
638                    {
639                        osg::BoundingBox bb = billboard->getDrawable(i)->getBound();
640                        billboard->setPosition(i,bb.center());
641
642                        osgUtil::TransformAttributeFunctor tf(osg::Matrix::translate(-bb.center()));
643                        billboard->getDrawable(i)->accept(tf);
644
645                        billboard->getDrawable(i)->dirtyBound();
646                    }
647
648                    billboard->dirtyBound();
649                }
650            }
651        }
652    }
653};
654
655REGISTER_FLTRECORD(Face, FACE_OP)
656
657
658
659/** VertexList -
660  * The VertexList is a leaf record.
661  * Possible parents: Face, Mesh & LightPoint
662  */
663class VertexListRecord : public PrimaryRecord
664{
665public:
666
667    VertexListRecord() {}
668
669    META_Record(VertexListRecord)
670
671    virtual void addVertex(Vertex& vertex)
672    {
673        // forward vertex to parent.
674        if (_parent.valid())
675            _parent->addVertex(vertex);
676    }
677
678    virtual void addVertexUV(int layer,const osg::Vec2& uv)
679    {
680        // forward uv to parent.
681        if (_parent.valid())
682            _parent->addVertexUV(layer,uv);
683    }
684
685protected:
686
687    virtual ~VertexListRecord() {}
688
689    virtual void readRecord(RecordInputStream& in, Document& document)
690    {
691        VertexPool* vp = document.getVertexPool();
692        if (vp)
693        {
694            int vertices = (in.getRecordSize()-4) / 4;
695
696            // Use the Vertex pool as a record stream.
697            RecordInputStream inVP(vp->rdbuf());
698            for (int n=0; n<vertices; n++)
699            {
700                // Get position of vertex.
701                uint32 pos = in.readUInt32();
702
703                // Get vertex from vertex pool.
704                inVP.seekg((std::istream::pos_type)pos);
705                inVP.readRecord(document);
706            }
707        }
708    }
709};
710
711
712REGISTER_FLTRECORD(VertexListRecord, VERTEX_LIST_OP)
713
714
715
716/** MorphVertexList -
717  * The MorphVertexList is a leaf record.
718  */
719class MorphVertexList : public PrimaryRecord
720{
721    enum Mode
722    {
723        UNDEFINED,
724        MORPH_0,
725        MORPH_100
726    };
727
728    Mode _mode;
729    Vertex _vertex0;
730    Vertex _vertex100;
731
732public:
733
734    MorphVertexList():
735        _mode(UNDEFINED)
736    {
737    }
738
739    META_Record(MorphVertexList)
740
741    virtual void addVertex(Vertex& vertex)
742    {
743        switch (_mode)
744        {
745        case MORPH_0:
746            _vertex0 = vertex;
747            break;
748        case MORPH_100:
749            _vertex100 = vertex;
750
751            // forward vertex to parent.
752            if (_parent.valid())
753                _parent->addMorphVertex(_vertex0, _vertex100);
754            break;
755        case UNDEFINED:
756            break;
757        }
758    }
759
760    //virtual void addVertexUV(int layer,const osg::Vec2& uv)
761    //{
762    //    // forward uv to parent.
763    //    if (_parent.valid())
764    //        _parent->addVertexUV(layer,uv);
765    //}
766
767protected:
768
769    virtual ~MorphVertexList() {}
770
771    virtual void readRecord(RecordInputStream& in, Document& document)
772    {
773        VertexPool* vp = document.getVertexPool();
774        if (vp)
775        {
776            int vertices = (in.getRecordSize()-4) / 8;
777
778            // Use the Vertex pool as a record stream.
779            RecordInputStream inVP(vp->rdbuf());
780            for (int n=0; n<vertices; n++)
781            {
782                // Get position of vertex.
783                uint32 offset0 = in.readUInt32();
784                uint32 offset100 = in.readUInt32();
785
786                // Get vertex from vertex pool.
787
788                // 0%
789                _mode = MORPH_0;
790                inVP.seekg((std::istream::pos_type)offset0);
791                inVP.readRecord(document);
792
793                // 100%
794                _mode = MORPH_100;
795                inVP.seekg((std::istream::pos_type)offset100);
796                inVP.readRecord(document);
797            }
798        }
799    }
800};
801
802REGISTER_FLTRECORD(MorphVertexList, MORPH_VERTEX_LIST_OP)
803
804
805
806/* Mesh record
807 */
808class Mesh : public PrimaryRecord
809{
810    // flags
811    static const unsigned int TERRAIN_BIT      = 0x80000000u >> 0;
812    static const unsigned int NO_COLOR_BIT     = 0x80000000u >> 1;
813    static const unsigned int NO_ALT_COLOR_BIT = 0x80000000u >> 2;
814    static const unsigned int PACKED_COLOR_BIT = 0x80000000u >> 3;
815    static const unsigned int FOOTPRINT_BIT    = 0x80000000u >> 4;    // Terrain culture cutout
816    static const unsigned int HIDDEN_BIT       = 0x80000000u >> 5;
817    static const unsigned int ROOFLINE_BIT     = 0x80000000u >> 6;
818
819    osg::Vec4   _primaryColor;
820    uint8       _drawFlag;
821    uint8       _template;
822    uint16      _transparency;
823    uint32      _flags;
824    uint8       _lightMode;
825
826    osg::ref_ptr<osg::Geode> _geode;
827
828public:
829
830    Mesh() :
831        _primaryColor(1,1,1,1),
832        _drawFlag(SOLID_NO_BACKFACE),
833        _template(FIXED_NO_ALPHA_BLENDING),
834        _transparency(0),
835        _flags(0),
836        _lightMode(FACE_COLOR)
837    {
838    }
839
840    META_Record(Mesh)
841
842    META_setID(_geode)
843    META_setComment(_geode)
844    META_setMultitexture(_geode)
845
846    // draw mode
847    enum DrawMode
848    {
849        SOLID_BACKFACED = 0,
850        SOLID_NO_BACKFACE = 1,
851        WIREFRAME_CLOSED = 2,
852        WIREFRAME_NOT_CLOSED = 3,
853        SURROUND_ALTERNATE_COLOR = 4,
854        OMNIDIRECTIONAL_LIGHT = 8,
855        UNIDIRECTIONAL_LIGHT = 9,
856        BIDIRECTIONAL_LIGHT = 10
857    };
858
859    inline DrawMode getDrawMode() const { return (DrawMode)_drawFlag; }
860
861    // lighting
862    enum LightMode
863    {
864        FACE_COLOR = 0,
865        VERTEX_COLOR = 1,
866        FACE_COLOR_LIGHTING = 2,
867        VERTEX_COLOR_LIGHTING = 3
868    };
869
870    inline LightMode getLightMode() const { return (LightMode)_lightMode; }
871    inline bool isLit() const { return (_lightMode==FACE_COLOR_LIGHTING) || (_lightMode==VERTEX_COLOR_LIGHTING); }
872    inline bool isGouraud() const { return (_lightMode==VERTEX_COLOR) || (_lightMode==VERTEX_COLOR_LIGHTING); }
873
874    // flags
875    inline bool noColor()         const { return (_flags & NO_COLOR_BIT)!=0; }
876    inline bool isHidden()        const { return (_flags & HIDDEN_BIT)!=0; }
877    inline bool isTerrain()       const { return (_flags & TERRAIN_BIT)!=0; }
878    inline bool isFootprint()     const { return (_flags & FOOTPRINT_BIT)!=0; }
879    inline bool isRoofline()      const { return (_flags & ROOFLINE_BIT)!=0; }
880    inline bool packedColorMode() const { return (_flags & PACKED_COLOR_BIT)!=0; }
881
882    // billboard
883    enum TemplateMode
884    {
885        FIXED_NO_ALPHA_BLENDING = 0,
886        FIXED_ALPHA_BLENDING = 1,
887        AXIAL_ROTATE_WITH_ALPHA_BLENDING = 2,
888        POINT_ROTATE_WITH_ALPHA_BLENDING = 4
889    };
890
891    inline TemplateMode getTemplateMode() const { return (TemplateMode)_template; }
892
893    // transparency & alpha
894    inline bool isAlphaBlend() const
895    {
896        return (_template==FIXED_ALPHA_BLENDING) ||
897               (_template==AXIAL_ROTATE_WITH_ALPHA_BLENDING) ||
898               (_template==POINT_ROTATE_WITH_ALPHA_BLENDING);
899    }
900
901    inline osg::Vec4 getPrimaryColor() const { return _primaryColor; }
902    inline float getTransparency() const { return (float)_transparency / 65535.0f; }
903    inline bool isTransparent() const { return _transparency > 0; }
904
905    virtual void addChild(osg::Node& child)
906    {
907        // Add subface to parent.
908        if (_parent.valid())
909            _parent->addChild(child);
910    }
911
912    virtual void addGeometry(osg::Geometry& geometry)
913    {
914        _geode->addDrawable(&geometry);
915    }
916
917protected:
918
919    virtual void readRecord(RecordInputStream& in, Document& document)
920    {
921        std::string id = in.readString(8);
922        in.forward(4);
923        /*int32 IRColor =*/ in.readInt32();
924        /*int16 relativePriority =*/ in.readInt16();
925        _drawFlag = in.readUInt8(SOLID_NO_BACKFACE);
926        uint8 texturedWhite = in.readUInt8();
927        int16 primaryNameIndex = in.readInt16(-1);
928        /*int16 secondaryNameIndex =*/ in.readInt16(-1);
929        in.forward(1);
930        _template = in.readUInt8(FIXED_NO_ALPHA_BLENDING);
931        /*int detailTexture =*/ in.readInt16(-1);
932        int textureIndex = in.readInt16(-1);
933        int materialIndex = in.readInt16(-1);
934        /*int16 surface =*/ in.readInt16();
935        /*int16 feature =*/ in.readInt16();
936        /*int32 IRMaterial =*/ in.readInt32(-1);
937        _transparency = in.readUInt16(0);
938        // version > 13
939        /*uint8 influenceLOD =*/ in.readUInt8();
940        /*uint8 linestyle =*/ in.readUInt8();
941        _flags = in.readUInt32(0);
942        _lightMode = in.readUInt8(FACE_COLOR);
943        in.forward(7);
944        osg::Vec4 primaryPackedColor = in.readColor32();
945        /*osg::Vec4 secondaryPackedColor =*/ in.readColor32();
946        // version >= VERSION_15_1
947        /*int textureMappingIndex =*/ in.readInt16(-1);
948        in.forward(2);
949        int primaryColorIndex = in.readInt32(-1);
950        /*int alternateColorIndex =*/ in.readInt32(-1);
951        // version >= 16
952        in.forward(2);
953        int shaderIndex = in.readInt16(-1);
954
955        // Create Geode or Billboard.
956        switch (_template)
957        {
958        case AXIAL_ROTATE_WITH_ALPHA_BLENDING:
959            {
960                osg::Billboard* billboard = new osg::Billboard;
961                billboard->setMode(osg::Billboard::AXIAL_ROT);
962                _geode = billboard;
963            }
964            break;
965        case POINT_ROTATE_WITH_ALPHA_BLENDING:
966            {
967                osg::Billboard* billboard = new osg::Billboard;
968                billboard->setMode(osg::Billboard::POINT_ROT_WORLD);
969                _geode = billboard;
970            }
971            break;
972        default:
973            _geode = new osg::Geode;
974        }
975
976        _geode->setDataVariance(osg::Object::STATIC);
977        _geode->setName(id);
978
979        // StateSet
980        osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
981
982        // Hidden
983        if (isHidden())
984            _geode->setNodeMask(0);
985
986        // Face color
987        if (texturedWhite!=0 && textureIndex>=0)
988        {
989            _primaryColor = osg::Vec4(1,1,1,1);
990        }
991        else
992        {
993            if (packedColorMode())
994            {
995                _primaryColor = primaryPackedColor;
996            }
997            else
998            {
999                if (document.version() < VERSION_15_1)
1000                    _primaryColor = document.getColorPool()->getColor(primaryNameIndex);
1001
1002                else // >= VERSION_15_1
1003                    _primaryColor = document.getColorPool()->getColor(primaryColorIndex);
1004            }
1005        }
1006
1007        // Lighting
1008        stateset->setMode(GL_LIGHTING, isLit() ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
1009
1010        // Material
1011        if (isLit() || materialIndex>=0)
1012        {
1013            // MaterialPool will return a "default" material if no material is defined for materialIndex.
1014            // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000228.html
1015            osg::Vec4 col = _primaryColor;
1016            col.a() = 1.0f - getTransparency();
1017            osg::Material* material = document.getOrCreateMaterialPool()->getOrCreateMaterial(materialIndex,col);
1018            stateset->setAttribute(material);
1019        }
1020
1021        // Shaders
1022        if (shaderIndex >= 0)
1023        {
1024            ShaderPool* sp = document.getOrCreateShaderPool();
1025            osg::Program* program = sp->get(shaderIndex);
1026            if (program)
1027                stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
1028        }
1029
1030         // Texture
1031        TexturePool* tp = document.getOrCreateTexturePool();
1032        osg::StateSet* textureStateSet = tp->get(textureIndex);
1033        if (textureStateSet)
1034        {
1035            // Merge face stateset with texture stateset
1036            stateset->merge(*textureStateSet);
1037        }
1038
1039        // Cull face
1040        switch(_drawFlag)
1041        {
1042        case SOLID_BACKFACED:     // Enable backface culling
1043        {
1044            static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
1045            stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
1046            break;
1047        }
1048        case SOLID_NO_BACKFACE:   // Disable backface culling
1049            if( document.getReplaceDoubleSidedPolys( ) )
1050            {
1051                static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
1052                stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
1053            }
1054            else
1055            {
1056                stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
1057            }
1058            break;
1059        }
1060
1061        // Subface
1062        if (document.subfaceLevel() > 0)
1063        {
1064            stateset->setAttributeAndModes(document.getSubSurfacePolygonOffset(document.subfaceLevel()), osg::StateAttribute::ON);
1065            stateset->setAttribute(document.getSubSurfaceDepth());
1066
1067            stateset->setRenderBinDetails(document.subfaceLevel(),"RenderBin");
1068        }
1069
1070        _geode->setStateSet(stateset.get());
1071
1072        // Add to parent.
1073        if (_parent.valid())
1074            _parent->addChild(*_geode);
1075    }
1076
1077    virtual void dispose(Document& document)
1078    {
1079        if (_geode.valid())
1080        {
1081            // Insert transform(s)
1082            if (_matrix.valid())
1083            {
1084                insertMatrixTransform(*_geode,*_matrix,_numberOfReplications);
1085            }
1086
1087            if( getDrawMode( ) == SOLID_NO_BACKFACE && document.getReplaceDoubleSidedPolys( ) )
1088            {
1089                addDrawableAndReverseWindingOrder( _geode.get() );
1090            }
1091
1092            osg::StateSet* stateset =  _geode->getOrCreateStateSet();
1093
1094            // Translucent image?
1095            bool isImageTranslucent = false;
1096            if (document.getUseTextureAlphaForTransparancyBinning())
1097            {
1098                for (unsigned int i=0; i<stateset->getTextureAttributeList().size(); ++i)
1099                {
1100                    osg::StateAttribute* sa = stateset->getTextureAttribute(i,osg::StateAttribute::TEXTURE);
1101                    osg::Texture2D* texture = dynamic_cast<osg::Texture2D*>(sa);
1102                    if (texture)
1103                    {
1104                        osg::Image* image = texture->getImage();
1105                        if (image && image->isImageTranslucent())
1106                            isImageTranslucent = true;
1107                    }
1108                }
1109            }
1110
1111            // Transparent Material?
1112            bool isMaterialTransparent = false;
1113            osg::Material* material = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
1114            if (material)
1115            {
1116                isMaterialTransparent = material->getDiffuse(osg::Material::FRONT).a() < 0.99f;
1117            }
1118
1119            // Enable alpha blend?
1120            if (isAlphaBlend() || isTransparent() || isImageTranslucent || isMaterialTransparent)
1121            {
1122                static osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
1123                stateset->setAttributeAndModes(blendFunc.get(), osg::StateAttribute::ON);
1124                stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
1125            }
1126
1127            if (document.getUseBillboardCenter())
1128            {
1129                // Set billboard rotation point to center of face.
1130                osg::Billboard* billboard = dynamic_cast<osg::Billboard*>(_geode.get());
1131                if (billboard)
1132                {
1133                    for (unsigned int i=0; i<billboard->getNumDrawables(); ++i)
1134                    {
1135                        osg::BoundingBox bb = billboard->getDrawable(i)->getBound();
1136                        billboard->setPosition(i,bb.center());
1137
1138                        osgUtil::TransformAttributeFunctor tf(osg::Matrix::translate(-bb.center()));
1139                        billboard->getDrawable(i)->accept(tf);
1140
1141                        billboard->getDrawable(i)->dirtyBound();
1142                    }
1143
1144                    billboard->dirtyBound();
1145                }
1146            }
1147        }
1148    }
1149};
1150
1151REGISTER_FLTRECORD(Mesh, MESH_OP)
1152
1153
1154
1155
1156/** LocalVertexPool -
1157  */
1158class LocalVertexPool : public Record
1159{
1160    // Attribute Mask
1161    static const unsigned int HAS_POSITION      = 0x80000000u >> 0;
1162    static const unsigned int HAS_COLOR_INDEX   = 0x80000000u >> 1;
1163    static const unsigned int HAS_RGBA_COLOR    = 0x80000000u >> 2;
1164    static const unsigned int HAS_NORMAL        = 0x80000000u >> 3;
1165    static const unsigned int HAS_BASE_UV       = 0x80000000u >> 4;
1166    static const unsigned int HAS_UV_LAYER1     = 0x80000000u >> 5;
1167    static const unsigned int HAS_UV_LAYER2     = 0x80000000u >> 6;
1168    static const unsigned int HAS_UV_LAYER3     = 0x80000000u >> 7;
1169    static const unsigned int HAS_UV_LAYER4     = 0x80000000u >> 8;
1170    static const unsigned int HAS_UV_LAYER5     = 0x80000000u >> 9;
1171    static const unsigned int HAS_UV_LAYER6     = 0x80000000u >> 10;
1172    static const unsigned int HAS_UV_LAYER7     = 0x80000000u >> 11;
1173
1174public:
1175
1176    LocalVertexPool() {}
1177
1178    META_Record(LocalVertexPool)
1179
1180protected:
1181
1182    virtual ~LocalVertexPool() {}
1183
1184    virtual void readRecord(RecordInputStream& in, Document& document)
1185    {
1186
1187        uint32 vertices = in.readUInt32();
1188        uint32 mask = in.readUInt32();
1189
1190        osg::ref_ptr<VertexList> _vertexList = new VertexList(vertices);
1191
1192
1193        for (unsigned int n=0; n<vertices; n++)
1194        {
1195            Vertex vertex;
1196
1197            if (mask & HAS_POSITION)
1198            {
1199                osg::Vec3d coord = in.readVec3d();
1200                vertex.setCoord(coord*document.unitScale());
1201
1202                if (!coord.valid())
1203                {
1204                    OSG_NOTICE<<"Warning: data error detected in LocalVertexPool::readRecord coord="<<coord.x()<<" "<<coord.y()<<" "<<coord.z()<<std::endl;
1205                }
1206            }
1207
1208            if (mask & HAS_COLOR_INDEX)
1209            {
1210                uint32 alphaIndex = in.readUInt32();
1211                int index = alphaIndex & 0x00ffffff;
1212                uint8 alpha = alphaIndex >> 24;
1213                osg::Vec4 color = document.getColorPool()->getColor(index);
1214                color.a() = (float)alpha/255;
1215                vertex.setColor(color);
1216
1217                if (!color.valid())
1218                {
1219                    OSG_NOTICE<<"Warning: data error detected in LocalVertexPool::readRecord color="<<color.r()<<" "<<color.g()<<" "<<color.b()<<" "<<color.a()<<std::endl;
1220                }
1221            }
1222
1223            if (mask & HAS_RGBA_COLOR)
1224            {
1225                osg::Vec4f color = in.readColor32();
1226                vertex.setColor(color);
1227
1228                if (!color.valid())
1229                {
1230                    OSG_NOTICE<<"Warning: data error detected in LocalVertexPool::readRecord color="<<color.r()<<" "<<color.g()<<" "<<color.b()<<" "<<color.a()<<std::endl;
1231                }
1232            }
1233
1234            if (mask & HAS_NORMAL)
1235            {
1236                osg::Vec3f normal = in.readVec3f();
1237                vertex.setNormal(normal);
1238
1239                if (!normal.valid())
1240                {
1241                    OSG_NOTICE<<"Warning: data error detected in LocalVertexPool::readRecord normal="<<normal.x()<<" "<<normal.y()<<" "<<normal.z()<<std::endl;
1242                }
1243            }
1244
1245            for (unsigned int layer=0; layer<8; layer++)
1246            {
1247                if (mask & (HAS_BASE_UV >> layer))
1248                {
1249                    osg::Vec2f uv = in.readVec2f();
1250                    vertex.setUV(layer,uv);
1251
1252                    if (!uv.valid())
1253                    {
1254                        OSG_NOTICE<<"Warning: data error detected in LocalVertexPool::readRecord uv="<<uv.x()<<" "<<uv.y()<<std::endl;
1255                    }
1256
1257                }
1258            }
1259
1260            (*_vertexList)[n] = vertex;
1261        }
1262
1263        if (_parent.valid())
1264            _parent->setLocalVertexPool(_vertexList.get());
1265
1266    }
1267};
1268
1269REGISTER_FLTRECORD(LocalVertexPool, LOCAL_VERTEX_POOL_OP)
1270
1271
1272
1273
1274/** MeshPrimitive -
1275  */
1276class MeshPrimitive : public PrimaryRecord
1277{
1278    enum PrimitiveType
1279    {
1280        TRIANGLE_STRIP = 1,
1281        TRIANGLE_FAN = 2,
1282        QUADRILATERAL_STRIP = 3,
1283        INDEXED_POLYGON = 4
1284    };
1285
1286public:
1287
1288    MeshPrimitive() {}
1289
1290    META_Record(MeshPrimitive)
1291
1292protected:
1293
1294    virtual ~MeshPrimitive() {}
1295
1296    virtual void readRecord(RecordInputStream& in, Document& /*document*/)
1297    {
1298        Mesh* mesh = dynamic_cast<Mesh*>(_parent.get());
1299        if (!mesh) return;
1300
1301        VertexList* vertexList = mesh->getLocalVertexPool();
1302        if (!vertexList) return;
1303
1304        int16 type = in.readInt16();
1305        uint16 indexSize = in.readUInt16();
1306        uint32 vertexCount = in.readUInt32();
1307
1308        GLenum mode = 0;
1309        switch(type)
1310        {
1311        case TRIANGLE_STRIP:
1312            mode = osg::PrimitiveSet::TRIANGLE_STRIP;
1313            break;
1314        case TRIANGLE_FAN:
1315            mode = osg::PrimitiveSet::TRIANGLE_FAN;
1316            break;
1317        case QUADRILATERAL_STRIP:
1318            mode = osg::PrimitiveSet::QUAD_STRIP;
1319            break;
1320        case INDEXED_POLYGON:
1321            mode = osg::PrimitiveSet::POLYGON;
1322            break;
1323        }
1324
1325        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
1326        geometry->addPrimitiveSet(new osg::DrawArrays(mode,0,vertexCount));
1327
1328        for (unsigned int n=0; n<vertexCount; n++)
1329        {
1330            unsigned int index = 0;
1331            switch (indexSize)
1332            {
1333            case 1:
1334                index = in.readUInt8();
1335                break;
1336            case 2:
1337                index = in.readUInt16();
1338                break;
1339            case 4:
1340                index = in.readUInt32();
1341                break;
1342            }
1343
1344            if (index < vertexList->size())
1345            {
1346                Vertex& vertex = (*vertexList)[index];
1347
1348                osg::Vec3Array* vertices = getOrCreateVertexArray(*geometry);
1349                vertices->push_back(vertex._coord);
1350
1351                if (vertex.validColor())
1352                {
1353                    osg::Vec4Array* colors = getOrCreateColorArray(*geometry);
1354                    colors->push_back(vertex._color);
1355                }
1356
1357                if (vertex.validNormal())
1358                {
1359                    osg::Vec3Array* normals = getOrCreateNormalArray(*geometry);
1360                    normals->push_back(vertex._normal);
1361                }
1362
1363                for (int layer=0; layer<Vertex::MAX_LAYERS; layer++)
1364                {
1365                    if (vertex.validUV(layer))
1366                    {
1367                        osg::Vec2Array* UVs = getOrCreateTextureArray(*geometry,layer);
1368                        UVs->push_back(vertex._uv[layer]);
1369                    }
1370                }
1371            }
1372        }
1373
1374        // Color binding
1375        if (mesh->isGouraud())
1376        {
1377            // Color per vertex
1378            geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
1379        }
1380        else
1381        {
1382            // Color per face
1383            osg::Vec4 col = mesh->getPrimaryColor();
1384            col[3] = 1.0f - mesh->getTransparency();
1385
1386            geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
1387            osg::Vec4Array* colors = new osg::Vec4Array(1);
1388            (*colors)[0] = col;
1389            geometry->setColorArray(colors);
1390        }
1391
1392        // Normal binding
1393        if (mesh->isLit())
1394        {
1395            geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX );
1396        }
1397        else
1398        {
1399            geometry->setNormalBinding(osg::Geometry::BIND_OFF);
1400            geometry->setNormalArray(NULL);
1401        }
1402
1403        mesh->addGeometry(*geometry);
1404
1405    }
1406};
1407
1408REGISTER_FLTRECORD(MeshPrimitive, MESH_PRIMITIVE_OP)
1409
1410
1411
1412} // end namespace
1413
1414
1415
Note: See TracBrowser for help on using the browser.