diff options
Diffstat (limited to 'indra/newview')
| -rw-r--r-- | indra/newview/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | indra/newview/lldrawable.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/lldrawable.h | 56 | ||||
| -rw-r--r-- | indra/newview/lldrawpoolavatar.cpp | 10 | ||||
| -rw-r--r-- | indra/newview/llface.cpp | 34 | ||||
| -rw-r--r-- | indra/newview/llfloatertools.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llselectmgr.cpp | 50 | ||||
| -rw-r--r-- | indra/newview/llspatialpartition.cpp | 109 | ||||
| -rw-r--r-- | indra/newview/llviewerobject.cpp | 14 | ||||
| -rw-r--r-- | indra/newview/llvovolume.cpp | 314 | ||||
| -rw-r--r-- | indra/newview/llvovolume.h | 32 | 
11 files changed, 554 insertions, 87 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 73f752b218..0f2d461511 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1422,9 +1422,7 @@ if (WINDOWS)      set_target_properties(${VIEWER_BINARY_NAME}          PROPERTIES -        # *TODO -reenable this once we get server usage sorted out -        #LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:\"__tcmalloc\"" -        LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS" +        LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:__tcmalloc"          LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO"          LINK_FLAGS_RELEASE ${release_flags}          ) @@ -1640,6 +1638,7 @@ if (WINDOWS)  endif (WINDOWS)  target_link_libraries(${VIEWER_BINARY_NAME} +	${GOOGLE_PERFTOOLS_LIBRARIES}      ${LLAUDIO_LIBRARIES}      ${LLCHARACTER_LIBRARIES}      ${LLIMAGE_LIBRARIES} @@ -1676,7 +1675,6 @@ target_link_libraries(${VIEWER_BINARY_NAME}      ${OPENSSL_LIBRARIES}      ${CRYPTO_LIBRARIES}      ${LLLOGIN_LIBRARIES} -    ${GOOGLE_PERFTOOLS_LIBRARIES}      ${LLCONVEXDECOMP_LIBRARY}      ) diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 68f52e04bc..efbb62011c 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -189,6 +189,11 @@ LLVOVolume* LLDrawable::getVOVolume() const  	}  } +const LLMatrix4& LLDrawable::getRenderMatrix() const +{  +	return isRoot() ? getWorldMatrix() : getParent()->getWorldMatrix(); +} +  BOOL LLDrawable::isLight() const  {  	LLViewerObject* objectp = mVObjp; @@ -713,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/lldrawable.h b/indra/newview/lldrawable.h index fc90bc57c4..a17e2172aa 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -101,7 +101,7 @@ public:  	LLVOVolume*	getVOVolume() const; // cast mVObjp tp LLVOVolume if OK  	const LLMatrix4&      getWorldMatrix() const		{ return mXform.getWorldMatrix(); } -	const LLMatrix4&	  getRenderMatrix() const		{ return isRoot() ? getWorldMatrix() : getParent()->getWorldMatrix(); } +	const LLMatrix4&	  getRenderMatrix() const;  	void				  setPosition(LLVector3 v) const { }  	const LLVector3&	  getPosition() const			{ return mXform.getPosition(); }  	const LLVector3&      getWorldPosition() const		{ return mXform.getPositionW(); } @@ -250,35 +250,37 @@ public:  	typedef enum e_drawable_flags  	{ - 		IN_REBUILD_Q1	= 0x00000002, - 		IN_REBUILD_Q2	= 0x00000004, - 		IN_LIGHT_Q		= 0x00000008, -		EARLY_MOVE		= 0x00000010, -		MOVE_UNDAMPED	= 0x00000020, -		ON_MOVE_LIST	= 0x00000040, -		USE_BACKLIGHT	= 0x00000080, -		UV				= 0x00000100, -		UNLIT			= 0x00000200, -		LIGHT			= 0x00000400, -		LIGHTING_BUILT	= 0x00000800, -		REBUILD_VOLUME  = 0x00001000,	//volume changed LOD or parameters, or vertex buffer changed -		REBUILD_TCOORD	= 0x00002000,	//texture coordinates changed -		REBUILD_COLOR	= 0x00004000,	//color changed -		REBUILD_POSITION= 0x00010000,	//vertex positions/normals changed + 		IN_REBUILD_Q1	= 0x00000001, + 		IN_REBUILD_Q2	= 0x00000002, + 		IN_LIGHT_Q		= 0x00000004, +		EARLY_MOVE		= 0x00000008, +		MOVE_UNDAMPED	= 0x00000010, +		ON_MOVE_LIST	= 0x00000020, +		USE_BACKLIGHT	= 0x00000040, +		UV				= 0x00000080, +		UNLIT			= 0x00000100, +		LIGHT			= 0x00000200, +		LIGHTING_BUILT	= 0x00000400, +		REBUILD_VOLUME  = 0x00000800,	//volume changed LOD or parameters, or vertex buffer changed +		REBUILD_TCOORD	= 0x00001000,	//texture coordinates changed +		REBUILD_COLOR	= 0x00002000,	//color changed +		REBUILD_POSITION= 0x00004000,	//vertex positions/normals changed  		REBUILD_GEOMETRY= REBUILD_POSITION|REBUILD_TCOORD|REBUILD_COLOR,  		REBUILD_MATERIAL= REBUILD_TCOORD|REBUILD_COLOR,  		REBUILD_ALL		= REBUILD_GEOMETRY|REBUILD_VOLUME, -		ON_SHIFT_LIST	= 0x00100000, -		BLOCKER			= 0x00400000, -		ACTIVE			= 0x00800000, -		DEAD			= 0x01000000, -		INVISIBLE		= 0x02000000, // stay invisible until flag is cleared - 		NEARBY_LIGHT	= 0x04000000, // In gPipeline.mNearbyLightSet -		BUILT			= 0x08000000, -		FORCE_INVISIBLE = 0x10000000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned) -		CLEAR_INVISIBLE = 0x20000000, // clear FORCE_INVISIBLE next draw frame -		REBUILD_SHADOW =  0x40000000, -		HAS_ALPHA		= 0x80000000, +		REBUILD_RIGGED	= 0x00008000, +		ON_SHIFT_LIST	= 0x00010000, +		BLOCKER			= 0x00020000, +		ACTIVE			= 0x00040000, +		DEAD			= 0x00080000, +		INVISIBLE		= 0x00100000, // stay invisible until flag is cleared + 		NEARBY_LIGHT	= 0x00200000, // In gPipeline.mNearbyLightSet +		BUILT			= 0x00400000, +		FORCE_INVISIBLE = 0x00800000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned) +		CLEAR_INVISIBLE = 0x01000000, // clear FORCE_INVISIBLE next draw frame +		REBUILD_SHADOW =  0x02000000, +		HAS_ALPHA		= 0x04000000, +		RIGGED			= 0x08000000,  	} EDrawableFlags;  	LLXformMatrix       mXform; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index ccc060f3fa..5cf6082f12 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 7c24eb77cd..3fa60e9f1e 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();  	} @@ -720,7 +748,7 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,  	LLMemType mt1(LLMemType::MTYPE_DRAWABLE);  	//get bounding box -	if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION)) +	if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED))  	{  		//VECTORIZE THIS  		LLMatrix4a mat_vert; diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index fa5d9b0892..653f838779 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -1016,10 +1016,12 @@ S32 LLFloaterTools::calcRenderCost()  		LLSelectNode *select_node = *selection_iter;  		if (select_node)  		{ -			LLVOVolume *viewer_volume = (LLVOVolume*)select_node->getObject(); -			if (viewer_volume) +			LLViewerObject *vobj = select_node->getObject(); +			if (vobj->getVolume())  			{ -				cost += viewer_volume->getRenderCost(textures); +				LLVOVolume* volume = (LLVOVolume*) vobj; + +				cost += volume->getRenderCost(textures);  				for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)  				{  					// add the cost of each individual texture in the linkset diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index ff2929695d..21f7e780e2 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 425fa42339..0f9f35dc57 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3035,11 +3035,11 @@ class LLRenderOctreeRaycast : public LLOctreeTriangleRayIntersect  {  public: -	LLRenderOctreeRaycast(const LLVector3& start, const LLVector3& end) +	 +	LLRenderOctreeRaycast(const LLVector4a& start, const LLVector4a& dir, F32* closest_t) +		: LLOctreeTriangleRayIntersect(start, dir, NULL, closest_t, NULL, NULL, NULL, NULL)  	{ -		mStart.load3(start.mV); -		mEnd.load3(end.mV); -		mDir.setSub(mEnd, mStart); +  	}  	void visit(const LLOctreeNode<LLVolumeTriangle>* branch) @@ -3047,9 +3047,22 @@ public:  		LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) branch->getListener(0);  		LLVector3 center, size; -		center.set(vl->mBounds[0].getF32ptr()); -		size.set(vl->mBounds[1].getF32ptr()); +		 +		if (branch->getData().empty()) +		{ +			gGL.color3f(1.f,0.2f,0.f); +			center.set(branch->getCenter().getF32ptr()); +			size.set(branch->getSize().getF32ptr()); +		} +		else +		{ +			gGL.color3f(0.75f, 1.f, 0.f); +			center.set(vl->mBounds[0].getF32ptr()); +			size.set(vl->mBounds[1].getF32ptr()); +		} +		drawBoxOutline(center, size);	 +		  		for (U32 i = 0; i < 2; i++)  		{  			LLGLDepthTest depth(GL_TRUE, GL_FALSE, i == 1 ? GL_LEQUAL : GL_GREATER); @@ -3061,9 +3074,14 @@ public:  			else  			{  				gGL.color4f(0,0.5f,0.5f, 0.25f); +				drawBoxOutline(center, size); +			} +			 +			if (i == 1) +			{ +				gGL.flush(); +				glLineWidth(3.f);  			} - -			drawBoxOutline(center, size);  			gGL.begin(LLRender::TRIANGLES);  			for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getData().begin(); @@ -3077,6 +3095,12 @@ public:  				gGL.vertex3fv(tri->mV[2]->getF32ptr());  			}	  			gGL.end(); + +			if (i == 1) +			{ +				gGL.flush(); +				glLineWidth(1.f); +			}  		}  	}  }; @@ -3096,26 +3120,63 @@ void renderRaycast(LLDrawable* drawablep)  			LLVOVolume* vobj = drawablep->getVOVolume();  			LLVolume* volume = vobj->getVolume(); -			for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + +			bool transform = true; +			if (drawablep->isState(LLDrawable::RIGGED))  			{ -				const LLVolumeFace& face = volume->getVolumeFace(i); -				if (!face.mOctree) +				volume = vobj->getRiggedVolume(); +				transform = false; +			} + +			if (volume) +			{ +				for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)  				{ -					((LLVolumeFace*) &face)->createOctree();  -				} +					const LLVolumeFace& face = volume->getVolumeFace(i); +					if (!face.mOctree) +					{ +						((LLVolumeFace*) &face)->createOctree();  +					} -				gGL.pushMatrix(); -				glMultMatrixf((F32*) vobj->getRelativeXform().mMatrix); -				LLVector3 start, end; -				start = vobj->agentPositionToVolume(gDebugRaycastStart); -				end = vobj->agentPositionToVolume(gDebugRaycastEnd); +					gGL.pushMatrix(); +					glMultMatrixf((F32*) vobj->getRelativeXform().mMatrix); -				LLRenderOctreeRaycast render(start, end); -				gGL.flush(); -				glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -				render.traverse(face.mOctree); -				gGL.popMatrix();		 -				glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +					LLVector3 start, end; +					if (transform) +					{ +						start = vobj->agentPositionToVolume(gDebugRaycastStart); +						end = vobj->agentPositionToVolume(gDebugRaycastEnd); +					} +					else +					{ +						start = gDebugRaycastStart; +						end = gDebugRaycastEnd; +					} + +					LLVector4a starta, enda; +					starta.load3(start.mV); +					enda.load3(end.mV); +					LLVector4a dir; +					dir.setSub(enda, starta); + +					F32 t = 1.f; + +					LLRenderOctreeRaycast render(starta, dir, &t); +					gGL.flush(); +					glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + +					{ +						//render face positions +						LLVertexBuffer::unbind(); +						glColor4f(0,1,1,0.5f); +						glVertexPointer(3, GL_FLOAT, sizeof(LLVector4a), face.mPositions); +						glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices); +					} +						 +					render.traverse(face.mOctree); +					gGL.popMatrix();		 +					glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +				}  			}  		}  		else if (drawablep->isAvatar()) diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index fd2212f25d..4c1a1958e8 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -3279,6 +3279,15 @@ const LLVector3 LLViewerObject::getPositionEdit() const  const LLVector3 LLViewerObject::getRenderPosition() const  { +	if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED)) +	{ +		LLVOAvatar* avatar = getAvatar(); +		if (avatar) +		{ +			return avatar->getPositionAgent(); +		} +	} +  	if (mDrawable.isNull() || mDrawable->getGeneration() < 0)  	{  		return getPositionAgent(); @@ -3297,6 +3306,11 @@ const LLVector3 LLViewerObject::getPivotPositionAgent() const  const LLQuaternion LLViewerObject::getRenderRotation() const  {  	LLQuaternion ret; +	if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED)) +	{ +		return ret; +	} +	  	if (mDrawable.isNull() || mDrawable->isStatic())  	{  		ret = getRotationEdit(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 5448e7dcd9..f09ce5b363 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -41,9 +41,11 @@  #include "llviewercontrol.h"  #include "lldir.h"  #include "llflexibleobject.h" +#include "llfloatertools.h"  #include "llmaterialtable.h"  #include "llprimitive.h"  #include "llvolume.h" +#include "llvolumeoctree.h"  #include "llvolumemgr.h"  #include "llvolumemessage.h"  #include "material_codes.h" @@ -70,6 +72,7 @@  #include "llselectmgr.h"  #include "pipeline.h"  #include "llsdutil.h" +#include "llmatrix4a.h"  #include "llmediaentry.h"  #include "llmediadataclient.h"  #include "llmeshrepository.h" @@ -1355,7 +1358,14 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)  	LLVector4a min,max; -	BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION); +	BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); + +	bool rigged = false; +	LLVolume* volume = mRiggedVolume; +	if (!volume) +	{ +		volume = getVolume(); +	}  	for (S32 i = 0; i < getVolume()->getNumVolumeFaces(); i++)  	{ @@ -1364,7 +1374,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)  		{  			continue;  		} -		res &= face->genVolumeBBoxes(*getVolume(), i, +		res &= face->genVolumeBBoxes(*volume, i,  										mRelativeXform, mRelativeXformInvTrans,  										(mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); @@ -1415,7 +1425,21 @@ void LLVOVolume::updateRelativeXform()  	LLDrawable* drawable = mDrawable; -	if (drawable->isActive()) +	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())  	{				  		// setup relative transforms  		LLQuaternion delta_rot; @@ -1497,11 +1521,22 @@ void LLVOVolume::updateRelativeXform()  static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies");  static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives"); +static LLFastTimer::DeclareTimer FTM_UPDATE_RIGGED_VOLUME("Update Rigged");  BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  {  	LLFastTimer t(FTM_UPDATE_PRIMITIVES); +	if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) +	{ +		{ +			LLFastTimer t(FTM_UPDATE_RIGGED_VOLUME); +			updateRiggedVolume(); +		} +		genBBoxes(FALSE); +		mDrawable->clearState(LLDrawable::REBUILD_RIGGED); +	} +  	if (mVolumeImpl != NULL)  	{  		BOOL res; @@ -1597,7 +1632,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  	{  		LLPipeline::sCompiles++;  	} -	 +		  	mVolumeChanged = FALSE;  	mLODChanged = FALSE;  	mSculptChanged = FALSE; @@ -2724,6 +2759,11 @@ BOOL LLVOVolume::isVolumeGlobal() const  	{  		return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE;  	} +	else if (mRiggedVolume.notNull()) +	{ +		return TRUE; +	} +  	return FALSE;  } @@ -3390,12 +3430,37 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e  	BOOL ret = FALSE;  	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 +			return FALSE; +		} +	} +	  	if (volume)  	{	  		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; @@ -3455,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();  					} @@ -3484,6 +3571,201 @@ 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) +	{ +		clearRiggedVolume(); +		return; +	} + +	LLVOAvatar* avatar = getAvatar(); + +	if (!avatar) +	{ +		clearRiggedVolume(); +		return; +	} + +	if (!mRiggedVolume) +	{ +		LLVolumeParams p; +		mRiggedVolume = new LLRiggedVolume(p); +		updateRelativeXform(); +	} + +	mRiggedVolume->update(skin, avatar, volume); + +} + +static LLFastTimer::DeclareTimer FTM_SKIN_RIGGED("Skin"); +static LLFastTimer::DeclareTimer FTM_RIGGED_OCTREE("Octree"); + +void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume) +{ +	bool copy = false; +	if (volume->getNumVolumeFaces() != getNumVolumeFaces()) +	{  +		copy = true; +	} + +	for (S32 i = 0; i < volume->getNumVolumeFaces() && !copy; ++i) +	{ +		const LLVolumeFace& src_face = volume->getVolumeFace(i); +		const LLVolumeFace& dst_face = getVolumeFace(i); + +		if (src_face.mNumIndices != dst_face.mNumIndices || +			src_face.mNumVertices != dst_face.mNumVertices) +		{ +			copy = true; +		} +	} + +	if (copy) +	{ +		copyVolumeFaces(volume);	 +	} + +	//build matrix palette +	LLMatrix4a mp[64]; +	LLMatrix4* mat = (LLMatrix4*) mp; +	 +	for (U32 j = 0; j < skin->mJointNames.size(); ++j) +	{ +		LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); +		if (joint) +		{ +			mat[j] = skin->mInvBindMatrix[j]; +			mat[j] *= joint->getWorldMatrix(); +		} +	} + +	for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) +	{ +		const LLVolumeFace& vol_face = volume->getVolumeFace(i); +		 +		LLVolumeFace& dst_face = mVolumeFaces[i]; +		 +		LLVector4a* weight = vol_face.mWeights; + +		LLMatrix4a bind_shape_matrix; +		bind_shape_matrix.loadu(skin->mBindShapeMatrix); + +		LLVector4a* pos = dst_face.mPositions; + +		{ +			LLFastTimer t(FTM_SKIN_RIGGED); + +			for (U32 j = 0; j < dst_face.mNumVertices; ++j) +			{ +				LLMatrix4a final_mat; +				final_mat.clear(); + +				S32 idx[4]; + +				LLVector4 wght; + +				F32 scale = 0.f; +				for (U32 k = 0; k < 4; k++) +				{ +					F32 w = weight[j][k]; + +					idx[k] = (S32) floorf(w); +					wght[k] = w - floorf(w); +					scale += wght[k]; +				} + +				wght *= 1.f/scale; + +				for (U32 k = 0; k < 4; k++) +				{ +					F32 w = wght[k]; + +					LLMatrix4a src; +					src.setMul(mp[idx[k]], w); + +					final_mat.add(src); +				} + +				 +				LLVector4a& v = vol_face.mPositions[j]; +				LLVector4a t; +				LLVector4a dst; +				bind_shape_matrix.affineTransform(v, t); +				final_mat.affineTransform(t, dst); +				pos[j] = dst; +			} + +			//update bounding box +			LLVector4a& min = dst_face.mExtents[0]; +			LLVector4a& max = dst_face.mExtents[1]; + +			min = pos[0]; +			max = pos[1]; + +			for (U32 j = 1; j < dst_face.mNumVertices; ++j) +			{ +				min.setMin(min, pos[j]); +				max.setMax(max, pos[j]); +			} + +			dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); +			dst_face.mCenter->mul(0.5f); + +		} + +		{ +			LLFastTimer t(FTM_RIGGED_OCTREE); +			delete dst_face.mOctree; +			dst_face.mOctree = NULL; + +			LLVector4a size; +			size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); +			size.splat(size.getLength3().getF32()*0.5f); +			 +			dst_face.createOctree(1.f); +		} +	} +} +  U32 LLVOVolume::getPartitionType() const  {  	if (isHUDAttachment()) @@ -3732,6 +4014,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  		bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); +		bool is_rigged = false; +  		//for each face  		for (S32 i = 0; i < drawablep->getNumFaces(); i++)  		{ @@ -3747,8 +4031,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  					facep->mVertexBuffer = NULL;  					facep->mLastVertexBuffer = NULL;  				} -				 +		  				facep->setState(LLFace::RIGGED); +				is_rigged = true;  				//get drawpool of avatar with rigged face  				LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); @@ -3958,6 +4243,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  				facep->mLastVertexBuffer = NULL;  			}		  		} + +		if (is_rigged) +		{ +			drawablep->setState(LLDrawable::RIGGED); +		} +		else +		{ +			drawablep->clearState(LLDrawable::RIGGED); +		}  	}  	group->mBufferUsage = useage; diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index eeb98726c9..f058710a27 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -46,6 +46,8 @@ class LLDrawPool;  class LLSelectNode;  class LLObjectMediaDataClient;  class LLObjectMediaNavigateClient; +class LLVOAvatar; +class LLMeshSkinInfo;  typedef std::vector<viewer_media_t> media_list_t; @@ -54,6 +56,18 @@ enum LLVolumeInterfaceType  	INTERFACE_FLEXIBLE = 1,  }; + +class LLRiggedVolume : public LLVolume +{ +public: +	LLRiggedVolume(const LLVolumeParams& params) +		: LLVolume(params, 0.f) +	{ +	} + +	void update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* src_volume); +}; +  // Base class for implementations of the volume - Primitive, Flexible Object, etc.  class LLVolumeInterface  { @@ -289,6 +303,21 @@ public:  	void removeMDCImpl() { --mMDCImplCount; }  	S32 getMDCImplCount() { return mMDCImplCount; } + +	//rigged volume update (for raycasting) +	void updateRiggedVolume(); +	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);  	BOOL calcLOD(); @@ -322,6 +351,9 @@ private:  	S32			mLastFetchedMediaVersion; // as fetched from the server, starts as -1  	S32 mIndexInTex;  	S32 mMDCImplCount; + +	LLPointer<LLRiggedVolume> mRiggedVolume; +  	// statics  public:  	static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop  | 
