vcglib/apps/nexus/decimate.cpp

261 lines
6.8 KiB
C++
Raw Normal View History

2004-09-17 17:25:59 +02:00
#include <iostream>
// stuff to define the mesh
#include <vcg/simplex/vertex/with/afvmvn.h>
2004-10-25 18:57:40 +02:00
#include <vcg/simplex/edge/edge.h>
2004-09-17 17:25:59 +02:00
#include <vcg/math/quadric.h>
#include <vcg/complex/trimesh/base.h>
#include <vcg/simplex/face/with/av.h>
#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>
2004-09-28 12:26:49 +02:00
2004-12-02 21:16:13 +01:00
#include "vpartition.h"
2004-10-22 12:33:35 +02:00
#include "fragment.h"
2004-10-01 18:54:57 +02:00
#include "decimate.h"
2004-10-06 18:40:47 +02:00
#include <wrap/io_trimesh/export_ply.h>
2004-10-01 18:54:57 +02:00
using namespace vcg;
using namespace tri;
using namespace nxs;
using namespace std;
2004-09-17 17:25:59 +02:00
class MyEdge;
class MyFace;
2004-10-01 18:54:57 +02:00
class MyVertex:
2004-10-25 18:57:40 +02:00
public vcg::VertexAFVMVNf<MyEdge, MyFace,DUMMYTETRATYPE> {
2004-10-01 18:54:57 +02:00
public:
ScalarType w;
2004-10-25 18:57:40 +02:00
vcg::math::Quadric<double> q;
2004-10-01 18:54:57 +02:00
ScalarType & W() { return w; }
};
2004-10-25 18:57:40 +02:00
struct MyEdge: public Edge<double,MyEdge,MyVertex> {
inline MyEdge():Edge<double,MyEdge,MyVertex>(){UberFlags()=0;}
inline MyEdge(MyVertex* a,MyVertex* b):Edge<double,MyEdge,MyVertex>(a,b){
UberFlags()=0;}
};
class MyFace : public vcg::FaceAV<MyVertex, MyEdge, MyFace> {};
2004-09-17 17:25:59 +02:00
class MyMesh:
2004-10-01 18:54:57 +02:00
public vcg::tri::TriMesh< std::vector<MyVertex>, std::vector<MyFace > > {};
2004-09-17 17:25:59 +02:00
2004-12-02 20:12:44 +01:00
class MyTriEdgeCollapse: public vcg::tri::TriEdgeCollapseQuadric< MyMesh, MyTriEdgeCollapse > {
public:
typedef vcg::tri::TriEdgeCollapseQuadric< MyMesh, MyTriEdgeCollapse > TECQ;
typedef TECQ::EdgeType EdgeType;
inline MyTriEdgeCollapse( EdgeType p, int i) :TECQ(p,i){}
2004-09-17 17:25:59 +02:00
};
2004-09-21 02:53:23 +02:00
float Cluster(MyMesh &mesh, unsigned int target_faces);
2004-10-01 18:54:57 +02:00
float Quadric(MyMesh &mesh, unsigned int target_faces);
float nxs::Decimate(Decimation mode,
unsigned int target_faces,
vector<Point3f> &newvert,
vector<unsigned int> &newface,
2004-12-02 20:12:44 +01:00
vector<BigLink> &newbord) {
for(unsigned int i = 0; i < newface.size(); i+= 3) {
2004-10-06 18:40:47 +02:00
assert(newface[i] != newface[i+1]);
assert(newface[i] != newface[i+2]);
assert(newface[i+1] != newface[i+2]);
}
2004-09-17 17:25:59 +02:00
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++) {
2004-10-06 18:40:47 +02:00
assert(newface[i+k] < mesh.vert.size());
2004-09-17 17:25:59 +02:00
face.V(k) = &mesh.vert[newface[i+k]];
}
mesh.face.push_back(face);
}
mesh.fn = mesh.face.size();
2004-10-01 18:54:57 +02:00
//mark borders
2004-09-17 17:25:59 +02:00
for(unsigned int i = 0; i < newbord.size(); i++)
mesh.vert[newbord[i].start_vert].ClearW();
2004-10-01 18:54:57 +02:00
float error;
2004-12-02 20:12:44 +01:00
switch(mode) {
2004-12-03 22:19:00 +01:00
case CLUSTER: error = Cluster(mesh, target_faces); break;
case QUADRIC: error = Quadric(mesh, target_faces); break;
default: cerr << "Unknown simplification mode: " << mode << endl;
exit(0);
2004-12-02 20:12:44 +01:00
}
2004-09-17 17:25:59 +02:00
newvert.clear();
newface.clear();
unsigned int totvert = 0;
2004-10-22 12:33:35 +02:00
vector<int> vert_remap;
2004-09-17 17:25:59 +02:00
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;
2004-10-06 18:40:47 +02:00
for(int k = 0; k < 3; k++)
2004-09-17 17:25:59 +02:00
newface.push_back(vert_remap[face.V(k) - vert_start]);
}
for(unsigned int i = 0; i < newbord.size(); i++) {
2004-10-22 12:33:35 +02:00
unsigned int &v = newbord[i].start_vert;
2004-09-17 17:25:59 +02:00
assert(vert_remap[v] != -1);
v = vert_remap[v];
}
2004-09-17 17:25:59 +02:00
return error;
}
2004-09-28 12:26:49 +02:00
2004-10-01 18:54:57 +02:00
float Quadric(MyMesh &mesh, unsigned int target_faces) {
vcg::tri::UpdateTopology<MyMesh>::VertexFace(mesh);
2004-12-02 20:12:44 +01:00
vcg::tri::UpdateBounding<MyMesh>::Box(mesh);
2004-10-01 18:54:57 +02:00
vcg::LocalOptimization<MyMesh> DeciSession(mesh);
MyTriEdgeCollapse::SetDefaultParams();
DeciSession.Init<MyTriEdgeCollapse>();
DeciSession.SetTargetSimplices(target_faces);
DeciSession.DoOptimization();
float error = 0;
int count = 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++) {
error += (face.cV(k)->cP() - face.cV((k+1)%3)->cP()).Norm();
count++;
}
}
error /= count;
2004-12-02 20:12:44 +01:00
return error;
return 0;
2004-10-01 18:54:57 +02:00
}
2004-09-21 02:53:23 +02:00
float Cluster(MyMesh &mesh, unsigned int target_faces) {
2004-09-17 17:25:59 +02:00
unsigned int starting = mesh.vn;
2004-10-30 22:17:03 +02:00
2004-09-28 12:26:49 +02:00
unsigned int nseeds = target_faces/2;
2004-12-03 02:20:56 +01:00
#ifndef NDEBUG
if(nseeds >= mesh.vert.size()) {
2004-12-03 22:19:00 +01:00
cerr << "Strange! nseeds > vert.size(): " << nseeds
<< " >= "<< mesh.vert.size() << endl;
2004-12-03 02:20:56 +01:00
}
#endif
2004-10-30 22:17:03 +02:00
2004-09-28 12:26:49 +02:00
vector<unsigned int> remap;
2004-10-30 22:17:03 +02:00
2004-12-02 21:16:13 +01:00
VPartition part;
2004-09-28 12:26:49 +02:00
for(unsigned int i = 0; i < mesh.vert.size(); i++) {
const Point3f &p = mesh.vert[i].cP();
if(!mesh.vert[i].IsW()) {
2004-10-30 22:17:03 +02:00
part.push_back(p);
2004-09-28 12:26:49 +02:00
remap.push_back(i);
nseeds--;
2004-09-17 17:25:59 +02:00
}
}
2004-09-28 12:26:49 +02:00
unsigned int nborder = part.size();
//Todo I should supersample before
2004-09-30 02:27:42 +02:00
while(nseeds > 0 && part.size() < mesh.vn) {
2004-09-28 12:26:49 +02:00
unsigned int i = rand() % mesh.vert.size();
if(mesh.vert[i].IsW() && !mesh.vert[i].IsV()) {
const Point3f &p = mesh.vert[i].cP();
2004-10-30 22:17:03 +02:00
part.push_back(p);
2004-09-28 12:26:49 +02:00
mesh.vert[i].SetV();
remap.push_back(i);
nseeds--;
}
}
part.Init();
vector<Point3f> centroid;
vector<unsigned int> count;
for(unsigned int i = 0; i < 3; i++) {
centroid.clear();
centroid.resize(mesh.vert.size(), Point3f(0, 0, 0));
count.clear();
count.resize(mesh.vert.size(), 0);
for(unsigned int i = 0; i < mesh.vert.size(); i++) {
unsigned int target = part.Locate(mesh.vert[i].cP());
centroid[target] += mesh.vert[i].cP();
count[target]++;
}
for(unsigned int i = nborder; i < part.size(); i++) {
if(count[i] > 0)
2004-12-02 20:12:44 +01:00
part[i] = centroid[i]/count[i];
2004-09-28 12:26:49 +02:00
}
2004-09-17 17:25:59 +02:00
}
2004-09-28 12:26:49 +02:00
for(unsigned int i = nborder; i < part.size(); i++) {
assert(mesh.vert[remap[i]].IsV());
2004-10-30 22:17:03 +02:00
mesh.vert[remap[i]].P() = part[i];
2004-09-28 12:26:49 +02:00
}
float error = 0;
//rimappiamo le facce.....
for(unsigned int i = 0; i < mesh.face.size(); i++) {
2004-09-17 17:25:59 +02:00
MyFace &face = mesh.face[i];
for(int k = 0; k < 3; k++) {
2004-09-28 12:26:49 +02:00
unsigned int target = part.Locate(face.V(k)->cP());
2004-10-06 18:40:47 +02:00
assert(target < remap.size());
assert(remap[target] < mesh.vert.size());
2004-09-28 12:26:49 +02:00
MyVertex &vert = mesh.vert[remap[target]];
float dist = Distance(vert.cP(), face.V(k)->cP());
if(dist > error) error = dist;
face.V(k) = &vert;
}
}
for(unsigned int i = 0; i < mesh.face.size(); i++) {
MyFace &face = mesh.face[i];
assert(!face.IsD());
for(int k = 0; k < 3; k++) {
assert(face.cV(k)->IsV() || !face.cV(k)->IsW());
2004-09-17 17:25:59 +02:00
}
2004-09-28 12:26:49 +02:00
if(face.cV(0) == face.cV(1) ||
face.cV(0) == face.cV(2) ||
face.cV(1) == face.cV(2)) {
2004-09-17 17:25:59 +02:00
face.SetD();
mesh.fn--;
}
}
2004-10-06 18:40:47 +02:00
2004-09-28 12:26:49 +02:00
for(unsigned int i = 0; i < mesh.vert.size(); i++)
if(!mesh.vert[i].IsV() && mesh.vert[i].IsW()) {
mesh.vert[i].SetD();
mesh.vn--;
}
2004-09-21 02:53:23 +02:00
return error;
2004-10-30 22:17:03 +02:00
2004-09-17 17:25:59 +02:00
}
2004-09-28 12:26:49 +02:00