Jannik Heller | 23 Apr 02:18 2016
Picon
Gravatar

Fix typo in containsNode method name

Hi,

what it says in the title. A typo in the ref_ptr overload for containsNode() had caused the overload to not be used.

Cheers,
Jannik

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=66934#66934

_______________________________________________
osg-submissions mailing list
osg-submissions@...
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
philippe renon | 18 Apr 19:11 2016
Picon
Gravatar

Re: osg-submissions Digest, Vol 106, Issue 1

Bumping this mail.

Not sure if it was missed or is in the todo queue...




Le Lundi 4 avril 2016 0h11, "osg-submissions-request-ZwoEplunGu0hajLcUbyfCyzIfGRoAfqp@public.gmane.org.org" <osg-submissions-request-ZwoEplunGu0hajLcUbyfC12AsgEQdTeF@public.gmane.org> a écrit :


When replying, please edit your Subject line so it is more specific
than "Re: Contents of osg-submissions digest..."


Today's Topics:

  1. osgViewer::Viewer::checkNeedToDoFrame should return true when
      only the root node has an update callback (philippe renon)


----------------------------------------------------------------------

Message: 1
Date: Sun, 3 Apr 2016 22:10:56 +0000 (UTC)
From: philippe renon <philippe_renon-Qt13gs6zZMY@public.gmane.org>
To: "osg-submissions-ZwoEplunGu0hajLcUbyfC12AsgEQdTeF@public.gmane.org"
    <osg-submissions-ZwoEplunGu0xBhcsjnZycA@public.gmane.orgegraph.org>
Subject: [osg-submissions] osgViewer::Viewer::checkNeedToDoFrame
    should return true when only the root node has an update callback
Message-ID:
    <682053180.3306511.1459721456307.JavaMail.yahoo-sAHhhX/85wg@public.gmane.orgoo.com>
Content-Type: text/plain; charset="utf-8"

Hi,
But it does not.
The attached file addresses this. It also contains minor cosmetic changes.

Philippe.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openscenegraph.org/pipermail/osg-submissions-openscenegraph.org/attachments/20160403/3e5c8aaa/attachment.htm>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: Viewer.cpp
URL: <http://lists.openscenegraph.org/pipermail/osg-submissions-openscenegraph.org/attachments/20160403/3e5c8aaa/attachment.asc>

------------------------------

Subject: Digest Footer

_______________________________________________
osg-submissions mailing list
osg-submissions-ZwoEplunGu0hajLcUbyfC12AsgEQdTeF@public.gmane.org
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org


------------------------------

End of osg-submissions Digest, Vol 106, Issue 1
***********************************************


_______________________________________________
osg-submissions mailing list
osg-submissions@...
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
Ralf Habacker | 14 Apr 16:01 2016
Picon
Gravatar

Coverity CID 86499 fix

Hi Robert,

the appended patch fixes the following issue reported by Coverity:

CID 86499 (#1 of 1): Missing break in switch (MISSING_BREAK)
unterminated_case: The case for value 7U is not terminated by a 'break'
statement.

The issue has been introduced with commit
https://github.com/openscenegraph/OpenSceneGraph/commit/e4c2a35a7b43f394ff9e184d559cf8979f29e542

Regards
 Ralf
Attachment (patch.zip): application/zip, 13 KiB
_______________________________________________
osg-submissions mailing list
osg-submissions@...
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
Tony Vasile | 13 Apr 09:53 2016
Picon

Re: OpenFlight-plugin with Surface Material Codes

There is one additional field that may be required by an existing application in addition to the IR Code is
the IR Material. I have a small fix to include the IR Material as the User Value <UA:IRM> .

------------------------
Tony V

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=66797#66797

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

//
// OpenFlight loader for OpenSceneGraph
//
//  Copyright (C) 2005-2007  Brede Johansen
//

#include <assert.h>
#include <osg/Geode>
#include <osg/Billboard>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/CullFace>
#include <osg/BlendFunc>
#include <osgUtil/TransformAttributeFunctor>
#include "Registry.h"
#include "Document.h"
#include "RecordInputStream.h"

#include <osg/ValueObject>

#include <algorithm>

namespace flt {

template<class ARRAY>
void reverseWindingOrder( ARRAY* data, GLenum mode, GLint first, GLint last )
{
    switch( mode )
    {
    case osg::PrimitiveSet::TRIANGLES:
    case osg::PrimitiveSet::QUADS:
    case osg::PrimitiveSet::POLYGON:
        // reverse all the vertices.
        std::reverse(data->begin()+first, data->begin()+last);
        break;
    case osg::PrimitiveSet::TRIANGLE_STRIP:
    case osg::PrimitiveSet::QUAD_STRIP:
        // reverse only the shared edges.
        for( GLint i = first; i < last-1; i+=2 )
        {
            std::swap( (*data)[i], (*data)[i+1] );
        }
        break;
    case osg::PrimitiveSet::TRIANGLE_FAN:
        // reverse all vertices except the first vertex.
        std::reverse(data->begin()+first+1, data->begin()+last);
        break;
    }
}

void addDrawableAndReverseWindingOrder( osg::Geode* geode )
{
    // Replace double sided polygons by duplicating the drawables and inverting the normals.
    std::vector<osg::Geometry*> new_drawables;

    for (size_t i=0; i<geode->getNumDrawables(); ++i)
    {
        const osg::Geometry* geometry = dynamic_cast<const osg::Geometry*>(geode->getDrawable(i));
        if(geometry)
        {
            osg::Geometry* geom = new osg::Geometry(*geometry
                , osg::CopyOp::DEEP_COPY_ARRAYS | osg::CopyOp::DEEP_COPY_PRIMITIVES);
            new_drawables.push_back(geom);

            for( size_t i = 0; i < geom->getNumPrimitiveSets( ); ++i )
            {
                osg::DrawArrays* drawarray = dynamic_cast<osg::DrawArrays*>( geom->getPrimitiveSet( i ) );
                if( drawarray )
                {
                    GLint first = drawarray->getFirst();
                    GLint last  = drawarray->getFirst()+drawarray->getCount();

                    // Invert vertex order.
                    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom->getVertexArray());
                    if( vertices )
                    {
                        reverseWindingOrder( vertices, drawarray->getMode(), first, last );
                    }

                    if( osg::getBinding(geom->getNormalArray()) == osg::Array::BIND_PER_VERTEX )
                    {
                        osg::Vec3Array* normals = dynamic_cast<osg::Vec3Array*>(geom->getNormalArray());
                        if( normals )
                        {
                            // First, invert the direction of the normals.
                            for( GLint i = first; i < last; ++i )
                            {
                                (*normals)[i] = -(*normals)[i];
                            }
                            reverseWindingOrder( normals, drawarray->getMode(), first, last );
                        }
                    }

                    if( osg::getBinding(geom->getColorArray()) == osg::Array::BIND_PER_VERTEX )
                    {
                        osg::Vec4Array* colors = dynamic_cast<osg::Vec4Array*>(geom->getColorArray());
                        if( colors )
                        {
                            reverseWindingOrder( colors, drawarray->getMode(), first, last );
                        }
                    }

                    for( size_t i = 0; i < geom->getNumTexCoordArrays(); ++i )
                    {
                        osg::Vec2Array* UVs = dynamic_cast<osg::Vec2Array*>(geom->getTexCoordArray(i));
                        if( UVs )
                        {
                            reverseWindingOrder( UVs, drawarray->getMode(), first, last );
                        }
                    }
                }
            }
        }
    }

    // Now add the new geometry drawable.
    for( size_t i = 0; i < new_drawables.size( ); ++i )
    {
        geode->addDrawable( new_drawables[i] );
    }
}

/* Face record
 */
class Face : public PrimaryRecord
{
    // flags
    static const unsigned int TERRAIN_BIT      = 0x80000000u >> 0;
    static const unsigned int NO_COLOR_BIT     = 0x80000000u >> 1;
    static const unsigned int NO_ALT_COLOR_BIT = 0x80000000u >> 2;
    static const unsigned int PACKED_COLOR_BIT = 0x80000000u >> 3;
    static const unsigned int FOOTPRINT_BIT    = 0x80000000u >> 4;    // Terrain culture cutout
    static const unsigned int HIDDEN_BIT       = 0x80000000u >> 5;
    static const unsigned int ROOFLINE_BIT     = 0x80000000u >> 6;

    osg::Vec4   _primaryColor;
    uint8       _drawFlag;
    uint8       _template;
    uint16      _transparency;
    uint32      _flags;
    uint8       _lightMode;

    osg::ref_ptr<osg::Geode> _geode;
    osg::ref_ptr<osg::Geometry> _geometry;

public:

    Face() :
        _primaryColor(1,1,1,1),
        _drawFlag(SOLID_NO_BACKFACE),
        _template(FIXED_NO_ALPHA_BLENDING),
        _transparency(0),
        _flags(0),
        _lightMode(FACE_COLOR)
    {
    }

    META_Record(Face)

    META_setID(_geode)
    META_setComment(_geode)
    META_setMultitexture(_geode)

    // draw mode
    enum DrawMode
    {
        SOLID_BACKFACED = 0,
        SOLID_NO_BACKFACE = 1,
        WIREFRAME_CLOSED = 2,
        WIREFRAME_NOT_CLOSED = 3,
        SURROUND_ALTERNATE_COLOR = 4,
        OMNIDIRECTIONAL_LIGHT = 8,
        UNIDIRECTIONAL_LIGHT = 9,
        BIDIRECTIONAL_LIGHT = 10
    };

    inline DrawMode getDrawMode() const { return (DrawMode)_drawFlag; }

    // lighting
    enum LightMode
    {
        FACE_COLOR = 0,
        VERTEX_COLOR = 1,
        FACE_COLOR_LIGHTING = 2,
        VERTEX_COLOR_LIGHTING = 3
    };

    inline LightMode getLightMode() const { return (LightMode)_lightMode; }
    inline bool isLit() const { return (_lightMode==FACE_COLOR_LIGHTING) ||
(_lightMode==VERTEX_COLOR_LIGHTING); }
    inline bool isGouraud() const { return (_lightMode==VERTEX_COLOR) ||
(_lightMode==VERTEX_COLOR_LIGHTING); }

    // flags
    inline bool noColor()         const { return (_flags & NO_COLOR_BIT)!=0; }
    inline bool isHidden()        const { return (_flags & HIDDEN_BIT)!=0; }
    inline bool isTerrain()       const { return (_flags & TERRAIN_BIT)!=0; }
    inline bool isFootprint()     const { return (_flags & FOOTPRINT_BIT)!=0; }
    inline bool isRoofline()      const { return (_flags & ROOFLINE_BIT)!=0; }
    inline bool packedColorMode() const { return (_flags & PACKED_COLOR_BIT)!=0; }

    // billboard
    enum TemplateMode
    {
        FIXED_NO_ALPHA_BLENDING = 0,
        FIXED_ALPHA_BLENDING = 1,
        AXIAL_ROTATE_WITH_ALPHA_BLENDING = 2,
        POINT_ROTATE_WITH_ALPHA_BLENDING = 4
    };

    inline TemplateMode getTemplateMode() const { return (TemplateMode)_template; }

    // transparency & alpha
    inline bool isAlphaBlend() const
    {
        return (_template==FIXED_ALPHA_BLENDING) ||
               (_template==AXIAL_ROTATE_WITH_ALPHA_BLENDING) ||
               (_template==POINT_ROTATE_WITH_ALPHA_BLENDING);
    }

    inline osg::Vec4 getPrimaryColor() const { return _primaryColor; }
    inline float getTransparency() const { return (float)_transparency / 65535.0f; }
    inline bool isTransparent() const { return _transparency > 0; }

    virtual void addChild(osg::Node& child)
    {
        // Add subface to parent.
        if (_parent.valid())
            _parent->addChild(child);
    }

    virtual void addVertex(Vertex& vertex)
    {
        osg::Vec3Array* vertices = getOrCreateVertexArray(*_geometry);
        vertices->push_back(vertex._coord);

        if (isGouraud())
        {
            osg::Vec4Array* colors = getOrCreateColorArray(*_geometry);
            if (vertex.validColor())
            {
                colors->push_back(vertex._color);
            }
            else
            {
                // Use face color if vertex color is -1 in a gouraud polygon.
                // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000967.html
                // Incorporate Face transparency per osg-users thread "Open Flight
                // characteristic not reflected in the current OSG" (Sept/Oct 2011)
                colors->push_back(osg::Vec4(_primaryColor.r(), _primaryColor.g(),
                    _primaryColor.b(), ( 1.0 - getTransparency() ) ));
            }
        }

        bool strict = false; // prepare for "strict" reader option.
        if (strict)
        {
            if (vertex.validNormal())
            {
                osg::Vec3Array* normals = getOrCreateNormalArray(*_geometry);
                normals->push_back(vertex._normal);
            }
        }
        else
        {
            // Add normal only if lit.
            if (isLit())
            {
                osg::Vec3Array* normals = getOrCreateNormalArray(*_geometry);

                if (vertex.validNormal())
                    normals->push_back(vertex._normal);
                else // if lit and no normal in Vertex
                {
                    // Use previous normal if available.
                    if (normals->empty())
                        normals->push_back(osg::Vec3(0,0,1));
                    else
                        normals->push_back(normals->back());
                }
            }
        }

        for (int layer=0; layer<Vertex::MAX_LAYERS; layer++)
        {
            if (vertex.validUV(layer))
            {
                osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,layer);
                UVs->push_back(vertex._uv[layer]);
            }
        }
    }

    virtual void addVertexUV(int unit, const osg::Vec2& uv)
    {
        osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,unit);
        UVs->push_back(uv);
    }

    virtual void addMorphVertex(Vertex& vertex0, Vertex& /*vertex100*/)
    {
        osg::Vec3Array* vertices = getOrCreateVertexArray(*_geometry);
        vertices->push_back(vertex0._coord);

        if (isGouraud())
        {
            osg::Vec4Array* colors = getOrCreateColorArray(*_geometry);
            if (vertex0.validColor())
            {
                colors->push_back(vertex0._color);
            }
            else
            {
                // Use face color if vertex color is -1 in a gouraud polygon.
                // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000967.html
                colors->push_back(_primaryColor);
            }
        }

        if (vertex0.validNormal())
        {
            osg::Vec3Array* normals = getOrCreateNormalArray(*_geometry);
            normals->push_back(vertex0._normal);
        }

        for (int layer=0; layer<Vertex::MAX_LAYERS; layer++)
        {
            if (vertex0.validUV(layer))
            {
                osg::Vec2Array* UVs = getOrCreateTextureArray(*_geometry,layer);
                UVs->push_back(vertex0._uv[layer]);
            }
        }
    }

