diff --git a/apps/nexus/nexusmt.cpp b/apps/nexus/nexusmt.cpp index 3d308431..5e78c3eb 100644 --- a/apps/nexus/nexusmt.cpp +++ b/apps/nexus/nexusmt.cpp @@ -115,7 +115,6 @@ bool NexusMt::Load(const string &filename, bool readonly) { SetComponent(TEXTURE, true); SetComponent(DATA, true); - patches.vbos.resize(index.size()); return true; } @@ -126,10 +125,9 @@ bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) { 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); - } + patches.vbo_size = vbosize / patches.chunk_size; + if(vbo_mode == VBO_OFF) + patches.vbo_size = 0; return true; } @@ -171,12 +169,14 @@ void NexusMt::Render() { char *nstart; if(vbo_mode != VBO_OFF) { - VboBuffer &vbo = patches.GetVbo(cell); - assert(vbo.index); - assert(vbo.vertex); + unsigned int vbo_array; + unsigned int vbo_element; + patches.GetVbo(cell, vbo_element, vbo_array); + assert(vbo_element); + assert(vbo_array); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo.vertex); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo.index); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_array); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo_element); fstart = NULL; vstart = NULL; @@ -208,6 +208,26 @@ void NexusMt::Render() { 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); diff --git a/apps/nexus/nexusmt.h b/apps/nexus/nexusmt.h index 8705f082..21b5a09f 100644 --- a/apps/nexus/nexusmt.h +++ b/apps/nexus/nexusmt.h @@ -74,7 +74,6 @@ namespace nxs { class NexusMt: public Nexus { private: std::vector nodes; - std::vector vbos; public: //Vertex buffer object mode diff --git a/apps/nexus/nexusview.cpp b/apps/nexus/nexusview.cpp index f9b3bcad..3eda7a59 100644 --- a/apps/nexus/nexusview.cpp +++ b/apps/nexus/nexusview.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.15 2004/10/15 16:45:27 ponchio +Vbo added. + Revision 1.14 2004/10/14 13:52:02 ponchio Small changes. @@ -188,6 +191,7 @@ int main(int argc, char *argv[]) { " b: increase memory buffer\n" " B: decrease memory buffer\n" " d: debug mode (show patches colored)\n" + " f: flas shading mode\n" " m: smooth mode\n" " c: show colors\n" " n: show normals\n" @@ -225,6 +229,8 @@ int main(int argc, char *argv[]) { int x, y; float alpha = 0; bool redraw = false; + float fps = 0; + float tframe = 0; while( !quit ) { bool first = true; SDL_WaitEvent(&event); @@ -256,6 +262,7 @@ int main(int argc, char *argv[]) { case SDLK_s: metric = NexusMt::FRUSTUM; break; case SDLK_p: mode = NexusMt::POINTS; nexus.SetMode(mode); break; case SDLK_d: mode = NexusMt::DEBUG; nexus.SetMode(mode); break; + case SDLK_f: mode = NexusMt::FLAT; nexus.SetMode(mode); break; case SDLK_m: mode = NexusMt::SMOOTH; nexus.SetMode(mode); break; case SDLK_r: @@ -389,9 +396,11 @@ int main(int argc, char *argv[]) { nexus.patches.vbo_used * nexus.chunk_size/(float)(1<<20)); gl_print(0.03, 0.06, buffer); - sprintf(buffer, "Triangles: %.2fK (tot) %.2fK (vis)", + sprintf(buffer, "Triangles: %.2fK (tot) %.2fK (vis) " + "%.3f time %.2f FPS", nexus.tri_total/(float)(1<<10), - nexus.tri_rendered/(float)(1<<10)); + nexus.tri_rendered/(float)(1<<10), + tframe, 1/tframe); gl_print(0.03, 0.03, buffer); @@ -407,6 +416,8 @@ int main(int argc, char *argv[]) { } SDL_GL_SwapBuffers(); + tframe = watch.Elapsed(); + } // Clean up diff --git a/apps/nexus/nxsalgo.cpp b/apps/nexus/nxsalgo.cpp index b25381c8..13cccec9 100644 --- a/apps/nexus/nxsalgo.cpp +++ b/apps/nexus/nxsalgo.cpp @@ -126,11 +126,12 @@ void nxs::ComputeNormals(Nexus &nexus) { Point3f &n = tmpb[off + i]; n.Normalize(); if(use_short) { - n *= 32767; + n *= 32766; short *np = patch.Norm16(link.start_vert); np[0] = (short)n[0]; np[1] = (short)n[1]; np[2] = (short)n[2]; + np[3] = 0; } else { patch.Norm32(link.start_vert) = n; } @@ -221,3 +222,36 @@ void nxs::ComputeTriStrip(unsigned short nfaces, unsigned short *faces, } } } + +void nxs::Reorder(unsigned int signature, Patch &patch) { + vector remap; + remap.resize(patch.nv, 0xffff); + + int nf = patch.nf; + if(signature & NXS_FACES) + nf *= 3; + + //building remap + unsigned short *f = patch.FaceBegin(); + unsigned int count = 0; + for(int i = 0; i < nf; i++) { + assert(f[i] < remap.size()); + if(remap[f[i]] == 0xffff) { + remap[f[i]] = count++; + } + } + //test no unreferenced vertices + for(int i = 0; i < patch.nv; i++) + if(remap[i] == 0xffff) + remap[i] = i; + + //converting faces + for(int i = 0; i < nf; i++) + f[i] = remap[f[i]]; + + vector vert; + vert.resize(patch.nv); + memcpy(&*vert.begin(), patch.VertBegin(), patch.nv * sizeof(Point3f)); + for(int i = 0; i < patch.nv; i++) + patch.Vert(remap[i]) = vert[i]; +} diff --git a/apps/nexus/nxsalgo.h b/apps/nexus/nxsalgo.h index 8f9b1e05..aea115d5 100644 --- a/apps/nexus/nxsalgo.h +++ b/apps/nexus/nxsalgo.h @@ -6,10 +6,12 @@ namespace nxs { class Nexus; + class Patch; void ComputeNormals(Nexus &nexus); void ComputeTriStrip(unsigned short nfaces, unsigned short *faces, std::vector &strip); + void Reorder(unsigned int signature, nxs::Patch &patch); } #endif diff --git a/apps/nexus/nxsedit.cpp b/apps/nexus/nxsedit.cpp index 2e8e5696..f10a089c 100644 --- a/apps/nexus/nxsedit.cpp +++ b/apps/nexus/nxsedit.cpp @@ -338,6 +338,9 @@ int main(int argc, char *argv[]) { memcpy(dst_patch.Norm16Begin(), src_patch.Norm16Begin(), src_patch.nv * sizeof(short)*4); + //reordering + //WATCH OUT BORDERS! + // Reorder(out.signature, dst_patch); //copying entry information; dst_entry.sphere = src_entry.sphere; dst_entry.error = src_entry.error; diff --git a/apps/nexus/patchserver.cpp b/apps/nexus/patchserver.cpp index de6e7915..ddf67e30 100644 --- a/apps/nexus/patchserver.cpp +++ b/apps/nexus/patchserver.cpp @@ -14,15 +14,16 @@ bool PatchServer::Create(const std::string &filename, unsigned int rsize) { signature = sig; chunk_size = csize; - frame = 0; + ram_size = rsize; ram_used = 0; - vbo_size = 0; vbo_used = 0; + frame = 0; ram_readed = 0; ram_flushed = 0; + lru.clear(); return File::Create(filename); } @@ -30,16 +31,19 @@ bool PatchServer::Create(const std::string &filename, bool PatchServer::Load(const std::string &filename, Signature sig, unsigned int csize, bool readonly, unsigned int rsize) { + signature = sig; chunk_size = csize; - ram_size = rsize; - frame = 0; - ram_used = 0; - ram_readed = 0; - ram_flushed = 0; + ram_size = rsize; + ram_used = 0; vbo_size = 0; vbo_used = 0; + + frame = 0; + ram_readed = 0; + ram_flushed = 0; + lru.clear(); return File::Load(filename, readonly); } @@ -55,7 +59,6 @@ bool PatchServer::ReadEntries(FILE *fp) { fread(&n, 1, sizeof(int), fp); patches.resize(n); for(unsigned int i = 0; i < n; i++) { - patches[i].patch = NULL; fread(&(patches[i].patch_start), 1, sizeof(unsigned int), fp); fread(&(patches[i].ram_size), 1, sizeof(unsigned short), fp); fread(&(patches[i].disk_size), 1, sizeof(unsigned short), fp); @@ -77,22 +80,12 @@ bool PatchServer::WriteEntries(FILE *fp) { void PatchServer::AddPatch(unsigned short nvert, unsigned short nface) { PatchEntry entry; - entry.patch = NULL; - entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size); - //if compressed we do not allocate space now (how much anyway?) - // if((signature & NXS_COMPRESSED) != 0) { - entry.disk_size = 0xffff; - entry.patch_start = 0xffffffff; - /* } else { - entry.disk_size = entry.ram_size; - entry.patch_start = Length()/chunk_size; - Redim(Length() + entry.disk_size * chunk_size); - }*/ + entry.patch_start = 0xffffffff; + entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size); + entry.disk_size = 0xffff; entry.lru_pos = 0xffffffff; patches.push_back(entry); - - } Patch &PatchServer::GetPatch(unsigned int idx, @@ -101,19 +94,12 @@ Patch &PatchServer::GetPatch(unsigned int idx, assert(idx < patches.size()); PatchEntry &entry = patches[idx]; - if(entry.patch) { //already on buffer - assert(entry.lru_pos < lru.size()); - assert(lru[entry.lru_pos].patch == idx); - lru[entry.lru_pos].frame = frame++; - - } else { - - assert(entry.lru_pos == 0xffffffff); + if(entry.lru_pos == 0xffffffff) { //not on buffer if(flush) Flush(); - + PTime nptime(idx); char *ram = new char[entry.ram_size * chunk_size]; - entry.patch = new Patch(signature, ram, nvert, nface); + nptime.patch = new Patch(signature, ram, nvert, nface); if(entry.patch_start != 0xffffffff) { //was allocated. assert(entry.disk_size != 0xffff); @@ -127,17 +113,20 @@ Patch &PatchServer::GetPatch(unsigned int idx, unsigned char *disk = new unsigned char[entry.disk_size * chunk_size]; ReadBuffer(disk, entry.disk_size * chunk_size); - entry.patch->Decompress(entry.ram_size * chunk_size, - disk, entry.disk_size * chunk_size); + nptime.patch->Decompress(entry.ram_size * chunk_size, + disk, entry.disk_size * chunk_size); delete []disk; } } - + entry.lru_pos = lru.size(); - lru.push_back(PTime(idx, frame++)); + lru.push_back(nptime); ram_used += entry.ram_size; ram_readed += entry.ram_size; } + + PTime &ptime = lru[entry.lru_pos]; + ptime.frame = frame++; //avoid frame overflow! if(frame > (1<<30)) { @@ -148,40 +137,47 @@ Patch &PatchServer::GetPatch(unsigned int idx, } make_heap(lru.begin(), lru.end()); for(unsigned int i = 0; i < lru.size(); i++) - patches[lru[i].patch].lru_pos = i; + patches[lru[i].npatch].lru_pos = i; } - return *(entry.patch); + return *(ptime.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; +void PatchServer::GetVbo(unsigned int p, + unsigned int &element, unsigned int &array) { + PatchEntry &entry = patches[p]; + assert(entry.lru_pos != 0xffffffff); + PTime &ptime = lru[entry.lru_pos]; + if(!ptime.vbo_element) { + //TODO cerr << "Adding vbo: " << p << endl; + assert(ptime.patch); + + Patch &patch = *ptime.patch; + + glGenBuffersARB(1, &ptime.vbo_element); + assert(ptime.vbo_element); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ptime.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); + + //TODO fix this when we allow data :p + size = sizeof(float) * patch.dstart; + + glGenBuffersARB(1, &ptime.vbo_array); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, ptime.vbo_array); + + glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, patch.VertBegin(), + GL_STATIC_DRAW_ARB); + + vbo_used += patches[p].ram_size; + } - 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; + element = ptime.vbo_element; + array = ptime.vbo_array; } @@ -191,22 +187,22 @@ void PatchServer::Flush() { make_heap(lru.begin(), lru.end()); for(unsigned int i = 0; i < lru.size(); i++) - patches[lru[i].patch].lru_pos = i; + patches[lru[i].npatch].lru_pos = i; while(ram_used > ram_size) { pop_heap(lru.begin(), lru.end()); PTime &ptime = lru.back(); - Flush(ptime.patch); + Flush(ptime.npatch); lru.pop_back(); } for(unsigned int i = 0; i < lru.size(); i++) - patches[lru[i].patch].lru_pos = i; + patches[lru[i].npatch].lru_pos = i; } void PatchServer::FlushAll() { for(unsigned int i = 0; i < lru.size(); i++) { PTime &ptime = lru[i]; - Flush(ptime.patch); + Flush(ptime.npatch); } assert(ram_used == 0); lru.clear(); @@ -214,14 +210,13 @@ void PatchServer::FlushAll() { void PatchServer::Flush(unsigned int patch) { PatchEntry &entry = patches[patch]; - assert(entry.patch); - + PTime &ptime = lru[entry.lru_pos]; if(!readonly) { //write back patch if((signature & NXS_COMPRESSED)) { unsigned int compressed_size; - char *compressed = entry.patch->Compress(entry.ram_size * chunk_size, + char *compressed = ptime.patch->Compress(entry.ram_size * chunk_size, compressed_size); if(entry.disk_size == 0xffff) {//allocate space assert(entry.patch_start == 0xffffffff); @@ -242,7 +237,7 @@ void PatchServer::Flush(unsigned int patch) { Redim(Length() + entry.disk_size * chunk_size); } SetPosition(entry.patch_start * chunk_size); - WriteBuffer(entry.patch->start, entry.disk_size * chunk_size); + WriteBuffer(ptime.patch->start, entry.disk_size * chunk_size); } /* FILE *fo = fopen("tmp", "wb+"); fwrite(entry.patch->start, 1, entry.disk_size * chunk_size, fo); @@ -250,12 +245,14 @@ void PatchServer::Flush(unsigned int patch) { exit(0);*/ } - delete [](entry.patch->start); - delete entry.patch; - entry.patch = NULL; - entry.lru_pos = 0xffffffff; + delete [](ptime.patch->start); + delete ptime.patch; + ptime.patch = NULL; + if(FlushVbo(patch)) vbo_used -= entry.ram_size; + + entry.lru_pos = 0xffffffff; ram_used -= entry.ram_size; ram_flushed += entry.ram_size; } @@ -263,11 +260,14 @@ void PatchServer::Flush(unsigned int patch) { bool PatchServer::FlushVbo(unsigned int patch) { //TODO //cerr << "Flushing vbo: " << patch << endl; - if(!vbos.size()) return false; - VboBuffer &buffer = vbos[patch]; - if(!buffer.index) return false; - glDeleteBuffersARB(1, &buffer.index); - glDeleteBuffersARB(1, &buffer.vertex); + PatchEntry &entry = patches[patch]; + assert(entry.lru_pos != 0xffffffff); + PTime &ptime = lru[entry.lru_pos]; + if(!ptime.vbo_element) return false; + + glDeleteBuffersARB(1, &ptime.vbo_element); + glDeleteBuffersARB(1, &ptime.vbo_array); + assert(!ptime.vbo_element); return true; } diff --git a/apps/nexus/patchserver.h b/apps/nexus/patchserver.h index ef7d78ac..e0cc70b3 100644 --- a/apps/nexus/patchserver.h +++ b/apps/nexus/patchserver.h @@ -9,29 +9,27 @@ namespace nxs { struct PatchEntry { - Patch *patch; unsigned int patch_start; //granularita' Chunk unsigned short ram_size; //in chunks unsigned short disk_size; // in chunks (used when compressed) 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 { - unsigned int patch; + unsigned int npatch; unsigned int frame; + + Patch *patch; + unsigned int vbo_array; + unsigned int vbo_element; + bool locked; PTime(unsigned int p = 0xffffffff, unsigned int f = 0xffffffff): - patch(p), frame(f) {} + npatch(p), frame(f), patch(NULL), + vbo_array(0), vbo_element(0) {} bool operator<(const PTime &p) const { return frame > p.frame; } }; @@ -67,7 +65,7 @@ class PatchServer: public File { unsigned short nvert, unsigned short nface, bool flush = true); - VboBuffer &GetVbo(unsigned int patch); + void GetVbo(unsigned int patch, unsigned int &element, unsigned int &array); void Flush(unsigned int patch); //return false if was not allocated. @@ -78,7 +76,6 @@ class PatchServer: public File { void SetRamBufferSize(unsigned int ram_buffer); std::vector patches; - std::vector vbos; std::vector lru; }; diff --git a/apps/nexus/voronoinxs.cpp b/apps/nexus/voronoinxs.cpp index 17ed2cac..1315b98a 100644 --- a/apps/nexus/voronoinxs.cpp +++ b/apps/nexus/voronoinxs.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.15 2004/10/15 11:41:03 ponchio +Tests and small changes. + Revision 1.14 2004/10/10 17:19:42 ponchio Added compression and debugged. @@ -85,6 +88,7 @@ using namespace std; #include "vert_remap.h" #include "decimate.h" +#include "fragment.h" #include "nxsbuild.h" using namespace vcg; using namespace nxs; @@ -116,6 +120,10 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain, Nexus::Update &update, float error); +void BuildFragment(Nexus &nexus, VoronoiPartition &part, + set &patches, + Fragment &fragment); + /*float Decimate(unsigned int target_faces, vector &newvert, vector &newface, @@ -324,9 +332,11 @@ int main(int argc, char *argv[]) { vector newvert; vector newface; vector newbord; - - nexus.Join((*fragment).second, newvert, newface, newbord); + Fragment frag; + BuildFragment(nexus, vchain.levels[level+1], (*fragment).second, frag); + // nexus.Join((*fragment).second, newvert, newface, newbord); + join(frag, newvert, newface, newbord); //simplyfy mesh vector vert_remap; float error = Decimate(decimation, @@ -610,6 +620,31 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain, } } +void BuildFragment(Nexus &nexus, VoronoiPartition &part, + set &patches, + Fragment &fragment) { + set::iterator f; + for(f = patches.begin(); f != patches.end(); f++) { + fragment.pieces.push_back(NxsPatch()); + NxsPatch &nxs = fragment.pieces.back(); + nxs.patch = *f; + + Patch &patch = nexus.GetPatch(*f); + Border border = nexus.GetBorder(*f); + + nxs.vert.resize(patch.nv); + nxs.face.resize(patch.nf * 3); + memcpy(&*nxs.vert.begin(), patch.VertBegin(), patch.nv * sizeof(Point3f)); + memcpy(&*nxs.face.begin(), patch.FaceBegin(), patch.nf * 3*sizeof(short)); + for(unsigned int i = 0; i < border.Size(); i++) { + Link &link = border[i]; + if(!link.IsNull()) + nxs.bord.push_back(link); + } + fragment.update.erased.push_back(*f); + } +} + void ReverseHistory(vector &history) { reverse(history.begin(), history.end()); vector::iterator i;