home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 4819 / rage.7z / main.cpp next >
Encoding:
C/C++ Source or Header  |  2011-10-23  |  29.9 KB  |  856 lines

  1. #include "stdafx.h"
  2.  
  3. struct quaternion {
  4.  float a, b, c, d;
  5. };
  6.  
  7. struct bone {
  8.  unsigned short index;
  9.  unsigned short parent_index;
  10.  char name[128];
  11.  float relative_x;
  12.  float relative_y;
  13.  float relative_z;
  14.  float absolute_x;
  15.  float absolute_y;
  16.  float absolute_z;
  17.  quaternion q_relative;
  18.  quaternion q_absolute;
  19.  std::set<unsigned short> children;
  20. };
  21.  
  22. bool extract_bmd6model(const char* filename, const char* savename, const char* bonename);
  23. bool extract_bmodel(const char* filename, const char* savename);
  24. bool extract_all_models_1(void);
  25. bool extract_all_models_2(void);
  26. void traverse_hierarchy(unsigned short node, std::deque<bone>& tree);
  27.  
  28. int main()
  29. {
  30.  extract_all_models_1();
  31.  extract_all_models_2();
  32.  return -1;
  33. }
  34.  
  35. bool extract_all_models_1(void)
  36. {
  37.  // get all ism2 files
  38.  deque<string> namelist;
  39.  if(!get_filename_list(namelist, "bmodel")) return false;
  40.  
  41.  // create a list of save filenames
  42.  deque<string> savelist;
  43.  deque<string> bonelist;
  44.  deque<string> dbuglist;
  45.  for(size_t i = 0; i < namelist.size(); i++)
  46.     {
  47.      // extract filename parameters
  48.      char param1[MAX_PATH];
  49.      char param2[MAX_PATH];
  50.      char param3[MAX_PATH];
  51.      char param4[MAX_PATH];
  52.      _splitpath(namelist[i].c_str(), param1, param2, param3, param4);
  53.  
  54.      // change extension
  55.      string savename(param1);
  56.      savename += param2;
  57.      savename += param3;
  58.      savename += ".ls";
  59.      savelist.push_back(savename);
  60.     }
  61.  
  62.  // extract
  63.  for(size_t i = 0; i < namelist.size(); i++)
  64.      extract_bmodel(namelist[i].c_str(), savelist[i].c_str());
  65.  
  66.  return true;
  67. }
  68.  
  69. bool extract_all_models_2(void)
  70. {
  71.  // get all ism2 files
  72.  deque<string> namelist;
  73.  if(!get_filename_list(namelist, "bmd6model")) return false;
  74.  
  75.  // create a list of save filenames
  76.  deque<string> savelist;
  77.  deque<string> bonelist;
  78.  deque<string> dbuglist;
  79.  for(size_t i = 0; i < namelist.size(); i++)
  80.     {
  81.      // extract filename parameters
  82.      char param1[MAX_PATH];
  83.      char param2[MAX_PATH];
  84.      char param3[MAX_PATH];
  85.      char param4[MAX_PATH];
  86.      _splitpath(namelist[i].c_str(), param1, param2, param3, param4);
  87.  
  88.      // change extension
  89.      string savename(param1);
  90.      savename += param2;
  91.      savename += param3;
  92.      savename += ".ls";
  93.      savelist.push_back(savename);
  94.  
  95.      // change extension
  96.      string bonename(param1);
  97.      bonename += param2;
  98.      bonename += param3;
  99.      bonename += "_bones.ls";
  100.      bonelist.push_back(bonename);
  101.  
  102.      // change extension
  103.      string dbugname(param1);
  104.      dbugname += param2;
  105.      dbugname += param3;
  106.      dbugname += ".txt";
  107.      dbuglist.push_back(dbugname);
  108.     }
  109.  
  110.  // extract
  111.  for(size_t i = 0; i < namelist.size(); i++)
  112.      extract_bmd6model(namelist[i].c_str(), savelist[i].c_str(), bonelist[i].c_str());
  113.  
  114.  return true;
  115. }
  116.  
  117. bool extract_bmodel(const char* filename, const char* savename)
  118. {
  119.  // open file
  120.  std::cout << "Processing file: " << filename << std::endl;
  121.  ifstream ifile(filename, ios::binary);
  122.  if(!ifile) return error("Could not open file.");
  123.  
  124.  // magic number
  125.  if(BE_read_uint32(ifile) != 0x184C4D42) return error("Invalid magic number.");
  126.  BE_read_uint32(ifile); // 0 or some number
  127.  unsigned int n_surfaces = BE_read_uint32(ifile); // 1, 2, 3
  128.  
  129.  // create output file
  130.  ofstream ofile(savename);
  131.  ofile << "main" << endl;
  132.  ofile << "{" << endl;
  133.  
  134.  // loop through surfaces
  135.  size_t namelen = LE_read_uint32(ifile);
  136.  size_t surface = 0;
  137.  do {
  138.     // read texture filename
  139.     char name[1024];
  140.     memset(name, 0, 1024);
  141.     ifile.read(name, namelen);
  142.  
  143.     // store texture
  144.     ofile << " editbegin();" << endl;
  145.     ofile << " uvmap = VMap(\"texture\", \"" << name << "\", 2);" << endl;
  146.     ofile << " editend();" << endl;
  147.  
  148.     // set layer and surface
  149.     ofile << " lyrsetfg(" << (surface + 1) << ");" << endl;
  150.     ofile << " setsurface(\"" << name  << "\");" << endl;
  151.  
  152.     // read 4-bytes (0xFFFFFFFF, 0, or 1)
  153.     BE_read_uint32(ifile);
  154.  
  155.     // read point information
  156.     size_t n_points = BE_read_uint32(ifile);
  157.     size_t n_values = BE_read_uint32(ifile);
  158.     size_t filetype = BE_read_uint32(ifile);
  159.     cout << " points = " << n_points << endl;
  160.     cout << " values = " << n_values << endl;
  161.     cout << " filetype = " << filetype << endl;
  162.  
  163.     if(filetype == 0x1F)
  164.       {
  165.        // read 40 bytes
  166.        BE_read_float(ifile);
  167.        BE_read_float(ifile);
  168.        BE_read_float(ifile);
  169.        BE_read_float(ifile);
  170.        BE_read_float(ifile);
  171.        BE_read_float(ifile);
  172.        BE_read_float(ifile);
  173.        BE_read_float(ifile);
  174.        BE_read_float(ifile);
  175.        BE_read_float(ifile);
  176.    
  177.        // read points
  178.        ofile << " editbegin();" << endl;
  179.        for(size_t i = 0; i < n_points; i++) {
  180.            float x = BE_read_float(ifile);
  181.            float y = BE_read_float(ifile);
  182.            float z = BE_read_float(ifile);
  183.            float u = BE_read_float(ifile);
  184.            float v = BE_read_float(ifile);
  185.            BE_read_uint32(ifile);
  186.            BE_read_uint32(ifile);
  187.            BE_read_uint32(ifile);
  188.            ofile << " pointlist[" << i + 1 << "]" << " = " << "addpoint(" << x << "," << y << "," << z << ");" << endl;
  189.            ofile << " uvmap.setValue(pointlist[" << (i + 1) << "]," << "@" << u << "," << v << "@);" << endl;
  190.           }
  191.        ofile << " editend();" << endl;
  192.  
  193.        // read triangles
  194.        if(n_values % 3) return error("Indicies must be divisible by 3 for type 0x1F.");
  195.    
  196.        // read triangles
  197.        ofile << " editbegin();" << endl;
  198.        boost::shared_array<unsigned short> data(new unsigned short[n_values]);
  199.        ifile.read((char*)&data.get()[0], n_values*sizeof(unsigned short));
  200.        for(size_t i = 0; i < n_values; i++) reverse_byte_order(&data.get()[i]);
  201.        ofile << " editbegin();" << endl;    
  202.        size_t index = 0;
  203.        for(size_t i = 0; i < n_values/3; i++) {
  204.            unsigned short a = data.get()[index++] + 1;
  205.            unsigned short b = data.get()[index++] + 1;
  206.            unsigned short c = data.get()[index++] + 1;
  207.            ofile << " addtriangle(pointlist[" << a << "], pointlist[" << c << "], pointlist[" << b << "]);" << endl;
  208.           }
  209.        ofile << " editend();" << endl;
  210.       }
  211.     else if(filetype == 0x63)
  212.       {
  213.        // read 40 bytes
  214.        BE_read_float(ifile);
  215.        BE_read_float(ifile);
  216.        BE_read_float(ifile);
  217.        BE_read_float(ifile);
  218.        BE_read_float(ifile);
  219.        BE_read_float(ifile);
  220.        BE_read_float(ifile);
  221.        BE_read_float(ifile);
  222.        BE_read_float(ifile);
  223.        BE_read_float(ifile);
  224.  
  225.        // read points
  226.        struct point { short x, y, z, w; unsigned short u, v; };
  227.        boost::shared_array<point> points(new point[n_points]);
  228.        ifile.read((char*)&points.get()[0], n_points*sizeof(point));
  229.  
  230.        ofile << " editbegin();" << endl;
  231.        for(size_t i = 0; i < n_points; i++) {
  232.            reverse_byte_order(&points[i].x);
  233.            reverse_byte_order(&points[i].y);
  234.            reverse_byte_order(&points[i].z);
  235.            reverse_byte_order(&points[i].w);
  236.            reverse_byte_order(&points[i].u);
  237.            reverse_byte_order(&points[i].v);
  238.            float x = points[i].x/32767.0f;
  239.            float y = points[i].y/32767.0f;
  240.            float z = points[i].z/32767.0f;
  241.            float u = points[i].u/65535.0f;
  242.            float v = points[i].v/65535.0f;
  243.            ofile << " pointlist[" << i + 1 << "]" << " = " << "addpoint(" << x << "," << y << "," << z << ");" << endl;
  244.            ofile << " uvmap.setValue(pointlist[" << (i + 1) << "]," << "@" << u << "," << v << "@);" << endl;
  245.           }
  246.        ofile << " editend();" << endl;
  247.  
  248.        // read triangles
  249.        if(n_values % 3) return error("Indicies must be divisible by 3 for type 0x1F.");
  250.    
  251.        // read triangles
  252.        ofile << " editbegin();" << endl;
  253.        boost::shared_array<unsigned short> data(new unsigned short[n_values]);
  254.        ifile.read((char*)&data.get()[0], n_values*sizeof(unsigned short));
  255.        for(size_t i = 0; i < n_values; i++) reverse_byte_order(&data.get()[i]);
  256.        ofile << " editbegin();" << endl;    
  257.        size_t index = 0;
  258.        for(size_t i = 0; i < n_values/3; i++) {
  259.            unsigned short a = data.get()[index++] + 1;
  260.            unsigned short b = data.get()[index++] + 1;
  261.            unsigned short c = data.get()[index++] + 1;
  262.            ofile << " addtriangle(pointlist[" << a << "], pointlist[" << c << "], pointlist[" << b << "]);" << endl;
  263.           }
  264.        ofile << " editend();" << endl;
  265.       }
  266.     else if(filetype == 0x077)
  267.       {
  268.        // read 40 bytes
  269.        BE_read_float(ifile);
  270.        BE_read_float(ifile);
  271.        BE_read_float(ifile);
  272.        BE_read_float(ifile);
  273.        BE_read_float(ifile);
  274.        BE_read_float(ifile);
  275.        BE_read_float(ifile);
  276.        BE_read_float(ifile);
  277.        BE_read_float(ifile);
  278.        BE_read_float(ifile);
  279.  
  280.        // read points (20 bytes per point)
  281.        struct point { short x, y, z; unsigned short a, b, c, d, e, f, g; };
  282.        boost::shared_array<point> points(new point[n_points]);
  283.        ifile.read((char*)&points.get()[0], n_points*sizeof(point));
  284.  
  285.        ofile << " editbegin();" << endl;
  286.        for(size_t i = 0; i < n_points; i++) {
  287.            reverse_byte_order(&points[i].x);
  288.            reverse_byte_order(&points[i].y);
  289.            reverse_byte_order(&points[i].z);
  290.            reverse_byte_order(&points[i].a);
  291.            reverse_byte_order(&points[i].b);
  292.            reverse_byte_order(&points[i].c);
  293.            reverse_byte_order(&points[i].d);
  294.            reverse_byte_order(&points[i].e);
  295.            reverse_byte_order(&points[i].f);
  296.            reverse_byte_order(&points[i].g);
  297.            float x = points[i].x/32767.0f;
  298.            float y = points[i].y/32767.0f;
  299.            float z = points[i].z/32767.0f;
  300.            float a = points[i].a/65535.0f;
  301.            float b = points[i].b/65535.0f;
  302.            float c = points[i].c/65535.0f;
  303.            float d = points[i].d/65535.0f;
  304.            float e = points[i].e/65535.0f;
  305.            float f = points[i].f/65535.0f;
  306.            float g = points[i].g/65535.0f;
  307.            ofile << " pointlist[" << i + 1 << "]" << " = " << "addpoint(" << x << "," << y << "," << z << ");" << endl;
  308.            ofile << " uvmap.setValue(pointlist[" << (i + 1) << "]," << "@" << b << "," << c << "@);" << endl;
  309.           }
  310.        ofile << " editend();" << endl;
  311.  
  312.        // read triangles
  313.        if(n_values % 3) return error("Indicies must be divisible by 3 for type 0x1F.");
  314.    
  315.        // read triangles
  316.        ofile << " editbegin();" << endl;
  317.        boost::shared_array<unsigned short> data(new unsigned short[n_values]);
  318.        ifile.read((char*)&data.get()[0], n_values*sizeof(unsigned short));
  319.        for(size_t i = 0; i < n_values; i++) reverse_byte_order(&data.get()[i]);
  320.        ofile << " editbegin();" << endl;    
  321.        size_t index = 0;
  322.        for(size_t i = 0; i < n_values/3; i++) {
  323.            unsigned short a = data.get()[index++] + 1;
  324.            unsigned short b = data.get()[index++] + 1;
  325.            unsigned short c = data.get()[index++] + 1;
  326.            ofile << " addtriangle(pointlist[" << a << "], pointlist[" << c << "], pointlist[" << b << "]);" << endl;
  327.           }
  328.        ofile << " editend();" << endl;
  329.       }
  330.     else if(filetype == 0x21F)
  331.       {
  332.        // read 40 bytes
  333.        BE_read_float(ifile);
  334.        BE_read_float(ifile);
  335.        BE_read_float(ifile);
  336.        BE_read_float(ifile);
  337.        BE_read_float(ifile);
  338.        BE_read_float(ifile);
  339.        BE_read_float(ifile);
  340.        BE_read_float(ifile);
  341.        BE_read_float(ifile);
  342.        BE_read_float(ifile);
  343.    
  344.        // read points
  345.        ofile << " editbegin();" << endl;
  346.        for(size_t i = 0; i < n_points; i++) {
  347.            float x = BE_read_float(ifile);
  348.            float y = BE_read_float(ifile);
  349.            float z = BE_read_float(ifile);
  350.            float u = BE_read_float(ifile);
  351.            float v = BE_read_float(ifile);
  352.            BE_read_uint32(ifile);
  353.            BE_read_uint32(ifile);
  354.            BE_read_uint32(ifile);
  355.            ofile << " pointlist[" << i + 1 << "]" << " = " << "addpoint(" << x << "," << y << "," << z << ");" << endl;
  356.            ofile << " uvmap.setValue(pointlist[" << (i + 1) << "]," << "@" << u << "," << v << "@);" << endl;
  357.           }
  358.        ofile << " editend();" << endl;
  359.  
  360.        // read triangles
  361.        ofile << " editbegin();" << endl;
  362.        deque<unsigned short> data;
  363.        for(size_t i = 0; i < n_values; i++)
  364.           {
  365.            unsigned short temp = BE_read_uint16(ifile);
  366.            if(temp != 0xFFFF) data.push_back(temp);
  367.       
  368.            if(temp == 0xFFFF || i == n_values - 1)
  369.              {
  370.               // must have at least 3 elements
  371.               if(data.size() < 3)
  372.                  return error("Expecting at least three tristrip indices.");
  373.       
  374.               // process first triangle
  375.               unsigned short a = data[0] + 1;
  376.               unsigned short b = data[1] + 1;
  377.               unsigned short c = data[2] + 1;
  378.               ofile << " addtriangle(pointlist[" << a << "], pointlist[" << c << "], pointlist[" << b << "]);" << endl;
  379.       
  380.               // process deque
  381.               for(size_t j = 3; j < data.size(); j++) {
  382.                   a = b;
  383.                   b = c;
  384.                   c = data[j] + 1;
  385.                   if(j % 2) ofile << " addtriangle(pointlist[" << a << "], pointlist[" << b << "], pointlist[" << c << "]);" << endl;
  386.                   else ofile << " addtriangle(pointlist[" << a << "], pointlist[" << c << "], pointlist[" << b << "]);" << endl;
  387.                  }
  388.       
  389.               // clear deque
  390.               data.erase(data.begin(), data.end());
  391.               data.clear();
  392.              }
  393.           }
  394.        ofile << " editend();" << endl;
  395.        break;
  396.       }
  397.     else if(filetype == 0x263)
  398.       {
  399.        // read 40 bytes
  400.        BE_read_float(ifile);
  401.        BE_read_float(ifile);
  402.        BE_read_float(ifile);
  403.        BE_read_float(ifile);
  404.        BE_read_float(ifile);
  405.        BE_read_float(ifile);
  406.        BE_read_float(ifile);
  407.        BE_read_float(ifile);
  408.        BE_read_float(ifile);
  409.        BE_read_float(ifile);
  410.    
  411.        // read points
  412.        struct point { short x, y, z, w; unsigned short u, v; };
  413.        boost::shared_array<point> points(new point[n_points]);
  414.        ifile.read((char*)&points.get()[0], n_points*sizeof(point));
  415.  
  416.        ofile << " editbegin();" << endl;
  417.        for(size_t i = 0; i < n_points; i++) {
  418.            reverse_byte_order(&points[i].x);
  419.            reverse_byte_order(&points[i].y);
  420.            reverse_byte_order(&points[i].z);
  421.            reverse_byte_order(&points[i].w);
  422.            reverse_byte_order(&points[i].u);
  423.            reverse_byte_order(&points[i].v);
  424.            float x = points[i].x/32767.0f;
  425.            float y = points[i].y/32767.0f;
  426.            float z = points[i].z/32767.0f;
  427.            float u = points[i].u/65535.0f;
  428.            float v = points[i].v/65535.0f;
  429.            ofile << " pointlist[" << i + 1 << "]" << " = " << "addpoint(" << x << "," << y << "," << z << ");" << endl;
  430.            ofile << " uvmap.setValue(pointlist[" << (i + 1) << "]," << "@" << u << "," << v << "@);" << endl;
  431.           }
  432.        ofile << " editend();" << endl;
  433.    
  434.        // read triangles
  435.        ofile << " editbegin();" << endl;
  436.        deque<unsigned short> data;
  437.        for(size_t i = 0; i < n_values; i++)
  438.           {
  439.            unsigned short temp = BE_read_uint16(ifile);
  440.            if(temp != 0xFFFF) data.push_back(temp);
  441.       
  442.            if(temp == 0xFFFF || i == n_values - 1)
  443.              {
  444.               // must have at least 3 elements
  445.               if(data.size() < 3)
  446.                  return error("Expecting at least three tristrip indices.");
  447.       
  448.               // process first triangle
  449.               unsigned short a = data[0] + 1;
  450.               unsigned short b = data[1] + 1;
  451.               unsigned short c = data[2] + 1;
  452.               ofile << " addtriangle(pointlist[" << a << "], pointlist[" << c << "], pointlist[" << b << "]);" << endl;
  453.       
  454.               // process deque
  455.               for(size_t j = 3; j < data.size(); j++) {
  456.                   a = b;
  457.                   b = c;
  458.                   c = data[j] + 1;
  459.                   if(j % 2) ofile << " addtriangle(pointlist[" << a << "], pointlist[" << b << "], pointlist[" << c << "]);" << endl;
  460.                   else ofile << " addtriangle(pointlist[" << a << "], pointlist[" << c << "], pointlist[" << b << "]);" << endl;
  461.                  }
  462.       
  463.               // clear deque
  464.               data.erase(data.begin(), data.end());
  465.               data.clear();
  466.              }
  467.           }
  468.        ofile << " editend();" << endl;
  469.       }
  470.     else if(filetype == 0x277)
  471.       {
  472.        // read 40 bytes
  473.        BE_read_float(ifile);
  474.        BE_read_float(ifile);
  475.        BE_read_float(ifile);
  476.        BE_read_float(ifile);
  477.        BE_read_float(ifile);
  478.        BE_read_float(ifile);
  479.        BE_read_float(ifile);
  480.        BE_read_float(ifile);
  481.        BE_read_float(ifile);
  482.        BE_read_float(ifile);
  483.       
  484.        // read points
  485.        struct point { short x, y, z; unsigned short a, b, c, d, e, f, g; };
  486.        boost::shared_array<point> points(new point[n_points]);
  487.        ifile.read((char*)&points.get()[0], n_points*sizeof(point));
  488.  
  489.        ofile << " editbegin();" << endl;
  490.        for(size_t i = 0; i < n_points; i++) {
  491.            reverse_byte_order(&points[i].x);
  492.            reverse_byte_order(&points[i].y);
  493.            reverse_byte_order(&points[i].z);
  494.            reverse_byte_order(&points[i].a);
  495.            reverse_byte_order(&points[i].b);
  496.            reverse_byte_order(&points[i].c);
  497.            reverse_byte_order(&points[i].d);
  498.            reverse_byte_order(&points[i].e);
  499.            reverse_byte_order(&points[i].f);
  500.            reverse_byte_order(&points[i].g);
  501.            float x = points[i].x/32767.0f;
  502.            float y = points[i].y/32767.0f;
  503.            float z = points[i].z/32767.0f;
  504.            float a = points[i].a/65535.0f;
  505.            float b = points[i].b/65535.0f;
  506.            float c = points[i].c/65535.0f;
  507.            float d = points[i].d/65535.0f;
  508.            float e = points[i].e/65535.0f;
  509.            float f = points[i].f/65535.0f;
  510.            float g = points[i].g/65535.0f;
  511.            ofile << " pointlist[" << i + 1 << "]" << " = " << "addpoint(" << x << "," << y << "," << z << ");" << endl;
  512.            ofile << " uvmap.setValue(pointlist[" << (i + 1) << "]," << "@" << b << "," << c << "@);" << endl;
  513.           }
  514.        ofile << " editend();" << endl;
  515.  
  516.        // read triangles
  517.        ofile << " editbegin();" << endl;
  518.        deque<unsigned short> data;
  519.        for(size_t i = 0; i < n_values; i++)
  520.           {
  521.            unsigned short temp = BE_read_uint16(ifile);
  522.            if(temp != 0xFFFF) data.push_back(temp);
  523.       
  524.            if(temp == 0xFFFF || i == n_values - 1)
  525.              {
  526.               // must have at least 3 elements
  527.               if(data.size() > 2)
  528.                 {
  529.                  // process first triangle
  530.                  unsigned short a = data[0] + 1;
  531.                  unsigned short b = data[1] + 1;
  532.                  unsigned short c = data[2] + 1;
  533.                  ofile << " addtriangle(pointlist[" << a << "], pointlist[" << c << "], pointlist[" << b << "]);" << endl;
  534.       
  535.                  // process deque
  536.                  for(size_t j = 3; j < data.size(); j++) {
  537.                      a = b;
  538.                      b = c;
  539.                      c = data[j] + 1;
  540.                      if(j % 2) ofile << " addtriangle(pointlist[" << a << "], pointlist[" << b << "], pointlist[" << c << "]);" << endl;
  541.                      else ofile << " addtriangle(pointlist[" << a << "], pointlist[" << c << "], pointlist[" << b << "]);" << endl;
  542.                     }
  543.                 }
  544.       
  545.               // clear deque
  546.               data.erase(data.begin(), data.end());
  547.               data.clear();
  548.              }
  549.           }
  550.        ofile << " editend();" << endl;
  551.       }
  552.     else {
  553.        Sleep(10000);
  554.        return error("Cannot process surface. Unknown surface type.");
  555.       }
  556.  
  557.     // increment number of surfaces processed
  558.     surface++;
  559.  
  560.     // read footer
  561.     char footer[28];
  562.     ifile.read(&footer[0], 28);
  563.  
  564.     // continue processing?
  565.     if(BE_read_uint32(ifile) != 0x184C4D42) {
  566.        Sleep(10000);
  567.        return error("Invalid magic number.");
  568.       }
  569.     namelen = LE_read_uint32(ifile);
  570.  }
  571.  while(surface < n_surfaces);
  572.  
  573.  // finalize lscript
  574.  ofile << "}" << endl;
  575.  
  576.  return true;
  577. }
  578.  
  579. void traverse_hierarchy(unsigned short node, std::deque<bone>& tree)
  580. {
  581.  typedef std::set<unsigned short>::iterator set_iterator;
  582.  for(set_iterator i = tree[node].children.begin(); i != tree[node].children.end(); i++) {
  583.      tree[*i].absolute_x += tree[node].relative_x;
  584.      tree[*i].absolute_y += tree[node].relative_y;
  585.      tree[*i].absolute_z += tree[node].relative_z;
  586.      traverse_hierarchy(*i, tree);
  587.     }
  588. }
  589.  
  590. bool extract_bmd6model(const char* filename, const char* savename, const char* bonename)
  591. {
  592.  std::cout << "Processing file: " << filename << std::endl;
  593.  ifstream ifile(filename, ios::binary);
  594.  if(!ifile) return error("Could not open file.");
  595.  
  596.  // 0x00
  597.  BE_read_uint32(ifile);
  598.  BE_read_uint16(ifile);
  599.  BE_read_uint16(ifile);
  600.  BE_read_float(ifile);
  601.  BE_read_float(ifile);
  602.  
  603.  // 0x10
  604.  BE_read_float(ifile);
  605.  BE_read_float(ifile);
  606.  BE_read_float(ifile);
  607.  BE_read_float(ifile);
  608.  
  609.  // 0x20
  610.  BE_read_uint08(ifile);
  611.  BE_read_uint16(ifile);
  612.  BE_read_uint16(ifile);
  613.  BE_read_uint16(ifile);
  614.  BE_read_uint16(ifile);
  615.  BE_read_uint16(ifile);
  616.  
  617.  unsigned short offset1 = BE_read_uint16(ifile); cout << "offset1 = " << offset1 << endl;
  618.  unsigned short offset2 = BE_read_uint16(ifile);
  619.  unsigned short n_strings_actual = BE_read_uint16(ifile);
  620.  unsigned short n_strings = (n_strings_actual + 7) & (~7);
  621.  boost::shared_array<unsigned short> offsets(new unsigned short[22]);
  622.  ifile.read((char*)&offsets[0], 44);
  623.  for(size_t i = 0; i < 22; i++) reverse_byte_order(&offsets[i]);
  624.  
  625.  // bone list
  626.  std::deque<bone> bone_list;
  627.  for(size_t i = 0; i < n_strings; i++) {
  628.      bone b = { i, 0xFFFF, "", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
  629.      bone_list.push_back(b);
  630.     }
  631.  
  632.  // read quaternions
  633.  cout << "n_strings_actual = " << n_strings_actual << endl;
  634.  cout << "n_strings = " << n_strings << endl;
  635.  for(size_t i = 0; i < n_strings; i++) {
  636.      float q[4];
  637.      ifile.read((char*)&q[0], 16);
  638.      reverse_byte_order(&q[0]);
  639.      reverse_byte_order(&q[1]);
  640.      reverse_byte_order(&q[2]);
  641.      reverse_byte_order(&q[3]);
  642.      bone_list[i].q_relative.a = q[0];
  643.      bone_list[i].q_relative.b = q[1];
  644.      bone_list[i].q_relative.c = q[2];
  645.      bone_list[i].q_relative.d = q[3];
  646.      bone_list[i].q_absolute.a = q[0];
  647.      bone_list[i].q_absolute.b = q[1];
  648.      bone_list[i].q_absolute.c = q[2];
  649.      bone_list[i].q_absolute.d = q[3];
  650.      //cout << "q = " << q[0] << "," << q[1] << "," << q[2] << "," << q[3] << endl;
  651.     }
  652.  
  653.  // read scale data
  654.  for(size_t i = 0; i < n_strings; i++) {
  655.      float s[3];
  656.      ifile.read((char*)&s[0], 12);
  657.      reverse_byte_order(&s[0]);
  658.      reverse_byte_order(&s[1]);
  659.      reverse_byte_order(&s[2]);
  660.     }
  661.  
  662.  // read translation data
  663.  deque<sl::vector3D<float>> translation_data;
  664.  for(size_t i = 0; i < n_strings; i++) {
  665.      float t[3];
  666.      ifile.read((char*)&t[0], 12);
  667.      reverse_byte_order(&t[0]);
  668.      reverse_byte_order(&t[1]);
  669.      reverse_byte_order(&t[2]);
  670.      sl::vector3D<float> temp(t[0], t[1], t[2]);
  671.      translation_data.push_back(temp);
  672.      bone_list[i].relative_x = bone_list[i].absolute_x = t[0];
  673.      bone_list[i].relative_y = bone_list[i].absolute_y = t[1];
  674.      bone_list[i].relative_z = bone_list[i].absolute_z = t[2];
  675.     }
  676.  
  677.  // read bone parent data
  678.  typedef std::map<unsigned short, std::set<unsigned short>> map_type;
  679.  
  680.  // bone hierarchy
  681.  for(size_t i = 0; i < n_strings; i++)
  682.     {
  683.      // get parent
  684.      unsigned short parent;
  685.      ifile.read((char*)&parent, sizeof(parent));
  686.      reverse_byte_order(&parent);
  687.  
  688.      // add child
  689.      if(parent == 0xFFFF) continue;
  690.      bone_list[parent].children.insert(i);
  691.      bone_list[i].parent_index = parent;
  692.     }
  693.  
  694.  traverse_hierarchy(0, bone_list);
  695.  
  696.  // move to bone strings
  697.  ifile.seekg(0x2D + offset1);
  698.  
  699.  // read bone strings
  700.  for(size_t i = 0; i < n_strings; i++) {
  701.      unsigned int slen = LE_read_uint32(ifile);
  702.      if(!slen) continue;
  703.      char buffer[1024];
  704.      ifile.read((char*)&buffer[0], slen);
  705.      buffer[slen] = '\0';
  706.      memmove(bone_list[i].name, buffer, strlen(buffer) + 1);
  707.     }
  708.  
  709.  // open destination file
  710.  //ofstream bfile(bonename);
  711.  //if(!bfile) return error("Could not create output file.");
  712.  
  713.  // save bone heirarchy
  714.  //bfile << "@version 2.3" << endl;
  715.  //bfile << "@warnings" << endl;
  716.  //bfile << "@script generic" << endl;
  717.  //bfile << "@name ShowHide" << endl;
  718.  //bfile << "generic" << endl;
  719.  //bfile << "{" << endl;
  720.  
  721.  for(size_t i = 0; i < bone_list.size(); i++)
  722.     {
  723.      // add child bone
  724.      if(bone_list[i].parent_index != 0xFFFF) {
  725.         //bfile << " SelectByName(\"" << bone_list[bone_list[i].parent_index].name << "\");" << endl;
  726.         //bfile << " AddChildBone(\"" << bone_list[i].name << "\");" << endl;
  727.         //bfile << " BoneType(2);" << endl;
  728.         //bfile << " Position(" << bone_list[i].absolute_x << "," << bone_list[i].absolute_y << "," << bone_list[i].absolute_z << ");" << endl;
  729.        }
  730.      else if(strlen(bone_list[i].name) > 0) {
  731.         //bfile << " AddBone(\"" << bone_list[i].name << "\");" << endl;
  732.         //bfile << " BoneType(2);" << endl;
  733.         //bfile << " Position(" << bone_list[i].absolute_x << "," << bone_list[i].absolute_y << "," << bone_list[i].absolute_z << ");" << endl;
  734.        }
  735.     }
  736.  //bfile << "}" << endl;
  737.  
  738.  // read bone information
  739.  boost::shared_array<unsigned char> bone_info(new unsigned char[n_strings]);
  740.  ifile.read((char*)&bone_info.get()[0], n_strings);
  741.  
  742.  // read rotation matrices
  743.  size_t bone_matrix_size = 12*n_strings;
  744.  boost::shared_array<float> bone_matrix(new float[bone_matrix_size]);
  745.  ifile.read((char*)&bone_matrix.get()[0], bone_matrix_size*sizeof(float));
  746.  for(size_t i = 0; i < bone_matrix_size; i++) reverse_byte_order(&bone_matrix.get()[i]);
  747.  
  748.  // read (min, max)
  749.  BE_read_float(ifile);
  750.  BE_read_float(ifile);
  751.  BE_read_float(ifile);
  752.  BE_read_float(ifile);
  753.  BE_read_float(ifile);
  754.  BE_read_float(ifile);
  755.  
  756.  // read number of surfaces
  757.  size_t surfaces = BE_read_uint32(ifile);
  758.  if(!surfaces) return error("No surfaces");
  759.  cout << " surfaces = " << surfaces << endl;
  760.  
  761.  // create file
  762.  ofstream ofile(savename);
  763.  ofile << "main" << endl;
  764.  ofile << "{" << endl;
  765.  
  766.  // for each surface
  767.  for(size_t s = 0; s < surfaces; s++)
  768.     {
  769.      // read surface name
  770.      char sname[1024];
  771.      memset(sname, 0, 1024);
  772.      unsigned int sname_size = LE_read_uint32(ifile);
  773.      if(sname_size) ifile.read(&sname[0], sname_size);
  774.      else sprintf(sname, "surface_%d", s);
  775.  
  776.      // read path name
  777.      char pname[1024];
  778.      memset(pname, 0, 1024);
  779.      unsigned int pname_size = LE_read_uint32(ifile);
  780.      if(pname_size) ifile.read(&pname[0], pname_size);
  781.      else sprintf(pname, "path_%d", s);
  782.  
  783.      // set foreground layer and surface name
  784.      ofile << " lyrsetfg(" << (s + 1) << ");" << endl;
  785.      ofile << " setsurface(\"" << sname  << "\");" << endl;
  786.  
  787.      // create UV map
  788.      ofile << " editbegin();" << endl;
  789.      ofile << " uvmap_" << (s + 1) << " = VMap(\"texture\", \"" << sname << "\", 2);" << endl;
  790.      ofile << " editend();" << endl;
  791.  
  792.      // read surface information
  793.      unsigned char infobyte = BE_read_uint08(ifile);
  794.      size_t n_points = BE_read_uint32(ifile);
  795.      size_t n_triangles = BE_read_uint32(ifile);
  796.      cout << " points = " << n_points << endl;
  797.      cout << " triangles = " << n_triangles << endl;
  798.      BE_read_float(ifile);
  799.      BE_read_float(ifile);
  800.      BE_read_float(ifile);
  801.      BE_read_float(ifile);
  802.      BE_read_float(ifile);
  803.      BE_read_float(ifile);
  804.  
  805.      // read points
  806.      ofile << " editbegin();" << endl;
  807.      for(size_t i = 0; i < n_points; i++)
  808.         {
  809.          float x = BE_read_float(ifile);
  810.          float y = BE_read_float(ifile);
  811.          float z = BE_read_float(ifile);
  812.          float u = BE_read_float(ifile);
  813.          float v = BE_read_float(ifile);
  814.          BE_read_uint16(ifile);
  815.          BE_read_uint16(ifile);
  816.          BE_read_uint16(ifile);
  817.          BE_read_uint16(ifile);
  818.          BE_read_uint16(ifile);
  819.          BE_read_uint16(ifile);
  820.          ofile << " pointlist[" << i + 1 << "]" << " = " << "addpoint(" << x << "," << y << "," << z << ");" << endl;
  821.          ofile << " uvmap_" << (s + 1) << ".setValue(pointlist[" << (i + 1) << "]," << "@" << u << "," << v << "@);" << endl;
  822.         }
  823.      ofile << " editend();" << endl;
  824.  
  825.      // read triangles
  826.      boost::shared_array<unsigned short> data(new unsigned short[n_triangles*3]);
  827.      ifile.read((char*)&data.get()[0], n_triangles*3*sizeof(unsigned short));
  828.      for(size_t i = 0; i < 3*n_triangles; i++) reverse_byte_order(&data.get()[i]);
  829.      ofile << " editbegin();" << endl;    
  830.      size_t index = 0;
  831.      for(size_t i = 0; i < n_triangles; i++) {
  832.          unsigned short a = data.get()[index++] + 1;
  833.          unsigned short b = data.get()[index++] + 1;
  834.          unsigned short c = data.get()[index++] + 1;
  835.          ofile << " addtriangle(pointlist[" << a << "], pointlist[" << c << "], pointlist[" << b << "]);" << endl;
  836.         }
  837.      ofile << " editend();" << endl;
  838.  
  839.      // padding?
  840.      BE_read_uint32(ifile); // usually 0
  841.      BE_read_uint32(ifile); // usually number of bones repeated
  842.      unsigned int has_weights = BE_read_uint08(ifile); // usually 0, but can be 1
  843.      BE_read_uint32(ifile); // usually 0
  844.  
  845.      // load weights
  846.      if(has_weights) {
  847.         boost::shared_array<float> weights(new float[n_points]);
  848.         ifile.read((char*)&weights.get()[0], n_points*sizeof(float));
  849.         for(size_t i = 0; i < n_points; i++) reverse_byte_order(&weights[i]);
  850.        }
  851.     }
  852.  
  853.  ofile << "}" << endl;
  854.  
  855.  return true;
  856. }