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:
parent
67e8e0b287
commit
745834c329
@ -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;
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user