powerfun-unity/Assets/AR/VideoPointsSync.cs
2023-04-14 15:51:28 +08:00

93 lines
3.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace Assets.AR
{
public class VideoPoint
{
public float Distance { get; set; }
public float Time { get; set; }
}
public class VideoPointsSync
{
private const float DefaultFps = 29.97f;
protected float[] videoDistances;
protected float[] videoTimes;
protected float fps;
public int Count => this.videoDistances.Length;
public float LastVideoFrame => this.videoTimes[this.videoTimes.Length - 1] * this.fps;
public VideoPointsSync(IEnumerable<VideoPoint> videoPoints, float fps = 29.97f)
{
List<VideoPoint> list = videoPoints.ToList<VideoPoint>();
list.Sort((Comparison<VideoPoint>)((x, y) => x.Distance.CompareTo(y.Distance)));
VideoPoint videoPoint1 = list[0];
for (int index = 1; index < list.Count; ++index)
{
VideoPoint videoPoint2 = list[index];
if ((double)videoPoint2.Distance == (double)videoPoint1.Distance)
{
list.RemoveAt(index);
--index;
}
else
videoPoint1 = videoPoint2;
}
this.videoDistances = list.Select<VideoPoint, float>((Func<VideoPoint, float>)(x => x.Distance)).ToArray<float>();
this.videoTimes = list.Select<VideoPoint, float>((Func<VideoPoint, float>)(x => x.Time)).ToArray<float>();
this.fps = fps;
}
public float GetVideoSpeedAtDistance(float distance)
{
int index = this.IndexOfVideoPointForDistance(distance);
return index == 0 || index == this.Count ? 0.0f : (float)(((double)this.videoDistances[index] - (double)this.videoDistances[index - 1]) / ((double)this.videoTimes[index] - (double)this.videoTimes[index - 1]));
}
public int IndexOfVideoPointForDistance(float distance)
{
int num = Array.BinarySearch<float>(this.videoDistances, distance);
return num < 0 ? ~num : num;
}
public int IndexOfVideoPointForTime(float time)
{
int num = Array.BinarySearch<float>(this.videoTimes, time);
return num < 0 ? ~num : num;
}
public float GetVideoFrameAtDistance(float distance)
{
int index = this.IndexOfVideoPointForDistance(distance);
if (index == 0)
return this.videoTimes[0] * this.fps;
if (index == this.Count)
return this.videoTimes[this.Count - 1] * this.fps;
float t = Mathf.InverseLerp(this.videoDistances[index - 1], this.videoDistances[index], distance);
return Mathf.Lerp(this.videoTimes[index - 1], this.videoTimes[index], t) * this.fps;
}
public float GetDistanceForVideoFrame(float frame)
{
float time = frame / this.fps;
int index = this.IndexOfVideoPointForTime(time);
if (index == 0)
return this.videoDistances[0];
if (index == this.Count)
return this.videoDistances[this.Count - 1];
float t = Mathf.InverseLerp(this.videoTimes[index - 1], this.videoTimes[index], time);
return Mathf.Lerp(this.videoDistances[index - 1], this.videoDistances[index], t);
}
public float AverageVideoSpeed(float startFrame, float endFrame) => (double)startFrame == (double)endFrame ? this.GetVideoSpeedAtDistance(this.GetDistanceForVideoFrame(startFrame)) : (float)(((double)this.GetDistanceForVideoFrame(endFrame) - (double)this.GetDistanceForVideoFrame(startFrame)) * ((double)this.fps / ((double)endFrame - (double)startFrame)));
}
}