Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

aseloader.cpp

Go to the documentation of this file.
00001 /*
00002     Sheep - A Rigid Body Dynamics Engine
00003     Copyright (C) 2001-2004 Francois Beaune
00004     Contact: http://toxicengine.sourceforge.net/
00005 
00006     This file is part of Sheep.
00007 
00008     Sheep is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     Sheep is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with Sheep; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #include "aseloader.h"  // include first
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 //#define VERBOSE
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 /*= DEFAULT_CONFIGURATION_BIT*/,
00073                      ProgressMonitor *progmon /*= 0*/)
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     //!\todo Close files and free resources.
00117     throw ParsingException(m_line);
00118 }
00119 
00120 void ASELoader::next() {
00121     int c;
00122 
00123     // Eat blanks.
00124     do {
00125         c = read_char();
00126     } while(isspace(c));
00127 
00128     // End of file.
00129     if(c == EOF)
00130         m_look_ahead.m_sym = END_OF_FILE;
00131 
00132     // Identifier.
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     // String.
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     // Number (integer or double).
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     // Keyword.
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     // Single character.
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;    // keep the compiler happy
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); // *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);   // *MATERIAL_REF
00330             m_mesh_data.back()->m_material_index = accept_integer();
00331             break;
00332 
00333         case NODE_NAME:
00334             {
00335                 accept(NODE_NAME);  // *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);    // *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);    // *MAP_DIFFUSE
00370     accept('{');
00371 
00372     while(true) {
00373         switch(look_ahead()) {
00374 
00375         case BITMAP:
00376             {
00377                 accept(BITMAP); // *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                     //!\todo Close files and free resources.
00401 
00402                     // There is no distinction between a missing texture file
00403                     // and an invalid texture file.
00404                     if(m_option_mask & STOP_ON_MISSING_FILE_BIT) {
00405                         m_matbuilder->EndMaterial();
00406                         throw FileNotFoundException(filename);
00407                     }
00408 
00409                     // Ignore invalid or missing texture file.
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 /*= false*/,
00431                                int submaterial_index /*= 0*/)
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);   // *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);   // *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);  // *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);      // *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);    // forbid *SUBMATERIAL inside *SUBMATERIAL
00499 
00500                 close_material = false;
00501 
00502                 // This material has one more submaterial.
00503                 ++m_submaterial_count[material_index];
00504 
00505                 accept(SUBMATERIAL);    // *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);  // *MATERIAL_LIST
00533     accept('{');
00534 
00535     while(true) {
00536         switch(look_ahead()) {
00537         case MATERIAL:
00538             {
00539                 accept(MATERIAL);   // *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);   // *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); // *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;     // no texture coordinates by default
00609                     f.m_normal_index[i] = -1;       // no normals by default
00610                 }
00611 
00612                 accept(MESH_FACE);      // *MESH_FACE
00613                 accept(INTEGER);        // face index
00614                 accept(':');
00615 
00616                 for(int i = 0; i < 3; ++i) {
00617                     accept(IDENTIFIER); // A, B, C
00618                     accept(':');
00619                     f.m_vertex_index[i] = accept_integer();
00620                 }
00621 
00622                 for(int i = 0; i < 3; ++i) {
00623                     accept(IDENTIFIER); // AB, BC, CA
00624                     accept(':');
00625                     accept(INTEGER);    // edge visibility (0 or 1)
00626                 }
00627 
00628                 accept(MESH_SMOOTHING); // *MESH_SMOOTHING
00629 
00630                 if(look_ahead() == INTEGER) {
00631                     f.m_sg.push_back(accept_integer()); // smooth group index
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()); // smooth group index
00642                         else if(look_ahead() == MESH_MTLID)
00643                             break;
00644                         else parse_error();
00645                     }
00646                 }
00647 
00648                 accept(MESH_MTLID);     // *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);   // *MESH_NORMALS
00670     accept('{');
00671 
00672     while(true) {
00673         switch(look_ahead()) {
00674         case MESH_FACENORMAL:
00675             {
00676                 accept(MESH_FACENORMAL);        // *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                 // Skip face normal coordinates.
00682                 accept(DOUBLE);
00683                 accept(DOUBLE);
00684                 accept(DOUBLE);
00685 
00686                 for(int i = 0; i < 3; ++i) {
00687                     accept(MESH_VERTEXNORMAL);  // *MESH_VERTEXNORMAL
00688                     accept(INTEGER);            // vertex index
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); // *MESH_TFACELIST
00717     accept('{');
00718 
00719     while(true) {
00720         switch(look_ahead()) {
00721         case MESH_TFACE:
00722             {
00723                 accept(MESH_TFACE); // *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); // *MESH_TVERTLIST
00747     accept('{');
00748 
00749     while(true) {
00750         switch(look_ahead()) {
00751         case MESH_TVERT:
00752             {
00753                 accept(MESH_TVERT); // *MESH_TVERT
00754                 accept(INTEGER);    // texture coordinate index
00755 
00756                 Vector2 v;
00757 
00758                 v.m_x = accept_double();
00759                 v.m_y = -accept_double();
00760 
00761                 // Skip W coordinate.
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);   // *MESH_VERTEX_LIST
00781     accept('{');
00782 
00783     while(true) {
00784         switch(look_ahead()) {
00785         case MESH_VERTEX:
00786             {
00787                 accept(MESH_VERTEX);    // *MESH_VERTEX
00788                 accept(INTEGER);        // vertex index
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     // For each mesh data block.
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         // Fix submaterial indices.
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         // Gather submaterial indices.
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         // Remove duplicates from the submaterial index vector.
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             // Create a new mesh.
00854             m_geombuilder->BeginSubMesh("");
00855 
00856             if(m_matbuilder) {
00857                 if(mesh->m_material_index == -1) {
00858                     // No material has been assigned to the mesh, use the wireframe color if defined.
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                     // Assign the right material to the mesh.
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                 // Append face vertices to the current mesh.
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                 // Append the new face to the current mesh.
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                     // Append face texture coordinates to the current mesh.
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                     // Set texture coordinates for current face vertices.
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                     // Append face normals to the current mesh.
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                     // Set normals for current face vertices.
00924                     m_geombuilder->SetFaceNormals(face_id, 3, normal_id);
00925                 }
00926             }
00927 
00928             // Close the mesh.
00929             m_geombuilder->EndSubMesh();
00930         }
00931 
00932         delete mesh;
00933     }
00934 }

Generated on Tue May 11 01:31:49 2004 for toxic by doxygen 1.3.6