Revolution.

This commit is contained in:
Federico Ponchio 2005-01-14 15:25:29 +00:00
parent 0fde2046fc
commit 975ec6ae04
20 changed files with 1588 additions and 995 deletions

View File

@ -4,61 +4,131 @@
using namespace std; using namespace std;
using namespace nxs; using namespace nxs;
bool BorderServer::Create(const string &file) {
ram_used = 0;
return IndexFile<BorderEntry>::Create(file, 2 * sizeof(Link));
}
bool BorderServer::Load(const string &file, bool rdonly) {
ram_used = 0;
cerr << "Loading...\n";
return IndexFile<BorderEntry>::Load(file, rdonly);
}
void BorderServer::Close() {
if(!Opened()) return;
Flush();
IndexFile<BorderEntry>::Close();
}
void BorderServer::Flush() {
std::map<unsigned int, list<unsigned int>::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) { void BorderServer::AddBorder(unsigned short nbord, unsigned int used) {
BorderEntry entry; BorderEntry entry;
entry.border_start = Size(); assert((Length() % sizeof(Link)) == 0);
entry.border_size = nbord;
entry.border_used = used; entry.start = Length()/ sizeof(Link);
borders.push_back(entry); entry.size = nbord;
Resize(entry.border_start + 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) { Border BorderServer::GetBorder(unsigned int border, bool flush) {
assert(border < borders.size()); BorderEntry &entry = operator[](border);
BorderEntry &entry = borders[border]; if(index.count(border)) {
Link *start = GetRegion(entry.border_start, entry.border_size, flush); assert(entry.links);
return Border(start, entry.border_used, entry.border_size); list<unsigned int>::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<unsigned int>::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) { bool BorderServer::ResizeBorder(unsigned int border, unsigned int nbord) {
assert(nbord < 65500); assert(nbord < 65500);
assert(border < borders.size()); assert(border < size());
BorderEntry &entry = borders[border]; BorderEntry &entry = operator[](border);
if(nbord > entry.border_size) { if(nbord > entry.size) {
int capacity = nbord; int capacity = nbord;
if(capacity < entry.border_size*2) if(capacity < entry.size*2)
capacity = entry.border_size * 2; capacity = entry.size * 2;
if(capacity > 65500) if(capacity > 65500)
capacity = 65500; capacity = 65500;
unsigned int newstart = Size(); unsigned int newstart = Length()/sizeof(Link);
Resize(newstart + capacity); Redim((newstart + capacity) * sizeof(Link));
if(entry.border_used > 0) { if(entry.used > 0) {
Link *src = GetRegion(entry.border_start, entry.border_size); Link *src = GetRegion(entry.start, entry.size);
Link *dst = GetRegion(newstart, capacity, false); Link *dst = GetRegion(newstart, capacity);
memcpy(dst, src, entry.border_used * sizeof(Link)); memcpy(dst, src, entry.used * sizeof(Link));
} }
entry.border_start = newstart; entry.start = newstart;
entry.border_size = capacity; entry.size = capacity;
entry.border_used = nbord; entry.used = nbord;
return true; return true;
} }
entry.border_used = nbord; entry.used = nbord;
return false; return false;
} }
bool BorderServer::ReadEntries(FILE *fp) { void BorderServer::FlushBorder(unsigned int border) {
unsigned int n; BorderEntry &entry = operator[](border);
fread(&n, 1, sizeof(int), fp); assert(entry.links);
borders.resize(n); if(!MFile::IsReadOnly()) { //write back patch
fread(&*borders.begin(), n, sizeof(BorderEntry), fp); 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; return true;
} }
bool BorderServer::WriteEntries(FILE *fp) { void BorderServer::SaveHeader() {
unsigned int n = borders.size(); unsigned int magic = 0x3042584e; // NXB0
fwrite(&n, 1, sizeof(int), fp); WriteBuffer(&magic, sizeof(unsigned int));
fwrite(&*borders.begin(), n, sizeof(BorderEntry), fp); WriteBuffer(&offset, sizeof(int64));
return true;
} }

View File

@ -1,40 +1,58 @@
#ifndef NXS_BORDERSERVER_H #ifndef NXS_BORDERSERVER_H
#define NXS_BORDERSERVER_H #define NXS_BORDERSERVER_H
#include "vfile.h" #include <list>
#include <map>
#include "index_file.h"
#include "border.h" #include "border.h"
#include <vector>
/*nell'header ci sta scritto solo:
spazio riservato: 2 * sizeof(Link);
magic: nxb0 (4 bytes)
offset: (int64) */
namespace nxs { namespace nxs {
struct BorderEntry { struct BorderEntry {
unsigned int border_start; //granuralita' Link unsigned int start; //granuralita' Link
unsigned short border_size; //in Links unsigned short size; //in Links
unsigned short border_used; //in Links unsigned short used; //in Links
Link *links;
}; };
class BorderServer: public VFile<Link> { class BorderServer: public IndexFile<BorderEntry> {
public: 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); void AddBorder(unsigned short nbord, unsigned int used = 0);
Border GetBorder(unsigned int border, bool flush = true); Border GetBorder(unsigned int border, bool flush = true);
//return true if you need to reread border as it changed location //return true if you need to reread border as it changed location
bool ResizeBorder(unsigned int border, unsigned int nbord); bool ResizeBorder(unsigned int border, unsigned int nbord);
bool ReadEntries(FILE *fp);
bool WriteEntries(FILE *fp);
unsigned int BorderSize(unsigned int i) { unsigned int BorderSize(unsigned int i) {
return borders[i].border_used; return operator[](i).used;
} }
unsigned int BorderCapacity(unsigned int i) { 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<unsigned int> pqueue;
std::map<unsigned int, std::list<unsigned int>::iterator> index;
bool LoadHeader();
void SaveHeader();
void FlushBorder(unsigned int border);
Link *GetRegion(unsigned int start, unsigned int size); //size in links.
std::vector<BorderEntry> borders;
}; };
} }

View File

@ -20,7 +20,7 @@ class LruPServer: public PServer {
Flush(); Flush();
} }
Patch &Lookup(unsigned int patch, unsigned short nv, unsigned short nf) { Patch &Lookup(unsigned int patch) {
if(index.count(patch)) { if(index.count(patch)) {
Items::iterator &i = index[patch]; Items::iterator &i = index[patch];
Item item = *i; Item item = *i;
@ -32,12 +32,12 @@ class LruPServer: public PServer {
while(ram_used > ram_max) { while(ram_used > ram_max) {
Item item = items.back(); Item item = items.back();
index.erase(item.first); index.erase(item.first);
FlushPatch(item.first, item.second); FlushPatch(item.first);
items.pop_back(); items.pop_back();
} }
Item item; Item item;
item.first = patch; item.first = patch;
item.second = LoadPatch(patch, nv, nf); item.second = LoadPatch(patch);
items.push_front(item); items.push_front(item);
Items::iterator i = items.begin(); Items::iterator i = items.begin();
index[patch] = i; index[patch] = i;
@ -52,10 +52,10 @@ class LruPServer: public PServer {
std::map<unsigned int, Items::iterator>::iterator i; std::map<unsigned int, Items::iterator>::iterator i;
for(i = index.begin(); i != index.end(); i++) { for(i = index.begin(); i != index.end(); i++) {
Item &item = *((*i).second); Item &item = *((*i).second);
FlushPatch((*i).first, item.second); FlushPatch((*i).first);
} }
for(int k = 0; k < entries.size(); k++) for(int k = 0; k < size(); k++)
entries[k].patch = NULL; operator[](k).patch = NULL;
items.clear(); items.clear();
index.clear(); index.clear();

View File

@ -8,7 +8,7 @@ using namespace nxs;
bool MFile::Create(const string &fname, unsigned int mxs) { bool MFile::Create(const string &fname, unsigned int mxs) {
Close(); Close();
filename = fname; filename = fname;
size = 0; _size = 0;
readonly = false; readonly = false;
assert(mxs <= MFILE_MAX_SIZE); assert(mxs <= MFILE_MAX_SIZE);
max_size = mxs; max_size = mxs;
@ -20,7 +20,7 @@ bool MFile::Load(const string &fname, bool ronly) {
filename = fname; filename = fname;
readonly = ronly; readonly = ronly;
max_size = MFILE_MAX_SIZE; max_size = MFILE_MAX_SIZE;
size = 0; _size = 0;
while(1) { while(1) {
string name = Name(files.size()); string name = Name(files.size());
@ -30,11 +30,11 @@ bool MFile::Load(const string &fname, bool ronly) {
files.pop_back(); files.pop_back();
break; break;
} }
size += file->Length(); _size += file->Length();
} }
if(files.size() == 0) return false; if(files.size() == 0) return false;
if(files.size() == 1) { if(files.size() == 1) {
assert(size <= max_size); assert(_size <= max_size);
} else { } else {
//SANITY TEST //SANITY TEST
for(unsigned int i = 0; i < files.size() -2; i++) { for(unsigned int i = 0; i < files.size() -2; i++) {
@ -61,28 +61,29 @@ void MFile::Delete() {
void MFile::Redim(int64 sz) { void MFile::Redim(int64 sz) {
assert(!readonly); assert(!readonly);
if(sz > size) { if(sz > _size) {
unsigned int totfile = (unsigned int)(sz/max_size); unsigned int totfile = (unsigned int)(sz/max_size);
//TODO test rhis!!!! //TODO test rhis!!!!
while(files.size() <= totfile) { while(files.size() <= totfile) {
RedimLast(max_size); RedimLast(max_size);
assert(size == (int64)max_size * (int64)(files.size())); assert(_size == (int64)max_size * (int64)(files.size()));
AddFile(); AddFile();
} }
assert(size <= sz); assert(_size <= sz);
assert(sz - size < max_size); assert(sz - _size < max_size);
assert(files.back()->Length() + (unsigned int)(sz - size) < max_size); assert(files.back()->Length() + (unsigned int)(sz - _size) < max_size);
RedimLast(files.back()->Length() + (unsigned int)(sz - size)); RedimLast(files.back()->Length() + (unsigned int)(sz - _size));
} else { } else {
while(size - files.back()->Length() > sz) while(_size - files.back()->Length() > sz)
RemoveFile(); RemoveFile();
assert(sz <= size); assert(sz <= _size);
RedimLast(files.back()->Length() - (unsigned int)(size - sz)); RedimLast(files.back()->Length() - (unsigned int)(_size - sz));
} }
assert(sz == _size);
} }
void MFile::SetPosition(int64 pos) { void MFile::SetPosition(int64 pos) {
assert(pos < size); assert(pos <= _size);
curr_fp = (unsigned int)(pos/(int64)max_size); curr_fp = (unsigned int)(pos/(int64)max_size);
curr_pos = (unsigned int)(pos - (int64)max_size * (int64)curr_fp); curr_pos = (unsigned int)(pos - (int64)max_size * (int64)curr_fp);
assert(curr_pos < max_size); assert(curr_pos < max_size);
@ -134,7 +135,7 @@ void MFile::WriteBuffer(void *data, unsigned int sz) {
unsigned int last_size = file->Length(); unsigned int last_size = file->Length();
delete file; delete file;
files.pop_back(); files.pop_back();
size -= last_size; _size -= last_size;
cerr << "Removing file: " << name << endl; cerr << "Removing file: " << name << endl;
#ifdef WIN32 #ifdef WIN32
DeleteFile(name.c_str()); DeleteFile(name.c_str());
@ -148,7 +149,7 @@ void MFile::RedimLast(unsigned int sz) {
File &file = *files.back(); File &file = *files.back();
unsigned int last_size = (int64)file.Length(); unsigned int last_size = (int64)file.Length();
file.Redim(sz); file.Redim(sz);
size += sz - (int64)last_size; _size += sz - (int64)last_size;
} }
std::string MFile::Name(unsigned int n) { std::string MFile::Name(unsigned int n) {

View File

@ -30,13 +30,14 @@ class MFile {
void Close(); void Close();
void Delete(); void Delete();
int64 Length() { return size; } int64 Length() { return _size; }
void Redim(int64 size); void Redim(int64 size);
void SetPosition(int64 pos); void SetPosition(int64 pos);
void ReadBuffer(void *data, unsigned int size); void ReadBuffer(void *data, unsigned int size);
void WriteBuffer(void *data, unsigned int size); void WriteBuffer(void *data, unsigned int size);
bool Opened() { return files.size() > 0; }
bool IsReadOnly() { return readonly; } bool IsReadOnly() { return readonly; }
void SetReadOnly(bool rd) { readonly = rd; } //USE WITH CARE!!!! void SetReadOnly(bool rd) { readonly = rd; } //USE WITH CARE!!!!
protected: protected:
@ -44,7 +45,7 @@ class MFile {
std::vector<File *> files; std::vector<File *> files;
unsigned int curr_pos; unsigned int curr_pos;
unsigned int curr_fp; unsigned int curr_fp;
int64 size; int64 _size;
unsigned int max_size; unsigned int max_size;
bool readonly; bool readonly;
private: private:

View File

@ -4,8 +4,6 @@
#include <set> #include <set>
#include "nexus.h" #include "nexus.h"
#include "lrupserver.h"
#include "queuepserver.h"
using namespace std; using namespace std;
using namespace vcg; using namespace vcg;
@ -16,155 +14,157 @@ Nexus::~Nexus() {
} }
bool Nexus::Create(const string &file, Signature sig, unsigned int c_size) { 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; signature = sig;
totvert = 0; totvert = 0;
totface = 0; totface = 0;
sphere = Sphere3f(); sphere = Sphere3f();
index.clear();
chunk_size = c_size; chunk_size = c_size;
unsigned int header_size = 256;
if(chunk_size > header_size) header_size = chunk_size;
history.clear(); history.Clear();
ram_used = 0;
ram_max = 50 * (1<<20) / chunk_size;
if(!patches.Create(file + ".nxp", signature, chunk_size)) { if(!IndexFile<Entry>::Create(file + ".nxp", header_size)) {
cerr << "Could not create file: " << file << ".nxp" << endl; cerr << "Could not create file: " << file << ".nxp" << endl;
return false; return false;
} }
//Important: chunk_size must be 1 so that i can use Region in VFile. //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; cerr << "Could not create file: " << file << ".nxb" << endl;
return false; return false;
} }
history.clear();
return true; return true;
} }
bool Nexus::Load(const string &file, bool rdonly) { bool Nexus::Load(const string &file, bool rdonly) {
readonly = rdonly; if(!IndexFile<Entry>::Load(file + ".nxp", rdonly)) return false;
ram_used = 0;
ram_max = 50 * (1<<20) / chunk_size;
index_file = fopen((file + ".nxs").c_str(), "rb+"); history.Clear();
if(!index_file) return false; SetPosition(history_offset);
unsigned int history_size;
ReadBuffer(&history_size, sizeof(unsigned int));
unsigned int readed; char *buffer = new char[history_size];
readed = fread(&signature, sizeof(unsigned int), 1, index_file); ReadBuffer(buffer, history_size);
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 if(!history.Load(history_size, buffer)) {
readed = fread(&size, sizeof(unsigned int), 1, index_file); cerr << "Error loading history\n";
if(!readed) return false; 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<unsigned int> 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) { borders.Load(file + ".nxb", rdonly);
fclose(index_file); //TODO on nxsbuilder assure borders are loaded
index_file = NULL;
}
//TODO support readonly
if(!patches.Load(file + ".nxp", signature, chunk_size, readonly))
return false;
if(!borders.Load(file + ".nxb", readonly, 1, 500))
return false;
return true; return true;
} }
void Nexus::Close() { void Nexus::Close() {
patches.Close(); if(!Opened()) return;
borders.Close();
if(!index_file) return;
rewind(index_file); Flush();
fwrite(&signature, sizeof(unsigned int), 1, index_file); if(!IsReadOnly()) {
fwrite(&totvert, sizeof(unsigned int), 1, index_file); //set history_offset
fwrite(&totface, sizeof(unsigned int), 1, index_file); if(!size()) history_offset = 0;
fwrite(&sphere, sizeof(Sphere3f), 1, index_file); else
fwrite(&chunk_size, sizeof(unsigned int), 1, index_file); history_offset = (back().patch_start + back().disk_size);
history_offset *= chunk_size;
unsigned int size = index.size(); //size of index unsigned int history_size;
fwrite(&size, sizeof(unsigned int), 1, index_file); char *mem = history.Save(history_size);
fwrite(&(index[0]), sizeof(PatchInfo), size, index_file); Redim(history_offset + history_size + sizeof(unsigned int));
SetPosition(history_offset);
//TODO this should be moved to the end... WriteBuffer(&history_size, sizeof(unsigned int));
//BUT it will break compatibility with existing models. WriteBuffer(mem, history_size);
patches.WriteEntries(index_file); delete []mem;
borders.WriteEntries(index_file);
vector<unsigned int> 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]);
} }
borders.Close();
size = buffer.size(); IndexFile<Entry>::Close();
fwrite(&size, sizeof(unsigned int), 1, index_file);
fwrite(&(buffer[0]), sizeof(unsigned int), size, index_file);
fclose(index_file);
index_file = NULL;
} }
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<unsigned int, list<unsigned int>::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) { Patch &Nexus::GetPatch(unsigned int patch, bool flush) {
assert(patch < index.size()); Entry &entry = operator[](patch);
PatchInfo &info = index[patch]; if(index.count(patch)) {
return patches.Lookup(patch, info.nvert, info.nface); assert(entry.patch);
list<unsigned int>::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<unsigned int>::iterator i = pqueue.begin();
index[patch] = i;
}
return *(entry.patch);
} }
Border Nexus::GetBorder(unsigned int patch, bool flush) { Border Nexus::GetBorder(unsigned int patch, bool flush) {
PatchInfo &info = index[patch];
return borders.GetBorder(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); Border border = GetBorder(patch);
unsigned int pos = border.Size(); unsigned int pos = border.Size();
@ -179,27 +179,30 @@ void Nexus::AddBorder(unsigned int patch, Link &link) {
assert(border.Available() > pos); assert(border.Available() > pos);
border[pos] = link; border[pos] = link;
} }*/
unsigned int Nexus::AddPatch(unsigned int nvert, unsigned int nface, unsigned int Nexus::AddPatch(unsigned int nvert, unsigned int nface,
unsigned int nbord) { unsigned int nbord) {
PatchInfo info; Entry entry;
info.nvert = nvert; entry.patch_start = 0xffffffff;
info.nface = nface; 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); borders.AddBorder(nbord);
index.push_back(info);
totvert += nvert; totvert += nvert;
totface += nface; totface += nface;
return index.size() -1; return size() - 1;
}
void Nexus::MaxRamBuffer(unsigned int r_size) {
patches.MaxRamBuffer(r_size);
//TODO do the same with borders
} }
void Nexus::Unify(float threshold) { void Nexus::Unify(float threshold) {
@ -207,9 +210,9 @@ void Nexus::Unify(float threshold) {
unsigned int duplicated = 0; unsigned int duplicated = 0;
unsigned int degenerate = 0; unsigned int degenerate = 0;
for(unsigned int p = 0; p < index.size(); p++) { for(unsigned int p = 0; p < size(); p++) {
PatchInfo &entry = index[p]; Entry &entry = operator[](p);
Patch patch = GetPatch(p); Patch &patch = GetPatch(p);
unsigned int vcount = 0; unsigned int vcount = 0;
map<Point3f, unsigned short> vertices; map<Point3f, unsigned short> vertices;
@ -294,7 +297,7 @@ void Nexus::Unify(float threshold) {
} }
//better to compact directly borders than setting them null. //better to compact directly borders than setting them null.
//finally: there may be duplicated borders //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); Border border = GetBorder(p);
set<Link> links; set<Link> links;
for(unsigned int b = 0; b < border.Size(); b++) { for(unsigned int b = 0; b < border.Size(); b++) {
@ -307,7 +310,7 @@ void Nexus::Unify(float threshold) {
for(set<Link>::iterator k = links.begin(); k != links.end(); k++) for(set<Link>::iterator k = links.begin(); k != links.end(); k++)
border[count++] = *k; border[count++] = *k;
borders.borders[p].border_used = links.size(); borders[p].used = links.size();
} }
totvert -= duplicated; totvert -= duplicated;
@ -316,3 +319,77 @@ void Nexus::Unify(float threshold) {
if(degenerate) if(degenerate)
cerr << "Found " << degenerate << " degenerate face while unmifying\n"; 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;
}

View File

@ -3,15 +3,65 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <list>
#include <map>
#include "nexusbase.h" #include <vcg/space/sphere3.h>
#include "lrupserver.h"
#include "patch.h"
#include "index_file.h"
#include "history.h"
#include "borderserver.h" #include "borderserver.h"
namespace nxs { 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<Entry> {
public: 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() {}
~Nexus(); ~Nexus();
@ -20,12 +70,17 @@ class Nexus: public NexusBase {
unsigned int chunk_size = 1024); unsigned int chunk_size = 1024);
bool Load(const std::string &filename, bool readonly = false); bool Load(const std::string &filename, bool readonly = false);
void Close(); void Close();
void Flush(bool all = true);
unsigned int AddPatch(unsigned int nv, unsigned int nf, unsigned int nb); unsigned int AddPatch(unsigned int nv, unsigned int nf, unsigned int nb);
Patch &GetPatch(unsigned int patch, bool flush = true); Patch &GetPatch(unsigned int patch, bool flush = true);
Border GetBorder(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 IsCompressed() { return (signature & NXS_COMPRESSED) != 0; }
bool HasStrips() { return (signature & NXS_STRIP) != 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 HasNormalsShort() { return (signature & NXS_NORMALS_SHORT) != 0; }
bool HasNormalsFloat() { return (signature & NXS_NORMALS_FLOAT) != 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! std::list<unsigned int> pqueue;
void Unify(float threshold = 0.0f); std::map<unsigned int, std::list<unsigned int>::iterator> index;
Patch *LoadPatch(unsigned int id);
virtual void FlushPatch(unsigned int id);
/* Nexus data */ bool LoadHeader();
void SaveHeader();
//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<PatchInfo> index;
LruPServer patches;
BorderServer borders;
// std::vector<Update> history;
// bool readonly;
// private:
// FILE *index_file;
}; };
} }

View File

@ -39,6 +39,10 @@
<a name="picture"><h1>Big picture</h1></a> <a name="picture"><h1>Big picture</h1></a>
La truttura nexus divide la mesh in tante piccole parti.<br>
Ciascuna parte ha le facce indicizzate localmente, e sono codificate
esplicitamente le corrispondenze tra vertici di patches diverse.<br>
<a name="struct"><h1>Structures and interfaces</h1></a> <a name="struct"><h1>Structures and interfaces</h1></a>
<a name="vfile"><h2>VFile</h2></a> <a name="vfile"><h2>VFile</h2></a>
@ -46,12 +50,24 @@ VFile dovrebbe avere piu' o meno la stessa interfaccia di <em>vector</em>
ma usare un file per storare i dati (un mmapping, ma non limitato a 4Gb).<br> ma usare un file per storare i dati (un mmapping, ma non limitato a 4Gb).<br>
<a name="crude"><h2>Crude</h2></a> <a name="crude"><h2>Crude</h2></a>
<pre>
Crude e' un formato tipo il ply... solo che usa dei VFile per 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)<br> 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, Per cui e' composto di 3 files:
vertici e Bounding box), file dei vertici, file delle facce ed Header (<b>.crd</b>)
opzionalmente file degli attributi dei vertici e delle facce.<br> Magic: 'c' 'r' 'd' 0x00 (4 bytes)
Come interfaccia e' sufficente che dia accesso casuale a facce e vertici... 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...
</pre>
<a name="pchain"><h2>PChain</h2></a> <a name="pchain"><h2>PChain</h2></a>
Sta per 'partition chain' cioe' una catena di partizioni dello Sta per 'partition chain' cioe' una catena di partizioni dello
spazio.<br> spazio.<br>
@ -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').<br> ne restituisce la distanza (o un valore 'equivalente').<br>
Si deve poter salvare su disco e recuperare una pchain<br> Si deve poter salvare su disco e recuperare una pchain<br>
<a name="remap"><h2>Remap</h2></a>
E' composta da 3 files:<br>
indice delle patches: per ogni patch il numero di vertici, di facce e
di bordi<br>
vertici -> lista di patches: per ogni vertice una lista di patch
di cui fa parte (se sono + di 1 e' ovviamente di bordo.<br>
facce->patches: per ogni faccia un intero che dice in quale patch
sta.<br>
<a name="nexus"><h2>Nexus</h2></a> <a name="nexus"><h2>Nexus</h2></a>
E' una struttura con 3 files: 'index', 'patches' e 'borders'.<br> <pre>
'Index' contiene l'indice delle patches: per ogni patch viene storato E' una struttura con 2 files:
offset, size (ma questa potrebbe essere storata direttamente nei
files?) dei dati geometrici nel file delle patches e dei bordi nel File delle patches: (<b>.nxs</b>)
file dei borders, oltre alla bounding sphere.<br> 1Kb riservato per dati globali:
'Patches' e' un VFile di chunks da 4k dove i dati geometrici di una Magic: 'n' 'x' 's' 0x00
patch occupano un numero intero di chunks. P.S. Come ce la caviamo con Signature: unsigned int (maschera di bit)
gli attributi dei vertici e delle facce?<br> Chunk size: unsigned int
'Borders' e' un VFile di 'links' dove ogni link fa riferimento ad un Index offset: int64 (offset to the index begin,
vertice di bordo tra la patch A (V_a) e la B (V_b) e contiene must be a multiple of chunk size)
(V_a, V_b, B) (A e' implicito). L'informazione e' replicata nei bordi History offset: int64: multiple of chunk_size
relativi a B con (V_b, V_a, A)<br>
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)
</pre>
<br>
<a name="bmt"><h2>Bmt</h2></a> <a name="bmt"><h2>Bmt</h2></a>
Bmt (batched multi triangulation) e' il formato per la Bmt (batched multi triangulation) e' il formato per la

View File

@ -8,13 +8,13 @@
namespace nxs { namespace nxs {
struct PatchInfo { /*struct PatchInfo {
unsigned short nvert; unsigned short nvert;
unsigned short nface; unsigned short nface;
vcg::Sphere3f sphere; vcg::Sphere3f sphere;
float error; float error;
}; };*/
class NexusBase { class NexusBase {
@ -49,7 +49,7 @@ class NexusBase {
unsigned int totface; unsigned int totface;
vcg::Sphere3f sphere; vcg::Sphere3f sphere;
std::vector<PatchInfo> index; // std::vector<PatchInfo> index;
std::vector<Update> history; std::vector<Update> history;
bool readonly; bool readonly;

File diff suppressed because it is too large Load Diff

View File

@ -1,178 +1,108 @@
#ifndef NXS_NEXUS_MT_H #ifndef NXS_MT_H
#define NXS_NEXUS_MT_H #define NXS_MT_H
#include <vector> #include <vector>
#include <queue> #include <queue>
#include <wrap/gui/frustum.h> #include <wrap/gui/frustum.h>
#include "nexusbase.h" #include "nexus.h"
#include "queuepserver.h" #include "history.h"
#include "borderserver.h" #include "extraction.h"
#include "prefetch.h" #include "metric.h"
#include "preload.h"
#include "watch.h"
namespace nxs { namespace nxs {
typedef std::vector<unsigned int> Frag; struct DrawContest {
struct Node {
std::vector<Node *> in;
std::vector<Node *> out;
std::vector<Frag> frags;
float error;
bool visited;
bool current;
// bool pushed;
};
struct TNode {
float error;
Node *node;
TNode(Node *n, float e): node(n), error(e) {}
bool operator<(const TNode &n) { return error < n.error; }
};
class Metric {
public:
std::vector<PatchInfo> *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<PatchEntry> *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;
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;
enum Mode { POINTS, SMOOTH, XRAY, HIDDEN_LINE, FLAT_WIRE, FLAT, PATCHES };
enum Attr { COLOR = 0x1, NORMAL = 0x2, TEXTURE = 0x4, DATA = 0x8 };
Mode mode; Mode mode;
unsigned int attrs;
unsigned int components; DrawContest(Mode m = SMOOTH, unsigned int a = 0xf): mode(m), attrs(a) {}
bool use_normals; void SetAttr(Attr attr, bool value);
bool use_colors; bool HasComponent(Attr attr);
bool use_textures; };
bool use_data;
//statistics: struct Stats {
unsigned int tri_rendered; float ktri; //k triangles rendered.
unsigned int tri_total; float kdisk; //k readed per frame (mean)
float kdisk_peak; //k readed peak.
float fps;
float fps_peak; //low fps peaks
vector<QueuePServer::Data *> todraw; //double last_time;
std::vector<PServer::Item> visited; unsigned int count;
std::vector<Node *> sequence;
QueuePServer patches; Watch watch;
BorderServer borders;
Prefetch prefetch; Stats(): count(0) {}
void Init();
};
class NexusMt: public Nexus {
public:
bool use_vbo;
bool prefetch;
unsigned int vbo_used; //TODO remember to zero it!
Preload preload;
NexusMt(); NexusMt();
~NexusMt(); ~NexusMt();
bool Load(const std::string &filename); bool Load(const std::string &filename);
void Close(); // void Close();
bool InitGL(Vbo mode = VBO_AUTO, unsigned int vbo_size = 64000000); bool InitGL(bool use_vbo = true);
void Render(DrawContest contest = DrawContest());
void Render(Extraction &extraction,
DrawContest &contest,
Stats *stats = NULL);
// void Draw(std::vector<unsigned int> &selected);
// void Extract(std::vector<unsigned int> &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(); void Render();
bool SetMode(DrawContest::Mode mode);
bool SetComponent(DrawContest::Component c, bool on);
bool SetComponents(unsigned int mask);
void SetMetric(MetricKind kind); void SetMetric(MetricKind kind);
void SetError(float error); void SetError(float error);
void SetExtractionSize(unsigned int ram_size);
void SetPrefetchSize(unsigned int size); //Uinits expressed in Kb
void SetVboSize(unsigned int vbo_size); void SetExtractionSize(unsigned int ksize);
void SetDrawSize(unsigned int ksize);
void SetDiskDelta(unsigned int kdelta);
//void SetPrefetchSize(unsigned int size);
};*/
bool SetMode(Mode mode);
bool SetComponent(Component c, bool on);
bool SetComponents(unsigned int mask);
void Draw(std::vector<unsigned int> &selected);
void Draw(unsigned int cell, QueuePServer::Data &data);
void Extract(std::vector<unsigned int> &selected);
protected:
std::vector<Node> nodes;
bool Expand(TNode &node);
void NodeVisited(Node *node);
void LoadHistory();
void ClearHistory();
void VisitNode(Node *node, std::vector<TNode> &heap);
void UnvisitNode(Node *node, std::vector<TNode> &heap);
void Select(std::vector<unsigned int> &selected);
Patch &LoadPatch(unsigned int p);
};
} }

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $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 Revision 1.26 2004/12/15 13:50:32 ponchio
Optimizing realtime vis. Optimizing realtime vis.
@ -205,7 +208,11 @@ int main(int argc, char *argv[]) {
cerr << "Could not load nexus file: " << argv[1] << endl; cerr << "Could not load nexus file: " << argv[1] << endl;
return -1; return -1;
} }
Sphere3f sphere = nexus.sphere; Sphere3f sphere = nexus.sphere;
Extraction extraction;
DrawContest contest;
Stats stats;
if(!init(argv[1])) { if(!init(argv[1])) {
cerr << "Could not init SDL window\n"; cerr << "Could not init SDL window\n";
@ -244,11 +251,11 @@ int main(int argc, char *argv[]) {
bool show_statistics = true; bool show_statistics = true;
bool extract = true; bool extract = true;
NexusMt::MetricKind metric; // NexusMt::MetricKind metric;
NexusMt::Mode mode = NexusMt::SMOOTH; //DrawContest::Mode mode = DrawContest::SMOOTH;
nexus.SetError(error); //nexus.SetError(error);
nexus.SetMetric(NexusMt::FRUSTUM); // nexus.SetMetric(NexusMt::FRUSTUM);
if(!nexus.InitGL()) { if(!nexus.InitGL()) {
cerr << "Could not init glew.\n"; cerr << "Could not init glew.\n";
} }
@ -292,32 +299,34 @@ int main(int argc, char *argv[]) {
case SDLK_c: show_colors = !show_colors; break; case SDLK_c: show_colors = !show_colors; break;
case SDLK_n: show_normals = !show_normals; break; case SDLK_n: show_normals = !show_normals; break;
case SDLK_LEFT: nexus.patches.ram_max *= 0.8; break; case SDLK_LEFT: nexus.MaxRam() *= 0.8; break;
case SDLK_RIGHT: nexus.patches.ram_max *= 1.3; break; case SDLK_RIGHT: nexus.MaxRam() *= 1.3; break;
case SDLK_UP: nexus.draw_max *= 1.3; break; case SDLK_UP: extraction.draw_max *= 1.3; break;
case SDLK_DOWN: nexus.draw_max *= 0.8; break; case SDLK_DOWN: extraction.draw_max *= 0.8; break;
case SDLK_PAGEUP: nexus.disk_max *= 1.3; break; case SDLK_PAGEUP: extraction.disk_max *= 1.3; break;
case SDLK_PAGEDOWN: nexus.disk_max *= 0.8; 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_s: metric = NexusMt::FRUSTUM; break;
case SDLK_p: mode = NexusMt::POINTS; nexus.SetMode(mode); break; case SDLK_p: contest.mode = DrawContest::POINTS; break;
case SDLK_d: mode = NexusMt::PATCHES; nexus.SetMode(mode); break; case SDLK_d: contest.mode = DrawContest::PATCHES; break;
case SDLK_f: mode = NexusMt::FLAT; nexus.SetMode(mode); break; case SDLK_f: contest.mode = DrawContest::FLAT; break;
case SDLK_m: mode = NexusMt::SMOOTH; nexus.SetMode(mode); break; case SDLK_m: contest.mode = DrawContest::SMOOTH; break;
case SDLK_r: case SDLK_r:
case SDLK_SPACE: rotate = !rotate; break; case SDLK_SPACE: rotate = !rotate; break;
case SDLK_MINUS: case SDLK_MINUS:
error *= 0.9f; extraction.target_error *= 0.9f;
nexus.SetError(error); cerr << "Error: " << extraction.target_error << endl;
cerr << "Error: " << error << endl; break; break;
case SDLK_EQUALS: case SDLK_EQUALS:
case SDLK_PLUS: case SDLK_PLUS:
error *= 1.1f; extraction.target_error *= 1.1f;
nexus.SetError(error); cerr << "Error: " << extraction.target_error << endl;
cerr << "Error: " << error << endl; break; break;
} }
break; break;
case SDL_KEYUP: case SDL_KEYUP:
@ -399,23 +408,12 @@ int main(int argc, char *argv[]) {
glColor3f(0.8f, 0.8f, 0.8f); 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<unsigned int> cells;
//watch.Start();
if(extract) { if(extract) {
// nexus.patches.Flush(); extraction.frustum.GetView();
extraction.metric->GetView();
nexus.metric->GetView(); extraction.Extract(&nexus);
// nexus.policy.Init();
nexus.tri_total = 0;
nexus.tri_rendered = 0;
nexus.Extract(cells);
} }
nexus.Draw(cells); nexus.Render(extraction, contest, &stats);
/* if(show_borders) { /* if(show_borders) {
for(unsigned int i = 0; i < cells.size(); i++) { 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; double ftime = (tframe[(offset+4)%5] - tframe[(offset)%5])/5.0f;
/* sprintf(buffer, "Ram size : %.3fMb (max) %.3fMb (cur)", sprintf(buffer, "Ram size : %.3fMb (max) %.3fMb (cur)",
nexus.patches->ram_size * nexus.chunk_size/(float)(1<<20), nexus.ram_max * nexus.chunk_size/(float)(1<<20),
nexus.patches->ram_used * nexus.chunk_size/(float)(1<<20)); nexus.ram_used * nexus.chunk_size/(float)(1<<20));
gl_print(0.03, 0.12, buffer);*/ gl_print(0.03, 0.15, buffer);
sprintf(buffer, "Ram size: %.3fMb(max) %.3fMb(cur)", sprintf(buffer, "Extr size: %.3fMb(max) %.3fMb(cur)",
nexus.patches.ram_max * nexus.chunk_size/(float)(1<<20), extraction.extr_max * nexus.chunk_size/(float)(1<<20),
nexus.patches.ram_used * 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); gl_print(0.03, 0.09, buffer);
sprintf(buffer, "Vbo size : %.3fMb(cur) Load: %.4fK Pref: %.4fK", sprintf(buffer, "Disk size: %.3fMb(max) %.3fMb(cur)",
nexus.patches.vbo_used * nexus.chunk_size/(float)(1<<20), extraction.disk_max * nexus.chunk_size/(float)(1<<20),
nexus.prefetch.loading, nexus.prefetch.prefetching); extraction.disk_used * nexus.chunk_size/(float)(1<<20));
gl_print(0.03, 0.06, buffer); 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) " sprintf(buffer, "Triangles: %.2fK (tot) %.2fK (vis) "
"%.3f time %.2f FPS", " %.2f FPS",
nexus.tri_total/(float)(1<<10), stats.ktri/(float)(1<<10),
nexus.tri_rendered/(float)(1<<10), stats.ktri/(float)(1<<10),
ftime, 1/ftime); stats.fps);
gl_print(0.03, 0.03, buffer); gl_print(0.03, 0.03, buffer);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);

View File

@ -5,6 +5,7 @@
//#include <wrap/strip/tristrip.h> //#include <wrap/strip/tristrip.h>
#include "nxsalgo.h" #include "nxsalgo.h"
#include "vfile.h"
#include "nexus.h" #include "nexus.h"
#include "watch.h" #include "watch.h"
@ -35,7 +36,7 @@ void nxs::ComputeNormals(Nexus &nexus) {
exit(0); 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); Border border = nexus.GetBorder(p);
tmpb_start.push_back(tmpb_offset); tmpb_start.push_back(tmpb_offset);
tmpb_offset += border.Size(); tmpb_offset += border.Size();
@ -50,10 +51,10 @@ void nxs::ComputeNormals(Nexus &nexus) {
//first step normals in the same patch. //first step normals in the same patch.
cerr << "First Step\n"; cerr << "First Step\n";
Report report(nexus.index.size(), 5); Report report(nexus.size(), 5);
vector<Point3f> normals; vector<Point3f> normals;
for(unsigned int p = 0; p < nexus.index.size(); p++) { for(unsigned int p = 0; p < nexus.size(); p++) {
report.Step(p); report.Step(p);
Patch &patch = nexus.GetPatch(p); Patch &patch = nexus.GetPatch(p);
@ -166,8 +167,8 @@ void nxs::ComputeNormals(Nexus &nexus) {
//Second step unify normals across borders //Second step unify normals across borders
cerr << "Second step\n"; cerr << "Second step\n";
report.Init(nexus.index.size()); report.Init(nexus.size());
for(unsigned int p = 0; p < nexus.index.size(); p++) { for(unsigned int p = 0; p < nexus.size(); p++) {
report.Step(p); report.Step(p);
Patch &patch = nexus.GetPatch(p); Patch &patch = nexus.GetPatch(p);
Border border = nexus.GetBorder(p); Border border = nexus.GetBorder(p);

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $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 Revision 1.10 2004/12/09 22:33:28 ponchio
Different splitting optimization. Different splitting optimization.
@ -93,7 +96,7 @@ void SaveFragment(Nexus &nexus, VChain &chain,
Fragment &fragin, Fragment &fragin,
Fragment &fragout); Fragment &fragout);
void ReverseHistory(vector<Nexus::Update> &history); void ReverseHistory(vector<History::Update> &history);
unsigned int current_level; unsigned int current_level;
@ -285,7 +288,7 @@ void ThirdStep(const string &crudefile, const string &output,
Nexus nexus; Nexus nexus;
//TODO here i really need no ram_buffer..... //TODO here i really need no ram_buffer.....
nexus.MaxRamBuffer(0); nexus.MaxRam() = 0;
if(!nexus.Create(output, NXS_FACES, chunk_size)) { if(!nexus.Create(output, NXS_FACES, chunk_size)) {
cerr << "Could not create nexus output: " << output << endl; cerr << "Could not create nexus output: " << output << endl;
getchar(); getchar();
@ -341,7 +344,7 @@ void ThirdStep(const string &crudefile, const string &output,
memcpy(patch.FaceBegin(), &*faces.begin(), fcount * sizeof(short)); memcpy(patch.FaceBegin(), &*faces.begin(), fcount * sizeof(short));
memcpy(patch.VertBegin(), &*vertices.begin(), vcount * sizeof(Point3f)); 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++) for(int i = 0; i < vertices.size(); i++)
sphere.Add(vertices[i]); sphere.Add(vertices[i]);
sphere.Radius() *= 1.01; sphere.Radius() *= 1.01;
@ -367,21 +370,21 @@ void ThirdStep(const string &crudefile, const string &output,
} }
//we can now update bounding sphere. //we can now update bounding sphere.
for(unsigned int i = 0; i < nexus.index.size(); i++) for(unsigned int i = 0; i < nexus.size(); i++)
nexus.sphere.Add(nexus.index[i].sphere); nexus.sphere.Add(nexus[i].sphere);
Nexus::Update update; History::Update update;
for(unsigned int i = 1; i < nexus.index.size(); i++) { for(unsigned int i = 1; i < nexus.size(); i++) {
update.created.push_back(i); update.created.push_back(i);
} }
nexus.history.push_back(update); nexus.history.updates.push_back(update);
update.created.clear(); update.created.clear();
update.created.push_back(0); 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); update.erased.push_back(i);
} }
nexus.history.push_back(update); nexus.history.updates.push_back(update);
if(!vert_index.Save(output + ".rvi")) { if(!vert_index.Save(output + ".rvi")) {
cerr << "Could not save: " << output << ".rvi\n"; 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; cerr << "Could not load nexus " << output << endl;
exit(0); exit(0);
} }
nexus.MaxRamBuffer(ram_buffer); nexus.MaxRam() = ram_buffer / nexus.chunk_size;
//TODO Clear borders in case of failure! //TODO Clear borders in case of failure!
VFile<unsigned int> vert_remap; VFile<unsigned int> vert_remap;
@ -411,11 +414,11 @@ void FourthStep(const string &crudefile, const string &output,
cerr << "Could not load index\n"; cerr << "Could not load index\n";
exit(0); 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); report.Step(start);
PatchInfo &s_entry = nexus.index[start]; Entry &s_entry = nexus[start];
vector<Link> links; vector<Link> links;
#ifdef WIN32 #ifdef WIN32
@ -428,10 +431,10 @@ void FourthStep(const string &crudefile, const string &output,
vremap[global] = i; vremap[global] = i;
} }
for(int end = 0; end < nexus.index.size(); end++) { for(int end = 0; end < nexus.size(); end++) {
if(start == end) continue; if(start == end) continue;
PatchInfo &e_entry = nexus.index[end]; Entry &e_entry = nexus[end];
float dist = Distance(s_entry.sphere, e_entry.sphere); float dist = Distance(s_entry.sphere, e_entry.sphere);
if(dist > s_entry.sphere.Radius() + e_entry.sphere.Radius()) { 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!) //TODO Horribili visu (interfaccia di cacca!)
nexus.borders.ResizeBorder(start, 3 * links.size()); 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); Border border = nexus.GetBorder(start);
memcpy(&(border[0]), &*links.begin(), links.size() * sizeof(Link)); 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; cerr << "Could not load nexus " << output << endl;
exit(0); exit(0);
} }
nexus.MaxRamBuffer(ram_buffer); nexus.MaxRam() = ram_buffer / nexus.chunk_size;
VChain vchain; VChain vchain;
if(!vchain.Load(output + ".vchain")) { if(!vchain.Load(output + ".vchain")) {
cerr << "Could not load : " << output << ".vchain\n"; cerr << "Could not load : " << output << ".vchain\n";
exit(0); exit(0);
} }
nexus.history.clear(); nexus.history.Clear();
Nexus::Update update; History::Update update;
for(unsigned int i = 0; i < nexus.index.size(); i++) { for(unsigned int i = 0; i < nexus.size(); i++) {
update.created.push_back(i); update.created.push_back(i);
patch_levels.push_back(0); patch_levels.push_back(0);
} }
nexus.history.push_back(update); nexus.history.updates.push_back(update);
nexus.Unify(); nexus.Unify();
nexus.patches.Flush(); nexus.Flush();
Dispatcher dispatcher(&nexus, &vchain); Dispatcher dispatcher(&nexus, &vchain);
@ -502,7 +505,7 @@ void FifthStep(const string &crudefile, const string &output,
current_level = level; current_level = level;
cerr << "Level: " << level << endl; cerr << "Level: " << level << endl;
unsigned int newoffset = nexus.index.size(); unsigned int newoffset = nexus.size();
BuildLevel(vchain, nexus, oldoffset, scaling, BuildLevel(vchain, nexus, oldoffset, scaling,
patch_size, patch_threshold, 65000, patch_size, patch_threshold, 65000,
optimization_steps); optimization_steps);
@ -571,8 +574,8 @@ void FifthStep(const string &crudefile, const string &output,
for(s = fcells.begin(); s != fcells.end(); s++) for(s = fcells.begin(); s != fcells.end(); s++)
update.erased.push_back(*s); update.erased.push_back(*s);
} }
nexus.history.push_back(update); nexus.history.updates.push_back(update);
ReverseHistory(nexus.history); ReverseHistory(nexus.history.updates);
// TestBorders(nexus); // TestBorders(nexus);
nexus.Close(); nexus.Close();
@ -719,7 +722,7 @@ void BuildFragment(Nexus &nexus, VPartition &part,
int nnears = 10; int nnears = 10;
if(part.size() < 10) nnears = part.size(); if(part.size() < 10) nnears = part.size();
for(f = patches.begin(); f != patches.end(); f++) { for(f = patches.begin(); f != patches.end(); f++) {
Point3f &center = nexus.index[*f].sphere.Center(); Point3f &center = nexus[*f].sphere.Center();
part.Closest(center, nnears, nears, dists); part.Closest(center, nnears, nears, dists);
for(int i = 0; i < nnears; i++) for(int i = 0; i < nnears; i++)
seeds.insert(nears[i]); seeds.insert(nears[i]);
@ -737,7 +740,7 @@ void SaveFragment(Nexus &nexus, VChain &chain,
set<unsigned int> orig_patches; set<unsigned int> orig_patches;
Nexus::Update update; History::Update update;
for(unsigned int i = 0; i < fragin.pieces.size(); i++) { for(unsigned int i = 0; i < fragin.pieces.size(); i++) {
NxsPatch &patch = fragin.pieces[i]; NxsPatch &patch = fragin.pieces[i];
update.erased.push_back(patch.patch); update.erased.push_back(patch.patch);
@ -756,7 +759,7 @@ void SaveFragment(Nexus &nexus, VChain &chain,
patch.face.size()/3, patch.face.size()/3,
bordsize); bordsize);
patch_levels.push_back(current_level); patch_levels.push_back(current_level);
PatchInfo &entry = nexus.index[patch_idx]; Entry &entry = nexus[patch_idx];
entry.error = fragout.error; entry.error = fragout.error;
patch_remap[i] = patch_idx; patch_remap[i] = patch_idx;
@ -784,7 +787,7 @@ void SaveFragment(Nexus &nexus, VChain &chain,
memcpy(patch.VertBegin(), &outpatch.vert[0], memcpy(patch.VertBegin(), &outpatch.vert[0],
outpatch.vert.size() * sizeof(Point3f)); 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++) { for(unsigned int v = 0; v < outpatch.vert.size(); v++) {
entry.sphere.Add(outpatch.vert[v]); entry.sphere.Add(outpatch.vert[v]);
nexus.sphere.Add(outpatch.vert[v]); nexus.sphere.Add(outpatch.vert[v]);
@ -866,16 +869,16 @@ void SaveFragment(Nexus &nexus, VChain &chain,
border[bstart++] = link; border[bstart++] = link;
} }
} }
nexus.history.push_back(update); nexus.history.updates.push_back(update);
} }
void ReverseHistory(vector<Nexus::Update> &history) { void ReverseHistory(vector<History::Update> &history) {
vector<Nexus::Update> revert = history; vector<History::Update> revert = history;
history.clear(); history.clear();
for(int i = revert.size()-1; i >= 0; i--) for(int i = revert.size()-1; i >= 0; i--)
history.push_back(revert[i]); history.push_back(revert[i]);
//std::reverse(history.begin(), history.end()); //std::reverse(history.begin(), history.end());
vector<Nexus::Update>::iterator i; vector<History::Update>::iterator i;
for(i = history.begin(); i != history.end(); i++) for(i = history.begin(); i != history.end(); i++)
swap((*i).erased, (*i).created); swap((*i).erased, (*i).created);
} }

View File

@ -216,7 +216,7 @@ int main(int argc, char *argv[]) {
cerr << "Could not open nexus file: " << input << "\n"; cerr << "Could not open nexus file: " << input << "\n";
return -1; return -1;
} }
nexus.MaxRamBuffer(ram_size); nexus.MaxRam() = ram_size / nexus.chunk_size;
//Sanity tests //Sanity tests
@ -263,7 +263,7 @@ int main(int argc, char *argv[]) {
<< "\n\tData : " << (int)((nexus.signature&NXS_DATA32) !=0) << "\n\tData : " << (int)((nexus.signature&NXS_DATA32) !=0)
<< "\n\n\tVertices: " << nexus.totvert << "\n\n\tVertices: " << nexus.totvert
<< "\tFaces: " << nexus.totface << "\tFaces: " << nexus.totface
<< "\tPatches: " << nexus.index.size() << "\tPatches: " << nexus.size()
<< "\n\tSphere: " << "\n\tSphere: "
<< nexus.sphere.Center()[0] << " " << nexus.sphere.Center()[0] << " "
<< nexus.sphere.Center()[1] << " " << nexus.sphere.Center()[1] << " "
@ -315,22 +315,22 @@ int main(int argc, char *argv[]) {
Nexus out; Nexus out;
if(!chunk_size) if(!chunk_size)
chunk_size = nexus.patches.chunk_size; chunk_size = nexus.chunk_size;
if(!out.Create(output, (Signature)signature, chunk_size)) { if(!out.Create(output, (Signature)signature, chunk_size)) {
cerr << "Could not open output: " << output << endl; cerr << "Could not open output: " << output << endl;
return -1; return -1;
} }
out.MaxRamBuffer(ram_size); out.MaxRam() = ram_size / out.chunk_size;
//TODO set rambuffer low (or even direct access!) //TODO set rambuffer low (or even direct access!)
Report report(nexus.index.size()); Report report(nexus.size());
cout << "Copying and allocating...\n"; 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); report.Step(patch);
PatchInfo &src_entry = nexus.index[patch]; Entry &src_entry = nexus[patch];
Patch src_patch = nexus.GetPatch(patch); Patch &src_patch = nexus.GetPatch(patch);
Border src_border = nexus.GetBorder(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()); 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: //copy vertices:
memcpy(dst_patch.VertBegin(), src_patch.VertBegin(), memcpy(dst_patch.VertBegin(), src_patch.VertBegin(),
@ -396,8 +396,8 @@ int main(int argc, char *argv[]) {
if(link.IsNull()) continue; if(link.IsNull()) continue;
assert(link.end_patch < nexus.index.size()); assert(link.end_patch < nexus.index.size());
}*/ }*/
Border dst_border = out.GetBorder(patch);
out.borders.ResizeBorder(patch, src_border.Size()); out.borders.ResizeBorder(patch, src_border.Size());
Border dst_border = out.GetBorder(patch);
memcpy(dst_border.Start(), src_border.Start(), memcpy(dst_border.Start(), src_border.Start(),
src_border.Size() * sizeof(Link)); src_border.Size() * sizeof(Link));
} }
@ -416,9 +416,9 @@ int main(int argc, char *argv[]) {
} }
if(qvertex && add_normals) { if(qvertex && add_normals) {
report.Init(nexus.index.size()); report.Init(nexus.size());
cout << "Quantizing vertices\n"; 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); report.Step(patch);
Patch src_patch = nexus.GetPatch(patch); Patch src_patch = nexus.GetPatch(patch);
@ -430,7 +430,12 @@ int main(int argc, char *argv[]) {
} }
out.sphere = nexus.sphere; 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(); out.Close();
nexus.Close(); nexus.Close();

View File

@ -4,31 +4,26 @@
using namespace std; using namespace std;
using namespace nxs; 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; ram_used = 0;
return MFile::Create(filename); return MFile::Create(filename);
} }
bool PServer::Load(const std::string &filename, Signature sig, bool PServer::Load(const std::string &filename, Signature _signature,
unsigned int csize, bool readonly, bool _readonly, unsigned int _chunk_size) {
unsigned int rsize) {
signature = sig; signature = _signature;
chunk_size = csize; chunk_size = _chunk_size;
ram_max = rsize/chunk_size + 1;
ram_used = 0; ram_used = 0;
return MFile::Load(filename, readonly); return MFile::Load(filename, _readonly);
} }
void PServer::Close() { void PServer::Close() {
@ -40,23 +35,21 @@ void PServer::Close() {
bool PServer::ReadEntries(FILE *fp) { bool PServer::ReadEntries(FILE *fp) {
unsigned int n; unsigned int n;
fread(&n, 1, sizeof(int), fp); fread(&n, 1, sizeof(int), fp);
entries.resize(n); resize(n);
for(unsigned int i = 0; i < n; i++) { for(unsigned int i = 0; i < n; i++) {
fread(&(entries[i].patch_start), 1, sizeof(unsigned int), fp); Entry &entry = operator[](i);
fread(&(entries[i].ram_size), 1, sizeof(unsigned short), fp); fread(&entry, sizeof(Entry), 1, fp);
fread(&(entries[i].disk_size), 1, sizeof(unsigned short), fp); entry.patch = NULL;
entries[i].patch = NULL;
} }
return true; return true;
} }
bool PServer::WriteEntries(FILE *fp) { bool PServer::WriteEntries(FILE *fp) {
unsigned int n = entries.size(); unsigned int n = size();
fwrite(&n, 1, sizeof(int), fp); fwrite(&n, 1, sizeof(int), fp);
for(unsigned int i = 0; i < entries.size(); i++) { for(unsigned int i = 0; i < size(); i++) {
fwrite(&(entries[i].patch_start), 1, sizeof(unsigned int), fp); Entry &entry = operator[](i);
fwrite(&(entries[i].ram_size), 1, sizeof(unsigned short), fp); fwrite(&entry, sizeof(Entry), 1, fp);
fwrite(&(entries[i].disk_size), 1, sizeof(unsigned short), fp);
} }
return true; return true;
} }
@ -66,17 +59,19 @@ void PServer::AddPatch(unsigned short nvert, unsigned short nface) {
entry.patch_start = 0xffffffff; entry.patch_start = 0xffffffff;
entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size); entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size);
entry.disk_size = 0xffff; entry.disk_size = 0xffff;
entry.nvert = nvert;
entry.nface = nface;
//sphere and error undefined.
entry.patch = NULL; entry.patch = NULL;
entries.push_back(entry); entry.vbo_array = 0;
entry.vbo_element = 0;
push_back(entry);
} }
Patch *PServer::LoadPatch(unsigned int idx, Patch *PServer::LoadPatch(unsigned int idx) {
unsigned short nvert, unsigned short nface) { assert(idx < size());
Entry &entry = operator[](idx);
// ramlock.rdlock();
assert(idx < entries.size());
Entry &entry = entries[idx];
if(entry.patch) return entry.patch; if(entry.patch) return entry.patch;
char *ram = new char[entry.ram_size * chunk_size]; char *ram = new char[entry.ram_size * chunk_size];
@ -87,18 +82,18 @@ Patch *PServer::LoadPatch(unsigned int idx,
} }
#endif #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. if(entry.patch_start != 0xffffffff) { //was allocated.
assert(entry.disk_size != 0xffff); 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 if((signature & NXS_COMPRESSED) == 0) { //not compressed
ReadBuffer(ram, entry.disk_size * chunk_size); MFile::ReadBuffer(ram, entry.disk_size * chunk_size);
} else { } else {
unsigned char *disk = new unsigned char[entry.disk_size * chunk_size]; 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, patch->Decompress(entry.ram_size * chunk_size,
disk, entry.disk_size * chunk_size); disk, entry.disk_size * chunk_size);
@ -110,46 +105,127 @@ Patch *PServer::LoadPatch(unsigned int idx,
return patch; 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!!!! //TODO move this into an assert!!!!
if(!patch) return; if(!entry.patch) return;
Entry &entry = entries[id];
// cerr << "entry: " << (void *)(entry.patch) << " patch: " << (void *)patch << endl;
entry.patch = NULL;
if(!readonly) { //write back patch
if(!MFile::IsReadOnly()) { //write back patch
if((signature & NXS_COMPRESSED)) { if((signature & NXS_COMPRESSED)) {
unsigned int compressed_size; 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); compressed_size);
if(entry.disk_size == 0xffff) {//allocate space if(entry.disk_size == 0xffff) {//allocate space
assert(entry.patch_start == 0xffffffff); assert(entry.patch_start == 0xffffffff);
entry.disk_size = (unsigned int)((compressed_size-1)/chunk_size) + 1; entry.disk_size = (unsigned int)((compressed_size-1)/chunk_size) + 1;
entry.patch_start = (unsigned int)(Length()/chunk_size); entry.patch_start = (unsigned int)( MFile::Length()/chunk_size);
Redim(Length() + entry.disk_size * chunk_size); MFile::Redim(MFile::Length() + entry.disk_size * chunk_size);
} else { } else {
//cerr << "OOOOPSPPPS not supported!" << endl; //cerr << "OOOOPSPPPS not supported!" << endl;
exit(-1); exit(-1);
} }
SetPosition((int64)entry.patch_start * (int64)chunk_size); MFile::SetPosition((int64)entry.patch_start * (int64)chunk_size);
WriteBuffer(compressed, entry.disk_size * chunk_size); MFile::WriteBuffer(compressed, entry.disk_size * chunk_size);
delete []compressed; delete []compressed;
} else { } else {
if(entry.disk_size == 0xffff) { if(entry.disk_size == 0xffff) {
entry.disk_size = entry.ram_size; entry.disk_size = entry.ram_size;
entry.patch_start = (unsigned int)(Length()/chunk_size); entry.patch_start = (unsigned int)(MFile::Length()/chunk_size);
Redim(Length() + entry.disk_size * chunk_size); MFile::Redim(MFile::Length() + entry.disk_size * chunk_size);
} }
SetPosition((int64)entry.patch_start * (int64)chunk_size); MFile::SetPosition((int64)entry.patch_start * (int64)chunk_size);
WriteBuffer(patch->start, entry.disk_size * chunk_size); MFile::WriteBuffer(entry.patch->start, entry.disk_size * chunk_size);
} }
} }
delete [](patch->start); delete [](entry.patch->start);
delete patch; delete entry.patch;
entry.patch = NULL;
ram_used -= entry.ram_size; ram_used -= entry.ram_size;
} }
void PServer::MaxRamBuffer(unsigned int r_buffer) { bool PServer::IsLoaded(unsigned int patch) {
ram_max = (unsigned int)(r_buffer/chunk_size) + 1; return operator[](patch).patch != NULL;
} }
Entry &PServer::Lookup(unsigned int patch, std::vector<unsigned int> &flush) {
Entry &entry = operator[](patch);
if(index.count(patch)) {
list<unsigned int>::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<unsigned int>::iterator i = pqueue.begin();
index[patch] = i;
}
return entry;
}
void PServer::Flush() {
std::map<unsigned int, list<unsigned int>::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;
}

View File

@ -2,41 +2,55 @@
#define NXS_PSERVER_H #define NXS_PSERVER_H
#include <vector> #include <vector>
#include <list>
#include <map> #include <map>
#include <iostream> #include <iostream>
#include "patch.h" #include "patch.h"
#include "mfile.h" #include "mfile.h"
namespace nxs { namespace nxs {
class PServer: public MFile { /* HEader fo pserver
public: 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)
struct Entry { 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 int patch_start; //granularita' Chunk
unsigned short ram_size; //in chunks unsigned short ram_size; //in chunks
unsigned short disk_size; // in chunks (used when compressed) unsigned short disk_size; // in chunks (used when compressed)
Patch *patch;
};
/* struct Data { unsigned short nvert;
// unsigned int npatch; unsigned short nface;
vcg::Sphere3f sphere;
float error;
Patch *patch; Patch *patch;
unsigned int vbo_array; unsigned int vbo_array;
unsigned int vbo_element; unsigned int vbo_element;
Data(): patch(NULL), vbo_array(0), vbo_element(0) {} };
};*/
struct Item { //used by lru and pqueue.
unsigned int patch;
float priority;
Item(unsigned int p, float f): patch(p), priority(f) {}
bool operator<(const Item &i) const {
return priority < i.priority;
}
};
class PServer: public IndexFile<Entry,
public:
std::list<unsigned int> pqueue;
std::map<unsigned int, std::list<unsigned int>::iterator> index;
Signature signature; Signature signature;
unsigned int chunk_size; unsigned int chunk_size;
@ -44,39 +58,39 @@ class PServer: public MFile {
unsigned int ram_max; unsigned int ram_max;
unsigned int ram_used; unsigned int ram_used;
std::vector<Entry> entries;
PServer(): chunk_size(1024), PServer(): chunk_size(1024),
ram_max(128000000), ram_max(128000000),
ram_used(0) {} ram_used(0) {}
virtual ~PServer() {
MFile::Close(); ~PServer() { PServer::Close(); }
}
bool Create(const std::string &filename, Signature signature, bool Create(const std::string &filename, Signature signature,
unsigned int chunk_size, unsigned int ram_max = 128000000); unsigned int chunk_size = 1024);
bool Load(const std::string &filename, Signature sig, bool Load(const std::string &filename, Signature signature,
unsigned int chunk_size, bool readonly, bool readonly = true, unsigned int chunk_size = 1024);
unsigned int ram_max = 128000000); void Close();
bool ReadEntries(FILE *fp); bool ReadEntries(FILE *fp);
bool WriteEntries(FILE *fp); bool WriteEntries(FILE *fp);
virtual void Close();
void AddPatch(unsigned short nvert, unsigned short nface); void AddPatch(unsigned short nvert, unsigned short nface);
Patch *LoadPatch(unsigned int id, unsigned short nv, unsigned short nf); Patch *LoadPatch(unsigned int id);
void FlushPatch(unsigned int id, Patch *patch); void FlushPatch(unsigned int id);
void Flush();
virtual bool IsLoaded(unsigned int patch) = 0; bool IsLoaded(unsigned int patch);
// virtual Patch &Lookup(unsigned int patch, Entry &Lookup(unsigned int patch, std::vector<unsigned int> &flushed);
// unsigned short nv, unsigned short nf) = 0; void LoadVbo(unsigned int patch);
virtual void Flush() = 0; 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 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);
}; };

View File

@ -245,9 +245,9 @@ void nxs::BuildLevel(VChain &chain,
unsigned int totface = 0; unsigned int totface = 0;
unsigned int totvert = 0; unsigned int totvert = 0;
for(unsigned int idx = offset; idx < nexus.index.size(); idx++) { for(unsigned int idx = offset; idx < nexus.size(); idx++) {
totface += nexus.index[idx].nface; totface += nexus[idx].nface;
totvert += nexus.index[idx].nvert; totvert += nexus[idx].nvert;
} }
VPartition *fine = chain[chain.size()-1]; VPartition *fine = chain[chain.size()-1];
@ -260,9 +260,9 @@ void nxs::BuildLevel(VChain &chain,
unsigned int ncells = (unsigned int)(scaling * totface/target_size); unsigned int ncells = (unsigned int)(scaling * totface/target_size);
//TODO this method for selecting the seeds is ugly! //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; float cratio = 0;
for(unsigned int idx = offset; idx < nexus.index.size(); idx++) { for(unsigned int idx = offset; idx < nexus.size(); idx++) {
cratio += ratio; cratio += ratio;
if(cratio > 1) { if(cratio > 1) {
Patch patch = nexus.GetPatch(idx); Patch patch = nexus.GetPatch(idx);
@ -296,8 +296,8 @@ void nxs::BuildLevel(VChain &chain,
centroids.resize(coarse->size(), Point3f(0, 0, 0)); centroids.resize(coarse->size(), Point3f(0, 0, 0));
counts.resize(coarse->size(), 0); counts.resize(coarse->size(), 0);
Report report(nexus.index.size()); Report report(nexus.size());
for(unsigned int idx = offset; idx < nexus.index.size(); idx++) { for(unsigned int idx = offset; idx < nexus.size(); idx++) {
report.Step(idx); report.Step(idx);
Patch patch = nexus.GetPatch(idx); Patch patch = nexus.GetPatch(idx);
for(unsigned int i = 0; i < patch.nf; i++) { for(unsigned int i = 0; i < patch.nf; i++) {

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $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 Revision 1.18 2004/12/01 03:24:32 ponchio
Level 2. Level 2.
@ -168,7 +171,7 @@ template <class T> class VFile: public MFile {
queue_size = _queue_size; queue_size = _queue_size;
if(!MFile::Load(filename, rdonly)) return false; if(!MFile::Load(filename, rdonly)) return false;
n_elements = size/sizeof(T); n_elements = _size/sizeof(T);
return true; return true;
} }

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $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 Revision 1.5 2004/12/01 16:00:35 ponchio
Level 3 Level 3
@ -54,6 +57,9 @@ First draft created.
****************************************************************************/ ****************************************************************************/
#ifndef VCG_WATCH_H
#define VCG_WATCH_H
#ifdef WIN32 #ifdef WIN32
#ifndef _WINDOWS_ #ifndef _WINDOWS_
#define _WINSOCKAPI_ #define _WINSOCKAPI_
@ -98,3 +104,5 @@ class Report {
double last; double last;
double interval; double interval;
}; };
#endif