protected:

    virtual void readRecord(RecordInputStream& in, Document& document)
    {
        std::string id = in.readString(8);
        int32 IRColor = in.readInt32();
        /*int16 relativePriority =*/ in.readInt16();
        _drawFlag = in.readUInt8(SOLID_NO_BACKFACE);
        uint8 texturedWhite = in.readUInt8();
        int16 primaryNameIndex = in.readInt16(-1);
        /*int16 secondaryNameIndex =*/ in.readInt16(-1);
        in.forward(1);
        _template = in.readUInt8(FIXED_NO_ALPHA_BLENDING);
        /*int detailTexture =*/ in.readInt16(-1);
        int textureIndex = in.readInt16(-1);
        int materialIndex = in.readInt16(-1);
        int16 surface = in.readInt16();
        int16 feature = in.readInt16();
        int32 IRMaterial = in.readInt32();
        _transparency = in.readUInt16(0);
        // version > 13
        /*uint8 influenceLOD =*/ in.readUInt8();
        /*uint8 linestyle =*/ in.readUInt8();
        _flags = in.readUInt32(0);
        _lightMode = in.readUInt8(FACE_COLOR);
        in.forward(7);
        osg::Vec4 primaryPackedColor = in.readColor32();
        /*osg::Vec4 secondaryPackedColor =*/ in.readColor32();
        // version >= VERSION_15_1
        /*int textureMappingIndex =*/ in.readInt16(-1);
        in.forward(2);
        int primaryColorIndex = in.readInt32(-1);
        /*int alternateColorIndex =*/ in.readInt32(-1);
        // version >= 16
        in.forward(2);
        int shaderIndex = in.readInt16(-1);

        // Create Geode or Billboard.
        switch (_template)
        {
        case AXIAL_ROTATE_WITH_ALPHA_BLENDING:
            {
                osg::Billboard* billboard = new osg::Billboard;
                billboard->setMode(osg::Billboard::AXIAL_ROT);
                _geode = billboard;
            }
            break;
        case POINT_ROTATE_WITH_ALPHA_BLENDING:
            {
                osg::Billboard* billboard = new osg::Billboard;
                billboard->setMode(osg::Billboard::POINT_ROT_WORLD);
                _geode = billboard;
            }
            break;
        default:
            _geode = new osg::Geode;
        }

        _geode->setDataVariance(osg::Object::STATIC);
        _geode->setName(id);

        _geometry = new osg::Geometry;
        _geometry->setDataVariance(osg::Object::STATIC);
        _geode->addDrawable(_geometry.get());

        // StateSet
        osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;

        // Hidden
        if (isHidden())
            _geode->setNodeMask(0);

        // Face color
        if (texturedWhite!=0 && textureIndex>=0)
        {
            _primaryColor = osg::Vec4(1,1,1,1);
        }
        else
        {
            if (packedColorMode())
            {
                _primaryColor = primaryPackedColor;
            }
            else
            {
                if (document.version() < VERSION_15_1)
                    _primaryColor = document.getColorPool()->getColor(primaryNameIndex);

                else // >= VERSION_15_1
                    _primaryColor = document.getColorPool()->getColor(primaryColorIndex);
            }
        }

        // Lighting
        stateset->setMode(GL_LIGHTING, isLit() ? osg::StateAttribute::ON : osg::StateAttribute::OFF);

        // Material
        if (isLit() || materialIndex>=0)
        {
            // MaterialPool will return a "default" material if no material is defined for materialIndex.
            // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000228.html
            osg::Vec4 col = _primaryColor;
            col.a() = 1.0f - getTransparency();
            osg::Material* material = document.getOrCreateMaterialPool()->getOrCreateMaterial(materialIndex,col);
            stateset->setAttribute(material);
        }

        // IRColor (IRC)
        if (document.getPreserveNonOsgAttrsAsUserData() && 0 != IRColor)
        {
          _geometry->setUserValue("<UA:IRC>", IRColor);
        }

        // IR Material ID (IRM)
        if (document.getPreserveNonOsgAttrsAsUserData() && 0 != IRMaterial)
        {
          _geometry->setUserValue("<UA:IRM>", IRMaterial);
        }

        // surface (SMC)
        if (document.getPreserveNonOsgAttrsAsUserData() && 0 != surface)
        {
          _geometry->setUserValue("<UA:SMC>", surface);
        }

        // feature (FID)
        if (document.getPreserveNonOsgAttrsAsUserData() && 0 != feature)
        {
          _geometry->setUserValue("<UA:FID>", feature);
        }

        // Shaders
        if (shaderIndex >= 0)
        {
            ShaderPool* sp = document.getOrCreateShaderPool();
            osg::Program* program = sp->get(shaderIndex);
            if (program)
                stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
        }

         // Texture
        TexturePool* tp = document.getOrCreateTexturePool();
        osg::StateSet* textureStateSet = tp->get(textureIndex);
        if (textureStateSet)
        {
            // Merge face stateset with texture stateset
            stateset->merge(*textureStateSet);
        }

        // Cull face
        switch(_drawFlag)
        {
        case SOLID_BACKFACED:     // Enable backface culling
        {
            static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
            stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
            break;
        }
        case SOLID_NO_BACKFACE:   // Disable backface culling
            if( document.getReplaceDoubleSidedPolys( ) )
            {
                static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
                stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
            }
            else
            {
                stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
            }
            break;
        }

        // Subface
        if (document.subfaceLevel() > 0)
        {

stateset->setAttributeAndModes(document.getSubSurfacePolygonOffset(document.subfaceLevel()), osg::StateAttribute::ON);
            stateset->setAttribute(document.getSubSurfaceDepth());

            stateset->setRenderBinDetails(document.subfaceLevel(),"RenderBin");
        }

        _geode->setStateSet(stateset.get());

        // Add to parent.
        if (_parent.valid())
            _parent->addChild(*_geode);
    }

    osg::PrimitiveSet::Mode getPrimitiveSetMode(int numVertices)
    {
        switch(getDrawMode())
        {
            case WIREFRAME_NOT_CLOSED:
                return osg::PrimitiveSet::LINE_STRIP;
            case WIREFRAME_CLOSED:
                return osg::PrimitiveSet::LINE_LOOP;
            case OMNIDIRECTIONAL_LIGHT:
            case UNIDIRECTIONAL_LIGHT:
            case BIDIRECTIONAL_LIGHT:
                return osg::PrimitiveSet::POINTS;
            default: break;
        }

        switch (numVertices)
        {
            case 1: return osg::PrimitiveSet::POINTS;
            case 2: return osg::PrimitiveSet::LINES;
            case 3: return osg::PrimitiveSet::TRIANGLES;
            case 4: return osg::PrimitiveSet::QUADS;
            default: break;
        }

        return osg::PrimitiveSet::POLYGON;
    }

    virtual void dispose(Document& document)
    {
        if (_geode.valid())
        {
            // Insert transform(s)
            if (_matrix.valid())
            {
                insertMatrixTransform(*_geode,*_matrix,_numberOfReplications);
            }

            // Add primitives, set bindings etc.
            for (unsigned int i=0; i<_geode->getNumDrawables(); ++i)
            {
                osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(_geode->getDrawable(i));
                if (geometry)
                {
                    osg::Array* vertices = geometry->getVertexArray();
                    if (vertices)
                    {
                        GLint first = 0;
                        GLsizei count = vertices->getNumElements();
                        osg::PrimitiveSet::Mode mode = getPrimitiveSetMode(count);
                        geometry->addPrimitiveSet(new osg::DrawArrays(mode,first,count));
                    }

                    // Color binding
                    if (isGouraud())
                    {
                        // Color per vertex
                        if (geometry->getColorArray()) geometry->getColorArray()->setBinding(osg::Array::BIND_PER_VERTEX);
                    }
                    else
                    {
                        // Color per face
                        osg::Vec4 col = getPrimaryColor();
                        col[3] = 1.0f - getTransparency();

                        osg::Vec4Array* colors = new osg::Vec4Array(1);
                        (*colors)[0] = col;
                        geometry->setColorArray(colors, osg::Array::BIND_OVERALL);
                    }

                    // Normal binding
                    if (isLit())
                    {
                        if (geometry->getNormalArray()) geometry->getNormalArray()->setBinding(osg::Array::BIND_PER_VERTEX);
                    }
                    else
                    {
                        geometry->setNormalArray(0);
                    }
                }
            }

            if( getDrawMode( ) == SOLID_NO_BACKFACE && document.getReplaceDoubleSidedPolys( ) )
            {
                addDrawableAndReverseWindingOrder( _geode.get() );
            }

            osg::StateSet* stateset =  _geode->getOrCreateStateSet();

            // Translucent image?
            bool isImageTranslucent = false;
            if (document.getUseTextureAlphaForTransparancyBinning())
            {
                for (unsigned int i=0; i<stateset->getTextureAttributeList().size(); ++i)
                {
                    osg::StateAttribute* sa = stateset->getTextureAttribute(i,osg::StateAttribute::TEXTURE);
                    osg::Texture2D* texture = dynamic_cast<osg::Texture2D*>(sa);
                    if (texture)
                    {
                        osg::Image* image = texture->getImage();
                        if (image && image->isImageTranslucent())
                            isImageTranslucent = true;
                    }
                }
            }

            // Transparent Material?
            bool isMaterialTransparent = false;
            osg::Material* material = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
            if (material)
            {
                isMaterialTransparent = material->getDiffuse(osg::Material::FRONT).a() < 0.99f;
            }

            // Enable alpha blend?
            if (isAlphaBlend() || isTransparent() || isImageTranslucent || isMaterialTransparent)
            {
                static osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
                stateset->setAttributeAndModes(blendFunc.get(), osg::StateAttribute::ON);
                stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
            }

            if (document.getUseBillboardCenter())
            {
                // Set billboard rotation point to center of face.
                osg::Billboard* billboard = dynamic_cast<osg::Billboard*>(_geode.get());
                if (billboard)
                {
                    for (unsigned int i=0; i<billboard->getNumDrawables(); ++i)
                    {
                        const osg::BoundingBox& bb = billboard->getDrawable(i)->getBoundingBox();
                        billboard->setPosition(i,bb.center());

                        osgUtil::TransformAttributeFunctor tf(osg::Matrix::translate(-bb.center()));
                        billboard->getDrawable(i)->accept(tf);

                        billboard->getDrawable(i)->dirtyBound();
                    }

                    billboard->dirtyBound();
                }
            }
        }
    }
};

