diff options
| author | Dave Parks <davep@lindenlab.com> | 2010-04-06 16:24:08 -0500 | 
|---|---|---|
| committer | Dave Parks <davep@lindenlab.com> | 2010-04-06 16:24:08 -0500 | 
| commit | 47ffcdb93d6e2ac1f9d497e43e0213c98d129254 (patch) | |
| tree | 1d3c1d159bca20cdca21a4e3eac23b1515372615 | |
| parent | 807d835c2bfc5d794a74f9690d1fafbe55ff88cc (diff) | |
Rigged attachments (almost works).
| -rw-r--r-- | indra/llmath/llvolume.cpp | 22 | ||||
| -rw-r--r-- | indra/llrender/llglslshader.cpp | 14 | ||||
| -rw-r--r-- | indra/llrender/llglslshader.h | 3 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/lldrawpoolavatar.cpp | 26 | ||||
| -rw-r--r-- | indra/newview/lldrawpoolavatar.h | 2 | ||||
| -rw-r--r-- | indra/newview/llface.cpp | 18 | ||||
| -rw-r--r-- | indra/newview/llface.h | 4 | ||||
| -rw-r--r-- | indra/newview/llspatialpartition.h | 7 | ||||
| -rw-r--r-- | indra/newview/llviewershadermgr.cpp | 25 | ||||
| -rw-r--r-- | indra/newview/llviewershadermgr.h | 3 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.cpp | 109 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.h | 1 | ||||
| -rw-r--r-- | indra/newview/llvovolume.cpp | 20 | 
14 files changed, 247 insertions, 15 deletions
| diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index c563af592f..fdd48b9e9e 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2013,22 +2013,23 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  			if (mdl[i].has("Weights"))  			{  				face.mWeights.resize(num_verts); +  				LLSD::Binary weights = mdl[i]["Weights"]; -				LLSD::Binary::iterator iter = weights.begin(); +				U32 idx = 0;  				U32 cur_vertex = 0; -				while (iter != weights.end()) +				while (idx < weights.size() && cur_vertex < num_verts)  				{ -					const S32 END_INFLUENCES = 0xFF; -					U8 joint = *(iter++); +					const U8 END_INFLUENCES = 0xFF; +					U8 joint = weights[idx++];  					U32 cur_influence = 0;  					while (joint != END_INFLUENCES)  					{ -						U16 influence = *(iter++); +						U16 influence = weights[idx++];  						influence = influence << 8; -						influence |= *(iter++); +						influence |= weights[idx++];  						F32 w = llmin((F32) influence / 65535.f, 0.99999f);  						face.mWeights[cur_vertex].mV[cur_influence++] = (F32) joint + w; @@ -2039,13 +2040,18 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  						}  						else  						{ -							joint = *(iter++); +							joint = weights[idx++];  						}  					}  					cur_vertex++; -					iter++;  				} + +				if (cur_vertex != num_verts || idx != weights.size()) +				{ +					llwarns << "Vertex weight count does not match vertex count!" << llendl; +				} +					  			}  			LLVector3 min_pos; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index ca92cb6580..949057df04 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -61,7 +61,7 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)  LLShaderFeatures::LLShaderFeatures()  : calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false), -hasTransport(false), hasSkinning(false), hasAtmospherics(false), isSpecular(false), +hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),  hasGamma(false), hasLighting(false), calculatesAtmospherics(false)  {  } @@ -717,6 +717,18 @@ GLint LLGLSLShader::getUniformLocation(const string& uniform)  	return -1;  } +GLint LLGLSLShader::getAttribLocation(U32 attrib) +{ +	if (attrib < mAttribute.size()) +	{ +		return mAttribute[attrib]; +	} +	else +	{ +		return -1; +	} +} +  void LLGLSLShader::uniform1i(const string& uniform, GLint v)  {  	GLint location = getUniformLocation(uniform); diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 166d4af04c..dc493ba162 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -48,6 +48,7 @@ public:  	bool hasWaterFog; // implies no gamma  	bool hasTransport; // implies no lighting (it's possible to have neither though)  	bool hasSkinning;	 +	bool hasObjectSkinning;  	bool hasAtmospherics;  	bool hasGamma; @@ -109,7 +110,7 @@ public:  	void vertexAttrib4fv(U32 index, GLfloat* v);  	GLint getUniformLocation(const std::string& uniform); -	 +	GLint getAttribLocation(U32 attrib);  	GLint mapUniformTextureChannel(GLint location, GLenum type); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 1286e91e49..23b76351eb 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -152,6 +152,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  			return FALSE;  		}  	} + +	if (features->hasObjectSkinning) +	{ +		if (!shader->attachObject("avatar/objectSkinV.glsl")) +		{ +			return FALSE; +		} +	}  	///////////////////////////////////////  	// Attach Fragment Shader Features Next diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 012e41383f..9311a5f60e 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -320,7 +320,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)  S32 LLDrawPoolAvatar::getNumPasses()  { -	return LLPipeline::sImpostorRender ? 1 : 3; +	return LLPipeline::sImpostorRender ? 1 : 4;  }  void LLDrawPoolAvatar::render(S32 pass) @@ -357,6 +357,8 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass)  		break;  	case 2:  		beginSkinned(); +	case 3: +		beginRigged();  		break;  	}  } @@ -381,6 +383,10 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass)  		break;  	case 2:  		endSkinned(); +		break; +	case 3: +		endRigged(); +		break;  	}  } @@ -566,6 +572,18 @@ void LLDrawPoolAvatar::endSkinned()  	gGL.getTexUnit(0)->activate();  } +void LLDrawPoolAvatar::beginRigged() +{ +	gSkinnedObjectSimpleProgram.bind(); +	LLVertexBuffer::sWeight4Loc = gSkinnedObjectSimpleProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endRigged() +{ +	gSkinnedObjectSimpleProgram.unbind(); +	LLVertexBuffer::sWeight4Loc = -1; +} +  void LLDrawPoolAvatar::beginDeferredSkinned()  {  	sShaderLevel = mVertexShaderLevel; @@ -711,6 +729,12 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)  		avatarp->renderRigid();  		return;  	} + +	if (pass == 3) +	{ +		avatarp->renderSkinnedAttachments(); +		return; +	}  	if (sShaderLevel > 0)  	{ diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index b947943619..c43aa9b1e3 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -90,10 +90,12 @@ public:  	void beginRigid();  	void beginFootShadow();  	void beginSkinned(); +	void beginRigged();  	void endRigid();  	void endFootShadow();  	void endSkinned(); +	void endRigged();  	void beginDeferredImpostor();  	void beginDeferredRigid(); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 53330e4d98..bc3e04db18 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -888,7 +888,8 @@ static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom");  BOOL LLFace::getGeometryVolume(const LLVolume& volume,  							   const S32 &f,  								const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, -								const U16 &index_offset) +								const U16 &index_offset, +								bool force_rebuild)  {  	LLFastTimer t(FTM_FACE_GET_GEOM);  	const LLVolumeFace &vf = volume.getVolumeFace(f); @@ -925,8 +926,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  	LLStrider<LLColor4U> colors;  	LLStrider<LLVector3> binormals;  	LLStrider<U16> indicesp; +	LLStrider<LLVector4> weights; -	BOOL full_rebuild = mDrawablep->isState(LLDrawable::REBUILD_VOLUME); +	BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME);  	BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal();  	LLVector3 scale; @@ -944,6 +946,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  	BOOL rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD);  	BOOL rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);  	BOOL rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL); +	bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4);  	const LLTextureEntry *tep = mVObjp->getTE(f);  	U8  bump_code = tep ? tep->getBumpmap() : 0; @@ -960,7 +963,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  	{  		mVertexBuffer->getBinormalStrider(binormals, mGeomIndex);  	} - +	if (rebuild_weights) +	{ +		mVertexBuffer->getWeight4Strider(weights, mGeomIndex); +	} +	  	F32 tcoord_xoffset = 0.f ;  	F32 tcoord_yoffset = 0.f ;  	F32 tcoord_xscale = 1.f ; @@ -1338,6 +1345,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  			*binormals++ = binormal;  		} +		if (rebuild_weights) +		{ +			*weights++ = vf.mWeights[i]; +		} +  		if (rebuild_color)  		{  			*colors++ = color;		 diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 67dd97e6f7..06ec043c76 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -73,6 +73,7 @@ public:  		HUD_RENDER		= 0x0008,  		USE_FACE_COLOR	= 0x0010,  		TEXTURE_ANIM	= 0x0020,  +		RIGGED			= 0x0040,  	};  	static void initClass(); @@ -145,7 +146,8 @@ public:  	BOOL getGeometryVolume(const LLVolume& volume,  						const S32 &f,  						const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, -						const U16 &index_offset); +						const U16 &index_offset, +						bool force_rebuild = false);  	// For avatar  	U16			 getGeometryAvatar( diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index d74216de2d..b5e5967374 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -615,6 +615,13 @@ public:  class LLVolumeGeometryManager: public LLGeometryManager  {   public: +	typedef enum +	{ +		NONE = 0, +		BATCH_SORT, +		DISTANCE_SORT +	} eSortType; +  	virtual ~LLVolumeGeometryManager() { }  	virtual void rebuildGeom(LLSpatialGroup* group);  	virtual void rebuildMesh(LLSpatialGroup* group); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index a0d0b9d490..8a68dd6ea7 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -77,6 +77,9 @@ LLGLSLShader		gObjectFullbrightShinyProgram;  LLGLSLShader		gObjectShinyProgram;  LLGLSLShader		gObjectShinyWaterProgram; +//object hardware skinning shaders +LLGLSLShader		gSkinnedObjectSimpleProgram; +  //environment shaders  LLGLSLShader		gTerrainProgram;  LLGLSLShader		gTerrainWaterProgram; @@ -148,6 +151,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() :  	mShaderList.push_back(&gObjectSimpleProgram);  	mShaderList.push_back(&gObjectFullbrightProgram);  	mShaderList.push_back(&gObjectFullbrightShinyProgram); +	mShaderList.push_back(&gSkinnedObjectSimpleProgram);  	mShaderList.push_back(&gTerrainProgram);  	mShaderList.push_back(&gTerrainWaterProgram);  	mShaderList.push_back(&gObjectSimpleWaterProgram); @@ -195,6 +199,7 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void)  		mReservedAttribs.push_back("materialColor");  		mReservedAttribs.push_back("specularColor");  		mReservedAttribs.push_back("binormal"); +		mReservedAttribs.push_back("object_weight");  		mAvatarAttribs.reserve(5);  		mAvatarAttribs.push_back("weight"); @@ -548,6 +553,9 @@ void LLViewerShaderMgr::unloadShaders()  	gObjectShinyProgram.unload();  	gObjectFullbrightShinyProgram.unload();  	gObjectShinyWaterProgram.unload(); + +	gSkinnedObjectSimpleProgram.unload(); +  	gWaterProgram.unload();  	gUnderWaterProgram.unload();  	gTerrainProgram.unload(); @@ -625,6 +633,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders()  	shaders.push_back( make_pair( "lighting/lightSpecularV.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );  	shaders.push_back( make_pair( "windlight/atmosphericsV.glsl",			mVertexShaderLevel[SHADER_WINDLIGHT] ) );  	shaders.push_back( make_pair( "avatar/avatarSkinV.glsl",				1 ) ); +	shaders.push_back( make_pair( "avatar/objectSkinV.glsl",				1 ) );  	// We no longer have to bind the shaders to global glhandles, they are automatically added to a map now.  	for (U32 i = 0; i < shaders.size(); i++) @@ -1214,6 +1223,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  		gObjectSimpleWaterProgram.unload();  		gObjectFullbrightProgram.unload();  		gObjectFullbrightWaterProgram.unload(); +		gSkinnedObjectSimpleProgram.unload();  		return FALSE;  	} @@ -1323,6 +1333,21 @@ BOOL LLViewerShaderMgr::loadShadersObject()  		success = gObjectFullbrightShinyProgram.createShader(NULL, &mShinyUniforms);  	} +	if (success) +	{ +		gSkinnedObjectSimpleProgram.mName = "Skinned Simple Shader"; +		gSkinnedObjectSimpleProgram.mFeatures.calculatesLighting = true; +		gSkinnedObjectSimpleProgram.mFeatures.calculatesAtmospherics = true; +		gSkinnedObjectSimpleProgram.mFeatures.hasGamma = true; +		gSkinnedObjectSimpleProgram.mFeatures.hasAtmospherics = true; +		gSkinnedObjectSimpleProgram.mFeatures.hasLighting = true; +		gSkinnedObjectSimpleProgram.mFeatures.hasObjectSkinning = true; +		gSkinnedObjectSimpleProgram.mShaderFiles.clear(); +		gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); +		gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); +		gSkinnedObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; +		success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL); +	}  	if( !success )  	{ diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index ac2b4624e0..83a650cdbc 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -82,6 +82,7 @@ public:  		MATERIAL_COLOR = 0,  		SPECULAR_COLOR,  		BINORMAL, +		OBJECT_WEIGHT,  		END_RESERVED_ATTRIBS  	} eGLSLReservedAttribs; @@ -313,6 +314,8 @@ extern LLGLSLShader			gObjectFullbrightShinyProgram;  extern LLGLSLShader			gObjectShinyProgram;  extern LLGLSLShader			gObjectShinyWaterProgram; +extern LLGLSLShader			gSkinnedObjectSimpleProgram; +  //environment shaders  extern LLGLSLShader			gTerrainProgram;  extern LLGLSLShader			gTerrainWaterProgram; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index c400e8510e..535440692f 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -64,6 +64,7 @@  #include "llkeyframefallmotion.h"  #include "llkeyframestandmotion.h"  #include "llkeyframewalkmotion.h" +#include "llmeshrepository.h"  #include "llmutelist.h"  #include "llmoveview.h"  #include "llquantize.h" @@ -79,6 +80,7 @@  #include "llviewermenu.h"  #include "llviewerobjectlist.h"  #include "llviewerparcelmgr.h" +#include "llviewershadermgr.h"  #include "llviewerstats.h"  #include "llvoavatarself.h"  #include "llvovolume.h" @@ -3644,6 +3646,113 @@ bool LLVOAvatar::shouldAlphaMask()  } +U32 LLVOAvatar::renderSkinnedAttachments() +{ +	U32 num_indices = 0; +	 +	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX |  +							LLVertexBuffer::MAP_NORMAL |  +							LLVertexBuffer::MAP_TEXCOORD0 |  +							LLVertexBuffer::MAP_WEIGHT4; + +	for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();  +		 iter != mAttachmentPoints.end(); +		 ++iter) +	{ +		LLViewerJointAttachment* attachment = iter->second; +		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); +			 attachment_iter != attachment->mAttachedObjects.end(); +			 ++attachment_iter) +		{ +			const LLViewerObject* attached_object = (*attachment_iter); +			if (attached_object && !attached_object->isHUDAttachment()) +			{ +				const LLDrawable* drawable = attached_object->mDrawable; +				if (drawable) +				{ +					for (S32 i = 0; i < drawable->getNumFaces(); ++i) +					{ +						LLFace* face = drawable->getFace(i); +						if (face->isState(LLFace::RIGGED)) +						{ +							LLVolume* volume = attached_object->getVolume(); +							const LLVolumeFace& vol_face = volume->getVolumeFace(i); + +							const LLMeshSkinInfo* skin = NULL; +							LLVertexBuffer* buff = face->mVertexBuffer; + +							if (!buff ||  +								!buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) || +								buff->getRequestedVerts() != vol_face.mVertices.size()) +							{ +								face->mVertexBuffer = NULL; +								face->mLastVertexBuffer = NULL; +								buff = NULL; + +								LLUUID mesh_id = volume->getParams().getSculptID(); +								if (mesh_id.notNull()) +								{ +									skin = gMeshRepo.getSkinInfo(mesh_id); +									if (skin) +									{ +										face->mVertexBuffer = new LLVertexBuffer(data_mask, 0); +										face->mVertexBuffer->allocateBuffer(vol_face.mVertices.size(), vol_face.mIndices.size(), true); + +										face->setGeomIndex(0); +										face->setIndicesIndex(0); +										 +										U16 offset = 0; +										 +										LLMatrix4 mat_vert = skin->mBindShapeMatrix; +										LLMatrix3 mat_normal; + +										face->getGeometryVolume(*volume, i, mat_vert, mat_normal, offset, true); +										buff = face->mVertexBuffer; +									} +								} +							}								 +							 +							if (buff) +							{ +								if (skin) +								{ +									LLMatrix4 mat[64]; + +									for (U32 i = 0; i < skin->mJointNames.size(); ++i) +									{ +										LLJoint* joint = getJoint(skin->mJointNames[i]); +										if (joint) +										{ +											mat[i] = skin->mInvBindMatrix[i]; +											mat[i] *= joint->getWorldMatrix(); +										} +									} +									 +									gSkinnedObjectSimpleProgram.uniformMatrix4fv("matrixPalette",  +										skin->mJointNames.size(), +										FALSE, +										(GLfloat*) mat[0].mMatrix); + +									buff->setBuffer(data_mask); + +									U16 start = face->getGeomStart(); +									U16 end = start + face->getGeomCount(); +									S32 offset = face->getIndicesStart(); +									U32 count = face->getIndicesCount(); + +									buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); +								} +							} +						} +					} +				} +			} +		} +	} + +	return num_indices; +} +  //-----------------------------------------------------------------------------  // renderSkinned()  //----------------------------------------------------------------------------- diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index d5485413f4..b0535a4a26 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -339,6 +339,7 @@ public:  	U32 		renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);  	U32 		renderRigid();  	U32 		renderSkinned(EAvatarRenderPass pass); +	U32			renderSkinnedAttachments();  	U32 		renderTransparent(BOOL first_pass);  	void 		renderCollisionVolumes();  	static void	deleteCachedImages(bool clearAll=true); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index bc83e11fd2..56fb42bb89 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3496,6 +3496,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  		drawablep->clearState(LLDrawable::HAS_ALPHA); +		bool rigged = vobj->isAttachment() &&  +					vobj->isMesh() &&  +					gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID()); +  		//for each face  		for (S32 i = 0; i < drawablep->getNumFaces(); i++)  		{ @@ -3503,6 +3507,22 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  			drawablep->updateFaceSize(i);  			LLFace* facep = drawablep->getFace(i); +			if (rigged)  +			{ +				if (!facep->isState(LLFace::RIGGED)) +				{ +					facep->mVertexBuffer = NULL; +					facep->mLastVertexBuffer = NULL; +					facep->setState(LLFace::RIGGED); +				} + +				continue; +			} +			else +			{ +				facep->clearState(LLFace::RIGGED); +			} +  			if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0)  			{  				facep->mVertexBuffer = NULL; | 
