CrystalSpace

Public API Reference

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__

Generated for Crystal Space 2.0 by doxygen 1.7.6.1