Initial commit of the bounding volume tree implementation.

The aim is to prove a better collion model in plenty ways.

Added Files:
 	.cvsignore BVHBoundingBoxVisitor.hxx
	BVHDebugCollectVisitor.hxx BVHGroup.cxx BVHGroup.hxx
	BVHLineGeometry.cxx BVHLineGeometry.hxx
	BVHLineSegmentVisitor.cxx BVHLineSegmentVisitor.hxx
	BVHMotionTransform.cxx BVHMotionTransform.hxx BVHNode.cxx
	BVHNode.hxx BVHStaticBinary.cxx BVHStaticBinary.hxx
	BVHStaticData.hxx BVHStaticGeometry.cxx BVHStaticGeometry.hxx
	BVHStaticGeometryBuilder.hxx BVHStaticLeaf.cxx
	BVHStaticLeaf.hxx BVHStaticNode.cxx BVHStaticNode.hxx
	BVHStaticTriangle.cxx BVHStaticTriangle.hxx
 	BVHSubTreeCollector.cxx BVHSubTreeCollector.hxx
	BVHTransform.cxx BVHTransform.hxx BVHVisitor.hxx Makefile.am
	bvhtest.cxx
This commit is contained in:
frohlich 2009-03-01 12:35:49 +00:00 committed by Tim Moore
parent e417903c23
commit 8545b6ce6b
32 changed files with 2658 additions and 0 deletions

View File

@ -0,0 +1,3 @@
.deps
Makefile
Makefile.in

View File

@ -0,0 +1,83 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHBoundingBoxVisitor_hxx
#define BVHBoundingBoxVisitor_hxx
#include <simgear/math/SGGeometry.hxx>
#include "BVHVisitor.hxx"
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
#include "BVHTransform.hxx"
#include "BVHMotionTransform.hxx"
#include "BVHLineGeometry.hxx"
#include "BVHStaticData.hxx"
#include "BVHStaticNode.hxx"
#include "BVHStaticLeaf.hxx"
#include "BVHStaticTriangle.hxx"
#include "BVHStaticBinary.hxx"
#include "BVHStaticGeometry.hxx"
namespace simgear {
class BVHBoundingBoxVisitor : public BVHVisitor {
public:
virtual ~BVHBoundingBoxVisitor() {}
void clear()
{ _box.clear(); }
virtual void apply(BVHGroup& node)
{ expandBy(node.getBoundingSphere()); }
virtual void apply(BVHTransform& node)
{ expandBy(node.getBoundingSphere()); }
virtual void apply(BVHMotionTransform& node)
{ expandBy(node.getBoundingSphere()); }
virtual void apply(BVHLineGeometry& node)
{ expandBy(node.getBoundingSphere()); }
virtual void apply(BVHStaticGeometry& node)
{ expandBy(node.getBoundingSphere()); }
virtual void apply(const BVHStaticBinary& node, const BVHStaticData& data)
{ expandBy(node.getBoundingBox()); }
virtual void apply(const BVHStaticLeaf& node, const BVHStaticData& data)
{ expandBy(node.computeBoundingBox(data)); }
virtual void apply(const BVHStaticTriangle& node, const BVHStaticData& data)
{ expandBy(node.computeBoundingBox(data)); }
const SGBoxf& getBox() const
{ return _box; }
private:
void expandBy(const SGSphered& sphere)
{
SGVec3f v0(sphere.getCenter() - sphere.getRadius()*SGVec3d(1, 1, 1));
SGVec3f v1(sphere.getCenter() + sphere.getRadius()*SGVec3d(1, 1, 1));
_box.expandBy(SGBoxf(v0, v1));
}
void expandBy(const SGBoxf& box)
{ _box.expandBy(box); }
SGBoxf _box;
};
}
#endif

View File

@ -0,0 +1,222 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHDebugCollectVisitor_hxx
#define BVHDebugCollectVisitor_hxx
#include <osg/ref_ptr>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/PolygonOffset>
#include <osg/PrimitiveSet>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/ShapeDrawable>
#include <osg/Shape>
#include <osg/Depth>
#include <osg/BlendFunc>
#include <osg/StateSet>
#include <simgear/math/SGGeometry.hxx>
#include "BVHVisitor.hxx"
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
#include "BVHTransform.hxx"
#include "BVHMotionTransform.hxx"
#include "BVHStaticGeometry.hxx"
#include "BVHStaticData.hxx"
#include "BVHStaticNode.hxx"
#include "BVHStaticLeaf.hxx"
#include "BVHStaticTriangle.hxx"
#include "BVHStaticBinary.hxx"
#include "BVHBoundingBoxVisitor.hxx"
namespace simgear {
class BVHNode;
class BVHStaticNode;
class BVHDebugCollectVisitor : public BVHVisitor {
public:
BVHDebugCollectVisitor(unsigned level = ~0u) :
_group(new osg::Group),
_level(level),
_currentLevel(0)
{
osg::StateSet* stateSet = _group->getOrCreateStateSet();
stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateSet->setAttribute(new osg::Depth(osg::Depth::LESS, 0, 1, false));
osg::BlendFunc *blendFunc;
blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA,
osg::BlendFunc::DST_ALPHA);
stateSet->setAttributeAndModes(blendFunc);
osg::PolygonOffset* polygonOffset = new osg::PolygonOffset(-1, -1);
stateSet->setAttributeAndModes(polygonOffset);
}
virtual ~BVHDebugCollectVisitor()
{ }
virtual void apply(BVHGroup& node)
{
addNodeSphere(node);
++_currentLevel;
node.traverse(*this);
--_currentLevel;
}
virtual void apply(BVHTransform& node)
{
addNodeSphere(node);
osg::ref_ptr<osg::Group> oldGroup = _group;
osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
transform->setMatrix(osg::Matrix(node.getToWorldTransform().data()));
_group = transform;
++_currentLevel;
node.traverse(*this);
--_currentLevel;
_group = oldGroup;
if (transform->getNumChildren())
_group->addChild(transform.get());
}
virtual void apply(BVHMotionTransform& node)
{
addNodeSphere(node);
osg::ref_ptr<osg::Group> oldGroup = _group;
osg::ref_ptr<osg::PositionAttitudeTransform> transform;
transform = new osg::PositionAttitudeTransform;
double tt = node.getReferenceTime() - node.getEndTime();
tt = 100*tt;
tt += node.getReferenceTime();
// transform->setPosition(node.getPosition(node.getEndTime()).osg());
transform->setPosition(node.getPosition().osg());
transform->setAttitude(inverse(node.getOrientation(tt)).osg());
// transform->setPosition(node.getPosition().osg());
// transform->setAttitude(inverse(node.getOrientation()).osg());
_group = transform;
++_currentLevel;
node.traverse(*this);
--_currentLevel;
_group = oldGroup;
if (transform->getNumChildren())
_group->addChild(transform.get());
}
virtual void apply(BVHLineGeometry&)
{
}
virtual void apply(BVHStaticGeometry& node)
{
addNodeSphere(node);
++_currentLevel;
node.traverse(*this);
--_currentLevel;
}
virtual void apply(const BVHStaticBinary& node, const BVHStaticData& data)
{
addNodeBox(node, data);
++_currentLevel;
node.traverse(*this, data);
--_currentLevel;
}
virtual void apply(const BVHStaticLeaf& node, const BVHStaticData& data)
{
addNodeBox(node, data);
}
virtual void apply(const BVHStaticTriangle& node, const BVHStaticData& data)
{
addNodeBox(node, data);
addTriangle(node.getTriangle(data), osg::Vec4(0.5, 0, 0.5, 0.2));
}
osg::Node* getNode() const { return _group.get(); }
static unsigned allLevels() { return ~0u; }
static unsigned triangles() { return ~0u - 1; }
private:
void addTriangle(const SGTrianglef& triangle, const osg::Vec4& color)
{
if (_level != triangles())
return;
osg::Geometry* geometry = new osg::Geometry;
osg::Vec3Array* vertices = new osg::Vec3Array;
vertices->push_back(triangle.getVertex(0).osg());
vertices->push_back(triangle.getVertex(1).osg());
vertices->push_back(triangle.getVertex(2).osg());
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(color);
geometry->setVertexArray(vertices);
geometry->setColorArray(colors);
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, 3));
osg::Geode* geode = new osg::Geode;
geode->addDrawable(geometry);
_group->addChild(geode);
}
void addNodeSphere(const BVHNode& node)
{
if (_level != ~0u && _level != _currentLevel)
return;
SGSphered sphere = node.getBoundingSphere();
osg::Sphere* shape = new osg::Sphere;
shape->setCenter(SGVec3f(sphere.getCenter()).osg());
shape->setRadius(sphere.getRadius());
addShape(shape, osg::Vec4(0.5f, 0.5f, 0.5f, 0.1f));
}
void addNodeBox(const BVHStaticNode& node, const BVHStaticData& data)
{
if (_level != ~0u && _level != _currentLevel)
return;
BVHBoundingBoxVisitor bbv;
node.accept(bbv, data);
osg::Box* shape = new osg::Box;
shape->setCenter(bbv.getBox().getCenter().osg());
shape->setHalfLengths((0.5*bbv.getBox().getSize()).osg());
addShape(shape, osg::Vec4(0.5f, 0, 0, 0.1f));
}
void addShape(osg::Shape* shape, const osg::Vec4& color)
{
osg::ShapeDrawable* shapeDrawable = new osg::ShapeDrawable;
shapeDrawable->setColor(color);
shapeDrawable->setShape(shape);
osg::Geode* geode = new osg::Geode;
geode->addDrawable(shapeDrawable);
_group->addChild(geode);
}
osg::ref_ptr<osg::Group> _group;
const unsigned _level;
unsigned _currentLevel;
};
}
#endif

