diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 07339f75267693d9e2f60cbbb3486669f8bf92c9..24528a8ce9e3b18bfa7c243cf95c8ff1b65971ce 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -1990,7 +1990,7 @@ void LLVolumeFace::VertexData::init()
 {
 	if (!mData)
 	{
-		mData = (LLVector4a*) ll_aligned_malloc_16(32);
+		mData = new LLVector4a[2];
 	}
 }
 
@@ -2019,7 +2019,7 @@ const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolu
 
 LLVolumeFace::VertexData::~VertexData()
 {
-	ll_aligned_free_16(mData);
+	delete [] mData;
 }
 
 LLVector4a& LLVolumeFace::VertexData::getPosition()
@@ -2257,12 +2257,12 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
 					U32 cur_influence = 0;
 					LLVector4 wght(0,0,0,0);
 
-					while (joint != END_INFLUENCES)
+					while (joint != END_INFLUENCES && idx < weights.size())
 					{
 						U16 influence = weights[idx++];
 						influence |= ((U16) weights[idx++] << 8);
 
-						F32 w = llmin((F32) influence / 65535.f, 0.99999f);
+						F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f);
 						wght.mV[cur_influence++] = (F32) joint + w;
 
 						if (cur_influence >= 4)
@@ -5230,7 +5230,7 @@ LLVolumeFace::LLVolumeFace() :
 	mWeights(NULL),
 	mOctree(NULL)
 {
-	mExtents = (LLVector4a*) ll_aligned_malloc_16(48);
+	mExtents = new LLVector4a[3];
 	mCenter = mExtents+2;
 }
 
@@ -5251,7 +5251,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)
 	mWeights(NULL),
 	mOctree(NULL)
 { 
-	mExtents = (LLVector4a*) ll_aligned_malloc_16(48);
+	mExtents = new LLVector4a[3];
 	mCenter = mExtents+2;
 	*this = src;
 }
@@ -5286,7 +5286,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
 
 	if (mNumVertices)
 	{
-		S32 vert_size = mNumVertices*4*sizeof(F32);
+		S32 vert_size = mNumVertices*sizeof(LLVector4a);
 		S32 tc_size = (mNumVertices*8+0xF) & ~0xF;
 			
 		LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size);
@@ -5301,7 +5301,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
 		}
 		else
 		{
-			ll_aligned_free_16(mBinormals);
+			delete [] mBinormals;
 			mBinormals = NULL;
 		}
 
@@ -5312,7 +5312,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
 		}
 		else
 		{
-			ll_aligned_free_16(mWeights);
+			delete [] mWeights;
 			mWeights = NULL;
 		}
 	}
