root/OpenSceneGraph/trunk/examples/osgdepthpartition/DepthPartitionNode.cpp @ 6248

Revision 6248, 7.6 kB (checked in by robert, 7 years ago)

Removed the exclusion of CullSettings? from the genwrapper.conf, and then changed the CullStack? RefMatrix?& methods to RefMatrix?*
as the RefMatrix?& versions caused the wrappers to fail.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include "DepthPartitionNode.h"
2#include <osgUtil/CullVisitor>
3
4using namespace osg;
5
6#define CURRENT_CLASS DepthPartitionNode
7
8CURRENT_CLASS::CURRENT_CLASS()
9{
10    _distAccumulator = new DistanceAccumulator;
11    init();
12}
13
14CURRENT_CLASS::CURRENT_CLASS(const CURRENT_CLASS& dpn, const osg::CopyOp& copyop)
15    : osg::Group(dpn, copyop),
16          _active(dpn._active),
17          _renderOrder(dpn._renderOrder),
18          _clearColorBuffer(dpn._clearColorBuffer)
19{
20    _distAccumulator = new DistanceAccumulator;
21    _numCameras = 0;
22}
23
24CURRENT_CLASS::~CURRENT_CLASS() {}
25
26void CURRENT_CLASS::init()
27{
28    _active = true;
29    _numCameras = 0;
30    setCullingActive(false);
31    _renderOrder = osg::Camera::POST_RENDER;
32    _clearColorBuffer = true;
33}
34
35void CURRENT_CLASS::setActive(bool active)
36{
37    if(_active == active) return;
38    _active = active;
39}
40
41void CURRENT_CLASS::setClearColorBuffer(bool clear)
42{
43    _clearColorBuffer = clear;
44
45    // Update the render order for the first Camera if it exists
46    if(!_cameraList.empty())
47    {
48      if(clear)
49        _cameraList[0]->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
50      else 
51        _cameraList[0]->setClearMask(GL_DEPTH_BUFFER_BIT);
52    }
53}
54
55void CURRENT_CLASS::setRenderOrder(osg::Camera::RenderOrder order)
56{
57    _renderOrder = order;
58
59    // Update the render order for existing Cameras
60    unsigned int numCameras = _cameraList.size();
61    for(unsigned int i = 0; i < numCameras; i++)
62    {
63      _cameraList[i]->setRenderOrder(_renderOrder);
64    }
65}
66
67void CURRENT_CLASS::traverse(osg::NodeVisitor &nv)
68{
69    // If the scene hasn't been defined then don't do anything
70    unsigned int numChildren = _children.size();
71    if(numChildren == 0) return;
72
73    // If the node is not active then don't analyze it
74    if(!_active)
75    {
76      // Traverse the graph as usual
77      Group::traverse(nv);
78      return;
79    }
80
81    // If the visitor is not a cull visitor, pass it directly onto the scene.
82    osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
83    if(!cv)
84    {
85      Group::traverse(nv);
86      return;
87    }
88
89    // We are in the cull traversal, so first collect information on the
90    // current modelview and projection matrices and viewport.
91    osg::RefMatrix& modelview = *(cv->getModelViewMatrix());
92    osg::RefMatrix& projection = *(cv->getProjectionMatrix());
93    osg::Viewport* viewport = cv->getViewport();
94
95    // Prepare for scene traversal.
96    _distAccumulator->setMatrices(modelview, projection);
97    _distAccumulator->setNearFarRatio(cv->getNearFarRatio());
98    _distAccumulator->reset();
99
100    // Step 1: Traverse the children, collecting the near/far distances.
101    unsigned int i;
102    for(i = 0; i < numChildren; i++)
103    {
104      _children[i]->accept(*(_distAccumulator.get()));
105    }
106
107    // Step 2: Compute the near and far distances for every Camera that
108    // should be used to render the scene.
109    _distAccumulator->computeCameraPairs();
110
111    // Step 3: Create the Cameras, and add them as children.
112    DistanceAccumulator::PairList& camPairs = _distAccumulator->getCameraPairs();
113    _numCameras = camPairs.size(); // Get the number of cameras
114
115    // Create the Cameras, and add them as children.
116    if(_numCameras > 0)
117    {
118      osg::Camera *currCam;
119      DistanceAccumulator::DistancePair currPair;
120
121      for(i = 0; i < _numCameras; i++)
122      {
123        // Create the camera, and clamp it's projection matrix
124        currPair = camPairs[i];  // (near,far) pair for current camera
125        currCam = createOrReuseCamera(projection, currPair.first,
126                                      currPair.second, i);
127
128        // Set the modelview matrix and viewport of the camera
129        currCam->setViewMatrix(modelview);
130        currCam->setViewport(viewport);
131
132        // Redirect the CullVisitor to the current camera
133        currCam->accept(nv);
134      }
135
136      // Set the clear color for the first camera
137      _cameraList[0]->setClearColor(cv->getRenderStage()->getClearColor());
138    }
139}
140
141bool CURRENT_CLASS::addChild(osg::Node *child)
142{
143    return insertChild(_children.size(), child);
144}
145
146bool CURRENT_CLASS::insertChild(unsigned int index, osg::Node *child)
147{
148    if(!Group::insertChild(index, child)) return false; // Insert child
149
150    // Insert child into each Camera
151    unsigned int totalCameras = _cameraList.size();
152    for(unsigned int i = 0; i < totalCameras; i++)
153    {
154      _cameraList[i]->insertChild(index, child);
155    }
156    return true;
157}
158
159
160bool CURRENT_CLASS::removeChildren(unsigned int pos, unsigned int numRemove)
161{
162    if(!Group::removeChildren(pos, numRemove)) return false; // Remove child
163
164    // Remove child from each Camera
165    unsigned int totalCameras = _cameraList.size();
166    for(unsigned int i = 0; i < totalCameras; i++)
167    {
168      _cameraList[i]->removeChildren(pos, numRemove);
169    }
170    return true;
171}
172
173bool CURRENT_CLASS::setChild(unsigned int i, osg::Node *node)
174{
175    if(!Group::setChild(i, node)) return false; // Set child
176
177    // Set child for each Camera
178    unsigned int totalCameras = _cameraList.size();
179    for(unsigned int j = 0; j < totalCameras; j++)
180    {
181      _cameraList[j]->setChild(i, node);
182    }
183    return true;
184}
185
186osg::Camera* CURRENT_CLASS::createOrReuseCamera(const osg::Matrix& proj,
187                            double znear, double zfar,
188                            const unsigned int &camNum)
189{
190    if(_cameraList.size() <= camNum) _cameraList.resize(camNum+1);
191    osg::Camera *camera = _cameraList[camNum].get();
192   
193    if(!camera) // Create a new Camera
194    {
195      camera = new osg::Camera;
196      camera->setCullingActive(false);
197      camera->setRenderOrder(_renderOrder);
198      camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
199
200      // We will compute the near/far planes ourselves
201      camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
202      camera->setCullingMode(osg::CullSettings::ENABLE_ALL_CULLING);
203
204      if(camNum == 0 && _clearColorBuffer)
205        camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
206      else
207        camera->setClearMask(GL_DEPTH_BUFFER_BIT);
208
209      // Add our children to the new Camera's children
210      unsigned int numChildren = _children.size();
211      for(unsigned int i = 0; i < numChildren; i++)
212      {
213        camera->addChild(_children[i].get());
214      }
215
216      _cameraList[camNum] = camera;
217    }
218
219    osg::Matrixd &projection = camera->getProjectionMatrix();
220    projection = proj;
221
222    // Slightly inflate the near & far planes to avoid objects at the
223    // extremes being clipped out.
224    znear *= 0.999;
225    zfar *= 1.001;
226
227    // Clamp the projection matrix z values to the range (near, far)
228    double epsilon = 1.0e-6;
229    if(fabs(projection(0,3)) < epsilon &&
230       fabs(projection(1,3)) < epsilon &&
231       fabs(projection(2,3)) < epsilon ) // Projection is Orthographic
232    {
233      epsilon = -1.0/(zfar - znear); // Used as a temp variable
234      projection(2,2) = 2.0*epsilon;
235      projection(3,2) = (zfar + znear)*epsilon;
236    }
237    else // Projection is Perspective
238    {
239      double trans_near = (-znear*projection(2,2) + projection(3,2)) /
240                          (-znear*projection(2,3) + projection(3,3));
241      double trans_far = (-zfar*projection(2,2) + projection(3,2)) /
242                         (-zfar*projection(2,3) + projection(3,3));
243      double ratio = fabs(2.0/(trans_near - trans_far));
244      double center = -0.5*(trans_near + trans_far);
245
246      projection.postMult(osg::Matrixd(1.0, 0.0, 0.0, 0.0,
247                                       0.0, 1.0, 0.0, 0.0,
248                            0.0, 0.0, ratio, 0.0,
249                       0.0, 0.0, center*ratio, 1.0));
250    }
251
252    return camera;
253}
254#undef CURRENT_CLASS
Note: See TracBrowser for help on using the browser.