00001
00032
00033
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;
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
00064
00065
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
00099 void update();
00100 virtual void updatePassive() {}
00101
00102 virtual BOOL refine();
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
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
00221
00222
00223
00224
00225
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
00285 void flushSplit();
00286 void flushMerge();
00287
00288
00289
00290
00291
00292
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