/* -*-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; class RenderInfo; /** 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(); } /** Set whether this camera allows events to be generated by the associated graphics window to be associated with this camera.*/ void setAllowEventFocus(bool focus) { _allowEventFocus = focus; } /** Get whether this camera allows events to be generated by the associated graphics window to be associated with this camera.*/ bool getAllowEventFocus() const { return _allowEventFocus; } /** Set the DsplaySettings object associated with this view.*/ void setDisplaySettings(osg::DisplaySettings* ds) { _displaySettings = ds; } /** Set the DsplaySettings object associated with this view.*/ osg::DisplaySettings* getDisplaySettings() { return _displaySettings.get(); } /** Set the DsplaySettings object associated with this view.*/ const osg::DisplaySettings* getDisplaySettings() const { return _displaySettings.get(); } /** 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 clear color used in glClearColor(..). * glClearColor is only called if mask & GL_COLOR_BUFFER_BIT is true*/ void setClearColor(const osg::Vec4& color) { _clearColor=color; } /** Get the clear color.*/ const osg::Vec4& getClearColor() const { return _clearColor; } /** Set the clear accum used in glClearAccum(..). * glClearAcumm is only called if mask & GL_ACCUM_BUFFER_BIT is true. */ void setClearAccum(const osg::Vec4& color) { _clearAccum=color; } /** Get the clear accum value.*/ const osg::Vec4& getClearAccum() const { return _clearAccum; } /** Set the clear depth used in glClearDepth(..). Defaults to 1.0 * glClearDepth is only called if mask & GL_DEPTH_BUFFER_BIT is true. */ void setClearDepth(double depth) { _clearDepth=depth; } /** Get the clear depth value.*/ double getClearDepth() const { return _clearDepth; } /** Set the clear stencil value used in glClearStencil(). Defaults to 0; * glClearStencil is only called if mask & GL_STENCIL_BUFFER_BIT is true*/ void setClearStencil(int stencil) { _clearStencil=stencil; } /** Get the clear stencil value.*/ int getClearStencil() const { return _clearStencil; } /** 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; } enum ProjectionResizePolicy { FIXED, /** Keep the projection matrix fixed, despite window resizes.*/ HORIZONTAL, /** Adjust the HORIZOTNAL field of view on window resizes.*/ VERTICAL /** Adjust the VERTICAL field of view on window resizes.*/ }; /** Set the policy used to determine if and how the projection matrix should be adjusted on window resizes. */ inline void setProjectionResizePolicy(ProjectionResizePolicy policy) { _projectionResizePolicy = policy; } /** Get the policy used to determine if and how the projection matrix should be adjusted on window resizes. */ inline ProjectionResizePolicy getProjectionResizePolicy() const { return _projectionResizePolicy; } /** 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 orthographic 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();} /** Get the view matrix. */ osg::Matrixd& getViewMatrix() { return _viewMatrix; } /** Get the const view matrix. */ const osg::Matrixd& getViewMatrix() const { return _viewMatrix; } /** Set to the position and orientation of view matrix, using the same convention as gluLookAt. */ void setViewMatrixAsLookAt(const osg::Vec3d& eye,const osg::Vec3d& center,const osg::Vec3d& up); /** Get to the position and orientation of a modelview matrix, using the same convention as gluLookAt. */ void getViewMatrixAsLookAt(osg::Vec3d& eye,osg::Vec3d& center,osg::Vec3d& up,double lookDistance=1.0); /** Get to the position and orientation of a modelview matrix, using the same convention as gluLookAt. */ void getViewMatrixAsLookAt(osg::Vec3f& eye,osg::Vec3f& center,osg::Vec3f& 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_BUFFER1 = COLOR_BUFFER0+1, COLOR_BUFFER2 = COLOR_BUFFER0+2, COLOR_BUFFER3 = COLOR_BUFFER0+3, COLOR_BUFFER4 = COLOR_BUFFER0+4, COLOR_BUFFER5 = COLOR_BUFFER0+5, COLOR_BUFFER6 = COLOR_BUFFER0+6, COLOR_BUFFER7 = COLOR_BUFFER0+7, COLOR_BUFFER8 = COLOR_BUFFER0+8, COLOR_BUFFER9 = COLOR_BUFFER0+9, COLOR_BUFFER10 = COLOR_BUFFER0+10, COLOR_BUFFER11 = COLOR_BUFFER0+11, COLOR_BUFFER12 = COLOR_BUFFER0+12, COLOR_BUFFER13 = COLOR_BUFFER0+13, COLOR_BUFFER14 = COLOR_BUFFER0+14, COLOR_BUFFER15 = COLOR_BUFFER0+15 }; /** Attach a buffer with specified OpenGL internal format.*/ void attach(BufferComponent buffer, GLenum internalFormat); /** Attach a Texture to specified buffer component. * The level parameter controls the mip map level of the texture that is attached. * The face parameter controls the face of texture cube map or z level of 3d texture. * The mipMapGeneration flag controls whether mipmap generation should be done for texture.*/ void attach(BufferComponent buffer, osg::Texture* texture, unsigned int level = 0, unsigned int face=0, bool mipMapGeneration=false); /** Attach a Image to specified buffer component.*/ void attach(BufferComponent buffer, osg::Image* image); /** Detach specified buffer component.*/ 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(OperationThread* gt); /** Get the operation thread assigned to this camera.*/ OperationThread* getCameraThread() { return _cameraThread.get(); } /** Get the const operation thread assigned to this camera.*/ const OperationThread* 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 setRenderer(osg::GraphicsOperation* rc) { _renderer = rc; } /** Get the Rendering object that is used to implement rendering of the subgraph.*/ osg::GraphicsOperation* getRenderer() { return _renderer.get(); } /** Get the const Rendering object that is used to implement rendering of the subgraph.*/ const osg::GraphicsOperation* getRenderer() const { return _renderer.get(); } /** Set the Rendering cache that is used for cached objects associated with rendering of subgraphs.*/ void setRenderingCache(osg::Object* rc) { _renderingCache = rc; } /** Get the Rendering cache that is used for cached objects associated with rendering of subgraphs.*/ osg::Object* getRenderingCache() { return _renderingCache.get(); } /** Get the const Rendering cache that is used for cached objects associated with rendering of subgraphs.*/ const osg::Object* getRenderingCache() const { return _renderingCache.get(); } /** Draw callback for custom operations.*/ struct OSG_EXPORT DrawCallback : virtual public Object { DrawCallback() {} DrawCallback(const DrawCallback&,const CopyOp&) {} META_Object(osg,DrawCallback) virtual void operator () (osg::RenderInfo& renderInfo) const; virtual void operator () (const osg::Camera& /*camera*/) const {} }; /** Set the initial draw callback for custom operations to be done before the drawing of the camera's subgraph and pre render stages.*/ void setInitialDrawCallback(DrawCallback* cb) { _initialDrawCallback = cb; } /** Get the initial draw callback.*/ DrawCallback* getInitialDrawCallback() { return _initialDrawCallback.get(); } /** Get the const initial draw callback.*/ const DrawCallback* getInitialDrawCallback() const { return _initialDrawCallback.get(); } /** Set the pre draw callback for custom operations to be done before the drawing of the camera's subgraph but after any pre render stages have been completed.*/ void setPreDrawCallback(DrawCallback* cb) { _preDrawCallback = cb; } /** Get the pre draw callback.*/ DrawCallback* getPreDrawCallback() { return _preDrawCallback.get(); } /** Get the const pre draw callback.*/ const DrawCallback* getPreDrawCallback() const { return _preDrawCallback.get(); } /** Set the post draw callback for custom operations to be done after the drawing of the camera's subgraph but before the any post render stages have 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(); } /** Set the final draw callback for custom operations to be done after the drawing of the camera's subgraph and all of the post render stages has been completed.*/ void setFinalDrawCallback(DrawCallback* cb) { _finalDrawCallback = cb; } /** Get the final draw callback.*/ DrawCallback* getFinalDrawCallback() { return _finalDrawCallback.get(); } /** Get the const final draw callback.*/ const DrawCallback* getFinalDrawCallback() const { return _finalDrawCallback.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; bool _allowEventFocus; osg::ref_ptr _displaySettings; GLbitfield _clearMask; osg::Vec4 _clearColor; osg::Vec4 _clearAccum; double _clearDepth; int _clearStencil; ref_ptr _colorMask; ref_ptr _viewport; TransformOrder _transformOrder; ProjectionResizePolicy _projectionResizePolicy; Matrixd _projectionMatrix; Matrixd _viewMatrix; RenderOrder _renderOrder; int _renderOrderNum; GLenum _drawBuffer; GLenum _readBuffer; RenderTargetImplementation _renderTargetImplementation; RenderTargetImplementation _renderTargetFallback; BufferAttachmentMap _bufferAttachmentMap; ref_ptr _cameraThread; ref_ptr _graphicsContext; ref_ptr _renderer; ref_ptr _renderingCache; ref_ptr _initialDrawCallback; ref_ptr _preDrawCallback; ref_ptr _postDrawCallback; ref_ptr _finalDrawCallback; }; } #endif