00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef BVHNearestPointVisitor_hxx
00019 #define BVHNearestPointVisitor_hxx
00020
00021 #include <simgear/math/SGGeometry.hxx>
00022
00023 #include "BVHVisitor.hxx"
00024
00025 #include "BVHNode.hxx"
00026 #include "BVHGroup.hxx"
00027 #include "BVHTransform.hxx"
00028 #include "BVHLineGeometry.hxx"
00029 #include "BVHStaticGeometry.hxx"
00030
00031 #include "BVHStaticData.hxx"
00032
00033 #include "BVHStaticNode.hxx"
00034 #include "BVHStaticTriangle.hxx"
00035 #include "BVHStaticBinary.hxx"
00036
00037 namespace simgear {
00038
00039 class BVHNearestPointVisitor : public BVHVisitor {
00040 public:
00041 BVHNearestPointVisitor(const SGSphered& sphere, const double& t) :
00042 _sphere(sphere),
00043 _time(t),
00044 _material(0),
00045 _id(0),
00046 _havePoint(false)
00047 { }
00048
00049 virtual void apply(BVHGroup& leaf)
00050 {
00051 if (!intersects(_sphere, leaf.getBoundingSphere()))
00052 return;
00053 leaf.traverse(*this);
00054 }
00055 virtual void apply(BVHTransform& transform)
00056 {
00057 if (!intersects(_sphere, transform.getBoundingSphere()))
00058 return;
00059
00060 SGSphered sphere = _sphere;
00061 _sphere = transform.sphereToLocal(sphere);
00062 bool havePoint = _havePoint;
00063 _havePoint = false;
00064
00065 transform.traverse(*this);
00066
00067 if (_havePoint) {
00068 _point = transform.ptToWorld(_point);
00069 _linearVelocity = transform.vecToWorld(_linearVelocity);
00070 _angularVelocity = transform.vecToWorld(_angularVelocity);
00071 }
00072 _havePoint |= havePoint;
00073 _sphere.setCenter(sphere.getCenter());
00074 }
00075 virtual void apply(BVHMotionTransform& transform)
00076 {
00077 if (!intersects(_sphere, transform.getBoundingSphere()))
00078 return;
00079
00080 SGSphered sphere = _sphere;
00081 _sphere = transform.sphereToLocal(sphere, _time);
00082 bool havePoint = _havePoint;
00083 _havePoint = false;
00084
00085 transform.traverse(*this);
00086
00087 if (_havePoint) {
00088 SGMatrixd toWorld = transform.getToWorldTransform(_time);
00089 SGVec3d localCenter = _sphere.getCenter();
00090 _linearVelocity += transform.getLinearVelocityAt(localCenter);
00091 _angularVelocity += transform.getAngularVelocity();
00092 _linearVelocity = toWorld.xformVec(_linearVelocity);
00093 _angularVelocity = toWorld.xformVec(_angularVelocity);
00094 _point = toWorld.xformPt(_point);
00095 if (!_id)
00096 _id = transform.getId();
00097 }
00098 _havePoint |= havePoint;
00099 _sphere.setCenter(sphere.getCenter());
00100 }
00101 virtual void apply(BVHLineGeometry& node)
00102 { }
00103 virtual void apply(BVHStaticGeometry& node)
00104 {
00105 if (!intersects(_sphere, node.getBoundingSphere()))
00106 return;
00107 node.traverse(*this);
00108 }
00109
00110 virtual void apply(const BVHStaticBinary& node, const BVHStaticData& data)
00111 {
00112 if (!intersects(_sphere, node.getBoundingBox()))
00113 return;
00114 node.traverse(*this, data, _sphere.getCenter());
00115 }
00116 virtual void apply(const BVHStaticTriangle& node, const BVHStaticData& data)
00117 {
00118 SGVec3f center(_sphere.getCenter());
00119 SGVec3d closest(closestPoint(node.getTriangle(data), center));
00120 if (!intersects(_sphere, closest))
00121 return;
00122 _point = closest;
00123 _linearVelocity = SGVec3d::zeros();
00124 _angularVelocity = SGVec3d::zeros();
00125 _material = data.getMaterial(node.getMaterialIndex());
00126
00127 _sphere.setRadius(length(closest - _sphere.getCenter()));
00128 _havePoint = true;
00129 _id = 0;
00130 }
00131
00132 void setSphere(const SGSphered& sphere)
00133 { _sphere = sphere; }
00134 const SGSphered& getSphere() const
00135 { return _sphere; }
00136
00137 const SGVec3d& getPoint() const
00138 { return _point; }
00139 const SGVec3d& getLinearVelocity() const
00140 { return _linearVelocity; }
00141 const SGVec3d& getAngularVelocity() const
00142 { return _angularVelocity; }
00143 const SGMaterial* getMaterial() const
00144 { return _material; }
00145 BVHNode::Id getId() const
00146 { return _id; }
00147
00148 bool empty() const
00149 { return !_havePoint; }
00150
00151 private:
00152 SGSphered _sphere;
00153 double _time;
00154
00155 SGVec3d _point;
00156 SGVec3d _linearVelocity;
00157 SGVec3d _angularVelocity;
00158 const SGMaterial* _material;
00159 BVHNode::Id _id;
00160
00161 bool _havePoint;
00162 };
00163
00164 }
00165
00166 #endif