Revolution.
This commit is contained in:
parent
0fde2046fc
commit
975ec6ae04
|
@ -4,61 +4,131 @@
|
|||
using namespace std;
|
||||
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) {
|
||||
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<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) {
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,40 +1,58 @@
|
|||
#ifndef NXS_BORDERSERVER_H
|
||||
#define NXS_BORDERSERVER_H
|
||||
|
||||
#include "vfile.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "index_file.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 {
|
||||
|
||||
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<Link> {
|
||||
class BorderServer: public IndexFile<BorderEntry> {
|
||||
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<unsigned int> pqueue;
|
||||
std::map<unsigned int, std::list<unsigned int>::iterator> index;
|
||||
|
||||
bool LoadHeader();
|
||||
void SaveHeader();
|
||||
|
||||
std::vector<BorderEntry> borders;
|
||||
|
||||
void FlushBorder(unsigned int border);
|
||||
Link *GetRegion(unsigned int start, unsigned int size); //size in links.
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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<unsigned int, Items::iterator>::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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<File *> files;
|
||||
unsigned int curr_pos;
|
||||
unsigned int curr_fp;
|
||||
int64 size;
|
||||
int64 _size;
|
||||
unsigned int max_size;
|
||||
bool readonly;
|
||||
private:
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#include <set>
|
||||
|
||||
#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<Entry>::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<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+");
|
||||
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<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) {
|
||||
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<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]);
|
||||
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<Entry>::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<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) {
|
||||
Entry &entry = operator[](patch);
|
||||
if(index.count(patch)) {
|
||||
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) {
|
||||
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<Point3f, unsigned short> 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<Link> links;
|
||||
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++)
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -3,15 +3,65 @@
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "nexusbase.h"
|
||||
#include "lrupserver.h"
|
||||
#include <vcg/space/sphere3.h>
|
||||
|
||||
#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<Entry> {
|
||||
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<unsigned int> pqueue;
|
||||
std::map<unsigned int, std::list<unsigned int>::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<PatchInfo> index;
|
||||
|
||||
LruPServer patches;
|
||||
BorderServer borders;
|
||||
|
||||
// std::vector<Update> history;
|
||||
|
||||
// bool readonly;
|
||||
|
||||
// private:
|
||||
// FILE *index_file;
|
||||
bool LoadHeader();
|
||||
void SaveHeader();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,10 @@
|
|||
|
||||
|
||||
<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="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>
|
||||
|
||||
<a name="crude"><h2>Crude</h2></a>
|
||||
<pre>
|
||||
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>
|
||||
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.<br>
|
||||
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 (<b>.crd</b>)
|
||||
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...
|
||||
</pre>
|
||||
|
||||
<a name="pchain"><h2>PChain</h2></a>
|
||||
Sta per 'partition chain' cioe' una catena di partizioni dello
|
||||
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>
|
||||
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>
|
||||
E' una struttura con 3 files: 'index', 'patches' e 'borders'.<br>
|
||||
'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.<br>
|
||||
'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?<br>
|
||||
'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)<br>
|
||||
<pre>
|
||||
E' una struttura con 2 files:
|
||||
|
||||
File delle patches: (<b>.nxs</b>)
|
||||
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)
|
||||
</pre>
|
||||
<br>
|
||||
|
||||
<a name="bmt"><h2>Bmt</h2></a>
|
||||
Bmt (batched multi triangulation) e' il formato per la
|
||||
|
|
|
@ -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<PatchInfo> index;
|
||||
// std::vector<PatchInfo> index;
|
||||
std::vector<Update> history;
|
||||
|
||||
bool readonly;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,179 +1,109 @@
|
|||
#ifndef NXS_NEXUS_MT_H
|
||||
#define NXS_NEXUS_MT_H
|
||||
#ifndef NXS_MT_H
|
||||
#define NXS_MT_H
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <wrap/gui/frustum.h>
|
||||
|
||||
#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<unsigned int> Frag;
|
||||
|
||||
struct Node {
|
||||
std::vector<Node *> in;
|
||||
std::vector<Node *> out;
|
||||
std::vector<Frag> 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<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;
|
||||
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<QueuePServer::Data *> todraw;
|
||||
std::vector<PServer::Item> visited;
|
||||
std::vector<Node *> 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<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();
|
||||
|
||||
|
||||
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<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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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<unsigned int> 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);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
//#include <wrap/strip/tristrip.h>
|
||||
|
||||
#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<Point3f> 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);
|
||||
|
|
|
@ -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<Nexus::Update> &history);
|
||||
void ReverseHistory(vector<History::Update> &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<unsigned int> 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<Link> 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<unsigned int> 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<Nexus::Update> &history) {
|
||||
vector<Nexus::Update> revert = history;
|
||||
void ReverseHistory(vector<History::Update> &history) {
|
||||
vector<History::Update> 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<Nexus::Update>::iterator i;
|
||||
vector<History::Update>::iterator i;
|
||||
for(i = history.begin(); i != history.end(); i++)
|
||||
swap((*i).erased, (*i).created);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,81 +2,95 @@
|
|||
#define NXS_PSERVER_H
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
#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<Entry,
|
||||
public:
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
std::list<unsigned int> pqueue;
|
||||
std::map<unsigned int, std::list<unsigned int>::iterator> index;
|
||||
|
||||
|
||||
|
||||
Signature signature;
|
||||
unsigned int chunk_size;
|
||||
|
||||
unsigned int ram_max;
|
||||
unsigned int ram_used;
|
||||
|
||||
std::vector<Entry> 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<unsigned int> &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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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 T> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue