This commit is contained in:
Federico Ponchio 2005-01-14 15:41:10 +00:00
parent fa6da0bbf3
commit c35cead5ce
8 changed files with 936 additions and 0 deletions

157
apps/nexus/extraction.cpp Normal file
View File

@ -0,0 +1,157 @@
#include "extraction.h"
#include "metric.h"
#include "nexusmt.h"
#include <algorithm>
using namespace std;
using namespace nxs;
Extraction::Extraction(): target_error(4.0f), extr_max(0xffffffff),
draw_max(640), disk_max(100) {
metric = new FrustumMetric;
}
Extraction::~Extraction() {
if(metric) delete metric;
}
void Extraction::Extract(NexusMt *_mt) {
mt = _mt;
//clear statistics
extr_used = draw_used = disk_used = 0;
//first we clear the visited flags
visited.clear();
visited.resize(mt->history.n_nodes(), false);
heap.clear();
History::Node *root = mt->history.Root();
HeapNode hroot(root, 0);
Diff(hroot);
extr_used += hroot.extr;
draw_used += hroot.draw;
disk_used += hroot.disk;
Visit(root);
while(heap.size()) {
pop_heap(heap.begin(), heap.end());
HeapNode hnode = heap.back();
heap.pop_back();
History::Node *node = hnode.node;
unsigned int id = node - root;
if(visited[id]) continue;
if(Expand(hnode)) {
extr_used += hnode.extr;
draw_used += hnode.draw;
disk_used += hnode.disk;
Visit(node);
}
}
Select();
}
void Extraction::Select() {
selected.clear();
History::Node *root = mt->history.Root();
History::Node *nodes = mt->history.nodes;
for(unsigned int i = 0; i < visited.size(); i++) {
if(!visited[i]) continue;
History::Node &node = nodes[i];
History::Node::iterator n;
for(n = node.out_begin(); n != node.out_end(); n++) {
unsigned int n_out = (*n).node - root;
if(!visited[n_out]) {
History::Link &link = *n;
for(History::Link::iterator k = link.begin(); k != link.end(); k++) {
unsigned int patch = (*k).patch;
selected.push_back(patch);
}
}
}
}
}
void Extraction::Visit(History::Node *node) {
History::Node *root = mt->history.Root();
unsigned int n_node = node - root;
if(visited[n_node]) return;
visited[n_node] = true;
History::Node::iterator i;
for(i = node->in_begin(); i != node->in_end(); i++) {
unsigned int n_in = (*i).node - root;
if(visited[n_in]) continue;
HeapNode hin((*i).node, 0);
Diff(hin);
extr_used += hin.extr;
draw_used += hin.draw;
disk_used += hin.disk;
Visit((*i).node);
}
for(i = node->out_begin(); i != node->out_end(); i++) {
float maxerror = 0;
History::Link &link = *i;
for(History::Link::iterator k = link.begin(); k != link.end(); k++) {
Entry &entry = (*mt)[(*k).patch];
float error = metric->GetError(entry);
if(error > maxerror) maxerror = error;
}
//TODO this check may be dangerous for non saturating things...
if(maxerror > target_error) {
HeapNode hnode((*i).node, maxerror);
Diff(hnode);
heap.push_back(hnode);
push_heap(heap.begin(), heap.end());
}
}
}
bool Extraction::Expand(HeapNode &node) {
if(extr_used >= extr_max) return false;
if(draw_used >= draw_max) return false;
// if(disk_used >= disk_max) return false;
return node.error > target_error;
}
void Extraction::Diff(HeapNode &hnode) {
History::Node &node = *(hnode.node);
History::Node::iterator i;
for(i = node.in_begin(); i != node.in_end(); i++) {
History::Link &link = *i;
for(History::Link::iterator k = link.begin(); k != link.end(); k++) {
unsigned int patch = (*k).patch;
Entry &entry = (*mt)[patch];
hnode.extr -= entry.ram_size;
vcg::Sphere3f &sphere = entry.sphere;
if(!frustum.IsOutside(sphere.Center(), sphere.Radius()))
hnode.draw -= entry.ram_size;
if(!entry.patch)
hnode.disk -= entry.disk_size;
}
}
for(i = node.out_begin(); i != node.out_end(); i++) {
History::Link &link = *i;
for(History::Link::iterator k = link.begin(); k != link.end(); k++) {
unsigned int patch = (*k).patch;
Entry &entry = (*mt)[patch];
hnode.extr += entry.ram_size;
vcg::Sphere3f &sphere = entry.sphere;
if(!frustum.IsOutside(sphere.Center(), sphere.Radius()))
hnode.draw += entry.ram_size;
if(!entry.patch)
hnode.disk += entry.disk_size;
}
}
}

