source: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/simplify.cpp @ 1007

Revision 1007, 13.0 KB checked in by gumbau, 18 years ago (diff)
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <memory.h>
4#include <float.h>
5#include <math.h>
6
7#include "../include/metrics.h"
8#include "../include/global.h"
9#include "../include/simplify.h"
10#include "../include/saliency.h"
11
12//#define RECOMPUTE_THE_WHOLE_HEAP
13//#define MAKE_FULL_COPY
14
15using namespace VMI;
16
17///////////////////////////////////////////////////////////////////////////////
18
19void VMI::bh_mydump(Mesh *mesh, bheap_t *h) {
20    int i, d;
21
22    printf("Heap status.\n");
23    for(i = 1; i <= h->n; i++) {
24        d = h->a[i].item;
25        printf ("Heap [%d] = pri %f, e%d(%d, %d)\n", i,
26                  h->a[i].key,d,
27                  mesh->edges[d].u,
28                  mesh->edges[d].v);
29    }
30
31    printf("\n");
32   
33    for(i = 2; i <= h->n; i++) {
34        if(h->a[i].key < h->a[i/2].key) {
35            printf("key error at entry %d, value %f\n", i, h->a[i].key);
36            exit(1);
37        }
38    }
39    for(i = 1; i <= h->n; i++) {
40        if(h->p[h->a[i].item] != i) {
41            printf("indexing error at entry %d", i); exit(1);
42        }
43    }   
44}
45
46bheap_t *VMI::initHeap(Mesh *mesh) {
47    GLuint i;
48    double cost;
49    bheap_t *h = NULL;
50#ifdef MAKE_FULL_COPY
51    Triangle *triangleCopy = NULL;
52    GLuint lastNumTriangles = mesh->numTriangles;
53
54    // Allocate memory
55    triangleCopy = (Triangle *)malloc(lastNumTriangles * sizeof(Triangle)); 
56    if (triangleCopy == NULL) {
57        fprintf(stderr, "Error allocating memory\n");
58        exit(1);
59    }
60    // Make a copy of current triangle list
61    memcpy(triangleCopy, mesh->triangles, lastNumTriangles * sizeof(Triangle));
62#endif
63   
64    printf("Creating a heap for simplification...");
65   
66    h = bh_alloc(mesh->numEdges);
67
68                //      Init percent update count.
69                float   percent =       60.0 / mesh->numEdges;
70
71    for (i = 0; i <mesh->numEdges; i++) {
72
73                                //      Update progress bar.
74                                mUPB(percent);
75
76        if (mesh->edges[i].enable == TRUE) {
77
78            cost = computeEdgeCost(mesh, i);
79       
80            // Add only valid edges
81            if (cost != FLT_MAX)
82                bh_insert(h, i, cost);
83
84#ifdef MAKE_FULL_COPY
85            // Restore initial triangle list
86            memcpy(mesh->triangles, triangleCopy, lastNumTriangles * sizeof(Triangle));
87            mesh->numTriangles = lastNumTriangles;
88#endif
89        }
90    }
91   
92#ifdef MAKE_FULL_COPY
93    // Free memory
94    if (triangleCopy != NULL) free(triangleCopy);
95#endif
96    printf("Ok\n");
97
98#ifdef DEBUG
99    bh_mydump(mesh, h);
100    //getchar();
101#endif
102
103    return h;
104}
105
106bheap_t *VMI::updateHeap(bheap_t *h, Mesh *mesh, Change *c) {
107    int e, i, n0, n1, n2, u, v;
108#ifdef RECOMPUTE_THE_WHOLE_HEAP
109    bheap_t *nh;
110#else
111    int *lv, *le, numV, numE;
112#endif
113    double cost;
114#ifdef MAKE_FULL_COPY
115    GLuint lastNumTriangles = mesh->numTriangles;
116    Triangle *triangleCopy = NULL;
117   
118    // Allocate memory
119    triangleCopy = (Triangle *)malloc(lastNumTriangles * sizeof(Triangle)); 
120    if (triangleCopy == NULL) {
121        fprintf(stderr, "Error allocating memory\n");
122        exit(1);
123    }
124    // Make a copy of current triangle list
125    memcpy(triangleCopy, mesh->triangles, lastNumTriangles * sizeof(Triangle));
126#endif
127
128    for (i=0; i<c->numDel; i++) {
129
130        n0 = c->deleted[i].indices[0];
131        n1 = c->deleted[i].indices[1];
132        n2 = c->deleted[i].indices[2];
133
134        if (((n0 == c->u) || (n1 == c->u)) &&
135            ((e = findEdge(mesh->edges, mesh->numEdges, n0, n1)) != -1)) {
136
137            mesh->edges[e].enable = FALSE;
138            bh_delete(h, e);
139        }
140
141        if (((n1 == c->u) || (n2 == c->u)) &&
142            ((e = findEdge(mesh->edges, mesh->numEdges, n1, n2)) != -1)) {
143             
144            mesh->edges[e].enable = FALSE;
145            bh_delete(h, e);
146        }
147
148        if (((n0 == c->u) || (n2 == c->u)) &&
149            ((e = findEdge(mesh->edges, mesh->numEdges, n0, n2)) != -1)) {
150             
151            mesh->edges[e].enable = FALSE;
152            bh_delete(h, e);
153        }
154    }
155
156    // Update mesh and heap
157    for(i = 1; i <= h->n; i++) {
158        e = h->a[i].item;
159
160        if ((int)mesh->edges[e].u == c->u)
161            mesh->edges[e].u = c->v;
162
163        if ((int)mesh->edges[e].v == c->u)
164            mesh->edges[e].v = c->v;
165       
166        // Check edge
167        u = mesh->edges[e].u;
168        v = mesh->edges[e].v;
169   
170        // if it is not a valid edge we simply delete it
171        if ((u == v) ||
172            (u == c->u) || (v == c->u)) {
173
174            mesh->edges[e].enable = FALSE;
175            bh_delete(h, e);
176        }
177    }
178
179#ifdef RECOMPUTE_THE_WHOLE_HEAP
180
181    nh = bh_alloc(mesh->numEdges);
182
183    // Recompute heap
184    for(i = 1; i <= h->n; i++) {
185        e = h->a[i].item;
186       
187        cost = computeEdgeCost(mesh, e);
188       
189        // Add only valid edges
190        if (cost != FLT_MAX)
191            bh_insert(nh, e, cost);
192       
193#ifdef MAKE_FULL_COPY
194        // Restore initial triangle list
195        memcpy(mesh->triangles, triangleCopy, lastNumTriangles * sizeof(Triangle));
196        mesh->numTriangles = lastNumTriangles;
197#endif
198    }
199
200#ifdef MAKE_FULL_COPY
201    // Free memory
202    if (triangleCopy != NULL) free(triangleCopy);
203#endif
204    bh_free(h);
205
206    h = nh;
207
208#else
209
210    // Compute vertices adjacent to a vertex
211    lv = verticesAdjToVertex(mesh, c->v, &numV);
212
213    // Compute edges adjacent to vertices
214    le = edgesAdjToVertices(mesh, lv, numV, &numE);
215
216    free(lv);
217
218    // Delete adjacent edges from the heap
219    for(i = 0; i <numE; i++) {
220        e = le[i];
221
222        mesh->edges[e].enable = FALSE;
223        bh_delete(h, e);
224    }
225
226    // Recompute cost only for the adjacent edges
227    for(i = 0; i <numE; i++) {
228        e = le[i];
229       
230        cost = computeEdgeCost(mesh, e);
231
232        // Add only valid edges
233        if (cost != FLT_MAX) {
234            bh_insert(h, e, cost);
235            mesh->edges[e].enable = TRUE;
236        }
237       
238#ifdef MAKE_FULL_COPY
239        // Restore initial triangle list
240        memcpy(mesh->triangles, triangleCopy, lastNumTriangles * sizeof(Triangle));
241        mesh->numTriangles = lastNumTriangles;
242#endif
243
244    }
245
246#ifdef MAKE_FULL_COPY
247    // Free memory
248    if (triangleCopy != NULL) free(triangleCopy);
249#endif
250
251    free(le);
252#endif
253
254#ifdef DEBUG
255    bh_mydump(mesh, h);
256    //getchar();
257#endif
258
259    return h;
260}
261
262GLdouble VMI::computeEdgeLength(Vertex *vertices, int u, int v) {
263    GLfloat ux, uy, uz, vx, vy ,vz, rx, ry, rz;
264   
265    ux = vertices[u].x;
266    uy = vertices[u].y;
267    uz = vertices[u].z;
268
269    vx = vertices[v].x;
270    vy = vertices[v].y;
271    vz = vertices[v].z;
272
273    rx = ux - vx;
274    ry = uy - vy;
275    rz = uz - vz;
276
277    return sqrt((rx * rx) + (ry * ry) + (rz * rz));
278}
279
280///////////////////////////////////////////////////////////////////////////////
281
282void VMI::swap(unsigned int *i, unsigned int *j) {
283    unsigned int t;
284
285    t = *i;
286    *i = *j;
287    *j = t;
288}
289
290void VMI::chooseBestEndPoints(Mesh *mesh, int e) {
291    int v = mesh->edges[e].v;
292    int u = mesh->edges[e].u;
293    int numTu;
294    int *Tu  = trianglesAdjToVertex(mesh, u, &numTu);
295    int numTuv = 0;
296    int *Tuv = (int *)malloc(numTu * sizeof(int));
297    int numTv;
298    int *Tv  = trianglesAdjToVertex(mesh, v, &numTv);
299    int i, j, f, n, n0, n1, n2;
300    float cost_u_v, cost_v_u, mincurve, curve, dot;
301   
302    //printItemList(Tv, numTv);
303    //printItemList(Tu, numTu);
304   
305    // Compute Tuv
306    for (i=0; i<(int)numTu; i++) {
307       
308        n = Tu[i];
309       
310        n0 = mesh->triangles[n].indices[0];
311        n1 = mesh->triangles[n].indices[1];
312        n2 = mesh->triangles[n].indices[2];
313       
314        if ((n0 == v) || (n1 == v) || (n2 == v))
315           
316            Tuv[numTuv++] = n;
317    }
318    //printItemList(Tuv, numTuv);
319   
320    curve = 0.0f;
321    for (i=0; i<numTu; i++) {
322        n = Tu[i];
323        mincurve = 1.0f;
324        for (j=0; j<numTuv; j++) {
325            f = Tuv[j];
326            dot = glmDot(mesh->triangles[f].normal, mesh->triangles[n].normal);
327            //printf("dot: %f \n", dot);
328            mincurve = MIN(mincurve, (1.0f - dot) / 2.0f);
329        }
330        //printf("mincurve: %f \n", mincurve);
331        curve = MAX(curve, mincurve);
332    }
333    cost_u_v = curve;
334   
335    curve = 0.0f;
336    for (i=0; i<numTv; i++) {
337        n = Tv[i];
338        mincurve = 1.0f;
339        for (j=0; j<numTuv; j++) {
340            f = Tuv[j];
341            dot = glmDot(mesh->triangles[f].normal, mesh->triangles[n].normal);
342            //printf("%f \n", dot);
343            mincurve = MIN(mincurve, (1.0f - dot) / 2.0f);
344        }
345        curve = MAX(curve, mincurve);
346    }
347    cost_v_u = curve;
348   
349    //printf("e%d(%d,%d) cost: %f \n", e, u, v, cost_u_v);
350    //printf("e%d(%d,%d) cost: %f \n", e, v, u, cost_v_u);
351   
352    if ( (cost_v_u + 0.000001) < cost_u_v) {
353        //printf("Swap edge\n");
354        //printf("e%d(%d,%d) cost: %f \n", e, u, v, cost_u_v);
355        //printf("e%d(%d,%d) cost: %f \n", e, v, u, cost_v_u);
356        swap(&mesh->edges[e].u, &mesh->edges[e].v);
357    }
358
359    free(Tuv);
360    free(Tu);
361    free(Tv);
362}
363///////////////////////////////////////////////////////////////////////////////
364
365GLdouble VMI::computeEdgeCost(Mesh *mesh, int e) {
366    GLdouble cost = 0.0, newI, sal = 1.0, /*length,*/ error;
367    GLuint i;
368    Change *c;
369
370    chooseBestEndPoints(mesh, e);
371    //getchar();
372
373    c = createChange(mesh, e);
374   
375    // Apply the edge collapse
376    computeChanges(mesh, c);
377   
378    // Compute cost only for boundary or manifold edges
379    if ((c->numDel <3) && (c->numDel > 0)) {
380
381        //length = computeEdgeLength(mesh->vertices, c->u, c->v);
382
383        doChange(mesh, c);
384       
385        // Compute the cost of an edge collapse
386        getProjectedAreas(histogram, numCameras);
387        //printFullHistogram(histogram, numCameras, mesh->numTriangles);
388        //getchar();
389#ifdef SALIENCY
390        sal = computeEdgeSaliency(mesh, c, percentile);
391        //printf("  e:%d s: %f\n", c->e, sal);
392#endif
393        for (i=0;i <numCameras; i++) {
394
395#ifdef KL // Kullback-Leibler
396            newI = computeKL(mesh, histogram[i]);
397#endif
398#ifdef MI // Mutual Information
399            newI = computeMI(mesh, histogram, numCameras, i);
400#endif
401#ifdef HE // Hellinger
402            newI = computeHE(mesh, histogram[i]);
403#endif
404#ifdef CS // Chi-Square
405            newI = computeCS(mesh, histogram[i]);
406#endif
407
408            error = ABS(initialIs[i] - newI);
409           
410            if (error > 0.0)
411                cost += ((error * cameras[i].weight * sal) /*+ (length * 0.05)*/);
412        }
413
414        undoChange(mesh, c);
415
416    } else cost = FLT_MAX;
417
418
419    deleteChange(c);
420
421    return cost;
422}
423
424///////////////////////////////////////////////////////////////////////////////
425
426void VMI::simplifyModel(Mesh *mesh, GLuint numDemandedTri)
427{
428        int                     e;
429        Change  *c;
430        FILE            *file                                   = NULL;
431        FILE            *file_simp_seq  =       NULL;
432        char            s[MAX_CHAR];
433        double  cost                                            = 0.0;
434        bheap_t *h                                                      = NULL;
435        float           percent =       (40.0) / (float)(mesh->numTriangles - numDemandedTri);
436
437        if (numDemandedTri > mesh->currentNumTriangles)
438        {
439                return;
440        }
441
442        // Save changes into a file
443        if (bSaveLog == TRUE)
444        {
445#ifdef SALIENCY       
446#ifdef KL // Kullback-Leibler
447                sprintf(s,"%s_VKL_S.log", filename);
448#endif
449#ifdef MI // Mutual Information
450                sprintf(s,"%s_VMI_S.log", filename);
451#endif
452#ifdef HE // Hellinger
453                sprintf(s,"%s_VHE_S.log", filename);
454#endif
455#ifdef CS // Chi-Square
456                sprintf(s,"%s_VCS_S.log", filename);
457#endif
458#else
459#ifdef KL // Kullback-Leibler
460                sprintf(s,"%s_VKL.log", filename);
461#endif
462#ifdef MI // Mutual Information
463                sprintf(s,"%s_VMI.log", filename);
464#endif
465#ifdef HE // Hellinger
466                sprintf(s,"%s_VHE.log", filename);
467#endif
468#ifdef CS // Chi-Square
469                sprintf(s,"%s_VCS.log", filename);
470#endif
471#endif
472
473                glmWriteOBJ(pmodel, s, GLM_NONE);
474
475                /* open the file */
476                file = fopen(s, "a+");
477               
478                if (!file)
479                {
480                        fprintf(stderr, "simplifyModel() failed: can't open file \"%s\" to write.\n", s);
481                        exit(1);
482                }
483        }
484
485        //      Open file of simplification sequence.
486        file_simp_seq   =       fopen("SimplifSequence.txt", "w");
487       
488        if (!file_simp_seq)
489        {
490                fprintf(stderr,
491                                                "simplifyModel() failed: ",
492                                                "can't open file \"SimplifSequence\" to write.\n");
493        }
494       
495        h = initHeap(mesh);
496
497        printf("Starting simplification...\n");
498
499        while (mesh->currentNumTriangles > numDemandedTri /*&& cost == 0.0*/)
500        {
501                // Get the edge that has the minimum cost
502                e = bh_min(h);
503
504                c = createChange(mesh, e);
505
506                // Apply the edge collapse
507                computeChanges(mesh, c);
508                doChange(mesh, c);
509
510                if (bSaveLog == TRUE) writeChange(file, c);
511
512                //      Write Simplification sequence.
513                saveSimplificationSequence(c);
514               
515                cost = h->a[h->p[e]].key;
516               
517                printf( "Edge collapse e%d(%d,%d) %f MIN d %d m %d\n",
518                                                c->e,
519                                                c->u,
520                                                c->v,
521                                                cost,
522                                                c->numDel,
523                                                c->numMod);
524
525                mesh->edges[e].enable = FALSE;
526               
527                bh_delete(h, e);
528
529                // Get projected areas after the edge collapse
530                getProjectedAreas(histogram, numCameras);
531
532                computeCameraIs(histogram, numCameras, initialIs);
533
534                // Update the heap according to the edge collapse
535                h = updateHeap(h, mesh, c);
536
537                mUPB((float)c->numDel * percent);
538
539                deleteChange(c);
540
541                printf("t %d\n", mesh->currentNumTriangles);
542        }
543
544        if (bSaveLog == TRUE)
545        {
546                fclose(file);
547                printf("Log file written...Ok\n");
548        }
549
550        //      Close simplification sequence file.
551        fclose(file_simp_seq);
552
553        bh_free(h);
554}
555
Note: See TracBrowser for help on using the repository browser.