Camera 30.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
/* -*-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 <osg/Transform>
#include <osg/Viewport>
#include <osg/ColorMask>
#include <osg/CullSettings>
#include <osg/Texture>
#include <osg/Image>
#include <osg/GraphicsContext>
#include <osg/Stats>

#include <OpenThreads/Mutex>

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 DisplaySettings object associated with this view.*/
        void setDisplaySettings(osg::DisplaySettings* ds) { _displaySettings = ds; }

        /** Get the DisplaySettings object associated with this view.*/
        osg::DisplaySettings* getDisplaySettings() { return _displaySettings.get(); }

        /** Get the const DisplaySettings 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; applyMaskAction(CLEAR_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; applyMaskAction(CLEAR_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 HORIZONTAL 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) const;

        /** 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) const;

        /** 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) const;



        /** 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) const;

        /** 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) const;

        /** 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; applyMaskAction( DRAW_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; applyMaskAction( READ_BUFFER ); }

        /** Get the read buffer for any required copy operations to use. */
        GLenum getReadBuffer() const { return _readBuffer; }

        enum BufferComponent
        {
            DEPTH_BUFFER,
            STENCIL_BUFFER,
            PACKED_DEPTH_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
        };

        static const unsigned int FACE_CONTROLLED_BY_GEOMETRY_SHADER;

        /** 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,
            unsigned int multisampleSamples = 0,
            unsigned int multisampleColorSamples = 0);

        /** Attach a Image to specified buffer component.*/
        void attach(BufferComponent buffer, osg::Image* image,
            unsigned int multisampleSamples = 0,
            unsigned int multisampleColorSamples = 0);

        /** Detach specified buffer component.*/
        void detach(BufferComponent buffer);

        struct Attachment
        {
            Attachment():
                _internalFormat(GL_NONE),
                _level(0),
                _face(0),
                _mipMapGeneration(false),
                _multisampleSamples(0),
                _multisampleColorSamples(0) {}

            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>      _image;
            ref_ptr<Texture>    _texture;
            unsigned int        _level;
            unsigned int        _face;
            bool                _mipMapGeneration;
            unsigned int        _multisampleSamples;
            unsigned int        _multisampleColorSamples;
        };

        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; }


        /** Explicit control over implicit allocation of buffers when using FBO.
         Implicit buffers are automatically substituted when user have not attached such buffer.

         Camera may set up two FBOs: primary Render FBO and secondary Resolve FBO for multisample usage.
         So in practive we have two masks defined for the Camera:
            implicitBufferAttachmentRenderMask
            implicitBufferAttachmentResolveMask
         They can be set together by setImplicitBufferAttachmentMask method, or separately
         by setImplicitBufferAttachmentRenderMask and setImplicitBufferAttachmentResolveMask.

         Camera defaults are USE_DISPLAY_SETTINGS_MASK which means that by default
         Camera chooses to substitue buffer attachments as defined by DisplaySettings.

         Usually DisplaySettings implicit buffer attachment selection defaults to: DEPTH and COLOR 
         for both primary (Render) FBO and seconday Multisample (Resolve) FBO
         ie: IMPLICT_DEPTH_BUFFER_ATTACHMENT | IMPLICIT_COLOR_BUFFER_ATTACHMENT

         If these masks are not changed and user did not attach depth buffer and/or color buffer 
         to Camera, then OSG implicitly substitues these buffers.
         By default it does not implicitly allocate a stencil buffer.
         Use implicti buffer attachment  masks to override default behavior: 
         to turn off DEPTH or COLOR buffer substitution or to enforce STENCIL buffer substitution.

         Note that both values are ignored if not using FBO.
         Note that the second mask value is ignored if not using MSFBO.
        */
        enum ImplicitBufferAttachment
        {
            IMPLICIT_DEPTH_BUFFER_ATTACHMENT = DisplaySettings::IMPLICIT_DEPTH_BUFFER_ATTACHMENT,
            IMPLICIT_STENCIL_BUFFER_ATTACHMENT = DisplaySettings::IMPLICIT_STENCIL_BUFFER_ATTACHMENT,
            IMPLICIT_COLOR_BUFFER_ATTACHMENT = DisplaySettings::IMPLICIT_COLOR_BUFFER_ATTACHMENT,
            USE_DISPLAY_SETTINGS_MASK = (~0)
        };

        typedef int ImplicitBufferAttachmentMask;

        void setImplicitBufferAttachmentMask(ImplicitBufferAttachmentMask renderMask = DisplaySettings::DEFAULT_IMPLICIT_BUFFER_ATTACHMENT, ImplicitBufferAttachmentMask resolveMask = DisplaySettings::DEFAULT_IMPLICIT_BUFFER_ATTACHMENT)
        {
            _implicitBufferAttachmentRenderMask = renderMask;
            _implicitBufferAttachmentResolveMask = resolveMask;
        }

        void setImplicitBufferAttachmentRenderMask(ImplicitBufferAttachmentMask implicitBufferAttachmentRenderMask)
        {
            _implicitBufferAttachmentRenderMask = implicitBufferAttachmentRenderMask;
        }

        void setImplicitBufferAttachmentResolveMask(ImplicitBufferAttachmentMask implicitBufferAttachmentResolveMask)
        {
            _implicitBufferAttachmentResolveMask = implicitBufferAttachmentResolveMask;
        }

        /** 
        Get mask selecting implict buffer attachments for Camera primary FBO 
        if effectiveMask parameter is set, method follows USE_DISPLAY_SETTINGS_MASK dependence and returns effective mask
        if effectiveMask parameter is reset, method returns nominal mask set by the Camera
        */
        ImplicitBufferAttachmentMask getImplicitBufferAttachmentRenderMask(bool effectiveMask = false) const
        { 
            if( effectiveMask && _implicitBufferAttachmentRenderMask == USE_DISPLAY_SETTINGS_MASK )
            {
                const DisplaySettings * ds = _displaySettings.valid() ? _displaySettings.get() : DisplaySettings::instance().get();
                return ds->getImplicitBufferAttachmentRenderMask();
            }
            else
            {
                return _implicitBufferAttachmentRenderMask;
            }
        }

        /** 
        Get mask selecting implict buffer attachments for Camera secondary MULTISAMPLE FBO 
        if effectiveMask parameter is set, method follows USE_DISPLAY_SETTINGS_MASK dependence and returns effective mask
        if effectiveMask parameter is reset, method returns nominal mask set by the Camera
        */
        ImplicitBufferAttachmentMask getImplicitBufferAttachmentResolveMask(bool effectiveMask = false) const
        { 
            if( effectiveMask && _implicitBufferAttachmentResolveMask == USE_DISPLAY_SETTINGS_MASK )
            {
                const DisplaySettings * ds = _displaySettings.valid() ? _displaySettings.get() : DisplaySettings::instance().get();
                return ds->getImplicitBufferAttachmentResolveMask();
            }
            else
            {
                return _implicitBufferAttachmentResolveMask;
            }
        }

        /** 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);

            /** Functor method called by rendering thread. Users will typically override this method to carry tasks such as screen capture.*/
            virtual void operator () (osg::RenderInfo& renderInfo) const;

            /** Functor method, provided for backwards compatibility, called by operator() (osg::RenderInfo& renderInfo) method.*/
            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;

        /** Inherit the local cull settings variable from specified CullSettings object, according to the inheritance mask.*/
        virtual void inheritCullSettings(const CullSettings& settings, unsigned int inheritanceMask);

    protected :

        virtual ~Camera();

        mutable OpenThreads::Mutex          _dataChangeMutex;


        View*                               _view;

        osg::ref_ptr<osg::Stats>            _stats;

        bool                                _allowEventFocus;

        osg::ref_ptr<osg::DisplaySettings>  _displaySettings;

        GLbitfield                          _clearMask;
        osg::Vec4                           _clearColor;
        osg::Vec4                           _clearAccum;
        double                              _clearDepth;
        int                                 _clearStencil;

        ref_ptr<ColorMask>                  _colorMask;
        ref_ptr<Viewport>                   _viewport;

        TransformOrder                      _transformOrder;
        ProjectionResizePolicy              _projectionResizePolicy;

        Matrixd                             _projectionMatrix;
        Matrixd                             _viewMatrix;

        RenderOrder                         _renderOrder;
        int                                 _renderOrderNum;

        GLenum                              _drawBuffer;
        GLenum                              _readBuffer;

        RenderTargetImplementation          _renderTargetImplementation;
        RenderTargetImplementation          _renderTargetFallback;
        BufferAttachmentMap                 _bufferAttachmentMap;
        ImplicitBufferAttachmentMask        _implicitBufferAttachmentRenderMask;
        ImplicitBufferAttachmentMask        _implicitBufferAttachmentResolveMask;

        ref_ptr<OperationThread>            _cameraThread;

        ref_ptr<GraphicsContext>            _graphicsContext;

        ref_ptr<GraphicsOperation>          _renderer;
        ref_ptr<Object>                     _renderingCache;

        ref_ptr<DrawCallback>               _initialDrawCallback;
        ref_ptr<DrawCallback>               _preDrawCallback;
        ref_ptr<DrawCallback>               _postDrawCallback;
        ref_ptr<DrawCallback>               _finalDrawCallback;
};

}

#endif