61
apps/nexus/extraction.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef NXS_EXTRACTION_H
#define NXS_EXTRACTION_H
#include "history.h"
#include <vector>
#include <wrap/gui/frustum.h>
namespace nxs {
class Metric;
class NexusMt;
class Extraction {
public:
struct HeapNode {
History::Node *node;
float error;
unsigned int extr;
unsigned int draw;
unsigned int disk;
HeapNode(History::Node *_node, float _error): node(_node), error(_error),
extr(0), draw(0), disk(0) {}
bool operator<(const HeapNode &node) const {
return error < node.error; }
};
Metric *metric;
vcg::Frustumf frustum;
float target_error;
unsigned int extr_used, extr_max;
unsigned int draw_used, draw_max;
unsigned int disk_used, disk_max;
std::vector<bool> visited;
std::vector<HeapNode> heap;
std::vector<unsigned int> selected;
Extraction();
~Extraction();
void Extract(NexusMt *mt);
// void Update(std::vector<unsigned int> &selected);
protected:
void Select();
void Visit(History::Node *node);
bool Expand(HeapNode &node);
void Diff(HeapNode &node);
private:
NexusMt *mt;
};
}//namespace
#endif

297
apps/nexus/history.cpp Normal file
View File

@ -0,0 +1,297 @@
#include <assert.h>
#include <map>
#include <iostream>
#include "history.h"
using namespace std;
using namespace nxs;
History::~History() {
if(buffer) delete []buffer;
nodes = NULL;
in_links= NULL;
out_links = NULL;
frags = NULL;
}
void History::Clear() {
if(buffer) delete []buffer;
buffer = NULL;
updates.clear();
}
void History::ClearQuick() {
if(buffer) delete []buffer;
buffer = NULL;
}
void History::ClearUpdates() {
updates.clear();
}
bool History::Load(unsigned int _size, char *mem) {
if(buffer) delete []buffer;
unsigned int is_quick = *(unsigned int *)mem;
bool success;
if(is_quick == 53) {
// cerr << "Load quick!\n";
success = LoadQuick(_size, mem);
} else if(is_quick == 32) {
// cerr << "Load updates\n";
success = LoadUpdates(_size, mem);
} else {
cerr << "Invalid history: " << is_quick << "\n";
return false;
}
return success;
}
bool History::LoadQuick(unsigned int _size, char *mem) {
buffer = mem;
nodes = (Node *)(buffer + 5 * sizeof(int));
in_links = (Link *)(nodes + n_nodes());
out_links = in_links + n_in_links();
frags = (Cell *)(out_links + n_out_links());
//check size is ok;
assert(n_nodes() * sizeof(Node) +
(n_in_links() + n_out_links()) * sizeof(Link) +
n_frags() * sizeof(Cell) +
5 * sizeof(int) == size);
size = _size;
return LoadPointers();
}
bool History::LoadUpdates(unsigned int _size, char *mem) {
unsigned int *tmp = (unsigned int *)mem;
updates.resize(tmp[1]);
unsigned int pos = 2;
for(unsigned int i = 0; i < updates.size(); i++) {
unsigned int erased = tmp[pos++];
unsigned int created = tmp[pos++];
updates[i].erased.resize(erased);
updates[i].created.resize(created);
for(unsigned int e = 0; e < erased; e++)
updates[i].erased[e] = tmp[pos++];
for(unsigned int e = 0; e < created; e++)
updates[i].created[e] = tmp[pos++];
}
delete []mem;
buffer = 0;
return true;
}
bool History::LoadPointers() {
//now convert integer to pointers
for(unsigned int i = 0; i < n_nodes(); i++) {
Node &node = nodes[i];
assert(((unsigned int)node.in_link_begin) <= n_in_links());
assert(((unsigned int)node.out_link_begin) <= n_out_links());
node.in_link_begin = in_links + (unsigned int)(node.in_link_begin);
node.out_link_begin = out_links + (unsigned int)(node.out_link_begin);
}
for(unsigned int i = 0; i < n_in_links(); i++) {
Link &link = in_links[i];
assert(((unsigned int)link.node) <= n_nodes());
assert(((unsigned int)link.frag_begin) <= n_frags());
link.node = nodes + (unsigned int)(link.node);
link.frag_begin = frags + (unsigned int)(link.frag_begin);
}
for(unsigned int i = 0; i < n_out_links(); i++) {
Link &link = out_links[i];
assert(((unsigned int)link.node) <= n_nodes());
assert(((unsigned int)link.frag_begin) <= n_frags());
link.node = nodes + (unsigned int)(link.node);
link.frag_begin = frags + (unsigned int)(link.frag_begin);
}
return true;
}
char *History::Save(unsigned int &_size) {
if(buffer) {
// cerr << "SaveQuick!\n";
return SaveQuick(_size);
} else {
// cerr << "Save updates\n";
return SaveUpdates(_size);
}
}
char *History::SaveQuick(unsigned int &_size) {
assert(buffer);
for(unsigned int i = 0; i < n_nodes(); i++) {
Node &node = nodes[i];
node.in_link_begin = (Link *)(node.in_link_begin - in_links);
node.out_link_begin = (Link *)(node.out_link_begin - out_links);
}
for(unsigned int i = 0; i < n_in_links(); i++) {
Link &link = in_links[i];
link.node = (Node *)(link.node - nodes);
link.frag_begin = (Cell *)(link.frag_begin - frags);
}
for(unsigned int i = 0; i < n_out_links(); i++) {
Link &link = out_links[i];
link.node = (Node *)(link.node - nodes);
link.frag_begin = (Cell *)(link.frag_begin - frags);
}
_size = size;
char *tmp = buffer;
buffer = NULL;
return tmp;
}
char *History::SaveUpdates(unsigned int &_size) {
vector<unsigned int> buf;
buf.push_back(32);
buf.push_back(updates.size());
for(unsigned int i = 0; i < updates.size(); i++) {
Update &update = updates[i];
buf.push_back(update.erased.size());
buf.push_back(update.created.size());
for(unsigned int e = 0; e < update.erased.size(); e++)
buf.push_back(update.erased[e]);
for(unsigned int e = 0; e < update.created.size(); e++)
buf.push_back(update.created[e]);
}
_size = buf.size() * sizeof(unsigned int);
char *mem = new char[_size];
memcpy(mem, &*buf.begin(), _size);
return mem;
}
bool History::UpdatesToQuick() {
//maps cell -> node containing it
map<unsigned int, unsigned int> cell_node;
//maps node -> Links
map<unsigned int, vector<Link> > node_inlinks;
map<unsigned int, vector<Link> > node_outlinks;
vector<Node> tmp_nodes;
tmp_nodes.resize(updates.size());
vector<Link> tmp_in_links;
vector<Link> tmp_out_links;
vector<Cell> tmp_frags;
unsigned int current_node = 0;
vector<Update>::iterator u;
for(u = updates.begin(); u != updates.end(); u++) {
Node &node = tmp_nodes[current_node];
//created cells belong to this node, we look also for max error.
for(unsigned int i = 0; i < (*u).created.size(); i++) {
unsigned int cell = (*u).created[i];
cell_node[cell] = current_node;
}
//Every erased cell already belonged to a node.
//node -> its cells
map<unsigned int, vector<unsigned int> > node_erased;
for(unsigned int i = 0; i < (*u).erased.size(); i++) {
unsigned int cell = (*u).erased[i];
assert(cell_node.count(cell));
node_erased[cell_node[cell]].push_back(cell);
}
//for every node with erased cells we build a fragment and
//put the corresponding cells in it.
map<unsigned int, vector<unsigned int> >::iterator e;
for(e = node_erased.begin(); e != node_erased.end(); e++) {
//node.in.push_back(innodes.size());
unsigned int floor_node = (*e).first;
vector<unsigned int> &cells = (*e).second;
Node &parent = tmp_nodes[floor_node];
Link inlink;
inlink.node = (Node *)floor_node;
inlink.frag_begin = (Cell *)(tmp_frags.size());
inlink.frag_size = cells.size();
Link outlink;
outlink.node = (Node *)current_node;
outlink.frag_begin = (Cell *)(tmp_frags.size());
outlink.frag_size = cells.size();
//Fill it with erased cells.
vector<unsigned int>::iterator k;
for(k = cells.begin(); k != cells.end(); k++) {
Cell cell;
cell.patch = (*k);
tmp_frags.push_back(cell);
}
//Add the new Frag to the node.
node_outlinks[floor_node].push_back(outlink);
node_inlinks[current_node].push_back(inlink);
//Update in and out of the nodes.
}
current_node++;
}
map<unsigned int, vector<Link> >::iterator k;
for(k = node_outlinks.begin(); k != node_outlinks.end(); k++) {
unsigned int inode = (*k).first;
vector<Link> &links = (*k).second;
tmp_nodes[inode].out_link_begin = (Link *)(tmp_out_links.size());
tmp_nodes[inode].out_link_size = links.size();
for(unsigned int i = 0; i < links.size(); i++)
tmp_out_links.push_back(links[i]);
}
for(k = node_inlinks.begin(); k != node_inlinks.end(); k++) {
unsigned int inode = (*k).first;
vector<Link> &links = (*k).second;
tmp_nodes[inode].in_link_begin = (Link *)(tmp_in_links.size());
tmp_nodes[inode].in_link_size = links.size();
for(unsigned int i = 0; i < links.size(); i++)
tmp_in_links.push_back(links[i]);
}
size = tmp_nodes.size() * sizeof(Node) +
tmp_in_links.size() * sizeof(Link) +
tmp_out_links.size() * sizeof(Link) +
tmp_frags.size() * sizeof(Cell) +
5 * sizeof(int);
if(buffer) delete []buffer;
buffer = new char[size];
quick() = 53;
n_nodes() = tmp_nodes.size();
n_in_links() = tmp_in_links.size();
n_out_links() = tmp_out_links.size();
n_frags() = tmp_frags.size();
nodes = (Node *)(buffer + 5 * sizeof(int));
in_links = (Link *)(nodes + n_nodes());
out_links = in_links + n_in_links();
frags = (Cell *)(out_links + n_out_links());
memcpy(nodes, &*tmp_nodes.begin(), tmp_nodes.size()*sizeof(Node));
memcpy(in_links, &*tmp_in_links.begin(), tmp_in_links.size()*sizeof(Node));
memcpy(out_links, &*tmp_out_links.begin(),
tmp_out_links.size()*sizeof(Node));
memcpy(frags, &*tmp_frags.begin(), tmp_frags.size() * sizeof(Cell));
return LoadPointers();
}

103
apps/nexus/history.h Normal file
View File

@ -0,0 +1,103 @@
#ifndef NXS_HISTORY_H
#define NXS_HISTORY_H
#include <vector>
//TODO fix a bit better the quick <-> updates duality
namespace nxs {
class History {
public:
enum Mode { QUICK = 1, UPDATES = 2 };
struct Update {
std::vector<unsigned int> erased;
std::vector<unsigned int> created;
};
struct Cell {
unsigned int patch;
// float error;
};
struct Node;
struct Link {
Node *node;
typedef Cell *iterator;
iterator begin() { return frag_begin; }
iterator end() { return frag_begin + frag_size; }
unsigned int size() { return frag_size; }
Cell *frag_begin;
unsigned int frag_size;
};
struct Node {
typedef Link *iterator;
iterator in_begin() { return in_link_begin; }
iterator in_end() { return in_link_begin + in_link_size; }
unsigned int size() { return in_link_size; }
iterator out_begin() { return out_link_begin; }
iterator out_end() { return out_link_begin + out_link_size; }
unsigned int out_size() { return out_link_size; }
Link *in_link_begin;
unsigned int in_link_size;
Link *out_link_begin;
unsigned int out_link_size;
};
Node *nodes;
Link *in_links;
Link *out_links;
Cell *frags;
std::vector<Update> updates;
History(): nodes(NULL), in_links(NULL), out_links(NULL), frags(NULL),
buffer(NULL) {}
~History();
Node *Root() { return &nodes[0]; }
void Clear();
void ClearQuick();
void ClearUpdates();
//Owns memory afterwards.. do not free mem.
bool Load(unsigned int size, char *mem);
bool LoadQuick(unsigned int size, char *mem);
bool LoadUpdates(unsigned int size, char *mem);
//after these call history is invalid! and memory returned must be freed...
char *Save(unsigned int &size); //autodetect
char *SaveQuick(unsigned int &size);
char *SaveUpdates(unsigned int &size);
bool QuickToUpdates();
bool UpdatesToQuick();
bool IsQuick() { return buffer != NULL; }
int &quick() { return ((int *)buffer)[0]; }
int &n_nodes() { return ((int *)buffer)[1]; }
int &n_in_links() { return ((int *)buffer)[2]; }
int &n_out_links() { return ((int *)buffer)[3]; }
int &n_frags() { return ((int *)buffer)[4]; }
typedef Node *iterator;
iterator begin() { return nodes; }
iterator end() { return nodes + n_nodes(); }
protected:
unsigned int size;
char *buffer;
bool LoadPointers();
};
}
#endif

