TriangleMesh.h

00001 /****************************************************************************
00002  * Copyright 2005 Evan Drumwright
00003  * This library is distributed under the terms of the GNU General Public 
00004  * License (found in COPYING).
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 }; // end class
00048 
00049 /***************************************************************
00050  * Template methods follow
00051  **************************************************************/
00053 
00056 template <class ForwardIterator>
00057 void TriangleMesh::get_unique_vertices(ForwardIterator first, ForwardIterator last, std::list<Vector3ConstPtr>& result)
00058 {
00059         // clear result
00060         result.clear();
00061 
00062         // get the vertices from all triangles
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         // sort the list and make it unique
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         // we'll reuse iterators for speed -- we want to pickup where left off
00084         // if point is outside the mesh
00085         ForwardIterator i;
00086 
00087         // initialize minimum distance
00088         Real min_dist = std::numeric_limits<Real>::max();
00089 
00090         // first, determine whether the point is inside or outside
00091         bool inside = true;
00092         for (i = first; i != last; i++)
00093         {
00094                 // compute the projected distance to the i'th face
00095                 Real proj_dist = Vector3::dot((*i)->normal(), point) - (*i)->get_d();
00096 
00097                 // if distance is positive, the point is visible from the face
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         // if the point is outside, recompute the distance 
00111         if (!inside)
00112         {
00113                 // reset the minimum distance
00114                 min_dist = std::numeric_limits<Real>::max();
00115 
00116                 // only calculate distance for the faces from which this point is 
00117                 // visible, since distance computation is expensive; note that we pick
00118                 // up where left off 
00119                 for (; i != last; i++)
00120                 {
00121                         // compute the distance to the i'th face
00122                         Real proj_dist = Vector3::dot((*i)->normal(), point) - (*i)->get_d();
00123         
00124                         // only compute distance for non-visible faces
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         // return the distance
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         // init a pointer to the closest triangle that we will not use..
00150         TriangleConstPtr pointer;
00151         return calc_signed_distance(first, last, point, pointer);
00152 }
00153 
00154 } // end namespace 
00155 
00156 #endif
00157 

Generated on Wed Oct 24 14:54:22 2007 for Physsim by  doxygen 1.5.1