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

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