diff --git a/OgreMain/include/OgreInstanceBatch.h b/OgreMain/include/OgreInstanceBatch.h index 2462a019552..954841b4ab3 100644 --- a/OgreMain/include/OgreInstanceBatch.h +++ b/OgreMain/include/OgreInstanceBatch.h @@ -127,6 +127,8 @@ namespace Ogre /// False if a technique doesn't support skeletal animation bool mTechnSupportsSkeletal; + /// Last update camera distance frame number + mutable unsigned long mCameraDistLastUpdateFrameNumber; /// Cached distance to last camera for getSquaredViewDepth mutable Real mCachedCameraDist; /// The camera for which the cached distance is valid diff --git a/OgreMain/include/OgreMath.h b/OgreMain/include/OgreMath.h index 851a75ea1fb..61b332a1d99 100644 --- a/OgreMain/include/OgreMath.h +++ b/OgreMain/include/OgreMath.h @@ -366,7 +366,7 @@ namespace Ogre static inline double saturate(double t) { return (t < 0) ? 0 : ((t > 1) ? 1 : t); } //Simulate the shader function lerp which performers linear interpolation - //given 3 parameters v0, v1 and t the function returns the value of (1 – t)* v0 + t * v1. + //given 3 parameters v0, v1 and t the function returns the value of (1 � t)* v0 + t * v1. //where v0 and v1 are matching vector or scalar types and t can be either a scalar or a vector of the same type as a and b. template static V lerp(const V& v0, const V& v1, const T& t) { return v0 * (1 - t) + v1 * t; } @@ -696,9 +696,11 @@ namespace Ogre static Matrix4 makeViewMatrix(const Vector3& position, const Quaternion& orientation, const Matrix4* reflectMatrix = 0); - /** Get a bounding radius value from a bounding box. */ + /** Get the radius of the origin-centered bounding sphere from the bounding box. */ static Real boundingRadiusFromAABB(const AxisAlignedBox& aabb); + /** Get the radius of the bbox-centered bounding sphere from the bounding box. */ + static Real boundingRadiusFromAABBCentered(const AxisAlignedBox &aabb); static const Real POS_INFINITY; diff --git a/OgreMain/src/OgreInstanceBatch.cpp b/OgreMain/src/OgreInstanceBatch.cpp index 7bd7a364977..df54543a262 100644 --- a/OgreMain/src/OgreInstanceBatch.cpp +++ b/OgreMain/src/OgreInstanceBatch.cpp @@ -34,6 +34,9 @@ THE SOFTWARE. #include "OgreCamera.h" #include "OgreException.h" #include "OgreRenderQueue.h" +#include "OgreLodListener.h" +#include "OgreSceneManager.h" +#include "OgreRoot.h" namespace Ogre { @@ -158,7 +161,7 @@ namespace Ogre mFullBoundingBox.setMinimum(mFullBoundingBox.getMinimum() - addToBound); - mBoundingRadius = Math::boundingRadiusFromAABB( mFullBoundingBox ); + mBoundingRadius = Math::boundingRadiusFromAABBCentered( mFullBoundingBox ); mBoundsDirty = false; } @@ -487,9 +490,9 @@ namespace Ogre //We use our own because our SceneNode is just filled with zeroes, and updating it //with real values is expensive, plus we would need to make sure it doesn't get to //the shader - Real depth = Math::Sqrt( getSquaredViewDepth(cam) ) - - mMeshReference->getBoundingSphereRadius(); + Real depth = Math::Sqrt(getSquaredViewDepth(cam)) - getBoundingRadius(); depth = std::max( depth, Real(0) ); + Real lodValue = depth * cam->_getLodBiasInverse(); //Now calculate Material LOD @@ -513,10 +516,52 @@ namespace Ogre //Notify LOD event listeners cam->getSceneManager()->_notifyEntityMaterialLodChanged(subEntEvt);*/ - //Change LOD index + // Change LOD index mMaterialLodIndex = idx; - MovableObject::_notifyCurrentCamera( cam ); + mBeyondFarDistance = false; + + if (cam->getUseRenderingDistance() && mUpperDistance > 0) + { + if (depth > mUpperDistance) + mBeyondFarDistance = true; + } + + if (!mBeyondFarDistance && cam->getUseMinPixelSize() && mMinPixelSize > 0) + { + Real pixelRatio = cam->getPixelDisplayRatio(); + + Ogre::Vector3 objBound = + getBoundingBox().getSize() * getParentNode()->_getDerivedScale(); + objBound.x = Math::Sqr(objBound.x); + objBound.y = Math::Sqr(objBound.y); + objBound.z = Math::Sqr(objBound.z); + float sqrObjMedianSize = std::max( + std::max(std::min(objBound.x, objBound.y), std::min(objBound.x, objBound.z)), + std::min(objBound.y, objBound.z)); + + // If we have a perspective camera calculations are done relative to distance + Real sqrDistance = 1; + + if (cam->getProjectionType() == PT_PERSPECTIVE) + sqrDistance = getSquaredViewDepth(cam->getLodCamera()); // it's ok + + mBeyondFarDistance = + sqrObjMedianSize < sqrDistance * Math::Sqr(pixelRatio * mMinPixelSize); + } + + if (mParentNode) + { + MovableObjectLodChangedEvent evt; + evt.movableObject = this; + evt.camera = cam; + + cam->getSceneManager()->_notifyMovableObjectLodChanged(evt); + } + + mRenderingDisabled = mListener && !mListener->objectRendering(this, cam); + + // MovableObject::_notifyCurrentCamera( cam ); // it does not suit } //----------------------------------------------------------------------- const AxisAlignedBox& InstanceBatch::getBoundingBox(void) const @@ -531,21 +576,15 @@ namespace Ogre //----------------------------------------------------------------------- Real InstanceBatch::getSquaredViewDepth( const Camera* cam ) const { - if( mCachedCamera != cam ) - { - mCachedCameraDist = std::numeric_limits::infinity(); - - InstancedEntityVec::const_iterator itor = mInstancedEntities.begin(); - InstancedEntityVec::const_iterator end = mInstancedEntities.end(); + unsigned long currentFrameNumber = Root::getSingleton().getNextFrameNumber(); - while( itor != end ) - { - if( (*itor)->isVisible() ) - mCachedCameraDist = std::min( mCachedCameraDist, (*itor)->getSquaredViewDepth( cam ) ); - ++itor; - } + if (mCameraDistLastUpdateFrameNumber != currentFrameNumber || mCachedCamera != cam) + { + mCachedCameraDist = + getBoundingBox().getCenter().squaredDistance(cam->getDerivedPosition()); mCachedCamera = cam; + mCameraDistLastUpdateFrameNumber = currentFrameNumber; } return mCachedCameraDist; diff --git a/OgreMain/src/OgreMath.cpp b/OgreMain/src/OgreMath.cpp index d89088636c3..f5d93fe8be3 100644 --- a/OgreMain/src/OgreMath.cpp +++ b/OgreMain/src/OgreMath.cpp @@ -973,8 +973,8 @@ namespace Ogre //--------------------------------------------------------------------- Real Math::boundingRadiusFromAABB(const AxisAlignedBox& aabb) { - Vector3 max = aabb.getMaximum(); - Vector3 min = aabb.getMinimum(); + const Vector3& max = aabb.getMaximum(); + const Vector3& min = aabb.getMinimum(); Vector3 magnitude = max; magnitude.makeCeil(-max); @@ -984,4 +984,11 @@ namespace Ogre return magnitude.length(); } + Real Math::boundingRadiusFromAABBCentered(const AxisAlignedBox& aabb) + { + const Vector3& max = aabb.getMaximum(); + const Vector3& min = aabb.getMinimum(); + + return ((min - max) * 0.5f).length(); + } }