Commit 38b326c2 authored by Philip Trettner's avatar Philip Trettner
Browse files

more range ops

parent 885fafb6
...@@ -27,4 +27,5 @@ Best used with glm and glow. ...@@ -27,4 +27,5 @@ Best used with glm and glow.
* normal, tangent, bitangent computation * normal, tangent, bitangent computation
* attribute iterator * attribute iterator
* primitive sort functions, better remap function, cache optimization * primitive sort functions, better remap function, cache optimization
* structure of arrays instead of AOS * structure of arrays instead of AOS
\ No newline at end of file * lowlevel API that allows direct half-edge manipulation and does not fix boundaries (but also mirrors high level one)
\ No newline at end of file
...@@ -106,6 +106,11 @@ public: ...@@ -106,6 +106,11 @@ public:
/// Creates a new mesh and returns a shared_ptr to it /// Creates a new mesh and returns a shared_ptr to it
static SharedMesh create() { return std::make_shared<Mesh>(); } static SharedMesh create() { return std::make_shared<Mesh>(); }
/// Clears this mesh and copies mesh topology, NOT attributes!
void copy_from(Mesh const &m);
/// Creates a new mesh and calls copy_from(*this);
SharedMesh copy() const;
// internal helper // internal helper
private: private:
// reserves a certain number of primitives // reserves a certain number of primitives
...@@ -245,11 +250,11 @@ private: ...@@ -245,11 +250,11 @@ private:
vertex_index from_vertex_of(halfedge_index idx) const { return halfedge(opposite(idx)).to_vertex; } vertex_index from_vertex_of(halfedge_index idx) const { return halfedge(opposite(idx)).to_vertex; }
/// applies an index remapping to all face indices (p[curr_idx] = new_idx) /// applies an index remapping to all face indices (p[curr_idx] = new_idx)
void permute_faces(std::vector<int> const& p); void permute_faces(std::vector<int> const &p);
/// applies an index remapping to all edge (and half-edge) indices (p[curr_idx] = new_idx) /// applies an index remapping to all edge (and half-edge) indices (p[curr_idx] = new_idx)
void permute_edges(std::vector<int> const& p); void permute_edges(std::vector<int> const &p);
/// applies an index remapping to all vertices indices (p[curr_idx] = new_idx) /// applies an index remapping to all vertices indices (p[curr_idx] = new_idx)
void permute_vertices(std::vector<int> const& p); void permute_vertices(std::vector<int> const &p);
// internal datastructures // internal datastructures
private: private:
......
...@@ -15,7 +15,7 @@ void triangulate_naive(Mesh& m); ...@@ -15,7 +15,7 @@ void triangulate_naive(Mesh& m);
/// ======== IMPLEMENTATION ======== /// ======== IMPLEMENTATION ========
void triangulate_naive(Mesh& m) inline void triangulate_naive(Mesh& m)
{ {
std::vector<vertex_handle> vs; std::vector<vertex_handle> vs;
for (auto f : m.faces()) for (auto f : m.faces())
......
...@@ -62,6 +62,12 @@ struct attribute_data ...@@ -62,6 +62,12 @@ struct attribute_data
} }
~attribute_data() { delete[] data; } ~attribute_data() { delete[] data; }
void clear(DataT const& value)
{
for (auto i = 0; i < size; ++i)
data[i] = value;
}
void resize(int new_size, DataT const& default_value) void resize(int new_size, DataT const& default_value)
{ {
auto new_data = new DataT[new_size]; auto new_data = new DataT[new_size];
......
...@@ -38,15 +38,15 @@ struct primitive_attribute : primitive_attribute_base<tag> ...@@ -38,15 +38,15 @@ struct primitive_attribute : primitive_attribute_base<tag>
// data access // data access
public: public:
AttrT& operator[](handle_t v) { return mData[v.idx.value]; } AttrT& operator[](handle_t h);
AttrT const& operator[](handle_t v) const { return mData[v.idx.value]; } AttrT const& operator[](handle_t h) const;
AttrT& operator[](index_t v) { return mData[v.value]; } AttrT& operator[](index_t h) { return mData[h.value]; }
AttrT const& operator[](index_t v) const { return mData[v.value]; } AttrT const& operator[](index_t h) const { return mData[h.value]; }
AttrT& operator()(handle_t v) { return mData[v.idx.value]; } AttrT& operator()(handle_t h);
AttrT const& operator()(handle_t v) const { return mData[v.idx.value]; } AttrT const& operator()(handle_t h) const;
AttrT& operator()(index_t v) { return mData[v.value]; } AttrT& operator()(index_t h) { return mData[h.value]; }
AttrT const& operator()(index_t v) const { return mData[v.value]; } AttrT const& operator()(index_t h) const { return mData[h.value]; }
AttrT* data() { return mData.data; } AttrT* data() { return mData.data; }
AttrT const* data() const { return mData.data; } AttrT const* data() const { return mData.data; }
...@@ -68,6 +68,8 @@ public: ...@@ -68,6 +68,8 @@ public:
void copy_from(std::vector<AttrT> const& data); void copy_from(std::vector<AttrT> const& data);
/// copies as much data as possible from the given array /// copies as much data as possible from the given array
void copy_from(AttrT const* data, int cnt); void copy_from(AttrT const* data, int cnt);
/// copies as much data as possible from the given attribute
void copy_from(attribute<AttrT> const& data);
// data // data
protected: protected:
...@@ -111,6 +113,21 @@ struct edge_attribute : primitive_attribute<edge_tag, AttrT> ...@@ -111,6 +113,21 @@ struct edge_attribute : primitive_attribute<edge_tag, AttrT>
{ {
using primitive_attribute<edge_tag, AttrT>::primitive_attribute; using primitive_attribute<edge_tag, AttrT>::primitive_attribute;
// shortcuts for half-edge handles
AttrT& operator[](halfedge_handle h);
AttrT const& operator[](halfedge_handle h) const;
AttrT& operator[](halfedge_index h) { return this->mData[h.value >> 1]; }
AttrT const& operator[](halfedge_index h) const { return this->mData[h.value >> 1]; }
AttrT& operator()(halfedge_handle h);
AttrT const& operator()(halfedge_handle h) const;
AttrT& operator()(halfedge_index h) { return this->mData[h.value >> 1]; }
AttrT const& operator()(halfedge_index h) const { return this->mData[h.value >> 1]; }
using primitive_attribute<edge_tag, AttrT>::operator[];
using primitive_attribute<edge_tag, AttrT>::operator();
template <class mesh_ptr, class tag, class iterator> template <class mesh_ptr, class tag, class iterator>
friend struct smart_collection; friend struct smart_collection;
}; };
......
...@@ -8,7 +8,7 @@ namespace polymesh ...@@ -8,7 +8,7 @@ namespace polymesh
namespace detail namespace detail
{ {
// from https://en.wikipedia.org/wiki/Xorshift // from https://en.wikipedia.org/wiki/Xorshift
uint64_t xorshift64star(uint64_t &state) inline uint64_t xorshift64star(uint64_t &state)
{ {
uint64_t x = state; /* The state must be seeded with a nonzero value. */ uint64_t x = state; /* The state must be seeded with a nonzero value. */
x ^= x >> 12; // a x ^= x >> 12; // a
......
...@@ -4,6 +4,56 @@ ...@@ -4,6 +4,56 @@
namespace polymesh namespace polymesh
{ {
template <class tag, class AttrT>
AttrT &primitive_attribute<tag, AttrT>::operator[](handle_t h)
{
assert(this->mMesh == h.mesh && "Handle belongs to a different mesh");
return mData[h.idx.value];
}
template <class tag, class AttrT>
AttrT const &primitive_attribute<tag, AttrT>::operator[](handle_t h) const
{
assert(this->mMesh == h.mesh && "Handle belongs to a different mesh");
return mData[h.idx.value];
}
template <class tag, class AttrT>
AttrT &primitive_attribute<tag, AttrT>::operator()(handle_t h)
{
assert(this->mMesh == h.mesh && "Handle belongs to a different mesh");
return mData[h.idx.value];
}
template <class tag, class AttrT>
AttrT const &primitive_attribute<tag, AttrT>::operator()(handle_t h) const
{
assert(this->mMesh == h.mesh && "Handle belongs to a different mesh");
return mData[h.idx.value];
}
template <class AttrT>
AttrT &edge_attribute<AttrT>::operator[](halfedge_handle h)
{
assert(this->mMesh == h.mesh && "Handle belongs to a different mesh");
return this->mData[h.idx.value >> 1];
}
template <class AttrT>
AttrT const &edge_attribute<AttrT>::operator[](halfedge_handle h) const
{
assert(this->mMesh == h.mesh && "Handle belongs to a different mesh");
return this->mData[h.idx.value >> 1];
}
template <class AttrT>
AttrT &edge_attribute<AttrT>::operator()(halfedge_handle h)
{
assert(this->mMesh == h.mesh && "Handle belongs to a different mesh");
return this->mData[h.idx.value >> 1];
}
template <class AttrT>
AttrT const &edge_attribute<AttrT>::operator()(halfedge_handle h) const
{
assert(this->mMesh == h.mesh && "Handle belongs to a different mesh");
return this->mData[h.idx.value >> 1];
}
template <class tag, class AttrT> template <class tag, class AttrT>
void primitive_attribute<tag, AttrT>::copy_from(const std::vector<AttrT> &data) void primitive_attribute<tag, AttrT>::copy_from(const std::vector<AttrT> &data)
{ {
...@@ -20,6 +70,14 @@ void primitive_attribute<tag, AttrT>::copy_from(const AttrT *data, int cnt) ...@@ -20,6 +70,14 @@ void primitive_attribute<tag, AttrT>::copy_from(const AttrT *data, int cnt)
this->mData[i] = data[i]; this->mData[i] = data[i];
} }
template <class tag, class AttrT>
void primitive_attribute<tag, AttrT>::copy_from(attribute<AttrT> const &data)
{
auto s = std::min(data.mDataSize, this->mDataSize);
for (auto i = 0; i < s; ++i)
this->mData[i] = data.mData[i];
}
template <class tag, class AttrT> template <class tag, class AttrT>
void primitive_attribute<tag, AttrT>::apply_remapping(const std::vector<int> &map) void primitive_attribute<tag, AttrT>::apply_remapping(const std::vector<int> &map)
{ {
...@@ -231,8 +289,7 @@ int primitive_attribute<tag, AttrT>::size() const ...@@ -231,8 +289,7 @@ int primitive_attribute<tag, AttrT>::size() const
template <class tag, class AttrT> template <class tag, class AttrT>
void primitive_attribute<tag, AttrT>::clear(AttrT const &value) void primitive_attribute<tag, AttrT>::clear(AttrT const &value)
{ {
this->mData.clear(); this->mData.clear(value);
this->mData.resize(size(), value);
} }
template <class tag, class AttrT> template <class tag, class AttrT>
......
...@@ -1242,6 +1242,37 @@ inline void Mesh::clear() ...@@ -1242,6 +1242,37 @@ inline void Mesh::clear()
compactify(); compactify();
} }
inline void Mesh::copy_from(const Mesh &m)
{
// copy topo
mVertices = m.mVertices;
mFaces = m.mFaces;
mHalfedges = m.mHalfedges;
// copy helper data
mRemovedFaces = m.mRemovedFaces;
mRemovedHalfedges = m.mRemovedHalfedges;
mRemovedVertices = m.mRemovedVertices;
mCompact = m.mCompact;
// resize attributes
for (auto a = mVertexAttrs; a; a = a->mNextAttribute)
a->resize(size_all_vertices(), true);
for (auto a = mFaceAttrs; a; a = a->mNextAttribute)
a->resize(size_all_faces(), true);
for (auto a = mEdgeAttrs; a; a = a->mNextAttribute)
a->resize(size_all_edges(), true);
for (auto a = mHalfedgeAttrs; a; a = a->mNextAttribute)
a->resize(size_all_halfedges(), true);
}
inline SharedMesh Mesh::copy() const
{
auto m = create();
m->copy_from(*this);
return m;
}
inline void Mesh::reserve_faces(int capacity) inline void Mesh::reserve_faces(int capacity)
{ {
for (auto a = mFaceAttrs; a; a = a->mNextAttribute) for (auto a = mFaceAttrs; a; a = a->mNextAttribute)
......
...@@ -261,6 +261,32 @@ auto smart_range<this_t, ElementT>::weighted_avg(FuncT &&f, WeightT &&w) const - ...@@ -261,6 +261,32 @@ auto smart_range<this_t, ElementT>::weighted_avg(FuncT &&f, WeightT &&w) const -
return s / ws; return s / ws;
} }
template <class this_t, class ElementT>
template <class FuncT, class FuncInvT>
auto smart_range<this_t, ElementT>::f_mean(FuncT &&f, FuncInvT &&f_inv) const
-> tmp::decayed_result_type_of<FuncInvT, tmp::decayed_result_type_of<FuncT, ElementT>>
{
return f_inv(this->avg(f));
}
template <class this_t, class ElementT>
template <class FuncT>
auto smart_range<this_t, ElementT>::arithmetic_mean(FuncT &&f) const -> tmp::decayed_result_type_of<FuncT, ElementT>
{
return this->avg(f);
}
template <class this_t, class ElementT>
template <class FuncT>
auto smart_range<this_t, ElementT>::geometric_mean(FuncT &&f) const -> tmp::decayed_result_type_of<FuncT, ElementT>
{
using std::exp;
using std::log;
auto ff = [&f](ElementT const &e) { return log(f(e)); };
auto ff_inv = [](decltype(ff(std::declval<ElementT>())) const &d) { return exp(d); };
return this->f_mean(ff, ff_inv);
}
template <class this_t, class ElementT> template <class this_t, class ElementT>
template <class FuncT> template <class FuncT>
auto smart_range<this_t, ElementT>::aabb(FuncT &&f) const -> polymesh::aabb<typename tmp::decayed_result_of<FuncT, ElementT>::type> auto smart_range<this_t, ElementT>::aabb(FuncT &&f) const -> polymesh::aabb<typename tmp::decayed_result_of<FuncT, ElementT>::type>
......
...@@ -92,6 +92,17 @@ struct smart_range ...@@ -92,6 +92,17 @@ struct smart_range
template <class FuncT, class WeightT> template <class FuncT, class WeightT>
auto weighted_avg(FuncT&& f, WeightT&& w) const -> tmp::decayed_result_type_of<FuncT, ElementT>; auto weighted_avg(FuncT&& f, WeightT&& w) const -> tmp::decayed_result_type_of<FuncT, ElementT>;
/// calculates the f-mean of this range
/// the f-mean is f_inv(avg(f))
template <class FuncT, class FuncInvT>
auto f_mean(FuncT&& f, FuncInvT&& f_inv) const -> tmp::decayed_result_type_of<FuncInvT, tmp::decayed_result_type_of<FuncT, ElementT>>;
/// calculates the arithmetic mean of f(e) for this range (same as avg)
template <class FuncT>
auto arithmetic_mean(FuncT&& f) const -> tmp::decayed_result_type_of<FuncT, ElementT>;
/// calculates the geometric mean of f(e) for this range (also known as log-average)
template <class FuncT>
auto geometric_mean(FuncT&& f) const -> tmp::decayed_result_type_of<FuncT, ElementT>;
/// calculates the aabb (min and max) of f(e) over all elements /// calculates the aabb (min and max) of f(e) over all elements
/// undefined behavior if range is empty /// undefined behavior if range is empty
/// works for std::min/max and everything reachable by ADL (calls min/max(_, _)) /// works for std::min/max and everything reachable by ADL (calls min/max(_, _))
......
Markdown is supported
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