namespace X3DTK {

template<class MData, class VData, class EData, class FData, bool RW>
TemplateSimplifiedMeshScene<MData, VData, EData, FData, RW>::TemplateSimplifiedMeshScene()
: mesh(0)
{
  loader = Singleton<X3D::Loader>::getInstance();
  bboxupdater = Singleton<X3D::BBoxUpdater>::getInstance();
  translator = Singleton<X3D::WorldCoordTranslator>::getInstance();
  meshbuilder = Singleton<X3D::TemplateMeshBuilder<MData, VData, EData, FData, RW> >::getInstance();
  normalsupdater = Singleton<MESH::TemplateNormalsUpdater<MData, VData, EData, FData, RW> >::getInstance();
  meshsimplifier = Singleton<MESH::TemplateMeshSimplifier<MData, VData, EData, FData, RW> >::getInstance();
  releaser = Singleton<MemReleaser>::getInstance();
}

template<class MData, class VData, class EData, class FData, bool RW>
TemplateSimplifiedMeshScene<MData, VData, EData, FData, RW>::~TemplateSimplifiedMeshScene()
{
  Singleton<X3D::Loader>::removeInstance();
  Singleton<X3D::BBoxUpdater>::removeInstance();
  Singleton<X3D::WorldCoordTranslator>::removeInstance();
  Singleton<X3D::TemplateMeshBuilder<MData, VData, EData, FData, RW> >::removeInstance();
  Singleton<MESH::TemplateNormalsUpdater<MData, VData, EData, FData, RW> >::removeInstance();
  Singleton<MESH::TemplateMeshSimplifier<MData, VData, EData, FData, RW> >::removeInstance();
}

template<class MData, class VData, class EData, class FData, bool RW>
void TemplateSimplifiedMeshScene<MData, VData, EData, FData, RW>::load(const char *file)
{
  X3D::Scene *S = loader->load(file, true);
  bboxupdater->update(S, true);
  releaser->release(mesh);
  mesh = 0;
      
  if (S != 0)
  {
    SFVec3f center = S->getBBoxCenter();
    SFVec3f size = S->getBBoxSize();

    SFVec3f A = center + 0.5f*size;
    SFVec3f B = center - 0.5f*size;

    if (A.x < B.x)
    {
      min.x = A.x;
      max.x = B.x;
    }  
    else
    {
      min.x = B.x;  
      max.x = A.x;
    }  
  
    if (A.y < B.y)
    {
      min.y = A.y;
      max.y = B.y;
    }  
    else
    {
      min.y = B.y;  
      max.y = A.y;
    }
  
    if (A.z < B.z)
    {
      min.z = A.z;
      max.z = B.z;
    }  
    else
    {
      min.z = B.z;  
      max.z = A.z;
    }  
    
    translator->translate(S);
    MESH::Scene *MS = meshbuilder->build(S);
    releaser->release(S);
    normalsupdater->updateNormals(MS);

    mesh = meshsimplifier->build(MS);
    releaser->release(MS);
  }
}

}
