Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <stdio.h>
00011 #include <math.h>
00012 #include <stdlib.h>
00013 #include <assert.h>
00014
00015
00016 #include "vector.h"
00017 #include "list.h"
00018 #include "progmesh.h"
00019
00020 #define min(x,y) (((x) <= (y)) ? (x) : (y))
00021 #define max(x,y) (((x) >= (y)) ? (x) : (y))
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 class Triangle;
00032 class Vertex;
00033
00034 class Triangle {
00035 public:
00036 Vertex * vertex[3];
00037 Vector normal;
00038 Triangle(Vertex *v0,Vertex *v1,Vertex *v2);
00039 ~Triangle();
00040 void ComputeNormal();
00041 void ReplaceVertex(Vertex *vold,Vertex *vnew);
00042 int HasVertex(Vertex *v);
00043 };
00044 class Vertex {
00045 public:
00046 Vector position;
00047 int id;
00048 List<Vertex *> neighbor;
00049 List<Triangle *> face;
00050 float objdist;
00051 Vertex * collapse;
00052 Vertex(Vector v,int _id);
00053 ~Vertex();
00054 void RemoveIfNonNeighbor(Vertex *n);
00055 };
00056 List<Vertex *> vertices;
00057 List<Triangle *> triangles;
00058
00059
00060 Triangle::Triangle(Vertex *v0,Vertex *v1,Vertex *v2){
00061 assert(v0!=v1 && v1!=v2 && v2!=v0);
00062 vertex[0]=v0;
00063 vertex[1]=v1;
00064 vertex[2]=v2;
00065 ComputeNormal();
00066 triangles.Add(this);
00067 for(int i=0;i<3;i++) {
00068 vertex[i]->face.Add(this);
00069 for(int j=0;j<3;j++) if(i!=j) {
00070 vertex[i]->neighbor.AddUnique(vertex[j]);
00071 }
00072 }
00073 }
00074 Triangle::~Triangle(){
00075 int i;
00076 triangles.Remove(this);
00077 for(i=0;i<3;i++) {
00078 if(vertex[i]) vertex[i]->face.Remove(this);
00079 }
00080 for(i=0;i<3;i++) {
00081 int i2 = (i+1)%3;
00082 if(!vertex[i] || !vertex[i2]) continue;
00083 vertex[i ]->RemoveIfNonNeighbor(vertex[i2]);
00084 vertex[i2]->RemoveIfNonNeighbor(vertex[i ]);
00085 }
00086 }
00087 int Triangle::HasVertex(Vertex *v) {
00088 return (v==vertex[0] ||v==vertex[1] || v==vertex[2]);
00089 }
00090 void Triangle::ComputeNormal(){
00091 Vector v0=vertex[0]->position;
00092 Vector v1=vertex[1]->position;
00093 Vector v2=vertex[2]->position;
00094 normal = (v1-v0)*(v2-v1);
00095 if(magnitude(normal)==0)return;
00096 normal = normalize(normal);
00097 }
00098 void Triangle::ReplaceVertex(Vertex *vold,Vertex *vnew) {
00099 assert(vold && vnew);
00100 assert(vold==vertex[0] || vold==vertex[1] || vold==vertex[2]);
00101 assert(vnew!=vertex[0] && vnew!=vertex[1] && vnew!=vertex[2]);
00102 if(vold==vertex[0]){
00103 vertex[0]=vnew;
00104 }
00105 else if(vold==vertex[1]){
00106 vertex[1]=vnew;
00107 }
00108 else {
00109 assert(vold==vertex[2]);
00110 vertex[2]=vnew;
00111 }
00112 int i;
00113 vold->face.Remove(this);
00114 assert(!vnew->face.Contains(this));
00115 vnew->face.Add(this);
00116 for(i=0;i<3;i++) {
00117 vold->RemoveIfNonNeighbor(vertex[i]);
00118 vertex[i]->RemoveIfNonNeighbor(vold);
00119 }
00120 for(i=0;i<3;i++) {
00121 assert(vertex[i]->face.Contains(this)==1);
00122 for(int j=0;j<3;j++) if(i!=j) {
00123 vertex[i]->neighbor.AddUnique(vertex[j]);
00124 }
00125 }
00126 ComputeNormal();
00127 }
00128
00129 Vertex::Vertex(Vector v,int _id) {
00130 position =v;
00131 id=_id;
00132 vertices.Add(this);
00133 }
00134
00135 Vertex::~Vertex(){
00136 assert(face.num==0);
00137 while(neighbor.num) {
00138 neighbor[0]->neighbor.Remove(this);
00139 neighbor.Remove(neighbor[0]);
00140 }
00141 vertices.Remove(this);
00142 }
00143 void Vertex::RemoveIfNonNeighbor(Vertex *n) {
00144
00145 if(!neighbor.Contains(n)) return;
00146 for(int i=0;i<face.num;i++) {
00147 if(face[i]->HasVertex(n)) return;
00148 }
00149 neighbor.Remove(n);
00150 }
00151
00152
00153 float ComputeEdgeCollapseCost(Vertex *u,Vertex *v) {
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 int i;
00166 float edgelength = magnitude(v->position - u->position);
00167 float curvature=0;
00168
00169
00170 List<Triangle *> sides;
00171 for(i=0;i<u->face.num;i++) {
00172 if(u->face[i]->HasVertex(v)){
00173 sides.Add(u->face[i]);
00174 }
00175 }
00176
00177
00178 for(i=0;i<u->face.num;i++) {
00179 float mincurv=1;
00180 for(int j=0;j<sides.num;j++) {
00181
00182 float dotprod = u->face[i]->normal ^ sides[j]->normal;
00183 mincurv = min(mincurv,(1-dotprod)/2.0f);
00184 }
00185 curvature = max(curvature,mincurv);
00186 }
00187
00188 return edgelength * curvature;
00189 }
00190
00191 void ComputeEdgeCostAtVertex(Vertex *v) {
00192
00193
00194
00195
00196
00197
00198 if(v->neighbor.num==0) {
00199
00200 v->collapse=NULL;
00201 v->objdist=-0.01f;
00202 return;
00203 }
00204 v->objdist = 1000000;
00205 v->collapse=NULL;
00206
00207 for(int i=0;i<v->neighbor.num;i++) {
00208 float dist;
00209 dist = ComputeEdgeCollapseCost(v,v->neighbor[i]);
00210 if(dist<v->objdist) {
00211 v->collapse=v->neighbor[i];
00212 v->objdist=dist;
00213 }
00214 }
00215 }
00216 void ComputeAllEdgeCollapseCosts() {
00217
00218
00219
00220 for(int i=0;i<vertices.num;i++) {
00221 ComputeEdgeCostAtVertex(vertices[i]);
00222 }
00223 }
00224
00225 void Collapse(Vertex *u,Vertex *v){
00226
00227
00228
00229 if(!v) {
00230
00231 delete u;
00232 return;
00233 }
00234 int i;
00235 List<Vertex *>tmp;
00236
00237 for(i=0;i<u->neighbor.num;i++) {
00238 tmp.Add(u->neighbor[i]);
00239 }
00240
00241 for(i=u->face.num-1;i>=0;i--) {
00242 if(u->face[i]->HasVertex(v)) {
00243 delete(u->face[i]);
00244 }
00245 }
00246
00247 for(i=u->face.num-1;i>=0;i--) {
00248 u->face[i]->ReplaceVertex(u,v);
00249 }
00250 delete u;
00251
00252 for(i=0;i<tmp.num;i++) {
00253 ComputeEdgeCostAtVertex(tmp[i]);
00254 }
00255 }
00256
00257 void AddVertex(List<Vector> &vert){
00258 for(int i=0;i<vert.num;i++) {
00259 new Vertex(vert[i],i);
00260 }
00261 }
00262 void AddFaces(List<tridata> &tri){
00263 for(int i=0;i<tri.num;i++) {
00264 new Triangle(
00265 vertices[tri[i].v[0]],
00266 vertices[tri[i].v[1]],
00267 vertices[tri[i].v[2]] );
00268 }
00269 }
00270
00271 Vertex *MinimumCostEdge(){
00272
00273
00274
00275
00276
00277
00278 Vertex *mn=vertices[0];
00279 for(int i=0;i<vertices.num;i++) {
00280 if(vertices[i]->objdist < mn->objdist) {
00281 mn = vertices[i];
00282 }
00283 }
00284 return mn;
00285 }
00286
00287 void ProgressiveMesh(List<Vector> &vert, List<tridata> &tri,
00288 List<int> &map, List<int> &permutation)
00289 {
00290 AddVertex(vert);
00291 AddFaces(tri);
00292 ComputeAllEdgeCollapseCosts();
00293 permutation.SetSize(vertices.num);
00294 map.SetSize(vertices.num);
00295
00296 while(vertices.num > 0) {
00297
00298 Vertex *mn = MinimumCostEdge();
00299
00300 permutation[mn->id]=vertices.num-1;
00301
00302 map[vertices.num-1] = (mn->collapse)?mn->collapse->id:-1;
00303
00304 Collapse(mn,mn->collapse);
00305 }
00306
00307 for(int i=0;i<map.num;i++) {
00308 map[i] = (map[i]==-1)?0:permutation[map[i]];
00309 }
00310
00311
00312 }
00313
00314
00315