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
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include <math.h>
00054 #include <stdlib.h>
00055 #include <stdio.h>
00056
00057 #include <ftl/cmdline.h>
00058 #include <flowvr/render/mesh.h>
00059
00060 using namespace flowvr::render;
00061
00062 extern void tesselateMesh(Mesh& obj, int rec=1, bool onSphere=false);
00063
00064 int main(int argc, char** argv)
00065 {
00066 bool normalize = false;
00067 bool flip = false;
00068 bool wnormals = false;
00069 bool rnormals = false;
00070 bool rtexcoords = false;
00071 bool closemesh = false;
00072 Vec3f translation;
00073 Vec3f rotation;
00074 Vec3f scale(1,1,1);
00075 float dilate = 0.0f;
00076 int tesselate = 0;
00077 bool sphere = false;
00078 bool dist = false;
00079 int res = 16;
00080 int rx=0,ry=0,rz=0;
00081 float border = 0.25f;
00082 ftl::CmdLine cmd("Usage: meshconv [options] mesh.input [mesh.output]");
00083 cmd.opt("normalize",'n',"transform points so that the center is at <0,0,0> and the max coodinate is 1",&normalize);
00084 cmd.opt("flip",'f',"flip normals",&flip);
00085 cmd.opt("wnormals",'N',"force writing of normals",&wnormals);
00086 cmd.opt("rnormals",'O',"remove normals",&rnormals);
00087 cmd.opt("rtexcoords",'T',"remove texcoords",&rtexcoords);
00088 cmd.opt("close",'c',"close mesh",&closemesh);
00089 cmd.opt("translate",'t',"translate the mesh",&translation);
00090 cmd.opt("rotate",'r',"rotate the mesh using euler angles in degree",&rotation);
00091 cmd.opt("scale",'s',"scale the mesh using 3 coefficients",&scale);
00092 cmd.opt("dilate",'d',"dilate (i.e. displace vertices of the given distance along their normals)",&dilate);
00093 cmd.opt("tesselate",'a',"tesselate (split each edge in 2 resursivly n times)",&tesselate);
00094 cmd.opt("sphere",'S',"consider the mesh as a sphere for tesselation",&sphere);
00095 cmd.opt("dist",'D',"compute distance field",&dist);
00096 cmd.opt("res",'R',"resolution of distance field",&res);
00097 cmd.opt("rx",'X',"X resolution of distance field",&rx);
00098 cmd.opt("ry",'Y',"Y resolution of distance field",&ry);
00099 cmd.opt("rz",'Z',"Z resolution of distance field",&rz);
00100 cmd.opt("border",'B',"distance field border size relative to the object's BBox size (or negative for exact size)",&border);
00101 bool error=false;
00102 if (!cmd.parse(argc,argv,&error))
00103 return error?1:0;
00104
00105 if (cmd.args.size()<1 || cmd.args.size()>2)
00106 {
00107 std::cerr << cmd.help() << std::endl;
00108 return 1;
00109 }
00110
00111 std::string file_in = cmd.args[0];
00112 std::string file_out;
00113 if (cmd.args.size()>=2) file_out = cmd.args[1];
00114
00115 Mesh obj;
00116
00117 if (!obj.load(file_in.c_str()))
00118 {
00119 std::cerr << "Failed to read "<<file_in<<std::endl;
00120 return 1;
00121 }
00122
00123 if (normalize)
00124 {
00125 BBox bb = obj.calcBBox();
00126 std::cout << "Mesh bbox="<<bb<<std::endl;
00127 std::cout << "Normalizing mesh..."<<std::endl;
00128 float size = 0;
00129 for (int i=0;i<3;i++)
00130 {
00131 float d = bb.b[i]-bb.a[i];
00132 if (d>size) size=d;
00133 }
00134 Vec3f center = (bb.a+bb.b)*0.5;
00135 float sc = 2/size;
00136 Mat4x4f m; m.identity();
00137 m(0,0)=sc; m(0,3) = -center[0]*sc;
00138 m(1,1)=sc; m(1,3) = -center[1]*sc;
00139 m(2,2)=sc; m(2,3) = -center[2]*sc;
00140 for (int i=0;i<obj.nbp();i++)
00141 obj.PP(i) = transform(m,obj.getPP(i));
00142 }
00143
00144 if (scale != Vec3f(1,1,1))
00145 {
00146 std::cout << "Scaling mesh..."<<std::endl;
00147 for (int i=0;i<obj.nbp();i++)
00148 {
00149 Vec3f p = obj.getPP(i);
00150 p[0] *= scale[0];
00151 p[1] *= scale[1];
00152 p[2] *= scale[2];
00153 obj.PP(i) = p;
00154 }
00155 }
00156
00157 Mat4x4f xform;
00158 bool hasXForm = false;
00159 xform.identity();
00160
00161 if (rotation != Vec3f(0,0,0))
00162 {
00163 std::cout << "Rotating mesh..."<<std::endl;
00164 Mat3x3f mat;
00165 Quat qx,qy,qz;
00166 qx.fromDegreeAngAxis(rotation[0],Vec3f(1,0,0));
00167 qy.fromDegreeAngAxis(rotation[1],Vec3f(0,1,0));
00168 qz.fromDegreeAngAxis(rotation[2],Vec3f(0,0,1));
00169 Quat q = qx*qy*qz;
00170 q.toMatrix(&mat);
00171 std::cout << "mat = "<<mat<<std::endl;
00172 for (int i=0;i<obj.nbp();i++)
00173 {
00174 obj.PP(i) = mat*obj.getPP(i);
00175 obj.PN(i) = mat*obj.getPN(i);
00176 }
00177 hasXForm = true;
00178 xform = mat;
00179 }
00180
00181 if (translation != Vec3f(0,0,0))
00182 {
00183 std::cout << "Translating mesh..."<<std::endl;
00184 for (int i=0;i<obj.nbp();i++)
00185 {
00186 obj.PP(i) = obj.getPP(i) + translation;
00187 }
00188 hasXForm = true;
00189 xform[0][3] = translation[0];
00190 xform[1][3] = translation[1];
00191 xform[2][3] = translation[2];
00192 }
00193
00194 if (obj.distmap && hasXForm)
00195 {
00196
00197 std::cout << "distmap mat = "<<xform <<" * " << obj.distmap->mat<<" = ";
00198 obj.distmap->mat = xform * obj.distmap->mat;
00199 std::cout << obj.distmap->mat<<std::endl;
00200 }
00201
00202 std::cout << "Mesh bbox="<<obj.calcBBox()<<std::endl;
00203 if (flip)
00204 {
00205 std::cout << "Flipping mesh..."<<std::endl;
00206 obj.flipAll();
00207
00208 }
00209 if (closemesh)
00210 {
00211 bool closed = obj.isClosed();
00212 std::cout << "Mesh is "<<(closed?"":"NOT ")<<"closed."<<std::endl;
00213 if (closemesh && !closed)
00214 {
00215 obj.calcFlip();
00216 std::cout << "Closing mesh..."<<std::endl;
00217 obj.close();
00218 std::cout << "Mesh is "<<(obj.isClosed()?"":"NOT ")<<"closed."<<std::endl;
00219 }
00220 }
00221
00222 if (dilate != 0.0f)
00223 obj.dilate(dilate);
00224
00225 if (tesselate > 0 || sphere)
00226 {
00227 std::cout << "Tesselating mesh..."<<std::endl;
00228 tesselateMesh(obj, tesselate, sphere);
00229 }
00230
00231 if (dist)
00232 {
00233 if (!rx) rx = res;
00234 if (!ry) ry = res;
00235 if (!rz) rz = res;
00236 std::cout << "Flipping mesh..."<<std::endl;
00237 obj.calcFlip();
00238 obj.calcEdges();
00239 bool closed = obj.isClosed();
00240 std::cout << "Mesh is "<<(closed?"":"NOT ")<<"closed."<<std::endl;
00241 if (!closed)
00242 {
00243 std::cout << "Closing mesh..."<<std::endl;
00244 obj.close();
00245 std::cout << "Mesh is "<<(obj.isClosed()?"":"NOT ")<<"closed."<<std::endl;
00246 }
00247 std::cout << "Computing "<<rx<<'x'<<ry<<'x'<<rz<<" DistMap..."<<std::endl;
00248 obj.calcDistMap(rx,ry,rz,(border<0 ? -border : obj.calcBBox().size()*border));
00249 }
00250
00251
00252 if (wnormals)
00253 obj.setAttrib(Mesh::MESH_POINTS_NORMAL,true);
00254 if (rnormals)
00255 obj.setAttrib(Mesh::MESH_POINTS_NORMAL,false);
00256 if (rtexcoords)
00257 obj.setAttrib(Mesh::MESH_POINTS_TEXCOORD,false);
00258 if (!file_out.empty())
00259 {
00260 std::cout << "Saving result..."<<std::endl;
00261 obj.save(file_out.c_str());
00262 }
00263 return 0;
00264 }