IParticleChannelTrueFalseIterator.h

Go to the documentation of this file.
00001 /**********************************************************************
00002  *<
00003     FILE: IParticleChannelTrueFalseIterator.h
00004 
00005     DESCRIPTION: Channel-generic interface for boolean type particle channels.
00006                 The interface is used for fast iteration through the subset of
00007                 true (or false) values. 
00008 
00009     CREATED BY: Oleg Bayborodin
00010 
00011     HISTORY:    created 2007-09-05
00012 
00013  *> Copyright (c) 2007 Orbaz Technologies, Inc. All Rights Reserved.
00014  **********************************************************************/
00015 
00016 #pragma once
00017 
00018 #include "IParticleContainer.h"
00019 #include "..\ifnpub.h"
00020 #include "..\bitarray.h"
00021 // forward declarations
00022 class OrbazTrueBlock;
00023 
00024 // generic particle channel "group selection"
00025 // interface ID
00026 #define PARTICLECHANNELTRUEFALSEITERATOR_INTERFACE Interface_ID(0x91cd191c, 0x1eb34500)
00027 #define GetParticleChannelTrueFalseIteratorInterface(obj) ((IParticleChannelTrueFalseIterator*)obj->GetInterface(PARTICLECHANNELTRUEFALSEITERATOR_INTERFACE))
00028 
00029 
00030 class IParticleChannelTrueFalseIterator : public FPMixinInterface
00031 {
00032 public:
00033 
00034     // resets iterator to first true value of the channel; returns particle index
00035     // if unable to find a true value then returns number of particles in the channel (end index)
00036     virtual int GetFirstTrue(void) = 0;
00037     // for multi-threaded usage
00038     virtual int GetFirstTrue(int& localIndex) = 0;
00039 
00040     // finds the next true value; returns particle index
00041     // if unable to find the next true value then returns number of particles in the channel (end index)
00042     virtual int GetNextTrue(void) = 0;
00043     // for multi-threaded usage
00044     virtual int GetNextTrue(int& localIndex) const = 0;
00045 
00046     // updates the table of true values and returns number of true indices
00047     virtual int GetTrueCount(void) = 0;
00048     // returns index of the i-th true value
00049     virtual int GetTrueIndex(int i) const = 0;
00050 
00051     // update the table of blocks of true values and returns number of trueBlocks
00052     virtual int GetTrueBlockCount(void) = 0;
00053     // returns TrueBlock with given index
00054     virtual const OrbazTrueBlock& GetTrueBlock(int i) const = 0;
00055 
00056     FPInterfaceDesc* GetDesc() { return GetDescByID(PARTICLECHANNELTRUEFALSEITERATOR_INTERFACE); }
00057 };
00058 
00059 class OrbazTrueEnumerator : public BitArrayCallback
00060 {
00061 public:
00062     OrbazTrueEnumerator(int*& iterIndices)
00063         : m_iterIndices(iterIndices)
00064         , m_index(0)
00065     {
00066     }
00067 
00068     void proc(int n)
00069     {
00070         m_iterIndices[m_index++] = n;
00071     }
00072     OrbazTrueEnumerator& operator=(const OrbazTrueEnumerator& rhs)
00073     {
00074         if (this != & rhs)
00075         {
00076             m_iterIndices = rhs.m_iterIndices;
00077             m_index       = rhs.m_index;
00078         }
00079         return *this;
00080     }
00081 private:
00082     int*&       m_iterIndices;
00083     int         m_index;
00084 };
00085 
00086 class OrbazTrueBlock : public MaxHeapOperators
00087 {
00088 public: 
00089     OrbazTrueBlock()
00090         :   m_majorIndex(0)
00091         ,   m_blockIndices(0)
00092     {
00093     }
00094     OrbazTrueBlock(const OrbazTrueBlock& block)
00095         :   m_majorIndex(block.m_majorIndex)
00096         ,   m_blockIndices(block.m_blockIndices)
00097     {
00098     }
00099     OrbazTrueBlock(int majorIndex, DWORD32 blockIndices)
00100         :   m_majorIndex(majorIndex)
00101         ,   m_blockIndices(blockIndices)
00102     {
00103     }
00104 
00105     inline int GetMajorIndex(void) const { return m_majorIndex; }
00106     inline void SetMajorIndex(int index) { m_majorIndex = index; }
00107     void AddBlockIndex(int index) { m_blockIndices |= (1<<(index&kBitsPerDWORDMask)); }
00108 
00109     // returns number of bits set in the TrueBlock
00110     int NumberSet(void) const
00111     {
00112         static NumberBitsSetInUChar nbc;
00113         int numSet = 0;
00114         uchar*  miniBlocks = (uchar*)(&m_blockIndices);
00115         for(int i=0; i<4; ++i)
00116             numSet += nbc.getNumBitsSet(miniBlocks[i]);
00117         return numSet;
00118     }
00119 
00120     // returns number of trueBlocks allocated and set
00121     static int SetAllTrueBlocks(int particleCount, OrbazTrueBlock*& trueBlocks)
00122     {
00123         if (trueBlocks != NULL)
00124         {
00125             delete [] trueBlocks;
00126             trueBlocks = NULL;
00127         }
00128 
00129         int numTrueBlocks = particleCount>>5;
00130         bool incompleteEndBlock = (particleCount%kBitsPerDWORD != 0);
00131         int numCompleteBlocks = numTrueBlocks;
00132         if (incompleteEndBlock)
00133             ++numTrueBlocks;
00134         trueBlocks = new OrbazTrueBlock[numTrueBlocks];
00135         int i=0;
00136         for(; i<numCompleteBlocks; ++i)
00137             trueBlocks[i] = OrbazTrueBlock(i<<5, 0xFFFFFFFF);
00138         if (incompleteEndBlock)
00139             for(int j=i<<5; j<particleCount; ++j)
00140                 trueBlocks[i].AddBlockIndex(j);
00141         return numTrueBlocks;
00142     }
00143 
00144     static int GetMaxNumTrueBlocks(int particleCount)
00145     {
00146         int numTrueBlocks = particleCount >> 5;
00147         if (particleCount % kBitsPerDWORD != 0)
00148             ++numTrueBlocks;
00149         return numTrueBlocks;
00150     }
00151 
00152     static int OptimizeMemoryUsage(int numBlocksSet, int numBlocksAllocated, OrbazTrueBlock*& trueBlocks)
00153     {
00154         if (numBlocksSet != numBlocksAllocated)
00155         {
00156             OrbazTrueBlock* temp = new OrbazTrueBlock[numBlocksSet];
00157             memcpy(temp, trueBlocks, sizeof(OrbazTrueBlock)*numBlocksSet);
00158             delete [] trueBlocks;
00159             trueBlocks = temp;
00160         }
00161         return numBlocksSet;
00162     }
00163 
00164 protected:
00165     int     m_majorIndex;
00166     DWORD32 m_blockIndices;
00167 
00168 private:
00169     static const int kBitsPerDWORDMask = 31;
00170     static const int kBitsPerDWORD = 32;
00171 
00172     class NumberBitsSetInUChar : public MaxHeapOperators
00173     {
00174     public:
00175         NumberBitsSetInUChar()
00176         {
00177             m_numBits[0] = 0;
00178             for(int i=0, j=1, index=1; i<8; ++i, j<<1)
00179             {
00180                 int lowIndex = index-j;
00181                 for(int k=0; k<j; ++k)
00182                 {
00183                     m_numBits[index++] = m_numBits[lowIndex++] + 1;
00184                 }
00185             }
00186         }
00187 
00188         inline uchar getNumBitsSet(uchar n)
00189         {
00190             return m_numBits[n];
00191         }
00192 
00193     private:
00194         uchar m_numBits[256];
00195     };
00196 };
00197 
00198 class OrbazTrueBlockIterator : public OrbazTrueBlock
00199 {
00200 public:
00201     OrbazTrueBlockIterator(const OrbazTrueBlock& block)
00202         :   OrbazTrueBlock(block)
00203         ,   m_iter(0)
00204         ,   m_mask(1)
00205     {
00206     }
00207 
00208     // finds the next true value; if used for the first time after constructor finds first true value of the block;
00209     // return particle index; if unable to find the next true value then returns -1
00210     int GetNextTrue(void)
00211     {
00212         for(; m_iter < kBitsPerDWORD; ++m_iter, m_mask<<=1)
00213         {
00214             if (m_mask & m_blockIndices)
00215             {
00216                 m_mask <<= 1;
00217                 return (m_majorIndex + (m_iter++));
00218             }
00219         }
00220         return -1;
00221     }
00222 
00223     static const int kBitsPerDWORD = 32;
00224 
00225 private:
00226     OrbazTrueBlockIterator(void)
00227         :   OrbazTrueBlock()
00228         ,   m_iter(0)
00229         ,   m_mask(1)
00230     {}
00231 
00232     int m_iter;
00233     int m_mask;
00234 };
00235 
00236 class OrbazTrueBlockEnumerator : public BitArrayCallback
00237 {
00238 public:
00239     OrbazTrueBlockEnumerator(OrbazTrueBlock*& trueBlocks)
00240         : m_trueBlocks(trueBlocks)
00241         , m_blockIndex(-1)
00242     {
00243     }
00244 
00245     void proc(int n)
00246     {
00247         int curMajorIndex = n & kMajorIndexMask;
00248         if (m_blockIndex  >= 0)
00249         {
00250             if (m_trueBlocks[m_blockIndex].GetMajorIndex() != curMajorIndex)
00251             {
00252                 m_trueBlocks[++m_blockIndex].SetMajorIndex(curMajorIndex);
00253             }
00254         }
00255         else
00256         {
00257             m_blockIndex = 0;
00258             m_trueBlocks[0].SetMajorIndex(curMajorIndex);
00259         }
00260         m_trueBlocks[m_blockIndex].AddBlockIndex(n);
00261     }
00262 
00263     inline int NumBlocksSet(void)  { return m_blockIndex+1; }
00264     OrbazTrueBlockEnumerator& operator=(const OrbazTrueBlockEnumerator& rhs)
00265     {
00266         if (this != &rhs)
00267         {
00268             m_trueBlocks = rhs.m_trueBlocks;
00269             m_blockIndex = rhs.m_blockIndex;
00270         }
00271         return *this;
00272     }
00273 private:
00274     OrbazTrueBlock*&    m_trueBlocks;
00275     int                 m_blockIndex;
00276     static const DWORD  kMajorIndexMask = 0xFFFFFFE0;
00277 };
00278 
00279