Erased.
This commit is contained in:
parent
bcbccb7801
commit
796b5bad89
|
@ -1,329 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
* VCGLib o o *
|
|
||||||
* Visual and Computer Graphics Library o o *
|
|
||||||
* _ O _ *
|
|
||||||
* Copyright(C) 2004 \/)\/ *
|
|
||||||
* Visual Computing Lab /\/| *
|
|
||||||
* ISTI - Italian National Research Council | *
|
|
||||||
* \ *
|
|
||||||
* All rights reserved. *
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
|
||||||
* for more details. *
|
|
||||||
* *
|
|
||||||
****************************************************************************/
|
|
||||||
/****************************************************************************
|
|
||||||
History
|
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
|
||||||
Revision 1.3 2004/07/15 14:32:49 ponchio
|
|
||||||
Debug.
|
|
||||||
|
|
||||||
Revision 1.2 2004/07/05 15:49:39 ponchio
|
|
||||||
Windows (DevCpp, mingw) port.
|
|
||||||
|
|
||||||
Revision 1.1 2004/07/04 15:30:00 ponchio
|
|
||||||
Changed directory structure.
|
|
||||||
|
|
||||||
Revision 1.3 2004/07/04 14:28:05 ponchio
|
|
||||||
Finito e debuggato
|
|
||||||
|
|
||||||
Revision 1.2 2004/07/02 17:42:12 ponchio
|
|
||||||
Backup.
|
|
||||||
|
|
||||||
Revision 1.1 2004/07/02 13:03:01 ponchio
|
|
||||||
Created
|
|
||||||
|
|
||||||
|
|
||||||
****************************************************************************/
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include <set> //DEBUG
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "nexus.h"
|
|
||||||
#include "crude.h"
|
|
||||||
#include "vert_remap.h"
|
|
||||||
#include "vfile.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace vcg;
|
|
||||||
using namespace nxs;
|
|
||||||
|
|
||||||
|
|
||||||
struct RemapLink {
|
|
||||||
unsigned int rel_vert;
|
|
||||||
unsigned int patch;
|
|
||||||
unsigned int abs_vert;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
if(argc <= 2) {
|
|
||||||
cerr << "Usage: " << argv[0] << " <crude input> <nexus output>\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
Crude crude;
|
|
||||||
if(!crude.Load(argv[1])) {
|
|
||||||
cerr << "Could not load crude:" << argv[1] << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
VertRemap vert_remap;
|
|
||||||
if(!vert_remap.Load(argv[1])) {
|
|
||||||
cerr << "Could not load vert_remap files: " << argv[1] << "\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
VFile<unsigned int> face_remap;
|
|
||||||
if(!face_remap.Load(argv[1] + string(".rmf"))) {
|
|
||||||
cerr << "Could not load face_remap file: " << argv[1] << ".frm\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VFile<RemapLink> border_remap;
|
|
||||||
if(!border_remap.Create(argv[1] + string(".tmp"))) {
|
|
||||||
cerr << "Could not create temporary border remap file\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Nexus nexus;
|
|
||||||
if(!nexus.Create(argv[2])) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//lets count faces,
|
|
||||||
vector<unsigned int> patch_faces;
|
|
||||||
unsigned int totface = 0;
|
|
||||||
unsigned int totvert = 0;
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < face_remap.Size(); i++) {
|
|
||||||
unsigned int patch = face_remap[i];
|
|
||||||
assert(patch != 0xffffffff);
|
|
||||||
if(patch >= patch_faces.size())
|
|
||||||
patch_faces.resize(patch+1, 0);
|
|
||||||
patch_faces[patch]++;
|
|
||||||
totface++;
|
|
||||||
}
|
|
||||||
|
|
||||||
cerr << "Vertremap size: " << vert_remap.Size() << endl;
|
|
||||||
|
|
||||||
|
|
||||||
//lets count vertices
|
|
||||||
vector<unsigned int> patch_verts;
|
|
||||||
patch_verts.resize(patch_faces.size(), 0);
|
|
||||||
|
|
||||||
unsigned int unreferenced = 0;
|
|
||||||
// counting vertices using border_size for number of vertices
|
|
||||||
for(unsigned int i = 0; i < vert_remap.all.Size(); i++) {
|
|
||||||
unsigned int patch = vert_remap.all[i];
|
|
||||||
if(patch == 0xffffffff) {
|
|
||||||
unreferenced++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
assert(patch < patch_verts.size());
|
|
||||||
patch_verts[patch]++;
|
|
||||||
totvert++;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int totbord = 0;
|
|
||||||
VFile<MFHash::Bucket> &border = vert_remap.borders.buffer;
|
|
||||||
for(unsigned int i = 0; i < border.Size(); i++) {
|
|
||||||
MFHash::Bucket &bucket = border[i];
|
|
||||||
if(bucket.key == 0xffffffff) continue;
|
|
||||||
unsigned int patch = bucket.value;
|
|
||||||
assert(patch < patch_verts.size());
|
|
||||||
patch_verts[patch]++;
|
|
||||||
totbord++;
|
|
||||||
// nexus.totvert++; (?)
|
|
||||||
}
|
|
||||||
|
|
||||||
if(unreferenced)
|
|
||||||
cerr << "Warning: found " << unreferenced << " unreferenced vertices.\n";
|
|
||||||
|
|
||||||
cerr << "Triangles found: " << totface << endl;
|
|
||||||
cerr << "Vertex found: " << totvert << endl;
|
|
||||||
cerr << "Borders found: " << totbord << endl;
|
|
||||||
|
|
||||||
|
|
||||||
nexus.index.resize(patch_verts.size());
|
|
||||||
|
|
||||||
unsigned int totchunks = 0;
|
|
||||||
//now that we know various sizes, lets allocate space
|
|
||||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
|
||||||
Nexus::Entry &entry = nexus.index[i];
|
|
||||||
|
|
||||||
if(patch_faces[i] == 0 || patch_verts[i] == 0)
|
|
||||||
cerr << "Warning! Empty patch.\n";
|
|
||||||
|
|
||||||
entry.patch_start = totchunks;
|
|
||||||
entry.patch_size = Patch::ChunkSize(patch_verts[i], patch_faces[i]);
|
|
||||||
|
|
||||||
totchunks += entry.patch_size;
|
|
||||||
entry.border_start = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
nexus.patches.Resize(totchunks);
|
|
||||||
|
|
||||||
//now we sort the faces into the patches (but still using absolute indexing
|
|
||||||
//instead of relative indexing
|
|
||||||
for(unsigned int i = 0; i < crude.face.Size(); i++) {
|
|
||||||
Crude::Face &face = crude.face[i];
|
|
||||||
unsigned int npatch = face_remap[i];
|
|
||||||
|
|
||||||
Nexus::Entry &entry = nexus.index[npatch];
|
|
||||||
Patch patch = nexus.GetPatch(npatch);
|
|
||||||
if(entry.border_start == 0) { //first time we find patch
|
|
||||||
entry.border_start = 0xffffffff;
|
|
||||||
entry.nvert = patch_verts[npatch];
|
|
||||||
// patch.VertSize() = patch_verts[npatch];
|
|
||||||
entry.nface = 0;
|
|
||||||
// patch.FaceSize() = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Crude::Face *faces = (Crude::Face *)patch.VertBegin();
|
|
||||||
faces[entry.nface] = face;
|
|
||||||
entry.nface++;
|
|
||||||
// faces[patch.FaceSize()] = face;
|
|
||||||
// patch.FaceSize()++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//finally for every patch we collect the vertices
|
|
||||||
//and fill the patch.
|
|
||||||
//we need to remember start and size in border_remap;
|
|
||||||
// vector<unsigned int> border_start;
|
|
||||||
// vector<unsigned int> border_size;
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
|
||||||
Patch patch = nexus.GetPatch(i);
|
|
||||||
assert(patch.FaceSize() == patch_faces[i]);
|
|
||||||
|
|
||||||
Nexus::Entry &entry = nexus.index[i];
|
|
||||||
|
|
||||||
//make a copy of faces (we need to write there :P)
|
|
||||||
Crude::Face *faces = new Crude::Face[patch_faces[i]];
|
|
||||||
memcpy(faces, (Crude::Face *)patch.VertBegin(),
|
|
||||||
patch.FaceSize() * sizeof(Crude::Face));
|
|
||||||
|
|
||||||
//collect all vertices we need.
|
|
||||||
//TODO an hash_map would be faster?
|
|
||||||
unsigned int count = 0;
|
|
||||||
map<unsigned int, unsigned short> remap;
|
|
||||||
for(unsigned int k = 0; k < patch.FaceSize(); k++) {
|
|
||||||
Crude::Face &face = faces[k];
|
|
||||||
|
|
||||||
for(int j = 0; j < 3; j++) {
|
|
||||||
if(!remap.count(face[j])) {
|
|
||||||
assert(count < patch.VertSize());
|
|
||||||
Point3f &v = crude.vert[face[j]];
|
|
||||||
patch.VertBegin()[remap.size()] = v;
|
|
||||||
entry.sphere.Add(v);
|
|
||||||
remap[face[j]] = count++;
|
|
||||||
}
|
|
||||||
patch.FaceBegin()[k*3 + j] = remap[face[j]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(count == remap.size());
|
|
||||||
assert(entry.nvert == remap.size());
|
|
||||||
|
|
||||||
//record start of border:
|
|
||||||
entry.border_start = border_remap.Size();
|
|
||||||
|
|
||||||
//TODO hash_set?
|
|
||||||
set<unsigned int> border_patches;
|
|
||||||
map<unsigned int, unsigned short>::iterator m;
|
|
||||||
for(m = remap.begin(); m != remap.end(); m++) {
|
|
||||||
RemapLink link;
|
|
||||||
link.abs_vert = (*m).first;
|
|
||||||
link.rel_vert = (*m).second;
|
|
||||||
|
|
||||||
vert_remap.GetValues(link.abs_vert, border_patches);
|
|
||||||
assert(border_patches.size() >= 1);
|
|
||||||
if(border_patches.size() == 1) continue; //its not a border
|
|
||||||
|
|
||||||
set<unsigned int>::iterator s;
|
|
||||||
for(s = border_patches.begin(); s != border_patches.end(); s++) {
|
|
||||||
if((*s) == i) continue;
|
|
||||||
link.patch = *s;
|
|
||||||
border_remap.PushBack(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//and number of borders:
|
|
||||||
entry.border_size = border_remap.Size() - entry.border_start;
|
|
||||||
delete []faces;
|
|
||||||
}
|
|
||||||
//we can now update bounding sphere.
|
|
||||||
for(unsigned int i = 0; i < nexus.index.size(); i++)
|
|
||||||
nexus.sphere.Add(nexus.index[i].sphere);
|
|
||||||
|
|
||||||
//and last convert RemapLinks into Links
|
|
||||||
nexus.borders.Resize(border_remap.Size());
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
|
||||||
Nexus::Entry &local = nexus.index[i];
|
|
||||||
|
|
||||||
// K is the main iterator (where we write to in nexus.borders)
|
|
||||||
for(unsigned int k = local.border_start;
|
|
||||||
k < local.border_start + local.border_size; k++) {
|
|
||||||
|
|
||||||
RemapLink start_link = border_remap[k];
|
|
||||||
assert(start_link.rel_vert < local.nvert);
|
|
||||||
|
|
||||||
Nexus::Entry &remote = nexus.index[start_link.patch];
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
for(unsigned int j = remote.border_start;
|
|
||||||
j < remote.border_start + remote.border_size; j++) {
|
|
||||||
|
|
||||||
RemapLink end_link = border_remap[j];
|
|
||||||
assert(end_link.rel_vert < remote.nvert);
|
|
||||||
|
|
||||||
if(start_link.abs_vert == end_link.abs_vert &&
|
|
||||||
end_link.patch == i) { //found the match
|
|
||||||
assert(!found);
|
|
||||||
nexus.borders[k] = Link(start_link.rel_vert,
|
|
||||||
end_link.rel_vert, start_link.patch);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(nexus.borders[k].start_vert < local.nvert);
|
|
||||||
assert(found);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nexus.borders.Flush();
|
|
||||||
|
|
||||||
//Checking border consistency:
|
|
||||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
|
||||||
Border border = nexus.GetBorder(i);
|
|
||||||
Nexus::Entry &entry = nexus.index[i];
|
|
||||||
for(unsigned int k = 0; k < border.Size(); k++) {
|
|
||||||
Link &link = border[k];
|
|
||||||
if(link.start_vert >= entry.nvert) {
|
|
||||||
cerr << "K: " << k << endl;
|
|
||||||
cerr << "patch: " << i << " nvert: " << entry.nvert << " startv: "
|
|
||||||
<< link.start_vert << endl;
|
|
||||||
cerr << "bstart: " << entry.border_start
|
|
||||||
<< "bsize: " << entry.border_size << endl;
|
|
||||||
}
|
|
||||||
assert(link.end_patch < nexus.index.size());
|
|
||||||
assert(link.start_vert < entry.nvert);
|
|
||||||
Nexus::Entry &remote = nexus.index[link.end_patch];
|
|
||||||
assert(link.end_vert < remote.nvert);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
nexus.Close();
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,144 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
* VCGLib o o *
|
|
||||||
* Visual and Computer Graphics Library o o *
|
|
||||||
* _ O _ *
|
|
||||||
* Copyright(C) 2004 \/)\/ *
|
|
||||||
* Visual Computing Lab /\/| *
|
|
||||||
* ISTI - Italian National Research Council | *
|
|
||||||
* \ *
|
|
||||||
* All rights reserved. *
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
|
||||||
* for more details. *
|
|
||||||
* *
|
|
||||||
****************************************************************************/
|
|
||||||
/****************************************************************************
|
|
||||||
History
|
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
|
||||||
Revision 1.3 2004/07/15 14:32:49 ponchio
|
|
||||||
Debug.
|
|
||||||
|
|
||||||
Revision 1.2 2004/07/05 17:07:14 ponchio
|
|
||||||
Tested a bit.
|
|
||||||
|
|
||||||
Revision 1.1 2004/07/04 15:24:50 ponchio
|
|
||||||
Created
|
|
||||||
|
|
||||||
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#include "nexus.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace vcg;
|
|
||||||
using namespace nxs;
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
if(argc != 2) {
|
|
||||||
cerr << "Usage: " << argv[0] << " <nexus>\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Nexus nexus;
|
|
||||||
if(!nexus.Load(argv[1])) {
|
|
||||||
cerr << "Could not load " << argv[1] << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int duplicated = 0;
|
|
||||||
for(unsigned int p = 0; p < nexus.index.size(); p++) {
|
|
||||||
Nexus::Entry &entry = nexus.index[p];
|
|
||||||
Patch patch = nexus.GetPatch(p);
|
|
||||||
|
|
||||||
unsigned int vcount = 0;
|
|
||||||
map<Point3f, unsigned short> vertices;
|
|
||||||
vector<unsigned short> remap;
|
|
||||||
remap.resize(patch.VertSize());
|
|
||||||
// map<unsigned short, unsigned short> remap;
|
|
||||||
for(unsigned int i = 0; i < patch.VertSize(); i++) {
|
|
||||||
Point3f &point = patch.Vert(i);
|
|
||||||
|
|
||||||
if(!vertices.count(point)) {
|
|
||||||
vertices[point] = vcount++;
|
|
||||||
} else {
|
|
||||||
duplicated++;
|
|
||||||
}
|
|
||||||
|
|
||||||
remap[i] = vertices[point];
|
|
||||||
}
|
|
||||||
assert(vertices.size() <= patch.VertSize());
|
|
||||||
if(vertices.size() == patch.VertSize()) //no need to unify
|
|
||||||
continue;
|
|
||||||
|
|
||||||
vector<Point3f> newvert;
|
|
||||||
newvert.resize(vertices.size());
|
|
||||||
map<Point3f, unsigned short>::iterator k;
|
|
||||||
for(k = vertices.begin(); k != vertices.end(); k++) {
|
|
||||||
newvert[(*k).second] = (*k).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
vector<unsigned short> newface;
|
|
||||||
newface.resize(patch.FaceSize() * 3);
|
|
||||||
for(unsigned int f = 0; f < newface.size(); f++)
|
|
||||||
newface[f] = remap[patch.FaceBegin()[f]];
|
|
||||||
|
|
||||||
//rewrite patch now.
|
|
||||||
entry.nvert = newvert.size();
|
|
||||||
patch.Resize(entry.nvert, entry.nface);
|
|
||||||
|
|
||||||
memcpy(patch.VertBegin(), &(newvert[0]), entry.nvert*sizeof(Point3f));
|
|
||||||
memcpy(patch.FaceBegin(), &(newface[0]), entry.nface*3*sizeof(unsigned short));
|
|
||||||
|
|
||||||
//fix patch borders now
|
|
||||||
set<unsigned int> close; //bordering pathes
|
|
||||||
Border border = nexus.GetBorder(p);
|
|
||||||
for(unsigned int b = 0; b < border.Size(); b++) {
|
|
||||||
if(border[b].IsNull()) continue;
|
|
||||||
close.insert(border[b].end_patch);
|
|
||||||
border[b].start_vert = remap[border[b].start_vert];
|
|
||||||
}
|
|
||||||
|
|
||||||
set<unsigned int>::iterator c;
|
|
||||||
for(c = close.begin(); c != close.end(); c++) {
|
|
||||||
Border bord = nexus.GetBorder(*c);
|
|
||||||
for(unsigned int b = 0; b < bord.Size(); b++) {
|
|
||||||
if(bord[b].IsNull()) continue;
|
|
||||||
if(bord[b].end_patch == p) {
|
|
||||||
bord[b].end_vert = remap[bord[b].end_vert];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//finally: there may be duplicated borders
|
|
||||||
for(unsigned int p = 0; p < nexus.index.size(); p++) {
|
|
||||||
Border border = nexus.GetBorder(p);
|
|
||||||
//Nexus::Entry &entry = nexus.index[p];
|
|
||||||
|
|
||||||
set<Link> links;
|
|
||||||
for(unsigned int b = 0; b < border.Size(); b++) {
|
|
||||||
if(border[b].IsNull()) continue;
|
|
||||||
if(links.count(border[b]))
|
|
||||||
border[b] = Link();
|
|
||||||
else
|
|
||||||
links.insert(border[b]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cout << "Found " << duplicated << " duplicated vertices" << endl;
|
|
||||||
cout << endl;
|
|
||||||
cout << endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,149 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
* VCGLib o o *
|
|
||||||
* Visual and Computer Graphics Library o o *
|
|
||||||
* _ O _ *
|
|
||||||
* Copyright(C) 2004 \/)\/ *
|
|
||||||
* Visual Computing Lab /\/| *
|
|
||||||
* ISTI - Italian National Research Council | *
|
|
||||||
* \ *
|
|
||||||
* All rights reserved. *
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
|
||||||
* for more details. *
|
|
||||||
* *
|
|
||||||
****************************************************************************/
|
|
||||||
/****************************************************************************
|
|
||||||
History
|
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
|
||||||
Revision 1.2 2004/07/01 21:46:36 ponchio
|
|
||||||
Added header.
|
|
||||||
|
|
||||||
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef PARTITION_INTERSECT_H
|
|
||||||
#define PARTITION_INTERSECT_H
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
#include <vcg/space/point3.h>
|
|
||||||
|
|
||||||
namespace nxs {
|
|
||||||
|
|
||||||
struct IPair {
|
|
||||||
unsigned int fine;
|
|
||||||
unsigned int coarse;
|
|
||||||
bool operator<(const IPair &p) const {
|
|
||||||
if(fine == p.fine) return coarse < p.coarse;
|
|
||||||
return fine < p.fine;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ICell {
|
|
||||||
unsigned int index;
|
|
||||||
unsigned int count;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <class Partition> class PIntersect {
|
|
||||||
public:
|
|
||||||
Partition *fine;
|
|
||||||
Partition *coarse;
|
|
||||||
|
|
||||||
// typedef typename Partition::Key Key;
|
|
||||||
|
|
||||||
unsigned int last_cell;
|
|
||||||
std::map<IPair, ICell> pairs;
|
|
||||||
std::set<unsigned int> cells;
|
|
||||||
|
|
||||||
PIntersect(Partition *f = NULL, Partition *c = NULL):
|
|
||||||
fine(f), coarse(c), last_cell(0) {}
|
|
||||||
|
|
||||||
void Init(Partition *f, Partition *c, unsigned int of_cell) {
|
|
||||||
fine = f;
|
|
||||||
coarse = c;
|
|
||||||
last_cell = of_cell;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Locate(const vcg::Point3f &p) {
|
|
||||||
IPair pp;
|
|
||||||
pp.fine = fine->Locate(p);
|
|
||||||
pp.coarse = coarse->Locate(p);
|
|
||||||
if(pairs.count(pp)) { //already there
|
|
||||||
ICell &cell = pairs[pp];
|
|
||||||
cell.count++;
|
|
||||||
return cell.index;
|
|
||||||
} else {
|
|
||||||
ICell &cell = pairs[pp];
|
|
||||||
cell.index = last_cell++;
|
|
||||||
cell.count = 1;
|
|
||||||
cells.insert(cell.index);
|
|
||||||
return cell.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Relocate(const vcg::Point3f &p) {
|
|
||||||
//TODO!!!!!!
|
|
||||||
}
|
|
||||||
void Prune(unsigned int threshold) {
|
|
||||||
//TODO!!!!!!
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Count(unsigned int cell) {
|
|
||||||
return cells.count(cell);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Save(const std::string &file) {
|
|
||||||
FILE *fp = fopen((file + ".chi").c_str(), "wb+");
|
|
||||||
if(!fp)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
unsigned int n = pairs.size();
|
|
||||||
fwrite(&n, sizeof(unsigned int), 1, fp);
|
|
||||||
|
|
||||||
std::map<IPair, ICell>::iterator i;
|
|
||||||
for(i = pairs.begin(); i != pairs.end(); i++) {
|
|
||||||
IPair pair = (*i).first;
|
|
||||||
ICell cell = (*i).second;
|
|
||||||
fwrite(&pair, sizeof(IPair), 1, fp);
|
|
||||||
fwrite(&cell, sizeof(ICell), 1, fp);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Load(const std::string &file) {
|
|
||||||
pairs.clear();
|
|
||||||
cells.clear();
|
|
||||||
FILE *fp = fopen((file + ".chi").c_str(), "rb");
|
|
||||||
if(!fp)
|
|
||||||
return false;
|
|
||||||
unsigned int n;
|
|
||||||
fread(&n, sizeof(unsigned int), 1, fp);
|
|
||||||
|
|
||||||
IPair pair;
|
|
||||||
ICell cell;
|
|
||||||
for(unsigned int i = 0; i < n; i++) {
|
|
||||||
fread(&pair, sizeof(IPair), 1, fp);
|
|
||||||
fread(&cell, sizeof(ICell), 1, fp);
|
|
||||||
pairs[pair] = cell;
|
|
||||||
cells.insert(cell.index);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}//namespace
|
|
||||||
#endif
|
|
|
@ -1,242 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
* VCGLib o o *
|
|
||||||
* Visual and Computer Graphics Library o o *
|
|
||||||
* _ O _ *
|
|
||||||
* Copyright(C) 2004 \/)\/ *
|
|
||||||
* Visual Computing Lab /\/| *
|
|
||||||
* ISTI - Italian National Research Council | *
|
|
||||||
* \ *
|
|
||||||
* All rights reserved. *
|
|
||||||
* *
|
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
|
||||||
* it under the terms of the GNU General Public License as published by *
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
|
||||||
* (at your option) any later version. *
|
|
||||||
* *
|
|
||||||
* This program is distributed in the hope that it will be useful, *
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
||||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
|
||||||
* for more details. *
|
|
||||||
* *
|
|
||||||
****************************************************************************/
|
|
||||||
/****************************************************************************
|
|
||||||
History
|
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
|
||||||
Revision 1.4 2004/07/20 14:05:45 ponchio
|
|
||||||
Inserted report on progress.
|
|
||||||
|
|
||||||
Revision 1.3 2004/07/15 14:32:49 ponchio
|
|
||||||
Debug.
|
|
||||||
|
|
||||||
Revision 1.2 2004/07/05 15:49:39 ponchio
|
|
||||||
Windows (DevCpp, mingw) port.
|
|
||||||
|
|
||||||
Revision 1.1 2004/07/04 15:30:00 ponchio
|
|
||||||
Changed directory structure.
|
|
||||||
|
|
||||||
Revision 1.3 2004/07/02 17:42:43 ponchio
|
|
||||||
Debug.
|
|
||||||
|
|
||||||
Revision 1.2 2004/07/02 13:09:31 ponchio
|
|
||||||
Extensions changed.
|
|
||||||
|
|
||||||
Revision 1.1 2004/07/01 21:32:18 ponchio
|
|
||||||
Created
|
|
||||||
|
|
||||||
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include "pchain.h"
|
|
||||||
#include "pvoronoi.h"
|
|
||||||
#include "vert_remap.h"
|
|
||||||
#include "crude.h"
|
|
||||||
#include "pintersect.h"
|
|
||||||
#include "report.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace nxs;
|
|
||||||
using namespace vcg;
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
if(argc < 3) {
|
|
||||||
cerr << "Usage: " << argv[0]
|
|
||||||
<< " <crude input> <output (remap and pchain)> "
|
|
||||||
"[patch_size] [threshold]\n\n";
|
|
||||||
cerr << "Patch size and treshold expressed int faces "
|
|
||||||
"and default to 1000 and 250\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Crude crude;
|
|
||||||
if(!crude.Load(argv[1])) {
|
|
||||||
cerr << "Could not open crude input\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string output = argv[2];
|
|
||||||
|
|
||||||
unsigned int target_size = 1000;
|
|
||||||
if(argc > 3)
|
|
||||||
target_size = atoi(argv[3]);
|
|
||||||
if(target_size <= 0) {
|
|
||||||
cerr << "Invalid patch_size: " << argv[3] << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int treshold = 250;
|
|
||||||
if(argc > 4)
|
|
||||||
treshold = atoi(argv[4]);
|
|
||||||
if(treshold <= 0) {
|
|
||||||
cerr << "Invalid patch_size: " << argv[4] << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cerr << "Verts: " << crude.Vertices() << endl;
|
|
||||||
cerr << "Faces: " << crude.Faces() << endl;
|
|
||||||
cerr << "Getting optimal radius...\n";
|
|
||||||
|
|
||||||
Report report;
|
|
||||||
report.Start((unsigned int)0, 0);
|
|
||||||
|
|
||||||
vector<unsigned int> target;
|
|
||||||
unsigned int patch_size = target_size;
|
|
||||||
for(patch_size = target_size; patch_size < crude.vert.Size(); patch_size *=2)
|
|
||||||
target.push_back(patch_size);
|
|
||||||
vector<float> radius;
|
|
||||||
radius = VoronoiPartition::OptimalRadii(crude.vert.Size(),
|
|
||||||
crude.vert.Begin(),
|
|
||||||
crude.vert.End(),
|
|
||||||
crude.GetBox(),
|
|
||||||
target);
|
|
||||||
// for(unsigned int i = 0; i < radius.size(); i++)
|
|
||||||
// cerr << "Radius: " << radius[i] << endl;
|
|
||||||
|
|
||||||
cerr << " ...done in " << report.Elapsed() << " secs\n";
|
|
||||||
|
|
||||||
assert(radius.size() > 1);
|
|
||||||
//TODO cosa succede se c'e' una sola patch?
|
|
||||||
|
|
||||||
PChain<VoronoiPartition> chain;
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < radius.size(); i++) {
|
|
||||||
VoronoiPartition part;
|
|
||||||
part.Init(crude.GetBox());
|
|
||||||
chain.levels.push_back(part);
|
|
||||||
}
|
|
||||||
report.Start(0, 0);
|
|
||||||
cerr << "Building voronoi partitions...";
|
|
||||||
|
|
||||||
//TODO move this part to pvoronoi (and create Crude::vert_iterator
|
|
||||||
VFile<Point3f>::iterator iter;
|
|
||||||
for(iter = crude.vert.Begin(); iter != crude.vert.End(); ++iter) {
|
|
||||||
Point3f &v = *iter;
|
|
||||||
VoronoiPartition::Key target;
|
|
||||||
float dist;
|
|
||||||
for(unsigned int i = 0; i < radius.size(); i++) {
|
|
||||||
VoronoiPartition &part = chain.levels[i];
|
|
||||||
dist = part.Closest(v, target);
|
|
||||||
if(dist >= radius[i] || dist == -1)
|
|
||||||
part.Add(v, radius[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cerr << "...done in " << report.Elapsed() << " secs\n";
|
|
||||||
|
|
||||||
VFile<unsigned int> face_remap;
|
|
||||||
if(!face_remap.Create(output + ".rmf")) {
|
|
||||||
cerr << "Could not create remap files: " << output << ".frm\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
face_remap.Resize(crude.Faces());
|
|
||||||
|
|
||||||
|
|
||||||
PIntersect<VoronoiPartition> inter(&(chain.levels[0]), &(chain.levels[1]));
|
|
||||||
|
|
||||||
report.Start(crude.Faces(), 100000);
|
|
||||||
cerr << "Splitting faces... ";
|
|
||||||
|
|
||||||
Point3f bari;
|
|
||||||
for(unsigned int i = 0; i < crude.Faces(); i++) {
|
|
||||||
bari = crude.GetBari(i);
|
|
||||||
unsigned int patch = inter.Locate(bari);
|
|
||||||
face_remap[i] = patch;
|
|
||||||
report.Output(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
cerr << "done in " << report.Elapsed() << " secs\n";
|
|
||||||
|
|
||||||
//TODO Prune inter to threshold and relocate faces
|
|
||||||
|
|
||||||
inter.Save(output);
|
|
||||||
|
|
||||||
VertRemap vert_remap;
|
|
||||||
if(!vert_remap.Create(output)) {
|
|
||||||
cerr << "Could not create remap files: " << output << ".rmv and .rmb\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
vert_remap.Resize(crude.vert.Size());
|
|
||||||
|
|
||||||
cerr << "Splitting vertices... ";
|
|
||||||
report.Start(crude.Faces(), 100000);
|
|
||||||
|
|
||||||
unsigned int totvert = 0;
|
|
||||||
for(unsigned int i = 0; i < crude.Faces(); i++) {
|
|
||||||
report.Output(i);
|
|
||||||
Crude::Face &face = crude.GetFace(i);
|
|
||||||
unsigned int patch = face_remap[i];
|
|
||||||
for(int k = 0; k < 3; k++) {
|
|
||||||
set<unsigned int> pp;
|
|
||||||
vert_remap.GetValues(face[k], pp);
|
|
||||||
if(!pp.count(patch))
|
|
||||||
totvert++;
|
|
||||||
vert_remap.Insert(face[k], patch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cerr << "done in " << report.Elapsed() << " secs\n";
|
|
||||||
cerr << "Tot vertices: " << totvert << endl;
|
|
||||||
chain.Save(output);
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < vert_remap.all.Size(); i++) {
|
|
||||||
unsigned int patch = vert_remap.all[i];
|
|
||||||
if(patch == 0xffffffff) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
totvert--;
|
|
||||||
}
|
|
||||||
int totbord = 0;
|
|
||||||
VFile<MFHash::Bucket> &border = vert_remap.borders.buffer;
|
|
||||||
cerr << "Border space:" << border.Size() << endl;
|
|
||||||
for(unsigned int i = 0; i < border.Size(); i++) {
|
|
||||||
MFHash::Bucket &bucket = border[i];
|
|
||||||
if(bucket.key == 0xffffffff) continue;
|
|
||||||
totvert--;
|
|
||||||
totbord++;
|
|
||||||
}
|
|
||||||
cerr << "Borders: " << totbord << endl;
|
|
||||||
vert_remap.Close();
|
|
||||||
|
|
||||||
//DEBUG testing if vert_remap.borders works
|
|
||||||
|
|
||||||
/* for(unsigned int i = 0; i < crude.Faces(); i++) {
|
|
||||||
Crude::Face &face = crude.GetFace(i);
|
|
||||||
unsigned int patch = face_remap[i];
|
|
||||||
for(int k = 0; k < 3; k++) {
|
|
||||||
set<unsigned int> v;
|
|
||||||
vert_remap.GetValues(face[k], v);
|
|
||||||
assert(v.size() != 0);
|
|
||||||
if(!v.count(patch)) {
|
|
||||||
cerr << "count: " << v.size() << endl;
|
|
||||||
cerr << "patch " << patch << endl;
|
|
||||||
}
|
|
||||||
assert(v.count(patch));
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in New Issue