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