root/OpenSceneGraph/trunk/src/osgShadow/DebugShadowMap.cpp @ 9540

Revision 9540, 22.8 kB (checked in by robert, 6 years ago)

Added forward declaration of callbacks to headers to avoid scoping issues of classes with same names.

RevLine 
[8984]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12 *
13 * ViewDependentShadow codes Copyright (C) 2008 Wojciech Lewandowski
14 * Thanks to to my company http://www.ai.com.pl for allowing me free this work.
15*/
16
17#include <osgShadow/DebugShadowMap>
18#include <osgShadow/ConvexPolyhedron>
19#include <osgUtil/RenderLeaf>
20#include <osg/Geometry>
21#include <osg/PrimitiveSet>
22#include <osg/MatrixTransform>
23#include <osg/Depth>
24#include <iostream>
25#include <iomanip>
26
27using namespace osgShadow;
28
29
30#define VECTOR_LENGTH( v ) ( sizeof(v)/sizeof(v[0]) )
31
32#define DEFAULT_DEBUG_HUD_SIZE_X 256
33#define DEFAULT_DEBUG_HUD_SIZE_Y 256
34#define DEFAULT_DEBUG_HUD_ORIGIN_X 8
35#define DEFAULT_DEBUG_HUD_ORIGIN_Y 8
36
37DebugShadowMap::DebugShadowMap():
38    BaseClass(),
39    _hudSize( 2, 2 ),
40    _hudOrigin( -1, -1 ),
41    _viewportSize( DEFAULT_DEBUG_HUD_SIZE_X, DEFAULT_DEBUG_HUD_SIZE_Y ),
42    _viewportOrigin( DEFAULT_DEBUG_HUD_ORIGIN_X, DEFAULT_DEBUG_HUD_ORIGIN_Y ),
43    _orthoSize( 2, 2 ),
[9376]44    _orthoOrigin( -1, -1 ),
45    _doDebugDraw( false )
[8984]46{
47   
48    // Why this fancy 24 bit depth to 24 bit rainbow colors shader ?
49    //
50    // Depth values cannot be easily cast on color component because they are:
51    // a) 24 or 32 bit and we loose lots of precision when cast on 8 bit
52    // b) depth value distribution is non linear due to projection division
53    // when cast on componenent color there is usually very minor shade variety
54    // and its often difficult to notice that there is anything in the buffer
55    //
56    // Shader looks complex but it is used only for debug head-up rectangle
57    // so performance impact is not significant. 
58   
59    _depthColorFragmentShader = new osg::Shader( osg::Shader::FRAGMENT,
60#if 0
61        "uniform sampler2D texture;                                              \n"
62        "                                                                        \n"
63        "void main(void)                                                         \n"
64        "{                                                                       \n"
65        "    float f = texture2D( texture, vec3( gl_TexCoord[0].xy, 1.0).xy ).r; \n"
66        "    gl_FragColor =  vec4( 0.0, 1.0 - f,  0.5 - f, 0.5 );                \n"
[8986]67        "}                                                                       \n"         
[8984]68#else 
69        "uniform sampler2D texture;                                              \n"
70        "                                                                        \n"
71        "void main(void)                                                         \n"
72        "{                                                                       \n"
73        "    float f = texture2D( texture, vec3( gl_TexCoord[0].xy, 1.0).xy ).r; \n"
74        "                                                                        \n"
75        "    f = 256.0 * f;                                                      \n"
76        "    float fC = floor( f ) / 256.0;                                      \n" 
77        "                                                                        \n"
78        "    f = 256.0 * fract( f );                                             \n"
79        "    float fS = floor( f ) / 256.0;                                      \n" 
80        "                                                                        \n"
81        "    f = 256.0 * fract( f );                                             \n"
82        "    float fH = floor( f ) / 256.0;                                      \n"
83        "                                                                        \n"
84        "    fS *= 0.5;                                                          \n"
85        "    fH = ( fH  * 0.34 + 0.66 ) * ( 1.0 - fS );                          \n"
86        "                                                                        \n"
87        "    vec3 rgb = vec3( ( fC > 0.5 ? ( 1.0 - fC ) : fC ),                  \n"
88        "                     abs( fC - 0.333333 ),                              \n"
89        "                     abs( fC - 0.666667 ) );                            \n"
90        "                                                                        \n"   
91        "    rgb = min( vec3( 1.0, 1.0, 1.0 ), 3.0 * rgb );                      \n"
92        "                                                                        \n"
93        "    float fMax = max( max( rgb.r, rgb.g ), rgb.b );                     \n"
94        "    fMax = 1.0 / fMax;                                                  \n" 
95        "                                                                        \n"
96        "    vec3 color = fMax * rgb;                                            \n"
97        "                                                                        \n"
98        "    gl_FragColor =  vec4( fS + fH * color, 1 ) * gl_Color;              \n"
99        "}                                                                       \n" 
100#endif
101    ); // end _depthColorFragmentShader
102}
103
104DebugShadowMap::DebugShadowMap
105(const DebugShadowMap& copy, const osg::CopyOp& copyop) :
106    BaseClass(copy,copyop),
107    _hudSize( copy._hudSize ),
108    _hudOrigin( copy._hudOrigin ),
109    _viewportSize( copy._viewportSize ),
110    _viewportOrigin( copy._viewportOrigin ),
111    _orthoSize( copy._viewportOrigin ),
[9376]112    _orthoOrigin( copy._viewportOrigin ),
113    _doDebugDraw( copy._doDebugDraw )
[8984]114{
115    if( copy._depthColorFragmentShader.valid() )
116        _depthColorFragmentShader =
117            dynamic_cast<osg::Shader*>
118                ( copy._depthColorFragmentShader->clone(copyop) );
119}
120
121DebugShadowMap::~DebugShadowMap()
122{
123}
124
125void DebugShadowMap::ViewData::cull( void )
126{
127    if( getDebugDraw() && !_cameraDebugHUD.valid() )
128        createDebugHUD();
129
130    BaseClass::ViewData::cull( );
131
132    cullDebugGeometry( );
133}
134
135bool DebugShadowMap::ViewData::DebugBoundingBox
136    ( const osg::BoundingBox & bb, const char * name )
137{
138    bool result = false;
[8986]139#if defined( _DEBUG    ) || defined( DEBUG )
[8984]140    if( !name ) name = "";
141
142    osg::BoundingBox & bb_prev = _boundingBoxMap[ std::string( name ) ];
143
144    result = bb.center() != bb_prev.center() || bb.radius() != bb_prev.radius();
145    if( result )
146        std::cout << "Box<" << name << "> (" 
147                  << ( bb._max._v[0] + bb._min._v[0] ) * 0.5 << " "
148                  << ( bb._max._v[1] + bb._min._v[1] ) * 0.5 << " " 
149                  << ( bb._max._v[2] + bb._min._v[2] ) * 0.5 << ") ["
150                  << ( bb._max._v[0] - bb._min._v[0] ) << " "
151                  << ( bb._max._v[1] - bb._min._v[1] ) << " "
152                  << ( bb._max._v[2] - bb._min._v[2] ) << "] "
153                  << std::endl;
154
155    bb_prev = bb;
156#endif
157    return result;
158}
159
160bool DebugShadowMap::ViewData::DebugPolytope
161( const osg::Polytope & p, const char * name )
162{
163    bool result = false;
[8986]164#if defined( _DEBUG    ) || defined( DEBUG )
[8984]165    if( !name ) name = "";
166
167    osg::Polytope & p_prev = _polytopeMap[ std::string( name ) ];
168
169    result = ( p.getPlaneList() != p_prev.getPlaneList() );
170
171    if( result ) {
172        std::cout << "Polytope<" << name
173                  << "> size(" << p.getPlaneList().size() << ")"
174                  << std::endl;
175
176        if( p.getPlaneList().size() == p_prev.getPlaneList().size() ) {
177            for( unsigned i = 0; i < p.getPlaneList().size(); ++i )
178            {
179                if( p.getPlaneList()[i] != p_prev.getPlaneList()[i] )
180                {
181                    std::cout << "Plane<" << i
182                        << "> (" 
183                        << p.getPlaneList()[i].asVec4()[0] << ", "
184                        << p.getPlaneList()[i].asVec4()[1] << ", "
185                        << p.getPlaneList()[i].asVec4()[2] << ", "
186                        << p.getPlaneList()[i].asVec4()[3] << ")"
187                        << std::endl;                   
188                }
189            }
190        }
191    }
192
193    p_prev = p;
194#endif
195    return result;
196}
197
198bool DebugShadowMap::ViewData::DebugMatrix
199    ( const osg::Matrix & m, const char * name )
200{
201    bool result = false;
[8986]202#if defined( _DEBUG    ) || defined( DEBUG )
[8984]203    if( !name ) name = "";
204
205    osg::Matrix & m_prev = _matrixMap[ std::string( name ) ];
206
207    result = ( m != m_prev );
208
209    if( result )
210        std::cout << "Matrix<" << name << "> " << std::endl
211            <<"[ " << m(0,0) << " " << m(0,1) << " " << m(0,2) << " " << m(0,3) << " ]  " << std::endl
212            <<"[ " << m(1,0) << " " << m(1,1) << " " << m(1,2) << " " << m(1,3) << " ]  " << std::endl
213            <<"[ " << m(2,0) << " " << m(2,1) << " " << m(2,2) << " " << m(2,3) << " ]  " << std::endl
214            <<"[ " << m(3,0) << " " << m(3,1) << " " << m(3,2) << " " << m(3,3) << " ]  " << std::endl;
215
216    m_prev = m;
217#endif
218    return result;
219}
220
221void DebugShadowMap::ViewData::setDebugPolytope
222    ( const char * name, const ConvexPolyhedron & polytope,
223      osg::Vec4 colorOutline, osg::Vec4 colorInside )
224{
225    if( !getDebugDraw() ) return;
226
227    if( &polytope == NULL ) { // delete       
228        PolytopeGeometry & pg = _polytopeGeometryMap[ std::string( name ) ];
[9376]229        for( unsigned int i = 0; i < VECTOR_LENGTH( pg._geometry ) ; i++ )
[8984]230        {
231            if( pg._geometry[i].valid() ) {
232                if( _geode[i].valid() &&
233                    _geode[i]->containsDrawable( pg._geometry[i].get() ) )
234                        _geode[i]->removeDrawable( pg._geometry[i].get() );
235
236                pg._geometry[i] = NULL;
237            }
238        }
239        _polytopeGeometryMap.erase( std::string( name ) );
240    } else { // update
241        PolytopeGeometry & pg = _polytopeGeometryMap[ std::string( name ) ];
242
243        pg._polytope = polytope;
244        if( colorOutline.a() > 0 )
245            pg._colorOutline = colorOutline;
246        if( colorInside.a() > 0 )
247            pg._colorInside = colorInside;
248
[9376]249        for( unsigned int i = 0; i < VECTOR_LENGTH( pg._geometry ) ; i++ )
[8984]250        {
251            if( !pg._geometry[i].valid() ) {
252                pg._geometry[i] = new osg::Geometry;
253                pg._geometry[i]->setDataVariance( osg::Object::DYNAMIC );
254                pg._geometry[i]->setUseDisplayList( false );
255                pg._geometry[i]->setSupportsDisplayList( false );
256            }
257
258            if( _geode[i].valid() &&
259                  !_geode[i]->containsDrawable( pg._geometry[i].get() ) ) {
260                        osg::Geode::DrawableList & dl =
261                           const_cast< osg::Geode::DrawableList &>
262                              ( _geode[i]->getDrawableList() );
263                        dl.insert( dl.begin(), pg._geometry[i].get() );
264            }           
265        }       
266    }
267}
268
269void DebugShadowMap::ViewData::updateDebugGeometry
270    ( const osg::Camera * viewCam, const osg::Camera * shadowCam )
271{
272    if( !getDebugDraw() ) return;
273    if( _polytopeGeometryMap.empty() ) return;
274
275    const int num = 2; // = VECTOR_LENGTH( PolytopeGeometry::_geometry );
276   
[8986]277    osg::Matrix   
[8984]278        transform[ num ] =
279            { viewCam->getViewMatrix() *
280                // use near far clamped projection ( precomputed in cullDebugGeometry )
281                ( viewCam == _viewCamera ? _viewProjection : viewCam->getProjectionMatrix() ),
282              shadowCam->getViewMatrix() * shadowCam->getProjectionMatrix() },
283        inverse[ num ] =
284            { osg::Matrix::inverse( transform[0] ),
285              osg::Matrix::inverse( transform[1] ) };
286
287#if 0
288    ConvexPolyhedron frustum[ num ];
289    for( int i = 0; i < num; i++ ) {
290        frustum[i].setToUnitFrustum( );
291#if 1
292        frustum[i].transform( inverse[i], transform[i] );
293#else
294        frustum[i].transform
295            ( osg::Matrix::inverse( camera[i]->getProjectionMatrix() ),
296              camera[i]->getProjectionMatrix() );
297        frustum[i].transform
298            ( osg::Matrix::inverse( camera[i]->getViewMatrix() ),
299              camera[i]->getViewMatrix() );
300#endif       
301    };
302#else
303    osg::Polytope frustum[ num ];
304    for( int i = 0; i < num; i++ ) {
305        frustum[i].setToUnitFrustum( );
306        frustum[i].transformProvidingInverse( transform[i] );
307    }
308#endif
309
310    transform[0] = viewCam->getViewMatrix();
311    inverse[0] = viewCam->getInverseViewMatrix();
312
313    for( PolytopeGeometryMap::iterator itr = _polytopeGeometryMap.begin();
314         itr != _polytopeGeometryMap.end();
315         ++itr )
316    {
317        PolytopeGeometry & pg = itr->second;
318
319        for( int i = 0; i < num ; i++ )
320        {
321
[8986]322            ConvexPolyhedron cp( pg._polytope );       
[8984]323            cp.cut( frustum[i] );
324            cp.transform( transform[i], inverse[i] );
325
326            pg._geometry[i] = cp.buildGeometry
327                ( pg._colorOutline, pg._colorInside, pg._geometry[i].get() );
328        }
329    }
330}
331
332void DebugShadowMap::ViewData::cullDebugGeometry( )
333{   
334    if( !getDebugDraw() ) return;
335    if( !_camera.valid() ) return;
336
337    // View camera may use clamping projection matrix after traversal.
338    // Since we need to know exact matrix for drawing the frusta,
339    // we have to compute it here in exactly the same way as cull visitor
340    // will after cull traversal completes view camera subgraph.
341    {
342        _viewProjection = *_cv->getProjectionMatrix();
343        _viewCamera = _cv->getRenderStage()->getCamera();
344
345        if( _cv->getComputeNearFarMode() ) {
346
347            // Redo steps from CullVisitor::popProjectionMatrix()
348            // which clamps projection matrix when Camera & Projection
349            // completes traversal of their children
350
351            // We have to do this now manually
352            // because we did not complete camera traversal yet but
353            // we need to know how this clamped projection matrix will be
354
355            _cv->computeNearPlane();
356       
[8989]357            osgUtil::CullVisitor::value_type n = _cv->getCalculatedNearPlane();
358            osgUtil::CullVisitor::value_type f = _cv->getCalculatedFarPlane();
[8984]359
360            if( n < f )
[8989]361                _cv->clampProjectionMatrix( _viewProjection, n, f );
[8984]362        }
363    }
364   
365    updateDebugGeometry( _viewCamera, _camera.get() );
366   
367#if 1 // Add geometries of polytopes to main cam Render Stage 
368    _transform[0]->accept( *_cv );
369#else
370    for( PolytopeGeometryMap::iterator itr = _polytopeGeometryMap.begin();
371         itr != _polytopeGeometryMap.end();
372         ++itr )
373    {
374        PolytopeGeometry & pg = itr->second;
375        _cv->pushStateSet( _geode[0]->getStateSet() );
376        _cv->addDrawableAndDepth( pg._geometry[0].get(), NULL, FLT_MAX );
377        _cv->popStateSet( );
378    }
379#endif
380
381    // Add geometries of polytopes to hud cam Render Stage
382    _cameraDebugHUD->accept( *_cv );
383}
384
385void DebugShadowMap::ViewData::init( ThisClass *st, osgUtil::CullVisitor *cv )
386{
387    BaseClass::ViewData::init( st, cv );
388
389    _doDebugDrawPtr           = &st->_doDebugDraw;
390
391    _hudSize                  = st->_hudSize;
392    _hudOrigin                = st->_hudOrigin;
393    _viewportSize             = st->_viewportSize;
394    _viewportOrigin           = st->_viewportOrigin;
395    _orthoSize                = st->_orthoSize;
396    _orthoOrigin              = st->_orthoOrigin;
397   
398    _depthColorFragmentShader = st->_depthColorFragmentShader;
399
400    // create placeholder geodeds for polytope geometries
401    // rest of their initialization will be performed during camera hud init
402    _geode[0] = new osg::Geode;
403    _geode[1] = new osg::Geode;
404   
405    _cameraDebugHUD           = NULL;//Force debug HUD rebuild ( if needed )
406}
407
[9540]408
[8984]409// Callback used by debugging hud to display Shadow Map to color buffer
410// Had to do it this way because OSG does not allow to use
411// the same GL Texture Id with different glTexParams.
412// Callback simply turns compare mode off via GL while rendering hud and
413// restores it before rendering the scene with shadows.
[9540]414class DebugShadowMap::DrawableDrawWithDepthShadowComparisonOffCallback:
[8984]415    public osg::Drawable::DrawCallback
416{
417public:
418    DrawableDrawWithDepthShadowComparisonOffCallback( osg::Texture2D *pTex )
419        : _pTexture( pTex )
420    {
421    }
422
423    virtual void drawImplementation
424        ( osg::RenderInfo & ri,const osg::Drawable* drawable ) const
425    {
426        ri.getState()->applyTextureAttribute( 0, _pTexture.get() );
427
428        // Turn off depth comparison mode
429        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
430
431        drawable->drawImplementation(ri);
432
433        // Turn it back on
434        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,
435            GL_COMPARE_R_TO_TEXTURE_ARB );           
436    }
437
438    osg::ref_ptr< osg::Texture2D > _pTexture;
439};
440
441void DebugShadowMap::ViewData::createDebugHUD( )
442{   
443    _cameraDebugHUD = new osg::Camera;
444
445    { // Make sure default HUD layout makes sense
446        if( _hudSize[0] <= 0 ) _hudSize[0] = DEFAULT_DEBUG_HUD_SIZE_X;
447        if( _hudSize[1] <= 0 ) _hudSize[1] = DEFAULT_DEBUG_HUD_SIZE_Y;
448
449        if( _viewportSize[0] <= 0 ) _viewportSize[0] = _hudSize[0];
450        if( _viewportSize[1] <= 0 ) _viewportSize[1] = _hudSize[1];
451
452        if( _orthoSize[0] <= 0 ) _orthoSize[0] = _viewportSize[0];
453        if( _orthoSize[1] <= 0 ) _orthoSize[1] = _viewportSize[1];
454    }
455
[8986]456    { // Initialize hud camera   
[8984]457        osg::Camera * camera = _cameraDebugHUD.get();
458        camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
459        camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
460        camera->setViewMatrix(osg::Matrix::identity());
461        camera->setViewport( _viewportOrigin[0], _viewportOrigin[1],
462                             _viewportSize[0], _viewportSize[1] );
463
464        camera->setProjectionMatrixAsOrtho(
465                _orthoOrigin[0], _orthoOrigin[0] + _orthoSize[0],
466                _orthoOrigin[1], _orthoOrigin[1] + _orthoSize[1],
467                -10, 10 );   
468
469        camera->setClearMask(GL_DEPTH_BUFFER_BIT);
470        camera->setRenderOrder(osg::Camera::POST_RENDER);
471    }
472
473    { // Add geode and drawable with BaseClass display
474        // create geode to contain hud drawables
475        osg::Geode* geode = new osg::Geode;
476        _cameraDebugHUD->addChild(geode);
477
478        // finally create and attach hud geometry
479        osg::Geometry* geometry = osg::createTexturedQuadGeometry
480            ( osg::Vec3(_hudOrigin[0],_hudOrigin[1],0),
481              osg::Vec3(_hudSize[0],0,0),
482              osg::Vec3(0,_hudSize[1],0) );
483   
484        osg::StateSet* stateset = _cameraDebugHUD->getOrCreateStateSet();
485        stateset->setTextureAttributeAndModes(0,_texture.get(),osg::StateAttribute::ON );
486        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
487//        stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
488        stateset->setAttributeAndModes
489            ( new osg::Depth( osg::Depth::ALWAYS, 0, 1, false ) );
490        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
491   
492        osg::Program* program = new osg::Program;
493        program->addShader( _depthColorFragmentShader.get() );
494        stateset->setAttribute( program );
495        stateset->addUniform( new osg::Uniform( "texture" , 0 ) );
496
497        geometry->setDrawCallback
498            ( new DrawableDrawWithDepthShadowComparisonOffCallback( _texture.get() ) );
499
500        geode->addDrawable( geometry );
501    }
502
503    { // Create transforms and geodes to manage polytope drawing
504        osg::StateSet * stateset = new osg::StateSet;
505        stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
506        stateset->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF);
507        stateset->setTextureMode(1, GL_TEXTURE_2D, osg::StateAttribute::OFF);
508        stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
509        stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
510        stateset->setAttribute( new osg::Program() );           
511        stateset->setAttributeAndModes
512            ( new osg::Depth( osg::Depth::LEQUAL, 0, 1, false ) );
513
514        for( int i = 0; i < 2; i++ ) {
515            _geode[i]->setStateSet( stateset );
516            _transform[i] = new osg::MatrixTransform;
517            _transform[i]->addChild( _geode[i].get() );
518            _transform[i]->setMatrix( osg::Matrix::identity() );
519            _transform[i]->setReferenceFrame( osg::MatrixTransform::ABSOLUTE_RF );
520        }
521
522        _transform[1]->setMatrix
523            ( osg::Matrix::translate( 1, 1, 0 ) *
524              osg::Matrix::scale( 0.5, 0.5, 1 ) *
525              osg::Matrix::scale( _hudSize[0], _hudSize[1], 1 ) *
526              osg::Matrix::translate( _hudOrigin[0], _hudOrigin[1], 0 ) );
527
528        _cameraDebugHUD->addChild( _transform[1].get() );
529    }
530}
531
532osg::Vec3d DebugShadowMap::ViewData::computeShadowTexelToPixelError
533     ( const osg::Matrix & mvpwView,
534       const osg::Matrix & mvpwShadow,
535       const osg::Vec3d & vWorld,
536       const osg::Vec3d & vDelta )
537{
538    osg::Vec3d vS0 = mvpwShadow * vWorld;
539    osg::Vec3d vS1 = mvpwShadow * ( vWorld + vDelta );
540
541    osg::Vec3d vV0 = mvpwView * vWorld;
542    osg::Vec3d vV1 = mvpwView * ( vWorld + vDelta );
543
544    osg::Vec3d dV = vV1 - vV0;
545    osg::Vec3d dS = vS1 - vS0;
546   
547    return osg::Vec3( dS[0] / dV[0], dS[1] / dV[1], dS[2] / dV[2] );
548}
549
550void DebugShadowMap::ViewData::displayShadowTexelToPixelErrors
551  ( const osg::Camera* viewCamera,
552    const osg::Camera* shadowCamera,
553    const ConvexPolyhedron* hull )
554{
555    osg::Matrix mvpwMain  =
556        viewCamera->getViewMatrix() *
557        viewCamera->getProjectionMatrix() *
558        viewCamera->getViewport()->computeWindowMatrix();
559
560    osg::Matrix mvpwShadow  =
561        shadowCamera->getViewMatrix() *
562        shadowCamera->getProjectionMatrix() *
563        shadowCamera->getViewport()->computeWindowMatrix();
564
565    osg::BoundingBox bb =
566        hull->computeBoundingBox( viewCamera->getViewMatrix() );
567
568    osg::Matrix m = viewCamera->getInverseViewMatrix();
569
570    osg::Vec3d vn = osg::Vec3d( 0, 0, bb._max[2] ) * m;
571    osg::Vec3d vf = osg::Vec3d( 0, 0, bb._min[2] ) * m;
572    osg::Vec3d vm = osg::Vec3d( 0, 0, ( bb._max[2] + bb._min[2] ) * 0.5 ) * m;
573
574    osg::Vec3d vne = computeShadowTexelToPixelError( mvpwMain, mvpwShadow, vn );
575    osg::Vec3d vfe = computeShadowTexelToPixelError( mvpwMain, mvpwShadow, vf );
576    osg::Vec3d vme = computeShadowTexelToPixelError( mvpwMain, mvpwShadow, vm );
577
578    std::cout << std::setprecision( 3 ) << " "
579        << "ne=(" << vne[0] << "," << vne[1] << "," << vne[2] << ")  "
580        << "fe=(" << vfe[0] << "," << vfe[1] << "," << vfe[2] << ")  "
581        << "me=(" << vme[0] << "," << vme[1] << "," << vme[2] << ")  " 
582        << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
583        << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
584        << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
585        << std::flush;
586}
Note: See TracBrowser for help on using the browser.