MipMapPatchIndex.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <geomipmap/MipMapPatchIndex.h>
00022 #include <common/DefinesAssert.h>
00023 #include <limits.h>
00024 #include <vector>
00025 
00026 MipMapPatchIndex::MipMapPatchIndex() : 
00027         indices_(0), size_(0), bufferOffSet_(-1),
00028         minIndex_(INT_MAX), maxIndex_(0)
00029 {
00030 }
00031 
00032 MipMapPatchIndex::~MipMapPatchIndex()
00033 {
00034         delete [] indices_;
00035 }
00036 
00037 void MipMapPatchIndex::generate(int size, int totalsize, int skip, unsigned int border, unsigned int totallods)
00038 {
00039         // Calculate the border (if any)
00040         unsigned int borderLeft  = (border & BorderLeft)  >> 0;
00041         unsigned int borderRight = (border & BorderRight) >> 3;
00042         unsigned int borderTop   = (border & BorderTop)   >> 6;
00043         unsigned int borderBottom= (border & BorderBottom)>> 9;
00044 
00045         if (borderLeft > totallods ||
00046                 borderRight > totallods ||
00047                 borderTop > totallods ||
00048                 borderBottom > totallods)
00049         {
00050                 // Check if we are exceeding the total number of lol levels
00051                 // e.g. the adjacent water patches only vary by 1 or 2 levels not the full range
00052                 return;
00053         }
00054 
00055         int borderLeftSkip = skip * (1 << borderLeft);
00056         int borderRightSkip = skip * (1 << borderRight);
00057         int borderTopSkip = skip * (1 << borderTop);
00058         int borderBottomSkip = skip * (1 << borderBottom);
00059 
00060         if (border != 0 &&
00061                 (borderLeftSkip > size ||
00062                 borderRightSkip > size ||
00063                 borderTopSkip > size ||
00064                 borderBottomSkip > size))
00065         {
00066                 // Check if we are try to border to a square that is larger than us
00067                 // i.e not needed
00068                 return;
00069         }
00070 
00071         // Generate a standard x by y grid of indices for a triangle strip
00072         // use degenerate indices to keep winding in the correct order
00073         std::vector<unsigned short> indices;
00074         int j=0;
00075         for (int y=0; y<size; y+=skip)
00076         {
00077                 for (int x=0; x<=size; x+=skip)
00078                 {
00079                         int i = 0;
00080                         // Check which way we are working across the grid
00081                         // alter the index order accordingly
00082                         bool up = (y % (2 * skip) == 0);
00083                         if (up)
00084                         {
00085                                 i = (size - x + y * (size + 1));
00086                         }
00087                         else
00088                         {
00089                                 i = (x + y * (size + 1));
00090                         }
00091 
00092                         // Add index for each side of the strip
00093                         indices.push_back(i);
00094                         indices.push_back(i + (size + 1) * skip);
00095                         
00096                         // Add degenerate index when needed
00097                         if (x == size && (y != (size - skip)))
00098                         {
00099                                 indices.push_back(i + (size + 1) * skip);
00100                         }
00101                 }
00102         }
00103 
00104         // Generate a mapping from the indices to the actual world indices
00105         // for when the patch size is larger than the index size.
00106         // Also move indices that don't exist in border squares.
00107         // Done here to keep the above code simpler.
00108         unsigned short *mappingIndices = new unsigned short[(size + 1) * (size + 1)];
00109         unsigned short *currentMappingIndex = mappingIndices;
00110         unsigned short currentMappingCount = 0;
00111         unsigned short lastGoodXTop, lastGoodXBottom, lastGoodYLeft, lastGoodYRight;
00112         for (int y=0; y<=size; y+=1)
00113         {
00114                 // Record last possible y border index
00115                 if (y % borderLeftSkip == 0) lastGoodYLeft = currentMappingCount;
00116                 if (y % borderRightSkip == 0) lastGoodYRight = currentMappingCount;
00117 
00118                 for (int x=0; x<=size; x+=1, currentMappingIndex++, currentMappingCount++)
00119                 {
00120                         // Record last possible x border index
00121                         if (x % borderTopSkip == 0) lastGoodXTop = currentMappingCount;
00122                         else if (x % borderTopSkip == 1) lastGoodXTop += borderTopSkip;
00123                         if (x % borderBottomSkip == 0) lastGoodXBottom = currentMappingCount;
00124 
00125                         // Set the index for case with no border
00126                         *currentMappingIndex = currentMappingCount;
00127 
00128                         // Move indices if we are on a border case
00129                         // and not only drawing one triangle
00130                         if (((border & BorderLeft) > 0) && x == 0)
00131                         {
00132                                 *currentMappingIndex = lastGoodYLeft;
00133                         }
00134                         if (((border & BorderRight) > 0) && x == size)
00135                         {
00136                                 *currentMappingIndex = lastGoodYRight + size;
00137                         }
00138                         if (((border & BorderBottom) > 0) && y == 0)
00139                         {
00140                                 *currentMappingIndex = lastGoodXBottom;
00141                         }
00142                         if (((border & BorderTop) > 0) && y == size)
00143                         {
00144                                 *currentMappingIndex = lastGoodXTop;
00145                         }
00146                 }
00147                 currentMappingCount += totalsize - size;
00148         }
00149 
00150         // Put the calculated indices into a unsigned array for OpenGL access
00151         size_ = (int) indices.size();
00152         if (!indices_) indices_ = new unsigned short[size_];
00153         for (int i=0; i<size_; i++)
00154         {
00155                 int j = indices[i];
00156                 DIALOG_ASSERT(!(j <0 || j > (size + 1) * (size + 1)));
00157                 int k = mappingIndices[j];
00158                 indices_[i] = k;
00159                 if (k > maxIndex_) maxIndex_ = k;
00160                 else if (k < minIndex_) minIndex_ = k;
00161         }
00162         delete [] mappingIndices;
00163 }

Generated on Mon Feb 16 15:14:38 2009 for Scorched3D by  doxygen 1.5.3