diff options
52 files changed, 1690 insertions, 1668 deletions
| diff --git a/autobuild.xml b/autobuild.xml index cd1e96c799..86a2f4ab2e 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -606,9 +606,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>9f8a9dc39fd7c3da0fb3533782d1fddf</string> +              <string>bd6f84f9fb3c2e68850676d06935373f</string>                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-freetype/rev/226814/arch/Linux/installer/freetype-2.3.9-linux-20110418.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-freetype/rev/271684/arch/Linux/installer/freetype-2.4.4-linux-20130312.tar.bz2</string>              </map>              <key>name</key>              <string>linux</string> diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 452fd5f356..aa1d50b993 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -128,6 +128,17 @@ if (LINUX)    # Let's actually get a numerical version of gxx's version    STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION_NUMBER ${CXX_VERSION}) +  # Hacks to work around gcc 4.1 TC build pool machines which can't process pragma warning disables +  # This is pure rubbish; I wish there was another way. +  # +  if(${CXX_VERSION_NUMBER} LESS 420) +    set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-uninitialized -Wno-unused-variable -Wno-unused-function ${CMAKE_CXX_FLAGS}") +  endif (${CXX_VERSION_NUMBER} LESS 420) + +  if(${CXX_VERSION_NUMBER} GREATER 459) +    set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-unused-but-set-variable -Wno-unused-variable ${CMAKE_CXX_FLAGS}") +  endif (${CXX_VERSION_NUMBER} GREATER 459) +    # gcc 4.3 and above don't like the LL boost and also    # cause warnings due to our use of deprecated headers    if(${CXX_VERSION_NUMBER} GREATER 429) @@ -218,7 +229,7 @@ if (LINUX OR DARWIN)    set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs")    if (NOT GCC_DISABLE_FATAL_WARNINGS) -    set(GCC_WARNINGS "${GCC_WARNINGS} -Werror") +#    set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")    endif (NOT GCC_DISABLE_FATAL_WARNINGS)    set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor") diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index c32e357da3..1551b0e3f7 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -266,6 +266,7 @@ elseif(LINUX)          libdb-5.1.so          libexpat.so          libexpat.so.1 +        libfreetype.so.6          libglod.so          libgmock_main.so          libgmock.so.0 diff --git a/indra/cmake/FreeType.cmake b/indra/cmake/FreeType.cmake index 43a9d282d0..c9a90a9a8d 100644 --- a/indra/cmake/FreeType.cmake +++ b/indra/cmake/FreeType.cmake @@ -7,13 +7,7 @@ if (STANDALONE)    pkg_check_modules(FREETYPE REQUIRED freetype2)  else (STANDALONE)    use_prebuilt_binary(freetype) -  if (LINUX) -    set(FREETYPE_INCLUDE_DIRS -        ${LIBS_PREBUILT_DIR}/include) -  else (LINUX) -    set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) -  endif (LINUX) - +  set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)    set(FREETYPE_LIBRARIES freetype)  endif (STANDALONE) diff --git a/indra/linux_crash_logger/CMakeLists.txt b/indra/linux_crash_logger/CMakeLists.txt index 98ebdc7487..5263b59584 100644 --- a/indra/linux_crash_logger/CMakeLists.txt +++ b/indra/linux_crash_logger/CMakeLists.txt @@ -12,6 +12,7 @@ include(LLVFS)  include(LLXML)  include(Linking)  include(UI) +include(FreeType)  include_directories(      ${LLCOMMON_INCLUDE_DIRS} @@ -53,6 +54,7 @@ target_link_libraries(linux-crash-logger      ${LLCOMMON_LIBRARIES}      ${UI_LIBRARIES}      ${DB_LIBRARIES} +    ${FREETYPE_LIBRARIES}      )  add_custom_target(linux-crash-logger-target ALL diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index e019c17280..0c2ceebb52 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -121,6 +121,7 @@ set(llcommon_HEADER_FILES      linden_common.h      linked_lists.h      llaccountingcost.h +    llalignedarray.h      llallocator.h      llallocator_heap_profile.h      llagentconstants.h diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h new file mode 100644 index 0000000000..ed8fd31205 --- /dev/null +++ b/indra/llcommon/llalignedarray.h @@ -0,0 +1,139 @@ +/**  + * @file llalignedarray.h + * @brief A static array which obeys alignment restrictions and mimics std::vector accessors. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLALIGNEDARRAY_H +#define LL_LLALIGNEDARRAY_H + +#include "llmemory.h" + +template <class T, U32 alignment> +class LLAlignedArray +{ +public: +	T* mArray; +	U32 mElementCount; +	U32 mCapacity; + +	LLAlignedArray(); +	~LLAlignedArray(); + +	void push_back(const T& elem); +	U32 size() const { return mElementCount; } +	void resize(U32 size); +	T* append(S32 N); +	T& operator[](int idx); +	const T& operator[](int idx) const; +}; + +template <class T, U32 alignment> +LLAlignedArray<T, alignment>::LLAlignedArray() +{ +	llassert(alignment >= 16); +	mArray = NULL; +	mElementCount = 0; +	mCapacity = 0; +} + +template <class T, U32 alignment> +LLAlignedArray<T, alignment>::~LLAlignedArray() +{ +	ll_aligned_free(mArray); +	mArray = NULL; +	mElementCount = 0; +	mCapacity = 0; +} + +template <class T, U32 alignment> +void LLAlignedArray<T, alignment>::push_back(const T& elem) +{ +	T* old_buf = NULL; +	if (mCapacity <= mElementCount) +	{ +		mCapacity++; +		mCapacity *= 2; +		T* new_buf = (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment); +		if (mArray) +		{ +			ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount); +		} +		old_buf = mArray; +		mArray = new_buf; +	} + +	mArray[mElementCount++] = elem; + +	//delete old array here to prevent error on a.push_back(a[0]) +	ll_aligned_free(old_buf); +} + +template <class T, U32 alignment> +void LLAlignedArray<T, alignment>::resize(U32 size) +{ +	if (mCapacity < size) +	{ +		mCapacity = size+mCapacity*2; +		T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment) : NULL; +		if (mArray) +		{ +			ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount); +			ll_aligned_free(mArray); +		} + +		/*for (U32 i = mElementCount; i < mCapacity; ++i) +		{ +			new(new_buf+i) T(); +		}*/ +		mArray = new_buf; +	} + +	mElementCount = size; +} + + +template <class T, U32 alignment> +T& LLAlignedArray<T, alignment>::operator[](int idx) +{ +	llassert(idx < mElementCount); +	return mArray[idx]; +} + +template <class T, U32 alignment> +const T& LLAlignedArray<T, alignment>::operator[](int idx) const +{ +	llassert(idx < mElementCount); +	return mArray[idx]; +} + +template <class T, U32 alignment> +T* LLAlignedArray<T, alignment>::append(S32 N) +{ +	U32 sz = size(); +	resize(sz+N); +	return &((*this)[sz]); +} + +#endif + diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 46cabfadcd..61e30f11cc 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -36,6 +36,44 @@ class LLMutex ;  #define LL_CHECK_MEMORY  #endif +LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); + +#ifdef SHOW_ASSERT +#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment)) +#else +#define ll_assert_aligned(ptr,alignment) +#endif + +#include <xmmintrin.h> + +template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address)  +{  +	return reinterpret_cast<T*>( +		(reinterpret_cast<uintptr_t>(address) + 0xF) & ~0xF); +} + +template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)  +{  +	return reinterpret_cast<T*>( +		(reinterpret_cast<uintptr_t>(address) + 0x3F) & ~0x3F); +} + +#if LL_LINUX || LL_DARWIN + +#define			LL_ALIGN_PREFIX(x) +#define			LL_ALIGN_POSTFIX(x)		__attribute__((aligned(x))) + +#elif LL_WINDOWS + +#define			LL_ALIGN_PREFIX(x)		__declspec(align(x)) +#define			LL_ALIGN_POSTFIX(x) + +#else +#error "LL_ALIGN_PREFIX and LL_ALIGN_POSTFIX undefined" +#endif + +#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) +  inline void* ll_aligned_malloc( size_t size, int align )  {  #if defined(LL_WINDOWS) @@ -144,6 +182,78 @@ inline void ll_aligned_free_32(void *p)  #endif  } + +// Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP.  +// Source and dest must be 16-byte aligned and size must be multiple of 16. +// +inline void ll_memcpy_nonaliased_aligned_16(char* __restrict dst, const char* __restrict src, size_t bytes) +{ +	assert(src != NULL); +	assert(dst != NULL); +	assert(bytes > 0); +	assert((bytes % sizeof(F32))== 0);  +	ll_assert_aligned(src,16); +	ll_assert_aligned(dst,16); +	assert((src < dst) ? ((src + bytes) < dst) : ((dst + bytes) < src)); +	assert(bytes%16==0); + +	char* end = dst + bytes; + +	if (bytes > 64) +	{ + +		// Find start of 64b aligned area within block +		// +		void* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst); +		 +		//at least 64 bytes before the end of the destination, switch to 16 byte copies +		void* end_64 = end-64; +	 +		// Prefetch the head of the 64b area now +		// +		_mm_prefetch((char*)begin_64, _MM_HINT_NTA); +		_mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA); +		_mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA); +		_mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA); +	 +		// Copy 16b chunks until we're 64b aligned +		// +		while (dst < begin_64) +		{ + +			_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src)); +			dst += 16; +			src += 16; +		} +	 +		// Copy 64b chunks up to your tail +		// +		// might be good to shmoo the 512b prefetch offset +		// (characterize performance for various values) +		// +		while (dst < end_64) +		{ +			_mm_prefetch((char*)src + 512, _MM_HINT_NTA); +			_mm_prefetch((char*)dst + 512, _MM_HINT_NTA); +			_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src)); +			_mm_store_ps((F32*)(dst + 16), _mm_load_ps((F32*)(src + 16))); +			_mm_store_ps((F32*)(dst + 32), _mm_load_ps((F32*)(src + 32))); +			_mm_store_ps((F32*)(dst + 48), _mm_load_ps((F32*)(src + 48))); +			dst += 64; +			src += 64; +		} +	} + +	// Copy remainder 16b tail chunks (or ALL 16b chunks for sub-64b copies) +	// +	while (dst < end) +	{ +		_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src)); +		dst += 16; +		src += 16; +	} +} +  #ifndef __DEBUG_PRIVATE_MEM__  #define __DEBUG_PRIVATE_MEM__  0  #endif @@ -552,13 +662,7 @@ void  LLPrivateMemoryPoolTester::operator delete[](void* addr)  // LLSingleton moved to llsingleton.h -LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); -#ifdef SHOW_ASSERT -#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment)) -#else -#define ll_assert_aligned(ptr,alignment) -#endif  #endif diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index c4cefdb4fa..d141298f69 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -107,15 +107,14 @@ public:  	inline void rotate(const LLVector4a& v, LLVector4a& res)  	{ +		LLVector4a y,z; +  		res = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); -		res.mul(mMatrix[0]); -		 -		LLVector4a y;  		y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); -		y.mul(mMatrix[1]); - -		LLVector4a z;  		z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); +		 +		res.mul(mMatrix[0]); +		y.mul(mMatrix[1]);  		z.mul(mMatrix[2]);  		res.add(y); diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h index 01458521ec..cebd2ace7d 100644 --- a/indra/llmath/llsimdmath.h +++ b/indra/llmath/llsimdmath.h @@ -39,34 +39,6 @@  #include <stdint.h>  #endif -template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address)  -{  -	return reinterpret_cast<T*>( -		(reinterpret_cast<uintptr_t>(address) + 0xF) & ~0xF); -} - -template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)  -{  -	return reinterpret_cast<T*>( -		(reinterpret_cast<uintptr_t>(address) + 0x3F) & ~0x3F); -} - -#if LL_LINUX || LL_DARWIN - -#define			LL_ALIGN_PREFIX(x) -#define			LL_ALIGN_POSTFIX(x)		__attribute__((aligned(x))) - -#elif LL_WINDOWS - -#define			LL_ALIGN_PREFIX(x)		__declspec(align(x)) -#define			LL_ALIGN_POSTFIX(x) - -#else -#error "LL_ALIGN_PREFIX and LL_ALIGN_POSTFIX undefined" -#endif - -#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) -  #include <xmmintrin.h>  #include <emmintrin.h> diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp index 6edeb0fefe..570fa41a43 100644 --- a/indra/llmath/llvector4a.cpp +++ b/indra/llmath/llvector4a.cpp @@ -41,55 +41,7 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast<const LLVector4a&> ( F  /*static */void LLVector4a::memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes)  { -	assert(src != NULL); -	assert(dst != NULL); -	assert(bytes > 0); -	assert((bytes % sizeof(F32))== 0);  -	ll_assert_aligned(src,16); -	ll_assert_aligned(dst,16); -	assert(bytes%16==0); - -	F32* end = dst + (bytes / sizeof(F32) ); - -	if (bytes > 64) -	{ -		F32* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst); -		 -		//at least 64 (16*4) bytes before the end of the destination, switch to 16 byte copies -		F32* end_64 = end-16; -		 -		_mm_prefetch((char*)begin_64, _MM_HINT_NTA); -		_mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA); -		_mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA); -		_mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA); -		 -		while (dst < begin_64) -		{ -			copy4a(dst, src); -			dst += 4; -			src += 4; -		} -		 -		while (dst < end_64) -		{ -			_mm_prefetch((char*)src + 512, _MM_HINT_NTA); -			_mm_prefetch((char*)dst + 512, _MM_HINT_NTA); -			copy4a(dst, src); -			copy4a(dst+4, src+4); -			copy4a(dst+8, src+8); -			copy4a(dst+12, src+12); -			 -			dst += 16; -			src += 16; -		} -	} - -	while (dst < end) -	{ -		copy4a(dst, src); -		dst += 4; -		src += 4; -	} +        ll_memcpy_nonaliased_aligned_16((char*)dst, (char*)src, bytes);  }  void LLVector4a::setRotated( const LLRotation& rot, const LLVector4a& vec ) diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl index 7c52ffef21..35a67204ec 100644 --- a/indra/llmath/llvector4a.inl +++ b/indra/llmath/llvector4a.inl @@ -460,16 +460,13 @@ inline void LLVector4a::setMax(const LLVector4a& lhs, const LLVector4a& rhs)  	mQ = _mm_max_ps(lhs.mQ, rhs.mQ);  } -// Set this to  (c * lhs) + rhs * ( 1 - c) +// Set this to  lhs + (rhs-lhs)*c  inline void LLVector4a::setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F32 c)  { -	LLVector4a a = lhs; -	a.mul(c); -	 -	LLVector4a b = rhs; -	b.mul(1.f-c); -	 -	setAdd(a, b); +	LLVector4a t; +	t.setSub(rhs,lhs); +	t.mul(c); +	setAdd(lhs, t);  }  inline LLBool32 LLVector4a::isFinite3() const diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index f503eea107..602f2c29e5 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -94,6 +94,8 @@ const S32 SCULPT_MIN_AREA_DETAIL = 1;  extern BOOL gDebugGL; +bool less_than_max_mag(const LLVector4a& vec); +  BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm)  {      	LLVector3 test = (pt2-pt1)%(pt3-pt2); @@ -474,7 +476,7 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  	const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };  	F32 scale = 0.5f;  	F32 t, t_step, t_first, t_fraction, ang, ang_step; -	LLVector3 pt1,pt2; +	LLVector4a pt1,pt2;  	F32 begin  = params.getBegin();  	F32 end    = params.getEnd(); @@ -497,20 +499,21 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  	// Starting t and ang values for the first face  	t = t_first;  	ang = 2.0f*F_PI*(t*ang_scale + offset); -	pt1.setVec(cos(ang)*scale,sin(ang)*scale, t); +	pt1.set(cos(ang)*scale,sin(ang)*scale, t);  	// Increment to the next point.  	// pt2 is the end point on the fractional face  	t += t_step;  	ang += ang_step; -	pt2.setVec(cos(ang)*scale,sin(ang)*scale,t); +	pt2.set(cos(ang)*scale,sin(ang)*scale,t);  	t_fraction = (begin - t_first)*sides;  	// Only use if it's not almost exactly on an edge.  	if (t_fraction < 0.9999f)  	{ -		LLVector3 new_pt = lerp(pt1, pt2, t_fraction); +		LLVector4a new_pt; +		new_pt.setLerp(pt1, pt2, t_fraction);  		mProfile.push_back(new_pt);  	} @@ -518,12 +521,17 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  	while (t < end)  	{  		// Iterate through all the integer steps of t. -		pt1.setVec(cos(ang)*scale,sin(ang)*scale,t); +		pt1.set(cos(ang)*scale,sin(ang)*scale,t);  		if (mProfile.size() > 0) { -			LLVector3 p = mProfile[mProfile.size()-1]; +			LLVector4a p = mProfile[mProfile.size()-1];  			for (S32 i = 0; i < split && mProfile.size() > 0; i++) { -				mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1)); +				//mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1)); +				LLVector4a new_pt; +				new_pt.setSub(pt1, p); +				new_pt.mul(1.0f/(float)(split+1) * (float)(i+1)); +				new_pt.add(p); +				mProfile.push_back(new_pt);  			}  		}  		mProfile.push_back(pt1); @@ -536,18 +544,25 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  	// pt1 is the first point on the fractional face  	// pt2 is the end point on the fractional face -	pt2.setVec(cos(ang)*scale,sin(ang)*scale,t); +	pt2.set(cos(ang)*scale,sin(ang)*scale,t);  	// Find the fraction that we need to add to the end point.  	t_fraction = (end - (t - t_step))*sides;  	if (t_fraction > 0.0001f)  	{ -		LLVector3 new_pt = lerp(pt1, pt2, t_fraction); +		LLVector4a new_pt; +		new_pt.setLerp(pt1, pt2, t_fraction);  		if (mProfile.size() > 0) { -			LLVector3 p = mProfile[mProfile.size()-1]; +			LLVector4a p = mProfile[mProfile.size()-1];  			for (S32 i = 0; i < split && mProfile.size() > 0; i++) { -				mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1)); +				//mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1)); + +				LLVector4a pt1; +				pt1.setSub(new_pt, p); +				pt1.mul(1.0f/(float)(split+1) * (float)(i+1)); +				pt1.add(p); +				mProfile.push_back(pt1);  			}  		}  		mProfile.push_back(new_pt); @@ -568,7 +583,7 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  		if (params.getHollow() <= 0)  		{  			// put center point if not hollow. -			mProfile.push_back(LLVector3(0,0,0)); +			mProfile.push_back(LLVector4a(0,0,0));  		}  	}  	else @@ -581,103 +596,6 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  	mTotal = mProfile.size();  } -void LLProfile::genNormals(const LLProfileParams& params) -{ -	S32 count = mProfile.size(); - -	S32 outer_count; -	if (mTotalOut) -	{ -		outer_count = mTotalOut; -	} -	else -	{ -		outer_count = mTotal / 2; -	} - -	mEdgeNormals.resize(count * 2); -	mEdgeCenters.resize(count * 2); -	mNormals.resize(count); - -	LLVector2 pt0,pt1; - -	BOOL hollow = (params.getHollow() > 0); - -	S32 i0, i1, i2, i3, i4; - -	// Parametrically generate normal -	for (i2 = 0; i2 < count; i2++) -	{ -		mNormals[i2].mV[0] = mProfile[i2].mV[0]; -		mNormals[i2].mV[1] = mProfile[i2].mV[1]; -		if (hollow && (i2 >= outer_count)) -		{ -			mNormals[i2] *= -1.f; -		} -		if (mNormals[i2].magVec() < 0.001) -		{ -			// Special case for point at center, get adjacent points. -			i1 = (i2 - 1) >= 0 ? i2 - 1 : count - 1; -			i0 = (i1 - 1) >= 0 ? i1 - 1 : count - 1; -			i3 = (i2 + 1) < count ? i2 + 1 : 0; -			i4 = (i3 + 1) < count ? i3 + 1 : 0; - -			pt0.setVec(mProfile[i1].mV[VX] + mProfile[i1].mV[VX] - mProfile[i0].mV[VX],  -				mProfile[i1].mV[VY] + mProfile[i1].mV[VY] - mProfile[i0].mV[VY]); -			pt1.setVec(mProfile[i3].mV[VX] + mProfile[i3].mV[VX] - mProfile[i4].mV[VX],  -				mProfile[i3].mV[VY] + mProfile[i3].mV[VY] - mProfile[i4].mV[VY]); - -			mNormals[i2] = pt0 + pt1; -			mNormals[i2] *= 0.5f; -		} -		mNormals[i2].normVec(); -	} - -	S32 num_normal_sets = isConcave() ? 2 : 1; -	for (S32 normal_set = 0; normal_set < num_normal_sets; normal_set++) -	{ -		S32 point_num; -		for (point_num = 0; point_num < mTotal; point_num++) -		{ -			LLVector3 point_1 = mProfile[point_num]; -			point_1.mV[VZ] = 0.f; - -			LLVector3 point_2; -			 -			if (isConcave() && normal_set == 0 && point_num == (mTotal - 1) / 2) -			{ -				point_2 = mProfile[mTotal - 1]; -			} -			else if (isConcave() && normal_set == 1 && point_num == mTotal - 1) -			{ -				point_2 = mProfile[(mTotal - 1) / 2]; -			} -			else -			{ -				LLVector3 delta_pos; -				S32 neighbor_point = (point_num + 1) % mTotal; -				while(delta_pos.magVecSquared() < 0.01f * 0.01f) -				{ -					point_2 = mProfile[neighbor_point]; -					delta_pos = point_2 - point_1; -					neighbor_point = (neighbor_point + 1) % mTotal; -					if (neighbor_point == point_num) -					{ -						break; -					} -				} -			} - -			point_2.mV[VZ] = 0.f; -			LLVector3 face_normal = (point_2 - point_1) % LLVector3::z_axis; -			face_normal.normVec(); -			mEdgeNormals[normal_set * count + point_num] = face_normal; -			mEdgeCenters[normal_set * count + point_num] = lerp(point_1, point_2, 0.5f); -		} -	} -} - -  // Hollow is percent of the original bounding box, not of this particular  // profile's geometry.  Thus, a swept triangle needs lower hollow values than  // a swept square. @@ -693,12 +611,13 @@ LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F3  	Face *face = addFace(mTotalOut, mTotal-mTotalOut,0,LL_FACE_INNER_SIDE, flat); -	std::vector<LLVector3> pt; +	static LLAlignedArray<LLVector4a,64> pt;  	pt.resize(mTotal) ;  	for (S32 i=mTotalOut;i<mTotal;i++)  	{ -		pt[i] = mProfile[i] * box_hollow; +		pt[i] = mProfile[i]; +		pt[i].mul(box_hollow);  	}  	S32 j=mTotal-1; @@ -844,8 +763,8 @@ BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detai  		detail = MIN_LOD;  	} -	mProfile.clear(); -	mFaces.clear(); +	mProfile.resize(0); +	mFaces.resize(0);  	// Generate the face data  	S32 i; @@ -877,10 +796,12 @@ BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detai  				addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, TRUE);  			} +			LLVector4a scale(1,1,4,1); +  			for (i = 0; i <(S32) mProfile.size(); i++)  			{  				// Scale by 4 to generate proper tex coords. -				mProfile[i].mV[2] *= 4.f; +				mProfile[i].mul(scale);  			}  			if (hollow) @@ -913,10 +834,11 @@ BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detai  	case  LL_PCODE_PROFILE_EQUALTRI:  		{  			genNGon(params, 3,0, 0, 1, split); +			LLVector4a scale(1,1,3,1);  			for (i = 0; i <(S32) mProfile.size(); i++)  			{  				// Scale by 3 to generate proper tex coords. -				mProfile[i].mV[2] *= 3.f; +				mProfile[i].mul(scale);  			}  			if (path_open) @@ -1094,8 +1016,6 @@ BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detai  			addFace(mTotal-2, 2,0.5,LL_FACE_PROFILE_END, TRUE);  		}  	} -	 -	//genNormals(params);  	return TRUE;  } @@ -1379,25 +1299,29 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en  	// the path begins at the correct cut.  	F32 step= 1.0f / sides;  	F32 t	= params.getBegin(); -	pt		= vector_append(mPath, 1); +	pt		= mPath.append(1);  	ang		= 2.0f*F_PI*revolutions * t;  	s		= sin(ang)*lerp(radius_start, radius_end, t);	  	c		= cos(ang)*lerp(radius_start, radius_end, t); -	pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) +	pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)  					  + lerp(-skew ,skew, t) * 0.5f,  					c + lerp(0,params.getShear().mV[1],s),   					s); -	pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); -	pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); +	pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), +		hole_y * lerp(taper_y_begin, taper_y_end, t), +		0,1);  	pt->mTexT  = t;  	// Twist rotates the path along the x,y plane (I think) - DJS 04/05/02  	twist.setQuat  (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1);  	// Rotate the point around the circle's center.  	qang.setQuat   (ang,path_axis); -	pt->mRot   = twist * qang; + +	LLMatrix3 rot(twist * qang); + +	pt->mRot.loadu(rot);  	t+=step; @@ -1408,51 +1332,55 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en  	// Run through the non-cut dependent points.  	while (t < params.getEnd())  	{ -		pt		= vector_append(mPath, 1); +		pt		= mPath.append(1);  		ang = 2.0f*F_PI*revolutions * t;  		c   = cos(ang)*lerp(radius_start, radius_end, t);  		s   = sin(ang)*lerp(radius_start, radius_end, t); -		pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) +		pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)  					      + lerp(-skew ,skew, t) * 0.5f,  						c + lerp(0,params.getShear().mV[1],s),   						s); -		pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); -		pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); +		pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), +					hole_y * lerp(taper_y_begin, taper_y_end, t), +					0,1);  		pt->mTexT  = t;  		// Twist rotates the path along the x,y plane (I think) - DJS 04/05/02  		twist.setQuat  (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1);  		// Rotate the point around the circle's center.  		qang.setQuat   (ang,path_axis); -		pt->mRot	= twist * qang; - +		LLMatrix3 tmp(twist*qang); +		pt->mRot.loadu(tmp); +		  		t+=step;  	}  	// Make one final pass for the end cut.  	t = params.getEnd(); -	pt		= vector_append(mPath, 1); +	pt		= mPath.append(1);  	ang = 2.0f*F_PI*revolutions * t;  	c   = cos(ang)*lerp(radius_start, radius_end, t);  	s   = sin(ang)*lerp(radius_start, radius_end, t); -	pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) +	pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)  					  + lerp(-skew ,skew, t) * 0.5f,  					c + lerp(0,params.getShear().mV[1],s),   					s); -	pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); -	pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); +	pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), +				   hole_y * lerp(taper_y_begin, taper_y_end, t), +				   0,1);  	pt->mTexT  = t;  	// Twist rotates the path along the x,y plane (I think) - DJS 04/05/02  	twist.setQuat  (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1);  	// Rotate the point around the circle's center.  	qang.setQuat   (ang,path_axis); -	pt->mRot   = twist * qang; - +	LLMatrix3 tmp(twist*qang); +	pt->mRot.loadu(tmp); +	  	mTotal = mPath.size();  } @@ -1549,7 +1477,7 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,  	mDirty = FALSE;  	S32 np = 2; // hardcode for line -	mPath.clear(); +	mPath.resize(0);  	mOpen = TRUE;  	// Is this 0xf0 mask really necessary?  DK 03/02/05 @@ -1575,12 +1503,16 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,  			for (S32 i=0;i<np;i++)  			{  				F32 t = lerp(params.getBegin(),params.getEnd(),(F32)i * mStep); -				mPath[i].mPos.setVec(lerp(0,params.getShear().mV[0],t), +				mPath[i].mPos.set(lerp(0,params.getShear().mV[0],t),  									 lerp(0,params.getShear().mV[1],t),  									 t - 0.5f); -				mPath[i].mRot.setQuat(lerp(F_PI * params.getTwistBegin(),F_PI * params.getTwist(),t),0,0,1); -				mPath[i].mScale.mV[0] = lerp(start_scale.mV[0],end_scale.mV[0],t); -				mPath[i].mScale.mV[1] = lerp(start_scale.mV[1],end_scale.mV[1],t); +				LLQuaternion quat; +				quat.setQuat(lerp(F_PI * params.getTwistBegin(),F_PI * params.getTwist(),t),0,0,1); +				LLMatrix3 tmp(quat); +				mPath[i].mRot.loadu(tmp); +				mPath[i].mScale.set(lerp(start_scale.mV[0],end_scale.mV[0],t), +									lerp(start_scale.mV[1],end_scale.mV[1],t), +									0,1);  				mPath[i].mTexT        = t;  			}  		} @@ -1617,7 +1549,7 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,  			F32 toggle = 0.5f;  			for (S32 i=0;i<(S32)mPath.size();i++)  			{ -				mPath[i].mPos.mV[0] = toggle; +				mPath[i].mPos.getF32ptr()[0] = toggle;  				if (toggle == 0.5f)  					toggle = -0.5f;  				else @@ -1638,13 +1570,16 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,  		for (S32 i=0;i<np;i++)  		{  			F32 t = (F32)i * mStep; -			mPath[i].mPos.setVec(0, +			mPath[i].mPos.set(0,  								lerp(0,   -sin(F_PI*params.getTwist()*t)*0.5f,t),  								lerp(-0.5, cos(F_PI*params.getTwist()*t)*0.5f,t)); -			mPath[i].mScale.mV[0] = lerp(1,params.getScale().mV[0],t); -			mPath[i].mScale.mV[1] = lerp(1,params.getScale().mV[1],t); +			mPath[i].mScale.set(lerp(1,params.getScale().mV[0],t), +								lerp(1,params.getScale().mV[1],t), 0,1);  			mPath[i].mTexT  = t; -			mPath[i].mRot.setQuat(F_PI * params.getTwist() * t,1,0,0); +			LLQuaternion quat; +			quat.setQuat(F_PI * params.getTwist() * t,1,0,0); +			LLMatrix3 tmp(quat); +			mPath[i].mRot.loadu(tmp);  		}  		break; @@ -1668,11 +1603,15 @@ BOOL LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split,  		// Path hasn't been generated yet.  		// Some algorithms later assume at least TWO path points.  		resizePath(2); +		LLQuaternion quat; +		quat.setQuat(0,0,0); +		LLMatrix3 tmp(quat); +  		for (U32 i = 0; i < 2; i++)  		{ -			mPath[i].mPos.setVec(0, 0, 0); -			mPath[i].mRot.setQuat(0, 0, 0); -			mPath[i].mScale.setVec(1, 1); +			mPath[i].mPos.set(0, 0, 0); +			mPath[i].mRot.loadu(tmp); +			mPath[i].mScale.set(1, 1, 0, 1);  			mPath[i].mTexT = 0;  		}  	} @@ -2045,7 +1984,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge  	mHullIndices = NULL;  	mNumHullPoints = 0;  	mNumHullIndices = 0; - +	  	// set defaults  	if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE)  	{ @@ -2105,6 +2044,7 @@ LLVolume::~LLVolume()  BOOL LLVolume::generate()  { +	LL_CHECK_MEMORY  	llassert_always(mProfilep);  	//Added 10.03.05 Dave Parks @@ -2141,20 +2081,6 @@ BOOL LLVolume::generate()  		mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);  	} -	//******************************************************************** -	//debug info, to be removed -	if((U32)(mPathp->mPath.size() * mProfilep->mProfile.size()) > (1u << 20)) -	{ -		llinfos << "sizeS: " << mPathp->mPath.size() << " sizeT: " << mProfilep->mProfile.size() << llendl ; -		llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ; -		llinfos << mParams << llendl ; -		llinfos << "more info to check if mProfilep is deleted or not." << llendl ; -		llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ; - -		llerrs << "LLVolume corrupted!" << llendl ; -	} -	//******************************************************************** -  	BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split);  	BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); @@ -2163,21 +2089,6 @@ BOOL LLVolume::generate()  		S32 sizeS = mPathp->mPath.size();  		S32 sizeT = mProfilep->mProfile.size(); -		//******************************************************************** -		//debug info, to be removed -		if((U32)(sizeS * sizeT) > (1u << 20)) -		{ -			llinfos << "regenPath: " << (S32)regenPath << " regenProf: " << (S32)regenProf << llendl ; -			llinfos << "sizeS: " << sizeS << " sizeT: " << sizeT << llendl ; -			llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ; -			llinfos << mParams << llendl ; -			llinfos << "more info to check if mProfilep is deleted or not." << llendl ; -			llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ; - -			llerrs << "LLVolume corrupted!" << llendl ; -		} -		//******************************************************************** -  		sNumMeshPoints -= mMesh.size();  		mMesh.resize(sizeT * sizeS);  		sNumMeshPoints += mMesh.size();		 @@ -2185,22 +2096,39 @@ BOOL LLVolume::generate()  		//generate vertex positions  		// Run along the path. +		LLVector4a* dst = mMesh.mArray; +  		for (S32 s = 0; s < sizeS; ++s)  		{ -			LLVector2  scale = mPathp->mPath[s].mScale; -			LLQuaternion rot = mPathp->mPath[s].mRot; +			F32* scale = mPathp->mPath[s].mScale.getF32ptr(); +			 +			F32 sc [] =  +			{ scale[0], 0, 0, 0, +				0, scale[1], 0, 0, +				0, 0, scale[2], 0, +					0, 0, 0, 1 }; +			 +			LLMatrix4 rot((F32*) mPathp->mPath[s].mRot.mMatrix); +			LLMatrix4 scale_mat(sc); +			 +			scale_mat *= rot; +			 +			LLMatrix4a rot_mat; +			rot_mat.loadu(scale_mat); +			 +			LLVector4a* profile = mProfilep->mProfile.mArray; +			LLVector4a* end_profile = profile+sizeT; +			LLVector4a offset = mPathp->mPath[s].mPos; + +			LLVector4a tmp;  			// Run along the profile. -			for (S32 t = 0; t < sizeT; ++t) +			while (profile < end_profile)  			{ -				S32 m = s*sizeT + t; -				Point& pt = mMesh[m]; -				 -				pt.mPos.mV[0] = mProfilep->mProfile[t].mV[0] * scale.mV[0]; -				pt.mPos.mV[1] = mProfilep->mProfile[t].mV[1] * scale.mV[1]; -				pt.mPos.mV[2] = 0.0f; -				pt.mPos       = pt.mPos * rot; -				pt.mPos      += mPathp->mPath[s].mPos; +				rot_mat.rotate(*profile++, tmp); +				dst->setAdd(tmp,offset); +				llassert(less_than_max_mag(*dst)); +				++dst;  			}  		} @@ -2210,9 +2138,11 @@ BOOL LLVolume::generate()  			LLFaceID id = iter->mFaceID;  			mFaceMask |= id;  		} -		 +		LL_CHECK_MEMORY  		return TRUE;  	} + +	LL_CHECK_MEMORY  	return FALSE;  } @@ -2790,14 +2720,16 @@ void LLVolume::createVolumeFaces()  } -inline LLVector3 sculpt_rgb_to_vector(U8 r, U8 g, U8 b) +inline LLVector4a sculpt_rgb_to_vector(U8 r, U8 g, U8 b)  {  	// maps RGB values to vector values [0..255] -> [-0.5..0.5] -	LLVector3 value; -	value.mV[VX] = r / 255.f - 0.5f; -	value.mV[VY] = g / 255.f - 0.5f; -	value.mV[VZ] = b / 255.f - 0.5f; +	LLVector4a value; +	LLVector4a sub(0.5f, 0.5f, 0.5f); +	value.set(r,g,b); +	value.mul(1.f/255.f); +	value.sub(sub); +	  	return value;  } @@ -2817,21 +2749,21 @@ inline U32 sculpt_st_to_index(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_w  } -inline LLVector3 sculpt_index_to_vector(U32 index, const U8* sculpt_data) +inline LLVector4a sculpt_index_to_vector(U32 index, const U8* sculpt_data)  { -	LLVector3 v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]); +	LLVector4a v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]);  	return v;  } -inline LLVector3 sculpt_st_to_vector(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) +inline LLVector4a sculpt_st_to_vector(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)  {  	U32 index = sculpt_st_to_index(s, t, size_s, size_t, sculpt_width, sculpt_height, sculpt_components);  	return sculpt_index_to_vector(index, sculpt_data);  } -inline LLVector3 sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) +inline LLVector4a sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)  {  	U32 index = sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); @@ -2853,15 +2785,26 @@ F32 LLVolume::sculptGetSurfaceArea()  		for (S32 t = 0; t < sizeT-1; t++)  		{  			// get four corners of quad -			LLVector3 p1 = mMesh[(s  )*sizeT + (t  )].mPos; -			LLVector3 p2 = mMesh[(s+1)*sizeT + (t  )].mPos; -			LLVector3 p3 = mMesh[(s  )*sizeT + (t+1)].mPos; -			LLVector3 p4 = mMesh[(s+1)*sizeT + (t+1)].mPos; +			LLVector4a& p1 = mMesh[(s  )*sizeT + (t  )]; +			LLVector4a& p2 = mMesh[(s+1)*sizeT + (t  )]; +			LLVector4a& p3 = mMesh[(s  )*sizeT + (t+1)]; +			LLVector4a& p4 = mMesh[(s+1)*sizeT + (t+1)];  			// compute the area of the quad by taking the length of the cross product of the two triangles -			LLVector3 cross1 = (p1 - p2) % (p1 - p3); -			LLVector3 cross2 = (p4 - p2) % (p4 - p3); -			area += (cross1.magVec() + cross2.magVec()) / 2.f; +			LLVector4a v0,v1,v2,v3; +			v0.setSub(p1,p2); +			v1.setSub(p1,p3); +			v2.setSub(p4,p2); +			v3.setSub(p4,p3); + +			LLVector4a cross1, cross2; +			cross1.setCross3(v0,v1); +			cross2.setCross3(v2,v3); + +			//LLVector3 cross1 = (p1 - p2) % (p1 - p3); +			//LLVector3 cross2 = (p4 - p2) % (p4 - p3); +			 +			area += (cross1.getLength3() + cross2.getLength3()).getF32() / 2.f;  		}  	} @@ -2882,17 +2825,19 @@ void LLVolume::sculptGeneratePlaceholder()  		for (S32 t = 0; t < sizeT; t++)  		{  			S32 i = t + line; -			Point& pt = mMesh[i]; +			LLVector4a& pt = mMesh[i];  			F32 u = (F32)s/(sizeS-1);  			F32 v = (F32)t/(sizeT-1);  			const F32 RADIUS = (F32) 0.3; -					 -			pt.mPos.mV[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); -			pt.mPos.mV[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS); -			pt.mPos.mV[2] = (F32)(cos(F_PI * v) * RADIUS); +			 +			F32* p = pt.getF32ptr(); + +			p[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); +			p[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS); +			p[2] = (F32)(cos(F_PI * v) * RADIUS);  		}  		line += sizeT; @@ -2917,7 +2862,7 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8  		for (S32 t = 0; t < sizeT; t++)  		{  			S32 i = t + line; -			Point& pt = mMesh[i]; +			LLVector4a& pt = mMesh[i];  			S32 reversed_t = t; @@ -2974,11 +2919,12 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8  				}  			} -			pt.mPos = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data); +			pt = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data);  			if (sculpt_mirror)  			{ -				pt.mPos.mV[VX] *= -1.f; +				LLVector4a scale(-1.f,1,1,1); +				pt.mul(scale);  			}  		} @@ -3560,627 +3506,6 @@ bool LLVolumeParams::validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 h  	return true;  } -S32 *LLVolume::getTriangleIndices(U32 &num_indices) const -{ -	S32 expected_num_triangle_indices = getNumTriangleIndices(); -	if (expected_num_triangle_indices > MAX_VOLUME_TRIANGLE_INDICES) -	{ -		// we don't allow LLVolumes with this many vertices -		llwarns << "Couldn't allocate triangle indices" << llendl; -		num_indices = 0; -		return NULL; -	} - -	S32* index = new S32[expected_num_triangle_indices]; -	S32 count = 0; - -	// Let's do this totally diffently, as we don't care about faces... -	// Counter-clockwise triangles are forward facing... - -	BOOL open = getProfile().isOpen(); -	BOOL hollow = (mParams.getProfileParams().getHollow() > 0); -	BOOL path_open = getPath().isOpen(); -	S32 size_s, size_s_out, size_t; -	S32 s, t, i; -	size_s = getProfile().getTotal(); -	size_s_out = getProfile().getTotalOut(); -	size_t = getPath().mPath.size(); - -	// NOTE -- if the construction of the triangles below ever changes -	// then getNumTriangleIndices() method may also have to be updated. - -	if (open)		/* Flawfinder: ignore */ -	{ -		if (hollow) -		{ -			// Open hollow -- much like the closed solid, except we  -			// we need to stitch up the gap between s=0 and s=size_s-1 - -			for (t = 0; t < size_t - 1; t++) -			{ -				// The outer face, first cut, and inner face -				for (s = 0; s < size_s - 1; s++) -				{ -					i  = s + t*size_s; -					index[count++]  = i;				// x,y -					index[count++]  = i + 1;			// x+1,y -					index[count++]  = i + size_s;		// x,y+1 -	 -					index[count++]  = i + size_s;		// x,y+1 -					index[count++]  = i + 1;			// x+1,y -					index[count++]  = i + size_s + 1;	// x+1,y+1 -				} - -				// The other cut face -				index[count++]  = s + t*size_s;		// x,y -				index[count++]  = 0 + t*size_s;		// x+1,y -				index[count++]  = s + (t+1)*size_s;	// x,y+1 -	 -				index[count++]  = s + (t+1)*size_s;	// x,y+1 -				index[count++]  = 0 + t*size_s;		// x+1,y -				index[count++]  = 0 + (t+1)*size_s;	// x+1,y+1 -			} - -			// Do the top and bottom caps, if necessary -			if (path_open) -			{ -				// Top cap -				S32 pt1 = 0; -				S32 pt2 = size_s-1; -				S32 i   = (size_t - 1)*size_s; - -				while (pt2 - pt1 > 1) -				{ -					// Use the profile points instead of the mesh, since you want -					// the un-transformed profile distances. -					LLVector3 p1 = getProfile().mProfile[pt1]; -					LLVector3 p2 = getProfile().mProfile[pt2]; -					LLVector3 pa = getProfile().mProfile[pt1+1]; -					LLVector3 pb = getProfile().mProfile[pt2-1]; - -					p1.mV[VZ] = 0.f; -					p2.mV[VZ] = 0.f; -					pa.mV[VZ] = 0.f; -					pb.mV[VZ] = 0.f; - -					// Use area of triangle to determine backfacing -					F32 area_1a2, area_1ba, area_21b, area_2ab; -					area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -								(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -								(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - -					area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -								(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -								(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - -					area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -								(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -					area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -								(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -					BOOL use_tri1a2 = TRUE; -					BOOL tri_1a2 = TRUE; -					BOOL tri_21b = TRUE; - -					if (area_1a2 < 0) -					{ -						tri_1a2 = FALSE; -					} -					if (area_2ab < 0) -					{ -						// Can't use, because it contains point b -						tri_1a2 = FALSE; -					} -					if (area_21b < 0) -					{ -						tri_21b = FALSE; -					} -					if (area_1ba < 0) -					{ -						// Can't use, because it contains point b -						tri_21b = FALSE; -					} - -					if (!tri_1a2) -					{ -						use_tri1a2 = FALSE; -					} -					else if (!tri_21b) -					{ -						use_tri1a2 = TRUE; -					} -					else -					{ -						LLVector3 d1 = p1 - pa; -						LLVector3 d2 = p2 - pb; - -						if (d1.magVecSquared() < d2.magVecSquared()) -						{ -							use_tri1a2 = TRUE; -						} -						else -						{ -							use_tri1a2 = FALSE; -						} -					} - -					if (use_tri1a2) -					{ -						index[count++] = pt1 + i; -						index[count++] = pt1 + 1 + i; -						index[count++] = pt2 + i; -						pt1++; -					} -					else -					{ -						index[count++] = pt1 + i; -						index[count++] = pt2 - 1 + i; -						index[count++] = pt2 + i; -						pt2--; -					} -				} - -				// Bottom cap -				pt1          = 0; -				pt2          = size_s-1; -				while (pt2 - pt1 > 1) -				{ -					// Use the profile points instead of the mesh, since you want -					// the un-transformed profile distances. -					LLVector3 p1 = getProfile().mProfile[pt1]; -					LLVector3 p2 = getProfile().mProfile[pt2]; -					LLVector3 pa = getProfile().mProfile[pt1+1]; -					LLVector3 pb = getProfile().mProfile[pt2-1]; - -					p1.mV[VZ] = 0.f; -					p2.mV[VZ] = 0.f; -					pa.mV[VZ] = 0.f; -					pb.mV[VZ] = 0.f; - -					// Use area of triangle to determine backfacing -					F32 area_1a2, area_1ba, area_21b, area_2ab; -					area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -								(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -								(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - -					area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -								(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -								(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - -					area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -								(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -					area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -								(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -					BOOL use_tri1a2 = TRUE; -					BOOL tri_1a2 = TRUE; -					BOOL tri_21b = TRUE; - -					if (area_1a2 < 0) -					{ -						tri_1a2 = FALSE; -					} -					if (area_2ab < 0) -					{ -						// Can't use, because it contains point b -						tri_1a2 = FALSE; -					} -					if (area_21b < 0) -					{ -						tri_21b = FALSE; -					} -					if (area_1ba < 0) -					{ -						// Can't use, because it contains point b -						tri_21b = FALSE; -					} - -					if (!tri_1a2) -					{ -						use_tri1a2 = FALSE; -					} -					else if (!tri_21b) -					{ -						use_tri1a2 = TRUE; -					} -					else -					{ -						LLVector3 d1 = p1 - pa; -						LLVector3 d2 = p2 - pb; - -						if (d1.magVecSquared() < d2.magVecSquared()) -						{ -							use_tri1a2 = TRUE; -						} -						else -						{ -							use_tri1a2 = FALSE; -						} -					} - -					if (use_tri1a2) -					{ -						index[count++] = pt1; -						index[count++] = pt2; -						index[count++] = pt1 + 1; -						pt1++; -					} -					else -					{ -						index[count++] = pt1; -						index[count++] = pt2; -						index[count++] = pt2 - 1; -						pt2--; -					} -				} -			} -		} -		else -		{ -			// Open solid - -			for (t = 0; t < size_t - 1; t++) -			{ -				// Outer face + 1 cut face -				for (s = 0; s < size_s - 1; s++) -				{ -					i  = s + t*size_s; - -					index[count++]  = i;				// x,y -					index[count++]  = i + 1;			// x+1,y -					index[count++]  = i + size_s;		// x,y+1 - -					index[count++]  = i + size_s;		// x,y+1 -					index[count++]  = i + 1;			// x+1,y -					index[count++]  = i + size_s + 1;	// x+1,y+1 -				} - -				// The other cut face -				index[count++] = (size_s - 1) + (t*size_s);		// x,y -				index[count++] = 0 + t*size_s;					// x+1,y -				index[count++] = (size_s - 1) + (t+1)*size_s;	// x,y+1 - -				index[count++] = (size_s - 1) + (t+1)*size_s;	// x,y+1 -				index[count++] = 0 + (t*size_s);				// x+1,y -				index[count++] = 0 + (t+1)*size_s;				// x+1,y+1 -			} - -			// Do the top and bottom caps, if necessary -			if (path_open) -			{ -				for (s = 0; s < size_s - 2; s++) -				{ -					index[count++] = s+1; -					index[count++] = s; -					index[count++] = size_s - 1; -				} - -				// We've got a top cap -				S32 offset = (size_t - 1)*size_s; -				for (s = 0; s < size_s - 2; s++) -				{ -					// Inverted ordering from bottom cap. -					index[count++] = offset + size_s - 1; -					index[count++] = offset + s; -					index[count++] = offset + s + 1; -				} -			} -		} -	} -	else if (hollow) -	{ -		// Closed hollow -		// Outer face -		 -		for (t = 0; t < size_t - 1; t++) -		{ -			for (s = 0; s < size_s_out - 1; s++) -			{ -				i  = s + t*size_s; - -				index[count++]  = i;				// x,y -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + size_s;		// x,y+1 - -				index[count++]  = i + size_s;		// x,y+1 -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + 1 + size_s;	// x+1,y+1 -			} -		} - -		// Inner face -		// Invert facing from outer face -		for (t = 0; t < size_t - 1; t++) -		{ -			for (s = size_s_out; s < size_s - 1; s++) -			{ -				i  = s + t*size_s; - -				index[count++]  = i;				// x,y -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + size_s;		// x,y+1 - -				index[count++]  = i + size_s;		// x,y+1 -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + 1 + size_s;	// x+1,y+1 -			} -		} - -		// Do the top and bottom caps, if necessary -		if (path_open) -		{ -			// Top cap -			S32 pt1 = 0; -			S32 pt2 = size_s-1; -			S32 i   = (size_t - 1)*size_s; - -			while (pt2 - pt1 > 1) -			{ -				// Use the profile points instead of the mesh, since you want -				// the un-transformed profile distances. -				LLVector3 p1 = getProfile().mProfile[pt1]; -				LLVector3 p2 = getProfile().mProfile[pt2]; -				LLVector3 pa = getProfile().mProfile[pt1+1]; -				LLVector3 pb = getProfile().mProfile[pt2-1]; - -				p1.mV[VZ] = 0.f; -				p2.mV[VZ] = 0.f; -				pa.mV[VZ] = 0.f; -				pb.mV[VZ] = 0.f; - -				// Use area of triangle to determine backfacing -				F32 area_1a2, area_1ba, area_21b, area_2ab; -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -				BOOL use_tri1a2 = TRUE; -				BOOL tri_1a2 = TRUE; -				BOOL tri_21b = TRUE; - -				if (area_1a2 < 0) -				{ -					tri_1a2 = FALSE; -				} -				if (area_2ab < 0) -				{ -					// Can't use, because it contains point b -					tri_1a2 = FALSE; -				} -				if (area_21b < 0) -				{ -					tri_21b = FALSE; -				} -				if (area_1ba < 0) -				{ -					// Can't use, because it contains point b -					tri_21b = FALSE; -				} - -				if (!tri_1a2) -				{ -					use_tri1a2 = FALSE; -				} -				else if (!tri_21b) -				{ -					use_tri1a2 = TRUE; -				} -				else -				{ -					LLVector3 d1 = p1 - pa; -					LLVector3 d2 = p2 - pb; - -					if (d1.magVecSquared() < d2.magVecSquared()) -					{ -						use_tri1a2 = TRUE; -					} -					else -					{ -						use_tri1a2 = FALSE; -					} -				} - -				if (use_tri1a2) -				{ -					index[count++] = pt1 + i; -					index[count++] = pt1 + 1 + i; -					index[count++] = pt2 + i; -					pt1++; -				} -				else -				{ -					index[count++] = pt1 + i; -					index[count++] = pt2 - 1 + i; -					index[count++] = pt2 + i; -					pt2--; -				} -			} - -			// Bottom cap -			pt1          = 0; -			pt2          = size_s-1; -			while (pt2 - pt1 > 1) -			{ -				// Use the profile points instead of the mesh, since you want -				// the un-transformed profile distances. -				LLVector3 p1 = getProfile().mProfile[pt1]; -				LLVector3 p2 = getProfile().mProfile[pt2]; -				LLVector3 pa = getProfile().mProfile[pt1+1]; -				LLVector3 pb = getProfile().mProfile[pt2-1]; - -				p1.mV[VZ] = 0.f; -				p2.mV[VZ] = 0.f; -				pa.mV[VZ] = 0.f; -				pb.mV[VZ] = 0.f; - -				// Use area of triangle to determine backfacing -				F32 area_1a2, area_1ba, area_21b, area_2ab; -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -				BOOL use_tri1a2 = TRUE; -				BOOL tri_1a2 = TRUE; -				BOOL tri_21b = TRUE; - -				if (area_1a2 < 0) -				{ -					tri_1a2 = FALSE; -				} -				if (area_2ab < 0) -				{ -					// Can't use, because it contains point b -					tri_1a2 = FALSE; -				} -				if (area_21b < 0) -				{ -					tri_21b = FALSE; -				} -				if (area_1ba < 0) -				{ -					// Can't use, because it contains point b -					tri_21b = FALSE; -				} - -				if (!tri_1a2) -				{ -					use_tri1a2 = FALSE; -				} -				else if (!tri_21b) -				{ -					use_tri1a2 = TRUE; -				} -				else -				{ -					LLVector3 d1 = p1 - pa; -					LLVector3 d2 = p2 - pb; - -					if (d1.magVecSquared() < d2.magVecSquared()) -					{ -						use_tri1a2 = TRUE; -					} -					else -					{ -						use_tri1a2 = FALSE; -					} -				} - -				if (use_tri1a2) -				{ -					index[count++] = pt1; -					index[count++] = pt2; -					index[count++] = pt1 + 1; -					pt1++; -				} -				else -				{ -					index[count++] = pt1; -					index[count++] = pt2; -					index[count++] = pt2 - 1; -					pt2--; -				} -			} -		}		 -	} -	else -	{ -		// Closed solid.  Easy case. -		for (t = 0; t < size_t - 1; t++) -		{ -			for (s = 0; s < size_s - 1; s++) -			{ -				// Should wrap properly, but for now... -				i  = s + t*size_s; - -				index[count++]  = i;				// x,y -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + size_s;		// x,y+1 - -				index[count++]  = i + size_s;		// x,y+1 -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + size_s + 1;	// x+1,y+1 -			} -		} - -		// Do the top and bottom caps, if necessary -		if (path_open) -		{ -			// bottom cap -			for (s = 1; s < size_s - 2; s++) -			{ -				index[count++] = s+1; -				index[count++] = s; -				index[count++] = 0; -			} - -			// top cap -			S32 offset = (size_t - 1)*size_s; -			for (s = 1; s < size_s - 2; s++) -			{ -				// Inverted ordering from bottom cap. -				index[count++] = offset; -				index[count++] = offset + s; -				index[count++] = offset + s + 1; -			} -		} -	} - -#ifdef LL_DEBUG -	// assert that we computed the correct number of indices -	if (count != expected_num_triangle_indices ) -	{ -		llerrs << "bad index count prediciton:" -			<< "  expected=" << expected_num_triangle_indices  -			<< " actual=" << count << llendl; -	} -#endif - -#if 0 -	// verify that each index does not point beyond the size of the mesh -	S32 num_vertices = mMesh.size(); -	for (i = 0; i < count; i+=3) -	{ -		llinfos << index[i] << ":" << index[i+1] << ":" << index[i+2] << llendl; -		llassert(index[i] < num_vertices); -		llassert(index[i+1] < num_vertices); -		llassert(index[i+2] < num_vertices); -	} -#endif - -	num_indices = count; -	return index; -} -  void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts)  { //attempt to approximate the number of triangles that will result from generating a volume LoD set for the   	//supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost @@ -4198,63 +3523,6 @@ void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts)  	}  } -S32 LLVolume::getNumTriangleIndices() const -{ -	BOOL profile_open = getProfile().isOpen(); -	BOOL hollow = (mParams.getProfileParams().getHollow() > 0); -	BOOL path_open = getPath().isOpen(); - -	S32 size_s, size_s_out, size_t; -	size_s = getProfile().getTotal(); -	size_s_out = getProfile().getTotalOut(); -	size_t = getPath().mPath.size(); - -	S32 count = 0; -	if (profile_open)		/* Flawfinder: ignore */ -	{ -		if (hollow) -		{ -			// Open hollow -- much like the closed solid, except we  -			// we need to stitch up the gap between s=0 and s=size_s-1 -			count = (size_t - 1) * (((size_s -1) * 6) + 6); -		} -		else -		{ -			count = (size_t - 1) * (((size_s -1) * 6) + 6);  -		} -	} -	else if (hollow) -	{ -		// Closed hollow -		// Outer face -		count = (size_t - 1) * (size_s_out - 1) * 6; - -		// Inner face -		count += (size_t - 1) * ((size_s - 1) - size_s_out) * 6; -	} -	else -	{ -		// Closed solid.  Easy case. -		count = (size_t - 1) * (size_s - 1) * 6; -	} - -	if (path_open) -	{ -		S32 cap_triangle_count = size_s - 3; -		if ( profile_open -			|| hollow ) -		{ -			cap_triangle_count = size_s - 2; -		} -		if ( cap_triangle_count > 0 ) -		{ -			// top and bottom caps -			count += cap_triangle_count * 2 * 3; -		} -	} -	return count; -} -  S32 LLVolume::getNumTriangles(S32* vcount) const  { @@ -5243,8 +4511,6 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  	freeData(); -	LLVector4a::memcpyNonAliased16((F32*) mExtents, (F32*) src.mExtents, 3*sizeof(LLVector4a)); -  	resizeVertices(src.mNumVertices);  	resizeIndices(src.mNumIndices); @@ -5331,52 +4597,23 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build)  	delete mOctree;  	mOctree = NULL; +	LL_CHECK_MEMORY  	BOOL ret = FALSE ;  	if (mTypeMask & CAP_MASK)  	{  		ret = createCap(volume, partial_build); +		LL_CHECK_MEMORY  	}  	else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK))  	{  		ret = createSide(volume, partial_build); +		LL_CHECK_MEMORY  	}  	else  	{  		llerrs << "Unknown/uninitialized face type!" << llendl;  	} -	//update the range of the texture coordinates -	if(ret) -	{ -		mTexCoordExtents[0].setVec(1.f, 1.f) ; -		mTexCoordExtents[1].setVec(0.f, 0.f) ; - -		for(U32 i = 0 ; i < mNumVertices ; i++) -		{ -			if(mTexCoordExtents[0].mV[0] > mTexCoords[i].mV[0]) -			{ -				mTexCoordExtents[0].mV[0] = mTexCoords[i].mV[0] ; -			} -			if(mTexCoordExtents[1].mV[0] < mTexCoords[i].mV[0]) -			{ -				mTexCoordExtents[1].mV[0] = mTexCoords[i].mV[0] ; -			} - -			if(mTexCoordExtents[0].mV[1] > mTexCoords[i].mV[1]) -			{ -				mTexCoordExtents[0].mV[1] = mTexCoords[i].mV[1] ; -			} -			if(mTexCoordExtents[1].mV[1] < mTexCoords[i].mV[1]) -			{ -				mTexCoordExtents[1].mV[1] = mTexCoords[i].mV[1] ; -			}			 -		} -		mTexCoordExtents[0].mV[0] = llmax(0.f, mTexCoordExtents[0].mV[0]) ; -		mTexCoordExtents[0].mV[1] = llmax(0.f, mTexCoordExtents[0].mV[1]) ; -		mTexCoordExtents[1].mV[0] = llmin(1.f, mTexCoordExtents[1].mV[0]) ; -		mTexCoordExtents[1].mV[1] = llmin(1.f, mTexCoordExtents[1].mV[1]) ; -	} -  	return ret ;  } @@ -5492,7 +4729,9 @@ void LLVolumeFace::optimize(F32 angle_cutoff)  		}  	} -	if (new_face.mNumVertices) +	// Only swap data if we've actually optimized the mesh +	// +	if (new_face.mNumVertices <= mNumVertices)  	{  		llassert(new_face.mNumIndices == mNumIndices);  		swapData(new_face); @@ -6069,18 +5308,15 @@ void	LerpPlanarVertex(LLVolumeFace::VertexData& v0,  BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  { -	const std::vector<LLVolume::Point>& mesh = volume->getMesh(); -	const std::vector<LLVector3>& profile = volume->getProfile().mProfile; +	LL_CHECK_MEMORY		 + +	const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); +	const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile;  	S32 max_s = volume->getProfile().getTotal();  	S32 max_t = volume->getPath().mPath.size();  	// S32 i; -	S32 num_vertices = 0, num_indices = 0;  	S32	grid_size = (profile.size()-1)/4; -	S32	quad_count = (grid_size * grid_size); - -	num_vertices = (grid_size+1)*(grid_size+1); -	num_indices = quad_count * 4;  	LLVector4a& min = mExtents[0];  	LLVector4a& max = mExtents[1]; @@ -6100,9 +5336,9 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  		VertexData baseVert;  		for(S32 t = 0; t < 4; t++)  		{ -			corners[t].getPosition().load3( mesh[offset + (grid_size*t)].mPos.mV); -			corners[t].mTexCoord.mV[0] = profile[grid_size*t].mV[0]+0.5f; -			corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t].mV[1]; +			corners[t].getPosition().load4a(mesh[offset + (grid_size*t)].getF32ptr()); +			corners[t].mTexCoord.mV[0] = profile[grid_size*t][0]+0.5f; +			corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t][1];  		}  		{ @@ -6183,6 +5419,9 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  		mCenter->mul(0.5f);   	} +	llassert(less_than_max_mag(mExtents[0])); +	llassert(less_than_max_mag(mExtents[1])); +  	if (!partial_build)  	{  		resizeIndices(grid_size*grid_size*6); @@ -6213,6 +5452,7 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  		}  	} +	LL_CHECK_MEMORY  	return TRUE;  } @@ -6231,8 +5471,8 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	S32 num_vertices = 0, num_indices = 0; -	const std::vector<LLVolume::Point>& mesh = volume->getMesh(); -	const std::vector<LLVector3>& profile = volume->getProfile().mProfile; +	const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); +	const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile;  	// All types of caps have the same number of vertices and indices  	num_vertices = profile.size(); @@ -6252,13 +5492,14 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	{  		resizeVertices(num_vertices);  		allocateBinormals(num_vertices); -  		if (!partial_build)  		{  			resizeIndices(num_indices);  		}  	} +	LL_CHECK_MEMORY; +  	S32 max_s = volume->getProfile().getTotal();  	S32 max_t = volume->getPath().mPath.size(); @@ -6289,35 +5530,68 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	LLVector4a* binorm = (LLVector4a*) mBinormals;  	// Copy the vertices into the array -	for (S32 i = 0; i < num_vertices; i++) + +	const LLVector4a* src = mesh.mArray+offset; +	const LLVector4a* end = src+num_vertices; +	 +	min = *src; +	max = min; +	 +	 +	const LLVector4a* p = profile.mArray; + +	if (mTypeMask & TOP_MASK)  	{ -		if (mTypeMask & TOP_MASK) -		{ -			tc[i].mV[0] = profile[i].mV[0]+0.5f; -			tc[i].mV[1] = profile[i].mV[1]+0.5f; -		} -		else +		min_uv.set((*p)[0]+0.5f, +					(*p)[1]+0.5f); + +		max_uv = min_uv; + +		while(src < end)  		{ -			// Mirror for underside. -			tc[i].mV[0] = profile[i].mV[0]+0.5f; -			tc[i].mV[1] = 0.5f - profile[i].mV[1]; -		} +			tc->mV[0] = (*p)[0]+0.5f; +			tc->mV[1] = (*p)[1]+0.5f; -		pos[i].load3(mesh[i + offset].mPos.mV); +			llassert(less_than_max_mag(*src)); +			update_min_max(min,max,*src); +			update_min_max(min_uv, max_uv, *tc); -		if (i == 0) -		{ -			max = pos[i]; -			min = max; -			min_uv = max_uv = tc[i]; +			*pos = *src; +		 +			++p; +			++tc; +			++src; +			++pos;  		} -		else +	} +	else +	{ + +		min_uv.set((*p)[0]+0.5f, +				   0.5f - (*p)[1]); +		max_uv = min_uv; + +		while(src < end)  		{ -			update_min_max(min,max,pos[i]); -			update_min_max(min_uv, max_uv, tc[i]); +			// Mirror for underside. +			tc->mV[0] = (*p)[0]+0.5f; +			tc->mV[1] = 0.5f - (*p)[1]; +		 +			llassert(less_than_max_mag(*src)); +			update_min_max(min,max,*src); +			update_min_max(min_uv, max_uv, *tc); +		 +			*pos = *src; +		 +			++p; +			++tc; +			++src; +			++pos;  		}  	} +	LL_CHECK_MEMORY +  	mCenter->setAdd(min, max);  	mCenter->mul(0.5f);  @@ -6354,15 +5628,25 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK))  	{ -		pos[num_vertices] = *mCenter; -		tc[num_vertices] = cuv; +		*pos++ = *mCenter; +		*tc++ = cuv;  		num_vertices++;  	} -		 -	for (S32 i = 0; i < num_vertices; i++) +	 +	LL_CHECK_MEMORY + +	F32* dst_binorm = (F32*) binorm; +	F32* end_binorm = (F32*) (binorm+num_vertices); + +	F32* dst_norm = (F32*) norm; +	 +	while (dst_binorm < end_binorm)  	{ -		binorm[i].load4a(binormal.getF32ptr()); -		norm[i].load4a(normal.getF32ptr()); +		binormal.store4a(dst_binorm); +		normal.store4a(dst_norm); + +		dst_binorm += 4; +		dst_norm += 4;  	}  	if (partial_build) @@ -6383,33 +5667,38 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  			{  				// Use the profile points instead of the mesh, since you want  				// the un-transformed profile distances. -				LLVector3 p1 = profile[pt1]; -				LLVector3 p2 = profile[pt2]; -				LLVector3 pa = profile[pt1+1]; -				LLVector3 pb = profile[pt2-1]; +				const LLVector4a& p1 = profile[pt1]; +				const LLVector4a& p2 = profile[pt2]; +				const LLVector4a& pa = profile[pt1+1]; +				const LLVector4a& pb = profile[pt2-1]; + +				const F32* p1V = p1.getF32ptr(); +				const F32* p2V = p2.getF32ptr(); +				const F32* paV = pa.getF32ptr(); +				const F32* pbV = pb.getF32ptr(); -				p1.mV[VZ] = 0.f; -				p2.mV[VZ] = 0.f; -				pa.mV[VZ] = 0.f; -				pb.mV[VZ] = 0.f; +				//p1.mV[VZ] = 0.f; +				//p2.mV[VZ] = 0.f; +				//pa.mV[VZ] = 0.f; +				//pb.mV[VZ] = 0.f;  				// Use area of triangle to determine backfacing  				F32 area_1a2, area_1ba, area_21b, area_2ab; -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); +				area_1a2 =  (p1V[0]*paV[1] - paV[0]*p1V[1]) + +							(paV[0]*p2V[1] - p2V[0]*paV[1]) + +							(p2V[0]*p1V[1] - p1V[0]*p2V[1]); -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); +				area_1ba =  (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + +							(pbV[0]*paV[1] - paV[0]*pbV[1]) + +							(paV[0]*p1V[1] - p1V[0]*paV[1]); -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); +				area_21b =  (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + +							(p1V[0]*pbV[1] - pbV[0]*p1V[1]) + +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]); -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); +				area_2ab =  (p2V[0]*paV[1] - paV[0]*p2V[1]) + +							(paV[0]*pbV[1] - pbV[0]*paV[1]) + +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]);  				BOOL use_tri1a2 = TRUE;  				BOOL tri_1a2 = TRUE; @@ -6444,10 +5733,13 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  				}  				else  				{ -					LLVector3 d1 = p1 - pa; -					LLVector3 d2 = p2 - pb; +					LLVector4a d1; +					d1.setSub(p1, pa); +					 +					LLVector4a d2;  +					d2.setSub(p2, pb); -					if (d1.magVecSquared() < d2.magVecSquared()) +					if (d1.dot3(d1) < d2.dot3(d2))  					{  						use_tri1a2 = TRUE;  					} @@ -6486,33 +5778,33 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  			{  				// Use the profile points instead of the mesh, since you want  				// the un-transformed profile distances. -				LLVector3 p1 = profile[pt1]; -				LLVector3 p2 = profile[pt2]; -				LLVector3 pa = profile[pt1+1]; -				LLVector3 pb = profile[pt2-1]; - -				p1.mV[VZ] = 0.f; -				p2.mV[VZ] = 0.f; -				pa.mV[VZ] = 0.f; -				pb.mV[VZ] = 0.f; - +				const LLVector4a& p1 = profile[pt1]; +				const LLVector4a& p2 = profile[pt2]; +				const LLVector4a& pa = profile[pt1+1]; +				const LLVector4a& pb = profile[pt2-1]; + +				const F32* p1V = p1.getF32ptr(); +				const F32* p2V = p2.getF32ptr(); +				const F32* paV = pa.getF32ptr(); +				const F32* pbV = pb.getF32ptr(); +				  				// Use area of triangle to determine backfacing  				F32 area_1a2, area_1ba, area_21b, area_2ab; -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); +				area_1a2 =  (p1V[0]*paV[1] - paV[0]*p1V[1]) + +							(paV[0]*p2V[1] - p2V[0]*paV[1]) + +							(p2V[0]*p1V[1] - p1V[0]*p2V[1]); -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); +				area_1ba =  (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + +							(pbV[0]*paV[1] - paV[0]*pbV[1]) + +							(paV[0]*p1V[1] - p1V[0]*paV[1]); -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); +				area_21b =  (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + +							(p1V[0]*pbV[1] - pbV[0]*p1V[1]) + +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]); -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); +				area_2ab =  (p2V[0]*paV[1] - paV[0]*p2V[1]) + +							(paV[0]*pbV[1] - pbV[0]*paV[1]) + +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]);  				BOOL use_tri1a2 = TRUE;  				BOOL tri_1a2 = TRUE; @@ -6547,10 +5839,12 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  				}  				else  				{ -					LLVector3 d1 = p1 - pa; -					LLVector3 d2 = p2 - pb; +					LLVector4a d1; +					d1.setSub(p1,pa); +					LLVector4a d2; +					d2.setSub(p2,pb); -					if (d1.magVecSquared() < d2.magVecSquared()) +					if (d1.dot3(d1) < d2.dot3(d2))  					{  						use_tri1a2 = TRUE;  					} @@ -6599,6 +5893,8 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	} + +	LL_CHECK_MEMORY  	return TRUE;  } @@ -6901,6 +6197,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat  BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  { +	LL_CHECK_MEMORY  	BOOL flat = mTypeMask & FLAT_MASK;  	U8 sculpt_type = volume->getParams().getSculptType(); @@ -6911,9 +6208,9 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  	S32 num_vertices, num_indices; -	const std::vector<LLVolume::Point>& mesh = volume->getMesh(); -	const std::vector<LLVector3>& profile = volume->getProfile().mProfile; -	const std::vector<LLPath::PathPt>& path_data = volume->getPath().mPath; +	const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); +	const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile; +	const LLAlignedArray<LLPath::PathPt,64>& path_data = volume->getPath().mPath;  	S32 max_s = volume->getProfile().getTotal(); @@ -6934,10 +6231,11 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  		}  	} +	LL_CHECK_MEMORY +  	LLVector4a* pos = (LLVector4a*) mPositions; -	LLVector4a* norm = (LLVector4a*) mNormals;  	LLVector2* tc = (LLVector2*) mTexCoords; -	F32 begin_stex = floorf(profile[mBeginS].mV[2]); +	F32 begin_stex = floorf(profile[mBeginS][2]);  	S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS;  	S32 cur_vertex = 0; @@ -6966,11 +6264,11 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  				// Get s value for tex-coord.  				if (!flat)  				{ -					ss = profile[mBeginS + s].mV[2]; +					ss = profile[mBeginS + s][2];  				}  				else  				{ -					ss = profile[mBeginS + s].mV[2] - begin_stex; +					ss = profile[mBeginS + s][2] - begin_stex;  				}  			} @@ -6990,19 +6288,17 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  				i = mBeginS + s + max_s*t;  			} -			pos[cur_vertex].load3(mesh[i].mPos.mV); -			tc[cur_vertex] = LLVector2(ss,tt); +			llassert(less_than_max_mag(mesh[i])); +			mesh[i].store4a((F32*)(pos+cur_vertex)); +			tc[cur_vertex].set(ss,tt); -			norm[cur_vertex].clear();  			cur_vertex++;  			if (test && s > 0)  			{ -				pos[cur_vertex].load3(mesh[i].mPos.mV); -				tc[cur_vertex] = LLVector2(ss,tt); -			 -				norm[cur_vertex].clear(); -				 +				llassert(less_than_max_mag(mesh[i])); +				mesh[i].store4a((F32*)(pos+cur_vertex)); +				tc[cur_vertex].set(ss,tt);  				cur_vertex++;  			}  		} @@ -7019,28 +6315,66 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  			}  			i = mBeginS + s + max_s*t; -			ss = profile[mBeginS + s].mV[2] - begin_stex; -			pos[cur_vertex].load3(mesh[i].mPos.mV); -			tc[cur_vertex] = LLVector2(ss,tt); -			norm[cur_vertex].clear();  -			 +			ss = profile[mBeginS + s][2] - begin_stex; + +			llassert(less_than_max_mag(mesh[i])); +			mesh[i].store4a((F32*)(pos+cur_vertex)); +			tc[cur_vertex].set(ss,tt); +						  			cur_vertex++;  		}  	} +	LL_CHECK_MEMORY -	//get bounding box for this side -	LLVector4a& face_min = mExtents[0]; -	LLVector4a& face_max = mExtents[1]; +	  	mCenter->clear(); -	face_min = face_max = pos[0]; +	LLVector4a* cur_pos = pos; +	LLVector4a* end_pos = pos + mNumVertices; + +	//get bounding box for this side +	LLVector4a face_min; +	LLVector4a face_max; +	 +	face_min = face_max = *cur_pos++; +		 +	while (cur_pos < end_pos) +	{ +		update_min_max(face_min, face_max, *cur_pos++); +	} + +	mExtents[0] = face_min; +	mExtents[1] = face_max; + +	U32 tc_count = mNumVertices; +	if (tc_count%2 == 1) +	{ //odd number of texture coordinates, duplicate last entry to padded end of array +		tc_count++; +		mTexCoords[mNumVertices] = mTexCoords[mNumVertices-1]; +	} + +	LLVector4a* cur_tc = (LLVector4a*) mTexCoords; +	LLVector4a* end_tc = (LLVector4a*) (mTexCoords+tc_count); + +	LLVector4a tc_min;  +	LLVector4a tc_max;  + +	tc_min = tc_max = *cur_tc++; -	for (U32 i = 1; i < mNumVertices; ++i) +	while (cur_tc < end_tc)  	{ -		update_min_max(face_min, face_max, pos[i]); +		update_min_max(tc_min, tc_max, *cur_tc++);  	} +	F32* minp = tc_min.getF32ptr(); +	F32* maxp = tc_max.getF32ptr(); + +	mTexCoordExtents[0].mV[0] = llmin(minp[0], minp[2]); +	mTexCoordExtents[0].mV[1] = llmin(minp[1], minp[3]); +	mTexCoordExtents[1].mV[0] = llmax(maxp[0], maxp[2]); +	mTexCoordExtents[1].mV[1] = llmax(maxp[1], maxp[3]); +  	mCenter->setAdd(face_min, face_max);  	mCenter->mul(0.5f); @@ -7105,33 +6439,94 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  		}  	} +	LL_CHECK_MEMORY +  	//clear normals -	for (U32 i = 0; i < mNumVertices; i++) +	F32* dst = (F32*) mNormals; +	F32* end = (F32*) (mNormals+mNumVertices); +	LLVector4a zero = LLVector4a::getZero(); + +	while (dst < end)  	{ -		mNormals[i].clear(); +		zero.store4a(dst); +		dst += 4;  	} +	LL_CHECK_MEMORY +  	//generate normals   	U32 count = mNumIndices/3; -	for (U32 i = 0; i < count; i++) //for each triangle +	LLVector4a* norm = mNormals; + +	static LLAlignedArray<LLVector4a, 64> triangle_normals; +	triangle_normals.resize(count); +	LLVector4a* output = triangle_normals.mArray; +	LLVector4a* end_output = output+count; + +	U16* idx = mIndices; + +	while (output < end_output)  	{ -		const U16* idx = &(mIndices[i*3]); -		 -		LLVector4a& v0 = *(pos+idx[0]); -		LLVector4a& v1 = *(pos+idx[1]); -		LLVector4a& v2 = *(pos+idx[2]); -		 -		LLVector4a& n0 = *(norm+idx[0]); -		LLVector4a& n1 = *(norm+idx[1]); -		LLVector4a& n2 = *(norm+idx[2]); +		LLVector4a b,v1,v2; +		b.load4a((F32*) (pos+idx[0])); +		v1.load4a((F32*) (pos+idx[1])); +		v2.load4a((F32*) (pos+idx[2]));  		//calculate triangle normal -		LLVector4a a, b, c; +		LLVector4a a; -		a.setSub(v0, v1); -		b.setSub(v0, v2); -		c.setCross3(a,b); +		a.setSub(b, v1); +		b.sub(v2); + + +		LLQuad& vector1 = *((LLQuad*) &v1); +		LLQuad& vector2 = *((LLQuad*) &v2); + +		LLQuad& amQ = *((LLQuad*) &a); +		LLQuad& bmQ = *((LLQuad*) &b); + +		//v1.setCross3(t,v0); +		//setCross3(const LLVector4a& a, const LLVector4a& b) +		// Vectors are stored in memory in w, z, y, x order from high to low +		// Set vector1 = { a[W], a[X], a[Z], a[Y] } +		vector1 = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 0, 2, 1 )); +		// Set vector2 = { b[W], b[Y], b[X], b[Z] } +		vector2 = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 1, 0, 2 )); +		// mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] } +		vector2 = _mm_mul_ps( vector1, vector2 ); +		// vector3 = { a[W], a[Y], a[X], a[Z] } +		amQ = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 1, 0, 2 )); +		// vector4 = { b[W], b[X], b[Z], b[Y] } +		bmQ = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 0, 2, 1 )); +		// mQ = { 0, a[X]*b[Y] - a[Y]*b[X], a[Z]*b[X] - a[X]*b[Z], a[Y]*b[Z] - a[Z]*b[Y] } +		vector1 = _mm_sub_ps( vector2, _mm_mul_ps( amQ, bmQ )); + +		v1.store4a((F32*) output); + +		output++; +		idx += 3; +	} + +	idx = mIndices; + +	LLVector4a* src = triangle_normals.mArray; +	 +	for (U32 i = 0; i < count; i++) //for each triangle +	{ +		LLVector4a c; +		c.load4a((F32*) (src++)); + +		LLVector4a* n0p = norm+idx[0]; +		LLVector4a* n1p = norm+idx[1]; +		LLVector4a* n2p = norm+idx[2]; + +		idx += 3; + +		LLVector4a n0,n1,n2; +		n0.load4a((F32*) n0p); +		n1.load4a((F32*) n1p); +		n2.load4a((F32*) n2p);  		n0.add(c);  		n1.add(c); @@ -7144,8 +6539,14 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  			case 1: n1.add(c); break;  			case 2: n2.add(c); break;  		}; + +		n0.store4a((F32*) n0p); +		n1.store4a((F32*) n1p); +		n2.store4a((F32*) n2p);  	} +	LL_CHECK_MEMORY +  	// adjust normals based on wrapping and stitching  	LLVector4a top; @@ -7277,6 +6678,8 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  	} +	LL_CHECK_MEMORY +  	return TRUE;  } @@ -7330,3 +6733,4 @@ void calc_binormal_from_triangle(LLVector4a& binormal,  		binormal.set( 0, 1 , 0 );  	}  } + diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 1d3b0fe52f..6b599a4126 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -37,7 +37,6 @@ class LLPath;  template <class T> class LLOctreeNode; -class LLVector4a;  class LLVolumeFace;  class LLVolume;  class LLVolumeTriangle; @@ -50,12 +49,15 @@ class LLVolumeTriangle;  #include "v3math.h"  #include "v3dmath.h"  #include "v4math.h" +#include "llvector4a.h" +#include "llmatrix4a.h"  #include "llquaternion.h"  #include "llstrider.h"  #include "v4coloru.h"  #include "llrefcount.h"  #include "llpointer.h"  #include "llfile.h" +#include "llalignedarray.h"  //============================================================================ @@ -708,16 +710,16 @@ public:  		LLFaceID  mFaceID;  	}; -	std::vector<LLVector3> mProfile;	 -	std::vector<LLVector2> mNormals; +	LLAlignedArray<LLVector4a, 64> mProfile;	 +	//LLAlignedArray<LLVector4a, 64> mNormals;  	std::vector<Face>      mFaces; -	std::vector<LLVector3> mEdgeNormals; -	std::vector<LLVector3> mEdgeCenters; + +	//LLAlignedArray<LLVector4a, 64> mEdgeNormals; +	//LLAlignedArray<LLVector4a, 64> mEdgeCenters;  	friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile);  protected: -	void genNormals(const LLProfileParams& params);  	static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);  	void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); @@ -741,13 +743,29 @@ protected:  class LLPath  {  public: -	struct PathPt +	class PathPt  	{ -		LLVector3	 mPos; -		LLVector2    mScale; -		LLQuaternion mRot; +	public: +		LLMatrix4a   mRot; +		LLVector4a	 mPos; +		 +		LLVector4a   mScale;  		F32			 mTexT; -		PathPt() { mPos.setVec(0,0,0); mTexT = 0; mScale.setVec(0,0); mRot.loadIdentity(); } +		F32 pad[3]; //for alignment +		PathPt()  +		{  +			mPos.clear();  +			mTexT = 0;  +			mScale.clear();  +			mRot.setRows(LLVector4a(1,0,0,0), +						LLVector4a(0,1,0,0), +						LLVector4a(0,0,1,0)); + +			//distinguished data in the pad for debugging +			pad[0] = 3.14159f; +			pad[1] = -3.14159f; +			pad[2] = 0.585f; +		}  	};  public: @@ -779,7 +797,7 @@ public:  	friend std::ostream& operator<<(std::ostream &s, const LLPath &path);  public: -	std::vector<PathPt> mPath; +	LLAlignedArray<PathPt, 64> mPath;  protected:  	BOOL		  mOpen; @@ -951,11 +969,7 @@ protected:  	~LLVolume(); // use unref  public: -	struct Point -	{ -		LLVector3 mPos; -	}; - +		  	struct FaceParams  	{  		LLFaceID mFaceID; @@ -978,8 +992,8 @@ public:  	const LLProfile& getProfile() const						{ return *mProfilep; }  	LLPath& getPath() const									{ return *mPathp; }  	void resizePath(S32 length); -	const std::vector<Point>& getMesh() const				{ return mMesh; } -	const LLVector3& getMeshPt(const U32 i) const			{ return mMesh[i].mPos; } +	const LLAlignedArray<LLVector4a,64>&	getMesh() const				{ return mMesh; } +	const LLVector4a& getMeshPt(const U32 i) const			{ return mMesh[i]; }  	void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); } @@ -994,10 +1008,7 @@ public:  	S32 getSculptLevel() const                              { return mSculptLevel; }  	void setSculptLevel(S32 level)							{ mSculptLevel = level; } -	S32 *getTriangleIndices(U32 &num_indices) const; - -	// returns number of triangle indeces required for path/profile mesh -	S32 getNumTriangleIndices() const; +	  	static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);  	S32 getNumTriangles(S32* vcount = NULL) const; @@ -1070,7 +1081,8 @@ public:  	LLVolumeParams mParams;  	LLPath *mPathp;  	LLProfile *mProfilep; -	std::vector<Point> mMesh; +	LLAlignedArray<LLVector4a,64> mMesh; +	  	BOOL mGenerateSingleFace;  	typedef std::vector<LLVolumeFace> face_list_t; diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index 0287026659..7713e553ef 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -592,6 +592,7 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(  	PUMP_DEBUG;  	apr_pool_t* new_pool = NULL;  	apr_status_t status = apr_pool_create(&new_pool, mPool); +	(void)status;  	apr_socket_t* socket = NULL;  	status = apr_socket_accept(  		&socket, diff --git a/indra/llmessage/llpartdata.cpp b/indra/llmessage/llpartdata.cpp index 26cafa025f..41a0310ce0 100644 --- a/indra/llmessage/llpartdata.cpp +++ b/indra/llmessage/llpartdata.cpp @@ -37,53 +37,46 @@ -const S32 PS_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; // 18 -const S32 PS_DATA_BLOCK_SIZE = 68 + PS_PART_DATA_BLOCK_SIZE; // 68 + 18 = 86 +const S32 PS_PART_DATA_GLOW_SIZE = 2; +const S32 PS_PART_DATA_BLEND_SIZE = 2; +const S32 PS_LEGACY_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; //18 +const S32 PS_SYS_DATA_BLOCK_SIZE = 68; +const S32 PS_MAX_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE+ +									PS_LEGACY_PART_DATA_BLOCK_SIZE + +									PS_PART_DATA_BLEND_SIZE + +									PS_PART_DATA_GLOW_SIZE+ +									8; //two S32 size fields + +const S32 PS_LEGACY_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE + PS_LEGACY_PART_DATA_BLOCK_SIZE; + + +const U32 PART_DATA_MASK = LLPartData::LL_PART_DATA_GLOW | LLPartData::LL_PART_DATA_BLEND; +  const F32 MAX_PART_SCALE = 4.f; -BOOL LLPartData::pack(LLDataPacker &dp) +bool LLPartData::hasGlow() const  { -	LLColor4U coloru; -	dp.packU32(mFlags, "pdflags"); -	dp.packFixed(mMaxAge, "pdmaxage", FALSE, 8, 8); -	coloru.setVec(mStartColor); -	dp.packColor4U(coloru, "pdstartcolor"); -	coloru.setVec(mEndColor); -	dp.packColor4U(coloru, "pdendcolor"); -	dp.packFixed(mStartScale.mV[0], "pdstartscalex", FALSE, 3, 5); -	dp.packFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5); -	dp.packFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5); -	dp.packFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5); -	return TRUE; +	return mStartGlow > 0.f || mEndGlow > 0.f;  } -LLSD LLPartData::asLLSD() const +bool LLPartData::hasBlendFunc() const  { -	LLSD sd = LLSD(); -	sd["pdflags"] = ll_sd_from_U32(mFlags); -	sd["pdmaxage"] = mMaxAge; -	sd["pdstartcolor"] = ll_sd_from_color4(mStartColor); -	sd["pdendcolor"] = ll_sd_from_color4(mEndColor); -	sd["pdstartscale"] = ll_sd_from_vector2(mStartScale); -	sd["pdendscale"] = ll_sd_from_vector2(mEndScale); -	return sd; +	return mBlendFuncSource != LLPartData::LL_PART_BF_SOURCE_ALPHA || mBlendFuncDest != LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;  } -bool LLPartData::fromLLSD(LLSD& sd) +S32 LLPartData::getSize() const  { -	mFlags = ll_U32_from_sd(sd["pdflags"]); -	mMaxAge = (F32)sd["pdmaxage"].asReal(); -	mStartColor = ll_color4_from_sd(sd["pdstartcolor"]); -	mEndColor = ll_color4_from_sd(sd["pdendcolor"]); -	mStartScale = ll_vector2_from_sd(sd["pdstartscale"]); -	mEndScale = ll_vector2_from_sd(sd["pdendscale"]); -	return true; +	S32 size = PS_LEGACY_PART_DATA_BLOCK_SIZE; +	if (hasGlow()) size += PS_PART_DATA_GLOW_SIZE; +	if (hasBlendFunc()) size += PS_PART_DATA_BLEND_SIZE; + +	return size;  } -BOOL LLPartData::unpack(LLDataPacker &dp) +BOOL LLPartData::unpackLegacy(LLDataPacker &dp)  {  	LLColor4U coloru; @@ -98,9 +91,70 @@ BOOL LLPartData::unpack(LLDataPacker &dp)  	dp.unpackFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5);  	dp.unpackFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5);  	dp.unpackFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5); + +	mStartGlow = 0.f; +	mEndGlow = 0.f; +	mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; +	mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; +  	return TRUE;  } +BOOL LLPartData::unpack(LLDataPacker &dp) +{ +	S32 size = 0; +	dp.unpackS32(size, "partsize"); + +	unpackLegacy(dp); +	size -= PS_LEGACY_PART_DATA_BLOCK_SIZE; + +	if (mFlags & LL_PART_DATA_GLOW) +	{ +		if (size < PS_PART_DATA_GLOW_SIZE) return FALSE; + +		U8 tmp_glow = 0; +		dp.unpackU8(tmp_glow,"pdstartglow"); +		mStartGlow = tmp_glow / 255.f; +		dp.unpackU8(tmp_glow,"pdendglow"); +		mEndGlow = tmp_glow / 255.f; + +		size -= PS_PART_DATA_GLOW_SIZE; +	} +	else +	{ +		mStartGlow = 0.f; +		mEndGlow = 0.f; +	} + +	if (mFlags & LL_PART_DATA_BLEND) +	{ +		if (size < PS_PART_DATA_BLEND_SIZE) return FALSE; +		dp.unpackU8(mBlendFuncSource,"pdblendsource"); +		dp.unpackU8(mBlendFuncDest,"pdblenddest"); +		size -= PS_PART_DATA_BLEND_SIZE; +	} +	else +	{ +		mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; +		mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; +	} + +	if (size > 0) +	{ //leftover bytes, unrecognized parameters +		U8 feh = 0; +		while (size > 0) +		{ //read remaining bytes in block +			dp.unpackU8(feh, "whippang"); +			size--; +		} + +		//this particle system won't display properly, better to not show anything +		return FALSE; +	} + + +	return TRUE; +}  void LLPartData::setFlags(const U32 flags)  { @@ -148,6 +202,18 @@ void LLPartData::setEndAlpha(const F32 alpha)  	mEndColor.mV[3] = alpha;  } +// static +bool LLPartData::validBlendFunc(S32 func) +{ +	if (func >= 0 +		&& func < LL_PART_BF_COUNT +		&& func != UNSUPPORTED_DEST_ALPHA +		&& func != UNSUPPORTED_ONE_MINUS_DEST_ALPHA) +	{ +		return true; +	} +	return false; +}  LLPartSysData::LLPartSysData()  { @@ -160,6 +226,10 @@ LLPartSysData::LLPartSysData()  	mPartData.mStartScale = LLVector2(1.f, 1.f);  	mPartData.mEndScale = LLVector2(1.f, 1.f);  	mPartData.mMaxAge = 10.0; +	mPartData.mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; +	mPartData.mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; +	mPartData.mStartGlow = 0.f; +	mPartData.mEndGlow = 0.f;  	mMaxAge = 0.0;  	mStartAge = 0.0; @@ -175,38 +245,7 @@ LLPartSysData::LLPartSysData()  	mNumParticles = 0;  } - -BOOL LLPartSysData::pack(LLDataPacker &dp) -{ -	dp.packU32(mCRC, "pscrc"); -	dp.packU32(mFlags, "psflags"); -	dp.packU8(mPattern, "pspattern"); -	dp.packFixed(mMaxAge, "psmaxage", FALSE, 8, 8); -	dp.packFixed(mStartAge, "psstartage", FALSE, 8, 8); -	dp.packFixed(mInnerAngle, "psinnerangle", FALSE, 3, 5); -	dp.packFixed(mOuterAngle, "psouterangle", FALSE, 3, 5); -	dp.packFixed(mBurstRate, "psburstrate", FALSE, 8, 8); -	dp.packFixed(mBurstRadius, "psburstradius", FALSE, 8, 8); -	dp.packFixed(mBurstSpeedMin, "psburstspeedmin", FALSE, 8, 8); -	dp.packFixed(mBurstSpeedMax, "psburstspeedmax", FALSE, 8, 8); -	dp.packU8(mBurstPartCount, "psburstpartcount"); - -	dp.packFixed(mAngularVelocity.mV[0], "psangvelx", TRUE, 8, 7); -	dp.packFixed(mAngularVelocity.mV[1], "psangvely", TRUE, 8, 7); -	dp.packFixed(mAngularVelocity.mV[2], "psangvelz", TRUE, 8, 7); - -	dp.packFixed(mPartAccel.mV[0], "psaccelx", TRUE, 8, 7); -	dp.packFixed(mPartAccel.mV[1], "psaccely", TRUE, 8, 7); -	dp.packFixed(mPartAccel.mV[2], "psaccelz", TRUE, 8, 7); - -	dp.packUUID(mPartImageID, "psuuid"); -	dp.packUUID(mTargetUUID, "pstargetuuid"); -	mPartData.pack(dp); -	return TRUE; -} - - -BOOL LLPartSysData::unpack(LLDataPacker &dp) +BOOL LLPartSysData::unpackSystem(LLDataPacker &dp)  {  	dp.unpackU32(mCRC, "pscrc");  	dp.unpackU32(mFlags, "psflags"); @@ -232,10 +271,48 @@ BOOL LLPartSysData::unpack(LLDataPacker &dp)  	dp.unpackUUID(mPartImageID, "psuuid");  	dp.unpackUUID(mTargetUUID, "pstargetuuid"); -	mPartData.unpack(dp);  	return TRUE;  } +BOOL LLPartSysData::unpackLegacy(LLDataPacker &dp) +{ +	unpackSystem(dp); +	mPartData.unpackLegacy(dp); + +	return TRUE; +} + +BOOL LLPartSysData::unpack(LLDataPacker &dp) +{ +	// syssize is currently unused.  Adding now when modifying the 'version to make extensible in the future +	S32 size = 0; +	dp.unpackS32(size, "syssize"); +	 +	if (size != PS_SYS_DATA_BLOCK_SIZE) +	{ //unexpected size, this viewer doesn't know how to parse this particle system +		 +		//skip to LLPartData block +		U8 feh = 0; +		 +		for (U32 i = 0; i < size; ++i) +		{ +			dp.unpackU8(feh, "whippang"); +		} +				 +		dp.unpackS32(size, "partsize"); +		//skip LLPartData block +		for (U32 i = 0; i < size; ++i) +		{ +			dp.unpackU8(feh, "whippang"); +		} +		return FALSE; +	} + +	unpackSystem(dp); +	 +	return mPartData.unpack(dp); +} +  std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)  {  	s << "Flags: " << std::hex << data.mFlags; @@ -253,7 +330,7 @@ std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)  BOOL LLPartSysData::isNullPS(const S32 block_num)  { -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; +	U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];  	U32 crc;  	S32 size; @@ -264,14 +341,28 @@ BOOL LLPartSysData::isNullPS(const S32 block_num)  	{  		return TRUE;  	} -	else if (size != PS_DATA_BLOCK_SIZE) +	 +	if (size > PS_MAX_DATA_BLOCK_SIZE)  	{ -		llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl; +		//size is too big, newer particle version unsupported  		return TRUE;  	} -	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE); -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); +	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE); + +	LLDataPackerBinaryBuffer dp(ps_data_block, size); +	if (size > PS_LEGACY_DATA_BLOCK_SIZE) +	{ +		// non legacy systems pack a size before the CRC +		S32 tmp = 0; +		dp.unpackS32(tmp, "syssize"); + +		if (tmp > PS_SYS_DATA_BLOCK_SIZE) +		{ //unknown system data block size, don't know how to parse it, treat as NULL +			return TRUE; +		} +	} +  	dp.unpackU32(crc, "crc");  	if (crc == 0) @@ -281,50 +372,37 @@ BOOL LLPartSysData::isNullPS(const S32 block_num)  	return FALSE;  } - -//static -BOOL LLPartSysData::packNull() -{ -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; -	gMessageSystem->addBinaryData("PSBlock", ps_data_block, 0); -	return TRUE; -} - - -BOOL LLPartSysData::packBlock() -{ -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; - -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); -	pack(dp); - -	// Add to message -	gMessageSystem->addBinaryData("PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE); - -	return TRUE; -}                                          - -  BOOL LLPartSysData::unpackBlock(const S32 block_num)  { -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; +	U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];  	// Check size of block  	S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock"); -	if (size != PS_DATA_BLOCK_SIZE) +	if (size > PS_MAX_DATA_BLOCK_SIZE)  	{ -		llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl; +		// Larger packets are newer and unsupported  		return FALSE;  	}  	// Get from message -	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE); +	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE); -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); -	unpack(dp); +	LLDataPackerBinaryBuffer dp(ps_data_block, size); -	return TRUE; +	if (size == PS_LEGACY_DATA_BLOCK_SIZE) +	{ +		return unpackLegacy(dp); +	} +	else +	{ +		return unpack(dp); +	} +} + +bool LLPartSysData::isLegacyCompatible() const +{ +	return !mPartData.hasGlow() && !mPartData.hasBlendFunc();  }  void LLPartSysData::clampSourceParticleRate() diff --git a/indra/llmessage/llpartdata.h b/indra/llmessage/llpartdata.h index a4ef058b30..ed5c1a6ac7 100644 --- a/indra/llmessage/llpartdata.h +++ b/indra/llmessage/llpartdata.h @@ -70,7 +70,12 @@ enum LLPSScriptFlags  	LLPS_SRC_TARGET_UUID,  	LLPS_SRC_OMEGA,  	LLPS_SRC_ANGLE_BEGIN, -	LLPS_SRC_ANGLE_END +	LLPS_SRC_ANGLE_END, + +	LLPS_PART_BLEND_FUNC_SOURCE, +	LLPS_PART_BLEND_FUNC_DEST, +	LLPS_PART_START_GLOW, +	LLPS_PART_END_GLOW  }; @@ -83,11 +88,13 @@ public:  		mParameter(0.f)  	{  	} +	BOOL unpackLegacy(LLDataPacker &dp);  	BOOL unpack(LLDataPacker &dp); +  	BOOL pack(LLDataPacker &dp); -	LLSD asLLSD() const; -	operator LLSD() const {return asLLSD(); } -	bool fromLLSD(LLSD& sd); +	 +	bool hasGlow() const; +	bool hasBlendFunc() const;  	// Masks for the different particle flags  	enum @@ -102,17 +109,39 @@ public:  		LL_PART_TARGET_LINEAR_MASK =	0x80,		// Particle uses a direct linear interpolation  		LL_PART_EMISSIVE_MASK =			0x100,		// Particle is "emissive", instead of being lit  		LL_PART_BEAM_MASK =				0x200,		// Particle is a "beam" connecting source and target +		LL_PART_RIBBON_MASK =			0x400,		// Particles are joined together into one continuous triangle strip  		// Not implemented yet!  		//LL_PART_RANDOM_ACCEL_MASK =		0x100,		// Particles have random acceleration  		//LL_PART_RANDOM_VEL_MASK =		0x200,		// Particles have random velocity shifts"  		//LL_PART_TRAIL_MASK =			0x400,		// Particles have historical "trails" +		//sYSTEM SET FLAGS +		LL_PART_DATA_GLOW =				0x10000, +		LL_PART_DATA_BLEND =			0x20000, +  		// Viewer side use only!  		LL_PART_HUD =					0x40000000,  		LL_PART_DEAD_MASK =				0x80000000,  	}; +	enum +	{ +		LL_PART_BF_ONE = 0, +		LL_PART_BF_ZERO = 1, +		LL_PART_BF_DEST_COLOR = 2, +		LL_PART_BF_SOURCE_COLOR = 3, +		LL_PART_BF_ONE_MINUS_DEST_COLOR = 4, +		LL_PART_BF_ONE_MINUS_SOURCE_COLOR = 5, +		UNSUPPORTED_DEST_ALPHA = 6, +		LL_PART_BF_SOURCE_ALPHA = 7, +		UNSUPPORTED_ONE_MINUS_DEST_ALPHA = 8, +		LL_PART_BF_ONE_MINUS_SOURCE_ALPHA = 9, +		LL_PART_BF_COUNT = 10 +	}; + +	static bool validBlendFunc(S32 func); +  	void setFlags(const U32 flags);  	void setMaxAge(const F32 max_age);  	void setStartScale(const F32 xs, F32 ys); @@ -126,6 +155,9 @@ public:  	friend class LLPartSysData;  	friend class LLViewerPartSourceScript; +private: +	S32 getSize() const; +  	// These are public because I'm really lazy...  public:  	U32					mFlags;						// Particle state/interpolators in effect @@ -137,6 +169,12 @@ public:  	LLVector3			mPosOffset;					// Offset from source if using FOLLOW_SOURCE  	F32					mParameter;					// A single floating point parameter + +	F32					mStartGlow; +	F32					mEndGlow; +	 +	U8					mBlendFuncSource; +	U8					mBlendFuncDest;  }; @@ -146,15 +184,13 @@ public:  	LLPartSysData();  	BOOL unpack(LLDataPacker &dp); -	BOOL pack(LLDataPacker &dp); - -	 +	BOOL unpackLegacy(LLDataPacker &dp);  	BOOL unpackBlock(const S32 block_num); -	BOOL packBlock(); - -	static BOOL packNull(); +		  	static BOOL isNullPS(const S32 block_num); // Returns FALSE if this is a "NULL" particle system (i.e. no system) +	bool isLegacyCompatible() const; +  	// Different masks for effects on the source  	enum  	{ @@ -187,7 +223,12 @@ public:  	void clampSourceParticleRate();  	friend std::ostream&	 operator<<(std::ostream& s, const LLPartSysData &data);		// Stream a + +	S32 getdataBlockSize() const; +private: +	BOOL unpackSystem(LLDataPacker &dp); +  public:  	// Public because I'm lazy.... diff --git a/indra/llmessage/tests/llpartdata_test.cpp b/indra/llmessage/tests/llpartdata_test.cpp index 9123bd06c7..de81e0bbb2 100644 --- a/indra/llmessage/tests/llpartdata_test.cpp +++ b/indra/llmessage/tests/llpartdata_test.cpp @@ -38,10 +38,34 @@  namespace tut  { + +	//bunch of sniffed data that *should* be a valid particle system +	static U8 msg[] = {  +		0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,  +		0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x80, 0x00, 0x80,  +		0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x5e, 0x12, 0x0b, 0xa1, 0x58, 0x05, 0xdc, 0x57, 0x66,  +		0xb7, 0xf5, 0xac, 0x4b, 0xd1, 0x8f, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x0a, 0xff,  +		0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,  +		0x00, 0x7e, 0xc6, 0x81, 0xdc, 0x7e, 0xc6, 0x81, 0xdc, 0x77, 0xcf, 0xef, 0xd4, 0xce, 0x64, 0x1a, 0x7e,  +		0x26, 0x87, 0x55, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0x77, 0xcf, 0x98, 0xa3, 0xab,  +		0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf2,  +		0xf1, 0x65, 0x32, 0x1b, 0xef, 0x18, 0x70, 0x66, 0xba, 0x30, 0xa0, 0x11, 0xaa, 0x2f, 0xb0, 0xab, 0xd0,  +		0x30, 0x7d, 0xbd, 0x01, 0x00, 0xf8, 0x0d, 0xb8, 0x30, 0x01, 0x00, 0x00, 0x00, 0xce, 0xc6, 0x81, 0xdc,  +		0xce, 0xc6, 0x81, 0xdc, 0xc7, 0xcf, 0xef, 0xd4, 0x75, 0x65, 0x1a, 0x7f, 0x62, 0x6f, 0x55, 0x7f, 0x6d,  +		0x65, 0x22, 0x7f, 0x6d, 0x65, 0x22, 0x7f, 0xc7, 0xcf, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,  +		0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xf2, 0xf1, 0x62, 0x12, 0x1b, 0xef,  +		0x18, 0x7e, 0xbd, 0x01, 0x00, 0x16, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  +		0x00, 0x00, 0x00, 0x00, 0x7c, 0xac, 0x28, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48,  +		0xe0, 0xb9, 0x30, 0x03, 0xe1, 0xb9, 0x30, 0xbb, 0x00, 0x00, 0x00, 0x48, 0xe0, 0xb9, 0x30, 0x36, 0xd9,  +		0x81, 0xdc, 0x36, 0xd9, 0x81, 0xdc, 0x3f, 0xd0, 0xef, 0xd4, 0xa5, 0x7a, 0x72, 0x7f, 0x26, 0x30, 0x55,  +		0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x3f, 0xd0, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab,  +		0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00 };  	struct partdata_test  	{  	}; +  	typedef test_group<partdata_test> partdata_test_t;  	typedef partdata_test_t::object partdata_test_object_t;  	tut::partdata_test_t tut_partdata_test("LLPartData"); @@ -49,168 +73,82 @@ namespace tut  	template<> template<>  	void partdata_test_object_t::test<1>()  	{ -		LLPartData llpdata,llpdata1; -		U8 pkbuf[128]; - -		llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | -		LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK | -		LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK | -		LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK); - -		llpdata.setMaxAge(29.3f); - -		LLVector3 llvec1(1.0f, .5f, .25f); -		llpdata.setStartColor(llvec1); -		llpdata.setStartAlpha(.7f); - -		LLVector3 llvec2(.2f, .3f, 1.0f); -		llpdata.setEndColor(llvec2); -		llpdata.setEndAlpha(1.0f); +		LLPartSysData llpsysdata; +		LLDataPackerBinaryBuffer dp1(msg, sizeof(msg)); -		llpdata.setStartScale(3.23f, 4.0f); -		llpdata.setEndScale(2.4678f, 1.0f); +		ensure("LLPartSysData::unpack failed.", llpsysdata.unpack(dp1)); -		LLDataPackerBinaryBuffer dp((U8*)pkbuf, 128); -		llpdata.pack(dp); -		S32 cur_size = dp.getCurrentSize(); -		 -		LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size); -		llpdata1.unpack(dp1); - -		ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags); -		ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8); - -		ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8); -		ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8); -		ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8); -		ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8); - -		ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8); -		ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8); -		ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8); -		ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8); - -		ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5); -		ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5); - -		ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5); -		ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5); -	} - - -	template<> template<> -	void partdata_test_object_t::test<2>() -	{ -		LLPartData llpdata,llpdata1; - -		llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | -		LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK | -		LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK | -		LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK); -		 -		llpdata.setMaxAge(29.3f); - -		LLVector3 llvec1(1.0f, .5f, .25f); -		llpdata.setStartColor(llvec1); -		llpdata.setStartAlpha(.7f); - -		LLVector3 llvec2(.2f, .3f, 1.0f); -		llpdata.setEndColor(llvec2); -		llpdata.setEndAlpha(1.0f); - -		llpdata.setStartScale(3.23f, 4.0f); -		llpdata.setEndScale(2.4678f, 1.0f); - -		LLSD llsd = llpdata.asLLSD(); - -		llpdata1.fromLLSD(llsd); - -		ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags); -		ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8); - -		ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8); -		ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8); -		ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8); -		ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8); - -		ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8); -		ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8); -		ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8); -		ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8); - -		ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5); -		ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5); - -		ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5); -		ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5); -	} - - -//*********llpartsysdata*********** - -	template<> template<> -	void partdata_test_object_t::test<3>() -	{ -		LLPartSysData llpsysdata, llpsysdata1; -		U8 pkbuf[256]; -		llpsysdata.setBurstSpeedMin(33.33f); -		ensure("1.mBurstSpeedMin coudnt be set", 33.33f == llpsysdata.mBurstSpeedMin); - -		llpsysdata.setBurstSpeedMax(44.44f);  -		ensure("2.mBurstSpeedMax coudnt be set", 44.44f == llpsysdata.mBurstSpeedMax); - -		llpsysdata.setBurstRadius(45.55f); -		ensure("3.mBurstRadius coudnt be set", 45.55f == llpsysdata.mBurstRadius); - -		LLVector3 llvec(44.44f, 111.11f, -40.4f); -		llpsysdata.setPartAccel(llvec); - -		llpsysdata.mCRC = 0xFFFFFFFF; -		llpsysdata.mFlags = 0x20; - -		llpsysdata.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE_EMPTY; - -		llpsysdata.mMaxAge = 99.99f; -		llpsysdata.mStartAge = 18.5f; -		llpsysdata.mInnerAngle = 4.234f; -		llpsysdata.mOuterAngle = 7.123f; -		llpsysdata.mBurstRate  = 245.53f; -		llpsysdata.mBurstPartCount = 0xFF; -		llpsysdata.mAngularVelocity = llvec; - -		llpsysdata.mPartImageID.generate(); -		llpsysdata.mTargetUUID.generate(); +		//mCRC	1	unsigned int +		ensure("mCRC different after unpacking", llpsysdata.mCRC == (U32) 1); +		//mFlags	0	unsigned int +		ensure ("mFlags different after unpacking", llpsysdata.mFlags == (U32) 0); +		//mPattern	1 ''	unsigned char +		ensure ("mPattern different after unpacking", llpsysdata.mPattern == (U8) 1); +		//mInnerAngle	0.00000000	float +		ensure_approximately_equals("mInnerAngle different after unpacking", llpsysdata.mInnerAngle, 0.f, 8); +		//mOuterAngle	0.00000000	float +		ensure_approximately_equals("mOuterAngle different after unpacking", llpsysdata.mOuterAngle, 0.f, 8); +		//mAngularVelocity	0,0,0 +		ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[0], 0.f, 8); +		ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[1], 0.f, 8); +		ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[2], 0.f, 8); +		//mBurstRate	0.097656250	float +		ensure_approximately_equals("mBurstRate different after unpacking", llpsysdata.mBurstRate, 0.097656250f, 8); +		//mBurstPartCount	1 ''	unsigned char +		ensure("mBurstPartCount different after unpacking", llpsysdata.mBurstPartCount == (U8) 1); +		//mBurstRadius	0.00000000	float +		ensure_approximately_equals("mBurstRadius different after unpacking", llpsysdata.mBurstRadius, 0.f, 8); +		//mBurstSpeedMin	1.0000000	float +		ensure_approximately_equals("mBurstSpeedMin different after unpacking", llpsysdata.mBurstSpeedMin, 1.f, 8); +		//mBurstSpeedMax	1.0000000	float +		ensure_approximately_equals("mBurstSpeedMax different after unpacking", llpsysdata.mBurstSpeedMax, 1.f, 8); +		//mMaxAge	0.00000000	float +		ensure_approximately_equals("mMaxAge different after unpacking", llpsysdata.mMaxAge, 0.f, 8); +		//mStartAge	0.00000000	float +		ensure_approximately_equals("mStartAge different after unpacking", llpsysdata.mStartAge, 0.f, 8); +		//mPartAccel	<0,0,0> +		ensure_approximately_equals("mPartAccel.mV[0] different after unpacking", llpsysdata.mPartAccel.mV[0], 0.f, 7); +		ensure_approximately_equals("mPartAccel.mV[1] different after unpacking", llpsysdata.mPartAccel.mV[1], 0.f, 7); +		ensure_approximately_equals("mPartAccel.mV[2] different after unpacking", llpsysdata.mPartAccel.mV[2], 0.f, 7); + +		//mPartData +		LLPartData& data = llpsysdata.mPartData; + +		//mFlags	132354	unsigned int +		ensure ("mPartData.mFlags different after unpacking", data.mFlags == (U32) 132354); +		//mMaxAge	10.000000	float +		ensure_approximately_equals("mPartData.mMaxAge different after unpacking", data.mMaxAge, 10.f, 8);  +		//mStartColor	<1,1,1,1> +		ensure_approximately_equals("mPartData.mStartColor.mV[0] different after unpacking", data.mStartColor.mV[0], 1.f, 8); +		ensure_approximately_equals("mPartData.mStartColor.mV[1] different after unpacking", data.mStartColor.mV[1], 1.f, 8); +		ensure_approximately_equals("mPartData.mStartColor.mV[2] different after unpacking", data.mStartColor.mV[2], 1.f, 8); +		ensure_approximately_equals("mPartData.mStartColor.mV[3] different after unpacking", data.mStartColor.mV[3], 1.f, 8); +		//mEndColor	<1,1,0,0> +		ensure_approximately_equals("mPartData.mEndColor.mV[0] different after unpacking", data.mEndColor.mV[0], 1.f, 8); +		ensure_approximately_equals("mPartData.mEndColor.mV[1] different after unpacking", data.mEndColor.mV[1], 1.f, 8); +		ensure_approximately_equals("mPartData.mEndColor.mV[2] different after unpacking", data.mEndColor.mV[2], 0.f, 8); +		ensure_approximately_equals("mPartData.mEndColor.mV[3] different after unpacking", data.mEndColor.mV[3], 0.f, 8); +		//mStartScale	<1,1> +		ensure_approximately_equals("mPartData.mStartScale.mV[0] different after unpacking", data.mStartScale.mV[0], 1.f, 8); +		ensure_approximately_equals("mPartData.mStartScale.mV[1] different after unpacking", data.mStartScale.mV[1], 1.f, 8); +		//mEndScale	<0,0> +		ensure_approximately_equals("mPartData.mEndScale.mV[0] different after unpacking", data.mEndScale.mV[0], 0.f, 8); +		ensure_approximately_equals("mPartData.mEndScale.mV[1] different after unpacking", data.mEndScale.mV[1], 0.f, 8); +		//mPosOffset	<0,0,0> +		ensure_approximately_equals("mPartData.mPosOffset.mV[0] different after unpacking", data.mPosOffset.mV[0], 0.f, 8); +		ensure_approximately_equals("mPartData.mPosOffset.mV[1] different after unpacking", data.mPosOffset.mV[1], 0.f, 8); +		ensure_approximately_equals("mPartData.mPosOffset.mV[2] different after unpacking", data.mPosOffset.mV[2], 0.f, 8); +		//mParameter	0.00000000	float +		ensure_approximately_equals("mPartData.mParameter different after unpacking", data.mParameter, 0.f, 8); -		LLDataPackerBinaryBuffer dp((U8*)pkbuf, 256); -		llpsysdata.pack(dp); -		S32 cur_size = dp.getCurrentSize(); -		LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size); -		llpsysdata1.unpack(dp1); - -		ensure("1.mCRC's not equal", llpsysdata.mCRC == llpsysdata1.mCRC); -		ensure("2.mFlags's not equal", llpsysdata.mFlags == llpsysdata1.mFlags); -		ensure("3.mPattern's not equal", llpsysdata.mPattern == llpsysdata1.mPattern); -		ensure_approximately_equals("4.mMaxAge's not equal", llpsysdata.mMaxAge , llpsysdata1.mMaxAge, 8); -		ensure_approximately_equals("5.mStartAge's not equal", llpsysdata.mStartAge, llpsysdata1.mStartAge, 8); -		ensure_approximately_equals("6.mOuterAngle's not equal", llpsysdata.mOuterAngle, llpsysdata1.mOuterAngle, 5); -		ensure_approximately_equals("7.mInnerAngles's not equal", llpsysdata.mInnerAngle, llpsysdata1.mInnerAngle, 5); -		ensure_approximately_equals("8.mBurstRate's not equal", llpsysdata.mBurstRate, llpsysdata1.mBurstRate, 8); -		ensure("9.mBurstPartCount's not equal", llpsysdata.mBurstPartCount == llpsysdata1.mBurstPartCount); - -		ensure_approximately_equals("10.mBurstSpeedMin's not equal", llpsysdata.mBurstSpeedMin, llpsysdata1.mBurstSpeedMin, 8); -		ensure_approximately_equals("11.mBurstSpeedMax's not equal", llpsysdata.mBurstSpeedMax, llpsysdata1.mBurstSpeedMax, 8); - -		ensure_approximately_equals("12.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[0], llpsysdata1.mAngularVelocity.mV[0], 7); -		ensure_approximately_equals("13.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[1], llpsysdata1.mAngularVelocity.mV[1], 7); -		ensure_approximately_equals("14.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[2], llpsysdata1.mAngularVelocity.mV[2], 7); -			 -		ensure_approximately_equals("15.mPartAccel's not equal", llpsysdata.mPartAccel.mV[0], llpsysdata1.mPartAccel.mV[0], 7); -		ensure_approximately_equals("16.mPartAccel's not equal", llpsysdata.mPartAccel.mV[1], llpsysdata1.mPartAccel.mV[1], 7); -		ensure_approximately_equals("17.mPartAccel's not equal", llpsysdata.mPartAccel.mV[2], llpsysdata1.mPartAccel.mV[2], 7); - -		ensure("18.mPartImageID's not equal", llpsysdata.mPartImageID == llpsysdata1.mPartImageID); -		ensure("19.mTargetUUID's not equal", llpsysdata.mTargetUUID == llpsysdata1.mTargetUUID); -		ensure_approximately_equals("20.mBurstRadius's not equal", llpsysdata.mBurstRadius, llpsysdata1.mBurstRadius, 8); +		//mStartGlow	0.00000000	float +		ensure_approximately_equals("mPartData.mStartGlow different after unpacking", data.mStartGlow, 0.f, 8); +		//mEndGlow	0.00000000	float +		ensure_approximately_equals("mPartData.mEndGlow different after unpacking", data.mEndGlow, 0.f, 8); +		//mBlendFuncSource	2 ''	unsigned char +		ensure("mPartData.mBlendFuncSource different after unpacking", data.mBlendFuncSource == (U8) 2); +		//mBlendFuncDest	1 ''	unsigned char  +		ensure("mPartData.mBlendFuncDest different after unpacking", data.mBlendFuncDest == (U8) 1);  	}  } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1d257d8415..f8ab085aac 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -310,7 +310,7 @@ void LLVBOPool::cleanup()  			if (r.mClientData)  			{ -				ll_aligned_free_16((void*) r.mClientData); +				ll_aligned_free((void*) r.mClientData);  			}  			l.pop_front(); @@ -2360,7 +2360,8 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)  		if (data_mask & MAP_COLOR)  		{  			S32 loc = TYPE_COLOR; -			void* ptr = (void*)(base + mOffsets[TYPE_COLOR]); +			//bind emissive instead of color pointer if emissive is present +			void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]);  			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);  		}  		if (data_mask & MAP_EMISSIVE) @@ -2368,6 +2369,12 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)  			S32 loc = TYPE_EMISSIVE;  			void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);  			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + +			if (!(data_mask & MAP_COLOR)) +			{ //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps +				loc = TYPE_COLOR; +				glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); +			}  		}  		if (data_mask & MAP_WEIGHT)  		{ diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp index 161496b1f5..fdfaf284de 100644 --- a/indra/llui/llconsole.cpp +++ b/indra/llui/llconsole.cpp @@ -243,8 +243,6 @@ void LLConsole::draw()  void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color)   {  	LLSD paragraph_color_segments; -	LLColor4 lcolor=color; -	  	paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText);  	LLSD color_sd = color.getValue();  	paragraph_color_segments[0]["color"]=color_sd; diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index c1cd04186b..537cc82302 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -368,7 +368,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW  	const llwchar* base = wtext.c_str();  	const llwchar* cur = base;  	const llwchar* line = NULL; - +        (void)line;  	while( *cur )  	{  		if( *cur == '\n' || cur == base ) diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 4c730286da..13c143b22f 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -478,7 +478,7 @@ void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp)  		{  			LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;  			LLRect resize_bar_rect = getRect(); - +			(void)resize_bar_rect;  			LLResizeBar::Params resize_params;  			resize_params.name("resize");  			resize_params.resizing_view(lp); @@ -855,3 +855,4 @@ void LLLayoutStack::updateResizeBarLimits()  		previous_visible_panelp = visible_panelp;  	}  } + diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 3815eec447..ec66b6df56 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -351,7 +351,6 @@ void LLTextBase::drawSelectionBackground()  		S32 selection_left		= llmin( mSelectionStart, mSelectionEnd );  		S32 selection_right		= llmax( mSelectionStart, mSelectionEnd ); -		LLRect selection_rect = mVisibleTextRect;  		// Skip through the lines we aren't drawing.  		LLRect content_display_rect = getVisibleDocumentRect(); @@ -2241,6 +2240,8 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,  	// Figure out which line we're nearest to.  	LLRect visible_region = getVisibleDocumentRect();  	LLRect doc_rect = mDocumentView->getRect(); +	(void)visible_region; +	(void)doc_rect;  	S32 doc_y = local_y - doc_rect.mBottom; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 46fbd1e6a0..e4bd51c8ce 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2490,7 +2490,6 @@ void LLTextEditor::updateSegments()  		mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this);  		clearSegments(); -		segment_set_t::iterator insert_it = mSegments.begin();  		for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)  		{  			insertSegment(*list_it); diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 63b7e452d2..62b6a0cd2f 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -653,7 +653,6 @@ void LLToolBar::updateLayoutAsNeeded()  	S32 max_row_length = 0;  	S32 max_length; -	S32 max_total_girth;  	S32 cur_start;  	S32 cur_row ;  	S32 row_pad_start; @@ -664,7 +663,6 @@ void LLToolBar::updateLayoutAsNeeded()  	if (orientation == LLLayoutStack::HORIZONTAL)  	{  		max_length = getRect().getWidth() - mPadLeft - mPadRight; -		max_total_girth = getRect().getHeight() - mPadTop - mPadBottom;  		row_pad_start = mPadLeft;  		row_pad_end = mPadRight;  		cur_row = mPadTop; @@ -673,7 +671,6 @@ void LLToolBar::updateLayoutAsNeeded()  	else // VERTICAL  	{  		max_length = getRect().getHeight() - mPadTop - mPadBottom; -		max_total_girth = getRect().getWidth() - mPadLeft - mPadRight;  		row_pad_start = mPadTop;  		row_pad_end = mPadBottom;  		cur_row = mPadLeft; @@ -842,6 +839,7 @@ void LLToolBar::draw()  	{  		LLRect caret_rect = caret->getRect();  		LLRect toolbar_rect = getRect(); +		(void)toolbar_rect;  		if (getOrientation(mSideType) == LLLayoutStack::HORIZONTAL)  		{  			caret->setRect(LLRect(mDragx-caret_rect.getWidth()/2+1, diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l index 307a5561a0..3f844d0fd1 100644 --- a/indra/lscript/lscript_compile/indra.l +++ b/indra/lscript/lscript_compile/indra.l @@ -355,6 +355,10 @@ extern "C" { int yyerror(const char *fmt, ...); }  "PSYS_PART_END_SCALE"	{ count(); yylval.ival = LLPS_PART_END_SCALE; return (INTEGER_CONSTANT); }  "PSYS_PART_MAX_AGE"		{ count(); yylval.ival = LLPS_PART_MAX_AGE; return (INTEGER_CONSTANT); } +"PSYS_PART_BLEND_FUNC_SOURCE"	{ count(); yylval.ival = LLPS_PART_BLEND_FUNC_SOURCE; return (INTEGER_CONSTANT); } +"PSYS_PART_BLEND_FUNC_DEST"		{ count(); yylval.ival = LLPS_PART_BLEND_FUNC_DEST; return (INTEGER_CONSTANT); } +"PSYS_PART_START_GLOW"	{ count(); yylval.ival = LLPS_PART_START_GLOW; return (INTEGER_CONSTANT); } +"PSYS_PART_END_GLOW"	{ count(); yylval.ival = LLPS_PART_END_GLOW; return (INTEGER_CONSTANT); }  "PSYS_PART_WIND_MASK"				{ count(); yylval.ival = LLPartData::LL_PART_WIND_MASK; return(INTEGER_CONSTANT); }  "PSYS_PART_INTERP_COLOR_MASK"		{ count(); yylval.ival = LLPartData::LL_PART_INTERP_COLOR_MASK; return(INTEGER_CONSTANT); } @@ -365,6 +369,16 @@ extern "C" { int yyerror(const char *fmt, ...); }  "PSYS_PART_TARGET_POS_MASK"			{ count(); yylval.ival = LLPartData::LL_PART_TARGET_POS_MASK; return(INTEGER_CONSTANT); }  "PSYS_PART_EMISSIVE_MASK"			{ count(); yylval.ival = LLPartData::LL_PART_EMISSIVE_MASK; return(INTEGER_CONSTANT); }  "PSYS_PART_TARGET_LINEAR_MASK"		{ count(); yylval.ival = LLPartData::LL_PART_TARGET_LINEAR_MASK; return(INTEGER_CONSTANT); } +"PSYS_PART_RIBBON_MASK"				{ count(); yylval.ival = LLPartData::LL_PART_RIBBON_MASK; return(INTEGER_CONSTANT); } + +"PSYS_PART_BF_ONE"						{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ZERO"						{ count(); yylval.ival = LLPartData::LL_PART_BF_ZERO; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_DEST_COLOR"				{ count(); yylval.ival = LLPartData::LL_PART_BF_DEST_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_SOURCE_COLOR"				{ count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ONE_MINUS_DEST_COLOR"		{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_DEST_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR"	{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_SOURCE_ALPHA"				{ count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_ALPHA; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA"	{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; return(INTEGER_CONSTANT); }  "PSYS_SRC_MAX_AGE"					{ count(); yylval.ival = LLPS_SRC_MAX_AGE; return(INTEGER_CONSTANT); } diff --git a/indra/lscript/lscript_execute/lscript_readlso.cpp b/indra/lscript/lscript_execute/lscript_readlso.cpp index 35caa41ae1..3cdb41ac17 100644 --- a/indra/lscript/lscript_execute/lscript_readlso.cpp +++ b/indra/lscript/lscript_execute/lscript_readlso.cpp @@ -145,7 +145,7 @@ void LLScriptLSOParse::printGlobals(LLFILE *fp)  		// get offset to skip past name  		varoffset = global_v_offset;  		offset = bytestream2integer(mRawData, global_v_offset); -		 +		(void)offset; //hush little compiler  		// get typeexport  		type = *(mRawData + global_v_offset++); @@ -262,8 +262,6 @@ void LLScriptLSOParse::printGlobalFunctions(LLFILE *fp)  		fprintf(fp, "[Function #%d] [0x%X] %s\n", function_number, orig_function_offset, name);  		fprintf(fp, "\tReturn Type: %s\n", LSCRIPTTypeNames[type]);  		type = *(mRawData + function_offset++); -		S32 params; -		params = 0;  		S32 pcount = 0;  		while (type)  		{ @@ -350,6 +348,7 @@ void LLScriptLSOParse::printStates(LLFILE *fp)  				S32 dummy;  				opcode_end = worst_case_opcode_end; +				(void)opcode_end;  				for (k = LSTT_STATE_BEGIN; k < LSTT_STATE_END; k++)  				{ @@ -357,6 +356,7 @@ void LLScriptLSOParse::printStates(LLFILE *fp)  					{  						temp_end = bytestream2integer(mRawData, read_ahead);  						dummy = bytestream2integer(mRawData, read_ahead); +						(void)dummy;  						if (  (temp_end < opcode_end)  							&&(temp_end > event_offset))  						{ diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 313b310e1e..6fa16825df 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -394,10 +394,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)  		if (group->mSpatialPartition->mRenderByGroup &&  		    !group->isDead())  		{ -			bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow. -				// All particle systems seem to come off the wire with texture entries which claim that they glow.  This is probably a bug in the data.  Suppress. -				group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE && -				group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE; +			static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group"); +			LLFastTimer t(FTM_RENDER_ALPHA_GROUP_LOOP); + +			bool draw_glow_for_this_partition = mVertexShaderLevel > 0; // no shaders = no glow. + +			bool disable_cull = group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_PARTICLE || +				group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; + +			LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0);  			LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; @@ -498,32 +503,31 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)  					}  				} -				params.mVertexBuffer->setBuffer(mask); -				params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); -				gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); +				static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_PUSH("Alpha Push Verts"); +				{ +					LLFastTimer t(FTM_RENDER_ALPHA_PUSH); +					gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); +					params.mVertexBuffer->setBuffer(mask); +					params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); +					gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); +				}  				// If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow).  Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha.  				if (current_shader &&   					draw_glow_for_this_partition &&  					params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE))  				{ +					static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_GLOW("Alpha Glow"); +					LLFastTimer t(FTM_RENDER_ALPHA_GLOW);  					// install glow-accumulating blend mode  					gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color  						      LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow) -					emissive_shader->bind(); -					 -					// glow doesn't use vertex colors from the mesh data -					params.mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE); +					params.mVertexBuffer->setBuffer(mask | LLVertexBuffer::MAP_EMISSIVE);  					// do the actual drawing, again  					params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);  					gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); - -					// restore our alpha blend mode -					gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - -					current_shader->bind();  				}  				if (tex_setup) @@ -536,6 +540,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)  		}  	} +	gGL.setSceneBlendType(LLRender::BT_ALPHA); +  	LLVertexBuffer::unbind();	  	if (!light_enabled) diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 86e5f20812..c3cb914120 100755 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -53,6 +53,12 @@  #include "llviewershadermgr.h"  #include "llvoavatar.h" +#if LL_LINUX +// Work-around spurious used before init warning on Vector4a +// +#pragma GCC diagnostic ignored "-Wuninitialized" +#endif +  extern BOOL gGLDebugLoggingEnabled;  #define LL_MAX_INDICES_COUNT 1000000 @@ -1982,6 +1988,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  			//_mm_prefetch((char*)dst, _MM_HINT_NTA); +  			LLVector4a res0; //,res1,res2,res3;  			LLVector4a texIdx; diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 77a0cdffce..cd4718381b 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -683,30 +683,36 @@ void LLVolumeImplFlexible::doFlexibleUpdate()  								LLVector4(z_axis, 0.f),  								LLVector4(delta_pos, 1.f)); +	LL_CHECK_MEMORY  	for (i=0; i<=num_render_sections; ++i)  	{  		new_point = &path->mPath[i];  		LLVector3 pos = newSection[i].mPosition * rel_xform;  		LLQuaternion rot = mSection[i].mAxisRotation * newSection[i].mRotation * delta_rot; -		 -		if (!mUpdated || (new_point->mPos-pos).magVec()/mVO->mDrawable->mDistanceWRTCamera > 0.001f) +	 +		LLVector3 np(new_point->mPos.getF32ptr()); + +		if (!mUpdated || (np-pos).magVec()/mVO->mDrawable->mDistanceWRTCamera > 0.001f)  		{ -			new_point->mPos = newSection[i].mPosition * rel_xform; +			new_point->mPos.load3((newSection[i].mPosition * rel_xform).mV);  			mUpdated = FALSE;  		} -		new_point->mRot = rot; -		new_point->mScale = newSection[i].mScale; +		new_point->mRot.loadu(LLMatrix3(rot)); +		new_point->mScale.set(newSection[i].mScale.mV[0], newSection[i].mScale.mV[1], 0,1);  		new_point->mTexT = ((F32)i)/(num_render_sections);  	} - +	LL_CHECK_MEMORY  	mLastSegmentRotation = parentSegmentRotation;  } +static LLFastTimer::DeclareTimer FTM_FLEXI_PREBUILD("Flexi Prebuild"); +  void LLVolumeImplFlexible::preRebuild()  {  	if (!mUpdated)  	{ +		LLFastTimer t(FTM_FLEXI_PREBUILD);  		doFlexibleRebuild();  	}  } diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index 5f5258bbce..916f3d8e06 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -983,12 +983,26 @@ LLVector4a *LLPolyMesh::getScaledBinormals()  //-----------------------------------------------------------------------------  void LLPolyMesh::initializeForMorph()  { -    LLVector4a::memcpyNonAliased16((F32*) mCoords, (F32*) mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices); -	LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); -	LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); -	LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); -	LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); -	LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2)); +	// Must insure that src and dst of copies below +	// are actually 16b aligned...the 16b mod 0 size +	// is assumed from the data being LLVector4a +	// +	ll_assert_aligned(mCoords,16); +	ll_assert_aligned(mNormals,16); +	ll_assert_aligned(mScaledNormals,16); +	ll_assert_aligned(mBinormals,16); +	ll_assert_aligned(mScaledBinormals,16); +	ll_assert_aligned(mTexCoords,16); +	ll_assert_aligned(mSharedData->mBaseCoords,16); +	ll_assert_aligned(mSharedData->mBaseNormals,16); +	ll_assert_aligned(mSharedData->mTexCoords,16); + +        ll_memcpy_nonaliased_aligned_16((char*)mCoords, (char*)mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices); +	ll_memcpy_nonaliased_aligned_16((char*)mNormals, (char*)mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); +	ll_memcpy_nonaliased_aligned_16((char*)mScaledNormals, (char*)mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); +	ll_memcpy_nonaliased_aligned_16((char*)mBinormals, (char*)mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); +	ll_memcpy_nonaliased_aligned_16((char*)mScaledBinormals, (char*)mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); +	ll_memcpy_nonaliased_aligned_16((char*)mTexCoords, (char*)mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2));  	for (U32 i = 0; i < mSharedData->mNumVertices; ++i)  	{ diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index dd69172184..1ec56eb5f8 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -4654,7 +4654,9 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,  	mGroup(NULL),  	mFace(NULL),  	mDistance(0.f), -	mDrawMode(LLRender::TRIANGLES) +	mDrawMode(LLRender::TRIANGLES), +	mBlendFuncSrc(LLRender::BF_SOURCE_ALPHA), +	mBlendFuncDst(LLRender::BF_ONE_MINUS_SOURCE_ALPHA)  {  	mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index b1706d9d35..08e77855c4 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -119,6 +119,8 @@ public:  	LL_ALIGN_16(LLFace* mFace); //associated face  	F32 mDistance;  	U32 mDrawMode; +	U32 mBlendFuncSrc; +	U32 mBlendFuncDst;  	struct CompareTexture  	{ @@ -739,7 +741,7 @@ class LLVolumeGeometryManager: public LLGeometryManager  	virtual void rebuildGeom(LLSpatialGroup* group);  	virtual void rebuildMesh(LLSpatialGroup* group);  	virtual void getGeometry(LLSpatialGroup* group); -	void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE); +	void genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE);  	void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);  }; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index b1a60197a2..09cc4a1121 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1553,6 +1553,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  				dp->setPassFlags(value);  				dp->unpackUUID(owner_id, "Owner"); +				mOwnerID = owner_id; +  				if (value & 0x80)  				{  					dp->unpackVector3(new_angv, "Omega"); @@ -1626,13 +1628,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,                  retval |= checkMediaURL(media_url);  				// -				// Unpack particle system data +				// Unpack particle system data (legacy)  				//  				if (value & 0x8)  				{ -					unpackParticleSource(*dp, owner_id); +					unpackParticleSource(*dp, owner_id, true);  				} -				else +				else if (!(value & 0x400))  				{  					deleteParticleSource();  				} @@ -1697,7 +1699,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  				// keep local flags and overwrite remote-controlled flags  				mFlags = (mFlags & FLAGS_LOCAL) | flags; -					// ...new objects that should come in selected need to be added to the selected list +				// ...new objects that should come in selected need to be added to the selected list  				mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);  			}  			break; @@ -4604,7 +4606,7 @@ void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& own  	}  } -void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id) +void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy)  {  	if (!mPartSourcep.isNull() && mPartSourcep->isDead())  	{ @@ -4613,7 +4615,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_  	if (mPartSourcep)  	{  		// If we've got one already, just update the existing source (or remove it) -		if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp)) +		if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp, legacy))  		{  			mPartSourcep->setDead();  			mPartSourcep = NULL; @@ -4621,7 +4623,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_  	}  	else  	{ -		LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp); +		LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp, legacy);  		//If the owner is muted, don't create the system  		if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return;  		// We need to be able to deal with a particle source that hasn't changed, but still got an update! @@ -5467,6 +5469,11 @@ F32 LLAlphaObject::getPartSize(S32 idx)  	return 0.f;  } +void LLAlphaObject::getBlendFunc(S32 face, U32& src, U32& dst) +{ + +} +  // virtual  void LLStaticViewerObject::updateDrawable(BOOL force_damped)  { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 97cf0a4850..cab617b745 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -584,6 +584,7 @@ public:  	} EPhysicsShapeType;  	LLUUID			mID; +	LLUUID			mOwnerID; //null if unknown  	// unique within region, not unique across regions  	// Local ID = 0 is not used @@ -662,7 +663,7 @@ protected:  	BOOL isOnMap();  	void unpackParticleSource(const S32 block_num, const LLUUID& owner_id); -	void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id); +	void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy);  	void deleteParticleSource();  	void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id); @@ -826,9 +827,12 @@ public:  								LLStrider<LLVector4a>& verticesp,  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp, -								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& colorsp, +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp) = 0; +	virtual void getBlendFunc(S32 face, U32& src, U32& dst); +  	F32 mDepth;  }; diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 61cdfd7818..21f1d2619c 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -80,12 +80,31 @@ LLViewerPart::LLViewerPart() :  	mImagep(NULL)  {  	mPartSourcep = NULL; - +	mParent = NULL; +	mChild = NULL;  	++LLViewerPartSim::sParticleCount2 ;  }  LLViewerPart::~LLViewerPart()  { +	if (mPartSourcep.notNull() && mPartSourcep->mLastPart == this) +	{ +		mPartSourcep->mLastPart = NULL; +	} + +	//patch up holes in the ribbon +	if (mParent) +	{ +		llassert(mParent->mChild == this); +		mParent->mChild = mChild; +	} + +	if (mChild) +	{ +		llassert (mChild->mParent == this); +		mChild->mParent = mParent; +	} +  	mPartSourcep = NULL;  	--LLViewerPartSim::sParticleCount2 ; @@ -367,6 +386,9 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)  			part->mScale += frac*part->mEndScale;  		} +		// Do glow interpolation +		part->mGlow.mV[3] = (U8) (lerp(part->mStartGlow, part->mEndGlow, frac)*255.f); +  		// Set the last update time to now.  		part->mLastUpdateTime = cur_time; @@ -623,6 +645,9 @@ void LLViewerPartSim::updateSimulation()  {  	static LLFrameTimer update_timer; +	//reset VBO cursor +	LLVOPartGroup::sVBSlotCursor = 0; +  	const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f);   	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))) diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index c91fcf0691..095de2060c 100644 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -65,15 +65,22 @@ public:  	LLVPCallback		mVPCallback;				// Callback function for more complicated behaviors  	LLPointer<LLViewerPartSource> mPartSourcep;		// Particle source used for this object -	 + +	LLViewerPart*		mParent;					// particle to connect to if this is part of a particle ribbon +	LLViewerPart*		mChild;						// child particle for clean reference destruction  	// Current particle state (possibly used for rendering)  	LLPointer<LLViewerTexture>	mImagep;  	LLVector3		mPosAgent;  	LLVector3		mVelocity;  	LLVector3		mAccel; +	LLVector3		mAxis;  	LLColor4		mColor;  	LLVector2		mScale; +	F32				mStartGlow; +	F32				mEndGlow; +	LLColor4U		mGlow; +  	static U32		sNextPartID;  }; diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp index b311f659fb..8c49ce646d 100644 --- a/indra/newview/llviewerpartsource.cpp +++ b/indra/newview/llviewerpartsource.cpp @@ -52,6 +52,8 @@ LLViewerPartSource::LLViewerPartSource(const U32 type) :  	static U32 id_seed = 0;  	mID = ++id_seed; +	mLastPart = NULL; +  	mDelay = 0 ;  } @@ -279,6 +281,22 @@ void LLViewerPartSourceScript::update(const F32 dt)  			{  				part->mFlags |= LLPartData::LL_PART_HUD;  			} + +			if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK && mLastPart) +			{ //set previous particle's parent to this particle to chain ribbon together +				mLastPart->mParent = part; +				part->mChild = mLastPart; +				part->mAxis = LLVector3(0,0,1); + +				if (mSourceObjectp.notNull()) +				{ +					LLQuaternion rot = mSourceObjectp->getRenderRotation(); +					part->mAxis *= rot; +				} +			} + +			mLastPart = part; +  			part->mMaxAge = mPartSysData.mPartData.mMaxAge;  			part->mStartColor = mPartSysData.mPartData.mStartColor;  			part->mEndColor = mPartSysData.mPartData.mEndColor; @@ -290,6 +308,13 @@ void LLViewerPartSourceScript::update(const F32 dt)  			part->mAccel = mPartSysData.mPartAccel; +			part->mBlendFuncDest = mPartSysData.mPartData.mBlendFuncDest; +			part->mBlendFuncSource = mPartSysData.mPartData.mBlendFuncSource; + +			part->mStartGlow = mPartSysData.mPartData.mStartGlow; +			part->mEndGlow = mPartSysData.mPartData.mEndGlow; +			part->mGlow = LLColor4U(0, 0, 0, (U8) (part->mStartGlow*255.f)); +			  			if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)  			{  				part->mPosAgent = mPosAgent; @@ -430,28 +455,51 @@ LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewer  } -LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp) +LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp, bool legacy)  {  	if (!pssp)  	{  		LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp); -		if (!new_pssp->mPartSysData.unpack(dp)) +		if (legacy)  		{ -			return NULL; +			if (!new_pssp->mPartSysData.unpackLegacy(dp)) +			{ +				return NULL; +			} +		} +		else +		{ +			if (!new_pssp->mPartSysData.unpack(dp)) +			{ +				return NULL; +			}  		} +		  		if (new_pssp->mPartSysData.mTargetUUID.notNull())  		{  			LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);  			new_pssp->setTargetObject(target_objp);  		} +		  		return new_pssp;  	}  	else  	{ -		if (!pssp->mPartSysData.unpack(dp)) +		if (legacy)  		{ -			return NULL; +			if (!pssp->mPartSysData.unpackLegacy(dp)) +			{ +				return NULL; +			}  		} +		else +		{ +			if (!pssp->mPartSysData.unpack(dp)) +			{ +				return NULL; +			} +		} +  		if (pssp->mPartSysData.mTargetUUID.notNull())  		{  			LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID); @@ -569,6 +617,11 @@ void LLViewerPartSourceSpiral::update(const F32 dt)  		part->mScale.mV[0] = 0.25f;  		part->mScale.mV[1] = 0.25f;  		part->mParameter = ll_frand(F_TWO_PI); +		part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; +		part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; +		part->mStartGlow = 0.f; +		part->mEndGlow = 0.f; +		part->mGlow = LLColor4U(0, 0, 0, 0);  		LLViewerPartSim::getInstance()->addPart(part);  	} @@ -721,6 +774,12 @@ void LLViewerPartSourceBeam::update(const F32 dt)  		part->mPosAgent = mPosAgent;  		part->mVelocity = mTargetPosAgent - mPosAgent; +		part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; +		part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; +		part->mStartGlow = 0.f; +		part->mEndGlow = 0.f; +		part->mGlow = LLColor4U(0, 0, 0, 0); +  		LLViewerPartSim::getInstance()->addPart(part);  	}  } @@ -825,6 +884,12 @@ void LLViewerPartSourceChat::update(const F32 dt)  		part->mScale.mV[0] = 0.25f;  		part->mScale.mV[1] = 0.25f;  		part->mParameter = ll_frand(F_TWO_PI); +		part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; +		part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; +		part->mStartGlow = 0.f; +		part->mEndGlow = 0.f; +		part->mGlow = LLColor4U(0, 0, 0, 0); +  		LLViewerPartSim::getInstance()->addPart(part);  	} diff --git a/indra/newview/llviewerpartsource.h b/indra/newview/llviewerpartsource.h index 28702d36a2..12e926173b 100644 --- a/indra/newview/llviewerpartsource.h +++ b/indra/newview/llviewerpartsource.h @@ -76,6 +76,7 @@ public:  	LLVector3	mLastUpdatePosAgent;  	LLPointer<LLViewerObject>	mSourceObjectp;  	U32 mID; +	LLViewerPart* mLastPart; //last particle emitted (for making particle ribbons)  protected:  	U32			mType; @@ -85,7 +86,6 @@ protected:  	F32			mLastPartTime;  	LLUUID		mOwnerUUID;  	LLPointer<LLViewerTexture>	mImagep; -  	// Particle information  	U32			mPartFlags; // Flags for the particle  	U32         mDelay ; //delay to start particles @@ -114,7 +114,7 @@ public:  	// Returns a new particle source to attach to an object...  	static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, const S32 block_num); -	static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp); +	static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp, bool legacy);  	static LLPointer<LLViewerPartSourceScript> createPSS(LLViewerObject *source_objp, const LLPartSysData& particle_parameters);  	LLViewerTexture *getImage() const				{ return mImagep; } diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 4dca87652d..ed62abe4ef 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -476,6 +476,7 @@ void LLVOGrass::getGeometry(S32 idx,  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp)  {  	if(!mNumBlades)//stop rendering grass @@ -708,7 +709,11 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group)  		facep->setIndicesIndex(index_count);  		facep->setVertexBuffer(buffer);  		facep->setPoolType(LLDrawPool::POOL_ALPHA); -		object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + +		//dummy parameter (unused by this implementation) +		LLStrider<LLColor4U> emissivep; + +		object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, emissivep, indicesp);  		vertex_count += facep->getGeomCount();  		index_count += facep->getIndicesCount(); diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h index b9835b8802..1fe9990cea 100644 --- a/indra/newview/llvograss.h +++ b/indra/newview/llvograss.h @@ -63,6 +63,7 @@ public:  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp);  	void updateFaceSize(S32 idx) { } diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 1a9769f09d..53d67347d1 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -49,17 +49,11 @@ const F32 MAX_PART_LIFETIME = 120.f;  extern U64 gFrameTime;  LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL; -S32 LLVOPartGroup::sVBSlotFree[]; -S32* LLVOPartGroup::sVBSlotCursor = NULL; +S32 LLVOPartGroup::sVBSlotCursor = 0;  void LLVOPartGroup::initClass()  { -	for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) -	{ -		sVBSlotFree[i] = i; -	} - -	sVBSlotCursor = sVBSlotFree; +	  }  //static @@ -122,36 +116,33 @@ void LLVOPartGroup::destroyGL()  //static  S32 LLVOPartGroup::findAvailableVBSlot()  { -	if (sVBSlotCursor >= sVBSlotFree+LL_MAX_PARTICLE_COUNT) +	if (sVBSlotCursor >= LL_MAX_PARTICLE_COUNT)  	{ //no more available slots  		return -1;  	} -	S32 ret = *sVBSlotCursor; -	sVBSlotCursor++; - -	return ret; +	return sVBSlotCursor++;  }  bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)  { -	while (start < end) +	/*while (start < end)  	{  		if (*start == idx)  		{ //not allocated (in free list)  			return false;  		}  		++start; -	} +	}*/  	//allocated (not in free list) -	return true; +	return false;  }  //static  void LLVOPartGroup::freeVBSlot(S32 idx)  { -	llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); +	/*llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0);  	llassert(sVBSlotCursor > sVBSlotFree);  	llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); @@ -159,7 +150,7 @@ void LLVOPartGroup::freeVBSlot(S32 idx)  	{  		sVBSlotCursor--;  		*sVBSlotCursor = idx; -	} +	}*/  }  LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) @@ -189,6 +180,7 @@ F32 LLVOPartGroup::getBinRadius()  void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)  {		  	const LLVector3& pos_agent = getPositionAgent(); +  	newMin.load3( (pos_agent - mScale).mV);  	newMax.load3( (pos_agent + mScale).mV);  	LLVector4a pos; @@ -273,6 +265,16 @@ F32 LLVOPartGroup::getPartSize(S32 idx)  	return 0.f;  } +void LLVOPartGroup::getBlendFunc(S32 idx, U32& src, U32& dst) +{ +	if (idx < (S32) mViewerPartGroupp->mParticles.size()) +	{ +		LLViewerPart* part = mViewerPartGroupp->mParticles[idx]; +		src = part->mBlendFuncSource; +		dst = part->mBlendFuncDest; +	} +} +  LLVector3 LLVOPartGroup::getCameraPosition() const  {  	return gAgentCamera.getCameraPositionAgent(); @@ -332,13 +334,42 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)  	mDepth = 0.f;  	S32 i = 0 ;  	LLVector3 camera_agent = getCameraPosition(); +	 +	F32 max_scale = 0.f; + +  	for (i = 0 ; i < (S32)mViewerPartGroupp->mParticles.size(); i++)  	{  		const LLViewerPart *part = mViewerPartGroupp->mParticles[i]; + +		//remember the largest particle +		max_scale = llmax(max_scale, part->mScale.mV[0], part->mScale.mV[1]); + +		if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK) +		{ //include ribbon segment length in scale +			const LLVector3* pos_agent = NULL; +			if (part->mParent) +			{ +				pos_agent = &(part->mParent->mPosAgent); +			} +			else if (part->mPartSourcep.notNull()) +			{ +				pos_agent = &(part->mPartSourcep->mPosAgent); +			} + +			if (pos_agent) +			{ +				F32 dist = (*pos_agent-part->mPosAgent).length(); + +				max_scale = llmax(max_scale, dist); +			} +		} +  		LLVector3 part_pos_agent(part->mPosAgent);  		LLVector3 at(part_pos_agent - camera_agent); +		  		F32 camera_dist_squared = at.lengthSquared();  		F32 inv_camera_dist_squared;  		if (camera_dist_squared > 1.f) @@ -411,6 +442,9 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)  		facep->setSize(0, 0);  	} +	//record max scale (used to stretch bounding box for visibility culling) +	mScale.set(max_scale, max_scale, max_scale); +  	mDrawable->movePartition();  	LLPipeline::sCompiles++;  	return TRUE; @@ -478,74 +512,129 @@ BOOL LLVOPartGroup::lineSegmentIntersect(const LLVector3& start, const LLVector3  void LLVOPartGroup::getGeometry(const LLViewerPart& part,  								LLStrider<LLVector4a>& verticesp)  { -	LLVector4a part_pos_agent; -	part_pos_agent.load3(part.mPosAgent.mV); -	LLVector4a camera_agent; -	camera_agent.load3(getCameraPosition().mV);  -	LLVector4a at; -	at.setSub(part_pos_agent, camera_agent); -	LLVector4a up(0, 0, 1); -	LLVector4a right; - -	right.setCross3(at, up); -	right.normalize3fast(); -	up.setCross3(right, at); -	up.normalize3fast(); - -	if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK) +	if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK)  	{ -		LLVector4a normvel; -		normvel.load3(part.mVelocity.mV); -		normvel.normalize3fast(); -		LLVector2 up_fracs; -		up_fracs.mV[0] = normvel.dot3(right).getF32(); -		up_fracs.mV[1] = normvel.dot3(up).getF32(); -		up_fracs.normalize(); -		LLVector4a new_up; -		LLVector4a new_right; - -		//new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up; -		LLVector4a t = right; -		t.mul(up_fracs.mV[0]); -		new_up = up; -		new_up.mul(up_fracs.mV[1]); -		new_up.add(t); - -		//new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up; -		t = right; -		t.mul(up_fracs.mV[1]); -		new_right = up; -		new_right.mul(up_fracs.mV[0]); -		t.sub(new_right); - -		up = new_up; -		right = t; -		up.normalize3fast(); -		right.normalize3fast(); +		LLVector4a axis, pos, paxis, ppos; +		F32 scale, pscale; + +		pos.load3(part.mPosAgent.mV); +		axis.load3(part.mAxis.mV); +		scale = part.mScale.mV[0]; +		 +		if (part.mParent) +		{ +			ppos.load3(part.mParent->mPosAgent.mV); +			paxis.load3(part.mParent->mAxis.mV); +			pscale = part.mParent->mScale.mV[0]; +		} +		else +		{ //use source object as position +			 +			if (part.mPartSourcep->mSourceObjectp.notNull()) +			{ +				LLVector3 v = LLVector3(0,0,1); +				v *= part.mPartSourcep->mSourceObjectp->getRenderRotation(); +				paxis.load3(v.mV); +				ppos.load3(part.mPartSourcep->mPosAgent.mV); +				pscale = part.mStartScale.mV[0]; +			} +			else +			{ //no source object, no parent, nothing to draw +				ppos = pos; +				pscale = scale; +				paxis = axis; +			} +		} + +		LLVector4a p0, p1, p2, p3; + +		scale *= 0.5f; +		pscale *= 0.5f; + +		axis.mul(scale); +		paxis.mul(pscale); + +		p0.setAdd(pos, axis); +		p1.setSub(pos,axis); +		p2.setAdd(ppos, paxis); +		p3.setSub(ppos, paxis); + +		(*verticesp++) = p2; +		(*verticesp++) = p3; +		(*verticesp++) = p0; +		(*verticesp++) = p1;  	} +	else +	{ +		LLVector4a part_pos_agent; +		part_pos_agent.load3(part.mPosAgent.mV); +		LLVector4a camera_agent; +		camera_agent.load3(getCameraPosition().mV);  +		LLVector4a at; +		at.setSub(part_pos_agent, camera_agent); +		LLVector4a up(0, 0, 1); +		LLVector4a right; + +		right.setCross3(at, up); +		right.normalize3fast(); +		up.setCross3(right, at); +		up.normalize3fast(); -	right.mul(0.5f*part.mScale.mV[0]); -	up.mul(0.5f*part.mScale.mV[1]); +		if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK) +		{ +			LLVector4a normvel; +			normvel.load3(part.mVelocity.mV); +			normvel.normalize3fast(); +			LLVector2 up_fracs; +			up_fracs.mV[0] = normvel.dot3(right).getF32(); +			up_fracs.mV[1] = normvel.dot3(up).getF32(); +			up_fracs.normalize(); +			LLVector4a new_up; +			LLVector4a new_right; + +			//new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up; +			LLVector4a t = right; +			t.mul(up_fracs.mV[0]); +			new_up = up; +			new_up.mul(up_fracs.mV[1]); +			new_up.add(t); + +			//new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up; +			t = right; +			t.mul(up_fracs.mV[1]); +			new_right = up; +			new_right.mul(up_fracs.mV[0]); +			t.sub(new_right); + +			up = new_up; +			right = t; +			up.normalize3fast(); +			right.normalize3fast(); +		} +		right.mul(0.5f*part.mScale.mV[0]); +		up.mul(0.5f*part.mScale.mV[1]); -	//HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) -	// this works because there is actually a 4th float stored after the vertex position which is used as a texture index -	// also, somebody please VECTORIZE THIS -	LLVector4a ppapu; -	LLVector4a ppamu; +		//HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) +		// this works because there is actually a 4th float stored after the vertex position which is used as a texture index +		// also, somebody please VECTORIZE THIS -	ppapu.setAdd(part_pos_agent, up); -	ppamu.setSub(part_pos_agent, up); +		LLVector4a ppapu; +		LLVector4a ppamu; -	verticesp->setSub(ppapu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; -	verticesp->setSub(ppamu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; -	verticesp->setAdd(ppapu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; -	verticesp->setAdd(ppamu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; +		ppapu.setAdd(part_pos_agent, up); +		ppamu.setSub(part_pos_agent, up); + +		verticesp->setSub(ppapu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +		verticesp->setSub(ppamu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +		verticesp->setAdd(ppapu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +		verticesp->setAdd(ppamu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +	}  } @@ -555,6 +644,7 @@ void LLVOPartGroup::getGeometry(S32 idx,  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp)  {  	if (idx >= (S32) mViewerPartGroupp->mParticles.size()) @@ -566,10 +656,40 @@ void LLVOPartGroup::getGeometry(S32 idx,  	getGeometry(part, verticesp); -	*colorsp++ = part.mColor; -	*colorsp++ = part.mColor; -	*colorsp++ = part.mColor; -	*colorsp++ = part.mColor; +	LLColor4U pcolor; +	LLColor4U color = part.mColor; + +	LLColor4U pglow; + +	if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK) +	{ //make sure color blends properly +		if (part.mParent) +		{ +			pglow = part.mParent->mGlow; +			pcolor = part.mParent->mColor; +		} +		else  +		{ +			pglow = LLColor4U(0, 0, 0, (U8) (255.f*part.mStartGlow)); +			pcolor = part.mStartColor; +		} +	} +	else +	{ +		pglow = part.mGlow; +		pcolor = color; +	} + +	*colorsp++ = pcolor; +	*colorsp++ = pcolor; +	*colorsp++ = color; +	*colorsp++ = color; + +	*emissivep++ = pglow; +	*emissivep++ = pglow; +	*emissivep++ = part.mGlow; +	*emissivep++ = part.mGlow; +  	if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK))  	{ //not fullbright, needs normal @@ -712,10 +832,13 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  	LLStrider<LLVector3> normalsp;  	LLStrider<LLVector2> texcoordsp;  	LLStrider<LLColor4U> colorsp; +	LLStrider<LLColor4U> emissivep;  	buffer->getVertexStrider(verticesp);  	buffer->getNormalStrider(normalsp);  	buffer->getColorStrider(colorsp); +	buffer->getEmissiveStrider(emissivep); +  	LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];	 @@ -724,7 +847,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		LLFace* facep = *i;  		LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); -		if (!facep->isState(LLFace::PARTICLE)) +		//if (!facep->isState(LLFace::PARTICLE))  		{ //set the indices of this face  			S32 idx = LLVOPartGroup::findAvailableVBSlot();  			if (idx >= 0) @@ -733,7 +856,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  				facep->setIndicesIndex(idx*6);  				facep->setVertexBuffer(LLVOPartGroup::sVB);  				facep->setPoolType(LLDrawPool::POOL_ALPHA); -				facep->setState(LLFace::PARTICLE); +				//facep->setState(LLFace::PARTICLE);  			}  			else  			{ @@ -748,8 +871,9 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		LLStrider<LLVector3> cur_norm = normalsp + geom_idx;  		LLStrider<LLVector2> cur_tc = texcoordsp + geom_idx;  		LLStrider<LLColor4U> cur_col = colorsp + geom_idx; +		LLStrider<LLColor4U> cur_glow = emissivep + geom_idx; -		object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_idx); +		object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_glow, cur_idx);  		llassert(facep->getGeomCount() == 4);  		llassert(facep->getIndicesCount() == 6); @@ -765,9 +889,16 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		bool batched = false; +		U32 bf_src = LLRender::BF_SOURCE_ALPHA; +		U32 bf_dst = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; + +		object->getBlendFunc(facep->getTEOffset(), bf_src, bf_dst); +  		if (idx >= 0 &&  			draw_vec[idx]->mTexture == facep->getTexture() && -			draw_vec[idx]->mFullbright == fullbright) +			draw_vec[idx]->mFullbright == fullbright && +			draw_vec[idx]->mBlendFuncDst == bf_dst && +			draw_vec[idx]->mBlendFuncSrc == bf_src)  		{  			if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1)  			{ @@ -799,6 +930,8 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  			info->mExtents[0] = group->mObjectExtents[0];  			info->mExtents[1] = group->mObjectExtents[1];  			info->mVSize = vsize; +			info->mBlendFuncDst = bf_dst; +			info->mBlendFuncSrc = bf_src;  			draw_vec.push_back(info);  			//for alpha sorting  			facep->setDrawInfo(info); diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index ce05a0282e..3c2e0344a2 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -42,8 +42,7 @@ public:  	//vertex buffer for holding all particles  	static LLPointer<LLVertexBuffer> sVB; -	static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; -	static S32* sVBSlotCursor; +	static S32 sVBSlotCursor;  	static void initClass();  	static void restoreGL(); @@ -57,6 +56,7 @@ public:  							LLVertexBuffer::MAP_NORMAL |  							LLVertexBuffer::MAP_TEXCOORD0 |  							LLVertexBuffer::MAP_COLOR | +							LLVertexBuffer::MAP_EMISSIVE |  							LLVertexBuffer::MAP_TEXTURE_INDEX  	}; @@ -91,10 +91,12 @@ public:  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp);  	void updateFaceSize(S32 idx) { }  	F32 getPartSize(S32 idx); +	void getBlendFunc(S32 idx, U32& src, U32& dst);  	LLUUID getPartOwner(S32 idx);  	LLUUID getPartSource(S32 idx); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 7adf18b6d0..e0ed13a3a7 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -384,7 +384,6 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  	}  	else  	{ -		// CORY TO DO: Figure out how to get the value here  		if (update_type != OUT_TERSE_IMPROVED)  		{  			LLVolumeParams volume_params; @@ -453,6 +452,11 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  				mFaceMappingChanged = TRUE;  				mTexAnimMode = 0;  			} + +			if (value & 0x400) +			{ //particle system (new) +				unpackParticleSource(*dp, mOwnerID, false); +			}  		}  		else  		{ @@ -1051,8 +1055,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo  				}  			}  		} - - +		  		static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback");  		bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject && @@ -1268,7 +1271,7 @@ BOOL LLVOVolume::calcLOD()  	else  	{  		distance = mDrawable->mDistanceWRTCamera; -		radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length(); +		radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length();  	}  	//hold onto unmodified distance for debugging @@ -1298,7 +1301,7 @@ BOOL LLVOVolume::calcLOD()  	{  		//setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail)); -		setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex())); +		//setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex()));  	}  	if (cur_detail != mLOD) @@ -2990,7 +2993,7 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p  		//transform view vector into volume space  		view_vector -= getRenderPosition(); -		mDrawable->mDistanceWRTCamera = view_vector.length(); +		//mDrawable->mDistanceWRTCamera = view_vector.length();  		LLQuaternion worldRot = getRenderRotation();  		view_vector = view_vector * ~worldRot;  		if (!isVolumeGlobal()) @@ -4242,11 +4245,20 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	mFaceList.clear(); -	std::vector<LLFace*> fullbright_faces; -	std::vector<LLFace*> bump_faces; -	std::vector<LLFace*> simple_faces; +	const U32 MAX_FACE_COUNT = 4096; +	 +	static LLFace** fullbright_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); +	static LLFace** bump_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); +	static LLFace** simple_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); +	static LLFace** alpha_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); +	 +	U32 fullbright_count = 0; +	U32 bump_count = 0; +	U32 simple_count = 0; +	U32 alpha_count = 0; + -	std::vector<LLFace*> alpha_faces; +	  	U32 useage = group->mSpatialPartition->mBufferUsage;  	U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); @@ -4257,6 +4269,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	bool emissive = false; +	 +  	{  		LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST); @@ -4558,7 +4572,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  					{  						if (facep->canRenderAsMask())  						{ //can be treated as alpha mask -							simple_faces.push_back(facep); +							if (simple_count < MAX_FACE_COUNT) +							{ +								simple_faces[simple_count++] = facep; +							}  						}  						else  						{ @@ -4566,7 +4583,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  							{ //only treat as alpha in the pipeline if < 100% transparent  								drawablep->setState(LLDrawable::HAS_ALPHA);  							} -							alpha_faces.push_back(facep); +							if (alpha_count < MAX_FACE_COUNT) +							{ +								alpha_faces[alpha_count++] = facep; +							}  						}  					}  					else @@ -4581,33 +4601,51 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  						{  							if (te->getBumpmap())  							{ //needs normal + binormal -								bump_faces.push_back(facep); +								if (bump_count < MAX_FACE_COUNT) +								{ +									bump_faces[bump_count++] = facep; +								}  							}  							else if (te->getShiny() || !te->getFullbright())  							{ //needs normal -								simple_faces.push_back(facep); +								if (simple_count < MAX_FACE_COUNT) +								{ +									simple_faces[simple_count++] = facep; +								}  							}  							else   							{ //doesn't need normal  								facep->setState(LLFace::FULLBRIGHT); -								fullbright_faces.push_back(facep); +								if (fullbright_count < MAX_FACE_COUNT) +								{ +									fullbright_faces[fullbright_count++] = facep; +								}  							}  						}  						else  						{  							if (te->getBumpmap() && LLPipeline::sRenderBump)  							{ //needs normal + binormal -								bump_faces.push_back(facep); +								if (bump_count < MAX_FACE_COUNT) +								{ +									bump_faces[bump_count++] = facep; +								}  							}  							else if ((te->getShiny() && LLPipeline::sRenderBump) ||  								!(te->getFullbright() || bake_sunlight))  							{ //needs normal -								simple_faces.push_back(facep); +								if (simple_count < MAX_FACE_COUNT) +								{ +									simple_faces[simple_count++] = facep; +								}  							}  							else   							{ //doesn't need normal  								facep->setState(LLFace::FULLBRIGHT); -								fullbright_faces.push_back(facep); +								if (fullbright_count < MAX_FACE_COUNT) +								{ +									fullbright_faces[fullbright_count++] = facep; +								}  							}  						}  					} @@ -4657,17 +4695,17 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	if (batch_textures)  	{  		bump_mask |= LLVertexBuffer::MAP_BINORMAL; -		genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, FALSE, TRUE); -		genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, FALSE, TRUE); -		genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, FALSE, FALSE); -		genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, TRUE, TRUE); +		genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, simple_count, FALSE, TRUE); +		genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, fullbright_count, FALSE, TRUE); +		genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, bump_count, FALSE, FALSE); +		genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, alpha_count, TRUE, TRUE);  	}  	else  	{ -		genDrawInfo(group, simple_mask, simple_faces); -		genDrawInfo(group, fullbright_mask, fullbright_faces); -		genDrawInfo(group, bump_mask, bump_faces, FALSE, TRUE); -		genDrawInfo(group, alpha_mask, alpha_faces, TRUE); +		genDrawInfo(group, simple_mask, simple_faces, simple_count); +		genDrawInfo(group, fullbright_mask, fullbright_faces, fullbright_count); +		genDrawInfo(group, bump_mask, bump_faces, bump_count,  FALSE, FALSE); +		genDrawInfo(group, alpha_mask, alpha_faces, alpha_count, TRUE);  	} @@ -4699,6 +4737,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	}  } +static LLFastTimer::DeclareTimer FTM_REBUILD_MESH_FLUSH("Flush Mesh");  void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  { @@ -4708,11 +4747,14 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  		LLFastTimer ftm(FTM_REBUILD_VOLUME_VB);  		LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers -		S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; -  		group->mBuilt = 1.f; -		std::set<LLVertexBuffer*> mapped_buffers; +		S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ; + +		const U32 MAX_BUFFER_COUNT = 4096; +		LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT]; + +		U32 buffer_count = 0;  		for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)  		{ @@ -4722,7 +4764,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  			{  				LLVOVolume* vobj = drawablep->getVOVolume();  				vobj->preRebuild(); - +				  				if (drawablep->isState(LLDrawable::ANIMATED_CHILD))  				{  					vobj->updateRelativeXform(true); @@ -4747,9 +4789,9 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  							} -							if (buff->isLocked()) +							if (buff->isLocked() && buffer_count < MAX_BUFFER_COUNT)  							{ -								mapped_buffers.insert(buff); +								locked_buffer[buffer_count++] = buff;  							}  						}  					} @@ -4765,21 +4807,24 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  			}  		} -		for (std::set<LLVertexBuffer*>::iterator iter = mapped_buffers.begin(); iter != mapped_buffers.end(); ++iter) -		{ -			(*iter)->flush(); -		} - -		// don't forget alpha -		if(group != NULL &&  -		   !group->mVertexBuffer.isNull() &&  -		   group->mVertexBuffer->isLocked())  		{ -			group->mVertexBuffer->flush(); +			LLFastTimer t(FTM_REBUILD_MESH_FLUSH); +			for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter) +			{ +				(*iter)->flush(); +			} +		 +			// don't forget alpha +			if(group != NULL &&  +			   !group->mVertexBuffer.isNull() &&  +			   group->mVertexBuffer->isLocked()) +			{ +				group->mVertexBuffer->flush(); +			}  		}  		//if not all buffers are unmapped -		if(num_mapped_veretx_buffer != LLVertexBuffer::sMappedCount)  +		if(num_mapped_vertex_buffer != LLVertexBuffer::sMappedCount)   		{  			llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ;   			for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) @@ -4839,7 +4884,7 @@ static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); -void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort, BOOL batch_textures) +void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures)  {  	LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); @@ -4875,17 +4920,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  		if (!distance_sort)  		{  			//sort faces by things that break batches -			std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified()); +			std::sort(faces, faces+face_count, CompareBatchBreakerModified());  		}  		else  		{  			//sort faces by distance -			std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); +			std::sort(faces, faces+face_count, LLFace::CompareDistanceGreater());  		}  	}  	bool hud_group = group->isHUDGroup() ; -	std::vector<LLFace*>::iterator face_iter = faces.begin(); +	LLFace** face_iter = faces; +	LLFace** end_faces = faces+face_count;  	LLSpatialGroup::buffer_map_t buffer_map; @@ -4916,7 +4962,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  	bool flexi = false; -	while (face_iter != faces.end()) +	while (face_iter != end_faces)  	{  		//pull off next face  		LLFace* facep = *face_iter; @@ -4945,10 +4991,13 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  		flexi = flexi || facep->getViewerObject()->getVolume()->isUnique();  		//sum up vertices needed for this render batch -		std::vector<LLFace*>::iterator i = face_iter; +		LLFace** i = face_iter;  		++i; -		std::vector<LLViewerTexture*> texture_list; +		const U32 MAX_TEXTURE_COUNT = 32; +		LLViewerTexture* texture_list[MAX_TEXTURE_COUNT]; +		 +		U32 texture_count = 0;  		{  			LLFastTimer t(FTM_GEN_DRAW_INFO_FACE_SIZE); @@ -4956,12 +5005,15 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  			{  				U8 cur_tex = 0;  				facep->setTextureIndex(cur_tex); -				texture_list.push_back(tex); - +				if (texture_count < MAX_TEXTURE_COUNT) +				{ +					texture_list[texture_count++] = tex; +				} +				  				if (can_batch_texture(facep))  				{ //populate texture_list with any textures that can be batched  				  //move i to the next unbatchable face -					while (i != faces.end()) +					while (i != end_faces)  					{  						facep = *i; @@ -4976,7 +5028,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  							if (distance_sort)  							{ //textures might be out of order, see if texture exists in current batch  								bool found = false; -								for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx) +								for (U32 tex_idx = 0; tex_idx < texture_count; ++tex_idx)  								{  									if (facep->getTexture() == texture_list[tex_idx])  									{ @@ -4988,7 +5040,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  								if (!found)  								{ -									cur_tex = texture_list.size(); +									cur_tex = texture_count;  								}  							}  							else @@ -5003,7 +5055,10 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  							tex = facep->getTexture(); -							texture_list.push_back(tex); +							if (texture_count < MAX_TEXTURE_COUNT) +							{ +								texture_list[texture_count++] = tex; +							}  						}  						if (geom_count + facep->getGeomCount() > max_vertices) @@ -5026,7 +5081,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  			}  			else  			{ -				while (i != faces.end() &&  +				while (i != end_faces &&   					(LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex)))  				{  					facep = *i; diff --git a/indra/newview/llwlanimator.h b/indra/newview/llwlanimator.h index 5223b45343..810f4cf7e5 100644 --- a/indra/newview/llwlanimator.h +++ b/indra/newview/llwlanimator.h @@ -137,3 +137,4 @@ private:  };  #endif // LL_WL_ANIMATOR_H + diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h index 72422500fc..e13aed98ed 100644 --- a/indra/newview/llwlparammanager.h +++ b/indra/newview/llwlparammanager.h @@ -412,3 +412,4 @@ inline LLVector4 LLWLParamManager::getRotatedLightDir(void) const  }  #endif + diff --git a/indra/newview/llwlparamset.cpp b/indra/newview/llwlparamset.cpp index 745cdae441..b307f19e8a 100644 --- a/indra/newview/llwlparamset.cpp +++ b/indra/newview/llwlparamset.cpp @@ -406,4 +406,5 @@ void LLWLParamSet::updateHashedNames()  	{  		mParamHashedNames.push_back(LLStaticHashedString(iter->first));  	} -}
\ No newline at end of file +} + diff --git a/indra/newview/llwlparamset.h b/indra/newview/llwlparamset.h index 3e9f77ba6c..6e5f1d3a4b 100644 --- a/indra/newview/llwlparamset.h +++ b/indra/newview/llwlparamset.h @@ -243,3 +243,4 @@ inline F32 LLWLParamSet::getCloudScrollY() {  #endif // LL_WLPARAM_SET_H + diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 54a62a858a..e9cd74406d 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7261,7 +7261,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)  				else  				{  					//focus on alt-zoom target -					focus_point = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal()); +					LLViewerRegion* region = gAgent.getRegion(); +					if (region) +					{ +						focus_point = LLVector3(gAgentCamera.getFocusGlobal()-region->getOriginGlobal()); +					}  				}  			} diff --git a/indra/test/io.cpp b/indra/test/io.cpp index ce747f667d..7f26ac6724 100644 --- a/indra/test/io.cpp +++ b/indra/test/io.cpp @@ -1141,6 +1141,7 @@ namespace tut  		ensure("Connected to server", connected);  		lldebugs << "connected" << llendl;  		F32 elapsed = pump_loop(mPump,0.1f); +		(void)elapsed;  		count = mPump->runningChains();  		ensure_equals("server chain onboard", count, 2);  		lldebugs << "** Client is connected." << llendl; diff --git a/indra/test/llstreamtools_tut.cpp b/indra/test/llstreamtools_tut.cpp index a93f2e8f65..68e56b5ee2 100644 --- a/indra/test/llstreamtools_tut.cpp +++ b/indra/test/llstreamtools_tut.cpp @@ -386,15 +386,17 @@ namespace tut  		std::string actual_result;  		std::istringstream is;  		bool ret; -  		is.clear();  		is.str(str = "  First Second \t \r  \n Third  Fourth-ShouldThisBePartOfFourth  Fifth\n");  		actual_result = "";  		ret = get_word(actual_result, is); // First +		(void)ret;  		actual_result = "";  		ret = get_word(actual_result, is); // Second +		(void)ret;  		actual_result = "";  		ret = get_word(actual_result, is); // Third +		(void)ret;  		// the current implementation of get_word seems inconsistent with  		// skip_to_next_word. skip_to_next_word treats any character other @@ -486,6 +488,7 @@ namespace tut  		is.str(str = "First Second \t \r\n Third  Fourth-ShouldThisBePartOfFourth  IsThisFifth\n");  		actual_result = "";  		ret = get_line(actual_result, is); +		(void)ret;  		expected_result = "First Second \t \r\n";  		ensure_equals("get_line: 1", actual_result, expected_result); @@ -551,6 +554,7 @@ namespace tut  		is.str(str = "Should not skip lone \r.\r\n");  		actual_result = "";  		ret = get_line(actual_result, is); +		(void)ret;  		expected_result = "Should not skip lone \r.\r\n";  		ensure_equals("get_line: carriage return skipped even though not followed by newline", actual_result, expected_result);  	} @@ -569,6 +573,7 @@ namespace tut  		is.str(str = "\n");  		actual_result = "";  		ret = get_line(actual_result, is); +		(void)ret;  		expected_result = "\n";  		ensure_equals("get_line: Just newline", actual_result, expected_result);  	} @@ -588,6 +593,7 @@ namespace tut  		is.str(str = "First Line.\nSecond Line.\n");  		actual_result = "";  		ret = get_line(actual_result, is, 255); +		(void)ret;  		expected_result = "First Line.\n";  		ensure_equals("get_line: Basic Operation", actual_result, expected_result); diff --git a/indra/test/lltemplatemessagebuilder_tut.cpp b/indra/test/lltemplatemessagebuilder_tut.cpp index 6e1c82bb24..0aad3cbc15 100644 --- a/indra/test/lltemplatemessagebuilder_tut.cpp +++ b/indra/test/lltemplatemessagebuilder_tut.cpp @@ -958,11 +958,13 @@ namespace tut  		reader->validateMessage(buffer, builtSize, LLHost());  		reader->readMessage(buffer, LLHost());  		reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue); +		(void)outValue;  		char outBuffer[bufferSize];  		memset(buffer, 0xcc, bufferSize);  		reader->getString(_PREHASH_Test1, _PREHASH_Test0, bufferSize,   						  outBuffer);  		outValue2 = reader->getNumberOfBlocks(_PREHASH_Test1); +		(void)outValue2;  		ensure_equals("Ensure present value ", outValue, inValue);  		ensure_equals("Ensure unchanged buffer ", strlen(outBuffer), 0);  		delete reader; | 
