Using baricenters... lotsa changes.
This commit is contained in:
parent
b23413ecb2
commit
75c9f2e194
|
@ -0,0 +1,107 @@
|
|||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
|
||||
#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] << " <input> <output> [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;
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ class File {
|
|||
|
||||
bool IsReadOnly() { return readonly; }
|
||||
|
||||
static void Delete(const std::string &filename);
|
||||
protected:
|
||||
|
||||
#ifdef WIN32
|
||||
|
|
|
@ -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<BigLink> newborders;
|
||||
for(unsigned int i = 0; i < in.pieces.size(); i++) {
|
||||
unsigned int offset = offsets[i];
|
||||
vector<Link> &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<Point3f> &vert = in.pieces[i].vert;
|
||||
vector<unsigned short> &face = in.pieces[i].face;
|
||||
vector<Link> &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<BigLink>::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<Point3f> &newvert,
|
||||
vector<unsigned int> &newface,
|
||||
vector<BigLink> &newbord,
|
||||
VoronoiPartition &part) {
|
||||
vector<BigLink> &newbord) {
|
||||
|
||||
unsigned int nseeds = out.seeds.size();
|
||||
vector<Point3f> &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<Point3f> newseeds;
|
||||
vector<unsigned int> 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;
|
||||
|
|
|
@ -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<vcg::Point3f> vert;
|
||||
std::vector<unsigned short> face;
|
||||
//when this is an outfragment link.end_patch is (1<<31) + end_patch
|
||||
//when it is an internal border!
|
||||
|
||||
std::vector<Link> bord;
|
||||
|
||||
void Write(pt::outstm *out);
|
||||
|
@ -52,8 +53,8 @@ class Fragment {
|
|||
|
||||
std::vector<NxsPatch> 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<vcg::Point3f> &newvert,
|
||||
std::vector<unsigned int> &newface,
|
||||
std::vector<BigLink> &newbord,
|
||||
VoronoiPartition &part);
|
||||
std::vector<BigLink> &newbord);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
#include <ptypes/pinet.h>
|
||||
|
||||
class NxsClientPool {
|
||||
vector<NxsClient> clients;
|
||||
void Push(NxsRequest *request);
|
||||
};
|
||||
|
||||
class NxsClient: public pt::ipstream {
|
||||
public:
|
||||
queue<NxsRequest *> 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
#include "nxsdispatcher.h"
|
||||
#include "fragment.h"
|
||||
#include "decimate.h"
|
||||
#include <iostream>
|
||||
#include <ptypes/ptypes.h>
|
||||
|
||||
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<Point3f> newvert;
|
||||
vector<unsigned int> newface;
|
||||
vector<BigLink> 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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
#include <ptypes/pinet.h>
|
||||
#include <ptypes/pasync.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
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<Server *> servers;
|
||||
std::map<int, FragIO *> 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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#include <iostream>
|
||||
#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] << " <side>\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;
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
#include <ptypes/ptime.h>
|
||||
#include <ptypes/pinet.h>
|
||||
#include <ptypes/pasync.h>
|
||||
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<Point3f> newvert;
|
||||
vector<unsigned int> newface;
|
||||
vector<BigLink> 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;
|
||||
}
|
|
@ -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<unsigned int> &face_remap,
|
||||
virtual void RemapFaces(VFile<vcg::Point3f> &baricenters,
|
||||
VFile<unsigned int> &face_remap,
|
||||
std::vector<unsigned int> &patch_faces,
|
||||
float scaling, int steps) = 0;
|
||||
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.4 2004/10/01 15:59:52 ponchio
|
||||
Added include <assert.h>
|
||||
|
||||
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();
|
||||
|
|
|
@ -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 <assert.h>
|
||||
#include <map>
|
||||
|
@ -94,7 +97,7 @@ Created
|
|||
|
||||
namespace nxs {
|
||||
|
||||
template <class T> class VFile: public File {
|
||||
template <class T> class VFile: public MFile {
|
||||
public:
|
||||
|
||||
struct Buffer {
|
||||
|
@ -138,7 +141,7 @@ template <class T> 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 T> 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 T> 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 T> class VFile: public File {
|
|||
|
||||
void Resize(unsigned int elem) {
|
||||
Flush();
|
||||
File::Redim(elem * sizeof(T));
|
||||
MFile::Redim(elem * sizeof(T));
|
||||
n_elements = elem;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<unsigned int> &counts,
|
||||
bool join) {
|
||||
|
||||
|
||||
|
||||
//remove small or really big patches.
|
||||
unsigned int failed = 0;
|
||||
vector<Point3f> 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<Point3f> &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<Point3f> &baricenters,
|
||||
VFile<unsigned int> &face_remap,
|
||||
vector<unsigned int> &patch_faces,
|
||||
float scaling, int steps) {
|
||||
|
||||
Init(crude, scaling, steps);
|
||||
Init(baricenters, scaling, steps);
|
||||
|
||||
//TODO: improve quality of patches and implement threshold.
|
||||
typedef map<pair<unsigned int, unsigned int>, 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();
|
||||
|
|
|
@ -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<vcg::Point3f> &baricenters, float scaling, int steps);
|
||||
virtual unsigned int Locate(unsigned int level, const vcg::Point3f &p);
|
||||
void RemapFaces(Crude &crude, VFile<unsigned int> &face_remap,
|
||||
void RemapFaces(VFile<vcg::Point3f> &baricenters,
|
||||
VFile<unsigned int> &face_remap,
|
||||
std::vector<unsigned int> &patch_faces, float scaling,
|
||||
int steps);
|
||||
|
||||
|
|
|
@ -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<unsigned int> &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<Nexus::Update> &history);
|
||||
|
@ -126,6 +128,9 @@ void ReverseHistory(vector<Nexus::Update> &history);
|
|||
void TestBorders(Nexus &nexus);
|
||||
void TestPatches(Nexus &nexus);
|
||||
|
||||
unsigned int current_level;
|
||||
vector<unsigned int> patch_levels;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
Decimation decimation = CLUSTER;
|
||||
|
@ -258,13 +263,24 @@ int main(int argc, char *argv[]) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
VFile<Point3f> 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<unsigned int> 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<Nexus::Update> level_history;
|
||||
map<unsigned int, set<unsigned int> >::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<Point3f> 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<unsigned int> &patches,
|
||||
Nexus::Update &update,
|
||||
Fragment &fragment) {
|
||||
|
||||
set<unsigned int>::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<unsigned int> &fcells = patches;
|
||||
set<unsigned int>::iterator s;
|
||||
for(s = fcells.begin(); s != fcells.end(); s++) {
|
||||
update.erased.push_back(*s);
|
||||
set<unsigned int> seeds;
|
||||
vector<int> nears;
|
||||
vector<float> 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<unsigned int> 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<unsigned int> 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<Link> 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<Nexus::Update> &history) {
|
||||
|
|
Loading…
Reference in New Issue