source: GTP/trunk/Lib/Geom/shared/GTGeometry/src/GeoLodStripsLibrary.cpp @ 2085

Revision 2085, 18.4 KB checked in by gumbau, 17 years ago (diff)
Line 
1/*========================================================================
2 *      (C) 2005 Universitat Jaume I
3 *========================================================================
4 *      PROYECT:        GAME TOOLS
5 *========================================================================
6 *      CONTENT:
7 *
8 *
9 *      @file   GeoLodStripsLibrary.cpp
10 *=======================================================================*/
11
12#include "GeoLodStripsLibrary.h"
13
14using namespace Geometry;
15using   namespace       std;
16
17//-------------------------------------------------------------------------
18//      Constructor.
19//-------------------------------------------------------------------------
20LodStripsLibrary::LodStripsLibrary(
21                                                                                                                const LodStripsLibraryData      *lodstripsdata,
22                                                                                                                Mesh                                                                                            *geomesh,
23                                                                                                                IndexData                                                                               *userindexdata)
24{
25        //      Sets the current lod.
26        mCurrentLod     =       0;
27
28        //      Sets the global mesh.
29        mGeoMesh = geomesh;
30
31        delete_indexdata                                =       false;
32        dataRetrievalInterface  =       userindexdata;
33        indices_x_submesh                               =       NULL;
34        offsets_x_submesh                               =       NULL;
35        mStripsSubmesh                                  =       NULL;
36        submesh_x_strip                                 =       NULL;
37        lodFactor                                                               =       1.0f;
38        current_triangle_count  =       0;
39       
40        //      Loads the Level Of Detail file.
41        LodStripsLibrary::LoadStripMesh(lodstripsdata,mGeoMesh);
42
43        GoToLod(0.0f);
44
45        minFaces        =       0;
46
47        for (unsigned int strip = 0; strip < mTotalStrips; strip++)
48        {
49                minFaces        +=      int(mStrips[strip].size() - 2);
50        }
51
52        GoToLod(1.0f);
53
54        maxFaces        =       0;
55
56        for (unsigned int strip = 0; strip < mTotalStrips; strip++)
57        {
58                maxFaces        +=      int(mStrips[strip].size() - 2);
59        }
60}
61
62//-------------------------------------------------------------------------
63//      Destructor
64//-------------------------------------------------------------------------
65LodStripsLibrary::~LodStripsLibrary()
66{
67        delete  [] mStrips;
68        if (delete_indexdata)
69                delete dataRetrievalInterface;
70        if (indices_x_submesh)
71                delete[] indices_x_submesh;
72        if (offsets_x_submesh)
73                delete[] offsets_x_submesh;
74        if (mStripsSubmesh)
75                delete[] mStripsSubmesh;
76        if (submesh_x_strip)
77                delete[] submesh_x_strip;
78}
79
80//-------------------------------------------------------------------------
81//      Public.
82//-------------------------------------------------------------------------
83
84//-------------------------------------------------------------------------
85//      Go to the level of detail.
86//-------------------------------------------------------------------------
87void LodStripsLibrary::GoToLod(float lodfactor)
88{
89        register        int                     j;
90        register        int                     offset;
91        long                    int                     i;
92        long                    int                     k;
93        long                    int                     b_change_ok     =       1;
94        unsigned long   int     lod;
95        long                    int                     t;
96        long                    int                     r;
97        long                    int                     next;
98        long                    int                     el1;
99        long                    int                     el2;
100        long                    int                     total_changes;
101        long                    int                     totalR;
102        SmallIntVector                                          *strip;
103        SmallIntVector::iterator        start;
104
105        if (lodfactor<0.0f) lodfactor=0.0f;
106        if (lodfactor>1.0f) lodfactor=1.0f;
107
108        uint32 newLOD = (uint32)((1.0f - lodfactor) * mLods);
109
110        lodFactor=lodfactor;
111   
112        if (newLOD != mCurrentLod)
113        {
114                if (newLOD > mCurrentLod)
115                {
116                        //      Forwards.
117                        //      Increments LOD (decreases level of detail)
118                        for (   lod     =       mCurrentLod;
119                                                (lod < newLOD)
120                                                ||
121                                                ((mCurrentRegLOD->obligatory == 1) && (lod < (mLods - 1)));
122                                                lod++)
123                        {
124                                next                                    =       mVertex[lod];
125                                total_changes   =       mPChanges[lod];
126
127                                for (i = 0; i < total_changes; i++)
128                                {
129                                        //      Strip change.
130                                        t                       =       mCurrentRegLOD->strip;
131                                        strip   =       &(mStrips[t]);
132                                        start   =       strip->begin();
133
134                                        int stripsize_ini = strip->size();
135                               
136                                        //      Position.
137                                        totalR  =       mCurrentRegLOD->position;
138
139                                        for (j = totalR - 1; j >= 0; j--)
140                                        {
141                                                start[*mCurrentData]    =       next;                                           
142                                                ++mCurrentData;
143                                        }
144                                       
145                                        //      L1.
146                                        totalR  =       mCurrentRegLOD->vertexRepetition;
147                                       
148                                        for (j = totalR - 1; j >= 0; j--)
149                                        {
150                                                offset  =       *mCurrentData + 1;
151
152                                                strip->erase(   start + offset,
153                                                                                                        start
154                                                                                                        +
155                                                                                                        offset
156                                                                                                        +
157                                                                                                        (*(mCurrentData + 1)));
158
159                                                ++mCurrentData;
160                                                ++mCurrentData;
161                                        }
162                                       
163                                        //      L2
164                                        totalR  =       mCurrentRegLOD->edgeRepetition;
165                                       
166                                        for (j = totalR - 1; j >= 0; j--)
167                                        {
168                                                offset  =       *mCurrentData + 2;
169                                                strip->erase(   start   +       offset,
170                                                                                                        start
171                                                                                                        +
172                                                                                                        offset
173                                                                                                        +
174                                                                                                        2*(*(mCurrentData + 1)));
175
176                                                mCurrentData++;
177                                                mCurrentData++;
178                                        }
179
180//                                      lastLOD = mCurrentRegLOD;
181                                        mCurrentRegLOD++;
182                                       
183                                        mStripsChanges[t]       =       1;
184
185                                        int stripsize_end = strip->size();
186                                        indices_x_submesh[submesh_x_strip[t]] -= (stripsize_ini - stripsize_end);
187                               
188                                }
189                               
190                                mCurrentLod     =       lod + 1;
191                        }
192
193                }
194                //      If LOD is less than actual.
195                else
196                {
197                        mCurrentRegLOD--;
198                        mCurrentData--;
199
200
201                        //      Decrements LOD.
202                        for (   lod     =       mCurrentLod;
203                                                (lod > newLOD)
204                                                ||
205                                                ((mCurrentRegLOD->obligatory == 1) && (lod > 0))
206                                                ||
207                                                ((mCurrentRegLOD[1].obligatory == 1) && (lod > 0));
208                                                lod--)
209                        {
210
211                                total_changes   =       mPChanges[lod - 1];
212                               
213                                for (i = 0; i < total_changes; i++)
214                                {
215                                        t                       =       mCurrentRegLOD->strip;
216                                        strip   =       &(mStrips[t]);
217                                        start   =       mStrips[t].begin();
218                                        int stripsize_ini = strip->size();
219
220                                        //      L2.
221                                        totalR  =       mCurrentRegLOD->edgeRepetition;
222                                       
223                                        for (j = 0; j < totalR; j++)
224                                        {
225                                                el1     =       (*strip)[*(mCurrentData - 1)];
226                                                el2     =       (*strip)[*(mCurrentData - 1) + 1];
227                                                r               =       *(mCurrentData);
228                                               
229                                                for (k = 0; k < r; k++)
230                                                {
231                                                        (*strip).insert(start+*(mCurrentData - 1),el2);
232                                                        (*strip).insert(start+*(mCurrentData - 1),el1);
233                                                }
234                                               
235                                                mCurrentData--;
236                                                mCurrentData--;
237                                        }
238
239                                        //      Vertex Repetition.
240                                        totalR  =       mCurrentRegLOD->vertexRepetition;
241                                       
242                                        for (j = 0; j < totalR; j++)
243                                        {
244                                                el1     =       (*strip)[*(mCurrentData-1)];
245                                                r               =       *(mCurrentData);
246                                               
247                                                for (k = 0; k < r; k++)
248                                                {
249                                                        (*strip).insert(start+*(mCurrentData-1),el1);
250                                                }
251
252                                                mCurrentData--;
253                                                mCurrentData--;
254                                        }
255                                       
256                                        //      POS.
257                                        totalR  =       mCurrentRegLOD->position;
258                                       
259                                        for (j = 0; j < totalR; j++)
260                                        {
261                                                (*strip)[*mCurrentData] =       lod - 1;
262                                                mCurrentData--;
263                                        }
264                                       
265        //                              lastLOD = mCurrentRegLOD;
266                                        mCurrentRegLOD--;
267                                        mStripsChanges[t]       =       1;
268
269                                        int stripsize_end = strip->size();
270                                        indices_x_submesh[submesh_x_strip[t]] += (stripsize_end - stripsize_ini);
271                                }                       
272                               
273                                //      Update LOD.
274                                mCurrentLod     =       lod - 1;
275
276                                //      Debug.
277                                cout    <<      "Obligatory: "
278                                                        <<      (int)mCurrentRegLOD->obligatory
279                                                        <<      endl;
280                        }
281                       
282                        mCurrentData++;
283                        mCurrentRegLOD++;
284                }
285        }
286
287/*      // debug!
288        FILE *f = fopen("lodstrips_lodinfo.txt","wt");
289        fprintf(f,"mCurrentLOD: %d",mCurrentLod);
290        fprintf(f,"mLods: %d",mLods);
291        for (int i=0; i<mTotalStrips; i++)
292        {
293                fprintf(f,"\nstrip: %d - ",i);
294                for (int j=0; j<mStrips[i].size(); j++)
295                {
296                        int ind = mStrips[i][j];
297                        fprintf(f,"%d ",ind);
298                }
299        }
300        fclose(f);*/
301
302        UpdateDataRetrievalInterface();
303//      return  return_value;
304}
305
306//-------------------------------------------------------------------------
307//      Returns the number of vertices of the highest LOD.
308//-------------------------------------------------------------------------
309uint32  LodStripsLibrary::MaxVertices()
310{
311        return  mMaxVerticesLOD;
312}
313
314//-------------------------------------------------------------------------
315//      Returns the number of vertices of the lowest LOD.
316//-------------------------------------------------------------------------
317uint32  LodStripsLibrary::MinVertices()
318{
319        uint32  number_of_vertices;
320
321        //      Total vertices of minimum lod.
322        number_of_vertices      =       mMaxVerticesLOD - (mMinLod + 1);
323
324        return  number_of_vertices;
325}
326
327//-------------------------------------------------------------------------
328//      Returns the number of triangles of the highest LOD.
329//-------------------------------------------------------------------------
330uint32  LodStripsLibrary::MaxFaces()
331{
332/*      uint32  number_of_faces;
333
334        uint32  current_lod;
335
336        current_lod     =       GoToLod(MaxLod());
337
338        //      Initialize number of faces count.
339        number_of_faces =       0;
340
341        //      For each strip.
342        for (unsigned int strip =       0; strip < mTotalStrips; strip++)
343        {
344                number_of_faces +=      int(mStrips[strip].size() - 2);
345        }
346
347        GoToLod(current_lod);
348
349        return  number_of_faces;*/
350
351        return maxFaces;
352}
353
354//-------------------------------------------------------------------------
355//      Returns the number of triangles of the lowest LOD.
356//-------------------------------------------------------------------------
357uint32  LodStripsLibrary::MinFaces()
358{
359/*      uint32  current_lod;
360        uint32  number_of_faces;
361
362        current_lod     =       GoToLod(MinLod());
363
364        //      Initialize number of faces count.
365        number_of_faces =       0;
366
367        //      For each strip.
368        for (unsigned int strip =       0; strip < mTotalStrips; strip++)
369        {
370                number_of_faces +=      int(mStrips[strip].size() - 2);
371        }
372
373        GoToLod(current_lod);
374
375        return  number_of_faces;*/
376
377        return minFaces;
378}
379
380//-------------------------------------------------------------------------
381//      Establishes the new LOD range.
382//      Only the LODs in that range are stored and used.
383//-------------------------------------------------------------------------
384void            LodStripsLibrary::TrimByLod(uint32 minLod, uint32 maxLod)
385{
386        //      Refresh number of vercies of the max lod.
387        mMaxVerticesLOD +=      mMaxLod - maxLod;
388       
389        mMinLod =       minLod;
390        mMaxLod =       maxLod;
391}
392/*
393//-------------------------------------------------------------------------
394//      Get strip count.
395//-------------------------------------------------------------------------
396uint32  LodStripsLibrary::GetStripCount() const
397{
398        return  (uint32)        mTotalStrips;
399}
400
401//-------------------------------------------------------------------------
402//      Get Index by strip.
403//-------------------------------------------------------------------------
404uint32  LodStripsLibrary::GetIndexCountByStrip(uint32 istrip) const
405{
406        return (uint32) mStrips[istrip].size();
407}
408*/
409//-------------------------------------------------------------------------
410//      Private.
411//-------------------------------------------------------------------------
412
413//-------------------------------------------------------------------------
414//      Copy a STL vector to a C array.
415//-------------------------------------------------------------------------
416void LodStripsLibrary::CopyVectors2Arrays(void)
417{
418        SmallInt                                        max;
419        SmallInt                                        t;
420        SmallInt                                        *data_array;
421        SmallIntVector          tira;
422        LODRegisterType         *changes_array;
423        LODRegisterVector       list_changes;
424
425        mTotalStrips            =       int(mFileStrips.size());
426        mVertex                                 =       new SmallInt[mTotalVertices];
427        mStripsChanges  =       new SmallInt[mTotalChanges];
428        mStrips                                 =       new SmallIntVector[mTotalStrips];
429        data_array                      =       new SmallInt[mData.size()];
430       
431        max                                     =       0;
432        mTotalFaces     =       0;
433
434//      unsigned int * strip_sizes = new unsigned int[mFileStrips.size()];
435        unsigned int total_strip_size = 0;
436       
437        for (unsigned   int     i = 0; i < mFileStrips.size(); i++)
438        {
439                total_strip_size += t = int(mFileStrips[i].size());
440                if (t>max)
441                        max     =       t;
442                mTotalFaces     +=      t - 2;
443        }
444
445        changes_array   =       new LODRegisterType[mFileChangesLOD.size()];
446       
447        //      Fill up changes array.
448        for (unsigned   int     i = 0; i < mFileChangesLOD.size(); ++i)
449        {
450                changes_array[i]        =       mFileChangesLOD[i];
451        }
452
453        mCurrentRegLOD  =       changes_array;
454       
455//      Copy strips.
456//      unsigned int numDegenerated = 2*mTotalStrips - 2;
457//      dataRetrievalInterface=create_index_data_func(total_strip_size,indexdata_user_data); // temporal!
458
459//      dataRetrievalInterface->Init(total_strip_size);
460/*      dataRetrievalInterface->numinds=total_strip_size;
461        dataRetrievalInterface->numvalidinds=total_strip_size;*/
462//      dataRetrievalInterface->Begin();
463
464        unsigned        int     ii = 0;
465
466        for (unsigned   int     i = 0; i < mFileStrips.size(); i++)
467        {
468                for (unsigned   int     j = 0; j < mFileStrips[i].size(); j++,ii++)
469                {
470                        mStrips[i].push_back(mFileStrips[i][j]);
471//                      dataRetrievalInterface->SetIndex(ii,mFileStrips[i][j]);
472                }
473               
474                //      Reset flags of strips changed.
475                mStripsChanges[i]       =       0;
476        }
477
478//      dataRetrievalInterface->End();
479
480        for (unsigned   int     i = 0; i < mData.size(); i++)
481        {
482                data_array[i]   =       mData[i];
483        }
484       
485        mCurrentData    =       data_array;
486
487        //      Fill up mVertex.
488        for(unsigned    int     i = 0; i < mFileVertices.size(); i++)
489        {
490                mVertex[i]      =       mFileVertices[i];
491        }
492
493//      delete[] strip_sizes;
494}
495
496//-------------------------------------------------------------------------
497//      LoadStripMesh
498//-------------------------------------------------------------------------
499void LodStripsLibrary::LoadStripMesh(
500                                                                                                                const LodStripsLibraryData *lodstripsdata,
501                                                                                                                Mesh *geomesh)
502{
503        SmallIntVector                                                                          strip_aux;
504        std::vector                     <LODRegisterType>       list_pos;
505        std::vector                     <unsigned int>          p_changes;
506        int                                                                                                                             v                       =       0;
507        int                                                                                                                             t                       =       -1;
508        int                                                                                                                             s                       =       0;
509        int                                                                                                                             next    =       0;
510        int                                                                                                                             c                       =       -1;
511        Index                                                                                                                   *index;
512        Index                                                                                                                   *indexBegin;
513        Index                                                                                                                   *indexEnd;
514        SubMesh                                                                                                         *geoSubMesh;
515
516        //      For each one of the submeshes.
517        indices_x_submesh = new int[geomesh->mSubMeshCount];
518        offsets_x_submesh = new int[geomesh->mSubMeshCount];
519
520        int totaltiras = 0;
521
522        for (   unsigned int submesh = 0;
523                                submesh < geomesh->mSubMeshCount;
524                                submesh++)
525        {
526                for (   unsigned int strip = 0;
527                                        strip < geomesh->mSubMesh[submesh].mStripCount;
528                                        strip++)
529                {
530                        totaltiras++;
531                }
532        }
533
534        submesh_x_strip = new int[totaltiras];
535
536        int istrip = 0;
537       
538        for (   size_t  submesh =       0;      submesh < geomesh->mSubMeshCount;       submesh++)
539        {
540                geoSubMesh      =       &geomesh->mSubMesh[submesh];
541                indices_x_submesh[submesh] = 0;
542
543                //      For each one of the strips.
544                for (   unsigned int strip = 0;
545                                        strip < geoSubMesh->mStripCount;
546                                        strip++, istrip++)
547                {
548                        // Insert an empty strip.
549                        submesh_x_strip[istrip] = submesh;
550                        t++;
551                        strip_aux.clear();
552                        mFileStrips.push_back(strip_aux);
553
554                        //      First index of the strip.
555                        indexBegin      =       geoSubMesh->mStrip[strip];
556
557                        //      If the strips is not the first. (DEG!)
558                        if (strip != 0)
559                        {
560                                indexBegin++;
561                        }
562
563                        //      If is the final strip
564                        if (strip       == (geoSubMesh->mStripCount - 1))
565                        {
566                                //      The end of the index array.
567                                indexEnd        = &geoSubMesh->mIndex[geoSubMesh->mIndexCount];
568                        }
569                        else
570                        {
571                                //      The beginning of the next strip.
572                                indexEnd        = geoSubMesh->mStrip[strip + 1];
573
574                                //      Remove degenerated (DEG!)
575                                indexEnd--;
576                        }
577                       
578                        int i;
579                        i       = 0;
580                       
581                        if (submesh==0)
582                        {
583                                offsets_x_submesh[submesh] = 0;
584                        }
585                        else
586                        {
587                                offsets_x_submesh[submesh] = indices_x_submesh[submesh-1];
588                        }
589
590                        //      For each index of the strip.
591                        for (index = indexBegin; index < indexEnd; index++)
592                        {
593                                mFileStrips[t].push_back(indexBegin[i]);
594                                indices_x_submesh[submesh]++;
595                                i++;
596                        }
597                }
598        }
599
600        mFileVertices           = lodstripsdata->mFileVertices;
601        mFileChangesLOD = lodstripsdata->mFileChangesLOD;
602        mData                                           = lodstripsdata->mData;
603        p_changes                               = lodstripsdata->p_changes;
604
605        mStripsSubmesh  = new int [geomesh->mSubMeshCount];
606
607        for (size_t     submesh = 0; submesh < geomesh->mSubMeshCount; submesh++)
608        {
609                mStripsSubmesh[submesh] =       0;
610        }
611
612        //      Max / Min values for LOD.
613        mLods                                                                                   =       int(p_changes.size());
614        mMaxLod                                                                         =       0;
615        mMinLod                                                                         =       mLods;
616
617        mPChanges                       =       new SmallInt[mLods];
618       
619        for (unsigned int i = 0; i < mLods; i++)
620        {
621                mPChanges[i] = p_changes[i];
622        }
623
624        mTotalVertices          =       int(mFileVertices.size());
625        mMaxVerticesLOD         =       mTotalVertices;
626        mTotalStrips                    =       int(mFileStrips.size());
627        mTotalChanges                   =       int(mFileChangesLOD.size());
628
629        //Copy the data to the structure we will use
630        CopyVectors2Arrays();
631}
632
633void LodStripsLibrary::UpdateDataRetrievalInterface(void)
634{
635        int                                             target_submesh  =       0;
636        size_t                          strip_count                     =       0;
637        unsigned int    ii_submesh                      =       0;
638        uint32                          numdeg                                  =       0;
639
640        current_triangle_count = 0;
641
642        // indices_x_submesh is calculated without degenerates,
643        // we must add the degenerate indices added here
644        if (mGeoMesh->mSubMesh[target_submesh].mStripCount > 0)
645        {
646                numdeg = mGeoMesh->mSubMesh[target_submesh].mStripCount * 2 - 2;
647        }
648
649        dataRetrievalInterface->Begin(target_submesh,
650                                                                                                                                indices_x_submesh[target_submesh] + numdeg);
651
652        current_triangle_count  +=      indices_x_submesh[target_submesh] + numdeg;
653
654        //      For each strip.
655        for (unsigned int i = 0; i < mTotalStrips; i++, strip_count++)
656        {
657                if (strip_count >= mGeoMesh->mSubMesh[target_submesh].mStripCount)
658                {
659                        if (target_submesh == 0)
660                        {
661                                offsets_x_submesh[target_submesh] = 0;
662                        }
663                        else
664                        {
665                                offsets_x_submesh[target_submesh] =
666                                                                        indices_x_submesh[target_submesh-1]
667                                                                        +
668                                                                        offsets_x_submesh[target_submesh-1];
669                        }
670
671                        mStripsSubmesh[target_submesh]  =       (int)strip_count;
672                        strip_count     =       0;
673
674                        target_submesh++;
675                        ii_submesh = 0;
676                        dataRetrievalInterface->End();
677
678                        if (mGeoMesh->mSubMesh[target_submesh].mStripCount > 0)
679                        {
680                                numdeg = mGeoMesh->mSubMesh[target_submesh].mStripCount*2 - 2;
681                        }
682
683                        dataRetrievalInterface->Begin(target_submesh,
684                                                                                                                                                indices_x_submesh[target_submesh]
685                                                                                                                                                +
686                                                                                                                                                numdeg);
687                       
688                        current_triangle_count  +=      indices_x_submesh[target_submesh]
689                                                                                                                                        +
690                                                                                                                                        numdeg;
691                }
692
693                int lastindex = -1;
694
695                for (   SmallIntVector::iterator it     =       mStrips[i].begin();
696                                        it != mStrips[i].end();
697                                        it++, ii_submesh++)
698                {
699                        // repeat the first index of the strip: degenerate (DEG!)
700                        // except for the first strip in a mesh
701                        if ((lastindex == -1) && (strip_count > 0))
702                        {
703                                lastindex       =       *it;
704
705                                dataRetrievalInterface->SetIndex(ii_submesh,*it);
706                                ii_submesh++;
707                        }
708
709                        lastindex       =       *it;
710                        dataRetrievalInterface->SetIndex(ii_submesh,*it);
711                }
712
713                // repeat last vertex of the strip: degenerate (DEG!)
714                // except for the last strip in a mesh
715                if (strip_count < mGeoMesh->mSubMesh[target_submesh].mStripCount-1)
716                {
717                        dataRetrievalInterface->SetIndex(ii_submesh,lastindex);
718                        ii_submesh++;
719                }
720        }
721
722        if (strip_count >= mGeoMesh->mSubMesh[target_submesh].mStripCount)
723        {
724                if (target_submesh == 0)
725                {
726                        offsets_x_submesh[target_submesh] = 0;
727                }
728                else
729                {
730                        offsets_x_submesh[target_submesh] =
731                                                                        indices_x_submesh[target_submesh - 1]
732                                                                        +
733                                                                        offsets_x_submesh[target_submesh - 1];
734                }
735
736                mStripsSubmesh[target_submesh]  =       (int)strip_count;
737                strip_count                                                                                     =       0;
738
739                target_submesh++;
740        }
741
742        dataRetrievalInterface->End();
743}
744
Note: See TracBrowser for help on using the repository browser.