From 95aa437160ef732d584868a7d37cbe55d5959fa0 Mon Sep 17 00:00:00 2001 From: prep Date: Wed, 22 Feb 2012 12:00:37 -0500 Subject: Path-305: Added support for retrieving compressed navmeshes in a LLSD. --- indra/llcommon/llsdserialize.cpp | 83 +++++++++++++++++++++++++++++++++++++- indra/llcommon/llsdserialize.h | 2 +- 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[] = ""; 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 "<extractNavMeshSrcFromLLSD( stuff, mDir ); - pObserver->getPathfindingConsole()->setHasNavMeshReceived(); + const std::vector& 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 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 "<getPathfindingConsole()->setHasNoNavMesh(); } } } -} - +} private: //Observer handle LLHandle mObserverHandle; -- cgit v1.2.3