@@ -5330,7 +5330,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
 
 LLVolumeFace::~LLVolumeFace()
 {
-	ll_aligned_free_16(mExtents);
+	delete [] mExtents;
 	mExtents = NULL;
 
 	freeData();
@@ -5338,17 +5338,17 @@ LLVolumeFace::~LLVolumeFace()
 
 void LLVolumeFace::freeData()
 {
-	ll_aligned_free_16(mPositions);
+	delete [] mPositions;
 	mPositions = NULL;
-	ll_aligned_free_16(mNormals);
+	delete []  mNormals;
 	mNormals = NULL;
-	ll_aligned_free_16(mTexCoords);
+	delete [] mTexCoords;
 	mTexCoords = NULL;
-	ll_aligned_free_16(mIndices);
+	delete [] mIndices;
 	mIndices = NULL;
-	ll_aligned_free_16(mBinormals);
+	delete [] mBinormals;
 	mBinormals = NULL;
-	ll_aligned_free_16(mWeights);
+	delete [] mWeights;
 	mWeights = NULL;
 
 	delete mOctree;
@@ -5461,18 +5461,13 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
 }
 
 
-void LLVolumeFace::createOctree(F32 scaler)
+void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVector4a& size)
 {
 	if (mOctree)
 	{
 		return;
 	}
 
-	LLVector4a center;
-	LLVector4a size;
-	center.splat(0.f);
-	size.splat(0.5f);
-
 	mOctree = new LLOctreeRoot<LLVolumeTriangle>(center, size, NULL);
 	new LLVolumeOctreeListener(mOctree);
 
@@ -6166,21 +6161,21 @@ void LLVolumeFace::createBinormals()
 
 void LLVolumeFace::resizeVertices(S32 num_verts)
 {
-	ll_aligned_free_16(mPositions);
-	ll_aligned_free_16(mNormals);
-	ll_aligned_free_16(mBinormals);
-	ll_aligned_free_16(mTexCoords);
+	delete [] mPositions;
+	delete [] mNormals;
+	delete [] mBinormals;
+	delete [] mTexCoords;
 
 	mBinormals = NULL;
 
 	if (num_verts)
 	{
-		mPositions = (LLVector4a*) ll_aligned_malloc_16(num_verts*16);
-		mNormals = (LLVector4a*) ll_aligned_malloc_16(num_verts*16);
+		mPositions = new LLVector4a[num_verts]; 
+		mNormals = new LLVector4a[num_verts]; 
 
 		//pad texture coordinate block end to allow for QWORD reads
 		S32 size = ((num_verts*8) + 0xF) & ~0xF;
-		mTexCoords = (LLVector2*) ll_aligned_malloc_16(size);
+		mTexCoords = new LLVector2[size/8];
 	}
 	else
 	{
@@ -6204,20 +6199,20 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
 	S32 old_size = mNumVertices*16;
 
 	//positions
-	LLVector4a* dst = (LLVector4a*) ll_aligned_malloc_16(new_size);
+	LLVector4a* dst = new LLVector4a[new_verts];
 	if (mPositions)
 	{
 		LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mPositions, old_size);
-		ll_aligned_free_16(mPositions);
+		delete [] mPositions;
 	}
 	mPositions = dst;
 
 	//normals
-	dst = (LLVector4a*) ll_aligned_malloc_16(new_size);
+	dst = new LLVector4a[new_verts]; 
 	if (mNormals)
 	{
 		LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mNormals, old_size);
-		ll_aligned_free_16(mNormals);
+		delete [] mNormals;
 	}
 	mNormals = dst;
 
@@ -6225,19 +6220,18 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
 	new_size = ((new_verts*8)+0xF) & ~0xF;
 	old_size = ((mNumVertices*8)+0xF) & ~0xF;
 
-	dst = (LLVector4a*) ll_aligned_malloc_16(new_size);
 	{
-		LLVector2* dst = (LLVector2*) ll_aligned_malloc_16(new_size);
+		LLVector2* dst = new LLVector2[new_size/8]; 
 		if (mTexCoords)
 		{
 			LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mTexCoords, old_size);
-			ll_aligned_free_16(mTexCoords);
+			delete [] mTexCoords;
 		}
+		mTexCoords = dst;
 	}
-	mTexCoords = (LLVector2*) dst;
 
 	//just clear binormals
-	ll_aligned_free_16(mBinormals);
+	delete [] mBinormals;
 	mBinormals = NULL;
 
 	mPositions[mNumVertices] = pos;
@@ -6249,26 +6243,26 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
 
 void LLVolumeFace::allocateBinormals(S32 num_verts)
 {
-	ll_aligned_free_16(mBinormals);
-	mBinormals = (LLVector4a*) ll_aligned_malloc_16(num_verts*16);
+	delete [] mBinormals;
+	mBinormals = new LLVector4a[num_verts]; 
 }
 
 void LLVolumeFace::allocateWeights(S32 num_verts)
 {
-	ll_aligned_free_16(mWeights);
-	mWeights = (LLVector4a*) ll_aligned_malloc_16(num_verts*16);
+	delete [] mWeights; 
+	mWeights = new LLVector4a[num_verts]; 
 }
 
 void LLVolumeFace::resizeIndices(S32 num_indices)
 {
-	ll_aligned_free_16(mIndices);
-
+	delete [] mIndices;
+	
 	if (num_indices)
 	{
 		//pad index block end to allow for QWORD reads
 		S32 size = ((num_indices*2) + 0xF) & ~0xF;
 		
-		mIndices = (U16*) ll_aligned_malloc_16(size);	
+		mIndices = new U16[size/2];
 	}
 	else
 	{
@@ -6286,11 +6280,11 @@ void LLVolumeFace::pushIndex(const U16& idx)
 	S32 old_size = ((mNumIndices*2)+0xF) & ~0xF;
 	if (new_size != old_size)
 	{
-		U16* dst = (U16*) ll_aligned_malloc_16(new_size);
+		U16* dst = new U16[new_size/2];
 		if (mIndices)
 		{
 			LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mIndices, old_size);
-			ll_aligned_free_16(mIndices);
+			delete [] mIndices;
 		}
 		mIndices = dst;
 	}
@@ -6333,9 +6327,9 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
 	}
 
 	//allocate new buffer space
-	LLVector4a* new_pos = (LLVector4a*) ll_aligned_malloc_16(new_count*16);
-	LLVector4a* new_norm = (LLVector4a*) ll_aligned_malloc_16(new_count*16);
-	LLVector2* new_tc = (LLVector2*) ll_aligned_malloc_16((new_count*8+0xF) & ~0xF);
+	LLVector4a* new_pos = new LLVector4a[new_count];
+	LLVector4a* new_norm = new LLVector4a[new_count];
+	LLVector2* new_tc = new LLVector2[((new_count*8+0xF) & ~0xF)/8];
 	
 
 	if (mNumVertices > 0)
@@ -6346,10 +6340,10 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
 	}
 
 	//free old buffer space
-	ll_aligned_free_16(mPositions);
-	ll_aligned_free_16(mNormals);
-	ll_aligned_free_16(mTexCoords);
-
+	delete [] mPositions;
+	delete [] mNormals;
+	delete [] mTexCoords;
+	
 	//point to new buffers
 	mPositions = new_pos;
 	mNormals = new_norm;
@@ -6399,7 +6393,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
 	new_count = mNumIndices + face.mNumIndices;
 
 	//allocate new index buffer
-	U16* new_indices = (U16*) ll_aligned_malloc_16((new_count*2+0xF) & ~0xF);
+	U16* new_indices = new U16[((new_count*2+0xF) & ~0xF)/2];
 	if (mNumIndices > 0)
 	{ //copy old index buffer
 		S32 old_size = (mNumIndices*2+0xF) & ~0xF;
@@ -6407,8 +6401,8 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
 	}
 
 	//free old index buffer
-	ll_aligned_free_16(mIndices);
-
+	delete [] mIndices;
+	
 	//point to new index buffer
 	mIndices = new_indices;
 
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index ff5e3d9dfa10b5a097fe7e116de6cd1bb52dd7e3..32364bd4b80063f6302374a56ef12982e8ab0492 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -882,7 +882,7 @@ public:
 	};
 
 	void optimize(F32 angle_cutoff = 2.f);
-	void createOctree(F32 scaler = 0.25f);
+	void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f));
 
 	enum
 	{
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 5949a373ae6e811d082d4a891154bc845a17c538..efbb62011c54666161a39b25652cfebe0b0cbd1e 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -191,15 +191,6 @@ LLVOVolume* LLDrawable::getVOVolume() const
 
 const LLMatrix4& LLDrawable::getRenderMatrix() const
 { 
-	if (LLDrawable::isState(LLDrawable::RIGGED))
-	{
-		LLVOAvatar* avatar = mVObjp->getAvatar();
-		if (avatar)
-		{
-			return avatar->mDrawable->getWorldMatrix();
-		}
-	}
-
 	return isRoot() ? getWorldMatrix() : getParent()->getWorldMatrix();
 }
 
@@ -727,8 +718,7 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
 		LLVOVolume* volume = getVOVolume();
 		if (volume)
 		{
-			volume->updateRelativeXform();
-			pos = volume->getRelativeXform().getTranslation();
+			pos.set(getPositionGroup().getF32ptr());
 			if (isStatic())
 			{
 				pos += volume->getRegion()->getOriginAgent();
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index ccc060f3fa2af23b9d7f82a2ea1a4c4553d820e1..5cf6082f124ac7db4e3aea790ca05b0c7c16ebd4 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -1325,6 +1325,12 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
 #if LL_MESH_ENABLED
 void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
 {
+	LLVector4a* weight = vol_face.mWeights;
+	if (!weight)
+	{
+		return;
+	}
+
 	LLVertexBuffer* buffer = face->mVertexBuffer;
 
 	U32 data_mask = 0;
@@ -1403,8 +1409,6 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
 			}
 		}
 
-		LLVector4a* weight = vol_face.mWeights;
-
 		LLMatrix4a bind_shape_matrix;
 		bind_shape_matrix.loadu(skin->mBindShapeMatrix);
 
@@ -1422,7 +1426,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
 			{
 				F32 w = weight[j][k];
 
-				idx[k] = (S32) floorf(w);
+				idx[k] = llclamp((S32) floorf(w), 0, 63);
 				wght[k] = w - floorf(w);
 				scale += wght[k];
 			}
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 9a178985cfdc5f6b20bfcd5df903338c0991a100..3fa60e9f1edc73dae772a1dfa01b9f70b6151f8d 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -556,8 +556,36 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
 		}
 
 		glColor4fv(color.mV);
-		mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
-		mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
+	
+		if (mDrawablep->isState(LLDrawable::RIGGED))
+		{
+			LLVOVolume* volume = mDrawablep->getVOVolume();
+			if (volume)
+			{
+				LLRiggedVolume* rigged = volume->getRiggedVolume();
+				if (rigged)
+				{
+					LLGLEnable offset(GL_POLYGON_OFFSET_FILL);
+					glPolygonOffset(-1.f, -1.f);
+					glMultMatrixf((F32*) volume->getRelativeXform().mMatrix);
+					const LLVolumeFace& vol_face = rigged->getVolumeFace(getTEOffset());
+					LLVertexBuffer::unbind();
+					glVertexPointer(3, GL_FLOAT, 16, vol_face.mPositions);
+					if (vol_face.mTexCoords)
+					{
+						glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+						glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords);
+					}
+					glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices);
+					glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+				}
+			}
+		}
+		else
+		{
+			mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
+			mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
+		}
 
 		gGL.popMatrix();
 	}
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index ff2929695db6f52e25b40193fb3856ffce8013ab..21f7e780e22db3e5ab3aa8fba8c1ad13e2f1c11f 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -5395,6 +5395,42 @@ BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power)
 	return (mPermissions->allowOperationBy(op, proxy_agent_id, group_id));
 }
 
+
+//helper function for pushing relevant vertices from drawable to GL
+void pushWireframe(LLDrawable* drawable)
+{
+	if (drawable->isState(LLDrawable::RIGGED))
+	{ //render straight from rigged volume if this is a rigged attachment
+		LLVOVolume* vobj = drawable->getVOVolume();
+		if (vobj)
+		{
+			vobj->updateRiggedVolume();
+			LLRiggedVolume* rigged_volume = vobj->getRiggedVolume();
+			if (rigged_volume)
+			{
+				LLVertexBuffer::unbind();
+				gGL.pushMatrix();
+				glMultMatrixf((F32*) vobj->getRelativeXform().mMatrix);
+				for (S32 i = 0; i < rigged_volume->getNumVolumeFaces(); ++i)
+				{
+					const LLVolumeFace& face = rigged_volume->getVolumeFace(i);
+					glVertexPointer(3, GL_FLOAT, 16, face.mPositions);
+					glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices);
+				}
+				gGL.popMatrix();
+			}
+		}
+	}
+	else
+	{
+		for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+		{
+			LLFace* face = drawable->getFace(i);
+			pushVerts(face, LLVertexBuffer::MAP_VERTEX);
+		}
+	}
+}
+
 void LLSelectNode::renderOneWireframe(const LLColor4& color)
 {
 	LLViewerObject* objectp = getObject();
@@ -5442,11 +5478,7 @@ void LLSelectNode::renderOneWireframe(const LLColor4& color)
 		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
 		{
 			glColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f);
-			for (S32 i = 0; i < drawable->getNumFaces(); ++i)
-			{
-				LLFace* face = drawable->getFace(i);
-				pushVerts(face, LLVertexBuffer::MAP_VERTEX);
-			}
+			pushWireframe(drawable);
 		}
 	}
 
@@ -5455,13 +5487,9 @@ void LLSelectNode::renderOneWireframe(const LLColor4& color)
 
 	glColor4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2);
 	LLGLEnable offset(GL_POLYGON_OFFSET_LINE);
-	glPolygonOffset(3.f, 2.f);
+	glPolygonOffset(3.f, 3.f);
 	glLineWidth(3.f);
