00001
00002
00003
00004
00005
00006
00007 #ifndef _TRIANGLE_MESH_H
00008 #define _TRIANGLE_MESH_H
00009
00010 #include <iostream>
00011 #include <cmath>
00012 #include <list>
00013 #include <string>
00014 #include <Physsim/Types.h>
00015 #include <Physsim/Triangle.h>
00016 #include <Physsim/Primitive.h>
00017 #include <Physsim/CompGeom.h>
00018
00019 namespace Physsim {
00020
00022 class TriangleMesh : public Primitive
00023 {
00024 public:
00025 TriangleMesh() {}
00026 TriangleMesh(TriangleArrayConstPtr trimesh, bool center = true);
00027 TriangleMesh(TriangleArrayConstPtr trimesh, const Matrix4& T, bool center = true);
00028 TriangleMesh(const std::string& filename, bool center = true);
00029 TriangleMesh(const std::string& filename, const Matrix4& T, bool center = true);
00030 virtual void load_from_xml(XMLTreeConstPtr node, std::map<std::string, BasePtr>& id_map);
00031 virtual void save_to_xml(XMLTreePtr node, std::list<BaseConstPtr>& shared_objects) const;
00032 static void write_to_obj(const std::string& filename, const std::vector<TriangleConstPtr>& mesh);
00033 static TriangleArrayConstPtr read_from_obj(const std::string& filename);
00034 static void transform_mesh(const std::vector<TrianglePtr>& mesh, const Matrix4& T);
00035 static void subdivide(std::vector<TrianglePtr>& mesh, Real max_tri_area);
00036 static TriangleArrayPtr clone_mesh(const std::vector<TriangleConstPtr>& mesh);
00037
00038
00039 template <class ForwardIterator>
00040 static void get_unique_vertices(ForwardIterator first, ForwardIterator last, std::list<Vector3ConstPtr>& result);
00041
00042 template <class ForwardIterator>
00043 static Real calc_signed_distance(ForwardIterator first, ForwardIterator last, const Vector3& point, TriangleConstPtr& closest_tri);
00044
00045 template <class ForwardIterator>
00046 static Real calc_signed_distance(ForwardIterator first, ForwardIterator last, const Vector3& point);
00047 };
00048
00049
00050
00051
00053
00056 template <class ForwardIterator>
00057 void TriangleMesh::get_unique_vertices(ForwardIterator first, ForwardIterator last, std::list<Vector3ConstPtr>& result)
00058 {
00059
00060 result.clear();
00061
00062
00063 for (ForwardIterator i = first; i != last; i++)
00064 {
00065 result.push_back((*i)->a());
00066 result.push_back((*i)->b());
00067 result.push_back((*i)->c());
00068 }
00069
00070
00071 result.erase(std::unique(result.begin(), result.end()), result.end());
00072 }
00073
00075
00080 template <class ForwardIterator>
00081 Real TriangleMesh::calc_signed_distance(ForwardIterator first, ForwardIterator last, const Vector3& point, TriangleConstPtr& closest_tri)
00082 {
00083
00084
00085 ForwardIterator i;
00086
00087
00088 Real min_dist = std::numeric_limits<Real>::max();
00089
00090
00091 bool inside = true;
00092 for (i = first; i != last; i++)
00093 {
00094
00095 Real proj_dist = Vector3::dot((*i)->normal(), point) - (*i)->get_d();
00096
00097
00098 if (proj_dist > NEAR_ZERO)
00099 {
00100 inside = false;
00101 break;
00102 }
00103 else if (proj_dist < min_dist)
00104 {
00105 min_dist = proj_dist;
00106 closest_tri = *i;
00107 }
00108 }
00109
00110
00111 if (!inside)
00112 {
00113
00114 min_dist = std::numeric_limits<Real>::max();
00115
00116
00117
00118
00119 for (; i != last; i++)
00120 {
00121
00122 Real proj_dist = Vector3::dot((*i)->normal(), point) - (*i)->get_d();
00123
00124
00125 if (proj_dist > NEAR_ZERO)
00126 {
00127 Vector3 closest_point;
00128 Real dist = (*i)->calc_distance(point, closest_point);
00129 if (dist < min_dist)
00130 {
00131 min_dist = dist;
00132 closest_tri = *i;
00133 }
00134 }
00135 }
00136 }
00137
00138
00139 return min_dist;
00140 }
00142
00146 template <class ForwardIterator>
00147 Real TriangleMesh::calc_signed_distance(ForwardIterator first, ForwardIterator last, const Vector3& point)
00148 {
00149
00150 TriangleConstPtr pointer;
00151 return calc_signed_distance(first, last, point, pointer);
00152 }
00153
00154 }
00155
00156 #endif
00157