vcglib/apps/nexus/voronoinxs.cpp

739 lines
22 KiB
C++
Raw Normal View History

2004-08-26 20:03:48 +02:00
/****************************************************************************
* 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.6 2004/10/01 16:54:57 ponchio
Daily backup.
2004-10-01 18:54:57 +02:00
Revision 1.5 2004/09/30 00:27:42 ponchio
Lot of changes. Backup.
2004-09-30 02:27:42 +02:00
Revision 1.4 2004/09/21 00:53:23 ponchio
Lotsa changes.
2004-09-21 02:53:23 +02:00
Revision 1.3 2004/09/17 15:25:09 ponchio
First working (hopefully) release.
2004-09-17 17:25:59 +02:00
Revision 1.2 2004/09/16 14:25:16 ponchio
Backup. (lot of changes).
2004-09-16 16:25:16 +02:00
Revision 1.1 2004/08/26 18:03:48 ponchio
First draft.
2004-08-26 20:03:48 +02:00
****************************************************************************/
#ifdef WIN32
#include "getopt.h"
2004-09-16 16:25:16 +02:00
#else
#include <unistd.h>
2004-08-26 20:03:48 +02:00
#endif
#include <iostream>
using namespace std;
#include "crude.h"
#include "nexus.h"
#include "voronoichain.h"
#include "pintersect.h"
#include "vert_remap.h"
2004-10-01 18:54:57 +02:00
#include "decimate.h"
#include "nxsbuild.h"
2004-08-26 20:03:48 +02:00
using namespace vcg;
using namespace nxs;
2004-10-01 18:54:57 +02:00
/*void RemapVertices(Crude &crude,
2004-08-26 20:03:48 +02:00
VertRemap &vert_remap,
VFile<unsigned int> &face_remap,
vector<unsigned int> &patch_verts);
void NexusAllocate(Crude &crude,
Nexus &nexus,
VFile<unsigned int> &face_remap,
vector<unsigned int> &patch_faces,
vector<unsigned int> &patch_verts);
void NexusFill(Crude &crude,
Nexus &nexus,
VertRemap &vert_remap,
VFile<RemapLink> &border_remap);
void NexusFixBorder(Nexus &nexus,
2004-10-01 18:54:57 +02:00
VFile<RemapLink> &border_remap);*/
2004-08-26 20:03:48 +02:00
void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
unsigned int level,
vector<Point3f> &newvert,
vector<unsigned int> &newface,
2004-09-16 16:25:16 +02:00
vector<Link> &newbord,
Nexus::Update &update,
float error);
2004-10-01 18:54:57 +02:00
/*float Decimate(unsigned int target_faces,
2004-09-16 16:25:16 +02:00
vector<Point3f> &newvert,
vector<unsigned int> &newface,
vector<Link> &newbord,
2004-10-01 18:54:57 +02:00
vector<int> &vert_remap);*/
2004-09-16 16:25:16 +02:00
void ReverseHistory(vector<Nexus::Update> &history);
2004-08-26 20:03:48 +02:00
2004-10-01 18:54:57 +02:00
2004-09-21 02:53:23 +02:00
2004-08-26 20:03:48 +02:00
int main(int argc, char *argv[]) {
2004-10-01 18:54:57 +02:00
Decimation decimation = CLUSTER;
2004-08-26 20:03:48 +02:00
unsigned int patch_size = 1000;
2004-09-30 02:27:42 +02:00
unsigned int patch_threshold = 0xffffffff;
2004-09-21 02:53:23 +02:00
unsigned int optimization_steps = 5;
bool stop_after_remap = false;
2004-08-26 20:03:48 +02:00
unsigned int max_level = 0xffffffff;
2004-09-16 16:25:16 +02:00
float scaling = 0.5;
2004-08-26 20:03:48 +02:00
int option;
2004-09-21 02:53:23 +02:00
while((option = getopt(argc, argv, "f:t:l:s:d:ro:")) != EOF) {
2004-08-26 20:03:48 +02:00
switch(option) {
case 'f': patch_size = atoi(optarg);
if(patch_size == 0 || patch_size > 32000) {
cerr << "Invalid number of faces per patch: " << optarg << endl;
return -1;
}
break;
case 't': patch_threshold = atoi(optarg);
if(patch_threshold == 0 || patch_threshold > patch_size) {
cerr << "Invalid patch threshold: " << optarg << endl;
return -1;
}
break;
case 'l': max_level = atoi(optarg);
if(max_level == 0) {
cerr << "Invalid number of levels: " << optarg << endl;
return -1;
}
break;
2004-09-16 16:25:16 +02:00
case 's': scaling = atof(optarg);
if(scaling <= 0 || scaling >= 1) {
cerr << "Invalid scaling: " << optarg << endl;
cerr << "Must be 0 < scaling < 1" << endl;
}
break;
2004-09-21 02:53:23 +02:00
case 'd':
if(!strcmp("quadric", optarg))
decimation = QUADRIC;
else if(!strcmp("cluster", optarg))
decimation = CLUSTER;
else {
cerr << "Unknown decimation method: " << optarg << endl;
return -1;
}
break;
case 'r': stop_after_remap = true; break;
case 'o': optimization_steps = atoi(optarg); break;
2004-08-26 20:03:48 +02:00
default: cerr << "Unknown option: " << (char)option << endl;
return -1;
}
}
2004-09-21 02:53:23 +02:00
//Test that there are still 2 arguments
2004-08-26 20:03:48 +02:00
if(optind != argc - 2) {
cerr << "Usage: " << argv[0] << " <crude> <output> [options]\n";
cerr << " Options:\n";
cerr << " -f N: use N faces per patch (default 1000, max 32000)\n";
cerr << " -t N: mini faces per patch (default 200)\n";
2004-09-16 16:25:16 +02:00
cerr << " -l N: number of levels\n";
cerr << " -s F: scaling factor (0 < F < 1, default 0.5)\n";
cerr << " -o N: nomber of optimization steps\n";
2004-09-21 02:53:23 +02:00
cerr << " -d <method>: decimation method: quadric, cluster. (default quadric)\n";
2004-08-26 20:03:48 +02:00
return -1;
}
Crude crude;
if(!crude.Load(argv[optind])) {
cerr << "Could not open crude input: " << argv[optind] << endl;
return -1;
}
if(patch_size > crude.vert.Size()/2) {
2004-09-21 02:53:23 +02:00
cerr << "Patch size too big: " << patch_size << " * 2 > " << crude.vert.Size()
2004-08-26 20:03:48 +02:00
<< endl;
return -1;
}
string output = argv[optind+1];
2004-09-16 16:25:16 +02:00
2004-08-26 20:03:48 +02:00
Nexus nexus;
2004-09-30 02:27:42 +02:00
if(!nexus.Create(output, NXS_FACES)) {
2004-08-26 20:03:48 +02:00
cerr << "Could not create nexus output: " << output << endl;
return -1;
}
2004-09-30 02:27:42 +02:00
if(patch_threshold == 0xffffffff)
patch_threshold = patch_size/4;
2004-09-21 02:53:23 +02:00
VoronoiChain vchain(patch_size, patch_threshold);
// vchain.scaling = scaling;
2004-08-26 20:03:48 +02:00
//Now building level 0 of the Nexus
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());
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.Vertices());
VFile<RemapLink> border_remap;
if(!border_remap.Create(output + string(".tmp"))) {
cerr << "Could not create temporary border remap file\n";
return -1;
}
/* BUILDING FIRST LEVEL */
//Remapping faces and vertices using level 0 and 1 of the chain
vector<unsigned int> patch_faces;
2004-09-21 02:53:23 +02:00
vchain.RemapFaces(crude, face_remap, patch_faces, scaling, optimization_steps);
2004-08-26 20:03:48 +02:00
vector<unsigned int> patch_verts;
patch_verts.resize(patch_faces.size(), 0);
RemapVertices(crude, vert_remap, face_remap, patch_verts);
2004-09-21 02:53:23 +02:00
if(stop_after_remap) return 0;
2004-08-26 20:03:48 +02:00
//allocate chunks for patches and copy faces (absoklute indexing) into them.
NexusAllocate(crude, nexus, face_remap, patch_faces, patch_verts);
//insert vertices and remap faces, prepare borders
NexusFill(crude, nexus, vert_remap, border_remap);
NexusFixBorder(nexus, border_remap);
2004-09-16 16:25:16 +02:00
//filling history
Nexus::Update update;
for(unsigned int i = 0; i < nexus.index.size(); i++)
update.created.push_back(i);
nexus.history.push_back(update);
2004-08-26 20:03:48 +02:00
2004-09-17 17:25:59 +02:00
//unify vertices otherwise you may get cracks.
nexus.Unify();
2004-08-26 20:03:48 +02:00
/* BUILDING OTHER LEVELS */
unsigned int oldoffset = 0;
for(unsigned int level = 1; level < max_level; level++) {
cerr << "Level: " << level << endl;
unsigned int newoffset = nexus.index.size();
2004-09-21 02:53:23 +02:00
vchain.BuildLevel(nexus, oldoffset, scaling, optimization_steps);
2004-08-26 20:03:48 +02:00
2004-09-21 02:53:23 +02:00
cerr << "Level built\n";
2004-09-17 17:25:59 +02:00
vector<Nexus::Update> level_history;
2004-08-26 20:03:48 +02:00
map<unsigned int, set<unsigned int> >::iterator fragment;
for(fragment = vchain.oldfragments.begin();
fragment != vchain.oldfragments.end(); fragment++) {
2004-09-16 16:25:16 +02:00
update.created.clear();
update.erased.clear();
2004-09-17 17:25:59 +02:00
cerr << "Join ";
2004-08-26 20:03:48 +02:00
set<unsigned int> &fcells = (*fragment).second;
set<unsigned int>::iterator s;
2004-09-16 16:25:16 +02:00
for(s = fcells.begin(); s != fcells.end(); s++) {
update.erased.push_back(*s);
2004-09-17 17:25:59 +02:00
cerr << *s << " ";
2004-09-16 16:25:16 +02:00
}
2004-08-26 20:03:48 +02:00
cerr << endl;
vector<Point3f> newvert;
vector<unsigned int> newface;
vector<Link> newbord;
2004-09-16 16:25:16 +02:00
2004-08-26 20:03:48 +02:00
nexus.Join((*fragment).second, newvert, newface, newbord);
2004-09-16 16:25:16 +02:00
2004-08-26 20:03:48 +02:00
//simplyfy mesh
2004-09-16 16:25:16 +02:00
vector<int> vert_remap;
2004-10-01 18:54:57 +02:00
float error = Decimate(decimation,
(unsigned int)((newface.size()/3) * scaling),
2004-09-17 17:25:59 +02:00
newvert, newface, newbord, vert_remap);
2004-09-16 16:25:16 +02:00
2004-08-26 20:03:48 +02:00
2004-09-16 16:25:16 +02:00
NexusSplit(nexus, vchain, level, newvert, newface, newbord,
update, error);
2004-08-26 20:03:48 +02:00
2004-09-16 16:25:16 +02:00
2004-09-17 17:25:59 +02:00
level_history.push_back(update);
2004-08-26 20:03:48 +02:00
}
2004-09-17 17:25:59 +02:00
for(int i = 0; i < level_history.size(); i++)
nexus.history.push_back(level_history[i]);
2004-09-16 16:25:16 +02:00
//if(vchain.levels.back().size() == 1) break;
if(vchain.oldfragments.size() == 1) break;
2004-08-26 20:03:48 +02:00
vchain.oldfragments = vchain.newfragments;
oldoffset = newoffset;
}
2004-09-17 17:25:59 +02:00
2004-09-16 16:25:16 +02:00
//last level clean history:
update.created.clear();
update.erased.clear();
map<unsigned int, set<unsigned int> >::iterator fragment;
for(fragment = vchain.newfragments.begin();
fragment != vchain.newfragments.end(); fragment++) {
set<unsigned int> &fcells = (*fragment).second;
set<unsigned int>::iterator s;
for(s = fcells.begin(); s != fcells.end(); s++)
update.erased.push_back(*s);
}
nexus.history.push_back(update);
ReverseHistory(nexus.history);
//debug:
2004-09-17 17:25:59 +02:00
/* for(unsigned int i = 0; i < nexus.history.size(); i++) {
2004-09-16 16:25:16 +02:00
Nexus::Update &update = nexus.history[i];
cerr << "created:";
for(unsigned int c = 0; c < update.created.size(); c++)
cerr << " " << update.created[c];
cerr << "\nerased:";
for(unsigned int c = 0; c < update.erased.size(); c++)
cerr << " " << update.erased[c];
cerr << "\n\n";
2004-09-17 17:25:59 +02:00
}*/
2004-08-26 20:03:48 +02:00
//Clean up:
nexus.Close();
//TODO remove vert_remap, face_remap, border_remap
return 0;
}
2004-10-01 18:54:57 +02:00
/*void RemapVertices(Crude &crude,
2004-08-26 20:03:48 +02:00
VertRemap &vert_remap,
VFile<unsigned int> &face_remap,
vector<unsigned int> &patch_verts) {
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> pp;
vert_remap.GetValues(face[k], pp);
if(!pp.count(patch)) {
vert_remap.Insert(face[k], patch);
patch_verts[patch]++;
}
}
}
2004-10-01 18:54:57 +02:00
}*/
2004-08-26 20:03:48 +02:00
2004-10-01 18:54:57 +02:00
/*void NexusAllocate(Crude &crude,
2004-08-26 20:03:48 +02:00
Nexus &nexus,
VFile<unsigned int> &face_remap,
vector<unsigned int> &patch_faces,
vector<unsigned int> &patch_verts) {
nexus.index.resize(patch_faces.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;
2004-09-16 16:25:16 +02:00
entry.patch_size = Patch::ChunkSize(nexus.signature,
patch_verts[i], patch_faces[i]);
2004-08-26 20:03:48 +02:00
totchunks += entry.patch_size;
entry.border_start = 0xffffffff;
entry.nvert = patch_verts[i];
entry.nface = 0;
2004-09-16 16:25:16 +02:00
entry.error = 0;
2004-08-26 20:03:48 +02:00
}
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];
2004-09-17 17:25:59 +02:00
//TODO this is slow because we have to initialize patch.
//just get patch.start.
2004-08-26 20:03:48 +02:00
Patch patch = nexus.GetPatch(npatch);
2004-09-17 17:25:59 +02:00
Crude::Face *faces = (Crude::Face *)patch.start;
2004-08-26 20:03:48 +02:00
faces[entry.nface] = face;
entry.nface++;
}
2004-10-01 18:54:57 +02:00
}*/
2004-08-26 20:03:48 +02:00
2004-10-01 18:54:57 +02:00
/*void NexusFill(Crude &crude,
2004-08-26 20:03:48 +02:00
Nexus &nexus,
VertRemap &vert_remap,
VFile<RemapLink> &border_remap) {
//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);
Nexus::Entry &entry = nexus.index[i];
//make a copy of faces (we need to write there :P)
2004-09-17 17:25:59 +02:00
Crude::Face *faces = new Crude::Face[patch.nf];
memcpy(faces, (Crude::Face *)patch.start,
patch.nf * sizeof(Crude::Face));
2004-08-26 20:03:48 +02:00
//collect all vertices we need.
//TODO an hash_map would be faster?
unsigned int count = 0;
map<unsigned int, unsigned short> remap;
2004-09-17 17:25:59 +02:00
for(unsigned int k = 0; k < patch.nf; k++) {
2004-08-26 20:03:48 +02:00
Crude::Face &face = faces[k];
for(int j = 0; j < 3; j++) {
if(!remap.count(face[j])) {
2004-09-17 17:25:59 +02:00
assert(count < patch.nv);
2004-08-26 20:03:48 +02:00
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:
2004-09-17 17:25:59 +02:00
entry.border_used = border_remap.Size() - entry.border_start;
2004-08-26 20:03:48 +02:00
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);
2004-10-01 18:54:57 +02:00
}*/
2004-08-26 20:03:48 +02:00
2004-10-01 18:54:57 +02:00
/*void NexusFixBorder(Nexus &nexus,
2004-08-26 20:03:48 +02:00
VFile<RemapLink> &border_remap) {
//and last convert RemapLinks into Links
2004-09-17 17:25:59 +02:00
nexus.borders.Resize(border_remap.Size() * 2);
//* 2 is to accomodate future borders
for(unsigned int i = 0; i < nexus.index.size(); i++) {
Nexus::Entry &local = nexus.index[i];
local.border_start *= 2;
local.border_size = local.border_used * 2;
}
2004-08-26 20:03:48 +02:00
for(unsigned int i = 0; i < nexus.index.size(); i++) {
Nexus::Entry &local = nexus.index[i];
2004-09-17 17:25:59 +02:00
unsigned int remap_start = local.border_start/2;
//* 2 is to accomodate future borders
2004-08-26 20:03:48 +02:00
// K is the main iterator (where we write to in nexus.borders)
2004-09-17 17:25:59 +02:00
for(unsigned int k = 0; k < local.border_used; k++) {
2004-08-26 20:03:48 +02:00
2004-09-17 17:25:59 +02:00
RemapLink start_link = border_remap[k + remap_start];
2004-08-26 20:03:48 +02:00
assert(start_link.rel_vert < local.nvert);
Nexus::Entry &remote = nexus.index[start_link.patch];
bool found = false;
2004-09-17 17:25:59 +02:00
unsigned int remote_remap_start = remote.border_start/2;
for(unsigned int j = 0; j < remote.border_used; j++) {
2004-08-26 20:03:48 +02:00
2004-09-17 17:25:59 +02:00
RemapLink end_link = border_remap[j + remote_remap_start];
2004-08-26 20:03:48 +02:00
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);
2004-09-17 17:25:59 +02:00
nexus.borders[k + local.border_start] = Link(start_link.rel_vert,
end_link.rel_vert,
start_link.patch);
2004-08-26 20:03:48 +02:00
found = true;
}
}
2004-09-17 17:25:59 +02:00
assert(nexus.borders[k + local.border_start].start_vert < local.nvert);
2004-08-26 20:03:48 +02:00
assert(found);
}
}
nexus.borders.Flush();
2004-10-01 18:54:57 +02:00
} */
2004-08-26 20:03:48 +02:00
void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
unsigned int level,
vector<Point3f> &newvert,
vector<unsigned int> &newface,
2004-09-16 16:25:16 +02:00
vector<Link> &newbord,
Nexus::Update &update,
float error) {
2004-08-26 20:03:48 +02:00
2004-09-17 17:25:59 +02:00
//if != -1 remap global index to cell index (first arg)
2004-08-26 20:03:48 +02:00
map<unsigned int, vector<int> > vert_remap;
map<unsigned int, unsigned int> vert_count;
//simply collects faces
map<unsigned int, vector<int> > face_remap;
map<unsigned int, unsigned int> face_count;
for(unsigned int f = 0; f < newface.size(); f += 3) {
Point3f bari = (newvert[newface[f]] +
newvert[newface[f+1]] +
newvert[newface[f+2]])/3;
unsigned int cell = vchain.Locate(level+1, bari);
vector<int> &f_remap = face_remap[cell];
f_remap.push_back(newface[f]);
f_remap.push_back(newface[f+1]);
f_remap.push_back(newface[f+2]);
face_count[cell]++;
if(!vert_remap.count(cell)) {
vert_remap[cell].resize(newvert.size(), -1);
vert_count[cell] = 0;
}
vector<int> &v_remap = vert_remap[cell];
for(int i = 0; i < 3; i++)
if(v_remap[newface[f+i]] == -1)
v_remap[newface[f+i]] = vert_count[cell]++;
}
2004-09-17 17:25:59 +02:00
2004-08-26 20:03:48 +02:00
//TODO prune small count cells
2004-09-17 17:25:59 +02:00
//lets count borders
map<unsigned int, unsigned int> bord_count;
2004-08-26 20:03:48 +02:00
map<unsigned int, unsigned int >::iterator c;
for(c = vert_count.begin(); c != vert_count.end(); c++) {
unsigned int cell = (*c).first;
2004-09-17 17:25:59 +02:00
unsigned int &count = bord_count[cell];
count = 0;
vector<int> &v_remap = vert_remap[cell];
//external borders
for(unsigned int i = 0; i < newbord.size(); i++) {
Link link = newbord[i];
if(v_remap[link.start_vert] == -1) continue;
count++;
}
//process internal borders;
//TODO higly inefficient!!!
map<unsigned int, unsigned int >::iterator t;
for(t = vert_count.begin(); t != vert_count.end(); t++) {
if(cell == (*t).first) continue;
vector<int> &vremapclose = vert_remap[(*t).first];
for(unsigned int i = 0; i < newvert.size(); i++) {
if(v_remap[i] != -1 && vremapclose[i] != -1) {
count++;
}
}
}
}
map<unsigned int, unsigned int> cells2patches;
//lets allocate space
for(c = vert_count.begin(); c != vert_count.end(); c++) {
unsigned int cell = (*c).first;
unsigned int patch_idx = nexus.AddPatch(vert_count[cell],
face_count[cell],
3 * bord_count[cell]);
2004-08-26 20:03:48 +02:00
2004-09-17 17:25:59 +02:00
//why double border space? because at next level
//we will need to add those borders...
cells2patches[cell] = patch_idx;
vchain.newfragments[cell].insert(patch_idx);
update.created.push_back(patch_idx);
}
//fill it now.
for(c = vert_count.begin(); c != vert_count.end(); c++) {
unsigned int cell = (*c).first;
unsigned int patch_idx = cells2patches[cell];
2004-08-26 20:03:48 +02:00
2004-09-17 17:25:59 +02:00
//vertices first
2004-08-26 20:03:48 +02:00
vector<int> &v_remap = vert_remap[cell];
2004-09-17 17:25:59 +02:00
vector<Point3f> verts;
2004-08-26 20:03:48 +02:00
verts.resize(vert_count[cell]);
for(unsigned int i = 0; i < newvert.size(); i++) {
if(v_remap[i] != -1)
verts[v_remap[i]] = newvert[i];
}
2004-09-17 17:25:59 +02:00
//faces now
vector<int> &f_remap = face_remap[cell];
vector<unsigned short> faces;
2004-08-26 20:03:48 +02:00
faces.resize(face_count[cell]*3);
2004-09-17 17:25:59 +02:00
2004-08-26 20:03:48 +02:00
for(unsigned int i = 0; i < f_remap.size(); i++) {
assert(v_remap[f_remap[i]] != -1);
faces[i] = v_remap[f_remap[i]];
}
2004-09-17 17:25:59 +02:00
if(patch_idx == 68)
cerr << "68 bord: " << bord_count[cell] << endl;
//borders last
vector<Link> bords;
//process external borders
//for every esternal link we must update external patches!
2004-08-26 20:03:48 +02:00
for(unsigned int i = 0; i < newbord.size(); i++) {
Link link = newbord[i];
if(v_remap[link.start_vert] == -1) continue;
link.start_vert = v_remap[link.start_vert];
bords.push_back(link);
2004-09-17 17:25:59 +02:00
Nexus::Entry &rentry = nexus.index[link.end_patch];
//TODO if !true reallocate borders.
2004-09-21 02:53:23 +02:00
Border rborder = nexus.GetBorder(link.end_patch);
2004-09-17 17:25:59 +02:00
if(rentry.border_used >= rentry.border_size) {
cerr << "patch: " << link.end_patch << endl;
cerr << "used: " << rentry.border_used << endl;
cerr << "size: " << rentry.border_size << endl;
2004-09-21 02:53:23 +02:00
unsigned int start = nexus.borders.Size();
nexus.borders.Resize(nexus.borders.Size() + 2 * rentry.border_size);
Link *tmp = new Link[rentry.border_size];
memcpy(tmp, &rborder[0], sizeof(Link) * rentry.border_size);
rentry.border_start = start;
rentry.border_size *= 2;
rborder = nexus.GetBorder(link.end_patch);
memcpy(&rborder[0], tmp, sizeof(Link) * rentry.border_used);
delete []tmp;
2004-09-17 17:25:59 +02:00
}
assert(rentry.border_used < rentry.border_size);
2004-09-21 02:53:23 +02:00
2004-09-17 17:25:59 +02:00
Link &newlink = rborder[rentry.border_used++];
newlink.start_vert = link.end_vert;
newlink.end_vert = link.start_vert;
newlink.end_patch = patch_idx;
2004-08-26 20:03:48 +02:00
}
2004-09-17 17:25:59 +02:00
2004-08-26 20:03:48 +02:00
//process internal borders;
//TODO higly inefficient!!!
map<unsigned int, unsigned int >::iterator t;
for(t = vert_count.begin(); t != vert_count.end(); t++) {
if(cell == (*t).first) continue;
vector<int> &vremapclose = vert_remap[(*t).first];
for(unsigned int i = 0; i < newvert.size(); i++) {
if(v_remap[i] != -1 && vremapclose[i] != -1) {
Link link;
2004-09-17 17:25:59 +02:00
link.end_patch = cells2patches[(*t).first];
2004-08-26 20:03:48 +02:00
link.start_vert = v_remap[i];
link.end_vert = vremapclose[i];
bords.push_back(link);
}
}
}
2004-09-17 17:25:59 +02:00
2004-09-16 16:25:16 +02:00
2004-08-26 20:03:48 +02:00
Nexus::Entry &entry = nexus.index[patch_idx];
2004-09-21 02:53:23 +02:00
entry.error = error;
2004-08-26 20:03:48 +02:00
Patch patch = nexus.GetPatch(patch_idx);
memcpy(patch.FaceBegin(), &faces[0],
faces.size() * sizeof(unsigned short));
memcpy(patch.VertBegin(), &verts[0], verts.size() * sizeof(Point3f));
for(int v = 0; v < verts.size(); v++) {
entry.sphere.Add(verts[v]);
nexus.sphere.Add(verts[v]);
}
Border border = nexus.GetBorder(patch_idx);
2004-09-17 17:25:59 +02:00
memcpy(&(border[0]), &(bords[0]), bords.size() * sizeof(Link));
entry.border_used = bords.size();
2004-08-26 20:03:48 +02:00
}
}
2004-09-16 16:25:16 +02:00
void ReverseHistory(vector<Nexus::Update> &history) {
reverse(history.begin(), history.end());
vector<Nexus::Update>::iterator i;
for(i = history.begin(); i != history.end(); i++)
swap((*i).erased, (*i).created);
}