From dfaed083ea0b1fac7ce1f90f150b51ad13b755bf Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 15 Jun 2005 10:59:10 +0000 Subject: [PATCH] Added osgmultiplecameras example and support for pre/post multiplaction. --- Make/makedirdefs | 1 + VisualStudio/VisualStudio.dsw | 27 ++++ .../osgmultiplecameras/osgmultiplecameras.dsp | 97 +++++++++++++ examples/osgmultiplecameras/GNUmakefile | 18 +++ examples/osgmultiplecameras/GNUmakefile.inst | 14 ++ .../osgmultiplecameras/osgmultiplecameras.cpp | 132 ++++++++++++++++++ include/osg/CameraNode | 13 ++ src/osg/CameraNode.cpp | 22 ++- src/osgUtil/CullVisitor.cpp | 42 ++++-- 9 files changed, 351 insertions(+), 15 deletions(-) create mode 100644 VisualStudio/examples/osgmultiplecameras/osgmultiplecameras.dsp create mode 100644 examples/osgmultiplecameras/GNUmakefile create mode 100644 examples/osgmultiplecameras/GNUmakefile.inst create mode 100644 examples/osgmultiplecameras/osgmultiplecameras.cpp diff --git a/Make/makedirdefs b/Make/makedirdefs index 2176cc5b2..f7394cec8 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -201,6 +201,7 @@ EXAMPLE_DIRS = \ osgmotionblur\ osgmovie\ osgmultitexture\ + osgmultiplecameras\ osgoccluder\ osgpagedlod\ osgparticle\ diff --git a/VisualStudio/VisualStudio.dsw b/VisualStudio/VisualStudio.dsw index 4aaa240a6..71b475bba 100644 --- a/VisualStudio/VisualStudio.dsw +++ b/VisualStudio/VisualStudio.dsw @@ -1074,6 +1074,33 @@ Package=<4> ############################################################################### +Project: "Example osgmultiplecameras"=.\examples\osgmultiplecameras\osgmultiplecameras.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 osgoccluder"=.\examples\osgoccluder\osgoccluder.dsp - Package Owner=<4> Package=<5> diff --git a/VisualStudio/examples/osgmultiplecameras/osgmultiplecameras.dsp b/VisualStudio/examples/osgmultiplecameras/osgmultiplecameras.dsp new file mode 100644 index 000000000..134a4e2a3 --- /dev/null +++ b/VisualStudio/examples/osgmultiplecameras/osgmultiplecameras.dsp @@ -0,0 +1,97 @@ +# Microsoft Developer Studio Project File - Name="Example osgmultiplecameras" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Example osgmultiplecameras - 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 "osgmultiplecameras.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 "osgmultiplecameras.mak" CFG="Example osgmultiplecameras - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Example osgmultiplecameras - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Example osgmultiplecameras - 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 osgmultiplecameras - 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 /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgmultiplecameras.exe" /libpath:"../../../lib" /libpath:"../../../../OpenThreads/lib/win32" /libpath:"../../../../Producer/lib" /libpath:"../../../../3rdParty/lib" + +!ELSEIF "$(CFG)" == "Example osgmultiplecameras - 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" /FR /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 glu32.lib opengl32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"../../../bin/osgmultiplecamerasd.exe" /pdbtype:sept /libpath:"../../../lib" /libpath:"../../../../OpenThreads/lib/win32" /libpath:"../../../../Producer/lib" /libpath:"../../../../3rdParty/lib" +# SUBTRACT LINK32 /incremental:no + +!ENDIF + +# Begin Target + +# Name "Example osgmultiplecameras - Win32 Release" +# Name "Example osgmultiplecameras - Win32 Debug" +# Begin Source File + +SOURCE=..\..\..\examples\osgmultiplecameras\osgmultiplecameras.cpp +# End Source File +# End Target +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Project diff --git a/examples/osgmultiplecameras/GNUmakefile b/examples/osgmultiplecameras/GNUmakefile new file mode 100644 index 000000000..0772bddb0 --- /dev/null +++ b/examples/osgmultiplecameras/GNUmakefile @@ -0,0 +1,18 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgmultiplecameras.cpp\ + +LIBS += -losgProducer -lProducer -losgText -losgProducer -lProducer -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +INSTFILES = \ + $(CXXFILES)\ + GNUmakefile.inst=GNUmakefile + +EXEC = osgmultiplecameras + +INC += $(X_INC) + +include $(TOPDIR)/Make/makerules + diff --git a/examples/osgmultiplecameras/GNUmakefile.inst b/examples/osgmultiplecameras/GNUmakefile.inst new file mode 100644 index 000000000..79769fdf5 --- /dev/null +++ b/examples/osgmultiplecameras/GNUmakefile.inst @@ -0,0 +1,14 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgmultiplecameras.cpp\ + +LIBS += -losgProducer -lProducer -losgText -losgProducer -lProducer -losgDB -losgText -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +EXEC = osgmultiplecameras + +INC += $(PRODUCER_INCLUDE_DIR) $(X_INC) +LDFLAGS += $(PRODUCER_LIB_DIR) + +include $(TOPDIR)/Make/makerules diff --git a/examples/osgmultiplecameras/osgmultiplecameras.cpp b/examples/osgmultiplecameras/osgmultiplecameras.cpp new file mode 100644 index 000000000..43ae222df --- /dev/null +++ b/examples/osgmultiplecameras/osgmultiplecameras.cpp @@ -0,0 +1,132 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +osg::Node* createRearView(osg::Node* subgraph) +{ + + osg::CameraNode* camera = new osg::CameraNode; + + // set the projection matrix + camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1280,0,1024)); + + camera->setViewport(420,800,400,200); + + camera->getOrCreateStateSet()->setAttribute(camera->getViewport()); + + + // set the view matrix + camera->setCullingActive(false); + camera->setReferenceFrame(osg::Transform::RELATIVE_RF); + camera->setTransformOrder(osg::CameraNode::POST_MULTIPLE); + camera->setProjectionMatrix(osg::Matrixd::identity()); + camera->setViewMatrix(osg::Matrixd::rotate(osg::inDegrees(180.0f),0.0f,1.0f,0.0f)); + + // only clear the depth buffer + camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + // draw subgraph after main camera view. + camera->setRenderOrder(osg::CameraNode::POST_RENDER); + + camera->addChild(subgraph); + + return camera; +} + +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()->setDescription(arguments.getApplicationName()+" is the example which demonstrates how to do Head Up Displays."); + arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] [filename] ..."); + arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information"); + + + // construct the viewer. + osgProducer::Viewer viewer(arguments); + + // set up the value with sensible default event handlers. + viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS); + + // get details on keyboard and mouse bindings used by the viewer. + viewer.getUsage(*arguments.getApplicationUsage()); + + // 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; + } + + // read the scene from the list of file specified commandline args. + osg::ref_ptr scene = osgDB::readNodeFiles(arguments); + + osg::ref_ptr group = new osg::Group; + + // add the HUD subgraph. + if (scene.valid()) group->addChild(scene.get()); + group->addChild(createRearView(scene.get())); + + // set the scene to render + viewer.setSceneData(group.get()); + + // create the windows and run the threads. + viewer.realize(); + + while( !viewer.done() ) + { + // wait for all cull and draw threads to complete. + viewer.sync(); + + // update the scene by traversing it with the the update visitor which will + // call all node update callbacks and animations. + viewer.update(); + + // fire off the cull and draw traversals of the scene. + viewer.frame(); + + } + + // wait for all cull and draw threads to complete before exit. + viewer.sync(); + + return 0; +} diff --git a/include/osg/CameraNode b/include/osg/CameraNode index 4ccf69a6f..e56bd84ca 100644 --- a/include/osg/CameraNode +++ b/include/osg/CameraNode @@ -64,6 +64,17 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings } + enum TransformOrder + { + PRE_MULTIPLE, + POST_MULTIPLE + }; + + void setTransformOrder(TransformOrder order) { _transformOrder = order; } + TransformOrder getTransformOrder() const { return _transformOrder; } + + + /** Set the projection matrix. Can be thought of as setting the lens of a camera. */ inline void setProjectionMatrix(const osg::Matrixf& matrix) { _projectionMatrix.set(matrix); } @@ -225,6 +236,8 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings Vec4 _clearColor; GLbitfield _clearMask; ref_ptr _viewport; + + TransformOrder _transformOrder; Matrixd _projectionMatrix; Matrixd _viewMatrix; diff --git a/src/osg/CameraNode.cpp b/src/osg/CameraNode.cpp index 96e291bfa..6c3f064c6 100644 --- a/src/osg/CameraNode.cpp +++ b/src/osg/CameraNode.cpp @@ -19,6 +19,7 @@ using namespace osg; CameraNode::CameraNode(): _clearColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f)), _clearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT), + _transformOrder(PRE_MULTIPLE), _renderOrder(POST_RENDER), _renderTargetImplementation(FRAME_BUFFER) { @@ -30,6 +31,7 @@ CameraNode::CameraNode(const CameraNode& camera,const CopyOp& copyop): _clearColor(camera._clearColor), _clearMask(camera._clearMask), _viewport(camera._viewport), + _transformOrder(camera._transformOrder), _projectionMatrix(camera._projectionMatrix), _viewMatrix(camera._viewMatrix), _renderOrder(camera._renderOrder), @@ -143,7 +145,14 @@ bool CameraNode::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const { if (_referenceFrame==RELATIVE_RF) { - matrix.preMult(_viewMatrix); + if (_transformOrder==PRE_MULTIPLE) + { + matrix.preMult(_viewMatrix); + } + else + { + matrix.postMult(_viewMatrix); + } } else // absolute { @@ -158,7 +167,16 @@ bool CameraNode::computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor*) const if (_referenceFrame==RELATIVE_RF) { - matrix.postMult(inverse); + if (_transformOrder==PRE_MULTIPLE) + { + // note doing inverse so pre becomes post. + matrix.postMult(inverse); + } + else + { + // note doing inverse so post becomes pre. + matrix.preMult(inverse); + } } else // absolute { diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 966460d28..e440eb2c1 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -1029,8 +1029,29 @@ void CullVisitor::apply(osg::CameraNode& camera) StateSet* node_state = camera.getStateSet(); if (node_state) pushStateSet(node_state); - // use render to texture stage. + if (camera.getReferenceFrame()==osg::Transform::ABSOLUTE_RF) { + pushProjectionMatrix(createOrReuseMatrix(camera.getProjectionMatrix())); + pushModelViewMatrix(createOrReuseMatrix(camera.getViewMatrix())); + } + else if (camera.getTransformOrder()==osg::CameraNode::POST_MULTIPLE) + { + pushProjectionMatrix(createOrReuseMatrix(getProjectionMatrix()*camera.getProjectionMatrix())); + pushModelViewMatrix(createOrReuseMatrix(getModelViewMatrix()*camera.getViewMatrix())); + } + else // pre multiple + { + pushProjectionMatrix(createOrReuseMatrix(camera.getProjectionMatrix()*getProjectionMatrix())); + pushModelViewMatrix(createOrReuseMatrix(camera.getViewMatrix()*getModelViewMatrix())); + } + + if (camera.getRenderOrder()==osg::CameraNode::NESTED_RENDER) + { + handle_cull_callbacks_and_traverse(camera); + } + else + { + // use render to texture stage. // create the render to texture stage. osg::ref_ptr rtts = new osgUtil::RenderToTextureStage; @@ -1056,20 +1077,12 @@ void CullVisitor::apply(osg::CameraNode& camera) // set the current renderbin to be the newly created stage. setCurrentRenderBin(rtts.get()); - pushProjectionMatrix(new osg::RefMatrix(camera.getProjectionMatrix())); - - pushModelViewMatrix(new osg::RefMatrix(camera.getViewMatrix())); // traverse the subgraph { handle_cull_callbacks_and_traverse(camera); } - // restore the previous model view matrix. - popModelViewMatrix(); - - // restore the previous model view matrix. - popProjectionMatrix(); // restore the previous renderbin. setCurrentRenderBin(previousRenderBin); @@ -1088,10 +1101,7 @@ void CullVisitor::apply(osg::CameraNode& camera) case osg::CameraNode::PRE_RENDER : getCurrentRenderBin()->getStage()->addPreRenderStage(rtts.get()); break; - case osg::CameraNode::NESTED_RENDER : - getCurrentRenderBin()->getStage()->addPostRenderStage(rtts.get()); - break; - case osg::CameraNode::POST_RENDER : + default : getCurrentRenderBin()->getStage()->addPostRenderStage(rtts.get()); break; } @@ -1112,6 +1122,12 @@ void CullVisitor::apply(osg::CameraNode& camera) } + // restore the previous model view matrix. + popModelViewMatrix(); + + // restore the previous model view matrix. + popProjectionMatrix(); + // pop the node's state off the render graph stack. if (node_state) popStateSet();