00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "objToEggConverter.h"
00016 #include "config_objegg.h"
00017 #include "eggData.h"
00018 #include "string_utils.h"
00019 #include "streamReader.h"
00020 #include "virtualFileSystem.h"
00021 #include "eggPolygon.h"
00022 #include "dcast.h"
00023
00024
00025
00026
00027
00028
00029 ObjToEggConverter::
00030 ObjToEggConverter() {
00031 }
00032
00033
00034
00035
00036
00037
00038 ObjToEggConverter::
00039 ObjToEggConverter(const ObjToEggConverter ©) :
00040 SomethingToEggConverter(copy)
00041 {
00042 }
00043
00044
00045
00046
00047
00048
00049 ObjToEggConverter::
00050 ~ObjToEggConverter() {
00051 }
00052
00053
00054
00055
00056
00057
00058 SomethingToEggConverter *ObjToEggConverter::
00059 make_copy() {
00060 return new ObjToEggConverter(*this);
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070 string ObjToEggConverter::
00071 get_name() const {
00072 return "obj";
00073 }
00074
00075
00076
00077
00078
00079
00080
00081 string ObjToEggConverter::
00082 get_extension() const {
00083 return "obj";
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093 bool ObjToEggConverter::
00094 supports_compressed() const {
00095 return true;
00096 }
00097
00098
00099
00100
00101
00102
00103
00104
00105 bool ObjToEggConverter::
00106 convert_file(const Filename &filename) {
00107 clear_error();
00108
00109 if (_egg_data->get_coordinate_system() == CS_default) {
00110 _egg_data->set_coordinate_system(CS_zup_right);
00111 }
00112
00113 if (!process(filename)) {
00114 _error = true;
00115 }
00116 return !had_error();
00117 }
00118
00119
00120
00121
00122
00123
00124 bool ObjToEggConverter::
00125 process(const Filename &filename) {
00126 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00127 istream *strm = vfs->open_read_file(filename, true);
00128 if (strm == NULL) {
00129 objegg_cat.error()
00130 << "Couldn't read " << filename << "\n";
00131 return false;
00132 }
00133
00134 _vi = 1;
00135 _vti = 1;
00136 _vni = 1;
00137
00138 _vpool = new EggVertexPool("vpool");
00139 _egg_data->add_child(_vpool);
00140 _root_group = new EggGroup("root");
00141 _egg_data->add_child(_root_group);
00142 _current_group = _root_group;
00143
00144 StreamReader sr(strm, true);
00145 string line = sr.readline();
00146 _line_number = 1;
00147 while (!line.empty()) {
00148 line = trim(line);
00149 if (line.empty()) {
00150 line = sr.readline();
00151 continue;
00152 }
00153
00154 if (line[0] == '#') {
00155 line = sr.readline();
00156 continue;
00157 }
00158
00159 if (!process_line(line)) {
00160 return false;
00161 }
00162 line = sr.readline();
00163 ++_line_number;
00164 }
00165
00166 return true;
00167 }
00168
00169
00170
00171
00172
00173
00174 bool ObjToEggConverter::
00175 process_line(const string &line) {
00176 vector_string words;
00177 tokenize(line, words, " \t", true);
00178 nassertr(!words.empty(), false);
00179
00180 string tag = words[0];
00181 if (tag == "v") {
00182 return process_v(words);
00183 } else if (tag == "vt") {
00184 return process_vt(words);
00185 } else if (tag == "vn") {
00186 return process_vn(words);
00187 } else if (tag == "f") {
00188 return process_f(words);
00189 } else if (tag == "g") {
00190 return process_g(words);
00191 } else {
00192 bool inserted = _ignored_tags.insert(tag).second;
00193 if (inserted) {
00194 objegg_cat.info()
00195 << "Ignoring tag " << tag << "\n";
00196 }
00197 }
00198
00199 return true;
00200 }
00201
00202
00203
00204
00205
00206
00207 bool ObjToEggConverter::
00208 process_v(vector_string &words) {
00209 if (words.size() != 4 && words.size() != 7) {
00210 objegg_cat.error()
00211 << "Wrong number of tokens at line " << _line_number << "\n";
00212 return false;
00213 }
00214
00215 bool okflag = true;
00216 LPoint3d pos;
00217 okflag &= string_to_double(words[1], pos[0]);
00218 okflag &= string_to_double(words[2], pos[1]);
00219 okflag &= string_to_double(words[3], pos[2]);
00220
00221 if (!okflag) {
00222 objegg_cat.error()
00223 << "Invalid number at line " << _line_number << "\n";
00224 return false;
00225 }
00226
00227 EggVertex *vertex = get_vertex(_vi);
00228 vertex->set_pos(pos);
00229
00230
00231
00232 if (words.size() == 7) {
00233 double r, g, b;
00234 okflag &= string_to_double(words[4], r);
00235 okflag &= string_to_double(words[5], g);
00236 okflag &= string_to_double(words[6], b);
00237
00238 if (!okflag) {
00239 objegg_cat.error()
00240 << "Invalid number at line " << _line_number << "\n";
00241 return false;
00242 }
00243 vertex->set_color(LColor(r, g, b, 1.0));
00244 }
00245
00246 ++_vi;
00247
00248 return true;
00249 }
00250
00251
00252
00253
00254
00255
00256 bool ObjToEggConverter::
00257 process_vt(vector_string &words) {
00258 if (words.size() != 3 && words.size() != 4) {
00259 objegg_cat.error()
00260 << "Wrong number of tokens at line " << _line_number << "\n";
00261 return false;
00262 }
00263
00264 bool okflag = true;
00265 LTexCoord3d uvw;
00266 okflag &= string_to_double(words[1], uvw[0]);
00267 okflag &= string_to_double(words[2], uvw[1]);
00268 if (words.size() == 4) {
00269 okflag &= string_to_double(words[3], uvw[2]);
00270 }
00271
00272 if (!okflag) {
00273 objegg_cat.error()
00274 << "Invalid number at line " << _line_number << "\n";
00275 return false;
00276 }
00277
00278 EggVertex *vertex = get_vertex(_vti);
00279 if (words.size() == 4) {
00280 vertex->set_uvw("", uvw);
00281 } else {
00282 vertex->set_uv("", LTexCoordd(uvw[0], uvw[1]));
00283 }
00284 ++_vti;
00285
00286 return true;
00287 }
00288
00289
00290
00291
00292
00293
00294 bool ObjToEggConverter::
00295 process_vn(vector_string &words) {
00296 if (words.size() != 4) {
00297 objegg_cat.error()
00298 << "Wrong number of tokens at line " << _line_number << "\n";
00299 return false;
00300 }
00301
00302 bool okflag = true;
00303 LVector3d normal;
00304 okflag &= string_to_double(words[1], normal[0]);
00305 okflag &= string_to_double(words[2], normal[1]);
00306 okflag &= string_to_double(words[3], normal[2]);
00307
00308 if (!okflag) {
00309 objegg_cat.error()
00310 << "Invalid number at line " << _line_number << "\n";
00311 return false;
00312 }
00313 normal.normalize();
00314
00315 EggVertex *vertex = get_vertex(_vni);
00316 vertex->set_normal(normal);
00317 ++_vni;
00318
00319 return true;
00320 }
00321
00322
00323
00324
00325
00326
00327 bool ObjToEggConverter::
00328 process_f(vector_string &words) {
00329 PT(EggPolygon) poly = new EggPolygon;
00330 for (size_t i = 1; i < words.size(); ++i) {
00331 EggVertex *vertex = get_face_vertex(words[i]);
00332 if (vertex == NULL) {
00333 return false;
00334 }
00335 poly->add_vertex(vertex);
00336 }
00337 _current_group->add_child(poly);
00338
00339 return true;
00340 }
00341
00342
00343
00344
00345
00346
00347 bool ObjToEggConverter::
00348 process_g(vector_string &words) {
00349 EggGroup *group = _root_group;
00350
00351
00352
00353
00354
00355
00356 size_t i = words.size();
00357 while (i != 0) {
00358 --i;
00359 EggNode *child = group->find_child(words[i]);
00360 if (child == NULL || !child->is_of_type(EggGroup::get_class_type())) {
00361 child = new EggGroup(words[i]);
00362 group->add_child(child);
00363 }
00364 group = DCAST(EggGroup, child);
00365 }
00366
00367 _current_group = group;
00368 return true;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377 EggVertex *ObjToEggConverter::
00378 get_vertex(int n) {
00379 if (n < 0) {
00380
00381 n = _vi + n;
00382 }
00383 EggVertex *vertex = _vpool->get_vertex(n);
00384 if (vertex == NULL) {
00385 vertex = new EggVertex;
00386 _vpool->add_vertex(vertex, n);
00387 }
00388
00389 return vertex;
00390 }
00391
00392
00393
00394
00395
00396
00397
00398 EggVertex *ObjToEggConverter::
00399 get_face_vertex(const string &reference) {
00400 vector_string words;
00401 tokenize(reference, words, "/", false);
00402 nassertr(!words.empty(), NULL);
00403
00404 vector<EggVertex *> vertices;
00405 vertices.reserve(words.size());
00406 for (size_t i = 0; i < words.size(); ++i) {
00407 if (trim(words[i]).empty()) {
00408 if (i == 0) {
00409 objegg_cat.error()
00410 << "Invalid null vertex at line " << _line_number << "\n";
00411 return NULL;
00412 } else {
00413 vertices.push_back(vertices[0]);
00414 continue;
00415 }
00416 }
00417
00418 int index;
00419 if (!string_to_int(words[i], index)) {
00420 objegg_cat.error()
00421 << "Invalid integer " << words[i] << " at line " << _line_number << "\n";
00422 return NULL;
00423 }
00424 EggVertex *vertex = get_vertex(index);
00425 if (vertex == NULL){
00426 objegg_cat.error()
00427 << "Invalid vertex " << index << " at line " << _line_number << "\n";
00428 return NULL;
00429 }
00430 vertices.push_back(vertex);
00431 }
00432 nassertr(!vertices.empty(), NULL);
00433 nassertr(vertices.size() == words.size(), NULL);
00434
00435 if (vertices.size() == 1) {
00436
00437 return vertices[0];
00438
00439 } else if (vertices.size() == 2) {
00440
00441 if (vertices[0] == vertices[1]) {
00442 return vertices[0];
00443 }
00444
00445 EggVertex synth(*vertices[0]);
00446 if (vertices[1]->has_uv("")) {
00447 synth.set_uv("", vertices[1]->get_uv(""));
00448 } else if (vertices[1]->has_uvw("")) {
00449 synth.set_uvw("", vertices[1]->get_uvw(""));
00450 }
00451
00452 return _vpool->create_unique_vertex(synth);
00453
00454 } else if (vertices.size() >= 3) {
00455
00456 if (vertices[0] == vertices[1] && vertices[0] == vertices[2]) {
00457 return vertices[0];
00458 }
00459
00460
00461 EggVertex synth(*vertices[0]);
00462 if (vertices[1]->has_uv("")) {
00463 synth.set_uv("", vertices[1]->get_uv(""));
00464 } else if (vertices[1]->has_uvw("")) {
00465 synth.set_uvw("", vertices[1]->get_uvw(""));
00466 }
00467 if (vertices[2]->has_normal()) {
00468 synth.set_normal(vertices[2]->get_normal());
00469 }
00470
00471 return _vpool->create_unique_vertex(synth);
00472 }
00473
00474 return NULL;
00475 }