REGISTER_FLTRECORD(Face, FACE_OP)

/** VertexList -
  * The VertexList is a leaf record.
  * Possible parents: Face, Mesh & LightPoint
  */
class VertexListRecord : public PrimaryRecord
{
public:

    VertexListRecord() {}

    META_Record(VertexListRecord)

    virtual void addVertex(Vertex& vertex)
    {
        // forward vertex to parent.
        if (_parent.valid())
            _parent->addVertex(vertex);
    }

    virtual void addVertexUV(int layer,const osg::Vec2& uv)
    {
        // forward uv to parent.
        if (_parent.valid())
            _parent->addVertexUV(layer,uv);
    }

protected:

    virtual ~VertexListRecord() {}

    virtual void readRecord(RecordInputStream& in, Document& document)
    {
        VertexPool* vp = document.getVertexPool();
        if (vp)
        {
            int vertices = (in.getRecordSize()-4) / 4;

            // Use the Vertex pool as a record stream.
            RecordInputStream inVP(vp->rdbuf());
            for (int n=0; n<vertices; n++)
            {
                // Get position of vertex.
                uint32 pos = in.readUInt32();

                // Get vertex from vertex pool.
                inVP.seekg((std::istream::pos_type)pos);
                inVP.readRecord(document);
            }
        }
    }
};

REGISTER_FLTRECORD(VertexListRecord, VERTEX_LIST_OP)

/** MorphVertexList -
  * The MorphVertexList is a leaf record.
  */
class MorphVertexList : public PrimaryRecord
{
    enum Mode
    {
        UNDEFINED,
        MORPH_0,
        MORPH_100
    };

    Mode _mode;
    Vertex _vertex0;
    Vertex _vertex100;

public:

    MorphVertexList():
        _mode(UNDEFINED)
    {
    }

    META_Record(MorphVertexList)

    virtual void addVertex(Vertex& vertex)
    {
        switch (_mode)
        {
        case MORPH_0:
            _vertex0 = vertex;
            break;
        case MORPH_100:
            _vertex100 = vertex;

            // forward vertex to parent.
            if (_parent.valid())
                _parent->addMorphVertex(_vertex0, _vertex100);
            break;
        case UNDEFINED:
            break;
        }
    }

    //virtual void addVertexUV(int layer,const osg::Vec2& uv)
    //{
    //    // forward uv to parent.
    //    if (_parent.valid())
    //        _parent->addVertexUV(layer,uv);
    //}

protected:

    virtual ~MorphVertexList() {}

    virtual void readRecord(RecordInputStream& in, Document& document)
    {
        VertexPool* vp = document.getVertexPool();
        if (vp)
        {
            int vertices = (in.getRecordSize()-4) / 8;

            // Use the Vertex pool as a record stream.
            RecordInputStream inVP(vp->rdbuf());
            for (int n=0; n<vertices; n++)
            {
                // Get position of vertex.
                uint32 offset0 = in.readUInt32();
                uint32 offset100 = in.readUInt32();

                // Get vertex from vertex pool.

                // 0%
                _mode = MORPH_0;
                inVP.seekg((std::istream::pos_type)offset0);
                inVP.readRecord(document);

                // 100%
                _mode = MORPH_100;
                inVP.seekg((std::istream::pos_type)offset100);
                inVP.readRecord(document);
            }
        }
    }
};

REGISTER_FLTRECORD(MorphVertexList, MORPH_VERTEX_LIST_OP)

/* Mesh record
 */
class Mesh : public PrimaryRecord
{
    // flags
    static const unsigned int TERRAIN_BIT      = 0x80000000u >> 0;
    static const unsigned int NO_COLOR_BIT     = 0x80000000u >> 1;
    static const unsigned int NO_ALT_COLOR_BIT = 0x80000000u >> 2;
    static const unsigned int PACKED_COLOR_BIT = 0x80000000u >> 3;
    static const unsigned int FOOTPRINT_BIT    = 0x80000000u >> 4;    // Terrain culture cutout
    static const unsigned int HIDDEN_BIT       = 0x80000000u >> 5;
    static const unsigned int ROOFLINE_BIT     = 0x80000000u >> 6;

    osg::Vec4   _primaryColor;
    uint8       _drawFlag;
    uint8       _template;
    uint16      _transparency;
    uint32      _flags;
    uint8       _lightMode;

    osg::ref_ptr<osg::Geode> _geode;

public:

    Mesh() :
        _primaryColor(1,1,1,1),
        _drawFlag(SOLID_NO_BACKFACE),
        _template(FIXED_NO_ALPHA_BLENDING),
        _transparency(0),
        _flags(0),
        _lightMode(FACE_COLOR)
    {
    }

    META_Record(Mesh)

    META_setID(_geode)
    META_setComment(_geode)
    META_setMultitexture(_geode)

    // draw mode
    enum DrawMode
    {
        SOLID_BACKFACED = 0,
        SOLID_NO_BACKFACE = 1,
        WIREFRAME_CLOSED = 2,
        WIREFRAME_NOT_CLOSED = 3,
        SURROUND_ALTERNATE_COLOR = 4,
        OMNIDIRECTIONAL_LIGHT = 8,
        UNIDIRECTIONAL_LIGHT = 9,
        BIDIRECTIONAL_LIGHT = 10
    };

    inline DrawMode getDrawMode() const { return (DrawMode)_drawFlag; }

    // lighting
    enum LightMode
    {
        FACE_COLOR = 0,
        VERTEX_COLOR = 1,
        FACE_COLOR_LIGHTING = 2,
        VERTEX_COLOR_LIGHTING = 3
    };

    inline LightMode getLightMode() const { return (LightMode)_lightMode; }
    inline bool isLit() const { return (_lightMode==FACE_COLOR_LIGHTING) ||
(_lightMode==VERTEX_COLOR_LIGHTING); }
    inline bool isGouraud() const { return (_lightMode==VERTEX_COLOR) ||
(_lightMode==VERTEX_COLOR_LIGHTING); }

    // flags
    inline bool noColor()         const { return (_flags & NO_COLOR_BIT)!=0; }
    inline bool isHidden()        const { return (_flags & HIDDEN_BIT)!=0; }
    inline bool isTerrain()       const { return (_flags & TERRAIN_BIT)!=0; }
    inline bool isFootprint()     const { return (_flags & FOOTPRINT_BIT)!=0; }
    inline bool isRoofline()      const { return (_flags & ROOFLINE_BIT)!=0; }
    inline bool packedColorMode() const { return (_flags & PACKED_COLOR_BIT)!=0; }

    // billboard
    enum TemplateMode
    {
        FIXED_NO_ALPHA_BLENDING = 0,
        FIXED_ALPHA_BLENDING = 1,
        AXIAL_ROTATE_WITH_ALPHA_BLENDING = 2,
        POINT_ROTATE_WITH_ALPHA_BLENDING = 4
    };

    inline TemplateMode getTemplateMode() const { return (TemplateMode)_template; }

    // transparency & alpha
    inline bool isAlphaBlend() const
    {
        return (_template==FIXED_ALPHA_BLENDING) ||
               (_template==AXIAL_ROTATE_WITH_ALPHA_BLENDING) ||
               (_template==POINT_ROTATE_WITH_ALPHA_BLENDING);
    }

    inline osg::Vec4 getPrimaryColor() const { return _primaryColor; }
    inline float getTransparency() const { return (float)_transparency / 65535.0f; }
    inline bool isTransparent() const { return _transparency > 0; }

    virtual void addChild(osg::Node& child)
    {
        // Add subface to parent.
        if (_parent.valid())
            _parent->addChild(child);
    }

    virtual void addGeometry(osg::Geometry& geometry)
    {
        _geode->addDrawable(&geometry);
    }

protected:

