summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autobuild.xml4
-rw-r--r--indra/cmake/00-Common.cmake13
-rw-r--r--indra/cmake/Copy3rdPartyLibs.cmake1
-rw-r--r--indra/cmake/FreeType.cmake8
-rw-r--r--indra/linux_crash_logger/CMakeLists.txt2
-rw-r--r--indra/llcommon/CMakeLists.txt1
-rw-r--r--indra/llcommon/llalignedarray.h139
-rw-r--r--indra/llcommon/llmemory.h116
-rw-r--r--indra/llmath/llmatrix4a.h11
-rw-r--r--indra/llmath/llsimdmath.h28
-rw-r--r--indra/llmath/llvector4a.cpp50
-rw-r--r--indra/llmath/llvector4a.inl13
-rw-r--r--indra/llmath/llvolume.cpp1514
-rw-r--r--indra/llmath/llvolume.h60
-rw-r--r--indra/llmessage/lliosocket.cpp1
-rw-r--r--indra/llmessage/llpartdata.cpp282
-rw-r--r--indra/llmessage/llpartdata.h61
-rw-r--r--indra/llmessage/tests/llpartdata_test.cpp256
-rw-r--r--indra/llrender/llvertexbuffer.cpp11
-rw-r--r--indra/llui/llconsole.cpp2
-rw-r--r--indra/llui/llkeywords.cpp2
-rw-r--r--indra/llui/lllayoutstack.cpp3
-rw-r--r--indra/llui/lltextbase.cpp3
-rw-r--r--indra/llui/lltexteditor.cpp1
-rw-r--r--indra/llui/lltoolbar.cpp4
-rw-r--r--indra/lscript/lscript_compile/indra.l14
-rw-r--r--indra/lscript/lscript_execute/lscript_readlso.cpp6
-rw-r--r--indra/newview/lldrawpoolalpha.cpp38
-rwxr-xr-xindra/newview/llface.cpp7
-rw-r--r--indra/newview/llflexibleobject.cpp18
-rw-r--r--indra/newview/llpolymesh.cpp26
-rw-r--r--indra/newview/llspatialpartition.cpp4
-rw-r--r--indra/newview/llspatialpartition.h4
-rw-r--r--indra/newview/llviewerobject.cpp21
-rw-r--r--indra/newview/llviewerobject.h8
-rw-r--r--indra/newview/llviewerpartsim.cpp27
-rw-r--r--indra/newview/llviewerpartsim.h9
-rw-r--r--indra/newview/llviewerpartsource.cpp75
-rw-r--r--indra/newview/llviewerpartsource.h4
-rw-r--r--indra/newview/llvograss.cpp7
-rw-r--r--indra/newview/llvograss.h1
-rw-r--r--indra/newview/llvopartgroup.cpp305
-rw-r--r--indra/newview/llvopartgroup.h6
-rw-r--r--indra/newview/llvovolume.cpp169
-rw-r--r--indra/newview/llwlanimator.h1
-rw-r--r--indra/newview/llwlparammanager.h1
-rw-r--r--indra/newview/llwlparamset.cpp3
-rw-r--r--indra/newview/llwlparamset.h1
-rw-r--r--indra/newview/pipeline.cpp6
-rw-r--r--indra/test/io.cpp1
-rw-r--r--indra/test/llstreamtools_tut.cpp8
-rw-r--r--indra/test/lltemplatemessagebuilder_tut.cpp2
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 &params, 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 &params_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;