/* -*-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. */ #ifndef OSG_CAMERA #define OSG_CAMERA 1 #include #include #include #include #include #include #include #include #include namespace osg { // forward declare View to allow Camera to point back to the View that its within class View; /** Camera - is a subclass of Transform which represents encapsulates the settings of a Camera. */ class OSG_EXPORT Camera : public Transform, public CullSettings { public : Camera(); /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ Camera(const Camera&,const CopyOp& copyop=CopyOp::SHALLOW_COPY); META_Node(osg, Camera); /** Set the View that this Camera is part of. */ void setView(View* view) { _view = view; } /** Get the View that this Camera is part of. */ View* getView() { return _view; } /** Get the const View that this Camera is part of. */ const View* getView() const { return _view; } /** Set the Stats object used for collect various frame related timing and scene graph stats.*/ void setStats(osg::Stats* stats) { _stats = stats; } /** Get the Stats object.*/ osg::Stats* getStats() { return _stats.get(); } /** Get the const Stats object.*/ const osg::Stats* getStats() const { return _stats.get(); } /** Sets the clear color. */ inline void setClearColor(const Vec4& color) { _clearColor = color; } /** Returns the clear color. */ inline const Vec4& getClearColor() const { return _clearColor; } /** Set the clear mask used in glClear(..). * Defaults to GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT. */ inline void setClearMask(GLbitfield mask) { _clearMask = mask; } /** Get the clear mask.*/ inline GLbitfield getClearMask() const { return _clearMask; } /** Set the color mask of the camera to use specified osg::ColorMask. */ void setColorMask(osg::ColorMask* colorMask); /** Set the color mask of the camera to specified values. */ void setColorMask(bool red, bool green, bool blue, bool alpha); /** Get the const ColorMask. */ const ColorMask* getColorMask() const { return _colorMask.get(); } /** Get the ColorMask. */ ColorMask* getColorMask() { return _colorMask.get(); } /** Set the viewport of the camera to use specified osg::Viewport. */ void setViewport(osg::Viewport* viewport); /** Set the viewport of the camera to specified dimensions. */ void setViewport(int x,int y,int width,int height); /** Get the const viewport. */ const Viewport* getViewport() const { return _viewport.get(); } /** Get the viewport. */ Viewport* getViewport() { return _viewport.get(); } enum TransformOrder { PRE_MULTIPLY, POST_MULTIPLY }; /** Set the transformation order for world-to-local and local-to-world transformation.*/ void setTransformOrder(TransformOrder order) { _transformOrder = order; } /** Get the transformation order.*/ TransformOrder getTransformOrder() const { return _transformOrder; } /** Set the projection matrix. Can be thought of as setting the lens of a camera. */ inline void setProjectionMatrix(const osg::Matrixf& matrix) { _projectionMatrix.set(matrix); } /** Set the projection matrix. Can be thought of as setting the lens of a camera. */ inline void setProjectionMatrix(const osg::Matrixd& matrix) { _projectionMatrix.set(matrix); } /** Set to an orthographic projection. See OpenGL glOrtho for documentation further details.*/ void setProjectionMatrixAsOrtho(double left, double right, double bottom, double top, double zNear, double zFar); /** Set to a 2D orthographic projection. See OpenGL glOrtho2D documentation for further details.*/ void setProjectionMatrixAsOrtho2D(double left, double right, double bottom, double top); /** Set to a perspective projection. See OpenGL glFrustum documentation for further details.*/ void setProjectionMatrixAsFrustum(double left, double right, double bottom, double top, double zNear, double zFar); /** Create a symmetrical perspective projection, See OpenGL gluPerspective documentation for further details. * Aspect ratio is defined as width/height.*/ void setProjectionMatrixAsPerspective(double fovy,double aspectRatio, double zNear, double zFar); /** Get the projection matrix.*/ osg::Matrixd& getProjectionMatrix() { return _projectionMatrix; } /** Get the const projection matrix.*/ const osg::Matrixd& getProjectionMatrix() const { return _projectionMatrix; } /** Get the othographic settings of the orthographic projection matrix. * Returns false if matrix is not an orthographic matrix, where parameter values are undefined.*/ bool getProjectionMatrixAsOrtho(double& left, double& right, double& bottom, double& top, double& zNear, double& zFar); /** Get the frustum setting of a perspective projection matrix. * Returns false if matrix is not a perspective matrix, where parameter values are undefined.*/ bool getProjectionMatrixAsFrustum(double& left, double& right, double& bottom, double& top, double& zNear, double& zFar); /** Get the frustum setting of a symmetric perspective projection matrix. * Returns false if matrix is not a perspective matrix, where parameter values are undefined. * Note, if matrix is not a symmetric perspective matrix then the shear will be lost. * Asymmetric matrices occur when stereo, power walls, caves and reality center display are used. * In these configurations one should use the 'getProjectionMatrixAsFrustum' method instead.*/ bool getProjectionMatrixAsPerspective(double& fovy,double& aspectRatio, double& zNear, double& zFar); /** Set the view matrix. Can be thought of as setting the position of the world relative to the camera in camera coordinates. */ inline void setViewMatrix(const osg::Matrixf& matrix) { _viewMatrix.set(matrix); dirtyBound();} /** Set the view matrix. Can be thought of as setting the position of the world relative to the camera in camera coordinates. */ inline void setViewMatrix(const osg::Matrixd& matrix) { _viewMatrix.set(matrix); dirtyBound();} /** Set to the position and orientation of view matrix, using the same convention as gluLookAt. */ void setViewMatrixAsLookAt(const osg::Vec3& eye,const osg::Vec3& center,const osg::Vec3& up); /** Get the view matrix. */ osg::Matrixd& getViewMatrix() { return _viewMatrix; } /** Get the const view matrix. */ const osg::Matrixd& getViewMatrix() const { return _viewMatrix; } /** Get to the position and orientation of a modelview matrix, using the same convention as gluLookAt. */ void getViewMatrixAsLookAt(osg::Vec3& eye,osg::Vec3& center,osg::Vec3& up,float lookDistance=1.0f); /** Get the inverse view matrix.*/ Matrixd getInverseViewMatrix() const; enum RenderOrder { PRE_RENDER, NESTED_RENDER, POST_RENDER }; /** Set the rendering order of this camera's subgraph relative to any camera that this subgraph is nested within. * For rendering to a texture, one typically uses PRE_RENDER. * For Head Up Displays, one would typically use POST_RENDER.*/ void setRenderOrder(RenderOrder order, int orderNum = 0) { _renderOrder = order; _renderOrderNum = orderNum; } /** Get the rendering order of this camera's subgraph relative to any camera that this subgraph is nested within.*/ RenderOrder getRenderOrder() const { return _renderOrder; } /** Get the rendering order number of this camera relative to any sibling cameras in this subgraph.*/ int getRenderOrderNum() const { return _renderOrderNum; } /** Return true if this Camera is set up as a render to texture camera, i.e. it has textures assigned to it.*/ bool isRenderToTextureCamera() const; enum RenderTargetImplementation { FRAME_BUFFER_OBJECT, PIXEL_BUFFER_RTT, PIXEL_BUFFER, FRAME_BUFFER, SEPERATE_WINDOW }; /** Set the render target.*/ void setRenderTargetImplementation(RenderTargetImplementation impl); /** Set the render target and fall-back that's used if the former isn't available.*/ void setRenderTargetImplementation(RenderTargetImplementation impl, RenderTargetImplementation fallback); /** Get the render target.*/ RenderTargetImplementation getRenderTargetImplementation() const { return _renderTargetImplementation; } /** Get the render target fallback.*/ RenderTargetImplementation getRenderTargetFallback() const { return _renderTargetFallback; } /** Set the draw buffer used at the start of each frame draw. * Note, a buffer value of GL_NONE is used to sepecify that the rendering back-end should choose the most appropriate buffer.*/ void setDrawBuffer(GLenum buffer) { _drawBuffer = buffer; } /** Get the draw buffer used at the start of each frame draw. */ GLenum getDrawBuffer() const { return _drawBuffer; } /** Set the read buffer for any required copy operations to use. * Note, a buffer value of GL_NONE is used to sepecify that the rendering back-end should choose the most appropriate buffer.*/ void setReadBuffer(GLenum buffer) { _readBuffer = buffer; } /** Get the read buffer for any required copy operations to use. */ GLenum getReadBuffer() const { return _readBuffer; } enum BufferComponent { DEPTH_BUFFER, STENCIL_BUFFER, COLOR_BUFFER, COLOR_BUFFER0 = COLOR_BUFFER, COLOR_BUFFER1 = COLOR_BUFFER+1, COLOR_BUFFER2 = COLOR_BUFFER+2, COLOR_BUFFER3 = COLOR_BUFFER+3, COLOR_BUFFER4 = COLOR_BUFFER+4, COLOR_BUFFER5 = COLOR_BUFFER+5, COLOR_BUFFER6 = COLOR_BUFFER+6, COLOR_BUFFER7 = COLOR_BUFFER+7 }; void attach(BufferComponent buffer, GLenum internalFormat); void attach(BufferComponent buffer, osg::Texture* texture, unsigned int level = 0, unsigned int face=0, bool mipMapGeneration=false); void attach(BufferComponent buffer, osg::Image* image); void detach(BufferComponent buffer); struct Attachment { Attachment(): _internalFormat(GL_NONE), _level(0), _face(0), _mipMapGeneration(false) {} int width() const { if (_texture.valid()) return _texture->getTextureWidth(); if (_image.valid()) return _image->s(); return 0; }; int height() const { if (_texture.valid()) return _texture->getTextureHeight(); if (_image.valid()) return _image->t(); return 0; }; int depth() const { if (_texture.valid()) return _texture->getTextureDepth(); if (_image.valid()) return _image->r(); return 0; }; GLenum _internalFormat; ref_ptr _image; ref_ptr _texture; unsigned int _level; unsigned int _face; bool _mipMapGeneration; }; typedef std::map< BufferComponent, Attachment> BufferAttachmentMap; /** Get the BufferAttachmentMap, used to configure frame buffer objects, pbuffers and texture reads.*/ BufferAttachmentMap& getBufferAttachmentMap() { return _bufferAttachmentMap; } /** Get the const BufferAttachmentMap, used to configure frame buffer objects, pbuffers and texture reads.*/ const BufferAttachmentMap& getBufferAttachmentMap() const { return _bufferAttachmentMap; } /** Create a operation thread for this camera.*/ void createCameraThread(); /** Assign a operation thread to the camera.*/ void setCameraThread(OperationsThread* gt); /** Get the operation thread assigned to this camera.*/ OperationsThread* getCameraThread() { return _cameraThread.get(); } /** Get the const operation thread assigned to this camera.*/ const OperationsThread* getCameraThread() const { return _cameraThread.get(); } /** Set the GraphicsContext that provides the mechansim for managing the OpenGL graphics context associated with this camera.*/ void setGraphicsContext(GraphicsContext* context); /** Get the GraphicsContext.*/ GraphicsContext* getGraphicsContext() { return _graphicsContext.get(); } /** Get the const GraphicsContext.*/ const GraphicsContext* getGraphicsContext() const { return _graphicsContext.get(); } /** Set the Rendering object that is used to implement rendering of the subgraph.*/ void setRenderingCache(unsigned int contextID, osg::Object* rc) { _renderingCache[contextID] = rc; } /** Get the Rendering object that is used to implement rendering of the subgraph.*/ osg::Object* getRenderingCache(unsigned int contextID) { return _renderingCache[contextID].get(); } /** Get the const Rendering object that is used to implement rendering of the subgraph.*/ const osg::Object* getRenderingCache(unsigned int contextID) const { return _renderingCache[contextID].get(); } /** Draw callback for custom operations.*/ struct DrawCallback : virtual public Object { DrawCallback() {} DrawCallback(const DrawCallback&,const CopyOp&) {} META_Object(osg,DrawCallback) virtual void operator () (const osg::Camera& /*camera*/) const {} }; /** Set the post draw callback for custom operations to do done after the drawing of the camera's subgraph has been completed.*/ void setPostDrawCallback(DrawCallback* cb) { _postDrawCallback = cb; } /** Get the post draw callback.*/ DrawCallback* getPostDrawCallback() { return _postDrawCallback.get(); } /** Get the const post draw callback.*/ const DrawCallback* getPostDrawCallback() const { return _postDrawCallback.get(); } OpenThreads::Mutex* getDataChangeMutex() const { return &_dataChangeMutex; } /** Resize any per context GLObject buffers to specified size. */ virtual void resizeGLObjectBuffers(unsigned int maxSize); /** If State is non-zero, this function releases any associated OpenGL objects for * the specified graphics context. Otherwise, releases OpenGL objexts * for all graphics contexts. */ virtual void releaseGLObjects(osg::State* = 0) const; public: /** Transform method that must be defined to provide generic interface for scene graph traversals.*/ virtual bool computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const; /** Transform method that must be defined to provide generic interface for scene graph traversals.*/ virtual bool computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor*) const; protected : virtual ~Camera(); mutable OpenThreads::Mutex _dataChangeMutex; View* _view; osg::ref_ptr _stats; Vec4 _clearColor; GLbitfield _clearMask; ref_ptr _colorMask; ref_ptr _viewport; TransformOrder _transformOrder; Matrixd _projectionMatrix; Matrixd _viewMatrix; RenderOrder _renderOrder; int _renderOrderNum; GLenum _drawBuffer; GLenum _readBuffer; RenderTargetImplementation _renderTargetImplementation; RenderTargetImplementation _renderTargetFallback; BufferAttachmentMap _bufferAttachmentMap; ref_ptr _cameraThread; ref_ptr _graphicsContext; buffered_object< ref_ptr > _renderingCache; ref_ptr _postDrawCallback; }; } #endif