summaryrefslogtreecommitdiff
path: root/Runtime/mecanim/generic
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/mecanim/generic')
-rw-r--r--Runtime/mecanim/generic/crc32.h208
-rw-r--r--Runtime/mecanim/generic/stringtable.cpp131
-rw-r--r--Runtime/mecanim/generic/stringtable.h128
-rw-r--r--Runtime/mecanim/generic/typetraits.h47
-rw-r--r--Runtime/mecanim/generic/valuearray.cpp925
-rw-r--r--Runtime/mecanim/generic/valuearray.h256
6 files changed, 1695 insertions, 0 deletions
diff --git a/Runtime/mecanim/generic/crc32.h b/Runtime/mecanim/generic/crc32.h
new file mode 100644
index 0000000..ca1797b
--- /dev/null
+++ b/Runtime/mecanim/generic/crc32.h
@@ -0,0 +1,208 @@
+#pragma once
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/types.h"
+#include "Runtime/mecanim/string.h"
+
+namespace mecanim
+{
+ template < std::size_t Bits > struct reflector
+ {
+ typedef typename mecanim::uint_t<Bits>::value_type value_type;
+ static value_type reflect( value_type x );
+ };
+
+ // Function that reflects its argument
+ template < std::size_t Bits > typename reflector<Bits>::value_type reflector<Bits>::reflect( typename reflector<Bits>::value_type x)
+ {
+ value_type reflection = 0;
+ value_type const one = 1;
+
+ for ( std::size_t i = 0 ; i < Bits ; ++i, x >>= 1 )
+ {
+ if ( x & one )
+ {
+ reflection |= ( one << (Bits - 1u - i) );
+ }
+ }
+
+ return reflection;
+ }
+
+ template <uint32_t TruncPoly> struct crc32_table_t
+ {
+ static const uint32_t byte_combos = (1ul << CHAR_BIT);
+
+ typedef uint32_t value_type;
+ typedef value_type table_type[byte_combos];
+
+ static void init_table();
+
+ static table_type table;
+ static bool isInitialized;
+ };
+
+ template <uint32_t TruncPoly> typename crc32_table_t<TruncPoly>::table_type crc32_table_t<TruncPoly>::table = { 0 };
+ template <uint32_t TruncPoly> bool crc32_table_t<TruncPoly>::isInitialized = false;
+
+ // Populate CRC lookup table
+ template<uint32_t TruncPoly> void crc32_table_t<TruncPoly>::init_table()
+ {
+ // factor-out constants to avoid recalculation
+ value_type const fast_hi_bit = 1ul << ( 32 - 1u );
+ unsigned char const byte_hi_bit = 1u << (CHAR_BIT - 1u);
+
+ // loop over every possible dividend value
+ unsigned char dividend = 0;
+ do
+ {
+ value_type remainder = 0;
+
+ // go through all the dividend's bits
+ for ( unsigned char mask = byte_hi_bit ; mask ; mask >>= 1 )
+ {
+ // check if divisor fits
+ if ( dividend & mask )
+ {
+ remainder ^= fast_hi_bit;
+ }
+
+ // do polynominal division
+ if ( remainder & fast_hi_bit )
+ {
+ remainder <<= 1;
+ remainder ^= TruncPoly;
+ }
+ else
+ {
+ remainder <<= 1;
+ }
+ }
+
+ table[ reflector<CHAR_BIT>::reflect(dividend) ] = reflector<32>::reflect( remainder );
+ }
+ while ( ++dividend );
+
+ isInitialized = true;
+ }
+
+ class crc32
+ {
+ public:
+ // Type
+ typedef uint32_t value_type;
+
+ // Constants for the template parameters
+ static const std::size_t bit_count = 32;
+ static const value_type truncated_polynominal = 0x04C11DB7;
+ static const value_type initial_remainder = 0xFFFFFFFF;
+ static const value_type final_xor_value = 0xFFFFFFFF;
+
+ // Constructor
+ explicit crc32( value_type init_rem = crc32::initial_remainder ):rem(reflector<bit_count>::reflect(init_rem)){}
+
+ inline void process_block(void const *bytes_begin, void const *bytes_end);
+ inline void process_block_skip2(void const * bytes_begin, void const * bytes_end);
+
+ inline void process_bytes(void const *buffer, std::size_t byte_count );
+ inline void process_bytes_skip2(void const * buffer, std::size_t byte_count);
+
+ inline value_type checksum() const;
+
+ typedef crc32_table_t<truncated_polynominal> crc32_table_type;
+
+ protected:
+
+ inline value_type get_truncated_polynominal() const{ return truncated_polynominal; }
+ inline value_type get_initial_remainder() const{return initial_remainder;}
+ inline value_type get_final_xor_value() const{return final_xor_value;}
+
+ static unsigned char index( value_type rem, unsigned char x ){ return static_cast<unsigned char>(x ^ rem); }
+
+ // Shift out the remainder's highest byte
+ static value_type shift( value_type rem ){ return rem >> CHAR_BIT; }
+
+ // Member data
+ value_type rem;
+ };
+
+ inline void crc32::process_block(void const * bytes_begin, void const * bytes_end)
+ {
+ Assert(crc32_table_type::isInitialized);
+
+ // Recompute the CRC for each byte passed
+ for ( unsigned char const * p = static_cast<unsigned char const *>(bytes_begin) ; p < bytes_end ; ++p )
+ {
+ // Compare the new byte with the remainder's higher bits to
+ // get the new bits, shift out the remainder's current higher
+ // bits, and update the remainder with the polynominal division
+ // of the new bits.
+ unsigned char const byte_index = index( rem, *p );
+ rem = shift( rem );
+ rem ^= crc32_table_type::table[ byte_index ];
+ }
+ }
+
+ inline void crc32::process_block_skip2(void const * bytes_begin, void const * bytes_end)
+ {
+ Assert(crc32_table_type::isInitialized);
+ unsigned char const * p;
+
+#if UNITY_BIG_ENDIAN
+ p = static_cast<unsigned char const *>(bytes_begin) + 1;
+#else
+ p = static_cast<unsigned char const *>(bytes_begin);
+#endif
+
+ // Recompute the CRC for every second byte passed. This is useful for hashing a UTF16 string that is known to actually be an ascii string.
+ for ( ; p < bytes_end ; p += 2 )
+ {
+ // Compare the new byte with the remainder's higher bits to
+ // get the new bits, shift out the remainder's current higher
+ // bits, and update the remainder with the polynominal division
+ // of the new bits.
+ unsigned char const byte_index = index( rem, *p );
+ rem = shift( rem );
+ rem ^= crc32_table_type::table[ byte_index ];
+ }
+ }
+
+
+ inline void crc32::process_bytes(void const * buffer, std::size_t byte_count)
+ {
+ unsigned char const * const b = static_cast<unsigned char const *>( buffer );
+ process_block( b, b + byte_count );
+ }
+
+ inline void crc32::process_bytes_skip2(void const * buffer, std::size_t byte_count)
+ {
+ unsigned char const * const b = static_cast<unsigned char const *>( buffer );
+ process_block_skip2( b, b + byte_count );
+ }
+
+ inline crc32::value_type crc32::checksum() const
+ {
+ return ( rem ^ get_final_xor_value() );
+ }
+
+ static inline int processCRC32(String const& string)
+ {
+ crc32 result;
+ result.process_bytes(string.c_str(), string.size());
+ return result.checksum();
+ }
+
+ static inline int processCRC32(char const* string)
+ {
+ crc32 result;
+ result.process_bytes(string, strlen(string));
+ return result.checksum();
+ }
+
+ static inline int processCRC32UTF16Ascii(unsigned short const* string, std::size_t stringLength)
+ {
+ crc32 result;
+ result.process_bytes_skip2(string, stringLength * 2);
+ return result.checksum();
+ }
+}
diff --git a/Runtime/mecanim/generic/stringtable.cpp b/Runtime/mecanim/generic/stringtable.cpp
new file mode 100644
index 0000000..85cf025
--- /dev/null
+++ b/Runtime/mecanim/generic/stringtable.cpp
@@ -0,0 +1,131 @@
+#include "UnityPrefix.h"
+#include "Runtime/mecanim/generic/stringtable.h"
+#include "Runtime/mecanim/generic/crc32.h"
+
+#define DEFINE_KEYWORD(s) table[mecanim::e##s] = mecanim::ReserveKeyword(mecanim::processCRC32(#s), #s)
+
+namespace
+{
+ mecanim::ReserveKeyword* InitTable()
+ {
+ static mecanim::ReserveKeyword table[mecanim::eLastString];
+
+ DEFINE_KEYWORD(T);
+ DEFINE_KEYWORD(Q);
+ DEFINE_KEYWORD(S);
+ DEFINE_KEYWORD(A);
+ DEFINE_KEYWORD(B);
+ DEFINE_KEYWORD(C);
+ DEFINE_KEYWORD(D);
+ DEFINE_KEYWORD(E);
+ DEFINE_KEYWORD(X);
+ DEFINE_KEYWORD(Y);
+ DEFINE_KEYWORD(Z);
+ DEFINE_KEYWORD(W);
+ DEFINE_KEYWORD(Result);
+ DEFINE_KEYWORD(Min);
+ DEFINE_KEYWORD(Max);
+ DEFINE_KEYWORD(Value);
+ DEFINE_KEYWORD(MinMin);
+ DEFINE_KEYWORD(MinMax);
+ DEFINE_KEYWORD(MaxMin);
+ DEFINE_KEYWORD(MaxMax);
+ DEFINE_KEYWORD(In);
+ DEFINE_KEYWORD(Out);
+ DEFINE_KEYWORD(RangeA);
+ DEFINE_KEYWORD(RangeB);
+ DEFINE_KEYWORD(RangeC);
+ DEFINE_KEYWORD(RangeD);
+ DEFINE_KEYWORD(RangeE);
+ DEFINE_KEYWORD(WeightA);
+ DEFINE_KEYWORD(WeightB);
+ DEFINE_KEYWORD(WeightC);
+ DEFINE_KEYWORD(WeightD);
+ DEFINE_KEYWORD(WeightE);
+ DEFINE_KEYWORD(OutA);
+ DEFINE_KEYWORD(OutB);
+ DEFINE_KEYWORD(OutC);
+ DEFINE_KEYWORD(OutD);
+ DEFINE_KEYWORD(OutE);
+ DEFINE_KEYWORD(Num);
+ DEFINE_KEYWORD(Den);
+ DEFINE_KEYWORD(Rem);
+ DEFINE_KEYWORD(DampTime);
+ DEFINE_KEYWORD(DeltaTime);
+ DEFINE_KEYWORD(PreviousValue);
+ DEFINE_KEYWORD(GravityWeight);
+ DEFINE_KEYWORD(SrcRefX);
+ DEFINE_KEYWORD(DstRefX);
+ DEFINE_KEYWORD(SrcPivotX);
+ DEFINE_KEYWORD(DstPivotX);
+ DEFINE_KEYWORD(RefWeight);
+ DEFINE_KEYWORD(PivotWeight);
+ DEFINE_KEYWORD(XI);
+ DEFINE_KEYWORD(XO);
+ DEFINE_KEYWORD(Condition);
+ DEFINE_KEYWORD(StateTime);
+ DEFINE_KEYWORD(StateSpeed);
+ DEFINE_KEYWORD(StateExitTime);
+ DEFINE_KEYWORD(DoTransition);
+ DEFINE_KEYWORD(NextStateStartTime);
+ DEFINE_KEYWORD(TransitionDuration);
+ DEFINE_KEYWORD(TransitionOffset);
+ DEFINE_KEYWORD(TransitionStartTime);
+ DEFINE_KEYWORD(StateMachineWeight);
+ DEFINE_KEYWORD(TransitionTime);
+ DEFINE_KEYWORD(BlendWeight);
+ DEFINE_KEYWORD(StateWeight);
+ DEFINE_KEYWORD(StabilizeFeet);
+ DEFINE_KEYWORD(RootX);
+ table[mecanim::eLeftFootWeightT] = mecanim::ReserveKeyword(mecanim::processCRC32("LeftFoot.WeightT"), "LeftFoot.WeightT");
+ table[mecanim::eLeftFootWeightR] = mecanim::ReserveKeyword(mecanim::processCRC32("LeftFoot.WeightR"), "LeftFoot.WeightR");
+ table[mecanim::eRightFootWeightT] = mecanim::ReserveKeyword(mecanim::processCRC32("RightFoot.WeightT"), "RightFoot.WeightT");
+ table[mecanim::eRightFootWeightR] = mecanim::ReserveKeyword(mecanim::processCRC32("RightFoot.WeightR"), "RightFoot.WeightR");
+ DEFINE_KEYWORD(ComputeSource);
+ DEFINE_KEYWORD(LookAt);
+ DEFINE_KEYWORD(LeftFootX);
+ DEFINE_KEYWORD(RightFootX);
+ DEFINE_KEYWORD(LeftFootSpeedT);
+ DEFINE_KEYWORD(LeftFootSpeedQ);
+ DEFINE_KEYWORD(RightFootSpeedT);
+ DEFINE_KEYWORD(RightFootSpeedQ);
+ DEFINE_KEYWORD(LeftFootStableT);
+ DEFINE_KEYWORD(LeftFootStableQ);
+ DEFINE_KEYWORD(RightFootStableT);
+ DEFINE_KEYWORD(RightFootStableQ);
+ DEFINE_KEYWORD(RootSpeedT);
+ DEFINE_KEYWORD(RootSpeedQ);
+ DEFINE_KEYWORD(RootStableT);
+ DEFINE_KEYWORD(RootStableQ);
+ DEFINE_KEYWORD(LeftFootProjX);
+ DEFINE_KEYWORD(RightFootProjX);
+ DEFINE_KEYWORD(PlantFeet);
+ DEFINE_KEYWORD(LeftFootSafeX);
+ DEFINE_KEYWORD(RightFootSafeX);
+ DEFINE_KEYWORD(PositionX);
+ DEFINE_KEYWORD(PositionY);
+ DEFINE_KEYWORD(PositionZ);
+ DEFINE_KEYWORD(QuaternionX);
+ DEFINE_KEYWORD(QuaternionY);
+ DEFINE_KEYWORD(QuaternionZ);
+ DEFINE_KEYWORD(QuaternionW);
+ DEFINE_KEYWORD(ScaleX);
+ DEFINE_KEYWORD(ScaleY);
+ DEFINE_KEYWORD(ScaleZ);
+ DEFINE_KEYWORD(DynamicCurve);
+ return table;
+ }
+}
+
+namespace mecanim
+{
+ ReserveKeyword* ReserveKeywordTable()
+ {
+ static ReserveKeyword* s_Table = InitTable();
+ return s_Table;
+ }
+ uint32_t CRCKey(eString id)
+ {
+ return ReserveKeywordTable()[id].m_ID;
+ }
+ }
diff --git a/Runtime/mecanim/generic/stringtable.h b/Runtime/mecanim/generic/stringtable.h
new file mode 100644
index 0000000..3bf01f5
--- /dev/null
+++ b/Runtime/mecanim/generic/stringtable.h
@@ -0,0 +1,128 @@
+#pragma once
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/types.h"
+
+
+namespace mecanim
+{
+ enum eString
+ {
+ eT,
+ eQ,
+ eS,
+ eA,
+ eB,
+ eC,
+ eD,
+ eE,
+ eX,
+ eY,
+ eZ,
+ eW,
+ eResult,
+ eMin,
+ eMax,
+ eValue,
+ eMinMin,
+ eMinMax,
+ eMaxMin,
+ eMaxMax,
+ eIn,
+ eOut,
+ eRangeA,
+ eRangeB,
+ eRangeC,
+ eRangeD,
+ eRangeE,
+ eWeightA,
+ eWeightB,
+ eWeightC,
+ eWeightD,
+ eWeightE,
+ eOutA,
+ eOutB,
+ eOutC,
+ eOutD,
+ eOutE,
+ eNum,
+ eDen,
+ eRem,
+ eDampTime,
+ eDeltaTime,
+ ePreviousValue,
+ eGravityWeight,
+ eSrcRefX,
+ eDstRefX,
+ eSrcPivotX,
+ eDstPivotX,
+ eRefWeight,
+ ePivotWeight,
+ eXI,
+ eXO,
+ eCondition,
+ eStateTime,
+ eStateSpeed,
+ eStateExitTime,
+ eDoTransition,
+ eNextStateStartTime,
+ eTransitionDuration,
+ eTransitionOffset,
+ eTransitionStartTime,
+ eStateMachineWeight,
+ eTransitionTime,
+ eBlendWeight,
+ eStateWeight,
+ eStabilizeFeet,
+ eRootX,
+ eLeftFootWeightT,
+ eLeftFootWeightR,
+ eRightFootWeightT,
+ eRightFootWeightR,
+ eComputeSource,
+ eLookAt,
+ eLeftFootX,
+ eRightFootX,
+ eLeftFootSpeedT,
+ eLeftFootSpeedQ,
+ eRightFootSpeedT,
+ eRightFootSpeedQ,
+ eLeftFootStableT,
+ eLeftFootStableQ,
+ eRightFootStableT,
+ eRightFootStableQ,
+ eRootSpeedT,
+ eRootSpeedQ,
+ eRootStableT,
+ eRootStableQ,
+ eLeftFootProjX,
+ eRightFootProjX,
+ ePlantFeet,
+ eLeftFootSafeX,
+ eRightFootSafeX,
+ ePositionX,
+ ePositionY,
+ ePositionZ,
+ eQuaternionX,
+ eQuaternionY,
+ eQuaternionZ,
+ eQuaternionW,
+ eScaleX,
+ eScaleY,
+ eScaleZ,
+ eDynamicCurve,
+ eLastString
+ };
+
+ struct ReserveKeyword
+ {
+ ReserveKeyword():m_ID(0),m_Keyword(0){}
+ ReserveKeyword(uint32_t id, char const* keyword):m_ID(id),m_Keyword(keyword){}
+
+ uint32_t m_ID;
+ char const* m_Keyword ;
+ };
+
+ ReserveKeyword* ReserveKeywordTable();
+ uint32_t CRCKey(eString id);
+}
diff --git a/Runtime/mecanim/generic/typetraits.h b/Runtime/mecanim/generic/typetraits.h
new file mode 100644
index 0000000..1f9aa25
--- /dev/null
+++ b/Runtime/mecanim/generic/typetraits.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include "Runtime/mecanim/types.h"
+#include "Runtime/Math/Simd/float4.h"
+#include "Runtime/Math/Simd/xform.h"
+#include "Runtime/Math/Simd/bool4.h"
+
+namespace mecanim
+{
+ enum ValueType
+ {
+ kFloatType = 1,
+ kInt32Type = 3,
+ kBoolType = 4,
+ kPositionType = 6,
+ kQuaternionType = 7,
+ kScaleType = 8,
+ kTriggerType = 9,
+ kLastType
+ };
+
+ template<typename TYPE> struct traits;
+
+ template<> struct traits<int32_t>
+ {
+ typedef int32_t value_type;
+
+ static value_type zero() { return 0; }
+ static ValueType type() { return kInt32Type; }
+ };
+
+ template<> struct traits<float>
+ {
+ typedef float value_type;
+
+ static value_type zero() { return 0.f; }
+ static ValueType type() { return kFloatType; }
+ };
+
+ template<> struct traits<bool>
+ {
+ typedef bool value_type;
+
+ static value_type zero() { return false; }
+ static ValueType type() { return kBoolType; }
+ };
+}
diff --git a/Runtime/mecanim/generic/valuearray.cpp b/Runtime/mecanim/generic/valuearray.cpp
new file mode 100644
index 0000000..e7bfb58
--- /dev/null
+++ b/Runtime/mecanim/generic/valuearray.cpp
@@ -0,0 +1,925 @@
+#include "UnityPrefix.h"
+#include "Runtime/mecanim/generic/valuearray.h"
+
+#include "Runtime/Math/Simd/float4.h"
+#include "Runtime/Math/Simd/bool4.h"
+#include "Runtime/Math/Simd/xform.h"
+
+namespace mecanim
+{
+ template<typename TYPE>
+ static void ValueCopy(TYPE const * RESTRICT source, TYPE * RESTRICT destination, uint32_t sourceIndex, uint32_t destinationIndex)
+ {
+ destination[destinationIndex] = source[sourceIndex];
+ }
+
+ template<typename TYPE>
+ static void ValueArrayCopy(TYPE const * RESTRICT source, TYPE * RESTRICT destination, uint32_t sourceCount, uint32_t destinationCount)
+ {
+ sourceCount = min (destinationCount, sourceCount);
+
+ uint32_t i;
+ for(i = 0; i < sourceCount; ++i)
+ {
+ destination[i] = source[i];
+ }
+ }
+
+ template<typename TYPE>
+ static void ValueArrayCopyMask(TYPE const * RESTRICT source, TYPE * RESTRICT destination, const bool* RESTRICT mask, uint32_t sourceCount)
+ {
+ uint32_t i;
+ for(i = 0; i < sourceCount; ++i)
+ {
+ if (mask[i])
+ destination[i] = source[i];
+ }
+ }
+
+ void SetupValueArrayConstant(ValueArrayConstant* cst, ValueType aType, uint32_t aCount, memory::Allocator& alloc)
+ {
+ cst->m_Count = aCount;
+ cst->m_ValueArray = alloc.ConstructArray<ValueConstant>(cst->m_Count);
+
+ uint32_t i;
+ for(i=0;i<aCount;++i)
+ {
+ cst->m_ValueArray[i].m_Type = aType;
+ cst->m_ValueArray[i].m_Index = i;
+ }
+ }
+
+ ValueArrayConstant* CreateValueArrayConstant(uint32_t* apTypeArray, uint32_t aCount, memory::Allocator& alloc)
+ {
+ SETPROFILERLABEL(ValueArrayConstant);
+
+ ValueArrayConstant* cst = alloc.Construct<ValueArrayConstant>();
+
+ cst->m_Count = aCount;
+ cst->m_ValueArray = alloc.ConstructArray<ValueConstant>(cst->m_Count);
+
+ uint32_t positionCount = 0;
+ uint32_t quaternionCount = 0;
+ uint32_t scaleCount = 0;
+ uint32_t floatCount = 0;
+ uint32_t intCount = 0;
+ uint32_t boolCount = 0;
+
+ uint32_t i;
+ for(i=0;i<aCount;++i)
+ {
+ cst->m_ValueArray[i].m_Type = apTypeArray[i];
+
+ switch(apTypeArray[i])
+ {
+ case kPositionType: cst->m_ValueArray[i].m_Index = positionCount++; break;
+ case kQuaternionType: cst->m_ValueArray[i].m_Index = quaternionCount++; break;
+ case kScaleType: cst->m_ValueArray[i].m_Index = scaleCount++; break;
+ case kFloatType: cst->m_ValueArray[i].m_Index = floatCount++; break;
+ case kInt32Type: cst->m_ValueArray[i].m_Index = intCount++; break;
+ case kTriggerType:
+ case kBoolType: cst->m_ValueArray[i].m_Index = boolCount++; break;
+ default: assert(false); break;
+ }
+ }
+ return cst;
+ }
+
+ ValueArrayConstant* CreateValueArrayConstant(ValueType aType, uint32_t aCount, memory::Allocator& alloc)
+ {
+
+ SETPROFILERLABEL(ValueArrayConstant);
+ ValueArrayConstant* cst = alloc.Construct<ValueArrayConstant>();
+
+ SetupValueArrayConstant(cst, aType, aCount, alloc);
+ return cst;
+ }
+
+ ValueArrayConstant* CreateValueArrayConstantCopy (const ValueArrayConstant* sourceConstant, uint32_t count, memory::Allocator& alloc)
+ {
+
+ SETPROFILERLABEL(ValueArrayConstant);
+
+ Assert(count <= sourceConstant->m_Count);
+
+ ValueArrayConstant* cst = alloc.Construct<ValueArrayConstant>();
+ cst->m_Count = count;
+ cst->m_ValueArray = alloc.ConstructArray<ValueConstant>(sourceConstant->m_ValueArray.Get(), count);
+
+ return cst;
+ }
+
+
+ void DestroyValueArrayConstant(ValueArrayConstant * apCst, memory::Allocator& alloc)
+ {
+ if(apCst)
+ {
+ alloc.Deallocate(apCst->m_ValueArray);
+ alloc.Deallocate(apCst);
+ }
+ }
+
+ void SetValueMask(ValueArrayMask *valueArrayMask, bool value)
+ {
+ for(int i = 0; i < valueArrayMask->m_PositionCount; i++)
+ valueArrayMask->m_PositionValues[i] = value;
+
+ for(int i = 0; i < valueArrayMask->m_QuaternionCount; i++)
+ valueArrayMask->m_QuaternionValues[i] = value;
+
+ for(int i = 0; i < valueArrayMask->m_ScaleCount; i++)
+ valueArrayMask->m_ScaleValues[i] = value;
+
+ for(int i = 0; i < valueArrayMask->m_FloatCount; i++)
+ valueArrayMask->m_FloatValues[i] = value;
+
+ for(int i = 0; i < valueArrayMask->m_IntCount; i++)
+ valueArrayMask->m_IntValues[i] = value;
+ }
+
+ void CopyValueMask(ValueArrayMask *valueArrayMask,ValueArrayMask const *srcValueArrayMask)
+ {
+ for(int i = 0; i < valueArrayMask->m_PositionCount; i++)
+ valueArrayMask->m_PositionValues[i] = srcValueArrayMask->m_PositionValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_QuaternionCount; i++)
+ valueArrayMask->m_QuaternionValues[i] = srcValueArrayMask->m_QuaternionValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_ScaleCount; i++)
+ valueArrayMask->m_ScaleValues[i] = srcValueArrayMask->m_ScaleValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_FloatCount; i++)
+ valueArrayMask->m_FloatValues[i] = srcValueArrayMask->m_FloatValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_IntCount; i++)
+ valueArrayMask->m_IntValues[i] = srcValueArrayMask->m_IntValues[i];
+ }
+
+ void OrValueMask(ValueArrayMask *valueArrayMask,ValueArrayMask const *srcValueArrayMask)
+ {
+ for(int i = 0; i < valueArrayMask->m_PositionCount; i++)
+ valueArrayMask->m_PositionValues[i] = valueArrayMask->m_PositionValues[i] || srcValueArrayMask->m_PositionValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_QuaternionCount; i++)
+ valueArrayMask->m_QuaternionValues[i] = valueArrayMask->m_QuaternionValues[i] || srcValueArrayMask->m_QuaternionValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_ScaleCount; i++)
+ valueArrayMask->m_ScaleValues[i] = valueArrayMask->m_ScaleValues[i] || srcValueArrayMask->m_ScaleValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_FloatCount; i++)
+ valueArrayMask->m_FloatValues[i] = valueArrayMask->m_FloatValues[i] || srcValueArrayMask->m_FloatValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_IntCount; i++)
+ valueArrayMask->m_IntValues[i] = valueArrayMask->m_IntValues[i] || srcValueArrayMask->m_IntValues[i];
+ }
+
+ void AndValueMask(ValueArrayMask *valueArrayMask,ValueArrayMask const *srcValueArrayMask)
+ {
+ for(int i = 0; i < valueArrayMask->m_PositionCount; i++)
+ valueArrayMask->m_PositionValues[i] = valueArrayMask->m_PositionValues[i] && srcValueArrayMask->m_PositionValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_QuaternionCount; i++)
+ valueArrayMask->m_QuaternionValues[i] = valueArrayMask->m_QuaternionValues[i] && srcValueArrayMask->m_QuaternionValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_ScaleCount; i++)
+ valueArrayMask->m_ScaleValues[i] = valueArrayMask->m_ScaleValues[i] && srcValueArrayMask->m_ScaleValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_FloatCount; i++)
+ valueArrayMask->m_FloatValues[i] = valueArrayMask->m_FloatValues[i] && srcValueArrayMask->m_FloatValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_IntCount; i++)
+ valueArrayMask->m_IntValues[i] = valueArrayMask->m_IntValues[i] && srcValueArrayMask->m_IntValues[i];
+ }
+
+ void InvertValueMask(ValueArrayMask *valueArrayMask)
+ {
+ for(int i = 0; i < valueArrayMask->m_PositionCount; i++)
+ valueArrayMask->m_PositionValues[i] = !valueArrayMask->m_PositionValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_QuaternionCount; i++)
+ valueArrayMask->m_QuaternionValues[i] = !valueArrayMask->m_QuaternionValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_ScaleCount; i++)
+ valueArrayMask->m_ScaleValues[i] = !valueArrayMask->m_ScaleValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_FloatCount; i++)
+ valueArrayMask->m_FloatValues[i] = !valueArrayMask->m_FloatValues[i];
+
+ for(int i = 0; i < valueArrayMask->m_IntCount; i++)
+ valueArrayMask->m_IntValues[i] = !valueArrayMask->m_IntValues[i];
+ }
+
+ ValueArrayMask* CreateValueArrayMask(ValueArrayConstant const* constant, memory::Allocator& alloc)
+ {
+ SETPROFILERLABEL(ValueArrayMask);
+ ValueArrayMask* valueArrayMask = alloc.Construct<ValueArrayMask>();
+
+ uint32_t i;
+ for(i=0;i<constant->m_Count;++i)
+ {
+ switch(constant->m_ValueArray[i].m_Type)
+ {
+ case kPositionType: valueArrayMask->m_PositionCount++; break;
+ case kQuaternionType: valueArrayMask->m_QuaternionCount++; break;
+ case kScaleType: valueArrayMask->m_ScaleCount++; break;
+ case kFloatType: valueArrayMask->m_FloatCount++; break;
+ case kInt32Type: valueArrayMask->m_IntCount++; break;
+ default: assert(false); break;
+ }
+ }
+
+ valueArrayMask->m_IntValues = alloc.ConstructArray<bool>(valueArrayMask->m_IntCount);
+ valueArrayMask->m_FloatValues = alloc.ConstructArray<bool>(valueArrayMask->m_FloatCount);
+ valueArrayMask->m_PositionValues = alloc.ConstructArray<bool>(valueArrayMask->m_PositionCount);
+ valueArrayMask->m_QuaternionValues = alloc.ConstructArray<bool>(valueArrayMask->m_QuaternionCount);
+ valueArrayMask->m_ScaleValues = alloc.ConstructArray<bool>(valueArrayMask->m_ScaleCount);
+
+ SetValueMask (valueArrayMask, false);
+
+ return valueArrayMask;
+ }
+
+ void DestroyValueArrayMask(ValueArrayMask *valueArrayMask, memory::Allocator& alloc)
+ {
+ if(valueArrayMask)
+ {
+ alloc.Deallocate(valueArrayMask->m_IntValues);
+ alloc.Deallocate(valueArrayMask->m_FloatValues);
+ alloc.Deallocate(valueArrayMask->m_PositionValues);
+ alloc.Deallocate(valueArrayMask->m_QuaternionValues);
+ alloc.Deallocate(valueArrayMask->m_ScaleValues);
+ alloc.Deallocate(valueArrayMask);
+ }
+ }
+
+ ValueArray* CreateValueArray(ValueArrayConstant const* apValueArrayConstant, memory::Allocator& alloc)
+ {
+ SETPROFILERLABEL(ValueArray);
+ ValueArray* valueArray = alloc.Construct<ValueArray>();
+
+ uint32_t i;
+ for(i=0;i<apValueArrayConstant->m_Count;++i)
+ {
+ switch(apValueArrayConstant->m_ValueArray[i].m_Type)
+ {
+ case kPositionType: valueArray->m_PositionCount++; break;
+ case kQuaternionType: valueArray->m_QuaternionCount++; break;
+ case kScaleType: valueArray->m_ScaleCount++; break;
+ case kFloatType: valueArray->m_FloatCount++; break;
+ case kInt32Type: valueArray->m_IntCount++; break;
+ case kTriggerType:
+ case kBoolType: valueArray->m_BoolCount++; break;
+ default: assert(false); break;
+ }
+ }
+
+ valueArray->m_BoolValues = alloc.ConstructArray<bool>(valueArray->m_BoolCount);
+ valueArray->m_IntValues = alloc.ConstructArray<int32_t>(valueArray->m_IntCount);
+ valueArray->m_FloatValues = alloc.ConstructArray<float>(valueArray->m_FloatCount);
+ valueArray->m_PositionValues = alloc.ConstructArray<math::float4>(valueArray->m_PositionCount);
+ valueArray->m_QuaternionValues = alloc.ConstructArray<math::float4>(valueArray->m_QuaternionCount);
+ valueArray->m_ScaleValues = alloc.ConstructArray<math::float4>(valueArray->m_ScaleCount);
+
+ for(i=0;i<valueArray->m_BoolCount;++i)
+ valueArray->m_BoolValues[i] = false;
+
+ for(i=0;i<valueArray->m_IntCount;++i)
+ valueArray->m_IntValues[i] = 0;
+
+ for(i=0;i<valueArray->m_FloatCount;++i)
+ valueArray->m_FloatValues[i] = 0.f;
+
+ for(i=0;i<valueArray->m_PositionCount;++i)
+ valueArray->m_PositionValues[i] = math::float4::zero();
+
+ for(i=0;i<valueArray->m_QuaternionCount;++i)
+ valueArray->m_QuaternionValues[i] = math::quatIdentity();
+
+ for(i=0;i<valueArray->m_ScaleCount;++i)
+ valueArray->m_ScaleValues[i] = math::float4::one();
+
+ return valueArray;
+ }
+
+ void DestroyValueArray(ValueArray * apInput, memory::Allocator& alloc)
+ {
+ if(apInput)
+ {
+ alloc.Deallocate(apInput->m_BoolValues);
+ alloc.Deallocate(apInput->m_IntValues);
+ alloc.Deallocate(apInput->m_FloatValues);
+ alloc.Deallocate(apInput->m_PositionValues);
+ alloc.Deallocate(apInput->m_QuaternionValues);
+ alloc.Deallocate(apInput->m_ScaleValues);
+
+ alloc.Deallocate(apInput);
+ }
+ }
+
+ void ValueArrayCopy(ValueArray const* apSourceValueArray, ValueArray * apDestinationValueArray)
+ {
+ ValueArrayCopy(apSourceValueArray->m_BoolValues.Get(), apDestinationValueArray->m_BoolValues.Get(), apSourceValueArray->m_BoolCount, apDestinationValueArray->m_BoolCount);
+ ValueArrayCopy(apSourceValueArray->m_IntValues.Get(), apDestinationValueArray->m_IntValues.Get(), apSourceValueArray->m_IntCount, apDestinationValueArray->m_IntCount);
+ ValueArrayCopy(apSourceValueArray->m_FloatValues.Get(), apDestinationValueArray->m_FloatValues.Get(), apSourceValueArray->m_FloatCount, apDestinationValueArray->m_FloatCount);
+ ValueArrayCopy(apSourceValueArray->m_PositionValues.Get(), apDestinationValueArray->m_PositionValues.Get(), apSourceValueArray->m_PositionCount, apDestinationValueArray->m_PositionCount);
+ ValueArrayCopy(apSourceValueArray->m_QuaternionValues.Get(), apDestinationValueArray->m_QuaternionValues.Get(), apSourceValueArray->m_QuaternionCount, apDestinationValueArray->m_QuaternionCount);
+ ValueArrayCopy(apSourceValueArray->m_ScaleValues.Get(), apDestinationValueArray->m_ScaleValues.Get(), apSourceValueArray->m_ScaleCount, apDestinationValueArray->m_ScaleCount);
+ }
+
+ void ValueArrayCopy(ValueArrayConstant const* sourceConstant, ValueArray const* source, ValueArrayConstant const* destinationConstant, ValueArray* destination, int32_t const* destinationInSourceIndexArray)
+ {
+ int dstCount = destinationConstant->m_Count;
+
+ for(int dstIter = 0; dstIter < dstCount; dstIter++)
+ {
+ int32_t srcIndex = destinationInSourceIndexArray[dstIter];
+ int32_t dstIndex = dstIter;
+
+ if(srcIndex != -1 && sourceConstant->m_ValueArray[srcIndex].m_Type == destinationConstant->m_ValueArray[dstIndex].m_Type)
+ {
+ switch(sourceConstant->m_ValueArray[srcIndex].m_Type)
+ {
+ case kPositionType:
+ {
+ math::float4 value = source->ReadPosition(sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WritePosition(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ case kQuaternionType:
+ {
+ math::float4 value = source->ReadQuaternion(sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WriteQuaternion(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ case kScaleType:
+ {
+ math::float4 value = source->ReadScale(sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WriteScale(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ case kFloatType:
+ {
+ float value;
+ source->ReadData(value, sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WriteData(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ case kInt32Type:
+ {
+ int32_t value;
+ source->ReadData(value, sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WriteData(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ case kTriggerType:
+ case kBoolType:
+ {
+ bool value;
+ source->ReadData(value, sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WriteData(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ void ValueArrayReverseCopy(ValueArrayConstant const* sourceConstant, ValueArray const* source, ValueArrayConstant const* destinationConstant, ValueArray* destination, int32_t const* sourceInDestinationIndexArray)
+ {
+ int srcCount = sourceConstant->m_Count;
+
+ for(int srcIter = 0; srcIter < srcCount; srcIter++)
+ {
+ int32_t dstIndex = sourceInDestinationIndexArray[srcIter];
+ int32_t srcIndex = srcIter;
+
+ if(dstIndex != -1 && sourceConstant->m_ValueArray[srcIndex].m_Type == destinationConstant->m_ValueArray[dstIndex].m_Type)
+ {
+ switch(sourceConstant->m_ValueArray[srcIndex].m_Type)
+ {
+ case kPositionType:
+ {
+ math::float4 value = source->ReadPosition(sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WritePosition(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ case kQuaternionType:
+ {
+ math::float4 value = source->ReadQuaternion(sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WriteQuaternion(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ case kScaleType:
+ {
+ math::float4 value = source->ReadScale(sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WriteScale(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ case kFloatType:
+ {
+ float value;
+ source->ReadData(value, sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WriteData(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ case kInt32Type:
+ {
+ int32_t value;
+ source->ReadData(value, sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WriteData(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ case kTriggerType:
+ case kBoolType:
+ {
+ bool value;
+ source->ReadData(value, sourceConstant->m_ValueArray[srcIndex].m_Index);
+ destination->WriteData(value, destinationConstant->m_ValueArray[dstIndex].m_Index);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ void ValueArrayCopy(ValueArray const *aSource, ValueArray* aValues, ValueArrayMask const *mask)
+ {
+ ValueArrayCopyMask (aSource->m_PositionValues.Get(), aValues->m_PositionValues.Get(), mask->m_PositionValues.Get(), aValues->m_PositionCount);
+ ValueArrayCopyMask (aSource->m_QuaternionValues.Get(), aValues->m_QuaternionValues.Get(), mask->m_QuaternionValues.Get(), aValues->m_QuaternionCount);
+ ValueArrayCopyMask (aSource->m_ScaleValues.Get(), aValues->m_ScaleValues.Get(), mask->m_ScaleValues.Get(), aValues->m_ScaleCount);
+ ValueArrayCopyMask (aSource->m_FloatValues.Get(), aValues->m_FloatValues.Get(), mask->m_FloatValues.Get(), aValues->m_FloatCount);
+ ValueArrayCopyMask (aSource->m_IntValues.Get(), aValues->m_IntValues.Get(), mask->m_IntValues.Get(), aValues->m_IntCount);
+ ValueArrayCopyMask (aSource->m_BoolValues.Get(), aValues->m_BoolValues.Get(), mask->m_BoolValues.Get(), aValues->m_BoolCount);
+ }
+
+ static uint32_t GetLargestBlendIndex(const float *apWeightArray, uint32_t aCount)
+ {
+ float largest = apWeightArray[0];
+ uint32_t index = 0;
+ for (int i=1;i<aCount;i++)
+ {
+ if (apWeightArray[i] > largest)
+ {
+ index = i;
+ largest = apWeightArray[i];
+ }
+ }
+
+ return index;
+ }
+
+
+ void ValueArrayBlend(ValueArray const *apValuesDefault,ValueArray* aValues, ValueArray ** aValuesArray, const float *apWeightArray, uint32_t aCount, ValueArrayMask const *mask)
+ {
+ // Blend positions
+ for (int valueIndex=0;valueIndex<aValues->m_PositionCount;valueIndex++)
+ {
+ if(!mask->m_PositionValues[valueIndex])
+ continue;
+
+ float sumW = 0;
+ math::float4 value4 = math::float4::zero();
+
+ for(int blendIter = 0; blendIter < aCount; blendIter++)
+ {
+ sumW += apWeightArray[blendIter];
+ math::float1 w = math::float1(apWeightArray[blendIter]);
+
+ math::float4 valuei = aValuesArray[blendIter]->ReadPosition(valueIndex);
+ value4 += valuei*w;
+ }
+
+ if(sumW < 1.0f)
+ {
+ math::float1 wd = math::float1(1.0-sumW);
+ math::float4 valued = apValuesDefault->ReadPosition(valueIndex);
+ value4 += valued*math::float1(wd);
+ }
+
+ aValues->WritePosition(value4,valueIndex);
+ }
+
+ // Blend Quaternions
+ for (int valueIndex=0;valueIndex<aValues->m_QuaternionCount;valueIndex++)
+ {
+ if(!mask->m_QuaternionValues[valueIndex])
+ continue;
+
+ float sumW = 0;
+ math::float4 value4 = math::float4::zero();
+
+ for(int blendIter = 0; blendIter < aCount; blendIter++)
+ {
+ sumW += apWeightArray[blendIter];
+ math::float1 w = math::float1(apWeightArray[blendIter]);
+
+ math::float4 valuei = aValuesArray[blendIter]->ReadQuaternion(valueIndex);
+ value4 += math::cond(math::dot(value4,valuei) < math::float1::zero(), valuei * -w, valuei * w);
+ }
+
+ if(sumW < 1.0f)
+ {
+ math::float1 wd = math::float1(1.0-sumW);
+ math::float4 valued = apValuesDefault->ReadQuaternion(valueIndex);
+ value4 += math::cond(math::dot(value4,valued) < math::float1::zero(), valued * -wd, valued * wd);
+ }
+
+ value4 = math::normalize(value4);
+ aValues->WriteQuaternion(value4,valueIndex);
+ }
+
+ // Blend scale
+ for (int valueIndex=0;valueIndex<aValues->m_ScaleCount;valueIndex++)
+ {
+ if(!mask->m_ScaleValues[valueIndex])
+ continue;
+
+ float sumW = 0;
+ math::float4 value4 = math::float4::one();
+
+ for(int blendIter = 0; blendIter < aCount; blendIter++)
+ {
+ sumW += apWeightArray[blendIter];
+ math::float1 w = math::float1(apWeightArray[blendIter]);
+
+ math::float4 valuei = aValuesArray[blendIter]->ReadScale(valueIndex);
+ math::float4 sng = math::sgn(valuei);
+ value4 = sng * math::abs( value4 * scaleWeight(valuei, w));
+ }
+
+ if(sumW < 1.0f)
+ {
+ math::float1 wd = math::float1(1.0-sumW);
+
+ math::float4 valued = apValuesDefault->ReadScale(valueIndex);
+ math::float4 sng = math::sgn(valued);
+ value4 = sng * math::abs( value4 * scaleWeight(valued, wd));
+ }
+
+ aValues->WriteScale(value4,valueIndex);
+ }
+
+ // Blend floats
+ for (int valueIndex=0;valueIndex<aValues->m_FloatCount;valueIndex++)
+ {
+ if(!mask->m_FloatValues[valueIndex])
+ continue;
+
+ float sumW = 0;
+ float value = 0;
+
+ for(int blendIter = 0; blendIter < aCount; blendIter++)
+ {
+ float w = apWeightArray[blendIter];
+ sumW += w;
+
+ float valuei;
+ aValuesArray[blendIter]->ReadData(valuei,valueIndex);
+ value += valuei*w;
+ }
+
+ if(sumW < 1.0f)
+ {
+ float wd = 1.0-sumW;
+
+ float valued;
+ apValuesDefault->ReadData(valued,valueIndex);
+ value += valued*wd;
+ }
+
+ aValues->WriteData(value,valueIndex);
+ }
+
+ // Blend integers (pick by largest weight)
+ uint32_t largestBlendIndex = GetLargestBlendIndex (apWeightArray, aCount);
+ for (int valueIndex=0;valueIndex<aValues->m_IntCount;valueIndex++)
+ {
+ if(!mask->m_IntValues[valueIndex])
+ continue;
+
+ int32_t valueInt;
+ aValuesArray[largestBlendIndex]->ReadData(valueInt,valueIndex);
+ aValues->WriteData(valueInt,valueIndex);
+ }
+ }
+
+ void ValueArrayAdd(ValueArray const *apValuesDefault, ValueArray const* apValues, ValueArrayMask const *readMask, float aWeight, bool aAdditive, ValueArray* apValuesOut, ValueArrayMask *defaultMask)
+ {
+ math::float1 w(aWeight);
+ float base1;
+ float value1;
+ math::float4 base4;
+ math::float4 value4;
+ int32_t valueInt;
+
+ // Positions
+ for (int valueIndex=0;valueIndex<apValues->m_PositionCount;valueIndex++)
+ {
+ if(!readMask->m_PositionValues[valueIndex])
+ continue;
+
+ value4 = apValues->ReadPosition(valueIndex);
+ if(aAdditive)
+ {
+ if(defaultMask->m_PositionValues[valueIndex])
+ base4 = apValuesDefault->ReadPosition(valueIndex);
+ else
+ base4 = apValuesOut->ReadPosition(valueIndex);
+ value4 = base4 + value4 * w;
+ }
+ else
+ {
+ if(aWeight < 1)
+ {
+ if(defaultMask->m_PositionValues[valueIndex])
+ base4 = apValuesDefault->ReadPosition(valueIndex);
+ else
+ base4 = apValuesOut->ReadPosition(valueIndex);
+
+ value4 = math::lerp(base4,value4,w);
+ }
+ }
+ apValuesOut->WritePosition(value4,valueIndex);
+ defaultMask->m_PositionValues[valueIndex] = false;
+ }
+
+ // Quaternions
+ for (int valueIndex=0;valueIndex<apValues->m_QuaternionCount;valueIndex++)
+ {
+ if(!readMask->m_QuaternionValues[valueIndex])
+ continue;
+
+ value4 = apValues->ReadQuaternion(valueIndex);
+ if(aAdditive)
+ {
+ if(defaultMask->m_QuaternionValues[valueIndex])
+ base4 = apValuesDefault->ReadQuaternion(valueIndex);
+ else
+ base4 = apValuesOut->ReadQuaternion(valueIndex);
+
+ value4 = math::quatMul(base4,math::quatWeight(value4,w));
+ }
+ else
+ {
+ if(aWeight < 1)
+ {
+ if(defaultMask->m_QuaternionValues[valueIndex])
+ base4 = apValuesDefault->ReadQuaternion(valueIndex);
+ else
+ base4 = apValuesOut->ReadQuaternion(valueIndex);
+
+ value4 = math::quatLerp(base4,value4,w);
+ }
+ }
+ apValuesOut->WriteQuaternion(value4,valueIndex);
+ defaultMask->m_QuaternionValues[valueIndex] = false;
+ }
+
+ // Scale
+ for (int valueIndex=0;valueIndex<apValues->m_ScaleCount;valueIndex++)
+ {
+ if(!readMask->m_ScaleValues[valueIndex])
+ continue;
+
+ value4 = apValues->ReadScale(valueIndex);
+ if(aAdditive)
+ {
+ if(defaultMask->m_ScaleValues[valueIndex])
+ base4 = apValuesDefault->ReadScale(valueIndex);
+ else
+ base4 = apValuesOut->ReadScale(valueIndex);
+
+ value4 = base4 * math::scaleWeight(value4,w);
+ }
+ else
+ {
+ if(aWeight < 1)
+ {
+ if(defaultMask->m_ScaleValues[valueIndex])
+ base4 = apValuesDefault->ReadScale(valueIndex);
+ else
+ base4 = apValuesOut->ReadScale(valueIndex);
+
+ value4 = math::scaleBlend(base4,value4,w);
+ }
+ }
+ apValuesOut->WriteScale(value4,valueIndex);
+ defaultMask->m_ScaleValues[valueIndex] = false;
+ }
+
+ // Floats
+ for (int valueIndex=0;valueIndex<apValues->m_FloatCount;valueIndex++)
+ {
+ if(!readMask->m_FloatValues[valueIndex])
+ continue;
+
+ apValues->ReadData(value1,valueIndex);
+ if(aAdditive)
+ {
+ if(defaultMask->m_FloatValues[valueIndex])
+ apValuesDefault->ReadData(base1,valueIndex);
+ else
+ apValuesOut->ReadData(base1,valueIndex);
+
+ value1 = base1 + value1 * aWeight;
+ }
+ else
+ {
+ if(aWeight < 1)
+ {
+ if(defaultMask->m_FloatValues[valueIndex])
+ apValuesDefault->ReadData(base1,valueIndex);
+ else
+ apValuesOut->ReadData(base1,valueIndex);
+
+ value1 = (1-aWeight) * base1 + value1 * aWeight;
+ }
+ }
+ apValuesOut->WriteData(value1,valueIndex);
+ defaultMask->m_FloatValues[valueIndex] = false;
+ }
+
+ // Ints
+ if (aWeight > 0.5F)
+ {
+ for (int valueIndex=0;valueIndex<apValues->m_IntCount;valueIndex++)
+ {
+ if(!readMask->m_IntValues[valueIndex])
+ continue;
+
+ apValues->ReadData(valueInt,valueIndex);
+ apValuesOut->WriteData(valueInt,valueIndex);
+ defaultMask->m_IntValues[valueIndex] = false;
+ }
+ }
+ else
+ {
+ for (int valueIndex=0;valueIndex<apValues->m_IntCount;valueIndex++)
+ {
+ if(!readMask->m_IntValues[valueIndex])
+ continue;
+
+ if(defaultMask->m_IntValues[valueIndex])
+ apValuesDefault->ReadData(valueInt,valueIndex);
+ else
+ apValuesOut->ReadData(valueInt,valueIndex);
+
+ apValuesOut->WriteData(valueInt,valueIndex);
+ defaultMask->m_IntValues[valueIndex] = false;
+ }
+ }
+ }
+
+ void ValueArraySub(ValueArray const &starts, ValueArray &values, ValueArrayMask const *mask)
+ {
+ float value,start;
+ math::float4 value4,start4;
+
+ // Positions
+ for (int valueIndex=0;valueIndex<values.m_PositionCount;valueIndex++)
+ {
+ if(!mask->m_PositionValues[valueIndex])
+ continue;
+
+ value4 = values.ReadPosition(valueIndex);
+ start4 = starts.ReadPosition(valueIndex);
+
+ value4 -= start4;
+
+ values.WritePosition(value4,valueIndex);
+ }
+
+ // Quaternions
+ for (int valueIndex=0;valueIndex<values.m_QuaternionCount;valueIndex++)
+ {
+ if(!mask->m_QuaternionValues[valueIndex])
+ continue;
+
+ value4 = values.ReadQuaternion(valueIndex);
+ start4 = starts.ReadQuaternion(valueIndex);
+
+ value4 = math::normalize(math::quatMul(math::quatConj(start4),value4));
+
+ values.WriteQuaternion(value4,valueIndex);
+ }
+
+ // Scale
+ for (int valueIndex=0;valueIndex<values.m_ScaleCount;valueIndex++)
+ {
+ if(!mask->m_ScaleValues[valueIndex])
+ continue;
+
+ value4 = values.ReadScale(valueIndex);
+ start4 = starts.ReadScale(valueIndex);
+
+ value4 /= start4;
+
+ values.WriteScale(value4,valueIndex);
+ }
+
+ // Floats
+ for (int valueIndex=0;valueIndex<values.m_FloatCount;valueIndex++)
+ {
+ if(!mask->m_FloatValues[valueIndex])
+ continue;
+
+ values.ReadData(value,valueIndex);
+ starts.ReadData(start,valueIndex);
+
+ value -= start;
+
+ values.WriteData(value,valueIndex);
+ }
+
+ // Integer substraction does not make sense
+ }
+
+ void ValueArrayLoop( ValueArray const &starts,
+ ValueArray const &stops,
+ ValueArray &values,
+ float loopWeight,
+ const ValueArrayMask& mask)
+ {
+ math::float1 loopWeight1(loopWeight);
+
+ float value,start,stop;
+ math::float4 value4,start4,stop4;
+
+ // Positions
+ for (int valueIndex=0;valueIndex<values.m_PositionCount;valueIndex++)
+ {
+ if(!mask.m_PositionValues[valueIndex])
+ continue;
+
+ value4 = values.ReadPosition(valueIndex);
+ start4 = starts.ReadPosition(valueIndex);
+ stop4 = stops.ReadPosition(valueIndex);
+
+ value4 += (start4 - stop4) * loopWeight1;
+
+ values.WritePosition(value4,valueIndex);
+ }
+
+ // Quaternions
+ for (int valueIndex=0;valueIndex<values.m_QuaternionCount;valueIndex++)
+ {
+ if(!mask.m_QuaternionValues[valueIndex])
+ continue;
+
+ value4 = values.ReadQuaternion(valueIndex);
+ start4 = starts.ReadQuaternion(valueIndex);
+ stop4 = stops.ReadQuaternion(valueIndex);
+
+ value4 = math::normalize(math::quatMul(value4,math::quatWeight(math::quatMul(math::quatConj(stop4),start4),loopWeight1)));
+
+ values.WriteQuaternion(value4,valueIndex);
+ }
+
+ // Scales
+ for (int valueIndex=0;valueIndex<values.m_ScaleCount;valueIndex++)
+ {
+ if(!mask.m_ScaleValues[valueIndex])
+ continue;
+
+ value4 = values.ReadScale(valueIndex);
+ start4 = starts.ReadScale(valueIndex);
+ stop4 = stops.ReadScale(valueIndex);
+
+ value4 *= math::scaleWeight(start4/stop4,loopWeight1);
+
+ values.WriteScale(value4,valueIndex);
+ }
+
+ // Floats
+ for (int valueIndex=0;valueIndex<values.m_FloatCount;valueIndex++)
+ {
+ if(!mask.m_FloatValues[valueIndex])
+ continue;
+
+ values.ReadData(value,valueIndex);
+ starts.ReadData(start,valueIndex);
+ stops.ReadData(stop,valueIndex);
+
+ value += (start - stop) * loopWeight;
+
+ values.WriteData(value,valueIndex);
+ }
+ }
+
+ int32_t FindValueIndex(const ValueArrayConstant *aValueArrayConstant, uint32_t id)
+ {
+ int32_t ret = -1;
+ if(aValueArrayConstant)
+ {
+ uint32_t i;
+ for( i = 0 ; i < aValueArrayConstant->m_Count ; i++)
+ {
+ if(aValueArrayConstant->m_ValueArray[i].m_ID == id)
+ {
+ return i;
+ }
+ }
+ }
+ return ret;
+ }
+}
diff --git a/Runtime/mecanim/generic/valuearray.h b/Runtime/mecanim/generic/valuearray.h
new file mode 100644
index 0000000..25dcacd
--- /dev/null
+++ b/Runtime/mecanim/generic/valuearray.h
@@ -0,0 +1,256 @@
+#pragma once
+
+#include "Runtime/mecanim/defs.h"
+#include "Runtime/mecanim/memory.h"
+#include "Runtime/mecanim/types.h"
+
+#include "Runtime/mecanim/generic/crc32.h"
+#include "Runtime/mecanim/generic/typetraits.h"
+
+#include "Runtime/Serialize/Blobification/offsetptr.h"
+#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h"
+#include "Runtime/Animation/MecanimArraySerialization.h"
+
+namespace mecanim
+{
+ struct ValueConstant
+ {
+ DEFINE_GET_TYPESTRING(ValueConstant)
+
+ ValueConstant():m_ID(0),m_Type(kLastType),m_TypeID(0),m_Index(0){}
+
+ uint32_t m_ID;
+ uint32_t m_TypeID; //@TODO: This is deprecated. We should probably make this webplayer only?
+ uint32_t m_Type;
+ uint32_t m_Index;
+
+ template<class TransferFunction>
+ inline void Transfer (TransferFunction& transfer)
+ {
+ TRANSFER(m_ID);
+ TRANSFER(m_TypeID);
+ TRANSFER(m_Type);
+ TRANSFER(m_Index);
+ }
+ };
+
+ struct ValueArrayConstant
+ {
+ DEFINE_GET_TYPESTRING(ValueArrayConstant)
+
+ ValueArrayConstant():m_Count(0){}
+
+ uint32_t m_Count;
+ OffsetPtr<ValueConstant> m_ValueArray;
+
+ template<class TransferFunction>
+ inline void Transfer (TransferFunction& transfer)
+ {
+ TRANSFER_BLOB_ONLY(m_Count);
+ MANUAL_ARRAY_TRANSFER2(ValueConstant, m_ValueArray, m_Count);
+ }
+ };
+
+ struct ValueArrayMask
+ {
+ DEFINE_GET_TYPESTRING(ValueArrayConstant)
+
+ ValueArrayMask():m_BoolCount(0),m_IntCount(0),m_FloatCount(0),m_PositionCount(0),m_QuaternionCount(0),m_ScaleCount(0) {}
+
+ uint32_t m_BoolCount;
+ OffsetPtr<bool> m_BoolValues;
+ uint32_t m_IntCount;
+ OffsetPtr<bool> m_IntValues;
+ uint32_t m_FloatCount;
+ OffsetPtr<bool> m_FloatValues;
+ uint32_t m_PositionCount;
+ OffsetPtr<bool> m_PositionValues;
+ uint32_t m_QuaternionCount;
+ OffsetPtr<bool> m_QuaternionValues;
+ uint32_t m_ScaleCount;
+ OffsetPtr<bool> m_ScaleValues;
+
+ template<class TransferFunction>
+ inline void Transfer (TransferFunction& transfer)
+ {
+ TRANSFER_BLOB_ONLY(m_BoolCount);
+ MANUAL_ARRAY_TRANSFER2(bool, m_BoolValues, m_BoolCount);
+
+ TRANSFER_BLOB_ONLY(m_IntCount);
+ MANUAL_ARRAY_TRANSFER2(bool, m_IntValues, m_IntCount);
+
+ TRANSFER_BLOB_ONLY(m_FloatCount);
+ MANUAL_ARRAY_TRANSFER2(bool, m_FloatValues, m_FloatCount);
+
+ TRANSFER_BLOB_ONLY(m_PositionCount);
+ MANUAL_ARRAY_TRANSFER2(bool, m_PositionValues, m_PositionCount);
+
+ TRANSFER_BLOB_ONLY(m_QuaternionCount);
+ MANUAL_ARRAY_TRANSFER2(bool, m_QuaternionValues, m_QuaternionCount);
+
+ TRANSFER_BLOB_ONLY(m_ScaleCount);
+ MANUAL_ARRAY_TRANSFER2(bool, m_ScaleValues, m_ScaleCount);
+ }
+ };
+
+ struct ValueArray
+ {
+ DEFINE_GET_TYPESTRING(ValueArray)
+
+ ValueArray():m_BoolCount(0),m_IntCount(0),m_FloatCount(0),m_PositionCount(0),m_QuaternionCount(0),m_ScaleCount(0) {}
+
+ uint32_t m_BoolCount;
+ OffsetPtr<bool> m_BoolValues;
+ uint32_t m_IntCount;
+ OffsetPtr<int32_t> m_IntValues;
+ uint32_t m_FloatCount;
+ OffsetPtr<float> m_FloatValues;
+ uint32_t m_PositionCount;
+ OffsetPtr<math::float4> m_PositionValues;
+ uint32_t m_QuaternionCount;
+ OffsetPtr<math::float4> m_QuaternionValues;
+ uint32_t m_ScaleCount;
+ OffsetPtr<math::float4> m_ScaleValues;
+
+ MECANIM_FORCE_INLINE void ReadData(bool& data, uint32_t index)const
+ {
+ Assert(index < m_BoolCount);
+ data = m_BoolValues[index];
+ }
+
+ MECANIM_FORCE_INLINE void WriteData(bool const& data, uint32_t index)
+ {
+ Assert(index < m_BoolCount);
+ m_BoolValues[index] = data;
+ }
+
+ MECANIM_FORCE_INLINE void ReadData(int32_t& data, uint32_t index)const
+ {
+ Assert(index < m_IntCount);
+ data = m_IntValues[index];
+ }
+
+ MECANIM_FORCE_INLINE void WriteData(int32_t const& data, uint32_t index)
+ {
+ Assert(index < m_IntCount);
+ m_IntValues[index] = data;
+ }
+
+ MECANIM_FORCE_INLINE void ReadData(float& data, uint32_t index)const
+ {
+ Assert(index < m_FloatCount);
+ data = m_FloatValues[index];
+ }
+
+ MECANIM_FORCE_INLINE void WriteData(float const& data, uint32_t index)
+ {
+ Assert(index < m_FloatCount);
+ m_FloatValues[index] = data;
+ }
+
+ MECANIM_FORCE_INLINE math::float4 ReadPosition(uint32_t index)const
+ {
+ Assert(index < m_PositionCount);
+ return m_PositionValues[index];
+ }
+
+ MECANIM_FORCE_INLINE void WritePosition(math::float4 const& data, uint32_t index)
+ {
+ Assert(index < m_PositionCount);
+ m_PositionValues[index] = data;
+ }
+
+ MECANIM_FORCE_INLINE math::float4 ReadQuaternion(uint32_t index)const
+ {
+ Assert(index < m_QuaternionCount);
+ return m_QuaternionValues[index];
+ }
+
+ MECANIM_FORCE_INLINE void WriteQuaternion(math::float4 const& data, uint32_t index)
+ {
+ Assert(index < m_QuaternionCount);
+ m_QuaternionValues[index] = data;
+ }
+
+ MECANIM_FORCE_INLINE math::float4 ReadScale(uint32_t index)const
+ {
+ Assert(index < m_ScaleCount);
+ return m_ScaleValues[index];
+ }
+
+ MECANIM_FORCE_INLINE void WriteScale(math::float4 const& data, uint32_t index)
+ {
+ Assert(index < m_ScaleCount);
+ m_ScaleValues[index] = data;
+ }
+
+ const float* GetFloatValues () const
+ {
+ return m_FloatValues.Get();
+ }
+
+ float* GetFloatValues ()
+ {
+ return m_FloatValues.Get();
+ }
+
+ template<class TransferFunction>
+ inline void Transfer (TransferFunction& transfer)
+ {
+ TRANSFER_BLOB_ONLY(m_BoolCount);
+ MANUAL_ARRAY_TRANSFER2(bool, m_BoolValues, m_BoolCount);
+ transfer.Align();
+
+ TRANSFER_BLOB_ONLY(m_IntCount);
+ MANUAL_ARRAY_TRANSFER2(int32_t, m_IntValues, m_IntCount);
+
+ TRANSFER_BLOB_ONLY(m_FloatCount);
+ MANUAL_ARRAY_TRANSFER2(float, m_FloatValues, m_FloatCount);
+
+ TRANSFER_BLOB_ONLY(m_PositionCount);
+ MANUAL_ARRAY_TRANSFER2(math::float4, m_PositionValues, m_PositionCount);
+
+ TRANSFER_BLOB_ONLY(m_QuaternionCount);
+ MANUAL_ARRAY_TRANSFER2(math::float4, m_QuaternionValues, m_QuaternionCount);
+
+ TRANSFER_BLOB_ONLY(m_ScaleCount);
+ MANUAL_ARRAY_TRANSFER2(math::float4, m_ScaleValues, m_ScaleCount);
+ }
+ };
+
+ void SetupValueArrayConstant(ValueArrayConstant* constant, ValueType aType, uint32_t aCount, memory::Allocator& alloc);
+
+ ValueArrayConstant* CreateValueArrayConstant(uint32_t* typeArray, uint32_t count, memory::Allocator& alloc);
+ ValueArrayConstant* CreateValueArrayConstantCopy(const ValueArrayConstant* constant, uint32_t count, memory::Allocator& alloc);
+ ValueArrayConstant* CreateValueArrayConstant(ValueType type, uint32_t count, memory::Allocator& alloc);
+ void DestroyValueArrayConstant(ValueArrayConstant * constant, memory::Allocator& alloc);
+
+ ValueArrayMask* CreateValueArrayMask(ValueArrayConstant const* constant, memory::Allocator& alloc);
+ void DestroyValueArrayMask(ValueArrayMask *valueArrayMask, memory::Allocator& alloc);
+ void SetValueMask(ValueArrayMask *valueArrayMask, bool value);
+ void CopyValueMask(ValueArrayMask *valueArrayMask,ValueArrayMask const *srcValueArrayMask);
+ void OrValueMask(ValueArrayMask *valueArrayMask,ValueArrayMask const *srcValueArrayMask);
+ void AndValueMask(ValueArrayMask *valueArrayMask,ValueArrayMask const *srcValueArrayMask);
+ void InvertValueMask(ValueArrayMask *valueArrayMask);
+
+ ValueArray* CreateValueArray(ValueArrayConstant const* constant, memory::Allocator& alloc);
+ void DestroyValueArray(ValueArray * valueArray, memory::Allocator& alloc);
+
+ void ValueArrayCopy(ValueArray const* source, ValueArray* destination);
+ void ValueArrayCopy(ValueArrayConstant const* sourceConstant, ValueArray const* source, ValueArrayConstant const* destinationConstant, ValueArray* destination, int32_t const* destinationInSourceIndexArray);
+ void ValueArrayReverseCopy(ValueArrayConstant const* sourceConstant, ValueArray const* source, ValueArrayConstant const* destinationConstant, ValueArray* destination, int32_t const* sourceInDestinationIndexArray);
+ void ValueArrayCopy(ValueArray const *aSource, ValueArray* aValues, ValueArrayMask const *mask);
+
+ void ValueArrayBlend(ValueArray const *apValuesDefault,ValueArray* aValues, ValueArray ** aValuesArray, const float *apWeightArray, uint32_t aCount, const ValueArrayMask *mask);
+
+ void ValueArrayAdd(ValueArray const *apValuesDefault, ValueArray const* apValues, ValueArrayMask const *readMask, float aWeight, bool aAdditive, ValueArray* apValuesOut, ValueArrayMask *defaultMask);
+ void ValueArraySub(ValueArray const &starts, ValueArray &values, ValueArrayMask const *mask);
+ void ValueArrayLoop(ValueArray const &starts, ValueArray const &stops, ValueArray &values, float loopWeight, const ValueArrayMask& mask);
+
+ int32_t FindValueIndex(const ValueArrayConstant *constant, uint32_t id);
+
+ STATIC_INLINE int32_t FindValueIndex(const ValueArrayConstant *constant, char const* binding)
+ {
+ return FindValueIndex(constant, processCRC32(binding));
+ }
+}