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

Revision 1007, 36.9 KB checked in by gumbau, 18 years ago (diff)
Line 
1#include <stdlib.h>
2#include "SimplificationMethod.h"
3#include <iostream>
4#include <fstream>
5
6using namespace std;
7using namespace Geometry;
8
9#include <gfx/geom/ProxGrid.h>
10#include "quadrics.h"
11
12//---------------------------------------------------------------------------
13//      Constructor
14//---------------------------------------------------------------------------
15SimplificationMethod::SimplificationMethod(const Mesh *m)
16{
17        objmesh                                                 =       m;
18        mGeoMesh                                                =       NULL;
19        first_index_submesh     =       new unsigned int[objmesh->mSubMeshCount];
20        indexMeshLeaves                 =       -1;
21}
22
23//---------------------------------------------------------------------------
24//      Destructor
25//---------------------------------------------------------------------------
26SimplificationMethod::~SimplificationMethod()
27{
28        delete heap;
29        delete [] first_index_submesh;
30}
31
32//---------------------------------------------------------------------------
33//      Recalculate the cost of the vertices of an edge
34//---------------------------------------------------------------------------
35void SimplificationMethod::compute_pair_info(qslim::pair_info *auxpair)
36{
37        qslim::Vertex *v0 = auxpair->v0;
38        qslim::Vertex *v1 = auxpair->v1;
39
40        qslim::vert_info& v0_info = vertex_info(v0);
41        qslim::vert_info& v1_info = vertex_info(v1);
42
43        qslim::Mat4 Q = v0_info.Q + v1_info.Q;
44        qslim::real norm = v0_info.norm + v1_info.norm;
45
46        auxpair->cost = qslim::quadrix_pair_target(Q, v0, v1, auxpair->candidate);
47
48        if( qslim::will_weight_by_area )
49                auxpair->cost /= norm;
50
51        if( qslim::will_preserve_mesh_quality )
52                auxpair->cost += pair_mesh_penalty(M0, v0, v1, auxpair->candidate);
53
54
55        //
56        // NOTICE:  In the heap we use the negative cost.  That's because
57        //          the heap is implemented as a MAX heap.
58        //
59        if( auxpair->isInHeap() )
60        {
61                heap->update(auxpair, (float)-auxpair->cost);
62        }
63        else
64        {
65                heap->insert(auxpair, (float)-auxpair->cost);
66        }
67}
68
69//---------------------------------------------------------------------------
70//      Reasign the new vertex to the adequate face
71//---------------------------------------------------------------------------
72int SimplificationMethod::predict_face(qslim::Face& F, qslim::Vertex *v1, qslim::Vertex *v2, qslim::Vec3& vnew, qslim::Vec3& f1, qslim::Vec3& f2, qslim::Vec3& f3)
73{
74        int nmapped = 0;
75
76        if( F.vertex(0) == v1 || F.vertex(0) == v2 )
77        { f1 = vnew;  nmapped++; }
78        else f1 = *F.vertex(0);
79
80        if( F.vertex(1) == v1 || F.vertex(1) == v2 )
81        { f2 = vnew;  nmapped++; }
82        else f2 = *F.vertex(1);
83
84        if( F.vertex(2) == v1 || F.vertex(2) == v2 )
85        { f3 = vnew;  nmapped++; }
86        else f3 = *F.vertex(2);
87
88        return nmapped;
89}
90
91#define MESH_INVERSION_PENALTY 1e9
92
93//---------------------------------------------------------------------------
94//---------------------------------------------------------------------------
95qslim::real SimplificationMethod::pair_mesh_penalty(qslim::Model& M, qslim::Vertex *v1, qslim::Vertex *v2, qslim::Vec3& vnew)
96{
97        static qslim::face_buffer changed;
98        changed.reset();
99
100        M.contractionRegion(v1, v2, changed);
101
102        // real Nsum = 0;
103        qslim::real Nmin = 0;
104
105        for(int i=0; i<changed.length(); i++)
106        {
107                qslim::Face& F = *changed(i);
108                qslim::Vec3 f1, f2, f3;
109
110                int nmapped = predict_face(F, v1, v2, vnew, f1, f2, f3);
111
112                // Only consider non-degenerate faces
113                if( nmapped < 2 )
114                {
115                        qslim::Plane Pnew(f1, f2, f3);
116                        qslim::real delta =  Pnew.normal() * F.plane().normal();
117
118                        if( Nmin > delta ) Nmin = delta;
119                }
120        }
121
122        //return (-Nmin) * MESH_INVERSION_PENALTY;
123        if( Nmin < 0.0 )
124                return MESH_INVERSION_PENALTY;
125        else
126                return 0.0;
127}
128
129//---------------------------------------------------------------------------
130//      Returns true if the givens vertices are a valid pair
131//---------------------------------------------------------------------------
132bool SimplificationMethod::check_for_pair(qslim::Vertex *v0, qslim::Vertex *v1)
133{
134        const qslim::pair_buffer& pairs = vertex_info(v0).pairs;
135
136        for(int i=0; i<pairs.length(); i++)
137        {
138                if( pairs(i)->v0==v1 || pairs(i)->v1==v1 )
139                        return true;
140        }
141
142        return false;
143}
144
145//---------------------------------------------------------------------------
146//      Create a new pair with two given vertices
147//---------------------------------------------------------------------------
148qslim::pair_info *SimplificationMethod::new_pair(qslim::Vertex *v0, qslim::Vertex *v1)
149{
150        qslim::vert_info& v0_info = vertex_info(v0);
151        qslim::vert_info& v1_info = vertex_info(v1);
152
153        qslim::pair_info *pair = new qslim::pair_info(v0,v1);
154        v0_info.pairs.add(pair);
155        v1_info.pairs.add(pair);
156
157        return pair;
158}
159
160//---------------------------------------------------------------------------
161//      Remove a given pair
162//---------------------------------------------------------------------------
163void SimplificationMethod::delete_pair(qslim::pair_info *auxpair)
164{
165        qslim::vert_info& v0_info = vertex_info(auxpair->v0);
166        qslim::vert_info& v1_info = vertex_info(auxpair->v1);
167
168        v0_info.pairs.remove(v0_info.pairs.find(auxpair));
169        v1_info.pairs.remove(v1_info.pairs.find(auxpair));
170
171        if( auxpair->isInHeap() )
172                heap->kill(auxpair->getHeapPos());
173
174        delete auxpair;
175}
176
177//---------------------------------------------------------------------------
178//      Contract a given pair
179//---------------------------------------------------------------------------
180void SimplificationMethod::do_contract(qslim::Model& m, qslim::pair_info *auxpair)
181{
182        qslim::Vertex *v0 = auxpair->v0;  qslim::Vertex *v1 = auxpair->v1;
183        qslim::vert_info& v0_info = vertex_info(v0);
184        qslim::vert_info& v1_info = vertex_info(v1);
185        qslim::Vec3 vnew = auxpair->candidate;
186        int i;
187
188        // Make v0 be the new vertex
189        v0_info.Q += v1_info.Q;
190        v0_info.norm += v1_info.norm;
191
192        qslim::Vec3 p(vnew);
193        qslim::Vec3 v0antes(v0->operator[](qslim::X),v0->operator[](qslim::Y),v0->operator[](qslim::Z));
194
195        // Find the edge to remove (before remove it (contract()))
196        qslim::Edge *econ=NULL;
197        bool finded = false;
198        for (i=0; i<v0->edgeUses().length(); i++)
199        {               
200                econ = v0->edgeUses()(i);
201                if (v1->vID == econ->org()->vID || v1->vID == econ->dest()->vID)
202                {
203                        finded = true;
204                        break;
205                }
206        }
207
208        assert(finded);
209
210
211        // Perform the actual contraction
212        static qslim::face_buffer changed;
213        changed.reset();
214        m.contract(v0, v1, vnew, changed);
215
216        // Stores the simplification step
217        MeshSimplificationSequence::Step simplifstep;
218        qslim::Vec3 vdesp = p - v0antes;
219
220        // Stores the displacement in the simplification step
221        simplifstep.x=(float)vdesp[qslim::X];
222        simplifstep.y = (float)vdesp[qslim::Y];
223        simplifstep.z = (float)vdesp[qslim::Z];
224       
225        //      Submeshes which pertains each vertex
226        simplifstep.mV1 = v0->validID();
227
228        //      The simplification method returns as v1 the dead vertex.
229        simplifstep.mV0 = v1->validID();
230
231        //      Number of triangles that are removed in this simplification step.
232        int _numDelTris = 0; // 1 or 2 triangles can be removed.
233
234        for (i = 0;     i < changed.length();   i++)
235        {
236                if (!changed(i)->isValid())
237                {
238                        _numDelTris++;
239                }
240        }
241
242        int del_index   =       0;
243
244        // mModfaces y mT0, mT1 of simplifstep stores the triangles id's -> geomesh has not triangles id's
245        for (i=0; i<changed.length(); i++)
246        {
247                qslim::Face *auxface = changed(i);
248
249                if (auxface->isValid())
250                {
251                        // Modified triangles
252                        simplifstep.mModfaces.push_back(auxface->validID());
253                }
254                else
255                {
256                        // Removed triangles
257                        if (_numDelTris==1)
258                        {
259                                simplifstep.mT0=auxface->validID();
260                                simplifstep.mT1=auxface->validID();
261                        }
262                        else
263                        {
264                                if(del_index==0)
265                                {
266                                        simplifstep.mT0=auxface->validID();
267                                        del_index++;
268                                }
269                                else
270                                {
271                                        simplifstep.mT1=auxface->validID();
272                                }
273                        }
274                }
275        }
276
277        decim_data.push_back(simplifstep); // Simplification sequence that make reference to the simplification method sequence
278
279#ifdef SUPPORT_VCOLOR
280        //
281        // If the vertices are colored, color the new vertex
282        // using the average of the old colors.
283        v0->props->color += v1->props->color;
284        v0->props->color /= 2;
285#endif
286
287        // Remove the pair that we just contracted
288        delete_pair(auxpair);
289
290        // Recalculate pairs associated with v0
291        for(i=0; i<v0_info.pairs.length(); i++)
292        {
293                qslim::pair_info *p = v0_info.pairs(i);
294                compute_pair_info(p);
295        }
296
297        // Process pairs associated with now dead vertex
298        static qslim::pair_buffer condemned(6); // collect condemned pairs for execution
299        condemned.reset();
300
301        for(i=0; i<v1_info.pairs.length(); i++)
302        {
303                qslim::pair_info *p = v1_info.pairs(i);
304
305                qslim::Vertex *u;
306                if( p->v0 == v1 )     
307                        u = p->v1;
308                else
309                        if( p->v1 == v1) 
310                                u = p->v0;
311                        else
312                                std::cerr << "YOW!  This is a bogus pair." << endl;
313
314                if( !check_for_pair(u, v0) )
315                {
316                        p->v0 = v0;
317                        p->v1 = u;
318                        v0_info.pairs.add(p);
319                        compute_pair_info(p);
320                }
321                else
322                        condemned.add(p);
323        }
324
325        for(i=0; i<condemned.length(); i++)
326                // Do you have any last requests?
327                delete_pair(condemned(i));
328        v1_info.pairs.reset(); // safety precaution
329
330}
331
332//---------------------------------------------------------------------------
333//---------------------------------------------------------------------------
334bool SimplificationMethod::decimate_quadric(qslim::Vertex *v, qslim::Mat4& Q)
335{
336        if( vinfo.length() > 0 )
337        {
338                Q = vinfo(v->uniqID).Q;
339                return true;
340        }
341        else
342                return false;
343}
344
345//---------------------------------------------------------------------------
346//      Extract a pair from the heap, concract it and remove it form the heap
347//---------------------------------------------------------------------------
348void SimplificationMethod::decimate_contract(qslim::Model& m)
349{
350        qslim::heap_node *top;
351        qslim::pair_info *pair;
352
353        for(;;)
354        {
355                top = heap->extract();
356                if( !top ) return;
357                pair = (qslim::pair_info *)top->obj;
358
359                //Remove all the vertices of the removed edges
360                bool sharededge= false;
361                for (int i=0; i<pair->v0->edgeUses().length(); i++)
362                {               
363                        qslim::Edge *econ = pair->v0->edgeUses()(i);
364                        if (pair->v1->vID == econ->org()->vID || pair->v1->vID == econ->dest()->vID)
365                        {
366                                sharededge= true;
367                                break;
368                        }
369
370                }
371
372                if( pair->isValid() && sharededge)
373                        break;
374
375                delete_pair(pair);
376        }
377
378        do_contract(m, pair);
379
380        M0.validVertCount--;  // Attempt to maintain valid vertex information
381}
382
383//---------------------------------------------------------------------------
384//---------------------------------------------------------------------------
385qslim::real SimplificationMethod::decimate_error(qslim::Vertex *v)
386{
387        qslim::vert_info& info = vertex_info(v);
388
389        qslim::real err = qslim::quadrix_evaluate_vertex(*v, info.Q);
390
391    if( qslim::will_weight_by_area )
392                err /= info.norm;
393
394    return err;
395}
396
397//---------------------------------------------------------------------------
398//      Extract the minimum cost of the the valid nodes (not simplified)
399//---------------------------------------------------------------------------
400qslim::real SimplificationMethod::decimate_min_error()
401{
402        qslim::heap_node *top;
403        qslim::pair_info *pair;
404
405        for(;;)
406        {
407                top = heap->top();
408                if( !top ) return -1.0;
409                pair = (qslim::pair_info *)top->obj;
410
411                if( pair->isValid() )
412                        break;
413
414                top = heap->extract();
415                delete_pair(pair);
416        }
417
418        return pair->cost;
419}
420
421//---------------------------------------------------------------------------
422//      Returns the maximum error by vertex
423//---------------------------------------------------------------------------
424qslim::real SimplificationMethod::decimate_max_error(qslim::Model& m)
425{
426        qslim::real max_err = 0;
427
428        for(int i=0; i<m.vertCount(); i++)
429                if( m.vertex(i)->isValid() )
430                {
431                        max_err = MAX(max_err, decimate_error(m.vertex(i)));
432                }
433
434        return max_err;
435}
436
437//---------------------------------------------------------------------------
438//      Initializations
439//---------------------------------------------------------------------------
440void SimplificationMethod::decimate_init(qslim::Model& m, qslim::real limit)
441{
442        int i,j;
443
444        vinfo.init(m.vertCount());
445
446        if( qslim::will_use_vertex_constraint )
447                for(i=0; i<m.vertCount(); i++)
448                {
449                        qslim::Vertex *v = m.vertex(i);
450                        if( v->isValid() )
451                                vertex_info(v).Q = qslim::quadrix_vertex_constraint(*v);
452                }
453
454        for(i=0; i<m.faceCount(); i++)
455                if( m.face(i)->isValid() )
456                {
457                        if( qslim::will_use_plane_constraint )
458                        {
459                                qslim::Mat4 Q = qslim::quadrix_plane_constraint(*m.face(i));
460                                qslim::real norm = 0.0;
461
462                                if( qslim::will_weight_by_area )
463                                {
464                                        norm = m.face(i)->area();
465                                        Q *= norm;
466                                }
467
468                                for(j=0; j<3; j++)
469                                {
470                                        vertex_info(m.face(i)->vertex(j)).Q += Q;
471                                        vertex_info(m.face(i)->vertex(j)).norm += norm;
472
473                                }
474                        }
475                }
476
477        if( qslim::will_constrain_boundaries )
478        {
479                for(i=0; i<m.edgeCount(); i++)
480                        if( m.edge(i)->isValid() && qslim::check_for_discontinuity(m.edge(i)) )
481                        {
482                                qslim::Mat4 B = qslim::quadrix_discontinuity_constraint(m.edge(i));
483                                qslim::real norm = 0.0;
484
485                                if( qslim::will_weight_by_area )
486                                {
487                                        norm = qslim::norm2(*m.edge(i)->org() - *m.edge(i)->dest());
488                                        B *= norm;
489                                }
490
491                                B *= qslim::boundary_constraint_weight;
492                                vertex_info(m.edge(i)->org()).Q += B;
493                                vertex_info(m.edge(i)->org()).norm += norm;
494                                vertex_info(m.edge(i)->dest()).Q += B;
495                                vertex_info(m.edge(i)->dest()).norm += norm;
496                        }
497        }
498
499        heap = new qslim::Heap(m.validEdgeCount);
500
501        int pair_count = 0;
502
503        for(i=0; i<m.edgeCount(); i++)
504                if( m.edge(i)->isValid() )
505                {
506                        qslim::pair_info *pair = new_pair(m.edge(i)->org(), m.edge(i)->dest());
507                        //pointers_to_remove.push_back(pair);
508                        compute_pair_info(pair);
509                        pair_count++;
510                }
511
512        if( limit<0 )
513        {
514                limit = m.bounds.radius * 0.05;
515        }
516        proximity_limit = limit * limit;
517        if( proximity_limit > 0 )
518        {
519                qslim::ProxGrid grid(m.bounds.min, m.bounds.max, limit);
520                for(i=0; i<m.vertCount(); i++)
521                        grid.addPoint(m.vertex(i));
522
523                qslim::buffer<qslim::Vec3 *> nearby(32);
524                for(i=0; i<m.vertCount(); i++)
525                {
526                        nearby.reset();
527                        grid.proximalPoints(m.vertex(i), nearby);
528
529                        for(j=0; j<nearby.length(); j++)
530                        {
531                                qslim::Vertex *v1 = m.vertex(i);
532                                qslim::Vertex *v2 = (qslim::Vertex *)nearby(j);
533
534                                if( v1->isValid() && v2->isValid() )
535                                {
536#ifdef SAFETY
537                                        assert(pair_is_valid(v1,v2));
538#endif
539                                        if( !check_for_pair(v1,v2) )
540                                        {
541                                                qslim::pair_info *pair = new_pair(v1,v2);
542                                                compute_pair_info(pair);
543                                                pair_count++;
544                                        }
545                                }
546
547                        }
548                }
549        }
550}
551
552//---------------------------------------------------------------------------
553//      Initilizations
554//---------------------------------------------------------------------------
555void SimplificationMethod::simplifmethod_init(void)
556{
557        int i;
558
559        // Change mesh structure.
560        geomesh2simplifModel();
561
562        M0.bounds.complete();
563
564        initialVertCount = M0.vertCount();
565        initialEdgeCount = M0.edgeCount();
566        initialFaceCount = M0.faceCount();
567
568        // Get rid of degenerate faces
569        for(i=0; i<M0.faceCount(); i++)
570                if( !M0.face(i)->plane().isValid() )
571                        M0.killFace(M0.face(i));
572
573        M0.removeDegeneracy(M0.allFaces());
574
575        // Get rid of unused vertices
576        for(i=0; i<M0.vertCount(); i++)
577        {
578                if( M0.vertex(i)->edgeUses().length() == 0 )
579                        M0.vertex(i)->kill();
580        }
581}
582
583//---------------------------------------------------------------------------
584//      Do the contractions till the required LOD (percentage option)
585//---------------------------------------------------------------------------
586void SimplificationMethod::simplifmethod_run(int finalfaces,TIPOFUNC upb)
587{
588        decimate_init(M0, qslim::pair_selection_tolerance);
589        unsigned        int     contador        =       0;
590        float                                   percent; // simplification percentage.
591
592        percent =       (float)(2.0 * 100.0) / (M0.validFaceCount - finalfaces);
593
594        //      Update progress bar.
595        if (upb)
596        {
597                upb(0.0);
598        }
599
600        for (std::vector<MeshSimplificationSequence::Step>::iterator it= decim_data.begin(); it!=decim_data.end(); it++)
601        {
602                it->mModfaces.clear();
603        }
604        decim_data.clear();
605
606        while( M0.validFaceCount > finalfaces/*qslim::face_target*/
607                        && M0.validFaceCount > 1
608                        && decimate_min_error() < qslim::error_tolerance )
609        {
610                decimate_contract(M0);
611
612                //      Update progress bar.
613                if (upb)
614                {
615                        upb(percent);
616                }
617        }
618
619        //      Update progress bar.
620        if (upb)
621        {
622                upb(100.0);
623        }
624}
625
626//---------------------------------------------------------------------------
627//      Do the contractions till the required LOD (number of vertices option)
628//---------------------------------------------------------------------------
629void SimplificationMethod::simplifmethod_runv(int numvertices,TIPOFUNC upb)
630{
631        decimate_init(M0, qslim::pair_selection_tolerance);
632        unsigned        int     contador        =       0;
633        int                                             previousValidVertCount;
634        float                                   percent; // Simplification percentage.
635
636        previousValidVertCount  =       0;
637
638        percent =       (float)(2.0 * 100.0) /(float)((M0.validFaceCount - numvertices / 3.0));
639
640        //      Update progress bar.
641        if (upb)
642        {
643                upb(0.0);
644        }
645
646        for (std::vector<MeshSimplificationSequence::Step>::iterator it= decim_data.begin(); it!=decim_data.end(); it++)
647        {
648                it->mModfaces.clear();
649        }
650        decim_data.clear();
651
652        while(  M0.validVertCount > numvertices /*qslim::face_target*/
653                        &&
654                        decimate_min_error() < qslim::error_tolerance
655                        &&
656                        previousValidVertCount  !=      M0.validVertCount)
657        {
658                previousValidVertCount  =       M0.validVertCount;
659
660                decimate_contract(M0);
661
662                //      Update progress bar.
663                if (upb)
664                {
665                        upb(percent);
666                }
667        }
668
669        //      Update progress bar.
670        if (upb)
671        {
672                upb(100.0);
673        }
674}
675
676//---------------------------------------------------------------------------
677// Class to create a map without repeated vertices
678//---------------------------------------------------------------------------
679class _float3_
680{
681        public:
682                float x,y,z;
683                _float3_(float x=0.0f, float y=0.0f, float z=0.0f){ this->x = x; this->y = y; this->z = z; }
684                _float3_(const _float3_ &f){ x=f.x; y=f.y; z=f.z; }
685                _float3_ & operator=(const _float3_ &f){ x=f.x; y=f.y; z=f.z; return *this; }
686                bool operator<(const _float3_ &f) const
687                {
688                        if (x<f.x) return true;
689                        if (x>f.x) return false;
690                        if (y<f.y) return true;
691                        if (y>f.y) return false;
692                        if (z<f.z) return true;
693                        if (z>f.z) return false;
694                        return false;
695                }
696};
697
698
699//---------------------------------------------------------------------------
700//Unify the model to work with it
701//The vertices that have the same space coordinates are stored as an unique vertex
702//in order to avoid holes in the simplification
703//The necessary information to store correctly the decimation data is stored
704//---------------------------------------------------------------------------
705void SimplificationMethod::geomesh2simplifModel(void)
706{
707        std::map<_float3_,int> vertices_map; //Unique vertices (without repetitions) from all the submeshes
708        unsigned int num_final_verts = 0; //Number of unique vertices from all the submeshes
709
710        int num_final_verts2=0;
711        int num_repeated_verts=0;
712
713        int simplifindex;
714        for (size_t i=0; i<objmesh->mSubMeshCount; i++) //For all the submeshes
715        {
716                if (i   !=      indexMeshLeaves)
717                {
718                        //If the model has texture information
719                        if (objmesh->mSubMesh[i].mVertexBuffer->mVertexInfo & VERTEX_TEXCOORDS)
720                        {
721                                //For all the vertices of each submesh
722                                for (size_t j=0; j<objmesh->mSubMesh[i].mVertexBuffer->mVertexCount; j++)
723                                {
724                                        _float3_ auxvert(objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].x,
725                                                        objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].y,
726                                                        objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].z);
727
728                                        std::map<_float3_,int>::iterator mit = vertices_map.find(auxvert);
729                                        if (mit==vertices_map.end())
730                                        {
731                                                //If the vertex is not in vertices_map, then is added
732                                                simplifindex=M0.in_Vertex(qslim::Vec3(objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].x,
733                                                                        objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].y,
734                                                                        objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].z));
735                                                M0.in_Normal(qslim::Vec3(objmesh->mSubMesh[i].mVertexBuffer->mNormal[j].x,
736                                                                        objmesh->mSubMesh[i].mVertexBuffer->mNormal[j].y,
737                                                                        objmesh->mSubMesh[i].mVertexBuffer->mNormal[j].z));
738
739                                                M0.in_TexCoord(qslim::Vec2(objmesh->mSubMesh[i].mVertexBuffer->mTexCoords[j].x,
740                                                                        objmesh->mSubMesh[i].mVertexBuffer->mTexCoords[j].y));
741                                                vertices_map[auxvert] = num_final_verts;
742                                                num_final_verts ++;
743
744                                                std::vector<int> v;
745                                                submeshmap[simplifindex]=v;
746                                                submeshmap[simplifindex].push_back((int)i); //Add the index of the mesh that contains the vertex
747                                                std::vector<int> v2;
748                                                vertexbuffermap[simplifindex]=v2;
749                                                vertexbuffermap[simplifindex].push_back((int)j); //Add the index of vertex in the submesh
750
751                                                // Debug
752                                                num_final_verts2++;
753                                        }
754                                        else
755                                        {
756                                                //the vertex is already in vertices_map, so store the reference of the first one with the same space coodinates
757                                                simplifindex = mit->second;
758                                                submeshmap[simplifindex].push_back((int)i); //Submeshes that contains the vertex
759                                                vertexbuffermap[simplifindex].push_back((int)j); //Indices of the vertex buffers that contains the vertex
760
761                                                // Debug
762                                                num_repeated_verts++;
763                                        }       
764                                }
765                        }
766                        else //the model has not texture information
767                        {
768                                //For all the vertices of each submesh
769                                for (size_t j=0; j<objmesh->mSubMesh[i].mVertexBuffer->mVertexCount; j++)
770                                {
771                                        _float3_ auxvert(objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].x,
772                                                        objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].y,
773                                                        objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].z);
774
775                                        std::map<_float3_,int>::iterator mit = vertices_map.find(auxvert);
776                                        if (mit==vertices_map.end())
777                                        {
778                                                //If the vertex is not in vertices_map, then is added
779                                                simplifindex=M0.in_Vertex(qslim::Vec3(objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].x,
780                                                                        objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].y,
781                                                                        objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].z));
782                                                M0.in_Normal(qslim::Vec3(objmesh->mSubMesh[i].mVertexBuffer->mNormal[j].x,
783                                                                        objmesh->mSubMesh[i].mVertexBuffer->mNormal[j].y,
784                                                                        objmesh->mSubMesh[i].mVertexBuffer->mNormal[j].z));
785                                                M0.in_TexCoord(qslim::Vec2(0.0,0.0));
786                                                vertices_map[auxvert] = num_final_verts;
787                                                num_final_verts ++;
788
789                                                std::vector<int> v;
790                                                submeshmap[simplifindex]=v;
791                                                submeshmap[simplifindex].push_back((int)i); //Add the index of the mesh that contains the vertex
792                                                std::vector<int> v2;
793                                                vertexbuffermap[simplifindex]=v2;
794                                                vertexbuffermap[simplifindex].push_back((int)j); //Add the index of vertex in the submesh
795                                        }
796                                        else
797                                        {
798                                                //the vertex is already in vertices_map, so store the reference of the first one with the same space coodinates
799                                                simplifindex = mit->second;
800                                                submeshmap[simplifindex].push_back((int)i); //Submeshes that contains the vertex
801                                                vertexbuffermap[simplifindex].push_back((int)j); //Indices of the vertex buffers that contains the vertex
802                                        }       
803                                }
804                        }
805                        if (objmesh->mSubMesh[i].mSharedVertexBuffer)
806                        {
807                                printf("Shared break");
808                                break;
809                        }
810                }
811        }
812
813        //Create the faces
814        unsigned int base_index=0;
815
816        number_of_triangles=0; //Number of triangles of the model
817        int face_index=0;
818
819        int index_in_vertices_map0,index_in_vertices_map1,index_in_vertices_map2;
820        for (size_t i=0; i<objmesh->mSubMeshCount; i++) //For all the submeshes
821        {
822                if (i!=indexMeshLeaves)
823                {
824                        for (Index j=0; j<objmesh->mSubMesh[i].mIndexCount; j+=3)
825                        {
826                                //+1 is required because the first index in the simplification method is 1
827                                //Index of the vertex in vertices_map
828                                Index indice0=objmesh->mSubMesh[i].mIndex[j];
829                                _float3_ auxvert0(objmesh->mSubMesh[i].mVertexBuffer->mPosition[indice0].x,
830                                                objmesh->mSubMesh[i].mVertexBuffer->mPosition[indice0].y,
831                                                objmesh->mSubMesh[i].mVertexBuffer->mPosition[indice0].z);
832                                index_in_vertices_map0=vertices_map[auxvert0] + 1;
833
834                                Index indice1=objmesh->mSubMesh[i].mIndex[j+1];
835                                _float3_ auxvert1(objmesh->mSubMesh[i].mVertexBuffer->mPosition[indice1].x,
836                                                objmesh->mSubMesh[i].mVertexBuffer->mPosition[indice1].y,
837                                                objmesh->mSubMesh[i].mVertexBuffer->mPosition[indice1].z);
838                                index_in_vertices_map1=vertices_map[auxvert1] + 1;
839
840                                Index indice2=objmesh->mSubMesh[i].mIndex[j+2];
841                                _float3_ auxvert2(objmesh->mSubMesh[i].mVertexBuffer->mPosition[indice2].x,
842                                                objmesh->mSubMesh[i].mVertexBuffer->mPosition[indice2].y,
843                                                objmesh->mSubMesh[i].mVertexBuffer->mPosition[indice2].z);
844                                index_in_vertices_map2=vertices_map[auxvert2] + 1;
845
846                                //Create a triangle with its indices in vertices_map
847                                face_index=M0.miin_Face(index_in_vertices_map0,index_in_vertices_map1,index_in_vertices_map2);
848
849                                //igeo allows to identify the submesh that contains the triangle
850                                M0.face(face_index)->igeo=(int)i;
851                        }
852                }
853        }
854        number_of_triangles=face_index;
855}
856
857
858//---------------------------------------------------------------------------
859//Wrties a file with the vertices, triangles and the simplification sequence
860//---------------------------------------------------------------------------
861void SimplificationMethod::WriteOBJ(void)
862{
863        MeshSimplificationSequence::Step stepaux;
864        vector<int> v0,v1,submesh0,submesh1;
865        std::ofstream obj("salida.lod");
866        obj << "begin" << std::endl;
867        //vertices
868        for (size_t i=0; i<objmesh->mSubMeshCount; i++)
869        {
870                for (size_t j=0; j<objmesh->mSubMesh[i].mVertexBuffer->mVertexCount; j++)
871                {       
872                        obj << "v " <<  objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].x << " " <<
873                                objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].y << " " <<
874                                objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].z << " " << std::endl;
875                }
876        }
877
878
879        //faces
880        for (size_t i=0; i<objmesh->mSubMeshCount; i++)
881        {
882                for (size_t j=0; j<objmesh->mSubMesh[i].mIndexCount; j=j+3)
883                {       
884                        obj << "f " <<  objmesh->mSubMesh[i].mIndex[j]+1 << " " <<
885                                objmesh->mSubMesh[i].mIndex[j+1]+1 << " " <<
886                                objmesh->mSubMesh[i].mIndex[j+2]+1 << std::endl;
887                }
888        }
889
890        obj << "end" << std::endl;
891
892        for (unsigned i=0; i<decim_data.size(); i++)
893        {
894                stepaux = decim_data.operator [](i);
895                v0=vertexbuffermap[stepaux.mV0];  //vertexbuffer index
896                submesh0=submeshmap[stepaux.mV0]; //displacement for each submesh
897                v1=vertexbuffermap[stepaux.mV1];
898                submesh1=submeshmap[stepaux.mV1];
899                for (unsigned j=0; j<v0.size(); j++)
900                {
901                        for (unsigned k=0; k<v1.size(); k++)
902                        {
903                                //obtain the index of the VertexBuffer of each submesh and the displacemente by submesh
904                                obj << "v% " << v1.operator [](k)+first_index_submesh[submesh1.operator [](k)] <<
905                                        " " << v0.operator [](j)+first_index_submesh[submesh0.operator [](j)] << " " <<
906                                        stepaux.x << " " << stepaux.y << " " << stepaux.z << " " << stepaux.mT0 << " " <<
907                                        stepaux.mT1 << " & ";
908                                if (stepaux.mModfaces.size()>0)
909                                {
910                                        unsigned int ii=0;
911                                        for (ii=0; ii<stepaux.mModfaces.size()-1; ii++)
912                                        {
913                                                obj << stepaux.mModfaces.operator [](ii) << " ";
914                                        }
915                                        obj << stepaux.mModfaces.operator [](ii) << std::endl;
916                                }
917                                else
918                                {
919                                        obj << std::endl;
920                                }                                       
921                        }
922                }
923        }
924        obj.close();
925}
926
927//---------------------------------------------------------------------------
928//simplifmethod_init is executed to do some initalizations
929//simplifmethod_run is executed to do the decimation
930//Then, the simpified model is created and the decimation information is returned
931//---------------------------------------------------------------------------
932MeshSimplificationSequence *SimplificationMethod::Decimate(     float lod,
933                                                                                                                                                                                                                                                int simpliftype,
934                                                                                                                                                                                                                                                TIPOFUNC upb)
935{
936        simplifmethod_init();
937
938        if (simpliftype == 0)
939        {
940                //Percentage option
941                simplifmethod_run((int)(number_of_triangles*lod),upb);
942        }
943        else
944        {
945                //Number of vertices option
946                simplifmethod_runv((int)lod,upb);
947        }
948
949        //      Store unique vertices by submesh (without repetitions).
950        typedef std::map<int,int> MAPAINDIND;
951
952        //      Store all the indices by submesh (with repetitions).
953        typedef std::vector<int> REPINDLIST;
954
955        MAPAINDIND *unique_verts_inds_by_geo = new MAPAINDIND[objmesh->mSubMeshCount];
956        REPINDLIST *ver_inds_rep_by_geo         = new REPINDLIST[objmesh->mSubMeshCount];
957
958        //      Index counter by submesh.
959        int *inextvert = new int[objmesh->mSubMeshCount];
960
961        for (unsigned int       i = 0;  i < objmesh->mSubMeshCount;     i++)
962        {
963                inextvert[i] = 0;
964        }
965
966
967        //      Construct the model.
968        for (int        i = 0;  i < M0.faceCount();     i++)
969        {
970                if (M0.face(i)->isValid())
971                {
972                        qslim::Face *auxface    =       M0.face(i);
973
974                        //      Determine to which submesh pertains the triangle.
975                        int igeo = auxface->igeo;
976
977                        //      Insert to each submesh its triangles.
978                        std::map<int,int>::iterator findit = unique_verts_inds_by_geo[igeo].find(auxface->vertex(0)->validID());
979                        if (findit == unique_verts_inds_by_geo[igeo].end())
980                        {
981                                //      If it is not added... add and map it.
982                                unique_verts_inds_by_geo[igeo][auxface->vertex(0)->validID()] = inextvert[igeo];
983                                inextvert[igeo]++;
984                        }                       
985                        findit = unique_verts_inds_by_geo[igeo].find(auxface->vertex(1)->validID());
986                        if (findit == unique_verts_inds_by_geo[igeo].end())
987                        {
988                                //      If it is not added... add and map it.
989                                unique_verts_inds_by_geo[igeo][auxface->vertex(1)->validID()] = inextvert[igeo];
990                                inextvert[igeo]++;
991                        }                       
992                        findit = unique_verts_inds_by_geo[igeo].find(auxface->vertex(2)->validID());
993                        if (findit == unique_verts_inds_by_geo[igeo].end())
994                        {
995                                //      If it is not added... add and map it.
996                                unique_verts_inds_by_geo[igeo][auxface->vertex(2)->validID()] = inextvert[igeo];
997                                inextvert[igeo]++;
998                        }                       
999
1000                        //      Total number of indices by submesh.
1001                        ver_inds_rep_by_geo[igeo].push_back(auxface->vertex(0)->validID());
1002                        ver_inds_rep_by_geo[igeo].push_back(auxface->vertex(1)->validID());
1003                        ver_inds_rep_by_geo[igeo].push_back(auxface->vertex(2)->validID());
1004                }
1005        }
1006
1007        //      Output simplified mesh.
1008        mGeoMesh                                                                =       new Mesh();
1009        mGeoMesh->mVertexBuffer =       new     VertexBuffer();
1010
1011        mGeoMesh->mSubMeshCount = objmesh->mSubMeshCount;
1012
1013        //      Memory allocation for the submeshes.
1014        mGeoMesh->mSubMesh = new SubMesh[objmesh->mSubMeshCount];
1015
1016        //      Fill up bounding box settings.
1017        mGeoMesh->mMeshBounds.maxX                                      =       objmesh->mMeshBounds.maxX;
1018        mGeoMesh->mMeshBounds.maxY                                      =       objmesh->mMeshBounds.maxY;
1019        mGeoMesh->mMeshBounds.maxZ                                      =       objmesh->mMeshBounds.maxZ;
1020        mGeoMesh->mMeshBounds.minX                                      =       objmesh->mMeshBounds.minX;
1021        mGeoMesh->mMeshBounds.minY                                      =       objmesh->mMeshBounds.minY;
1022        mGeoMesh->mMeshBounds.minZ                                      =       objmesh->mMeshBounds.minZ;
1023        mGeoMesh->mMeshBounds.radius                            =       objmesh->mMeshBounds.radius;
1024        mGeoMesh->mMeshBounds.scaleFactor               =       objmesh->mMeshBounds.scaleFactor;
1025
1026        //      Copy skeleton name.
1027        if (objmesh->hasSkeleton)
1028        {
1029                mGeoMesh->hasSkeleton   =       true;
1030
1031                strcpy(mGeoMesh->mSkeletonName,objmesh->mSkeletonName);
1032        }
1033
1034        //      Copy mesh bones.
1035        if (!objmesh->mBones.empty())
1036        {
1037                for (unsigned int j = 0; j < objmesh->mBones.size(); j++)
1038                {
1039                        mGeoMesh->mBones.push_back(objmesh->mBones[j]);
1040                }
1041        }
1042
1043        bool copiedShared = false;
1044
1045        for (size_t     i = 0;  i < objmesh->mSubMeshCount;     i++)
1046        {
1047                mGeoMesh->mSubMesh[i].mStripCount                                       =       0;
1048                mGeoMesh->mSubMesh[i].mStrip                                                    =       NULL;
1049
1050                mGeoMesh->
1051                        mSubMesh[i].mSharedVertexBuffer =       false;
1052
1053                strcpy( mGeoMesh->mSubMesh[i].mMaterialName,
1054                                objmesh->mSubMesh[i].mMaterialName);
1055
1056                //      Copy submesh bones.
1057                if (!objmesh->mSubMesh[i].mBones.empty())
1058                {
1059                        for (unsigned int j = 0; j < objmesh->mSubMesh[i].mBones.size(); j++)
1060                        {
1061                                mGeoMesh->mSubMesh[i].mBones.push_back(objmesh->
1062                                                mSubMesh[i].mBones[j]);
1063                        }
1064                }
1065
1066                if (i != indexMeshLeaves)
1067                {
1068                        //      Indices vectors.
1069                        mGeoMesh->mSubMesh[i].mIndexCount       =       ver_inds_rep_by_geo[i].size();
1070                        mGeoMesh->mSubMesh[i].mIndex                    =       new Index[mGeoMesh->
1071                                mSubMesh[i].mIndexCount];
1072
1073                        //      Store the indices.
1074                        for (unsigned int       j = 0;  j < mGeoMesh->mSubMesh[i].mIndexCount;  j++)
1075                        {
1076                                //      Obtain the indices that point at VertexBuffer.
1077                                mGeoMesh->mSubMesh[i].mIndex[j] =       unique_verts_inds_by_geo[i].operator [](ver_inds_rep_by_geo[i].operator [](j));
1078                        }
1079
1080                        //      Copy the vertices.
1081                        if (mGeoMesh->mSubMesh[i].mSharedVertexBuffer)
1082                        {
1083                                //      Shared vertices.
1084                                if (!copiedShared)
1085                                {
1086                                        mGeoMesh->mVertexBuffer = new VertexBuffer();
1087                                        copiedShared                                            = true;
1088                                }
1089
1090                                mGeoMesh->mSubMesh[i].mVertexBuffer = mGeoMesh->mVertexBuffer;
1091                        }
1092                        else
1093                        {
1094                                //      There's no shared vertices.
1095                                mGeoMesh->mSubMesh[i].mVertexBuffer     =       new VertexBuffer();
1096                        }
1097
1098                        mGeoMesh->mSubMesh[i].mVertexBuffer->mVertexCount       =       unique_verts_inds_by_geo[i].size();
1099                        mGeoMesh->mSubMesh[i].mVertexBuffer->mVertexInfo        =       objmesh->mSubMesh[i].mVertexBuffer->mVertexInfo;
1100
1101                        //      Allocate memory for position, normal and texutre coordinates.
1102                        mGeoMesh->mSubMesh[i].mVertexBuffer->mPosition  =       new Vector3[mGeoMesh->mSubMesh[i].mVertexBuffer->mVertexCount];
1103                        mGeoMesh->mSubMesh[i].mVertexBuffer->mNormal            =       new Vector3[mGeoMesh->mSubMesh[i].mVertexBuffer->mVertexCount];
1104                        mGeoMesh->mSubMesh[i].mVertexBuffer->mTexCoords =       new Vector2[mGeoMesh->mSubMesh[i].mVertexBuffer->mVertexCount];
1105
1106                        for (   MAPAINDIND::iterator mapit = unique_verts_inds_by_geo[i].begin();
1107                                                mapit != unique_verts_inds_by_geo[i].end();
1108                                                mapit++)
1109                        {
1110                                //      Key and value.
1111                                int isrc = mapit->first;
1112                                int idst = mapit->second;
1113
1114                                //      Vertex coordinate.
1115                                //      Construction of the submeshes.
1116                                Vector3 v3((Real)M0.vertex(isrc)->operator [](0),
1117                                                (Real)M0.vertex(isrc)->operator [](1),
1118                                                (Real)M0.vertex(isrc)->operator [](2));
1119                                mGeoMesh->mSubMesh[i].mVertexBuffer->mPosition[idst]=v3;
1120
1121                                //      Normal coordinates.
1122                                Vector3 v3n((Real)M0.normal(isrc)(0), (Real)M0.normal(isrc)(1), (Real)M0.normal(isrc)(2));
1123                                mGeoMesh->mSubMesh[i].mVertexBuffer->mNormal[idst]=v3n;
1124
1125                                //      Texture coordinates.
1126                                Vector2 v2((Real)M0.texcoord(isrc)(0), (Real)M0.texcoord(isrc)(1));
1127                                mGeoMesh->mSubMesh[i].mVertexBuffer->mTexCoords[idst]=v2;
1128                        }
1129                }
1130                else
1131                {
1132                        //      Leaves mesh.
1133                        mGeoMesh->mSubMesh[i].mIndexCount=objmesh->mSubMesh[i].mIndexCount;
1134                        mGeoMesh->mSubMesh[i].mIndex=new Index[mGeoMesh->mSubMesh[i].mIndexCount];
1135
1136                        //      Copy the leaves submesh indexes.
1137                        for (unsigned int j=0; j<mGeoMesh->mSubMesh[i].mIndexCount; j++)
1138                        {       
1139                                mGeoMesh->mSubMesh[i].mIndex[j]=objmesh->mSubMesh[i].mIndex[j];
1140                        }
1141
1142                        //      Copy the leaves submesh vertices.
1143                        mGeoMesh->mSubMesh[i].mVertexBuffer=new VertexBuffer();
1144                        mGeoMesh->mSubMesh[i].mVertexBuffer->mVertexCount=objmesh->mSubMesh[i].mVertexBuffer->mVertexCount;
1145                        mGeoMesh->mSubMesh[i].mVertexBuffer->mVertexInfo=objmesh->mSubMesh[i].mVertexBuffer->mVertexInfo;
1146
1147                        //      Allocate memory for position, normal and texture coordinates.
1148                        mGeoMesh->mSubMesh[i].mVertexBuffer->mPosition=new Vector3[mGeoMesh->mSubMesh[i].mVertexBuffer->mVertexCount];
1149                        mGeoMesh->mSubMesh[i].mVertexBuffer->mNormal=new Vector3[mGeoMesh->mSubMesh[i].mVertexBuffer->mVertexCount];
1150                        mGeoMesh->mSubMesh[i].mVertexBuffer->mTexCoords=new Vector2[mGeoMesh->mSubMesh[i].mVertexBuffer->mVertexCount];
1151
1152                        for (   unsigned int j = 0;
1153                                        j < mGeoMesh->mSubMesh[i].mVertexBuffer->mVertexCount;
1154                                        j++)
1155                        {
1156                                //      Position.
1157                                mGeoMesh->mSubMesh[i].mVertexBuffer->mPosition[j].x=objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].x;
1158                                mGeoMesh->mSubMesh[i].mVertexBuffer->mPosition[j].y=objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].y;
1159                                mGeoMesh->mSubMesh[i].mVertexBuffer->mPosition[j].z=objmesh->mSubMesh[i].mVertexBuffer->mPosition[j].z;
1160
1161                                //      Normals.
1162                                mGeoMesh->mSubMesh[i].mVertexBuffer->mNormal[j].x=objmesh->mSubMesh[i].mVertexBuffer->mNormal[j].x;
1163                                mGeoMesh->mSubMesh[i].mVertexBuffer->mNormal[j].y=objmesh->mSubMesh[i].mVertexBuffer->mNormal[j].y;
1164                                mGeoMesh->mSubMesh[i].mVertexBuffer->mNormal[j].z=objmesh->mSubMesh[i].mVertexBuffer->mNormal[j].z;
1165
1166                                //      Textures.
1167                                mGeoMesh->mSubMesh[i].mVertexBuffer->mTexCoords[j].x=objmesh->mSubMesh[i].mVertexBuffer->mTexCoords[j].x;
1168                                mGeoMesh->mSubMesh[i].mVertexBuffer->mTexCoords[j].y=objmesh->mSubMesh[i].mVertexBuffer->mTexCoords[j].y;
1169                        }
1170                }
1171        }
1172
1173        delete[] unique_verts_inds_by_geo;
1174        delete[] ver_inds_rep_by_geo;
1175        delete[] inextvert;
1176
1177        //      Store the simplification steps in MeshSimplificationSequence.
1178        int acum        =       0;
1179
1180        for (size_t i   =       0; i < objmesh->mSubMeshCount; i++)
1181        {
1182                if (objmesh->mSubMesh[i].mSharedVertexBuffer)
1183                {
1184                        first_index_submesh[i]  =       0;
1185                }
1186                else
1187                {
1188                        first_index_submesh[i]  =       acum;
1189                }
1190
1191                acum    +=      (int)objmesh->mSubMesh[i].mVertexBuffer->mVertexCount;
1192        }
1193
1194        MeshSimplificationSequence::Step stepaux, newstep;
1195        vector<int> v0,v1,submesh0,submesh1;
1196        MeshSimplificationSequence *msimpseq;
1197
1198        msimpseq        =       new MeshSimplificationSequence();
1199
1200        for (unsigned i = 0;    i < decim_data.size();  i++)
1201        {
1202                stepaux         =       decim_data.operator [](i);
1203                v0                              =       vertexbuffermap[stepaux.mV0];  // vertexbuffer index
1204                submesh0        =       submeshmap[stepaux.mV0]; // displacement by submesh
1205                v1                              =       vertexbuffermap[stepaux.mV1];
1206                submesh1        =       submeshmap[stepaux.mV1];
1207
1208                for (unsigned j = 0;    j < v0.size();  j++)
1209                {
1210                        for (unsigned k = 0;    k < v1.size(); k++)
1211                        {
1212                                //      Obtain the submesh index in VertexBuffer
1213                                //      and the displacement by submesh
1214                                newstep.mV0     =       v0.operator [](j)+first_index_submesh[submesh0.operator [](j)];
1215                                newstep.mV1     =       v1.operator [](k)+first_index_submesh[submesh1.operator [](k)];
1216                                newstep.x               =       stepaux.x;
1217                                newstep.y               =       stepaux.y;
1218                                newstep.z               =       stepaux.z;
1219
1220                                // mT0 y mT1 are unique triangles identifiers
1221                                // returned by the simplification method
1222                                newstep.mT0     =       stepaux.mT0;
1223                                newstep.mT1     =       stepaux.mT1;
1224
1225                                if (j == v0.size() - 1 && k == v1.size() - 1)
1226                                {
1227                                        newstep.obligatorio     =       0;
1228                                }
1229                                else
1230                                {
1231                                        newstep.obligatorio     =       1;
1232                                }
1233
1234                                if (j == 0 && k == 0)
1235                                {
1236                                        //      First simplification step.
1237                                        //      unique triangle identifiers
1238                                        //      returned by the simplification method.
1239                                        newstep.mModfaces       =       stepaux.mModfaces;
1240                                }
1241                                else
1242                                {
1243                                        std::vector<Index>      vvacio;
1244
1245                                        newstep.mModfaces       =       vvacio;
1246                                }
1247
1248                                msimpseq->mSteps.push_back(newstep);
1249                        }
1250                }
1251        }
1252
1253        // WriteOBJ();
1254        return msimpseq;
1255}
1256
1257//---------------------------------------------------------------------------
1258//      Set submesh leaves.
1259//---------------------------------------------------------------------------
1260void SimplificationMethod::setMeshLeaves(int meshLeaves)
1261{
1262        indexMeshLeaves =       meshLeaves;
1263}
1264
1265//      Gets mesh simplified.
1266Mesh    *       SimplificationMethod::GetMesh()
1267{
1268        return  mGeoMesh;
1269}
1270
Note: See TracBrowser for help on using the repository browser.