2004-07-02 15:00:02 +02:00
|
|
|
#include <iostream>
|
|
|
|
#include "nexus.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace vcg;
|
|
|
|
using namespace nxs;
|
|
|
|
|
|
|
|
Nexus::Nexus(): index_file(NULL) {}
|
|
|
|
Nexus::~Nexus() {
|
|
|
|
Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Nexus::Create(const string &file) {
|
|
|
|
index_file = fopen((file + ".nxs").c_str(), "wb+");
|
|
|
|
if(!index_file) {
|
|
|
|
cerr << "Could not create file: " << file << ".nxs\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
totvert = 0;
|
|
|
|
totface = 0;
|
|
|
|
sphere = Sphere3f();
|
|
|
|
|
|
|
|
//Important: chunk_size must be 1 so that i can use Region in VFile.
|
|
|
|
if(!patches.Create(file + ".nxp", 1)) {
|
|
|
|
cerr << "Could not create file: " << file << ".nxp" << endl;
|
|
|
|
return false;
|
|
|
|
}
|
2004-07-04 16:26:46 +02:00
|
|
|
if(!borders.Create(file + ".nxb", 1)) {
|
|
|
|
cerr << "Could not create file: " << file << ".nxb" << endl;
|
2004-07-02 15:00:02 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Nexus::Load(const string &file) {
|
|
|
|
index_file = fopen((file + ".nxs").c_str(), "rb+");
|
|
|
|
if(!index_file) return false;
|
|
|
|
|
|
|
|
unsigned int readed;
|
|
|
|
readed = fread(&totvert, sizeof(unsigned int), 1, index_file);
|
|
|
|
if(!readed) return false;
|
|
|
|
readed = fread(&totface, sizeof(unsigned int), 1, index_file);
|
|
|
|
if(!readed) return false;
|
|
|
|
readed = fread(&sphere, sizeof(Sphere3f), 1, index_file);
|
|
|
|
if(!readed) return false;
|
|
|
|
|
|
|
|
unsigned int size; //size of index
|
|
|
|
readed = fread(&size, sizeof(unsigned int), 1, index_file);
|
|
|
|
if(!readed) return false;
|
|
|
|
|
|
|
|
index.resize(size);
|
|
|
|
readed = fread(&index[0], sizeof(Entry), size, index_file);
|
|
|
|
if(readed != size) return false;
|
|
|
|
|
2004-07-04 16:26:46 +02:00
|
|
|
if(!patches.Load(file + ".nxp", 1)) return false;
|
|
|
|
if(!borders.Load(file + ".nxb", 1)) return false;
|
2004-07-02 15:00:02 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Nexus::Close() {
|
|
|
|
if(!index_file) return;
|
|
|
|
rewind(index_file);
|
|
|
|
|
|
|
|
fwrite(&totvert, sizeof(unsigned int), 1, index_file);
|
|
|
|
fwrite(&totface, sizeof(unsigned int), 1, index_file);
|
|
|
|
fwrite(&sphere, sizeof(Sphere3f), 1, index_file);
|
|
|
|
|
|
|
|
unsigned int size = index.size(); //size of index
|
|
|
|
fwrite(&size, sizeof(unsigned int), 1, index_file);
|
2004-07-30 15:18:25 +02:00
|
|
|
fwrite(&(index[0]), sizeof(Entry), size, index_file);
|
2004-07-02 15:00:02 +02:00
|
|
|
fclose(index_file);
|
2004-07-30 15:18:25 +02:00
|
|
|
index_file = NULL;
|
|
|
|
|
2004-07-02 15:00:02 +02:00
|
|
|
patches.Close();
|
|
|
|
borders.Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
Patch Nexus::GetPatch(unsigned int patch) {
|
|
|
|
Entry &entry = index[patch];
|
2004-07-04 16:26:46 +02:00
|
|
|
Chunk *start = patches.GetRegion(entry.patch_start, entry.patch_size);
|
|
|
|
return Patch(start, entry.nvert, entry.nface);
|
|
|
|
}
|
|
|
|
|
|
|
|
Border Nexus::GetBorder(unsigned int patch) {
|
|
|
|
Entry &entry = index[patch];
|
|
|
|
Link *start = borders.GetRegion(entry.border_start, entry.border_size);
|
|
|
|
return Border(start, entry.border_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int Nexus::AddPatch(unsigned int nvert, unsigned int nface,
|
|
|
|
unsigned int nbord) {
|
|
|
|
Entry entry;
|
|
|
|
entry.patch_start = patches.Size();
|
|
|
|
entry.patch_size = Patch::ChunkSize(nvert, nface);
|
|
|
|
entry.border_start = borders.Size();
|
|
|
|
entry.border_size = nbord;
|
|
|
|
entry.nvert = nvert;
|
|
|
|
entry.nface = nface;
|
|
|
|
|
|
|
|
patches.Resize(patches.Size() + entry.patch_size);
|
|
|
|
borders.Resize(borders.Size() + nbord);
|
|
|
|
index.push_back(entry);
|
2004-08-27 02:38:34 +02:00
|
|
|
totvert += nvert;
|
|
|
|
totface += nface;
|
2004-07-04 16:26:46 +02:00
|
|
|
return index.size() -1;
|
|
|
|
}
|
|
|
|
|
2004-08-27 02:38:34 +02:00
|
|
|
void Nexus::Join(const std::set<unsigned int> &patches,
|
2004-07-05 17:49:39 +02:00
|
|
|
std::vector<Point3f> &newvert,
|
2004-07-04 16:26:46 +02:00
|
|
|
std::vector<unsigned int> &newface,
|
2004-07-05 17:49:39 +02:00
|
|
|
std::vector<Link> &newbord) {
|
2004-07-04 16:26:46 +02:00
|
|
|
|
|
|
|
map<unsigned int, vector<unsigned int> > remap;
|
|
|
|
|
2004-08-27 02:38:34 +02:00
|
|
|
set<unsigned int>::const_iterator i;
|
2004-07-04 16:26:46 +02:00
|
|
|
for(i = patches.begin(); i != patches.end(); i++) {
|
|
|
|
unsigned int patch = *i;
|
|
|
|
Nexus::Entry &entry = index[patch];
|
|
|
|
remap[*i].resize(entry.nvert, 0xffffffff);
|
|
|
|
}
|
|
|
|
unsigned int vcount = 0;
|
|
|
|
unsigned int fcount = 0;
|
|
|
|
unsigned int bcount = 0;
|
|
|
|
for(i = patches.begin(); i != patches.end(); i++) {
|
|
|
|
unsigned int patch = *i;
|
|
|
|
Nexus::Entry &entry = index[patch];
|
|
|
|
fcount += entry.nface;
|
|
|
|
assert(fcount < 0xffff);
|
|
|
|
for(unsigned int k = 0; k < entry.nvert; k++) {
|
|
|
|
if(remap[patch][k] == 0xffffffff) { //first time
|
|
|
|
remap[patch][k] = vcount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Border border = GetBorder(patch);
|
|
|
|
for(unsigned int k = 0; k < border.Size(); k++) {
|
|
|
|
Link &link = border[k];
|
|
|
|
if(!remap.count(link.end_patch)) {
|
|
|
|
bcount++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(remap[link.end_patch][link.end_vert] == 0xffffffff) { //first time
|
|
|
|
remap[link.end_patch][link.end_vert] = remap[patch][link.start_vert];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newvert.resize(vcount);
|
|
|
|
newface.resize(fcount*3);
|
|
|
|
newbord.resize(bcount);
|
|
|
|
|
|
|
|
fcount = 0;
|
|
|
|
bcount = 0;
|
|
|
|
for(i = patches.begin(); i != patches.end(); i++) {
|
|
|
|
Patch patch = GetPatch(*i);
|
|
|
|
Border border = GetBorder(*i);
|
|
|
|
vector<unsigned int> &vmap = remap[*i];
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < patch.VertSize(); i++)
|
|
|
|
newvert[vmap[i]] = patch.Vert(i);
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < patch.FaceSize(); i++) {
|
|
|
|
for(int k = 0; k < 3; k++) {
|
|
|
|
newface[3*fcount + k] = vmap[patch.Face(i)[k]];
|
|
|
|
}
|
|
|
|
fcount++;
|
|
|
|
}
|
|
|
|
for(unsigned int i = 0; i < border.Size(); i++) {
|
|
|
|
Link &link = border[i];
|
|
|
|
if(remap.count(link.end_patch)) continue;
|
|
|
|
Link newlink = link;
|
|
|
|
newlink.start_vert = vmap[link.start_vert];
|
|
|
|
newbord[bcount++] = newlink;
|
|
|
|
}
|
|
|
|
}
|
2004-07-05 17:49:39 +02:00
|
|
|
/* unsigned int newentry = AddPatch(vcount, fcount, bcount);
|
2004-07-04 16:26:46 +02:00
|
|
|
Patch newpatch = GetPatch(newentry);
|
|
|
|
Border newborder = GetBorder(newentry);
|
|
|
|
|
|
|
|
memcpy(newpatch.VertBegin(), &(newvert)[0],
|
|
|
|
newvert.size() * sizeof(Point3f));
|
|
|
|
|
|
|
|
memcpy(newpatch.FaceBegin(), &(newface)[0],
|
|
|
|
newface.size() * sizeof(unsigned short));
|
|
|
|
|
|
|
|
memcpy(&(newborder[0]), &(newbord[0]),
|
2004-07-05 17:49:39 +02:00
|
|
|
newbord.size() * sizeof(Link));*/
|
|
|
|
return;
|
2004-07-02 15:00:02 +02:00
|
|
|
}
|