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

Revision 10084, 40.4 kB (checked in by robert, 5 years ago)

Refactored the subsurface PolygonOffset? code so that it uses sensible values and also moves management of the PolygonOffset? and Depth attribute objects into the Document object rather than using static vars.

  • 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
539RegisterRecordProxy<Face> g_Face(FACE_OP);
540
541
542/** VertexList -
543  * The VertexList is a leaf record.
544  * Possible parents: Face, Mesh & LightPoint
545  */
[5136]546class VertexListRecord : public PrimaryRecord
[5038]547{
548public:
549
[5136]550    VertexListRecord() {}
[5038]551
[5136]552    META_Record(VertexListRecord)
[5038]553
554    virtual void addVertex(Vertex& vertex)
555    {
556        // forward vertex to parent.
557        if (_parent.valid())
558            _parent->addVertex(vertex);
559    }
560
561    virtual void addVertexUV(int layer,const osg::Vec2& uv)
562    {
563        // forward uv to parent.
564        if (_parent.valid())
565            _parent->addVertexUV(layer,uv);
566    }
567
568protected:
569
[5136]570    virtual ~VertexListRecord() {}
[5038]571
572    virtual void readRecord(RecordInputStream& in, Document& document)
573    {
574        VertexPool* vp = document.getVertexPool();
575        if (vp)
576        {
577            int vertices = (in.getRecordSize()-4) / 4;
578
579            // Use the Vertex pool as a record stream.
[5205]580            RecordInputStream inVP(vp->rdbuf());
[5038]581            for (int n=0; n<vertices; n++)
582            {
583                // Get position of vertex.
584                uint32 pos = in.readUInt32();
585
586                // Get vertex from vertex pool.
[5205]587                inVP.seekg((std::istream::pos_type)pos);
[5038]588                inVP.readRecord(document);
589            }
590        }
591    }
592};
593
594
[5136]595RegisterRecordProxy<VertexListRecord> g_VertexList(VERTEX_LIST_OP);
[5038]596
597
598/** MorphVertexList -
599  * The MorphVertexList is a leaf record.
600  */
601class MorphVertexList : public PrimaryRecord
602{
603    enum Mode
604    {
605        UNDEFINED,
606        MORPH_0,
607        MORPH_100
608    };
609
610    Mode _mode;
611    Vertex _vertex0;
612    Vertex _vertex100;
613
614public:
615
616    MorphVertexList():
617        _mode(UNDEFINED)
618    {
619    }
620
621    META_Record(MorphVertexList)
622
623    virtual void addVertex(Vertex& vertex)
624    {
625        switch (_mode)
626        {
627        case MORPH_0:
628            _vertex0 = vertex;
629            break;
630        case MORPH_100:
631            _vertex100 = vertex;
632
633            // forward vertex to parent.
634            if (_parent.valid())
635                _parent->addMorphVertex(_vertex0, _vertex100);
636            break;
[5229]637        case UNDEFINED:
638            break;
[5038]639        }
640    }
641
642    //virtual void addVertexUV(int layer,const osg::Vec2& uv)
643    //{
644    //    // forward uv to parent.
645    //    if (_parent.valid())
646    //        _parent->addVertexUV(layer,uv);
647    //}
648
649protected:
650
651    virtual ~MorphVertexList() {}
652
653    virtual void readRecord(RecordInputStream& in, Document& document)
654    {
655        VertexPool* vp = document.getVertexPool();
656        if (vp)
657        {
658            int vertices = (in.getRecordSize()-4) / 8;
659
660            // Use the Vertex pool as a record stream.
[5205]661            RecordInputStream inVP(vp->rdbuf());
[5038]662            for (int n=0; n<vertices; n++)
663            {
664                // Get position of vertex.
665                uint32 offset0 = in.readUInt32();
666                uint32 offset100 = in.readUInt32();
667
668                // Get vertex from vertex pool.
669
670                // 0%
671                _mode = MORPH_0;
[5205]672                inVP.seekg((std::istream::pos_type)offset0);
[5038]673                inVP.readRecord(document);
674
675                // 100%
676                _mode = MORPH_100;
[5205]677                inVP.seekg((std::istream::pos_type)offset100);
[5038]678                inVP.readRecord(document);
679            }
680        }
681    }
682};
683
684RegisterRecordProxy<MorphVertexList> g_MorphVertexList(MORPH_VERTEX_LIST_OP);
685
[5122]686
[5136]687/* Mesh record
688 */
689class Mesh : public PrimaryRecord
690{
691    // flags
692    static const unsigned int TERRAIN_BIT      = 0x80000000u >> 0;
693    static const unsigned int NO_COLOR_BIT     = 0x80000000u >> 1;
694    static const unsigned int NO_ALT_COLOR_BIT = 0x80000000u >> 2;
695    static const unsigned int PACKED_COLOR_BIT = 0x80000000u >> 3;
696    static const unsigned int FOOTPRINT_BIT    = 0x80000000u >> 4;    // Terrain culture cutout
697    static const unsigned int HIDDEN_BIT       = 0x80000000u >> 5;
698    static const unsigned int ROOFLINE_BIT     = 0x80000000u >> 6;
[5122]699
[5136]700    osg::Vec4   _primaryColor;
701    uint8       _drawFlag;
702    uint8       _template;
703    uint16      _transparency;
704    uint32      _flags;
705    uint8       _lightMode;
[5122]706
[5136]707    osg::ref_ptr<osg::Geode> _geode;
[5122]708
[5136]709public:
[5122]710
[5136]711    Mesh() :
[5625]712        _primaryColor(1,1,1,1),
713        _drawFlag(SOLID_NO_BACKFACE),
714        _template(FIXED_NO_ALPHA_BLENDING),
715        _transparency(0),
716        _flags(0),
717        _lightMode(FACE_COLOR)
[5136]718    {
719    }
[5122]720
[5136]721    META_Record(Mesh)
[5122]722
[5136]723    META_setID(_geode)
724    META_setComment(_geode)
725    META_setMultitexture(_geode)
[5122]726
[5136]727    // draw mode
728    enum DrawMode
729    {
730        SOLID_BACKFACED = 0,
731        SOLID_NO_BACKFACE = 1,
732        WIREFRAME_CLOSED = 2,
733        WIREFRAME_NOT_CLOSED = 3,
734        SURROUND_ALTERNATE_COLOR = 4,
735        OMNIDIRECTIONAL_LIGHT = 8,
736        UNIDIRECTIONAL_LIGHT = 9,
737        BIDIRECTIONAL_LIGHT = 10
738    };
[5122]739
[5136]740    inline DrawMode getDrawMode() const { return (DrawMode)_drawFlag; }
[5122]741
[5136]742    // lighting
743    enum LightMode
744    {
745        FACE_COLOR = 0,
746        VERTEX_COLOR = 1,
747        FACE_COLOR_LIGHTING = 2,
748        VERTEX_COLOR_LIGHTING = 3
749    };
[5122]750
[5136]751    inline LightMode getLightMode() const { return (LightMode)_lightMode; }
752    inline bool isLit() const { return (_lightMode==FACE_COLOR_LIGHTING) || (_lightMode==VERTEX_COLOR_LIGHTING); }
753    inline bool isGouraud() const { return (_lightMode==VERTEX_COLOR) || (_lightMode==VERTEX_COLOR_LIGHTING); }
[5122]754
[5136]755    // flags
756    inline bool noColor()         const { return (_flags & NO_COLOR_BIT)!=0; }
757    inline bool isHidden()        const { return (_flags & HIDDEN_BIT)!=0; }
758    inline bool isTerrain()       const { return (_flags & TERRAIN_BIT)!=0; }
759    inline bool isFootprint()     const { return (_flags & FOOTPRINT_BIT)!=0; }
760    inline bool isRoofline()      const { return (_flags & ROOFLINE_BIT)!=0; }
761    inline bool packedColorMode() const { return (_flags & PACKED_COLOR_BIT)!=0; }
762
763    // billboard
764    enum TemplateMode
765    {
766        FIXED_NO_ALPHA_BLENDING = 0,
767        FIXED_ALPHA_BLENDING = 1,
768        AXIAL_ROTATE_WITH_ALPHA_BLENDING = 2,
769        POINT_ROTATE_WITH_ALPHA_BLENDING = 4
770    };
771
772    inline TemplateMode getTemplateMode() const { return (TemplateMode)_template; }
773
774    // transparency & alpha
775    inline bool isAlphaBlend() const
776    {
777        return (_template==FIXED_ALPHA_BLENDING) ||
778               (_template==AXIAL_ROTATE_WITH_ALPHA_BLENDING) ||
779               (_template==POINT_ROTATE_WITH_ALPHA_BLENDING);
780    }
781
782    inline osg::Vec4 getPrimaryColor() const { return _primaryColor; }
783    inline float getTransparency() const { return (float)_transparency / 65535.0f; }
784    inline bool isTransparent() const { return _transparency > 0; }
785
786    virtual void addChild(osg::Node& child)
787    {
788        // Add subface to parent.
789        if (_parent.valid())
790            _parent->addChild(child);
791    }
792
793    virtual void addGeometry(osg::Geometry& geometry)
794    {
795        _geode->addDrawable(&geometry);
796    }
797
798protected:
799
800    virtual void readRecord(RecordInputStream& in, Document& document)
801    {
802        std::string id = in.readString(8);
803        in.forward(4);
[5229]804        /*int32 IRColor =*/ in.readInt32();
805        /*int16 relativePriority =*/ in.readInt16();
[5625]806        _drawFlag = in.readUInt8(SOLID_NO_BACKFACE);
[5136]807        uint8 texturedWhite = in.readUInt8();
808        int16 primaryNameIndex = in.readInt16(-1);
[5229]809        /*int16 secondaryNameIndex =*/ in.readInt16(-1);
[5136]810        in.forward(1);
811        _template = in.readUInt8(FIXED_NO_ALPHA_BLENDING);
[5229]812        /*int detailTexture =*/ in.readInt16(-1);
[5136]813        int textureIndex = in.readInt16(-1);
814        int materialIndex = in.readInt16(-1);
[5229]815        /*int16 surface =*/ in.readInt16();
816        /*int16 feature =*/ in.readInt16();
817        /*int32 IRMaterial =*/ in.readInt32(-1);
[5136]818        _transparency = in.readUInt16(0);
819        // version > 13
[5229]820        /*uint8 influenceLOD =*/ in.readUInt8();
821        /*uint8 linestyle =*/ in.readUInt8();
[5136]822        _flags = in.readUInt32(0);
823        _lightMode = in.readUInt8(FACE_COLOR);
824        in.forward(7);
825        osg::Vec4 primaryPackedColor = in.readColor32();
826        osg::Vec4 secondaryPackedColor = in.readColor32();
827        // version >= VERSION_15_1
[5229]828        /*int textureMappingIndex =*/ in.readInt16(-1);
[5136]829        in.forward(2);
830        int primaryColorIndex = in.readInt32(-1);
[5229]831        /*int alternateColorIndex =*/ in.readInt32(-1);
[5136]832        // version >= 16
833        in.forward(2);
834        int shaderIndex = in.readInt16(-1);
835
836        // Create Geode or Billboard.
837        switch (_template)
838        {
839        case AXIAL_ROTATE_WITH_ALPHA_BLENDING:
840            {
841                osg::Billboard* billboard = new osg::Billboard;
842                billboard->setMode(osg::Billboard::AXIAL_ROT);
843                _geode = billboard;
844            }
845            break;
846        case POINT_ROTATE_WITH_ALPHA_BLENDING:
847            {
848                osg::Billboard* billboard = new osg::Billboard;
849                billboard->setMode(osg::Billboard::POINT_ROT_WORLD);
850                _geode = billboard;
851            }
852            break;
853        default:
854            _geode = new osg::Geode;
855        }
856
857        _geode->setDataVariance(osg::Object::STATIC);
858        _geode->setName(id);
859
860        // StateSet
861        osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
862
863        // Hidden
864        if (isHidden())
865            _geode->setNodeMask(0);
866
867        // Face color
868        if (texturedWhite!=0 && textureIndex>=0)
869        {
870            _primaryColor = osg::Vec4(1,1,1,1);
871        }
872        else
873        {
874            if (packedColorMode())
875            {
876                _primaryColor = primaryPackedColor;
877            }
878            else
879            {
880                if (document.version() < VERSION_15_1)
881                    _primaryColor = document.getColorPool()->getColor(primaryNameIndex);
882
883                else // >= VERSION_15_1
884                    _primaryColor = document.getColorPool()->getColor(primaryColorIndex);
885            }
886        }
887
888        // Lighting
889        stateset->setMode(GL_LIGHTING, isLit() ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
890
891        // Material
[5640]892        if (isLit() || materialIndex>=0)
[5136]893        {
[5640]894            // MaterialPool will return a "default" material if no material is defined for materialIndex.
895            // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000228.html
[5136]896            osg::Vec4 col = _primaryColor;
897            col.a() = 1.0f - getTransparency();
898            osg::Material* material = document.getOrCreateMaterialPool()->getOrCreateMaterial(materialIndex,col);
899            stateset->setAttribute(material);
900        }
901
902        // Shaders
903        if (shaderIndex >= 0)
904        {
905            ShaderPool* sp = document.getOrCreateShaderPool();
906            osg::Program* program = sp->get(shaderIndex);
907            if (program)
908                stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
909        }
910
911         // Texture
912        TexturePool* tp = document.getOrCreateTexturePool();
913        osg::StateSet* textureStateSet = tp->get(textureIndex);
914        if (textureStateSet)
915        {
916            // Merge face stateset with texture stateset
917            stateset->merge(*textureStateSet);
918        }
919
920        // Cull face
921        switch(_drawFlag)
922        {
923        case SOLID_BACKFACED:     // Enable backface culling
924        {
925            static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
926            stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
927            break;
928        }
929        case SOLID_NO_BACKFACE:   // Disable backface culling
930            stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
931            break;
932        }
933
934        // Subface
935        if (document.subfaceLevel() > 0)
936        {
[10084]937            stateset->setAttributeAndModes(document.getSubSurfacePolygonOffset(document.subfaceLevel()), osg::StateAttribute::ON);
938            stateset->setAttribute(document.getSubSurfaceDepth());
[5136]939
940            stateset->setRenderBinDetails(document.subfaceLevel(),"RenderBin");
941        }
942
943        _geode->setStateSet(stateset.get());
944
945        // Add to parent.
946        if (_parent.valid())
947            _parent->addChild(*_geode);
948    }
949
[7756]950    virtual void dispose(Document& document)
[5625]951    {
952        if (_geode.valid())
953        {
[7756]954            // Insert transform(s)
955            if (_matrix.valid())
956            {
957                insertMatrixTransform(*_geode,*_matrix,_numberOfReplications);
958            }
959
[5625]960            osg::StateSet* stateset =  _geode->getOrCreateStateSet();
961
962            // Translucent image?
963            bool isImageTranslucent = false;
964            if (document.getUseTextureAlphaForTransparancyBinning())
965            {
966                for (unsigned int i=0; i<stateset->getTextureAttributeList().size(); ++i)
967                {
968                    osg::StateAttribute* sa = stateset->getTextureAttribute(i,osg::StateAttribute::TEXTURE);
969                    osg::Texture2D* texture = dynamic_cast<osg::Texture2D*>(sa);
970                    if (texture)
971                    {
972                        osg::Image* image = texture->getImage();
973                        if (image && image->isImageTranslucent())
974                            isImageTranslucent = true;
975                    }
976                }
977            }
978
979            // Transparent Material?
980            bool isMaterialTransparent = false;
981            osg::Material* material = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
982            if (material)
983            {
984                isMaterialTransparent = material->getDiffuse(osg::Material::FRONT).a() < 0.99f;
985            }
986
987            // Enable alpha blend?
988            if (isAlphaBlend() || isTransparent() || isImageTranslucent || isMaterialTransparent)
989            {
990                static osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
991                stateset->setAttributeAndModes(blendFunc.get(), osg::StateAttribute::ON);
992                stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
993            }
994
995            if (document.getUseBillboardCenter())
996            {
997                // Set billboard rotation point to center of face.
998                osg::Billboard* billboard = dynamic_cast<osg::Billboard*>(_geode.get());
999                if (billboard)
1000                {
1001                    for (unsigned int i=0; i<billboard->getNumDrawables(); ++i)
1002                    {
1003                        osg::BoundingBox bb = billboard->getDrawable(i)->getBound();
1004                        billboard->setPosition(i,bb.center());
1005
1006                        osgUtil::TransformAttributeFunctor tf(osg::Matrix::translate(-bb.center()));
1007                        billboard->getDrawable(i)->accept(tf);
1008
1009                        billboard->getDrawable(i)->dirtyBound();
1010                    }
1011                   
1012                    billboard->dirtyBound();
1013                }
1014            }
1015        }
1016    }
[5136]1017};
1018
1019RegisterRecordProxy<Mesh> g_Mesh(MESH_OP);
1020
1021
1022
1023/** LocalVertexPool -
1024  */
1025class LocalVertexPool : public Record
1026{
1027    // Attribute Mask
1028    static const unsigned int HAS_POSITION      = 0x80000000u >> 0;
1029    static const unsigned int HAS_COLOR_INDEX   = 0x80000000u >> 1;
1030    static const unsigned int HAS_RGBA_COLOR    = 0x80000000u >> 2;
1031    static const unsigned int HAS_NORMAL        = 0x80000000u >> 3;
1032    static const unsigned int HAS_BASE_UV       = 0x80000000u >> 4;
1033    static const unsigned int HAS_UV_LAYER1     = 0x80000000u >> 5;
1034    static const unsigned int HAS_UV_LAYER2     = 0x80000000u >> 6;
1035    static const unsigned int HAS_UV_LAYER3     = 0x80000000u >> 7;
1036    static const unsigned int HAS_UV_LAYER4     = 0x80000000u >> 8;
1037    static const unsigned int HAS_UV_LAYER5     = 0x80000000u >> 9;
1038    static const unsigned int HAS_UV_LAYER6     = 0x80000000u >> 10;
1039    static const unsigned int HAS_UV_LAYER7     = 0x80000000u >> 11;
1040
1041public:
1042
1043    LocalVertexPool() {}
1044
1045    META_Record(LocalVertexPool)
1046
1047protected:
1048
1049    virtual ~LocalVertexPool() {}
1050
1051    virtual void readRecord(RecordInputStream& in, Document& document)
1052    {
1053
1054        uint32 vertices = in.readUInt32();
1055        uint32 mask = in.readUInt32();
1056
1057        osg::ref_ptr<VertexList> _vertexList = new VertexList(vertices);
1058
1059
1060        for (unsigned int n=0; n<vertices; n++)
1061        {
1062            Vertex vertex;
1063
1064            if (mask & HAS_POSITION)
1065            {
1066                osg::Vec3d coord = in.readVec3d();
1067                vertex.setCoord(coord*document.unitScale());
[5407]1068
1069                if (!coord.valid())
1070                {
1071                    osg::notify(osg::NOTICE)<<"Warning: data error detected in LocalVertexPool::readRecord coord="<<coord.x()<<" "<<coord.y()<<" "<<coord.z()<<std::endl;
1072                }
[5136]1073            }
1074
1075            if (mask & HAS_COLOR_INDEX)
1076            {
1077                uint32 alphaIndex = in.readUInt32();
1078                int index = alphaIndex & 0x00ffffff;
1079                uint8 alpha = alphaIndex >> 24;
1080                osg::Vec4 color = document.getColorPool()->getColor(index);
1081                color.a() = (float)alpha/255;
1082                vertex.setColor(color);
[5407]1083
1084                if (!color.valid())
1085                {
1086                    osg::notify(osg::NOTICE)<<"Warning: data error detected in LocalVertexPool::readRecord color="<<color.r()<<" "<<color.g()<<" "<<color.b()<<" "<<color.a()<<std::endl;
1087                }
[5136]1088            }
1089
1090            if (mask & HAS_RGBA_COLOR)
1091            {
1092                osg::Vec4f color = in.readColor32();
1093                vertex.setColor(color);
[5407]1094
1095                if (!color.valid())
1096                {
1097                    osg::notify(osg::NOTICE)<<"Warning: data error detected in LocalVertexPool::readRecord color="<<color.r()<<" "<<color.g()<<" "<<color.b()<<" "<<color.a()<<std::endl;
1098                }
[5136]1099            }
1100
1101            if (mask & HAS_NORMAL)
1102            {
1103                osg::Vec3f normal = in.readVec3f();
1104                vertex.setNormal(normal);
[5407]1105
1106                if (!normal.valid())
1107                {
1108                    osg::notify(osg::NOTICE)<<"Warning: data error detected in LocalVertexPool::readRecord normal="<<normal.x()<<" "<<normal.y()<<" "<<normal.z()<<std::endl;
1109                }
[5136]1110            }
1111
1112            for (unsigned int layer=0; layer<8; layer++)
1113            {
1114                if (mask & (HAS_BASE_UV >> layer))
1115                {
1116                    osg::Vec2f uv = in.readVec2f();
1117                    vertex.setUV(layer,uv);
[5407]1118                   
1119                    if (!uv.valid())
1120                    {
1121                        osg::notify(osg::NOTICE)<<"Warning: data error detected in LocalVertexPool::readRecord uv="<<uv.x()<<" "<<uv.y()<<std::endl;
1122                    }
1123
[5136]1124                }
1125            }
1126
1127            (*_vertexList)[n] = vertex;
1128        }
1129
1130        if (_parent.valid())
1131            _parent->setLocalVertexPool(_vertexList.get());
1132
1133    }
1134};
1135
1136RegisterRecordProxy<LocalVertexPool> g_LocalVertexPool(LOCAL_VERTEX_POOL_OP);
1137
1138
1139
1140/** MeshPrimitive -
1141  */
1142class MeshPrimitive : public PrimaryRecord
1143{
1144    enum PrimitiveType
1145    {
1146        TRIANGLE_STRIP = 1,
1147        TRIANGLE_FAN = 2,
1148        QUADRILATERAL_STRIP = 3,
1149        INDEXED_POLYGON = 4
1150    };
1151
1152public:
1153
1154    MeshPrimitive() {}
1155
1156    META_Record(MeshPrimitive)
1157
1158protected:
1159
1160    virtual ~MeshPrimitive() {}
1161
[5229]1162    virtual void readRecord(RecordInputStream& in, Document& /*document*/)
[5136]1163    {
1164        Mesh* mesh = dynamic_cast<Mesh*>(_parent.get());
1165        if (!mesh) return;
1166
1167        VertexList* vertexList = mesh->getLocalVertexPool();
1168        if (!vertexList) return;
1169
1170        int16 type = in.readInt16();
1171        uint16 indexSize = in.readUInt16();
1172        uint32 vertexCount = in.readUInt32();
1173
1174        GLenum mode = 0;
1175        switch(type)
1176        {
1177        case TRIANGLE_STRIP:
1178            mode = osg::PrimitiveSet::TRIANGLE_STRIP;
1179            break;
1180        case TRIANGLE_FAN:
1181            mode = osg::PrimitiveSet::TRIANGLE_FAN;
1182            break;
1183        case QUADRILATERAL_STRIP:
1184            mode = osg::PrimitiveSet::QUAD_STRIP;
1185            break;
1186        case INDEXED_POLYGON:
1187            mode = osg::PrimitiveSet::POLYGON;
1188            break;
1189        }
1190
1191        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
1192        geometry->addPrimitiveSet(new osg::DrawArrays(mode,0,vertexCount));
1193
1194        for (unsigned int n=0; n<vertexCount; n++)
1195        {
1196            unsigned int index = 0;
1197            switch (indexSize)
1198            {
1199            case 1:
1200                index = in.readUInt8();
1201                break;
1202            case 2:
1203                index = in.readUInt16();
1204                break;
1205            case 4:
1206                index = in.readUInt32();
1207                break;
1208            }
1209           
1210            if (index < vertexList->size())
1211            {
1212                Vertex& vertex = (*vertexList)[index];
1213
1214                osg::Vec3Array* vertices = getOrCreateVertexArray(*geometry);
1215                vertices->push_back(vertex._coord);
1216
1217                if (vertex.validColor())
1218                {
1219                    osg::Vec4Array* colors = getOrCreateColorArray(*geometry);
1220                    colors->push_back(vertex._color);
1221                }
1222
1223                if (vertex.validNormal())
1224                {
1225                    osg::Vec3Array* normals = getOrCreateNormalArray(*geometry);
1226                    normals->push_back(vertex._normal);
1227                }
1228
1229                for (int layer=0; layer<Vertex::MAX_LAYERS; layer++)
1230                {
1231                    if (vertex.validUV(layer))
1232                    {
1233                        osg::Vec2Array* UVs = getOrCreateTextureArray(*geometry,layer);
1234                        UVs->push_back(vertex._uv[layer]);
1235                    }
1236                }
1237            }
1238        }
1239
1240        // Color binding
1241        if (mesh->isGouraud())
1242        {
1243            // Color per vertex
1244            geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
1245        }
1246        else
1247        {
1248            // Color per face
1249            osg::Vec4 col = mesh->getPrimaryColor();
1250            col[3] = 1.0f - mesh->getTransparency();
1251
1252            geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
1253            osg::Vec4Array* colors = new osg::Vec4Array(1);
1254            (*colors)[0] = col;
1255            geometry->setColorArray(colors);
1256        }
1257
1258        // Normal binding
1259        if (mesh->isLit())
1260        {
1261            geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX );
1262        }
1263        else
1264        {
1265            geometry->setNormalBinding(osg::Geometry::BIND_OFF);
1266            geometry->setNormalArray(NULL);
1267        }
1268
1269        mesh->addGeometry(*geometry);
1270
1271    }
1272};
1273
1274RegisterRecordProxy<MeshPrimitive> g_MeshPrimitive(MESH_PRIMITIVE_OP);
1275
1276
1277} // end namespace
1278
1279
1280
Note: See TracBrowser for help on using the browser.