PageRenderTime 21ms CodeModel.GetById 1ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llpatchvertexarray.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 257 lines | 144 code | 28 blank | 85 comment | 24 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
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llpatchvertexarray.h"
 30#include "llsurfacepatch.h"
 31
 32// constructors
 33
 34LLPatchVertexArray::LLPatchVertexArray() :
 35	mSurfaceWidth(0),
 36	mPatchWidth(0),
 37	mPatchOrder(0),
 38	mRenderLevelp(NULL),
 39	mRenderStridep(NULL)
 40{
 41}
 42
 43LLPatchVertexArray::LLPatchVertexArray(U32 surface_width, U32 patch_width, F32 meters_per_grid) :
 44	mRenderLevelp(NULL),
 45	mRenderStridep(NULL)
 46{
 47	create(surface_width, patch_width, meters_per_grid);
 48}
 49
 50
 51LLPatchVertexArray::~LLPatchVertexArray() 
 52{
 53	destroy();
 54}
 55
 56
 57void LLPatchVertexArray::create(U32 surface_width, U32 patch_width, F32 meters_per_grid) 
 58{
 59	// PART 1 -- Make sure the arguments are good...
 60	// Make sure patch_width is not greater than surface_width
 61	if (patch_width > surface_width) 
 62	{
 63		U32 temp = patch_width;
 64		patch_width = surface_width;
 65		surface_width = temp;
 66	}
 67
 68	// Make sure (surface_width-1) is equal to a power_of_two.
 69	// (The -1 is there because an LLSurface has a buffer of 1 on 
 70	// its East and North edges).
 71	U32 power_of_two = 1;
 72	U32 surface_order = 0;
 73	while (power_of_two < (surface_width-1))
 74	{
 75		power_of_two *= 2;
 76		surface_order += 1;
 77	}
 78
 79	if (power_of_two == (surface_width-1))
 80	{
 81		mSurfaceWidth = surface_width;
 82
 83		// Make sure patch_width is a factor of (surface_width - 1)
 84		U32 ratio = (surface_width - 1) / patch_width;
 85		F32 fratio = ((float)(surface_width - 1)) / ((float)(patch_width));
 86		if ( fratio == (float)(ratio))
 87		{
 88			// Make sure patch_width is a power of two
 89			power_of_two = 1;
 90			U32 patch_order = 0;
 91			while (power_of_two < patch_width)
 92			{
 93				power_of_two *= 2;
 94				patch_order += 1;
 95			}
 96			if (power_of_two == patch_width)
 97			{
 98				mPatchWidth = patch_width;
 99				mPatchOrder = patch_order;
100			}
101			else // patch_width is not a power of two...
102			{
103				mPatchWidth = 0;
104				mPatchOrder = 0;
105			}
106		}
107		else // patch_width is not a factor of (surface_width - 1)...
108		{
109			mPatchWidth = 0;
110			mPatchOrder = 0;
111		}
112	}
113	else // surface_width is not a power of two...
114	{
115		mSurfaceWidth = 0;
116		mPatchWidth = 0;
117		mPatchOrder = 0;
118	}
119
120	// PART 2 -- Allocate memory for the render level table
121	if (mPatchWidth > 0) 
122	{
123		mRenderLevelp = new U32 [2*mPatchWidth + 1];
124		mRenderStridep = new U32 [mPatchOrder + 1];
125	}
126
127	if (NULL == mRenderLevelp || NULL == mRenderStridep)
128	{
129		// init() and some other things all want to deref these
130		// pointers, so this is serious.
131		llerrs << "mRenderLevelp or mRenderStridep was NULL; we'd crash soon." << llendl;
132		return;
133	}
134
135	// Now that we've allocated memory, we can initialize
136	// the arrays...
137	init();
138}
139
140
141void LLPatchVertexArray::destroy()
142{
143	if (mPatchWidth == 0)
144	{
145		return;
146	}
147
148	delete [] mRenderLevelp;
149	delete [] mRenderStridep;
150	mSurfaceWidth = 0;
151	mPatchWidth = 0;
152	mPatchOrder = 0;
153}
154
155
156void LLPatchVertexArray::init() 
157// Initializes the triangle strip arrays.
158{
159	U32 j;
160	U32 level, stride;
161	U32 k;
162
163	// We need to build two look-up tables... 
164
165	// render_level -> render_stride 
166	// A 16x16 patch has 5 render levels : 2^0 to 2^4
167	// render_level		render_stride
168	//		4				1
169	//		3				2
170	//		2				4
171	//		1				8
172	//		0				16
173	stride = mPatchWidth;
174	for (level=0; level<mPatchOrder + 1; level++)
175	{
176		mRenderStridep[level] = stride;
177		stride /= 2;
178	}
179
180	// render_level <- render_stride.
181/*
182	// For a 16x16 patch we'll clamp the render_strides to 0 through 16
183	// and enter the nearest render_level in the table.  Of course, only
184	// power-of-two render strides are actually used. 
185	//
186	// render_stride	render_level
187	//		0				4
188	//		1				4	*
189	//		2				3	*
190	//		3				3
191	//		4				2	*
192	//		5				2
193	//		6				2
194	//		7				1
195	//		8				1	*
196	//		9				1
197	//		10				1
198	//		11				1
199	//		12				1
200	//		13				0
201	//		14				0
202	//		15				0
203	//		16				Always 0
204
205	level = mPatchOrder;
206	for (stride=0; stride<mPatchWidth; stride++)
207	{
208		if ((F32) stride > 2.1f * mRenderStridep[level])
209		{
210			level--;	
211		};
212		mRenderLevelp[stride] = level;
213	}
214	*/
215
216	// This method is more agressive about putting triangles onscreen
217	level = mPatchOrder;
218	k = 2;
219	mRenderLevelp[0] = mPatchOrder;
220	mRenderLevelp[1] = mPatchOrder;
221	stride = 2;
222	while(stride < 2*mPatchWidth)
223	{
224		for (j=0; j<k  &&  stride<2*mPatchWidth; j++)
225		{
226			mRenderLevelp[stride++] = level;
227		}
228		k *= 2;
229		level--;	
230	}
231	mRenderLevelp[2*mPatchWidth] = 0;
232}
233
234
235std::ostream& operator<<(std::ostream &s, const LLPatchVertexArray &va)
236{
237	U32 i;
238	s << "{ \n";
239	s << "  mSurfaceWidth = " << va.mSurfaceWidth << "\n";
240	s << "  mPatchWidth = " << va.mPatchWidth << "\n";
241	s << "  mPatchOrder = " << va.mPatchOrder << "\n";
242	s << "  mRenderStridep = \n";
243	for (i=0; i<va.mPatchOrder+1; i++)
244	{
245		s << "    " << i << "    " << va.mRenderStridep[i] << "\n";
246	}
247	s << "  mRenderLevelp = \n";
248	for (i=0; i < 2*va.mPatchWidth + 1; i++)
249	{
250		s << "    " << i << "    " << va.mRenderLevelp[i] << "\n";
251	}
252	s << "}";	
253	return s;
254}
255
256
257// EOF