/*
 * Copyright (C) 2012 Open Source Robotics Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <tinyxml.h>
#include <boost/filesystem.hpp>
#include <ignition/math/Vector3.hh>

#include "gazebo/common/Material.hh"
#include "gazebo/common/Mesh.hh"
#include "gazebo/common/Console.hh"
#include "gazebo/common/ColladaExporterPrivate.hh"
#include "gazebo/common/ColladaExporter.hh"

// snprintf is available since VS 2015
#if defined(_MSC_VER) && (_MSC_VER < 1900)
  #define snprintf _snprintf
#endif

using namespace gazebo;
using namespace common;

//////////////////////////////////////////////////
ColladaExporter::ColladaExporter()
: MeshExporter(), dataPtr(new ColladaExporterPrivate)
{
}

//////////////////////////////////////////////////
ColladaExporter::~ColladaExporter()
{
  delete this->dataPtr;
  this->dataPtr = 0;
}

//////////////////////////////////////////////////
void ColladaExporter::Export(const Mesh *_mesh, const std::string &_filename,
    bool _exportTextures)
{
  this->dataPtr->mesh = _mesh;
  this->dataPtr->materialCount = this->dataPtr->mesh->GetMaterialCount();
  this->dataPtr->subMeshCount = this->dataPtr->mesh->GetSubMeshCount();
  this->dataPtr->exportTextures = _exportTextures;

  // File name and path
  unsigned int beginFilename = _filename.rfind("/")+1;

  this->dataPtr->path = _filename.substr(0, beginFilename);
  this->dataPtr->filename = _filename.substr(beginFilename);

  if (this->dataPtr->materialCount != 0 &&
      this->dataPtr->materialCount != this->dataPtr->subMeshCount)
  {
    gzwarn << "Material count [" << this->dataPtr->materialCount <<
        "] different from submesh count [" <<
        this->dataPtr->subMeshCount << "]\n";
  }

  // Collada file
  TiXmlDocument xmlDoc;

  // XML declaration
  TiXmlDeclaration *declarationXml = new TiXmlDeclaration("1.0", "utf-8", "");
  xmlDoc.LinkEndChild(declarationXml);

  // Collada element
  TiXmlElement *colladaXml = new TiXmlElement("COLLADA");
  xmlDoc.LinkEndChild(colladaXml);
  colladaXml->SetAttribute("version", "1.4.1");
  colladaXml->SetAttribute("xmlns",
      "http://www.collada.org/2005/11/COLLADASchema");

  // Asset element
  TiXmlElement *assetXml = new TiXmlElement("asset");
  this->ExportAsset(assetXml);
  colladaXml->LinkEndChild(assetXml);

  // Library geometries element
  TiXmlElement *libraryGeometriesXml = new TiXmlElement("library_geometries");
  this->ExportGeometries(libraryGeometriesXml);
  colladaXml->LinkEndChild(libraryGeometriesXml);

  if (this->dataPtr->materialCount != 0)
  {
    // Library images element
    TiXmlElement *libraryImagesXml = new TiXmlElement("library_images");
    int imageCount = this->ExportImages(libraryImagesXml);
    if (imageCount != 0)
    {
      colladaXml->LinkEndChild(libraryImagesXml);
    }

    // Library materials element
    TiXmlElement *libraryMaterialsXml = new TiXmlElement("library_materials");
    this->ExportMaterials(libraryMaterialsXml);
    colladaXml->LinkEndChild(libraryMaterialsXml);

    // Library effects element
    TiXmlElement *libraryEffectsXml = new TiXmlElement("library_effects");
    this->ExportEffects(libraryEffectsXml);
    colladaXml->LinkEndChild(libraryEffectsXml);
  }

  // Library visual scenes element
  TiXmlElement *libraryVisualScenesXml =
      new TiXmlElement("library_visual_scenes");
  this->ExportVisualScenes(libraryVisualScenesXml);
  colladaXml->LinkEndChild(libraryVisualScenesXml);

  // Scene element
  TiXmlElement *sceneXml = new TiXmlElement("scene");
  this->ExportScene(sceneXml);
  colladaXml->LinkEndChild(sceneXml);

  // Save file
  if (this->dataPtr->exportTextures)
  {
    boost::filesystem::create_directories(
        boost::filesystem::path(this->dataPtr->path + this->dataPtr->filename +
        std::string("/meshes/")));
    xmlDoc.SaveFile(this->dataPtr->path + this->dataPtr->filename +
        std::string("/meshes/") + this->dataPtr->filename +
        std::string(".dae"));
  }
  else
  {
    xmlDoc.SaveFile(this->dataPtr->path + this->dataPtr->filename +
        std::string(".dae"));
  }
}

//////////////////////////////////////////////////
void ColladaExporter::ExportAsset(TiXmlElement *_assetXml)
{
  TiXmlElement *unitXml = new TiXmlElement("unit");
  unitXml->SetAttribute("meter", "1");
  unitXml->SetAttribute("name", "meter");
  _assetXml->LinkEndChild(unitXml);

  TiXmlElement *upAxisXml = new TiXmlElement("up_axis");
  upAxisXml->LinkEndChild(new TiXmlText("Z_UP"));
  _assetXml->LinkEndChild(upAxisXml);
}

//////////////////////////////////////////////////
void ColladaExporter::ExportGeometrySource(
    const gazebo::common::SubMesh *_subMesh,
    TiXmlElement *_meshXml, GeometryType _type, const char *_meshID)
{
  char sourceId[100], sourceArrayId[100];
  std::ostringstream fillData;
  fillData.precision(8);
  fillData << std::fixed;
  int stride;
  unsigned int count = 0;

  if (_type == POSITION)
  {
    snprintf(sourceId, sizeof(sourceId), "%s-Positions", _meshID);
    count = _subMesh->GetVertexCount();
    stride = 3;
    ignition::math::Vector3d vertex;
    for (unsigned int i = 0; i < count; ++i)
    {
      vertex = _subMesh->Vertex(i);
      fillData << vertex.X() << " " << vertex.Y() << " " << vertex.Z() << " ";
    }
  }
  if (_type == NORMAL)
  {
    snprintf(sourceId, sizeof(sourceId), "%s-Normals", _meshID);
    count = _subMesh->GetNormalCount();
    stride = 3;
    ignition::math::Vector3d normal;
    for (unsigned int i = 0; i < count; ++i)
    {
      normal = _subMesh->Normal(i);
      fillData << normal.X() << " " << normal.Y() << " " << normal.Z() << " ";
    }
  }
  if (_type == UVMAP)
  {
    snprintf(sourceId, sizeof(sourceId), "%s-UVMap", _meshID);
    count = _subMesh->GetVertexCount();
    stride = 2;
    ignition::math::Vector2d inTexCoord;
    for (unsigned int i = 0; i < count; ++i)
    {
      inTexCoord = _subMesh->TexCoord(i);
      fillData << inTexCoord.X() << " " << 1-inTexCoord.Y() << " ";
    }
  }
  TiXmlElement *sourceXml = new TiXmlElement("source");
  _meshXml->LinkEndChild(sourceXml);
  sourceXml->SetAttribute("id", sourceId);
  sourceXml->SetAttribute("name", sourceId);

  snprintf(sourceArrayId, sizeof(sourceArrayId), "%s-array", sourceId);
  TiXmlElement *floatArrayXml = new TiXmlElement("float_array");
  floatArrayXml->SetAttribute("count", count *stride);
  floatArrayXml->SetAttribute("id", sourceArrayId);
  floatArrayXml->LinkEndChild(new TiXmlText(fillData.str().c_str()));
  sourceXml->LinkEndChild(floatArrayXml);

  TiXmlElement *techniqueCommonXml = new TiXmlElement("technique_common");
  sourceXml->LinkEndChild(techniqueCommonXml);

  snprintf(sourceArrayId, sizeof(sourceArrayId), "#%s-array", sourceId);
  TiXmlElement *accessorXml = new TiXmlElement("accessor");
  accessorXml->SetAttribute("count", count);
  accessorXml->SetAttribute("source", sourceArrayId);
  accessorXml->SetAttribute("stride", stride);
  techniqueCommonXml->LinkEndChild(accessorXml);

  TiXmlElement *paramXml = new TiXmlElement("param");
  if (_type == POSITION || _type == NORMAL)
  {
    paramXml->SetAttribute("type", "float");
    paramXml->SetAttribute("name", "X");
    accessorXml->LinkEndChild(paramXml);

    paramXml = new TiXmlElement("param");
    paramXml->SetAttribute("type", "float");
    paramXml->SetAttribute("name", "Y");
    accessorXml->LinkEndChild(paramXml);

    paramXml = new TiXmlElement("param");
    paramXml->SetAttribute("type", "float");
    paramXml->SetAttribute("name", "Z");
    accessorXml->LinkEndChild(paramXml);
  }
  if (_type == UVMAP)
  {
    paramXml->SetAttribute("type", "float");
    paramXml->SetAttribute("name", "U");
    accessorXml->LinkEndChild(paramXml);

    paramXml = new TiXmlElement("param");
    paramXml->SetAttribute("type", "float");
    paramXml->SetAttribute("name", "V");
    accessorXml->LinkEndChild(paramXml);
  }
}

//////////////////////////////////////////////////
void ColladaExporter::ExportGeometries(TiXmlElement *_libraryGeometriesXml)
{
  for (unsigned int i = 0; i < this->dataPtr->subMeshCount; ++i)
  {
    char meshId[100], materialId[100];
    snprintf(meshId, sizeof(meshId), "mesh_%u", i);
    snprintf(materialId, sizeof(materialId), "material_%u", i);

    TiXmlElement *geometryXml = new TiXmlElement("geometry");
    geometryXml->SetAttribute("id", meshId);
    _libraryGeometriesXml->LinkEndChild(geometryXml);

    TiXmlElement *meshXml = new TiXmlElement("mesh");
    geometryXml->LinkEndChild(meshXml);

    const gazebo::common::SubMesh *subMesh =
        this->dataPtr->mesh->GetSubMesh(i);

    ExportGeometrySource(subMesh, meshXml, POSITION, meshId);
    ExportGeometrySource(subMesh, meshXml, NORMAL, meshId);
    if (subMesh->GetTexCoordCount() != 0)
    {
      ExportGeometrySource(subMesh, meshXml, UVMAP, meshId);
    }

    char attributeValue[100];

    TiXmlElement *verticesXml = new TiXmlElement("vertices");
    meshXml->LinkEndChild(verticesXml);
    snprintf(attributeValue, sizeof(attributeValue), "%s-Vertex", meshId);
    verticesXml->SetAttribute("id", attributeValue);
    verticesXml->SetAttribute("name", attributeValue);

    TiXmlElement *inputXml = new TiXmlElement("input");
    verticesXml->LinkEndChild(inputXml);
    inputXml->SetAttribute("semantic", "POSITION");
    snprintf(attributeValue, sizeof(attributeValue), "#%s-Positions", meshId);
    inputXml->SetAttribute("source", attributeValue);

    unsigned int indexCount = subMesh->GetIndexCount();

    TiXmlElement *trianglesXml = new TiXmlElement("triangles");
    meshXml->LinkEndChild(trianglesXml);
    trianglesXml->SetAttribute("count", indexCount/3);
    if (this->dataPtr->materialCount != 0)
    {
      trianglesXml->SetAttribute("material", materialId);
    }

    inputXml = new TiXmlElement("input");
    trianglesXml->LinkEndChild(inputXml);
    inputXml->SetAttribute("offset", 0);
    inputXml->SetAttribute("semantic", "VERTEX");
    snprintf(attributeValue, sizeof(attributeValue), "#%s-Vertex", meshId);
    inputXml->SetAttribute("source", attributeValue);

    inputXml = new TiXmlElement("input");
    trianglesXml->LinkEndChild(inputXml);
    inputXml->SetAttribute("offset", 1);
    inputXml->SetAttribute("semantic", "NORMAL");
    snprintf(attributeValue, sizeof(attributeValue), "#%s-Normals", meshId);
    inputXml->SetAttribute("source", attributeValue);

    if (subMesh->GetTexCoordCount() != 0)
    {
      inputXml = new TiXmlElement("input");
      trianglesXml->LinkEndChild(inputXml);
      inputXml->SetAttribute("offset", 2);
      inputXml->SetAttribute("semantic", "TEXCOORD");
      snprintf(attributeValue, sizeof(attributeValue), "#%s-UVMap", meshId);
      inputXml->SetAttribute("source", attributeValue);
    }

    std::ostringstream fillData;
    for (unsigned int j = 0; j < indexCount; ++j)
    {
      fillData << subMesh->GetIndex(j) << " "
               << subMesh->GetIndex(j) << " ";
      if (subMesh->GetTexCoordCount() != 0)
      {
        fillData << subMesh->GetIndex(j) << " ";
      }
    }

    TiXmlElement *pXml = new TiXmlElement("p");
    trianglesXml->LinkEndChild(pXml);
    pXml->LinkEndChild(new TiXmlText(fillData.str().c_str()));
  }
}

//////////////////////////////////////////////////
int ColladaExporter::ExportImages(TiXmlElement *_libraryImagesXml)
{
  int imageCount = 0;
  for (unsigned int i = 0; i < this->dataPtr->materialCount; ++i)
  {
    const gazebo::common::Material *material =
        this->dataPtr->mesh->GetMaterial(i);
    std::string imageString = material->GetTextureImage();

    if (imageString.find("meshes/") != std::string::npos)
    {
      char id[100];
      snprintf(id, sizeof(id), "image_%u", i);

      TiXmlElement *imageXml = new TiXmlElement("image");
      imageXml->SetAttribute("id", id);
      _libraryImagesXml->LinkEndChild(imageXml);

      TiXmlElement *initFromXml = new TiXmlElement("init_from");
      initFromXml->LinkEndChild(new TiXmlText(
        imageString.substr(imageString.find("meshes/")+7)));
      imageXml->LinkEndChild(initFromXml);

      if (this->dataPtr->exportTextures)
      {
        boost::filesystem::create_directories(boost::filesystem::path(
            this->dataPtr->path + this->dataPtr->filename +
            "/materials/textures"));

        std::ifstream  src(imageString.c_str(), std::ios::binary);
        std::ofstream  dst((this->dataPtr->path + this->dataPtr->filename +
            "/materials/textures" + imageString.substr(
            imageString.rfind("/"))).c_str(), std::ios::binary);
        dst << src.rdbuf();
      }

      imageCount++;
    }
  }

  return imageCount;
}

//////////////////////////////////////////////////
void ColladaExporter::ExportMaterials(TiXmlElement *_libraryMaterialsXml)
{
  for (unsigned int i = 0; i < this->dataPtr->materialCount; ++i)
  {
    char id[100];
    snprintf(id, sizeof(id), "material_%u", i);

    TiXmlElement *materialXml = new TiXmlElement("material");
    materialXml->SetAttribute("id", id);
    _libraryMaterialsXml->LinkEndChild(materialXml);

    snprintf(id, sizeof(id), "#material_%u_fx", i);
    TiXmlElement *instanceEffectXml = new TiXmlElement("instance_effect");
    instanceEffectXml->SetAttribute("url", id);
    materialXml->LinkEndChild(instanceEffectXml);
  }
}

//////////////////////////////////////////////////
void ColladaExporter::ExportEffects(TiXmlElement *_libraryEffectsXml)
{
  for (unsigned int i = 0; i < this->dataPtr->materialCount; ++i)
  {
    char id[100];
    snprintf(id, sizeof(id), "material_%u_fx", i);

    TiXmlElement *effectXml = new TiXmlElement("effect");
    effectXml->SetAttribute("id", id);
    _libraryEffectsXml->LinkEndChild(effectXml);

    TiXmlElement *profileCommonXml = new TiXmlElement("profile_COMMON");
    effectXml->LinkEndChild(profileCommonXml);

    // Image
    const gazebo::common::Material *material =
        this->dataPtr->mesh->GetMaterial(i);
    std::string imageString = material->GetTextureImage();

    if (imageString.find("meshes/") != std::string::npos)
    {
      TiXmlElement *newParamXml = new TiXmlElement("newparam");
      snprintf(id, sizeof(id), "image_%u_surface", i);
      newParamXml->SetAttribute("sid", id);
      profileCommonXml->LinkEndChild(newParamXml);

      TiXmlElement *surfaceXml = new TiXmlElement("surface");
      surfaceXml->SetAttribute("type", "2D");
      newParamXml->LinkEndChild(surfaceXml);

      TiXmlElement *initFromXml = new TiXmlElement("init_from");
      snprintf(id, sizeof(id), "image_%u", i);
      initFromXml->LinkEndChild(new TiXmlText(id));
      surfaceXml->LinkEndChild(initFromXml);

      newParamXml = new TiXmlElement("newparam");
      snprintf(id, sizeof(id), "image_%u_sampler", i);
      newParamXml->SetAttribute("sid", id);
      profileCommonXml->LinkEndChild(newParamXml);

      TiXmlElement *sampler2dXml = new TiXmlElement("sampler2D");
      newParamXml->LinkEndChild(sampler2dXml);

      TiXmlElement *sourceXml = new TiXmlElement("source");
      snprintf(id, sizeof(id), "image_%u_surface", i);
      sourceXml->LinkEndChild(new TiXmlText(id));
      sampler2dXml->LinkEndChild(sourceXml);

      TiXmlElement *minFilterXml = new TiXmlElement("minfilter");
      minFilterXml->LinkEndChild(new TiXmlText("LINEAR"));
      sampler2dXml->LinkEndChild(minFilterXml);

      TiXmlElement *magFilterXml = new TiXmlElement("magfilter");
      magFilterXml->LinkEndChild(new TiXmlText("LINEAR"));
      sampler2dXml->LinkEndChild(magFilterXml);
    }

    TiXmlElement *techniqueXml = new TiXmlElement("technique");
    techniqueXml->SetAttribute("sid", "COMMON");
    profileCommonXml->LinkEndChild(techniqueXml);

    // gazebo::common::Material::ShadeMode shadeMode =
    //    material->GetShadeMode();

    // Using phong for now
    TiXmlElement *phongXml = new TiXmlElement("phong");
    techniqueXml->LinkEndChild(phongXml);

    // ambient
    unsigned int RGBAcolor = material->Ambient().AsRGBA();
    float r = ((RGBAcolor >> 24) & 0xFF) / 255.0f;
    float g = ((RGBAcolor >> 16) & 0xFF) / 255.0f;
    float b = ((RGBAcolor >> 8) & 0xFF) / 255.0f;
    float a = (RGBAcolor & 0xFF) / 255.0f;

    TiXmlElement *ambientXml = new TiXmlElement("ambient");
    phongXml->LinkEndChild(ambientXml);

    TiXmlElement *colorXml = new TiXmlElement("color");
    snprintf(id, sizeof(id), "%f %f %f %f", r, g, b, a);
    colorXml->LinkEndChild(new TiXmlText(id));
    ambientXml->LinkEndChild(colorXml);

    // emission
    RGBAcolor = material->Emissive().AsRGBA();
    r = ((RGBAcolor >> 24) & 0xFF) / 255.0f;
    g = ((RGBAcolor >> 16) & 0xFF) / 255.0f;
    b = ((RGBAcolor >> 8) & 0xFF) / 255.0f;
    a = (RGBAcolor & 0xFF) / 255.0f;

    TiXmlElement *emissionXml = new TiXmlElement("emission");
    phongXml->LinkEndChild(emissionXml);

    colorXml = new TiXmlElement("color");
    snprintf(id, sizeof(id), "%f %f %f %f", r, g, b, a);
    colorXml->LinkEndChild(new TiXmlText(id));
    emissionXml->LinkEndChild(colorXml);

    // diffuse
    TiXmlElement *diffuseXml = new TiXmlElement("diffuse");
    phongXml->LinkEndChild(diffuseXml);

    if (imageString.find("meshes/") != std::string::npos)
    {
      TiXmlElement *textureXml = new TiXmlElement("texture");
      snprintf(id, sizeof(id), "image_%u", i);
      textureXml->SetAttribute("texture", id);
      textureXml->SetAttribute("texcoord", "UVSET0");
      diffuseXml->LinkEndChild(textureXml);
    }
    else
    {
      RGBAcolor = material->Diffuse().AsRGBA();
      r = ((RGBAcolor >> 24) & 0xFF) / 255.0f;
      g = ((RGBAcolor >> 16) & 0xFF) / 255.0f;
      b = ((RGBAcolor >> 8) & 0xFF) / 255.0f;
      a = (RGBAcolor & 0xFF) / 255.0f;

      colorXml = new TiXmlElement("color");
      snprintf(id, sizeof(id), "%f %f %f %f", r, g, b, a);
      colorXml->LinkEndChild(new TiXmlText(id));
      diffuseXml->LinkEndChild(colorXml);
    }

    // specular
    RGBAcolor = material->Specular().AsRGBA();
    r = ((RGBAcolor >> 24) & 0xFF) / 255.0f;
    g = ((RGBAcolor >> 16) & 0xFF) / 255.0f;
    b = ((RGBAcolor >> 8) & 0xFF) / 255.0f;
    a = (RGBAcolor & 0xFF) / 255.0f;

    TiXmlElement *specularXml = new TiXmlElement("specular");
    phongXml->LinkEndChild(specularXml);

    colorXml = new TiXmlElement("color");
    snprintf(id, sizeof(id), "%f %f %f %f", r, g, b, a);
    colorXml->LinkEndChild(new TiXmlText(id));
    specularXml->LinkEndChild(colorXml);

    // transparency
    double transp = material->GetTransparency();

    TiXmlElement *transparencyXml = new TiXmlElement("transparency");
    phongXml->LinkEndChild(transparencyXml);

    TiXmlElement *floatXml = new TiXmlElement("float");
    snprintf(id, sizeof(id), "%f", transp);
    floatXml->LinkEndChild(new TiXmlText(id));
    transparencyXml->LinkEndChild(floatXml);

    // shininess
    double shine = material->GetShininess();

    TiXmlElement *shininessXml = new TiXmlElement("shininess");
    phongXml->LinkEndChild(shininessXml);

    colorXml = new TiXmlElement("color");
    snprintf(id, sizeof(id), "%f", shine);
    colorXml->LinkEndChild(new TiXmlText(id));
    shininessXml->LinkEndChild(colorXml);
  }
}

//////////////////////////////////////////////////
void ColladaExporter::ExportVisualScenes(
    TiXmlElement *_libraryVisualScenesXml)
{
  TiXmlElement *visualSceneXml = new TiXmlElement("visual_scene");
  _libraryVisualScenesXml->LinkEndChild(visualSceneXml);
  visualSceneXml->SetAttribute("name", "Scene");
  visualSceneXml->SetAttribute("id", "Scene");

  TiXmlElement *nodeXml = new TiXmlElement("node");
  visualSceneXml->LinkEndChild(nodeXml);
  nodeXml->SetAttribute("name", "node");
  nodeXml->SetAttribute("id", "node");

  for (unsigned int i = 0; i < this->dataPtr->subMeshCount; ++i)
  {
    char meshId[100], materialId[100], attributeValue[100];
    snprintf(meshId, sizeof(meshId), "mesh_%u", i);
    snprintf(materialId, sizeof(materialId), "material_%u", i);

    TiXmlElement *instanceGeometryXml = new TiXmlElement("instance_geometry");
    nodeXml->LinkEndChild(instanceGeometryXml);
    snprintf(attributeValue, sizeof(attributeValue), "#%s", meshId);
    instanceGeometryXml->SetAttribute("url", attributeValue);

    const gazebo::common::Material *material =
        this->dataPtr->mesh->GetMaterial(i);

    if (material)
    {
      TiXmlElement *bindMaterialXml = new TiXmlElement("bind_material");
      instanceGeometryXml->LinkEndChild(bindMaterialXml);

      TiXmlElement *techniqueCommonXml = new TiXmlElement("technique_common");
      bindMaterialXml->LinkEndChild(techniqueCommonXml);

      TiXmlElement *instanceMaterialXml =
          new TiXmlElement("instance_material");
      techniqueCommonXml->LinkEndChild(instanceMaterialXml);
      instanceMaterialXml->SetAttribute("symbol", materialId);
      snprintf(attributeValue, sizeof(attributeValue), "#%s", materialId);
      instanceMaterialXml->SetAttribute("target", attributeValue);

      std::string imageString = material->GetTextureImage();

      if (imageString.find("meshes/") != std::string::npos)
      {
        TiXmlElement *bindVertexInputXml =
            new TiXmlElement("bind_vertex_input");
        instanceMaterialXml->LinkEndChild(bindVertexInputXml);
        bindVertexInputXml->SetAttribute("semantic", "UVSET0");
        bindVertexInputXml->SetAttribute("input_semantic", "TEXCOORD");
      }
    }
  }
}

//////////////////////////////////////////////////
void ColladaExporter::ExportScene(TiXmlElement *_sceneXml)
{
  TiXmlElement *instanceVisualSceneXml =
      new TiXmlElement("instance_visual_scene");
  _sceneXml->LinkEndChild(instanceVisualSceneXml);
  instanceVisualSceneXml->SetAttribute("url", "#Scene");
}
