llpatchvertexarray.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llpatchvertexarray.h"
00035 #include "llsurfacepatch.h"
00036 
00037 // constructors
00038 
00039 LLPatchVertexArray::LLPatchVertexArray() :
00040         mSurfaceWidth(0),
00041         mPatchWidth(0),
00042         mPatchOrder(0),
00043         mRenderLevelp(NULL),
00044         mRenderStridep(NULL)
00045 {
00046 }
00047 
00048 LLPatchVertexArray::LLPatchVertexArray(U32 surface_width, U32 patch_width, F32 meters_per_grid) :
00049         mRenderLevelp(NULL),
00050         mRenderStridep(NULL)
00051 {
00052         create(surface_width, patch_width, meters_per_grid);
00053 }
00054 
00055 
00056 LLPatchVertexArray::~LLPatchVertexArray() 
00057 {
00058         destroy();
00059 }
00060 
00061 
00062 void LLPatchVertexArray::create(U32 surface_width, U32 patch_width, F32 meters_per_grid) 
00063 {
00064         // PART 1 -- Make sure the arguments are good...
00065         // Make sure patch_width is not greater than surface_width
00066         if (patch_width > surface_width) 
00067         {
00068                 U32 temp = patch_width;
00069                 patch_width = surface_width;
00070                 surface_width = temp;
00071         }
00072 
00073         // Make sure (surface_width-1) is equal to a power_of_two.
00074         // (The -1 is there because an LLSurface has a buffer of 1 on 
00075         // its East and North edges).
00076         U32 power_of_two = 1;
00077         U32 surface_order = 0;
00078         while (power_of_two < (surface_width-1))
00079         {
00080                 power_of_two *= 2;
00081                 surface_order += 1;
00082         }
00083 
00084         if (power_of_two == (surface_width-1))
00085         {
00086                 mSurfaceWidth = surface_width;
00087 
00088                 // Make sure patch_width is a factor of (surface_width - 1)
00089                 U32 ratio = (surface_width - 1) / patch_width;
00090                 F32 fratio = ((float)(surface_width - 1)) / ((float)(patch_width));
00091                 if ( fratio == (float)(ratio))
00092                 {
00093                         // Make sure patch_width is a power of two
00094                         power_of_two = 1;
00095                         U32 patch_order = 0;
00096                         while (power_of_two < patch_width)
00097                         {
00098                                 power_of_two *= 2;
00099                                 patch_order += 1;
00100                         }
00101                         if (power_of_two == patch_width)
00102                         {
00103                                 mPatchWidth = patch_width;
00104                                 mPatchOrder = patch_order;
00105                         }
00106                         else // patch_width is not a power of two...
00107                         {
00108                                 mPatchWidth = 0;
00109                                 mPatchOrder = 0;
00110                         }
00111                 }
00112                 else // patch_width is not a factor of (surface_width - 1)...
00113                 {
00114                         mPatchWidth = 0;
00115                         mPatchOrder = 0;
00116                 }
00117         }
00118         else // surface_width is not a power of two...
00119         {
00120                 mSurfaceWidth = 0;
00121                 mPatchWidth = 0;
00122                 mPatchOrder = 0;
00123         }
00124 
00125         // PART 2 -- Allocate memory for the render level table
00126         if (mPatchWidth > 0) 
00127         {
00128                 mRenderLevelp = new U32 [2*mPatchWidth + 1];
00129                 mRenderStridep = new U32 [mPatchOrder + 1];
00130         }
00131 
00132         if (NULL == mRenderLevelp || NULL == mRenderStridep)
00133         {
00134                 // init() and some other things all want to deref these
00135                 // pointers, so this is serious.
00136                 llerrs << "mRenderLevelp or mRenderStridep was NULL; we'd crash soon." << llendl;
00137                 return;
00138         }
00139 
00140         // Now that we've allocated memory, we can initialize
00141         // the arrays...
00142         init();
00143 }
00144 
00145 
00146 void LLPatchVertexArray::destroy()
00147 {
00148         if (mPatchWidth == 0)
00149         {
00150                 return;
00151         }
00152 
00153         delete [] mRenderLevelp;
00154         delete [] mRenderStridep;
00155         mSurfaceWidth = 0;
00156         mPatchWidth = 0;
00157         mPatchOrder = 0;
00158 }
00159 
00160 
00161 void LLPatchVertexArray::init() 
00162 // Initializes the triangle strip arrays.
00163 {
00164         U32 j;
00165         U32 level, stride;
00166         U32 k;
00167 
00168         // We need to build two look-up tables... 
00169 
00170         // render_level -> render_stride 
00171         // A 16x16 patch has 5 render levels : 2^0 to 2^4
00172         // render_level         render_stride
00173         //              4                               1
00174         //              3                               2
00175         //              2                               4
00176         //              1                               8
00177         //              0                               16
00178         stride = mPatchWidth;
00179         for (level=0; level<mPatchOrder + 1; level++)
00180         {
00181                 mRenderStridep[level] = stride;
00182                 stride /= 2;
00183         }
00184 
00185         // render_level <- render_stride.
00186 /*
00187         // For a 16x16 patch we'll clamp the render_strides to 0 through 16
00188         // and enter the nearest render_level in the table.  Of course, only
00189         // power-of-two render strides are actually used. 
00190         //
00191         // render_stride        render_level
00192         //              0                               4
00193         //              1                               4       *
00194         //              2                               3       *
00195         //              3                               3
00196         //              4                               2       *
00197         //              5                               2
00198         //              6                               2
00199         //              7                               1
00200         //              8                               1       *
00201         //              9                               1
00202         //              10                              1
00203         //              11                              1
00204         //              12                              1
00205         //              13                              0
00206         //              14                              0
00207         //              15                              0
00208         //              16                              Always 0
00209 
00210         level = mPatchOrder;
00211         for (stride=0; stride<mPatchWidth; stride++)
00212         {
00213                 if ((F32) stride > 2.1f * mRenderStridep[level])
00214                 {
00215                         level--;        
00216                 };
00217                 mRenderLevelp[stride] = level;
00218         }
00219         */
00220 
00221         // This method is more agressive about putting triangles onscreen
00222         level = mPatchOrder;
00223         k = 2;
00224         mRenderLevelp[0] = mPatchOrder;
00225         mRenderLevelp[1] = mPatchOrder;
00226         stride = 2;
00227         while(stride < 2*mPatchWidth)
00228         {
00229                 for (j=0; j<k  &&  stride<2*mPatchWidth; j++)
00230                 {
00231                         mRenderLevelp[stride++] = level;
00232                 }
00233                 k *= 2;
00234                 level--;        
00235         }
00236         mRenderLevelp[2*mPatchWidth] = 0;
00237 }
00238 
00239 
00240 std::ostream& operator<<(std::ostream &s, const LLPatchVertexArray &va)
00241 {
00242         U32 i;
00243         s << "{ \n";
00244         s << "  mSurfaceWidth = " << va.mSurfaceWidth << "\n";
00245         s << "  mPatchWidth = " << va.mPatchWidth << "\n";
00246         s << "  mPatchOrder = " << va.mPatchOrder << "\n";
00247         s << "  mRenderStridep = \n";
00248         for (i=0; i<va.mPatchOrder+1; i++)
00249         {
00250                 s << "    " << i << "    " << va.mRenderStridep[i] << "\n";
00251         }
00252         s << "  mRenderLevelp = \n";
00253         for (i=0; i < 2*va.mPatchWidth + 1; i++)
00254         {
00255                 s << "    " << i << "    " << va.mRenderLevelp[i] << "\n";
00256         }
00257         s << "}";       
00258         return s;
00259 }
00260 
00261 
00262 // EOF

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