PageRenderTime 169ms CodeModel.GetById 38ms app.highlight 117ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llface.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2472 lines | 1890 code | 378 blank | 204 comment | 310 complexity | 5eb7f045053bb5b3bac2320a7edd0b1d MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/** 
   2 * @file llface.cpp
   3 * @brief LLFace class implementation
   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 "lldrawable.h" // lldrawable needs to be included before llface
  30#include "llface.h"
  31#include "llviewertextureanim.h"
  32
  33#include "llviewercontrol.h"
  34#include "llvolume.h"
  35#include "m3math.h"
  36#include "llmatrix4a.h"
  37#include "v3color.h"
  38
  39#include "lldrawpoolavatar.h"
  40#include "lldrawpoolbump.h"
  41#include "llgl.h"
  42#include "llrender.h"
  43#include "lllightconstants.h"
  44#include "llsky.h"
  45#include "llviewercamera.h"
  46#include "llviewertexturelist.h"
  47#include "llvosky.h"
  48#include "llvovolume.h"
  49#include "pipeline.h"
  50#include "llviewerregion.h"
  51#include "llviewerwindow.h"
  52
  53#define LL_MAX_INDICES_COUNT 1000000
  54
  55BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE
  56
  57#define DOTVEC(a,b) (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2])
  58
  59
  60/*
  61For each vertex, given:
  62	B - binormal
  63	T - tangent
  64	N - normal
  65	P - position
  66
  67The resulting texture coordinate <u,v> is:
  68
  69	u = 2(B dot P)
  70	v = 2(T dot P)
  71*/
  72void planarProjection(LLVector2 &tc, const LLVector4a& normal,
  73					  const LLVector4a &center, const LLVector4a& vec)
  74{	
  75	LLVector4a binormal;
  76	F32 d = normal[0];
  77
  78	if (d >= 0.5f || d <= -0.5f)
  79	{
  80		if (d < 0)
  81		{
  82			binormal.set(0,-1,0);
  83		}
  84		else
  85		{
  86			binormal.set(0, 1, 0);
  87		}
  88	}
  89	else
  90	{
  91        if (normal[1] > 0)
  92		{
  93			binormal.set(-1,0,0);
  94		}
  95		else
  96		{
  97			binormal.set(1,0,0);
  98		}
  99	}
 100	LLVector4a tangent;
 101	tangent.setCross3(binormal,normal);
 102
 103	tc.mV[1] = -((tangent.dot3(vec).getF32())*2 - 0.5f);
 104	tc.mV[0] = 1.0f+((binormal.dot3(vec).getF32())*2 - 0.5f);
 105}
 106
 107void sphericalProjection(LLVector2 &tc, const LLVector4a& normal,
 108						 const LLVector4a &mCenter, const LLVector4a& vec)
 109{	//BROKEN
 110	/*tc.mV[0] = acosf(vd.mNormal * LLVector3(1,0,0))/3.14159f;
 111	
 112	tc.mV[1] = acosf(vd.mNormal * LLVector3(0,0,1))/6.284f;
 113	if (vd.mNormal.mV[1] > 0)
 114	{
 115		tc.mV[1] = 1.0f-tc.mV[1];
 116	}*/
 117}
 118
 119void cylindricalProjection(LLVector2 &tc, const LLVector4a& normal, const LLVector4a &mCenter, const LLVector4a& vec)
 120{	//BROKEN
 121	/*LLVector3 binormal;
 122	float d = vd.mNormal * LLVector3(1,0,0);
 123	if (d >= 0.5f || d <= -0.5f)
 124	{
 125		binormal = LLVector3(0,1,0);
 126	}
 127	else{
 128		binormal = LLVector3(1,0,0);
 129	}
 130	LLVector3 tangent = binormal % vd.mNormal;
 131
 132	tc.mV[1] = -((tangent*vec)*2 - 0.5f);
 133
 134	tc.mV[0] = acosf(vd.mNormal * LLVector3(1,0,0))/6.284f;
 135
 136	if (vd.mNormal.mV[1] < 0)
 137	{
 138		tc.mV[0] = 1.0f-tc.mV[0];
 139	}*/
 140}
 141
 142////////////////////
 143//
 144// LLFace implementation
 145//
 146
 147void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
 148{
 149	mLastUpdateTime = gFrameTimeSeconds;
 150	mLastMoveTime = 0.f;
 151	mLastSkinTime = gFrameTimeSeconds;
 152	mVSize = 0.f;
 153	mPixelArea = 16.f;
 154	mState      = GLOBAL;
 155	mDrawPoolp  = NULL;
 156	mPoolType = 0;
 157	mCenterLocal = objp->getPosition();
 158	mCenterAgent = drawablep->getPositionAgent();
 159	mDistance	= 0.f;
 160
 161	mGeomCount		= 0;
 162	mGeomIndex		= 0;
 163	mIndicesCount	= 0;
 164	mIndicesIndex	= 0;
 165	mIndexInTex = 0;
 166	mTexture		= NULL;
 167	mTEOffset		= -1;
 168	mTextureIndex = 255;
 169
 170	setDrawable(drawablep);
 171	mVObjp = objp;
 172
 173	mReferenceIndex = -1;
 174
 175	mTextureMatrix = NULL;
 176	mDrawInfo = NULL;
 177
 178	mFaceColor = LLColor4(1,0,0,1);
 179
 180	mLastVertexBuffer = mVertexBuffer;
 181	mLastGeomCount = mGeomCount;
 182	mLastGeomIndex = mGeomIndex;
 183	mLastIndicesCount = mIndicesCount;
 184	mLastIndicesIndex = mIndicesIndex;
 185
 186	mImportanceToCamera = 0.f ;
 187	mBoundingSphereRadius = 0.0f ;
 188
 189	mAtlasInfop = NULL ;
 190	mUsingAtlas  = FALSE ;
 191	mHasMedia = FALSE ;
 192}
 193
 194void LLFace::destroy()
 195{
 196	if (gDebugGL)
 197	{
 198		gPipeline.checkReferences(this);
 199	}
 200
 201	if(mTexture.notNull())
 202	{
 203		mTexture->removeFace(this) ;
 204	}
 205	
 206	if (mDrawPoolp)
 207	{
 208		if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR)
 209		{
 210			((LLDrawPoolAvatar*) mDrawPoolp)->removeRiggedFace(this);
 211		}
 212		else
 213		{
 214			mDrawPoolp->removeFace(this);
 215		}
 216	
 217		mDrawPoolp = NULL;
 218	}
 219
 220	if (mTextureMatrix)
 221	{
 222		delete mTextureMatrix;
 223		mTextureMatrix = NULL;
 224
 225		if (mDrawablep.notNull())
 226		{
 227			LLSpatialGroup* group = mDrawablep->getSpatialGroup();
 228			if (group)
 229			{
 230				group->dirtyGeom();
 231				gPipeline.markRebuild(group, TRUE);
 232			}
 233		}
 234	}
 235	
 236	setDrawInfo(NULL);
 237	removeAtlas();
 238		
 239	mDrawablep = NULL;
 240	mVObjp = NULL;
 241}
 242
 243
 244// static
 245void LLFace::initClass()
 246{
 247}
 248
 249void LLFace::setWorldMatrix(const LLMatrix4 &mat)
 250{
 251	llerrs << "Faces on this drawable are not independently modifiable\n" << llendl;
 252}
 253
 254void LLFace::setPool(LLFacePool* pool)
 255{
 256	mDrawPoolp = pool;
 257}
 258
 259void LLFace::setPool(LLFacePool* new_pool, LLViewerTexture *texturep)
 260{
 261	LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
 262	
 263	if (!new_pool)
 264	{
 265		llerrs << "Setting pool to null!" << llendl;
 266	}
 267
 268	if (new_pool != mDrawPoolp)
 269	{
 270		// Remove from old pool
 271		if (mDrawPoolp)
 272		{
 273			mDrawPoolp->removeFace(this);
 274
 275			if (mDrawablep)
 276			{
 277				gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_ALL, TRUE);
 278			}
 279		}
 280		mGeomIndex = 0;
 281
 282		// Add to new pool
 283		if (new_pool)
 284		{
 285			new_pool->addFace(this);
 286		}
 287		mDrawPoolp = new_pool;
 288	}
 289	
 290	setTexture(texturep) ;
 291}
 292
 293void LLFace::setTexture(LLViewerTexture* tex) 
 294{
 295	if(mTexture == tex)
 296	{
 297		return ;
 298	}
 299
 300	if(mTexture.notNull())
 301	{
 302		mTexture->removeFace(this) ;
 303		removeAtlas() ;
 304	}	
 305	
 306	if(tex)
 307	{
 308		tex->addFace(this) ;
 309	}
 310
 311	mTexture = tex ;
 312}
 313
 314void LLFace::dirtyTexture()
 315{
 316	gPipeline.markTextured(getDrawable());
 317}
 318
 319void LLFace::switchTexture(LLViewerTexture* new_texture)
 320{
 321	if(mTexture == new_texture)
 322	{
 323		return ;
 324	}
 325
 326	if(!new_texture)
 327	{
 328		llerrs << "Can not switch to a null texture." << llendl;
 329		return;
 330	}
 331	new_texture->addTextureStats(mTexture->getMaxVirtualSize()) ;
 332
 333	getViewerObject()->changeTEImage(mTEOffset, new_texture) ;
 334	setTexture(new_texture) ;	
 335	dirtyTexture();
 336}
 337
 338void LLFace::setTEOffset(const S32 te_offset)
 339{
 340	mTEOffset = te_offset;
 341}
 342
 343
 344void LLFace::setFaceColor(const LLColor4& color)
 345{
 346	mFaceColor = color;
 347	setState(USE_FACE_COLOR);
 348}
 349
 350void LLFace::unsetFaceColor()
 351{
 352	clearState(USE_FACE_COLOR);
 353}
 354
 355void LLFace::setDrawable(LLDrawable *drawable)
 356{
 357	mDrawablep  = drawable;
 358	mXform      = &drawable->mXform;
 359}
 360
 361void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align)
 362{
 363	if (align)
 364	{
 365		//allocate vertices in blocks of 4 for alignment
 366		num_vertices = (num_vertices + 0x3) & ~0x3;
 367	}
 368	
 369	if (mGeomCount != num_vertices ||
 370		mIndicesCount != num_indices)
 371	{
 372		mGeomCount    = num_vertices;
 373		mIndicesCount = num_indices;
 374		mVertexBuffer = NULL;
 375		mLastVertexBuffer = NULL;
 376	}
 377
 378	llassert(verify());
 379}
 380
 381void LLFace::setGeomIndex(U16 idx) 
 382{ 
 383	if (mGeomIndex != idx)
 384	{
 385		mGeomIndex = idx; 
 386		mVertexBuffer = NULL;
 387	}
 388}
 389
 390void LLFace::setTextureIndex(U8 index)
 391{
 392	if (index != mTextureIndex)
 393	{
 394		mTextureIndex = index;
 395
 396		if (mTextureIndex != 255)
 397		{
 398			mDrawablep->setState(LLDrawable::REBUILD_POSITION);
 399		}
 400		else
 401		{
 402			if (mDrawInfo && !mDrawInfo->mTextureList.empty())
 403			{
 404				llerrs << "Face with no texture index references indexed texture draw info." << llendl;
 405			}
 406		}
 407	}
 408}
 409
 410void LLFace::setIndicesIndex(S32 idx) 
 411{ 
 412	if (mIndicesIndex != idx)
 413	{
 414		mIndicesIndex = idx; 
 415		mVertexBuffer = NULL;
 416	}
 417}
 418	
 419//============================================================================
 420
 421U16 LLFace::getGeometryAvatar(
 422						LLStrider<LLVector3> &vertices,
 423						LLStrider<LLVector3> &normals,
 424						LLStrider<LLVector2> &tex_coords,
 425						LLStrider<F32>		 &vertex_weights,
 426						LLStrider<LLVector4> &clothing_weights)
 427{
 428	LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
 429
 430	if (mVertexBuffer.notNull())
 431	{
 432		mVertexBuffer->getVertexStrider      (vertices, mGeomIndex, mGeomCount);
 433		mVertexBuffer->getNormalStrider      (normals, mGeomIndex, mGeomCount);
 434		mVertexBuffer->getTexCoord0Strider    (tex_coords, mGeomIndex, mGeomCount);
 435		mVertexBuffer->getWeightStrider(vertex_weights, mGeomIndex, mGeomCount);
 436		mVertexBuffer->getClothWeightStrider(clothing_weights, mGeomIndex, mGeomCount);
 437	}
 438
 439	return mGeomIndex;
 440}
 441
 442U16 LLFace::getGeometry(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &normals,
 443					    LLStrider<LLVector2> &tex_coords, LLStrider<U16> &indicesp)
 444{
 445	LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
 446	
 447	if (mVertexBuffer.notNull())
 448	{
 449		mVertexBuffer->getVertexStrider(vertices,   mGeomIndex, mGeomCount);
 450		if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL))
 451		{
 452			mVertexBuffer->getNormalStrider(normals,    mGeomIndex, mGeomCount);
 453		}
 454		if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD0))
 455		{
 456			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount);
 457		}
 458
 459		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount);
 460	}
 461	
 462	return mGeomIndex;
 463}
 464
 465void LLFace::updateCenterAgent()
 466{
 467	if (mDrawablep->isActive())
 468	{
 469		mCenterAgent = mCenterLocal * getRenderMatrix();
 470	}
 471	else
 472	{
 473		mCenterAgent = mCenterLocal;
 474	}
 475}
 476
 477void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
 478{
 479	if (mDrawablep->getSpatialGroup() == NULL)
 480	{
 481		return;
 482	}
 483
 484	mDrawablep->getSpatialGroup()->rebuildGeom();
 485	mDrawablep->getSpatialGroup()->rebuildMesh();
 486		
 487	if(mDrawablep.isNull() || mVertexBuffer.isNull())
 488	{
 489		return;
 490	}
 491
 492	if (mGeomCount > 0 && mIndicesCount > 0)
 493	{
 494		gGL.getTexUnit(0)->bind(imagep);
 495	
 496		gGL.pushMatrix();
 497		if (mDrawablep->isActive())
 498		{
 499			gGL.multMatrix((GLfloat*)mDrawablep->getRenderMatrix().mMatrix);
 500		}
 501		else
 502		{
 503			gGL.multMatrix((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix);
 504		}
 505
 506		gGL.diffuseColor4fv(color.mV);
 507	
 508		if (mDrawablep->isState(LLDrawable::RIGGED))
 509		{
 510			LLVOVolume* volume = mDrawablep->getVOVolume();
 511			if (volume)
 512			{
 513				LLRiggedVolume* rigged = volume->getRiggedVolume();
 514				if (rigged)
 515				{
 516					LLGLEnable offset(GL_POLYGON_OFFSET_FILL);
 517					glPolygonOffset(-1.f, -1.f);
 518					gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix);
 519					const LLVolumeFace& vol_face = rigged->getVolumeFace(getTEOffset());
 520					LLVertexBuffer::unbind();
 521					glVertexPointer(3, GL_FLOAT, 16, vol_face.mPositions);
 522					if (vol_face.mTexCoords)
 523					{
 524						glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 525						glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords);
 526					}
 527					gGL.syncMatrices();
 528					glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices);
 529					glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 530				}
 531			}
 532		}
 533		else
 534		{
 535			mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
 536			mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
 537		}
 538
 539		gGL.popMatrix();
 540	}
 541}
 542
 543
 544/* removed in lieu of raycast uv detection
 545void LLFace::renderSelectedUV()
 546{
 547	LLViewerTexture* red_blue_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test1.j2c", TRUE, LLViewerTexture::BOOST_UI);
 548	LLViewerTexture* green_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test2.tga", TRUE, LLViewerTexture::BOOST_UI);
 549
 550	LLGLSUVSelect object_select;
 551
 552	// use red/blue gradient to get coarse UV coordinates
 553	renderSelected(red_blue_imagep, LLColor4::white);
 554	
 555	static F32 bias = 0.f;
 556	static F32 factor = -10.f;
 557	glPolygonOffset(factor, bias);
 558
 559	// add green dither pattern on top of red/blue gradient
 560	gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_ONE);
 561	gGL.matrixMode(LLRender::MM_TEXTURE);
 562	gGL.pushMatrix();
 563	// make green pattern repeat once per texel in red/blue texture
 564	gGL.scalef(256.f, 256.f, 1.f);
 565	gGL.matrixMode(LLRender::MM_MODELVIEW);
 566
 567	renderSelected(green_imagep, LLColor4::white);
 568
 569	gGL.matrixMode(LLRender::MM_TEXTURE);
 570	gGL.popMatrix();
 571	gGL.matrixMode(LLRender::MM_MODELVIEW);
 572	gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
 573}
 574*/
 575
 576void LLFace::setDrawInfo(LLDrawInfo* draw_info)
 577{
 578	if (draw_info)
 579	{
 580		if (draw_info->mFace)
 581		{
 582			draw_info->mFace->setDrawInfo(NULL);
 583		}
 584		draw_info->mFace = this;
 585	}
 586	
 587	if (mDrawInfo)
 588	{
 589		mDrawInfo->mFace = NULL;
 590	}
 591
 592	mDrawInfo = draw_info;
 593}
 594
 595void LLFace::printDebugInfo() const
 596{
 597	LLFacePool *poolp = getPool();
 598	llinfos << "Object: " << getViewerObject()->mID << llendl;
 599	if (getDrawable())
 600	{
 601		llinfos << "Type: " << LLPrimitive::pCodeToString(getDrawable()->getVObj()->getPCode()) << llendl;
 602	}
 603	if (getTexture())
 604	{
 605		llinfos << "Texture: " << getTexture() << " Comps: " << (U32)getTexture()->getComponents() << llendl;
 606	}
 607	else
 608	{
 609		llinfos << "No texture: " << llendl;
 610	}
 611
 612	llinfos << "Face: " << this << llendl;
 613	llinfos << "State: " << getState() << llendl;
 614	llinfos << "Geom Index Data:" << llendl;
 615	llinfos << "--------------------" << llendl;
 616	llinfos << "GI: " << mGeomIndex << " Count:" << mGeomCount << llendl;
 617	llinfos << "Face Index Data:" << llendl;
 618	llinfos << "--------------------" << llendl;
 619	llinfos << "II: " << mIndicesIndex << " Count:" << mIndicesCount << llendl;
 620	llinfos << llendl;
 621
 622	if (poolp)
 623	{
 624		poolp->printDebugInfo();
 625
 626		S32 pool_references = 0;
 627		for (std::vector<LLFace*>::iterator iter = poolp->mReferences.begin();
 628			 iter != poolp->mReferences.end(); iter++)
 629		{
 630			LLFace *facep = *iter;
 631			if (facep == this)
 632			{
 633				llinfos << "Pool reference: " << pool_references << llendl;
 634				pool_references++;
 635			}
 636		}
 637
 638		if (pool_references != 1)
 639		{
 640			llinfos << "Incorrect number of pool references!" << llendl;
 641		}
 642	}
 643
 644#if 0
 645	llinfos << "Indices:" << llendl;
 646	llinfos << "--------------------" << llendl;
 647
 648	const U32 *indicesp = getRawIndices();
 649	S32 indices_count = getIndicesCount();
 650	S32 geom_start = getGeomStart();
 651
 652	for (S32 i = 0; i < indices_count; i++)
 653	{
 654		llinfos << i << ":" << indicesp[i] << ":" << (S32)(indicesp[i] - geom_start) << llendl;
 655	}
 656	llinfos << llendl;
 657
 658	llinfos << "Vertices:" << llendl;
 659	llinfos << "--------------------" << llendl;
 660	for (S32 i = 0; i < mGeomCount; i++)
 661	{
 662		llinfos << mGeomIndex + i << ":" << poolp->getVertex(mGeomIndex + i) << llendl;
 663	}
 664	llinfos << llendl;
 665#endif
 666}
 667
 668// Transform the texture coordinates for this face.
 669static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 offT, F32 magS, F32 magT)
 670{
 671	// New, good way
 672	F32 s = tex_coord.mV[0];
 673	F32 t = tex_coord.mV[1];
 674
 675	// Texture transforms are done about the center of the face.
 676	s -= 0.5; 
 677	t -= 0.5;
 678
 679	// Handle rotation
 680	F32 temp = s;
 681	s  = s     * cosAng + t * sinAng;
 682	t  = -temp * sinAng + t * cosAng;
 683
 684	// Then scale
 685	s *= magS;
 686	t *= magT;
 687
 688	// Then offset
 689	s += offS + 0.5f; 
 690	t += offT + 0.5f;
 691
 692	tex_coord.mV[0] = s;
 693	tex_coord.mV[1] = t;
 694}
 695
 696
 697bool less_than_max_mag(const LLVector4a& vec)
 698{
 699	LLVector4a MAX_MAG;
 700	MAX_MAG.splat(1024.f*1024.f);
 701
 702	LLVector4a val;
 703	val.setAbs(vec);
 704
 705	S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7;
 706	
 707	return lt == 0x7;
 708}
 709
 710BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 711								const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume)
 712{
 713	LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
 714
 715	//get bounding box
 716	if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED))
 717	{
 718		//VECTORIZE THIS
 719		LLMatrix4a mat_vert;
 720		mat_vert.loadu(mat_vert_in);
 721
 722		LLMatrix4a mat_normal;
 723		mat_normal.loadu(mat_normal_in);
 724
 725		//if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME))
 726		//{ //vertex buffer no longer valid
 727		//	mVertexBuffer = NULL;
 728		//	mLastVertexBuffer = NULL;
 729		//}
 730
 731		//VECTORIZE THIS
 732		LLVector4a min,max;
 733	
 734		if (f >= volume.getNumVolumeFaces())
 735		{
 736			llwarns << "Generating bounding box for invalid face index!" << llendl;
 737			f = 0;
 738		}
 739
 740		const LLVolumeFace &face = volume.getVolumeFace(f);
 741		min = face.mExtents[0];
 742		max = face.mExtents[1];
 743		
 744		llassert(less_than_max_mag(min));
 745		llassert(less_than_max_mag(max));
 746
 747		//min, max are in volume space, convert to drawable render space
 748		LLVector4a center;
 749		LLVector4a t;
 750		t.setAdd(min, max);
 751		t.mul(0.5f);
 752		mat_vert.affineTransform(t, center);
 753		LLVector4a size;
 754		size.setSub(max, min);
 755		size.mul(0.5f);
 756
 757		llassert(less_than_max_mag(min));
 758		llassert(less_than_max_mag(max));
 759
 760		if (!global_volume)
 761		{
 762			//VECTORIZE THIS
 763			LLVector4a scale;
 764			scale.load3(mDrawablep->getVObj()->getScale().mV);
 765			size.mul(scale);
 766		}
 767
 768		mat_normal.mMatrix[0].normalize3fast();
 769		mat_normal.mMatrix[1].normalize3fast();
 770		mat_normal.mMatrix[2].normalize3fast();
 771		
 772		LLVector4a v[4];
 773
 774		//get 4 corners of bounding box
 775		mat_normal.rotate(size,v[0]);
 776
 777		//VECTORIZE THIS
 778		LLVector4a scale;
 779		
 780		scale.set(-1.f, -1.f, 1.f);
 781		scale.mul(size);
 782		mat_normal.rotate(scale, v[1]);
 783		
 784		scale.set(1.f, -1.f, -1.f);
 785		scale.mul(size);
 786		mat_normal.rotate(scale, v[2]);
 787		
 788		scale.set(-1.f, 1.f, -1.f);
 789		scale.mul(size);
 790		mat_normal.rotate(scale, v[3]);
 791
 792		LLVector4a& newMin = mExtents[0];
 793		LLVector4a& newMax = mExtents[1];
 794		
 795		newMin = newMax = center;
 796		
 797		llassert(less_than_max_mag(center));
 798		
 799		for (U32 i = 0; i < 4; i++)
 800		{
 801			LLVector4a delta;
 802			delta.setAbs(v[i]);
 803			LLVector4a min;
 804			min.setSub(center, delta);
 805			LLVector4a max;
 806			max.setAdd(center, delta);
 807
 808			newMin.setMin(newMin,min);
 809			newMax.setMax(newMax,max);
 810
 811			llassert(less_than_max_mag(newMin));
 812			llassert(less_than_max_mag(newMax));
 813		}
 814
 815		if (!mDrawablep->isActive())
 816		{
 817			LLVector4a offset;
 818			offset.load3(mDrawablep->getRegion()->getOriginAgent().mV);
 819			newMin.add(offset);
 820			newMax.add(offset);
 821			
 822			llassert(less_than_max_mag(newMin));
 823			llassert(less_than_max_mag(newMax));
 824		}
 825
 826		t.setAdd(newMin, newMax);
 827		t.mul(0.5f);
 828
 829		llassert(less_than_max_mag(t));
 830		
 831		//VECTORIZE THIS
 832		mCenterLocal.set(t.getF32ptr());
 833		
 834		llassert(less_than_max_mag(newMin));
 835		llassert(less_than_max_mag(newMax));
 836
 837		t.setSub(newMax,newMin);
 838		mBoundingSphereRadius = t.getLength3().getF32()*0.5f;
 839
 840		updateCenterAgent();
 841	}
 842
 843	return TRUE;
 844}
 845
 846
 847
 848// convert surface coordinates to texture coordinates, based on
 849// the values in the texture entry.  probably should be
 850// integrated with getGeometryVolume() for its texture coordinate
 851// generation - but i'll leave that to someone more familiar
 852// with the implications.
 853LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, LLVector3 position, LLVector3 normal)
 854{
 855	LLVector2 tc = surface_coord;
 856	
 857	const LLTextureEntry *tep = getTextureEntry();
 858
 859	if (tep == NULL)
 860	{
 861		// can't do much without the texture entry
 862		return surface_coord;
 863	}
 864
 865	//VECTORIZE THIS
 866	// see if we have a non-default mapping
 867    U8 texgen = getTextureEntry()->getTexGen();
 868	if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
 869	{
 870		LLVector4a& center = *(mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter);
 871		
 872		LLVector4a volume_position;
 873		volume_position.load3(mDrawablep->getVOVolume()->agentPositionToVolume(position).mV);
 874		
 875		if (!mDrawablep->getVOVolume()->isVolumeGlobal())
 876		{
 877			LLVector4a scale;
 878			scale.load3(mVObjp->getScale().mV);
 879			volume_position.mul(scale);
 880		}
 881		
 882		LLVector4a volume_normal;
 883		volume_normal.load3(mDrawablep->getVOVolume()->agentDirectionToVolume(normal).mV);
 884		volume_normal.normalize3fast();
 885		
 886		switch (texgen)
 887		{
 888		case LLTextureEntry::TEX_GEN_PLANAR:
 889			planarProjection(tc, volume_normal, center, volume_position);
 890			break;
 891		case LLTextureEntry::TEX_GEN_SPHERICAL:
 892			sphericalProjection(tc, volume_normal, center, volume_position);
 893			break;
 894		case LLTextureEntry::TEX_GEN_CYLINDRICAL:
 895			cylindricalProjection(tc, volume_normal, center, volume_position);
 896			break;
 897		default:
 898			break;
 899		}		
 900	}
 901
 902	if (mTextureMatrix)	// if we have a texture matrix, use it
 903	{
 904		LLVector3 tc3(tc);
 905		tc3 = tc3 * *mTextureMatrix;
 906		tc = LLVector2(tc3);
 907	}
 908	
 909	else // otherwise use the texture entry parameters
 910	{
 911		xform(tc, cos(tep->getRotation()), sin(tep->getRotation()),
 912			  tep->mOffsetS, tep->mOffsetT, tep->mScaleS, tep->mScaleT);
 913	}
 914
 915	
 916	return tc;
 917}
 918
 919// Returns scale compared to default texgen, and face orientation as calculated
 920// by planarProjection(). This is needed to match planar texgen parameters.
 921void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_pos, F32* scale) const
 922{
 923	const LLMatrix4& vol_mat = getWorldMatrix();
 924	const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset);
 925	const LLVector4a& normal4a = vf.mNormals[0];
 926	const LLVector4a& binormal4a = vf.mBinormals[0];
 927	LLVector2 projected_binormal;
 928	planarProjection(projected_binormal, normal4a, *vf.mCenter, binormal4a);
 929	projected_binormal -= LLVector2(0.5f, 0.5f); // this normally happens in xform()
 930	*scale = projected_binormal.length();
 931	// rotate binormal to match what planarProjection() thinks it is,
 932	// then find rotation from that:
 933	projected_binormal.normalize();
 934	F32 ang = acos(projected_binormal.mV[VY]);
 935	ang = (projected_binormal.mV[VX] < 0.f) ? -ang : ang;
 936
 937	//VECTORIZE THIS
 938	LLVector3 binormal(binormal4a.getF32ptr());
 939	LLVector3 normal(normal4a.getF32ptr());
 940	binormal.rotVec(ang, normal);
 941	LLQuaternion local_rot( binormal % normal, binormal, normal );
 942	*face_rot = local_rot * vol_mat.quaternion();
 943	*face_pos = vol_mat.getTranslation();
 944}
 945
 946// Returns the necessary texture transform to align this face's TE to align_to's TE
 947bool LLFace::calcAlignedPlanarTE(const LLFace* align_to,  LLVector2* res_st_offset, 
 948								 LLVector2* res_st_scale, F32* res_st_rot) const
 949{
 950	if (!align_to)
 951	{
 952		return false;
 953	}
 954	const LLTextureEntry *orig_tep = align_to->getTextureEntry();
 955	if ((orig_tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR) ||
 956		(getTextureEntry()->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR))
 957	{
 958		return false;
 959	}
 960
 961	LLVector3 orig_pos, this_pos;
 962	LLQuaternion orig_face_rot, this_face_rot;
 963	F32 orig_proj_scale, this_proj_scale;
 964	align_to->getPlanarProjectedParams(&orig_face_rot, &orig_pos, &orig_proj_scale);
 965	getPlanarProjectedParams(&this_face_rot, &this_pos, &this_proj_scale);
 966
 967	// The rotation of "this face's" texture:
 968	LLQuaternion orig_st_rot = LLQuaternion(orig_tep->getRotation(), LLVector3::z_axis) * orig_face_rot;
 969	LLQuaternion this_st_rot = orig_st_rot * ~this_face_rot;
 970	F32 x_ang, y_ang, z_ang;
 971	this_st_rot.getEulerAngles(&x_ang, &y_ang, &z_ang);
 972	*res_st_rot = z_ang;
 973
 974	// Offset and scale of "this face's" texture:
 975	LLVector3 centers_dist = (this_pos - orig_pos) * ~orig_st_rot;
 976	LLVector3 st_scale(orig_tep->mScaleS, orig_tep->mScaleT, 1.f);
 977	st_scale *= orig_proj_scale;
 978	centers_dist.scaleVec(st_scale);
 979	LLVector2 orig_st_offset(orig_tep->mOffsetS, orig_tep->mOffsetT);
 980
 981	*res_st_offset = orig_st_offset + (LLVector2)centers_dist;
 982	res_st_offset->mV[VX] -= (S32)res_st_offset->mV[VX];
 983	res_st_offset->mV[VY] -= (S32)res_st_offset->mV[VY];
 984
 985	st_scale /= this_proj_scale;
 986	*res_st_scale = (LLVector2)st_scale;
 987	return true;
 988}
 989
 990void LLFace::updateRebuildFlags()
 991{
 992	if (!mDrawablep->isState(LLDrawable::REBUILD_VOLUME))
 993	{
 994		BOOL moved = TRUE;
 995		if (mLastVertexBuffer == mVertexBuffer && 
 996			!mVertexBuffer->isEmpty())
 997		{	//this face really doesn't need to be regenerated, try real hard not to do so
 998			if (mLastGeomCount == mGeomCount &&
 999				mLastGeomIndex == mGeomIndex &&
1000				mLastIndicesCount == mIndicesCount &&
1001				mLastIndicesIndex == mIndicesIndex)
1002			{ //data is in same location in vertex buffer
1003				moved = FALSE;
1004			}
1005		}
1006		mLastMoveTime = gFrameTimeSeconds;
1007		
1008		if (moved)
1009		{
1010			mDrawablep->setState(LLDrawable::REBUILD_VOLUME);
1011		}
1012	}
1013	else
1014	{
1015		mLastUpdateTime = gFrameTimeSeconds;
1016	}
1017}
1018
1019
1020bool LLFace::canRenderAsMask()
1021{
1022	if (LLPipeline::sNoAlpha)
1023	{
1024		return true;
1025	}
1026
1027	const LLTextureEntry* te = getTextureEntry();
1028
1029	if ((te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha
1030		(te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask
1031		getTexture()->getIsAlphaMask()) // texture actually qualifies for masking (lazily recalculated but expensive)
1032	{
1033		if (LLPipeline::sRenderDeferred)
1034		{
1035			if (getViewerObject()->isHUDAttachment() || te->getFullbright())
1036			{ //hud attachments and fullbright objects are NOT subject to the deferred rendering pipe
1037				return LLPipeline::sAutoMaskAlphaNonDeferred;
1038			}
1039			else
1040			{
1041				return LLPipeline::sAutoMaskAlphaDeferred;
1042			}
1043		}
1044		else
1045		{
1046			return LLPipeline::sAutoMaskAlphaNonDeferred;
1047		}
1048	}
1049
1050	return false;
1051}
1052
1053
1054static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom");
1055static LLFastTimer::DeclareTimer FTM_FACE_GEOM_POSITION("Position");
1056static LLFastTimer::DeclareTimer FTM_FACE_GEOM_NORMAL("Normal");
1057static LLFastTimer::DeclareTimer FTM_FACE_GEOM_TEXTURE("Texture");
1058static LLFastTimer::DeclareTimer FTM_FACE_GEOM_COLOR("Color");
1059static LLFastTimer::DeclareTimer FTM_FACE_GEOM_EMISSIVE("Emissive");
1060static LLFastTimer::DeclareTimer FTM_FACE_GEOM_WEIGHTS("Weights");
1061static LLFastTimer::DeclareTimer FTM_FACE_GEOM_BINORMAL("Binormal");
1062static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX("Index");
1063
1064BOOL LLFace::getGeometryVolume(const LLVolume& volume,
1065							   const S32 &f,
1066								const LLMatrix4& mat_vert_in, const LLMatrix3& mat_norm_in,
1067								const U16 &index_offset,
1068								bool force_rebuild)
1069{
1070	LLFastTimer t(FTM_FACE_GET_GEOM);
1071	llassert(verify());
1072	const LLVolumeFace &vf = volume.getVolumeFace(f);
1073	S32 num_vertices = (S32)vf.mNumVertices;
1074	S32 num_indices = (S32) vf.mNumIndices;
1075	
1076	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
1077	{
1078		updateRebuildFlags();
1079	}
1080
1081	bool map_range = gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange;
1082
1083	if (mVertexBuffer.notNull())
1084	{
1085		if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices())
1086		{
1087			llwarns	<< "Index buffer overflow!" << llendl;
1088			llwarns << "Indices Count: " << mIndicesCount
1089					<< " VF Num Indices: " << num_indices
1090					<< " Indices Index: " << mIndicesIndex
1091					<< " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl;
1092			llwarns	<< "Last Indices Count: " << mLastIndicesCount
1093					<< " Last Indices Index: " << mLastIndicesIndex
1094					<< " Face Index: " << f
1095					<< " Pool Type: " << mPoolType << llendl;
1096			return FALSE;
1097		}
1098
1099		if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts())
1100		{
1101			llwarns << "Vertex buffer overflow!" << llendl;
1102			return FALSE;
1103		}
1104	}
1105
1106	LLStrider<LLVector3> vert;
1107	LLVector4a* vertices = NULL;
1108	LLStrider<LLVector2> tex_coords;
1109	LLStrider<LLVector2> tex_coords2;
1110	LLVector4a* normals = NULL;
1111	LLStrider<LLVector3> norm;
1112	LLStrider<LLColor4U> colors;
1113	LLVector4a* binormals = NULL;
1114	LLStrider<LLVector3> binorm;
1115	LLStrider<U16> indicesp;
1116	LLVector4a* weights = NULL;
1117	LLStrider<LLVector4> wght;
1118
1119	BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME);
1120	
1121	BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal();
1122	LLVector3 scale;
1123	if (global_volume)
1124	{
1125		scale.setVec(1,1,1);
1126	}
1127	else
1128	{
1129		scale = mVObjp->getScale();
1130	}
1131	
1132	bool rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION);
1133	bool rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR);
1134	bool rebuild_emissive = rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE);
1135	bool rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD);
1136	bool rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
1137	bool rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL);
1138	bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4);
1139
1140	const LLTextureEntry *tep = mVObjp->getTE(f);
1141	const U8 bump_code = tep ? tep->getBumpmap() : 0;
1142
1143	F32 tcoord_xoffset = 0.f ;
1144	F32 tcoord_yoffset = 0.f ;
1145	F32 tcoord_xscale = 1.f ;
1146	F32 tcoord_yscale = 1.f ;
1147	BOOL in_atlas = FALSE ;
1148
1149	if (rebuild_tcoord)
1150	{
1151		in_atlas = isAtlasInUse() ;
1152		if(in_atlas)
1153		{
1154			const LLVector2* tmp = getTexCoordOffset() ;
1155			tcoord_xoffset = tmp->mV[0] ; 
1156			tcoord_yoffset = tmp->mV[1] ;
1157
1158			tmp = getTexCoordScale() ;
1159			tcoord_xscale = tmp->mV[0] ; 
1160			tcoord_yscale = tmp->mV[1] ;	
1161		}
1162	}
1163	
1164	BOOL is_static = mDrawablep->isStatic();
1165	BOOL is_global = is_static;
1166
1167	LLVector3 center_sum(0.f, 0.f, 0.f);
1168	
1169	if (is_global)
1170	{
1171		setState(GLOBAL);
1172	}
1173	else
1174	{
1175		clearState(GLOBAL);
1176	}
1177
1178	LLColor4U color = tep->getColor();
1179
1180	if (rebuild_color)
1181	{
1182		if (tep)
1183		{
1184			GLfloat alpha[4] =
1185			{
1186				0.00f,
1187				0.25f,
1188				0.5f,
1189				0.75f
1190			};
1191			
1192			if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny())))
1193			{
1194				color.mV[3] = U8 (alpha[tep->getShiny()] * 255);
1195			}
1196		}
1197	}
1198
1199	// INDICES
1200	if (full_rebuild)
1201	{
1202		LLFastTimer t(FTM_FACE_GEOM_INDEX);
1203		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, map_range);
1204
1205		__m128i* dst = (__m128i*) indicesp.get();
1206		__m128i* src = (__m128i*) vf.mIndices;
1207		__m128i offset = _mm_set1_epi16(index_offset);
1208
1209		S32 end = num_indices/8;
1210		
1211		for (S32 i = 0; i < end; i++)
1212		{
1213			__m128i res = _mm_add_epi16(src[i], offset);
1214			_mm_storeu_si128(dst+i, res);
1215		}
1216
1217		for (S32 i = end*8; i < num_indices; ++i)
1218		{
1219			indicesp[i] = vf.mIndices[i]+index_offset;
1220		}
1221
1222		if (map_range)
1223		{
1224			mVertexBuffer->flush();
1225		}
1226	}
1227	
1228	LLMatrix4a mat_normal;
1229	mat_normal.loadu(mat_norm_in);
1230	
1231	//if it's not fullbright and has no normals, bake sunlight based on face normal
1232	//bool bake_sunlight = !getTextureEntry()->getFullbright() &&
1233	//  !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
1234
1235	F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0;
1236
1237	if (rebuild_tcoord)
1238	{
1239		LLFastTimer t(FTM_FACE_GEOM_TEXTURE);
1240		bool do_xform;
1241			
1242		if (tep)
1243		{
1244			r  = tep->getRotation();
1245			os = tep->mOffsetS;
1246			ot = tep->mOffsetT;
1247			ms = tep->mScaleS;
1248			mt = tep->mScaleT;
1249			cos_ang = cos(r);
1250			sin_ang = sin(r);
1251
1252			if (cos_ang != 1.f || 
1253				sin_ang != 0.f ||
1254				os != 0.f ||
1255				ot != 0.f ||
1256				ms != 1.f ||
1257				mt != 1.f)
1258			{
1259				do_xform = true;
1260			}
1261			else
1262			{
1263				do_xform = false;
1264			}	
1265		}
1266		else
1267		{
1268			do_xform = false;
1269		}
1270						
1271		//bump setup
1272		LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f );
1273		LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f);
1274		LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f);
1275
1276		LLQuaternion bump_quat;
1277		if (mDrawablep->isActive())
1278		{
1279			bump_quat = LLQuaternion(mDrawablep->getRenderMatrix());
1280		}
1281		
1282		if (bump_code)
1283		{
1284			mVObjp->getVolume()->genBinormals(f);
1285			F32 offset_multiple; 
1286			switch( bump_code )
1287			{
1288				case BE_NO_BUMP:
1289				offset_multiple = 0.f;
1290				break;
1291				case BE_BRIGHTNESS:
1292				case BE_DARKNESS:
1293				if( mTexture.notNull() && mTexture->hasGLTexture())
1294				{
1295					// Offset by approximately one texel
1296					S32 cur_discard = mTexture->getDiscardLevel();
1297					S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() );
1298					max_size <<= cur_discard;
1299					const F32 ARTIFICIAL_OFFSET = 2.f;
1300					offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size;
1301				}
1302				else
1303				{
1304					offset_multiple = 1.f/256;
1305				}
1306				break;
1307
1308				default:  // Standard bumpmap textures.  Assumed to be 256x256
1309				offset_multiple = 1.f / 256;
1310				break;
1311			}
1312
1313			F32 s_scale = 1.f;
1314			F32 t_scale = 1.f;
1315			if( tep )
1316			{
1317				tep->getScale( &s_scale, &t_scale );
1318			}
1319			// Use the nudged south when coming from above sun angle, such
1320			// that emboss mapping always shows up on the upward faces of cubes when 
1321			// it's noon (since a lot of builders build with the sun forced to noon).
1322			LLVector3   sun_ray  = gSky.mVOSkyp->mBumpSunDir;
1323			LLVector3   moon_ray = gSky.getMoonDirection();
1324			LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray;
1325
1326			bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV);
1327			bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV);
1328		}
1329
1330		U8 texgen = getTextureEntry()->getTexGen();
1331		if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT)
1332		{ //planar texgen needs binormals
1333			mVObjp->getVolume()->genBinormals(f);
1334		}
1335
1336		U8 tex_mode = 0;
1337	
1338		if (isState(TEXTURE_ANIM))
1339		{
1340			LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;	
1341			tex_mode = vobj->mTexAnimMode;
1342
1343			if (!tex_mode)
1344			{
1345				clearState(TEXTURE_ANIM);
1346			}
1347			else
1348			{
1349				os = ot = 0.f;
1350				r = 0.f;
1351				cos_ang = 1.f;
1352				sin_ang = 0.f;
1353				ms = mt = 1.f;
1354
1355				do_xform = false;
1356			}
1357
1358			if (getVirtualSize() >= MIN_TEX_ANIM_SIZE)
1359			{ //don't override texture transform during tc bake
1360				tex_mode = 0;
1361			}
1362		}
1363
1364		LLVector4a scalea;
1365		scalea.load3(scale.mV);
1366
1367		bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1);
1368		bool do_tex_mat = tex_mode && mTextureMatrix;
1369
1370		if (!in_atlas && !do_bump)
1371		{ //not in atlas or not bump mapped, might be able to do a cheap update
1372			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount);
1373
1374			if (texgen != LLTextureEntry::TEX_GEN_PLANAR)
1375			{
1376				if (!do_tex_mat)
1377				{
1378					if (!do_xform)
1379					{
1380						LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32));
1381					}
1382					else
1383					{
1384						for (S32 i = 0; i < num_vertices; i++)
1385						{	
1386							LLVector2 tc(vf.mTexCoords[i]);
1387							xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
1388							*tex_coords++ = tc;	
1389						}
1390					}
1391				}
1392				else
1393				{ //do tex mat, no texgen, no atlas, no bump
1394					for (S32 i = 0; i < num_vertices; i++)
1395					{	
1396						LLVector2 tc(vf.mTexCoords[i]);
1397						//LLVector4a& norm = vf.mNormals[i];
1398						//LLVector4a& center = *(vf.mCenter);
1399
1400						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
1401						tmp = tmp * *mTextureMatrix;
1402						tc.mV[0] = tmp.mV[0];
1403						tc.mV[1] = tmp.mV[1];
1404						*tex_coords++ = tc;	
1405					}
1406				}
1407			}
1408			else
1409			{ //no bump, no atlas, tex gen planar
1410				if (do_tex_mat)
1411				{
1412					for (S32 i = 0; i < num_vertices; i++)
1413					{	
1414						LLVector2 tc(vf.mTexCoords[i]);
1415						LLVector4a& norm = vf.mNormals[i];
1416						LLVector4a& center = *(vf.mCenter);
1417						LLVector4a vec = vf.mPositions[i];	
1418						vec.mul(scalea);
1419						planarProjection(tc, norm, center, vec);
1420						
1421						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
1422						tmp = tmp * *mTextureMatrix;
1423						tc.mV[0] = tmp.mV[0];
1424						tc.mV[1] = tmp.mV[1];
1425				
1426						*tex_coords++ = tc;	
1427					}
1428				}
1429				else
1430				{
1431					for (S32 i = 0; i < num_vertices; i++)
1432					{	
1433						LLVector2 tc(vf.mTexCoords[i]);
1434						LLVector4a& norm = vf.mNormals[i];
1435						LLVector4a& center = *(vf.mCenter);
1436						LLVector4a vec = vf.mPositions[i];	
1437						vec.mul(scalea);
1438						planarProjection(tc, norm, center, vec);
1439						
1440						xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
1441
1442						*tex_coords++ = tc;	
1443					}
1444				}
1445			}
1446
1447			if (map_range)
1448			{
1449				mVertexBuffer->flush();
1450			}
1451		}
1452		else
1453		{ //either bump mapped or in atlas, just do the whole expensive loop
1454			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range);
1455
1456			std::vector<LLVector2> bump_tc;
1457		
1458			for (S32 i = 0; i < num_vertices; i++)
1459			{	
1460				LLVector2 tc(vf.mTexCoords[i]);
1461			
1462				LLVector4a& norm = vf.mNormals[i];
1463				
1464				LLVector4a& center = *(vf.mCenter);
1465		   
1466				if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
1467				{
1468					LLVector4a vec = vf.mPositions[i];
1469				
1470					vec.mul(scalea);
1471
1472					switch (texgen)
1473					{
1474						case LLTextureEntry::TEX_GEN_PLANAR:
1475							planarProjection(tc, norm, center, vec);
1476							break;
1477						case LLTextureEntry::TEX_GEN_SPHERICAL:
1478							sphericalProjection(tc, norm, center, vec);
1479							break;
1480						case LLTextureEntry::TEX_GEN_CYLINDRICAL:
1481							cylindricalProjection(tc, norm, center, vec);
1482							break;
1483						default:
1484							break;
1485					}		
1486				}
1487
1488				if (tex_mode && mTextureMatrix)
1489				{
1490					LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
1491					tmp = tmp * *mTextureMatrix;
1492					tc.mV[0] = tmp.mV[0];
1493					tc.mV[1] = tmp.mV[1];
1494				}
1495				else
1496				{
1497					xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
1498				}
1499
1500				if(in_atlas)
1501				{
1502					//
1503					//manually calculate tex-coord per vertex for varying address modes.
1504					//should be removed if shader can handle this.
1505					//
1506
1507					S32 int_part = 0 ;
1508					switch(mTexture->getAddressMode())
1509					{
1510					case LLTexUnit::TAM_CLAMP:
1511						if(tc.mV[0] < 0.f)
1512						{
1513							tc.mV[0] = 0.f ;
1514						}
1515						else if(tc.mV[0] > 1.f)
1516						{
1517							tc.mV[0] = 1.f;
1518						}
1519
1520						if(tc.mV[1] < 0.f)
1521						{
1522							tc.mV[1] = 0.f ;
1523						}
1524						else if(tc.mV[1] > 1.f)
1525						{
1526							tc.mV[1] = 1.f;
1527						}
1528						break;
1529					case LLTexUnit::TAM_MIRROR:
1530						if(tc.mV[0] < 0.f)
1531						{
1532							tc.mV[0] = -tc.mV[0] ;
1533						}
1534						int_part = (S32)tc.mV[0] ;
1535						if(int_part & 1) //odd number
1536						{
1537							tc.mV[0] = int_part + 1 - tc.mV[0] ;
1538						}
1539						else //even number
1540						{
1541							tc.mV[0] -= int_part ;
1542						}
1543
1544						if(tc.mV[1] < 0.f)
1545						{
1546							tc.mV[1] = -tc.mV[1] ;
1547						}
1548						int_part = (S32)tc.mV[1] ;
1549						if(int_part & 1) //odd number
1550						{
1551							tc.mV[1] = int_part + 1 - tc.mV[1] ;
1552						}
1553						else //even number
1554						{
1555							tc.mV[1] -= int_part ;
1556						}
1557						break;
1558					case LLTexUnit::TAM_WRAP:
1559						if(tc.mV[0] > 1.f)
1560							tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ;
1561						else if(tc.mV[0] < -1.f)
1562							tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ;
1563
1564						if(tc.mV[1] > 1.f)
1565							tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ;
1566						else if(tc.mV[1] < -1.f)
1567							tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ;
1568
1569						if(tc.mV[0] < 0.f)
1570						{
1571							tc.mV[0] = 1.0f + tc.mV[0] ;
1572						}
1573						if(tc.mV[1] < 0.f)
1574						{
1575							tc.mV[1] = 1.0f + tc.mV[1] ;
1576						}
1577						break;
1578					default:
1579						break;
1580					}
1581				
1582					tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ;
1583					tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ;
1584				}
1585				
1586
1587				*tex_coords++ = tc;
1588				if (do_bump)
1589				{
1590					bump_tc.push_back(tc);
1591				}
1592			}
1593
1594			if (map_range)
1595			{
1596				mVertexBuffer->flush();
1597			}
1598
1599			if (do_bump)
1600			{
1601				mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range);
1602		
1603				for (S32 i = 0; i < num_vertices; i++)
1604				{
1605					LLVector4a tangent;
1606					tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]);
1607
1608					LLMatrix4a tangent_to_object;
1609					tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]);
1610					LLVector4a t;
1611					tangent_to_object.rotate(binormal_dir, t);
1612					LLVector4a binormal;
1613					mat_normal.rotate(t, binormal);
1614						
1615					//VECTORIZE THIS
1616					if (mDrawablep->isActive())
1617					{
1618						LLVector3 t;
1619						t.set(binormal.getF32ptr());
1620						t *= bump_quat;
1621						binormal.load3(t.mV);
1622					}
1623
1624					binormal.normalize3fast();
1625					LLVector2 tc = bump_tc[i];
1626					tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() );
1627					
1628					*tex_coords2++ = tc;
1629				}
1630
1631				if (map_range)
1632				{
1633					mVertexBuffer->flush();
1634				}
1635			}
1636		}
1637	}
1638
1639	if (rebuild_pos)
1640	{
1641		LLFastTimer t(FTM_FACE_GEOM_POSITION);
1642		llassert(num_vertices > 0);
1643		
1644		mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range);
1645		vertices = (LLVector4a*) vert.get();
1646	
1647		LLMatrix4a mat_vert;
1648		mat_vert.loadu(mat_vert_in);
1649
1650		LLVector4a* src = vf.mPositions;
1651		LLVector4a* dst = vertices;
1652
1653		LLVector4a* end = dst+num_vertices;
1654		do
1655		{	
1656			mat_vert.affineTransform(*src++, *dst++);
1657		}
1658		while(dst < end);
1659
1660		F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0);
1661
1662		llassert(index <= LLGLSLShader::sIndexedTextureChannels-1);
1663		F32 *index_dst = (F32*) vertices;
1664		F32 *index_end = (F32*) end;
1665
1666		index_dst += 3;
1667		index_end += 3;
1668		do
1669		{
1670			*index_dst = index;
1671			index_dst += 4;
1672		}
1673		while (index_dst < index_end);
1674		
1675		S32 aligned_pad_vertices = mGeomCount - num_vertices;
1676		LLVector4a* last_vec = end - 1;
1677		while (aligned_pad_vertices > 0)
1678		{
1679			--aligned_pad_vertices;
1680			*dst++ = *last_vec;
1681		}
1682		
1683		if (map_range)
1684		{
1685			mVertexBuffer->flush();
1686		}
1687	}
1688		
1689	if (rebuild_normal)
1690	{
1691		LLFastTimer t(FTM_FACE_GEOM_NORMAL);
1692		mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range);
1693		normals = (LLVector4a*) norm.get();
1694	
1695		for (S32 i = 0; i < num_vertices; i++)
1696		{	
1697			LLVector4a normal;
1698			mat_normal.rotate(vf.mNormals[i], normal);
1699			normal.normalize3fast();
1700			normals[i] = normal;
1701		}
1702
1703		if (map_range)
1704		{
1705			mVertexBuffer->flush();
1706		}
1707	}
1708		
1709	if (rebuild_binormal)
1710	{
1711		LLFastTimer t(FTM_FACE_GEOM_BINORMAL);
1712		mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range);
1713		binormals = (LLVector4a*) binorm.get();
1714		
1715		for (S32 i = 0; i < num_vertices; i++)
1716		{	
1717			LLVector4a binormal;
1718			mat_normal.rotate(vf.mBinormals[i], binormal);
1719			binormal.normalize3fast();
1720			binormals[i] = binormal;
1721		}
1722
1723		if (map_range)
1724		{
1725			mVertexBuffer->flush();
1726		}
1727	}
1728	
1729	if (rebuild_weights && vf.mWeights)
1730	{
1731		LLFastTimer t(FTM_FACE_GEOM_WEIGHTS);
1732		mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range);
1733		weights = (LLVector4a*) wght.get();
1734		LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32));
1735		if (map_range)
1736		{
1737			mVertexBuffer->flush();
1738		}
1739	}
1740
1741	if (rebuild_color)
1742	{
1743		LLFastTimer t(FTM_FACE_GEOM_COLOR);
1744		mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range);
1745
1746		LLVector4a src;
1747
1748		U32 vec[4];
1749		vec[0] = vec[1] = vec[2] = vec[3] = color.mAll;
1750		
1751		src.loadua((F32*) vec);
1752
1753		LLVector4a* dst = (LLVector4a*) colors.get();
1754		S32 num_vecs = num_vertices/4;
1755		if (num_vertices%4 > 0)
1756		{
1757			++num_vecs;
1758		}
1759
1760		for (S32 i = 0; i < num_vecs; i++)
1761		{	
1762			dst[i] = src;
1763		}
1764
1765		if (map_range)
1766		{
1767			mVertexBuffer->flush();
1768		}
1769	}
1770
1771	if (rebuild_emissive)
1772	{
1773		LLFastTimer t(FTM_FACE_GEOM_EMISSIVE);
1774		LLStrider<LLColor4U> emissive;
1775		mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range);
1776
1777		U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255);
1778
1779		LLVector4a src;
1780
1781		
1782		U32 glow32 = glow |
1783					 (glow << 8) |
1784					 (glow << 16) |
1785					 (glow << 24);
1786
1787		U32 vec[4];
1788		vec[0] = vec[1] = vec[2] = vec[3] = glow32;
1789		
1790		src.loadua((F32*) vec);
1791
1792		LLVector4a* dst = (LLVector4a*) emissive.get();
1793		S32 num_vecs = num_vertices/4;
1794		if (num_vertices%4 > 0)
1795		{
1796			++num_vecs;
1797		}
1798
1799		for (S32 i = 0; i < num_vecs; i++)
1800		{	
1801			dst[i] = src;
1802		}
1803
1804		if (map_range)
1805		{
1806			mVertexBuffer->flush();
1807		}
1808	}
1809	if (rebuild_tcoord)
1810	{
1811		mTexExtents[0].setVec(0,0);
1812		mTexExtents[1].setVec(1,1);
1813		xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt);
1814		xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt);
1815		
1816		F32 es = vf.mTexCoordExtents[1].mV[0] - vf.mTexCoordExtents[0].mV[0] ;
1817		F32 et = vf.mTexCoordExtents[1].mV[1] - vf.mTexCoordExtents[0].mV[1] ;
1818		mTexExtents[0][0] *= es ;
1819		mTexExtents[1][0] *= es ;
1820		mTexExtents[0][1] *= et ;
1821		mTexExtents[1][1] *= et ;
1822	}
1823
1824	mLastVertexBuffer = mVertexBuffer;
1825	mLastGeomCount = mGeomCount;
1826	mLastGeomIndex = mGeomIndex;
1827	mLastIndicesCount = mIndicesCount;
1828	mLastIndicesIndex = mIndicesIndex;
1829
1830	return TRUE;
1831}
1832
1833//check if the face has a media
1834BOOL LLFace::hasMedia() const 
1835{
1836	if(mHasMedia)
1837	{
1838		return TRUE ;
1839	}
1840	if(mTexture.notNull()) 
1841	{
1842		return mTexture->hasParcelMedia() ;  //if has a parcel media
1843	}
1844
1845	return FALSE ; //no media.
1846}
1847
1848const F32 LEAST_IMPORTANCE = 0.05f ;
1849const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ;
1850
1851F32 LLFace::getTextureVirtualSize()
1852{
1853	F32 radius;
1854	F32 cos_angle_to_view_dir;	
1855	BOOL in_frustum = calcPixelArea(cos_angle_to_view_dir, radius);
1856
1857	if (mPixelArea < F_ALMOST_ZERO || !in_frustum)
1858	{
1859		setVirtualSize(0.f) ;
1860		return 0.f;
1861	}
1862
1863	//get area of circle in texture space
1864	LLVector2 tdim = mTexExtents[1] - mTexExtents[0];
1865	F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f;
1866	if (texel_area <= 0)
1867	{
1868		// Probably animated, use default
1869		texel_area = 1.f;
1870	}
1871
1872	F32 face_area;
1873	if (mVObjp->isSculpted() && texel_area > 1.f)
1874	{
1875		//sculpts can break assumptions about texel area
1876		face_area = mPixelArea;
1877	}
1878	else
1879	{
1880		//apply texel area to face area to get accurate ratio
1881		//face_area /= llclamp(texel_area, 1.f/64.f, 16.f);
1882		face_area =  mPixelArea / llclamp(texel_area, 0.015625f, 128.f);
1883	}
1884
1885	face_area = LLFace::adjustPixelArea(mImportanceToCamera, face_area) ;
1886	if(face_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping.
1887	{
1888		if(mImportanceToCamera > LEAST_IMPORTANCE_FOR_LARGE_IMAGE && mTexture.notNull() && mTexture->isLargeImage())
1889		{		
1890			face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius );
1891		}	
1892	}
1893
1894	setVirtualSize(face_area) ;
1895
1896	return face_area;
1897}
1898
1899BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
1900{
1901	//VECTORIZE THIS
1902	//get area of circle around face
1903	LLVector4a center;
1904	center.load3(getPositionAgent().mV);
1905	LLVector4a size;
1906	size.setSub(mExtents[1], mExtents[0]);
1907	size.mul(0.5f);
1908
1909	LLViewerCamera* camera = LLViewerCamera::getInstance();
1910
1911	F32 size_squared = size.dot3(size).getF32();
1912	LLVector4a lookAt;
1913	LLVector4a t;
1914	t.load3(camera->getOrigin().mV);
1915	lookAt.setSub(center, t);
1916	F32 dist = lookAt.getLength3().getF32();
1917	dist = llmax(dist-size.getLength3().getF32(), 0.f);
1918	lookAt.normalize3fast() ;	
1919
1920	//get area of circle around node
1921	F32 app_angle = atanf((F32) sqrt(size_squared) / dist);
1922	radius = app_angle*LLDrawable::sCurPixelAngle;
1923	mPixelArea = radius*radius * 3.14159f;
1924	LLVector4a x_axis;
1925	x_axis.load3(camera->getXAxis().mV);
1926	cos_angle_to_view_dir = lookAt.dot3(x_axis).getF32();
1927
1928	//if has media, check if the face is out of the view frustum.	
1929	if(hasMedia())
1930	{
1931		if(!camera->AABBInFrustum(center, size)) 
1932		{
1933			mImportanceToCamera = 0.f ;
1934			return false ;
1935		}
1936		if(cos_angle_to_view_dir > camera->getCosHalfFov()) //the center is within the view frustum
1937		{
1938			cos_angle_to_view_dir = 1.0f ;
1939		}
1940		else
1941		{		
1942			LLVector4a d;
1943			d.setSub(lookAt, x_axis);
1944
1945			if(dist * dist * d.dot3(d) < size_squared)
1946			{
1947				cos_angle_to_view_dir = 1.0f ;
1948			}
1949		}
1950	}
1951
1952	if(dist < mBoundingSphereRadius) //camera is very close
1953	{
1954		cos_angle_to_view_dir = 1.0f ;
1955		mImportanceToCamera = 1.0f ;
1956	}
1957	else
1958	{		
1959		mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ;
1960	}
1961
1962	return true ;
1963}
1964
1965//the projection of the face partially overlaps with the screen
1966F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius )
1967{
1968	F32 screen_radius = (F32)llmax(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()) ;
1969	F32 center_angle = acosf(cos_angle_to_view_dir) ;
1970	F32 d = center_angle * LLDrawable::sCurPixelAngle ;
1971
1972	if(d + radius > screen_radius + 5.f)
1973	{
1974		//----------------------------------------------
1975		//calculate the intersection area of two circles
1976		//F32 radius_square = radius * radius ;
1977		//F32 d_square = d * d ;
1978		//F32 screen_radius_square = screen_radius * screen_radius ;
1979		//face_area = 
1980		//	radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) +
1981		//	screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) -
1982		//	0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ;			
1983		//----------------------------------------------
1984
1985		//the above calculation is too expensive
1986		//the below is a good estimation: bounding box of the bounding sphere:
1987		F32 alpha = 0.5f * (radius + screen_radius - d) / radius ;
1988		alpha = llclamp(alpha, 0.f, 1.f) ;
1989		return alpha * alpha ;
1990	}
1991	return 1.0f ;
1992}
1993
1994const S8 FACE_IMPORTANCE_LEVEL = 4 ;
1995const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //{distance, importance_weight}
1996	{{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ;
1997const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] =    //{cos(angle), importance_weight}
1998	{{0.985f /*cos(10 degrees)*/, 1.0f}, {0.94f /*cos(20 degrees)*/, 0.8f}, {0.866f /*cos(30 degrees)*/, 0.64f}, {0.0f, 0.36f}} ;
1999
2000//static 
2001F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist)
2002{
2003	F32 importance = 0.f ;
2004	
2005	if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() && 
2006		dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0]) 
2007	{
2008		LLViewerCamera* camera = LLViewerCamera::getInstance();
2009		F32 camera_moving_speed = camera->getAverageSpeed() ;
2010		F32 camera_angular_speed = camera->getAverageAngularSpeed();
2011
2012		if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f)
2013		{
2014			//if camera moves or rotates too fast, ignore the importance factor
2015			return 0.f ;
2016		}
2017		
2018		//F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ;
2019		
2020		S32 i = 0 ;
2021		for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i);
2022		i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
2023		F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ;
2024		
2025		for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ;
2026		i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
2027		importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ;
2028	}
2029
2030	return importance ;
2031}
2032
2033//static 
2034F32 LLFace::adjustPixelArea(F32 importance, F32 pixel_area)
2035{
2036	if(pixel_area > LLViewerTexture::sMaxSmallImageSize)
2037	{
2038		if(importance < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res.
2039		{
2040			static const F32 MAX_LEAST_IMPORTANCE_IMAGE_SIZE = 128.0f * 128.0f ;
2041			pixel_area = llmin(pixel_area * 0.5f, MAX_LEAST_IMPORTANCE_IMAGE_SIZE) ;
2042		}
2043		else if(pixel_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping.
2044		{
2045			if(importance < LEAST_IMPORTANCE_FOR_LARGE_IMAGE

Large files files are truncated, but you can click here to view the full file