Tests and small changes.

This commit is contained in:
Federico Ponchio 2004-10-15 11:41:03 +00:00
parent 818428b69a
commit 94895e32a6
7 changed files with 191 additions and 74 deletions

View File

@ -161,9 +161,9 @@ float Quadric(MyMesh &mesh, unsigned int target_faces) {
}
}
error /= count;
cerr << "Error: " << error << endl;
// cerr << "Error: " << error << endl;
cerr << "faces: " << mesh.fn << endl;
cerr << "verts: " << mesh.vn << endl;
// cerr << "verts: " << mesh.vn << endl;
return error;
}
@ -201,8 +201,6 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
part.SetBox(box);
part.Init();
cerr << "inited points\n";
vector<Point3f> centroid;
vector<unsigned int> count;
for(unsigned int i = 0; i < 3; i++) {
@ -226,8 +224,6 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
mesh.vert[remap[i]].P() = part[i].p;
}
cerr << "remapping faces\n";
float error = 0;
//rimappiamo le facce.....
for(unsigned int i = 0; i < mesh.face.size(); i++) {
@ -245,7 +241,6 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
}
}
cerr << "Deleting faces\n";
for(unsigned int i = 0; i < mesh.face.size(); i++) {
MyFace &face = mesh.face[i];
assert(!face.IsD());
@ -260,17 +255,15 @@ float Cluster(MyMesh &mesh, unsigned int target_faces) {
}
}
cerr << "deleting vertices\n";
for(unsigned int i = 0; i < mesh.vert.size(); i++)
if(!mesh.vert[i].IsV() && mesh.vert[i].IsW()) {
mesh.vert[i].SetD();
mesh.vn--;
}
cerr << "Error: " << error << endl;
cerr << "faces: " << mesh.fn << endl;
cerr << "verts: " << mesh.vn << endl;
// cerr << "Error: " << error << endl;
// cerr << "faces: " << mesh.fn << endl;
// cerr << "verts: " << mesh.vn << endl;
return error;
}

View File

@ -15,18 +15,35 @@ using namespace vcg;
using namespace triangle_stripper;
void nxs::ComputeNormals(Nexus &nexus) {
/* WARNING pathological cases may require a lot of memory
expecially if one patch borders with many many other patches */
assert(nexus.signature & NXS_NORMALS_SHORT ||
nexus.signature & NXS_NORMALS_FLOAT);
bool use_short = (nexus.signature & NXS_NORMALS_SHORT) != 0;
//TODO use a temporary file to store border normals
unsigned int tmpb_offset = 0;
vector<unsigned int> tmpb_start;
VFile<Point3f> tmpb;
if(!tmpb.Create("tmpb.tmp")) {
cerr << "Could not create temporary border file\n";
exit(0);
}
for(unsigned int p = 0; p < nexus.index.size(); p++) {
Border border = nexus.GetBorder(p);
tmpb_start.push_back(tmpb_offset);
tmpb_offset += border.Size();
}
Point3f zero(0.0f, 0.0f, 0.0f);
tmpb.Resize(tmpb_offset);
for(unsigned int i = 0; i < tmpb.Size(); i++)
tmpb[i] = zero;
//first step normals in the same patch.
for(unsigned int p = 0; p < nexus.index.size(); p++) {
Patch &patch = nexus.GetPatch(p);
vector<Point3f> normals;
normals.resize(patch.nv, Point3f(0, 0, 0));
@ -72,62 +89,54 @@ void nxs::ComputeNormals(Nexus &nexus) {
memcpy(patch.Norm16Begin(), &*normals.begin(),
normals.size() * sizeof(Point3f));
}
Border border = nexus.GetBorder(p);
set<unsigned int> close;
for(unsigned int i = 0; i < border.Size(); i++) {
Link &link = border[i];
if(link.IsNull()) continue;
unsigned int off = tmpb_start[p];
tmpb[off + i] += normals[link.start_vert];
close.insert(link.end_patch);
}
set<unsigned int>::iterator k;
for(k = close.begin(); k != close.end(); k++) {
Border remote = nexus.GetBorder(*k);
unsigned int off = tmpb_start[*k];
for(unsigned int i = 0; i < remote.Size(); i++) {
Link &link = remote[i];
if(link.IsNull()) continue;
if(link.end_patch != p) continue;
tmpb[off + i] += normals[link.end_vert];
}
}
}
//Second step unify normals across borders
for(unsigned int p = 0; p < nexus.index.size(); p++) {
//notice now ew allow flushing of old patches
Patch &patch = nexus.GetPatch(p);
Border border = nexus.GetBorder(p);
//first pass we collect all normals
map<unsigned short, Point3f> normals;
for(unsigned int i = 0; i < border.Size(); i++) {
Link &link = border[i];
if(link.IsNull()) continue;
if(!normals.count(link.start_vert)) {
assert(link.start_vert < patch.nv);
if(use_short) {
short *n = patch.Norm16(link.start_vert);
normals[link.start_vert] = Point3f(n[0], n[1], n[2]);
} else
normals[link.start_vert] = patch.Norm32(link.start_vert);
}
//no flushing now!
Patch &remote = nexus.GetPatch(link.end_patch, false);
assert(link.end_vert < remote.nv);
if(use_short) {
short *n = remote.Norm16(link.end_vert);
normals[link.start_vert] += Point3f(n[0], n[1], n[2]);
} else
normals[link.start_vert] += remote.Norm32(link.end_vert);
}
//second pass we update values in all the patches involved
for(unsigned int i = 0; i < border.Size(); i++) {
Link &link = border[i];
if(link.IsNull()) continue;
Patch &remote = nexus.GetPatch(link.end_patch, false);
Point3f &n = normals[link.start_vert];
n.Normalize();
unsigned int off = tmpb_start[p];
Point3f &n = tmpb[off + i];
n.Normalize();
if(use_short) {
n *= 32767;
short *nr = remote.Norm16(link.end_vert);
short *np = patch.Norm16(link.start_vert);
nr[0] = np[0] = (short)n[0];
nr[1] = np[1] = (short)n[1];
nr[2] = np[2] = (short)n[2];
np[0] = (short)n[0];
np[1] = (short)n[1];
np[2] = (short)n[2];
} else {
remote.Norm32(link.end_vert) = n;
patch.Norm32(link.end_vert) = n;
patch.Norm32(link.start_vert) = n;
}
}
}
//TODO remove temporary file.
}
/*void nxs::ComputeTriStrip(unsigned short nfaces, unsigned short *faces,

View File

@ -14,6 +14,7 @@ static double wrkmem[LZO1X_1_MEM_COMPRESS/sizeof(double) +1];
static double wrkmem[LZO1X_999_MEM_COMPRESS/sizeof(double) +1];
#endif
void pad(unsigned int &size) {
while(size&0x3) size++;
}
@ -183,9 +184,13 @@ char *Patch::Compress(unsigned int ram_size, unsigned int &size) {
(unsigned char *)buffer + sizeof(int), &size,
(char *)wrkmem);
#else
lzo1x_999_compress(((unsigned char *)start), ram_size,
(unsigned char *)buffer + sizeof(int), &size,
lzo1x_999_compress(((unsigned char *)start), ram_size,
(unsigned char *)buffer + sizeof(int), &size,
(char *)wrkmem);
lzo1x_optimize((unsigned char *)buffer + sizeof(int), size,
((unsigned char *)start), &ram_size,
NULL);
#endif
*(int *)buffer = size;
@ -193,10 +198,7 @@ char *Patch::Compress(unsigned int ram_size, unsigned int &size) {
// memcpy(buffer, start, ram_size);
// size = ram_size;
//TODO optimize!
// lzo1x_optimize((unsigned char *)entry.patch->start,
// entry.ram_size * chunk_size,
// compressed, &compressed_size, NULL);
return buffer;
}

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.5 2004/09/28 10:26:21 ponchio
Rewrote.
Revision 1.4 2004/09/21 00:53:23 ponchio
Lotsa changes.
@ -87,3 +90,28 @@ float VoronoiPartition::Closest(const vcg::Point3f &p,
return mindist;
}
Point3f VoronoiPartition::FindBorder(vcg::Point3f &p, float radius) {
Point3f a = p;
unsigned int atarget = Locate(a);
Point3f &seed = operator[](atarget).p;
if((a - seed).Norm() < radius/100) return p; //Bad luck.
Point3f dir = (a - seed).Normalize();
Point3f b = seed + dir*radius*1.1;
unsigned int btarget = Locate(b);
if(atarget == btarget) {
//probably nothing on the side we are looking gor;
return p;
}
Point3f m;
for(unsigned int i = 0; i < 10; i++) {
m = (a + b)/2;
unsigned int mtarget = Locate(m);
if(mtarget == atarget) a = m;
else if(mtarget == btarget) b = m;
else break; //something in the middle
}
return m;
}

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.7 2004/09/28 10:26:21 ponchio
Rewrote.
Revision 1.6 2004/09/21 00:53:23 ponchio
Lotsa changes.
@ -101,7 +104,8 @@ namespace nxs {
void Init();
float Closest(const vcg::Point3f &p,
unsigned int &target, float radius = 0);
vcg::Point3f FindBorder(vcg::Point3f &p, float radius);
unsigned int Locate(const vcg::Point3f &p) {
unsigned int target;
Closest(p, target);

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.11 2004/10/10 17:19:42 ponchio
Added compression and debugged.
Revision 1.10 2004/10/09 14:46:47 ponchio
Windows porting small changes.
@ -143,12 +146,14 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) {
//Coarse optimization.
vector<Point3f> ccentroids;
vector<unsigned int> ccount;
vector<float> radius;
for(int i = 0; i < steps; i++) {
cerr << "Optimization step 0: " << i << "/" << steps << endl;
ccentroids.clear();
ccount.clear();
ccentroids.resize(fine.size(), Point3f(0, 0, 0));
ccount.resize(fine.size(), 0);
ccentroids.resize(coarse.size(), Point3f(0, 0, 0));
ccount.resize(coarse.size(), 0);
radius.resize(coarse.size(), 0);
for(unsigned int v = 0; v < crude.Vertices(); v++) {
unsigned int ctarget = 0xffffffff;
@ -156,12 +161,37 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) {
assert(ctarget != 0xffffffff);
ccentroids[ctarget] += crude.vert[v];
ccount[ctarget]++;
if(dist > radius[ctarget]) radius[ctarget] = dist;
}
for(unsigned int v = 0; v < coarse.size(); v++) {
if(ccount[v] == 0) continue;
coarse[v].p = ccentroids[v]/(float)ccount[v];
coarse[v].weight = (float)pow(ccount[v]/(float)coarse_vmean, 0.3f);
if(radius[v] == 0) continue;
//repel from fine seeds
unsigned int atarget;
float closest = fine.Closest(coarse[v].p, atarget);
Point3f dir = (coarse[v].p - fine[atarget].p).Normalize();
Point3f a = coarse[v].p;
Point3f b = fine[atarget].p + dir*radius[v]*1.1;
unsigned int btarget;
closest = fine.Closest(b, btarget);
if(atarget == btarget) {
continue;
}
Point3f m;
for(unsigned int i = 0; i < 10; i++) {
m = (a + b)/2;
unsigned int mtarget;
fine.Closest(m, mtarget);
if(mtarget == atarget) a = m;
else if(mtarget == btarget) b = m;
else break;
}
coarse[v].p = m;
}
coarse.Init();
}
@ -343,7 +373,7 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset,
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);
@ -373,13 +403,15 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset,
//Coarse optimization.
vector<Point3f> ccentroids;
vector<unsigned int> ccount;
vector<float> radius;
for(int i = 0; i < steps; i++) {
cerr << "Optimization step 0: " << i << "/" << steps << endl;
ccentroids.clear();
ccount.clear();
ccentroids.resize(fine.size(), Point3f(0, 0, 0));
ccount.resize(fine.size(), 0);
ccentroids.resize(coarse.size(), Point3f(0, 0, 0));
ccount.resize(coarse.size(), 0);
radius.resize(coarse.size(), 0);
for(unsigned int idx = offset; idx < nexus.index.size(); idx++) {
Patch patch = nexus.GetPatch(idx);
for(unsigned int i = 0; i < patch.nv; i++) {
@ -389,6 +421,7 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset,
assert(ctarget != 0xffffffff);
ccentroids[ctarget] += patch.Vert(i);
ccount[ctarget]++;
if(dist > radius[ctarget]) radius[ctarget] = dist;
}
}
for(unsigned int v = 0; v < coarse.size(); v++) {
@ -397,7 +430,11 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset,
coarse[v].p = ccentroids[v]/(float)ccount[v];
//0.3 is related to the fact is doubled the box size.
coarse[v].weight = (float)pow(ccount[v]/(float)coarse_vmean, 0.3f);
// fine.bbox.Add(fine[v].p);
if(radius[v] == 0) continue;
//repel from fine seeds
}
// fine.Init(fine.bbox);
coarse.Init();

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.14 2004/10/10 17:19:42 ponchio
Added compression and debugged.
Revision 1.13 2004/10/09 17:32:25 ponchio
Ram buffer option added (last)
@ -289,7 +292,6 @@ int main(int argc, char *argv[]) {
//unify vertices otherwise you may get cracks.
nexus.Unify();
nexus.patches.FlushAll();
TestPatches(nexus);
/* BUILDING OTHER LEVELS */
unsigned int oldoffset = 0;
@ -377,6 +379,46 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
Nexus::Update &update,
float error) {
cerr << "Counting nearby cells" << endl;
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;
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;
@ -390,7 +432,9 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
newvert[newface[f+1]] +
newvert[newface[f+2]])/3;
unsigned int cell = vchain.Locate(level+1, bari);
// 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]);
@ -409,7 +453,7 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
v_remap[newface[f+i]] = vert_count[cell]++;
}
//TODO prune small count cells
//TODO prune small count cells and assure no big ones.
//lets count borders
map<unsigned int, unsigned int> bord_count;