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
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 #include <string>
00090 #include <sstream>
00091 #include <limits>
00092 #include "mesh/lmesh.H"
00093 #include "std/config.H"
00094
00095 static bool debug = Config::get_var_bool("DEBUG_OBJ2SM",false,true);
00096
00097 inline void
00098 skip_line(istream& in)
00099 {
00100 in.ignore(numeric_limits<std::streamsize>::max(), '\n');
00101 }
00102
00103 inline void
00104 read_vert(LMESH* mesh, istream& in)
00105 {
00106 double x, y, z;
00107 in >> x >> y >> z;
00108 skip_line(in);
00109 assert(mesh);
00110 mesh->add_vertex(Wpt(x,y,z));
00111 }
00112
00113 inline void
00114 read_texcoord(UVpt_list& uvs, istream& in)
00115 {
00116 double u, v;
00117 in >> u >> v;
00118 skip_line(in);
00119 uvs += UVpt(u,v);
00120 }
00121
00122 class vtn {
00123 public:
00124 int _v, _t, _n;
00125
00126 vtn(int v = -1, int t = -1, int n = -1) : _v(v), _t(t), _n(n) {}
00127
00128 bool operator==(const vtn& v) const {
00129 return v._v == _v && v._t == _t && v._n == _n;
00130 }
00131
00132 bool is_valid() const { return _v >= 0; }
00133 };
00134
00135 inline istream&
00136 operator>>(istream& in, vtn& v)
00137 {
00138
00139
00140
00141 in >> v._v;
00142 v._v -= 1;
00143 if (in.peek() == '/') {
00144 char slash;
00145 in >> slash >> v._t;
00146 v._t -= 1;
00147 if (in.peek() == '/') {
00148 in >> slash >> v._n;
00149 v._n -= 1;
00150 }
00151 }
00152 return in;
00153 }
00154
00155 template <class T>
00156 inline bool
00157 all_valid_indices(const T& l, int i, int j, int k)
00158 {
00159 return l.valid_index(i) && l.valid_index(j) && l.valid_index(k);
00160 }
00161
00162 template <class T>
00163 inline bool
00164 any_valid_indices(const T& l, int i, int j, int k)
00165 {
00166 return l.valid_index(i) || l.valid_index(j) || l.valid_index(k);
00167 }
00168
00169 inline void
00170 add_tri(LMESH* mesh, CUVpt_list& uvs, const vtn& v1, const vtn& v2, const vtn& v3)
00171 {
00172 assert(mesh);
00173 assert(all_valid_indices(mesh->verts(), v1._v, v2._v, v3._v));
00174
00175 if (all_valid_indices(uvs, v1._t, v2._t, v3._t)) {
00176 mesh->add_face(v1._v, v2._v, v3._v, uvs[v1._t], uvs[v2._t], uvs[v3._t]);
00177 } else {
00178 mesh->add_face(v1._v, v2._v, v3._v);
00179 }
00180 }
00181
00182 inline void
00183 add_poly(LMESH* mesh, CUVpt_list& uvs, const ARRAY<vtn>& vtns)
00184 {
00185 assert(vtns.num() > 2);
00186
00187 for (int k=2; k < vtns.num(); k++) {
00188 add_tri(mesh, uvs, vtns[0], vtns[k-1], vtns[k]);
00189 }
00190
00191 if (vtns.num() == 4) {
00192 Bedge* e = lookup_edge(mesh->bv(vtns[0]._v), mesh->bv(vtns[2]._v));
00193 assert(e);
00194 e->set_bit(Bedge::WEAK_BIT);
00195 }
00196 }
00197
00198 inline void
00199 read_face(LMESH* mesh, CUVpt_list& uvs, istream& in)
00200 {
00201
00202
00203
00204
00205
00206
00207
00208 ARRAY<vtn> vtns;
00209 const int BUF_SIZE = (1 << 12);
00210 char buf[BUF_SIZE] = {};
00211 in.getline(buf, BUF_SIZE);
00212 if (in.fail())
00213 return;
00214 istringstream is(buf);
00215 while (!(is.eof() || is.fail())) {
00216 vtn v;
00217 is >> v;
00218 if (v.is_valid())
00219 vtns += v;
00220 else break;
00221 }
00222
00223
00224 if (vtns.num() < 3) {
00225 cerr << "read_face: error: read " << vtns.num() << " vertices for face" << endl;
00226 return;
00227 }
00228 add_poly(mesh, uvs, vtns);
00229 }
00230
00231 static LMESHptr
00232 read_obj(istream& in)
00233 {
00234 UVpt_list uvs;
00235
00236 LMESHptr mesh = new LMESH;
00237
00238 string token;
00239 while (!(in.eof() || in.fail())) {
00240 in >> token;
00241 if (token == "v") {
00242 read_vert(mesh, in);
00243 } else if (token == "vt") {
00244 read_texcoord(uvs, in);
00245 } else if (token == "f") {
00246 read_face(mesh, uvs, in);
00247 } else {
00248
00249 skip_line(in);
00250 }
00251 }
00252
00253 return mesh;
00254 }
00255
00256 int
00257 main(int argc, char *argv[])
00258 {
00259 if (argc != 1) {
00260 err_msg("usage: %s < mesh.obj > mesh.sm", argv[0]);
00261 return 1;
00262 }
00263
00264 LMESHptr mesh = read_obj(cin);
00265 if (!mesh)
00266 return 1;
00267
00268 if (Config::get_var_bool("JOT_RECENTER"))
00269 mesh->recenter();
00270
00271 mesh->write_stream(cout);
00272
00273 return 0;
00274 }
00275
00276