tesselate.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
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];
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
00133 i1 = obj.addP(v);
00134
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];
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 {
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
00167 int i2;
00168 if (i1 == -1)
00169 i2 = obj.addP(v);
00170 else
00171 {
00172
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 {
00185 obj.GP0(obj.nbg()) = -i2;
00186 }
00187 }
00188
00189 it->second.f2 = i2;
00190 }
00191 }
00192 }
00193 }
00194
00195
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
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
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
00245 obj.setAttrib(Mesh::MESH_POINTS_GROUP,false);
00246 }
00247 obj.calcNormals();
00248 }