2001-09-20 05:08:56 +08:00
|
|
|
#include <osgUtil/SceneView>
|
2001-09-22 10:42:08 +08:00
|
|
|
#include <osgUtil/AppVisitor>
|
2001-10-21 04:26:36 +08:00
|
|
|
#include <osgUtil/DisplayListVisitor>
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
#include <osg/Notify>
|
|
|
|
#include <osg/Texture>
|
|
|
|
#include <osg/AlphaFunc>
|
|
|
|
#include <osg/TexEnv>
|
2001-12-19 08:38:23 +08:00
|
|
|
#include <osg/ColorMatrix>
|
2002-03-04 06:31:46 +08:00
|
|
|
#include <osg/LightModel>
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2001-10-04 05:44:07 +08:00
|
|
|
#include <osg/GLU>
|
2001-01-11 00:32:10 +08:00
|
|
|
|
|
|
|
using namespace osg;
|
|
|
|
using namespace osgUtil;
|
|
|
|
|
2001-12-22 06:48:19 +08:00
|
|
|
SceneView::SceneView(DisplaySettings* ds)
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-12-22 06:48:19 +08:00
|
|
|
_displaySettings = ds;
|
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
_calc_nearfar = true;
|
|
|
|
|
|
|
|
_backgroundColor.set(0.2f, 0.2f, 0.4f, 1.0f);
|
|
|
|
|
|
|
|
_near_plane = 1.0f;
|
|
|
|
_far_plane = 1.0f;
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
_lodBias = 1.0f;
|
|
|
|
|
|
|
|
_lightingMode=HEADLIGHT;
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
_prioritizeTextures = false;
|
|
|
|
|
2002-03-27 07:52:52 +08:00
|
|
|
_viewport = osgNew Viewport;
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2001-10-21 04:26:36 +08:00
|
|
|
_initCalled = false;
|
|
|
|
|
2002-03-04 06:31:46 +08:00
|
|
|
_cullMask = 0xffffffff;
|
|
|
|
_cullMaskLeft = 0xffffffff;
|
2002-03-21 19:57:16 +08:00
|
|
|
_cullMaskRight = 0xffffffff;
|
2002-03-04 06:31:46 +08:00
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
SceneView::~SceneView()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
void SceneView::setDefaults()
|
|
|
|
{
|
2002-03-27 07:52:52 +08:00
|
|
|
_globalState = osgNew osg::StateSet;
|
2001-01-11 00:32:10 +08:00
|
|
|
|
|
|
|
_lightingMode=HEADLIGHT;
|
2002-03-27 07:52:52 +08:00
|
|
|
_light = osgNew osg::Light;
|
2001-12-25 05:34:40 +08:00
|
|
|
_light->setLightNum(0);
|
2001-12-03 06:20:46 +08:00
|
|
|
_light->setAmbient(Vec4(0.00f,0.0f,0.00f,1.0f));
|
2001-09-20 05:08:56 +08:00
|
|
|
_light->setDiffuse(Vec4(0.8f,0.8f,0.8f,1.0f));
|
2001-12-03 06:20:46 +08:00
|
|
|
_light->setSpecular(Vec4(1.0f,1.0f,1.0f,1.0f));
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2002-03-27 07:52:52 +08:00
|
|
|
_state = osgNew State;
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2002-03-27 07:52:52 +08:00
|
|
|
_camera = osgNew Camera(_displaySettings.get());
|
2001-12-03 06:20:46 +08:00
|
|
|
|
2002-03-27 07:52:52 +08:00
|
|
|
_rendergraph = osgNew RenderGraph;
|
|
|
|
_renderStage = osgNew RenderStage;
|
2001-09-22 10:42:08 +08:00
|
|
|
|
|
|
|
|
2002-03-29 07:06:20 +08:00
|
|
|
#ifndef __sgi
|
2002-02-11 01:16:43 +08:00
|
|
|
// sgi's IR graphics has a problem with lighting and display lists, as it seems to store
|
|
|
|
// lighting state with the display list, and the display list visitor doesn't currently apply
|
|
|
|
// state before creating display lists. So will disable the init visitor default, this won't
|
|
|
|
// affect functionality since the display lists will be created as and when needed.
|
2002-03-27 07:52:52 +08:00
|
|
|
DisplayListVisitor* dlv = osgNew DisplayListVisitor();
|
2001-10-21 04:26:36 +08:00
|
|
|
dlv->setState(_state.get());
|
2002-03-15 01:34:08 +08:00
|
|
|
dlv->setNodeMaskOverride(0xffffffff);
|
2001-10-21 04:26:36 +08:00
|
|
|
_initVisitor = dlv;
|
2002-03-29 07:06:20 +08:00
|
|
|
#endif
|
2001-10-21 04:26:36 +08:00
|
|
|
|
2002-03-27 07:52:52 +08:00
|
|
|
_appVisitor = osgNew AppVisitor;
|
2001-10-21 04:26:36 +08:00
|
|
|
|
2002-03-27 07:52:52 +08:00
|
|
|
_cullVisitor = osgNew CullVisitor;
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
_cullVisitor->setRenderGraph(_rendergraph.get());
|
|
|
|
_cullVisitor->setRenderStage(_renderStage.get());
|
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
_globalState->setGlobalDefaults();
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
// enable lighting by default.
|
|
|
|
_globalState->setMode(GL_LIGHTING, osg::StateAttribute::ON);
|
2001-12-25 05:34:40 +08:00
|
|
|
_light->setStateSetModes(*_globalState,osg::StateAttribute::ON);
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
// enable depth testing by default.
|
|
|
|
_globalState->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
|
|
|
|
|
|
|
|
// set up an alphafunc by default to speed up blending operations.
|
2002-03-27 07:52:52 +08:00
|
|
|
osg::AlphaFunc* alphafunc = osgNew osg::AlphaFunc;
|
2001-09-20 05:08:56 +08:00
|
|
|
alphafunc->setFunction(osg::AlphaFunc::GREATER,0.0f);
|
|
|
|
_globalState->setAttributeAndModes(alphafunc, osg::StateAttribute::ON);
|
|
|
|
|
|
|
|
// set up an alphafunc by default to speed up blending operations.
|
2002-03-27 07:52:52 +08:00
|
|
|
osg::TexEnv* texenv = osgNew osg::TexEnv;
|
2001-09-20 05:08:56 +08:00
|
|
|
texenv->setMode(osg::TexEnv::MODULATE);
|
|
|
|
_globalState->setAttributeAndModes(texenv, osg::StateAttribute::ON);
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2002-03-27 07:52:52 +08:00
|
|
|
osg::LightModel* lightmodel = osgNew osg::LightModel;
|
2002-03-04 06:31:46 +08:00
|
|
|
lightmodel->setAmbientIntensity(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
|
|
|
|
_globalState->setAttributeAndModes(lightmodel, osg::StateAttribute::ON);
|
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
_backgroundColor.set(0.2f, 0.2f, 0.4f, 1.0f);
|
|
|
|
|
2002-03-04 06:31:46 +08:00
|
|
|
_cullMask = 0xffffffff;
|
|
|
|
_cullMaskLeft = 0xffffffff;
|
|
|
|
_cullMaskLeft = 0xffffffff;
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-10-21 04:26:36 +08:00
|
|
|
void SceneView::init()
|
|
|
|
{
|
|
|
|
_initCalled = true;
|
|
|
|
|
|
|
|
if (_sceneData.valid() && _initVisitor.valid())
|
|
|
|
{
|
|
|
|
_initVisitor->reset();
|
|
|
|
_initVisitor->setFrameStamp(_frameStamp.get());
|
|
|
|
|
|
|
|
if (_frameStamp.valid())
|
|
|
|
{
|
|
|
|
_initVisitor->setTraversalNumber(_frameStamp->getFrameNumber());
|
|
|
|
}
|
|
|
|
|
|
|
|
_sceneData->accept(*_initVisitor.get());
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
void SceneView::app()
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-10-21 04:26:36 +08:00
|
|
|
if (!_initCalled) init();
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
if (_sceneData.valid() && _appVisitor.valid())
|
|
|
|
{
|
|
|
|
_appVisitor->reset();
|
2001-09-22 10:42:08 +08:00
|
|
|
|
|
|
|
_appVisitor->setFrameStamp(_frameStamp.get());
|
|
|
|
|
|
|
|
// use the frame number for the traversal number.
|
|
|
|
if (_frameStamp.valid())
|
|
|
|
{
|
|
|
|
_appVisitor->setTraversalNumber(_frameStamp->getFrameNumber());
|
|
|
|
}
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
_sceneData->accept(*_appVisitor.get());
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
2001-09-22 10:42:08 +08:00
|
|
|
|
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
void SceneView::cull()
|
2002-02-14 21:26:37 +08:00
|
|
|
{
|
2002-02-19 07:01:09 +08:00
|
|
|
|
2002-03-30 01:26:40 +08:00
|
|
|
_state->reset();
|
|
|
|
|
|
|
|
|
2002-02-14 21:26:37 +08:00
|
|
|
if (_displaySettings.valid() && _displaySettings->getStereo())
|
|
|
|
{
|
|
|
|
|
|
|
|
_camera->setScreenDistance(_displaySettings->getScreenDistance());
|
|
|
|
|
2002-03-27 07:52:52 +08:00
|
|
|
_cameraLeft = osgNew osg::Camera(*_camera);
|
|
|
|
_cameraRight = osgNew osg::Camera(*_camera);
|
2002-02-14 21:26:37 +08:00
|
|
|
|
|
|
|
float iod = _displaySettings->getEyeSeperation();
|
|
|
|
|
|
|
|
_cameraLeft->adjustEyeOffsetForStereo(osg::Vec3(-iod*0.5,0.0f,0.0f));
|
|
|
|
_cameraRight->adjustEyeOffsetForStereo(osg::Vec3(iod*0.5,0.0f,0.0f));
|
|
|
|
|
2002-02-19 07:01:09 +08:00
|
|
|
if (!_cullVisitorLeft.valid()) _cullVisitorLeft = dynamic_cast<CullVisitor*>(_cullVisitor->cloneType());
|
|
|
|
if (!_rendergraphLeft.valid()) _rendergraphLeft = dynamic_cast<RenderGraph*>(_rendergraph->cloneType());
|
2002-02-14 21:26:37 +08:00
|
|
|
if (!_renderStageLeft.valid()) _renderStageLeft = dynamic_cast<RenderStage*>(_renderStage->cloneType());
|
2002-02-19 07:01:09 +08:00
|
|
|
|
|
|
|
if (!_cullVisitorRight.valid()) _cullVisitorRight = dynamic_cast<CullVisitor*>(_cullVisitor->cloneType());
|
|
|
|
if (!_rendergraphRight.valid()) _rendergraphRight = dynamic_cast<RenderGraph*>(_rendergraph->cloneType());
|
2002-02-14 21:26:37 +08:00
|
|
|
if (!_renderStageRight.valid()) _renderStageRight = dynamic_cast<RenderStage*>(_renderStage->cloneType());
|
|
|
|
|
2002-03-04 06:31:46 +08:00
|
|
|
_cullVisitorLeft->setTraversalMask(_cullMaskLeft);
|
2002-02-19 07:01:09 +08:00
|
|
|
cullStage(_cameraLeft.get(),_cullVisitorLeft.get(),_rendergraphLeft.get(),_renderStageLeft.get());
|
2002-03-04 06:31:46 +08:00
|
|
|
|
|
|
|
_cullVisitorRight->setTraversalMask(_cullMaskRight);
|
2002-02-19 07:01:09 +08:00
|
|
|
cullStage(_cameraRight.get(),_cullVisitorRight.get(),_rendergraphRight.get(),_renderStageRight.get());
|
2002-02-14 21:26:37 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-03-04 06:31:46 +08:00
|
|
|
_cullVisitor->setTraversalMask(_cullMask);
|
2002-02-19 07:01:09 +08:00
|
|
|
cullStage(_camera.get(),_cullVisitor.get(),_rendergraph.get(),_renderStage.get());
|
2002-02-14 21:26:37 +08:00
|
|
|
}
|
2002-02-19 07:01:09 +08:00
|
|
|
|
2002-02-14 21:26:37 +08:00
|
|
|
}
|
|
|
|
|
2002-02-19 07:01:09 +08:00
|
|
|
void SceneView::cullStage(osg::Camera* camera, osgUtil::CullVisitor* cullVisitor, osgUtil::RenderGraph* rendergraph, osgUtil::RenderStage* renderStage)
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-10-21 04:26:36 +08:00
|
|
|
|
2001-12-19 08:38:23 +08:00
|
|
|
if (!_sceneData || !_viewport->valid()) return;
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2001-10-21 04:26:36 +08:00
|
|
|
if (!_initCalled) init();
|
|
|
|
|
2002-03-30 01:26:40 +08:00
|
|
|
if (!_state)
|
|
|
|
{
|
|
|
|
osg::notify(osg::WARN) << "Warning: no valid osgUtil::SceneView::_state"<< std::endl;
|
|
|
|
osg::notify(osg::WARN) << " creating a state automatically."<< std::endl;
|
|
|
|
|
|
|
|
// note the constructor for osg::State will set ContextID to 0.
|
|
|
|
_state = osgNew osg::State;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we in theory should be able to be able to bypass reset, but we'll call it just incase.
|
|
|
|
_state->reset();
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2002-03-30 01:26:40 +08:00
|
|
|
_state->setFrameStamp(_frameStamp.get());
|
|
|
|
_state->setDisplaySettings(_displaySettings.get());
|
|
|
|
|
|
|
|
|
|
|
|
camera->adjustAspectRatio(_viewport->aspectRatio());
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2002-02-19 07:01:09 +08:00
|
|
|
cullVisitor->reset();
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2002-02-19 07:01:09 +08:00
|
|
|
cullVisitor->setFrameStamp(_frameStamp.get());
|
2001-09-22 10:42:08 +08:00
|
|
|
|
|
|
|
// use the frame number for the traversal number.
|
|
|
|
if (_frameStamp.valid())
|
|
|
|
{
|
2002-02-19 07:01:09 +08:00
|
|
|
cullVisitor->setTraversalNumber(_frameStamp->getFrameNumber());
|
2001-09-22 10:42:08 +08:00
|
|
|
}
|
|
|
|
|
2002-02-12 03:51:24 +08:00
|
|
|
// get the camera's modelview
|
2002-04-10 00:09:19 +08:00
|
|
|
osg::Matrix* projection = osgNew osg::Matrix(camera->getProjectionMatrix());
|
2002-03-27 07:52:52 +08:00
|
|
|
osg::Matrix* modelview = osgNew osg::Matrix(camera->getModelViewMatrix());
|
2002-02-12 03:51:24 +08:00
|
|
|
|
2002-02-19 07:01:09 +08:00
|
|
|
cullVisitor->setLODBias(_lodBias);
|
|
|
|
cullVisitor->setEarthSky(NULL); // reset earth sky on each frame.
|
|
|
|
|
|
|
|
cullVisitor->setRenderGraph(rendergraph);
|
|
|
|
cullVisitor->setRenderStage(renderStage);
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2002-04-01 00:40:44 +08:00
|
|
|
// // SandB
|
|
|
|
// //now make it compute "clipping directions" needed for detailed culling
|
|
|
|
// if(cullVisitor->getDetailedCulling())
|
|
|
|
// cullVisitor->calcClippingDirections();//only once pre frame
|
2001-12-17 06:20:26 +08:00
|
|
|
|
2002-02-14 21:26:37 +08:00
|
|
|
renderStage->reset();
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2002-02-19 07:01:09 +08:00
|
|
|
// comment out reset of rendergraph since clean is more efficient.
|
|
|
|
// rendergraph->reset();
|
|
|
|
|
|
|
|
// use clean of the rendergraph rather than reset, as it is able to
|
|
|
|
// reuse the structure on the rendergraph in the next frame. This
|
|
|
|
// achieves a certain amount of frame cohereancy of memory allocation.
|
|
|
|
rendergraph->clean();
|
|
|
|
|
2002-02-14 21:26:37 +08:00
|
|
|
renderStage->setViewport(_viewport.get());
|
|
|
|
renderStage->setClearColor(_backgroundColor);
|
2001-01-11 00:32:10 +08:00
|
|
|
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
switch(_lightingMode)
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-09-20 05:08:56 +08:00
|
|
|
case(HEADLIGHT):
|
2002-02-14 21:26:37 +08:00
|
|
|
renderStage->addLight(_light.get(),NULL);
|
2001-09-20 05:08:56 +08:00
|
|
|
break;
|
|
|
|
case(SKY_LIGHT):
|
2002-02-14 21:26:37 +08:00
|
|
|
renderStage->addLight(_light.get(),modelview);
|
2001-09-20 05:08:56 +08:00
|
|
|
break;
|
|
|
|
case(NO_SCENEVIEW_LIGHT):
|
|
|
|
break;
|
|
|
|
}
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2002-02-19 07:01:09 +08:00
|
|
|
if (_globalState.valid()) cullVisitor->pushStateSet(_globalState.get());
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
|
2002-04-10 00:09:19 +08:00
|
|
|
cullVisitor->pushViewport(_viewport.get());
|
|
|
|
cullVisitor->pushProjectionMatrix(projection);
|
|
|
|
cullVisitor->pushModelViewMatrix(modelview);
|
2002-02-12 03:51:24 +08:00
|
|
|
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
// traverse the scene graph to generate the rendergraph.
|
2002-02-19 07:01:09 +08:00
|
|
|
_sceneData->accept(*cullVisitor);
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2002-02-19 07:01:09 +08:00
|
|
|
if (_globalState.valid()) cullVisitor->popStateSet();
|
2002-02-12 03:51:24 +08:00
|
|
|
|
2002-04-10 00:09:19 +08:00
|
|
|
cullVisitor->popModelViewMatrix();
|
|
|
|
cullVisitor->popProjectionMatrix();
|
|
|
|
cullVisitor->popViewport();
|
2001-01-11 00:32:10 +08:00
|
|
|
|
|
|
|
|
2002-02-19 07:01:09 +08:00
|
|
|
const osg::EarthSky* earthSky = cullVisitor->getEarthSky();
|
2001-10-02 19:36:14 +08:00
|
|
|
if (earthSky)
|
|
|
|
{
|
|
|
|
if (earthSky->getRequiresClear())
|
|
|
|
{
|
2002-02-14 21:26:37 +08:00
|
|
|
renderStage->setClearColor(earthSky->getClearColor());
|
|
|
|
renderStage->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
2001-10-02 19:36:14 +08:00
|
|
|
// really should set clear mask here, but what to? Need
|
|
|
|
// to consider the stencil and accumulation buffers..
|
|
|
|
// will defer to later. Robert Osfield. October 2001.
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// we have an earth sky implementation to do the work for use
|
|
|
|
// so we don't need to clear.
|
2002-02-14 21:26:37 +08:00
|
|
|
renderStage->setClearMask(0);
|
2001-10-02 19:36:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
if (_calc_nearfar)
|
|
|
|
{
|
2002-02-19 07:01:09 +08:00
|
|
|
_near_plane = cullVisitor->getCalculatedNearPlane();
|
|
|
|
_far_plane = cullVisitor->getCalculatedFarPlane();
|
2001-09-20 05:08:56 +08:00
|
|
|
|
|
|
|
if (_near_plane<=_far_plane)
|
|
|
|
{
|
|
|
|
// shift the far plane slight further away from the eye point.
|
|
|
|
// and shift the near plane slightly near the eye point, this
|
|
|
|
// will give a little space betwenn the near and far planes
|
|
|
|
// and the model, crucial when the naer and far planes are
|
|
|
|
// coincedent.
|
|
|
|
_far_plane *= 1.05;
|
|
|
|
_near_plane *= 0.95;
|
|
|
|
|
2002-04-01 00:40:44 +08:00
|
|
|
// // if required clamp the near plane to prevent negative or near zero
|
|
|
|
// // near planes.
|
|
|
|
// if(!cullVisitor->getDetailedCulling())
|
|
|
|
// {
|
2002-02-14 21:26:37 +08:00
|
|
|
float min_near_plane = _far_plane*0.0005f;
|
|
|
|
if (_near_plane<min_near_plane) _near_plane=min_near_plane;
|
2002-04-01 00:40:44 +08:00
|
|
|
// }
|
2001-09-20 05:08:56 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_near_plane = 1.0f;
|
|
|
|
_far_plane = 1000.0f;
|
|
|
|
}
|
|
|
|
|
2002-02-13 06:51:18 +08:00
|
|
|
camera->setNearFar(_near_plane,_far_plane);
|
2001-09-20 05:08:56 +08:00
|
|
|
}
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2002-02-19 07:01:09 +08:00
|
|
|
// prune out any empty RenderGraph children.
|
|
|
|
// note, this would be not required if the rendergraph had been
|
|
|
|
// reset at the start of each frame (see top of this method) but
|
|
|
|
// a clean has been used instead to try to minimize the amount of
|
|
|
|
// allocation and deleteing of the RenderGraph nodes.
|
|
|
|
rendergraph->prune();
|
2001-09-20 05:08:56 +08:00
|
|
|
}
|
2001-01-11 00:32:10 +08:00
|
|
|
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
void SceneView::draw()
|
|
|
|
{
|
2002-03-30 01:26:40 +08:00
|
|
|
|
2001-12-22 06:48:19 +08:00
|
|
|
if (_displaySettings.valid() && _displaySettings->getStereo())
|
2001-12-03 06:20:46 +08:00
|
|
|
{
|
2001-12-19 08:38:23 +08:00
|
|
|
|
2001-12-22 06:48:19 +08:00
|
|
|
_camera->setScreenDistance(_displaySettings->getScreenDistance());
|
2001-12-21 21:07:35 +08:00
|
|
|
|
2001-12-22 06:48:19 +08:00
|
|
|
switch(_displaySettings->getStereoMode())
|
2001-12-03 06:20:46 +08:00
|
|
|
{
|
2001-12-22 06:48:19 +08:00
|
|
|
case(osg::DisplaySettings::QUAD_BUFFER):
|
2001-12-19 08:38:23 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
glDrawBuffer(GL_BACK_LEFT);
|
2002-02-14 21:26:37 +08:00
|
|
|
drawStage(_renderStageLeft.get());
|
2001-12-19 08:38:23 +08:00
|
|
|
|
|
|
|
|
|
|
|
glDrawBuffer(GL_BACK_RIGHT);
|
2002-02-14 21:26:37 +08:00
|
|
|
drawStage(_renderStageRight.get());
|
|
|
|
|
2001-12-19 08:38:23 +08:00
|
|
|
}
|
|
|
|
break;
|
2001-12-22 06:48:19 +08:00
|
|
|
case(osg::DisplaySettings::ANAGLYPHIC):
|
2001-12-19 08:38:23 +08:00
|
|
|
{
|
2001-12-19 23:20:29 +08:00
|
|
|
|
|
|
|
// draw left eye.
|
2002-03-27 18:52:40 +08:00
|
|
|
osg::ref_ptr<osg::ColorMask> red = osgNew osg::ColorMask;
|
|
|
|
red->setMask(true,false,false,true);
|
2002-02-14 21:26:37 +08:00
|
|
|
_globalState->setAttribute(red.get());
|
|
|
|
_renderStageLeft->setColorMask(red.get());
|
|
|
|
drawStage(_renderStageLeft.get());
|
|
|
|
|
|
|
|
// draw right eye.
|
2002-03-27 18:52:40 +08:00
|
|
|
osg::ref_ptr<osg::ColorMask> green = osgNew osg::ColorMask;
|
|
|
|
green->setMask(false,true,true,true);
|
2002-02-14 21:26:37 +08:00
|
|
|
_globalState->setAttribute(green.get());
|
|
|
|
_renderStageRight->setColorMask(green.get());
|
|
|
|
drawStage(_renderStageRight.get());
|
2001-12-19 08:38:23 +08:00
|
|
|
|
2002-03-27 18:52:40 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case(osg::DisplaySettings::HORIZONTAL_SPLIT):
|
|
|
|
{
|
|
|
|
int left_half = _viewport->width()/2;
|
|
|
|
int right_half = _viewport->width()-left_half;
|
|
|
|
|
|
|
|
|
|
|
|
// draw left eye.
|
|
|
|
osg::ref_ptr<osg::Viewport> viewportLeft = osgNew osg::Viewport;
|
|
|
|
viewportLeft->setViewport(_viewport->x(),_viewport->y(),left_half,_viewport->height());
|
|
|
|
_renderStageLeft->setViewport(viewportLeft.get());
|
|
|
|
drawStage(_renderStageLeft.get());
|
|
|
|
|
|
|
|
// draw right eye.
|
|
|
|
osg::ref_ptr<osg::Viewport> viewportRight = osgNew osg::Viewport;
|
|
|
|
viewportRight->setViewport(_viewport->x()+left_half,_viewport->y(),right_half,_viewport->height());
|
|
|
|
_renderStageRight->setViewport(viewportRight.get());
|
|
|
|
drawStage(_renderStageRight.get());
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case(osg::DisplaySettings::VERTICAL_SPLIT):
|
|
|
|
{
|
|
|
|
int bottom_half = _viewport->height()/2;
|
|
|
|
int top_half = _viewport->height()-bottom_half;
|
|
|
|
|
|
|
|
// draw left eye.
|
|
|
|
// assume left eye at top, this could be implementation dependant...
|
|
|
|
osg::ref_ptr<osg::Viewport> viewportLeft = osgNew osg::Viewport;
|
|
|
|
viewportLeft->setViewport(_viewport->x(),_viewport->y()+bottom_half,_viewport->width(),top_half);
|
|
|
|
_renderStageLeft->setViewport(viewportLeft.get());
|
|
|
|
drawStage(_renderStageLeft.get());
|
|
|
|
|
|
|
|
// draw right eye.
|
|
|
|
// assume right eye at top, this could be implementation dependant...
|
|
|
|
osg::ref_ptr<osg::Viewport> viewportRight = osgNew osg::Viewport;
|
|
|
|
viewportRight->setViewport(_viewport->x(),_viewport->y(),_viewport->width(),bottom_half);
|
|
|
|
_renderStageRight->setViewport(viewportRight.get());
|
|
|
|
drawStage(_renderStageRight.get());
|
|
|
|
|
2001-12-19 08:38:23 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
osg::notify(osg::NOTICE)<<"Warning: stereo camera mode not implemented yet."<< std::endl;
|
2002-02-14 21:26:37 +08:00
|
|
|
drawStage(_renderStageLeft.get());
|
2001-12-19 08:38:23 +08:00
|
|
|
}
|
|
|
|
break;
|
2001-12-03 06:20:46 +08:00
|
|
|
}
|
|
|
|
}
|
2001-12-19 08:38:23 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// bog standard draw.
|
2002-02-14 21:26:37 +08:00
|
|
|
drawStage(_renderStage.get());
|
2001-12-19 08:38:23 +08:00
|
|
|
}
|
2002-02-14 21:26:37 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SceneView::drawStage(osgUtil::RenderStage* renderStage)
|
|
|
|
{
|
|
|
|
if (!_sceneData || !_viewport->valid()) return;
|
|
|
|
|
|
|
|
|
|
|
|
// note, to support multi-pipe systems the deletion of OpenGL display list
|
|
|
|
// and texture objects is deferred until the OpenGL context is the correct
|
|
|
|
// context for when the object were originally created. Here we know what
|
|
|
|
// context we are in so can flush the appropriate caches.
|
|
|
|
osg::Drawable::flushDeletedDisplayLists(_state->getContextID());
|
|
|
|
osg::Texture::flushDeletedTextureObjects(_state->getContextID());
|
|
|
|
|
|
|
|
RenderLeaf* previous = NULL;
|
|
|
|
|
|
|
|
renderStage->draw(*_state,previous);
|
2001-12-19 08:38:23 +08:00
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
GLenum errorNo = glGetError();
|
|
|
|
if (errorNo!=GL_NO_ERROR)
|
|
|
|
{
|
2001-12-15 18:00:43 +08:00
|
|
|
osg::notify(WARN)<<"Warning: detected OpenGL error '"<<gluErrorString(errorNo)<<"'"<< std::endl;
|
2001-09-20 05:08:56 +08:00
|
|
|
}
|
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
/** Calculate, via glUnProject, the object coordinates of a window point.
|
|
|
|
Note, current implementation requires that SceneView::draw() has been previously called
|
|
|
|
for projectWindowIntoObject to produce valid values. As per OpenGL
|
|
|
|
windows coordinates are calculated relative to the bottom left of the window.*/
|
|
|
|
bool SceneView::projectWindowIntoObject(const osg::Vec3& window,osg::Vec3& object) const
|
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
return _camera->unproject(window,*_viewport,object);
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
/** Calculate, via glUnProject, the object coordinates of a window x,y
|
|
|
|
when projected onto the near and far planes.
|
|
|
|
Note, current implementation requires that SceneView::draw() has been previously called
|
|
|
|
for projectWindowIntoObject to produce valid values. As per OpenGL
|
|
|
|
windows coordinates are calculated relative to the bottom left of the window.*/
|
|
|
|
bool SceneView::projectWindowXYIntoObject(int x,int y,osg::Vec3& near_point,osg::Vec3& far_point) const
|
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
bool result_near = _camera->unproject(Vec3(x,y,0.0f),*_viewport,near_point);
|
|
|
|
bool result_far = _camera->unproject(Vec3(x,y,1.0f),*_viewport,far_point);
|
2001-09-20 05:08:56 +08:00
|
|
|
return result_near & result_far;
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
/** Calculate, via glProject, the object coordinates of a window.
|
|
|
|
Note, current implementation requires that SceneView::draw() has been previously called
|
|
|
|
for projectWindowIntoObject to produce valid values. As per OpenGL
|
|
|
|
windows coordinates are calculated relative to the bottom left of the window.*/
|
|
|
|
bool SceneView::projectObjectIntoWindow(const osg::Vec3& object,osg::Vec3& window) const
|
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
return _camera->project(object,*_viewport,window);
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|