diff --git a/include/osg/ImpostorSprite b/include/osg/ImpostorSprite index 7e2c26016..1fb42e9e1 100644 --- a/include/osg/ImpostorSprite +++ b/include/osg/ImpostorSprite @@ -102,9 +102,9 @@ class SG_EXPORT ImpostorSprite : public Drawable inline const Vec3* getControlCoords() const { return _controlcoords; } - /** calculate the pixel error value for current camera position and object position.*/ - const float calcPixelError(const Camera& camera,const Viewport& viewport,const osg::Matrix* matrix) const; - + /** calculate the pixel error value for passing in the ModelViewProjectionWindow transform, + * which transform local coords into screen space.*/ + const float ImpostorSprite::calcPixelError(const Matrix& MVPW) const; void setTexture(Texture* tex,int s,int t); diff --git a/include/osg/Matrix b/include/osg/Matrix index 10b985a60..f281a6f59 100644 --- a/include/osg/Matrix +++ b/include/osg/Matrix @@ -88,9 +88,35 @@ class SG_EXPORT Matrix : public Object void makeRotate( float angle, float x, float y, float z ); void makeRotate( const Quat& ); void makeRotate( float, float, float ); //Euler angles + + + /** Set to a orthographic projection. See glOrtho for further details.*/ + void makeOrtho(const double left, const double right, + const double bottom, const double top, + const double zNear, const double zFar); + + /** Set to a 2D orthographic projection. See glOrtho2D for further details.*/ + inline void makeOrtho2D(const double left, const double right, + const double bottom, const double top) + { + makeOrtho(left,right,bottom,top,-1.0,1.0); + } + + /** Set to a perspective projection. See glFrustum for further details.*/ + void makeFrustum(const double left, const double right, + const double bottom, const double top, + const double zNear, const double zFar); + + /** Set to a symmetrical perspective projection, See gluPerspective for further details. + * Aspect ratio is defined as width/height.*/ + void makePerspective(const double fovy,const double aspectRatio, + const double zNear, const double zFar); + + /** Set to the position and orientation as per a camera, using the same convention as gluLookAt. */ + void makeLookAt(const Vec3& eye,const Vec3& center,const Vec3& up); + bool invert( const Matrix& ); - bool invertAffine( const Matrix& ); //basic utility functions to create new matrices inline static Matrix identity( void ); @@ -101,7 +127,30 @@ class SG_EXPORT Matrix : public Object inline static Matrix rotate( const Vec3&, const Vec3& ); inline static Matrix rotate( float, float, float, float ); inline static Matrix rotate( float angle, const Vec3& axis); - inline static Matrix rotate( const Quat& ); + inline static Matrix rotate( const Quat&); + + /** Create a orthographic projection. See glOrtho for further details.*/ + inline static Matrix ortho(const double left, const double right, + const double bottom, const double top, + const double zNear, const double zFar); + + /** Create a 2D orthographic projection. See glOrtho for further details.*/ + inline static Matrix ortho2D(const double left, const double right, + const double bottom, const double top); + + /** Create a perspective projection. See glFrustum for further details.*/ + inline static Matrix frustum(const double left, const double right, + const double bottom, const double top, + const double zNear, const double zFar); + + /** Create a symmetrical perspective projection, See gluPerspective for further details. + * Aspect ratio is defined as width/height.*/ + inline static Matrix perspective(const double fovy,const double aspectRatio, + const double zNear, const double zFar); + + /** Create the position and orientation as per a camera, using the same convention as gluLookAt. */ + inline static Matrix lookAt(const Vec3& eye,const Vec3& center,const Vec3& up); + inline Vec3 preMult( const Vec3& v ) const; inline Vec3 postMult( const Vec3& v ) const; @@ -227,6 +276,48 @@ inline Matrix Matrix::rotate(const Vec3& from, const Vec3& to ) return m; } +inline Matrix Matrix::ortho(const double left, const double right, + const double bottom, const double top, + const double zNear, const double zFar) +{ + Matrix m; + m.makeOrtho(left,right,bottom,top,zNear,zFar); + return m; +} + +inline Matrix Matrix::ortho2D(const double left, const double right, + const double bottom, const double top) +{ + Matrix m; + m.makeOrtho2D(left,right,bottom,top); + return m; +} + +inline Matrix Matrix::frustum(const double left, const double right, + const double bottom, const double top, + const double zNear, const double zFar) +{ + Matrix m; + m.makeFrustum(left,right,bottom,top,zNear,zFar); + return m; +} + +inline Matrix Matrix::perspective(const double fovy,const double aspectRatio, + const double zNear, const double zFar) +{ + Matrix m; + m.makePerspective(fovy,aspectRatio,zNear,zFar); + return m; +} + +inline Matrix Matrix::lookAt(const Vec3& eye,const Vec3& center,const Vec3& up) +{ + Matrix m; + m.makeLookAt(eye,center,up); + return m; +} + + inline Vec3 Matrix::postMult( const Vec3& v ) const { float d = 1.0f/(_mat[3][0]*v.x()+_mat[3][1]*v.y()+_mat[3][2]*v.z()+_mat[3][3]) ; diff --git a/include/osgUtil/NewCullVisitor b/include/osgUtil/NewCullVisitor index f0344e6ac..2e060d014 100644 --- a/include/osgUtil/NewCullVisitor +++ b/include/osgUtil/NewCullVisitor @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -60,12 +59,6 @@ class OSGUTIL_EXPORT NewCullVisitor : 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 NewCullVisitor : public osg::NodeVisitor CullViewState::CullingMode getCullingMode() const; - /** Set the viewport. - * Used to enable the NewCullVisitor 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 @@ -202,55 +185,56 @@ class OSGUTIL_EXPORT NewCullVisitor : 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 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& getUpLocal() const + inline const osg::Vec3 NewCullVisitor::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); - /**calculates near for "global" vertex in scene*/ - double calculateZNear(const osg::Vec3& position, const osg::Vec3& eye, const osg::Vec3& look); - - /** Add a drawable to current render graph.*/ inline void addDrawable(osg::Drawable* drawable,osg::Matrix* matrix) { @@ -262,7 +246,7 @@ class OSGUTIL_EXPORT NewCullVisitor : 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.*/ @@ -276,7 +260,7 @@ class OSGUTIL_EXPORT NewCullVisitor : 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.*/ @@ -289,33 +273,125 @@ class OSGUTIL_EXPORT NewCullVisitor : public osg::NodeVisitor * to generate the impostor texture. */ osg::ImpostorSprite* createImpostorSprite(osg::Impostor& node); - 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/RenderStage b/include/osgUtil/RenderStage index c0c06a4f6..4c744ed21 100644 --- a/include/osgUtil/RenderStage +++ b/include/osgUtil/RenderStage @@ -5,7 +5,6 @@ #ifndef OSGUTIL_RENDERSTAGE #define OSGUTIL_RENDERSTAGE 1 -#include #include #include @@ -92,12 +91,6 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin /** Get the clear color.*/ const int getClearStencil() const { return _clearStencil; } - - void setCamera(osg::Camera* camera) { _camera = camera; } - osg::Camera* getCamera() { return _camera.get(); } - const osg::Camera* getCamera() const { return _camera.get(); } - - void setRenderStageLighting(RenderStageLighting* rsl) { _renderStageLighting = rsl; } RenderStageLighting* getRenderStageLighting() const @@ -125,8 +118,6 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin bool _stageDrawnThisFrame; DependencyList _dependencyList; - osg::ref_ptr _camera; - // viewport x,y,width,height. osg::ref_ptr _viewport; diff --git a/src/osg/ImpostorSprite.cpp b/src/osg/ImpostorSprite.cpp index a37997826..90ec9aff4 100644 --- a/src/osg/ImpostorSprite.cpp +++ b/src/osg/ImpostorSprite.cpp @@ -40,31 +40,16 @@ ImpostorSprite::~ImpostorSprite() } } -const float ImpostorSprite::calcPixelError(const Camera& camera,const Viewport& viewport,const osg::Matrix* matrix) const +const float ImpostorSprite::calcPixelError(const Matrix& MVPW) const { // find the maximum screen space pixel error between the control coords and the quad coners. float max_error_sqrd = 0.0f; + for(int i=0;i<4;++i) { - Vec3 projected_coord; - Vec3 projected_control; - if (matrix) - { - // project the coords of the quad into screen space. - camera.project(_coords[i]*(*matrix),viewport,projected_coord); - - // project the controls coords into screen space. - camera.project(_controlcoords[i]*(*matrix),viewport,projected_control); - } - else - { - // project the coords of the quad into screen space. - camera.project(_coords[i],viewport,projected_coord); - - // project the controls coords into screen space. - camera.project(_controlcoords[i],viewport,projected_control); - } + Vec3 projected_coord = _coords[i]*MVPW; + Vec3 projected_control = _controlcoords[i]*MVPW; float dx = (projected_coord.x()-projected_control.x()); float dy = (projected_coord.y()-projected_control.y()); @@ -77,7 +62,6 @@ const float ImpostorSprite::calcPixelError(const Camera& camera,const Viewport& return sqrtf(max_error_sqrd); } - void ImpostorSprite::drawImmediateMode(State&) { // when the tex env is set to REPLACE, and the diff --git a/src/osg/Matrix.cpp b/src/osg/Matrix.cpp index 5c837b3ae..ff97383e5 100644 --- a/src/osg/Matrix.cpp +++ b/src/osg/Matrix.cpp @@ -227,7 +227,6 @@ void Matrix::postMult( const Matrix& other ) } } -#undef SET_ROW #undef INNER_PRODUCT @@ -310,24 +309,51 @@ bool Matrix::invert( const Matrix& mat ) return true; } -bool Matrix::invertAffine( const Matrix& mat) +void Matrix::makeOrtho(const double left, const double right, + const double bottom, const double top, + const double zNear, const double zFar) { - // | R p |' | R' -R'p |' - // | | -> | | - // | 0 0 0 1 | | 0 0 0 1 | - for (unsigned int i=0; i<3; i++) - { - operator()(i,3) = 0; - operator()(3,i) = -(mat(i,0)*mat(3,0) + - mat(i,1)*mat(3,1) + - mat(i,2)*mat(3,2)); - for (unsigned int j=0; j<3; j++) - { - operator()(i,j) = mat(j,i); - } - } - operator()(3,3) = 1; - - return true; + // note transpose of Matrix wr.t OpenGL documentation, since the OSG use post multiplication rather than pre. + double tx = -(right+left)/(right-left); + double ty = -(top+bottom)/(top-bottom); + double tz = -(zFar+zNear)/(zFar-zNear); + SET_ROW(0, 2.0f/(right-left), 0.0f, 0.0f, 0.0f ) + SET_ROW(1, 0.0f, 2.0f/(top-bottom), 0.0f, 0.0f ) + SET_ROW(2, 0.0f, 0.0f, -2.0f/(zFar-zNear), 0.0f ) + SET_ROW(3, tx, ty, tz, 1.0f ) } +void Matrix::makeFrustum(const double left, const double right, + const double bottom, const double top, + const double zNear, const double zFar) +{ + // note transpose of Matrix wr.t OpenGL documentation, since the OSG use post multiplication rather than pre. + double A = (right+left)/(right-left); + double B = (top+bottom)/(top-bottom); + double C = -(zFar+zNear)/(zFar-zNear); + double D = -2.0*zFar*zNear/(zFar-zNear); + SET_ROW(0, 2.0f*zNear/(right-left), 0.0f, 0.0f, 0.0f ) + SET_ROW(1, 0.0f, 2.0f*zNear/(top-bottom), 0.0f, 0.0f ) + SET_ROW(2, A, B, C, -1.0f ) + SET_ROW(3, 0.0f, 0.0f, D, 0.0f ) +} + + +void Matrix::makePerspective(const double fovy,const double aspectRatio, + const double zNear, const double zFar) +{ + // calculate the appropriate left, right etc. + double tan_fovy = tan(DegreesToRadians(fovy*0.5)); + double right = tan_fovy * aspectRatio * zNear; + double left = -right; + double top = tan_fovy * zNear; + double bottom = -top; + makeFrustum(left,right,bottom,top,zNear,zFar); +} + + +void Matrix::makeLookAt(const Vec3& eye,const Vec3& center,const Vec3& up) +{ +} + +#undef SET_ROW diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 32e75edce..c18c5dcdd 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -1280,8 +1280,11 @@ void CullVisitor::apply(Impostor& node) if (impostorSprite) { // impostor found, now check to see if it is good enough to use - float error = impostorSprite->calcPixelError(*_camera,*_viewport,matrix); - + // RO, commenting this out since the calcPixelError's calling convention + // has changed, this version of CullVisitor is soon to be removed + // so this shouldn't be a problem. + //float error = impostorSprite->calcPixelError(*_camera,*_viewport,matrix); + float error = 0.0f; if (error>_impostorPixelErrorThreshold) { // chosen impostor sprite pixel error is too great to use @@ -1403,9 +1406,10 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node) // set up to charge the same RenderStageLighting is the parent previous stage. rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); - - osg::Camera* camera = osgNew osg::Camera(*_camera); - rtts->setCamera(camera); +// 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."< #include +#include + using namespace osg; using namespace osgUtil; @@ -86,23 +88,14 @@ NewCullVisitor::NewCullVisitor() // 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; @@ -124,20 +117,32 @@ 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; @@ -152,188 +157,105 @@ void NewCullVisitor::reset() } -void NewCullVisitor::setCamera(const Camera& camera) +void NewCullVisitor::pushClippingVolume() { - _camera = &camera; - - _tvs->_clippingVolume.setToUnitFrustumWithoutNearFar(); - _tvs->_clippingVolume.transformProvidingInverse(_camera->getModelViewMatrix()*_camera->getProjectionMatrix()); - - //_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 NewCullVisitor::pushCullViewState_Projection(Matrix* matrix) +void NewCullVisitor::popClippingVolume() { - std::cout<<"NewCullVisitor::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 NewCullVisitor::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)); - -// osg::ClippingVolume cv; -// cv.setToUnitFrustum(); -// cv.transformProvidingInverse((*(nvs->_matrix))*_camera->getProjectionMatrix()); -// -// std::cout << "cv "<_clippingVolume "<_clippingVolume.getPlaneList().begin(); -// itr!=nvs->_clippingVolume.getPlaneList().end(); -// ++itr) -// { -// std::cout << " Plane "<<*itr<_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 NewCullVisitor::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 NewCullVisitor::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 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) @@ -352,18 +274,18 @@ void NewCullVisitor::updateCalculatedNearFar(const osg::BoundingBox& bb) } float d_near,d_far; - if (_cvs->_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) @@ -388,9 +310,9 @@ void NewCullVisitor::updateCalculatedNearFar(const osg::BoundingBox& bb) void NewCullVisitor::updateCalculatedNearFar(const osg::Vec3& pos) { float d; - if (_cvs->_matrix.valid()) + if (!_modelviewStack.empty()) { - const osg::Matrix& matrix = *(_cvs->_matrix); + const osg::Matrix& matrix = *(_modelviewStack.back()); d = distance(pos,matrix); } else @@ -487,14 +409,13 @@ void NewCullVisitor::apply(Geode& node) { center = drawable->getBound().center(); } - Vec3 delta_center = center-_tvs->_eyePoint; float depth; switch(_tsm) { - case(LOOK_VECTOR_DISTANCE):depth = _tvs->_lookVector*delta_center;break; + case(LOOK_VECTOR_DISTANCE):depth = -center.z();break; case(OBJECT_EYE_POINT_DISTANCE): - default: depth = delta_center.length2();break; + default: depth = center.length2();break; } if (stateset) pushStateSet(stateset); @@ -567,14 +488,13 @@ void NewCullVisitor::apply(Billboard& node) { center = pos; } - Vec3 delta_center = center-_tvs->_eyePoint; float depth; switch(_tsm) { - case(LOOK_VECTOR_DISTANCE):depth = _tvs->_lookVector*delta_center;break; + case(LOOK_VECTOR_DISTANCE):depth = -center.z();break; case(OBJECT_EYE_POINT_DISTANCE): - default: depth = delta_center.length2();break; + default: depth = center.length2();break; } if (stateset) pushStateSet(stateset); @@ -657,14 +577,13 @@ void NewCullVisitor::apply(Transform& node) if (node_state) pushStateSet(node_state); ref_ptr matrix = createOrReuseMatrix(); - ref_ptr inverse = createOrReuseMatrix(); node.getLocalToWorldMatrix(*matrix,this); - node.getWorldToLocalMatrix(*inverse,this); - pushCullViewState_ModelView(matrix.get(),inverse.get()); + matrix->postMult(*getCurrentMatrix()); + pushModelViewMatrix(matrix.get()); traverse(node); - popCullViewState(); + popModelViewMatrix(); // pop the node's state off the render graph stack. if (node_state) popStateSet(); @@ -691,11 +610,11 @@ void NewCullVisitor::apply(Projection& node) ref_ptr matrix = createOrReuseMatrix(); *matrix = node.getMatrix(); - pushCullViewState_Projection(matrix.get()); + pushProjectionMatrix(matrix.get()); traverse(node); - popCullViewState(); + popProjectionMatrix(); // pop the node's state off the render graph stack. if (node_state) popStateSet(); @@ -791,7 +710,7 @@ void NewCullVisitor::apply(Impostor& node) // traverse the appropriate child of the LOD. node.getChild(eval)->accept(*this); } - else if (!_viewport.valid()) + else if (_viewportStack.empty()) { // need to use impostor but no valid viewport is defined to simply // default to using the LOD child as above. @@ -799,6 +718,7 @@ void NewCullVisitor::apply(Impostor& node) } else { + // within the impostor distance threshold therefore attempt // to use impostor instead. @@ -810,8 +730,8 @@ void NewCullVisitor::apply(Impostor& node) if (impostorSprite) { // impostor found, now check to see if it is good enough to use - float error = impostorSprite->calcPixelError(*_camera,*_viewport,matrix); - + float error = impostorSprite->calcPixelError(getMVPW()); + if (error>_impostorPixelErrorThreshold) { // chosen impostor sprite pixel error is too great to use @@ -853,14 +773,13 @@ void NewCullVisitor::apply(Impostor& node) { center = node.getCenter(); } - Vec3 delta_center = center-_tvs->_eyePoint; float depth; switch(_tsm) { - case(LOOK_VECTOR_DISTANCE):depth = _tvs->_lookVector*delta_center;break; + case(LOOK_VECTOR_DISTANCE):depth = -center.z();break; case(OBJECT_EYE_POINT_DISTANCE): - default: depth = delta_center.length2();break; + default: depth = center.length2();break; } addDrawableAndDepth(impostorSprite,matrix,depth); @@ -878,8 +797,8 @@ void NewCullVisitor::apply(Impostor& node) } else { - // no impostor has been selected or created so default to - // traversing the usual LOD selected child. + // no impostor has been selected or created so default to + // traversing the usual LOD selected child. node.getChild(eval)->accept(*this); } @@ -894,10 +813,10 @@ void NewCullVisitor::apply(Impostor& node) ImpostorSprite* NewCullVisitor::createImpostorSprite(Impostor& node) { - if (!_camera.valid()) return NULL; - - bool isPerspectiveCamera = _camera->getProjectionType()==Camera::FRUSTUM || - _camera->getProjectionType()==Camera::PERSPECTIVE; + + // default to true right now, will dertermine if perspective from the + // projection matrix... + bool isPerspectiveProjection = true; Matrix* matrix = getCurrentMatrix(); const BoundingSphere& bs = node.getBound(); @@ -906,11 +825,12 @@ ImpostorSprite* NewCullVisitor::createImpostorSprite(Impostor& node) if (!bs.isValid()) { + cout << "bb invalid"<<&node<_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 @@ -929,13 +849,10 @@ ImpostorSprite* NewCullVisitor::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()); - - - osg::Camera* camera = osgNew osg::Camera(*_camera); - rtts->setCamera(camera); + // record the render bin, to be restored after creation // of the render to text @@ -944,86 +861,10 @@ ImpostorSprite* NewCullVisitor::createImpostorSprite(Impostor& node) // 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::NewCullVisitor::creatImpostorSprite() local_znear ("< ("<_upVector; + Vec3 camera_up_local = getUpLocal(); Vec3 lv_local = center_local-eye_local; float distance_local = lv_local.length(); @@ -1037,7 +878,7 @@ ImpostorSprite* NewCullVisitor::createImpostorSprite(Impostor& node) 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())); @@ -1055,55 +896,33 @@ ImpostorSprite* NewCullVisitor::createImpostorSprite(Impostor& node) // 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(); @@ -1111,62 +930,89 @@ ImpostorSprite* NewCullVisitor::createImpostorSprite(Impostor& node) 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. @@ -1193,21 +1039,21 @@ ImpostorSprite* NewCullVisitor::createImpostorSprite(Impostor& node) 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. @@ -1252,7 +1098,7 @@ ImpostorSprite* NewCullVisitor::createImpostorSprite(Impostor& node) 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/RenderLeaf.cpp b/src/osgUtil/RenderLeaf.cpp index d1c23a4f8..323fe54ae 100644 --- a/src/osgUtil/RenderLeaf.cpp +++ b/src/osgUtil/RenderLeaf.cpp @@ -30,7 +30,7 @@ void RenderLeaf::render(State& state,RenderLeaf* previous) } - //state.applyProjectionMatrix(_projection.get()); + state.applyProjectionMatrix(_projection.get()); state.applyModelViewMatrix(_modelview.get()); _drawable->draw(state); @@ -42,7 +42,7 @@ void RenderLeaf::render(State& state,RenderLeaf* previous) // send state changes and matrix changes to OpenGL. state.apply(_parent->_stateset.get()); - //state.applyProjectionMatrix(_projection.get()); + state.applyProjectionMatrix(_projection.get()); state.applyModelViewMatrix(_modelview.get()); _drawable->draw(state); diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index 45f67ffe4..74aba9c40 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -97,9 +97,6 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous) glDisable( GL_SCISSOR_TEST ); #endif - // set up projection - state.applyProjectionMatrix(&(_camera->getProjectionMatrix())); - glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index baffc1a3a..07c7b531b 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -233,6 +233,7 @@ void SceneView::cullStage(osg::Camera* camera, osgUtil::CullVisitor* cullVisitor } // get the camera's modelview + osg::Matrix* projection = osgNew osg::Matrix(camera->getProjectionMatrix()); osg::Matrix* modelview = osgNew osg::Matrix(camera->getModelViewMatrix()); @@ -243,8 +244,6 @@ void SceneView::cullStage(osg::Camera* camera, osgUtil::CullVisitor* cullVisitor cullVisitor->setLODBias(_lodBias); - cullVisitor->setCamera(*local_camera); - cullVisitor->setViewport(_viewport.get()); cullVisitor->setEarthSky(NULL); // reset earth sky on each frame. cullVisitor->setRenderGraph(rendergraph); @@ -266,7 +265,6 @@ void SceneView::cullStage(osg::Camera* camera, osgUtil::CullVisitor* cullVisitor rendergraph->clean(); renderStage->setViewport(_viewport.get()); - renderStage->setCamera(local_camera); renderStage->setClearColor(_backgroundColor); @@ -285,7 +283,9 @@ void SceneView::cullStage(osg::Camera* camera, osgUtil::CullVisitor* cullVisitor if (_globalState.valid()) cullVisitor->pushStateSet(_globalState.get()); - cullVisitor->pushCullViewState_ModelView(modelview); + cullVisitor->pushViewport(_viewport.get()); + cullVisitor->pushProjectionMatrix(projection); + cullVisitor->pushModelViewMatrix(modelview); // traverse the scene graph to generate the rendergraph. @@ -293,7 +293,9 @@ void SceneView::cullStage(osg::Camera* camera, osgUtil::CullVisitor* cullVisitor if (_globalState.valid()) cullVisitor->popStateSet(); - cullVisitor->popCullViewState(); + cullVisitor->popModelViewMatrix(); + cullVisitor->popProjectionMatrix(); + cullVisitor->popViewport(); const osg::EarthSky* earthSky = cullVisitor->getEarthSky();