diff --git a/src/Main/CameraGroup.cxx b/src/Main/CameraGroup.cxx index 2aabd4a97..013303028 100644 --- a/src/Main/CameraGroup.cxx +++ b/src/Main/CameraGroup.cxx @@ -182,10 +182,28 @@ namespace flightgear { void CameraInfo::updateCameras() { - if (camera.valid()) - camera->getViewport()->setViewport(x, y, width, height); - if (farCamera.valid()) - farCamera->getViewport()->setViewport(x, y, width, height); + for (CameraMap::iterator ii = cameras.begin(); ii != cameras.end(); ++ii ) { + float f = ii->second.scaleFactor; + ii->second.camera->getViewport()->setViewport(x*f, y*f, width*f, height*f); + } +} + +osg::Camera* CameraInfo::getCamera(CameraKind k) const +{ + CameraMap::const_iterator ii = cameras.find( k ); + if (ii == cameras.end()) + return 0; + return ii->second.camera.get(); +} + +osg::Camera* CameraInfo::getMainCamera() const +{ + return cameras.find( MAIN_CAMERA )->second.camera.get(); +} + +int CameraInfo::getMainSlaveIndex() const +{ + return cameras.find( MAIN_CAMERA )->second.slaveIndex; } void CameraGroup::update(const osg::Vec3d& position, @@ -198,12 +216,12 @@ void CameraGroup::update(const osg::Vec3d& position, double masterZoomFactor = zoomFactor(); for (CameraList::iterator i = _cameras.begin(); i != _cameras.end(); ++i) { const CameraInfo* info = i->get(); - const View::Slave& slave = _viewer->getSlave(info->slaveIndex); + 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 - Camera* camera = info->camera.get(); + Camera* camera = info->getMainCamera(); Matrix viewMatrix; if (info->flags & GUI) { @@ -226,8 +244,9 @@ void CameraGroup::update(const osg::Vec3d& position, // The already known projection and view matrix of the parent camera const CameraInfo* parentInfo = _cameras[info->relativeCameraParent].get(); - osg::Matrix pP = parentInfo->camera->getProjectionMatrix(); - osg::Matrix pR = parentInfo->camera->getViewMatrix(); + RenderStageInfo prsi = parentInfo->cameras.find(CameraInfo::MAIN_CAMERA)->second; + osg::Matrix pP = prsi.camera->getProjectionMatrix(); + osg::Matrix pR = prsi.camera->getViewMatrix(); // And the projection matrix derived from P0 so that the reference points match projectionMatrix = relativeProjection(P0, R, info->thisReference, @@ -245,10 +264,11 @@ void CameraGroup::update(const osg::Vec3d& position, projectionMatrix = masterProj * slave._projectionOffset; } - if (!info->farCamera.valid()) { + CameraInfo::CameraMap::const_iterator ii = info->cameras.find(CameraInfo::FAR_CAMERA); + if (ii == info->cameras.end() || !ii->second.camera.valid()) { camera->setProjectionMatrix(projectionMatrix); } else { - Camera* farCamera = info->farCamera.get(); + Camera* farCamera = ii->second.camera; farCamera->setViewMatrix(viewMatrix); double left, right, bottom, top, parentNear, parentFar; projectionMatrix.getFrustum(left, right, bottom, top, @@ -296,7 +316,8 @@ double CameraGroup::getMasterAspectRatio() const const CameraInfo* info = _cameras.front(); - const osg::Viewport* viewport = info->camera->getViewport(); + osg::Camera* camera = info->cameras.find(CameraInfo::MAIN_CAMERA)->second.camera.get(); + const osg::Viewport* viewport = camera->getViewport(); if (!viewport) { return 0.0; } @@ -857,7 +878,7 @@ CameraInfo* CameraGroup::buildGUICamera(SGPropertyNode* cameraNode, buildViewport(result, viewportNode, window->gc->getTraits()); // Disable statistics for the GUI camera. - result->camera->setStats(0); + result->getMainCamera()->setStats(0); result->updateCameras(); return result; } @@ -890,17 +911,19 @@ void CameraGroup::setCameraCullMasks(Node::NodeMask nm) CameraInfo* info = i->get(); if (info->flags & GUI) continue; - if (info->farCamera.valid() && info->farCamera->getNodeMask() != 0) { - info->camera->setCullMask(nm & ~simgear::BACKGROUND_BIT); - info->camera->setCullMaskLeft(nm & ~simgear::BACKGROUND_BIT); - info->camera->setCullMaskRight(nm & ~simgear::BACKGROUND_BIT); - info->farCamera->setCullMask(nm); - info->farCamera->setCullMaskLeft(nm); - info->farCamera->setCullMaskRight(nm); + osg::ref_ptr farCamera = info->getCamera(CameraInfo::FAR_CAMERA); + osg::Camera* camera = info->getMainCamera(); + if (farCamera.valid() && farCamera->getNodeMask() != 0) { + camera->setCullMask(nm & ~simgear::BACKGROUND_BIT); + camera->setCullMaskLeft(nm & ~simgear::BACKGROUND_BIT); + camera->setCullMaskRight(nm & ~simgear::BACKGROUND_BIT); + farCamera->setCullMask(nm); + farCamera->setCullMaskLeft(nm); + farCamera->setCullMaskRight(nm); } else { - info->camera->setCullMask(nm); - info->camera->setCullMaskLeft(nm); - info->camera->setCullMaskRight(nm); + camera->setCullMask(nm); + camera->setCullMaskLeft(nm); + camera->setCullMaskRight(nm); } } } @@ -909,7 +932,7 @@ void CameraGroup::resized() { for (CameraIterator i = camerasBegin(), e = camerasEnd(); i != e; ++i) { CameraInfo *info = i->get(); - const Viewport* viewport = info->camera->getViewport(); + const Viewport* viewport = info->getMainCamera()->getViewport(); info->x = viewport->x(); info->y = viewport->y(); info->width = viewport->width(); @@ -936,7 +959,7 @@ Camera* getGUICamera(CameraGroup* cgroup) return NULL; } - return info->camera.get(); + return info->getMainCamera(); } static bool computeCameraIntersection(const CameraInfo* cinfo, @@ -951,7 +974,7 @@ static bool computeCameraIntersection(const CameraInfo* cinfo, if (!(cinfo->flags & CameraGroup::DO_INTERSECTION_TEST)) return false; - const Camera* camera = cinfo->camera.get(); + const Camera* camera = cinfo->getMainCamera(); if (camera->getGraphicsContext() != ea->getGraphicsContext()) return false; @@ -969,10 +992,11 @@ static bool computeCameraIntersection(const CameraInfo* cinfo, Matrix startPtMat = Matrix::inverse(camera->getProjectionMatrix() * windowMat); Matrix endPtMat; - if (!cinfo->farCamera.valid() || cinfo->farCamera->getNodeMask() == 0) + const Camera* farCamera = cinfo->getCamera( CameraInfo::FAR_CAMERA ); + if (!farCamera || farCamera->getNodeMask() == 0) endPtMat = startPtMat; else - endPtMat = Matrix::inverse(cinfo->farCamera->getProjectionMatrix() + endPtMat = Matrix::inverse(farCamera->getProjectionMatrix() * windowMat); start = start * startPtMat; start /= start.w(); diff --git a/src/Main/CameraGroup.hxx b/src/Main/CameraGroup.hxx index dd76c709a..b0d723f46 100644 --- a/src/Main/CameraGroup.hxx +++ b/src/Main/CameraGroup.hxx @@ -46,18 +46,37 @@ namespace flightgear class GraphicsWindow; +struct RenderStageInfo { + RenderStageInfo(osg::Camera* camera_ = 0, int si = -1) + : camera(camera_), slaveIndex(si), scaleFactor(1.0f) + { + } + + osg::ref_ptr camera; + int slaveIndex; + float scaleFactor; +}; + /** A wrapper around osg::Camera that contains some extra information. */ struct CameraInfo : public osg::Referenced { CameraInfo(unsigned flags_, osg::Camera* camera_ = 0) - : flags(flags_), camera(camera_), slaveIndex(-1), farSlaveIndex(-1), + : flags(flags_), x(0.0), y(0.0), width(0.0), height(0.0), physicalWidth(0), physicalHeight(0), bezelHeightTop(0), bezelHeightBottom(0), bezelWidthLeft(0), bezelWidthRight(0), relativeCameraParent(~0u) { + cameras.insert( std::make_pair( MAIN_CAMERA, camera_ ) ); } + + enum CameraKind { + MAIN_CAMERA, + FAR_CAMERA + }; + typedef std::map CameraMap; + /** Update and resize cameras */ void updateCameras(); @@ -67,18 +86,13 @@ struct CameraInfo : public osg::Referenced /** Properties of the camera. @see CameraGroup::Flags. */ unsigned flags; - /** the camera object + /** the camera objects */ - osg::ref_ptr camera; - /** camera for rendering far field, if needed - */ - osg::ref_ptr farCamera; - /** Index of this camera in the osgViewer::Viewer slave list. - */ - int slaveIndex; - /** index of far camera in slave list - */ - int farSlaveIndex; + CameraMap cameras; + void addCamera( CameraKind k, osg::Camera* c, int si = -1 ) { cameras[k] = RenderStageInfo(c,si); } + osg::Camera* getCamera(CameraKind k) const; + osg::Camera* getMainCamera() const; + int getMainSlaveIndex() const; /** Viewport parameters. */ double x; diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index fe06b8430..e32756b7b 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -575,17 +575,17 @@ FGRenderer::buildClassicalPipeline(flightgear::CameraGroup* cgroup, unsigned fla } cgroup->getViewer()->addSlave(farCamera, projection, view, useMasterSceneData); installCullVisitor(farCamera); - info->farCamera = farCamera; - info->farSlaveIndex = cgroup->getViewer()->getNumSlaves() - 1; - farCamera->setRenderOrder(Camera::POST_RENDER, info->farSlaveIndex); + int farSlaveIndex = cgroup->getViewer()->getNumSlaves() - 1; + info->addCamera( CameraInfo::FAR_CAMERA, farCamera, farSlaveIndex ); + farCamera->setRenderOrder(Camera::POST_RENDER, farSlaveIndex); camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT); camera->setClearMask(GL_DEPTH_BUFFER_BIT); } cgroup->getViewer()->addSlave(camera, projection, view, useMasterSceneData); installCullVisitor(camera); - info->camera = camera; - info->slaveIndex = cgroup->getViewer()->getNumSlaves() - 1; - camera->setRenderOrder(Camera::POST_RENDER, info->slaveIndex); + int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1; + info->addCamera( CameraInfo::MAIN_CAMERA, camera, slaveIndex ); + camera->setRenderOrder(Camera::POST_RENDER, slaveIndex); cgroup->addCamera(info); return info; } @@ -602,9 +602,9 @@ FGRenderer::buildDeferredPipeline(flightgear::CameraGroup* cgroup, unsigned flag Camera* farCamera = 0; cgroup->getViewer()->addSlave(camera, projection, view, false); installCullVisitor(camera); - info->camera = camera; - info->slaveIndex = cgroup->getViewer()->getNumSlaves() - 1; - camera->setRenderOrder(Camera::POST_RENDER, info->slaveIndex); + int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1; + info->addCamera( CameraInfo::MAIN_CAMERA, camera, slaveIndex ); + camera->setRenderOrder(Camera::POST_RENDER, slaveIndex); cgroup->addCamera(info); return info; }