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;
|
||||
}
|
||||
|
||||
/** 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)
|
||||
{
|
||||
// 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) +
|
||||
coord[2]*matrix(2,2) + matrix(3,2) );
|
||||
}
|
||||
@ -56,19 +60,19 @@ void CURRENT_CLASS::pushLocalFrustum()
|
||||
{
|
||||
osg::Matrix& currMatrix = _viewMatrices.back();
|
||||
|
||||
// Compute the frustum in local space
|
||||
osg::Polytope localFrustum;
|
||||
localFrustum.setToUnitFrustum(false, false);
|
||||
localFrustum.transformProvidingInverse(currMatrix*_projectionMatrices.back());
|
||||
_localFrusta.push_back(localFrustum);
|
||||
// Compute the frustum in local space
|
||||
osg::Polytope localFrustum;
|
||||
localFrustum.setToUnitFrustum(false, false);
|
||||
localFrustum.transformProvidingInverse(currMatrix*_projectionMatrices.back());
|
||||
_localFrusta.push_back(localFrustum);
|
||||
|
||||
// Compute new bounding box corners
|
||||
bbCornerPair corner;
|
||||
corner.second = (currMatrix(0,2)<=0?1:0) |
|
||||
(currMatrix(1,2)<=0?2:0) |
|
||||
(currMatrix(2,2)<=0?4:0);
|
||||
corner.first = (~corner.second)&7;
|
||||
_bbCorners.push_back(corner);
|
||||
// Compute new bounding box corners
|
||||
bbCornerPair corner;
|
||||
corner.second = (currMatrix(0,2)<=0?1:0) |
|
||||
(currMatrix(1,2)<=0?2:0) |
|
||||
(currMatrix(2,2)<=0?4:0);
|
||||
corner.first = (~corner.second)&7;
|
||||
_bbCorners.push_back(corner);
|
||||
}
|
||||
|
||||
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.
|
||||
bool keepTraversing = (_currentDepth < _maxDepth);
|
||||
|
||||
const osg::BoundingSphere &bs = node.getBound();
|
||||
osg::BoundingSphere bs = node.getBound();
|
||||
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())
|
||||
{
|
||||
// Make sure bounding sphere is within the viewing volume
|
||||
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
|
||||
zNear = distance(bs._center, _viewMatrices.back());
|
||||
zFar = zNear + bs._radius;
|
||||
zNear -= bs._radius;
|
||||
// Since the view matrix could involve complex transformations,
|
||||
// we need to determine a new BoundingSphere that would encompass
|
||||
// the transformed BoundingSphere.
|
||||
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
|
||||
// traversing children of this node.
|
||||
@ -130,9 +172,9 @@ void CURRENT_CLASS::apply(osg::Node &node)
|
||||
if(shouldContinueTraversal(node))
|
||||
{
|
||||
// Traverse this node
|
||||
_currentDepth++;
|
||||
++_currentDepth;
|
||||
traverse(node);
|
||||
_currentDepth--;
|
||||
--_currentDepth;
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,9 +187,9 @@ void CURRENT_CLASS::apply(osg::Projection &proj)
|
||||
pushLocalFrustum();
|
||||
|
||||
// Traverse the group
|
||||
_currentDepth++;
|
||||
++_currentDepth;
|
||||
traverse(proj);
|
||||
_currentDepth--;
|
||||
--_currentDepth;
|
||||
|
||||
// Reload original matrix and frustum
|
||||
_localFrusta.pop_back();
|
||||
@ -171,9 +213,9 @@ void CURRENT_CLASS::apply(osg::Transform &transform)
|
||||
pushLocalFrustum();
|
||||
}
|
||||
|
||||
_currentDepth++;
|
||||
++_currentDepth;
|
||||
traverse(transform);
|
||||
_currentDepth--;
|
||||
--_currentDepth;
|
||||
|
||||
if(pushMatrix)
|
||||
{
|
||||
@ -195,7 +237,7 @@ void CURRENT_CLASS::apply(osg::Geode &geode)
|
||||
double zNear, zFar;
|
||||
|
||||
// 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);
|
||||
|
||||
@ -268,7 +310,7 @@ void CURRENT_CLASS::computeCameraPairs()
|
||||
// pairs (called combined pairs) will not overlap.
|
||||
PairList combinedPairs;
|
||||
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
|
||||
// save the current combined pair and start a new one.
|
||||
@ -290,7 +332,7 @@ void CURRENT_CLASS::computeCameraPairs()
|
||||
double currNearLimit, numSegs, new_ratio;
|
||||
double ratio_invlog = 1.0/log(_nearFarRatio);
|
||||
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
|
||||
|
||||
@ -311,7 +353,7 @@ void CURRENT_CLASS::computeCameraPairs()
|
||||
}
|
||||
|
||||
// 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
|
||||
if(j->first < currNearLimit) break;
|
||||
|
@ -38,34 +38,88 @@ osg::Node* createScene()
|
||||
// Create the Earth, in blue
|
||||
osg::ShapeDrawable *earth_sd = new osg::ShapeDrawable;
|
||||
osg::Sphere* earth_sphere = new osg::Sphere;
|
||||
earth_sphere->setName("EarthSphere");
|
||||
earth_sphere->setRadius(r_earth);
|
||||
earth_sd->setShape(earth_sphere);
|
||||
earth_sd->setColor(osg::Vec4(0, 0, 1.0, 1.0));
|
||||
|
||||
osg::Geode* earth = new osg::Geode;
|
||||
earth->setName("earth");
|
||||
earth->addDrawable(earth_sd);
|
||||
|
||||
osg::Geode* earth_geode = new osg::Geode;
|
||||
earth_geode->setName("EarthGeode");
|
||||
earth_geode->addDrawable(earth_sd);
|
||||
|
||||
// Create the Sun, in yellow
|
||||
osg::ShapeDrawable *sun_sd = new osg::ShapeDrawable;
|
||||
osg::Sphere* sun_sphere = new osg::Sphere;
|
||||
sun_sphere->setName("SunSphere");
|
||||
sun_sphere->setRadius(r_sun);
|
||||
sun_sd->setShape(sun_sphere);
|
||||
sun_sd->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
|
||||
|
||||
osg::Geode* sun_geode = new osg::Geode;
|
||||
sun_geode->setName("sun");
|
||||
sun_geode->setName("SunGeode");
|
||||
sun_geode->addDrawable(sun_sd);
|
||||
|
||||
// Move the sun behind the earth
|
||||
osg::PositionAttitudeTransform *pat = new osg::PositionAttitudeTransform;
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -102,7 +156,7 @@ int main( int argc, char **argv )
|
||||
|
||||
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.
|
||||
|
Loading…
Reference in New Issue
Block a user