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 namespace CS 00032 { 00033 00038 template<typename T> 00039 class TriangleIndicesStream 00040 { 00041 protected: 00042 size_t stride; 00043 const uint8* index; 00044 const uint8* indexEnd; 00045 T old2, old1; 00046 bool stripFlag; 00047 int quadPart; 00048 00049 iRenderBuffer* buf; 00050 csRenderBufferComponentType compType; 00051 csRenderMeshType meshtype; 00052 00054 T GetNextIndex() 00055 { 00056 T r; 00057 switch (compType) 00058 { 00059 default: 00060 CS_ASSERT(false); 00061 case CS_BUFCOMP_BYTE: 00062 r = *(char*)index; 00063 break; 00064 case CS_BUFCOMP_UNSIGNED_BYTE: 00065 r = *(unsigned char*)index; 00066 break; 00067 case CS_BUFCOMP_SHORT: 00068 r = *(short*)index; 00069 break; 00070 case CS_BUFCOMP_UNSIGNED_SHORT: 00071 r = *(unsigned short*)index; 00072 break; 00073 case CS_BUFCOMP_INT: 00074 r = *(int*)index; 00075 break; 00076 case CS_BUFCOMP_UNSIGNED_INT: 00077 r = *(unsigned int*)index; 00078 break; 00079 case CS_BUFCOMP_FLOAT: 00080 r = uint (*(float*)index); 00081 break; 00082 case CS_BUFCOMP_DOUBLE: 00083 r = uint (*(double*)index); 00084 break; 00085 } 00086 index += stride; 00087 return r; 00088 } 00090 T GetIndex (size_t idx, const uint8* index) const 00091 { 00092 switch (compType) 00093 { 00094 default: 00095 CS_ASSERT(false); 00096 case CS_BUFCOMP_BYTE: 00097 return T (*(char*)(index+idx*stride)); 00098 case CS_BUFCOMP_UNSIGNED_BYTE: 00099 return T (*(unsigned char*)(index+idx*stride)); 00100 case CS_BUFCOMP_SHORT: 00101 return T (*(short*)(index+idx*stride)); 00102 case CS_BUFCOMP_UNSIGNED_SHORT: 00103 return T (*(unsigned short*)(index+idx*stride)); 00104 case CS_BUFCOMP_INT: 00105 return T (*(int*)(index+idx*stride)); 00106 case CS_BUFCOMP_UNSIGNED_INT: 00107 return T (*(unsigned int*)(index+idx*stride)); 00108 case CS_BUFCOMP_FLOAT: 00109 return T (*(float*)(index+idx*stride)); 00110 case CS_BUFCOMP_DOUBLE: 00111 return T (*(double*)(index+idx*stride)); 00112 } 00113 return 0; 00114 } 00115 public: 00121 TriangleIndicesStream () : old2(0), old1(0), buf (0) { } 00130 TriangleIndicesStream (iRenderBuffer* indices, 00131 csRenderMeshType meshtype, 00132 size_t indexStart = 0, 00133 size_t indexEnd = (size_t)~0) : old2(0), old1(0) 00134 { 00135 BeginTriangulate (indices, meshtype, indexStart, indexEnd); 00136 } 00137 ~TriangleIndicesStream() 00138 { 00139 if (buf != 0) buf->Release (); 00140 } 00141 00150 void BeginTriangulate (const uint8* indexStart, const uint8* indexEnd, 00151 size_t stride, csRenderBufferComponentType compType, 00152 csRenderMeshType meshtype) 00153 { 00154 this->index = indexStart; 00155 this->indexEnd = indexEnd; 00156 this->stride = stride; 00157 stripFlag = false; 00158 quadPart = 0; 00159 this->compType = compType; 00160 this->meshtype = meshtype; 00161 00162 switch (meshtype) 00163 { 00164 case CS_MESHTYPE_TRIANGLESTRIP: 00165 case CS_MESHTYPE_TRIANGLEFAN: 00166 { 00167 old2 = GetNextIndex(); 00168 old1 = GetNextIndex(); 00169 break; 00170 } 00171 default: 00172 ; 00173 } 00174 } 00175 00184 void BeginTriangulate (iRenderBuffer* indices, 00185 csRenderMeshType meshtype, 00186 size_t indexStart = 0, 00187 size_t indexEnd = (size_t)~0) 00188 { 00189 if (indexEnd == (size_t)~0) indexEnd = indices->GetElementCount(); 00190 00191 buf = indices; 00192 uint8* indexLock = (uint8*)buf->Lock (CS_BUF_LOCK_READ); 00193 00194 size_t stride = indices->GetElementDistance(); 00195 uint8* tri = indexLock + indexStart*stride; 00196 const uint8* triEnd = indexLock + indexEnd*stride; 00197 00198 BeginTriangulate (tri, triEnd, stride, indices->GetComponentType(), 00199 meshtype); 00200 } 00201 00203 bool HasNext() const 00204 { 00205 return (index < indexEnd); 00206 } 00207 CS_DEPRECATED_METHOD_MSG("Use HasNext() instead") 00208 bool HasNextTri() const { return HasNext(); } 00210 TriangleT<T> Next () 00211 { 00212 CS_ASSERT (index < indexEnd); 00213 TriangleT<T> t; 00214 switch (meshtype) 00215 { 00216 case CS_MESHTYPE_TRIANGLES: 00217 { 00218 t.a = GetIndex (0, index); 00219 t.b = GetIndex (1, index); 00220 t.c = GetIndex (2, index); 00221 index += 3*csRenderBufferComponentSizes[compType]; 00222 } 00223 break; 00224 case CS_MESHTYPE_TRIANGLESTRIP: 00225 { 00226 const T cur = GetNextIndex(); 00227 t.a = old1; 00228 t.b = old2; 00229 t.c = cur; 00230 if (stripFlag) 00231 old2 = cur; 00232 else 00233 old1 = cur; 00234 stripFlag = !stripFlag; 00235 } 00236 break; 00237 case CS_MESHTYPE_TRIANGLEFAN: 00238 { 00239 const T cur = GetNextIndex(); 00240 t.a = old2; 00241 t.b = old1; 00242 t.c = cur; 00243 old1 = cur; 00244 } 00245 break; 00246 case CS_MESHTYPE_QUADS: 00247 { 00248 if (quadPart == 0) 00249 { 00250 t.a = GetIndex (0, index); 00251 t.b = GetIndex (1, index); 00252 t.c = GetIndex (2, index); 00253 } 00254 else 00255 { 00256 t.a = GetIndex (0, index); 00257 t.b = GetIndex (2, index); 00258 t.c = GetIndex (3, index); 00259 index += 4*csRenderBufferComponentSizes[compType]; 00260 } 00261 quadPart ^= 1; 00262 } 00263 break; 00264 default: 00265 CS_ASSERT_MSG("Unsupported mesh type", false); 00266 ; 00267 } 00268 return t; 00269 } 00270 CS_DEPRECATED_METHOD_MSG("Use Next() instead") 00271 bool NextTriangle (T& a, T& b, T& c) 00272 { 00273 TriangleT<T> tri = Next (); 00274 a = tri.a; b = tri.b; c = tri.c; 00275 return true; 00276 } 00277 00283 size_t GetRemainingComponents() const 00284 { 00285 size_t size; 00286 switch (compType) 00287 { 00288 default: 00289 CS_ASSERT(false); 00290 case CS_BUFCOMP_BYTE: size = sizeof (char); break; 00291 case CS_BUFCOMP_UNSIGNED_BYTE: size = sizeof (unsigned char); break; 00292 case CS_BUFCOMP_SHORT: size = sizeof (short); break; 00293 case CS_BUFCOMP_UNSIGNED_SHORT: size = sizeof (unsigned short); break; 00294 case CS_BUFCOMP_INT: size = sizeof (int); break; 00295 case CS_BUFCOMP_UNSIGNED_INT: size = sizeof (unsigned int); break; 00296 case CS_BUFCOMP_FLOAT: size = sizeof (float); break; 00297 case CS_BUFCOMP_DOUBLE: size = sizeof (double); break; 00298 } 00299 return (indexEnd - index) / size; 00300 } 00301 }; 00302 00310 template<typename T> 00311 class TriangleIndicesStreamRandom : public TriangleIndicesStream<T> 00312 { 00313 protected: 00314 const uint8* indexStart; 00315 size_t triangleNum; 00316 const uint8* streamIndex; 00317 size_t streamTriangleNum; 00318 00319 // Update internal stream position from TriangleIndicesStream position 00320 void SwitchToInternalStreaming () 00321 { 00322 if (streamIndex != 0) return; 00323 streamIndex = this->index; 00324 streamTriangleNum = triangleNum; 00325 } 00326 /* Restore TriangleIndicesStream with the position set before using 00327 * "internal" streaming */ 00328 void SwitchToExternalStreaming () 00329 { 00330 if (streamIndex == 0) return; 00331 this->index = streamIndex; 00332 triangleNum = streamTriangleNum; 00333 streamIndex = 0; 00334 } 00335 00336 template<typename T2> 00337 void GetTriangleFastDefault (TriangleT<T2>& tri, size_t index) const 00338 { 00339 tri.a = T2 (this->GetIndex (index*3+0, indexStart)); 00340 tri.b = T2 (this->GetIndex (index*3+1, indexStart)); 00341 tri.c = T2 (this->GetIndex (index*3+2, indexStart)); 00342 } 00343 void GetTriangleFast (TriangleT<char>& tri, size_t index) const 00344 { 00345 if (this->compType == CS_BUFCOMP_BYTE) 00346 memcpy (&tri, indexStart + (index*3), sizeof (char)*3); 00347 else 00348 GetTriangleFastDefault (tri, index); 00349 } 00350 void GetTriangleFast (TriangleT<unsigned char>& tri, size_t index) const 00351 { 00352 if (this->compType == CS_BUFCOMP_UNSIGNED_BYTE) 00353 memcpy (&tri, indexStart + (index*3), sizeof (unsigned char)*3); 00354 else 00355 GetTriangleFastDefault (tri, index); 00356 } 00357 void GetTriangleFast (TriangleT<short>& tri, size_t index) const 00358 { 00359 if (this->compType == CS_BUFCOMP_SHORT) 00360 memcpy (&tri, indexStart + (index*3), sizeof (short)*3); 00361 else 00362 GetTriangleFastDefault (tri, index); 00363 } 00364 void GetTriangleFast (TriangleT<unsigned short>& tri, size_t index) const 00365 { 00366 if (this->compType == CS_BUFCOMP_UNSIGNED_SHORT) 00367 memcpy (&tri, indexStart + (index*3), sizeof (unsigned short)*3); 00368 else 00369 GetTriangleFastDefault (tri, index); 00370 } 00371 void GetTriangleFast (TriangleT<int>& tri, size_t index) const 00372 { 00373 if (this->compType == CS_BUFCOMP_INT) 00374 memcpy (&tri, indexStart + (index*3), sizeof (int)*3); 00375 else 00376 GetTriangleFastDefault (tri, index); 00377 } 00378 void GetTriangleFast (TriangleT<unsigned int>& tri, size_t index) const 00379 { 00380 if (this->compType == CS_BUFCOMP_UNSIGNED_INT) 00381 memcpy (&tri, indexStart + (index*3), sizeof (unsigned int)*3); 00382 else 00383 GetTriangleFastDefault (tri, index); 00384 } 00385 void GetTriangleFast (TriangleT<float>& tri, size_t index) const 00386 { 00387 if (this->compType == CS_BUFCOMP_FLOAT) 00388 memcpy (&tri, indexStart + (index*3), sizeof (float)*3); 00389 else 00390 GetTriangleFastDefault (tri, index); 00391 } 00392 void GetTriangleFast (TriangleT<double>& tri, size_t index) const 00393 { 00394 if (this->compType == CS_BUFCOMP_DOUBLE) 00395 memcpy (&tri, indexStart + (index*3), sizeof (double)*3); 00396 else 00397 GetTriangleFastDefault (tri, index); 00398 } 00399 TriangleT<T> InternalNext () 00400 { 00401 SwitchToInternalStreaming (); 00402 TriangleT<T> tri (TriangleIndicesStream<T>::Next ()); 00403 ++triangleNum; 00404 return tri; 00405 } 00406 public: 00412 TriangleIndicesStreamRandom () : TriangleIndicesStream<T> () { } 00421 TriangleIndicesStreamRandom (iRenderBuffer* indices, 00422 csRenderMeshType meshtype, size_t indexStart = 0, 00423 size_t indexEnd = (size_t)~0) : 00424 TriangleIndicesStream<T> (indices, meshtype, indexStart, indexEnd) 00425 { 00426 streamIndex = this->indexStart = this->index; 00427 streamTriangleNum = triangleNum = 0; 00428 } 00429 ~TriangleIndicesStreamRandom() 00430 { 00431 } 00432 00441 void BeginTriangulate (const uint8* indexStart, const uint8* indexEnd, 00442 size_t stride, csRenderBufferComponentType compType, 00443 csRenderMeshType meshtype) 00444 { 00445 TriangleIndicesStream<T>::BeginTriangulate (indexStart, indexEnd, stride, 00446 compType, meshtype); 00447 streamIndex = this->indexStart = this->index; 00448 streamTriangleNum = triangleNum = 0; 00449 } 00450 00459 void BeginTriangulate (iRenderBuffer* indices, 00460 csRenderMeshType meshtype, 00461 size_t indexStart = 0, 00462 size_t indexEnd = (size_t)~0) 00463 { 00464 TriangleIndicesStream<T>::BeginTriangulate (indices, meshtype, 00465 indexStart, indexEnd); 00466 streamIndex = this->indexStart = this->index; 00467 streamTriangleNum = triangleNum = 0; 00468 } 00469 00471 void Reset() 00472 { 00473 this->index = indexStart; 00474 triangleNum = 0; 00475 streamIndex = 0; 00476 } 00477 00479 bool HasNext() const 00480 { 00481 SwitchToExternalStreaming (); 00482 return TriangleIndicesStream<T>::HasNext (); 00483 } 00485 TriangleT<T> Next () 00486 { 00487 SwitchToExternalStreaming (); 00488 return TriangleIndicesStream<T>::Next (); 00489 } 00490 00492 TriangleT<T> operator[] (size_t index) 00493 { 00494 if (this->meshtype == CS_MESHTYPE_TRIANGLES) 00495 { 00496 // Simple triangles: direct access 00497 TriangleT<T> tri; 00498 GetTriangleFast (tri, index); 00499 return tri; 00500 } 00501 else 00502 { 00503 // Strips, fans...: need to iterate over all to find a specific tri 00504 if (index < triangleNum) Reset(); 00505 while (index > triangleNum) InternalNext (); 00506 return InternalNext (); 00507 } 00508 } 00509 }; 00510 } // namespace CS 00511 00512 #endif // __CS_TRIANGLESTREAM_H__
Generated for Crystal Space 1.4.1 by doxygen 1.7.1