From 2acaf1a5036f07461fb6c16e771f4823ab086a48 Mon Sep 17 00:00:00 2001 From: ponchio Date: Fri, 15 Oct 2004 16:45:27 +0000 Subject: [PATCH] Vbo added. --- apps/nexus/nexus.cpp | 3 ++ apps/nexus/nexus.h | 4 +- apps/nexus/nexusmt.cpp | 65 +++++++++++++++++++++---------- apps/nexus/nexusmt.h | 18 ++++----- apps/nexus/nexusview.cpp | 76 ++++++++++++++++++++++++++++++------- apps/nexus/patchserver.cpp | 51 +++++++++++++++++++++++++ apps/nexus/patchserver.h | 21 +++++++++- apps/nexus/voronoichain.cpp | 51 ++++++++++--------------- 8 files changed, 212 insertions(+), 77 deletions(-) diff --git a/apps/nexus/nexus.cpp b/apps/nexus/nexus.cpp index bf4c5418..e330a1c3 100644 --- a/apps/nexus/nexus.cpp +++ b/apps/nexus/nexus.cpp @@ -164,6 +164,9 @@ 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::Join(const std::set &patches, std::vector &newvert, diff --git a/apps/nexus/nexus.h b/apps/nexus/nexus.h index 24aee63c..6706d1b0 100644 --- a/apps/nexus/nexus.h +++ b/apps/nexus/nexus.h @@ -64,7 +64,9 @@ class Nexus { bool HasColors() { return (signature & NXS_COLORS) != 0; } bool HasNormalsShort() { return (signature & NXS_NORMALS_SHORT) != 0; } bool HasNormalsFloat() { return (signature & NXS_NORMALS_FLOAT) != 0; } - + + void SetRamBufferSize(unsigned int ram_size); + //MOVE to nexus_build.cpp void Join(const std::set &patches, std::vector &vert, diff --git a/apps/nexus/nexusmt.cpp b/apps/nexus/nexusmt.cpp index a19ec473..3d308431 100644 --- a/apps/nexus/nexusmt.cpp +++ b/apps/nexus/nexusmt.cpp @@ -89,7 +89,7 @@ void Policy::NodeVisited(Node *node) { } } -NexusMt::NexusMt(): vbo(VBO_AUTO), vbo_size(0), +NexusMt::NexusMt(): vbo_mode(VBO_AUTO), metric(NULL), mode(SMOOTH) { metric = new FrustumMetric(); metric->index = &index; @@ -115,18 +115,26 @@ bool NexusMt::Load(const string &filename, bool readonly) { SetComponent(TEXTURE, true); SetComponent(DATA, true); + patches.vbos.resize(index.size()); return true; } -bool NexusMt::InitGL() { +bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) { GLenum ret = glewInit(); if(ret != GLEW_OK) return false; - if(!GLEW_ARB_vertex_buffer_object) - vbo = VBO_OFF; + if(!GLEW_ARB_vertex_buffer_object) { + cerr << "No vbo available!" << endl; + vbo_mode = VBO_OFF; + } + if(vbo_mode == VBO_OFF) { + patches.vbo_size = vbosize / patches.chunk_size; + patches.vbos.resize(0); + } return true; } void NexusMt::Render() { + patches.Flush(); Frustumf frustum; frustum.GetView(); @@ -156,15 +164,36 @@ void NexusMt::Render() { tri_rendered += entry.nface; - Patch &patch = GetPatch(cell); + Patch &patch = GetPatch(cell, false); + char *fstart; + char *vstart; + char *cstart; + char *nstart; - assert(patch.start); + if(vbo_mode != VBO_OFF) { + VboBuffer &vbo = patches.GetVbo(cell); + assert(vbo.index); + assert(vbo.vertex); - glVertexPointer(3, GL_FLOAT, 0, patch.VertBegin()); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo.vertex); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo.index); + + 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, patch.ColorBegin()); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, cstart); if(use_normals) - glNormalPointer(GL_SHORT, 8, patch.Norm16Begin()); + glNormalPointer(GL_SHORT, 8, nstart); switch(mode) { case POINTS: @@ -174,10 +203,10 @@ void NexusMt::Render() { case SMOOTH: if(signature & NXS_FACES) glDrawElements(GL_TRIANGLES, patch.nf * 3, - GL_UNSIGNED_SHORT, patch.FaceBegin()); + GL_UNSIGNED_SHORT, fstart); else if(signature & NXS_STRIP) glDrawElements(GL_TRIANGLE_STRIP, patch.nf, - GL_UNSIGNED_SHORT, patch.FaceBegin()); + GL_UNSIGNED_SHORT, fstart); break; default: cerr << "Unsupported rendering mode sorry\n"; @@ -190,7 +219,7 @@ void NexusMt::Render() { glDisableClientState(GL_NORMAL_ARRAY); } -void NexusMt::SetRamSize(unsigned int r_size) { +void NexusMt::SetRamExtractionSize(unsigned int r_size) { policy.ram_size = r_size/patches.chunk_size; } @@ -203,13 +232,8 @@ void NexusMt::SetError(float error) { policy.error = error; } -void NexusMt::SetVbo(Vbo _vbo, unsigned int _vbo_size, - unsigned int _ram_size) { - vbo = _vbo; - if(!GLEW_ARB_vertex_buffer_object) - vbo = VBO_OFF; - vbo_size = _vbo_size; - patches.ram_size = _ram_size/chunk_size; +void NexusMt::SetVboSize(unsigned int _vbo_size) { + patches.vbo_size = _vbo_size; } bool NexusMt::SetMode(Mode _mode) { @@ -448,4 +472,5 @@ void NexusMt::VisitNode(Node *node, vector &heap) { node->visited = true; policy.NodeVisited(node); -} \ No newline at end of file +} + diff --git a/apps/nexus/nexusmt.h b/apps/nexus/nexusmt.h index dcd9ae74..8705f082 100644 --- a/apps/nexus/nexusmt.h +++ b/apps/nexus/nexusmt.h @@ -28,7 +28,7 @@ namespace nxs { TNode(Node *n, float e): node(n), error(e) {} bool operator<(const TNode &n) { return error < n.error; } }; - + class Metric { public: vector *index; @@ -74,11 +74,11 @@ namespace nxs { class NexusMt: public Nexus { private: std::vector nodes; + std::vector vbos; public: //Vertex buffer object mode - enum Vbo { VBO_AUTO, //autodetect best size (fallback if not VBO) - VBO_AUTO_ON, //autodetect best size must use VBO + enum Vbo { VBO_AUTO, //autodetect best size VBO_OFF, //no vertex buffer object VBO_FIXED }; //user supplied size @@ -99,8 +99,7 @@ class NexusMt: public Nexus { TEXTURE = 0x4, DATA = 0x8}; - Vbo vbo; - unsigned int vbo_size; + Vbo vbo_mode; Metric *metric; Policy policy; @@ -121,15 +120,14 @@ class NexusMt: public Nexus { ~NexusMt(); bool Load(const std::string &filename, bool readonly = true); - bool InitGL(); + bool InitGL(Vbo mode = VBO_AUTO, unsigned int vbo_size = 0); void Render(); - + void SetMetric(MetricKind kind); void SetError(float error); - void SetRamSize(unsigned int ram_size); - void SetVbo(Vbo mode, unsigned int vbo_size = 0, - unsigned int ram_size = 128000000); + void SetRamExtractionSize(unsigned int ram_size); + void SetVboSize(unsigned int vbo_size); bool SetMode(Mode mode); bool SetComponent(Component c, bool on); diff --git a/apps/nexus/nexusview.cpp b/apps/nexus/nexusview.cpp index ef2c6adb..f9b3bcad 100644 --- a/apps/nexus/nexusview.cpp +++ b/apps/nexus/nexusview.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.14 2004/10/14 13:52:02 ponchio +Small changes. + Revision 1.13 2004/10/14 13:41:34 ponchio Added statistics. @@ -47,7 +50,6 @@ Backup Revision 1.6 2004/09/17 15:25:09 ponchio First working (hopefully) release. - Revision 1.5 2004/09/16 14:25:16 ponchio Backup. (lot of changes). @@ -94,7 +96,7 @@ using namespace std; #include #include - +#include #include #include "stopwatch.h" @@ -107,7 +109,7 @@ bool fullscreen = false; int width =1024; int height = 768; -//TrackHand hand; +void gl_print(float x, float y, char *str); SDL_Surface *screen = NULL; @@ -206,9 +208,11 @@ int main(int argc, char *argv[]) { unsigned int ram_size = 640000; nexus.SetError(error); - nexus.SetRamSize(ram_size); + nexus.SetRamExtractionSize(ram_size); nexus.SetMetric(NexusMt::FRUSTUM); - + if(!nexus.InitGL()) { + cerr << "Could not init glew.\n"; + } glClearColor(0, 0, 0, 0); glEnable(GL_LIGHTING); @@ -242,11 +246,11 @@ int main(int argc, char *argv[]) { case SDLK_LEFT: ram_size *= 0.7; - nexus.SetRamSize(ram_size); + nexus.SetRamExtractionSize(ram_size); cerr << "Max extraction ram size: " << ram_size << endl; break; case SDLK_RIGHT: ram_size *= 1.5; - nexus.SetRamSize(ram_size); + nexus.SetRamExtractionSize(ram_size); cerr << "Max extraction ram size: " << ram_size << endl; break; case SDLK_s: metric = NexusMt::FRUSTUM; break; @@ -356,13 +360,50 @@ int main(int argc, char *argv[]) { //cerr Do some reporting: if(show_statistics) { - cerr << "Ram used : " << nexus.policy.ram_used << endl; - cerr << "Tri drawn: " << nexus.tri_rendered << endl; - cerr << "Tri tot : " << nexus.tri_total << endl; - cerr << "Ram flushed: " << nexus.patches.ram_flushed << endl; - cerr << "Ram readed: " << nexus.patches.ram_readed << endl; - nexus.patches.ram_flushed = 0; - nexus.patches.ram_readed = 0; + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + gluOrtho2D(0, 1, 0, 1); + + + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + 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, "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)); + 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)); + gl_print(0.03, 0.06, buffer); + + sprintf(buffer, "Triangles: %.2fK (tot) %.2fK (vis)", + nexus.tri_total/(float)(1<<10), + nexus.tri_rendered/(float)(1<<10)); + gl_print(0.03, 0.03, buffer); + + + /* cerr << "Ram flushed: " << nexus.patches.ram_flushed << endl; + cerr << "Ram readed: " << nexus.patches.ram_readed << endl;*/ + nexus.patches.ram_flushed = 0; + nexus.patches.ram_readed = 0; + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } SDL_GL_SwapBuffers(); @@ -374,4 +415,11 @@ int main(int argc, char *argv[]) { return -1; } +void gl_print(float x, float y, char *str) { + glRasterPos2f(x, y); + int len = strlen(str); + for(int i = 0; i < len; i++) + glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, str[i]); +} + diff --git a/apps/nexus/patchserver.cpp b/apps/nexus/patchserver.cpp index 3f0f3437..6b06fbab 100644 --- a/apps/nexus/patchserver.cpp +++ b/apps/nexus/patchserver.cpp @@ -2,6 +2,8 @@ #include #include +#include + using namespace std; using namespace nxs; @@ -16,6 +18,9 @@ bool PatchServer::Create(const std::string &filename, ram_size = rsize; ram_used = 0; + vbo_size = 0; + vbo_used = 0; + ram_readed = 0; ram_flushed = 0; lru.clear(); @@ -33,6 +38,8 @@ bool PatchServer::Load(const std::string &filename, Signature sig, ram_readed = 0; ram_flushed = 0; + vbo_size = 0; + vbo_used = 0; lru.clear(); return File::Load(filename, readonly); } @@ -146,6 +153,38 @@ Patch &PatchServer::GetPatch(unsigned int idx, return *(entry.patch); } +VboBuffer &PatchServer::GetVbo(unsigned int p) { + VboBuffer &buffer = vbos[p]; + if(buffer.index) return buffer; + + //TODO cerr << "Adding vbo: " << p << endl; + assert(patches[p].patch); + Patch &patch = *patches[p].patch; + + glGenBuffersARB(1, &buffer.index); + assert(buffer.index); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer.index); + + 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); + + //TODO fix this when we allow data :p + size = sizeof(float) * patch.dstart; + + glGenBuffersARB(1, &buffer.vertex); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer.vertex); + + glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, patch.VertBegin(), + GL_STATIC_DRAW_ARB); + + vbo_used += patches[p].ram_size; + return buffer; +} + + void PatchServer::Flush() { if(ram_used < ram_size * 1.1) return; @@ -215,10 +254,22 @@ void PatchServer::Flush(unsigned int patch) { delete entry.patch; entry.patch = NULL; entry.lru_pos = 0xffffffff; + if(FlushVbo(patch)) + vbo_used -= entry.ram_size; ram_used -= entry.ram_size; ram_flushed += entry.ram_size; } +bool PatchServer::FlushVbo(unsigned int patch) { + //TODO + //cerr << "Flushing vbo: " << patch << endl; + VboBuffer &buffer = vbos[patch]; + if(!buffer.index) return false; + glDeleteBuffersARB(1, &buffer.index); + glDeleteBuffersARB(1, &buffer.vertex); + return true; +} + void PatchServer::SetRamBufferSize(unsigned int r_buffer) { ram_size = (unsigned int)(r_buffer/chunk_size) + 1; } diff --git a/apps/nexus/patchserver.h b/apps/nexus/patchserver.h index f95d729f..ef7d78ac 100644 --- a/apps/nexus/patchserver.h +++ b/apps/nexus/patchserver.h @@ -16,6 +16,14 @@ struct PatchEntry { unsigned int lru_pos; }; + struct VboBuffer { + VboBuffer(unsigned int v = 0, unsigned int i = 0): + vertex(v), index(i) {} + unsigned int vertex; + unsigned int index; + }; + + class PatchServer: public File { public: struct PTime { @@ -34,6 +42,8 @@ class PatchServer: public File { unsigned int ram_size; unsigned int ram_used; + unsigned int vbo_size; + unsigned int vbo_used; unsigned int frame; //statistics: @@ -53,15 +63,22 @@ class PatchServer: public File { bool WriteEntries(FILE *fp); void AddPatch(unsigned short nvert, unsigned short nface); - Patch &GetPatch(unsigned int patch, unsigned short nvert, unsigned short nface, + Patch &GetPatch(unsigned int patch, + unsigned short nvert, unsigned short nface, bool flush = true); + VboBuffer &GetVbo(unsigned int patch); + + void Flush(unsigned int patch); + //return false if was not allocated. + bool FlushVbo(unsigned int patch); void Flush(); void FlushAll(); - void Flush(unsigned int patch); + void SetRamBufferSize(unsigned int ram_buffer); std::vector patches; + std::vector vbos; std::vector lru; }; diff --git a/apps/nexus/voronoichain.cpp b/apps/nexus/voronoichain.cpp index 0cb7a06e..bd790177 100644 --- a/apps/nexus/voronoichain.cpp +++ b/apps/nexus/voronoichain.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.12 2004/10/15 11:41:03 ponchio +Tests and small changes. + Revision 1.11 2004/10/10 17:19:42 ponchio Added compression and debugged. @@ -127,7 +130,7 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { for(unsigned int v = 0; v < fine.size(); v++) { if(fcount[v] == 0) continue; fine[v].p = fcentroids[v]/(float)fcount[v]; - fine[v].weight = (float)pow(fcount[v]/(float)fine_vmean, 0.3f); + fine[v].weight = (float)pow(fcount[v]/(float)fine_vmean, 0.2f); } fine.Init(); } @@ -138,7 +141,10 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { if(fcount[i] > min_size) seeds.push_back(fine[i]); } - swap(fine, seeds); + fine.clear(); + for(unsigned int i = 0; i < seeds.size(); i++) + fine.push_back(seeds[i]); + if(fine.size() == 0) fine.push_back(Point3f(0,0,0)); fine.Init(); @@ -167,31 +173,12 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { if(ccount[v] == 0) continue; coarse[v].p = ccentroids[v]/(float)ccount[v]; - coarse[v].weight = (float)pow(ccount[v]/(float)coarse_vmean, 0.3f); + coarse[v].weight = (float)pow(ccount[v]/(float)coarse_vmean, 0.2f); if(radius[v] == 0) continue; //repel from fine seeds - unsigned int atarget; - float closest = fine.Closest(coarse[v].p, atarget); - Point3f dir = (coarse[v].p - fine[atarget].p).Normalize(); - Point3f a = coarse[v].p; - Point3f b = fine[atarget].p + dir*radius[v]*1.1; - unsigned int btarget; - closest = fine.Closest(b, btarget); - if(atarget == btarget) { - continue; - } - Point3f m; - for(unsigned int i = 0; i < 10; i++) { - m = (a + b)/2; - unsigned int mtarget; - fine.Closest(m, mtarget); - if(mtarget == atarget) a = m; - else if(mtarget == btarget) b = m; - else break; - } - coarse[v].p = m; + // coarse[v].p = fine.FindBorder(coarse[v].p, radius[v]); } coarse.Init(); } @@ -203,7 +190,10 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { if(ccount[i] > (int)min_size) seeds.push_back(coarse[i]); } - swap(coarse, seeds); + coarse.clear(); + for(unsigned int i = 0; i < seeds.size(); i++) + coarse.push_back(seeds[i]); + if(coarse.size() == 0) coarse.push_back(Point3f(0,0,0)); coarse.Init(); @@ -429,14 +419,11 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset, coarse[v].p = ccentroids[v]/(float)ccount[v]; //0.3 is related to the fact is doubled the box size. - coarse[v].weight = (float)pow(ccount[v]/(float)coarse_vmean, 0.3f); + coarse[v].weight = (float)pow(ccount[v]/(float)coarse_vmean, 0.2f); if(radius[v] == 0) continue; - - //repel from fine seeds - + //coarse[v].p = fine.FindBorder(coarse[v].p, radius[v]); } - // fine.Init(fine.bbox); coarse.Init(); } vector seeds; @@ -444,7 +431,11 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset, if(ccount[i] > (int)min_size) seeds.push_back(coarse[i]); } - swap(coarse, seeds); + + coarse.clear(); + for(unsigned int i = 0; i < seeds.size(); i++) + coarse.push_back(seeds[i]); + if(coarse.size() == 0) coarse.push_back(Point3f(0,0,0)); coarse.Init();