Fixed big patches problem.

This commit is contained in:
Federico Ponchio 2004-10-30 20:17:03 +00:00
parent 21ee08ab67
commit b6d9d125da
12 changed files with 339 additions and 498 deletions

View File

@ -176,12 +176,10 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
vector<unsigned int> remap; vector<unsigned int> remap;
VoronoiPartition part; VoronoiPartition part;
Box3f box;
for(unsigned int i = 0; i < mesh.vert.size(); i++) { for(unsigned int i = 0; i < mesh.vert.size(); i++) {
const Point3f &p = mesh.vert[i].cP(); const Point3f &p = mesh.vert[i].cP();
box.Add(p);
if(!mesh.vert[i].IsW()) { if(!mesh.vert[i].IsW()) {
part.push_back(Seed(p, 1)); part.push_back(p);
remap.push_back(i); remap.push_back(i);
nseeds--; nseeds--;
} }
@ -192,13 +190,12 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
unsigned int i = rand() % mesh.vert.size(); unsigned int i = rand() % mesh.vert.size();
if(mesh.vert[i].IsW() && !mesh.vert[i].IsV()) { if(mesh.vert[i].IsW() && !mesh.vert[i].IsV()) {
const Point3f &p = mesh.vert[i].cP(); const Point3f &p = mesh.vert[i].cP();
part.push_back(Seed(p, 1)); part.push_back(p);
mesh.vert[i].SetV(); mesh.vert[i].SetV();
remap.push_back(i); remap.push_back(i);
nseeds--; nseeds--;
} }
} }
part.SetBox(box);
part.Init(); part.Init();
vector<Point3f> centroid; vector<Point3f> centroid;
@ -215,13 +212,13 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
} }
for(unsigned int i = nborder; i < part.size(); i++) { for(unsigned int i = nborder; i < part.size(); i++) {
if(count[i] > 0) 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++) { for(unsigned int i = nborder; i < part.size(); i++) {
assert(mesh.vert[remap[i]].IsV()); assert(mesh.vert[remap[i]].IsV());
mesh.vert[remap[i]].P() = part[i].p; mesh.vert[remap[i]].P() = part[i];
} }
float error = 0; float error = 0;
@ -261,5 +258,6 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
mesh.vn--; mesh.vn--;
} }
return error; return error;
} }

View File

