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