Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Philip Trettner
polymesh
Commits
8f885d5d
Commit
8f885d5d
authored
Jul 23, 2018
by
Philip Trettner
Browse files
working on SOA refactoring
parent
befd1997
Changes
4
Hide whitespace changes
Inline
Side-by-side
Readme.md
View file @
8f885d5d
...
...
@@ -29,4 +29,8 @@ Best used with glm and glow.
*
primitive sort functions, better remap function, cache optimization
*
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)
*
primitive collection sort and sort_by functions
\ No newline at end of file
*
primitive collection sort and sort_by functions
Low-level TODO:
*
face_of(opposite(h)) -> opposite_face_of
src/polymesh/Mesh.hh
View file @
8f885d5d
...
...
@@ -30,6 +30,8 @@ using SharedMesh = std::shared_ptr<Mesh>;
* * `for (auto h : <primitive>())` iterates over _all_ primitives, including invalid ones
* (`for (auto h : valid_<primitive>())` skips over invalid ones)
*
* * low-level operations can be performed by accessing low_level_api(mesh)
*
* For more concept documents see:
* * http://kaba.hilvi.org/homepage/blog/halfedge/halfedge.htm
* * https://www.openmesh.org/media/Documentations/OpenMesh-Doc-Latest/a03930.html
...
...
@@ -145,6 +147,8 @@ private:
/// Does NOT invalidate iterators!
vertex_index
add_vertex
();
/// Allocates a new vertex
vertex_index
alloc_vertex
();
/// Allocates a new face
face_index
alloc_face
();
/// Allocates a new edge
...
...
@@ -223,9 +227,36 @@ private:
void
fix_boundary_state_of_vertices
(
face_index
f_idx
);
// attributes
bool
is_free
(
halfedge_index
idx
)
const
;
bool
is_boundary
(
vertex_index
idx
)
const
;
bool
is_boundary
(
halfedge_index
idx
)
const
;
bool
is_removed
(
vertex_index
idx
)
const
;
bool
is_removed
(
face_index
idx
)
const
;
bool
is_removed
(
edge_index
idx
)
const
;
bool
is_removed
(
halfedge_index
idx
)
const
;
bool
is_isolated
(
vertex_index
idx
)
const
;
vertex_index
&
to_vertex_of
(
halfedge_index
idx
);
face_index
&
face_of
(
halfedge_index
idx
);
halfedge_index
&
next_halfedge_of
(
halfedge_index
idx
);
halfedge_index
&
prev_halfedge_of
(
halfedge_index
idx
);
halfedge_index
&
halfedge_of
(
face_index
idx
);
halfedge_index
&
outgoing_halfedge_of
(
vertex_index
idx
);
vertex_index
to_vertex_of
(
halfedge_index
idx
)
const
;
face_index
face_of
(
halfedge_index
idx
)
const
;
halfedge_index
next_halfedge_of
(
halfedge_index
idx
)
const
;
halfedge_index
prev_halfedge_of
(
halfedge_index
idx
)
const
;
halfedge_index
halfedge_of
(
face_index
idx
)
const
;
halfedge_index
outgoing_halfedge_of
(
vertex_index
idx
)
const
;
void
set_removed
(
vertex_index
idx
);
void
set_removed
(
face_index
idx
);
void
set_removed
(
edge_index
idx
);
/// Returns the opposite of a given valid half-edge
halfedge_index
opposite
(
halfedge_index
he
)
const
;
...
...
@@ -255,10 +286,8 @@ private:
/// returns a half-edge belonging to an edge
halfedge_index
halfedge_of
(
edge_index
idx
,
int
i
)
const
{
return
halfedge_index
((
idx
.
value
<<
1
)
+
i
);
}
/// returns the vertex that this half-edge is pointing to
vertex_index
to_vertex_of
(
halfedge_index
idx
)
const
{
return
halfedge
(
idx
).
to_vertex
;
}
/// returns the vertex that this half-edge is leaving from
vertex_index
from_vertex_of
(
halfedge_index
idx
)
const
{
return
halfedge
(
opposite
(
idx
)).
to_vertex
;
}
vertex_index
&
from_vertex_of
(
halfedge_index
idx
);
vertex_index
from_vertex_of
(
halfedge_index
idx
)
const
;
/// applies an index remapping to all face indices (p[curr_idx] = new_idx)
void
permute_faces
(
std
::
vector
<
int
>
const
&
p
);
...
...
@@ -312,10 +341,19 @@ private:
// internal primitives
private:
std
::
vector
<
face_info
>
mFaces
;
std
::
vector
<
vertex_info
>
mVertices
;
std
::
vector
<
halfedge_info
>
mHalfedges
;
// std::vector<face_info> mFaces;
// std::vector<vertex_info> mVertices;
// std::vector<halfedge_info> mHalfedges;
std
::
vector
<
halfedge_index
>
mFaceToHalfedge
;
std
::
vector
<
halfedge_index
>
mVertexToOutgoingHalfedge
;
std
::
vector
<
vertex_index
>
mHalfedgeToVertex
;
std
::
vector
<
face_index
>
mHalfedgeToFace
;
std
::
vector
<
halfedge_index
>
mHalfedgeToNextHalfedge
;
std
::
vector
<
halfedge_index
>
mHalfedgeToPrevHalfedge
;
/*
struct face_info &face(face_index i)
{
assert(i.is_valid() && i.value < size_all_faces());
...
...
@@ -356,6 +394,7 @@ private:
assert(i.is_valid() && i.value < size_all_edges());
return mHalfedges[(i.value << 1) + h];
}
*/
// internal state
private:
...
...
@@ -431,6 +470,8 @@ private:
friend
struct
edge_collection
;
template
<
class
iterator
>
friend
struct
halfedge_collection
;
friend
struct
low_level_api
;
};
}
...
...
src/polymesh/impl/impl_mesh.hh
View file @
8f885d5d
...
...
@@ -6,13 +6,15 @@
namespace
polymesh
{
inline
vertex_index
Mesh
::
add_vertex
()
inline
vertex_index
Mesh
::
add_vertex
()
{
return
alloc_vertex
();
}
inline
vertex_index
Mesh
::
alloc_vertex
()
{
auto
idx
=
vertex_index
(
(
int
)
mV
ertices
.
size
());
mVert
ices
.
push_back
(
vertex_info
());
auto
idx
=
vertex_index
(
size_all_v
ertices
());
mVert
exToOutgoingHalfedge
.
push_back
(
halfedge_index
::
invalid
());
// notify attributes
auto
vCnt
=
(
int
)
mV
ertices
.
size
();
auto
vCnt
=
size_all_v
ertices
();
for
(
auto
p
=
mVertexAttrs
;
p
;
p
=
p
->
mNextAttribute
)
p
->
resize
(
vCnt
,
false
);
...
...
@@ -21,11 +23,11 @@ inline vertex_index Mesh::add_vertex()
inline
face_index
Mesh
::
alloc_face
()
{
auto
idx
=
face_index
(
(
int
)
mFaces
.
size
());
mFace
s
.
push_back
(
face_info
());
auto
idx
=
face_index
(
size_all_faces
());
mFace
ToHalfedge
.
push_back
(
halfedge_index
::
invalid
());
// notify attributes
auto
fCnt
=
(
int
)
mFaces
.
size
();
auto
fCnt
=
size_all_faces
();
for
(
auto
p
=
mFaceAttrs
;
p
;
p
=
p
->
mNextAttribute
)
p
->
resize
(
fCnt
,
false
);
...
...
@@ -34,13 +36,20 @@ inline face_index Mesh::alloc_face()
inline
edge_index
Mesh
::
alloc_edge
()
{
auto
idx
=
edge_index
((
int
)
mHalfedges
.
size
()
>>
1
);
mHalfedges
.
push_back
(
halfedge_info
());
mHalfedges
.
push_back
(
halfedge_info
());
auto
idx
=
edge_index
(
size_all_edges
());
mHalfedgeToFace
.
push_back
(
face_index
::
invalid
());
mHalfedgeToFace
.
push_back
(
face_index
::
invalid
());
mHalfedgeToVertex
.
push_back
(
vertex_index
::
invalid
());
mHalfedgeToVertex
.
push_back
(
vertex_index
::
invalid
());
mHalfedgeToNextHalfedge
.
push_back
(
halfedge_index
::
invalid
());
mHalfedgeToNextHalfedge
.
push_back
(
halfedge_index
::
invalid
());
mHalfedgeToPrevHalfedge
.
push_back
(
halfedge_index
::
invalid
());
mHalfedgeToPrevHalfedge
.
push_back
(
halfedge_index
::
invalid
());
// notify attributes
auto
hCnt
=
(
int
)
mH
alfedges
.
size
();
auto
eCnt
=
(
int
)
mHalfedges
.
size
()
>>
1
;
auto
hCnt
=
size_all_h
alfedges
();
auto
eCnt
=
size_all_edges
()
;
for
(
auto
p
=
mEdgeAttrs
;
p
;
p
=
p
->
mNextAttribute
)
p
->
resize
(
eCnt
,
false
);
for
(
auto
p
=
mHalfedgeAttrs
;
p
;
p
=
p
->
mNextAttribute
)
...
...
@@ -77,7 +86,7 @@ inline face_index Mesh::add_face(const halfedge_index *half_loop, int vcnt)
{
assert
(
vcnt
>=
3
&&
"no support for less-than-triangular faces"
);
auto
fidx
=
face_index
((
int
)
mFaces
.
size
()
);
auto
fidx
=
alloc_face
(
);
// ensure that half-edges are adjacent at each vertex
for
(
auto
i
=
0
;
i
<
vcnt
;
++
i
)
...
...
@@ -88,21 +97,21 @@ inline face_index Mesh::add_face(const halfedge_index *half_loop, int vcnt)
// half-edge must form a chain
assert
(
to_vertex_of
(
h0
)
==
from_vertex_of
(
h1
)
&&
"half-edges do not form a chain"
);
// half-edge must be free, i.e. allow a new polygon
assert
(
halfedge
(
h0
).
is_free
()
&&
"half-edge already contains a face"
);
assert
(
is_free
(
h0
)
&&
"half-edge already contains a face"
);
// make them adjacent
make_adjacent
(
h0
,
h1
);
// link face
halfedge
(
h0
).
face
=
fidx
;
face_of
(
h0
)
=
fidx
;
}
// fix boundary states
for
(
auto
i
=
0
;
i
<
vcnt
;
++
i
)
{
auto
h
=
half_loop
[
i
];
auto
v
=
halfedge
(
h
).
to_vertex
;
auto
f
=
halfedge
(
opposite
(
h
))
.
face
;
auto
v
=
to_vertex
_of
(
h
)
;
auto
f
=
face_of
(
opposite
(
h
));
// fix vertex
fix_boundary_state_of
(
v
);
...
...
@@ -113,18 +122,11 @@ inline face_index Mesh::add_face(const halfedge_index *half_loop, int vcnt)
}
// set up face data
face_info
f
;
f
.
halfedge
=
half_loop
[
0
];
mFaces
.
push_back
(
f
);
halfedge_of
(
fidx
)
=
half_loop
[
0
];
// fix new face
fix_boundary_state_of
(
fidx
);
// notify attributes
auto
fCnt
=
(
int
)
mFaces
.
size
();
for
(
auto
p
=
mFaceAttrs
;
p
;
p
=
p
->
mNextAttribute
)
p
->
resize
(
fCnt
,
false
);
return
fidx
;
}
...
...
@@ -288,17 +290,15 @@ inline halfedge_index Mesh::add_or_get_halfedge(halfedge_index h_from, halfedge_
auto
e
=
add_or_get_edge
(
h_from
,
h_to
);
auto
h0
=
halfedge_of
(
e
,
0
);
auto
h1
=
halfedge_of
(
e
,
1
);
return
halfedge
(
h_from
)
.
next_halfedge
==
h0
?
h0
:
h1
;
return
next_
halfedge
_of
(
h_from
)
==
h0
?
h0
:
h1
;
}
inline
void
Mesh
::
make_adjacent
(
halfedge_index
he_in
,
halfedge_index
he_out
)
{
// see http://kaba.hilvi.org/homepage/blog/halfedge/halfedge.htm ::makeAdjacent
auto
&
in
=
halfedge
(
he_in
);
auto
&
out
=
halfedge
(
he_out
);
auto
he_b
=
in
.
next_halfedge
;
auto
he_d
=
out
.
prev_halfedge
;
auto
he_b
=
next_halfedge
_of
(
he_in
)
;
auto
he_d
=
prev_halfedge
_of
(
he_out
)
;
// already correct
if
(
he_b
==
he_out
)
...
...
@@ -308,56 +308,44 @@ inline void Mesh::make_adjacent(halfedge_index he_in, halfedge_index he_out)
auto
he_g
=
find_free_incident
(
opposite
(
he_out
),
he_in
);
assert
(
he_g
.
is_valid
());
// unable to make adjacent
auto
&
b
=
halfedge
(
he_b
);
auto
&
d
=
halfedge
(
he_d
);
auto
&
g
=
halfedge
(
he_g
);
auto
he_h
=
g
.
next_halfedge
;
auto
&
h
=
halfedge
(
he_h
);
auto
he_h
=
next_halfedge_of
(
he_g
);
// properly rewire
in
.
next_halfedge
=
he_out
;
out
.
prev_halfedge
=
he_in
;
g
.
next_halfedge
=
he_b
;
b
.
prev_halfedge
=
he_g
;
d
.
next_halfedge
=
he_h
;
h
.
prev_halfedge
=
he_d
;
connect_prev_next
(
he_in
,
he_out
);
connect_prev_next
(
he_g
,
he_b
);
connect_prev_next
(
he_d
,
he_h
);
}
inline
void
Mesh
::
remove_face
(
face_index
f_idx
)
{
auto
&
f
=
face
(
f_idx
);
assert
(
f
.
halfedge
.
is_valid
());
assert
(
!
is_removed
(
f_idx
));
auto
he_begin
=
f
.
halfedge
;
auto
he_begin
=
halfedge
_of
(
f_idx
)
;
auto
he
=
he_begin
;
do
{
auto
&
h
=
halfedge
(
he
);
assert
(
h
.
face
==
f_idx
);
assert
(
face_of
(
h
)
==
f_idx
);
// set half-edge face to invalid
h
.
face
=
face_index
::
invalid
();
face
_of
(
he
)
=
face_index
::
invalid
();
// fix outgoing vertex half-edge
// (vertex correctly reports is_boundary)
vertex
(
from_vertex_of
(
he
))
.
outgoing_halfedge
=
he
;
outgoing_halfedge_of
(
from_vertex_of
(
he
))
=
he
;
// fix opposite face half-edge
auto
ohe
=
opposite
(
he
);
auto
of
=
halfedge
(
ohe
).
face
;
auto
of
=
face_of
(
ohe
)
;
if
(
of
.
is_valid
())
face
(
of
).
halfedge
=
ohe
;
halfedge
_of
(
of
)
=
ohe
;
// advance
he
=
h
.
next_halfedge
;
he
=
next_halfedge
_of
(
he
)
;
}
while
(
he
!=
he_begin
);
// mark removed
// (at the end!)
f
.
set_removed
();
set_removed
(
f_idx
);
// bookkeeping
mRemovedFaces
++
;
...
...
@@ -430,15 +418,14 @@ inline void Mesh::remove_edge(edge_index e_idx)
inline
void
Mesh
::
remove_vertex
(
vertex_index
v_idx
)
{
auto
&
v
=
vertex
(
v_idx
);
assert
(
v
.
is_valid
());
assert
(
!
is_removed
(
v_idx
));
// remove all outgoing edges
while
(
!
v
.
is_isolated
())
remove_edge
(
edge_of
(
v
.
outgoing_halfedge
));
while
(
!
is_isolated
(
v_idx
))
remove_edge
(
edge_of
(
outgoing_halfedge
_of
(
v_idx
)
));
// mark removed
v
.
set_removed
();
set_removed
(
v_idx
);
// bookkeeping
mRemovedVertices
++
;
...
...
@@ -447,60 +434,53 @@ inline void Mesh::remove_vertex(vertex_index v_idx)
inline
void
Mesh
::
fix_boundary_state_of
(
vertex_index
v_idx
)
{
auto
&
v
=
vertex
(
v_idx
);
assert
(
!
v
.
is_isolated
());
assert
(
!
is_isolated
(
v_idx
));
auto
he_begin
=
v
.
outgoing_halfedge
;
auto
he_begin
=
outgoing_halfedge
_of
(
v_idx
)
;
auto
he
=
he_begin
;
do
{
// if half-edge is boundary, set it
if
(
halfedge
(
he
).
is_free
())
if
(
is_free
(
he
))
{
v
.
outgoing_halfedge
=
he
;
outgoing_halfedge
_of
(
v_idx
)
=
he
;
return
;
}
// advance
he
=
halfedge
(
opposite
(
he
))
.
next_halfedge
;
he
=
next_
halfedge
_of
(
opposite
(
he
));
}
while
(
he
!=
he_begin
);
}
inline
void
Mesh
::
fix_boundary_state_of
(
face_index
f_idx
)
{
auto
&
f
=
face
(
f_idx
);
auto
he_begin
=
f
.
halfedge
;
auto
he_begin
=
halfedge_of
(
f_idx
);
auto
he
=
he_begin
;
do
{
// if half-edge is boundary, set it
if
(
halfedg
e
(
opposite
(
he
))
.
is_free
()
)
if
(
is_fre
e
(
opposite
(
he
)))
{
f
.
halfedge
=
he
;
halfedge
_of
(
f_idx
)
=
he
;
return
;
}
// advance
he
=
halfedge
(
he
).
next_halfedge
;
he
=
next_halfedge
_of
(
he
)
;
}
while
(
he
!=
he_begin
);
}
inline
void
Mesh
::
fix_boundary_state_of_vertices
(
face_index
f_idx
)
{
auto
&
f
=
face
(
f_idx
);
auto
he_begin
=
f
.
halfedge
;
auto
he_begin
=
halfedge_of
(
f_idx
);
auto
he
=
he_begin
;
do
{
auto
&
h_ref
=
halfedge
(
he
);
// fix vertex
fix_boundary_state_of
(
h_ref
.
to_vertex
);
fix_boundary_state_of
(
to_vertex
_of
(
he
)
);
// advance
he
=
h_ref
.
next_halfedge
;
he
=
next_halfedge
_of
(
he
)
;
}
while
(
he
!=
he_begin
);
}
...
...
@@ -511,15 +491,14 @@ inline halfedge_index Mesh::find_free_incident(halfedge_index in_begin, halfedge
auto
he
=
in_begin
;
do
{
auto
const
&
h
=
halfedge
(
he
);
assert
(
h
.
to_vertex
==
halfedge
(
in_end
).
to_vertex
);
assert
(
to_vertex_of
(
he
)
==
to_vertex
(
in_end
));
// free? found one!
if
(
h
.
is_free
())
if
(
is_free
(
he
))
return
he
;
// next half-edge of vertex
he
=
opposite
(
h
.
next_halfedge
);
he
=
opposite
(
next_halfedge
_of
(
he
)
);
}
while
(
he
!=
in_end
);
return
halfedge_index
::
invalid
();
...
...
@@ -527,27 +506,25 @@ inline halfedge_index Mesh::find_free_incident(halfedge_index in_begin, halfedge
inline
halfedge_index
Mesh
::
find_free_incident
(
vertex_index
v
)
const
{
auto
in_begin
=
opposite
(
vertex
(
v
).
outgoing_halfedge
);
auto
in_begin
=
opposite
(
outgoing_halfedge
_of
(
v
)
);
return
find_free_incident
(
in_begin
,
in_begin
);
}
inline
halfedge_index
Mesh
::
find_halfedge
(
vertex_index
from
,
vertex_index
to
)
const
{
auto
he_begin
=
vertex
(
from
).
outgoing_halfedge
;
auto
he_begin
=
outgoing_halfedge
_of
(
from
)
;
if
(
!
he_begin
.
is_valid
())
return
halfedge_index
::
invalid
();
// isolated vertex
auto
he
=
he_begin
;
do
{
auto
const
&
h
=
halfedge
(
he
);
// found?
if
(
h
.
to_vertex
==
to
)
if
(
to_vertex
_of
(
he
)
==
to
)
return
he
;
// advance
he
=
halfedge
(
opposite
(
he
))
.
next_halfedge
;
he
=
next_
halfedge
_of
(
opposite
(
he
));
}
while
(
he
!=
he_begin
);
...
...
@@ -556,92 +533,126 @@ inline halfedge_index Mesh::find_halfedge(vertex_index from, vertex_index to) co
inline
bool
Mesh
::
is_boundary
(
vertex_index
idx
)
const
{
auto
const
&
v
=
vertex
(
idx
);
return
v
.
outgoing_halfedge
.
is_valid
()
&&
is_boundary
(
v
.
outgoing_halfedge
);
auto
oh
=
outgoing_halfedge_of
(
idx
);
return
oh
.
is_valid
()
&&
is_boundary
(
oh
);
}
inline
bool
Mesh
::
is_free
(
halfedge_index
idx
)
const
{
return
face_of
(
idx
).
is_invalid
();
}
inline
bool
Mesh
::
is_boundary
(
halfedge_index
idx
)
const
{
return
is_free
(
idx
);
}
inline
bool
Mesh
::
is_isolated
(
vertex_index
idx
)
const
{
return
outgoing_halfedge_of
(
idx
).
is_invalid
();
}
inline
bool
Mesh
::
is_removed
(
vertex_index
idx
)
const
{
return
outgoing_halfedge_of
(
idx
).
value
>=
-
1
;
}
inline
bool
Mesh
::
is_removed
(
face_index
idx
)
const
{
return
halfedge_of
(
idx
).
is_invalid
();
}
inline
bool
Mesh
::
is_removed
(
edge_index
idx
)
const
{
return
to_vertex_of
(
halfedge_of
(
idx
,
0
)).
is_invalid
();
}
inline
bool
Mesh
::
is_removed
(
halfedge_index
idx
)
const
{
return
to_vertex_of
(
idx
).
is_invalid
();
}
inline
void
Mesh
::
set_removed
(
vertex_index
idx
)
{
outgoing_halfedge_of
(
idx
)
=
halfedge_index
::
invalid
();
}
inline
void
Mesh
::
set_removed
(
face_index
idx
)
{
halfedge_of
(
idx
)
=
halfedge_index
::
invalid
();
}
inline
void
Mesh
::
set_removed
(
edge_index
idx
)
{
to_vertex_of
(
halfedge_of
(
idx
,
0
))
=
vertex_index
::
invalid
();
to_vertex_of
(
halfedge_of
(
idx
,
1
))
=
vertex_index
::
invalid
();
}
inline
bool
Mesh
::
is_boundary
(
halfedge_index
idx
)
const
{
return
halfedge
(
idx
).
is_free
();
}
inline
face_index
&
Mesh
::
face_of
(
halfedge_index
idx
)
{
return
mHalfedgeToFace
[(
int
)
idx
];
}
inline
vertex_index
&
Mesh
::
to_vertex_of
(
halfedge_index
idx
)
{
return
mHalfedgeToVertex
[(
int
)
idx
];
}
inline
halfedge_index
&
Mesh
::
next_halfedge_of
(
halfedge_index
idx
)
{
return
mHalfedgeToNextHalfedge
[(
int
)
idx
];
}
inline
halfedge_index
&
Mesh
::
prev_halfedge_of
(
halfedge_index
idx
)
{
return
mHalfedgeToPrevHalfedge
[(
int
)
idx
];
}
inline
halfedge_index
&
Mesh
::
halfedge_of
(
face_index
idx
)
{
return
mFaceToHalfedge
[(
int
)
idx
];
}
inline
halfedge_index
&
Mesh
::
outgoing_halfedge_of
(
vertex_index
idx
)
{
return
mVertexToOutgoingHalfedge
[(
int
)
idx
];
}
inline
face_index
Mesh
::
face_of
(
halfedge_index
idx
)
const
{
return
mHalfedgeToFace
[(
int
)
idx
];
}
inline
vertex_index
Mesh
::
to_vertex_of
(
halfedge_index
idx
)
const
{
return
mHalfedgeToVertex
[(
int
)
idx
];
}
inline
halfedge_index
Mesh
::
next_halfedge_of
(
halfedge_index
idx
)
const
{
return
mHalfedgeToNextHalfedge
[(
int
)
idx
];
}
inline
halfedge_index
Mesh
::
prev_halfedge_of
(
halfedge_index
idx
)
const
{
return
mHalfedgeToPrevHalfedge
[(
int
)
idx
];
}
inline
halfedge_index
Mesh
::
halfedge_of
(
face_index
idx
)
const
{
return
mFaceToHalfedge
[(
int
)
idx
];
}
inline
halfedge_index
Mesh
::
outgoing_halfedge_of
(
vertex_index
idx
)
const
{
return
mVertexToOutgoingHalfedge
[(
int
)
idx
];
}
inline
halfedge_index
Mesh
::
opposite
(
halfedge_index
he
)
const
{
return
halfedge_index
(
he
.
value
^
1
);
}
inline
vertex_index
&
Mesh
::
from_vertex_of
(
halfedge_index
idx
)
{
return
to_vertex_of
(
opposite
(
idx
));
}
inline
vertex_index
Mesh
::
from_vertex_of
(
halfedge_index
idx
)
const
{
return
to_vertex_of
(
opposite
(
idx
));
}
inline
vertex_index
Mesh
::
next_valid_idx_from
(
vertex_index
idx
)
const
{
for
(
auto
i
=
idx
.
value
;
i
<
(
int
)
mVertices
.
size
();
++
i
)
if
(
mVertices
[
i
].
is_valid
())
return
vertex_index
(
i
);
return
vertex_index
(
size_all_vertices
());
// end index
auto
s
=
size_all_vertices
();
auto
i
=
idx
;
while
(
i
.
value
<
s
&&
is_removed
(
i
))
i
.
value
++
;
return
i
;
}
inline
vertex_index
Mesh
::
prev_valid_idx_from
(
vertex_index
idx
)
const
{
for
(
auto
i
=
idx
.
value
;
i
>=
0
;
--
i
)
if
(
mVertices
[
i
].
is_vali
d
())
return
vertex_index
(
i
)
;
return
{};
// invalid
auto
i
=
idx
;
while
(
i
.
value
>=
0
&&
is_remove
d
(
i
))
i
.
value
--
;
return
i
;
}
inline
edge_index
Mesh
::
next_valid_idx_from
(
edge_index
idx
)
const
{
for
(
auto
i
=
idx
.
value
<<
1
;
i
<
(
int
)
mHalfedges
.
size
();
i
+=
2
)
if
(
mHalfedges
[
i
].
is_valid
())
return
edge_index
(
i
>>
1
);
return
edge_index
(
size_all_edges
());
// end index
auto
s
=
size_all_edges
();
auto
i
=
idx
;
while
(
i
.
value
<
s
&&
is_removed
(
i
))
i
.
value
++
;
return
i
;
}
inline
edge_index
Mesh
::
prev_valid_idx_from
(
edge_index
idx
)
const
{
for
(
auto
i
=
idx
.
value
<<
1
;
i
>=
0
;
i
-=
2
)
if
(
mHalfedges
[
i
].
is_vali
d
())
return
edge_index
(
i
>>
1
)
;
return
{};
// invalid
auto
i
=
idx
;
while
(
i
.
value
>=
0
&&
is_remove
d
(
i
))
i
.
value
--
;
return
i
;
}
inline
face_index
Mesh
::
next_valid_idx_from
(
face_index
idx
)
const
{
for
(
auto
i
=
idx
.
value
;
i
<
(
int
)
mFaces
.
size
();
++
i
)
if
(
mFaces
[
i
].
is_valid
())
return
face_index
(
i
);
return
face_index
(
size_all_faces
());
// end index
auto
s
=
size_all_faces
();
auto
i
=
idx
;
while
(
i
.
value
<
s
&&
is_removed
(
i
))
i
.
value
++
;
return
i
;
}
inline
face_index
Mesh
::
prev_valid_idx_from
(
face_index
idx
)
const
{
for
(
auto
i
=
idx
.
value
;
i
>=
0
;
--
i
)
if
(
mFaces
[
i
].
is_vali
d
())
return
face_index
(
i
)
;
return
{};
// invalid
auto
i
=
idx
;
while
(
i
.
value
>=
0
&&
is_remove
d
(
i
))
i
.
value
--
;
return
i
;
}
inline
halfedge_index
Mesh
::
next_valid_idx_from
(
halfedge_index
idx
)
const
{
for
(
auto
i
=
idx
.
value
;
i
<
(
int
)
mHalfedges
.
size
();
++
i
)
if
(
mHalfedges
[
i
].
is_valid
())
return
halfedge_index
(
i
);
return
halfedge_index
(
size_all_halfedges
());
// end index
auto
s
=
size_all_halfedges
();
auto
i
=
idx
;
while
(
i
.
value
<
s
&&
is_removed
(
i
))
i
.
value
++
;
return
i
;
}
inline
halfedge_index
Mesh
::
prev_valid_idx_from
(
halfedge_index
idx
)
const
{
for
(
auto
i
=
idx
.
value
;
i
>=
0
;
--
i
)