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

Revision 774, 32.9 KB checked in by gumbau, 18 years ago (diff)

GTGeometry and GeoTool? initial imports

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