-	for (S32 i = 0; i < drawable->getNumFaces(); ++i)
-	{
-		LLFace* face = drawable->getFace(i);
-		pushVerts(face, LLVertexBuffer::MAP_VERTEX);
-	}
+	pushWireframe(drawable);
 	glLineWidth(1.f);
 	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 	gGL.popMatrix();
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 191cdac981cb7b0f1a2a465fef6634ee3413af7a..0f9f35dc5771d4fcb9dee3900f1e7b08c59cd384 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -3121,9 +3121,11 @@ void renderRaycast(LLDrawable* drawablep)
 			LLVOVolume* vobj = drawablep->getVOVolume();
 			LLVolume* volume = vobj->getVolume();
 
+			bool transform = true;
 			if (drawablep->isState(LLDrawable::RIGGED))
 			{
-				volume = NULL;
+				volume = vobj->getRiggedVolume();
+				transform = false;
 			}
 
 			if (volume)
@@ -3140,8 +3142,16 @@ void renderRaycast(LLDrawable* drawablep)
 					glMultMatrixf((F32*) vobj->getRelativeXform().mMatrix);
 
 					LLVector3 start, end;
-					start = vobj->agentPositionToVolume(gDebugRaycastStart);
-					end = vobj->agentPositionToVolume(gDebugRaycastEnd);
+					if (transform)
+					{
+						start = vobj->agentPositionToVolume(gDebugRaycastStart);
+						end = vobj->agentPositionToVolume(gDebugRaycastEnd);
+					}
+					else
+					{
+						start = gDebugRaycastStart;
+						end = gDebugRaycastEnd;
+					}
 
 					LLVector4a starta, enda;
 					starta.load3(start.mV);
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 60bdfc24b9c3a51bcaf9b0fcc3cc2ffc8b748ffb..f09ce5b363f73a9f8079eda2e3cfc80cd4768df8 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1358,8 +1358,9 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
 
 	LLVector4a min,max;
 
-	BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION) || mRiggedVolume.notNull();
+	BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED);
 
