llpatchvertexarray.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:6k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llpatchvertexarray.cpp
  3.  * @brief Implementation of the LLSurfaceVertexArray class.
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llpatchvertexarray.h"
  34. #include "llsurfacepatch.h"
  35. // constructors
  36. LLPatchVertexArray::LLPatchVertexArray() :
  37. mSurfaceWidth(0),
  38. mPatchWidth(0),
  39. mPatchOrder(0),
  40. mRenderLevelp(NULL),
  41. mRenderStridep(NULL)
  42. {
  43. }
  44. LLPatchVertexArray::LLPatchVertexArray(U32 surface_width, U32 patch_width, F32 meters_per_grid) :
  45. mRenderLevelp(NULL),
  46. mRenderStridep(NULL)
  47. {
  48. create(surface_width, patch_width, meters_per_grid);
  49. }
  50. LLPatchVertexArray::~LLPatchVertexArray() 
  51. {
  52. destroy();
  53. }
  54. void LLPatchVertexArray::create(U32 surface_width, U32 patch_width, F32 meters_per_grid) 
  55. {
  56. // PART 1 -- Make sure the arguments are good...
  57. // Make sure patch_width is not greater than surface_width
  58. if (patch_width > surface_width) 
  59. {
  60. U32 temp = patch_width;
  61. patch_width = surface_width;
  62. surface_width = temp;
  63. }
  64. // Make sure (surface_width-1) is equal to a power_of_two.
  65. // (The -1 is there because an LLSurface has a buffer of 1 on 
  66. // its East and North edges).
  67. U32 power_of_two = 1;
  68. U32 surface_order = 0;
  69. while (power_of_two < (surface_width-1))
  70. {
  71. power_of_two *= 2;
  72. surface_order += 1;
  73. }
  74. if (power_of_two == (surface_width-1))
  75. {
  76. mSurfaceWidth = surface_width;
  77. // Make sure patch_width is a factor of (surface_width - 1)
  78. U32 ratio = (surface_width - 1) / patch_width;
  79. F32 fratio = ((float)(surface_width - 1)) / ((float)(patch_width));
  80. if ( fratio == (float)(ratio))
  81. {
  82. // Make sure patch_width is a power of two
  83. power_of_two = 1;
  84. U32 patch_order = 0;
  85. while (power_of_two < patch_width)
  86. {
  87. power_of_two *= 2;
  88. patch_order += 1;
  89. }
  90. if (power_of_two == patch_width)
  91. {
  92. mPatchWidth = patch_width;
  93. mPatchOrder = patch_order;
  94. }
  95. else // patch_width is not a power of two...
  96. {
  97. mPatchWidth = 0;
  98. mPatchOrder = 0;
  99. }
  100. }
  101. else // patch_width is not a factor of (surface_width - 1)...
  102. {
  103. mPatchWidth = 0;
  104. mPatchOrder = 0;
  105. }
  106. }
  107. else // surface_width is not a power of two...
  108. {
  109. mSurfaceWidth = 0;
  110. mPatchWidth = 0;
  111. mPatchOrder = 0;
  112. }
  113. // PART 2 -- Allocate memory for the render level table
  114. if (mPatchWidth > 0) 
  115. {
  116. mRenderLevelp = new U32 [2*mPatchWidth + 1];
  117. mRenderStridep = new U32 [mPatchOrder + 1];
  118. }
  119. if (NULL == mRenderLevelp || NULL == mRenderStridep)
  120. {
  121. // init() and some other things all want to deref these
  122. // pointers, so this is serious.
  123. llerrs << "mRenderLevelp or mRenderStridep was NULL; we'd crash soon." << llendl;
  124. return;
  125. }
  126. // Now that we've allocated memory, we can initialize
  127. // the arrays...
  128. init();
  129. }
  130. void LLPatchVertexArray::destroy()
  131. {
  132. if (mPatchWidth == 0)
  133. {
  134. return;
  135. }
  136. delete [] mRenderLevelp;
  137. delete [] mRenderStridep;
  138. mSurfaceWidth = 0;
  139. mPatchWidth = 0;
  140. mPatchOrder = 0;
  141. }
  142. void LLPatchVertexArray::init() 
  143. // Initializes the triangle strip arrays.
  144. {
  145. U32 j;
  146. U32 level, stride;
  147. U32 k;
  148. // We need to build two look-up tables... 
  149. // render_level -> render_stride 
  150. // A 16x16 patch has 5 render levels : 2^0 to 2^4
  151. // render_level render_stride
  152. // 4 1
  153. // 3 2
  154. // 2 4
  155. // 1 8
  156. // 0 16
  157. stride = mPatchWidth;
  158. for (level=0; level<mPatchOrder + 1; level++)
  159. {
  160. mRenderStridep[level] = stride;
  161. stride /= 2;
  162. }
  163. // render_level <- render_stride.
  164. /*
  165. // For a 16x16 patch we'll clamp the render_strides to 0 through 16
  166. // and enter the nearest render_level in the table.  Of course, only
  167. // power-of-two render strides are actually used. 
  168. //
  169. // render_stride render_level
  170. // 0 4
  171. // 1 4 *
  172. // 2 3 *
  173. // 3 3
  174. // 4 2 *
  175. // 5 2
  176. // 6 2
  177. // 7 1
  178. // 8 1 *
  179. // 9 1
  180. // 10 1
  181. // 11 1
  182. // 12 1
  183. // 13 0
  184. // 14 0
  185. // 15 0
  186. // 16 Always 0
  187. level = mPatchOrder;
  188. for (stride=0; stride<mPatchWidth; stride++)
  189. {
  190. if ((F32) stride > 2.1f * mRenderStridep[level])
  191. {
  192. level--;
  193. };
  194. mRenderLevelp[stride] = level;
  195. }
  196. */
  197. // This method is more agressive about putting triangles onscreen
  198. level = mPatchOrder;
  199. k = 2;
  200. mRenderLevelp[0] = mPatchOrder;
  201. mRenderLevelp[1] = mPatchOrder;
  202. stride = 2;
  203. while(stride < 2*mPatchWidth)
  204. {
  205. for (j=0; j<k  &&  stride<2*mPatchWidth; j++)
  206. {
  207. mRenderLevelp[stride++] = level;
  208. }
  209. k *= 2;
  210. level--;
  211. }
  212. mRenderLevelp[2*mPatchWidth] = 0;
  213. }
  214. std::ostream& operator<<(std::ostream &s, const LLPatchVertexArray &va)
  215. {
  216. U32 i;
  217. s << "{ n";
  218. s << "  mSurfaceWidth = " << va.mSurfaceWidth << "n";
  219. s << "  mPatchWidth = " << va.mPatchWidth << "n";
  220. s << "  mPatchOrder = " << va.mPatchOrder << "n";
  221. s << "  mRenderStridep = n";
  222. for (i=0; i<va.mPatchOrder+1; i++)
  223. {
  224. s << "    " << i << "    " << va.mRenderStridep[i] << "n";
  225. }
  226. s << "  mRenderLevelp = n";
  227. for (i=0; i < 2*va.mPatchWidth + 1; i++)
  228. {
  229. s << "    " << i << "    " << va.mRenderLevelp[i] << "n";
  230. }
  231. s << "}";
  232. return s;
  233. }
  234. // EOF