View File

@ -0,0 +1,88 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHGroup.hxx"
#include <algorithm>
namespace simgear {
BVHGroup::BVHGroup()
{
}
BVHGroup::~BVHGroup()
{
ChildList::iterator i;
for (i = _children.begin(); i != _children.end(); ++i) {
(*i)->removeParent(this);
*i = 0;
}
}
void
BVHGroup::accept(BVHVisitor& visitor)
{
visitor.apply(*this);
}
void
BVHGroup::clear()
{
_children.clear();
invalidateBound();
}
void
BVHGroup::addChild(BVHNode* child)
{
if (!child)
return;
ChildList::iterator i;
i = std::find(_children.begin(), _children.end(), child);
if (i != _children.end())
return;
invalidateBound();
child->addParent(this);
_children.push_back(child);
}
void
BVHGroup::removeChild(BVHNode* child)
{
if (!child)
return;
ChildList::iterator i;
i = std::find(_children.begin(), _children.end(), child);
if (i == _children.end())
return;
invalidateBound();
child->removeParent(this);
_children.erase(i);
}
SGSphered
BVHGroup::computeBoundingSphere() const
{
SGSphered sphere;
ChildList::const_iterator i;
for (i = _children.begin(); i != _children.end(); ++i)
sphere.expandBy((*i)->getBoundingSphere());
return sphere;
}
}

View File

@ -0,0 +1,61 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHGroup_hxx
#define BVHGroup_hxx
#include <simgear/structure/SGSharedPtr.hxx>
#include "BVHNode.hxx"
#include "BVHVisitor.hxx"
namespace simgear {
class BVHGroup : public BVHNode {
public:
BVHGroup();
virtual ~BVHGroup();
virtual void accept(BVHVisitor& visitor);
void traverse(BVHVisitor& visitor)
{
ChildList::const_iterator i;
for (i = _children.begin(); i != _children.end(); ++i)
(*i)->accept(visitor);
}
void clear();
void addChild(BVHNode* child);
void removeChild(BVHNode* child);
unsigned getNumChildren() const
{ return _children.size(); }
const BVHNode* getChild(unsigned i) const
{ if (_children.size() <= i) return 0; return _children[i]; }
BVHNode* getChild(unsigned i)
{ if (_children.size() <= i) return 0; return _children[i]; }
virtual SGSphered computeBoundingSphere() const;
private:
typedef std::vector<SGSharedPtr<BVHNode> > ChildList;
ChildList _children;
};
}
#endif

View File

@ -0,0 +1,49 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHLineGeometry.hxx"
#include "BVHVisitor.hxx"
namespace simgear {
BVHLineGeometry::BVHLineGeometry(const SGLineSegmentf& lineSegment, Type type) :
_lineSegment(lineSegment),
_type(type)
{
}
BVHLineGeometry::~BVHLineGeometry()
{
}
void
BVHLineGeometry::accept(BVHVisitor& visitor)
{
visitor.apply(*this);
}
SGSphered
BVHLineGeometry::computeBoundingSphere() const
{
SGSphered sphere;
sphere.expandBy(SGVec3d(_lineSegment.getStart()));
sphere.expandBy(SGVec3d(_lineSegment.getEnd()));
return sphere;
}
}

View File

@ -0,0 +1,53 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHLineGeometry_hxx
#define BVHLineGeometry_hxx
#include <simgear/math/SGGeometry.hxx>
#include "BVHNode.hxx"
namespace simgear {
class BVHLineGeometry : public BVHNode {
public:
enum Type {
CarrierCatapult,
CarrierWire
};
BVHLineGeometry(const SGLineSegmentf& lineSegment, Type type);
virtual ~BVHLineGeometry();
virtual void accept(BVHVisitor& visitor);
const SGLineSegmentf& getLineSegment() const
{ return _lineSegment; }
Type getType() const
{ return _type; }
virtual SGSphered computeBoundingSphere() const;
private:
SGLineSegmentf _lineSegment;
Type _type;
};
}
#endif

View File

@ -0,0 +1,157 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHLineSegmentVisitor.hxx"
#include <simgear/math/SGGeometry.hxx>
#include "BVHVisitor.hxx"
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
#include "BVHTransform.hxx"
#include "BVHMotionTransform.hxx"
#include "BVHLineGeometry.hxx"
#include "BVHStaticGeometry.hxx"
#include "BVHStaticData.hxx"
#include "BVHStaticNode.hxx"
#include "BVHStaticLeaf.hxx"
#include "BVHStaticTriangle.hxx"
#include "BVHStaticBinary.hxx"
namespace simgear {
void
BVHLineSegmentVisitor::apply(BVHGroup& group)
{
if (!intersects(_lineSegment, group.getBoundingSphere()))
return;
group.traverse(*this);
}
void
BVHLineSegmentVisitor::apply(BVHTransform& transform)
{
if (!intersects(_lineSegment, transform.getBoundingSphere()))
return;
bool haveHit = _haveHit;
_haveHit = false;
// Push the line segment
SGLineSegmentd lineSegment = getLineSegment();
_lineSegment = transform.lineSegmentToLocal(lineSegment);
transform.traverse(*this);
if (_haveHit) {
_linearVelocity = transform.vecToWorld(_linearVelocity);
_angularVelocity = transform.vecToWorld(_angularVelocity);
SGVec3d point(transform.ptToWorld(_lineSegment.getEnd()));
_lineSegment.set(lineSegment.getStart(), point);
_normal = transform.vecToWorld(_normal);
} else {
_lineSegment = lineSegment;
_haveHit = haveHit;
}
}
void
BVHLineSegmentVisitor::apply(BVHMotionTransform& transform)
{
if (!intersects(_lineSegment, transform.getBoundingSphere()))
return;
bool haveHit = _haveHit;
_haveHit = false;
// Push the line segment
SGLineSegmentd lineSegment = getLineSegment();
SGMatrixd toLocal = transform.getToLocalTransform(_time);
_lineSegment = lineSegment.transform(toLocal);
transform.traverse(*this);
if (_haveHit) {
SGMatrixd toWorld = transform.getToWorldTransform(_time);
SGVec3d localStart = _lineSegment.getStart();
_linearVelocity += transform.getLinearVelocityAt(localStart);
_angularVelocity += transform.getAngularVelocity();
_linearVelocity = toWorld.xformVec(_linearVelocity);
_angularVelocity = toWorld.xformVec(_angularVelocity);
SGVec3d localEnd = _lineSegment.getEnd();
_lineSegment.set(lineSegment.getStart(), toWorld.xformPt(localEnd));
_normal = toWorld.xformVec(_normal);
} else {
_lineSegment = lineSegment;
_haveHit = haveHit;
}
}
void
BVHLineSegmentVisitor::apply(BVHLineGeometry&)
{
}
void
BVHLineSegmentVisitor::apply(BVHStaticGeometry& node)
{
if (!intersects(_lineSegment, node.getBoundingSphere()))
return;
node.traverse(*this);
}
void
BVHLineSegmentVisitor::apply(const BVHStaticBinary& node,
const BVHStaticData& data)
{
if (!intersects(SGLineSegmentf(_lineSegment), node.getBoundingBox()))
return;
// The first box to enter is the one the startpoint is in.
// this increases the probability, that on exit of that box we do not
// even need to walk the other one, since the line segment is
// then already short enough to not intersect the other one anymore.
node.traverse(*this, data, _lineSegment.getStart());
}
void
BVHLineSegmentVisitor::apply(const BVHStaticLeaf& node,
const BVHStaticData& data)
{
}
void
BVHLineSegmentVisitor::apply(const BVHStaticTriangle& triangle,
const BVHStaticData& data)
{
SGTrianglef tri = triangle.getTriangle(data);
SGVec3f point;
if (!intersects(point, tri, SGLineSegmentf(_lineSegment), 1e-4f))
return;
setLineSegmentEnd(SGVec3d(point));
_normal = SGVec3d(tri.getNormal());
_linearVelocity = SGVec3d::zeros();
_angularVelocity = SGVec3d::zeros();
_material = data.getMaterial(triangle.getMaterialIndex());
_haveHit = true;
}
}

View File

@ -0,0 +1,94 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHLineSegmentVisitor_hxx
#define BVHLineSegmentVisitor_hxx
#include <simgear/math/SGGeometry.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/scene/material/mat.hxx>
#include "BVHVisitor.hxx"
namespace simgear {
class BVHLineSegmentVisitor : public BVHVisitor {
public:
BVHLineSegmentVisitor(const SGLineSegmentd& lineSegment,
const double& t = 0) :
_lineSegment(lineSegment),
_time(t),
_material(0),
_haveHit(false)
{ }
virtual ~BVHLineSegmentVisitor()
{ }
bool empty() const
{ return !_haveHit; }
const SGLineSegmentd& getLineSegment() const
{ return _lineSegment; }
SGVec3d getPoint() const
{ return _lineSegment.getEnd(); }
const SGVec3d& getNormal() const
{ return _normal; }
const SGVec3d& getLinearVelocity() const
{ return _linearVelocity; }
const SGVec3d& getAngularVelocity() const
{ return _angularVelocity; }
const SGMaterial* getMaterial() const
{ return _material; }
virtual void apply(BVHGroup& group);
virtual void apply(BVHTransform& transform);
virtual void apply(BVHMotionTransform& transform);
virtual void apply(BVHLineGeometry&);
virtual void apply(BVHStaticGeometry& node);
virtual void apply(const BVHStaticBinary&, const BVHStaticData&);
virtual void apply(const BVHStaticLeaf&, const BVHStaticData&);
virtual void apply(const BVHStaticTriangle&, const BVHStaticData&);
protected:
bool setLineSegmentEnd(const SGVec3d& end)
{
// Ok, you need to make sure that the new end is in the previous
// direction and that the line segment is not enlarged by that call.
#ifndef _NDEBUG
// FIXME insert code to check this...
#endif
_lineSegment.set(_lineSegment.getStart(), end);
}
private:
SGLineSegmentd _lineSegment;
double _time;
// belongs in a derived class
SGVec3d _normal;
SGVec3d _linearVelocity;
SGVec3d _angularVelocity;
const SGMaterial* _material;
bool _haveHit;
};
}
#endif

View File

@ -0,0 +1,111 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHMotionTransform.hxx"
#include "BVHVisitor.hxx"
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
namespace simgear {
BVHMotionTransform::BVHMotionTransform() :
_toWorldReference(SGMatrixd::unit()),
_toLocalReference(SGMatrixd::unit()),
_toWorldAmplification(1),
_toLocalAmplification(1),
_linearVelocity(0, 0, 0),
_angularVelocity(0, 0, 0),
_referenceTime(0),
_endTime(0)
{
}
BVHMotionTransform::~BVHMotionTransform()
{
}
void
BVHMotionTransform::accept(BVHVisitor& visitor)
{
visitor.apply(*this);
}
void
BVHMotionTransform::setTransform(const BVHMotionTransform& transform)
{
_toWorldReference = transform._toWorldReference;
_toLocalReference = transform._toLocalReference;
_toWorldAmplification = transform._toWorldAmplification;
_toLocalAmplification = transform._toLocalAmplification;
_linearVelocity = transform._linearVelocity;
_angularVelocity = transform._angularVelocity;
_referenceTime = transform._referenceTime;
_endTime = transform._endTime;
invalidateParentBound();
}
void
BVHMotionTransform::setToWorldTransform(const SGMatrixd& transform)
{
_toWorldReference = transform;
invert(_toLocalReference, transform);
updateAmplificationFactors();
invalidateParentBound();
}
void
BVHMotionTransform::setToLocalTransform(const SGMatrixd& transform)
{
_toLocalReference = transform;
invert(_toWorldReference, transform);
updateAmplificationFactors();
invalidateParentBound();
}
SGSphered
BVHMotionTransform::computeBoundingSphere() const
{
SGSphered sphere(BVHGroup::computeBoundingSphere());
if (sphere.empty())
return sphere;
SGVec3d centerStart = _toWorldReference.xformPt(sphere.getCenter());
SGMatrixd toWorldEnd = getToWorldTransform(_endTime);
SGVec3d centerEnd = toWorldEnd.xformPt(sphere.getCenter());
double rad = 0.5*length(centerStart - centerEnd) + sphere.getRadius();
rad *= _toWorldAmplification;
return SGSphered(0.5*(centerStart + centerEnd), rad);
}
void
BVHMotionTransform::updateAmplificationFactors()
{
// Hmm, this is just a hint, true?
// But anyway, almost all transforms in a scenegraph will
// have them equal to 1 ...
double r = norm(_toWorldReference.xformVec(SGVec3d(1, 0, 0)));
r = std::max(r, norm(_toWorldReference.xformVec(SGVec3d(0, 1, 0))));
r = std::max(r, norm(_toWorldReference.xformVec(SGVec3d(0, 0, 1))));
_toWorldAmplification = r;
r = norm(_toLocalReference.xformVec(SGVec3d(1, 0, 0)));
r = std::max(r, norm(_toLocalReference.xformVec(SGVec3d(0, 1, 0))));
r = std::max(r, norm(_toLocalReference.xformVec(SGVec3d(0, 0, 1))));
_toLocalAmplification = r;
}
}

View File

