Advertisement
Guest User

RPCCurve in XNA

a guest
Mar 2nd, 2011
274
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.31 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using Microsoft.Xna.Framework;
  4.  
  5. namespace Power
  6. {    
  7.     /// <summary>
  8.     /// Represents an XACT RPC curve.
  9.     /// </summary>
  10.     public class RPCCurve
  11.     {
  12.         // X and Y represents X and Y coordinates, Z represents the curve type
  13.         List<Vector3> points = new List<Vector3>();
  14.  
  15.         public RPCCurve()
  16.         {
  17.         }
  18.         public RPCCurve(params Vector3[] points)
  19.         {
  20.             for (int i = 0; i < points.Length; i++)
  21.                 AddPoint(points[i].X, points[i].Y, (int)points[i].Z);
  22.         }
  23.        
  24.         /*
  25.            In a .xap file (the XACT project file) an RPC curve is represented as as bunch of RPC points with something that looks like this:
  26.          
  27.             RPC Point
  28.             {
  29.                 X = 1200.000000;
  30.                 Y = -200.000000;
  31.                 Curve = 3;
  32.             }
  33.          
  34.            The integer for Curve desginates with of the 4 curve functions to use for this point to the next point.
  35.            0 is linear, 1 is fast, 2 is slow, 3 is Sin/Cos  (the same order they appear in the drop down in the XACT RPC Curve GUI).
  36.          
  37.            You can also rip these values directly from the XACT RPC Curve GUI.
  38.            X corresponds to the variable, Y corresponds to the parameter, curve is as described above
  39.            
  40.            Just drop those values straight into this function to add a point to this RPC curve.
  41.         */
  42.         public void AddPoint(float x, float y, int curve)
  43.         {
  44.             points.Add(new Vector3(x, y, curve));
  45.             points.Sort(PointSorter);
  46.         }
  47.  
  48.         // Makes sure the points are sorted correctly
  49.         int PointSorter(Vector3 left, Vector3 right)
  50.         {
  51.             return left.X.CompareTo(right.X);
  52.         }
  53.  
  54.         // gets the y value based on the given X position of the curve
  55.         public float GetY(float xPosition)
  56.         {
  57.             if (xPosition <= points[0].X)
  58.                 return points[0].Y;
  59.             if (xPosition >= points[points.Count - 1].X)
  60.                 return points[points.Count - 1].Y;
  61.  
  62.             // loop over the points to find where this xPosition is contained between
  63.             for (int i = 0; i < points.Count - 1; i++)
  64.             {
  65.                 if (xPosition < points[i].X || xPosition >= points[i + 1].X)
  66.                     continue;
  67.  
  68.                 Vector2 p0 = new Vector2(points[i].X, points[i].Y);
  69.                 Vector2 p1 = new Vector2(points[i + 1].X, points[i + 1].Y);
  70.  
  71.                 int curve = (int)points[i].Z;
  72.  
  73.                 switch (curve)
  74.                 {
  75.                     // Linear interpolation. from wikipedia linear interpolation
  76.                     case 0 :                        
  77.                         return p0.Y + (xPosition - p0.X) * ((p1.Y - p0.Y) / (p1.X - p0.X));
  78.  
  79.                     // Fast interpolation, x^2 with parabola apex at p1. from Kazooie, equation in gmail and DC logs
  80.                     case 1 :                                          
  81.                         return (p0.Y - p1.Y) / (float)Math.Pow(p0.X - p1.X,2) * (float)Math.Pow(xPosition - p1.X, 2) + p1.Y;                                    
  82.  
  83.                     // Slow interpolation, x^2 with parabola apex at p0. from Kazooie, equation in gmail and DC logs
  84.                     case 2 :                                        
  85.                         return (p1.Y - p0.Y) / (float)Math.Pow(p1.X - p0.X,2) * (float)Math.Pow(xPosition - p0.X, 2) + p0.Y;
  86.  
  87.                     // Sin/Cos interpolation. Actually just a quarter of an ellipse and doesn't use sin or cos at all. From Kazooie, equation in gmail and DC logs
  88.                     case 3 :
  89.  
  90.                         // swap the points around as required by the function
  91.                         if (p0.Y > p1.Y)
  92.                         {
  93.                             Vector2 temp = p0;
  94.                             p0 = p1;
  95.                             p1 = temp;
  96.                         }
  97.                        
  98.                         return p0.Y + (p1.Y - p0.Y) * (float)Math.Sqrt((1 - (float)Math.Pow(xPosition - p1.X, 2) / (float)Math.Pow(p1.X - p0.X, 2)));
  99.  
  100.                     // Logarithmic interpolation. Not in XACT, but it's here as a bonus.  From Kazooie, equation in gmail and DC logs
  101.                     case 4:
  102.  
  103.                         float factor1 = 1f;
  104.                         float yAdd1 = p0.Y;
  105.  
  106.                         // swap the points around as required by the function
  107.                         if (p0.Y > p1.Y)
  108.                         {
  109.                             yAdd1 = p0.Y;
  110.                             factor1 = -1;
  111.  
  112.                             float kemp2 = p0.Y;
  113.                             p0.Y = p1.Y;
  114.                             p1.Y = kemp2;
  115.                         }
  116.                        
  117.                         return factor1 * (float)Math.Log(xPosition - p0.X + 1, (float)Math.Exp((float)Math.Log(p1.X - p0.X) / (p1.Y - p0.Y))) + yAdd1;
  118.  
  119.                     // Exponential interpolation. Not in XACT, but it's here as a bonus. From Kazooie, equation in gmail and DC logs
  120.                     case 5:
  121.  
  122.                         float factor2 = 1f;
  123.                         float yAdd2 = p0.Y - 1;
  124.  
  125.                         // swap the points around as required by the function
  126.                         if (p0.Y > p1.Y)
  127.                         {
  128.                             factor2 = -1;
  129.                             yAdd2 = p0.Y + 1;
  130.  
  131.                             float kemp2 = p0.Y;
  132.                             p0.Y = p1.Y;
  133.                             p1.Y = kemp2;
  134.                         }
  135.                        
  136.                         return factor2 * (float)Math.Pow((float)Math.Exp((float)Math.Log(p1.Y - p0.Y + 1) / (p1.X - p0.X)), xPosition - p0.X) + yAdd2;
  137.  
  138.                     default :
  139.                         throw new Exception("Curve value not valid for point: " + curve);
  140.                 }
  141.             }
  142.  
  143.             throw new Exception("RPC curve error, didn't find xPosition on curve: " + xPosition);
  144.  
  145.         }        
  146.  
  147.     }
  148.  
  149.     /// <summary>
  150.     /// Provides static functions to convert XACT values to SoundEffect values
  151.     /// </summary>
  152.     public class XACTToSEConverter
  153.     {
  154.         // converts XACT db levels (-96db to 6db) to SoundEffect volume levels (0 to 1)
  155.         public static float XACTVolumeToSoundEffectVolume(float xactVolume)
  156.         {
  157.             // How was this calculated? I ran the XACT cue at a known db and a SoundEffect at a known volume
  158.             // I then matched the two up using Audacity to work out when the two sounds were playing at the same volume
  159.             // I then graphed a ton of these values and solved the equation in a stats program
  160.             // it took a long, long time to get this function, so enjoy it!
  161.             return 0.98320878f *  (float)Math.Exp(0.11532328f * xactVolume);
  162.         }
  163.         // converts XACT pitch levels (-12 to 12) to SoundEffect pitch levels (-1 to 1)
  164.         public static float XACTPitchToSoundEffectPitch(float xactPitch)
  165.         {
  166.             // XACT does pitch in semi-tones, SoundEffect does it in octaves for some arbitrary reason
  167.             // there are 12 semi-tones in an octave, hence the simple conversion.
  168.             return xactPitch / 12f;
  169.         }
  170.  
  171.     }
  172. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement