Commit 9c3d267c authored by Philip Trettner's avatar Philip Trettner
Browse files

better attributes

parent 23da7387
......@@ -10,9 +10,6 @@ using namespace polymesh;
void Mesh::assert_consistency() const
{
/// TODO
/// check compact!
// check sizes
assert(mHalfedges.size() % 2 == 0); ///< even number of halfedges
......
......@@ -104,10 +104,10 @@ public:
// internal helper
private:
// reserves a certain number of primitives
void reserve_faces(size_t capacity) { mFaces.reserve(capacity); }
void reserve_vertices(size_t capacity) { mVertices.reserve(capacity); }
void reserve_edges(size_t capacity) { mHalfedges.reserve(capacity * 2); }
void reserve_halfedges(size_t capacity) { mHalfedges.reserve(capacity); }
void reserve_faces(size_t capacity);
void reserve_vertices(size_t capacity);
void reserve_edges(size_t capacity);
void reserve_halfedges(size_t capacity);
int size_faces() const { return (int)mFaces.size(); }
int size_vertices() const { return (int)mVertices.size(); }
......@@ -384,7 +384,7 @@ inline vertex_index Mesh::add_vertex()
// notify attributes
auto vCnt = mVertices.size();
for (auto p = mVertexAttrs; p; p = p->mNextAttribute)
p->resize(vCnt);
p->resize(vCnt, false);
return idx;
}
......@@ -463,7 +463,7 @@ inline face_index Mesh::add_face(const halfedge_index *half_loop, size_t vcnt)
// notify attributes
auto fCnt = mFaces.size();
for (auto p = mFaceAttrs; p; p = p->mNextAttribute)
p->resize(fCnt);
p->resize(fCnt, false);
return fidx;
}
......@@ -538,9 +538,9 @@ inline edge_index Mesh::add_or_get_edge(vertex_index v_from, vertex_index v_to)
auto hCnt = mHalfedges.size();
auto eCnt = hCnt >> 1;
for (auto p = mHalfedgeAttrs; p; p = p->mNextAttribute)
p->resize(hCnt);
p->resize(hCnt, false);
for (auto p = mEdgeAttrs; p; p = p->mNextAttribute)
p->resize(eCnt);
p->resize(eCnt, false);
return eidx;
}
......@@ -1355,12 +1355,62 @@ inline void Mesh::compactify()
for (auto a = mHalfedgeAttrs; a; a = a->mNextAttribute)
a->apply_remapping(h_new_to_old);
// shrink to fit
mVertices.shrink_to_fit();
mFaces.shrink_to_fit();
mHalfedges.shrink_to_fit();
for (auto a = mVertexAttrs; a; a = a->mNextAttribute)
a->resize(size_vertices(), true);
for (auto a = mFaceAttrs; a; a = a->mNextAttribute)
a->resize(size_faces(), true);
for (auto a = mEdgeAttrs; a; a = a->mNextAttribute)
a->resize(size_edges(), true);
for (auto a = mHalfedgeAttrs; a; a = a->mNextAttribute)
a->resize(size_halfedges(), true);
mRemovedFaces = 0;
mRemovedHalfedges = 0;
mRemovedVertices = 0;
mCompact = true;
}
inline void Mesh::reserve_faces(size_t capacity)
{
for (auto a = mFaceAttrs; a; a = a->mNextAttribute)
a->resize(capacity, false);
mFaces.reserve(capacity);
}
inline void Mesh::reserve_vertices(size_t capacity)
{
for (auto a = mVertexAttrs; a; a = a->mNextAttribute)
a->resize(capacity, false);
mVertices.reserve(capacity);
}
inline void Mesh::reserve_edges(size_t capacity)
{
for (auto a = mEdgeAttrs; a; a = a->mNextAttribute)
a->resize(capacity, false);
for (auto a = mHalfedgeAttrs; a; a = a->mNextAttribute)
a->resize(capacity << 1, false);
mHalfedges.reserve(capacity * 2);
}
inline void Mesh::reserve_halfedges(size_t capacity)
{
for (auto a = mHalfedgeAttrs; a; a = a->mNextAttribute)
a->resize(capacity, false);
for (auto a = mEdgeAttrs; a; a = a->mNextAttribute)
a->resize(capacity >> 1, false);
mHalfedges.reserve(capacity);
}
/// ======== HANDLES IMPLEMENTATION ========
inline bool vertex_handle::is_removed() const
......@@ -1632,7 +1682,7 @@ inline void Mesh::register_attr(vertex_attribute_base *attr) const
nextAttrs->mPrevAttribute = attr;
// resize attr
attr->resize(vertices().size());
attr->resize(vertices().size(), false);
}
inline void Mesh::deregister_attr(vertex_attribute_base *attr) const
......@@ -1641,10 +1691,13 @@ inline void Mesh::deregister_attr(vertex_attribute_base *attr) const
attr->mPrevAttribute->mNextAttribute = attr->mNextAttribute;
if (attr->mNextAttribute)
attr->mNextAttribute = attr->mPrevAttribute;
attr->mNextAttribute->mPrevAttribute = attr->mPrevAttribute;
if (mVertexAttrs == attr)
mVertexAttrs = attr->mNextAttribute;
attr->mNextAttribute = nullptr;
attr->mPrevAttribute = nullptr;
}
inline void Mesh::register_attr(face_attribute_base *attr) const
......@@ -1657,7 +1710,7 @@ inline void Mesh::register_attr(face_attribute_base *attr) const
nextAttrs->mPrevAttribute = attr;
// resize attr
attr->resize(faces().size());
attr->resize(faces().size(), false);
}
inline void Mesh::deregister_attr(face_attribute_base *attr) const
......@@ -1666,10 +1719,13 @@ inline void Mesh::deregister_attr(face_attribute_base *attr) const
attr->mPrevAttribute->mNextAttribute = attr->mNextAttribute;
if (attr->mNextAttribute)
attr->mNextAttribute = attr->mPrevAttribute;
attr->mNextAttribute->mPrevAttribute = attr->mPrevAttribute;
if (mFaceAttrs == attr)
mFaceAttrs = attr->mNextAttribute;
attr->mNextAttribute = nullptr;
attr->mPrevAttribute = nullptr;
}
inline void Mesh::register_attr(edge_attribute_base *attr) const
......@@ -1682,7 +1738,7 @@ inline void Mesh::register_attr(edge_attribute_base *attr) const
nextAttrs->mPrevAttribute = attr;
// resize attr
attr->resize(edges().size());
attr->resize(edges().size(), false);
}
inline void Mesh::deregister_attr(edge_attribute_base *attr) const
......@@ -1691,10 +1747,13 @@ inline void Mesh::deregister_attr(edge_attribute_base *attr) const
attr->mPrevAttribute->mNextAttribute = attr->mNextAttribute;
if (attr->mNextAttribute)
attr->mNextAttribute = attr->mPrevAttribute;
attr->mNextAttribute->mPrevAttribute = attr->mPrevAttribute;
if (mEdgeAttrs == attr)
mEdgeAttrs = attr->mNextAttribute;
attr->mNextAttribute = nullptr;
attr->mPrevAttribute = nullptr;
}
inline void Mesh::register_attr(halfedge_attribute_base *attr) const
......@@ -1707,7 +1766,7 @@ inline void Mesh::register_attr(halfedge_attribute_base *attr) const
nextAttrs->mPrevAttribute = attr;
// resize attr
attr->resize(halfedges().size());
attr->resize(halfedges().size(), false);
}
inline void Mesh::deregister_attr(halfedge_attribute_base *attr) const
......@@ -1716,10 +1775,13 @@ inline void Mesh::deregister_attr(halfedge_attribute_base *attr) const
attr->mPrevAttribute->mNextAttribute = attr->mNextAttribute;
if (attr->mNextAttribute)
attr->mNextAttribute = attr->mPrevAttribute;
attr->mNextAttribute->mPrevAttribute = attr->mPrevAttribute;
if (mHalfedgeAttrs == attr)
mHalfedgeAttrs = attr->mNextAttribute;
attr->mNextAttribute = nullptr;
attr->mPrevAttribute = nullptr;
}
inline vertex_attribute_base::vertex_attribute_base(const Mesh *mesh) : mMesh(mesh)
......@@ -1742,24 +1804,40 @@ inline halfedge_attribute_base::halfedge_attribute_base(const Mesh *mesh) : mMes
// mMesh->register_attr(this); TOO EARLY!
}
inline vertex_attribute_base::~vertex_attribute_base()
inline void vertex_attribute_base::deregister_attr()
{
mMesh->deregister_attr(this);
if (mMesh)
{
mMesh->deregister_attr(this);
mMesh = nullptr;
}
}
inline face_attribute_base::~face_attribute_base()
inline void face_attribute_base::deregister_attr()
{
mMesh->deregister_attr(this);
if (mMesh)
{
mMesh->deregister_attr(this);
mMesh = nullptr;
}
}
inline edge_attribute_base::~edge_attribute_base()
inline void edge_attribute_base::deregister_attr()
{
mMesh->deregister_attr(this);
if (mMesh)
{
mMesh->deregister_attr(this);
mMesh = nullptr;
}
}
inline halfedge_attribute_base::~halfedge_attribute_base()
inline void halfedge_attribute_base::deregister_attr()
{
mMesh->deregister_attr(this);
if (mMesh)
{
mMesh->deregister_attr(this);
mMesh = nullptr;
}
}
inline void vertex_attribute_base::register_attr()
......
......@@ -13,9 +13,9 @@
namespace polymesh
{
vertex_handle split(edge_handle e)
{
// TODO
}
// vertex_handle split(edge_handle e)
// {
// // TODO
// }
}
\ No newline at end of file
}
#pragma once
#include <vector>
#include <cstddef>
#include <vector>
// Helper for mesh-based attribute bookkeeping
......@@ -9,29 +9,113 @@ namespace polymesh
{
class Mesh;
template <typename DataT>
struct attribute_data
{
size_t size = 0;
DataT* data = nullptr;
DataT& operator[](int i) { return data[i]; }
DataT const& operator[](int i) const { return data[i]; }
attribute_data() = default;
attribute_data(attribute_data<DataT> const& rhs) // copy
{
size = rhs.size;
data = new DataT[size];
for (size_t i = 0; i < size; ++i)
data[i] = rhs.data[i];
}
attribute_data(attribute_data<DataT>&& rhs) // move
{
size = rhs.size;
data = rhs.data;
rhs.size = 0;
rhs.data = nullptr;
}
attribute_data<DataT>& operator=(attribute_data<DataT> const& rhs) // copy
{
delete[] data;
size = rhs.size;
data = new DataT[size];
for (size_t i = 0; i < size; ++i)
data[i] = rhs.data[i];
return *this;
}
attribute_data<DataT>& operator=(attribute_data<DataT>&& rhs) // move
{
delete[] data;
size = rhs.size;
data = rhs.data;
rhs.size = 0;
rhs.data = nullptr;
return *this;
}
~attribute_data() { delete[] data; }
void resize(size_t new_size, DataT const& default_value)
{
auto new_data = new DataT[new_size];
if (new_size < size)
{
for (size_t i = 0; i < new_size; ++i)
new_data[i] = data[i];
}
else
{
for (size_t i = 0; i < size; ++i)
new_data[i] = data[i];
for (size_t i = size; i < new_size; ++i)
new_data[i] = default_value;
}
delete[] data;
data = new_data;
size = new_size;
}
};
struct vertex_attribute_base
{
private:
vertex_attribute_base* mNextAttribute = nullptr;
vertex_attribute_base* mPrevAttribute = nullptr;
size_t mDataSize = 0;
void resize(size_t newSize)
void resize(size_t newSize, bool force)
{
if (force)
{
mDataSize = newSize;
on_resize(mDataSize);
return;
}
if (mDataSize < newSize)
{
mDataSize = 1 + newSize + (newSize >> 1); // 1 + s * 1.5
mDataSize = std::max(newSize, 1 + mDataSize + (mDataSize >> 1)); // 1 + s * 1.5
on_resize(mDataSize);
}
}
protected:
size_t mDataSize = 0;
Mesh const* mMesh;
vertex_attribute_base(Mesh const* mesh);
virtual ~vertex_attribute_base();
virtual ~vertex_attribute_base() { deregister_attr(); }
virtual void on_resize(size_t newSize) = 0;
virtual void apply_remapping(std::vector<int> const& map) = 0;
void register_attr();
void deregister_attr();
friend class Mesh;
};
......@@ -40,24 +124,32 @@ struct face_attribute_base
private:
face_attribute_base* mNextAttribute = nullptr;
face_attribute_base* mPrevAttribute = nullptr;
size_t mDataSize = 0;
void resize(size_t newSize)
void resize(size_t newSize, bool force)
{
if (force)
{
mDataSize = newSize;
on_resize(mDataSize);
return;
}
if (mDataSize < newSize)
{
mDataSize = 1 + newSize + (newSize >> 1); // 1 + s * 1.5
mDataSize = std::max(newSize, 1 + mDataSize + (mDataSize >> 1)); // 1 + s * 1.5
on_resize(mDataSize);
}
}
protected:
size_t mDataSize = 0;
Mesh const* mMesh;
face_attribute_base(Mesh const* mesh);
virtual ~face_attribute_base();
virtual ~face_attribute_base() { deregister_attr(); }
virtual void on_resize(size_t newSize) = 0;
virtual void apply_remapping(std::vector<int> const& map) = 0;
void register_attr();
void deregister_attr();
friend class Mesh;
};
......@@ -66,24 +158,32 @@ struct edge_attribute_base
private:
edge_attribute_base* mNextAttribute = nullptr;
edge_attribute_base* mPrevAttribute = nullptr;
size_t mDataSize = 0;
void resize(size_t newSize)
void resize(size_t newSize, bool force)
{
if (force)
{
mDataSize = newSize;
on_resize(mDataSize);
return;
}
if (mDataSize < newSize)
{
mDataSize = 1 + newSize + (newSize >> 1); // 1 + s * 1.5
mDataSize = std::max(newSize, 1 + mDataSize + (mDataSize >> 1)); // 1 + s * 1.5
on_resize(mDataSize);
}
}
protected:
size_t mDataSize = 0;
Mesh const* mMesh;
edge_attribute_base(Mesh const* mesh);
virtual ~edge_attribute_base();
virtual ~edge_attribute_base() { deregister_attr(); }
virtual void on_resize(size_t newSize) = 0;
virtual void apply_remapping(std::vector<int> const& map) = 0;
void register_attr();
void deregister_attr();
friend class Mesh;
};
......@@ -92,24 +192,32 @@ struct halfedge_attribute_base
private:
halfedge_attribute_base* mNextAttribute = nullptr;
halfedge_attribute_base* mPrevAttribute = nullptr;
size_t mDataSize = 0;
void resize(size_t newSize)
void resize(size_t newSize, bool force)
{
if (force)
{
mDataSize = newSize;
on_resize(mDataSize);
return;
}
if (mDataSize < newSize)
{
mDataSize = 1 + newSize + (newSize >> 1); // 1 + s * 1.5
mDataSize = std::max(newSize, 1 + mDataSize + (mDataSize >> 1)); // 1 + s * 1.5
on_resize(mDataSize);
}
}
protected:
size_t mDataSize = 0;
Mesh const* mMesh;
halfedge_attribute_base(Mesh const* mesh);
virtual ~halfedge_attribute_base();
virtual ~halfedge_attribute_base() { deregister_attr(); }
virtual void on_resize(size_t newSize) = 0;
virtual void apply_remapping(std::vector<int> const& map) = 0;
void register_attr();
void deregister_attr();
friend class Mesh;
};
}
......@@ -3,10 +3,10 @@
#include <cstddef>
#include <vector>
#include "cursors.hh"
#include "attribute_base.hh"
#include "cursors.hh"
/** Attrerties
/** Attributes
*
* Golden rule:
* - the Mesh must always outlive the attribute!
......@@ -18,8 +18,6 @@
* vertex_handle v; // or _index
* v[myAttr] = 7;
* myAttr[v] = 7;
*
* TODO: correct copy and move ctors/assignments
*/
namespace polymesh
......@@ -34,8 +32,8 @@ public:
AttrT& operator[](vertex_index v) { return mData[v.value]; }
AttrT const& operator[](vertex_index v) const { return mData[v.value]; }
AttrT* data() { return mData.data(); }
AttrT const* data() const { return mData.data(); }
AttrT* data() { return mData; }
AttrT const* data() const { return mData; }
size_t size() const;
// methods
......@@ -45,7 +43,7 @@ public:
// data
private:
std::vector<AttrT> mData;
attribute_data<AttrT> mData;
AttrT mDefaultValue;
void on_resize(size_t newSize) override { mData.resize(newSize, mDefaultValue); }
......@@ -55,6 +53,13 @@ private:
private:
vertex_attribute(Mesh const* mesh, AttrT const& def_value);
friend struct vertex_collection;
// move & copy
public:
vertex_attribute(vertex_attribute const&);
vertex_attribute(vertex_attribute&&);
vertex_attribute& operator=(vertex_attribute const&);
vertex_attribute& operator=(vertex_attribute&&);
};
template <typename AttrT>
......@@ -78,7 +83,7 @@ public:
// data
private:
std::vector<AttrT> mData;
attribute_data<AttrT> mData;
AttrT mDefaultValue;
void on_resize(size_t newSize) override { mData.resize(newSize, mDefaultValue); }
......@@ -88,6 +93,13 @@ private:
private:
face_attribute(Mesh const* mesh, AttrT const& def_value);
friend struct face_collection;
// move & copy
public:
face_attribute(face_attribute const&);
face_attribute(face_attribute&&);
face_attribute& operator=(face_attribute const&);
face_attribute& operator=(face_attribute&&);
};
template <typename AttrT>
......@@ -111,7 +123,7 @@ public:
// data
private:
std::vector<AttrT> mData;
attribute_data<AttrT> mData;
AttrT mDefaultValue;
void on_resize(size_t newSize) override { mData.resize(newSize, mDefaultValue); }
......@@ -121,6 +133,13 @@ private:
private:
edge_attribute(Mesh const* mesh, AttrT const& def_value);
friend struct edge_collection;
// move & copy
public:
edge_attribute(edge_attribute const&);
edge_attribute(edge_attribute&&);
edge_attribute& operator=(edge_attribute const&);
edge_attribute& operator=(edge_attribute&&);
};
template <typename AttrT>
......@@ -147,42 +166,242 @@ public:
// data
private:
std::vector<AttrT> mData;
attribute_data<AttrT> mData;
AttrT mDefaultValue;
// ctor
private:
halfedge_attribute(Mesh const* mesh, AttrT const& def_value);