diff --git a/include/osgUtil/CullVisitor b/include/osgUtil/CullVisitor index 7f1d24764..3b23e7593 100644 --- a/include/osgUtil/CullVisitor +++ b/include/osgUtil/CullVisitor @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -60,12 +59,6 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor virtual void apply(osg::EarthSky& node); virtual void apply(osg::Impostor& node); - - - void setCamera(const osg::Camera& camera); - const osg::Camera* getCamera() const { return _camera.get(); } - - void setEarthSky(const osg::EarthSky* earthSky) { _earthSky = earthSky; } const osg::EarthSky* getEarthSky() const { return _earthSky.get(); } @@ -118,24 +111,14 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor CullViewState::CullingMode getCullingMode() const; - /** Set the viewport. - * Used to enable the CullVisitor can make decision - * such as based on viewport dimensions.*/ - void setViewport(osg::Viewport* viewport) { _viewport = viewport; } + void pushViewport(osg::Viewport* viewport); + void popViewport(); - /** Get the const viewport. */ - const osg::Viewport* getViewport() const { return _viewport.get(); } + void pushProjectionMatrix(osg::Matrix* matrix); + void popProjectionMatrix(); - /** Get the viewport. */ - osg::Viewport* getViewport() { return _viewport.get(); } - - inline void pushCullViewState() { pushCullViewState_ModelView(NULL,NULL); } - - void pushCullViewState_Projection(osg::Matrix* matrix); - void pushCullViewState_ModelView(osg::Matrix* matrix); - void pushCullViewState_ModelView(osg::Matrix* matrix,osg::Matrix* inverse); - - void popCullViewState(); + void pushModelViewMatrix(osg::Matrix* matrix); + void popModelViewMatrix(); /** Push state set on the current state group. * If the state exists in a child state group of the current @@ -192,16 +175,6 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor const float getCalculatedFarPlane() const { return _calculated_zfar; } - //SandB - /**sets the flag for detailed culling*/ - void setDetailedCulling(bool detailed) {_detailedCulling = detailed;} - - /**gets the status of detailed culling*/ - const bool getDetailedCulling() const {return _detailedCulling;} - - /**calculates unit directions of vectors that are intersections of cameras' clipping planes*/ - void calcClippingDirections() const; - protected: /** prevent unwanted copy construction.*/ @@ -212,70 +185,56 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor inline osg::Matrix* getCurrentMatrix() { - return _cvs->_matrix.get(); - } - - - inline osg::Matrix* getInverseCurrentMatrix() - { - return _cvs->_inverse.get(); + return _modelviewStack.back().get(); } inline const osg::Vec3& getEyeLocal() const { - return _cvs->_eyePoint; + return _eyePointStack.back(); + } + + inline const osg::Vec3 getUpLocal() const + { + const osg::Matrix& matrix = *_modelviewStack.back(); + return osg::Vec3(matrix(0,1),matrix(1,1),matrix(2,1)); } - inline const osg::Vec3& getUpLocal() const + inline const osg::Vec3 getLookVectorLocal() const { - return _cvs->_upVector; - } - - inline const osg::Vec3& getCenterLocal() const - { - return _cvs->_centerPoint; - } - - - inline const osg::Vec3& getLookVectorLocal() const - { - return _cvs->_lookVector; + const osg::Matrix& matrix = *_modelviewStack.back(); + return osg::Vec3(-matrix(0,2),-matrix(1,2),-matrix(2,2)); } inline bool isCulled(const osg::BoundingSphere& sp,CullViewState::CullingMode& mode) const { - return _cvs->isCulled(sp,mode); + if (!sp.isValid()) return true; + + if (!(_modelviewClippingVolumeStack.back().contains(sp,mode))) return true; + + if (mode&CullViewState::SMALL_FEATURE_CULLING) + { + const float _ratio2 = 0.002f*0.002f; + osg::Vec3 delta(sp._center-getEyeLocal()); + if (sp.radius2()isCulled(bb,mode); + if (!bb.isValid()) return true; + + return !_modelviewClippingVolumeStack.back().contains(bb,mode); } void updateCalculatedNearFar(const osg::BoundingBox& bb); void updateCalculatedNearFar(const osg::Vec3& pos); - - //SandB added: //////////////////////////////////////////////////////////////////////////////// - /**updates near and far clipping values for case of detailed culling*/ - void updateCalculatedNearFar(osg::Drawable* pDrawable); - - /**calculates near for "global" vertex in scene*/ - double calculateZNear(const osg::Vec3& position, const osg::Vec3& eye, const osg::Vec3& look); - /////////////////////////////////////////////////////////////////////////////////////////////// - - /**unit vector of direction along intersection of cameras left and top clipping planes in "global" coordinates*/ - mutable osg::Vec3 _LeftUp; - /**unit vector of direction along intersection of cameras right and top clipping planes in "global" coordinates*/ - mutable osg::Vec3 _RightUp; - /**unit vector of direction along intersection of cameras left and down clipping planes in "global" coordinates*/ - mutable osg::Vec3 _LeftDown; - /**unit vector of direction along intersection of cameras right and down clipping planes in "global" coordinates*/ - mutable osg::Vec3 _RightDown; - - /** Add a drawable to current render graph.*/ inline void addDrawable(osg::Drawable* drawable,osg::Matrix* matrix) { @@ -287,7 +246,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor _currentRenderBin->addRenderGraph(_currentRenderGraph); } //_currentRenderGraph->addLeaf(new RenderLeaf(drawable,matrix)); - _currentRenderGraph->addLeaf(createOrReuseRenderLeaf(drawable,_cvs->_projection.get(),matrix)); + _currentRenderGraph->addLeaf(createOrReuseRenderLeaf(drawable,_projectionStack.back().get(),matrix)); } /** Add a drawable and depth to current render graph.*/ @@ -301,7 +260,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor _currentRenderBin->addRenderGraph(_currentRenderGraph); } //_currentRenderGraph->addLeaf(new RenderLeaf(drawable,matrix,depth)); - _currentRenderGraph->addLeaf(createOrReuseRenderLeaf(drawable,_cvs->_projection.get(),matrix,depth)); + _currentRenderGraph->addLeaf(createOrReuseRenderLeaf(drawable,_projectionStack.back().get(),matrix,depth)); } /** Add a light to current render graph.*/ @@ -314,35 +273,125 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor * to generate the impostor texture. */ osg::ImpostorSprite* createImpostorSprite(osg::Impostor& node); - bool _detailedCulling; - typedef std::vector< osg::ref_ptr > CullViewStateStack; - CullViewStateStack _viewStateStack; - osg::ref_ptr _tvs; - osg::ref_ptr _cvs; + osg::Viewport* getViewport() + { + if (!_viewportStack.empty()) + { + return _viewportStack.back().get(); + } + else + { + return 0L; + } + } + + osg::Matrix& getModelViewMatrix() + { + if (!_modelviewStack.empty()) + { + return *_modelviewStack.back(); + } + else + { + // default construction to identity. + static osg::Matrix identity; + return identity; + } + } + + osg::Matrix& getProjectionMatrix() + { + if (!_projectionStack.empty()) + { + return *_projectionStack.back(); + } + else + { + // default construction to identity. + static osg::Matrix identity; + return identity; + } + } + + const osg::Matrix getWindowMatrix() + { + if (!_viewportStack.empty()) + { + osg::Viewport* viewport = _viewportStack.back().get(); + return osg::Matrix::scale(0.5f*viewport->width(),viewport->height(),0.5f)*osg::Matrix::translate(0.5f,0.5f,0.5f); + } + else + { + // default construction to identity. + static osg::Matrix identity; + return identity; + } + } + + const osg::Matrix& getMVPW() + { + if (!_MVPW_Stack.empty()) + { + if (!_MVPW_Stack.back()) + { + _MVPW_Stack.back() = new osg::Matrix(getModelViewMatrix()*getProjectionMatrix()*getWindowMatrix()); + } + return *_MVPW_Stack.back(); + } + else + { + // default construction to identity. + static osg::Matrix identity; + return identity; + } + } + + + void pushClippingVolume(); + void popClippingVolume(); + + typedef std::vector ClippingVolumeStack; + typedef std::vector > MatrixStack; + + MatrixStack _projectionStack; + MatrixStack _PW_Stack; + ClippingVolumeStack _projectionClippingVolumeStack; + + MatrixStack _modelviewStack; + MatrixStack _MVPW_Stack; + ClippingVolumeStack _modelviewClippingVolumeStack; + + typedef std::vector > ViewportStack; + ViewportStack _viewportStack; + + typedef std::vector EyePointStack; + EyePointStack _eyePointStack; + + typedef std::vector CullingModeStack; + CullingModeStack _cullingModeStack; + + unsigned int _bbCornerNear; + unsigned int _bbCornerFar; + + osg::ref_ptr _rootRenderGraph; RenderGraph* _currentRenderGraph; osg::ref_ptr _rootRenderStage; RenderBin* _currentRenderBin; - std::vector _cullingModeStack; float _LODBias; float _calculated_znear; float _calculated_zfar; - osg::ref_ptr _camera; - osg::ref_ptr _earthSky; TransparencySortMode _tsm; - // viewport x,y,width,height respectively. - osg::ref_ptr _viewport; - bool _impostorActive; bool _depthSortImpostorSprites; float _impostorPixelErrorThreshold; diff --git a/include/osgUtil/NewCullVisitor b/include/osgUtil/NewCullVisitor deleted file mode 100644 index 2e060d014..000000000 --- a/include/osgUtil/NewCullVisitor +++ /dev/null @@ -1,467 +0,0 @@ -//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield -//Distributed under the terms of the GNU Library General Public License (LGPL) -//as published by the Free Software Foundation. - -#ifndef OSGUTIL_NEWCULLVISITOR -#define OSGUTIL_NEWCULLVISITOR 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -namespace osgUtil { - -/** - * Basic NodeVisitor implementation for rendering a scene. - * This visitor traverses the scene graph, collecting transparent and - * opaque osg::Drawables into a depth sorted transparent bin and a state - * sorted opaque bin. The opaque bin is rendered first, and then the - * transparent bin in rendered in order from the furthest osg::Drawable - * from the eye to the one nearest the eye. - */ -class OSGUTIL_EXPORT NewCullVisitor : public osg::NodeVisitor -{ - public: - - NewCullVisitor(); - virtual ~NewCullVisitor(); - - virtual NewCullVisitor* cloneType() const { return new NewCullVisitor(); } - - virtual void reset(); - - virtual void apply(osg::Node&); - virtual void apply(osg::Geode& node); - virtual void apply(osg::Billboard& node); - virtual void apply(osg::LightSource& node); - - virtual void apply(osg::Group& node); - virtual void apply(osg::Transform& node); - virtual void apply(osg::Projection& node); - virtual void apply(osg::Switch& node); - virtual void apply(osg::LOD& node); - virtual void apply(osg::EarthSky& node); - virtual void apply(osg::Impostor& node); - - void setEarthSky(const osg::EarthSky* earthSky) { _earthSky = earthSky; } - const osg::EarthSky* getEarthSky() const { return _earthSky.get(); } - - - void setLODBias(const float bias) { _LODBias = bias; } - const float getLODBias() const { return _LODBias; } - - /** Switch the creation of Impostors on or off. - * Setting active to false forces the NewCullVisitor to use the Impostor - * LOD children for rendering. Setting active to true forces the - * NewCullVisitor to create the appropriate pre-rendering stages which - * render to the ImpostorSprite's texture.*/ - void setImpostorsActive(const bool active) { _impostorActive = active; } - - /** Get whether impostors are active or not. */ - const bool getImpostorsActive() const { return _impostorActive; } - - /** Set the impostor error threshold. - * Used in calculation of whether impostors remain valid.*/ - void setImpostorPixelErrorThreshold(const float numPixels) { _impostorPixelErrorThreshold=numPixels; } - - /** Get the impostor error threshold.*/ - const float getImpostorPixelErrorThreshold() const { return _impostorPixelErrorThreshold; } - - /** Set whether ImpsotorSprite's should be placed in a depth sorted bin for rendering.*/ - void setDepthSortImpostorSprites(const bool doDepthSort) { _depthSortImpostorSprites = doDepthSort; } - - /** Get whether ImpsotorSprite's are depth sorted bin for rendering.*/ - const bool setDepthSortImpostorSprites() const { return _depthSortImpostorSprites; } - - /** Set the number of frames that an ImpsotorSprite's is kept whilst not being beyond, - * before being recycled.*/ - void setNumberOfFrameToKeepImpostorSprites(const int numFrames) { _numFramesToKeepImpostorSprites = numFrames; } - - /** Get the number of frames that an ImpsotorSprite's is kept whilst not being beyond, - * before being recycled.*/ - const int getNumberOfFrameToKeepImpostorSprites() const { return _numFramesToKeepImpostorSprites; } - - enum TransparencySortMode { - LOOK_VECTOR_DISTANCE, - OBJECT_EYE_POINT_DISTANCE - }; - - void setTransparencySortMode(TransparencySortMode tsm) { _tsm = tsm; } - - /** Sets the current CullingMode.*/ - void setCullingMode(CullViewState::CullingMode mode); - - /** Returns the current CullingMode.*/ - CullViewState::CullingMode getCullingMode() const; - - - void pushViewport(osg::Viewport* viewport); - void popViewport(); - - void pushProjectionMatrix(osg::Matrix* matrix); - void popProjectionMatrix(); - - void pushModelViewMatrix(osg::Matrix* matrix); - void popModelViewMatrix(); - - /** Push state set on the current state group. - * If the state exists in a child state group of the current - * state group then move the current state group to that child. - * Otherwise, create a new state group for the state set, add - * it to the current state group then move the current state - * group pointer to the new state group. - */ - inline void pushStateSet(const osg::StateSet* ss) - { - _currentRenderGraph = _currentRenderGraph->find_or_insert(ss); - if (ss->useRenderBinDetails()) - { - _currentRenderBin = _currentRenderBin->find_or_insert(ss->getBinNumber(),ss->getBinName()); - } - } - - /** Pop the top state set and hence associated state group. - * Move the current state group to the parent of the popped - * state group. - */ - inline void popStateSet() - { - if (_currentRenderGraph->_stateset->useRenderBinDetails()) - { - _currentRenderBin = _currentRenderBin->_parent; - } - _currentRenderGraph = _currentRenderGraph->_parent; - } - - void setRenderGraph(RenderGraph* rg) - { - _rootRenderGraph = rg; - _currentRenderGraph = rg; - } - - RenderGraph* getRenderGraph() - { - return _rootRenderGraph.get(); - } - - void setRenderStage(RenderStage* rg) - { - _rootRenderStage = rg; - _currentRenderBin = rg; - } - - RenderStage* getRenderStage() - { - return _rootRenderStage.get(); - } - - const float getCalculatedNearPlane() const { return _calculated_znear; } - - const float getCalculatedFarPlane() const { return _calculated_zfar; } - - protected: - - /** prevent unwanted copy construction.*/ - NewCullVisitor(const NewCullVisitor&):osg::NodeVisitor() {} - - /** prevent unwanted copy operator.*/ - NewCullVisitor& operator = (const NewCullVisitor&) { return *this; } - - inline osg::Matrix* getCurrentMatrix() - { - return _modelviewStack.back().get(); - } - - inline const osg::Vec3& getEyeLocal() const - { - return _eyePointStack.back(); - } - - inline const osg::Vec3 NewCullVisitor::getUpLocal() const - { - const osg::Matrix& matrix = *_modelviewStack.back(); - return osg::Vec3(matrix(0,1),matrix(1,1),matrix(2,1)); - } - - inline const osg::Vec3 NewCullVisitor::getLookVectorLocal() const - { - const osg::Matrix& matrix = *_modelviewStack.back(); - return osg::Vec3(-matrix(0,2),-matrix(1,2),-matrix(2,2)); - } - - - inline bool isCulled(const osg::BoundingSphere& sp,CullViewState::CullingMode& mode) const - { - if (!sp.isValid()) return true; - - if (!(_modelviewClippingVolumeStack.back().contains(sp,mode))) return true; - - if (mode&CullViewState::SMALL_FEATURE_CULLING) - { - const float _ratio2 = 0.002f*0.002f; - osg::Vec3 delta(sp._center-getEyeLocal()); - if (sp.radius2()leaves_empty()) - { - // this is first leaf to be added to RenderGraph - // and therefore should not already know to current render bin, - // so need to add it. - _currentRenderBin->addRenderGraph(_currentRenderGraph); - } - //_currentRenderGraph->addLeaf(new RenderLeaf(drawable,matrix)); - _currentRenderGraph->addLeaf(createOrReuseRenderLeaf(drawable,_projectionStack.back().get(),matrix)); - } - - /** Add a drawable and depth to current render graph.*/ - inline void addDrawableAndDepth(osg::Drawable* drawable,osg::Matrix* matrix,const float depth) - { - if (_currentRenderGraph->leaves_empty()) - { - // this is first leaf to be added to RenderGraph - // and therefore should not already know to current render bin, - // so need to add it. - _currentRenderBin->addRenderGraph(_currentRenderGraph); - } - //_currentRenderGraph->addLeaf(new RenderLeaf(drawable,matrix,depth)); - _currentRenderGraph->addLeaf(createOrReuseRenderLeaf(drawable,_projectionStack.back().get(),matrix,depth)); - } - - /** Add a light to current render graph.*/ - inline void addLight(osg::Light* light,osg::Matrix* matrix) - { - _currentRenderBin->_stage->addLight(light,matrix); - } - - /** create an impostor sprite by setting up a pre-rendering stage - * to generate the impostor texture. */ - osg::ImpostorSprite* createImpostorSprite(osg::Impostor& node); - - - osg::Viewport* getViewport() - { - if (!_viewportStack.empty()) - { - return _viewportStack.back().get(); - } - else - { - return 0L; - } - } - - osg::Matrix& getModelViewMatrix() - { - if (!_modelviewStack.empty()) - { - return *_modelviewStack.back(); - } - else - { - // default construction to identity. - static osg::Matrix identity; - return identity; - } - } - - osg::Matrix& getProjectionMatrix() - { - if (!_projectionStack.empty()) - { - return *_projectionStack.back(); - } - else - { - // default construction to identity. - static osg::Matrix identity; - return identity; - } - } - - const osg::Matrix getWindowMatrix() - { - if (!_viewportStack.empty()) - { - osg::Viewport* viewport = _viewportStack.back().get(); - return osg::Matrix::scale(0.5f*viewport->width(),viewport->height(),0.5f)*osg::Matrix::translate(0.5f,0.5f,0.5f); - } - else - { - // default construction to identity. - static osg::Matrix identity; - return identity; - } - } - - const osg::Matrix& getMVPW() - { - if (!_MVPW_Stack.empty()) - { - if (!_MVPW_Stack.back()) - { - _MVPW_Stack.back() = new osg::Matrix(getModelViewMatrix()*getProjectionMatrix()*getWindowMatrix()); - } - return *_MVPW_Stack.back(); - } - else - { - // default construction to identity. - static osg::Matrix identity; - return identity; - } - } - - - void pushClippingVolume(); - void popClippingVolume(); - - - typedef std::vector ClippingVolumeStack; - typedef std::vector > MatrixStack; - - MatrixStack _projectionStack; - MatrixStack _PW_Stack; - ClippingVolumeStack _projectionClippingVolumeStack; - - MatrixStack _modelviewStack; - MatrixStack _MVPW_Stack; - ClippingVolumeStack _modelviewClippingVolumeStack; - - typedef std::vector > ViewportStack; - ViewportStack _viewportStack; - - typedef std::vector EyePointStack; - EyePointStack _eyePointStack; - - typedef std::vector CullingModeStack; - CullingModeStack _cullingModeStack; - - unsigned int _bbCornerNear; - unsigned int _bbCornerFar; - - - osg::ref_ptr _rootRenderGraph; - RenderGraph* _currentRenderGraph; - - osg::ref_ptr _rootRenderStage; - RenderBin* _currentRenderBin; - - - float _LODBias; - - float _calculated_znear; - float _calculated_zfar; - - osg::ref_ptr _earthSky; - - TransparencySortMode _tsm; - - bool _impostorActive; - bool _depthSortImpostorSprites; - float _impostorPixelErrorThreshold; - int _numFramesToKeepImpostorSprites; - - typedef std::vector< osg::ref_ptr > MatrixList; - MatrixList _reuseMatrixList; - unsigned int _currentReuseMatrixIndex; - - inline osg::Matrix* createOrReuseMatrix() - { - // skip of any already reused matrix. - while (_currentReuseMatrixIndex<_reuseMatrixList.size() && - _reuseMatrixList[_currentReuseMatrixIndex]->referenceCount()>1) - { - osg::notify(osg::NOTICE)<<"Warning:createOrReuseMatrix() skipping multiply refrenced entry."<< std::endl; - ++_currentReuseMatrixIndex; - } - - // if still within list, element must be singularly referenced - // there return it to be reused. - if (_currentReuseMatrixIndex<_reuseMatrixList.size()) - { - osg::Matrix* matrix = _reuseMatrixList[_currentReuseMatrixIndex++].get(); - matrix->makeIdentity(); - return matrix; - } - - // otherwise need to create new matrix. - osg::Matrix* matrix = new osg::Matrix(); - _reuseMatrixList.push_back(matrix); - ++_currentReuseMatrixIndex; - return matrix; - } - - typedef std::vector< osg::ref_ptr > RenderLeafList; - RenderLeafList _reuseRenderLeafList; - unsigned int _currentReuseRenderLeafIndex; - - inline RenderLeaf* createOrReuseRenderLeaf(osg::Drawable* drawable,osg::Matrix* projection,osg::Matrix* matrix, float depth=0.0f) - { - // skip of any already reused renderleaf. - while (_currentReuseRenderLeafIndex<_reuseRenderLeafList.size() && - _reuseRenderLeafList[_currentReuseRenderLeafIndex]->referenceCount()>1) - { - osg::notify(osg::NOTICE)<<"Warning:createOrReuseRenderLeaf() skipping multiply refrenced entry."<< std::endl; - ++_currentReuseRenderLeafIndex; - } - - // if still within list, element must be singularly referenced - // there return it to be reused. - if (_currentReuseRenderLeafIndex<_reuseRenderLeafList.size()) - { - RenderLeaf* renderleaf = _reuseRenderLeafList[_currentReuseRenderLeafIndex++].get(); - renderleaf->set(drawable,projection,matrix,depth); - return renderleaf; - } - - // otherwise need to create new renderleaf. - RenderLeaf* renderleaf = new RenderLeaf(drawable,projection,matrix,depth); - _reuseRenderLeafList.push_back(renderleaf); - ++_currentReuseRenderLeafIndex; - return renderleaf; - } - - osg::ref_ptr _impostorSpriteManager; - -}; - -} - -#endif - diff --git a/src/osg/Image.cpp b/src/osg/Image.cpp index 91682e347..8665882d0 100644 --- a/src/osg/Image.cpp +++ b/src/osg/Image.cpp @@ -68,6 +68,79 @@ void Image::setFileName(const std::string& fileName) void Image::computePixelSize() { + + +// /* Data types */ + +// #define GL_BITMAP 0x1A00 + +// #define GL_BYTE 0x1400 +// #define GL_UNSIGNED_BYTE 0x1401 +// #define GL_SHORT 0x1402 +// #define GL_UNSIGNED_SHORT 0x1403 +// #define GL_INT 0x1404 +// #define GL_UNSIGNED_INT 0x1405 +// #define GL_FLOAT 0x1406 +// #define GL_DOUBLE 0x140A +// #define GL_2_BYTES 0x1407 +// #define GL_3_BYTES 0x1408 +// #define GL_4_BYTES 0x1409 +// +#ifndef GL_VERSION_1_1 + /* Internal texture formats (GL 1.1) */ + #define GL_ALPHA4 0x803B + #define GL_ALPHA8 0x803C + #define GL_ALPHA12 0x803D + #define GL_ALPHA16 0x803E + #define GL_LUMINANCE4 0x803F + #define GL_LUMINANCE8 0x8040 + #define GL_LUMINANCE12 0x8041 + #define GL_LUMINANCE16 0x8042 + #define GL_LUMINANCE4_ALPHA4 0x8043 + #define GL_LUMINANCE6_ALPHA2 0x8044 + #define GL_LUMINANCE8_ALPHA8 0x8045 + #define GL_LUMINANCE12_ALPHA4 0x8046 + #define GL_LUMINANCE12_ALPHA12 0x8047 + #define GL_LUMINANCE16_ALPHA16 0x8048 + #define GL_INTENSITY 0x8049 + #define GL_INTENSITY4 0x804A + #define GL_INTENSITY8 0x804B + #define GL_INTENSITY12 0x804C + #define GL_INTENSITY16 0x804D + #define GL_R3_G3_B2 0x2A10 + #define GL_RGB4 0x804F + #define GL_RGB5 0x8050 + #define GL_RGB8 0x8051 + #define GL_RGB10 0x8052 + #define GL_RGB12 0x8053 + #define GL_RGB16 0x8054 + #define GL_RGBA2 0x8055 + #define GL_RGBA4 0x8056 + #define GL_RGB5_A1 0x8057 + #define GL_RGBA8 0x8058 + #define GL_RGB10_A2 0x8059 + #define GL_RGBA12 0x805A + #define GL_RGBA16 0x805B +#endif + +#ifndef GL_VERSION_1_2 + /* 1.2 definitions...*/ + #define GL_BGR 0x80E0 + #define GL_BGRA 0x80E1 + #define GL_UNSIGNED_BYTE_3_3_2 0x8032 + #define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 + #define GL_UNSIGNED_SHORT_5_6_5 0x8363 + #define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 + #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 + #define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 + #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 + #define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 + #define GL_UNSIGNED_INT_8_8_8_8 0x8035 + #define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 + #define GL_UNSIGNED_INT_10_10_10_2 0x8036 + #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#endif + // temporary code.. to be filled in properly ASAP. RO. _pixelSizeInBits=32; } diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index c18c5dcdd..3be1d02f1 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -12,7 +12,7 @@ #include -#include +#include #include #include @@ -20,6 +20,8 @@ #include #include +#include + using namespace osg; using namespace osgUtil; @@ -72,318 +74,7 @@ class PrintVisitor : public NodeVisitor int _step; }; -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// SandB change to this - -struct TriangleViewFrustumIntersect -{ - //members ................. - - //the clipping volume, so that triangle vertices can be shecked if inside - osg::ClippingVolume _cv; - - //map serves not to have mulitple entries of same vertices - std::map _listVectors; - - //transformation matrix - const osg::Matrix* _t_mat; - - //value needed to set up triangles properly - double _current_near; - - //eye point of camera - osg::Vec3 _eye; - - osg::Vec3 _LeftUp; - osg::Vec3 _LeftDown; - osg::Vec3 _RightUp; - osg::Vec3 _RightDown; - - //constructor - TriangleViewFrustumIntersect( - const osg::ClippingVolume& clip_vol, - const osg::Matrix* matr, -// double current_near, - const osg::Vec3& eyePoint, - const osg::Vec3& LeftUp, - const osg::Vec3& LeftDown, - const osg::Vec3& RightUp, - const osg::Vec3& RightDown) - { - _cv = clip_vol; - _t_mat = matr; -// _current_near = current_near; - _eye = eyePoint; - _LeftUp = LeftUp; - _LeftDown = LeftDown; - _RightUp = RightUp; - _RightDown = RightDown; - } - - //pretty much the copy of IntersectVisitor intersect() function - int intersect_linesegment_and_triangle( - osg::Vec3& to_return, - const osg::LineSegment& ls, - const osg::Vec3& vertex1, - const osg::Vec3& vertex2, - const osg::Vec3& vertex3); - - void intersect_triangle(const osg::Vec3& vert1, const osg::Vec3& vert2, const osg::Vec3& vert3); - - //and crucial: - void operator() (const osg::Vec3& vert1, const osg::Vec3& vert2, const osg::Vec3& vert3) - { - intersect_triangle(vert1, vert2, vert3); - } -}; - - -//SandB added: pretty much copy of the IntersectVisitor intersection of traingle function -int TriangleViewFrustumIntersect::intersect_linesegment_and_triangle(osg::Vec3& to_return, - const osg::LineSegment& ls, - const osg::Vec3& v1, - const osg::Vec3& v2, - const osg::Vec3& v3) -{ - - if(v1 == v2 || v1 == v3 || v2 == v3) return -1; - - osg::Vec3 _s = ls.start(); - osg::Vec3 _d = ls.end() - ls.start(); - float _length = _d.length(); - _d /= _length; - - osg::Vec3 v12 = v2 - v1; - osg::Vec3 n12 = v12^_d; - - float ds12 = (_s-v1)*n12; - float d312 = (v3-v1)*n12; - if (d312>=0.0f) - { - if (ds12<0.0f) return 3; - if (ds12>d312) return 3; - } - else // d312 < 0 - { - if (ds12>0.0f) return 3; - if (ds12=0.0f) - { - if (ds23<0.0f) return 3; - if (ds23>d123) return 3; - } - else // d123 < 0 - { - if (ds23>0.0f) return 3; - if (ds23=0.0f) - { - if (ds31<0.0f) return 3; - if (ds31>d231) return 3; - } - else // d231 < 0 - { - if (ds31>0.0f) return 3; - if (ds31_length) return 2; - - return 0; -} - -void TriangleViewFrustumIntersect::intersect_triangle(const osg::Vec3& vert1, const osg::Vec3& vert2, const osg::Vec3& vert3) -{ - //if we have vertices in "transformed" coordinates, transform them to "global" coordinates - osg::Vec3 v1, v2, v3; - if(_t_mat) - { - v1 = vert1*(*_t_mat); - v2 = vert2*(*_t_mat); - v3 = vert3*(*_t_mat); - } - else - { - v1 = vert1; - v2 = vert2; - v3 = vert3; - } - - - //construct positions of truncated clipping volume corners - /* - osg::Vec3 UpLeft(_eye + _LeftUp * _current_near); - osg::Vec3 DownLeft(_eye + _LeftDown*_current_near); - osg::Vec3 UpRight(_eye + _RightUp*_current_near); - osg::Vec3 DownRight(_eye + _RightDown*_current_near); - */ - osg::Vec3 UpLeft(_eye + _LeftUp); - osg::Vec3 DownLeft(_eye + _LeftDown); - osg::Vec3 UpRight(_eye + _RightUp); - osg::Vec3 DownRight(_eye + _RightDown); - - - //construct truncation "back plane" - osg::Plane back_plane(DownLeft, DownRight, UpRight);//CCW, to have normal where it should be - - //add this plane to clipping volume - _cv.add(back_plane); - - //check if all three triangle vertices are contained in truncated clipping volume - unsigned int check = 0; - - //check if all three triangle vertices are behind truncation ("back") plane - unsigned int check2 = 0; - - if(back_plane.distance(v1) <= 0.0) - check2 |= 1; - else if(_cv.contains(v1)) //can not be contained if behind - { - _listVectors[v1] = true; - check |= 1; - } - - if(back_plane.distance(v2)<=0.0) - check2 |= 2; - else if(_cv.contains(v2)) - { - _listVectors[v2] = true; - check |= 2; - } - - if(back_plane.distance(v3) <= 0.0) - check2 |= 4; - else if(_cv.contains(v3)) - { - _listVectors[v3] = true; - check |= 4; - } - - if(check2 == 7) - { - //all three traingle vertices are behind truncation plane so no need to check them - //for heavily tesselated situation, htis is where most of tries will end - return; - } - - - - if(check != 7) - { - //just if it happens that all three are contained in truncated clipping volume, no need to do extra calculation - //(and they already are added to candidate vertices)) - - //at least one of the trianngle vertices is not contained in clipping volume, so extra checks are necessary - - //"working" variable - osg::Vec3 returned; - - //construct line segment of two triangle vertices and check if they intersect any clipping plane - //but within correct clipping plane triangle - osg::ref_ptr s12 = osgNew LineSegment(v1, v2); - - - //left triangle - if(intersect_linesegment_and_triangle(returned, *s12, _eye, UpLeft, DownLeft) == 0) - _listVectors[returned] = true; - - //up triangle - if(intersect_linesegment_and_triangle(returned, *s12, _eye, UpLeft, UpRight) == 0) - _listVectors[returned] = true; - - //right triangle - if(intersect_linesegment_and_triangle(returned, *s12, _eye, UpRight, DownRight) == 0) - _listVectors[returned] = true; - - //bottom triangled - if(intersect_linesegment_and_triangle(returned, *s12, _eye, DownLeft, DownRight) == 0) - _listVectors[returned] = true; - - //now for second edge of triangle - s12->set(v2, v3); - - //left triangle - if(intersect_linesegment_and_triangle(returned, *s12, _eye, UpLeft, DownLeft) == 0) - _listVectors[returned] = true; - - //up triangle - if(intersect_linesegment_and_triangle(returned, *s12, _eye, UpLeft, UpRight) == 0) - _listVectors[returned] = true; - - //right triangle - if(intersect_linesegment_and_triangle(returned, *s12, _eye, UpRight, DownRight) == 0) - _listVectors[returned] = true; - - //bottom triangled - if(intersect_linesegment_and_triangle(returned, *s12, _eye, DownLeft, DownRight) == 0) - _listVectors[returned] = true; - - s12->set(v3, v1); - - //left triangle - if(intersect_linesegment_and_triangle(returned, *s12, _eye, UpLeft, DownLeft) == 0) - _listVectors[returned] = true; - - //up triangle - if(intersect_linesegment_and_triangle(returned, *s12, _eye, UpLeft, UpRight) == 0) - _listVectors[returned] = true; - - //right triangle - if(intersect_linesegment_and_triangle(returned, *s12, _eye, UpRight, DownRight) == 0) - _listVectors[returned] = true; - - //bottom triangled - if(intersect_linesegment_and_triangle(returned, *s12, _eye, DownLeft, DownRight) == 0) - _listVectors[returned] = true; - - - //we still have possibility of camera being above huge triangle, so it is possible that clipping volume - //intersects this triangle thus giving coordinates relevant for determination of near plane - - s12->set(_eye, UpLeft); - - if(intersect_linesegment_and_triangle(returned, *s12, v1, v2, v3) == 0) - _listVectors[returned] = true; - - s12->set(_eye, DownLeft); - - if(intersect_linesegment_and_triangle(returned, *s12, v1, v2, v3) == 0) - _listVectors[returned] = true; - - s12->set(_eye, UpRight); - - if(intersect_linesegment_and_triangle(returned, *s12, v1, v2, v3) == 0) - _listVectors[returned] = true; - - s12->set(_eye, DownRight); - - if(intersect_linesegment_and_triangle(returned, *s12, v1, v2, v3) == 0) - _listVectors[returned] = true; - } -} - -CullVisitor::CullVisitor() +NewCullVisitor::NewCullVisitor() { // overide the default node visitor mode. setTraversalMode(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); @@ -397,61 +88,61 @@ CullVisitor::CullVisitor() // unless there is bug somewhere... _cullingModeStack.push_back(CullViewState::ENABLE_ALL_CULLING); - _tvs = osgNew CullViewState; - _tvs->_eyePoint.set(0.0f,0.0f,1.0f); - _tvs->_centerPoint.set(0.0f,0.0f,0.0f); - _tvs->_lookVector.set(0.0f,0.0f,-1.0f); - _tvs->_upVector.set(0.0f,1.0f,0.0f); - _cvs = _tvs; - - _tsm = LOOK_VECTOR_DISTANCE; + //_tsm = LOOK_VECTOR_DISTANCE; _tsm = OBJECT_EYE_POINT_DISTANCE; _calculated_znear = FLT_MAX; _calculated_zfar = -FLT_MAX; - _viewport = NULL; - _impostorActive = true; _depthSortImpostorSprites = false; _impostorPixelErrorThreshold = 4.0f; _numFramesToKeepImpostorSprites = 10; _impostorSpriteManager = osgNew ImpostorSpriteManager; - //SandB change - _detailedCulling = false; - } -CullVisitor::~CullVisitor() +NewCullVisitor::~NewCullVisitor() { reset(); } -void CullVisitor::reset() +void NewCullVisitor::reset() { // // first unref all referenced objects and then empty the containers. // - _viewStateStack.clear(); + _projectionStack.clear(); + _projectionClippingVolumeStack.clear(); + + _modelviewStack.clear(); + _modelviewClippingVolumeStack.clear(); + + _viewportStack.clear(); + + _eyePointStack.clear(); + + // remove all accept the first element of the stack. + _cullingModeStack.erase(_cullingModeStack.begin()+1,_cullingModeStack.end()); - if (_cvs!=_tvs) - { - _cvs = _tvs; - } // reset the calculated near far planes. _calculated_znear = FLT_MAX; _calculated_zfar = -FLT_MAX; - // remove all accept the first element of the stack. - _cullingModeStack.erase(_cullingModeStack.begin()+1,_cullingModeStack.end()); + osg::Vec3 lookVector(0.0,0.0,-1.0); + + _bbCornerFar = (lookVector.x()>=0?1:0) | + (lookVector.y()>=0?2:0) | + (lookVector.z()>=0?4:0); + + _bbCornerNear = (~_bbCornerFar)&7; // reset the resuse lists. _currentReuseMatrixIndex = 0; @@ -466,345 +157,135 @@ void CullVisitor::reset() } -void CullVisitor::setCamera(const Camera& camera) +void NewCullVisitor::pushClippingVolume() { - _camera = &camera; - - _tvs->_clippingVolume = camera.getClippingVolume(); - - _tvs->_eyePoint = camera.getEyePoint_Model(); - - _tvs->_centerPoint = camera.getCenterPoint_Model(); - - _tvs->_lookVector = _tvs->_centerPoint-_tvs->_eyePoint; - _tvs->_lookVector.normalize(); - - _tvs->_upVector = camera.getUpVector_Model(); - - _tvs->_bbCornerFar = (_tvs->_lookVector.x()>=0?1:0) | - (_tvs->_lookVector.y()>=0?2:0) | - (_tvs->_lookVector.z()>=0?4:0); - - _tvs->_bbCornerNear = (~_tvs->_bbCornerFar)&7; + _modelviewClippingVolumeStack.push_back(_projectionClippingVolumeStack.back()); + if (!_modelviewStack.empty()) _modelviewClippingVolumeStack.back().transformProvidingInverse(*_modelviewStack.back()); + _MVPW_Stack.push_back(0L); } -void CullVisitor::pushCullViewState_Projection(Matrix* matrix) +void NewCullVisitor::popClippingVolume() { - std::cout<<"CullVisitor::pushCullViewState_Projection(Matrix* matrix) not properly implemented yet..."<invert(*matrix); - pushCullViewState_ModelView(matrix,inverse); - } - else - pushCullViewState_ModelView(NULL,NULL); + _viewportStack.push_back(viewport); + _MVPW_Stack.push_back(0L); } -void CullVisitor::pushCullViewState_ModelView(Matrix* matrix,osg::Matrix* inverse) +void NewCullVisitor::popViewport() { + _viewportStack.pop_back(); + _MVPW_Stack.pop_back(); +} - osg::ref_ptr nvs = osgNew CullViewState; - - Matrix* inverse_world = NULL; - - if (matrix) - { - if (_cvs.valid() && _cvs->_matrix.valid()) - { - matrix->postMult(*(_cvs->_matrix)); - } - - nvs->_matrix = matrix; - - } - else - { - if (_cvs.valid()) - { - nvs->_matrix = _cvs->_matrix; - - } - else - { - nvs->_matrix = NULL; - } - } - - if (inverse) - { - if (_cvs.valid() && _cvs->_inverse.valid()) - { - inverse->preMult(*(_cvs->_inverse)); - } - - nvs->_inverse = inverse; - - } - else - { - if (_cvs.valid()) - { - nvs->_inverse = _cvs->_inverse; - } - else - { - nvs->_inverse = NULL; - } - } - inverse_world = nvs->_inverse.get(); +void NewCullVisitor::pushProjectionMatrix(Matrix* matrix) +{ + _projectionStack.push_back(matrix); - if (inverse_world) - { - nvs->_eyePoint = _tvs->_eyePoint*(*inverse_world); - //nvs->_eyePoint = inverse_world->getTrans(); - - nvs->_centerPoint = _tvs->_centerPoint*(*inverse_world); - - nvs->_lookVector = nvs->_centerPoint - nvs->_eyePoint; - nvs->_lookVector.normalize(); - - Vec3 zero_transformed = Vec3(0.0f,0.0f,0.0f)*(*inverse_world); - nvs->_upVector = (_tvs->_upVector)*(*inverse_world) - zero_transformed; - nvs->_upVector.normalize(); - - nvs->_clippingVolume = _tvs->_clippingVolume; - nvs->_clippingVolume.transformProvidingInverse(*(nvs->_matrix)); - - } - else - { - nvs->_eyePoint = _tvs->_eyePoint; - - nvs->_lookVector = _tvs->_lookVector; - - nvs->_centerPoint = _tvs->_centerPoint; - - nvs->_upVector = _tvs->_upVector; - - nvs->_clippingVolume = _tvs->_clippingVolume; - } - - - nvs->_bbCornerFar = (nvs->_lookVector.x()>=0?1:0) | - (nvs->_lookVector.y()>=0?2:0) | - (nvs->_lookVector.z()>=0?4:0); - - nvs->_bbCornerNear = (~nvs->_bbCornerFar)&7; - - _cvs = nvs; - - _viewStateStack.push_back(nvs); + _projectionClippingVolumeStack.push_back(ClippingVolume()); + _projectionClippingVolumeStack.back().setToUnitFrustumWithoutNearFar(); + _projectionClippingVolumeStack.back().transformProvidingInverse(*matrix); + + pushClippingVolume(); } -void CullVisitor::popCullViewState() +void NewCullVisitor::popProjectionMatrix() { - // pop the top of the view stack and unref it. - _viewStateStack.pop_back(); - - // to new cvs and ref it. - if (_viewStateStack.empty()) - { - _cvs = _tvs; - } - else - { - _cvs = _viewStateStack.back().get(); - } + _projectionStack.pop_back(); + _projectionClippingVolumeStack.pop_back(); + popClippingVolume(); } -double CullVisitor::calculateZNear(const osg::Vec3& position, const osg::Vec3& eye, const osg::Vec3& look) +void NewCullVisitor::pushModelViewMatrix(Matrix* matrix) { - //note: the candidate points are always in "global" coordinates - return (position - eye)*look; + _modelviewStack.push_back(matrix); + + pushClippingVolume(); + + // fast method for computing the eye point in local coords which doesn't require the inverse matrix. + const float x_0 = (*matrix)(0,0); + const float x_1 = (*matrix)(1,0); + const float x_2 = (*matrix)(2,0); + const float x_scale = (*matrix)(3,0) / -(x_0*x_0+x_1*x_1+x_2*x_2); + + const float y_0 = (*matrix)(0,1); + const float y_1 = (*matrix)(1,1); + const float y_2 = (*matrix)(2,1); + const float y_scale = (*matrix)(3,1) / -(y_0*y_0+y_1*y_1+y_2*y_2); + + const float z_0 = (*matrix)(0,2); + const float z_1 = (*matrix)(1,2); + const float z_2 = (*matrix)(2,2); + const float z_scale = (*matrix)(3,2) / -(z_0*z_0+z_1*z_1+z_2*z_2); + + _eyePointStack.push_back(osg::Vec3(x_0*x_scale + y_0*y_scale + z_0*z_scale, + x_1*x_scale + y_1*y_scale + z_1*z_scale, + x_2*x_scale + y_2*y_scale + z_2*z_scale)); + + + osg::Vec3 lookVector = getLookVectorLocal(); + + _bbCornerFar = (lookVector.x()>=0?1:0) | + (lookVector.y()>=0?2:0) | + (lookVector.z()>=0?4:0); + + _bbCornerNear = (~_bbCornerFar)&7; + } -void CullVisitor::calcClippingDirections() const +void NewCullVisitor::popModelViewMatrix() { - //need to calculate intersections of clipping planes - osg::Vec3 t_up = _camera->getUpVector(); - osg::Vec3 t_side = _camera->getSideVector(); + _modelviewStack.pop_back(); + _eyePointStack.pop_back(); + popClippingVolume(); - double pitch_up_angle = atan(_camera->top()/_camera->zNear()); - //we need to pitch up the cameras up vector for angle that is half fovy, -// osg::Vec3 pitched_up_up = t_up * osg::Matrix::rotate(t_VFOV_2, t_side.x(), t_side.y(), t_side.z()); - osg::Vec3 pitched_up_up = t_up * osg::Matrix::rotate(pitch_up_angle, t_side.x(), t_side.y(), t_side.z()); + osg::Vec3 lookVector(0.0f,0.0f,-1.0f); + if (!_modelviewStack.empty()) + { + lookVector = getLookVectorLocal(); + } + _bbCornerFar = (lookVector.x()>=0?1:0) | + (lookVector.y()>=0?2:0) | + (lookVector.z()>=0?4:0); - //we need also pitched down cameras up vector -// osg::Vec3 pitched_down_up = t_up * osg::Matrix::rotate(-t_VFOV_2, t_side.x(), t_side.y(), t_side.z()); - double pitch_down_angle = atan(_camera->bottom()/_camera->zNear()); -// osg::Vec3 pitched_down_up = t_up * osg::Matrix::rotate(-t_VFOV_2, t_side.x(), t_side.y(), t_side.z()); - osg::Vec3 pitched_down_up = t_up * osg::Matrix::rotate(pitch_down_angle, t_side.x(), t_side.y(), t_side.z()); - - //we need either left and right or up and down planes of clipping volume (their normals better said) - - osg::Vec4 temp_plane = _cvs.get()->_clippingVolume.getPlaneList()[0].asVec4();//take left - osg::Vec3 left(temp_plane.x(), temp_plane.y(), temp_plane.z()); - - temp_plane = _cvs.get()->_clippingVolume.getPlaneList()[1].asVec4();//take right - osg::Vec3 right(temp_plane.x(), temp_plane.y(), temp_plane.z()); - - //now, the line from eye along intersecion of left and up clipping planes is cross product of properly pitched up "up" vector and left - //clipping plane normal - _LeftUp = pitched_up_up^left; _LeftUp.normalize();//upper left line of clipping volume - _LeftDown = pitched_down_up^left; _LeftDown.normalize();//lower left line of clipping volume - _RightUp = right^pitched_up_up; _RightUp.normalize();//upper right line of clipping volume - _RightDown = right^pitched_down_up; _RightDown.normalize();//lower right line of clipping volume + _bbCornerNear = (~_bbCornerFar)&7; } -void CullVisitor::updateCalculatedNearFar(osg::Drawable* pDrawable) -{ - //new philosophy, to have detailed checking - - //do all the same as non-detailed update near and far - const BoundingBox& bb = pDrawable->getBound(); - - const osg::Vec3& eyePoint = _tvs->_eyePoint; // note world eye point. - const osg::Vec3& lookVector = _tvs->_lookVector; // world look vector. - - float d_near,d_far; - - if (_cvs->_matrix.valid()) - { - - const osg::Matrix& matrix = *(_cvs->_matrix); - // calculate the offset from the eye in local coords then transform - // the offset into world and then compare against the world look vector. - d_near = ((bb.corner(_cvs->_bbCornerNear)*matrix) - eyePoint)*lookVector; - d_far = ((bb.corner(_cvs->_bbCornerFar)*matrix) - eyePoint)*lookVector; - - } - else - { - d_near = (bb.corner(_cvs->_bbCornerNear)-eyePoint)*lookVector; - d_far = (bb.corner(_cvs->_bbCornerFar)-eyePoint)*lookVector; - } - - //this is where difference arises: check if near is less than zero: - - if(d_near >= 0.0) - { - //this is the same as before (non detailed: - if(d_near <= d_far) - { - if(d_near < _calculated_znear) _calculated_znear = d_near; - if(d_far > _calculated_zfar) _calculated_zfar = d_far; - } - else - { - if ( !EQUAL_F(d_near, d_far) ) - { - osg::notify(osg::WARN)<<"Warning: CullVisitor::updateCalculatedNearFar(.) near>far in range calculation,"<_matrix.valid()) + if (!_modelviewStack.empty()) { - const osg::Matrix& matrix = *(_cvs->_matrix); - d_near = distance(bb.corner(_cvs->_bbCornerNear),matrix); - d_far = distance(bb.corner(_cvs->_bbCornerFar),matrix); + const osg::Matrix& matrix = *(_modelviewStack.back()); + d_near = distance(bb.corner(_bbCornerNear),matrix); + d_far = distance(bb.corner(_bbCornerFar),matrix); } else { - d_near = -(bb.corner(_cvs->_bbCornerNear)).z(); - d_far = -(bb.corner(_cvs->_bbCornerFar)).z(); + d_near = -(bb.corner(_bbCornerNear)).z(); + d_far = -(bb.corner(_bbCornerFar)).z(); } if (d_near<=d_far) @@ -816,7 +297,7 @@ void CullVisitor::updateCalculatedNearFar(const osg::BoundingBox& bb) { if ( !EQUAL_F(d_near, d_far) ) { - osg::notify(osg::WARN)<<"Warning: CullVisitor::updateCalculatedNearFar(.) near>far in range calculation,"<< std::endl; + osg::notify(osg::WARN)<<"Warning: NewCullVisitor::updateCalculatedNearFar(.) near>far in range calculation,"<< std::endl; osg::notify(osg::WARN)<<" correcting by swapping values d_near="<_eyePoint; + Vec3 eye_world(0.0,0.0,0.0); Vec3 center_world = bs.center()*(*matrix); // no appropriate sprite has been found therefore need to create @@ -1402,14 +849,10 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node) clear_color[3] = 0.0f; // set the alpha to zero. rtts->setClearColor(clear_color); rtts->setClearMask(previous_stage->getClearMask()); - + // set up to charge the same RenderStageLighting is the parent previous stage. rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); - -// temporarily commeted out to keep things compiling. - osg::Camera* camera = osgNew osg::Camera(*_camera); -// rtts->setCamera(camera); -std::cout<<"Warning:: in createImpostorSprite() rtts->setCamera(camera) call has been removed, this will cause problems."<setCamera(camera) call has // set the current renderbin to be the newly created stage. _currentRenderBin = rtts.get(); - // store the previous camera setting - - Vec3 rotate_from = bs.center()-eye_local; - Vec3 rotate_to = getLookVectorLocal(); - - osg::Matrix* rotate_matrix = osgNew osg::Matrix( - osg::Matrix::translate(-eye_local)* - osg::Matrix::rotate(rotate_from,rotate_to)* - osg::Matrix::translate(eye_local)); - - // pushing the cull view state will update it so it takes - // into account the new camera orientation. - pushCullViewState_ModelView(rotate_matrix); - - // what shall we do about the near far? - // we could need to save the near and far, or switch it off. - // simplicist to save near and far. will do this for now. - - float previous_znear = _calculated_znear; - float previous_zfar = _calculated_zfar; - - _calculated_znear = FLT_MAX; - _calculated_zfar = -FLT_MAX; - - ref_ptr dummyState = osgNew StateSet; - - -// dummyState->setMode(GL_BLEND,osg::StateAttribute::OVERRIDE_OFF); - - pushStateSet(dummyState.get()); - - - // switch off the view frustum culling, since we will have - // the whole subgraph in view. - _cullingModeStack.push_back((_cullingModeStack.back() & ~CullViewState::VIEW_FRUSTUM_CULLING)); - - { - - // traversing the usual LOD selected child. - node.getChild(eval)->accept(*this); - - } - - popStateSet(); - - // restore the culling mode. - _cullingModeStack.pop_back(); - - float local_znear = _calculated_znear; - float local_zfar = _calculated_zfar; - - // restore the previous near and far. - _calculated_znear = previous_znear; - _calculated_zfar = previous_zfar; - - // restor the previous renderbin. - _currentRenderBin = previousRenderBin; - - // restore the previous _tvs and _cvs; - popCullViewState(); - - - if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0) - { - // getting to this point means that all the subgraph has been - // culled by small feature culling or is beyond LOD ranges. - return NULL; - } - - if (local_znear>local_zfar) - { - notify(WARN) << "Warning : problem with osg::CullVisitor::creatImpostorSprite() local_znear ("< ("<_upVector; + Vec3 camera_up_local = getUpLocal(); Vec3 lv_local = center_local-eye_local; float distance_local = lv_local.length(); @@ -1511,7 +878,7 @@ std::cout<<"Warning:: in createImpostorSprite() rtts->setCamera(camera) call has float width = bs.radius(); - if (isPerspectiveCamera) + if (isPerspectiveProjection) { // expand the width to account for projection onto sprite. width *= (distance_local/sqrtf(distance_local*distance_local-bs.radius2())); @@ -1529,55 +896,33 @@ std::cout<<"Warning:: in createImpostorSprite() rtts->setCamera(camera) call has // adjust camera left,right,up,down to fit (in world coords) -#define USE_SPHERE_NEAR_FAR - -#ifdef USE_SPHERE_NEAR_FAR Vec3 near_local ( center_local-lv_local*width ); Vec3 far_local ( center_local+lv_local*width ); -#endif Vec3 top_local ( center_local+up_local); Vec3 right_local ( center_local+sv_local); -#ifdef USE_SPHERE_NEAR_FAR Vec3 near_world; Vec3 far_world; -#endif Vec3 top_world; Vec3 right_world; if (matrix) { -#ifdef USE_SPHERE_NEAR_FAR near_world = near_local * (*matrix); far_world = far_local * (*matrix); -#endif top_world = top_local * (*matrix); right_world = right_local * (*matrix); } else { -#ifdef USE_SPHERE_NEAR_FAR near_world = near_local; far_world = far_local; -#endif top_world = top_local; right_world = right_local; } -#ifdef USE_SPHERE_NEAR_FAR float znear = (near_world-eye_world).length(); float zfar = (far_world-eye_world).length(); -#else - float znear = local_znear; - float zfar = local_zfar; -#endif - - if (local_zfar>=local_znear) - { - znear = local_znear; - zfar = local_zfar; - } - float top = (top_world-center_world).length(); float right = (right_world-center_world).length(); @@ -1585,62 +930,89 @@ std::cout<<"Warning:: in createImpostorSprite() rtts->setCamera(camera) call has znear *= 0.9f; zfar *= 1.1f; - if (isPerspectiveCamera) + // set up projection. + osg::Matrix* projection = osgNew osg::Matrix; + if (isPerspectiveProjection) { // deal with projection issue move the top and right points // onto the near plane. - float ratio = znear/(center_world-eye_world).length(); + float ratio = znear/(center_world-eye_world).length(); top *= ratio; right *= ratio; - camera->setFrustum(-right,right,-top,top,znear,zfar); - + projection->makeFrustum(-right,right,-top,top,znear,zfar); } else { - // othographic projection. - - camera->setOrtho(-right,right,-top,top,znear,zfar); + projection->makeOrtho(-right,right,-top,top,znear,zfar); } - - if (local_znear dummyState = osgNew StateSet; + + pushStateSet(dummyState.get()); + + + // switch off the view frustum culling, since we will have + // the whole subgraph in view. + _cullingModeStack.push_back((_cullingModeStack.back() & ~CullViewState::VIEW_FRUSTUM_CULLING)); + { - znear = local_znear; + + // traversing the usual LOD selected child. + node.getChild(eval)->accept(*this); + } - - if (local_zfar>zfar) + + // restore the culling mode. + _cullingModeStack.pop_back(); + + popStateSet(); + + // restore the previous model view matrix. + popModelViewMatrix(); + + // restore the previous model view matrix. + popProjectionMatrix(); + + // restore the previous renderbin. + _currentRenderBin = previousRenderBin; + + + + if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0) { - zfar = local_zfar; + // getting to this point means that all the subgraph has been + // culled by small feature culling or is beyond LOD ranges. + return NULL; } - // restore the previous near and far. - local_znear = previous_znear; - local_zfar = previous_zfar; -// calc texture size for eye, bs. - Vec3 c00_world; - Vec3 c11_world; - - if (matrix) - { - c00_world = c00 * (*matrix); - c11_world = c11 * (*matrix); - } - else - { - c00_world = c00; - c11_world = c11; - } + const osg::Viewport& viewport = *getViewport(); + // calc texture size for eye, bs. + // convert the corners of the sprite (in world coords) into their // equivilant window coordinates by using the camera's project method. - Vec3 c00_win; - Vec3 c11_win; - _camera->project(c00_world,*_viewport,c00_win); - _camera->project(c11_world,*_viewport,c11_win); - + const osg::Matrix& MVPW = getMVPW(); + Vec3 c00_win = c00 * MVPW; + Vec3 c11_win = c11 * MVPW; // adjust texture size to be nearest power of 2. @@ -1667,21 +1039,21 @@ std::cout<<"Warning:: in createImpostorSprite() rtts->setCamera(camera) call has int new_t = (int)(powf(2.0f,rounded_tp2)); // if dimension is bigger than window divide it down. - while (new_s>_viewport->width()) new_s /= 2; + while (new_s>viewport.width()) new_s /= 2; // if dimension is bigger than window divide it down. - while (new_t>_viewport->height()) new_t /= 2; + while (new_t>viewport.height()) new_t /= 2; // offset the impostor viewport from the center of the main window // viewport as often the edges of the viewport might be obscured by // other windows, which can cause image/reading writing problems. - int center_x = _viewport->x()+_viewport->width()/2; - int center_y = _viewport->y()+_viewport->height()/2; + int center_x = viewport.x()+viewport.width()/2; + int center_y = viewport.y()+viewport.height()/2; - Viewport* viewport = osgNew Viewport; - viewport->setViewport(center_x-new_s/2,center_y-new_t/2,new_s,new_t); - rtts->setViewport(viewport); + Viewport* new_viewport = osgNew Viewport; + new_viewport->setViewport(center_x-new_s/2,center_y-new_t/2,new_s,new_t); + rtts->setViewport(new_viewport); // create the impostor sprite. @@ -1726,7 +1098,7 @@ std::cout<<"Warning:: in createImpostorSprite() rtts->setCamera(camera) call has Vec3* controlcoords = impostorSprite->getControlCoords(); - if (isPerspectiveCamera) + if (isPerspectiveProjection) { // deal with projection issue by moving the coorners of the quad // towards the eye point. diff --git a/src/osgUtil/Makefile b/src/osgUtil/Makefile index 620209949..fee2ad37c 100644 --- a/src/osgUtil/Makefile +++ b/src/osgUtil/Makefile @@ -14,7 +14,6 @@ CXXFILES = \ FlightManipulator.cpp\ InsertImpostorsVisitor.cpp\ IntersectVisitor.cpp\ - NewCullVisitor.cpp\ NvTriStripObjects.cpp\ Optimizer.cpp\ RenderBin.cpp\ diff --git a/src/osgUtil/NewCullVisitor.cpp b/src/osgUtil/NewCullVisitor.cpp deleted file mode 100644 index 3be1d02f1..000000000 --- a/src/osgUtil/NewCullVisitor.cpp +++ /dev/null @@ -1,1143 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -#include - -#include -#include - -#include - -using namespace osg; -using namespace osgUtil; - -inline float MAX_F(float a, float b) - { return a>b?a:b; } -inline int EQUAL_F(float a, float b) - { return a == b || fabsf(a-b) <= MAX_F(fabsf(a),fabsf(b))*1e-3f; } - - -class PrintVisitor : public NodeVisitor -{ - - public: - - PrintVisitor():NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN) - { - _indent = 0; - _step = 4; - } - - inline void moveIn() { _indent += _step; } - inline void moveOut() { _indent -= _step; } - inline void writeIndent() - { - for(int i=0;i<_indent;++i) std::cout << " "; - } - - virtual void apply(Node& node) - { - moveIn(); - writeIndent(); std::cout << node.className() <=0?1:0) | - (lookVector.y()>=0?2:0) | - (lookVector.z()>=0?4:0); - - _bbCornerNear = (~_bbCornerFar)&7; - - // reset the resuse lists. - _currentReuseMatrixIndex = 0; - _currentReuseRenderLeafIndex = 0; - - for(RenderLeafList::iterator itr=_reuseRenderLeafList.begin(); - itr!=_reuseRenderLeafList.end(); - ++itr) - { - (*itr)->reset(); - } - -} - -void NewCullVisitor::pushClippingVolume() -{ - _modelviewClippingVolumeStack.push_back(_projectionClippingVolumeStack.back()); - if (!_modelviewStack.empty()) _modelviewClippingVolumeStack.back().transformProvidingInverse(*_modelviewStack.back()); - - _MVPW_Stack.push_back(0L); -} - -void NewCullVisitor::popClippingVolume() -{ - _modelviewClippingVolumeStack.pop_back(); - _MVPW_Stack.pop_back(); -} - -void NewCullVisitor::pushViewport(osg::Viewport* viewport) -{ - _viewportStack.push_back(viewport); - _MVPW_Stack.push_back(0L); -} - -void NewCullVisitor::popViewport() -{ - _viewportStack.pop_back(); - _MVPW_Stack.pop_back(); -} - -void NewCullVisitor::pushProjectionMatrix(Matrix* matrix) -{ - _projectionStack.push_back(matrix); - - _projectionClippingVolumeStack.push_back(ClippingVolume()); - _projectionClippingVolumeStack.back().setToUnitFrustumWithoutNearFar(); - _projectionClippingVolumeStack.back().transformProvidingInverse(*matrix); - - pushClippingVolume(); -} - -void NewCullVisitor::popProjectionMatrix() -{ - _projectionStack.pop_back(); - _projectionClippingVolumeStack.pop_back(); - - popClippingVolume(); -} - -void NewCullVisitor::pushModelViewMatrix(Matrix* matrix) -{ - _modelviewStack.push_back(matrix); - - pushClippingVolume(); - - // fast method for computing the eye point in local coords which doesn't require the inverse matrix. - const float x_0 = (*matrix)(0,0); - const float x_1 = (*matrix)(1,0); - const float x_2 = (*matrix)(2,0); - const float x_scale = (*matrix)(3,0) / -(x_0*x_0+x_1*x_1+x_2*x_2); - - const float y_0 = (*matrix)(0,1); - const float y_1 = (*matrix)(1,1); - const float y_2 = (*matrix)(2,1); - const float y_scale = (*matrix)(3,1) / -(y_0*y_0+y_1*y_1+y_2*y_2); - - const float z_0 = (*matrix)(0,2); - const float z_1 = (*matrix)(1,2); - const float z_2 = (*matrix)(2,2); - const float z_scale = (*matrix)(3,2) / -(z_0*z_0+z_1*z_1+z_2*z_2); - - _eyePointStack.push_back(osg::Vec3(x_0*x_scale + y_0*y_scale + z_0*z_scale, - x_1*x_scale + y_1*y_scale + z_1*z_scale, - x_2*x_scale + y_2*y_scale + z_2*z_scale)); - - - osg::Vec3 lookVector = getLookVectorLocal(); - - _bbCornerFar = (lookVector.x()>=0?1:0) | - (lookVector.y()>=0?2:0) | - (lookVector.z()>=0?4:0); - - _bbCornerNear = (~_bbCornerFar)&7; - -} - -void NewCullVisitor::popModelViewMatrix() -{ - _modelviewStack.pop_back(); - _eyePointStack.pop_back(); - popClippingVolume(); - - - osg::Vec3 lookVector(0.0f,0.0f,-1.0f); - if (!_modelviewStack.empty()) - { - lookVector = getLookVectorLocal(); - } - _bbCornerFar = (lookVector.x()>=0?1:0) | - (lookVector.y()>=0?2:0) | - (lookVector.z()>=0?4:0); - - _bbCornerNear = (~_bbCornerFar)&7; -} - -inline float distance(const osg::Vec3& coord,const osg::Matrix& matrix) -{ - return -(coord[0]*matrix(0,2)+coord[1]*matrix(1,2)+coord[2]*matrix(2,2)+matrix(3,2)); -} - - -void NewCullVisitor::updateCalculatedNearFar(const osg::BoundingBox& bb) -{ - - if (!bb.isValid()) - { - osg::notify(osg::WARN)<<"Warning: NewCullVisitor::updateCalculatedNearFar(..) passed a null bounding box."<< std::endl; - return; - } - - float d_near,d_far; - if (!_modelviewStack.empty()) - { - - const osg::Matrix& matrix = *(_modelviewStack.back()); - d_near = distance(bb.corner(_bbCornerNear),matrix); - d_far = distance(bb.corner(_bbCornerFar),matrix); - - } - else - { - d_near = -(bb.corner(_bbCornerNear)).z(); - d_far = -(bb.corner(_bbCornerFar)).z(); - } - - if (d_near<=d_far) - { - if (d_near<_calculated_znear) _calculated_znear = d_near; - if (d_far>_calculated_zfar) _calculated_zfar = d_far; - } - else - { - if ( !EQUAL_F(d_near, d_far) ) - { - osg::notify(osg::WARN)<<"Warning: NewCullVisitor::updateCalculatedNearFar(.) near>far in range calculation,"<< std::endl; - osg::notify(osg::WARN)<<" correcting by swapping values d_near="<accept(*this); - - // pop the node's state off the render graph stack. - if (node_state) popStateSet(); - - // pop the culling mode. - _cullingModeStack.pop_back(); -} - -void NewCullVisitor::apply(osg::EarthSky& node) -{ - // simply override the current earth sky. - setEarthSky(&node); - - // push the node's state. - StateSet* node_state = node.getStateSet(); - if (node_state) pushStateSet(node_state); - - traverse(node); - - // pop the node's state off the render graph stack. - if (node_state) popStateSet(); - -} - - -void NewCullVisitor::apply(Impostor& node) -{ - const BoundingSphere& bs = node.getBound(); - - // return if object's bounding sphere is culled. - CullViewState::CullingMode mode = _cullingModeStack.back(); - - if (!node.getCullingActive()) mode = 0; - else if (node.getNumChildrenWithCullingDisabled()==0 && - isCulled(node.getBound(),mode)) return; - - osg::Vec3 eyeLocal = getEyeLocal(); - - int eval = node.evaluate(eyeLocal,_LODBias); - if (eval<0){ - return; - } - - // push the culling mode. - _cullingModeStack.push_back(mode); - - // push the node's state. - StateSet* node_state = node.getStateSet(); - if (node_state) pushStateSet(node_state); - - - float distance2 = (eyeLocal-bs.center()).length2(); - if (!_impostorActive || - distance2*_LODBias*_LODBiasaccept(*this); - } - else if (_viewportStack.empty()) - { - // need to use impostor but no valid viewport is defined to simply - // default to using the LOD child as above. - node.getChild(eval)->accept(*this); - } - else - { - - // within the impostor distance threshold therefore attempt - // to use impostor instead. - - Matrix* matrix = getCurrentMatrix(); - - // search for the best fit ImpostorSprite; - ImpostorSprite* impostorSprite = node.findBestImpostorSprite(eyeLocal); - - if (impostorSprite) - { - // impostor found, now check to see if it is good enough to use - float error = impostorSprite->calcPixelError(getMVPW()); - - if (error>_impostorPixelErrorThreshold) - { - // chosen impostor sprite pixel error is too great to use - // from this eye point, therefore invalidate it. - impostorSprite=NULL; - } - } - - -// need to think about sprite reuse and support for multiple context's. - - if (impostorSprite==NULL) - { - // no appropriate sprite has been found therefore need to create - // one for use. - - // create the impostor sprite. - impostorSprite = createImpostorSprite(node); - - } - - if (impostorSprite) - { - - updateCalculatedNearFar(impostorSprite->getBound()); - - StateSet* stateset = impostorSprite->getStateSet(); - - if (stateset) pushStateSet(stateset); - - if (_depthSortImpostorSprites) - { - Vec3 center; - if (matrix) - { - center = node.getCenter()*(*matrix); - } - else - { - center = node.getCenter(); - } - - float depth; - switch(_tsm) - { - case(LOOK_VECTOR_DISTANCE):depth = -center.z();break; - case(OBJECT_EYE_POINT_DISTANCE): - default: depth = center.length2();break; - } - - addDrawableAndDepth(impostorSprite,matrix,depth); - } - else - { - addDrawable(impostorSprite,matrix); - } - - if (stateset) popStateSet(); - - // update frame number to show that impostor is in action. - impostorSprite->setLastFrameUsed(getTraversalNumber()); - - } - else - { - // no impostor has been selected or created so default to - // traversing the usual LOD selected child. - node.getChild(eval)->accept(*this); - } - - } - - // pop the node's state off the render graph stack. - if (node_state) popStateSet(); - - // pop the culling mode. - _cullingModeStack.pop_back(); -} - -ImpostorSprite* NewCullVisitor::createImpostorSprite(Impostor& node) -{ - - // default to true right now, will dertermine if perspective from the - // projection matrix... - bool isPerspectiveProjection = true; - - Matrix* matrix = getCurrentMatrix(); - const BoundingSphere& bs = node.getBound(); - osg::Vec3 eye_local = getEyeLocal(); - int eval = node.evaluate(eye_local,_LODBias); - - if (!bs.isValid()) - { - cout << "bb invalid"<<&node< rtts = osgNew RenderToTextureStage; - - // set up lighting. - // currently ignore lights in the scene graph itself.. - // will do later. - RenderStage* previous_stage = _currentRenderBin->_stage; - - // set up the background color and clear mask. - osg::Vec4 clear_color = previous_stage->getClearColor(); - clear_color[3] = 0.0f; // set the alpha to zero. - rtts->setClearColor(clear_color); - rtts->setClearMask(previous_stage->getClearMask()); - - // set up to charge the same RenderStageLighting is the parent previous stage. - rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); - - - // record the render bin, to be restored after creation - // of the render to text - RenderBin* previousRenderBin = _currentRenderBin; - - // set the current renderbin to be the newly created stage. - _currentRenderBin = rtts.get(); - - // create quad coords (in local coords) - - Vec3 center_local = bs.center(); - Vec3 camera_up_local = getUpLocal(); - Vec3 lv_local = center_local-eye_local; - - float distance_local = lv_local.length(); - lv_local /= distance_local; - - Vec3 sv_local = lv_local^camera_up_local; - sv_local.normalize(); - - Vec3 up_local = sv_local^lv_local; - - - - float width = bs.radius(); - if (isPerspectiveProjection) - { - // expand the width to account for projection onto sprite. - width *= (distance_local/sqrtf(distance_local*distance_local-bs.radius2())); - } - - // scale up and side vectors to sprite width. - up_local *= width; - sv_local *= width; - - // create the corners of the sprite. - Vec3 c00(center_local - sv_local - up_local); - Vec3 c10(center_local + sv_local - up_local); - Vec3 c01(center_local - sv_local + up_local); - Vec3 c11(center_local + sv_local + up_local); - -// adjust camera left,right,up,down to fit (in world coords) - - Vec3 near_local ( center_local-lv_local*width ); - Vec3 far_local ( center_local+lv_local*width ); - Vec3 top_local ( center_local+up_local); - Vec3 right_local ( center_local+sv_local); - - Vec3 near_world; - Vec3 far_world; - Vec3 top_world; - Vec3 right_world; - - if (matrix) - { - near_world = near_local * (*matrix); - far_world = far_local * (*matrix); - top_world = top_local * (*matrix); - right_world = right_local * (*matrix); - } - else - { - near_world = near_local; - far_world = far_local; - top_world = top_local; - right_world = right_local; - } - - float znear = (near_world-eye_world).length(); - float zfar = (far_world-eye_world).length(); - - float top = (top_world-center_world).length(); - float right = (right_world-center_world).length(); - - znear *= 0.9f; - zfar *= 1.1f; - - // set up projection. - osg::Matrix* projection = osgNew osg::Matrix; - if (isPerspectiveProjection) - { - // deal with projection issue move the top and right points - // onto the near plane. - float ratio = znear/(center_world-eye_world).length(); - top *= ratio; - right *= ratio; - projection->makeFrustum(-right,right,-top,top,znear,zfar); - } - else - { - projection->makeOrtho(-right,right,-top,top,znear,zfar); - } - - pushProjectionMatrix(projection); - - Vec3 rotate_from = bs.center()-eye_local; - Vec3 rotate_to = getLookVectorLocal(); - - osg::Matrix* rotate_matrix = osgNew osg::Matrix( - osg::Matrix::translate(-eye_local)* - osg::Matrix::rotate(rotate_from,rotate_to)* - osg::Matrix::translate(eye_local)* - getModelViewMatrix()); - - // pushing the cull view state will update it so it takes - // into account the new camera orientation. - pushModelViewMatrix(rotate_matrix); - - ref_ptr dummyState = osgNew StateSet; - - pushStateSet(dummyState.get()); - - - // switch off the view frustum culling, since we will have - // the whole subgraph in view. - _cullingModeStack.push_back((_cullingModeStack.back() & ~CullViewState::VIEW_FRUSTUM_CULLING)); - - { - - // traversing the usual LOD selected child. - node.getChild(eval)->accept(*this); - - } - - // restore the culling mode. - _cullingModeStack.pop_back(); - - popStateSet(); - - // restore the previous model view matrix. - popModelViewMatrix(); - - // restore the previous model view matrix. - popProjectionMatrix(); - - // restore the previous renderbin. - _currentRenderBin = previousRenderBin; - - - - if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0) - { - // getting to this point means that all the subgraph has been - // culled by small feature culling or is beyond LOD ranges. - return NULL; - } - - - - - const osg::Viewport& viewport = *getViewport(); - - - // calc texture size for eye, bs. - - // convert the corners of the sprite (in world coords) into their - // equivilant window coordinates by using the camera's project method. - const osg::Matrix& MVPW = getMVPW(); - Vec3 c00_win = c00 * MVPW; - Vec3 c11_win = c11 * MVPW; - -// adjust texture size to be nearest power of 2. - - float s = c11_win.x()-c00_win.x(); - float t = c11_win.y()-c00_win.y(); - - // may need to reverse sign of width or height if a matrix has - // been applied which flips the orientation of this subgraph. - if (s<0.0f) s = -s; - if (t<0.0f) t = -t; - - // bias value used to assist the rounding up or down of - // the texture dimensions to the nearest power of two. - // bias near 0.0 will almost always round down. - // bias near 1.0 will almost always round up. - float bias = 0.7f; - - float sp2 = logf((float)s)/logf(2.0f); - float rounded_sp2 = floorf(sp2+bias); - int new_s = (int)(powf(2.0f,rounded_sp2)); - - float tp2 = logf((float)t)/logf(2.0f); - float rounded_tp2 = floorf(tp2+bias); - int new_t = (int)(powf(2.0f,rounded_tp2)); - - // if dimension is bigger than window divide it down. - while (new_s>viewport.width()) new_s /= 2; - - // if dimension is bigger than window divide it down. - while (new_t>viewport.height()) new_t /= 2; - - - // offset the impostor viewport from the center of the main window - // viewport as often the edges of the viewport might be obscured by - // other windows, which can cause image/reading writing problems. - int center_x = viewport.x()+viewport.width()/2; - int center_y = viewport.y()+viewport.height()/2; - - Viewport* new_viewport = osgNew Viewport; - new_viewport->setViewport(center_x-new_s/2,center_y-new_t/2,new_s,new_t); - rtts->setViewport(new_viewport); - -// create the impostor sprite. - - ImpostorSprite* impostorSprite = - _impostorSpriteManager->createOrReuseImpostorSprite(new_s,new_t,getTraversalNumber()-_numFramesToKeepImpostorSprites); - - if (impostorSprite==NULL) return NULL; - - // have successfully created an impostor sprite so now need to - // add it into the impostor. - node.addImpostorSprite(impostorSprite); - - if (_depthSortImpostorSprites) - { - // the depth sort bin should probably be user definable, - // will look into this later. RO July 2001. - StateSet* stateset = impostorSprite->getStateSet(); - stateset->setRenderBinDetails(1,"DepthSortedBin"); - } - - Texture* texture = impostorSprite->getTexture(); - - // update frame number to show that impostor is in action. - impostorSprite->setLastFrameUsed(getTraversalNumber()); - - Vec3* coords = impostorSprite->getCoords(); - Vec2* texcoords = impostorSprite->getTexCoords(); - - coords[0] = c01; - texcoords[0].set(0.0f,1.0f); - - coords[1] = c00; - texcoords[1].set(0.0f,0.0f); - - coords[2] = c10; - texcoords[2].set(1.0f,0.0f); - - coords[3] = c11; - texcoords[3].set(1.0f,1.0f); - - impostorSprite->dirtyBound(); - - Vec3* controlcoords = impostorSprite->getControlCoords(); - - if (isPerspectiveProjection) - { - // deal with projection issue by moving the coorners of the quad - // towards the eye point. - float ratio = width/(center_local-eye_local).length(); - float one_minus_ratio = 1.0f-ratio; - Vec3 eye_local_ratio = eye_local*ratio; - - controlcoords[0] = coords[0]*one_minus_ratio + eye_local_ratio; - controlcoords[1] = coords[1]*one_minus_ratio + eye_local_ratio; - controlcoords[2] = coords[2]*one_minus_ratio + eye_local_ratio; - controlcoords[3] = coords[3]*one_minus_ratio + eye_local_ratio; - } - else - { - // project the control points forward towards the eyepoint, - // but since this an othographics projection this projection is - // parallel. - Vec3 dv = lv_local*width; - - controlcoords[0] = coords[0]-dv; - controlcoords[1] = coords[1]-dv; - controlcoords[2] = coords[2]-dv; - controlcoords[3] = coords[3]-dv; - } - - impostorSprite->setStoredLocalEyePoint(eye_local); - - - // and the render to texture stage to the current stages - // dependancy list. - _currentRenderBin->_stage->addToDependencyList(rtts.get()); - - // attach texture to the RenderToTextureStage. - rtts->setTexture(texture); - - // must sort the RenderToTextureStage so that all leaves are - // accounted correctly in all renderbins i.e depth sorted bins. - rtts->sort(); - - return impostorSprite; - -}