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.
* normal, tangent, bitangent computation
* attribute iterator
* primitive sort functions, better remap function, cache optimization
* structure of arrays instead of AOS
\ No newline at end of file
* structure of arrays instead of AOS
* 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:
/// Creates a new mesh and returns a shared_ptr to it
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
private:
// reserves a certain number of primitives
......@@ -245,11 +250,11 @@ private:
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)
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)
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)
void permute_vertices(std::vector<int> const& p);
void permute_vertices(std::vector<int> const &p);
// internal datastructures
private:
......
......@@ -15,7 +15,7 @@ void triangulate_naive(Mesh& m);
/// ======== IMPLEMENTATION ========
void triangulate_naive(Mesh& m)
inline void triangulate_naive(Mesh& m)
{
std::vector<vertex_handle> vs;
for (auto f : m.faces())
......
......@@ -62,6 +62,12 @@ struct attribute_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)
{
auto new_data = new DataT[new_size];
......
......@@ -38,15 +38,15 @@ struct primitive_attribute : primitive_attribute_base<tag>
// data access
public:
AttrT& operator[](handle_t v) { return mData[v.idx.value]; }
AttrT const& operator[](handle_t v) const { return mData[v.idx.value]; }
AttrT& operator[](index_t v) { return mData[v.value]; }
AttrT const& operator[](index_t v) const { return mData[v.value]; }
AttrT& operator[](handle_t h);
AttrT const& operator[](handle_t h) const;
AttrT& operator[](index_t h) { return mData[h.value]; }
AttrT const& operator[](index_t h) const { return mData[h.value]; }
AttrT& operator()(handle_t v) { return mData[v.idx.value]; }
AttrT const& operator()(handle_t v) const { return mData[v.idx.value]; }
AttrT& operator()(index_t v) { return mData[v.value]; }
AttrT const& operator()(index_t v) const { return mData[v.value]; }
AttrT& operator()(handle_t h);
AttrT const& operator()(handle_t h) const;
AttrT& operator()(index_t h) { return mData[h.value]; }
AttrT const& operator()(index_t h) const { return mData[h.value]; }
AttrT* data() { return mData.data; }
AttrT const* data() const { return mData.data; }
......@@ -68,6 +68,8 @@ public:
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);
/// copies as much data as possible from the given attribute
void copy_from(attribute<AttrT> const& data);
// data
protected:
......@@ -111,6 +113,21 @@ struct edge_attribute : primitive_attribute<edge_tag, AttrT>
{
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>
friend struct smart_collection;
};
......
......@@ -8,7 +8,7 @@ namespace polymesh
namespace detail
{
// 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. */
x ^= x >> 12; // a
......
......@@ -4,6 +4,56 @@
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>
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)
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>
void primitive_attribute<tag, AttrT>::apply_remapping(const std::vector<int> &map)
{
......@@ -231,8 +289,7 @@ int primitive_attribute<tag, AttrT>::size() const
template <class tag, class AttrT>
void primitive_attribute<tag, AttrT>::clear(AttrT const &value)
{
this->mData.clear();
this->mData.resize(size(), value);
this->mData.clear(value);
}
template <class tag, class AttrT>
......
......@@ -1242,6 +1242,37 @@ inline void Mesh::clear()
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)
{
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 -
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 FuncT>
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
template <class FuncT, class WeightT>
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
/// undefined behavior if range is empty
/// 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