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

  1. #include "xentax.h"
  2.  
  3. bool GeometryToDAE(const char* path, const char* name, const GEOMETRY& data, const MATERIAL_LIST& materials, const TEXTURE_LIST& textures, const SKELETON_LIST& sl)
  4. {
  5.  if(!path || !strlen(path)) return error("DAE EXPORT: Expecting pathname.");
  6.  if(!name || !strlen(name)) return error("DAE EXPORT: Expecting filename.");
  7.  if(!data.meshlist.size()) return error("DAE EXPORT: Expecting geometry.");
  8.  
  9.  // create DAE file
  10.  stringstream ss;
  11.  ss << path << name << ".dae";
  12.  ofstream ofile(ss.str().c_str());
  13.  if(!ofile) return error("DAE EXPORT: Error creating output file."); 
  14.  
  15.  // save <collada>
  16.  ofile << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << endl;
  17.  ofile << "<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">" << endl;
  18.  ofile << endl;
  19.  
  20.  // save <asset>
  21.  ofile << " <!-- ASSET -->" << endl;
  22.  ofile << " <asset>" << endl;
  23.  ofile << "  <created>2012-01-01T21:00:00Z</created>" << endl;
  24.  ofile << "  <modified>2012-01-01T21:00:00Z</modified>" << endl;
  25.  ofile << "  <up_axis>Z_UP</up_axis>" << endl;
  26.  ofile << " </asset>" << endl;
  27.  ofile << endl;
  28.  
  29.  // save <library_images>
  30.  if(textures.size())
  31.    {
  32.     ofile << " <!-- LIBRARY_IMAGES -->" << endl;
  33.     ofile << " <library_images>" << endl;
  34.     for(size_t i = 0; i < textures.size(); i++) {
  35.         ofile << "  <image id=\"" << textures[i].id << "\">" << endl;
  36.         ofile << "   <init_from>" << textures[i].filename << "</init_from>" << endl;
  37.         ofile << "  </image>" << endl;
  38.        }
  39.     ofile << " </library_images>" << endl;
  40.     ofile << endl;
  41.    }
  42.  
  43.  // save <library_effects>
  44.  ofile << " <!-- LIBRARY_EFFECTS -->" << endl;
  45.  ofile << " <library_effects>" << endl;
  46.  for(size_t i = 0; i < materials.size(); i++)
  47.     {
  48.      stringstream e_id; // effect
  49.      stringstream s_id; // surface
  50.      stringstream o_id; // options
  51.      e_id << "effects_" << setfill('0') << setw(3) << i;
  52.      s_id << "surface_" << setfill('0') << setw(3) << i;
  53.      o_id << "options_" << setfill('0') << setw(3) << i;
  54.  
  55.      ofile << "  <effect id=\"" << e_id.str() << "\">" << endl;
  56.      ofile << "   <profile_COMMON>" << endl;
  57.      if(materials[i].basemap != 0xFFFFFFFF)
  58.        {
  59.         ofile << "    <technique sid=\"common\">" << endl;
  60.         ofile << "     <newparam sid=\"" << s_id.str() << "\">" << endl;
  61.         ofile << "      <surface type=\"2D\">" << endl;
  62.         ofile << "       <init_from>" << textures[materials[i].basemap].id << "</init_from>" << endl;
  63.         ofile << "       <format>A8R8G8B8</format>" << endl;
  64.         ofile << "      </surface>" << endl;
  65.         ofile << "     </newparam>" << endl;
  66.         ofile << "     <newparam sid=\"" << o_id.str() << "\">" << endl;
  67.         ofile << "      <sampler2D>" << endl;
  68.         ofile << "       <source>" << s_id.str() << "</source>" << endl;
  69.         ofile << "       <minfilter>LINEAR_MIPMAP_LINEAR</minfilter>" << endl;
  70.         ofile << "       <magfilter>LINEAR</magfilter>" << endl;
  71.         ofile << "      </sampler2D>" << endl;
  72.         ofile << "     </newparam>" << endl;
  73.         ofile << "     <lambert>" << endl;
  74.         ofile << "      <diffuse>" << endl;
  75.         ofile << "       <texture texture=\"" << o_id.str() << "\" texcoord=\"TEX0\" />" << endl;
  76.         ofile << "      </diffuse>" << endl;
  77.         ofile << "     </lambert>" << endl;
  78.         ofile << "    </technique>" << endl;
  79.        }
  80.      ofile << "   </profile_COMMON>" << endl;
  81.      ofile << "  </effect>" << endl;
  82.     }
  83.  ofile << " </library_effects>" << endl;
  84.  ofile << endl;
  85.  
  86.  // save <library_materials>
  87.  ofile << " <!-- LIBRARY_MATERIALS -->" << endl;
  88.  ofile << " <library_materials>" << endl;
  89.  for(size_t i = 0; i < materials.size(); i++) {
  90.      ofile << "  <material id=\"" << materials[i].id << "\">" << endl;
  91.      ofile << "   <instance_effect url=\"#effects_" << setfill('0') << setw(3) << i << "\" />" << endl;
  92.      ofile << "  </material>" << endl;
  93.     }
  94.  ofile << " </library_materials>" << endl;
  95.  ofile << endl;
  96.  
  97.  // save <library_geometries>
  98.  ofile << " <!-- LIBRARY_GEOMETRIES -->" << endl;
  99.  ofile << " <library_geometries>" << endl;
  100.  ofile << "  <geometry id=\"" << data.id << "\" name=\"" << data.name << "\">" << endl;
  101.  ofile << "   <mesh>" << endl;
  102.  
  103.  // for each mesh
  104.  for(size_t mesh_index = 0; mesh_index < data.meshlist.size(); mesh_index++)
  105.     {
  106.      // get vertices
  107.      VTX_BUFFER& vertices = data.meshlist[mesh_index]->vertices;
  108.      size_t n_vertices = vertices.elem;
  109.  
  110.      // get surfaces
  111.      deque<IDX_BUFFER>& surfaces = data.meshlist[mesh_index]->surfaces;
  112.      size_t n_surfaces = surfaces.size();
  113.  
  114.      // get properties
  115.      bool has_vertex = (vertices.flags & VERTEX_POSITION) != 0;
  116.      bool has_normal = (vertices.flags & VERTEX_NORMAL) != 0;
  117.      bool has_texmap = (vertices.flags & VERTEX_UV) != 0;
  118.  
  119.      // vertex data identifiers
  120.      stringstream pid; pid << data.id << "_position";
  121.      stringstream nid; nid << data.id << "_normal";
  122.      stringstream tid; tid << data.id << "_uv";
  123.      stringstream vid; vid << data.id << "_vertices";
  124.      
  125.      // save <source> (positions)
  126.      if(has_vertex) {
  127.         size_t n_values = n_vertices*3;
  128.         ofile << "    <source id=\"" << pid.str() << "\" name=\"" << pid.str() << "\">" << endl;
  129.         ofile << "     <float_array id=\"" << pid.str() << "_array\" name=\"" << pid.str() << "_array\" count=\"" << n_values << "\">" << endl;
  130.         for(size_t i = 0; i < n_vertices; i++) ofile << "      " << vertices.data[i].vx << " " << vertices.data[i].vy << " " << vertices.data[i].vz << endl;
  131.         ofile << "     </float_array>" << endl;
  132.         ofile << "     <technique_common>" << endl;
  133.         ofile << "      <accessor source=\"#" << pid.str() << "_array\" count=\"" << n_vertices << "\" stride=\"3\">" << endl;
  134.         ofile << "       <param name=\"X\" type=\"float\" />" << endl;
  135.         ofile << "       <param name=\"Y\" type=\"float\" />" << endl;
  136.         ofile << "       <param name=\"Z\" type=\"float\" />" << endl;
  137.         ofile << "      </accessor>" << endl;
  138.         ofile << "     </technique_common>" << endl;
  139.         ofile << "    </source>" << endl;
  140.        }
  141.  
  142.      // save <source> (normals)
  143.      if(has_normal) {
  144.         size_t n_values = n_vertices*3;
  145.         ofile << "    <source id=\"" << nid.str() << "\" name=\"" << nid.str() << "\">" << endl;
  146.         ofile << "     <float_array id=\"" << nid.str() << "_array\" name=\"" << nid.str() << "_array\" count=\"" << n_values << "\">" << endl;
  147.         for(size_t i = 0; i < n_vertices; i++) ofile << "      " << vertices.data[i].nx << " " << vertices.data[i].ny << " " << vertices.data[i].nz << endl;
  148.         ofile << "     </float_array>" << endl;
  149.         ofile << "     <technique_common>" << endl;
  150.         ofile << "      <accessor source=\"#" << nid.str() << "_array\" count=\"" << n_vertices << "\" stride=\"3\">" << endl;
  151.         ofile << "       <param name=\"X\" type=\"float\" />" << endl;
  152.         ofile << "       <param name=\"Y\" type=\"float\" />" << endl;
  153.         ofile << "       <param name=\"Z\" type=\"float\" />" << endl;
  154.         ofile << "      </accessor>" << endl;
  155.         ofile << "     </technique_common>" << endl;
  156.         ofile << "    </source>" << endl;
  157.        }
  158.  
  159.      // save <source> (UV)
  160.      if(has_texmap) {
  161.         size_t n_values = n_vertices*2;
  162.         ofile << "    <source id=\"" << tid.str() << "\" name=\"" << tid.str() << "\">" << endl;
  163.         ofile << "     <float_array id=\"" << tid.str() << "_array\" name=\"" << tid.str() << "_array\" count=\"" << n_values << "\">" << endl;
  164.         for(size_t i = 0; i < n_vertices; i++) ofile << "      " << vertices.data[i].tu << " " << vertices.data[i].tv << endl;
  165.         ofile << "     </float_array>" << endl;
  166.         ofile << "     <technique_common>" << endl;
  167.         ofile << "      <accessor source=\"#" << tid.str() << "_array\" count=\"" << n_vertices << "\" stride=\"2\">" << endl;
  168.         ofile << "       <param name=\"S\" type=\"float\" />" << endl;
  169.         ofile << "       <param name=\"T\" type=\"float\" />" << endl;
  170.         ofile << "      </accessor>" << endl;
  171.         ofile << "     </technique_common>" << endl;
  172.         ofile << "    </source>" << endl;
  173.        }
  174.  
  175.      // save <vertices>
  176.      if(has_vertex) {
  177.         ofile << "    <vertices id=\"" << vid.str() << "\">" << endl;
  178.         ofile << "     <input semantic=\"POSITION\" source=\"#" << pid.str() << "\" />" << endl;
  179.         ofile << "    </vertices>" << endl;
  180.        }
  181.  
  182.      // save <polygons>
  183.      for(size_t i = 0; i < surfaces.size(); i++)
  184.         {
  185.          unsigned char type = surfaces[i].type;
  186.          unsigned char format = surfaces[i].format;
  187.  
  188.          // material index
  189.          uint32 material_index = surfaces[i].material;
  190.          if(!(material_index < materials.size())) return error("DAE EXPORT: Material index out of range.");
  191.          string material_id = materials[material_index].id;
  192.  
  193.          if(type == FACE_TYPE_TRIANGLES)
  194.            {
  195.             // begin
  196.             size_t n_triangles = surfaces[i].elem/3;
  197.             ofile << "    <triangles count=\"" << n_triangles << "\" material=\"" << material_id << "\">" << endl;
  198.  
  199.             // position + normals + texture
  200.             if(has_vertex && has_normal && has_texmap) {
  201.                ofile << "     <input semantic=\"VERTEX\" source=\"#" << vid.str() << "\" offset=\"0\" />" << endl;
  202.                ofile << "     <input semantic=\"NORMAL\" source=\"#" << nid.str() << "\" offset=\"1\" />" << endl;
  203.                ofile << "     <input semantic=\"TEXCOORD\" source=\"#" << tid.str() << "\" offset=\"2\" />" << endl;
  204.                ofile << "     <p>" << endl;
  205.  
  206.                if(format == FACE_FORMAT_UINT_08) {
  207.                   uint08* data = reinterpret_cast<uint08*>(surfaces[i].data.get());
  208.                   size_t curr = 0;
  209.                   for(size_t j = 0; j < n_triangles; j++) {
  210.                       size_t a = data[curr++];
  211.                       size_t b = data[curr++];
  212.                       size_t c = data[curr++];
  213.                       ofile << "     " << a << " " << a << " " <<  a << " " << b << " " << b << " " << b << " " << c << " " << c << " " << c << endl;
  214.                      }
  215.                  }
  216.                else if(format == FACE_FORMAT_UINT_16) {
  217.                   uint16* data = reinterpret_cast<uint16*>(surfaces[i].data.get());
  218.                   size_t curr = 0;
  219.                   for(size_t j = 0; j < n_triangles; j++) {
  220.                       size_t a = data[curr++];
  221.                       size_t b = data[curr++];
  222.                       size_t c = data[curr++];
  223.                       ofile << "     " << a << " " << a << " " << a << " " << b << " " << b << " " << b << " " << c << " " << c << " " << c << endl;
  224.                      }
  225.                  }
  226.                else if(format == FACE_FORMAT_UINT_32) {
  227.                   uint32* data = reinterpret_cast<uint32*>(surfaces[i].data.get());
  228.                   size_t curr = 0;
  229.                   for(size_t j = 0; j < n_triangles; j++) {
  230.                       size_t a = data[curr++];
  231.                       size_t b = data[curr++];
  232.                       size_t c = data[curr++];
  233.                       ofile << "     " << a << " " << a << " " << a << " " << b << " " << b << " " << b << " " << c << " " << c << " " << c << endl;
  234.                      }
  235.                  }
  236.  
  237.                ofile << "</p>" << endl;
  238.               }
  239.             // position
  240.             else if(has_vertex && !has_normal && !has_texmap) {
  241.                ofile << "     <input semantic=\"VERTEX\" source=\"#" << vid.str() << "\" offset=\"0\" />" << endl;
  242.               }
  243.             // position + texture
  244.             else if(!has_normal && has_texmap)
  245.               {
  246.                ofile << "     <input semantic=\"VERTEX\" source=\"#" << vid.str() << "\" offset=\"0\" />" << endl;
  247.                ofile << "     <input semantic=\"TEXCOORD\" source=\"#" << tid.str() << "\" offset=\"1\" />" << endl;
  248.                ofile << "     <p>" << endl;
  249.  
  250.                if(format == FACE_FORMAT_UINT_08) {
  251.                   uint08* data = reinterpret_cast<uint08*>(surfaces[i].data.get());
  252.                   size_t curr = 0;
  253.                   for(size_t j = 0; j < n_triangles; j++) {
  254.                       size_t a = data[curr++];
  255.                       size_t b = data[curr++];
  256.                       size_t c = data[curr++];
  257.                       ofile << "     " << a << " " << a << " " << b << " " << b << " " << c << " " << c << endl;
  258.                      }
  259.                  }
  260.                else if(format == FACE_FORMAT_UINT_16) {
  261.                   uint16* data = reinterpret_cast<uint16*>(surfaces[i].data.get());
  262.                   size_t curr = 0;
  263.                   for(size_t j = 0; j < n_triangles; j++) {
  264.                       size_t a = data[curr++];
  265.                       size_t b = data[curr++];
  266.                       size_t c = data[curr++];
  267.                       ofile << "     " << a << " " << a << " " << b << " " << b << " " << c << " " << c << endl;
  268.                      }
  269.                  }
  270.                else if(format == FACE_FORMAT_UINT_32) {
  271.                   uint32* data = reinterpret_cast<uint32*>(surfaces[i].data.get());
  272.                   size_t curr = 0;
  273.                   for(size_t j = 0; j < n_triangles; j++) {
  274.                       size_t a = data[curr++];
  275.                       size_t b = data[curr++];
  276.                       size_t c = data[curr++];
  277.                       ofile << "     " << a << " " << a << " " << b << " " << b << " " << c << " " << c << endl;
  278.                      }
  279.                  }
  280.  
  281.                ofile << "     </p>" << endl;
  282.               }
  283.             // position + normals
  284.             else if(has_normal && !has_texmap)
  285.               {
  286.                ofile << "     <input semantic=\"VERTEX\" source=\"#" << vid.str() << "\" offset=\"0\" />" << endl;
  287.                ofile << "     <input semantic=\"NORMAL\" source=\"#" << nid.str() << "\" offset=\"1\" />" << endl;
  288.                ofile << "     <p>" << endl;
  289.  
  290.                if(format == FACE_FORMAT_UINT_08) {
  291.                   uint08* data = reinterpret_cast<uint08*>(surfaces[i].data.get());
  292.                   size_t curr = 0;
  293.                   for(size_t j = 0; j < n_triangles; j++) {
  294.                       size_t a = data[curr++];
  295.                       size_t b = data[curr++];
  296.                       size_t c = data[curr++];
  297.                       ofile << "     " << a << " " << a << " " << b << " " << b << " " << c << " " << c << endl;
  298.                      }
  299.                  }
  300.                else if(format == FACE_FORMAT_UINT_16) {
  301.                   uint16* data = reinterpret_cast<uint16*>(surfaces[i].data.get());
  302.                   size_t curr = 0;
  303.                   for(size_t j = 0; j < n_triangles; j++) {
  304.                       size_t a = data[curr++];
  305.                       size_t b = data[curr++];
  306.                       size_t c = data[curr++];
  307.                       ofile << "     " << a << " " << a << " " << b << " " << b << " " << c << " " << c << endl;
  308.                      }
  309.                  }
  310.                else if(format == FACE_FORMAT_UINT_32) {
  311.                   uint32* data = reinterpret_cast<uint32*>(surfaces[i].data.get());
  312.                   size_t curr = 0;
  313.                   for(size_t j = 0; j < n_triangles; j++) {
  314.                       size_t a = data[curr++];
  315.                       size_t b = data[curr++];
  316.                       size_t c = data[curr++];
  317.                       ofile << "     " << a << " " << a << " " << b << " " << b << " " << c << " " << c << endl;
  318.                      }
  319.                  }
  320.  
  321.                ofile << "     </p>" << endl;
  322.               }
  323.             else return error("DAE EXPORT: Invalid input semantics.");
  324.  
  325.             // end
  326.             ofile << "    </triangles>" << endl;
  327.            }
  328.          else if(type == FACE_TYPE_TRISTRIP)
  329.            {
  330.            }
  331.          else if(type == FACE_TYPE_TRISTRIPCUT)
  332.            {
  333.            }
  334.          else
  335.             return error("DAE EXPORT: Invalid face type.");
  336.         }
  337.     }
  338.  
  339.  // terminate <library_geometries>
  340.  ofile << "   </mesh>" << endl;
  341.  ofile << "  </geometry>" << endl;
  342.  ofile << " </library_geometries>" << endl;
  343.  ofile << endl;
  344.  
  345.  // skeleton and weights
  346.  bool has_skeletons = (sl.size() > 0);
  347.  if(has_skeletons)
  348.    {
  349.     // save <library_nodes>
  350.     ofile << " <!-- LIBRARY_NODES -->" << endl;
  351.     ofile << " <library_nodes>" << endl;
  352.     for(size_t i = 0; i < sl.size(); i++) {
  353.         stringstream ss;
  354.         sl[i].tree.PrintColladaNodeHeirarchy(sl[i].id, ss);
  355.         ofile << ss.str();
  356.        }
  357.     ofile << " </library_nodes>" << endl;
  358.     ofile << endl;
  359.  
  360.     // save <library_controllers>
  361.     ofile << " <!-- LIBRARY_CONTROLLERS -->" << endl;
  362.     ofile << " <library_controllers>" << endl;
  363.     for(size_t i = 0; i < data.meshlist.size(); i++)
  364.        {
  365.         ofile << "  <controller id=\"" << data.id << "_controller\">" << endl;
  366.         ofile << "   <skin source=\"#" << data.id << "\">" << endl;
  367.         for(size_t j = 0; j < sl.size(); j++) {
  368.             stringstream ss;
  369.             sl[j].tree.PrintColladaJoints(sl[j].id, ss);
  370.             ofile << ss.str();
  371.            }
  372.         for(size_t j = 0; j < sl.size(); j++) {
  373.             stringstream ss;
  374.             sl[j].tree.PrintColladaBindMatrices(sl[j].id, ss);
  375.             ofile << ss.str();
  376.            }
  377.         // vertex weights
  378.         if(data.meshlist[i]->vertices.flags & VERTEX_WEIGHTS)
  379.           {
  380.            size_t n_weights = 4*data.meshlist[i]->vertices.elem;
  381.            ofile << "    <source id=\"" << data.id << "_weights\">" << endl;
  382.            ofile << "     <float_array count=\"" << n_weights << "\">" << endl;
  383.            for(size_t j = 0; j < data.meshlist[i]->vertices.elem; j++) {
  384.                float w1 = data.meshlist[i]->vertices.data[j].w1;
  385.                float w2 = data.meshlist[i]->vertices.data[j].w2;
  386.                float w3 = data.meshlist[i]->vertices.data[j].w3;
  387.                float w4 = data.meshlist[i]->vertices.data[j].w4;
  388.                ofile << "      " << w1 << " " << w2 << " " << w3 << " " << w4 << endl;
  389.               }
  390.            ofile << "     </float_array>" << endl;
  391.            ofile << "     <technique_common>" << endl;
  392.            ofile << "      <acessor source=\"#" << data.id << "_weights\" count=\"" << n_weights << "\" stride=\"1\">" << endl;
  393.            ofile << "       <param name=\"WEIGHT\" type=\"float\" />" << endl;
  394.            ofile << "      </acessor>" << endl;
  395.            ofile << "     </technique_common>" << endl;
  396.            ofile << "    </source>" << endl;
  397.           }
  398.         // joints
  399.         for(size_t j = 0; j < sl.size(); j++) {
  400.             ofile << "    <joints>" << endl;
  401.             ofile << "     <input semantic=\"JOINT\" source=\"#" << sl[j].id << "_joints\" />" << endl;
  402.             ofile << "     <input semantic=\"INV_BIND_MATRIX\" source=\"#" << sl[j].id << "_matrices\" />" << endl;
  403.             ofile << "    </joints>" << endl;
  404.            }
  405.         // vertex weights
  406.         for(size_t j = 0; j < sl.size(); j++) {
  407.             ofile << "    <vertex_weights count=\"" << data.meshlist[i]->vertices.elem << "\">" << endl;
  408.             ofile << "     <input semantic=\"JOINT\" source=\"#" << sl[j].id << "_joints\"/>" << endl;
  409.             ofile << "     <input semantic=\"WEIGHT\" source=\"#" << data.id << "_weights\"/>" << endl;
  410.             ofile << "     <vcount>";
  411.             for(size_t k = 0; k < data.meshlist[i]->vertices.elem - 1; k++) ofile << "4 ";
  412.             ofile << 4 << "</vcount>" << endl;
  413.             ofile << "     <v>" << endl;
  414.             for(size_t k = 0; k < data.meshlist[i]->vertices.elem; k++) {
  415.                 size_t weight_offset = 4*k;
  416.                 ofile << "      " <<
  417.                          data.meshlist[i]->vertices.data[k].b1 << " " << weight_offset + 0 << " " <<
  418.                          data.meshlist[i]->vertices.data[k].b2 << " " << weight_offset + 1 << " " <<
  419.                          data.meshlist[i]->vertices.data[k].b3 << " " << weight_offset + 2 << " " <<
  420.                          data.meshlist[i]->vertices.data[k].b4 << " " << weight_offset + 3 << endl;
  421.                }
  422.             ofile << "     </v>" << endl;
  423.             ofile << "    </vertex_weights>" << endl;
  424.            }
  425.         ofile << "   </skin>" << endl;
  426.         ofile << "  </controller>" << endl;
  427.        }
  428.     ofile << " </library_controllers>" << endl;
  429.     ofile << endl;
  430.    }
  431.  
  432.  // save <scene>
  433.  ofile << " <!-- SCENE -->" << endl;
  434.  ofile << " <library_visual_scenes>" << endl;
  435.  ofile << "  <visual_scene id=\"DefaultScene\">" << endl;
  436.  ofile << "   <node id=\"DefaultNode\" name=\"DefaultNode\">" << endl;
  437.  ofile << "    <rotate>1 0 0 90</rotate>" << endl;
  438.  ofile << "    <instance_geometry url=\"#" << data.id << "\">" << endl;
  439.  for(size_t i = 0; i < materials.size(); i++)
  440.     {
  441.      ofile << "     <bind_material>" << endl;
  442.      ofile << "      <technique_common>" << endl;
  443.      ofile << "       <instance_material symbol=\"" << materials[i].id << "\" target=\"#" << materials[i].id << "\">" << endl;
  444.      ofile << "        <bind_vertex_input semantic=\"TEX0\" input_semantic=\"TEXCOORD\" input_set=\"0\" />" << endl;
  445.      ofile << "       </instance_material>" << endl;
  446.      ofile << "      </technique_common>" << endl;
  447.      ofile << "     </bind_material>" << endl;
  448.     }
  449.  ofile << "    </instance_geometry>" << endl;
  450.  ofile << "   </node>" << endl;
  451.  
  452.  // create skeleton instances
  453.  for(size_t i = 0; i < sl.size(); i++)
  454.     {
  455.      // create skeleton instance (refers to a list of node names)
  456.      ofile << "   <!-- SKELETON INSTANCE -->" << endl;
  457.      ofile << "   <node id=\"" << sl[i].id << "_instance\">" << endl;
  458.      ofile << "    <rotate>1 0 0 90</rotate>" << endl;
  459.      ofile << "    <instance_node url=\"#" << sl[i].id << "\" />" << endl;
  460.      ofile << "   </node>" << endl;
  461.      // create skeleton controller (must define which skeleton and which controller to use)
  462.      ofile << "   <!-- SKELETON CONTROLLER INSTANCE -->" << endl;
  463.      ofile << "   <node>" << endl;
  464.      ofile << "    <instance_controller url=\"#" << data.id << "_controller\">" << endl;
  465.      ofile << "     <skeleton>#" << sl[i].id << "_instance</skeleton>" << endl;
  466.      ofile << "    </instance_controller>" << endl;
  467.      ofile << "   </node>" << endl;
  468.     }
  469.  ofile << "  </visual_scene>" << endl;
  470.  ofile << " </library_visual_scenes>" << endl;
  471.  ofile << endl;
  472.  
  473.  // save <scene>
  474.  ofile << " <!-- SCENE -->" << endl;
  475.  ofile << " <scene>" << endl;
  476.  ofile << "  <instance_visual_scene url=\"#DefaultScene\"></instance_visual_scene>" << endl;
  477.  ofile << " </scene>" << endl;
  478.  ofile << endl;
  479.  
  480.  // finish <collada>
  481.  ofile << "</COLLADA>";
  482.  return true;
  483. }