llroam.h

Go to the documentation of this file.
00001 
00032 /****************************************/
00033 /*      Implementation of ROAM algorithm        */
00034 /****************************************/
00035 
00036 #ifndef LL_ROAM_H
00037 #define LL_ROAM_H
00038 
00039 #include "stdtypes.h"
00040 #include "doublelinkedlist.h"
00041 
00042 class LLRoamPatch;
00043 class LLRoam;
00044 
00045 class LLRoamTriNode
00046 {
00047 protected:
00048         U8                              mLevel;
00049         S8                              mType;  // -1 - left child, 1 - righ child, 0 - top vertex
00050         LLRoamTriNode*  mParent;
00051         LLRoamTriNode*  mLchild;
00052         LLRoamTriNode*  mRchild;
00053         LLRoamTriNode*  mLeft;
00054         LLRoamTriNode*  mRight;
00055         LLRoamTriNode*  mBase;
00056         LLRoamPatch*    mPatch;
00057         BOOL                    mLeaf;
00058         BOOL                    mInQueue;
00059 
00060 public:
00061         static LLRoam*  sQueues;
00062 
00063         //LLRoamTriNode(S8 level = 0, const LLRoamTriNode* left = 0
00064         //      const LLRoamTriNode* right = 0, const LLRoamTriNode* base = 0): 
00065         //      mLevel(level), mLeft(left), mRight(right), mBase(base), mLchild(0), mRchild(0) {}
00066         LLRoamTriNode(U8 level = 0, S8 type = 0, LLRoamTriNode* par = 0):
00067                 mLevel(level), mType(type), mParent(par), mLchild(0), mRchild(0),
00068                 mLeft(0), mRight(0), mBase(0), mPatch(0),
00069                 mLeaf(TRUE), mInQueue(FALSE) {}
00070 
00071         virtual LLRoamTriNode* newLChild()
00072         {
00073                 return new LLRoamTriNode(mLevel+1, -1, this);
00074         }
00075         virtual LLRoamTriNode* newRChild()
00076         {
00077                 return new LLRoamTriNode(mLevel+1, 1, this);
00078         }
00079 
00080         virtual ~LLRoamTriNode();
00081         LLRoamTriNode*  Lchild() const { return mLchild; }
00082         LLRoamTriNode*  Rchild() const { return mRchild; }
00083         LLRoamTriNode*  left() const { return mLeft; }
00084         LLRoamTriNode*  right() const { return mRight; }
00085         LLRoamTriNode*  base() const { return mBase; }
00086         LLRoamTriNode*  parent() const { return mParent; }
00087         void setLeft(LLRoamTriNode* left) { mLeft = left; }
00088         void setRight(LLRoamTriNode* right) { mRight = right; }
00089         void setBase(LLRoamTriNode* base) { mBase = base; }
00090         void setParent(LLRoamTriNode* parent) { mParent = parent; }
00091         U8 level() const { return mLevel; }
00092         BOOL leaf() const { return mLeaf; }
00093 
00094         void updateLink(LLRoamTriNode* old_link, LLRoamTriNode* new_link);
00095         BOOL split(BOOL forceful = FALSE);
00096         BOOL merge();
00097         void mergeSimple();
00098         //void refine();
00099         void update();
00100         virtual void updatePassive() {}
00101 
00102         virtual BOOL refine();// { return patch()->refine(this); }
00103         virtual void initForcefulRefine() {}
00104         virtual void flushFromQueue() {}
00105         LLRoamPatch* patch() const { return mPatch; }
00106         void setPatch(LLRoamPatch*  p) { mPatch = p; }
00107 
00108         const LLRoamTriNode* getFirstLeaf() const;
00109         const LLRoamTriNode* getNextLeaf() const;
00110 
00111         BOOL inQueue() const { return mInQueue; }
00112         void enqueue() { mInQueue = TRUE; }
00113         void dequeue() { mInQueue = FALSE; }
00114 
00115         BOOL checkConsistensy() const
00116         {
00117                 BOOL ok = TRUE;
00118                 if (leaf())
00119                 {
00120                         if (base() && !base()->leaf())
00121                                 ok = FALSE;
00122                         if (Lchild() && !Lchild()->leaf())
00123                                 ok = FALSE;
00124                         if (Rchild() && !Rchild()->leaf())
00125                                 ok = FALSE;
00126                 } else {
00127                         if (base() && base()->leaf())
00128                                 ok = FALSE;
00129                 }
00130                 return ok;
00131         }
00132 
00133 };
00134 
00135 
00136 class LLRoamPatch
00137 {
00138 protected:
00139         BOOL mBackSlash;
00140         LLRoamTriNode* mTri[2];
00141         U8 mMaxLevel;
00142         U32 mNumTris;
00143 public:
00144         LLRoamPatch(U8 max_level, BOOL back_slash) : mBackSlash(back_slash), mMaxLevel(max_level), mNumTris(0)
00145         {
00146                 mTri[0] = 0;
00147                 mTri[1] = 0;
00148         }
00149 
00150         virtual ~LLRoamPatch() { deleteTris(); }
00151         void deleteTris()
00152         {
00153                 delete mTri[0];
00154                 mTri[0] = 0;
00155                 delete mTri[1];
00156                 mTri[1] = 0;
00157         }
00158 
00159         void updatePassive()
00160         {
00161                 mTri[0]->updatePassive();
00162                 mTri[1]->updatePassive();
00163         }
00164 
00165         void update()
00166         {
00167                 mTri[0]->update();
00168                 mTri[1]->update();
00169                 
00170                 //checkCount();
00171         }
00172 
00173         U32 checkCount()
00174         {
00175                 BOOL ok = TRUE;
00176                 U32 ntri = 0;
00177                 for (U8 h = 0; h < 2; h++)
00178                 {
00179                         for (const LLRoamTriNode*   tri = mTri[h]->getFirstLeaf();
00180                                                                                 tri != NULL;
00181                                                                                 tri = tri->getNextLeaf())
00182                                 ntri++;
00183                 }
00184                 if (ntri != mNumTris)
00185                         ok = FALSE;
00186                 return mNumTris;
00187         }
00188 
00189         LLRoamTriNode*  left() const { return mTri[0]; }
00190         LLRoamTriNode*  right() const { return mTri[1]; }
00191         LLRoamTriNode*  half(U8 h) const { return mTri[h]; }
00192 
00193         U8 maxLevel() const { return mMaxLevel; }
00194         BOOL refine(const LLRoamTriNode* tri) const { return tri->level() < mMaxLevel; }
00195         U32 numTris() const { return mNumTris; }
00196         U32 numTrisInc() { mNumTris++; return mNumTris; }
00197         U32 numTrisDec() { mNumTris--; return mNumTris; }
00198         void setTris(LLRoamTriNode* left, LLRoamTriNode* right)
00199         {
00200                 mTri[0] = left;
00201                 mTri[1] = right;
00202                 setTris();
00203         }
00204 
00205         void setTris()
00206         {
00207                 mTri[0]->setBase(mTri[1]);
00208                 mTri[1]->setBase(mTri[0]);
00209                 mTri[0]->setPatch(this);
00210                 mTri[1]->setPatch(this);
00211                 mNumTris = 2;
00212         }
00213         void checkConsistensy() const
00214         {
00215                 for (U8 h = 0; h < 2; h++)
00216                 {
00217                         left()->checkConsistensy();
00218                         right()->checkConsistensy();
00219                         /*
00220                         for (const LLWaterTri*  tri = (LLWaterTri*)mTri[h]->getFirstLeaf();
00221                                                                         tri != NULL;
00222                                                                         tri = (LLWaterTri*)tri->getNextLeaf())
00223                         {
00224                                 if (!tri->upToDate())
00225                                         return FALSE;
00226                         } */
00227                 }
00228         }
00229 };
00230 
00231 inline BOOL LLRoamTriNode::refine() { return patch()->refine(this); }
00232 
00233 class LLRoam
00234 {
00235 protected:
00236         LLDoubleLinkedList<LLRoamTriNode> mSplitQ;
00237         LLDoubleLinkedList<LLRoamTriNode> mMergeQ;
00238         U32             mNum;
00239 public:
00240         LLRoam() {}
00241         ~LLRoam() { mSplitQ.removeAllNodes(); mMergeQ.removeAllNodes(); }
00242 
00243         void pushSplit(LLRoamTriNode* t)
00244         {
00245                 if (!t->inQueue())
00246                 {
00247                         mSplitQ.addDataAtEnd(t);
00248                         t->enqueue();
00249                 }
00250         }
00251         LLRoamTriNode* popSplit()
00252         {
00253                 LLRoamTriNode* t = mSplitQ.getFirstData();
00254                 t->dequeue();
00255                 mSplitQ.removeCurrentData();
00256                 return t;
00257         }
00258         void pushMerge(LLRoamTriNode* t)
00259         {
00260                 if (!t->inQueue())
00261                 {
00262                         mMergeQ.addDataAtEnd(t);
00263                         t->enqueue();
00264                 }
00265         }
00266         LLRoamTriNode* popMerge()
00267         {
00268                 LLRoamTriNode* t = mMergeQ.getFirstData();
00269                 t->dequeue();
00270                 mMergeQ.removeCurrentData();
00271                 return t;
00272         }
00273 
00274         void queueForSplit(LLRoamTriNode* t, BOOL process_base = TRUE);
00275         void queueForMerge(LLRoamTriNode* t, BOOL process_base = TRUE);
00276 
00277         void processSplit();
00278         void processMerge();
00279         void process();
00280 
00281         U32  numOfProcessedTris() const { return mNum; }
00282         void numOfProcessedTrisInc() { mNum++; }
00283         void resetCount() { mNum = 0; }
00284 //      BOOL processTooLong() const { return mNum > 10000; }
00285         void flushSplit();
00286         void flushMerge();
00287         /*
00288         void cutProcessing()
00289         {
00290                 flushMerge();
00291                 flushSplit();
00292                 resetCount();
00293         } */
00294         void checkTiming()
00295         {
00296                 if (mNum > 1000)
00297                 {
00298                         flushMerge();
00299                         flushSplit();
00300                         resetCount();
00301                 }
00302         }
00303 
00304         BOOL mergeQueueTooLong() const { return mMergeQ.getLength() > 1000; }
00305         BOOL splitQueueTooLong() const { return mSplitQ.getLength() > 1000; }
00306 };
00307 
00308 #endif

Generated on Thu Jul 1 06:09:05 2010 for Second Life Viewer by  doxygen 1.4.7