    virtual void readRecord(RecordInputStream& in, Document& document)
    {
        std::string id = in.readString(8);
        in.forward(4);
        int32 IRColor = in.readInt32();
        /*int16 relativePriority =*/ in.readInt16();
        _drawFlag = in.readUInt8(SOLID_NO_BACKFACE);
        uint8 texturedWhite = in.readUInt8();
        int16 primaryNameIndex = in.readInt16(-1);
        /*int16 secondaryNameIndex =*/ in.readInt16(-1);
        in.forward(1);
        _template = in.readUInt8(FIXED_NO_ALPHA_BLENDING);
        /*int detailTexture =*/ in.readInt16(-1);
        int textureIndex = in.readInt16(-1);
        int materialIndex = in.readInt16(-1);
        int16 surface = in.readInt16();
        int16 feature = in.readInt16();
        /*int32 IRMaterial =*/ in.readInt32(-1);
        _transparency = in.readUInt16(0);
        // version > 13
        /*uint8 influenceLOD =*/ in.readUInt8();
        /*uint8 linestyle =*/ in.readUInt8();
        _flags = in.readUInt32(0);
        _lightMode = in.readUInt8(FACE_COLOR);
        in.forward(7);
        osg::Vec4 primaryPackedColor = in.readColor32();
        /*osg::Vec4 secondaryPackedColor =*/ in.readColor32();
        // version >= VERSION_15_1
        /*int textureMappingIndex =*/ in.readInt16(-1);
        in.forward(2);
        int primaryColorIndex = in.readInt32(-1);
        /*int alternateColorIndex =*/ in.readInt32(-1);
        // version >= 16
        in.forward(2);
        int shaderIndex = in.readInt16(-1);

        // Create Geode or Billboard.
        switch (_template)
        {
        case AXIAL_ROTATE_WITH_ALPHA_BLENDING:
            {
                osg::Billboard* billboard = new osg::Billboard;
                billboard->setMode(osg::Billboard::AXIAL_ROT);
                _geode = billboard;
            }
            break;
        case POINT_ROTATE_WITH_ALPHA_BLENDING:
            {
                osg::Billboard* billboard = new osg::Billboard;
                billboard->setMode(osg::Billboard::POINT_ROT_WORLD);
                _geode = billboard;
            }
            break;
        default:
            _geode = new osg::Geode;
        }

        _geode->setDataVariance(osg::Object::STATIC);
        _geode->setName(id);

        // StateSet
        osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;

        // Hidden
        if (isHidden())
            _geode->setNodeMask(0);

        // Face color
        if (texturedWhite!=0 && textureIndex>=0)
        {
            _primaryColor = osg::Vec4(1,1,1,1);
        }
        else
        {
            if (packedColorMode())
            {
                _primaryColor = primaryPackedColor;
            }
            else
            {
                if (document.version() < VERSION_15_1)
                    _primaryColor = document.getColorPool()->getColor(primaryNameIndex);

                else // >= VERSION_15_1
                    _primaryColor = document.getColorPool()->getColor(primaryColorIndex);
            }
        }

        // Lighting
        stateset->setMode(GL_LIGHTING, isLit() ? osg::StateAttribute::ON : osg::StateAttribute::OFF);

        // Material
        if (isLit() || materialIndex>=0)
        {
            // MaterialPool will return a "default" material if no material is defined for materialIndex.
            // http://www.multigen-paradigm.com/ubb/Forum1/HTML/000228.html
            osg::Vec4 col = _primaryColor;
            col.a() = 1.0f - getTransparency();
            osg::Material* material = document.getOrCreateMaterialPool()->getOrCreateMaterial(materialIndex,col);
            stateset->setAttribute(material);
        }

        // IRColor (IRC)
        if (document.getPreserveNonOsgAttrsAsUserData() && 0 != IRColor)
        {
          _geode->setUserValue("<UA:IRC>", IRColor);
        }

        // surface (SMC)
        if (document.getPreserveNonOsgAttrsAsUserData() && 0 != surface)
        {
          _geode->setUserValue("<UA:SMC>", surface);
        }

        // feature (FID)
        if (document.getPreserveNonOsgAttrsAsUserData() && 0 != feature)
        {
          _geode->setUserValue("<UA:FID>", feature);
        }

        // Shaders
        if (shaderIndex >= 0)
        {
            ShaderPool* sp = document.getOrCreateShaderPool();
            osg::Program* program = sp->get(shaderIndex);
            if (program)
                stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
        }

         // Texture
        TexturePool* tp = document.getOrCreateTexturePool();
        osg::StateSet* textureStateSet = tp->get(textureIndex);
        if (textureStateSet)
        {
            // Merge face stateset with texture stateset
            stateset->merge(*textureStateSet);
        }

        // Cull face
        switch(_drawFlag)
        {
        case SOLID_BACKFACED:     // Enable backface culling
        {
            static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
            stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
            break;
        }
        case SOLID_NO_BACKFACE:   // Disable backface culling
            if( document.getReplaceDoubleSidedPolys( ) )
            {
                static osg::ref_ptr<osg::CullFace> cullFace = new osg::CullFace(osg::CullFace::BACK);
                stateset->setAttributeAndModes(cullFace.get(), osg::StateAttribute::ON);
            }
            else
            {
                stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
            }
            break;
        }

        // Subface
        if (document.subfaceLevel() > 0)
        {

stateset->setAttributeAndModes(document.getSubSurfacePolygonOffset(document.subfaceLevel()), osg::StateAttribute::ON);
            stateset->setAttribute(document.getSubSurfaceDepth());

            stateset->setRenderBinDetails(document.subfaceLevel(),"RenderBin");
        }

        _geode->setStateSet(stateset.get());

        // Add to parent.
        if (_parent.valid())
            _parent->addChild(*_geode);
    }

    virtual void dispose(Document& document)
    {
        if (_geode.valid())
        {
            // Insert transform(s)
            if (_matrix.valid())
            {
                insertMatrixTransform(*_geode,*_matrix,_numberOfReplications);
            }

            if( getDrawMode( ) == SOLID_NO_BACKFACE && document.getReplaceDoubleSidedPolys( ) )
            {
                addDrawableAndReverseWindingOrder( _geode.get() );
            }

            osg::StateSet* stateset =  _geode->getOrCreateStateSet();

            // Translucent image?
            bool isImageTranslucent = false;
            if (document.getUseTextureAlphaForTransparancyBinning())
            {
                for (unsigned int i=0; i<stateset->getTextureAttributeList().size(); ++i)
                {
                    osg::StateAttribute* sa = stateset->getTextureAttribute(i,osg::StateAttribute::TEXTURE);
                    osg::Texture2D* texture = dynamic_cast<osg::Texture2D*>(sa);
                    if (texture)
                    {
                        osg::Image* image = texture->getImage();
                        if (image && image->isImageTranslucent())
                            isImageTranslucent = true;
                    }
                }
            }

            // Transparent Material?
            bool isMaterialTransparent = false;
            osg::Material* material = dynamic_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
            if (material)
            {
                isMaterialTransparent = material->getDiffuse(osg::Material::FRONT).a() < 0.99f;
            }

            // Enable alpha blend?
            if (isAlphaBlend() || isTransparent() || isImageTranslucent || isMaterialTransparent)
            {
                static osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
                stateset->setAttributeAndModes(blendFunc.get(), osg::StateAttribute::ON);
                stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
            }

            if (document.getUseBillboardCenter())
            {
                // Set billboard rotation point to center of face.
                osg::Billboard* billboard = dynamic_cast<osg::Billboard*>(_geode.get());
                if (billboard)
                {
                    for (unsigned int i=0; i<billboard->getNumDrawables(); ++i)
                    {
                        const osg::BoundingBox& bb = billboard->getDrawable(i)->getBoundingBox();
                        billboard->setPosition(i,bb.center());

                        osgUtil::TransformAttributeFunctor tf(osg::Matrix::translate(-bb.center()));
                        billboard->getDrawable(i)->accept(tf);

                        billboard->getDrawable(i)->dirtyBound();
                    }

                    billboard->dirtyBound();
                }
            }
        }
    }
};

REGISTER_FLTRECORD(Mesh, MESH_OP)

/** LocalVertexPool -
  */
class LocalVertexPool : public Record
{
    // Attribute Mask
    static const unsigned int HAS_POSITION      = 0x80000000u >> 0;
    static const unsigned int HAS_COLOR_INDEX   = 0x80000000u >> 1;
    static const unsigned int HAS_RGBA_COLOR    = 0x80000000u >> 2;
    static const unsigned int HAS_NORMAL        = 0x80000000u >> 3;
    static const unsigned int HAS_BASE_UV       = 0x80000000u >> 4;
    static const unsigned int HAS_UV_LAYER1     = 0x80000000u >> 5;
    static const unsigned int HAS_UV_LAYER2     = 0x80000000u >> 6;
    static const unsigned int HAS_UV_LAYER3     = 0x80000000u >> 7;
    static const unsigned int HAS_UV_LAYER4     = 0x80000000u >> 8;
    static const unsigned int HAS_UV_LAYER5     = 0x80000000u >> 9;
    static const unsigned int HAS_UV_LAYER6     = 0x80000000u >> 10;
    static const unsigned int HAS_UV_LAYER7     = 0x80000000u >> 11;

public:

    LocalVertexPool() {}

    META_Record(LocalVertexPool)

protected:

    virtual ~LocalVertexPool() {}

    virtual void readRecord(RecordInputStream& in, Document& document)
    {

        uint32 vertices = in.readUInt32();
        uint32 mask = in.readUInt32();

        osg::ref_ptr<VertexList> _vertexList = new VertexList(vertices);

        for (unsigned int n=0; n<vertices; n++)
        {
            Vertex vertex;

            if (mask & HAS_POSITION)
            {
                osg::Vec3d coord = in.readVec3d();
                vertex.setCoord(coord*document.unitScale());

                if (!coord.valid())
                {
                    OSG_NOTICE<<"Warning: data error detected in LocalVertexPool::readRecord coord="<<coord.x()<<"
"<<coord.y()<<" "<<coord.z()<<std::endl;
                }
            }

            if (mask & HAS_COLOR_INDEX)
            {
                uint32 alphaIndex = in.readUInt32();
                int index = alphaIndex & 0x00ffffff;
                uint8 alpha = alphaIndex >> 24;
                osg::Vec4 color = document.getColorPool()->getColor(index);
                color.a() = (float)alpha/255;
                vertex.setColor(color);

                if (!color.valid())
                {
                    OSG_NOTICE<<"Warning: data error detected in LocalVertexPool::readRecord color="<<color.r()<<"
"<<color.g()<<" "<<color.b()<<" "<<color.a()<<std::endl;
                }
            }

            if (mask & HAS_RGBA_COLOR)
            {
                osg::Vec4f color = in.readColor32();
                vertex.setColor(color);

                if (!color.valid())
                {
                    OSG_NOTICE<<"Warning: data error detected in LocalVertexPool::readRecord color="<<color.r()<<"
"<<color.g()<<" "<<color.b()<<" "<<color.a()<<std::endl;
                }
            }

            if (mask & HAS_NORMAL)
            {
                osg::Vec3f normal = in.readVec3f();
                vertex.setNormal(normal);

                if (!normal.valid())
                {
                    OSG_NOTICE<<"Warning: data error detected in LocalVertexPool::readRecord normal="<<normal.x()<<"
"<<normal.y()<<" "<<normal.z()<<std::endl;
                }
            }

            for (unsigned int layer=0; layer<8; layer++)
            {
                if (mask & (HAS_BASE_UV >> layer))
                {
                    osg::Vec2f uv = in.readVec2f();
                    vertex.setUV(layer,uv);

                    if (!uv.valid())
                    {
                        OSG_NOTICE<<"Warning: data error detected in LocalVertexPool::readRecord uv="<<uv.x()<<" "<<uv.y()<<std::endl;
                    }

                }
            }

            (*_vertexList)[n] = vertex;
        }

        if (_parent.valid())
            _parent->setLocalVertexPool(_vertexList.get());

    }
};

REGISTER_FLTRECORD(LocalVertexPool, LOCAL_VERTEX_POOL_OP)

/** MeshPrimitive -
  */
class MeshPrimitive : public PrimaryRecord
{
    enum PrimitiveType
    {
        TRIANGLE_STRIP = 1,
        TRIANGLE_FAN = 2,
        QUADRILATERAL_STRIP = 3,
        INDEXED_POLYGON = 4
    };

public:

    MeshPrimitive() {}

    META_Record(MeshPrimitive)

protected:

    virtual ~MeshPrimitive() {}

    virtual void readRecord(RecordInputStream& in, Document& /*document*/)
    {
        Mesh* mesh = dynamic_cast<Mesh*>(_parent.get());
        if (!mesh) return;

        VertexList* vertexList = mesh->getLocalVertexPool();
        if (!vertexList) return;

        int16 type = in.readInt16();
        uint16 indexSize = in.readUInt16();
        uint32 vertexCount = in.readUInt32();

        GLenum mode = 0;
        switch(type)
        {
        case TRIANGLE_STRIP:
            mode = osg::PrimitiveSet::TRIANGLE_STRIP;
            break;
        case TRIANGLE_FAN:
            mode = osg::PrimitiveSet::TRIANGLE_FAN;
            break;
        case QUADRILATERAL_STRIP:
            mode = osg::PrimitiveSet::QUAD_STRIP;
            break;
        case INDEXED_POLYGON:
            mode = osg::PrimitiveSet::POLYGON;
            break;
        }

        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
        geometry->addPrimitiveSet(new osg::DrawArrays(mode,0,vertexCount));

        for (unsigned int n=0; n<vertexCount; n++)
        {
            unsigned int index = 0;
            switch (indexSize)
            {
            case 1:
                index = in.readUInt8();
                break;
            case 2:
                index = in.readUInt16();
                break;
            case 4:
                index = in.readUInt32();
                break;
            }

            if (index < vertexList->size())
            {
                Vertex& vertex = (*vertexList)[index];

                osg::Vec3Array* vertices = getOrCreateVertexArray(*geometry);
                vertices->push_back(vertex._coord);

                if (vertex.validColor())
                {
                    osg::Vec4Array* colors = getOrCreateColorArray(*geometry);
                    colors->push_back(vertex._color);
                }

                if (vertex.validNormal())
                {
                    osg::Vec3Array* normals = getOrCreateNormalArray(*geometry);
                    normals->push_back(vertex._normal);
                }

                for (int layer=0; layer<Vertex::MAX_LAYERS; layer++)
                {
                    if (vertex.validUV(layer))
                    {
                        osg::Vec2Array* UVs = getOrCreateTextureArray(*geometry,layer);
                        UVs->push_back(vertex._uv[layer]);
                    }
                }
            }
        }

        // Color binding
        if (mesh->isGouraud())
        {
            // Color per vertex
            if (geometry->getColorArray()) geometry->getColorArray()->setBinding(osg::Array::BIND_PER_VERTEX);
        }
        else
        {
            // Color per face
            osg::Vec4 col = mesh->getPrimaryColor();
            col[3] = 1.0f - mesh->getTransparency();

            osg::Vec4Array* colors = new osg::Vec4Array(1);
            (*colors)[0] = col;
            geometry->setColorArray(colors, osg::Array::BIND_OVERALL);
        }

        // Normal binding
        if (mesh->isLit())
        {
            if (geometry->getNormalArray()) geometry->getNormalArray()->setBinding(osg::Array::BIND_PER_VERTEX);
        }
        else
        {
            geometry->setNormalArray(0);
        }

        mesh->addGeometry(*geometry);

    }
};

