From b6d9d125da819f8a3856aea61ad8de9b4ac7781b Mon Sep 17 00:00:00 2001 From: ponchio Date: Sat, 30 Oct 2004 20:17:03 +0000 Subject: [PATCH] Fixed big patches problem. --- apps/nexus/decimate.cpp | 18 +- apps/nexus/fragment.cpp | 10 +- apps/nexus/fragment.h | 2 +- apps/nexus/nexusmt.cpp | 11 +- apps/nexus/nexusmt.h | 2 +- apps/nexus/nexusview.cpp | 25 ++- apps/nexus/nxsedit.cpp | 60 ++++-- apps/nexus/pvoronoi.cpp | 60 +++++- apps/nexus/pvoronoi.h | 30 ++- apps/nexus/voronoichain.cpp | 367 +++++++++++++++--------------------- apps/nexus/voronoichain.h | 7 + apps/nexus/voronoinxs.cpp | 245 +----------------------- 12 files changed, 339 insertions(+), 498 deletions(-) diff --git a/apps/nexus/decimate.cpp b/apps/nexus/decimate.cpp index 40e5d640..5293753d 100644 --- a/apps/nexus/decimate.cpp +++ b/apps/nexus/decimate.cpp @@ -169,19 +169,17 @@ float Quadric(MyMesh &mesh, unsigned int target_faces) { float Cluster(MyMesh &mesh, unsigned int target_faces) { unsigned int starting = mesh.vn; - + unsigned int nseeds = target_faces/2; assert(nseeds < mesh.vert.size()); - + vector remap; - + VoronoiPartition part; - Box3f box; for(unsigned int i = 0; i < mesh.vert.size(); i++) { const Point3f &p = mesh.vert[i].cP(); - box.Add(p); if(!mesh.vert[i].IsW()) { - part.push_back(Seed(p, 1)); + part.push_back(p); remap.push_back(i); nseeds--; } @@ -192,13 +190,12 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) { unsigned int i = rand() % mesh.vert.size(); if(mesh.vert[i].IsW() && !mesh.vert[i].IsV()) { const Point3f &p = mesh.vert[i].cP(); - part.push_back(Seed(p, 1)); + part.push_back(p); mesh.vert[i].SetV(); remap.push_back(i); nseeds--; } } - part.SetBox(box); part.Init(); vector centroid; @@ -215,13 +212,13 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) { } for(unsigned int i = nborder; i < part.size(); i++) { if(count[i] > 0) - part[i].p = centroid[i]/count[i]; + part[i] = centroid[i]/count[i]; } } for(unsigned int i = nborder; i < part.size(); i++) { assert(mesh.vert[remap[i]].IsV()); - mesh.vert[remap[i]].P() = part[i].p; + mesh.vert[remap[i]].P() = part[i]; } float error = 0; @@ -261,5 +258,6 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) { mesh.vn--; } return error; + } diff --git a/apps/nexus/fragment.cpp b/apps/nexus/fragment.cpp index ad849c11..60245ea9 100644 --- a/apps/nexus/fragment.cpp +++ b/apps/nexus/fragment.cpp @@ -47,7 +47,7 @@ void Fragment::Write(outstm *out) { unsigned int ssize = seeds.size(); out->write(&ssize, sizeof(unsigned int)); - out->write(&*seeds.begin(), ssize * sizeof(Seed)); + out->write(&*seeds.begin(), ssize * sizeof(Point3f)); out->write(&*seeds_id.begin(), ssize * sizeof(unsigned int)); unsigned int psize = pieces.size(); @@ -66,7 +66,7 @@ void Fragment::Read(instm *in) { in->read(&ssize, sizeof(unsigned int)); seeds.resize(ssize); seeds_id.resize(ssize); - in->read(&*seeds.begin(), ssize * sizeof(Seed)); + in->read(&*seeds.begin(), ssize * sizeof(Point3f)); in->read(&*seeds_id.begin(), ssize * sizeof(unsigned int)); unsigned int psize; @@ -206,7 +206,7 @@ void nxs::Split(Fragment &out, VoronoiPartition &part) { unsigned int nseeds = out.seeds.size(); - vector &seeds = out.seeds; + vector &seeds = out.seeds; vector &seeds_id = out.seeds_id; //preliminary count vector count; @@ -222,7 +222,7 @@ void nxs::Split(Fragment &out, //pruning small patches float min_size = (newface.size()/3) / 20.0f; - vector newseeds; + vector newseeds; vector newseeds_id; for(unsigned int seed = 0; seed < nseeds; seed++) { @@ -346,7 +346,7 @@ unsigned int Fragment::Locate(const Point3f &p) { float max_dist = 1e20; unsigned int id = 0xffffffff; for(unsigned int i = 0; i < seeds.size(); i++) { - float dist = seeds[i].Dist(p); + float dist = Distance(seeds[i], p); if(dist < max_dist) { max_dist = dist; id = i; diff --git a/apps/nexus/fragment.h b/apps/nexus/fragment.h index d6df6891..67abac83 100644 --- a/apps/nexus/fragment.h +++ b/apps/nexus/fragment.h @@ -47,7 +47,7 @@ class Fragment { float error; - std::vector seeds; + std::vector seeds; std::vector seeds_id; std::vector pieces; diff --git a/apps/nexus/nexusmt.cpp b/apps/nexus/nexusmt.cpp index 7bb607d9..6ed3760a 100644 --- a/apps/nexus/nexusmt.cpp +++ b/apps/nexus/nexusmt.cpp @@ -146,8 +146,6 @@ bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) { void NexusMt::Render() { patches.Flush(); - Frustumf frustum; - frustum.GetView(); vector cells; metric->GetView(); @@ -155,9 +153,14 @@ void NexusMt::Render() { tri_total = 0; tri_rendered = 0; - Extract(cells); - + Draw(cells); +} + +void NexusMt::Draw(vector &cells) { + Frustumf frustum; + frustum.GetView(); + glEnableClientState(GL_VERTEX_ARRAY); if(use_colors) glEnableClientState(GL_COLOR_ARRAY); diff --git a/apps/nexus/nexusmt.h b/apps/nexus/nexusmt.h index 86b2a715..9e782a52 100644 --- a/apps/nexus/nexusmt.h +++ b/apps/nexus/nexusmt.h @@ -135,7 +135,7 @@ class NexusMt: public Nexus { bool SetComponents(unsigned int mask); - //void ExtractFixed(std::vector &selected, float error); + void Draw(std::vector &selected); void Extract(std::vector &selected); protected: diff --git a/apps/nexus/nexusview.cpp b/apps/nexus/nexusview.cpp index 7f21a612..2dcdc8b0 100644 --- a/apps/nexus/nexusview.cpp +++ b/apps/nexus/nexusview.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.18 2004/10/21 13:40:16 ponchio +Debugging. + Revision 1.17 2004/10/21 12:22:21 ponchio Small changes. @@ -212,6 +215,7 @@ int main(int argc, char *argv[]) { bool show_colors = true; bool show_normals = true; bool show_statistics = true; + bool extract = true; NexusMt::MetricKind metric; NexusMt::Mode mode = NexusMt::SMOOTH; @@ -251,10 +255,11 @@ int main(int argc, char *argv[]) { track.ButtonDown(Trackball::KEY_CTRL); break; case SDLK_q: exit(0); break; case SDLK_b: show_borders = !show_borders; break; + case SDLK_e: extract = !extract; break; case SDLK_c: show_colors = !show_colors; break; case SDLK_n: show_normals = !show_normals; break; - case SDLK_9: nexus.patches.ram_size *= 0.8; break; - case SDLK_0: nexus.patches.ram_size *= 1.2; break; + case SDLK_9: nexus.patches.ram_size *= 0.8f; break; + case SDLK_0: nexus.patches.ram_size *= 1.2f; break; case SDLK_LEFT: ram_size *= 0.7; @@ -366,10 +371,20 @@ int main(int argc, char *argv[]) { //nexus.SetPolicy(policy, error); nexus.SetComponent(NexusMt::COLOR, show_colors); nexus.SetComponent(NexusMt::NORMAL, show_normals); - - watch.Start(); - nexus.Render(); + static vector cells; + watch.Start(); + if(extract) { + nexus.patches.Flush(); + + nexus.metric->GetView(); + nexus.policy.Init(); + nexus.tri_total = 0; + nexus.tri_rendered = 0; + nexus.Extract(cells); + nexus.Draw(cells); + } else + nexus.Draw(cells); //cerr Do some reporting: if(show_statistics) { diff --git a/apps/nexus/nxsedit.cpp b/apps/nexus/nxsedit.cpp index 2b105717..ff8251f2 100644 --- a/apps/nexus/nxsedit.cpp +++ b/apps/nexus/nxsedit.cpp @@ -1,13 +1,3 @@ -#include -using namespace std; - -#include "nxsalgo.h" -#include "nexus.h" -#include "watch.h" - -using namespace nxs; -using namespace vcg; - #ifdef WIN32 #include #else @@ -17,6 +7,33 @@ using namespace vcg; #include +#include + + +#include +#include +#include +//WARNING WARNING this must be included AFTER mesh includes.... +#include +#include + +#include "nxsalgo.h" +#include "nexus.h" +#include "watch.h" + +using namespace nxs; +using namespace vcg; +using namespace std; +using namespace tri; + +class CFace; + +class CVertex: public VertexVCf {}; + +class CFace: public Face{}; + +class CMesh: public tri::TriMesh, vector > {}; + string getSuffix(unsigned int signature) { string suff; if(signature&NXS_COMPRESSED) suff += "Z"; @@ -261,7 +278,25 @@ int main(int argc, char *argv[]) { nexus.Close(); return 0; } - + CMesh mesh; + GridStaticPtr grid; + if(add_colors) { + if(!plysource.size()) { + cerr << "No plysource specified when adding color (-p option)\n"; + return -1; + } + if(!tri::io::ImporterPLY::Open(mesh, plysource.c_str())) { + cerr << "Could not load ply: " << plysource << endl; + return -1; + } + //calcoliamo il box: + Box3f box; + for(unsigned int i = 0; i < mesh.vert.size(); i++) + box.Add(mesh.vert[i].P()); + grid.SetBBox(box); + grid.Set(mesh.face); + } + if((add & NXS_NORMALS_SHORT) && compress) { cerr << "Its not possible to add normals and compress in the same step\n"; return -1; @@ -377,6 +412,7 @@ int main(int argc, char *argv[]) { cerr << "Unsupported color\n"; return -1; } + if(qvertex && add_normals) { report.Init(nexus.index.size()); cout << "Quantizing vertices\n"; @@ -391,9 +427,7 @@ int main(int argc, char *argv[]) { report.Finish(); } - //fixing sphere. out.sphere = nexus.sphere; - //copying history: out.history = nexus.history; out.Close(); diff --git a/apps/nexus/pvoronoi.cpp b/apps/nexus/pvoronoi.cpp index f8e179c9..dc061fc4 100644 --- a/apps/nexus/pvoronoi.cpp +++ b/apps/nexus/pvoronoi.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.6 2004/10/15 11:41:03 ponchio +Tests and small changes. + Revision 1.5 2004/09/28 10:26:21 ponchio Rewrote. @@ -48,16 +51,68 @@ Created ****************************************************************************/ -#pragma warning(disable:4786 4804 4244 4018 4267 4311) #include #include #include "pvoronoi.h" +#include using namespace std; using namespace vcg; using namespace nxs; -bool Seed::Dist(const Point3f &point, float &mindist, +void VoronoiPartition::Init() { + if(bd) delete bd; + buffer.resize(size() * 3); + for(unsigned int i = 0; i < size(); i++) { + for(int k = 0; k < 3; k++) + buffer[i*3+k] = operator[](i)[k]; + } + points.resize(size()); + for(unsigned int i = 0; i < size(); i++) { + points[i] = &buffer[i*3]; + } + bd = new ANNkd_tree(&*points.begin(), size(), 3); + +} +void VoronoiPartition::Closest(const vcg::Point3f &p, unsigned int nsize, + vector &near, + vector &dist) { + double point[3]; + point[0] = p[0]; + point[1] = p[1]; + point[2] = p[2]; + + near.resize(nsize); + dist.resize(nsize); + vector dists; + dists.resize(nsize); + bd->annkSearch(&point[0], nsize, &*near.begin(), &*dists.begin()); + for(unsigned int i = 0; i < nsize; i++) + dist[i] = (float)dists[i]; +} + +void VoronoiPartition::Closest(const vcg::Point3f &p, + int &target, float &dist) { + double point[3]; + point[0] = p[0]; + point[1] = p[1]; + point[2] = p[2]; + double dists; + bd->annkSearch(&point[0], 1, &target, &dists, 1); + assert(target >= 0); + assert(target < size()); + + dist = (float)dists; +} + +int VoronoiPartition::Locate(const vcg::Point3f &p) { + int target = -2; + float dist; + Closest(p, target, dist); + return target; +} + +/*bool Seed::Dist(const Point3f &point, float &mindist, Point3f &res) { float newdist = Distance(p, point) * weight; if(newdist < mindist) { @@ -115,3 +170,4 @@ Point3f VoronoiPartition::FindBorder(vcg::Point3f &p, float radius) { } return m; } +*/ diff --git a/apps/nexus/pvoronoi.h b/apps/nexus/pvoronoi.h index bb56bfa1..ccd85dce 100644 --- a/apps/nexus/pvoronoi.h +++ b/apps/nexus/pvoronoi.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.8 2004/10/15 11:41:03 ponchio +Tests and small changes. + Revision 1.7 2004/09/28 10:26:21 ponchio Rewrote. @@ -63,16 +66,33 @@ Created #include #include -#include -#include -#include "crude.h" //TODO provide a Sort function, to sort spatially the seeds. +class ANNkd_tree; + namespace nxs { - class Seed { + + + class VoronoiPartition: public std::vector { + public: + VoronoiPartition(): bd(NULL) {} + void Init(); + void Closest(const vcg::Point3f &p, unsigned int nsize, + std::vector &near, + std::vector &dist); + void Closest(const vcg::Point3f &p, + int &target, float &dist); + + int Locate(const vcg::Point3f &p); + + ANNkd_tree *bd; + std::vector buffer; + std::vector points; + }; + /* class Seed { public: vcg::Point3f p; float weight; @@ -112,7 +132,7 @@ namespace nxs { return target; } vcg::Box3f box; - }; + };*/ } #endif diff --git a/apps/nexus/voronoichain.cpp b/apps/nexus/voronoichain.cpp index cb4df46e..6393eec5 100644 --- a/apps/nexus/voronoichain.cpp +++ b/apps/nexus/voronoichain.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.17 2004/10/29 16:33:29 ponchio +Trying to fix big patches. + Revision 1.16 2004/10/22 14:31:56 ponchio Some controls added. @@ -85,35 +88,140 @@ using namespace vcg; using namespace nxs; +void print(Point3f p) { + cerr << p[0] << " " << p[1] << " " << p[2] << endl; +} + +float getClosest(const Point3f &seed, VoronoiPartition &part) { + vector near; + vector dist; + part.Closest(seed, 2, near, dist); + for(int k = 0; k < 2; k++) { + int c = near[k]; + assert(c >= 0); + assert(c < part.size()); + if(part[c] == seed) continue; + return Distance(seed, part[c]); + } + return -1; +} + +int getBest(const Point3f &seed, VoronoiPartition &part, + vector &mark, + vector &counts) { + + vector near; + vector dist; + int nnear = 7; + if(part.size() < 7) nnear = part.size()/2; + if(!nnear) return -1; + + part.Closest(seed, nnear, near, dist); + int best = -1; + int bestcount = -1; + int bestdist = -1; + for(int k = 0; k < nnear; k++) { + int c = near[k]; + assert(c >= 0); + assert(c < part.size()); if(mark[c]) continue; + if(part[c] == seed) continue; + if(bestcount < 0 || + (counts[c] < bestcount)) { + best = c; + bestcount = counts[c]; + } + /*if(bestdist < 0 || + Distance(seed, part[c]) < bestdist) { + best = c; + bestdist = Distance(seed, part[c]); + }*/ + } + return best; +} + +//return false if still not ok +bool VoronoiChain::Optimize(int mean, VoronoiPartition &part, + vector ¢roids, + vector &counts, + bool join) { + + //remove small or really big patches. + unsigned int failed = 0; + vector seeds; + vector mark; + mark.resize(part.size(), false); + + //first pass we check only big ones + for(unsigned int i = 0; i < part.size(); i++) { + if(counts[i] > max_size || counts[i] > 2 * mean) { + failed++; + cerr << "Failed> " << counts[i] << endl; + float radius= getClosest(part[i], part); + radius /= 3; + if(radius < 0) continue; + seeds.push_back(part[i] + Point3f(1, 0, 0) * radius); + seeds.push_back(part[i] + Point3f(0, 1, 0) * radius); + seeds.push_back(part[i] + Point3f(0, 0, 1) * radius); + + seeds.push_back(part[i] - Point3f(1, 0, 0) * radius); + seeds.push_back(part[i] - Point3f(0, 1, 0) * radius); + seeds.push_back(part[i] - Point3f(0, 0, 1) * radius); + mark[i]; + } + } + + for(unsigned int i = 0; i < part.size(); i++) { + if(mark[i]) continue; + if(join && counts[i] < min_size) { + failed++; + int best = getBest(part[i], part, mark, counts); + if(best < 0) continue; + assert(mark[best] == false); + mark[best] = true; + mark[i] = true; + seeds.push_back((part[i] + part[best])/2); + } + } + + for(unsigned int i = 0; i < part.size(); i++) { + if(mark[i]) continue; + if(join) part[i] = centroids[i]/(float)counts[i]; + seeds.push_back(part[i]); + } + + part.clear(); + for(unsigned int i = 0; i < seeds.size(); i++) + part.push_back(seeds[i]); + + if(part.size() == 0) part.push_back(Point3f(0,0,0)); + part.Init(); + return failed == 0; +} + void VoronoiChain::Init(Crude &crude, float scaling, int steps) { 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 &fine = levels[0]; VoronoiPartition &coarse = levels[1]; - fine.SetBox(crude.GetBox()); - coarse.SetBox(crude.GetBox()); srand(0); float fine_vmean = mean_size/2.0f; - float coarse_vmean = (mean_size/scaling)/2; + float coarse_vmean = (mean_size/scaling)/2.0f; + 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) { + int f = (int)(fine_vmean * rand()/(RAND_MAX + 1.0)); + int c = (int)(coarse_vmean * rand()/(RAND_MAX + 1.0)); + if(f == 2) { Point3f &point = crude.GetVertex(i); - fine.push_back(Seed(point, 1)); + fine.push_back(point); } - if(c == 1) { + if(c == 2) { Point3f &point = crude.GetVertex(i); - coarse.push_back(Seed(point, 1)); + coarse.push_back(point); } } //TODO! Check for duplicates (use the closest :P) @@ -122,8 +230,8 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { fine.Init(); coarse.Init(); -//here goes some optimization pass. - //Fine optimization. + //here goes some optimization pass. + //Fine optimization. Report report; vector centroids; vector counts; @@ -136,51 +244,20 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { report.Init(crude.Vertices()); for(unsigned int v = 0; v < crude.Vertices(); v++) { - if(v & 0xffff) report.Step(v); - unsigned int ftarget; - float dist = fine.Closest(crude.vert[v], ftarget); - assert(ftarget != -1); - centroids[ftarget] += crude.vert[v]; - counts[ftarget]++; + report.Step(v); + unsigned int target = fine.Locate(crude.vert[v]); + centroids[target] += crude.vert[v]; + counts[target]++; } - - //remove small or really big patches. - unsigned int failed = 0; - vector seeds; - for(unsigned int i = 0; i < fine.size(); i++) { - if(counts[i] == 0 || (counts[i] < min_size && step != steps -3)) { - failed++; - } else if(counts[i] > max_size) { - cerr << "Failed: " << i << " tot: " << counts[i] << endl; - failed++; - Seed s = fine[i]; - s.p = centroids[i]/(float)counts[i] + Point3f(1, 0, 0); - fine[i].weight = (float)pow((counts[i]/2)/(float)fine_vmean, 0.2f); - s.weight = fine[i].weight; - seeds.push_back(fine[i]); - seeds.push_back(s); - } else { - if(step != steps-1) { - fine[i].p = centroids[i]/(float)counts[i]; - fine[i].weight = (float)pow(counts[i]/(float)fine_vmean, 0.2f); - } - seeds.push_back(fine[i]); - } - } - fine.clear(); - for(unsigned int i = 0; i < seeds.size(); i++) - fine.push_back(seeds[i]); - - if(fine.size() == 0) fine.push_back(Point3f(0,0,0)); - fine.Init(); - if(step == steps-1 && failed) step--; - } - - - - //here goes some optimization pass. - //Coarse optimization. - //vector radius; + if(step == steps-1) { + if(!Optimize(fine_vmean, fine, centroids, counts, false)) + step--; + } else + Optimize(fine_vmean, fine, centroids, counts, true); + } +//here goes some optimization pass. +//Coarse optimization. +//vector radius; for(int step = 0; step < steps; step++) { cerr << "Optimization step: " << step+1 << "/" << steps << endl; centroids.clear(); @@ -193,121 +270,20 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { for(unsigned int v = 0; v < crude.Vertices(); v++) { if(v & 0xffff) report.Step(v); unsigned int ctarget = 0xffffffff; - float dist = coarse.Closest(crude.vert[v], ctarget); + ctarget = coarse.Locate(crude.vert[v]); + // float dist; + // coarse.Closest(crude.vert[v], ctarget, dist); assert(ctarget != 0xffffffff); centroids[ctarget] += crude.vert[v]; counts[ctarget]++; //if(dist > radius[ctarget]) radius[ctarget] = dist; } - - //remove small or really big patches. - unsigned int failed = 0; - vector seeds; - for(unsigned int i = 0; i < coarse.size(); i++) { - if(counts[i] == 0 || (counts[i] < min_size && step != steps-3)) { - failed++; - } else if(counts[i] > max_size) { - cerr << "Failed: " << i << " tot: " << counts[i] << endl; - failed++; - Seed s = coarse[i]; - s.p = centroids[i]/(float)counts[i] + Point3f(1, 0, 0); - coarse[i].weight = (float)pow((counts[i]/2)/(float)coarse_vmean, 0.2f); - s.weight = coarse[i].weight; - seeds.push_back(coarse[i]); - seeds.push_back(s); - } else { - if(step != steps -1) { - coarse[i].p = centroids[i]/(float)counts[i]; - coarse[i].weight = (float)pow(counts[i]/(float)coarse_vmean, 0.2f); - } - seeds.push_back(coarse[i]); - } - } - coarse.clear(); - for(unsigned int i = 0; i < seeds.size(); i++) - coarse.push_back(seeds[i]); - - if(coarse.size() == 0) coarse.push_back(Point3f(0,0,0)); - coarse.Init(); - if(step == steps-1 && failed) step--; + if(step == steps-1) { + if(!Optimize(coarse_vmean, coarse, centroids, counts, false)) + step --; + } else + Optimize(coarse_vmean, coarse, centroids, counts, true); } - - - //remove small or zero patches. - vector seeds; - for(unsigned int i = 0; i < coarse.size(); i++) { - if(counts[i] > (int)min_size) - seeds.push_back(coarse[i]); - } - coarse.clear(); - for(unsigned int i = 0; i < seeds.size(); i++) - coarse.push_back(seeds[i]); - - if(coarse.size() == 0) coarse.push_back(Point3f(0,0,0)); - coarse.Init(); - - - //Coarse optimization - /* vector< map > centroids; - vector< map > counts; - - for(unsigned int i = 0; i < steps; i++) { - cerr << "Optimization step 1: " << i << "/" << steps << endl; - centroids.clear(); - counts.clear(); - centroids.resize(coarse.size()); - counts.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 ¢roids = centroids[ctarget]; - map &count = counts[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 ¢roids = centroids[v]; - map &count = counts[v]; - - - coarse[v].p = Point3f(0, 0, 0); - float weight = 0; - unsigned int tot_size =0; - map::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.Init(); - }*/ } unsigned int VoronoiChain::Locate(unsigned int level, @@ -418,7 +394,6 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset, levels.push_back(VoronoiPartition()); VoronoiPartition &coarse = levels[levels.size()-1]; VoronoiPartition &fine = levels[levels.size()-2]; - coarse.SetBox(fine.box); fine.Init(); unsigned int tot_coarse = (unsigned int)(fine.size() * scaling); @@ -452,60 +427,32 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset, //Coarse optimization. vector centroids; vector counts; - //vector radius; + for(int step = 0; step < steps; step++) { cerr << "Optimization step: " << step+1 << "/" << steps << endl; centroids.clear(); counts.clear(); centroids.resize(coarse.size(), Point3f(0, 0, 0)); counts.resize(coarse.size(), 0); - //radius.resize(coarse.size(), 0); report.Init(nexus.index.size()); for(unsigned int idx = offset; idx < nexus.index.size(); idx++) { report.Step(idx); Patch patch = nexus.GetPatch(idx); for(unsigned int i = 0; i < patch.nv; i++) { - - unsigned int ctarget = 0xffffffff; - float dist = coarse.Closest(patch.Vert(i), ctarget); - assert(ctarget != 0xffffffff); - centroids[ctarget] += patch.Vert(i); - counts[ctarget]++; - //if(dist > radius[ctarget]) radius[ctarget] = dist; + + unsigned int ctarget = coarse.Locate(patch.Vert(i)); + assert(ctarget < coarse.size()); + centroids[ctarget] += patch.Vert(i); + counts[ctarget]++; } } - //remove small or really big patches. - unsigned int failed = 0; - vector seeds; - for(unsigned int i = 0; i < coarse.size(); i++) { - if(counts[i] == 0 || (counts[i] < min_size && step != steps -3)) { - failed++; - } else if(counts[i] > max_size) { - cerr << "Failed: " << i << " tot: " << counts[i] << endl; - failed++; - Seed s = coarse[i]; - s.p = centroids[i]/(float)counts[i] + Point3f(1, 0, 0); - coarse[i].weight = (float)pow((counts[i]/2)/(float)coarse_vmean, 0.2f); - s.weight = coarse[i].weight; - seeds.push_back(coarse[i]); - seeds.push_back(s); - } else { - if(step != steps-1) { - coarse[i].p = centroids[i]/(float)counts[i]; - coarse[i].weight = (float)pow(counts[i]/(float)coarse_vmean, 0.2f); - } - seeds.push_back(coarse[i]); - } - } - coarse.clear(); - for(unsigned int i = 0; i < seeds.size(); i++) - coarse.push_back(seeds[i]); - - if(coarse.size() == 0) coarse.push_back(Point3f(0,0,0)); - coarse.Init(); - if(step == steps-1 && failed) step--; - } + if(step == steps-1) { + if(!Optimize(coarse_vmean, coarse, centroids, counts, false)) + step--; + } else + Optimize(coarse_vmean, coarse, centroids, counts, true); + } + newfragments.clear(); - //TODO add some optimization } diff --git a/apps/nexus/voronoichain.h b/apps/nexus/voronoichain.h index fdddfb67..cbe80398 100644 --- a/apps/nexus/voronoichain.h +++ b/apps/nexus/voronoichain.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.4 2004/09/30 00:27:42 ponchio +Lot of changes. Backup. + Revision 1.3 2004/09/21 00:53:23 ponchio Lotsa changes. @@ -81,6 +84,10 @@ class VoronoiChain: public PChain { float radius; vcg::Box3f box; + + bool Optimize(int mean, VoronoiPartition &part, + std::vector ¢roids, + std::vector &counts, bool join); }; } diff --git a/apps/nexus/voronoinxs.cpp b/apps/nexus/voronoinxs.cpp index 6ffeec12..f42aab25 100644 --- a/apps/nexus/voronoinxs.cpp +++ b/apps/nexus/voronoinxs.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.19 2004/10/22 10:37:32 ponchio +Split is now in fragment. + Revision 1.18 2004/10/21 13:40:16 ponchio Debugging. @@ -103,13 +106,6 @@ using namespace std; using namespace vcg; using namespace nxs; -/*void NexusSplit(Nexus &nexus, VoronoiChain &vchain, - unsigned int level, - vector &newvert, - vector &newface, - vector &newbord, - Nexus::Update &update, - float error);*/ void BuildFragment(Nexus &nexus, VoronoiPartition &part, set &patches, @@ -377,241 +373,6 @@ int main(int argc, char *argv[]) { return 0; } -/*void NexusSplit(Nexus &nexus, VoronoiChain &vchain, - unsigned int level, - vector &newvert, - vector &newface, - vector &newbord, - Nexus::Update &update, - float error) { - - map centroids; - map counts; - - Point3f centroid(0, 0, 0); - Box3f box; - for(unsigned int f = 0; f < newface.size(); f += 3) { - Point3f bari = (newvert[newface[f]] + - newvert[newface[f+1]] + - newvert[newface[f+2]])/3; - centroid += bari; - box.Add(bari); - unsigned int cell = vchain.Locate(level+1, bari); - if(!centroids.count(cell)) centroids[cell] = Point3f(0, 0, 0); - if(!counts.count(cell)) counts[cell] = 0; - centroids[cell] += bari; - counts[cell]++; - } - centroid /= newface.size()/3; - //prune small cells: - float min_size = (newface.size()/3) / 20.0f; - - vector cellremap; - VoronoiPartition local; - local.SetBox(vchain.levels[level].box); - map::iterator r; - for(r = centroids.begin(); r != centroids.end(); r++) { - unsigned int cell = (*r).first; - if(counts[cell] < min_size) continue; - - Point3f seed = (*r).second/counts[cell]; - Point3f orig = vchain.levels[level+1][cell].p; - // seed = (seed + orig*2)/3; - seed = orig; - local.push_back(seed); - cellremap.push_back(cell); - } - local.Init(); - - //if != -1 remap global index to cell index (first arg) - map > vert_remap; - map vert_count; - - //simply collects faces - map > face_remap; - map face_count; - - for(unsigned int f = 0; f < newface.size(); f += 3) { - Point3f bari = (newvert[newface[f]] + - newvert[newface[f+1]] + - newvert[newface[f+2]])/3; - - // unsigned int cell = vchain.Locate(level+1, bari); - unsigned int cell = cellremap[local.Locate(bari)]; - - vector &f_remap = face_remap[cell]; - f_remap.push_back(newface[f]); - f_remap.push_back(newface[f+1]); - f_remap.push_back(newface[f+2]); - face_count[cell]++; - - if(!vert_remap.count(cell)) { - vert_remap[cell].resize(newvert.size(), -1); - vert_count[cell] = 0; - } - - vector &v_remap = vert_remap[cell]; - - for(int i = 0; i < 3; i++) - if(v_remap[newface[f+i]] == -1) - v_remap[newface[f+i]] = vert_count[cell]++; - } - - //TODO prune small count cells and assure no big ones. - - //lets count borders - map bord_count; - - map::iterator c; - for(c = vert_count.begin(); c != vert_count.end(); c++) { - unsigned int cell = (*c).first; - unsigned int &count = bord_count[cell]; - count = 0; - - vector &v_remap = vert_remap[cell]; - - //external borders - for(unsigned int i = 0; i < newbord.size(); i++) { - Link link = newbord[i]; - if(v_remap[link.start_vert] == -1) continue; - count++; - } - - //process internal borders; - //TODO higly inefficient!!! - map::iterator t; - for(t = vert_count.begin(); t != vert_count.end(); t++) { - if(cell == (*t).first) continue; - vector &vremapclose = vert_remap[(*t).first]; - for(unsigned int i = 0; i < newvert.size(); i++) { - if(v_remap[i] != -1 && vremapclose[i] != -1) { - count++; - } - } - } - } - - map cells2patches; - - //lets allocate space - for(c = vert_count.begin(); c != vert_count.end(); c++) { - unsigned int cell = (*c).first; - //TODO detect best parameter below. - unsigned int patch_idx = nexus.AddPatch(vert_count[cell], - face_count[cell], - 6 * bord_count[cell]); - - //why double border space? because at next level - //we will need to add those borders... - cells2patches[cell] = patch_idx; - vchain.newfragments[cell].insert(patch_idx); - update.created.push_back(patch_idx); - } - - - //fill it now. - for(c = vert_count.begin(); c != vert_count.end(); c++) { - unsigned int cell = (*c).first; - unsigned int patch_idx = cells2patches[cell]; - - //vertices first - vector &v_remap = vert_remap[cell]; - - vector verts; - verts.resize(vert_count[cell]); - for(unsigned int i = 0; i < newvert.size(); i++) { - if(v_remap[i] != -1) - verts[v_remap[i]] = newvert[i]; - } - - //faces now - vector &f_remap = face_remap[cell]; - - vector faces; - faces.resize(face_count[cell]*3); - - for(unsigned int i = 0; i < f_remap.size(); i++) { - assert(v_remap[f_remap[i]] != -1); - faces[i] = v_remap[f_remap[i]]; - } - - //borders last - vector bords; - - //process external borders - //for every esternal link we must update external patches! - for(unsigned int i = 0; i < newbord.size(); i++) { - Link link = newbord[i]; - assert(!link.IsNull()); - if(v_remap[link.start_vert] == -1) continue; - link.start_vert = v_remap[link.start_vert]; - bords.push_back(link); - - - Border rborder = nexus.GetBorder(link.end_patch); - - unsigned int pos = rborder.Size(); - if(nexus.borders.ResizeBorder(link.end_patch, pos+1)) { - rborder = nexus.GetBorder(link.end_patch); - } - - assert(rborder.Size() < rborder.Available()); - assert(rborder.Available() > pos); - - Link newlink; - newlink.start_vert = link.end_vert; - newlink.end_vert = link.start_vert; - newlink.end_patch = patch_idx; - rborder[pos] = newlink; - } - - //process internal borders; - //TODO higly inefficient!!! - map::iterator t; - for(t = vert_count.begin(); t != vert_count.end(); t++) { - unsigned int rcell = (*t).first; - if(cell == rcell) continue; - - assert(cells2patches.count(rcell)); - unsigned int rpatch = cells2patches[rcell]; - assert(rpatch < nexus.index.size()); - - vector &vremapclose = vert_remap[rcell]; - for(unsigned int i = 0; i < newvert.size(); i++) { - if(v_remap[i] != -1 && vremapclose[i] != -1) { - Link link; - link.end_patch = rpatch; - link.start_vert = v_remap[i]; - link.end_vert = vremapclose[i]; - bords.push_back(link); - } - } - } - - - Nexus::PatchInfo &entry = nexus.index[patch_idx]; - entry.error = error; - - Patch patch = nexus.GetPatch(patch_idx); - memcpy(patch.FaceBegin(), &faces[0], - faces.size() * sizeof(unsigned short)); - memcpy(patch.VertBegin(), &verts[0], verts.size() * sizeof(Point3f)); - - - for(unsigned int v = 0; v < verts.size(); v++) { - entry.sphere.Add(verts[v]); - nexus.sphere.Add(verts[v]); - } - - Border border = nexus.GetBorder(patch_idx); - assert(border.Available() >= bords.size()); - if(nexus.borders.ResizeBorder(patch_idx, bords.size())) { - border = nexus.GetBorder(patch_idx); - } - memcpy(&(border[0]), &(bords[0]), bords.size() * sizeof(Link)); - } - }*/ - void BuildFragment(Nexus &nexus, VoronoiPartition &part, set &patches, Nexus::Update &update,