ar帧数匹配精准度问题
This commit is contained in:
1 parent
e3059fc1c2
commit
9552fed2e0
57 files changed
+852691
-1
No files matched your search
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 328b5d62a858984408481bbfd6024557
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using DG.Tweening;
|
||||||
|
|
||||||
|
namespace Assets.AR
|
||||||
|
{
|
||||||
|
public class ARLaneObject : ARObject
|
||||||
|
{
|
||||||
|
public Vector3 Lean { get; set; }//偏移量
|
||||||
|
|
||||||
|
public int StartPosition;
|
||||||
|
|
||||||
|
public bool IsAtFinish { get; set; }//是否到达终点
|
||||||
|
|
||||||
|
public float RouteDistance { get; set; }//线路上的距离
|
||||||
|
|
||||||
|
public float Lane { get; set; }//车道上的位置
|
||||||
|
|
||||||
|
public float BaseOffset { get; set; }//基准偏移量
|
||||||
|
|
||||||
|
public float DeltaLane { get; set; }//
|
||||||
|
|
||||||
|
public float LaneWidth { get; set; }//车道宽度
|
||||||
|
|
||||||
|
public float Speed { get; set; }//速度
|
||||||
|
|
||||||
|
public float Curvature { get; set; }//转向
|
||||||
|
|
||||||
|
public float LaneChangingDirection { get; set; }//方向
|
||||||
|
|
||||||
|
public float LaneCamera { get; set; }//车道上摄像机的位置
|
||||||
|
|
||||||
|
public float DistanceSort { get; set; }//距离排序
|
||||||
|
|
||||||
|
public float FrameIndexDistanceCorrection { get; set; }//位置纠正
|
||||||
|
|
||||||
|
public double TestPower = 500;
|
||||||
|
|
||||||
|
|
||||||
|
//重置碰撞检测参数
|
||||||
|
public void ResetCollisionDetectionParameters()
|
||||||
|
{
|
||||||
|
this.StartPosition = 0;//开始位置
|
||||||
|
this.Lane = 0.0f;//轨迹上的距离
|
||||||
|
this.DeltaLane = 0.0f;//差距
|
||||||
|
this.LaneWidth = 0.0f;//轨迹宽度
|
||||||
|
this.LaneCamera = 0.0f;//轨迹上摄像头的位置
|
||||||
|
this.DistanceSort = 0.0f;//距离上的远近
|
||||||
|
this.Curvature = 0.0f;//角度
|
||||||
|
this.LaneChangingDirection = 0.0f;//偏转方向
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新人物的位置和转向
|
||||||
|
public override void UpdateTransform()
|
||||||
|
{
|
||||||
|
PositionOffset = Vector3.up * route.CameraHeight * (-1);
|
||||||
|
Quaternion cameraRotation = this.GetCameraRotation(this.frame - this.FrameIndexDistanceCorrection);
|
||||||
|
Vector3 filteredCameraPosition = this.GetFilteredCameraPosition(this.frame + this.FrameIndexDistanceCorrection);
|
||||||
|
|
||||||
|
|
||||||
|
Debug.Log($"{filteredCameraPosition}={this.CameraPositionOffset}:{this.Route.GetFilteredCameraPosition(this.frame )}");
|
||||||
|
|
||||||
|
Vector3 vector3 = Vector3.left * (this.route.LeftHanded ? -1f : 1f) * (this.LaneWidth * (this.Lane + this.LaneCamera) - this.BaseOffset);
|
||||||
|
this.transform.position = filteredCameraPosition + cameraRotation * (vector3 + this.PositionOffset);
|
||||||
|
this.transform.rotation = cameraRotation * Quaternion.Euler(this.RotationOffset) * Quaternion.Euler(this.Lean);
|
||||||
|
this.transform.localScale = this.Scale;
|
||||||
|
|
||||||
|
var animator = GetComponent<Animator>();
|
||||||
|
animator.SetFloat("speed", 30);
|
||||||
|
animator.SetFloat("power", (float)TestPower);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c83121d82f416c345a6250c354717a41
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets.AR
|
||||||
|
{
|
||||||
|
public abstract class ARLaneObjectsController : ARObjectsController
|
||||||
|
{
|
||||||
|
protected const float LaneWidth = 0.7f;
|
||||||
|
protected const float StartRegionDistance = 200f;
|
||||||
|
private const float StartRowsGap = 2.2f;
|
||||||
|
private const float StartRowsRandomDistance = 0.4f;
|
||||||
|
private const float StartRowsRandomWidth = 0.15f;
|
||||||
|
private const float MinCollisionDistance = 1.33f;
|
||||||
|
protected readonly Dictionary<int, ARLaneObject> riderObjects = new Dictionary<int, ARLaneObject>();
|
||||||
|
private readonly Dictionary<int, Vector2> randomizedStartOffsets = new Dictionary<int, Vector2>();
|
||||||
|
private readonly List<ARLaneObject> collisionList = new List<ARLaneObject>();
|
||||||
|
|
||||||
|
public bool AllowStartOrder { get; set; } = true;
|
||||||
|
|
||||||
|
protected float StartRegionRouteWidth { get; private set; }
|
||||||
|
|
||||||
|
protected int RiderCountInStartRow { get; private set; }
|
||||||
|
|
||||||
|
public float OvertakingThreshold { get; set; } = 5f;
|
||||||
|
|
||||||
|
public bool NearViewMode { get; set; }
|
||||||
|
|
||||||
|
public int FollowedRiderId { get; set; }
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<int, ARLaneObject> ArRiders => (IReadOnlyDictionary<int, ARLaneObject>)this.riderObjects;
|
||||||
|
|
||||||
|
protected virtual void Start()
|
||||||
|
{
|
||||||
|
float frame = 100f;
|
||||||
|
this.StartRegionRouteWidth = this.GetRouteLeftOffset(frame) + this.GetRouteRightOffset(frame);
|
||||||
|
this.RiderCountInStartRow = Mathf.Max(1, Mathf.CeilToInt(this.StartRegionRouteWidth / 0.7f));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateObjects(
|
||||||
|
float videoFrame,
|
||||||
|
float visibilityRear,
|
||||||
|
float visibilityFront)
|
||||||
|
{
|
||||||
|
base.UpdateObjects(videoFrame, visibilityRear, visibilityFront);//控制3d物体显示隐藏
|
||||||
|
if (this.Route == null || this.videoSync == null)
|
||||||
|
return;
|
||||||
|
this.DetectRidersCollisions(this.CameraDistance);//计算3d物体的位置和转向
|
||||||
|
}
|
||||||
|
//检测碰撞
|
||||||
|
private void DetectRidersCollisions(float cameraDistance)
|
||||||
|
{
|
||||||
|
float num1 = cameraDistance - ARObject.MaxDistanceVisibilityModels;
|
||||||
|
float num2 = cameraDistance + ARObject.MaxDistanceVisibilityModels;
|
||||||
|
this.collisionList.Clear();
|
||||||
|
foreach (ARLaneObject arLaneObject in this.riderObjects.Values)
|
||||||
|
{
|
||||||
|
if (arLaneObject.gameObject.activeSelf && !arLaneObject.IsAtFinish)
|
||||||
|
{
|
||||||
|
if ((double)arLaneObject.Distance >= (double)num1 && (double)arLaneObject.Distance <= (double)num2)
|
||||||
|
{
|
||||||
|
this.collisionList.Add(arLaneObject);
|
||||||
|
arLaneObject.DistanceSort = arLaneObject.Distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (ARLaneObject collision in this.collisionList)
|
||||||
|
{
|
||||||
|
if ((double)collision.RouteDistance < 200.0)
|
||||||
|
{
|
||||||
|
collision.Distance = this.GetModelRouteDistance(collision.StartPosition, collision.RouteDistance);
|
||||||
|
collision.DistanceSort = collision.Distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.collisionList.Sort((Comparison<ARLaneObject>)((r1, r2) =>
|
||||||
|
{
|
||||||
|
int num3 = r1.Lane.CompareTo(r2.Lane);
|
||||||
|
if (num3 == 0)
|
||||||
|
num3 = r2.DistanceSort.CompareTo(r1.DistanceSort);
|
||||||
|
return num3;
|
||||||
|
}));
|
||||||
|
float deltaTime = Time.deltaTime;
|
||||||
|
for (int index = 0; index < this.collisionList.Count; ++index)
|
||||||
|
{
|
||||||
|
ARLaneObject collision = this.collisionList[index];
|
||||||
|
float lane = collision.Lane;
|
||||||
|
float num4 = this.GetLane(collision.RouteDistance, collision.DistanceSort, index);
|
||||||
|
if ((double)collision.LaneWidth != 0.0)
|
||||||
|
{
|
||||||
|
float num5 = 0.02f * deltaTime * Mathf.Log(collision.Speed + 5f, 1.1f);
|
||||||
|
num4 = Mathf.Clamp(num4, lane - num5, lane + num5 * 1.5f);
|
||||||
|
collision.DeltaLane = (num4 - lane) / deltaTime;
|
||||||
|
}
|
||||||
|
collision.Lane = num4;
|
||||||
|
}
|
||||||
|
this.CalculateOvertakingParameters();
|
||||||
|
foreach (ARLaneObject collision in this.collisionList)
|
||||||
|
{
|
||||||
|
collision.LaneWidth = 0.7f;
|
||||||
|
float num6 = this.Route.LeftHanded ? this.GetRouteLeftOffset(collision.Frame) : this.GetRouteRightOffset(collision.Frame);
|
||||||
|
float num7 = Mathf.Lerp(this.GetStartOffset(collision.StartPosition).x, 0.0f, collision.Distance / 200f);
|
||||||
|
collision.BaseOffset = num6 + num7;
|
||||||
|
}
|
||||||
|
this.CalculateCameraAvoidance(cameraDistance);
|
||||||
|
}
|
||||||
|
//摄像机障碍物避免
|
||||||
|
private void CalculateCameraAvoidance(float cameraDistance)
|
||||||
|
{
|
||||||
|
float deltaTime = Time.deltaTime;
|
||||||
|
for (int index = 0; index < this.collisionList.Count; ++index)
|
||||||
|
{
|
||||||
|
ARLaneObject collision = this.collisionList[index];
|
||||||
|
bool flag1 = collision.StartPosition == this.FollowedRiderId;
|
||||||
|
float x = Math.Abs(collision.Distance - cameraDistance);
|
||||||
|
float x2 = 4f;
|
||||||
|
if (this.NearViewMode && !flag1)
|
||||||
|
x2 = 5.5f;
|
||||||
|
if ((double)x > (double)x2)
|
||||||
|
{
|
||||||
|
if ((double)collision.LaneCamera > 0.0)
|
||||||
|
collision.LaneCamera = Mathf.Max(0.0f, collision.LaneCamera - deltaTime);
|
||||||
|
else if ((double)collision.LaneCamera < 0.0)
|
||||||
|
collision.LaneCamera = Mathf.Min(0.0f, collision.LaneCamera + deltaTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float num1 = VTMath.Lerp(0.0f, 1f, x2, 0.0f, x);
|
||||||
|
float num2 = collision.Lane * collision.LaneWidth - collision.BaseOffset;
|
||||||
|
float num3 = 0.75f;
|
||||||
|
if (this.NearViewMode && !flag1)
|
||||||
|
{
|
||||||
|
num2 += num3 / 2f;
|
||||||
|
num3 *= 1.5f;
|
||||||
|
}
|
||||||
|
bool flag2 = (double)collision.LaneCamera < 0.0 || (double)collision.LaneCamera <= 0.0 && (double)num2 < 0.0;
|
||||||
|
float a1 = (float)(-(double)num2 - (double)num1 * (double)num3) / collision.LaneWidth;
|
||||||
|
float a2 = (num1 * num3 - num2) / collision.LaneWidth;
|
||||||
|
if (this.NearViewMode & flag1)
|
||||||
|
{
|
||||||
|
float num4 = Mathf.Max(a1 - collision.LaneCamera, -deltaTime);
|
||||||
|
collision.LaneCamera = Mathf.Min(collision.LaneCamera + num4, -1.401298E-45f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
collision.LaneCamera = !flag2 ? Mathf.Max(a2, float.Epsilon) : Mathf.Min(a1, -1.401298E-45f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateOvertakingParameters()
|
||||||
|
{
|
||||||
|
float deltaTime = Time.deltaTime;
|
||||||
|
foreach (ARLaneObject laneObject in this.riderObjects.Values)
|
||||||
|
{
|
||||||
|
float num1 = laneObject.Speed * deltaTime;
|
||||||
|
if ((double)num1 == 0.0)
|
||||||
|
{
|
||||||
|
laneObject.Curvature = 0.0f;
|
||||||
|
laneObject.LaneChangingDirection = 0.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float num2 = (this.Route.LeftHanded ? -1f : 1f) * laneObject.DeltaLane * laneObject.LaneWidth * deltaTime;
|
||||||
|
if ((double)laneObject.LaneCamera != 0.0)
|
||||||
|
num2 = 0.0f;
|
||||||
|
float curvature = 0.0f;
|
||||||
|
if ((double)num1 > 0.0)
|
||||||
|
{
|
||||||
|
float num3 = Mathf.Atan(num2 / num1);
|
||||||
|
curvature = (float)(0.039999999105930328 * (double)VTMath.Lerp(0.0f, 3f, 20f, 1f, laneObject.Speed)) * num3;
|
||||||
|
}
|
||||||
|
this.UpdateRiderCurvature(laneObject, curvature, deltaTime);
|
||||||
|
float angle = -57.29578f * Mathf.Atan(num2 / num1);
|
||||||
|
this.UpdateLaneChangingDirection(laneObject, angle, deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateRiderCurvature(ARLaneObject laneObject, float curvature, float deltaTime)
|
||||||
|
{
|
||||||
|
float num = 6f;
|
||||||
|
laneObject.Curvature = Mathf.Lerp(laneObject.Curvature, curvature, num * deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateLaneChangingDirection(
|
||||||
|
ARLaneObject laneObject,
|
||||||
|
float angle,
|
||||||
|
float deltaTime)
|
||||||
|
{
|
||||||
|
float num = 10f * deltaTime;
|
||||||
|
laneObject.LaneChangingDirection = Mathf.Clamp(angle, laneObject.LaneChangingDirection - num, laneObject.LaneChangingDirection + num);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float GetLane(float routeDistance, float modelDistance, int count = -1)
|
||||||
|
{
|
||||||
|
if (count == -1)
|
||||||
|
count = this.collisionList.Count;
|
||||||
|
float overtakingThreshold = this.GetOvertakingThreshold(routeDistance);
|
||||||
|
float b = 0.0f;
|
||||||
|
for (int index = count - 1; index >= 0; --index)
|
||||||
|
{
|
||||||
|
ARLaneObject collision = this.collisionList[index];
|
||||||
|
if ((double)collision.Lane + 1.0 >= (double)b)
|
||||||
|
{
|
||||||
|
float collisionParameter = ARLaneObjectsController.GetCollisionParameter(modelDistance, collision.DistanceSort, overtakingThreshold);
|
||||||
|
if ((double)collisionParameter > 0.0)
|
||||||
|
b = Mathf.Max(collision.Lane + collisionParameter, b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float GetOvertakingThreshold(float routeDistance)
|
||||||
|
{
|
||||||
|
float b = this.OvertakingThreshold;
|
||||||
|
if (this.AllowStartOrder && (double)routeDistance < 200.0)
|
||||||
|
b = Mathf.Lerp(1.33f, b, routeDistance / 200f);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 GetStartOffset(int atIndex)
|
||||||
|
{
|
||||||
|
Vector2 startOffset;
|
||||||
|
if (this.randomizedStartOffsets.TryGetValue(atIndex, out startOffset))
|
||||||
|
return startOffset;
|
||||||
|
startOffset = new Vector2(UnityEngine.Random.Range(-0.15f, 0.15f), UnityEngine.Random.Range(-0.4f, 0.4f));
|
||||||
|
this.randomizedStartOffsets.Add(atIndex, startOffset);
|
||||||
|
return startOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetModelRouteDistance(int startPosition, float routeDistance)
|
||||||
|
{
|
||||||
|
if (!this.AllowStartOrder || (double)routeDistance >= 200.0)
|
||||||
|
return routeDistance;
|
||||||
|
float num = Mathf.Lerp((float)((double)(RiderCountInStartRow == 0 ? 0 :(startPosition - 1) / this.RiderCountInStartRow) * 2.2000000476837158 + 6.0) + this.GetStartOffset(startPosition).y, 0.0f, routeDistance / 200f);
|
||||||
|
return routeDistance + num;
|
||||||
|
}
|
||||||
|
|
||||||
|
//计算碰撞距离
|
||||||
|
protected static float GetCollisionParameter(
|
||||||
|
float distSource,
|
||||||
|
float distOther,
|
||||||
|
float maxDistance)
|
||||||
|
{
|
||||||
|
float x = distSource - distOther;
|
||||||
|
if ((double)x < 0.0)
|
||||||
|
x = -x;
|
||||||
|
if ((double)x < 1.0)
|
||||||
|
return 1f;
|
||||||
|
return (double)x > (double)maxDistance ? 0.0f : VTMath.SmoothStep(1f, 1f, maxDistance, 0.0f, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float GetRouteLeftOffset(float frame) => this.Route == null ? 0.0f : this.Route.GetLeftSideOffset(frame);
|
||||||
|
|
||||||
|
private float GetRouteRightOffset(float frame) => this.Route == null ? 0.0f : this.Route.GetRightSideOffset(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: beab89ef5c7a65d4693d9b8b472bb0d1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Rendering;
|
||||||
|
|
||||||
|
namespace Assets.AR
|
||||||
|
{
|
||||||
|
public static class ARMeshFactory
|
||||||
|
{
|
||||||
|
private static bool IsValidVertex(Vector3 v) => !float.IsNaN(v.x) && !float.IsInfinity(v.x) && !float.IsNaN(v.y) && !float.IsInfinity(v.y) && !float.IsNaN(v.z) && !float.IsInfinity(v.z);
|
||||||
|
//创建轨迹
|
||||||
|
public static GameObject CreateTrajectory(
|
||||||
|
ARRoute route,
|
||||||
|
int segment,
|
||||||
|
float lOffset,
|
||||||
|
float rOffset,
|
||||||
|
float margin = float.NaN)
|
||||||
|
{
|
||||||
|
int start;
|
||||||
|
int end;
|
||||||
|
route.GetSlamSegmentRange(segment, out start, out end);
|
||||||
|
int num1 = end - start + 1;
|
||||||
|
int[] indices = new int[(num1 - 1) * 6];
|
||||||
|
Vector3[] vector3Array1 = new Vector3[num1 * 2];
|
||||||
|
Vector3 left;
|
||||||
|
Vector3 right;
|
||||||
|
ARMeshFactory.CreateVertices(start, route, lOffset, rOffset, out left, out right, margin);
|
||||||
|
vector3Array1[0] = left;
|
||||||
|
vector3Array1[1] = right;
|
||||||
|
int num2 = 2;
|
||||||
|
int num3 = 0;
|
||||||
|
for (int frame = start + 1; frame <= end; ++frame)
|
||||||
|
{
|
||||||
|
ARMeshFactory.CreateVertices(frame, route, lOffset, rOffset, out left, out right, margin);
|
||||||
|
if (ARMeshFactory.IsValidVertex(left) && ARMeshFactory.IsValidVertex(right))
|
||||||
|
{
|
||||||
|
Vector3[] vector3Array2 = vector3Array1;
|
||||||
|
int index1 = num2;
|
||||||
|
int num4 = index1 + 1;
|
||||||
|
Vector3 vector3_1 = left;
|
||||||
|
vector3Array2[index1] = vector3_1;
|
||||||
|
Vector3[] vector3Array3 = vector3Array1;
|
||||||
|
int index2 = num4;
|
||||||
|
num2 = index2 + 1;
|
||||||
|
Vector3 vector3_2 = right;
|
||||||
|
vector3Array3[index2] = vector3_2;
|
||||||
|
int[] numArray1 = indices;
|
||||||
|
int index3 = num3;
|
||||||
|
int num5 = index3 + 1;
|
||||||
|
int num6 = num2 - 3;
|
||||||
|
numArray1[index3] = num6;
|
||||||
|
int[] numArray2 = indices;
|
||||||
|
int index4 = num5;
|
||||||
|
int num7 = index4 + 1;
|
||||||
|
int num8 = num2 - 4;
|
||||||
|
numArray2[index4] = num8;
|
||||||
|
int[] numArray3 = indices;
|
||||||
|
int index5 = num7;
|
||||||
|
int num9 = index5 + 1;
|
||||||
|
int num10 = num2 - 1;
|
||||||
|
numArray3[index5] = num10;
|
||||||
|
int[] numArray4 = indices;
|
||||||
|
int index6 = num9;
|
||||||
|
int num11 = index6 + 1;
|
||||||
|
int num12 = num2 - 4;
|
||||||
|
numArray4[index6] = num12;
|
||||||
|
int[] numArray5 = indices;
|
||||||
|
int index7 = num11;
|
||||||
|
int num13 = index7 + 1;
|
||||||
|
int num14 = num2 - 2;
|
||||||
|
numArray5[index7] = num14;
|
||||||
|
int[] numArray6 = indices;
|
||||||
|
int index8 = num13;
|
||||||
|
num3 = index8 + 1;
|
||||||
|
int num15 = num2 - 1;
|
||||||
|
numArray6[index8] = num15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Mesh mesh = new Mesh();
|
||||||
|
mesh.vertices = vector3Array1;
|
||||||
|
mesh.indexFormat = IndexFormat.UInt32;
|
||||||
|
mesh.SetIndices(indices, MeshTopology.Triangles, 0);
|
||||||
|
GameObject trajectory = new GameObject(string.Format("Segment {0}", (object)segment), new System.Type[3]
|
||||||
|
{
|
||||||
|
typeof (MeshFilter),
|
||||||
|
typeof (MeshRenderer),
|
||||||
|
typeof (MeshCollider)
|
||||||
|
});
|
||||||
|
trajectory.GetComponent<MeshFilter>().sharedMesh = mesh;
|
||||||
|
trajectory.GetComponent<MeshCollider>().sharedMesh = trajectory.GetComponent<MeshFilter>().sharedMesh;
|
||||||
|
return trajectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateVertices(
|
||||||
|
int frame,
|
||||||
|
ARRoute route,
|
||||||
|
float lOffset,
|
||||||
|
float rOffset,
|
||||||
|
out Vector3 left,
|
||||||
|
out Vector3 right,
|
||||||
|
float margin = float.NaN)
|
||||||
|
{
|
||||||
|
Quaternion trajectoryOrientationAt = route.GetTrajectoryOrientationAt(frame);
|
||||||
|
Vector3 vector3 = route.GetCameraPositionAt(frame) - trajectoryOrientationAt * Vector3.up * route.CameraHeight;
|
||||||
|
if ((double)lOffset == 0.0)
|
||||||
|
lOffset = route.GetLeftSideOffset((float)frame);
|
||||||
|
if (float.IsNaN(margin))
|
||||||
|
lOffset += route.RouteMargin;
|
||||||
|
else
|
||||||
|
lOffset += margin;
|
||||||
|
left = vector3 + trajectoryOrientationAt * Vector3.left * lOffset;
|
||||||
|
if ((double)rOffset == 0.0)
|
||||||
|
rOffset = route.GetRightSideOffset((float)frame);
|
||||||
|
if (float.IsNaN(margin))
|
||||||
|
rOffset += route.RouteMargin;
|
||||||
|
else
|
||||||
|
rOffset += margin;
|
||||||
|
right = vector3 - trajectoryOrientationAt * Vector3.left * rOffset;
|
||||||
|
left.y = right.y = vector3.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6ed86df267dfdd249bbec364a3c88ac9
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,178 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets.AR
|
||||||
|
{
|
||||||
|
public class ARObject : MonoBehaviour
|
||||||
|
{
|
||||||
|
public string Hash;
|
||||||
|
public const int Layer = 9;
|
||||||
|
public const int TestRidersLayer = 10;
|
||||||
|
public static float MaxDistanceVisibilityModels = 80f;
|
||||||
|
public const float VisibilityHidingTime = 0.2f;
|
||||||
|
public const float VisibilityHidingeRange = 0.5f;
|
||||||
|
protected VideoPointsSync videoSync { get; set; }
|
||||||
|
protected ARRoute route { get; set; }
|
||||||
|
public float frame;
|
||||||
|
private float lastVisibilityLevel;
|
||||||
|
public float distance;
|
||||||
|
private int nextTimeDefIndex;
|
||||||
|
protected bool useMultilapTransform;
|
||||||
|
public Vector3 PositionOffset = Vector3.zero;
|
||||||
|
public Vector3 RotationOffset = Vector3.zero;
|
||||||
|
public Vector3 Scale = Vector3.one;
|
||||||
|
|
||||||
|
private float FrameRate = 29.97f;
|
||||||
|
|
||||||
|
public string CustomUrl { get; set; }
|
||||||
|
|
||||||
|
public string ArName { get; set; }
|
||||||
|
|
||||||
|
public Vector3 CameraPositionOffset { get; set; }
|
||||||
|
|
||||||
|
public float Frame => !this.useMultilapTransform ? this.frame : this.frame + this.videoSync.LastVideoFrame;
|
||||||
|
|
||||||
|
public float VisibilityLevel { get; protected set; }
|
||||||
|
|
||||||
|
public float ManualVisibility { get; set; }
|
||||||
|
|
||||||
|
public ARRoute Route
|
||||||
|
{
|
||||||
|
get => this.route;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (this.route == value)
|
||||||
|
return;
|
||||||
|
this.route = value;
|
||||||
|
this.SetFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public VideoPointsSync VideoSync
|
||||||
|
{
|
||||||
|
get => this.videoSync;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (this.videoSync == value)
|
||||||
|
return;
|
||||||
|
this.videoSync = value;
|
||||||
|
this.SetFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Distance
|
||||||
|
{
|
||||||
|
get => this.distance;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if ((double)this.distance == (double)value)
|
||||||
|
return;
|
||||||
|
this.distance = value;
|
||||||
|
this.SetFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void UpdateTransform()
|
||||||
|
{
|
||||||
|
if (this.Route == null)
|
||||||
|
return;
|
||||||
|
Quaternion cameraRotation = this.GetCameraRotation(this.frame);
|
||||||
|
Vector3 filteredCameraPosition = this.GetFilteredCameraPosition(this.frame);
|
||||||
|
this.transform.rotation = cameraRotation * Quaternion.Euler(this.RotationOffset);
|
||||||
|
this.transform.position = filteredCameraPosition + cameraRotation * this.PositionOffset;
|
||||||
|
this.transform.localScale = this.Scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void UpdateOffsets()
|
||||||
|
{
|
||||||
|
if (this.Route == null || this.VideoSync == null)
|
||||||
|
return;
|
||||||
|
Quaternion quaternion = Quaternion.Inverse(this.GetCameraRotation(this.frame));
|
||||||
|
Vector3 filteredCameraPosition = this.GetFilteredCameraPosition(this.frame);
|
||||||
|
this.RotationOffset = (quaternion * this.transform.rotation).eulerAngles;
|
||||||
|
this.PositionOffset = quaternion * (this.transform.position - filteredCameraPosition);
|
||||||
|
this.Scale = this.transform.localScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateVisibility(
|
||||||
|
float videoFrame,
|
||||||
|
float visibilityRear,
|
||||||
|
float visibilityFront,
|
||||||
|
bool multiLap)
|
||||||
|
{
|
||||||
|
if ((double)this.ManualVisibility > 0.0)
|
||||||
|
{
|
||||||
|
visibilityFront = this.ManualVisibility;
|
||||||
|
visibilityRear = this.ManualVisibility;
|
||||||
|
}
|
||||||
|
float deltaVisibility = Time.deltaTime * 5f;
|
||||||
|
float a = this.GetVisibilityParameter(this.frame, videoFrame, visibilityRear, visibilityFront, deltaVisibility);
|
||||||
|
if (multiLap && (double)a <= 0.0)
|
||||||
|
{
|
||||||
|
float visibilityParameter = this.GetVisibilityParameter(this.frame + this.videoSync.LastVideoFrame, videoFrame, visibilityRear, visibilityFront, deltaVisibility);
|
||||||
|
a = Mathf.Max(a, visibilityParameter);
|
||||||
|
if ((double)a > 0.0)
|
||||||
|
this.useMultilapTransform = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this.useMultilapTransform = false;
|
||||||
|
this.VisibilityLevel = a;
|
||||||
|
this.lastVisibilityLevel = this.VisibilityLevel;
|
||||||
|
}
|
||||||
|
protected virtual void Update()
|
||||||
|
{
|
||||||
|
if (this.Route == null || this.VideoSync == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.UpdateTransform();
|
||||||
|
}
|
||||||
|
protected virtual void Awake()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
protected Quaternion GetCameraRotation(float frame) => this.Route.GetTrajectoryOrientation(this.useMultilapTransform ? frame + this.videoSync.LastVideoFrame : frame);
|
||||||
|
|
||||||
|
protected Vector3 GetFilteredCameraPosition(float frame) => this.Route.GetFilteredCameraPosition(this.useMultilapTransform ? frame + this.videoSync.LastVideoFrame : frame) - this.CameraPositionOffset;
|
||||||
|
|
||||||
|
private void SetFrame()
|
||||||
|
{
|
||||||
|
if (this.Route == null || this.VideoSync == null)
|
||||||
|
return;
|
||||||
|
this.frame = this.VideoSync.GetVideoFrameAtDistance(this.Distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float GetVisibilityParameter(
|
||||||
|
float objectFrame,
|
||||||
|
float videoFrame,
|
||||||
|
float visibilityRear,
|
||||||
|
float visibilityFront,
|
||||||
|
float deltaVisibility)
|
||||||
|
{
|
||||||
|
if ((double)objectFrame < (double)videoFrame - (double)visibilityRear)
|
||||||
|
return 0.0f;
|
||||||
|
if ((double)visibilityFront <= 0.0)
|
||||||
|
return 1f;
|
||||||
|
if ((double)this.ManualVisibility == -1.0)
|
||||||
|
return Mathf.Clamp(0.0f, this.lastVisibilityLevel - deltaVisibility, this.lastVisibilityLevel + deltaVisibility);
|
||||||
|
float num1;
|
||||||
|
if ((double)objectFrame > (double)videoFrame)
|
||||||
|
{
|
||||||
|
float num2 = (float)((double)videoFrame + (double)visibilityFront - 0.5 * (double)this.FrameRate);
|
||||||
|
float num3 = videoFrame + visibilityFront;
|
||||||
|
num1 = 1f - Mathf.Clamp01((float)(((double)objectFrame - (double)num2) / ((double)num3 - (double)num2)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float num4 = videoFrame - visibilityRear;
|
||||||
|
float num5 = (float)((double)videoFrame - (double)visibilityRear + 0.5 * (double)this.FrameRate);
|
||||||
|
num1 = Mathf.Clamp01((float)(((double)objectFrame - (double)num4) / ((double)num5 - (double)num4)));
|
||||||
|
}
|
||||||
|
return Mathf.Clamp(num1, this.lastVisibilityLevel - deltaVisibility, this.lastVisibilityLevel + deltaVisibility);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dbf584e2324021741a949900752a8650
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Assets.AR
|
||||||
|
{
|
||||||
|
public enum ARObjectType
|
||||||
|
{
|
||||||
|
Sign,
|
||||||
|
Box,
|
||||||
|
Sphere,
|
||||||
|
SplitGate,
|
||||||
|
FinishGate,
|
||||||
|
Bariccade,
|
||||||
|
Custom,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum RiderCameraDistance
|
||||||
|
{
|
||||||
|
FirstPerson,
|
||||||
|
Near,
|
||||||
|
Middle,
|
||||||
|
Far,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum VideoControlMode
|
||||||
|
{
|
||||||
|
Front,
|
||||||
|
AutoPanorama,
|
||||||
|
Rear,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0a289f05c09632e48b90c9f12837743a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
using RenderHeads.Media.AVProVideo;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Rendering;
|
||||||
|
|
||||||
|
namespace Assets.AR
|
||||||
|
{
|
||||||
|
public abstract class ARObjectsController : MonoBehaviour
|
||||||
|
{
|
||||||
|
public float MaximumVisibilityDistance = 200f;
|
||||||
|
private readonly Vector3 CameraOriginOffset = Vector3.up * -100f;
|
||||||
|
protected static readonly Vector3 DefaultObjectPosition = new Vector3(0.0f, 1000f, 0.0f);
|
||||||
|
protected List<ARObject> arObjects = new List<ARObject>();
|
||||||
|
protected Material matShadow { get; set; }
|
||||||
|
protected Material matModelMask;
|
||||||
|
protected AVProVideoPlayer videoPlayer { get; set; }
|
||||||
|
protected VideoPointsSync videoSync{ get; set; }
|
||||||
|
protected Vector3 cameraPositionOffset { get; set; }
|
||||||
|
private GameObject panoramaObject;
|
||||||
|
private Material panoramaMaterial;
|
||||||
|
private Material skyboxMaterialBackup;
|
||||||
|
protected GameObject trajectoryObject;
|
||||||
|
private float ambientIntensity;
|
||||||
|
private GameObject camGo;
|
||||||
|
protected Dictionary<int, ARObjectsController.Segment> trajectorySegments = new Dictionary<int, ARObjectsController.Segment>();
|
||||||
|
protected int lapCount = 1;
|
||||||
|
protected double lapLength;
|
||||||
|
|
||||||
|
public bool AR360Version { get; private set; }
|
||||||
|
|
||||||
|
public Camera UnityCamera { get; protected set; }
|
||||||
|
|
||||||
|
public float FrameIndexDistanceCorrection { get; set; }
|
||||||
|
|
||||||
|
public ARRoute Route { get; private set; }
|
||||||
|
|
||||||
|
protected float CameraDistance { get; private set; }
|
||||||
|
|
||||||
|
public float TargetCameraDistance { get; private set; }
|
||||||
|
|
||||||
|
public Camera PanoramaCamera { get; private set; }
|
||||||
|
|
||||||
|
public bool PassedPanorama { get; set; }
|
||||||
|
|
||||||
|
public bool IsMultilap => this.lapCount > 1;
|
||||||
|
|
||||||
|
protected virtual void Awake()
|
||||||
|
{
|
||||||
|
this.ambientIntensity = RenderSettings.ambientIntensity;
|
||||||
|
this.matShadow = Resources.Load<Material>("UI/Material/TransparentPlane");
|
||||||
|
//this.matModelMask = Resources.Load<Material>("Materials/ModelDepth");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void SetupCamera()
|
||||||
|
{
|
||||||
|
this.camGo = new GameObject("ARCamera");
|
||||||
|
this.camGo.transform.parent = this.transform;
|
||||||
|
this.UnityCamera = this.camGo.AddComponent<Camera>();
|
||||||
|
this.UnityCamera.cullingMask = 512;
|
||||||
|
this.UnityCamera.clearFlags = CameraClearFlags.Nothing;
|
||||||
|
this.UnityCamera.depth = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SetArRoute(ARRoute route, VideoPointsSync videoSync,AVProVideoPlayer mediaPlayer)
|
||||||
|
{
|
||||||
|
videoPlayer = mediaPlayer;
|
||||||
|
this.Route = route;
|
||||||
|
this.videoSync = videoSync;
|
||||||
|
if (this.Route.CameraRotationsRear != null && this.Route.CameraRotationsRear.Length == this.Route.CameraRotations.Length)
|
||||||
|
{
|
||||||
|
this.AR360Version = true;
|
||||||
|
ARObject.MaxDistanceVisibilityModels = 200f;
|
||||||
|
this.MaximumVisibilityDistance = 500f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.AR360Version = false;
|
||||||
|
ARObject.MaxDistanceVisibilityModels = 80f;
|
||||||
|
this.MaximumVisibilityDistance = 200f;
|
||||||
|
}
|
||||||
|
if (route == null)
|
||||||
|
return;
|
||||||
|
foreach (ARObject arObject in this.arObjects)
|
||||||
|
{
|
||||||
|
arObject.VideoSync = videoSync;
|
||||||
|
arObject.Route = route;
|
||||||
|
}
|
||||||
|
this.trajectoryObject = new GameObject("TrajectoryMesh");
|
||||||
|
this.trajectoryObject.transform.parent = this.transform;
|
||||||
|
this.trajectoryObject.layer = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdateObjects(
|
||||||
|
float videoFrame,
|
||||||
|
float visibilityRear,
|
||||||
|
float visibilityFront)
|
||||||
|
{
|
||||||
|
foreach (ARObject arObject in this.arObjects)
|
||||||
|
{
|
||||||
|
arObject.CameraPositionOffset = this.cameraPositionOffset;
|
||||||
|
if (arObject is ARLaneObject arLaneObject)
|
||||||
|
arLaneObject.FrameIndexDistanceCorrection = this.FrameIndexDistanceCorrection;
|
||||||
|
|
||||||
|
{
|
||||||
|
arObject.UpdateVisibility(videoFrame, visibilityRear, visibilityFront, this.IsMultilap);
|
||||||
|
bool flag = this.IsArObjectActive(arObject);
|
||||||
|
//arObject.gameObject.SetActive(flag); TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual bool IsArObjectActive(ARObject arObject) => (double)arObject.VisibilityLevel > 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
protected virtual Material GetTrajectoryMaterial() => this.matShadow;
|
||||||
|
|
||||||
|
|
||||||
|
protected virtual void Update()
|
||||||
|
{
|
||||||
|
if (this.Route == null)
|
||||||
|
return;
|
||||||
|
this.arObjects.Clear();
|
||||||
|
this.arObjects.AddRange(FindObjectsOfType<ARObject>());
|
||||||
|
float num1 = this.videoPlayer.CurrentFrame - (float)this.Route.VideoFrameOffset;
|
||||||
|
{
|
||||||
|
this.cameraPositionOffset = this.Route.GetCameraPosition(num1) - this.CameraOriginOffset;
|
||||||
|
Camera.main.transform.position = this.CameraOriginOffset;
|
||||||
|
Camera.main.transform.rotation = this.Route.GetCameraRotation(num1);
|
||||||
|
this.Route.SetCameraProjection(num1, Camera.main);
|
||||||
|
}
|
||||||
|
this.CameraDistance = this.videoSync.GetDistanceForVideoFrame(num1 + this.FrameIndexDistanceCorrection);
|
||||||
|
float num2 = Mathf.Min(float.MaxValue, this.Route.GetVisibility(num1));
|
||||||
|
float num3 = num2;
|
||||||
|
float visibilityRear = 200f;
|
||||||
|
if ((double)num3 == 0.0)
|
||||||
|
num3 = 600f;
|
||||||
|
if ((double)visibilityRear == 0.0)
|
||||||
|
visibilityRear = 600f;
|
||||||
|
this.UpdateTrajectory(num1, num3);//更新轨迹
|
||||||
|
this.UpdateObjects(num1, visibilityRear, num3);//更新骑手等位置
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//更新当前可见轨迹
|
||||||
|
private void UpdateTrajectory(float frame, float defaultVisibility)
|
||||||
|
{
|
||||||
|
int start;
|
||||||
|
int end;
|
||||||
|
this.Route.GetVisibleSlamSegments((int)frame, out start, out end, defaultVisibility);
|
||||||
|
List<int> intList = new List<int>();
|
||||||
|
foreach (int key in this.trajectorySegments.Keys)
|
||||||
|
{
|
||||||
|
if (key < start || key > end)
|
||||||
|
intList.Add(key);
|
||||||
|
}
|
||||||
|
foreach (int key in intList)
|
||||||
|
{
|
||||||
|
UnityEngine.Object.Destroy((UnityEngine.Object)this.trajectorySegments[key].GameObject);
|
||||||
|
this.trajectorySegments.Remove(key);
|
||||||
|
}
|
||||||
|
for (int index = start; index <= end; ++index)
|
||||||
|
{
|
||||||
|
if (!this.trajectorySegments.ContainsKey(index))
|
||||||
|
{
|
||||||
|
GameObject trajectory = this.CreateTrajectory(index, 0.0f, 0.0f);
|
||||||
|
ARObjectsController.Segment segment = new ARObjectsController.Segment(trajectory, trajectory.transform.position);
|
||||||
|
this.trajectorySegments.Add(index, segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (int key in this.trajectorySegments.Keys)
|
||||||
|
{
|
||||||
|
ARObjectsController.Segment trajectorySegment = this.trajectorySegments[key];
|
||||||
|
trajectorySegment.GameObject.transform.position = trajectorySegment.Position - this.cameraPositionOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建轨迹
|
||||||
|
protected virtual GameObject CreateTrajectory(
|
||||||
|
int segment,
|
||||||
|
float lOffset,
|
||||||
|
float rOffset,
|
||||||
|
float margin = float.NaN)
|
||||||
|
{
|
||||||
|
GameObject trajectory = ARMeshFactory.CreateTrajectory(this.Route, segment, lOffset, rOffset, margin);
|
||||||
|
trajectory.transform.parent = this.trajectoryObject.transform;
|
||||||
|
trajectory.layer = 9;
|
||||||
|
trajectory.GetComponent<MeshRenderer>().shadowCastingMode = ShadowCastingMode.Off;
|
||||||
|
trajectory.GetComponent<MeshRenderer>().material = this.GetTrajectoryMaterial();
|
||||||
|
return trajectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Vector3 GetCameraPosition(float frame) => this.Route.GetCameraPosition(frame) - this.cameraPositionOffset;
|
||||||
|
|
||||||
|
public class Segment
|
||||||
|
{
|
||||||
|
public GameObject GameObject;
|
||||||
|
public Vector3 Position;
|
||||||
|
|
||||||
|
public Segment(GameObject gameObject, Vector3 position)
|
||||||
|
{
|
||||||
|
this.GameObject = gameObject;
|
||||||
|
this.Position = position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3d565e7e3c0027f41836c0210a05072c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,578 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Rendering;
|
||||||
|
|
||||||
|
namespace Assets
|
||||||
|
{
|
||||||
|
public class ARRoute
|
||||||
|
{
|
||||||
|
private const float ProjectionSmoothFrames = 30f;
|
||||||
|
private const float DefaultNearSideOffset = 0.0f;
|
||||||
|
private const float DefaultFarSideOffset = 4f;
|
||||||
|
public int[] LeftSideOffsetFrames;
|
||||||
|
public float[] LeftSideOffsets;
|
||||||
|
public int[] RightSideOffsetFrames;
|
||||||
|
public float[] RightSideOffsets;
|
||||||
|
public bool RearMode;
|
||||||
|
|
||||||
|
public ARRoute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ARRoute(ARRouteData data) => this.LoadData(data);
|
||||||
|
|
||||||
|
public int[] Visibility { get; set; }
|
||||||
|
|
||||||
|
public Vector3[] CameraPositions { get; set; }
|
||||||
|
|
||||||
|
public Vector3[] FilteredCameraPositions { get; set; }
|
||||||
|
|
||||||
|
public double[] FrameDistances { get; set; }
|
||||||
|
|
||||||
|
public Quaternion[] CameraRotations { get; set; }
|
||||||
|
|
||||||
|
public Quaternion[] CameraRotationsRear { get; set; }
|
||||||
|
|
||||||
|
public Quaternion[] TrajectoryOrientation { get; set; }
|
||||||
|
|
||||||
|
public float[] TrajectoryCurvatures { get; set; }
|
||||||
|
|
||||||
|
public float[] LightRotationFrames { get; set; }
|
||||||
|
|
||||||
|
public Quaternion[] LightRotations { get; set; }
|
||||||
|
|
||||||
|
public float[] ShadowIntensityFrames { get; set; }
|
||||||
|
|
||||||
|
public float[] ShadowIntensities { get; set; }
|
||||||
|
|
||||||
|
public SphericalHarmonicsL2[] SphericalHarmonics { get; set; }
|
||||||
|
|
||||||
|
public int[] SlamSegments { get; set; }
|
||||||
|
|
||||||
|
public CameraProjectionParameters[] ProjectionParameters { get; set; }
|
||||||
|
|
||||||
|
public bool LeftHanded { get; set; }
|
||||||
|
|
||||||
|
public int VideoFrameOffset { get; set; }
|
||||||
|
|
||||||
|
public float CameraHeight { get; set; }
|
||||||
|
|
||||||
|
public float RiderScale { get; set; } = 1f;
|
||||||
|
|
||||||
|
public float RouteMargin { get; private set; } = 2f;
|
||||||
|
|
||||||
|
public bool HasLeftSideOffsets => this.LeftSideOffsetFrames != null && this.LeftSideOffsets != null;
|
||||||
|
|
||||||
|
public bool HasRightSideOffsets => this.RightSideOffsetFrames != null && this.RightSideOffsets != null;
|
||||||
|
|
||||||
|
public int FrameCount => this.CameraPositions.Length;
|
||||||
|
|
||||||
|
public double Lenght => this.FrameDistances[this.FrameCount - 1];
|
||||||
|
|
||||||
|
private float DefaultLeftSideOffset => !this.LeftHanded ? 4f : 0.0f;
|
||||||
|
|
||||||
|
private float DefaultRightSideOffset => !this.LeftHanded ? 0.0f : 4f;
|
||||||
|
|
||||||
|
public int GetVisibilityAt(int frame)
|
||||||
|
{
|
||||||
|
if (this.Visibility == null || this.Visibility.Length == 0)
|
||||||
|
return 0;
|
||||||
|
if (frame <= 0)
|
||||||
|
return this.Visibility[0];
|
||||||
|
return frame >= this.Visibility.Length ? this.Visibility[this.Visibility.Length - 1] : this.Visibility[frame];
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetVisibility(float frame)
|
||||||
|
{
|
||||||
|
if (this.Visibility == null || this.Visibility.Length == 0)
|
||||||
|
return 0.0f;
|
||||||
|
int index = (int)Math.Ceiling((double)frame);
|
||||||
|
if (index <= 0)
|
||||||
|
return (float)this.Visibility[0];
|
||||||
|
if (index >= this.Visibility.Length)
|
||||||
|
return (float)this.Visibility[this.Visibility.Length - 1];
|
||||||
|
float t = frame - (float)(index - 1);
|
||||||
|
return Mathf.Lerp((float)this.Visibility[index - 1], (float)this.Visibility[index], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 GetCameraPositionAt(int frame)
|
||||||
|
{
|
||||||
|
if (frame <= 0)
|
||||||
|
return this.CameraPositions[0];
|
||||||
|
return frame >= this.FrameCount ? this.CameraPositions[this.CameraPositions.Length - 1] : this.CameraPositions[frame];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 GetCameraPosition(float frame)
|
||||||
|
{
|
||||||
|
int index = (int)Math.Ceiling((double)frame);
|
||||||
|
if (index <= 0)
|
||||||
|
return this.CameraPositions[0];
|
||||||
|
if (index >= this.FrameCount)
|
||||||
|
return this.CameraPositions[this.CameraPositions.Length - 1];
|
||||||
|
float t = frame - (float)(index - 1);
|
||||||
|
return Vector3.Lerp(this.CameraPositions[index - 1], this.CameraPositions[index], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 GetFilteredCameraPositionAt(int frame)
|
||||||
|
{
|
||||||
|
if (frame <= 0)
|
||||||
|
return this.FilteredCameraPositions[0];
|
||||||
|
return frame >= this.FrameCount ? this.FilteredCameraPositions[this.FilteredCameraPositions.Length - 1] : this.FilteredCameraPositions[frame];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 GetFilteredCameraPosition(float frame)
|
||||||
|
{
|
||||||
|
int index = (int)Math.Ceiling((double)frame);
|
||||||
|
if (index <= 0)
|
||||||
|
return this.FilteredCameraPositions[0];
|
||||||
|
if (index >= this.FrameCount)
|
||||||
|
return this.FilteredCameraPositions[this.FilteredCameraPositions.Length - 1];
|
||||||
|
float t = frame - (float)(index - 1);
|
||||||
|
return Vector3.Lerp(this.FilteredCameraPositions[index - 1], this.FilteredCameraPositions[index], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion GetCameraRotationAt(int frame)
|
||||||
|
{
|
||||||
|
if (frame <= 0)
|
||||||
|
return this.CameraRotations[0];
|
||||||
|
return frame >= this.FrameCount ? this.CameraRotations[this.CameraRotations.Length - 1] : this.CameraRotations[frame];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion GetCameraRotation(float frame)
|
||||||
|
{
|
||||||
|
int index = (int)Math.Ceiling((double)frame);
|
||||||
|
if (index <= 0)
|
||||||
|
return this.CameraRotations[0];
|
||||||
|
if (index >= this.FrameCount)
|
||||||
|
return this.CameraRotations[this.CameraRotations.Length - 1];
|
||||||
|
float t = frame - (float)(index - 1);
|
||||||
|
return Quaternion.Slerp(this.CameraRotations[index - 1], this.CameraRotations[index], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion GetCameraRotationRear(float frame)
|
||||||
|
{
|
||||||
|
int index = (int)Math.Ceiling((double)frame);
|
||||||
|
if (index <= 0)
|
||||||
|
return this.CameraRotationsRear[0];
|
||||||
|
if (index >= this.FrameCount)
|
||||||
|
return this.CameraRotationsRear[this.CameraRotationsRear.Length - 1];
|
||||||
|
float t = frame - (float)(index - 1);
|
||||||
|
return Quaternion.Slerp(this.CameraRotationsRear[index - 1], this.CameraRotationsRear[index], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetSlamSegmentIndex(float frame)
|
||||||
|
{
|
||||||
|
for (int index = 1; index < this.SlamSegments.Length; ++index)
|
||||||
|
{
|
||||||
|
if ((double)this.SlamSegments[index] > (double)frame)
|
||||||
|
return index - 1;
|
||||||
|
}
|
||||||
|
return this.SlamSegments.Length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetSlamSegmentRange(int index, out int start, out int end)
|
||||||
|
{
|
||||||
|
index = Mathf.Clamp(index, 0, this.SlamSegments.Length - 1);
|
||||||
|
start = this.SlamSegments[index];
|
||||||
|
if (index < this.SlamSegments.Length - 1)
|
||||||
|
end = this.SlamSegments[index + 1];
|
||||||
|
else
|
||||||
|
end = this.FrameCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetVisibleSlamSegments(
|
||||||
|
int frame,
|
||||||
|
out int start,
|
||||||
|
out int end,
|
||||||
|
float defultVisibility = 0.0f)
|
||||||
|
{
|
||||||
|
float num = (float)this.GetVisibilityAt(frame);
|
||||||
|
if ((double)num == 0.0)
|
||||||
|
num = defultVisibility;
|
||||||
|
start = this.GetSlamSegmentIndex((float)frame);
|
||||||
|
end = this.GetSlamSegmentIndex((float)frame + num);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double GetFrameAtDistance(double distance)
|
||||||
|
{
|
||||||
|
double[] frameDistances = this.FrameDistances;
|
||||||
|
int index = Array.BinarySearch<double>(frameDistances, distance);
|
||||||
|
if (index < 0)
|
||||||
|
index = ~index;
|
||||||
|
if (index == 0)
|
||||||
|
return 0.0;
|
||||||
|
if (index == frameDistances.Length)
|
||||||
|
return (double)(frameDistances.Length - 1);
|
||||||
|
double num = VTMath.InverseLerp(frameDistances[index - 1], frameDistances[index], distance);
|
||||||
|
return (double)index + num - 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double GetDistanceForFrame(double frame)
|
||||||
|
{
|
||||||
|
int index = (int)Math.Ceiling(frame);
|
||||||
|
if (index <= 0)
|
||||||
|
return this.FrameDistances[0];
|
||||||
|
if (index >= this.FrameCount)
|
||||||
|
return this.FrameDistances[this.FrameDistances.Length - 1];
|
||||||
|
double t = frame - (double)(index - 1);
|
||||||
|
return VTMath.Lerp(this.FrameDistances[index - 1], this.FrameDistances[index], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CameraProjectionParameters GetCameraProjectionParameters(
|
||||||
|
float frame)
|
||||||
|
{
|
||||||
|
int index = Mathf.Clamp(this.GetSlamSegmentIndex(frame), 0, this.ProjectionParameters.Length - 1);
|
||||||
|
CameraProjectionParameters projectionParameter1 = this.ProjectionParameters[index];
|
||||||
|
int slamSegment1 = this.SlamSegments[index];
|
||||||
|
if (index > 0 && (double)frame < (double)slamSegment1 + 15.0)
|
||||||
|
{
|
||||||
|
float t = (float)(0.5 + ((double)frame - (double)slamSegment1) / 30.0);
|
||||||
|
return CameraProjectionParameters.Lerp(this.ProjectionParameters[index - 1], projectionParameter1, t);
|
||||||
|
}
|
||||||
|
if (index < this.SlamSegments.Length - 1)
|
||||||
|
{
|
||||||
|
int slamSegment2 = this.SlamSegments[index + 1];
|
||||||
|
if ((double)frame > (double)slamSegment2 - 15.0)
|
||||||
|
{
|
||||||
|
float t = (float)(0.5 - ((double)slamSegment2 - (double)frame) / 30.0);
|
||||||
|
CameraProjectionParameters projectionParameter2 = this.ProjectionParameters[index + 1];
|
||||||
|
return CameraProjectionParameters.Lerp(projectionParameter1, projectionParameter2, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return projectionParameter1;
|
||||||
|
}
|
||||||
|
//设置摄像机投影矩阵
|
||||||
|
public void SetCameraProjection(float frame, Camera camera, bool fitInside = false)
|
||||||
|
{
|
||||||
|
CameraProjectionParameters projectionParameters = this.GetCameraProjectionParameters(frame);
|
||||||
|
if ((double)projectionParameters.alpha == 0.0)
|
||||||
|
return;
|
||||||
|
float num1 = projectionParameters.cx / projectionParameters.cy;
|
||||||
|
float num2 = (float)Screen.width / (float)Screen.height;
|
||||||
|
float cx = projectionParameters.cx;
|
||||||
|
float cy = projectionParameters.cy;
|
||||||
|
if (fitInside)
|
||||||
|
{
|
||||||
|
if ((double)num2 > (double)num1)
|
||||||
|
cx = cy * num2;
|
||||||
|
if ((double)num2 < (double)num1)
|
||||||
|
cy = cx * 1f / num2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((double)num2 < (double)num1)
|
||||||
|
cx = cy * num2;
|
||||||
|
if ((double)num2 > (double)num1)
|
||||||
|
cy = cx * 1f / num2;
|
||||||
|
}
|
||||||
|
camera.projectionMatrix = this.GetCameraProjectionMatrix(projectionParameters.alpha, projectionParameters.beta, cx, cy, camera.nearClipPlane, camera.farClipPlane);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Matrix4x4 GetCameraProjectionMatrix(
|
||||||
|
float alpha,
|
||||||
|
float beta,
|
||||||
|
float cx,
|
||||||
|
float cy,
|
||||||
|
float nearClipPlane,
|
||||||
|
float farClipPlane)
|
||||||
|
{
|
||||||
|
Matrix4x4 projectionMatrix = new Matrix4x4();
|
||||||
|
float z = (float)(-((double)farClipPlane + (double)nearClipPlane) / ((double)farClipPlane - (double)nearClipPlane));
|
||||||
|
float w = (float)(-2.0 * (double)farClipPlane * (double)nearClipPlane / ((double)farClipPlane - (double)nearClipPlane));
|
||||||
|
projectionMatrix.SetRow(0, new Vector4(alpha / cx, 0.0f, 0.0f, 0.0f));
|
||||||
|
projectionMatrix.SetRow(1, new Vector4(0.0f, beta / cy, 0.0f, 0.0f));
|
||||||
|
projectionMatrix.SetRow(2, new Vector4(0.0f, 0.0f, z, w));
|
||||||
|
projectionMatrix.SetRow(3, new Vector4(0.0f, 0.0f, -1f, 0.0f));
|
||||||
|
return projectionMatrix;
|
||||||
|
}
|
||||||
|
//处理摄像机3d位置
|
||||||
|
public void CreateFilteredCameraPositions()
|
||||||
|
{
|
||||||
|
int length = this.CameraPositions.Length;
|
||||||
|
Vector3[] vector3Array = new Vector3[length];
|
||||||
|
for (int index = 0; index < length; ++index)
|
||||||
|
vector3Array[index] = this.CameraPositions[index];
|
||||||
|
for (int index1 = 0; index1 < 3; ++index1)
|
||||||
|
{
|
||||||
|
for (int index2 = 1; index2 < vector3Array.Length - 1; ++index2)
|
||||||
|
vector3Array[index2] = (vector3Array[index2 - 1] + vector3Array[index2] + vector3Array[index2 + 1]) / 3f;
|
||||||
|
}
|
||||||
|
this.FilteredCameraPositions = vector3Array;
|
||||||
|
}
|
||||||
|
//创建摄像机在3d空间的距离
|
||||||
|
private void CreateFrameDistances()
|
||||||
|
{
|
||||||
|
int length = this.CameraPositions.Length;
|
||||||
|
this.FrameDistances = new double[length];
|
||||||
|
this.FrameDistances[0] = 0.0;
|
||||||
|
double num = 0.0;
|
||||||
|
for (int index = 1; index < length; ++index)
|
||||||
|
{
|
||||||
|
num += (double)Vector3.Distance(this.CameraPositions[index - 1], this.CameraPositions[index]);
|
||||||
|
this.FrameDistances[index] = num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建轨迹上的转向
|
||||||
|
public void CreateTrajectoryOrientations()
|
||||||
|
{
|
||||||
|
Quaternion[] quaternionArray = new Quaternion[this.FilteredCameraPositions.Length];
|
||||||
|
for (int index = 1; index < this.FilteredCameraPositions.Length - 1; ++index)
|
||||||
|
quaternionArray[index] = Quaternion.LookRotation(this.FilteredCameraPositions[index + 1] - this.FilteredCameraPositions[index - 1], Vector3.up);
|
||||||
|
quaternionArray[0] = quaternionArray[1];
|
||||||
|
quaternionArray[this.FilteredCameraPositions.Length - 1] = quaternionArray[this.FilteredCameraPositions.Length - 2];
|
||||||
|
this.TrajectoryOrientation = quaternionArray;
|
||||||
|
}
|
||||||
|
//获取轨迹上某帧的转向
|
||||||
|
public Quaternion GetTrajectoryOrientationAt(int frame)
|
||||||
|
{
|
||||||
|
int index = Mathf.Clamp(frame, 0, this.FrameCount);
|
||||||
|
if (index <= 0)
|
||||||
|
return this.TrajectoryOrientation[0];
|
||||||
|
return index >= this.FrameCount ? this.TrajectoryOrientation[this.TrajectoryOrientation.Length - 1] : this.TrajectoryOrientation[index];
|
||||||
|
}
|
||||||
|
//鬼区轨迹上模糊帧的转向
|
||||||
|
public Quaternion GetTrajectoryOrientation(float frame)
|
||||||
|
{
|
||||||
|
frame = Mathf.Clamp(frame, 0.0f, (float)this.FrameCount);
|
||||||
|
int index = (int)Math.Ceiling((double)frame);
|
||||||
|
if (index <= 0)
|
||||||
|
return this.TrajectoryOrientation[0];
|
||||||
|
if (index >= this.FrameCount)
|
||||||
|
return this.TrajectoryOrientation[this.TrajectoryOrientation.Length - 1];
|
||||||
|
float t = frame - (float)(index - 1);
|
||||||
|
return Quaternion.Slerp(this.TrajectoryOrientation[index - 1], this.TrajectoryOrientation[index], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetTrajectoryCurvature(float frame)
|
||||||
|
{
|
||||||
|
int index = (int)Math.Ceiling((double)frame);
|
||||||
|
if (index <= 0)
|
||||||
|
return this.TrajectoryCurvatures[0];
|
||||||
|
if (index >= this.FrameCount)
|
||||||
|
return this.TrajectoryCurvatures[this.TrajectoryCurvatures.Length - 1];
|
||||||
|
float t = frame - (float)(index - 1);
|
||||||
|
return Mathf.Lerp(this.TrajectoryCurvatures[index - 1], this.TrajectoryCurvatures[index], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion GetLightDirection(float distance)
|
||||||
|
{
|
||||||
|
if (this.LightRotations == null || this.LightRotations.Length == 0)
|
||||||
|
return Quaternion.Euler(new Vector3(90f, 0.0f, 0.0f));
|
||||||
|
int index1 = 0;
|
||||||
|
for (int index2 = 0; index2 < this.LightRotationFrames.Length; ++index2)
|
||||||
|
{
|
||||||
|
if ((double)this.LightRotationFrames[index2] < (double)distance)
|
||||||
|
index1 = index2;
|
||||||
|
}
|
||||||
|
if (index1 + 1 == this.LightRotations.Length)
|
||||||
|
return this.LightRotations[this.LightRotations.Length - 1];
|
||||||
|
float t = Mathf.InverseLerp(this.LightRotationFrames[index1], this.LightRotationFrames[index1 + 1], distance);
|
||||||
|
return Quaternion.Slerp(this.LightRotations[index1], this.LightRotations[index1 + 1], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetShadowIntensity(float distance)
|
||||||
|
{
|
||||||
|
if (this.ShadowIntensities == null || this.ShadowIntensities.Length == 0)
|
||||||
|
return 1f;
|
||||||
|
int index1 = 0;
|
||||||
|
for (int index2 = 0; index2 < this.ShadowIntensityFrames.Length; ++index2)
|
||||||
|
{
|
||||||
|
if ((double)this.ShadowIntensityFrames[index2] < (double)distance)
|
||||||
|
index1 = index2;
|
||||||
|
}
|
||||||
|
if (index1 + 1 == this.ShadowIntensities.Length)
|
||||||
|
return this.ShadowIntensities[this.ShadowIntensities.Length - 1];
|
||||||
|
float t = Mathf.InverseLerp(this.ShadowIntensityFrames[index1], this.ShadowIntensityFrames[index1 + 1], distance);
|
||||||
|
return Mathf.Lerp(this.ShadowIntensities[index1], this.ShadowIntensities[index1 + 1], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetLeftSideOffset(float frame)
|
||||||
|
{
|
||||||
|
if (!this.HasLeftSideOffsets)
|
||||||
|
return this.DefaultLeftSideOffset;
|
||||||
|
int index = Array.BinarySearch<int>(this.LeftSideOffsetFrames, (int)Math.Ceiling((double)frame));
|
||||||
|
if (index < 0)
|
||||||
|
index = ~index;
|
||||||
|
if (index == 0)
|
||||||
|
return this.LeftSideOffsets[0];
|
||||||
|
if (index == this.LeftSideOffsetFrames.Length)
|
||||||
|
return this.LeftSideOffsets[this.LeftSideOffsetFrames.Length - 1];
|
||||||
|
float t = Mathf.InverseLerp((float)this.LeftSideOffsetFrames[index - 1], (float)this.LeftSideOffsetFrames[index], frame);
|
||||||
|
return Mathf.Lerp(this.LeftSideOffsets[index - 1], this.LeftSideOffsets[index], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetRightSideOffset(float frame)
|
||||||
|
{
|
||||||
|
if (!this.HasRightSideOffsets)
|
||||||
|
return this.DefaultRightSideOffset;
|
||||||
|
int index = Array.BinarySearch<int>(this.RightSideOffsetFrames, (int)Math.Ceiling((double)frame));
|
||||||
|
if (index < 0)
|
||||||
|
index = ~index;
|
||||||
|
if (index == 0)
|
||||||
|
return this.RightSideOffsets[0];
|
||||||
|
if (index == this.RightSideOffsetFrames.Length)
|
||||||
|
return this.RightSideOffsets[this.RightSideOffsetFrames.Length - 1];
|
||||||
|
float t = Mathf.InverseLerp((float)this.RightSideOffsetFrames[index - 1], (float)this.RightSideOffsetFrames[index], frame);
|
||||||
|
return Mathf.Lerp(this.RightSideOffsets[index - 1], this.RightSideOffsets[index], t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadData(ARRouteData data)
|
||||||
|
{
|
||||||
|
this.Visibility = data.Visibility;
|
||||||
|
this.VideoFrameOffset = data.VideoFrameOffset;
|
||||||
|
this.LeftHanded = data.LeftHanded;
|
||||||
|
this.SlamSegments = data.SlamSegments;
|
||||||
|
this.CameraHeight = data.CameraHeight;
|
||||||
|
this.RiderScale = (double)data.RiderScale != 0.0 ? data.RiderScale : 1f;
|
||||||
|
this.CameraPositions = ((IEnumerable<VectorData>)data.CameraPositions).Select<VectorData, Vector3>((Func<VectorData, Vector3>)(x => x.ToUnityVector())).ToArray<Vector3>();
|
||||||
|
this.ProjectionParameters = data.CameraProjectionParameters;
|
||||||
|
this.CameraRotations = ((IEnumerable<VectorData>)data.CameraRotations).Select<VectorData, Quaternion>((Func<VectorData, Quaternion>)(x => Quaternion.Euler(x.ToUnityVector()))).ToArray<Quaternion>();
|
||||||
|
VectorData[] cameraRotationsRear = data.CameraRotationsRear;
|
||||||
|
this.CameraRotationsRear = cameraRotationsRear != null ? ((IEnumerable<VectorData>)cameraRotationsRear).Select<VectorData, Quaternion>((Func<VectorData, Quaternion>)(x => Quaternion.Euler(x.ToUnityVector()))).ToArray<Quaternion>() : (Quaternion[])null;
|
||||||
|
this.LeftSideOffsetFrames = data.LeftSideOffsetFrames;
|
||||||
|
this.LeftSideOffsets = data.LeftSideOffsets;
|
||||||
|
this.RightSideOffsetFrames = data.RightSideOffsetFrames;
|
||||||
|
this.RightSideOffsets = data.RightSideOffsets;
|
||||||
|
if (data.LightRotationFrames == null || data.LightRotationFrames.Length == 0)
|
||||||
|
{
|
||||||
|
this.LightRotationFrames = new float[0];
|
||||||
|
this.LightRotations = new Quaternion[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.LightRotations = ((IEnumerable<VectorData>)data.LightRotations).Select<VectorData, Quaternion>((Func<VectorData, Quaternion>)(x => Quaternion.Euler(x.ToUnityVector()))).ToArray<Quaternion>();
|
||||||
|
this.LightRotationFrames = data.LightRotationFrames;
|
||||||
|
}
|
||||||
|
if (data.ShadowIntensityFrames == null || data.ShadowIntensityFrames.Length == 0)
|
||||||
|
{
|
||||||
|
this.ShadowIntensityFrames = new float[0];
|
||||||
|
this.ShadowIntensities = new float[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.ShadowIntensities = data.ShadowIntensities;
|
||||||
|
this.ShadowIntensityFrames = data.ShadowIntensityFrames;
|
||||||
|
}
|
||||||
|
this.SphericalHarmonics = this.LoadSphericalHarmonics(data.SphericalHarmonics);
|
||||||
|
this.CreateFilteredCameraPositions();
|
||||||
|
this.CreateFrameDistances();
|
||||||
|
this.CreateTrajectoryOrientations();
|
||||||
|
this.CreateTrajectoryCurvatures();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ARRouteData ToARRouteData()
|
||||||
|
{
|
||||||
|
ARRouteData arRouteData = new ARRouteData();
|
||||||
|
arRouteData.Visibility = this.Visibility;
|
||||||
|
arRouteData.VideoFrameOffset = this.VideoFrameOffset;
|
||||||
|
arRouteData.LeftHanded = this.LeftHanded;
|
||||||
|
arRouteData.SlamSegments = this.SlamSegments;
|
||||||
|
arRouteData.CameraHeight = this.CameraHeight;
|
||||||
|
arRouteData.RiderScale = (double)this.RiderScale != 0.0 ? this.RiderScale : 1f;
|
||||||
|
arRouteData.CameraPositions = ((IEnumerable<Vector3>)this.CameraPositions).Select<Vector3, VectorData>((Func<Vector3, VectorData>)(x => new VectorData(x))).ToArray<VectorData>();
|
||||||
|
arRouteData.CameraProjectionParameters = this.ProjectionParameters;
|
||||||
|
arRouteData.CameraRotations = ((IEnumerable<Quaternion>)this.CameraRotations).Select<Quaternion, VectorData>((Func<Quaternion, VectorData>)(x => new VectorData(x.eulerAngles))).ToArray<VectorData>();
|
||||||
|
arRouteData.LeftSideOffsetFrames = this.LeftSideOffsetFrames;
|
||||||
|
arRouteData.LeftSideOffsets = this.LeftSideOffsets;
|
||||||
|
arRouteData.RightSideOffsetFrames = this.RightSideOffsetFrames;
|
||||||
|
arRouteData.RightSideOffsets = this.RightSideOffsets;
|
||||||
|
if (this.LightRotationFrames == null || this.LightRotationFrames.Length == 0)
|
||||||
|
{
|
||||||
|
arRouteData.LightRotationFrames = new float[0];
|
||||||
|
arRouteData.LightRotations = ((IEnumerable<Quaternion>)new Quaternion[0]).Select<Quaternion, VectorData>((Func<Quaternion, VectorData>)(x => new VectorData(x.eulerAngles))).ToArray<VectorData>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arRouteData.LightRotations = ((IEnumerable<Quaternion>)this.LightRotations).Select<Quaternion, VectorData>((Func<Quaternion, VectorData>)(x => new VectorData(x.eulerAngles))).ToArray<VectorData>();
|
||||||
|
arRouteData.LightRotationFrames = this.LightRotationFrames;
|
||||||
|
}
|
||||||
|
if (this.ShadowIntensityFrames == null || this.ShadowIntensityFrames.Length == 0)
|
||||||
|
{
|
||||||
|
arRouteData.ShadowIntensityFrames = new float[1];
|
||||||
|
arRouteData.ShadowIntensities = new float[1] { 1f };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arRouteData.ShadowIntensities = this.ShadowIntensities;
|
||||||
|
arRouteData.ShadowIntensityFrames = this.ShadowIntensityFrames;
|
||||||
|
}
|
||||||
|
arRouteData.SphericalHarmonics = this.StoreSphericalHarmonics(this.SphericalHarmonics);
|
||||||
|
return arRouteData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SphericalHarmonicsL2[] LoadSphericalHarmonics(float[] coefficients)
|
||||||
|
{
|
||||||
|
if (coefficients == null || coefficients.Length == 0)
|
||||||
|
return (SphericalHarmonicsL2[])null;
|
||||||
|
if (coefficients.Length % 27 != 0)
|
||||||
|
throw new ArgumentException("An array of SH coefficients must be divisible by 27.");
|
||||||
|
int num = 0;
|
||||||
|
SphericalHarmonicsL2[] sphericalHarmonicsL2Array = new SphericalHarmonicsL2[coefficients.Length / 27];
|
||||||
|
for (int index = 0; index < coefficients.Length / 27; ++index)
|
||||||
|
{
|
||||||
|
for (int rgb = 0; rgb < 3; ++rgb)
|
||||||
|
{
|
||||||
|
for (int coefficient = 0; coefficient < 9; ++coefficient)
|
||||||
|
sphericalHarmonicsL2Array[index][rgb, coefficient] = coefficients[num++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sphericalHarmonicsL2Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float[] StoreSphericalHarmonics(SphericalHarmonicsL2[] sphericalHarmonics)
|
||||||
|
{
|
||||||
|
if (sphericalHarmonics == null || sphericalHarmonics.Length == 0)
|
||||||
|
return (float[])null;
|
||||||
|
int num = 0;
|
||||||
|
float[] numArray = new float[sphericalHarmonics.Length * 27];
|
||||||
|
for (int index = 0; index < sphericalHarmonics.Length; ++index)
|
||||||
|
{
|
||||||
|
for (int rgb = 0; rgb < 3; ++rgb)
|
||||||
|
{
|
||||||
|
for (int coefficient = 0; coefficient < 9; ++coefficient)
|
||||||
|
numArray[num++] = sphericalHarmonics[index][rgb, coefficient];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return numArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateTrajectoryCurvatures()
|
||||||
|
{
|
||||||
|
Vector3[] cameraPositions = this.CameraPositions;
|
||||||
|
double[] frameDistances = this.FrameDistances;
|
||||||
|
int length = cameraPositions.Length;
|
||||||
|
float[] numArray = new float[length];
|
||||||
|
for (int index = 0; index < length; ++index)
|
||||||
|
{
|
||||||
|
Vector3 aP1 = cameraPositions[index];
|
||||||
|
double num = frameDistances[index];
|
||||||
|
Vector3 filteredCameraPosition1 = this.GetFilteredCameraPosition((float)this.GetFrameAtDistance(num - 10.0));
|
||||||
|
Vector3 filteredCameraPosition2 = this.GetFilteredCameraPosition((float)this.GetFrameAtDistance(num + 10.0));
|
||||||
|
Vector3 center;
|
||||||
|
if (!Geometry.CircleCenter(filteredCameraPosition1, aP1, filteredCameraPosition2, out center))
|
||||||
|
{
|
||||||
|
numArray[index] = 0.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float magnitude = (center - filteredCameraPosition1).magnitude;
|
||||||
|
Vector3 normalized = Vector3.Cross(aP1 - filteredCameraPosition1, Vector3.up).normalized;
|
||||||
|
if (((double)center.x - (double)filteredCameraPosition1.x) * (double)normalized.x + ((double)center.y - (double)filteredCameraPosition1.y) * (double)normalized.y + ((double)center.z - (double)filteredCameraPosition1.z) * (double)normalized.z < 0.0)
|
||||||
|
magnitude *= -1f;
|
||||||
|
numArray[index] = 1f / magnitude;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int index1 = 0; index1 < 2; ++index1)
|
||||||
|
{
|
||||||
|
for (int index2 = 1; index2 < numArray.Length - 1; ++index2)
|
||||||
|
numArray[index2] = (float)(((double)numArray[index2 - 1] + (double)numArray[index2] + (double)numArray[index2 + 1]) / 3.0);
|
||||||
|
}
|
||||||
|
this.TrajectoryCurvatures = numArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0a1e61467f8f84048b899dc7815c65ba
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class RouteDetailData
|
||||||
|
{
|
||||||
|
public RouteInfoData RouteInfo;
|
||||||
|
public List<RouteGeometryPointData> Geometry;
|
||||||
|
public List<RouteVideoPointData> VideoPoints;
|
||||||
|
public List<RouteDetailSplitData> Splits;
|
||||||
|
public long Record;
|
||||||
|
public long UserRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RouteDetailSplitData
|
||||||
|
{
|
||||||
|
private bool lapFinish;
|
||||||
|
private int lapFinishIndex;
|
||||||
|
public double Distance;
|
||||||
|
public string Name;
|
||||||
|
|
||||||
|
public bool IsLapFinish => this.lapFinish;
|
||||||
|
|
||||||
|
public int LapFinishIndex => !this.IsLapFinish ? -1 : this.lapFinishIndex;
|
||||||
|
|
||||||
|
public void SetLapFinish(bool lapFinish, int lapFinishIndex)
|
||||||
|
{
|
||||||
|
this.lapFinish = lapFinish;
|
||||||
|
this.lapFinishIndex = lapFinishIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj == null || !this.GetType().Equals(obj.GetType()))
|
||||||
|
return false;
|
||||||
|
RouteDetailSplitData routeDetailSplitData = obj as RouteDetailSplitData;
|
||||||
|
return this.Distance == routeDetailSplitData.Distance && string.Equals(this.Name, routeDetailSplitData.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
int hashCode = 23 * 31 + this.Distance.GetHashCode();
|
||||||
|
if (this.Name != null)
|
||||||
|
hashCode = hashCode * 31 + this.Name.GetHashCode();
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RouteVideoPointData
|
||||||
|
{
|
||||||
|
public double Distance;
|
||||||
|
public double VideoTime;
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public class RouteInfoData
|
||||||
|
{
|
||||||
|
private double lapLength;
|
||||||
|
private double lapUpclimb;
|
||||||
|
public string Name;
|
||||||
|
public string CountryCode;
|
||||||
|
public string VideoScreen;
|
||||||
|
public string Profile;
|
||||||
|
public int Version;
|
||||||
|
public int Rating;
|
||||||
|
public int RatingCount;
|
||||||
|
public double Length;
|
||||||
|
public int Upclimb;
|
||||||
|
public double MaxSlope;
|
||||||
|
public double AvgSlope;
|
||||||
|
public bool IsFavourite;
|
||||||
|
public string ARFileUrl;
|
||||||
|
public List<RouteVideoData> Videos;
|
||||||
|
public bool SuitableForRunning;
|
||||||
|
public bool SuitableForCycling;
|
||||||
|
public bool IsMultiLap;
|
||||||
|
public int LiveSegmentsCount;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public bool HasVideo => this.Videos != null && this.Videos.Count > 0;
|
||||||
|
|
||||||
|
public bool IsAr => !string.IsNullOrEmpty(this.ARFileUrl);
|
||||||
|
|
||||||
|
public double LapLength => this.lapLength != 0.0 ? this.lapLength : this.Length;
|
||||||
|
|
||||||
|
public double LapUpclimb => this.lapUpclimb != 0.0 ? this.lapUpclimb : (double)this.Upclimb;
|
||||||
|
|
||||||
|
public void SetLapLength(double lapLength) => this.lapLength = lapLength;
|
||||||
|
|
||||||
|
public void SetLapUpclimb(double lapUpclimb) => this.lapUpclimb = lapUpclimb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RouteVideoData
|
||||||
|
{
|
||||||
|
public const int MobileQuality = 540;
|
||||||
|
public const int DesktopQuality = 720;
|
||||||
|
public const int HdQuality = 1080;
|
||||||
|
public const int QhdQuality = 1440;
|
||||||
|
public bool IsOFlow;
|
||||||
|
public int Quality;
|
||||||
|
public string Url;
|
||||||
|
public long Size;
|
||||||
|
|
||||||
|
public static int[] AllQualitites() => new int[4]
|
||||||
|
{
|
||||||
|
540,
|
||||||
|
720,
|
||||||
|
1080,
|
||||||
|
1440
|
||||||
|
};
|
||||||
|
|
||||||
|
public static int[] StreamingQualities() => new int[3]
|
||||||
|
{
|
||||||
|
540,
|
||||||
|
720,
|
||||||
|
1080
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public class RouteGeometryPointData
|
||||||
|
{
|
||||||
|
public double Latitude;
|
||||||
|
public double Longitude;
|
||||||
|
public double Distance;
|
||||||
|
public double Altitude;
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public class ARData
|
||||||
|
{
|
||||||
|
public ARRouteData Route;
|
||||||
|
public ARObjectData[] Objects;
|
||||||
|
public ARPanoramaData[] Panoramas;
|
||||||
|
public ARPanoramaData[] Panoramas20;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class ARObjectData
|
||||||
|
{
|
||||||
|
[OptionalField]
|
||||||
|
public string Hash;
|
||||||
|
public int ObjectTypeId;
|
||||||
|
public float Distance;
|
||||||
|
public VectorData PositionOffset;
|
||||||
|
public VectorData RotationOffset;
|
||||||
|
public VectorData Scale;
|
||||||
|
public float ManualVisibility;
|
||||||
|
public ARObjectTimeTransformData[] TimeData;
|
||||||
|
public string CustomUrl;
|
||||||
|
public string ArName;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class ARPanoramaData
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
public string url;
|
||||||
|
public float frame;
|
||||||
|
public int visibilityRear;
|
||||||
|
public int visibilityFront;
|
||||||
|
public float[] matrix;
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public class ARObjectTimeTransformData
|
||||||
|
{
|
||||||
|
public int Frame;
|
||||||
|
public float Distance;
|
||||||
|
public VectorData PositionOffset;
|
||||||
|
public VectorData RotationOffset;
|
||||||
|
public VectorData Scale;
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public class ARRouteData
|
||||||
|
{
|
||||||
|
public int[] Visibility;
|
||||||
|
public VectorData[] CameraPositions;
|
||||||
|
public VectorData[] CameraRotations;
|
||||||
|
public VectorData[] CameraRotationsRear;
|
||||||
|
public float[] LightRotationFrames;
|
||||||
|
public VectorData[] LightRotations;
|
||||||
|
public float[] ShadowIntensityFrames;
|
||||||
|
public float[] ShadowIntensities;
|
||||||
|
public float[] SphericalHarmonics;
|
||||||
|
public int[] SlamSegments;
|
||||||
|
public CameraProjectionParameters[] CameraProjectionParameters;
|
||||||
|
public bool LeftHanded;
|
||||||
|
public int VideoFrameOffset;
|
||||||
|
public int VideoFrameOffsetMac = -1;
|
||||||
|
public float CameraHeight;
|
||||||
|
public float RiderScale = 1f;
|
||||||
|
public int[] LeftSideOffsetFrames;
|
||||||
|
public float[] LeftSideOffsets;
|
||||||
|
public int[] RightSideOffsetFrames;
|
||||||
|
public float[] RightSideOffsets;
|
||||||
|
}
|
||||||
|
public class VectorData
|
||||||
|
{
|
||||||
|
public float x;
|
||||||
|
public float y;
|
||||||
|
public float z;
|
||||||
|
|
||||||
|
public Vector3 ToUnityVector() => new Vector3(this.x, this.y, this.z);
|
||||||
|
|
||||||
|
public VectorData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public VectorData(Vector3 unityVector)
|
||||||
|
{
|
||||||
|
this.x = unityVector.x;
|
||||||
|
this.y = unityVector.y;
|
||||||
|
this.z = unityVector.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class CameraProjectionParameters
|
||||||
|
{
|
||||||
|
public float alpha;
|
||||||
|
public float beta;
|
||||||
|
public float cx;
|
||||||
|
public float cy;
|
||||||
|
|
||||||
|
public CameraProjectionParameters Clone() => new CameraProjectionParameters()
|
||||||
|
{
|
||||||
|
alpha = this.alpha,
|
||||||
|
beta = this.beta,
|
||||||
|
cx = this.cx,
|
||||||
|
cy = this.cy
|
||||||
|
};
|
||||||
|
|
||||||
|
public static CameraProjectionParameters Lerp(
|
||||||
|
CameraProjectionParameters a,
|
||||||
|
CameraProjectionParameters b,
|
||||||
|
float t)
|
||||||
|
{
|
||||||
|
return new CameraProjectionParameters()
|
||||||
|
{
|
||||||
|
alpha = Mathf.Lerp(a.alpha, b.alpha, t),
|
||||||
|
beta = Mathf.Lerp(a.beta, b.beta, t),
|
||||||
|
cx = Mathf.Lerp(a.cx, b.cx, t),
|
||||||
|
cy = Mathf.Lerp(a.cy, b.cy, t)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f4aaeffc1df7bde4880cda54a3cfaf61
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,283 @@
|
|||||||
|
using RenderHeads.Media.AVProVideo;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets.AR
|
||||||
|
{
|
||||||
|
public class AVProVideoPlayer : MonoBehaviour
|
||||||
|
{
|
||||||
|
private const float DefaultFps = 29.97f;
|
||||||
|
public MediaPlayer videoPlayer;
|
||||||
|
private Vector2Int videoResolution = Vector2Int.zero;
|
||||||
|
private Vector2Int textureResolution = Vector2Int.zero;
|
||||||
|
private int displacement;
|
||||||
|
private bool interpolate;
|
||||||
|
private bool useFlow;
|
||||||
|
private bool pausedByTrainingPause = false;
|
||||||
|
private bool pausedByPlaybackSpeed;
|
||||||
|
private RenderTexture currentTexture;
|
||||||
|
private RenderTexture previousTexture;
|
||||||
|
private bool switchBuffer = true;
|
||||||
|
private bool canSwitchBuffer = true;
|
||||||
|
private int previousTextureFrameCount;
|
||||||
|
private float previousVideoTimeMs;
|
||||||
|
private float shift;
|
||||||
|
private DateTime lastPlaybackSpeedChange = DateTime.MinValue;
|
||||||
|
private float localCurrentFrame;
|
||||||
|
private bool intendedRear;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
//this.videoPlayer = this.gameObject.AddComponent<MediaPlayer>();
|
||||||
|
//this.videoPlayer.PlatformOptionsAndroid.videoApi = RenderHeads.Media.AVProVideo.Android.VideoApi.MediaPlayer;
|
||||||
|
//this.videoPlayer.PlatformOptionsAndroid.preferSoftwareDecoder = true;
|
||||||
|
//GameObject primitive = GameObject.CreatePrimitive(PrimitiveType.Quad);
|
||||||
|
//primitive.name = "VideoMesh";
|
||||||
|
//primitive.layer = 9;
|
||||||
|
//UnityEngine.Object.Destroy((UnityEngine.Object)primitive.GetComponent<MeshCollider>());
|
||||||
|
//this.VideoRenderer = (Renderer)primitive.GetComponent<MeshRenderer>();
|
||||||
|
//primitive.transform.parent = this.transform;
|
||||||
|
//this.VideoRenderer.material = new Material(Shader.Find("Rouvy/FrameInterpolation"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable() => this.ReleaseRenderTextures();
|
||||||
|
|
||||||
|
private void OnDestroy() => UnityEngine.Object.Destroy((UnityEngine.Object)this.VideoRenderer?.material);
|
||||||
|
|
||||||
|
public bool Initialized => true;
|
||||||
|
|
||||||
|
public float CurrentFrame => (double)this.localCurrentFrame >= (double)this.StreamFrameCount ? this.localCurrentFrame - (float)this.StreamFrameCount : this.localCurrentFrame;
|
||||||
|
|
||||||
|
public bool IntendedRear
|
||||||
|
{
|
||||||
|
get => this.intendedRear;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (this.intendedRear == value)
|
||||||
|
return;
|
||||||
|
this.intendedRear = value;
|
||||||
|
this.Seek((long)(int)this.CurrentFrame, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRear => (double)this.localCurrentFrame >= (double)this.StreamFrameCount;
|
||||||
|
|
||||||
|
public int StreamFrameCount { get; set; }
|
||||||
|
|
||||||
|
public void UpdateCurrentFrame()
|
||||||
|
{
|
||||||
|
this.localCurrentFrame = (float)(this.videoPlayer.Control.GetCurrentTime() * 29.97f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float FrameRate { get; private set; } = 29.97f;
|
||||||
|
|
||||||
|
public bool HasOpticalFlow { get; private set; }
|
||||||
|
|
||||||
|
public float PlaybackSpeed => this.videoPlayer.Control.GetPlaybackRate();
|
||||||
|
|
||||||
|
public Renderer VideoRenderer { get; private set; }
|
||||||
|
|
||||||
|
public bool IsPaused => this.pausedByTrainingPause;
|
||||||
|
|
||||||
|
public bool IsSeeking => this.videoPlayer.Control.IsSeeking();
|
||||||
|
|
||||||
|
private bool Interpolate
|
||||||
|
{
|
||||||
|
get => this.interpolate;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (this.interpolate == value)
|
||||||
|
return;
|
||||||
|
this.interpolate = value;
|
||||||
|
this.SetShaderKeywords();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool UseFlow
|
||||||
|
{
|
||||||
|
get => this.useFlow;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (this.useFlow == value)
|
||||||
|
return;
|
||||||
|
this.useFlow = value;
|
||||||
|
this.SetShaderKeywords();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenVideo(string videoUrl, int streamFramesCount)
|
||||||
|
{
|
||||||
|
this.StreamFrameCount = streamFramesCount;
|
||||||
|
this.StopVideo();
|
||||||
|
//this.videoPlayer.OpenVideoFromFile(MediaPlayer.FileLocation.AbsolutePathOrURL, videoUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Pause()
|
||||||
|
{
|
||||||
|
this.videoPlayer.Pause();
|
||||||
|
this.pausedByTrainingPause = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Resume()
|
||||||
|
{
|
||||||
|
if (!this.pausedByPlaybackSpeed)
|
||||||
|
this.videoPlayer.Play();
|
||||||
|
this.pausedByTrainingPause = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopVideo()
|
||||||
|
{
|
||||||
|
this.videoPlayer.Stop();
|
||||||
|
this.videoPlayer.CloseMedia();
|
||||||
|
this.ReleaseRenderTextures();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SetPlaybackSpeed(float playbackSpeed)
|
||||||
|
{
|
||||||
|
if (this.IsSeeking || this.IsPaused || DateTime.UtcNow.Subtract(this.lastPlaybackSpeedChange).TotalSeconds < 1.0)
|
||||||
|
return false;
|
||||||
|
if ((double)playbackSpeed == 0.0 && !this.pausedByPlaybackSpeed)
|
||||||
|
{
|
||||||
|
this.pausedByPlaybackSpeed = true;
|
||||||
|
this.videoPlayer.Pause();
|
||||||
|
}
|
||||||
|
else if ((double)playbackSpeed > 0.0 && this.pausedByPlaybackSpeed)
|
||||||
|
{
|
||||||
|
this.pausedByPlaybackSpeed = false;
|
||||||
|
if (!this.pausedByTrainingPause)
|
||||||
|
this.videoPlayer.Play();
|
||||||
|
}
|
||||||
|
this.videoPlayer.PlaybackRate = playbackSpeed;
|
||||||
|
this.lastPlaybackSpeedChange = DateTime.UtcNow;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Seek(long frame, bool force = false)
|
||||||
|
{
|
||||||
|
if (this.IntendedRear)
|
||||||
|
frame += (long)this.StreamFrameCount;
|
||||||
|
if (!this.Initialized || this.IsSeeking && !force)
|
||||||
|
return false;
|
||||||
|
this.videoPlayer.Control.SeekToFrame((int)frame);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Initialize()
|
||||||
|
{
|
||||||
|
if (this.Initialized)
|
||||||
|
return;
|
||||||
|
this.VideoPrepareAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LateUpdate()
|
||||||
|
{
|
||||||
|
if (!this.Initialized)
|
||||||
|
{
|
||||||
|
this.Initialize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.previousVideoTimeMs = (float)this.videoPlayer.Control.GetCurrentTime();
|
||||||
|
if (!this.pausedByTrainingPause && this.videoPlayer.Control.IsPaused() && !this.pausedByPlaybackSpeed)
|
||||||
|
this.videoPlayer.Play();
|
||||||
|
if (!this.pausedByTrainingPause && !this.pausedByPlaybackSpeed || this.videoPlayer.Control.IsPaused())
|
||||||
|
return;
|
||||||
|
this.videoPlayer.Pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckAndPauseByPlaybackSpeed()
|
||||||
|
{
|
||||||
|
if ((double)this.videoPlayer.Control.GetPlaybackRate() != 0.0 || this.pausedByPlaybackSpeed)
|
||||||
|
return;
|
||||||
|
this.pausedByPlaybackSpeed = true;
|
||||||
|
this.videoPlayer.Pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VideoPrepareAction()
|
||||||
|
{
|
||||||
|
this.FrameRate = 29.97f;
|
||||||
|
this.videoPlayer.Control.SetTextureProperties(anisoLevel: 0);
|
||||||
|
if (Math.Abs(this.videoPlayer.Info.GetVideoWidth() - 1688) < 10)
|
||||||
|
{
|
||||||
|
this.videoResolution = new Vector2Int(1280, 720);
|
||||||
|
this.displacement = 40;
|
||||||
|
this.HasOpticalFlow = true;
|
||||||
|
}
|
||||||
|
else if (Math.Abs(this.videoPlayer.Info.GetVideoWidth() - 2528) < 10)
|
||||||
|
{
|
||||||
|
this.videoResolution = new Vector2Int(1920, 1080);
|
||||||
|
this.displacement = 64;
|
||||||
|
this.HasOpticalFlow = true;
|
||||||
|
}
|
||||||
|
else if (Math.Abs(this.videoPlayer.Info.GetVideoWidth() - 3372) < 10)
|
||||||
|
{
|
||||||
|
this.videoResolution = new Vector2Int(2560, 1440);
|
||||||
|
this.displacement = 128;
|
||||||
|
this.HasOpticalFlow = true;
|
||||||
|
}
|
||||||
|
else if (Math.Abs(this.videoPlayer.Info.GetVideoWidth() - 1264) < 10)
|
||||||
|
{
|
||||||
|
this.videoResolution = new Vector2Int(960, 540);
|
||||||
|
this.HasOpticalFlow = true;
|
||||||
|
this.displacement = 32;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.videoResolution = new Vector2Int(this.videoPlayer.Info.GetVideoWidth(), this.videoPlayer.Info.GetVideoHeight());
|
||||||
|
this.HasOpticalFlow = false;
|
||||||
|
}
|
||||||
|
this.Interpolate = this.UseFlow = this.HasOpticalFlow;
|
||||||
|
this.videoPlayer.Play();
|
||||||
|
if (!this.pausedByTrainingPause)
|
||||||
|
return;
|
||||||
|
this.videoPlayer.Pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReleaseRenderTextures()
|
||||||
|
{
|
||||||
|
if ((UnityEngine.Object)this.currentTexture != (UnityEngine.Object)null)
|
||||||
|
{
|
||||||
|
this.currentTexture.Release();
|
||||||
|
this.currentTexture = (RenderTexture)null;
|
||||||
|
}
|
||||||
|
if (!((UnityEngine.Object)this.previousTexture != (UnityEngine.Object)null))
|
||||||
|
return;
|
||||||
|
this.previousTexture.Release();
|
||||||
|
this.previousTexture = (RenderTexture)null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetShaderKeywords()
|
||||||
|
{
|
||||||
|
if (this.Interpolate)
|
||||||
|
this.VideoRenderer.material.EnableKeyword(AVProVideoPlayer.ShaderKeyword.interpolate);
|
||||||
|
else
|
||||||
|
this.VideoRenderer.material.DisableKeyword(AVProVideoPlayer.ShaderKeyword.interpolate);
|
||||||
|
if (this.UseFlow && this.videoResolution != this.textureResolution)
|
||||||
|
this.VideoRenderer.material.EnableKeyword(AVProVideoPlayer.ShaderKeyword.useFlow);
|
||||||
|
else
|
||||||
|
this.VideoRenderer.material.DisableKeyword(AVProVideoPlayer.ShaderKeyword.useFlow);
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Size = 1)]
|
||||||
|
private struct ShaderID
|
||||||
|
{
|
||||||
|
public static int previousFrame = Shader.PropertyToID("_PreviousFrame");
|
||||||
|
public static int currentFrame = Shader.PropertyToID("_CurrentFrame");
|
||||||
|
public static int displacement = Shader.PropertyToID("_MaxDisplacement");
|
||||||
|
public static int shift = Shader.PropertyToID("_Shift");
|
||||||
|
public static int flip = Shader.PropertyToID("_Flip");
|
||||||
|
public static int videoResolution = Shader.PropertyToID("_VideoResolution");
|
||||||
|
public static int textureResolution = Shader.PropertyToID("_TextureResolution");
|
||||||
|
public static int screenResolution = Shader.PropertyToID("_ScreenResolution");
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Size = 1)]
|
||||||
|
private struct ShaderKeyword
|
||||||
|
{
|
||||||
|
public static string interpolate = "INTERPOLATE";
|
||||||
|
public static string useFlow = "USE_FLOW";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5609ccb62c92e784e873a76e89abc3aa
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets.AR
|
||||||
|
{
|
||||||
|
public abstract class BaseRenderer : ARLaneObject
|
||||||
|
{
|
||||||
|
protected Animator animator;
|
||||||
|
protected Shader shaderNormal;
|
||||||
|
protected Shader shaderAplha;
|
||||||
|
protected MaterialPropertyBlock materialPropertyBlock;
|
||||||
|
private bool paused = true;
|
||||||
|
|
||||||
|
public bool Male { get; protected set; }
|
||||||
|
|
||||||
|
public Texture2D JerseyTexture { get; set; }
|
||||||
|
|
||||||
|
public Color ColorSkin { get; set; }
|
||||||
|
|
||||||
|
public Color ColorUser { get; set; }
|
||||||
|
|
||||||
|
public bool Paused
|
||||||
|
{
|
||||||
|
get => this.paused;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == this.paused)
|
||||||
|
return;
|
||||||
|
this.paused = value;
|
||||||
|
this.OnPause(this.paused);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
base.Awake();
|
||||||
|
this.animator = this.GetComponent<Animator>();
|
||||||
|
//this.shaderAplha = Shader.Find("Rouvy/RiderShaderOneAlpha");
|
||||||
|
//this.shaderNormal = Shader.Find("Rouvy/RiderShaderOne");
|
||||||
|
this.materialPropertyBlock = new MaterialPropertyBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(bool male) => this.Male = male;
|
||||||
|
|
||||||
|
protected virtual void Start()
|
||||||
|
{
|
||||||
|
this.SetupModels();
|
||||||
|
this.SetLayerRecursively(this.gameObject, 9);
|
||||||
|
this.animator.avatar = (Avatar)null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void SetupModels();
|
||||||
|
|
||||||
|
|
||||||
|
protected virtual void OnPause(bool paused)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetLayerRecursively(GameObject obj, int layer)
|
||||||
|
{
|
||||||
|
obj.layer = layer;
|
||||||
|
foreach (Component component in obj.transform)
|
||||||
|
this.SetLayerRecursively(component.gameObject, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Size = 1)]
|
||||||
|
public struct ShaderID
|
||||||
|
{
|
||||||
|
public static int mainTex = Shader.PropertyToID("_MainTex");
|
||||||
|
public static int opacity = Shader.PropertyToID("_Opacity");
|
||||||
|
public static int colorCustom = Shader.PropertyToID("_ColorCustom");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4f542667dd24fe84e87fcb325e8535cb
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets
|
||||||
|
{
|
||||||
|
public static class Geometry
|
||||||
|
{
|
||||||
|
public static bool CircleCenter(Vector3 aP0, Vector3 aP1, Vector3 aP2, out Vector3 center)
|
||||||
|
{
|
||||||
|
Vector3 lhs = aP1 - aP0;
|
||||||
|
Vector3 vector3 = aP2 - aP0;
|
||||||
|
Vector3 rhs = Vector3.Cross(lhs, vector3);
|
||||||
|
if ((double)rhs.sqrMagnitude < 9.9999998245167E-15)
|
||||||
|
{
|
||||||
|
center = Vector3.zero;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rhs.Normalize();
|
||||||
|
if ((double)rhs.sqrMagnitude < 9.9999998245167E-15)
|
||||||
|
{
|
||||||
|
center = Vector3.zero;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Vector3 normalized1 = Vector3.Cross(lhs, rhs).normalized;
|
||||||
|
Vector3 normalized2 = Vector3.Cross(vector3, rhs).normalized;
|
||||||
|
Vector3 from = (lhs - vector3) * 0.5f;
|
||||||
|
float num1 = Vector3.Angle(normalized1, normalized2);
|
||||||
|
float num2 = Vector3.Angle(from, normalized1);
|
||||||
|
float num3 = from.magnitude * Mathf.Sin(num2 * ((float)Math.PI / 180f)) / Mathf.Sin(num1 * ((float)Math.PI / 180f));
|
||||||
|
center = (double)Vector3.Dot(lhs, aP2 - aP1) <= 0.0 ? aP0 + vector3 * 0.5f + normalized2 * num3 : aP0 + vector3 * 0.5f - normalized2 * num3;
|
||||||
|
return !float.IsInfinity(center.x) && !float.IsNaN(center.x) && !float.IsInfinity(center.y) && !float.IsNaN(center.y) && !float.IsInfinity(center.z) && !float.IsNaN(center.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 192a6b01fc9e2ec44b90f5d19c277ca4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets.AR
|
||||||
|
{
|
||||||
|
public class RiderRenderer : BaseRenderer
|
||||||
|
{
|
||||||
|
private const int PowerWindowSize = 10;
|
||||||
|
private const float Circumference = 2.13097382f;
|
||||||
|
private const double SpeedLimitForWheelRotation = 10.0;
|
||||||
|
private const double MaxAngularSpeed = 1689.3684817282528;
|
||||||
|
private const double MaxAnglePerFrame = 6.5;
|
||||||
|
private const float AfterFinishRideInSec = 5f;
|
||||||
|
public const float MaxLeanAngle = 35f;
|
||||||
|
public const float MaxLeanAngleChange = 60f;
|
||||||
|
public const float MaxTurnAngle = 6f;
|
||||||
|
public const float MaxTurnAngleChange = 10f;
|
||||||
|
public const float LeanAngleSoftStageLength = 15f;
|
||||||
|
private float lastSpeed = 1f;
|
||||||
|
private bool lastPauseState;
|
||||||
|
private int lastDifficultyLevel;
|
||||||
|
private float lastVisibilitylevel = -1f;
|
||||||
|
private float afterFinishTime;
|
||||||
|
private float afterFinishFrame;
|
||||||
|
private float finishPassSpeed;
|
||||||
|
private float afterFinishOffsetZ;
|
||||||
|
private float lastDiffLevelChange = float.MinValue;
|
||||||
|
private float[] powerWindow = new float[10];
|
||||||
|
private float lastPowerWinWrite;
|
||||||
|
private int lastPowerWinIndex;
|
||||||
|
private float PowerWinSum;
|
||||||
|
private float lastPowerPeak = float.MinValue;
|
||||||
|
private int powerPeakSum;
|
||||||
|
private Transform wheelFront;
|
||||||
|
private Transform wheelRear;
|
||||||
|
private float lookTime;
|
||||||
|
private bool lockIdleAnimations;
|
||||||
|
|
||||||
|
public float Cadence { get; set; }
|
||||||
|
|
||||||
|
public int DifficultyLevel { get; set; }
|
||||||
|
|
||||||
|
public float Power { get; set; }
|
||||||
|
|
||||||
|
public float Weight { get; set; }
|
||||||
|
|
||||||
|
public float Slope { get; set; }
|
||||||
|
|
||||||
|
public Texture2D HelmTexture { get; set; }
|
||||||
|
|
||||||
|
public Texture2D BikeTexture { get; set; }
|
||||||
|
|
||||||
|
public bool WinAnimation { get; set; }
|
||||||
|
|
||||||
|
public bool TimeTrialBike { get; private set; }
|
||||||
|
|
||||||
|
public GameObject BasicShadowRenderer { get; set; }
|
||||||
|
|
||||||
|
public bool LockIdleAnimations
|
||||||
|
{
|
||||||
|
get => this.lockIdleAnimations;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == this.lockIdleAnimations)
|
||||||
|
return;
|
||||||
|
this.lockIdleAnimations = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Awake()
|
||||||
|
{
|
||||||
|
base.Awake();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(bool male, bool timeTrialBike)
|
||||||
|
{
|
||||||
|
this.Initialize(male);
|
||||||
|
this.TimeTrialBike = timeTrialBike;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
if ((UnityEngine.Object)this.animator != (UnityEngine.Object)null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
if (!this.LockIdleAnimations)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Start()
|
||||||
|
{
|
||||||
|
base.Start();
|
||||||
|
this.PlanNextLook();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
if (this.route == null)
|
||||||
|
return;
|
||||||
|
this.UpdateDiffciulityLevel();
|
||||||
|
base.Update();
|
||||||
|
float num = this.Speed;
|
||||||
|
bool flag = this.Paused;
|
||||||
|
if (this.IsAtFinish)
|
||||||
|
{
|
||||||
|
if ((double)this.afterFinishTime < 5.0)
|
||||||
|
{
|
||||||
|
this.ManualVisibility = 1000f;
|
||||||
|
float videoSpeedAtDistance = this.videoSync.GetVideoSpeedAtDistance(this.Distance - 5f);
|
||||||
|
if ((double)this.afterFinishFrame == 0.0 && (double)this.afterFinishOffsetZ == 0.0)
|
||||||
|
{
|
||||||
|
this.finishPassSpeed = (double)this.lastSpeed > 0.0 ? this.lastSpeed : 10f;
|
||||||
|
}
|
||||||
|
flag = false;
|
||||||
|
this.afterFinishTime += Time.deltaTime;
|
||||||
|
this.afterFinishTime = Math.Min(5f, this.afterFinishTime);
|
||||||
|
num = Mathf.Lerp(this.finishPassSpeed, 0.0f, this.afterFinishTime / 5f);
|
||||||
|
//this.afterFinishFrame += num / videoSpeedAtDistance * Time.deltaTime * this.VideoPlayer.FrameRate;
|
||||||
|
this.frame = Math.Min((float)(this.route.CameraPositions.Length - 1), this.videoSync.GetVideoFrameAtDistance(this.Distance) + this.afterFinishFrame);
|
||||||
|
if ((double)this.frame == (double)(this.route.CameraPositions.Length - 1))
|
||||||
|
this.afterFinishOffsetZ += num * Time.deltaTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.afterFinishTime += Time.deltaTime;
|
||||||
|
num = 0.0f;
|
||||||
|
if ((double)this.afterFinishTime > 15.0)
|
||||||
|
this.ManualVisibility = -1f;
|
||||||
|
else
|
||||||
|
this.ManualVisibility = 1000f;
|
||||||
|
}
|
||||||
|
this.PositionOffset.z = this.afterFinishOffsetZ;
|
||||||
|
this.transform.localScale = Vector3.one * this.route.RiderScale;
|
||||||
|
this.UpdateTransform();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.transform.localScale = Vector3.one * this.route.RiderScale;
|
||||||
|
if (flag)
|
||||||
|
num = 0.0f;
|
||||||
|
this.ManualVisibility = 0.0f;
|
||||||
|
this.afterFinishTime = 0.0f;
|
||||||
|
this.afterFinishFrame = 0.0f;
|
||||||
|
this.afterFinishOffsetZ = 0.0f;
|
||||||
|
this.PositionOffset.z = 0.0f;
|
||||||
|
}
|
||||||
|
if (flag != this.lastPauseState)
|
||||||
|
{
|
||||||
|
this.lastPauseState = flag;
|
||||||
|
}
|
||||||
|
if ((double)this.lastSpeed != (double)num)
|
||||||
|
{
|
||||||
|
this.lastSpeed = num;
|
||||||
|
}
|
||||||
|
if ((double)this.lastSpeed > 0.0 && this.lastDifficultyLevel != this.DifficultyLevel && !this.lastPauseState && (double)Math.Abs(Time.time - this.lastDiffLevelChange) > 2.0)
|
||||||
|
{
|
||||||
|
this.lastDifficultyLevel = this.DifficultyLevel;
|
||||||
|
this.lastDiffLevelChange = Time.time;
|
||||||
|
}
|
||||||
|
if ((double)this.lastVisibilitylevel == (double)this.VisibilityLevel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.lastVisibilitylevel = this.VisibilityLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void FixedUpdate()
|
||||||
|
{
|
||||||
|
//if (this.Paused || (double)this.Speed <= 0.0)
|
||||||
|
// return;
|
||||||
|
//float angle = (float)VTMath.Clamp(VTMath.Lerp(0.0, 0.0, 1689.3684817282528, 6.5, 360.0 * ((double)this.Speed < 10.0 ? (double)this.Speed : 2.3463451135114624)), 0.0, 6.5);
|
||||||
|
//this.wheelFront.transform.Rotate(Vector3.right, angle);
|
||||||
|
//this.wheelRear.transform.Rotate(Vector3.right, angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetupModels()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void PlanNextLook()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateDiffciulityLevel()
|
||||||
|
{
|
||||||
|
float num = this.PowerWinSum / 10f;
|
||||||
|
if ((double)Math.Abs(Time.time - this.lastPowerWinWrite) >= 1.0)
|
||||||
|
{
|
||||||
|
++this.lastPowerWinIndex;
|
||||||
|
this.lastPowerWinIndex %= 10;
|
||||||
|
this.PowerWinSum -= this.powerWindow[this.lastPowerWinIndex];
|
||||||
|
this.powerWindow[this.lastPowerWinIndex] = this.Power;
|
||||||
|
this.PowerWinSum += this.Power;
|
||||||
|
this.lastPowerWinWrite = Time.time;
|
||||||
|
num = this.PowerWinSum / 10f;
|
||||||
|
if ((double)this.Power > (double)num * 1.2000000476837158 && (double)this.Power / (double)this.Weight > 2.0)
|
||||||
|
++this.powerPeakSum;
|
||||||
|
else
|
||||||
|
this.powerPeakSum = 0;
|
||||||
|
}
|
||||||
|
if ((double)this.Power / (double)this.Weight > 8.0 || this.powerPeakSum > 2 || (double)this.Power > (double)num * 3.0 && (double)this.Power / (double)this.Weight > 2.0)
|
||||||
|
this.lastPowerPeak = Time.time;
|
||||||
|
if ((double)Math.Abs(Time.time - this.lastPowerPeak) < 2.0)
|
||||||
|
this.DifficultyLevel = 2;
|
||||||
|
else if ((double)this.Power / (double)this.Weight > 2.0)
|
||||||
|
this.DifficultyLevel = 1;
|
||||||
|
else
|
||||||
|
this.DifficultyLevel = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a779f3247875ef947ab87e8093f5bb39
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,367 @@
|
|||||||
|
using Assets.AR;
|
||||||
|
using DG.Tweening;
|
||||||
|
using RenderHeads.Media.AVProVideo;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets.Scripts.Scenes.VideoRide
|
||||||
|
{
|
||||||
|
public class TestPlayer : ARLaneObjectsController
|
||||||
|
{
|
||||||
|
protected Transform LightTrans { get; set; }
|
||||||
|
public MediaPlayer mediaPlayer;
|
||||||
|
public Transform Player;
|
||||||
|
private ARData aRData;
|
||||||
|
private RouteDetailData detail;
|
||||||
|
private VideoPointsSync videoPointsSync;
|
||||||
|
private int index = 1;
|
||||||
|
private readonly List<ARLaneObject> collisionList = new List<ARLaneObject>();
|
||||||
|
///private Dictionary<int, IRouteRider> riders = new Dictionary<int, IRouteRider>();
|
||||||
|
VideoPlayerControl VideoPlayerControl;
|
||||||
|
ARLaneObject[] rides;
|
||||||
|
public ARLaneObject mainObject;
|
||||||
|
|
||||||
|
private Light arLight;
|
||||||
|
private Light arBackLight;
|
||||||
|
|
||||||
|
protected override void Start()
|
||||||
|
{
|
||||||
|
base.Start();
|
||||||
|
var txt = Resources.Load<TextAsset>("UI/88019").text;
|
||||||
|
var route = Resources.Load<TextAsset>("UI/route-88019").text;
|
||||||
|
aRData = Newtonsoft.Json.JsonConvert.DeserializeObject<ARData>(txt);
|
||||||
|
detail = Newtonsoft.Json.JsonConvert.DeserializeObject<RouteDetailData>(route);
|
||||||
|
|
||||||
|
videoPointsSync = new VideoPointsSync(detail.VideoPoints.Select(c => new VideoPoint()
|
||||||
|
{
|
||||||
|
Distance = (float)c.Distance,
|
||||||
|
Time = (float)c.VideoTime
|
||||||
|
}));
|
||||||
|
|
||||||
|
videoSync = videoPointsSync;
|
||||||
|
|
||||||
|
this.VideoPlayerControl = new VideoPlayerControl();
|
||||||
|
this.VideoPlayerControl.VideoSyncSource = videoSync;
|
||||||
|
this.videoPlayer = new AVProVideoPlayer();
|
||||||
|
this.videoPlayer.videoPlayer = mediaPlayer;
|
||||||
|
SetArRoute(new ARRoute(aRData.Route), videoSync, videoPlayer);
|
||||||
|
this.VideoPlayerControl.VideoFrameOffset = this.Route.VideoFrameOffset;
|
||||||
|
this.VideoPlayerControl.Route = Route;
|
||||||
|
this.VideoPlayerControl.SetVideoPlayer(videoPlayer);
|
||||||
|
rides = FindObjectsOfType<ARLaneObject>();
|
||||||
|
CreateBackLight();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateBackLight()
|
||||||
|
{
|
||||||
|
GameObject gameObject2 = new GameObject("ARBackLight");
|
||||||
|
gameObject2.layer = this.gameObject.layer;
|
||||||
|
gameObject2.transform.SetParent(this.transform);
|
||||||
|
this.arBackLight = gameObject2.AddComponent<Light>();
|
||||||
|
this.arBackLight.type = LightType.Directional;
|
||||||
|
this.arBackLight.transform.rotation = Quaternion.Euler(0.0f, 0.0f, 0.0f);
|
||||||
|
this.arBackLight.shadows = LightShadows.None;
|
||||||
|
this.arBackLight.intensity = 0.5f;
|
||||||
|
this.arBackLight.cullingMask = 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
float timers = 0f;
|
||||||
|
double weight = 70;
|
||||||
|
double bikeWeight = 20;
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
timers -= Time.deltaTime;
|
||||||
|
|
||||||
|
while (timers < 0)
|
||||||
|
{
|
||||||
|
foreach (var item in rides)
|
||||||
|
{
|
||||||
|
item.Speed = (float)(Assets.Scenes.Ride.Scripts.Helper.CalculateSpeed(0, 0, item.TestPower, weight, bikeWeight) / 3.6d);
|
||||||
|
item.Distance += item.Speed;
|
||||||
|
item.RouteDistance = item.Distance;
|
||||||
|
item.Route = Route;
|
||||||
|
item.VideoSync = videoPointsSync;
|
||||||
|
if (!this.riderObjects.ContainsKey(item.GetInstanceID()))
|
||||||
|
this.riderObjects.Add(item.GetInstanceID(), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
timers += 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.FollowedRiderId = 1;
|
||||||
|
this.UpdateCameraFollowDistance();
|
||||||
|
VideoPlayerControl.UpdateVideoPlaybackSpeed(mainObject.Speed, mainObject.distance-this.CameraDistance);
|
||||||
|
this.FrameIndexDistanceCorrection = this.VideoPlayerControl.FrameIndexDistanceCorrection;
|
||||||
|
base.Update();
|
||||||
|
this.UpdateRidersVisibility();
|
||||||
|
this.UpdateRidersLean();
|
||||||
|
|
||||||
|
if (Input.GetKeyDown(KeyCode.F))
|
||||||
|
this.SetVideoControlMode(VideoControlMode.Front);
|
||||||
|
if (Input.GetKeyDown(KeyCode.P))
|
||||||
|
this.SetVideoControlMode(VideoControlMode.AutoPanorama);
|
||||||
|
if (!Input.GetKeyDown(KeyCode.B))
|
||||||
|
return;
|
||||||
|
this.SetVideoControlMode(VideoControlMode.Rear);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator PlayPosition(ARLaneObject aRLaneObject,double prePos, double offset)
|
||||||
|
{
|
||||||
|
float t = 0;
|
||||||
|
while (t <= 1)
|
||||||
|
{
|
||||||
|
t += Time.deltaTime * 5f;
|
||||||
|
double result = prePos + offset * t;
|
||||||
|
aRLaneObject.distance = (float)result;
|
||||||
|
aRLaneObject.RouteDistance = (float)result ;
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public VideoControlMode VideoControlMode { get; private set; }
|
||||||
|
private float autoCameraSwitchTimeCounter = 80f;
|
||||||
|
public void SetVideoControlMode(VideoControlMode mode)
|
||||||
|
{
|
||||||
|
if (mode == this.VideoControlMode)
|
||||||
|
return;
|
||||||
|
if (!this.AR360Version)
|
||||||
|
mode = VideoControlMode.Front;
|
||||||
|
this.VideoControlMode = mode;
|
||||||
|
this.autoCameraSwitchTimeCounter = 80f;
|
||||||
|
if (mode == VideoControlMode.AutoPanorama)
|
||||||
|
return;
|
||||||
|
this.videoPlayer.IntendedRear = mode == VideoControlMode.Rear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RiderCameraDistance RiderCameraDistance { get; set; }
|
||||||
|
//更新摄像机的位置
|
||||||
|
private void UpdateCameraFollowDistance()
|
||||||
|
{
|
||||||
|
this.RiderCameraDistance = RiderCameraDistance.Near;
|
||||||
|
this.NearViewMode = this.RiderCameraDistance == RiderCameraDistance.Near;
|
||||||
|
float cameraFollowDistance = GetCameraFollowDistance(this.RiderCameraDistance);
|
||||||
|
this.VideoPlayerControl.CameraFollowDistance = this.videoPlayer.IsRear ? cameraFollowDistance * -1f : cameraFollowDistance;
|
||||||
|
}
|
||||||
|
protected override bool IsArObjectActive(ARObject arObject)
|
||||||
|
{
|
||||||
|
bool flag = base.IsArObjectActive(arObject);
|
||||||
|
if ((UnityEngine.Object)arObject != (UnityEngine.Object)this.mainObject)
|
||||||
|
return flag;
|
||||||
|
if ((double)this.VideoPlayerControl.CameraFollowDistance > 0.0 || this.AR360Version)
|
||||||
|
return flag;
|
||||||
|
return flag && (double)this.VideoPlayerControl.CameraDistanceError > 5.0;
|
||||||
|
}
|
||||||
|
//获取摄像机的位置
|
||||||
|
public static float GetCameraFollowDistance(RiderCameraDistance distance)
|
||||||
|
{
|
||||||
|
switch (distance)
|
||||||
|
{
|
||||||
|
case RiderCameraDistance.FirstPerson:
|
||||||
|
return 0.0f;
|
||||||
|
case RiderCameraDistance.Near:
|
||||||
|
return 1.5f;
|
||||||
|
case RiderCameraDistance.Middle:
|
||||||
|
return 5f;
|
||||||
|
case RiderCameraDistance.Far:
|
||||||
|
return 10f;
|
||||||
|
default:
|
||||||
|
throw new ArgumentException("Unknown rider's camera distance.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void UpdateRidersVisibility()
|
||||||
|
{
|
||||||
|
//if (!this.videoPlayer.Initialized)
|
||||||
|
// return;
|
||||||
|
//this.UpdateVisibleRiders();
|
||||||
|
////删除当前道路上应该消失的骑手
|
||||||
|
//foreach (int num in this.riderObjects.Keys.ToArray<int>())
|
||||||
|
//{
|
||||||
|
// if (!this.visibleRiders.ContainsKey(num))
|
||||||
|
// {
|
||||||
|
// ARLaneObject riderObject = this.riderObjects[num];
|
||||||
|
// if (!riderObject.IsAtFinish || (double)riderObject.VisibilityLevel <= 0.0)
|
||||||
|
// {
|
||||||
|
// this.DestroyRider(num);
|
||||||
|
// this.DestroyRiderTitle(num);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
////新增应该显示的骑手
|
||||||
|
//foreach (TrainingARController.VisibleRiderItem visibleRiderItem in this.visibleRiders.Values)
|
||||||
|
//{
|
||||||
|
// IRouteRider rider = visibleRiderItem.Rider;
|
||||||
|
// bool showModel = visibleRiderItem.ShowModel;
|
||||||
|
// ARLaneObject arLaneObject;
|
||||||
|
// //二次检查
|
||||||
|
// if (this.riderObjects.TryGetValue(rider.Id, out arLaneObject))
|
||||||
|
// {
|
||||||
|
// if (arLaneObject is BaseRenderer)
|
||||||
|
// {
|
||||||
|
// if (!showModel)
|
||||||
|
// {
|
||||||
|
// float lane = arLaneObject.Lane;
|
||||||
|
// this.DestroyRider(rider.Id);
|
||||||
|
// this.CreateRiderObject(rider, lane);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else if (showModel)
|
||||||
|
// {
|
||||||
|
// float lane = arLaneObject.Lane;
|
||||||
|
// this.DestroyRider(rider.Id);
|
||||||
|
// this.CreateRiderModel(rider, lane);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// if (showModel)
|
||||||
|
// this.CreateRiderModel(rider, visibleRiderItem.Lane);
|
||||||
|
// else
|
||||||
|
// this.CreateRiderObject(rider, visibleRiderItem.Lane);
|
||||||
|
// this.CreateRiderTitleObject(rider);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
//更新骑手的偏移角度
|
||||||
|
private void UpdateRidersLean()
|
||||||
|
{
|
||||||
|
foreach (ARLaneObject riderObject in this.riderObjects.Values)
|
||||||
|
{
|
||||||
|
float num1 = this.Route.GetTrajectoryCurvature(riderObject.Frame) + riderObject.Curvature;
|
||||||
|
float z1;
|
||||||
|
if ((double)num1 == 0.0)
|
||||||
|
{
|
||||||
|
z1 = 0.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double speed = riderObject.Speed;
|
||||||
|
float f = 57.29578f * Mathf.Atan((float)(speed * speed * (double)num1 / 9.81));
|
||||||
|
float num2 = (double)f >= 0.0 ? 1f : -1f;
|
||||||
|
float num3 = Mathf.Abs(f);
|
||||||
|
if ((double)num3 > 20.0)
|
||||||
|
f = (float)((double)Mathf.Atan((float)(((double)num3 - 20.0) / 10.5)) * 10.5 + 20.0) * num2;
|
||||||
|
float num4 = Mathf.Clamp(f, -35f, 35f);
|
||||||
|
float z2 = riderObject.Lean.z;
|
||||||
|
z1 = Mathf.Clamp(num4, z2 - 60f * Time.deltaTime, z2 + 60f * Time.deltaTime);
|
||||||
|
}
|
||||||
|
float y = Mathf.Clamp(riderObject.LaneChangingDirection, -6f, 6f);
|
||||||
|
riderObject.Lean = new Vector3(0.0f, y, z1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime lastPlaybackSpeedChange = DateTime.UtcNow;
|
||||||
|
bool pausedByPlaybackSpeed = false;
|
||||||
|
bool pausedByTrainingPause = false;
|
||||||
|
float frame = 0f;
|
||||||
|
public bool SetPlaybackSpeed(float playbackSpeed)
|
||||||
|
{
|
||||||
|
if (this.mediaPlayer.Control.IsSeeking() || DateTime.UtcNow.Subtract(this.lastPlaybackSpeedChange).TotalSeconds < 1.0)
|
||||||
|
return false;
|
||||||
|
if ((double)playbackSpeed == 0.0 && !this.pausedByPlaybackSpeed)
|
||||||
|
{
|
||||||
|
this.pausedByPlaybackSpeed = true;
|
||||||
|
this.mediaPlayer.Pause();
|
||||||
|
}
|
||||||
|
else if ((double)playbackSpeed > 0.0 && this.pausedByPlaybackSpeed)
|
||||||
|
{
|
||||||
|
this.pausedByPlaybackSpeed = false;
|
||||||
|
if (!this.pausedByTrainingPause)
|
||||||
|
this.mediaPlayer.Play();
|
||||||
|
}
|
||||||
|
this.mediaPlayer.Control.SetPlaybackRate(playbackSpeed);
|
||||||
|
this.lastPlaybackSpeedChange = DateTime.UtcNow;
|
||||||
|
mediaPlayer.Play();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
//人物状态
|
||||||
|
private string ConfigPath = Application.streamingAssetsPath + "/newdirection.txt";
|
||||||
|
public const int HERO_UP = 0;
|
||||||
|
public const int HERO_RIGHT = 1;
|
||||||
|
public const int HERO_DOWN = 2;
|
||||||
|
public const int HERO_LEFT = 3;
|
||||||
|
public const int UP = 4;
|
||||||
|
public const int DOWN = 5;
|
||||||
|
private Vector3 rotation = Vector3.zero;
|
||||||
|
private void keyBordControl()
|
||||||
|
{
|
||||||
|
#region 人物方向控制
|
||||||
|
var zdelta = 0.05f;
|
||||||
|
var delta = 0.2f;
|
||||||
|
if (Input.GetKey(KeyCode.W))
|
||||||
|
{
|
||||||
|
//mediaPlayer.Play();
|
||||||
|
//mediaPlayer.PlaybackRate = 1f;
|
||||||
|
var z = transform.position.z + zdelta;
|
||||||
|
//transform.DOMoveZ(z, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.GetKey(KeyCode.A))
|
||||||
|
{
|
||||||
|
mediaPlayer.PlaybackRate = 1f;
|
||||||
|
mediaPlayer.Play();
|
||||||
|
var z = transform.position.x - zdelta;
|
||||||
|
//transform.DOMoveX(z, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.GetKey(KeyCode.D))
|
||||||
|
{
|
||||||
|
mediaPlayer.PlaybackRate = 1f;
|
||||||
|
mediaPlayer.Play();
|
||||||
|
var z = transform.position.x + zdelta;
|
||||||
|
//transform.DOMoveX(z, 0);
|
||||||
|
}
|
||||||
|
if (Input.GetKey(KeyCode.S))
|
||||||
|
{
|
||||||
|
mediaPlayer.PlaybackRate = 1f;
|
||||||
|
mediaPlayer.Play();
|
||||||
|
var z = transform.position.z - zdelta;
|
||||||
|
//transform.DOMoveZ(z, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//控制人物方向
|
||||||
|
if (Input.GetKey(KeyCode.Q))
|
||||||
|
{
|
||||||
|
rotation.y -= delta;
|
||||||
|
transform.DORotate(rotation, 0);
|
||||||
|
Camera.main.transform.DORotate(rotation, 0);
|
||||||
|
}
|
||||||
|
if (Input.GetKey(KeyCode.E))
|
||||||
|
{
|
||||||
|
rotation.y += delta;
|
||||||
|
transform.DORotate(rotation, 0);
|
||||||
|
Camera.main.transform.DORotate(rotation, 0);
|
||||||
|
}
|
||||||
|
//控制人物左右倾斜
|
||||||
|
if (Input.GetKey(KeyCode.J))
|
||||||
|
{
|
||||||
|
rotation.z += zdelta;
|
||||||
|
transform.DORotate(rotation, 0);
|
||||||
|
}
|
||||||
|
if (Input.GetKey(KeyCode.K))
|
||||||
|
{
|
||||||
|
rotation.z -= zdelta;
|
||||||
|
transform.DORotate(rotation, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.GetKey(KeyCode.UpArrow))
|
||||||
|
{
|
||||||
|
var z = transform.position.y + zdelta;
|
||||||
|
transform.DOMoveY(z, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.GetKey(KeyCode.DownArrow))
|
||||||
|
{
|
||||||
|
var z = transform.position.y - zdelta;
|
||||||
|
transform.DOMoveY(z, 0);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 523f7d25735c76b4ea28ecc390829ed7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets
|
||||||
|
{
|
||||||
|
public static class VTMath
|
||||||
|
{
|
||||||
|
public const double Deg2Rad = 0.017453292519943295;
|
||||||
|
public const double Rad2Deg = 57.295779513082323;
|
||||||
|
|
||||||
|
public static int Clamp(int value, int min, int max)
|
||||||
|
{
|
||||||
|
if (value < min)
|
||||||
|
return min;
|
||||||
|
return value <= max ? value : max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double Clamp(double value, double min, double max)
|
||||||
|
{
|
||||||
|
if (value < min)
|
||||||
|
return min;
|
||||||
|
return value <= max ? value : max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Clamp(float value, float min, float max)
|
||||||
|
{
|
||||||
|
if ((double)value < (double)min)
|
||||||
|
return min;
|
||||||
|
return (double)value <= (double)max ? value : max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Clamp01(float value) => VTMath.Clamp(value, 0.0f, 1f);
|
||||||
|
|
||||||
|
public static double Clamp01(double value) => VTMath.Clamp(value, 0.0, 1.0);
|
||||||
|
|
||||||
|
public static bool InBounds(double value, double min, double max) => min <= value && value <= max;
|
||||||
|
|
||||||
|
public static bool InBounds(int value, int min, int max) => min <= value && value <= max;
|
||||||
|
|
||||||
|
public static double Lerp(double x1, double y1, double x2, double y2, double x)
|
||||||
|
{
|
||||||
|
double t = x1 != x2 ? VTMath.InverseLerp(x1, x2, x) : 0.5;
|
||||||
|
return VTMath.Lerp(y1, y2, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Lerp(float x1, float y1, float x2, float y2, float x)
|
||||||
|
{
|
||||||
|
float t = (double)x1 != (double)x2 ? VTMath.InverseLerp(x1, x2, x) : 0.5f;
|
||||||
|
return VTMath.Lerp(y1, y2, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double Lerp(double a, double b, double t) => (1.0 - t) * a + t * b;
|
||||||
|
|
||||||
|
public static float Lerp(float a, float b, float t) => (float)((1.0 - (double)t) * (double)a + (double)t * (double)b);
|
||||||
|
|
||||||
|
public static double InverseLerp(double a, double b, double value) => a != b ? (value - a) / (b - a) : 0.0;
|
||||||
|
|
||||||
|
public static float InverseLerp(float a, float b, float value) => (double)a != (double)b ? (float)(((double)value - (double)a) / ((double)b - (double)a)) : 0.0f;
|
||||||
|
|
||||||
|
public static double SmoothStep(double x) => x * x * (3.0 - 2.0 * x);
|
||||||
|
|
||||||
|
public static float SmoothStep(float x) => (float)((double)x * (double)x * (3.0 - 2.0 * (double)x));
|
||||||
|
|
||||||
|
public static double SmoothStep(double a, double b, double t) => VTMath.Lerp(a, b, VTMath.SmoothStep(t));
|
||||||
|
|
||||||
|
public static float SmoothStep(float a, float b, float t) => VTMath.Lerp(a, b, VTMath.SmoothStep(t));
|
||||||
|
|
||||||
|
public static double SmoothStep(double x1, double y1, double x2, double y2, double x)
|
||||||
|
{
|
||||||
|
double t = x1 != x2 ? VTMath.InverseLerp(x1, x2, x) : 0.5;
|
||||||
|
return VTMath.SmoothStep(y1, y2, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float SmoothStep(float x1, float y1, float x2, float y2, float x)
|
||||||
|
{
|
||||||
|
float t = (double)x1 != (double)x2 ? VTMath.InverseLerp(x1, x2, x) : 0.5f;
|
||||||
|
return VTMath.SmoothStep(y1, y2, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double InverseSmoothStep(double a, double b, double value) => VTMath.InverseSmoothStep(VTMath.InverseLerp(a, b, value));
|
||||||
|
|
||||||
|
public static double InverseSmoothStep(double x)
|
||||||
|
{
|
||||||
|
x = 1.0 - 2.0 * x;
|
||||||
|
return 0.5 - Math.Sin(Math.Asin(x) / 3.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double SmoothStepDerivative(double x) => 6.0 * x * (1.0 - x);
|
||||||
|
|
||||||
|
public static double SmoothStepDerivative(double a, double b, double t) => 6.0 * t * (b - a) * (1.0 - t);
|
||||||
|
|
||||||
|
public static double Round(double value, double step) => step * Math.Round(value / step);
|
||||||
|
|
||||||
|
public static float Round(float value, float step) => step * Mathf.Round(value / step);
|
||||||
|
|
||||||
|
public static double Floor(double value, double step) => step * Math.Floor(value / step);
|
||||||
|
|
||||||
|
public static float Floor(float value, float step) => step * Mathf.Floor(value / step);
|
||||||
|
|
||||||
|
public static double Ceil(double value, double step) => step * Math.Ceiling(value / step);
|
||||||
|
|
||||||
|
public static float Ceil(float value, float step) => step * Mathf.Ceil(value / step);
|
||||||
|
|
||||||
|
public static double DistancePointToLineSegment(
|
||||||
|
Vector3d point,
|
||||||
|
Vector3d lineStart,
|
||||||
|
Vector3d lineEnd)
|
||||||
|
{
|
||||||
|
return Vector3d.Magnitude(VTMath.ProjectPointToLineSegment(point, lineStart, lineEnd) - point);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3d ProjectPointToLineSegment(
|
||||||
|
Vector3d point,
|
||||||
|
Vector3d lineStart,
|
||||||
|
Vector3d lineEnd)
|
||||||
|
{
|
||||||
|
double lineParameter = VTMath.ProjectPointToLineParameter(point, lineStart, lineEnd);
|
||||||
|
return Vector3d.LerpClamped(lineStart, lineEnd, lineParameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double ProjectPointToLineParameter(
|
||||||
|
Vector3d point,
|
||||||
|
Vector3d lineStart,
|
||||||
|
Vector3d lineEnd)
|
||||||
|
{
|
||||||
|
Vector3d rhs = point - lineStart;
|
||||||
|
Vector3d vector3d = lineEnd - lineStart;
|
||||||
|
return Vector3d.Dot(vector3d, rhs) / Vector3d.SqrMagnitude(vector3d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: edfe6b3cfb01f654bb5045ca7a9217f8
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Assets
|
||||||
|
{
|
||||||
|
public struct Vector3d : IEquatable<Vector3d>
|
||||||
|
{
|
||||||
|
private static readonly Vector3d ZeroVector = new Vector3d(0.0, 0.0, 0.0);
|
||||||
|
private static readonly Vector3d OneVector = new Vector3d(1.0, 1.0, 1.0);
|
||||||
|
public double x;
|
||||||
|
public double y;
|
||||||
|
public double z;
|
||||||
|
|
||||||
|
public Vector3d(double x, double y, double z)
|
||||||
|
{
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3d(double[] c)
|
||||||
|
{
|
||||||
|
this.x = c[0];
|
||||||
|
this.y = c[1];
|
||||||
|
this.z = c[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3d Zero => Vector3d.ZeroVector;
|
||||||
|
|
||||||
|
public static Vector3d One => Vector3d.OneVector;
|
||||||
|
|
||||||
|
public Vector3d Normalized => Vector3d.Normalize(this);
|
||||||
|
|
||||||
|
public double this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return this.x;
|
||||||
|
case 1:
|
||||||
|
return this.y;
|
||||||
|
case 2:
|
||||||
|
return this.z;
|
||||||
|
default:
|
||||||
|
throw new IndexOutOfRangeException("Invalid Vector3d index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
this.x = value;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
this.y = value;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
this.z = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IndexOutOfRangeException("Invalid Vector3d index!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Set(double newX, double newY, double newZ)
|
||||||
|
{
|
||||||
|
this.x = newX;
|
||||||
|
this.y = newY;
|
||||||
|
this.z = newZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double Magnitude(Vector3d v) => Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||||
|
|
||||||
|
public static double SqrMagnitude(Vector3d v) => v.x * v.x + v.y * v.y + v.z * v.z;
|
||||||
|
|
||||||
|
public static Vector3d Lerp(Vector3d a, Vector3d b, double t) => new Vector3d((1.0 - t) * a.x + t * b.x, (1.0 - t) * a.y + t * b.y, (1.0 - t) * a.z + t * b.z);
|
||||||
|
|
||||||
|
public static Vector3d LerpClamped(Vector3d a, Vector3d b, double t)
|
||||||
|
{
|
||||||
|
t = VTMath.Clamp01(t);
|
||||||
|
return Vector3d.Lerp(a, b, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3d Scale(Vector3d a, Vector3d b) => new Vector3d(a.x * b.x, a.y * b.y, a.z * b.z);
|
||||||
|
|
||||||
|
public void Scale(Vector3d scale)
|
||||||
|
{
|
||||||
|
this.x *= scale.x;
|
||||||
|
this.y *= scale.y;
|
||||||
|
this.z *= scale.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3d Cross(Vector3d lhs, Vector3d rhs) => new Vector3d(lhs.y * rhs.z - lhs.z * rhs.y, lhs.z * rhs.x - lhs.x * rhs.z, lhs.x * rhs.y - lhs.y * rhs.x);
|
||||||
|
|
||||||
|
public override int GetHashCode() => this.x.GetHashCode() ^ this.y.GetHashCode() << 2 ^ this.z.GetHashCode() >> 2;
|
||||||
|
|
||||||
|
public override bool Equals(object other) => other is Vector3d other1 && this.Equals(other1);
|
||||||
|
|
||||||
|
public bool Equals(Vector3d other) => this == other;
|
||||||
|
|
||||||
|
public static Vector3d Normalize(Vector3d value)
|
||||||
|
{
|
||||||
|
double num = Vector3d.Magnitude(value);
|
||||||
|
return num > 0.0 ? value / num : Vector3d.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Normalize()
|
||||||
|
{
|
||||||
|
double num = Vector3d.Magnitude(this);
|
||||||
|
if (num > 0.0)
|
||||||
|
this = this / num;
|
||||||
|
else
|
||||||
|
this = Vector3d.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double Dot(Vector3d lhs, Vector3d rhs) => lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
|
||||||
|
|
||||||
|
public static double Distance(Vector3d a, Vector3d b)
|
||||||
|
{
|
||||||
|
double num1 = a.x - b.x;
|
||||||
|
double num2 = a.y - b.y;
|
||||||
|
double num3 = a.z - b.z;
|
||||||
|
return Math.Sqrt(num1 * num1 + num2 * num2 + num3 * num3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3d operator +(Vector3d a, Vector3d b) => new Vector3d(a.x + b.x, a.y + b.y, a.z + b.z);
|
||||||
|
|
||||||
|
public static Vector3d operator -(Vector3d a, Vector3d b) => new Vector3d(a.x - b.x, a.y - b.y, a.z - b.z);
|
||||||
|
|
||||||
|
public static Vector3d operator -(Vector3d a) => new Vector3d(-a.x, -a.y, -a.z);
|
||||||
|
|
||||||
|
public static Vector3d operator *(Vector3d a, double d) => new Vector3d(a.x * d, a.y * d, a.z * d);
|
||||||
|
|
||||||
|
public static Vector3d operator *(double d, Vector3d a) => new Vector3d(a.x * d, a.y * d, a.z * d);
|
||||||
|
|
||||||
|
public static Vector3d operator /(Vector3d a, double d) => new Vector3d(a.x / d, a.y / d, a.z / d);
|
||||||
|
|
||||||
|
public static bool operator ==(Vector3d lhs, Vector3d rhs) => lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z;
|
||||||
|
|
||||||
|
public static bool operator !=(Vector3d lhs, Vector3d rhs) => !(lhs == rhs);
|
||||||
|
|
||||||
|
public override string ToString() => this.ToString((string)null);
|
||||||
|
|
||||||
|
public string ToString(string format)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(format))
|
||||||
|
format = "F2";
|
||||||
|
return "(" + this.x.ToString(format) + ", " + this.y.ToString(format) + ", " + this.z.ToString(format) + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8454158d7f8e40a47b7134e3fcb68882
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets.AR
|
||||||
|
{
|
||||||
|
public class VideoPlayerControl
|
||||||
|
{
|
||||||
|
private const float MinVideoPlaybackSpeedChangeInterval = 0.2f;
|
||||||
|
private const float MaxPlaybackSpeed = 1.5f;
|
||||||
|
private const float MaxCameraDistanceError = 200f;
|
||||||
|
private DateTime lastPlaybackSpeedChange = DateTime.MinValue;
|
||||||
|
private float fixedTimeFrame;
|
||||||
|
private DateTime fixedTimeSeekFinished = DateTime.MinValue;
|
||||||
|
private int lapCount = 1;
|
||||||
|
private double lapLength;
|
||||||
|
|
||||||
|
public float FixedVideoFrame => this.fixedTimeFrame;
|
||||||
|
|
||||||
|
//public IDistanceSource RiderDistance { get; set;
|
||||||
|
|
||||||
|
public AVProVideoPlayer VideoPlayer { get; private set; }
|
||||||
|
|
||||||
|
//public ISpeedSource RiderSpeed { get; set; }
|
||||||
|
|
||||||
|
public VideoPointsSync VideoSyncSource { get; set; }
|
||||||
|
|
||||||
|
public ARRoute Route { get; set; }
|
||||||
|
|
||||||
|
public int VideoFrameOffset { get; set; }
|
||||||
|
|
||||||
|
public float CameraFollowDistance { get; set; }
|
||||||
|
|
||||||
|
public bool AllowUpdate { get; set; } = true;
|
||||||
|
|
||||||
|
public float CameraDistanceError { get; private set; }
|
||||||
|
|
||||||
|
public bool IsTimeFixed { get; private set; }
|
||||||
|
|
||||||
|
public float FrameIndexDistanceCorrection { get; private set; }
|
||||||
|
|
||||||
|
public bool IsMultilap => this.lapCount > 1;
|
||||||
|
|
||||||
|
public void SetVideoPlayer(AVProVideoPlayer player) => this.VideoPlayer = player;
|
||||||
|
|
||||||
|
public void SetMultiLap(int lapCount, double lapLength)
|
||||||
|
{
|
||||||
|
this.lapCount = lapCount;
|
||||||
|
this.lapLength = lapLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FixTimeByDistance(float distance) => this.FixTimeByFrame(this.VideoSyncSource.GetVideoFrameAtDistance(distance));
|
||||||
|
|
||||||
|
public void FixTimeByFrame(float frame)
|
||||||
|
{
|
||||||
|
this.IsTimeFixed = true;
|
||||||
|
this.fixedTimeFrame = frame;
|
||||||
|
this.fixedTimeSeekFinished = DateTime.MinValue;
|
||||||
|
if (this.VideoPlayer.IsPaused)
|
||||||
|
this.VideoPlayer.Resume();
|
||||||
|
this.VideoPlayer.SetPlaybackSpeed(0.25f);
|
||||||
|
this.VideoPlayer.Seek((long)frame, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//public void UnFixTime()
|
||||||
|
//{
|
||||||
|
// this.IsTimeFixed = false;
|
||||||
|
// float videoFrameAtDistance = this.VideoSyncSource.GetVideoFrameAtDistance(this.RiderDistance.LapDistance);
|
||||||
|
// float num = this.VideoSyncSource.AverageVideoSpeed(videoFrameAtDistance, videoFrameAtDistance);
|
||||||
|
// float playbackSpeed = (double)num != 0.0 ? this.RiderSpeed.Speed / num : 0.0f;
|
||||||
|
// if (this.VideoPlayer.IsPaused)
|
||||||
|
// this.VideoPlayer.Resume();
|
||||||
|
// this.VideoPlayer.SetPlaybackSpeed(playbackSpeed);
|
||||||
|
// this.lastPlaybackSpeedChange = DateTime.UtcNow;
|
||||||
|
// this.VideoPlayer.Seek((long)videoFrameAtDistance, true);
|
||||||
|
//}
|
||||||
|
|
||||||
|
private void SkipVideoToDistance(float distance) => this.SkipVideoToFrame((long)this.VideoSyncSource.GetVideoFrameAtDistance(distance));
|
||||||
|
|
||||||
|
private void SkipVideoToFrame(long frame) => this.VideoPlayer.Seek(frame);
|
||||||
|
|
||||||
|
public void UpdateVideoPlaybackSpeed(float speed, float routeDistance)
|
||||||
|
{
|
||||||
|
if (!this.AllowUpdate)
|
||||||
|
return;
|
||||||
|
if (this.IsTimeFixed)
|
||||||
|
{
|
||||||
|
if (this.VideoPlayer.IsSeeking)
|
||||||
|
return;
|
||||||
|
if (this.fixedTimeSeekFinished == DateTime.MinValue)
|
||||||
|
this.fixedTimeSeekFinished = DateTime.UtcNow;
|
||||||
|
if (DateTime.UtcNow.Subtract(this.fixedTimeSeekFinished).TotalSeconds < 0.25)
|
||||||
|
return;
|
||||||
|
if ((double)this.VideoPlayer.CurrentFrame > (double)this.fixedTimeFrame)
|
||||||
|
this.VideoPlayer.Pause();
|
||||||
|
|
||||||
|
this.VideoPlayer.UpdateCurrentFrame();
|
||||||
|
this.FrameIndexDistanceCorrection = 0.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float videoFrameAtDistance1 = this.VideoSyncSource.GetVideoFrameAtDistance(routeDistance);
|
||||||
|
float val2 = routeDistance - this.CameraFollowDistance;
|
||||||
|
//if (this.IsMultilap && (double)this.RiderDistance.RouteDistance > (double)distance && (double)val2 < 0.0)
|
||||||
|
// val2 += (float)this.lapLength;
|
||||||
|
float distance = Math.Max(0.0f, val2);
|
||||||
|
float frame = this.VideoSyncSource.GetVideoFrameAtDistance(distance) + (float)this.VideoFrameOffset;
|
||||||
|
if (this.Route != null && (double)this.Route.GetVisibility(frame) > 10.0)
|
||||||
|
frame = (float)this.Route.GetFrameAtDistance(Math.Max(0.0, this.Route.GetDistanceForFrame((double)videoFrameAtDistance1) - (double)this.CameraFollowDistance)) + (float)this.VideoFrameOffset;
|
||||||
|
|
||||||
|
this.VideoPlayer.UpdateCurrentFrame();
|
||||||
|
|
||||||
|
float distanceForVideoFrame = this.VideoSyncSource.GetDistanceForVideoFrame(this.VideoPlayer.CurrentFrame - (float)this.VideoFrameOffset);
|
||||||
|
float f;
|
||||||
|
if (this.Route != null)
|
||||||
|
{
|
||||||
|
double frameAtDistance = this.Route.GetFrameAtDistance(this.Route.GetDistanceForFrame((double)this.VideoPlayer.CurrentFrame - (double)this.VideoFrameOffset) + (double)Mathf.Min(routeDistance, this.CameraFollowDistance));
|
||||||
|
f = videoFrameAtDistance1 - (float)frameAtDistance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f = frame - (this.VideoPlayer.CurrentFrame - (float)this.VideoFrameOffset);
|
||||||
|
float num1 = Mathf.Clamp01(VTMath.Lerp(0.0f, 1f, 100f, 0.0f, Mathf.Abs(f)));
|
||||||
|
this.FrameIndexDistanceCorrection = f * num1;
|
||||||
|
this.CameraDistanceError = distance - distanceForVideoFrame;
|
||||||
|
if (this.IsMultilap)
|
||||||
|
{
|
||||||
|
float num2 = distance - (distanceForVideoFrame + (float)this.lapLength);
|
||||||
|
if ((double)Math.Abs(num2) < (double)Math.Abs(this.CameraDistanceError) && (double)Math.Abs(num2) < 200.0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((double)Math.Abs(this.CameraDistanceError) > 200.0)
|
||||||
|
{
|
||||||
|
this.SkipVideoToDistance(distance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double totalSeconds = DateTime.UtcNow.Subtract(this.lastPlaybackSpeedChange).TotalSeconds;
|
||||||
|
if (totalSeconds >= 0.0 && totalSeconds < 0.20000000298023224)
|
||||||
|
return;
|
||||||
|
float num3 = 1f;
|
||||||
|
float num4 = num3 * speed;
|
||||||
|
if ((double)Math.Abs(distance + num4 - this.VideoSyncSource.GetDistanceForVideoFrame((float)((double)this.VideoPlayer.CurrentFrame - (double)this.VideoFrameOffset + (double)num3 * (double)this.VideoPlayer.PlaybackSpeed * (double)this.VideoPlayer.FrameRate))) <= (double)Math.Abs(this.CameraDistanceError))
|
||||||
|
return;
|
||||||
|
float videoFrameAtDistance2 = this.VideoSyncSource.GetVideoFrameAtDistance(routeDistance + num4);
|
||||||
|
float num5 = this.VideoSyncSource.AverageVideoSpeed(videoFrameAtDistance1, videoFrameAtDistance2);
|
||||||
|
float playbackSpeed = Mathf.Clamp(((double)num5 != 0.0 ? speed / num5 : 0.0f) + (float)(((double)frame - ((double)this.VideoPlayer.CurrentFrame - (double)this.VideoFrameOffset)) / 2.0) / this.VideoPlayer.FrameRate, 0.0f, 1.5f);
|
||||||
|
if ((double)playbackSpeed == (double)this.VideoPlayer.PlaybackSpeed || !this.VideoPlayer.SetPlaybackSpeed(playbackSpeed))
|
||||||
|
return;
|
||||||
|
this.lastPlaybackSpeedChange = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void UpdateVideoPlaybackSpeed(double speed, float distance)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9f244e092373e2d40935fd6ec79c8af7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Assets
|
||||||
|
{
|
||||||
|
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fe1742dfacafb6e429b9388feba5699a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"Route":{"Visibility":[465,465,340,340,340,339,339,338,338,337,337,336,336,336,335,335,334,334,334,333,333,332,332,332,331,331,331,331,331,330,330,330,330,330,329,329,329,328,328,328,327,327,327,326,326,326,325,325,324,324,323,323,323,322,322,322,322,321,321,320,320,320,320,319,319,318,318,318,318,317,317,317,316,316,316,315,315,314,314,314,313,313,313,313,312,312,312,312,312,311,311,311,310,310,310,310,310,309,309,309,308,308,308,308,307,307,307,307,307,306,306,306,306,305,306,305,305,305,304,304,305,304,304,304,303,303,303,303,303,303,302,302,302,302,302,302,301,301,301,301,301,300,301,300,300,300,300,300,300,300,299,299,299,299,299,299,298,298,298,298,298,298,297,297,297,297,297,297,297,297,297,296,296,296,296,296,296,296,296,296,296,296,295,295,295,295,295,295,295,295,295,295,294,294,294,294,294,294,294,293,293,293,293,293,293,293,292,292,292,292,292,292,292,292,292,291,291,291,291,291,291,291,290,290,290,290,290,290,290,289,289,290,290,289,289,289,289,289,289,289,288,288,289,288,288,288,288,288,288,288,288,288,288,288,287,287,287,287,287,287,287,287,287,286,286,286,286,286,286,286,286,286,286,285,285,285,285,285,284,284,284,284,284,284,284,284,284,283,283,283,283,283,283,283,283,283,282,282,282,282,282,282,282,282,282,282,282,282,282,282,281,281,281,281,281,281,281,281,280,280,280,280,280,280,280,280,280,280,280,280,280,280,279,279,279,279,279,279,279,279,279,278,279,279,278,278,278,278,278,278,278,278,278,278,278,278,277,278,278,278,278,278,278,278,278,278,278,278,278,277,278,278,277,277,278,277,277,277,277,277,277,277,277,277,277,276,277,277,277,276,276,276,277,276,276,276,276,276,276,276,276,276,276,275,276,276,276,275,275,275,275,275,275,275,275,275,275,275,275,275,274,274,274,274,274,274,274,274,274,274,274,273,274,274,274,273,273,273,273,273,273,273,273,273,273,273,273,273,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,271,271,271,271,271,271,271,271,271,271,270,271,271,271,270,271,271,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,271,270,271,270,271,270,271,270,271,270,271,271,271,271,271,271,271,271,271,271,271,271,271,272,271,272,271,272,271,272,272,272,272,272,271,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,273,273,273,273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,276,275,276,275,275,275,275,276,275,276,276,276,276,276,277,276,277,277,277,277,277,278,277,278,278,278,278,278,278,279,278,279,278,279,279,279,279,279,279,279,280,279,280,280,280,280,280,280,280,281,280,281,281,281,281,281,282,281,282,282,282,282,282,282,283,283,283,283,284,283,284,284,284,284,284,284,284,285,285,285,285,285,285,285,286,286,286,286,286,286,286,287,287,287,287,287,287,288,287,288,288,288,288,288,289,288,288,289,289,289,289,290,289,290,289,290,290,290,290,290,291,290,291,290,291,291,291,291,291,291,291,292,292,292,292,292,292,292,293,293,292,292,293,293,293,293,292,293,293,293,293,293,293,293,293,293,294,293,293,294,293,293,293,293,294,294,294,294,293,294,294,294,294,294,294,294,295,294,295,295,295,295,295,295,295,295,295,295,296,296,296,296,296,296,296,296,296,296,296,297,297,297,297,297,297,297,297,297,297,297,298,298,298,298,298,298,298,298,299,299,298,299,299,299,299,299,299,299,299,299,300,300,300,300,300,300,299,300,300,300,300,301,301,301,301,302,301,301,302,301,302,302,302,302,302,302,302,302,303,302,303,303,302,303,303,303,303,303,303,304,303,303,303,303,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,303,304,304,304,304,304,304,304,304,304,304,304,304,304,304,303,304,304,304,303,303,304,304,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,304,303,303,303,303,303,303,303,303,303,303,303,303,303,303,304,303,303,303,303,303,303,304,303,303,304,303,303,304,303,303,303,304,303,303,304,303,303,303,304,303,303,304,303,303,304,304,303,303,304,303,304,304,303,304,303,304,303,304,304,303,304,303,303,304,303,303,303,303,303,303,303,303,303,302,303,303,302,303,302,303,303,302,302,303,302,303,302,302,302,302,302,302,302,302,302,301,301,301,300,300,300,300,300,299,299,299,298,298,299,298,298,298,297,297,297,297,297,297,296,296,296,296,296,295,295,294,294,294,294,294,294,293,294,294,293,293,293,292,292,292,293,292,292,292,292,292,291,291,291,291,291,290,290,290,290,290,290,289,289,289,289,289,289,289,288,288,288,288,288,287,287,287,287,287,286,286,286,286,286,286,286,285,285,285,285,285,284,284,284,284,284,283,283,283,283,283,282,282,282,282,282,282,281,281,281,281,281,281,280,280,280,280,279,279,279,279,278,278,278,278,278,277,277,277,277,276,276,276,276,276,275,275,275,275,275,275,274,274,274,274,273,273,273,272,272,272,272,272Line truncated
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 341c9bc6edccecd498b3d3b74b08f3b9
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"Route":{"Visibility":[460,460,205,205,205,205,205,205,205,205,205,205,206,205,205,206,205,206,205,205,206,205,206,206,206,206,206,206,206,206,206,207,206,206,207,206,207,207,206,207,206,207,207,207,207,207,207,207,207,207,208,207,207,208,207,208,208,207,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,209,208,209,209,208,209,209,209,209,209,209,209,209,209,210,210,209,209,210,210,209,210,210,210,210,210,210,211,210,210,211,211,210,210,211,211,210,211,211,211,210,211,211,211,211,211,211,211,211,211,211,211,212,211,211,212,212,211,212,212,212,212,212,212,213,212,212,213,213,213,213,213,213,213,213,213,214,213,213,214,214,214,214,214,214,215,214,214,215,215,214,215,215,215,215,215,216,216,215,216,216,216,216,216,216,216,216,216,216,217,217,216,217,217,217,217,217,217,217,217,218,218,217,218,218,218,218,218,219,219,218,218,219,219,219,219,219,219,219,219,219,220,220,219,220,220,220,220,220,220,220,220,221,221,220,221,221,221,221,221,221,221,221,221,222,222,221,222,222,222,222,222,222,223,223,222,223,223,223,222,223,223,223,223,223,223,224,224,223,224,224,224,224,224,224,224,224,224,225,224,224,225,225,225,225,225,226,226,225,226,226,226,226,226,226,226,226,226,227,226,226,226,227,227,226,227,227,227,227,227,227,227,227,227,227,228,227,227,228,228,228,228,228,228,228,228,228,228,228,228,228,228,227,228,227,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,227,228,228,228,228,228,228,228,228,228,228,228,228,228,227,228,228,227,228,228,227,228,228,227,228,227,227,228,227,227,228,227,227,228,227,228,227,227,228,227,227,228,227,227,228,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,225,222,219,219,219,216,214,214,213,214,211,211,211,211,211,209,208,203,203,203,203,203,203,203,203,203,203,203,203,198,198,198,198,198,197,198,198,192,190,190,189,190,190,184,182,182,181,182,181,179,176,176,177,176,171,169,166,163,163,163,163,163,163,160,158,158,157,158,157,157,158,157,158,158,157,157,158,157,157,157,157,157,157,157,154,155,154,155,155,154,150,149,149,149,149,146,147,144,144,144,144,141,141,141,141,139,138,138,138,138,139,136,135,136,136,135,136,136,133,133,133,133,133,130,130,128,127,127,128,127,128,128,125,125,125,125,125,125,124,125,125,124,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,121,122,122,121,122,122,121,122,122,121,122,122,122,122,121,122,122,121,122,121,121,131,132,131,136,137,137,137,137,136,139,142,141,144,144,146,147,146,149,149,207,207,212,212,211,212,211,211,212,211,211,211,211,211,211,211,211,211,211,210,211,211,210,211,210,210,210,210,211,210,210,210,210,210,210,210,210,210,210,210,207,207,204,205,204,202,202,202,202,202,202,200,199,199,200,199,199,199,199,200,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,198,199,199,199,199,198,199,199,198,199,198,199,199,198,199,198,198,199,198,198,199,198,199,199,198,198,199,198,199,198,198,199,198,198,199,198,198,198,198,198,199,198,198,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,217,216,216,217,216,216,217,216,216,217,216,216,217,217,216,217,217,217,217,217,217,217,217,218,218,217,218,218,218,217,218,218,218,218,218,218,218,218,218,218,218,218,219,219,218,219,219,219,219,219,219,220,219,219,220,220,219,220,220,220,219,220,220,220,220,220,220,220,220,220,221,220,220,221,221,220,221,221,221,221,221,221,221,221,221,221,221,221,222,222,221,221,222,222,221,221,222,222,221,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,223,222,222,222,223,222,222,223,223,222,223,223,223,223,223,223,223,223,223,224,223,223,224,224,223,224,224,224,224,224,224,224,224,224,225,224,224,225,225,225,225,225,225,225,225,225,226,225,225,226,226,225,225,226,226,225,226,226,226,226,226,226,226,226,226,227,226,226,227,227,226,227,227,227,227,227,227,227,227,227,227,227,228,227,227,227,228,228,227,227,228,228,228,228,228,228,229,229,229,228,229,229,229,229,229,229,230,229,229,230,230,229,230,230,230,230,230,230,231,230,230,231,230,230,231,231,230,231,231,231,231,231,231,232,231,231,232,232,231,232,232,232,232,232,232,232,232,232,233,233,232,233,233,233,233,233,233,233,233,233,234,233,233,234,234,233,234,234,234,234,234,234,234,234,234,235,234,234,235,235,235,235,235,235,236,235,235,236,236,236,236,236,236,236,236,236,237,237,237,237,237,237,237,237,237,238,238,237,238,238,238,238,238,238,239,239,238,239,239,239,239,239,239,240,239,239,240,240,240,240,240,240,241,240,240,241,241,240,241,241,241,241,241,241,242,241,241,242,242,242,242,242,242,243,242,242,243,243,242,243,243,243,243,243,243,244,243,243,244,244,244,244,244,245,244,244,244,245,245,244,245,245,245,245,245,245,246,245,245,246,246,245,246,246,246,246,246,246,246,246,246,247,246,246,247,247,246,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247Line truncated
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f2e696010ab476541b5d4458dbc3b21e
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"Route":{"Visibility":[465,465,235,235,235,236,236,236,236,236,237,236,237,237,237,237,237,238,237,238,238,238,238,239,238,239,239,239,239,239,239,240,240,240,240,240,240,241,240,240,241,241,241,241,241,242,241,242,242,242,242,242,243,243,242,240,240,240,240,237,235,234,235,235,236,235,235,236,236,236,236,236,237,237,237,237,237,238,238,238,238,238,239,239,240,239,239,240,237,237,238,234,234,235,234,235,235,235,235,232,233,233,233,230,230,230,230,230,231,230,228,224,222,222,222,218,219,219,219,216,213,214,210,211,211,211,211,211,211,211,211,212,208,208,208,209,209,209,209,209,210,209,209,210,210,210,214,213,214,217,217,217,221,224,224,224,227,234,237,243,246,249,252,255,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,259,259,258,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,259,260,259,259,259,259,259,259,259,259,259,259,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,257,258,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,258,257,257,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,259,259,259,259,259,259,259,259,260,260,260,260,260,260,260,260,260,260,260,261,261,261,261,261,261,261,261,261,262,262,262,262,262,262,262,262,263,263,263,263,263,263,263,263,263,263,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,266,265,265,265,265,265,266,265,266,265,265,265,266,265,265,265,266,266,266,266,265,266,265,266,266,265,265,266,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,264,264,264,264,264,264,264,264,264,264,263,263,263,263,263,263,263,263,262,262,262,262,262,262,262,262,262,262,262,262,261,261,261,261,261,261,261,261,261,260,260,260,260,260,260,260,260,259,259,259,259,259,259,259,258,258,258,258,258,258,258,258,258,258,257,257,257,257,257,257,257,257,257,256,256,256,256,256,256,256,256,256,256,256,255,255,255,255,255,255,255,255,254,254,254,254,254,254,254,254,254,254,254,254,253,253,253,253,253,253,253,253,253,253,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,251,251,251,251,251,251,251,251,251,251,251,251,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,248,249,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,247,248,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,246,247,247,246,246,247,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,240,234,229,223,220,220,217,214,208,206,200,197,197,197,197,191,189,186,186,185,185,185,186,186,186,185,185,185,183,180,179,179,174,174,174,174,174,174,174,174,171,165,163,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,161,161,161,161,161,162,162,162,162,162,162,162,162,161,162,162,162,162,162,162,162,162,162,162,162,165,165,171,171,171,171,171,171,171,171,171,172,172,171,171,172,172,172,172,172,172,172,172,172,172,173,173,173,172,175,175,176,176,179,178,181,182,182,184,184,185,185,185,184,185,185,188,188,188,188,191,191,191,191,191,191,194,194,194,194,194,194,194,194,194,195,195,195,195,195,195,195,195,195,195,195,195,195,196,196,196,196,196,196,196,196,196,196,196,196,197,197,196,196,197,197,197,197,197,198,198,197,197,198,198,198,198,197,198,198,198,199,198,199,199,199,199,199,199,199,199,199,199,200,200,199,196,193,193,193,193,193,193,194,193,190,190,187,187,184,181,181,181,178,175,175,169,165,165,165,166,166,166,166,166,166,166,166,166,166,166,167,167,167,167,167,167,167,167,167,167,167,168,167,167,167,167,168,168,168,168,168,168,168,168,168,168,169,169,169,169,169,169,169,169,169,166,166,166,166,167,160,160,160,160,160,161,160,160,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,158,158,158,158,158,158,159,158,158,158,155,155,155,155,155,155,155,155,155,152,152,152,152,152,151,151,151,148,149,148,146,146,145,145,145,145,145,145,145,145,145,145,145,145,145,142,142,141,141,138,138,138,138,138,138,138,135,135,135,135,132,132,132,132,129,129,129,129,129,128,122,122,122,122,122,122,122,122,122,122,122,121,121,121,119,118,115,115,115,115,115,115,115,115,115,115,112,112,112,112,112,112,109,109,109,109,108,108,105,105,105,105,106,102,99,97,96,96,93,93,93,93,93,93,93,93,90,90,90,90,90,90,90,90,90,90,84,84,81,81,81,81,78,79,79,79,79,79,78,78,78,78,78,78,78,78,78,78,78,78,7Line truncated
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 329bdb26604fbd6499707e6457df4921
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 874a748024ffda74a841855f69348615
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File renamed without changes.
File renamed without changes.
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4d018f8014dec174390f06f9fa947a05
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"RouteInfo":{"Name":"Cape Point | Cape Town | Tour of South Africa","CountryCode":"ZA","VideoScreen":"https://cdn.virtualtraining.eu/routes/84288/video/thumbnail_313x147.png","Profile":"https://cdn.virtualtraining.eu/routes/84288/profile/profile_313x147_transparent.png","Version":1,"Rating":5,"RatingCount":3666,"Length":27700,"Upclimb":344,"MaxSlope":9,"AvgSlope":1,"IsFavourite":false,"ARFileUrl":"https://cdn.virtualtraining.eu/routes/84288/ar/84288","Videos":[{"IsOFlow":false,"Quality":540,"Url":"https://mediacdn.rouvy.com/routes/84288/video/84288_540.mp4","Size":654946148},{"IsOFlow":false,"Quality":720,"Url":"https://mediacdn.rouvy.com/routes/84288/video/84288_720.mp4","Size":1308886312},{"IsOFlow":false,"Quality":1080,"Url":"https://mediacdn.rouvy.com/routes/84288/video/84288_1080.mp4","Size":3924921189},{"IsOFlow":false,"Quality":1440,"Url":"https://mediacdn.rouvy.com/routes/84288/video/84288_1440.mp4","Size":6541877926},{"IsOFlow":true,"Quality":540,"Url":"https://mediacdn.rouvy.com/routes/84288/video/84288_540_ar.mp4","Size":654965182},{"IsOFlow":true,"Quality":720,"Url":"https://mediacdn.rouvy.com/routes/84288/video/84288_720_ar.mp4","Size":1308964317},{"IsOFlow":true,"Quality":1080,"Url":"https://mediacdn.rouvy.com/routes/84288/video/84288_1080_ar.mp4","Size":3924915981},{"IsOFlow":true,"Quality":1440,"Url":"https://mediacdn.rouvy.com/routes/84288/video/84288_1440_ar.mp4","Size":6541969663}],"SuitableForRunning":false,"SuitableForCycling":true,"IsMultiLap":false,"LiveSegmentsCount":0,"Categories":[41,45,46,49],"LastRefreshed":"2022-11-25T07:50:51.602Z","Id":84288},"Geometry":[{"Latitude":-34.20594075155,"Longitude":18.45782935967,"Distance":0,"Altitude":15.2},{"Latitude":-34.20612280453,"Longitude":18.45797177578,"Distance":24.108,"Altitude":15.106},{"Latitude":-34.20630485751,"Longitude":18.45811419189,"Distance":48.215,"Altitude":15.261},{"Latitude":-34.20658778865,"Longitude":18.45832818188,"Distance":85.319,"Altitude":15.683},{"Latitude":-34.20687071979,"Longitude":18.45854217187,"Distance":122.422,"Altitude":16.355},{"Latitude":-34.20704388991,"Longitude":18.45869086683,"Distance":146.036,"Altitude":16.873},{"Latitude":-34.20721001923,"Longitude":18.45883067697,"Distance":168.54,"Altitude":17.242},{"Latitude":-34.20737614855,"Longitude":18.45897048712,"Distance":191.044,"Altitude":17.51},{"Latitude":-34.20754043385,"Longitude":18.45910845324,"Distance":213.282,"Altitude":17.541},{"Latitude":-34.20770471916,"Longitude":18.45924641937,"Distance":235.521,"Altitude":17.471},{"Latitude":-34.20794703998,"Longitude":18.45947256312,"Distance":269.553,"Altitude":17.366},{"Latitude":-34.20807268471,"Longitude":18.4596697893,"Distance":292.444,"Altitude":17.498},{"Latitude":-34.20822624117,"Longitude":18.46000548452,"Distance":327.718,"Altitude":17.612},{"Latitude":-34.20836647041,"Longitude":18.46020229161,"Distance":351.604,"Altitude":17.655},{"Latitude":-34.20853280928,"Longitude":18.46036322415,"Distance":375.289,"Altitude":17.814},{"Latitude":-34.20869914815,"Longitude":18.46052415669,"Distance":398.974,"Altitude":18.174},{"Latitude":-34.20895257499,"Longitude":18.46072838176,"Distance":432.834,"Altitude":18.816},{"Latitude":-34.20920600183,"Longitude":18.46093260683,"Distance":466.694,"Altitude":19.709},{"Latitude":-34.20951663516,"Longitude":18.46118724905,"Distance":508.419,"Altitude":21.258},{"Latitude":-34.20967061073,"Longitude":18.46130233258,"Distance":528.544,"Altitude":21.863},{"Latitude":-34.20991502702,"Longitude":18.46145153046,"Distance":558.985,"Altitude":22.366},{"Latitude":-34.21025524847,"Longitude":18.46163945273,"Distance":600.571,"Altitude":22.467},{"Latitude":-34.21070728451,"Longitude":18.46189417876,"Distance":656.018,"Altitude":22.541},{"Latitude":-34.21113484539,"Longitude":18.46213683486,"Distance":708.53,"Altitude":22.583},{"Latitude":-34.21139476821,"Longitude":18.46227907576,"Distance":740.25,"Altitude":22.69},{"Latitude":-34.21178310178,"Longitude":18.46241972409,"Distance":785.321,"Altitude":23.027},{"Latitude":-34.21213044785,"Longitude":18.4624153655,"Distance":823.941,"Altitude":23.249},{"Latitude":-34.21241048723,"Longitude":18.46236188896,"Distance":855.462,"Altitude":23.088},{"Latitude":-34.21260880306,"Longitude":18.46236700192,"Distance":877.516,"Altitude":23.081},{"Latitude":-34.21310761012,"Longitude":18.4625087399,"Distance":934.485,"Altitude":22.86},{"Latitude":-34.21338974498,"Longitude":18.46261359751,"Distance":967.301,"Altitude":22.55},{"Latitude":-34.21369124204,"Longitude":18.46277335659,"Distance":1003.899,"Altitude":22.493},{"Latitude":-34.21407253481,"Longitude":18.46310494468,"Distance":1056.116,"Altitude":22.384},{"Latitude":-34.21447201632,"Longitude":18.46337039955,"Distance":1106.795,"Altitude":22.427},{"Latitude":-34.21489764936,"Longitude":18.46352839842,"Distance":1156.296,"Altitude":22.276},{"Latitude":-34.21529528685,"Longitude":18.46369444393,"Distance":1203.068,"Altitude":21.87},{"Latitude":-34.21564548276,"Longitude":18.46402351744,Line truncated
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5a1f568492ae0ed498af496a6a4fb796
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"RouteInfo":{"Name":"Gradistei Keys climb to Biathlon Arena | Romania","CountryCode":"RO","VideoScreen":"https://cdn.virtualtraining.eu/routes/88019/video/thumbnail_313x147.png","Profile":"https://cdn.virtualtraining.eu/routes/88019/profile/profile_313x147_transparent.png","Version":1,"Rating":4,"RatingCount":21,"Length":9788,"Upclimb":461,"MaxSlope":14,"AvgSlope":5,"IsFavourite":false,"ARFileUrl":"https://cdn.virtualtraining.eu/routes/88019/ar/88019","Videos":[{"IsOFlow":false,"Quality":540,"Url":"https://mediacdn.rouvy.com/routes/88019/video/88019_540.mp4","Size":335790164},{"IsOFlow":false,"Quality":720,"Url":"https://mediacdn.rouvy.com/routes/88019/video/88019_720.mp4","Size":670919336},{"IsOFlow":false,"Quality":1080,"Url":"https://mediacdn.rouvy.com/routes/88019/video/88019_1080.mp4","Size":2012083660},{"IsOFlow":false,"Quality":1440,"Url":"https://mediacdn.rouvy.com/routes/88019/video/88019_1440.mp4","Size":3354449811},{"IsOFlow":true,"Quality":540,"Url":"https://mediacdn.rouvy.com/routes/88019/video/88019_540_ar.mp4","Size":335820484},{"IsOFlow":true,"Quality":720,"Url":"https://mediacdn.rouvy.com/routes/88019/video/88019_720_ar.mp4","Size":671002738},{"IsOFlow":true,"Quality":1080,"Url":"https://mediacdn.rouvy.com/routes/88019/video/88019_1080_ar.mp4","Size":2012171004},{"IsOFlow":true,"Quality":1440,"Url":"https://mediacdn.rouvy.com/routes/88019/video/88019_1440_ar.mp4","Size":3354665975}],"SuitableForRunning":false,"SuitableForCycling":true,"IsMultiLap":false,"LiveSegmentsCount":0,"Categories":[44,46],"LastRefreshed":"2022-11-25T08:47:31.403Z","Id":88019},"Geometry":[{"Latitude":45.4952196382,"Longitude":25.32992956866,"Distance":0,"Altitude":809.6},{"Latitude":45.49506252632,"Longitude":25.32975666225,"Distance":22.09,"Altitude":809.761},{"Latitude":45.49490032601,"Longitude":25.32957436633,"Distance":45.078,"Altitude":809.999},{"Latitude":45.49475594773,"Longitude":25.32941002864,"Distance":65.64,"Altitude":810.236},{"Latitude":45.49460795475,"Longitude":25.32923402963,"Distance":87.089,"Altitude":810.576},{"Latitude":45.49447858008,"Longitude":25.32906572102,"Distance":106.581,"Altitude":810.949},{"Latitude":45.49435221241,"Longitude":25.32888876856,"Distance":126.294,"Altitude":811.375},{"Latitude":45.49422042794,"Longitude":25.32871821779,"Distance":146.102,"Altitude":811.836},{"Latitude":45.49407375511,"Longitude":25.32854979392,"Distance":167.063,"Altitude":812.251},{"Latitude":45.49392434768,"Longitude":25.32840193715,"Distance":187.306,"Altitude":812.628},{"Latitude":45.49378311262,"Longitude":25.32827759162,"Distance":205.783,"Altitude":812.918},{"Latitude":45.4936451884,"Longitude":25.32815358136,"Distance":223.932,"Altitude":813.156},{"Latitude":45.4934868752,"Longitude":25.3280120634,"Distance":244.731,"Altitude":813.343},{"Latitude":45.4933328263,"Longitude":25.32787103788,"Distance":265.108,"Altitude":813.515},{"Latitude":45.49316209741,"Longitude":25.32772541279,"Distance":287.253,"Altitude":813.78},{"Latitude":45.49299419741,"Longitude":25.32757657114,"Distance":309.259,"Altitude":814.087},{"Latitude":45.49282825668,"Longitude":25.32744723838,"Distance":330.31,"Altitude":814.454},{"Latitude":45.49266655929,"Longitude":25.32733849366,"Distance":350.211,"Altitude":814.734},{"Latitude":45.49249770585,"Longitude":25.3272478329,"Distance":370.296,"Altitude":814.925},{"Latitude":45.49232933437,"Longitude":25.3271953098,"Distance":389.483,"Altitude":815.016},{"Latitude":45.49216314219,"Longitude":25.32721540541,"Distance":408.051,"Altitude":814.856},{"Latitude":45.49198808614,"Longitude":25.32725641388,"Distance":427.8,"Altitude":814.594},{"Latitude":45.49180792761,"Longitude":25.32725827885,"Distance":447.857,"Altitude":814.243},{"Latitude":45.4916347051,"Longitude":25.32718536677,"Distance":467.963,"Altitude":813.99},{"Latitude":45.49146359903,"Longitude":25.32704719109,"Distance":489.852,"Altitude":813.92},{"Latitude":45.49128471874,"Longitude":25.32687907107,"Distance":513.699,"Altitude":813.96},{"Latitude":45.49111138098,"Longitude":25.32671042718,"Distance":537.057,"Altitude":814.038},{"Latitude":45.49092061934,"Longitude":25.32651787391,"Distance":563.073,"Altitude":814.253},{"Latitude":45.49073463539,"Longitude":25.32632138114,"Distance":588.838,"Altitude":814.479},{"Latitude":45.49056521617,"Longitude":25.32613033662,"Distance":612.88,"Altitude":814.802},{"Latitude":45.49039808102,"Longitude":25.3259435459,"Distance":636.517,"Altitude":815.118},{"Latitude":45.49023434054,"Longitude":25.32575962599,"Distance":659.718,"Altitude":815.452},{"Latitude":45.49007508438,"Longitude":25.32556292368,"Distance":683.17,"Altitude":815.783},{"Latitude":45.48989887582,"Longitude":25.32539262436,"Distance":706.865,"Altitude":816.139},{"Latitude":45.48972782213,"Longitude":25.32525421819,"Distance":728.757,"Altitude":816.496},{"Latitude":45.4895530385,"Longitude":25.3251618077,"Distance":749.509,"Altitude":816.929},{"Latitude":45.48937703948,"Longitude":25.32510634046,"Distance":769.574,"AltitLine truncated
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8553de40c8498114ebee6f2d9d3e8641
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7611371c02fe34b43a5205f80056dd82
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b5f405e85b6fce54eb64e445b8a7997f
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -226,7 +226,7 @@ public static class App
|
|||||||
//TcpAddress = new IPEndPoint(IPAddress.Parse("192.168.0.102"), 21001);
|
//TcpAddress = new IPEndPoint(IPAddress.Parse("192.168.0.102"), 21001);
|
||||||
Debug.unityLogger.logEnabled = false;
|
Debug.unityLogger.logEnabled = false;
|
||||||
#else
|
#else
|
||||||
Host = "http://pf.juze.pro/"; //"http://192.168.0.102:5082/";//
|
//Host = "http://pf.juze.pro/"; //"http://192.168.0.102:5082/";//
|
||||||
UdpAddress = new IPEndPoint(IPAddress.Parse("47.97.84.8"), 21000);
|
UdpAddress = new IPEndPoint(IPAddress.Parse("47.97.84.8"), 21000);
|
||||||
TcpAddress = new IPEndPoint(IPAddress.Parse("47.97.84.8"), 21001);
|
TcpAddress = new IPEndPoint(IPAddress.Parse("47.97.84.8"), 21001);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -17,4 +17,7 @@ EditorBuildSettings:
|
|||||||
- enabled: 1
|
- enabled: 1
|
||||||
path: Assets/Scenes/VideoPlay.unity
|
path: Assets/Scenes/VideoPlay.unity
|
||||||
guid: f25b9f482e27079448d130ae1ed0ea34
|
guid: f25b9f482e27079448d130ae1ed0ea34
|
||||||
|
- enabled: 1
|
||||||
|
path: Assets/Scenes/TestVideoPlay.unity
|
||||||
|
guid: b5f405e85b6fce54eb64e445b8a7997f
|
||||||
m_configObjects: {}
|
m_configObjects: {}
|
||||||
Reference in new issue
Block a user