Sirikata
libspace/include/sirikata/space/SegmentedRegion.hpp
Go to the documentation of this file.
00001 /*  Sirikata
00002  *  SegmentedRegion.hpp
00003  *
00004  *  Copyright (c) 2009, Tahir Azim
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions are
00009  *  met:
00010  *  * Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *  * Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in
00014  *    the documentation and/or other materials provided with the
00015  *    distribution.
00016  *  * Neither the name of Sirikata nor the names of its contributors may
00017  *    be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00024  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #ifndef _SIRIKATA_SEGMENTED_REGION_HPP_
00034 #define _SIRIKATA_SEGMENTED_REGION_HPP_
00035 
00036 
00037 namespace Sirikata {
00038 
00039 typedef struct SerializedBBox{
00040   float32 minX;
00041   float32 minY;
00042   float32 minZ;
00043 
00044   float32 maxX;
00045   float32 maxY;
00046   float32 maxZ;
00047 
00048   void serialize(const BoundingBox3f& bbox) {
00049     minX = bbox.min().x;
00050     minY = bbox.min().y;
00051     minZ = bbox.min().z;
00052 
00053     maxX = bbox.max().x;
00054     maxY = bbox.max().y;
00055     maxZ = bbox.max().z;
00056   }
00057 
00058   void deserialize(BoundingBox3f& bbox) {
00059     bbox = BoundingBox3f(Vector3f(minX,minY,minZ),
00060              Vector3f(maxX, maxY, maxZ));
00061   }
00062 
00063 } SerializedBBox ;
00064 
00065 typedef struct SegmentedRegion {
00066 
00067   SegmentedRegion(SegmentedRegion* parent) {
00068     mLeafCount = 0;
00069     mLeftChild  = mRightChild = NULL;
00070     mParent = parent;
00071     mServer = 0;
00072     mLoadValue = 0;
00073     mSplitAxis = UNDEFINED;
00074   }
00075 
00076   void destroy() {
00077     if (mLeftChild != NULL) {
00078       mLeftChild->destroy();
00079 
00080       SegmentedRegion* prevLeftChild = mLeftChild;
00081       mLeftChild = NULL;
00082 
00083       delete prevLeftChild;
00084     }
00085     if (mRightChild != NULL) {
00086       mRightChild->destroy();
00087 
00088       SegmentedRegion* prevRightChild = mRightChild;
00089       mRightChild = NULL;
00090 
00091       delete prevRightChild;
00092     }
00093   }
00094 
00095   SegmentedRegion* getRandomLeaf() {
00096     if (mRightChild == NULL && mLeftChild == NULL) {
00097       return this;
00098     }
00099 
00100     int random = rand() % 2;
00101     if (random == 0)
00102       return mLeftChild->getRandomLeaf();
00103     else
00104       return mRightChild->getRandomLeaf();
00105   }
00106 
00107   SegmentedRegion* getSibling(SegmentedRegion* region) {
00108     assert(region->mLeftChild == NULL && region->mRightChild == NULL);
00109 
00110     if (mRightChild == NULL && mLeftChild == NULL) return NULL;
00111 
00112     if (mRightChild == region) return mLeftChild;
00113     if (mLeftChild == region) return mRightChild;
00114 
00115     SegmentedRegion* r1 = mLeftChild->getSibling(region);
00116 
00117     if (r1 != NULL) return r1;
00118 
00119     SegmentedRegion* r2 = mRightChild->getSibling(region);
00120 
00121     if (r2 != NULL) return r2;
00122 
00123     return NULL;
00124   }
00125 
00126   SegmentedRegion* getParent(SegmentedRegion* region) {
00127     if (mRightChild == NULL && mLeftChild == NULL) return NULL;
00128 
00129     if (mRightChild == region) return this;
00130     if (mLeftChild == region) return this;
00131 
00132     SegmentedRegion* r1 = mLeftChild->getParent(region);
00133 
00134     if (r1 != NULL) return r1;
00135 
00136     SegmentedRegion* r2 = mRightChild->getParent(region);
00137 
00138     if (r2 != NULL) return r2;
00139 
00140     return NULL;
00141   }
00142 
00143   int countServers() const {
00144     if (mRightChild == NULL && mLeftChild == NULL) return 1;
00145 
00146     int count = 0;
00147 
00148     if (mLeftChild != NULL) {
00149       count += mLeftChild->countServers();
00150     }
00151     if (mRightChild != NULL) {
00152       count += mRightChild->countServers();
00153     }
00154 
00155     return count;
00156   }
00157 
00158   int countNodes() const {
00159     if (mRightChild == NULL && mLeftChild == NULL) return 1;
00160 
00161     int count = 0;
00162 
00163     if (mLeftChild != NULL) {
00164       count += mLeftChild->countNodes();
00165     }
00166     if (mRightChild != NULL) {
00167       count += mRightChild->countNodes();
00168     }
00169 
00170     return count+1;
00171   }
00172 
00173   SegmentedRegion* lookupSegmentedRegion(const ServerID& server_id) {
00174     if (mRightChild == NULL && mLeftChild == NULL && mServer==server_id) {
00175       return this;
00176     }
00177 
00178     SegmentedRegion* segRegion = mLeftChild->lookupSegmentedRegion(server_id);
00179 
00180     if (segRegion != NULL) {
00181       return segRegion;
00182     }
00183 
00184     segRegion = mRightChild->lookupSegmentedRegion(server_id);
00185 
00186     if (segRegion != NULL) {
00187       return segRegion;
00188     }
00189 
00190     return NULL;
00191   }
00192 
00193   SegmentedRegion* lookup(const Vector3f& pos) const {
00194     if (mRightChild == NULL && mLeftChild == NULL) {      
00195       if (mBoundingBox.contains(pos) || mBoundingBox.degenerate()) {        
00196     return ((SegmentedRegion*)this);
00197       }
00198     }
00199     
00200     SegmentedRegion* region = NULL;
00201 
00202     if (mLeftChild != NULL && mLeftChild->mBoundingBox.contains(pos)) {
00203       region = mLeftChild->lookup(pos);
00204     }
00205 
00206     if (region == NULL && mRightChild!=NULL && mRightChild->mBoundingBox.contains(pos)){
00207       region= mRightChild->lookup(pos);
00208     }
00209 
00210     return region;
00211   }
00212 
00213   void lookupBoundingBox(const BoundingBox3f& bbox, std::vector<SegmentedRegion*>& intersectingLeaves) {
00214     if (mRightChild == NULL && mLeftChild == NULL) {
00215       if (mBoundingBox.intersects(bbox)) {
00216     intersectingLeaves.push_back((SegmentedRegion*) this);
00217       }
00218     }
00219 
00220     if (mLeftChild != NULL && mLeftChild->mBoundingBox.intersects(bbox)) {
00221       mLeftChild->lookupBoundingBox(bbox, intersectingLeaves);
00222     }
00223 
00224     if ( mRightChild!=NULL && mRightChild->mBoundingBox.intersects(bbox)) {
00225       mRightChild->lookupBoundingBox(bbox, intersectingLeaves);
00226     }
00227   }
00228 
00229   void serverRegion(const ServerID& server, BoundingBoxList& boundingBoxList) const {
00230     if (mServer == server && mRightChild==NULL && mLeftChild==NULL) {
00231       boundingBoxList.push_back(mBoundingBox);
00232       return;
00233     }
00234 
00235     if (mLeftChild != NULL) {
00236       mLeftChild->serverRegion(server, boundingBoxList);
00237     }
00238 
00239     if (mRightChild != NULL) {
00240       mRightChild->serverRegion(server, boundingBoxList);
00241     }
00242 
00243     return;
00244   }
00245 
00246   ServerID mServer;
00247   SegmentedRegion* mLeftChild;
00248   SegmentedRegion* mRightChild;
00249   SegmentedRegion* mParent;
00250 
00251   enum SplitAxis{ X, Y, Z, UNDEFINED  };
00252 
00253   SplitAxis mSplitAxis;
00254 
00255   uint32 mLeafCount;
00256   BoundingBox3f mBoundingBox;
00257   uint32 mLoadValue;
00258 
00259 } SegmentedRegion;
00260 
00261 typedef struct SerializedSegmentedRegion {
00262   ServerID mServerID;
00263   uint32 mLeftChildIdx;
00264   uint32 mRightChildIdx;
00265   SerializedBBox mBoundingBox;
00266   uint32 mLeafCount;
00267 
00268   SerializedSegmentedRegion() {
00269     mLeftChildIdx = 0;
00270     mRightChildIdx = 0;
00271   }
00272 
00273 } SerializedSegmentedRegion;
00274 
00275 
00276 
00277 typedef struct SerializedBSPTree {
00278   uint32 mNodeCount;
00279   SerializedSegmentedRegion* mSegmentedRegions;  //allocate dynamically based on
00280                                                  //size of region.
00281 
00282   SerializedBSPTree(int numNodes) {
00283     mNodeCount = numNodes;
00284     mSegmentedRegions = new SerializedSegmentedRegion[numNodes];
00285   }
00286 
00287   ~SerializedBSPTree() {
00288     delete mSegmentedRegions;
00289   }
00290 
00291   void deserializeBSPTree(SegmentedRegion* region, uint32 idx,
00292               SerializedBSPTree* serializedTree)
00293   {
00294     assert(idx<serializedTree->mNodeCount);
00295 
00296     region->mServer = serializedTree->mSegmentedRegions[idx].mServerID;
00297 
00298     region->mLeafCount = serializedTree->mSegmentedRegions[idx].mLeafCount;
00299 
00300     serializedTree->mSegmentedRegions[idx].mBoundingBox.deserialize(region->mBoundingBox);
00301 
00302     if (serializedTree->mSegmentedRegions[idx].mLeftChildIdx == 0 &&
00303        serializedTree->mSegmentedRegions[idx].mRightChildIdx == 0)
00304     {
00305       //std::cout << region->mServer << " : " <<region->mLeafCount << "\n";
00306       //std::cout << region->mBoundingBox << "\n";
00307     }
00308 
00309     //std::cout << "left " << serializedTree->mSegmentedRegions[idx].mLeftChildIdx << "\n";
00310     //std::cout << "right " <<  serializedTree->mSegmentedRegions[idx].mRightChildIdx << "\n";
00311 
00312     if (serializedTree->mSegmentedRegions[idx].mLeftChildIdx != 0) {
00313       region->mLeftChild = new SegmentedRegion(region);
00314       deserializeBSPTree(region->mLeftChild, serializedTree->mSegmentedRegions[idx].mLeftChildIdx, serializedTree);
00315     }
00316 
00317     if (serializedTree->mSegmentedRegions[idx].mRightChildIdx != 0) {
00318       region->mRightChild = new SegmentedRegion(region);
00319       deserializeBSPTree(region->mRightChild,serializedTree->mSegmentedRegions[idx].mRightChildIdx, serializedTree);
00320     }
00321   }
00322 
00323 private:
00324   SerializedBSPTree() {
00325     mNodeCount = 0;
00326   }
00327 
00328 } SerializedBSPTree;
00329 
00330 
00331 }
00332 #endif