From Ravi Mathur, "OK I have been away for a looong time, but still occasionally watching from a distance, and saw the bug people have reported about the DepthPartitionNode not handling scaled models properly.
I believe this is now fixed ... I have attached the new DistanceAccumulator.cpp, along with a modified example file that uses a PositionAttitudeTransform to draw the Earth's orbit around the Sun."
This commit is contained in:
parent
38b02a26a9
commit
fddaaf0d00
@ -34,9 +34,13 @@ bool precedes(const DistanceAccumulator::DistancePair &a,
|
|||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Computes distance betwen a point and the viewpoint of a matrix */
|
/** Computes distance (in z direction) betwen a point and the viewer's eye,
|
||||||
|
given by a view matrix */
|
||||||
double distance(const osg::Vec3 &coord, const osg::Matrix& matrix)
|
double distance(const osg::Vec3 &coord, const osg::Matrix& matrix)
|
||||||
{
|
{
|
||||||
|
// Here we are taking only the z coordinate of the point transformed
|
||||||
|
// by the matrix, ie coord*matrix. The negative sign is because we
|
||||||
|
// want to consider into the screen as INCREASING distance.
|
||||||
return -( coord[0]*matrix(0,2) + coord[1]*matrix(1,2) +
|
return -( coord[0]*matrix(0,2) + coord[1]*matrix(1,2) +
|
||||||
coord[2]*matrix(2,2) + matrix(3,2) );
|
coord[2]*matrix(2,2) + matrix(3,2) );
|
||||||
}
|
}
|
||||||
@ -56,19 +60,19 @@ void CURRENT_CLASS::pushLocalFrustum()
|
|||||||
{
|
{
|
||||||
osg::Matrix& currMatrix = _viewMatrices.back();
|
osg::Matrix& currMatrix = _viewMatrices.back();
|
||||||
|
|
||||||
// Compute the frustum in local space
|
// Compute the frustum in local space
|
||||||
osg::Polytope localFrustum;
|
osg::Polytope localFrustum;
|
||||||
localFrustum.setToUnitFrustum(false, false);
|
localFrustum.setToUnitFrustum(false, false);
|
||||||
localFrustum.transformProvidingInverse(currMatrix*_projectionMatrices.back());
|
localFrustum.transformProvidingInverse(currMatrix*_projectionMatrices.back());
|
||||||
_localFrusta.push_back(localFrustum);
|
_localFrusta.push_back(localFrustum);
|
||||||
|
|
||||||
// Compute new bounding box corners
|
// Compute new bounding box corners
|
||||||
bbCornerPair corner;
|
bbCornerPair corner;
|
||||||
corner.second = (currMatrix(0,2)<=0?1:0) |
|
corner.second = (currMatrix(0,2)<=0?1:0) |
|
||||||
(currMatrix(1,2)<=0?2:0) |
|
(currMatrix(1,2)<=0?2:0) |
|
||||||
(currMatrix(2,2)<=0?4:0);
|
(currMatrix(2,2)<=0?4:0);
|
||||||
corner.first = (~corner.second)&7;
|
corner.first = (~corner.second)&7;
|
||||||
_bbCorners.push_back(corner);
|
_bbCorners.push_back(corner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CURRENT_CLASS::pushDistancePair(double zNear, double zFar)
|
void CURRENT_CLASS::pushDistancePair(double zNear, double zFar)
|
||||||
@ -99,19 +103,57 @@ bool CURRENT_CLASS::shouldContinueTraversal(osg::Node &node)
|
|||||||
// Allow traversal to continue if we haven't reached maximum depth.
|
// Allow traversal to continue if we haven't reached maximum depth.
|
||||||
bool keepTraversing = (_currentDepth < _maxDepth);
|
bool keepTraversing = (_currentDepth < _maxDepth);
|
||||||
|
|
||||||
const osg::BoundingSphere &bs = node.getBound();
|
osg::BoundingSphere bs = node.getBound();
|
||||||
double zNear = 0.0, zFar = 0.0;
|
double zNear = 0.0, zFar = 0.0;
|
||||||
|
|
||||||
// Make sure bounding sphere is valid and within viewing volume
|
// Make sure bounding sphere is valid
|
||||||
if(bs.valid())
|
if(bs.valid())
|
||||||
{
|
{
|
||||||
|
// Make sure bounding sphere is within the viewing volume
|
||||||
if(!_localFrusta.back().contains(bs)) keepTraversing = false;
|
if(!_localFrusta.back().contains(bs)) keepTraversing = false;
|
||||||
else
|
|
||||||
|
else // Compute near and far planes for this node
|
||||||
{
|
{
|
||||||
// Compute near and far planes for this node
|
// Since the view matrix could involve complex transformations,
|
||||||
zNear = distance(bs._center, _viewMatrices.back());
|
// we need to determine a new BoundingSphere that would encompass
|
||||||
zFar = zNear + bs._radius;
|
// the transformed BoundingSphere.
|
||||||
zNear -= bs._radius;
|
const osg::Matrix &l2w = _viewMatrices.back();
|
||||||
|
|
||||||
|
// Get the transformed x-axis of the BoundingSphere
|
||||||
|
osg::Vec3d newX = bs._center;
|
||||||
|
newX.x() += bs._radius; // Get X-edge of bounding sphere
|
||||||
|
newX = newX * l2w;
|
||||||
|
|
||||||
|
// Get the transformed y-axis of the BoundingSphere
|
||||||
|
osg::Vec3d newY = bs._center;
|
||||||
|
newY.y() += bs._radius; // Get Y-edge of bounding sphere
|
||||||
|
newY = newY * l2w;
|
||||||
|
|
||||||
|
// Get the transformed z-axis of the BoundingSphere
|
||||||
|
osg::Vec3d newZ = bs._center;
|
||||||
|
newZ.z() += bs._radius; // Get Z-edge of bounding sphere
|
||||||
|
newZ = newZ * l2w;
|
||||||
|
|
||||||
|
// Get the transformed center of the BoundingSphere
|
||||||
|
bs._center = bs._center * l2w;
|
||||||
|
|
||||||
|
// Compute lengths of transformed x, y, and z axes
|
||||||
|
double newXLen = (newX - bs._center).length();
|
||||||
|
double newYLen = (newY - bs._center).length();
|
||||||
|
double newZLen = (newZ - bs._center).length();
|
||||||
|
|
||||||
|
// The encompassing radius is the max of the transformed lengths
|
||||||
|
bs._radius = newXLen;
|
||||||
|
if(newYLen > bs._radius) bs._radius = newYLen;
|
||||||
|
if(newZLen > bs._radius) bs._radius = newZLen;
|
||||||
|
|
||||||
|
// Now we can compute the near & far planes, noting that for
|
||||||
|
// complex view transformations (ie. involving scales) the new
|
||||||
|
// BoundingSphere may be bigger than the original one.
|
||||||
|
// Note that the negative sign on the bounding sphere center is
|
||||||
|
// because we want distance to increase INTO the screen.
|
||||||
|
zNear = -bs._center.z() - bs._radius;
|
||||||
|
zFar = -bs._center.z() + bs._radius;
|
||||||
|
|
||||||
// If near/far ratio is big enough, then we don't need to keep
|
// If near/far ratio is big enough, then we don't need to keep
|
||||||
// traversing children of this node.
|
// traversing children of this node.
|
||||||
@ -130,9 +172,9 @@ void CURRENT_CLASS::apply(osg::Node &node)
|
|||||||
if(shouldContinueTraversal(node))
|
if(shouldContinueTraversal(node))
|
||||||
{
|
{
|
||||||
// Traverse this node
|
// Traverse this node
|
||||||
_currentDepth++;
|
++_currentDepth;
|
||||||
traverse(node);
|
traverse(node);
|
||||||
_currentDepth--;
|
--_currentDepth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,9 +187,9 @@ void CURRENT_CLASS::apply(osg::Projection &proj)
|
|||||||
pushLocalFrustum();
|
pushLocalFrustum();
|
||||||
|
|
||||||
// Traverse the group
|
// Traverse the group
|
||||||
_currentDepth++;
|
++_currentDepth;
|
||||||
traverse(proj);
|
traverse(proj);
|
||||||
_currentDepth--;
|
--_currentDepth;
|
||||||
|
|
||||||
// Reload original matrix and frustum
|
// Reload original matrix and frustum
|
||||||
_localFrusta.pop_back();
|
_localFrusta.pop_back();
|
||||||
@ -171,9 +213,9 @@ void CURRENT_CLASS::apply(osg::Transform &transform)
|
|||||||
pushLocalFrustum();
|
pushLocalFrustum();
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentDepth++;
|
++_currentDepth;
|
||||||
traverse(transform);
|
traverse(transform);
|
||||||
_currentDepth--;
|
--_currentDepth;
|
||||||
|
|
||||||
if(pushMatrix)
|
if(pushMatrix)
|
||||||
{
|
{
|
||||||
@ -195,7 +237,7 @@ void CURRENT_CLASS::apply(osg::Geode &geode)
|
|||||||
double zNear, zFar;
|
double zNear, zFar;
|
||||||
|
|
||||||
// Handle each drawable in this geode
|
// Handle each drawable in this geode
|
||||||
for(unsigned int i = 0; i < geode.getNumDrawables(); i++)
|
for(unsigned int i = 0; i < geode.getNumDrawables(); ++i)
|
||||||
{
|
{
|
||||||
drawable = geode.getDrawable(i);
|
drawable = geode.getDrawable(i);
|
||||||
|
|
||||||
@ -268,7 +310,7 @@ void CURRENT_CLASS::computeCameraPairs()
|
|||||||
// pairs (called combined pairs) will not overlap.
|
// pairs (called combined pairs) will not overlap.
|
||||||
PairList combinedPairs;
|
PairList combinedPairs;
|
||||||
DistancePair currPair = _distancePairs.front();
|
DistancePair currPair = _distancePairs.front();
|
||||||
for(i = _distancePairs.begin(); i != _distancePairs.end(); i++)
|
for(i = _distancePairs.begin(); i != _distancePairs.end(); ++i)
|
||||||
{
|
{
|
||||||
// Current distance pair does not overlap current combined pair, so
|
// Current distance pair does not overlap current combined pair, so
|
||||||
// save the current combined pair and start a new one.
|
// save the current combined pair and start a new one.
|
||||||
@ -290,7 +332,7 @@ void CURRENT_CLASS::computeCameraPairs()
|
|||||||
double currNearLimit, numSegs, new_ratio;
|
double currNearLimit, numSegs, new_ratio;
|
||||||
double ratio_invlog = 1.0/log(_nearFarRatio);
|
double ratio_invlog = 1.0/log(_nearFarRatio);
|
||||||
unsigned int temp;
|
unsigned int temp;
|
||||||
for(i = combinedPairs.begin(); i != combinedPairs.end(); i++)
|
for(i = combinedPairs.begin(); i != combinedPairs.end(); ++i)
|
||||||
{
|
{
|
||||||
currPair = *i; // Save current view segment
|
currPair = *i; // Save current view segment
|
||||||
|
|
||||||
@ -311,7 +353,7 @@ void CURRENT_CLASS::computeCameraPairs()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See if the closest view segment can absorb other combined pairs
|
// See if the closest view segment can absorb other combined pairs
|
||||||
for(j = i+1; j != combinedPairs.end(); j++)
|
for(j = i+1; j != combinedPairs.end(); ++j)
|
||||||
{
|
{
|
||||||
// No other distance pairs can be included
|
// No other distance pairs can be included
|
||||||
if(j->first < currNearLimit) break;
|
if(j->first < currNearLimit) break;
|
||||||
|
@ -38,34 +38,88 @@ osg::Node* createScene()
|
|||||||
// Create the Earth, in blue
|
// Create the Earth, in blue
|
||||||
osg::ShapeDrawable *earth_sd = new osg::ShapeDrawable;
|
osg::ShapeDrawable *earth_sd = new osg::ShapeDrawable;
|
||||||
osg::Sphere* earth_sphere = new osg::Sphere;
|
osg::Sphere* earth_sphere = new osg::Sphere;
|
||||||
|
earth_sphere->setName("EarthSphere");
|
||||||
earth_sphere->setRadius(r_earth);
|
earth_sphere->setRadius(r_earth);
|
||||||
earth_sd->setShape(earth_sphere);
|
earth_sd->setShape(earth_sphere);
|
||||||
earth_sd->setColor(osg::Vec4(0, 0, 1.0, 1.0));
|
earth_sd->setColor(osg::Vec4(0, 0, 1.0, 1.0));
|
||||||
|
|
||||||
osg::Geode* earth = new osg::Geode;
|
osg::Geode* earth_geode = new osg::Geode;
|
||||||
earth->setName("earth");
|
earth_geode->setName("EarthGeode");
|
||||||
earth->addDrawable(earth_sd);
|
earth_geode->addDrawable(earth_sd);
|
||||||
|
|
||||||
// Create the Sun, in yellow
|
// Create the Sun, in yellow
|
||||||
osg::ShapeDrawable *sun_sd = new osg::ShapeDrawable;
|
osg::ShapeDrawable *sun_sd = new osg::ShapeDrawable;
|
||||||
osg::Sphere* sun_sphere = new osg::Sphere;
|
osg::Sphere* sun_sphere = new osg::Sphere;
|
||||||
|
sun_sphere->setName("SunSphere");
|
||||||
sun_sphere->setRadius(r_sun);
|
sun_sphere->setRadius(r_sun);
|
||||||
sun_sd->setShape(sun_sphere);
|
sun_sd->setShape(sun_sphere);
|
||||||
sun_sd->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
|
sun_sd->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
|
||||||
|
|
||||||
osg::Geode* sun_geode = new osg::Geode;
|
osg::Geode* sun_geode = new osg::Geode;
|
||||||
sun_geode->setName("sun");
|
sun_geode->setName("SunGeode");
|
||||||
sun_geode->addDrawable(sun_sd);
|
sun_geode->addDrawable(sun_sd);
|
||||||
|
|
||||||
// Move the sun behind the earth
|
// Move the sun behind the earth
|
||||||
osg::PositionAttitudeTransform *pat = new osg::PositionAttitudeTransform;
|
osg::PositionAttitudeTransform *pat = new osg::PositionAttitudeTransform;
|
||||||
pat->setPosition(osg::Vec3d(0.0, AU, 0.0));
|
pat->setPosition(osg::Vec3d(0.0, AU, 0.0));
|
||||||
|
|
||||||
osg::Group* scene = new osg::Group;
|
|
||||||
scene->addChild(earth);
|
|
||||||
scene->addChild(pat);
|
|
||||||
pat->addChild(sun_geode);
|
pat->addChild(sun_geode);
|
||||||
|
|
||||||
|
osg::Geometry * unitCircle = new osg::Geometry();
|
||||||
|
{
|
||||||
|
osg::Vec4Array * colours = new osg::Vec4Array(1);
|
||||||
|
(*colours)[0] = osg::Vec4d(1.0,1.0,1.0,1.0);
|
||||||
|
unitCircle->setColorArray(colours);
|
||||||
|
unitCircle->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||||
|
const unsigned int n_points = 1024;
|
||||||
|
osg::Vec3Array * coords = new osg::Vec3Array(n_points);
|
||||||
|
const double dx = 2.0*M_PI/n_points;
|
||||||
|
double s,c;
|
||||||
|
for (unsigned int j=0; j<n_points; ++j) {
|
||||||
|
s = sin(dx*j);
|
||||||
|
c = cos(dx*j);
|
||||||
|
(*coords)[j].set(osg::Vec3d(c,s,0.0));
|
||||||
|
}
|
||||||
|
unitCircle->setVertexArray(coords);
|
||||||
|
unitCircle->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||||
|
unitCircle->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,n_points));
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Geometry *axes = new osg::Geometry;
|
||||||
|
{
|
||||||
|
osg::Vec4Array *colours = new osg::Vec4Array(1);
|
||||||
|
(*colours)[0] = osg::Vec4d(1.0,0.0,0.0,1.0);
|
||||||
|
axes->setColorArray(colours);
|
||||||
|
axes->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||||
|
osg::Vec3Array *coords = new osg::Vec3Array(6);
|
||||||
|
(*coords)[0].set(osg::Vec3d(0.0, 0.0, 0.0));
|
||||||
|
(*coords)[1].set(osg::Vec3d(0.5, 0.0, 0.0));
|
||||||
|
(*coords)[2].set(osg::Vec3d(0.0, 0.0, 0.0));
|
||||||
|
(*coords)[3].set(osg::Vec3d(0.0, 0.5, 0.0));
|
||||||
|
(*coords)[4].set(osg::Vec3d(0.0, 0.0, 0.0));
|
||||||
|
(*coords)[5].set(osg::Vec3d(0.0, 0.0, 0.5));
|
||||||
|
axes->setVertexArray(coords);
|
||||||
|
axes->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||||
|
axes->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,6));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Earth orbit
|
||||||
|
osg::Geode * earthOrbitGeode = new osg::Geode;
|
||||||
|
earthOrbitGeode->addDrawable(unitCircle);
|
||||||
|
earthOrbitGeode->addDrawable(axes);
|
||||||
|
earthOrbitGeode->setName("EarthOrbitGeode");
|
||||||
|
|
||||||
|
osg::PositionAttitudeTransform * earthOrbitPAT = new osg::PositionAttitudeTransform;
|
||||||
|
earthOrbitPAT->setScale(osg::Vec3d(AU,AU,AU));
|
||||||
|
earthOrbitPAT->setPosition(osg::Vec3d(0.0, AU, 0.0));
|
||||||
|
earthOrbitPAT->addChild(earthOrbitGeode);
|
||||||
|
earthOrbitPAT->setName("EarthOrbitPAT");
|
||||||
|
|
||||||
|
osg::Group* scene = new osg::Group;
|
||||||
|
scene->setName("SceneGroup");
|
||||||
|
scene->addChild(earth_geode);
|
||||||
|
scene->addChild(pat);
|
||||||
|
scene->addChild(earthOrbitPAT);
|
||||||
|
|
||||||
return scene;
|
return scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +156,7 @@ int main( int argc, char **argv )
|
|||||||
|
|
||||||
if (needToSetHomePosition)
|
if (needToSetHomePosition)
|
||||||
{
|
{
|
||||||
viewer.getCameraManipulator()->setHomePosition(osg::Vec3d(0.0,-5.0*r_earth,0.0),osg::Vec3d(0.0,0.0,0.0),osg::Vec3d(0.0,0.0,1.0));
|
viewer.getCameraManipulator()->setHomePosition(osg::Vec3d(0.0,-5.0*r_earth,0.0),osg::Vec3d(0.0,0.0,0.0),osg::Vec3d(0.0,0.0,1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// depth partion node is only supports single window/single threaded at present.
|
// depth partion node is only supports single window/single threaded at present.
|
||||||
|
Loading…
Reference in New Issue
Block a user