speed-dreams/src/modules/graphic/osggraph/Viewer/OsgScreens.cpp

313 lines
9.7 KiB
C++

/***************************************************************************
file : OsgScreens.cpp
created : Sun Jan 13 22:11:03 CEST 2013
copyright : (C) 2013 by Xavier Bertaux
email : bertauxx@yahoo.fr
version : $Id$
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <tgfclient.h>
#include <stdexcept>
#include <osgViewer/Viewer>
#include <osgViewer/GraphicsWindow>
#include <osg/GraphicsContext>
#include <osg/ValueObject>
#include <osg/FrontFace>
#include "OsgScreens.h"
#if SDL_MAJOR_VERSION >= 2
//#include "OsgGraphicsWindow.h"
#endif
#include "OsgDebugHUD.h"
#include "OsgReflectionMapping.h"
#include "OsgMain.h"
#include "OsgCar.h"
#include "OsgHUD.h"
SDScreens::SDScreens() :
root(NULL),
prerenderRoot(NULL),
m_gw(NULL),
m_NbActiveScreens(0),
m_NbArrangeScreens(0),
m_SpanSplit(false),
m_CurrentScreenIndex(0)
{
debugHUD = new SDDebugHUD();
}
extern SDHUD hud;
class CameraDrawnCallback : public osg::Camera::DrawCallback
{
public:
virtual void operator()(const osg::Camera& cam) const
{
getCars()->updateShadingParameters(cam.getViewMatrix());
}
};
void SDScreens::Init(int x,int y, int width, int height, osg::ref_ptr<osg::Node> m_sceneroot, osg::Vec3f fogcolor)
{
//intialising main screen
viewer = new osgViewer::Viewer;
viewer->setLightingMode( osg::View::NO_LIGHT );
viewer->setThreadingModel( osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext );
#if 1 //SDL_MAJOR_VERSION < 2
m_gw = viewer->setUpViewerAsEmbeddedInWindow(0, 0, width, height);
osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw = m_gw;
osg::ref_ptr<osg::Camera> Camera = viewer->getCamera();
//Camera->setGraphicsContext(gw);
//Camera->setViewport(new osg::Viewport(0, 0, width, height));
Camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
Camera->setPreDrawCallback(new CameraDrawnCallback);
Camera->setClearColor(osg::Vec4f(0.3f,0.3f,0.4f,1.0f));
#else
SDL_Window* GfuiWindow = GfScrGetMainWindow();
//viewer->setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);
//viewer->setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
//viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
SDL_GetWindowPosition(GfuiWindow, &traits->x, &traits->y);
SDL_GetWindowSize(GfuiWindow, &traits->width, &traits->height);
traits->windowName = SDL_GetWindowTitle(GfuiWindow);
traits->windowDecoration = !(SDL_GetWindowFlags(GfuiWindow)&SDL_WINDOW_BORDERLESS);
traits->screenNum = SDL_GetWindowDisplayIndex(GfuiWindow);
traits->red = 8;
traits->green = 8;
traits->blue = 8;
traits->alpha = 0; // set to 0 to stop ScreenCaptureHandler reading the alpha channel
traits->depth = 24;
traits->stencil = 8;
traits->vsync = true;
traits->doubleBuffer = true;
traits->inheritedWindowData = new OSGUtil::OsgGraphicsWindowSDL2::WindowData(GfuiWindow);
osg::ref_ptr<OSGUtil::OsgGraphicsWindowSDL2> gw = new OSGUtil::OsgGraphicsWindowSDL2(traits.get());
viewer->getCamera()->setGraphicsContext(gw);
viewer->getCamera()->setViewport(new osg::Viewport(0, 0, width, height));
viewer->getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
viewer->getCamera()->setPreDrawCallback(new CameraDrawnCallback);
if(!gw->valid())
throw std::runtime_error("Failed to create GraphicsContext");
#endif
osg::ref_ptr<osg::Camera> mirrorCam = new osg::Camera;
mirrorCam->setGraphicsContext(gw);
mirrorCam->setClearColor(osg::Vec4f(0.3f,0.3f,0.4f,1.0f));
mirrorCam->setClearMask( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
mirrorCam->setReferenceFrame( osg::Camera::ABSOLUTE_RF );
SDView * view = new SDView((int)Screens.size(), viewer->getCamera(),0,0, width, height, mirrorCam.get());
Screens.push_back(view);
/* Set the scene graph root node for traversal by the viewer */
root = new osg::Group;
viewer->setSceneData(root.get());
#if 1
prerenderRoot = new osg::Group;
root->addChild(prerenderRoot);
//root->addChild(reflectionMapping->getCamerasRoot());
#endif
root->addChild(m_sceneroot.get());
root->addChild(mirrorCam);
mirrorCam->addChild(m_sceneroot.get());
root->getOrCreateStateSet()->setMode( GL_CULL_FACE, osg::StateAttribute::ON );
//create the hud and its own camera and add it to the viewer
hud.CreateHUD(height, width);
hud.camera->setGraphicsContext(gw);
hud.camera->setViewport(0,0, width, height);
viewer->addSlave(hud.camera, false);
//viewer->setSceneData(root.get());
viewer->realize();
}
void SDScreens::InitCars(tSituation *s)
{
const char *pszSpanSplit;
int grNbSuggestedScreens = 0;
for (int i = 0; i < s->_ncars; i++)
{
tCarElt *elt = s->cars[i];
// Pre-assign each human driver (if any) to a different screen
// (set him as the "current driver" for this screen).
if (grNbSuggestedScreens < SD_NB_MAX_SCREEN
&& elt->_driverType == RM_DRV_HUMAN && !elt->_networkPlayer)
{
Screens[0]->setCurrentCar(elt);
GfLogTrace("Screen #%d : Assigned to %s\n", 0, elt->_name);
grNbSuggestedScreens++;
}
}
/* Check whether view should be spanned across vertical splits */
pszSpanSplit = GfParmGetStr(grHandle, GR_SCT_GRAPHIC, GR_ATT_SPANSPLIT, GR_VAL_NO);
m_SpanSplit = strcmp(pszSpanSplit, GR_VAL_YES) ? 0 : 1;
if (m_SpanSplit == 0 && grNbSuggestedScreens > 1)
{
// Mulitplayer, so ignore the stored number of screens
m_NbActiveScreens = grNbSuggestedScreens;
m_NbArrangeScreens = 0;
} else
{
// Load the real number of active screens and the arrangment.
m_NbActiveScreens = (int)GfParmGetNum(grHandle, GR_SCT_DISPMODE, GR_ATT_NB_SCREENS, NULL, 1.0);
m_NbArrangeScreens = (int)GfParmGetNum(grHandle, GR_SCT_DISPMODE, GR_ATT_ARR_SCREENS, NULL, 0.0);
}
// Initialize the cameras for all the screens.
for (unsigned i=0; i<Screens.size();i++)
{
Screens[i]->Init(s);
}
}
void SDScreens::update(tSituation * s, SDFrameInfo* fi,osg::Vec4f(colorfog))
{
if(GfScrUsingResizableWindow())
{
int width = 0;
int height = 0;
int grWinx = 0;
int grWiny = 0;
GfScrGetSize(&grWinx, &grWiny, &width, &height);
m_gw->resized(grWinx,grWiny,width,height);
m_gw->setClearColor(colorfog);
}
for (unsigned i=0; i< Screens.size(); i++)
{
Screens[i]->update(s, fi);
}
SDCars * cars = getCars();
tCarElt * c = this->getActiveView()->getCurrentCar();
this->debugHUD->setTexture(cars->getCar(c)->getReflectionMap()->getReflectionMap());
if (!viewer->done())
viewer->frame();
}
void SDScreens::changeCamera(long p)
{
this->getActiveView()->getCameras()->nextCamera(p);
// For SpanSplit ensure screens change together
if (m_SpanSplit && getActiveView()->getViewOffset() )
{
int camList,camNum;
getActiveView()->getCameras()->getIntSelectedListAndCamera(&camList,&camNum);
for (int i=0; i < m_NbActiveScreens; i++)
if (Screens[i]->getViewOffset() )
Screens[i]->getCameras()->selectCamera(camList,camNum);
}
}
int prevCamList=0;
int prevCamNum=0;
bool usingRearCam = false;
void SDScreens::changeCameraTemporaryOn()
{
//if we are already on rear cam do nothing
if(usingRearCam) return;
int newCamList = 0;
int newCamNum = 0;
GfLogInfo("Switching camera\n");
//remember the currently selected cameras
int camList,camNum;
getActiveView()->getCameras()->getIntSelectedListAndCamera(&camList,&camNum);
GfLogInfo("Previous cam was %i %i \n",camList,camNum);
//temporary switch to this the rear view one
newCamList = 0; //(see osgcamera.cpp for reference)
newCamNum = 5;
prevCamList = camList;
prevCamNum = camNum;
this->getActiveView()->getCameras()->selectCamera(newCamList,newCamNum);
usingRearCam = true;
}
void SDScreens::changeCameraTemporaryOff()
{
//if we are already not on rear cam do nothing
if(!usingRearCam) return;
this->getActiveView()->getCameras()->selectCamera(prevCamList,prevCamNum);
usingRearCam = false;
}
void SDScreens::toggleHUD()
{
hud.ToggleHUD();
}
void SDScreens::toggleHUDwidget(const std::string &widget)
{
hud.ToggleHUDwidget(widget);
}
void SDScreens::toggleHUDwidgets(const std::string & widgets)
{
hud.ToggleHUDwidgets(widgets);
}
void SDScreens::toggleHUDdriverinput()
{
hud.ToggleHUDdriverinput();
}
void SDScreens::toggleHUDeditmode()
{
hud.ToggleHUDeditmode();
}
void SDScreens::registerViewDependantPreRenderNode(osg::ref_ptr<osg::Node> node)
{
//TODO : multi-screen support of this feature
prerenderRoot->addChild(node);
}
SDScreens::~SDScreens()
{
root->removeChildren(0, root->getNumChildren());
root = NULL;
for (unsigned i=0;i< Screens.size();i++)
{
delete Screens[i];
}
delete debugHUD;
}