Lotsa changes...

This commit is contained in:
Federico Ponchio 2004-12-13 00:44:48 +00:00
parent bdb503ef17
commit 9bb65dd0c3
16 changed files with 852 additions and 339 deletions

64
apps/nexus/lrupserver.h Normal file
View File

@ -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

View File

@ -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;

View File

@ -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;
};
}

63
apps/nexus/nexusbase.h Normal file
View 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

View File

@ -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);
}

View File

@ -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);

View File

@ -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) "

View File

@ -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]);

View File

@ -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);

View File

@ -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;
}
}

56
apps/nexus/prefetch.cpp Normal file
View File

@ -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);
}
}

41
apps/nexus/prefetch.h Normal file
View File

@ -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

158
apps/nexus/pserver.cpp Normal file
View File

@ -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;
}

93
apps/nexus/pserver.h Normal file
View File

@ -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

View File

@ -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;
}

42
apps/nexus/queuepserver.h Normal file
View File

@ -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