From e80496d5dba20440847b36666af930308f7ed7b6 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 14 Mar 2002 16:01:21 +0000 Subject: [PATCH] Changed Texture so that is use lazy updating on texture paramters (Filter/Wrap) mode by using a _texParamtersDirty flag in combination with an applyTexParamters(State&) method which does the paramters setting in one tidy bundle. This new implementations replaces the CompileFlags submitted yesterday. Simplified NodeCallback by remove osg::NodeCallback::Requirements as they are no longer needed. Fixed comments in Drawable. Put guards around cosf definations so that they are only used under Win32/Mac. Fixed warning in CullVisitor. --- include/osg/Drawable | 8 ++-- include/osg/Math | 85 +++++++++++++++++----------------- include/osg/NodeCallback | 19 +------- include/osg/Texture | 40 +++++++--------- src/osg/Texture.cpp | 80 +++++++++++++++----------------- src/osgPlugins/osg/Texture.cpp | 2 + src/osgUtil/CullVisitor.cpp | 69 ++++++++++++++------------- 7 files changed, 139 insertions(+), 164 deletions(-) diff --git a/include/osg/Drawable b/include/osg/Drawable index f09bab9e1..9cfe6e8c1 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -177,10 +177,10 @@ class SG_EXPORT Drawable : public Object /** Set the DrawCallback which allows users to attach customize the drawing of existing Drawable object.*/ void setDrawCallback(DrawCallback* dc) { _drawCallback=dc; dirtyDisplayList(); } - /** Get the non const ComputerTransfromCallback.*/ + /** Get the non const DrawCallback.*/ DrawCallback* getDrawCallback() { return _drawCallback.get(); } - /** Get the const ComputerTransfromCallback.*/ + /** Get the const DrawCallback.*/ const DrawCallback* getDrawCallback() const { return _drawCallback.get(); } struct CullCallback : public osg::Referenced @@ -194,10 +194,10 @@ class SG_EXPORT Drawable : public Object /** Set the CullCallback which allows users to attach customize the drawing of existing Drawable object.*/ void setCullCallback(CullCallback* cc) { _cullCallback=cc; } - /** Get the non const ComputerTransfromCallback.*/ + /** Get the non const CullCallback.*/ CullCallback* getCullCallback() { return _cullCallback.get(); } - /** Get the const ComputerTransfromCallback.*/ + /** Get the const CullCallback.*/ const CullCallback* getCullCallback() const { return _cullCallback.get(); } diff --git a/include/osg/Math b/include/osg/Math index ba32e6d3a..80ef32d3f 100644 --- a/include/osg/Math +++ b/include/osg/Math @@ -8,51 +8,52 @@ #include #if defined(WIN32) || defined (macintosh) + #include + + + // PJA MAC OSX + // This appears to be the simplest way to get these defined under MACOSX + // where they arent in math.h + + #ifndef acosf + #define acosf (float)acos + #endif + + #ifndef asinf + #define asinf (float)asin + #endif + + #ifndef cosf + #define cosf (float)cos + #endif + + #ifndef sinf + #define sinf (float)sin + #endif + + #ifndef logf + #define logf (float)log + #endif + + #ifndef floorf + #define floorf (float)floor + #endif + + #ifndef powf + #define powf (float)pow + #endif + + #ifndef sqrtf + #define sqrtf (float)sqrt + #endif + + #ifndef fabsf + #define fabsf (float)fabs + #endif + #endif - -// PJA MAC OSX -// This appears to be the simplest way to get these defined under MACOSX -// where they arent in math.h - -#ifndef acosf -#define acosf (float)acos -#endif - -#ifndef asinf -#define asinf (float)asin -#endif - -#ifndef cosf -#define cosf (float)cos -#endif - -#ifndef sinf -#define sinf (float)sin -#endif - -#ifndef logf -#define logf (float)log -#endif - -#ifndef floorf -#define floorf (float)floor -#endif - -#ifndef powf -#define powf (float)pow -#endif - -#ifndef sqrtf -#define sqrtf (float)sqrt -#endif - -#ifndef fabsf -#define fabsf (float)fabs -#endif - - namespace osg { // define the stand trig values diff --git a/include/osg/NodeCallback b/include/osg/NodeCallback index e6bb7f297..d9a2719e1 100644 --- a/include/osg/NodeCallback +++ b/include/osg/NodeCallback @@ -16,26 +16,11 @@ class SG_EXPORT NodeCallback : public Referenced { public : - /** The range of values which can be accumulated by the NodeVisitor. */ - enum Requirements - { - NO_REQUIREMENTS = 0x0, - REQUIRES_TRAVERSAL = 0x1, - REQUIRES_PARENT_PATH = 0x2, - REQUIRES_ACCUMULATED_MATRIX = 0x4, - REQUIRES_ACCUMULATED_INVERSE = 0x8 - }; - NodeCallback(const Requirements ncr=NO_REQUIREMENTS):_requirements(ncr) {} + NodeCallback(){} virtual ~NodeCallback() {} - /** Set what values from traversal are required by this NodeCallback.*/ - inline void setRequirements(const Requirements ncr) { _requirements=ncr; } - - /** Get what values from traversal are required by this NodeCallback.*/ - inline const Requirements getRequirements() const { return _requirements; } - /** Callback method call by the NodeVisitor when visiting a node.*/ virtual void operator()(Node*, NodeVisitor*) {} @@ -80,8 +65,6 @@ class SG_EXPORT NodeCallback : public Referenced { public: - Requirements _requirements; - ref_ptr _nestedCallback; }; diff --git a/include/osg/Texture b/include/osg/Texture index 62e55db8e..a018c08bb 100644 --- a/include/osg/Texture +++ b/include/osg/Texture @@ -87,6 +87,7 @@ class SG_EXPORT Texture : public StateAttribute _wrap_r(text._wrap_r), _min_filter(text._min_filter), _mag_filter(text._mag_filter), + _texParamtersDirty(false), _internalFormatMode(text._internalFormatMode), _internalFormatValue(text._internalFormatValue), _borderColor(text._borderColor), @@ -150,9 +151,9 @@ class SG_EXPORT Texture : public StateAttribute enum WrapMode { CLAMP = GL_CLAMP, CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, + CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER_ARB, REPEAT = GL_REPEAT, - MIRROR = GL_MIRRORED_REPEAT_IBM, - CLAMP_TO_BORDER_ARB = GL_CLAMP_TO_BORDER_ARB + MIRROR = GL_MIRRORED_REPEAT_IBM }; /** Set the texture wrap mode.*/ @@ -161,6 +162,13 @@ class SG_EXPORT Texture : public StateAttribute const WrapMode getWrap(const WrapParameter which) const; + /** Sets the border color for this texture. Makes difference only if + * wrap mode is CLAMP_TO_BORDER */ + void setBorderColor(const Vec4& color) { _borderColor = color; _texParamtersDirty = true; } + + const Vec4& borderColor(void) const { return _borderColor; } + + enum FilterParameter { MIN_FILTER, MAG_FILTER @@ -182,22 +190,6 @@ class SG_EXPORT Texture : public StateAttribute /** Get the texture filter mode.*/ const FilterMode getFilter(const FilterParameter which) const; - enum CompileFlags { - COMPILE_NONE = 0x0, - COMPILE_MAG_FILTER = 0x1, - COMPILE_MIN_FILTER = 0x2, - COMPILE_WRAP_S = 0x4, - COMPILE_WRAP_T = 0x8, - COMPILE_ALL = 0xFF - }; - - /** Set the compile flags. Whatever is set will be compiled - ** when the texture object is built. Otherwise, immediate mode - ** setting of these modes will occur during the apply - **/ - void setCompileFlags( const CompileFlags compile_flags ) { _compile_flags = compile_flags; } - const CompileFlags getCompileFlags( void ) const { return _compile_flags; } - enum InternalFormatMode { USE_IMAGE_DATA_FORMAT, @@ -299,10 +291,6 @@ class SG_EXPORT Texture : public StateAttribute * does not set or use texture binding. */ virtual void applyImmediateMode(State& state) const; - /** Sets the border color for this texture. Makes difference only if - * wrap mode is CLAMP_TO_BORDER_ARB */ - void setBorderColor(const Vec4& color) {_borderColor = color;} - const Vec4& borderColor(void) const {return _borderColor;} /** use deleteTextureObject instead of glDeleteTextures to allow @@ -320,6 +308,9 @@ class SG_EXPORT Texture : public StateAttribute virtual ~Texture(); + + void applyTexParameters(State& state) const; + typedef std::vector TextureNameList; mutable TextureNameList _handleList; @@ -329,6 +320,7 @@ class SG_EXPORT Texture : public StateAttribute // size of the created OpenGL texture object, may be estimated. mutable uint _textureObjectSize; + // not ideal that _image is mutable, but its required since // Image::ensureDimensionsArePowerOfTwo() can only be called // in a valid OpenGL context, a therefore within an Texture::apply @@ -344,7 +336,9 @@ class SG_EXPORT Texture : public StateAttribute FilterMode _min_filter; FilterMode _mag_filter; - CompileFlags _compile_flags; + // true if apply tex parameters required. + mutable bool _texParamtersDirty; + InternalFormatMode _internalFormatMode; int _internalFormatValue; diff --git a/src/osg/Texture.cpp b/src/osg/Texture.cpp index c5f94a017..fdad18829 100644 --- a/src/osg/Texture.cpp +++ b/src/osg/Texture.cpp @@ -43,7 +43,7 @@ Texture::Texture() _borderColor.set(0.0, 0.0, 0.0, 0.0);//OpenGL default - _compile_flags = COMPILE_ALL; + _texParamtersDirty = true; } @@ -121,11 +121,12 @@ void Texture::setWrap(const WrapParameter which, const WrapMode wrap) { switch( which ) { - case WRAP_S : _wrap_s = wrap; break; - case WRAP_T : _wrap_t = wrap; break; - case WRAP_R : _wrap_r = wrap; break; + case WRAP_S : _wrap_s = wrap; _texParamtersDirty = true; break; + case WRAP_T : _wrap_t = wrap; _texParamtersDirty = true; break; + case WRAP_R : _wrap_r = wrap; _texParamtersDirty = true; break; default : notify(WARN)<<"Error: invalid 'which' passed Texture::setWrap("<<(unsigned int)which<<","<<(unsigned int)wrap<<")"<data()) { @@ -210,6 +204,7 @@ void Texture::apply(State& state) const (_subloadMode == IF_DIRTY && modifiedTag != _image->getModifiedTag())) { glBindTexture( GL_TEXTURE_2D, handle ); + if (_texParamtersDirty) applyTexParameters(state); glTexSubImage2D(GL_TEXTURE_2D, 0, _subloadOffsX, _subloadOffsY, _image->s(), _image->t(), @@ -243,25 +238,8 @@ void Texture::compile(State& state) const } -void Texture::applyImmediateMode(State& state) const +void Texture::applyTexParameters(State&) const { - // if we don't have a valid image we can't create a texture! - if (!_image.valid() || !_image->data()) - return; - - // get the contextID (user defined ID of 0 upwards) for the - // current OpenGL context. - const uint contextID = state.getContextID(); - - // update the modified tag to show that it is upto date. - getModifiedTag(contextID) = _image->getModifiedTag(); - - - if (_subloadMode == OFF) - _image->ensureDimensionsArePowerOfTwo(); - - glPixelStorei(GL_UNPACK_ALIGNMENT,_image->packing()); - WrapMode ws = _wrap_s, wt = _wrap_t; // GL_IBM_texture_mirrored_repeat, fall-back REPEAT @@ -287,9 +265,9 @@ void Texture::applyImmediateMode(State& state) const static bool s_borderClampSupported = isGLExtensionSupported("GL_ARB_texture_border_clamp"); if(!s_borderClampSupported) { - if(ws == CLAMP_TO_BORDER_ARB) + if(ws == CLAMP_TO_BORDER) ws = CLAMP; - if(wt == CLAMP_TO_BORDER_ARB) + if(wt == CLAMP_TO_BORDER) wt = CLAMP; } @@ -328,6 +306,30 @@ void Texture::applyImmediateMode(State& state) const glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _mag_filter); } + _texParamtersDirty=false; + +} + +void Texture::applyImmediateMode(State& state) const +{ + // if we don't have a valid image we can't create a texture! + if (!_image.valid() || !_image->data()) + return; + + // get the contextID (user defined ID of 0 upwards) for the + // current OpenGL context. + const uint contextID = state.getContextID(); + + // update the modified tag to show that it is upto date. + getModifiedTag(contextID) = _image->getModifiedTag(); + + + if (_subloadMode == OFF) + _image->ensureDimensionsArePowerOfTwo(); + + glPixelStorei(GL_UNPACK_ALIGNMENT,_image->packing()); + + applyTexParameters(state); static bool s_ARB_Compression = isGLExtensionSupported("GL_ARB_texture_compression"); static bool s_S3TC_Compression = isGLExtensionSupported("GL_EXT_texture_compression_s3tc"); @@ -549,10 +551,7 @@ void Texture::copyTexImage2D(State& state, int x, int y, int width, int height ) glGenTextures( 1, &handle ); glBindTexture( GL_TEXTURE_2D, handle ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _wrap_s ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _wrap_t ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _min_filter ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _mag_filter ); + applyTexParameters(state); glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, width, height, 0 ); @@ -579,10 +578,7 @@ void Texture::copyTexSubImage2D(State& state, int xoffset, int yoffset, int x, i { // we have a valid image glBindTexture( GL_TEXTURE_2D, handle ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _wrap_s ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _wrap_t ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _min_filter ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _mag_filter ); + applyTexParameters(state); glCopyTexSubImage2D( GL_TEXTURE_2D, 0, xoffset,yoffset, x, y, width, height); /* Redundant, delete later */ diff --git a/src/osgPlugins/osg/Texture.cpp b/src/osgPlugins/osg/Texture.cpp index d56ee8468..fa157e65e 100644 --- a/src/osgPlugins/osg/Texture.cpp +++ b/src/osgPlugins/osg/Texture.cpp @@ -174,6 +174,7 @@ bool Texture_matchWrapStr(const char* str,Texture::WrapMode& wrap) { if (strcmp(str,"CLAMP")==0) wrap = Texture::CLAMP; else if (strcmp(str,"CLAMP_TO_EDGE")==0) wrap = Texture::CLAMP_TO_EDGE; + else if (strcmp(str,"CLAMP_TO_BORDER")==0) wrap = Texture::CLAMP_TO_BORDER; else if (strcmp(str,"REPEAT")==0) wrap = Texture::REPEAT; else if (strcmp(str,"MIRROR")==0) wrap = Texture::MIRROR; else return false; @@ -187,6 +188,7 @@ const char* Texture_getWrapStr(Texture::WrapMode wrap) { case(Texture::CLAMP): return "CLAMP"; case(Texture::CLAMP_TO_EDGE): return "CLAMP_TO_EDGE"; + case(Texture::CLAMP_TO_BORDER): return "CLAMP_TO_BORDER"; case(Texture::REPEAT): return "REPEAT"; case(Texture::MIRROR): return "MIRROR"; } diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index f2d25c55f..5a96cbd2c 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -228,19 +228,19 @@ void TriangleViewFrustumIntersect::intersect_triangle(const osg::Vec3& vert1, co 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 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 @@ -624,18 +624,17 @@ void CullVisitor::calcClippingDirections() const osg::Vec3 t_up = _camera->getUpVector(); osg::Vec3 t_side = _camera->getSideVector(); - double t_VFOV_2 = osg::DegreesToRadians(_camera->calc_fovy() * 0.5);//half of vertical FOV in radians - double pitch_up_angle = atan(_camera->top()/_camera->zNear()); + 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 pitched_up_up = t_up * osg::Matrix::rotate(pitch_up_angle, t_side.x(), t_side.y(), t_side.z()); //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()); + 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) @@ -721,33 +720,33 @@ void CullVisitor::updateCalculatedNearFar(osg::Drawable* pDrawable) current_near = _calculated_zfar * current_near; else current_near = 10000.0;//something must be put - double mult_factor; - if(_calculated_znear != FLT_MAX)//just in case this is the very first entry (i.e. the first bounding box contained eyePoint of camera + double mult_factor; + if(_calculated_znear != FLT_MAX)//just in case this is the very first entry (i.e. the first bounding box contained eyePoint of camera mult_factor = _calculated_znear * current_near;//this is side of triangle ... else if(_calculated_zfar != -FLT_MAX) mult_factor = _calculated_zfar * current_near; else mult_factor = 10000.0;//something must be put - double LUdistance = _LeftUp*lookVector; - LUdistance = mult_factor / LUdistance; + double LUdistance = _LeftUp*lookVector; + LUdistance = mult_factor / LUdistance; - double LDdistance = _LeftDown*lookVector; - LDdistance = mult_factor / LDdistance; + double LDdistance = _LeftDown*lookVector; + LDdistance = mult_factor / LDdistance; - double RUdistance = _RightUp*lookVector; - RUdistance = mult_factor / RUdistance; + double RUdistance = _RightUp*lookVector; + RUdistance = mult_factor / RUdistance; - double RDdistance = _RightDown*lookVector; - RDdistance = mult_factor / RDdistance; + double RDdistance = _RightDown*lookVector; + RDdistance = mult_factor / RDdistance; //construct functor: needs clipping volume, matrix, and current near, while some members for speed are kept in CullVisitor since //they need be calculated only once per frame - /* + /* TriangleViewFrustumIntersect ti(_cvs->_clippingVolume, _cvs->_matrix.get(), current_near, eyePoint, _LeftUp,_LeftDown,_RightUp,_RightDown); - */ - TriangleViewFrustumIntersect ti(_cvs->_clippingVolume, + */ + TriangleViewFrustumIntersect ti(_cvs->_clippingVolume, _cvs->_matrix.get(), eyePoint, _LeftUp*LUdistance,_LeftDown*LDdistance,_RightUp*RUdistance,_RightDown*RDdistance); @@ -886,7 +885,7 @@ void CullVisitor::apply(Geode& node) if (!node.getCullingActive()) mode = 0; else if (node.getNumChildrenWithCullingDisabled()==0 && - isCulled(node.getBound(),mode)) return; + isCulled(node.getBound(),mode)) return; // push the node's state. StateSet* node_state = node.getStateSet(); @@ -898,19 +897,19 @@ void CullVisitor::apply(Geode& node) Drawable* drawable = node.getDrawable(i); const BoundingBox &bb =drawable->getBound(); - if( drawable->getCullCallback() ) - { - if( drawable->getCullCallback()->cull( this, drawable ) == true ) - continue; - } - else - { + if( drawable->getCullCallback() ) + { + if( drawable->getCullCallback()->cull( this, drawable ) == true ) + continue; + } + else + { if (isCulled(bb,mode)) continue; - } + } //SandB change: -// updateCalculatedNearFar(bb); + // updateCalculatedNearFar(bb); if(_detailedCulling) { updateCalculatedNearFar(drawable); @@ -923,7 +922,7 @@ void CullVisitor::apply(Geode& node) // push the geoset's state on the geostate stack. StateSet* stateset = drawable->getStateSet(); - + bool isTransparent = stateset && stateset->getRenderingHint()==osg::StateSet::TRANSPARENT_BIN; if (isTransparent) {