REGISTER_FLTRECORD(MeshPrimitive, MESH_PRIMITIVE_OP)

} // end namespace

_______________________________________________
osg-submissions mailing list
osg-submissions@...
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
We See | 5 Apr 11:39 2016
Picon

Small fix for option "readObjectRecordData" of OpenFlight-plugin

Hi Robert,

See attached a small submission, which makes the option "readObjectRecordData" of OpenFlight-plugin
working like documented in the Knowledge Base of OSG (52-using-the-openflight-plugin).

Actually, if the option "readObjectRecordData" is set, ObjectRecordData will not be read and set.
With this submission, if the option "readObjectRecordData" is set, ObjectRecordData will be read and set.

Thank you!

Cheers,
WeSee

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=66729#66729

Attachments: 
http://forum.openscenegraph.org//files/readerwriterflt_894.zip
philippe renon | 4 Apr 00:10 2016
Picon
Gravatar

osgViewer::Viewer::checkNeedToDoFrame should return true when only the root node has an update callback

Hi,

But it does not.

The attached file addresses this. It also contains minor cosmetic changes.

Philippe.
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <stdio.h>
#include <stdlib.h>

#include <osg/DeleteHandler>
#include <osg/io_utils>
#include <osg/TextureRectangle>
#include <osg/TextureCubeMap>

#include <osgUtil/RayIntersector>

#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgGA/TrackballManipulator>

#include <osgViewer/Viewer>
#include <osgViewer/Renderer>
#include <osgViewer/CompositeViewer>

#include <osgViewer/config/SphericalDisplay>
#include <osgViewer/config/PanoramicSphericalDisplay>
#include <osgViewer/config/WoWVxDisplay>

#include <sstream>
#include <string.h>

using namespace osgViewer;


Viewer::Viewer()
{
    _viewerBase = this;

    constructorInit();
}

