Advertisement
Guest User

Untitled

a guest
Dec 11th, 2017
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.66 KB | None | 0 0
  1. using BlamCore.Serialization;
  2. using System;
  3.  
  4. namespace BlamCore.Common
  5. {
  6.     [TagStructure(Size = 0x14)]
  7.     public class TagFunction
  8.     {
  9.         public byte[] Data;
  10.  
  11.         public enum TagFunctionType : byte
  12.         {
  13.             Identity,
  14.             Constant,
  15.             Transition,
  16.             Periodic,
  17.             Linear,
  18.             LinearKey,
  19.             MultiLinearKey,
  20.             Spline,
  21.             MultiSpline,
  22.             Exponent,
  23.             Spline2
  24.         }
  25.  
  26.         [Flags]
  27.         public enum TagFunctionTypeFlag : byte
  28.         {
  29.            HasRange = 1,
  30.            IsBounded = 4,
  31.  
  32.         }
  33.  
  34.         public float ComputeFunction(float input, float scale)
  35.         {
  36.             if (Data == null || Data.Length <= 0)
  37.                 return 0.0f;
  38.  
  39.             else
  40.             {
  41.                 TagFunctionType opcode = (TagFunctionType)Data[0];
  42.                 TagFunctionTypeFlag flags = (TagFunctionTypeFlag)Data[1];
  43.  
  44.                 float result = ComputeSubFunction(0, input, scale);
  45.  
  46.                 if (Data[2] >= 1)
  47.                     return result;
  48.  
  49.                 //Weird
  50.                 return (Data[2] - Data[1]) * result + Data[1];
  51.             }
  52.            
  53.         }
  54.  
  55.         private float ComputeSubFunction(int index, float input, float scale)
  56.         {
  57.             float result = 0.0f;
  58.             float min = 0.0f;
  59.             float max = 0.0f;
  60.  
  61.             TagFunctionType opcode = (TagFunctionType) Data[index];
  62.             TagFunctionTypeFlag flags = (TagFunctionTypeFlag) Data[index + 1];
  63.  
  64.             min = ParseFunctionTypeMin(opcode, input, scale, index);
  65.  
  66.             if (flags.HasFlag(TagFunctionTypeFlag.HasRange))
  67.             {
  68.                 max = ParseFunctionTypeMax(opcode, input, scale, index);
  69.  
  70.                 if (opcode == TagFunctionType.Constant)
  71.                     result = max;
  72.                 else
  73.                     result = ScaleOutput(min, max, scale);
  74.             }
  75.             else
  76.                 result = min;
  77.  
  78.             if (flags.HasFlag(TagFunctionTypeFlag.IsBounded))
  79.                 result = FitToBounds(0, 1, result);
  80.            
  81.             return result;
  82.         }
  83.  
  84.         private float ParseFunctionTypeMin(TagFunctionType type, float input, float scale, int index)
  85.         {
  86.             float result = 0.0f;
  87.             switch (type)
  88.             {
  89.                 case TagFunctionType.Identity:
  90.                     result = input;
  91.                     break;
  92.  
  93.                 case TagFunctionType.Constant:
  94.                     result = 0.0f;
  95.                     break;
  96.  
  97.                 case TagFunctionType.Transition:
  98.                     result = Transition(index + 32, input);
  99.                     break;
  100.  
  101.                 case TagFunctionType.Spline:
  102.                     result = ComputePolynomial(3, GetCoefficients(32, 3), input);
  103.                     break;
  104.  
  105.                 case TagFunctionType.Periodic:
  106.                     result = ComputePolynomial(1, GetCoefficients(32, 1), input);
  107.                     break;
  108.  
  109.                 case TagFunctionType.LinearKey:
  110.                     result = LinearKey(index + 32, input);
  111.                     break;
  112.  
  113.                 default:
  114.                     break;
  115.             }
  116.             return result;
  117.         }
  118.  
  119.         private float ParseFunctionTypeMax(TagFunctionType type, float input, float scale, int index)
  120.         {
  121.             float result = 0.0f;
  122.             switch (type)
  123.             {
  124.                 case TagFunctionType.Identity:
  125.                     result = input;
  126.                     break;
  127.  
  128.                 case TagFunctionType.Constant:
  129.                     result = scale;
  130.                     break;
  131.  
  132.                 case TagFunctionType.Transition:
  133.                     result = Transition(index + 44, input);
  134.                     break;
  135.  
  136.                 case TagFunctionType.Spline:
  137.                     result = ComputePolynomial(3, GetCoefficients(48, 3), input);
  138.                     break;
  139.  
  140.                 case TagFunctionType.Periodic:
  141.                     result = ComputePolynomial(1, GetCoefficients(40, 1), input);
  142.                     break;
  143.  
  144.                 case TagFunctionType.LinearKey:
  145.                     result = LinearKey(index + 112, input);
  146.                     break;
  147.  
  148.                 default:
  149.                     break;
  150.             }
  151.             return result;
  152.         }
  153.  
  154.         private float Transition(int index, float value)
  155.         {
  156.             float max = GetFloatFromBytes(index + 8);
  157.             float min = GetFloatFromBytes(index + 4);
  158.  
  159.             float scale = 0.0f; // another function call
  160.  
  161.             return (max - min) * scale + min;
  162.         }
  163.  
  164.         private float LinearKey(int index, float value)
  165.         {
  166.             float a = value - GetFloatFromBytes(index + 36) * GetFloatFromBytes(index + 52);
  167.             float b = value - GetFloatFromBytes(index + 40) * GetFloatFromBytes(index + 56);
  168.             float c = value - GetFloatFromBytes(index + 44) * GetFloatFromBytes(index + 60);
  169.             a = FitToBounds(0, 1, a);
  170.             b = FitToBounds(0, 1, b);
  171.             c = FitToBounds(0, 1, c);
  172.  
  173.             return GetFloatFromBytes(index + 68) * a + GetFloatFromBytes(index + 64)+ GetFloatFromBytes(index+72)*b + GetFloatFromBytes(index+76)*c;
  174.         }
  175.  
  176.         private float[] GetCoefficients(int index,int order)
  177.         {
  178.             float[] coefficients = new float[order + 1];
  179.             for(int i = 0; i <= order; i++)
  180.             {
  181.                 coefficients[order - i] = GetFloatFromBytes(index + 4 * i);
  182.             }
  183.             return coefficients;
  184.         }
  185.  
  186.         private float ComputePolynomial(int order, float[] coefficients, float x)
  187.         {
  188.             float result = 0.0f;
  189.  
  190.             if (coefficients.Length != order + 1)
  191.                 return result;
  192.  
  193.             for(int i =0;i<=order; i++)
  194.                 result = result + (float)Math.Pow(x, i) * coefficients[i];
  195.  
  196.             return result;
  197.         }
  198.  
  199.         private float GetFloatFromBytes(int index)
  200.         {
  201.             byte[] temp = new byte[4];
  202.             Array.Copy(Data, index, temp, 0, 4);
  203.             Array.Reverse(temp);
  204.             return BitConverter.ToSingle(temp, index);
  205.         }
  206.  
  207.         private float FitToBounds(float min, float max, float value)
  208.         {
  209.             if (value < min)
  210.                 return min;
  211.             else if (max - value < 0.0f)
  212.                 return max;
  213.             else
  214.                 return value;
  215.         }
  216.  
  217.         private float ScaleOutput(float min, float max, float scale)
  218.         {
  219.             return (max - min) * scale + min;
  220.         }
  221.  
  222.     }
  223.    
  224. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement