#include "FGEventHandler.hxx"
#include "WindowBuilder.hxx"
#include "WindowSystemAdapter.hxx"
+
+#include <simgear/math/SGRect.hxx>
#include <simgear/props/props.hxx>
+#include <simgear/props/props_io.hxx> // for copyProperties
#include <simgear/structure/OSGUtils.hxx>
#include <simgear/structure/OSGVersion.hxx>
#include <simgear/scene/material/EffectCullVisitor.hxx>
#include <osgViewer/GraphicsWindow>
#include <osgViewer/Renderer>
-namespace flightgear {
-const char* MAIN_CAMERA = "main";
-const char* FAR_CAMERA = "far";
-const char* GEOMETRY_CAMERA = "geometry";
-const char* SHADOW_CAMERA = "shadow";
-const char* LIGHTING_CAMERA = "lighting";
-const char* DISPLAY_CAMERA = "display";
-}
-
-static osg::Matrix
-invert(const osg::Matrix& matrix)
-{
- return osg::Matrix::inverse(matrix);
-}
+using namespace osg;
-/// Returns the zoom factor of the master camera.
-/// The reference fov is the historic 55 deg
-static double
-zoomFactor()
+namespace
{
- double fov = fgGetDouble("/sim/current-view/field-of-view", 55);
- if (fov < 1)
- fov = 1;
- return tan(55*0.5*SG_DEGREES_TO_RADIANS)/tan(fov*0.5*SG_DEGREES_TO_RADIANS);
-}
+
+ // Given a projection matrix, return a new one with the same frustum
+ // sides and new near / far values.
+
+ void makeNewProjMat(Matrixd& oldProj, double znear,
+ double zfar, Matrixd& projection)
+ {
+ projection = oldProj;
+ // Slightly inflate the near & far planes to avoid objects at the
+ // extremes being clipped out.
+ znear *= 0.999;
+ zfar *= 1.001;
+
+ // Clamp the projection matrix z values to the range (near, far)
+ double epsilon = 1.0e-6;
+ if (fabs(projection(0,3)) < epsilon &&
+ fabs(projection(1,3)) < epsilon &&
+ fabs(projection(2,3)) < epsilon) {
+ // Projection is Orthographic
+ epsilon = -1.0/(zfar - znear); // Used as a temp variable
+ projection(2,2) = 2.0*epsilon;
+ projection(3,2) = (zfar + znear)*epsilon;
+ } else {
+ // Projection is Perspective
+ double trans_near = (-znear*projection(2,2) + projection(3,2)) /
+ (-znear*projection(2,3) + projection(3,3));
+ double trans_far = (-zfar*projection(2,2) + projection(3,2)) /
+ (-zfar*projection(2,3) + projection(3,3));
+ double ratio = fabs(2.0/(trans_near - trans_far));
+ double center = -0.5*(trans_near + trans_far);
+
+ projection.postMult(osg::Matrixd(1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, ratio, 0.0,
+ 0.0, 0.0, center*ratio, 1.0));
+ }
+ }
+
+ osg::Matrix
+ invert(const osg::Matrix& matrix)
+ {
+ return osg::Matrix::inverse(matrix);
+ }
+
+ /// Returns the zoom factor of the master camera.
+ /// The reference fov is the historic 55 deg
+ double
+ zoomFactor()
+ {
+ double fov = fgGetDouble("/sim/current-view/field-of-view", 55);
+ if (fov < 1)
+ fov = 1;
+ return tan(55*0.5*SG_DEGREES_TO_RADIANS)/tan(fov*0.5*SG_DEGREES_TO_RADIANS);
+ }
+
+ osg::Vec2d
+ preMult(const osg::Vec2d& v, const osg::Matrix& m)
+ {
+ osg::Vec3d tmp = m.preMult(osg::Vec3(v, 0));
+ return osg::Vec2d(tmp[0], tmp[1]);
+ }
+
+ osg::Matrix
+ relativeProjection(const osg::Matrix& P0, const osg::Matrix& R, const osg::Vec2d ref[2],
+ const osg::Matrix& pP, const osg::Matrix& pR, const osg::Vec2d pRef[2])
+ {
+ // Track the way from one projection space to the other:
+ // We want
+ // P = T*S*P0
+ // where P0 is the projection template sensible for the given window size,
+ // T is a translation matrix and S a scale matrix.
+ // We need to determine T and S so that the reference points in the parents
+ // projection space match the two reference points in this cameras projection space.
+
+ // Starting from the parents camera projection space, we get into this cameras
+ // projection space by the transform matrix:
+ // P*R*inv(pP*pR) = T*S*P0*R*inv(pP*pR)
+ // So, at first compute that matrix without T*S and determine S and T from that
+
+ // Ok, now osg uses the inverse matrix multiplication order, thus:
+ osg::Matrix PtoPwithoutTS = invert(pR*pP)*R*P0;
+ // Compute the parents reference points in the current projection space
+ // without the yet unknown T and S
+ osg::Vec2d pRefInThis[2] = {
+ preMult(pRef[0], PtoPwithoutTS),
+ preMult(pRef[1], PtoPwithoutTS)
+ };
+
+ // To get the same zoom, rescale to match the parents size
+ double s = (ref[0] - ref[1]).length()/(pRefInThis[0] - pRefInThis[1]).length();
+ osg::Matrix S = osg::Matrix::scale(s, s, 1);
+
+ // For the translation offset, incorporate the now known scale
+ // and recompute the position ot the first reference point in the
+ // currents projection space without the yet unknown T.
+ pRefInThis[0] = preMult(pRef[0], PtoPwithoutTS*S);
+ // The translation is then the difference of the reference points
+ osg::Matrix T = osg::Matrix::translate(osg::Vec3d(ref[0] - pRefInThis[0], 0));
+
+ // Compose and return the desired final projection matrix
+ return P0*S*T;
+ }
-static osg::Vec2d
-preMult(const osg::Vec2d& v, const osg::Matrix& m)
-{
- osg::Vec3d tmp = m.preMult(osg::Vec3(v, 0));
- return osg::Vec2d(tmp[0], tmp[1]);
-}
+} // of anonymous namespace
-static osg::Matrix
-relativeProjection(const osg::Matrix& P0, const osg::Matrix& R, const osg::Vec2d ref[2],
- const osg::Matrix& pP, const osg::Matrix& pR, const osg::Vec2d pRef[2])
-{
- // Track the way from one projection space to the other:
- // We want
- // P = T*S*P0
- // where P0 is the projection template sensible for the given window size,
- // T is a translation matrix and S a scale matrix.
- // We need to determine T and S so that the reference points in the parents
- // projection space match the two reference points in this cameras projection space.
-
- // Starting from the parents camera projection space, we get into this cameras
- // projection space by the transform matrix:
- // P*R*inv(pP*pR) = T*S*P0*R*inv(pP*pR)
- // So, at first compute that matrix without T*S and determine S and T from that
-
- // Ok, now osg uses the inverse matrix multiplication order, thus:
- osg::Matrix PtoPwithoutTS = invert(pR*pP)*R*P0;
- // Compute the parents reference points in the current projection space
- // without the yet unknown T and S
- osg::Vec2d pRefInThis[2] = {
- preMult(pRef[0], PtoPwithoutTS),
- preMult(pRef[1], PtoPwithoutTS)
- };
-
- // To get the same zoom, rescale to match the parents size
- double s = (ref[0] - ref[1]).length()/(pRefInThis[0] - pRefInThis[1]).length();
- osg::Matrix S = osg::Matrix::scale(s, s, 1);
-
- // For the translation offset, incorporate the now known scale
- // and recompute the position ot the first reference point in the
- // currents projection space without the yet unknown T.
- pRefInThis[0] = preMult(pRef[0], PtoPwithoutTS*S);
- // The translation is then the difference of the reference points
- osg::Matrix T = osg::Matrix::translate(osg::Vec3d(ref[0] - pRefInThis[0], 0));
-
- // Compose and return the desired final projection matrix
- return P0*S*T;
-}
+typedef std::vector<SGPropertyNode_ptr> SGPropertyNodeVec;
namespace flightgear
{
using std::strcmp;
using std::string;
-ref_ptr<CameraGroup> CameraGroup::_defaultGroup;
-
-CameraGroup::CameraGroup(osgViewer::Viewer* viewer) :
- _viewer(viewer)
-{
-}
-
-}
-
-namespace
-{
-using namespace osg;
-
-// Given a projection matrix, return a new one with the same frustum
-// sides and new near / far values.
-
-void makeNewProjMat(Matrixd& oldProj, double znear,
- double zfar, Matrixd& projection)
-{
- projection = oldProj;
- // Slightly inflate the near & far planes to avoid objects at the
- // extremes being clipped out.
- znear *= 0.999;
- zfar *= 1.001;
-
- // Clamp the projection matrix z values to the range (near, far)
- double epsilon = 1.0e-6;
- if (fabs(projection(0,3)) < epsilon &&
- fabs(projection(1,3)) < epsilon &&
- fabs(projection(2,3)) < epsilon) {
- // Projection is Orthographic
- epsilon = -1.0/(zfar - znear); // Used as a temp variable
- projection(2,2) = 2.0*epsilon;
- projection(3,2) = (zfar + znear)*epsilon;
- } else {
- // Projection is Perspective
- double trans_near = (-znear*projection(2,2) + projection(3,2)) /
- (-znear*projection(2,3) + projection(3,3));
- double trans_far = (-zfar*projection(2,2) + projection(3,2)) /
- (-zfar*projection(2,3) + projection(3,3));
- double ratio = fabs(2.0/(trans_near - trans_far));
- double center = -0.5*(trans_near + trans_far);
-
- projection.postMult(osg::Matrixd(1.0, 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0, 0.0,
- 0.0, 0.0, ratio, 0.0,
- 0.0, 0.0, center*ratio, 1.0));
- }
-}
-}
+ class CameraGroupListener : public SGPropertyChangeListener
+ {
+ public:
+ CameraGroupListener(CameraGroup* cg, SGPropertyNode* gnode) :
+ _groupNode(gnode),
+ _cameraGroup(cg)
+ {
+ listenToNode("znear", 0.1f);
+ listenToNode("zfar", 120000.0f);
+ listenToNode("near-field", 100.0f);
+ }
+
+ virtual ~CameraGroupListener()
+ {
+ unlisten("znear");
+ unlisten("zfar");
+ unlisten("near-field");
+ }
+
+ virtual void valueChanged(SGPropertyNode* prop)
+ {
+ if (!strcmp(prop->getName(), "znear")) {
+ _cameraGroup->setZNear(prop->getFloatValue());
+ } else if (!strcmp(prop->getName(), "zfar")) {
+ _cameraGroup->setZFar(prop->getFloatValue());
+ } else if (!strcmp(prop->getName(), "near-field")) {
+ _cameraGroup->setNearField(prop->getFloatValue());
+ }
+ }
+ private:
+ void listenToNode(const std::string& name, double val)
+ {
+ SGPropertyNode* n = _groupNode->getChild(name);
+ if (!n) {
+ n = _groupNode->getChild(name, 0 /* index */, true);
+ n->setDoubleValue(val);
+ }
+ n->addChangeListener(this);
+ valueChanged(n); // propogate initial state through
+ }
+
+ void unlisten(const std::string& name)
+ {
+ _groupNode->getChild(name)->removeChangeListener(this);
+ }
+
+ SGPropertyNode_ptr _groupNode;
+ CameraGroup* _cameraGroup; // non-owning reference
+
+ };
+
+ class CameraViewportListener : public SGPropertyChangeListener
+ {
+ public:
+ CameraViewportListener(CameraInfo* info,
+ SGPropertyNode* vnode,
+ const osg::GraphicsContext::Traits *traits) :
+ _viewportNode(vnode),
+ _camera(info)
+ {
+ listenToNode("x", 0.0f);
+ listenToNode("y", 0.0f);
+ listenToNode("width", traits->width);
+ listenToNode("height", traits->height);
+ }
+
+ virtual ~CameraViewportListener()
+ {
+ unlisten("x");
+ unlisten("y");
+ unlisten("width");
+ unlisten("height");
+ }
+
+ virtual void valueChanged(SGPropertyNode* prop)
+ {
+ if (!strcmp(prop->getName(), "x")) {
+ _camera->x = prop->getDoubleValue();
+ } else if (!strcmp(prop->getName(), "y")) {
+ _camera->y = prop->getDoubleValue();
+ } else if (!strcmp(prop->getName(), "width")) {
+ _camera->width = prop->getDoubleValue();
+ } else if (!strcmp(prop->getName(), "height")) {
+ _camera->height = prop->getDoubleValue();
+ }
+ }
+ private:
+ void listenToNode(const std::string& name, double val)
+ {
+ SGPropertyNode* n = _viewportNode->getChild(name);
+ if (!n) {
+ n = _viewportNode->getChild(name, 0 /* index */, true);
+ n->setDoubleValue(val);
+ }
+ n->addChangeListener(this);
+ valueChanged(n); // propogate initial state through
+ }
+
+ void unlisten(const std::string& name)
+ {
+ _viewportNode->getChild(name)->removeChangeListener(this);
+ }
+
+ SGPropertyNode_ptr _viewportNode;
+ CameraInfo* _camera;
+
+ };
+
+ const char* MAIN_CAMERA = "main";
+ const char* FAR_CAMERA = "far";
+ const char* GEOMETRY_CAMERA = "geometry";
+ const char* SHADOW_CAMERA = "shadow";
+ const char* LIGHTING_CAMERA = "lighting";
+ const char* DISPLAY_CAMERA = "display";
-namespace flightgear
-{
void CameraInfo::updateCameras()
{
bufferSize->set( osg::Vec2f( width, height ) );
for (CameraMap::iterator ii = cameras.begin(); ii != cameras.end(); ++ii ) {
float f = ii->second.scaleFactor;
if ( f == 0.0f ) continue;
- ii->second.camera->getViewport()->setViewport(x*f, y*f, width*f, height*f);
+
+ if (ii->second.camera->getRenderTargetImplementation() == osg::Camera::FRAME_BUFFER_OBJECT)
+ ii->second.camera->getViewport()->setViewport(0, 0, width*f, height*f);
+ else
+ ii->second.camera->getViewport()->setViewport(x*f, y*f, width*f, height*f);
}
for (RenderBufferMap::iterator ii = buffers.begin(); ii != buffers.end(); ++ii ) {
void CameraInfo::resized(double w, double h)
{
+ if (w == 1.0 && h == 1.0)
+ return;
+
bufferSize->set( osg::Vec2f( w, h ) );
for (RenderBufferMap::iterator ii = buffers.begin(); ii != buffers.end(); ++ii) {
}
}
+CameraInfo::~CameraInfo()
+{
+ delete viewportListener;
+}
+
osg::Camera* CameraInfo::getCamera(const std::string& k) const
{
CameraMap::const_iterator ii = cameras.find( k );
worldPosGeod->set( osg::Vec3f( pos2.getLongitudeRad(), pos2.getLatitudeRad(), pos2.getElevationM() ) );
}
+CameraGroup::~CameraGroup()
+{
+
+ for (CameraList::iterator i = _cameras.begin(); i != _cameras.end(); ++i) {
+ CameraInfo* info = *i;
+ for (CameraMap::iterator ii = info->cameras.begin(); ii != info->cameras.end(); ++ii) {
+ RenderStageInfo& rsi = ii->second;
+ unsigned int slaveIndex = _viewer->findSlaveIndexForCamera(rsi.camera);
+ _viewer->removeSlave(slaveIndex);
+ }
+ }
+
+ _cameras.clear();
+}
+
void CameraGroup::update(const osg::Vec3d& position,
const osg::Quat& orientation)
{
Camera* camera = info->getCamera(MAIN_CAMERA);
if ( camera ) {
- const View::Slave& slave = _viewer->getSlave(info->getMainSlaveIndex());
-#if SG_OSG_VERSION_LESS_THAN(3,0,0)
- // refreshes camera viewports (for now)
- info->updateCameras();
-#endif
+ const osg::View::Slave& slave = _viewer->getSlave(info->getMainSlaveIndex());
+
Matrix viewMatrix;
if (info->flags & GUI) {
viewMatrix = osg::Matrix(); // identifty transform on the GUI camera
Camera* camera = ii->second.camera.get();
int slaveIndex = ii->second.slaveIndex;
- const View::Slave& slave = _viewer->getSlave(slaveIndex);
+ const osg::View::Slave& slave = _viewer->getSlave(slaveIndex);
if ( !viewDone ) {
if ((info->flags & VIEW_ABSOLUTE) != 0)
globals->get_renderer()->setPlanes( _zNear, _zFar );
}
+ref_ptr<CameraGroup> CameraGroup::_defaultGroup;
+
+CameraGroup::CameraGroup(osgViewer::Viewer* viewer) :
+_viewer(viewer)
+{
+}
+
void CameraGroup::setCameraParameters(float vfov, float aspectRatio)
{
if (vfov != 0.0f && aspectRatio != 0.0f)
return static_cast<double>(viewport->height()) / viewport->width();
}
-
-}
-
-namespace
-{
-// A raw value for property nodes that references a class member via
-// an osg::ref_ptr.
-template<class C, class T>
-class RefMember : public SGRawValue<T>
-{
-public:
- RefMember (C *obj, T C::*ptr)
- : _obj(obj), _ptr(ptr) {}
- virtual ~RefMember () {}
- virtual T getValue () const
- {
- return _obj.get()->*_ptr;
- }
- virtual bool setValue (T value)
- {
- _obj.get()->*_ptr = value;
- return true;
- }
- virtual SGRawValue<T> * clone () const
- {
- return new RefMember(_obj.get(), _ptr);
- }
-private:
- ref_ptr<C> _obj;
- T C::* const _ptr;
-};
-
-template<typename C, typename T>
-RefMember<C, T> makeRefMember(C *obj, T C::*ptr)
-{
- return RefMember<C, T>(obj, ptr);
-}
-
-template<typename C, typename T>
-void bindMemberToNode(SGPropertyNode* parent, const char* childName,
- C* obj, T C::*ptr, T value)
-{
- SGPropertyNode* valNode = parent->getNode(childName);
- RefMember<C, T> refMember = makeRefMember(obj, ptr);
- if (!valNode) {
- valNode = parent->getNode(childName, true);
- valNode->tie(refMember, false);
- setValue(valNode, value);
- } else {
- valNode->tie(refMember, true);
- }
-}
-
-void buildViewport(flightgear::CameraInfo* info, SGPropertyNode* viewportNode,
- const osg::GraphicsContext::Traits *traits)
-{
- using namespace flightgear;
- bindMemberToNode(viewportNode, "x", info, &CameraInfo::x, 0.0);
- bindMemberToNode(viewportNode, "y", info, &CameraInfo::y, 0.0);
- bindMemberToNode(viewportNode, "width", info, &CameraInfo::width,
- static_cast<double>(traits->width));
- bindMemberToNode(viewportNode, "height", info, &CameraInfo::height,
- static_cast<double>(traits->height));
-}
-}
-
-namespace flightgear
-{
// Mostly copied from osg's osgViewer/View.cpp
return 0;
}
Camera* camera = new Camera;
+ camera->setName("windowCamera");
camera->setAllowEventFocus(false);
camera->setGraphicsContext(window->gc.get());
camera->setViewport(new Viewport);
bool useMasterSceneGraph = !psNode;
CameraInfo* info = globals->get_renderer()->buildRenderingPipeline(this, cameraFlags, camera, vOff, pOff,
window->gc.get(), useMasterSceneGraph);
+
info->name = cameraNode->getStringValue("name");
info->physicalWidth = physicalWidth;
info->physicalHeight = physicalHeight;
info->parentReference[1] = parentReference[1];
info->thisReference[0] = thisReference[0];
info->thisReference[1] = thisReference[1];
+
// 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.
- buildViewport(info, viewportNode, window->gc->getTraits());
+
+ info->viewportListener = new CameraViewportListener(info, viewportNode, window->gc->getTraits());
+
info->updateCameras();
// Distortion camera needs the viewport which is created by addCamera().
if (psNode) {
const int cameraFlags = GUI | DO_INTERSECTION_TEST;
CameraInfo* result = new CameraInfo(cameraFlags);
+ result->name = "GUI camera";
// The camera group will always update the camera
camera->setReferenceFrame(Transform::ABSOLUTE_RF);
+ // Draw all nodes in the order they are added to the GUI camera
+ camera->getOrCreateStateSet()
+ ->setRenderBinDetails( 0,
+ "PreOrderBin",
+ osg::StateSet::OVERRIDE_RENDERBIN_DETAILS );
+
getViewer()->addSlave(camera, Matrixd::identity(), Matrixd::identity(), false);
//installCullVisitor(camera);
int slaveIndex = getViewer()->getNumSlaves() - 1;
// should be assigned by a camera manager.
camera->setRenderOrder(osg::Camera::POST_RENDER, 10000);
SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true);
- buildViewport(result, viewportNode, window->gc->getTraits());
+
+ result->viewportListener = new CameraViewportListener(result, viewportNode,
+ window->gc->getTraits());
// Disable statistics for the GUI camera.
camera->setStats(0);
SGPropertyNode* gnode)
{
CameraGroup* cgroup = new CameraGroup(viewer);
+ cgroup->_listener.reset(new CameraGroupListener(cgroup, gnode));
+
for (int i = 0; i < gnode->nChildren(); ++i) {
SGPropertyNode* pNode = gnode->getChild(i);
const char* name = pNode->getName();
cgroup->buildGUICamera(pNode);
}
}
- bindMemberToNode(gnode, "znear", cgroup, &CameraGroup::_zNear, .1f);
- bindMemberToNode(gnode, "zfar", cgroup, &CameraGroup::_zFar, 120000.0f);
- bindMemberToNode(gnode, "near-field", cgroup, &CameraGroup::_nearField,
- 100.0f);
+
return cgroup;
}
camera = info->getCamera( GEOMETRY_CAMERA );
if (camera == 0) continue;
camera->setCullMask( nm & ~simgear::MODELLIGHT_BIT );
+
+ camera = info->getCamera( LIGHTING_CAMERA );
+ if (camera == 0) continue;
+ osg::Switch* sw = camera->getChild(0)->asSwitch();
+ for (unsigned int i = 0; i < sw->getNumChildren(); ++i) {
+ osg::Camera* lc = dynamic_cast<osg::Camera*>(sw->getChild(i));
+ if (lc == 0) continue;
+ string name = lc->getName();
+ if (name == "LightCamera") {
+ lc->setCullMask( (nm & simgear::LIGHTS_BITS) | (lc->getCullMask() & ~simgear::LIGHTS_BITS) );
+ }
+ }
}
}
}
return info->getCamera(MAIN_CAMERA);
}
-static bool computeCameraIntersection(const CameraInfo* cinfo,
- const osgGA::GUIEventAdapter* ea,
+
+static bool computeCameraIntersection(const CameraInfo* cinfo, const osg::Vec2d& windowPos,
osgUtil::LineSegmentIntersector::Intersections& intersections)
{
using osgUtil::Intersector;
using osgUtil::LineSegmentIntersector;
- double x, y;
- eventToWindowCoords(ea, x, y);
-
+
if (!(cinfo->flags & CameraGroup::DO_INTERSECTION_TEST))
return false;
const Camera* camera = cinfo->getCamera(MAIN_CAMERA);
if ( !camera )
camera = cinfo->getCamera( GEOMETRY_CAMERA );
- if (camera->getGraphicsContext() != ea->getGraphicsContext())
- return false;
+
+ // if (camera->getGraphicsContext() != ea->getGraphicsContext())
+ // return false;
const Viewport* viewport = camera->getViewport();
+ SGRect<double> viewportRect(viewport->x(), viewport->y(),
+ viewport->x() + viewport->width() - 1.0,
+ viewport->y() + viewport->height()- 1.0);
+
double epsilon = 0.5;
- if (!(x >= viewport->x() - epsilon
- && x < viewport->x() + viewport->width() -1.0 + epsilon
- && y >= viewport->y() - epsilon
- && y < viewport->y() + viewport->height() -1.0 + epsilon))
+ if (!viewportRect.contains(windowPos.x(), windowPos.y(), epsilon))
return false;
- Vec4d start(x, y, 0.0, 1.0);
- Vec4d end(x, y, 1.0, 1.0);
+ Vec4d start(windowPos.x(), windowPos.y(), 0.0, 1.0);
+ Vec4d end(windowPos.x(), windowPos.y(), 1.0, 1.0);
Matrix windowMat = viewport->computeWindowMatrix();
Matrix startPtMat = Matrix::inverse(camera->getProjectionMatrix()
* windowMat);
Vec3d(start.x(), start.y(), start.z()),
Vec3d(end.x(), end.y(), end.z()));
osgUtil::IntersectionVisitor iv(picker.get());
- iv.setTraversalMask( ~simgear::MODELLIGHT_BIT );
+ iv.setTraversalMask( simgear::PICK_BIT );
+
const_cast<Camera*>(camera)->accept(iv);
if (picker->containsIntersections()) {
intersections = picker->getIntersections();
}
bool computeIntersections(const CameraGroup* cgroup,
- const osgGA::GUIEventAdapter* ea,
+ const osg::Vec2d& windowPos,
osgUtil::LineSegmentIntersector::Intersections& intersections)
{
// test the GUI first
const CameraInfo* guiCamera = cgroup->getGUICamera();
- if (guiCamera && computeCameraIntersection(guiCamera, ea, intersections))
+ if (guiCamera && computeCameraIntersection(guiCamera, windowPos, intersections))
return true;
// Find camera that contains event
if (cinfo == guiCamera)
continue;
- if (computeCameraIntersection(cinfo, ea, intersections))
+ if (computeCameraIntersection(cinfo, windowPos, intersections))
return true;
}
* (eventState->getYmax() - eventState->getYmin())));
cgroup->getViewer()->getEventQueue()->mouseWarped(viewerX, viewerY);
}
+
+void CameraGroup::buildDefaultGroup(osgViewer::Viewer* viewer)
+{
+ // Look for windows, camera groups, and the old syntax of
+ // top-level cameras
+ SGPropertyNode* renderingNode = fgGetNode("/sim/rendering");
+ SGPropertyNode* cgroupNode = renderingNode->getNode("camera-group", true);
+ bool oldSyntax = !cgroupNode->hasChild("camera");
+ if (oldSyntax) {
+ for (int i = 0; i < renderingNode->nChildren(); ++i) {
+ SGPropertyNode* propNode = renderingNode->getChild(i);
+ const char* propName = propNode->getName();
+ if (!strcmp(propName, "window") || !strcmp(propName, "camera")) {
+ SGPropertyNode* copiedNode
+ = cgroupNode->getNode(propName, propNode->getIndex(), true);
+ copyProperties(propNode, copiedNode);
+ }
+ }
+
+ SGPropertyNodeVec cameras(cgroupNode->getChildren("camera"));
+ SGPropertyNode* masterCamera = 0;
+ SGPropertyNodeVec::const_iterator it;
+ for (it = cameras.begin(); it != cameras.end(); ++it) {
+ if ((*it)->getDoubleValue("shear-x", 0.0) == 0.0
+ && (*it)->getDoubleValue("shear-y", 0.0) == 0.0) {
+ masterCamera = it->ptr();
+ break;
+ }
+ }
+ if (!masterCamera) {
+ WindowBuilder *windowBuilder = WindowBuilder::getWindowBuilder();
+ masterCamera = cgroupNode->getChild("camera", cameras.size(), true);
+ setValue(masterCamera->getNode("window/name", true),
+ windowBuilder->getDefaultWindowName());
+ }
+ SGPropertyNode* nameNode = masterCamera->getNode("window/name");
+ if (nameNode)
+ setValue(cgroupNode->getNode("gui/window/name", true),
+ nameNode->getStringValue());
+ }
+
+ CameraGroup* cgroup = buildCameraGroup(viewer, cgroupNode);
+ setDefault(cgroup);
}
+
+} // of namespace flightgear
+