diff --git a/apps/nexus/exploder.cpp b/apps/nexus/exploder.cpp new file mode 100644 index 00000000..e15b3a77 --- /dev/null +++ b/apps/nexus/exploder.cpp @@ -0,0 +1,107 @@ +#include +#include + +#include "nexus.h" + +using namespace nxs; +using namespace vcg; +using namespace std; + +Point3f explode(Point3f &v, Point3f ¢er, Point3f &dir, float mag) { + v = ((v - center) * mag + center) + dir; + return v; +} + +int main(int argc, char *argv[]) { + if(argc < 3) { + cerr << "Usage: " << argv[0] << " [factor]\n"; + return -1; + } + string input = argv[1]; + string output = argv[2]; + float factor = 2; + if(argc == 4) { + factor = atoi(argv[3]); + if(factor == 0) { + cerr << "Invalid factor: " << argv[3] << endl; + return -1; + } + } + Nexus in; + if(!in.Load(input, true)) { + cerr << "Could not load nexus: " << input << endl; + return -1; + } + Nexus out; + if(!out.Create(output, in.signature, in.chunk_size)) { + cerr << "Could not create nexus: " << output << endl; + return -1; + } + + out.sphere = in.sphere; + out.history = in.history; + for(unsigned int i = 0; i < in.index.size(); i++) { + unsigned int patch = i; + Nexus::PatchInfo &src_entry = in.index[patch]; + Patch &src_patch = in.GetPatch(patch); + Border src_border = in.GetBorder(patch); + + out.AddPatch(src_entry.nvert, src_entry.nface, src_border.Available()); + + Nexus::PatchInfo &dst_entry = out.index[patch]; + + Patch dst_patch = out.GetPatch(patch); + + Point3f dir = src_entry.sphere.Center() - in.sphere.Center(); + dir.Normalize(); + dir *= 10 * src_entry.error; + + memcpy(dst_patch.VertBegin(), src_patch.VertBegin(), + src_patch.nv * sizeof(Point3f)); + + Point3f *ptr = dst_patch.VertBegin(); + for(int i = 0; i < dst_patch.nv; i++) { + ptr[i] = explode(ptr[i], src_entry.sphere.Center(), dir, + 0.5 *src_entry.error); + } + + + if(in.signature & NXS_STRIP) { + memcpy(dst_patch.FaceBegin(), src_patch.FaceBegin(), + src_patch.nf * sizeof(unsigned short)); + } else { + memcpy(dst_patch.FaceBegin(), src_patch.FaceBegin(), + src_patch.nf * sizeof(unsigned short) * 3); + } + + if((in.signature & NXS_COLORS) && (out.signature & NXS_COLORS)) + memcpy(dst_patch.ColorBegin(), src_patch.ColorBegin(), + src_patch.nv * sizeof(unsigned int)); + + if((in.signature & NXS_NORMALS_SHORT) && + (out.signature & NXS_NORMALS_SHORT)) + 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; + + //adding borders. + for(unsigned int i = 0; i < src_border.Size(); i++) { + Link &link = src_border[i]; + if(link.IsNull()) continue; + assert(link.end_patch < in.index.size()); + } + Border dst_border = out.GetBorder(patch); + out.borders.ResizeBorder(patch, src_border.Size()); + memcpy(dst_border.Start(), src_border.Start(), + src_border.Size() * sizeof(Link)); + } + in.Close(); + out.Close(); + return 0; +} diff --git a/apps/nexus/file.cpp b/apps/nexus/file.cpp index 325bc042..d1ca0826 100644 --- a/apps/nexus/file.cpp +++ b/apps/nexus/file.cpp @@ -120,3 +120,11 @@ void File::WriteBuffer(void *data, unsigned int sz) { assert(0 && "Could not write"); #endif } + +void File::Delete(const string &filename) { +#ifdef WIN32 + DeleteFile(filename.c_str()); +#else + unlink(filename.c_str()); +#endif +} diff --git a/apps/nexus/file.h b/apps/nexus/file.h index dc48ddaa..6dda2580 100644 --- a/apps/nexus/file.h +++ b/apps/nexus/file.h @@ -39,6 +39,7 @@ class File { bool IsReadOnly() { return readonly; } + static void Delete(const std::string &filename); protected: #ifdef WIN32 diff --git a/apps/nexus/fragment.cpp b/apps/nexus/fragment.cpp index 60245ea9..a80ab0ba 100644 --- a/apps/nexus/fragment.cpp +++ b/apps/nexus/fragment.cpp @@ -40,41 +40,54 @@ void NxsPatch::Read(instm *in) { in->read(&*bord.begin(), bord.size() * sizeof(Link)); } -void Fragment::Write(outstm *out) { - out->write(&id, sizeof(unsigned int)); - out->write(&error, sizeof(float)); - - unsigned int ssize = seeds.size(); - out->write(&ssize, sizeof(unsigned int)); - - out->write(&*seeds.begin(), ssize * sizeof(Point3f)); - out->write(&*seeds_id.begin(), ssize * sizeof(unsigned int)); +bool Fragment::Write(outstm *out) { + try { + out->write(&id, sizeof(unsigned int)); + out->write(&error, sizeof(float)); + unsigned int ssize = seeds.size(); + out->write(&ssize, sizeof(unsigned int)); + out->write(&*seeds.begin(), ssize * sizeof(Point3f)); + out->write(&*seeds_id.begin(), ssize * sizeof(unsigned int)); + unsigned int psize = pieces.size(); + out->write(&psize, sizeof(unsigned int)); - unsigned int psize = pieces.size(); - out->write(&psize, sizeof(unsigned int)); - - for(unsigned int i = 0; i < pieces.size(); i++) - pieces[i].Write(out); + for(unsigned int i = 0; i < pieces.size(); i++) + pieces[i].Write(out); + return true; + } catch (estream *e) { + perr.putf("Error: %s\n", pconst(e->get_message())); + delete e; + return false; + } } -void Fragment::Read(instm *in) { - - in->read(&id, sizeof(unsigned int)); - in->read(&error, sizeof(float)); - - unsigned int ssize; - in->read(&ssize, sizeof(unsigned int)); - seeds.resize(ssize); - seeds_id.resize(ssize); - in->read(&*seeds.begin(), ssize * sizeof(Point3f)); - in->read(&*seeds_id.begin(), ssize * sizeof(unsigned int)); - - unsigned int psize; - in->read(&psize, sizeof(unsigned int)); - pieces.resize(psize); - - for(unsigned int i = 0; i < psize; i++) - pieces[i].Read(in); +bool Fragment::Read(instm *in) { + try { + in->read(&id, sizeof(unsigned int)); + in->read(&error, sizeof(float)); + + //TODO move this control to all read! + unsigned int ssize; + if(sizeof(int) != in->read(&ssize, sizeof(unsigned int))) + return false; + seeds.resize(ssize); + seeds_id.resize(ssize); + in->read(&*seeds.begin(), ssize * sizeof(Point3f)); + in->read(&*seeds_id.begin(), ssize * sizeof(unsigned int)); + + unsigned int psize; + in->read(&psize, sizeof(unsigned int)); + pieces.resize(psize); + + for(unsigned int i = 0; i < psize; i++) { + pieces[i].Read(in); + } + return true; + } catch (estream *e) { + perr.putf("Error: %s\n", pconst(e->get_message())); + delete e; + return false; + } } void nxs::Join(Fragment &in, @@ -132,6 +145,54 @@ void nxs::Join(Fragment &in, } assert(vcount < (1<<16)); + set newborders; + for(unsigned int i = 0; i < in.pieces.size(); i++) { + unsigned int offset = offsets[i]; + vector &bord = in.pieces[i].bord; + for(unsigned int k = 0; k < bord.size(); k++) { + Link llink = bord[k]; + if(llink.IsNull()) continue; + if(!patch_remap.count(llink.end_patch)) {//external + BigLink link; + link.start_vert = remap[offset + llink.start_vert]; + link.end_patch = in.pieces[i].patch; + link.end_vert = llink.start_vert; + newborders.insert(link); + } + } + } + + newvert.resize(vcount); + newface.resize(fcount*3); + newbord.resize(newborders.size()); + + fcount = 0; + for(unsigned int i = 0; i < in.pieces.size(); i++) { + unsigned int offset = offsets[i]; + vector &vert = in.pieces[i].vert; + vector &face = in.pieces[i].face; + vector &bord = in.pieces[i].bord; + + for(unsigned int i = 0; i < vert.size(); i++) { + assert(offset + i < remap.size()); + assert(remap[offset + i] < vcount); + newvert[remap[offset + i]] = vert[i]; + } + + for(unsigned int i = 0; i < face.size(); i++) { + assert(offset + face[i] < remap.size()); + assert(remap[offset + face[i]] < newvert.size()); + assert(fcount < newface.size()); + newface[fcount++] = remap[offset + face[i]]; + } + } + set::iterator b; + for(b = newborders.begin(); b != newborders.end(); b++) + newbord.push_back(*b); + + /* old code (more general.. but not parallelizable) + + //L(a, b): Exist link between a, b //An external link L(e, v) where v belongs to the patches (and e not) //is valid only if: for every x in patches L(v, x) => L(e, x) @@ -148,8 +209,10 @@ void nxs::Join(Fragment &in, for(unsigned int k = 0; k < bord.size(); k++) { Link llink = bord[k]; if(llink.IsNull()) continue; - if(!patch_remap.count(llink.end_patch)) {//external...may be erased though + if(!patch_remap.count(llink.end_patch)) {//external...may be erased BigLink link; + link.orig_vert = llink.start_vert; + link.orig_patch = in.pieces[i].patch; link.start_vert = remap[offset + llink.start_vert]; link.end_patch = llink.end_patch; link.end_vert = llink.end_vert; @@ -196,14 +259,13 @@ void nxs::Join(Fragment &in, unsigned int n = (*b).second; if(n * (n-1) == internal_links[link.start_vert]) newbord.push_back(link); - } + }*/ } void nxs::Split(Fragment &out, vector &newvert, vector &newface, - vector &newbord, - VoronoiPartition &part) { + vector &newbord) { unsigned int nseeds = out.seeds.size(); vector &seeds = out.seeds; @@ -219,12 +281,12 @@ void nxs::Split(Fragment &out, assert(seed < nseeds); count[seed]++; } - + //pruning small patches float min_size = (newface.size()/3) / 20.0f; vector newseeds; vector newseeds_id; - + for(unsigned int seed = 0; seed < nseeds; seed++) { if(count[seed] > min_size) { newseeds.push_back(seeds[seed]); @@ -313,17 +375,15 @@ void nxs::Split(Fragment &out, //for every esternal link we must update external patches! for(unsigned int i = 0; i < newbord.size(); i++) { BigLink link = newbord[i]; - if(v_remap[link.start_vert] == -1) continue; - link.start_vert = v_remap[link.start_vert]; - assert(link.start_vert < (1<<16)); + if(v_remap[link.start_vert] == -1) continue; Link llink; - llink.start_vert = link.start_vert; + llink.start_vert = v_remap[link.start_vert]; llink.end_patch = link.end_patch; llink.end_vert = link.end_vert; bords.push_back(llink); } - //process internal borders; + //process internal borders; //TODO higly inefficient!!! for(unsigned int rseed = 0; rseed < nseeds; rseed++) { if(seed == rseed) continue; diff --git a/apps/nexus/fragment.h b/apps/nexus/fragment.h index 67abac83..309e0f9c 100644 --- a/apps/nexus/fragment.h +++ b/apps/nexus/fragment.h @@ -12,6 +12,8 @@ namespace nxs { class VoronoiPartition; struct BigLink { + // unsigned int orig_vert; + // unsigned int orig_patch; unsigned int start_vert; unsigned int end_patch; unsigned int end_vert; @@ -33,8 +35,7 @@ class NxsPatch { unsigned int patch; std::vector vert; std::vector face; - //when this is an outfragment link.end_patch is (1<<31) + end_patch - //when it is an internal border! + std::vector bord; void Write(pt::outstm *out); @@ -52,8 +53,8 @@ class Fragment { std::vector pieces; - void Write(pt::outstm *out); - void Read(pt::instm *in); + bool Write(pt::outstm *out); + bool Read(pt::instm *in); //returns the index of the seed unsigned int Locate(const vcg::Point3f &p); @@ -67,8 +68,7 @@ class Fragment { void Split(Fragment &out, std::vector &newvert, std::vector &newface, - std::vector &newbord, - VoronoiPartition &part); + std::vector &newbord); } #endif diff --git a/apps/nexus/mfhash.cpp b/apps/nexus/mfhash.cpp index e9d08de5..a4333c75 100644 --- a/apps/nexus/mfhash.cpp +++ b/apps/nexus/mfhash.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.5 2004/07/05 15:49:39 ponchio +Windows (DevCpp, mingw) port. + Revision 1.4 2004/07/04 14:23:14 ponchio *** empty log message *** @@ -73,6 +76,11 @@ bool MFHash::Load(const string &file, unsigned int used) { return true; } +void MFHash::Delete() { + buffer.Flush(); + buffer.Delete(); +} + void MFHash::Resize(unsigned int n) { assert(buffer.Size() - space <= n); //lets dump actual content diff --git a/apps/nexus/mfhash.h b/apps/nexus/mfhash.h index e157308d..6689007b 100644 --- a/apps/nexus/mfhash.h +++ b/apps/nexus/mfhash.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.4 2004/07/02 17:40:30 ponchio +Debug. + Revision 1.3 2004/07/02 13:08:43 ponchio *** empty log message *** @@ -62,6 +65,7 @@ class MFHash { MFHash() {} bool Create(const std::string &file, unsigned int reserved = 32); bool Load(const std::string &file, unsigned int used = 0xffffffff); + void Delete(); void Resize(unsigned int n); void Insert(unsigned int key, unsigned int value, bool rehash = true); diff --git a/apps/nexus/mfile.cpp b/apps/nexus/mfile.cpp index eb76ce08..50c55bf3 100644 --- a/apps/nexus/mfile.cpp +++ b/apps/nexus/mfile.cpp @@ -52,6 +52,11 @@ void MFile::Close() { files.clear(); } +void MFile::Delete() { + while(files.size()) + RemoveFile(); +} + void MFile::Redim(int64 sz) { assert(!readonly); if(sz > size) { @@ -120,11 +125,12 @@ void MFile::WriteBuffer(void *data, unsigned int sz) { void MFile::RemoveFile() { assert(files.size()); - string name = Name(files.size()); + string name = Name(files.size()-1); File &file = files.back(); unsigned int last_size = file.Length(); files.pop_back(); size -= last_size; + cerr << "Removing file: " << name << endl; #ifdef WIN32 DeleteFile(name.c_str()); #else diff --git a/apps/nexus/mfile.h b/apps/nexus/mfile.h index bf167b72..12d2408d 100644 --- a/apps/nexus/mfile.h +++ b/apps/nexus/mfile.h @@ -27,6 +27,7 @@ class MFile { unsigned int max_file_size = MFILE_MAX_SIZE); bool Load(const std::string &filename, bool readonly = false); void Close(); + void Delete(); int64 Length() { return size; } void Redim(int64 size); diff --git a/apps/nexus/nexus.cpp b/apps/nexus/nexus.cpp index 200b04a9..a187c1c1 100644 --- a/apps/nexus/nexus.cpp +++ b/apps/nexus/nexus.cpp @@ -147,6 +147,19 @@ Border Nexus::GetBorder(unsigned int patch, bool flush) { return borders.GetBorder(patch); } +void Nexus::AddBorder(unsigned int patch, Link &link) { + Border border = GetBorder(patch); + + unsigned int pos = border.Size(); + if(borders.ResizeBorder(patch, pos+1)) { + border = GetBorder(patch); + } + + assert(border.Size() < border.Available()); + assert(border.Available() > pos); + + border[pos] = link; +} unsigned int Nexus::AddPatch(unsigned int nvert, unsigned int nface, unsigned int nbord) { diff --git a/apps/nexus/nexus.h b/apps/nexus/nexus.h index e91edc60..e157e402 100644 --- a/apps/nexus/nexus.h +++ b/apps/nexus/nexus.h @@ -59,6 +59,8 @@ class Nexus { Patch &GetPatch(unsigned int patch, bool flush = true); Border GetBorder(unsigned int patch, bool flush = true); + void AddBorder(unsigned int patch, Link &link); + bool IsCompressed() { return (signature & NXS_COMPRESSED) != 0; } bool HasStrips() { return (signature & NXS_STRIP) != 0; } bool HasColors() { return (signature & NXS_COLORS) != 0; } diff --git a/apps/nexus/nexusview.cpp b/apps/nexus/nexusview.cpp index 2dcdc8b0..8d5a4b48 100644 --- a/apps/nexus/nexusview.cpp +++ b/apps/nexus/nexusview.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.19 2004/10/30 20:17:03 ponchio +Fixed big patches problem. + Revision 1.18 2004/10/21 13:40:16 ponchio Debugging. @@ -386,6 +389,23 @@ int main(int argc, char *argv[]) { } else nexus.Draw(cells); + if(show_borders) { + for(unsigned int i = 0; i < cells.size(); i++) { + Border border = nexus.GetBorder(cells[i]); + Patch &patch = nexus.GetPatch(cells[i]); + glPointSize(4); + glColor3f(1.0f, 1.0f, 1.0f); + glBegin(GL_POINTS); + for(int b = 0; b < border.Size(); b++) { + Link &link = border[b]; + Point3f &p = patch.Vert(link.start_vert); + glVertex3f(p[0], p[1], p[2]); + } + glEnd(); + glPointSize(1); + } + } + //cerr Do some reporting: if(show_statistics) { glMatrixMode(GL_MODELVIEW); diff --git a/apps/nexus/nxsclient.cpp b/apps/nexus/nxsclient.cpp new file mode 100644 index 00000000..5724fbd5 --- /dev/null +++ b/apps/nexus/nxsclient.cpp @@ -0,0 +1,42 @@ +#include + +class NxsClientPool { + vector clients; + void Push(NxsRequest *request); +}; + +class NxsClient: public pt::ipstream { +public: + queue requests; + + void Push(NxsRequest *request); +}; + + +ipaddress addr = phostbyname("nb-ponchio.isti.cnr.it"); + ipstream client; + client.set_ip(addr); + client.set_port(testport); + try + { + client.open(); + + pout.put("Sending a request to the server...\n"); + client.write("Hello", 6); + client.flush(); + + // receive the response + string rsp = client.line(maxtoken); + pout.putf("Received: %s\n", pconst(rsp)); + + // need to close the socket explicitly to gracefully shutdown + // the peer host too. otherwise, ~ipstream() will call cancel() + // and leave the peer in a waiting state (not forever though). + client.close(); + } + catch(estream* e) + { + perr.putf("Error: %s\n", pconst(e->get_message())); + delete e; + } + diff --git a/apps/nexus/nxsdispatcher.cpp b/apps/nexus/nxsdispatcher.cpp new file mode 100644 index 00000000..0cd4d145 --- /dev/null +++ b/apps/nexus/nxsdispatcher.cpp @@ -0,0 +1,178 @@ +#include "nxsdispatcher.h" +#include "fragment.h" +#include "decimate.h" +#include +#include + +using namespace std; +using namespace vcg; +using namespace nxs; +using namespace pt; + +void SaveFragment(Nexus &nexus, VoronoiChain &chain, + Fragment &fragin, + Fragment &fragout); + + +void Opener::execute() { + server->reading.lock(); + server->writing.lock(); + while(1) { + if(get_signaled()) + return; + try { + server->open(); + server->connected = true; + break; + } catch(...) { + } + sleep(4); + } + server->reading.unlock(); + server->writing.unlock(); +} + +void FragIO::execute() { + + server->writing.lock(); + // cerr << "Writing frag...: " << fragin->id << "\n"; + + outmemory outm; + outm.open(); + fragin->Write(&outm); + pt::string a = outm.get_strdata(); + try { + server->write((const char *)a, length(a)); + server->flush(); + } catch (estream *e) { + perr.putf("Error: %s\n", pconst(e->get_message())); + delete e; + + message *msg = new message(MSG_FAIL, (int)fragin); + dispatcher->post(msg); + + //TODO restart Server! + return; + } + + server->reading.lock(); + server->writing.unlock(); + + Fragment *out = new Fragment; + if(!out->Read(server)) { + message *msg = new message(MSG_FAIL, (int)fragin); + dispatcher->post(msg); + return; + } + server->reading.unlock(); + + // cerr << "Received frag: " << out->id << endl; + + message *msg = new message(MSG_RECEIVE, (int)fragin); + msg->result = (int)out; + dispatcher->post(msg); + // dispatcher->ReceiveFragment(fragin, out); +} + +bool Dispatcher::Init(const std::string &file) { + FILE *fp = fopen(file.c_str(), "rb"); + if(!fp) return false; + char host[256]; + int port; + while(fscanf(fp, "%s %d\n", host, &port) == 2) { + cerr << "Host: " << host << " port: " << port << endl; + Server *server = new Server(host, port); + server->opener.start(); + servers.push_back(server); + } + fclose(fp); + if(servers.size() == 0) { + cerr << "Empty server file!\n"; + return false; + } + return true; +} + +Dispatcher::~Dispatcher() { + for(unsigned int i = 0; i < servers.size(); i++) { + Server *server = servers[i]; + server->opener.signal(); + server->close(); + delete server; + } +} + +void Dispatcher::SendFragment(Fragment *frag) { + //WARNING this handles no more than 1<<31 fragments! + frag->id = count++; + message *msg = new message(MSG_SEND, (int)frag); + post(msg); +} + +Server *Dispatcher::BestServer() { + Server *best = NULL; + for(unsigned int i = 0; i < servers.size(); i++){ + if(servers[i]->connected) { + if(!best || servers[i]->queue < best->queue) { + best = servers[i]; + } + } + } + return best; +} + +void Dispatcher::ReceiveFragment(Fragment *in, Fragment *out) { + //lock nexus if run in thread. + // cerr << "Saving: " << in->id << endl; + SaveFragment(*nexus, *chain, *in, *out); + + if(frags.count(in->id)) { + FragIO *frag = frags[in->id]; + delete frag; + frags.erase(frags.find(in->id)); + } + delete in; + delete out; +} + +void Dispatcher::msghandler(message &msg) { + switch(msg.id) { + case MSG_FAIL: break; + case MSG_SEND: { + //get server! + Server *best = BestServer(); + Fragment *fragin = (Fragment *)(msg.param); + + if(!best) { //no server process locally.... + // cerr << "No best!" << endl; + vector newvert; + vector newface; + vector newbord; + Join(*fragin, newvert, newface, newbord); + + float error = Decimate(QUADRIC, + (unsigned int)((newface.size()/3) * 0.5), + newvert, newface, newbord); + + Fragment *fragout = new Fragment; + + fragout->error = error; + fragout->id = fragin->id; + fragout->seeds = fragin->seeds; + fragout->seeds_id = fragin->seeds_id; + Split(*fragout, newvert, newface, newbord); + ReceiveFragment(fragin, fragout); + } else { + FragIO *frag = new FragIO(best, this, fragin); + assert(!frags.count(fragin->id)); + frags[fragin->id] = frag; + frag->start(); + } + } break; + case MSG_RECEIVE: + ReceiveFragment((Fragment *)(msg.param), (Fragment *)(msg.result)); + break; + default: + defhandler(msg); + } +} diff --git a/apps/nexus/nxsdispatcher.h b/apps/nexus/nxsdispatcher.h new file mode 100644 index 00000000..11e90995 --- /dev/null +++ b/apps/nexus/nxsdispatcher.h @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include + +namespace nxs { + +#define MSG_SEND MSG_USER + 1 +#define MSG_RECEIVE MSG_USER + 2 +#define MSG_FAIL MSG_USER + 3 + + class Fragment; + class Nexus; + class VoronoiChain; + + class Server; + class FragIO; + class Dispatcher; + + + class Opener: public pt::thread { + public: + Opener(Server *s): thread(false), server(s) {} + ~Opener() { waitfor(); } + void execute(); + void cleanup() {} + + Server *server; + }; + + + class Server: public pt::ipstream { + public: + Server(pt::string host, int port): ipstream(host, port), + connected(false), opener(this) {} + + int queue; + pt::mutex reading; + pt::mutex writing; + bool connected; + Opener opener; + }; + + + class Dispatcher: public pt::msgqueue { + public: + Dispatcher(Nexus *nx, VoronoiChain *ch): + count(0), nexus(nx), chain(ch) {} + ~Dispatcher(); + + bool Init(const std::string &file); + void SendFragment(Fragment *frag); + void ReceiveFragment(Fragment *in, Fragment *out); + Server *BestServer(); + + void msghandler(pt::message &msg); + + int count; + Nexus *nexus; + VoronoiChain *chain; + std::vector servers; + std::map frags; + }; + + class FragIO: public pt::thread { + public: + FragIO(Server *se, Dispatcher *di, Fragment *frag): + thread(false), server(se), dispatcher(di), fragin(frag) {} + ~FragIO() { waitfor(); } + void execute(); + void cleanup() {} + + Server *server; + Dispatcher *dispatcher; + Fragment *fragin; + }; + + + +} diff --git a/apps/nexus/nxspatcher.cpp b/apps/nexus/nxspatcher.cpp new file mode 100644 index 00000000..7ff3aea0 --- /dev/null +++ b/apps/nexus/nxspatcher.cpp @@ -0,0 +1,47 @@ +#include +#include "crude.h" +using namespace nxs; +using namespace vcg; +using namespace std; + +int main(int argc, char *argv[]) { + if(argc != 2) { + cerr << "Uso: " << argv[0] << " \n"; + return -1; + } + + unsigned int side = atoi(argv[1]); + if(side > 1000 || side == 0) { + cerr << "Invalid side: " << argv[1] << endl; + return -1; + } + + Crude crude; + if(!crude.Create("square")) { + cerr << "Could not create square" << endl; + return -1; + } + + int half = side/2; + crude.Resize(side * side, (side-1) * (side-1) * 2); + for(unsigned int x = 0; x < side; x++) + for(unsigned int y = 0; y < side; y++) { + Point3f p(x*x*x/((float)side), + y*y*y/((float)side), x*y/((float)side)); + crude.GetVertex(x + side * y) = p; + crude.GetBox().Add(p); + } + + for(unsigned int x = 0; x < side-1; x++) + for(unsigned int y = 0; y < side-1; y++) { + unsigned int pos = x + side*y; + Crude::Face face(pos, pos + 1, pos + side); + crude.GetFace(0 + 2*x + (side-1)*y*2) = face; + + face = Crude::Face(pos + 1, pos + 1 + side, pos +side); + crude.GetFace(1 + 2*x + (side-1)*y*2) = face; + } + + crude.Close(); + return 0; +} diff --git a/apps/nexus/nxsserver.cpp b/apps/nexus/nxsserver.cpp new file mode 100644 index 00000000..f34400c8 --- /dev/null +++ b/apps/nexus/nxsserver.cpp @@ -0,0 +1,179 @@ +#include +#include +#include +using namespace pt; + +#include "fragment.h" +#include "decimate.h" +using namespace nxs; +using namespace vcg; +using namespace std; + +const int port = 10102; + +class FragOutQueue: public msgqueue { +public: + FragOutQueue(ipstream &cli): client(cli) {} + void msghandler(message &msg) { + if(msg.id != MSG_USER) { + defhandler(msg); + return; + } + Fragment &fragment = *(Fragment *)(msg.param); + + // pout.putf("Sending: %d\n", fragment.id); + outmemory outm; + outm.open(); + fragment.Write(&outm); + pt::string a = outm.get_strdata(); + try { + client.write((const char *)a, length(a)); + client.flush(); + pout.putf("Sent fragment id: %d\n", fragment.id); + } catch (estream *e) { + perr.putf("Error: %s\n", pconst(e->get_message())); + delete e; + } + delete (Fragment *)(msg.param); + } + ipstream &client; +}; + +class FragInQueue: public msgqueue { +public: + FragInQueue(FragOutQueue &o): out(o) {} + void msghandler(message &msg) { + if(msg.id != MSG_USER) { + defhandler(msg); + return; + } + Fragment &fragin = *(Fragment *)(msg.param); + // pout.putf("Processing: %d\n", fragin.id); + vector newvert; + vector newface; + vector newbord; + Join(fragin, newvert, newface, newbord); + + float error = Decimate(QUADRIC, + (unsigned int)((newface.size()/3) * 0.5), + newvert, newface, newbord); + + message *outmsg = new message(MSG_USER); + outmsg->param = (int)(new Fragment); + Fragment &fragout = *(Fragment *)(outmsg->param); + + fragout.error = error; + fragout.id = fragin.id; + fragout.seeds = fragin.seeds; + fragout.seeds_id = fragin.seeds_id; + Split(fragout, newvert, newface, newbord); + out.post(outmsg); + delete (Fragment *)(msg.param); + } + + FragOutQueue &out; +}; + + +class Reader: public thread { +public: + Reader(ipstream &cli, FragInQueue &que): + thread(false), client(cli), queue(que) {} + + ~Reader() {waitfor(); } + + void execute() { + while(1) { + if(get_signaled()) return; + message *msg = new message(MSG_USER); + msg->param = (int)(new Fragment); + Fragment &fragment = *(Fragment *)(msg->param); + if(!fragment.Read(&client)) { + pout.putf("Could not read!\n"); + return; + } + queue.post(msg); + // pout.putf("Incoming: %d\n", fragment.id); + } + } + void cleanup() {} + + ipstream &client; + FragInQueue &queue; +}; + +class Worker: public thread { +public: + Worker(FragInQueue &que): thread(false), queue(que) {} + ~Worker() { waitfor(); } + + void execute() { + queue.run(); + } + void cleanup() {} + FragInQueue &queue; +}; + +class Writer: public thread { +public: + Writer(FragOutQueue &que): thread(false), queue(que) {} + ~Writer() {waitfor(); } + void execute() { + queue.run(); + } + void cleanup() {} + FragOutQueue &queue; +}; + + +void servermain(ipstmserver& svr) { + ipstream client; + pout.putf("Ready to answer queries on port %d\n", port); + + while(true) { + // serve() will wait for a connection request and will prepare + // the supplied ipstream object for talking to the peer. + svr.serve(client); + + if (client.get_active()) { + try { + pout.putf("Incoming connection\n"); + FragOutQueue out(client); + FragInQueue in(out); + Reader reader(client, in); + Worker worker(in); + Writer writer(out); + + reader.start(); + worker.start(); + writer.start(); + + reader.waitfor(); + worker.waitfor(); + writer.waitfor(); + + client.flush(); + client.close(); + } catch(estream* e) { + perr.putf("Error: %s\n", pconst(e->get_message())); + delete e; + } + } + } +} + +int main() { + ipstmserver svr; + + try { + // bind to all local addresses on port 8085 + svr.bindall(port); + + // enter an infinite loop of serving requests + servermain(svr); + } catch(estream* e) { + perr.putf("FATAL: %s\n", pconst(e->get_message())); + delete e; + } + return 0; +} diff --git a/apps/nexus/pchain.h b/apps/nexus/pchain.h index b361941f..57c2b1fb 100644 --- a/apps/nexus/pchain.h +++ b/apps/nexus/pchain.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.5 2004/09/21 00:53:23 ponchio +Lotsa changes. + Revision 1.4 2004/08/27 00:39:28 ponchio Rewrote. @@ -62,7 +65,8 @@ class PChain { virtual unsigned int Locate(unsigned int level, const vcg::Point3f &p) = 0; - virtual void RemapFaces(Crude &crude, VFile &face_remap, + virtual void RemapFaces(VFile &baricenters, + VFile &face_remap, std::vector &patch_faces, float scaling, int steps) = 0; diff --git a/apps/nexus/vert_remap.cpp b/apps/nexus/vert_remap.cpp index 60512152..603451c4 100644 --- a/apps/nexus/vert_remap.cpp +++ b/apps/nexus/vert_remap.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.5 2004/07/05 15:49:39 ponchio +Windows (DevCpp, mingw) port. + Revision 1.4 2004/07/02 17:41:37 ponchio Debug. @@ -66,6 +69,12 @@ void VertRemap::Close() { borders.Close(); } +void VertRemap::Delete() { + all.Flush(); + all.Delete(); + borders.Delete(); +} + void VertRemap::Resize(unsigned int n_vert) { all.Resize(n_vert); for(unsigned int i = 0; i < n_vert; i++) diff --git a/apps/nexus/vert_remap.h b/apps/nexus/vert_remap.h index e2f92095..3007dfea 100644 --- a/apps/nexus/vert_remap.h +++ b/apps/nexus/vert_remap.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.4 2004/10/01 15:59:52 ponchio +Added include + Revision 1.3 2004/07/02 17:41:37 ponchio Debug. @@ -55,6 +58,7 @@ class VertRemap { bool Create(const std::string &file); bool Load(const std::string &file); void Close(); + void Delete(); void Resize(unsigned int n_vert); unsigned int Size(); diff --git a/apps/nexus/vfile.h b/apps/nexus/vfile.h index a9370fdd..10009154 100644 --- a/apps/nexus/vfile.h +++ b/apps/nexus/vfile.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.14 2004/10/19 16:50:27 ponchio +Added row file access .... + Revision 1.13 2004/10/08 15:12:04 ponchio Working version (maybe) @@ -78,7 +81,7 @@ Created #ifndef VFILE_H #define VFILE_H -#include "file.h" +#include "mfile.h" #include #include @@ -94,7 +97,7 @@ Created namespace nxs { -template class VFile: public File { +template class VFile: public MFile { public: struct Buffer { @@ -138,7 +141,7 @@ template class VFile: public File { chunk_size = _chunk_size; queue_size = _queue_size; - return File::Create(filename); + return MFile::Create(filename); } bool Load(const std:: string &filename, @@ -150,7 +153,7 @@ template class VFile: public File { chunk_size = _chunk_size; queue_size = _queue_size; - if(!File::Load(filename)) return false; + if(!MFile::Load(filename)) return false; n_elements = size/sizeof(T); return true; } @@ -159,6 +162,11 @@ template class VFile: public File { Flush(); } + void Delete() { + Flush(); + MFile::Delete(); + } + void Flush() { list_iterator i; for(i = buffers.begin(); i != buffers.end(); i++) @@ -176,7 +184,7 @@ template class VFile: public File { void Resize(unsigned int elem) { Flush(); - File::Redim(elem * sizeof(T)); + MFile::Redim(elem * sizeof(T)); n_elements = elem; } diff --git a/apps/nexus/voronoichain.cpp b/apps/nexus/voronoichain.cpp index 07b29dda..b3e02a08 100644 --- a/apps/nexus/voronoichain.cpp +++ b/apps/nexus/voronoichain.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.19 2004/11/03 16:31:38 ponchio +Trying to fix big patches. + Revision 1.18 2004/10/30 20:17:03 ponchio Fixed big patches problem. @@ -159,6 +162,8 @@ bool VoronoiChain::Optimize(int mean, VoronoiPartition &part, vector &counts, bool join) { + + //remove small or really big patches. unsigned int failed = 0; vector seeds; @@ -233,8 +238,10 @@ bool VoronoiChain::Optimize(int mean, VoronoiPartition &part, return failed == 0; } -void VoronoiChain::Init(Crude &crude, float scaling, int steps) { - unsigned int f_cells = crude.Faces() / mean_size; +void VoronoiChain::Init(VFile &baricenters, + float scaling, int steps) { + + unsigned int f_cells = baricenters.Size() / mean_size; unsigned int c_cells = (unsigned int)(scaling * f_cells); levels.push_back(VoronoiPartition()); @@ -244,23 +251,22 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { srand(0); - float fine_vmean = mean_size/2.0f; - float coarse_vmean = (mean_size/scaling)/2.0f; + float coarse_vmean = mean_size/scaling; - for(unsigned int i = 0; i < crude.Vertices(); i++) { - int f = (int)(fine_vmean * rand()/(RAND_MAX + 1.0)); - int c = (int)(coarse_vmean * rand()/(RAND_MAX + 1.0)); + for(unsigned int i = 0; i < baricenters.Size(); i++) { + int f = (int)(mean_size * (float)rand()/(RAND_MAX + 1.0)); + int c = (int)(coarse_vmean * (float)rand()/(RAND_MAX + 1.0)); if(f == 2) { - Point3f &point = crude.GetVertex(i); + Point3f &point = baricenters[i]; fine.push_back(point); } if(c == 2) { - Point3f &point = crude.GetVertex(i); + Point3f &point = baricenters[i]; coarse.push_back(point); } } //TODO! Check for duplicates (use the closest :P) - //cerr << "fine_seeds.size: " << fine.size() << endl; + // cerr << "fine_seeds.size: " << fine.size() << endl; //cerr << "coarse_seeds.size: " << coarse.size() << endl; fine.Init(); coarse.Init(); @@ -277,18 +283,18 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { centroids.resize(fine.size(), Point3f(0, 0, 0)); counts.resize(fine.size(), 0); - report.Init(crude.Vertices()); - for(unsigned int v = 0; v < crude.Vertices(); v++) { + report.Init(baricenters.Size()); + for(unsigned int v = 0; v < baricenters.Size(); v++) { report.Step(v); - unsigned int target = fine.Locate(crude.vert[v]); - centroids[target] += crude.vert[v]; + unsigned int target = fine.Locate(baricenters[v]); + centroids[target] += baricenters[v]; counts[target]++; } if(step == steps-1) { - if(!Optimize(fine_vmean, fine, centroids, counts, false)) + if(!Optimize(mean_size, fine, centroids, counts, false)) step--; } else - Optimize(fine_vmean, fine, centroids, counts, true); + Optimize(mean_size, fine, centroids, counts, true); } cerr << "Optimized (fine)!\n"; //here goes some optimization pass. @@ -302,23 +308,23 @@ void VoronoiChain::Init(Crude &crude, float scaling, int steps) { counts.resize(coarse.size(), 0); //radius.resize(coarse.size(), 0); - report.Init(crude.Vertices()); - for(unsigned int v = 0; v < crude.Vertices(); v++) { + report.Init(baricenters.Size()); + for(unsigned int v = 0; v < baricenters.Size(); v++) { if(v & 0xffff) report.Step(v); unsigned int ctarget = 0xffffffff; - ctarget = coarse.Locate(crude.vert[v]); + ctarget = coarse.Locate(baricenters[v]); // float dist; // coarse.Closest(crude.vert[v], ctarget, dist); assert(ctarget != 0xffffffff); - centroids[ctarget] += crude.vert[v]; + centroids[ctarget] += baricenters[v]; counts[ctarget]++; //if(dist > radius[ctarget]) radius[ctarget] = dist; } if(step == steps-1) { - if(!Optimize(coarse_vmean, coarse, centroids, counts, false)) + if(!Optimize((int)coarse_vmean, coarse, centroids, counts, false)) step --; } else - Optimize(coarse_vmean, coarse, centroids, counts, true); + Optimize((int)coarse_vmean, coarse, centroids, counts, true); } cerr << "Optimized coarse!\n"; } @@ -329,12 +335,12 @@ unsigned int VoronoiChain::Locate(unsigned int level, } //TODO move this to nxsbuild -void VoronoiChain::RemapFaces(Crude &crude, +void VoronoiChain::RemapFaces(VFile &baricenters, VFile &face_remap, vector &patch_faces, float scaling, int steps) { - Init(crude, scaling, steps); + Init(baricenters, scaling, steps); //TODO: improve quality of patches and implement threshold. typedef map, unsigned int> FragIndex; @@ -345,8 +351,8 @@ void VoronoiChain::RemapFaces(Crude &crude, unsigned int totpatches = 0; Point3f bari; - for(unsigned int i = 0; i < crude.Faces(); i++) { - bari = crude.GetBari(i); + for(unsigned int i = 0; i < baricenters.Size(); i++) { + bari = baricenters[i]; unsigned int fine = Locate(0, bari); unsigned int coarse = Locate(1, bari); @@ -485,10 +491,10 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset, } } if(step == steps-1) { - if(!Optimize(coarse_vmean, coarse, centroids, counts, false)) + if(!Optimize((int)coarse_vmean, coarse, centroids, counts, false)) step--; } else - Optimize(coarse_vmean, coarse, centroids, counts, true); + Optimize((int)coarse_vmean, coarse, centroids, counts, true); } newfragments.clear(); diff --git a/apps/nexus/voronoichain.h b/apps/nexus/voronoichain.h index cbe80398..1102b833 100644 --- a/apps/nexus/voronoichain.h +++ b/apps/nexus/voronoichain.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.5 2004/10/30 20:17:03 ponchio +Fixed big patches problem. + Revision 1.4 2004/09/30 00:27:42 ponchio Lot of changes. Backup. @@ -49,7 +52,6 @@ First draft. #include "pchain.h" #include "pvoronoi.h" -#include "crude.h" #include "nexus.h" #include "vfile.h" @@ -67,9 +69,10 @@ class VoronoiChain: public PChain { mean_size(mean_s), min_size(min_s), max_size(max_s) {} virtual ~VoronoiChain() {} - void Init(Crude &crude, float scaling, int steps); + void Init(VFile &baricenters, float scaling, int steps); virtual unsigned int Locate(unsigned int level, const vcg::Point3f &p); - void RemapFaces(Crude &crude, VFile &face_remap, + void RemapFaces(VFile &baricenters, + VFile &face_remap, std::vector &patch_faces, float scaling, int steps); diff --git a/apps/nexus/voronoinxs.cpp b/apps/nexus/voronoinxs.cpp index 114aaaec..98b8192d 100644 --- a/apps/nexus/voronoinxs.cpp +++ b/apps/nexus/voronoinxs.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.21 2004/11/03 16:31:38 ponchio +Trying to fix big patches. + Revision 1.20 2004/10/30 20:17:03 ponchio Fixed big patches problem. @@ -107,18 +110,17 @@ using namespace std; #include "fragment.h" #include "nxsbuild.h" #include "watch.h" +#include "nxsdispatcher.h" using namespace vcg; using namespace nxs; void BuildFragment(Nexus &nexus, VoronoiPartition &part, set &patches, - Nexus::Update &update, Fragment &fragment); void SaveFragment(Nexus &nexus, VoronoiChain &chain, - unsigned int level, - Nexus::Update &update, + Fragment &fragin, Fragment &fragout); void ReverseHistory(vector &history); @@ -126,6 +128,9 @@ void ReverseHistory(vector &history); void TestBorders(Nexus &nexus); void TestPatches(Nexus &nexus); +unsigned int current_level; +vector patch_levels; + int main(int argc, char *argv[]) { Decimation decimation = CLUSTER; @@ -258,13 +263,24 @@ int main(int argc, char *argv[]) { return -1; } + VFile baricenters; + if(!baricenters.Create(output + string(".bvr"))) { + cerr << "Could not create temporary baricenters file\n"; + return -1; + } + baricenters.Resize(crude.Faces()); + + //TODO use some smarter rule :P + for(unsigned int i = 0; i < crude.Faces(); i++) { + baricenters[i] = crude.GetBari(i); + } /* BUILDING FIRST LEVEL */ //Remapping faces and vertices using level 0 and 1 of the chain cerr << "Remapping faces.\n"; vector patch_faces; - vchain.RemapFaces(crude, face_remap, patch_faces, + vchain.RemapFaces(baricenters, face_remap, patch_faces, scaling, optimization_steps); cerr << "Remapping vertices.\n"; @@ -274,6 +290,8 @@ int main(int argc, char *argv[]) { if(stop_after_remap) return 0; + + cerr << "Allocating space\n"; //allocate chunks for patches and copy faces (absoklute indexing) into them. NexusAllocate(crude, nexus, face_remap, patch_faces, patch_verts); @@ -282,12 +300,20 @@ int main(int argc, char *argv[]) { //insert vertices and remap faces, prepare borders NexusFill(crude, nexus, vert_remap, border_remap); - // NexusFixBorder(nexus, border_remap); + //Now face_remap, vert_remap, border_remap can be deleted! + face_remap.Delete(); + vert_remap.Delete(); + border_remap.Delete(); + baricenters.Delete(); + + //filling history Nexus::Update update; - for(unsigned int i = 0; i < nexus.index.size(); i++) + for(unsigned int i = 0; i < nexus.index.size(); i++) { update.created.push_back(i); + patch_levels.push_back(0); + } nexus.history.push_back(update); //unify vertices otherwise you may get cracks. @@ -297,9 +323,15 @@ int main(int argc, char *argv[]) { /* BUILDING OTHER LEVELS */ Report report; + Dispatcher dispatcher(&nexus, &vchain); + if(!dispatcher.Init("servers.txt")) { + cerr << "Could not parse server file: " << "servers.txt" + << " proceding locally\n"; + } unsigned int oldoffset = 0; for(unsigned int level = 1; level < max_level; level++) { + current_level = level; cerr << "Level: " << level << endl; unsigned int newoffset = nexus.index.size(); @@ -307,20 +339,20 @@ int main(int argc, char *argv[]) { report.Init(vchain.oldfragments.size(), 1); unsigned int fcount = 0; - vector level_history; map >::iterator fragment; for(fragment = vchain.oldfragments.begin(); fragment != vchain.oldfragments.end(); fragment++) { report.Step(fcount++); - - - Fragment fragin; - BuildFragment(nexus, vchain.levels[level+1], (*fragment).second, - update, fragin); + Fragment *fragin = new Fragment; + BuildFragment(nexus, vchain.levels[level+1], + (*fragment).second, *fragin); + dispatcher.SendFragment(fragin); + /* + //this can be executed on a remote host //TODO move this part to remote.... vector newvert; @@ -336,19 +368,19 @@ int main(int argc, char *argv[]) { fragout.id = fragin.id; fragout.seeds = fragin.seeds; fragout.seeds_id = fragin.seeds_id; - Split(fragout, newvert, newface, newbord, vchain.levels[level+1]); + Split(fragout, newvert, newface, newbord);//, vchain.levels[level+1]); - - - - - SaveFragment(nexus, vchain, level, update, fragout); - level_history.push_back(update); + + SaveFragment(nexus, vchain, fragin, fragout); + */ + dispatcher.processmsgs(); + } + //TODO porcata!!!! + while(dispatcher.frags.size()) { + dispatcher.processmsgs(); } - report.Finish(); - for(unsigned int i = 0; i < level_history.size(); i++) - nexus.history.push_back(level_history[i]); + report.Finish(); if(vchain.oldfragments.size() == 1) break; @@ -379,8 +411,8 @@ int main(int argc, char *argv[]) { void BuildFragment(Nexus &nexus, VoronoiPartition &part, set &patches, - Nexus::Update &update, Fragment &fragment) { + set::iterator f; for(f = patches.begin(); f != patches.end(); f++) { fragment.pieces.push_back(NxsPatch()); @@ -396,42 +428,54 @@ void BuildFragment(Nexus &nexus, VoronoiPartition &part, 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()) + if(!link.IsNull() && patch_levels[link.end_patch] == current_level-1) nxs.bord.push_back(link); } } - update.created.clear(); - update.erased.clear(); - - set &fcells = patches; - set::iterator s; - for(s = fcells.begin(); s != fcells.end(); s++) { - update.erased.push_back(*s); + set seeds; + vector nears; + vector dists; + int nnears = 10; + if(part.size() < 10) nnears = part.size(); + for(f = patches.begin(); f != patches.end(); f++) { + Point3f ¢er = nexus.index[*f].sphere.Center(); + part.Closest(center, nnears, nears, dists); + for(int i = 0; i < nnears; i++) + seeds.insert(nears[i]); } - - //copy all seeds! //TODO copy only closest ones - for(unsigned int i = 0; i < part.size(); i++) { - fragment.seeds.push_back(part[i]); - fragment.seeds_id.push_back(i); + for(f = seeds.begin(); f != seeds.end(); f++) { + Point3f &p = part[*f]; + fragment.seeds.push_back(p); + fragment.seeds_id.push_back(*f); } } void SaveFragment(Nexus &nexus, VoronoiChain &chain, - unsigned int level, - Nexus::Update &update, + Fragment &fragin, Fragment &fragout) { + + + set orig_patches; + + Nexus::Update update; + for(unsigned int i = 0; i < fragin.pieces.size(); i++) { + NxsPatch &patch = fragin.pieces[i]; + update.erased.push_back(patch.patch); + orig_patches.insert(patch.patch); + } vector patch_remap; patch_remap.resize(fragout.pieces.size()); - + for(unsigned int i = 0; i < fragout.pieces.size(); i++) { NxsPatch &patch = fragout.pieces[i]; //TODO detect best parameter below for bordersize... unsigned int patch_idx = nexus.AddPatch(patch.vert.size(), patch.face.size()/3, 6 * patch.bord.size()); + patch_levels.push_back(current_level); Nexus::PatchInfo &entry = nexus.index[patch_idx]; entry.error = fragout.error; @@ -455,19 +499,59 @@ void SaveFragment(Nexus &nexus, VoronoiChain &chain, entry.sphere.Add(outpatch.vert[v]); nexus.sphere.Add(outpatch.vert[v]); } - //remap borders + + + vector actual; + //remap internal borders for(unsigned int i = 0; i < outpatch.bord.size(); i++) { Link &link = outpatch.bord[i]; - if(link.end_patch >= (1<<31)) //internal + if(link.end_patch >= (1<<31)) { //internal link.end_patch = patch_remap[link.end_patch - (1<<31)]; - else { //if external add the reverse border - Border rborder = nexus.GetBorder(link.end_patch); + actual.push_back(link); + } + } + //TODO not efficient! + //processing external borders + for(unsigned int i = 0; i < outpatch.bord.size(); i++) { + Link &link = outpatch.bord[i]; + if(link.end_patch >= (1<<31)) continue; + unsigned short &start_vert = link.start_vert; + unsigned int &start_patch = patch_idx; + + Border cborder = nexus.GetBorder(link.end_patch); + for(unsigned int k = 0; k < cborder.Size(); k++) { + Link &clink = cborder[k]; + if(clink.start_vert != link.end_vert) continue; + if(patch_levels[clink.end_patch] < current_level-1) continue; + + unsigned short &end_vert = clink.end_vert; + unsigned int &end_patch = clink.end_patch; + + Link newlink; + + newlink.start_vert = start_vert; + newlink.end_vert = end_vert; + newlink.end_patch = end_patch; + + actual.push_back(newlink); + // nexus.AddBorder(start_patch, newlink); + + newlink.start_vert = end_vert; + newlink.end_vert = start_vert; + newlink.end_patch = start_patch; + + nexus.AddBorder(end_patch, newlink); + + + + /* Border rborder = nexus.GetBorder(clink.end_patch); + unsigned int pos = rborder.Size(); if(nexus.borders.ResizeBorder(link.end_patch, pos+1)) { rborder = nexus.GetBorder(link.end_patch); } - + assert(rborder.Size() < rborder.Available()); assert(rborder.Available() > pos); @@ -475,17 +559,23 @@ void SaveFragment(Nexus &nexus, VoronoiChain &chain, newlink.start_vert = link.end_vert; newlink.end_vert = link.start_vert; newlink.end_patch = patch_idx; - rborder[pos] = newlink; + rborder[pos] = newlink;*/ } } Border border = nexus.GetBorder(patch_idx); - assert(border.Available() >= outpatch.bord.size()); + if(nexus.borders.ResizeBorder(patch_idx, actual.size())) { + border = nexus.GetBorder(patch_idx); + } + memcpy(&(border[0]), &(actual[0]), + actual.size() * sizeof(Link)); + /* assert(border.Available() >= outpatch.bord.size()); if(nexus.borders.ResizeBorder(patch_idx, outpatch.bord.size())) { border = nexus.GetBorder(patch_idx); } memcpy(&(border[0]), &(outpatch.bord[0]), - outpatch.bord.size() * sizeof(Link)); + outpatch.bord.size() * sizeof(Link)); */ } + nexus.history.push_back(update); } void ReverseHistory(vector &history) {