93 lines
3.8 KiB
C#
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)));
|
|
}
|
|
}
|