00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "aseloader.h"
00024 #include "common/misc/progressmonitor.h"
00025 #include "common/misc/stringutils.h"
00026
00027 #include <algorithm>
00028 #include <cctype>
00029 #include <IL/il.h>
00030
00031
00032
00033 #ifdef VERBOSE
00034 #include <iostream>
00035 #endif // VERBOSE
00036
00037 using namespace sheep;
00038 using namespace std;
00039
00040 ASELoader::ASELoader() {
00041 m_keyword_table.Insert("BITMAP", BITMAP);
00042 m_keyword_table.Insert("GEOMOBJECT", GEOMOBJECT);
00043 m_keyword_table.Insert("MAP_DIFFUSE", MAP_DIFFUSE);
00044 m_keyword_table.Insert("MATERIAL", MATERIAL);
00045 m_keyword_table.Insert("MATERIAL_AMBIENT", MATERIAL_AMBIENT);
00046 m_keyword_table.Insert("MATERIAL_DIFFUSE", MATERIAL_DIFFUSE);
00047 m_keyword_table.Insert("MATERIAL_LIST", MATERIAL_LIST);
00048 m_keyword_table.Insert("MATERIAL_NAME", MATERIAL_NAME);
00049 m_keyword_table.Insert("MATERIAL_REF", MATERIAL_REF);
00050 m_keyword_table.Insert("MATERIAL_SPECULAR", MATERIAL_SPECULAR);
00051 m_keyword_table.Insert("MESH", MESH);
00052 m_keyword_table.Insert("MESH_FACE", MESH_FACE);
00053 m_keyword_table.Insert("MESH_FACE_LIST", MESH_FACE_LIST);
00054 m_keyword_table.Insert("MESH_FACENORMAL", MESH_FACENORMAL);
00055 m_keyword_table.Insert("MESH_MTLID", MESH_MTLID);
00056 m_keyword_table.Insert("MESH_NORMALS", MESH_NORMALS);
00057 m_keyword_table.Insert("MESH_SMOOTHING", MESH_SMOOTHING);
00058 m_keyword_table.Insert("MESH_TFACE", MESH_TFACE);
00059 m_keyword_table.Insert("MESH_TFACELIST", MESH_TFACELIST);
00060 m_keyword_table.Insert("MESH_TVERT", MESH_TVERT);
00061 m_keyword_table.Insert("MESH_TVERTLIST", MESH_TVERTLIST);
00062 m_keyword_table.Insert("MESH_VERTEX", MESH_VERTEX);
00063 m_keyword_table.Insert("MESH_VERTEX_LIST", MESH_VERTEX_LIST);
00064 m_keyword_table.Insert("MESH_VERTEXNORMAL", MESH_VERTEXNORMAL);
00065 m_keyword_table.Insert("NODE_NAME", NODE_NAME);
00066 m_keyword_table.Insert("SUBMATERIAL", SUBMATERIAL);
00067 m_keyword_table.Insert("WIREFRAME_COLOR", WIREFRAME_COLOR);
00068 }
00069
00070 void ASELoader::Load(const string &filename,
00071 IMeshBuilder &builder,
00072 int option_mask ,
00073 ProgressMonitor *progmon )
00074 {
00075 m_path = StringUtils::GetPath(filename);
00076
00077 m_geombuilder = builder.GeometryBuilder();
00078 m_matbuilder = builder.MaterialBuilder();
00079
00080 m_option_mask = option_mask;
00081
00082 m_progmon = progmon;
00083
00084 m_file = fopen(filename.c_str(), "r");
00085
00086 if(!m_file)
00087 throw FileNotFoundException(filename);
00088
00089 if(m_progmon) {
00090 fseek(m_file, 0, SEEK_END);
00091 m_progmon->StartJob(0, ftell(m_file));
00092 fseek(m_file, 0, SEEK_SET);
00093 }
00094
00095 m_line = 1;
00096
00097 next();
00098
00099 m_geomobject_index = 0;
00100
00101 m_mat_key_to_mat_id.clear();
00102 m_mesh_data.clear();
00103
00104 parse_file();
00105
00106 if(m_geombuilder)
00107 dispatch_mesh_data();
00108
00109 if(m_progmon)
00110 m_progmon->Done();
00111
00112 fclose(m_file);
00113 }
00114
00115 void ASELoader::parse_error() {
00116
00117 throw ParsingException(m_line);
00118 }
00119
00120 void ASELoader::next() {
00121 int c;
00122
00123
00124 do {
00125 c = read_char();
00126 } while(isspace(c));
00127
00128
00129 if(c == EOF)
00130 m_look_ahead.m_sym = END_OF_FILE;
00131
00132
00133 else if(isalpha(c) || c == '_') {
00134 m_look_ahead.m_sym = IDENTIFIER;
00135 m_look_ahead.m_val.m_str = "";
00136
00137 while(isalpha(c)) {
00138 m_look_ahead.m_val.m_str += c;
00139
00140 c = read_char();
00141 }
00142
00143 unread_char(c);
00144 }
00145
00146
00147 else if(c == '"') {
00148 m_look_ahead.m_sym = STRING;
00149 m_look_ahead.m_val.m_str = "";
00150
00151 while(true) {
00152 c = read_char();
00153
00154 if(c == '"')
00155 break;
00156
00157 m_look_ahead.m_val.m_str += c;
00158 }
00159 }
00160
00161
00162 else if(c == '+' || c == '-' || c == '.' || isdigit(c)) {
00163 string number;
00164 number = c;
00165
00166 while(true) {
00167 c = read_char();
00168
00169 if(!(isdigit(c) || c == '.'))
00170 break;
00171
00172 number += c;
00173 }
00174
00175 unread_char(c);
00176
00177 if(number.find('.') == string::npos) {
00178 m_look_ahead.m_sym = INTEGER;
00179 m_look_ahead.m_val.m_int = atoi(number.c_str());
00180 } else {
00181 m_look_ahead.m_sym = DOUBLE;
00182 m_look_ahead.m_val.m_dbl = atof(number.c_str());
00183 }
00184 }
00185
00186
00187 else if(c == '*') {
00188 string keyword = "";
00189
00190 while(true) {
00191 c = read_char();
00192
00193 if(!(isalnum(c) || c == '_'))
00194 break;
00195
00196 keyword += c;
00197 }
00198
00199 unread_char(c);
00200
00201 const int symbol = m_keyword_table.GetSymbol(keyword);
00202
00203 m_look_ahead.m_sym = (symbol == -1) ? UNKNOWN_KEYWORD : symbol;
00204 }
00205
00206
00207 else {
00208 assert(c != EOF);
00209 m_look_ahead.m_sym = c;
00210 }
00211 }
00212
00213 void ASELoader::accept(int token) {
00214 if(look_ahead() == token)
00215 next();
00216 else parse_error();
00217 }
00218
00219 string ASELoader::accept_string() {
00220 if(look_ahead() != STRING)
00221 parse_error();
00222
00223 const string s = m_look_ahead.m_val.m_str;
00224
00225 next();
00226
00227 return s;
00228 }
00229
00230 int ASELoader::accept_integer() {
00231 if(look_ahead() != INTEGER)
00232 parse_error();
00233
00234 const int n = m_look_ahead.m_val.m_int;
00235
00236 next();
00237
00238 return n;
00239 }
00240
00241 double ASELoader::accept_double() {
00242 double d;
00243
00244 if(look_ahead() == DOUBLE)
00245 d = m_look_ahead.m_val.m_dbl;
00246 else if(look_ahead() == INTEGER)
00247 d = m_look_ahead.m_val.m_int;
00248 else {
00249 d = 0.0;
00250 parse_error();
00251 }
00252
00253 next();
00254
00255 return d;
00256 }
00257
00258 void ASELoader::skip_compound() {
00259 accept('{');
00260
00261 while(true) {
00262 const int token = look_ahead();
00263
00264 if(token == '{')
00265 skip_compound();
00266 else if(token == '}')
00267 break;
00268 else next();
00269 }
00270
00271 accept('}');
00272 }
00273
00274 void ASELoader::skip_statement() {
00275 while(true) {
00276 next();
00277
00278 const int token = look_ahead();
00279
00280 if(token == '{') {
00281 skip_compound();
00282 break;
00283 } else if(token == '}')
00284 break;
00285 else if(m_keyword_table.IsKeyword(token))
00286 break;
00287 }
00288 }
00289
00290 void ASELoader::parse_file() {
00291 while(true) {
00292 switch(look_ahead()) {
00293 case MATERIAL_LIST:
00294 if(m_matbuilder)
00295 parse_material_list();
00296 else skip_statement();
00297 break;
00298 case GEOMOBJECT:
00299 if(m_geombuilder)
00300 parse_geomobject();
00301 else skip_statement();
00302 ++m_geomobject_index;
00303 break;
00304 case UNKNOWN_KEYWORD:
00305 skip_statement();
00306 break;
00307 case END_OF_FILE:
00308 return;
00309 default:
00310 parse_error();
00311 }
00312 }
00313 }
00314
00315 void ASELoader::parse_geomobject() {
00316 accept(GEOMOBJECT);
00317 accept('{');
00318
00319 m_mesh_data.push_back(new mesh_data());
00320
00321 while(true) {
00322 switch(look_ahead()) {
00323
00324 case MESH:
00325 parse_mesh();
00326 break;
00327
00328 case MATERIAL_REF:
00329 accept(MATERIAL_REF);
00330 m_mesh_data.back()->m_material_index = accept_integer();
00331 break;
00332
00333 case NODE_NAME:
00334 {
00335 accept(NODE_NAME);
00336
00337 const string mesh_name = accept_string();
00338
00339 #ifdef VERBOSE
00340 cerr << "[ASELoader] Loading mesh '" << mesh_name << "'..." << endl;
00341 #endif // VERBOSE
00342 }
00343 break;
00344
00345 case WIREFRAME_COLOR:
00346 accept(WIREFRAME_COLOR);
00347 m_mesh_data.back()->m_has_wf_color = true;
00348 m_mesh_data.back()->m_wf_r = accept_double();
00349 m_mesh_data.back()->m_wf_g = accept_double();
00350 m_mesh_data.back()->m_wf_b = accept_double();
00351 break;
00352
00353 case UNKNOWN_KEYWORD:
00354 skip_statement();
00355 break;
00356
00357 case '}':
00358 accept('}');
00359 return;
00360
00361 default:
00362 parse_error();
00363
00364 }
00365 }
00366 }
00367
00368 void ASELoader::parse_map_diffuse() {
00369 accept(MAP_DIFFUSE);
00370 accept('{');
00371
00372 while(true) {
00373 switch(look_ahead()) {
00374
00375 case BITMAP:
00376 {
00377 accept(BITMAP);
00378
00379 ILuint image_id;
00380
00381 ilGenImages(1, &image_id);
00382 ilBindImage(image_id);
00383
00384 const string filename = accept_string();
00385
00386 if(TryLoadingImage(m_path, filename)) {
00387 const int w = ilGetInteger(IL_IMAGE_WIDTH);
00388 const int h = ilGetInteger(IL_IMAGE_HEIGHT);
00389
00390 unsigned char *texels = new unsigned char[w * h * 3];
00391
00392 ilCopyPixels(0, 0, 0, w, h, 1, IL_RGB, IL_UNSIGNED_BYTE, texels);
00393
00394 ilDeleteImages(1, &image_id);
00395
00396 m_matbuilder->SetTexture(w, h, texels);
00397
00398 delete [] texels;
00399 } else {
00400
00401
00402
00403
00404 if(m_option_mask & STOP_ON_MISSING_FILE_BIT) {
00405 m_matbuilder->EndMaterial();
00406 throw FileNotFoundException(filename);
00407 }
00408
00409
00410 }
00411 }
00412 break;
00413
00414 case UNKNOWN_KEYWORD:
00415 skip_statement();
00416 break;
00417
00418 case '}':
00419 accept('}');
00420 return;
00421
00422 default:
00423 parse_error();
00424
00425 }
00426 }
00427 }
00428
00429 void ASELoader::parse_material(int material_index,
00430 bool is_submaterial ,
00431 int submaterial_index )
00432 {
00433 accept('{');
00434
00435 bool close_material = true;
00436
00437 const material_key key(material_index, submaterial_index);
00438
00439 if(!is_submaterial || submaterial_index != 0)
00440 m_mat_key_to_mat_id[key] = m_matbuilder->BeginMaterial("");
00441
00442 while(true) {
00443 switch(look_ahead()) {
00444
00445 case MAP_DIFFUSE:
00446 parse_map_diffuse();
00447 break;
00448
00449 case MATERIAL_AMBIENT:
00450 {
00451 accept(MATERIAL_AMBIENT);
00452
00453 const Real r = accept_double();
00454 const Real g = accept_double();
00455 const Real b = accept_double();
00456
00457 m_matbuilder->SetAmbientColor(r, g, b);
00458 }
00459 break;
00460
00461 case MATERIAL_DIFFUSE:
00462 {
00463 accept(MATERIAL_DIFFUSE);
00464
00465 const Real r = accept_double();
00466 const Real g = accept_double();
00467 const Real b = accept_double();
00468
00469 m_matbuilder->SetDiffuseColor(r, g, b);
00470 }
00471 break;
00472
00473 case MATERIAL_SPECULAR:
00474 {
00475 accept(MATERIAL_SPECULAR);
00476
00477 const Real r = accept_double();
00478 const Real g = accept_double();
00479 const Real b = accept_double();
00480
00481 m_matbuilder->SetSpecularColor(r, g, b);
00482 }
00483 break;
00484
00485 case MATERIAL_NAME:
00486 {
00487 accept(MATERIAL_NAME);
00488 const string material_name = accept_string();
00489
00490 #ifdef VERBOSE
00491 cerr << "[ASELoader] Loading material '" << material_name << "'..." << endl;
00492 #endif // VERBOSE
00493 }
00494 break;
00495
00496 case SUBMATERIAL:
00497 {
00498 assert(!is_submaterial);
00499
00500 close_material = false;
00501
00502
00503 ++m_submaterial_count[material_index];
00504
00505 accept(SUBMATERIAL);
00506 const int submaterial_index = accept_integer();
00507
00508 parse_material(
00509 material_index,
00510 true,
00511 submaterial_index);
00512 }
00513 break;
00514
00515 case UNKNOWN_KEYWORD:
00516 skip_statement();
00517 break;
00518
00519 case '}':
00520 accept('}');
00521 if(close_material)
00522 m_matbuilder->EndMaterial();
00523 return;
00524
00525 default:
00526 parse_error();
00527 }
00528 }
00529 }
00530
00531 void ASELoader::parse_material_list() {
00532 accept(MATERIAL_LIST);
00533 accept('{');
00534
00535 while(true) {
00536 switch(look_ahead()) {
00537 case MATERIAL:
00538 {
00539 accept(MATERIAL);
00540 const int material_index = accept_integer();
00541 parse_material(material_index);
00542 }
00543 break;
00544 case UNKNOWN_KEYWORD:
00545 skip_statement();
00546 break;
00547 case '}':
00548 accept('}');
00549 return;
00550 default:
00551 parse_error();
00552 }
00553
00554 if(m_progmon) {
00555 m_progmon->SetJobProgress(ftell(m_file));
00556 }
00557 }
00558 }
00559
00560 void ASELoader::parse_mesh() {
00561 accept(MESH);
00562 accept('{');
00563
00564 while(true) {
00565 switch(look_ahead()) {
00566 case MESH_FACE_LIST:
00567 parse_mesh_face_list();
00568 break;
00569 case MESH_NORMALS:
00570 parse_mesh_normals();
00571 break;
00572 case MESH_TFACELIST:
00573 parse_mesh_tfacelist();
00574 break;
00575 case MESH_TVERTLIST:
00576 parse_mesh_tvertlist();
00577 break;
00578 case MESH_VERTEX_LIST:
00579 parse_mesh_vertex_list();
00580 break;
00581 case UNKNOWN_KEYWORD:
00582 skip_statement();
00583 break;
00584 case '}':
00585 accept('}');
00586 return;
00587 default:
00588 parse_error();
00589 }
00590
00591 if(m_progmon) {
00592 m_progmon->SetJobProgress(ftell(m_file));
00593 }
00594 }
00595 }
00596
00597 void ASELoader::parse_mesh_face_list() {
00598 accept(MESH_FACE_LIST);
00599 accept('{');
00600
00601 while(true) {
00602 switch(look_ahead()) {
00603 case MESH_FACE:
00604 {
00605 mesh_data::face f;
00606
00607 for(int i = 0; i < 3; ++i) {
00608 f.m_texcoord_index[i] = -1;
00609 f.m_normal_index[i] = -1;
00610 }
00611
00612 accept(MESH_FACE);
00613 accept(INTEGER);
00614 accept(':');
00615
00616 for(int i = 0; i < 3; ++i) {
00617 accept(IDENTIFIER);
00618 accept(':');
00619 f.m_vertex_index[i] = accept_integer();
00620 }
00621
00622 for(int i = 0; i < 3; ++i) {
00623 accept(IDENTIFIER);
00624 accept(':');
00625 accept(INTEGER);
00626 }
00627
00628 accept(MESH_SMOOTHING);
00629
00630 if(look_ahead() == INTEGER) {
00631 f.m_sg.push_back(accept_integer());
00632
00633 while(true) {
00634 if(look_ahead() == ',')
00635 accept(',');
00636 else if(look_ahead() == MESH_MTLID)
00637 break;
00638 else parse_error();
00639
00640 if(look_ahead() == INTEGER)
00641 f.m_sg.push_back(accept_integer());
00642 else if(look_ahead() == MESH_MTLID)
00643 break;
00644 else parse_error();
00645 }
00646 }
00647
00648 accept(MESH_MTLID);
00649 f.m_submaterial_index = accept_integer();
00650
00651 assert(f.m_submaterial_index >= 0);
00652
00653 m_mesh_data.back()->m_faces.push_back(f);
00654 }
00655 break;
00656 case UNKNOWN_KEYWORD:
00657 skip_statement();
00658 break;
00659 case '}':
00660 accept('}');
00661 return;
00662 default:
00663 parse_error();
00664 }
00665 }
00666 }
00667
00668 void ASELoader::parse_mesh_normals() {
00669 accept(MESH_NORMALS);
00670 accept('{');
00671
00672 while(true) {
00673 switch(look_ahead()) {
00674 case MESH_FACENORMAL:
00675 {
00676 accept(MESH_FACENORMAL);
00677
00678 const int face_index = accept_integer();
00679 mesh_data::face &f = m_mesh_data.back()->m_faces[face_index];
00680
00681
00682 accept(DOUBLE);
00683 accept(DOUBLE);
00684 accept(DOUBLE);
00685
00686 for(int i = 0; i < 3; ++i) {
00687 accept(MESH_VERTEXNORMAL);
00688 accept(INTEGER);
00689
00690 Vector3 n;
00691
00692 n.m_x = accept_double();
00693 n.m_z = -accept_double();
00694 n.m_y = accept_double();
00695
00696 n.Normalize();
00697
00698 f.m_normal_index[i] = m_mesh_data.back()->m_normals.size();
00699 m_mesh_data.back()->m_normals.push_back(n);
00700 }
00701 }
00702 break;
00703 case UNKNOWN_KEYWORD:
00704 skip_statement();
00705 break;
00706 case '}':
00707 accept('}');
00708 return;
00709 default:
00710 parse_error();
00711 }
00712 }
00713 }
00714
00715 void ASELoader::parse_mesh_tfacelist() {
00716 accept(MESH_TFACELIST);
00717 accept('{');
00718
00719 while(true) {
00720 switch(look_ahead()) {
00721 case MESH_TFACE:
00722 {
00723 accept(MESH_TFACE);
00724
00725 const int face_index = accept_integer();
00726 mesh_data::face &f = m_mesh_data.back()->m_faces[face_index];
00727
00728 f.m_texcoord_index[0] = accept_integer();
00729 f.m_texcoord_index[1] = accept_integer();
00730 f.m_texcoord_index[2] = accept_integer();
00731 }
00732 break;
00733 case UNKNOWN_KEYWORD:
00734 skip_statement();
00735 break;
00736 case '}':
00737 accept('}');
00738 return;
00739 default:
00740 parse_error();
00741 }
00742 }
00743 }
00744
00745 void ASELoader::parse_mesh_tvertlist() {
00746 accept(MESH_TVERTLIST);
00747 accept('{');
00748
00749 while(true) {
00750 switch(look_ahead()) {
00751 case MESH_TVERT:
00752 {
00753 accept(MESH_TVERT);
00754 accept(INTEGER);
00755
00756 Vector2 v;
00757
00758 v.m_x = accept_double();
00759 v.m_y = -accept_double();
00760
00761
00762 accept(DOUBLE);
00763
00764 m_mesh_data.back()->m_texcoords.push_back(v);
00765 }
00766 break;
00767 case UNKNOWN_KEYWORD:
00768 skip_statement();
00769 break;
00770 case '}':
00771 accept('}');
00772 return;
00773 default:
00774 parse_error();
00775 }
00776 }
00777 }
00778
00779 void ASELoader::parse_mesh_vertex_list() {
00780 accept(MESH_VERTEX_LIST);
00781 accept('{');
00782
00783 while(true) {
00784 switch(look_ahead()) {
00785 case MESH_VERTEX:
00786 {
00787 accept(MESH_VERTEX);
00788 accept(INTEGER);
00789
00790 Vector3 v;
00791
00792 v.m_x = accept_double();
00793 v.m_z = -accept_double();
00794 v.m_y = accept_double();
00795
00796 m_mesh_data.back()->m_vertices.push_back(v);
00797 }
00798 break;
00799 case UNKNOWN_KEYWORD:
00800 skip_statement();
00801 break;
00802 case '}':
00803 accept('}');
00804 return;
00805 default:
00806 parse_error();
00807 }
00808 }
00809 }
00810
00811 void ASELoader::dispatch_mesh_data() {
00812 assert(m_geombuilder);
00813
00814
00815 for(mesh_data_vector::iterator i = m_mesh_data.begin(),
00816 ie = m_mesh_data.end(); i != ie; ++i)
00817 {
00818 mesh_data *mesh = *i;
00819 const int submaterial_count = m_submaterial_count[mesh->m_material_index];
00820
00821
00822 for(vector<mesh_data::face>::iterator j = mesh->m_faces.begin(),
00823 je = mesh->m_faces.end(); j != je; ++j)
00824 {
00825 mesh_data::face &f = *j;
00826
00827 if(submaterial_count > 0)
00828 f.m_submaterial_index %= submaterial_count;
00829 else f.m_submaterial_index = 0;
00830 }
00831
00832 vector<int> submaterial_index_vector;
00833
00834
00835 for(vector<mesh_data::face>::const_iterator j = mesh->m_faces.begin(),
00836 je = mesh->m_faces.end(); j != je; ++j)
00837 {
00838 const mesh_data::face &f = *j;
00839 submaterial_index_vector.push_back(f.m_submaterial_index);
00840 }
00841
00842
00843 sort(submaterial_index_vector.begin(), submaterial_index_vector.end());
00844 submaterial_index_vector.erase(
00845 unique(submaterial_index_vector.begin(), submaterial_index_vector.end()),
00846 submaterial_index_vector.end());
00847
00848 for(vector<int>::const_iterator j = submaterial_index_vector.begin(),
00849 je = submaterial_index_vector.end(); j != je; ++j)
00850 {
00851 const int submaterial_index = *j;
00852
00853
00854 m_geombuilder->BeginSubMesh("");
00855
00856 if(m_matbuilder) {
00857 if(mesh->m_material_index == -1) {
00858
00859 if(mesh->m_has_wf_color) {
00860 const IMeshBuilder::FeatureId material_id =
00861 m_matbuilder->BeginMaterial("");
00862 m_matbuilder->SetDiffuseColor(
00863 mesh->m_wf_r, mesh->m_wf_g, mesh->m_wf_b);
00864 m_matbuilder->EndMaterial();
00865 m_geombuilder->SetMaterial(material_id);
00866 }
00867 } else {
00868
00869 const material_key key(mesh->m_material_index, submaterial_index);
00870 assert(m_mat_key_to_mat_id.find(key) != m_mat_key_to_mat_id.end());
00871 const IMeshBuilder::FeatureId material_id = m_mat_key_to_mat_id[key];
00872 m_geombuilder->SetMaterial(material_id);
00873 }
00874 }
00875
00876 map<int, IMeshBuilder::FeatureId> global_vertex_id;
00877
00878 for(vector<mesh_data::face>::const_iterator k = mesh->m_faces.begin(),
00879 ke = mesh->m_faces.end(); k != ke; ++k)
00880 {
00881 const mesh_data::face &f = *k;
00882
00883 if(f.m_submaterial_index != submaterial_index)
00884 continue;
00885
00886 IMeshBuilder::FeatureId vertex_id[3];
00887
00888
00889 for(int i = 0; i < 3; ++i) {
00890 const int vertex_index = f.m_vertex_index[i];
00891
00892 if(global_vertex_id.find(vertex_index) == global_vertex_id.end()) {
00893 global_vertex_id[vertex_index] = vertex_id[i] =
00894 m_geombuilder->AppendVertex(mesh->m_vertices[vertex_index]);
00895 } else vertex_id[i] = global_vertex_id[vertex_index];
00896 }
00897
00898
00899 const IMeshBuilder::FeatureId face_id = m_geombuilder->AppendFace(3, vertex_id);
00900
00901 if(f.m_texcoord_index[0] != -1) {
00902 IMeshBuilder::FeatureId texcoord_id[3];
00903
00904
00905 for(int i = 0; i < 3; ++i) {
00906 const int texcoord_index = f.m_texcoord_index[i];
00907 texcoord_id[i] = m_geombuilder->AppendTexCoord(mesh->m_texcoords[texcoord_index]);
00908 }
00909
00910
00911 m_geombuilder->SetFaceTexCoords(face_id, 3, texcoord_id);
00912 }
00913
00914 if(f.m_normal_index[0] != -1) {
00915 IMeshBuilder::FeatureId normal_id[3];
00916
00917
00918 for(int i = 0; i < 3; ++i) {
00919 const int normal_index = f.m_normal_index[i];
00920 normal_id[i] = m_geombuilder->AppendNormal(mesh->m_normals[normal_index]);
00921 }
00922
00923
00924 m_geombuilder->SetFaceNormals(face_id, 3, normal_id);
00925 }
00926 }
00927
00928
00929 m_geombuilder->EndSubMesh();
00930 }
00931
00932 delete mesh;
00933 }
00934 }