@ -0,0 +1,113 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHMotionTransform_hxx
#define BVHMotionTransform_hxx
#include "BVHVisitor.hxx"
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
namespace simgear {
class BVHMotionTransform : public BVHGroup {
public:
BVHMotionTransform();
virtual ~BVHMotionTransform();
virtual void accept(BVHVisitor& visitor);
void setTransform(const BVHMotionTransform& transform);
void setToWorldTransform(const SGMatrixd& transform);
void setToLocalTransform(const SGMatrixd& transform);
void setLinearVelocity(const SGVec3d& linearVelocity)
{ _linearVelocity = linearVelocity; }
const SGVec3d& getLinearVelocity() const
{ return _linearVelocity; }
void setAngularVelocity(const SGVec3d& angularVelocity)
{ _angularVelocity = angularVelocity; }
const SGVec3d& getAngularVelocity() const
{ return _angularVelocity; }
void setReferenceTime(const double& referenceTime)
{ _referenceTime = referenceTime; }
const double& getReferenceTime() const
{ return _referenceTime; }
void setEndTime(const double& endTime)
{ _endTime = endTime; }
const double& getEndTime() const
{ return _endTime; }
SGMatrixd getToWorldTransform(const double& t) const
{
double dt = t - _referenceTime;
if (0 == dt)
return _toWorldReference;
SGMatrixd matrix(_toWorldReference);
matrix.postMultRotate(SGQuatd::fromAngleAxis(dt*_angularVelocity));
matrix.postMultTranslate(dt*_linearVelocity);
return matrix;
}
SGMatrixd getToLocalTransform(const double& t) const
{
double dt = _referenceTime - t;
if (0 == dt)
return _toLocalReference;
SGMatrixd matrix(_toLocalReference);
matrix.preMultRotate(SGQuatd::fromAngleAxis(dt*_angularVelocity));
matrix.preMultTranslate(dt*_linearVelocity);
return matrix;
}
const SGMatrixd& getToWorldReferenceTransform() const
{ return _toWorldReference; }
const SGMatrixd& getToLocalReferenceTransform() const
{ return _toLocalReference; }
SGVec3d getLinearVelocityAt(const SGVec3d& reference) const
{ return _linearVelocity + cross(_angularVelocity, reference); }
SGSphered sphereToLocal(const SGSphered& sphere, const double& t) const
{
SGMatrixd matrix = getToLocalTransform(t);
SGVec3d center = matrix.xformPt(sphere.getCenter());
double radius = _toLocalAmplification*sphere.getRadius();
return SGSphered(center, radius);
}
private:
virtual SGSphered computeBoundingSphere() const;
void updateAmplificationFactors();
SGMatrixd _toWorldReference;
SGMatrixd _toLocalReference;
double _toWorldAmplification;
double _toLocalAmplification;
SGVec3d _linearVelocity;
SGVec3d _angularVelocity;
double _referenceTime;
double _endTime;
};
}
#endif

View File

@ -0,0 +1,72 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHNode.hxx"
#include <algorithm>
#include <simgear/math/SGGeometry.hxx>
namespace simgear {
BVHNode::BVHNode() :
_dirtyBoundingSphere(true)
{
}
BVHNode::~BVHNode()
{
}
void
BVHNode::addParent(BVHNode* parent)
{
// should not happen, but be paranoid ...
ParentList::iterator i;
i = std::find(_parents.begin(), _parents.end(), parent);
if (i != _parents.end())
return;
// add to the parents list ...
_parents.push_back(parent);
}
void
BVHNode::removeParent(BVHNode* parent)
{
ParentList::iterator i;
i = std::find(_parents.begin(), _parents.end(), parent);
if (i == _parents.end())
return;
_parents.erase(i);
}
void
BVHNode::invalidateParentBound()
{
for (ParentList::iterator i = _parents.begin(); i != _parents.end(); ++i)
(*i)->invalidateBound();
}
void
BVHNode::invalidateBound()
{
if (_dirtyBoundingSphere)
return;
invalidateParentBound();
_dirtyBoundingSphere = true;
}
}

View File

@ -0,0 +1,67 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHNode_hxx
#define BVHNode_hxx
#include <vector>
#include <simgear/math/SGGeometry.hxx>
#include <simgear/structure/SGReferenced.hxx>
namespace simgear {
class BVHGroup;
class BVHVisitor;
// Base for the tree nodes
class BVHNode : public SGReferenced {
public:
BVHNode();
virtual ~BVHNode();
// visitors ...
virtual void accept(BVHVisitor& visitor) = 0;
const SGSphered& getBoundingSphere() const
{
if (_dirtyBoundingSphere) {
_boundingSphere = computeBoundingSphere();
_dirtyBoundingSphere = false;
}
return _boundingSphere;
}
virtual SGSphered computeBoundingSphere() const = 0;
protected:
friend class BVHGroup;
void addParent(BVHNode* parent);
void removeParent(BVHNode* parent);
void invalidateParentBound();
virtual void invalidateBound();
private:
mutable bool _dirtyBoundingSphere;
mutable SGSphered _boundingSphere;
typedef std::vector<BVHNode*> ParentList;
ParentList _parents;
};
}
#endif

View File

@ -0,0 +1,45 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHStaticBinary.hxx"
#include "BVHVisitor.hxx"
namespace simgear {
BVHStaticBinary::BVHStaticBinary(unsigned splitAxis,
const BVHStaticNode* leftChild,
const BVHStaticNode* rightChild,
const SGBoxf& boundingBox) :
_splitAxis(splitAxis),
_leftChild(leftChild),
_rightChild(rightChild),
_boundingBox(boundingBox)
{
}
BVHStaticBinary::~BVHStaticBinary()
{
}
void
BVHStaticBinary::accept(BVHVisitor& visitor, const BVHStaticData& data) const
{
visitor.apply(*this, data);
}
}

View File

@ -0,0 +1,78 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHStaticBinary_hxx
#define BVHStaticBinary_hxx
#include <simgear/math/SGGeometry.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include "BVHStaticNode.hxx"
namespace simgear {
class BVHStaticBinary : public BVHStaticNode {
public:
BVHStaticBinary(unsigned splitAxis, const BVHStaticNode* leftChild,
const BVHStaticNode* rightChild, const SGBoxf& box);
virtual ~BVHStaticBinary();
virtual void accept(BVHVisitor& visitor, const BVHStaticData& data) const;
void traverse(BVHVisitor& visitor, const BVHStaticData& data) const
{
_leftChild->accept(visitor, data);
_rightChild->accept(visitor, data);
}
// Traverse call that first enters the child node that is potentially closer
// to the given point than the other.
template<typename T>
void traverse(BVHVisitor& visitor, const BVHStaticData& data,
const SGVec3<T>& pt) const
{
float center = 0.5f*(_boundingBox.getMin()[_splitAxis]
+ _boundingBox.getMax()[_splitAxis]);
if (pt[_splitAxis] < center) {
_leftChild->accept(visitor, data);
_rightChild->accept(visitor, data);
} else {
_rightChild->accept(visitor, data);
_leftChild->accept(visitor, data);
}
}
unsigned getSplitAxis() const
{ return _splitAxis; }
const BVHStaticNode* getLeftChild() const
{ return _leftChild; }
const BVHStaticNode* getRightChild() const
{ return _rightChild; }
const SGBoxf& getBoundingBox() const
{ return _boundingBox; }
private:
// Note the order of the members, this is to avoid padding
unsigned _splitAxis;
SGSharedPtr<const BVHStaticNode> _leftChild;
SGSharedPtr<const BVHStaticNode> _rightChild;
SGBoxf _boundingBox;
};
}
#endif

View File

