Lotsa changes.

This commit is contained in:
Federico Ponchio 2004-09-21 00:53:23 +00:00
parent 96f9a33c92
commit 51f13ef53c
7 changed files with 321 additions and 71 deletions

View File

@ -45,7 +45,14 @@ using namespace tri;
using namespace nxs;
using namespace std;
void Cluster(MyMesh &mesh, unsigned int target_faces);
float Clustering(unsigned int target_faces,
vector<Point3f> &newvert,
vector<unsigned int> &newface,
vector<Link> &newbord,
vector<int> &vert_remap) {
}
float Cluster(MyMesh &mesh, unsigned int target_faces);
float Decimate(unsigned int target_faces,
vector<Point3f> &newvert,
@ -128,8 +135,9 @@ float Decimate(unsigned int target_faces,
FinalSize = mesh.fn - FinalSize; //number of faces to remove
FinalSize/=2; //Number of vertices to remove
DeciSession.SetTargetOperations(FinalSize);
DeciSession.DoOptimization();
float error = 1; //get error;
// DeciSession.DoOptimization();
float error = Cluster(mesh, target_faces);
// float error = DeciSession.currMetric/4;//1; //get error;
int t3=clock();
/* printf(" vol %d \n lkv %d \n lke %d \n lkf %d \n ood %d\n bor %d\n ",
@ -176,7 +184,7 @@ float Decimate(unsigned int target_faces,
return error;
}
void Cluster(MyMesh &mesh, unsigned int target_faces) {
float Cluster(MyMesh &mesh, unsigned int target_faces) {
unsigned int starting = mesh.vn;
cerr << "starting face: " << mesh.fn << endl;
//veramente brutale
@ -200,6 +208,7 @@ void Cluster(MyMesh &mesh, unsigned int target_faces) {
}
}
float error = 0;
cerr << "done" << endl;
map<float, pair<int, int> >::iterator s;
for(s = dist.begin(); s != dist.end(); s++) {
@ -214,6 +223,7 @@ void Cluster(MyMesh &mesh, unsigned int target_faces) {
assert(!mesh.vert[source].IsD());
mesh.vert[source].SetD();
error = (*s).first;
remap[source] = target;
remap[target] = target;
toremove -= 2;
@ -238,5 +248,5 @@ void Cluster(MyMesh &mesh, unsigned int target_faces) {
}
}
cerr << "Ending faces: " << mesh.fn << endl;
return error;
}

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.4 2004/08/27 00:39:28 ponchio
Rewrote.
Revision 1.3 2004/07/20 14:06:02 ponchio
Changed filename saving.
@ -60,7 +63,8 @@ class PChain {
virtual void RemapFaces(Crude &crude, VFile<unsigned int> &face_remap,
std::vector<unsigned int> &patch_faces) = 0;
std::vector<unsigned int> &patch_faces,
float scaling, int steps) = 0;
/* virtual unsigned int Levels() = 0;

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.3 2004/08/27 00:39:28 ponchio
Rewrote.
Revision 1.2 2004/07/01 21:35:34 ponchio
int -> Key
@ -50,7 +53,7 @@ using namespace nxs;
bool Seed::Dist(const Point3f &point, float &mindist,
Point3f &res) {
float newdist = Distance(p, point);
float newdist = Distance(p, point) * weight;
if(newdist < mindist) {
mindist = newdist;
res = p;

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.5 2004/08/27 00:39:28 ponchio
Rewrote.
Revision 1.4 2004/07/20 14:17:51 ponchio
*** empty log message ***
@ -113,6 +116,7 @@ namespace nxs {
unsigned int count(unsigned int key);
Seed &operator[](unsigned int key);
void clear();
void reload() { ug_seeds = all_seeds; ug.Set(ug_seeds); }
unsigned int Locate(const vcg::Point3f &p);
float Priority(const vcg::Point3f &p, unsigned int key);
@ -184,7 +188,7 @@ namespace nxs {
return radius;
}
private:
// private:
vcg::Box3f bbox;
vcg::GridStaticPtr< std::vector<Seed> > ug;
std::vector<Seed> all_seeds;

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.3 2004/09/17 15:25:09 ponchio
First working (hopefully) release.
Revision 1.2 2004/09/16 14:25:16 ponchio
Backup. (lot of changes).
@ -41,40 +44,144 @@ using namespace std;
using namespace vcg;
using namespace nxs;
void VoronoiChain::Initialize(unsigned int psize, unsigned int pthreshold) {
patch_size = psize;
patch_threshold = pthreshold;
}
void VoronoiChain::Init(Crude &crude) {
void VoronoiChain::Init(Crude &crude, float scaling, int steps) {
box = crude.GetBox();
radius = VoronoiPartition::OptimalRadius(crude, patch_size);
float radius0 = radius;
float radius1 = radius * 1.4;
// float radius1 = VoronoiPartition::OptimalRadius(crude, patch_size*2);
box.Offset(box.max - box.min);
//how many cells do i need?
cerr << "scaling: " << scaling << endl;
unsigned int f_cells = crude.Faces() / mean_size;
unsigned int c_cells = (unsigned int)(scaling * f_cells);
cerr << "mean size: " << mean_size << endl;
cerr << "f cells: " << f_cells << endl;
cerr << "c_cells: " << c_cells << endl;
levels.push_back(VoronoiPartition());
levels.push_back(VoronoiPartition());
VoronoiPartition &part0 = levels[0];
VoronoiPartition &part1 = levels[1];
part0.Init(crude.GetBox());
part1.Init(crude.GetBox());
VoronoiPartition &fine = levels[0];
VoronoiPartition &coarse = levels[1];
VFile<Point3f>::iterator iter;
for(iter = crude.vert.Begin(); iter != crude.vert.End(); ++iter) {
Point3f &v = *iter;
unsigned int target_patch;
fine.Init(box);
coarse.Init(box);
float dist = part0.Closest(v, target_patch);
if(dist >= radius0 || dist == -1)
part0.Add(v, radius0);
srand(0);
vector<Seed> fine_seeds;
vector<Seed> coarse_seeds;
dist = part1.Closest(v, target_patch);
if(dist >= radius1 || dist == -1)
part1.Add(v, radius1);
float fine_vmean = mean_size/2;
float coarse_vmean = (mean_size/scaling)/2;
for(unsigned int i = 0; i < crude.Vertices(); i++) {
int f = (int)(fine_vmean*rand()/(RAND_MAX + 1.0));
int c = (int)(coarse_vmean *rand()/(RAND_MAX + 1.0));
if(f == 1) {
Point3f &point = crude.GetVertex(i);
fine_seeds.push_back(Seed(point, 1));
}
if(c == 1) {
Point3f &point = crude.GetVertex(i);
coarse_seeds.push_back(Seed(point, 1));
}
}
cerr << "fine_seeds.size: " << fine_seeds.size() << endl;
cerr << "coarse_seeds.size: " << coarse_seeds.size() << endl;
fine.all_seeds = fine_seeds;
coarse.all_seeds = coarse_seeds;
fine.reload();
coarse.reload();
//here goes some optimization pass.
//Fine optimization.
vector<Point3f> fcentroids;
vector<unsigned int> fcount;
for(unsigned int i = 0; i < steps; i++) {
cerr << "Optimization step 0: " << i << "/" << steps << endl;
fcentroids.clear();
fcount.clear();
fcentroids.resize(fine.size(), Point3f(0, 0, 0));
fcount.resize(fine.size(), 0);
for(unsigned int v = 0; v < crude.Vertices(); v++) {
unsigned int ftarget;
float dist = fine.Closest(crude.vert[v], ftarget);
assert(ftarget != -1);
fcentroids[ftarget] += crude.vert[v];
fcount[ftarget]++;
}
for(unsigned int v = 0; v < fine.size(); v++) {
assert(fcount[v] != 0);
fine[v].p = fcentroids[v]/fcount[v];
//0.3 is related to the fact is doubled the box size.
fine[v].weight = pow(fcount[v]/fine_vmean, 0.3f);
// fine.bbox.Add(fine[v].p);
}
// fine.Init(fine.bbox);
fine.reload();
}
//Coarse optimization
vector< map<unsigned int, Point3f> > ccentroids;
vector< map<unsigned int, unsigned int> > ccount;
for(unsigned int i = 0; i < steps; i++) {
cerr << "Optimization step 1: " << i << "/" << steps << endl;
ccentroids.clear();
ccount.clear();
ccentroids.resize(coarse.size());
ccount.resize(coarse.size());
for(unsigned int v = 0; v < crude.Vertices(); v++) {
unsigned int ftarget;
float dist = fine.Closest(crude.vert[v], ftarget);
assert(ftarget != -1);
unsigned int ctarget;
dist = coarse.Closest(crude.vert[v], ctarget);
assert(ctarget != -1);
map<unsigned int, Point3f> &centroids = ccentroids[ctarget];
map<unsigned int, unsigned int> &count = ccount[ctarget];
if(!centroids.count(ftarget))
centroids[ftarget]= Point3f(0, 0, 0);
if(!count.count(ftarget))
count[ftarget] = 0;
centroids[ftarget] += crude.vert[v];
count[ftarget]++;
}
for(unsigned int v = 0; v < coarse.size(); v++) {
map<unsigned int, Point3f> &centroids = ccentroids[v];
map<unsigned int, unsigned int> &count = ccount[v];
coarse[v].p = Point3f(0, 0, 0);
float weight = 0;
unsigned int tot_size =0;
map<unsigned int, Point3f>::iterator k;
for(k = centroids.begin();k != centroids.end(); k++) {
unsigned int size = count[(*k).first];
tot_size += size;
//coarse[v].p += (*k).second / (size * size);
//weight += 1/(float)size;
coarse[v].p += (*k).second / size;
weight += 1;
// coarse[v].p += (*k).second;
// weight += size;
}
assert(weight > 0);
coarse[v].p /= weight;
//TODO find a solution
// coarse[v].weight = pow(tot_size/coarse_vmean, 0.25f);
}
coarse.reload();
}
}
unsigned int VoronoiChain::Locate(unsigned int level,
@ -86,11 +193,11 @@ unsigned int VoronoiChain::Locate(unsigned int level,
return fine + coarse * levels[level].size();*/
}
void VoronoiChain::RemapFaces(Crude &crude,
VFile<unsigned int> &face_remap,
vector<unsigned int> &patch_faces) {
void VoronoiChain::RemapFaces(Crude &crude, VFile<unsigned int> &face_remap,
vector<unsigned int> &patch_faces,
float scaling, int steps) {
Init(crude);
Init(crude, scaling, steps);
//TODO: improve quality of patches and implement threshold.
typedef map<pair<unsigned int, unsigned int>, unsigned int> FragIndex;
@ -115,7 +222,10 @@ void VoronoiChain::RemapFaces(Crude &crude,
} else
patch = patches[make_pair(coarse, fine)];
//BEWARE unkomment this!
face_remap[i] = patch;
//face_remap[i] = fine;
// face_remap[i] = coarse;
if(patch_faces.size() <= patch)
patch_faces.resize(patch+1, 0);
patch_faces[patch]++;
@ -164,28 +274,109 @@ void VoronoiChain::RemapFaces(Crude &crude,
patch_faces.resize(tot_patches);
}
void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset) {
unsigned int target_faces = (int)(patch_size *
pow(scaling, (float)levels.size()));
float rad = radius * pow(sqrt(1/scaling), (float)levels.size());
void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset,
float scaling, int steps) {
// unsigned int target_faces = (int)(mean_size *
// pow(0.5f, (float)levels.size()));
unsigned int totface = 0;
for(unsigned int idx = offset; idx < nexus.index.size(); idx++)
totface += nexus.index[idx].nface;
levels.push_back(VoronoiPartition());
VoronoiPartition &part = levels[levels.size()-1];
part.Init(box);
VoronoiPartition &coarse = levels[levels.size()-1];
VoronoiPartition &fine = levels[levels.size()-2];
coarse.Init(box);
fine.reload();
srand(0);
float coarse_vmean = (totface/2)/(fine.size() * scaling);
cerr << "initing random seeds\n";
vector<Seed> coarse_seeds;
for(unsigned int idx = offset; idx < nexus.index.size(); idx++) {
Patch patch = nexus.GetPatch(idx);
for(unsigned int i = 0; i < patch.nv; i++) {
Point3f &v = patch.Vert(i);
unsigned int target_patch;
float dist = part.Closest(v, target_patch);
if(dist >= rad || dist == -1)
part.Add(v, rad);
int c = (int)(coarse_vmean*rand()/(RAND_MAX + 1.0));
if(c == 1) {
Point3f &v = patch.Vert(i);
coarse_seeds.push_back(v);
}
}
}
cerr << "radius: " << rad << " ... cells: " << part.size() << endl;
if(coarse_seeds.size() == 0)
coarse_seeds.push_back(Point3f(0, 0, 0));
coarse.all_seeds = coarse_seeds;
coarse.reload();
//Coarse optimization
vector< map<unsigned int, Point3f> > ccentroids;
vector< map<unsigned int, unsigned int> > ccount;
for(unsigned int step = 0; step < steps; step++) {
cerr << "Optimization step " << levels.size()-1 << ":"
<< step << "/" << steps << endl;
ccentroids.clear();
ccount.clear();
ccentroids.resize(coarse.size());
ccount.resize(coarse.size());
for(unsigned int idx = offset; idx < nexus.index.size(); idx++) {
Patch patch = nexus.GetPatch(idx);
for(unsigned int i = 0; i < patch.nv; i++) {
Point3f &v = patch.Vert(i);
unsigned int ftarget;
float dist = fine.Closest(Point3f(1,1,1), ftarget);
dist = fine.Closest(v, ftarget);
assert(ftarget != -1);
unsigned int ctarget;
dist = coarse.Closest(v, ctarget);
assert(ctarget != -1);
map<unsigned int, Point3f> &centroids = ccentroids[ctarget];
map<unsigned int, unsigned int> &count = ccount[ctarget];
if(!centroids.count(ftarget))
centroids[ftarget]= Point3f(0, 0, 0);
if(!count.count(ftarget))
count[ftarget] = 0;
centroids[ftarget] += v;
count[ftarget]++;
}
}
cerr << "recentring" << endl;
for(unsigned int v = 0; v < coarse.size(); v++) {
map<unsigned int, Point3f> &centroids = ccentroids[v];
map<unsigned int, unsigned int> &count = ccount[v];
coarse[v].p = Point3f(0, 0, 0);
float weight = 0;
unsigned int tot_size =0;
map<unsigned int, Point3f>::iterator k;
for(k = centroids.begin();k != centroids.end(); k++) {
unsigned int size = count[(*k).first];
tot_size += size;
coarse[v].p += (*k).second / size;
weight += 1;
}
assert(weight > 0);
coarse[v].p /= weight;
//TODO find a solution!
// coarse[v].weight = pow(tot_size/coarse_vmean, 0.25f);
}
coarse.reload();
}
newfragments.clear();
//TODO add some optimization
}

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.2 2004/09/16 14:25:16 ponchio
Backup. (lot of changes).
Revision 1.1 2004/08/26 18:03:48 ponchio
First draft.
@ -48,16 +51,23 @@ namespace nxs {
class VoronoiChain: public PChain {
public:
VoronoiChain():scaling(0.5), patch_size(1000), patch_threshold(300) {}
virtual ~VoronoiChain() {}
void Initialize(unsigned int psize, unsigned int pthreshold);
void Init(Crude &crude);
unsigned int mean_size; //mean number of faces per patch
unsigned int min_size; //minimum number of faces per patch (soft)
unsigned int max_size; //max number of faces per patch (hard);
VoronoiChain(unsigned int mean_s = 1000,
unsigned int min_s = 300,
unsigned int max_s = 32000):
mean_size(mean_s), min_size(min_s), max_size(max_s) {}
virtual ~VoronoiChain() {}
void Init(Crude &crude, float scaling, int steps);
virtual unsigned int Locate(unsigned int level, const vcg::Point3f &p);
void RemapFaces(Crude &crude, VFile<unsigned int> &face_remap,
std::vector<unsigned int> &patch_faces);
std::vector<unsigned int> &patch_faces, float scaling,
int steps);
void BuildLevel(Nexus &nexus, unsigned int offset);
void BuildLevel(Nexus &nexus, unsigned int offset, float scaling, int steps);
std::vector<VoronoiPartition> levels;
@ -65,9 +75,6 @@ class VoronoiChain: public PChain {
std::map<unsigned int, std::set<unsigned int> > newfragments;
std::map<unsigned int, std::set<unsigned int> > oldfragments;
// private:
float scaling;
unsigned int patch_size;
unsigned int patch_threshold;
float radius;
vcg::Box3f box;

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.3 2004/09/17 15:25:09 ponchio
First working (hopefully) release.
Revision 1.2 2004/09/16 14:25:16 ponchio
Backup. (lot of changes).
@ -97,15 +100,20 @@ float Decimate(unsigned int target_faces,
void ReverseHistory(vector<Nexus::Update> &history);
enum Decimation { QUADRIC, CLUSTER };
int main(int argc, char *argv[]) {
Decimation decimation = QUADRIC;
unsigned int patch_size = 1000;
unsigned int patch_threshold = 200;
unsigned int optimization_steps = 5;
bool stop_after_remap = false;
unsigned int max_level = 0xffffffff;
float scaling = 0.5;
int option;
while((option = getopt(argc, argv, "f:t:l:s:")) != EOF) {
while((option = getopt(argc, argv, "f:t:l:s:d:ro:")) != EOF) {
switch(option) {
case 'f': patch_size = atoi(optarg);
if(patch_size == 0 || patch_size > 32000) {
@ -131,12 +139,24 @@ int main(int argc, char *argv[]) {
cerr << "Must be 0 < scaling < 1" << endl;
}
break;
case 'd':
if(!strcmp("quadric", optarg))
decimation = QUADRIC;
else if(!strcmp("cluster", optarg))
decimation = CLUSTER;
else {
cerr << "Unknown decimation method: " << optarg << endl;
return -1;
}
break;
case 'r': stop_after_remap = true; break;
case 'o': optimization_steps = atoi(optarg); break;
default: cerr << "Unknown option: " << (char)option << endl;
return -1;
}
}
//Test there are still 2 arguments
//Test that there are still 2 arguments
if(optind != argc - 2) {
cerr << "Usage: " << argv[0] << " <crude> <output> [options]\n";
cerr << " Options:\n";
@ -144,6 +164,7 @@ int main(int argc, char *argv[]) {
cerr << " -t N: mini faces per patch (default 200)\n";
cerr << " -l N: number of levels\n";
cerr << " -s F: scaling factor (0 < F < 1, default 0.5)\n\n";
cerr << " -d <method>: decimation method: quadric, cluster. (default quadric)\n";
return -1;
}
@ -154,23 +175,21 @@ int main(int argc, char *argv[]) {
}
if(patch_size > crude.vert.Size()/2) {
cerr << "Patch size too big: " << patch_size << " ~ " << crude.vert.Size()
cerr << "Patch size too big: " << patch_size << " * 2 > " << crude.vert.Size()
<< endl;
return -1;
}
string output = argv[optind+1];
Signature signature = HAS_FACES;
Nexus nexus;
if(!nexus.Create(output, signature)) {
if(!nexus.Create(output, HAS_FACES)) {
cerr << "Could not create nexus output: " << output << endl;
return -1;
}
VoronoiChain vchain;
vchain.Initialize(patch_size, patch_threshold);
vchain.scaling = scaling;
VoronoiChain vchain(patch_size, patch_threshold);
// vchain.scaling = scaling;
//Now building level 0 of the Nexus
@ -200,12 +219,13 @@ int main(int argc, char *argv[]) {
//Remapping faces and vertices using level 0 and 1 of the chain
vector<unsigned int> patch_faces;
vchain.RemapFaces(crude, face_remap, patch_faces);
vchain.RemapFaces(crude, face_remap, patch_faces, scaling, optimization_steps);
vector<unsigned int> patch_verts;
patch_verts.resize(patch_faces.size(), 0);
RemapVertices(crude, vert_remap, face_remap, patch_verts);
if(stop_after_remap) return 0;
//allocate chunks for patches and copy faces (absoklute indexing) into them.
NexusAllocate(crude, nexus, face_remap, patch_faces, patch_verts);
@ -231,8 +251,9 @@ int main(int argc, char *argv[]) {
cerr << "Level: " << level << endl;
unsigned int newoffset = nexus.index.size();
vchain.BuildLevel(nexus, oldoffset);
vchain.BuildLevel(nexus, oldoffset, scaling, optimization_steps);
cerr << "Level built\n";
vector<Nexus::Update> level_history;
map<unsigned int, set<unsigned int> >::iterator fragment;
for(fragment = vchain.oldfragments.begin();
@ -662,13 +683,24 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
Nexus::Entry &rentry = nexus.index[link.end_patch];
//TODO if !true reallocate borders.
Border rborder = nexus.GetBorder(link.end_patch);
if(rentry.border_used >= rentry.border_size) {
cerr << "patch: " << link.end_patch << endl;
cerr << "used: " << rentry.border_used << endl;
cerr << "size: " << rentry.border_size << endl;
unsigned int start = nexus.borders.Size();
nexus.borders.Resize(nexus.borders.Size() + 2 * rentry.border_size);
Link *tmp = new Link[rentry.border_size];
memcpy(tmp, &rborder[0], sizeof(Link) * rentry.border_size);
rentry.border_start = start;
rentry.border_size *= 2;
rborder = nexus.GetBorder(link.end_patch);
memcpy(&rborder[0], tmp, sizeof(Link) * rentry.border_used);
delete []tmp;
}
assert(rentry.border_used < rentry.border_size);
Border rborder = nexus.GetBorder(link.end_patch);
Link &newlink = rborder[rentry.border_used++];
newlink.start_vert = link.end_vert;
@ -695,8 +727,7 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
Nexus::Entry &entry = nexus.index[patch_idx];
// entry.error = error;
entry.error = level;
entry.error = error;
Patch patch = nexus.GetPatch(patch_idx);
memcpy(patch.FaceBegin(), &faces[0],