From 975ec6ae0452e0ba93a4f71afdf6ce435446a4ae Mon Sep 17 00:00:00 2001 From: ponchio Date: Fri, 14 Jan 2005 15:25:29 +0000 Subject: [PATCH] Revolution. --- apps/nexus/borderserver.cpp | 142 ++++-- apps/nexus/borderserver.h | 48 +- apps/nexus/lrupserver.h | 12 +- apps/nexus/mfile.cpp | 33 +- apps/nexus/mfile.h | 5 +- apps/nexus/nexus.cpp | 341 ++++++++----- apps/nexus/nexus.h | 99 ++-- apps/nexus/nexus.html | 84 +++- apps/nexus/nexusbase.h | 6 +- apps/nexus/nexusmt.cpp | 977 +++++++++++++++++++++++------------- apps/nexus/nexusmt.h | 242 ++++----- apps/nexus/nexusview.cpp | 146 +++--- apps/nexus/nxsalgo.cpp | 11 +- apps/nexus/nxsbuilder.cpp | 71 +-- apps/nexus/nxsedit.cpp | 33 +- apps/nexus/pserver.cpp | 194 ++++--- apps/nexus/pserver.h | 112 +++-- apps/nexus/remapping.cpp | 14 +- apps/nexus/vfile.h | 5 +- apps/nexus/watch.h | 8 + 20 files changed, 1588 insertions(+), 995 deletions(-) diff --git a/apps/nexus/borderserver.cpp b/apps/nexus/borderserver.cpp index 2a3ac079..469d3e71 100644 --- a/apps/nexus/borderserver.cpp +++ b/apps/nexus/borderserver.cpp @@ -4,61 +4,131 @@ using namespace std; using namespace nxs; +bool BorderServer::Create(const string &file) { + ram_used = 0; + 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); +} + +void BorderServer::Close() { + if(!Opened()) return; + Flush(); + IndexFile::Close(); +} + +void BorderServer::Flush() { + std::map::iterator>::iterator i; + for(i = index.begin(); i != index.end(); i++) { + unsigned int patch = (*i).first; + FlushBorder(patch); + } + pqueue.clear(); + index.clear(); +} + void BorderServer::AddBorder(unsigned short nbord, unsigned int used) { BorderEntry entry; - entry.border_start = Size(); - entry.border_size = nbord; - entry.border_used = used; - borders.push_back(entry); - Resize(entry.border_start + nbord); + assert((Length() % sizeof(Link)) == 0); + + entry.start = Length()/ sizeof(Link); + entry.size = nbord; + entry.used = used; + entry.links = NULL; + push_back(entry); + Redim(entry.start * sizeof(Link) + nbord * sizeof(Link)); } Border BorderServer::GetBorder(unsigned int border, bool flush) { - assert(border < borders.size()); - BorderEntry &entry = borders[border]; - Link *start = GetRegion(entry.border_start, entry.border_size, flush); - return Border(start, entry.border_used, entry.border_size); + BorderEntry &entry = operator[](border); + if(index.count(border)) { + assert(entry.links); + list::iterator &i = index[border]; + pqueue.erase(i); + pqueue.push_front(border); + + } else { + while(flush && ram_used > ram_max) { + unsigned int to_flush = pqueue.back(); + pqueue.pop_back(); + index.erase(to_flush); + FlushBorder(to_flush); + } + assert(!entry.links); + entry.links = GetRegion(entry.start, entry.size); + pqueue.push_front(border); + list::iterator i = pqueue.begin(); + index[border] = i; + ram_used += entry.size; + } + return Border(entry.links, entry.used, entry.size); } bool BorderServer::ResizeBorder(unsigned int border, unsigned int nbord) { assert(nbord < 65500); - assert(border < borders.size()); - BorderEntry &entry = borders[border]; - if(nbord > entry.border_size) { + assert(border < size()); + BorderEntry &entry = operator[](border); + if(nbord > entry.size) { int capacity = nbord; - if(capacity < entry.border_size*2) - capacity = entry.border_size * 2; + if(capacity < entry.size*2) + capacity = entry.size * 2; if(capacity > 65500) capacity = 65500; - unsigned int newstart = Size(); - Resize(newstart + capacity); - if(entry.border_used > 0) { - Link *src = GetRegion(entry.border_start, entry.border_size); - Link *dst = GetRegion(newstart, capacity, false); - memcpy(dst, src, entry.border_used * sizeof(Link)); + unsigned int newstart = Length()/sizeof(Link); + Redim((newstart + capacity) * sizeof(Link)); + if(entry.used > 0) { + Link *src = GetRegion(entry.start, entry.size); + Link *dst = GetRegion(newstart, capacity); + memcpy(dst, src, entry.used * sizeof(Link)); } - entry.border_start = newstart; - entry.border_size = capacity; - entry.border_used = nbord; + entry.start = newstart; + entry.size = capacity; + entry.used = nbord; return true; } - entry.border_used = nbord; + entry.used = nbord; return false; } -bool BorderServer::ReadEntries(FILE *fp) { - unsigned int n; - fread(&n, 1, sizeof(int), fp); - borders.resize(n); - fread(&*borders.begin(), n, sizeof(BorderEntry), fp); +void BorderServer::FlushBorder(unsigned int border) { + BorderEntry &entry = operator[](border); + assert(entry.links); + if(!MFile::IsReadOnly()) { //write back patch + MFile::SetPosition((int64)entry.start * sizeof(Link)); + MFile::WriteBuffer(entry.links, entry.used * sizeof(Link)); + } + + delete [](entry.links); + entry.links = NULL; + ram_used -= entry.size; +} + +Link *BorderServer::GetRegion(unsigned int start, unsigned int size) { + SetPosition(start * sizeof(Link)); + Link *buf = new Link[size]; + assert(buf); + ReadBuffer(buf, size * sizeof(Link)); + return buf; +} + +bool BorderServer::LoadHeader() { + unsigned int magic; + ReadBuffer(&magic, sizeof(unsigned int)); + if(magic != 0x3042584e) { //NXB0 + cerr << "Invalid magic. Not a nxs file\n"; + return false; + } + ReadBuffer(&offset, sizeof(int64)); + cerr << "Offset: " << offset << endl; return true; } -bool BorderServer::WriteEntries(FILE *fp) { - unsigned int n = borders.size(); - fwrite(&n, 1, sizeof(int), fp); - fwrite(&*borders.begin(), n, sizeof(BorderEntry), fp); - return true; +void BorderServer::SaveHeader() { + unsigned int magic = 0x3042584e; // NXB0 + WriteBuffer(&magic, sizeof(unsigned int)); + WriteBuffer(&offset, sizeof(int64)); } - - diff --git a/apps/nexus/borderserver.h b/apps/nexus/borderserver.h index 36faabb1..2d2001d4 100644 --- a/apps/nexus/borderserver.h +++ b/apps/nexus/borderserver.h @@ -1,40 +1,58 @@ #ifndef NXS_BORDERSERVER_H #define NXS_BORDERSERVER_H -#include "vfile.h" +#include +#include + +#include "index_file.h" #include "border.h" -#include + + +/*nell'header ci sta scritto solo: + spazio riservato: 2 * sizeof(Link); + magic: nxb0 (4 bytes) + offset: (int64) */ namespace nxs { struct BorderEntry { - unsigned int border_start; //granuralita' Link - unsigned short border_size; //in Links - unsigned short border_used; //in Links + unsigned int start; //granuralita' Link + unsigned short size; //in Links + unsigned short used; //in Links + Link *links; }; -class BorderServer: public VFile { +class BorderServer: public IndexFile { public: + BorderServer(): ram_max(1000000), ram_used(0) {} + ~BorderServer() { Close(); } + bool Create(const std::string &file); + bool Load(const std::string &file, bool readonly = true); + 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); - bool ReadEntries(FILE *fp); - bool WriteEntries(FILE *fp); - unsigned int BorderSize(unsigned int i) { - return borders[i].border_used; + return operator[](i).used; } unsigned int BorderCapacity(unsigned int i) { - return borders[i].border_size; + return operator[](i).size; } - - + protected: + unsigned int ram_max; + unsigned int ram_used; + std::list pqueue; + std::map::iterator> index; + bool LoadHeader(); + void SaveHeader(); - std::vector borders; - + void FlushBorder(unsigned int border); + Link *GetRegion(unsigned int start, unsigned int size); //size in links. }; } diff --git a/apps/nexus/lrupserver.h b/apps/nexus/lrupserver.h index ca916668..3ffaf348 100644 --- a/apps/nexus/lrupserver.h +++ b/apps/nexus/lrupserver.h @@ -20,7 +20,7 @@ class LruPServer: public PServer { Flush(); } - Patch &Lookup(unsigned int patch, unsigned short nv, unsigned short nf) { + Patch &Lookup(unsigned int patch) { if(index.count(patch)) { Items::iterator &i = index[patch]; Item item = *i; @@ -32,12 +32,12 @@ class LruPServer: public PServer { while(ram_used > ram_max) { Item item = items.back(); index.erase(item.first); - FlushPatch(item.first, item.second); + FlushPatch(item.first); items.pop_back(); } Item item; item.first = patch; - item.second = LoadPatch(patch, nv, nf); + item.second = LoadPatch(patch); items.push_front(item); Items::iterator i = items.begin(); index[patch] = i; @@ -52,10 +52,10 @@ class LruPServer: public PServer { std::map::iterator i; for(i = index.begin(); i != index.end(); i++) { Item &item = *((*i).second); - FlushPatch((*i).first, item.second); + FlushPatch((*i).first); } - for(int k = 0; k < entries.size(); k++) - entries[k].patch = NULL; + for(int k = 0; k < size(); k++) + operator[](k).patch = NULL; items.clear(); index.clear(); diff --git a/apps/nexus/mfile.cpp b/apps/nexus/mfile.cpp index 17bc4515..0945ce78 100644 --- a/apps/nexus/mfile.cpp +++ b/apps/nexus/mfile.cpp @@ -8,7 +8,7 @@ using namespace nxs; bool MFile::Create(const string &fname, unsigned int mxs) { Close(); filename = fname; - size = 0; + _size = 0; readonly = false; assert(mxs <= MFILE_MAX_SIZE); max_size = mxs; @@ -20,7 +20,7 @@ bool MFile::Load(const string &fname, bool ronly) { filename = fname; readonly = ronly; max_size = MFILE_MAX_SIZE; - size = 0; + _size = 0; while(1) { string name = Name(files.size()); @@ -30,11 +30,11 @@ bool MFile::Load(const string &fname, bool ronly) { files.pop_back(); break; } - size += file->Length(); + _size += file->Length(); } if(files.size() == 0) return false; if(files.size() == 1) { - assert(size <= max_size); + assert(_size <= max_size); } else { //SANITY TEST for(unsigned int i = 0; i < files.size() -2; i++) { @@ -61,28 +61,29 @@ void MFile::Delete() { void MFile::Redim(int64 sz) { assert(!readonly); - if(sz > size) { + if(sz > _size) { unsigned int totfile = (unsigned int)(sz/max_size); //TODO test rhis!!!! while(files.size() <= totfile) { RedimLast(max_size); - assert(size == (int64)max_size * (int64)(files.size())); + assert(_size == (int64)max_size * (int64)(files.size())); AddFile(); } - assert(size <= sz); - assert(sz - size < max_size); - assert(files.back()->Length() + (unsigned int)(sz - size) < max_size); - RedimLast(files.back()->Length() + (unsigned int)(sz - size)); + assert(_size <= sz); + assert(sz - _size < max_size); + assert(files.back()->Length() + (unsigned int)(sz - _size) < max_size); + RedimLast(files.back()->Length() + (unsigned int)(sz - _size)); } else { - while(size - files.back()->Length() > sz) + while(_size - files.back()->Length() > sz) RemoveFile(); - assert(sz <= size); - RedimLast(files.back()->Length() - (unsigned int)(size - sz)); + assert(sz <= _size); + RedimLast(files.back()->Length() - (unsigned int)(_size - sz)); } + assert(sz == _size); } void MFile::SetPosition(int64 pos) { - assert(pos < size); + assert(pos <= _size); curr_fp = (unsigned int)(pos/(int64)max_size); curr_pos = (unsigned int)(pos - (int64)max_size * (int64)curr_fp); assert(curr_pos < max_size); @@ -134,7 +135,7 @@ void MFile::WriteBuffer(void *data, unsigned int sz) { unsigned int last_size = file->Length(); delete file; files.pop_back(); - size -= last_size; + _size -= last_size; cerr << "Removing file: " << name << endl; #ifdef WIN32 DeleteFile(name.c_str()); @@ -148,7 +149,7 @@ void MFile::RedimLast(unsigned int sz) { File &file = *files.back(); unsigned int last_size = (int64)file.Length(); file.Redim(sz); - size += sz - (int64)last_size; + _size += sz - (int64)last_size; } std::string MFile::Name(unsigned int n) { diff --git a/apps/nexus/mfile.h b/apps/nexus/mfile.h index 4a2d1b28..b2918617 100644 --- a/apps/nexus/mfile.h +++ b/apps/nexus/mfile.h @@ -30,13 +30,14 @@ class MFile { void Close(); void Delete(); - int64 Length() { return size; } + int64 Length() { return _size; } void Redim(int64 size); void SetPosition(int64 pos); void ReadBuffer(void *data, unsigned int size); void WriteBuffer(void *data, unsigned int size); + bool Opened() { return files.size() > 0; } bool IsReadOnly() { return readonly; } void SetReadOnly(bool rd) { readonly = rd; } //USE WITH CARE!!!! protected: @@ -44,7 +45,7 @@ class MFile { std::vector files; unsigned int curr_pos; unsigned int curr_fp; - int64 size; + int64 _size; unsigned int max_size; bool readonly; private: diff --git a/apps/nexus/nexus.cpp b/apps/nexus/nexus.cpp index 5c6eb227..9c7df486 100644 --- a/apps/nexus/nexus.cpp +++ b/apps/nexus/nexus.cpp @@ -4,8 +4,6 @@ #include #include "nexus.h" -#include "lrupserver.h" -#include "queuepserver.h" using namespace std; using namespace vcg; @@ -16,155 +14,157 @@ Nexus::~Nexus() { } bool Nexus::Create(const string &file, Signature sig, unsigned int c_size) { - index_file = fopen((file + ".nxs").c_str(), "wb+"); - if(!index_file) { - cerr << "Could not create file: " << file << ".nxs\n"; - return false; - } - signature = sig; totvert = 0; totface = 0; sphere = Sphere3f(); - - index.clear(); - chunk_size = c_size; + unsigned int header_size = 256; + if(chunk_size > header_size) header_size = chunk_size; + + history.Clear(); + ram_used = 0; + ram_max = 50 * (1<<20) / chunk_size; - history.clear(); - - if(!patches.Create(file + ".nxp", signature, chunk_size)) { + if(!IndexFile::Create(file + ".nxp", header_size)) { cerr << "Could not create file: " << file << ".nxp" << endl; return false; } + //Important: chunk_size must be 1 so that i can use Region in VFile. - if(!borders.Create(file + ".nxb", 1, 100)) { + if(!borders.Create(file + ".nxb")) { cerr << "Could not create file: " << file << ".nxb" << endl; return false; } - history.clear(); return true; } bool Nexus::Load(const string &file, bool rdonly) { - readonly = rdonly; + if(!IndexFile::Load(file + ".nxp", rdonly)) return false; + ram_used = 0; + ram_max = 50 * (1<<20) / chunk_size; - index_file = fopen((file + ".nxs").c_str(), "rb+"); - if(!index_file) return false; - - unsigned int readed; - readed = fread(&signature, sizeof(unsigned int), 1, index_file); - if(!readed) return false; - readed = fread(&totvert, sizeof(unsigned int), 1, index_file); - if(!readed) return false; - readed = fread(&totface, sizeof(unsigned int), 1, index_file); - if(!readed) return false; - readed = fread(&sphere, sizeof(Sphere3f), 1, index_file); - if(!readed) return false; - readed = fread(&chunk_size, sizeof(unsigned int), 1, index_file); - if(!readed) return false; + history.Clear(); + SetPosition(history_offset); + unsigned int history_size; + ReadBuffer(&history_size, sizeof(unsigned int)); - unsigned int size; //size of index - readed = fread(&size, sizeof(unsigned int), 1, index_file); - if(!readed) return false; + char *buffer = new char[history_size]; + ReadBuffer(buffer, history_size); - index.resize(size); - readed = fread(&index[0], sizeof(PatchInfo), size, index_file); - if(readed != size) return false; - - patches.ReadEntries(index_file); - borders.ReadEntries(index_file); - - //history size; - fread(&size, sizeof(unsigned int), 1, index_file); - vector buffer; - buffer.resize(size); - fread(&(buffer[0]), sizeof(unsigned int), size, index_file); - - //number of history updates - size = buffer[0]; - history.resize(size); - - unsigned int pos = 1; - for(unsigned int i = 0; i < size; i++) { - unsigned int erased = buffer[pos++]; - unsigned int created = buffer[pos++]; - history[i].erased.resize(erased); - history[i].created.resize(created); - for(unsigned int e = 0; e < erased; e++) - history[i].erased[e] = buffer[pos++]; - for(unsigned int e = 0; e < created; e++) - history[i].created[e] = buffer[pos++]; - } - - if(readonly) { - fclose(index_file); - index_file = NULL; + if(!history.Load(history_size, buffer)) { + cerr << "Error loading history\n"; + return false; } - //TODO support readonly - if(!patches.Load(file + ".nxp", signature, chunk_size, readonly)) - return false; - if(!borders.Load(file + ".nxb", readonly, 1, 500)) - return false; + borders.Load(file + ".nxb", rdonly); + //TODO on nxsbuilder assure borders are loaded return true; } -void Nexus::Close() { - patches.Close(); - borders.Close(); - if(!index_file) return; - - rewind(index_file); - - fwrite(&signature, sizeof(unsigned int), 1, index_file); - fwrite(&totvert, sizeof(unsigned int), 1, index_file); - fwrite(&totface, sizeof(unsigned int), 1, index_file); - fwrite(&sphere, sizeof(Sphere3f), 1, index_file); - fwrite(&chunk_size, sizeof(unsigned int), 1, index_file); - - unsigned int size = index.size(); //size of index - fwrite(&size, sizeof(unsigned int), 1, index_file); - fwrite(&(index[0]), sizeof(PatchInfo), size, index_file); +void Nexus::Close() { + if(!Opened()) return; - //TODO this should be moved to the end... - //BUT it will break compatibility with existing models. - patches.WriteEntries(index_file); - borders.WriteEntries(index_file); - - vector buffer; - buffer.push_back(history.size()); - for(unsigned int i = 0; i < history.size(); i++) { - Update &update = history[i]; - buffer.push_back(update.erased.size()); - buffer.push_back(update.created.size()); - for(unsigned int e = 0; e < update.erased.size(); e++) - buffer.push_back(update.erased[e]); - for(unsigned int e = 0; e < update.created.size(); e++) - buffer.push_back(update.created[e]); + Flush(); + + if(!IsReadOnly()) { + //set history_offset + if(!size()) history_offset = 0; + else + history_offset = (back().patch_start + back().disk_size); + history_offset *= chunk_size; + + unsigned int history_size; + char *mem = history.Save(history_size); + Redim(history_offset + history_size + sizeof(unsigned int)); + SetPosition(history_offset); + WriteBuffer(&history_size, sizeof(unsigned int)); + WriteBuffer(mem, history_size); + delete []mem; } - - size = buffer.size(); - fwrite(&size, sizeof(unsigned int), 1, index_file); - fwrite(&(buffer[0]), sizeof(unsigned int), size, index_file); - - fclose(index_file); - index_file = NULL; + borders.Close(); + IndexFile::Close(); } -Patch &Nexus::GetPatch(unsigned int patch, bool flush) { - assert(patch < index.size()); - PatchInfo &info = index[patch]; - return patches.Lookup(patch, info.nvert, info.nface); +void Nexus::SaveHeader() { + unsigned int magic = 0x3053584e; // nxs0 + WriteBuffer(&magic, sizeof(unsigned int)); + WriteBuffer(&signature, sizeof(unsigned int)); + WriteBuffer(&chunk_size, sizeof(unsigned int)); + WriteBuffer(&offset, sizeof(int64)); + WriteBuffer(&history_offset, sizeof(int64)); + WriteBuffer(&totvert, sizeof(unsigned int)); + WriteBuffer(&totface, sizeof(unsigned int)); + WriteBuffer(&sphere, sizeof(Sphere3f)); +} + +bool Nexus::LoadHeader() { + unsigned int magic; + ReadBuffer(&magic, sizeof(unsigned int)); + if(magic != 0x3053584e) { + cerr << "Invalid magic. Not a nxs file\n"; + return false; + } + ReadBuffer(&signature, sizeof(unsigned int)); + ReadBuffer(&chunk_size, sizeof(unsigned int)); + ReadBuffer(&offset, sizeof(int64)); + ReadBuffer(&history_offset, sizeof(int64)); + ReadBuffer(&totvert, sizeof(unsigned int)); + ReadBuffer(&totface, sizeof(unsigned int)); + ReadBuffer(&sphere, sizeof(Sphere3f)); +} + +void Nexus::Flush(bool all) { + if(all) { + std::map::iterator>::iterator i; + for(i = index.begin(); i != index.end(); i++) { + unsigned int patch = (*i).first; + FlushPatch(patch); + } + pqueue.clear(); + index.clear(); + } else { + while(ram_used > ram_max) { + unsigned int to_flush = pqueue.back(); + pqueue.pop_back(); + index.erase(to_flush); + FlushPatch(to_flush); + } + } +} + + + +Patch &Nexus::GetPatch(unsigned int patch, bool flush) { + Entry &entry = operator[](patch); + if(index.count(patch)) { + assert(entry.patch); + list::iterator &i = index[patch]; + pqueue.erase(i); + pqueue.push_front(patch); + + } else { + while(flush && ram_used > ram_max) { + unsigned int to_flush = pqueue.back(); + pqueue.pop_back(); + index.erase(to_flush); + FlushPatch(to_flush); + } + assert(!entry.patch); + entry.patch = LoadPatch(patch); + pqueue.push_front(patch); + list::iterator i = pqueue.begin(); + index[patch] = i; + } + return *(entry.patch); } Border Nexus::GetBorder(unsigned int patch, bool flush) { - PatchInfo &info = index[patch]; return borders.GetBorder(patch); } -void Nexus::AddBorder(unsigned int patch, Link &link) { +/*void Nexus::AddBorder(unsigned int patch, Link &link) { Border border = GetBorder(patch); unsigned int pos = border.Size(); @@ -179,27 +179,30 @@ void Nexus::AddBorder(unsigned int patch, Link &link) { assert(border.Available() > pos); border[pos] = link; -} + }*/ unsigned int Nexus::AddPatch(unsigned int nvert, unsigned int nface, unsigned int nbord) { - PatchInfo info; - info.nvert = nvert; - info.nface = nface; + Entry entry; + entry.patch_start = 0xffffffff; + entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size); + entry.disk_size = 0xffff; + entry.nvert = nvert; + entry.nface = nface; + entry.error = 0; + //sphere undefined. + entry.patch = NULL; + entry.vbo_array = 0; + entry.vbo_element = 0; + + push_back(entry); - patches.AddPatch(nvert, nface); borders.AddBorder(nbord); - index.push_back(info); totvert += nvert; totface += nface; - return index.size() -1; -} - -void Nexus::MaxRamBuffer(unsigned int r_size) { - patches.MaxRamBuffer(r_size); - //TODO do the same with borders + return size() - 1; } void Nexus::Unify(float threshold) { @@ -207,9 +210,9 @@ void Nexus::Unify(float threshold) { unsigned int duplicated = 0; unsigned int degenerate = 0; - for(unsigned int p = 0; p < index.size(); p++) { - PatchInfo &entry = index[p]; - Patch patch = GetPatch(p); + for(unsigned int p = 0; p < size(); p++) { + Entry &entry = operator[](p); + Patch &patch = GetPatch(p); unsigned int vcount = 0; map vertices; @@ -294,7 +297,7 @@ void Nexus::Unify(float threshold) { } //better to compact directly borders than setting them null. //finally: there may be duplicated borders - for(unsigned int p = 0; p < index.size(); p++) { + for(unsigned int p = 0; p < size(); p++) { Border border = GetBorder(p); set links; for(unsigned int b = 0; b < border.Size(); b++) { @@ -307,7 +310,7 @@ void Nexus::Unify(float threshold) { for(set::iterator k = links.begin(); k != links.end(); k++) border[count++] = *k; - borders.borders[p].border_used = links.size(); + borders[p].used = links.size(); } totvert -= duplicated; @@ -316,3 +319,77 @@ void Nexus::Unify(float threshold) { if(degenerate) cerr << "Found " << degenerate << " degenerate face while unmifying\n"; } + +Patch *Nexus::LoadPatch(unsigned int idx) { + assert(idx < size()); + Entry &entry = operator[](idx); + if(entry.patch) return entry.patch; + + char *ram = new char[entry.ram_size * chunk_size]; +#ifndef NDEBUG + if(!ram) { + cerr << "COuld not allocate ram!\n"; + exit(0); + } +#endif + + Patch *patch = new Patch(signature, ram, entry.nvert, entry.nface); + + if(entry.patch_start != 0xffffffff) { //was allocated. + assert(entry.disk_size != 0xffff); + + MFile::SetPosition((int64)entry.patch_start * (int64)chunk_size); + + if((signature & NXS_COMPRESSED) == 0) { //not compressed + MFile::ReadBuffer(ram, entry.disk_size * chunk_size); + } else { + unsigned char *disk = new unsigned char[entry.disk_size * chunk_size]; + MFile::ReadBuffer(disk, entry.disk_size * chunk_size); + + patch->Decompress(entry.ram_size * chunk_size, + disk, entry.disk_size * chunk_size); + delete []disk; + } + } + ram_used += entry.ram_size; + entry.patch = patch; + return patch; +} + +void Nexus::FlushPatch(unsigned int id) { + Entry &entry = operator[](id); + assert(entry.patch); + + if(!MFile::IsReadOnly()) { //write back patch + if((signature & NXS_COMPRESSED)) { + unsigned int compressed_size; + char *compressed = entry.patch->Compress(entry.ram_size * chunk_size, + compressed_size); + if(entry.disk_size == 0xffff) {//allocate space + assert(entry.patch_start == 0xffffffff); + entry.disk_size = (unsigned int)((compressed_size-1)/chunk_size) + 1; + entry.patch_start = (unsigned int)(Length()/chunk_size); + Redim(Length() + entry.disk_size * chunk_size); + } else { + //cerr << "OOOOPSPPPS not supported!" << endl; + exit(-1); + } + MFile::SetPosition((int64)entry.patch_start * (int64)chunk_size); + MFile::WriteBuffer(compressed, entry.disk_size * chunk_size); + delete []compressed; + } else { + if(entry.disk_size == 0xffff) { + entry.disk_size = entry.ram_size; + entry.patch_start = (unsigned int)(Length()/chunk_size); + Redim(Length() + entry.disk_size * chunk_size); + } + MFile::SetPosition((int64)entry.patch_start * (int64)chunk_size); + MFile::WriteBuffer(entry.patch->start, entry.disk_size * chunk_size); + } + } + + delete [](entry.patch->start); + delete entry.patch; + entry.patch = NULL; + ram_used -= entry.ram_size; +} diff --git a/apps/nexus/nexus.h b/apps/nexus/nexus.h index eda64a5b..ada69328 100644 --- a/apps/nexus/nexus.h +++ b/apps/nexus/nexus.h @@ -3,15 +3,65 @@ #include #include +#include +#include -#include "nexusbase.h" -#include "lrupserver.h" +#include + +#include "patch.h" +#include "index_file.h" +#include "history.h" #include "borderserver.h" namespace nxs { -class Nexus: public NexusBase { + /* Header fo nexus: + 1Kb riservato per dati globali: + Magic: 'n' 'x' 's' 0x00 + Signature: unsigned int (maschera di bit) + Chunk size: unsigned int + Index offset: unsigned int (offset to the index begin, + must be a multiple of chunk size) + History offset: unsigned int: multiple of chunk_size + + Tot vert: unsigned int + Tot face: unsigned int + Bound sphere: Sphere3f (4 float: Point3f center (x, y, z), (radius)) + + 11 * 4 = 44 bytes -> 4k per alignment purpoouses and reserving space. */ + +struct Entry { + unsigned int patch_start; //granularita' Chunk + unsigned short ram_size; //in chunks + unsigned short disk_size; // in chunks (used when compressed) + + unsigned short nvert; + unsigned short nface; + + vcg::Sphere3f sphere; + float error; + + Patch *patch; + unsigned int vbo_array; + unsigned int vbo_element; +}; + +class Nexus: public IndexFile { public: + //HEader data: + Signature signature; + unsigned int chunk_size; + //unsigned int .IndexFile::offset; + int64 history_offset; + + unsigned int totvert; + unsigned int totface; + vcg::Sphere3f sphere; + + History history; + + BorderServer borders; + Nexus() {} ~Nexus(); @@ -20,12 +70,17 @@ class Nexus: public NexusBase { unsigned int chunk_size = 1024); bool Load(const std::string &filename, bool readonly = false); void Close(); - + void Flush(bool all = true); + 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); - void AddBorder(unsigned int patch, Link &link); + unsigned int &MaxRam() { return ram_max; } + // void AddBorder(unsigned int patch, Link &link); + + //move to nxsalgo! + void Unify(float threshold = 0.0f); bool IsCompressed() { return (signature & NXS_COMPRESSED) != 0; } bool HasStrips() { return (signature & NXS_STRIP) != 0; } @@ -33,34 +88,18 @@ class Nexus: public NexusBase { bool HasNormalsShort() { return (signature & NXS_NORMALS_SHORT) != 0; } bool HasNormalsFloat() { return (signature & NXS_NORMALS_FLOAT) != 0; } - void MaxRamBuffer(unsigned int ram_size); + unsigned int ram_max; + unsigned int ram_used; + protected: - //move to nxsalgo! - void Unify(float threshold = 0.0f); + std::list pqueue; + std::map::iterator> index; + Patch *LoadPatch(unsigned int id); + virtual void FlushPatch(unsigned int id); - /* Nexus data */ - - //BE CAREFUL: this 2 members get replicated into patchserver - //TODO fix this nasty thing it is dangerous as it is. - // Signature signature; - // unsigned int chunk_size; - - // unsigned int totvert; - // unsigned int totface; - // vcg::Sphere3f sphere; - - // std::vector index; - - LruPServer patches; - BorderServer borders; - - // std::vector history; - - // bool readonly; - - // private: - // FILE *index_file; + bool LoadHeader(); + void SaveHeader(); }; } diff --git a/apps/nexus/nexus.html b/apps/nexus/nexus.html index 89e89ac4..1ec180bd 100644 --- a/apps/nexus/nexus.html +++ b/apps/nexus/nexus.html @@ -39,6 +39,10 @@

Big picture

+La truttura nexus divide la mesh in tante piccole parti.
+Ciascuna parte ha le facce indicizzate localmente, e sono codificate +esplicitamente le corrispondenze tra vertici di patches diverse.
+

Structures and interfaces

VFile

@@ -46,12 +50,24 @@ VFile dovrebbe avere piu' o meno la stessa interfaccia di vector ma usare un file per storare i dati (un mmapping, ma non limitato a 4Gb).

Crude

+
 Crude e' un formato tipo il ply... solo che usa dei VFile per 
-storare i dati.(3 unsigned int per una faccia e 3 float per un vertice)
-Per cui e' composto di 3 files almeno: header (numero di facce, -vertici e Bounding box), file dei vertici, file delle facce ed -opzionalmente file degli attributi dei vertici e delle facce.
-Come interfaccia e' sufficente che dia accesso casuale a facce e vertici... +storare i dati.(3 unsigned int per una faccia e 3 float per un vertice). +Per cui e' composto di 3 files: + Header (.crd) + Magic: 'c' 'r' 'd' 0x00 (4 bytes) + N vertici: unsigned int (4 bytes) + N facce: unsigned int (4 bytes) + Box: Box3f (6 float min(x, y, z) e max(x, y, z)) + + File dei vertici: Point3f in sequenza (3 float, x, y, z) + File delle facce: 3 unsigned int + + opzionalmente file degli attributi dei vertici e delle facce. + + Come interfaccia e' sufficente che dia accesso casuale a facce e vertici... +
+

PChain

Sta per 'partition chain' cioe' una catena di partizioni dello spazio.
@@ -62,29 +78,47 @@ Oltre a questo va aggiunta una funzione che dato un punto e una patch ne restituisce la distanza (o un valore 'equivalente').
Si deve poter salvare su disco e recuperare una pchain
-

Remap

-E' composta da 3 files:
-indice delle patches: per ogni patch il numero di vertici, di facce e -di bordi
- vertici -> lista di patches: per ogni vertice una lista di patch -di cui fa parte (se sono + di 1 e' ovviamente di bordo.
-facce->patches: per ogni faccia un intero che dice in quale patch -sta.

Nexus

-E' una struttura con 3 files: 'index', 'patches' e 'borders'.
-'Index' contiene l'indice delle patches: per ogni patch viene storato -offset, size (ma questa potrebbe essere storata direttamente nei -files?) dei dati geometrici nel file delle patches e dei bordi nel -file dei borders, oltre alla bounding sphere.
-'Patches' e' un VFile di chunks da 4k dove i dati geometrici di una -patch occupano un numero intero di chunks. P.S. Come ce la caviamo con -gli attributi dei vertici e delle facce?
-'Borders' e' un VFile di 'links' dove ogni link fa riferimento ad un -vertice di bordo tra la patch A (V_a) e la B (V_b) e contiene -(V_a, V_b, B) (A e' implicito). L'informazione e' replicata nei bordi -relativi a B con (V_b, V_a, A)
+
+E' una struttura con 2 files:
+
+File delle patches: (.nxs)
+  1Kb riservato per dati globali:
+     Magic:        'n' 'x' 's' 0x00
+     Signature:    unsigned int (maschera di bit)
+     Chunk size:   unsigned int
+     Index offset: int64 (offset to the index begin, 
+                                 must be a multiple of chunk size)
+     History offset: int64: multiple of chunk_size
+
+     Tot vert:     unsigned int
+     Tot face:     unsigned int  
+     Bound sphere: Sphere3f (4 float: Point3f center (x, y, z), (radius))
+
+  Dati (la sequenza di patches)
+ 
+  Index
+  History
+
+  'Index' contiene l'indice delle patches, per ogni patch viene storato:
+  offset, size dei dati geometrici nel file delle patches etc.
+  'History' vedi history.h
+
+  Index e History sono tenuti in memoria se il file e' aperto per creare
+  o per modificare, e sono salvati quando si chiude il file.
+
+File dei bordi:
+   Links.
+   Index (offset, size tot size used)
+
+
+  Ogni link fa riferimento ad un vertice di bordo 
+  tra la patch A (V_a) e la B (V_b) e contiene (V_a, V_b, B) (A e' implicito). 
+   L'informazione e' replicata nei bordi relativi a B con (V_b, V_a, A)
+
+

Bmt

Bmt (batched multi triangulation) e' il formato per la diff --git a/apps/nexus/nexusbase.h b/apps/nexus/nexusbase.h index 0559aac9..e3935e2c 100644 --- a/apps/nexus/nexusbase.h +++ b/apps/nexus/nexusbase.h @@ -8,13 +8,13 @@ namespace nxs { -struct PatchInfo { + /*struct PatchInfo { unsigned short nvert; unsigned short nface; vcg::Sphere3f sphere; float error; -}; + };*/ class NexusBase { @@ -49,7 +49,7 @@ class NexusBase { unsigned int totface; vcg::Sphere3f sphere; - std::vector index; + // std::vector index; std::vector history; bool readonly; diff --git a/apps/nexus/nexusmt.cpp b/apps/nexus/nexusmt.cpp index 3a86e4a7..47901e2c 100644 --- a/apps/nexus/nexusmt.cpp +++ b/apps/nexus/nexusmt.cpp @@ -11,24 +11,28 @@ using namespace nxs; using namespace vcg; using namespace std; -/*void Policy::Visit(Node *node, std::queue &qnode) { - std::vector::iterator n; - for(n = node->in.begin(); n != node->in.end(); n++) - if(!(*n)->visited) - Visit(*n, qnode); - - node->visited = true; - qnode.push(node); +void Stats::Init() { + ktri = 0; + kdisk = 0; + if(count == 25) count = 0; + if(!count) { + fps = 25/watch.Time(); + watch.Start(); + } + count++; } -bool FrustumPolicy::Expand(unsigned int patch, Nexus::PatchInfo &entry) { - if(entry.error == 0) return false; - float dist = Distance(entry.sphere, frustum.ViewPoint()); - if(dist < 0) return true; - // dist = pow(dist, 1.2); - return entry.error > error * frustum.Resolution(dist); -} */ +/*float ExtractContest::GetError(PatchInfo &entry) { + Sphere3f &sphere = entry.sphere; + float dist = Distance(sphere, frustum.ViewPoint()); + if(dist < 0) + return 1e20f; + if(frustum.IsOutside(sphere.Center(), sphere.Radius())) + return -1; + return entry.error/frustum.Resolution(dist); + }*/ +/* float Metric::GetError(Node *node) { float max_error = 0; vector::iterator frag; @@ -71,14 +75,14 @@ bool NexusMt::Expand(TNode &tnode) { return error > target_error; } return tnode.error > target_error; -} + }*/ -void NexusMt::NodeVisited(Node *node) { +/*void NexusMt::NodeVisited(Node *node) { //TODO write this a bit more elegant. //first we process arcs removed: for(unsigned int i = 0; i < node->out.size(); i++) { - assert(!(node->out[i]->visited)); + //assert(!(node->out[i]->visited)); Frag &frag = node->frags[i]; for(unsigned int k = 0; k < frag.size(); k++) { unsigned int patch = frag[k]; @@ -113,154 +117,128 @@ void NexusMt::NodeVisited(Node *node) { } } } -} - -NexusMt::NexusMt(): vbo_mode(VBO_AUTO), - metric(NULL), mode(SMOOTH) { - metric = new FrustumMetric(); - metric->index = &index; - target_error = 4.0f; - extraction_max = 64000000000; - draw_max = 12000; //1M triangles (ZSN) - disk_max = 300; + }*/ +NexusMt::NexusMt() { + preload.mt = this; + preload.start(); + + cerr << "Ramsize: " << ram_max << endl; + // SetPrefetchSize(patches.ram_max/2); + // prefetch.start(); } NexusMt::~NexusMt() { - if(metric) - delete metric; - prefetch.signal(); - prefetch.waitfor(); + preload.signal(); + preload.waitfor(); } bool NexusMt::Load(const string &filename) { - index_file = fopen((filename + ".nxs").c_str(), "rb+"); - if(!index_file) return false; - - unsigned int readed; - readed = fread(&signature, sizeof(unsigned int), 1, index_file); - if(!readed) return false; - readed = fread(&totvert, sizeof(unsigned int), 1, index_file); - if(!readed) return false; - readed = fread(&totface, sizeof(unsigned int), 1, index_file); - if(!readed) return false; - readed = fread(&sphere, sizeof(Sphere3f), 1, index_file); - if(!readed) return false; - readed = fread(&chunk_size, sizeof(unsigned int), 1, index_file); - if(!readed) return false; - - unsigned int size; //size of index - readed = fread(&size, sizeof(unsigned int), 1, index_file); - if(!readed) return false; - - index.resize(size); - readed = fread(&index[0], sizeof(PatchInfo), size, index_file); - if(readed != size) return false; - - patches.ReadEntries(index_file); - borders.ReadEntries(index_file); - - //history size; - fread(&size, sizeof(unsigned int), 1, index_file); - vector buffer; - buffer.resize(size); - fread(&(buffer[0]), sizeof(unsigned int), size, index_file); - - //number of history updates - size = buffer[0]; - history.resize(size); - - unsigned int pos = 1; - for(unsigned int i = 0; i < size; i++) { - unsigned int erased = buffer[pos++]; - unsigned int created = buffer[pos++]; - history[i].erased.resize(erased); - history[i].created.resize(created); - for(unsigned int e = 0; e < erased; e++) - history[i].erased[e] = buffer[pos++]; - for(unsigned int e = 0; e < created; e++) - history[i].created[e] = buffer[pos++]; - } - - fclose(index_file); - index_file = NULL; - - if(!patches.Load(filename + ".nxp", signature, chunk_size, true)) + if(!Nexus::Load(filename, true)) return false; + if(!history.IsQuick() && !history.UpdatesToQuick()) return false; - - LoadHistory(); - - use_colors = false; - use_normals = false; - use_textures = false; - use_data = false; - - SetComponent(COLOR, true); - SetComponent(NORMAL, true); - SetComponent(TEXTURE, true); - SetComponent(DATA, true); - - SetPrefetchSize(patches.ram_max/2); - cerr << "Start!\n"; - - cerr << "Started\n"; return true; } -void NexusMt::Close() { - patches.Close(); -} +//void NexusMt::Close() { + // prefetch.signal(); + // prefetch.waitfor(); + // patches.Close(); +//} + +bool NexusMt::InitGL(bool vbo) { + use_vbo = vbo; -bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) { GLenum ret = glewInit(); if(ret != GLEW_OK) return false; - if(!GLEW_ARB_vertex_buffer_object) { + if(vbo && !GLEW_ARB_vertex_buffer_object) { cerr << "No vbo available!" << endl; - vbo_mode = VBO_OFF; + use_vbo = false; } -/*WORKING? patches.vbo_max = vbosize / chunk_size; - if(vbo_mode == VBO_OFF) - patches.vbo_max = 0;*/ - - prefetch.start(); return true; } -void NexusMt::Render() { - - vector cells; - metric->GetView(); - - Extract(cells); - Draw(cells); +void NexusMt::Render(DrawContest contest) { + Extraction extraction; + extraction.frustum.GetView(); + extraction.metric->GetView(); + extraction.Extract(this); + Render(extraction, contest); } -void NexusMt::Draw(vector &cells) { - tri_total = 0; - tri_rendered = 0; +void NexusMt::Render(Extraction &extraction, DrawContest &contest, + Stats *stats) { + if(stats) stats->Init(); - frustum.GetView(); - - vector draw; - for(unsigned int i = 0; i < cells.size(); i++) { - PatchInfo &entry = index[cells[i]]; - tri_total += entry.nface; - - if(!frustum.IsOutside(entry.sphere.Center(), entry.sphere.Radius())) { - draw.push_back(cells[i]); - tri_rendered += entry.nface; - } - } - prefetch.init(this, draw, visited); + preload.post(extraction.selected); glEnableClientState(GL_VERTEX_ARRAY); - if(use_colors) + if((signature & NXS_COLORS) && (contest.attrs & DrawContest::COLOR)) glEnableClientState(GL_COLOR_ARRAY); - if(use_normals) + if((signature & NXS_NORMALS_SHORT) && (contest.attrs & DrawContest::NORMAL)) + glEnableClientState(GL_NORMAL_ARRAY); + + vector skipped; + + vector::iterator i; + for(i = extraction.selected.begin(); i != extraction.selected.end(); i++) { + Entry &entry = operator[](*i); + vcg::Sphere3f &sphere = entry.sphere; + if(extraction.frustum.IsOutside(sphere.Center(), sphere.Radius())) + continue; + + if(stats) stats->ktri += entry.nface; + + if(!entry.patch) { + skipped.push_back(*i); + continue; + } + + Draw(*i, contest); + } + + preload.lock.enter(); + for(i = skipped.begin(); i != skipped.end(); i++) { + GetPatch(*i); + Draw(*i, contest); + } + // Flush(false); //not useful now + preload.lock.leave(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + + //flushing mem + + + +} + + + +/*void NexusMt::Draw(vector &cells) { + stats.start(); + + todraw.clear(); + vector flush; + for(unsigned int i = 0; i < cells.size(); i++) { + PatchInfo &entry = index[cells[i]]; + QueuePServer::Data &data = patches.Lookup(cells[i], entry.nvert, + entry.nface, flush); + todraw.push_back(&data); + } + + glEnableClientState(GL_VERTEX_ARRAY); + if(draw_cnt.use_colors) + glEnableClientState(GL_COLOR_ARRAY); + if(draw_cnt.use_normals) glEnableClientState(GL_NORMAL_ARRAY); //TODO textures and data. - unsigned int count = draw.size(); + + // unsigned int count = draw.size(); + unsigned int count = todraw.size(); while(count > 0 || prefetch.draw.get_count()) { if(todraw.size()) { QueuePServer::Data *data = todraw.back(); @@ -270,17 +248,17 @@ void NexusMt::Draw(vector &cells) { // cerr << "Getting message: " << count << endl; pt::message *msg = prefetch.draw.getmessage(); QueuePServer::Data *data = (QueuePServer::Data *)(msg->param); - if(msg->id == QueuePServer::FLUSH) { - if(data->vbo_element) { - glDeleteBuffersARB(1, &(data->vbo_element)); - glDeleteBuffersARB(1, &(data->vbo_array)); - } + if(msg->id == Prefetch::FLUSH) { + patches.FlushVbo(*data); + // if(data->vbo_element) { + //glDeleteBuffersARB(1, &(data->vbo_element)); + //glDeleteBuffersARB(1, &(data->vbo_array)); delete data; delete msg; continue; } - if(msg->id != QueuePServer::DRAW) { + if(msg->id != Prefetch::DRAW) { cerr << "Unknown message!\n"; continue; } @@ -295,23 +273,22 @@ void NexusMt::Draw(vector &cells) { glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); -} + }*/ -void NexusMt::Draw(unsigned int cell, QueuePServer::Data &data) { - - Patch &patch = *(data.patch); +void NexusMt::Draw(unsigned int cell, DrawContest &contest) { + Entry &entry = operator[](cell); + Patch &patch = *(entry.patch); char *fstart; char *vstart; char *cstart; char *nstart; - if(vbo_mode != VBO_OFF) { - if(!data.vbo_element) { - patches.LoadVbo(data); - } + if(use_vbo) { + if(!entry.vbo_element) + LoadVbo(entry); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, data.vbo_array); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, data.vbo_element); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, entry.vbo_array); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, entry.vbo_element); fstart = NULL; vstart = NULL; @@ -325,17 +302,17 @@ void NexusMt::Draw(unsigned int cell, QueuePServer::Data &data) { } glVertexPointer(3, GL_FLOAT, 0, vstart); - if(use_colors) + if(contest.attrs & DrawContest::COLOR) glColorPointer(4, GL_UNSIGNED_BYTE, 0, cstart); - if(use_normals) + if(contest.attrs & DrawContest::NORMAL) glNormalPointer(GL_SHORT, 8, nstart); - switch(mode) { - case POINTS: + switch(contest.mode) { + case DrawContest::POINTS: glDrawArrays(GL_POINTS, 0, patch.nv); break; - case PATCHES: + case DrawContest::PATCHES: glColor3ub((cell * 27)%255, (cell * 37)%255, (cell * 87)%255); - case SMOOTH: + case DrawContest::SMOOTH: if(signature & NXS_FACES) glDrawElements(GL_TRIANGLES, patch.nf * 3, GL_UNSIGNED_SHORT, fstart); @@ -343,7 +320,7 @@ void NexusMt::Draw(unsigned int cell, QueuePServer::Data &data) { glDrawElements(GL_TRIANGLE_STRIP, patch.nf, GL_UNSIGNED_SHORT, fstart); break; - case FLAT: + case DrawContest::FLAT: if(signature & NXS_FACES) { glBegin(GL_TRIANGLES); for(int i = 0; i < patch.nf; i++) { @@ -370,139 +347,122 @@ void NexusMt::Draw(unsigned int cell, QueuePServer::Data &data) { } } -void NexusMt::SetExtractionSize(unsigned int r_size) { - extraction_max = r_size/patches.chunk_size; +void NexusMt::FlushPatch(unsigned int id) { + Entry &entry = operator[](id); + if(entry.vbo_element) + FlushVbo(entry); + + if(entry.patch->start) + delete [](entry.patch->start); + delete entry.patch; + entry.patch = NULL; + ram_used -= entry.ram_size; } -void NexusMt::SetMetric(NexusMt::MetricKind kind) { +void NexusMt::LoadVbo(Entry &entry) { + if(entry.vbo_element) return; + glGenBuffersARB(1, &entry.vbo_element); + assert(entry.vbo_element); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, entry.vbo_element); + + Patch &patch = *entry.patch; + unsigned int size = patch.nf * sizeof(unsigned short); + if((signature & NXS_FACES) != 0) size *= 3; + + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, size, patch.FaceBegin(), + GL_STATIC_DRAW_ARB); + vbo_used += size; + + //TODO fix this when we allow data :p + size = sizeof(float) * patch.dstart; + + glGenBuffersARB(1, &entry.vbo_array); + assert(entry.vbo_array); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, entry.vbo_array); + + glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, patch.VertBegin(), + GL_STATIC_DRAW_ARB); + + vbo_used += size; + delete [](entry.patch->start); + entry.patch->start = NULL; +} + +void NexusMt::FlushVbo(Entry &entry) { + if(!entry.vbo_element) return; + glDeleteBuffersARB(1, &entry.vbo_element); + glDeleteBuffersARB(1, &entry.vbo_array); + entry.vbo_element = 0; + entry.vbo_array = 0; + + Patch &patch = *entry.patch; + vbo_used -= patch.nf * sizeof(unsigned short); + vbo_used -= sizeof(float) * patch.dstart; +} + +/*void NexusMt::SetExtractionSize(unsigned int r_size) { + extract_cnt.extraction_max = r_size/patches.chunk_size; +} + +//void NexusMt::SetMetric(NexusMt::MetricKind kind) { //do nothing at the moment. -} +//} void NexusMt::SetError(float error) { - target_error = error; + extract_cnt.target_error = error; } -void NexusMt::SetVboSize(unsigned int _vbo_max) { +//void NexusMt::SetVboSize(unsigned int _vbo_max) { //WORKING patches.vbo_max = _vbo_max; -} +//} void NexusMt::SetPrefetchSize(unsigned int size) { //TODO do something reasonable with this. } -bool NexusMt::SetMode(Mode _mode) { - mode = _mode; +bool NexusMt::SetMode(DrawContest::Mode _mode) { + draw_cnt.mode = _mode; return true; } -bool NexusMt::SetComponent(Component c, bool on) { - if(c == COLOR && (signature & NXS_COLORS)) - use_colors = on; - if(c == NORMAL && (signature & NXS_NORMALS_SHORT)) - use_normals = on; - if(c == TEXTURE && (signature & NXS_TEXTURES_SHORT)) - use_textures = on; - if(c == DATA && (signature & NXS_DATA32)) - use_data = on; +bool NexusMt::SetComponent(DrawContest::Component c, bool on) { + if(c == DrawContest::COLOR && (signature & NXS_COLORS)) + draw_cnt.use_colors = on; + if(c == DrawContest::NORMAL && (signature & NXS_NORMALS_SHORT)) + draw_cnt.use_normals = on; + if(c == DrawContest::TEXTURE && (signature & NXS_TEXTURES_SHORT)) + draw_cnt.use_textures = on; + if(c == DrawContest::DATA && (signature & NXS_DATA32)) + draw_cnt.use_data = on; - components = COLOR * use_colors + NORMAL * use_normals + - TEXTURE * use_textures + DATA * use_data; + // unsigned int components = DrawContest::COLOR * use_colors + + // DrawContest::NORMAL * use_normals + + // DrawContest::TEXTURE * use_textures + + // DrawContest::DATA * use_data; return true; } bool NexusMt::SetComponents(unsigned int mask) { - SetComponent(COLOR, (mask & COLOR) != 0); - SetComponent(NORMAL, (mask & NORMAL) != 0); - SetComponent(TEXTURE, (mask & TEXTURE) != 0); - SetComponent(DATA, (mask & DATA) != 0); + SetComponent(DrawContest::COLOR, (mask & DrawContest::COLOR) != 0); + SetComponent(DrawContest::NORMAL, (mask & DrawContest::NORMAL) != 0); + SetComponent(DrawContest::TEXTURE, (mask & DrawContest::TEXTURE) != 0); + SetComponent(DrawContest::DATA, (mask & DrawContest::DATA) != 0); - components = mask; + // unsigned int components = mask; - if( ((mask & COLOR) && !(signature & NXS_COLORS)) || - ((mask & NORMAL) && !(signature & NXS_NORMALS_SHORT)) || - ((mask & TEXTURE) && !(signature & NXS_TEXTURES_SHORT)) || - ((mask & DATA) && !(signature & NXS_DATA32)) ) + if( ((mask & DrawContest::COLOR) && !(signature & NXS_COLORS)) || + ((mask & DrawContest::NORMAL) && !(signature & NXS_NORMALS_SHORT)) || + ((mask & DrawContest::TEXTURE) && !(signature & NXS_TEXTURES_SHORT)) || + ((mask & DrawContest::DATA) && !(signature & NXS_DATA32)) ) return false; return true; -} + }*/ //TODO: nodes and fragment sholuld be kept in another way, // so we can save that structure instead of the history! -void NexusMt::LoadHistory() { - //The last update erases everything. - assert(history[0].erased.size() == 0); - - //maps cell -> node containing it - map cell_node; - nodes.resize(history.size()); - //building fragments and nodes. - unsigned int current_node = 0; - vector::iterator u; - for(u = history.begin(); u != history.end(); u++) { - - Node &node = nodes[current_node]; - node.error = 0; - - //cerr << "Created: "; - //created cells belong to this node, we look also for max error. - for(unsigned int i = 0; i < (*u).created.size(); i++) { - unsigned int cell = (*u).created[i]; - //cerr << cell << " "; - if(index[cell].error > node.error) - node.error = index[cell].error; - cell_node[cell] = current_node; - } - //cerr << endl; - - //Every erased cell already belonged to a node. - //we record for each node its cells. - map > node_erased; - - for(unsigned int i = 0; i < (*u).erased.size(); i++) { - unsigned int cell = (*u).erased[i]; - assert(cell_node.count(cell)); - node_erased[cell_node[cell]].push_back(cell); - } - - //for every node with erased cells we build a frag and - //put the corresponding cells in it. - map >::iterator e; - for(e = node_erased.begin(); e != node_erased.end(); e++) { - //Build a new Frag. - Frag fr; - float max_err = -1; - - //Fill it with erased cells. - vector &cells = (*e).second; - vector::iterator k; - for(k = cells.begin(); k != cells.end(); k++) { - unsigned int cell = (*k); - assert(cell < index.size()); - fr.push_back(cell); - if(index[cell].error > max_err) - max_err = index[cell].error; - } - //Add the new Frag to the node. - unsigned int floor_node = (*e).first; - Node &oldnode = nodes[floor_node]; - oldnode.frags.push_back(fr); - if(node.error < max_err) - node.error = max_err; - - //Update in and out of the nodes. - node.in.push_back(&oldnode); - oldnode.out.push_back(&node); - } - current_node++; - } -} - -void NexusMt::ClearHistory() { - nodes.clear(); -} /*void NexusMt::ExtractFixed(vector &selected, float error) { std::vector::iterator n; @@ -528,80 +488,302 @@ void NexusMt::ClearHistory() { (*on)->visited = 1; } else { vector::iterator cell; - for(cell=(*fragment).begin(); cell != (*fragment).end(); ++cell) - selected.push_back(*cell); + for(cell=(*fragment).begin(); cell != (*fragment).end(); ++cell) selected.push_back(*cell); } } } } */ -void NexusMt::Extract(std::vector &selected) { - extraction_used = 0; - draw_used = 0; - disk_used = 0; - visited.clear(); +/*void NexusMt::Expand(Node &node, vector &expand) { + if(node.visited) return; + cerr << "Expanding\n"; + for(unsigned int i = 0; i < node.in_size; i++) { + Link &link = innodes[node.in + i]; + Node &parent = nodes[link.node]; + if(!parent.visited) + Expand(parent, expand); + } - float bestcost = -1; - int best = -1; - float cost = 0; + for(unsigned int o = 0; o < node.out_size; o++) { + Link &link = outnodes[node.out + o]; + Node &outnode = nodes[link.node]; + if(outnode.visited) continue; + assert(link.error != -1); + if(link.error > extract_cnt.target_error) { + HeapNode hnode(&outnode, node.error - extract_cnt.target_error); + expand.push_back(hnode); + push_heap(expand.begin(), expand.end()); + } + } - std::vector::iterator n; - for(n = nodes.begin(); n != nodes.end(); n++) - (*n).visited = false; - - std::vector heap; - Node *root = &nodes[0]; - VisitNode(root, heap); + unsigned int d_extr = 0; + unsigned int d_draw = 0; + unsigned int d_disk = 0; + Diff(node, d_extr, d_draw, d_disk); + extract_cnt.extraction_used += d_extr; + extract_cnt.draw_used += d_draw; + extract_cnt.disk_used += d_disk; + node.visited = true; +} - sequence.clear(); - //vector sequence; - while(heap.size()) { - pop_heap(heap.begin(), heap.end()); - TNode tnode = heap.back(); - heap.pop_back(); +void NexusMt::Contract(Node &node) { + if(!node.visited) return; + cerr << "Contracting...\n"; + for(unsigned int i = 0; i < node.out_size; i++) { + Link &link = outnodes[node.out + i]; + Node &child = nodes[link.node]; + if(child.visited) + Contract(child); + } - Node *node = tnode.node; - if(node->visited) continue; + unsigned int d_extr = 0; + unsigned int d_draw = 0; + unsigned int d_disk = 0; + Diff(node, d_extr, d_draw, d_disk); + extract_cnt.extraction_used -= d_extr; + extract_cnt.draw_used -= d_draw; + extract_cnt.disk_used -= d_disk; + node.visited = false; +} - bool expand = Expand(tnode); +void NexusMt::GetErrorLink(Node &node, Link &link) { + if(link.error != -1) return; + for(unsigned int c = link.frag; frags[c].patch != 0xffffffff; c++) { + Cell &cell = frags[c]; + if(cell.error != -1) continue; + PatchInfo &info = index[cell.patch]; + cell.error = extract_cnt.GetError(info); + cerr << "Cell.error: " << cell.error << endl; + if(link.error < cell.error) link.error = cell.error; + } +} - if(expand) //{ - VisitNode(node, heap); - - /* float cost = disk_used * 100; - if(draw_used > draw_max) - cost += 1 * (draw_used - draw_max); - if(tnode.error > target_error) - cost += 1000 * (tnode.error - target_error) * (tnode.error - target_error); - if(best == -1 || cost < bestcost) { - bestcost = cost; - best = sequence.size(); +void NexusMt::GetErrorNode(Node &node) { + if(node.error != -1) return; + for(unsigned int o = 0; o < node.out_size; o++) { + Link &link = outnodes[node.out + o]; + GetErrorLink(node, link); + if(node.error < link.error) node.error = link.error; + } +} + +void NexusMt::NodeExplore(Node &node, + vector &expand, + vector &contract) { + assert(node.visited); + GetErrorNode(node); + + cerr << "node.error: " << node.error << + " target: " << extract_cnt.target_error << endl; + if(node.error > extract_cnt.target_error) { + cerr << "Expandible node...\n"; + for(unsigned int o = 0; o < node.out_size; o++) { + Link &link = outnodes[node.out + o]; + assert(link.error != -1); + Node &outnode = nodes[link.node]; + if(outnode.visited) continue; + + if(link.error > extract_cnt.target_error) { + HeapNode hnode(&outnode, node.error - extract_cnt.target_error); + expand.push_back(hnode); + push_heap(expand.begin(), expand.end()); } - } */ + } } - //cerr << "best: " << best << " tot: " << sequence.size() << endl; - /*for(n = nodes.begin(); n != nodes.end(); n++) - (*n).visited = false; - - for(unsigned int i = 0; i < best; i++) { - Node *node = sequence[i]; - node->visited = true; - for(unsigned int n = 0; n < node->out.size(); n++) { - Node *outnode = node->out[n]; - for(unsigned int k = 0; k < outnode->frags.size(); k++) { - for(unsigned int j = 0; j < outnode->frags[k].size(); j++) { - unsigned int patch = outnode->frags[k][j]; - float error = metric->GetError(patch); - visited.push_back(PServer::Item(patch, fabs(error - target_error))); - } - } - } - } */ - - Select(selected); + float max_err = -1; + + bool can_contract = true; + for(unsigned int o = 0; o < node.out_size; o++) { + Link &link = outnodes[node.out + o]; + Node &outnode = nodes[link.node]; + if(node.visited) { + can_contract = false; + break; + } + } + if(can_contract) { + for(unsigned int o = 0; o < node.in_size; o++) { + Link &link = innodes[node.in + o]; + GetErrorLink(node, link); + if(max_err < link.error) max_err = link.error; + } + HeapNode hnode(&node, extract_cnt.target_error - max_err); + contract.push_back(hnode); + push_heap(contract.begin(), contract.end()); + } } +void NexusMt::FrontExplore(vector &expand, + vector &contract) { + + + extract_cnt.extraction_used = 0; + extract_cnt.draw_used = 0; + extract_cnt.disk_used = 0; + + std::vector::iterator i; + for(i = nodes.begin(); i != nodes.end(); i++) { + Node &node = *i; + if(!node.visited) + continue; + + for(int k = 0; k < node.out_size; k++) { + Link &link = outnodes[node.out + k]; + assert(link.node < nodes.size()); + Node &children = nodes[link.node]; + if(!children.visited) { + cerr << "Exploting child...\n"; + NodeExplore(node, expand, contract); + + for(unsigned int c = link.frag; frags[c].patch != 0xffffffff; c++) { + PServer::Entry &entry = patches.entries[c]; + if(!entry.patch) extract_cnt.disk_used += entry.disk_size; + extract_cnt.extraction_used += entry.ram_size; + vcg::Sphere3f &sphere = index[c].sphere; + if(!extract_cnt.frustum.IsOutside(sphere.Center(), sphere.Radius())) + extract_cnt.draw_used += entry.ram_size; + } + } + } + } +} + +void NexusMt::Diff(Node &node, + unsigned int &d_extr, + unsigned int &d_draw, + unsigned int &d_disk) { + d_extr = 0; + d_draw = 0; + d_disk = 0; + for(unsigned int o = 0; o < node.out_size; o++) { + Link &link = outnodes[node.out + o]; + for(unsigned int c = link.frag; frags[c].patch != 0xffffffff; c++) { + PServer::Entry &entry = patches.entries[c]; + if(!entry.patch) d_disk += entry.disk_size; + d_extr += entry.ram_size; + Sphere3f &sphere = index[c].sphere; + if(!extract_cnt.frustum.IsOutside(sphere.Center(), sphere.Radius())) + d_draw += entry.ram_size; + } + } + for(unsigned int o = 0; o < node.in_size; o++) { + Link &link = innodes[node.in + o]; + for(unsigned int c = link.frag; frags[c].patch != 0xffffffff; c++) { + PServer::Entry &entry = patches.entries[c]; + if(!entry.patch) d_disk -= entry.disk_size; + d_extr -= entry.ram_size; + if(!extract_cnt.frustum.IsOutside(sphere.Center(), sphere.Radius())) + d_draw -= entry.ram_size; + } + } + }*/ + +/*void NexusMt::Extract(std::vector &selected) { + extract_cnt.frustum.GetView(); + + + //clear error (no more valid...) + for(unsigned int i = 0; i < nodes.size(); i++) + nodes[i].error = -1; + for(unsigned int i = 0; i < outnodes.size(); i++) + outnodes[i].error = -1; + for(unsigned int i = 0; i < innodes.size(); i++) + innodes[i].error = -1; + for(unsigned int i = 0; i < frags.size(); i++) + frags[i].error = -1; + + + std::vector expand; + std::vector contract; + + if(!nodes[0].visited) + nodes[0].visited = true; + //explore front + FrontExplore(expand, contract); + + bool can_expand = true; + bool can_contract = true; + float current_error = 1e30; + while(can_expand || can_contract) { + if(can_expand) { + if(!expand.size()) { + can_expand = false; + continue; + } + cerr << "trying to expand..\n"; + pop_heap(expand.begin(), expand.end()); + HeapNode hnode = expand.back(); + + Node *node = hnode.node; + // if(node->visited) { + //cerr << "Failed cause already visited\n"; +// expand.pop_back(); + //continue; //already expanded... +// } + unsigned int d_extr = 0; + unsigned int d_draw = 0; + unsigned int d_disk = 0; + Diff(*node, d_extr, d_draw, d_disk); + + if(extract_cnt.disk_used + d_disk > extract_cnt.disk_max) { + cerr << "Failed cause disk...\n"; + cerr << "d_disl: " << d_disk << " extract_cnt.disk_max " + << extract_cnt.disk_max << endl; + expand.pop_back(); + continue; + } + if(extract_cnt.extraction_used + d_extr > extract_cnt.extraction_max || + extract_cnt.draw_used + d_draw > extract_cnt.draw_max) { + cerr << "Failed...\n"; + can_expand = false; + push_heap(expand.begin(), expand.end()); + continue; + } else { + cerr << "Expanding...\n"; + current_error = hnode.error; + expand.pop_back(); + Expand(*node, expand); + } + } else if(can_contract) { + if(!contract.size()) { + can_contract = false; + continue; + } + pop_heap(contract.begin(), contract.end()); + HeapNode hnode = contract.back(); + + if(hnode.error < extract_cnt.target_error - current_error) { + can_contract = false; + continue; + } + Node *node = hnode.node; + if(!node->visited) { + contract.pop_back(); + continue;//already contracted + } + + unsigned int d_extr = 0; + unsigned int d_draw = 0; + unsigned int d_disk = 0; + Diff(*node, d_extr, d_draw, d_disk); + + if(extract_cnt.disk_used - d_disk > extract_cnt.disk_max) { + expand.pop_back(); + continue; + } + if(extract_cnt.extraction_used - d_extr < extract_cnt.extraction_max && + extract_cnt.draw_used - d_draw < extract_cnt.draw_max) { + can_expand = true; + } + current_error = hnode.error; + contract.pop_back(); + Contract(*node); + } + } + Select(selected); +}*/ + /*void NexusMt::Extract(std::vector &selected, Policy *policy) { std::vector::iterator n; for(n = nodes.begin(); n != nodes.end(); n++) @@ -630,7 +812,7 @@ void NexusMt::Extract(std::vector &selected) { Select(selected); } */ -void NexusMt::Select(vector &selected) { +/*void NexusMt::Select(vector &selected) { selected.clear(); std::vector::iterator i; for(i = nodes.begin(); i != nodes.end(); i++) { @@ -638,8 +820,20 @@ void NexusMt::Select(vector &selected) { if(!node.visited) continue; - std::vector::iterator n; - std::vector::iterator f; + for(unsigned int o = 0; o < node.out_size; o++) { + Link &link = outnodes[node.out + o]; + for(unsigned int c = link.frag; frags[c].patch != 0xffffffff; c++) { + Cell &cell = frags[c]; + selected.push_back(cell.patch); + } + } + }*/ + // for(unsigned int i = 0; i < selected.size(); i++) { + // cerr << "Sel: " << selected[i] << endl; + // } + + /* std::vector::iterator n; + std::vector<>::iterator f; for(n = node.out.begin(), f = node.frags.begin(); n != node.out.end(); n++, f++) { if(!(*n)->visited || (*n)->error == 0) { @@ -649,8 +843,8 @@ void NexusMt::Select(vector &selected) { selected.push_back(*c); } } - } -} + }*/ +//} /*bool NexusMt::TestCurrent(Node *node) { if(!visited) return; for(unsigned int i = 0; i < node->out.size(); i++) @@ -662,7 +856,7 @@ void NexusMt::Select(vector &selected) { return false; } */ -void NexusMt::VisitNode(Node *node, vector &heap) { +/*void NexusMt::VisitNode(Node *node, vector &heap) { //TestCurrent(*i); if(node->visited) return; @@ -677,13 +871,6 @@ void NexusMt::VisitNode(Node *node, vector &heap) { for(unsigned int k = 0; k < node->out.size(); k++) { Node *outnode = node->out[k]; float max_error = metric->GetError(outnode); - /* for(unsigned int j = 0; j < node->frags[k].size(); j++) { - unsigned int patch = node->frags[k][j]; - PServer::Entry &entry = patches.entries[patch]; - if(!entry.patch) - max_error /= 2; - }*/ - for(unsigned int j = 0; j < node->frags[k].size(); j++) { unsigned int patch = node->frags[k][j]; float error = metric->GetError(patch); @@ -698,7 +885,7 @@ void NexusMt::VisitNode(Node *node, vector &heap) { sequence.push_back(node); NodeVisited(node); -} + }*/ /*void NexusMt::UnvisitNode(Node *node, vector &heap) { node->current = false; @@ -709,4 +896,122 @@ void NexusMt::VisitNode(Node *node, vector &heap) { heap.push_back(TNode(*i, error)); push_heap(heap.begin(), heap.end()); } -} */ \ No newline at end of file +} */ + + +/*void NexusMt::LoadHistory() { + //The last update erases everything. + assert(history[0].erased.size() == 0); + + //maps cell -> node containing it + map cell_node; + //maps node -> Links + map > node_inlinks; + map > node_outlinks; + nodes.resize(history.size()); + + //building fragments and nodes. + unsigned int current_node = 0; + vector::iterator u; + for(u = history.begin(); u != history.end(); u++) { + + Node &node = nodes[current_node]; + node.error = 0; + + //created cells belong to this node, we look also for max error. + for(unsigned int i = 0; i < (*u).created.size(); i++) { + unsigned int cell = (*u).created[i]; + if(index[cell].error > node.error) + node.error = index[cell].error; + cell_node[cell] = current_node; + } + + //Every erased cell already belonged to a node. + //we record for each node its cells. + map > node_erased; + + for(unsigned int i = 0; i < (*u).erased.size(); i++) { + unsigned int cell = (*u).erased[i]; + assert(cell_node.count(cell)); + node_erased[cell_node[cell]].push_back(cell); + } + + //for every node with erased cells we build a frag and + //put the corresponding cells in it. + map >::iterator e; + for(e = node_erased.begin(); e != node_erased.end(); e++) { + + //node.in.push_back(innodes.size()); + + unsigned int floor_node = (*e).first; + Node &oldnode = nodes[floor_node]; + + Link inlink; + inlink.node = floor_node; + inlink.frag = frags.size(); + + Link outlink; + outlink.node = current_node; + outlink.frag = frags.size(); + + float max_err = -1; + + //Fill it with erased cells. + vector &cells = (*e).second; + vector::iterator k; + for(k = cells.begin(); k != cells.end(); k++) { + Cell cell; + cell.patch = (*k); + assert(cell.patch < index.size()); + frags.push_back(cell); + if(index[cell.patch].error > max_err) + max_err = index[cell.patch].error; + } + Cell cell; + cell.patch = 0xffffffff; + cell.error = -1; + frags.push_back(cell); + + inlink.error = max_err; + outlink.error = max_err; + + //Add the new Frag to the node. + + node_outlinks[floor_node].push_back(outlink); + node_outlinks[current_node].push_back(inlink); + if(node.error < max_err) + node.error = max_err; + + //Update in and out of the nodes. + } + current_node++; + } + + map >::iterator k; + for(k = node_outlinks.begin(); k != node_outlinks.end(); k++) { + unsigned int inode = (*k).first; + vector &links = (*k).second; + nodes[inode].out = outnodes.size(); + nodes[inode].out_size = links.size(); + + for(unsigned int i = 0; i < links.size(); i++) + outnodes.push_back(links[i]); + } + + for(k = node_inlinks.begin(); k != node_inlinks.end(); k++) { + unsigned int inode = (*k).first; + vector &links = (*k).second; + nodes[inode].in = innodes.size(); + nodes[inode].in_size = links.size(); + + for(unsigned int i = 0; i < links.size(); i++) + innodes.push_back(links[i]); + } +} + +void NexusMt::ClearHistory() { + nodes.clear(); + innodes.clear(); + outnodes.clear(); + frags.clear(); + }*/ diff --git a/apps/nexus/nexusmt.h b/apps/nexus/nexusmt.h index 3234235a..bffe37b4 100644 --- a/apps/nexus/nexusmt.h +++ b/apps/nexus/nexusmt.h @@ -1,179 +1,109 @@ -#ifndef NXS_NEXUS_MT_H -#define NXS_NEXUS_MT_H +#ifndef NXS_MT_H +#define NXS_MT_H #include #include #include -#include "nexusbase.h" -#include "queuepserver.h" -#include "borderserver.h" -#include "prefetch.h" +#include "nexus.h" +#include "history.h" +#include "extraction.h" +#include "metric.h" +#include "preload.h" +#include "watch.h" namespace nxs { - typedef std::vector Frag; - - struct Node { - std::vector in; - std::vector out; - std::vector frags; - float error; - bool visited; - bool current; - // bool pushed; - }; + struct DrawContest { - struct TNode { - float error; - Node *node; - TNode(Node *n, float e): node(n), error(e) {} - bool operator<(const TNode &n) { return error < n.error; } - }; + enum Mode { POINTS, SMOOTH, XRAY, HIDDEN_LINE, FLAT_WIRE, FLAT, PATCHES }; + enum Attr { COLOR = 0x1, NORMAL = 0x2, TEXTURE = 0x4, DATA = 0x8 }; - class Metric { - public: - std::vector *index; - - float GetError(Node *node); - float GetError(Frag &frag); - virtual float GetError(unsigned int cell) = 0; - virtual void GetView() {} - }; - - class FlatMetric: public Metric { - public: - void GetView() {} - float GetError(unsigned int cell); - }; - - class DeltaMetric: public Metric { - public: - vcg::Point3f delta; - void GetView() {} - float GetError(unsigned int cell); - }; - - class FrustumMetric: public Metric { - public: - vcg::Frustumf frustum; - - void GetView() { frustum.GetView(); } - float GetError(unsigned int cell); - }; - - /* class Policy { - public: - float error; - int ram_used; - int ram_size; - - vector *entries; - - void Init(); - bool Expand(TNode &node); - void NodeVisited(Node *node); - };*/ - -class NexusMt: public NexusBase { - public: - //Vertex buffer object mode - enum Vbo { VBO_AUTO, //autodetect best size - VBO_OFF, //no vertex buffer object - VBO_FIXED }; //user supplied size - - enum MetricKind { FRUSTUM, //screen error extraction - GEOMETRY, //geometry error extraction - DELTA }; //delta error - - enum Mode { POINTS, - SMOOTH, - XRAY, - HIDDEN_LINE, - FLAT_WIRE, - FLAT, - PATCHES }; - - enum Component { COLOR = 0x1, - NORMAL = 0x2, - TEXTURE = 0x4, - DATA = 0x8}; - - Vbo vbo_mode; - - Metric *metric; - float target_error; - - vcg::Frustumf frustum; + Mode mode; + unsigned int attrs; - unsigned int extraction_max; //total extraxtion (even culled parts) - unsigned int extraction_used; - unsigned int draw_max; //only visible parts - unsigned int draw_used; - unsigned int disk_max; //max not in ram loadable size - unsigned int disk_used; + DrawContest(Mode m = SMOOTH, unsigned int a = 0xf): mode(m), attrs(a) {} + void SetAttr(Attr attr, bool value); + bool HasComponent(Attr attr); + }; + struct Stats { + float ktri; //k triangles rendered. + float kdisk; //k readed per frame (mean) + float kdisk_peak; //k readed peak. + float fps; + float fps_peak; //low fps peaks - Mode mode; + //double last_time; + unsigned int count; - unsigned int components; - bool use_normals; - bool use_colors; - bool use_textures; - bool use_data; + Watch watch; - //statistics: - unsigned int tri_rendered; - unsigned int tri_total; - - vector todraw; - std::vector visited; - std::vector sequence; - - QueuePServer patches; - BorderServer borders; - - Prefetch prefetch; - - NexusMt(); - ~NexusMt(); + Stats(): count(0) {} + void Init(); + }; - bool Load(const std::string &filename); - void Close(); + class NexusMt: public Nexus { + public: + bool use_vbo; + bool prefetch; - bool InitGL(Vbo mode = VBO_AUTO, unsigned int vbo_size = 64000000); + unsigned int vbo_used; //TODO remember to zero it! + + Preload preload; + + NexusMt(); + ~NexusMt(); + + bool Load(const std::string &filename); + // void Close(); + + bool InitGL(bool use_vbo = true); + + void Render(DrawContest contest = DrawContest()); + void Render(Extraction &extraction, + DrawContest &contest, + Stats *stats = NULL); + // void Draw(std::vector &selected); + // void Extract(std::vector &selected); + + protected: + void FlushPatch(unsigned int id); + void LoadVbo(Entry &entry); + void FlushVbo(Entry &entry); + void Draw(unsigned int cell, DrawContest &contest); + + }; + + /* class NexusViewer { + public: + NexusMt &mt; + + DrawContest contest; + Extraction extraction; + Statistics stats; + + NexusViewer(NexyusMt &_mt): mt(&mt) {} + void Render(); + + + bool SetMode(DrawContest::Mode mode); + bool SetComponent(DrawContest::Component c, bool on); + bool SetComponents(unsigned int mask); + + void SetMetric(MetricKind kind); + void SetError(float error); + + //Uinits expressed in Kb + void SetExtractionSize(unsigned int ksize); + void SetDrawSize(unsigned int ksize); + void SetDiskDelta(unsigned int kdelta); + //void SetPrefetchSize(unsigned int size); + };*/ - void Render(); - - void SetMetric(MetricKind kind); - void SetError(float error); - void SetExtractionSize(unsigned int ram_size); - void SetPrefetchSize(unsigned int size); - void SetVboSize(unsigned int vbo_size); - bool SetMode(Mode mode); - bool SetComponent(Component c, bool on); - bool SetComponents(unsigned int mask); - - void Draw(std::vector &selected); - void Draw(unsigned int cell, QueuePServer::Data &data); - void Extract(std::vector &selected); - - protected: - std::vector nodes; - - bool Expand(TNode &node); - void NodeVisited(Node *node); - - void LoadHistory(); - void ClearHistory(); - void VisitNode(Node *node, std::vector &heap); - void UnvisitNode(Node *node, std::vector &heap); - void Select(std::vector &selected); - Patch &LoadPatch(unsigned int p); -}; } - + #endif diff --git a/apps/nexus/nexusview.cpp b/apps/nexus/nexusview.cpp index 89e3514c..55477282 100644 --- a/apps/nexus/nexusview.cpp +++ b/apps/nexus/nexusview.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.27 2004/12/15 16:37:55 ponchio +Optimizing realtime vis. + Revision 1.26 2004/12/15 13:50:32 ponchio Optimizing realtime vis. @@ -205,7 +208,11 @@ int main(int argc, char *argv[]) { cerr << "Could not load nexus file: " << argv[1] << endl; return -1; } + Sphere3f sphere = nexus.sphere; + Extraction extraction; + DrawContest contest; + Stats stats; if(!init(argv[1])) { cerr << "Could not init SDL window\n"; @@ -244,11 +251,11 @@ int main(int argc, char *argv[]) { bool show_statistics = true; bool extract = true; - NexusMt::MetricKind metric; - NexusMt::Mode mode = NexusMt::SMOOTH; + // NexusMt::MetricKind metric; + //DrawContest::Mode mode = DrawContest::SMOOTH; - nexus.SetError(error); - nexus.SetMetric(NexusMt::FRUSTUM); + //nexus.SetError(error); + // nexus.SetMetric(NexusMt::FRUSTUM); if(!nexus.InitGL()) { cerr << "Could not init glew.\n"; } @@ -274,50 +281,52 @@ int main(int argc, char *argv[]) { watch.Start(); while( !quit ) { - unsigned int anything = SDL_PollEvent(&event); - if(!anything && !keepdrawing) { - SDL_WaitEvent(&event); - anything = true; - } - if(anything) { - switch( event.type ) { - case SDL_QUIT: quit = 1; break; - case SDL_KEYDOWN: - switch(event.key.keysym.sym) { - case SDLK_RCTRL: - case SDLK_LCTRL: track.ButtonDown(Trackball::KEY_CTRL); break; - case SDLK_q: exit(0); break; - case SDLK_k: keepdrawing = !keepdrawing; break; - case SDLK_e: extract = !extract; break; - case SDLK_c: show_colors = !show_colors; break; - case SDLK_n: show_normals = !show_normals; break; - - case SDLK_LEFT: nexus.patches.ram_max *= 0.8; break; - case SDLK_RIGHT: nexus.patches.ram_max *= 1.3; break; - case SDLK_UP: nexus.draw_max *= 1.3; break; - case SDLK_DOWN: nexus.draw_max *= 0.8; break; - case SDLK_PAGEUP: nexus.disk_max *= 1.3; break; - case SDLK_PAGEDOWN: nexus.disk_max *= 0.8; break; + unsigned int anything = SDL_PollEvent(&event); + if(!anything && !keepdrawing) { + SDL_WaitEvent(&event); + anything = true; + } + if(anything) { + switch( event.type ) { + case SDL_QUIT: quit = 1; break; + case SDL_KEYDOWN: + switch(event.key.keysym.sym) { + case SDLK_RCTRL: + case SDLK_LCTRL: track.ButtonDown(Trackball::KEY_CTRL); break; + case SDLK_q: exit(0); break; + case SDLK_k: keepdrawing = !keepdrawing; break; + case SDLK_e: extract = !extract; break; + case SDLK_c: show_colors = !show_colors; break; + case SDLK_n: show_normals = !show_normals; break; + + case SDLK_LEFT: nexus.MaxRam() *= 0.8; break; + case SDLK_RIGHT: nexus.MaxRam() *= 1.3; break; + case SDLK_UP: extraction.draw_max *= 1.3; break; + case SDLK_DOWN: extraction.draw_max *= 0.8; break; + case SDLK_PAGEUP: extraction.disk_max *= 1.3; break; + case SDLK_PAGEDOWN: extraction.disk_max *= 0.8; break; + case SDLK_0: extraction.extr_max *= 1.3; break; + case SDLK_9: extraction.extr_max *= 0.8; break; - case SDLK_s: metric = NexusMt::FRUSTUM; break; - case SDLK_p: mode = NexusMt::POINTS; nexus.SetMode(mode); break; - case SDLK_d: mode = NexusMt::PATCHES; nexus.SetMode(mode); break; - case SDLK_f: mode = NexusMt::FLAT; nexus.SetMode(mode); break; - case SDLK_m: mode = NexusMt::SMOOTH; nexus.SetMode(mode); break; + // case SDLK_s: metric = NexusMt::FRUSTUM; break; + case SDLK_p: contest.mode = DrawContest::POINTS; break; + case SDLK_d: contest.mode = DrawContest::PATCHES; break; + case SDLK_f: contest.mode = DrawContest::FLAT; break; + case SDLK_m: contest.mode = DrawContest::SMOOTH; break; case SDLK_r: case SDLK_SPACE: rotate = !rotate; break; case SDLK_MINUS: - error *= 0.9f; - nexus.SetError(error); - cerr << "Error: " << error << endl; break; + extraction.target_error *= 0.9f; + cerr << "Error: " << extraction.target_error << endl; + break; case SDLK_EQUALS: case SDLK_PLUS: - error *= 1.1f; - nexus.SetError(error); - cerr << "Error: " << error << endl; break; + extraction.target_error *= 1.1f; + cerr << "Error: " << extraction.target_error << endl; + break; } break; case SDL_KEYUP: @@ -399,23 +408,12 @@ int main(int argc, char *argv[]) { glColor3f(0.8f, 0.8f, 0.8f); - - //nexus.SetPolicy(policy, error); - nexus.SetComponent(NexusMt::COLOR, show_colors); - nexus.SetComponent(NexusMt::NORMAL, show_normals); - - static vector cells; - //watch.Start(); if(extract) { - // nexus.patches.Flush(); - - nexus.metric->GetView(); - // nexus.policy.Init(); - nexus.tri_total = 0; - nexus.tri_rendered = 0; - nexus.Extract(cells); - } - nexus.Draw(cells); + extraction.frustum.GetView(); + extraction.metric->GetView(); + extraction.Extract(&nexus); + } + nexus.Render(extraction, contest, &stats); /* if(show_borders) { for(unsigned int i = 0; i < cells.size(); i++) { @@ -452,26 +450,36 @@ int main(int argc, char *argv[]) { double ftime = (tframe[(offset+4)%5] - tframe[(offset)%5])/5.0f; - /* sprintf(buffer, "Ram size : %.3fMb (max) %.3fMb (cur)", - nexus.patches->ram_size * nexus.chunk_size/(float)(1<<20), - nexus.patches->ram_used * nexus.chunk_size/(float)(1<<20)); - gl_print(0.03, 0.12, buffer);*/ + sprintf(buffer, "Ram size : %.3fMb (max) %.3fMb (cur)", + nexus.ram_max * nexus.chunk_size/(float)(1<<20), + nexus.ram_used * nexus.chunk_size/(float)(1<<20)); + gl_print(0.03, 0.15, buffer); - sprintf(buffer, "Ram size: %.3fMb(max) %.3fMb(cur)", - nexus.patches.ram_max * nexus.chunk_size/(float)(1<<20), - nexus.patches.ram_used * nexus.chunk_size/(float)(1<<20)); + sprintf(buffer, "Extr size: %.3fMb(max) %.3fMb(cur)", + extraction.extr_max * nexus.chunk_size/(float)(1<<20), + extraction.extr_used * nexus.chunk_size/(float)(1<<20)); + gl_print(0.03, 0.12, buffer); + + sprintf(buffer, "Draw size: %.3fMb(max) %.3fMb(cur)", + extraction.draw_max * nexus.chunk_size/(float)(1<<20), + extraction.draw_used * nexus.chunk_size/(float)(1<<20)); gl_print(0.03, 0.09, buffer); - sprintf(buffer, "Vbo size : %.3fMb(cur) Load: %.4fK Pref: %.4fK", - nexus.patches.vbo_used * nexus.chunk_size/(float)(1<<20), - nexus.prefetch.loading, nexus.prefetch.prefetching); + sprintf(buffer, "Disk size: %.3fMb(max) %.3fMb(cur)", + extraction.disk_max * nexus.chunk_size/(float)(1<<20), + extraction.disk_used * nexus.chunk_size/(float)(1<<20)); gl_print(0.03, 0.06, buffer); + // sprintf(buffer, "Vbo size : %.3fMb(cur) Load: %.4fK Pref: %.4fK", + // nexus.patches.vbo_used * nexus.chunk_size/(float)(1<<20), + // nexus.prefetch.loading, nexus.prefetch.prefetching); + // gl_print(0.03, 0.06, buffer); + sprintf(buffer, "Triangles: %.2fK (tot) %.2fK (vis) " - "%.3f time %.2f FPS", - nexus.tri_total/(float)(1<<10), - nexus.tri_rendered/(float)(1<<10), - ftime, 1/ftime); + " %.2f FPS", + stats.ktri/(float)(1<<10), + stats.ktri/(float)(1<<10), + stats.fps); gl_print(0.03, 0.03, buffer); glEnable(GL_DEPTH_TEST); diff --git a/apps/nexus/nxsalgo.cpp b/apps/nexus/nxsalgo.cpp index 9f79d6b3..f1577184 100644 --- a/apps/nexus/nxsalgo.cpp +++ b/apps/nexus/nxsalgo.cpp @@ -5,6 +5,7 @@ //#include #include "nxsalgo.h" +#include "vfile.h" #include "nexus.h" #include "watch.h" @@ -35,7 +36,7 @@ void nxs::ComputeNormals(Nexus &nexus) { exit(0); } - for(unsigned int p = 0; p < nexus.index.size(); p++) { + for(unsigned int p = 0; p < nexus.size(); p++) { Border border = nexus.GetBorder(p); tmpb_start.push_back(tmpb_offset); tmpb_offset += border.Size(); @@ -50,10 +51,10 @@ void nxs::ComputeNormals(Nexus &nexus) { //first step normals in the same patch. cerr << "First Step\n"; - Report report(nexus.index.size(), 5); + Report report(nexus.size(), 5); vector normals; - for(unsigned int p = 0; p < nexus.index.size(); p++) { + for(unsigned int p = 0; p < nexus.size(); p++) { report.Step(p); Patch &patch = nexus.GetPatch(p); @@ -166,8 +167,8 @@ void nxs::ComputeNormals(Nexus &nexus) { //Second step unify normals across borders cerr << "Second step\n"; - report.Init(nexus.index.size()); - for(unsigned int p = 0; p < nexus.index.size(); p++) { + report.Init(nexus.size()); + for(unsigned int p = 0; p < nexus.size(); p++) { report.Step(p); Patch &patch = nexus.GetPatch(p); Border border = nexus.GetBorder(p); diff --git a/apps/nexus/nxsbuilder.cpp b/apps/nexus/nxsbuilder.cpp index caa6946e..6d898025 100644 --- a/apps/nexus/nxsbuilder.cpp +++ b/apps/nexus/nxsbuilder.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.11 2004/12/13 00:44:48 ponchio +Lotsa changes... + Revision 1.10 2004/12/09 22:33:28 ponchio Different splitting optimization. @@ -93,7 +96,7 @@ void SaveFragment(Nexus &nexus, VChain &chain, Fragment &fragin, Fragment &fragout); -void ReverseHistory(vector &history); +void ReverseHistory(vector &history); unsigned int current_level; @@ -285,7 +288,7 @@ void ThirdStep(const string &crudefile, const string &output, Nexus nexus; //TODO here i really need no ram_buffer..... - nexus.MaxRamBuffer(0); + nexus.MaxRam() = 0; if(!nexus.Create(output, NXS_FACES, chunk_size)) { cerr << "Could not create nexus output: " << output << endl; getchar(); @@ -341,7 +344,7 @@ void ThirdStep(const string &crudefile, const string &output, memcpy(patch.FaceBegin(), &*faces.begin(), fcount * sizeof(short)); memcpy(patch.VertBegin(), &*vertices.begin(), vcount * sizeof(Point3f)); - Sphere3f &sphere = nexus.index[patch_idx].sphere; + Sphere3f &sphere = nexus[patch_idx].sphere; for(int i = 0; i < vertices.size(); i++) sphere.Add(vertices[i]); sphere.Radius() *= 1.01; @@ -367,21 +370,21 @@ void ThirdStep(const string &crudefile, const string &output, } //we can now update bounding sphere. - for(unsigned int i = 0; i < nexus.index.size(); i++) - nexus.sphere.Add(nexus.index[i].sphere); + for(unsigned int i = 0; i < nexus.size(); i++) + nexus.sphere.Add(nexus[i].sphere); - Nexus::Update update; - for(unsigned int i = 1; i < nexus.index.size(); i++) { + History::Update update; + for(unsigned int i = 1; i < nexus.size(); i++) { update.created.push_back(i); } - nexus.history.push_back(update); + nexus.history.updates.push_back(update); update.created.clear(); update.created.push_back(0); - for(unsigned int i = 1; i < nexus.index.size(); i++) { + for(unsigned int i = 1; i < nexus.size(); i++) { update.erased.push_back(i); } - nexus.history.push_back(update); + nexus.history.updates.push_back(update); if(!vert_index.Save(output + ".rvi")) { cerr << "Could not save: " << output << ".rvi\n"; @@ -397,7 +400,7 @@ void FourthStep(const string &crudefile, const string &output, cerr << "Could not load nexus " << output << endl; exit(0); } - nexus.MaxRamBuffer(ram_buffer); + nexus.MaxRam() = ram_buffer / nexus.chunk_size; //TODO Clear borders in case of failure! VFile vert_remap; @@ -411,11 +414,11 @@ void FourthStep(const string &crudefile, const string &output, cerr << "Could not load index\n"; exit(0); } - Report report(nexus.index.size()); + Report report(nexus.size()); - for(int start = 0; start < nexus.index.size(); start++) { + for(int start = 0; start < nexus.size(); start++) { report.Step(start); - PatchInfo &s_entry = nexus.index[start]; + Entry &s_entry = nexus[start]; vector links; #ifdef WIN32 @@ -428,10 +431,10 @@ void FourthStep(const string &crudefile, const string &output, vremap[global] = i; } - for(int end = 0; end < nexus.index.size(); end++) { + for(int end = 0; end < nexus.size(); end++) { if(start == end) continue; - PatchInfo &e_entry = nexus.index[end]; + Entry &e_entry = nexus[end]; float dist = Distance(s_entry.sphere, e_entry.sphere); if(dist > s_entry.sphere.Radius() + e_entry.sphere.Radius()) { @@ -451,7 +454,7 @@ void FourthStep(const string &crudefile, const string &output, } //TODO Horribili visu (interfaccia di cacca!) nexus.borders.ResizeBorder(start, 3 * links.size()); - nexus.borders.borders[start].border_used = links.size(); + nexus.borders[start].used = links.size(); Border border = nexus.GetBorder(start); memcpy(&(border[0]), &*links.begin(), links.size() * sizeof(Link)); } @@ -471,22 +474,22 @@ void FifthStep(const string &crudefile, const string &output, cerr << "Could not load nexus " << output << endl; exit(0); } - nexus.MaxRamBuffer(ram_buffer); + nexus.MaxRam() = ram_buffer / nexus.chunk_size; VChain vchain; if(!vchain.Load(output + ".vchain")) { cerr << "Could not load : " << output << ".vchain\n"; exit(0); } - nexus.history.clear(); - Nexus::Update update; - for(unsigned int i = 0; i < nexus.index.size(); i++) { + nexus.history.Clear(); + History::Update update; + for(unsigned int i = 0; i < nexus.size(); i++) { update.created.push_back(i); patch_levels.push_back(0); } - nexus.history.push_back(update); + nexus.history.updates.push_back(update); nexus.Unify(); - nexus.patches.Flush(); + nexus.Flush(); Dispatcher dispatcher(&nexus, &vchain); @@ -502,7 +505,7 @@ void FifthStep(const string &crudefile, const string &output, current_level = level; cerr << "Level: " << level << endl; - unsigned int newoffset = nexus.index.size(); + unsigned int newoffset = nexus.size(); BuildLevel(vchain, nexus, oldoffset, scaling, patch_size, patch_threshold, 65000, optimization_steps); @@ -571,8 +574,8 @@ void FifthStep(const string &crudefile, const string &output, for(s = fcells.begin(); s != fcells.end(); s++) update.erased.push_back(*s); } - nexus.history.push_back(update); - ReverseHistory(nexus.history); + nexus.history.updates.push_back(update); + ReverseHistory(nexus.history.updates); // TestBorders(nexus); nexus.Close(); @@ -719,7 +722,7 @@ void BuildFragment(Nexus &nexus, VPartition &part, int nnears = 10; if(part.size() < 10) nnears = part.size(); for(f = patches.begin(); f != patches.end(); f++) { - Point3f ¢er = nexus.index[*f].sphere.Center(); + Point3f ¢er = nexus[*f].sphere.Center(); part.Closest(center, nnears, nears, dists); for(int i = 0; i < nnears; i++) seeds.insert(nears[i]); @@ -737,7 +740,7 @@ void SaveFragment(Nexus &nexus, VChain &chain, set orig_patches; - Nexus::Update update; + History::Update update; for(unsigned int i = 0; i < fragin.pieces.size(); i++) { NxsPatch &patch = fragin.pieces[i]; update.erased.push_back(patch.patch); @@ -756,7 +759,7 @@ void SaveFragment(Nexus &nexus, VChain &chain, patch.face.size()/3, bordsize); patch_levels.push_back(current_level); - PatchInfo &entry = nexus.index[patch_idx]; + Entry &entry = nexus[patch_idx]; entry.error = fragout.error; patch_remap[i] = patch_idx; @@ -784,7 +787,7 @@ void SaveFragment(Nexus &nexus, VChain &chain, memcpy(patch.VertBegin(), &outpatch.vert[0], outpatch.vert.size() * sizeof(Point3f)); - PatchInfo &entry = nexus.index[patch_idx]; + Entry &entry = nexus[patch_idx]; for(unsigned int v = 0; v < outpatch.vert.size(); v++) { entry.sphere.Add(outpatch.vert[v]); nexus.sphere.Add(outpatch.vert[v]); @@ -866,16 +869,16 @@ void SaveFragment(Nexus &nexus, VChain &chain, border[bstart++] = link; } } - nexus.history.push_back(update); + nexus.history.updates.push_back(update); } -void ReverseHistory(vector &history) { - vector revert = history; +void ReverseHistory(vector &history) { + vector revert = history; history.clear(); for(int i = revert.size()-1; i >= 0; i--) history.push_back(revert[i]); //std::reverse(history.begin(), history.end()); - vector::iterator i; + vector::iterator i; for(i = history.begin(); i != history.end(); i++) swap((*i).erased, (*i).created); } diff --git a/apps/nexus/nxsedit.cpp b/apps/nexus/nxsedit.cpp index ac487d5e..4e20db5d 100644 --- a/apps/nexus/nxsedit.cpp +++ b/apps/nexus/nxsedit.cpp @@ -216,7 +216,7 @@ int main(int argc, char *argv[]) { cerr << "Could not open nexus file: " << input << "\n"; return -1; } - nexus.MaxRamBuffer(ram_size); + nexus.MaxRam() = ram_size / nexus.chunk_size; //Sanity tests @@ -263,7 +263,7 @@ int main(int argc, char *argv[]) { << "\n\tData : " << (int)((nexus.signature&NXS_DATA32) !=0) << "\n\n\tVertices: " << nexus.totvert << "\tFaces: " << nexus.totface - << "\tPatches: " << nexus.index.size() + << "\tPatches: " << nexus.size() << "\n\tSphere: " << nexus.sphere.Center()[0] << " " << nexus.sphere.Center()[1] << " " @@ -315,22 +315,22 @@ int main(int argc, char *argv[]) { Nexus out; if(!chunk_size) - chunk_size = nexus.patches.chunk_size; + chunk_size = nexus.chunk_size; if(!out.Create(output, (Signature)signature, chunk_size)) { cerr << "Could not open output: " << output << endl; return -1; } - out.MaxRamBuffer(ram_size); + out.MaxRam() = ram_size / out.chunk_size; //TODO set rambuffer low (or even direct access!) - Report report(nexus.index.size()); + Report report(nexus.size()); cout << "Copying and allocating...\n"; - for(unsigned int patch = 0; patch < nexus.index.size(); patch++) { + for(unsigned int patch = 0; patch < nexus.size(); patch++) { report.Step(patch); - PatchInfo &src_entry = nexus.index[patch]; - Patch src_patch = nexus.GetPatch(patch); + Entry &src_entry = nexus[patch]; + Patch &src_patch = nexus.GetPatch(patch); Border src_border = nexus.GetBorder(patch); @@ -343,9 +343,9 @@ int main(int argc, char *argv[]) { out.AddPatch(src_entry.nvert, src_entry.nface, src_border.Available()); - PatchInfo &dst_entry = out.index[patch]; + Entry &dst_entry = out[patch]; - Patch dst_patch = out.GetPatch(patch); + Patch &dst_patch = out.GetPatch(patch); //copy vertices: memcpy(dst_patch.VertBegin(), src_patch.VertBegin(), @@ -396,8 +396,8 @@ int main(int argc, char *argv[]) { if(link.IsNull()) continue; assert(link.end_patch < nexus.index.size()); }*/ - Border dst_border = out.GetBorder(patch); out.borders.ResizeBorder(patch, src_border.Size()); + Border dst_border = out.GetBorder(patch); memcpy(dst_border.Start(), src_border.Start(), src_border.Size() * sizeof(Link)); } @@ -416,9 +416,9 @@ int main(int argc, char *argv[]) { } if(qvertex && add_normals) { - report.Init(nexus.index.size()); + report.Init(nexus.size()); cout << "Quantizing vertices\n"; - for(unsigned int patch = 0; patch < nexus.index.size(); patch++) { + for(unsigned int patch = 0; patch < nexus.size(); patch++) { report.Step(patch); Patch src_patch = nexus.GetPatch(patch); @@ -430,7 +430,12 @@ int main(int argc, char *argv[]) { } out.sphere = nexus.sphere; - out.history = nexus.history; + + //Fixing history + unsigned int h_size; + char *buffer = nexus.history.Save(h_size); + out.history.Load(h_size, buffer); + // out.history = nexus.history; out.Close(); nexus.Close(); diff --git a/apps/nexus/pserver.cpp b/apps/nexus/pserver.cpp index bdbc67b5..f1677327 100644 --- a/apps/nexus/pserver.cpp +++ b/apps/nexus/pserver.cpp @@ -4,31 +4,26 @@ using namespace std; using namespace nxs; +bool PServer::Create(const std::string &_filename, + Signature _signature, + unsigned int _chunk_size) { + signature = _signature; + chunk_size = _chunk_size; -bool PServer::Create(const std::string &filename, - Signature sig, - unsigned int csize, - unsigned int rsize) { - signature = sig; - chunk_size = csize; - - ram_max = rsize/chunk_size + 1; ram_used = 0; return MFile::Create(filename); } -bool PServer::Load(const std::string &filename, Signature sig, - unsigned int csize, bool readonly, - unsigned int rsize) { +bool PServer::Load(const std::string &filename, Signature _signature, + bool _readonly, unsigned int _chunk_size) { - signature = sig; - chunk_size = csize; + signature = _signature; + chunk_size = _chunk_size; - ram_max = rsize/chunk_size + 1; ram_used = 0; - return MFile::Load(filename, readonly); + return MFile::Load(filename, _readonly); } void PServer::Close() { @@ -40,23 +35,21 @@ void PServer::Close() { bool PServer::ReadEntries(FILE *fp) { unsigned int n; fread(&n, 1, sizeof(int), fp); - entries.resize(n); + resize(n); for(unsigned int i = 0; i < n; i++) { - fread(&(entries[i].patch_start), 1, sizeof(unsigned int), fp); - fread(&(entries[i].ram_size), 1, sizeof(unsigned short), fp); - fread(&(entries[i].disk_size), 1, sizeof(unsigned short), fp); - entries[i].patch = NULL; + Entry &entry = operator[](i); + fread(&entry, sizeof(Entry), 1, fp); + entry.patch = NULL; } return true; } bool PServer::WriteEntries(FILE *fp) { - unsigned int n = entries.size(); + unsigned int n = size(); fwrite(&n, 1, sizeof(int), fp); - for(unsigned int i = 0; i < entries.size(); i++) { - fwrite(&(entries[i].patch_start), 1, sizeof(unsigned int), fp); - fwrite(&(entries[i].ram_size), 1, sizeof(unsigned short), fp); - fwrite(&(entries[i].disk_size), 1, sizeof(unsigned short), fp); + for(unsigned int i = 0; i < size(); i++) { + Entry &entry = operator[](i); + fwrite(&entry, sizeof(Entry), 1, fp); } return true; } @@ -66,17 +59,19 @@ void PServer::AddPatch(unsigned short nvert, unsigned short nface) { entry.patch_start = 0xffffffff; entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size); entry.disk_size = 0xffff; + entry.nvert = nvert; + entry.nface = nface; + //sphere and error undefined. entry.patch = NULL; - entries.push_back(entry); + entry.vbo_array = 0; + entry.vbo_element = 0; + + push_back(entry); } -Patch *PServer::LoadPatch(unsigned int idx, - unsigned short nvert, unsigned short nface) { - - // ramlock.rdlock(); - - assert(idx < entries.size()); - Entry &entry = entries[idx]; +Patch *PServer::LoadPatch(unsigned int idx) { + assert(idx < size()); + Entry &entry = operator[](idx); if(entry.patch) return entry.patch; char *ram = new char[entry.ram_size * chunk_size]; @@ -87,18 +82,18 @@ Patch *PServer::LoadPatch(unsigned int idx, } #endif - Patch *patch = new Patch(signature, ram, nvert, nface); - + Patch *patch = new Patch(signature, ram, entry.nvert, entry.nface); + if(entry.patch_start != 0xffffffff) { //was allocated. assert(entry.disk_size != 0xffff); - - SetPosition((int64)entry.patch_start * (int64)chunk_size); + + MFile::SetPosition((int64)entry.patch_start * (int64)chunk_size); if((signature & NXS_COMPRESSED) == 0) { //not compressed - ReadBuffer(ram, entry.disk_size * chunk_size); + MFile::ReadBuffer(ram, entry.disk_size * chunk_size); } else { unsigned char *disk = new unsigned char[entry.disk_size * chunk_size]; - ReadBuffer(disk, entry.disk_size * chunk_size); + MFile::ReadBuffer(disk, entry.disk_size * chunk_size); patch->Decompress(entry.ram_size * chunk_size, disk, entry.disk_size * chunk_size); @@ -110,46 +105,127 @@ Patch *PServer::LoadPatch(unsigned int idx, return patch; } -void PServer::FlushPatch(unsigned int id, Patch *patch) { +void PServer::FlushPatch(unsigned int id) { + Entry &entry = operator[](id); //TODO move this into an assert!!!! - if(!patch) return; - Entry &entry = entries[id]; -// cerr << "entry: " << (void *)(entry.patch) << " patch: " << (void *)patch << endl; - entry.patch = NULL; + if(!entry.patch) return; - if(!readonly) { //write back patch + + if(!MFile::IsReadOnly()) { //write back patch if((signature & NXS_COMPRESSED)) { unsigned int compressed_size; - char *compressed = patch->Compress(entry.ram_size * chunk_size, + char *compressed = entry.patch->Compress(entry.ram_size * chunk_size, compressed_size); if(entry.disk_size == 0xffff) {//allocate space assert(entry.patch_start == 0xffffffff); entry.disk_size = (unsigned int)((compressed_size-1)/chunk_size) + 1; - entry.patch_start = (unsigned int)(Length()/chunk_size); - Redim(Length() + entry.disk_size * chunk_size); + entry.patch_start = (unsigned int)( MFile::Length()/chunk_size); + MFile::Redim(MFile::Length() + entry.disk_size * chunk_size); } else { //cerr << "OOOOPSPPPS not supported!" << endl; exit(-1); } - SetPosition((int64)entry.patch_start * (int64)chunk_size); - WriteBuffer(compressed, entry.disk_size * chunk_size); + MFile::SetPosition((int64)entry.patch_start * (int64)chunk_size); + MFile::WriteBuffer(compressed, entry.disk_size * chunk_size); delete []compressed; } else { if(entry.disk_size == 0xffff) { entry.disk_size = entry.ram_size; - entry.patch_start = (unsigned int)(Length()/chunk_size); - Redim(Length() + entry.disk_size * chunk_size); + entry.patch_start = (unsigned int)(MFile::Length()/chunk_size); + MFile::Redim(MFile::Length() + entry.disk_size * chunk_size); } - SetPosition((int64)entry.patch_start * (int64)chunk_size); - WriteBuffer(patch->start, entry.disk_size * chunk_size); + MFile::SetPosition((int64)entry.patch_start * (int64)chunk_size); + MFile::WriteBuffer(entry.patch->start, entry.disk_size * chunk_size); } } - delete [](patch->start); - delete patch; + delete [](entry.patch->start); + delete entry.patch; + entry.patch = NULL; ram_used -= entry.ram_size; } - -void PServer::MaxRamBuffer(unsigned int r_buffer) { - ram_max = (unsigned int)(r_buffer/chunk_size) + 1; + +bool PServer::IsLoaded(unsigned int patch) { + return operator[](patch).patch != NULL; } + +Entry &PServer::Lookup(unsigned int patch, std::vector &flush) { + Entry &entry = operator[](patch); + if(index.count(patch)) { + list::iterator &i = index[patch]; + pqueue.erase(i); + pqueue.push_front(patch); + assert(entry.patch); + } else { + while(ram_used > ram_max) { + unsigned int to_flush = pqueue.back(); + pqueue.pop_back(); + //TODO i should not flush current extraction! + //CRITICAL actually works just if ram_max is big enough. + index.erase(to_flush); + FlushPatch(to_flush); + flush.push_back(to_flush); + } + assert(!entry.patch); + entry.patch = LoadPatch(patch); + pqueue.push_front(patch); + list::iterator i = pqueue.begin(); + index[patch] = i; + } + return entry; +} + +void PServer::Flush() { + std::map::iterator>::iterator i; + for(i = index.begin(); i != index.end(); i++) { + unsigned int patch = *((*i).second); + Item &item = *((*i).second); + FlushVbo(patch); + FlushPatch(patch); + } + + pqueue.clear(); + index.clear(); +} + +void PServer::LoadVbo(unsigned int npatch) { +//WORKING if(!vbo_max) return; + Entryg &entry = operator[](npatch); + Patch &patch = *entry.patch; + glGenBuffersARB(1, &entry.vbo_element); + assert(entry.vbo_element); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, entry.vbo_element); + + unsigned int size = patch.nf * sizeof(unsigned short); + if((signature & NXS_FACES) != 0) size *= 3; + + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, size, patch.FaceBegin(), + GL_STATIC_DRAW_ARB); + vbo_used += size; + + //TODO fix this when we allow data :p + size = sizeof(float) * patch.dstart; + + glGenBuffersARB(1, &entry.vbo_array); + assert(entry.vbo_array); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, entry.vbo_array); + + glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, patch.VertBegin(), + GL_STATIC_DRAW_ARB); + + vbo_used += size; +} +void PServer::FlushVbo(unsigned int npatch) { + Entryg &entry = operator[](npatch); + if(!entry.vbo_element) return; + glDeleteBuffersARB(1, &entry.vbo_element); + glDeleteBuffersARB(1, &entry.vbo_array); + entry.vbo_element = 0; + entry.vbo_array = 0; + + Patch &patch = *entry.patch; + vbo_used -= patch.nf * sizeof(unsigned short); + vbo_used -= sizeof(float) * patch.dstart; +} + + diff --git a/apps/nexus/pserver.h b/apps/nexus/pserver.h index 32f2dffc..4d1c5ee8 100644 --- a/apps/nexus/pserver.h +++ b/apps/nexus/pserver.h @@ -2,81 +2,95 @@ #define NXS_PSERVER_H #include +#include #include #include + #include "patch.h" #include "mfile.h" -namespace nxs { +namespace nxs { -class PServer: public MFile { - public: + /* HEader fo pserver + 1Kb riservato per dati globali: + Magic: 'n' 'x' 's' 0x00 + Signature: unsigned int (maschera di bit) + Chunk size: unsigned int + Index offset: unsigned int (offset to the index begin, + must be a multiple of chunk size) + Index size: unsigned int (in number of entryies) + History mode: unsigned int 0 means erased and created + 1 means ready for drawing + History offset: unsigned int: multiple of chunk_size + History size: unsigned int (in chars) + + Tot vert: unsigned int + Tot face: unsigned int + Bound sphere: Sphere3f (4 float: Point3f center (x, y, z), (radius))*/ + + + +struct Entry { + unsigned int patch_start; //granularita' Chunk + unsigned short ram_size; //in chunks + unsigned short disk_size; // in chunks (used when compressed) + + unsigned short nvert; + unsigned short nface; - struct Entry { - unsigned int patch_start; //granularita' Chunk - unsigned short ram_size; //in chunks - unsigned short disk_size; // in chunks (used when compressed) - Patch *patch; - }; + vcg::Sphere3f sphere; + float error; - /* struct Data { - // unsigned int npatch; - Patch *patch; - unsigned int vbo_array; - unsigned int vbo_element; - Data(): patch(NULL), vbo_array(0), vbo_element(0) {} - };*/ + Patch *patch; + unsigned int vbo_array; + unsigned int vbo_element; +}; + + class PServer: public IndexFile pqueue; + std::map::iterator> index; - - Signature signature; unsigned int chunk_size; unsigned int ram_max; unsigned int ram_used; - std::vector entries; - PServer(): chunk_size(1024), - ram_max(128000000), - ram_used(0) {} - virtual ~PServer() { - MFile::Close(); - } + ram_max(128000000), + ram_used(0) {} + + ~PServer() { PServer::Close(); } bool Create(const std::string &filename, Signature signature, - unsigned int chunk_size, unsigned int ram_max = 128000000); - bool Load(const std::string &filename, Signature sig, - unsigned int chunk_size, bool readonly, - unsigned int ram_max = 128000000); + unsigned int chunk_size = 1024); + bool Load(const std::string &filename, Signature signature, + bool readonly = true, unsigned int chunk_size = 1024); + void Close(); bool ReadEntries(FILE *fp); bool WriteEntries(FILE *fp); - virtual void Close(); + void AddPatch(unsigned short nvert, unsigned short nface); - Patch *LoadPatch(unsigned int id, unsigned short nv, unsigned short nf); - void FlushPatch(unsigned int id, Patch *patch); - - virtual bool IsLoaded(unsigned int patch) = 0; - // virtual Patch &Lookup(unsigned int patch, - // unsigned short nv, unsigned short nf) = 0; - virtual void Flush() = 0; + Patch *LoadPatch(unsigned int id); + void FlushPatch(unsigned int id); + void Flush(); + + bool IsLoaded(unsigned int patch); + Entry &Lookup(unsigned int patch, std::vector &flushed); + void LoadVbo(unsigned int patch); + void FlushVbo(unsigned int patch); + + bool IsCompressed() { return (signature & NXS_COMPRESSED) != 0; } + bool HasStrips() { return (signature & NXS_STRIP) != 0; } + bool HasColors() { return (signature & NXS_COLORS) != 0; } + bool HasNormalsShort() { return (signature & NXS_NORMALS_SHORT) != 0; } + bool HasNormalsFloat() { return (signature & NXS_NORMALS_FLOAT) != 0; } void MaxRamBuffer(unsigned int ram_buffer); - - //void GetVbo(unsigned int patch, unsigned int &elem, unsigned int &array); - //bool FlushVbo(unsigned int patch, Data &data); - //void MaxVboBuffer(unsigned int ram_buffer); }; diff --git a/apps/nexus/remapping.cpp b/apps/nexus/remapping.cpp index 1437b15a..e474c06f 100644 --- a/apps/nexus/remapping.cpp +++ b/apps/nexus/remapping.cpp @@ -245,9 +245,9 @@ void nxs::BuildLevel(VChain &chain, unsigned int totface = 0; unsigned int totvert = 0; - for(unsigned int idx = offset; idx < nexus.index.size(); idx++) { - totface += nexus.index[idx].nface; - totvert += nexus.index[idx].nvert; + for(unsigned int idx = offset; idx < nexus.size(); idx++) { + totface += nexus[idx].nface; + totvert += nexus[idx].nvert; } VPartition *fine = chain[chain.size()-1]; @@ -260,9 +260,9 @@ void nxs::BuildLevel(VChain &chain, unsigned int ncells = (unsigned int)(scaling * totface/target_size); //TODO this method for selecting the seeds is ugly! - float ratio = ncells/(float)(nexus.index.size() - offset); + float ratio = ncells/(float)(nexus.size() - offset); float cratio = 0; - for(unsigned int idx = offset; idx < nexus.index.size(); idx++) { + for(unsigned int idx = offset; idx < nexus.size(); idx++) { cratio += ratio; if(cratio > 1) { Patch patch = nexus.GetPatch(idx); @@ -296,8 +296,8 @@ void nxs::BuildLevel(VChain &chain, centroids.resize(coarse->size(), Point3f(0, 0, 0)); counts.resize(coarse->size(), 0); - Report report(nexus.index.size()); - for(unsigned int idx = offset; idx < nexus.index.size(); idx++) { + Report report(nexus.size()); + for(unsigned int idx = offset; idx < nexus.size(); idx++) { report.Step(idx); Patch patch = nexus.GetPatch(idx); for(unsigned int i = 0; i < patch.nf; i++) { diff --git a/apps/nexus/vfile.h b/apps/nexus/vfile.h index b869b1cd..eb194c71 100644 --- a/apps/nexus/vfile.h +++ b/apps/nexus/vfile.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.19 2004/12/03 01:20:56 ponchio +Debug + Revision 1.18 2004/12/01 03:24:32 ponchio Level 2. @@ -168,7 +171,7 @@ template class VFile: public MFile { queue_size = _queue_size; if(!MFile::Load(filename, rdonly)) return false; - n_elements = size/sizeof(T); + n_elements = _size/sizeof(T); return true; } diff --git a/apps/nexus/watch.h b/apps/nexus/watch.h index cbe364b5..160af708 100644 --- a/apps/nexus/watch.h +++ b/apps/nexus/watch.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.6 2004/12/15 13:50:32 ponchio +Optimizing realtime vis. + Revision 1.5 2004/12/01 16:00:35 ponchio Level 3 @@ -54,6 +57,9 @@ First draft created. ****************************************************************************/ +#ifndef VCG_WATCH_H +#define VCG_WATCH_H + #ifdef WIN32 #ifndef _WINDOWS_ #define _WINSOCKAPI_ @@ -98,3 +104,5 @@ class Report { double last; double interval; }; + +#endif