@ -0,0 +1,55 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHStaticData_hxx
#define BVHStaticData_hxx
#include <vector>
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/math/SGGeometry.hxx>
/// FIXME, the SGMaterial class is too much tied to the scenegraph aspects of
/// the materials. Use some class more decribing the
/// nature of the surface we live on ...
class SGMaterial;
namespace simgear {
class BVHStaticData : public SGReferenced {
public:
virtual ~BVHStaticData() {}
unsigned addVertex(const SGVec3f& vertex)
{ _vertices.push_back(vertex); return _vertices.size() - 1; }
const SGVec3f& getVertex(unsigned i) const
{ return _vertices[i]; }
unsigned addMaterial(const SGMaterial* material)
{ _materials.push_back(material); return _materials.size() - 1; }
const SGMaterial* getMaterial(unsigned i) const
{ if (_materials.size() <= i) return 0; return _materials[i]; }
private:
std::vector<SGVec3f> _vertices;
std::vector<const SGMaterial*> _materials;
};
}
#endif

View File

@ -0,0 +1,51 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHStaticGeometry.hxx"
#include "BVHBoundingBoxVisitor.hxx"
namespace simgear {
BVHStaticGeometry::BVHStaticGeometry(const BVHStaticNode* staticNode,
const BVHStaticData* staticData) :
_staticNode(staticNode),
_staticData(staticData)
{
}
BVHStaticGeometry::~BVHStaticGeometry()
{
}
void
BVHStaticGeometry::accept(BVHVisitor& visitor)
{
visitor.apply(*this);
}
SGSphered
BVHStaticGeometry::computeBoundingSphere() const
{
BVHBoundingBoxVisitor bbv;
_staticNode->accept(bbv, *_staticData);
SGSphered sphere;
sphere.expandBy(SGBoxd(bbv.getBox()));
return sphere;
}
}

View File

@ -0,0 +1,56 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHStaticGeometry_hxx
#define BVHStaticGeometry_hxx
#include <simgear/math/SGGeometry.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include "BVHVisitor.hxx"
#include "BVHNode.hxx"
#include "BVHStaticData.hxx"
#include "BVHStaticNode.hxx"
namespace simgear {
class BVHStaticGeometry : public BVHNode {
public:
BVHStaticGeometry(const BVHStaticNode* staticNode,
const BVHStaticData* staticData);
virtual ~BVHStaticGeometry();
virtual void accept(BVHVisitor& visitor);
void traverse(BVHVisitor& visitor) const
{ _staticNode->accept(visitor, *_staticData); }
const BVHStaticData* getStaticData() const
{ return _staticData; }
const BVHStaticNode* getStaticNode() const
{ return _staticNode; }
virtual SGSphered computeBoundingSphere() const;
private:
SGSharedPtr<const BVHStaticNode> _staticNode;
SGSharedPtr<const BVHStaticData> _staticData;
};
}
#endif

View File

@ -0,0 +1,215 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHStaticGeometryBuilder_hxx
#define BVHStaticGeometryBuilder_hxx
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include "BVHVisitor.hxx"
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
#include "BVHTransform.hxx"
#include "BVHStaticData.hxx"
#include "BVHStaticNode.hxx"
#include "BVHStaticLeaf.hxx"
#include "BVHStaticTriangle.hxx"
#include "BVHStaticBinary.hxx"
#include "BVHStaticGeometry.hxx"
namespace simgear {
class BVHStaticGeometryBuilder : public SGReferenced {
public:
BVHStaticGeometryBuilder() :
_staticData(new BVHStaticData),
_currentMaterial(0),
_currentMaterialIndex(~0u)
{ }
virtual ~BVHStaticGeometryBuilder()
{ }
struct LeafRef {
LeafRef(const BVHStaticLeaf* leaf, const BVHStaticData& data) :
_leaf(leaf),
_box(_leaf->computeBoundingBox(data)),
_center(_leaf->computeCenter(data))
{ }
SGSharedPtr<const BVHStaticLeaf> _leaf;
SGBoxf _box;
SGVec3f _center;
};
typedef std::list<LeafRef> LeafRefList;
struct LeafRefLess : public std::binary_function<LeafRef, LeafRef, bool> {
LeafRefLess(unsigned sortAxis) : _sortAxis(sortAxis) {}
bool operator()(const LeafRef& x, const LeafRef& y)
{ return x._center[_sortAxis] < y._center[_sortAxis]; }
unsigned _sortAxis;
};
SGSharedPtr<BVHStaticData> _staticData;
LeafRefList _leafRefList;
typedef std::map<SGVec3f, unsigned> VertexMap;
VertexMap _vertexMap;
void setCurrentMaterial(const SGMaterial* material)
{
_currentMaterial = material;
_currentMaterialIndex = addMaterial(material);
}
const SGMaterial* getCurrentMaterial() const
{
return _currentMaterial;
}
unsigned addMaterial(const SGMaterial* material)
{
MaterialMap::const_iterator i = _materialMap.find(material);
if (i != _materialMap.end())
return i->second;
unsigned index = _staticData->addMaterial(material);
_materialMap[material] = index;
return index;
}
typedef std::map<const SGMaterial*, unsigned> MaterialMap;
MaterialMap _materialMap;
const SGMaterial* _currentMaterial;
unsigned _currentMaterialIndex;
void addTriangle(const SGVec3f& v1, const SGVec3f& v2, const SGVec3f& v3)
{
unsigned indices[3] = { addVertex(v1), addVertex(v2), addVertex(v3) };
BVHStaticTriangle* staticTriangle;
staticTriangle = new BVHStaticTriangle(_currentMaterialIndex, indices);
_leafRefList.push_back(LeafRef(staticTriangle, *_staticData));
}
unsigned addVertex(const SGVec3f& v)
{
VertexMap::const_iterator i = _vertexMap.find(v);
if (i != _vertexMap.end())
return i->second;
unsigned index = _staticData->addVertex(v);
_vertexMap[v] = index;
return index;
}
BVHStaticGeometry* buildTree()
{
const BVHStaticNode* tree = buildTreeRecursive(_leafRefList);
if (!tree)
return 0;
return new BVHStaticGeometry(tree, _staticData);
}
private:
static void
centerSplitLeafs(unsigned splitAxis, const double& splitValue,
LeafRefList& leafs, LeafRefList split[2])
{
while (!leafs.empty()) {
if (leafs.front()._center[splitAxis] < splitValue) {
split[0].splice(split[0].begin(), leafs, leafs.begin());
} else {
split[1].splice(split[1].begin(), leafs, leafs.begin());
}
}
}
static void
equalSplitLeafs(unsigned splitAxis, LeafRefList& leafs,
LeafRefList split[2])
{
leafs.sort(LeafRefLess(splitAxis));
while (true) {
if (leafs.empty())
break;
split[0].splice(split[0].begin(), leafs, leafs.begin());
if (leafs.empty())
break;
split[1].splice(split[1].begin(), leafs, --leafs.end());
}
}
static const BVHStaticNode* buildTreeRecursive(LeafRefList& leafs)
{
// recursion termination
if (leafs.empty())
return 0;
// FIXME size is O(n)!!!
// if (leafs.size() == 1)
if (++leafs.begin() == leafs.end())
return leafs.front()._leaf;
SGBoxf box;
for (LeafRefList::const_iterator i = leafs.begin();
i != leafs.end(); ++i)
box.expandBy(i->_box);
// // FIXME ...
// if (length(box.getSize()) < 1)
// return new BVHBox(box);
if (box.empty())
return 0;
unsigned splitAxis = box.getBroadestAxis();
LeafRefList splitLeafs[2];
double splitValue = box.getCenter()[splitAxis];
centerSplitLeafs(splitAxis, splitValue, leafs, splitLeafs);
if (splitLeafs[0].empty() || splitLeafs[1].empty()) {
for (unsigned i = 0; i < 3 ; ++i) {
if (i == splitAxis)
continue;
leafs.swap(splitLeafs[0]);
leafs.splice(leafs.begin(), splitLeafs[1]);
splitValue = box.getCenter()[i];
centerSplitLeafs(i, splitValue, leafs, splitLeafs);
if (!splitLeafs[0].empty() && !splitLeafs[1].empty()) {
splitAxis = i;
break;
}
}
}
if (splitLeafs[0].empty() || splitLeafs[1].empty()) {
leafs.swap(splitLeafs[0]);
leafs.splice(leafs.begin(), splitLeafs[1]);
equalSplitLeafs(splitAxis, leafs, splitLeafs);
}
const BVHStaticNode* child0 = buildTreeRecursive(splitLeafs[0]);
const BVHStaticNode* child1 = buildTreeRecursive(splitLeafs[1]);
if (!child0)
return child1;
if (!child1)
return child0;
return new BVHStaticBinary(splitAxis, child0, child1, box);
}
};
}
#endif

View File

@ -0,0 +1,33 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHStaticLeaf.hxx"
#include "BVHVisitor.hxx"
namespace simgear {
BVHStaticLeaf::~BVHStaticLeaf()
{
}
void
BVHStaticLeaf::accept(BVHVisitor& visitor, const BVHStaticData& data) const
{
visitor.apply(*this, data);
}
}

View File

@ -0,0 +1,38 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHStaticLeaf_hxx
#define BVHStaticLeaf_hxx
#include <simgear/math/SGGeometry.hxx>
#include "BVHStaticNode.hxx"
namespace simgear {
class BVHStaticLeaf : public BVHStaticNode {
public:
virtual ~BVHStaticLeaf();
virtual void accept(BVHVisitor& visitor, const BVHStaticData& data) const;
virtual SGBoxf computeBoundingBox(const BVHStaticData&) const = 0;
virtual SGVec3f computeCenter(const BVHStaticData&) const = 0;
};
}
#endif

View File

@ -0,0 +1,26 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHStaticNode.hxx"
namespace simgear {
BVHStaticNode::~BVHStaticNode()
{
}
}

View File

@ -0,0 +1,37 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHStaticNode_hxx
#define BVHStaticNode_hxx
#include <simgear/structure/SGReferenced.hxx>
namespace simgear {
class BVHStaticData;
class BVHVisitor;
class BVHStaticNode : public SGReferenced {
public:
virtual ~BVHStaticNode();
virtual void accept(BVHVisitor&, const BVHStaticData&) const = 0;
};
}
#endif

View File

@ -0,0 +1,58 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHStaticTriangle.hxx"
#include "BVHVisitor.hxx"
namespace simgear {
BVHStaticTriangle::BVHStaticTriangle(unsigned material,
const unsigned indices[3]) :
_material(material)
{
for (unsigned i = 0; i < 3; ++i)
_indices[i] = indices[i];
}
BVHStaticTriangle::~BVHStaticTriangle()
{
}
void
BVHStaticTriangle::accept(BVHVisitor& visitor, const BVHStaticData& data) const
{
visitor.apply(*this, data);
}
SGBoxf
BVHStaticTriangle::computeBoundingBox(const BVHStaticData& data) const
{
SGBoxf box;
box.expandBy(data.getVertex(_indices[0]));
box.expandBy(data.getVertex(_indices[1]));
box.expandBy(data.getVertex(_indices[2]));
return box;
}
SGVec3f
BVHStaticTriangle::computeCenter(const BVHStaticData& data) const
{
return getTriangle(data).getCenter();
}
}

View File

@ -0,0 +1,54 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHStaticTriangle_hxx
#define BVHStaticTriangle_hxx
#include <simgear/math/SGGeometry.hxx>
#include "BVHStaticData.hxx"
#include "BVHStaticLeaf.hxx"
namespace simgear {
class BVHStaticTriangle : public BVHStaticLeaf {
public:
BVHStaticTriangle(unsigned material, const unsigned indices[3]);
virtual ~BVHStaticTriangle();
virtual void accept(BVHVisitor& visitor, const BVHStaticData& data) const;
virtual SGBoxf computeBoundingBox(const BVHStaticData& data) const;
virtual SGVec3f computeCenter(const BVHStaticData& data) const;
SGTrianglef getTriangle(const BVHStaticData& data) const
{
return SGTrianglef(data.getVertex(_indices[0]),
data.getVertex(_indices[1]),
data.getVertex(_indices[2]));
}
unsigned getMaterialIndex() const
{ return _material; }
private:
unsigned _indices[3];
unsigned _material;
};
}
#endif

View File

@ -0,0 +1,258 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHSubTreeCollector.hxx"
#include <simgear/math/SGGeometry.hxx>
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
#include "BVHTransform.hxx"
#include "BVHStaticData.hxx"
#include "BVHStaticNode.hxx"
#include "BVHStaticLeaf.hxx"
#include "BVHStaticTriangle.hxx"
#include "BVHStaticBinary.hxx"
#include "BVHStaticGeometry.hxx"
#include "BVHBoundingBoxVisitor.hxx"
namespace simgear {
BVHSubTreeCollector::BVHSubTreeCollector(const SGSphered& sphere) :
_sphere(sphere)
{
}
BVHSubTreeCollector::~BVHSubTreeCollector()
{
}
void
BVHSubTreeCollector::apply(BVHGroup& group)
{
if (!intersects(_sphere, group.getBoundingSphere()))
return;
// The _nodeList content is somehow the 'return value' of the subtree.
// Set it to zero to see if we have something to collect down there.
NodeList parentNodeList;
pushNodeList(parentNodeList);
group.traverse(*this);
popNodeList(parentNodeList);
}
void
BVHSubTreeCollector::apply(BVHTransform& transform)
{
if (!intersects(_sphere, transform.getBoundingSphere()))
return;
SGSphered sphere = _sphere;
_sphere = transform.sphereToLocal(sphere);
NodeList parentNodeList;
pushNodeList(parentNodeList);
transform.traverse(*this);
if (haveChildren()) {
BVHTransform* currentBvTransform = new BVHTransform;
currentBvTransform->setTransform(transform);
popNodeList(parentNodeList, currentBvTransform);
} else {
popNodeList(parentNodeList);
}
_sphere = sphere;
}
void
BVHSubTreeCollector::apply(BVHMotionTransform& transform)
{
if (!intersects(_sphere, transform.getBoundingSphere()))
return;
SGSphered sphere = _sphere;
_sphere = transform.sphereToLocal(sphere, transform.getReferenceTime());
_sphere.expandBy(transform.sphereToLocal(sphere, transform.getEndTime()));
NodeList parentNodeList;
pushNodeList(parentNodeList);
transform.traverse(*this);
if (haveChildren()) {
BVHMotionTransform* currentBvTransform = new BVHMotionTransform;
currentBvTransform->setTransform(transform);
popNodeList(parentNodeList, currentBvTransform);
} else {
popNodeList(parentNodeList);
}
_sphere = sphere;
}
void
BVHSubTreeCollector::apply(BVHLineGeometry& lineSegment)
{
if (!intersects(_sphere, lineSegment.getBoundingSphere()))
return;
addNode(&lineSegment);
}
void
BVHSubTreeCollector::apply(BVHStaticGeometry& node)
{
if (!intersects(_sphere, node.getBoundingSphere()))
return;
assert(!_staticNode);
node.traverse(*this);
if (!_staticNode)
return;
BVHStaticGeometry* staticTree;
staticTree = new BVHStaticGeometry(_staticNode, node.getStaticData());
addNode(staticTree);
_staticNode = 0;
}
void
BVHSubTreeCollector::apply(const BVHStaticBinary& node,
const BVHStaticData& data)
{
assert(!_staticNode);
if (!intersects(_sphere, node.getBoundingBox()))
return;
SGVec3d corner(node.getBoundingBox().getFarestCorner(_sphere.getCenter()));
if (intersects(_sphere, corner)) {
// If the box is totally contained in the sphere, just take it all
_staticNode = &node;
} else {
// We have still a chance to seperate something out, try it.
node.getLeftChild()->accept(*this, data);
SGSharedPtr<const BVHStaticNode> leftStaticNode = _staticNode;
_staticNode = 0;
node.getRightChild()->accept(*this, data);
SGSharedPtr<const BVHStaticNode> rightStaticNode = _staticNode;
_staticNode = 0;
if (leftStaticNode) {
if (rightStaticNode) {
BVHBoundingBoxVisitor bbv;
leftStaticNode->accept(bbv, data);
rightStaticNode->accept(bbv, data);
_staticNode
= new BVHStaticBinary(node.getSplitAxis(), leftStaticNode,
rightStaticNode, bbv.getBox());
} else {
_staticNode = leftStaticNode;
}
} else {
if (rightStaticNode) {
_staticNode = rightStaticNode;
} else {
// Nothing to report to parents ...
}
}
}
}
void
BVHSubTreeCollector::apply(const BVHStaticLeaf& node,
const BVHStaticData& data)
{
if (!intersects(_sphere, node.computeBoundingBox(data)))
return;
_staticNode = &node;
}
void
BVHSubTreeCollector::apply(const BVHStaticTriangle& node,
const BVHStaticData& data)
{
if (!intersects(_sphere, node.computeBoundingBox(data)))
return;
_staticNode = &node;
}
void
BVHSubTreeCollector::addNode(BVHNode* node)
{
if (!node)
return;
if (!_nodeList.capacity())
_nodeList.reserve(64);
_nodeList.push_back(node);
}
void
BVHSubTreeCollector::popNodeList(NodeList& parentNodeList, BVHGroup* transform)
{
// Only do something if we really have children
if (!_nodeList.empty()) {
NodeList::const_iterator i;
for (i = _nodeList.begin(); i != _nodeList.end(); ++i)
transform->addChild(*i);
parentNodeList.push_back(transform);
}
_nodeList.swap(parentNodeList);
}
void
BVHSubTreeCollector::popNodeList(NodeList& parentNodeList)
{
// Only do something if we really have children
if (!_nodeList.empty()) {
if (_nodeList.size() == 1) {
parentNodeList.push_back(_nodeList.front());
} else {
BVHGroup* group = new BVHGroup;
NodeList::const_iterator i;
for (i = _nodeList.begin(); i != _nodeList.end(); ++i)
group->addChild(*i);
parentNodeList.push_back(group);
}
}
_nodeList.swap(parentNodeList);
}
SGSharedPtr<BVHNode>
BVHSubTreeCollector::getNode() const
{
if (_nodeList.empty())
return 0;
if (_nodeList.size() == 1)
return _nodeList.front();
BVHGroup* group = new BVHGroup;
NodeList::const_iterator i;
for (i = _nodeList.begin(); i != _nodeList.end(); ++i)
group->addChild(*i);
return group;
}
}

