diff --git a/apps/nexus/extraction.cpp b/apps/nexus/extraction.cpp index 25897a23..15dedd96 100644 --- a/apps/nexus/extraction.cpp +++ b/apps/nexus/extraction.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.9 2005/02/20 00:43:23 ponchio +Less memory x extraction. (removed frags) + Revision 1.8 2005/02/19 16:22:45 ponchio Minor changes (visited and Cell) @@ -64,7 +67,9 @@ void Extraction::Extract(NexusMt *_mt) { //first we clear the visited flags visited.clear(); - visited.resize(mt->history.n_nodes(), 0); + visited.resize(mt->history.n_nodes(), false); + visible.clear(); + visible.resize(mt->size(), true); heap.clear(); @@ -96,34 +101,28 @@ void Extraction::Init() { Node *nodes = mt->history.nodes; for(unsigned int i = 0; i < visited.size(); i++) { if(!visited[i]) continue; - // if(!visited[i]) continue; Node &node = nodes[i]; bool cancoarse = true; + Node::iterator n; for(n = node.out_begin(); n != node.out_end(); n++) { if(!Visited((*n).node)) { - // if(!visited[(*n).node - root]) { float maxerror = -1; Link &link = *n; for(Link::iterator k = link.begin(); k != link.end(); k++) { - // unsigned int patch = *k; unsigned int patch = k; Entry &entry = (*mt)[patch]; bool visible; float error = metric->GetError(entry, visible); - if(error > maxerror) maxerror = error; cost.extr += entry.ram_size; - //TODO if(frustum) else - //if(visible) - // cost.draw += entry.ram_size; - vcg::Sphere3f &sphere = entry.sphere; - if(!frustum.IsOutside(sphere.Center(), sphere.Radius())) + SetVisible(patch, visible); + if(visible) cost.draw += entry.ram_size; if(!entry.patch) @@ -135,7 +134,7 @@ void Extraction::Init() { } else cancoarse = false; } - if(cancoarse && &node != root) { + if(cancoarse && (&node != root)) { float error = GetRefineError(&node); back.push_back(HeapNode(&node, error)); } @@ -157,31 +156,48 @@ void Extraction::Update(NexusMt *_mt) { if(!visited.size()) { visited.resize(mt->history.n_nodes(), false); SetVisited(root, true); - } + } + visible.clear(); + visible.resize(mt->size(), true); Init(); bool no_draw = false; - bool no_disk = false; //TODO big problem: nodes a (error 10) with parent b (error -1) //i try to refine a, refine b (recursive) but fail to refine a //next step i coarse b whis cause a cycle. + /* Updateing strategy: + if i can refine (not at leaves, have draw and extr buffer, not past target_error) + i try to refine BUT + i can fail because i finish some buffer (exp. while recursively refine) + (then i put the operation back on the stack) + if i have finished disk i should just quit + if i cannot refine i consider coarsening: + i need 1) not be at root (eheh) + 2) have finished draw and extr buffer + 3) do not make global error worse (unless it is < target_error...) + 4) check it is not a recursive coarsening (drop it otherwise) + i try to coarse BUT + i can fail because i need disk + (then i put the operation back on the stack) + if i cannot coarse i just quit + */ + while(1) { if(!no_draw && //we have buffer front.size() && //we are not at max level - front[0].error > target_error) { //we are not already target_error + front[0].error > target_error) { //we are not already at target_error max_error = front[0].error; pop_heap(front.begin(), front.end()); HeapNode hnode = front.back(); front.pop_back(); - if(!Visited(hnode.node)) { - if(!Refine(hnode)) { + + if(!Visited(hnode.node) && !Refine(hnode)) no_draw = true; - } - } + continue; } @@ -191,6 +207,7 @@ void Extraction::Update(NexusMt *_mt) { } if(no_draw) { //suppose i have no more buffer + //TODO see point 3 //if i do error damages coarsening better get out if(front.size() && ((back.front().error + 0.001) >= front.front().error)) { //cerr << "Balanced cut\n"; @@ -219,10 +236,10 @@ void Extraction::Update(NexusMt *_mt) { Node *child = (*i).node; if(Visited(child)) recursive = true; } - if(!recursive && !Coarse(hnode)) { //no more disk so.. push back on heap the heapnode - back.push_back(hnode); - push_heap(back.begin(), back.end(), greater()); - break; + if(!recursive && !Coarse(hnode)) { //no more disk so. push back on heap the heapnode + back.push_back(hnode); + push_heap(back.begin(), back.end(), greater()); + break; } } @@ -244,8 +261,6 @@ void Extraction::Update(NexusMt *_mt) { for(l = node->out_begin(); l != node->out_end(); l++) { Link &link = (*l); for(Link::iterator k = link.begin(); k != link.end(); k++) { - // selected.push_back(Item(*k, i)); - // errors[*k] = i; selected.push_back(Item(k, i)); errors[k] = i; } @@ -259,8 +274,6 @@ void Extraction::Update(NexusMt *_mt) { for(l = node->in_begin(); l != node->in_end(); l++) { Link &link = (*l); for(Link::iterator k = link.begin(); k != link.end(); k++) { - // selected.push_back(Item(*k, i)); - // errors[*k] = i; selected.push_back(Item(k, i)); errors[k] = i; } @@ -279,6 +292,7 @@ float Extraction::GetRefineError(Node *node) { bool visible; float error = metric->GetError(entry, visible); if(error > maxerror) maxerror = error; + SetVisible(p, visible); } } return maxerror; @@ -399,11 +413,6 @@ void Extraction::Select() { unsigned int n_out = (*n).node - root; if(!visited[n_out]) { Link &link = *n; - /* for(Link::iterator k = link.begin(); k != link.end(); k++) { - unsigned int patch = *k; - selected.push_back(Item(patch,0)); - errors[patch] = 0.0f; - }*/ for(Link::iterator p= link.begin(); p != link.end(); p++) { selected.push_back(Item(p, 0)); errors[p] = 0.0f; @@ -438,6 +447,7 @@ void Extraction::Visit(Node *node) { bool visible; float error = metric->GetError(entry, visible); if(error > maxerror) maxerror = error; + SetVisible(p, visible); } //TODO this check may be dangerous for non saturating things... if(maxerror > target_error) { @@ -462,9 +472,8 @@ void Extraction::Diff(Node *node, Cost &cost) { for(Link::iterator p = link.begin(); p != link.end(); p++) { Entry &entry = (*mt)[p]; cost.extr -= entry.ram_size; - vcg::Sphere3f &sphere = entry.sphere; - if(!frustum.IsOutside(sphere.Center(), sphere.Radius())) - cost.draw -= entry.ram_size; + if(Visible(p)) cost.draw -= entry.ram_size; + if(!entry.patch) cost.disk -= entry.disk_size; } @@ -475,9 +484,8 @@ void Extraction::Diff(Node *node, Cost &cost) { for(Link::iterator p = link.begin(); p != link.end(); p++) { Entry &entry = (*mt)[p]; cost.extr += entry.ram_size; - vcg::Sphere3f &sphere = entry.sphere; - if(!frustum.IsOutside(sphere.Center(), sphere.Radius())) - cost.draw += entry.ram_size; + if(Visible(p)) cost.draw += entry.ram_size; + if(!entry.patch) cost.disk += entry.disk_size; } diff --git a/apps/nexus/extraction.h b/apps/nexus/extraction.h index addec984..e0af7208 100644 --- a/apps/nexus/extraction.h +++ b/apps/nexus/extraction.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.8 2005/02/19 16:22:45 ponchio +Minor changes (visited and Cell) + Revision 1.7 2005/02/10 09:18:20 ponchio Statistics. @@ -81,12 +84,9 @@ class Extraction { }; Metric *metric; - - //TODO make a pointer so no need to doubl check visibility...! - vcg::Frustumf frustum; - float target_error; - float max_error; + + float max_error; //actual error at end of extraction unsigned int extr_used, extr_max; unsigned int draw_used, draw_max; unsigned int disk_used, disk_max; @@ -98,7 +98,7 @@ class Extraction { std::vector selected; unsigned int draw_size; //first in selected should be drawn - std::vector heap; //no realtime extraxtion + std::vector heap; //no realtime extraxtion TODO (use front) //nodes that i can expand to std::vector front; @@ -114,6 +114,8 @@ class Extraction { void Update(NexusMt *mt); + bool Visible(unsigned int p) { return visible[p]; } + void SetVisible(unsigned int p, bool v) { visible[p] = v; } protected: void Select(); @@ -126,16 +128,15 @@ class Extraction { bool Coarse(HeapNode node); void Init(); + + bool Visited(Node *node) { return visited[node - root]; } + void SetVisited(Node *node, bool v) { visited[node - root] = v; } + private: NexusMt *mt; Node *root; Node *sink; - bool Visited(Node *node) { return visited[node - root]; } - void SetVisited(Node *node, bool v) { visited[node - root] = v; } - bool Visible(Node *node) { return visible[node - root]; } - void SetVisible(Node *node, bool v) { visible[node - root] = v; } - float GetRefineError(Node *node); }; diff --git a/apps/nexus/metric.h b/apps/nexus/metric.h index 44bfb380..3c777445 100644 --- a/apps/nexus/metric.h +++ b/apps/nexus/metric.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.5 2005/02/19 16:22:45 ponchio +Minor changes (visited and Cell) + Revision 1.4 2005/02/08 12:43:03 ponchio Added copyright @@ -43,22 +46,25 @@ namespace nxs { class Metric { public: - virtual void GetView() {} + vcg::Frustumf frustum; + bool culling; + + Metric(): culling(true) {} + virtual void GetView() { frustum.GetView(); } virtual float GetError(Entry &entry, bool &visible) = 0; + }; class FlatMetric: public Metric { public: float GetError(Entry &entry, bool &visible) { visible = true; - return entry.error; } + return entry.error; + } }; class FrustumMetric: public Metric { public: - vcg::Frustumf frustum; - - virtual void GetView() { frustum.GetView(); } float GetError(Entry &entry, bool &visible) { visible = true; vcg::Sphere3f &sph = entry.sphere; @@ -66,12 +72,16 @@ namespace nxs { if(dist < 0) return 1e20f; - float remote = frustum.Remoteness(sph.Center(), sph.Radius()); float error = entry.error/frustum.Resolution(dist); - if(remote > 0) { - visible = false; - error /= remote; - } + if(culling) { + float remote = frustum.Remoteness(sph.Center(), sph.Radius()); + if(remote > 0) { + visible = false; + error /= remote; + } else if(entry.cone.Backface(sph, frustum.ViewPoint())) { + visible = false; + } + } return error; } }; diff --git a/apps/nexus/nexusmt.cpp b/apps/nexus/nexusmt.cpp index 6b0ef1ee..54716cfb 100644 --- a/apps/nexus/nexusmt.cpp +++ b/apps/nexus/nexusmt.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.33 2005/02/20 00:43:23 ponchio +Less memory x extraction. (removed frags) + Revision 1.32 2005/02/19 12:06:53 ponchio Debug... @@ -129,7 +132,6 @@ bool NexusMt::InitGL(bool vbo) { void NexusMt::Render(DrawContest contest) { Extraction extraction; - extraction.frustum.GetView(); extraction.metric->GetView(); extraction.Extract(this); Render(extraction, contest); @@ -162,11 +164,9 @@ void NexusMt::Render(Extraction &extraction, DrawContest &contest, for(unsigned int i = 0; i < extraction.draw_size; i++) { unsigned int patch = extraction.selected[i].id; Entry &entry = operator[](patch); - vcg::Sphere3f &sphere = entry.sphere; - if(stats) stats->extr += 2*entry.nvert; - if(extraction.frustum.IsOutside(sphere.Center(), sphere.Radius())) + if(!extraction.Visible(patch)) continue; if(stats) stats->tri += 2*entry.nvert; diff --git a/apps/nexus/nexusview.cpp b/apps/nexus/nexusview.cpp index f48c6fa9..6c0e6991 100644 --- a/apps/nexus/nexusview.cpp +++ b/apps/nexus/nexusview.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.42 2005/02/20 00:43:24 ponchio +Less memory x extraction. (removed frags) + Revision 1.41 2005/02/19 12:06:55 ponchio Debug... @@ -314,9 +317,6 @@ int main(int argc, char *argv[]) { return -1; } - - // FrustumPolicy frustum_policy; - cerr << "Commands: \n" " q : quit\n" " t : toggle statistics\n" @@ -408,7 +408,6 @@ int main(int argc, char *argv[]) { case SDLK_0: extraction.extr_max *= 1.3; break; case SDLK_9: extraction.extr_max *= 0.8; break; - // case SDLK_s: metric = NexusMt::FRUSTUM; break; case SDLK_p: contest.mode = DrawContest::POINTS; break; case SDLK_d: contest.mode = DrawContest::PATCHES; break; case SDLK_f: contest.mode = DrawContest::FLAT; break; @@ -517,7 +516,8 @@ int main(int argc, char *argv[]) { glColor3f(0.8f, 0.8f, 0.8f); if(extract) { - extraction.frustum.GetView(); + // Sould we want a different view from metric and extraction + // extraction.frustum->GetView(); extraction.metric->GetView(); if(!realtime) { extraction.Extract(&nexus); diff --git a/apps/nexus/nxsalgo.cpp b/apps/nexus/nxsalgo.cpp index 894679b6..97f82d79 100644 --- a/apps/nexus/nxsalgo.cpp +++ b/apps/nexus/nxsalgo.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.20 2005/02/19 10:45:04 ponchio +Patch generalized and small fixes. + Revision 1.19 2005/02/18 13:04:12 ponchio Added patch reordering. @@ -57,6 +60,57 @@ using namespace vcg; #include "tristripper/tri_stripper.h" using namespace triangle_stripper; + +void nxs::TightSphere(vcg::Sphere3f &sphere, + std::vector &points) { + //test: + //assumes radius is ok.... and try to optimize moving center. + //TODO using a gradiend descent? really a mess. + Point3f center; + float radius; + Point3f pert[14]; + while(1) { + radius = sphere.Radius(); + float step = radius/40; + pert[0] = Point3f(step, 0, 0); + pert[1] = -pert[0]; + pert[2] = Point3f(0, step, 0); + pert[3] = -pert[2]; + pert[4] = Point3f(0, 0, step); + pert[5] = -pert[4]; + pert[6] = Point3f(step, step, step); + pert[7] = Point3f(step, step, -step); + pert[8] = Point3f(step, -step, step); + pert[9] = Point3f(step, -step, -step); + pert[10] = Point3f(-step, step, step); + pert[11] = Point3f(-step, step, -step); + pert[12] = Point3f(-step, -step, step); + pert[13] = Point3f(-step, -step, -step); + + unsigned int best = 14; + float best_radius = sphere.Radius(); + + for(unsigned int k = 0; k < 14; k++) { + center = sphere.Center() + pert[k]; + radius = 0; + for(unsigned int i = 0; i < points.size(); i++) { + float r = 1.01 * Distance(center, points[i]); + if(r > radius) + radius = r; + } + if(radius < best_radius) { + best = k; + best_radius = radius; + } + } + if(best == 14) break; + sphere.Center() = sphere.Center() + pert[best]; + sphere.Radius() = best_radius; + } +} + + + void nxs::ComputeNormals(Nexus &nexus) { assert(nexus.signature.vnorm); @@ -74,9 +128,8 @@ void nxs::ComputeNormals(Nexus &nexus) { exit(0); } - //TODO optimize! it is not necessary to read all the borders. for(unsigned int p = 0; p < nexus.size(); p++) { - Border &border = nexus.GetBorder(p); + Border &border = nexus.borders[p]; tmpb_start.push_back(tmpb_offset); tmpb_offset += border.Size(); } @@ -131,6 +184,10 @@ void nxs::ComputeNormals(Nexus &nexus) { normals[f[2]] += norm; } + //compute normalscone (done in building... + // ANCone3f cone; + // cone.AddNormals(normals, cone_threshold); + // nexus[p].cone.Import(cone); if(nexus.signature.vnorm == Encodings::SHORT4) { short *n = (short *)patch.VNormBegin(); for(unsigned int i = 0; i < patch.nv; i++, n += 4) { diff --git a/apps/nexus/nxsalgo.h b/apps/nexus/nxsalgo.h index 7a746032..8e7a501b 100644 --- a/apps/nexus/nxsalgo.h +++ b/apps/nexus/nxsalgo.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.6 2005/02/19 10:45:04 ponchio +Patch generalized and small fixes. + Revision 1.5 2005/02/18 13:04:13 ponchio Added patch reordering. @@ -38,12 +41,14 @@ Added copyright #include #include "patch.h" +#include namespace nxs { class Nexus; class Patch; + struct ZEntry { unsigned int id; unsigned int pos; @@ -57,6 +62,7 @@ namespace nxs { void Unify(Nexus &nexus, float threshold); void ZSort(Nexus &nexus, std::vector &forward, std::vector &backward); + void TightSphere(vcg::Sphere3f &sphere, std::vector &points); } #endif diff --git a/apps/nexus/nxsbuilder.cpp b/apps/nexus/nxsbuilder.cpp index 29aca586..75d9fa94 100644 --- a/apps/nexus/nxsbuilder.cpp +++ b/apps/nexus/nxsbuilder.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.18 2005/02/20 00:43:24 ponchio +Less memory x extraction. (removed frags) + Revision 1.17 2005/02/19 17:14:02 ponchio History quick by default. @@ -338,7 +341,8 @@ void ThirdStep(const string &crudefile, const string &output, assert(vcount == vertices.size()); assert(fcount == faces.size()); - //TODO deal with this case adding another patch at the end... its not that difficult! + //TODO deal with this case adding another patch at the end... + //its not that difficult! //This can happen on degenerate cases when we have a lot of detached faces.... if(vcount > 65000 && fcount > 65000) { @@ -359,6 +363,23 @@ void ThirdStep(const string &crudefile, const string &output, sphere.Add(vertices[i]); sphere.Radius() *= 1.01; + TightSphere(sphere, vertices); + + vector normals; + for(unsigned int i = 0; i < patch.nf; i++) { + unsigned short *f = patch.Face(i); + Point3f &v0 = patch.Vert3f(f[0]); + Point3f &v1 = patch.Vert3f(f[1]); + Point3f &v2 = patch.Vert3f(f[2]); + + Point3f norm = (v1 - v0) ^ (v2 - v0); + normals.push_back(norm.Normalize()); + } + ANCone3f cone; + cone.AddNormals(normals, 0.99f); + nexus[patch_idx].cone.Import(cone); + + #ifndef NDEBUG for(int i = 0; i < vertices.size(); i++) { assert(sphere.IsIn(vertices[i])); @@ -836,6 +857,7 @@ void SaveFragment(Nexus &nexus, VChain &chain, nexus.sphere.Add(outpatch.vert[v]); } entry.sphere.Radius() *= 1.01; + TightSphere(entry.sphere, outpatch.vert); //remap internal borders for(unsigned int k = 0; k < outpatch.bord.size(); k++) { diff --git a/apps/nexus/nxsedit.cpp b/apps/nexus/nxsedit.cpp index 183ef29e..2a8a1cd9 100644 --- a/apps/nexus/nxsedit.cpp +++ b/apps/nexus/nxsedit.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.22 2005/02/20 00:43:24 ponchio +Less memory x extraction. (removed frags) + Revision 1.21 2005/02/19 17:14:02 ponchio History quick by default. @@ -86,21 +89,25 @@ string getSuffix(Signature &signature) { return suff; } +void printInfo(Nexus &nexus, bool verbose, bool dump_history); + int main(int argc, char *argv[]) { string input; string output; string plysource; + bool info = false; bool verbose = false; bool dump_history = false; + unsigned int ram_size = 128000000; unsigned int chunk_size = 0; bool add = false; bool add_strips = false; bool add_colors = false; - bool add_normals = false; + unsigned char add_normals = 0; bool add_textures = false; bool add_data = false; @@ -113,45 +120,32 @@ int main(int argc, char *argv[]) { bool compress = false; bool uncompress = false; + bool zsort = false; + float qvertex = 0; float qnormal = 0; float qcolor = 0; float qtexture = 0; - bool zsort = false; + float cone_threshold = 0; int option; - while((option = getopt(argc, argv, "ilho:a:r:zxsv:n:k:t:b:c:")) != EOF) { + while((option = getopt(argc, argv, "ilho:a:r:zxsv:n:k:t:b:c:V:")) != EOF) { switch(option) { case 'i': info = true; break; case 'l': verbose = true; break; case 'h': dump_history = true; break; case 'o': output = optarg; break; + case 'p': plysource = optarg; break; + case 'a': { - if(strstr(optarg, "strips")) { - add_strips = true; - add = true; - // add |= NXS_STRIP; - // remove |= NXS_FACES; - } - if(strstr(optarg, "colors")) { - add_colors = true; - add = true; - // add |= NXS_COLORS; - } - if(strstr(optarg, "normals")) { - add_normals = true; - add = true; - // add |= NXS_NORMALS_SHORT; - } - if(strstr(optarg, "textures")) { - add_textures = true; - add = true; - // add |= NXS_TEXTURES_SHORT; - } - if(strstr(optarg, "data")) { - add_data = true; - // add |= NXS_DATA32; - } + if(strstr(optarg, "strips")) { add_strips = true; add = true; } + if(strstr(optarg, "colors")) { add_colors = true; add = true; } + if(strstr(optarg, "normals")) { + add_normals = Encodings::SHORT4; add = true; } + if(strstr(optarg, "normalf")) { + add_normals = Encodings::FLOAT3; add = true; } + if(strstr(optarg, "textures")) { add_textures = true; add = true; } + if(strstr(optarg, "data")) { add_data = true; add = true; } if(add == false) { cerr << "Invalid -a argument: " << optarg << "\n" << "Valid options are: strips, colors, normals, textures, data\n"; @@ -159,50 +153,31 @@ int main(int argc, char *argv[]) { } break; } - case 'r': { if(strstr(optarg, "strips")) { cerr << "Strips removing not supported!\n"; return -1; - remove_strips = true; - remove = true; - add = true; - // add |= NXS_FACES; - // remove |= NXS_STRIP; - } - if(strstr(optarg, "colors")) { - remove_colors = true; - remove = true; - // remove |= NXS_COLORS; - } - if(strstr(optarg, "normals")) { - remove_normals = true; - remove = true; - // remove |= NXS_NORMALS_SHORT; - } - if(strstr(optarg, "textures")) { - remove_textures = true; - remove = true; - // remove |= NXS_TEXTURES_SHORT; - } - if(strstr(optarg, "data")) { - remove_data = true; - remove = true; - // remove |= NXS_DATA32; } + if(strstr(optarg, "colors")) { remove_colors = true; remove = true; } + if(strstr(optarg, "normals")) { remove_normals = true; remove = true; } + if(strstr(optarg, "textures")) { remove_textures = true; remove = true; } + if(strstr(optarg, "data")) { remove_data = true; remove = true; } if(remove == false) { cerr << "Invalid -a argument: " << optarg << "\n" - << "Valid options are: strip, colors, normals, textures, data\n"; + << "Valid options are: strip, colors, normals, normalf, " + << "textures, data\n"; return -1; } break; } - case 'p': plysource = optarg; break; + + case 'z': compress = true; break; case 'x': uncompress = true; break; case 's': zsort = true; break; + case 'V': cone_threshold = atof(optarg); break; case 'v': qvertex = (float)atof(optarg); if(qvertex == 0) { cerr << "Invalid value for quantization: " << optarg << endl; @@ -227,6 +202,7 @@ int main(int argc, char *argv[]) { return -1; } break; + case 'b': ram_size = atoi(optarg); if(ram_size == 0) { cerr << "Invalid ram_size: " << optarg << endl; @@ -244,18 +220,13 @@ int main(int argc, char *argv[]) { } } - if(compress && uncompress) { - cerr << "x and z are obviously exclusive :P\n"; - return -1; - } - if(optind != argc - 1) { cerr << "Usage: " << argv[0] << " [options]\n" << " -i : display some info about nexus file\n" << " -l : list nodes\n" << " -h : list history\n" << " -o : output filename (default is adding 00 to nexus)\n" - << " -a : Add [colors|normals|strips|textures|data|borders]\n" + << " -a : Add [colors|normals|normalf|strips|textures|data|borders]\n" << " -r : As add...\n" << " -p : Ply source for colors or textures or data\n" << " -z : compress\n" @@ -264,12 +235,34 @@ int main(int argc, char *argv[]) { << " -v: Vertex quantization (float is the 0 level amount)\n" << " -n: Normal quantization\n" << " -c: Color quantization\n" - << " -t: Texture quantization\n\n"; + << " -t: Texture quantization\n" + << " -V: Normal cone threshold [0, 1] (0.95 default)\n\n" + << " This option will not create a new nexus file\n"; return -1; } input = argv[optind]; + //Sanity test of options... + if(compress && uncompress) { + cerr << "x and z are obviously exclusive :P\n"; + return -1; + } + + if(add_normals && compress) { + cerr << "Its not possible to add normals and compress in the same step\n" + << "Because normals requires 2 passes to be calculated\n\n"; + return -1; + } + + + + bool compute_cones = false; + if(!add && !remove && !compress && !uncompress && !zsort && + !qvertex && !qcolor && !qnormal && !qtexture && cone_threshold != 0) + compute_cones = true; + + Nexus nexus; if(!nexus.Load(input, true)) { @@ -301,6 +294,26 @@ int main(int argc, char *argv[]) { return -1; } + if(add_strips && (nexus.signature.face == Signature::STRIPS)) { + cerr << "Nexus file already has strips\n"; + return -1; + } + if(add_colors && nexus.signature.vcolor) { + cerr << "Nexus file already has colors\n"; + return -1; + } + if(add_normals && nexus.signature.vnorm) { + cerr << "Nexus file already has normals\n"; + return -1; + } + if(add_textures && nexus.signature.vtext) { + cerr << "Nexus file already has textures\n"; + return -1; + } + if(add_data && nexus.signature.vdata) { + cerr << "Nexus file already has data\n"; + return -1; + } if(nexus.IsCompressed() && compress) { cerr << "File already compressed.\n"; @@ -314,91 +327,29 @@ int main(int argc, char *argv[]) { if(info) { - //perform locality statistics - double meandist = 0; - vcg::Sphere3f last = nexus[0].sphere; - for(unsigned int i = 1; i < nexus.size(); i++) { - vcg::Sphere3f &sphere = nexus[i].sphere; - double dist = vcg::Distance(last.Center(), sphere.Center()); - meandist += dist; - last = sphere; - } - meandist /= nexus.size() -1; - cout << "Nexus file: " << input << "\n" - << "\n\tCompressed: " << nexus.IsCompressed() - << "\n\tStripped: " - << (int)(nexus.signature.face == Signature::STRIPS) - << "\n\tColor : " << (int)(nexus.signature.vcolor !=0) - << "\n\tNormal : " << (int)((nexus.signature.vnorm) !=0) - << "\n\tTexture : " << (int)((nexus.signature.vtext) !=0) - << "\n\tData : " << (int)((nexus.signature.vdata) !=0) - << "\n\n\tVertices: " << nexus.totvert - << "\tFaces: " << nexus.totface - << "\tPatches: " << nexus.size() - << "\n\tSphere: " - << nexus.sphere.Center()[0] << " " - << nexus.sphere.Center()[1] << " " - << nexus.sphere.Center()[2] << " R: " - << nexus.sphere.Radius() - << "\n\tAverage distance: " << meandist - << "\n\tChunk size " << nexus.chunk_size << endl; - - if(dump_history) { - if(nexus.history.IsQuick()) { - cout << "Quick format\n"; - for(unsigned int i = 0; i < nexus.history.n_nodes(); i++) { - cout << "Node: " << i << " out: "; - History::History::Node node = nexus.history.nodes[i]; - for(History::Node::iterator l = node.out_begin(); l != node.out_end(); l++) { - cout << "."; - History::Link &link = *l; - for(History::Link::iterator p = link.begin(); p != link.end(); p++) { - cout << p << " "; - } - } - cout << " in: "; - for(History::Node::iterator j = node.in_begin(); j != node.in_end(); j++) { - cout << "."; - History::Link &link = *j; - for(History::Link::iterator p = link.begin(); p != link.end(); p++) { - cout << p << " "; - } - } - cout << endl; - } - - } else { - cout << "Update format\n"; - for(unsigned int i = 0; i < nexus.history.updates.size(); i++) { - History::Update &update = nexus.history.updates[i]; - cout << "Created: "; - for(unsigned int k = 0; k < update.created.size(); k++) { - cout << update.created[k] << " "; - } - cout << "\nErased: "; - for(unsigned int k = 0; k < update.erased.size(); k++) { - cout << update.erased[k] << " "; - } - cout << "\n\n"; - } - } - } - - if(verbose) { - for(unsigned int i = 0; i < nexus.size(); i++) { - Entry &entry = nexus[i]; - cout << i << " -> nv: " << entry.nvert << " nf: " << entry.nface - << " error: " << entry.error - << " disk_size: " << entry.disk_size - << " start: " << entry.patch_start << endl; - } - cout << endl; - } + cout << "Nexus file: " << input << "\n"; + printInfo(nexus, verbose, dump_history); } + //determine if we must proceed: if(!add && !remove && !compress && !uncompress && !zsort && - qvertex == 0 && qnormal == 0 && qcolor == 0 && qtexture == 0) { + qvertex == 0 && qnormal == 0 && qcolor == 0 && qtexture == 0 && + cone_threshold == 0) { + nexus.Close(); + return 0; + } + + if(compute_cones) {//just recalculate normal cones + cerr << "Unimplemented at the moment...\n"; + + /*vector cones; + // ComputeCones(Nexus &nexus, float cone_threshold); + nexus.Close(); + nexus.Load(intput, false); + for(unsigned int i = 0; i < nexus.size(); i++) { + nexus[i].cone = cones[i]; + }*/ nexus.Close(); return 0; } @@ -422,15 +373,9 @@ int main(int argc, char *argv[]) { grid.Set(mesh.face); } - if(add_normals && compress) { - cerr << "Its not possible to add normals and compress in the same step\n" - << "Because normals requires 2 passes to be calculated\n\n"; - return -1; - } - Signature signature = nexus.signature; if(add_strips) signature.face = Signature::STRIPS; - if(add_normals) signature.vnorm = Encodings::SHORT4; + if(add_normals) signature.vnorm = add_normals; if(add_colors) signature.vcolor = Encodings::BYTE4; if(remove_normals) signature.vnorm = 0; @@ -442,6 +387,7 @@ int main(int argc, char *argv[]) { if(!output.size()) output = input + getSuffix(signature); if(output == input) { cerr << "Output and input files are the same.\n" + << "Use option -o \n" << "You do not want to overwrite your data. Trust me.\n"; return -1; } @@ -576,7 +522,7 @@ int main(int argc, char *argv[]) { //copying entry information; dst_entry.sphere = src_entry.sphere; dst_entry.error = src_entry.error; - //WARNING copy also normals cone + dst_entry.cone = src_entry.cone; out.borders.ResizeBorder(p, src_border.Size()); Border &dst_border = out.GetBorder(p); @@ -623,3 +569,87 @@ int main(int argc, char *argv[]) { return 0; } + +void printInfo(Nexus &nexus, bool verbose, bool dump_history) { + //perform locality statistics + double meandist = 0; + vcg::Sphere3f last = nexus[0].sphere; + for(unsigned int i = 1; i < nexus.size(); i++) { + vcg::Sphere3f &sphere = nexus[i].sphere; + double dist = vcg::Distance(last.Center(), sphere.Center()); + meandist += dist; + last = sphere; + } + meandist /= nexus.size() -1; + cout << "\n\tCompressed: " << nexus.IsCompressed() + << "\n\tStripped: " + << (int)(nexus.signature.face == Signature::STRIPS) + << "\n\tColor : " << (int)(nexus.signature.vcolor !=0) + << "\n\tNormal : " << (int)((nexus.signature.vnorm) !=0) + << "\n\tTexture : " << (int)((nexus.signature.vtext) !=0) + << "\n\tData : " << (int)((nexus.signature.vdata) !=0) + << "\n\n\tVertices: " << nexus.totvert + << "\tFaces: " << nexus.totface + << "\tPatches: " << nexus.size() + << "\n\tSphere: " + << nexus.sphere.Center()[0] << " " + << nexus.sphere.Center()[1] << " " + << nexus.sphere.Center()[2] << " R: " + << nexus.sphere.Radius() + << "\n\tAverage distance: " << meandist + << "\n\tChunk size " << nexus.chunk_size << endl; + + if(dump_history) { + if(nexus.history.IsQuick()) { + cout << "Quick format\n"; + for(unsigned int i = 0; i < nexus.history.n_nodes(); i++) { + cout << "Node: " << i << " out: "; + History::History::Node node = nexus.history.nodes[i]; + for(History::Node::iterator l = node.out_begin(); + l != node.out_end(); l++) { + cout << "."; + History::Link &link = *l; + for(History::Link::iterator p = link.begin(); p != link.end(); p++) { + cout << p << " "; + } + } + cout << " in: "; + for(History::Node::iterator j = node.in_begin(); + j != node.in_end(); j++) { + cout << "."; + History::Link &link = *j; + for(History::Link::iterator p = link.begin(); p != link.end(); p++) { + cout << p << " "; + } + } + cout << endl; + } + + } else { + cout << "Update format\n"; + for(unsigned int i = 0; i < nexus.history.updates.size(); i++) { + History::Update &update = nexus.history.updates[i]; + cout << "Created: "; + for(unsigned int k = 0; k < update.created.size(); k++) { + cout << update.created[k] << " "; + } + cout << "\nErased: "; + for(unsigned int k = 0; k < update.erased.size(); k++) { + cout << update.erased[k] << " "; + } + cout << "\n\n"; + } + } + } + + if(verbose) { + for(unsigned int i = 0; i < nexus.size(); i++) { + Entry &entry = nexus[i]; + cout << i << " -> nv: " << entry.nvert << " nf: " << entry.nface + << " error: " << entry.error + << " disk_size: " << entry.disk_size + << " start: " << entry.patch_start << endl; + } + cout << endl; + } +}