Lotsa changes...
This commit is contained in:
parent
bdb503ef17
commit
9bb65dd0c3
|
@ -0,0 +1,64 @@
|
|||
#ifndef NXS_LRU_PSERVER_H
|
||||
#define NXS_LRU_PSERVER_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include "pserver.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
class LruPServer: public PServer {
|
||||
public:
|
||||
//TODO change name to Item
|
||||
typedef std::pair<unsigned int, Patch *> Item;
|
||||
std::list<Item> items;
|
||||
typedef std::list<Item> Items;
|
||||
std::map<unsigned int, Items::iterator> index;
|
||||
|
||||
~LruPServer() {
|
||||
Flush();
|
||||
}
|
||||
|
||||
Patch &Lookup(unsigned int patch, unsigned short nv, unsigned short nf) {
|
||||
if(index.count(patch)) {
|
||||
Items::iterator &i = index[patch];
|
||||
Item item = *i;
|
||||
items.erase(i);
|
||||
items.push_front(item);
|
||||
i = items.begin();
|
||||
return *((*i).second);
|
||||
} else {
|
||||
while(ram_used > ram_max) {
|
||||
index.erase(items.back().first);
|
||||
FlushPatch(patch, items.back().second);
|
||||
items.pop_back();
|
||||
}
|
||||
Item item;
|
||||
item.first = patch;
|
||||
item.second = LoadPatch(patch, nv, nf);
|
||||
items.push_front(item);
|
||||
Items::iterator i = items.begin();
|
||||
index[patch] = i;
|
||||
return *((*i).second);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsLoaded(unsigned int patch) {
|
||||
return index.count(patch);
|
||||
}
|
||||
void Flush() {
|
||||
std::cerr << "Lru flulshing\n";
|
||||
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);
|
||||
}
|
||||
|
||||
items.clear();
|
||||
index.clear();
|
||||
}
|
||||
};
|
||||
|
||||
}//namespace
|
||||
|
||||
#endif
|
|
@ -1,12 +1,16 @@
|
|||
#include <iostream>
|
||||
#include <assert.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
#include "nexus.h"
|
||||
#include "lrupserver.h"
|
||||
#include "queuepserver.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace vcg;
|
||||
using namespace nxs;
|
||||
|
||||
Nexus::Nexus(): index_file(NULL) {}
|
||||
Nexus::~Nexus() {
|
||||
Close();
|
||||
}
|
||||
|
@ -17,7 +21,7 @@ bool Nexus::Create(const string &file, Signature sig, unsigned int c_size) {
|
|||
cerr << "Could not create file: " << file << ".nxs\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
signature = sig;
|
||||
totvert = 0;
|
||||
totface = 0;
|
||||
|
@ -27,6 +31,8 @@ bool Nexus::Create(const string &file, Signature sig, unsigned int c_size) {
|
|||
|
||||
chunk_size = c_size;
|
||||
|
||||
history.clear();
|
||||
|
||||
if(!patches.Create(file + ".nxp", signature, chunk_size)) {
|
||||
cerr << "Could not create file: " << file << ".nxp" << endl;
|
||||
return false;
|
||||
|
@ -40,7 +46,10 @@ bool Nexus::Create(const string &file, Signature sig, unsigned int c_size) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Nexus::Load(const string &file, bool readonly) {
|
||||
|
||||
bool Nexus::Load(const string &file, bool rdonly) {
|
||||
readonly = rdonly;
|
||||
|
||||
index_file = fopen((file + ".nxs").c_str(), "rb+");
|
||||
if(!index_file) return false;
|
||||
|
||||
|
@ -63,6 +72,7 @@ bool Nexus::Load(const string &file, bool readonly) {
|
|||
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);
|
||||
|
||||
|
@ -88,20 +98,26 @@ bool Nexus::Load(const string &file, bool readonly) {
|
|||
history[i].created[e] = buffer[pos++];
|
||||
}
|
||||
|
||||
if(readonly) {
|
||||
fclose(index_file);
|
||||
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;
|
||||
if(!borders.Load(file + ".nxb", readonly, 1, 500))
|
||||
return false;
|
||||
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);
|
||||
|
@ -112,9 +128,11 @@ void Nexus::Close() {
|
|||
fwrite(&size, sizeof(unsigned int), 1, index_file);
|
||||
fwrite(&(index[0]), sizeof(PatchInfo), size, index_file);
|
||||
|
||||
//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++) {
|
||||
|
@ -126,12 +144,11 @@ void Nexus::Close() {
|
|||
for(unsigned int e = 0; e < update.created.size(); e++)
|
||||
buffer.push_back(update.created[e]);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -139,7 +156,7 @@ void Nexus::Close() {
|
|||
Patch &Nexus::GetPatch(unsigned int patch, bool flush) {
|
||||
assert(patch < index.size());
|
||||
PatchInfo &info = index[patch];
|
||||
return patches.GetPatch(patch, info.nvert, info.nface, flush);
|
||||
return patches.Lookup(patch, info.nvert, info.nface);
|
||||
}
|
||||
|
||||
Border Nexus::GetBorder(unsigned int patch, bool flush) {
|
||||
|
@ -180,111 +197,13 @@ unsigned int Nexus::AddPatch(unsigned int nvert, unsigned int nface,
|
|||
return index.size() -1;
|
||||
}
|
||||
|
||||
void Nexus::SetRamBufferSize(unsigned int r_size) {
|
||||
patches.SetRamBufferSize(r_size);
|
||||
void Nexus::MaxRamBuffer(unsigned int r_size) {
|
||||
patches.MaxRamBuffer(r_size);
|
||||
//TODO do the same with borders
|
||||
}
|
||||
|
||||
/*void Nexus::Join(const std::set<unsigned int> &patches,
|
||||
std::vector<Point3f> &newvert,
|
||||
std::vector<unsigned int> &newface,
|
||||
std::vector<Link> &newbord) {
|
||||
|
||||
map<unsigned int, vector<unsigned int> > remap;
|
||||
set<Link> newborders;
|
||||
set<unsigned int> erased;
|
||||
for(unsigned int u = 0; u < history.size(); u++)
|
||||
for(unsigned int e = 0; e < history[u].erased.size(); e++)
|
||||
erased.insert(history[u].erased[e]);
|
||||
|
||||
set<unsigned int>::const_iterator patch_idx;
|
||||
for(patch_idx = patches.begin(); patch_idx != patches.end(); patch_idx++) {
|
||||
unsigned int patch = *patch_idx;
|
||||
PatchInfo &entry = index[patch];
|
||||
remap[patch].resize(entry.nvert, 0xffffffff);
|
||||
}
|
||||
|
||||
unsigned int vcount = 0;
|
||||
unsigned int fcount = 0;
|
||||
unsigned int bcount = 0;
|
||||
for(patch_idx = patches.begin(); patch_idx != patches.end(); patch_idx++) {
|
||||
unsigned int patch = *patch_idx;
|
||||
vector<unsigned int> &vmap = remap[patch];
|
||||
|
||||
PatchInfo &entry = index[patch];
|
||||
fcount += entry.nface;
|
||||
for(unsigned int k = 0; k < entry.nvert; k++) {
|
||||
if(vmap[k] == 0xffffffff) { //first time
|
||||
vmap[k] = vcount++;
|
||||
}
|
||||
}
|
||||
|
||||
Border border = GetBorder(patch);
|
||||
for(unsigned int k = 0; k < border.Size(); k++) {
|
||||
Link link = border[k];
|
||||
if(link.IsNull()) continue;
|
||||
|
||||
assert(link.start_vert < entry.nvert);
|
||||
assert(vmap[link.start_vert] != 0xffffffff);
|
||||
|
||||
if(!remap.count(link.end_patch)) { //external
|
||||
//test if erased in history... in wich case we do not add border
|
||||
if(!erased.count(link.end_patch)) {
|
||||
link.start_vert = vmap[link.start_vert];
|
||||
newborders.insert(link);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//internal
|
||||
//TODO unsigned int &rmpv = remap[link.end_patch][link.end_vert];
|
||||
if(remap[link.end_patch][link.end_vert] == 0xffffffff) { //first time
|
||||
remap[link.end_patch][link.end_vert] = vmap[link.start_vert];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
newvert.resize(vcount);
|
||||
newface.resize(fcount*3);
|
||||
newbord.resize(0);
|
||||
|
||||
fcount = 0;
|
||||
for(patch_idx = patches.begin(); patch_idx != patches.end(); patch_idx++) {
|
||||
Patch patch = GetPatch(*patch_idx);
|
||||
|
||||
vector<unsigned int> &vmap = remap[*patch_idx];
|
||||
assert(vmap.size() == patch.nv);
|
||||
|
||||
for(unsigned int i = 0; i < vmap.size(); i++) {
|
||||
assert(vmap[i] < vcount);
|
||||
newvert[vmap[i]] = patch.Vert(i);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < patch.nf; i++)
|
||||
for(int k = 0; k < 3; k++) {
|
||||
//TODO remove this check.
|
||||
if(patch.Face(i)[k] >= vmap.size()) {
|
||||
cerr << "Face overflow: " << patch.Face(i)[k] << endl;
|
||||
exit(0);
|
||||
}
|
||||
assert(patch.Face(i)[k] < vmap.size());
|
||||
newface[fcount++] = vmap[patch.Face(i)[k]];
|
||||
}
|
||||
}
|
||||
|
||||
assert(fcount == newface.size());
|
||||
|
||||
set<Link>::iterator b;
|
||||
for(b = newborders.begin(); b != newborders.end(); b++)
|
||||
newbord.push_back(*b);
|
||||
|
||||
return;
|
||||
}*/
|
||||
|
||||
|
||||
void Nexus::Unify(float threshold) {
|
||||
//TODO what if colors or normals or strips?
|
||||
//TODO update totvert
|
||||
unsigned int duplicated = 0;
|
||||
unsigned int degenerate = 0;
|
||||
|
||||
|
|
|
@ -3,57 +3,23 @@
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <vcg/space/point3.h>
|
||||
|
||||
#include "patchserver.h"
|
||||
#include "nexusbase.h"
|
||||
#include "lrupserver.h"
|
||||
#include "borderserver.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
|
||||
struct PatchInfo {
|
||||
unsigned short nvert;
|
||||
unsigned short nface;
|
||||
|
||||
vcg::Sphere3f sphere;
|
||||
float error;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Nexus {
|
||||
class Nexus: public NexusBase {
|
||||
public:
|
||||
|
||||
struct BorderEntry {
|
||||
unsigned int border_start; //granuralita' Link
|
||||
unsigned short border_size; //in Links
|
||||
unsigned short border_used; //in Links
|
||||
};
|
||||
Nexus() {}
|
||||
~Nexus();
|
||||
|
||||
struct PatchInfo {
|
||||
unsigned short nvert;
|
||||
unsigned short nface;
|
||||
|
||||
vcg::Sphere3f sphere;
|
||||
float error;
|
||||
};
|
||||
|
||||
|
||||
//TODO optimize to be vector with offset.
|
||||
struct Update {
|
||||
std::vector<unsigned int> erased;
|
||||
std::vector<unsigned int> created;
|
||||
};
|
||||
|
||||
|
||||
Nexus();
|
||||
virtual ~Nexus();
|
||||
|
||||
bool Create(const std::string &filename, Signature signature,
|
||||
unsigned int chunk_size = 1024);
|
||||
virtual bool Load(const std::string &filename, bool readonly = false);
|
||||
virtual void Close();
|
||||
bool Load(const std::string &filename, bool readonly = false);
|
||||
void Close();
|
||||
|
||||
unsigned int AddPatch(unsigned int nv, unsigned int nf, unsigned int nb);
|
||||
Patch &GetPatch(unsigned int patch, bool flush = true);
|
||||
|
@ -67,12 +33,7 @@ class Nexus {
|
|||
bool HasNormalsShort() { return (signature & NXS_NORMALS_SHORT) != 0; }
|
||||
bool HasNormalsFloat() { return (signature & NXS_NORMALS_FLOAT) != 0; }
|
||||
|
||||
void SetRamBufferSize(unsigned int ram_size);
|
||||
|
||||
/* void Join(const std::set<unsigned int> &patches,
|
||||
std::vector<vcg::Point3f> &vert,
|
||||
std::vector<unsigned int> &faces,
|
||||
std::vector<Link> &links);*/
|
||||
void MaxRamBuffer(unsigned int ram_size);
|
||||
|
||||
//move to nxsalgo!
|
||||
void Unify(float threshold = 0.0f);
|
||||
|
@ -82,24 +43,24 @@ class Nexus {
|
|||
|
||||
//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;
|
||||
// Signature signature;
|
||||
// unsigned int chunk_size;
|
||||
|
||||
unsigned int totvert;
|
||||
unsigned int totface;
|
||||
vcg::Sphere3f sphere;
|
||||
// unsigned int totvert;
|
||||
// unsigned int totface;
|
||||
// vcg::Sphere3f sphere;
|
||||
|
||||
std::vector<PatchInfo> index;
|
||||
// std::vector<PatchInfo> index;
|
||||
|
||||
PatchServer patches;
|
||||
LruPServer patches;
|
||||
BorderServer borders;
|
||||
|
||||
std::vector<Update> history;
|
||||
// std::vector<Update> history;
|
||||
|
||||
bool readonly;
|
||||
// bool readonly;
|
||||
|
||||
private:
|
||||
FILE *index_file;
|
||||
// private:
|
||||
// FILE *index_file;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
#ifndef NXS_NEXUS_BASE_H
|
||||
#define NXS_NEXUS_BASE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "pserver.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
struct PatchInfo {
|
||||
unsigned short nvert;
|
||||
unsigned short nface;
|
||||
|
||||
vcg::Sphere3f sphere;
|
||||
float error;
|
||||
};
|
||||
|
||||
|
||||
class NexusBase {
|
||||
public:
|
||||
|
||||
//TODO optimize to be vector with offset.
|
||||
struct Update {
|
||||
std::vector<unsigned int> erased;
|
||||
std::vector<unsigned int> created;
|
||||
};
|
||||
|
||||
NexusBase(): index_file(NULL) {}
|
||||
|
||||
// bool Create(const std::string &filename, Signature signature,
|
||||
// unsigned int chunk_size = 1024);
|
||||
// bool Load(const std::string &filename, bool readonly = false);
|
||||
// void Close();
|
||||
|
||||
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; }
|
||||
|
||||
|
||||
//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;
|
||||
std::vector<Update> history;
|
||||
|
||||
bool readonly;
|
||||
|
||||
protected:
|
||||
FILE *index_file;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -48,28 +48,23 @@ float Metric::GetError(Frag &frag) {
|
|||
|
||||
float FrustumMetric::GetError(unsigned int cell) {
|
||||
float max_error = 0;
|
||||
Nexus::PatchInfo &entry = (*index)[cell];
|
||||
PatchInfo &entry = (*index)[cell];
|
||||
Sphere3f &sphere = entry.sphere;
|
||||
float dist = Distance(sphere, frustum.ViewPoint());
|
||||
if(dist < 0) return 1e20f;
|
||||
float error = entry.error/frustum.Resolution(dist);
|
||||
if(frustum.IsOutside(sphere.Center(), sphere.Radius()))
|
||||
error /= 4;
|
||||
error /= 256;
|
||||
return error;
|
||||
}
|
||||
|
||||
void Policy::Init() {
|
||||
ram_used = 0;
|
||||
}
|
||||
|
||||
bool Policy::Expand(TNode &node) {
|
||||
bool NexusMt::Expand(TNode &node) {
|
||||
//expand if node error > target error
|
||||
if(ram_used >= ram_size) return false;
|
||||
//cerr << "Error: " << error << " node.error: " << node.error << endl;
|
||||
return node.error > error;
|
||||
if(extraction_used >= extraction_max) return false;
|
||||
return node.error > target_error;
|
||||
}
|
||||
|
||||
void Policy::NodeVisited(Node *node) {
|
||||
void NexusMt::NodeVisited(Node *node) {
|
||||
//TODO write this a bit more elegant.
|
||||
//first we process arcs removed:
|
||||
|
||||
|
@ -77,11 +72,11 @@ void Policy::NodeVisited(Node *node) {
|
|||
assert(!(node->out[i]->visited));
|
||||
Frag &frag = node->frags[i];
|
||||
for(unsigned int k = 0; k < frag.size(); k++) {
|
||||
PatchEntry &entry = (*entries)[frag[k]];
|
||||
ram_used += entry.ram_size;
|
||||
PServer::Entry &entry = patches.entries[frag[k]];
|
||||
extraction_used += entry.ram_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vector<Node *>::iterator from;
|
||||
for(from = node->in.begin(); from != node->in.end(); from++) {
|
||||
assert((*from)->visited);
|
||||
|
@ -90,59 +85,84 @@ void Policy::NodeVisited(Node *node) {
|
|||
if((*from)->out[i] == node) {
|
||||
vector<unsigned int> &frag = frags[i];
|
||||
for(unsigned int k = 0; k < frag.size(); k++) {
|
||||
PatchEntry &entry = (*entries)[frag[k]];
|
||||
ram_used -= entry.ram_size;
|
||||
PServer::Entry &entry = patches.entries[frag[k]];
|
||||
extraction_used -= entry.ram_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Prefetch::Prefetch(): thread(true), nexus(NULL) {}
|
||||
|
||||
Prefetch::~Prefetch() { signal(); waitfor(); }
|
||||
|
||||
void Prefetch::execute() {
|
||||
assert(nexus != NULL);
|
||||
while(1) {
|
||||
if(get_signaled()) return;
|
||||
if(cells.size() == 0 ||
|
||||
nexus->patches.ram_used > nexus->patches.ram_size) {
|
||||
relax(100);
|
||||
continue;
|
||||
}
|
||||
cells_mx.lock();
|
||||
|
||||
pop_heap(cells.begin(), cells.end());
|
||||
unsigned int cell = cells.back();
|
||||
cells.pop_back();
|
||||
|
||||
patch_mx.lock();
|
||||
Patch &patch = nexus->GetPatch(cell, false);
|
||||
patch_mx.unlock();
|
||||
|
||||
cells_mx.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
NexusMt::NexusMt(): vbo_mode(VBO_AUTO),
|
||||
metric(NULL), mode(SMOOTH), prefetching(true) {
|
||||
metric(NULL), mode(SMOOTH) {
|
||||
metric = new FrustumMetric();
|
||||
metric->index = &index;
|
||||
policy.error = 4;
|
||||
policy.ram_size = 64000000;
|
||||
|
||||
prefetch.nexus = this;
|
||||
target_error = 4.0f;
|
||||
extraction_max = 640000000;
|
||||
}
|
||||
|
||||
NexusMt::~NexusMt() {}
|
||||
NexusMt::~NexusMt() {
|
||||
if(metric)
|
||||
delete metric;
|
||||
}
|
||||
|
||||
bool NexusMt::Load(const string &filename, bool readonly) {
|
||||
if(!Nexus::Load(filename, readonly)) return false;
|
||||
bool NexusMt::Load(const string &filename) {
|
||||
index_file = fopen((filename + ".nxs").c_str(), "rb+");
|
||||
if(!index_file) return false;
|
||||
|
||||
unsigned int readed;
|
||||
readed = fread(&signature, sizeof(unsigned int), 1, index_file);
|
||||
if(!readed) return false;
|
||||
readed = fread(&totvert, sizeof(unsigned int), 1, index_file);
|
||||
if(!readed) return false;
|
||||
readed = fread(&totface, sizeof(unsigned int), 1, index_file);
|
||||
if(!readed) return false;
|
||||
readed = fread(&sphere, sizeof(Sphere3f), 1, index_file);
|
||||
if(!readed) return false;
|
||||
readed = fread(&chunk_size, sizeof(unsigned int), 1, index_file);
|
||||
if(!readed) return false;
|
||||
|
||||
unsigned int size; //size of index
|
||||
readed = fread(&size, sizeof(unsigned int), 1, index_file);
|
||||
if(!readed) return false;
|
||||
|
||||
index.resize(size);
|
||||
readed = fread(&index[0], sizeof(PatchInfo), size, index_file);
|
||||
if(readed != size) return false;
|
||||
|
||||
patches.ReadEntries(index_file);
|
||||
borders.ReadEntries(index_file);
|
||||
|
||||
//history size;
|
||||
fread(&size, sizeof(unsigned int), 1, index_file);
|
||||
vector<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++];
|
||||
}
|
||||
|
||||
fclose(index_file);
|
||||
index_file = NULL;
|
||||
|
||||
if(!patches.Load(filename + ".nxp", signature, chunk_size, true))
|
||||
return false;
|
||||
|
||||
LoadHistory();
|
||||
|
||||
policy.entries = &patches.patches;
|
||||
|
||||
|
||||
use_colors = false;
|
||||
use_normals = false;
|
||||
use_textures = false;
|
||||
|
@ -153,10 +173,14 @@ bool NexusMt::Load(const string &filename, bool readonly) {
|
|||
SetComponent(TEXTURE, true);
|
||||
SetComponent(DATA, true);
|
||||
|
||||
SetPrefetching(prefetching);
|
||||
SetPrefetchSize(patches.ram_max/2);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NexusMt::Close() {
|
||||
patches.Close();
|
||||
}
|
||||
|
||||
bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) {
|
||||
GLenum ret = glewInit();
|
||||
if(ret != GLEW_OK) return false;
|
||||
|
@ -164,26 +188,26 @@ bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) {
|
|||
cerr << "No vbo available!" << endl;
|
||||
vbo_mode = VBO_OFF;
|
||||
}
|
||||
patches.vbo_size = vbosize / patches.chunk_size;
|
||||
if(vbo_mode == VBO_OFF)
|
||||
patches.vbo_size = 0;
|
||||
patches.vbo_max = vbosize / chunk_size;
|
||||
if(vbo_mode == VBO_OFF)
|
||||
patches.vbo_max = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void NexusMt::Render() {
|
||||
patches.Flush();
|
||||
|
||||
vector<unsigned int> cells;
|
||||
metric->GetView();
|
||||
policy.Init();
|
||||
tri_total = 0;
|
||||
tri_rendered = 0;
|
||||
|
||||
|
||||
Extract(cells);
|
||||
Draw(cells);
|
||||
}
|
||||
|
||||
void NexusMt::Draw(vector<unsigned int> &cells) {
|
||||
|
||||
tri_total = 0;
|
||||
tri_rendered = 0;
|
||||
|
||||
Frustumf frustum;
|
||||
frustum.GetView();
|
||||
|
||||
|
@ -196,7 +220,7 @@ void NexusMt::Draw(vector<unsigned int> &cells) {
|
|||
|
||||
for(unsigned int i = 0; i < cells.size(); i++) {
|
||||
unsigned int cell = cells[i];
|
||||
Nexus::PatchInfo &entry = index[cell];
|
||||
PatchInfo &entry = index[cell];
|
||||
tri_total += entry.nface;
|
||||
//frustum culling
|
||||
if(frustum.IsOutside(entry.sphere.Center(), entry.sphere.Radius()))
|
||||
|
@ -204,21 +228,22 @@ void NexusMt::Draw(vector<unsigned int> &cells) {
|
|||
|
||||
tri_rendered += entry.nface;
|
||||
|
||||
Patch &patch = GetPatch(cell, false);
|
||||
QueuePServer::Data &data = patches.Lookup(cell,entry.nvert,entry.nface, 0);
|
||||
Patch &patch = *data.patch;
|
||||
char *fstart;
|
||||
char *vstart;
|
||||
char *cstart;
|
||||
char *nstart;
|
||||
|
||||
if(vbo_mode != VBO_OFF) {
|
||||
unsigned int vbo_array;
|
||||
unsigned int vbo_element;
|
||||
patches.GetVbo(cell, vbo_element, vbo_array);
|
||||
assert(vbo_element);
|
||||
assert(vbo_array);
|
||||
// unsigned int vbo_array;
|
||||
// unsigned int vbo_element;
|
||||
// patches.GetVbo(cell, vbo_element, vbo_array);
|
||||
assert(data.vbo_element);
|
||||
assert(data.vbo_array);
|
||||
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_array);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo_element);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, data.vbo_array);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, data.vbo_element);
|
||||
|
||||
fstart = NULL;
|
||||
vstart = NULL;
|
||||
|
@ -281,8 +306,8 @@ void NexusMt::Draw(vector<unsigned int> &cells) {
|
|||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
void NexusMt::SetRamExtractionSize(unsigned int r_size) {
|
||||
policy.ram_size = r_size/patches.chunk_size;
|
||||
void NexusMt::SetExtractionSize(unsigned int r_size) {
|
||||
extraction_max = r_size/patches.chunk_size;
|
||||
}
|
||||
|
||||
void NexusMt::SetMetric(NexusMt::MetricKind kind) {
|
||||
|
@ -291,24 +316,15 @@ void NexusMt::SetMetric(NexusMt::MetricKind kind) {
|
|||
}
|
||||
|
||||
void NexusMt::SetError(float error) {
|
||||
policy.error = error;
|
||||
target_error = error;
|
||||
}
|
||||
|
||||
void NexusMt::SetVboSize(unsigned int _vbo_size) {
|
||||
patches.vbo_size = _vbo_size;
|
||||
void NexusMt::SetVboSize(unsigned int _vbo_max) {
|
||||
patches.vbo_max = _vbo_max;
|
||||
}
|
||||
|
||||
void NexusMt::SetPrefetching(bool on) {
|
||||
if(on && prefetch.Running()) return;
|
||||
if(!on && !prefetch.Running()) return;
|
||||
if(on) {
|
||||
prefetch.cells.clear();
|
||||
prefetch.start();
|
||||
} else {
|
||||
prefetch.signal();
|
||||
prefetch.waitfor();
|
||||
}
|
||||
prefetching = on;
|
||||
void NexusMt::SetPrefetchSize(unsigned int size) {
|
||||
//TODO do something reasonable with this.
|
||||
}
|
||||
|
||||
bool NexusMt::SetMode(Mode _mode) {
|
||||
|
@ -370,8 +386,8 @@ void NexusMt::LoadHistory() {
|
|||
for(unsigned int i = 0; i < (*u).created.size(); i++) {
|
||||
unsigned int cell = (*u).created[i];
|
||||
if(index[cell].error > node.error)
|
||||
node.error = index[cell].error;
|
||||
|
||||
node.error = index[cell].error;
|
||||
|
||||
cell_node[cell] = current_node;
|
||||
}
|
||||
|
||||
|
@ -397,18 +413,18 @@ void NexusMt::LoadHistory() {
|
|||
vector<unsigned int> &cells = (*e).second;
|
||||
vector<unsigned int>::iterator k;
|
||||
for(k = cells.begin(); k != cells.end(); k++) {
|
||||
unsigned int cell = (*k);
|
||||
unsigned int cell = (*k);
|
||||
assert(cell < index.size());
|
||||
fr.push_back(cell);
|
||||
if(index[cell].error > max_err)
|
||||
max_err = index[cell].error;
|
||||
fr.push_back(cell);
|
||||
if(index[cell].error > max_err)
|
||||
max_err = index[cell].error;
|
||||
}
|
||||
//Add the new Frag to the node.
|
||||
unsigned int floor_node = (*e).first;
|
||||
Node &oldnode = nodes[floor_node];
|
||||
oldnode.frags.push_back(fr);
|
||||
if(node.error < max_err)
|
||||
node.error = max_err;
|
||||
node.error = max_err;
|
||||
|
||||
//Update in and out of the nodes.
|
||||
node.in.push_back(&oldnode);
|
||||
|
@ -454,10 +470,12 @@ void NexusMt::ClearHistory() {
|
|||
} */
|
||||
|
||||
void NexusMt::Extract(std::vector<unsigned int> &selected) {
|
||||
extraction_used = 0;
|
||||
|
||||
std::vector<Node>::iterator n;
|
||||
for(n = nodes.begin(); n != nodes.end(); n++) {
|
||||
(*n).visited = false;
|
||||
(*n).pushed = false;
|
||||
// (*n).pushed = false;
|
||||
}
|
||||
|
||||
std::vector<TNode> heap;
|
||||
|
@ -472,7 +490,7 @@ void NexusMt::Extract(std::vector<unsigned int> &selected) {
|
|||
Node *node = tnode.node;
|
||||
if(node->visited) continue;
|
||||
|
||||
bool expand = policy.Expand(tnode);
|
||||
bool expand = Expand(tnode);
|
||||
|
||||
if(expand)
|
||||
VisitNode(node, heap);
|
||||
|
@ -539,13 +557,22 @@ void NexusMt::VisitNode(Node *node, vector<TNode> &heap) {
|
|||
|
||||
for(unsigned int k = 0; k < node->out.size(); k++) {
|
||||
Node *outnode = node->out[k];
|
||||
float error = metric->GetError(node->frags[k]);
|
||||
// if(node->pushed) continue
|
||||
heap.push_back(TNode(outnode, error));
|
||||
float max_error = 0;
|
||||
|
||||
|
||||
for(unsigned int j = 0; j < node->frags[k].size(); j++) {
|
||||
unsigned int patch = node->frags[k][j];
|
||||
float error = metric->GetError(patch);
|
||||
if(max_error < error) max_error = error;
|
||||
visited.push_back(PServer::Item(patch, fabs(error - target_error)));
|
||||
// push_heap(visited.begin(), visited.end());
|
||||
}
|
||||
|
||||
heap.push_back(TNode(outnode, max_error));
|
||||
push_heap(heap.begin(), heap.end());
|
||||
}
|
||||
|
||||
node->visited = true;
|
||||
policy.NodeVisited(node);
|
||||
NodeVisited(node);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
#ifndef NXS_NEXUS_MT_H
|
||||
#define NXS_NEXUS_MT_H
|
||||
|
||||
|
||||
#include "nexus.h"
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <ptypes/pasync.h>
|
||||
#include <wrap/gui/frustum.h>
|
||||
|
||||
#include "nexusbase.h"
|
||||
#include "queuepserver.h"
|
||||
#include "borderserver.h"
|
||||
#include "prefetch.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
|
@ -19,7 +21,7 @@ namespace nxs {
|
|||
std::vector<Frag> frags;
|
||||
float error;
|
||||
bool visited;
|
||||
bool pushed;
|
||||
// bool pushed;
|
||||
};
|
||||
|
||||
struct TNode {
|
||||
|
@ -31,7 +33,7 @@ namespace nxs {
|
|||
|
||||
class Metric {
|
||||
public:
|
||||
vector<Nexus::PatchInfo> *index;
|
||||
std::vector<PatchInfo> *index;
|
||||
|
||||
float GetError(Node *node);
|
||||
float GetError(Frag &frag);
|
||||
|
@ -60,7 +62,7 @@ namespace nxs {
|
|||
float GetError(unsigned int cell);
|
||||
};
|
||||
|
||||
class Policy {
|
||||
/* class Policy {
|
||||
public:
|
||||
float error;
|
||||
int ram_used;
|
||||
|
@ -71,27 +73,9 @@ namespace nxs {
|
|||
void Init();
|
||||
bool Expand(TNode &node);
|
||||
void NodeVisited(Node *node);
|
||||
};
|
||||
};*/
|
||||
|
||||
class Prefetch: public pt::thread {
|
||||
public:
|
||||
Prefetch();
|
||||
~Prefetch();
|
||||
void execute();
|
||||
void cleanup() {}
|
||||
|
||||
bool Running() { return get_running(); }
|
||||
|
||||
std::vector<unsigned int> cells;
|
||||
pt::mutex cells_mx;
|
||||
pt::mutex patch_mx;
|
||||
Nexus *nexus;
|
||||
};
|
||||
|
||||
class NexusMt: public Nexus {
|
||||
private:
|
||||
std::vector<Node> nodes;
|
||||
Prefetch prefetch;
|
||||
class NexusMt: public NexusBase {
|
||||
public:
|
||||
//Vertex buffer object mode
|
||||
enum Vbo { VBO_AUTO, //autodetect best size
|
||||
|
@ -118,10 +102,13 @@ class NexusMt: public Nexus {
|
|||
Vbo vbo_mode;
|
||||
|
||||
Metric *metric;
|
||||
Policy policy;
|
||||
float target_error;
|
||||
|
||||
int extraction_max;
|
||||
int extraction_used;
|
||||
|
||||
|
||||
Mode mode;
|
||||
bool prefetching;
|
||||
|
||||
unsigned int components;
|
||||
bool use_normals;
|
||||
|
@ -132,31 +119,41 @@ class NexusMt: public Nexus {
|
|||
//statistics:
|
||||
unsigned int tri_rendered;
|
||||
unsigned int tri_total;
|
||||
|
||||
|
||||
std::vector<PServer::Item> visited;
|
||||
QueuePServer patches;
|
||||
BorderServer borders;
|
||||
|
||||
NexusMt();
|
||||
~NexusMt();
|
||||
|
||||
bool Load(const std::string &filename, bool readonly = true);
|
||||
bool InitGL(Vbo mode = VBO_AUTO, unsigned int vbo_size = 0);
|
||||
bool Load(const std::string &filename);
|
||||
void Close();
|
||||
|
||||
bool InitGL(Vbo mode = VBO_AUTO, unsigned int vbo_size = 64000000);
|
||||
|
||||
void Render();
|
||||
|
||||
void SetMetric(MetricKind kind);
|
||||
void SetError(float error);
|
||||
void SetRamExtractionSize(unsigned int ram_size);
|
||||
void SetExtractionSize(unsigned int ram_size);
|
||||
void SetPrefetchSize(unsigned int size);
|
||||
void SetVboSize(unsigned int vbo_size);
|
||||
|
||||
void SetPrefetching(bool on);
|
||||
|
||||
bool SetMode(Mode mode);
|
||||
bool SetComponent(Component c, bool on);
|
||||
bool SetComponents(unsigned int mask);
|
||||
|
||||
|
||||
void Draw(std::vector<unsigned int> &selected);
|
||||
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);
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.23 2004/12/01 18:46:21 ponchio
|
||||
Microchanges.
|
||||
|
||||
Revision 1.22 2004/11/28 04:16:19 ponchio
|
||||
*** empty log message ***
|
||||
|
||||
|
@ -234,7 +237,7 @@ int main(int argc, char *argv[]) {
|
|||
unsigned int ram_size = 640000;
|
||||
|
||||
nexus.SetError(error);
|
||||
nexus.SetRamExtractionSize(ram_size);
|
||||
nexus.SetExtractionSize(ram_size);
|
||||
nexus.SetMetric(NexusMt::FRUSTUM);
|
||||
if(!nexus.InitGL()) {
|
||||
cerr << "Could not init glew.\n";
|
||||
|
@ -271,16 +274,16 @@ int main(int argc, char *argv[]) {
|
|||
case SDLK_e: extract = !extract; break;
|
||||
case SDLK_c: show_colors = !show_colors; break;
|
||||
case SDLK_n: show_normals = !show_normals; break;
|
||||
case SDLK_9: nexus.patches.ram_size *= 0.8f; break;
|
||||
case SDLK_0: nexus.patches.ram_size *= 1.2f; break;
|
||||
// case SDLK_9: nexus.patches->ram_size *= 0.8f; break;
|
||||
// case SDLK_0: nexus.patches->ram_size *= 1.2f; break;
|
||||
|
||||
case SDLK_LEFT:
|
||||
ram_size *= 0.7;
|
||||
nexus.SetRamExtractionSize(ram_size);
|
||||
nexus.SetExtractionSize(ram_size);
|
||||
cerr << "Max extraction ram size: " << ram_size << endl; break;
|
||||
case SDLK_RIGHT:
|
||||
ram_size *= 1.5;
|
||||
nexus.SetRamExtractionSize(ram_size);
|
||||
nexus.SetExtractionSize(ram_size);
|
||||
cerr << "Max extraction ram size: " << ram_size << endl; break;
|
||||
|
||||
case SDLK_s: metric = NexusMt::FRUSTUM; break;
|
||||
|
@ -388,17 +391,17 @@ int main(int argc, char *argv[]) {
|
|||
static vector<unsigned int> cells;
|
||||
watch.Start();
|
||||
if(extract) {
|
||||
nexus.patches.Flush();
|
||||
// nexus.patches.Flush();
|
||||
|
||||
nexus.metric->GetView();
|
||||
nexus.policy.Init();
|
||||
// nexus.policy.Init();
|
||||
nexus.tri_total = 0;
|
||||
nexus.tri_rendered = 0;
|
||||
nexus.Extract(cells);
|
||||
}
|
||||
nexus.Draw(cells);
|
||||
|
||||
if(show_borders) {
|
||||
/* if(show_borders) {
|
||||
for(unsigned int i = 0; i < cells.size(); i++) {
|
||||
Border border = nexus.GetBorder(cells[i]);
|
||||
Patch &patch = nexus.GetPatch(cells[i]);
|
||||
|
@ -413,7 +416,7 @@ int main(int argc, char *argv[]) {
|
|||
glEnd();
|
||||
glPointSize(1);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//cerr Do some reporting:
|
||||
if(show_statistics) {
|
||||
|
@ -431,19 +434,19 @@ int main(int argc, char *argv[]) {
|
|||
char buffer[1024];
|
||||
glColor3f(1.0f, 1.0f, 1.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.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, "Extr size: %.3fMb(max) %.3fMb(cur)",
|
||||
nexus.policy.ram_size * nexus.chunk_size/(float)(1<<20),
|
||||
nexus.policy.ram_used * nexus.chunk_size/(float)(1<<20));
|
||||
nexus.extraction_max * nexus.chunk_size/(float)(1<<20),
|
||||
nexus.extraction_used * nexus.chunk_size/(float)(1<<20));
|
||||
gl_print(0.03, 0.09, buffer);
|
||||
|
||||
|
||||
sprintf(buffer, "Vbo size : %.3fMb(max) %.3fMb(cur)",
|
||||
nexus.patches.vbo_size * nexus.chunk_size/(float)(1<<20),
|
||||
nexus.patches.vbo_used * nexus.chunk_size/(float)(1<<20));
|
||||
nexus.patches.vbo_max * nexus.chunk_size/(float)(1<<20),
|
||||
nexus.patches.vbo_used * nexus.chunk_size/(float)(1<<20));
|
||||
gl_print(0.03, 0.06, buffer);
|
||||
|
||||
sprintf(buffer, "Triangles: %.2fK (tot) %.2fK (vis) "
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.10 2004/12/09 22:33:28 ponchio
|
||||
Different splitting optimization.
|
||||
|
||||
Revision 1.9 2004/12/04 13:22:55 ponchio
|
||||
*** empty log message ***
|
||||
|
||||
|
@ -282,7 +285,7 @@ void ThirdStep(const string &crudefile, const string &output,
|
|||
|
||||
Nexus nexus;
|
||||
//TODO here i really need no ram_buffer.....
|
||||
nexus.patches.SetRamBufferSize(0);
|
||||
nexus.MaxRamBuffer(0);
|
||||
if(!nexus.Create(output, NXS_FACES, chunk_size)) {
|
||||
cerr << "Could not create nexus output: " << output << endl;
|
||||
getchar();
|
||||
|
@ -384,6 +387,7 @@ void ThirdStep(const string &crudefile, const string &output,
|
|||
cerr << "Could not save: " << output << ".rvi\n";
|
||||
exit(0);
|
||||
}
|
||||
nexus.Close();
|
||||
}
|
||||
|
||||
void FourthStep(const string &crudefile, const string &output,
|
||||
|
@ -393,7 +397,7 @@ void FourthStep(const string &crudefile, const string &output,
|
|||
cerr << "Could not load nexus " << output << endl;
|
||||
exit(0);
|
||||
}
|
||||
nexus.patches.SetRamBufferSize(ram_buffer);
|
||||
nexus.MaxRamBuffer(ram_buffer);
|
||||
//TODO Clear borders in case of failure!
|
||||
|
||||
VFile<unsigned int> vert_remap;
|
||||
|
@ -411,7 +415,7 @@ void FourthStep(const string &crudefile, const string &output,
|
|||
|
||||
for(int start = 0; start < nexus.index.size(); start++) {
|
||||
report.Step(start);
|
||||
Nexus::PatchInfo &s_entry = nexus.index[start];
|
||||
PatchInfo &s_entry = nexus.index[start];
|
||||
|
||||
vector<Link> links;
|
||||
#ifdef WIN32
|
||||
|
@ -427,7 +431,7 @@ void FourthStep(const string &crudefile, const string &output,
|
|||
for(int end = 0; end < nexus.index.size(); end++) {
|
||||
if(start == end) continue;
|
||||
|
||||
Nexus::PatchInfo &e_entry = nexus.index[end];
|
||||
PatchInfo &e_entry = nexus.index[end];
|
||||
float dist = Distance(s_entry.sphere, e_entry.sphere);
|
||||
|
||||
if(dist > s_entry.sphere.Radius() + e_entry.sphere.Radius()) {
|
||||
|
@ -467,7 +471,7 @@ void FifthStep(const string &crudefile, const string &output,
|
|||
cerr << "Could not load nexus " << output << endl;
|
||||
exit(0);
|
||||
}
|
||||
nexus.patches.SetRamBufferSize(ram_buffer);
|
||||
nexus.MaxRamBuffer(ram_buffer);
|
||||
|
||||
VChain vchain;
|
||||
if(!vchain.Load(output + ".vchain")) {
|
||||
|
@ -482,7 +486,7 @@ void FifthStep(const string &crudefile, const string &output,
|
|||
}
|
||||
nexus.history.push_back(update);
|
||||
nexus.Unify();
|
||||
nexus.patches.FlushAll();
|
||||
nexus.patches.Flush();
|
||||
|
||||
|
||||
Dispatcher dispatcher(&nexus, &vchain);
|
||||
|
@ -752,7 +756,7 @@ void SaveFragment(Nexus &nexus, VChain &chain,
|
|||
patch.face.size()/3,
|
||||
bordsize);
|
||||
patch_levels.push_back(current_level);
|
||||
Nexus::PatchInfo &entry = nexus.index[patch_idx];
|
||||
PatchInfo &entry = nexus.index[patch_idx];
|
||||
entry.error = fragout.error;
|
||||
|
||||
patch_remap[i] = patch_idx;
|
||||
|
@ -780,7 +784,7 @@ void SaveFragment(Nexus &nexus, VChain &chain,
|
|||
memcpy(patch.VertBegin(), &outpatch.vert[0],
|
||||
outpatch.vert.size() * sizeof(Point3f));
|
||||
|
||||
Nexus::PatchInfo &entry = nexus.index[patch_idx];
|
||||
PatchInfo &entry = nexus.index[patch_idx];
|
||||
for(unsigned int v = 0; v < outpatch.vert.size(); v++) {
|
||||
entry.sphere.Add(outpatch.vert[v]);
|
||||
nexus.sphere.Add(outpatch.vert[v]);
|
||||
|
|
|
@ -211,7 +211,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
|
||||
Nexus nexus;
|
||||
nexus.patches.SetRamBufferSize(ram_size);
|
||||
nexus.MaxRamBuffer(ram_size);
|
||||
if(!nexus.Load(input, true)) {
|
||||
cerr << "Could not open nexus file: " << input << "\n";
|
||||
return -1;
|
||||
|
@ -312,7 +312,7 @@ int main(int argc, char *argv[]) {
|
|||
cout << "Writing to nexus: " << output << endl;
|
||||
|
||||
Nexus out;
|
||||
out.patches.SetRamBufferSize(ram_size);
|
||||
out.MaxRamBuffer(ram_size);
|
||||
if(!chunk_size)
|
||||
chunk_size = nexus.patches.chunk_size;
|
||||
|
||||
|
@ -327,7 +327,7 @@ int main(int argc, char *argv[]) {
|
|||
cout << "Copying and allocating...\n";
|
||||
for(unsigned int patch = 0; patch < nexus.index.size(); patch++) {
|
||||
report.Step(patch);
|
||||
Nexus::PatchInfo &src_entry = nexus.index[patch];
|
||||
PatchInfo &src_entry = nexus.index[patch];
|
||||
Patch src_patch = nexus.GetPatch(patch);
|
||||
Border src_border = nexus.GetBorder(patch);
|
||||
|
||||
|
@ -341,7 +341,7 @@ int main(int argc, char *argv[]) {
|
|||
out.AddPatch(src_entry.nvert, src_entry.nface, src_border.Available());
|
||||
|
||||
|
||||
Nexus::PatchInfo &dst_entry = out.index[patch];
|
||||
PatchInfo &dst_entry = out.index[patch];
|
||||
|
||||
Patch dst_patch = out.GetPatch(patch);
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ int main(int argc, char *argv[]) {
|
|||
Report report(nexus.index.size());
|
||||
for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) {
|
||||
report.Step(patchid);
|
||||
Nexus::PatchInfo &info = nexus.index[patchid];
|
||||
PatchInfo &info = nexus.index[patchid];
|
||||
Patch &patch = nexus.GetPatch(patchid);
|
||||
for(int f = 0; f < patch.nf; f++) {
|
||||
unsigned short *face = patch.Face(f);
|
||||
|
@ -52,7 +52,7 @@ int main(int argc, char *argv[]) {
|
|||
cerr << "Testing borders\n";
|
||||
|
||||
for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) {
|
||||
Nexus::PatchInfo &info = nexus.index[patchid];
|
||||
PatchInfo &info = nexus.index[patchid];
|
||||
Border border = nexus.GetBorder(patchid);
|
||||
for(unsigned int i = 0; i < border.Size(); i++) {
|
||||
Link &link = border[i];
|
||||
|
@ -80,7 +80,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
cerr << "Reciprocity borders test\n";
|
||||
for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) {
|
||||
Nexus::PatchInfo &info = nexus.index[patchid];
|
||||
PatchInfo &info = nexus.index[patchid];
|
||||
Border border = nexus.GetBorder(patchid);
|
||||
vector<Link> links;
|
||||
links.resize(border.Size());
|
||||
|
@ -125,4 +125,4 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
#include "prefetch.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace nxs;
|
||||
|
||||
|
||||
void Prefetch::init(NexusMt *m, std::vector<unsigned int> &selected,
|
||||
std::vector<PServer::Item> &visited) {
|
||||
safety.lock();
|
||||
mt = m;
|
||||
missing.clear();
|
||||
|
||||
std::map<unsigned int, float> tmp;
|
||||
for(unsigned int i = 0; i < selected.size(); i++) {
|
||||
unsigned int patch = selected[i];
|
||||
tmp[patch] = 0.0f;
|
||||
missing.push_back(PServer::Item(patch, 0.0f));
|
||||
}
|
||||
for(unsigned int i = 0; i < visited.size(); i++) {
|
||||
PServer::Item &item = visited[i];
|
||||
if(tmp.count(item.patch)) continue;
|
||||
if(mt->patches.IsLoaded(item.patch))
|
||||
tmp[item.patch] = item.priority;
|
||||
else
|
||||
missing.push_back(item);
|
||||
}
|
||||
|
||||
QueuePServer &ps = mt->patches;
|
||||
for(unsigned int i = 0; i < ps.heap.size(); i++) {
|
||||
PServer::Item &item = ps.heap[i];
|
||||
if(tmp.count(item.patch))
|
||||
item.priority = tmp[item.patch];
|
||||
else
|
||||
item.priority = 1e40;
|
||||
}
|
||||
make_heap(ps.heap.begin(), ps.heap.end());
|
||||
sort(missing.begin(), missing.end()); //CRITICAL reverse pero'!
|
||||
reverse(missing.begin(), missing.end());
|
||||
safety.unlock();
|
||||
}
|
||||
|
||||
void Prefetch::execute() {
|
||||
while(1) {
|
||||
if(get_signaled()) return;
|
||||
while(1) {
|
||||
safety.lock();
|
||||
if(missing.size() == 0) break;
|
||||
PServer::Item item = missing.back();
|
||||
missing.pop_back();
|
||||
PatchInfo &info = mt->index[item.patch];
|
||||
mt->patches.Lookup(item.patch, info.nvert, info.nface, item.priority);
|
||||
safety.unlock();
|
||||
}
|
||||
relax(50);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef NXS_PREFETCH_H
|
||||
#define NXS_PREFETCH_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <ptypes/pasync.h>
|
||||
|
||||
#include "nexusmt.h"
|
||||
#include "queuepserver.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
class NexusMt;
|
||||
|
||||
class Prefetch: public pt::thread{
|
||||
public:
|
||||
|
||||
pt::mutex safety;
|
||||
unsigned int ram_max;
|
||||
unsigned int ram_used;
|
||||
|
||||
NexusMt *mt;
|
||||
std::vector<PServer::Item> missing;
|
||||
|
||||
|
||||
Prefetch(): thread(false) {}
|
||||
~Prefetch() {
|
||||
waitfor();
|
||||
}
|
||||
|
||||
void init(NexusMt *m,
|
||||
std::vector<unsigned int> &selected,
|
||||
std::vector<PServer::Item> &visited);
|
||||
void execute();
|
||||
void cleanup() {}
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,158 @@
|
|||
#include <iostream>
|
||||
#include "pserver.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace nxs;
|
||||
|
||||
|
||||
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_readed = 0;
|
||||
ram_flushed = 0;
|
||||
|
||||
return MFile::Create(filename);
|
||||
}
|
||||
|
||||
bool PServer::Load(const std::string &filename, Signature sig,
|
||||
unsigned int csize, bool readonly,
|
||||
unsigned int rsize) {
|
||||
|
||||
signature = sig;
|
||||
chunk_size = csize;
|
||||
|
||||
ram_max = rsize/chunk_size + 1;
|
||||
ram_used = 0;
|
||||
|
||||
ram_readed = 0;
|
||||
ram_flushed = 0;
|
||||
|
||||
return MFile::Load(filename, readonly);
|
||||
}
|
||||
|
||||
void PServer::Close() {
|
||||
Flush();
|
||||
MFile::Close();
|
||||
}
|
||||
|
||||
//TODO add error checking.
|
||||
bool PServer::ReadEntries(FILE *fp) {
|
||||
unsigned int n;
|
||||
fread(&n, 1, sizeof(int), fp);
|
||||
entries.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);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PServer::WriteEntries(FILE *fp) {
|
||||
unsigned int n = entries.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);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PServer::AddPatch(unsigned short nvert, unsigned short nface) {
|
||||
Entry entry;
|
||||
entry.patch_start = 0xffffffff;
|
||||
entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size);
|
||||
entry.disk_size = 0xffff;
|
||||
entries.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];
|
||||
|
||||
char *ram = new char[entry.ram_size * chunk_size];
|
||||
#ifdef CONTROLS
|
||||
if(!ram) {
|
||||
cerr << "COuld not allocate ram!\n";
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
Patch *patch = new Patch(signature, ram, nvert, nface);
|
||||
|
||||
if(entry.patch_start != 0xffffffff) { //was allocated.
|
||||
assert(entry.disk_size != 0xffff);
|
||||
|
||||
SetPosition((int64)entry.patch_start * (int64)chunk_size);
|
||||
|
||||
if((signature & NXS_COMPRESSED) == 0) { //not compressed
|
||||
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);
|
||||
|
||||
patch->Decompress(entry.ram_size * chunk_size,
|
||||
disk, entry.disk_size * chunk_size);
|
||||
delete []disk;
|
||||
}
|
||||
}
|
||||
ram_used += entry.ram_size;
|
||||
ram_readed += entry.ram_size;
|
||||
|
||||
return patch;
|
||||
}
|
||||
|
||||
void PServer::FlushPatch(unsigned int id, Patch *patch) {
|
||||
|
||||
Entry &entry = entries[id];
|
||||
|
||||
if(!readonly) { //write back patch
|
||||
if((signature & NXS_COMPRESSED)) {
|
||||
unsigned int compressed_size;
|
||||
char *compressed = 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);
|
||||
}
|
||||
SetPosition((int64)entry.patch_start * (int64)chunk_size);
|
||||
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);
|
||||
}
|
||||
SetPosition((int64)entry.patch_start * (int64)chunk_size);
|
||||
WriteBuffer(patch->start, entry.disk_size * chunk_size);
|
||||
}
|
||||
}
|
||||
|
||||
delete [](patch->start);
|
||||
delete patch;
|
||||
|
||||
ram_used -= entry.ram_size;
|
||||
ram_flushed += entry.ram_size;
|
||||
}
|
||||
|
||||
void PServer::MaxRamBuffer(unsigned int r_buffer) {
|
||||
ram_max = (unsigned int)(r_buffer/chunk_size) + 1;
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
#ifndef NXS_PSERVER_H
|
||||
#define NXS_PSERVER_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include "patch.h"
|
||||
#include "mfile.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
class PServer: public MFile {
|
||||
public:
|
||||
|
||||
struct Entry {
|
||||
unsigned int patch_start; //granularita' Chunk
|
||||
unsigned short ram_size; //in chunks
|
||||
unsigned short disk_size; // in chunks (used when compressed)
|
||||
};
|
||||
|
||||
/* struct Data {
|
||||
// unsigned int npatch;
|
||||
Patch *patch;
|
||||
unsigned int vbo_array;
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Signature signature;
|
||||
unsigned int chunk_size;
|
||||
|
||||
unsigned int ram_max;
|
||||
unsigned int ram_used;
|
||||
|
||||
//statistics:
|
||||
unsigned int ram_readed;
|
||||
unsigned int ram_flushed;
|
||||
|
||||
//pt::rwlock ramlock; //read only thread safety...
|
||||
//pt::rwlock disklock; //read only thread safety...
|
||||
|
||||
std::vector<Entry> entries;
|
||||
|
||||
|
||||
|
||||
PServer(): chunk_size(1024),
|
||||
ram_max(128000000),
|
||||
ram_used(0) {}
|
||||
virtual ~PServer() {
|
||||
std::cerr << "Closing pserver" << std::endl;
|
||||
MFile::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);
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
}//namespace
|
||||
#endif
|
|
@ -0,0 +1,85 @@
|
|||
#include <GL/glew.h>
|
||||
|
||||
#include "queuepserver.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace nxs;
|
||||
|
||||
|
||||
QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
|
||||
unsigned short nv, unsigned short nf,
|
||||
float priority) {
|
||||
if(index.count(patch)) {
|
||||
return index[patch];
|
||||
} else {
|
||||
while(ram_used > ram_max) {
|
||||
pop_heap(heap.begin(), heap.end());
|
||||
Item item = heap.back();
|
||||
if(item.priority == 0) break; //no deleting needed patches.
|
||||
Data &data = index[patch];
|
||||
FlushVbo(data);
|
||||
FlushPatch(patch, data.patch);
|
||||
index.erase(patch);
|
||||
}
|
||||
Item item(patch, priority);
|
||||
heap.push_back(item);
|
||||
push_heap(heap.begin(), heap.end());
|
||||
Data &data = index[patch];
|
||||
data.patch = LoadPatch(patch, nv, nf);
|
||||
LoadVbo(data);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
bool QueuePServer::IsLoaded(unsigned int patch) {
|
||||
return index.count(patch);
|
||||
}
|
||||
void QueuePServer::Flush() {
|
||||
std::map<unsigned int, Data>::iterator i;
|
||||
for(i = index.begin(); i != index.end(); i++) {
|
||||
FlushVbo((*i).second);
|
||||
FlushPatch((*i).first, (*i).second.patch);
|
||||
}
|
||||
}
|
||||
|
||||
void QueuePServer::LoadVbo(Data &data) {
|
||||
if(!vbo_max) return;
|
||||
Patch &patch = *data.patch;
|
||||
glGenBuffersARB(1, &data.vbo_element);
|
||||
assert(data.vbo_element);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, data.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, &data.vbo_array);
|
||||
assert(data.vbo_array);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, data.vbo_array);
|
||||
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, patch.VertBegin(),
|
||||
GL_STATIC_DRAW_ARB);
|
||||
|
||||
vbo_used += size;
|
||||
}
|
||||
void QueuePServer::FlushVbo(Data &data) {
|
||||
if(!vbo_max) return;
|
||||
assert(data.vbo_element);
|
||||
assert(data.vbo_array);
|
||||
glDeleteBuffersARB(1, &data.vbo_element);
|
||||
glDeleteBuffersARB(1, &data.vbo_array);
|
||||
data.vbo_element = 0;
|
||||
data.vbo_array = 0;
|
||||
|
||||
Patch &patch = *data.patch;
|
||||
vbo_used -= patch.nf * sizeof(unsigned short);
|
||||
vbo_used -= sizeof(float) * patch.dstart;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef NXS_QUEUE_PSERVER_H
|
||||
#define NXS_QUEUE_PSERVER_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "pserver.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
class QueuePServer: public PServer {
|
||||
public:
|
||||
|
||||
struct Data {
|
||||
Patch *patch;
|
||||
unsigned int vbo_array;
|
||||
unsigned int vbo_element;
|
||||
Data(): patch(NULL), vbo_array(0), vbo_element(0) {}
|
||||
};
|
||||
|
||||
unsigned int vbo_used;
|
||||
unsigned int vbo_max;
|
||||
|
||||
std::map<unsigned int, Data> index;
|
||||
std::vector<Item> heap;
|
||||
|
||||
Data &Lookup(unsigned int patch, unsigned short nv, unsigned short nf,
|
||||
float priority = 0.0f);
|
||||
|
||||
bool IsLoaded(unsigned int patch);
|
||||
void Flush();
|
||||
|
||||
protected:
|
||||
|
||||
void LoadVbo(Data &data);
|
||||
void FlushVbo(Data &data);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue