2001-10-04 23:12:57 +08:00
|
|
|
//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.
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
#ifndef OSGUTIL_CULLVISITOR
|
|
|
|
#define OSGUTIL_CULLVISITOR 1
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
#include <osg/NodeVisitor>
|
|
|
|
#include <osg/BoundingSphere>
|
|
|
|
#include <osg/BoundingBox>
|
|
|
|
#include <osg/Matrix>
|
|
|
|
#include <osg/Drawable>
|
|
|
|
#include <osg/StateSet>
|
|
|
|
#include <osg/State>
|
|
|
|
#include <osg/Impostor>
|
2001-10-02 19:36:14 +08:00
|
|
|
#include <osg/EarthSky>
|
2001-09-20 05:19:47 +08:00
|
|
|
#include <osg/Notify>
|
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
#include <osg/fast_back_stack>
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
#include <osgUtil/RenderGraph>
|
|
|
|
#include <osgUtil/RenderStage>
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <vector>
|
|
|
|
|
2001-12-17 06:20:26 +08:00
|
|
|
#include <osg/Vec3>
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
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 CullVisitor : public osg::NodeVisitor
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2002-04-25 04:24:10 +08:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
NO_CULLING = 0x00,
|
|
|
|
FRUSTUM_LEFT_CULLING = 0x01,
|
|
|
|
FRUSTUM_RIGHT_CULLING = 0x02,
|
|
|
|
FRUSTUM_BOTTOM_CULLING = 0x04,
|
|
|
|
FRUSTUM_TOP_CULLING = 0x08,
|
|
|
|
FRUSTUM_NEAR_CULLING = 0x10,
|
|
|
|
FRUSTUM_FAR_CULLING = 0x20,
|
|
|
|
VIEW_FRUSTUM_CULLING = 0x3F,
|
|
|
|
SMALL_FEATURE_CULLING = 0x40,
|
|
|
|
ENABLE_ALL_CULLING = 0x7F
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef unsigned int CullingMode;
|
|
|
|
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
CullVisitor();
|
|
|
|
virtual ~CullVisitor();
|
|
|
|
|
2002-02-19 07:01:09 +08:00
|
|
|
virtual CullVisitor* cloneType() const { return new CullVisitor(); }
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
virtual void reset();
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
virtual void apply(osg::Node&);
|
|
|
|
virtual void apply(osg::Geode& node);
|
|
|
|
virtual void apply(osg::Billboard& node);
|
|
|
|
virtual void apply(osg::LightSource& node);
|
2002-05-02 08:14:40 +08:00
|
|
|
virtual void apply(osg::ClipNode& node);
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
virtual void apply(osg::Group& node);
|
|
|
|
virtual void apply(osg::Transform& node);
|
2002-04-01 00:40:44 +08:00
|
|
|
virtual void apply(osg::Projection& node);
|
2001-09-20 05:19:47 +08:00
|
|
|
virtual void apply(osg::Switch& node);
|
|
|
|
virtual void apply(osg::LOD& node);
|
2001-10-02 19:36:14 +08:00
|
|
|
virtual void apply(osg::EarthSky& node);
|
2001-09-20 05:19:47 +08:00
|
|
|
virtual void apply(osg::Impostor& node);
|
|
|
|
|
2001-10-02 19:36:14 +08:00
|
|
|
void setEarthSky(const osg::EarthSky* earthSky) { _earthSky = earthSky; }
|
|
|
|
const osg::EarthSky* getEarthSky() const { return _earthSky.get(); }
|
|
|
|
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
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 CullVisitor to use the Impostor
|
|
|
|
* LOD children for rendering. Setting active to true forces the
|
|
|
|
* CullVisitor 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; }
|
|
|
|
|
2002-05-15 19:27:47 +08:00
|
|
|
enum ComputeNearFarMode
|
|
|
|
{
|
|
|
|
DO_NOT_COMPUTE_NEAR_FAR = 0,
|
|
|
|
COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES,
|
|
|
|
COMPUTE_NEAR_FAR_USING_PRIMITIVES
|
|
|
|
};
|
|
|
|
|
|
|
|
void setComputeNearFarMode(ComputeNearFarMode cnfm) { _computeNearFar=cnfm; }
|
|
|
|
ComputeNearFarMode getComputeNearFarMode() const { return _computeNearFar;}
|
|
|
|
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
enum TransparencySortMode {
|
|
|
|
LOOK_VECTOR_DISTANCE,
|
|
|
|
OBJECT_EYE_POINT_DISTANCE
|
|
|
|
};
|
|
|
|
|
|
|
|
void setTransparencySortMode(TransparencySortMode tsm) { _tsm = tsm; }
|
|
|
|
|
|
|
|
/** Sets the current CullingMode.*/
|
2002-04-25 04:24:10 +08:00
|
|
|
void setCullingMode(CullingMode mode);
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
/** Returns the current CullingMode.*/
|
2002-04-25 04:24:10 +08:00
|
|
|
CullingMode getCullingMode() const;
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2002-05-14 18:20:55 +08:00
|
|
|
void setSmallFeatureCullingPixelSize(float s) { _smallFeatureCullingPixelSize=s; }
|
|
|
|
float getSmallFeatureCullingPixelSize() const { return _smallFeatureCullingPixelSize; }
|
2001-09-22 10:42:08 +08:00
|
|
|
|
2002-04-11 06:10:07 +08:00
|
|
|
void pushViewport(osg::Viewport* viewport);
|
|
|
|
void popViewport();
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2002-04-11 06:10:07 +08:00
|
|
|
void pushProjectionMatrix(osg::Matrix* matrix);
|
|
|
|
void popProjectionMatrix();
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2002-04-11 06:10:07 +08:00
|
|
|
void pushModelViewMatrix(osg::Matrix* matrix);
|
|
|
|
void popModelViewMatrix();
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
/** 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;
|
|
|
|
}
|
|
|
|
|
2002-05-15 19:27:47 +08:00
|
|
|
inline void setRenderGraph(RenderGraph* rg)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
|
|
|
_rootRenderGraph = rg;
|
|
|
|
_currentRenderGraph = rg;
|
|
|
|
}
|
|
|
|
|
2002-05-22 20:01:12 +08:00
|
|
|
inline RenderGraph* getRootRenderGraph()
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
|
|
|
return _rootRenderGraph.get();
|
|
|
|
}
|
|
|
|
|
2002-05-22 20:01:12 +08:00
|
|
|
inline RenderGraph* getCurrentRenderGraph()
|
|
|
|
{
|
|
|
|
return _currentRenderGraph;
|
|
|
|
}
|
|
|
|
|
2002-05-15 19:27:47 +08:00
|
|
|
inline void setRenderStage(RenderStage* rg)
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
|
|
|
_rootRenderStage = rg;
|
|
|
|
_currentRenderBin = rg;
|
|
|
|
}
|
|
|
|
|
2002-05-15 19:27:47 +08:00
|
|
|
inline RenderStage* getRenderStage()
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
|
|
|
return _rootRenderStage.get();
|
|
|
|
}
|
|
|
|
|
2002-05-15 19:27:47 +08:00
|
|
|
inline RenderBin* getCurrentRenderBin()
|
|
|
|
{
|
|
|
|
return _currentRenderBin;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline osg::Viewport* getViewport();
|
|
|
|
inline osg::Matrix& getModelViewMatrix();
|
|
|
|
inline osg::Matrix& getProjectionMatrix();
|
|
|
|
inline const osg::Matrix getWindowMatrix();
|
|
|
|
inline const osg::Matrix& getMVPW();
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2002-04-23 03:41:33 +08:00
|
|
|
inline const osg::Vec3& getEyeLocal() const
|
|
|
|
{
|
|
|
|
return _eyePointStack.back();
|
|
|
|
}
|
|
|
|
|
2002-05-15 19:27:47 +08:00
|
|
|
inline const float getCalculatedNearPlane() const { return _computed_znear; }
|
|
|
|
|
|
|
|
inline const float getCalculatedFarPlane() const { return _computed_zfar; }
|
2002-05-10 02:59:19 +08:00
|
|
|
|
|
|
|
inline float pixelSize(const osg::Vec3& v, float const radius)
|
|
|
|
{
|
|
|
|
const osg::Matrix& mvpw = getMVPW();
|
|
|
|
if (_windowToModelFactorDirty)
|
|
|
|
{
|
|
|
|
_windowToModelFactorDirty=false;
|
|
|
|
_windowToModelFactor = osg::Vec3(mvpw(0,0),mvpw(1,0),mvpw(2,0)).length();
|
|
|
|
}
|
|
|
|
float W = v.x()*mvpw(0,3)+
|
|
|
|
v.y()*mvpw(1,3)+
|
|
|
|
v.z()*mvpw(2,3)+
|
|
|
|
mvpw(3,3);
|
|
|
|
|
|
|
|
return fabs(radius*_windowToModelFactor/W);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-18 16:39:42 +08:00
|
|
|
osg::ClippingVolume& getCurrentClippingVolume() { return _modelviewClippingVolumeStack.back(); }
|
|
|
|
|
2002-05-10 02:59:19 +08:00
|
|
|
inline bool isCulled(const osg::BoundingSphere& sp,CullingMode& mode)
|
|
|
|
{
|
|
|
|
if (!sp.isValid()) return true;
|
|
|
|
|
|
|
|
if (!(_modelviewClippingVolumeStack.back().contains(sp,mode))) return true;
|
|
|
|
|
|
|
|
if (mode&SMALL_FEATURE_CULLING)
|
|
|
|
{
|
|
|
|
if (pixelSize(sp.center(),sp.radius())<_smallFeatureCullingPixelSize) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const bool isCulled(const osg::BoundingBox& bb,CullingMode mode)
|
|
|
|
{
|
|
|
|
if (!bb.isValid()) return true;
|
|
|
|
|
|
|
|
return !_modelviewClippingVolumeStack.back().contains(bb,mode);
|
|
|
|
}
|
|
|
|
|
2002-05-18 16:39:42 +08:00
|
|
|
const CullingMode getCurrentCullingMode() const { return _cullingModeStack.back(); }
|
|
|
|
|
|
|
|
void updateCalculatedNearFar(const osg::Matrix& matrix,const osg::Drawable& drawable) { updateCalculatedNearFar(matrix,drawable.getBound()); }
|
|
|
|
void updateCalculatedNearFar(const osg::Matrix& matrix,const osg::BoundingBox& bb);
|
2002-05-14 18:20:55 +08:00
|
|
|
void updateCalculatedNearFar(const osg::Vec3& pos);
|
|
|
|
|
|
|
|
/** Add a drawable to current render graph.*/
|
2002-05-15 19:27:47 +08:00
|
|
|
inline void addDrawable(osg::Drawable* drawable,osg::Matrix* matrix);
|
2002-05-14 18:20:55 +08:00
|
|
|
|
|
|
|
/** Add a drawable and depth to current render graph.*/
|
2002-05-15 19:27:47 +08:00
|
|
|
inline void addDrawableAndDepth(osg::Drawable* drawable,osg::Matrix* matrix,const float depth);
|
2002-05-14 18:20:55 +08:00
|
|
|
|
|
|
|
/** Add an attribute which is positioned related to the modelview matrix.*/
|
2002-05-15 19:27:47 +08:00
|
|
|
inline void addPositionedAttribute(osg::Matrix* matrix,const osg::StateAttribute* attr);
|
2002-05-10 02:59:19 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
protected:
|
|
|
|
|
|
|
|
/** prevent unwanted copy construction.*/
|
|
|
|
CullVisitor(const CullVisitor&):osg::NodeVisitor() {}
|
|
|
|
|
|
|
|
/** prevent unwanted copy operator.*/
|
|
|
|
CullVisitor& operator = (const CullVisitor&) { return *this; }
|
|
|
|
|
2002-04-15 21:15:48 +08:00
|
|
|
inline void handle_cull_callbacks_and_traverse(osg::Node& node)
|
|
|
|
{
|
|
|
|
osg::NodeCallback* callback = node.getCullCallback();
|
|
|
|
if (callback) (*callback)(&node,this);
|
|
|
|
else traverse(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void handle_cull_callbacks_and_accept(osg::Node& node,osg::Node* acceptNode)
|
|
|
|
{
|
|
|
|
osg::NodeCallback* callback = node.getCullCallback();
|
|
|
|
if (callback) (*callback)(&node,this);
|
|
|
|
else acceptNode->accept(*this);
|
|
|
|
}
|
|
|
|
|
2002-04-11 06:10:07 +08:00
|
|
|
|
|
|
|
inline const osg::Vec3 getUpLocal() const
|
2002-01-19 06:36:56 +08:00
|
|
|
{
|
2002-04-11 06:10:07 +08:00
|
|
|
const osg::Matrix& matrix = *_modelviewStack.back();
|
|
|
|
return osg::Vec3(matrix(0,1),matrix(1,1),matrix(2,1));
|
2002-01-19 06:36:56 +08:00
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2002-04-11 06:10:07 +08:00
|
|
|
inline const osg::Vec3 getLookVectorLocal() const
|
2001-09-20 05:19:47 +08:00
|
|
|
{
|
2002-04-11 06:10:07 +08:00
|
|
|
const osg::Matrix& matrix = *_modelviewStack.back();
|
|
|
|
return osg::Vec3(-matrix(0,2),-matrix(1,2),-matrix(2,2));
|
2001-09-20 05:19:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-05-02 08:14:40 +08:00
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
/** create an impostor sprite by setting up a pre-rendering stage
|
|
|
|
* to generate the impostor texture. */
|
|
|
|
osg::ImpostorSprite* createImpostorSprite(osg::Impostor& node);
|
|
|
|
|
2001-12-17 06:20:26 +08:00
|
|
|
|
2002-04-11 06:10:07 +08:00
|
|
|
|
|
|
|
void pushClippingVolume();
|
|
|
|
void popClippingVolume();
|
|
|
|
|
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
// typedef std::vector<osg::ClippingVolume> ClippingVolumeStack;
|
|
|
|
// typedef std::vector<osg::ref_ptr<osg::Matrix> > MatrixStack;
|
|
|
|
|
|
|
|
typedef osg::fast_back_stack<osg::ClippingVolume> ClippingVolumeStack;
|
|
|
|
typedef osg::fast_back_stack< osg::ref_ptr<osg::Matrix> > MatrixStack;
|
2002-04-11 06:10:07 +08:00
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
MatrixStack _projectionStack;
|
|
|
|
MatrixStack _PW_Stack;
|
|
|
|
ClippingVolumeStack _projectionClippingVolumeStack;
|
2002-04-11 06:10:07 +08:00
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
MatrixStack _modelviewStack;
|
|
|
|
MatrixStack _MVPW_Stack;
|
|
|
|
ClippingVolumeStack _modelviewClippingVolumeStack;
|
2002-05-10 02:59:19 +08:00
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
bool _windowToModelFactorDirty;
|
|
|
|
float _windowToModelFactor;
|
2002-05-10 02:59:19 +08:00
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
// typedef std::vector<osg::ref_ptr<osg::Viewport> > ViewportStack;
|
|
|
|
typedef osg::fast_back_stack<osg::ref_ptr<osg::Viewport> > ViewportStack;
|
|
|
|
ViewportStack _viewportStack;
|
2002-04-11 06:10:07 +08:00
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
// typedef std::vector<osg::Vec3> EyePointStack;
|
|
|
|
typedef osg::fast_back_stack<osg::Vec3> EyePointStack;
|
|
|
|
EyePointStack _eyePointStack;
|
2002-04-11 06:10:07 +08:00
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
typedef osg::fast_back_stack<CullingMode> CullingModeStack;
|
|
|
|
CullingModeStack _cullingModeStack;
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
unsigned int _bbCornerNear;
|
|
|
|
unsigned int _bbCornerFar;
|
2002-04-11 06:10:07 +08:00
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
osg::Matrix _identity;
|
2002-04-11 06:10:07 +08:00
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
osg::ref_ptr<RenderGraph> _rootRenderGraph;
|
|
|
|
RenderGraph* _currentRenderGraph;
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
osg::ref_ptr<RenderStage> _rootRenderStage;
|
|
|
|
RenderBin* _currentRenderBin;
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
|
2002-05-28 18:24:43 +08:00
|
|
|
float _LODBias;
|
|
|
|
float _smallFeatureCullingPixelSize;
|
2002-04-22 22:54:39 +08:00
|
|
|
|
|
|
|
|
|
|
|
ComputeNearFarMode _computeNearFar;
|
|
|
|
float _computed_znear;
|
|
|
|
float _computed_zfar;
|
2001-09-20 05:19:47 +08:00
|
|
|
|
2001-10-02 19:36:14 +08:00
|
|
|
osg::ref_ptr<const osg::EarthSky> _earthSky;
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
TransparencySortMode _tsm;
|
|
|
|
|
|
|
|
bool _impostorActive;
|
|
|
|
bool _depthSortImpostorSprites;
|
|
|
|
float _impostorPixelErrorThreshold;
|
|
|
|
int _numFramesToKeepImpostorSprites;
|
|
|
|
|
|
|
|
typedef std::vector< osg::ref_ptr<osg::Matrix> > MatrixList;
|
|
|
|
MatrixList _reuseMatrixList;
|
|
|
|
unsigned int _currentReuseMatrixIndex;
|
|
|
|
|
2002-05-15 19:27:47 +08:00
|
|
|
inline osg::Matrix* createOrReuseMatrix(const osg::Matrix& value);
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
typedef std::vector< osg::ref_ptr<RenderLeaf> > RenderLeafList;
|
|
|
|
RenderLeafList _reuseRenderLeafList;
|
|
|
|
unsigned int _currentReuseRenderLeafIndex;
|
|
|
|
|
2002-05-15 19:27:47 +08:00
|
|
|
inline RenderLeaf* createOrReuseRenderLeaf(osg::Drawable* drawable,osg::Matrix* projection,osg::Matrix* matrix, float depth=0.0f);
|
|
|
|
|
2001-09-20 05:19:47 +08:00
|
|
|
osg::ref_ptr<osg::ImpostorSpriteManager> _impostorSpriteManager;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2002-05-15 19:27:47 +08:00
|
|
|
|
|
|
|
|
|
|
|
inline osg::Viewport* CullVisitor::getViewport()
|
|
|
|
{
|
|
|
|
if (!_viewportStack.empty())
|
|
|
|
{
|
|
|
|
return _viewportStack.back().get();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline osg::Matrix& CullVisitor::getModelViewMatrix()
|
|
|
|
{
|
|
|
|
if (!_modelviewStack.empty())
|
|
|
|
{
|
|
|
|
return *_modelviewStack.back();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return _identity;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline osg::Matrix& CullVisitor::getProjectionMatrix()
|
|
|
|
{
|
|
|
|
if (!_projectionStack.empty())
|
|
|
|
{
|
|
|
|
return *_projectionStack.back();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return _identity;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const osg::Matrix CullVisitor::getWindowMatrix()
|
|
|
|
{
|
|
|
|
if (!_viewportStack.empty())
|
|
|
|
{
|
|
|
|
osg::Viewport* viewport = _viewportStack.back().get();
|
|
|
|
return viewport->computeWindowMatrix();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return _identity;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const osg::Matrix& CullVisitor::getMVPW()
|
|
|
|
{
|
|
|
|
if (!_MVPW_Stack.empty())
|
|
|
|
{
|
|
|
|
if (!_MVPW_Stack.back())
|
|
|
|
{
|
|
|
|
_MVPW_Stack.back() = createOrReuseMatrix(getModelViewMatrix());
|
|
|
|
(*_MVPW_Stack.back()) *= getProjectionMatrix();
|
|
|
|
(*_MVPW_Stack.back()) *= getWindowMatrix();
|
|
|
|
}
|
|
|
|
return *_MVPW_Stack.back();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return _identity;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void CullVisitor::addDrawable(osg::Drawable* drawable,osg::Matrix* matrix)
|
|
|
|
{
|
|
|
|
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));
|
|
|
|
_currentRenderGraph->addLeaf(createOrReuseRenderLeaf(drawable,_projectionStack.back().get(),matrix));
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Add a drawable and depth to current render graph.*/
|
|
|
|
inline void CullVisitor::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 an attribute which is positioned related to the modelview matrix.*/
|
|
|
|
inline void CullVisitor::addPositionedAttribute(osg::Matrix* matrix,const osg::StateAttribute* attr)
|
|
|
|
{
|
|
|
|
_currentRenderBin->_stage->addPositionedAttribute(matrix,attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline osg::Matrix* CullVisitor::createOrReuseMatrix(const osg::Matrix& value)
|
|
|
|
{
|
|
|
|
// 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->set(value);
|
|
|
|
return matrix;
|
|
|
|
}
|
|
|
|
|
|
|
|
// otherwise need to create new matrix.
|
|
|
|
osg::Matrix* matrix = new osg::Matrix(value);
|
|
|
|
_reuseMatrixList.push_back(matrix);
|
|
|
|
++_currentReuseMatrixIndex;
|
|
|
|
return matrix;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline RenderLeaf* CullVisitor::createOrReuseRenderLeaf(osg::Drawable* drawable,osg::Matrix* projection,osg::Matrix* matrix, float depth)
|
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-02-03 20:33:41 +08:00
|
|
|
}
|
2001-09-20 05:19:47 +08:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|