diff --git a/apps/nexus/nxsedit.cpp b/apps/nexus/nxsedit.cpp new file mode 100644 index 00000000..f544e5a1 --- /dev/null +++ b/apps/nexus/nxsedit.cpp @@ -0,0 +1,321 @@ +#include +using namespace std; + +#include "nexus.h" + +using namespace nxs; +using namespace vcg; + +#ifdef WIN32 +#include "getopt.h" +#else +#include +#endif + +int main(int argc, char *argv[]) { + + string input; + string output; + string plysource; + bool info = false; + + unsigned int add = 0; + bool add_strip = false; + bool add_colors = false; + bool add_normals = false; + bool add_textures = false; + bool add_data = false; + + unsigned int remove = 0; + bool remove_strip = false; + bool remove_colors = false; + bool remove_normals = false; + bool remove_textures = false; + bool remove_data = false; + + bool compress = false; + bool uncompress = false; + float qvertex = 0; + float qnormal = 0; + float qcolor = 0; + float qtexture = 0; + + int option; + while((option = getopt(argc, argv, "io:a:r:zxv:n:c:t:")) != EOF) { + switch(option) { + case 'i': info = true; break; + case 'o': output = optarg; break; + case 'a': { + if(strstr(optarg, "strip")) { + add_strip = true; + add |= NXS_STRIP; + remove |= NXS_FACES; + } + if(strstr(optarg, "colors")) { + add_colors = true; + add |= NXS_COLORS; + } + if(strstr(optarg, "normals")) { + add_normals = true; + add |= NXS_NORMALS_SHORT; + } + if(strstr(optarg, "textures")) { + add_textures = true; + add |= NXS_TEXTURES_SHORT; + } + if(strstr(optarg, "data")) { + add_data = true; + add |= NXS_DATA32; + } + if(add == 0) { + cerr << "Invalid -a argument: " << optarg << "\n" + << "Valid options are: strip, colors, normals, textures, data\n"; + return -1; + } + break; + } + + case 'r': { + if(strstr(optarg, "strip")) { + cerr << "Strip reming not supported!\n"; + return -1; + remove_strip = true; + add |= NXS_FACES; + remove |= NXS_STRIP; + } + if(strstr(optarg, "colors")) { + remove_colors = true; + remove |= NXS_COLORS; + } + if(strstr(optarg, "normals")) { + remove_normals = true; + remove |= NXS_NORMALS_SHORT; + } + if(strstr(optarg, "textures")) { + remove_textures = true; + remove |= NXS_TEXTURES_SHORT; + } + if(strstr(optarg, "data")) { + remove_data = true; + remove |= NXS_DATA32; + } + if(remove == 0) { + cerr << "Invalid -a argument: " << optarg << "\n" + << "Valid options are: strip, colors, normals, textures, data\n"; + return -1; + } + break; + } + + case 'p': plysource = optarg; break; + case 'z': compress = true; break; + case 'x': uncompress = true; break; + + case 'v': qvertex = atof(optarg); + if(qvertex == 0) { + cerr << "Invalid value for quantization: " << optarg << endl; + return -1; + } + break; + case 'n': qnormal = atof(optarg); + if(qnormal == 0) { + cerr << "Invalid value for quantization: " << optarg << endl; + return -1; + } + break; + case 'c': qcolor = atof(optarg); + if(qcolor == 0) { + cerr << "Invalid value for quantization: " << optarg << endl; + return -1; + } + break; + case 't': qtexture = atof(optarg); + if(qtexture == 0) { + cerr << "Invalid value for quantization: " << optarg << endl; + return -1; + } + break; + + default: cerr << "Unknown option: " << (char)option << endl; + return -1; + } + } + + 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" + << " -o : output filename (default is adding 00 to nexus)\n" + << " -a : Add [colors|normals|strip|textures|data|borders]\n" + << " -r : As add...\n" + << " -p : Ply source for colors or textures or data\n" + << " -z : compress\n" + << " -x : uncompress\n" + << " -v: Vertex quantization (float is the 0 level amount)\n" + << " -n: Normal quantization\n" + << " -c: Color quantization\n" + << " -t: Texture quantization\n\n"; + } + input = argv[optind]; + if(!output.size()) output = input + "00"; + + Nexus nexus; + if(!nexus.Load(input)) { + cerr << "Could not open nexus file: " << input << ".mt\n"; + return -1; + } + + //Sanity tests + if(remove_strip && !(nexus.signature & NXS_STRIP)) { + cerr << "Nexus file does not have strips\n"; + return -1; + } + if(remove_colors && !(nexus.signature & NXS_COLORS)) { + cerr << "Nexus file does not have colors\n"; + return -1; + } + if(remove_normals && !(nexus.signature & NXS_NORMALS_SHORT)) { + cerr << "Nexus file does not have normals\n"; + return -1; + } + if(remove_textures && !(nexus.signature & NXS_TEXTURES_SHORT)) { + cerr << "Nexus file does not have textures\n"; + return -1; + } + if(remove_data && !(nexus.signature & NXS_DATA32)) { + cerr << "Nexus file does not have data\n"; + return -1; + } + + + if(nexus.IsCompressed() && compress) { + cerr << "File already compressed.\n"; + return -1; + } + + if(!nexus.IsCompressed() && uncompress) { + cerr << "File not compressed.\n"; + return -1; + } + + + if(info) { + cerr << "Nexus file: " << input << "\n\n" + << "\n\tCompressed: " << nexus.IsCompressed() + << "\n\tStripped: " << (int)((nexus.signature&NXS_STRIP) !=0) + << "\n\tColor : " << (int)((nexus.signature&NXS_COLORS) !=0) + << "\n\tNormal : " << (int)((nexus.signature&NXS_NORMALS_SHORT) !=0) + << "\n\tTexture : " << (int)((nexus.signature&NXS_TEXTURES_SHORT) !=0) + << "\n\tData : " << (int)((nexus.signature&NXS_DATA32) !=0) + << "\n\n\tVertices: " << nexus.totvert + << "\tFaces: " << nexus.totface + << "\tPatches: " << nexus.index.size() << "\n\n"; + } + + //determine if we must proceed: + if(add == 0 && remove == 0 && !compress && !uncompress && + qvertex == 0 && qnormal == 0 && qcolor == 0 && qtexture == 0) { + nexus.Close(); + return 0; + } + + unsigned int signature = nexus.signature; + signature |= add; + signature &= ~remove; + + Nexus out; + if(!out.Create(output, (Signature)signature)) { + cerr << "Could not open output: " << output << endl; + return -1; + } + + for(unsigned int patch = 0; patch < nexus.index.size(); patch++) { + Nexus::Entry &src_entry = nexus.index[patch]; + Patch src_patch = nexus.GetPatch(patch); + Border src_border = nexus.GetBorder(patch); + + out.AddPatch(src_entry.nvert, src_entry.nface, src_entry.border_size); + + Nexus::Entry &dst_entry = out.index[patch]; + Patch dst_patch = out.GetPatch(patch); + Border dst_border = out.GetBorder(patch); + + //copy vertices: //no clustering + memcpy(dst_patch.VertBegin(), src_patch.VertBegin(), + src_patch.nv * sizeof(Point3f)); + + //now faces. + if(add_strip) { + cerr << "Unsupported strips\n"; + return -1; + } else { + memcpy(dst_patch.FaceBegin(), src_patch.FaceBegin(), + src_patch.nf * sizeof(unsigned short) *3); + } + + if(add_colors) { + //source of color: + cerr << "Unsupported color\n"; + return -1; + } + if(add_normals) { + vector normals; + normals.resize(dst_patch.nv, Point3f(0, 0, 0)); + + for(unsigned int i = 0; i < dst_patch.nf; i++) { + unsigned short *f = dst_patch.Face(i); + Point3f &v0 = dst_patch.Vert(f[0]); + Point3f &v1 = dst_patch.Vert(f[1]); + Point3f &v2 = dst_patch.Vert(f[2]); + + Point3f norm = (v1 - v0) ^ (v2 - v0); + normals[f[0]] += norm; + normals[f[1]] += norm; + normals[f[2]] += norm; + } + for(unsigned int i = 0; i < dst_patch.nv; i++) { + Point3f &norm = normals[i]; + norm.Normalize(); + short *n = dst_patch.Norm16(i); + for(int k = 0; k < 3; k++) { + n[k] = (short)(norm[k] * 32766); + } + n[3] = 0; + } + } + + //copying entry information; + dst_entry.sphere = src_entry.sphere; + dst_entry.error = src_entry.error; + + //adding borders. + dst_entry.border_used = src_entry.border_used; + memcpy(dst_border.Start(), src_border.Start(), + src_border.Size() * sizeof(Link)); + } + + //TODO !!! FIX NORMALS ACROSS BORDERS + /* + for(unsigned int patch = 0; patch < nexus.index.size(); patch++) { + for(unsigned int i = 0; i < dst_border.Size(); i++) { + Link &link = dst_border[i]; + //we just make the mean... + } + } + */ + + + //fixing sphere. + out.sphere = nexus.sphere; + //copying history: + out.history = nexus.history; + + out.Close(); + nexus.Close(); + return 0; +} +