Realtime viz
This commit is contained in:
parent
9bb65dd0c3
commit
7fb2c4b831
|
@ -1,8 +1,11 @@
|
|||
#include <GL/glew.h>
|
||||
#include "nexusmt.h"
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <ptypes/pasync.h>
|
||||
|
||||
#include "nexusmt.h"
|
||||
|
||||
using namespace nxs;
|
||||
using namespace vcg;
|
||||
|
@ -104,6 +107,8 @@ NexusMt::NexusMt(): vbo_mode(VBO_AUTO),
|
|||
NexusMt::~NexusMt() {
|
||||
if(metric)
|
||||
delete metric;
|
||||
prefetch.signal();
|
||||
prefetch.waitfor();
|
||||
}
|
||||
|
||||
bool NexusMt::Load(const string &filename) {
|
||||
|
@ -174,6 +179,9 @@ bool NexusMt::Load(const string &filename) {
|
|||
SetComponent(DATA, true);
|
||||
|
||||
SetPrefetchSize(patches.ram_max/2);
|
||||
cerr << "Start!\n";
|
||||
prefetch.start();
|
||||
cerr << "Started\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -204,7 +212,7 @@ void NexusMt::Render() {
|
|||
}
|
||||
|
||||
void NexusMt::Draw(vector<unsigned int> &cells) {
|
||||
|
||||
prefetch.init(this, cells, visited);
|
||||
tri_total = 0;
|
||||
tri_rendered = 0;
|
||||
|
||||
|
@ -218,94 +226,117 @@ void NexusMt::Draw(vector<unsigned int> &cells) {
|
|||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
//TODO textures and data.
|
||||
|
||||
for(unsigned int i = 0; i < cells.size(); i++) {
|
||||
unsigned int cell = cells[i];
|
||||
unsigned int count = cells.size();
|
||||
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];
|
||||
tri_total += entry.nface;
|
||||
//frustum culling
|
||||
if(frustum.IsOutside(entry.sphere.Center(), entry.sphere.Radius()))
|
||||
continue;
|
||||
|
||||
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();
|
||||
if(!frustum.IsOutside(entry.sphere.Center(), entry.sphere.Radius())) {
|
||||
tri_rendered += entry.nface;
|
||||
Draw(cell, *data);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
delete msg;
|
||||
count--;
|
||||
}
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_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) {
|
||||
extraction_max = r_size/patches.chunk_size;
|
||||
}
|
||||
|
@ -471,6 +502,7 @@ void NexusMt::ClearHistory() {
|
|||
|
||||
void NexusMt::Extract(std::vector<unsigned int> &selected) {
|
||||
extraction_used = 0;
|
||||
visited.clear();
|
||||
|
||||
std::vector<Node>::iterator n;
|
||||
for(n = nodes.begin(); n != nodes.end(); n++) {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <ptypes/pasync.h>
|
||||
#include <wrap/gui/frustum.h>
|
||||
|
||||
#include "nexusbase.h"
|
||||
|
@ -121,9 +120,12 @@ class NexusMt: public NexusBase {
|
|||
unsigned int tri_total;
|
||||
|
||||
std::vector<PServer::Item> visited;
|
||||
|
||||
QueuePServer patches;
|
||||
BorderServer borders;
|
||||
|
||||
Prefetch prefetch;
|
||||
|
||||
NexusMt();
|
||||
~NexusMt();
|
||||
|
||||
|
@ -146,6 +148,7 @@ class NexusMt: public NexusBase {
|
|||
bool SetComponents(unsigned int mask);
|
||||
|
||||
void Draw(std::vector<unsigned int> &selected);
|
||||
void Draw(unsigned int cell, QueuePServer::Data &data);
|
||||
void Extract(std::vector<unsigned int> &selected);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "prefetch.h"
|
||||
#include "nexusmt.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace nxs;
|
||||
|
@ -6,23 +7,35 @@ using namespace nxs;
|
|||
|
||||
void Prefetch::init(NexusMt *m, std::vector<unsigned int> &selected,
|
||||
std::vector<PServer::Item> &visited) {
|
||||
|
||||
// cerr << "Init\n";
|
||||
|
||||
safety.lock();
|
||||
mt = m;
|
||||
missing.clear();
|
||||
|
||||
unsigned int notloaded = 0;
|
||||
std::map<unsigned int, float> tmp;
|
||||
for(unsigned int i = 0; i < selected.size(); i++) {
|
||||
unsigned int patch = selected[i];
|
||||
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));
|
||||
}
|
||||
if(notloaded)
|
||||
cerr << "Patches to load: " << notloaded << endl;
|
||||
|
||||
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);
|
||||
|
||||
missing.push_back(item);
|
||||
}
|
||||
|
||||
QueuePServer &ps = mt->patches;
|
||||
|
@ -34,6 +47,7 @@ void Prefetch::init(NexusMt *m, std::vector<unsigned int> &selected,
|
|||
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();
|
||||
|
@ -44,13 +58,26 @@ void Prefetch::execute() {
|
|||
if(get_signaled()) return;
|
||||
while(1) {
|
||||
safety.lock();
|
||||
if(missing.size() == 0) break;
|
||||
if(missing.size() == 0) {
|
||||
safety.unlock();
|
||||
break;
|
||||
}
|
||||
PServer::Item item = missing.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];
|
||||
|
||||
// cerr << "prefetching: " << item.patch << endl;
|
||||
mt->patches.Lookup(item.patch, info.nvert, info.nface, item.priority);
|
||||
|
||||
safety.unlock();
|
||||
}
|
||||
relax(50);
|
||||
relax(5);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include <ptypes/pasync.h>
|
||||
|
||||
#include "nexusmt.h"
|
||||
#include "queuepserver.h"
|
||||
|
||||
namespace nxs {
|
||||
|
@ -20,7 +19,7 @@ class Prefetch: public pt::thread{
|
|||
pt::mutex safety;
|
||||
unsigned int ram_max;
|
||||
unsigned int ram_used;
|
||||
|
||||
|
||||
NexusMt *mt;
|
||||
std::vector<PServer::Item> missing;
|
||||
|
||||
|
|
|
@ -4,28 +4,74 @@
|
|||
|
||||
using namespace std;
|
||||
using namespace nxs;
|
||||
using namespace pt;
|
||||
|
||||
|
||||
QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
|
||||
unsigned short nv, unsigned short nf,
|
||||
float priority) {
|
||||
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 {
|
||||
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];
|
||||
// cerr << "Dropping: " << item.patch << endl;
|
||||
Data &data = index[item.patch];
|
||||
FlushVbo(data);
|
||||
FlushPatch(patch, data.patch);
|
||||
index.erase(patch);
|
||||
Data *d = new Data(data);
|
||||
queue.post(FLUSH, (unsigned int)d);
|
||||
|
||||
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 = 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);
|
||||
return data;
|
||||
}
|
||||
|
@ -34,6 +80,12 @@ QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
|
|||
bool QueuePServer::IsLoaded(unsigned int patch) {
|
||||
return index.count(patch);
|
||||
}
|
||||
|
||||
float QueuePServer::MaxPriority() {
|
||||
if(!heap.size()) return 0;
|
||||
return heap.front().priority;
|
||||
}
|
||||
|
||||
void QueuePServer::Flush() {
|
||||
std::map<unsigned int, Data>::iterator i;
|
||||
for(i = index.begin(); i != index.end(); i++) {
|
||||
|
@ -70,12 +122,11 @@ void QueuePServer::LoadVbo(Data &data) {
|
|||
}
|
||||
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;
|
||||
if(!data.vbo_element) return;
|
||||
//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);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <ptypes/pasync.h>
|
||||
|
||||
#include "pserver.h"
|
||||
|
||||
namespace nxs {
|
||||
|
@ -12,6 +14,7 @@ namespace nxs {
|
|||
class QueuePServer: public PServer {
|
||||
public:
|
||||
|
||||
enum Action { DRAW = 1, FLUSH = 0 };
|
||||
struct Data {
|
||||
Patch *patch;
|
||||
unsigned int vbo_array;
|
||||
|
@ -19,6 +22,8 @@ class QueuePServer: public PServer {
|
|||
Data(): patch(NULL), vbo_array(0), vbo_element(0) {}
|
||||
};
|
||||
|
||||
pt::jobqueue queue;
|
||||
|
||||
unsigned int vbo_used;
|
||||
unsigned int vbo_max;
|
||||
|
||||
|
@ -28,10 +33,11 @@ class QueuePServer: public PServer {
|
|||
Data &Lookup(unsigned int patch, unsigned short nv, unsigned short nf,
|
||||
float priority = 0.0f);
|
||||
|
||||
bool IsLoaded(unsigned int patch);
|
||||
void Flush();
|
||||
Data &Lookup(unsigned int patch, Patch *mem, float priority = 0.0f);
|
||||
|
||||
protected:
|
||||
bool IsLoaded(unsigned int patch);
|
||||
float MaxPriority();
|
||||
void Flush();
|
||||
|
||||
void LoadVbo(Data &data);
|
||||
void FlushVbo(Data &data);
|
||||
|
|
Loading…
Reference in New Issue