00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00034
00035
00036
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
00329 void SwitchToInternalStreaming ()
00330 {
00331 if (streamIndex != 0) return;
00332 streamIndex = this->index;
00333 streamTriangleNum = triangleNum;
00334 }
00335
00336
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
00506 TriangleT<T> tri;
00507 GetTriangleFast (tri, index);
00508 return tri;
00509 }
00510 else
00511 {
00512
00513 if (index < triangleNum) Reset();
00514 while (index > triangleNum) InternalNext ();
00515 return InternalNext ();
00516 }
00517 }
00518 };
00519 }
00520
00521 #ifdef CS_COMPILER_MSVC
00522 #pragma warning(pop)
00523 #endif
00524
00525 #endif // __CS_TRIANGLESTREAM_H__