Tests and small changes.
This commit is contained in:
parent
818428b69a
commit
94895e32a6
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue