Converted tabs to four spaces
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
|
||||
namespace triangle_stripper {
|
||||
|
||||
namespace detail {
|
||||
namespace detail {
|
||||
|
||||
|
||||
|
||||
@@ -27,26 +27,26 @@ namespace triangle_stripper {
|
||||
class cache_simulator
|
||||
{
|
||||
public:
|
||||
cache_simulator();
|
||||
cache_simulator();
|
||||
|
||||
void clear();
|
||||
void resize(size_t Size);
|
||||
void reset();
|
||||
void push_cache_hits(bool Enabled = true);
|
||||
size_t size() const;
|
||||
void clear();
|
||||
void resize(size_t Size);
|
||||
void reset();
|
||||
void push_cache_hits(bool Enabled = true);
|
||||
size_t size() const;
|
||||
|
||||
void push(index i, bool CountCacheHit = false);
|
||||
void merge(const cache_simulator & Backward, size_t PossibleOverlap);
|
||||
void push(index i, bool CountCacheHit = false);
|
||||
void merge(const cache_simulator & Backward, size_t PossibleOverlap);
|
||||
|
||||
void reset_hitcount();
|
||||
size_t hitcount() const;
|
||||
void reset_hitcount();
|
||||
size_t hitcount() const;
|
||||
|
||||
protected:
|
||||
typedef std::deque<index> indices_deque;
|
||||
typedef std::deque<index> indices_deque;
|
||||
|
||||
indices_deque m_Cache;
|
||||
size_t m_NbHits;
|
||||
bool m_PushHits;
|
||||
indices_deque m_Cache;
|
||||
size_t m_NbHits;
|
||||
bool m_PushHits;
|
||||
};
|
||||
|
||||
|
||||
@@ -58,8 +58,8 @@ protected:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline cache_simulator::cache_simulator()
|
||||
: m_NbHits(0),
|
||||
m_PushHits(true)
|
||||
: m_NbHits(0),
|
||||
m_PushHits(true)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -67,84 +67,84 @@ inline cache_simulator::cache_simulator()
|
||||
|
||||
inline void cache_simulator::clear()
|
||||
{
|
||||
reset_hitcount();
|
||||
m_Cache.clear();
|
||||
reset_hitcount();
|
||||
m_Cache.clear();
|
||||
}
|
||||
|
||||
|
||||
inline void cache_simulator::resize(const size_t Size)
|
||||
{
|
||||
m_Cache.resize(Size, (std::numeric_limits<index>::max)());
|
||||
m_Cache.resize(Size, (std::numeric_limits<index>::max)());
|
||||
}
|
||||
|
||||
|
||||
inline void cache_simulator::reset()
|
||||
{
|
||||
std::fill(m_Cache.begin(), m_Cache.end(), (std::numeric_limits<index>::max)());
|
||||
reset_hitcount();
|
||||
std::fill(m_Cache.begin(), m_Cache.end(), (std::numeric_limits<index>::max)());
|
||||
reset_hitcount();
|
||||
}
|
||||
|
||||
|
||||
inline void cache_simulator::push_cache_hits(bool Enabled)
|
||||
{
|
||||
m_PushHits = Enabled;
|
||||
m_PushHits = Enabled;
|
||||
}
|
||||
|
||||
|
||||
inline size_t cache_simulator::size() const
|
||||
{
|
||||
return m_Cache.size();
|
||||
return m_Cache.size();
|
||||
}
|
||||
|
||||
|
||||
inline void cache_simulator::push(const index i, const bool CountCacheHit)
|
||||
{
|
||||
if (CountCacheHit || m_PushHits) {
|
||||
if (CountCacheHit || m_PushHits) {
|
||||
|
||||
if (std::find(m_Cache.begin(), m_Cache.end(), i) != m_Cache.end()) {
|
||||
if (std::find(m_Cache.begin(), m_Cache.end(), i) != m_Cache.end()) {
|
||||
|
||||
// Should we count the cache hits?
|
||||
if (CountCacheHit)
|
||||
++m_NbHits;
|
||||
|
||||
// Should we not push the index into the cache if it's a cache hit?
|
||||
if (! m_PushHits)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Manage the indices cache as a FIFO structure
|
||||
m_Cache.push_front(i);
|
||||
m_Cache.pop_back();
|
||||
// Should we count the cache hits?
|
||||
if (CountCacheHit)
|
||||
++m_NbHits;
|
||||
|
||||
// Should we not push the index into the cache if it's a cache hit?
|
||||
if (! m_PushHits)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Manage the indices cache as a FIFO structure
|
||||
m_Cache.push_front(i);
|
||||
m_Cache.pop_back();
|
||||
}
|
||||
|
||||
|
||||
inline void cache_simulator::merge(const cache_simulator & Backward, const size_t PossibleOverlap)
|
||||
{
|
||||
const size_t Overlap = (std::min)(PossibleOverlap, size());
|
||||
const size_t Overlap = (std::min)(PossibleOverlap, size());
|
||||
|
||||
for (size_t i = 0; i < Overlap; ++i)
|
||||
push(Backward.m_Cache[i], true);
|
||||
for (size_t i = 0; i < Overlap; ++i)
|
||||
push(Backward.m_Cache[i], true);
|
||||
|
||||
m_NbHits += Backward.m_NbHits;
|
||||
m_NbHits += Backward.m_NbHits;
|
||||
}
|
||||
|
||||
|
||||
inline void cache_simulator::reset_hitcount()
|
||||
{
|
||||
m_NbHits = 0;
|
||||
m_NbHits = 0;
|
||||
}
|
||||
|
||||
|
||||
inline size_t cache_simulator::hitcount() const
|
||||
{
|
||||
return m_NbHits;
|
||||
return m_NbHits;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
} // namespace triangle_stripper
|
||||
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
namespace triangle_stripper
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
void make_connectivity_graph(graph_array<triangle> & Triangles, const indices & Indices);
|
||||
void make_connectivity_graph(graph_array<triangle> & Triangles, const indices & Indices);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
namespace triangle_stripper {
|
||||
|
||||
namespace detail {
|
||||
namespace detail {
|
||||
|
||||
|
||||
|
||||
@@ -32,116 +32,116 @@ class graph_array
|
||||
{
|
||||
public:
|
||||
|
||||
class arc;
|
||||
class node;
|
||||
class arc;
|
||||
class node;
|
||||
|
||||
// New types
|
||||
typedef size_t nodeid;
|
||||
typedef nodetype value_type;
|
||||
typedef std::vector<node> node_vector;
|
||||
typedef typename node_vector::iterator node_iterator;
|
||||
typedef typename node_vector::const_iterator const_node_iterator;
|
||||
typedef typename node_vector::reverse_iterator node_reverse_iterator;
|
||||
typedef typename node_vector::const_reverse_iterator const_node_reverse_iterator;
|
||||
// New types
|
||||
typedef size_t nodeid;
|
||||
typedef nodetype value_type;
|
||||
typedef std::vector<node> node_vector;
|
||||
typedef typename node_vector::iterator node_iterator;
|
||||
typedef typename node_vector::const_iterator const_node_iterator;
|
||||
typedef typename node_vector::reverse_iterator node_reverse_iterator;
|
||||
typedef typename node_vector::const_reverse_iterator const_node_reverse_iterator;
|
||||
|
||||
typedef graph_array<nodetype> graph_type;
|
||||
|
||||
typedef graph_array<nodetype> graph_type;
|
||||
|
||||
|
||||
// graph_array::arc class
|
||||
class arc
|
||||
{
|
||||
public:
|
||||
node_iterator terminal() const;
|
||||
// graph_array::arc class
|
||||
class arc
|
||||
{
|
||||
public:
|
||||
node_iterator terminal() const;
|
||||
|
||||
protected:
|
||||
friend class graph_array<nodetype>;
|
||||
protected:
|
||||
friend class graph_array<nodetype>;
|
||||
|
||||
arc(node_iterator Terminal);
|
||||
|
||||
node_iterator m_Terminal;
|
||||
};
|
||||
arc(node_iterator Terminal);
|
||||
|
||||
node_iterator m_Terminal;
|
||||
};
|
||||
|
||||
|
||||
// New types
|
||||
typedef std::vector<arc> arc_list;
|
||||
typedef typename arc_list::iterator out_arc_iterator;
|
||||
typedef typename arc_list::const_iterator const_out_arc_iterator;
|
||||
// New types
|
||||
typedef std::vector<arc> arc_list;
|
||||
typedef typename arc_list::iterator out_arc_iterator;
|
||||
typedef typename arc_list::const_iterator const_out_arc_iterator;
|
||||
|
||||
|
||||
// graph_array::node class
|
||||
class node
|
||||
{
|
||||
public:
|
||||
void mark();
|
||||
void unmark();
|
||||
bool marked() const;
|
||||
// graph_array::node class
|
||||
class node
|
||||
{
|
||||
public:
|
||||
void mark();
|
||||
void unmark();
|
||||
bool marked() const;
|
||||
|
||||
bool out_empty() const;
|
||||
size_t out_size() const;
|
||||
bool out_empty() const;
|
||||
size_t out_size() const;
|
||||
|
||||
out_arc_iterator out_begin();
|
||||
out_arc_iterator out_end();
|
||||
const_out_arc_iterator out_begin() const;
|
||||
const_out_arc_iterator out_end() const;
|
||||
out_arc_iterator out_begin();
|
||||
out_arc_iterator out_end();
|
||||
const_out_arc_iterator out_begin() const;
|
||||
const_out_arc_iterator out_end() const;
|
||||
|
||||
value_type & operator * ();
|
||||
value_type * operator -> ();
|
||||
const value_type & operator * () const;
|
||||
const value_type * operator -> () const;
|
||||
value_type & operator * ();
|
||||
value_type * operator -> ();
|
||||
const value_type & operator * () const;
|
||||
const value_type * operator -> () const;
|
||||
|
||||
value_type & operator = (const value_type & Elem);
|
||||
value_type & operator = (const value_type & Elem);
|
||||
|
||||
protected:
|
||||
friend class graph_array<nodetype>;
|
||||
friend class std::vector<node>;
|
||||
protected:
|
||||
friend class graph_array<nodetype>;
|
||||
friend class std::vector<node>;
|
||||
|
||||
node(arc_list & Arcs);
|
||||
node(arc_list & Arcs);
|
||||
|
||||
arc_list & m_Arcs;
|
||||
size_t m_Begin;
|
||||
size_t m_End;
|
||||
arc_list & m_Arcs;
|
||||
size_t m_Begin;
|
||||
size_t m_End;
|
||||
|
||||
value_type m_Elem;
|
||||
bool m_Marker;
|
||||
value_type m_Elem;
|
||||
bool m_Marker;
|
||||
private:
|
||||
node& operator = (const node&) { return *this; }
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
graph_array();
|
||||
explicit graph_array(size_t NbNodes);
|
||||
graph_array();
|
||||
explicit graph_array(size_t NbNodes);
|
||||
|
||||
// Node related member functions
|
||||
bool empty() const;
|
||||
size_t size() const;
|
||||
// Node related member functions
|
||||
bool empty() const;
|
||||
size_t size() const;
|
||||
|
||||
node & operator [] (nodeid i);
|
||||
const node & operator [] (nodeid i) const;
|
||||
node & operator [] (nodeid i);
|
||||
const node & operator [] (nodeid i) const;
|
||||
|
||||
node_iterator begin();
|
||||
node_iterator end();
|
||||
const_node_iterator begin() const;
|
||||
const_node_iterator end() const;
|
||||
node_iterator begin();
|
||||
node_iterator end();
|
||||
const_node_iterator begin() const;
|
||||
const_node_iterator end() const;
|
||||
|
||||
node_reverse_iterator rbegin();
|
||||
node_reverse_iterator rend();
|
||||
const_node_reverse_iterator rbegin() const;
|
||||
const_node_reverse_iterator rend() const;
|
||||
node_reverse_iterator rbegin();
|
||||
node_reverse_iterator rend();
|
||||
const_node_reverse_iterator rbegin() const;
|
||||
const_node_reverse_iterator rend() const;
|
||||
|
||||
// Arc related member functions
|
||||
out_arc_iterator insert_arc(nodeid Initial, nodeid Terminal);
|
||||
out_arc_iterator insert_arc(node_iterator Initial, node_iterator Terminal);
|
||||
// Arc related member functions
|
||||
out_arc_iterator insert_arc(nodeid Initial, nodeid Terminal);
|
||||
out_arc_iterator insert_arc(node_iterator Initial, node_iterator Terminal);
|
||||
|
||||
// Optimized (overloaded) functions
|
||||
void swap(graph_type & Right);
|
||||
friend void swap(graph_type & Left, graph_type & Right) { Left.swap(Right); }
|
||||
// Optimized (overloaded) functions
|
||||
void swap(graph_type & Right);
|
||||
friend void swap(graph_type & Left, graph_type & Right) { Left.swap(Right); }
|
||||
|
||||
protected:
|
||||
graph_array(const graph_type &);
|
||||
graph_type & operator = (const graph_type &);
|
||||
graph_array(const graph_type &);
|
||||
graph_type & operator = (const graph_type &);
|
||||
|
||||
node_vector m_Nodes;
|
||||
arc_list m_Arcs;
|
||||
node_vector m_Nodes;
|
||||
arc_list m_Arcs;
|
||||
};
|
||||
|
||||
|
||||
@@ -160,13 +160,13 @@ void unmark_nodes(graph_array<nodetype> & G);
|
||||
|
||||
template <class N>
|
||||
inline graph_array<N>::arc::arc(node_iterator Terminal)
|
||||
: m_Terminal(Terminal) { }
|
||||
: m_Terminal(Terminal) { }
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::node_iterator graph_array<N>::arc::terminal() const
|
||||
{
|
||||
return m_Terminal;
|
||||
return m_Terminal;
|
||||
}
|
||||
|
||||
|
||||
@@ -177,10 +177,10 @@ inline typename graph_array<N>::node_iterator graph_array<N>::arc::terminal() co
|
||||
|
||||
template <class N>
|
||||
inline graph_array<N>::node::node(arc_list & Arcs)
|
||||
: m_Arcs(Arcs),
|
||||
m_Begin((std::numeric_limits<size_t>::max)()),
|
||||
m_End((std::numeric_limits<size_t>::max)()),
|
||||
m_Marker(false)
|
||||
: m_Arcs(Arcs),
|
||||
m_Begin((std::numeric_limits<size_t>::max)()),
|
||||
m_End((std::numeric_limits<size_t>::max)()),
|
||||
m_Marker(false)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -189,98 +189,98 @@ inline graph_array<N>::node::node(arc_list & Arcs)
|
||||
template <class N>
|
||||
inline void graph_array<N>::node::mark()
|
||||
{
|
||||
m_Marker = true;
|
||||
m_Marker = true;
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline void graph_array<N>::node::unmark()
|
||||
{
|
||||
m_Marker = false;
|
||||
m_Marker = false;
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline bool graph_array<N>::node::marked() const
|
||||
{
|
||||
return m_Marker;
|
||||
return m_Marker;
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline bool graph_array<N>::node::out_empty() const
|
||||
{
|
||||
return (m_Begin == m_End);
|
||||
return (m_Begin == m_End);
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline size_t graph_array<N>::node::out_size() const
|
||||
{
|
||||
return (m_End - m_Begin);
|
||||
return (m_End - m_Begin);
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::out_arc_iterator graph_array<N>::node::out_begin()
|
||||
{
|
||||
return (m_Arcs.begin() + m_Begin);
|
||||
return (m_Arcs.begin() + m_Begin);
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::out_arc_iterator graph_array<N>::node::out_end()
|
||||
{
|
||||
return (m_Arcs.begin() + m_End);
|
||||
return (m_Arcs.begin() + m_End);
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::const_out_arc_iterator graph_array<N>::node::out_begin() const
|
||||
{
|
||||
return (m_Arcs.begin() + m_Begin);
|
||||
return (m_Arcs.begin() + m_Begin);
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::const_out_arc_iterator graph_array<N>::node::out_end() const
|
||||
{
|
||||
return (m_Arcs.begin() + m_End);
|
||||
return (m_Arcs.begin() + m_End);
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline N & graph_array<N>::node::operator * ()
|
||||
{
|
||||
return m_Elem;
|
||||
return m_Elem;
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline N * graph_array<N>::node::operator -> ()
|
||||
{
|
||||
return &m_Elem;
|
||||
return &m_Elem;
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline const N & graph_array<N>::node::operator * () const
|
||||
{
|
||||
return m_Elem;
|
||||
return m_Elem;
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline const N * graph_array<N>::node::operator -> () const
|
||||
{
|
||||
return &m_Elem;
|
||||
return &m_Elem;
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline N & graph_array<N>::node::operator = (const N & Elem)
|
||||
{
|
||||
return (m_Elem = Elem);
|
||||
return (m_Elem = Elem);
|
||||
}
|
||||
|
||||
|
||||
@@ -295,146 +295,146 @@ inline graph_array<N>::graph_array() { }
|
||||
|
||||
template <class N>
|
||||
inline graph_array<N>::graph_array(const size_t NbNodes)
|
||||
: m_Nodes(NbNodes, node(m_Arcs))
|
||||
: m_Nodes(NbNodes, node(m_Arcs))
|
||||
{
|
||||
// optimisation: we consider that, averagely, a triangle may have at least 2 neighbours
|
||||
// otherwise we are just wasting a bit of memory, but not that much
|
||||
m_Arcs.reserve(NbNodes * 2);
|
||||
// optimisation: we consider that, averagely, a triangle may have at least 2 neighbours
|
||||
// otherwise we are just wasting a bit of memory, but not that much
|
||||
m_Arcs.reserve(NbNodes * 2);
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline bool graph_array<N>::empty() const
|
||||
{
|
||||
return m_Nodes.empty();
|
||||
return m_Nodes.empty();
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline size_t graph_array<N>::size() const
|
||||
{
|
||||
return m_Nodes.size();
|
||||
return m_Nodes.size();
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::node & graph_array<N>::operator [] (const nodeid i)
|
||||
{
|
||||
assert(i < size());
|
||||
assert(i < size());
|
||||
|
||||
return m_Nodes[i];
|
||||
return m_Nodes[i];
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline const typename graph_array<N>::node & graph_array<N>::operator [] (const nodeid i) const
|
||||
{
|
||||
assert(i < size());
|
||||
assert(i < size());
|
||||
|
||||
return m_Nodes[i];
|
||||
return m_Nodes[i];
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::node_iterator graph_array<N>::begin()
|
||||
{
|
||||
return m_Nodes.begin();
|
||||
return m_Nodes.begin();
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::node_iterator graph_array<N>::end()
|
||||
{
|
||||
return m_Nodes.end();
|
||||
return m_Nodes.end();
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::const_node_iterator graph_array<N>::begin() const
|
||||
{
|
||||
return m_Nodes.begin();
|
||||
return m_Nodes.begin();
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::const_node_iterator graph_array<N>::end() const
|
||||
{
|
||||
return m_Nodes.end();
|
||||
return m_Nodes.end();
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::node_reverse_iterator graph_array<N>::rbegin()
|
||||
{
|
||||
return m_Nodes.rbegin();
|
||||
return m_Nodes.rbegin();
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::node_reverse_iterator graph_array<N>::rend()
|
||||
{
|
||||
return m_Nodes.rend();
|
||||
return m_Nodes.rend();
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::const_node_reverse_iterator graph_array<N>::rbegin() const
|
||||
{
|
||||
return m_Nodes.rbegin();
|
||||
return m_Nodes.rbegin();
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::const_node_reverse_iterator graph_array<N>::rend() const
|
||||
{
|
||||
return m_Nodes.rend();
|
||||
return m_Nodes.rend();
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::out_arc_iterator graph_array<N>::insert_arc(const nodeid Initial, const nodeid Terminal)
|
||||
{
|
||||
assert(Initial < size());
|
||||
assert(Terminal < size());
|
||||
assert(Initial < size());
|
||||
assert(Terminal < size());
|
||||
|
||||
return insert_arc(m_Nodes.begin() + Initial, m_Nodes.begin() + Terminal);
|
||||
return insert_arc(m_Nodes.begin() + Initial, m_Nodes.begin() + Terminal);
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline typename graph_array<N>::out_arc_iterator graph_array<N>::insert_arc(const node_iterator Initial, const node_iterator Terminal)
|
||||
{
|
||||
assert((Initial >= begin()) && (Initial < end()));
|
||||
assert((Terminal >= begin()) && (Terminal < end()));
|
||||
assert((Initial >= begin()) && (Initial < end()));
|
||||
assert((Terminal >= begin()) && (Terminal < end()));
|
||||
|
||||
node & Node = * Initial;
|
||||
node & Node = * Initial;
|
||||
|
||||
if (Node.out_empty()) {
|
||||
if (Node.out_empty()) {
|
||||
|
||||
Node.m_Begin = m_Arcs.size();
|
||||
Node.m_End = m_Arcs.size() + 1;
|
||||
Node.m_Begin = m_Arcs.size();
|
||||
Node.m_End = m_Arcs.size() + 1;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
// we optimise here for make_connectivity_graph()
|
||||
// we know all the arcs for a given node are successively and sequentially added
|
||||
assert(Node.m_End == m_Arcs.size());
|
||||
|
||||
++(Node.m_End);
|
||||
}
|
||||
// we optimise here for make_connectivity_graph()
|
||||
// we know all the arcs for a given node are successively and sequentially added
|
||||
assert(Node.m_End == m_Arcs.size());
|
||||
|
||||
++(Node.m_End);
|
||||
}
|
||||
|
||||
m_Arcs.push_back(arc(Terminal));
|
||||
m_Arcs.push_back(arc(Terminal));
|
||||
|
||||
out_arc_iterator it = m_Arcs.end();
|
||||
return (--it);
|
||||
out_arc_iterator it = m_Arcs.end();
|
||||
return (--it);
|
||||
}
|
||||
|
||||
|
||||
template <class N>
|
||||
inline void graph_array<N>::swap(graph_type & Right)
|
||||
{
|
||||
std::swap(m_Nodes, Right.m_Nodes);
|
||||
std::swap(m_Arcs, Right.m_Arcs);
|
||||
std::swap(m_Nodes, Right.m_Nodes);
|
||||
std::swap(m_Arcs, Right.m_Arcs);
|
||||
}
|
||||
|
||||
|
||||
@@ -446,13 +446,13 @@ inline void graph_array<N>::swap(graph_type & Right)
|
||||
template <class N>
|
||||
inline void unmark_nodes(graph_array<N> & G)
|
||||
{
|
||||
std::for_each(G.begin(), G.end(), std::mem_fun_ref(&graph_array<N>::node::unmark));
|
||||
std::for_each(G.begin(), G.end(), std::mem_fun_ref(&graph_array<N>::node::unmark));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
} // namespace triangle_stripper
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
namespace triangle_stripper {
|
||||
|
||||
namespace detail {
|
||||
namespace detail {
|
||||
|
||||
|
||||
|
||||
@@ -29,59 +29,59 @@ class heap_array
|
||||
{
|
||||
public:
|
||||
|
||||
// Pre = PreCondition, Post = PostCondition
|
||||
// Pre = PreCondition, Post = PostCondition
|
||||
|
||||
heap_array() : m_Locked(false) { } // Post: ((size() == 0) && ! locked())
|
||||
heap_array() : m_Locked(false) { } // Post: ((size() == 0) && ! locked())
|
||||
|
||||
void clear(); // Post: ((size() == 0) && ! locked())
|
||||
void clear(); // Post: ((size() == 0) && ! locked())
|
||||
|
||||
void reserve(size_t Size);
|
||||
size_t size() const;
|
||||
void reserve(size_t Size);
|
||||
size_t size() const;
|
||||
|
||||
bool empty() const;
|
||||
bool locked() const;
|
||||
bool removed(size_t i) const; // Pre: (valid(i))
|
||||
bool valid(size_t i) const;
|
||||
bool empty() const;
|
||||
bool locked() const;
|
||||
bool removed(size_t i) const; // Pre: (valid(i))
|
||||
bool valid(size_t i) const;
|
||||
|
||||
size_t position(size_t i) const; // Pre: (valid(i))
|
||||
size_t position(size_t i) const; // Pre: (valid(i))
|
||||
|
||||
const T & top() const; // Pre: (! empty())
|
||||
const T & peek(size_t i) const; // Pre: (! removed(i))
|
||||
const T & operator [] (size_t i) const; // Pre: (! removed(i))
|
||||
const T & top() const; // Pre: (! empty())
|
||||
const T & peek(size_t i) const; // Pre: (! removed(i))
|
||||
const T & operator [] (size_t i) const; // Pre: (! removed(i))
|
||||
|
||||
void lock(); // Pre: (! locked()) Post: (locked())
|
||||
size_t push(const T & Elem); // Pre: (! locked())
|
||||
void lock(); // Pre: (! locked()) Post: (locked())
|
||||
size_t push(const T & Elem); // Pre: (! locked())
|
||||
|
||||
void pop(); // Pre: (locked() && ! empty())
|
||||
void erase(size_t i); // Pre: (locked() && ! removed(i))
|
||||
void update(size_t i, const T & Elem); // Pre: (locked() && ! removed(i))
|
||||
void pop(); // Pre: (locked() && ! empty())
|
||||
void erase(size_t i); // Pre: (locked() && ! removed(i))
|
||||
void update(size_t i, const T & Elem); // Pre: (locked() && ! removed(i))
|
||||
|
||||
protected:
|
||||
|
||||
heap_array(const heap_array &);
|
||||
heap_array & operator = (const heap_array &);
|
||||
heap_array(const heap_array &);
|
||||
heap_array & operator = (const heap_array &);
|
||||
|
||||
class linker
|
||||
{
|
||||
public:
|
||||
linker(const T & Elem, size_t i)
|
||||
: m_Elem(Elem), m_Index(i) { }
|
||||
class linker
|
||||
{
|
||||
public:
|
||||
linker(const T & Elem, size_t i)
|
||||
: m_Elem(Elem), m_Index(i) { }
|
||||
|
||||
T m_Elem;
|
||||
size_t m_Index;
|
||||
};
|
||||
T m_Elem;
|
||||
size_t m_Index;
|
||||
};
|
||||
|
||||
typedef std::vector<linker> linked_heap;
|
||||
typedef std::vector<size_t> finder;
|
||||
typedef std::vector<linker> linked_heap;
|
||||
typedef std::vector<size_t> finder;
|
||||
|
||||
void Adjust(size_t i);
|
||||
void Swap(size_t a, size_t b);
|
||||
bool Less(const linker & a, const linker & b) const;
|
||||
void Adjust(size_t i);
|
||||
void Swap(size_t a, size_t b);
|
||||
bool Less(const linker & a, const linker & b) const;
|
||||
|
||||
linked_heap m_Heap;
|
||||
finder m_Finder;
|
||||
CmpT m_Compare;
|
||||
bool m_Locked;
|
||||
linked_heap m_Heap;
|
||||
finder m_Finder;
|
||||
CmpT m_Compare;
|
||||
bool m_Locked;
|
||||
};
|
||||
|
||||
|
||||
@@ -95,199 +95,199 @@ protected:
|
||||
template <class T, class CmpT>
|
||||
inline void heap_array<T, CmpT>::clear()
|
||||
{
|
||||
m_Heap.clear();
|
||||
m_Finder.clear();
|
||||
m_Locked = false;
|
||||
m_Heap.clear();
|
||||
m_Finder.clear();
|
||||
m_Locked = false;
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline bool heap_array<T, CmpT>::empty() const
|
||||
{
|
||||
return m_Heap.empty();
|
||||
return m_Heap.empty();
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline bool heap_array<T, CmpT>::locked() const
|
||||
{
|
||||
return m_Locked;
|
||||
return m_Locked;
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline void heap_array<T, CmpT>::reserve(const size_t Size)
|
||||
{
|
||||
m_Heap.reserve(Size);
|
||||
m_Finder.reserve(Size);
|
||||
m_Heap.reserve(Size);
|
||||
m_Finder.reserve(Size);
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline size_t heap_array<T, CmpT>::size() const
|
||||
{
|
||||
return m_Heap.size();
|
||||
return m_Heap.size();
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline const T & heap_array<T, CmpT>::top() const
|
||||
{
|
||||
assert(! empty());
|
||||
assert(! empty());
|
||||
|
||||
return m_Heap.front().m_Elem;
|
||||
return m_Heap.front().m_Elem;
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline const T & heap_array<T, CmpT>::peek(const size_t i) const
|
||||
{
|
||||
assert(! removed(i));
|
||||
assert(! removed(i));
|
||||
|
||||
return (m_Heap[m_Finder[i]].m_Elem);
|
||||
return (m_Heap[m_Finder[i]].m_Elem);
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline const T & heap_array<T, CmpT>::operator [] (const size_t i) const
|
||||
{
|
||||
return peek(i);
|
||||
return peek(i);
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline void heap_array<T, CmpT>::pop()
|
||||
{
|
||||
assert(locked());
|
||||
assert(! empty());
|
||||
assert(locked());
|
||||
assert(! empty());
|
||||
|
||||
Swap(0, size() - 1);
|
||||
m_Heap.pop_back();
|
||||
Swap(0, size() - 1);
|
||||
m_Heap.pop_back();
|
||||
|
||||
if (! empty())
|
||||
Adjust(0);
|
||||
if (! empty())
|
||||
Adjust(0);
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline void heap_array<T, CmpT>::lock()
|
||||
{
|
||||
assert(! locked());
|
||||
assert(! locked());
|
||||
|
||||
m_Locked =true;
|
||||
m_Locked =true;
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline size_t heap_array<T, CmpT>::push(const T & Elem)
|
||||
{
|
||||
assert(! locked());
|
||||
assert(! locked());
|
||||
|
||||
const size_t Id = size();
|
||||
m_Finder.push_back(Id);
|
||||
m_Heap.push_back(linker(Elem, Id));
|
||||
Adjust(Id);
|
||||
const size_t Id = size();
|
||||
m_Finder.push_back(Id);
|
||||
m_Heap.push_back(linker(Elem, Id));
|
||||
Adjust(Id);
|
||||
|
||||
return Id;
|
||||
return Id;
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline void heap_array<T, CmpT>::erase(const size_t i)
|
||||
{
|
||||
assert(locked());
|
||||
assert(! removed(i));
|
||||
assert(locked());
|
||||
assert(! removed(i));
|
||||
|
||||
const size_t j = m_Finder[i];
|
||||
Swap(j, size() - 1);
|
||||
m_Heap.pop_back();
|
||||
const size_t j = m_Finder[i];
|
||||
Swap(j, size() - 1);
|
||||
m_Heap.pop_back();
|
||||
|
||||
if (j != size())
|
||||
Adjust(j);
|
||||
if (j != size())
|
||||
Adjust(j);
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline bool heap_array<T, CmpT>::removed(const size_t i) const
|
||||
{
|
||||
assert(valid(i));
|
||||
assert(valid(i));
|
||||
|
||||
return (m_Finder[i] >= m_Heap.size());
|
||||
return (m_Finder[i] >= m_Heap.size());
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline bool heap_array<T, CmpT>::valid(const size_t i) const
|
||||
{
|
||||
return (i < m_Finder.size());
|
||||
return (i < m_Finder.size());
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline size_t heap_array<T, CmpT>::position(const size_t i) const
|
||||
{
|
||||
assert(valid(i));
|
||||
assert(valid(i));
|
||||
|
||||
return (m_Heap[i].m_Index);
|
||||
return (m_Heap[i].m_Index);
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline void heap_array<T, CmpT>::update(const size_t i, const T & Elem)
|
||||
{
|
||||
assert(locked());
|
||||
assert(! removed(i));
|
||||
assert(locked());
|
||||
assert(! removed(i));
|
||||
|
||||
const size_t j = m_Finder[i];
|
||||
m_Heap[j].m_Elem = Elem;
|
||||
Adjust(j);
|
||||
const size_t j = m_Finder[i];
|
||||
m_Heap[j].m_Elem = Elem;
|
||||
Adjust(j);
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline void heap_array<T, CmpT>::Adjust(size_t i)
|
||||
{
|
||||
assert(i < m_Heap.size());
|
||||
assert(i < m_Heap.size());
|
||||
|
||||
size_t j;
|
||||
size_t j;
|
||||
|
||||
// Check the upper part of the heap
|
||||
for (j = i; (j > 0) && (Less(m_Heap[(j - 1) / 2], m_Heap[j])); j = ((j - 1) / 2))
|
||||
Swap(j, (j - 1) / 2);
|
||||
// Check the upper part of the heap
|
||||
for (j = i; (j > 0) && (Less(m_Heap[(j - 1) / 2], m_Heap[j])); j = ((j - 1) / 2))
|
||||
Swap(j, (j - 1) / 2);
|
||||
|
||||
// Check the lower part of the heap
|
||||
for (i = j; (j = 2 * i + 1) < size(); i = j) {
|
||||
if ((j + 1 < size()) && (Less(m_Heap[j], m_Heap[j + 1])))
|
||||
++j;
|
||||
// Check the lower part of the heap
|
||||
for (i = j; (j = 2 * i + 1) < size(); i = j) {
|
||||
if ((j + 1 < size()) && (Less(m_Heap[j], m_Heap[j + 1])))
|
||||
++j;
|
||||
|
||||
if (Less(m_Heap[j], m_Heap[i]))
|
||||
return;
|
||||
if (Less(m_Heap[j], m_Heap[i]))
|
||||
return;
|
||||
|
||||
Swap(i, j);
|
||||
}
|
||||
Swap(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline void heap_array<T, CmpT>::Swap(const size_t a, const size_t b)
|
||||
{
|
||||
std::swap(m_Heap[a], m_Heap[b]);
|
||||
std::swap(m_Heap[a], m_Heap[b]);
|
||||
|
||||
m_Finder[(m_Heap[a].m_Index)] = a;
|
||||
m_Finder[(m_Heap[b].m_Index)] = b;
|
||||
m_Finder[(m_Heap[a].m_Index)] = a;
|
||||
m_Finder[(m_Heap[b].m_Index)] = b;
|
||||
}
|
||||
|
||||
|
||||
template <class T, class CmpT>
|
||||
inline bool heap_array<T, CmpT>::Less(const linker & a, const linker & b) const
|
||||
{
|
||||
return m_Compare(a.m_Elem, b.m_Elem);
|
||||
return m_Compare(a.m_Elem, b.m_Elem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
} // namespace triangle_stripper
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace triangle_stripper {
|
||||
|
||||
namespace detail {
|
||||
namespace detail {
|
||||
|
||||
|
||||
|
||||
@@ -26,19 +26,19 @@ namespace triangle_stripper {
|
||||
class policy
|
||||
{
|
||||
public:
|
||||
policy(size_t MinStripSize, bool Cache);
|
||||
policy(size_t MinStripSize, bool Cache);
|
||||
|
||||
strip BestStrip() const;
|
||||
void Challenge(strip Strip, size_t Degree, size_t CacheHits);
|
||||
strip BestStrip() const;
|
||||
void Challenge(strip Strip, size_t Degree, size_t CacheHits);
|
||||
|
||||
private:
|
||||
policy& operator = (const policy&) { return *this; }
|
||||
strip m_Strip;
|
||||
size_t m_Degree;
|
||||
size_t m_CacheHits;
|
||||
strip m_Strip;
|
||||
size_t m_Degree;
|
||||
size_t m_CacheHits;
|
||||
|
||||
const size_t m_MinStripSize;
|
||||
const bool m_Cache;
|
||||
const size_t m_MinStripSize;
|
||||
const bool m_Cache;
|
||||
};
|
||||
|
||||
|
||||
@@ -51,13 +51,13 @@ inline policy::policy(size_t MinStripSize, bool Cache)
|
||||
|
||||
inline strip policy::BestStrip() const
|
||||
{
|
||||
return m_Strip;
|
||||
return m_Strip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
} // namespace triangle_stripper
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace triangle_stripper {
|
||||
|
||||
namespace detail {
|
||||
namespace detail {
|
||||
|
||||
|
||||
|
||||
@@ -23,24 +23,24 @@ namespace triangle_stripper {
|
||||
class triangle
|
||||
{
|
||||
public:
|
||||
triangle() { }
|
||||
triangle(index A, index B, index C)
|
||||
: m_A(A), m_B(B), m_C(C), m_StripID(0) { }
|
||||
triangle() { }
|
||||
triangle(index A, index B, index C)
|
||||
: m_A(A), m_B(B), m_C(C), m_StripID(0) { }
|
||||
|
||||
void ResetStripID() { m_StripID = 0; }
|
||||
void SetStripID(size_t StripID) { m_StripID = StripID; }
|
||||
size_t StripID() const { return m_StripID; }
|
||||
void ResetStripID() { m_StripID = 0; }
|
||||
void SetStripID(size_t StripID) { m_StripID = StripID; }
|
||||
size_t StripID() const { return m_StripID; }
|
||||
|
||||
index A() const { return m_A; }
|
||||
index B() const { return m_B; }
|
||||
index C() const { return m_C; }
|
||||
|
||||
index A() const { return m_A; }
|
||||
index B() const { return m_B; }
|
||||
index C() const { return m_C; }
|
||||
|
||||
private:
|
||||
index m_A;
|
||||
index m_B;
|
||||
index m_C;
|
||||
index m_A;
|
||||
index m_B;
|
||||
index m_C;
|
||||
|
||||
size_t m_StripID;
|
||||
size_t m_StripID;
|
||||
};
|
||||
|
||||
|
||||
@@ -48,19 +48,19 @@ private:
|
||||
class triangle_edge
|
||||
{
|
||||
public:
|
||||
triangle_edge(index A, index B)
|
||||
: m_A(A), m_B(B) { }
|
||||
triangle_edge(index A, index B)
|
||||
: m_A(A), m_B(B) { }
|
||||
|
||||
index A() const { return m_A; }
|
||||
index B() const { return m_B; }
|
||||
index A() const { return m_A; }
|
||||
index B() const { return m_B; }
|
||||
|
||||
bool operator == (const triangle_edge & Right) const {
|
||||
return ((A() == Right.A()) && (B() == Right.B()));
|
||||
}
|
||||
bool operator == (const triangle_edge & Right) const {
|
||||
return ((A() == Right.A()) && (B() == Right.B()));
|
||||
}
|
||||
|
||||
private:
|
||||
index m_A;
|
||||
index m_B;
|
||||
index m_A;
|
||||
index m_B;
|
||||
};
|
||||
|
||||
|
||||
@@ -72,26 +72,26 @@ enum triangle_order { ABC, BCA, CAB };
|
||||
class strip
|
||||
{
|
||||
public:
|
||||
strip()
|
||||
: m_Start(0), m_Order(ABC), m_Size(0) { }
|
||||
strip()
|
||||
: m_Start(0), m_Order(ABC), m_Size(0) { }
|
||||
|
||||
strip(size_t Start, triangle_order Order, size_t Size)
|
||||
: m_Start(Start), m_Order(Order), m_Size(Size) { }
|
||||
strip(size_t Start, triangle_order Order, size_t Size)
|
||||
: m_Start(Start), m_Order(Order), m_Size(Size) { }
|
||||
|
||||
size_t Start() const { return m_Start; }
|
||||
triangle_order Order() const { return m_Order; }
|
||||
size_t Size() const { return m_Size; }
|
||||
size_t Start() const { return m_Start; }
|
||||
triangle_order Order() const { return m_Order; }
|
||||
size_t Size() const { return m_Size; }
|
||||
|
||||
private:
|
||||
size_t m_Start;
|
||||
triangle_order m_Order;
|
||||
size_t m_Size;
|
||||
size_t m_Start;
|
||||
triangle_order m_Order;
|
||||
size_t m_Size;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
} // namespace triangle_stripper
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Tri Stripper
|
||||
// ************
|
||||
// Tri Stripper
|
||||
// ************
|
||||
//
|
||||
// Post TnL cache aware triangle stripifier in O(n.log(n)).
|
||||
//
|
||||
@@ -57,78 +57,78 @@ class tri_stripper
|
||||
{
|
||||
public:
|
||||
|
||||
explicit tri_stripper(const indices & TriIndices);
|
||||
explicit tri_stripper(const indices & TriIndices);
|
||||
|
||||
void Strip(primitive_vector * out_pPrimitivesVector);
|
||||
void Strip(primitive_vector * out_pPrimitivesVector);
|
||||
|
||||
/* Stripifier Algorithm Settings */
|
||||
|
||||
// Set the post-T&L cache size (0 disables the cache optimizer).
|
||||
void SetCacheSize(size_t CacheSize = 10);
|
||||
/* Stripifier Algorithm Settings */
|
||||
|
||||
// Set the post-T&L cache size (0 disables the cache optimizer).
|
||||
void SetCacheSize(size_t CacheSize = 10);
|
||||
|
||||
// Set the minimum size of a triangle strip (should be at least 2 triangles).
|
||||
// The stripifier discard any candidate strips that does not satisfy the minimum size condition.
|
||||
void SetMinStripSize(size_t MinStripSize = 2);
|
||||
// Set the minimum size of a triangle strip (should be at least 2 triangles).
|
||||
// The stripifier discard any candidate strips that does not satisfy the minimum size condition.
|
||||
void SetMinStripSize(size_t MinStripSize = 2);
|
||||
|
||||
// Set the backward search mode in addition to the forward search mode.
|
||||
// In forward mode, the candidate strips are build with the current candidate triangle being the first
|
||||
// triangle of the strip. When the backward mode is enabled, the stripifier also tests candidate strips
|
||||
// where the current candidate triangle is the last triangle of the strip.
|
||||
// Enable this if you want better results at the expense of being slightly slower.
|
||||
// Note: Do *NOT* use this when the cache optimizer is enabled; it only gives worse results.
|
||||
void SetBackwardSearch(bool Enabled = false);
|
||||
|
||||
// Set the cache simulator FIFO behavior (does nothing if the cache optimizer is disabled).
|
||||
// When enabled, the cache is simulated as a simple FIFO structure. However, when
|
||||
// disabled, indices that trigger cache hits are not pushed into the FIFO structure.
|
||||
// This allows simulating some GPUs that do not duplicate cache entries (e.g. NV25 or greater).
|
||||
void SetPushCacheHits(bool Enabled = true);
|
||||
// Set the backward search mode in addition to the forward search mode.
|
||||
// In forward mode, the candidate strips are build with the current candidate triangle being the first
|
||||
// triangle of the strip. When the backward mode is enabled, the stripifier also tests candidate strips
|
||||
// where the current candidate triangle is the last triangle of the strip.
|
||||
// Enable this if you want better results at the expense of being slightly slower.
|
||||
// Note: Do *NOT* use this when the cache optimizer is enabled; it only gives worse results.
|
||||
void SetBackwardSearch(bool Enabled = false);
|
||||
|
||||
// Set the cache simulator FIFO behavior (does nothing if the cache optimizer is disabled).
|
||||
// When enabled, the cache is simulated as a simple FIFO structure. However, when
|
||||
// disabled, indices that trigger cache hits are not pushed into the FIFO structure.
|
||||
// This allows simulating some GPUs that do not duplicate cache entries (e.g. NV25 or greater).
|
||||
void SetPushCacheHits(bool Enabled = true);
|
||||
|
||||
/* End Settings */
|
||||
/* End Settings */
|
||||
|
||||
private:
|
||||
|
||||
typedef detail::graph_array<detail::triangle> triangle_graph;
|
||||
typedef detail::heap_array<size_t, std::greater<size_t> > triangle_heap;
|
||||
typedef std::vector<size_t> candidates;
|
||||
typedef triangle_graph::node_iterator tri_iterator;
|
||||
typedef triangle_graph::const_node_iterator const_tri_iterator;
|
||||
typedef triangle_graph::out_arc_iterator link_iterator;
|
||||
typedef triangle_graph::const_out_arc_iterator const_link_iterator;
|
||||
typedef detail::graph_array<detail::triangle> triangle_graph;
|
||||
typedef detail::heap_array<size_t, std::greater<size_t> > triangle_heap;
|
||||
typedef std::vector<size_t> candidates;
|
||||
typedef triangle_graph::node_iterator tri_iterator;
|
||||
typedef triangle_graph::const_node_iterator const_tri_iterator;
|
||||
typedef triangle_graph::out_arc_iterator link_iterator;
|
||||
typedef triangle_graph::const_out_arc_iterator const_link_iterator;
|
||||
|
||||
void InitTriHeap();
|
||||
void Stripify();
|
||||
void AddLeftTriangles();
|
||||
void ResetStripIDs();
|
||||
void InitTriHeap();
|
||||
void Stripify();
|
||||
void AddLeftTriangles();
|
||||
void ResetStripIDs();
|
||||
|
||||
detail::strip FindBestStrip();
|
||||
detail::strip ExtendToStrip(size_t Start, detail::triangle_order Order);
|
||||
detail::strip BackExtendToStrip(size_t Start, detail::triangle_order Order, bool ClockWise);
|
||||
const_link_iterator LinkToNeighbour(const_tri_iterator Node, bool ClockWise, detail::triangle_order & Order, bool NotSimulation);
|
||||
const_link_iterator BackLinkToNeighbour(const_tri_iterator Node, bool ClockWise, detail::triangle_order & Order);
|
||||
void BuildStrip(const detail::strip Strip);
|
||||
void MarkTriAsTaken(size_t i);
|
||||
void AddIndex(index i, bool NotSimulation);
|
||||
void BackAddIndex(index i);
|
||||
void AddTriangle(const detail::triangle & Tri, detail::triangle_order Order, bool NotSimulation);
|
||||
void BackAddTriangle(const detail::triangle & Tri, detail::triangle_order Order);
|
||||
detail::strip FindBestStrip();
|
||||
detail::strip ExtendToStrip(size_t Start, detail::triangle_order Order);
|
||||
detail::strip BackExtendToStrip(size_t Start, detail::triangle_order Order, bool ClockWise);
|
||||
const_link_iterator LinkToNeighbour(const_tri_iterator Node, bool ClockWise, detail::triangle_order & Order, bool NotSimulation);
|
||||
const_link_iterator BackLinkToNeighbour(const_tri_iterator Node, bool ClockWise, detail::triangle_order & Order);
|
||||
void BuildStrip(const detail::strip Strip);
|
||||
void MarkTriAsTaken(size_t i);
|
||||
void AddIndex(index i, bool NotSimulation);
|
||||
void BackAddIndex(index i);
|
||||
void AddTriangle(const detail::triangle & Tri, detail::triangle_order Order, bool NotSimulation);
|
||||
void BackAddTriangle(const detail::triangle & Tri, detail::triangle_order Order);
|
||||
|
||||
bool Cache() const;
|
||||
size_t CacheSize() const;
|
||||
bool Cache() const;
|
||||
size_t CacheSize() const;
|
||||
|
||||
static detail::triangle_edge FirstEdge(const detail::triangle & Triangle, detail::triangle_order Order);
|
||||
static detail::triangle_edge LastEdge(const detail::triangle & Triangle, detail::triangle_order Order);
|
||||
static detail::triangle_edge FirstEdge(const detail::triangle & Triangle, detail::triangle_order Order);
|
||||
static detail::triangle_edge LastEdge(const detail::triangle & Triangle, detail::triangle_order Order);
|
||||
|
||||
primitive_vector m_PrimitivesVector;
|
||||
triangle_graph m_Triangles;
|
||||
triangle_heap m_TriHeap;
|
||||
candidates m_Candidates;
|
||||
detail::cache_simulator m_Cache;
|
||||
detail::cache_simulator m_BackCache;
|
||||
size_t m_StripID;
|
||||
size_t m_MinStripSize;
|
||||
bool m_BackwardSearch;
|
||||
bool m_FirstRun;
|
||||
primitive_vector m_PrimitivesVector;
|
||||
triangle_graph m_Triangles;
|
||||
triangle_heap m_TriHeap;
|
||||
candidates m_Candidates;
|
||||
detail::cache_simulator m_Cache;
|
||||
detail::cache_simulator m_BackCache;
|
||||
size_t m_StripID;
|
||||
size_t m_MinStripSize;
|
||||
bool m_BackwardSearch;
|
||||
bool m_FirstRun;
|
||||
};
|
||||
|
||||
|
||||
@@ -141,30 +141,30 @@ private:
|
||||
|
||||
inline void tri_stripper::SetCacheSize(const size_t CacheSize)
|
||||
{
|
||||
m_Cache.resize(CacheSize);
|
||||
m_BackCache.resize(CacheSize);
|
||||
m_Cache.resize(CacheSize);
|
||||
m_BackCache.resize(CacheSize);
|
||||
}
|
||||
|
||||
|
||||
inline void tri_stripper::SetMinStripSize(const size_t MinStripSize)
|
||||
{
|
||||
if (MinStripSize < 2)
|
||||
m_MinStripSize = 2;
|
||||
else
|
||||
m_MinStripSize = MinStripSize;
|
||||
if (MinStripSize < 2)
|
||||
m_MinStripSize = 2;
|
||||
else
|
||||
m_MinStripSize = MinStripSize;
|
||||
}
|
||||
|
||||
|
||||
inline void tri_stripper::SetBackwardSearch(const bool Enabled)
|
||||
{
|
||||
m_BackwardSearch = Enabled;
|
||||
m_BackwardSearch = Enabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void tri_stripper::SetPushCacheHits(bool Enabled)
|
||||
{
|
||||
m_Cache.push_cache_hits(Enabled);
|
||||
m_Cache.push_cache_hits(Enabled);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
namespace triangle_stripper {
|
||||
|
||||
namespace detail {
|
||||
namespace detail {
|
||||
|
||||
|
||||
|
||||
@@ -24,30 +24,30 @@ namespace triangle_stripper {
|
||||
namespace
|
||||
{
|
||||
|
||||
class tri_edge : public triangle_edge
|
||||
{
|
||||
public:
|
||||
tri_edge(index A, index B, size_t TriPos)
|
||||
: triangle_edge(A, B), m_TriPos(TriPos) { }
|
||||
class tri_edge : public triangle_edge
|
||||
{
|
||||
public:
|
||||
tri_edge(index A, index B, size_t TriPos)
|
||||
: triangle_edge(A, B), m_TriPos(TriPos) { }
|
||||
|
||||
size_t TriPos() const { return m_TriPos; }
|
||||
size_t TriPos() const { return m_TriPos; }
|
||||
|
||||
private:
|
||||
size_t m_TriPos;
|
||||
};
|
||||
private:
|
||||
size_t m_TriPos;
|
||||
};
|
||||
|
||||
|
||||
class cmp_tri_edge_lt
|
||||
{
|
||||
public:
|
||||
bool operator() (const tri_edge & a, const tri_edge & b) const;
|
||||
};
|
||||
class cmp_tri_edge_lt
|
||||
{
|
||||
public:
|
||||
bool operator() (const tri_edge & a, const tri_edge & b) const;
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<tri_edge> edge_map;
|
||||
typedef std::vector<tri_edge> edge_map;
|
||||
|
||||
|
||||
void LinkNeighbours(graph_array<triangle> & Triangles, const edge_map & EdgeMap, const tri_edge Edge);
|
||||
void LinkNeighbours(graph_array<triangle> & Triangles, const edge_map & EdgeMap, const tri_edge Edge);
|
||||
|
||||
}
|
||||
|
||||
@@ -56,77 +56,77 @@ namespace
|
||||
|
||||
void make_connectivity_graph(graph_array<triangle> & Triangles, const indices & Indices)
|
||||
{
|
||||
assert(Triangles.size() == (Indices.size() / 3));
|
||||
assert(Triangles.size() == (Indices.size() / 3));
|
||||
|
||||
// Fill the triangle data
|
||||
for (size_t i = 0; i < Triangles.size(); ++i)
|
||||
Triangles[i] = triangle(Indices[i * 3 + 0], Indices[i * 3 + 1], Indices[i * 3 + 2]);
|
||||
// Fill the triangle data
|
||||
for (size_t i = 0; i < Triangles.size(); ++i)
|
||||
Triangles[i] = triangle(Indices[i * 3 + 0], Indices[i * 3 + 1], Indices[i * 3 + 2]);
|
||||
|
||||
// Build an edge lookup table
|
||||
edge_map EdgeMap;
|
||||
EdgeMap.reserve(Triangles.size() * 3);
|
||||
// Build an edge lookup table
|
||||
edge_map EdgeMap;
|
||||
EdgeMap.reserve(Triangles.size() * 3);
|
||||
|
||||
for (size_t i = 0; i < Triangles.size(); ++i) {
|
||||
for (size_t i = 0; i < Triangles.size(); ++i) {
|
||||
|
||||
const triangle & Tri = * Triangles[i];
|
||||
const triangle & Tri = * Triangles[i];
|
||||
|
||||
EdgeMap.push_back(tri_edge(Tri.A(), Tri.B(), i));
|
||||
EdgeMap.push_back(tri_edge(Tri.B(), Tri.C(), i));
|
||||
EdgeMap.push_back(tri_edge(Tri.C(), Tri.A(), i));
|
||||
}
|
||||
EdgeMap.push_back(tri_edge(Tri.A(), Tri.B(), i));
|
||||
EdgeMap.push_back(tri_edge(Tri.B(), Tri.C(), i));
|
||||
EdgeMap.push_back(tri_edge(Tri.C(), Tri.A(), i));
|
||||
}
|
||||
|
||||
std::sort(EdgeMap.begin(), EdgeMap.end(), cmp_tri_edge_lt());
|
||||
std::sort(EdgeMap.begin(), EdgeMap.end(), cmp_tri_edge_lt());
|
||||
|
||||
// Link neighbour triangles together using the lookup table
|
||||
for (size_t i = 0; i < Triangles.size(); ++i) {
|
||||
// Link neighbour triangles together using the lookup table
|
||||
for (size_t i = 0; i < Triangles.size(); ++i) {
|
||||
|
||||
const triangle & Tri = * Triangles[i];
|
||||
const triangle & Tri = * Triangles[i];
|
||||
|
||||
LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.B(), Tri.A(), i));
|
||||
LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.C(), Tri.B(), i));
|
||||
LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.A(), Tri.C(), i));
|
||||
}
|
||||
LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.B(), Tri.A(), i));
|
||||
LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.C(), Tri.B(), i));
|
||||
LinkNeighbours(Triangles, EdgeMap, tri_edge(Tri.A(), Tri.C(), i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
inline bool cmp_tri_edge_lt::operator() (const tri_edge & a, const tri_edge & b) const
|
||||
{
|
||||
const index A1 = a.A();
|
||||
const index B1 = a.B();
|
||||
const index A2 = b.A();
|
||||
const index B2 = b.B();
|
||||
|
||||
inline bool cmp_tri_edge_lt::operator() (const tri_edge & a, const tri_edge & b) const
|
||||
{
|
||||
const index A1 = a.A();
|
||||
const index B1 = a.B();
|
||||
const index A2 = b.A();
|
||||
const index B2 = b.B();
|
||||
|
||||
if ((A1 < A2) || ((A1 == A2) && (B1 < B2)))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if ((A1 < A2) || ((A1 == A2) && (B1 < B2)))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void LinkNeighbours(graph_array<triangle> & Triangles, const edge_map & EdgeMap, const tri_edge Edge)
|
||||
{
|
||||
// Find the first edge equal to Edge
|
||||
edge_map::const_iterator it = std::lower_bound(EdgeMap.begin(), EdgeMap.end(), Edge, cmp_tri_edge_lt());
|
||||
void LinkNeighbours(graph_array<triangle> & Triangles, const edge_map & EdgeMap, const tri_edge Edge)
|
||||
{
|
||||
// Find the first edge equal to Edge
|
||||
edge_map::const_iterator it = std::lower_bound(EdgeMap.begin(), EdgeMap.end(), Edge, cmp_tri_edge_lt());
|
||||
|
||||
// See if there are any other edges that are equal
|
||||
// (if so, it means that more than 2 triangles are sharing the same edge,
|
||||
// which is unlikely but not impossible)
|
||||
for (; (it != EdgeMap.end()) && (Edge == (* it)); ++it)
|
||||
Triangles.insert_arc(Edge.TriPos(), it->TriPos());
|
||||
// See if there are any other edges that are equal
|
||||
// (if so, it means that more than 2 triangles are sharing the same edge,
|
||||
// which is unlikely but not impossible)
|
||||
for (; (it != EdgeMap.end()) && (Edge == (* it)); ++it)
|
||||
Triangles.insert_arc(Edge.TriPos(), it->TriPos());
|
||||
|
||||
// Note: degenerated triangles will also point themselves as neighbour triangles
|
||||
}
|
||||
// Note: degenerated triangles will also point themselves as neighbour triangles
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
@@ -14,50 +14,50 @@
|
||||
|
||||
namespace triangle_stripper {
|
||||
|
||||
namespace detail {
|
||||
namespace detail {
|
||||
|
||||
|
||||
|
||||
|
||||
void policy::Challenge(strip Strip, size_t Degree, size_t CacheHits)
|
||||
{
|
||||
if (Strip.Size() < m_MinStripSize)
|
||||
return;
|
||||
if (Strip.Size() < m_MinStripSize)
|
||||
return;
|
||||
|
||||
// Cache is disabled, take the longest strip
|
||||
if (! m_Cache) {
|
||||
// Cache is disabled, take the longest strip
|
||||
if (! m_Cache) {
|
||||
|
||||
if (Strip.Size() > m_Strip.Size())
|
||||
m_Strip = Strip;
|
||||
if (Strip.Size() > m_Strip.Size())
|
||||
m_Strip = Strip;
|
||||
|
||||
// Cache simulator enabled
|
||||
} else {
|
||||
// Cache simulator enabled
|
||||
} else {
|
||||
|
||||
// Priority 1: Keep the strip with the best cache hit count
|
||||
if (CacheHits > m_CacheHits) {
|
||||
m_Strip = Strip;
|
||||
m_Degree = Degree;
|
||||
m_CacheHits = CacheHits;
|
||||
// Priority 1: Keep the strip with the best cache hit count
|
||||
if (CacheHits > m_CacheHits) {
|
||||
m_Strip = Strip;
|
||||
m_Degree = Degree;
|
||||
m_CacheHits = CacheHits;
|
||||
|
||||
} else if (CacheHits == m_CacheHits) {
|
||||
} else if (CacheHits == m_CacheHits) {
|
||||
|
||||
// Priority 2: Keep the strip with the loneliest start triangle
|
||||
if ((m_Strip.Size() != 0) && (Degree < m_Degree)) {
|
||||
m_Strip = Strip;
|
||||
m_Degree = Degree;
|
||||
// Priority 2: Keep the strip with the loneliest start triangle
|
||||
if ((m_Strip.Size() != 0) && (Degree < m_Degree)) {
|
||||
m_Strip = Strip;
|
||||
m_Degree = Degree;
|
||||
|
||||
// Priority 3: Keep the longest strip
|
||||
} else if (Strip.Size() > m_Strip.Size()) {
|
||||
m_Strip = Strip;
|
||||
m_Degree = Degree;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Priority 3: Keep the longest strip
|
||||
} else if (Strip.Size() > m_Strip.Size()) {
|
||||
m_Strip = Strip;
|
||||
m_Degree = Degree;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
} // namespace triangle_stripper
|
||||
|
||||
@@ -19,533 +19,533 @@
|
||||
|
||||
namespace triangle_stripper {
|
||||
|
||||
using namespace detail;
|
||||
using namespace detail;
|
||||
|
||||
|
||||
|
||||
|
||||
tri_stripper::tri_stripper(const indices & TriIndices)
|
||||
: m_Triangles(TriIndices.size() / 3), // Silently ignore extra indices if (Indices.size() % 3 != 0)
|
||||
m_StripID(0),
|
||||
m_FirstRun(true)
|
||||
: m_Triangles(TriIndices.size() / 3), // Silently ignore extra indices if (Indices.size() % 3 != 0)
|
||||
m_StripID(0),
|
||||
m_FirstRun(true)
|
||||
{
|
||||
SetCacheSize();
|
||||
SetMinStripSize();
|
||||
SetBackwardSearch();
|
||||
SetPushCacheHits();
|
||||
SetCacheSize();
|
||||
SetMinStripSize();
|
||||
SetBackwardSearch();
|
||||
SetPushCacheHits();
|
||||
|
||||
make_connectivity_graph(m_Triangles, TriIndices);
|
||||
make_connectivity_graph(m_Triangles, TriIndices);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tri_stripper::Strip(primitive_vector * out_pPrimitivesVector)
|
||||
{
|
||||
assert(out_pPrimitivesVector);
|
||||
assert(out_pPrimitivesVector);
|
||||
|
||||
if (! m_FirstRun) {
|
||||
unmark_nodes(m_Triangles);
|
||||
ResetStripIDs();
|
||||
m_Cache.reset();
|
||||
m_TriHeap.clear();
|
||||
m_Candidates.clear();
|
||||
m_StripID = 0;
|
||||
if (! m_FirstRun) {
|
||||
unmark_nodes(m_Triangles);
|
||||
ResetStripIDs();
|
||||
m_Cache.reset();
|
||||
m_TriHeap.clear();
|
||||
m_Candidates.clear();
|
||||
m_StripID = 0;
|
||||
|
||||
m_FirstRun = false;
|
||||
}
|
||||
m_FirstRun = false;
|
||||
}
|
||||
|
||||
out_pPrimitivesVector->clear();
|
||||
out_pPrimitivesVector->clear();
|
||||
|
||||
InitTriHeap();
|
||||
InitTriHeap();
|
||||
|
||||
Stripify();
|
||||
AddLeftTriangles();
|
||||
|
||||
std::swap(m_PrimitivesVector, (* out_pPrimitivesVector));
|
||||
Stripify();
|
||||
AddLeftTriangles();
|
||||
|
||||
std::swap(m_PrimitivesVector, (* out_pPrimitivesVector));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tri_stripper::InitTriHeap()
|
||||
{
|
||||
m_TriHeap.reserve(m_Triangles.size());
|
||||
m_TriHeap.reserve(m_Triangles.size());
|
||||
|
||||
// Set up the triangles priority queue
|
||||
// The lower the number of available neighbour triangles, the higher the priority.
|
||||
for (size_t i = 0; i < m_Triangles.size(); ++i)
|
||||
m_TriHeap.push(m_Triangles[i].out_size());
|
||||
// Set up the triangles priority queue
|
||||
// The lower the number of available neighbour triangles, the higher the priority.
|
||||
for (size_t i = 0; i < m_Triangles.size(); ++i)
|
||||
m_TriHeap.push(m_Triangles[i].out_size());
|
||||
|
||||
// We're not going to add new elements anymore
|
||||
m_TriHeap.lock();
|
||||
// We're not going to add new elements anymore
|
||||
m_TriHeap.lock();
|
||||
|
||||
// Remove useless triangles
|
||||
// Note: we had to put all of them into the heap before to ensure coherency of the heap_array object
|
||||
while ((! m_TriHeap.empty()) && (m_TriHeap.top() == 0))
|
||||
m_TriHeap.pop();
|
||||
// Remove useless triangles
|
||||
// Note: we had to put all of them into the heap before to ensure coherency of the heap_array object
|
||||
while ((! m_TriHeap.empty()) && (m_TriHeap.top() == 0))
|
||||
m_TriHeap.pop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tri_stripper::ResetStripIDs()
|
||||
{
|
||||
for (triangle_graph::node_iterator it = m_Triangles.begin(); it != m_Triangles.end(); ++it)
|
||||
(**it).ResetStripID();
|
||||
for (triangle_graph::node_iterator it = m_Triangles.begin(); it != m_Triangles.end(); ++it)
|
||||
(**it).ResetStripID();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tri_stripper::Stripify()
|
||||
{
|
||||
while (! m_TriHeap.empty()) {
|
||||
while (! m_TriHeap.empty()) {
|
||||
|
||||
// There is no triangle in the candidates list, refill it with the loneliest triangle
|
||||
const size_t HeapTop = m_TriHeap.position(0);
|
||||
m_Candidates.push_back(HeapTop);
|
||||
// There is no triangle in the candidates list, refill it with the loneliest triangle
|
||||
const size_t HeapTop = m_TriHeap.position(0);
|
||||
m_Candidates.push_back(HeapTop);
|
||||
|
||||
while (! m_Candidates.empty()) {
|
||||
while (! m_Candidates.empty()) {
|
||||
|
||||
// Note: FindBestStrip empties the candidate list, while BuildStrip refills it
|
||||
const strip TriStrip = FindBestStrip();
|
||||
// Note: FindBestStrip empties the candidate list, while BuildStrip refills it
|
||||
const strip TriStrip = FindBestStrip();
|
||||
|
||||
if (TriStrip.Size() >= m_MinStripSize)
|
||||
BuildStrip(TriStrip);
|
||||
}
|
||||
if (TriStrip.Size() >= m_MinStripSize)
|
||||
BuildStrip(TriStrip);
|
||||
}
|
||||
|
||||
if (! m_TriHeap.removed(HeapTop))
|
||||
m_TriHeap.erase(HeapTop);
|
||||
if (! m_TriHeap.removed(HeapTop))
|
||||
m_TriHeap.erase(HeapTop);
|
||||
|
||||
// Eliminate all the triangles that have now become useless
|
||||
while ((! m_TriHeap.empty()) && (m_TriHeap.top() == 0))
|
||||
m_TriHeap.pop();
|
||||
}
|
||||
// Eliminate all the triangles that have now become useless
|
||||
while ((! m_TriHeap.empty()) && (m_TriHeap.top() == 0))
|
||||
m_TriHeap.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline strip tri_stripper::FindBestStrip()
|
||||
{
|
||||
// Allow to restore the cache (modified by ExtendTriToStrip) and implicitly reset the cache hit count
|
||||
const cache_simulator CacheBackup = m_Cache;
|
||||
// Allow to restore the cache (modified by ExtendTriToStrip) and implicitly reset the cache hit count
|
||||
const cache_simulator CacheBackup = m_Cache;
|
||||
|
||||
policy Policy(m_MinStripSize, Cache());
|
||||
policy Policy(m_MinStripSize, Cache());
|
||||
|
||||
while (! m_Candidates.empty()) {
|
||||
while (! m_Candidates.empty()) {
|
||||
|
||||
const size_t Candidate = m_Candidates.back();
|
||||
m_Candidates.pop_back();
|
||||
const size_t Candidate = m_Candidates.back();
|
||||
m_Candidates.pop_back();
|
||||
|
||||
// Discard useless triangles from the candidate list
|
||||
if ((m_Triangles[Candidate].marked()) || (m_TriHeap[Candidate] == 0))
|
||||
continue;
|
||||
// Discard useless triangles from the candidate list
|
||||
if ((m_Triangles[Candidate].marked()) || (m_TriHeap[Candidate] == 0))
|
||||
continue;
|
||||
|
||||
// Try to extend the triangle in the 3 possible forward directions
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
// Try to extend the triangle in the 3 possible forward directions
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
|
||||
const strip Strip = ExtendToStrip(Candidate, triangle_order(i));
|
||||
Policy.Challenge(Strip, m_TriHeap[Strip.Start()], m_Cache.hitcount());
|
||||
|
||||
m_Cache = CacheBackup;
|
||||
}
|
||||
const strip Strip = ExtendToStrip(Candidate, triangle_order(i));
|
||||
Policy.Challenge(Strip, m_TriHeap[Strip.Start()], m_Cache.hitcount());
|
||||
|
||||
m_Cache = CacheBackup;
|
||||
}
|
||||
|
||||
// Try to extend the triangle in the 6 possible backward directions
|
||||
if (m_BackwardSearch) {
|
||||
// Try to extend the triangle in the 6 possible backward directions
|
||||
if (m_BackwardSearch) {
|
||||
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
|
||||
const strip Strip = BackExtendToStrip(Candidate, triangle_order(i), false);
|
||||
Policy.Challenge(Strip, m_TriHeap[Strip.Start()], m_Cache.hitcount());
|
||||
|
||||
m_Cache = CacheBackup;
|
||||
}
|
||||
const strip Strip = BackExtendToStrip(Candidate, triangle_order(i), false);
|
||||
Policy.Challenge(Strip, m_TriHeap[Strip.Start()], m_Cache.hitcount());
|
||||
|
||||
m_Cache = CacheBackup;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
|
||||
const strip Strip = BackExtendToStrip(Candidate, triangle_order(i), true);
|
||||
Policy.Challenge(Strip, m_TriHeap[Strip.Start()], m_Cache.hitcount());
|
||||
|
||||
m_Cache = CacheBackup;
|
||||
}
|
||||
}
|
||||
const strip Strip = BackExtendToStrip(Candidate, triangle_order(i), true);
|
||||
Policy.Challenge(Strip, m_TriHeap[Strip.Start()], m_Cache.hitcount());
|
||||
|
||||
m_Cache = CacheBackup;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return Policy.BestStrip();
|
||||
return Policy.BestStrip();
|
||||
}
|
||||
|
||||
|
||||
|
||||
strip tri_stripper::ExtendToStrip(const size_t Start, triangle_order Order)
|
||||
{
|
||||
const triangle_order StartOrder = Order;
|
||||
|
||||
// Begin a new strip
|
||||
m_Triangles[Start]->SetStripID(++m_StripID);
|
||||
AddTriangle(* m_Triangles[Start], Order, false);
|
||||
const triangle_order StartOrder = Order;
|
||||
|
||||
// Begin a new strip
|
||||
m_Triangles[Start]->SetStripID(++m_StripID);
|
||||
AddTriangle(* m_Triangles[Start], Order, false);
|
||||
|
||||
size_t Size = 1;
|
||||
bool ClockWise = false;
|
||||
size_t Size = 1;
|
||||
bool ClockWise = false;
|
||||
|
||||
// Loop while we can further extend the strip
|
||||
for (tri_iterator Node = (m_Triangles.begin() + Start);
|
||||
(Node != m_Triangles.end()) && (!Cache() || ((Size + 2) < CacheSize()));
|
||||
++Size) {
|
||||
// Loop while we can further extend the strip
|
||||
for (tri_iterator Node = (m_Triangles.begin() + Start);
|
||||
(Node != m_Triangles.end()) && (!Cache() || ((Size + 2) < CacheSize()));
|
||||
++Size) {
|
||||
|
||||
const const_link_iterator Link = LinkToNeighbour(Node, ClockWise, Order, false);
|
||||
const const_link_iterator Link = LinkToNeighbour(Node, ClockWise, Order, false);
|
||||
|
||||
// Is it the end of the strip?
|
||||
if (Link == Node->out_end()) {
|
||||
// Is it the end of the strip?
|
||||
if (Link == Node->out_end()) {
|
||||
|
||||
Node = m_Triangles.end();
|
||||
--Size;
|
||||
Node = m_Triangles.end();
|
||||
--Size;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
Node = Link->terminal();
|
||||
(* Node)->SetStripID(m_StripID);
|
||||
ClockWise = ! ClockWise;
|
||||
Node = Link->terminal();
|
||||
(* Node)->SetStripID(m_StripID);
|
||||
ClockWise = ! ClockWise;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strip(Start, StartOrder, Size);
|
||||
return strip(Start, StartOrder, Size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
strip tri_stripper::BackExtendToStrip(size_t Start, triangle_order Order, bool ClockWise)
|
||||
{
|
||||
// Begin a new strip
|
||||
m_Triangles[Start]->SetStripID(++m_StripID);
|
||||
BackAddIndex(LastEdge(* m_Triangles[Start], Order).B());
|
||||
size_t Size = 1;
|
||||
// Begin a new strip
|
||||
m_Triangles[Start]->SetStripID(++m_StripID);
|
||||
BackAddIndex(LastEdge(* m_Triangles[Start], Order).B());
|
||||
size_t Size = 1;
|
||||
|
||||
tri_iterator Node;
|
||||
tri_iterator Node;
|
||||
|
||||
// Loop while we can further extend the strip
|
||||
for (Node = (m_Triangles.begin() + Start);
|
||||
!Cache() || ((Size + 2) < CacheSize());
|
||||
++Size) {
|
||||
// Loop while we can further extend the strip
|
||||
for (Node = (m_Triangles.begin() + Start);
|
||||
!Cache() || ((Size + 2) < CacheSize());
|
||||
++Size) {
|
||||
|
||||
const const_link_iterator Link = BackLinkToNeighbour(Node, ClockWise, Order);
|
||||
const const_link_iterator Link = BackLinkToNeighbour(Node, ClockWise, Order);
|
||||
|
||||
// Is it the end of the strip?
|
||||
if (Link == Node->out_end())
|
||||
break;
|
||||
// Is it the end of the strip?
|
||||
if (Link == Node->out_end())
|
||||
break;
|
||||
|
||||
else {
|
||||
Node = Link->terminal();
|
||||
(* Node)->SetStripID(m_StripID);
|
||||
ClockWise = ! ClockWise;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Node = Link->terminal();
|
||||
(* Node)->SetStripID(m_StripID);
|
||||
ClockWise = ! ClockWise;
|
||||
}
|
||||
}
|
||||
|
||||
// We have to start from a counterclockwise triangle.
|
||||
// Simply return an empty strip in the case where the first triangle is clockwise.
|
||||
// Even though we could discard the first triangle and start from the next counterclockwise triangle,
|
||||
// this often leads to more lonely triangles afterward.
|
||||
if (ClockWise)
|
||||
return strip();
|
||||
// We have to start from a counterclockwise triangle.
|
||||
// Simply return an empty strip in the case where the first triangle is clockwise.
|
||||
// Even though we could discard the first triangle and start from the next counterclockwise triangle,
|
||||
// this often leads to more lonely triangles afterward.
|
||||
if (ClockWise)
|
||||
return strip();
|
||||
|
||||
if (Cache()) {
|
||||
m_Cache.merge(m_BackCache, Size);
|
||||
m_BackCache.reset();
|
||||
}
|
||||
if (Cache()) {
|
||||
m_Cache.merge(m_BackCache, Size);
|
||||
m_BackCache.reset();
|
||||
}
|
||||
|
||||
return strip(Node - m_Triangles.begin(), Order, Size);
|
||||
return strip(Node - m_Triangles.begin(), Order, Size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tri_stripper::BuildStrip(const strip Strip)
|
||||
{
|
||||
const size_t Start = Strip.Start();
|
||||
const size_t Start = Strip.Start();
|
||||
|
||||
bool ClockWise = false;
|
||||
triangle_order Order = Strip.Order();
|
||||
bool ClockWise = false;
|
||||
triangle_order Order = Strip.Order();
|
||||
|
||||
// Create a new strip
|
||||
m_PrimitivesVector.push_back(primitive_group());
|
||||
m_PrimitivesVector.back().Type = TRIANGLE_STRIP;
|
||||
AddTriangle(* m_Triangles[Start], Order, true);
|
||||
MarkTriAsTaken(Start);
|
||||
// Create a new strip
|
||||
m_PrimitivesVector.push_back(primitive_group());
|
||||
m_PrimitivesVector.back().Type = TRIANGLE_STRIP;
|
||||
AddTriangle(* m_Triangles[Start], Order, true);
|
||||
MarkTriAsTaken(Start);
|
||||
|
||||
// Loop while we can further extend the strip
|
||||
tri_iterator Node = (m_Triangles.begin() + Start);
|
||||
// Loop while we can further extend the strip
|
||||
tri_iterator Node = (m_Triangles.begin() + Start);
|
||||
|
||||
for (size_t Size = 1; Size < Strip.Size(); ++Size) {
|
||||
for (size_t Size = 1; Size < Strip.Size(); ++Size) {
|
||||
|
||||
const const_link_iterator Link = LinkToNeighbour(Node, ClockWise, Order, true);
|
||||
const const_link_iterator Link = LinkToNeighbour(Node, ClockWise, Order, true);
|
||||
|
||||
assert(Link != Node->out_end());
|
||||
assert(Link != Node->out_end());
|
||||
|
||||
// Go to the next triangle
|
||||
Node = Link->terminal();
|
||||
MarkTriAsTaken(Node - m_Triangles.begin());
|
||||
ClockWise = ! ClockWise;
|
||||
}
|
||||
// Go to the next triangle
|
||||
Node = Link->terminal();
|
||||
MarkTriAsTaken(Node - m_Triangles.begin());
|
||||
ClockWise = ! ClockWise;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline tri_stripper::const_link_iterator tri_stripper::LinkToNeighbour(const const_tri_iterator Node, const bool ClockWise, triangle_order & Order, const bool NotSimulation)
|
||||
{
|
||||
const triangle_edge Edge = LastEdge(** Node, Order);
|
||||
const triangle_edge Edge = LastEdge(** Node, Order);
|
||||
|
||||
for (const_link_iterator Link = Node->out_begin(); Link != Node->out_end(); ++Link) {
|
||||
for (const_link_iterator Link = Node->out_begin(); Link != Node->out_end(); ++Link) {
|
||||
|
||||
// Get the reference to the possible next triangle
|
||||
const triangle & Tri = ** Link->terminal();
|
||||
// Get the reference to the possible next triangle
|
||||
const triangle & Tri = ** Link->terminal();
|
||||
|
||||
// Check whether it's already been used
|
||||
if (NotSimulation || (Tri.StripID() != m_StripID)) {
|
||||
// Check whether it's already been used
|
||||
if (NotSimulation || (Tri.StripID() != m_StripID)) {
|
||||
|
||||
if (! Link->terminal()->marked()) {
|
||||
if (! Link->terminal()->marked()) {
|
||||
|
||||
// Does the current candidate triangle match the required position for the strip?
|
||||
// Does the current candidate triangle match the required position for the strip?
|
||||
|
||||
if ((Edge.B() == Tri.A()) && (Edge.A() == Tri.B())) {
|
||||
Order = (ClockWise) ? ABC : BCA;
|
||||
AddIndex(Tri.C(), NotSimulation);
|
||||
return Link;
|
||||
}
|
||||
if ((Edge.B() == Tri.A()) && (Edge.A() == Tri.B())) {
|
||||
Order = (ClockWise) ? ABC : BCA;
|
||||
AddIndex(Tri.C(), NotSimulation);
|
||||
return Link;
|
||||
}
|
||||
|
||||
else if ((Edge.B() == Tri.B()) && (Edge.A() == Tri.C())) {
|
||||
Order = (ClockWise) ? BCA : CAB;
|
||||
AddIndex(Tri.A(), NotSimulation);
|
||||
return Link;
|
||||
}
|
||||
else if ((Edge.B() == Tri.B()) && (Edge.A() == Tri.C())) {
|
||||
Order = (ClockWise) ? BCA : CAB;
|
||||
AddIndex(Tri.A(), NotSimulation);
|
||||
return Link;
|
||||
}
|
||||
|
||||
else if ((Edge.B() == Tri.C()) && (Edge.A() == Tri.A())) {
|
||||
Order = (ClockWise) ? CAB : ABC;
|
||||
AddIndex(Tri.B(), NotSimulation);
|
||||
return Link;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((Edge.B() == Tri.C()) && (Edge.A() == Tri.A())) {
|
||||
Order = (ClockWise) ? CAB : ABC;
|
||||
AddIndex(Tri.B(), NotSimulation);
|
||||
return Link;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return Node->out_end();
|
||||
return Node->out_end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline tri_stripper::const_link_iterator tri_stripper::BackLinkToNeighbour(const_tri_iterator Node, bool ClockWise, triangle_order & Order)
|
||||
{
|
||||
const triangle_edge Edge = FirstEdge(** Node, Order);
|
||||
const triangle_edge Edge = FirstEdge(** Node, Order);
|
||||
|
||||
for (const_link_iterator Link = Node->out_begin(); Link != Node->out_end(); ++Link) {
|
||||
for (const_link_iterator Link = Node->out_begin(); Link != Node->out_end(); ++Link) {
|
||||
|
||||
// Get the reference to the possible previous triangle
|
||||
const triangle & Tri = ** Link->terminal();
|
||||
// Get the reference to the possible previous triangle
|
||||
const triangle & Tri = ** Link->terminal();
|
||||
|
||||
// Check whether it's already been used
|
||||
if ((Tri.StripID() != m_StripID) && ! Link->terminal()->marked()) {
|
||||
// Check whether it's already been used
|
||||
if ((Tri.StripID() != m_StripID) && ! Link->terminal()->marked()) {
|
||||
|
||||
// Does the current candidate triangle match the required position for the strip?
|
||||
// Does the current candidate triangle match the required position for the strip?
|
||||
|
||||
if ((Edge.B() == Tri.A()) && (Edge.A() == Tri.B())) {
|
||||
Order = (ClockWise) ? CAB : BCA;
|
||||
BackAddIndex(Tri.C());
|
||||
return Link;
|
||||
}
|
||||
if ((Edge.B() == Tri.A()) && (Edge.A() == Tri.B())) {
|
||||
Order = (ClockWise) ? CAB : BCA;
|
||||
BackAddIndex(Tri.C());
|
||||
return Link;
|
||||
}
|
||||
|
||||
else if ((Edge.B() == Tri.B()) && (Edge.A() == Tri.C())) {
|
||||
Order = (ClockWise) ? ABC : CAB;
|
||||
BackAddIndex(Tri.A());
|
||||
return Link;
|
||||
}
|
||||
else if ((Edge.B() == Tri.B()) && (Edge.A() == Tri.C())) {
|
||||
Order = (ClockWise) ? ABC : CAB;
|
||||
BackAddIndex(Tri.A());
|
||||
return Link;
|
||||
}
|
||||
|
||||
else if ((Edge.B() == Tri.C()) && (Edge.A() == Tri.A())) {
|
||||
Order = (ClockWise) ? BCA : ABC;
|
||||
BackAddIndex(Tri.B());
|
||||
return Link;
|
||||
}
|
||||
}
|
||||
else if ((Edge.B() == Tri.C()) && (Edge.A() == Tri.A())) {
|
||||
Order = (ClockWise) ? BCA : ABC;
|
||||
BackAddIndex(Tri.B());
|
||||
return Link;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return Node->out_end();
|
||||
return Node->out_end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tri_stripper::MarkTriAsTaken(const size_t i)
|
||||
{
|
||||
typedef triangle_graph::node_iterator tri_node_iter;
|
||||
typedef triangle_graph::out_arc_iterator tri_link_iter;
|
||||
typedef triangle_graph::node_iterator tri_node_iter;
|
||||
typedef triangle_graph::out_arc_iterator tri_link_iter;
|
||||
|
||||
// Mark the triangle node
|
||||
m_Triangles[i].mark();
|
||||
// Mark the triangle node
|
||||
m_Triangles[i].mark();
|
||||
|
||||
// Remove triangle from priority queue if it isn't yet
|
||||
if (! m_TriHeap.removed(i))
|
||||
m_TriHeap.erase(i);
|
||||
// Remove triangle from priority queue if it isn't yet
|
||||
if (! m_TriHeap.removed(i))
|
||||
m_TriHeap.erase(i);
|
||||
|
||||
// Adjust the degree of available neighbour triangles
|
||||
for (tri_link_iter Link = m_Triangles[i].out_begin(); Link != m_Triangles[i].out_end(); ++Link) {
|
||||
// Adjust the degree of available neighbour triangles
|
||||
for (tri_link_iter Link = m_Triangles[i].out_begin(); Link != m_Triangles[i].out_end(); ++Link) {
|
||||
|
||||
const size_t j = Link->terminal() - m_Triangles.begin();
|
||||
const size_t j = Link->terminal() - m_Triangles.begin();
|
||||
|
||||
if ((! m_Triangles[j].marked()) && (! m_TriHeap.removed(j))) {
|
||||
size_t NewDegree = m_TriHeap.peek(j);
|
||||
NewDegree = NewDegree - 1;
|
||||
m_TriHeap.update(j, NewDegree);
|
||||
if ((! m_Triangles[j].marked()) && (! m_TriHeap.removed(j))) {
|
||||
size_t NewDegree = m_TriHeap.peek(j);
|
||||
NewDegree = NewDegree - 1;
|
||||
m_TriHeap.update(j, NewDegree);
|
||||
|
||||
// Update the candidate list if cache is enabled
|
||||
if (Cache() && (NewDegree > 0))
|
||||
m_Candidates.push_back(j);
|
||||
}
|
||||
}
|
||||
// Update the candidate list if cache is enabled
|
||||
if (Cache() && (NewDegree > 0))
|
||||
m_Candidates.push_back(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline triangle_edge tri_stripper::FirstEdge(const triangle & Triangle, const triangle_order Order)
|
||||
{
|
||||
switch (Order)
|
||||
{
|
||||
case ABC:
|
||||
return triangle_edge(Triangle.A(), Triangle.B());
|
||||
switch (Order)
|
||||
{
|
||||
case ABC:
|
||||
return triangle_edge(Triangle.A(), Triangle.B());
|
||||
|
||||
case BCA:
|
||||
return triangle_edge(Triangle.B(), Triangle.C());
|
||||
case BCA:
|
||||
return triangle_edge(Triangle.B(), Triangle.C());
|
||||
|
||||
case CAB:
|
||||
return triangle_edge(Triangle.C(), Triangle.A());
|
||||
case CAB:
|
||||
return triangle_edge(Triangle.C(), Triangle.A());
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
return triangle_edge(0, 0);
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
return triangle_edge(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline triangle_edge tri_stripper::LastEdge(const triangle & Triangle, const triangle_order Order)
|
||||
{
|
||||
switch (Order)
|
||||
{
|
||||
case ABC:
|
||||
return triangle_edge(Triangle.B(), Triangle.C());
|
||||
switch (Order)
|
||||
{
|
||||
case ABC:
|
||||
return triangle_edge(Triangle.B(), Triangle.C());
|
||||
|
||||
case BCA:
|
||||
return triangle_edge(Triangle.C(), Triangle.A());
|
||||
case BCA:
|
||||
return triangle_edge(Triangle.C(), Triangle.A());
|
||||
|
||||
case CAB:
|
||||
return triangle_edge(Triangle.A(), Triangle.B());
|
||||
case CAB:
|
||||
return triangle_edge(Triangle.A(), Triangle.B());
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
return triangle_edge(0, 0);
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
return triangle_edge(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void tri_stripper::AddIndex(const index i, const bool NotSimulation)
|
||||
{
|
||||
if (Cache())
|
||||
m_Cache.push(i, ! NotSimulation);
|
||||
if (Cache())
|
||||
m_Cache.push(i, ! NotSimulation);
|
||||
|
||||
if (NotSimulation)
|
||||
m_PrimitivesVector.back().Indices.push_back(i);
|
||||
if (NotSimulation)
|
||||
m_PrimitivesVector.back().Indices.push_back(i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void tri_stripper::BackAddIndex(const index i)
|
||||
{
|
||||
if (Cache())
|
||||
m_BackCache.push(i, true);
|
||||
if (Cache())
|
||||
m_BackCache.push(i, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void tri_stripper::AddTriangle(const triangle & Tri, const triangle_order Order, const bool NotSimulation)
|
||||
{
|
||||
switch (Order)
|
||||
{
|
||||
case ABC:
|
||||
AddIndex(Tri.A(), NotSimulation);
|
||||
AddIndex(Tri.B(), NotSimulation);
|
||||
AddIndex(Tri.C(), NotSimulation);
|
||||
break;
|
||||
switch (Order)
|
||||
{
|
||||
case ABC:
|
||||
AddIndex(Tri.A(), NotSimulation);
|
||||
AddIndex(Tri.B(), NotSimulation);
|
||||
AddIndex(Tri.C(), NotSimulation);
|
||||
break;
|
||||
|
||||
case BCA:
|
||||
AddIndex(Tri.B(), NotSimulation);
|
||||
AddIndex(Tri.C(), NotSimulation);
|
||||
AddIndex(Tri.A(), NotSimulation);
|
||||
break;
|
||||
case BCA:
|
||||
AddIndex(Tri.B(), NotSimulation);
|
||||
AddIndex(Tri.C(), NotSimulation);
|
||||
AddIndex(Tri.A(), NotSimulation);
|
||||
break;
|
||||
|
||||
case CAB:
|
||||
AddIndex(Tri.C(), NotSimulation);
|
||||
AddIndex(Tri.A(), NotSimulation);
|
||||
AddIndex(Tri.B(), NotSimulation);
|
||||
break;
|
||||
}
|
||||
case CAB:
|
||||
AddIndex(Tri.C(), NotSimulation);
|
||||
AddIndex(Tri.A(), NotSimulation);
|
||||
AddIndex(Tri.B(), NotSimulation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void tri_stripper::BackAddTriangle(const triangle & Tri, const triangle_order Order)
|
||||
{
|
||||
switch (Order)
|
||||
{
|
||||
case ABC:
|
||||
BackAddIndex(Tri.C());
|
||||
BackAddIndex(Tri.B());
|
||||
BackAddIndex(Tri.A());
|
||||
break;
|
||||
switch (Order)
|
||||
{
|
||||
case ABC:
|
||||
BackAddIndex(Tri.C());
|
||||
BackAddIndex(Tri.B());
|
||||
BackAddIndex(Tri.A());
|
||||
break;
|
||||
|
||||
case BCA:
|
||||
BackAddIndex(Tri.A());
|
||||
BackAddIndex(Tri.C());
|
||||
BackAddIndex(Tri.B());
|
||||
break;
|
||||
case BCA:
|
||||
BackAddIndex(Tri.A());
|
||||
BackAddIndex(Tri.C());
|
||||
BackAddIndex(Tri.B());
|
||||
break;
|
||||
|
||||
case CAB:
|
||||
BackAddIndex(Tri.B());
|
||||
BackAddIndex(Tri.A());
|
||||
BackAddIndex(Tri.C());
|
||||
break;
|
||||
}
|
||||
case CAB:
|
||||
BackAddIndex(Tri.B());
|
||||
BackAddIndex(Tri.A());
|
||||
BackAddIndex(Tri.C());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void tri_stripper::AddLeftTriangles()
|
||||
{
|
||||
// Create the last indices array and fill it with all the triangles that couldn't be stripped
|
||||
primitive_group Primitives;
|
||||
Primitives.Type = TRIANGLES;
|
||||
m_PrimitivesVector.push_back(Primitives);
|
||||
indices & Indices = m_PrimitivesVector.back().Indices;
|
||||
// Create the last indices array and fill it with all the triangles that couldn't be stripped
|
||||
primitive_group Primitives;
|
||||
Primitives.Type = TRIANGLES;
|
||||
m_PrimitivesVector.push_back(Primitives);
|
||||
indices & Indices = m_PrimitivesVector.back().Indices;
|
||||
|
||||
for (size_t i = 0; i < m_Triangles.size(); ++i)
|
||||
if (! m_Triangles[i].marked()) {
|
||||
Indices.push_back(m_Triangles[i]->A());
|
||||
Indices.push_back(m_Triangles[i]->B());
|
||||
Indices.push_back(m_Triangles[i]->C());
|
||||
}
|
||||
for (size_t i = 0; i < m_Triangles.size(); ++i)
|
||||
if (! m_Triangles[i].marked()) {
|
||||
Indices.push_back(m_Triangles[i]->A());
|
||||
Indices.push_back(m_Triangles[i]->B());
|
||||
Indices.push_back(m_Triangles[i]->C());
|
||||
}
|
||||
|
||||
// Undo if useless
|
||||
if (Indices.size() == 0)
|
||||
m_PrimitivesVector.pop_back();
|
||||
// Undo if useless
|
||||
if (Indices.size() == 0)
|
||||
m_PrimitivesVector.pop_back();
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool tri_stripper::Cache() const
|
||||
{
|
||||
return (m_Cache.size() != 0);
|
||||
return (m_Cache.size() != 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline size_t tri_stripper::CacheSize() const
|
||||
{
|
||||
return m_Cache.size();
|
||||
return m_Cache.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user