79
apps/nexus/index_file.h Normal file
View File

@ -0,0 +1,79 @@
#ifndef NXS_INDEX_FILE_H
#define NXS_INDEX_FILE_H
#include <assert.h>
#include <vector>
#include "mfile.h"
namespace nxs {
/* WARINING when subclassing this class you must add a Close()
in the destructor! */
template <class T>
class IndexFile: public MFile, public std::vector<T> {
public:
virtual ~IndexFile() {}
bool Create(const std::string &filename, unsigned int header_size,
unsigned int max_file_size = MFILE_MAX_SIZE) {
clear();
if(!MFile::Create(filename, max_file_size)) return false;
MFile::Redim(header_size);
offset = header_size;
return true;
}
bool Load(const std::string &filename, bool readonly = false) {
clear();
if(!MFile::Load(filename, readonly)) return false;
SetPosition(0);
LoadHeader();
SetPosition(offset);
unsigned int tot;
ReadBuffer(&tot, sizeof(unsigned int));
resize(tot);
ReadBuffer(&*begin(), size() * sizeof(T));
return true;
}
void Close() {
if(IsReadOnly()) return;
if(files.size() == 0) return; //not loaded, not created or closed
MFile::Redim(offset + size() * sizeof(T));
SetPosition(offset);
unsigned int tot = size();
WriteBuffer(&tot, sizeof(unsigned int));
WriteBuffer(&*begin(), size() * sizeof(T));
SetPosition(0);
SaveHeader();
MFile::Close();
}
int64 Length() { //count the header but not the index...
return offset;
}
void Redim(int64 size) {
MFile::Redim(size);
offset = size;
assert(MFile::Length() == offset);
}
protected:
int64 offset;
//MUST set offset to its correct value
virtual bool LoadHeader() = 0;
//MUST save offset somewhere
virtual void SaveHeader() = 0;
};
} //namespace
#endif