View File

@ -0,0 +1,82 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHSubTreeCollector_hxx
#define BVHSubTreeCollector_hxx
#include <simgear/math/SGGeometry.hxx>
#include "BVHVisitor.hxx"
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
#include "BVHStaticNode.hxx"
namespace simgear {
/// Visitor to subcollect parts of an existing bounding volume tree.
/// Given a sphere, it takes those sub parts of the tree that intersect the
/// sphere. Transform nodes of any kind are preserved to be able to ask for
/// intersections a different times. The subcollected tree is kept as small as
/// possible as it does avoid having groups with single childs.
/// Also the BVHStaticGeometry parts are seached for subtrees that are outside
/// the sphere.
class BVHSubTreeCollector : public BVHVisitor {
public:
typedef std::vector<SGSharedPtr<BVHNode> > NodeList;
BVHSubTreeCollector(const SGSphered& sphere = SGSphered());
virtual ~BVHSubTreeCollector();
virtual void apply(BVHGroup&);
virtual void apply(BVHTransform&);
virtual void apply(BVHMotionTransform&);
virtual void apply(BVHLineGeometry&);
virtual void apply(BVHStaticGeometry&);
virtual void apply(const BVHStaticBinary&, const BVHStaticData&);
virtual void apply(const BVHStaticLeaf&, const BVHStaticData&);
virtual void apply(const BVHStaticTriangle&, const BVHStaticData&);
void setSphere(const SGSphered& sphere)
{ _sphere = sphere; }
const SGSphered& getSphere() const
{ return _sphere; }
bool haveChildren() const
{ return !_nodeList.empty(); }
void addNode(BVHNode* node);
void pushNodeList(NodeList& parentNodeList)
{ _nodeList.swap(parentNodeList); }
void popNodeList(NodeList& parentNodeList, BVHGroup* transform);
void popNodeList(NodeList& parentNodeList);
SGSharedPtr<BVHNode> getNode() const;
protected:
NodeList _nodeList;
SGSharedPtr<const BVHStaticNode> _staticNode;
private:
SGSphered _sphere;
};
}
#endif

View File

@ -0,0 +1,95 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "BVHTransform.hxx"
#include "BVHVisitor.hxx"
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
namespace simgear {
BVHTransform::BVHTransform() :
_toWorld(SGMatrixd::unit()),
_toLocal(SGMatrixd::unit()),
_toWorldAmplification(1),
_toLocalAmplification(1)
{
}
BVHTransform::~BVHTransform()
{
}
void
BVHTransform::accept(BVHVisitor& visitor)
{
visitor.apply(*this);
}
void
BVHTransform::setTransform(const BVHTransform& transform)
{
_toWorld = transform._toWorld;
_toLocal = transform._toLocal;
_toWorldAmplification = transform._toWorldAmplification;
_toLocalAmplification = transform._toLocalAmplification;
invalidateParentBound();
}
void
BVHTransform::setToWorldTransform(const SGMatrixd& transform)
{
_toWorld = transform;
invert(_toLocal, transform);
updateAmplificationFactors();
invalidateParentBound();
}
void
BVHTransform::setToLocalTransform(const SGMatrixd& transform)
{
_toLocal = transform;
invert(_toWorld, transform);
updateAmplificationFactors();
invalidateParentBound();
}
SGSphered
BVHTransform::computeBoundingSphere() const
{
return sphereToWorld(BVHGroup::computeBoundingSphere());
}
void
BVHTransform::updateAmplificationFactors()
{
// Hmm, this is just a hint, true?
// But anyway, almost all transforms in a scenegraph will
// have them equal to 1 ...
double r = norm(vecToWorld(SGVec3d(1, 0, 0)));
r = std::max(r, norm(vecToWorld(SGVec3d(0, 1, 0))));
r = std::max(r, norm(vecToWorld(SGVec3d(0, 0, 1))));
_toWorldAmplification = r;
r = norm(vecToLocal(SGVec3d(1, 0, 0)));
r = std::max(r, norm(vecToLocal(SGVec3d(0, 1, 0))));
r = std::max(r, norm(vecToLocal(SGVec3d(0, 0, 1))));
_toLocalAmplification = r;
}
}

View File

