tesselate.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This program is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU General Public License as published by the Free  *
00007 * Software Foundation; either version 2 of the License, or (at your option)   *
00008 * any later version.                                                          *
00009 *                                                                             *
00010 * This program is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
00013 * more details.                                                               *
00014 *                                                                             *
00015 * You should have received a copy of the GNU General Public License along     *
00016 * with this program; if not, write to the Free Software Foundation, Inc., 51  *
00017 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
00018 *******************************************************************************
00019 *                            SOFA :: Applications                             *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #include <math.h>
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 
00031 #include <flowvr/render/mesh.h>
00032 
00033 using namespace flowvr::render;
00034 using ftl::Vec3f;
00035 
00036 void projectOnSphere(Vec3f& p, Vec3f center, float radius)
00037 {
00038     p -= center;
00039     p = p * (radius / p.norm());
00040     p += center;
00041 }
00042 
00043 void projectOnSphere(Vec3f& p,Vec3f& n, Vec3f center, float radius)
00044 {
00045     p -= center;
00046     n = p;
00047     n.normalize();
00048     p = p * (radius / p.norm());
00049     p += center;
00050 }
00051 
00052 void tesselateMesh(Mesh& obj, int rec=1, bool onSphere=false)
00053 {
00054     BBox bb = obj.calcBBox();
00055     std::cout << "Mesh bbox="<<bb<<std::endl;
00056     
00057     std::cout << "Flipping mesh..."<<std::endl;
00058     obj.calcFlip();
00059     obj.calcEdges();
00060     bool closed = obj.isClosed();
00061     std::cout << "Mesh is "<<(closed?"":"NOT ")<<"closed."<<std::endl;
00062     
00063     Vec3f center; Vec3f radius;
00064     if (onSphere)
00065     {
00066         center = (bb.b+bb.a)/2;
00067         radius = (bb.b-bb.a)/2;
00068     }
00069 
00070     if (rec == 0 && onSphere)
00071     {
00072     for(int i=0;i<obj.nbp();i++)
00073         projectOnSphere(obj.PP(i),obj.PN(i),center,radius[0]);
00074     obj.calcNormals();
00075     return;
00076     }
00077 
00078   bool groups = obj.getAttrib(Mesh::MESH_POINTS_GROUP);
00079   if (!groups)
00080   {
00081       std::cout << "Creating artificial groups."<<std::endl;
00082       // create artificial groups
00083       for(int i=0;i<obj.nbp();i++)
00084       {
00085       obj.PG(i) = i;
00086       obj.GP0(i) = i;
00087       }
00088       obj.setAttrib(Mesh::MESH_POINTS_GROUP,true);
00089   }
00090 
00091   std::cout << "Input mesh: "<<obj.nbp()<<" points, "<<obj.nbf()<<" faces."<<std::endl;
00092 
00093   for (int r=0;r<rec;r++)
00094   {
00095       std::cout << "Tesselation level "<<r+1<<"..."<<std::endl;
00096       obj.calcEdges();
00097 
00098       std::cout << "Creating new points..."<<std::endl;
00099       // first create a new point on each edge
00100       for(int e1 = 0 ; e1 < (int)obj.edges.size(); ++e1)
00101       {
00102       int g1 = obj.getPG(e1);
00103       for(std::map< int,Mesh::Edge >::iterator it = obj.edges[e1].begin(), itend = obj.edges[e1].end(); it != itend; ++it)
00104       {
00105           int g2 = obj.getPG(it->first);
00106 
00107           int f1p1 = -1, f1p2 = -1;
00108           int f2p1 = -1, f2p2 = -1;
00109           int i1 = -1;
00110           if (it->second.f1 >= 0)
00111           {
00112           Vec3i fp = obj.getFP(it->second.f1);
00113           f1p1 = fp[0], f1p2 = fp[1];
00114           if (obj.getPG(f1p1) != g1)
00115           {
00116               f1p1 = fp[1]; f1p2 = fp[2];
00117               if (obj.getPG(f1p1) != g1)
00118               {
00119               f1p1 = fp[2]; f1p2 = fp[0]; // this is the last possible edge
00120               }
00121           }
00122           if (obj.getPG(f1p1) != g1 || (obj.getPG(f1p2) != g2))
00123           {
00124               std::cerr << "ERROR: Edge "<<g1<<" - "<<g2<<" not found on face 1 ( "<<it->second.f1<<" = "<<fp<<" = "<<Vec3i(obj.getPG(fp[0]),obj.getPG(fp[1]),obj.getPG(fp[2]))<<" )"<<std::endl;
00125               it->second.f1 = -1;
00126               continue;
00127           }
00128           Mesh::Vertex v;
00129           v = obj.getP(f1p1);
00130           v += obj.getP(f1p2);
00131           v.mean(2);
00132                   //if (onSphere) v.p = projectOnSphere(v.p, center, radius[0]);
00133           i1 = obj.addP(v);
00134           // replace the face index with the new point index
00135           it->second.f1 = i1;
00136           }
00137           
00138           if (it->second.f2 >= 0)
00139           {
00140           Vec3i fp = obj.getFP(it->second.f2);
00141           f2p1 = fp[0], f2p2 = fp[1];
00142           if (obj.getPG(f2p1) != g2)
00143           {
00144               f2p1 = fp[1]; f2p2 = fp[2];
00145               if (obj.getPG(f2p1) != g2)
00146               {
00147               f2p1 = fp[2]; f2p2 = fp[0]; // this is the last possible edge
00148               }
00149           }
00150           if (obj.getPG(f2p1) != g2 || (obj.getPG(f2p2) != g1))
00151           {
00152               std::cerr << "ERROR: Edge "<<g1<<" - "<<g2<<" not found on face 2 ( "<<it->second.f2<<" = "<<fp<<" = "<<Vec3i(obj.getPG(fp[0]),obj.getPG(fp[1]),obj.getPG(fp[2]))<<" )"<<std::endl;
00153               it->second.f2 = -1;
00154               continue;
00155           }
00156           if (f1p1 == f2p2 && f1p2 == f2p1)
00157           { // same point as other face
00158               it->second.f2 = i1;
00159           }
00160           else
00161           {
00162               Mesh::Vertex v;
00163               v = obj.getP(f2p1);
00164               v += obj.getP(f2p2);
00165               v.mean(2);
00166                       //if (onSphere) v.p = projectOnSphere(v.p, center, radius[0]);
00167               int i2;
00168               if (i1 == -1) // no other edge, create a new group
00169               i2 = obj.addP(v);
00170               else
00171               {
00172               // see of all points are on the same subgroup
00173               int gf1p1 = g1;
00174               while (obj.getGP0(gf1p1+1) <= -f1p1) ++gf1p1;
00175               int gf1p2 = g2;
00176               while (obj.getGP0(gf1p2+1) <= -f1p2) ++gf1p2;
00177               int gf2p1 = g2;
00178               while (obj.getGP0(gf2p1+1) <= -f2p1) ++gf2p1;
00179               int gf2p2 = g1;
00180               while (obj.getGP0(gf2p2+1) <= -f2p2) ++gf2p2;
00181               int g = obj.getPG(i1);
00182               i2 = obj.addP(v,g);
00183               if (gf1p1 != gf2p2 || gf1p2 != gf2p1)
00184               { // create a subgroup
00185                   obj.GP0(obj.nbg()) = -i2;
00186               }
00187               }
00188               // replace the face index with the new point index
00189               it->second.f2 = i2;
00190           }
00191           }
00192       }
00193       }
00194 
00195       // then create new faces
00196       std::cout << "Creating new faces..."<<std::endl;
00197       std::vector<Vec3i> faces_p;
00198       int nbf0 = obj.nbf();
00199       faces_p.reserve(nbf0*4);
00200       for(int i=0; i<nbf0; ++i)
00201       {
00202       Vec3i points = obj.getFP(i);
00203       Vec3i edges;
00204       edges[0] = obj.getEdgeFace(points[0],points[1]);
00205       edges[1] = obj.getEdgeFace(points[1],points[2]);
00206       edges[2] = obj.getEdgeFace(points[2],points[0]);
00207       if ((unsigned)edges[0] >= (unsigned)obj.nbp() || (unsigned)edges[1] >= (unsigned)obj.nbp() || (unsigned)edges[2] >= (unsigned)obj.nbp())
00208       {
00209           std::cerr << "ERROR: invalid edge points " << edges << " in face " <<i<<" = "<<points<<std::endl;
00210           continue;
00211       }
00212       faces_p.push_back(Vec3i(edges[2],points[0],edges[0]));
00213       faces_p.push_back(Vec3i(edges[0],points[1],edges[1]));
00214       faces_p.push_back(Vec3i(edges[2],edges[0],edges[1]));
00215       faces_p.push_back(Vec3i(edges[1],points[2],edges[2]));
00216       }
00217       obj.faces_p = faces_p;
00218 
00219       // finally we update the material groups
00220       std::cout << "Updating materials..."<<std::endl;
00221       for(unsigned int i=0; i<obj.mat_groups.size(); ++i)
00222       {
00223       obj.mat_groups[i].f0 *= 4;
00224       obj.mat_groups[i].nbf *= 4;
00225       }
00226       // and we recompute the edges
00227       if (r < rec-1)
00228       {
00229       std::cout << "Updating edges..."<<std::endl;
00230       obj.calcEdges();
00231       bool closed = obj.isClosed();
00232       std::cout << "Mesh is "<<(closed?"":"NOT ")<<"closed."<<std::endl;
00233       }
00234       if (onSphere)
00235       {
00236           for(int i=0;i<obj.nbp();i++)
00237               projectOnSphere(obj.PP(i),obj.PN(i),center,radius[0]);
00238           obj.calcNormals();
00239       }
00240       std::cout << "Tesselation level "<<r<<" DONE: "<<obj.nbp()<<" points, "<<obj.nbf()<<" faces."<<std::endl;
00241   }
00242   if (!groups)
00243   {
00244       // remove artificial groups
00245       obj.setAttrib(Mesh::MESH_POINTS_GROUP,false);
00246   }
00247   obj.calcNormals();
00248 }

Generated on Sun Nov 23 02:28:34 2008 for Sofa by  doxygen 1.5.7.1