123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- //
- // Gradient.cpp
- // cocos2d_libs
- //
- // Created by 徐俊杰 on 2020/5/22.
- //
- #include "Gradient.h"
- //#include "UnityPrefix.h"
- //#include "Runtime/BaseClasses/ObjectDefines.h"
- #include "rparticle/Serialize/TransferFunctions/SerializeTransfer.h"
- //#include "Runtime/Math/Gradient.h"
- NS_RRP_BEGIN
- GradientNEW::GradientNEW()
- : m_NumColorKeys(2)
- , m_NumAlphaKeys(2)
- {
- m_Keys[0] = m_Keys[1] = ColorRGBA32(0xffffffff);
- m_ColorTime[0] = m_AlphaTime[0] = NormalizedToWord(0.0f);
- m_ColorTime[1] = m_AlphaTime[1] = NormalizedToWord(1.0f);
-
- for(UInt32 i = 2; i < kGradientMaxNumKeys; i++)
- {
- m_Keys[i] = ColorRGBA32(0);
- m_ColorTime[i] = NormalizedToWord(0.0f);
- m_AlphaTime[i] = NormalizedToWord(0.0f);
- }
- }
- GradientNEW::~GradientNEW()
- {
- }
- void GradientNEW::SetKeys (ColorKey* colorKeys, unsigned numColorKeys, AlphaKey* alphaKeys, unsigned numAlphaKeys)
- {
- SetColorKeys (colorKeys, numColorKeys);
- SetAlphaKeys (alphaKeys, numAlphaKeys);
- }
- void GradientNEW::SwapColorKeys(int i, int j)
- {
- ColorRGBA32 tmpCol = m_Keys[i];
- UInt16 tmpTime = m_ColorTime[i];
- m_Keys[i].r = m_Keys[j].r;
- m_Keys[i].g = m_Keys[j].g;
- m_Keys[i].b = m_Keys[j].b;
- m_ColorTime[i] = m_ColorTime[j];
- m_Keys[j].r = tmpCol.r;
- m_Keys[j].g = tmpCol.g;
- m_Keys[j].b = tmpCol.b;
- m_ColorTime[j] = tmpTime;
- }
- void GradientNEW::SwapAlphaKeys(int i, int j)
- {
- ColorRGBA32 tmpCol = m_Keys[i];
- UInt16 tmpTime = m_AlphaTime[i];
- m_Keys[i].a = m_Keys[j].a;
- m_AlphaTime[i] = m_AlphaTime[j];
- m_Keys[j].a = tmpCol.a;
- m_AlphaTime[j] = tmpTime;
- }
- void GradientNEW::SetColorKeys (ColorKey* colorKeys, unsigned numKeys)
- {
- DebugAssert (numKeys <= kGradientMaxNumKeys);
- if (numKeys > kGradientMaxNumKeys)
- numKeys = kGradientMaxNumKeys;
-
- for (int i=0; i<numKeys; ++i)
- {
- const ColorRGBAf& color = colorKeys[i].m_Color;
- m_Keys[i].r = NormalizedToByte(color.r);
- m_Keys[i].g = NormalizedToByte(color.g);
- m_Keys[i].b = NormalizedToByte(color.b);
- m_ColorTime[i] = NormalizedToWord(colorKeys[i].m_Time);
- }
- m_NumColorKeys = numKeys;
-
- // Ensure sorted!
- int i = 0;
- const int keyCount = m_NumColorKeys;
- while ((i + 1) < keyCount)
- {
- if (m_ColorTime[i] > m_ColorTime[i+1])
- {
- SwapColorKeys(i, i + 1);
- if (i > 0)
- i -= 2;
- }
- i++;
- }
-
- ValidateColorKeys();
- }
- void GradientNEW::SetAlphaKeys (AlphaKey* alphaKeys, unsigned numKeys)
- {
- DebugAssert (numKeys <= kGradientMaxNumKeys);
- if (numKeys > kGradientMaxNumKeys)
- numKeys = kGradientMaxNumKeys;
-
- for (int i=0; i<numKeys; ++i)
- {
- float alpha = alphaKeys[i].m_Alpha;
- m_Keys[i].a = NormalizedToByte(alpha);
- m_AlphaTime[i] = NormalizedToWord(alphaKeys[i].m_Time);
- }
- m_NumAlphaKeys = numKeys;
-
- // Ensure sorted!
- int i = 0;
- const int keyCount = m_NumAlphaKeys;
- while ((i + 1) < keyCount)
- {
- if (m_AlphaTime[i] > m_AlphaTime[i+1])
- {
- SwapAlphaKeys(i, i + 1);
- if (i > 0)
- i -= 2;
- }
- i++;
- }
-
- ValidateAlphaKeys();
- }
- ColorRGBA32 GradientNEW::GetConstantColor () const
- {
- return m_Keys[0];
- }
- void GradientNEW::SetConstantColor (ColorRGBA32 color)
- {
- m_Keys[0] = color;
- m_NumAlphaKeys = 1;
- m_NumColorKeys = 1;
- }
- void GradientNEW::ValidateColorKeys()
- {
- // Make sure there is a minimum of 2 keys
- if(m_NumColorKeys < 2)
- {
- m_NumColorKeys = 2;
- for(int rgb = 0; rgb < 3; rgb++)
- m_Keys[1][rgb] = m_Keys[0][rgb];
- m_ColorTime[0] = NormalizedToWord(0.0f);
- m_ColorTime[1] = NormalizedToWord(1.0f);
- }
- }
- void GradientNEW::ValidateAlphaKeys()
- {
- // Make sure there is a minimum of 2 keys
- if(m_NumAlphaKeys < 2)
- {
- m_NumAlphaKeys = 2;
- m_Keys[1].a = m_Keys[0].a;
- m_AlphaTime[0] = NormalizedToWord(0.0f);
- m_AlphaTime[1] = NormalizedToWord(1.0f);
- }
- }
- void GradientNEW::InitializeOptimized(OptimizedGradient& gradient)
- {
- // Copy all time values
- for(int i = 0; i < m_NumColorKeys; ++i)
- gradient.times[i] = m_ColorTime[i];
-
- for(int i = 0, i2 = m_NumColorKeys; i < m_NumAlphaKeys; ++i, ++i2)
- gradient.times[i2] = m_AlphaTime[i];
-
- // Remove duplicates
- int keyCount = m_NumColorKeys + m_NumAlphaKeys;
- for(int i = 0; i < keyCount-1; ++i)
- {
- for(int j = i+1; j < keyCount; )
- {
- if(gradient.times[i] == gradient.times[j])
- {
- std::swap(gradient.times[j], gradient.times[keyCount-1]);
- keyCount--;
- continue;
- }
- ++j;
- }
- }
-
- // Sort
- int i = 0;
- while ((i + 1) < keyCount)
- {
- if (gradient.times[i] > gradient.times[i+1])
- {
- std::swap(gradient.times[i], gradient.times[i+1]);
- if (i > 0)
- i -= 2;
- }
- i++;
- }
-
- for(int i = 0; i < keyCount; ++i)
- gradient.colors[i] = Evaluate(WordToNormalized(gradient.times[i]));
- gradient.keyCount = keyCount;
-
- for(int i = 1; i < keyCount; ++i)
- gradient.rcp[i] = ((((1<<24)) / std::max<UInt32>(gradient.times[i] - gradient.times[i-1], 1)))+1;
- }
- template<class TransferFunction>
- void GradientNEW::Transfer (TransferFunction& transfer)
- {
- AssertIf (kGradientMaxNumKeys > 9);
-
- const char* kKeyNames [kGradientMaxNumKeys] = { "key0", "key1", "key2", "key3", "key4", "key5", "key6", "key7", };
- for(UInt32 i = 0; i < kGradientMaxNumKeys; i++)
- transfer.Transfer(m_Keys[i], kKeyNames[i]);//, kHideInEditorMask);
-
- const char* kColorTimeNames [kGradientMaxNumKeys] = { "ctime0", "ctime1", "ctime2", "ctime3", "ctime4", "ctime5", "ctime6", "ctime7", };
- for(UInt32 i = 0; i < kGradientMaxNumKeys; i++)
- transfer.Transfer(m_ColorTime[i], kColorTimeNames[i]);//, kHideInEditorMask);
-
- const char* kAlphaTimeNames [kGradientMaxNumKeys] = { "atime0", "atime1", "atime2", "atime3", "atime4", "atime5", "atime6", "atime7", };
- for(UInt32 i = 0; i < kGradientMaxNumKeys; i++)
- transfer.Transfer(m_AlphaTime[i], kAlphaTimeNames[i]);//, kHideInEditorMask);
-
- transfer.Transfer (m_NumColorKeys, "m_NumColorKeys");//, kHideInEditorMask);
- transfer.Transfer (m_NumAlphaKeys, "m_NumAlphaKeys");//, kHideInEditorMask);
- transfer.Align();
-
- if(transfer.IsReading())
- {
- ValidateColorKeys();
- ValidateAlphaKeys();
- }
- }
- INSTANTIATE_TEMPLATE_TRANSFER(GradientNEW)
- #if ENABLE_UNIT_TESTS
- #include "External/UnitTest++/src/UnitTest++.h"
- bool CompareColors(ColorRGBA32 c0, ColorRGBA32 c1, int tolerance)
- {
- if(Abs(c0.r-c1.r) > tolerance)
- return false;
- if(Abs(c0.g-c1.g) > tolerance)
- return false;
- if(Abs(c0.b-c1.b) > tolerance)
- return false;
- if(Abs(c0.a-c1.a) > tolerance)
- return false;
- return true;
- }
- SUITE (GradientTests)
- {
- TEST (GradientTests_GradientEvaluate)
- {
- // Set up rainbow gradient
- GradientNEW gradient;
- gradient.SetNumColorKeys(5);
- gradient.SetNumAlphaKeys(3);
- gradient.GetKey(0) = ColorRGBA32(0xff, 0x00, 0x00, 0xff);
- gradient.GetKey(1) = ColorRGBA32(0xf8, 0xff, 0x00, 0x00);
- gradient.GetKey(2) = ColorRGBA32(0x00, 0xff, 0x49, 0xff);
- gradient.GetKey(3) = ColorRGBA32(0x22, 0x00, 0xff, 0x00);
- gradient.GetKey(4) = ColorRGBA32(0xff, 0x00, 0xe6, 0x00);
- gradient.GetColorTime(0) = 0x0000;
- gradient.GetColorTime(1) = 0x40c1;
- gradient.GetColorTime(2) = 0x9212;
- gradient.GetColorTime(3) = 0xce4e;
- gradient.GetColorTime(4) = 0xffff;
- gradient.GetAlphaTime(0) = 0x0000;
- gradient.GetAlphaTime(1) = 0x8000;
- gradient.GetAlphaTime(2) = 0xffff;
-
- CHECK_EQUAL(ColorRGBA32(0xff, 0x00, 0x00, 0xff) == gradient.Evaluate(0.0f), true);
- CHECK_EQUAL(ColorRGBA32(0xfd, 0x31, 0x00, 0xe6) == gradient.Evaluate(0.05f), true);
- CHECK_EQUAL(ColorRGBA32(0xfa, 0x96, 0x00, 0xb3) == gradient.Evaluate(0.15f), true);
- CHECK_EQUAL(ColorRGBA32(0xf8, 0xfc, 0x00, 0x7f) == gradient.Evaluate(0.25f), true);
- CHECK_EQUAL(ColorRGBA32(0xac, 0xff, 0x16, 0x4c) == gradient.Evaluate(0.35f), true);
- CHECK_EQUAL(ColorRGBA32(0x5e, 0xff, 0x2d, 0x19) == gradient.Evaluate(0.45f), true);
- CHECK_EQUAL(ColorRGBA32(0x10, 0xff, 0x44, 0x18) == gradient.Evaluate(0.55f), true);
- CHECK_EQUAL(ColorRGBA32(0x0b, 0xa9, 0x86, 0x4b) == gradient.Evaluate(0.65f), true);
- CHECK_EQUAL(ColorRGBA32(0x19, 0x3c, 0xd3, 0x7e) == gradient.Evaluate(0.75f), true);
- CHECK_EQUAL(ColorRGBA32(0x54, 0x00, 0xf9, 0xb2) == gradient.Evaluate(0.85f), true);
- CHECK_EQUAL(ColorRGBA32(0xc6, 0x00, 0xec, 0xe5) == gradient.Evaluate(0.95f), true);
- CHECK_EQUAL(ColorRGBA32(0xff, 0x00, 0xe6, 0xff) == gradient.Evaluate(1.0f), true);
-
- OptimizedGradient optGradient;
- gradient.InitializeOptimized(optGradient);
-
- #if UNITY_LINUX
- #warning Investigate/fix GradientEvaluateTest!
- #else
- // Being off by 1LSB is okay... (due to rounding)
- for(float time = 0.0f; time <= 1.0f; time += 0.02f)
- CHECK_EQUAL(CompareColors(optGradient.Evaluate(time), gradient.Evaluate(time), 1), true);
-
- // ... but require exactness precicely at key times
- for(int i = 0; i < 5; i++)
- {
- float time = WordToNormalized(gradient.GetColorTime(i));
- CHECK_EQUAL(CompareColors(optGradient.Evaluate(time), gradient.Evaluate(time), 0), true);
- }
- for(int i = 0; i < 3; i++)
- {
- float time = WordToNormalized(gradient.GetAlphaTime(i));
- CHECK_EQUAL(CompareColors(optGradient.Evaluate(time), gradient.Evaluate(time), 0), true);
- }
- #endif
- }
- }
- #endif
- NS_RRP_END
|