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 <assert.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "nexus.h"
|
#include "nexus.h"
|
||||||
|
#include "lrupserver.h"
|
||||||
|
#include "queuepserver.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace vcg;
|
using namespace vcg;
|
||||||
using namespace nxs;
|
using namespace nxs;
|
||||||
|
|
||||||
Nexus::Nexus(): index_file(NULL) {}
|
|
||||||
Nexus::~Nexus() {
|
Nexus::~Nexus() {
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
@ -27,6 +31,8 @@ bool Nexus::Create(const string &file, Signature sig, unsigned int c_size) {
|
||||||
|
|
||||||
chunk_size = c_size;
|
chunk_size = c_size;
|
||||||
|
|
||||||
|
history.clear();
|
||||||
|
|
||||||
if(!patches.Create(file + ".nxp", signature, chunk_size)) {
|
if(!patches.Create(file + ".nxp", signature, chunk_size)) {
|
||||||
cerr << "Could not create file: " << file << ".nxp" << endl;
|
cerr << "Could not create file: " << file << ".nxp" << endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -40,7 +46,10 @@ bool Nexus::Create(const string &file, Signature sig, unsigned int c_size) {
|
||||||
return true;
|
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+");
|
index_file = fopen((file + ".nxs").c_str(), "rb+");
|
||||||
if(!index_file) return false;
|
if(!index_file) return false;
|
||||||
|
|
||||||
|
@ -63,6 +72,7 @@ bool Nexus::Load(const string &file, bool readonly) {
|
||||||
index.resize(size);
|
index.resize(size);
|
||||||
readed = fread(&index[0], sizeof(PatchInfo), size, index_file);
|
readed = fread(&index[0], sizeof(PatchInfo), size, index_file);
|
||||||
if(readed != size) return false;
|
if(readed != size) return false;
|
||||||
|
|
||||||
patches.ReadEntries(index_file);
|
patches.ReadEntries(index_file);
|
||||||
borders.ReadEntries(index_file);
|
borders.ReadEntries(index_file);
|
||||||
|
|
||||||
|
@ -88,18 +98,24 @@ bool Nexus::Load(const string &file, bool readonly) {
|
||||||
history[i].created[e] = buffer[pos++];
|
history[i].created[e] = buffer[pos++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(readonly) {
|
||||||
|
fclose(index_file);
|
||||||
|
index_file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//TODO support readonly
|
//TODO support readonly
|
||||||
if(!patches.Load(file + ".nxp", signature, chunk_size, readonly))
|
if(!patches.Load(file + ".nxp", signature, chunk_size, readonly))
|
||||||
return false;
|
return false;
|
||||||
if(!borders.Load(file + ".nxb", readonly, 1, 500)) return false;
|
if(!borders.Load(file + ".nxb", readonly, 1, 500))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nexus::Close() {
|
void Nexus::Close() {
|
||||||
patches.Close();
|
patches.Close();
|
||||||
borders.Close();
|
borders.Close();
|
||||||
|
|
||||||
if(!index_file) return;
|
if(!index_file) return;
|
||||||
|
|
||||||
rewind(index_file);
|
rewind(index_file);
|
||||||
|
|
||||||
fwrite(&signature, sizeof(unsigned int), 1, index_file);
|
fwrite(&signature, sizeof(unsigned int), 1, index_file);
|
||||||
|
@ -112,6 +128,8 @@ void Nexus::Close() {
|
||||||
fwrite(&size, sizeof(unsigned int), 1, index_file);
|
fwrite(&size, sizeof(unsigned int), 1, index_file);
|
||||||
fwrite(&(index[0]), sizeof(PatchInfo), size, 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);
|
patches.WriteEntries(index_file);
|
||||||
borders.WriteEntries(index_file);
|
borders.WriteEntries(index_file);
|
||||||
|
|
||||||
|
@ -131,7 +149,6 @@ void Nexus::Close() {
|
||||||
fwrite(&size, sizeof(unsigned int), 1, index_file);
|
fwrite(&size, sizeof(unsigned int), 1, index_file);
|
||||||
fwrite(&(buffer[0]), sizeof(unsigned int), size, index_file);
|
fwrite(&(buffer[0]), sizeof(unsigned int), size, index_file);
|
||||||
|
|
||||||
|
|
||||||
fclose(index_file);
|
fclose(index_file);
|
||||||
index_file = NULL;
|
index_file = NULL;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +156,7 @@ void Nexus::Close() {
|
||||||
Patch &Nexus::GetPatch(unsigned int patch, bool flush) {
|
Patch &Nexus::GetPatch(unsigned int patch, bool flush) {
|
||||||
assert(patch < index.size());
|
assert(patch < index.size());
|
||||||
PatchInfo &info = index[patch];
|
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) {
|
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;
|
return index.size() -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Nexus::SetRamBufferSize(unsigned int r_size) {
|
void Nexus::MaxRamBuffer(unsigned int r_size) {
|
||||||
patches.SetRamBufferSize(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) {
|
void Nexus::Unify(float threshold) {
|
||||||
//TODO what if colors or normals or strips?
|
//TODO what if colors or normals or strips?
|
||||||
//TODO update totvert
|
|
||||||
unsigned int duplicated = 0;
|
unsigned int duplicated = 0;
|
||||||
unsigned int degenerate = 0;
|
unsigned int degenerate = 0;
|
||||||
|
|
||||||
|
|
|
@ -3,57 +3,23 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
|
||||||
#include <vcg/space/point3.h>
|
|
||||||
|
|
||||||
#include "patchserver.h"
|
#include "nexusbase.h"
|
||||||
|
#include "lrupserver.h"
|
||||||
#include "borderserver.h"
|
#include "borderserver.h"
|
||||||
|
|
||||||
namespace nxs {
|
namespace nxs {
|
||||||
|
|
||||||
|
class Nexus: public NexusBase {
|
||||||
struct PatchInfo {
|
|
||||||
unsigned short nvert;
|
|
||||||
unsigned short nface;
|
|
||||||
|
|
||||||
vcg::Sphere3f sphere;
|
|
||||||
float error;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Nexus {
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct BorderEntry {
|
Nexus() {}
|
||||||
unsigned int border_start; //granuralita' Link
|
~Nexus();
|
||||||
unsigned short border_size; //in Links
|
|
||||||
unsigned short border_used; //in Links
|
|
||||||
};
|
|
||||||
|
|
||||||
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,
|
bool Create(const std::string &filename, Signature signature,
|
||||||
unsigned int chunk_size = 1024);
|
unsigned int chunk_size = 1024);
|
||||||
virtual bool Load(const std::string &filename, bool readonly = false);
|
bool Load(const std::string &filename, bool readonly = false);
|
||||||
virtual void Close();
|
void Close();
|
||||||
|
|
||||||
unsigned int AddPatch(unsigned int nv, unsigned int nf, unsigned int nb);
|
unsigned int AddPatch(unsigned int nv, unsigned int nf, unsigned int nb);
|
||||||
Patch &GetPatch(unsigned int patch, bool flush = true);
|
Patch &GetPatch(unsigned int patch, bool flush = true);
|
||||||
|
@ -67,12 +33,7 @@ class Nexus {
|
||||||
bool HasNormalsShort() { return (signature & NXS_NORMALS_SHORT) != 0; }
|
bool HasNormalsShort() { return (signature & NXS_NORMALS_SHORT) != 0; }
|
||||||
bool HasNormalsFloat() { return (signature & NXS_NORMALS_FLOAT) != 0; }
|
bool HasNormalsFloat() { return (signature & NXS_NORMALS_FLOAT) != 0; }
|
||||||
|
|
||||||
void SetRamBufferSize(unsigned int ram_size);
|
void MaxRamBuffer(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);*/
|
|
||||||
|
|
||||||
//move to nxsalgo!
|
//move to nxsalgo!
|
||||||
void Unify(float threshold = 0.0f);
|
void Unify(float threshold = 0.0f);
|
||||||
|
@ -82,24 +43,24 @@ class Nexus {
|
||||||
|
|
||||||
//BE CAREFUL: this 2 members get replicated into patchserver
|
//BE CAREFUL: this 2 members get replicated into patchserver
|
||||||
//TODO fix this nasty thing it is dangerous as it is.
|
//TODO fix this nasty thing it is dangerous as it is.
|
||||||
Signature signature;
|
// Signature signature;
|
||||||
unsigned int chunk_size;
|
// unsigned int chunk_size;
|
||||||
|
|
||||||
unsigned int totvert;
|
// unsigned int totvert;
|
||||||
unsigned int totface;
|
// unsigned int totface;
|
||||||
vcg::Sphere3f sphere;
|
// vcg::Sphere3f sphere;
|
||||||
|
|
||||||
std::vector<PatchInfo> index;
|
// std::vector<PatchInfo> index;
|
||||||
|
|
||||||
PatchServer patches;
|
LruPServer patches;
|
||||||
BorderServer borders;
|
BorderServer borders;
|
||||||
|
|
||||||
std::vector<Update> history;
|
// std::vector<Update> history;
|
||||||
|
|
||||||
bool readonly;
|
// bool readonly;
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
FILE *index_file;
|
// 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 FrustumMetric::GetError(unsigned int cell) {
|
||||||
float max_error = 0;
|
float max_error = 0;
|
||||||
Nexus::PatchInfo &entry = (*index)[cell];
|
PatchInfo &entry = (*index)[cell];
|
||||||
Sphere3f &sphere = entry.sphere;
|
Sphere3f &sphere = entry.sphere;
|
||||||
float dist = Distance(sphere, frustum.ViewPoint());
|
float dist = Distance(sphere, frustum.ViewPoint());
|
||||||
if(dist < 0) return 1e20f;
|
if(dist < 0) return 1e20f;
|
||||||
float error = entry.error/frustum.Resolution(dist);
|
float error = entry.error/frustum.Resolution(dist);
|
||||||
if(frustum.IsOutside(sphere.Center(), sphere.Radius()))
|
if(frustum.IsOutside(sphere.Center(), sphere.Radius()))
|
||||||
error /= 4;
|
error /= 256;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Policy::Init() {
|
bool NexusMt::Expand(TNode &node) {
|
||||||
ram_used = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Policy::Expand(TNode &node) {
|
|
||||||
//expand if node error > target error
|
//expand if node error > target error
|
||||||
if(ram_used >= ram_size) return false;
|
if(extraction_used >= extraction_max) return false;
|
||||||
//cerr << "Error: " << error << " node.error: " << node.error << endl;
|
return node.error > target_error;
|
||||||
return node.error > error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Policy::NodeVisited(Node *node) {
|
void NexusMt::NodeVisited(Node *node) {
|
||||||
//TODO write this a bit more elegant.
|
//TODO write this a bit more elegant.
|
||||||
//first we process arcs removed:
|
//first we process arcs removed:
|
||||||
|
|
||||||
|
@ -77,8 +72,8 @@ void Policy::NodeVisited(Node *node) {
|
||||||
assert(!(node->out[i]->visited));
|
assert(!(node->out[i]->visited));
|
||||||
Frag &frag = node->frags[i];
|
Frag &frag = node->frags[i];
|
||||||
for(unsigned int k = 0; k < frag.size(); k++) {
|
for(unsigned int k = 0; k < frag.size(); k++) {
|
||||||
PatchEntry &entry = (*entries)[frag[k]];
|
PServer::Entry &entry = patches.entries[frag[k]];
|
||||||
ram_used += entry.ram_size;
|
extraction_used += entry.ram_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,59 +85,84 @@ void Policy::NodeVisited(Node *node) {
|
||||||
if((*from)->out[i] == node) {
|
if((*from)->out[i] == node) {
|
||||||
vector<unsigned int> &frag = frags[i];
|
vector<unsigned int> &frag = frags[i];
|
||||||
for(unsigned int k = 0; k < frag.size(); k++) {
|
for(unsigned int k = 0; k < frag.size(); k++) {
|
||||||
PatchEntry &entry = (*entries)[frag[k]];
|
PServer::Entry &entry = patches.entries[frag[k]];
|
||||||
ram_used -= entry.ram_size;
|
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),
|
NexusMt::NexusMt(): vbo_mode(VBO_AUTO),
|
||||||
metric(NULL), mode(SMOOTH), prefetching(true) {
|
metric(NULL), mode(SMOOTH) {
|
||||||
metric = new FrustumMetric();
|
metric = new FrustumMetric();
|
||||||
metric->index = &index;
|
metric->index = &index;
|
||||||
policy.error = 4;
|
target_error = 4.0f;
|
||||||
policy.ram_size = 64000000;
|
extraction_max = 640000000;
|
||||||
|
|
||||||
prefetch.nexus = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NexusMt::~NexusMt() {}
|
NexusMt::~NexusMt() {
|
||||||
|
if(metric)
|
||||||
|
delete metric;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
bool NexusMt::Load(const string &filename, bool readonly) {
|
|
||||||
if(!Nexus::Load(filename, readonly)) return false;
|
|
||||||
LoadHistory();
|
LoadHistory();
|
||||||
|
|
||||||
policy.entries = &patches.patches;
|
|
||||||
|
|
||||||
use_colors = false;
|
use_colors = false;
|
||||||
use_normals = false;
|
use_normals = false;
|
||||||
use_textures = false;
|
use_textures = false;
|
||||||
|
@ -153,10 +173,14 @@ bool NexusMt::Load(const string &filename, bool readonly) {
|
||||||
SetComponent(TEXTURE, true);
|
SetComponent(TEXTURE, true);
|
||||||
SetComponent(DATA, true);
|
SetComponent(DATA, true);
|
||||||
|
|
||||||
SetPrefetching(prefetching);
|
SetPrefetchSize(patches.ram_max/2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NexusMt::Close() {
|
||||||
|
patches.Close();
|
||||||
|
}
|
||||||
|
|
||||||
bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) {
|
bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) {
|
||||||
GLenum ret = glewInit();
|
GLenum ret = glewInit();
|
||||||
if(ret != GLEW_OK) return false;
|
if(ret != GLEW_OK) return false;
|
||||||
|
@ -164,26 +188,26 @@ bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) {
|
||||||
cerr << "No vbo available!" << endl;
|
cerr << "No vbo available!" << endl;
|
||||||
vbo_mode = VBO_OFF;
|
vbo_mode = VBO_OFF;
|
||||||
}
|
}
|
||||||
patches.vbo_size = vbosize / patches.chunk_size;
|
patches.vbo_max = vbosize / chunk_size;
|
||||||
if(vbo_mode == VBO_OFF)
|
if(vbo_mode == VBO_OFF)
|
||||||
patches.vbo_size = 0;
|
patches.vbo_max = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexusMt::Render() {
|
void NexusMt::Render() {
|
||||||
patches.Flush();
|
|
||||||
|
|
||||||
vector<unsigned int> cells;
|
vector<unsigned int> cells;
|
||||||
metric->GetView();
|
metric->GetView();
|
||||||
policy.Init();
|
|
||||||
tri_total = 0;
|
|
||||||
tri_rendered = 0;
|
|
||||||
|
|
||||||
Extract(cells);
|
Extract(cells);
|
||||||
Draw(cells);
|
Draw(cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexusMt::Draw(vector<unsigned int> &cells) {
|
void NexusMt::Draw(vector<unsigned int> &cells) {
|
||||||
|
|
||||||
|
tri_total = 0;
|
||||||
|
tri_rendered = 0;
|
||||||
|
|
||||||
Frustumf frustum;
|
Frustumf frustum;
|
||||||
frustum.GetView();
|
frustum.GetView();
|
||||||
|
|
||||||
|
@ -196,7 +220,7 @@ void NexusMt::Draw(vector<unsigned int> &cells) {
|
||||||
|
|
||||||
for(unsigned int i = 0; i < cells.size(); i++) {
|
for(unsigned int i = 0; i < cells.size(); i++) {
|
||||||
unsigned int cell = cells[i];
|
unsigned int cell = cells[i];
|
||||||
Nexus::PatchInfo &entry = index[cell];
|
PatchInfo &entry = index[cell];
|
||||||
tri_total += entry.nface;
|
tri_total += entry.nface;
|
||||||
//frustum culling
|
//frustum culling
|
||||||
if(frustum.IsOutside(entry.sphere.Center(), entry.sphere.Radius()))
|
if(frustum.IsOutside(entry.sphere.Center(), entry.sphere.Radius()))
|
||||||
|
@ -204,21 +228,22 @@ void NexusMt::Draw(vector<unsigned int> &cells) {
|
||||||
|
|
||||||
tri_rendered += entry.nface;
|
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 *fstart;
|
||||||
char *vstart;
|
char *vstart;
|
||||||
char *cstart;
|
char *cstart;
|
||||||
char *nstart;
|
char *nstart;
|
||||||
|
|
||||||
if(vbo_mode != VBO_OFF) {
|
if(vbo_mode != VBO_OFF) {
|
||||||
unsigned int vbo_array;
|
// unsigned int vbo_array;
|
||||||
unsigned int vbo_element;
|
// unsigned int vbo_element;
|
||||||
patches.GetVbo(cell, vbo_element, vbo_array);
|
// patches.GetVbo(cell, vbo_element, vbo_array);
|
||||||
assert(vbo_element);
|
assert(data.vbo_element);
|
||||||
assert(vbo_array);
|
assert(data.vbo_array);
|
||||||
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_array);
|
glBindBufferARB(GL_ARRAY_BUFFER_ARB, data.vbo_array);
|
||||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo_element);
|
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, data.vbo_element);
|
||||||
|
|
||||||
fstart = NULL;
|
fstart = NULL;
|
||||||
vstart = NULL;
|
vstart = NULL;
|
||||||
|
@ -281,8 +306,8 @@ void NexusMt::Draw(vector<unsigned int> &cells) {
|
||||||
glDisableClientState(GL_NORMAL_ARRAY);
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexusMt::SetRamExtractionSize(unsigned int r_size) {
|
void NexusMt::SetExtractionSize(unsigned int r_size) {
|
||||||
policy.ram_size = r_size/patches.chunk_size;
|
extraction_max = r_size/patches.chunk_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexusMt::SetMetric(NexusMt::MetricKind kind) {
|
void NexusMt::SetMetric(NexusMt::MetricKind kind) {
|
||||||
|
@ -291,24 +316,15 @@ void NexusMt::SetMetric(NexusMt::MetricKind kind) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexusMt::SetError(float error) {
|
void NexusMt::SetError(float error) {
|
||||||
policy.error = error;
|
target_error = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexusMt::SetVboSize(unsigned int _vbo_size) {
|
void NexusMt::SetVboSize(unsigned int _vbo_max) {
|
||||||
patches.vbo_size = _vbo_size;
|
patches.vbo_max = _vbo_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NexusMt::SetPrefetching(bool on) {
|
void NexusMt::SetPrefetchSize(unsigned int size) {
|
||||||
if(on && prefetch.Running()) return;
|
//TODO do something reasonable with this.
|
||||||
if(!on && !prefetch.Running()) return;
|
|
||||||
if(on) {
|
|
||||||
prefetch.cells.clear();
|
|
||||||
prefetch.start();
|
|
||||||
} else {
|
|
||||||
prefetch.signal();
|
|
||||||
prefetch.waitfor();
|
|
||||||
}
|
|
||||||
prefetching = on;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NexusMt::SetMode(Mode _mode) {
|
bool NexusMt::SetMode(Mode _mode) {
|
||||||
|
@ -370,7 +386,7 @@ void NexusMt::LoadHistory() {
|
||||||
for(unsigned int i = 0; i < (*u).created.size(); i++) {
|
for(unsigned int i = 0; i < (*u).created.size(); i++) {
|
||||||
unsigned int cell = (*u).created[i];
|
unsigned int cell = (*u).created[i];
|
||||||
if(index[cell].error > node.error)
|
if(index[cell].error > node.error)
|
||||||
node.error = index[cell].error;
|
node.error = index[cell].error;
|
||||||
|
|
||||||
cell_node[cell] = current_node;
|
cell_node[cell] = current_node;
|
||||||
}
|
}
|
||||||
|
@ -397,18 +413,18 @@ void NexusMt::LoadHistory() {
|
||||||
vector<unsigned int> &cells = (*e).second;
|
vector<unsigned int> &cells = (*e).second;
|
||||||
vector<unsigned int>::iterator k;
|
vector<unsigned int>::iterator k;
|
||||||
for(k = cells.begin(); k != cells.end(); k++) {
|
for(k = cells.begin(); k != cells.end(); k++) {
|
||||||
unsigned int cell = (*k);
|
unsigned int cell = (*k);
|
||||||
assert(cell < index.size());
|
assert(cell < index.size());
|
||||||
fr.push_back(cell);
|
fr.push_back(cell);
|
||||||
if(index[cell].error > max_err)
|
if(index[cell].error > max_err)
|
||||||
max_err = index[cell].error;
|
max_err = index[cell].error;
|
||||||
}
|
}
|
||||||
//Add the new Frag to the node.
|
//Add the new Frag to the node.
|
||||||
unsigned int floor_node = (*e).first;
|
unsigned int floor_node = (*e).first;
|
||||||
Node &oldnode = nodes[floor_node];
|
Node &oldnode = nodes[floor_node];
|
||||||
oldnode.frags.push_back(fr);
|
oldnode.frags.push_back(fr);
|
||||||
if(node.error < max_err)
|
if(node.error < max_err)
|
||||||
node.error = max_err;
|
node.error = max_err;
|
||||||
|
|
||||||
//Update in and out of the nodes.
|
//Update in and out of the nodes.
|
||||||
node.in.push_back(&oldnode);
|
node.in.push_back(&oldnode);
|
||||||
|
@ -454,10 +470,12 @@ void NexusMt::ClearHistory() {
|
||||||
} */
|
} */
|
||||||
|
|
||||||
void NexusMt::Extract(std::vector<unsigned int> &selected) {
|
void NexusMt::Extract(std::vector<unsigned int> &selected) {
|
||||||
|
extraction_used = 0;
|
||||||
|
|
||||||
std::vector<Node>::iterator n;
|
std::vector<Node>::iterator n;
|
||||||
for(n = nodes.begin(); n != nodes.end(); n++) {
|
for(n = nodes.begin(); n != nodes.end(); n++) {
|
||||||
(*n).visited = false;
|
(*n).visited = false;
|
||||||
(*n).pushed = false;
|
// (*n).pushed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TNode> heap;
|
std::vector<TNode> heap;
|
||||||
|
@ -472,7 +490,7 @@ void NexusMt::Extract(std::vector<unsigned int> &selected) {
|
||||||
Node *node = tnode.node;
|
Node *node = tnode.node;
|
||||||
if(node->visited) continue;
|
if(node->visited) continue;
|
||||||
|
|
||||||
bool expand = policy.Expand(tnode);
|
bool expand = Expand(tnode);
|
||||||
|
|
||||||
if(expand)
|
if(expand)
|
||||||
VisitNode(node, heap);
|
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++) {
|
for(unsigned int k = 0; k < node->out.size(); k++) {
|
||||||
Node *outnode = node->out[k];
|
Node *outnode = node->out[k];
|
||||||
float error = metric->GetError(node->frags[k]);
|
float max_error = 0;
|
||||||
// if(node->pushed) continue
|
|
||||||
heap.push_back(TNode(outnode, error));
|
|
||||||
|
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());
|
push_heap(heap.begin(), heap.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
node->visited = true;
|
node->visited = true;
|
||||||
policy.NodeVisited(node);
|
NodeVisited(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
#ifndef NXS_NEXUS_MT_H
|
#ifndef NXS_NEXUS_MT_H
|
||||||
#define NXS_NEXUS_MT_H
|
#define NXS_NEXUS_MT_H
|
||||||
|
|
||||||
|
|
||||||
#include "nexus.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <ptypes/pasync.h>
|
#include <ptypes/pasync.h>
|
||||||
#include <wrap/gui/frustum.h>
|
#include <wrap/gui/frustum.h>
|
||||||
|
|
||||||
|
#include "nexusbase.h"
|
||||||
|
#include "queuepserver.h"
|
||||||
|
#include "borderserver.h"
|
||||||
|
#include "prefetch.h"
|
||||||
|
|
||||||
namespace nxs {
|
namespace nxs {
|
||||||
|
|
||||||
|
@ -19,7 +21,7 @@ namespace nxs {
|
||||||
std::vector<Frag> frags;
|
std::vector<Frag> frags;
|
||||||
float error;
|
float error;
|
||||||
bool visited;
|
bool visited;
|
||||||
bool pushed;
|
// bool pushed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TNode {
|
struct TNode {
|
||||||
|
@ -31,7 +33,7 @@ namespace nxs {
|
||||||
|
|
||||||
class Metric {
|
class Metric {
|
||||||
public:
|
public:
|
||||||
vector<Nexus::PatchInfo> *index;
|
std::vector<PatchInfo> *index;
|
||||||
|
|
||||||
float GetError(Node *node);
|
float GetError(Node *node);
|
||||||
float GetError(Frag &frag);
|
float GetError(Frag &frag);
|
||||||
|
@ -60,7 +62,7 @@ namespace nxs {
|
||||||
float GetError(unsigned int cell);
|
float GetError(unsigned int cell);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Policy {
|
/* class Policy {
|
||||||
public:
|
public:
|
||||||
float error;
|
float error;
|
||||||
int ram_used;
|
int ram_used;
|
||||||
|
@ -71,27 +73,9 @@ namespace nxs {
|
||||||
void Init();
|
void Init();
|
||||||
bool Expand(TNode &node);
|
bool Expand(TNode &node);
|
||||||
void NodeVisited(Node *node);
|
void NodeVisited(Node *node);
|
||||||
};
|
};*/
|
||||||
|
|
||||||
class Prefetch: public pt::thread {
|
class NexusMt: public NexusBase {
|
||||||
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;
|
|
||||||
public:
|
public:
|
||||||
//Vertex buffer object mode
|
//Vertex buffer object mode
|
||||||
enum Vbo { VBO_AUTO, //autodetect best size
|
enum Vbo { VBO_AUTO, //autodetect best size
|
||||||
|
@ -118,10 +102,13 @@ class NexusMt: public Nexus {
|
||||||
Vbo vbo_mode;
|
Vbo vbo_mode;
|
||||||
|
|
||||||
Metric *metric;
|
Metric *metric;
|
||||||
Policy policy;
|
float target_error;
|
||||||
|
|
||||||
|
int extraction_max;
|
||||||
|
int extraction_used;
|
||||||
|
|
||||||
|
|
||||||
Mode mode;
|
Mode mode;
|
||||||
bool prefetching;
|
|
||||||
|
|
||||||
unsigned int components;
|
unsigned int components;
|
||||||
bool use_normals;
|
bool use_normals;
|
||||||
|
@ -133,30 +120,40 @@ class NexusMt: public Nexus {
|
||||||
unsigned int tri_rendered;
|
unsigned int tri_rendered;
|
||||||
unsigned int tri_total;
|
unsigned int tri_total;
|
||||||
|
|
||||||
|
std::vector<PServer::Item> visited;
|
||||||
|
QueuePServer patches;
|
||||||
|
BorderServer borders;
|
||||||
|
|
||||||
NexusMt();
|
NexusMt();
|
||||||
~NexusMt();
|
~NexusMt();
|
||||||
|
|
||||||
bool Load(const std::string &filename, bool readonly = true);
|
bool Load(const std::string &filename);
|
||||||
bool InitGL(Vbo mode = VBO_AUTO, unsigned int vbo_size = 0);
|
void Close();
|
||||||
|
|
||||||
|
bool InitGL(Vbo mode = VBO_AUTO, unsigned int vbo_size = 64000000);
|
||||||
|
|
||||||
void Render();
|
void Render();
|
||||||
|
|
||||||
void SetMetric(MetricKind kind);
|
void SetMetric(MetricKind kind);
|
||||||
void SetError(float error);
|
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 SetVboSize(unsigned int vbo_size);
|
||||||
|
|
||||||
void SetPrefetching(bool on);
|
|
||||||
|
|
||||||
bool SetMode(Mode mode);
|
bool SetMode(Mode mode);
|
||||||
bool SetComponent(Component c, bool on);
|
bool SetComponent(Component c, bool on);
|
||||||
bool SetComponents(unsigned int mask);
|
bool SetComponents(unsigned int mask);
|
||||||
|
|
||||||
|
|
||||||
void Draw(std::vector<unsigned int> &selected);
|
void Draw(std::vector<unsigned int> &selected);
|
||||||
void Extract(std::vector<unsigned int> &selected);
|
void Extract(std::vector<unsigned int> &selected);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
std::vector<Node> nodes;
|
||||||
|
|
||||||
|
bool Expand(TNode &node);
|
||||||
|
void NodeVisited(Node *node);
|
||||||
|
|
||||||
void LoadHistory();
|
void LoadHistory();
|
||||||
void ClearHistory();
|
void ClearHistory();
|
||||||
void VisitNode(Node *node, std::vector<TNode> &heap);
|
void VisitNode(Node *node, std::vector<TNode> &heap);
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
History
|
History
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
$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
|
Revision 1.22 2004/11/28 04:16:19 ponchio
|
||||||
*** empty log message ***
|
*** empty log message ***
|
||||||
|
|
||||||
|
@ -234,7 +237,7 @@ int main(int argc, char *argv[]) {
|
||||||
unsigned int ram_size = 640000;
|
unsigned int ram_size = 640000;
|
||||||
|
|
||||||
nexus.SetError(error);
|
nexus.SetError(error);
|
||||||
nexus.SetRamExtractionSize(ram_size);
|
nexus.SetExtractionSize(ram_size);
|
||||||
nexus.SetMetric(NexusMt::FRUSTUM);
|
nexus.SetMetric(NexusMt::FRUSTUM);
|
||||||
if(!nexus.InitGL()) {
|
if(!nexus.InitGL()) {
|
||||||
cerr << "Could not init glew.\n";
|
cerr << "Could not init glew.\n";
|
||||||
|
@ -271,16 +274,16 @@ int main(int argc, char *argv[]) {
|
||||||
case SDLK_e: extract = !extract; break;
|
case SDLK_e: extract = !extract; break;
|
||||||
case SDLK_c: show_colors = !show_colors; break;
|
case SDLK_c: show_colors = !show_colors; break;
|
||||||
case SDLK_n: show_normals = !show_normals; break;
|
case SDLK_n: show_normals = !show_normals; break;
|
||||||
case SDLK_9: nexus.patches.ram_size *= 0.8f; break;
|
// case SDLK_9: nexus.patches->ram_size *= 0.8f; break;
|
||||||
case SDLK_0: nexus.patches.ram_size *= 1.2f; break;
|
// case SDLK_0: nexus.patches->ram_size *= 1.2f; break;
|
||||||
|
|
||||||
case SDLK_LEFT:
|
case SDLK_LEFT:
|
||||||
ram_size *= 0.7;
|
ram_size *= 0.7;
|
||||||
nexus.SetRamExtractionSize(ram_size);
|
nexus.SetExtractionSize(ram_size);
|
||||||
cerr << "Max extraction ram size: " << ram_size << endl; break;
|
cerr << "Max extraction ram size: " << ram_size << endl; break;
|
||||||
case SDLK_RIGHT:
|
case SDLK_RIGHT:
|
||||||
ram_size *= 1.5;
|
ram_size *= 1.5;
|
||||||
nexus.SetRamExtractionSize(ram_size);
|
nexus.SetExtractionSize(ram_size);
|
||||||
cerr << "Max extraction ram size: " << ram_size << endl; break;
|
cerr << "Max extraction ram size: " << ram_size << endl; break;
|
||||||
|
|
||||||
case SDLK_s: metric = NexusMt::FRUSTUM; break;
|
case SDLK_s: metric = NexusMt::FRUSTUM; break;
|
||||||
|
@ -388,17 +391,17 @@ int main(int argc, char *argv[]) {
|
||||||
static vector<unsigned int> cells;
|
static vector<unsigned int> cells;
|
||||||
watch.Start();
|
watch.Start();
|
||||||
if(extract) {
|
if(extract) {
|
||||||
nexus.patches.Flush();
|
// nexus.patches.Flush();
|
||||||
|
|
||||||
nexus.metric->GetView();
|
nexus.metric->GetView();
|
||||||
nexus.policy.Init();
|
// nexus.policy.Init();
|
||||||
nexus.tri_total = 0;
|
nexus.tri_total = 0;
|
||||||
nexus.tri_rendered = 0;
|
nexus.tri_rendered = 0;
|
||||||
nexus.Extract(cells);
|
nexus.Extract(cells);
|
||||||
}
|
}
|
||||||
nexus.Draw(cells);
|
nexus.Draw(cells);
|
||||||
|
|
||||||
if(show_borders) {
|
/* if(show_borders) {
|
||||||
for(unsigned int i = 0; i < cells.size(); i++) {
|
for(unsigned int i = 0; i < cells.size(); i++) {
|
||||||
Border border = nexus.GetBorder(cells[i]);
|
Border border = nexus.GetBorder(cells[i]);
|
||||||
Patch &patch = nexus.GetPatch(cells[i]);
|
Patch &patch = nexus.GetPatch(cells[i]);
|
||||||
|
@ -413,7 +416,7 @@ int main(int argc, char *argv[]) {
|
||||||
glEnd();
|
glEnd();
|
||||||
glPointSize(1);
|
glPointSize(1);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
//cerr Do some reporting:
|
//cerr Do some reporting:
|
||||||
if(show_statistics) {
|
if(show_statistics) {
|
||||||
|
@ -431,19 +434,19 @@ int main(int argc, char *argv[]) {
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
glColor3f(1.0f, 1.0f, 1.0f);
|
glColor3f(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
sprintf(buffer, "Ram size : %.3fMb (max) %.3fMb (cur)",
|
/* sprintf(buffer, "Ram size : %.3fMb (max) %.3fMb (cur)",
|
||||||
nexus.patches.ram_size * nexus.chunk_size/(float)(1<<20),
|
nexus.patches->ram_size * nexus.chunk_size/(float)(1<<20),
|
||||||
nexus.patches.ram_used * nexus.chunk_size/(float)(1<<20));
|
nexus.patches->ram_used * nexus.chunk_size/(float)(1<<20));
|
||||||
gl_print(0.03, 0.12, buffer);
|
gl_print(0.03, 0.12, buffer);*/
|
||||||
|
|
||||||
sprintf(buffer, "Extr size: %.3fMb(max) %.3fMb(cur)",
|
sprintf(buffer, "Extr size: %.3fMb(max) %.3fMb(cur)",
|
||||||
nexus.policy.ram_size * nexus.chunk_size/(float)(1<<20),
|
nexus.extraction_max * nexus.chunk_size/(float)(1<<20),
|
||||||
nexus.policy.ram_used * nexus.chunk_size/(float)(1<<20));
|
nexus.extraction_used * nexus.chunk_size/(float)(1<<20));
|
||||||
gl_print(0.03, 0.09, buffer);
|
gl_print(0.03, 0.09, buffer);
|
||||||
|
|
||||||
sprintf(buffer, "Vbo size : %.3fMb(max) %.3fMb(cur)",
|
sprintf(buffer, "Vbo size : %.3fMb(max) %.3fMb(cur)",
|
||||||
nexus.patches.vbo_size * 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));
|
nexus.patches.vbo_used * nexus.chunk_size/(float)(1<<20));
|
||||||
gl_print(0.03, 0.06, buffer);
|
gl_print(0.03, 0.06, buffer);
|
||||||
|
|
||||||
sprintf(buffer, "Triangles: %.2fK (tot) %.2fK (vis) "
|
sprintf(buffer, "Triangles: %.2fK (tot) %.2fK (vis) "
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
History
|
History
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
$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
|
Revision 1.9 2004/12/04 13:22:55 ponchio
|
||||||
*** empty log message ***
|
*** empty log message ***
|
||||||
|
|
||||||
|
@ -282,7 +285,7 @@ void ThirdStep(const string &crudefile, const string &output,
|
||||||
|
|
||||||
Nexus nexus;
|
Nexus nexus;
|
||||||
//TODO here i really need no ram_buffer.....
|
//TODO here i really need no ram_buffer.....
|
||||||
nexus.patches.SetRamBufferSize(0);
|
nexus.MaxRamBuffer(0);
|
||||||
if(!nexus.Create(output, NXS_FACES, chunk_size)) {
|
if(!nexus.Create(output, NXS_FACES, chunk_size)) {
|
||||||
cerr << "Could not create nexus output: " << output << endl;
|
cerr << "Could not create nexus output: " << output << endl;
|
||||||
getchar();
|
getchar();
|
||||||
|
@ -384,6 +387,7 @@ void ThirdStep(const string &crudefile, const string &output,
|
||||||
cerr << "Could not save: " << output << ".rvi\n";
|
cerr << "Could not save: " << output << ".rvi\n";
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
nexus.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FourthStep(const string &crudefile, const string &output,
|
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;
|
cerr << "Could not load nexus " << output << endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
nexus.patches.SetRamBufferSize(ram_buffer);
|
nexus.MaxRamBuffer(ram_buffer);
|
||||||
//TODO Clear borders in case of failure!
|
//TODO Clear borders in case of failure!
|
||||||
|
|
||||||
VFile<unsigned int> vert_remap;
|
VFile<unsigned int> vert_remap;
|
||||||
|
@ -411,7 +415,7 @@ void FourthStep(const string &crudefile, const string &output,
|
||||||
|
|
||||||
for(int start = 0; start < nexus.index.size(); start++) {
|
for(int start = 0; start < nexus.index.size(); start++) {
|
||||||
report.Step(start);
|
report.Step(start);
|
||||||
Nexus::PatchInfo &s_entry = nexus.index[start];
|
PatchInfo &s_entry = nexus.index[start];
|
||||||
|
|
||||||
vector<Link> links;
|
vector<Link> links;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
@ -427,7 +431,7 @@ void FourthStep(const string &crudefile, const string &output,
|
||||||
for(int end = 0; end < nexus.index.size(); end++) {
|
for(int end = 0; end < nexus.index.size(); end++) {
|
||||||
if(start == end) continue;
|
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);
|
float dist = Distance(s_entry.sphere, e_entry.sphere);
|
||||||
|
|
||||||
if(dist > s_entry.sphere.Radius() + e_entry.sphere.Radius()) {
|
if(dist > s_entry.sphere.Radius() + e_entry.sphere.Radius()) {
|
||||||
|
@ -467,7 +471,7 @@ void FifthStep(const string &crudefile, const string &output,
|
||||||
cerr << "Could not load nexus " << output << endl;
|
cerr << "Could not load nexus " << output << endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
nexus.patches.SetRamBufferSize(ram_buffer);
|
nexus.MaxRamBuffer(ram_buffer);
|
||||||
|
|
||||||
VChain vchain;
|
VChain vchain;
|
||||||
if(!vchain.Load(output + ".vchain")) {
|
if(!vchain.Load(output + ".vchain")) {
|
||||||
|
@ -482,7 +486,7 @@ void FifthStep(const string &crudefile, const string &output,
|
||||||
}
|
}
|
||||||
nexus.history.push_back(update);
|
nexus.history.push_back(update);
|
||||||
nexus.Unify();
|
nexus.Unify();
|
||||||
nexus.patches.FlushAll();
|
nexus.patches.Flush();
|
||||||
|
|
||||||
|
|
||||||
Dispatcher dispatcher(&nexus, &vchain);
|
Dispatcher dispatcher(&nexus, &vchain);
|
||||||
|
@ -752,7 +756,7 @@ void SaveFragment(Nexus &nexus, VChain &chain,
|
||||||
patch.face.size()/3,
|
patch.face.size()/3,
|
||||||
bordsize);
|
bordsize);
|
||||||
patch_levels.push_back(current_level);
|
patch_levels.push_back(current_level);
|
||||||
Nexus::PatchInfo &entry = nexus.index[patch_idx];
|
PatchInfo &entry = nexus.index[patch_idx];
|
||||||
entry.error = fragout.error;
|
entry.error = fragout.error;
|
||||||
|
|
||||||
patch_remap[i] = patch_idx;
|
patch_remap[i] = patch_idx;
|
||||||
|
@ -780,7 +784,7 @@ void SaveFragment(Nexus &nexus, VChain &chain,
|
||||||
memcpy(patch.VertBegin(), &outpatch.vert[0],
|
memcpy(patch.VertBegin(), &outpatch.vert[0],
|
||||||
outpatch.vert.size() * sizeof(Point3f));
|
outpatch.vert.size() * sizeof(Point3f));
|
||||||
|
|
||||||
Nexus::PatchInfo &entry = nexus.index[patch_idx];
|
PatchInfo &entry = nexus.index[patch_idx];
|
||||||
for(unsigned int v = 0; v < outpatch.vert.size(); v++) {
|
for(unsigned int v = 0; v < outpatch.vert.size(); v++) {
|
||||||
entry.sphere.Add(outpatch.vert[v]);
|
entry.sphere.Add(outpatch.vert[v]);
|
||||||
nexus.sphere.Add(outpatch.vert[v]);
|
nexus.sphere.Add(outpatch.vert[v]);
|
||||||
|
|
|
@ -211,7 +211,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
|
||||||
Nexus nexus;
|
Nexus nexus;
|
||||||
nexus.patches.SetRamBufferSize(ram_size);
|
nexus.MaxRamBuffer(ram_size);
|
||||||
if(!nexus.Load(input, true)) {
|
if(!nexus.Load(input, true)) {
|
||||||
cerr << "Could not open nexus file: " << input << "\n";
|
cerr << "Could not open nexus file: " << input << "\n";
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -312,7 +312,7 @@ int main(int argc, char *argv[]) {
|
||||||
cout << "Writing to nexus: " << output << endl;
|
cout << "Writing to nexus: " << output << endl;
|
||||||
|
|
||||||
Nexus out;
|
Nexus out;
|
||||||
out.patches.SetRamBufferSize(ram_size);
|
out.MaxRamBuffer(ram_size);
|
||||||
if(!chunk_size)
|
if(!chunk_size)
|
||||||
chunk_size = nexus.patches.chunk_size;
|
chunk_size = nexus.patches.chunk_size;
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ int main(int argc, char *argv[]) {
|
||||||
cout << "Copying and allocating...\n";
|
cout << "Copying and allocating...\n";
|
||||||
for(unsigned int patch = 0; patch < nexus.index.size(); patch++) {
|
for(unsigned int patch = 0; patch < nexus.index.size(); patch++) {
|
||||||
report.Step(patch);
|
report.Step(patch);
|
||||||
Nexus::PatchInfo &src_entry = nexus.index[patch];
|
PatchInfo &src_entry = nexus.index[patch];
|
||||||
Patch src_patch = nexus.GetPatch(patch);
|
Patch src_patch = nexus.GetPatch(patch);
|
||||||
Border src_border = nexus.GetBorder(patch);
|
Border src_border = nexus.GetBorder(patch);
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ int main(int argc, char *argv[]) {
|
||||||
out.AddPatch(src_entry.nvert, src_entry.nface, src_border.Available());
|
out.AddPatch(src_entry.nvert, src_entry.nface, src_border.Available());
|
||||||
|
|
||||||
|
|
||||||
Nexus::PatchInfo &dst_entry = out.index[patch];
|
PatchInfo &dst_entry = out.index[patch];
|
||||||
|
|
||||||
Patch dst_patch = out.GetPatch(patch);
|
Patch dst_patch = out.GetPatch(patch);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ int main(int argc, char *argv[]) {
|
||||||
Report report(nexus.index.size());
|
Report report(nexus.index.size());
|
||||||
for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) {
|
for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) {
|
||||||
report.Step(patchid);
|
report.Step(patchid);
|
||||||
Nexus::PatchInfo &info = nexus.index[patchid];
|
PatchInfo &info = nexus.index[patchid];
|
||||||
Patch &patch = nexus.GetPatch(patchid);
|
Patch &patch = nexus.GetPatch(patchid);
|
||||||
for(int f = 0; f < patch.nf; f++) {
|
for(int f = 0; f < patch.nf; f++) {
|
||||||
unsigned short *face = patch.Face(f);
|
unsigned short *face = patch.Face(f);
|
||||||
|
@ -52,7 +52,7 @@ int main(int argc, char *argv[]) {
|
||||||
cerr << "Testing borders\n";
|
cerr << "Testing borders\n";
|
||||||
|
|
||||||
for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) {
|
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);
|
Border border = nexus.GetBorder(patchid);
|
||||||
for(unsigned int i = 0; i < border.Size(); i++) {
|
for(unsigned int i = 0; i < border.Size(); i++) {
|
||||||
Link &link = border[i];
|
Link &link = border[i];
|
||||||
|
@ -80,7 +80,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
cerr << "Reciprocity borders test\n";
|
cerr << "Reciprocity borders test\n";
|
||||||
for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) {
|
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);
|
Border border = nexus.GetBorder(patchid);
|
||||||
vector<Link> links;
|
vector<Link> links;
|
||||||
links.resize(border.Size());
|
links.resize(border.Size());
|
||||||
|
|
|
@ -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