From c6c26d5d440ee2a1b9e3fd6da03bc202dfc55dee Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sat, 3 Apr 2010 16:21:34 +0000 Subject: [PATCH] Change Terrain so that it subclassed from CoordinateSystemNode. Implemented new update scheme of GeometryTechnique to avoid potential threading issues. Added Terrain support to .ive. --- include/osgTerrain/GeometryTechnique | 2 +- include/osgTerrain/Terrain | 3 +- include/osgTerrain/TerrainTechnique | 2 +- include/osgTerrain/TerrainTile | 3 +- src/osgPlugins/ive/CMakeLists.txt | 1 + src/osgPlugins/ive/DataInputStream.cpp | 5 ++ src/osgPlugins/ive/DataOutputStream.cpp | 12 +++- src/osgPlugins/ive/ReadWrite.h | 2 +- src/osgPlugins/ive/Terrain.cpp | 63 +++++++++++++++++++ src/osgPlugins/ive/Terrain.h | 33 ++++++++++ src/osgPlugins/ive/TerrainTile.cpp | 2 +- src/osgPlugins/ive/TerrainTile.h | 4 +- src/osgTerrain/GeometryTechnique.cpp | 39 ++++++------ src/osgTerrain/Terrain.cpp | 4 +- src/osgTerrain/TerrainTechnique.cpp | 11 ++-- src/osgTerrain/TerrainTile.cpp | 18 ++++-- .../deprecated-dotosg/osgTerrain/Terrain.cpp | 2 +- .../serializers/osgTerrain/Terrain.cpp | 2 +- 18 files changed, 165 insertions(+), 43 deletions(-) create mode 100644 src/osgPlugins/ive/Terrain.cpp create mode 100644 src/osgPlugins/ive/Terrain.h diff --git a/include/osgTerrain/GeometryTechnique b/include/osgTerrain/GeometryTechnique index c22cf5b6d..d455ec2f7 100644 --- a/include/osgTerrain/GeometryTechnique +++ b/include/osgTerrain/GeometryTechnique @@ -34,7 +34,7 @@ class OSGTERRAIN_EXPORT GeometryTechnique : public TerrainTechnique META_Object(osgTerrain, GeometryTechnique); - virtual void init(); + virtual void init(int dirtyMask, bool assumeMultiThreaded); virtual Locator* computeMasterLocator(); diff --git a/include/osgTerrain/Terrain b/include/osgTerrain/Terrain index ff3c91cd1..011e43a38 100644 --- a/include/osgTerrain/Terrain +++ b/include/osgTerrain/Terrain @@ -14,7 +14,6 @@ #ifndef OSGTerrain #define OSGTerrain 1 -#include #include #include @@ -23,7 +22,7 @@ namespace osgTerrain { /** Terrain provides a framework for loosely coupling height field data with height rendering algorithms. * This allows TerrainTechniques to be plugged in at runtime.*/ -class OSGTERRAIN_EXPORT Terrain : public osg::Group +class OSGTERRAIN_EXPORT Terrain : public osg::CoordinateSystemNode { public: diff --git a/include/osgTerrain/TerrainTechnique b/include/osgTerrain/TerrainTechnique index 2046a02fa..683e0876d 100644 --- a/include/osgTerrain/TerrainTechnique +++ b/include/osgTerrain/TerrainTechnique @@ -63,7 +63,7 @@ class OSGTERRAIN_EXPORT TerrainTechnique : public osg::Object, public osg::Obser TerrainTile* getTerrainTile() { return _terrainTile; } const TerrainTile* getTerrainTile() const { return _terrainTile; } - virtual void init(); + virtual void init(int dirtyMask, bool assumeMultiThreaded); virtual void update(osgUtil::UpdateVisitor* nv); diff --git a/include/osgTerrain/TerrainTile b/include/osgTerrain/TerrainTile index ab5e8ba87..973852bac 100644 --- a/include/osgTerrain/TerrainTile +++ b/include/osgTerrain/TerrainTile @@ -78,8 +78,7 @@ class OSGTERRAIN_EXPORT TerrainTile : public osg::Group virtual void traverse(osg::NodeVisitor& nv); /** Call init on any attached TerrainTechnique.*/ - void init(); - + void init(int dirtyMask, bool assumeMultiThreaded); /** Set the Terrain that this Terrain tile is a member of.*/ void setTerrain(Terrain* ts); diff --git a/src/osgPlugins/ive/CMakeLists.txt b/src/osgPlugins/ive/CMakeLists.txt index 1483c3cbc..c1658a4f0 100644 --- a/src/osgPlugins/ive/CMakeLists.txt +++ b/src/osgPlugins/ive/CMakeLists.txt @@ -101,6 +101,7 @@ SET(TARGET_SRC Stencil.cpp Switch.cpp SwitchLayer.cpp + Terrain.cpp TerrainTile.cpp TexEnvCombine.cpp TexEnv.cpp diff --git a/src/osgPlugins/ive/DataInputStream.cpp b/src/osgPlugins/ive/DataInputStream.cpp index d02a89e53..364b11917 100644 --- a/src/osgPlugins/ive/DataInputStream.cpp +++ b/src/osgPlugins/ive/DataInputStream.cpp @@ -112,6 +112,7 @@ #include "Text.h" +#include "Terrain.h" #include "TerrainTile.h" #include "Locator.h" #include "ImageLayer.h" @@ -1836,6 +1837,10 @@ osg::Node* DataInputStream::readNode() node = new osgTerrain::TerrainTile(); ((ive::TerrainTile*)(node.get()))->read(this); } + else if(nodeTypeID== IVETERRAIN){ + node = new osgTerrain::Terrain(); + ((ive::Terrain*)(node.get()))->read(this); + } else if(nodeTypeID== IVEVOLUME){ node = new osgVolume::Volume(); ((ive::Volume*)(node.get()))->read(this); diff --git a/src/osgPlugins/ive/DataOutputStream.cpp b/src/osgPlugins/ive/DataOutputStream.cpp index 65cfe2f3c..bf0588aa4 100644 --- a/src/osgPlugins/ive/DataOutputStream.cpp +++ b/src/osgPlugins/ive/DataOutputStream.cpp @@ -103,6 +103,7 @@ #include "Text.h" +#include "Terrain.h" #include "TerrainTile.h" #include "Locator.h" #include "ImageLayer.h" @@ -1333,9 +1334,6 @@ void DataOutputStream::writeNode(const osg::Node* node) else if(dynamic_cast(node)){ ((ive::Switch*)(node))->write(this); } - else if(dynamic_cast(node)){ - ((ive::CoordinateSystemNode*)(node))->write(this); - } else if(dynamic_cast(node)){ ((ive::MultiSwitch*)(node))->write(this); } @@ -1378,9 +1376,17 @@ void DataOutputStream::writeNode(const osg::Node* node) else if(dynamic_cast(node)){ ((ive::TerrainTile*)(node))->write(this); } + else if(dynamic_cast(node)){ + ((ive::Terrain*)(node))->write(this); + } else if(dynamic_cast(node)){ ((ive::Volume*)(node))->write(this); } + + else if(dynamic_cast(node)){ + ((ive::CoordinateSystemNode*)(node))->write(this); + } + else if(dynamic_cast(node)){ ((ive::VolumeTile*)(node))->write(this); } diff --git a/src/osgPlugins/ive/ReadWrite.h b/src/osgPlugins/ive/ReadWrite.h index 8c425a211..bda73ccda 100644 --- a/src/osgPlugins/ive/ReadWrite.h +++ b/src/osgPlugins/ive/ReadWrite.h @@ -138,7 +138,7 @@ namespace ive { #define IVEVALIDRANGE 0x0020000B #define IVENODATAVALUE 0x0020000C #define IVESWITCHLAYER 0x0020000D -#define IVETERRAIN 0x0020000A +#define IVETERRAIN 0x0020000E // osgVolume classes #define IVEVOLUMETILE 0x00300001 diff --git a/src/osgPlugins/ive/Terrain.cpp b/src/osgPlugins/ive/Terrain.cpp new file mode 100644 index 000000000..4b5ed7dac --- /dev/null +++ b/src/osgPlugins/ive/Terrain.cpp @@ -0,0 +1,63 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 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 "Exception.h" +#include "Terrain.h" +#include "TerrainTile.h" +#include "CoordinateSystemNode.h" + +#include + +using namespace ive; + +void Terrain::write(DataOutputStream* out) +{ + // Write Terrain's identification. + out->writeInt(IVETERRAIN); + + // If the osg class is inherited by any other class we should also write this to file. + osg::CoordinateSystemNode* csn = dynamic_cast(this); + if(csn) + ((ive::CoordinateSystemNode*)(csn))->write(out); + else + out_THROW_EXCEPTION("Terrain::write(): Could not cast this osgTerrain::Terrain to an osg::CoordinateSystemNode."); + + out->writeFloat(getSampleRatio()); + out->writeFloat(getVerticalScale()); + out->writeInt(getBlendingPolicy()); + + TerrainTile::writeTerrainTechnique(out, getTerrainTechniquePrototype()); +} + +void Terrain::read(DataInputStream* in) +{ + // Peek on Terrain's identification. + int id = in->peekInt(); + if (id != IVETERRAIN) in_THROW_EXCEPTION("TerrainTile::read(): Expected Terrain identification."); + + // Read Terrain's identification. + id = in->readInt(); + + osg::CoordinateSystemNode* csn = dynamic_cast(this); + if(csn) + ((ive::CoordinateSystemNode*)(csn))->read(in); + else + in_THROW_EXCEPTION("Terrain::read(): Could not cast this osgTerran::Terrain to an osg::CoordinateSystemNode."); + + setSampleRatio(in->readFloat()); + setVerticalScale(in->readFloat()); + setBlendingPolicy(static_cast(in->readInt())); + + setTerrainTechniquePrototype(TerrainTile::readTerrainTechnique(in)); +} + diff --git a/src/osgPlugins/ive/Terrain.h b/src/osgPlugins/ive/Terrain.h new file mode 100644 index 000000000..51547f1a5 --- /dev/null +++ b/src/osgPlugins/ive/Terrain.h @@ -0,0 +1,33 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 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. +*/ + +#ifndef IVE_TERRAIN +#define IVE_TERRAIN 1 + +#include + +#include "ReadWrite.h" + +namespace ive +{ + +class Terrain : public osgTerrain::Terrain, public ReadWrite +{ +public: + void write(DataOutputStream* out); + void read(DataInputStream* in); +}; + +} + +#endif diff --git a/src/osgPlugins/ive/TerrainTile.cpp b/src/osgPlugins/ive/TerrainTile.cpp index 96b5aee29..c3ef17b22 100644 --- a/src/osgPlugins/ive/TerrainTile.cpp +++ b/src/osgPlugins/ive/TerrainTile.cpp @@ -153,7 +153,7 @@ osgTerrain::TerrainTechnique* TerrainTile::readTerrainTechnique(DataInputStream* { bool hasTechnique = in->readBool(); if (!hasTechnique) return 0; - + int id = in->readInt(); if (id==IVEGEOMETRYTECHNIQUE) { diff --git a/src/osgPlugins/ive/TerrainTile.h b/src/osgPlugins/ive/TerrainTile.h index b97d7b69f..1b7458aba 100644 --- a/src/osgPlugins/ive/TerrainTile.h +++ b/src/osgPlugins/ive/TerrainTile.h @@ -27,8 +27,8 @@ public: void write(DataOutputStream* out); void read(DataInputStream* in); - void writeTerrainTechnique(DataOutputStream* out, osgTerrain::TerrainTechnique* technique); - osgTerrain::TerrainTechnique* readTerrainTechnique(DataInputStream* out); + static void writeTerrainTechnique(DataOutputStream* out, osgTerrain::TerrainTechnique* technique); + static osgTerrain::TerrainTechnique* readTerrainTechnique(DataInputStream* out); }; diff --git a/src/osgTerrain/GeometryTechnique.cpp b/src/osgTerrain/GeometryTechnique.cpp index 238f2811c..a2c695367 100644 --- a/src/osgTerrain/GeometryTechnique.cpp +++ b/src/osgTerrain/GeometryTechnique.cpp @@ -95,7 +95,7 @@ void GeometryTechnique::setFilterMatrixAs(FilterType filterType) }; } -void GeometryTechnique::init() +void GeometryTechnique::init(int dirtyMask, bool assumeMultiThreaded) { OSG_INFO<<"Doing GeometryTechnique::init()"< tile = _terrainTile; - if (_terrainTile->getDirtyMask()==0) return; + if (dirtyMask==0) return; osg::ref_ptr buffer = new BufferData; @@ -114,7 +114,7 @@ void GeometryTechnique::init() osg::Vec3d centerModel = computeCenterModel(*buffer, masterLocator); - if ((_terrainTile->getDirtyMask() & TerrainTile::IMAGERY_DIRTY)==0) + if ((dirtyMask & TerrainTile::IMAGERY_DIRTY)==0) { generateGeometry(*buffer, masterLocator, centerModel); @@ -141,12 +141,14 @@ void GeometryTechnique::init() if (buffer->_transform.valid()) buffer->_transform->setThreadSafeRefUnref(true); - if (!_currentBufferData) + if (!_currentBufferData || !assumeMultiThreaded) { + // no currentBufferData so we must be the first init to be applied _currentBufferData = buffer; } else { + // there is already an active _currentBufferData so we'll request that this gets swapped on next frame. _newBufferData = buffer; if (_terrainTile->getTerrain()) _terrainTile->getTerrain()->updateTerrainTileOnNextFrame(_terrainTile); } @@ -259,7 +261,7 @@ class VertexNormalGenerator { if (r<0 || r>=_numRows || c<0 || c>=_numColumns) { - i = -(1+_boundaryVertices->size()); + i = -(1+static_cast(_boundaryVertices->size())); _boundaryVertices->push_back(v); // OSG_NOTICE<<"setVertex("<getTerrainTechnique()->containsNeighbour(_terrainTile))) { - left_tile->setDirtyMask(left_tile->getDirtyMask() | TerrainTile::LEFT_EDGE_DIRTY); - if (updateNeighboursImmediately) - { - left_tile->init(); - } + int dirtyMask = left_tile->getDirtyMask() | TerrainTile::LEFT_EDGE_DIRTY; + if (updateNeighboursImmediately) left_tile->init(dirtyMask, true); + else left_tile->setDirtyMask(dirtyMask); } } if (right_tile.valid()) { if (!(right_tile->getTerrainTechnique()->containsNeighbour(_terrainTile))) { - right_tile->setDirtyMask(right_tile->getDirtyMask() | TerrainTile::RIGHT_EDGE_DIRTY); - if (updateNeighboursImmediately) right_tile->init(); + int dirtyMask = right_tile->getDirtyMask() | TerrainTile::RIGHT_EDGE_DIRTY; + if (updateNeighboursImmediately) right_tile->init(dirtyMask, true); + else right_tile->setDirtyMask(dirtyMask); } } if (top_tile.valid()) { if (!(top_tile->getTerrainTechnique()->containsNeighbour(_terrainTile))) { - top_tile->setDirtyMask(top_tile->getDirtyMask() | TerrainTile::TOP_EDGE_DIRTY); - if (updateNeighboursImmediately) top_tile->init(); + int dirtyMask = top_tile->getDirtyMask() | TerrainTile::TOP_EDGE_DIRTY; + if (updateNeighboursImmediately) top_tile->init(dirtyMask, true); + else top_tile->setDirtyMask(dirtyMask); } } @@ -845,8 +847,9 @@ void GeometryTechnique::generateGeometry(BufferData& buffer, Locator* masterLoca { if (!(bottom_tile->getTerrainTechnique()->containsNeighbour(_terrainTile))) { - bottom_tile->setDirtyMask(bottom_tile->getDirtyMask() | TerrainTile::BOTTOM_EDGE_DIRTY); - if (updateNeighboursImmediately) bottom_tile->init(); + int dirtyMask = bottom_tile->getDirtyMask() | TerrainTile::BOTTOM_EDGE_DIRTY; + if (updateNeighboursImmediately) bottom_tile->init(dirtyMask, true); + else bottom_tile->setDirtyMask(dirtyMask); } } } @@ -1322,7 +1325,7 @@ void GeometryTechnique::traverse(osg::NodeVisitor& nv) // if app traversal update the frame count. if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR) { - if (_terrainTile->getDirty()) _terrainTile->init(); + if (_terrainTile->getDirty()) _terrainTile->init(_terrainTile->getDirtyMask(), false); osgUtil::UpdateVisitor* uv = dynamic_cast(&nv); if (uv) @@ -1345,7 +1348,7 @@ void GeometryTechnique::traverse(osg::NodeVisitor& nv) if (_terrainTile->getDirty()) { OSG_INFO<<"******* Doing init ***********"<init(); + _terrainTile->init(_terrainTile->getDirtyMask(), false); } if (_currentBufferData.valid()) diff --git a/src/osgTerrain/Terrain.cpp b/src/osgTerrain/Terrain.cpp index 24f2a8ca6..90047f04b 100644 --- a/src/osgTerrain/Terrain.cpp +++ b/src/osgTerrain/Terrain.cpp @@ -30,7 +30,7 @@ Terrain::Terrain(): } Terrain::Terrain(const Terrain& ts, const osg::CopyOp& copyop): - osg::Group(ts,copyop), + osg::CoordinateSystemNode(ts,copyop), _sampleRatio(ts._sampleRatio), _verticalScale(ts._verticalScale), _blendingPolicy(ts._blendingPolicy), @@ -69,7 +69,7 @@ void Terrain::traverse(osg::NodeVisitor& nv) ++itr) { TerrainTile* tile = *itr; - if (tile->getTerrainTechnique()) tile->getTerrainTechnique()->update(uv); + tile->traverse(nv); } _updateTerrainTileSet.clear(); } diff --git a/src/osgTerrain/TerrainTechnique.cpp b/src/osgTerrain/TerrainTechnique.cpp index ce4267eae..e1a63903d 100644 --- a/src/osgTerrain/TerrainTechnique.cpp +++ b/src/osgTerrain/TerrainTechnique.cpp @@ -83,9 +83,9 @@ void TerrainTechnique::setTerrainTile(TerrainTile* tile) _terrainTile = tile; } -void TerrainTechnique::init() +void TerrainTechnique::init(int dirtyMask, bool assumeMultiThreaded) { - OSG_NOTIFY(osg::NOTICE)<getDirty()) _terrainTile->init(); + if (_terrainTile->getDirty()) _terrainTile->init(_terrainTile->getDirtyMask(), false); osgUtil::UpdateVisitor* uv = dynamic_cast(&nv); if (uv) @@ -132,7 +132,10 @@ void TerrainTechnique::traverse(osg::NodeVisitor& nv) } } - if (_terrainTile->getDirty()) _terrainTile->init(); + if (_terrainTile->getDirty()) + { + _terrainTile->init(_terrainTile->getDirtyMask(), false); + } // otherwise fallback to the Group::traverse() _terrainTile->osg::Group::traverse(nv); diff --git a/src/osgTerrain/TerrainTile.cpp b/src/osgTerrain/TerrainTile.cpp index b659d690d..7cf8af21b 100644 --- a/src/osgTerrain/TerrainTile.cpp +++ b/src/osgTerrain/TerrainTile.cpp @@ -140,7 +140,7 @@ void TerrainTile::traverse(osg::NodeVisitor& nv) } } - init(); + init(getDirtyMask(), false); _hasBeenTraversal = true; } @@ -164,7 +164,7 @@ void TerrainTile::traverse(osg::NodeVisitor& nv) } } -void TerrainTile::init() +void TerrainTile::init(int dirtyMask, bool assumeMultiThreaded) { if (!_terrainTechnique) { @@ -179,9 +179,9 @@ void TerrainTile::init() } } - if (_terrainTechnique.valid() && getDirty()) + if (_terrainTechnique.valid()) { - _terrainTechnique->init(); + _terrainTechnique->init(dirtyMask, assumeMultiThreaded); } } @@ -218,6 +218,15 @@ void TerrainTile::setDirtyMask(int dirtyMask) if (_dirtyMask!=NOT_DIRTY) dirtyDelta += 1; +#if 1 + if (dirtyDelta>0) + { + // need to signal that we need an update + if (_terrain) _terrain->updateTerrainTileOnNextFrame(this); + } +#else + + // setNumChildrenRequeingUpdateTraversal() isn't thread safe so should avoid using it. if (dirtyDelta>0) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1); @@ -226,6 +235,7 @@ void TerrainTile::setDirtyMask(int dirtyMask) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1); } +#endif } diff --git a/src/osgWrappers/deprecated-dotosg/osgTerrain/Terrain.cpp b/src/osgWrappers/deprecated-dotosg/osgTerrain/Terrain.cpp index 025caec9e..a1e333482 100644 --- a/src/osgWrappers/deprecated-dotosg/osgTerrain/Terrain.cpp +++ b/src/osgWrappers/deprecated-dotosg/osgTerrain/Terrain.cpp @@ -13,7 +13,7 @@ REGISTER_DOTOSGWRAPPER(Terrain) ( new osgTerrain::Terrain, "Terrain", - "Object Node Terrain Group", + "Object Node Terrain CoordinateSystemNode Group", &Terrain_readLocalData, &Terrain_writeLocalData ); diff --git a/src/osgWrappers/serializers/osgTerrain/Terrain.cpp b/src/osgWrappers/serializers/osgTerrain/Terrain.cpp index 3957407d8..8dbfb9d92 100644 --- a/src/osgWrappers/serializers/osgTerrain/Terrain.cpp +++ b/src/osgWrappers/serializers/osgTerrain/Terrain.cpp @@ -6,7 +6,7 @@ REGISTER_OBJECT_WRAPPER( osgTerrain_Terrain, new osgTerrain::Terrain, osgTerrain::Terrain, - "osg::Object osg::Node osg::Group osgTerrain::Terrain" ) + "osg::Object osg::Node osg::CoordinateSystemNode osgTerrain::Terrain" ) { ADD_FLOAT_SERIALIZER( SampleRatio, 1.0f ); // _sampleRatio ADD_FLOAT_SERIALIZER( VerticalScale, 1.0f ); // _verticalScale