Skip to content
Snippets Groups Projects
Commit c8c4f882 authored by Philip Trettner's avatar Philip Trettner
Browse files

renamed PropT to AttrT, added copy from data for attributes

parent 9746ec6e
No related branches found
No related tags found
No related merge requests found
......@@ -24,3 +24,4 @@ Best used with glm and glow.
* _copy versions of topological operations that copy attributes
* vertex split?
* 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
......
......@@ -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;
};
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment