/indra/newview/llpatchvertexarray.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 257 lines · 144 code · 28 blank · 85 comment · 25 complexity · 7d07e2ac6fa843aff28d69b285739495 MD5 · raw file

  1. /**
  2. * @file llpatchvertexarray.cpp
  3. * @brief Implementation of the LLSurfaceVertexArray class.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llpatchvertexarray.h"
  28. #include "llsurfacepatch.h"
  29. // constructors
  30. LLPatchVertexArray::LLPatchVertexArray() :
  31. mSurfaceWidth(0),
  32. mPatchWidth(0),
  33. mPatchOrder(0),
  34. mRenderLevelp(NULL),
  35. mRenderStridep(NULL)
  36. {
  37. }
  38. LLPatchVertexArray::LLPatchVertexArray(U32 surface_width, U32 patch_width, F32 meters_per_grid) :
  39. mRenderLevelp(NULL),
  40. mRenderStridep(NULL)
  41. {
  42. create(surface_width, patch_width, meters_per_grid);
  43. }
  44. LLPatchVertexArray::~LLPatchVertexArray()
  45. {
  46. destroy();
  47. }
  48. void LLPatchVertexArray::create(U32 surface_width, U32 patch_width, F32 meters_per_grid)
  49. {
  50. // PART 1 -- Make sure the arguments are good...
  51. // Make sure patch_width is not greater than surface_width
  52. if (patch_width > surface_width)
  53. {
  54. U32 temp = patch_width;
  55. patch_width = surface_width;
  56. surface_width = temp;
  57. }
  58. // Make sure (surface_width-1) is equal to a power_of_two.
  59. // (The -1 is there because an LLSurface has a buffer of 1 on
  60. // its East and North edges).
  61. U32 power_of_two = 1;
  62. U32 surface_order = 0;
  63. while (power_of_two < (surface_width-1))
  64. {
  65. power_of_two *= 2;
  66. surface_order += 1;
  67. }
  68. if (power_of_two == (surface_width-1))
  69. {
  70. mSurfaceWidth = surface_width;
  71. // Make sure patch_width is a factor of (surface_width - 1)
  72. U32 ratio = (surface_width - 1) / patch_width;
  73. F32 fratio = ((float)(surface_width - 1)) / ((float)(patch_width));
  74. if ( fratio == (float)(ratio))
  75. {
  76. // Make sure patch_width is a power of two
  77. power_of_two = 1;
  78. U32 patch_order = 0;
  79. while (power_of_two < patch_width)
  80. {
  81. power_of_two *= 2;
  82. patch_order += 1;
  83. }
  84. if (power_of_two == patch_width)
  85. {
  86. mPatchWidth = patch_width;
  87. mPatchOrder = patch_order;
  88. }
  89. else // patch_width is not a power of two...
  90. {
  91. mPatchWidth = 0;
  92. mPatchOrder = 0;
  93. }
  94. }
  95. else // patch_width is not a factor of (surface_width - 1)...
  96. {
  97. mPatchWidth = 0;
  98. mPatchOrder = 0;
  99. }
  100. }
  101. else // surface_width is not a power of two...
  102. {
  103. mSurfaceWidth = 0;
  104. mPatchWidth = 0;
  105. mPatchOrder = 0;
  106. }
  107. // PART 2 -- Allocate memory for the render level table
  108. if (mPatchWidth > 0)
  109. {
  110. mRenderLevelp = new U32 [2*mPatchWidth + 1];
  111. mRenderStridep = new U32 [mPatchOrder + 1];
  112. }
  113. if (NULL == mRenderLevelp || NULL == mRenderStridep)
  114. {
  115. // init() and some other things all want to deref these
  116. // pointers, so this is serious.
  117. llerrs << "mRenderLevelp or mRenderStridep was NULL; we'd crash soon." << llendl;
  118. return;
  119. }
  120. // Now that we've allocated memory, we can initialize
  121. // the arrays...
  122. init();
  123. }
  124. void LLPatchVertexArray::destroy()
  125. {
  126. if (mPatchWidth == 0)
  127. {
  128. return;
  129. }
  130. delete [] mRenderLevelp;
  131. delete [] mRenderStridep;
  132. mSurfaceWidth = 0;
  133. mPatchWidth = 0;
  134. mPatchOrder = 0;
  135. }
  136. void LLPatchVertexArray::init()
  137. // Initializes the triangle strip arrays.
  138. {
  139. U32 j;
  140. U32 level, stride;
  141. U32 k;
  142. // We need to build two look-up tables...
  143. // render_level -> render_stride
  144. // A 16x16 patch has 5 render levels : 2^0 to 2^4
  145. // render_level render_stride
  146. // 4 1
  147. // 3 2
  148. // 2 4
  149. // 1 8
  150. // 0 16
  151. stride = mPatchWidth;
  152. for (level=0; level<mPatchOrder + 1; level++)
  153. {
  154. mRenderStridep[level] = stride;
  155. stride /= 2;
  156. }
  157. // render_level <- render_stride.
  158. /*
  159. // For a 16x16 patch we'll clamp the render_strides to 0 through 16
  160. // and enter the nearest render_level in the table. Of course, only
  161. // power-of-two render strides are actually used.
  162. //
  163. // render_stride render_level
  164. // 0 4
  165. // 1 4 *
  166. // 2 3 *
  167. // 3 3
  168. // 4 2 *
  169. // 5 2
  170. // 6 2
  171. // 7 1
  172. // 8 1 *
  173. // 9 1
  174. // 10 1
  175. // 11 1
  176. // 12 1
  177. // 13 0
  178. // 14 0
  179. // 15 0
  180. // 16 Always 0
  181. level = mPatchOrder;
  182. for (stride=0; stride<mPatchWidth; stride++)
  183. {
  184. if ((F32) stride > 2.1f * mRenderStridep[level])
  185. {
  186. level--;
  187. };
  188. mRenderLevelp[stride] = level;
  189. }
  190. */
  191. // This method is more agressive about putting triangles onscreen
  192. level = mPatchOrder;
  193. k = 2;
  194. mRenderLevelp[0] = mPatchOrder;
  195. mRenderLevelp[1] = mPatchOrder;
  196. stride = 2;
  197. while(stride < 2*mPatchWidth)
  198. {
  199. for (j=0; j<k && stride<2*mPatchWidth; j++)
  200. {
  201. mRenderLevelp[stride++] = level;
  202. }
  203. k *= 2;
  204. level--;
  205. }
  206. mRenderLevelp[2*mPatchWidth] = 0;
  207. }
  208. std::ostream& operator<<(std::ostream &s, const LLPatchVertexArray &va)
  209. {
  210. U32 i;
  211. s << "{ \n";
  212. s << " mSurfaceWidth = " << va.mSurfaceWidth << "\n";
  213. s << " mPatchWidth = " << va.mPatchWidth << "\n";
  214. s << " mPatchOrder = " << va.mPatchOrder << "\n";
  215. s << " mRenderStridep = \n";
  216. for (i=0; i<va.mPatchOrder+1; i++)
  217. {
  218. s << " " << i << " " << va.mRenderStridep[i] << "\n";
  219. }
  220. s << " mRenderLevelp = \n";
  221. for (i=0; i < 2*va.mPatchWidth + 1; i++)
  222. {
  223. s << " " << i << " " << va.mRenderLevelp[i] << "\n";
  224. }
  225. s << "}";
  226. return s;
  227. }
  228. // EOF