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

Revision 10283, 40.4 kB (checked in by robert, 6 years ago)

From Gregory Jaegy and Robert Osfield, added support for static linking of OpenFlight? plugin

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