source: GTP/trunk/App/Demos/Geom/Demo_LodStrips/OgreLodStripsLibrary.cpp @ 1041

Revision 1041, 15.0 KB checked in by gumbau, 18 years ago (diff)
Line 
1/*      ==========================================================================
2 *      (C) 2006 Universitat Jaume I
3 *      ==========================================================================
4 *      PROYECT:        GAME TOOLS
5 *      ==========================================================================*/
6/**     CONTENT:       
7        *
8        *
9        *       @file   OgreLodStripsLibrary.cpp
10/*===========================================================================*/
11
12#include "OgreLodStripsLibrary.h"
13
14//-----------------------------------------------------------------------------
15//      Constructors.
16//-----------------------------------------------------------------------------
17LodStripsLibrary::LodStripsLibrary(     std::string     name, Ogre::Mesh        *geomesh)
18{
19        const   char    *name_of_file;
20
21        mMaxLod=0;
22        mMinLod=0;
23
24        //      Sets the current lod.
25        mCurrentLod     =       0;
26
27        //      Converts a String to const char *.
28        name_of_file    =       name.data();
29
30        original_mesh=geomesh;
31
32        //      Loads the Level Of Detail file.
33        LodStripsLibrary::LoadStripMesh((char*)name_of_file,geomesh);
34}
35
36//-----------------------------------------------------------------------------
37//      Destroyer.
38//-----------------------------------------------------------------------------
39LodStripsLibrary::~LodStripsLibrary()
40{               
41                delete [] mPChanges;
42               
43                if (mMaxLod>0)
44                        delete [] mStrips;
45
46                delete [] mVertex;
47                delete [] mStripsSubmesh;
48                delete [] mRegLODBegin;
49                delete [] mDataBegin;
50}
51
52//-----------------------------------------------------------------------------
53//      Public.
54//-----------------------------------------------------------------------------
55
56/*
57        Go to the level of detail.
58*/
59Ogre::uint32 LodStripsLibrary::GoToLod(Ogre::uint32 newLOD)
60{
61        register        int                                                     j;
62        register        int                                                     offset;
63        unsigned                        int                                                     i;
64        long                    int                                                     k;
65        long                    int                                                     l;
66        unsigned                        int                                                     lod;
67        long                    int                                                     t;
68        long                    int                                                     r;
69        long                    int                                                     sig;
70        long                    int                                                     el1;
71        long                    int                                                     el2;
72        long                    int                                                     total_changes;
73        long                    int                                                     totalR;
74        SmallIntVector                                          *strip;
75        SmallIntVector::iterator        start;
76        Ogre::uint32                                                                            return_value;
77
78        //      Initialize the return value to the current LOD.
79        return_value    =       mCurrentLod;
80
81        if (newLOD != mCurrentLod)
82        {
83                if (newLOD > mCurrentLod)
84                {
85                        //HACIA ADELANTE
86                        //CurrentRegLOD
87                        //Incrementamos el LOD -> Calcular siguientes
88                        for (lod = mCurrentLod; lod < newLOD; lod++)
89                        {
90                                sig                             =       mVertex[lod];
91                                total_changes   =       mPChanges[lod];
92
93                                for (i = 0; i < total_changes; i++)
94                                {
95                                        //      Strip q Cambia.
96                                        t                       =       mCurrentRegLOD->strip;
97                                        strip   =       &(mStrips[t]);
98                                        //start =       strip->begin();
99
100                                        start=(mStrips+t)->begin();
101                               
102                                        //      Position.
103                                        totalR  =       mCurrentRegLOD->position;
104
105                                        for (j = totalR - 1; j >= 0; j--)
106                                        {
107                                                //start[*mCurrentData]  =       sig;
108                                                *(start+*mCurrentData)=sig;
109                                               
110                                                ++mCurrentData;
111                                        }
112                                       
113                                        //      L1.
114                                        totalR  =       mCurrentRegLOD->vertexRepetition;
115                                       
116                                        for (j = totalR - 1; j >= 0; j--)
117                                        {
118                                                offset  =       *mCurrentData + 1;
119
120                                                strip->erase(   start + offset,
121                                                                                                        start
122                                                                                                        +
123                                                                                                        offset
124                                                                                                        +
125                                                                                                        (*(mCurrentData + 1)));
126
127                                                ++mCurrentData;
128                                                ++mCurrentData;
129                                        }
130                                       
131                                        //      L2
132                                        totalR  =       mCurrentRegLOD->edgeRepetition;
133                                       
134                                        for (j = totalR - 1; j >= 0; j--)
135                                        {
136                                                offset  =       *mCurrentData + 2;
137                                                strip->erase(   start   +       offset,
138                                                                                                        start
139                                                                                                        +
140                                                                                                        offset
141                                                                                                        +
142                                                                                                        2*(*(mCurrentData + 1)));
143
144                                                ++mCurrentData;
145                                                ++mCurrentData;
146                                        }
147
148                                        ++mCurrentRegLOD;
149                                       
150                                       
151                               
152                                }
153                               
154                                mCurrentLod     =       lod + 1;
155                        }
156
157                }
158                //      Si el nuevo LOD es menos que el actual.
159                else
160                {
161                        --mCurrentRegLOD;
162                        --mCurrentData;
163                       
164                        //      Decrementamos el LOD -> Calcular anteriores.
165                        for (lod = mCurrentLod; lod > newLOD; lod--)
166                        {
167                                total_changes   =       mPChanges[lod - 1];
168                               
169                                for (i = 0; i < total_changes; i++)
170                                {
171                                        t                       =       mCurrentRegLOD->strip;
172                                        strip   =       &(mStrips[t]);
173                                        //start =       mStrips[t].begin();
174
175                                        start=(mStrips+t)->begin();
176
177                                        //      L2.
178                                        totalR  =       mCurrentRegLOD->edgeRepetition;
179                                       
180                                        for (j = 0; j < totalR; j++)
181                                        {
182                                                el1     =       (*strip)[*(mCurrentData - 1)];
183                                                el2     =       (*strip)[*(mCurrentData - 1) + 1];
184                                                r               =       *(mCurrentData);
185                                               
186                                                for (k = 0; k < r; k++)
187                                                {
188                                                        (*strip).insert(start+*(mCurrentData - 1),el2);
189                                                        (*strip).insert(start+*(mCurrentData - 1),el1);
190                                                }
191                                               
192                                                --mCurrentData;
193                                                --mCurrentData;
194                                        }
195
196                                        //      Vertex Repetition.
197                                        totalR  =       mCurrentRegLOD->vertexRepetition;
198                                       
199                                        for (j = 0; j < totalR; j++)
200                                        {
201                                                el1     =       (*strip)[*(mCurrentData-1)];
202                                                r               =       *(mCurrentData);
203                                               
204                                                for (k = 0; k < r; k++)
205                                                {
206                                                        (*strip).insert(start+*(mCurrentData-1),el1);
207                                                }
208
209                                                --mCurrentData;
210                                                --mCurrentData;
211                                        }
212                                       
213                                        //      POS.
214                                        totalR  =       mCurrentRegLOD->position;
215                                       
216                                        for (j = 0; j < totalR; j++)
217                                        {
218                                                (*strip)[*mCurrentData] =       lod - 1;
219                                                --mCurrentData;
220                                        }
221                                       
222                                        --mCurrentRegLOD;
223                                       
224                                }                       
225                               
226                                //      Actualizar LOD.
227                                mCurrentLod     =       lod - 1;
228                        }
229                       
230                        ++mCurrentData;
231                        ++mCurrentRegLOD;
232                }
233
234        }       
235
236        // Copy to Ogre buffers including the degenerated triangles
237
238        for (i  =       0; i < GetStripCount(); i++)
239        {
240                start   =       mStrips[i].begin();
241               
242                mStrips[i].insert(start,mStrips[i][0]);
243                mStrips[i].push_back(mStrips[i][mStrips[i].size()-1]);
244        }
245
246
247        Ogre::HardwareIndexBufferSharedPtr      ibuf;
248        Ogre::IndexData *indexes;
249        Ogre::RenderOperation mRenderOp;
250
251        j=0;
252
253        for (int submesh=0; submesh < original_mesh->getNumSubMeshes(); submesh++)
254        {
255                k=0;
256                for (i  =       0; i < mStripsSubmesh[submesh]; i++)
257                        k+=mStrips[j+i].size();
258
259
260                original_mesh->getSubMesh(submesh)->_getRenderOperation(mRenderOp,0);
261
262                ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
263                        Ogre::HardwareIndexBuffer::IT_32BIT, // type of index
264                        k, // number of indexes
265                        Ogre::HardwareBuffer::HBU_DISCARDABLE , // usage
266                        false); // no shadow buffer
267                                       
268                mRenderOp.indexData->indexBuffer = ibuf;
269                mRenderOp.indexData->indexStart = 0;
270                mRenderOp.indexData->indexCount = k;
271
272                k=0;
273                unsigned long* pIdx = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
274
275                for (i  =       0; i < mStripsSubmesh[submesh]; i++)
276                {
277                        for (l=0;l<mStrips[j].size();l++)
278                        {
279                                pIdx[k++]=mStrips[j][l];
280                        }
281
282                        j++;
283                }
284
285               
286
287                ibuf->unlock();
288
289        }
290       
291
292        //Erase the degenerated triangles
293        for (i  =       0; i < GetStripCount(); i++)
294        {
295                start   =       mStrips[i].begin();
296
297                mStrips[i].erase(start);
298
299                mStrips[i].pop_back();
300        }
301       
302        return  return_value;
303}
304
305
306/*
307        Gets the maximum level of detail.
308*/
309Ogre::uint32 LodStripsLibrary::MaxLod()
310{
311        return  mMaxLod;
312}
313
314/*
315        Gets the minimum level of detail.
316*/
317Ogre::uint32 LodStripsLibrary::MinLod()
318{
319        return  mMinLod;
320}
321
322/// Returns the number of vertices of the highest LOD.
323Ogre::uint32    LodStripsLibrary::MaxVertices()
324{
325        Ogre::uint32    number_of_vertices;
326
327        number_of_vertices      =       mTotalVertices;
328
329        return  number_of_vertices;
330}
331
332/// Returns the number of vertices of the lowest LOD.
333Ogre::uint32    LodStripsLibrary::MinVertices()
334{
335        Ogre::uint32    number_of_vertices;
336
337        //      Total vertices less total lod.
338        number_of_vertices      =       mTotalVertices - (mMaxLod + 1);
339
340        return  number_of_vertices;
341}
342
343/// Returns the number of triangles of the highest LOD.
344Ogre::uint32    LodStripsLibrary::MaxFaces()
345{
346        Ogre::uint32    number_of_faces;
347
348        Ogre::uint32    current_lod;
349
350        current_lod     =       GoToLod(MaxLod());
351
352        //      Initialize number of faces count.
353        number_of_faces =       0;
354
355        //      For each strip.
356        for (int strip  =       0; strip < mTotalStrips; strip++)
357        {
358                number_of_faces +=      mStrips[strip].size() - 2;
359        }
360
361        GoToLod(current_lod);
362
363        return  number_of_faces;
364}
365
366/// Returns the number of triangles of the lowest LOD.
367Ogre::uint32    LodStripsLibrary::MinFaces()
368{
369        Ogre::uint32    current_lod;
370        Ogre::uint32    number_of_faces;
371
372        current_lod     =       GoToLod(MinLod());
373
374        //      Initialize number of faces count.
375        number_of_faces =       0;
376
377        //      For each strip.
378        for (int strip  =       0; strip < mTotalStrips; strip++)
379        {
380                number_of_faces +=      mStrips[strip].size() - 2;
381        }
382
383        GoToLod(current_lod);
384
385        return  number_of_faces;
386}
387
388/// Establishes the new LOD range.
389/// Only the LODs in that range are stored and used.
390void            LodStripsLibrary::TrimByLod(Ogre::uint32 minLod, Ogre::uint32 maxLod)
391{
392        mMinLod =       minLod;
393        mMaxLod =       maxLod;
394}
395
396Ogre::uint32    LodStripsLibrary::GetStripCount() const
397{
398        return  (Ogre::uint32)  mTotalStrips;
399}
400
401Ogre::uint32    LodStripsLibrary::GetIndexCountByStrip(Ogre::uint32 istrip) const
402{
403        return (Ogre::uint32)   mStrips[istrip].size();
404}
405
406//-----------------------------------------------------------------------------
407//      Private.
408//-----------------------------------------------------------------------------
409
410/*
411        Copy a STL vector to a C array.
412*/
413void LodStripsLibrary::CopyVectors2Arrays()
414{
415        unsigned int            i;
416        int                                     j;
417        SmallInt                        max;
418        SmallInt                        t;
419        SmallInt                        *data_array;
420        SmallIntVector          tira;
421        LODRegisterType         *changes_array;
422        LODRegisterVector       list_changes;
423
424        mTotalStrips            =       mFileStrips.size();
425        mVertex                         =       new SmallInt[mTotalVertices];
426        mStrips                         =       new SmallIntVector[mTotalStrips];
427        data_array                      =       new SmallInt[mData.size()];
428       
429        //Calcular el tamaño maximo de tira y el numero de caras total
430        max                                     =       0;
431        mTotalFaces     =       0;
432       
433        for (i = 0; i < mFileStrips.size(); i++)
434        {
435                t       =       mFileStrips[i].size();
436               
437                if (t>max)
438                {
439                        max     =       t;
440                }
441
442                mTotalFaces     +=      t - 2;
443        }
444
445        //Nueva version de ALLOCATE.
446        changes_array   =       new LODRegisterType[mFileChangesLOD.size()];
447       
448        //Rellenar vChanges
449        for (i = 0; i < mFileChangesLOD.size(); ++i)
450        {
451                changes_array[i]        =       mFileChangesLOD[i];
452        }
453
454        mCurrentRegLOD  =       changes_array;
455        mRegLODBegin    =       changes_array;
456       
457        //COPY----------------------------------
458        //Copiar las tiras
459        for (i = 0; i < mFileStrips.size(); i++)
460        {
461                for (j = 0; j < mFileStrips[i].size(); j++)
462                {
463                        //Rellenar el vVector
464                        mStrips[i].push_back(mFileStrips[i][j]);
465                }
466                                       
467        }
468
469        for (i = 0; i < mData.size(); i++)
470        {
471                data_array[i]   =       mData[i];
472        }
473       
474        mCurrentData    =       data_array;
475        mDataBegin      =       data_array;
476
477        //Meter los vertices en mVertex
478        for(i = 0; i < mFileVertices.size(); i++)
479        {
480                mVertex[i]      =       mFileVertices[i];
481        }
482
483        mFileVertices.clear();
484        mFileVertices.clear();
485        mFileChangesLOD.clear();
486        mFileStrips.clear();
487        mData.clear();
488
489       
490}
491
492//-----------------------------------------------------------------------------
493// LoadStripMesh
494//-----------------------------------------------------------------------------
495void LodStripsLibrary::LoadStripMesh(char *name, Ogre::Mesh *geomesh)
496{
497        FILE                                                                                                                    *fp;
498        SmallIntVector                                                                          strip_aux;
499        LODRegisterType                                                                         lod_register;
500        std::vector                     <LODRegisterType>       list_pos;
501        std::vector                     <unsigned int>          p_changes;
502        int                                                                                                                             value;
503        int                                                                                                                             v               =       0;
504        int                                                                                                                             t               =       0;
505        int                                                                                                                             c               =       -1;
506        char                                                                                                                    buff[80];
507        Ogre::SubMesh                                                                                                           *geoSubMesh;
508        int count=0;
509        int num_strips=0;
510
511        //      Open the LOD file.
512        if ((fp = fopen (name, "r")) == NULL)
513        {
514                //      Error in open.
515        }
516        else
517        {
518                mTotalChanges   =       0;
519               
520
521                while (!feof (fp))
522                {
523                        fgets (buff, 80, fp);
524                       
525                        if (*buff == 'v')
526                        {
527                                //VERTICES
528                                sscanf (buff+2,"%d",&value);
529                               
530                                mFileVertices.push_back(value);
531                                v++;
532                        }
533                        else if ( (*buff == 'c') || (*buff == 'd'))
534                        {
535                                if (*buff == 'c')
536                                {
537                                        // c indica que empieza un nuevo cambio
538                                        c++;
539                                }
540                                else
541                                {
542                                        unsigned        int     a;
543                                        unsigned        int     b;
544                                        unsigned        int     c;
545                                        unsigned        int     d;
546                                       
547                                        sscanf (buff+2,"%u %u %u %u\n",&a,&b,&c,&d);
548                                        lod_register.strip                                              =       a;
549                                        lod_register.position                                   =       b;
550                                        lod_register.vertexRepetition   =       c;
551                                        lod_register.edgeRepetition             =       d;
552                                       
553                                        mFileChangesLOD.push_back(lod_register);
554                                }
555                        }
556                        else if (*buff=='b')
557                        {
558                                sscanf(buff+2,"%u",&value);
559                                mData.push_back(value);
560                        }
561                        else if (*buff=='p')
562                        {
563                                sscanf (buff+2,"%u",&value);
564                                p_changes.push_back(value);
565                        }//Fin ElseIf
566
567                } // End WhileEOF
568               
569                fclose(fp);
570
571                mStripsSubmesh= new int [geomesh->getNumSubMeshes()];
572
573                //      For each one of the submeshes.
574                for (int submesh        =       0; submesh < geomesh->getNumSubMeshes(); submesh++)
575                {
576                        geoSubMesh      =       geomesh->getSubMesh(submesh);
577
578                        count=0;
579                        num_strips=0;
580
581                        Ogre::HardwareIndexBufferSharedPtr ibuf =       geoSubMesh->indexData->indexBuffer;
582
583                        if (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT)
584                        {
585                                unsigned int* pIndexes = static_cast<unsigned int*> (ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY) );
586
587                                //We must be carefull with the degenerated triangles
588                                while (count<(geoSubMesh->indexData->indexCount-1))
589                                {
590                                        // Insert an empty strip.
591                                        strip_aux.clear();
592                                        mFileStrips.push_back(strip_aux);
593
594                                        mFileStrips[t].push_back(pIndexes[count++]);
595
596                                        while ((count<(geoSubMesh->indexData->indexCount-1))&&(pIndexes[count]!=pIndexes[count+1]))
597                                        {
598                                                mFileStrips[t].push_back(pIndexes[count++]);
599                                        }
600
601                                        mFileStrips[t].push_back(pIndexes[count]);
602
603                                        //For the degenerated triangles
604                                        count+=3;
605
606                                        char linea[256];
607                                        sprintf(linea,"%d %d (%d) %d %d %d %d",pIndexes[count-2],pIndexes[count-1],pIndexes[count],pIndexes[count+1],pIndexes[count+2],pIndexes[count+3],pIndexes[count+4]);
608                                       
609                                        t++;
610                                        num_strips++;
611
612                                }
613
614                        }
615                        else
616                        {
617                                unsigned short* pIndexes = static_cast<unsigned short*> (ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY) );
618
619                                while (count<geoSubMesh->indexData->indexCount)
620                                {
621                                        // Insert an empty strip.
622                                        strip_aux.clear();
623                                        mFileStrips.push_back(strip_aux);
624
625                                        mFileStrips[t].push_back(pIndexes[count++]);
626
627                                        while ((count<(geoSubMesh->indexData->indexCount-1))&&(pIndexes[count]!=pIndexes[count+1]))
628                                        {
629                                                mFileStrips[t].push_back(pIndexes[count++]);
630                                        }
631
632                                        mFileStrips[t].push_back(pIndexes[count]);
633
634                                        //For the degenerated triangles
635                                        count+=3;
636
637                                        char linea[256];
638                                        sprintf(linea,"%d %d (%d) %d %d %d %d",pIndexes[count-2],pIndexes[count-1],pIndexes[count],pIndexes[count+1],pIndexes[count+2],pIndexes[count+3],pIndexes[count+4]);
639                                       
640                                        t++;
641                                        num_strips++;
642
643                                }
644                        }
645
646                        ibuf->unlock();
647
648                        mStripsSubmesh[submesh]=num_strips;
649                }
650               
651                //      Max / Min values for LOD.
652                mLods                                                                                   =       p_changes.size();
653                mMinLod                                                                         =       0;
654                mMaxLod                                                                         =       mLods;
655
656                //// CHAPUZA PROVISIONAL: EL ULTIMO ELEMENTO SE REPITE 2 VECES V.v
657                mPChanges                       =       new SmallInt[mLods];
658               
659                for (unsigned int i = 0; i < mLods; i++)
660                {
661                        mPChanges[i] = p_changes[i];
662                }
663
664                mTotalVertices                  =       mFileVertices.size();
665                mTotalStrips                            =       mFileStrips.size();
666                mTotalChanges                           =       mFileChangesLOD.size();
667
668                //Copy the data to the structure we will use
669                CopyVectors2Arrays();
670        }
671}
672
Note: See TracBrowser for help on using the repository browser.