Allow any number of cameras as render stages for a single viewport
This commit is contained in:
parent
19e7163971
commit
400129ae15
3 changed files with 86 additions and 48 deletions
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue