Realtime viz

This commit is contained in:
Federico Ponchio 2004-12-14 14:10:22 +00:00
parent 9bb65dd0c3
commit 7fb2c4b831
6 changed files with 218 additions and 100 deletions

View File

@ -1,8 +1,11 @@
#include <GL/glew.h>
#include "nexusmt.h"
#include <map> #include <map>
#include <queue> #include <queue>
#include <GL/glew.h>
#include <ptypes/pasync.h>
#include "nexusmt.h"
using namespace nxs; using namespace nxs;
using namespace vcg; using namespace vcg;
@ -104,6 +107,8 @@ NexusMt::NexusMt(): vbo_mode(VBO_AUTO),
NexusMt::~NexusMt() { NexusMt::~NexusMt() {
if(metric) if(metric)
delete metric; delete metric;
prefetch.signal();
prefetch.waitfor();
} }
bool NexusMt::Load(const string &filename) { bool NexusMt::Load(const string &filename) {
@ -174,6 +179,9 @@ bool NexusMt::Load(const string &filename) {
SetComponent(DATA, true); SetComponent(DATA, true);
SetPrefetchSize(patches.ram_max/2); SetPrefetchSize(patches.ram_max/2);
cerr << "Start!\n";
prefetch.start();
cerr << "Started\n";
return true; return true;
} }
@ -204,7 +212,7 @@ void NexusMt::Render() {
} }
void NexusMt::Draw(vector<unsigned int> &cells) { void NexusMt::Draw(vector<unsigned int> &cells) {
prefetch.init(this, cells, visited);
tri_total = 0; tri_total = 0;
tri_rendered = 0; tri_rendered = 0;
@ -218,94 +226,117 @@ void NexusMt::Draw(vector<unsigned int> &cells) {
glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_NORMAL_ARRAY);
//TODO textures and data. //TODO textures and data.
for(unsigned int i = 0; i < cells.size(); i++) { unsigned int count = cells.size();
unsigned int cell = cells[i]; while(count) {
// cerr << "Getting message: " << count << endl;
pt::message *msg = patches.queue.getmessage();
QueuePServer::Data *data = (QueuePServer::Data *)(msg->param);
if(msg->id == QueuePServer::FLUSH) {
// cerr << "Flush...\n";
if(data->vbo_element) {
glDeleteBuffersARB(1, &(data->vbo_element));
glDeleteBuffersARB(1, &(data->vbo_array));
}
delete data;
delete msg;
continue;
}
if(msg->id != QueuePServer::DRAW) {
cerr << "Unknown message!\n";
continue;
}
unsigned int cell = msg->result;
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())) {
continue; tri_rendered += entry.nface;
Draw(cell, *data);
tri_rendered += entry.nface;
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(data.vbo_element);
assert(data.vbo_array);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, data.vbo_array);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, data.vbo_element);
fstart = NULL;
vstart = NULL;
cstart = (char *)(sizeof(float) * patch.cstart);
nstart = (char *)(sizeof(float) * patch.nstart);
} else {
fstart = (char *)patch.FaceBegin();
vstart = (char *)patch.VertBegin();
cstart = (char *)patch.ColorBegin();
nstart = (char *)patch.Norm16Begin();
} }
glVertexPointer(3, GL_FLOAT, 0, vstart); delete msg;
if(use_colors) count--;
glColorPointer(4, GL_UNSIGNED_BYTE, 0, cstart);
if(use_normals)
glNormalPointer(GL_SHORT, 8, nstart);
switch(mode) {
case POINTS:
glDrawArrays(GL_POINTS, 0, patch.nv); break;
case PATCHES:
glColor3ub((cell * 27)%255, (cell * 37)%255, (cell * 87)%255);
case SMOOTH:
if(signature & NXS_FACES)
glDrawElements(GL_TRIANGLES, patch.nf * 3,
GL_UNSIGNED_SHORT, fstart);
else if(signature & NXS_STRIP)
glDrawElements(GL_TRIANGLE_STRIP, patch.nf,
GL_UNSIGNED_SHORT, fstart);
break;
case FLAT:
if(signature & NXS_FACES) {
glBegin(GL_TRIANGLES);
for(int i = 0; i < patch.nf; i++) {
unsigned short *f = patch.Face(i);
Point3f &p0 = patch.Vert(f[0]);
Point3f &p1 = patch.Vert(f[1]);
Point3f &p2 = patch.Vert(f[2]);
Point3f n = ((p1 - p0) ^ (p2 - p0));
glNormal3f(n[0], n[1], n[2]);
glVertex3f(p0[0], p0[1], p0[2]);
glVertex3f(p1[0], p1[1], p1[2]);
glVertex3f(p2[0], p2[1], p2[2]);
}
glEnd();
} else if(signature & NXS_STRIP) {
cerr << "Unsupported rendering mode sorry\n";
exit(0);
}
break;
default:
cerr << "Unsupported rendering mode sorry\n";
exit(0);
break;
}
} }
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_NORMAL_ARRAY);
} }
void NexusMt::Draw(unsigned int cell, QueuePServer::Data &data) {
Patch &patch = *(data.patch);
char *fstart;
char *vstart;
char *cstart;
char *nstart;
if(vbo_mode != VBO_OFF) {
if(!data.vbo_element) {
patches.LoadVbo(data);
}
glBindBufferARB(GL_ARRAY_BUFFER_ARB, data.vbo_array);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, data.vbo_element);
fstart = NULL;
vstart = NULL;
cstart = (char *)(sizeof(float) * patch.cstart);
nstart = (char *)(sizeof(float) * patch.nstart);
} else {
fstart = (char *)patch.FaceBegin();
vstart = (char *)patch.VertBegin();
cstart = (char *)patch.ColorBegin();
nstart = (char *)patch.Norm16Begin();
}
glVertexPointer(3, GL_FLOAT, 0, vstart);
if(use_colors)
glColorPointer(4, GL_UNSIGNED_BYTE, 0, cstart);
if(use_normals)
glNormalPointer(GL_SHORT, 8, nstart);
switch(mode) {
case POINTS:
glDrawArrays(GL_POINTS, 0, patch.nv); break;
case PATCHES:
glColor3ub((cell * 27)%255, (cell * 37)%255, (cell * 87)%255);
case SMOOTH:
if(signature & NXS_FACES)
glDrawElements(GL_TRIANGLES, patch.nf * 3,
GL_UNSIGNED_SHORT, fstart);
else if(signature & NXS_STRIP)
glDrawElements(GL_TRIANGLE_STRIP, patch.nf,
GL_UNSIGNED_SHORT, fstart);
break;
case FLAT:
if(signature & NXS_FACES) {
glBegin(GL_TRIANGLES);
for(int i = 0; i < patch.nf; i++) {
unsigned short *f = patch.Face(i);
Point3f &p0 = patch.Vert(f[0]);
Point3f &p1 = patch.Vert(f[1]);
Point3f &p2 = patch.Vert(f[2]);
Point3f n = ((p1 - p0) ^ (p2 - p0));
glNormal3f(n[0], n[1], n[2]);
glVertex3f(p0[0], p0[1], p0[2]);
glVertex3f(p1[0], p1[1], p1[2]);
glVertex3f(p2[0], p2[1], p2[2]);
}
glEnd();
} else if(signature & NXS_STRIP) {
cerr << "Unsupported rendering mode sorry\n";
exit(0);
}
break;
default:
cerr << "Unsupported rendering mode sorry\n";
exit(0);
break;
}
}
void NexusMt::SetExtractionSize(unsigned int r_size) { void NexusMt::SetExtractionSize(unsigned int r_size) {
extraction_max = r_size/patches.chunk_size; extraction_max = r_size/patches.chunk_size;
} }
@ -471,6 +502,7 @@ void NexusMt::ClearHistory() {
void NexusMt::Extract(std::vector<unsigned int> &selected) { void NexusMt::Extract(std::vector<unsigned int> &selected) {
extraction_used = 0; extraction_used = 0;
visited.clear();
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++) {

View File

@ -3,7 +3,6 @@
#include <vector> #include <vector>
#include <queue> #include <queue>
#include <ptypes/pasync.h>
#include <wrap/gui/frustum.h> #include <wrap/gui/frustum.h>
#include "nexusbase.h" #include "nexusbase.h"
@ -121,9 +120,12 @@ class NexusMt: public NexusBase {
unsigned int tri_total; unsigned int tri_total;
std::vector<PServer::Item> visited; std::vector<PServer::Item> visited;
QueuePServer patches; QueuePServer patches;
BorderServer borders; BorderServer borders;
Prefetch prefetch;
NexusMt(); NexusMt();
~NexusMt(); ~NexusMt();
@ -146,6 +148,7 @@ class NexusMt: public NexusBase {
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 Draw(unsigned int cell, QueuePServer::Data &data);
void Extract(std::vector<unsigned int> &selected); void Extract(std::vector<unsigned int> &selected);
protected: protected:

View File

@ -1,4 +1,5 @@
#include "prefetch.h" #include "prefetch.h"
#include "nexusmt.h"
using namespace std; using namespace std;
using namespace nxs; using namespace nxs;
@ -6,23 +7,35 @@ using namespace nxs;
void Prefetch::init(NexusMt *m, std::vector<unsigned int> &selected, void Prefetch::init(NexusMt *m, std::vector<unsigned int> &selected,
std::vector<PServer::Item> &visited) { std::vector<PServer::Item> &visited) {
// cerr << "Init\n";
safety.lock(); safety.lock();
mt = m; mt = m;
missing.clear(); missing.clear();
unsigned int notloaded = 0;
std::map<unsigned int, float> tmp; std::map<unsigned int, float> tmp;
for(unsigned int i = 0; i < selected.size(); i++) { for(unsigned int i = 0; i < selected.size(); i++) {
unsigned int patch = selected[i]; unsigned int patch = selected[i];
tmp[patch] = 0.0f; tmp[patch] = 0.0f;
if(!mt->patches.IsLoaded(patch))
notloaded++;
// if(mt->patches.IsLoaded(patch))
// mt->todraw.push_back(make_pair(patch, (Patch *)NULL));
// else
missing.push_back(PServer::Item(patch, 0.0f)); missing.push_back(PServer::Item(patch, 0.0f));
} }
if(notloaded)
cerr << "Patches to load: " << notloaded << endl;
for(unsigned int i = 0; i < visited.size(); i++) { for(unsigned int i = 0; i < visited.size(); i++) {
PServer::Item &item = visited[i]; PServer::Item &item = visited[i];
if(tmp.count(item.patch)) continue; if(tmp.count(item.patch)) continue;
if(mt->patches.IsLoaded(item.patch)) if(mt->patches.IsLoaded(item.patch))
tmp[item.patch] = item.priority; tmp[item.patch] = item.priority;
else
missing.push_back(item); missing.push_back(item);
} }
QueuePServer &ps = mt->patches; QueuePServer &ps = mt->patches;
@ -34,6 +47,7 @@ void Prefetch::init(NexusMt *m, std::vector<unsigned int> &selected,
item.priority = 1e40; item.priority = 1e40;
} }
make_heap(ps.heap.begin(), ps.heap.end()); make_heap(ps.heap.begin(), ps.heap.end());
sort(missing.begin(), missing.end()); //CRITICAL reverse pero'! sort(missing.begin(), missing.end()); //CRITICAL reverse pero'!
reverse(missing.begin(), missing.end()); reverse(missing.begin(), missing.end());
safety.unlock(); safety.unlock();
@ -44,13 +58,26 @@ void Prefetch::execute() {
if(get_signaled()) return; if(get_signaled()) return;
while(1) { while(1) {
safety.lock(); safety.lock();
if(missing.size() == 0) break; if(missing.size() == 0) {
safety.unlock();
break;
}
PServer::Item item = missing.back(); PServer::Item item = missing.back();
missing.pop_back(); missing.pop_back();
if(item.priority > 0 &&
mt->patches.ram_used > mt->patches.ram_max &&
item.priority >= mt->patches.MaxPriority()) {
safety.unlock();
break;
}
PatchInfo &info = mt->index[item.patch]; PatchInfo &info = mt->index[item.patch];
// cerr << "prefetching: " << item.patch << endl;
mt->patches.Lookup(item.patch, info.nvert, info.nface, item.priority); mt->patches.Lookup(item.patch, info.nvert, info.nface, item.priority);
safety.unlock(); safety.unlock();
} }
relax(50); relax(5);
} }
} }

View File

@ -7,7 +7,6 @@
#include <ptypes/pasync.h> #include <ptypes/pasync.h>
#include "nexusmt.h"
#include "queuepserver.h" #include "queuepserver.h"
namespace nxs { namespace nxs {
@ -20,7 +19,7 @@ class Prefetch: public pt::thread{
pt::mutex safety; pt::mutex safety;
unsigned int ram_max; unsigned int ram_max;
unsigned int ram_used; unsigned int ram_used;
NexusMt *mt; NexusMt *mt;
std::vector<PServer::Item> missing; std::vector<PServer::Item> missing;

View File

@ -4,28 +4,74 @@
using namespace std; using namespace std;
using namespace nxs; using namespace nxs;
using namespace pt;
QueuePServer::Data &QueuePServer::Lookup(unsigned int patch, QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
unsigned short nv, unsigned short nf, unsigned short nv, unsigned short nf,
float priority) { float priority) {
if(index.count(patch)) { if(index.count(patch)) {
return index[patch]; Data &data = index[patch];
if(priority == 0) {
// cerr << "Posting draw!\n";
message *msg = new message(DRAW, (unsigned int)&data);
msg->result = patch;
queue.post(msg);
}
return data;
} else { } else {
while(ram_used > ram_max) { while(ram_used > ram_max) {
pop_heap(heap.begin(), heap.end()); pop_heap(heap.begin(), heap.end());
Item item = heap.back(); Item item = heap.back();
if(item.priority == 0) break; //no deleting needed patches. if(item.priority == 0) break; //no deleting needed patches.
Data &data = index[patch]; // cerr << "Dropping: " << item.patch << endl;
Data &data = index[item.patch];
FlushVbo(data); FlushVbo(data);
FlushPatch(patch, data.patch); Data *d = new Data(data);
index.erase(patch); queue.post(FLUSH, (unsigned int)d);
FlushPatch(item.patch, data.patch);
index.erase(item.patch);
} }
Item item(patch, priority); Item item(patch, priority);
heap.push_back(item); heap.push_back(item);
push_heap(heap.begin(), heap.end()); push_heap(heap.begin(), heap.end());
Data &data = index[patch]; Data &data = index[patch];
// cerr << "Loading: " << patch << endl;
data.patch = LoadPatch(patch, nv, nf); data.patch = LoadPatch(patch, nv, nf);
if(priority == 0) {
message *msg = new message(DRAW, (unsigned int)&data);
msg->result = patch;
queue.post(msg);
}
return data;
}
}
QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
Patch *mem,
float priority) {
if(index.count(patch)) {
Data &data = index[patch];
return data;
} 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.
// cerr << "Dropping: " << item.patch << endl;
Data &data = index[item.patch];
FlushVbo(data);
FlushPatch(item.patch, data.patch);
index.erase(item.patch);
}
Item item(patch, priority);
heap.push_back(item);
push_heap(heap.begin(), heap.end());
Data &data = index[patch];
// cerr << "Loading: " << patch << endl;
data.patch = mem;
LoadVbo(data); LoadVbo(data);
return data; return data;
} }
@ -34,6 +80,12 @@ QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
bool QueuePServer::IsLoaded(unsigned int patch) { bool QueuePServer::IsLoaded(unsigned int patch) {
return index.count(patch); return index.count(patch);
} }
float QueuePServer::MaxPriority() {
if(!heap.size()) return 0;
return heap.front().priority;
}
void QueuePServer::Flush() { void QueuePServer::Flush() {
std::map<unsigned int, Data>::iterator i; std::map<unsigned int, Data>::iterator i;
for(i = index.begin(); i != index.end(); i++) { for(i = index.begin(); i != index.end(); i++) {
@ -70,12 +122,11 @@ void QueuePServer::LoadVbo(Data &data) {
} }
void QueuePServer::FlushVbo(Data &data) { void QueuePServer::FlushVbo(Data &data) {
if(!vbo_max) return; if(!vbo_max) return;
assert(data.vbo_element); if(!data.vbo_element) return;
assert(data.vbo_array); //glDeleteBuffersARB(1, &data.vbo_element);
glDeleteBuffersARB(1, &data.vbo_element); //glDeleteBuffersARB(1, &data.vbo_array);
glDeleteBuffersARB(1, &data.vbo_array); //data.vbo_element = 0;
data.vbo_element = 0; // data.vbo_array = 0;
data.vbo_array = 0;
Patch &patch = *data.patch; Patch &patch = *data.patch;
vbo_used -= patch.nf * sizeof(unsigned short); vbo_used -= patch.nf * sizeof(unsigned short);

View File

@ -5,6 +5,8 @@
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <ptypes/pasync.h>
#include "pserver.h" #include "pserver.h"
namespace nxs { namespace nxs {
@ -12,6 +14,7 @@ namespace nxs {
class QueuePServer: public PServer { class QueuePServer: public PServer {
public: public:
enum Action { DRAW = 1, FLUSH = 0 };
struct Data { struct Data {
Patch *patch; Patch *patch;
unsigned int vbo_array; unsigned int vbo_array;
@ -19,6 +22,8 @@ class QueuePServer: public PServer {
Data(): patch(NULL), vbo_array(0), vbo_element(0) {} Data(): patch(NULL), vbo_array(0), vbo_element(0) {}
}; };
pt::jobqueue queue;
unsigned int vbo_used; unsigned int vbo_used;
unsigned int vbo_max; unsigned int vbo_max;
@ -28,10 +33,11 @@ class QueuePServer: public PServer {
Data &Lookup(unsigned int patch, unsigned short nv, unsigned short nf, Data &Lookup(unsigned int patch, unsigned short nv, unsigned short nf,
float priority = 0.0f); float priority = 0.0f);
bool IsLoaded(unsigned int patch); Data &Lookup(unsigned int patch, Patch *mem, float priority = 0.0f);
void Flush();
protected: bool IsLoaded(unsigned int patch);
float MaxPriority();
void Flush();
void LoadVbo(Data &data); void LoadVbo(Data &data);
void FlushVbo(Data &data); void FlushVbo(Data &data);