diff options
Diffstat (limited to 'Runtime/mecanim/generic')
-rw-r--r-- | Runtime/mecanim/generic/crc32.h | 208 | ||||
-rw-r--r-- | Runtime/mecanim/generic/stringtable.cpp | 131 | ||||
-rw-r--r-- | Runtime/mecanim/generic/stringtable.h | 128 | ||||
-rw-r--r-- | Runtime/mecanim/generic/typetraits.h | 47 | ||||
-rw-r--r-- | Runtime/mecanim/generic/valuearray.cpp | 925 | ||||
-rw-r--r-- | Runtime/mecanim/generic/valuearray.h | 256 |
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)); + } +} |