Fixed big patches problem.
This commit is contained in:
parent
21ee08ab67
commit
b6d9d125da
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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> ¢roids,
|
||||||
|
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> ¢roids = 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> ¢roids = 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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> ¢roids,
|
||||||
|
std::vector<unsigned int> &counts, bool join);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue