diff options
| author | prep <prep@lindenlab.com> | 2012-02-22 12:00:37 -0500 | 
|---|---|---|
| committer | prep <prep@lindenlab.com> | 2012-02-22 12:00:37 -0500 | 
| commit | 95aa437160ef732d584868a7d37cbe55d5959fa0 (patch) | |
| tree | 9206af968a68976b1c65556f5793c2ee67c38469 | |
| parent | 06970dd907db7a7c5ebe950c0e74e10bab13483d (diff) | |
Path-305: Added support for retrieving compressed navmeshes in a LLSD.
| -rw-r--r-- | indra/llcommon/llsdserialize.cpp | 83 | ||||
| -rw-r--r-- | indra/llcommon/llsdserialize.h | 2 | ||||
| -rw-r--r-- | indra/newview/llnavmeshstation.cpp | 51 | 
3 files changed, 122 insertions, 14 deletions
| diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index bf62600514..4722421fca 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -55,6 +55,10 @@ static const char LEGACY_NON_HEADER[] = "<llsd>";  const std::string LLSD_BINARY_HEADER("LLSD/Binary");  const std::string LLSD_XML_HEADER("LLSD/XML"); +//used to deflate a gzipped asset (currently used for navmeshes) +#define windowBits 15
 +#define ENABLE_ZLIB_GZIP 32
 +  /**   * LLSDSerialize   */ @@ -2096,7 +2100,7 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)  	strm.next_in = in;  	S32 ret = inflateInit(&strm); - +	  	do  	{  		strm.avail_out = CHUNK; @@ -2159,12 +2163,87 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)  			llwarns << "Failed to unzip LLSD block" << llendl;  			free(result);  			return false; -		} +		}		  	}  	free(result);  	return true;  } +//This unzip function will only work with a gzip header and trailer - while the contents +//of the actual compressed data is the same for either format (gzip vs zlib ), the headers +//and trailers are different for the formats. +U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size ) +{ +	U8* result = NULL; +	U32 cur_size = 0; +	z_stream strm; +		 +	const U32 CHUNK = 0x4000; +	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 = inflateInit2(&strm,  windowBits | ENABLE_ZLIB_GZIP ); +	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; +			valid = 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; +			valid = 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 (ret == Z_OK); + +	inflateEnd(&strm); +	delete [] in; + +	if (ret != Z_STREAM_END) +	{ +		free(result); +		valid = false; +		return NULL; +	} + +	//result now points to the decompressed LLSD block +	{ +		outsize= cur_size; +		valid = true;		 +	} + +	return result; +} diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index 99a3ea3cd4..86e3fc864c 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -793,5 +793,5 @@ 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); - +LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize,std::istream& is, S32 size);  #endif // LL_LLSDSERIALIZE_H diff --git a/indra/newview/llnavmeshstation.cpp b/indra/newview/llnavmeshstation.cpp index 87f7e92ddd..54a945e562 100644 --- a/indra/newview/llnavmeshstation.cpp +++ b/indra/newview/llnavmeshstation.cpp @@ -32,7 +32,7 @@  #include "llviewerregion.h"  #include "llsdutil.h"  #include "llfloaterpathfindingconsole.h" - +#include "llsdserialize.h"  //===============================================================================  LLNavMeshStation::LLNavMeshStation()  { @@ -48,8 +48,7 @@ public:  	}  	void error( U32 statusNum, const std::string& reason ) -	{ -		//statusNum; +	{	  		llwarns	<< "Transport error "<<reason<<llendl;			  	} @@ -65,23 +64,53 @@ public:  		{  			LLNavMeshDownloadObserver* pObserver = mObserverHandle.get();  			if ( pObserver ) -			{ -				 +			{				  				if ( content.has("navmesh_data") )  				{ -					const LLSD::Binary& stuff = content["navmesh_data"].asBinary(); -					LLPathingLib::getInstance()->extractNavMeshSrcFromLLSD( stuff, mDir ); -					pObserver->getPathfindingConsole()->setHasNavMeshReceived(); +					const std::vector<U8>& value = content["navmesh_data"].asBinary();
 +					unsigned int binSize = value.size();
 +					U8* pBinBuffer = new U8[binSize];
 +					memcpy( &pBinBuffer[0], &value[0], binSize );
 +					std::string newStr((char*) pBinBuffer, binSize );
 +                    std::istringstream streamdecomp( newStr );                 
 +					unsigned int decompBinSize = 0;
 +					bool valid = false;
 +					if ( pBinBuffer ) 
 +					{
 +						delete [] pBinBuffer ;
 +					}
 +					U8* pUncompressedNavMeshContainer = unzip_llsdNavMesh( valid, decompBinSize, streamdecomp, binSize ) ;
 +					if ( !valid )
 +                    {
 +						if ( pUncompressedNavMeshContainer )
 +						{
 +							free( pUncompressedNavMeshContainer );
 +						}
 +                        llwarns << "Unable to decompress the navmesh llsd." << llendl;
 +						pObserver->getPathfindingConsole()->setHasNoNavMesh();
 +                        return;
 +                    }
 +                    else
 +                    {                    
 +						if ( pUncompressedNavMeshContainer )
 +						{
 +							std::vector<U8> lsd;
 +							lsd.resize( decompBinSize );
 +							memcpy( &lsd[0], &pUncompressedNavMeshContainer[0], decompBinSize );
 +							LLPathingLib::getInstance()->extractNavMeshSrcFromLLSD( lsd, mDir );
 +							pObserver->getPathfindingConsole()->setHasNavMeshReceived();
 +							free( pUncompressedNavMeshContainer );
 +						}
 +                    }					  				}  				else  				{ -					llwarns<<"no mesh data "<<llendl; +					llwarns<<"No mesh data received"<<llendl;  					pObserver->getPathfindingConsole()->setHasNoNavMesh();  				}  			}  		}	 -}	 -	 +}		  private:  	//Observer handle  	LLHandle<LLNavMeshDownloadObserver> mObserverHandle; | 
