Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_misc.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define INCLUDE_HPP
Toshihiro Shimizu 890ddd
#include "tmeshimage.h"
Toshihiro Shimizu 890ddd
#undef INCLUDE_HPP
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
//    Explicit instantiations
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef tcg::TriMesh<ttexturevertex, tcg::edge,="" tcg::facen<3="">> TriMesh_base;</ttexturevertex,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
//    TTextureMesh  implementation
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DEFINE_CLASS_CODE(TTextureMesh, 120)
Toshihiro Shimizu 890ddd
PERSIST_IDENTIFIER(TTextureMesh, "mesh")
Toshihiro Shimizu 890ddd
Campbell Barton 8c6c57
static void static_check() {
Shinya Kitaoka 120a6e
  /* input iterator */
Shinya Kitaoka 120a6e
  static_assert(
Shinya Kitaoka 120a6e
      std::is_same
Shinya Kitaoka 120a6e
                       std::vector<ttexturemesh>::iterator>::iterator_category,</ttexturemesh>
Shinya Kitaoka 120a6e
                   std::random_access_iterator_tag>::value == true,
Shinya Kitaoka 120a6e
      "random");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  static_assert(
Shinya Kitaoka 120a6e
      std::is_base_of
Shinya Kitaoka 120a6e
                      std::iterator_traits
Shinya Kitaoka 120a6e
                          TTextureMesh>::iterator>::iterator_category>::value ==
Shinya Kitaoka 120a6e
          true,
Shinya Kitaoka 120a6e
      "input");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  static_assert(
Shinya Kitaoka 120a6e
      std::is_base_of
Shinya Kitaoka 120a6e
                      std::iterator_traits
Shinya Kitaoka 120a6e
                          TTextureMesh>::iterator>::iterator_category>::value ==
Shinya Kitaoka 120a6e
          true,
Shinya Kitaoka 120a6e
      "forward");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  static_assert(
Shinya Kitaoka 120a6e
      std::is_constructible
Shinya Kitaoka 120a6e
                            std::iterator_traits
Shinya Kitaoka 120a6e
                                TTextureMeshP>::iterator>::reference>::value ==
Shinya Kitaoka 120a6e
          true,
Shinya Kitaoka 120a6e
      "akan");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TTextureMesh::TTextureMesh() : TSmartObject(m_classCode) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TTextureMesh::TTextureMesh(const TTextureMesh &other)
Shinya Kitaoka 120a6e
    : TriMesh_base(other), TSmartObject(m_classCode) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TTextureMesh &TTextureMesh::operator=(const TTextureMesh &other) {
Shinya Kitaoka 120a6e
  TriMesh_base::operator=(other);
Shinya Kitaoka 120a6e
  return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TTextureMesh::faceContains(int f, const TPointD &p) const {
Shinya Kitaoka 120a6e
  int v0, v1, v2;
Shinya Kitaoka 120a6e
  this->faceVertices(f, v0, v1, v2);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TPointD &p0 = vertex(v0).P();
Shinya Kitaoka 120a6e
  const TPointD &p1 = vertex(v1).P();
Shinya Kitaoka 120a6e
  const TPointD &p2 = vertex(v2).P();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool clockwise = (tcg::point_ops::cross(p2 - p0, p1 - p0) >= 0);
Shinya Kitaoka 120a6e
  return ((tcg::point_ops::cross(p - p0, p1 - p0) >= 0) == clockwise) &&
Shinya Kitaoka 120a6e
         ((tcg::point_ops::cross(p - p1, p2 - p1) >= 0) == clockwise) &&
Shinya Kitaoka 120a6e
         ((tcg::point_ops::cross(p - p2, p0 - p2) >= 0) == clockwise);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TTextureMesh::faceContaining(const TPointD &p) const {
Shinya Kitaoka 120a6e
  int f, fCount = facesCount();
Shinya Kitaoka 120a6e
  for (f = 0; f < fCount; ++f)
Shinya Kitaoka 120a6e
    if (faceContains(f, p)) return f;
Shinya Kitaoka 120a6e
  return -1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRectD TTextureMesh::getBBox() const {
Shinya Kitaoka 120a6e
  // TODO: Should be cached...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const double max = (std::numeric_limits<double>::max)();</double>
Shinya Kitaoka 120a6e
  TRectD result(max, max, -max, -max);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Iterate all meshes
Shinya Kitaoka 120a6e
  assert(m_vertices.size() == m_vertices.nodesCount());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int v, vCount = int(m_vertices.size());
Shinya Kitaoka 120a6e
  for (v = 0; v != vCount; ++v) {
Shinya Kitaoka 120a6e
    const TTextureVertex &vx = m_vertices[v];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    result.x0 = std::min(result.x0, vx.P().x);
Shinya Kitaoka 120a6e
    result.y0 = std::min(result.y0, vx.P().y);
Shinya Kitaoka 120a6e
    result.x1 = std::max(result.x1, vx.P().x);
Shinya Kitaoka 120a6e
    result.y1 = std::max(result.y1, vx.P().y);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TTextureMesh::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static inline bool hasNon1Rigidity(const TTextureMesh &mesh) {
Shinya Kitaoka 120a6e
      int v, vCount = int(mesh.verticesCount());
Shinya Kitaoka 120a6e
      for (v = 0; v != vCount; ++v)
Shinya Kitaoka 120a6e
        if (mesh.vertex(v).P().rigidity != 1.0) return true;
Shinya Kitaoka 120a6e
      return false;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // NOTE: Primitives saved by INDEX iteration is NOT COINCIDENTAL - since
Shinya Kitaoka 120a6e
  // the lists' internal linking could have been altered to mismatch the
Shinya Kitaoka 120a6e
  // natural indexing referred to by primitives' data.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_vertices.size() != m_vertices.nodesCount() ||
Shinya Kitaoka 120a6e
      m_edges.size() != m_edges.nodesCount() ||
Shinya Kitaoka 120a6e
      m_faces.size() != m_faces.nodesCount()) {
Shinya Kitaoka 120a6e
    // Ensure the mesh is already squeezed - save a squeezed
Shinya Kitaoka 120a6e
    // copy if necessary
Shinya Kitaoka 120a6e
    TTextureMesh mesh(*this);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    mesh.squeeze();
Shinya Kitaoka 120a6e
    mesh.saveData(os);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(m_vertices.size() == m_vertices.nodesCount());
Shinya Kitaoka 120a6e
  assert(m_edges.size() == m_edges.nodesCount());
Shinya Kitaoka 120a6e
  assert(m_faces.size() == m_faces.nodesCount());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Store Vertices
Shinya Kitaoka 120a6e
  os.openChild("V");
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    int vCount = int(m_vertices.size());
Shinya Kitaoka 120a6e
    os << vCount;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (int v = 0; v != vCount; ++v) {
Shinya Kitaoka 120a6e
      TTextureMesh::vertex_type &vx = m_vertices[v];
Shinya Kitaoka 120a6e
      os << vx.P().x << vx.P().y;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os.closeChild();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Store Edges
Shinya Kitaoka 120a6e
  os.openChild("E");
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    int eCount = int(m_edges.size());
Shinya Kitaoka 120a6e
    os << eCount;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (int e = 0; e != eCount; ++e) {
Shinya Kitaoka 120a6e
      TTextureMesh::edge_type &ed = m_edges[e];
Shinya Kitaoka 120a6e
      os << ed.vertex(0) << ed.vertex(1);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os.closeChild();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Store Faces
Shinya Kitaoka 120a6e
  os.openChild("F");
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    int fCount = int(m_faces.size());
Shinya Kitaoka 120a6e
    os << fCount;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (int f = 0; f != fCount; ++f) {
Shinya Kitaoka 120a6e
      TTextureMesh::face_type &fc = m_faces[f];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int e, eCount = fc.edgesCount();
Shinya Kitaoka 120a6e
      for (e = 0; e < eCount; ++e) os << fc.edge(e);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os.closeChild();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Store rigidities
Shinya Kitaoka 120a6e
  if (locals::hasNon1Rigidity(*this)) {
Shinya Kitaoka 120a6e
    os.openChild("rigidities");
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      int vCount = int(m_vertices.size());
Shinya Kitaoka 120a6e
      os << vCount;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      for (int v = 0; v != vCount; ++v) os << m_vertices[v].P().rigidity;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    os.closeChild();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TTextureMesh::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  typedef tcg::Mesh<vertex_type, edge_type,="" face_type=""> mesh_type;</vertex_type,>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::string str;
Shinya Kitaoka 120a6e
  int i, size;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  while (is.openChild(str)) {
Shinya Kitaoka 120a6e
    if (str == "V") {
Shinya Kitaoka 120a6e
      is >> size;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_vertices.reserve(size);
Shinya Kitaoka 120a6e
      TTextureMesh::vertex_type v;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (i = 0; i < size; ++i) {
Shinya Kitaoka 120a6e
        is >> v.P().x >> v.P().y;
Shinya Kitaoka 120a6e
        mesh_type::addVertex(v);
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      is.closeChild();
Shinya Kitaoka 120a6e
    } else if (str == "E") {
Shinya Kitaoka 120a6e
      is >> size;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_edges.reserve(size);
Shinya Kitaoka 120a6e
      int v0, v1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (i = 0; i < size; ++i) {
Shinya Kitaoka 120a6e
        is >> v0 >> v1;
Shinya Kitaoka 120a6e
        mesh_type::addEdge(TTextureMesh::edge_type(v0, v1));
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      is.closeChild();
Shinya Kitaoka 120a6e
    } else if (str == "F") {
Shinya Kitaoka 120a6e
      is >> size;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_faces.reserve(size);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      int e[3];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (i = 0; i < size; ++i) {
Shinya Kitaoka 120a6e
        is >> e[0] >> e[1] >> e[2];
Shinya Kitaoka 120a6e
        mesh_type::addFace(TTextureMesh::face_type(e));
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      is.closeChild();
Shinya Kitaoka 120a6e
    } else if (str == "rigidities") {
Shinya Kitaoka 120a6e
      is >> size;
Shinya Kitaoka 120a6e
      size = std::min(size, this->verticesCount());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (i = 0; i < size; ++i) is >> m_vertices[i].P().rigidity;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      is.closeChild();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      assert(false);
Shinya Kitaoka 120a6e
      is.skipCurrentTag();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
//    TMeshImage::Imp  definition
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TMeshImage::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  std::vector<ttexturemeshp> m_meshes;  //!< Mesh data</ttexturemeshp>
Shinya Kitaoka 120a6e
  double m_dpiX, m_dpiY;                //!< Meshes dpi
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Imp() : m_dpiX(), m_dpiY() {}
Toshihiro Shimizu 890ddd
otakuto e347ad
  Imp(const Imp &other) : m_dpiX(other.m_dpiX), m_dpiY(other.m_dpiY) {
otakuto e347ad
    for (auto const &e : other.m_meshes) {
otakuto e347ad
      m_meshes.push_back(cloneMesh(e));
otakuto e347ad
    }
otakuto e347ad
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  static TTextureMeshP cloneMesh(const TTextureMeshP &other) {
Shinya Kitaoka 120a6e
    return TTextureMeshP(new TTextureMesh(*other));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Not assignable
Shinya Kitaoka 120a6e
  Imp &operator=(const Imp &other);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
//    TMeshImage  implementation
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TMeshImage::TMeshImage() : m_imp(new Imp) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TMeshImage::TMeshImage(std::shared_ptr<imp> imp) : m_imp(std::move(imp)) {}</imp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TMeshImage::~TMeshImage() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TMeshImage::TMeshImage(const TMeshImage &other)
Shinya Kitaoka 120a6e
    : m_imp(new Imp(*other.m_imp)) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TMeshImage &TMeshImage::operator=(TMeshImage other) {
Shinya Kitaoka 120a6e
  swap(*this, other);
Shinya Kitaoka 120a6e
  return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRectD TMeshImage::getBBox() const {
Shinya Kitaoka 120a6e
  const double max = (std::numeric_limits<double>::max)();</double>
Shinya Kitaoka 120a6e
  TRectD result(max, max, -max, -max);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Iterate all meshes
Shinya Kitaoka 120a6e
  int m, mCount = int(m_imp->m_meshes.size());
Shinya Kitaoka 120a6e
  for (m = 0; m < mCount; ++m) result += m_imp->m_meshes[m]->getBBox();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TImage *TMeshImage::cloneImage() const { return new TMeshImage(*this); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMeshImage::getDpi(double &dpix, double &dpiy) const {
Shinya Kitaoka 120a6e
  dpix = m_imp->m_dpiX, dpiy = m_imp->m_dpiY;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMeshImage::setDpi(double dpix, double dpiy) {
Shinya Kitaoka 120a6e
  m_imp->m_dpiX = dpix, m_imp->m_dpiY = dpiy;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const std::vector<ttexturemeshp> &TMeshImage::meshes() const {</ttexturemeshp>
Shinya Kitaoka 120a6e
  return m_imp->m_meshes;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::vector<ttexturemeshp> &TMeshImage::meshes() { return m_imp->m_meshes; }</ttexturemeshp>