Commit 0a8a4f3e authored by Philip Trettner's avatar Philip Trettner
Browse files

properties

parent 209097ab
......@@ -5,6 +5,7 @@
#include <vector>
#include "cursors.hh"
#include "properties.hh"
#include "ranges.hh"
namespace polymesh
......@@ -30,7 +31,7 @@ using SharedMesh = std::shared_ptr<Mesh>;
* * http://kaba.hilvi.org/homepage/blog/halfedge/halfedge.htm
* * https://www.openmesh.org/media/Documentations/OpenMesh-Doc-Latest/a03930.html
*/
struct Mesh
class Mesh
{
// accessors and iterators
public:
......@@ -210,6 +211,7 @@ private:
// internal datastructures
private:
// 4 byte per face
struct face_info
{
halfedge_index halfedge; ///< one half-edge bounding this face
......@@ -218,6 +220,7 @@ private:
void set_deleted() { halfedge = halfedge_index::invalid(); }
};
// 4 byte per vertex
struct vertex_info
{
halfedge_index outgoing_halfedge;
......@@ -229,6 +232,7 @@ private:
// is_boundary: check if outgoing_halfedge is boundary
};
// 32 byte per edge
struct halfedge_info
{
vertex_index to_vertex; ///< half-edge points towards this vertex
......@@ -271,6 +275,23 @@ private:
std::vector<halfedge_index> mFaceInsertCache;
// properties
private:
// linked lists of all properties
mutable vertex_property_base *mVertexProps = nullptr;
mutable face_property_base *mFaceProps = nullptr;
mutable edge_property_base *mEdgeProps = nullptr;
mutable halfedge_property_base *mHalfedgeProps = nullptr;
void register_prop(vertex_property_base *prop) const;
void deregister_prop(vertex_property_base *prop) const;
void register_prop(face_property_base *prop) const;
void deregister_prop(face_property_base *prop) const;
void register_prop(edge_property_base *prop) const;
void deregister_prop(edge_property_base *prop) const;
void register_prop(halfedge_property_base *prop) const;
void deregister_prop(halfedge_property_base *prop) const;
// friends
private:
friend struct vertex_handle;
......@@ -279,6 +300,7 @@ private:
friend struct valid_vertex_iterator;
friend struct valid_vertex_collection;
friend struct const_vertex_collection;
friend struct vertex_property_base;
friend struct face_handle;
friend struct face_collection;
......@@ -286,6 +308,7 @@ private:
friend struct valid_face_iterator;
friend struct valid_face_collection;
friend struct const_face_collection;
friend struct face_property_base;
friend struct edge_handle;
friend struct edge_collection;
......@@ -293,6 +316,7 @@ private:
friend struct valid_edge_iterator;
friend struct valid_edge_collection;
friend struct const_edge_collection;
friend struct edge_property_base;
friend struct halfedge_handle;
friend struct halfedge_collection;
......@@ -300,16 +324,21 @@ private:
friend struct valid_halfedge_iterator;
friend struct valid_halfedge_collection;
friend struct const_halfedge_collection;
friend struct halfedge_property_base;
};
/// ======== IMPLEMENTATION ========
inline vertex_index Mesh::add_vertex()
{
/// TODO: properties
auto idx = vertex_index((int)mVertices.size());
mVertices.push_back(vertex_info());
// notify properties
auto vCnt = mVertices.size();
for (auto p = mVertexProps; p; p = p->mNextProperty)
p->resize(vCnt);
return idx;
}
......@@ -367,6 +396,11 @@ inline face_index Mesh::add_face(const halfedge_index *half_loop, size_t vcnt)
f.halfedge = half_loop[0];
mFaces.push_back(f);
// notify properties
auto fCnt = mFaces.size();
for (auto p = mFaceProps; p; p = p->mNextProperty)
p->resize(fCnt);
return fidx;
}
......@@ -435,6 +469,15 @@ inline edge_index Mesh::add_or_get_edge(vertex_index v_from, vertex_index v_to)
// finalize
mHalfedges.push_back(h_from_to);
mHalfedges.push_back(h_to_from);
// notify properties
auto hCnt = mHalfedges.size();
auto eCnt = hCnt >> 1;
for (auto p = mHalfedgeProps; p; p = p->mNextProperty)
p->resize(hCnt);
for (auto p = mEdgeProps; p; p = p->mNextProperty)
p->resize(eCnt);
return eidx;
}
......@@ -998,4 +1041,290 @@ inline bool halfedge_handle::is_deleted() const
{
return !idx.is_valid() || !mesh->halfedge(idx).is_valid();
}
/// ======== PROPERTIES IMPLEMENTATION ========
template <typename PropT>
vertex_property<PropT> vertex_collection::make_property(const PropT &def_value)
{
return vertex_property<PropT>(mesh, def_value);
}
template <typename PropT>
face_property<PropT> face_collection::make_property(const PropT &def_value)
{
return face_property<PropT>(mesh, def_value);
}
template <typename PropT>
edge_property<PropT> edge_collection::make_property(const PropT &def_value)
{
return edge_property<PropT>(mesh, def_value);
}
template <typename PropT>
halfedge_property<PropT> halfedge_collection::make_property(const PropT &def_value)
{
return halfedge_property<PropT>(mesh, def_value);
}
inline void Mesh::register_prop(vertex_property_base *prop) const
{
// insert in front
auto nextProps = mVertexProps;
mVertexProps = prop;
prop->mNextProperty = nextProps;
if (nextProps)
nextProps->mPrevProperty = prop;
// resize prop
prop->resize(vertices().size());
}
inline void Mesh::deregister_prop(vertex_property_base *prop) const
{
if (prop->mPrevProperty)
prop->mPrevProperty->mNextProperty = prop->mNextProperty;
if (prop->mNextProperty)
prop->mNextProperty = prop->mPrevProperty;
if (mVertexProps == prop)
mVertexProps = prop->mNextProperty;
}
inline void Mesh::register_prop(face_property_base *prop) const
{
// insert in front
auto nextProps = mFaceProps;
mFaceProps = prop;
prop->mNextProperty = nextProps;
if (nextProps)
nextProps->mPrevProperty = prop;
// resize prop
prop->resize(faces().size());
}
inline void Mesh::deregister_prop(face_property_base *prop) const
{
if (prop->mPrevProperty)
prop->mPrevProperty->mNextProperty = prop->mNextProperty;
if (prop->mNextProperty)
prop->mNextProperty = prop->mPrevProperty;
if (mFaceProps == prop)
mFaceProps = prop->mNextProperty;
}
inline void Mesh::register_prop(edge_property_base *prop) const
{
// insert in front
auto nextProps = mEdgeProps;
mEdgeProps = prop;
prop->mNextProperty = nextProps;
if (nextProps)
nextProps->mPrevProperty = prop;
// resize prop
prop->resize(edges().size());
}
inline void Mesh::deregister_prop(edge_property_base *prop) const
{
if (prop->mPrevProperty)
prop->mPrevProperty->mNextProperty = prop->mNextProperty;
if (prop->mNextProperty)
prop->mNextProperty = prop->mPrevProperty;
if (mEdgeProps == prop)
mEdgeProps = prop->mNextProperty;
}
inline void Mesh::register_prop(halfedge_property_base *prop) const
{
// insert in front
auto nextProps = mHalfedgeProps;
mHalfedgeProps = prop;
prop->mNextProperty = nextProps;
if (nextProps)
nextProps->mPrevProperty = prop;
// resize prop
prop->resize(halfedges().size());
}
inline void Mesh::deregister_prop(halfedge_property_base *prop) const
{
if (prop->mPrevProperty)
prop->mPrevProperty->mNextProperty = prop->mNextProperty;
if (prop->mNextProperty)
prop->mNextProperty = prop->mPrevProperty;
if (mHalfedgeProps == prop)
mHalfedgeProps = prop->mNextProperty;
}
inline vertex_property_base::vertex_property_base(const Mesh *mesh) : mMesh(mesh)
{
// mMesh->register_prop(this); TOO EARLY!
}
inline face_property_base::face_property_base(const Mesh *mesh) : mMesh(mesh)
{
// mMesh->register_prop(this); TOO EARLY!
}
inline edge_property_base::edge_property_base(const Mesh *mesh) : mMesh(mesh)
{
// mMesh->register_prop(this); TOO EARLY!
}
inline halfedge_property_base::halfedge_property_base(const Mesh *mesh) : mMesh(mesh)
{
// mMesh->register_prop(this); TOO EARLY!
}
inline vertex_property_base::~vertex_property_base()
{
mMesh->deregister_prop(this);
}
inline face_property_base::~face_property_base()
{
mMesh->deregister_prop(this);
}
inline edge_property_base::~edge_property_base()
{
mMesh->deregister_prop(this);
}
inline halfedge_property_base::~halfedge_property_base()
{
mMesh->deregister_prop(this);
}
inline void vertex_property_base::register_prop()
{
mMesh->register_prop(this);
}
inline void face_property_base::register_prop()
{
mMesh->register_prop(this);
}
inline void edge_property_base::register_prop()
{
mMesh->register_prop(this);
}
inline void halfedge_property_base::register_prop()
{
mMesh->register_prop(this);
}
template <typename PropT>
vertex_property<PropT>::vertex_property(const Mesh *mesh, const PropT &def_value)
: vertex_property_base(mesh), mDefaultValue(def_value)
{
register_prop();
}
template <typename PropT>
face_property<PropT>::face_property(const Mesh *mesh, const PropT &def_value)
: face_property_base(mesh), mDefaultValue(def_value)
{
register_prop();
}
template <typename PropT>
edge_property<PropT>::edge_property(const Mesh *mesh, const PropT &def_value)
: edge_property_base(mesh), mDefaultValue(def_value)
{
register_prop();
}
template <typename PropT>
halfedge_property<PropT>::halfedge_property(const Mesh *mesh, const PropT &def_value)
: halfedge_property_base(mesh), mDefaultValue(def_value)
{
register_prop();
}
template <typename PropT>
size_t vertex_property<PropT>::size() const
{
return mMesh->vertices().size();
}
template <typename PropT>
void vertex_property<PropT>::clear(PropT const &value)
{
mData.clear();
mData.resize(mMesh->vertices().size(), value);
}
template <typename PropT>
void vertex_property<PropT>::clear()
{
clear(mDefaultValue);
}
template <typename PropT>
size_t face_property<PropT>::size() const
{
return mMesh->vertices().size();
}
template <typename PropT>
void face_property<PropT>::clear(PropT const &value)
{
mData.clear();
mData.resize(mMesh->vertices().size(), value);
}
template <typename PropT>
void face_property<PropT>::clear()
{
clear(mDefaultValue);
}
template <typename PropT>
size_t edge_property<PropT>::size() const
{
return mMesh->vertices().size();
}
template <typename PropT>
void edge_property<PropT>::clear(PropT const &value)
{
mData.clear();
mData.resize(mMesh->vertices().size(), value);
}
template <typename PropT>
void edge_property<PropT>::clear()
{
clear(mDefaultValue);
}
template <typename PropT>
size_t halfedge_property<PropT>::size() const
{
return mMesh->vertices().size();
}
template <typename PropT>
void halfedge_property<PropT>::clear(PropT const &value)
{
mData.clear();
mData.resize(mMesh->vertices().size(), value);
}
template <typename PropT>
void halfedge_property<PropT>::clear()
{
clear(mDefaultValue);
}
}
......@@ -2,7 +2,16 @@
namespace polymesh
{
struct Mesh;
class Mesh;
template <typename PropT>
struct vertex_property;
template <typename PropT>
struct face_property;
template <typename PropT>
struct edge_property;
template <typename PropT>
struct halfedge_property;
// ======================== INDICES ========================
......@@ -18,6 +27,11 @@ struct face_index
bool operator==(face_index const& rhs) const { return value == rhs.value; }
bool operator!=(face_index const& rhs) const { return value != rhs.value; }
template <typename PropT>
PropT& operator[](face_property<PropT>& prop) const;
template <typename PropT>
PropT const& operator[](face_property<PropT> const& prop) const;
};
struct vertex_index
......@@ -32,6 +46,11 @@ struct vertex_index
bool operator==(vertex_index const& rhs) const { return value == rhs.value; }
bool operator!=(vertex_index const& rhs) const { return value != rhs.value; }
template <typename PropT>
PropT& operator[](vertex_property<PropT>& prop) const;
template <typename PropT>
PropT const& operator[](vertex_property<PropT> const& prop) const;
};
struct edge_index
......@@ -46,6 +65,11 @@ struct edge_index
bool operator==(edge_index const& rhs) const { return value == rhs.value; }
bool operator!=(edge_index const& rhs) const { return value != rhs.value; }
template <typename PropT>
PropT& operator[](edge_property<PropT>& prop) const;
template <typename PropT>
PropT const& operator[](edge_property<PropT> const& prop) const;
};
struct halfedge_index
......@@ -60,6 +84,11 @@ struct halfedge_index
bool operator==(halfedge_index const& rhs) const { return value == rhs.value; }
bool operator!=(halfedge_index const& rhs) const { return value != rhs.value; }
template <typename PropT>
PropT& operator[](halfedge_property<PropT>& prop) const;
template <typename PropT>
PropT const& operator[](halfedge_property<PropT> const& prop) const;
};
// ======================== HANDLES ========================
......@@ -76,6 +105,11 @@ struct face_handle
bool operator==(face_handle const& rhs) const { return mesh == rhs.mesh && idx == rhs.idx; }
bool operator!=(face_handle const& rhs) const { return mesh != rhs.mesh || idx != rhs.idx; }
template <typename PropT>
PropT& operator[](face_property<PropT>& prop) const;
template <typename PropT>
PropT const& operator[](face_property<PropT> const& prop) const;
bool is_valid() const; ///< valid idx and not deleted
bool is_deleted() const; ///< marked for deletion (or invalid idx)
};
......@@ -92,6 +126,11 @@ struct vertex_handle
bool operator==(vertex_handle const& rhs) const { return mesh == rhs.mesh && idx == rhs.idx; }
bool operator!=(vertex_handle const& rhs) const { return mesh != rhs.mesh || idx != rhs.idx; }
template <typename PropT>
PropT& operator[](vertex_property<PropT>& prop) const;
template <typename PropT>
PropT const& operator[](vertex_property<PropT> const& prop) const;
bool is_valid() const; ///< valid idx and not deleted
bool is_deleted() const; ///< marked for deletion (or invalid idx)
};
......@@ -108,6 +147,11 @@ struct edge_handle
bool operator==(edge_handle const& rhs) const { return mesh == rhs.mesh && idx == rhs.idx; }
bool operator!=(edge_handle const& rhs) const { return mesh != rhs.mesh || idx != rhs.idx; }
template <typename PropT>
PropT& operator[](edge_property<PropT>& prop) const;
template <typename PropT>
PropT const& operator[](edge_property<PropT> const& prop) const;
bool is_valid() const; ///< valid idx and not deleted
bool is_deleted() const; ///< marked for deletion (or invalid idx)
};
......@@ -124,6 +168,11 @@ struct halfedge_handle
bool operator==(halfedge_handle const& rhs) const { return mesh == rhs.mesh && idx == rhs.idx; }
bool operator!=(halfedge_handle const& rhs) const { return mesh != rhs.mesh || idx != rhs.idx; }
template <typename PropT>
PropT& operator[](halfedge_property<PropT>& prop) const;
template <typename PropT>
PropT const& operator[](halfedge_property<PropT> const& prop) const;
bool is_valid() const; ///< valid idx and not deleted
bool is_deleted() const; ///< marked for deletion (or invalid idx)
......
#pragma once
#include <cstddef>
#include <vector>
#include "cursors.hh"
#include "property_base.hh"
/** Properties
*
* Golden rule:
* - the Mesh must always outlive the property!
*
* Create properties:
* auto myProp = mesh.vertices().make_property(0.0f);
*
* Access properties:
* vertex_handle v; // or _index
* v[myProp] = 7;
* myProp[v] = 7;
*
* TODO: correct copy and move ctors/assignments
*/
namespace polymesh
{
/// TODO
template <typename PropT>
struct vertex_property : vertex_property_base
{
// data access
public:
PropT& operator[](vertex_handle v) { return mData[v.idx.value]; }
PropT const& operator[](vertex_handle v) const { return mData[v.idx.value]; }
PropT& operator[](vertex_index v) { return mData[v.value]; }
PropT const& operator[](vertex_index v) const { return mData[v.value]; }
PropT* data() { return mData.data(); }
PropT const* data() const { return mData.data(); }
size_t size() const;
// methods
public:
void clear(PropT const& value);
void clear();
// data
private:
std::vector<PropT> mData;
PropT mDefaultValue;
void on_resize(size_t newSize) override { mData.resize(newSize, mDefaultValue); }
// ctor
private:
vertex_property(Mesh const* mesh, PropT const& def_value);
friend class vertex_collection;
};
template <typename PropT>
struct face_property : face_property_base
{
// data access
public:
PropT& operator[](face_handle v) { return mData[v.idx.value]; }
PropT const& operator[](face_handle v) const { return mData[v.idx.value]; }
PropT& operator[](face_index v) { return mData[v.value]; }
PropT const& operator[](face_index v) const { return mData[v.value]; }
PropT* data() { return mData.data(); }
PropT const* data() const { return mData.data(); }
size_t size() const;
// methods
public:
void clear(PropT const& value);
void clear();
// data
private:
std::vector<PropT> mData;
PropT mDefaultValue;
void on_resize(size_t newSize) override { mData.resize(newSize, mDefaultValue); }