foreach( mylibfolder
bucket
+ bvh
debug
ephemeris
io
--- /dev/null
+// 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 "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 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
--- /dev/null
+// 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.
+//
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#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;
+}
+
+}
--- /dev/null
+// 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
--- /dev/null
+// 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;
+}
+
+}
--- /dev/null
+// 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
--- /dev/null
+// 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.
+//
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#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 "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);
+ if (!_id)
+ _id = transform.getId();
+ } 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 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());
+ _id = 0;
+ _haveHit = true;
+}
+
+
+}
--- /dev/null
+// 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"
+#include "BVHNode.hxx"
+
+namespace simgear {
+
+class BVHLineSegmentVisitor : public BVHVisitor {
+public:
+ BVHLineSegmentVisitor(const SGLineSegmentd& lineSegment,
+ const double& t = 0) :
+ _lineSegment(lineSegment),
+ _time(t),
+ _material(0),
+ _id(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; }
+ BVHNode::Id getId() const
+ { return _id; }
+
+ 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 BVHStaticTriangle&, const BVHStaticData&);
+
+protected:
+ void 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;
+ BVHNode::Id _id;
+
+ bool _haveHit;
+};
+
+}
+
+#endif
--- /dev/null
+// 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.
+//
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#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),
+ _startTime(0),
+ _endTime(0),
+ _id(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;
+ _startTime = transform._startTime;
+ _endTime = transform._endTime;
+ _id = transform._id;
+ 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;
+ SGMatrixd toWorldStart = getToWorldTransform(_startTime);
+ SGVec3d centerStart = toWorldStart.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 = SGMiscd::max(r, norm(_toWorldReference.xformVec(SGVec3d(0, 1, 0))));
+ r = SGMiscd::max(r, norm(_toWorldReference.xformVec(SGVec3d(0, 0, 1))));
+ _toWorldAmplification = r;
+
+ r = norm(_toLocalReference.xformVec(SGVec3d(1, 0, 0)));
+ r = SGMiscd::max(r, norm(_toLocalReference.xformVec(SGVec3d(0, 1, 0))));
+ r = SGMiscd::max(r, norm(_toLocalReference.xformVec(SGVec3d(0, 0, 1))));
+ _toLocalAmplification = r;
+}
+
+}
--- /dev/null
+// 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 setStartTime(const double& startTime)
+ { _startTime = startTime; }
+ const double& getStartTime() const
+ { return _startTime; }
+
+ void setEndTime(const double& endTime)
+ { _endTime = endTime; }
+ const double& getEndTime() const
+ { return _endTime; }
+
+ SGMatrixd getToWorldTransform(const double& t) const
+ {
+ if (t == _referenceTime)
+ return _toWorldReference;
+ double dt = t - _referenceTime;
+ SGMatrixd matrix(_toWorldReference);
+ matrix.postMultRotate(SGQuatd::fromAngleAxis(dt*_angularVelocity));
+ matrix.postMultTranslate(dt*_linearVelocity);
+ return matrix;
+ }
+ SGMatrixd getToLocalTransform(const double& t) const
+ {
+ if (t == _referenceTime)
+ return _toLocalReference;
+ double dt = _referenceTime - t;
+ 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);
+ }
+
+ void setId(Id id)
+ { _id = id; }
+ Id getId() const
+ { return _id; }
+
+private:
+ virtual SGSphered computeBoundingSphere() const;
+ void updateAmplificationFactors();
+
+ SGMatrixd _toWorldReference;
+ SGMatrixd _toLocalReference;
+ double _toWorldAmplification;
+ double _toLocalAmplification;
+
+ SGVec3d _linearVelocity;
+ SGVec3d _angularVelocity;
+
+ double _referenceTime;
+ double _startTime;
+ double _endTime;
+
+ Id _id;
+};
+
+}
+
+#endif
--- /dev/null
+// 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 BVHNearestPointVisitor_hxx
+#define BVHNearestPointVisitor_hxx
+
+#include <simgear/math/SGGeometry.hxx>
+
+#include "BVHVisitor.hxx"
+
+#include "BVHNode.hxx"
+#include "BVHGroup.hxx"
+#include "BVHTransform.hxx"
+#include "BVHLineGeometry.hxx"
+#include "BVHStaticGeometry.hxx"
+
+#include "BVHStaticData.hxx"
+
+#include "BVHStaticNode.hxx"
+#include "BVHStaticTriangle.hxx"
+#include "BVHStaticBinary.hxx"
+
+namespace simgear {
+
+class BVHNearestPointVisitor : public BVHVisitor {
+public:
+ BVHNearestPointVisitor(const SGSphered& sphere, const double& t) :
+ _sphere(sphere),
+ _time(t),
+ _material(0),
+ _id(0),
+ _havePoint(false)
+ { }
+
+ virtual void apply(BVHGroup& leaf)
+ {
+ if (!intersects(_sphere, leaf.getBoundingSphere()))
+ return;
+ leaf.traverse(*this);
+ }
+ virtual void apply(BVHTransform& transform)
+ {
+ if (!intersects(_sphere, transform.getBoundingSphere()))
+ return;
+
+ SGSphered sphere = _sphere;
+ _sphere = transform.sphereToLocal(sphere);
+ bool havePoint = _havePoint;
+ _havePoint = false;
+
+ transform.traverse(*this);
+
+ if (_havePoint) {
+ _point = transform.ptToWorld(_point);
+ _linearVelocity = transform.vecToWorld(_linearVelocity);
+ _angularVelocity = transform.vecToWorld(_angularVelocity);
+ }
+ _havePoint |= havePoint;
+ _sphere.setCenter(sphere.getCenter());
+ }
+ virtual void apply(BVHMotionTransform& transform)
+ {
+ if (!intersects(_sphere, transform.getBoundingSphere()))
+ return;
+
+ SGSphered sphere = _sphere;
+ _sphere = transform.sphereToLocal(sphere, _time);
+ bool havePoint = _havePoint;
+ _havePoint = false;
+
+ transform.traverse(*this);
+
+ if (_havePoint) {
+ SGMatrixd toWorld = transform.getToWorldTransform(_time);
+ SGVec3d localCenter = _sphere.getCenter();
+ _linearVelocity += transform.getLinearVelocityAt(localCenter);
+ _angularVelocity += transform.getAngularVelocity();
+ _linearVelocity = toWorld.xformVec(_linearVelocity);
+ _angularVelocity = toWorld.xformVec(_angularVelocity);
+ _point = toWorld.xformPt(_point);
+ if (!_id)
+ _id = transform.getId();
+ }
+ _havePoint |= havePoint;
+ _sphere.setCenter(sphere.getCenter());
+ }
+ virtual void apply(BVHLineGeometry& node)
+ { }
+ virtual void apply(BVHStaticGeometry& node)
+ {
+ if (!intersects(_sphere, node.getBoundingSphere()))
+ return;
+ node.traverse(*this);
+ }
+
+ virtual void apply(const BVHStaticBinary& node, const BVHStaticData& data)
+ {
+ if (!intersects(_sphere, node.getBoundingBox()))
+ return;
+ node.traverse(*this, data, _sphere.getCenter());
+ }
+ virtual void apply(const BVHStaticTriangle& node, const BVHStaticData& data)
+ {
+ SGVec3f center(_sphere.getCenter());
+ SGVec3d closest(closestPoint(node.getTriangle(data), center));
+ if (!intersects(_sphere, closest))
+ return;
+ _point = closest;
+ _linearVelocity = SGVec3d::zeros();
+ _angularVelocity = SGVec3d::zeros();
+ _material = data.getMaterial(node.getMaterialIndex());
+ // The trick is to decrease the radius of the search sphere.
+ _sphere.setRadius(length(closest - _sphere.getCenter()));
+ _havePoint = true;
+ _id = 0;
+ }
+
+ void setSphere(const SGSphered& sphere)
+ { _sphere = sphere; }
+ const SGSphered& getSphere() const
+ { return _sphere; }
+
+ const SGVec3d& getPoint() const
+ { return _point; }
+ const SGVec3d& getLinearVelocity() const
+ { return _linearVelocity; }
+ const SGVec3d& getAngularVelocity() const
+ { return _angularVelocity; }
+ const SGMaterial* getMaterial() const
+ { return _material; }
+ BVHNode::Id getId() const
+ { return _id; }
+
+ bool empty() const
+ { return !_havePoint; }
+
+private:
+ SGSphered _sphere;
+ double _time;
+
+ SGVec3d _point;
+ SGVec3d _linearVelocity;
+ SGVec3d _angularVelocity;
+ const SGMaterial* _material;
+ BVHNode::Id _id;
+
+ bool _havePoint;
+};
+
+}
+
+#endif
--- /dev/null
+// 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/structure/SGAtomic.hxx>
+#include <simgear/math/SGGeometry.hxx>
+
+namespace simgear {
+
+BVHNode::BVHNode() :
+ _dirtyBoundingSphere(true)
+{
+}
+
+BVHNode::~BVHNode()
+{
+}
+
+BVHNode::Id
+BVHNode::getNewId()
+{
+ static SGAtomic id(0);
+ return ++id;
+}
+
+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;
+}
+
+}
--- /dev/null
+// 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;
+
+ /// A unique id for some kind of BVHNodes.
+ /// Currently only motions transforms.
+ typedef unsigned Id;
+
+ // Factory to get a new id
+ static Id getNewId();
+
+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
--- /dev/null
+// 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);
+}
+
+}
--- /dev/null
+// 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
--- /dev/null
+// 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]; }
+
+ void trim()
+ {
+ std::vector<SGVec3f>(_vertices).swap(_vertices);
+ std::vector<const SGMaterial*>(_materials).swap(_materials);
+ }
+
+private:
+ std::vector<SGVec3f> _vertices;
+ std::vector<const SGMaterial*> _materials;
+};
+
+}
+
+#endif
--- /dev/null
+// 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;
+}
+
+}
--- /dev/null
+// 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
--- /dev/null
+// 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 <algorithm>
+#include <map>
+#include <set>
+
+#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;
+
+ typedef std::set<SGVec3<unsigned> > TriangleSet;
+ TriangleSet _triangleSet;
+
+ 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) };
+ std::sort(indices, indices + 3);
+ SGVec3<unsigned> indexKey(indices);
+ if (_triangleSet.find(indexKey) != _triangleSet.end())
+ return;
+ _triangleSet.insert(indexKey);
+ 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;
+ _staticData->trim();
+ 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
--- /dev/null
+// 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()
+{
+}
+
+}
--- /dev/null
+// 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 = 0;
+
+ virtual SGBoxf computeBoundingBox(const BVHStaticData&) const = 0;
+ virtual SGVec3f computeCenter(const BVHStaticData&) const = 0;
+};
+
+}
+
+#endif
--- /dev/null
+// 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()
+{
+}
+
+}
--- /dev/null
+// 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
--- /dev/null
+// 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();
+}
+
+}
--- /dev/null
+// 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
--- /dev/null
+// 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 <cassert>
+
+#include "BVHNode.hxx"
+#include "BVHGroup.hxx"
+#include "BVHTransform.hxx"
+
+#include "BVHStaticData.hxx"
+
+#include "BVHStaticNode.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.getStartTime());
+ _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 BVHStaticTriangle& node,
+ const BVHStaticData& data)
+{
+ if (!intersects(_sphere, node.getTriangle(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;
+}
+
+}
--- /dev/null
+// 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 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
--- /dev/null
+// 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.
+//
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#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;
+}
+
+}
--- /dev/null
+// 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
--- /dev/null
+// 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 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 BVHStaticTriangle&, const BVHStaticData&) = 0;
+};
+
+}
+
+#endif
--- /dev/null
+include (SimGearComponent)
+
+set(HEADERS
+ BVHBoundingBoxVisitor.hxx
+ BVHGroup.hxx
+ BVHLineGeometry.hxx
+ BVHLineSegmentVisitor.hxx
+ BVHMotionTransform.hxx
+ BVHNearestPointVisitor.hxx
+ BVHNode.hxx
+ BVHStaticBinary.hxx
+ BVHStaticData.hxx
+ BVHStaticGeometry.hxx
+ BVHStaticGeometryBuilder.hxx
+ BVHStaticLeaf.hxx
+ BVHStaticNode.hxx
+ BVHStaticTriangle.hxx
+ BVHSubTreeCollector.hxx
+ BVHTransform.hxx
+ BVHVisitor.hxx
+)
+
+set(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
+)
+
+simgear_component(bvh bvh "${SOURCES}" "${HEADERS}")
+
+if(ENABLE_TESTS)
+ if (SIMGEAR_SHARED)
+ set(TEST_LIBS SimGearCore)
+ else()
+ set(TEST_LIBS sgbvh sgmath sgstructure sgdebug)
+ endif()
+
+ add_executable(bvhtest bvhtest.cxx)
+ target_link_libraries(bvhtest ${TEST_LIBS})
+ add_test(bvhtest ${EXECUTABLE_OUTPUT_PATH}/bvhtest)
+endif(ENABLE_TESTS)
--- /dev/null
+// 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"
+#include "BVHNearestPointVisitor.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;
+}
+
+bool
+testNearestPoint()
+{
+ SGVec3f v1(-1, -1, 0);
+ SGVec3f v2(1, -1, 0);
+ SGVec3f v3(-1, 1, 0);
+ SGSharedPtr<BVHNode> node = buildSingleTriangle(v1, v2, v3);
+
+ SGSphered sphere(SGVec3d(0, 0, -1), 2);
+ {
+ BVHNearestPointVisitor nearestPointVisitor(sphere, 0);
+ node->accept(nearestPointVisitor);
+ if (nearestPointVisitor.empty())
+ return false;
+ if (!equivalent(nearestPointVisitor.getPoint(), SGVec3d(0, 0, 0)))
+ return false;
+ }
+
+ return true;
+}
+
+int
+main(int argc, char** argv)
+{
+ if (!testLineIntersections())
+ return EXIT_FAILURE;
+ if (!testNearestPoint())
+ return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+}
include_directories(${PROJECT_SOURCE_DIR})
foreach( mylibfolder
- bvh
material
model
sky
+++ /dev/null
-// 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 "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 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
+++ /dev/null
-// 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/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 "BVHStaticTriangle.hxx"
-#include "BVHStaticBinary.hxx"
-
-#include "BVHBoundingBoxVisitor.hxx"
-
-namespace simgear {
-
-class BVHNode;
-class BVHStaticNode;
-
-class BVHDebugCollectVisitor : public BVHVisitor {
-public:
- BVHDebugCollectVisitor(const double& time, unsigned level = ~0u) :
- _group(new osg::Group),
- _time(time),
- _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::MatrixTransform> transform = new osg::MatrixTransform;
- transform->setMatrix(osg::Matrix(node.getToWorldTransform(_time).data()));
- _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 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(toOsg(triangle.getVertex(0)));
- vertices->push_back(toOsg(triangle.getVertex(1)));
- vertices->push_back(toOsg(triangle.getVertex(2)));
-
- 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(toOsg(sphere.getCenter()));
- 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(toOsg(bbv.getBox().getCenter()));
- shape->setHalfLengths(toOsg((0.5*bbv.getBox().getSize())));
- 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 double _time;
- const unsigned _level;
- unsigned _currentLevel;
-};
-
-}
-
-#endif
+++ /dev/null
-// 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.
-//
-
-#ifdef HAVE_CONFIG_H
-# include <simgear_config.h>
-#endif
-
-#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;
-}
-
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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;
-}
-
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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.
-//
-
-#ifdef HAVE_CONFIG_H
-# include <simgear_config.h>
-#endif
-
-#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 "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);
- if (!_id)
- _id = transform.getId();
- } 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 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());
- _id = 0;
- _haveHit = true;
-}
-
-
-}
+++ /dev/null
-// 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"
-#include "BVHNode.hxx"
-
-namespace simgear {
-
-class BVHLineSegmentVisitor : public BVHVisitor {
-public:
- BVHLineSegmentVisitor(const SGLineSegmentd& lineSegment,
- const double& t = 0) :
- _lineSegment(lineSegment),
- _time(t),
- _material(0),
- _id(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; }
- BVHNode::Id getId() const
- { return _id; }
-
- 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 BVHStaticTriangle&, const BVHStaticData&);
-
-protected:
- void 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;
- BVHNode::Id _id;
-
- bool _haveHit;
-};
-
-}
-
-#endif
+++ /dev/null
-// 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.
-//
-
-#ifdef HAVE_CONFIG_H
-# include <simgear_config.h>
-#endif
-
-#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),
- _startTime(0),
- _endTime(0),
- _id(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;
- _startTime = transform._startTime;
- _endTime = transform._endTime;
- _id = transform._id;
- 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;
- SGMatrixd toWorldStart = getToWorldTransform(_startTime);
- SGVec3d centerStart = toWorldStart.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 = SGMiscd::max(r, norm(_toWorldReference.xformVec(SGVec3d(0, 1, 0))));
- r = SGMiscd::max(r, norm(_toWorldReference.xformVec(SGVec3d(0, 0, 1))));
- _toWorldAmplification = r;
-
- r = norm(_toLocalReference.xformVec(SGVec3d(1, 0, 0)));
- r = SGMiscd::max(r, norm(_toLocalReference.xformVec(SGVec3d(0, 1, 0))));
- r = SGMiscd::max(r, norm(_toLocalReference.xformVec(SGVec3d(0, 0, 1))));
- _toLocalAmplification = r;
-}
-
-}
+++ /dev/null
-// 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 setStartTime(const double& startTime)
- { _startTime = startTime; }
- const double& getStartTime() const
- { return _startTime; }
-
- void setEndTime(const double& endTime)
- { _endTime = endTime; }
- const double& getEndTime() const
- { return _endTime; }
-
- SGMatrixd getToWorldTransform(const double& t) const
- {
- if (t == _referenceTime)
- return _toWorldReference;
- double dt = t - _referenceTime;
- SGMatrixd matrix(_toWorldReference);
- matrix.postMultRotate(SGQuatd::fromAngleAxis(dt*_angularVelocity));
- matrix.postMultTranslate(dt*_linearVelocity);
- return matrix;
- }
- SGMatrixd getToLocalTransform(const double& t) const
- {
- if (t == _referenceTime)
- return _toLocalReference;
- double dt = _referenceTime - t;
- 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);
- }
-
- void setId(Id id)
- { _id = id; }
- Id getId() const
- { return _id; }
-
-private:
- virtual SGSphered computeBoundingSphere() const;
- void updateAmplificationFactors();
-
- SGMatrixd _toWorldReference;
- SGMatrixd _toLocalReference;
- double _toWorldAmplification;
- double _toLocalAmplification;
-
- SGVec3d _linearVelocity;
- SGVec3d _angularVelocity;
-
- double _referenceTime;
- double _startTime;
- double _endTime;
-
- Id _id;
-};
-
-}
-
-#endif
+++ /dev/null
-// 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 BVHNearestPointVisitor_hxx
-#define BVHNearestPointVisitor_hxx
-
-#include <simgear/math/SGGeometry.hxx>
-
-#include "BVHVisitor.hxx"
-
-#include "BVHNode.hxx"
-#include "BVHGroup.hxx"
-#include "BVHTransform.hxx"
-#include "BVHLineGeometry.hxx"
-#include "BVHStaticGeometry.hxx"
-
-#include "BVHStaticData.hxx"
-
-#include "BVHStaticNode.hxx"
-#include "BVHStaticTriangle.hxx"
-#include "BVHStaticBinary.hxx"
-
-namespace simgear {
-
-class BVHNearestPointVisitor : public BVHVisitor {
-public:
- BVHNearestPointVisitor(const SGSphered& sphere, const double& t) :
- _sphere(sphere),
- _time(t),
- _material(0),
- _id(0),
- _havePoint(false)
- { }
-
- virtual void apply(BVHGroup& leaf)
- {
- if (!intersects(_sphere, leaf.getBoundingSphere()))
- return;
- leaf.traverse(*this);
- }
- virtual void apply(BVHTransform& transform)
- {
- if (!intersects(_sphere, transform.getBoundingSphere()))
- return;
-
- SGSphered sphere = _sphere;
- _sphere = transform.sphereToLocal(sphere);
- bool havePoint = _havePoint;
- _havePoint = false;
-
- transform.traverse(*this);
-
- if (_havePoint) {
- _point = transform.ptToWorld(_point);
- _linearVelocity = transform.vecToWorld(_linearVelocity);
- _angularVelocity = transform.vecToWorld(_angularVelocity);
- }
- _havePoint |= havePoint;
- _sphere.setCenter(sphere.getCenter());
- }
- virtual void apply(BVHMotionTransform& transform)
- {
- if (!intersects(_sphere, transform.getBoundingSphere()))
- return;
-
- SGSphered sphere = _sphere;
- _sphere = transform.sphereToLocal(sphere, _time);
- bool havePoint = _havePoint;
- _havePoint = false;
-
- transform.traverse(*this);
-
- if (_havePoint) {
- SGMatrixd toWorld = transform.getToWorldTransform(_time);
- SGVec3d localCenter = _sphere.getCenter();
- _linearVelocity += transform.getLinearVelocityAt(localCenter);
- _angularVelocity += transform.getAngularVelocity();
- _linearVelocity = toWorld.xformVec(_linearVelocity);
- _angularVelocity = toWorld.xformVec(_angularVelocity);
- _point = toWorld.xformPt(_point);
- if (!_id)
- _id = transform.getId();
- }
- _havePoint |= havePoint;
- _sphere.setCenter(sphere.getCenter());
- }
- virtual void apply(BVHLineGeometry& node)
- { }
- virtual void apply(BVHStaticGeometry& node)
- {
- if (!intersects(_sphere, node.getBoundingSphere()))
- return;
- node.traverse(*this);
- }
-
- virtual void apply(const BVHStaticBinary& node, const BVHStaticData& data)
- {
- if (!intersects(_sphere, node.getBoundingBox()))
- return;
- node.traverse(*this, data, _sphere.getCenter());
- }
- virtual void apply(const BVHStaticTriangle& node, const BVHStaticData& data)
- {
- SGVec3f center(_sphere.getCenter());
- SGVec3d closest(closestPoint(node.getTriangle(data), center));
- if (!intersects(_sphere, closest))
- return;
- _point = closest;
- _linearVelocity = SGVec3d::zeros();
- _angularVelocity = SGVec3d::zeros();
- _material = data.getMaterial(node.getMaterialIndex());
- // The trick is to decrease the radius of the search sphere.
- _sphere.setRadius(length(closest - _sphere.getCenter()));
- _havePoint = true;
- _id = 0;
- }
-
- void setSphere(const SGSphered& sphere)
- { _sphere = sphere; }
- const SGSphered& getSphere() const
- { return _sphere; }
-
- const SGVec3d& getPoint() const
- { return _point; }
- const SGVec3d& getLinearVelocity() const
- { return _linearVelocity; }
- const SGVec3d& getAngularVelocity() const
- { return _angularVelocity; }
- const SGMaterial* getMaterial() const
- { return _material; }
- BVHNode::Id getId() const
- { return _id; }
-
- bool empty() const
- { return !_havePoint; }
-
-private:
- SGSphered _sphere;
- double _time;
-
- SGVec3d _point;
- SGVec3d _linearVelocity;
- SGVec3d _angularVelocity;
- const SGMaterial* _material;
- BVHNode::Id _id;
-
- bool _havePoint;
-};
-
-}
-
-#endif
+++ /dev/null
-// 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/structure/SGAtomic.hxx>
-#include <simgear/math/SGGeometry.hxx>
-
-namespace simgear {
-
-BVHNode::BVHNode() :
- _dirtyBoundingSphere(true)
-{
-}
-
-BVHNode::~BVHNode()
-{
-}
-
-BVHNode::Id
-BVHNode::getNewId()
-{
- static SGAtomic id(0);
- return ++id;
-}
-
-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;
-}
-
-}
+++ /dev/null
-// 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;
-
- /// A unique id for some kind of BVHNodes.
- /// Currently only motions transforms.
- typedef unsigned Id;
-
- // Factory to get a new id
- static Id getNewId();
-
-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
+++ /dev/null
-// 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);
-}
-
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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]; }
-
- void trim()
- {
- std::vector<SGVec3f>(_vertices).swap(_vertices);
- std::vector<const SGMaterial*>(_materials).swap(_materials);
- }
-
-private:
- std::vector<SGVec3f> _vertices;
- std::vector<const SGMaterial*> _materials;
-};
-
-}
-
-#endif
+++ /dev/null
-// 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;
-}
-
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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 <algorithm>
-#include <map>
-#include <set>
-
-#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;
-
- typedef std::set<SGVec3<unsigned> > TriangleSet;
- TriangleSet _triangleSet;
-
- 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) };
- std::sort(indices, indices + 3);
- SGVec3<unsigned> indexKey(indices);
- if (_triangleSet.find(indexKey) != _triangleSet.end())
- return;
- _triangleSet.insert(indexKey);
- 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;
- _staticData->trim();
- 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
+++ /dev/null
-// 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()
-{
-}
-
-}
+++ /dev/null
-// 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 = 0;
-
- virtual SGBoxf computeBoundingBox(const BVHStaticData&) const = 0;
- virtual SGVec3f computeCenter(const BVHStaticData&) const = 0;
-};
-
-}
-
-#endif
+++ /dev/null
-// 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()
-{
-}
-
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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();
-}
-
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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 <cassert>
-
-#include "BVHNode.hxx"
-#include "BVHGroup.hxx"
-#include "BVHTransform.hxx"
-
-#include "BVHStaticData.hxx"
-
-#include "BVHStaticNode.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.getStartTime());
- _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 BVHStaticTriangle& node,
- const BVHStaticData& data)
-{
- if (!intersects(_sphere, node.getTriangle(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;
-}
-
-}
+++ /dev/null
-// 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 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
+++ /dev/null
-// 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.
-//
-
-#ifdef HAVE_CONFIG_H
-# include <simgear_config.h>
-#endif
-
-#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;
-}
-
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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 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 BVHStaticTriangle&, const BVHStaticData&) = 0;
-};
-
-}
-
-#endif
+++ /dev/null
-include (SimGearComponent)
-
-set(HEADERS
- BVHBoundingBoxVisitor.hxx
- BVHDebugCollectVisitor.hxx
- BVHGroup.hxx
- BVHLineGeometry.hxx
- BVHLineSegmentVisitor.hxx
- BVHMotionTransform.hxx
- BVHNearestPointVisitor.hxx
- BVHNode.hxx
- BVHStaticBinary.hxx
- BVHStaticData.hxx
- BVHStaticGeometry.hxx
- BVHStaticGeometryBuilder.hxx
- BVHStaticLeaf.hxx
- BVHStaticNode.hxx
- BVHStaticTriangle.hxx
- BVHSubTreeCollector.hxx
- BVHTransform.hxx
- BVHVisitor.hxx
- )
-
-set(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
- )
-
-simgear_scene_component(bvh scene/bvh "${SOURCES}" "${HEADERS}")
+++ /dev/null
-// 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"
-#include "BVHNearestPointVisitor.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;
-}
-
-bool
-testNearestPoint()
-{
- SGVec3f v1(-1, -1, 0);
- SGVec3f v2(1, -1, 0);
- SGVec3f v3(-1, 1, 0);
- SGSharedPtr<BVHNode> node = buildSingleTriangle(v1, v2, v3);
-
- SGSphered sphere(SGVec3d(0, 0, -1), 2);
- {
- BVHNearestPointVisitor nearestPointVisitor(sphere, 0);
- node->accept(nearestPointVisitor);
- if (nearestPointVisitor.empty())
- return false;
- if (!equivalent(nearestPointVisitor.getPoint(), SGVec3d(0, 0, 0)))
- return false;
- }
-
- return true;
-}
-
-int
-main(int argc, char** argv)
-{
- if (!testLineIntersections())
- return EXIT_FAILURE;
- if (!testNearestPoint())
- return EXIT_FAILURE;
- return EXIT_SUCCESS;
-}
--- /dev/null
+// 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/ShapeDrawable>
+#include <osg/Shape>
+#include <osg/Depth>
+#include <osg/BlendFunc>
+#include <osg/StateSet>
+
+#include <simgear/math/SGGeometry.hxx>
+#include <simgear/scene/util/OsgMath.hxx>
+
+#include <simgear/bvh/BVHVisitor.hxx>
+#include <simgear/bvh/BVHNode.hxx>
+#include <simgear/bvh/BVHGroup.hxx>
+#include <simgear/bvh/BVHTransform.hxx>
+#include <simgear/bvh/BVHMotionTransform.hxx>
+#include <simgear/bvh/BVHStaticGeometry.hxx>
+
+#include <simgear/bvh/BVHStaticData.hxx>
+
+#include <simgear/bvh/BVHStaticNode.hxx>
+#include <simgear/bvh/BVHStaticTriangle.hxx>
+#include <simgear/bvh/BVHStaticBinary.hxx>
+
+#include <simgear/bvh/BVHBoundingBoxVisitor.hxx>
+
+namespace simgear {
+
+class BVHNode;
+class BVHStaticNode;
+
+class BVHDebugCollectVisitor : public BVHVisitor {
+public:
+ BVHDebugCollectVisitor(const double& time, unsigned level = ~0u) :
+ _group(new osg::Group),
+ _time(time),
+ _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::MatrixTransform> transform = new osg::MatrixTransform;
+ transform->setMatrix(osg::Matrix(node.getToWorldTransform(_time).data()));
+ _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 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(toOsg(triangle.getVertex(0)));
+ vertices->push_back(toOsg(triangle.getVertex(1)));
+ vertices->push_back(toOsg(triangle.getVertex(2)));
+
+ 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(toOsg(sphere.getCenter()));
+ 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(toOsg(bbv.getBox().getCenter()));
+ shape->setHalfLengths(toOsg((0.5*bbv.getBox().getSize())));
+ 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 double _time;
+ const unsigned _level;
+ unsigned _currentLevel;
+};
+
+}
+
+#endif
#include <simgear/scene/util/SGSceneUserData.hxx>
#include <simgear/math/SGGeometry.hxx>
-#include <simgear/scene/bvh/BVHStaticGeometryBuilder.hxx>
+#include <simgear/bvh/BVHStaticGeometryBuilder.hxx>
namespace simgear {
set(HEADERS
BoundingVolumeBuildVisitor.hxx
+ BVHDebugCollectVisitor.hxx
CheckSceneryVisitor.hxx
ConditionNode.hxx
ModelRegistry.hxx
#include <osg/NodeVisitor>
#include <osg/TemplatePrimitiveFunctor>
+#include <simgear/bvh/BVHGroup.hxx>
+#include <simgear/bvh/BVHLineGeometry.hxx>
#include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/SGSceneUserData.hxx>
-#include <simgear/scene/bvh/BVHGroup.hxx>
-#include <simgear/scene/bvh/BVHLineGeometry.hxx>
class SGInteractionAnimation::LineCollector : public osg::NodeVisitor {
struct LinePrimitiveFunctor {
#include <vector>
#include <osg/Node>
#include <osg/Object>
-#include <simgear/scene/bvh/BVHNode.hxx>
+#include <simgear/bvh/BVHNode.hxx>
#include "SGPickCallback.hxx"
class SGSceneUserData : public osg::Object {