@ -47,7 +47,7 @@ void Fragment::Write(outstm *out) {
unsigned int ssize = seeds.size(); unsigned int ssize = seeds.size();
out->write(&ssize, sizeof(unsigned int)); 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)); out->write(&*seeds_id.begin(), ssize * sizeof(unsigned int));
unsigned int psize = pieces.size(); unsigned int psize = pieces.size();
@ -66,7 +66,7 @@ void Fragment::Read(instm *in) {
in->read(&ssize, sizeof(unsigned int)); in->read(&ssize, sizeof(unsigned int));
seeds.resize(ssize); seeds.resize(ssize);
seeds_id.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)); in->read(&*seeds_id.begin(), ssize * sizeof(unsigned int));
unsigned int psize; unsigned int psize;
@ -206,7 +206,7 @@ void nxs::Split(Fragment &out,
VoronoiPartition &part) { VoronoiPartition &part) {
unsigned int nseeds = out.seeds.size(); unsigned int nseeds = out.seeds.size();
vector<Seed> &seeds = out.seeds; vector<Point3f> &seeds = out.seeds;
vector<unsigned int> &seeds_id = out.seeds_id; vector<unsigned int> &seeds_id = out.seeds_id;
//preliminary count //preliminary count
vector<unsigned int> count; vector<unsigned int> count;
@ -222,7 +222,7 @@ void nxs::Split(Fragment &out,
//pruning small patches //pruning small patches
float min_size = (newface.size()/3) / 20.0f; float min_size = (newface.size()/3) / 20.0f;
vector<Seed> newseeds; vector<Point3f> newseeds;
vector<unsigned int> newseeds_id; vector<unsigned int> newseeds_id;
for(unsigned int seed = 0; seed < nseeds; seed++) { for(unsigned int seed = 0; seed < nseeds; seed++) {
@ -346,7 +346,7 @@ unsigned int Fragment::Locate(const Point3f &p) {
float max_dist = 1e20; float max_dist = 1e20;
unsigned int id = 0xffffffff; unsigned int id = 0xffffffff;
for(unsigned int i = 0; i < seeds.size(); i++) { 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) { if(dist < max_dist) {
max_dist = dist; max_dist = dist;
id = i; id = i;

View File

@ -47,7 +47,7 @@ class Fragment {
float error; float error;
std::vector<Seed> seeds; std::vector<vcg::Point3f> seeds;
std::vector<unsigned int> seeds_id; std::vector<unsigned int> seeds_id;
std::vector<NxsPatch> pieces; std::vector<NxsPatch> pieces;

View File

@ -146,8 +146,6 @@ bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) {
void NexusMt::Render() { void NexusMt::Render() {
patches.Flush(); patches.Flush();
Frustumf frustum;
frustum.GetView();
vector<unsigned int> cells; vector<unsigned int> cells;
metric->GetView(); metric->GetView();
@ -155,8 +153,13 @@ void NexusMt::Render() {
tri_total = 0; tri_total = 0;
tri_rendered = 0; tri_rendered = 0;
Extract(cells); Extract(cells);
Draw(cells);
}
void NexusMt::Draw(vector<unsigned int> &cells) {
Frustumf frustum;
frustum.GetView();
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
if(use_colors) if(use_colors)

View File

@ -135,7 +135,7 @@ class NexusMt: public Nexus {
bool SetComponents(unsigned int mask); bool SetComponents(unsigned int mask);
//void ExtractFixed(std::vector<unsigned int> &selected, float error); void Draw(std::vector<unsigned int> &selected);
void Extract(std::vector<unsigned int> &selected); void Extract(std::vector<unsigned int> &selected);
protected: protected:

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $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 Revision 1.17 2004/10/21 12:22:21 ponchio
Small changes. Small changes.
@ -212,6 +215,7 @@ int main(int argc, char *argv[]) {
bool show_colors = true; bool show_colors = true;
bool show_normals = true; bool show_normals = true;
bool show_statistics = true; bool show_statistics = true;
bool extract = true;
NexusMt::MetricKind metric; NexusMt::MetricKind metric;
NexusMt::Mode mode = NexusMt::SMOOTH; NexusMt::Mode mode = NexusMt::SMOOTH;
@ -251,10 +255,11 @@ int main(int argc, char *argv[]) {
track.ButtonDown(Trackball::KEY_CTRL); break; track.ButtonDown(Trackball::KEY_CTRL); break;
case SDLK_q: exit(0); break; case SDLK_q: exit(0); break;
case SDLK_b: show_borders = !show_borders; 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_c: show_colors = !show_colors; break;
case SDLK_n: show_normals = !show_normals; break; case SDLK_n: show_normals = !show_normals; break;
case SDLK_9: nexus.patches.ram_size *= 0.8; break; case SDLK_9: nexus.patches.ram_size *= 0.8f; break;
case SDLK_0: nexus.patches.ram_size *= 1.2; break; case SDLK_0: nexus.patches.ram_size *= 1.2f; break;
case SDLK_LEFT: case SDLK_LEFT:
ram_size *= 0.7; ram_size *= 0.7;
@ -367,9 +372,19 @@ int main(int argc, char *argv[]) {
nexus.SetComponent(NexusMt::COLOR, show_colors); nexus.SetComponent(NexusMt::COLOR, show_colors);
nexus.SetComponent(NexusMt::NORMAL, show_normals); nexus.SetComponent(NexusMt::NORMAL, show_normals);
static vector<unsigned int> cells;
watch.Start(); watch.Start();
if(extract) {
nexus.patches.Flush();
nexus.Render(); 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: //cerr Do some reporting:
if(show_statistics) { if(show_statistics) {

View File

@ -1,13 +1,3 @@
#include <iostream>
using namespace std;
#include "nxsalgo.h"
#include "nexus.h"
#include "watch.h"
using namespace nxs;
using namespace vcg;
#ifdef WIN32 #ifdef WIN32
#include <wrap/system/getopt.h> #include <wrap/system/getopt.h>
#else #else
@ -17,6 +7,33 @@ using namespace vcg;
#include <assert.h> #include <assert.h>
#include <iostream>
#include <vcg/simplex/vertex/with/vc.h>
#include <vcg/simplex/face/face.h>
#include <vcg/complex/trimesh/base.h>
//WARNING WARNING this must be included AFTER mesh includes....
#include <wrap/io_trimesh/import_ply.h>
#include <vcg/space/index/grid_static_ptr.h>
#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<DUMMYEDGETYPE,CFace ,DUMMYTETRATYPE> {};
class CFace: public Face<CVertex, DUMMYEDGETYPE , CFace>{};
class CMesh: public tri::TriMesh<vector<CVertex>, vector<CFace> > {};
string getSuffix(unsigned int signature) { string getSuffix(unsigned int signature) {
string suff; string suff;
if(signature&NXS_COMPRESSED) suff += "Z"; if(signature&NXS_COMPRESSED) suff += "Z";
@ -261,6 +278,24 @@ int main(int argc, char *argv[]) {
nexus.Close(); nexus.Close();
return 0; return 0;
} }
CMesh mesh;
GridStaticPtr<CMesh::FaceContainer> grid;
if(add_colors) {
if(!plysource.size()) {
cerr << "No plysource specified when adding color (-p option)\n";
return -1;
}
if(!tri::io::ImporterPLY<CMesh>::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) { if((add & NXS_NORMALS_SHORT) && compress) {
cerr << "Its not possible to add normals and compress in the same step\n"; cerr << "Its not possible to add normals and compress in the same step\n";
@ -377,6 +412,7 @@ int main(int argc, char *argv[]) {
cerr << "Unsupported color\n"; cerr << "Unsupported color\n";
return -1; return -1;
} }
if(qvertex && add_normals) { if(qvertex && add_normals) {
report.Init(nexus.index.size()); report.Init(nexus.index.size());
cout << "Quantizing vertices\n"; cout << "Quantizing vertices\n";
@ -391,9 +427,7 @@ int main(int argc, char *argv[]) {
report.Finish(); report.Finish();
} }
//fixing sphere.
out.sphere = nexus.sphere; out.sphere = nexus.sphere;
//copying history:
out.history = nexus.history; out.history = nexus.history;
out.Close(); out.Close();

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $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 Revision 1.5 2004/09/28 10:26:21 ponchio
Rewrote. Rewrote.
@ -48,16 +51,68 @@ Created
****************************************************************************/ ****************************************************************************/
#pragma warning(disable:4786 4804 4244 4018 4267 4311)
#include <stdio.h> #include <stdio.h>
#include <iostream> #include <iostream>
#include "pvoronoi.h" #include "pvoronoi.h"
#include <ANN/ANN.h>
using namespace std; using namespace std;
using namespace vcg; using namespace vcg;
using namespace nxs; 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<int> &near,
vector<float> &dist) {
double point[3];
point[0] = p[0];
point[1] = p[1];
point[2] = p[2];
near.resize(nsize);
dist.resize(nsize);
vector<double> 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) { Point3f &res) {
float newdist = Distance(p, point) * weight; float newdist = Distance(p, point) * weight;
if(newdist < mindist) { if(newdist < mindist) {
@ -115,3 +170,4 @@ Point3f VoronoiPartition::FindBorder(vcg::Point3f &p, float radius) {
} }
return m; return m;
} }
*/

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $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 Revision 1.7 2004/09/28 10:26:21 ponchio
Rewrote. Rewrote.
@ -63,16 +66,33 @@ Created
#include <stdio.h> #include <stdio.h>
#include <vcg/space/point3.h> #include <vcg/space/point3.h>
#include <vcg/space/box3.h>
#include <vcg/space/index/grid_static_ptr.h>
#include "crude.h"
//TODO provide a Sort function, to sort spatially the seeds. //TODO provide a Sort function, to sort spatially the seeds.
class ANNkd_tree;
namespace nxs { namespace nxs {
class Seed {
class VoronoiPartition: public std::vector<vcg::Point3f> {
public:
VoronoiPartition(): bd(NULL) {}
void Init();
void Closest(const vcg::Point3f &p, unsigned int nsize,
std::vector<int> &near,
std::vector<float> &dist);
void Closest(const vcg::Point3f &p,
int &target, float &dist);
int Locate(const vcg::Point3f &p);
ANNkd_tree *bd;
std::vector<double> buffer;
std::vector<double *> points;
};
/* class Seed {
public: public:
vcg::Point3f p; vcg::Point3f p;
float weight; float weight;
@ -112,7 +132,7 @@ namespace nxs {
return target; return target;
} }
vcg::Box3f box; vcg::Box3f box;
}; };*/
} }
#endif #endif

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $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 Revision 1.16 2004/10/22 14:31:56 ponchio
Some controls added. Some controls added.
@ -85,35 +88,140 @@ using namespace vcg;
using namespace nxs; using namespace nxs;
void print(Point3f p) {
cerr << p[0] << " " << p[1] << " " << p[2] << endl;
}
float getClosest(const Point3f &seed, VoronoiPartition &part) {
vector<int> near;
vector<float> 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<bool> &mark,
vector<unsigned int> &counts) {
vector<int> near;
vector<float> 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<Point3f> &centroids,
vector<unsigned int> &counts,
bool join) {
//remove small or really big patches.
unsigned int failed = 0;
vector<Point3f> seeds;
vector<bool> 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) { void VoronoiChain::Init(Crude &crude, float scaling, int steps) {
unsigned int f_cells = crude.Faces() / mean_size; unsigned int f_cells = crude.Faces() / mean_size;
unsigned int c_cells = (unsigned int)(scaling * f_cells); 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());
levels.push_back(VoronoiPartition()); levels.push_back(VoronoiPartition());
VoronoiPartition &fine = levels[0]; VoronoiPartition &fine = levels[0];
VoronoiPartition &coarse = levels[1]; VoronoiPartition &coarse = levels[1];
fine.SetBox(crude.GetBox());
coarse.SetBox(crude.GetBox());
srand(0); srand(0);
float fine_vmean = mean_size/2.0f; 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++) { for(unsigned int i = 0; i < crude.Vertices(); i++) {
int f = (int)(fine_vmean*rand()/(RAND_MAX + 1.0)); int f = (int)(fine_vmean * rand()/(RAND_MAX + 1.0));
int c = (int)(coarse_vmean *rand()/(RAND_MAX + 1.0)); int c = (int)(coarse_vmean * rand()/(RAND_MAX + 1.0));
if(f == 1) { if(f == 2) {
Point3f &point = crude.GetVertex(i); 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); Point3f &point = crude.GetVertex(i);
coarse.push_back(Seed(point, 1)); coarse.push_back(point);
} }
} }
//TODO! Check for duplicates (use the closest :P) //TODO! Check for duplicates (use the closest :P)
@ -122,7 +230,7 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) {
fine.Init(); fine.Init();
coarse.Init(); coarse.Init();
//here goes some optimization pass. //here goes some optimization pass.
//Fine optimization. //Fine optimization.
Report report; Report report;
vector<Point3f> centroids; vector<Point3f> centroids;
@ -136,51 +244,20 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) {
report.Init(crude.Vertices()); report.Init(crude.Vertices());
for(unsigned int v = 0; v < crude.Vertices(); v++) { for(unsigned int v = 0; v < crude.Vertices(); v++) {
if(v & 0xffff) report.Step(v); report.Step(v);
unsigned int ftarget; unsigned int target = fine.Locate(crude.vert[v]);
float dist = fine.Closest(crude.vert[v], ftarget); centroids[target] += crude.vert[v];
assert(ftarget != -1); counts[target]++;
centroids[ftarget] += crude.vert[v];
counts[ftarget]++;
} }
if(step == steps-1) {
//remove small or really big patches. if(!Optimize(fine_vmean, fine, centroids, counts, false))
unsigned int failed = 0; step--;
vector<Seed> seeds; } else
for(unsigned int i = 0; i < fine.size(); i++) { Optimize(fine_vmean, fine, centroids, counts, true);
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]); //here goes some optimization pass.
} //Coarse optimization.
} //vector<float> radius;
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<float> radius;
for(int step = 0; step < steps; step++) { for(int step = 0; step < steps; step++) {
cerr << "Optimization step: " << step+1 << "/" << steps << endl; cerr << "Optimization step: " << step+1 << "/" << steps << endl;
centroids.clear(); centroids.clear();
@ -193,121 +270,20 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) {
for(unsigned int v = 0; v < crude.Vertices(); v++) { for(unsigned int v = 0; v < crude.Vertices(); v++) {
if(v & 0xffff) report.Step(v); if(v & 0xffff) report.Step(v);
unsigned int ctarget = 0xffffffff; 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); assert(ctarget != 0xffffffff);
centroids[ctarget] += crude.vert[v]; centroids[ctarget] += crude.vert[v];
counts[ctarget]++; counts[ctarget]++;
//if(dist > radius[ctarget]) radius[ctarget] = dist; //if(dist > radius[ctarget]) radius[ctarget] = dist;
} }
if(step == steps-1) {
//remove small or really big patches. if(!Optimize(coarse_vmean, coarse, centroids, counts, false))
unsigned int failed = 0; step --;
vector<Seed> seeds; } else
for(unsigned int i = 0; i < coarse.size(); i++) { Optimize(coarse_vmean, coarse, centroids, counts, true);
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--;
}
//remove small or zero patches.
vector<Seed> 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<unsigned int, Point3f> > centroids;
vector< map<unsigned int, unsigned int> > 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<unsigned int, Point3f> &centroids = centroids[ctarget];
map<unsigned int, unsigned int> &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<unsigned int, Point3f> &centroids = centroids[v];
map<unsigned int, unsigned int> &count = counts[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.Init();
}*/
} }
unsigned int VoronoiChain::Locate(unsigned int level, unsigned int VoronoiChain::Locate(unsigned int level,
@ -418,7 +394,6 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset,
levels.push_back(VoronoiPartition()); levels.push_back(VoronoiPartition());
VoronoiPartition &coarse = levels[levels.size()-1]; VoronoiPartition &coarse = levels[levels.size()-1];
VoronoiPartition &fine = levels[levels.size()-2]; VoronoiPartition &fine = levels[levels.size()-2];
coarse.SetBox(fine.box);
fine.Init(); fine.Init();
unsigned int tot_coarse = (unsigned int)(fine.size() * scaling); unsigned int tot_coarse = (unsigned int)(fine.size() * scaling);
@ -452,14 +427,13 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset,
//Coarse optimization. //Coarse optimization.
vector<Point3f> centroids; vector<Point3f> centroids;
vector<unsigned int> counts; vector<unsigned int> counts;
//vector<float> radius;
for(int step = 0; step < steps; step++) { for(int step = 0; step < steps; step++) {
cerr << "Optimization step: " << step+1 << "/" << steps << endl; cerr << "Optimization step: " << step+1 << "/" << steps << endl;
centroids.clear(); centroids.clear();
counts.clear(); counts.clear();
centroids.resize(coarse.size(), Point3f(0, 0, 0)); centroids.resize(coarse.size(), Point3f(0, 0, 0));
counts.resize(coarse.size(), 0); counts.resize(coarse.size(), 0);
//radius.resize(coarse.size(), 0);
report.Init(nexus.index.size()); report.Init(nexus.index.size());
for(unsigned int idx = offset; idx < nexus.index.size(); idx++) { for(unsigned int idx = offset; idx < nexus.index.size(); idx++) {
@ -467,45 +441,18 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset,
Patch patch = nexus.GetPatch(idx); Patch patch = nexus.GetPatch(idx);
for(unsigned int i = 0; i < patch.nv; i++) { for(unsigned int i = 0; i < patch.nv; i++) {
unsigned int ctarget = 0xffffffff; unsigned int ctarget = coarse.Locate(patch.Vert(i));
float dist = coarse.Closest(patch.Vert(i), ctarget); assert(ctarget < coarse.size());
assert(ctarget != 0xffffffff);
centroids[ctarget] += patch.Vert(i); centroids[ctarget] += patch.Vert(i);
counts[ctarget]++; counts[ctarget]++;
//if(dist > radius[ctarget]) radius[ctarget] = dist;
} }
} }
//remove small or really big patches. if(step == steps-1) {
unsigned int failed = 0; if(!Optimize(coarse_vmean, coarse, centroids, counts, false))
vector<Seed> seeds; step--;
for(unsigned int i = 0; i < coarse.size(); i++) { } else
if(counts[i] == 0 || (counts[i] < min_size && step != steps -3)) { Optimize(coarse_vmean, coarse, centroids, counts, true);
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--;
}
newfragments.clear(); newfragments.clear();
//TODO add some optimization
} }

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $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 Revision 1.3 2004/09/21 00:53:23 ponchio
Lotsa changes. Lotsa changes.
@ -81,6 +84,10 @@ class VoronoiChain: public PChain {
float radius; float radius;
vcg::Box3f box; vcg::Box3f box;
bool Optimize(int mean, VoronoiPartition &part,
std::vector<vcg::Point3f> &centroids,
std::vector<unsigned int> &counts, bool join);
}; };
} }

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $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 Revision 1.18 2004/10/21 13:40:16 ponchio
Debugging. Debugging.
@ -103,13 +106,6 @@ using namespace std;
using namespace vcg; using namespace vcg;
using namespace nxs; using namespace nxs;
/*void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
unsigned int level,
vector<Point3f> &newvert,
vector<unsigned int> &newface,
vector<Link> &newbord,
Nexus::Update &update,
float error);*/
void BuildFragment(Nexus &nexus, VoronoiPartition &part, void BuildFragment(Nexus &nexus, VoronoiPartition &part,
set<unsigned int> &patches, set<unsigned int> &patches,
@ -377,241 +373,6 @@ int main(int argc, char *argv[]) {
return 0; return 0;
} }
/*void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
unsigned int level,
vector<Point3f> &newvert,
vector<unsigned int> &newface,
vector<Link> &newbord,
Nexus::Update &update,
float error) {
map<unsigned int, Point3f> centroids;
map<unsigned int, unsigned int> 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<unsigned int> cellremap;
VoronoiPartition local;
local.SetBox(vchain.levels[level].box);
map<unsigned int, Point3f>::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<unsigned int, vector<int> > vert_remap;
map<unsigned int, unsigned int> vert_count;
//simply collects faces
map<unsigned int, vector<int> > face_remap;
map<unsigned int, unsigned int> 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<int> &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<int> &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<unsigned int, unsigned int> bord_count;
map<unsigned int, unsigned int >::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<int> &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<unsigned int, unsigned int >::iterator t;
for(t = vert_count.begin(); t != vert_count.end(); t++) {
if(cell == (*t).first) continue;
vector<int> &vremapclose = vert_remap[(*t).first];
for(unsigned int i = 0; i < newvert.size(); i++) {
if(v_remap[i] != -1 && vremapclose[i] != -1) {
count++;
}
}
}
}
map<unsigned int, unsigned int> 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<int> &v_remap = vert_remap[cell];
vector<Point3f> 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<int> &f_remap = face_remap[cell];
vector<unsigned short> 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<Link> 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<unsigned int, unsigned int >::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<int> &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, void BuildFragment(Nexus &nexus, VoronoiPartition &part,
set<unsigned int> &patches, set<unsigned int> &patches,
Nexus::Update &update, Nexus::Update &update,