update to the latest version of HACD (hierarchical approximate convex decomposition, http://sourceforge.net/projects/hacd)

Thanks to Khaled Mammou for the fix.
This commit is contained in:
erwin.coumans
2011-07-24 02:01:32 +00:00
parent c7b8035556
commit cf0d948d97
7 changed files with 165 additions and 44 deletions

View File

@@ -34,6 +34,7 @@ namespace HACD
{
m_convexHull = 0;
m_name = -1;
m_cc = -1;
m_error = 0;
m_surf = 0;
m_perimeter = 0;
@@ -57,6 +58,7 @@ namespace HACD
{
m_nV = 0;
m_nE = 0;
m_nCCs = 0;
}
Graph::~Graph()
@@ -78,7 +80,7 @@ namespace HACD
{
size_t name = m_vertices.size();
m_vertices.resize(name+1);
m_vertices[name].m_name = name;
m_vertices[name].m_name = static_cast<long>(name);
m_nV++;
return static_cast<long>(name);
}
@@ -87,11 +89,11 @@ namespace HACD
{
size_t name = m_edges.size();
m_edges.push_back(GraphEdge());
m_edges[name].m_name = name;
m_edges[name].m_name = static_cast<long>(name);
m_edges[name].m_v1 = v1;
m_edges[name].m_v2 = v2;
m_vertices[v1].AddEdge(name);
m_vertices[v2].AddEdge(name);
m_vertices[v1].AddEdge(static_cast<long>(name));
m_vertices[v2].AddEdge(static_cast<long>(name));
m_nE++;
return static_cast<long>(name);
}
@@ -236,5 +238,55 @@ namespace HACD
m_nV = 0;
m_nE = 0;
}
long Graph::ExtractCCs()
{
// all CCs to -1
for (size_t v = 0; v < m_vertices.size(); ++v)
{
if (!m_vertices[v].m_deleted)
{
m_vertices[v].m_cc = -1;
}
}
// we get the CCs
m_nCCs = 0;
long v2 = -1;
std::vector<long> temp;
for (size_t v = 0; v < m_vertices.size(); ++v)
{
if (!m_vertices[v].m_deleted && m_vertices[v].m_cc == -1)
{
m_vertices[v].m_cc = static_cast<long>(m_nCCs);
temp.clear();
temp.push_back(m_vertices[v].m_name);
while (temp.size())
{
long vertex = temp[temp.size()-1];
temp.pop_back();
std::set<long>::const_iterator ed(m_vertices[vertex].m_edges.begin());
std::set<long>::const_iterator itEnd(m_vertices[vertex].m_edges.end());
for(; ed != itEnd; ++ed)
{
if (m_edges[*ed].m_v1 == vertex)
{
v2 = m_edges[*ed].m_v2;
}
else
{
v2 = m_edges[*ed].m_v1;
}
if ( !m_vertices[v2].m_deleted && m_vertices[v2].m_cc == -1)
{
m_vertices[v2].m_cc = static_cast<long>(m_nCCs);
temp.push_back(v2);
}
}
}
m_nCCs++;
}
}
return static_cast<long>(m_nCCs);
}
}

View File

@@ -42,6 +42,7 @@ namespace HACD
~GraphVertex(){ delete m_convexHull;};
private:
long m_name;
long m_cc;
std::set<long> m_edges;
bool m_deleted;
std::vector<long> m_ancestors;
@@ -100,12 +101,14 @@ namespace HACD
long GetEdgeID(long v1, long v2) const;
void Clear();
void Print() const;
long ExtractCCs();
Graph();
virtual ~Graph();
void Allocate(size_t nV, size_t nE);
private:
size_t m_nCCs;
size_t m_nV;
size_t m_nE;
std::vector<GraphEdge> m_edges;

View File

