diff --git a/include/osg/ClusterCullingCallback b/include/osg/ClusterCullingCallback index 9f8cee6c9..a5e64ca8d 100644 --- a/include/osg/ClusterCullingCallback +++ b/include/osg/ClusterCullingCallback @@ -15,13 +15,14 @@ #define OSG_CLUSTERCULLINGCALLBACK 1 #include +#include namespace osg { /** Implements cluster culling to cull back facing drawables. Derived from * Drawable::CullCallback. */ -class SG_EXPORT ClusterCullingCallback : public Drawable::CullCallback +class SG_EXPORT ClusterCullingCallback : public Drawable::CullCallback, public NodeCallback { public: @@ -35,6 +36,9 @@ class SG_EXPORT ClusterCullingCallback : public Drawable::CullCallback /** Computes the control point, normal, and deviation from the * given drawable contents. */ void computeFrom(const osg::Drawable* drawable); + + /** Transform the ClusterCullingCallback's positional members to a new coordinate frame.*/ + void transform(const osg::Matrixd& matrix); void set(const osg::Vec3& controlPoint, const osg::Vec3& normal, float deviation, float radius); @@ -52,6 +56,9 @@ class SG_EXPORT ClusterCullingCallback : public Drawable::CullCallback virtual bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const; + /** Callback method called by the NodeVisitor when visiting a node.*/ + virtual void operator()(Node* node, NodeVisitor* nv); + protected: virtual ~ClusterCullingCallback() {} diff --git a/src/osg/ClusterCullingCallback.cpp b/src/osg/ClusterCullingCallback.cpp index a0519b0cd..194122407 100644 --- a/src/osg/ClusterCullingCallback.cpp +++ b/src/osg/ClusterCullingCallback.cpp @@ -143,6 +143,13 @@ void ClusterCullingCallback::set(const osg::Vec3& controlPoint, const osg::Vec3& _radius = radius; } +void ClusterCullingCallback::transform(const osg::Matrixd& matrix) +{ + _controlPoint = Vec3d(_controlPoint)*matrix; + _normal = Matrixd::transform3x3(Matrixd::inverse(matrix),Vec3d(_normal)); + _normal.normalize(); +} + bool ClusterCullingCallback::cull(osg::NodeVisitor* nv, osg::Drawable* , osg::State*) const { @@ -162,7 +169,10 @@ bool ClusterCullingCallback::cull(osg::NodeVisitor* nv, osg::Drawable* , osg::St osg::Vec3 eye_cp = nv->getEyePoint() - _controlPoint; float radius = eye_cp.length(); - if (radius<_radius) return false; + if (radius<_radius) + { + return false; + } float deviation = (eye_cp * _normal)/radius; @@ -172,3 +182,14 @@ bool ClusterCullingCallback::cull(osg::NodeVisitor* nv, osg::Drawable* , osg::St return deviation < _deviation; } + + +void ClusterCullingCallback::operator()(Node* node, NodeVisitor* nv) +{ + if (nv) + { + if (cull(nv,0,0)) return; + + traverse(node,nv); + } +} diff --git a/src/osgPlugins/ive/IveVersion.h b/src/osgPlugins/ive/IveVersion.h index 46f72191d..f33de6281 100644 --- a/src/osgPlugins/ive/IveVersion.h +++ b/src/osgPlugins/ive/IveVersion.h @@ -8,11 +8,13 @@ compatibility (if implemented). VERSION is stored in the 2nd 4 bytes of the file */ -#define VERSION_0002 0x00000002 -#define VERSION_0003 0x00000003 -#define VERSION_0004 0x00000004 -#define VERSION_0005 0x00000005 -#define VERSION VERSION_0005 +#define VERSION_0001 1 +#define VERSION_0002 2 +#define VERSION_0003 3 +#define VERSION_0004 4 +#define VERSION_0005 5 +#define VERSION_0006 6 +#define VERSION VERSION_0006 /* The BYTE_SEX tag is used to check the endian diff --git a/src/osgPlugins/ive/Node.cpp b/src/osgPlugins/ive/Node.cpp index 6614ebb99..3a89abc10 100644 --- a/src/osgPlugins/ive/Node.cpp +++ b/src/osgPlugins/ive/Node.cpp @@ -18,6 +18,7 @@ #include "Object.h" #include "StateSet.h" #include "AnimationPathCallback.h" +#include "ClusterCullingCallback.h" using namespace ive; @@ -62,9 +63,19 @@ void Node::write(DataOutputStream* out){ { ((ive::AnimationPathCallback*)(nc))->write(out); } + + if (out->getVersion() >= VERSION_0006) + { + osg::ClusterCullingCallback* ccc = dynamic_cast(getCullCallback()); + out->writeBool(ccc!=0); + if(ccc) + { + ((ive::ClusterCullingCallback*)(ccc))->write(out); + } + } - // Write NodeMask - out->writeUInt(getNodeMask()); + // Write NodeMask + out->writeUInt(getNodeMask()); } @@ -95,6 +106,7 @@ void Node::read(DataInputStream* in){ { setStateSet(in->readStateSet()); } + // Read UpdateCallback if any if(in->readBool()) { @@ -102,8 +114,19 @@ void Node::read(DataInputStream* in){ ((ive::AnimationPathCallback*)(nc))->read(in); setUpdateCallback(nc); } - // Read NodeMask - setNodeMask(in->readUInt()); + + if (in->getVersion() >= VERSION_0006) + { + if(in->readBool()) + { + osg::ClusterCullingCallback* ccc = new osg::ClusterCullingCallback(); + ((ive::ClusterCullingCallback*)(ccc))->read(in); + setCullCallback(ccc); + } + } + + // Read NodeMask + setNodeMask(in->readUInt()); } else{ throw Exception("Node::read(): Expected Node identification"); diff --git a/src/osgTerrain/DataSet.cpp b/src/osgTerrain/DataSet.cpp index 06a656a62..a28d86910 100644 --- a/src/osgTerrain/DataSet.cpp +++ b/src/osgTerrain/DataSet.cpp @@ -2303,9 +2303,10 @@ osg::Node* DataSet::DestinationTile::createPolygonal() float local_dot_product = -sin(theta + phi); float local_m = globe_radius*( 1.0/ cos(theta+phi) - 1.0); + float local_radius = static_cast(globe_radius * tan(beta)); // beta*globe_radius; min_dot_product = osg::minimum(min_dot_product, local_dot_product); max_cluster_culling_height = osg::maximum(max_cluster_culling_height,local_m); - max_cluster_culling_radius = osg::maximum(max_cluster_culling_radius,static_cast(beta*globe_radius)); + max_cluster_culling_radius = osg::maximum(max_cluster_culling_radius,local_radius); } else { @@ -2838,6 +2839,66 @@ std::string DataSet::CompositeDestination::getSubTileName() return _name+"_subtile"+_dataSet->getDestinationTileExtension(); } + +class CollectClusterCullingCallbacks : public osg::NodeVisitor +{ +public: + + + struct Triple + { + Triple(): + _drawable(0), + _callback(0) {} + + Triple(osg::NodePath nodePath, osg::Drawable* drawable, osg::ClusterCullingCallback* callback): + _nodePath(nodePath), + _drawable(drawable), + _callback(callback) {} + + Triple(const Triple& t): + _nodePath(t._nodePath), + _drawable(t._drawable), + _callback(t._callback) {} + + Triple& operator = (const Triple& t) + { + _nodePath = t._nodePath; + _drawable = t._drawable; + _callback = t._callback; + return *this; + } + + osg::NodePath _nodePath; + osg::Drawable* _drawable; + osg::ClusterCullingCallback* _callback; + }; + + typedef std::vector ClusterCullingCallbackList; + + CollectClusterCullingCallbacks(): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + + virtual void apply(osg::Geode& geode) + { + for(unsigned int i=0; i(geode.getDrawable(i)->getCullCallback()); + if (callback) + { + _callbackList.push_back(Triple(getNodePath(),geode.getDrawable(i),callback)); + } + else + { + osg::notify(osg::NOTICE)<<" Note found"<getCullCallback()<addChild(group); } + + // find cluster culling callbacks on drawables and move them to the PagedLOD level. + { + CollectClusterCullingCallbacks collect; + pagedLOD->accept(collect); + + if (!collect._callbackList.empty()) + { + if (collect._callbackList.size()==1) + { + CollectClusterCullingCallbacks::Triple& triple = collect._callbackList.front(); + + osg::Matrixd matrix = osg::computeLocalToWorld(triple._nodePath); + + triple._callback->transform(matrix); + + osg::notify(osg::NOTICE)<<"cluster culling matrix "<setCullCallback(triple._callback); + + // remove it from the drawable. + triple._drawable->setCullCallback(0); + } + } + } + // cutOffDistance = pagedLOD->getBound().radius()*_dataSet->getRadiusToMaxVisibleDistanceRatio(); pagedLOD->setRange(0,cutOffDistance,farDistance);