From 58c216871966cd4cee871f5de71f78de247a4c44 Mon Sep 17 00:00:00 2001 From: ponchio Date: Fri, 1 Oct 2004 16:54:57 +0000 Subject: [PATCH] Daily backup. --- apps/nexus/decimate.cpp | 112 ++++++++++------- apps/nexus/decimate.h | 20 +++ apps/nexus/nexus.cpp | 8 +- apps/nexus/nexus.h | 4 +- apps/nexus/nexusmt.cpp | 3 + apps/nexus/nexusview.cpp | 241 ++++++++++++------------------------ apps/nexus/nxsalgo.cpp | 8 +- apps/nexus/nxsbuild.cpp | 223 +++++++++++++++++++++++++++++++++ apps/nexus/nxsbuild.h | 39 ++++++ apps/nexus/nxsedit.cpp | 17 ++- apps/nexus/patch.cpp | 32 ++++- apps/nexus/patch.h | 6 +- apps/nexus/voronoichain.cpp | 6 + apps/nexus/voronoinxs.cpp | 69 ++++------- 14 files changed, 520 insertions(+), 268 deletions(-) create mode 100644 apps/nexus/decimate.h create mode 100644 apps/nexus/nxsbuild.cpp create mode 100644 apps/nexus/nxsbuild.h diff --git a/apps/nexus/decimate.cpp b/apps/nexus/decimate.cpp index 3278ea25..01845692 100644 --- a/apps/nexus/decimate.cpp +++ b/apps/nexus/decimate.cpp @@ -1,4 +1,3 @@ -#include #include // stuff to define the mesh @@ -7,10 +6,6 @@ #include #include -// io -//#include -//#include -// update #include #include @@ -19,53 +14,53 @@ #include #include "pvoronoi.h" -#include "border.h" +//#include "border.h" -class MyEdge; -class MyFace; -class MyVertex:public vcg::VertexAFVMVNf{public: -ScalarType w; -vcg::math::Quadric >q; -ScalarType & W(){return w;} -} ; -class MyFace : public vcg::FaceAV{}; - -class MyMesh: - public vcg::tri::TriMesh< std::vector, std::vector >{}; - -class MyTriEdgeCollapse: - public vcg::tri::TriEdgeCollapseQuadric< MyMesh, MyTriEdgeCollapse >{ -public: - typedef vcg::tri::TriEdgeCollapseQuadric TECQ; - typedef TECQ::PosType PosType; - MyTriEdgeCollapse(PosType p, int i):TECQ(p,i){} - ~MyTriEdgeCollapse(){} -}; +#include "decimate.h" using namespace vcg; using namespace tri; using namespace nxs; using namespace std; -float Clustering(unsigned int target_faces, - vector &newvert, - vector &newface, - vector &newbord, - vector &vert_remap) { -} +class MyEdge; +class MyFace; +class MyVertex: + public vcg::VertexAFVMVNf { +public: + ScalarType w; + vcg::math::Quadric > q; + ScalarType & W() { return w; } +}; + +class MyFace : public vcg::FaceAV {}; + +class MyMesh: + public vcg::tri::TriMesh< std::vector, std::vector > {}; + +class MyTriEdgeCollapse: + public vcg::tri::TriEdgeCollapseQuadric< MyMesh, MyTriEdgeCollapse > { +public: + typedef vcg::tri::TriEdgeCollapseQuadric TECQ; + typedef TECQ::PosType PosType; + MyTriEdgeCollapse(PosType p, int i): TECQ(p, i) {} + ~MyTriEdgeCollapse() {} +}; + float Cluster(MyMesh &mesh, unsigned int target_faces); +float Quadric(MyMesh &mesh, unsigned int target_faces); -float Decimate(unsigned int target_faces, - vector &newvert, - vector &newface, - vector &newbord, - vector &vert_remap) { +float nxs::Decimate(Decimation mode, + unsigned int target_faces, + vector &newvert, + vector &newface, + vector &newbord, + vector &vert_remap) { MyMesh mesh; //build mesh - for(unsigned int i = 0; i < newvert.size(); i++) { MyVertex vertex; vertex.ClearFlags(); @@ -85,18 +80,17 @@ float Decimate(unsigned int target_faces, } mesh.fn = mesh.face.size(); - //emark borders + //mark borders for(unsigned int i = 0; i < newbord.size(); i++) mesh.vert[newbord[i].start_vert].ClearW(); + // int FinalSize = mesh.face.size()/2; // if(FinalSize > target_faces) FinalSize = target_faces; - int FinalSize = target_faces; - printf("mesh loaded %d %d \n",mesh.vn,mesh.fn); - printf("reducing it to %i\n",FinalSize); + printf("reducing it to %i\n", target_faces); /* @@ -115,7 +109,11 @@ float Decimate(unsigned int target_faces, float error = DeciSession.currMetric/4;//1; //get error; int t3=clock(); */ - float error = Cluster(mesh, target_faces); + float error; + if(mode == CLUSTER) + error = Cluster(mesh, target_faces); + else + error = Quadric(mesh, target_faces); @@ -164,6 +162,34 @@ float Decimate(unsigned int target_faces, } +float Quadric(MyMesh &mesh, unsigned int target_faces) { + vcg::tri::UpdateTopology::VertexFace(mesh); + vcg::LocalOptimization DeciSession(mesh); + + MyTriEdgeCollapse::SetDefaultParams(); + + DeciSession.Init(); + + DeciSession.SetTargetSimplices(target_faces); + DeciSession.DoOptimization(); + + float error = 0; + int count = 0; + for(unsigned int i = 0; i < mesh.face.size(); i++) { + MyFace &face = mesh.face[i]; + if(face.IsD()) continue; + for(int k = 0; k < 3; k++) { + error += (face.cV(k)->cP() - face.cV((k+1)%3)->cP()).Norm(); + count++; + } + } + error /= count; + cerr << "Error: " << error << endl; + cerr << "faces: " << mesh.fn << endl; + cerr << "verts: " << mesh.vn << endl; + return error; +} + float Cluster(MyMesh &mesh, unsigned int target_faces) { unsigned int starting = mesh.vn; diff --git a/apps/nexus/decimate.h b/apps/nexus/decimate.h new file mode 100644 index 00000000..6d1215c5 --- /dev/null +++ b/apps/nexus/decimate.h @@ -0,0 +1,20 @@ +#ifndef NXS_DECIMATE_H +#define NXS_DECIMATE_H + +#include +#include "border.h" +#include +namespace nxs { + + enum Decimation { QUADRIC, CLUSTER }; + + float Decimate(Decimation mode, + unsigned int target_faces, + std::vector &newvert, + std::vector &newface, + std::vector &newbord, + std::vector &vert_remap); + +} + +#endif diff --git a/apps/nexus/nexus.cpp b/apps/nexus/nexus.cpp index b89168fb..87df6ff2 100644 --- a/apps/nexus/nexus.cpp +++ b/apps/nexus/nexus.cpp @@ -124,15 +124,15 @@ void Nexus::Close() { borders.Close(); } -Patch Nexus::GetPatch(unsigned int patch) { +Patch Nexus::GetPatch(unsigned int patch, bool flush) { Entry &entry = index[patch]; - Chunk *start = patches.GetRegion(entry.patch_start, entry.patch_size); + Chunk *start = patches.GetRegion(entry.patch_start, entry.patch_size,flush); return Patch(signature, start, entry.nvert, entry.nface); } -Border Nexus::GetBorder(unsigned int patch) { +Border Nexus::GetBorder(unsigned int patch, bool flush) { Entry &entry = index[patch]; - Link *start = borders.GetRegion(entry.border_start, entry.border_size); + Link *start = borders.GetRegion(entry.border_start, entry.border_size,flush); return Border(start, entry.border_used, entry.border_size); } diff --git a/apps/nexus/nexus.h b/apps/nexus/nexus.h index f8160b74..63afd7bf 100644 --- a/apps/nexus/nexus.h +++ b/apps/nexus/nexus.h @@ -49,8 +49,8 @@ class Nexus { virtual bool Load(const std::string &filename); virtual void Close(); - Patch GetPatch(unsigned int patch); - Border GetBorder(unsigned int patch); + Patch GetPatch(unsigned int patch, bool flush = true); + Border GetBorder(unsigned int patch, bool flush = true); bool IsCompressed() { return signature & NXS_COMPRESSED; } diff --git a/apps/nexus/nexusmt.cpp b/apps/nexus/nexusmt.cpp index e2f6150b..b5227fd6 100644 --- a/apps/nexus/nexusmt.cpp +++ b/apps/nexus/nexusmt.cpp @@ -86,15 +86,18 @@ void NexusMt::Render() { for(unsigned int i = 0; i < cells.size(); i++) { unsigned int cell = cells[i]; Nexus::Entry &entry = index[cell]; + //frustum culling // if(frustum.Outside(entry.sphere.center, entry.sphere.radius)) // continue; + Patch patch = GetPatch(cell); glVertexPointer(3, GL_FLOAT, 0, patch.VertBegin()); if(use_colors) glColorPointer(4, GL_UNSIGNED_BYTE, 0, patch.ColorBegin()); if(use_normals) glNormalPointer(GL_SHORT, 8, patch.Norm16Begin()); + switch(mode) { case POINTS: glDrawArrays(GL_POINTS, 0, patch.nv); break; diff --git a/apps/nexus/nexusview.cpp b/apps/nexus/nexusview.cpp index 65a7c51d..2785d4b2 100644 --- a/apps/nexus/nexusview.cpp +++ b/apps/nexus/nexusview.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.9 2004/09/30 23:56:33 ponchio +Backup (added strips and normals) + Revision 1.8 2004/09/30 00:27:42 ponchio Lot of changes. Backup. @@ -66,12 +69,6 @@ Created ****************************************************************************/ -#ifdef WIN32 -#include "getopt.h" -#else -#include -#endif - #include using namespace std; @@ -95,7 +92,7 @@ int height = 768; SDL_Surface *screen = NULL; -bool init() { +bool init(const string &str) { if(SDL_Init(SDL_INIT_VIDEO) != 0) { return false; @@ -117,7 +114,7 @@ bool init() { } SDL_WM_SetIcon(SDL_LoadBMP("inspector.bmp"), NULL); - SDL_WM_SetCaption(" Inspector", "Inspector"); + SDL_WM_SetCaption(str.c_str(), str.c_str()); glDisable(GL_DITHER); @@ -135,54 +132,53 @@ bool init() { int main(int argc, char *argv[]) { - enum Mode { SCREEN, GEO }; int level = 0; int apatch = -1; - float error = 1; - Mode mode = SCREEN; + float error = 4; Trackball track; int option; - while((option = getopt(argc, argv, "l:p:g:s:")) != EOF) { - switch(option) { - case 'l': level = atoi(optarg); break; - case 'p': apatch = atoi(optarg); break; - case 'g': mode = GEO; error = (float)atof(optarg); break; - case 's': mode = SCREEN; error = (float)atof(optarg); break; - default: cerr << "Unknown option: " << (char)option << endl; - return -1; - } - } - - if(optind != argc - 1) { - cerr << "Usage: " << argv[0] << " [options]\n" - << " -l : show level n\n" - << " -p : show patch n\n" - << " -g : extract at geometry error e\n" - << " -s : extract at screen error e\n\n"; + if(argc != 2) { + cerr << "Usage: " << argv[0] << " \n"; return -1; } NexusMt nexus; - if(!nexus.Load(argv[optind])) { + if(!nexus.Load(argv[1])) { cerr << "Could not load nexus file: " << argv[1] << endl; return -1; } Sphere3f sphere = nexus.sphere; - if(!init()) { + if(!init(argv[1])) { cerr << "Could not init SDL window\n"; return -1; } // FrustumPolicy frustum_policy; + + cerr << "Commands: \n" + " q: quit\n" + " s: screen error extraction\n" + " g: geometry error extraction\n" + " p: draw points\n" + " d: debug mode (show patches colored)\n" + " m: smooth mode\n" + " c: show colors\n" + " n: show normals\n" + " r: rotate model\n" + " -: decrease error\n" + " +: increase error (= too)\n"; - bool rotate = true; + bool rotate = false; bool show_borders = true; bool show_colors = true; bool show_normals = true; + NexusMt::Mode mode = NexusMt::SMOOTH; + NexusMt::PolicyKind policy = NexusMt::FRUSTUM; + glClearColor(0, 0, 0, 0); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); @@ -190,24 +186,28 @@ int main(int argc, char *argv[]) { glEnable(GL_COLOR_MATERIAL); glEnable(GL_CULL_FACE); int quit = 0; - SDL_Event event; + SDL_Event event; int x, y; float alpha = 0; - while( !quit ) { - while( SDL_WaitEvent( &event ) ){ + bool redraw = false; + while( !quit ) { + bool first = true; + SDL_WaitEvent(&event); + while( first || SDL_PollEvent( &event ) ){ + first = false; switch( event.type ) { case SDL_QUIT: quit = 1; break; case SDL_KEYDOWN: switch(event.key.keysym.sym) { case SDLK_q: exit(0); break; - case SDLK_b: show_borders = !show_borders;break; - case SDLK_c: - show_colors = !show_colors; + case SDLK_b: show_borders = !show_borders; break; + case SDLK_c: show_colors = !show_colors; break; + case SDLK_n: show_normals = !show_normals; break; - break; - case SDLK_n: - show_normals = !show_normals; - break; + case SDLK_s: policy = NexusMt::FRUSTUM; break; + case SDLK_p: mode = NexusMt::POINTS; break; + case SDLK_d: mode = NexusMt::DEBUG; break; + case SDLK_m: mode = NexusMt::SMOOTH; break; case SDLK_r: case SDLK_SPACE: rotate = !rotate; break; @@ -219,10 +219,6 @@ int main(int argc, char *argv[]) { case SDLK_PLUS: error *= 1.1; cerr << "error: " << error << endl; break; } - //quit = 1; - //error++; - //if(error == 5) error = 0; - //render.setMaxError(error/10.0); break; case SDL_MOUSEBUTTONDOWN: x = event.button.x; @@ -233,135 +229,62 @@ int main(int argc, char *argv[]) { track.MouseWheel(-1); } else track.MouseDown(x, y, 1); - // hand.buttonDown(x, y, 1); break; case SDL_MOUSEBUTTONUP: x = event.button.x; y = height - event.button.y; track.MouseUp(x, y, 1); - // hand.buttonUp(x, y); break; case SDL_MOUSEMOTION: while(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK)); x = event.motion.x; y = height - event.motion.y; track.MouseMove(x, y); - // hand.mouseMove(x, y); break; + case SDL_VIDEOEXPOSE: default: break; } - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(40, 1, 0.1, 100); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - gluLookAt(0,0,5, 0,0,0, 0,1,0); - - - track.GetView(); - track.Apply(); - - float scale = 2/sphere.Radius(); - // glRotatef(alpha, 0, 1, 0); - // if(rotate) - // alpha++; - // if(alpha > 360) alpha = 0; - glScalef(scale, scale, scale); - Point3f center = sphere.Center(); - glTranslatef(-center[0], -center[1], -center[2]); - - nexus.SetMode(NexusMt::DEBUG); - nexus.SetPolicy(NexusMt::FRUSTUM, error); - nexus.SetComponent(NexusMt::COLOR, show_colors); - nexus.SetComponent(NexusMt::NORMAL, show_normals); - - nexus.Render(); - - /* vector cells; - if(apatch != -1) { - cells.push_back(apatch); - } else if(mode == GEO) { - nexus.ExtractFixed(cells, error); - } else if(mode == SCREEN) { - frustum_policy.error = error; - frustum_policy.GetView(); - nexus.Extract(cells, &frustum_policy); - } else { - for(int i = 0; i < nexus.index.size(); i++) { - if(nexus.index[i].error == 0) - cells.push_back(i); - } - } - - glColor3f(1, 1, 1); - - for(unsigned int i = 0; i < cells.size(); i++) { - unsigned int cell = cells[i]; - Patch patch = nexus.GetPatch(cell); - - if(show_color) { - unsigned int val = cell + 1; - glColor3ub(((val * 27)%128) + 128, - ((val * 37)%128) + 128, - ((val * 87)%128) + 128); - } - - glBegin(GL_TRIANGLES); - unsigned short *f = patch.FaceBegin(); - for(unsigned int j = 0; j < patch.nf*3; j+= 3) { - Point3f &p1 = patch.Vert(f[j]); - Point3f &p2 = patch.Vert(f[j+1]); - Point3f &p3 = patch.Vert(f[j+2]); - Point3f n = ((p2 - p1) ^ (p3 - p1)); - - if(!show_normals) { - glNormal3f(n[0], n[1], n[2]); - glVertex3f(p1[0], p1[1], p1[2]); - glVertex3f(p2[0], p2[1], p2[2]); - glVertex3f(p3[0], p3[1], p3[2]); - } else { - short *n1 = patch.Norm16(f[j]); - short *n2 = patch.Norm16(f[j+1]); - short *n3 = patch.Norm16(f[j+2]); - glNormal3s(n1[0], n1[1], n1[2]); - glVertex3f(p1[0], p1[1], p1[2]); - glNormal3s(n2[0], n2[1], n2[2]); - glVertex3f(p2[0], p2[1], p2[2]); - glNormal3s(n3[0], n3[1], n3[2]); - glVertex3f(p3[0], p3[1], p3[2]); - } - - } - glEnd(); - } - if(show_borders) { - for(unsigned int i = 0; i < cells.size(); i++) { - unsigned int cell = cells[i]; - Patch patch = nexus.GetPatch(cell); - //drawing borders - glColor3f(1, 1, 1); - - Border border = nexus.GetBorder(cell); - glPointSize(4); - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - glBegin(GL_POINTS); - for(unsigned int k = 0; k < border.Size(); k++) { - if(border[k].IsNull()) continue; - Point3f &p = patch.Vert(border[k].start_vert); - glVertex3f(p[0], p[1], p[2]); - } - glEnd(); - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - } - } -*/ - - SDL_GL_SwapBuffers(); + redraw = true; } + + if(!redraw) continue; + redraw = false; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(40, 1, 0.1, 100); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0,0,5, 0,0,0, 0,1,0); + + glRotatef(alpha, 0, 1, 0); + if(rotate) { + alpha++; + if(alpha > 360) alpha = 0; + SDL_Event redraw; + redraw.type = SDL_VIDEOEXPOSE; + SDL_PushEvent(&redraw); + } + + + track.GetView(); + track.Apply(); + + float scale = 2/sphere.Radius(); + + glScalef(scale, scale, scale); + Point3f center = sphere.Center(); + glTranslatef(-center[0], -center[1], -center[2]); + + glColor3f(0.9, 0.9, 0.9); + nexus.SetMode(mode); + nexus.SetPolicy(policy, error); + nexus.SetComponent(NexusMt::COLOR, show_colors); + nexus.SetComponent(NexusMt::NORMAL, show_normals); + + nexus.Render(); + + SDL_GL_SwapBuffers(); } // Clean up diff --git a/apps/nexus/nxsalgo.cpp b/apps/nexus/nxsalgo.cpp index 951eed67..1c00b838 100644 --- a/apps/nexus/nxsalgo.cpp +++ b/apps/nexus/nxsalgo.cpp @@ -23,10 +23,9 @@ void nxs::ComputeNormals(Nexus &nexus) { bool use_short = (nexus.signature & NXS_NORMALS_SHORT) != 0; //first step normals in the same patch. - cerr << "First step" << endl; for(unsigned int p = 0; p < nexus.index.size(); p++) { Patch patch = nexus.GetPatch(p); - + vector normals; normals.resize(patch.nv, Point3f(0, 0, 0)); @@ -43,6 +42,7 @@ void nxs::ComputeNormals(Nexus &nexus) { normals[f[1]] += norm; normals[f[2]] += norm; } + if(nexus.signature & NXS_STRIP) for(unsigned int i = 0; i < patch.nf-2; i++) { unsigned short *f = patch.FaceBegin() + i; @@ -72,16 +72,13 @@ void nxs::ComputeNormals(Nexus &nexus) { normals.size() * sizeof(Point3f)); } } - cerr << "Second step" << endl; //Second step unify normals across borders for(unsigned int p = 0; p < nexus.index.size(); p++) { //notice now ew allow flushing of old patches - cerr << "Colleting" << endl; Patch patch = nexus.GetPatch(p); Border border = nexus.GetBorder(p); - cerr << "nv: " << patch.nv << " nf: " << patch.nf << endl; //first pass we collect all normals map normals; for(unsigned int i = 0; i < border.Size(); i++) { @@ -108,7 +105,6 @@ void nxs::ComputeNormals(Nexus &nexus) { normals[link.start_vert] += remote.Norm32(link.end_vert); } - cerr << "Adding" << endl; //second pass we update values in all the patches involved for(unsigned int i = 0; i < border.Size(); i++) { Link &link = border[i]; diff --git a/apps/nexus/nxsbuild.cpp b/apps/nexus/nxsbuild.cpp new file mode 100644 index 00000000..bc5d06d8 --- /dev/null +++ b/apps/nexus/nxsbuild.cpp @@ -0,0 +1,223 @@ +#include "nxsbuild.h" +#include +#include + +using namespace nxs; +using namespace vcg; +using namespace std; + +void nxs::RemapVertices(Crude &crude, + VertRemap &vert_remap, + VFile &face_remap, + vector &patch_verts) { + + for(unsigned int i = 0; i < crude.Faces(); i++) { + Crude::Face &face = crude.GetFace(i); + unsigned int patch = face_remap[i]; + for(int k = 0; k < 3; k++) { + set pp; + vert_remap.GetValues(face[k], pp); + if(!pp.count(patch)) { + vert_remap.Insert(face[k], patch); + patch_verts[patch]++; + } + } + } +} + +void nxs::NexusAllocate(Crude &crude, + Nexus &nexus, + VFile &face_remap, + vector &patch_faces, + vector &patch_verts) { + + + nexus.index.resize(patch_faces.size()); + + unsigned int totchunks = 0; + //now that we know various sizes, lets allocate space + for(unsigned int i = 0; i < nexus.index.size(); i++) { + Nexus::Entry &entry = nexus.index[i]; + + if(patch_faces[i] == 0 || patch_verts[i] == 0) + cerr << "Warning! Empty patch.\n"; + + entry.patch_start = totchunks; + entry.patch_size = Patch::ChunkSize(nexus.signature, + patch_verts[i], patch_faces[i]); + + totchunks += entry.patch_size; + entry.border_start = 0xffffffff; + entry.nvert = patch_verts[i]; + entry.nface = 0; + entry.error = 0; + } + + nexus.patches.Resize(totchunks); + + + //now we sort the faces into the patches (but still using absolute indexing + //instead of relative indexing + for(unsigned int i = 0; i < crude.face.Size(); i++) { + Crude::Face &face = crude.face[i]; + unsigned int npatch = face_remap[i]; + + Nexus::Entry &entry = nexus.index[npatch]; + + //TODO this is slow because we have to initialize patch. + //just get patch.start. + Patch patch = nexus.GetPatch(npatch); + + Crude::Face *faces = (Crude::Face *)patch.start; + faces[entry.nface] = face; + entry.nface++; + } +} + +void nxs::NexusFill(Crude &crude, + Nexus &nexus, + VertRemap &vert_remap, + VFile &border_remap) { + + + //finally for every patch we collect the vertices + //and fill the patch. + //we need to remember start and size in border_remap; + // vector border_start; + // vector border_size; + + for(unsigned int i = 0; i < nexus.index.size(); i++) { + Patch patch = nexus.GetPatch(i); + Nexus::Entry &entry = nexus.index[i]; + + //make a copy of faces (we need to write there :P) + Crude::Face *faces = new Crude::Face[patch.nf]; + memcpy(faces, (Crude::Face *)patch.start, + patch.nf * sizeof(Crude::Face)); + + //collect all vertices we need. + //TODO an hash_map would be faster? + unsigned int count = 0; + map remap; + for(unsigned int k = 0; k < patch.nf; k++) { + Crude::Face &face = faces[k]; + + for(int j = 0; j < 3; j++) { + if(!remap.count(face[j])) { + assert(count < patch.nv); + Point3f &v = crude.vert[face[j]]; + patch.VertBegin()[remap.size()] = v; + entry.sphere.Add(v); + remap[face[j]] = count++; + } + patch.FaceBegin()[k*3 + j] = remap[face[j]]; + } + } + assert(count == remap.size()); + assert(entry.nvert == remap.size()); + + //record start of border: + entry.border_start = border_remap.Size(); + + //TODO hash_set? + set border_patches; + map::iterator m; + for(m = remap.begin(); m != remap.end(); m++) { + RemapLink link; + link.abs_vert = (*m).first; + link.rel_vert = (*m).second; + + vert_remap.GetValues(link.abs_vert, border_patches); + assert(border_patches.size() >= 1); + if(border_patches.size() == 1) continue; //its not a border + + set::iterator s; + for(s = border_patches.begin(); s != border_patches.end(); s++) { + if((*s) == i) continue; + link.patch = *s; + border_remap.PushBack(link); + } + } + //and number of borders: + entry.border_used = border_remap.Size() - entry.border_start; + delete []faces; + } + + //we can now update bounding sphere. + for(unsigned int i = 0; i < nexus.index.size(); i++) + nexus.sphere.Add(nexus.index[i].sphere); +} + +void nxs::NexusFixBorder(Nexus &nexus, + VFile &border_remap) { + + //and last convert RemapLinks into Links + nexus.borders.Resize(border_remap.Size() * 2); + //* 2 is to accomodate future borders + + for(unsigned int i = 0; i < nexus.index.size(); i++) { + Nexus::Entry &local = nexus.index[i]; + local.border_start *= 2; + local.border_size = local.border_used * 2; + } + + for(unsigned int i = 0; i < nexus.index.size(); i++) { + Nexus::Entry &local = nexus.index[i]; + + unsigned int remap_start = local.border_start/2; + //* 2 is to accomodate future borders + + + // K is the main iterator (where we write to in nexus.borders) + for(unsigned int k = 0; k < local.border_used; k++) { + + + RemapLink start_link = border_remap[k + remap_start]; + assert(start_link.rel_vert < local.nvert); + + Nexus::Entry &remote = nexus.index[start_link.patch]; + + bool found = false; + + unsigned int remote_remap_start = remote.border_start/2; + for(unsigned int j = 0; j < remote.border_used; j++) { + + RemapLink end_link = border_remap[j + remote_remap_start]; + assert(end_link.rel_vert < remote.nvert); + + if(start_link.abs_vert == end_link.abs_vert && + end_link.patch == i) { //found the match + assert(!found); + nexus.borders[k + local.border_start] = Link(start_link.rel_vert, + end_link.rel_vert, + start_link.patch); + found = true; + } + } + assert(nexus.borders[k + local.border_start].start_vert < local.nvert); + assert(found); + } + } + nexus.borders.Flush(); + + //Checking border consistency: + /* for(unsigned int i = 0; i < nexus.index.size(); i++) { + Border border = nexus.GetBorder(i); + Nexus::Entry &entry = nexus.index[i]; + for(unsigned int k = 0; k < border.Size(); k++) { + Link &link = border[k]; + if(link.start_vert >= entry.nvert) { + cerr << "K: " << k << endl; + cerr << "patch: " << i << " nvert: " << entry.nvert << " startv: " + << link.start_vert << endl; + cerr << "bstart: " << entry.border_start + << "bsize: " << entry.border_size << endl; + } + assert(link.end_patch < nexus.index.size()); + assert(link.start_vert < entry.nvert); + Nexus::Entry &remote = nexus.index[link.end_patch]; + assert(link.end_vert < remote.nvert); + } + + }*/ +} diff --git a/apps/nexus/nxsbuild.h b/apps/nexus/nxsbuild.h new file mode 100644 index 00000000..776806f5 --- /dev/null +++ b/apps/nexus/nxsbuild.h @@ -0,0 +1,39 @@ +#ifndef NXS_BUILD_H +#define NXS_BUILD_H + +#include "vert_remap.h" +#include "crude.h" +#include "nexus.h" + +#include + +namespace nxs { + +struct RemapLink { + unsigned int rel_vert; + unsigned int patch; + unsigned int abs_vert; +}; + +void RemapVertices(Crude &crude, + VertRemap &vert_remap, + VFile &face_remap, + std::vector &patch_verts); + +void NexusAllocate(Crude &crude, + nxs::Nexus &nexus, + VFile &face_remap, + std::vector &patch_faces, + std::vector &patch_verts); + +void NexusFill(Crude &crude, + Nexus &nexus, + VertRemap &vert_remap, + VFile &border_remap); + +void NexusFixBorder(Nexus &nexus, + VFile &border_remap); + +} + +#endif diff --git a/apps/nexus/nxsedit.cpp b/apps/nexus/nxsedit.cpp index 6261169b..e2812906 100644 --- a/apps/nexus/nxsedit.cpp +++ b/apps/nexus/nxsedit.cpp @@ -13,6 +13,17 @@ using namespace vcg; #include #endif +string getSuffix(unsigned int signature) { + string suff; + if(signature&NXS_COMPRESSED) suff += "Z"; + if(signature&NXS_STRIP) suff += "S"; + if(signature&NXS_COLORS) suff += "C"; + if(signature&NXS_NORMALS_SHORT) suff += "N"; + if(signature&NXS_TEXTURES_SHORT) suff += "T"; + if(signature&NXS_DATA32) suff += "D"; + return suff; +} + int main(int argc, char *argv[]) { string input; @@ -160,9 +171,10 @@ int main(int argc, char *argv[]) { << " -n: Normal quantization\n" << " -c: Color quantization\n" << " -t: Texture quantization\n\n"; + return -1; } input = argv[optind]; - if(!output.size()) output = input + "00"; + Nexus nexus; if(!nexus.Load(input)) { @@ -228,6 +240,8 @@ int main(int argc, char *argv[]) { signature |= add; signature &= ~remove; + if(!output.size()) output = input + getSuffix(signature); + Nexus out; if(!out.Create(output, (Signature)signature)) { cerr << "Could not open output: " << output << endl; @@ -243,6 +257,7 @@ int main(int argc, char *argv[]) { vector strip; if(add_strip) { ComputeTriStrip(src_patch.nf, src_patch.FaceBegin(), strip); + assert(strip.size() < 32767); out.AddPatch(src_entry.nvert, strip.size(), src_entry.border_size); } else out.AddPatch(src_entry.nvert, src_entry.nface, src_entry.border_size); diff --git a/apps/nexus/patch.cpp b/apps/nexus/patch.cpp index bd9ad177..b822ef80 100644 --- a/apps/nexus/patch.cpp +++ b/apps/nexus/patch.cpp @@ -2,6 +2,9 @@ using namespace nxs; +void pad(unsigned int &size) { + while(size&0x3) size++; +} Patch::Patch(Signature signature, Chunk *s, unsigned short nvert, unsigned short nface): @@ -24,7 +27,27 @@ void Patch::Init(Signature signature, //align memory if(((int)vstart) & 0x2) vstart = (float *)(((char *)vstart) + 2); - cstart = nv * sizeof(float) * 3; + cstart = nv * 3; + if(signature & NXS_COLORS) + nstart = cstart + nv; + else + nstart = cstart; + + if(signature & NXS_NORMALS_SHORT) + tstart = nstart + nv * 2; + else if(signature & NXS_NORMALS_FLOAT) + tstart = nstart + nv * 3; + else + tstart = nstart; + + if(signature & NXS_TEXTURES_SHORT) + dstart = tstart + nv; + else if(signature & NXS_TEXTURES_FLOAT) + dstart = tstart + nv; + else + dstart = tstart; + + /* cstart = nv * sizeof(float) * 3; if(signature & NXS_COLORS) nstart = cstart + nv * sizeof(unsigned int); else @@ -42,7 +65,8 @@ void Patch::Init(Signature signature, else if(signature & NXS_TEXTURES_FLOAT) dstart = tstart + nv * sizeof(float) * 2; else - dstart = tstart; + dstart = tstart;*/ + } unsigned int Patch::ChunkSize(Signature signature, @@ -63,7 +87,7 @@ unsigned int Patch::ByteSize(Signature signature, size += nface * 3 * sizeof(unsigned short); //memory alignment - if(size & 0x2) size += 2; + pad(size); size += nvert * sizeof(vcg::Point3f); @@ -84,8 +108,10 @@ unsigned int Patch::ByteSize(Signature signature, if(signature & NXS_DATA8) size += nvert * sizeof(char); + pad(size); if(signature & NXS_DATA16) size += nvert * 2 * sizeof(char); + pad(size); if(signature & NXS_DATA32) size += nvert * 4 * sizeof(char); if(signature & NXS_DATA64) diff --git a/apps/nexus/patch.h b/apps/nexus/patch.h index 57cec6dd..7c82f5c4 100644 --- a/apps/nexus/patch.h +++ b/apps/nexus/patch.h @@ -80,11 +80,11 @@ inline unsigned short *Patch::Face(unsigned short f) { } inline unsigned int *Patch::ColorBegin() { - return (unsigned int *)(((char *)vstart) + cstart); + return (unsigned int *)(vstart + cstart); } inline short *Patch::Norm16Begin() { - return (short *)(((char *)vstart) + nstart); + return (short *)(vstart + nstart); } inline short *Patch::Norm16(unsigned short v) { @@ -92,7 +92,7 @@ inline short *Patch::Norm16(unsigned short v) { } inline vcg::Point3f *Patch::Norm32Begin() { - return (vcg::Point3f *)(((char *)vstart) + nstart); + return (vcg::Point3f *)(vstart + nstart); } inline vcg::Point3f &Patch::Norm32(unsigned short v) { return Norm32Begin()[v]; diff --git a/apps/nexus/voronoichain.cpp b/apps/nexus/voronoichain.cpp index 5ee4170b..8844f6d2 100644 --- a/apps/nexus/voronoichain.cpp +++ b/apps/nexus/voronoichain.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.6 2004/09/30 00:27:42 ponchio +Lot of changes. Backup. + Revision 1.5 2004/09/28 10:26:07 ponchio Voronoi partition changes. @@ -121,6 +124,7 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { seeds.push_back(fine[i]); } swap(fine, seeds); + if(fine.size() == 0) fine.push_back(Point3f(0,0,0)); fine.Init(); //here goes some optimization pass. @@ -158,6 +162,7 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { seeds.push_back(coarse[i]); } swap(coarse, seeds); + if(coarse.size() == 0) coarse.push_back(Point3f(0,0,0)); coarse.Init(); @@ -395,6 +400,7 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset, seeds.push_back(coarse[i]); } swap(coarse, seeds); + if(coarse.size() == 0) coarse.push_back(Point3f(0,0,0)); coarse.Init(); //Coarse optimization diff --git a/apps/nexus/voronoinxs.cpp b/apps/nexus/voronoinxs.cpp index 95b42045..3aa01263 100644 --- a/apps/nexus/voronoinxs.cpp +++ b/apps/nexus/voronoinxs.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.5 2004/09/30 00:27:42 ponchio +Lot of changes. Backup. + Revision 1.4 2004/09/21 00:53:23 ponchio Lotsa changes. @@ -54,21 +57,13 @@ using namespace std; #include "voronoichain.h" #include "pintersect.h" #include "vert_remap.h" + +#include "decimate.h" +#include "nxsbuild.h" using namespace vcg; using namespace nxs; -struct RemapLink { - unsigned int rel_vert; - unsigned int patch; - unsigned int abs_vert; -}; - -/*void RemapFaces(Crude &crude, - VoronoiChain &vchain, - VFile &face_remap, - vector &patch_faces);*/ - -void RemapVertices(Crude &crude, +/*void RemapVertices(Crude &crude, VertRemap &vert_remap, VFile &face_remap, vector &patch_verts); @@ -85,7 +80,7 @@ void NexusFill(Crude &crude, VFile &border_remap); void NexusFixBorder(Nexus &nexus, - VFile &border_remap); +VFile &border_remap);*/ void NexusSplit(Nexus &nexus, VoronoiChain &vchain, unsigned int level, @@ -95,19 +90,19 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain, Nexus::Update &update, float error); -float Decimate(unsigned int target_faces, +/*float Decimate(unsigned int target_faces, vector &newvert, vector &newface, vector &newbord, - vector &vert_remap); + vector &vert_remap);*/ void ReverseHistory(vector &history); -enum Decimation { QUADRIC, CLUSTER }; + int main(int argc, char *argv[]) { - Decimation decimation = QUADRIC; + Decimation decimation = CLUSTER; unsigned int patch_size = 1000; unsigned int patch_threshold = 0xffffffff; unsigned int optimization_steps = 5; @@ -286,7 +281,8 @@ int main(int argc, char *argv[]) { //simplyfy mesh vector vert_remap; - float error = Decimate((unsigned int)(newface.size() * scaling/3), + float error = Decimate(decimation, + (unsigned int)((newface.size()/3) * scaling), newvert, newface, newbord, vert_remap); @@ -338,7 +334,7 @@ int main(int argc, char *argv[]) { return 0; } -void RemapVertices(Crude &crude, +/*void RemapVertices(Crude &crude, VertRemap &vert_remap, VFile &face_remap, vector &patch_verts) { @@ -355,9 +351,9 @@ void RemapVertices(Crude &crude, } } } -} + }*/ -void NexusAllocate(Crude &crude, +/*void NexusAllocate(Crude &crude, Nexus &nexus, VFile &face_remap, vector &patch_faces, @@ -404,10 +400,10 @@ void NexusAllocate(Crude &crude, faces[entry.nface] = face; entry.nface++; } -} + }*/ -void NexusFill(Crude &crude, +/*void NexusFill(Crude &crude, Nexus &nexus, VertRemap &vert_remap, VFile &border_remap) { @@ -479,9 +475,9 @@ void NexusFill(Crude &crude, //we can now update bounding sphere. for(unsigned int i = 0; i < nexus.index.size(); i++) nexus.sphere.Add(nexus.index[i].sphere); -} + }*/ -void NexusFixBorder(Nexus &nexus, +/*void NexusFixBorder(Nexus &nexus, VFile &border_remap) { //and last convert RemapLinks into Links @@ -532,28 +528,7 @@ void NexusFixBorder(Nexus &nexus, } } nexus.borders.Flush(); - - //Checking border consistency: - /* for(unsigned int i = 0; i < nexus.index.size(); i++) { - Border border = nexus.GetBorder(i); - Nexus::Entry &entry = nexus.index[i]; - for(unsigned int k = 0; k < border.Size(); k++) { - Link &link = border[k]; - if(link.start_vert >= entry.nvert) { - cerr << "K: " << k << endl; - cerr << "patch: " << i << " nvert: " << entry.nvert << " startv: " - << link.start_vert << endl; - cerr << "bstart: " << entry.border_start - << "bsize: " << entry.border_size << endl; - } - assert(link.end_patch < nexus.index.size()); - assert(link.start_vert < entry.nvert); - Nexus::Entry &remote = nexus.index[link.end_patch]; - assert(link.end_vert < remote.nvert); - } - - }*/ -} +} */ void NexusSplit(Nexus &nexus, VoronoiChain &vchain,