Commit c8c4f882 authored by Philip Trettner's avatar Philip Trettner
Browse files

renamed PropT to AttrT, added copy from data for attributes

parent 9746ec6e
......@@ -23,4 +23,5 @@ Best used with glm and glow.
* make handle.<primitives>() contain only valid ones and provide an all_<primitives>() version
* _copy versions of topological operations that copy attributes
* vertex split?
* half-edge collapse
\ No newline at end of file
* half-edge collapse
* normal, tangent, bitangent computation
\ No newline at end of file
......@@ -19,6 +19,9 @@
// - intersections
#include "algorithms/operations.hh"
// Geodesics
#include "algorithms/geodesic_nnf.hh"
// TODO:
// - decimation
// - subdivision
......
#pragma once
#include "../Mesh.hh"
#include "../fields.hh"
namespace polymesh
{
/**
* @brief Implements geodesic distances using the NNF algorithm
*
* Usage:
*
* auto nnf = make_geodesic_nnf(mesh, positions);
*/
template <class Vec3, class Scalar = typename field_3d<Vec3>::Scalar>
struct GeodesicNNF
{
public:
GeodesicNNF(Mesh const& m, vertex_attribute<Vec3> const& position);
private:
Mesh const& mesh;
vertex_attribute<Vec3> const& position;
};
template <class Vec3, class Scalar = typename field_3d<Vec3>::Scalar>
GeodesicNNF<Vec3, Scalar> make_geodesic_nnf(Mesh const& m, vertex_attribute<Vec3> const& position);
}
// Implementation
#include "geodesic_nnf.impl.hh"
#pragma once
#include "geodesic_nnf.hh"
namespace polymesh
{
template <class Vec3, class Scalar>
GeodesicNNF<Vec3, Scalar> make_geodesic_nnf(Mesh const& m, vertex_attribute<Vec3> const& position)
{
return {m, position};
}
template <class Vec3, class Scalar>
GeodesicNNF<Vec3, Scalar>::GeodesicNNF(const Mesh& m, const vertex_attribute<Vec3>& position) : mesh(m), position(position)
{
}
}
......@@ -113,11 +113,13 @@ protected:
int mDataSize = 0;
Mesh const* mMesh;
primitive_attribute_base(Mesh const* mesh) : mMesh(mesh) {} // no registration, it's too early!
virtual ~primitive_attribute_base() { deregister_attr(); }
virtual void on_resize(int new_size) = 0;
virtual void apply_remapping(std::vector<int> const& map) = 0;
void register_attr();
void deregister_attr();
friend class Mesh;
public:
virtual ~primitive_attribute_base() { deregister_attr(); }
};
}
#pragma once
#include <cassert>
#include <map>
#include <memory>
#include <string>
#include "attributes.hh"
namespace polymesh
{
/// Collection of named attributes (requires RTTI)
/// Attributes are owned by the collection
///
/// Usage:
///
/// attribute_collection ac;
///
/// // insert attributes
/// // NOTE: copies the attribute!
/// // TODO: support std::move
/// ac["aPosition"] = m.vertices().make_attribute<glm::vec3>();
///
/// // access attributes (must exist)
/// auto aPos = ac["aPosition"].vertex<glm::vec3>();
struct attribute_collection
{
struct accessor;
struct const_accessor;
/// returns access to a named attribute
accessor operator[](std::string const& name) { return {name, *this}; }
const_accessor operator[](std::string const& name) const { return {name, *this}; }
public:
struct accessor
{
std::string name;
attribute_collection& ref;
template <class AttrT>
accessor& operator=(vertex_attribute<AttrT> const& a)
{
ref.mVertexAttrs[name].reset(new vertex_attribute<AttrT>(a));
return *this;
}
template <class AttrT>
accessor& operator=(face_attribute<AttrT> const& a)
{
ref.mFaceAttrs[name].reset(new face_attribute<AttrT>(a));
return *this;
}
template <class AttrT>
accessor& operator=(edge_attribute<AttrT> const& a)
{
ref.mEdgeAttrs[name].reset(new edge_attribute<AttrT>(a));
return *this;
}
template <class AttrT>
accessor& operator=(halfedge_attribute<AttrT> const& a)
{
ref.mHalfedgeAttrs[name].reset(new halfedge_attribute<AttrT>(a));
return *this;
}
template <class AttrT>
vertex_attribute<AttrT>& vertex()
{
auto pa = ref.mVertexAttrs.at(name).get();
assert(pa && "non-existent attribute");
return *dynamic_cast<vertex_attribute<AttrT>*>(pa);
}
template <class AttrT>
face_attribute<AttrT>& face()
{
auto pa = ref.mVertexAttrs.at(name).get();
assert(pa && "non-existent attribute");
return *dynamic_cast<face_attribute<AttrT>*>(pa);
}
template <class AttrT>
edge_attribute<AttrT>& edge()
{
auto pa = ref.mVertexAttrs.at(name).get();
assert(pa && "non-existent attribute");
return *dynamic_cast<edge_attribute<AttrT>*>(pa);
}
template <class AttrT>
halfedge_attribute<AttrT>& halfedge()
{
auto pa = ref.mVertexAttrs.at(name).get();
assert(pa && "non-existent attribute");
return *dynamic_cast<halfedge_attribute<AttrT>*>(pa);
}
};
struct const_accessor
{
std::string name;
attribute_collection const& ref;
template <class AttrT>
vertex_attribute<AttrT>& vertex()
{
auto pa = ref.mVertexAttrs.at(name).get();
assert(pa && "non-existent attribute");
return *dynamic_cast<vertex_attribute<AttrT>*>(pa);
}
template <class AttrT>
face_attribute<AttrT>& face()
{
auto pa = ref.mVertexAttrs.at(name).get();
assert(pa && "non-existent attribute");
return *dynamic_cast<face_attribute<AttrT>*>(pa);
}
template <class AttrT>
edge_attribute<AttrT>& edge()
{
auto pa = ref.mVertexAttrs.at(name).get();
assert(pa && "non-existent attribute");
return *dynamic_cast<edge_attribute<AttrT>*>(pa);
}
template <class AttrT>
halfedge_attribute<AttrT>& halfedge()
{
auto pa = ref.mVertexAttrs.at(name).get();
assert(pa && "non-existent attribute");
return *dynamic_cast<halfedge_attribute<AttrT>*>(pa);
}
};
private:
std::map<std::string, primitive_attribute_base<vertex_tag>> mVertexAttrs;
// TODO
std::map<std::string, std::unique_ptr<primitive_attribute_base<vertex_tag>>> mVertexAttrs;
std::map<std::string, std::unique_ptr<primitive_attribute_base<face_tag>>> mFaceAttrs;
std::map<std::string, std::unique_ptr<primitive_attribute_base<edge_tag>>> mEdgeAttrs;
std::map<std::string, std::unique_ptr<primitive_attribute_base<halfedge_tag>>> mHalfedgeAttrs;
friend accessor;
friend const_accessor;
};
}
......@@ -59,6 +59,11 @@ public:
template <class FuncT>
void apply(FuncT&& f);
/// copies as much data as possible from the given vector
void copy_from(std::vector<AttrT> const& data);
/// copies as much data as possible from the given array
void copy_from(AttrT const* data, int cnt);
// data
protected:
attribute_data<AttrT> mData;
......@@ -112,64 +117,4 @@ struct halfedge_attribute : primitive_attribute<halfedge_tag, AttrT>
friend struct smart_collection;
};
/// ======== IMPLEMENTATION ========
template <class tag, class AttrT>
void primitive_attribute<tag, AttrT>::apply_remapping(const std::vector<int>& map)
{
for (auto i = 0u; i < map.size(); ++i)
this->mData[i] = this->mData[map[i]];
}
template <class tag, class AttrT>
primitive_attribute<tag, AttrT>::primitive_attribute(primitive_attribute const& rhs) noexcept : primitive_attribute_base<tag>(rhs.mMesh) // copy
{
this->mDefaultValue = rhs.mDefaultValue;
this->mData = rhs.mData;
this->mDataSize = rhs.mDataSize;
this->register_attr();
}
template <class tag, class AttrT>
primitive_attribute<tag, AttrT>::primitive_attribute(primitive_attribute&& rhs) noexcept : primitive_attribute_base<tag>(rhs.mMesh) // move
{
this->mDefaultValue = std::move(rhs.mDefaultValue);
this->mData = std::move(rhs.mData);
this->mDataSize = rhs.mDataSize;
rhs.deregister_attr();
this->register_attr();
}
template <class tag, class AttrT>
primitive_attribute<tag, AttrT>& primitive_attribute<tag, AttrT>::operator=(primitive_attribute const& rhs) noexcept // copy
{
this->deregister_attr();
this->mMesh = rhs.mMesh;
this->mDefaultValue = rhs.mDefaultValue;
this->mData = rhs.mData;
this->mDataSize = rhs.mDataSize;
this->register_attr();
return *this;
}
template <class tag, class AttrT>
primitive_attribute<tag, AttrT>& primitive_attribute<tag, AttrT>::operator=(primitive_attribute&& rhs) noexcept // move
{
this->deregister_attr();
this->mMesh = rhs.mMesh;
this->mDefaultValue = std::move(rhs.mDefaultValue);
this->mData = std::move(rhs.mData);
this->mDataSize = rhs.mDataSize;
rhs.deregister_attr();
this->register_attr();
return *this;
}
}
......@@ -4,6 +4,81 @@
namespace polymesh
{
template <class tag, class AttrT>
void primitive_attribute<tag, AttrT>::copy_from(const std::vector<AttrT> &data)
{
auto s = std::min((int)data.size(), this->mDataSize);
for (auto i = 0; i < s; ++i)
this->mData[i] = data[i];
}
template <class tag, class AttrT>
void primitive_attribute<tag, AttrT>::copy_from(const AttrT *data, int cnt)
{
auto s = std::min(cnt, this->mDataSize);
for (auto i = 0; i < s; ++i)
this->mData[i] = data[i];
}
template <class tag, class AttrT>
void primitive_attribute<tag, AttrT>::apply_remapping(const std::vector<int> &map)
{
for (auto i = 0u; i < map.size(); ++i)
this->mData[i] = this->mData[map[i]];
}
template <class tag, class AttrT>
primitive_attribute<tag, AttrT>::primitive_attribute(primitive_attribute const &rhs) noexcept : primitive_attribute_base<tag>(rhs.mMesh) // copy
{
this->mDefaultValue = rhs.mDefaultValue;
this->mData = rhs.mData;
this->mDataSize = rhs.mDataSize;
this->register_attr();
}
template <class tag, class AttrT>
primitive_attribute<tag, AttrT>::primitive_attribute(primitive_attribute &&rhs) noexcept : primitive_attribute_base<tag>(rhs.mMesh) // move
{
this->mDefaultValue = std::move(rhs.mDefaultValue);
this->mData = std::move(rhs.mData);
this->mDataSize = rhs.mDataSize;
rhs.deregister_attr();
this->register_attr();
}
template <class tag, class AttrT>
primitive_attribute<tag, AttrT> &primitive_attribute<tag, AttrT>::operator=(primitive_attribute const &rhs) noexcept // copy
{
this->deregister_attr();
this->mMesh = rhs.mMesh;
this->mDefaultValue = rhs.mDefaultValue;
this->mData = rhs.mData;
this->mDataSize = rhs.mDataSize;
this->register_attr();
return *this;
}
template <class tag, class AttrT>
primitive_attribute<tag, AttrT> &primitive_attribute<tag, AttrT>::operator=(primitive_attribute &&rhs) noexcept // move
{
this->deregister_attr();
this->mMesh = rhs.mMesh;
this->mDefaultValue = std::move(rhs.mDefaultValue);
this->mData = std::move(rhs.mData);
this->mDataSize = rhs.mDataSize;
rhs.deregister_attr();
this->register_attr();
return *this;
}
inline void Mesh::register_attr(primitive_attribute_base<vertex_tag> *attr) const
{
// insert in front
......
......@@ -279,23 +279,41 @@ void smart_collection<mesh_ptr, tag, iterator>::reserve(int capacity) const
}
template <class mesh_ptr, class tag, class iterator>
template <class PropT>
typename primitive<tag>::template attribute<PropT> smart_collection<mesh_ptr, tag, iterator>::make_attribute() const
template <class AttrT>
typename primitive<tag>::template attribute<AttrT> smart_collection<mesh_ptr, tag, iterator>::make_attribute() const
{
return typename primitive<tag>::template attribute<PropT>(mesh, PropT());
return typename primitive<tag>::template attribute<AttrT>(mesh, AttrT());
}
template <class mesh_ptr, class tag, class iterator>
template <class PropT>
typename primitive<tag>::template attribute<PropT> smart_collection<mesh_ptr, tag, iterator>::make_attribute_default(PropT const &def_value) const
template <class AttrT>
typename primitive<tag>::template attribute<AttrT> smart_collection<mesh_ptr, tag, iterator>::make_attribute_with_default(AttrT const &def_value) const
{
return typename primitive<tag>::template attribute<PropT>(mesh, def_value);
return typename primitive<tag>::template attribute<AttrT>(mesh, def_value);
}
template <class mesh_ptr, class tag, class iterator>
template <class FuncT, class PropT>
typename primitive<tag>::template attribute<PropT> smart_collection<mesh_ptr, tag, iterator>::make_attribute(FuncT &&f, PropT const &def_value) const
template <class AttrT>
typename primitive<tag>::template attribute<AttrT> smart_collection<mesh_ptr, tag, iterator>::make_attribute_from_data(std::vector<AttrT> const &data) const
{
auto attr = make_attribute_default<PropT>(def_value);
auto attr = make_attribute<AttrT>();
attr.copy_from(data);
return attr; // copy elison
}
template <class mesh_ptr, class tag, class iterator>
template <class AttrT>
typename primitive<tag>::template attribute<AttrT> smart_collection<mesh_ptr, tag, iterator>::make_attribute_from_data(AttrT const *data, int cnt) const
{
auto attr = make_attribute<AttrT>();
attr.copy_from(data, cnt);
return attr; // copy elison
}
template <class mesh_ptr, class tag, class iterator>
template <class FuncT, class AttrT>
typename primitive<tag>::template attribute<AttrT> smart_collection<mesh_ptr, tag, iterator>::make_attribute(FuncT &&f, AttrT const &def_value) const
{
auto attr = make_attribute_with_default<AttrT>(def_value);
for (auto h : *this)
attr[h] = f(h);
return attr; // copy elison
......@@ -564,7 +582,7 @@ void vertex_collection<iterator>::collapse(vertex_handle v) const
this->mesh->vertex_collapse(v.idx);
}
template<class iterator>
template <class iterator>
void halfedge_collection<iterator>::collapse(halfedge_handle h) const
{
this->mesh->halfedge_collapse(h.idx);
......
......@@ -125,14 +125,20 @@ struct smart_collection : smart_range<smart_collection<mesh_ptr, tag, iterator>,
void reserve(int capacity) const;
/// Creates a new primitive attribute
template <class PropT>
attribute<PropT> make_attribute() const;
template <class AttrT>
attribute<AttrT> make_attribute() const;
/// Creates a new primitive attribute with a given default value
template <class PropT>
attribute<PropT> make_attribute_default(PropT const& def_value) const;
template <class AttrT>
attribute<AttrT> make_attribute_with_default(AttrT const& def_value) const;
/// Creates a new primitive attribute and copies the given data
template <class AttrT>
attribute<AttrT> make_attribute_from_data(std::vector<AttrT> const& data) const;
/// Creates a new primitive attribute and copies the given data
template <class AttrT>
attribute<AttrT> make_attribute_from_data(AttrT const* data, int cnt) const;
/// Creates a new primitive attribute and initializes it with f(h) for each handle h
template <class FuncT, class PropT = tmp::decayed_result_type_of<FuncT, handle>>
attribute<PropT> make_attribute(FuncT&& f, PropT const& def_value = PropT()) const;
template <class FuncT, class AttrT = tmp::decayed_result_type_of<FuncT, handle>>
attribute<AttrT> make_attribute(FuncT&& f, AttrT const& def_value = AttrT()) const;
// Iteration:
iterator begin() const;
......@@ -445,5 +451,4 @@ struct halfedge_ring : halfedge_primitive_ring<halfedge_tag, halfedge_ring_circu
{
using halfedge_primitive_ring<halfedge_tag, halfedge_ring_circulator>::halfedge_primitive_ring;
};
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment