csgfx/trianglestream.h Source File (Crystal Space 2.0 Public API Reference)

| ## Public API Reference

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

csgfx/trianglestream.h
Go to the documentation of this file.

    00001 /*
    00002     Copyright (C) 2006 by Jorrit Tyberghein
    00003               (C) 2006 by Frank Richter
    00004
    00005     This library is free software; you can redistribute it and/or
    00006     modify it under the terms of the GNU Library General Public
    00007     License as published by the Free Software Foundation; either
    00008     version 2 of the License, or (at your option) any later version.
    00009
    00010     This library is distributed in the hope that it will be useful,
    00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013     Library General Public License for more details.
    00014
    00015     You should have received a copy of the GNU Library General Public
    00016     License along with this library; if not, write to the Free
    00017     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    00018 */
    00019
    00020 #ifndef __CS_TRIANGLESTREAM_H__
    00021 #define __CS_TRIANGLESTREAM_H__
    00022
    00027 #include "csgeom/tri.h"
    00028 #include "ivideo/graph3d.h"
    00029 #include "ivideo/rndbuf.h"
    00030
    00031 #ifdef CS_COMPILER_MSVC
    00032 #pragma warning(push)
    00033 /* Apparently, whatever return type MSVC sees first for GetIndex() below is
    00034    taken as "the" return type, at least when it comes to return value precision
    00035    checking: sometimes there is a lot of warning spam that assigning size_t to
    00036    <something else> may lose precision. */
    00037 #pragma warning(disable:4267)
    00038 #endif
    00039
    00040 namespace CS
    00041 {
    00042
    00047   template<typename T>
    00048   class TriangleIndicesStream
    00049   {
    00050   protected:
    00051     size_t stride;
    00052     const uint8* index;
    00053     const uint8* indexEnd;
    00054     T old2, old1;
    00055     bool stripFlag;
    00056     int quadPart;
    00057
    00058     iRenderBuffer* buf;
    00059     csRenderBufferComponentType compType;
    00060     csRenderMeshType meshtype;
    00061
    00063     T GetNextIndex()
    00064     {
    00065       T r;
    00066       switch (compType)
    00067       {
    00068         default:
    00069           CS_ASSERT(false);
    00070         case CS_BUFCOMP_BYTE:
    00071           r = *(char*)index;
    00072           break;
    00073         case CS_BUFCOMP_UNSIGNED_BYTE:
    00074           r = *(unsigned char*)index;
    00075           break;
    00076         case CS_BUFCOMP_SHORT:
    00077           r = *(short*)index;
    00078           break;
    00079         case CS_BUFCOMP_UNSIGNED_SHORT:
    00080           r = *(unsigned short*)index;
    00081           break;
    00082         case CS_BUFCOMP_INT:
    00083           r = *(int*)index;
    00084           break;
    00085         case CS_BUFCOMP_UNSIGNED_INT:
    00086           r = *(unsigned int*)index;
    00087           break;
    00088         case CS_BUFCOMP_FLOAT:
    00089           r = uint (*(float*)index);
    00090           break;
    00091         case CS_BUFCOMP_DOUBLE:
    00092           r = uint (*(double*)index);
    00093           break;
    00094       }
    00095       index += stride;
    00096       return r;
    00097     }
    00099     T GetIndex (size_t idx, const uint8* index) const
    00100     {
    00101       switch (compType)
    00102       {
    00103         default:
    00104           CS_ASSERT(false);
    00105         case CS_BUFCOMP_BYTE:
    00106           return T (*(char*)(index+idx*stride));
    00107         case CS_BUFCOMP_UNSIGNED_BYTE:
    00108           return T (*(unsigned char*)(index+idx*stride));
    00109         case CS_BUFCOMP_SHORT:
    00110           return T (*(short*)(index+idx*stride));
    00111         case CS_BUFCOMP_UNSIGNED_SHORT:
    00112           return T (*(unsigned short*)(index+idx*stride));
    00113         case CS_BUFCOMP_INT:
    00114           return T (*(int*)(index+idx*stride));
    00115         case CS_BUFCOMP_UNSIGNED_INT:
    00116           return T (*(unsigned int*)(index+idx*stride));
    00117         case CS_BUFCOMP_FLOAT:
    00118           return T (*(float*)(index+idx*stride));
    00119         case CS_BUFCOMP_DOUBLE:
    00120           return T (*(double*)(index+idx*stride));
    00121       }
    00122       return 0;
    00123     }
    00124   public:
    00130     TriangleIndicesStream () : old2(0), old1(0), buf (0) { }
    00139     TriangleIndicesStream (iRenderBuffer* indices,
    00140                            csRenderMeshType meshtype,
    00141                            size_t indexStart = 0,
    00142                            size_t indexEnd = (size_t)~0) : old2(0), old1(0)
    00143     {
    00144       BeginTriangulate (indices, meshtype, indexStart, indexEnd);
    00145     }
    00146     ~TriangleIndicesStream()
    00147     {
    00148       if (buf != 0) buf->Release ();
    00149     }
    00150
    00159     void BeginTriangulate (const uint8* indexStart, const uint8* indexEnd,
    00160       size_t stride, csRenderBufferComponentType compType,
    00161       csRenderMeshType meshtype)
    00162     {
    00163       this->index = indexStart;
    00164       this->indexEnd = indexEnd;
    00165       this->stride = stride;
    00166       stripFlag = false;
    00167       quadPart = 0;
    00168       this->compType = compType;
    00169       this->meshtype = meshtype;
    00170
    00171       switch (meshtype)
    00172       {
    00173       case CS_MESHTYPE_TRIANGLESTRIP:
    00174       case CS_MESHTYPE_TRIANGLEFAN:
    00175         {
    00176           old2 = GetNextIndex();
    00177           old1 = GetNextIndex();
    00178           break;
    00179         }
    00180       default:
    00181         ;
    00182       }
    00183     }
    00184
    00193     void BeginTriangulate (iRenderBuffer* indices,
    00194                             csRenderMeshType meshtype,
    00195                             size_t indexStart = 0,
    00196                             size_t indexEnd = (size_t)~0)
    00197     {
    00198       if (indexEnd == (size_t)~0) indexEnd = indices->GetElementCount();
    00199
    00200       buf = indices;
    00201       uint8* indexLock = (uint8*)buf->Lock (CS_BUF_LOCK_READ);
    00202
    00203       size_t stride = indices->GetElementDistance();
    00204       uint8* tri = indexLock + indexStart*stride;
    00205       const uint8* triEnd = indexLock + indexEnd*stride;
    00206
    00207       BeginTriangulate (tri, triEnd, stride, indices->GetComponentType(),
    00208         meshtype);
    00209     }
    00210
    00212     bool HasNext() const
    00213     {
    00214       return (index < indexEnd);
    00215     }
    00216     CS_DEPRECATED_METHOD_MSG("Use HasNext() instead")
    00217     bool HasNextTri() const { return HasNext(); }
    00219     TriangleT<T> Next ()
    00220     {
    00221       CS_ASSERT (index < indexEnd);
    00222       TriangleT<T> t;
    00223       switch (meshtype)
    00224       {
    00225       case CS_MESHTYPE_TRIANGLES:
    00226         {
    00227           t.a = GetIndex (0, index);
    00228           t.b = GetIndex (1, index);
    00229           t.c = GetIndex (2, index);
    00230           index += 3*csRenderBufferComponentSizes[compType];
    00231         }
    00232         break;
    00233       case CS_MESHTYPE_TRIANGLESTRIP:
    00234         {
    00235           const T cur = GetNextIndex();
    00236           t.a = old1;
    00237           t.b = old2;
    00238           t.c = cur;
    00239           if (stripFlag)
    00240             old2 = cur;
    00241           else
    00242             old1 = cur;
    00243           stripFlag = !stripFlag;
    00244         }
    00245         break;
    00246       case CS_MESHTYPE_TRIANGLEFAN:
    00247         {
    00248           const T cur = GetNextIndex();
    00249           t.a = old2;
    00250           t.b = old1;
    00251           t.c = cur;
    00252           old1 = cur;
    00253         }
    00254         break;
    00255       case CS_MESHTYPE_QUADS:
    00256         {
    00257           if (quadPart == 0)
    00258           {
    00259             t.a = GetIndex (0, index);
    00260             t.b = GetIndex (1, index);
    00261             t.c = GetIndex (2, index);
    00262           }
    00263           else
    00264           {
    00265             t.a = GetIndex (0, index);
    00266             t.b = GetIndex (2, index);
    00267             t.c = GetIndex (3, index);
    00268             index += 4*csRenderBufferComponentSizes[compType];
    00269           }
    00270           quadPart ^= 1;
    00271         }
    00272         break;
    00273       default:
    00274         CS_ASSERT_MSG("Unsupported mesh type", false);
    00275         ;
    00276       }
    00277       return t;
    00278     }
    00279     CS_DEPRECATED_METHOD_MSG("Use Next() instead")
    00280     bool NextTriangle (T& a, T& b, T& c)
    00281     {
    00282       TriangleT<T> tri = Next ();
    00283       a = tri.a; b = tri.b; c = tri.c;
    00284       return true;
    00285     }
    00286
    00292     size_t GetRemainingComponents() const
    00293     {
    00294       size_t size;
    00295       switch (compType)
    00296       {
    00297         default:
    00298           CS_ASSERT(false);
    00299         case CS_BUFCOMP_BYTE:           size = sizeof (char); break;
    00300         case CS_BUFCOMP_UNSIGNED_BYTE:  size = sizeof (unsigned char); break;
    00301         case CS_BUFCOMP_SHORT:          size = sizeof (short); break;
    00302         case CS_BUFCOMP_UNSIGNED_SHORT: size = sizeof (unsigned short); break;
    00303         case CS_BUFCOMP_INT:            size = sizeof (int); break;
    00304         case CS_BUFCOMP_UNSIGNED_INT:   size = sizeof (unsigned int); break;
    00305         case CS_BUFCOMP_FLOAT:          size = sizeof (float); break;
    00306         case CS_BUFCOMP_DOUBLE:         size = sizeof (double); break;
    00307       }
    00308       return (indexEnd - index) / size;
    00309     }
    00310   };
    00311
    00319   template<typename T>
    00320   class TriangleIndicesStreamRandom : public TriangleIndicesStream<T>
    00321   {
    00322   protected:
    00323     const uint8* indexStart;
    00324     size_t triangleNum;
    00325     const uint8* streamIndex;
    00326     size_t streamTriangleNum;
    00327
    00328     // Update internal stream position from TriangleIndicesStream position
    00329     void SwitchToInternalStreaming ()
    00330     {
    00331       if (streamIndex != 0) return;
    00332       streamIndex = this->index;
    00333       streamTriangleNum = triangleNum;
    00334     }
    00335     /* Restore TriangleIndicesStream with the position set before using
    00336      * "internal" streaming */
    00337     void SwitchToExternalStreaming ()
    00338     {
    00339       if (streamIndex == 0) return;
    00340       this->index = streamIndex;
    00341       triangleNum = streamTriangleNum;
    00342       streamIndex = 0;
    00343     }
    00344
    00345     template<typename T2>
    00346     void GetTriangleFastDefault (TriangleT<T2>& tri, size_t index) const
    00347     {
    00348       tri.a = T2 (this->GetIndex (index*3+0, indexStart));
    00349       tri.b = T2 (this->GetIndex (index*3+1, indexStart));
    00350       tri.c = T2 (this->GetIndex (index*3+2, indexStart));
    00351     }
    00352     void GetTriangleFast (TriangleT<char>& tri, size_t index) const
    00353     {
    00354       if (this->compType == CS_BUFCOMP_BYTE)
    00355         memcpy (&tri, indexStart + (index*3), sizeof (char)*3);
    00356       else
    00357         GetTriangleFastDefault (tri, index);
    00358     }
    00359     void GetTriangleFast (TriangleT<unsigned char>& tri, size_t index) const
    00360     {
    00361       if (this->compType == CS_BUFCOMP_UNSIGNED_BYTE)
    00362         memcpy (&tri, indexStart + (index*3), sizeof (unsigned char)*3);
    00363       else
    00364         GetTriangleFastDefault (tri, index);
    00365     }
    00366     void GetTriangleFast (TriangleT<short>& tri, size_t index) const
    00367     {
    00368       if (this->compType == CS_BUFCOMP_SHORT)
    00369         memcpy (&tri, indexStart + (index*3), sizeof (short)*3);
    00370       else
    00371         GetTriangleFastDefault (tri, index);
    00372     }
    00373     void GetTriangleFast (TriangleT<unsigned short>& tri, size_t index) const
    00374     {
    00375       if (this->compType == CS_BUFCOMP_UNSIGNED_SHORT)
    00376         memcpy (&tri, indexStart + (index*3), sizeof (unsigned short)*3);
    00377       else
    00378         GetTriangleFastDefault (tri, index);
    00379     }
    00380     void GetTriangleFast (TriangleT<int>& tri, size_t index) const
    00381     {
    00382       if (this->compType == CS_BUFCOMP_INT)
    00383         memcpy (&tri, indexStart + (index*3), sizeof (int)*3);
    00384       else
    00385         GetTriangleFastDefault (tri, index);
    00386     }
    00387     void GetTriangleFast (TriangleT<unsigned int>& tri, size_t index) const
    00388     {
    00389       if (this->compType == CS_BUFCOMP_UNSIGNED_INT)
    00390         memcpy (&tri, indexStart + (index*3), sizeof (unsigned int)*3);
    00391       else
    00392         GetTriangleFastDefault (tri, index);
    00393     }
    00394     void GetTriangleFast (TriangleT<float>& tri, size_t index) const
    00395     {
    00396       if (this->compType == CS_BUFCOMP_FLOAT)
    00397         memcpy (&tri, indexStart + (index*3), sizeof (float)*3);
    00398       else
    00399         GetTriangleFastDefault (tri, index);
    00400     }
    00401     void GetTriangleFast (TriangleT<double>& tri, size_t index) const
    00402     {
    00403       if (this->compType == CS_BUFCOMP_DOUBLE)
    00404         memcpy (&tri, indexStart + (index*3), sizeof (double)*3);
    00405       else
    00406         GetTriangleFastDefault (tri, index);
    00407     }
    00408     TriangleT<T> InternalNext ()
    00409     {
    00410       SwitchToInternalStreaming ();
    00411       TriangleT<T> tri (TriangleIndicesStream<T>::Next ());
    00412       ++triangleNum;
    00413       return tri;
    00414     }
    00415 public:
    00421     TriangleIndicesStreamRandom () : TriangleIndicesStream<T> () { }
    00430     TriangleIndicesStreamRandom (iRenderBuffer* indices,
    00431       csRenderMeshType meshtype, size_t indexStart = 0,
    00432       size_t indexEnd = (size_t)~0) :
    00433       TriangleIndicesStream<T> (indices, meshtype, indexStart, indexEnd)
    00434     {
    00435       streamIndex = this->indexStart = this->index;
    00436       streamTriangleNum = triangleNum = 0;
    00437     }
    00438     ~TriangleIndicesStreamRandom()
    00439     {
    00440     }
    00441
    00450     void BeginTriangulate (const uint8* indexStart, const uint8* indexEnd,
    00451       size_t stride, csRenderBufferComponentType compType,
    00452       csRenderMeshType meshtype)
    00453     {
    00454       TriangleIndicesStream<T>::BeginTriangulate (indexStart, indexEnd, stride,
    00455         compType, meshtype);
    00456       streamIndex = this->indexStart = this->index;
    00457       streamTriangleNum = triangleNum = 0;
    00458     }
    00459
    00468     void BeginTriangulate (iRenderBuffer* indices,
    00469                             csRenderMeshType meshtype,
    00470                             size_t indexStart = 0,
    00471                             size_t indexEnd = (size_t)~0)
    00472     {
    00473       TriangleIndicesStream<T>::BeginTriangulate (indices, meshtype,
    00474         indexStart, indexEnd);
    00475       streamIndex = this->indexStart = this->index;
    00476       streamTriangleNum = triangleNum = 0;
    00477     }
    00478
    00480     void Reset()
    00481     {
    00482       this->index = indexStart;
    00483       triangleNum = 0;
    00484       streamIndex = 0;
    00485     }
    00486
    00488     bool HasNext() const
    00489     {
    00490       SwitchToExternalStreaming ();
    00491       return TriangleIndicesStream<T>::HasNext ();
    00492     }
    00494     TriangleT<T> Next ()
    00495     {
    00496       SwitchToExternalStreaming ();
    00497       return TriangleIndicesStream<T>::Next ();
    00498     }
    00499
    00501     TriangleT<T> operator[] (size_t index)
    00502     {
    00503       if (this->meshtype == CS_MESHTYPE_TRIANGLES)
    00504       {
    00505         // Simple triangles: direct access
    00506         TriangleT<T> tri;
    00507         GetTriangleFast (tri, index);
    00508         return tri;
    00509       }
    00510       else
    00511       {
    00512         // Strips, fans...: need to iterate over all to find a specific tri
    00513         if (index < triangleNum) Reset();
    00514         while (index > triangleNum) InternalNext ();
    00515         return InternalNext ();
    00516       }
    00517     }
    00518   };
    00519 } // namespace CS
    00520
    00521 #ifdef CS_COMPILER_MSVC
    00522 #pragma warning(pop)
    00523 #endif
    00524
    00525 #endif // __CS_TRIANGLESTREAM_H__