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

Revision 13041, 24.5 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

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