3 #include <simgear/compiler.h>
4 #include <simgear/structure/exception.hxx>
5 #include <simgear/debug/logstream.hxx>
7 #include <osg/GraphicsContext>
10 #include <osg/Viewport>
11 #include <osgViewer/StatsHandler>
12 #include <osgViewer/Viewer>
13 #include <osgGA/MatrixManipulator>
16 #include "fg_props.hxx"
18 #include "globals.hxx"
19 #include "renderer.hxx"
21 // fg_os implementation using OpenSceneGraph's osgViewer::Viewer class
22 // to create the graphics window and run the event/update/render loop.
24 // fg_os callback registration APIs
28 // Event handling and scene graph update is all handled by a
29 // manipulator. See FGManipulator.cpp
30 void fgRegisterIdleHandler(fgIdleHandler func)
32 globals->get_renderer()->getManipulator()->setIdleHandler(func);
35 void fgRegisterDrawHandler(fgDrawHandler func)
37 globals->get_renderer()->getManipulator()->setDrawHandler(func);
40 void fgRegisterWindowResizeHandler(fgWindowResizeHandler func)
42 globals->get_renderer()->getManipulator()->setWindowResizeHandler(func);
45 void fgRegisterKeyHandler(fgKeyHandler func)
47 globals->get_renderer()->getManipulator()->setKeyHandler(func);
50 void fgRegisterMouseClickHandler(fgMouseClickHandler func)
52 globals->get_renderer()->getManipulator()->setMouseClickHandler(func);
55 void fgRegisterMouseMotionHandler(fgMouseMotionHandler func)
57 globals->get_renderer()->getManipulator()->setMouseMotionHandler(func);
60 // Redraw "happens" every frame whether you want it or not.
61 void fgRequestRedraw()
66 // fg_os implementation
69 static osg::ref_ptr<osgViewer::Viewer> viewer;
70 static osg::ref_ptr<osg::Camera> mainCamera;
72 void fgOSOpenWindow(int w, int h, int bpp,
73 bool alpha, bool stencil, bool fullscreen)
75 osg::GraphicsContext::WindowingSystemInterface* wsi;
76 wsi = osg::GraphicsContext::getWindowingSystemInterface();
78 viewer = new osgViewer::Viewer;
79 // Avoid complications with fg's custom drawables.
81 mode = fgGetString("/sim/rendering/multithreading-mode", "SingleThreaded");
82 if (mode == "AutomaticSelection")
83 viewer->setThreadingModel(osgViewer::Viewer::AutomaticSelection);
84 else if (mode == "CullDrawThreadPerContext")
85 viewer->setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
86 else if (mode == "DrawThreadPerContext")
87 viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
88 else if (mode == "CullThreadPerCameraDrawThreadPerContext")
89 viewer->setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);
91 viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
92 osg::ref_ptr<osg::GraphicsContext::Traits> traits;
93 traits = new osg::GraphicsContext::Traits;
94 int cbits = (bpp <= 16) ? 5 : 8;
95 int zbits = (bpp <= 16) ? 16 : 24;
96 traits->red = traits->green = traits->blue = cbits;
97 traits->depth = zbits;
102 traits->doubleBuffer = true;
103 traits->mipMapGeneration = true;
104 traits->windowName = "FlightGear";
105 traits->sampleBuffers = fgGetBool("/sim/rendering/multi-sample-buffers", traits->sampleBuffers);
106 traits->samples = fgGetBool("/sim/rendering/multi-samples", traits->samples);
107 traits->vsync = fgGetBool("/sim/rendering/vsync-enable", traits->vsync);
112 wsi->getScreenResolution(*traits, width, height);
113 traits->windowDecoration = false;
114 traits->width = width;
115 traits->height = height;
116 traits->supportsResize = false;
118 traits->windowDecoration = true;
121 traits->supportsResize = true;
124 osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
126 // Ok, first the children.
127 // that achieves some magic ordering og the slaves so that we end up
128 // in the main window more often.
129 // This can be sorted out better when we got rid of glut and sdl.
130 if (fgHasNode("/sim/rendering/camera")) {
131 SGPropertyNode* renderingNode = fgGetNode("/sim/rendering");
132 for (int i = 0; i < renderingNode->nChildren(); ++i) {
133 SGPropertyNode* cameraNode = renderingNode->getChild(i);
134 if (strcmp(cameraNode->getName(), "camera") != 0)
137 // get a new copy of the traits struct
138 osg::ref_ptr<osg::GraphicsContext::Traits> cameraTraits;
139 cameraTraits = new osg::GraphicsContext::Traits(*traits);
141 double shearx = cameraNode->getDoubleValue("shear-x", 0);
142 double sheary = cameraNode->getDoubleValue("shear-y", 0);
143 cameraTraits->hostName = cameraNode->getStringValue("host-name", "");
144 cameraTraits->displayNum = cameraNode->getIntValue("display", 0);
145 cameraTraits->screenNum = cameraNode->getIntValue("screen", 0);
146 if (cameraNode->getBoolValue("fullscreen", fullscreen)) {
149 wsi->getScreenResolution(*cameraTraits, width, height);
150 cameraTraits->windowDecoration = false;
151 cameraTraits->width = width;
152 cameraTraits->height = height;
153 cameraTraits->supportsResize = false;
155 cameraTraits->windowDecoration = true;
156 cameraTraits->width = cameraNode->getIntValue("width", w);
157 cameraTraits->height = cameraNode->getIntValue("height", h);
158 cameraTraits->supportsResize = true;
160 // FIXME, currently this is too much of a problem to route the resize
161 // events. When we do no longer need sdl and such this
163 cameraTraits->supportsResize = false;
165 // ok found a camera configuration, add a new slave ...
166 osg::ref_ptr<osg::Camera> camera = new osg::Camera;
168 osg::GraphicsContext* gc;
169 gc = osg::GraphicsContext::createGraphicsContext(cameraTraits.get());
171 camera->setGraphicsContext(gc);
172 // If a viewport isn't set on the camera, then it's hard to dig it
173 // out of the SceneView objects in the viewer, and the coordinates
174 // of mouse events are somewhat bizzare.
175 camera->setViewport(new osg::Viewport(0, 0, cameraTraits->width, cameraTraits->height));
176 camera->setProjectionResizePolicy(rsp);
177 viewer->addSlave(camera.get(), osg::Matrix::translate(-shearx, -sheary, 0), osg::Matrix());
181 // now the main camera ...
182 osg::ref_ptr<osg::Camera> camera = new osg::Camera;
184 osg::GraphicsContext* gc;
185 gc = osg::GraphicsContext::createGraphicsContext(traits.get());
188 camera->setGraphicsContext(gc);
189 // If a viewport isn't set on the camera, then it's hard to dig it
190 // out of the SceneView objects in the viewer, and the coordinates
191 // of mouse events are somewhat bizzare.
192 camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
193 camera->setProjectionResizePolicy(rsp);
194 viewer->addSlave(camera.get());
196 viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
197 // Let FG handle the escape key with a confirmation
198 viewer->setKeyEventSetsDone(0);
199 osgViewer::StatsHandler* statsHandler = new osgViewer::StatsHandler;
200 statsHandler->setKeyEventTogglesOnScreenStats('*');
201 statsHandler->setKeyEventPrintsOutStats(0);
202 viewer->addEventHandler(statsHandler);
203 // The viewer won't start without some root.
204 viewer->setSceneData(new osg::Group);
205 globals->get_renderer()->setViewer(viewer.get());
208 static int status = 0;
210 void fgOSExit(int code)
212 viewer->setDone(true);
222 int fgGetKeyModifiers()
224 return globals->get_renderer()->getManipulator()->getCurrentModifiers();
227 void fgWarpMouse(int x, int y)
229 // Hack, currently the pointer is just recentered. So, we know the relative coordinates ...
230 viewer->requestWarpPointer(0, 0);
234 void fgOSInit(int* argc, char** argv)
239 void fgOSFullScreen()
243 // #define OSG_HAS_MOUSE_CURSOR_PATCH
244 #ifdef OSG_HAS_MOUSE_CURSOR_PATCH
245 static void setMouseCursor(osg::Camera* camera, int cursor)
249 osg::GraphicsContext* gc = camera->getGraphicsContext();
252 osgViewer::GraphicsWindow* gw;
253 gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc);
257 osgViewer::GraphicsWindow::MouseCursor mouseCursor;
258 mouseCursor = osgViewer::GraphicsWindow::InheritCursor;
259 if (cursor == MOUSE_CURSOR_NONE)
260 mouseCursor = osgViewer::GraphicsWindow::NoCursor;
261 else if(cursor == MOUSE_CURSOR_POINTER)
262 mouseCursor = osgViewer::GraphicsWindow::RightArrowCursor;
263 else if(cursor == MOUSE_CURSOR_WAIT)
264 mouseCursor = osgViewer::GraphicsWindow::WaitCursor;
265 else if(cursor == MOUSE_CURSOR_CROSSHAIR)
266 mouseCursor = osgViewer::GraphicsWindow::CrosshairCursor;
267 else if(cursor == MOUSE_CURSOR_LEFTRIGHT)
268 mouseCursor = osgViewer::GraphicsWindow::LeftRightCursor;
270 gw->setCursor(mouseCursor);
274 static int _cursor = -1;
276 void fgSetMouseCursor(int cursor)
279 #ifdef OSG_HAS_MOUSE_CURSOR_PATCH
280 setMouseCursor(viewer->getCamera(), cursor);
281 for (unsigned i = 0; i < viewer->getNumSlaves(); ++i)
282 setMouseCursor(viewer->getSlave(i)._camera.get(), cursor);
286 int fgGetMouseCursor()
293 if (!mainCamera.valid())
295 osg::GraphicsContext* gc = mainCamera->getGraphicsContext();
301 bool fgOSIsMainContext(const osg::GraphicsContext* context)
303 if (!mainCamera.valid())
305 return context == mainCamera->getGraphicsContext();
308 bool fgOSIsMainCamera(const osg::Camera* camera)
312 if (camera == mainCamera.get())
316 if (camera == viewer->getCamera())