+	bool rigged = false;
 	LLVolume* volume = mRiggedVolume;
 	if (!volume)
 	{
@@ -1424,10 +1425,19 @@ void LLVOVolume::updateRelativeXform()
 	
 	LLDrawable* drawable = mDrawable;
 	
-	if (drawable->isState(LLDrawable::RIGGED))
-	{
-		mRelativeXform.setIdentity();
-		mRelativeXformInvTrans.setIdentity();
+	if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull())
+	{ //rigged volume (which is in agent space) is used for generating bounding boxes etc
+	  //inverse of render matrix should go to partition space
+		mRelativeXform = getRenderMatrix();
+
+		F32* dst = (F32*) mRelativeXformInvTrans.mMatrix;
+		F32* src = (F32*) mRelativeXform.mMatrix;
+		dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2];
+		dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6];
+		dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10];
+		
+		mRelativeXform.invert();
+		mRelativeXformInvTrans.transpose();
 	}
 	else if (drawable->isActive())
 	{				
@@ -3421,12 +3431,15 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 
 	LLVolume* volume = getVolume();
 
+	bool transform = true;
+
 	if (mDrawable->isState(LLDrawable::RIGGED))
 	{
 		if (LLFloater::isVisible(gFloaterTools) && getAvatar()->isSelf())
 		{
 			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE);
 			volume = mRiggedVolume;
+			transform = false;
 		}
 		else
 		{ //cannot pick rigged attachments on other avatars or when not in build mode
@@ -3438,8 +3451,16 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 	{	
 		LLVector3 v_start, v_end, v_dir;
 	
-		v_start = agentPositionToVolume(start);
-		v_end = agentPositionToVolume(end);
+		if (transform)
+		{
+			v_start = agentPositionToVolume(start);
+			v_end = agentPositionToVolume(end);
+		}
+		else
+		{
+			v_start = start;
+			v_end = end;
+		}
 		
 		LLVector3 p;
 		LLVector3 n;
@@ -3499,18 +3520,40 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 					
 					if (intersection != NULL)
 					{
-						*intersection = volumePositionToAgent(p);  // must map back to agent space
+						if (transform)
+						{
+							*intersection = volumePositionToAgent(p);  // must map back to agent space
+						}
+						else
+						{
+							*intersection = p;
+						}
 					}
 
 					if (normal != NULL)
 					{
-						*normal = volumeDirectionToAgent(n);
+						if (transform)
+						{
+							*normal = volumeDirectionToAgent(n);
+						}
+						else
+						{
+							*normal = n;
+						}
+
 						(*normal).normVec();
 					}
 
 					if (bi_normal != NULL)
 					{
-						*bi_normal = volumeDirectionToAgent(bn);
+						if (transform)
+						{
+							*bi_normal = volumeDirectionToAgent(bn);
+						}
+						else
+						{
+							*bi_normal = bn;
+						}
 						(*bi_normal).normVec();
 					}
 
@@ -3528,18 +3571,49 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 	return ret;
 }
 
+bool LLVOVolume::treatAsRigged()
+{
+	return LLFloater::isVisible(gFloaterTools) && 
+			isAttachment() && 
+			getAvatar() &&
+			getAvatar()->isSelf() &&
+			mDrawable.notNull() &&
+			mDrawable->isState(LLDrawable::RIGGED);
+}
+
+LLRiggedVolume* LLVOVolume::getRiggedVolume()
+{
+	return mRiggedVolume;
+}
+
+void LLVOVolume::clearRiggedVolume()
+{
+	if (mRiggedVolume.notNull())
+	{
+		mRiggedVolume = NULL;
+		updateRelativeXform();
+	}
+}
+
 void LLVOVolume::updateRiggedVolume()
 {
 	//Update mRiggedVolume to match current animation frame of avatar. 
 	//Also update position/size in octree.  
 
+	if (!treatAsRigged())
+	{
+		clearRiggedVolume();
+		
+		return;
+	}
+
 	LLVolume* volume = getVolume();
 
 	const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID());
 
 	if (!skin)
 	{
-		mRiggedVolume = NULL;
+		clearRiggedVolume();
 		return;
 	}
 
@@ -3547,7 +3621,7 @@ void LLVOVolume::updateRiggedVolume()
 
 	if (!avatar)
 	{
-		mRiggedVolume = NULL;
+		clearRiggedVolume();
 		return;
 	}
 
@@ -3555,6 +3629,7 @@ void LLVOVolume::updateRiggedVolume()
 	{
 		LLVolumeParams p;
 		mRiggedVolume = new LLRiggedVolume(p);
+		updateRelativeXform();
 	}
 
 	mRiggedVolume->update(skin, avatar, volume);
@@ -3592,12 +3667,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
 	//build matrix palette
 	LLMatrix4a mp[64];
 	LLMatrix4* mat = (LLMatrix4*) mp;
-
-	LLMatrix4 agent_to_root;
-
-	LLVector4a origin;
-	origin.load3(avatar->getPositionAgent().mV);
-
+	
 	for (U32 j = 0; j < skin->mJointNames.size(); ++j)
 	{
 		LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
@@ -3661,7 +3731,6 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
 				LLVector4a dst;
 				bind_shape_matrix.affineTransform(v, t);
 				final_mat.affineTransform(t, dst);
-				dst.sub(origin);
 				pos[j] = dst;
 			}
 
@@ -3687,7 +3756,12 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
 			LLFastTimer t(FTM_RIGGED_OCTREE);
 			delete dst_face.mOctree;
 			dst_face.mOctree = NULL;
-			dst_face.createOctree(2.f);
+
+			LLVector4a size;
+			size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]);
+			size.splat(size.getLength3().getF32()*0.5f);
+			
+			dst_face.createOctree(1.f);
 		}
 	}
 }
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index d868099eeb162aa77506351f8a0c319264852b90..f058710a27a11e42c382ba692d29c52de6ecb9d3 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -306,7 +306,17 @@ public:
 
 	//rigged volume update (for raycasting)
 	void updateRiggedVolume();
-	LLRiggedVolume* getRiggedVolume() { return mRiggedVolume; }
+	LLRiggedVolume* getRiggedVolume();
+
+	//returns true if volume should be treated as a rigged volume
+	// - Build tools are open
+	// - object is an attachment
+	// - object is attached to self
+	// - object is rendered as rigged
+	bool treatAsRigged();
+
+	//clear out rigged volume and revert back to non-rigged state for picking/LOD/distance updates
+	void clearRiggedVolume();
 
 protected:
 	S32	computeLODDetail(F32	distance, F32 radius);