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

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