40
apps/nexus/metric.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef NXS_METRIC_H
#define NXS_METRIC_H
#include <wrap/gui/frustum.h>
#include <vcg/space/sphere3.h>
#include "nexus.h"
namespace nxs {
enum MetricKind { FRUSTUM, FLAT, DELTA };
class Metric {
public:
virtual void GetView() {}
virtual float GetError(Entry &entry) = 0;
};
class FlatMetric: public Metric {
public:
float GetError(Entry &entry) { return entry.error; }
};
class FrustumMetric: public Metric {
public:
vcg::Frustumf frustum;
virtual void GetView() { frustum.GetView(); }
float GetError(Entry &entry) {
vcg::Sphere3f &sphere = entry.sphere;
float dist = Distance(sphere, frustum.ViewPoint());
if(dist < 0)
return 1e20f;
if(frustum.IsOutside(sphere.Center(), sphere.Radius()))
return -1;
return entry.error/frustum.Resolution(dist);
}
};
}
#endif

159
apps/nexus/preload.cpp Normal file
View File

@ -0,0 +1,159 @@
#include "preload.h"
#include "nexusmt.h"
using namespace std;
using namespace nxs;
void Preload::execute() {
assert(mt);
while(!get_signaled()) {
lock.enter();
while(!queue.size()) {
lock.leave();
pt::psleep(10);
lock.enter();
}
//TODO check we are not loading too much memory!
assert(queue.size());
unsigned int patch = queue.back();
mt->GetPatch(patch, false);
queue.pop_back();
lock.leave();
}
}
/*void Preload::init(NexusMt *m, std::vector<unsigned int> &selected,
std::vector<PServer::Item> &visited) {
// cerr << "Init\n";
safety.lock();
mt = m;
missing.clear();
mt->todraw.clear();
float loaded = 0;
unsigned int notloaded = 0;
set<unsigned int> tmp;
//std::map<unsigned int, float> tmp;
vector<QueuePServer::Data> flush;
for(unsigned int i = 0; i < selected.size(); i++) {
unsigned int patch = selected[i];
tmp.insert(patch);
if(!mt->patches.entries[patch].patch) {
PServer::Entry &entry = mt->patches.entries[patch];
load.post(patch);
loaded += entry.disk_size;
} else {
PatchInfo &info = mt->index[patch];
//WORKING QueuePServer::Data &data = mt->patches.Lookup(patch, info.nvert, info.nface, 0.0f, flush);
QueuePServer::Data &data = mt->patches.Lookup(patch, info.nvert, info.nface, flush);
for(unsigned int i = 0; i < flush.size(); i++) {
QueuePServer::Data *data = new QueuePServer::Data;
*data = flush[i];
draw.post(FLUSH, (unsigned int)data);
}
// WORKING if(flush.size() != 0) {
// cerr << "Flushing!\n";
// exit(0);
//}
mt->todraw.push_back(&data);
}
//missing.push_back(PServer::Item(patch, 0.0f));
}
loading = 0.2 * loaded + 0.8 * loading;
for(unsigned int i = 0; i < visited.size(); i++) {
PServer::Item &item = visited[i];
if(tmp.count(item.patch)) continue;
// if(mt->patches.entries[item.patch].patch)
// tmp[item.patch] = item.priority;
if(item.priority != 0.0f)
missing.push_back(item);
}*/
/* WORKING 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 = 0;
else {
if(item.priority == 0)
item.priority = 1;
item.priority *= 1.1;
}
}
make_heap(ps.heap.begin(), ps.heap.end());*/
/* sort(missing.begin(), missing.end()); //CRITICAL reverse pero'!
reverse(missing.begin(), missing.end());
load.post(0xffffffff);
safety.unlock();
}
void Preload::execute() {
float preload;
prefetching = 0;
loading = 0;
while(1) {
if(get_signaled()) return;
vector<QueuePServer::Data> flush;
if(load.get_count() || missing.size() == 0) {
preload = 0;
pt::message *msg = load.getmessage();
if(msg->id != 0xffffffff) {
safety.lock();
PatchInfo &info = mt->index[msg->id];
PServer::Entry &entry = mt->patches.entries[msg->id];
loading += entry.disk_size;
//posting draw message
//WORKING QueuePServer::Data &data = mt->patches.Lookup(msg->id, info.nvert, info.nface, 0.0f, flush);
QueuePServer::Data &data = mt->patches.Lookup(msg->id, info.nvert, info.nface, flush);
pt::message *msg = new pt::message(DRAW, (unsigned int)&data);
msg->result = msg->id;
draw.post(msg);
//p;osting flush messages
for(unsigned int i = 0; i < flush.size(); i++) {
QueuePServer::Data *data = new QueuePServer::Data;
*data = flush[i];
draw.post(FLUSH, (unsigned int)data);
}
safety.unlock();
} else {
prefetching = 0.2 * preload + 0.8 * prefetching;
}
delete msg;
} else {
safety.lock();
if(missing.size() != 0) {
PServer::Item item = missing.back();
missing.pop_back();
/*Working if(item.priority > mt->patches.MaxPriority()) {
missing.clear();
} else { */
/*PatchInfo &info = mt->index[item.patch];
//cerr << "prefetching: " << item.patch << endl;
//WORKING mt->patches.Lookup(item.patch, info.nvert, info.nface, item.priority, flush);
if(!mt->patches.entries[item.patch].patch) {
PServer::Entry &entry = mt->patches.entries[item.patch];
preload += entry.disk_size;
mt->patches.Lookup(item.patch, info.nvert, info.nface, flush);
for(unsigned int i = 0; i < flush.size(); i++) {
QueuePServer::Data *data = new QueuePServer::Data;
*data = flush[i];
draw.post(FLUSH, (unsigned int)data);
}
}
// }
}
safety.unlock();
}
}
}*/

40
apps/nexus/preload.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef NXS_PRELOAD_H
#define NXS_PRELOAD_H
#include <assert.h>
#include <vector>
#include <ptypes/pasync.h>
namespace nxs {
class NexusMt;
class Preload: public pt::thread{
public:
NexusMt *mt;
pt::mutex lock;
std::vector<unsigned int> queue;
Preload(): thread(false) {}
~Preload() {
waitfor();
}
void execute();
void post(std::vector<unsigned int> &patches) {
lock.enter();
queue = patches;
lock.leave();
}
void cleanup() {}
};
}
#endif