Fixed degenerate faces.
This commit is contained in:
parent
fcfab2d616
commit
4dc937e514
|
@ -17,7 +17,7 @@
|
||||||
//#include "border.h"
|
//#include "border.h"
|
||||||
|
|
||||||
#include "decimate.h"
|
#include "decimate.h"
|
||||||
//#include <wrap/io_trimesh/export_ply.h>
|
#include <wrap/io_trimesh/export_ply.h>
|
||||||
|
|
||||||
using namespace vcg;
|
using namespace vcg;
|
||||||
using namespace tri;
|
using namespace tri;
|
||||||
|
@ -59,11 +59,10 @@ float nxs::Decimate(Decimation mode,
|
||||||
vector<Link> &newbord,
|
vector<Link> &newbord,
|
||||||
vector<int> &vert_remap) {
|
vector<int> &vert_remap) {
|
||||||
|
|
||||||
//Temporary test:
|
|
||||||
for(unsigned int i = 0; i < newface.size(); i+= 3) {
|
for(unsigned int i = 0; i < newface.size(); i+= 3) {
|
||||||
assert(newface[i*3] != newface[i*3+1]);
|
assert(newface[i] != newface[i+1]);
|
||||||
assert(newface[i*3] != newface[i*3+2]);
|
assert(newface[i] != newface[i+2]);
|
||||||
assert(newface[i*3+1] != newface[i*3+2]);
|
assert(newface[i+1] != newface[i+2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyMesh mesh;
|
MyMesh mesh;
|
||||||
|
@ -81,7 +80,7 @@ float nxs::Decimate(Decimation mode,
|
||||||
MyFace face;
|
MyFace face;
|
||||||
face.ClearFlags();
|
face.ClearFlags();
|
||||||
for(int k = 0; k < 3; k++) {
|
for(int k = 0; k < 3; k++) {
|
||||||
assert(newface[i+k] < mesh.vn);
|
assert(newface[i+k] < mesh.vert.size());
|
||||||
face.V(k) = &mesh.vert[newface[i+k]];
|
face.V(k) = &mesh.vert[newface[i+k]];
|
||||||
}
|
}
|
||||||
mesh.face.push_back(face);
|
mesh.face.push_back(face);
|
||||||
|
@ -92,57 +91,18 @@ float nxs::Decimate(Decimation mode,
|
||||||
for(unsigned int i = 0; i < newbord.size(); i++)
|
for(unsigned int i = 0; i < newbord.size(); i++)
|
||||||
mesh.vert[newbord[i].start_vert].ClearW();
|
mesh.vert[newbord[i].start_vert].ClearW();
|
||||||
|
|
||||||
|
|
||||||
// int FinalSize = mesh.face.size()/2;
|
|
||||||
// if(FinalSize > target_faces) FinalSize = target_faces;
|
|
||||||
|
|
||||||
|
|
||||||
/* if(target_faces == 2404) {
|
|
||||||
vcg::tri::io::ExporterPLY<MyMesh>::Save(mesh, "bum");
|
|
||||||
}*/
|
|
||||||
printf("mesh loaded %d %d \n",mesh.vn,mesh.fn);
|
printf("mesh loaded %d %d \n",mesh.vn,mesh.fn);
|
||||||
printf("reducing it to %i\n", target_faces);
|
printf("reducing it to %i\n", target_faces);
|
||||||
|
|
||||||
|
// if(target_faces == 1446)
|
||||||
|
// vcg::tri::io::ExporterPLY<MyMesh>::Save(mesh, "ribum.ply");
|
||||||
|
|
||||||
/*
|
|
||||||
int t0=clock();
|
|
||||||
vcg::tri::UpdateTopology<MyMesh>::VertexFace(mesh);
|
|
||||||
int t1=clock();
|
|
||||||
vcg::LocalOptimization<MyMesh> DeciSession(mesh);
|
|
||||||
MyTriEdgeCollapse::SetDefaultParams();
|
|
||||||
|
|
||||||
DeciSession.Init<MyTriEdgeCollapse>();
|
|
||||||
|
|
||||||
FinalSize = mesh.fn - FinalSize; //number of faces to remove
|
|
||||||
FinalSize/=2; //Number of vertices to remove
|
|
||||||
DeciSession.SetTargetOperations(FinalSize);
|
|
||||||
DeciSession.DoOptimization();
|
|
||||||
float error = DeciSession.currMetric/4;//1; //get error;
|
|
||||||
int t3=clock();
|
|
||||||
*/
|
|
||||||
float error;
|
float error;
|
||||||
if(mode == CLUSTER)
|
if(mode == CLUSTER)
|
||||||
error = Cluster(mesh, target_faces);
|
error = Cluster(mesh, target_faces);
|
||||||
else
|
else
|
||||||
error = Quadric(mesh, target_faces);
|
error = Quadric(mesh, target_faces);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* printf(" vol %d \n lkv %d \n lke %d \n lkf %d \n ood %d\n bor %d\n ",
|
|
||||||
MyTriEdgeCollapse::FailStat::Volume() ,
|
|
||||||
MyTriEdgeCollapse::FailStat::LinkConditionFace(),
|
|
||||||
MyTriEdgeCollapse::FailStat::LinkConditionEdge(),
|
|
||||||
MyTriEdgeCollapse::FailStat::LinkConditionVert(),
|
|
||||||
MyTriEdgeCollapse::FailStat::OutOfDate() ,
|
|
||||||
MyTriEdgeCollapse::FailStat::Border()
|
|
||||||
);*/
|
|
||||||
|
|
||||||
// printf("Completed in %i+%i+%i msec\n",t1-t0,t2-t1,t3-t2);
|
|
||||||
// printf("mesh %d %d \n",mesh.vn,mesh.fn);
|
|
||||||
|
|
||||||
//recort vert start.
|
|
||||||
|
|
||||||
|
|
||||||
newvert.clear();
|
newvert.clear();
|
||||||
newface.clear();
|
newface.clear();
|
||||||
|
|
||||||
|
@ -158,10 +118,8 @@ float nxs::Decimate(Decimation mode,
|
||||||
for(unsigned int i = 0; i < mesh.face.size(); i++) {
|
for(unsigned int i = 0; i < mesh.face.size(); i++) {
|
||||||
MyFace &face = mesh.face[i];
|
MyFace &face = mesh.face[i];
|
||||||
if(face.IsD()) continue;
|
if(face.IsD()) continue;
|
||||||
for(int k = 0; k < 3; k++) {
|
for(int k = 0; k < 3; k++)
|
||||||
assert(vert_remap[face.V(k) - vert_start] != -1);
|
|
||||||
newface.push_back(vert_remap[face.V(k) - vert_start]);
|
newface.push_back(vert_remap[face.V(k) - vert_start]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int i = 0; i < newbord.size(); i++) {
|
for(unsigned int i = 0; i < newbord.size(); i++) {
|
||||||
|
@ -172,9 +130,9 @@ float nxs::Decimate(Decimation mode,
|
||||||
|
|
||||||
//Temporary test again:
|
//Temporary test again:
|
||||||
for(unsigned int i = 0; i < newface.size(); i+= 3) {
|
for(unsigned int i = 0; i < newface.size(); i+= 3) {
|
||||||
assert(newface[i*3] != newface[i*3+1]);
|
assert(newface[i] != newface[i+1]);
|
||||||
assert(newface[i*3] != newface[i*3+2]);
|
assert(newface[i] != newface[i+2]);
|
||||||
assert(newface[i*3+1] != newface[i*3+2]);
|
assert(newface[i+1] != newface[i+2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
@ -243,6 +201,8 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
|
||||||
part.SetBox(box);
|
part.SetBox(box);
|
||||||
part.Init();
|
part.Init();
|
||||||
|
|
||||||
|
cerr << "inited points\n";
|
||||||
|
|
||||||
vector<Point3f> centroid;
|
vector<Point3f> centroid;
|
||||||
vector<unsigned int> count;
|
vector<unsigned int> count;
|
||||||
for(unsigned int i = 0; i < 3; i++) {
|
for(unsigned int i = 0; i < 3; i++) {
|
||||||
|
@ -266,12 +226,16 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
|
||||||
mesh.vert[remap[i]].P() = part[i].p;
|
mesh.vert[remap[i]].P() = part[i].p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << "remapping faces\n";
|
||||||
|
|
||||||
float error = 0;
|
float error = 0;
|
||||||
//rimappiamo le facce.....
|
//rimappiamo le facce.....
|
||||||
for(unsigned int i = 0; i < mesh.face.size(); i++) {
|
for(unsigned int i = 0; i < mesh.face.size(); i++) {
|
||||||
MyFace &face = mesh.face[i];
|
MyFace &face = mesh.face[i];
|
||||||
for(int k = 0; k < 3; k++) {
|
for(int k = 0; k < 3; k++) {
|
||||||
unsigned int target = part.Locate(face.V(k)->cP());
|
unsigned int target = part.Locate(face.V(k)->cP());
|
||||||
|
assert(target < remap.size());
|
||||||
|
assert(remap[target] < mesh.vert.size());
|
||||||
MyVertex &vert = mesh.vert[remap[target]];
|
MyVertex &vert = mesh.vert[remap[target]];
|
||||||
|
|
||||||
float dist = Distance(vert.cP(), face.V(k)->cP());
|
float dist = Distance(vert.cP(), face.V(k)->cP());
|
||||||
|
@ -281,6 +245,7 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << "Deleting faces\n";
|
||||||
for(unsigned int i = 0; i < mesh.face.size(); i++) {
|
for(unsigned int i = 0; i < mesh.face.size(); i++) {
|
||||||
MyFace &face = mesh.face[i];
|
MyFace &face = mesh.face[i];
|
||||||
assert(!face.IsD());
|
assert(!face.IsD());
|
||||||
|
@ -294,6 +259,8 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
|
||||||
mesh.fn--;
|
mesh.fn--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << "deleting vertices\n";
|
||||||
|
|
||||||
for(unsigned int i = 0; i < mesh.vert.size(); i++)
|
for(unsigned int i = 0; i < mesh.vert.size(); i++)
|
||||||
if(!mesh.vert[i].IsV() && mesh.vert[i].IsW()) {
|
if(!mesh.vert[i].IsV() && mesh.vert[i].IsW()) {
|
||||||
|
|
|
@ -185,7 +185,6 @@ void Nexus::Join(const std::set<unsigned int> &patches,
|
||||||
|
|
||||||
Nexus::Entry &entry = index[patch];
|
Nexus::Entry &entry = index[patch];
|
||||||
fcount += entry.nface;
|
fcount += entry.nface;
|
||||||
// assert(fcount < 0xffff);
|
|
||||||
for(unsigned int k = 0; k < entry.nvert; k++) {
|
for(unsigned int k = 0; k < entry.nvert; k++) {
|
||||||
if(vmap[k] == 0xffffffff) { //first time
|
if(vmap[k] == 0xffffffff) { //first time
|
||||||
vmap[k] = vcount++;
|
vmap[k] = vcount++;
|
||||||
|
@ -224,57 +223,45 @@ void Nexus::Join(const std::set<unsigned int> &patches,
|
||||||
fcount = 0;
|
fcount = 0;
|
||||||
for(i = patches.begin(); i != patches.end(); i++) {
|
for(i = patches.begin(); i != patches.end(); i++) {
|
||||||
Patch patch = GetPatch(*i);
|
Patch patch = GetPatch(*i);
|
||||||
// Border border = GetBorder(*i);
|
|
||||||
|
|
||||||
vector<unsigned int> &vmap = remap[*i];
|
vector<unsigned int> &vmap = remap[*i];
|
||||||
|
|
||||||
for(unsigned int i = 0; i < patch.nv; i++) {
|
for(unsigned int i = 0; i < patch.nv; i++) {
|
||||||
assert(vmap[i] < vcount);
|
assert(vmap[i] < vcount);
|
||||||
newvert[vmap[i]] = patch.Vert(i);
|
newvert[vmap[i]] = patch.Vert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int i = 0; i < patch.nf; i++) {
|
for(unsigned int i = 0; i < patch.nf; i++) {
|
||||||
for(int k = 0; k < 3; k++) {
|
unsigned short *face = patch.Face(i);
|
||||||
newface[3*fcount + k] = vmap[patch.Face(i)[k]];
|
if(patch.Vert(face[0]) == patch.Vert(face[1]) ||
|
||||||
|
patch.Vert(face[0]) == patch.Vert(face[2]) ||
|
||||||
|
patch.Vert(face[1]) == patch.Vert(face[2])) {
|
||||||
|
cerr << "MALEDETTO!" << endl;
|
||||||
|
Point3f &v0 = patch.Vert(face[0]);
|
||||||
|
Point3f &v1 = patch.Vert(face[1]);
|
||||||
|
Point3f &v2 = patch.Vert(face[2]);
|
||||||
|
cerr << "V0: " << v0[0] << " " << v0[1] << " " << v0[2] << endl;
|
||||||
|
cerr << "V1: " << v1[0] << " " << v1[1] << " " << v1[2] << endl;
|
||||||
|
cerr << "V2: " << v2[0] << " " << v2[1] << " " << v2[2] << endl;
|
||||||
|
}
|
||||||
|
if(patch.Face(i)[0] == patch.Face(i)[1] ||
|
||||||
|
patch.Face(i)[0] == patch.Face(i)[2] ||
|
||||||
|
patch.Face(i)[1] == patch.Face(i)[2]) {
|
||||||
|
cerr << "Damn: " << i << endl;
|
||||||
|
cerr << patch.Face(i)[0] << " " << patch.Face(i)[1]
|
||||||
|
<< patch.Face(i)[2] << endl;
|
||||||
}
|
}
|
||||||
assert(patch.Face(i)[0] != patch.Face(i)[1]);
|
|
||||||
assert(patch.Face(i)[0] != patch.Face(i)[2]);
|
|
||||||
assert(patch.Face(i)[1] != patch.Face(i)[2]);
|
|
||||||
assert(newface[3*fcount + 0] != newface[3*fcount + 1]);
|
|
||||||
assert(newface[3*fcount + 0] != newface[3*fcount + 2]);
|
|
||||||
assert(newface[3*fcount + 1] != newface[3*fcount + 2]);
|
|
||||||
|
|
||||||
fcount++;
|
|
||||||
assert(fcount *3 <= newface.size());
|
|
||||||
}
|
}
|
||||||
/* for(unsigned int i = 0; i < border.Size(); i++) {
|
for(unsigned int i = 0; i < patch.nf; i++)
|
||||||
Link link = border[i];
|
for(int k = 0; k < 3; k++)
|
||||||
if(patches.count(link.end_patch)) continue;
|
newface[fcount++] = vmap[patch.Face(i)[k]];
|
||||||
link.start_vert = vmap[link.start_vert];
|
|
||||||
newbord.push_back(link);*/
|
|
||||||
|
|
||||||
/* if(remap.count(link.end_patch)) continue;
|
|
||||||
Link newlink = link;
|
|
||||||
newlink.start_vert = vmap[link.start_vert];
|
|
||||||
newbord[bcount++] = newlink;*/
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
assert(fcount == newface.size());
|
||||||
|
|
||||||
set<Link>::iterator b;
|
set<Link>::iterator b;
|
||||||
for(b = newborders.begin(); b != newborders.end(); b++)
|
for(b = newborders.begin(); b != newborders.end(); b++)
|
||||||
newbord.push_back(*b);
|
newbord.push_back(*b);
|
||||||
|
|
||||||
/* unsigned int newentry = AddPatch(vcount, fcount, bcount);
|
|
||||||
Patch newpatch = GetPatch(newentry);
|
|
||||||
Border newborder = GetBorder(newentry);
|
|
||||||
|
|
||||||
memcpy(newpatch.VertBegin(), &(newvert)[0],
|
|
||||||
newvert.size() * sizeof(Point3f));
|
|
||||||
|
|
||||||
memcpy(newpatch.FaceBegin(), &(newface)[0],
|
|
||||||
newface.size() * sizeof(unsigned short));
|
|
||||||
|
|
||||||
memcpy(&(newborder[0]), &(newbord[0]),
|
|
||||||
newbord.size() * sizeof(Link));*/
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,23 +270,25 @@ void Nexus::Unify(float threshold) {
|
||||||
//TODO what if colors or normals or strips?
|
//TODO what if colors or normals or strips?
|
||||||
//TODO update totvert
|
//TODO update totvert
|
||||||
unsigned int duplicated = 0;
|
unsigned int duplicated = 0;
|
||||||
|
unsigned int degenerate = 0;
|
||||||
|
|
||||||
for(unsigned int p = 0; p < index.size(); p++) {
|
for(unsigned int p = 0; p < index.size(); p++) {
|
||||||
Nexus::Entry &entry = index[p];
|
Nexus::Entry &entry = index[p];
|
||||||
Patch patch = GetPatch(p);
|
Patch patch = GetPatch(p);
|
||||||
|
|
||||||
unsigned int vcount = 0;
|
unsigned int vcount = 0;
|
||||||
map<Point3f, unsigned short> vertices;
|
map<Point3f, unsigned short> vertices;
|
||||||
|
|
||||||
vector<unsigned short> remap;
|
vector<unsigned short> remap;
|
||||||
remap.resize(patch.nv);
|
remap.resize(patch.nv);
|
||||||
// map<unsigned short, unsigned short> remap;
|
|
||||||
for(unsigned int i = 0; i < patch.nv; i++) {
|
for(unsigned int i = 0; i < patch.nv; i++) {
|
||||||
Point3f &point = patch.Vert(i);
|
Point3f &point = patch.Vert(i);
|
||||||
|
|
||||||
if(!vertices.count(point)) {
|
if(!vertices.count(point))
|
||||||
vertices[point] = vcount++;
|
vertices[point] = vcount++;
|
||||||
} else {
|
else
|
||||||
duplicated++;
|
duplicated++;
|
||||||
}
|
|
||||||
|
|
||||||
remap[i] = vertices[point];
|
remap[i] = vertices[point];
|
||||||
}
|
}
|
||||||
|
@ -316,17 +305,29 @@ void Nexus::Unify(float threshold) {
|
||||||
|
|
||||||
|
|
||||||
vector<unsigned short> newface;
|
vector<unsigned short> newface;
|
||||||
newface.resize(patch.nf * 3);
|
//check no degenerate faces get created.
|
||||||
for(unsigned int f = 0; f < newface.size(); f++)
|
for(unsigned int f = 0; f < entry.nface; f++) {
|
||||||
newface[f] = remap[patch.FaceBegin()[f]];
|
unsigned short *face = patch.Face(f);
|
||||||
|
if(face[0] != face[1] && face[1] != face[2] && face[0] != face[2] &&
|
||||||
|
newvert[remap[face[0]]] != newvert[remap[face[1]]] &&
|
||||||
|
newvert[remap[face[0]]] != newvert[remap[face[2]]] &&
|
||||||
|
newvert[remap[face[1]]] != newvert[remap[face[2]]]) {
|
||||||
|
newface.push_back(remap[face[0]]);
|
||||||
|
newface.push_back(remap[face[1]]);
|
||||||
|
newface.push_back(remap[face[2]]);
|
||||||
|
} else {
|
||||||
|
degenerate++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//rewrite patch now.
|
//rewrite patch now.
|
||||||
entry.nvert = newvert.size();
|
entry.nvert = newvert.size();
|
||||||
|
entry.nface = newface.size()/3;
|
||||||
patch.Init(signature, entry.nvert, entry.nface);
|
patch.Init(signature, entry.nvert, entry.nface);
|
||||||
|
|
||||||
memcpy(patch.VertBegin(), &(newvert[0]), entry.nvert*sizeof(Point3f));
|
memcpy(patch.VertBegin(), &(newvert[0]), entry.nvert*sizeof(Point3f));
|
||||||
memcpy(patch.FaceBegin(), &(newface[0]), entry.nface*3*sizeof(unsigned short));
|
memcpy(patch.FaceBegin(), &(newface[0]), entry.nface*3*sizeof(short));
|
||||||
|
|
||||||
//fix patch borders now
|
//fix patch borders now
|
||||||
set<unsigned int> close; //bordering pathes
|
set<unsigned int> close; //bordering pathes
|
||||||
Border border = GetBorder(p);
|
Border border = GetBorder(p);
|
||||||
|
@ -350,8 +351,6 @@ void Nexus::Unify(float threshold) {
|
||||||
//finally: there may be duplicated borders
|
//finally: there may be duplicated borders
|
||||||
for(unsigned int p = 0; p < index.size(); p++) {
|
for(unsigned int p = 0; p < index.size(); p++) {
|
||||||
Border border = GetBorder(p);
|
Border border = GetBorder(p);
|
||||||
//Nexus::Entry &entry = index[p];
|
|
||||||
|
|
||||||
set<Link> links;
|
set<Link> links;
|
||||||
for(unsigned int b = 0; b < border.Size(); b++) {
|
for(unsigned int b = 0; b < border.Size(); b++) {
|
||||||
if(border[b].IsNull()) continue;
|
if(border[b].IsNull()) continue;
|
||||||
|
@ -361,7 +360,10 @@ void Nexus::Unify(float threshold) {
|
||||||
links.insert(border[b]);
|
links.insert(border[b]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
totvert -= duplicated;
|
totvert -= duplicated;
|
||||||
// cout << "Found " << duplicated << " duplicated vertices" << endl;
|
if(duplicated)
|
||||||
|
cerr << "Found " << duplicated << " duplicated vertices" << endl;
|
||||||
|
if(degenerate)
|
||||||
|
cerr << "Found " << degenerate << " degenerate face while unmifying\n";
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,7 +362,6 @@ Patch &NexusMt::LoadPatch(unsigned int p) {
|
||||||
if(ram_used > ram_size * 1.5)
|
if(ram_used > ram_size * 1.5)
|
||||||
FlushRam();
|
FlushRam();
|
||||||
|
|
||||||
cerr << "Ram: " << ram_used << endl;
|
|
||||||
return *(sgurz.patch);
|
return *(sgurz.patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,12 +106,11 @@ void nxs::NexusFill(Crude &crude,
|
||||||
//TODO an hash_map would be faster?
|
//TODO an hash_map would be faster?
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
map<unsigned int, unsigned short> remap;
|
map<unsigned int, unsigned short> remap;
|
||||||
|
|
||||||
for(unsigned int k = 0; k < patch.nf; k++) {
|
for(unsigned int k = 0; k < patch.nf; k++) {
|
||||||
Crude::Face &face = faces[k];
|
Crude::Face &face = faces[k];
|
||||||
|
|
||||||
for(int j = 0; j < 3; j++) {
|
for(int j = 0; j < 3; j++) {
|
||||||
if(!remap.count(face[j])) {
|
if(!remap.count(face[j])) {
|
||||||
assert(count < patch.nv);
|
|
||||||
Point3f &v = crude.vert[face[j]];
|
Point3f &v = crude.vert[face[j]];
|
||||||
patch.VertBegin()[remap.size()] = v;
|
patch.VertBegin()[remap.size()] = v;
|
||||||
entry.sphere.Add(v);
|
entry.sphere.Add(v);
|
||||||
|
@ -119,10 +118,6 @@ void nxs::NexusFill(Crude &crude,
|
||||||
}
|
}
|
||||||
patch.FaceBegin()[k*3 + j] = remap[face[j]];
|
patch.FaceBegin()[k*3 + j] = remap[face[j]];
|
||||||
}
|
}
|
||||||
//test for degenerate faces.
|
|
||||||
assert(patch.FaceBegin()[k*3] != patch.FaceBegin()[k*3+1]);
|
|
||||||
assert(patch.FaceBegin()[k*3] != patch.FaceBegin()[k*3+2]);
|
|
||||||
assert(patch.FaceBegin()[k*3+1] != patch.FaceBegin()[k*3+2]);
|
|
||||||
}
|
}
|
||||||
assert(count == remap.size());
|
assert(count == remap.size());
|
||||||
assert(entry.nvert == remap.size());
|
assert(entry.nvert == remap.size());
|
||||||
|
@ -157,6 +152,16 @@ void nxs::NexusFill(Crude &crude,
|
||||||
//we can now update bounding sphere.
|
//we can now update bounding sphere.
|
||||||
for(unsigned int i = 0; i < nexus.index.size(); i++)
|
for(unsigned int i = 0; i < nexus.index.size(); i++)
|
||||||
nexus.sphere.Add(nexus.index[i].sphere);
|
nexus.sphere.Add(nexus.index[i].sphere);
|
||||||
|
|
||||||
|
//test no duplicated faces:
|
||||||
|
/* for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
||||||
|
Patch patch = nexus.GetPatch(i);
|
||||||
|
for(unsigned int k = 0; k < patch.nf; k++) {
|
||||||
|
assert(patch.Face(k)[0] != patch.Face(k)[1]);
|
||||||
|
assert(patch.Face(k)[0] != patch.Face(k)[2]);
|
||||||
|
assert(patch.Face(k)[1] != patch.Face(k)[2]);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void nxs::NexusFixBorder(Nexus &nexus,
|
void nxs::NexusFixBorder(Nexus &nexus,
|
||||||
|
@ -194,19 +199,19 @@ void nxs::NexusFixBorder(Nexus &nexus,
|
||||||
for(unsigned int j = 0; j < remote.border_used; j++) {
|
for(unsigned int j = 0; j < remote.border_used; j++) {
|
||||||
|
|
||||||
RemapLink end_link = border_remap[j + remote_remap_start];
|
RemapLink end_link = border_remap[j + remote_remap_start];
|
||||||
assert(end_link.rel_vert < remote.nvert);
|
// assert(end_link.rel_vert < remote.nvert);
|
||||||
|
|
||||||
if(start_link.abs_vert == end_link.abs_vert &&
|
if(start_link.abs_vert == end_link.abs_vert &&
|
||||||
end_link.patch == i) { //found the match
|
end_link.patch == i) { //found the match
|
||||||
assert(!found);
|
// assert(!found);
|
||||||
nexus.borders[k + local.border_start] = Link(start_link.rel_vert,
|
nexus.borders[k + local.border_start] = Link(start_link.rel_vert,
|
||||||
end_link.rel_vert,
|
end_link.rel_vert,
|
||||||
start_link.patch);
|
start_link.patch);
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(nexus.borders[k + local.border_start].start_vert < local.nvert);
|
// assert(nexus.borders[k + local.border_start].start_vert < local.nvert);
|
||||||
assert(found);
|
// assert(found);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nexus.borders.Flush();
|
nexus.borders.Flush();
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
History
|
History
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
$Log: not supported by cvs2svn $
|
||||||
|
Revision 1.7 2004/10/04 16:49:54 ponchio
|
||||||
|
Daily backup. Preparing for compression.
|
||||||
|
|
||||||
Revision 1.6 2004/10/01 16:54:57 ponchio
|
Revision 1.6 2004/10/01 16:54:57 ponchio
|
||||||
Daily backup.
|
Daily backup.
|
||||||
|
|
||||||
|
@ -282,7 +285,6 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
nexus.Join((*fragment).second, newvert, newface, newbord);
|
nexus.Join((*fragment).second, newvert, newface, newbord);
|
||||||
|
|
||||||
|
|
||||||
//simplyfy mesh
|
//simplyfy mesh
|
||||||
vector<int> vert_remap;
|
vector<int> vert_remap;
|
||||||
float error = Decimate(decimation,
|
float error = Decimate(decimation,
|
||||||
|
@ -319,17 +321,6 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
nexus.history.push_back(update);
|
nexus.history.push_back(update);
|
||||||
ReverseHistory(nexus.history);
|
ReverseHistory(nexus.history);
|
||||||
//debug:
|
|
||||||
/* for(unsigned int i = 0; i < nexus.history.size(); i++) {
|
|
||||||
Nexus::Update &update = nexus.history[i];
|
|
||||||
cerr << "created:";
|
|
||||||
for(unsigned int c = 0; c < update.created.size(); c++)
|
|
||||||
cerr << " " << update.created[c];
|
|
||||||
cerr << "\nerased:";
|
|
||||||
for(unsigned int c = 0; c < update.erased.size(); c++)
|
|
||||||
cerr << " " << update.erased[c];
|
|
||||||
cerr << "\n\n";
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//Clean up:
|
//Clean up:
|
||||||
nexus.Close();
|
nexus.Close();
|
||||||
|
@ -338,203 +329,6 @@ int main(int argc, char *argv[]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void RemapVertices(Crude &crude,
|
|
||||||
VertRemap &vert_remap,
|
|
||||||
VFile<unsigned int> &face_remap,
|
|
||||||
vector<unsigned int> &patch_verts) {
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < crude.Faces(); i++) {
|
|
||||||
Crude::Face &face = crude.GetFace(i);
|
|
||||||
unsigned int patch = face_remap[i];
|
|
||||||
for(int k = 0; k < 3; k++) {
|
|
||||||
set<unsigned int> pp;
|
|
||||||
vert_remap.GetValues(face[k], pp);
|
|
||||||
if(!pp.count(patch)) {
|
|
||||||
vert_remap.Insert(face[k], patch);
|
|
||||||
patch_verts[patch]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*void NexusAllocate(Crude &crude,
|
|
||||||
Nexus &nexus,
|
|
||||||
VFile<unsigned int> &face_remap,
|
|
||||||
vector<unsigned int> &patch_faces,
|
|
||||||
vector<unsigned int> &patch_verts) {
|
|
||||||
|
|
||||||
|
|
||||||
nexus.index.resize(patch_faces.size());
|
|
||||||
|
|
||||||
unsigned int totchunks = 0;
|
|
||||||
//now that we know various sizes, lets allocate space
|
|
||||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
|
||||||
Nexus::Entry &entry = nexus.index[i];
|
|
||||||
|
|
||||||
if(patch_faces[i] == 0 || patch_verts[i] == 0)
|
|
||||||
cerr << "Warning! Empty patch.\n";
|
|
||||||
|
|
||||||
entry.patch_start = totchunks;
|
|
||||||
entry.patch_size = Patch::ChunkSize(nexus.signature,
|
|
||||||
patch_verts[i], patch_faces[i]);
|
|
||||||
|
|
||||||
totchunks += entry.patch_size;
|
|
||||||
entry.border_start = 0xffffffff;
|
|
||||||
entry.nvert = patch_verts[i];
|
|
||||||
entry.nface = 0;
|
|
||||||
entry.error = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
nexus.patches.Resize(totchunks);
|
|
||||||
|
|
||||||
|
|
||||||
//now we sort the faces into the patches (but still using absolute indexing
|
|
||||||
//instead of relative indexing
|
|
||||||
for(unsigned int i = 0; i < crude.face.Size(); i++) {
|
|
||||||
Crude::Face &face = crude.face[i];
|
|
||||||
unsigned int npatch = face_remap[i];
|
|
||||||
|
|
||||||
Nexus::Entry &entry = nexus.index[npatch];
|
|
||||||
|
|
||||||
//TODO this is slow because we have to initialize patch.
|
|
||||||
//just get patch.start.
|
|
||||||
Patch patch = nexus.GetPatch(npatch);
|
|
||||||
|
|
||||||
Crude::Face *faces = (Crude::Face *)patch.start;
|
|
||||||
faces[entry.nface] = face;
|
|
||||||
entry.nface++;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
/*void NexusFill(Crude &crude,
|
|
||||||
Nexus &nexus,
|
|
||||||
VertRemap &vert_remap,
|
|
||||||
VFile<RemapLink> &border_remap) {
|
|
||||||
|
|
||||||
|
|
||||||
//finally for every patch we collect the vertices
|
|
||||||
//and fill the patch.
|
|
||||||
//we need to remember start and size in border_remap;
|
|
||||||
// vector<unsigned int> border_start;
|
|
||||||
// vector<unsigned int> border_size;
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
|
||||||
Patch patch = nexus.GetPatch(i);
|
|
||||||
Nexus::Entry &entry = nexus.index[i];
|
|
||||||
|
|
||||||
//make a copy of faces (we need to write there :P)
|
|
||||||
Crude::Face *faces = new Crude::Face[patch.nf];
|
|
||||||
memcpy(faces, (Crude::Face *)patch.start,
|
|
||||||
patch.nf * sizeof(Crude::Face));
|
|
||||||
|
|
||||||
//collect all vertices we need.
|
|
||||||
//TODO an hash_map would be faster?
|
|
||||||
unsigned int count = 0;
|
|
||||||
map<unsigned int, unsigned short> remap;
|
|
||||||
for(unsigned int k = 0; k < patch.nf; k++) {
|
|
||||||
Crude::Face &face = faces[k];
|
|
||||||
|
|
||||||
for(int j = 0; j < 3; j++) {
|
|
||||||
if(!remap.count(face[j])) {
|
|
||||||
assert(count < patch.nv);
|
|
||||||
Point3f &v = crude.vert[face[j]];
|
|
||||||
patch.VertBegin()[remap.size()] = v;
|
|
||||||
entry.sphere.Add(v);
|
|
||||||
remap[face[j]] = count++;
|
|
||||||
}
|
|
||||||
patch.FaceBegin()[k*3 + j] = remap[face[j]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(count == remap.size());
|
|
||||||
assert(entry.nvert == remap.size());
|
|
||||||
|
|
||||||
//record start of border:
|
|
||||||
entry.border_start = border_remap.Size();
|
|
||||||
|
|
||||||
//TODO hash_set?
|
|
||||||
set<unsigned int> border_patches;
|
|
||||||
map<unsigned int, unsigned short>::iterator m;
|
|
||||||
for(m = remap.begin(); m != remap.end(); m++) {
|
|
||||||
RemapLink link;
|
|
||||||
link.abs_vert = (*m).first;
|
|
||||||
link.rel_vert = (*m).second;
|
|
||||||
|
|
||||||
vert_remap.GetValues(link.abs_vert, border_patches);
|
|
||||||
assert(border_patches.size() >= 1);
|
|
||||||
if(border_patches.size() == 1) continue; //its not a border
|
|
||||||
|
|
||||||
set<unsigned int>::iterator s;
|
|
||||||
for(s = border_patches.begin(); s != border_patches.end(); s++) {
|
|
||||||
if((*s) == i) continue;
|
|
||||||
link.patch = *s;
|
|
||||||
border_remap.PushBack(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//and number of borders:
|
|
||||||
entry.border_used = border_remap.Size() - entry.border_start;
|
|
||||||
delete []faces;
|
|
||||||
}
|
|
||||||
|
|
||||||
//we can now update bounding sphere.
|
|
||||||
for(unsigned int i = 0; i < nexus.index.size(); i++)
|
|
||||||
nexus.sphere.Add(nexus.index[i].sphere);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*void NexusFixBorder(Nexus &nexus,
|
|
||||||
VFile<RemapLink> &border_remap) {
|
|
||||||
|
|
||||||
//and last convert RemapLinks into Links
|
|
||||||
nexus.borders.Resize(border_remap.Size() * 2);
|
|
||||||
//* 2 is to accomodate future borders
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
|
||||||
Nexus::Entry &local = nexus.index[i];
|
|
||||||
local.border_start *= 2;
|
|
||||||
local.border_size = local.border_used * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
|
||||||
Nexus::Entry &local = nexus.index[i];
|
|
||||||
|
|
||||||
unsigned int remap_start = local.border_start/2;
|
|
||||||
//* 2 is to accomodate future borders
|
|
||||||
|
|
||||||
|
|
||||||
// K is the main iterator (where we write to in nexus.borders)
|
|
||||||
for(unsigned int k = 0; k < local.border_used; k++) {
|
|
||||||
|
|
||||||
|
|
||||||
RemapLink start_link = border_remap[k + remap_start];
|
|
||||||
assert(start_link.rel_vert < local.nvert);
|
|
||||||
|
|
||||||
Nexus::Entry &remote = nexus.index[start_link.patch];
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
unsigned int remote_remap_start = remote.border_start/2;
|
|
||||||
for(unsigned int j = 0; j < remote.border_used; j++) {
|
|
||||||
|
|
||||||
RemapLink end_link = border_remap[j + remote_remap_start];
|
|
||||||
assert(end_link.rel_vert < remote.nvert);
|
|
||||||
|
|
||||||
if(start_link.abs_vert == end_link.abs_vert &&
|
|
||||||
end_link.patch == i) { //found the match
|
|
||||||
assert(!found);
|
|
||||||
nexus.borders[k + local.border_start] = Link(start_link.rel_vert,
|
|
||||||
end_link.rel_vert,
|
|
||||||
start_link.patch);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(nexus.borders[k + local.border_start].start_vert < local.nvert);
|
|
||||||
assert(found);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nexus.borders.Flush();
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
|
void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
|
||||||
unsigned int level,
|
unsigned int level,
|
||||||
vector<Point3f> &newvert,
|
vector<Point3f> &newvert,
|
||||||
|
|
Loading…
Reference in New Issue