working backup
This commit is contained in:
parent
6eb4a5b293
commit
36db742b83
|
@ -26,6 +26,7 @@ class Pivot {
|
||||||
ScalarType radius; //default 1 (not meaningful
|
ScalarType radius; //default 1 (not meaningful
|
||||||
ScalarType mindist; //minimum distance between points in the mesh (% of radius)
|
ScalarType mindist; //minimum distance between points in the mesh (% of radius)
|
||||||
ScalarType crease; // -0.5
|
ScalarType crease; // -0.5
|
||||||
|
bool normals; //default false
|
||||||
Box3<ScalarType> box;
|
Box3<ScalarType> box;
|
||||||
|
|
||||||
MESH &mesh;
|
MESH &mesh;
|
||||||
|
@ -37,7 +38,11 @@ class Pivot {
|
||||||
//this edge belongs to
|
//this edge belongs to
|
||||||
int face; //corresponding face
|
int face; //corresponding face
|
||||||
Coord center; //center of the sphere touching the face
|
Coord center; //center of the sphere touching the face
|
||||||
int count; //test delay touch edges.
|
int count; //test delay touch edges.
|
||||||
|
|
||||||
|
float angle;
|
||||||
|
int candidate;
|
||||||
|
Coord newcenter;
|
||||||
|
|
||||||
//the loops in the front are mantained as a double linked list
|
//the loops in the front are mantained as a double linked list
|
||||||
typename std::list<Edge>::iterator next;
|
typename std::list<Edge>::iterator next;
|
||||||
|
@ -46,7 +51,7 @@ class Pivot {
|
||||||
Edge() {}
|
Edge() {}
|
||||||
Edge(int _v0, int _v1, int _v2, int _face, Point3f &_center):
|
Edge(int _v0, int _v1, int _v2, int _face, Point3f &_center):
|
||||||
v0(_v0), v1(_v1), v2(_v2),
|
v0(_v0), v1(_v1), v2(_v2),
|
||||||
face(_face), center(_center), count(0) {
|
face(_face), center(_center), count(-1) {
|
||||||
assert(v0 != v1 && v1 != v2 && v0 != v2);
|
assert(v0 != v1 && v1 != v2 && v0 != v2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -66,8 +71,8 @@ class Pivot {
|
||||||
int last_seed;
|
int last_seed;
|
||||||
|
|
||||||
|
|
||||||
Pivot(MESH &_mesh, ScalarType _radius, ScalarType _mindist = 0.05, ScalarType _crease = -0.5):
|
Pivot(MESH &_mesh, ScalarType _radius, ScalarType _mindist = 0.1, ScalarType _crease = -0.5):
|
||||||
mesh(_mesh), radius(_radius), mindist(_mindist), crease(_crease), last_seed(0) {
|
mesh(_mesh), radius(_radius), mindist(_mindist), crease(_crease), normals(false), last_seed(0) {
|
||||||
|
|
||||||
//Compute bounding box. (this may be passed as a parameter?
|
//Compute bounding box. (this may be passed as a parameter?
|
||||||
for(int i = 0; i < mesh.vert.size(); i++)
|
for(int i = 0; i < mesh.vert.size(); i++)
|
||||||
|
@ -83,10 +88,54 @@ Pivot(MESH &_mesh, ScalarType _radius, ScalarType _mindist = 0.05, ScalarType _c
|
||||||
grid.Set(mesh.vert.begin(), mesh.vert.end(), box);
|
grid.Set(mesh.vert.begin(), mesh.vert.end(), box);
|
||||||
nb.clear();
|
nb.clear();
|
||||||
nb.resize(mesh.vert.size(), 0);
|
nb.resize(mesh.vert.size(), 0);
|
||||||
for(int i = 0; i < mesh.vert.size(); i++)
|
if(mesh.face.size()) {
|
||||||
mesh.vert[i].ClearFlags();
|
//init border from mesh
|
||||||
|
Point3x center;
|
||||||
|
CVertex *start = &*mesh.vert.begin();
|
||||||
|
for(int i = 0; i < mesh.face.size(); i++) {
|
||||||
|
CFace &face = mesh.face[i];
|
||||||
|
for(int k = 0; k < 3; k++) {
|
||||||
|
if(!face.V(k)->IsB()) face.V(k)->SetV();
|
||||||
|
if(face.IsB(k)) {
|
||||||
|
//compute center:
|
||||||
|
findSphere(face.P(k), face.P((k+1)%3), face.P((k+2)%3), center);
|
||||||
|
newEdge(Edgex(face.V((k)%3) -start, face.V((k+1)%3) - start, face.V((k+2)%3) - start,
|
||||||
|
i, center));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(typename std::list<Edgex>::iterator s = front.begin(); s != front.end(); s++) {
|
||||||
|
(*s).previous = front.end();
|
||||||
|
(*s).next = front.end();
|
||||||
|
printf("%d %d\n", (*s).v0, (*s).v1);
|
||||||
|
}
|
||||||
|
//now create loops:
|
||||||
|
for(typename std::list<Edgex>::iterator s = front.begin(); s != front.end(); s++) {
|
||||||
|
for(typename std::list<Edgex>::iterator j = front.begin(); j != front.end(); j++) {
|
||||||
|
if(s == j) continue;
|
||||||
|
if((*s).v1 != (*j).v0) continue;
|
||||||
|
if((*j).previous != front.end()) continue;
|
||||||
|
(*s).next = j;
|
||||||
|
(*j).previous = s;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* for(typename std::list<Edgex>::iterator s = front.begin(); s != front.end(); s++) {
|
||||||
|
assert((*s).next != front.end());
|
||||||
|
assert((*s).previous != front.end());
|
||||||
|
} */
|
||||||
|
for(int i = 0; i < mesh.face.size(); i++) {
|
||||||
|
CFace &face = mesh.face[i];
|
||||||
|
for(int k = 0; k < 3; k++)
|
||||||
|
face.V(k) = (CVertex *)(face.V(k) - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < mesh.vert.size(); i++)
|
||||||
|
mesh.vert[i].ClearFlags();
|
||||||
|
|
||||||
|
}
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
}
|
}
|
||||||
/* return false if you want to stop.\n */
|
/* return false if you want to stop.\n */
|
||||||
void buildMesh(CallBackPos *call = NULL, int interval = 512) {
|
void buildMesh(CallBackPos *call = NULL, int interval = 512) {
|
||||||
|
@ -122,13 +171,14 @@ void buildMesh(CallBackPos *call = NULL, int interval = 512) {
|
||||||
bool seed(bool outside = true, int start = -1) {
|
bool seed(bool outside = true, int start = -1) {
|
||||||
|
|
||||||
//pick a random point (well...)
|
//pick a random point (well...)
|
||||||
if(start == -1) start = rand()%mesh.vert.size();
|
if(start == -1) start = 0;//rand()%mesh.vert.size();
|
||||||
|
|
||||||
//get a sphere of neighbours
|
//get a sphere of neighbours
|
||||||
std::vector<int> targets;
|
std::vector<int> targets;
|
||||||
std::vector<ScalarType> dists;
|
std::vector<ScalarType> dists;
|
||||||
int n = getInSphere(mesh.vert[start].P(), 2*radius, targets, dists);
|
int n = getInSphere(mesh.vert[start].P(), 2*radius, targets, dists);
|
||||||
if(n < 3) {
|
if(n < 3) {
|
||||||
|
mesh.vert[start].SetD();
|
||||||
//bad luck. we should call seed again (assuming random pick) up to
|
//bad luck. we should call seed again (assuming random pick) up to
|
||||||
//some maximum tries. im lazy.
|
//some maximum tries. im lazy.
|
||||||
return false;
|
return false;
|
||||||
|
@ -160,8 +210,14 @@ bool seed(bool outside = true, int start = -1) {
|
||||||
if((p2 - p0).Norm() < mindist*radius) continue;
|
if((p2 - p0).Norm() < mindist*radius) continue;
|
||||||
if((p2 - p1).Norm() < mindist*radius) continue;
|
if((p2 - p1).Norm() < mindist*radius) continue;
|
||||||
Point3x normal = (p1 - p0)^(p2 - p0);
|
Point3x normal = (p1 - p0)^(p2 - p0);
|
||||||
//check normal pointing inside
|
if(!normals) {
|
||||||
if(normal * out < 0) continue;
|
//check normal pointing inside
|
||||||
|
if(normal * out < 0) continue;
|
||||||
|
} else {
|
||||||
|
if(normal * vv0.N() < 0) continue;
|
||||||
|
if(normal * vv1.N() < 0) continue;
|
||||||
|
if(normal * vv2.N() < 0) continue;
|
||||||
|
}
|
||||||
if(!findSphere(p0, p1, p2, center)) continue;
|
if(!findSphere(p0, p1, p2, center)) continue;
|
||||||
|
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
|
@ -241,7 +297,6 @@ int addFace() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!front.size()) {
|
if(!front.size()) {
|
||||||
return -1;
|
|
||||||
//maybe there are unconnected parts of the mesh:
|
//maybe there are unconnected parts of the mesh:
|
||||||
//find a non D, V, B point and try to seed if failed D it.
|
//find a non D, V, B point and try to seed if failed D it.
|
||||||
for(; last_seed < mesh.vert.size(); ++last_seed) {
|
for(; last_seed < mesh.vert.size(); ++last_seed) {
|
||||||
|
@ -260,21 +315,40 @@ int addFace() {
|
||||||
Edgex &e = *ei;
|
Edgex &e = *ei;
|
||||||
Edgex &previous = *e.previous;
|
Edgex &previous = *e.previous;
|
||||||
Edgex &next = *e.next;
|
Edgex &next = *e.next;
|
||||||
|
|
||||||
|
/* if(e.count == -1) {
|
||||||
|
printf("angle %f\n", e.angle);
|
||||||
|
if(e.angle < 1) e.count = 0;
|
||||||
|
else if(e.angle < 1.5) e.count = 2;
|
||||||
|
else if(e.angle < 2) e.count = 4;
|
||||||
|
else e.count = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e.count > 0) {
|
||||||
|
printf("delay\n");
|
||||||
|
e.count--;
|
||||||
|
moveBack(ei);
|
||||||
|
return 0;
|
||||||
|
} */
|
||||||
|
|
||||||
int v0 = e.v0, v1 = e.v1;
|
int v0 = e.v0, v1 = e.v1;
|
||||||
|
|
||||||
|
assert(nb[v0] < 10 && nb[v1] < 10);
|
||||||
int v2;
|
int v2;
|
||||||
Point3x center;
|
Point3x center;
|
||||||
std::vector<int> targets;
|
bool success = pivot(e);
|
||||||
bool success = pivot(e, v2, center, targets);
|
v2 = e.candidate;
|
||||||
|
center = e.newcenter;
|
||||||
|
|
||||||
//if no pivoting or we are trying to connect to the inside of the mesh.
|
//if no pivoting or we are trying to connect to the inside of the mesh.
|
||||||
if(!success || mesh.vert[v2].IsV()) {
|
if(!success || mesh.vert[v2].IsV()) {
|
||||||
|
printf("no success\n");
|
||||||
killEdge(ei);
|
killEdge(ei);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//does v2 belongs to a front? (and which?)
|
//does v2 belongs to a front? (and which?)
|
||||||
typename std::list<Edgex>::iterator touch = touches(v2, ei);
|
typename std::list<Edgex>::iterator touch = touches(ei);
|
||||||
|
|
||||||
assert(v2 != v0 && v2 != v1);
|
assert(v2 != v0 && v2 != v1);
|
||||||
|
|
||||||
|
@ -307,6 +381,7 @@ int addFace() {
|
||||||
|
|
||||||
previous.next = e.next;
|
previous.next = e.next;
|
||||||
next.previous = e.previous;
|
next.previous = e.previous;
|
||||||
|
pivot(previous);
|
||||||
moveBack(e.previous);
|
moveBack(e.previous);
|
||||||
|
|
||||||
//this checks if we can glue something to e.previous
|
//this checks if we can glue something to e.previous
|
||||||
|
@ -315,6 +390,7 @@ int addFace() {
|
||||||
|
|
||||||
|
|
||||||
} else if(v2 == next.v1) {
|
} else if(v2 == next.v1) {
|
||||||
|
|
||||||
|
|
||||||
/*touching next edge (we reuse next)
|
/*touching next edge (we reuse next)
|
||||||
previous
|
previous
|
||||||
|
@ -333,6 +409,7 @@ int addFace() {
|
||||||
next.center = center;
|
next.center = center;
|
||||||
next.previous = e.previous;
|
next.previous = e.previous;
|
||||||
previous.next = e.next;
|
previous.next = e.next;
|
||||||
|
pivot(next);
|
||||||
// moveBack(e.next);
|
// moveBack(e.next);
|
||||||
|
|
||||||
//this checks if we can glue something to e.previous
|
//this checks if we can glue something to e.previous
|
||||||
|
@ -340,7 +417,12 @@ int addFace() {
|
||||||
front.erase(ei);
|
front.erase(ei);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
/* if(e.count == -1) {
|
||||||
|
e.count = 4;
|
||||||
|
moveBack(ei);
|
||||||
|
return 0;
|
||||||
|
}*/
|
||||||
/* this code would delay the joining edge to avoid bad situations not used but..
|
/* this code would delay the joining edge to avoid bad situations not used but..
|
||||||
if(e.count < 2) {
|
if(e.count < 2) {
|
||||||
e.count++;
|
e.count++;
|
||||||
|
@ -387,7 +469,9 @@ int addFace() {
|
||||||
(*up).v1 = v2;
|
(*up).v1 = v2;
|
||||||
(*up).face = fn;
|
(*up).face = fn;
|
||||||
(*up).center = center;
|
(*up).center = center;
|
||||||
moveBack(ei);
|
pivot(*up);
|
||||||
|
pivot(*down);
|
||||||
|
moveBack(ei);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -420,6 +504,8 @@ int addFace() {
|
||||||
e.face = fn;
|
e.face = fn;
|
||||||
e.center = center;
|
e.center = center;
|
||||||
e.next = down;
|
e.next = down;
|
||||||
|
pivot(*ei);
|
||||||
|
pivot(*down);
|
||||||
moveBack(ei);
|
moveBack(ei);
|
||||||
}
|
}
|
||||||
addFace(v0, v2, v1);
|
addFace(v0, v2, v1);
|
||||||
|
@ -430,7 +516,7 @@ int addFace() {
|
||||||
|
|
||||||
/* return new vertex and the center of the new sphere pivoting from edge
|
/* return new vertex and the center of the new sphere pivoting from edge
|
||||||
if the vertex belongs to another edge, touch points to it. */
|
if the vertex belongs to another edge, touch points to it. */
|
||||||
bool pivot(Edgex &edge, int &candidate, Point3x &end_pivot, std::vector<int> &targets) {
|
bool pivot(Edgex &edge) {
|
||||||
Point3x v0 = mesh.vert[edge.v0].P();
|
Point3x v0 = mesh.vert[edge.v0].P();
|
||||||
Point3x v1 = mesh.vert[edge.v1].P();
|
Point3x v1 = mesh.vert[edge.v1].P();
|
||||||
Point3x v2 = mesh.vert[edge.v2].P();
|
Point3x v2 = mesh.vert[edge.v2].P();
|
||||||
|
@ -440,8 +526,7 @@ int addFace() {
|
||||||
Point3x &normal = mesh.face[edge.face].N();
|
Point3x &normal = mesh.face[edge.face].N();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Point3x normal = ((v1 - v0)^(v2 - v0)).Normalize();
|
Point3x normal = ((v1 - v0)^(v2 - v0)).Normalize();
|
||||||
|
|
||||||
Point3x middle = (v0 + v1)/2;
|
Point3x middle = (v0 + v1)/2;
|
||||||
Point3x start_pivot = edge.center - middle;
|
Point3x start_pivot = edge.center - middle;
|
||||||
Point3x axis = (v1 - v0);
|
Point3x axis = (v1 - v0);
|
||||||
|
@ -453,13 +538,13 @@ int addFace() {
|
||||||
// r is the radius of the thorus of all possible spheres passing throug v0 and v1
|
// r is the radius of the thorus of all possible spheres passing throug v0 and v1
|
||||||
ScalarType r = sqrt(radius*radius - axis_len/4);
|
ScalarType r = sqrt(radius*radius - axis_len/4);
|
||||||
|
|
||||||
|
std::vector<int> targets;
|
||||||
std::vector<ScalarType> dists;
|
std::vector<ScalarType> dists;
|
||||||
getInSphere(middle, r + radius, targets, dists);
|
getInSphere(middle, r + radius, targets, dists);
|
||||||
|
|
||||||
if(targets.size() == 0) return false; //this really would be strange but one never knows.
|
if(targets.size() == 0) return false; //this really would be strange but one never knows.
|
||||||
|
|
||||||
candidate = -1;
|
edge.candidate = -1;
|
||||||
ScalarType minangle = 0;
|
ScalarType minangle = 0;
|
||||||
Point3x center; //to be computed for each sample
|
Point3x center; //to be computed for each sample
|
||||||
for(int i = 0; i < targets.size(); i++) {
|
for(int i = 0; i < targets.size(); i++) {
|
||||||
|
@ -472,9 +557,12 @@ int addFace() {
|
||||||
|
|
||||||
Point3x p = mesh.vert[id].P();
|
Point3x p = mesh.vert[id].P();
|
||||||
|
|
||||||
|
if(normals && normal * mesh.vert[id].N() < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
/* Prevent 360 edges, also often reject ~ 50% points */
|
/* Prevent 360 edges, also often reject ~ 50% points */
|
||||||
Point3x n = ((p - v0)^(v1 - v0)).Normalize();
|
Point3x n = ((p - v0)^(v1 - v0)).Normalize();
|
||||||
if(n * normal < -0.5) {
|
if(n * normal < crease) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,7 +577,7 @@ int addFace() {
|
||||||
|
|
||||||
/* adding a small bias to already chosen vertices.
|
/* adding a small bias to already chosen vertices.
|
||||||
doesn't solve numerical problems, but helps. */
|
doesn't solve numerical problems, but helps. */
|
||||||
if(mesh.vert[id].IsB()) alpha -= 0.001;
|
// if(mesh.vert[id].IsB()) alpha -= 0.001;
|
||||||
|
|
||||||
/* Sometimes alpha might be little less then M_PI while it should be 0,
|
/* Sometimes alpha might be little less then M_PI while it should be 0,
|
||||||
by numerical errors: happens for example pivoting
|
by numerical errors: happens for example pivoting
|
||||||
|
@ -503,18 +591,23 @@ int addFace() {
|
||||||
|
|
||||||
if(alpha > beta) alpha -= 2*M_PI;
|
if(alpha > beta) alpha -= 2*M_PI;
|
||||||
}
|
}
|
||||||
if(candidate == -1 || alpha < minangle) {
|
//if alphs < 0.1
|
||||||
candidate = id;
|
|
||||||
minangle = alpha;
|
//scale alpha by distance:
|
||||||
end_pivot = center;
|
if(edge.candidate == -1 ||
|
||||||
|
(alpha < 0.1 && id < edge.candidate) ||
|
||||||
|
(alpha >= 0.1 && alpha < edge.angle)) {
|
||||||
|
edge.candidate = id;
|
||||||
|
edge.angle = alpha;
|
||||||
|
edge.newcenter = center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//found no point suitable.
|
//found no point suitable.
|
||||||
if(candidate == -1) {
|
if(edge.candidate == -1 || normal * mesh.vert[edge.candidate].N() < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(candidate != edge.v0 && candidate != edge.v1);
|
assert(edge.candidate != edge.v0 && edge.candidate != edge.v1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,7 +633,7 @@ int addFace() {
|
||||||
bool checkEdge(int v0, int v1) {
|
bool checkEdge(int v0, int v1) {
|
||||||
int tot = 0;
|
int tot = 0;
|
||||||
//HACK to speed up things until i can use a seach structure
|
//HACK to speed up things until i can use a seach structure
|
||||||
int i = mesh.face.size() - 2*(front.size());
|
int i = mesh.face.size() - 4*(front.size());
|
||||||
if(front.size() < 100) i = mesh.face.size() - 100;
|
if(front.size() < 100) i = mesh.face.size() - 100;
|
||||||
// i = 0;
|
// i = 0;
|
||||||
if(i < 0) i = 0;
|
if(i < 0) i = 0;
|
||||||
|
@ -697,10 +790,11 @@ int addFace() {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
typename std::list<Edgex>::iterator touches(int v, typename std::list<Edgex>::iterator e) {
|
|
||||||
|
typename std::list<Edgex>::iterator touches(typename std::list<Edgex>::iterator e) {
|
||||||
//TODO what happens when it touches more than one front?
|
//TODO what happens when it touches more than one front?
|
||||||
//might still work.
|
//might still work.
|
||||||
|
int v = (*e).candidate;
|
||||||
typename std::list<Edgex>::iterator touch = front.end();
|
typename std::list<Edgex>::iterator touch = front.end();
|
||||||
if(mesh.vert[v].IsB()) {
|
if(mesh.vert[v].IsB()) {
|
||||||
//test nearby Edges: it is faster
|
//test nearby Edges: it is faster
|
||||||
|
|
Loading…
Reference in New Issue