@ -0,0 +1,82 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHTransform_hxx
#define BVHTransform_hxx
#include "BVHGroup.hxx"
namespace simgear {
class BVHTransform : public BVHGroup {
public:
BVHTransform();
virtual ~BVHTransform();
virtual void accept(BVHVisitor& visitor);
void setTransform(const BVHTransform& transform);
void setToWorldTransform(const SGMatrixd& transform);
const SGMatrixd& getToWorldTransform() const
{ return _toWorld; }
void setToLocalTransform(const SGMatrixd& transform);
const SGMatrixd& getToLocalTransform() const
{ return _toLocal; }
SGVec3d ptToWorld(const SGVec3d& point) const
{ return _toWorld.xformPt(point); }
SGVec3d ptToLocal(const SGVec3d& point) const
{ return _toLocal.xformPt(point); }
SGVec3d vecToWorld(const SGVec3d& vec) const
{ return _toWorld.xformVec(vec); }
SGVec3d vecToLocal(const SGVec3d& vec) const
{ return _toLocal.xformVec(vec); }
SGLineSegmentd lineSegmentToWorld(const SGLineSegmentd& lineSeg) const
{ return lineSeg.transform(_toWorld); }
SGLineSegmentd lineSegmentToLocal(const SGLineSegmentd& lineSeg) const
{ return lineSeg.transform(_toLocal); }
SGSphered sphereToWorld(const SGSphered& sphere) const
{
SGVec3d center = ptToWorld(sphere.getCenter());
double radius = _toWorldAmplification*sphere.getRadius();
return SGSphered(center, radius);
}
SGSphered sphereToLocal(const SGSphered& sphere) const
{
SGVec3d center = ptToLocal(sphere.getCenter());
double radius = _toLocalAmplification*sphere.getRadius();
return SGSphered(center, radius);
}
private:
virtual SGSphered computeBoundingSphere() const;
void updateAmplificationFactors();
SGMatrixd _toWorld;
SGMatrixd _toLocal;
double _toWorldAmplification;
double _toLocalAmplification;
};
}
#endif

View File

@ -0,0 +1,58 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef BVHVisitor_hxx
#define BVHVisitor_hxx
namespace simgear {
class BVHStaticData;
class BVHGroup;
class BVHTransform;
class BVHMotionTransform;
class BVHStaticGeometry;
class BVHLineGeometry;
class BVHStaticBinary;
class BVHStaticLeaf;
class BVHStaticTriangle;
class BVHVisitor {
public:
// The magnitudes of pure virtuals is because of the fact that this chaining
// just takes needless runtime. This declaration should force the user of
// this classes to implement a common functionality that should be called
// from each apropriate apply method directly.
virtual ~BVHVisitor() {}
// High level nodes to handle
virtual void apply(BVHGroup&) = 0;
virtual void apply(BVHTransform&) = 0;
virtual void apply(BVHMotionTransform&) = 0;
virtual void apply(BVHLineGeometry&) = 0;
virtual void apply(BVHStaticGeometry&) = 0;
// Static tree nodes to handle
virtual void apply(const BVHStaticBinary&, const BVHStaticData&) = 0;
virtual void apply(const BVHStaticLeaf&, const BVHStaticData&) = 0;
virtual void apply(const BVHStaticTriangle&, const BVHStaticData&) = 0;
};
}
#endif

View File

@ -0,0 +1,46 @@
includedir = @includedir@/scene/bvh
check_PROGRAMS = bvhtest
TESTS = $(check_PROGRAMS)
bvhtest_SOURCES = bvhtest.cxx
bvhtest_LDADD = libsgbvh.a -lsgstructure -lsgmath $(base_LIBS)
lib_LIBRARIES = libsgbvh.a
noinst_HEADERS =
include_HEADERS = \
BVHBoundingBoxVisitor.hxx \
BVHDebugCollectVisitor.hxx \
BVHGroup.hxx \
BVHLineSegmentVisitor.hxx \
BVHLineGeometry.hxx \
BVHMotionTransform.hxx \
BVHNode.hxx \
BVHStaticBinary.hxx \
BVHStaticData.hxx \
BVHStaticGeometry.hxx \
BVHStaticGeometryBuilder.hxx \
BVHStaticLeaf.hxx \
BVHStaticNode.hxx \
BVHStaticTriangle.hxx \
BVHSubTreeCollector.hxx \
BVHTransform.hxx \
BVHVisitor.hxx
libsgbvh_a_SOURCES = \
BVHGroup.cxx \
BVHLineGeometry.cxx \
BVHLineSegmentVisitor.cxx \
BVHMotionTransform.cxx \
BVHNode.cxx \
BVHStaticBinary.cxx \
BVHStaticGeometry.cxx \
BVHStaticLeaf.cxx \
BVHStaticNode.cxx \
BVHStaticTriangle.cxx \
BVHSubTreeCollector.cxx \
BVHTransform.cxx
INCLUDES = -I$(top_srcdir)

View File

@ -0,0 +1,118 @@
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include <iostream>
#include <simgear/structure/SGSharedPtr.hxx>
#include "BVHNode.hxx"
#include "BVHGroup.hxx"
#include "BVHTransform.hxx"
#include "BVHStaticData.hxx"
#include "BVHStaticNode.hxx"
#include "BVHStaticLeaf.hxx"
#include "BVHStaticTriangle.hxx"
#include "BVHStaticBinary.hxx"
#include "BVHStaticGeometry.hxx"
#include "BVHBoundingBoxVisitor.hxx"
#include "BVHSubTreeCollector.hxx"
#include "BVHLineSegmentVisitor.hxx"
using namespace simgear;
BVHNode*
buildSingleTriangle(const SGVec3f& v1, const SGVec3f& v2, const SGVec3f& v3)
{
BVHStaticData* staticData = new BVHStaticData;
unsigned indices[3] = {
staticData->addVertex(v1),
staticData->addVertex(v2),
staticData->addVertex(v3)
};
BVHStaticTriangle* staticTriangle = new BVHStaticTriangle(~0u, indices);
return new BVHStaticGeometry(staticTriangle, staticData);
}
bool
testLineIntersections()
{
SGVec3f v1(-1, -1, 0);
SGVec3f v2(1, -1, 0);
SGVec3f v3(-1, 1, 0);
SGSharedPtr<BVHNode> node = buildSingleTriangle(v1, v2, v3);
SGLineSegmentd lineSegment(SGVec3d(0, 0, -1), SGVec3d(0, 0, 1));
{
BVHLineSegmentVisitor lineSegmentVisitor(lineSegment);
node->accept(lineSegmentVisitor);
if (lineSegmentVisitor.empty())
return false;
if (!equivalent(lineSegmentVisitor.getPoint(), SGVec3d(0, 0, 0)))
return false;
}
SGVec3d position(1000, 1000, 1000);
SGMatrixd matrix(position);
SGSharedPtr<BVHTransform> transform1 = new BVHTransform;
transform1->setToWorldTransform(matrix);
transform1->addChild(node);
SGSharedPtr<BVHTransform> transform2 = new BVHTransform;
transform2->setToLocalTransform(matrix);
transform2->addChild(transform1);
{
BVHLineSegmentVisitor lineSegmentVisitor(lineSegment);
transform2->accept(lineSegmentVisitor);
if (lineSegmentVisitor.empty())
return false;
if (!equivalent(lineSegmentVisitor.getPoint(), SGVec3d(0, 0, 0)))
return false;
}
SGSharedPtr<BVHMotionTransform> transform3 = new BVHMotionTransform;
transform3->setLinearVelocity(SGVec3d(0, 0, 1));
transform3->setAngularVelocity(SGVec3d(1, 0, 0));
transform3->addChild(node);
{
BVHLineSegmentVisitor lineSegmentVisitor(lineSegment, 0);
transform3->accept(lineSegmentVisitor);
if (lineSegmentVisitor.empty())
return false;
if (!equivalent(lineSegmentVisitor.getPoint(), SGVec3d(0, 0, 0)))
return false;
if (!equivalent(lineSegmentVisitor.getLinearVelocity(),
SGVec3d(0, 1, 1)))
return false;
if (!equivalent(lineSegmentVisitor.getAngularVelocity(),
SGVec3d(1, 0, 0)))
return false;
}
return true;
}
int
main(int argc, char** argv)
{
if (!testLineIntersections())
return EXIT_FAILURE;
return EXIT_SUCCESS;
}