1
0
Fork 0

Allow any number of cameras as render stages for a single viewport

This commit is contained in:
Frederic Bouvier 2012-03-11 20:38:17 +01:00
parent 19e7163971
commit 400129ae15
3 changed files with 86 additions and 48 deletions

View file

@ -182,10 +182,28 @@ namespace flightgear
{ {
void CameraInfo::updateCameras() void CameraInfo::updateCameras()
{ {
if (camera.valid()) for (CameraMap::iterator ii = cameras.begin(); ii != cameras.end(); ++ii ) {
camera->getViewport()->setViewport(x, y, width, height); float f = ii->second.scaleFactor;
if (farCamera.valid()) ii->second.camera->getViewport()->setViewport(x*f, y*f, width*f, height*f);
farCamera->getViewport()->setViewport(x, y, width, height); }
}
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, void CameraGroup::update(const osg::Vec3d& position,
@ -198,12 +216,12 @@ void CameraGroup::update(const osg::Vec3d& position,
double masterZoomFactor = zoomFactor(); double masterZoomFactor = zoomFactor();
for (CameraList::iterator i = _cameras.begin(); i != _cameras.end(); ++i) { for (CameraList::iterator i = _cameras.begin(); i != _cameras.end(); ++i) {
const CameraInfo* info = i->get(); 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) #if SG_OSG_VERSION_LESS_THAN(3,0,0)
// refreshes camera viewports (for now) // refreshes camera viewports (for now)
info->updateCameras(); info->updateCameras();
#endif #endif
Camera* camera = info->camera.get(); Camera* camera = info->getMainCamera();
Matrix viewMatrix; Matrix viewMatrix;
if (info->flags & GUI) { 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 // The already known projection and view matrix of the parent camera
const CameraInfo* parentInfo = _cameras[info->relativeCameraParent].get(); const CameraInfo* parentInfo = _cameras[info->relativeCameraParent].get();
osg::Matrix pP = parentInfo->camera->getProjectionMatrix(); RenderStageInfo prsi = parentInfo->cameras.find(CameraInfo::MAIN_CAMERA)->second;
osg::Matrix pR = parentInfo->camera->getViewMatrix(); 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 // And the projection matrix derived from P0 so that the reference points match
projectionMatrix = relativeProjection(P0, R, info->thisReference, projectionMatrix = relativeProjection(P0, R, info->thisReference,
@ -245,10 +264,11 @@ void CameraGroup::update(const osg::Vec3d& position,
projectionMatrix = masterProj * slave._projectionOffset; 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); camera->setProjectionMatrix(projectionMatrix);
} else { } else {
Camera* farCamera = info->farCamera.get(); Camera* farCamera = ii->second.camera;
farCamera->setViewMatrix(viewMatrix); farCamera->setViewMatrix(viewMatrix);
double left, right, bottom, top, parentNear, parentFar; double left, right, bottom, top, parentNear, parentFar;
projectionMatrix.getFrustum(left, right, bottom, top, projectionMatrix.getFrustum(left, right, bottom, top,
@ -296,7 +316,8 @@ double CameraGroup::getMasterAspectRatio() const
const CameraInfo* info = _cameras.front(); 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) { if (!viewport) {
return 0.0; return 0.0;
} }
@ -857,7 +878,7 @@ CameraInfo* CameraGroup::buildGUICamera(SGPropertyNode* cameraNode,
buildViewport(result, viewportNode, window->gc->getTraits()); buildViewport(result, viewportNode, window->gc->getTraits());
// Disable statistics for the GUI camera. // Disable statistics for the GUI camera.
result->camera->setStats(0); result->getMainCamera()->setStats(0);
result->updateCameras(); result->updateCameras();
return result; return result;
} }
@ -890,17 +911,19 @@ void CameraGroup::setCameraCullMasks(Node::NodeMask nm)
CameraInfo* info = i->get(); CameraInfo* info = i->get();
if (info->flags & GUI) if (info->flags & GUI)
continue; continue;
if (info->farCamera.valid() && info->farCamera->getNodeMask() != 0) { osg::ref_ptr<osg::Camera> farCamera = info->getCamera(CameraInfo::FAR_CAMERA);
info->camera->setCullMask(nm & ~simgear::BACKGROUND_BIT); osg::Camera* camera = info->getMainCamera();
info->camera->setCullMaskLeft(nm & ~simgear::BACKGROUND_BIT); if (farCamera.valid() && farCamera->getNodeMask() != 0) {
info->camera->setCullMaskRight(nm & ~simgear::BACKGROUND_BIT); camera->setCullMask(nm & ~simgear::BACKGROUND_BIT);
info->farCamera->setCullMask(nm); camera->setCullMaskLeft(nm & ~simgear::BACKGROUND_BIT);
info->farCamera->setCullMaskLeft(nm); camera->setCullMaskRight(nm & ~simgear::BACKGROUND_BIT);
info->farCamera->setCullMaskRight(nm); farCamera->setCullMask(nm);
farCamera->setCullMaskLeft(nm);
farCamera->setCullMaskRight(nm);
} else { } else {
info->camera->setCullMask(nm); camera->setCullMask(nm);
info->camera->setCullMaskLeft(nm); camera->setCullMaskLeft(nm);
info->camera->setCullMaskRight(nm); camera->setCullMaskRight(nm);
} }
} }
} }
@ -909,7 +932,7 @@ void CameraGroup::resized()
{ {
for (CameraIterator i = camerasBegin(), e = camerasEnd(); i != e; ++i) { for (CameraIterator i = camerasBegin(), e = camerasEnd(); i != e; ++i) {
CameraInfo *info = i->get(); CameraInfo *info = i->get();
const Viewport* viewport = info->camera->getViewport(); const Viewport* viewport = info->getMainCamera()->getViewport();
info->x = viewport->x(); info->x = viewport->x();
info->y = viewport->y(); info->y = viewport->y();
info->width = viewport->width(); info->width = viewport->width();
@ -936,7 +959,7 @@ Camera* getGUICamera(CameraGroup* cgroup)
return NULL; return NULL;
} }
return info->camera.get(); return info->getMainCamera();
} }
static bool computeCameraIntersection(const CameraInfo* cinfo, static bool computeCameraIntersection(const CameraInfo* cinfo,
@ -951,7 +974,7 @@ static bool computeCameraIntersection(const CameraInfo* cinfo,
if (!(cinfo->flags & CameraGroup::DO_INTERSECTION_TEST)) if (!(cinfo->flags & CameraGroup::DO_INTERSECTION_TEST))
return false; return false;
const Camera* camera = cinfo->camera.get(); const Camera* camera = cinfo->getMainCamera();
if (camera->getGraphicsContext() != ea->getGraphicsContext()) if (camera->getGraphicsContext() != ea->getGraphicsContext())
return false; return false;
@ -969,10 +992,11 @@ static bool computeCameraIntersection(const CameraInfo* cinfo,
Matrix startPtMat = Matrix::inverse(camera->getProjectionMatrix() Matrix startPtMat = Matrix::inverse(camera->getProjectionMatrix()
* windowMat); * windowMat);
Matrix endPtMat; 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; endPtMat = startPtMat;
else else
endPtMat = Matrix::inverse(cinfo->farCamera->getProjectionMatrix() endPtMat = Matrix::inverse(farCamera->getProjectionMatrix()
* windowMat); * windowMat);
start = start * startPtMat; start = start * startPtMat;
start /= start.w(); start /= start.w();

View file

@ -46,18 +46,37 @@ namespace flightgear
class GraphicsWindow; class GraphicsWindow;
struct RenderStageInfo {
RenderStageInfo(osg::Camera* camera_ = 0, int si = -1)
: camera(camera_), slaveIndex(si), scaleFactor(1.0f)
{
}
osg::ref_ptr<osg::Camera> camera;
int slaveIndex;
float scaleFactor;
};
/** A wrapper around osg::Camera that contains some extra information. /** A wrapper around osg::Camera that contains some extra information.
*/ */
struct CameraInfo : public osg::Referenced struct CameraInfo : public osg::Referenced
{ {
CameraInfo(unsigned flags_, osg::Camera* camera_ = 0) 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), x(0.0), y(0.0), width(0.0), height(0.0),
physicalWidth(0), physicalHeight(0), bezelHeightTop(0), physicalWidth(0), physicalHeight(0), bezelHeightTop(0),
bezelHeightBottom(0), bezelWidthLeft(0), bezelWidthRight(0), bezelHeightBottom(0), bezelWidthLeft(0), bezelWidthRight(0),
relativeCameraParent(~0u) relativeCameraParent(~0u)
{ {
cameras.insert( std::make_pair( MAIN_CAMERA, camera_ ) );
} }
enum CameraKind {
MAIN_CAMERA,
FAR_CAMERA
};
typedef std::map<CameraKind,RenderStageInfo> CameraMap;
/** Update and resize cameras /** Update and resize cameras
*/ */
void updateCameras(); void updateCameras();
@ -67,18 +86,13 @@ struct CameraInfo : public osg::Referenced
/** Properties of the camera. @see CameraGroup::Flags. /** Properties of the camera. @see CameraGroup::Flags.
*/ */
unsigned flags; unsigned flags;
/** the camera object /** the camera objects
*/ */
osg::ref_ptr<osg::Camera> camera; CameraMap cameras;
/** camera for rendering far field, if needed void addCamera( CameraKind k, osg::Camera* c, int si = -1 ) { cameras[k] = RenderStageInfo(c,si); }
*/ osg::Camera* getCamera(CameraKind k) const;
osg::ref_ptr<osg::Camera> farCamera; osg::Camera* getMainCamera() const;
/** Index of this camera in the osgViewer::Viewer slave list. int getMainSlaveIndex() const;
*/
int slaveIndex;
/** index of far camera in slave list
*/
int farSlaveIndex;
/** Viewport parameters. /** Viewport parameters.
*/ */
double x; double x;

View file

@ -575,17 +575,17 @@ FGRenderer::buildClassicalPipeline(flightgear::CameraGroup* cgroup, unsigned fla
} }
cgroup->getViewer()->addSlave(farCamera, projection, view, useMasterSceneData); cgroup->getViewer()->addSlave(farCamera, projection, view, useMasterSceneData);
installCullVisitor(farCamera); installCullVisitor(farCamera);
info->farCamera = farCamera; int farSlaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
info->farSlaveIndex = cgroup->getViewer()->getNumSlaves() - 1; info->addCamera( CameraInfo::FAR_CAMERA, farCamera, farSlaveIndex );
farCamera->setRenderOrder(Camera::POST_RENDER, info->farSlaveIndex); farCamera->setRenderOrder(Camera::POST_RENDER, farSlaveIndex);
camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT); camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT);
camera->setClearMask(GL_DEPTH_BUFFER_BIT); camera->setClearMask(GL_DEPTH_BUFFER_BIT);
} }
cgroup->getViewer()->addSlave(camera, projection, view, useMasterSceneData); cgroup->getViewer()->addSlave(camera, projection, view, useMasterSceneData);
installCullVisitor(camera); installCullVisitor(camera);
info->camera = camera; int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
info->slaveIndex = cgroup->getViewer()->getNumSlaves() - 1; info->addCamera( CameraInfo::MAIN_CAMERA, camera, slaveIndex );
camera->setRenderOrder(Camera::POST_RENDER, info->slaveIndex); camera->setRenderOrder(Camera::POST_RENDER, slaveIndex);
cgroup->addCamera(info); cgroup->addCamera(info);
return info; return info;
} }
@ -602,9 +602,9 @@ FGRenderer::buildDeferredPipeline(flightgear::CameraGroup* cgroup, unsigned flag
Camera* farCamera = 0; Camera* farCamera = 0;
cgroup->getViewer()->addSlave(camera, projection, view, false); cgroup->getViewer()->addSlave(camera, projection, view, false);
installCullVisitor(camera); installCullVisitor(camera);
info->camera = camera; int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
info->slaveIndex = cgroup->getViewer()->getNumSlaves() - 1; info->addCamera( CameraInfo::MAIN_CAMERA, camera, slaveIndex );
camera->setRenderOrder(Camera::POST_RENDER, info->slaveIndex); camera->setRenderOrder(Camera::POST_RENDER, slaveIndex);
cgroup->addCamera(info); cgroup->addCamera(info);
return info; return info;
} }