Modified Files:
src/Input/input.cxx src/Input/input.hxx src/Main/FGManipulator.cxx src/Main/fg_os.cxx src/Main/fg_os.hxx src/Main/fg_os_osgviewer.cxx src/Main/fg_os_sdl.cxx src/Main/renderer.cxx src/Main/renderer.hxx: First cut of osg multi view configurations.
This commit is contained in:
parent
4317dbf729
commit
46ccdeffd4
9 changed files with 333 additions and 204 deletions
|
@ -66,7 +66,7 @@ SG_USING_STD(ifstream);
|
|||
SG_USING_STD(string);
|
||||
SG_USING_STD(vector);
|
||||
|
||||
void mouseClickHandler(int button, int updown, int x, int y);
|
||||
void mouseClickHandler(int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter*);
|
||||
void mouseMotionHandler(int x, int y);
|
||||
void keyHandler(int key, int keymod, int mousex, int mousey);
|
||||
|
||||
|
@ -247,7 +247,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
|
|||
}
|
||||
|
||||
void
|
||||
FGInput::doMouseClick (int b, int updown, int x, int y)
|
||||
FGInput::doMouseClick (int b, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter* ea)
|
||||
{
|
||||
int modifiers = fgGetKeyModifiers();
|
||||
|
||||
|
@ -272,13 +272,15 @@ FGInput::doMouseClick (int b, int updown, int x, int y)
|
|||
}
|
||||
|
||||
if (mode.pass_through) {
|
||||
if (puMouse(b, updown, x, y))
|
||||
// The pu stuff seems to need that. May be it does opengl picking ...
|
||||
fgMakeCurrent();
|
||||
if (0 <= x && 0 <= y && puMouse(b, updown, x, y))
|
||||
return;
|
||||
else if ((globals->get_current_panel() != 0) &&
|
||||
else if (0 <= x && 0 <= y && (globals->get_current_panel() != 0) &&
|
||||
globals->get_current_panel()->getVisibility() &&
|
||||
globals->get_current_panel()->doMouseAction(b, updown, x, y))
|
||||
return;
|
||||
else if (fgHandle3DPanelMouseEvent(b, updown, x, y))
|
||||
else if (0 <= x && 0 <= y && fgHandle3DPanelMouseEvent(b, updown, x, y))
|
||||
return;
|
||||
else {
|
||||
// pui didn't want the click event so compute a
|
||||
|
@ -291,7 +293,7 @@ FGInput::doMouseClick (int b, int updown, int x, int y)
|
|||
// The nearest one is the first one and the deepest
|
||||
// (the most specialized one in the scenegraph) is the first.
|
||||
std::vector<SGSceneryPick> pickList;
|
||||
if (FGRenderer::pick(x, y, pickList)) {
|
||||
if (FGRenderer::pick(x, y, pickList, ea)) {
|
||||
std::vector<SGSceneryPick>::const_iterator i;
|
||||
for (i = pickList.begin(); i != pickList.end(); ++i) {
|
||||
if (i->callback->buttonPressed(b, i->info)) {
|
||||
|
@ -1097,10 +1099,10 @@ void keyHandler(int key, int keymod, int mousex, int mousey)
|
|||
default_input->doKey(key, keymod, mousex, mousey);
|
||||
}
|
||||
|
||||
void mouseClickHandler(int button, int updown, int x, int y)
|
||||
void mouseClickHandler(int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter* ea)
|
||||
{
|
||||
if(default_input)
|
||||
default_input->doMouseClick(button, updown, x, y);
|
||||
default_input->doMouseClick(button, updown, x, y, mainWindow, ea);
|
||||
}
|
||||
|
||||
void mouseMotionHandler(int x, int y)
|
||||
|
|
|
@ -134,7 +134,7 @@ public:
|
|||
* @param x The X position of the mouse event, in screen coordinates.
|
||||
* @param y The Y position of the mouse event, in screen coordinates.
|
||||
*/
|
||||
virtual void doMouseClick (int button, int updown, int x, int y);
|
||||
virtual void doMouseClick (int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter*);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -44,9 +44,8 @@ osg::Node* FGManipulator::getNode()
|
|||
return _node.get();
|
||||
}
|
||||
|
||||
namespace {
|
||||
// All the usual translation from window system to FG / plib
|
||||
int osgToFGModifiers(int modifiers)
|
||||
static int osgToFGModifiers(int modifiers)
|
||||
{
|
||||
int result = 0;
|
||||
if (modifiers & (osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT |
|
||||
|
@ -60,7 +59,6 @@ int osgToFGModifiers(int modifiers)
|
|||
result |= KEYMOD_ALT;
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void FGManipulator::init(const osgGA::GUIEventAdapter& ea,
|
||||
osgGA::GUIActionAdapter& us)
|
||||
|
@ -69,17 +67,29 @@ void FGManipulator::init(const osgGA::GUIEventAdapter& ea,
|
|||
(void)handle(ea, us);
|
||||
}
|
||||
|
||||
namespace {
|
||||
void eventToViewport(const osgGA::GUIEventAdapter& ea,
|
||||
osgGA::GUIActionAdapter& us,
|
||||
int& x, int& y)
|
||||
static bool
|
||||
eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us,
|
||||
int& x, int& y)
|
||||
{
|
||||
x = (int)ea.getX();
|
||||
y = (int)ea.getY();
|
||||
if (ea.getMouseYOrientation()
|
||||
== osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)
|
||||
y = (int)ea.getWindowHeight() - y;
|
||||
}
|
||||
x = -1;
|
||||
y = -1;
|
||||
|
||||
const osgViewer::Viewer* viewer;
|
||||
viewer = dynamic_cast<const osgViewer::Viewer*>(&us);
|
||||
if (!viewer)
|
||||
return false;
|
||||
|
||||
float lx, ly;
|
||||
const osg::Camera* camera;
|
||||
camera = viewer->getCameraContainingPosition(ea.getX(), ea.getY(), lx, ly);
|
||||
|
||||
if (!fgOSIsMainCamera(camera))
|
||||
return false;
|
||||
|
||||
x = int(lx);
|
||||
y = int(camera->getViewport()->height() - ly);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
|
||||
|
@ -101,12 +111,12 @@ bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
|
|||
eventToViewport(ea, us, x, y);
|
||||
if (keyHandler)
|
||||
(*keyHandler)(key, modmask, x, y);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
case osgGA::GUIEventAdapter::PUSH:
|
||||
case osgGA::GUIEventAdapter::RELEASE:
|
||||
{
|
||||
eventToViewport(ea, us, x, y);
|
||||
bool mainWindow = eventToViewport(ea, us, x, y);
|
||||
int button = 0;
|
||||
switch (ea.getButton()) {
|
||||
case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON:
|
||||
|
@ -122,7 +132,7 @@ bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
|
|||
if (mouseClickHandler)
|
||||
(*mouseClickHandler)(button,
|
||||
(ea.getEventType()
|
||||
== osgGA::GUIEventAdapter::RELEASE), x, y);
|
||||
== osgGA::GUIEventAdapter::RELEASE), x, y, mainWindow, &ea);
|
||||
return true;
|
||||
}
|
||||
case osgGA::GUIEventAdapter::MOVE:
|
||||
|
@ -131,10 +141,6 @@ bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
|
|||
if (mouseMotionHandler)
|
||||
(*mouseMotionHandler)(x, y);
|
||||
return true;
|
||||
case osgGA::GUIEventAdapter::RESIZE:
|
||||
if (windowResizeHandler)
|
||||
(*windowResizeHandler)(ea.getWindowWidth(), ea.getWindowHeight());
|
||||
return true;
|
||||
case osgGA::GUIEventAdapter::CLOSE_WINDOW:
|
||||
case osgGA::GUIEventAdapter::QUIT_APPLICATION:
|
||||
fgOSExit(0);
|
||||
|
@ -143,7 +149,7 @@ bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FGManipulator::handleKey(const osgGA::GUIEventAdapter& ea, int& key,
|
||||
int& modifiers)
|
||||
{
|
||||
|
|
|
@ -90,7 +90,7 @@ static void GLUTmotion (int x, int y)
|
|||
static void GLUTmouse (int button, int updown, int x, int y)
|
||||
{
|
||||
GlutModifiers = glutGetModifiers();
|
||||
if(MouseClickHandler) (*MouseClickHandler)(button, updown, x, y);
|
||||
if(MouseClickHandler) (*MouseClickHandler)(button, updown, x, y, true, 0);
|
||||
}
|
||||
|
||||
static void GLUTspecialkeyup(int k, int x, int y)
|
||||
|
@ -240,3 +240,13 @@ void fgOSOpenWindow(int w, int h, int bpp, bool alpha,
|
|||
void fgMakeCurrent()
|
||||
{
|
||||
}
|
||||
|
||||
bool fgOSIsMainCamera(const osg::Camera*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fgOSIsMainContext(const osg::GraphicsContext*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -60,12 +60,15 @@ void fgRequestRedraw();
|
|||
// Callbacks and registration API
|
||||
//
|
||||
|
||||
namespace osg { class Camera; class GraphicsContext; }
|
||||
namespace osgGA { class GUIEventAdapter; }
|
||||
|
||||
typedef void (*fgIdleHandler)();
|
||||
typedef void (*fgDrawHandler)();
|
||||
typedef void (*fgWindowResizeHandler)(int w, int h);
|
||||
|
||||
typedef void (*fgKeyHandler)(int key, int keymod, int mousex, int mousey);
|
||||
typedef void (*fgMouseClickHandler)(int button, int updown, int x, int y);
|
||||
typedef void (*fgMouseClickHandler)(int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter*);
|
||||
typedef void (*fgMouseMotionHandler)(int x, int y);
|
||||
|
||||
void fgRegisterIdleHandler(fgIdleHandler func);
|
||||
|
@ -77,4 +80,8 @@ void fgRegisterMouseClickHandler(fgMouseClickHandler func);
|
|||
void fgRegisterMouseMotionHandler(fgMouseMotionHandler func);
|
||||
|
||||
void fgMakeCurrent();
|
||||
|
||||
bool fgOSIsMainCamera(const osg::Camera* camera);
|
||||
bool fgOSIsMainContext(const osg::GraphicsContext* context);
|
||||
|
||||
#endif // _FG_OS_HXX
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <osgGA/MatrixManipulator>
|
||||
|
||||
#include "fg_os.hxx"
|
||||
#include "fg_props.hxx"
|
||||
#include "util.hxx"
|
||||
#include "globals.hxx"
|
||||
#include "renderer.hxx"
|
||||
|
@ -65,42 +66,133 @@ void fgRequestRedraw()
|
|||
// fg_os implementation
|
||||
//
|
||||
|
||||
|
||||
static osg::ref_ptr<osgViewer::Viewer> viewer;
|
||||
static osg::ref_ptr<osg::Camera> mainCamera;
|
||||
|
||||
void fgOSOpenWindow(int w, int h, int bpp,
|
||||
bool alpha, bool stencil, bool fullscreen)
|
||||
{
|
||||
osg::GraphicsContext::WindowingSystemInterface* wsi;
|
||||
wsi = osg::GraphicsContext::getWindowingSystemInterface();
|
||||
|
||||
viewer = new osgViewer::Viewer;
|
||||
// Avoid complications with fg's custom drawables.
|
||||
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
|
||||
osg::ref_ptr<osg::GraphicsContext::Traits> traits
|
||||
= new osg::GraphicsContext::Traits;
|
||||
std::string mode;
|
||||
mode = fgGetString("/sim/rendering/multithreading-mode", "SingleThreaded");
|
||||
if (mode == "AutomaticSelection")
|
||||
viewer->setThreadingModel(osgViewer::Viewer::AutomaticSelection);
|
||||
else if (mode == "CullDrawThreadPerContext")
|
||||
viewer->setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
|
||||
else if (mode == "DrawThreadPerContext")
|
||||
viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
|
||||
else if (mode == "CullThreadPerCameraDrawThreadPerContext")
|
||||
viewer->setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);
|
||||
else
|
||||
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
|
||||
osg::ref_ptr<osg::GraphicsContext::Traits> traits;
|
||||
traits = new osg::GraphicsContext::Traits;
|
||||
int cbits = (bpp <= 16) ? 5 : 8;
|
||||
int zbits = (bpp <= 16) ? 16 : 24;
|
||||
traits->width = w;
|
||||
traits->height = h;
|
||||
traits->red = traits->green = traits->blue = cbits;
|
||||
traits->depth = zbits;
|
||||
if (alpha)
|
||||
traits->alpha = 8;
|
||||
if (stencil)
|
||||
traits->stencil = 8;
|
||||
if (fullscreen)
|
||||
traits->windowDecoration = false;
|
||||
else
|
||||
traits->windowDecoration = true;
|
||||
traits->supportsResize = true;
|
||||
traits->doubleBuffer = true;
|
||||
osg::GraphicsContext* gc
|
||||
= osg::GraphicsContext::createGraphicsContext(traits.get());
|
||||
viewer->getCamera()->setGraphicsContext(gc);
|
||||
traits->mipMapGeneration = true;
|
||||
traits->windowName = "FlightGear";
|
||||
traits->sampleBuffers = fgGetBool("/sim/rendering/multi-sample-buffers", traits->sampleBuffers);
|
||||
traits->samples = fgGetBool("/sim/rendering/multi-samples", traits->samples);
|
||||
traits->vsync = fgGetBool("/sim/rendering/vsync-enable", traits->vsync);
|
||||
|
||||
if (fullscreen) {
|
||||
unsigned width = 0;
|
||||
unsigned height = 0;
|
||||
wsi->getScreenResolution(*traits, width, height);
|
||||
traits->windowDecoration = false;
|
||||
traits->width = width;
|
||||
traits->height = height;
|
||||
traits->supportsResize = false;
|
||||
} else {
|
||||
traits->windowDecoration = true;
|
||||
traits->width = w;
|
||||
traits->height = h;
|
||||
traits->supportsResize = true;
|
||||
}
|
||||
|
||||
osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
|
||||
|
||||
// Ok, first the children.
|
||||
// that achieves some magic ordering og the slaves so that we end up
|
||||
// in the main window more often.
|
||||
// This can be sorted out better when we got rid of glut and sdl.
|
||||
if (fgHasNode("/sim/rendering/camera")) {
|
||||
SGPropertyNode* renderingNode = fgGetNode("/sim/rendering");
|
||||
for (int i = 0; i < renderingNode->nChildren(); ++i) {
|
||||
SGPropertyNode* cameraNode = renderingNode->getChild(i);
|
||||
if (strcmp(cameraNode->getName(), "camera") != 0)
|
||||
continue;
|
||||
|
||||
// get a new copy of the traits struct
|
||||
osg::ref_ptr<osg::GraphicsContext::Traits> cameraTraits;
|
||||
cameraTraits = new osg::GraphicsContext::Traits(*traits);
|
||||
|
||||
double shearx = cameraNode->getDoubleValue("shear-x", 0);
|
||||
double sheary = cameraNode->getDoubleValue("shear-y", 0);
|
||||
cameraTraits->hostName = cameraNode->getStringValue("host-name", "");
|
||||
cameraTraits->displayNum = cameraNode->getIntValue("display", 0);
|
||||
cameraTraits->screenNum = cameraNode->getIntValue("screen", 0);
|
||||
if (cameraNode->getBoolValue("fullscreen", fullscreen)) {
|
||||
unsigned width = 0;
|
||||
unsigned height = 0;
|
||||
wsi->getScreenResolution(*cameraTraits, width, height);
|
||||
cameraTraits->windowDecoration = false;
|
||||
cameraTraits->width = width;
|
||||
cameraTraits->height = height;
|
||||
cameraTraits->supportsResize = false;
|
||||
} else {
|
||||
cameraTraits->windowDecoration = true;
|
||||
cameraTraits->width = cameraNode->getIntValue("width", w);
|
||||
cameraTraits->height = cameraNode->getIntValue("height", h);
|
||||
cameraTraits->supportsResize = true;
|
||||
}
|
||||
// FIXME, currently this is too much of a problem to route the resize
|
||||
// events. When we do no longer need sdl and such this
|
||||
// can be simplified
|
||||
cameraTraits->supportsResize = false;
|
||||
|
||||
// ok found a camera configuration, add a new slave ...
|
||||
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
|
||||
|
||||
osg::GraphicsContext* gc;
|
||||
gc = osg::GraphicsContext::createGraphicsContext(cameraTraits.get());
|
||||
gc->realize();
|
||||
camera->setGraphicsContext(gc);
|
||||
// If a viewport isn't set on the camera, then it's hard to dig it
|
||||
// out of the SceneView objects in the viewer, and the coordinates
|
||||
// of mouse events are somewhat bizzare.
|
||||
camera->setViewport(new osg::Viewport(0, 0, cameraTraits->width, cameraTraits->height));
|
||||
camera->setProjectionResizePolicy(rsp);
|
||||
viewer->addSlave(camera.get(), osg::Matrix::translate(-shearx, -sheary, 0), osg::Matrix());
|
||||
}
|
||||
}
|
||||
|
||||
// now the main camera ...
|
||||
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
|
||||
mainCamera = camera;
|
||||
osg::GraphicsContext* gc;
|
||||
gc = osg::GraphicsContext::createGraphicsContext(traits.get());
|
||||
gc->realize();
|
||||
gc->makeCurrent();
|
||||
camera->setGraphicsContext(gc);
|
||||
// If a viewport isn't set on the camera, then it's hard to dig it
|
||||
// out of the SceneView objects in the viewer, and the coordinates
|
||||
// of mouse events are somewhat bizzare.
|
||||
viewer->getCamera()->setViewport(new osg::Viewport(0, 0,
|
||||
traits->width,
|
||||
traits->height));
|
||||
camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
|
||||
camera->setProjectionResizePolicy(rsp);
|
||||
viewer->addSlave(camera.get());
|
||||
|
||||
viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
|
||||
// Let FG handle the escape key with a confirmation
|
||||
viewer->setKeyEventSetsDone(0);
|
||||
|
@ -134,7 +226,8 @@ int fgGetKeyModifiers()
|
|||
|
||||
void fgWarpMouse(int x, int y)
|
||||
{
|
||||
viewer->requestWarpPointer((float)x, (float)y);
|
||||
// Hack, currently the pointer is just recentered. So, we know the relative coordinates ...
|
||||
viewer->requestWarpPointer(0, 0);
|
||||
}
|
||||
|
||||
// Noop
|
||||
|
@ -142,24 +235,85 @@ void fgOSInit(int* argc, char** argv)
|
|||
{
|
||||
}
|
||||
|
||||
// Noop
|
||||
void fgOSFullScreen()
|
||||
{
|
||||
// Noop, but is probably doable
|
||||
|
||||
}
|
||||
|
||||
// No support in OSG yet
|
||||
// #define OSG_HAS_MOUSE_CURSOR_PATCH
|
||||
#ifdef OSG_HAS_MOUSE_CURSOR_PATCH
|
||||
static void setMouseCursor(osg::Camera* camera, int cursor)
|
||||
{
|
||||
if (!camera)
|
||||
return;
|
||||
osg::GraphicsContext* gc = camera->getGraphicsContext();
|
||||
if (!gc)
|
||||
return;
|
||||
osgViewer::GraphicsWindow* gw;
|
||||
gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc);
|
||||
if (!gw)
|
||||
return;
|
||||
|
||||
osgViewer::GraphicsWindow::MouseCursor mouseCursor;
|
||||
mouseCursor = osgViewer::GraphicsWindow::InheritCursor;
|
||||
if (cursor == MOUSE_CURSOR_NONE)
|
||||
mouseCursor = osgViewer::GraphicsWindow::NoCursor;
|
||||
else if(cursor == MOUSE_CURSOR_POINTER)
|
||||
mouseCursor = osgViewer::GraphicsWindow::RightArrowCursor;
|
||||
else if(cursor == MOUSE_CURSOR_WAIT)
|
||||
mouseCursor = osgViewer::GraphicsWindow::WaitCursor;
|
||||
else if(cursor == MOUSE_CURSOR_CROSSHAIR)
|
||||
mouseCursor = osgViewer::GraphicsWindow::CrosshairCursor;
|
||||
else if(cursor == MOUSE_CURSOR_LEFTRIGHT)
|
||||
mouseCursor = osgViewer::GraphicsWindow::LeftRightCursor;
|
||||
|
||||
gw->setCursor(mouseCursor);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _cursor = -1;
|
||||
|
||||
void fgSetMouseCursor(int cursor)
|
||||
{
|
||||
_cursor = cursor;
|
||||
#ifdef OSG_HAS_MOUSE_CURSOR_PATCH
|
||||
setMouseCursor(viewer->getCamera(), cursor);
|
||||
for (unsigned i = 0; i < viewer->getNumSlaves(); ++i)
|
||||
setMouseCursor(viewer->getSlave(i)._camera.get(), cursor);
|
||||
#endif
|
||||
}
|
||||
|
||||
int fgGetMouseCursor()
|
||||
{
|
||||
return 0;
|
||||
return _cursor;
|
||||
}
|
||||
|
||||
void fgMakeCurrent()
|
||||
{
|
||||
osg::GraphicsContext* gc = viewer->getCamera()->getGraphicsContext();
|
||||
if (!mainCamera.valid())
|
||||
return;
|
||||
osg::GraphicsContext* gc = mainCamera->getGraphicsContext();
|
||||
if (!gc)
|
||||
return;
|
||||
gc->makeCurrent();
|
||||
}
|
||||
|
||||
bool fgOSIsMainContext(const osg::GraphicsContext* context)
|
||||
{
|
||||
if (!mainCamera.valid())
|
||||
return false;
|
||||
return context == mainCamera->getGraphicsContext();
|
||||
}
|
||||
|
||||
bool fgOSIsMainCamera(const osg::Camera* camera)
|
||||
{
|
||||
if (!camera)
|
||||
return false;
|
||||
if (camera == mainCamera.get())
|
||||
return true;
|
||||
if (!viewer.valid())
|
||||
return false;
|
||||
if (camera == viewer->getCamera())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@ void fgOSMainLoop()
|
|||
if(MouseClickHandler)
|
||||
(*MouseClickHandler)(e.button.button - 1,
|
||||
e.button.state == SDL_RELEASED,
|
||||
e.button.x, e.button.y);
|
||||
e.button.x, e.button.y, true, 0);
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
CurrentMouseX = e.motion.x;
|
||||
|
@ -412,3 +412,13 @@ static void initCursors()
|
|||
void fgMakeCurrent()
|
||||
{
|
||||
}
|
||||
|
||||
bool fgOSIsMainCamera(const osg::Camera*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fgOSIsMainContext(const osg::GraphicsContext*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include <osgUtil/SceneView>
|
||||
#include <osgUtil/UpdateVisitor>
|
||||
#include <osgUtil/IntersectVisitor>
|
||||
#include <osgUtil/LineSegmentIntersector>
|
||||
|
||||
#include <osg/io_utils>
|
||||
#include <osgDB/WriteFile>
|
||||
|
@ -125,6 +126,9 @@ public:
|
|||
{ drawImplementation(*renderInfo.getState()); }
|
||||
void drawImplementation(osg::State& state) const
|
||||
{
|
||||
if (!fgOSIsMainContext(state.getGraphicsContext()))
|
||||
return;
|
||||
|
||||
state.pushStateSet(getStateSet());
|
||||
state.apply();
|
||||
state.setActiveTextureUnit(0);
|
||||
|
@ -174,6 +178,10 @@ public:
|
|||
{ drawImplementation(*renderInfo.getState()); }
|
||||
void drawImplementation(osg::State& state) const
|
||||
{
|
||||
// std::cout << state.getGraphicsContext() << std::endl;
|
||||
if (!fgOSIsMainContext(state.getGraphicsContext()))
|
||||
return;
|
||||
|
||||
state.pushStateSet(getStateSet());
|
||||
state.apply();
|
||||
state.setActiveTextureUnit(0);
|
||||
|
@ -428,7 +436,7 @@ FGRenderer::init( void ) {
|
|||
glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
|
||||
|
||||
if (viewer) {
|
||||
viewer->getCamera()
|
||||
viewer->getCamera()
|
||||
->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
} else {
|
||||
sceneView->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
|
@ -797,6 +805,7 @@ FGRenderer::update( bool refresh_camera_settings ) {
|
|||
// need to call the update visitor once
|
||||
if (!viewer) {
|
||||
mFrameStamp->setReferenceTime(globals->get_sim_time_sec());
|
||||
mFrameStamp->setSimulationTime(globals->get_sim_time_sec());
|
||||
mFrameStamp->setFrameNumber(1+mFrameStamp->getFrameNumber());
|
||||
}
|
||||
mFrameStamp->setCalendarTime(*globals->get_time_params()->getGmt());
|
||||
|
@ -845,8 +854,9 @@ FGRenderer::resize( int width, int height ) {
|
|||
}
|
||||
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
|
||||
if (viewer)
|
||||
viewer->getCamera()->getViewport()->setViewport(0, height - view_h,
|
||||
width, view_h);
|
||||
;
|
||||
// viewer->getCamera()->getViewport()->setViewport(0, height - view_h,
|
||||
// width, view_h);
|
||||
else
|
||||
sceneView->getViewport()->setViewport(0, height - view_h,
|
||||
width, view_h);
|
||||
|
@ -874,84 +884,6 @@ FGRenderer::resize( int width, int height ) {
|
|||
}
|
||||
|
||||
|
||||
// These are wrapper functions around ssgSetNearFar() and ssgSetFOV()
|
||||
// which will post process and rewrite the resulting frustum if we
|
||||
// want to do asymmetric view frustums.
|
||||
|
||||
static void fgHackFrustum() {
|
||||
|
||||
// specify a percent of the configured view frustum to actually
|
||||
// display. This is a bit of a hack to achieve asymmetric view
|
||||
// frustums. For instance, if you want to display two monitors
|
||||
// side by side, you could specify each with a double fov, a 0.5
|
||||
// aspect ratio multiplier, and then the left side monitor would
|
||||
// have a left_pct = 0.0, a right_pct = 0.5, a bottom_pct = 0.0,
|
||||
// and a top_pct = 1.0. The right side monitor would have a
|
||||
// left_pct = 0.5 and a right_pct = 1.0.
|
||||
|
||||
static SGPropertyNode *left_pct
|
||||
= fgGetNode("/sim/current-view/frustum-left-pct");
|
||||
static SGPropertyNode *right_pct
|
||||
= fgGetNode("/sim/current-view/frustum-right-pct");
|
||||
static SGPropertyNode *bottom_pct
|
||||
= fgGetNode("/sim/current-view/frustum-bottom-pct");
|
||||
static SGPropertyNode *top_pct
|
||||
= fgGetNode("/sim/current-view/frustum-top-pct");
|
||||
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
|
||||
double left, right;
|
||||
double bottom, top;
|
||||
double zNear, zFar;
|
||||
if (viewer)
|
||||
viewer->getCamera()->getProjectionMatrixAsFrustum(left, right,
|
||||
bottom, top,
|
||||
zNear, zFar);
|
||||
else
|
||||
sceneView->getProjectionMatrixAsFrustum(left, right, bottom, top,
|
||||
zNear, zFar);
|
||||
// cout << " l = " << f->getLeft()
|
||||
// << " r = " << f->getRight()
|
||||
// << " b = " << f->getBot()
|
||||
// << " t = " << f->getTop()
|
||||
// << " n = " << f->getNear()
|
||||
// << " f = " << f->getFar()
|
||||
// << endl;
|
||||
|
||||
double width = right - left;
|
||||
double height = top - bottom;
|
||||
|
||||
double l, r, t, b;
|
||||
|
||||
if ( left_pct != NULL ) {
|
||||
l = left + width * left_pct->getDoubleValue();
|
||||
} else {
|
||||
l = left;
|
||||
}
|
||||
|
||||
if ( right_pct != NULL ) {
|
||||
r = left + width * right_pct->getDoubleValue();
|
||||
} else {
|
||||
r = right;
|
||||
}
|
||||
|
||||
if ( bottom_pct != NULL ) {
|
||||
b = bottom + height * bottom_pct->getDoubleValue();
|
||||
} else {
|
||||
b = bottom;
|
||||
}
|
||||
|
||||
if ( top_pct != NULL ) {
|
||||
t = bottom + height * top_pct->getDoubleValue();
|
||||
} else {
|
||||
t = top;
|
||||
}
|
||||
if (viewer)
|
||||
viewer->getCamera()->setProjectionMatrixAsFrustum(l, r, b, t,
|
||||
zNear, zFar);
|
||||
else
|
||||
sceneView->setProjectionMatrixAsFrustum(l, r, b, t, zNear, zFar);
|
||||
}
|
||||
|
||||
|
||||
// we need some static storage space for these values. However, we
|
||||
// can't store it in a renderer class object because the functions
|
||||
// that manipulate these are static. They are static so they can
|
||||
|
@ -972,17 +904,11 @@ void FGRenderer::setFOV( float w, float h ) {
|
|||
fov_height = h;
|
||||
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
|
||||
if (viewer)
|
||||
viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height,
|
||||
fov_width/fov_height,
|
||||
fov_near, fov_far);
|
||||
viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, fov_near, fov_far);
|
||||
else
|
||||
sceneView->setProjectionMatrixAsPerspective(fov_height,
|
||||
fov_width/fov_height,
|
||||
fov_near, fov_far);
|
||||
// fully specify the view frustum before hacking it (so we don't
|
||||
// accumulate hacked effects
|
||||
fgHackFrustum();
|
||||
// sgEnviro.setFOV( w, h );
|
||||
}
|
||||
|
||||
|
||||
|
@ -996,36 +922,29 @@ n = 0.1;
|
|||
fov_far = f;
|
||||
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
|
||||
if (viewer)
|
||||
viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height,
|
||||
fov_width/fov_height,
|
||||
fov_near, fov_far);
|
||||
else
|
||||
viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, fov_near, fov_far);
|
||||
else
|
||||
sceneView->setProjectionMatrixAsPerspective(fov_height,
|
||||
fov_width/fov_height,
|
||||
fov_near, fov_far);
|
||||
|
||||
// fully specify the view frustum before hacking it (so we don't
|
||||
// accumulate hacked effects
|
||||
fgHackFrustum();
|
||||
}
|
||||
|
||||
bool
|
||||
FGRenderer::pick( unsigned x, unsigned y,
|
||||
std::vector<SGSceneryPick>& pickList )
|
||||
std::vector<SGSceneryPick>& pickList,
|
||||
const osgGA::GUIEventAdapter* ea )
|
||||
{
|
||||
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
|
||||
// wipe out the return ...
|
||||
pickList.resize(0);
|
||||
|
||||
osg::Node* sceneData = globals->get_scenery()->get_scene_graph();
|
||||
if (!sceneData)
|
||||
return false;
|
||||
osg::Viewport* viewport = 0;
|
||||
osg::Matrix projection;
|
||||
osg::Matrix modelview;
|
||||
|
||||
if (sceneView.valid()) {
|
||||
viewport = sceneView->getViewport();
|
||||
osg::Node* sceneData = globals->get_scenery()->get_scene_graph();
|
||||
if (!sceneData)
|
||||
return false;
|
||||
|
||||
osg::Viewport* viewport = sceneView->getViewport();
|
||||
if (!viewport)
|
||||
return false;
|
||||
// don't know why, but the update has partly happened somehow,
|
||||
|
@ -1047,40 +966,64 @@ FGRenderer::pick( unsigned x, unsigned y,
|
|||
// accumulated transform
|
||||
if (!nodePath.empty())
|
||||
modelview.preMult(computeLocalToWorld(nodePath.front()));
|
||||
} else if (viewer) {
|
||||
// I don't think the Viewer case needs to update the camera
|
||||
// matrices before picking. The user has clicked on the old scene
|
||||
// -- that which is displayed in the front buffer -- so we need to
|
||||
// use the camera state in effect for that view of the scene.
|
||||
osg::Camera *camera = viewer->getCamera();
|
||||
viewport = camera->getViewport();
|
||||
projection = camera->getProjectionMatrix();
|
||||
modelview = camera->getViewMatrix();
|
||||
// Accumulated transforms? Don't think that applies for the
|
||||
// Viewer's camera.
|
||||
} else { // we can get called early ...
|
||||
return false;
|
||||
}
|
||||
// swap the y values ...
|
||||
y = viewport->height() - y;
|
||||
// set up the pick visitor
|
||||
osgUtil::PickVisitor pickVisitor(viewport, projection, modelview, x, y);
|
||||
sceneData->accept(pickVisitor);
|
||||
if (!pickVisitor.hits())
|
||||
return false;
|
||||
|
||||
// collect all interaction callbacks on the pick ray.
|
||||
// They get stored in the pickCallbacks list where they are sorted back
|
||||
// to front and croasest to finest wrt the scenery node they are attached to
|
||||
osgUtil::PickVisitor::LineSegmentHitListMap::const_iterator mi;
|
||||
for (mi = pickVisitor.getSegHitList().begin();
|
||||
mi != pickVisitor.getSegHitList().end();
|
||||
++mi) {
|
||||
osgUtil::IntersectVisitor::HitList::const_iterator hi;
|
||||
for (hi = mi->second.begin(); hi != mi->second.end(); ++hi) {
|
||||
// ok, go back the nodes and ask for intersection callbacks,
|
||||
// execute them in top down order
|
||||
const osg::NodePath& np = hi->getNodePath();
|
||||
// swap the y values ...
|
||||
y = viewport->height() - y;
|
||||
// set up the pick visitor
|
||||
osgUtil::PickVisitor pickVisitor(viewport, projection, modelview, x, y);
|
||||
sceneData->accept(pickVisitor);
|
||||
if (!pickVisitor.hits())
|
||||
return false;
|
||||
|
||||
// collect all interaction callbacks on the pick ray.
|
||||
// They get stored in the pickCallbacks list where they are sorted back
|
||||
// to front and croasest to finest wrt the scenery node they are attached to
|
||||
osgUtil::PickVisitor::LineSegmentHitListMap::const_iterator mi;
|
||||
for (mi = pickVisitor.getSegHitList().begin();
|
||||
mi != pickVisitor.getSegHitList().end();
|
||||
++mi) {
|
||||
osgUtil::IntersectVisitor::HitList::const_iterator hi;
|
||||
for (hi = mi->second.begin(); hi != mi->second.end(); ++hi) {
|
||||
// ok, go back the nodes and ask for intersection callbacks,
|
||||
// execute them in top down order
|
||||
const osg::NodePath& np = hi->getNodePath();
|
||||
osg::NodePath::const_reverse_iterator npi;
|
||||
for (npi = np.rbegin(); npi != np.rend(); ++npi) {
|
||||
SGSceneUserData* ud = SGSceneUserData::getSceneUserData(*npi);
|
||||
if (!ud)
|
||||
continue;
|
||||
for (unsigned i = 0; i < ud->getNumPickCallbacks(); ++i) {
|
||||
SGPickCallback* pickCallback = ud->getPickCallback(i);
|
||||
if (!pickCallback)
|
||||
continue;
|
||||
SGSceneryPick sceneryPick;
|
||||
/// note that this is done totally in doubles instead of
|
||||
/// just using getWorldIntersectionPoint
|
||||
osg::Vec3d localPt = hi->getLocalIntersectPoint();
|
||||
sceneryPick.info.local = SGVec3d(localPt);
|
||||
if (hi->getMatrix())
|
||||
sceneryPick.info.wgs84 = SGVec3d(localPt*(*hi->getMatrix()));
|
||||
else
|
||||
sceneryPick.info.wgs84 = SGVec3d(localPt);
|
||||
sceneryPick.callback = pickCallback;
|
||||
pickList.push_back(sceneryPick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !pickList.empty();
|
||||
|
||||
} else if (viewer) {
|
||||
|
||||
// just compute intersections in the viewers method ...
|
||||
typedef osgUtil::LineSegmentIntersector::Intersections Intersections;
|
||||
Intersections intersections;
|
||||
viewer->computeIntersections(ea->getX(), ea->getY(), intersections);
|
||||
|
||||
Intersections::iterator hit;
|
||||
for (hit = intersections.begin(); hit != intersections.end(); ++hit) {
|
||||
const osg::NodePath& np = hit->nodePath;
|
||||
osg::NodePath::const_reverse_iterator npi;
|
||||
for (npi = np.rbegin(); npi != np.rend(); ++npi) {
|
||||
SGSceneUserData* ud = SGSceneUserData::getSceneUserData(*npi);
|
||||
|
@ -1091,22 +1034,18 @@ FGRenderer::pick( unsigned x, unsigned y,
|
|||
if (!pickCallback)
|
||||
continue;
|
||||
SGSceneryPick sceneryPick;
|
||||
/// note that this is done totally in doubles instead of
|
||||
/// just using getWorldIntersectionPoint
|
||||
osg::Vec3d localPt = hi->getLocalIntersectPoint();
|
||||
sceneryPick.info.local = SGVec3d(localPt);
|
||||
if (hi->getMatrix())
|
||||
sceneryPick.info.wgs84 = SGVec3d(localPt*(*hi->getMatrix()));
|
||||
else
|
||||
sceneryPick.info.wgs84 = SGVec3d(localPt);
|
||||
sceneryPick.info.local = SGVec3d(hit->getLocalIntersectPoint());
|
||||
sceneryPick.info.wgs84 = SGVec3d(hit->getWorldIntersectPoint());
|
||||
sceneryPick.callback = pickCallback;
|
||||
pickList.push_back(sceneryPick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !pickList.empty();
|
||||
return !pickList.empty();
|
||||
} else { // we can get called early ...
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool fgDumpSceneGraphToFile(const char* filename)
|
||||
|
|
|
@ -54,7 +54,8 @@ public:
|
|||
/** Just pick into the scene and return the pick callbacks on the way ...
|
||||
*/
|
||||
static bool pick( unsigned x, unsigned y,
|
||||
std::vector<SGSceneryPick>& pickList );
|
||||
std::vector<SGSceneryPick>& pickList,
|
||||
const osgGA::GUIEventAdapter* ea );
|
||||
|
||||
/** Get and set the OSG Viewer object, if any.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue