diff --git a/examples/osgforest/osgforest.cpp b/examples/osgforest/osgforest.cpp index c9d2f4400..5333377cd 100644 --- a/examples/osgforest/osgforest.cpp +++ b/examples/osgforest/osgforest.cpp @@ -21,32 +21,129 @@ // for the grid data.. #include "../osghangglide/terrain_coords.h" -class Tree : public osg::Referenced +// class to create the forest and manage the movement between various techniques. +class ForestTechniqueManager : public osg::Referenced { public: - Tree(): - _color(255,255,255,255), - _width(1.0f), - _height(1.0f), - _type(0) {} + ForestTechniqueManager() {} - Tree(const osg::Vec3& position, const osg::UByte4& color, float width, float height, unsigned int type): - _position(position), - _color(color), - _width(width), - _height(height), - _type(type) {} + class Tree : public osg::Referenced + { + public: + + Tree(): + _color(255,255,255,255), + _width(1.0f), + _height(1.0f), + _type(0) {} + + Tree(const osg::Vec3& position, const osg::UByte4& color, float width, float height, unsigned int type): + _position(position), + _color(color), + _width(width), + _height(height), + _type(type) {} + + osg::Vec3 _position; + osg::UByte4 _color; + float _width; + float _height; + unsigned int _type; + }; + + typedef std::vector< osg::ref_ptr > TreeList; + + float random(float min,float max) { return min + (max-min)*(float)rand()/(float)RAND_MAX; } + int random(int min,int max) { return min + (int)((float)(max-min)*(float)rand()/(float)RAND_MAX); } + + osg::Geode* createTerrain(const osg::Vec3& origin, const osg::Vec3& size); + + void createTreeList(osg::Node* terrain,const osg::Vec3& origin, const osg::Vec3& size,unsigned int numTreesToCreate,TreeList& trees); + + osg::Geometry* createSprite( float w, float h, osg::UByte4 color ); + + osg::Geometry* createOrthogonalQuads( const osg::Vec3& pos, float w, float h, osg::UByte4 color ); + + osg::Node* createScene(); + + void advanceToNextTechnique(int delta=1) + { + if (_techniqueSwitch.valid()) + { + _currentTechnique = (_currentTechnique + delta)%_techniqueSwitch->getNumChildren(); + _techniqueSwitch->setSingleChildOn(_currentTechnique); + } + } + + osg::ref_ptr _techniqueSwitch; + int _currentTechnique; + - osg::Vec3 _position; - osg::UByte4 _color; - float _width; - float _height; - unsigned int _type; }; +// event handler to capture keyboard events and use them to advance the technique used for rendering +class TechniqueEventHandler : public osgGA::GUIEventHandler, public osg::NodeCallback +{ +public: -osg::Geode* createTerrain(const osg::Vec3& origin, const osg::Vec3& size) + TechniqueEventHandler(ForestTechniqueManager* ttm=0) { _ForestTechniqueManager = ttm; } + + META_Object(osgforestApp,TechniqueEventHandler); + + virtual void accept(osgGA::GUIEventHandlerVisitor& v) { v.visit(*this); } + + virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&); + + virtual void getUsage(osg::ApplicationUsage& usage) const; + +protected: + + ~TechniqueEventHandler() {} + + TechniqueEventHandler(const TechniqueEventHandler&,const osg::CopyOp&) {} + + osg::ref_ptr _ForestTechniqueManager; + + +}; + +bool TechniqueEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&) +{ + switch(ea.getEventType()) + { + case(osgGA::GUIEventAdapter::KEYDOWN): + { + if (ea.getKey()=='n' || + ea.getKey()==osgGA::GUIEventAdapter::KEY_Right || + ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Right) + { + _ForestTechniqueManager->advanceToNextTechnique(1); + return true; + } + else if (ea.getKey()=='p' || + ea.getKey()==osgGA::GUIEventAdapter::KEY_Left || + ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Left) + { + _ForestTechniqueManager->advanceToNextTechnique(-1); + return true; + } + return false; + } + + default: + return false; + } +} + +void TechniqueEventHandler::getUsage(osg::ApplicationUsage& usage) const +{ + usage.addKeyboardMouseBinding("n or Left Arrow","Advance to next technique"); + usage.addKeyboardMouseBinding("p or Right Array","Move to previous technique"); +} + + +osg::Geode* ForestTechniqueManager::createTerrain(const osg::Vec3& origin, const osg::Vec3& size) { osg::Geode* geode = new osg::Geode(); @@ -166,12 +263,7 @@ osg::Geode* createTerrain(const osg::Vec3& origin, const osg::Vec3& size) return geode; } -typedef std::vector< osg::ref_ptr > TreeList; - -float random(float min,float max) { return min + (max-min)*(float)rand()/(float)RAND_MAX; } -int random(int min,int max) { return min + (int)((float)(max-min)*(float)rand()/(float)RAND_MAX); } - -void createTreeList(osg::Node* terrain,const osg::Vec3& origin, const osg::Vec3& size,unsigned int numTreesToCreate,TreeList& trees) +void ForestTechniqueManager::createTreeList(osg::Node* terrain,const osg::Vec3& origin, const osg::Vec3& size,unsigned int numTreesToCreate,TreeList& trees) { float max_TreeHeight = sqrtf(size.length2()/(float)numTreesToCreate); @@ -218,7 +310,7 @@ void createTreeList(osg::Node* terrain,const osg::Vec3& origin, const osg::Vec3& } } -osg::Geometry* createSprite( float w, float h, osg::UByte4 color ) +osg::Geometry* ForestTechniqueManager::createSprite( float w, float h, osg::UByte4 color ) { // set up the coords osg::Vec3Array& v = *(new osg::Vec3Array(4)); @@ -251,7 +343,7 @@ osg::Geometry* createSprite( float w, float h, osg::UByte4 color ) return geom; } -osg::Geometry* createOrthogonalQuads( const osg::Vec3& pos, float w, float h, osg::UByte4 color ) +osg::Geometry* ForestTechniqueManager::createOrthogonalQuads( const osg::Vec3& pos, float w, float h, osg::UByte4 color ) { // set up the coords osg::Vec3Array& v = *(new osg::Vec3Array(8)); @@ -298,7 +390,7 @@ osg::Geometry* createOrthogonalQuads( const osg::Vec3& pos, float w, float h, os return geom; } -osg::Node* createScene() +osg::Node* ForestTechniqueManager::createScene() { osg::Vec3 origin(0.0f,0.0f,0.0f); osg::Vec3 size(1000.0f,1000.0f,200.0f); @@ -329,7 +421,7 @@ osg::Node* createScene() } - osg::Switch* switchNode = new osg::Switch; + _techniqueSwitch = new osg::Switch; { osg::Billboard* billboard = new osg::Billboard; @@ -343,7 +435,7 @@ osg::Node* createScene() billboard->addDrawable(createSprite(tree._width,tree._height,tree._color),tree._position); } - switchNode->addChild(billboard); + _techniqueSwitch->addChild(billboard); } { @@ -358,7 +450,7 @@ osg::Node* createScene() geode->addDrawable(createOrthogonalQuads(tree._position,tree._width,tree._height,tree._color)); } - switchNode->addChild(geode); + _techniqueSwitch->addChild(geode); } { @@ -383,15 +475,17 @@ osg::Node* createScene() transform_group->addChild(transform); } - switchNode->addChild(transform_group); + _techniqueSwitch->addChild(transform_group); } - switchNode->setSingleChildOn(1); + _currentTechnique = 0; + _techniqueSwitch->setSingleChildOn(_currentTechnique); + osg::Group* scene = new osg::Group; scene->addChild(terrain.get()); - scene->addChild(switchNode); + scene->addChild(_techniqueSwitch.get()); return scene; } @@ -412,6 +506,10 @@ int main( int argc, char **argv ) // set up the value with sensible default event handlers. viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS); + + osg::ref_ptr ttm = new ForestTechniqueManager; + + viewer.getEventHandlerList().push_front(new TechniqueEventHandler(ttm.get())); // get details on keyboard and mouse bindings used by the viewer. viewer.getUsage(*arguments.getApplicationUsage()); @@ -433,7 +531,7 @@ int main( int argc, char **argv ) return 1; } - osg::Node* node = createScene(); + osg::Node* node = ttm->createScene(); // add model to viewer. viewer.setSceneData( node ); diff --git a/include/osg/CullStack b/include/osg/CullStack index 746e3231f..615dccf0d 100644 --- a/include/osg/CullStack +++ b/include/osg/CullStack @@ -141,7 +141,7 @@ class SG_EXPORT CullStack } - typedef fast_back_stack > CullingStack; + typedef std::vector< CullingSet > CullingStack; inline CullingStack& getClipSpaceCullingStack() { return _clipspaceCullingStack; } @@ -152,8 +152,8 @@ class SG_EXPORT CullStack // inline CullingSet& getCurrentCullingSet() { return _modelviewCullingStack.back(); } // inline const CullingSet& getCurrentCullingSet() const { return _modelviewCullingStack.back(); } - inline CullingSet& getCurrentCullingSet() { return *_modelviewCullingStack.back(); } - inline const CullingSet& getCurrentCullingSet() const { return *_modelviewCullingStack.back(); } + inline CullingSet& getCurrentCullingSet() { return *_back_modelviewCullingStack; } + inline const CullingSet& getCurrentCullingSet() const { return *_back_modelviewCullingStack; } inline osg::Viewport* getViewport(); inline osg::RefMatrix& getModelViewMatrix(); @@ -202,7 +202,10 @@ class SG_EXPORT CullStack CullingStack _clipspaceCullingStack; CullingStack _projectionCullingStack; + CullingStack _modelviewCullingStack; + unsigned int _index_modelviewCullingStack; + CullingSet* _back_modelviewCullingStack; void computeFrustumVolume(); float _frustumVolume; diff --git a/include/osgGA/AnimationPathManipulator b/include/osgGA/AnimationPathManipulator index d9737791d..8c6686c64 100644 --- a/include/osgGA/AnimationPathManipulator +++ b/include/osgGA/AnimationPathManipulator @@ -40,6 +40,9 @@ class OSGGA_EXPORT AnimationPathManipulator : public MatrixManipulator AnimationPathManipulator( const std::string& filename ); virtual const char* className() const { return "AnimationPath"; } + + void setPrintOutTimingInfo(bool printOutTiminInfo) { _printOutTiminInfo=printOutTiminInfo; } + bool getPrintOutTimingInfo() const { return _printOutTiminInfo; } /** set the position of the matrix manipulator using a 4x4 Matrix.*/ virtual void setByMatrix(const osg::Matrixd& matrix) { _matrix = matrix; } @@ -74,6 +77,8 @@ class OSGGA_EXPORT AnimationPathManipulator : public MatrixManipulator protected: bool _valid; + + bool _printOutTiminInfo; void handleFrame( double time ); diff --git a/src/osg/CullStack.cpp b/src/osg/CullStack.cpp index 050fab7dd..ba029b771 100644 --- a/src/osg/CullStack.cpp +++ b/src/osg/CullStack.cpp @@ -25,6 +25,9 @@ CullStack::CullStack() _bbCornerFar = 7; _currentReuseMatrixIndex=0; _identity = new RefMatrix(); + + _index_modelviewCullingStack = 0; + _back_modelviewCullingStack = 0; } @@ -33,7 +36,6 @@ CullStack::~CullStack() reset(); } - void CullStack::reset() { @@ -48,8 +50,11 @@ void CullStack::reset() _clipspaceCullingStack.clear(); _projectionCullingStack.clear(); - _modelviewCullingStack.clear(); - + + //_modelviewCullingStack.clear(); + _index_modelviewCullingStack=0; + _back_modelviewCullingStack = 0; + osg::Vec3 lookVector(0.0,0.0,-1.0); _bbCornerFar = (lookVector.x()>=0?1:0) | @@ -59,14 +64,17 @@ void CullStack::reset() _bbCornerNear = (~_bbCornerFar)&7; } + void CullStack::pushCullingSet() { _MVPW_Stack.push_back(0L); - - if (_modelviewStack.empty()) - { - _modelviewCullingStack.push_back(_projectionCullingStack.back()); + if (_index_modelviewCullingStack==0) + { + if (_modelviewCullingStack.empty()) + _modelviewCullingStack.push_back(CullingSet()); + + _modelviewCullingStack[_index_modelviewCullingStack++].set(_projectionCullingStack.back()); } else { @@ -104,11 +112,19 @@ void CullStack::pushCullingSet() float scaleRatio = 0.701f/sqrtf(scale_00.length2()+scale_10.length2()); pixelSizeVector *= scaleRatio; + - _modelviewCullingStack.push_back(new osg::CullingSet(*_projectionCullingStack.back(),*_modelviewStack.back(),pixelSizeVector)); + if (_index_modelviewCullingStack>=_modelviewCullingStack.size()) + { + _modelviewCullingStack.push_back(CullingSet()); + } + + _modelviewCullingStack[_index_modelviewCullingStack++].set(_projectionCullingStack.back(),*_modelviewStack.back(),pixelSizeVector); } + _back_modelviewCullingStack = &_modelviewCullingStack[_index_modelviewCullingStack-1]; + // const osg::Polytope& polytope = _modelviewCullingStack.back()->getFrustum(); // const osg::Polytope::PlaneList& pl = polytope.getPlaneList(); // std::cout <<"new cull stack"<0) _back_modelviewCullingStack = &_modelviewCullingStack[_index_modelviewCullingStack-1]; + } void CullStack::pushViewport(osg::Viewport* viewport) @@ -144,17 +163,18 @@ void CullStack::pushProjectionMatrix(RefMatrix* matrix) { _projectionStack.push_back(matrix); - osg::CullingSet* cullingSet = new osg::CullingSet(); + _projectionCullingStack.push_back(osg::CullingSet()); + osg::CullingSet& cullingSet = _projectionCullingStack.back(); // set up view frustum. - cullingSet->getFrustum().setToUnitFrustum(((_cullingMode&NEAR_PLANE_CULLING)!=0),((_cullingMode&FAR_PLANE_CULLING)!=0)); - cullingSet->getFrustum().transformProvidingInverse(*matrix); + cullingSet.getFrustum().setToUnitFrustum(((_cullingMode&NEAR_PLANE_CULLING)!=0),((_cullingMode&FAR_PLANE_CULLING)!=0)); + cullingSet.getFrustum().transformProvidingInverse(*matrix); // set the culling mask ( There should be a more elegant way!) Nikolaus H. - cullingSet->setCullingMask(_cullingMode); + cullingSet.setCullingMask(_cullingMode); // set the small feature culling. - cullingSet->setSmallFeatureCullingPixelSize(_smallFeatureCullingPixelSize); + cullingSet.setSmallFeatureCullingPixelSize(_smallFeatureCullingPixelSize); // set up the relevant occluders which a related to this projection. for(ShadowVolumeOccluderList::iterator itr=_occluderList.begin(); @@ -165,12 +185,11 @@ void CullStack::pushProjectionMatrix(RefMatrix* matrix) if (itr->matchProjectionMatrix(*matrix)) { //std::cout << " ** activating occluder"<addOccluder(*itr); + cullingSet.addOccluder(*itr); } } - _projectionCullingStack.push_back(cullingSet); // need to recompute frustum volume. _frustumVolume = -1.0f; diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index 54f6f08f8..efc03ccf4 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -2025,7 +2025,7 @@ bool _verifyBindings(const osg::Geometry& geom, const A& arrayData) } template -bool _computeCorrectBindingsAndArraySizes(const osg::Geometry& geom, A& arrayData, const char* arrayName) +void _computeCorrectBindingsAndArraySizes(const osg::Geometry& geom, A& arrayData, const char* arrayName) { if (!geom.getVertexArray() || geom.getVertexArray()==0) { diff --git a/src/osgGA/AnimationPathManipulator.cpp b/src/osgGA/AnimationPathManipulator.cpp index d445b3579..0f978a314 100644 --- a/src/osgGA/AnimationPathManipulator.cpp +++ b/src/osgGA/AnimationPathManipulator.cpp @@ -5,6 +5,8 @@ using namespace osgGA; AnimationPathManipulator::AnimationPathManipulator(osg::AnimationPath* animationPath) { + _printOutTiminInfo = true; + _animationPath = animationPath; _timeOffset = 0.0; _timeScale = 1.0; @@ -17,6 +19,8 @@ AnimationPathManipulator::AnimationPathManipulator(osg::AnimationPath* animation AnimationPathManipulator::AnimationPathManipulator( const std::string& filename ) { + _printOutTiminInfo = true; + _animationPath = new osg::AnimationPath; _animationPath->setLoopMode(osg::AnimationPath::LOOP); _timeOffset = 0.0f; @@ -140,19 +144,22 @@ void AnimationPathManipulator::handleFrame( double time ) ++_numOfFramesSinceStartOfTimedPeriod; - double delta = (animTime-_animStartOfTimedPeriod); - if (delta>=_animationPath->getPeriod()) + if (_printOutTiminInfo) { - double frameRate = (double)_numOfFramesSinceStartOfTimedPeriod/delta; - osg::notify(osg::INFO) <<"AnimatonPath completed in "<