@@ -20,6 +20,7 @@
#include <string.h>
#include <algorithm>
#include <iterator>
#include <limits>
namespace HACD
{
@@ -61,13 +62,13 @@ namespace HACD
vertexToTriangles.resize(m_nPoints);
for(size_t t = 0; t < m_nTriangles; ++t)
{
vertexToTriangles[m_triangles[t].X()].insert(t);
vertexToTriangles[m_triangles[t].Y()].insert(t);
vertexToTriangles[m_triangles[t].Z()].insert(t);
vertexToTriangles[m_triangles[t].X()].insert(static_cast<long>(t));
vertexToTriangles[m_triangles[t].Y()].insert(static_cast<long>(t));
vertexToTriangles[m_triangles[t].Z()].insert(static_cast<long>(t));
}
m_graph.Clear();
m_graph.Allocate(m_nTriangles, 3 * m_nTriangles);
m_graph.Allocate(m_nTriangles, 5 * m_nTriangles);
unsigned long long tr1[3];
unsigned long long tr2[3];
long i1, j1, k1, i2, j2, k2;
@@ -112,6 +113,65 @@ namespace HACD
}
}
}
if (m_ccConnectDist >= 0.0)
{
m_graph.ExtractCCs();
if (m_graph.m_nCCs > 1)
{
std::vector< std::set<long> > cc2V;
cc2V.resize(m_graph.m_nCCs);
long cc;
for(size_t t = 0; t < m_nTriangles; ++t)
{
cc = m_graph.m_vertices[t].m_cc;
cc2V[cc].insert(m_triangles[t].X());
cc2V[cc].insert(m_triangles[t].Y());
cc2V[cc].insert(m_triangles[t].Z());
}
for(size_t cc1 = 0; cc1 < m_graph.m_nCCs; ++cc1)
{
for(size_t cc2 = cc1+1; cc2 < m_graph.m_nCCs; ++cc2)
{
std::set<long>::const_iterator itV1(cc2V[cc1].begin()), itVEnd1(cc2V[cc1].end());
for(; itV1 != itVEnd1; ++itV1)
{
double distC1C2 = std::numeric_limits<double>::max();
double dist;
t1 = -1;
t2 = -1;
std::set<long>::const_iterator itV2(cc2V[cc2].begin()), itVEnd2(cc2V[cc2].end());
for(; itV2 != itVEnd2; ++itV2)
{
dist = (m_points[*itV1] - m_points[*itV2]).GetNorm();
if (dist < distC1C2)
{
distC1C2 = dist;
t1 = *vertexToTriangles[*itV1].begin();
std::set<long>::const_iterator it2(vertexToTriangles[*itV2].begin()),
it2End(vertexToTriangles[*itV2].end());
t2 = -1;
for(; it2 != it2End; ++it2)
{
if (*it2 != t1)
{
t2 = *it2;
break;
}
}
}
}
if (distC1C2 < m_ccConnectDist && t1 > 0 && t2 > 0)
{
m_graph.AddEdge(t1, t2);
}
}
}
}
}
}
}
void HACD::InitializeDualGraph()
{
@@ -294,6 +354,7 @@ namespace HACD
m_nMinClusters = 3;
m_facePoints = 0;
m_faceNormals = 0;
m_ccConnectDist = 30;
}
HACD::~HACD(void)
{
@@ -479,8 +540,8 @@ namespace HACD
m_pqueue.reserve(m_graph.m_nE + 100);
for (size_t e=0; e < m_graph.m_nE; ++e)
{
ComputeEdgeCost(e);
m_pqueue.push(GraphEdgePriorityQueue(e, m_graph.m_edges[e].m_error));
ComputeEdgeCost(static_cast<long>(e));
m_pqueue.push(GraphEdgePriorityQueue(static_cast<long>(e), m_graph.m_edges[e].m_error));
}
return true;
}
@@ -495,7 +556,7 @@ namespace HACD
double ptgStep = 1.0;
while ( (globalConcavity < m_concavity) &&
(m_graph.GetNVertices() > m_nMinClusters) &&
(m_graph.GetNEdges()> 1))
(m_graph.GetNEdges() > 0))
{
progress = 100.0-m_graph.GetNVertices() * 100.0 / m_nTriangles;
if (fabs(progress-progressOld) > ptgStep && m_callBack)
@@ -520,18 +581,16 @@ namespace HACD
done = false;
if (m_pqueue.size() == 0)
{
done = true;
break;
}
else
{
currentEdge = m_pqueue.top();
m_pqueue.pop();
done = true;
break;
}
currentEdge = m_pqueue.top();
m_pqueue.pop();
}
while ( m_graph.m_edges[currentEdge.m_name].m_deleted ||
m_graph.m_edges[currentEdge.m_name].m_error != currentEdge.m_priority);
if (m_graph.m_edges[currentEdge.m_name].m_concavity < m_concavity && !done)
{
globalConcavity = std::max<double>(globalConcavity ,m_graph.m_edges[currentEdge.m_name].m_concavity);
@@ -557,8 +616,8 @@ namespace HACD
for(; itE != itEEnd; ++itE)
{
size_t e = *itE;
ComputeEdgeCost(e);
m_pqueue.push(GraphEdgePriorityQueue(e, m_graph.m_edges[e].m_error));
ComputeEdgeCost(static_cast<long>(e));
m_pqueue.push(GraphEdgePriorityQueue(static_cast<long>(e), m_graph.m_edges[e].m_error));
}
}
else
@@ -570,10 +629,10 @@ namespace HACD
{
m_pqueue.pop();
}
m_cVertices.clear();
m_cVertices.reserve(m_nClusters);
m_nClusters = m_graph.GetNVertices();
m_cVertices.reserve(m_nClusters);
for (size_t p=0, v = 0; v != m_graph.m_vertices.size(); ++v)
{
if (!m_graph.m_vertices[v].m_deleted)
@@ -585,7 +644,7 @@ namespace HACD
(*m_callBack)(msg, 0.0, 0.0, m_nClusters);
p++;
}
m_cVertices.push_back(v);
m_cVertices.push_back(static_cast<long>(v));
}
}
if (m_callBack)
@@ -595,6 +654,7 @@ namespace HACD
}
}
bool HACD::Compute(bool fullCH, bool exportDistPoints)
{
if ( !m_points || !m_triangles || !m_nPoints || !m_nTriangles)
@@ -614,11 +674,12 @@ namespace HACD
msg << "\t compacity weigth \t" << m_alpha << std::endl;
msg << "\t volume weigth \t" << m_beta << std::endl;
msg << "\t # vertices per convex-hull \t" << m_nVerticesPerCH << std::endl;
msg << "\t Scale \t" << m_scale << std::endl;
msg << "\t Add extra distance points \t" << m_addExtraDistPoints << std::endl;
msg << "\t Add neighbours distance points \t" << m_addNeighboursDistPoints << std::endl;
msg << "\t Add face distance points \t" << m_addFacesPoints << std::endl;
msg << "\t Produce full convex-hulls \t" << fullCH << std::endl;
msg << "\t scale \t" << m_scale << std::endl;
msg << "\t add extra distance points \t" << m_addExtraDistPoints << std::endl;
msg << "\t add neighbours distance points \t" << m_addNeighboursDistPoints << std::endl;
msg << "\t add face distance points \t" << m_addFacesPoints << std::endl;
msg << "\t produce full convex-hulls \t" << fullCH << std::endl;
msg << "\t max. distance to connect CCs \t" << m_ccConnectDist << std::endl;
(*m_callBack)(msg.str().c_str(), 0.0, 0.0, nV);
}
if (m_callBack) (*m_callBack)("+ Normalizing Data\n", 0.0, 0.0, nV);
@@ -643,10 +704,10 @@ namespace HACD
for (size_t p = 0; p != m_cVertices.size(); ++p)
{
size_t v = m_cVertices[p];
m_partition[v] = p;
m_partition[v] = static_cast<long>(p);
for(size_t a = 0; a < m_graph.m_vertices[v].m_ancestors.size(); a++)
{
m_partition[m_graph.m_vertices[v].m_ancestors[a]] = p;
m_partition[m_graph.m_vertices[v].m_ancestors[a]] = static_cast<long>(p);
}
// compute the convex-hull
const std::map<long, DPoint> & pointsCH = m_graph.m_vertices[v].m_distPoints;
@@ -666,7 +727,7 @@ namespace HACD
}
else
{
m_convexHulls[p].Process(m_nVerticesPerCH);
m_convexHulls[p].Process(static_cast<unsigned long>(m_nVerticesPerCH));
}
if (exportDistPoints)
{

View File

@@ -65,13 +65,11 @@ namespace HACD
};
inline bool operator<(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs)
{
if (lhs.m_priority!=rhs.m_priority) return lhs.m_priority<rhs.m_priority;
return lhs.m_name < rhs.m_name;
return lhs.m_priority<rhs.m_priority;
}
inline bool operator>(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs)
{
if (lhs.m_priority!=rhs.m_priority) return lhs.m_priority>rhs.m_priority;
return lhs.m_name > rhs.m_name;
return lhs.m_priority>rhs.m_priority;
}
typedef void (*CallBackFunction)(const char *, double, double, size_t);
@@ -150,6 +148,12 @@ namespace HACD
//! Gives the maximum allowed concavity.
//! @return maximum concavity
double GetConcavity() const { return m_concavity;}
//! Sets the maximum allowed distance to get CCs connected.
//! @param concavity maximum distance to get CCs connected
void SetConnectDist(double ccConnectDist) { m_ccConnectDist = ccConnectDist;}
//! Gives the maximum allowed distance to get CCs connected.
//! @return maximum distance to get CCs connected
double GetConnectDist() const { return m_ccConnectDist;}
//! Sets the volume weight.
//! @param beta volume weight
void SetVolumeWeight(double beta) { m_beta = beta;}
@@ -252,6 +256,7 @@ namespace HACD
size_t m_nPoints; //>! number of vertices in the original mesh
size_t m_nClusters; //>! number of clusters
size_t m_nMinClusters; //>! minimum number of clusters
double m_ccConnectDist; //>! maximum allowed distance to connect CCs
double m_concavity; //>! maximum concavity
double m_alpha; //>! compacity weigth
double m_beta; //>! volume weigth

