home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 4802 / template.7z / main.cpp next >
Encoding:
C/C++ Source or Header  |  2011-10-21  |  42.9 KB  |  1,329 lines

  1. #include "stdafx.h"
  2.  
  3. bool extract_TGP(const char* filename);
  4. bool process_MDL(const char* filename);
  5. bool parse(const char* data, deque<string>& list);
  6. string strip(const string& data, char c);
  7. string strip_trailing_spaces(const string& data);
  8.  
  9. class Exporter {
  10.  private :
  11.   struct Material {
  12.    string name;
  13.    string type;
  14.    deque<unsigned int> diffuse_texture_index;
  15.    float ambient[3];
  16.    float diffuse[3];
  17.    float specular[3];
  18.    float emissive[3];
  19.    float bump[3];
  20.    float opacity;
  21.    float shininess;
  22.    float reflectivity;
  23.   };
  24.   struct Texture {
  25.    string name;
  26.    string type;
  27.    string filename;
  28.   };
  29.   struct Skeleton {
  30.    string parent;
  31.    string type;
  32.    string order;
  33.    float translation[3];
  34.    float rotation[3];
  35.    float scale[3];
  36.   };
  37.   struct Polygon {
  38.    deque<unsigned int> material_index;
  39.    unsigned int face_index[3];
  40.    unsigned int uv_index[3];
  41.    unsigned int color[3];
  42.   };
  43.   struct Weight {
  44.    size_t index;
  45.    float value;
  46.   };
  47.   struct WeightMap {
  48.    size_t size;
  49.    string name;
  50.    deque<Weight> data;
  51.   };
  52.   struct Mesh {
  53.    string name;
  54.    deque<Polygon> polygon_list;
  55.    deque<vector3D<float>> vertex_list;
  56.    deque<WeightMap> weight_list;
  57.    deque<vector3D<float>> normal_list;
  58.    deque<vector2D<float>> uv_list;
  59.    deque<unsigned int> material_index_list;
  60.   };
  61.  private :
  62.   deque<string> line_list;
  63.   size_t curr_line;
  64.  private :
  65.   deque<Material> material_list;
  66.   deque<Texture> texture_list;
  67.   map<string, Skeleton> skeleton_list;
  68.   deque<Mesh> mesh_list;
  69.  private :
  70.   void clear(void);
  71.  public :
  72.   bool ProcessMaterialList(size_t n_materials);
  73.   bool ProcessMaterial(void);
  74.  public :
  75.   bool ProcessSkeletonList(size_t n_nodes);
  76.   bool ProcessSkeleton(void);
  77.  public :
  78.   bool ProcessMeshList(size_t n_meshes);
  79.   bool ProcessMesh(void);
  80.   bool ProcessPolygonList(size_t n_polygons, Mesh& mesh);
  81.   bool ProcessPolygon(Mesh& mesh);
  82.   bool ProcessVertexList(size_t n_points, Mesh& mesh);
  83.   bool ProcessWeightList(size_t n_weights, Mesh& mesh);
  84.   bool ProcessWeight(Mesh& mesh);
  85.   bool ProcessNormalList(size_t n_normals, Mesh& mesh);
  86.   bool ProcessUVList(size_t n_points, Mesh& mesh);
  87.   bool ProcessMaterialIndexList(size_t n_items, Mesh& mesh);
  88.  public :
  89.   bool ProcessTextureList(size_t n_textures);
  90.   bool ProcessTexture(void);
  91.  public :
  92.   bool process(const char* filename, const char* savename, const char* editname, const char* wavename, const char* wmtlname);
  93.  public :
  94.   Exporter();
  95.  ~Exporter();
  96.  private :
  97.   Exporter(const Exporter&);
  98.   void operator =(const Exporter&);
  99. };
  100.  
  101. int main()
  102. {
  103.  // create namelist
  104.  deque<string> namelist;
  105.  if(get_filename_list(namelist, "tgp")) {
  106.     for(size_t i = 0; i < namelist.size(); i++)
  107.         extract_TGP(namelist[i].c_str());
  108.    }
  109.  
  110.  // create model namelist
  111.  deque<string> filelist;
  112.  deque<string> savelist;
  113.  deque<string> editlist;
  114.  deque<string> wavelist;
  115.  deque<string> wmtllist;
  116.  
  117.  if(!get_filename_list(filelist, "mdl"))
  118.     return -1;
  119.  
  120.  for(size_t i = 0; i < filelist.size(); i++)
  121.     {
  122.      // extract filename parameters
  123.      char param1[MAX_PATH];
  124.      char param2[MAX_PATH];
  125.      char param3[MAX_PATH];
  126.      char param4[MAX_PATH];
  127.      _splitpath(filelist[i].c_str(), param1, param2, param3, param4);
  128.  
  129.      // change extension
  130.      string savename(param1);
  131.      savename += param2;
  132.      savename += param3;
  133.      savename += ".ls";
  134.      savelist.push_back(savename);
  135.  
  136.      // change extension
  137.      string wavename(param1);
  138.      wavename += param2;
  139.      wavename += param3;
  140.      wavename += ".obj";
  141.      wavelist.push_back(wavename);
  142.  
  143.      // change extension
  144.      string wmtlname(param1);
  145.      wmtlname += param2;
  146.      wmtlname += param3;
  147.      wmtlname += ".mtl";
  148.      wmtllist.push_back(wmtlname);
  149.  
  150.      // change extension
  151.      string editname(param1);
  152.      editname += param2;
  153.      editname += param3;
  154.      editname += ".txt";
  155.      editlist.push_back(editname);
  156.     }
  157.  
  158.  // process model files
  159.  for(size_t i = 0; i < filelist.size(); i++) {
  160.      cout << "Processing " << filelist[i].c_str() << "..." << endl;
  161.      Exporter e;
  162.      e.process(filelist[i].c_str(), savelist[i].c_str(), editlist[i].c_str(), wavelist[i].c_str(), wmtllist[i].c_str());
  163.     }
  164.  
  165.  return -1;
  166. }
  167.  
  168. Exporter::Exporter()
  169. {
  170. }
  171.  
  172. Exporter::~Exporter()
  173. {
  174. }
  175.  
  176. void Exporter::clear(void)
  177. {
  178.  // clear data
  179.  material_list.clear();
  180.  texture_list.clear();
  181.  skeleton_list.clear();
  182.  mesh_list.clear();
  183.  
  184.  // clear file data
  185.  line_list.clear();
  186.  curr_line = 0;
  187. }
  188.  
  189. bool Exporter::process(const char* filename, const char* savename, const char* editname, const char* wavename, const char* wmtlname)
  190. {
  191.  // clear data
  192.  clear();
  193.  
  194.  // open file
  195.  ifstream ifile(filename, ios::binary);
  196.  if(!ifile) return error("Cannot open file.");
  197.  
  198.  // edit file
  199.  ofstream efile(editname);
  200.  if(!ifile) return error("Cannot open file.");
  201.  
  202.  // load data line-by-line
  203.  for(;;)
  204.     {
  205.      // read line
  206.      char buffer[2048];
  207.      ifile.getline(buffer, 2048);
  208.      if(ifile.fail()) break;
  209.  
  210.      // must have data
  211.      string data(buffer);
  212.      if(data.length() == 0) continue;
  213.      if(data.length() == 1 && data[0] == 0x0A) continue;
  214.      if(data.length() == 1 && data[0] == 0x0D) continue;
  215.  
  216.      // remove comments
  217.      size_t position = data.find('#');
  218.      if(position == 0) continue;
  219.      if(position != string::npos) data = data.substr(0, position);
  220.      if(!data.length()) continue;
  221.  
  222.      // remove beginning spaces
  223.      size_t j = 0;
  224.      for(size_t i = 0; i < data.length(); i++) {
  225.          if(data[i] != 0x09) break;
  226.          else j++;
  227.         }
  228.      data = data.substr(j);
  229.      if(data.length() == 0) continue;
  230.      if(data.length() == 1 && data[0] == 0x0A) continue;
  231.      if(data.length() == 1 && data[0] == 0x0D) continue;
  232.  
  233.      // remove trailing spaces
  234.      data = strip_trailing_spaces(data);
  235.  
  236.      // insert line
  237.      line_list.push_back(data);
  238.      efile << data.c_str() << endl;
  239.     }
  240.  
  241.  // process data line-by-line
  242.  curr_line = 0;
  243.  do {
  244.     // parse line
  245.     deque<string> list;
  246.     if(parse(line_list[curr_line].c_str(), list) == false) break;
  247.  
  248.     // process root nodes
  249.     if(list[0] == "TGL Model Format Text Ver 0.8") curr_line++;
  250.     else if(list[0] == "MaterialList") {
  251.        if(list.size() < 2) return error("<MaterialList>: Expecting at least two arguments.");
  252.        cout << " <MaterialList>" << endl;
  253.        ProcessMaterialList(stoi(list[1].c_str()));
  254.       }
  255.     else if(list[0] == "MeshList") {
  256.        cout << " <MeshList>" << endl;
  257.        if(list.size() < 2) return error("<MeshList>: Expecting at least two arguments.");
  258.        ProcessMeshList(stoi(list[1].c_str()));
  259.       }
  260.     else if(list[0] == "SkeltonList") {
  261.        cout << " <SkeltonList>" << endl;
  262.        if(list.size() < 2) return error("<SkeletonList>: Expecting at least two arguments.");
  263.        ProcessSkeletonList(stoi(list[1].c_str()));
  264.       }
  265.     else if(list[0] == "TextureList") {
  266.        cout << " <TextureList>" << endl;
  267.        if(list.size() < 2) return error("<TextureList>: Expecting at least two arguments.");
  268.        ProcessTextureList(stoi(list[1].c_str()));
  269.       }
  270.     else curr_line++;
  271.  }
  272.  while(curr_line < line_list.size());
  273.  
  274.  // create lscript file
  275.  ofstream ofile(savename);
  276.  ofile << "main" << endl;
  277.  ofile << "{" << endl;
  278.  ofile << " editbegin();" << endl;
  279.  
  280.  // for each mesh
  281.  for(size_t i = 0; i < mesh_list.size(); i++)
  282.     {
  283.      // store texture
  284.      ofile << " editbegin();" << endl;
  285.      ofile << " uvmap = VMap(\"texture\", " << mesh_list[i].name << ", 2);" << endl;
  286.      ofile << " editend();" << endl;
  287.  
  288.      // set layer and surface
  289.      ofile << " lyrsetfg(" << (i + 1) << ");" << endl;
  290.      ofile << " setsurface(" << mesh_list[i].name  << ");" << endl;
  291.  
  292.      // save triangles
  293.      ofile << " editbegin();" << endl;
  294.      size_t point_index = 1;
  295.      for(size_t j = 0; j < mesh_list[i].polygon_list.size(); j++)
  296.         {
  297.          // point indeces
  298.          size_t a_index = point_index++;
  299.          size_t b_index = point_index++;
  300.          size_t c_index = point_index++;
  301.  
  302.          // get vertex index
  303.          unsigned short a_vertex_index = mesh_list[i].polygon_list[j].face_index[0];
  304.          unsigned short b_vertex_index = mesh_list[i].polygon_list[j].face_index[1];
  305.          unsigned short c_vertex_index = mesh_list[i].polygon_list[j].face_index[2];
  306.  
  307.          // get vertex value
  308.          vector3D<float> a_vertex = mesh_list[i].vertex_list[a_vertex_index];
  309.          vector3D<float> b_vertex = mesh_list[i].vertex_list[b_vertex_index];
  310.          vector3D<float> c_vertex = mesh_list[i].vertex_list[c_vertex_index];
  311.  
  312.          // get uv index
  313.          unsigned short a_uv_index = mesh_list[i].polygon_list[j].uv_index[0];
  314.          unsigned short b_uv_index = mesh_list[i].polygon_list[j].uv_index[1];
  315.          unsigned short c_uv_index = mesh_list[i].polygon_list[j].uv_index[2];
  316.  
  317.          // get uv value
  318.          vector2D<float> a_uv_value = mesh_list[i].uv_list[a_uv_index];
  319.          vector2D<float> b_uv_value = mesh_list[i].uv_list[b_uv_index];
  320.          vector2D<float> c_uv_value = mesh_list[i].uv_list[c_uv_index];
  321.  
  322.          // save points
  323.          ofile << " pointlist[" << a_index << "]" << " = " << "addpoint(" << a_vertex[0] << "," << a_vertex[1] << "," << a_vertex[2] << ");" << endl;
  324.          ofile << " pointlist[" << b_index << "]" << " = " << "addpoint(" << b_vertex[0] << "," << b_vertex[1] << "," << b_vertex[2] << ");" << endl;
  325.          ofile << " pointlist[" << c_index << "]" << " = " << "addpoint(" << c_vertex[0] << "," << c_vertex[1] << "," << c_vertex[2] << ");" << endl;
  326.  
  327.          // save uv map
  328.          ofile << " uvmap.setValue(pointlist[" << a_index << "]," << "@" << a_uv_value[0] << "," << -a_uv_value[1] << "@);" << endl;
  329.          ofile << " uvmap.setValue(pointlist[" << b_index << "]," << "@" << b_uv_value[0] << "," << -b_uv_value[1] << "@);" << endl;
  330.          ofile << " uvmap.setValue(pointlist[" << c_index << "]," << "@" << c_uv_value[0] << "," << -c_uv_value[1] << "@);" << endl;
  331.  
  332.          // save triangle
  333.          ofile << " addtriangle(pointlist[" << a_index << "], pointlist[" << b_index << "], pointlist[" << c_index << "]);" << endl;
  334.         }
  335.      ofile << " editend();" << endl;
  336.     }
  337.  
  338.  // finish lscript file
  339.  ofile << " editend();" << endl;
  340.  ofile << "}" << endl;
  341.  
  342.  // extract filename parameters
  343.  char param1[MAX_PATH];
  344.  char param2[MAX_PATH];
  345.  char param3[MAX_PATH];
  346.  char param4[MAX_PATH];
  347.  _splitpath(filename, param1, param2, param3, param4);
  348.  
  349.  // create obj file
  350.  ofstream objfile(wavename);
  351.  objfile << "o " << param3 << ".obj" << endl;
  352.  objfile << "mtllib " << param3 << ".mtl" << endl;
  353.  
  354.  // for each mesh
  355.  size_t v_offset = 0;
  356.  size_t t_offset = 0;
  357.  for(size_t i = 0; i < mesh_list.size(); i++)
  358.     {
  359.      objfile << "g " << strip(mesh_list[i].name, '\"').c_str() << endl;
  360.      objfile << "usemtl " << strip(mesh_list[i].name, '\"').c_str() << endl;
  361.  
  362.      // vertices
  363.      for(size_t j = 0; j < mesh_list[i].vertex_list.size(); j++) {
  364.          float x = mesh_list[i].vertex_list[j][0];
  365.          float y = mesh_list[i].vertex_list[j][1];
  366.          float z = mesh_list[i].vertex_list[j][2];
  367.          objfile << "v " << x << " " << y << " " << z << endl;
  368.         }
  369.  
  370.      // texture coordinates
  371.      for(size_t j = 0; j < mesh_list[i].uv_list.size(); j++) {
  372.          float u = mesh_list[i].uv_list[j][0];
  373.          float v = mesh_list[i].uv_list[j][1];
  374.          objfile << "vt " << u << " " << -v << endl;
  375.         }
  376.  
  377.      // normals
  378.      for(size_t j = 0; j < mesh_list[i].normal_list.size(); j++) {
  379.          float x = mesh_list[i].normal_list[j][0];
  380.          float y = mesh_list[i].normal_list[j][1];
  381.          float z = mesh_list[i].normal_list[j][2];
  382.          objfile << "vn " << x << " " << y << " " << z << endl;
  383.         }
  384.  
  385.      // triangles
  386.      for(size_t j = 0; j < mesh_list[i].polygon_list.size(); j++)
  387.         {
  388.          unsigned short v1 = v_offset + mesh_list[i].polygon_list[j].face_index[0] + 1;
  389.          unsigned short v2 = v_offset + mesh_list[i].polygon_list[j].face_index[1] + 1;
  390.          unsigned short v3 = v_offset + mesh_list[i].polygon_list[j].face_index[2] + 1;
  391.  
  392.          unsigned short t1 = t_offset + mesh_list[i].polygon_list[j].uv_index[0] + 1;
  393.          unsigned short t2 = t_offset + mesh_list[i].polygon_list[j].uv_index[1] + 1;
  394.          unsigned short t3 = t_offset + mesh_list[i].polygon_list[j].uv_index[2] + 1;
  395.  
  396.          objfile << "f " << 
  397.           v1 << "/" << t1 << " " <<
  398.           v2 << "/" << t2 << " " <<
  399.           v3 << "/" << t3 << endl;
  400.         }
  401.  
  402.      v_offset += mesh_list[i].vertex_list.size();
  403.      t_offset += mesh_list[i].uv_list.size();
  404.      objfile << endl;
  405.     }
  406.  
  407.  // create material file
  408.  ofstream mtlfile(wmtlname);
  409.  
  410.  for(size_t i = 0; i < mesh_list.size(); i++)
  411.     {
  412.      unsigned int material_index = mesh_list[i].material_index_list[0];
  413.      unsigned int texture_index = 0;
  414.      if(material_list[material_index].diffuse_texture_index.size()) texture_index = material_list[material_index].diffuse_texture_index[0];
  415.  
  416.      mtlfile << "newmtl " << strip(mesh_list[i].name, '\"').c_str() << endl;
  417.      mtlfile << "Ka " << 0 << " " << 0 << " " << 0 << endl;
  418.      mtlfile << "Kd " << 0.784314 << " " << 0.784314 << " " << 0.784314 << endl;
  419.      mtlfile << "Ks " << 0 << " " << 0 << " " << 0 << endl;
  420.      mtlfile << "Ni " << 1 << endl;
  421.      mtlfile << "Ns " << 400 << endl;
  422.      mtlfile << "Tf " << 1 << " " << 1 << " " << 1 << endl;
  423.      mtlfile << "d " << 1 << endl;
  424.      mtlfile << "map_Kd " << strip(texture_list[texture_index].filename, '\"').c_str() << endl;
  425.      mtlfile << endl;
  426.     }
  427.  
  428.  return true;
  429. }
  430.  
  431. bool Exporter::ProcessMaterialList(size_t n_materials)
  432. {
  433.  // parse line
  434.  deque<string> parse_list;
  435.  
  436.  // line should be '{'
  437.  curr_line++;
  438.  parse_list.clear();
  439.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<MaterialList>: Empty token list.");
  440.  if(parse_list[0] != "{") return error("<MaterialList>: Expecting '{' token.");
  441.  
  442.  // process textures
  443.  for(size_t i = 0; i < n_materials; i++)
  444.      if(!ProcessMaterial()) return false;
  445.  
  446.  // line should be ''
  447.  curr_line++;
  448.  parse_list.clear();
  449.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<MaterialList>: Empty token list.");
  450.  if(parse_list[0] != "}") return error("<MaterialList>: Expecting '}' token.");
  451.  
  452.  // success
  453.  return true;
  454. }
  455.  
  456. bool Exporter::ProcessMaterial(void)
  457. {
  458.  // variables
  459.  deque<string> parse_list;
  460.  Material material;
  461.  
  462.  // line should be 'Material "name"'
  463.  curr_line++;
  464.  parse_list.clear();
  465.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Material>: Empty token list.");
  466.  if(parse_list.size() < 2) return error("<Material>: Expecting <Material> <name>.");
  467.  material.name = parse_list[1];
  468.  
  469.  // line should be '{'
  470.  curr_line++;
  471.  parse_list.clear();
  472.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Material>: Empty token list.");
  473.  if(parse_list[0] != "{") return error("<Material>: Expecting '{' token.");
  474.  
  475.  // process lines
  476.  for(;;)
  477.     {
  478.      // parse line
  479.      curr_line++;
  480.      parse_list.clear();
  481.      if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Material>: Empty token list.");
  482.  
  483.      // process tokens
  484.      if(parse_list.size() == 1) {
  485.         if(parse_list[0] == "}") break;
  486.         else return error("<Material>: Unexpected token.");
  487.        }
  488.      else if(parse_list.size() == 2) {
  489.         if(parse_list[0] == "type") material.type = parse_list[1];
  490.         else if(parse_list[0] == "Opacity") {
  491.            parse_list[1] = strip(parse_list[1], '(');
  492.            parse_list[1] = strip(parse_list[1], ')');
  493.            material.opacity = stof(parse_list[1]);
  494.           }
  495.         else if(parse_list[0] == "Shininess") {
  496.            parse_list[1] = strip(parse_list[1], '(');
  497.            parse_list[1] = strip(parse_list[1], ')');
  498.            material.shininess = stof(parse_list[1]);
  499.           }
  500.         else if(parse_list[0] == "Reflectivity") {
  501.            parse_list[1] = strip(parse_list[1], '(');
  502.            parse_list[1] = strip(parse_list[1], ')');
  503.            material.reflectivity = stof(parse_list[1]);
  504.           }
  505.         else if(parse_list[0] == "DiffuseTextureIndex")
  506.           {
  507.            // number of indices
  508.            size_t n_indices = stoi(parse_list[1].c_str());
  509.  
  510.            // line should be '{'
  511.            curr_line++;
  512.            parse_list.clear();
  513.            if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<DiffuseTextureIndex>: Empty token list.");
  514.            if(parse_list[0] != "{") return error("<DiffuseTextureIndex>: Expecting '{' token.");
  515.  
  516.            // process indicies
  517.            for(size_t i = 0; i < n_indices; i++) {
  518.                curr_line++;
  519.                parse_list.clear();
  520.                if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<DiffuseTextureIndex>: Empty token list.");
  521.                material.diffuse_texture_index.push_back(stoi(parse_list[0].c_str()));
  522.               }
  523.  
  524.            // line should be '}'
  525.            curr_line++;
  526.            parse_list.clear();
  527.            if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<DiffuseTextureIndex>: Empty token list.");
  528.            if(parse_list[0] != "}") return error("<DiffuseTextureIndex>: Expecting '}' token.");
  529.           }
  530.         else return error("<Material>: Unexpected token.");
  531.        }
  532.      else if(parse_list.size() == 4) {
  533.         if(parse_list[0] == "Ambient") {
  534.            parse_list[1] = strip(parse_list[1], '(');
  535.            parse_list[3] = strip(parse_list[3], ')');
  536.            material.ambient[0] = stof(parse_list[1]);
  537.            material.ambient[1] = stof(parse_list[2]);
  538.            material.ambient[2] = stof(parse_list[3]);
  539.           }
  540.         else if(parse_list[0] == "Diffuse") {
  541.            parse_list[1] = strip(parse_list[1], '(');
  542.            parse_list[3] = strip(parse_list[3], ')');
  543.            material.diffuse[0] = stof(parse_list[1]);
  544.            material.diffuse[1] = stof(parse_list[2]);
  545.            material.diffuse[2] = stof(parse_list[3]);
  546.           }
  547.         else if(parse_list[0] == "Specular") {
  548.            parse_list[1] = strip(parse_list[1], '(');
  549.            parse_list[3] = strip(parse_list[3], ')');
  550.            material.specular[0] = stof(parse_list[1]);
  551.            material.specular[1] = stof(parse_list[2]);
  552.            material.specular[2] = stof(parse_list[3]);
  553.           }
  554.         else if(parse_list[0] == "Emissive") {
  555.            parse_list[1] = strip(parse_list[1], '(');
  556.            parse_list[3] = strip(parse_list[3], ')');
  557.            material.emissive[0] = stof(parse_list[1]);
  558.            material.emissive[1] = stof(parse_list[2]);
  559.            material.emissive[2] = stof(parse_list[3]);
  560.           }
  561.         else if(parse_list[0] == "Bump") {
  562.            parse_list[1] = strip(parse_list[1], '(');
  563.            parse_list[3] = strip(parse_list[3], ')');
  564.            material.bump[0] = stof(parse_list[1]);
  565.            material.bump[1] = stof(parse_list[2]);
  566.            material.bump[2] = stof(parse_list[3]);
  567.           }
  568.         else return error("<Material>: Unexpected token.");
  569.        }
  570.     }
  571.  
  572.  // debug
  573.  //cout << "MATERIAL" << endl;
  574.  //cout << " name = " << material.name << endl;
  575.  //cout << " type = " << material.type << endl;
  576.  //cout << " ambient = " << material.ambient[0] << "," << material.ambient[1] << "," << material.ambient[2] << endl;
  577.  //cout << " diffuse = " << material.diffuse[0] << "," << material.diffuse[1] << "," << material.diffuse[2] << endl;
  578.  //cout << " specular = " << material.specular[0] << "," << material.specular[1] << "," << material.specular[2] << endl;
  579.  //cout << " emissive = " << material.emissive[0] << "," << material.emissive[1] << "," << material.emissive[2] << endl;
  580.  //cout << " bump = " << material.bump[0] << "," << material.bump[1] << "," << material.bump[2] << endl;
  581.  //cout << " opacity = " << material.opacity << endl;
  582.  //cout << " shininess = " << material.shininess << endl;
  583.  //cout << " reflectivity = " << material.reflectivity << endl;
  584.  
  585.  // insert texture
  586.  material_list.push_back(material);
  587.  return true;
  588. }
  589.  
  590. bool Exporter::ProcessSkeletonList(size_t n_nodes)
  591. {
  592.  // parse line
  593.  deque<string> parse_list;
  594.  
  595.  // line should be '{'
  596.  curr_line++;
  597.  parse_list.clear();
  598.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<SkeletonList>: Empty token list.");
  599.  if(parse_list[0] != "{") return error("<SkeletonList>: Expecting '{' token.");
  600.  
  601.  // process textures
  602.  for(size_t i = 0; i < n_nodes; i++)
  603.      if(!ProcessSkeleton()) return false;
  604.  
  605.  // line should be ''
  606.  curr_line++;
  607.  parse_list.clear();
  608.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<SkeletonList>: Empty token list.");
  609.  if(parse_list[0] != "}") return error("<SkeletonList>: Expecting '}' token.");
  610.  
  611.  // success
  612.  return true;
  613. }
  614.  
  615. bool Exporter::ProcessSkeleton(void)
  616. {
  617.  // variables
  618.  deque<string> parse_list;
  619.  Skeleton skeleton;
  620.  
  621.  // line should be 'Texture "name"'
  622.  curr_line++;
  623.  parse_list.clear();
  624.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Skeleton>: Empty token list.");
  625.  if(parse_list.size() < 2) return error("<Skeleton>: Expecting <Skeleton> <name>.");
  626.  string skeleton_name = parse_list[1];
  627.  
  628.  // line should be '{'
  629.  curr_line++;
  630.  parse_list.clear();
  631.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Skeleton>: Empty token list.");
  632.  if(parse_list[0] != "{") return error("<Skeleton>: Expecting '{' token.");
  633.  
  634.  // process lines
  635.  for(;;)
  636.     {
  637.      // parse line
  638.      curr_line++;
  639.      parse_list.clear();
  640.      if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Skeleton>: Empty token list.");
  641.  
  642.      // process tokens
  643.      if(parse_list.size() == 1) {
  644.         if(parse_list[0] == "}") break;
  645.         else return error("<Skeleton>: Unexpected token.");
  646.        }
  647.      else if(parse_list.size() == 2) {
  648.         if(parse_list[0] == "Parent") skeleton.parent = parse_list[1];
  649.         else if(parse_list[0] == "Type") skeleton.type = parse_list[1];
  650.         else if(parse_list[0] == "RotationOrder") skeleton.order = parse_list[1];
  651.         else return error("<Skeleton>: Unexpected token.");
  652.        }
  653.      else if(parse_list.size() == 4) {
  654.         if(parse_list[0] == "Trans") {
  655.            parse_list[1] = strip(parse_list[1], '(');
  656.            parse_list[3] = strip(parse_list[3], ')');
  657.            skeleton.translation[0] = stof(parse_list[1]);
  658.            skeleton.translation[1] = stof(parse_list[2]);
  659.            skeleton.translation[2] = stof(parse_list[3]);
  660.           }
  661.         else if(parse_list[0] == "Rotate") {
  662.            parse_list[1] = strip(parse_list[1], '(');
  663.            parse_list[3] = strip(parse_list[3], ')');
  664.            skeleton.rotation[0] = stof(parse_list[1]);
  665.            skeleton.rotation[1] = stof(parse_list[2]);
  666.            skeleton.rotation[2] = stof(parse_list[3]);
  667.           }
  668.         else if(parse_list[0] == "Scale") {
  669.            parse_list[1] = strip(parse_list[1], '(');
  670.            parse_list[3] = strip(parse_list[3], ')');
  671.            skeleton.scale[0] = stof(parse_list[1]);
  672.            skeleton.scale[1] = stof(parse_list[2]);
  673.            skeleton.scale[2] = stof(parse_list[3]);
  674.           }
  675.         else return error("<Skeleton>: Unexpected token.");
  676.        }
  677.      else return error("<Skeleton>: Unexpected number of tokens.");
  678.     }
  679.  
  680.  // insert texture
  681.  typedef map<string, Skeleton>::value_type value_type;
  682.  skeleton_list.insert(value_type(skeleton_name, skeleton));
  683.  
  684.  // debug
  685.  //cout << "SKELETON" << endl;
  686.  //cout << " parent = " << skeleton.parent << endl;
  687.  //cout << " type = " << skeleton.type << endl;
  688.  //cout << " order = " << skeleton.order << endl;
  689.  //cout << " translation = " << skeleton.translation[0] << "," << skeleton.translation[1] << "," << skeleton.translation[2] << endl;
  690.  //cout << " rotation = " << skeleton.rotation[0] << "," << skeleton.rotation[1] << "," << skeleton.rotation[2] << endl;
  691.  //cout << " scale = " << skeleton.scale[0] << "," << skeleton.scale[1] << "," << skeleton.scale[2] << endl;
  692.  //cout << endl;
  693.  
  694.  return true;
  695. }
  696.  
  697. bool Exporter::ProcessMeshList(size_t n_meshes)
  698. {
  699.  // parse line
  700.  deque<string> parse_list;
  701.  
  702.  // line should be '{'
  703.  curr_line++;
  704.  parse_list.clear();
  705.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<MeshList>: Empty token list.");
  706.  if(parse_list[0] != "{") return error("<MeshList>: Expecting '{' token.");
  707.  
  708.  // process textures
  709.  for(size_t i = 0; i < n_meshes; i++)
  710.      if(!ProcessMesh()) return false;
  711.  
  712.  // line should be '}'
  713.  curr_line++;
  714.  parse_list.clear();
  715.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<MeshList>: Empty token list.");
  716.  if(parse_list[0] != "}") return error("<MeshList>: Expecting '}' token.");
  717.  
  718.  // success
  719.  return true;
  720. }
  721.  
  722. bool Exporter::ProcessMesh(void)
  723. {
  724.  // variables
  725.  deque<string> parse_list;
  726.  Mesh mesh;
  727.  
  728.  // line should be 'Mesh "name"'
  729.  curr_line++;
  730.  parse_list.clear();
  731.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Mesh>: Empty token list.");
  732.  if(parse_list.size() < 2) return error("<Mesh>: Expecting <Mesh> <name>.");
  733.  mesh.name = parse_list[1];
  734.  
  735.  // line should be '{'
  736.  curr_line++;
  737.  parse_list.clear();
  738.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Mesh>: Empty token list.");
  739.  if(parse_list[0] != "{") return error("<Mesh>: Expecting '{' token.");
  740.  
  741.  // process lines
  742.  for(;;)
  743.     {
  744.      // parse line
  745.      curr_line++;
  746.      parse_list.clear();
  747.      if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Mesh>: Empty token list.");
  748.  
  749.      // process tokens
  750.      if(parse_list.size() == 1) {
  751.         if(parse_list[0] == "}") break;
  752.         else return error("<Mesh>: Unexpected token.");
  753.        }
  754.      else if(parse_list.size() == 2) {
  755.         if(parse_list[0] == "PolygonList") {
  756.            if(!ProcessPolygonList(stoi(parse_list[1]), mesh))
  757.               return false;
  758.           }
  759.         else if(parse_list[0] == "VertexList") {
  760.            if(!ProcessVertexList(stoi(parse_list[1]), mesh))
  761.               return false;
  762.           }
  763.         else if(parse_list[0] == "WeightList") {
  764.            if(!ProcessWeightList(stoi(parse_list[1]), mesh))
  765.               return false;
  766.           }
  767.         else if(parse_list[0] == "NormalList") {
  768.            if(!ProcessNormalList(stoi(parse_list[1]), mesh))
  769.               return false;
  770.           }
  771.         else if(parse_list[0] == "UVList") {
  772.            if(!ProcessUVList(stoi(parse_list[1]), mesh))
  773.               return false;
  774.           }
  775.         else if(parse_list[0] == "MaterialIndexList") {
  776.            if(!ProcessMaterialIndexList(stoi(parse_list[1]), mesh))
  777.               return false;
  778.           }
  779.         else return error("<Mesh>: Unexpected token.");
  780.        }
  781.     }
  782.  
  783.  // debug
  784.  //cout << "Mesh" << endl;
  785.  
  786.  // insert texture
  787.  mesh_list.push_back(mesh);
  788.  return true;
  789. }
  790.  
  791. bool Exporter::ProcessPolygonList(size_t n_polygons, Mesh& mesh)
  792. {
  793.  // parse line
  794.  deque<string> parse_list;
  795.  
  796.  // line should be '{'
  797.  curr_line++;
  798.  parse_list.clear();
  799.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<PolygonList>: Empty token list.");
  800.  if(parse_list[0] != "{") return error("<PolygonList>: Expecting '{' token.");
  801.  
  802.  // process textures
  803.  for(size_t i = 0; i < n_polygons; i++)
  804.      if(!ProcessPolygon(mesh)) return false;
  805.  
  806.  // line should be '}'
  807.  curr_line++;
  808.  parse_list.clear();
  809.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<PolygonList>: Empty token list.");
  810.  if(parse_list[0] != "}") return error("<PolygonList>: Expecting '}' token.");
  811.  
  812.  // success
  813.  return true;
  814. }
  815.  
  816. bool Exporter::ProcessPolygon(Mesh& mesh)
  817. {
  818.  // variables
  819.  deque<string> parse_list;
  820.  Polygon polygon;
  821.  
  822.  // line should be <Polygon> <n>
  823.  curr_line++;
  824.  parse_list.clear();
  825.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Polygon>: Empty token list.");
  826.  if(parse_list.size() < 2) return error("<Polygon>: Expecting <Polygon> <n>.");
  827.  
  828.  // line should be '{'
  829.  curr_line++;
  830.  parse_list.clear();
  831.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Polygon>: Empty token list.");
  832.  if(parse_list[0] != "{") return error("<Polygon>: Expecting '{' token.");
  833.  
  834.  // process lines
  835.  for(;;)
  836.     {
  837.      // parse line
  838.      curr_line++;
  839.      parse_list.clear();
  840.      if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Polygon>: Empty token list.");
  841.  
  842.      // process tokens
  843.      if(parse_list[0] == "}") break;
  844.      else if(parse_list[0] == "Material")
  845.        {
  846.         size_t n_indices = stoi(parse_list[1]);
  847.  
  848.         // line should be '{'
  849.         curr_line++;
  850.         parse_list.clear();
  851.         if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Polygon>: Empty token list.");
  852.         if(parse_list[0] != "{") return error("<Polygon>: Expecting '{' token.");
  853.  
  854.         // read indices
  855.         for(size_t i = 0; i < n_indices; i++) {
  856.             curr_line++;
  857.             parse_list.clear();
  858.             if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Polygon>: Empty token list.");
  859.             polygon.material_index.push_back(stoi(parse_list[0].c_str()));
  860.            }
  861.  
  862.         // line should be '}'
  863.         curr_line++;
  864.         parse_list.clear();
  865.         if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Polygon>: Empty token list.");
  866.         if(parse_list[0] != "}") return error("<Polygon>: Expecting '}' token.");
  867.        }
  868.      else if(parse_list[0] == "Face")
  869.        {
  870.         parse_list[2] = strip(parse_list[2], '(');
  871.         parse_list[4] = strip(parse_list[4], ')');
  872.         polygon.face_index[0] = stoi(parse_list[2]);
  873.         polygon.face_index[1] = stoi(parse_list[3]);
  874.         polygon.face_index[2] = stoi(parse_list[4]);
  875.        }
  876.      else if(parse_list[0] == "UV")
  877.        {
  878.         parse_list[2] = strip(parse_list[2], '(');
  879.         parse_list[4] = strip(parse_list[4], ')');
  880.         polygon.uv_index[0] = stoi(parse_list[2]);
  881.         polygon.uv_index[1] = stoi(parse_list[3]);
  882.         polygon.uv_index[2] = stoi(parse_list[4]);
  883.        }
  884.      else if(parse_list[0] == "Color")
  885.        {
  886.         parse_list[2] = strip(parse_list[2], '(');
  887.         parse_list[4] = strip(parse_list[4], ')');
  888.         polygon.color[0] = stoul(parse_list[2]); // careful here! crashes for stoi
  889.         polygon.color[1] = stoul(parse_list[3]); // careful here! crashes for stoi
  890.         polygon.color[2] = stoul(parse_list[4]); // careful here! crashes for stoi
  891.        }
  892.      else
  893.         return error("<Polygon>: Unexpected token.");
  894.     }
  895.  
  896.  // insert texture
  897.  mesh.polygon_list.push_back(polygon);
  898.  return true;
  899. }
  900.  
  901. bool Exporter::ProcessVertexList(size_t n_points, Mesh& mesh)
  902. {
  903.  // parse line
  904.  deque<string> parse_list;
  905.  
  906.  // line should be '{'
  907.  curr_line++;
  908.  parse_list.clear();
  909.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<VertexList>: Empty token list.");
  910.  if(parse_list[0] != "{") return error("<VertexList>: Expecting '{' token.");
  911.  
  912.  // process points
  913.  for(size_t i = 0; i < n_points; i++)
  914.     {
  915.      // parse line
  916.      curr_line++;
  917.      parse_list.clear();
  918.      if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<VertexList>: Empty token list.");
  919.      if(parse_list.size() != 3) return error("<VertexList>: Invalid vertex.");
  920.  
  921.      // add vertex
  922.      vector3D<float> v;
  923.      v[0] = stof(parse_list[0]);
  924.      v[1] = stof(parse_list[1]);
  925.      v[2] = stof(parse_list[2]);
  926.      mesh.vertex_list.push_back(v);
  927.     }
  928.  
  929.  // line should be '}'
  930.  curr_line++;
  931.  parse_list.clear();
  932.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<VertexList>: Empty token list.");
  933.  if(parse_list[0] != "}") return error("<VertexList>: Expecting '}' token.");
  934.  
  935.  // success
  936.  return true;
  937. }
  938.  
  939. bool Exporter::ProcessWeightList(size_t n_weights, Mesh& mesh)
  940. {
  941.  // parse line
  942.  deque<string> parse_list;
  943.  
  944.  // line should be '{'
  945.  curr_line++;
  946.  parse_list.clear();
  947.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<WeightList>: Empty token list.");
  948.  if(parse_list[0] != "{") return error("<WeightList>: Expecting '{' token.");
  949.  
  950.  // process points
  951.  for(size_t i = 0; i < n_weights; i++)
  952.      ProcessWeight(mesh);
  953.  
  954.  // line should be '}'
  955.  curr_line++;
  956.  parse_list.clear();
  957.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<WeightList>: Empty token list.");
  958.  if(parse_list[0] != "}") return error("<WeightList>: Expecting '}' token.");
  959.  
  960.  // success
  961.  return true;
  962. }
  963.  
  964. bool Exporter::ProcessWeight(Mesh& mesh)
  965. {
  966.  // variables
  967.  deque<string> parse_list;
  968.  WeightMap wmap;
  969.  
  970.  // line should be <Weight> <n> <name>
  971.  curr_line++;
  972.  parse_list.clear();
  973.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Weight>: Empty token list.");
  974.  if(parse_list.size() != 3) return error("<Weight>: Expecting <Weight> <n> <name>.");
  975.  
  976.  wmap.size = stoi(parse_list[1]);
  977.  wmap.name = parse_list[2];
  978.  
  979.  // line should be '{'
  980.  curr_line++;
  981.  parse_list.clear();
  982.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Weight>: Empty token list.");
  983.  if(parse_list[0] != "{") return error("<Weight>: Expecting '{' token.");
  984.  
  985.  // process weights
  986.  for(size_t i = 0; i < wmap.size; i++)
  987.     {
  988.      // parse line
  989.      curr_line++;
  990.      parse_list.clear();
  991.      if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Weight>: Empty token list.");
  992.  
  993.      // insert weight
  994.      Weight w;
  995.      w.index = stoi(parse_list[0].c_str());
  996.      w.value = stof(parse_list[0].c_str());
  997.      wmap.data.push_back(w);
  998.     }
  999.  
  1000.  // line should be '}'
  1001.  curr_line++;
  1002.  parse_list.clear();
  1003.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Weight>: Empty token list.");
  1004.  if(parse_list[0] != "}") return error("<Weight>: Expecting '}' token.");
  1005.  
  1006.  // insert texture
  1007.  mesh.weight_list.push_back(wmap);
  1008.  return true;
  1009. }
  1010.  
  1011. bool Exporter::ProcessNormalList(size_t n_normals, Mesh& mesh)
  1012. {
  1013.  // parse line
  1014.  deque<string> parse_list;
  1015.  
  1016.  // line should be '{'
  1017.  curr_line++;
  1018.  parse_list.clear();
  1019.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<NormalList>: Empty token list.");
  1020.  if(parse_list[0] != "{") return error("<NormalList>: Expecting '{' token.");
  1021.  
  1022.  // process points
  1023.  for(size_t i = 0; i < n_normals; i++)
  1024.     {
  1025.      // parse line
  1026.      curr_line++;
  1027.      parse_list.clear();
  1028.      if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<NormalList>: Empty token list.");
  1029.      if(parse_list.size() != 3) return error("<NormalList>: Invalid vertex.");
  1030.  
  1031.      // add vertex
  1032.      vector3D<float> v;
  1033.      v[0] = stof(parse_list[0]);
  1034.      v[1] = stof(parse_list[1]);
  1035.      v[2] = stof(parse_list[2]);
  1036.      mesh.normal_list.push_back(v);
  1037.     }
  1038.  
  1039.  // line should be '}'
  1040.  curr_line++;
  1041.  parse_list.clear();
  1042.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<NormalList>: Empty token list.");
  1043.  if(parse_list[0] != "}") return error("<NormalList>: Expecting '}' token.");
  1044.  
  1045.  // success
  1046.  return true;
  1047. }
  1048.  
  1049. bool Exporter::ProcessUVList(size_t n_points, Mesh& mesh)
  1050. {
  1051.  // parse line
  1052.  deque<string> parse_list;
  1053.  
  1054.  // line should be '{'
  1055.  curr_line++;
  1056.  parse_list.clear();
  1057.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<UVList>: Empty token list.");
  1058.  if(parse_list[0] != "{") return error("<UVList>: Expecting '{' token.");
  1059.  
  1060.  // process points
  1061.  for(size_t i = 0; i < n_points; i++)
  1062.     {
  1063.      // parse line
  1064.      curr_line++;
  1065.      parse_list.clear();
  1066.      if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<UVList>: Empty token list.");
  1067.      if(parse_list.size() != 2) return error("<UVList>: Invalid vertex.");
  1068.  
  1069.      // add vertex
  1070.      vector2D<float> v;
  1071.      v[0] = stof(parse_list[0]);
  1072.      v[1] = stof(parse_list[1]);
  1073.      mesh.uv_list.push_back(v);
  1074.     }
  1075.  
  1076.  // line should be '}'
  1077.  curr_line++;
  1078.  parse_list.clear();
  1079.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<UVList>: Empty token list.");
  1080.  if(parse_list[0] != "}") return error("<UVList>: Expecting '}' token.");
  1081.  
  1082.  // success
  1083.  return true;
  1084. }
  1085.  
  1086. bool Exporter::ProcessMaterialIndexList(size_t n_items, Mesh& mesh)
  1087. {
  1088.  // parse line
  1089.  deque<string> parse_list;
  1090.  
  1091.  // line should be '{'
  1092.  curr_line++;
  1093.  parse_list.clear();
  1094.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<MaterialIndexList>: Empty token list.");
  1095.  if(parse_list[0] != "{") return error("<MaterialIndexList>: Expecting '{' token.");
  1096.  
  1097.  // process material indices
  1098.  for(size_t i = 0; i < n_items; i++)
  1099.     {
  1100.      // parse line
  1101.      curr_line++;
  1102.      parse_list.clear();
  1103.      if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<MaterialIndexList>: Empty token list.");
  1104.      if(parse_list.size() != 1) return error("<MaterialIndexList>: Invalid index.");
  1105.  
  1106.      // add material index
  1107.      mesh.material_index_list.push_back(stoi(parse_list[0].c_str()));
  1108.     }
  1109.  
  1110.  // line should be '}'
  1111.  curr_line++;
  1112.  parse_list.clear();
  1113.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<MaterialIndexList>: Empty token list.");
  1114.  if(parse_list[0] != "}") return error("<MaterialIndexList>: Expecting '}' token.");
  1115.  
  1116.  // success
  1117.  return true;
  1118. }
  1119.  
  1120. bool Exporter::ProcessTextureList(size_t n_textures)
  1121. {
  1122.  // parse line
  1123.  deque<string> parse_list;
  1124.  
  1125.  // line should be '{'
  1126.  curr_line++;
  1127.  parse_list.clear();
  1128.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<TextureList>: Empty token list.");
  1129.  if(parse_list[0] != "{") return error("<TextureList>: Expecting '{' token.");
  1130.  
  1131.  // process textures
  1132.  for(size_t i = 0; i < n_textures; i++)
  1133.      if(!ProcessTexture()) return false;
  1134.  
  1135.  // line should be '}'
  1136.  curr_line++;
  1137.  parse_list.clear();
  1138.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<TextureList>: Empty token list.");
  1139.  if(parse_list[0] != "}") return error("<TextureList>: Expecting '}' token.");
  1140.  
  1141.  // success
  1142.  return true;
  1143. }
  1144.  
  1145. bool Exporter::ProcessTexture(void)
  1146. {
  1147.  // variables
  1148.  deque<string> parse_list;
  1149.  Texture texture;
  1150.  
  1151.  // line should be 'Texture "name"'
  1152.  curr_line++;
  1153.  parse_list.clear();
  1154.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Texture>: Empty token list.");
  1155.  if(parse_list.size() < 2) return error("<Texture>: Expecting <Texture> <name>.");
  1156.  texture.name = parse_list[1];
  1157.  
  1158.  // line should be '{'
  1159.  curr_line++;
  1160.  parse_list.clear();
  1161.  if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Texture>: Empty token list.");
  1162.  if(parse_list[0] != "{") return error("<Texture>: Expecting '{' token.");
  1163.  
  1164.  // process lines
  1165.  for(;;)
  1166.     {
  1167.      // parse line
  1168.      curr_line++;
  1169.      parse_list.clear();
  1170.      if(parse(line_list[curr_line].c_str(), parse_list) == false) return error("<Texture>: Empty token list.");
  1171.  
  1172.      // process tokens
  1173.      if(parse_list.size() == 1) {
  1174.         if(parse_list[0] == "}") break;
  1175.         else return error("<Texture>: Unexpected token.");
  1176.        }
  1177.      else if(parse_list.size() == 2) {
  1178.         if(parse_list[0] == "type") texture.type = parse_list[1];
  1179.         else if(parse_list[0] == "file") texture.filename = parse_list[1];
  1180.         else return error("<Texture>: Unexpected token.");
  1181.        }
  1182.     }
  1183.  
  1184.  // insert texture
  1185.  texture_list.push_back(texture);
  1186.  return true;
  1187. }
  1188.  
  1189. bool extract_TGP(const char* filename)
  1190. {
  1191.  ifstream ifile(filename, ios::binary);
  1192.  if(!ifile) return error("Cannot open file.");
  1193.  
  1194.  unsigned int h01 = LE_read_uint32(ifile); // magic
  1195.  unsigned int h02 = LE_read_uint32(ifile); // 1
  1196.  unsigned int h03 = LE_read_uint32(ifile); // 0
  1197.  unsigned int h04 = LE_read_uint32(ifile); // offset to data
  1198.  
  1199.  // read filelist
  1200.  struct filedata {
  1201.   string name;
  1202.   unsigned int offset;
  1203.   unsigned int length;
  1204.  };
  1205.  deque<filedata> filelist;
  1206.  for(size_t i = 0; i < h04; i++)
  1207.     {
  1208.      // read filename
  1209.      char buffer[1024];
  1210.      ifile.read(&buffer[0], 0x60);
  1211.  
  1212.      // read offsets
  1213.      unsigned int o1, waste01;
  1214.      unsigned int o2, waste02;
  1215.      ifile.read((char*)&o1, sizeof(o1));
  1216.      ifile.read((char*)&waste01, sizeof(waste01));
  1217.      ifile.read((char*)&o2, sizeof(o2));
  1218.      ifile.read((char*)&waste02, sizeof(waste02));
  1219.  
  1220.      // add item
  1221.      filedata fd = { buffer, o1, o2 };
  1222.      filelist.push_back(fd);
  1223.     }
  1224.  
  1225.  // get full path filename
  1226.  char full_filename[1024];
  1227.  GetFullPathNameA(filename, 1024, full_filename, NULL);
  1228.  cout << full_filename << endl;
  1229.  
  1230.  // get full path
  1231.  char drive[1024];
  1232.  char dir[1024];
  1233.  _splitpath(full_filename, drive, dir, NULL, NULL);
  1234.  string full_pathname = drive;
  1235.  full_pathname += dir;
  1236.  cout << full_pathname.c_str() << endl;
  1237.  
  1238.  for(size_t i = 0; i < filelist.size(); i++)
  1239.     {
  1240.      // get full path filename
  1241.      string fname = full_pathname;
  1242.      fname += filelist[i].name;
  1243.  
  1244.      // get full path
  1245.      char drive[1024];
  1246.      char dir[1024];
  1247.      _splitpath(fname.c_str(), drive, dir, NULL, NULL);
  1248.      string fpath = drive;
  1249.      fpath += dir;
  1250.  
  1251.      // create path if not already created
  1252.      SHCreateDirectoryEx(NULL, fpath.c_str(), NULL);
  1253.  
  1254.      // create file
  1255.      ofstream ofile(fname, ios::binary);
  1256.      if(!ofile) return error("Could not create file.");
  1257.      cout << "Processing " << filelist[i].name.c_str() << "..." << endl;
  1258.  
  1259.      // move to offset and read data
  1260.      ifile.seekg(filelist[i].offset);
  1261.      char* data = new char[filelist[i].length];
  1262.      ifile.read(data, filelist[i].length);
  1263.  
  1264.      // save data
  1265.      ofile.write(data, filelist[i].length);
  1266.  
  1267.      // delete data
  1268.      delete[] data;
  1269.      data = 0;
  1270.     }
  1271.  
  1272.  return true;
  1273. }
  1274.  
  1275. bool parse(const char* data, deque<string>& list)
  1276. {
  1277.  // must have data
  1278.  size_t size = strlen(data);
  1279.  if(size == 0) return false;
  1280.  
  1281.  // count spaces
  1282.  size_t spaces = 0;
  1283.  for(size_t i = 0; i < size; i++) if(data[i] == ' ') spaces++;
  1284.  if(spaces == size) return false;
  1285.  
  1286.  // parse
  1287.  size_t i = 0;
  1288.  while(i < size)
  1289.       {
  1290.        // find first non-whitespace character
  1291.        while(data[i] == ' ') i++;
  1292.        if(i == size) return true;
  1293.        
  1294.        // find next whitespace character
  1295.        size_t j = i + 1;
  1296.        while(data[j] != '\0' && data[j] != ' ') j++;
  1297.        
  1298.        // add string
  1299.        string temp(data);
  1300.        list.push_back(temp.substr(i, j - i));
  1301.  
  1302.        // increment
  1303.        i = j + 1;
  1304.       }
  1305.  
  1306.  return true;
  1307. }
  1308.  
  1309. string strip(const string& data, char c)
  1310. {
  1311.  string retval = "";
  1312.  for(size_t i = 0; i < data.length(); i++) {
  1313.      if(data[i] == c) continue;
  1314.      else retval += data[i];
  1315.     }
  1316.  return retval;
  1317. }
  1318.  
  1319. string strip_trailing_spaces(const string& data)
  1320. {
  1321.  string retval = "";
  1322.  for(size_t i = 0; i < data.length(); i++) {
  1323.      size_t j = (data.length() - 1) - i;
  1324.      if(data[j] == 0x09 || data[j] == 0x0A || data[j] == 0x0D) continue;
  1325.      else retval.push_back(data[j]);
  1326.     }
  1327.  std::reverse(retval.begin(), retval.end());
  1328.  return retval;
  1329. }