Viewer::Viewer(osg::ArgumentParser& arguments)
{
    _viewerBase = this;

    constructorInit();

    // Add help for command-line options read here
    arguments.getApplicationUsage()->addCommandLineOption("--SingleThreaded","Select
SingleThreaded threading model for viewer.");
    arguments.getApplicationUsage()->addCommandLineOption("--CullDrawThreadPerContext","Select
CullDrawThreadPerContext threading model for viewer.");
    arguments.getApplicationUsage()->addCommandLineOption("--DrawThreadPerContext","Select
DrawThreadPerContext threading model for viewer.");

arguments.getApplicationUsage()->addCommandLineOption("--CullThreadPerCameraDrawThreadPerContext","Select
CullThreadPerCameraDrawThreadPerContext threading model for viewer.");
    arguments.getApplicationUsage()->addCommandLineOption("--clear-color <color>","Set the
background color of the viewer in the form \"r,g,b[,a]\".");
    arguments.getApplicationUsage()->addCommandLineOption("--screen <num>","Set the screen to use
when multiple screens are present.");
    arguments.getApplicationUsage()->addCommandLineOption("--window <x y w h>","Set the position
(x,y) and size (w,h) of the viewer window.");

    arguments.getApplicationUsage()->addCommandLineOption("--run-on-demand","Set the run methods
frame rate management to only rendering frames when required.");
    arguments.getApplicationUsage()->addCommandLineOption("--run-continuous","Set the run methods
frame rate management to rendering frames continuously.");
    arguments.getApplicationUsage()->addCommandLineOption("--run-max-frame-rate","Set the run
methods maximum permissible frame rate, 0.0 is default and switching off frame rate capping.");
    arguments.getApplicationUsage()->addCommandLineOption("--enable-object-cache","Enable
caching of objects, images, etc.");

    // FIXME: Uncomment these lines when the options have been documented properly
    //arguments.getApplicationUsage()->addCommandLineOption("--3d-sd","");
    //arguments.getApplicationUsage()->addCommandLineOption("--panoramic-sd","");
    //arguments.getApplicationUsage()->addCommandLineOption("--radius","");
    //arguments.getApplicationUsage()->addCommandLineOption("--collar","");
    //arguments.getApplicationUsage()->addCommandLineOption("--im","");

    if (arguments.read("--ico"))
    {
        setIncrementalCompileOperation(new osgUtil::IncrementalCompileOperation());
    }

    std::string filename;
    bool readConfig = false;
    while (arguments.read("-c",filename))
    {
        readConfig = readConfiguration(filename) || readConfig;
    }

    // Enable caching?
    while (arguments.read("--enable-object-cache"))
    {
        if (osgDB::Registry::instance()->getOptions()==0)
osgDB::Registry::instance()->setOptions(new osgDB::Options());
        osgDB::Registry::instance()->getOptions()->setObjectCacheHint(osgDB::Options::CACHE_ALL);
    }

    while (arguments.read("--SingleThreaded")) setThreadingModel(SingleThreaded);
    while (arguments.read("--CullDrawThreadPerContext")) setThreadingModel(CullDrawThreadPerContext);
    while (arguments.read("--DrawThreadPerContext")) setThreadingModel(DrawThreadPerContext);
    while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) setThreadingModel(CullThreadPerCameraDrawThreadPerContext);

    osg::DisplaySettings::instance()->readCommandLine(arguments);
    osgDB::readCommandLine(arguments);

    std::string colorStr;
    while (arguments.read("--clear-color",colorStr))
    {
        float r, g, b;
        float a = 1.0f;
        int cnt = sscanf( colorStr.c_str(), "%f,%f,%f,%f", &r, &g, &b, &a );
        if( cnt==3 || cnt==4 )
        {
            getCamera()->setClearColor( osg::Vec4(r,g,b,a) );
        }
        else
        {
            OSG_WARN<<"Invalid clear color \""<<colorStr<<"\""<<std::endl;
        }
    }


    while(arguments.read("--run-on-demand")) { setRunFrameScheme(ON_DEMAND); }
    while(arguments.read("--run-continuous")) { setRunFrameScheme(CONTINUOUS); }

    double runMaxFrameRate;
    while(arguments.read("--run-max-frame-rate", runMaxFrameRate)) {
setRunMaxFrameRate(runMaxFrameRate); }


    int screenNum = -1;
    while (arguments.read("--screen",screenNum)) {}

    int x = -1, y = -1, width = -1, height = -1;
    while (arguments.read("--window",x,y,width,height)) {}

    bool ss3d = false;
    bool wowvx20 = false;
    bool wowvx42 = false;
    if ((wowvx20=arguments.read("--wowvx-20")) || (wowvx42=arguments.read("--wowvx-42")) || arguments.read("--wowvx"))
    {
        osg::ref_ptr<WoWVxDisplay> wow = new WoWVxDisplay;

        if (screenNum>=0) wow->setScreenNum(screenNum);
        if (wowvx20) wow->WoWVx20();
        if (wowvx42) wow->WoWVx42();

        unsigned int c;
        float v;
        while (arguments.read("--wow-content",c)) { wow->setContent(c); }
        while (arguments.read("--wow-factor",c)) { wow->setFactor(c); }
        while (arguments.read("--wow-offset",c)) { wow->setOffset(c); }
        while (arguments.read("--wow-zd",v)) { wow->setDisparityZD(v); }
        while (arguments.read("--wow-vz",v)) { wow->setDisparityVZ(v); }
        while (arguments.read("--wow-M",v)) { wow->setDisparityM(v); }
        while (arguments.read("--wow-C",v)) { wow->setDisparityC(v); }

        apply(wow.get());
    }
    else if ((ss3d=arguments.read("--3d-sd")) || arguments.read("--panoramic-sd"))
    {
        double radius = 1.0;
        while (arguments.read("--radius",radius)) {}

        double collar = 0.45;
        while (arguments.read("--collar",collar)) {}

        std::string intensityMapFilename;
        while (arguments.read("--im",intensityMapFilename)) {}

        osg::ref_ptr<osg::Image> intensityMap = intensityMapFilename.empty() ? 0 : osgDB::readRefImageFile(intensityMapFilename);

        if (screenNum<0) screenNum = 0;

        if (ss3d)
        {
            setThreadingModel(SingleThreaded);
            setUpViewFor3DSphericalDisplay(radius, collar, screenNum, intensityMap.get());
        }
        else
        {
            setThreadingModel(SingleThreaded);
            setUpViewForPanoramicSphericalDisplay(radius, collar, screenNum, intensityMap.get());
        }
    }
    else if (width>0 && height>0)
    {
        if (screenNum>=0) setUpViewInWindow(x, y, width, height, screenNum);
        else setUpViewInWindow(x,y,width,height);

    }
    else if (screenNum>=0)
    {
        setUpViewOnSingleScreen(screenNum);
    }

}

Viewer::Viewer(const osgViewer::Viewer& viewer, const osg::CopyOp& copyop):
    osg::Object(true),
    ViewerBase(viewer),
    View(viewer,copyop)
{
    _viewerBase = this;
}

void Viewer::constructorInit()
{
    _eventVisitor = new osgGA::EventVisitor;
    _eventVisitor->setActionAdapter(this);
    _eventVisitor->setFrameStamp(_frameStamp.get());

    _updateVisitor = new osgUtil::UpdateVisitor;
    _updateVisitor->setFrameStamp(_frameStamp.get());

    setViewerStats(new osg::Stats("Viewer"));
}

Viewer::~Viewer()
{
    //OSG_NOTICE<<"Viewer::~Viewer()"<<std::endl;

    Threads threads;
    getAllThreads(threads);

    OSG_INFO<<"Viewer::~Viewer():: start destructor getThreads = "<<threads.size()<<std::endl;

    stopThreading();

    if (_scene.valid() && _scene->getDatabasePager())
    {
        _scene->getDatabasePager()->cancel();
        _scene->setDatabasePager(0);
    }

    Contexts contexts;
    getContexts(contexts);

    // clear out all the previously assigned operations
    for(Contexts::iterator citr = contexts.begin();
        citr != contexts.end();
        ++citr)
    {
        (*citr)->close();
    }

    //OSG_NOTICE<<"finish Viewer::~Viewer()"<<std::endl;

    getAllThreads(threads);

    OSG_INFO<<"Viewer::~Viewer() end destructor getThreads = "<<threads.size()<<std::endl;
}

void Viewer::take(osg::View& rhs)
{
    osgViewer::View::take(rhs);

#if 1
    osgViewer::Viewer* rhs_viewer = dynamic_cast<osgViewer::Viewer*>(&rhs);
    if (rhs_viewer)
    {
        // variables left to take.
        _done = rhs_viewer->_done;
        _keyEventSetsDone = rhs_viewer->_keyEventSetsDone;
        _quitEventSetsDone = rhs_viewer->_quitEventSetsDone;
        _threadingModel = rhs_viewer->_threadingModel;
        _threadsRunning = rhs_viewer->_threadsRunning;
        _endBarrierPosition = rhs_viewer->_endBarrierPosition;
        _startRenderingBarrier = rhs_viewer->_startRenderingBarrier;
        _endRenderingDispatchBarrier = rhs_viewer->_endRenderingDispatchBarrier;
        _endDynamicDrawBlock = rhs_viewer->_endDynamicDrawBlock;

        _eventVisitor = rhs_viewer->_eventVisitor;
        _eventVisitor->setActionAdapter(this);
        _eventVisitor->setFrameStamp(_frameStamp.get());

        _updateOperations = rhs_viewer->_updateOperations;
        _updateVisitor = rhs_viewer->_updateVisitor;

        _realizeOperation = rhs_viewer->_realizeOperation;
        _currentContext = rhs_viewer->_currentContext;


        // objects to clear
        rhs_viewer->_done = true;
        rhs_viewer->_startRenderingBarrier = 0;
        rhs_viewer->_endRenderingDispatchBarrier = 0;
        rhs_viewer->_endDynamicDrawBlock = 0;
        rhs_viewer->_eventVisitor = 0;
        rhs_viewer->_updateOperations = 0;
        rhs_viewer->_updateVisitor = 0;
        rhs_viewer->_realizeOperation = 0;
        rhs_viewer->_currentContext = 0;

    }
#endif
}

bool Viewer::readConfiguration(const std::string& filename)
{
    OSG_INFO<<"Viewer::readConfiguration("<<filename<<")"<<std::endl;

    osg::ref_ptr<osg::Object> object = osgDB::readRefObjectFile(filename);
    if (!object)
    {
        //OSG_NOTICE<<"Error: Unable to load configuration file \""<<filename<<"\""<<std::endl;
        return false;
    }

    ViewConfig* config = dynamic_cast<ViewConfig*>(object.get());
    if (config)
    {
        OSG_INFO<<"Using osgViewer::Config : "<<config->className()<<std::endl;

        config->configure(*this);

        //osgDB::writeObjectFile(*config,"test.osgt");

        return true;
    }


    CompositeViewer* compositeViewer = dynamic_cast<CompositeViewer*>(object.get());
    if (compositeViewer)
    {
        OSG_NOTICE<<"Error: Config file \""<<filename<<"\" containing CompositeViewer cannot be loaded by Viewer."<<std::endl;
        return false;
    }

    View* view = dynamic_cast<osgViewer::View*>(object.get());
    if (view)
    {
        take(*view);

        return true;
    }
    else
    {
        OSG_NOTICE<<"Error: Config file \""<<filename<<"\" does not contain a valid Viewer configuration."<<std::endl;
        return false;
    }
}

bool Viewer::isRealized() const
{
    Contexts contexts;
    const_cast<Viewer*>(this)->getContexts(contexts);

    unsigned int numRealizedWindows = 0;

    // clear out all the previously assigned operations
    for(Contexts::iterator citr = contexts.begin();
        citr != contexts.end();
        ++citr)
    {
        if ((*citr)->isRealized()) ++numRealizedWindows;
    }

    return numRealizedWindows > 0;
}

bool Viewer::checkNeedToDoFrame()
{
    // check if any event handler has prompted a redraw
    if (_requestRedraw) return true;
    if (_requestContinousUpdate) return true;

    // check if the database pager needs to update the scene
    if (getDatabasePager()->requiresUpdateSceneGraph() ||
getDatabasePager()->getRequestsInProgress()) return true;

    // check if there are node update callbacks
    if (_camera->getUpdateCallback()) return true;
    if (getSceneData() != 0 && getSceneData()->getUpdateCallback()) return true;
    if (getSceneData() != 0 && getSceneData()->getNumChildrenRequiringUpdateTraversal() > 0) return true;

    // check if events are available and need processing
    if (checkEvents()) return true;

    // and check again if any event handler has prompted a redraw
    if (_requestRedraw) return true;
    if (_requestContinousUpdate) return true;

    return false;
}

bool Viewer::checkEvents()
{
    // check events from any attached sources
    for(Devices::iterator eitr = _eventSources.begin();
        eitr != _eventSources.end();
        ++eitr)
    {
        osgGA::Device* es = eitr->get();
        if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS)
        {
            if (es->checkEvents()) return true;
        }

    }

    // get events from all windows attached to Viewer.
    Windows windows;
    getWindows(windows);
    for(Windows::iterator witr = windows.begin();
        witr != windows.end();
        ++witr)
    {
        if ((*witr)->checkEvents()) return true;
    }

    return false;
}

int Viewer::run()
{
    if (!getCameraManipulator() && getCamera()->getAllowEventFocus())
    {
        setCameraManipulator(new osgGA::TrackballManipulator());
    }

    setReleaseContextAtEndOfFrameHint(false);

    return ViewerBase::run();
}

void Viewer::setStartTick(osg::Timer_t tick)
{
    View::setStartTick(tick);

    Contexts contexts;
    getContexts(contexts,false);

    getEventQueue()->setStartTick(_startTick);
    for(Contexts::iterator citr = contexts.begin();
        citr != contexts.end();
        ++citr)
    {
        osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
        if (gw)
        {
            gw->getEventQueue()->setStartTick(_startTick);
        }
    }
}

void Viewer::setReferenceTime(double time)
{
    osg::Timer_t tick = osg::Timer::instance()->tick();
    double currentTime = osg::Timer::instance()->delta_s(_startTick, tick);
    double delta_ticks = (time-currentTime)/(osg::Timer::instance()->getSecondsPerTick());
    if (delta_ticks>=0) tick += osg::Timer_t(delta_ticks);
    else tick -= osg::Timer_t(-delta_ticks);

    // assign the new start tick
    setStartTick(tick);
}


void Viewer::setSceneData(osg::Node* node)
{
    setReferenceTime(0.0);

    View::setSceneData(node);
}

GraphicsWindowEmbedded* Viewer::setUpViewerAsEmbeddedInWindow(int x, int y, int width, int height)
{
    setThreadingModel(SingleThreaded);
    osgViewer::GraphicsWindowEmbedded* gw = new osgViewer::GraphicsWindowEmbedded(x,y,width,height);
    getCamera()->setViewport(new osg::Viewport(0,0,width,height));
    getCamera()->setProjectionMatrixAsPerspective(30.0f,
static_cast<double>(width)/static_cast<double>(height), 1.0f, 10000.0f);
    getCamera()->setGraphicsContext(gw);
    return gw;
}

void Viewer::realize()
{
    //OSG_INFO<<"Viewer::realize()"<<std::endl;

    Contexts contexts;
    getContexts(contexts);

    if (contexts.empty())
    {
        OSG_INFO<<"Viewer::realize() - No valid contexts found, setting up view across all screens."<<std::endl;

        // no windows are already set up so set up a default view

        const char* ptr = 0;
        if ((ptr = getenv("OSG_CONFIG_FILE")) != 0)
        {
            readConfiguration(ptr);
        }
        else
        {
            int screenNum = -1;
            if ((ptr = getenv("OSG_SCREEN")) != 0)
            {
                if (strlen(ptr)!=0) screenNum = atoi(ptr);
                else screenNum = -1;
            }

            int x = -1, y = -1, width = -1, height = -1;
            if ((ptr = getenv("OSG_WINDOW")) != 0)
            {
                std::istringstream iss(ptr);
                iss >> x >> y >> width >> height;
            }

            if (width>0 && height>0)
            {
                if (screenNum>=0) setUpViewInWindow(x, y, width, height, screenNum);
                else setUpViewInWindow(x,y,width,height);
            }
            else if (screenNum>=0)
            {
                setUpViewOnSingleScreen(screenNum);
            }
            else
            {
                setUpViewAcrossAllScreens();
            }
        }

        getContexts(contexts);
    }

    if (contexts.empty())
    {
        OSG_NOTICE<<"Viewer::realize() - failed to set up any windows"<<std::endl;
        _done = true;
        return;
    }

    // get the display settings that will be active for this viewer
    osg::DisplaySettings* ds = _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance().get();
    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();

    // pass on the display settings to the WindowSystemInterface.
    if (wsi && wsi->getDisplaySettings()==0) wsi->setDisplaySettings(ds);

    unsigned int maxTexturePoolSize = ds->getMaxTexturePoolSize();
    unsigned int maxBufferObjectPoolSize = ds->getMaxBufferObjectPoolSize();

    for(Contexts::iterator citr = contexts.begin();
        citr != contexts.end();
        ++citr)
    {
        osg::GraphicsContext* gc = *citr;

        if (ds->getSyncSwapBuffers()) gc->setSwapCallback(new osg::SyncSwapBuffersCallback);

        // set the pool sizes, 0 the default will result in no GL object pools.
        gc->getState()->setMaxTexturePoolSize(maxTexturePoolSize);
        gc->getState()->setMaxBufferObjectPoolSize(maxBufferObjectPoolSize);

        gc->realize();

        if (_realizeOperation.valid() && gc->valid())
        {
            gc->makeCurrent();

            (*_realizeOperation)(gc);

            gc->releaseContext();
        }
    }

    // attach contexts to _incrementalCompileOperation if attached.
    if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts);

    bool grabFocus = true;
    if (grabFocus)
    {
        for(Contexts::iterator citr = contexts.begin();
            citr != contexts.end();
            ++citr)
        {
            osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
            if (gw)
            {
                gw->grabFocusIfPointerInWindow();
            }
        }
    }

    // initialize the global timer to be relative to the current time.
    osg::Timer::instance()->setStartTick();

    // pass on the start tick to all the associated event queues
    setStartTick(osg::Timer::instance()->getStartTick());

    // configure threading.
    setUpThreading();

    if (osg::DisplaySettings::instance()->getCompileContextsHint())
    {
        int numProcessors = OpenThreads::GetNumberOfProcessors();
        int processNum = 0;

        for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i)
        {
            osg::GraphicsContext* gc = osg::GraphicsContext::getOrCreateCompileContext(i);

            if (gc)
            {
                gc->createGraphicsThread();
                gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors);
                gc->getGraphicsThread()->startThread();

                ++processNum;
            }
        }
    }
#if 0
    osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
    if (getCamera()->getViewport())
    {
        osg::Viewport* viewport = getCamera()->getViewport();
        eventState->setInputRange( viewport->x(), viewport->y(), viewport->x() + viewport->width(),
viewport->y() + viewport->height());
    }
    else
    {
        eventState->setInputRange(-1.0, -1.0, 1.0, 1.0);
    }
#endif
}



void Viewer::advance(double simulationTime)
{
    if (_done) return;

    double previousReferenceTime = _frameStamp->getReferenceTime();
    unsigned int previousFrameNumber = _frameStamp->getFrameNumber();

    _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1);

    _frameStamp->setReferenceTime( osg::Timer::instance()->delta_s(_startTick,
osg::Timer::instance()->tick()) );

    if (simulationTime==USE_REFERENCE_TIME)
    {
        _frameStamp->setSimulationTime(_frameStamp->getReferenceTime());
    }
    else
    {
        _frameStamp->setSimulationTime(simulationTime);
    }

    if (getViewerStats() && getViewerStats()->collectStats("frame_rate"))
    {
        // update previous frame stats
        double deltaFrameTime = _frameStamp->getReferenceTime() - previousReferenceTime;
        getViewerStats()->setAttribute(previousFrameNumber, "Frame duration", deltaFrameTime);
        getViewerStats()->setAttribute(previousFrameNumber, "Frame rate", 1.0/deltaFrameTime);

        // update current frames stats
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Reference time", _frameStamp->getReferenceTime());
    }


    if (osg::Referenced::getDeleteHandler())
    {
        osg::Referenced::getDeleteHandler()->flush();
        osg::Referenced::getDeleteHandler()->setFrameNumber(_frameStamp->getFrameNumber());
    }

}

void Viewer::generateSlavePointerData(osg::Camera* camera, osgGA::GUIEventAdapter& event)
{
    osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
    if (!gw) return;

    // What type of Camera is it?
    // 1) Master Camera : do nothin extra
    // 2) Slave Camera, Relative RF, Same scene graph as master : transform coords into Master Camera and add to
PointerData list
    // 3) Slave Camera, Relative RF, Different scene graph from master : do nothing extra?
    // 4) Slave Camera, Absolute RF, Same scene graph as master : do nothing extra?
    // 5) Slave Camera, Absolute RF, Different scene graph : do nothing extra?
    // 6) Slave Camera, Absolute RF, Different scene graph but a distortion correction subgraph depending
upon RTT Camera (slave or master)
    //                              : project ray into RTT Camera's clip space, and RTT Camera's is Relative RF and sharing same scene graph as
master then transform coords.

    // if camera isn't the master it must be a slave and could need reprojecting.
    if (camera!=getCamera())
    {
        float x = event.getX();
        float y = event.getY();

        bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
        if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;

        double master_min_x = -1.0;
        double master_max_x = 1.0;
        double master_min_y = -1.0;
        double master_max_y = 1.0;

        osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix();
        if (getCamera()->getViewport())
        {
            osg::Viewport* viewport = getCamera()->getViewport();
            master_min_x = viewport->x();
            master_min_y = viewport->y();
            master_max_x = viewport->x()+viewport->width();
            master_max_y = viewport->y()+viewport->height();
            masterCameraVPW *= viewport->computeWindowMatrix();
        }

        // slave Camera if it shares the same View
        osg::View::Slave* slave = findSlaveForCamera(camera);
        if (slave)
        {
            if (camera->getReferenceFrame()==osg::Camera::RELATIVE_RF && slave->_useMastersSceneData)
            {
                osg::Viewport* viewport = camera->getViewport();
                osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
                if (viewport)
                {
                    localCameraVPW *= viewport->computeWindowMatrix();
                }

                osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW );
                osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;
                event.addPointerData(new osgGA::PointerData(getCamera(), new_coord.x(), master_min_x, master_max_x,
                                                                         new_coord.y(), master_min_y, master_max_y));
            }
            else if (!slave->_useMastersSceneData)
            {
                // Are their any RTT Camera's that this Camera depends upon for textures?

                osg::ref_ptr<osgUtil::RayIntersector> ray = new
osgUtil::RayIntersector(osgUtil::Intersector::WINDOW, x,y);
                osgUtil::IntersectionVisitor iv(ray.get());
                camera->accept(iv);
                if (ray->containsIntersections())
                {
                    osg::Vec3 tc;
                    osg::Texture* texture = ray->getFirstIntersection().getTextureLookUp(tc);
                    if (texture)
                    {
                        // look up Texture in RTT Camera's.
                        for(unsigned int i=0; i<getNumSlaves();++i)
                        {
                            osg::Camera* slave_camera = getSlave(i)._camera.get();
                            if (slave_camera)
                            {
                                osg::Camera::BufferAttachmentMap::const_iterator ba_itr = slave_camera->getBufferAttachmentMap().find(osg::Camera::COLOR_BUFFER);
                                if (ba_itr != slave_camera->getBufferAttachmentMap().end())
                                {
                                    if (ba_itr->second._texture == texture)
                                    {
                                        osg::TextureRectangle* tr = dynamic_cast<osg::TextureRectangle*>(ba_itr->second._texture.get());
                                        osg::TextureCubeMap* tcm = dynamic_cast<osg::TextureCubeMap*>(ba_itr->second._texture.get());
                                        if (tr)
                                        {
                                            event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, static_cast<float>(tr->getTextureWidth()),
                                                                                                      tc.y(), 0.0f, static_cast<float>(tr->getTextureHeight())));
                                        }
                                        else if (tcm)
                                        {
                                            OSG_INFO<<"  Slave has matched texture cubemap"<<ba_itr->second._texture.get()<<", "<<ba_itr->second._face<<std::endl;
                                        }
                                        else
                                        {
                                            event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, 1.0f,
                                                                                                      tc.y(), 0.0f, 1.0f));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}


void Viewer::generatePointerData(osgGA::GUIEventAdapter& event)
{
    osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
    if (!gw) return;

    float x = event.getX();
    float y = event.getY();

    bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
    if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;

    event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width,
                                                    y, 0, gw->getTraits()->height));

    event.setMouseYOrientationAndUpdateCoords(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);

    typedef std::vector<osg::Camera*> CameraVector;
    CameraVector activeCameras;

    osgViewer::View* this_view = dynamic_cast<osgViewer::View*>(this);
    osg::GraphicsContext::Cameras& cameras = gw->getCameras();
    for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
        citr != cameras.end();
        ++citr)
    {
        osg::Camera* camera = *citr;
        if (camera->getView()==this_view &&
            camera->getAllowEventFocus() &&
            camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
        {
            osg::Viewport* viewport = camera ? camera->getViewport() : 0;
            if (viewport &&
                x >= viewport->x() && y >= viewport->y() &&
                x <= (viewport->x()+viewport->width()) && y <= (viewport->y()+viewport->height()) )
            {
                activeCameras.push_back(camera);
            }
        }
    }

    std::sort(activeCameras.begin(), activeCameras.end(), osg::CameraRenderOrderSortOp());

    osg::Camera* camera = activeCameras.empty() ? 0 : activeCameras.back();

    if (camera)
    {
        osg::Viewport* viewport = camera ? camera->getViewport() : 0;

        event.addPointerData(new osgGA::PointerData(camera,
(x-viewport-≥x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,
                                                            (y-viewport-≥y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));

        // if camera isn't the master it must be a slave and could need reprojecting.
        if (camera!=getCamera())
        {
            generateSlavePointerData(camera, event);
        }
    }
}

void Viewer::reprojectPointerData(osgGA::GUIEventAdapter& source_event,
osgGA::GUIEventAdapter& dest_event)
{
    osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(dest_event.getGraphicsContext());
    if (!gw) return;

    float x = dest_event.getX();
    float y = dest_event.getY();

    bool invert_y = dest_event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
    if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;

    dest_event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width,
                                                         y, 0, gw->getTraits()->height));

    dest_event.setMouseYOrientationAndUpdateCoords(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);

    osg::Object* object = (source_event.getNumPointerData()>=2) ?
source_event.getPointerData(1)->object.get() : 0;
    osg::Camera* camera = object ? object->asCamera() : 0;
    osg::Viewport* viewport = camera ? camera->getViewport() : 0;

    if (!viewport) return;

    dest_event.addPointerData(new osgGA::PointerData(camera,
(x-viewport-≥x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,
                                                             (y-viewport-≥y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));

    // if camera isn't the master it must be a slave and could need reprojecting.
    if (camera!=getCamera())
    {
        generateSlavePointerData(camera, dest_event);
    }
}

void Viewer::eventTraversal()
{
    if (_done) return;

    double cutOffTime = _frameStamp->getReferenceTime();

    double beginEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());

    // OSG_NOTICE<<"Viewer::frameEventTraversal()."<<std::endl;

    // need to copy events from the GraphicsWindow's into local EventQueue;
    osgGA::EventQueue::Events events;

    Contexts contexts;
    getContexts(contexts);

    // set done if there are no windows
    checkWindowStatus(contexts);
    if (_done) return;

    osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();

    // get events from user Devices attached to Viewer.
    for(Devices::iterator eitr = _eventSources.begin();
        eitr != _eventSources.end();
        ++eitr)
    {
        osgGA::Device* es = eitr->get();
        if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS)
            es->checkEvents();

        // open question, will we need to reproject mouse coordinates into current view's coordinate frame as is
down for GraphicsWindow provided events?
        // for now assume now and just get the events directly without any reprojection.
        es->getEventQueue()->takeEvents(events, cutOffTime);
    }

    // get events from all windows attached to Viewer.
    for(Contexts::iterator citr = contexts.begin();
        citr != contexts.end();
        ++citr)
    {
        osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
        if (gw)
        {
            gw->checkEvents();

            osgGA::EventQueue::Events gw_events;
            gw->getEventQueue()->takeEvents(gw_events, cutOffTime);

            osgGA::EventQueue::Events::iterator itr;
            for(itr = gw_events.begin();
                itr != gw_events.end();
                ++itr)
            {
                osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
                if (!event) continue;

                event->setGraphicsContext(gw);

                switch(event->getEventType())
                {
                    case(osgGA::GUIEventAdapter::PUSH):
                    case(osgGA::GUIEventAdapter::RELEASE):
                    case(osgGA::GUIEventAdapter::DOUBLECLICK):
                    case(osgGA::GUIEventAdapter::MOVE):
                    case(osgGA::GUIEventAdapter::DRAG):
                    {
                        if (event->getEventType()!=osgGA::GUIEventAdapter::DRAG ||
                            eventState->getGraphicsContext()!=event->getGraphicsContext() ||
                            eventState->getNumPointerData()<2)
                        {
                            generatePointerData(*event);
                        }
                        else
                        {
                            reprojectPointerData(*eventState, *event);
                        }


                        eventState->copyPointerDataFrom(*event);

                        break;
                    }
                    default:
                        event->copyPointerDataFrom(*eventState);
                        break;
                }

                events.push_back(event);
            }

            for(itr = gw_events.begin();
                itr != gw_events.end();
                ++itr)
            {
                osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
                if (!event) continue;
                switch(event->getEventType())
                {
                    case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
                    {
                        bool wasThreading = areThreadsRunning();
                        if (wasThreading) stopThreading();

                        gw->close();
                        _currentContext = NULL;

                        if (wasThreading) startThreading();

                        break;
                    }
                    default:
                        break;
                }
            }

        }
    }

    // create a frame event for the new frame.
    {
        osg::ref_ptr<osgGA::GUIEventAdapter> event = _eventQueue->frame(
getFrameStamp()->getReferenceTime() );

        if (!eventState || eventState->getNumPointerData()<2)
        {
            generatePointerData(*event);
        }
        else
        {
            reprojectPointerData(*eventState, *event);
        }
    }

    // OSG_NOTICE<<"mouseEventState Xmin = "<<eventState->getXmin()<<"
Ymin="<<eventState->getYmin()<<" xMax="<<eventState->getXmax()<<" Ymax="<<eventState->getYmax()<<std::endl;

    _eventQueue->takeEvents(events, cutOffTime);

    // OSG_NOTICE<<"Events "<<events.size()<<std::endl;

    if ((_keyEventSetsDone!=0) || _quitEventSetsDone)
    {
        for(osgGA::EventQueue::Events::iterator itr = events.begin();
            itr != events.end();
            ++itr)
        {
            osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
            if (!event) continue;

            // ignore event if it's already been handled.
            if (event->getHandled()) continue;

            switch(event->getEventType())
            {
                case(osgGA::GUIEventAdapter::KEYUP):
                    if (_keyEventSetsDone && event->getKey()==_keyEventSetsDone) _done = true;
                    break;

                case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
                    if (_quitEventSetsDone) _done = true;
                    break;

                default:
                    break;
            }
        }
    }

    if (_done) return;

    if (_eventVisitor.valid() && getSceneData())
    {
        _eventVisitor->setFrameStamp(getFrameStamp());
        _eventVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());

        for(osgGA::EventQueue::Events::iterator itr = events.begin();
            itr != events.end();
            ++itr)
        {
            osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
            if (!event) continue;

            _eventVisitor->reset();
            _eventVisitor->addEvent( event );

            getSceneData()->accept(*_eventVisitor);

            // Do EventTraversal for slaves with their own subgraph
            for(unsigned int i=0; i<getNumSlaves(); ++i)
            {
                osg::View::Slave& slave = getSlave(i);
                osg::Camera* camera = slave._camera.get();
                if(camera && !slave._useMastersSceneData)
                {
                    camera->accept(*_eventVisitor);
                }
            }


            // call any camera event callbacks, but only traverse that callback, don't traverse its subgraph
            // leave that to the scene update traversal.
            osg::NodeVisitor::TraversalMode tm = _eventVisitor->getTraversalMode();
            _eventVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);

            if (_camera.valid() && _camera->getEventCallback()) _camera->accept(*_eventVisitor);

            for(unsigned int i=0; i<getNumSlaves(); ++i)
            {
                osg::View::Slave& slave = getSlave(i);
                osg::Camera* camera = slave._camera.get();
                if (camera && slave._useMastersSceneData && camera->getEventCallback())
                {
                    camera->accept(*_eventVisitor);
                }
            }

            _eventVisitor->setTraversalMode(tm);

        }
    }


    for(osgGA::EventQueue::Events::iterator itr = events.begin();
        itr != events.end();
        ++itr)
    {
        osgGA::Event* event = itr->get();
        for(EventHandlers::iterator hitr = _eventHandlers.begin();
            hitr != _eventHandlers.end();
            ++hitr)
        {
            (*hitr)->handle( event, 0, _eventVisitor.get());
        }

    }

    for(osgGA::EventQueue::Events::iterator itr = events.begin();
        itr != events.end();
        ++itr)
    {
        osgGA::Event* event = itr->get();
        if (event && _cameraManipulator.valid())
        {
            _cameraManipulator->handle( event, 0, _eventVisitor.get());
        }
    }

    if (getViewerStats() && getViewerStats()->collectStats("event"))
    {
        double endEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());

        // update current frames stats
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal begin time", beginEventTraversal);
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal end time", endEventTraversal);
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal time taken", endEventTraversal-beginEventTraversal);
    }

}

void Viewer::updateTraversal()
{
    if (_done) return;

    double beginUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());

    _updateVisitor->reset();
    _updateVisitor->setFrameStamp(getFrameStamp());
    _updateVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());

    _scene->updateSceneGraph(*_updateVisitor);

    // if we have a shared state manager prune any unused entries
    if (osgDB::Registry::instance()->getSharedStateManager())
        osgDB::Registry::instance()->getSharedStateManager()->prune();

    // update the Registry object cache.
    osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExternalReferences(*getFrameStamp());
    osgDB::Registry::instance()->removeExpiredObjectsInCache(*getFrameStamp());


    if (_updateOperations.valid())
    {
        _updateOperations->runOperations(this);
    }

    if (_incrementalCompileOperation.valid())
    {
        // merge subgraphs that have been compiled by the incremental compiler operation.
        _incrementalCompileOperation->mergeCompiledSubgraphs(getFrameStamp());
    }

    {
        // Do UpdateTraversal for slaves with their own subgraph
        for(unsigned int i=0; i<getNumSlaves(); ++i)
        {
            osg::View::Slave& slave = getSlave(i);
            osg::Camera* camera = slave._camera.get();
            if(camera && !slave._useMastersSceneData)
            {
                camera->accept(*_updateVisitor);
            }
        }
    }

    {
        // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
        // leave that to the scene update traversal.
        osg::NodeVisitor::TraversalMode tm = _updateVisitor->getTraversalMode();
        _updateVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);

        if (_camera.valid() && _camera->getUpdateCallback()) _camera->accept(*_updateVisitor);

        for(unsigned int i=0; i<getNumSlaves(); ++i)
        {
            osg::View::Slave& slave = getSlave(i);
            osg::Camera* camera = slave._camera.get();
            if (camera && slave._useMastersSceneData && camera->getUpdateCallback())
            {
                camera->accept(*_updateVisitor);
            }
        }

        _updateVisitor->setTraversalMode(tm);
    }

    if (_cameraManipulator.valid())
    {
        setFusionDistance( getCameraManipulator()->getFusionDistanceMode(),
                            getCameraManipulator()->getFusionDistanceValue() );

        _cameraManipulator->updateCamera(*_camera);
    }

    updateSlaves();

    if (getViewerStats() && getViewerStats()->collectStats("update"))
    {
        double endUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());

        // update current frames stats
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal begin time", beginUpdateTraversal);
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal end time", endUpdateTraversal);
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal time taken", endUpdateTraversal-beginUpdateTraversal);
    }
}

