diff --git a/apps/nexus/border.h b/apps/nexus/border.h index 08670b73..df23329e 100644 --- a/apps/nexus/border.h +++ b/apps/nexus/border.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.5 2004/10/08 14:46:26 ponchio +Working version. + Revision 1.4 2004/09/30 00:27:08 ponchio Added used counter. @@ -71,18 +74,18 @@ struct Link { class Border { public: Border(Link *l = NULL, unsigned short _used = 0, unsigned short _size = 0): - start(l), used(_used), size(_size) {} + links(l), used(_used), size(_size), start(0) {} unsigned int Size() { return used; } //TODO rename available to capacity. unsigned int Available() { return size; } - Link &operator[](unsigned int i) { return start[i]; } - Link *Start() { return start; } + Link &operator[](unsigned int i) { return links[i]; } + Link *Start() { return links; } - //TODO implement an iterator! - private: - Link *start; - unsigned short used; - unsigned short size; + //TODO implement an iterator! + Link *links; + unsigned int used; + unsigned int size; + unsigned int start; }; } diff --git a/apps/nexus/borderserver.cpp b/apps/nexus/borderserver.cpp index 8b91bbba..123bef9f 100644 --- a/apps/nexus/borderserver.cpp +++ b/apps/nexus/borderserver.cpp @@ -6,19 +6,22 @@ using namespace nxs; bool BorderServer::Create(const string &file) { ram_used = 0; - return IndexFile::Create(file, 2 * sizeof(Link)); + return IndexFile::Create(file, 2 * sizeof(Link)); } bool BorderServer::Load(const string &file, bool rdonly) { - ram_used = 0; - cerr << "Loading...\n"; - return IndexFile::Load(file, rdonly); + ram_used = 0; + bool success = IndexFile::Load(file, rdonly); + if(!success) return false; + for(unsigned int i = 0; i < size(); i++) + operator[](i).links = NULL; + return true; } void BorderServer::Close() { if(!Opened()) return; Flush(); - IndexFile::Close(); + IndexFile::Close(); } void BorderServer::Flush() { @@ -31,20 +34,20 @@ void BorderServer::Flush() { index.clear(); } -void BorderServer::AddBorder(unsigned short nbord, unsigned int used) { - BorderEntry entry; +void BorderServer::AddBorder(unsigned short _size, unsigned int used) { + Border entry; assert((Length() % sizeof(Link)) == 0); entry.start = Length()/ sizeof(Link); - entry.size = nbord; + entry.size = _size; entry.used = used; entry.links = NULL; push_back(entry); - Redim(entry.start * sizeof(Link) + nbord * sizeof(Link)); + Redim(entry.start * sizeof(Link) + _size * sizeof(Link)); } -Border BorderServer::GetBorder(unsigned int border, bool flush) { - BorderEntry &entry = operator[](border); +Border &BorderServer::GetBorder(unsigned int border, bool flush) { + Border &entry = operator[](border); //assert(entry.size != 0); if(index.count(border)) { //assert(entry.links); @@ -59,61 +62,59 @@ Border BorderServer::GetBorder(unsigned int border, bool flush) { pqueue.pop_back(); index.erase(to_flush); FlushBorder(to_flush); - } - assert(!entry.links); - if(entry.size != 0) - entry.links = GetRegion(entry.start, entry.size); + } + entry.links = GetRegion(entry.start, entry.size); pqueue.push_front(border); index[border] = pqueue.begin(); ram_used += entry.size; } - return Border(entry.links, entry.used, entry.size); + return entry; } //TODO Change when remving borderentry class. -bool BorderServer::ResizeBorder(unsigned int border, unsigned int nbord) { - assert(nbord < 65500); - assert(border < size()); - GetBorder(border); - BorderEntry &entry = operator[](border); - if(nbord > entry.size) { - int capacity = nbord; - if(capacity < entry.size*2) - capacity = entry.size * 2; - if(capacity > 65500) - capacity = 65500; - unsigned int newstart = Length()/sizeof(Link); - Redim((newstart + capacity) * sizeof(Link)); - Link *dst = GetRegion(newstart, capacity); - if(entry.used > 0) { - Link *src = GetRegion(entry.start, entry.size); - memcpy(dst, src, entry.used * sizeof(Link)); - } - entry.links = dst; - entry.start = newstart; - entry.size = capacity; - entry.used = nbord; - return true; +void BorderServer::ResizeBorder(unsigned int border, unsigned int used) { + assert(border < size()); + Border &entry = GetBorder(border); + if(used <= entry.size) { + entry.used = used; + return; } - entry.used = nbord; - return false; + + int capacity = used; + if(capacity < entry.size * 2) + capacity = entry.size * 2; + + unsigned int newstart = Length()/sizeof(Link); + Redim((newstart + capacity) * sizeof(Link)); + Link *newlinks = new Link[capacity]; + if(entry.used > 0) { + assert(entry.links); + memcpy(newlinks, entry.links, entry.used * sizeof(Link)); + delete []entry.links; + entry.links = NULL; + } + assert(entry.links == NULL); + entry.links = newlinks; + entry.start = newstart; + entry.size = capacity; + entry.used = used; } void BorderServer::FlushBorder(unsigned int border) { - BorderEntry &entry = operator[](border); + Border &entry = operator[](border); //assert(entry.links); if(entry.size && !MFile::IsReadOnly()) { //write back patch MFile::SetPosition((int64)entry.start * sizeof(Link)); MFile::WriteBuffer(entry.links, entry.used * sizeof(Link)); } - if(entry.size) + if(entry.links) delete [](entry.links); entry.links = NULL; ram_used -= entry.size; } Link *BorderServer::GetRegion(unsigned int start, unsigned int size) { - assert(size > 0); - SetPosition(start * sizeof(Link)); + if(size == 0) return NULL; + SetPosition((int64)start * sizeof(Link)); Link *buf = new Link[size]; assert(buf); ReadBuffer(buf, size * sizeof(Link)); diff --git a/apps/nexus/borderserver.h b/apps/nexus/borderserver.h index 83c94ce8..0b41449a 100644 --- a/apps/nexus/borderserver.h +++ b/apps/nexus/borderserver.h @@ -16,14 +16,14 @@ namespace nxs { //This should be Border class!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -struct BorderEntry { +/*struct BorderEntry { unsigned int start; //granuralita' Link unsigned short size; //in Links //TODO what are this? be clear! unsigned short used; //in Links Link *links; -}; +};*/ -class BorderServer: public IndexFile { +class BorderServer: public IndexFile { public: BorderServer(): ram_max(1000000), ram_used(0) {} ~BorderServer() { Close(); } @@ -32,17 +32,16 @@ class BorderServer: public IndexFile { void Close(); void Flush(); - void AddBorder(unsigned short nbord, unsigned int used = 0); - Border GetBorder(unsigned int border, bool flush = true); - //return true if you need to reread border as it changed location - bool ResizeBorder(unsigned int border, unsigned int nbord); + void AddBorder(unsigned short size, unsigned int used = 0); + Border &GetBorder(unsigned int border, bool flush = true); + void ResizeBorder(unsigned int border, unsigned int size); - unsigned int BorderSize(unsigned int i) { + /*unsigned int BorderSize(unsigned int i) { return operator[](i).used; } unsigned int BorderCapacity(unsigned int i) { return operator[](i).size; - } + } */ protected: unsigned int ram_max; unsigned int ram_used; diff --git a/apps/nexus/extraction.cpp b/apps/nexus/extraction.cpp index 02037549..52f145d6 100644 --- a/apps/nexus/extraction.cpp +++ b/apps/nexus/extraction.cpp @@ -7,8 +7,8 @@ using namespace std; using namespace nxs; -Extraction::Extraction(): target_error(4.0f), extr_max(0xffffffff), - draw_max(640), disk_max(100) { +Extraction::Extraction(): target_error(4.0f), extr_max(10000), + draw_max(10000), disk_max(100) { metric = new FrustumMetric; } @@ -63,26 +63,26 @@ void Extraction::Init() { for(n = node.out_begin(); n != node.out_end(); n++) { if(!visited[(*n).node - root]) { - float maxerror = 0; + float maxerror = -1; - Link &link = *n; - for(Link::iterator k = link.begin(); k != link.end(); k++) { - unsigned int patch = (*k).patch; - Entry &entry = (*mt)[patch]; - float error = metric->GetError(entry); - if(error > maxerror) maxerror = error; + Link &link = *n; + for(Link::iterator k = link.begin(); k != link.end(); k++) { + unsigned int patch = (*k).patch; + Entry &entry = (*mt)[patch]; + float error = metric->GetError(entry); + if(error > maxerror) maxerror = error; - cost.extr += entry.ram_size; - vcg::Sphere3f &sphere = entry.sphere; - if(!frustum.IsOutside(sphere.Center(), sphere.Radius())) - cost.draw += entry.ram_size; - if(!entry.patch) - cost.disk += entry.disk_size; - } - if((*n).node != sink && maxerror > target_error) - front.push_back(HeapNode((*n).node, maxerror)); + cost.extr += entry.ram_size; + vcg::Sphere3f &sphere = entry.sphere; + if(!frustum.IsOutside(sphere.Center(), sphere.Radius())) + cost.draw += entry.ram_size; + if(!entry.patch) + cost.disk += entry.disk_size; + } + if((*n).node != sink && maxerror > target_error) + front.push_back(HeapNode((*n).node, maxerror)); } else - cancoarse = false; + cancoarse = false; } if(cancoarse && &node != root) { float error = GetRefineError(&node); @@ -109,44 +109,80 @@ void Extraction::Update(NexusMt *_mt) { } Init(); + + bool no_draw = false; + bool no_disk = false; - //first we coarse - while(back.size()) { - if(draw_used <= draw_max && - extr_used <= extr_max && - (front.size() && back.front().error > front.front().error)) + //TODO big problem: nodes a (error 10) with parent b (error -1) + //i try to refine a, refine b (recursive) but fail to refine a + //next step i coarse b whis cause a cycle. + + while(1) { + if(!no_draw && //we have buffer + front.size() && //we are not at max level + front[0].error > target_error) { //we are not already target_error + + pop_heap(front.begin(), front.end()); + HeapNode hnode = front.back(); + front.pop_back(); + if(!Visited(hnode.node)) { + if(!Refine(hnode)) { + no_draw = true; + } + } + continue; + } + + if(!back.size()) { + //cerr << "nothing to coarse!\n"; + break; //nothing to coarse (happen only on extr_max < root.extr + } + + if(no_draw) { //suppose i have no more buffer + //if i do error damages coarsening better get out + if(front.size() && ((back.front().error + 0.001) >= front.front().error)) { + //cerr << "Balanced cut\n"; + break; + } + if(!front.size() && back.front().error >= target_error) { + //cerr << "Maxed out\n"; + break; + } + } + + //nothing to refine, coarse only if error <= target_error + if(!no_draw && back.front().error >= target_error) { + //cerr << "error dominating\n"; break; + } + + pop_heap(back.begin(), back.end(), greater()); HeapNode hnode = back.back(); - - if(Visited(hnode.node)) { - if(!Coarse(hnode)) { //push back on heap the heapnode - push_heap(back.begin(), back.end(), greater()); - break; - } - } back.pop_back(); - } - - while(front.size() && (*front.begin()).error > target_error) { - pop_heap(front.begin(), front.end()); - HeapNode hnode = front.back(); - - if(!Visited(hnode.node)) { - if(!Refine(hnode.node)) { - push_heap(front.begin(), front.end()); - break; + if(Visited(hnode.node)) { + bool recursive = false; + Node::iterator i; + for(i = hnode.node->out_begin(); i != hnode.node->out_end(); i++) { + Node *child = (*i).node; + if(visited[child-root]) recursive = true; + } + if(!recursive && !Coarse(hnode)) { //no more disk so.. push back on heap the heapnode + back.push_back(hnode); + push_heap(back.begin(), back.end(), greater()); + break; } } - front.pop_back(); - } + + no_draw = false; + } Select(); draw_size = selected.size(); //Preloading now - for(unsigned int i = 0; i < 100; i++) { + for(unsigned int i = 0; i < 1000; i++) { if(!front.size() && !back.size()) break; if((i%2) && front.size()) { pop_heap(front.begin(), front.end()); @@ -155,10 +191,10 @@ void Extraction::Update(NexusMt *_mt) { front.pop_back(); Node::iterator i; for(i = node->out_begin(); i != node->out_end(); i++) { - Link &link = (*i); - for(Link::iterator k = link.begin(); k != link.end(); k++) { - selected.push_back((*k).patch); - } + Link &link = (*i); + for(Link::iterator k = link.begin(); k != link.end(); k++) { + selected.push_back((*k).patch); + } } } else if(back.size()) { pop_heap(back.begin(), back.end(), greater()); @@ -167,17 +203,17 @@ void Extraction::Update(NexusMt *_mt) { back.pop_back(); Node::iterator i; for(i = node->in_begin(); i != node->in_end(); i++) { - Link &link = (*i); - for(Link::iterator k = link.begin(); k != link.end(); k++) { - selected.push_back((*k).patch); - } + Link &link = (*i); + for(Link::iterator k = link.begin(); k != link.end(); k++) { + selected.push_back((*k).patch); + } } } } } float Extraction::GetRefineError(Node *node) { - float maxerror = 0; + float maxerror = -1; Node::iterator i; for(i = node->in_begin(); i != node->in_end(); i++) { Link &link = *i; @@ -190,23 +226,43 @@ float Extraction::GetRefineError(Node *node) { return maxerror; } -bool Extraction::Refine(Node *node) { +bool Extraction::Refine(HeapNode &hnode) { + + Node *node = hnode.node; + //cerr << "Refine node: " << (void *)hnode.node << " err: " << hnode.error << endl; + //recursively refine parent if applicable. Node::iterator i; for(i = node->in_begin(); i != node->in_end(); i++) { Node *parent = (*i).node; - if(!Visited(parent)) - if(!Refine(parent)) - return false; + if(!Visited(parent)) { + //Here i use parent refine error!!! + if(!Refine(HeapNode(parent, hnode.error))) return false; + } } Cost cost; Diff(node, cost); - if(disk_used + cost.disk > disk_max) return false; - if(extr_used + cost.extr > extr_max) return false; - if(draw_used + cost.draw > draw_max) return false; + bool failed = false; + if(disk_used + cost.disk > disk_max) { + //cerr << "Disk failed\n"; + failed = true; + } + if(extr_used + cost.extr > extr_max) { + //cerr << "Extr failed\n"; + failed = true; + } + if(draw_used + cost.draw > draw_max) { + //cerr << "Draw failed\n"; + failed = true; + } + if(failed) { + front.push_back(hnode); + push_heap(front.begin(), front.end()); + return false; + } extr_used += cost.extr; draw_used += cost.draw; disk_used += cost.disk; @@ -225,19 +281,25 @@ bool Extraction::Refine(Node *node) { front.push_back(HeapNode((*i).node, maxerror)); } push_heap(front.begin(), front.end()); + + back.push_back(hnode); + push_heap(back.begin(), back.end(), greater()); return true; } bool Extraction::Coarse(HeapNode &hnode) { + //cerr << "Coarse node: " << (void *)hnode.node << " err: " << hnode.error << endl; Node *node = hnode.node; + //recursively coarse children if applicable. Node::iterator i; for(i = node->out_begin(); i != node->out_end(); i++) { Node *child = (*i).node; float error = GetRefineError(child); HeapNode hchild(child, error); - if(Visited(child)) + if(Visited(child)) { if(!Coarse(hchild)) return false; + } } @@ -308,7 +370,7 @@ void Extraction::Visit(Node *node) { disk_used += cost.disk; for(i = node->out_begin(); i != node->out_end(); i++) { - float maxerror = 0; + float maxerror = -1; Link &link = *i; for(Link::iterator k = link.begin(); k != link.end(); k++) { Entry &entry = (*mt)[(*k).patch]; diff --git a/apps/nexus/extraction.h b/apps/nexus/extraction.h index 5ec5189b..b2dbcc00 100644 --- a/apps/nexus/extraction.h +++ b/apps/nexus/extraction.h @@ -64,7 +64,7 @@ class Extraction { void Update(NexusMt *mt); - protected: + protected: void Select(); void Visit(Node *node); @@ -72,7 +72,7 @@ class Extraction { bool Expand(HeapNode &node); void Diff(Node *node, Cost &cost); - bool Refine(Node *node); + bool Refine(HeapNode &node); bool Coarse(HeapNode &node); void Init(); diff --git a/apps/nexus/history.cpp b/apps/nexus/history.cpp index 25668895..1b368227 100644 --- a/apps/nexus/history.cpp +++ b/apps/nexus/history.cpp @@ -232,9 +232,9 @@ bool History::UpdatesToQuick() { vector::iterator k; for(k = cells.begin(); k != cells.end(); k++) { - Cell cell; - cell.patch = (*k); - tmp_frags.push_back(cell); + Cell cell; + cell.patch = (*k); + tmp_frags.push_back(cell); } //Add the new Frag to the node. diff --git a/apps/nexus/metric.h b/apps/nexus/metric.h index 1ecabe7e..5521d1d2 100644 --- a/apps/nexus/metric.h +++ b/apps/nexus/metric.h @@ -30,9 +30,15 @@ namespace nxs { float dist = (sphere.Center() - frustum.ViewPoint()).Norm() - sphere.Radius(); //float dist = Distance(sphere, frustum.ViewPoint()); if(dist < 0) - return 1e20f; - if(frustum.IsOutside(sphere.Center(), sphere.Radius())) - return -1; + return 1e20f; + + float remote = frustum.Remoteness(sphere.Center(), sphere.Radius()); + if(remote > 0) + return (entry.error/remote)/frustum.Resolution(dist); + + //if(frustum.IsOutside(sphere.Center(), sphere.Radius())) + //return -1; + return entry.error/frustum.Resolution(dist); } }; diff --git a/apps/nexus/nexus.cpp b/apps/nexus/nexus.cpp index 7ae1b8bc..08fa9dd5 100644 --- a/apps/nexus/nexus.cpp +++ b/apps/nexus/nexus.cpp @@ -161,27 +161,10 @@ Patch &Nexus::GetPatch(unsigned int patch, bool flush) { return *(entry.patch); } -Border Nexus::GetBorder(unsigned int patch, bool flush) { +Border &Nexus::GetBorder(unsigned int patch, bool flush) { return borders.GetBorder(patch); } -/*void Nexus::AddBorder(unsigned int patch, Link &link) { - Border border = GetBorder(patch); - - unsigned int pos = border.Size(); - if(pos > 65500) { - cerr << "Exceding border size!!!\n"; - exit(0); - } - if(borders.ResizeBorder(patch, pos+1)) { - border = GetBorder(patch); - } - - assert(border.Available() > pos); - - border[pos] = link; - }*/ - unsigned int Nexus::AddPatch(unsigned int nvert, unsigned int nface, unsigned int nbord) { @@ -206,121 +189,6 @@ unsigned int Nexus::AddPatch(unsigned int nvert, unsigned int nface, return size() - 1; } -/*void Nexus::Unify(float threshold) { - //TODO what if colors or normals or strips? - unsigned int duplicated = 0; - unsigned int degenerate = 0; - - for(unsigned int p = 0; p < size(); p++) { - Entry &entry = operator[](p); - Patch &patch = GetPatch(p); - - unsigned int vcount = 0; - map vertices; - - vector remap; - remap.resize(patch.nv); - - for(unsigned int i = 0; i < patch.nv; i++) { - Point3f &point = patch.Vert(i); - - if(!vertices.count(point)) - vertices[point] = vcount++; - else - duplicated++; - - remap[i] = vertices[point]; - } - assert(vertices.size() <= patch.nv); - if(vertices.size() == patch.nv) //no need to unify - continue; - - vector newvert; - newvert.resize(vertices.size()); - map::iterator k; - for(k = vertices.begin(); k != vertices.end(); k++) { - newvert[(*k).second] = (*k).first; - } - - - vector newface; - //check no degenerate faces get created. - for(unsigned int f = 0; f < entry.nface; f++) { - unsigned short *face = patch.Face(f); - if(face[0] != face[1] && face[1] != face[2] && face[0] != face[2] && - newvert[remap[face[0]]] != newvert[remap[face[1]]] && - newvert[remap[face[0]]] != newvert[remap[face[2]]] && - newvert[remap[face[1]]] != newvert[remap[face[2]]]) { - newface.push_back(remap[face[0]]); - newface.push_back(remap[face[1]]); - newface.push_back(remap[face[2]]); - } else { - degenerate++; - } - } - - //rewrite patch now. - entry.nvert = newvert.size(); - entry.nface = newface.size()/3; - patch.Init(signature, entry.nvert, entry.nface); - - memcpy(patch.VertBegin(), &(newvert[0]), entry.nvert*sizeof(Point3f)); - memcpy(patch.FaceBegin(), &(newface[0]), entry.nface*3*sizeof(short)); - - //testiamo il tutto... TODO remove this of course - for(unsigned int i =0; i < patch.nf; i++) { - for(int k =0 ; k < 3; k++) - if(patch.Face(i)[k] >= patch.nv) { - cerr <<" Unify has problems\n"; - exit(0); - } - } - - //fix patch borders now - set close; //bordering pathes - Border border = GetBorder(p); - for(unsigned int b = 0; b < border.Size(); b++) { - if(border[b].IsNull()) continue; - close.insert(border[b].end_patch); - border[b].start_vert = remap[border[b].start_vert]; - } - - set::iterator c; - for(c = close.begin(); c != close.end(); c++) { - Border bord = GetBorder(*c); - for(unsigned int b = 0; b < bord.Size(); b++) { - if(bord[b].IsNull()) continue; - if(bord[b].end_patch == p) { - bord[b].end_vert = remap[bord[b].end_vert]; - } - } - } - } - //better to compact directly borders than setting them null. - //finally: there may be duplicated borders - for(unsigned int p = 0; p < size(); p++) { - Border border = GetBorder(p); - set links; - for(unsigned int b = 0; b < border.Size(); b++) { - Link &link = border[b]; - assert(!link.IsNull()); - //if(border[b].IsNull()) continue; - links.insert(link); - } - int count = 0; - for(set::iterator k = links.begin(); k != links.end(); k++) - border[count++] = *k; - - borders[p].used = links.size(); - } - - totvert -= duplicated; - if(duplicated) - cerr << "Found " << duplicated << " duplicated vertices" << endl; - if(degenerate) - cerr << "Found " << degenerate << " degenerate face while unmifying\n"; - }*/ - Patch *Nexus::LoadPatch(unsigned int idx) { assert(idx < size()); Entry &entry = operator[](idx); diff --git a/apps/nexus/nexus.h b/apps/nexus/nexus.h index ada69328..274347a1 100644 --- a/apps/nexus/nexus.h +++ b/apps/nexus/nexus.h @@ -74,7 +74,7 @@ class Nexus: public IndexFile { unsigned int AddPatch(unsigned int nv, unsigned int nf, unsigned int nb); Patch &GetPatch(unsigned int patch, bool flush = true); - Border GetBorder(unsigned int patch, bool flush = true); + Border &GetBorder(unsigned int patch, bool flush = true); unsigned int &MaxRam() { return ram_max; } // void AddBorder(unsigned int patch, Link &link); diff --git a/apps/nexus/nexusview.cpp b/apps/nexus/nexusview.cpp index 52f1c9c2..16c06850 100644 --- a/apps/nexus/nexusview.cpp +++ b/apps/nexus/nexusview.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.29 2005/01/17 17:35:47 ponchio +Small changes and adding realtime extr. + Revision 1.28 2005/01/14 15:25:29 ponchio Revolution. @@ -425,7 +428,7 @@ int main(int argc, char *argv[]) { /* if(show_borders) { for(unsigned int i = 0; i < cells.size(); i++) { - Border border = nexus.GetBorder(cells[i]); + Border &border = nexus.GetBorder(cells[i]); Patch &patch = nexus.GetPatch(cells[i]); glPointSize(4); glColor3f(1.0f, 1.0f, 1.0f); diff --git a/apps/nexus/nxsalgo.cpp b/apps/nexus/nxsalgo.cpp index cef9dc07..c0fb7814 100644 --- a/apps/nexus/nxsalgo.cpp +++ b/apps/nexus/nxsalgo.cpp @@ -39,7 +39,7 @@ void nxs::ComputeNormals(Nexus &nexus) { //TODO optimize! it is not necessary to read all the borders. for(unsigned int p = 0; p < nexus.size(); p++) { - Border border = nexus.GetBorder(p); + Border &border = nexus.GetBorder(p); tmpb_start.push_back(tmpb_offset); tmpb_offset += border.Size(); } @@ -106,7 +106,7 @@ void nxs::ComputeNormals(Nexus &nexus) { } - Border border = nexus.GetBorder(p); + Border &border = nexus.GetBorder(p); map > bnorm; @@ -125,7 +125,7 @@ void nxs::ComputeNormals(Nexus &nexus) { map >::iterator k; for(k = bnorm.begin(); k != bnorm.end(); k++) { unsigned int patch = (*k).first; - Border border = nexus.GetBorder(patch); + Border &border = nexus.GetBorder(patch); unsigned int offset = tmpb_start[patch]; for(unsigned int i = 0; i < border.Size(); i++) { Link &link = border[i]; @@ -151,7 +151,7 @@ void nxs::ComputeNormals(Nexus &nexus) { set::iterator k; for(k = close.begin(); k != close.end(); k++) { - Border remote = nexus.GetBorder(*k); + Border &remote = nexus.GetBorder(*k); unsigned int off = tmpb_start[*k]; for(unsigned int i = 0; i < remote.Size(); i++) { @@ -172,7 +172,7 @@ void nxs::ComputeNormals(Nexus &nexus) { for(unsigned int p = 0; p < nexus.size(); p++) { report.Step(p); Patch &patch = nexus.GetPatch(p); - Border border = nexus.GetBorder(p); + Border &border = nexus.GetBorder(p); for(unsigned int i = 0; i < border.Size(); i++) { Link &link = border[i]; @@ -357,7 +357,7 @@ void nxs::Unify(Nexus &nexus, float threshold) { //fix patch borders now set close; //bordering pathes - Border border = nexus.GetBorder(p); + Border &border = nexus.GetBorder(p); for(unsigned int b = 0; b < border.Size(); b++) { if(border[b].IsNull()) continue; close.insert(border[b].end_patch); @@ -366,7 +366,7 @@ void nxs::Unify(Nexus &nexus, float threshold) { set::iterator c; for(c = close.begin(); c != close.end(); c++) { - Border bord = nexus.GetBorder(*c); + Border &bord = nexus.GetBorder(*c); for(unsigned int b = 0; b < bord.Size(); b++) { if(bord[b].IsNull()) continue; if(bord[b].end_patch == p) { @@ -378,7 +378,7 @@ void nxs::Unify(Nexus &nexus, float threshold) { //better to compact directly borders than setting them null. //finally: there may be duplicated borders for(unsigned int p = 0; p < nexus.size(); p++) { - Border border = nexus.GetBorder(p); + Border &border = nexus.GetBorder(p); set links; for(unsigned int b = 0; b < border.Size(); b++) { Link &link = border[b]; diff --git a/apps/nexus/nxsbuilder.cpp b/apps/nexus/nxsbuilder.cpp index f6f775c0..b991fb60 100644 --- a/apps/nexus/nxsbuilder.cpp +++ b/apps/nexus/nxsbuilder.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.13 2005/01/17 17:35:48 ponchio +Small changes and adding realtime extr. + Revision 1.12 2005/01/14 15:25:29 ponchio Revolution. @@ -170,8 +173,8 @@ void FirstStep(const string &crudefile, const string &output, BlockIndex face_index; Remap(vchain, baricenters, face_remap, face_index, - patch_size, patch_threshold, 65000, scaling, - optimization_steps); + patch_size, patch_threshold, 65000, scaling, + optimization_steps); if(!vchain.Save(output + ".vchain")) { cerr << "Could not save file: " << output << ".vchain\n"; @@ -221,7 +224,6 @@ void SecondStep(const string &crudefile, const string &output) { for(unsigned int i = 0; i < face_remap.Size(); i++) { unsigned int patch = face_remap[i]; assert(patch < face_index.size()); - assert(patch >= 0); int64 offset = face_index[patch].offset + done[patch]++; sorted[offset] = crude.GetFace(i); } @@ -231,16 +233,6 @@ void SecondStep(const string &crudefile, const string &output) { assert(done[i] == face_index[i].size); #endif - /*#ifndef NDEBUG - //test: - for(unsigned int i = 0; i < sorted.Size(); i++) { - Crude::Face face = sorted[i]; - assert(face[0] < crude.Vertices()); - assert(face[1] < crude.Vertices()); - assert(face[2] < crude.Vertices()); - } - #endif*/ - //once sorted crude.Close(); sorted.Close(); @@ -318,16 +310,16 @@ void ThirdStep(const string &crudefile, const string &output, // Crude::Face face = crude.GetFace(i); Crude::Face face = sorted[i]; if(face[0] == face[1] || face[1] == face[2] || face[0] == face[2]) - continue; //degenerate + continue; //degenerate for(int j = 0; j < 3; j++) { - assert(face[j] < crude.Vertices()); - if(!vremap.count(face[j])) { - Point3f &v = crude.vert[face[j]]; - vertices.push_back(v); - vremap[face[j]] = vcount++; - } - faces.push_back(vremap[face[j]]); - fcount++; + assert(face[j] < crude.Vertices()); + if(!vremap.count(face[j])) { + Point3f &v = crude.vert[face[j]]; + vertices.push_back(v); + vremap[face[j]] = vcount++; + } + faces.push_back(vremap[face[j]]); + fcount++; } } assert(vcount == vertices.size()); @@ -364,7 +356,7 @@ void ThirdStep(const string &crudefile, const string &output, //saving vert_remap int64 vroffset = vert_remap.Size(); vert_index.push_back(BlockEntry(vroffset, vcount)); - vert_remap.Resize(vroffset + vcount); + vert_remap.Resize(vroffset + vcount); map::iterator r; for(r = vremap.begin(); r != vremap.end(); r++) { @@ -372,7 +364,10 @@ void ThirdStep(const string &crudefile, const string &output, assert(vroffset + (*r).second < vert_remap.Size()); vert_remap[vroffset + (*r).second] = (*r).first; } - } + if(vcount < 100) { + cerr << "Small patch: " << vcount << "\n"; + } + } //we can now update bounding sphere. for(unsigned int i = 0; i < nexus.size(); i++) @@ -409,10 +404,11 @@ void FourthStep(const string &crudefile, const string &output, //TODO Clear borders in case of failure! VFile vert_remap; - if(!vert_remap.Load(crudefile + ".rvm", true)) { + if(!vert_remap.Load(output + ".rvm", true)) { cerr << "Could not load: " << crudefile << ".rvm\n"; exit(0); } + cerr << "Vert_remap.size: " << vert_remap.Size() << endl; BlockIndex vert_index; if(!vert_index.Load(output + ".rvi")) { @@ -421,7 +417,7 @@ void FourthStep(const string &crudefile, const string &output, } Report report(nexus.size()); - for(int start = 0; start < nexus.size(); start++) { + for(int start = 0; start < nexus.size(); start++) { report.Step(start); Entry &s_entry = nexus[start]; @@ -432,6 +428,14 @@ void FourthStep(const string &crudefile, const string &output, map vremap; #endif for(unsigned int i = 0; i < vert_index[start].size; i++) { +//#ifndef NDEBUG + if(vert_index[start].offset + i >= vert_remap.Size()) { + cerr << "Ahi Ahi start: " << start << endl; + cerr << "offset: " << vert_index[start].offset << endl; + cerr << "size: " << vert_index[start].size << endl; + exit(0); + } +//#endif unsigned int global = vert_remap[vert_index[start].offset + i]; vremap[global] = i; } @@ -446,21 +450,30 @@ void FourthStep(const string &crudefile, const string &output, continue; } - for(unsigned int i = 0; i < vert_index[end].size; i++) { - unsigned int global = vert_remap[vert_index[end].offset + i]; - if(vremap.count(global)) { - Link link; - link.start_vert = vremap[global]; - link.end_vert = i; - link.end_patch = end; - links.push_back(link); - } + for(unsigned int i = 0; i < vert_index[end].size; i++) { + +//#ifndef NDEBUG + if(vert_index[end].offset + i >= vert_remap.Size()) { + cerr << "aaa Ahi Ahi start: " << end << endl; + cerr << "offset: " << vert_index[end].offset << endl; + cerr << "size: " << vert_index[end].size << endl; + exit(0); + } +//#endif + unsigned int global = vert_remap[vert_index[end].offset + i]; + if(vremap.count(global)) { + Link link; + link.start_vert = vremap[global]; + link.end_vert = i; + link.end_patch = end; + links.push_back(link); + } } } - //TODO Horribili visu (interfaccia di cacca!) + + Border &border = nexus.GetBorder(start); nexus.borders.ResizeBorder(start, 3 * links.size()); - nexus.borders[start].used = links.size(); - Border border = nexus.GetBorder(start); + border.used = links.size(); memcpy(&(border[0]), &*links.begin(), links.size() * sizeof(Link)); } } @@ -699,7 +712,7 @@ void BuildFragment(Nexus &nexus, VPartition &part, nxs.patch = *f; Patch &patch = nexus.GetPatch(*f); - Border border = nexus.GetBorder(*f); + Border &border = nexus.GetBorder(*f); for(unsigned int k = 0; k < patch.nf; k++) { assert(patch.Face(k)[0] != patch.Face(k)[1]); @@ -825,7 +838,7 @@ void SaveFragment(Nexus &nexus, VChain &chain, newlinks[link.end_patch].insert(up); assert(link.end_patch != patch_idx); - Border cborder = nexus.GetBorder(link.end_patch); + Border &cborder = nexus.GetBorder(link.end_patch); for(unsigned int k = 0; k < cborder.Size(); k++) { //cerr << "Cborder.size: " << cborder.Size() << endl; //cerr << "K: " << k << endl; @@ -865,11 +878,9 @@ void SaveFragment(Nexus &nexus, VChain &chain, set::iterator l; unsigned int patch = (*n).first; set &links = (*n).second; - Border border = nexus.GetBorder(patch); + Border &border = nexus.GetBorder(patch); unsigned int bstart = border.Size(); - - if(nexus.borders.ResizeBorder(patch, border.Size() + links.size())) - border = nexus.GetBorder(patch); + nexus.borders.ResizeBorder(patch, border.Size() + links.size()); for(l = links.begin(); l != links.end(); l++) { Link link = *l; border[bstart++] = link; diff --git a/apps/nexus/nxsedit.cpp b/apps/nexus/nxsedit.cpp index 4e20db5d..afbc0755 100644 --- a/apps/nexus/nxsedit.cpp +++ b/apps/nexus/nxsedit.cpp @@ -51,6 +51,7 @@ int main(int argc, char *argv[]) { string output; string plysource; bool info = false; + bool verbose = false; unsigned int ram_size = 128000000; unsigned int chunk_size = 0; @@ -76,9 +77,10 @@ int main(int argc, char *argv[]) { float qtexture = 0; int option; - while((option = getopt(argc, argv, "io:a:r:zxv:n:k:t:b:c:")) != EOF) { + while((option = getopt(argc, argv, "ilo:a:r:zxv:n:k:t:b:c:")) != EOF) { switch(option) { case 'i': info = true; break; + case 'l': verbose = true; break; case 'o': output = optarg; break; case 'a': { if(strstr(optarg, "strip")) { @@ -195,6 +197,7 @@ int main(int argc, char *argv[]) { if(optind != argc - 1) { cerr << "Usage: " << argv[0] << " [options]\n" << " -i : display some info about nexus file\n" + << " -l : list nodes\n" << " -o : output filename (default is adding 00 to nexus)\n" << " -a : Add [colors|normals|strip|textures|data|borders]\n" << " -r : As add...\n" @@ -254,7 +257,7 @@ int main(int argc, char *argv[]) { if(info) { - cerr << "Nexus file: " << input << "\n\n" + cout << "Nexus file: " << input << "\n\n" << "\n\tCompressed: " << nexus.IsCompressed() << "\n\tStripped: " << (int)((nexus.signature&NXS_STRIP) !=0) << "\n\tColor : " << (int)((nexus.signature&NXS_COLORS) !=0) @@ -270,7 +273,15 @@ int main(int argc, char *argv[]) { << nexus.sphere.Center()[2] << " R: " << nexus.sphere.Radius() << "\n\tChunk size " << nexus.chunk_size << endl; - + + if(verbose) { + for(unsigned int i = 0; i < nexus.size(); i++) { + Entry &entry = nexus[i]; + cout << i << " -> nv: " << entry.nvert << " nf: " << entry.nface + << " error: " << entry.error << " disk_size: " << entry.disk_size << endl; + } + cout << endl; + } } //determine if we must proceed: @@ -331,7 +342,7 @@ int main(int argc, char *argv[]) { report.Step(patch); Entry &src_entry = nexus[patch]; Patch &src_patch = nexus.GetPatch(patch); - Border src_border = nexus.GetBorder(patch); + Border &src_border = nexus.GetBorder(patch); vector strip; @@ -397,7 +408,7 @@ int main(int argc, char *argv[]) { assert(link.end_patch < nexus.index.size()); }*/ out.borders.ResizeBorder(patch, src_border.Size()); - Border dst_border = out.GetBorder(patch); + Border &dst_border = out.GetBorder(patch); memcpy(dst_border.Start(), src_border.Start(), src_border.Size() * sizeof(Link)); } diff --git a/apps/nexus/nxstest.cpp b/apps/nexus/nxstest.cpp index 4ed759f7..bdded76a 100644 --- a/apps/nexus/nxstest.cpp +++ b/apps/nexus/nxstest.cpp @@ -53,7 +53,7 @@ int main(int argc, char *argv[]) { for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) { PatchInfo &info = nexus.index[patchid]; - Border border = nexus.GetBorder(patchid); + Border &border = nexus.GetBorder(patchid); for(unsigned int i = 0; i < border.Size(); i++) { Link &link = border[i]; if(link.start_vert == 0 && link.end_vert == 0 && link.end_patch == 0) { @@ -81,13 +81,13 @@ int main(int argc, char *argv[]) { cerr << "Reciprocity borders test\n"; for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) { PatchInfo &info = nexus.index[patchid]; - Border border = nexus.GetBorder(patchid); + Border &border = nexus.GetBorder(patchid); vector links; links.resize(border.Size()); memcpy(&*links.begin(),&(border[0]),links.size() * sizeof(Link)); for(unsigned int i = 0; i < links.size(); i++) { Link &link = links[i]; - Border rborder = nexus.GetBorder(link.end_patch); + Border &rborder = nexus.GetBorder(link.end_patch, false); bool found = false; for(unsigned int k = 0; k < rborder.Size(); k++) { diff --git a/apps/nexus/preload.cpp b/apps/nexus/preload.cpp index 88df625c..c4c068ee 100644 --- a/apps/nexus/preload.cpp +++ b/apps/nexus/preload.cpp @@ -9,9 +9,10 @@ using namespace nxs; while(!get_signaled()) { lock.enter(); while(!queue.size()) { - lock.leave(); - pt::psleep(10); - lock.enter(); + //cerr << "Acc nothing to preload!\n"; + lock.leave(); + pt::psleep(10); + lock.enter(); } //TODO check we are not loading too much memory! assert(queue.size()); diff --git a/apps/nexus/remapping.cpp b/apps/nexus/remapping.cpp index ddcd9fa5..99c6ca81 100644 --- a/apps/nexus/remapping.cpp +++ b/apps/nexus/remapping.cpp @@ -45,27 +45,22 @@ void nxs::Remap(VChain &chain, float scaling, int steps) { - VPartition *finepart = new VPartition; - // finepart.Init(); + VPartition *finepart = new VPartition; chain.push_back(finepart); BuildPartition(*finepart, points, target_size, min_size, max_size, steps); - - VPartition *coarsepart = new VPartition; - // coarsepart.Init(); + VPartition *coarsepart = new VPartition; chain.push_back(coarsepart); BuildPartition(*coarsepart, points, (int)(target_size/scaling), min_size, max_size, steps); - - - cerr << "Fine size: " << finepart->size() << endl; cerr << "Coarse size: " << coarsepart->size() << endl; - typedef map, unsigned int> FragIndex; +// typedef map, unsigned int> FragIndex; + typedef map > FragIndex; FragIndex patches; unsigned int totpatches = 0; @@ -79,12 +74,11 @@ void nxs::Remap(VChain &chain, unsigned int coarse = coarsepart->Locate(bari); unsigned int patch; - - if(!patches.count(make_pair(coarse, fine))) { + if(!patches.count(coarse) || !patches[coarse].count(fine)) { patch = totpatches; - patches[make_pair(coarse, fine)] = totpatches++; + patches[coarse][fine] = totpatches++; } else - patch = patches[make_pair(coarse, fine)]; + patch = patches[coarse][fine]; remap[i] = patch; @@ -93,40 +87,96 @@ void nxs::Remap(VChain &chain, count[patch]++; } - cerr << "Prune faces...\n"; - - //prune faces (now only 0 faces); - unsigned int new_totpatches = 0; - vector patch_remap; for(unsigned int i = 0; i < totpatches; i++) { - //if below threshold (and can join faces) - // if(count[i] < min_size) - if(count[i] == 0) - patch_remap.push_back(-1); - else - patch_remap.push_back(new_totpatches++); - if(count[i] > 32000) { //TODO do something to reduce patch size... :P cerr << "Found a patch too big... sorry\n"; exit(0); } } - - cerr << "BUilding fragmenbts\n"; + unsigned int mean = 0; + for(unsigned int i = 0; i < count.size(); i++) + mean += count[i]; + mean /= count.size(); + + min_size /= 4; + cerr << "Pruning small patches... < " << min_size << " mean: " << mean << endl; + + + //prune small patches + + vector patch_map; + patch_map.resize(totpatches); + for(unsigned int i = 0; i < totpatches; i++) + patch_map[i] = i; + + for(FragIndex::iterator s = patches.begin(); s != patches.end(); s++) { + map &fines = (*s).second; + + while(1) { + if(fines.size() <= 1) break; + unsigned int inf_fine = 0xffffffff; + unsigned int inf_count, min_count; + unsigned int min_fine = 0xffffffff; + unsigned int min_patch, inf_patch; + map::iterator t; + for(t = fines.begin(); t != fines.end(); t++) { + unsigned int c = count[(*t).second]; + if(inf_fine == 0xffffffff || c < inf_count) { + if(inf_fine != 0xffffffff) { + min_fine = inf_fine; + min_count = inf_count; + min_patch = inf_patch; + } + inf_fine = (*t).first; + inf_count = c; + inf_patch = (*t).second; + } else if(min_fine == 0xffffffff || c < min_count) { + min_fine = (*t).first; + min_count = c; + min_patch = (*t).second; + } + } + if(inf_count >= min_size || + inf_count + min_count > max_size) break; + + count[min_patch] += count[inf_patch]; + patch_map[inf_patch] = min_patch; + fines.erase(inf_fine); + } + } + for(unsigned int i = 0; i < totpatches; i++) + while(patch_map[patch_map[i]] != patch_map[i]) + patch_map[i] = patch_map[patch_map[i]]; + + //now we remap remaining patches into 0 - n. + unsigned int new_totpatches = 0; + vector patch_remap; + patch_remap.resize(totpatches, -1); + for(unsigned int i = 0; i < totpatches; i++) { + unsigned int p = patch_map[i]; + if(patch_remap[p] == -1) + patch_remap[p] = new_totpatches++; + patch_remap[i] = patch_remap[p]; + } + + cerr << "Building fragments\n"; //building fragments - FragIndex::iterator f; - for(f = patches.begin(); f != patches.end(); f++) { - unsigned int coarse = (*f).first.first; - unsigned int fine = (*f).first.second; - unsigned int oldpatch = (*f).second; - assert(oldpatch < patch_remap.size()); - unsigned int patch = patch_remap[oldpatch]; - if(patch != -1) //not deleted... - chain.oldfragments[coarse].insert(patch); - } + for(FragIndex::iterator s = patches.begin(); s != patches.end(); s++) { + unsigned int coarse = (*s).first; + map &fines = (*s).second; + map::iterator t; + for(t = fines.begin(); t != fines.end(); t++) { + unsigned int fine = (*t).first; + unsigned int oldpatch = (*t).second; + assert(oldpatch < patch_remap.size()); + unsigned int patch = patch_remap[oldpatch]; + if(patch != -1) //not deleted... + chain.oldfragments[coarse].insert(patch); + } + } cerr << "remapping faces again\n"; //remapping faces @@ -428,92 +478,4 @@ bool nxs::Optimize(VPartition &part, } part.Init(); return true; - // for(unsigned int i = 0; i < part.size(); i++) { - // if(counts[i] > max_size || counts[i] > max_size) { - // failed++; - // } else { - // } - // } - //PREPHASE: - /* if(join) { - - - // float bigthresh = 1.2f; - // float smallthresh = 0.5f; - - float bigthresh = 10.0f; - float smallthresh = 0.1f; - - unsigned int failed = 0; - vector seeds; - vector mark; - mark.resize(part.size(), false); - - //first pass we check only big ones - for(unsigned int i = 0; i < part.size(); i++) { - if(counts[i] > max_size || counts[i] > bigthresh * target_size) { - failed++; - float radius; - - if(part.size() == 1) - radius = 0.00001; - else - radius = part.Radius(i); - - if(radius == 0) { - cerr << "Radius zero???\n"; - exit(0); - } - radius /= 4; - seeds.push_back(centroids[i] + Point3f(1, -1, 1) * radius); - seeds.push_back(centroids[i] + Point3f(-1, 1, 1) * radius); - seeds.push_back(centroids[i] + Point3f(-1, -1, -1) * radius); - seeds.push_back(centroids[i] + Point3f(1, 1, -1) * radius); - mark[i] = true; - } - } - if(failed > 0) - cerr << "Found " << failed << " patches too big.\n"; - - if(join) { - for(unsigned int i = 0; i < part.size(); i++) { - if(mark[i]) continue; - if(counts[i] >= min_size && counts[i] >= smallthresh * target_size) continue; - - failed++; - int best = GetBest(part, i, mark, counts); - if(best < 0) { - cerr << "Best not found! while looking for: " << i << "\n"; - 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(counts[i] == 0) continue; - if(join) { - // if(counts[i] < min_size) { - // cerr << "Could not fix: " << i << endl; - // } else { - part[i] = centroids[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) { - cerr << "OOOPS i accidentally deleted all seeds... backup :P\n"; - part.push_back(Point3f(0,0,0)); - } - part.Init(); - return failed == 0;*/ } diff --git a/apps/nexus/vpartition.cpp b/apps/nexus/vpartition.cpp index 50ae2d9a..4668d4b3 100644 --- a/apps/nexus/vpartition.cpp +++ b/apps/nexus/vpartition.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.2 2004/12/04 13:24:27 ponchio +Fixed a couple of memory leak... + Revision 1.1 2004/11/30 22:50:30 ponchio Level 0. @@ -64,6 +67,7 @@ void VPartition::Closest(const vcg::Point3f &p, unsigned int nsize, point[0] = p[0]; point[1] = p[1]; point[2] = p[2]; + if(nsize > size()) nsize = size(); nears.resize(nsize); dist.resize(nsize);