home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 5257 / source.7z / x_smc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2012-03-20  |  11.2 KB  |  342 lines

  1. #include "xentax.h"
  2. #include "x_lwo.h"
  3. #include "x_smc.h"
  4.  
  5. struct SMCJointInfo {
  6.  uint32 listindex;
  7.  std::string name;
  8. };
  9.  
  10. class SMCJointVisitor : public JOINTVISITOR {
  11.  private :
  12.   std::map<uint32, SMCJointInfo> indexmap;
  13.   std::deque<lwVertex3D> pnts;
  14.   std::deque<lwSkelegon> pols;
  15.  private :
  16.   SMCJointVisitor(const SMCJointVisitor&);
  17.   void operator =(const SMCJointVisitor&);
  18.  public :
  19.   SMCJointVisitor() {}
  20.  ~SMCJointVisitor() {}
  21.  public :
  22.   uint32 joints(void)const
  23.   {
  24.    return pnts.size();
  25.   }
  26.   uint32 bones(void)const
  27.   {
  28.    return pols.size();
  29.   }
  30.   boost::shared_array<lwVertex3D> createJoints(void)const
  31.   {
  32.    boost::shared_array<lwVertex3D> data(new lwVertex3D[pnts.size()]);
  33.    for(size_t i = 0; i < pnts.size(); i++) {
  34.        data[i].x = pnts[i].x;
  35.        data[i].y = pnts[i].y;
  36.        data[i].z = pnts[i].z;
  37.       }
  38.    return data;
  39.   }
  40.   boost::shared_array<lwSkelegon> createBones(void)const
  41.   {
  42.    boost::shared_array<lwSkelegon> data(new lwSkelegon[pols.size()]);
  43.    for(size_t i = 0; i < pols.size(); i++) {
  44.        data[i].a = pols[i].a;
  45.        data[i].b = pols[i].b;
  46.        data[i].name = pols[i].name;
  47.       }
  48.    return data;
  49.   }
  50.   return_type operator ()(argument1 joint, argument2 index)
  51.   {
  52.    // joint must be valid
  53.    if(index == INVALID_JOINT) return false;
  54.  
  55.    // initialize position
  56.    lwVertex3D pos;
  57.    pos.x = joint.rel_x;
  58.    pos.y = joint.rel_y;
  59.    pos.z = joint.rel_z;
  60.  
  61.    // save bone
  62.    if(joint.parent != INVALID_JOINT)
  63.      {
  64.       // get parent information
  65.       std::map<uint32, SMCJointInfo>::iterator iter = indexmap.find(joint.parent);
  66.       if(iter == indexmap.end()) return false;
  67.       SMCJointInfo parent_info = iter->second;
  68.  
  69.       // convert to absolute position
  70.       pos.x += pnts[parent_info.listindex].x;
  71.       pos.y += pnts[parent_info.listindex].y;
  72.       pos.z += pnts[parent_info.listindex].z;
  73.  
  74.       // save bone
  75.       lwSkelegon bone;
  76.       bone.a = parent_info.listindex;
  77.       bone.b = pnts.size();
  78.       bone.name += parent_info.name;
  79.       bone.name += "_";
  80.       bone.name += joint.name;
  81.       pols.push_back(bone);
  82.      }
  83.  
  84.    // save point information
  85.    SMCJointInfo info;
  86.    info.listindex = pnts.size();
  87.    info.name = joint.name;
  88.    indexmap.insert(std::map<uint32, SMCJointInfo>::value_type(index, info));
  89.  
  90.    // save point
  91.    pnts.push_back(pos);
  92.    return true;
  93.   }
  94. };
  95.  
  96. template<class T>
  97. bool SaveTriangleList(const SMC_INDEX_BUFFER& ib, boost::shared_array<lwTriangle>& facedata)
  98. {
  99.  // validate
  100.  if(ib.elem < 3) return error("Index buffer is not a triangle list.");
  101.  if(ib.elem % 3) return error("Index buffer is not a triangle list.");
  102.  if(ib.type != FACE_TYPE_TRIANGLES) return error("Index buffer is not a triangle list.");
  103.  
  104.  // pointer to data
  105.  const T* data = reinterpret_cast<const T*>(ib.data.get());
  106.  if(!data) return error("Invalid data pointer.");
  107.  
  108.  // transfer data
  109.  uint32 n_triangles = ib.elem/3;
  110.  uint32 index = 0;
  111.  for(uint32 i = 0; i < n_triangles; i++) {
  112.      facedata[i].a = data[index++];
  113.      facedata[i].b = data[index++];
  114.      facedata[i].c = data[index++];
  115.     }
  116.  
  117.  return true;
  118. }
  119.  
  120. template<class T>
  121. bool SaveTriangleStrip(const SMC_INDEX_BUFFER& ib, boost::shared_array<lwTriangle>& facedata)
  122. {
  123.  // validate
  124.  if(ib.elem < 3) return error("Index buffer is not a triangle strip.");
  125.  if(ib.type != FACE_TYPE_TRISTRIP) return error("Index buffer is not a triangle strip.");
  126.  
  127.  // pointer to data
  128.  const T* data = reinterpret_cast<const T*>(ib.data.get());
  129.  if(!data) return error("Invalid data pointer.");
  130.  
  131.  // first triangle
  132.  uint32 a = facedata[0].a = data[0];
  133.  uint32 b = facedata[0].b = data[1];
  134.  uint32 c = facedata[0].c = data[2];
  135.  
  136.  // other triangles
  137.  uint32 n_triangles = ib.elem - 2;
  138.  for(size_t i = 1; i < n_triangles; i++)
  139.     {
  140.      // next triangle
  141.      a = b;
  142.      b = c;
  143.      c = data[i];
  144.  
  145.      // winding
  146.      if(!(a == b || a == c || b == c)) {
  147.         if(i % 2) {
  148.            facedata[i].a = a;
  149.            facedata[i].b = c;
  150.            facedata[i].c = b;
  151.           }
  152.         else {
  153.            facedata[i].a = a;
  154.            facedata[i].b = b;
  155.            facedata[i].c = c;
  156.           }
  157.        }
  158.     }
  159.  
  160.  return true;
  161. }
  162.  
  163. bool SaveLWO(const char* path, const char* name, const SIMPLEMODELCONTAINER& data)
  164. {
  165.  // validate
  166.  using namespace std;
  167.  if(!path || !strlen(path)) return error("SaveLWO: A path must be specified.");
  168.  if(!name || !strlen(name)) return error("SaveLWO: A name must be specified.");
  169.  
  170.  // data
  171.  boost::shared_array<lwVertex3D> vd; // PNTS data
  172.  boost::shared_array<lwVertex2D> ud; // TXUV data
  173.  boost::shared_array<lwTriangle> fd; // POLS data
  174.  
  175.  // save LAYR
  176.  lwFileSaver saver;
  177.  saver.insertLayr(0, nullptr);
  178.  
  179.  // save CLIP
  180.  for(size_t i = 0; i < data.textures.size(); i++)
  181.      saver.insertClip((i + 1), data.textures[i].filename.c_str());
  182.  
  183.  // save PNTS
  184.  if(data.vbuffer.elem) {
  185.     // save xyz
  186.     if(data.vbuffer.flags & VERTEX_POSITION) {
  187.        vd.reset(new lwVertex3D[data.vbuffer.elem]);
  188.        for(uint32 i = 0; i < data.vbuffer.elem; i++) {
  189.            vd[i].x = data.vbuffer.data[i].vx;
  190.            vd[i].y = data.vbuffer.data[i].vy;
  191.            vd[i].z = data.vbuffer.data[i].vz;
  192.           }
  193.        saver.insertPnts(0, 0, vd, data.vbuffer.elem);
  194.       }
  195.     // save uv
  196.     if(data.vbuffer.flags & VERTEX_UV) {
  197.        ud.reset(new lwVertex2D[data.vbuffer.elem]);
  198.        for(uint32 i = 0; i < data.vbuffer.elem; i++) {
  199.            ud[i].x = data.vbuffer.data[i].tu;
  200.            ud[i].y = data.vbuffer.data[i].tv;
  201.           }
  202.       }
  203.     // save weights
  204.     if(data.vbuffer.flags & VERTEX_WEIGHTS)
  205.       {
  206.        if(data.vbuffer.flags & VERTEX_BONEIDX)
  207.          {
  208.           // TODO:
  209.          }
  210.        else if(data.vbuffer.flags & VERTEX_WMAPIDX)
  211.          {
  212.           // construct WGHT maps
  213.           typedef map<uint32, deque<lwRefVertex1D>> wmap_type;
  214.           wmap_type wmap;
  215.           for(uint32 i = 0; i < data.vbuffer.elem; i++) {
  216.               for(uint32 j = 0; j < 8; j++) {
  217.                   if(data.vbuffer.data[i].mi[j] != INVALID_VERTEX_WMAP_INDEX) {
  218.                      wmap_type::iterator iter = wmap.find(data.vbuffer.data[i].mi[j]);
  219.                      if(iter == wmap.end()) iter = wmap.insert(wmap_type::value_type(data.vbuffer.data[i].mi[j], deque<lwRefVertex1D>())).first;
  220.                      lwRefVertex1D item;
  221.                      item.reference = i;
  222.                      item.x = data.vbuffer.data[i].wv[j]/65535.0f;
  223.                      iter->second.push_back(item);
  224.                     }
  225.                  }
  226.              }
  227.  
  228.           // save WGHT maps
  229.           for(wmap_type::iterator iter = wmap.begin(); iter != wmap.end(); iter++) {
  230.               if(iter->second.size()) {
  231.                  boost::shared_array<lwRefVertex1D> wset(new lwRefVertex1D[iter->second.size()]);
  232.                  uint32 index = 0;
  233.                  for(size_t i = 0; i < iter->second.size(); i++) {
  234.                      wset[index].reference = iter->second[i].reference;
  235.                      wset[index].x = iter->second[i].x;
  236.                      index++;
  237.                     }
  238.                  stringstream ss;
  239.                  ss << "wmap_" << setfill('0') << setw(3) << iter->first;
  240.                  saver.insertWght(0, 0, ss.str().c_str(), wset, iter->second.size());
  241.                 }
  242.              }
  243.          }
  244.       }
  245.    }
  246.  
  247.  // save POLS
  248.  for(uint32 i = 0; i < data.ibuffer.size(); i++)
  249.     {
  250.      const SMC_INDEX_BUFFER& ib = data.ibuffer[i];
  251.      if(ib.type == FACE_TYPE_TRIANGLES) {
  252.         uint32 n_triangles = ib.elem/3;
  253.         fd.reset(new lwTriangle[n_triangles]);
  254.         if(ib.format == FACE_FORMAT_UINT_08) SaveTriangleList<uint08>(ib, fd);
  255.         else if(ib.format == FACE_FORMAT_UINT_16) SaveTriangleList<uint16>(ib, fd);
  256.         else if(ib.format == FACE_FORMAT_UINT_32) SaveTriangleList<uint32>(ib, fd);
  257.         saver.insertPols(0, 0, ib.name.c_str(), fd, n_triangles);
  258.        }
  259.      else if(ib.type == FACE_TYPE_TRISTRIP) {
  260.         uint32 n_triangles = ib.elem - 2;
  261.         fd.reset(new lwTriangle[n_triangles]);
  262.         if(ib.format == FACE_FORMAT_UINT_08) SaveTriangleStrip<uint08>(ib, fd);
  263.         else if(ib.format == FACE_FORMAT_UINT_16) SaveTriangleStrip<uint16>(ib, fd);
  264.         else if(ib.format == FACE_FORMAT_UINT_32) SaveTriangleStrip<uint32>(ib, fd);
  265.         saver.insertPols(0, 0, ib.name.c_str(), fd, n_triangles);
  266.        }
  267.  
  268.      // save TXUV
  269.     if(data.vbuffer.flags & VERTEX_UV)
  270.       {
  271.        // construct TXUV map
  272.        map<uint32, lwVertex2D> uvmap;
  273.        uint32 n_triangles = ib.elem/3;
  274.        for(uint32 j = 0; j < n_triangles; j++) {
  275.            uint32 ref_a = fd[j].a;
  276.            uint32 ref_b = fd[j].b;
  277.            uint32 ref_c = fd[j].c;
  278.            lwVertex2D val_a = ud[ref_a];
  279.            lwVertex2D val_b = ud[ref_b];
  280.            lwVertex2D val_c = ud[ref_c];
  281.            uvmap.insert(map<uint32, lwVertex2D>::value_type(ref_a, val_a));
  282.            uvmap.insert(map<uint32, lwVertex2D>::value_type(ref_b, val_b));
  283.            uvmap.insert(map<uint32, lwVertex2D>::value_type(ref_c, val_c));
  284.           }
  285.  
  286.        // save TXUV map
  287.        boost::shared_array<lwRefVertex2D> uvset(new lwRefVertex2D[uvmap.size()]);
  288.        uint32 index = 0;
  289.        for(map<uint32, lwVertex2D>::iterator iter = uvmap.begin(); iter != uvmap.end(); iter++) {
  290.            uvset[index].reference = iter->first;
  291.            uvset[index].x = iter->second.x;
  292.            uvset[index].y = iter->second.y;
  293.            index++;
  294.           }
  295.        saver.insertTxuv(0, 0, ib.name.c_str(), uvset, uvmap.size());
  296.  
  297.        // enable texture mapping
  298.        if(ib.material != INVALID_MATERIAL)
  299.          {
  300.           // enable material
  301.           const SMC_MATERIAL& material = data.materials[ib.material];
  302.           if(material.basemap != INVALID_TEXTURE_INDEX) {
  303.              saver.enableSurfColrImag(ib.name.c_str());
  304.              saver.setSurfColrVmap(ib.name.c_str(), ib.name.c_str());
  305.              saver.setSurfColrImag(ib.name.c_str(), material.basemap + 1);
  306.             }
  307.           if(material.specmap != INVALID_TEXTURE_INDEX) {
  308.              saver.enableSurfSpecImag(ib.name.c_str());
  309.              saver.setSurfSpecVmap(ib.name.c_str(), ib.name.c_str());
  310.              saver.setSurfSpecImag(ib.name.c_str(), material.specmap + 1);
  311.             }
  312.           if(material.tranmap != INVALID_TEXTURE_INDEX) {
  313.              saver.enableSurfTranImag(ib.name.c_str());
  314.              saver.setSurfTranVmap(ib.name.c_str(), ib.name.c_str());
  315.              saver.setSurfTranImag(ib.name.c_str(), material.tranmap + 1);
  316.              saver.setSurfTranNega(ib.name.c_str(), 1); // TODO: remove
  317.             }
  318.          }
  319.       }
  320.     }
  321.  
  322.  // save SKEL
  323.  for(size_t i = 0; i < data.skeletons.size(); i++)
  324.     {
  325.      // skeleton identifier
  326.      const SKELETON& item = data.skeletons[i];
  327.  
  328.      // traverse joints
  329.      SMCJointVisitor jv;
  330.      item.traverse(jv);
  331.      if(jv.joints() != item.joints()) return error("Invalid skeleton.");
  332.  
  333.      // insert skeleton
  334.      saver.insertJnts(0, i, jv.createJoints(), jv.joints());
  335.      saver.insertSkel(0, 0, item.get_identifier(), jv.createBones(), jv.bones());
  336.     }
  337.  
  338.  // save file
  339.  std::stringstream ss;
  340.  ss << path << name << ".lwo";
  341.  return saver.save(ss.str().c_str());
  342. }