home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 5036 / source.7z / x_geom.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2012-02-01  |  13.2 KB  |  282 lines

  1. #include "xentax.h"
  2.  
  3. bool GeometryToOBJ(const char* path, const char* name, const deque<VERTEX_BUFFER>& vd, const deque<INDEX_BUFFER>& fd)
  4. {
  5.  // create OBJ file
  6.  stringstream ss;
  7.  ss << path << name << ".obj";
  8.  ofstream objfile(ss.str().c_str());
  9.  if(!objfile) return error("OBJ EXPORT: Error creating output file.");
  10.  
  11.  // OBJ file header
  12.  objfile << "o " << name << ".obj" << endl;
  13.  objfile << "mtllib " << name << ".mtl" << endl;
  14.  
  15.  struct OBJOFFSETINFO {
  16.   uint32 vertex_base;
  17.   uint32 normal_base;
  18.   uint32 texmap_base;
  19.  };
  20.  
  21.  // index to each vertex buffer
  22.  OBJOFFSETINFO ooi = { 0, 0, 0 };
  23.  deque<OBJOFFSETINFO> offset_list;
  24.  for(size_t i = 0; i < vd.size(); i++) {
  25.      offset_list.push_back(ooi);
  26.      if(vd[i].flags & VERTEX_POSITION) ooi.vertex_base += vd[i].elem;
  27.      if(vd[i].flags & VERTEX_NORMAL) ooi.normal_base += vd[i].elem;
  28.      if(vd[i].flags & VERTEX_UV) ooi.texmap_base += vd[i].elem;
  29.     }
  30.  
  31.  // output vertices
  32.  for(size_t i = 0; i < vd.size(); i++) {
  33.      if(vd[i].flags & VERTEX_POSITION) {
  34.         objfile << "# POSITION BUFFER " << i << endl;
  35.         for(size_t j = 0; j < vd[i].elem; j++)
  36.             objfile << "v " << vd[i].data[j].vx << " " << vd[i].data[j].vy << " " << vd[i].data[j].vz << endl;
  37.        }
  38.     }
  39.  for(size_t i = 0; i < vd.size(); i++) {
  40.      if(vd[i].flags & VERTEX_NORMAL) {
  41.         objfile << "# NORMAL BUFFER " << i << endl;
  42.         for(size_t j = 0; j < vd[i].elem; j++)
  43.             objfile << "vn " << vd[i].data[j].nx << " " << vd[i].data[j].ny << " " << vd[i].data[j].nz << endl;
  44.        }
  45.     }
  46.  for(size_t i = 0; i < vd.size(); i++) {
  47.      if(vd[i].flags & VERTEX_UV) {
  48.         objfile << "# UV BUFFER " << i << endl;
  49.         for(size_t j = 0; j < vd[i].elem; j++)
  50.             objfile << "vt " << vd[i].data[j].tu << " " << vd[i].data[j].tv << endl;
  51.        }
  52.     }
  53.  
  54.  // output faces
  55.  for(size_t i = 0; i < fd.size(); i++)
  56.     {
  57.      objfile << "# INDEX BUFFER " << i << endl;
  58.      objfile << "g " << fd[i].name.c_str() << endl;
  59.      objfile << "usemtl " << fd[i].name.c_str() << endl;
  60.  
  61.      // set vertex buffer reference index
  62.      uint32 vertex_buffer_index = fd[i].reference;
  63.      if(!(vertex_buffer_index < offset_list.size())) return error("OBJ EXPORT: Invalid vertex buffer reference.");
  64.  
  65.      // set vertex buffer properties
  66.      bool has_vertex = (vd[vertex_buffer_index].flags & VERTEX_POSITION) != 0;
  67.      bool has_normal = (vd[vertex_buffer_index].flags & VERTEX_NORMAL) != 0;
  68.      bool has_texmap = (vd[vertex_buffer_index].flags & VERTEX_UV) != 0;
  69.  
  70.      // set base vertex
  71.      uint32 base_vertex = offset_list[vertex_buffer_index].vertex_base;
  72.      uint32 base_normal = offset_list[vertex_buffer_index].normal_base;
  73.      uint32 base_texmap = offset_list[vertex_buffer_index].texmap_base;
  74.  
  75.      // tri-strips
  76.      if(fd[i].type == FACE_TYPE_TRISTRIP)
  77.        {
  78.         // validate
  79.         if(fd[i].elem < 3) return error("OBJ EXPORT: Tri-strips require at least three points.");
  80.  
  81.         if(fd[i].format == FACE_FORMAT_UINT_16)
  82.           {
  83.            // first triangle
  84.            const uint16* data = reinterpret_cast<uint16*>(fd[i].data.get());
  85.            uint32 va = base_vertex + data[0] + 1;
  86.            uint32 vb = base_vertex + data[1] + 1;
  87.            uint32 vc = base_vertex + data[2] + 1;
  88.            uint32 na = base_normal + data[0] + 1;
  89.            uint32 nb = base_normal + data[1] + 1;
  90.            uint32 nc = base_normal + data[2] + 1;
  91.            uint32 ta = base_texmap + data[0] + 1;
  92.            uint32 tb = base_texmap + data[1] + 1;
  93.            uint32 tc = base_texmap + data[2] + 1;
  94.  
  95.            // first triangle (draw only if not degenerate)
  96.            if(!(va == vb || va == vc || vb == vc)) {
  97.               if(!has_normal && !has_texmap) objfile << "f " << va << " " << vb << " " << vc << endl;
  98.               else if(!has_normal && has_texmap) objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
  99.               else if(!has_texmap && has_normal) objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
  100.               else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
  101.              }
  102.  
  103.            // other triangles
  104.            for(size_t j = 3; j < fd[i].elem; j++)
  105.               {
  106.                // update position
  107.                va = vb;
  108.                vb = vc;
  109.                vc = base_vertex + data[j] + 1;
  110.  
  111.                // update normal
  112.                if(has_normal) {
  113.                   na = nb;
  114.                   nb = nc;
  115.                   nc = base_normal + data[j] + 1;
  116.                  }
  117.  
  118.                // update UV
  119.                if(has_texmap) {
  120.                   ta = tb;
  121.                   tb = tc;
  122.                   tc = base_texmap + data[j] + 1;
  123.                  }
  124.  
  125.                // skip degenerate triangles
  126.                if(va == vb || va == vc || vb == vc) continue;
  127.  
  128.                if(!has_normal && !has_texmap) {
  129.                   if(j % 2) objfile << "f " << va << " " << vc << " " << vb << endl;
  130.                   else objfile << "f " << va << " " << vb << " " << vc << endl;
  131.                  }
  132.                else if(!has_normal && has_texmap) {
  133.                   if(j % 2) objfile << "f " << va << "/" << ta << " " << vc << "/" << tc << " " << vb << "/" << tb << endl;
  134.                   else objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
  135.                  }
  136.                else if(has_normal && !has_texmap) {
  137.                   if(j % 2) objfile << "f " << va << "//" << na << " " << vc << "//" << nc << " " << vb << "//" << nb << endl;
  138.                   else objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
  139.                  }
  140.                else {
  141.                   if(j % 2) objfile << "f " << va << "/" << ta << "/" << na << " " << vc << "/" << tc << "/" << nc << " " << vb << "/" << tb << "/" << nb << endl;
  142.                   else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
  143.                  }
  144.               }
  145.           }
  146.         else if(fd[i].format == FACE_FORMAT_UINT_32)
  147.           {
  148.            // first triangle
  149.            const uint32* data = reinterpret_cast<uint32*>(fd[i].data.get());
  150.            uint32 va = base_vertex + data[0] + 1;
  151.            uint32 vb = base_vertex + data[1] + 1;
  152.            uint32 vc = base_vertex + data[2] + 1;
  153.            uint32 na = base_normal + data[0] + 1;
  154.            uint32 nb = base_normal + data[1] + 1;
  155.            uint32 nc = base_normal + data[2] + 1;
  156.            uint32 ta = base_texmap + data[0] + 1;
  157.            uint32 tb = base_texmap + data[1] + 1;
  158.            uint32 tc = base_texmap + data[2] + 1;
  159.            if(!has_normal && !has_texmap) objfile << "f " << va << " " << vb << " " << vc << endl;
  160.            else if(!has_normal && has_texmap) objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
  161.            else if(!has_texmap && has_normal) objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
  162.            else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
  163.  
  164.            // other triangles
  165.            for(size_t j = 3; j < fd[i].elem; j++)
  166.               {
  167.                va = vb;
  168.                vb = vc;
  169.                vc = base_vertex + data[j] + 1;
  170.  
  171.                if(has_normal) {
  172.                   na = nb;
  173.                   nb = nc;
  174.                   nc = base_normal + data[j] + 1;
  175.                  }
  176.                if(has_texmap) {
  177.                   ta = tb;
  178.                   tb = tc;
  179.                   tc = base_texmap + data[j] + 1;
  180.                  }
  181.  
  182.                if(!has_normal && !has_texmap) {
  183.                   if(j % 2) objfile << "f " << va << " " << vc << " " << vb << endl;
  184.                   else objfile << "f " << va << " " << vb << " " << vc << endl;
  185.                  }
  186.                else if(!has_normal && has_texmap) {
  187.                   if(j % 2) objfile << "f " << va << "/" << ta << " " << vc << "/" << tc << " " << vb << "/" << tb << endl;
  188.                   else objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
  189.                  }
  190.                else if(has_normal && !has_texmap) {
  191.                   if(j % 2) objfile << "f " << va << "//" << na << " " << vc << "//" << nc << " " << vb << "//" << nb << endl;
  192.                   else objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
  193.                  }
  194.                else {
  195.                   if(j % 2) objfile << "f " << va << "/" << ta << "/" << na << " " << vc << "/" << tc << "/" << nc << " " << vb << "/" << tb << "/" << nb << endl;
  196.                   else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
  197.                  }
  198.               }
  199.           }
  200.         else
  201.            return error("OBJ EXPORT: Invalid index buffer data format.");
  202.        }
  203.      // triangles
  204.      else if(fd[i].type == FACE_TYPE_TRIANGLES)
  205.        {
  206.         if(fd[i].format == FACE_FORMAT_UINT_16)
  207.           {
  208.            size_t n_triangles = fd[i].elem/3;
  209.            for(size_t j = 0; j < n_triangles; j++)
  210.               {
  211.                // base OBJ indices
  212.                const uint16* ib_data = reinterpret_cast<uint16*>(fd[i].data.get());
  213.                uint32 va = base_vertex + ib_data[(3*j + 0)] + 1;
  214.                uint32 vb = base_vertex + ib_data[(3*j + 1)] + 1;
  215.                uint32 vc = base_vertex + ib_data[(3*j + 2)] + 1;
  216.                uint32 na = base_normal + ib_data[(3*j + 0)] + 1;
  217.                uint32 nb = base_normal + ib_data[(3*j + 1)] + 1;
  218.                uint32 nc = base_normal + ib_data[(3*j + 2)] + 1;
  219.                uint32 ta = base_texmap + ib_data[(3*j + 0)] + 1;
  220.                uint32 tb = base_texmap + ib_data[(3*j + 1)] + 1;
  221.                uint32 tc = base_texmap + ib_data[(3*j + 2)] + 1;
  222.  
  223.                // write triangle
  224.                if(!has_normal && !has_texmap) objfile << "f " << va << " " << vb << " " << vc << endl;
  225.                else if(!has_normal && has_texmap) objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
  226.                else if(has_normal && !has_texmap) objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
  227.                else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
  228.               }
  229.           }
  230.         else if(fd[i].format == FACE_FORMAT_UINT_32)
  231.           {
  232.            size_t n_triangles = fd[i].elem/3;
  233.            for(size_t j = 0; j < n_triangles; j++)
  234.               {
  235.                // base OBJ indices
  236.                const uint32* ib_data = reinterpret_cast<uint32*>(fd[i].data.get());
  237.                uint32 va = base_vertex + ib_data[(3*j + 0)] + 1;
  238.                uint32 vb = base_vertex + ib_data[(3*j + 1)] + 1;
  239.                uint32 vc = base_vertex + ib_data[(3*j + 2)] + 1;
  240.                uint32 na = base_normal + ib_data[(3*j + 0)] + 1;
  241.                uint32 nb = base_normal + ib_data[(3*j + 1)] + 1;
  242.                uint32 nc = base_normal + ib_data[(3*j + 2)] + 1;
  243.                uint32 ta = base_texmap + ib_data[(3*j + 0)] + 1;
  244.                uint32 tb = base_texmap + ib_data[(3*j + 1)] + 1;
  245.                uint32 tc = base_texmap + ib_data[(3*j + 2)] + 1;
  246.  
  247.                // write triangle
  248.                if(!has_normal && !has_texmap) objfile << "f " << va << " " << vb << " " << vc << endl;
  249.                else if(!has_normal && has_texmap) objfile << "f " << va << "/" << ta << " " << vb << "/" << tb << " " << vc << "/" << tc << endl;
  250.                else if(has_normal && !has_texmap) objfile << "f " << va << "//" << na << " " << vb << "//" << nb << " " << vc << "//" << nc << endl;
  251.                else objfile << "f " << va << "/" << ta << "/" << na << " " << vb << "/" << tb << "/" << nb << " " << vc << "/" << tc << "/" << nc << endl;
  252.               }
  253.           }
  254.        }
  255.     }
  256.  
  257.  // create MTL file
  258.  stringstream mtlfilename;
  259.  mtlfilename << path << name << ".mtl" << ends;
  260.  ofstream mtlfile(mtlfilename.str().c_str());
  261.  if(!mtlfile) return error("OBJ EXPORT: Error creating material file.");
  262.  
  263.  // save materials
  264.  for(size_t i = 0; i < fd.size(); i++)
  265.     {
  266.      mtlfile << "newmtl " << fd[i].name.c_str() << endl;
  267.      mtlfile << "Ka 0 0 0" << endl;
  268.      mtlfile << "Kd 0.784314 0.784314 0.784314" << endl;
  269.      mtlfile << "Ks 0 0 0" << endl;
  270.      mtlfile << "Ni 1" << endl;
  271.      mtlfile << "Ns 400" << endl;
  272.      mtlfile << "Tf 1 1 1" << endl;
  273.      mtlfile << "d 1" << endl;
  274.      //if(fd[i].basemap.length()) mtlfile << "map_Ka " << fd[i].basemap << endl;
  275.      //if(fd[i].basemap.length()) mtlfile << "map_Kd " << fd[i].basemap << endl;
  276.      //if(fd[i].specmap.length()) mtlfile << "map_Ks " << fd[i].specmap << endl;
  277.      //if(fd[i].basemap.length()) mtlfile << "map_d  " << fd[i].basemap << endl;
  278.      mtlfile << endl;
  279.     }
  280.  
  281.  return true;
  282. }