void Viewer::getScenes(Scenes& scenes, bool /*onlyValid*/)
{
    scenes.clear();
    scenes.push_back(_scene.get());
}

void Viewer::getViews(Views& views, bool /*onlyValid*/)
{
    views.clear();
    views.push_back(this);
}

void Viewer::getAllThreads(Threads& threads, bool onlyActive)
{
    threads.clear();

    OperationThreads operationThreads;
    getOperationThreads(operationThreads);

    for(OperationThreads::iterator itr = operationThreads.begin();
        itr != operationThreads.end();
        ++itr)
    {
        threads.push_back(*itr);
    }


    if (_scene.valid())
    {
        osgDB::DatabasePager* dp = _scene->getDatabasePager();
        if (dp)
        {
            for(unsigned int i=0; i<dp->getNumDatabaseThreads(); ++i)
            {
                osgDB::DatabasePager::DatabaseThread* dt = dp->getDatabaseThread(i);
                if (!onlyActive || dt->isRunning())
                {
                    threads.push_back(dt);
                }
            }
        }
    }
}


void Viewer::getOperationThreads(OperationThreads& threads, bool onlyActive)
{
    threads.clear();

    Contexts contexts;
    getContexts(contexts);
    for(Contexts::iterator gcitr = contexts.begin();
        gcitr != contexts.end();
        ++gcitr)
    {
        osg::GraphicsContext* gc = *gcitr;
        if (gc->getGraphicsThread() &&
            (!onlyActive || gc->getGraphicsThread()->isRunning()) )
        {
            threads.push_back(gc->getGraphicsThread());
        }
    }

    Cameras cameras;
    getCameras(cameras);
    for(Cameras::iterator citr = cameras.begin();
        citr != cameras.end();
        ++citr)
    {
        osg::Camera* camera = *citr;
        if (camera->getCameraThread() &&
            (!onlyActive || camera->getCameraThread()->isRunning()) )
        {
            threads.push_back(camera->getCameraThread());
        }
    }

}