View File

@@ -16,7 +16,7 @@
#include <limits>
namespace HACD
{
const long ICHull::sc_dummyIndex = static_cast<size_t>(-1);
const long ICHull::sc_dummyIndex = std::numeric_limits<long>::max();
ICHull::ICHull(void)
{
m_distPoints = 0;
@@ -36,7 +36,7 @@ namespace HACD
vertex->GetData().m_pos.X() = points[i].X();
vertex->GetData().m_pos.Y() = points[i].Y();
vertex->GetData().m_pos.Z() = points[i].Z();
vertex->GetData().m_name = i;
vertex->GetData().m_name = static_cast<long>(i);
}
return true;
}
@@ -788,7 +788,7 @@ namespace HACD
bary.Z() += m_mesh.m_vertices.GetHead()->GetData().m_pos.Z();
m_mesh.m_vertices.Next();
}
bary /= nV;
bary /= static_cast<double>(nV);
size_t nT = m_mesh.m_triangles.GetSize();
Vec3<double> ver0, ver1, ver2;

View File

@@ -231,9 +231,9 @@ namespace HACD
for(size_t f = 0; f < nT; f++)
{
TMMTriangle & currentTriangle = m_triangles.GetData();
triangles[f].X() = currentTriangle.m_vertices[0]->GetData().m_id;
triangles[f].Y() = currentTriangle.m_vertices[1]->GetData().m_id;
triangles[f].Z() = currentTriangle.m_vertices[2]->GetData().m_id;
triangles[f].X() = static_cast<long>(currentTriangle.m_vertices[0]->GetData().m_id);
triangles[f].Y() = static_cast<long>(currentTriangle.m_vertices[1]->GetData().m_id);
triangles[f].Z() = static_cast<long>(currentTriangle.m_vertices[2]->GetData().m_id);
m_triangles.Next();
}
}
@@ -373,7 +373,7 @@ namespace HACD
Vec3<double> s0 = (I-V0) ^ edge3;
Vec3<double> s1 = (I-V1) ^ edge1;
Vec3<double> s2 = (I-V2) ^ edge2;
if (s0*s1 >= 0.0 && s2*s1 >= 0.0)
if (s0*s1 > -1e-9 && s2*s1 > -1e-9)
{
return 1;
}

View File

@@ -21,7 +21,7 @@
namespace HACD
{
typedef float Real;
typedef double Real;
//! Vector dim 3.
template < typename T > class Vec3
{