From 8d5d5436002867dee3727ef37d5eaeeb8678148b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 4 Jan 2008 11:26:21 +0000 Subject: [PATCH] From Brede Johansen, support for contiuation records. --- src/osgPlugins/OpenFlight/ControlRecords.cpp | 12 +- src/osgPlugins/OpenFlight/Document.cpp | 13 +- src/osgPlugins/OpenFlight/Document.h | 3 +- src/osgPlugins/OpenFlight/GeometryRecords.cpp | 19 +- .../OpenFlight/LightPointRecords.cpp | 14 +- src/osgPlugins/OpenFlight/PrimaryRecords.cpp | 174 ++++++++---------- src/osgPlugins/OpenFlight/Record.cpp | 78 ++++---- src/osgPlugins/OpenFlight/Record.h | 13 +- src/osgPlugins/OpenFlight/RoadRecords.cpp | 9 +- 9 files changed, 168 insertions(+), 167 deletions(-) diff --git a/src/osgPlugins/OpenFlight/ControlRecords.cpp b/src/osgPlugins/OpenFlight/ControlRecords.cpp index cf710bd6f..31d07c95b 100644 --- a/src/osgPlugins/OpenFlight/ControlRecords.cpp +++ b/src/osgPlugins/OpenFlight/ControlRecords.cpp @@ -38,7 +38,7 @@ class PushLevel : public Record META_Record(PushLevel) - virtual void read(RecordInputStream& /*in*/, Document& document) + virtual void readRecord(RecordInputStream& /*in*/, Document& document) { document.pushLevel(); } @@ -63,6 +63,13 @@ class PopLevel : public Record virtual void read(RecordInputStream& /*in*/, Document& document) { + // Finally call dispose() for primary with push, pop level pair. + PrimaryRecord* primary = document.getTopOfLevelStack(); + if (primary) + { + primary->dispose(document); + } + document.popLevel(); } @@ -181,9 +188,6 @@ class PushAttribute : public Record virtual void read(RecordInputStream& in, Document& document) { readRecord(in,document); - // in().seekg(in.getEndOfRecord(), std::ios_base::beg); - // loop until PopAttribute - } protected: diff --git a/src/osgPlugins/OpenFlight/Document.cpp b/src/osgPlugins/OpenFlight/Document.cpp index 1a82d1675..6a650edaf 100644 --- a/src/osgPlugins/OpenFlight/Document.cpp +++ b/src/osgPlugins/OpenFlight/Document.cpp @@ -46,45 +46,37 @@ Document::Document() : { } - Document::~Document() { } - void Document::pushLevel() { _levelStack.push_back(_currentPrimaryRecord.get()); - _levelStack.back()->pushLevel(*this); _level++; } - void Document::popLevel() { - _levelStack.back()->popLevel(*this); _levelStack.pop_back(); if (!_levelStack.empty()) - _currentPrimaryRecord = _levelStack.back().get(); + _currentPrimaryRecord = _levelStack.back(); if (--_level<=0) _done = true; } - void Document::pushSubface() { _subfaceLevel++; } - void Document::popSubface() { _subfaceLevel--; } - void Document::pushExtension() { if (!_currentPrimaryRecord.valid()) @@ -96,7 +88,6 @@ void Document::pushExtension() _extensionStack.push_back(_currentPrimaryRecord.get()); } - void Document::popExtension() { _currentPrimaryRecord=_extensionStack.back().get(); @@ -109,7 +100,6 @@ void Document::popExtension() _extensionStack.pop_back(); } - osg::Node* Document::getInstanceDefinition(int no) { InstanceDefinitionMap::iterator itr = _instanceDefinitionMap.find(no); @@ -119,7 +109,6 @@ osg::Node* Document::getInstanceDefinition(int no) return NULL; } - double flt::unitsToMeters(CoordUnits unit) { switch (unit) diff --git a/src/osgPlugins/OpenFlight/Document.h b/src/osgPlugins/OpenFlight/Document.h index fa92f2564..41a10f8f5 100644 --- a/src/osgPlugins/OpenFlight/Document.h +++ b/src/osgPlugins/OpenFlight/Document.h @@ -96,7 +96,7 @@ class Document const osgDB::ReaderWriter::Options* getOptions() const { return _options.get(); } // Current primar record - void setCurrentPrimaryRecord(PrimaryRecord* record) {_currentPrimaryRecord=record; } + void setCurrentPrimaryRecord(PrimaryRecord* record) { _currentPrimaryRecord=record; } PrimaryRecord* getCurrentPrimaryRecord() { return _currentPrimaryRecord.get(); } const PrimaryRecord* getCurrentPrimaryRecord() const { return _currentPrimaryRecord.get(); } @@ -113,7 +113,6 @@ class Document void pushExtension(); void popExtension(); - void setHeaderNode(osg::Node* node) { _osgHeader = node; } osg::Node* getHeaderNode() { return _osgHeader.get(); } diff --git a/src/osgPlugins/OpenFlight/GeometryRecords.cpp b/src/osgPlugins/OpenFlight/GeometryRecords.cpp index db3c5b102..b63f7c60c 100644 --- a/src/osgPlugins/OpenFlight/GeometryRecords.cpp +++ b/src/osgPlugins/OpenFlight/GeometryRecords.cpp @@ -72,7 +72,6 @@ public: META_setID(_geode) META_setComment(_geode) - META_setMatrix(_geode) META_setMultitexture(_geode) // draw mode @@ -434,10 +433,17 @@ protected: return osg::PrimitiveSet::POLYGON; } - virtual void popLevel(Document& document) + 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(_geode->getDrawable(i)); @@ -728,7 +734,6 @@ public: META_setID(_geode) META_setComment(_geode) - META_setMatrix(_geode) META_setMultitexture(_geode) // draw mode @@ -964,10 +969,16 @@ protected: _parent->addChild(*_geode); } - virtual void popLevel(Document& document) + virtual void dispose(Document& document) { if (_geode.valid()) { + // Insert transform(s) + if (_matrix.valid()) + { + insertMatrixTransform(*_geode,*_matrix,_numberOfReplications); + } + osg::StateSet* stateset = _geode->getOrCreateStateSet(); // Translucent image? diff --git a/src/osgPlugins/OpenFlight/LightPointRecords.cpp b/src/osgPlugins/OpenFlight/LightPointRecords.cpp index 0bb090486..110bf4b06 100644 --- a/src/osgPlugins/OpenFlight/LightPointRecords.cpp +++ b/src/osgPlugins/OpenFlight/LightPointRecords.cpp @@ -113,7 +113,7 @@ public: META_setID(_lpn) META_setComment(_lpn) - META_setMatrix(_lpn) + META_dispose(_lpn) // Add lightpoint, add two if bidirectional. virtual void addVertex(Vertex& vertex) @@ -263,7 +263,7 @@ public: META_setID(_lpn) META_setComment(_lpn) - META_setMatrix(_lpn) + META_dispose(_lpn) // Add lightpoint, add two if bidirectional. virtual void addVertex(Vertex& vertex) @@ -481,8 +481,16 @@ protected: _parent->addChild(*((osg::Group*)_switch.get())); } - virtual void popLevel(Document& document) + virtual void dispose(Document& document) { + if (!_switch.valid()) return; + + // Insert transform(s) + if (_matrix.valid()) + { + insertMatrixTransform(*_switch,*_matrix,_numberOfReplications); + } + // Set default sets: 0 for all off, 1 for all on _switch->setAllChildrenOff( 0 ); _switch->setAllChildrenOn( 1 ); diff --git a/src/osgPlugins/OpenFlight/PrimaryRecords.cpp b/src/osgPlugins/OpenFlight/PrimaryRecords.cpp index f8c7621c0..aaab5808d 100644 --- a/src/osgPlugins/OpenFlight/PrimaryRecords.cpp +++ b/src/osgPlugins/OpenFlight/PrimaryRecords.cpp @@ -54,7 +54,6 @@ public: META_setID(_header) META_setComment(_header) -// META_setMatrix(_header) META_setMultitexture(_header) META_addChild(_header) @@ -132,7 +131,7 @@ protected: document.setHeaderNode(_header.get()); } - virtual void popLevel(Document& document) + virtual void dispose(Document& document) { if (_header.valid()) { @@ -186,7 +185,6 @@ public: META_setID(_group) META_setComment(_group) - META_setMatrix(_group) META_setMultitexture(_group) META_addChild(_group) @@ -236,8 +234,16 @@ protected: _parent->addChild(*_group); } - virtual void popLevel(Document& document) + virtual void dispose(Document& document) { + if (!_group.valid()) return; + + // Insert transform(s) + if (_matrix.valid()) + { + insertMatrixTransform(*_group,*_matrix,_numberOfReplications); + } + // Children are added! osg::Sequence* sequence = dynamic_cast(_group.get()); if (sequence && sequence->getNumChildren() > 0) @@ -318,14 +324,13 @@ public: META_setID(_dof) META_setComment(_dof) - META_setMatrix(_dof) META_setMultitexture(_dof) META_addChild(_dof) + META_dispose(_dof) protected: virtual ~DegreeOfFreedom() {} - virtual void readRecord(RecordInputStream& in, Document& document) { std::string id = in.readString(8); @@ -453,14 +458,13 @@ public: META_setID(_lod) META_setComment(_lod) - META_setMatrix(_lod) META_setMultitexture(_lod) META_addChild(_impChild0) + META_dispose(_lod) protected: virtual ~LevelOfDetail() {} - virtual void readRecord(RecordInputStream& in, Document& document) { std::string id = in.readString(8); @@ -509,14 +513,13 @@ public: META_setID(_lod) META_setComment(_lod) - META_setMatrix(_lod) META_setMultitexture(_lod) META_addChild(_impChild0) + META_dispose(_lod) protected: virtual ~OldLevelOfDetail() {} - virtual void readRecord(RecordInputStream& in, Document& document) { std::string id = in.readString(8); @@ -570,8 +573,8 @@ public: META_setID(_multiSwitch) META_setComment(_multiSwitch) - META_setMatrix(_multiSwitch) META_setMultitexture(_multiSwitch) + META_dispose(_multiSwitch) virtual void addChild(osg::Node& child) { @@ -593,7 +596,6 @@ public: protected: virtual ~Switch() {} - virtual void readRecord(RecordInputStream& in, Document& /*document*/) { std::string id = in.readString(8); @@ -652,14 +654,13 @@ public: META_setID(_external) META_setComment(_external) - META_setMatrix(_external) META_setMultitexture(_external) META_addChild(_external) + META_dispose(_external) protected: virtual ~ExternalReference() {} - virtual void readRecord(RecordInputStream& in, Document& document) { std::string strFile = in.readString(200); @@ -717,11 +718,12 @@ RegisterRecordProxy g_ExternalReference(EXTERNAL_REFERENCE_OP */ class InstanceDefinition : public PrimaryRecord { + int _number; osg::ref_ptr _instanceDefinition; public: - InstanceDefinition() {} + InstanceDefinition():_number(0) {} META_Record(InstanceDefinition) @@ -730,28 +732,32 @@ public: META_setMultitexture(_instanceDefinition) META_addChild(_instanceDefinition) - virtual void setMatrix(osg::Matrix& matrix) - { - osg::ref_ptr transform = new osg::MatrixTransform(matrix); - transform->setDataVariance(osg::Object::STATIC); - transform->addChild(_instanceDefinition.get()); - _instanceDefinition = transform.get(); - } - protected: virtual ~InstanceDefinition() {} - virtual void readRecord(RecordInputStream& in, Document& document) { in.forward(2); - uint16 number = in.readUInt16(); + _number = (int)in.readUInt16(); _instanceDefinition = new osg::Group; + } + + virtual void dispose(Document& document) + { + // Insert transform(s) + if (_matrix.valid()) + { + osg::ref_ptr transform = new osg::MatrixTransform(*_matrix); + transform->setDataVariance(osg::Object::STATIC); + transform->addChild(_instanceDefinition.get()); + _instanceDefinition = transform.get(); + } // Add to instance definition table. - document.setInstanceDefinition(number,_instanceDefinition.get()); + document.setInstanceDefinition(_number,_instanceDefinition.get()); } + }; RegisterRecordProxy g_InstanceDefinition(INSTANCE_DEFINITION_OP); @@ -771,7 +777,6 @@ public: protected: virtual ~InstanceReference() {} - virtual void readRecord(RecordInputStream& in, Document& document) { in.forward(2); @@ -781,7 +786,7 @@ protected: osg::Node* instance = document.getInstanceDefinition(number); // Add this implementation to parent implementation. - if (_parent.valid()) + if (_parent.valid() && instance) _parent->addChild(*instance); } }; @@ -803,14 +808,13 @@ public: META_setID(_extension) META_setComment(_extension) - META_setMatrix(_extension) META_setMultitexture(_extension) META_addChild(_extension) + META_dispose(_extension) protected: virtual ~Extension() {} - virtual void readRecord(RecordInputStream& in, Document& /*document*/) { std::string id = in.readString(8); @@ -850,85 +854,68 @@ public: META_setID(_object) META_setComment(_object) - - virtual void setMatrix(osg::Matrix& matrix) - { - if (_object.valid()) - insertMatrixTransform(*_object,matrix); - else - { - _object = new osg::MatrixTransform(matrix); - _object->setDataVariance(osg::Object::STATIC); - - if (_parent.valid()) - _parent->addChild(*_object); - } - } - - virtual void addChild(osg::Node& child) - { - // If object excists it means it is preserved. - if (_object.valid()) - _object->addChild(&child); - // If no object add child to parent. - else if (_parent.valid()) - _parent->addChild(child); - } + META_addChild(_object) protected: - virtual ~Object() {} - virtual void readRecord(RecordInputStream& in, Document& document) { - // Is it safe to remove the object? - if (!document.getPreserveObject()) - { - // The following tests need a valid parent. - if (!_parent.valid()) - return; + std::string id = in.readString(8); + /*uint32 flags =*/ in.readUInt32(); + _object = new osg::Group; + _object->setName(id); + + // Postpone add-to-parent until we know a bit more. + } + + virtual void dispose(Document& document) + { + if (!_parent.valid() || !_object.valid()) return; + + // Is it safe to remove _object? + if (!document.getPreserveObject() && isSafeToRemoveObject() && !_matrix.valid()) + { + // Add children of _object to parent. + // _object will not be added to graph. + for (unsigned int i=0; i<_object->getNumChildren(); ++i) + { + _parent->addChild(*(_object->getChild(i))); + } + } + else + { + _parent->addChild(*_object); + } + + // Insert transform(s) + if (_matrix.valid()) + { + insertMatrixTransform(*_object,*_matrix,_numberOfReplications); + } + } + + bool isSafeToRemoveObject() const + { + // The following tests need a valid parent. + if (_parent.valid()) + { // LODs adds an empty child group so it is safe to remove this object record. if (typeid(*_parent)==typeid(flt::LevelOfDetail)) - return; + return true; if (typeid(*_parent)==typeid(flt::OldLevelOfDetail)) - return; + return true; // If parent is a Group record we have to check for animation. Group* parentGroup = dynamic_cast(_parent.get()); if (parentGroup && !parentGroup->hasAnimation()) - return; + return true; } - std::string id = in.readString(8); - _object = new osg::Group; - _object->setName(id); - - -#if 1 - /*uint32 flags =*/ in.readUInt32(); -#else - - // The Object "Flat Shaded" checkbox in Creator is used by the "Calculate Shading" operation, - // it is not a flat shaded state attribute. - - uint32 flags = in.readUInt32(); - // Flat shaded? - if (flags & FLAT_SHADED) - { - static osg::ref_ptr shademodel; - if (!shademodel.valid()) - { - shademodel = new osg::ShadeModel; - shademodel->setMode(osg::ShadeModel::FLAT); - } - _object->getOrCreateStateSet()->setAttribute(shademodel.get()); - } -#endif - if (_parent.valid()) - _parent->addChild(*_object); + return false; } + }; RegisterRecordProxy g_Object(OBJECT_OP); @@ -952,12 +939,11 @@ public: META_setID(_lightSource) META_setComment(_lightSource) - META_setMatrix(_lightSource) + META_dispose(_lightSource) protected: virtual ~LightSource() {} - virtual void readRecord(RecordInputStream& in, Document& document) { std::string id = in.readString(8); diff --git a/src/osgPlugins/OpenFlight/Record.cpp b/src/osgPlugins/OpenFlight/Record.cpp index 1b734ce2e..354a844b0 100644 --- a/src/osgPlugins/OpenFlight/Record.cpp +++ b/src/osgPlugins/OpenFlight/Record.cpp @@ -30,51 +30,39 @@ Record::Record() { } -Record::~Record() -{ -} - -void Record::setParent(PrimaryRecord* parent) -{ - _parent = parent; -} - -//PrimaryRecord& Record::parent() -//{ -// if (!_parent) -// throw std::runtime_error("Record::parent(): invalid pointer to parent exception."); -// -// return *_parent; -//} - - void Record::read(RecordInputStream& in, Document& document) { - setParent(document.getCurrentPrimaryRecord()); + _parent = document.getCurrentPrimaryRecord(); // Read record body. readRecord(in,document); } - void Record::readRecord(RecordInputStream& /*in*/, Document& /*document*/) { } - PrimaryRecord::PrimaryRecord() : _numberOfReplications(0) { } - void PrimaryRecord::read(RecordInputStream& in, Document& document) { - setParent(document.getTopOfLevelStack()); + PrimaryRecord* parentPrimary = document.getTopOfLevelStack(); + PrimaryRecord* currentPrimary = document.getCurrentPrimaryRecord(); - // Update primary record. + // Finally call dispose() for primary without push, pop level pair. + if (currentPrimary && currentPrimary!=parentPrimary) + { + currentPrimary->dispose(document); + } + + // Update current primary record. document.setCurrentPrimaryRecord(this); + _parent = parentPrimary; + // Read record body. readRecord(in,document); } @@ -82,27 +70,47 @@ void PrimaryRecord::read(RecordInputStream& in, Document& document) /////////////////////////////////////////////////////////////////////////////////// // Helper methods -// Insert matrix-tranform above node. -// Return transform. -osg::ref_ptr flt::insertMatrixTransform(osg::Node& node, const osg::Matrix& matrix) +// Insert matrix-tranform(s) +// +// node: node to apply transform +// matrix: transformation matrix +// numberOfReplications: zero for regular transform, number of copies if replication is used. +void flt::insertMatrixTransform(osg::Node& node, const osg::Matrix& matrix, int numberOfReplications) { osg::ref_ptr ref = &node; - osg::ref_ptr transform = new osg::MatrixTransform(matrix); - transform->setDataVariance(osg::Object::STATIC); - - // Replace parent osg::Node::ParentList parents = node.getParents(); + + // Disconnect node from parents. for (osg::Node::ParentList::iterator itr=parents.begin(); itr!=parents.end(); ++itr) { - (*itr)->replaceChild(&node,transform.get()); + (*itr)->removeChild(&node); } - // Make primary a child of matrix transform. - transform->addChild(&node); + // Start without transformation if replication. + osg::Matrix accumulatedMatrix = (numberOfReplications > 0)? osg::Matrix::identity() : matrix; - return transform; + for (int n=0; n<=numberOfReplications; n++) + { + // Accumulate transformation for each replication. + osg::ref_ptr transform = new osg::MatrixTransform(accumulatedMatrix); + transform->setDataVariance(osg::Object::STATIC); + + // Add transform to parents + for (osg::Node::ParentList::iterator itr=parents.begin(); + itr!=parents.end(); + ++itr) + { + (*itr)->addChild(transform.get()); + } + + // Make primary a child of matrix transform. + transform->addChild(&node); + + // Accumulate transform if multiple replications. + accumulatedMatrix *= matrix; + } } diff --git a/src/osgPlugins/OpenFlight/Record.h b/src/osgPlugins/OpenFlight/Record.h index 5cfb14cb9..4d525a600 100644 --- a/src/osgPlugins/OpenFlight/Record.h +++ b/src/osgPlugins/OpenFlight/Record.h @@ -42,10 +42,9 @@ class Matrix; virtual bool isSameKindAs(const flt::Record* rec) const { return dynamic_cast(rec)!=NULL; } #define META_setID(imp) virtual void setID(const std::string& id) { if (imp.valid()) imp->setName(id); } #define META_setComment(imp) virtual void setComment(const std::string& id) { if (imp.valid()) imp->addDescription(id); } -#define META_setMatrix(imp) virtual void setMatrix(osg::Matrix& matrix) { if (imp.valid()) insertMatrixTransform(*imp,matrix); } #define META_setMultitexture(imp) virtual void setMultitexture(osg::StateSet& multitexture) { if (imp.valid()) imp->getOrCreateStateSet()->merge(multitexture); } #define META_addChild(imp) virtual void addChild(osg::Node& child) { if (imp.valid()) imp->addChild(&child); } - +#define META_dispose(imp) virtual void dispose(Document&) { if (imp.valid() && _matrix.valid()) insertMatrixTransform(*imp,*_matrix,_numberOfReplications); } // pure virtual base class class Record : public osg::Referenced @@ -62,7 +61,7 @@ public: protected: - virtual ~Record(); + virtual ~Record() {} virtual void readRecord(RecordInputStream& in, Document& document); @@ -77,13 +76,11 @@ public: PrimaryRecord(); virtual void read(RecordInputStream& in, Document& document); - virtual void pushLevel(Document& /*document*/) {} - virtual void popLevel(Document& /*document*/) {} + virtual void dispose(Document& /*document*/) {} // Ancillary operations virtual void setID(const std::string& /*id*/) {} virtual void setComment(const std::string& /*comment*/) {} - virtual void setMatrix(osg::Matrix& /*matrix*/) {} virtual void setMultitexture(osg::StateSet& /*multitexture*/) {} virtual void addChild(osg::Node& /*child*/) {} virtual void addVertex(Vertex& /*vertex*/) {} @@ -91,6 +88,7 @@ public: virtual void addMorphVertex(Vertex& /*vertex0*/, Vertex& /*vertex100*/) {} void setNumberOfReplications(int num) { _numberOfReplications = num; } + void setMatrix(const osg::Matrix& matrix) { _matrix = new osg::RefMatrix(matrix); } void setLocalVertexPool(VertexList* pool) { _localVertexPool = pool; } VertexList* getLocalVertexPool() { return _localVertexPool.get(); } @@ -100,6 +98,7 @@ protected: virtual ~PrimaryRecord() {} int _numberOfReplications; + osg::ref_ptr _matrix; osg::ref_ptr _localVertexPool; }; @@ -120,7 +119,7 @@ class DummyRecord : public Record }; -osg::ref_ptr insertMatrixTransform(osg::Node& node, const osg::Matrix& matrix); +void insertMatrixTransform(osg::Node& node, const osg::Matrix& matrix, int numberOfReplications); osg::Vec3Array* getOrCreateVertexArray(osg::Geometry& geometry); osg::Vec3Array* getOrCreateNormalArray(osg::Geometry& geometry); diff --git a/src/osgPlugins/OpenFlight/RoadRecords.cpp b/src/osgPlugins/OpenFlight/RoadRecords.cpp index 90077447e..d64cd8a54 100644 --- a/src/osgPlugins/OpenFlight/RoadRecords.cpp +++ b/src/osgPlugins/OpenFlight/RoadRecords.cpp @@ -40,14 +40,13 @@ class RoadSegment : public PrimaryRecord META_setID(_roadSegment) META_setComment(_roadSegment) - META_setMatrix(_roadSegment) META_setMultitexture(_roadSegment) META_addChild(_roadSegment) + META_dispose(_roadSegment) protected: virtual ~RoadSegment() {} - virtual void readRecord(RecordInputStream& in, Document& /*document*/) { _roadSegment = new osg::Group; @@ -78,14 +77,13 @@ class RoadConstruction : public PrimaryRecord META_setID(_roadConstruction) META_setComment(_roadConstruction) - META_setMatrix(_roadConstruction) META_setMultitexture(_roadConstruction) META_addChild(_roadConstruction) + META_dispose(_roadConstruction) protected: virtual ~RoadConstruction() {} - virtual void readRecord(RecordInputStream& in, Document& /*document*/) { _roadConstruction = new osg::Group; @@ -117,14 +115,13 @@ class RoadPath : public PrimaryRecord META_setID(_roadPath) META_setComment(_roadPath) - META_setMatrix(_roadPath) META_setMultitexture(_roadPath) META_addChild(_roadPath) + META_dispose(_roadPath) protected: virtual ~RoadPath() {} - virtual void readRecord(RecordInputStream& /*in*/, Document& /*document*/) { _roadPath = new osg::Group;