diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llcommon/llsdserialize.cpp | 139 | ||||
| -rw-r--r-- | indra/llcommon/llsdserialize.h | 4 | ||||
| -rw-r--r-- | indra/llmath/llvolume.cpp | 141 | ||||
| -rw-r--r-- | indra/llmath/llvolume.h | 6 | ||||
| -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/llrender/llvertexbuffer.cpp | 14 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.h | 5 | ||||
| -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 | 
19 files changed, 452 insertions, 97 deletions
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index cf337be161..fdeb93e27f 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -39,6 +39,7 @@  #include <iostream>  #include "apr_base64.h" +#include "zlib/zlib.h"  // for davep's dirty little zip functions  #if !LL_WINDOWS  #include <netinet/in.h> // htonl & ntohl @@ -1989,3 +1990,141 @@ std::ostream& operator<<(std::ostream& s, const LLSD& llsd)  	return s;  } + +//dirty little zippers -- yell at davep if these are horrid + +//return a string containing gzipped bytes of binary serialized LLSD +// VERY inefficient -- creates several copies of LLSD block in memory +std::string zip_llsd(LLSD& data) +{  +	std::stringstream llsd_strm; + +	LLSDSerialize::serialize(data, llsd_strm, LLSDSerialize::LLSD_BINARY); + +	z_stream strm; +	strm.zalloc = Z_NULL; +	strm.zfree = Z_NULL; +	strm.opaque = Z_NULL; + +	S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION); +	if (ret != Z_OK) +	{ +		llwarns << "Failed to compress LLSD block." << llendl; +		return std::string(); +	} + +	std::string source = llsd_strm.str(); + +	strm.avail_in = source.size(); +	strm.next_in = (U8*) source.data(); +	U8* output = new U8[strm.avail_in]; +	strm.avail_out = strm.avail_in; +	strm.next_out = output; +	ret = deflate(&strm, Z_FINISH); +	if (ret != Z_STREAM_END) +	{ +		delete [] output; +		llwarns << "Failed to compress LLSD block." << llendl; +		return std::string(); +	} + +	std::string::size_type size = source.size()-strm.avail_out; + +	std::string result((char*) output, size); +	deflateEnd(&strm); +	delete [] output; + +	return result; +} + +//decompress a block of LLSD from provided istream +// not very efficient -- creats a copy of decompressed LLSD block in memory +// and deserializes from that copy using LLSDSerialize +bool unzip_llsd(LLSD& data, std::istream& is, S32 size) +{ +	U8* result = NULL; +	U32 cur_size = 0; +	z_stream strm; +		 +	const U32 CHUNK = 65536; + +	U8 *in = new U8[size]; +	is.read((char*) in, size);  + +	U8 out[CHUNK]; +		 +	strm.zalloc = Z_NULL; +	strm.zfree = Z_NULL; +	strm.opaque = Z_NULL; +	strm.avail_in = size; +	strm.next_in = in; + +	S32 ret = inflateInit(&strm); + +	if (ret != Z_OK) +	{ +		llerrs << "WTF?" << llendl; +	} +	 +	do +	{ +		strm.avail_out = CHUNK; +		strm.next_out = out; +		ret = inflate(&strm, Z_NO_FLUSH); +		if (ret == Z_STREAM_ERROR) +		{ +			inflateEnd(&strm); +			free(result); +			delete [] in; +			return false; +		} +		 +		switch (ret) +		{ +		case Z_NEED_DICT: +			ret = Z_DATA_ERROR; +		case Z_DATA_ERROR: +		case Z_MEM_ERROR: +			inflateEnd(&strm); +			free(result); +			delete [] in; +			return false; +			break; +		} + +		U32 have = CHUNK-strm.avail_out; + +		result = (U8*) realloc(result, cur_size + have); +		memcpy(result+cur_size, out, have); +		cur_size += have; + +	} while (strm.avail_out == 0); + +	inflateEnd(&strm); +	delete [] in; + +	if (ret != Z_STREAM_END) +	{ +		free(result); +		return false; +	} + +	//result now points to the decompressed LLSD block +	{ +		std::string res_str((char*) result, cur_size); +		std::istringstream istr(res_str); + +		if (!LLSDSerialize::deserialize(data, istr, cur_size)) +		{ +			llwarns << "Failed to unzip LLSD block" << llendl; +			free(result); +			return false; +		} +	} + +	free(result); +	return true; +} + + + diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index 2f2b292189..390eaca783 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -796,4 +796,8 @@ public:  	}  }; +//dirty little zip functions -- yell at davep +LL_COMMON_API std::string zip_llsd(LLSD& data); +LL_COMMON_API bool unzip_llsd(LLSD& data, std::istream& is, S32 size); +  #endif // LL_LLSDSERIALIZE_H diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 52a3fb2195..fdd48b9e9e 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -47,8 +47,6 @@  #include "llvolume.h"  #include "llstl.h"  #include "llsdserialize.h" -#include "zlib/zlib.h" -  #define DEBUG_SILHOUETTE_BINORMALS 0  #define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette @@ -1964,97 +1962,15 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is)  bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  { -	U8* result = NULL; -	U32 cur_size = 0; - -	{ -		//input stream is now pointing at a zlib compressed block of LLSD -		//decompress block -		z_stream strm; -		 -		const U32 CHUNK = 65536; - -		U8 *in = new U8[size]; -		is.read((char*) in, size);  - -		U8 out[CHUNK]; -			 -		strm.zalloc = Z_NULL; -		strm.zfree = Z_NULL; -		strm.opaque = Z_NULL; -		strm.avail_in = size; -		strm.next_in = in; - -		S32 ret = inflateInit(&strm); - -		if (ret != Z_OK) -		{ -			llerrs << "WTF?" << llendl; -		} -		 -		do -		{ -			strm.avail_out = CHUNK; -			strm.next_out = out; -			ret = inflate(&strm, Z_NO_FLUSH); -			if (ret == Z_STREAM_ERROR) -			{ -				inflateEnd(&strm); -				free(result); -				delete [] in; -				return false; -			} -			 -			switch (ret) -			{ -			case Z_NEED_DICT: -				ret = Z_DATA_ERROR; -			case Z_DATA_ERROR: -			case Z_MEM_ERROR: -				inflateEnd(&strm); -				free(result); -				delete [] in; -				return false; -				break; -			} - -			U32 have = CHUNK-strm.avail_out; - -			result = (U8*) realloc(result, cur_size + have); -			memcpy(result+cur_size, out, have); -			cur_size += have; - -		} while (strm.avail_out == 0); - -		inflateEnd(&strm); -		delete [] in; - -		if (ret != Z_STREAM_END) -		{ -			free(result); -			return false; -		} -	} - -	//result now points to the decompressed LLSD block - +	//input stream is now pointing at a zlib compressed block of LLSD +	//decompress block  	LLSD mdl; - +	if (!unzip_llsd(mdl, is, size))  	{ -		std::string res_str((char*) result, cur_size); -		std::istringstream istr(res_str); - -		if (!LLSDSerialize::deserialize(mdl, istr, cur_size)) -		{ -			llwarns << "not a valid mesh asset!" << llendl; -			return false; -		} +		llwarns << "not a valid mesh asset!" << llendl; +		return false;  	} - - -	free(result); - - +	  	{  		U32 face_count = mdl.size(); @@ -2094,11 +2010,56 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  			U32 num_verts = pos.size()/(3*2);  			face.mVertices.resize(num_verts); +			if (mdl[i].has("Weights")) +			{ +				face.mWeights.resize(num_verts); + +				LLSD::Binary weights = mdl[i]["Weights"]; + +				U32 idx = 0; + +				U32 cur_vertex = 0; +				while (idx < weights.size() && cur_vertex < num_verts) +				{ +					const U8 END_INFLUENCES = 0xFF; +					U8 joint = weights[idx++]; + +					U32 cur_influence = 0; +					while (joint != END_INFLUENCES) +					{ +						U16 influence = weights[idx++]; +						influence = influence << 8; +						influence |= weights[idx++]; + +						F32 w = llmin((F32) influence / 65535.f, 0.99999f); +						face.mWeights[cur_vertex].mV[cur_influence++] = (F32) joint + w; + +						if (cur_influence >= 4) +						{ +							joint = END_INFLUENCES; +						} +						else +						{ +							joint = weights[idx++]; +						} +					} + +					cur_vertex++; +				} + +				if (cur_vertex != num_verts || idx != weights.size()) +				{ +					llwarns << "Vertex weight count does not match vertex count!" << llendl; +				} +					 +			} +  			LLVector3 min_pos;  			LLVector3 max_pos;  			LLVector2 min_tc;   			LLVector2 max_tc;  +		  			min_pos.setValue(mdl[i]["PositionDomain"]["Min"]);  			max_pos.setValue(mdl[i]["PositionDomain"]["Max"]);  			min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 60c1569e55..c6a156ae37 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -49,6 +49,7 @@ class LLVolume;  //#include "vmath.h"  #include "v2math.h"  #include "v3math.h" +#include "v4math.h"  #include "llquaternion.h"  #include "llstrider.h"  #include "v4coloru.h" @@ -887,6 +888,11 @@ public:  	std::vector<U16>	mTriStrip;  	std::vector<S32>	mEdge; +	//list of skin weights for rigged volumes +	// format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight> +	// mWeights.size() should be empty or match mVertices.size()   +	std::vector<LLVector4> mWeights; +  private:  	BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);  	BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE); 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/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 4064e688e8..d5b00f27a7 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -62,6 +62,7 @@ BOOL LLVertexBuffer::sIBOActive = FALSE;  U32 LLVertexBuffer::sAllocatedBytes = 0;  BOOL LLVertexBuffer::sMapped = FALSE;  BOOL LLVertexBuffer::sUseStreamDraw = TRUE; +S32	LLVertexBuffer::sWeight4Loc = -1;  std::vector<U32> LLVertexBuffer::sDeleteList; @@ -76,6 +77,7 @@ S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =  	sizeof(LLColor4U), // TYPE_COLOR,  	sizeof(LLVector3), // TYPE_BINORMAL,  	sizeof(F32),	   // TYPE_WEIGHT, +	sizeof(LLVector4), // TYPE_WEIGHT4,  	sizeof(LLVector4), // TYPE_CLOTHWEIGHT,  }; @@ -1015,6 +1017,12 @@ bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index)  {  	return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index);  } + +bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index) +{ +	return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index); +} +  bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index)  {  	return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index); @@ -1284,6 +1292,12 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  	{  		glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT]));  	} + +	if (data_mask & MAP_WEIGHT4 && sWeight4Loc != -1) +	{ +		glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, stride, (void*)(base+mOffsets[TYPE_WEIGHT4])); +	} +  	if (data_mask & MAP_CLOTHWEIGHT)  	{  		glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE,  stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index e2fecdffef..225237215c 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -84,6 +84,8 @@ public:  	static LLVBOPool sStreamIBOPool;  	static LLVBOPool sDynamicIBOPool; +	static S32	sWeight4Loc; +  	static BOOL	sUseStreamDraw;  	static void initClass(bool use_vbo); @@ -109,6 +111,7 @@ public:  		// These use VertexAttribPointer and should possibly be made generic  		TYPE_BINORMAL,  		TYPE_WEIGHT, +		TYPE_WEIGHT4,  		TYPE_CLOTHWEIGHT,  		TYPE_MAX,  		TYPE_INDEX, @@ -124,6 +127,7 @@ public:  		// These use VertexAttribPointer and should possibly be made generic  		MAP_BINORMAL = (1<<TYPE_BINORMAL),  		MAP_WEIGHT = (1<<TYPE_WEIGHT), +		MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),  		MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT),  	}; @@ -173,6 +177,7 @@ public:  	bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0);  	bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0);  	bool getWeightStrider(LLStrider<F32>& strider, S32 index=0); +	bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0);  	bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0);  	BOOL isEmpty() const					{ return mEmpty; } 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 540cb47710..0e75da4677 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" @@ -3637,6 +3639,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;  | 