void Viewer::getContexts(Contexts& contexts, bool onlyValid)
{
    typedef std::set<osg::GraphicsContext*> ContextSet;
    ContextSet contextSet;

    contexts.clear();

    if (_camera.valid() &&
        _camera->getGraphicsContext() &&
        (_camera->getGraphicsContext()->valid() || !onlyValid))
    {
        contextSet.insert(_camera->getGraphicsContext());
        contexts.push_back(_camera->getGraphicsContext());
    }

    for(unsigned int i=0; i<getNumSlaves(); ++i)
    {
        Slave& slave = getSlave(i);
        osg::GraphicsContext* sgc = slave._camera.valid() ? slave._camera->getGraphicsContext() : 0;
        if (sgc && (sgc->valid() || !onlyValid))
        {
            if (contextSet.count(sgc)==0)
            {
                contextSet.insert(sgc);
                contexts.push_back(sgc);
            }
        }
    }
}

void Viewer::getCameras(Cameras& cameras, bool onlyActive)
{
    cameras.clear();

    if (_camera.valid() &&
        (!onlyActive || (_camera->getGraphicsContext() && _camera->getGraphicsContext()->valid())) ) cameras.push_back(_camera.get());

    for(Slaves::iterator itr = _slaves.begin();
        itr != _slaves.end();
        ++itr)
    {
        if (itr->_camera.valid() &&
            (!onlyActive || (itr->_camera->getGraphicsContext() &&
itr->_camera->getGraphicsContext()->valid())) ) cameras.push_back(itr->_camera.get());
    }
}


double Viewer::elapsedTime()
{
    return osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
}


void Viewer::getUsage(osg::ApplicationUsage& usage) const
{
    if (_cameraManipulator.valid())
    {
        _cameraManipulator->getUsage(usage);
    }

    for(EventHandlers::const_iterator hitr = _eventHandlers.begin();
        hitr != _eventHandlers.end();
        ++hitr)
    {
        (*hitr)->getUsage(usage);
    }
}

_______________________________________________
osg-submissions mailing list
osg-submissions@...
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
Daniel Schmid | 31 Mar 11:28 2016
Picon

decoratorStateGraph

Hi all

I have a gereral question about the use of  decoratorStateGraph concept in the shadow classes. In the VDSM
shadow classes we find:

Code:

    cv.pushStateSet( _shadowRecievingPlaceholderStateSet.get() );

    osg::ref_ptr<osgUtil::StateGraph> decoratorStateGraph = cv.getCurrentStateGraph();

    cullShadowReceivingScene(&cv);

    cv.popStateSet();

and later on a call to:

Code:

decoratorStateGraph>setStateSet(selectStateSetForRenderingShadow(*vdd));

What is the reason for doing this? I also figured that the selected stateset in vdd is always cleared and
rebuild per frame. I have the impression that this comes at a performance cost. Why not building the
stateset once and pushing it directly into the cv instead of the placeholder?

Cheers,
Daniel

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=66686#66686
Tony Vasile | 31 Mar 08:56 2016
Picon

Creating fixed size X11 window.

I have specified the geometry 

Code:

    osg::GraphicsContext::Traits *traits = new osg::GraphicsContext::Traits;
    traits->windowDecoration = false;
    traits->supportsResize = false;
    traits->sharedContext = NULL;
    traits->doubleBuffer = true;
    traits->red = 8;
    traits->blue = 8;
    traits->green = 8;
    traits->alpha = 8;
    traits->depth = 24;
    traits->stencil = 8;
    traits->stencil = 8;
    traits->x = 100;
    traits->y = 0;
    traits->width = 1024;
    traits->height = 1024;
     osg::GraphicsContext * gc = osg::GraphicsContext::createGraphicsContext(traits);

What I am expecting is a window that is positioned at (100, 0) with size (1024, 1024). What I am getting a
window that is size (1024, 996). Is there anyway to force that size to my desired size?

I am running on Centos 6 on 64 bit kernel.

------------------------
Tony V

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=66680#66680
Chris Kuliukas | 29 Mar 04:05 2016

Re: osgtessellationshaders.cpp

Just to save someone some time:

When integrating this code in with some other code I found that it would mess up everything else (textures
wouldn't allocate, etc, etc). Turns out this line:
s->setUseVertexAttributeAliasing(true);
was screwing up the fixed pipeline stuff, but that it actually isn't necessary, so I would leave that line out.

------------------------
http://www.hrwallingford.com/facilities/ship-simulation-centre (http://www.hrwallingford.com/facilities/ship-simulation-centre)

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=66645#66645
Jannik Heller | 23 Mar 16:48 2016
Picon
Gravatar

Dont change the cmake build postfixes

Hi,

On Linux, building the OSG with any build type other than "Release" or "" results in the OSG find script being
unable to find the libraries. You can reproduce this issue simply by building and installing OSG with
-DCMAKE_BUILD_TYPE=RelWithDebInfo, then try to build a client application with the same flag. The
libraries aren't found due to the "rd" postfix at the end.

This is fixed by removing the custom build postfixes that were set in the OSG cmake script. Using the cmake
default postfixes will ensure that it matches what the find script expects.

Lastly, the code to "# Set the build postfix extension according to what configuration is being built."
appears to have been completely redundant, according to my test cmake does that automatically.

Cheers,
Jannik

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=66612#66612

_______________________________________________
osg-submissions mailing list
osg-submissions@...
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
Alberto Luaces | 23 Mar 14:01 2016
Picon

Typo fixes

Hi,

those are a fair amount of typo fixes based on current trunk.

Regards,

Attachment (typos.tar.gz): application/gzip, 300 KiB

--

-- 
Alberto
_______________________________________________
osg-submissions mailing list
osg-submissions@...
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Gmane