From Ravi Mathur, osgdepthpartition example program.
This commit is contained in:
parent
290e0b6eed
commit
b7fd3bfdc4
@ -183,6 +183,7 @@ EXAMPLE_DIRS = \
|
||||
osgcopy\
|
||||
osgcubemap\
|
||||
osgdepthshadow\
|
||||
osgdepthpartition\
|
||||
osgdistortion\
|
||||
osgfbo\
|
||||
osgforest\
|
||||
|
@ -627,6 +627,33 @@ Package=<4>
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "Example osgdepthpartition"=.\examples\osgdepthpartition\osgdepthpartition.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name Core osg
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name Core osgDB
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name Core osgGA
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name Core osgProducer
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name Core osgUtil
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "Example osgdepthshadow"=.\examples\osgdepthshadow\osgdepthshadow.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
|
125
VisualStudio/examples/osgdepthpartition/osgdepthpartition.dsp
Normal file
125
VisualStudio/examples/osgdepthpartition/osgdepthpartition.dsp
Normal file
@ -0,0 +1,125 @@
|
||||
# Microsoft Developer Studio Project File - Name="Example osgdepthpartition" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=Example osgdepthpartition - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "osgdepthpartition.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "osgdepthpartition.mak" CFG="Example osgdepthpartition - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Example osgdepthpartition - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Example osgdepthpartition - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Example osgdepthpartition - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
MTL=midl.exe
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /I "../../../../OpenThreads/include" /I "../../../../Producer/include" /I "../../../../3rdParty/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm200 /c
|
||||
# ADD BASE RSC /l 0x809 /d "NDEBUG"
|
||||
# ADD RSC /l 0x809 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 OpenThreadsWin32.lib opengl32.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgdepthpartition.exe" /libpath:"../../../lib" /libpath:"../../../../OpenThreads/lib/win32" /libpath:"../../../../Producer/lib" /libpath:"../../../../3rdParty/lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "Example osgdepthpartition - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
MTL=midl.exe
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "../../../include" /I "../../../../OpenThreads/include" /I "../../../../Producer/include" /I "../../../../3rdParty/include" /D "_CONSOLE" /D "_MBCS" /D "FL_DLL" /D "WIN32" /D "_DEBUG" /YX /FD /Zm200 /c
|
||||
# ADD BASE RSC /l 0x809 /d "_DEBUG"
|
||||
# ADD RSC /l 0x809 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 OpenThreadsWin32d.lib opengl32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"../../../bin/osgdepthpartitiond.exe" /pdbtype:sept /libpath:"../../../lib" /libpath:"../../../../OpenThreads/lib/win32" /libpath:"../../../../Producer/lib" /libpath:"../../../../3rdParty/lib"
|
||||
# SUBTRACT LINK32 /incremental:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Example osgdepthpartition - Win32 Release"
|
||||
# Name "Example osgdepthpartition - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\examples\osgdepthpartition\DepthPartitionNode.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\examples\osgdepthpartition\DistanceAccumulator.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\examples\osgdepthpartition\osgdepthpartition.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter ";h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\examples\osgdepthpartition\DepthPartitionNode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\examples\osgdepthpartition\DistanceAccumulator.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\icons\osg_icon.rc
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
263
examples/osgdepthpartition/DepthPartitionNode.cpp
Normal file
263
examples/osgdepthpartition/DepthPartitionNode.cpp
Normal file
@ -0,0 +1,263 @@
|
||||
#include "DepthPartitionNode.h"
|
||||
#include <osgUtil/CullVisitor>
|
||||
#include <iostream>
|
||||
|
||||
#define CURRENT_CLASS DepthPartitionNode
|
||||
CURRENT_CLASS::CURRENT_CLASS()
|
||||
{
|
||||
_distAccumulator = new DistanceAccumulator;
|
||||
init();
|
||||
}
|
||||
|
||||
CURRENT_CLASS::CURRENT_CLASS(const CURRENT_CLASS& dpn, const osg::CopyOp& copyop)
|
||||
: _active(dpn._active),
|
||||
_renderOrder(dpn._renderOrder),
|
||||
_clearColorBuffer(dpn._clearColorBuffer)
|
||||
{
|
||||
_distAccumulator = new DistanceAccumulator;
|
||||
_numCameras = 0;
|
||||
}
|
||||
|
||||
CURRENT_CLASS::~CURRENT_CLASS() {}
|
||||
|
||||
void CURRENT_CLASS::init()
|
||||
{
|
||||
_active = true;
|
||||
_numCameras = 0;
|
||||
setCullingActive(false);
|
||||
_renderOrder = osg::CameraNode::POST_RENDER;
|
||||
_clearColorBuffer = true;
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::setActive(bool active)
|
||||
{
|
||||
if(_active == active) return;
|
||||
_active = active;
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::setClearColorBuffer(bool clear)
|
||||
{
|
||||
_clearColorBuffer = clear;
|
||||
|
||||
// Update the render order for the first CameraNode if it exists
|
||||
if(!_cameraList.empty())
|
||||
{
|
||||
if(clear)
|
||||
_cameraList[0]->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
else
|
||||
_cameraList[0]->setClearMask(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::setRenderOrder(osg::CameraNode::RenderOrder order)
|
||||
{
|
||||
_renderOrder = order;
|
||||
|
||||
// Update the render order for existing CameraNodes
|
||||
unsigned int numCameras = _cameraList.size();
|
||||
for(unsigned int i = 0; i < numCameras; i++)
|
||||
{
|
||||
_cameraList[i]->setRenderOrder(_renderOrder);
|
||||
}
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::traverse(osg::NodeVisitor &nv)
|
||||
{
|
||||
// If the scene hasn't been defined then don't do anything
|
||||
unsigned int numChildren = _children.size();
|
||||
if(numChildren == 0) return;
|
||||
|
||||
// If the node is not active then don't analyze it
|
||||
if(!_active)
|
||||
{
|
||||
// Traverse the graph as usual
|
||||
Group::traverse(nv);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the visitor is not a cull visitor, pass it directly onto the scene.
|
||||
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
|
||||
if(!cv)
|
||||
{
|
||||
Group::traverse(nv);
|
||||
return;
|
||||
}
|
||||
|
||||
// We are in the cull traversal, so first collect information on the
|
||||
// current modelview and projection matrices and viewport.
|
||||
osg::RefMatrix& modelview = cv->getModelViewMatrix();
|
||||
osg::RefMatrix& projection = cv->getProjectionMatrix();
|
||||
osg::Viewport* viewport = cv->getViewport();
|
||||
|
||||
// Prepare for scene traversal.
|
||||
_distAccumulator->setMatrices(modelview, projection);
|
||||
_distAccumulator->setNearFarRatio(cv->getNearFarRatio());
|
||||
_distAccumulator->reset();
|
||||
|
||||
// Step 1: Traverse the children, collecting the near/far distances.
|
||||
unsigned int i;
|
||||
for(i = 0; i < numChildren; i++)
|
||||
{
|
||||
_children[i]->accept(*(_distAccumulator.get()));
|
||||
}
|
||||
|
||||
// Step 2: Compute the near and far distances for every CameraNode that
|
||||
// should be used to render the scene.
|
||||
_distAccumulator->computeCameraPairs();
|
||||
|
||||
// Step 3: Create the CameraNodes, and add them as children.
|
||||
DistanceAccumulator::PairList& camPairs = _distAccumulator->getCameraPairs();
|
||||
_numCameras = camPairs.size(); // Get the number of cameras
|
||||
|
||||
// Create the CameraNodes, and add them as children.
|
||||
if(_numCameras > 0)
|
||||
{
|
||||
osg::CameraNode *currCam;
|
||||
DistanceAccumulator::DistancePair currPair;
|
||||
|
||||
for(unsigned int j = 0; j < _numCameras; j++)
|
||||
{
|
||||
// Create the camera, and clamp it's projection matrix
|
||||
currPair = camPairs[j]; // (near,far) pair for current camera
|
||||
currCam = createOrReuseCamera(projection, currPair.first,
|
||||
currPair.second, j);
|
||||
|
||||
// Set the modelview matrix and viewport of the camera
|
||||
currCam->setViewMatrix(modelview);
|
||||
currCam->setViewport(viewport);
|
||||
|
||||
/*
|
||||
// Set our children as the camera's children
|
||||
currCam->removeChild(0, currCam->getNumChildren());
|
||||
for(i = 0; i < numChildren; i++)
|
||||
{
|
||||
currCam->addChild(_children[i].get());
|
||||
}
|
||||
*/
|
||||
|
||||
// Redirect the CullVisitor to the current camera
|
||||
currCam->accept(nv);
|
||||
}
|
||||
|
||||
// Set the clear color for the first camera
|
||||
_cameraList[0]->setClearColor(cv->getRenderStage()->getClearColor());
|
||||
}
|
||||
}
|
||||
|
||||
bool CURRENT_CLASS::addChild(osg::Node *child)
|
||||
{
|
||||
return insertChild(_children.size(), child);
|
||||
}
|
||||
|
||||
bool CURRENT_CLASS::insertChild(unsigned int index, osg::Node *child)
|
||||
{
|
||||
if(!Group::insertChild(index, child)) return false; // Insert child
|
||||
|
||||
// Insert child into each CameraNode
|
||||
unsigned int totalCameras = _cameraList.size();
|
||||
for(unsigned int i = 0; i < totalCameras; i++)
|
||||
{
|
||||
_cameraList[i]->insertChild(index, child);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CURRENT_CLASS::removeChild(osg::Node *child)
|
||||
{
|
||||
return Group::removeChild(child);
|
||||
}
|
||||
|
||||
bool CURRENT_CLASS::removeChild(unsigned int pos, unsigned int numRemove)
|
||||
{
|
||||
if(!Group::removeChild(pos, numRemove)) return false; // Remove child
|
||||
|
||||
// Remove child from each CameraNode
|
||||
unsigned int totalCameras = _cameraList.size();
|
||||
for(unsigned int i = 0; i < totalCameras; i++)
|
||||
{
|
||||
_cameraList[i]->removeChild(pos, numRemove);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CURRENT_CLASS::setChild(unsigned int i, osg::Node *node)
|
||||
{
|
||||
if(!Group::setChild(i, node)) return false; // Set child
|
||||
|
||||
// Set child for each CameraNode
|
||||
unsigned int totalCameras = _cameraList.size();
|
||||
for(unsigned int i = 0; i < totalCameras; i++)
|
||||
{
|
||||
_cameraList[i]->setChild(i, node);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
osg::CameraNode* CURRENT_CLASS::createOrReuseCamera(const osg::Matrix& proj,
|
||||
double near, double far, const unsigned int &camNum)
|
||||
{
|
||||
if(_cameraList.size() <= camNum) _cameraList.resize(camNum+1);
|
||||
osg::CameraNode *camera = _cameraList[camNum].get();
|
||||
|
||||
if(!camera) // Create a new CameraNode
|
||||
{
|
||||
camera = new osg::CameraNode;
|
||||
camera->setCullingActive(false);
|
||||
camera->setRenderOrder(_renderOrder);
|
||||
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
|
||||
// We will compute the near/far planes ourselves
|
||||
camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
camera->setCullingMode(osg::CullSettings::ENABLE_ALL_CULLING);
|
||||
|
||||
if(camNum == 0 && _clearColorBuffer)
|
||||
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
else
|
||||
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Add our children to the new CameraNode's children
|
||||
unsigned int numChildren = _children.size();
|
||||
for(unsigned int i = 0; i < numChildren; i++)
|
||||
{
|
||||
camera->addChild(_children[i].get());
|
||||
}
|
||||
|
||||
_cameraList[camNum] = camera;
|
||||
}
|
||||
|
||||
osg::Matrixd &projection = camera->getProjectionMatrix();
|
||||
projection = proj;
|
||||
|
||||
// Slightly inflate the near & far planes to avoid objects at the
|
||||
// extremes being clipped out.
|
||||
near *= 0.999;
|
||||
far *= 1.001;
|
||||
|
||||
// Clamp the projection matrix z values to the range (near, far)
|
||||
double epsilon = 1.0e-6;
|
||||
if(fabs(projection(0,3)) < epsilon &&
|
||||
fabs(projection(1,3)) < epsilon &&
|
||||
fabs(projection(2,3)) < epsilon ) // Projection is Orthographic
|
||||
{
|
||||
epsilon = -1.0/(far - near); // Used as a temp variable
|
||||
projection(2,2) = 2.0*epsilon;
|
||||
projection(3,2) = (far + near)*epsilon;
|
||||
}
|
||||
else // Projection is Perspective
|
||||
{
|
||||
double trans_near = (-near*projection(2,2) + projection(3,2)) /
|
||||
(-near*projection(2,3) + projection(3,3));
|
||||
double trans_far = (-far*projection(2,2) + projection(3,2)) /
|
||||
(-far*projection(2,3) + projection(3,3));
|
||||
double ratio = fabs(2.0/(trans_near - trans_far));
|
||||
double center = -0.5*(trans_near + trans_far);
|
||||
|
||||
projection.postMult(osg::Matrixd(1.0, 0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0, 0.0,
|
||||
0.0, 0.0, ratio, 0.0,
|
||||
0.0, 0.0, center*ratio, 1.0));
|
||||
}
|
||||
|
||||
return camera;
|
||||
}
|
||||
#undef CURRENT_CLASS
|
77
examples/osgdepthpartition/DepthPartitionNode.h
Normal file
77
examples/osgdepthpartition/DepthPartitionNode.h
Normal file
@ -0,0 +1,77 @@
|
||||
#ifndef _OF_DEPTHPARTITIONNODE_
|
||||
#define _OF_DEPTHPARTITIONNODE_
|
||||
|
||||
#include "DistanceAccumulator.h"
|
||||
#include <osg/CameraNode>
|
||||
|
||||
#define CURRENT_CLASS DepthPartitionNode
|
||||
/**********************************************************
|
||||
* Ravi Mathur
|
||||
* OpenFrames API, class DepthPartitionNode
|
||||
* A type of osg::Group that analyzes a scene, then partitions it into
|
||||
* several segments that can be rendered separately. Each segment
|
||||
* is small enough in the z-direction to avoid depth buffer problems
|
||||
* for very large scenes.
|
||||
**********************************************************/
|
||||
class CURRENT_CLASS : public osg::Group
|
||||
{
|
||||
public:
|
||||
CURRENT_CLASS();
|
||||
CURRENT_CLASS(const CURRENT_CLASS& dpn,
|
||||
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_Node( OpenFrames, CURRENT_CLASS ); // Common Node functions
|
||||
|
||||
/** Set the active state. If not active, this node will simply add the
|
||||
specified scene as it's child, without analyzing it at all. */
|
||||
void setActive(bool active);
|
||||
inline bool getActive() const { return _active; }
|
||||
|
||||
/** Specify whether the color buffer should be cleared before the first
|
||||
CameraNode draws it's scene. */
|
||||
void setClearColorBuffer(bool clear);
|
||||
inline bool getClearColorBuffer() const { return _clearColorBuffer; }
|
||||
|
||||
/** Specify the render order for each CameraNode */
|
||||
void setRenderOrder(osg::CameraNode::RenderOrder order);
|
||||
inline osg::CameraNode::RenderOrder getRenderOrder() const
|
||||
{ return _renderOrder; }
|
||||
|
||||
/** Override update and cull traversals */
|
||||
virtual void traverse(osg::NodeVisitor &nv);
|
||||
|
||||
/** Catch child management functions so the CameraNodes can be informed
|
||||
of new/removed children */
|
||||
virtual bool addChild(osg::Node *child);
|
||||
virtual bool insertChild(unsigned int index, osg::Node *child);
|
||||
virtual bool removeChild(osg::Node *child);
|
||||
virtual bool removeChild(unsigned int pos, unsigned int numRemove = 1);
|
||||
virtual bool setChild(unsigned int i, osg::Node *node);
|
||||
|
||||
protected:
|
||||
typedef std::vector< osg::ref_ptr<osg::CameraNode> > CameraList;
|
||||
|
||||
~CURRENT_CLASS();
|
||||
|
||||
void init();
|
||||
|
||||
// Creates a new CameraNode object with default settings
|
||||
osg::CameraNode* createOrReuseCamera(const osg::Matrix& proj, double near,
|
||||
double far, const unsigned int &camNum);
|
||||
|
||||
bool _active; // Whether partitioning is active on the scene
|
||||
|
||||
// The NodeVisitor that computes cameras for the scene
|
||||
osg::ref_ptr<DistanceAccumulator> _distAccumulator;
|
||||
|
||||
osg::CameraNode::RenderOrder _renderOrder;
|
||||
bool _clearColorBuffer;
|
||||
|
||||
// Cameras that should be used to draw the scene. These cameras
|
||||
// will be reused on every frame in order to save time and memory.
|
||||
CameraList _cameraList;
|
||||
unsigned int _numCameras; // Number of CameraNodes actually being used
|
||||
};
|
||||
#undef CURRENT_CLASS
|
||||
|
||||
#endif
|
282
examples/osgdepthpartition/DistanceAccumulator.cpp
Normal file
282
examples/osgdepthpartition/DistanceAccumulator.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
#include "DistanceAccumulator.h"
|
||||
#include <osg/Geode>
|
||||
#include <osg/Transform>
|
||||
#include <osg/Projection>
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
|
||||
/** Function that sees whether one DistancePair should come before another in
|
||||
an sorted list. Used to sort the vector of DistancePairs. */
|
||||
bool precedes(const DistanceAccumulator::DistancePair &a,
|
||||
const DistanceAccumulator::DistancePair &b)
|
||||
{
|
||||
// This results in sorting in order of descending far distances
|
||||
if(a.second > b.second) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
/** Computes distance betwen a point and the viewpoint of a matrix */
|
||||
double distance(const osg::Vec3 &coord, const osg::Matrix& matrix)
|
||||
{
|
||||
return -( coord[0]*matrix(0,2) + coord[1]*matrix(1,2) +
|
||||
coord[2]*matrix(2,2) + matrix(3,2) );
|
||||
}
|
||||
|
||||
#define CURRENT_CLASS DistanceAccumulator
|
||||
CURRENT_CLASS::CURRENT_CLASS()
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), _nearFarRatio(0.0)
|
||||
{
|
||||
setMatrices(osg::Matrix::identity(), osg::Matrix::identity());
|
||||
reset();
|
||||
setNearFarRatio(0.0005);
|
||||
}
|
||||
|
||||
CURRENT_CLASS::~CURRENT_CLASS() {}
|
||||
|
||||
void CURRENT_CLASS::pushLocalFrustum()
|
||||
{
|
||||
osg::Matrix& currMatrix = _viewMatrices.back();
|
||||
|
||||
// Compute the frustum in local space
|
||||
osg::Polytope localFrustum;
|
||||
localFrustum.setToUnitFrustum(false, false);
|
||||
localFrustum.transformProvidingInverse(currMatrix*_projectionMatrices.back());
|
||||
_localFrusta.push_back(localFrustum);
|
||||
|
||||
// Compute new bounding box corners
|
||||
osg::Vec3d lookVector(-currMatrix(0,2), -currMatrix(1,2), -currMatrix(2,2));
|
||||
bbCornerPair corner;
|
||||
corner.second = (lookVector.x()>=0?1:0) |
|
||||
(lookVector.y()>=0?2:0) |
|
||||
(lookVector.z()>=0?4:0);
|
||||
corner.first = (~corner.second)&7;
|
||||
_bbCorners.push_back(corner);
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::apply(osg::CameraNode &camera)
|
||||
{
|
||||
// We don't support scenes with CameraNodes in them
|
||||
return;
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::apply(osg::Projection &proj)
|
||||
{
|
||||
// Push the new projection matrix view frustum
|
||||
_projectionMatrices.push_back(proj.getMatrix());
|
||||
pushLocalFrustum();
|
||||
|
||||
traverse(proj); // Traverse the rest of the scene graph
|
||||
|
||||
// Reload original matrix and frustum
|
||||
_localFrusta.pop_back();
|
||||
_bbCorners.pop_back();
|
||||
_projectionMatrices.pop_back();
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::apply(osg::Transform &transform)
|
||||
{
|
||||
// Compute transform for current node
|
||||
osg::Matrix currMatrix = _viewMatrices.back();
|
||||
bool pushMatrix = transform.computeLocalToWorldMatrix(currMatrix, this);
|
||||
|
||||
if(pushMatrix)
|
||||
{
|
||||
// Store the new modelview matrix and view frustum
|
||||
_viewMatrices.push_back(currMatrix);
|
||||
pushLocalFrustum();
|
||||
}
|
||||
|
||||
traverse(transform); // Traverse the rest of the scene graph
|
||||
|
||||
if(pushMatrix)
|
||||
{
|
||||
// Restore the old modelview matrix and view frustum
|
||||
_localFrusta.pop_back();
|
||||
_bbCorners.pop_back();
|
||||
_viewMatrices.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::apply(osg::Geode &geode)
|
||||
{
|
||||
osg::Drawable *drawable;
|
||||
double zNear, zFar;
|
||||
|
||||
// Handle each drawable in this geode
|
||||
for(unsigned int i = 0; i < geode.getNumDrawables(); i++)
|
||||
{
|
||||
drawable = geode.getDrawable(i);
|
||||
|
||||
const osg::BoundingBox &bb = drawable->getBound();
|
||||
if(bb.valid())
|
||||
{
|
||||
// Make sure drawable will be visible in the scene
|
||||
if(!_localFrusta.back().contains(bb)) continue;
|
||||
|
||||
// Compute near/far distances for current drawable
|
||||
zNear = distance(bb.corner(_bbCorners.back().first),
|
||||
_viewMatrices.back());
|
||||
zFar = distance(bb.corner(_bbCorners.back().second),
|
||||
_viewMatrices.back());
|
||||
if(zNear > zFar) std::swap(zNear, zFar);
|
||||
|
||||
if(zFar > 0.0) // Make sure some of drawable is visible
|
||||
{
|
||||
// Make sure near plane is in front of viewpoint.
|
||||
if(zNear <= 0.0)
|
||||
{
|
||||
zNear = zFar*_nearFarRatio;
|
||||
if(zNear >= 1.0) zNear = 1.0; // 1.0 limit chosen arbitrarily!
|
||||
}
|
||||
|
||||
// Add distance pair for current drawable and current rendering mode
|
||||
_distancePairs.push_back(DistancePair(zNear, zFar));
|
||||
|
||||
// Override the current nearest/farthest planes if necessary
|
||||
if(zNear < _limits.first) _limits.first = zNear;
|
||||
if(zFar > _limits.second) _limits.second = zFar;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::setMatrices(const osg::Matrix &modelview,
|
||||
const osg::Matrix &projection)
|
||||
{
|
||||
_modelview = modelview;
|
||||
_projection = projection;
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::reset()
|
||||
{
|
||||
// Clear vectors & values
|
||||
_distancePairs.clear();
|
||||
_cameraPairs.clear();
|
||||
_limits.first = DBL_MAX;
|
||||
_limits.second = 0.0;
|
||||
|
||||
// Initial transform matrix is the modelview matrix
|
||||
_viewMatrices.clear();
|
||||
_viewMatrices.push_back(_modelview);
|
||||
|
||||
// Set the initial projection matrix
|
||||
_projectionMatrices.clear();
|
||||
_projectionMatrices.push_back(_projection);
|
||||
|
||||
// Create a frustum without near/far planes, for cull computations
|
||||
_localFrusta.clear();
|
||||
_bbCorners.clear();
|
||||
pushLocalFrustum();
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::computeCameraPairs()
|
||||
{
|
||||
// Nothing in the scene, so no cameras needed
|
||||
if(_distancePairs.empty()) return;
|
||||
|
||||
// Entire scene can be handled by just one camera
|
||||
if(_limits.first >= _limits.second*_nearFarRatio)
|
||||
{
|
||||
_cameraPairs.push_back(_limits);
|
||||
return;
|
||||
}
|
||||
|
||||
PairList::iterator i,j;
|
||||
|
||||
// Sort the list of distance pairs by descending far distance
|
||||
std::sort(_distancePairs.begin(), _distancePairs.end(), precedes);
|
||||
|
||||
// Combine overlapping distance pairs. The resulting set of distance
|
||||
// pairs (called combined pairs) will not overlap.
|
||||
PairList combinedPairs;
|
||||
DistancePair currPair = _distancePairs.front();
|
||||
for(i = _distancePairs.begin(); i != _distancePairs.end(); i++)
|
||||
{
|
||||
// Current distance pair does not overlap current combined pair, so
|
||||
// save the current combined pair and start a new one.
|
||||
if(i->second < 0.99*currPair.first)
|
||||
{
|
||||
combinedPairs.push_back(currPair);
|
||||
currPair = *i;
|
||||
}
|
||||
|
||||
// Current distance pair overlaps current combined pair, so expand
|
||||
// current combined pair to encompass distance pair.
|
||||
else
|
||||
currPair.first = std::min(i->first, currPair.first);
|
||||
}
|
||||
combinedPairs.push_back(currPair); // Add last pair
|
||||
|
||||
// Compute the (near,far) distance pairs for each camera.
|
||||
// Each of these distance pairs is called a "view segment".
|
||||
double currNearLimit, numSegs, new_ratio;
|
||||
double ratio_invlog = 1.0/log(_nearFarRatio);
|
||||
unsigned int temp;
|
||||
for(i = combinedPairs.begin(); i != combinedPairs.end(); i++)
|
||||
{
|
||||
currPair = *i; // Save current view segment
|
||||
|
||||
// Compute the fractional number of view segments needed to span
|
||||
// the current combined distance pair.
|
||||
currNearLimit = currPair.second*_nearFarRatio;
|
||||
if(currPair.first >= currNearLimit) numSegs = 1.0;
|
||||
else
|
||||
{
|
||||
numSegs = log(currPair.first/currPair.second)*ratio_invlog;
|
||||
|
||||
// Compute the near plane of the last view segment
|
||||
//currNearLimit *= pow(_nearFarRatio, -floor(-numSegs) - 1);
|
||||
for(temp = (unsigned int)(-floor(-numSegs)); temp > 1; temp--)
|
||||
{
|
||||
currNearLimit *= _nearFarRatio;
|
||||
}
|
||||
}
|
||||
|
||||
// See if the closest view segment can absorb other combined pairs
|
||||
for(j = i+1; j != combinedPairs.end(); j++)
|
||||
{
|
||||
// No other distance pairs can be included
|
||||
if(j->first < currNearLimit) break;
|
||||
}
|
||||
|
||||
// If we did absorb another combined distance pair, recompute the
|
||||
// number of required view segments.
|
||||
if(i != j-1)
|
||||
{
|
||||
i = j-1;
|
||||
currPair.first = i->first;
|
||||
if(currPair.first >= currPair.second*_nearFarRatio) numSegs = 1.0;
|
||||
else numSegs = log(currPair.first/currPair.second)*ratio_invlog;
|
||||
}
|
||||
|
||||
/* Compute an integer number of segments by rounding the fractional
|
||||
number of segments according to how many segments there are.
|
||||
In general, the more segments there are, the more likely that the
|
||||
integer number of segments will be rounded down.
|
||||
The purpose of this is to try to minimize the number of view segments
|
||||
that are used to render any section of the scene without violating
|
||||
the specified _nearFarRatio by too much. */
|
||||
if(numSegs < 10.0) numSegs = floor(numSegs + 1.0 - 0.1*floor(numSegs));
|
||||
else numSegs = floor(numSegs);
|
||||
|
||||
|
||||
// Compute the near/far ratio that will be used for each view segment
|
||||
// in this section of the scene.
|
||||
new_ratio = pow(currPair.first/currPair.second, 1.0/numSegs);
|
||||
|
||||
// Add numSegs new view segments to the camera pairs list
|
||||
for(temp = (unsigned int)numSegs; temp > 0; temp--)
|
||||
{
|
||||
currPair.first = currPair.second*new_ratio;
|
||||
_cameraPairs.push_back(currPair);
|
||||
currPair.second = currPair.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CURRENT_CLASS::setNearFarRatio(double ratio)
|
||||
{
|
||||
if(_nearFarRatio == ratio || ratio <= 0.0 || ratio >= 1.0) return;
|
||||
_nearFarRatio = ratio;
|
||||
}
|
||||
#undef CURRENT_CLASS
|
87
examples/osgdepthpartition/DistanceAccumulator.h
Normal file
87
examples/osgdepthpartition/DistanceAccumulator.h
Normal file
@ -0,0 +1,87 @@
|
||||
#ifndef _OF_DISTANCEACCUMULATOR_
|
||||
#define _OF_DISTANCEACCUMULATOR_
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/Polytope>
|
||||
#include <osg/fast_back_stack>
|
||||
|
||||
#define CURRENT_CLASS DistanceAccumulator
|
||||
/**********************************************************
|
||||
* Ravi Mathur
|
||||
* OpenFrames API, class DistanceAccumulator
|
||||
* Class that traverses the scene and computes the distance to each
|
||||
* visible drawable, and splits up the scene if the drawables are
|
||||
* too far away (in the z direction) from each other.
|
||||
**********************************************************/
|
||||
class CURRENT_CLASS : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
typedef std::pair<double, double> DistancePair;
|
||||
typedef std::vector<DistancePair> PairList;
|
||||
|
||||
CURRENT_CLASS();
|
||||
|
||||
virtual void apply(osg::CameraNode &camera);
|
||||
virtual void apply(osg::Projection &proj);
|
||||
virtual void apply(osg::Transform &transform);
|
||||
virtual void apply(osg::Geode &geode);
|
||||
|
||||
// Specify the modelview & projection matrices
|
||||
void setMatrices(const osg::Matrix &modelview,
|
||||
const osg::Matrix &projection);
|
||||
|
||||
// Reset visitor before a new traversal
|
||||
virtual void reset();
|
||||
|
||||
// Create a (near,far) distance pair for each camera of the specified
|
||||
// distance pair list and distance limits.
|
||||
void computeCameraPairs();
|
||||
|
||||
// Get info on the cameras that should be used for scene rendering
|
||||
PairList& getCameraPairs() { return _cameraPairs; }
|
||||
|
||||
// Get info on the computed distance pairs
|
||||
PairList& getDistancePairs() { return _distancePairs; }
|
||||
|
||||
// Get info on the computed nearest/farthest distances
|
||||
DistancePair& getLimits() { return _limits; }
|
||||
|
||||
// Set/get the desired near/far ratio
|
||||
void setNearFarRatio(double ratio);
|
||||
inline double getNearFarRatio() const { return _nearFarRatio; }
|
||||
|
||||
protected:
|
||||
virtual ~CURRENT_CLASS();
|
||||
|
||||
void pushLocalFrustum();
|
||||
|
||||
// Stack of matrices accumulated during traversal
|
||||
osg::fast_back_stack<osg::Matrix> _viewMatrices;
|
||||
osg::fast_back_stack<osg::Matrix> _projectionMatrices;
|
||||
|
||||
// Main modelview/projection matrices
|
||||
osg::Matrix _modelview, _projection;
|
||||
|
||||
// The view frusta in local coordinate space
|
||||
osg::fast_back_stack<osg::Polytope> _localFrusta;
|
||||
|
||||
// Bounding box corners that should be used for cull computation
|
||||
typedef std::pair<unsigned int, unsigned int> bbCornerPair;
|
||||
osg::fast_back_stack<bbCornerPair> _bbCorners;
|
||||
|
||||
// Nar/far planes that should be used for each camera
|
||||
PairList _cameraPairs;
|
||||
|
||||
// Accumulated pairs of min/max distances
|
||||
PairList _distancePairs;
|
||||
|
||||
// The closest & farthest distances found while traversing
|
||||
DistancePair _limits;
|
||||
|
||||
// Ratio of nearest/farthest clip plane for each section of the scene
|
||||
double _nearFarRatio;
|
||||
};
|
||||
#undef CURRENT_CLASS
|
||||
|
||||
#endif
|
20
examples/osgdepthpartition/GNUmakefile
Normal file
20
examples/osgdepthpartition/GNUmakefile
Normal file
@ -0,0 +1,20 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgdepthpartition.cpp\
|
||||
DepthPartitionNode.cpp\
|
||||
DistanceAccumulator.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgdepthpartion
|
||||
|
||||
INC += $(X_INC)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
15
examples/osgdepthpartition/GNUmakefile.inst
Normal file
15
examples/osgdepthpartition/GNUmakefile.inst
Normal file
@ -0,0 +1,15 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgdepthpartition.cpp\
|
||||
DepthPartitionNode.cpp\
|
||||
DistanceAccumulator.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgText -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgdepthpartion
|
||||
|
||||
INC += $(X_INC)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
217
examples/osgdepthpartition/osgdepthpartition.cpp
Normal file
217
examples/osgdepthpartition/osgdepthpartition.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
//C++ source file - Open Producer - Copyright (C) 2002 Don Burns
|
||||
//Distributed under the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE (LGPL)
|
||||
//as published by the Free Software Foundation.
|
||||
|
||||
// Simple example of use of Producer::RenderSurface
|
||||
// The myGraphics class is a simple sample of how one would implement
|
||||
// graphics drawing with Producer::RenderSurface
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Producer/Camera>
|
||||
#include <Producer/CameraConfig>
|
||||
#include <Producer/InputArea>
|
||||
#include <Producer/KeyboardMouse>
|
||||
#include <Producer/Trackball>
|
||||
|
||||
#include <osg/Timer>
|
||||
|
||||
#include <osgUtil/UpdateVisitor>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osg/ShapeDrawable>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
||||
#include <osgProducer/OsgCameraGroup>
|
||||
#include <osgProducer/OsgSceneHandler>
|
||||
|
||||
#include "DepthPartitionNode.h"
|
||||
|
||||
class MyKeyboardMouseCallback : public Producer::KeyboardMouseCallback
|
||||
{
|
||||
public:
|
||||
|
||||
MyKeyboardMouseCallback() :
|
||||
Producer::KeyboardMouseCallback(),
|
||||
_mx(0.0f),_my(0.0f),_mbutton(0),
|
||||
_done(false)
|
||||
{}
|
||||
|
||||
virtual void specialKeyPress( Producer::KeyCharacter key )
|
||||
{
|
||||
if (key==Producer::KeyChar_Escape)
|
||||
shutdown();
|
||||
}
|
||||
|
||||
virtual void shutdown()
|
||||
{
|
||||
_done = true;
|
||||
}
|
||||
|
||||
virtual void keyPress( Producer::KeyCharacter )
|
||||
{
|
||||
}
|
||||
|
||||
virtual void mouseMotion( float mx, float my )
|
||||
{
|
||||
_mx = mx;
|
||||
_my = my;
|
||||
}
|
||||
virtual void buttonPress( float mx, float my, unsigned int mbutton )
|
||||
{
|
||||
_mx = mx;
|
||||
_my = my;
|
||||
_mbutton |= (1<<(mbutton-1));
|
||||
}
|
||||
virtual void buttonRelease( float mx, float my, unsigned int mbutton )
|
||||
{
|
||||
_mx = mx;
|
||||
_my = my;
|
||||
_mbutton &= ~(1<<(mbutton-1));
|
||||
}
|
||||
|
||||
bool done() { return _done; }
|
||||
float mx() { return _mx; }
|
||||
float my() { return _my; }
|
||||
unsigned int mbutton() { return _mbutton; }
|
||||
|
||||
private:
|
||||
|
||||
float _mx, _my;
|
||||
unsigned int _mbutton;
|
||||
bool _done;
|
||||
};
|
||||
|
||||
const double r_earth = 6378.137;
|
||||
const double r_sun = 695990.0;
|
||||
const double AU = 149697900.0;
|
||||
|
||||
osg::Node* createScene()
|
||||
{
|
||||
// Create the Earth, in blue
|
||||
osg::ShapeDrawable *earth_sd = new osg::ShapeDrawable;
|
||||
osg::Sphere* earth_sphere = new osg::Sphere;
|
||||
earth_sphere->setRadius(r_earth);
|
||||
earth_sd->setShape(earth_sphere);
|
||||
earth_sd->setColor(osg::Vec4(0, 0, 1.0, 1.0));
|
||||
|
||||
osg::Geode* earth = new osg::Geode;
|
||||
earth->setName("earth");
|
||||
earth->addDrawable(earth_sd);
|
||||
|
||||
// Create the Sun, in yellow
|
||||
osg::ShapeDrawable *sun_sd = new osg::ShapeDrawable;
|
||||
osg::Sphere* sun_sphere = new osg::Sphere;
|
||||
sun_sphere->setRadius(r_sun);
|
||||
sun_sd->setShape(sun_sphere);
|
||||
sun_sd->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
|
||||
|
||||
osg::Geode* sun = new osg::Geode;
|
||||
sun->setName("sun");
|
||||
sun->addDrawable(sun_sd);
|
||||
|
||||
// Move the sun behind the earth
|
||||
osg::PositionAttitudeTransform *pat = new osg::PositionAttitudeTransform;
|
||||
pat->setPosition(osg::Vec3d(0.0, AU, 0.0));
|
||||
|
||||
osg::Group* scene = new osg::Group;
|
||||
scene->addChild(earth);
|
||||
scene->addChild(pat);
|
||||
pat->addChild(sun);
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
|
||||
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard example of using osgProducer::CameraGroup.");
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
// create the camera group.
|
||||
osgProducer::OsgCameraGroup cg(arguments);
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// set up the keyboard and mouse handling.
|
||||
Producer::InputArea *ia = cg.getCameraConfig()->getInputArea();
|
||||
Producer::KeyboardMouse *kbm = ia ?
|
||||
(new Producer::KeyboardMouse(ia)) :
|
||||
(new Producer::KeyboardMouse(cg.getCamera(0)->getRenderSurface()));
|
||||
|
||||
|
||||
osg::ref_ptr<MyKeyboardMouseCallback> kbmcb = new MyKeyboardMouseCallback;
|
||||
|
||||
// register the callback with the keyboard mouse manger.
|
||||
kbm->setCallback( kbmcb.get() );
|
||||
kbm->startThread();
|
||||
|
||||
// Create a DepthPartitionNode to manage partitioning of the scene
|
||||
DepthPartitionNode *dpn = new DepthPartitionNode;
|
||||
osg::Node* scene = createScene();
|
||||
dpn->addChild(scene);
|
||||
dpn->setActive(true); // Control whether the node analyzes the scene
|
||||
|
||||
// set the scene to render
|
||||
cg.setSceneData(dpn);
|
||||
|
||||
// Set the view to be looking at the earth
|
||||
osg::BoundingSphere bs;
|
||||
bs._radius = r_earth;
|
||||
|
||||
osg::ref_ptr<Producer::Trackball> tb = new Producer::Trackball;
|
||||
tb->setOrientation( Producer::Trackball::Z_UP );
|
||||
tb->setDistance(bs.radius()*10.0f);
|
||||
tb->translate(-bs.center().x(),-bs.center().y(),-bs.center().z());
|
||||
|
||||
// create the windows and run the threads.
|
||||
cg.realize();
|
||||
|
||||
osgUtil::UpdateVisitor update;
|
||||
|
||||
while( !kbmcb->done() )
|
||||
{
|
||||
// syncronize to the when cull and draw threads have completed.
|
||||
cg.sync();
|
||||
|
||||
// update the scene by traversing it with the the update visitor which will
|
||||
// call all node update callbacks and animations.
|
||||
cg.getSceneData()->accept(update);
|
||||
|
||||
tb->input( kbmcb->mx(), kbmcb->my(), kbmcb->mbutton() );
|
||||
|
||||
// update the main producer camera
|
||||
cg.setViewByMatrix(tb->getMatrix());
|
||||
|
||||
// fire off the cull and draw traversals of the scene.
|
||||
cg.frame();
|
||||
}
|
||||
|
||||
// syncronize to the when cull and draw threads have completed.
|
||||
cg.sync();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user