First working (hopefully) release.
This commit is contained in:
parent
ad6b893cae
commit
92fa5a7e4a
|
@ -24,6 +24,9 @@
|
|||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
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.
|
||||
|
||||
|
@ -140,9 +143,16 @@ int main(int argc, char *argv[]) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_NORMALIZE);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
|
||||
|
||||
bool show_normals = true;
|
||||
int quit = 0;
|
||||
SDL_Event event;
|
||||
SDL_Event event;
|
||||
int x, y;
|
||||
float alpha = 0;
|
||||
while( !quit ) {
|
||||
|
@ -206,10 +216,18 @@ int main(int argc, char *argv[]) {
|
|||
unsigned int val = face_remap[i];
|
||||
glColor3ub((val * 27)%255, (val * 37)%255, (val * 87)%255);
|
||||
}
|
||||
for(int k = 0; k < 3; k++) {
|
||||
Point3f &p = crude.GetVertex(face[k]);
|
||||
glVertex3f(p[0], p[1], p[2]);
|
||||
Point3f &p0 = crude.GetVertex(face[0]);
|
||||
Point3f &p1 = crude.GetVertex(face[1]);
|
||||
Point3f &p2 = crude.GetVertex(face[2]);
|
||||
|
||||
if(show_normals) {
|
||||
Point3f n = ((p1 - p0) ^ (p2 - p0));
|
||||
glNormal3f(n[0], n[1], n[2]);
|
||||
}
|
||||
glVertex3f(p0[0], p0[1], p0[2]);
|
||||
glVertex3f(p1[0], p1[1], p1[2]);
|
||||
glVertex3f(p2[0], p2[1], p2[2]);
|
||||
|
||||
}
|
||||
glEnd();
|
||||
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
// stuff to define the mesh
|
||||
#include <vcg/simplex/vertex/with/afvmvn.h>
|
||||
#include <vcg/math/quadric.h>
|
||||
#include <vcg/complex/trimesh/base.h>
|
||||
#include <vcg/simplex/face/with/av.h>
|
||||
|
||||
// io
|
||||
//#include <wrap/io_trimesh/import_ply.h>
|
||||
//#include <wrap/io_trimesh/export_ply.h>
|
||||
// update
|
||||
#include <vcg/complex/trimesh/update/topology.h>
|
||||
|
||||
#include <vcg/complex/local_optimization.h>
|
||||
#include <vcg/complex/local_optimization/tri_edge_collapse_quadric.h>
|
||||
|
||||
#include <vcg/space/point3.h>
|
||||
#include "border.h"
|
||||
|
||||
class MyEdge;
|
||||
class MyFace;
|
||||
class MyVertex:public vcg::VertexAFVMVNf<DUMMYEDGETYPE , MyFace,DUMMYTETRATYPE>{public:
|
||||
ScalarType w;
|
||||
vcg::math::Quadric<vcg::Plane3<ScalarType,false> >q;
|
||||
ScalarType & W(){return w;}
|
||||
} ;
|
||||
class MyFace : public vcg::FaceAV<MyVertex,DUMMYEDGETYPE , MyFace>{};
|
||||
|
||||
class MyMesh:
|
||||
public vcg::tri::TriMesh< std::vector<MyVertex>, std::vector<MyFace > >{};
|
||||
|
||||
class MyTriEdgeCollapse:
|
||||
public vcg::tri::TriEdgeCollapseQuadric< MyMesh, MyTriEdgeCollapse >{
|
||||
public:
|
||||
typedef vcg::tri::TriEdgeCollapseQuadric<MyMesh, MyTriEdgeCollapse > TECQ;
|
||||
typedef TECQ::PosType PosType;
|
||||
MyTriEdgeCollapse(PosType p, int i):TECQ(p,i){}
|
||||
~MyTriEdgeCollapse(){}
|
||||
};
|
||||
|
||||
using namespace vcg;
|
||||
using namespace tri;
|
||||
using namespace nxs;
|
||||
using namespace std;
|
||||
|
||||
void Cluster(MyMesh &mesh, unsigned int target_faces);
|
||||
|
||||
float Decimate(unsigned int target_faces,
|
||||
vector<Point3f> &newvert,
|
||||
vector<unsigned int> &newface,
|
||||
vector<Link> &newbord,
|
||||
vector<int> &vert_remap) {
|
||||
|
||||
MyMesh mesh;
|
||||
|
||||
//build mesh
|
||||
|
||||
for(unsigned int i = 0; i < newvert.size(); i++) {
|
||||
MyVertex vertex;
|
||||
vertex.ClearFlags();
|
||||
vertex.P() = newvert[i];
|
||||
mesh.vert.push_back(vertex);
|
||||
}
|
||||
mesh.vn = mesh.vert.size();
|
||||
|
||||
for(unsigned int i = 0; i < newface.size(); i+=3) {
|
||||
MyFace face;
|
||||
face.ClearFlags();
|
||||
for(int k = 0; k < 3; k++) {
|
||||
assert(newface[i+k] < mesh.vn);
|
||||
face.V(k) = &mesh.vert[newface[i+k]];
|
||||
}
|
||||
mesh.face.push_back(face);
|
||||
}
|
||||
mesh.fn = mesh.face.size();
|
||||
|
||||
//emark borders
|
||||
for(unsigned int i = 0; i < newbord.size(); i++)
|
||||
mesh.vert[newbord[i].start_vert].ClearW();
|
||||
|
||||
// int FinalSize = mesh.face.size()/2;
|
||||
// if(FinalSize > target_faces) FinalSize = target_faces;
|
||||
int FinalSize = target_faces;
|
||||
|
||||
int t0=clock();
|
||||
|
||||
printf("mesh loaded %d %d \n",mesh.vn,mesh.fn);
|
||||
printf("reducing it to %i\n",FinalSize);
|
||||
vcg::tri::UpdateTopology<MyMesh>::VertexFace(mesh);
|
||||
|
||||
// cerr << "topology ok" << endl;
|
||||
int t1=clock();
|
||||
|
||||
//micro random semplificatore
|
||||
|
||||
/* for(unsigned int i = 0; i < mesh.face.size(); i+= 2) {
|
||||
MyFace &face = mesh.face[i];
|
||||
if(face.V(0)->IsW() && face.V(1)->IsW() && face.V(1)->IsW())
|
||||
mesh.face[i].SetD();
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < mesh.vert.size(); i++) {
|
||||
if(mesh.vert[i].IsW())
|
||||
mesh.vert[i].SetD();
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < mesh.face.size(); i++) {
|
||||
MyFace &face = mesh.face[i];
|
||||
if(face.IsD()) continue;
|
||||
face.V(0)->ClearD();
|
||||
face.V(1)->ClearD();
|
||||
face.V(2)->ClearD();
|
||||
}*/
|
||||
|
||||
// Cluster(mesh, target_faces);
|
||||
// cerr << "simplified" << endl;
|
||||
|
||||
vcg::LocalOptimization<MyMesh> DeciSession(mesh);
|
||||
MyTriEdgeCollapse::SetDefaultParams();
|
||||
|
||||
DeciSession.Init<MyTriEdgeCollapse>();
|
||||
|
||||
int t2=clock();
|
||||
// printf("Initial Heap Size %i\n",DeciSession.h.size());
|
||||
|
||||
FinalSize = mesh.fn - FinalSize; //number of faces to remove
|
||||
FinalSize/=2; //Number of vertices to remove
|
||||
DeciSession.SetTargetOperations(FinalSize);
|
||||
DeciSession.DoOptimization();
|
||||
float error = 1; //get error;
|
||||
int t3=clock();
|
||||
|
||||
/* printf(" vol %d \n lkv %d \n lke %d \n lkf %d \n ood %d\n bor %d\n ",
|
||||
MyTriEdgeCollapse::FailStat::Volume() ,
|
||||
MyTriEdgeCollapse::FailStat::LinkConditionFace(),
|
||||
MyTriEdgeCollapse::FailStat::LinkConditionEdge(),
|
||||
MyTriEdgeCollapse::FailStat::LinkConditionVert(),
|
||||
MyTriEdgeCollapse::FailStat::OutOfDate() ,
|
||||
MyTriEdgeCollapse::FailStat::Border()
|
||||
);*/
|
||||
|
||||
// printf("Completed in %i+%i+%i msec\n",t1-t0,t2-t1,t3-t2);
|
||||
// printf("mesh %d %d \n",mesh.vn,mesh.fn);
|
||||
|
||||
//recort vert start.
|
||||
|
||||
|
||||
newvert.clear();
|
||||
newface.clear();
|
||||
|
||||
unsigned int totvert = 0;
|
||||
vert_remap.resize(mesh.vert.size(), -1);
|
||||
for(unsigned int i = 0; i < mesh.vert.size(); i++) {
|
||||
if(mesh.vert[i].IsD()) continue;
|
||||
newvert.push_back(mesh.vert[i].cP());
|
||||
vert_remap[i] = totvert++;
|
||||
}
|
||||
|
||||
MyMesh::VertexPointer vert_start = &mesh.vert[0];
|
||||
for(unsigned int i = 0; i < mesh.face.size(); i++) {
|
||||
MyFace &face = mesh.face[i];
|
||||
if(face.IsD()) continue;
|
||||
for(int k = 0; k < 3; k++) {
|
||||
assert(vert_remap[face.V(k) - vert_start] != -1);
|
||||
newface.push_back(vert_remap[face.V(k) - vert_start]);
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < newbord.size(); i++) {
|
||||
unsigned short &v = newbord[i].start_vert;
|
||||
assert(vert_remap[v] != -1);
|
||||
v = vert_remap[v];
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
void Cluster(MyMesh &mesh, unsigned int target_faces) {
|
||||
unsigned int starting = mesh.vn;
|
||||
cerr << "starting face: " << mesh.fn << endl;
|
||||
//veramente brutale
|
||||
vector<int> remap;
|
||||
remap.resize(mesh.vert.size());
|
||||
for(int i = 0; i < mesh.vert.size(); i++)
|
||||
remap[i] = -1;
|
||||
|
||||
int toremove = mesh.fn - target_faces;
|
||||
|
||||
cerr << "counting" << endl;
|
||||
map<float, pair<int, int> > dist;
|
||||
for(int i = 0; i < mesh.vert.size(); i++) {
|
||||
if(mesh.vert[i].IsD()) continue;
|
||||
if(!mesh.vert[i].IsW()) continue;
|
||||
for(int k = i+1; k < mesh.vert.size(); k++) {
|
||||
if(mesh.vert[k].IsD()) continue;
|
||||
if(!mesh.vert[k].IsW()) continue;
|
||||
float d = (mesh.vert[i].P() - mesh.vert[k].P()).SquaredNorm();
|
||||
dist[d] = make_pair(i, k);
|
||||
}
|
||||
}
|
||||
|
||||
cerr << "done" << endl;
|
||||
map<float, pair<int, int> >::iterator s;
|
||||
for(s = dist.begin(); s != dist.end(); s++) {
|
||||
if(toremove < 0) break;
|
||||
int target = (*s).second.first;
|
||||
int source = (*s).second.second;
|
||||
|
||||
if(remap[target] != -1) continue;
|
||||
if(remap[source] != -1) continue;
|
||||
|
||||
assert(!mesh.vert[target].IsD());
|
||||
assert(!mesh.vert[source].IsD());
|
||||
|
||||
mesh.vert[source].SetD();
|
||||
remap[source] = target;
|
||||
remap[target] = target;
|
||||
toremove -= 2;
|
||||
mesh.vn--;
|
||||
// if(mesh.vn < starting/2) break;
|
||||
}
|
||||
|
||||
//PULIAMO LE FACCE
|
||||
for(int i = 0; i < mesh.face.size(); i++) {
|
||||
MyFace &face = mesh.face[i];
|
||||
if(face.IsD()) continue;
|
||||
for(int k = 0; k < 3; k++) {
|
||||
if(face.V(k)->IsD()) {
|
||||
face.V(k) = &mesh.vert[remap[face.V(k) - &mesh.vert[0]]];
|
||||
}
|
||||
assert(!face.V(k)->IsD());
|
||||
}
|
||||
if(face.V(0) == face.V(1) || face.V(0) == face.V(2) ||
|
||||
face.V(1) == face.V(2)) {
|
||||
face.SetD();
|
||||
mesh.fn--;
|
||||
}
|
||||
}
|
||||
cerr << "Ending faces: " << mesh.fn << endl;
|
||||
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#include <iostream>
|
||||
#include <assert.h>
|
||||
#include "nexus.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -10,7 +11,7 @@ Nexus::~Nexus() {
|
|||
Close();
|
||||
}
|
||||
|
||||
bool Nexus::Create(const string &file, Patch::Signature sig) {
|
||||
bool Nexus::Create(const string &file, Signature sig) {
|
||||
index_file = fopen((file + ".nxs").c_str(), "wb+");
|
||||
if(!index_file) {
|
||||
cerr << "Could not create file: " << file << ".nxs\n";
|
||||
|
@ -132,7 +133,7 @@ Patch Nexus::GetPatch(unsigned int patch) {
|
|||
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);
|
||||
return Border(start, entry.border_used);
|
||||
}
|
||||
|
||||
|
||||
|
@ -143,6 +144,7 @@ unsigned int Nexus::AddPatch(unsigned int nvert, unsigned int nface,
|
|||
entry.patch_size = Patch::ChunkSize(signature, nvert, nface);
|
||||
entry.border_start = borders.Size();
|
||||
entry.border_size = nbord;
|
||||
entry.border_used = 0;
|
||||
entry.nvert = nvert;
|
||||
entry.nface = nface;
|
||||
|
||||
|
@ -160,6 +162,11 @@ void Nexus::Join(const std::set<unsigned int> &patches,
|
|||
std::vector<Link> &newbord) {
|
||||
|
||||
map<unsigned int, vector<unsigned int> > remap;
|
||||
set<Link> newborders;
|
||||
set<unsigned int> erased;
|
||||
for(int u = 0; u < history.size(); u++)
|
||||
for(int e = 0; e < history[u].erased.size(); e++)
|
||||
erased.insert(history[u].erased[e]);
|
||||
|
||||
set<unsigned int>::const_iterator i;
|
||||
for(i = patches.begin(); i != patches.end(); i++) {
|
||||
|
@ -167,29 +174,42 @@ void Nexus::Join(const std::set<unsigned int> &patches,
|
|||
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;
|
||||
vector<unsigned int> &vmap = remap[*i];
|
||||
|
||||
Nexus::Entry &entry = index[patch];
|
||||
fcount += entry.nface;
|
||||
assert(fcount < 0xffff);
|
||||
// assert(fcount < 0xffff);
|
||||
for(unsigned int k = 0; k < entry.nvert; k++) {
|
||||
if(remap[patch][k] == 0xffffffff) { //first time
|
||||
remap[patch][k] = vcount++;
|
||||
if(vmap[k] == 0xffffffff) { //first time
|
||||
vmap[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;
|
||||
}
|
||||
Link link = border[k];
|
||||
if(link.IsNull()) continue;
|
||||
|
||||
assert(link.start_vert < entry.nvert);
|
||||
assert(vmap[link.start_vert] != 0xffffffff);
|
||||
|
||||
if(!remap.count(link.end_patch)) { //external
|
||||
//test if erased in history... in wich case we do not add border
|
||||
if(!erased.count(link.end_patch)) {
|
||||
link.start_vert = vmap[link.start_vert];
|
||||
newborders.insert(link);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//internal
|
||||
if(remap[link.end_patch][link.end_vert] == 0xffffffff) { //first time
|
||||
remap[link.end_patch][link.end_vert] = remap[patch][link.start_vert];
|
||||
remap[link.end_patch][link.end_vert] = vmap[link.start_vert];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,32 +218,43 @@ void Nexus::Join(const std::set<unsigned int> &patches,
|
|||
|
||||
newvert.resize(vcount);
|
||||
newface.resize(fcount*3);
|
||||
newbord.resize(bcount);
|
||||
newbord.resize(0);
|
||||
|
||||
fcount = 0;
|
||||
bcount = 0;
|
||||
for(i = patches.begin(); i != patches.end(); i++) {
|
||||
Patch patch = GetPatch(*i);
|
||||
Border border = GetBorder(*i);
|
||||
// Border border = GetBorder(*i);
|
||||
|
||||
vector<unsigned int> &vmap = remap[*i];
|
||||
|
||||
for(unsigned int i = 0; i < patch.VertSize(); i++)
|
||||
for(unsigned int i = 0; i < patch.nv; i++) {
|
||||
assert(vmap[i] < vcount);
|
||||
newvert[vmap[i]] = patch.Vert(i);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < patch.FaceSize(); i++) {
|
||||
for(unsigned int i = 0; i < patch.nf; i++) {
|
||||
for(int k = 0; k < 3; k++) {
|
||||
newface[3*fcount + k] = vmap[patch.Face(i)[k]];
|
||||
}
|
||||
fcount++;
|
||||
assert(fcount *3 <= newface.size());
|
||||
}
|
||||
for(unsigned int i = 0; i < border.Size(); i++) {
|
||||
Link &link = border[i];
|
||||
if(remap.count(link.end_patch)) continue;
|
||||
/* for(unsigned int i = 0; i < border.Size(); i++) {
|
||||
Link link = border[i];
|
||||
if(patches.count(link.end_patch)) continue;
|
||||
link.start_vert = vmap[link.start_vert];
|
||||
newbord.push_back(link);*/
|
||||
|
||||
/* if(remap.count(link.end_patch)) continue;
|
||||
Link newlink = link;
|
||||
newlink.start_vert = vmap[link.start_vert];
|
||||
newbord[bcount++] = newlink;
|
||||
}
|
||||
newbord[bcount++] = newlink;*/
|
||||
// }
|
||||
}
|
||||
set<Link>::iterator b;
|
||||
for(b = newborders.begin(); b != newborders.end(); b++)
|
||||
newbord.push_back(*b);
|
||||
|
||||
/* unsigned int newentry = AddPatch(vcount, fcount, bcount);
|
||||
Patch newpatch = GetPatch(newentry);
|
||||
Border newborder = GetBorder(newentry);
|
||||
|
@ -238,3 +269,91 @@ void Nexus::Join(const std::set<unsigned int> &patches,
|
|||
newbord.size() * sizeof(Link));*/
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void Nexus::Unify(float threshold) {
|
||||
//TODO what if colors or normals or strips?
|
||||
//TODO update totvert
|
||||
unsigned int duplicated = 0;
|
||||
for(unsigned int p = 0; p < index.size(); p++) {
|
||||
Nexus::Entry &entry = index[p];
|
||||
Patch patch = GetPatch(p);
|
||||
|
||||
unsigned int vcount = 0;
|
||||
map<Point3f, unsigned short> vertices;
|
||||
vector<unsigned short> remap;
|
||||
remap.resize(patch.nv);
|
||||
// map<unsigned short, unsigned short> remap;
|
||||
for(unsigned int i = 0; i < patch.nv; i++) {
|
||||
Point3f &point = patch.Vert(i);
|
||||
|
||||
if(!vertices.count(point)) {
|
||||
vertices[point] = vcount++;
|
||||
} else {
|
||||
duplicated++;
|
||||
}
|
||||
|
||||
remap[i] = vertices[point];
|
||||
}
|
||||
assert(vertices.size() <= patch.nv);
|
||||
if(vertices.size() == patch.nv) //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.nf * 3);
|
||||
for(unsigned int f = 0; f < newface.size(); f++)
|
||||
newface[f] = remap[patch.FaceBegin()[f]];
|
||||
|
||||
//rewrite patch now.
|
||||
entry.nvert = newvert.size();
|
||||
patch.Init(signature, 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 = 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 = 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 < index.size(); p++) {
|
||||
Border border = GetBorder(p);
|
||||
//Nexus::Entry &entry = 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]);
|
||||
}
|
||||
}
|
||||
totvert -= duplicated;
|
||||
// cout << "Found " << duplicated << " duplicated vertices" << endl;
|
||||
|
||||
}
|
||||
|
|
|
@ -19,17 +19,19 @@ class Nexus {
|
|||
|
||||
struct Entry {
|
||||
Entry(): patch_start(0xffffffff), border_start(0xffffffff),
|
||||
patch_size(0), border_size(0),
|
||||
patch_size(0), border_size(0), border_used(0),
|
||||
nvert(0), nface(0), sphere(vcg::Sphere3f()) {}
|
||||
|
||||
unsigned int patch_start; //granularita' Chunk
|
||||
unsigned int border_start; //granuralita' Link
|
||||
unsigned short patch_size; //in cuhnks
|
||||
unsigned short border_size; //in Links
|
||||
unsigned short border_used; //in Links
|
||||
|
||||
//Data used for extraction
|
||||
unsigned short nvert;
|
||||
unsigned short nface;
|
||||
vcg::Sphere3f sphere;
|
||||
|
||||
float error;
|
||||
unsigned short ram;
|
||||
unsigned short agp;
|
||||
|
@ -43,13 +45,16 @@ class Nexus {
|
|||
|
||||
Nexus();
|
||||
~Nexus();
|
||||
bool Create(const std::string &filename, Patch::Signature signature);
|
||||
bool Create(const std::string &filename, Signature signature);
|
||||
bool Load(const std::string &filename);
|
||||
void Close();
|
||||
|
||||
Patch GetPatch(unsigned int patch);
|
||||
Border GetBorder(unsigned int patch);
|
||||
|
||||
|
||||
//MOVE to nexus_build.cpp
|
||||
|
||||
unsigned int AddPatch(unsigned int nvert, unsigned int nface,
|
||||
unsigned int nbord);
|
||||
|
||||
|
@ -59,12 +64,15 @@ class Nexus {
|
|||
std::vector<unsigned int> &faces,
|
||||
std::vector<Link> &links);
|
||||
|
||||
void Unify(float threshold = 0.0f);
|
||||
|
||||
//TODO implement theese
|
||||
void CompactBorder(unsigned int patch);
|
||||
void CompactBorders();
|
||||
void CompactPatches();
|
||||
|
||||
Patch::Signature signature;
|
||||
|
||||
|
||||
Signature signature;
|
||||
|
||||
unsigned int totvert;
|
||||
unsigned int totface;
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
#include "nexusmt.h"
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
using namespace nxs;
|
||||
using namespace std;
|
||||
|
||||
void NexusMt::LoadHistory() {
|
||||
//The last update erases everything.
|
||||
assert(history[0].erased.size() == 0);
|
||||
|
||||
//maps cell -> node containing it
|
||||
map<unsigned int, unsigned int> cell_node;
|
||||
nodes.resize(history.size());
|
||||
|
||||
//building fragments and nodes.
|
||||
unsigned int current_node = 0;
|
||||
vector<Update>::iterator u;
|
||||
for(u = history.begin(); u != history.end(); u++) {
|
||||
|
||||
Node &node = nodes[current_node];
|
||||
node.error = 0;
|
||||
|
||||
//created cells belong to this node, we look also for max error.
|
||||
for(unsigned int i = 0; i < (*u).created.size(); i++) {
|
||||
unsigned int cell = (*u).created[i];
|
||||
if(index[cell].error > node.error)
|
||||
node.error = index[cell].error;
|
||||
|
||||
cell_node[cell] = current_node;
|
||||
}
|
||||
|
||||
//Every erased cell already belonged to a node.
|
||||
//we record for each node its cells.
|
||||
map<unsigned int, vector<unsigned int> > node_erased;
|
||||
|
||||
for(unsigned int i = 0; i < (*u).erased.size(); i++) {
|
||||
unsigned int cell = (*u).erased[i];
|
||||
assert(cell_node.count(cell));
|
||||
node_erased[cell_node[cell]].push_back(cell);
|
||||
}
|
||||
|
||||
//for every node with erased cells we build a frag and
|
||||
//put the corresponding cells in it.
|
||||
map<unsigned int, vector<unsigned int> >::iterator e;
|
||||
for(e = node_erased.begin(); e != node_erased.end(); e++) {
|
||||
//Build a new Frag.
|
||||
Frag fr;
|
||||
float max_err = -1;
|
||||
|
||||
//Fill it with erased cells.
|
||||
vector<unsigned int> &cells = (*e).second;
|
||||
vector<unsigned int>::iterator k;
|
||||
for(k = cells.begin(); k != cells.end(); k++) {
|
||||
unsigned int cell = (*k);
|
||||
fr.push_back(cell);
|
||||
if(index[cell].error > max_err)
|
||||
max_err = index[cell].error;
|
||||
}
|
||||
|
||||
//Add the new Frag to the node.
|
||||
unsigned int floor_node = (*e).first;
|
||||
Node &oldnode = nodes[floor_node];
|
||||
oldnode.frags.push_back(fr);
|
||||
if(node.error < max_err)
|
||||
node.error = max_err;
|
||||
|
||||
//Update in and out of the nodes.
|
||||
node.in.push_back(&oldnode);
|
||||
oldnode.out.push_back(&node);
|
||||
}
|
||||
current_node++;
|
||||
}
|
||||
}
|
||||
|
||||
void NexusMt::ClearHistory() {
|
||||
nodes.clear();
|
||||
}
|
||||
|
||||
void NexusMt::ExtractFixed(vector<unsigned int> &selected, float error) {
|
||||
std::vector<Node>::iterator n;
|
||||
for(n = nodes.begin(); n != nodes.end(); n++)
|
||||
(*n).visited = false;
|
||||
|
||||
std::queue<Node *> qnodo;
|
||||
qnodo.push(&nodes[0]);
|
||||
nodes[0].visited = true;
|
||||
|
||||
for( ; !qnodo.empty(); qnodo.pop()) {
|
||||
Node &node = *qnodo.front();
|
||||
|
||||
std::vector<Frag>::iterator fragment;
|
||||
std::vector<Node *>::iterator on;
|
||||
for(on = node.out.begin(), fragment = node.frags.begin();
|
||||
on != node.out.end(); ++on, ++fragment) {
|
||||
|
||||
if((*on)->visited) continue;
|
||||
|
||||
if(error < (*on)->error) { //need to expand this node.
|
||||
qnodo.push(*on);
|
||||
(*on)->visited = 1;
|
||||
} else {
|
||||
vector<unsigned int>::iterator cell;
|
||||
for(cell=(*fragment).begin(); cell != (*fragment).end(); ++cell)
|
||||
selected.push_back(*cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef NXS_NEXUS_MT_H
|
||||
#define NXS_NEXUS_MT_H
|
||||
|
||||
|
||||
#include "nexus.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
class NexusMt: public Nexus {
|
||||
private:
|
||||
|
||||
class Frag:public std::vector<unsigned int> {};
|
||||
|
||||
struct Node {
|
||||
std::vector<Node *> in;
|
||||
std::vector<Node *> out;
|
||||
std::vector<Frag> frags;
|
||||
float error;
|
||||
bool visited;
|
||||
};
|
||||
|
||||
std::vector<Node> nodes;
|
||||
public:
|
||||
void LoadHistory();
|
||||
void ClearHistory();
|
||||
|
||||
void ExtractFixed(std::vector<unsigned int> &selected, float error);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -24,6 +24,9 @@
|
|||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.5 2004/09/16 14:25:16 ponchio
|
||||
Backup. (lot of changes).
|
||||
|
||||
Revision 1.4 2004/08/27 00:38:34 ponchio
|
||||
Minor changes.
|
||||
|
||||
|
@ -161,6 +164,7 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
bool rotate = true;
|
||||
bool show_borders = true;
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
|
@ -170,8 +174,7 @@ int main(int argc, char *argv[]) {
|
|||
SDL_Event event;
|
||||
int x, y;
|
||||
float alpha = 0;
|
||||
while( !quit ) {
|
||||
while( SDL_PollEvent( &event ) ){
|
||||
while( !quit ) { while( SDL_PollEvent( &event ) ){
|
||||
switch( event.type ) {
|
||||
case SDL_QUIT: quit = 1; break;
|
||||
case SDL_KEYDOWN:
|
||||
|
@ -245,7 +248,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
glBegin(GL_TRIANGLES);
|
||||
unsigned short *f = patch.FaceBegin();
|
||||
for(unsigned int j = 0; j < patch.FaceSize()*3; j+= 3) {
|
||||
for(unsigned int j = 0; j < patch.nf*3; j+= 3) {
|
||||
Point3f &p1 = patch.Vert(f[j]);
|
||||
Point3f &p2 = patch.Vert(f[j+1]);
|
||||
Point3f &p3 = patch.Vert(f[j+2]);
|
||||
|
@ -257,21 +260,28 @@ int main(int argc, char *argv[]) {
|
|||
glVertex3f(p3[0], p3[1], p3[2]);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
//drawing borders
|
||||
glColor3f(1, 1, 1);
|
||||
|
||||
Border border = nexus.GetBorder(cell);
|
||||
glPointSize(2);
|
||||
glDisable(GL_LIGHTING);
|
||||
glBegin(GL_POINTS);
|
||||
for(unsigned int k = 0; k < border.Size(); k++) {
|
||||
if(border[k].IsNull()) continue;
|
||||
Point3f &p = patch.Vert(border[k].start_vert);
|
||||
glVertex3f(p[0], p[1], p[2]);
|
||||
}
|
||||
if(show_borders) {
|
||||
for(unsigned int i = 0; i < cells.size(); i++) {
|
||||
unsigned int cell = cells[i];
|
||||
Patch patch = nexus.GetPatch(cell);
|
||||
//drawing borders
|
||||
glColor3f(1, 1, 1);
|
||||
|
||||
Border border = nexus.GetBorder(cell);
|
||||
glPointSize(4);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glBegin(GL_POINTS);
|
||||
for(unsigned int k = 0; k < border.Size(); k++) {
|
||||
if(border[k].IsNull()) continue;
|
||||
Point3f &p = patch.Vert(border[k].start_vert);
|
||||
glVertex3f(p[0], p[1], p[2]);
|
||||
}
|
||||
glEnd();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
glEnd();
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
#include "patch.h"
|
||||
|
||||
using namespace nxs;
|
||||
|
||||
|
||||
Patch::Patch(Signature signature, Chunk *s,
|
||||
unsigned short nvert, unsigned short nface):
|
||||
start(s) {
|
||||
Init(signature, nvert, nface);
|
||||
}
|
||||
|
||||
void Patch::Init(Signature signature,
|
||||
unsigned short nvert, unsigned short nface) {
|
||||
nv = nvert;
|
||||
nf = nface;
|
||||
|
||||
if(signature & HAS_FACES)
|
||||
vstart = (float *)(((char *)start) + nf * sizeof(unsigned short) * 3);
|
||||
else if(signature & HAS_STRIP)
|
||||
vstart = (float *)(((char *)start) + nf * sizeof(unsigned short));
|
||||
else
|
||||
vstart = (float *)start;
|
||||
|
||||
//align memory
|
||||
if(((int)vstart) & 0x2) vstart = (float *)(((char *)vstart) + 2);
|
||||
|
||||
cstart = nv * sizeof(float) * 3;
|
||||
nstart = cstart + nv * sizeof(unsigned int) * (signature & HAS_COLORS);
|
||||
|
||||
if(signature & HAS_NORMALS_SHORT)
|
||||
tstart = nstart + nv * sizeof(short) * 3;
|
||||
else if(signature & HAS_NORMALS_FLOAT)
|
||||
tstart = nstart + nv * sizeof(float) * 3;
|
||||
else
|
||||
tstart = nstart;
|
||||
|
||||
if(signature & HAS_TEXTURES_SHORT)
|
||||
dstart = tstart + nv * sizeof(short) * 2;
|
||||
else if(signature & HAS_TEXTURES_FLOAT)
|
||||
dstart = tstart + nv * sizeof(float) * 2;
|
||||
else
|
||||
dstart = tstart;
|
||||
}
|
||||
|
||||
unsigned int Patch::ChunkSize(Signature signature,
|
||||
unsigned short nvert,
|
||||
unsigned short nface) {
|
||||
unsigned int size = ByteSize(signature, nvert, nface);
|
||||
size = (size/sizeof(Chunk) + 1);
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned int Patch::ByteSize(Signature signature,
|
||||
unsigned short nvert,
|
||||
unsigned short nface) {
|
||||
unsigned int size = 0;
|
||||
if(signature & HAS_STRIP)
|
||||
size += nface * sizeof(unsigned short);
|
||||
else if(signature & HAS_FACES)
|
||||
size += nface * 3 * sizeof(unsigned short);
|
||||
|
||||
//memory alignment
|
||||
if(size & 0x2) size += 2;
|
||||
|
||||
size += nvert * sizeof(vcg::Point3f);
|
||||
|
||||
if(signature & HAS_COLORS)
|
||||
size += nvert * sizeof(unsigned int);
|
||||
|
||||
if(signature & HAS_NORMALS_SHORT)
|
||||
size += nvert * 4 * sizeof(short);
|
||||
|
||||
if(signature & HAS_NORMALS_FLOAT)
|
||||
size += nvert * 3 * sizeof(float);
|
||||
|
||||
if(signature & HAS_TEXTURES_SHORT)
|
||||
size += nvert * 2 * sizeof(short);
|
||||
|
||||
if(signature & HAS_TEXTURES_FLOAT)
|
||||
size += nvert * 2 * sizeof(float);
|
||||
|
||||
if(signature & HAS_DATA8)
|
||||
size += nvert * sizeof(char);
|
||||
if(signature & HAS_DATA16)
|
||||
size += nvert * 2 * sizeof(char);
|
||||
if(signature & HAS_DATA32)
|
||||
size += nvert * 4 * sizeof(char);
|
||||
if(signature & HAS_DATA64)
|
||||
size += nvert * 8 * sizeof(char);
|
||||
|
||||
|
||||
//this condition should really rarely happen but helps save space
|
||||
//during construction
|
||||
if(size < nface * 3 * sizeof(unsigned int))
|
||||
size = nface * 3 * sizeof(unsigned int);
|
||||
|
||||
return size;
|
||||
}
|
|
@ -5,134 +5,73 @@
|
|||
#include <iostream>
|
||||
namespace nxs {
|
||||
|
||||
enum Signature {
|
||||
HAS_FACES = 0x00000001,
|
||||
HAS_STRIP = 0x00000002,
|
||||
HAS_COLORS = 0x00000010,
|
||||
HAS_NORMALS_SHORT = 0x00000100,
|
||||
HAS_NORMALS_FLOAT = 0x00000200,
|
||||
HAS_TEXTURES_SHORT = 0x00001000,
|
||||
HAS_TEXTURES_FLOAT = 0x00002000,
|
||||
HAS_DATA8 = 0x00010000,
|
||||
HAS_DATA16 = 0x00020000,
|
||||
HAS_DATA32 = 0x00040000,
|
||||
HAS_DATA64 = 0x00080000 };
|
||||
|
||||
struct Chunk {
|
||||
unsigned char p[4096];
|
||||
};
|
||||
|
||||
|
||||
class Patch {
|
||||
public:
|
||||
|
||||
enum Signature { DEFAULT = 0,
|
||||
HAS_STRIP = 0x002, //if true faces saved as strip
|
||||
HAS_COLORS = 0x004,
|
||||
HAS_NORMALS_SHORT = 0x008,
|
||||
HAS_NORMALS_FLOAT = 0x008,
|
||||
HAS_TEXTURES_SHORT = 0x010,
|
||||
HAS_TEXTURES_FLOAT = 0x020,
|
||||
HAS_DATA8 = 0x040,
|
||||
HAS_DATA16 = 0x080,
|
||||
HAS_DATA32 = 0x100,
|
||||
HAS_DATA64 = 0x200 };
|
||||
|
||||
Patch(Signature signature, Chunk *s = NULL,
|
||||
unsigned short nv = 0, unsigned short nf = 0):
|
||||
start(s) {
|
||||
Resize(signature, nv, nf);
|
||||
}
|
||||
Patch(Signature signature, Chunk *s,
|
||||
unsigned short nv, unsigned short nf);
|
||||
|
||||
void Resize(Signature signature, unsigned short nv, unsigned short nf) {
|
||||
nvert = nv;
|
||||
nface = nf;
|
||||
fstart = (unsigned short *)(((char *)start) +
|
||||
VertSize() * sizeof(vcg::Point3f));
|
||||
void Init(Signature signature, unsigned short nv, unsigned short nf);
|
||||
|
||||
unsigned int size = nf * sizeof(unsigned short);
|
||||
if(!(signature & HAS_STRIP)) size *= 3;
|
||||
cstart = (void *)(((char *)fstart) + size);
|
||||
inline vcg::Point3f *VertBegin();
|
||||
inline unsigned short *FaceBegin();
|
||||
|
||||
if(signature & HAS_COLORS) size = nv * sizeof(unsigned int);
|
||||
else size = 0;
|
||||
|
||||
nstart = (void *)(((char *)cstart) + size);
|
||||
|
||||
size = 0;
|
||||
if(signature & HAS_NORMALS_SHORT) size = nv * 4*sizeof(short);
|
||||
if(signature & HAS_NORMALS_FLOAT) size = nv * 4*sizeof(float);
|
||||
|
||||
tstart = (void *)(((char *)cstart) + size);
|
||||
|
||||
size = 0;
|
||||
if(signature & HAS_TEXTURES_SHORT) size = nv * 2*sizeof(short);
|
||||
if(signature & HAS_TEXTURES_FLOAT) size = nv * 2*sizeof(float);
|
||||
|
||||
dstart = (void *)(((char *)tstart) + size);
|
||||
}
|
||||
|
||||
unsigned short VertSize() { return nvert; }
|
||||
|
||||
vcg::Point3f *VertBegin() { return (vcg::Point3f *)(start); }
|
||||
|
||||
unsigned short FaceSize() { return nface; }
|
||||
|
||||
unsigned short *FaceBegin() { return fstart; }
|
||||
|
||||
vcg::Point3f &Vert(unsigned int v) { return VertBegin()[v]; }
|
||||
|
||||
unsigned short *Face(unsigned int f) { return FaceBegin() + f * 3; }
|
||||
inline vcg::Point3f &Vert(unsigned short v);
|
||||
inline unsigned short *Face(unsigned short f);
|
||||
|
||||
// unsigned int ChunkSize() { return ChunkSize(VertSize(), FaceSize()); }
|
||||
|
||||
// unsigned int ByteSize() { return ByteSize(VertSize(), FaceSize()); }
|
||||
|
||||
static unsigned int ChunkSize(Signature signature,
|
||||
unsigned short nvert, unsigned short nface) {
|
||||
unsigned int size = ByteSize(signature, nvert, nface);
|
||||
size = (size/sizeof(Chunk) + 1);
|
||||
return size;
|
||||
}
|
||||
unsigned short nvert,
|
||||
unsigned short nface);
|
||||
|
||||
static unsigned int ByteSize(Signature signature,
|
||||
unsigned short nvert, unsigned short nface) {
|
||||
unsigned int size = nvert * sizeof(vcg::Point3f);
|
||||
if(signature & HAS_STRIP)
|
||||
size += nface * sizeof(unsigned short);
|
||||
else
|
||||
size += nface * 3 * sizeof(unsigned short);
|
||||
|
||||
if(signature & HAS_COLORS)
|
||||
size += nvert * sizeof(unsigned int);
|
||||
unsigned short nvert,
|
||||
unsigned short nface);
|
||||
|
||||
if(signature & HAS_NORMALS_SHORT)
|
||||
size += nvert * 4 * sizeof(short);
|
||||
|
||||
if(signature & HAS_NORMALS_FLOAT)
|
||||
size += nvert * 3 * sizeof(float);
|
||||
|
||||
if(signature & HAS_TEXTURES_SHORT)
|
||||
size += nvert * 2 * sizeof(short);
|
||||
|
||||
if(signature & HAS_TEXTURES_FLOAT)
|
||||
size += nvert * 2 * sizeof(float);
|
||||
|
||||
if(signature & HAS_DATA8)
|
||||
size += nvert * sizeof(char);
|
||||
if(signature & HAS_DATA16)
|
||||
size += nvert * 2 * sizeof(char);
|
||||
if(signature & HAS_DATA32)
|
||||
size += nvert * 4 * sizeof(char);
|
||||
if(signature & HAS_DATA64)
|
||||
size += nvert * 8 * sizeof(char);
|
||||
|
||||
|
||||
//this condition should really rarely happen but helps save space
|
||||
//during construction
|
||||
if(size < nface * 3 * sizeof(unsigned int))
|
||||
size = nface * 3 * sizeof(unsigned int);
|
||||
|
||||
return size;
|
||||
}
|
||||
// private:
|
||||
unsigned short nvert;
|
||||
unsigned short nface;
|
||||
|
||||
Chunk *start;
|
||||
unsigned short *fstart;
|
||||
void *cstart;
|
||||
void *nstart;
|
||||
void *tstart;
|
||||
void *dstart;
|
||||
|
||||
unsigned short nv;
|
||||
unsigned short nf;
|
||||
|
||||
float *vstart;
|
||||
unsigned short cstart;
|
||||
unsigned short nstart;
|
||||
unsigned short tstart;
|
||||
unsigned short dstart;
|
||||
};
|
||||
|
||||
};
|
||||
inline vcg::Point3f *Patch::VertBegin() {
|
||||
return (vcg::Point3f *)vstart;
|
||||
}
|
||||
inline unsigned short *Patch::FaceBegin() {
|
||||
return (unsigned short *)start;
|
||||
}
|
||||
|
||||
inline vcg::Point3f &Patch::Vert(unsigned short v) {
|
||||
return VertBegin()[v];
|
||||
}
|
||||
inline unsigned short *Patch::Face(unsigned short f) {
|
||||
return FaceBegin() + f * 3;
|
||||
}
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.2 2004/09/16 14:25:16 ponchio
|
||||
Backup. (lot of changes).
|
||||
|
||||
Revision 1.1 2004/08/26 18:03:47 ponchio
|
||||
First draft.
|
||||
|
||||
|
@ -173,7 +176,7 @@ void VoronoiChain::BuildLevel(Nexus &nexus, unsigned int offset) {
|
|||
|
||||
for(unsigned int idx = offset; idx < nexus.index.size(); idx++) {
|
||||
Patch patch = nexus.GetPatch(idx);
|
||||
for(unsigned int i = 0; i < patch.VertSize(); i++) {
|
||||
for(unsigned int i = 0; i < patch.nv; i++) {
|
||||
Point3f &v = patch.Vert(i);
|
||||
unsigned int target_patch;
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
History
|
||||
|
||||
$Log: not supported by cvs2svn $
|
||||
Revision 1.2 2004/09/16 14:25:16 ponchio
|
||||
Backup. (lot of changes).
|
||||
|
||||
Revision 1.1 2004/08/26 18:03:48 ponchio
|
||||
First draft.
|
||||
|
||||
|
@ -158,7 +161,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
string output = argv[optind+1];
|
||||
|
||||
Patch::Signature signature = Patch::DEFAULT;
|
||||
Signature signature = HAS_FACES;
|
||||
Nexus nexus;
|
||||
if(!nexus.Create(output, signature)) {
|
||||
cerr << "Could not create nexus output: " << output << endl;
|
||||
|
@ -218,6 +221,9 @@ int main(int argc, char *argv[]) {
|
|||
update.created.push_back(i);
|
||||
nexus.history.push_back(update);
|
||||
|
||||
//unify vertices otherwise you may get cracks.
|
||||
nexus.Unify();
|
||||
|
||||
/* BUILDING OTHER LEVELS */
|
||||
unsigned int oldoffset = 0;
|
||||
|
||||
|
@ -227,6 +233,7 @@ int main(int argc, char *argv[]) {
|
|||
unsigned int newoffset = nexus.index.size();
|
||||
vchain.BuildLevel(nexus, oldoffset);
|
||||
|
||||
vector<Nexus::Update> level_history;
|
||||
map<unsigned int, set<unsigned int> >::iterator fragment;
|
||||
for(fragment = vchain.oldfragments.begin();
|
||||
fragment != vchain.oldfragments.end(); fragment++) {
|
||||
|
@ -235,12 +242,12 @@ int main(int argc, char *argv[]) {
|
|||
update.created.clear();
|
||||
update.erased.clear();
|
||||
|
||||
cerr << "Joining: ";
|
||||
cerr << "Join ";
|
||||
set<unsigned int> &fcells = (*fragment).second;
|
||||
set<unsigned int>::iterator s;
|
||||
for(s = fcells.begin(); s != fcells.end(); s++) {
|
||||
update.erased.push_back(*s);
|
||||
cerr << " " << (*s) << endl;
|
||||
cerr << *s << " ";
|
||||
}
|
||||
cerr << endl;
|
||||
|
||||
|
@ -253,23 +260,26 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
//simplyfy mesh
|
||||
vector<int> vert_remap;
|
||||
float error = Decimate(newface.size() * scaling/3, newvert,
|
||||
newface, newbord, vert_remap);
|
||||
float error = Decimate((unsigned int)(newface.size() * scaling/3),
|
||||
newvert, newface, newbord, vert_remap);
|
||||
|
||||
|
||||
NexusSplit(nexus, vchain, level, newvert, newface, newbord,
|
||||
update, error);
|
||||
|
||||
|
||||
nexus.history.push_back(update);
|
||||
level_history.push_back(update);
|
||||
}
|
||||
|
||||
for(int i = 0; i < level_history.size(); i++)
|
||||
nexus.history.push_back(level_history[i]);
|
||||
//if(vchain.levels.back().size() == 1) break;
|
||||
if(vchain.oldfragments.size() == 1) break;
|
||||
|
||||
vchain.oldfragments = vchain.newfragments;
|
||||
oldoffset = newoffset;
|
||||
}
|
||||
|
||||
//last level clean history:
|
||||
update.created.clear();
|
||||
update.erased.clear();
|
||||
|
@ -284,7 +294,7 @@ int main(int argc, char *argv[]) {
|
|||
nexus.history.push_back(update);
|
||||
ReverseHistory(nexus.history);
|
||||
//debug:
|
||||
for(unsigned int i = 0; i < nexus.history.size(); i++) {
|
||||
/* for(unsigned int i = 0; i < nexus.history.size(); i++) {
|
||||
Nexus::Update &update = nexus.history[i];
|
||||
cerr << "created:";
|
||||
for(unsigned int c = 0; c < update.created.size(); c++)
|
||||
|
@ -293,7 +303,7 @@ int main(int argc, char *argv[]) {
|
|||
for(unsigned int c = 0; c < update.erased.size(); c++)
|
||||
cerr << " " << update.erased[c];
|
||||
cerr << "\n\n";
|
||||
}
|
||||
}*/
|
||||
|
||||
//Clean up:
|
||||
nexus.Close();
|
||||
|
@ -359,9 +369,12 @@ void NexusAllocate(Crude &crude,
|
|||
unsigned int npatch = face_remap[i];
|
||||
|
||||
Nexus::Entry &entry = nexus.index[npatch];
|
||||
|
||||
//TODO this is slow because we have to initialize patch.
|
||||
//just get patch.start.
|
||||
Patch patch = nexus.GetPatch(npatch);
|
||||
|
||||
Crude::Face *faces = (Crude::Face *)patch.VertBegin();
|
||||
Crude::Face *faces = (Crude::Face *)patch.start;
|
||||
faces[entry.nface] = face;
|
||||
entry.nface++;
|
||||
}
|
||||
|
@ -385,20 +398,20 @@ void NexusFill(Crude &crude,
|
|||
Nexus::Entry &entry = nexus.index[i];
|
||||
|
||||
//make a copy of faces (we need to write there :P)
|
||||
Crude::Face *faces = new Crude::Face[patch.FaceSize()];
|
||||
memcpy(faces, (Crude::Face *)patch.VertBegin(),
|
||||
patch.FaceSize() * sizeof(Crude::Face));
|
||||
|
||||
Crude::Face *faces = new Crude::Face[patch.nf];
|
||||
memcpy(faces, (Crude::Face *)patch.start,
|
||||
patch.nf * 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++) {
|
||||
for(unsigned int k = 0; k < patch.nf; k++) {
|
||||
Crude::Face &face = faces[k];
|
||||
|
||||
for(int j = 0; j < 3; j++) {
|
||||
if(!remap.count(face[j])) {
|
||||
assert(count < patch.VertSize());
|
||||
assert(count < patch.nv);
|
||||
Point3f &v = crude.vert[face[j]];
|
||||
patch.VertBegin()[remap.size()] = v;
|
||||
entry.sphere.Add(v);
|
||||
|
@ -433,7 +446,7 @@ void NexusFill(Crude &crude,
|
|||
}
|
||||
}
|
||||
//and number of borders:
|
||||
entry.border_size = border_remap.Size() - entry.border_start;
|
||||
entry.border_used = border_remap.Size() - entry.border_start;
|
||||
delete []faces;
|
||||
}
|
||||
|
||||
|
@ -446,36 +459,49 @@ void NexusFixBorder(Nexus &nexus,
|
|||
VFile<RemapLink> &border_remap) {
|
||||
|
||||
//and last convert RemapLinks into Links
|
||||
nexus.borders.Resize(border_remap.Size());
|
||||
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;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < nexus.index.size(); i++) {
|
||||
Nexus::Entry &local = nexus.index[i];
|
||||
|
||||
unsigned int remap_start = local.border_start/2;
|
||||
//* 2 is to accomodate future borders
|
||||
|
||||
|
||||
// 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++) {
|
||||
for(unsigned int k = 0; k < local.border_used; k++) {
|
||||
|
||||
|
||||
RemapLink start_link = border_remap[k];
|
||||
RemapLink start_link = border_remap[k + remap_start];
|
||||
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++) {
|
||||
|
||||
unsigned int remote_remap_start = remote.border_start/2;
|
||||
for(unsigned int j = 0; j < remote.border_used; j++) {
|
||||
|
||||
RemapLink end_link = border_remap[j];
|
||||
RemapLink end_link = border_remap[j + remote_remap_start];
|
||||
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);
|
||||
nexus.borders[k + local.border_start] = Link(start_link.rel_vert,
|
||||
end_link.rel_vert,
|
||||
start_link.patch);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
assert(nexus.borders[k].start_vert < local.nvert);
|
||||
assert(nexus.borders[k + local.border_start].start_vert < local.nvert);
|
||||
assert(found);
|
||||
}
|
||||
}
|
||||
|
@ -512,7 +538,7 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
|
|||
Nexus::Update &update,
|
||||
float error) {
|
||||
|
||||
//if != -1 remap global index to cell index
|
||||
//if != -1 remap global index to cell index (first arg)
|
||||
map<unsigned int, vector<int> > vert_remap;
|
||||
map<unsigned int, unsigned int> vert_count;
|
||||
|
||||
|
@ -543,47 +569,113 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
|
|||
if(v_remap[newface[f+i]] == -1)
|
||||
v_remap[newface[f+i]] = vert_count[cell]++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//TODO prune small count cells
|
||||
|
||||
//for every new cell
|
||||
//lets count borders
|
||||
map<unsigned int, unsigned int> bord_count;
|
||||
|
||||
map<unsigned int, unsigned int >::iterator c;
|
||||
for(c = vert_count.begin(); c != vert_count.end(); c++) {
|
||||
unsigned int cell = (*c).first;
|
||||
cerr << "Processing cell: " << cell << endl;
|
||||
|
||||
vector<unsigned short> faces;
|
||||
vector<Point3f> verts;
|
||||
vector<Link> bords;
|
||||
|
||||
unsigned int &count = bord_count[cell];
|
||||
count = 0;
|
||||
|
||||
vector<int> &v_remap = vert_remap[cell];
|
||||
vector<int> &f_remap = face_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]);
|
||||
|
||||
//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];
|
||||
|
||||
//vertices first
|
||||
vector<int> &v_remap = vert_remap[cell];
|
||||
|
||||
vector<Point3f> verts;
|
||||
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];
|
||||
// verts.push_back(newvert[v_remap[i]]);
|
||||
}
|
||||
|
||||
assert(verts.size() == vert_count[cell]);
|
||||
assert(f_remap.size()/3 == face_count[cell]);
|
||||
|
||||
|
||||
//faces now
|
||||
vector<int> &f_remap = face_remap[cell];
|
||||
|
||||
vector<unsigned short> faces;
|
||||
faces.resize(face_count[cell]*3);
|
||||
|
||||
|
||||
for(unsigned int i = 0; i < f_remap.size(); i++) {
|
||||
assert(v_remap[f_remap[i]] != -1);
|
||||
faces[i] = v_remap[f_remap[i]];
|
||||
}
|
||||
//process external borders
|
||||
|
||||
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!
|
||||
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);
|
||||
|
||||
Nexus::Entry &rentry = nexus.index[link.end_patch];
|
||||
//TODO if !true reallocate borders.
|
||||
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;
|
||||
}
|
||||
assert(rentry.border_used < rentry.border_size);
|
||||
Border rborder = nexus.GetBorder(link.end_patch);
|
||||
|
||||
Link &newlink = rborder[rentry.border_used++];
|
||||
newlink.start_vert = link.end_vert;
|
||||
newlink.end_vert = link.start_vert;
|
||||
newlink.end_patch = patch_idx;
|
||||
}
|
||||
|
||||
|
||||
//process internal borders;
|
||||
//TODO higly inefficient!!!
|
||||
map<unsigned int, unsigned int >::iterator t;
|
||||
|
@ -593,19 +685,14 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
|
|||
for(unsigned int i = 0; i < newvert.size(); i++) {
|
||||
if(v_remap[i] != -1 && vremapclose[i] != -1) {
|
||||
Link link;
|
||||
link.end_patch = (*t).first;
|
||||
link.end_patch = cells2patches[(*t).first];
|
||||
link.start_vert = v_remap[i];
|
||||
link.end_vert = vremapclose[i];
|
||||
bords.push_back(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
//create new nexus patch
|
||||
unsigned int patch_idx = nexus.AddPatch(verts.size(),
|
||||
faces.size()/3,
|
||||
bords.size());
|
||||
vchain.newfragments[cell].insert(patch_idx);
|
||||
update.created.push_back(patch_idx);
|
||||
|
||||
|
||||
Nexus::Entry &entry = nexus.index[patch_idx];
|
||||
// entry.error = error;
|
||||
|
@ -623,9 +710,9 @@ void NexusSplit(Nexus &nexus, VoronoiChain &vchain,
|
|||
}
|
||||
|
||||
Border border = nexus.GetBorder(patch_idx);
|
||||
memcpy(&border[0], &bords[0], bords.size());
|
||||
memcpy(&(border[0]), &(bords[0]), bords.size() * sizeof(Link));
|
||||
entry.border_used = bords.size();
|
||||
}
|
||||
cerr << "newfrag: " << vchain.newfragments.size() << endl;
|
||||
}
|
||||
|
||||
void ReverseHistory(vector<Nexus::Update> &history) {
|
||||
|
|
Loading…
Reference in New Issue