345 lines
10 KiB
C++
345 lines
10 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
|
*
|
|
* This library is open source and may be redistributed and/or modified under
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
* included with this distribution, and on the openscenegraph.org website.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* OpenSceneGraph Public License for more details.
|
|
*/
|
|
#include <osg/Camera>
|
|
#include <osg/Notify>
|
|
|
|
using namespace osg;
|
|
|
|
Camera::Camera():
|
|
_view(0),
|
|
_allowEventFocus(true),
|
|
_clearColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f)),
|
|
_clearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT),
|
|
_transformOrder(PRE_MULTIPLY),
|
|
_projectionResizePolicy(HORIZONTAL),
|
|
_renderOrder(POST_RENDER),
|
|
_renderOrderNum(0),
|
|
_drawBuffer(GL_NONE),
|
|
_readBuffer(GL_NONE),
|
|
_renderTargetImplementation(FRAME_BUFFER),
|
|
_renderTargetFallback(FRAME_BUFFER)
|
|
{
|
|
setStateSet(new StateSet);
|
|
}
|
|
|
|
Camera::Camera(const Camera& camera,const CopyOp& copyop):
|
|
Transform(camera,copyop),
|
|
CullSettings(camera),
|
|
_view(camera._view),
|
|
_allowEventFocus(camera._allowEventFocus),
|
|
_displaySettings(camera._displaySettings),
|
|
_clearColor(camera._clearColor),
|
|
_clearMask(camera._clearMask),
|
|
_colorMask(camera._colorMask),
|
|
_viewport(camera._viewport),
|
|
_transformOrder(camera._transformOrder),
|
|
_projectionResizePolicy(camera._projectionResizePolicy),
|
|
_projectionMatrix(camera._projectionMatrix),
|
|
_viewMatrix(camera._viewMatrix),
|
|
_renderOrder(camera._renderOrder),
|
|
_renderOrderNum(camera._renderOrderNum),
|
|
_drawBuffer(camera._drawBuffer),
|
|
_readBuffer(camera._readBuffer),
|
|
_renderTargetImplementation(camera._renderTargetImplementation),
|
|
_renderTargetFallback(camera._renderTargetFallback),
|
|
_bufferAttachmentMap(camera._bufferAttachmentMap),
|
|
_preDrawCallback(camera._preDrawCallback),
|
|
_postDrawCallback(camera._postDrawCallback)
|
|
{
|
|
// need to copy/share graphics context?
|
|
}
|
|
|
|
|
|
Camera::~Camera()
|
|
{
|
|
setCameraThread(0);
|
|
|
|
if (_graphicsContext.valid()) _graphicsContext->removeCamera(this);
|
|
}
|
|
|
|
void Camera::setGraphicsContext(GraphicsContext* context)
|
|
{
|
|
if (_graphicsContext == context) return;
|
|
|
|
if (_graphicsContext.valid()) _graphicsContext->removeCamera(this);
|
|
|
|
_graphicsContext = context;
|
|
|
|
if (_graphicsContext.valid()) _graphicsContext->addCamera(this);
|
|
}
|
|
|
|
|
|
bool Camera::isRenderToTextureCamera() const
|
|
{
|
|
return (!_bufferAttachmentMap.empty());
|
|
}
|
|
|
|
void Camera::setRenderTargetImplementation(RenderTargetImplementation impl)
|
|
{
|
|
_renderTargetImplementation = impl;
|
|
if (impl<FRAME_BUFFER) _renderTargetFallback = (RenderTargetImplementation)(impl+1);
|
|
else _renderTargetFallback = impl;
|
|
}
|
|
|
|
void Camera::setRenderTargetImplementation(RenderTargetImplementation impl, RenderTargetImplementation fallback)
|
|
{
|
|
if (impl<fallback || (impl==FRAME_BUFFER && fallback==FRAME_BUFFER))
|
|
{
|
|
_renderTargetImplementation = impl;
|
|
_renderTargetFallback = fallback;
|
|
}
|
|
else
|
|
{
|
|
osg::notify(osg::NOTICE)<<"Warning: Camera::setRenderTargetImplementation(impl,fallback) must have a lower rated fallback than the main target implementation."<<std::endl;
|
|
setRenderTargetImplementation(impl);
|
|
}
|
|
}
|
|
|
|
void Camera::setColorMask(osg::ColorMask* colorMask)
|
|
{
|
|
if (_colorMask == colorMask) return;
|
|
|
|
osg::StateSet* stateset = getOrCreateStateSet();
|
|
if (_colorMask.valid() && stateset)
|
|
{
|
|
stateset->removeAttribute(_colorMask.get());
|
|
}
|
|
|
|
_colorMask = colorMask;
|
|
|
|
if (_colorMask.valid() && stateset)
|
|
{
|
|
stateset->setAttribute(_colorMask.get());
|
|
}
|
|
}
|
|
|
|
void Camera::setColorMask(bool red, bool green, bool blue, bool alpha)
|
|
{
|
|
if (!_colorMask) setColorMask(new osg::ColorMask);
|
|
if (_colorMask.valid()) _colorMask->setMask(red,green,blue,alpha);
|
|
}
|
|
|
|
void Camera::setViewport(osg::Viewport* viewport)
|
|
{
|
|
if (_viewport == viewport) return;
|
|
|
|
osg::StateSet* stateset = getOrCreateStateSet();
|
|
if (_viewport.valid() && stateset)
|
|
{
|
|
stateset->removeAttribute(_viewport.get());
|
|
}
|
|
|
|
_viewport = viewport;
|
|
|
|
if (_viewport.valid() && stateset)
|
|
{
|
|
stateset->setAttribute(_viewport.get());
|
|
}
|
|
}
|
|
|
|
void Camera::setViewport(int x,int y,int width,int height)
|
|
{
|
|
if (!_viewport) setViewport(new osg::Viewport);
|
|
if (_viewport.valid()) _viewport->setViewport(x,y,width,height);
|
|
}
|
|
|
|
Matrixd Camera::getInverseViewMatrix() const
|
|
{
|
|
Matrixd inverse;
|
|
inverse.invert(_viewMatrix);
|
|
return inverse;
|
|
}
|
|
void Camera::setProjectionMatrixAsOrtho(double left, double right,
|
|
double bottom, double top,
|
|
double zNear, double zFar)
|
|
{
|
|
setProjectionMatrix(osg::Matrixd::ortho(left, right,
|
|
bottom, top,
|
|
zNear, zFar));
|
|
}
|
|
|
|
void Camera::setProjectionMatrixAsOrtho2D(double left, double right,
|
|
double bottom, double top)
|
|
{
|
|
setProjectionMatrix(osg::Matrixd::ortho2D(left, right,
|
|
bottom, top));
|
|
}
|
|
|
|
void Camera::setProjectionMatrixAsFrustum(double left, double right,
|
|
double bottom, double top,
|
|
double zNear, double zFar)
|
|
{
|
|
setProjectionMatrix(osg::Matrixd::frustum(left, right,
|
|
bottom, top,
|
|
zNear, zFar));
|
|
}
|
|
|
|
void Camera::setProjectionMatrixAsPerspective(double fovy,double aspectRatio,
|
|
double zNear, double zFar)
|
|
{
|
|
setProjectionMatrix(osg::Matrixd::perspective(fovy,aspectRatio,
|
|
zNear, zFar));
|
|
}
|
|
|
|
bool Camera::getProjectionMatrixAsOrtho(double& left, double& right,
|
|
double& bottom, double& top,
|
|
double& zNear, double& zFar)
|
|
{
|
|
return _projectionMatrix.getOrtho(left, right,
|
|
bottom, top,
|
|
zNear, zFar);
|
|
}
|
|
|
|
bool Camera::getProjectionMatrixAsFrustum(double& left, double& right,
|
|
double& bottom, double& top,
|
|
double& zNear, double& zFar)
|
|
{
|
|
return _projectionMatrix.getFrustum(left, right,
|
|
bottom, top,
|
|
zNear, zFar);
|
|
}
|
|
|
|
bool Camera::getProjectionMatrixAsPerspective(double& fovy,double& aspectRatio,
|
|
double& zNear, double& zFar)
|
|
{
|
|
return _projectionMatrix.getPerspective(fovy, aspectRatio, zNear, zFar);
|
|
}
|
|
|
|
void Camera::setViewMatrixAsLookAt(const Vec3& eye,const Vec3& center,const Vec3& up)
|
|
{
|
|
setViewMatrix(osg::Matrixd::lookAt(eye,center,up));
|
|
}
|
|
|
|
void Camera::getViewMatrixAsLookAt(Vec3& eye,Vec3& center,Vec3& up,float lookDistance)
|
|
{
|
|
_viewMatrix.getLookAt(eye,center,up,lookDistance);
|
|
}
|
|
|
|
|
|
void Camera::attach(BufferComponent buffer, GLenum internalFormat)
|
|
{
|
|
_bufferAttachmentMap[buffer]._internalFormat = internalFormat;
|
|
}
|
|
|
|
void Camera::attach(BufferComponent buffer, osg::Texture* texture, unsigned int level, unsigned int face, bool mipMapGeneration)
|
|
{
|
|
_bufferAttachmentMap[buffer]._texture = texture;
|
|
_bufferAttachmentMap[buffer]._level = level;
|
|
_bufferAttachmentMap[buffer]._face = face;
|
|
_bufferAttachmentMap[buffer]._mipMapGeneration = mipMapGeneration;
|
|
}
|
|
|
|
void Camera::attach(BufferComponent buffer, osg::Image* image)
|
|
{
|
|
_bufferAttachmentMap[buffer]._image = image;
|
|
}
|
|
|
|
void Camera::detach(BufferComponent buffer)
|
|
{
|
|
_bufferAttachmentMap.erase(buffer);
|
|
}
|
|
|
|
void Camera::resizeGLObjectBuffers(unsigned int maxSize)
|
|
{
|
|
if (_renderingCache.valid())
|
|
{
|
|
const_cast<Camera*>(this)->_renderingCache->resizeGLObjectBuffers(maxSize);
|
|
}
|
|
|
|
Transform::resizeGLObjectBuffers(maxSize);
|
|
}
|
|
|
|
void Camera::releaseGLObjects(osg::State* state) const
|
|
{
|
|
if (_renderingCache.valid())
|
|
{
|
|
const_cast<Camera*>(this)->_renderingCache->releaseGLObjects(state);
|
|
}
|
|
|
|
Transform::releaseGLObjects(state);
|
|
}
|
|
|
|
|
|
bool Camera::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
|
|
{
|
|
if (_referenceFrame==RELATIVE_RF)
|
|
{
|
|
if (_transformOrder==PRE_MULTIPLY)
|
|
{
|
|
matrix.preMult(_viewMatrix);
|
|
}
|
|
else
|
|
{
|
|
matrix.postMult(_viewMatrix);
|
|
}
|
|
}
|
|
else // absolute
|
|
{
|
|
matrix = _viewMatrix;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Camera::computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor*) const
|
|
{
|
|
const Matrixd& inverse = getInverseViewMatrix();
|
|
|
|
if (_referenceFrame==RELATIVE_RF)
|
|
{
|
|
if (_transformOrder==PRE_MULTIPLY)
|
|
{
|
|
// note doing inverse so pre becomes post.
|
|
matrix.postMult(inverse);
|
|
}
|
|
else
|
|
{
|
|
// note doing inverse so post becomes pre.
|
|
matrix.preMult(inverse);
|
|
}
|
|
}
|
|
else // absolute
|
|
{
|
|
matrix = inverse;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Camera::createCameraThread()
|
|
{
|
|
if (!_cameraThread)
|
|
{
|
|
setCameraThread(new OperationThread);
|
|
}
|
|
}
|
|
|
|
void Camera::setCameraThread(OperationThread* gt)
|
|
{
|
|
if (_cameraThread==gt) return;
|
|
|
|
if (_cameraThread.valid())
|
|
{
|
|
// need to kill the thread in some way...
|
|
_cameraThread->cancel();
|
|
_cameraThread->setParent(0);
|
|
}
|
|
|
|
_cameraThread = gt;
|
|
|
|
if (_cameraThread.valid())
|
|
{
|
|
_cameraThread->setParent(this);
|
|
}
|
|
}
|
|
|
|
|