HI Alan,

The OSG strives to be flexible, and probably the most flexible scene
graph on the planet, but there are just so many different ways people
can set up scene graphs and use that even it is even it will have
problems keeping up.  Flexibility in one area sometimes has to balance
flexibility in others - for instance if you drop multi-thread,
multiple cameras, multiple window support then you make more
assumptions and provide more flexibility in state as it is no longer
potentially multivalued, but of course this blows out the water usage
for many users and limits it.

As for access to the projection matrix once its been modified by the
clamping of the projection matrix.  The projection matrix is managed
as a RefMatrix so potentially one could take a references to this
matrix, and then later query it when you need to. Unfortunately
osg::Uniform is set up to take a copy of a Matrix rather than a
reference to a RefMatrix, if it did take a reference then you would be
able to just assign the projection matrix and reuse that.  Perhaps
this generalization could be considered for the future, or perhaps
osg::Uniform could be extended to copy and matrix of take a reference
to a RefMatrix.

Robert.

On Dec 7, 2007 9:00 PM, Alan Purvis <[EMAIL PROTECTED]> wrote:
> Hi Robert,
>
> Thanks to this advice I finally appear to have solved my problem! I
> used my cull callback to highjack the matrix clamping implementation
> callback of all cull visitors passing through the camera node. This
> isn't thread safe, and undoes the flexibility of making the clamp
> function overridable with a callback, but works for my needs. I've
> pasted the code at the bottom of this email incase the code should
> prove useful to anyone else with similar problems.
>
> I know it might seem like a selfish thing to say and OSG's design
> shouldn't be driven by the needs of individual users and programs,
> but with the advent of shaders and freedom from the fixed pipeline
> rendering, getting "program-side" access to the actual OpenGL state
> used to render a scene is becoming more and important. Back when OSG
> was strictly fixed function it didn't really matter if OSG was
> sliding the culling planes around the place to improve visual
> quality, nobody needed to know it was going on and it produced nicer
> images with less z-fighting. But now that OpenGL and OSG has given
> programmers the freedom to redefine parts of the pipeline, knowing
> what "hidden changes" OSG is making to the OpenGL state behind the
> scenes is becoming more important I think.
>
> In this program of mine for example I need to reverse the normalised
> z-buffer values stored in a depth texture to world space coordinates.
> With the projection matrix used to generate the image, this is
> trivial. But when OSG changes the matrix used, the values I back-
> project become skewed. Does it make sense to provide an additional
> callback or something in the CullVisitor class to provide access to
> this matrix once it is computed? It seems like this kind of problem
> will only become more common in the future with the proliferation of
> RTT and all the rest of it.
>
> Thanks,
> Alan.
>
> class WriteProjectionMatrixToUniformCallback : public osg::NodeCallback
> {
>         private:
>         struct ClampProjectionMatrixCallback : public
> osg::CullSettings::ClampProjectionMatrixCallback
>         {
>                 private:
>                 osg::ref_ptr<osg::Uniform> _uniform;
>
>                 template<class matrix_type> bool clampprojectionmatriximpl
> (matrix_type &PROJECTION, double &ZNEAR, double &ZFAR) const
>                 {
>                         double epsilon = 1e-6;
>                         double nearfarratio = 0.0005;
>
>                         bool valid = true;
>                         if(ZFAR < ZNEAR -epsilon)
>                         {
>                                 osg::notify(osg::INFO) << 
> "_clampProjectionMatrix not applied,
> invalid depth range, ZNEAR = " << ZNEAR <<"  ZFAR = "<< ZFAR <<
> std::endl;
>                                 valid = false;
>                         }
>                         else
>                         {
>                                 if(ZFAR < ZNEAR +epsilon)
>                                 {
>                                         double average = (ZNEAR +ZFAR) *0.5;
>                                         ZNEAR = average -epsilon;
>                                         ZFAR = average +epsilon;
>                                 }
>
>                                 if(fabs(PROJECTION(0, 3)) < epsilon && 
> fabs(PROJECTION(1, 3)) <
> epsilon && fabs(PROJECTION(2, 3)) < epsilon)
>                                 {
>                                         double deltaspan = (ZFAR -ZNEAR) 
> *0.02;
>                                         if(deltaspan < 1.0) deltaspan = 1.0;
>                                         double desiredznear = ZNEAR 
> -deltaspan;
>                                         double desiredzfar = ZFAR +deltaspan;
>
>                                         ZNEAR = desiredznear;
>                                         ZFAR = desiredzfar;
>
>                                         PROJECTION(2, 2) =- 2.0f 
> /(desiredzfar -desiredznear);
>                                         PROJECTION(3, 2) =- (desiredzfar 
> +desiredznear) /(desiredzfar -
> desiredznear);
>                                 }
>                                 else
>                                 {
>                                         double zpushratio = 1.02;
>                                         double zpullratio = 0.98;
>
>                                         double desiredznear = ZNEAR 
> *zpullratio;
>                                         double desiredzfar = ZFAR *zpushratio;
>
>                                         double minnearplane = ZFAR 
> *nearfarratio;
>                                         if(desiredznear < minnearplane) 
> desiredznear = minnearplane;
>
>                                         ZNEAR = desiredznear;
>                                         ZFAR = desiredzfar;
>
>                                         double transnearplane = 
> (-desiredznear *PROJECTION(2, 2)
> +PROJECTION(3, 2)) /(-desiredznear *PROJECTION(2, 3) +PROJECTION(3, 3));
>                                         double transfarplane = (-desiredzfar 
> *PROJECTION(2, 2)
> +PROJECTION(3, 2)) /(-desiredzfar *PROJECTION(2, 3) +PROJECTION(3, 3));
>
>                                         double ratio = fabs(2.0 
> /(transnearplane -transfarplane));
>                                         double center = -(transnearplane 
> +transfarplane) /2.0;
>
>                                         PROJECTION.postMult(osg::Matrix(1.0f, 
> 0.0f, 0.0f, 0.0f,
>                                                                               
>                                                                               
>             0.0f, 1.0f, 0.0f, 0.0f,
>                                                                               
>                                                                               
>             0.0f, 0.0f, ratio, 0.0f,
>                                                                               
>                                                                               
>             0.0f, 0.0f, center *ratio, 1.0f));
>                                 }
>                         }
>
>                         if(_uniform != NULL) _uniform->set(PROJECTION);
>
>                         /*
>                         float n = (PROJECTION(3, 2) +PROJECTION(3, 3)) 
> /(PROJECTION(2, 2)
> +PROJECTION(2, 3));
>                         float f = (PROJECTION(3, 3) -PROJECTION(3, 2)) 
> /(PROJECTION(2, 3) -
> PROJECTION(2, 2));
>
>                         std::cout << "n = " << n << ", f = " << f << "\n";
>                         */
>
>                         return valid;
>                 }
>
>                 public:
>                 ClampProjectionMatrixCallback(osg::ref_ptr<osg::Uniform> 
> UNIFORM)
> { _uniform = UNIFORM; }
>                 virtual ~ClampProjectionMatrixCallback(void) {}
>
>                 virtual bool clampProjectionMatrixImplementation(osg::Matrixf
> &PROJECTION, double &ZNEAR, double &ZFAR) const
>                 {
>                         return clampprojectionmatriximpl(PROJECTION, ZNEAR, 
> ZFAR);
>                 }
>                 virtual bool clampProjectionMatrixImplementation(osg::Matrixd
> &PROJECTION, double &ZNEAR, double &ZFAR) const
>                 {
>                         return clampprojectionmatriximpl(PROJECTION, ZNEAR, 
> ZFAR);
>                 }
>         };
>
>         static osg::ref_ptr<ClampProjectionMatrixCallback> _cpmc;
>
>         public:
>         WriteProjectionMatrixToUniformCallback(osg::ref_ptr<osg::Uniform>
> UNIFORM) { if(_cpmc == NULL) _cpmc = new ClampProjectionMatrixCallback
> (UNIFORM); }
>         virtual ~WriteProjectionMatrixToUniformCallback(void) {}
>
>         virtual void operator()(osg::Node* NODE, osg::NodeVisitor* NV)
>         {
>                 NodeCallback::traverse(NODE, NV);
>
>                 osgUtil::CullVisitor *cv = 
> dynamic_cast<osgUtil::CullVisitor*>(NV);
>                 if(cv == NULL) return;
>
>                 cv->setClampProjectionMatrixCallback(_cpmc.get());
>         }
> };
>
> osg::ref_ptr<WriteProjectionMatrixToUniformCallback::ClampProjectionMatr
> ixCallback> WriteProjectionMatrixToUniformCallback::_cpmc = NULL;
>
>
> On 7 Dec 2007, at 15:58, Robert Osfield wrote:
>
>
> > On Dec 7, 2007 3:34 PM, Alan Purvis <[EMAIL PROTECTED]> wrote:
> >> Does anyone have an idea what I might be doing wrong? Am I right to
> >> call traverse before I deference the pointer to the matrix? Am I
> >> getting a pointer to the right matrix?
> >
> > Reading through your you email the reason pinged into my head.  Your
> > not doing anything wrong in terms of accessing the projection matrix,
> > the problem lies in the fact that the cull visitor does the clamping
> > of the projection matrix once its traversed the whole subgraph below a
> > camera - which will be after your cull callback returns.  The actual
> > clamping is dispatched within the CullVisitor;:popProjectionMatrix()
> > method.
> >
> > Looking at your code you are setting a uniform with the projection
> > matrix.   Perhaps you can dispense with this completely as OpenGL
> > itself has the projection matrix as a built in uniform.
> >
> > Robert.
>
> > _______________________________________________
> > osg-users mailing list
> > [email protected]
> > http://lists.openscenegraph.org/listinfo.cgi/osg-users-
> > openscenegraph.org
> >
>
> _______________________________________________
> osg-users mailing list
> [email protected]
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to