00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <iostream>
00010 #include <fstream>
00011 #include <sstream>
00012 #include <vector>
00013 #include <map>
00014 #include <string>
00015 #include <limits>
00016 #include <algorithm>
00017
00018 using namespace std;
00019
00020 #include "geom/texturegl.H"
00021 #include "mesh/bmesh.H"
00022 #include "mesh/patch.H"
00023 #include "mlib/points.H"
00024 #include "std/config.H"
00025
00026 using namespace mlib;
00027
00028 #include "objreader.H"
00029
00030 static bool debug = Config::get_var_bool("DEBUG_OBJ_READER",false);
00031
00032
00033
00034
00035
00036
00037
00038 inline void
00039 eat_line(istream& in, int delim = '\n')
00040 {
00041 in.ignore(numeric_limits<std::streamsize>::max(), delim);
00042 }
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 template <typename T>
00064 class Reader {
00065
00066 public:
00067
00068 Reader()
00069 : read_succeeded(false)
00070 { }
00071
00072 bool read(istream &in, T *object);
00073
00074 void add_reader_function(const string &name,
00075 bool (*func)(istream&, T*));
00076
00077 bool was_successful() const
00078 { return read_succeeded; }
00079
00080 private:
00081
00082 bool read_succeeded;
00083
00084 typedef map<string, bool (*)(istream&, T*)> reader_map_t;
00085 reader_map_t reader_map;
00086
00087
00088
00089
00090 string get_next_token(istream &in);
00091
00092 void ignore_element(istream &in);
00093
00094 void extract_line(istream &in, string &line);
00095
00096
00097
00098 };
00099
00100 template <typename T>
00101 bool
00102 Reader<T>::read(istream &in, T *object)
00103 {
00104
00105
00106
00107 read_succeeded = true;
00108
00109
00110
00111 string token;
00112 string line;
00113
00114 typename reader_map_t::iterator reader_itor;
00115
00116 while(read_succeeded && !(token = get_next_token(in)).empty()){
00117
00118 reader_itor = reader_map.find(token);
00119
00120 if(reader_itor == reader_map.end()){
00121
00122
00123 ignore_element(in);
00124
00125 cerr << "Reader::read() - Warning: Skipped element with token "
00126 << token << endl;
00127
00128 } else {
00129
00130 extract_line(in, line);
00131
00132 istringstream line_stream(line);
00133
00134 read_succeeded = read_succeeded &&
00135 (*(reader_itor->second))(line_stream, object);
00136
00137 }
00138
00139 }
00140
00141 if(!read_succeeded){
00142
00143 cerr << "Reader::read() - Error: Failed while reading element with token "
00144 << token << endl;
00145
00146 }
00147
00148 return read_succeeded;
00149
00150 }
00151
00152 template <typename T>
00153 void
00154 Reader<T>::add_reader_function(const string &name,
00155 bool (*func)(istream&, T*))
00156 {
00157
00158 reader_map[name] = func;
00159
00160 }
00161
00162
00163
00164
00165
00166
00167 template <typename T>
00168 string
00169 Reader<T>::get_next_token(istream &in)
00170 {
00171
00172 string buf;
00173
00174
00175 while(in >> buf){
00176
00177
00178 if(buf[0] == '#')
00179 eat_line(in);
00180 else
00181 break;
00182
00183 }
00184
00185
00186 return in ? buf : string();
00187
00188 }
00189
00190
00191
00192
00193
00194
00195 template <typename T>
00196 void
00197 Reader<T>::ignore_element(istream &in)
00198 {
00199
00200 char c;
00201
00202 while(in.get(c)){
00203
00204 if(c == '\\')
00205 eat_line(in);
00206 else if(c == '\n')
00207 break;
00208
00209 }
00210
00211 }
00212
00213
00214
00215
00216
00217
00218
00219 template <typename T>
00220 void
00221 Reader<T>::extract_line(istream &in, string &line)
00222 {
00223
00224 line.clear();
00225
00226 string buf;
00227
00228 string::size_type continuation_loc;
00229
00230 while(getline(in, buf)){
00231
00232 if((continuation_loc = buf.rfind('\\')) != string::npos){
00233
00234 buf.resize(continuation_loc);
00235
00236 line.push_back(' ');
00237 line.append(buf);
00238
00239 } else {
00240
00241 line.append(buf);
00242 break;
00243
00244 }
00245
00246 }
00247
00248 }
00249
00250
00251
00252
00253
00254
00255
00256 class OBJFace {
00257
00258 public:
00259
00260 OBJFace(long mtl_index_in = -1)
00261 : mtl_index(mtl_index_in)
00262 { }
00263
00264 unsigned long num_vertices() const { return vertices.size(); }
00265 unsigned long num_texcoords() const { return texcoords.size(); }
00266 unsigned long num_normals() const { return normals.size(); }
00267
00268 unsigned long get_vertex_idx(unsigned long idx) const
00269 { return vertices[idx]; }
00270 unsigned long get_texcoord_idx(unsigned long idx) const
00271 { return texcoords[idx]; }
00272 unsigned long get_normal_idx(unsigned long idx) const
00273 { return normals[idx]; }
00274
00275 bool has_texcoords() const { return num_texcoords() > 0; }
00276 bool has_normals() const { return num_normals() > 0; }
00277
00278 bool add_vertex(long vertex, unsigned long total_vertices);
00279 bool add_texcoord(long texcoord, unsigned long total_texcoords);
00280 bool add_normal(long normal, unsigned long total_normals);
00281
00282
00283
00284 bool good() const;
00285
00286 private:
00287
00288 bool process_index(long index, unsigned long max_val,
00289 vector<unsigned long> &index_list);
00290
00291 long mtl_index;
00292
00293 vector<unsigned long> vertices;
00294 vector<unsigned long> texcoords;
00295 vector<unsigned long> normals;
00296
00297 };
00298
00299 bool
00300 OBJFace::add_vertex(long vertex, unsigned long total_vertices)
00301 {
00302
00303 return process_index(vertex, total_vertices, vertices);
00304
00305 }
00306
00307 bool
00308 OBJFace::add_texcoord(long texcoord, unsigned long total_texcoords)
00309 {
00310
00311 return process_index(texcoord, total_texcoords, texcoords);
00312
00313 }
00314
00315 bool
00316 OBJFace::add_normal(long normal, unsigned long total_normals)
00317 {
00318
00319 return process_index(normal, total_normals, normals);
00320
00321 }
00322
00323 bool
00324 OBJFace::good() const
00325 {
00326
00327 return ((vertices.size() > 2) &&
00328 ((vertices.size() == texcoords.size()) || texcoords.empty()) &&
00329 ((vertices.size() == normals.size()) || normals.empty()));
00330
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 bool
00348 OBJFace::process_index(long index, unsigned long max_val,
00349 vector<unsigned long> &index_list)
00350 {
00351
00352
00353 if((index == 0) ||
00354 (index > static_cast<long>(max_val)) ||
00355 (index < -static_cast<long>(max_val))){
00356
00357 return false;
00358
00359 }
00360
00361 if(index < 0)
00362 index = max_val + index + 1;
00363
00364 index_list.push_back(static_cast<unsigned long>(index));
00365
00366 return true;
00367
00368 }
00369
00370
00371
00372
00373
00374
00375
00376 class OBJMtl {
00377
00378 public:
00379
00380 enum color_component_t {COLOR_RED = 0, COLOR_GREEN = 1, COLOR_BLUE = 2};
00381
00382 OBJMtl(const string &mtl_name = "",
00383 double ambt_r = 0.2, double ambt_g = 0.2, double ambt_b = 0.2,
00384 double diff_r = 0.8, double diff_g = 0.8, double diff_b = 0.8,
00385 double spec_r = 1.0, double spec_g = 1.0, double spec_b = 1.0,
00386 double trans = 1.0, double shin = 0.0, int illum = 1,
00387 const string &texture_color_diffuse_filename = "");
00388
00389 const string &get_name() const
00390 { return name; }
00391
00392 double get_ambient(color_component_t comp) const
00393 { return color_ambient[comp]; }
00394
00395 void set_ambient(color_component_t comp, double val)
00396 { color_ambient[comp] = val; }
00397
00398 void set_ambient(double ambient[3])
00399 { copy(ambient, ambient + 3, color_ambient); }
00400
00401 double get_diffuse(color_component_t comp) const
00402 { return color_diffuse[comp]; }
00403
00404 void set_diffuse(color_component_t comp, double val)
00405 { color_diffuse[comp] = val; }
00406
00407 void set_diffuse(double diffuse[3])
00408 { copy(diffuse, diffuse + 3, color_diffuse); }
00409
00410 double get_specular(color_component_t comp) const
00411 { return color_specular[comp]; }
00412
00413 void set_specular(color_component_t comp, double val)
00414 { color_specular[comp] = val; }
00415
00416 void set_specular(double specular[3])
00417 { copy(specular, specular + 3, color_specular); }
00418
00419 double get_transparency() const
00420 { return transparency; }
00421
00422 void set_transparency(double trans)
00423 { transparency = trans; }
00424
00425 double get_shininess() const
00426 { return shininess; }
00427
00428 void set_shininess(double shin)
00429 { shininess = shin; }
00430
00431 int get_illumination_model() const
00432 { return illumination_model; }
00433
00434 void set_illumination_model(int illum)
00435 { illumination_model = illum; }
00436
00437 const string &get_diffuse_texture_map() const
00438 { return texmap_color_diffuse; }
00439
00440 void set_diffuse_texture_map(const string &texmap)
00441 { texmap_color_diffuse = texmap; }
00442
00443 private:
00444
00445 string name;
00446
00447 double color_ambient[3];
00448 double color_diffuse[3];
00449 double color_specular[3];
00450
00451 double transparency;
00452
00453 double shininess;
00454
00455 int illumination_model;
00456
00457 string texmap_color_diffuse;
00458
00459 };
00460
00461 OBJMtl::OBJMtl(const string &mtl_name,
00462 double ambt_r, double ambt_g, double ambt_b,
00463 double diff_r, double diff_g, double diff_b,
00464 double spec_r, double spec_g, double spec_b,
00465 double trans, double shin, int illum,
00466 const string &texture_color_diffuse_filename)
00467 : name(mtl_name), transparency(trans), shininess(shin),
00468 illumination_model(illum),
00469 texmap_color_diffuse(texture_color_diffuse_filename)
00470 {
00471
00472 color_ambient[0] = ambt_r;
00473 color_ambient[1] = ambt_g;
00474 color_ambient[2] = ambt_b;
00475
00476 color_diffuse[0] = diff_r;
00477 color_diffuse[1] = diff_g;
00478 color_diffuse[2] = diff_b;
00479
00480 color_specular[0] = spec_r;
00481 color_specular[1] = spec_g;
00482 color_specular[2] = spec_b;
00483
00484 }
00485
00486
00487
00488
00489
00490
00491
00492 class MTLReader {
00493
00494 public:
00495
00496 MTLReader();
00497
00498 bool read(istream &in);
00499
00500 bool has_material(const string &mtl_name) const
00501 { return mtl_name2id.count(mtl_name) > 0; }
00502
00503 const OBJMtl &get_material(const string &mtl_name) const
00504 { assert(has_material(mtl_name));
00505 return materials[mtl_name2id.find(mtl_name)->second]; }
00506
00507 private:
00508
00509 Reader<MTLReader> reader;
00510
00511
00512
00513
00514 static bool read_newmtl(istream &in, MTLReader *self);
00515 static bool read_Ka(istream &in, MTLReader *self);
00516 static bool read_Kd(istream &in, MTLReader *self);
00517 static bool read_Ks(istream &in, MTLReader *self);
00518 static bool read_d(istream &in, MTLReader *self);
00519 static bool read_Tr(istream &in, MTLReader *self);
00520 static bool read_Ns(istream &in, MTLReader *self);
00521 static bool read_illum(istream &in, MTLReader *self);
00522 static bool read_map_Kd(istream &in, MTLReader *self);
00523
00524 bool exists_current_material();
00525
00526
00527
00528
00529
00530
00531 vector<OBJMtl> materials;
00532
00533 typedef map<string, long> mtl_name2id_map_t;
00534 mtl_name2id_map_t mtl_name2id;
00535
00536
00537
00538 };
00539
00540 MTLReader::MTLReader()
00541 {
00542
00543 reader.add_reader_function("newmtl", &MTLReader::read_newmtl);
00544 reader.add_reader_function("Ka", &MTLReader::read_Ka);
00545 reader.add_reader_function("Kd", &MTLReader::read_Kd);
00546 reader.add_reader_function("Ks", &MTLReader::read_Ks);
00547 reader.add_reader_function("d", &MTLReader::read_d);
00548 reader.add_reader_function("Tr", &MTLReader::read_Tr);
00549 reader.add_reader_function("Ns", &MTLReader::read_Ns);
00550 reader.add_reader_function("illum", &MTLReader::read_illum);
00551 reader.add_reader_function("map_Kd", &MTLReader::read_map_Kd);
00552
00553 }
00554
00555 bool
00556 MTLReader::read(istream &in)
00557 {
00558
00559
00560
00561 materials.clear();
00562 mtl_name2id.clear();
00563
00564 return reader.read(in, this);
00565
00566 }
00567
00568 bool
00569 MTLReader::read_newmtl(istream &in, MTLReader *self)
00570 {
00571
00572 string name;
00573
00574 if(!(in >> name))
00575 return false;
00576
00577
00578 if(self->mtl_name2id.count(name) != 0)
00579 return false;
00580
00581 self->materials.push_back(OBJMtl(name));
00582
00583 self->mtl_name2id[name] = self->materials.size() - 1;
00584
00585 return true;
00586
00587 }
00588
00589 bool
00590 MTLReader::read_Ka(istream &in, MTLReader *self)
00591 {
00592
00593 if(!self->exists_current_material())
00594 return false;
00595
00596 double ambient[3];
00597
00598 if(!(in >> ambient[0] >> ambient[1] >> ambient[2]))
00599 return false;
00600
00601 self->materials.back().set_ambient(ambient);
00602
00603 return true;
00604
00605 }
00606
00607 bool
00608 MTLReader::read_Kd(istream &in, MTLReader *self)
00609 {
00610
00611 if(!self->exists_current_material())
00612 return false;
00613
00614 double diffuse[3];
00615
00616 if(!(in >> diffuse[0] >> diffuse[1] >> diffuse[2]))
00617 return false;
00618
00619 self->materials.back().set_diffuse(diffuse);
00620
00621 return true;
00622
00623 }
00624
00625 bool
00626 MTLReader::read_Ks(istream &in, MTLReader *self)
00627 {
00628
00629 if(!self->exists_current_material())
00630 return false;
00631
00632 double specular[3];
00633
00634 if(!(in >> specular[0] >> specular[1] >> specular[2]))
00635 return false;
00636
00637 self->materials.back().set_specular(specular);
00638
00639 return true;
00640
00641 }
00642
00643 bool
00644 MTLReader::read_d(istream &in, MTLReader *self)
00645 {
00646
00647 return read_Tr(in, self);
00648
00649 }
00650
00651 bool
00652 MTLReader::read_Tr(istream &in, MTLReader *self)
00653 {
00654
00655 if(!self->exists_current_material())
00656 return false;
00657
00658 double trans;
00659
00660 if(!(in >> trans))
00661 return false;
00662
00663 self->materials.back().set_transparency(trans);
00664
00665 return true;
00666
00667 }
00668
00669 bool
00670 MTLReader::read_Ns(istream &in, MTLReader *self)
00671 {
00672
00673 if(!self->exists_current_material())
00674 return false;
00675
00676 double shin;
00677
00678 if(!(in >> shin))
00679 return false;
00680
00681 self->materials.back().set_shininess(shin);
00682
00683 return true;
00684
00685 }
00686
00687 bool
00688 MTLReader::read_illum(istream &in, MTLReader *self)
00689 {
00690
00691 if(!self->exists_current_material())
00692 return false;
00693
00694 int illum;
00695
00696 if(!(in >> illum))
00697 return false;
00698
00699 self->materials.back().set_illumination_model(illum);
00700
00701 return true;
00702
00703 }
00704
00705 bool
00706 MTLReader::read_map_Kd(istream &in, MTLReader *self)
00707 {
00708
00709 if(!self->exists_current_material())
00710 return false;
00711
00712 string texmap;
00713
00714 if(!(in >> texmap))
00715 return false;
00716
00717 self->materials.back().set_diffuse_texture_map(texmap);
00718
00719 return true;
00720
00721 }
00722
00723 bool
00724 MTLReader::exists_current_material()
00725 {
00726
00727 return materials.size() > 0;
00728
00729 }
00730
00731
00732
00733
00734
00735
00736
00737 class OBJReaderImpl {
00738
00739 public:
00740
00741 OBJReaderImpl();
00742
00743 bool read(istream &in);
00744
00745 BMESH *get_mesh() const;
00746
00747 void get_mesh(BMESH *mesh) const;
00748
00749 friend class OBJReader;
00750
00751 private:
00752
00753 Reader<OBJReaderImpl> reader;
00754
00755 bool read_mtl_files();
00756
00757
00758
00759
00760 static bool read_v(istream &in, OBJReaderImpl *self);
00761 static bool read_vn(istream &in, OBJReaderImpl *self);
00762 static bool read_vt(istream &in, OBJReaderImpl *self);
00763 static bool read_f(istream &in, OBJReaderImpl *self);
00764 static bool read_mtllib(istream &in, OBJReaderImpl *self);
00765 static bool read_usemtl(istream &in, OBJReaderImpl *self);
00766
00767
00768
00769
00770
00771
00772 bool read_succeeded;
00773
00774 vector<Wpt> vertices;
00775 vector<Wvec> normals;
00776 vector<UVpt> texcoords;
00777 vector<OBJFace> faces;
00778
00779 vector<string> mtl_files;
00780 vector<OBJMtl> materials;
00781 vector< vector<long> > material_faces;
00782
00783 typedef map<string, long> mtl_name2id_map_t;
00784 mtl_name2id_map_t mtl_name2id;
00785
00786 long current_material;
00787
00788
00789
00790
00791
00792
00793 void add_vertices(BMESH *mesh) const;
00794
00795 void add_patches(BMESH *mesh) const;
00796
00797 void set_vert_normals(BMESH *mesh) const;
00798
00799 void add_face(BMESH *mesh, Patch *patch, unsigned long index) const;
00800
00801 void add_tri(BMESH *mesh, Patch *patch, const OBJFace &face,
00802 unsigned long idx0, unsigned long idx1, unsigned long idx2) const;
00803
00804 void add_creases(BMESH *mesh) const;
00805
00806
00807
00808
00809
00810
00811
00812 mutable vector<unsigned long> mesh_faces2obj_faces;
00813
00814
00815
00816 };
00817
00818 OBJReaderImpl::OBJReaderImpl()
00819 : read_succeeded(false), current_material(-1)
00820 {
00821
00822
00823
00824 reader.add_reader_function("v", &OBJReaderImpl::read_v);
00825 reader.add_reader_function("vn", &OBJReaderImpl::read_vn);
00826 reader.add_reader_function("vt", &OBJReaderImpl::read_vt);
00827 reader.add_reader_function("f", &OBJReaderImpl::read_f);
00828 reader.add_reader_function("mtllib", &OBJReaderImpl::read_mtllib);
00829 reader.add_reader_function("usemtl", &OBJReaderImpl::read_usemtl);
00830
00831 }
00832
00833 bool
00834 OBJReaderImpl::read(istream &in)
00835 {
00836
00837
00838
00839 read_succeeded = false;
00840
00841 vertices.clear();
00842 normals.clear();
00843 texcoords.clear();
00844 faces.clear();
00845 mtl_files.clear();
00846 materials.clear();
00847 mtl_name2id.clear();
00848
00849
00850
00851 materials.push_back(OBJMtl());
00852 material_faces.push_back(vector<long>());
00853 current_material = 0;
00854
00855 read_succeeded = reader.read(in, this);
00856
00857
00858 assert(materials.size() == material_faces.size());
00859
00860 read_succeeded = read_succeeded && read_mtl_files();
00861
00862 return read_succeeded;
00863
00864 }
00865
00866 BMESH*
00867 OBJReaderImpl::get_mesh() const
00868 {
00869
00870 if(!read_succeeded) return 0;
00871
00872 BMESH *mesh = new BMESH;
00873
00874 get_mesh(mesh);
00875
00876 return mesh;
00877
00878 }
00879
00880 void
00881 OBJReaderImpl::get_mesh(BMESH *mesh) const
00882 {
00883
00884
00885 if(!read_succeeded)
00886 return;
00887
00888
00889 mesh->delete_elements();
00890
00891
00892 mesh_faces2obj_faces.clear();
00893
00894
00895
00896 add_vertices(mesh);
00897
00898 add_patches(mesh);
00899
00900 add_creases(mesh);
00901
00902 set_vert_normals(mesh);
00903
00904 mesh->changed();
00905 }
00906
00907 bool
00908 OBJReaderImpl::read_mtl_files()
00909 {
00910
00911 if(!read_succeeded)
00912 return false;
00913
00914 MTLReader mtl_reader;
00915
00916 for(unsigned long i = 0; i < mtl_files.size(); ++i){
00917
00918 ifstream mtl_stream(mtl_files[i].c_str());
00919
00920 if(!mtl_stream.is_open()){
00921
00922 cerr << "OBJReader::read_mtl_files() - Warning: Couldn't open material file "
00923 << mtl_files[i] << "!" << endl;
00924
00925 continue;
00926
00927 }
00928
00929 if(!mtl_reader.read(mtl_stream))
00930 return false;
00931
00932 for(unsigned long j = 0; j < materials.size(); ++j){
00933
00934 if(mtl_reader.has_material(materials[j].get_name())){
00935
00936 materials[j] = mtl_reader.get_material(materials[j].get_name());
00937
00938 }
00939
00940 }
00941
00942 }
00943
00944 return true;
00945
00946 }
00947
00948
00949
00950
00951
00952
00953 bool
00954 OBJReaderImpl::read_v(istream &in, OBJReaderImpl *self)
00955 {
00956
00957 double vals[3];
00958
00959 if(!(in >> vals[0] >> vals[1] >> vals[2]))
00960 return false;
00961
00962 self->vertices.push_back(Wpt(vals[0], vals[1], vals[2]));
00963
00964 return true;
00965
00966 }
00967
00968
00969
00970
00971
00972
00973 bool
00974 OBJReaderImpl::read_vn(istream &in, OBJReaderImpl *self)
00975 {
00976
00977 double vals[3];
00978
00979 if(!(in >> vals[0] >> vals[1] >> vals[2]))
00980 return false;
00981
00982 self->normals.push_back(Wvec(vals[0], vals[1], vals[2]));
00983
00984 return true;
00985
00986 }
00987
00988
00989
00990
00991
00992
00993 bool
00994 OBJReaderImpl::read_vt(istream &in, OBJReaderImpl *self)
00995 {
00996
00997 double vals[2];
00998
00999 if(!(in >> vals[0] >> vals[1]))
01000 return false;
01001
01002 self->texcoords.push_back(UVpt(vals[0], vals[1]));
01003
01004 return true;
01005
01006 }
01007
01008
01009
01010
01011
01012
01013 bool
01014 OBJReaderImpl::read_f(istream &in, OBJReaderImpl *self)
01015 {
01016
01017 long pos, tcoord, norm;
01018
01019 char slash;
01020
01021 OBJFace face(self->current_material);
01022
01023 while(in >> pos){
01024
01025 face.add_vertex(pos, self->vertices.size());
01026
01027 if(in.peek() == '/'){
01028
01029 in >> slash;
01030
01031 if(in.peek() != '/'){
01032
01033 in >> tcoord;
01034 face.add_texcoord(tcoord, self->texcoords.size());
01035
01036 }
01037
01038 if(in.peek() == '/'){
01039
01040 in >> slash >> norm;
01041 face.add_normal(norm, self->normals.size());
01042
01043 }
01044
01045 }
01046
01047 }
01048
01049 if(!face.good())
01050 return false;
01051
01052 self->faces.push_back(face);
01053 self->material_faces[self->current_material].push_back(self->faces.size() - 1);
01054
01055 return true;
01056
01057 }
01058
01059
01060
01061
01062
01063
01064 bool
01065 OBJReaderImpl::read_mtllib(istream &in, OBJReaderImpl *self)
01066 {
01067
01068 string buf;
01069
01070 bool valid = false;
01071
01072 while(in >> buf){
01073
01074 if(buf[0] == '#')
01075 break;
01076
01077 self->mtl_files.push_back(buf);
01078
01079 valid = true;
01080
01081 }
01082
01083 return valid;
01084
01085 }
01086
01087
01088
01089
01090
01091
01092 bool
01093 OBJReaderImpl::read_usemtl(istream &in, OBJReaderImpl *self)
01094 {
01095
01096 string mtl_name;
01097
01098
01099 if(!(in >> mtl_name) || (mtl_name[0] == '#'))
01100 return false;
01101
01102 mtl_name2id_map_t::iterator name2id_itor = self->mtl_name2id.find(mtl_name);
01103
01104
01105 if(name2id_itor == self->mtl_name2id.end()){
01106
01107 self->materials.push_back(OBJMtl(mtl_name));
01108 self->material_faces.push_back(vector<long>());
01109
01110 name2id_itor =
01111 self->mtl_name2id.insert(self->mtl_name2id.begin(),
01112 make_pair(mtl_name, self->materials.size() - 1));
01113
01114 }
01115
01116 self->current_material = name2id_itor->second;
01117
01118 return true;
01119
01120 }
01121
01122 void
01123 OBJReaderImpl::add_vertices(BMESH *mesh) const
01124 {
01125
01126 for(unsigned long i = 0; i < vertices.size(); ++i){
01127
01128 mesh->add_vertex(vertices[i]);
01129
01130 }
01131
01132 }
01133
01134 void
01135 OBJReaderImpl::add_patches(BMESH *mesh) const
01136 {
01137 err_adv(debug, "OBJReaderImpl::add_patches: %d materials", int(materials.size()));
01138
01139 for(unsigned long i = 0; i < materials.size(); ++i){
01140
01141 if(material_faces[i].size() == 0)
01142 continue;
01143
01144 Patch *patch = mesh->new_patch();
01145
01146 if(materials[i].get_name().size() > 0)
01147 patch->set_name(materials[i].get_name().c_str());
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 for(unsigned long j = 0; j < material_faces[i].size(); ++j)
01177 add_face(mesh, patch, material_faces[i][j]);
01178
01179 }
01180 }
01181
01182 void
01183 OBJReaderImpl::set_vert_normals(BMESH *mesh) const
01184 {
01185 assert(mesh);
01186 if (vertices.empty() || vertices.size() != normals.size()) {
01187 err_adv(debug, "OBJReaderImpl::set_vert_normals: skipping...");
01188 return;
01189 }
01190 err_adv(debug, "OBJReaderImpl::set_vert_normals: assigning normals to vertices");
01191 assert((unsigned long)(mesh->nverts()) == normals.size());
01192 for (unsigned long i=0; i<normals.size(); i++) {
01193 mesh->bv(int(i))->set_norm(normals[i]);
01194 }
01195 }
01196
01197 void
01198 OBJReaderImpl::add_face(BMESH *mesh, Patch *patch, unsigned long index) const
01199 {
01200
01201 assert(faces[index].good());
01202
01203 for(unsigned long k = 2; k < faces[index].num_vertices(); ++k){
01204
01205 add_tri(mesh, patch, faces[index], 0, k-1, k);
01206 mesh_faces2obj_faces.push_back(index);
01207
01208 }
01209
01210
01211 if (faces[index].num_vertices() == 4) {
01212
01213 Bedge* e = lookup_edge(mesh->bv(faces[index].get_vertex_idx(0) - 1),
01214 mesh->bv(faces[index].get_vertex_idx(2) - 1));
01215 assert(e);
01216 e->set_bit(Bedge::WEAK_BIT);
01217
01218 }
01219
01220 }
01221
01222
01223
01224
01225
01226
01227
01228 void
01229 OBJReaderImpl::add_tri(BMESH *mesh, Patch *patch, const OBJFace &face,
01230 unsigned long idx0, unsigned long idx1, unsigned long idx2) const
01231 {
01232
01233
01234 assert((face.get_vertex_idx(idx0) > 0) &&
01235 (face.get_vertex_idx(idx0) <= vertices.size()) &&
01236 (face.get_vertex_idx(idx1) > 0) &&
01237 (face.get_vertex_idx(idx1) <= vertices.size()) &&
01238 (face.get_vertex_idx(idx2) > 0) &&
01239 (face.get_vertex_idx(idx2) <= vertices.size()));
01240
01241
01242 assert(!face.has_texcoords() ||
01243 ((face.get_texcoord_idx(idx0) > 0) &&
01244 (face.get_texcoord_idx(idx0) <= texcoords.size()) &&
01245 (face.get_texcoord_idx(idx1) > 0) &&
01246 (face.get_texcoord_idx(idx1) <= texcoords.size()) &&
01247 (face.get_texcoord_idx(idx2) > 0) &&
01248 (face.get_texcoord_idx(idx2) <= texcoords.size())));
01249
01250
01251 assert(!face.has_normals() ||
01252 ((face.get_normal_idx(idx0) > 0) &&
01253 (face.get_normal_idx(idx0) <= normals.size()) &&
01254 (face.get_normal_idx(idx1) > 0) &&
01255 (face.get_normal_idx(idx1) <= normals.size()) &&
01256 (face.get_normal_idx(idx2) > 0) &&
01257 (face.get_normal_idx(idx2) <= normals.size())));
01258
01259 if(face.has_texcoords()){
01260
01261 mesh->add_face(face.get_vertex_idx(idx0) - 1,
01262 face.get_vertex_idx(idx1) - 1,
01263 face.get_vertex_idx(idx2) - 1,
01264 texcoords[face.get_texcoord_idx(idx0) - 1],
01265 texcoords[face.get_texcoord_idx(idx1) - 1],
01266 texcoords[face.get_texcoord_idx(idx2) - 1],
01267 patch);
01268
01269 } else {
01270
01271 mesh->add_face(face.get_vertex_idx(idx0) - 1,
01272 face.get_vertex_idx(idx1) - 1,
01273 face.get_vertex_idx(idx2) - 1,
01274 patch);
01275
01276 }
01277
01278 }
01279
01280 void
01281 OBJReaderImpl::add_creases(BMESH *mesh) const
01282 {
01283
01284 for(int ei = 0; ei < mesh->nedges(); ++ei){
01285
01286 Bedge *cur_edge = mesh->be(ei);
01287
01288
01289 if((cur_edge->f1() == 0) || (cur_edge->f2() == 0))
01290 continue;
01291
01292
01293 if(mesh_faces2obj_faces[cur_edge->f1()->index()] ==
01294 mesh_faces2obj_faces[cur_edge->f2()->index()])
01295 continue;
01296
01297
01298 if(!faces[mesh_faces2obj_faces[cur_edge->f1()->index()]].has_normals() ||
01299 !faces[mesh_faces2obj_faces[cur_edge->f2()->index()]].has_normals())
01300 continue;
01301
01302 int vertex_indices[2];
01303 vertex_indices[0] = cur_edge->v1()->index();
01304 vertex_indices[1] = cur_edge->v2()->index();
01305
01306
01307 int normal_indices[2][2] = {{-1, -1}, {-1, -1}};
01308
01309 for(int fi = 0; fi < 2; ++fi){
01310
01311 unsigned long obj_face_idx = mesh_faces2obj_faces[cur_edge->f(fi + 1)->index()];
01312
01313 for (uint vi = 0; vi < faces[obj_face_idx].num_vertices(); ++vi){
01314
01315 for (int evi = 0; evi < 2; ++evi){
01316
01317 if (vertex_indices[evi] ==
01318 int(faces[obj_face_idx].get_vertex_idx(vi) - 1)) {
01319
01320 normal_indices[evi][fi] =
01321 faces[obj_face_idx].get_normal_idx(vi);
01322
01323 }
01324
01325 }
01326
01327 }
01328
01329 }
01330
01331
01332 assert(normal_indices[0][0] != -1);
01333 assert(normal_indices[0][1] != -1);
01334 assert(normal_indices[1][0] != -1);
01335 assert(normal_indices[1][1] != -1);
01336
01337 if((normal_indices[0][0] != normal_indices[0][1]) ||
01338 (normal_indices[1][0] != normal_indices[1][1])){
01339
01340 cur_edge->set_crease();
01341
01342 }
01343
01344 }
01345
01346 }
01347
01348
01349
01350 OBJReader::OBJReader()
01351 : impl(0)
01352 {
01353
01354 impl = new OBJReaderImpl();
01355
01356 }
01357
01358 OBJReader::~OBJReader()
01359 {
01360
01361 delete impl;
01362
01363 }
01364
01365
01366
01367
01368
01369
01370 bool
01371 OBJReader::read(istream &in)
01372 {
01373
01374 return impl->read(in);
01375
01376 }
01377
01378 BMESH*
01379 OBJReader::get_mesh() const
01380 {
01381
01382 return impl->get_mesh();
01383
01384 }
01385
01386 void
01387 OBJReader::get_mesh(BMESH *mesh) const
01388 {
01389
01390 impl->get_mesh(mesh);
01391
01392 }
01393
01394
01395
01396 unsigned long
01397 OBJReader::get_num_vertices() const
01398 {
01399
01400 return impl->vertices.size();
01401
01402 }
01403
01404 unsigned long
01405 OBJReader::get_num_texcoords() const
01406 {
01407
01408 return impl->texcoords.size();
01409
01410 }
01411
01412 unsigned long
01413 OBJReader::get_num_normals() const
01414 {
01415
01416 return impl->normals.size();
01417
01418 }
01419
01420 unsigned long
01421 OBJReader::get_num_faces() const
01422 {
01423
01424 return impl->faces.size();
01425
01426 }
01427
01428 unsigned long
01429 OBJReader::get_num_materials() const
01430 {
01431
01432 return impl->materials.size();
01433
01434 }
01435
01436 unsigned long
01437 OBJReader::get_num_material_libs() const
01438 {
01439
01440 return impl->mtl_files.size();
01441
01442 }