aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llpatchvertexarray.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llpatchvertexarray.cpp')
-rw-r--r--linden/indra/newview/llpatchvertexarray.cpp250
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
35LLPatchVertexArray::LLPatchVertexArray() :
36 mSurfaceWidth(0),
37 mPatchWidth(0),
38 mPatchOrder(0),
39 mRenderLevelp(NULL),
40 mRenderStridep(NULL)
41{
42}
43
44LLPatchVertexArray::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
52LLPatchVertexArray::~LLPatchVertexArray()
53{
54 destroy();
55}
56
57
58void 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
134void 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
149void 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
228std::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