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.6.1