Added triangle index functor to src/osgUtil/SphereSegment.cpp for computing

the intersection between an indivual geometry and the sphere segment.

Converted the terrain in osgspheresegment to be an osg::Geometry based
drawable rather than a osg::ShapeDrawable/osg::HeightField one to make it
more practicle to use as a test for the new SphereSegment intersection code.
This commit is contained in:
Robert Osfield 2005-09-09 11:13:40 +00:00
parent 67e8e0b287
commit 745834c329
3 changed files with 199 additions and 27 deletions

View File

@ -8,6 +8,8 @@
#include <osg/MatrixTransform>
#include <osg/Geometry>
#include <osgUtil/SmoothingVisitor>
#include <osgDB/ReadFile>
#include <osgText/Text>
@ -233,24 +235,84 @@ void build_world(osg::Group *root)
terrainGeode->setStateSet( stateset );
float size = 1000; // 10km;
float scale = size/39.0f; // 10km;
float z_scale = scale*3.0f;
osg::HeightField* grid = new osg::HeightField;
grid->allocate(38,39);
grid->setXInterval(scale);
grid->setYInterval(scale);
for(unsigned int r=0;r<39;++r)
{
for(unsigned int c=0;c<38;++c)
{
grid->setHeight(c,r,z_scale*vertex[r+c*39][2]);
}
}
terrainGeode->addDrawable(new osg::ShapeDrawable(grid));
{
unsigned int numColumns = 38;
unsigned int numRows = 39;
unsigned int r, c;
osg::Vec3 origin(0.0f,0.0f,0.0f);
osg::Vec3 size(1000.0f,1000.0f,250.0f);
osg::Geometry* geometry = new osg::Geometry;
osg::Vec3Array& v = *(new osg::Vec3Array(numColumns*numRows));
osg::Vec2Array& tc = *(new osg::Vec2Array(numColumns*numRows));
osg::Vec4ubArray& color = *(new osg::Vec4ubArray(1));
color[0].set(255,255,255,255);
float rowCoordDelta = size.y()/(float)(numRows-1);
float columnCoordDelta = size.x()/(float)(numColumns-1);
float rowTexDelta = 1.0f/(float)(numRows-1);
float columnTexDelta = 1.0f/(float)(numColumns-1);
// compute z range of z values of grid data so we can scale it.
float min_z = FLT_MAX;
float max_z = -FLT_MAX;
for(r=0;r<numRows;++r)
{
for(c=0;c<numColumns;++c)
{
min_z = osg::minimum(min_z,vertex[r+c*numRows][2]);
max_z = osg::maximum(max_z,vertex[r+c*numRows][2]);
}
}
float scale_z = size.z()/(max_z-min_z);
osg::Vec3 pos = origin;
osg::Vec2 tex(0.0f,0.0f);
int vi=0;
for(r=0;r<numRows;++r)
{
pos.x() = origin.x();
tex.x() = 0.0f;
for(c=0;c<numColumns;++c)
{
v[vi].set(pos.x(),pos.y(),pos.z()+(vertex[r+c*numRows][2]-min_z)*scale_z);
tc[vi] = tex;
pos.x()+=columnCoordDelta;
tex.x()+=columnTexDelta;
++vi;
}
pos.y() += rowCoordDelta;
tex.y() += rowTexDelta;
}
geometry->setVertexArray(&v);
geometry->setTexCoordArray(0, &tc);
geometry->setColorArray(&color);
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
for(r=0;r<numRows-1;++r)
{
osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_QUAD_STRIP,2*numColumns));
geometry->addPrimitiveSet(&drawElements);
int ei=0;
for(c=0;c<numColumns;++c)
{
drawElements[ei++] = (r+1)*numColumns+c;
drawElements[ei++] = (r)*numColumns+c;
}
}
osgUtil::SmoothingVisitor smoother;
smoother.smooth(*geometry);
terrainGeode->addDrawable(geometry);
}
}
@ -272,7 +334,7 @@ void build_world(osg::Group *root)
root->addChild(ss.get());
}
osgSim::SphereSegment::LineList lines = ss->computeIntersection(terrainGeode.get(), osg::Matrixd::identity());
osgSim::SphereSegment::LineList lines = ss->computeIntersection(osg::Matrixd::identity(), terrainGeode.get());
if (!lines.empty())
{
osg::notify(osg::NOTICE)<<"We've found intersections!!!!"<<std::endl;

View File

@ -231,8 +231,11 @@ public:
/** A list of vertex arrays representing a list of lines.*/
typedef std::vector< osg::ref_ptr<osg::Vec3Array> > LineList;
/** Compute the interesection lines between specified geometry and this sphere segment.*/
LineList computeIntersection(osg::Node* subgraph, const osg::Matrixd& transform);
/** Compute the interesection lines between subgraph and this sphere segment.*/
LineList computeIntersection(const osg::Matrixd& matrix, osg::Node* subgraph);
/** Compute the interesection lines between specified drawable and this sphere segment.*/
LineList computeIntersection(const osg::Matrixd& matrix, osg::Drawable* drawable);
private:

View File

@ -1,8 +1,24 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osgSim/SphereSegment>
#include <osg/Notify>
#include <osg/CullFace>
#include <osg/LineWidth>
#include <osg/Transform>
#include <osg/Geometry>
#include <osg/TriangleIndexFunctor>
#include <osg/io_utils>
#include <algorithm>
@ -1057,10 +1073,9 @@ class PolytopeVisitor : public osg::NodeVisitor
};
SphereSegment::LineList SphereSegment::computeIntersection(osg::Node* subgraph, const osg::Matrixd& transform)
SphereSegment::LineList SphereSegment::computeIntersection(const osg::Matrixd& transform, osg::Node* subgraph)
{
osg::notify(osg::NOTICE)<<"Creating line intersection between sphere segment and subgraph."<<std::endl;
SphereSegment::LineList lines;
osg::BoundingBox bb = getBoundingBox();
@ -1081,11 +1096,103 @@ SphereSegment::LineList SphereSegment::computeIntersection(osg::Node* subgraph,
if (polytopeVisitor.getHits().empty())
{
osg::notify(osg::NOTICE)<<"No hits found."<<std::endl;
}
else
{
osg::notify(osg::NOTICE)<<"Hits found. "<<polytopeVisitor.getHits().size()<<std::endl;
return LineList();
}
return lines;
// create a LineList to store all the compute line segments
LineList all_lines;
// compute the line intersections with each of the hit drawables
osg::notify(osg::NOTICE)<<"Hits found. "<<polytopeVisitor.getHits().size()<<std::endl;
PolytopeVisitor::HitList& hits = polytopeVisitor.getHits();
for(PolytopeVisitor::HitList::iterator itr = hits.begin();
itr != hits.end();
++itr)
{
SphereSegment::LineList lines = computeIntersection(itr->_matrix, itr->_drawable.get());
all_lines.insert(all_lines.end(), lines.begin(), lines.end());
}
// join all the lines that have ends that are close together..
return all_lines;
}
struct TriangleIntersectOperator
{
TriangleIntersectOperator():
_radius(-1.0f),
_azMin(0.0f),
_azMax(0.0f),
_elevMin(0.0f),
_elevMax(0.0f),
_numOutside(0),
_numInside(0),
_numIntersecting(0) {}
typedef osg::ref_ptr<osg::Vec3Array> PositionArray;
typedef std::vector<int> RegionArray;
PositionArray _positions;
RegionArray _regions;
float _radius;
float _azMin, _azMax, _elevMin, _elevMax;
unsigned int _numOutside;
unsigned int _numInside;
unsigned int _numIntersecting;
inline void operator()(unsigned int p1, unsigned int p2, unsigned int p3)
{
// reject if outside.
if (_regions[p1]==1 && _regions[p2]==1 && _regions[p3]==1)
{
++_numOutside;
return;
}
if (_regions[p1]==-1 && _regions[p2]==-1 && _regions[p3]==-1)
{
++_numInside;
return;
}
++_numIntersecting;
}
};
SphereSegment::LineList SphereSegment::computeIntersection(const osg::Matrixd& transform, osg::Drawable* drawable)
{
// cast to Geometry, return empty handed if Drawable not a Geometry.
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(drawable);
if (!geometry) return LineList();
// get vertices from geometry, return empty handed if a Vec3Array not present.
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
if (!vertices) return LineList();
typedef osg::TriangleIndexFunctor<TriangleIntersectOperator> TriangleIntersectFunctor;
TriangleIntersectFunctor tif;
tif._radius = _radius;
tif._azMin = _azMin;
tif._azMax = _azMax;
tif._elevMin = _elevMin;
tif._elevMax = _elevMax;
tif._positions = vertices;
tif._regions.resize(vertices->size(), 1);
// traverse the triangles in the Geometry dedicating intersections
geometry->accept(tif);
osg::notify(osg::NOTICE)<<"_numOutside = "<<tif._numOutside<<std::endl;
osg::notify(osg::NOTICE)<<"_numInside = "<<tif._numInside<<std::endl;
osg::notify(osg::NOTICE)<<"_numIntersecting = "<<tif._numIntersecting<<std::endl;
return LineList();
}