ar帧数匹配精准度问题
This commit is contained in:
parent
e3059fc1c2
commit
9552fed2e0
8
Assets/AR.meta
Normal file
8
Assets/AR.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 328b5d62a858984408481bbfd6024557
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
72
Assets/AR/ARLaneObject.cs
Normal file
72
Assets/AR/ARLaneObject.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/ARLaneObject.cs.meta
Normal file
11
Assets/AR/ARLaneObject.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c83121d82f416c345a6250c354717a41
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
258
Assets/AR/ARLaneObjectsController.cs
Normal file
258
Assets/AR/ARLaneObjectsController.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
11
Assets/AR/ARLaneObjectsController.cs.meta
Normal file
11
Assets/AR/ARLaneObjectsController.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: beab89ef5c7a65d4693d9b8b472bb0d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
120
Assets/AR/ARMeshFactory.cs
Normal file
120
Assets/AR/ARMeshFactory.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/ARMeshFactory.cs.meta
Normal file
11
Assets/AR/ARMeshFactory.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ed86df267dfdd249bbec364a3c88ac9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
178
Assets/AR/ARObject.cs
Normal file
178
Assets/AR/ARObject.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/ARObject.cs.meta
Normal file
11
Assets/AR/ARObject.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dbf584e2324021741a949900752a8650
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
34
Assets/AR/ARObjectType.cs
Normal file
34
Assets/AR/ARObjectType.cs
Normal file
@ -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,
|
||||
}
|
||||
}
|
||||
11
Assets/AR/ARObjectType.cs.meta
Normal file
11
Assets/AR/ARObjectType.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a289f05c09632e48b90c9f12837743a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
206
Assets/AR/ARObjectsController.cs
Normal file
206
Assets/AR/ARObjectsController.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/ARObjectsController.cs.meta
Normal file
11
Assets/AR/ARObjectsController.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d565e7e3c0027f41836c0210a05072c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
578
Assets/AR/ARRoute.cs
Normal file
578
Assets/AR/ARRoute.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/ARRoute.cs.meta
Normal file
11
Assets/AR/ARRoute.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a1e61467f8f84048b899dc7815c65ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
248
Assets/AR/ARRouteData.cs
Normal file
248
Assets/AR/ARRouteData.cs
Normal file
@ -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)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/ARRouteData.cs.meta
Normal file
11
Assets/AR/ARRouteData.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4aaeffc1df7bde4880cda54a3cfaf61
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
283
Assets/AR/AVProVideoPlayer.cs
Normal file
283
Assets/AR/AVProVideoPlayer.cs
Normal file
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/AVProVideoPlayer.cs.meta
Normal file
11
Assets/AR/AVProVideoPlayer.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5609ccb62c92e784e873a76e89abc3aa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
80
Assets/AR/BaseRenderer.cs
Normal file
80
Assets/AR/BaseRenderer.cs
Normal file
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/BaseRenderer.cs.meta
Normal file
11
Assets/AR/BaseRenderer.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f542667dd24fe84e87fcb325e8535cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
34
Assets/AR/Geometry.cs
Normal file
34
Assets/AR/Geometry.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/Geometry.cs.meta
Normal file
11
Assets/AR/Geometry.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 192a6b01fc9e2ec44b90f5d19c277ca4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
214
Assets/AR/RiderRenderer.cs
Normal file
214
Assets/AR/RiderRenderer.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/RiderRenderer.cs.meta
Normal file
11
Assets/AR/RiderRenderer.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a779f3247875ef947ab87e8093f5bb39
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
367
Assets/AR/TestPlayer.cs
Normal file
367
Assets/AR/TestPlayer.cs
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/AR/TestPlayer.cs.meta
Normal file
11
Assets/AR/TestPlayer.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 523f7d25735c76b4ea28ecc390829ed7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
131
Assets/AR/VTMath.cs
Normal file
131
Assets/AR/VTMath.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/VTMath.cs.meta
Normal file
11
Assets/AR/VTMath.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: edfe6b3cfb01f654bb5045ca7a9217f8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
154
Assets/AR/Vector3d.cs
Normal file
154
Assets/AR/Vector3d.cs
Normal file
@ -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) + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/Vector3d.cs.meta
Normal file
11
Assets/AR/Vector3d.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8454158d7f8e40a47b7134e3fcb68882
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
162
Assets/AR/VideoPlayerControl.cs
Normal file
162
Assets/AR/VideoPlayerControl.cs
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AR/VideoPlayerControl.cs.meta
Normal file
11
Assets/AR/VideoPlayerControl.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f244e092373e2d40935fd6ec79c8af7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
92
Assets/AR/VideoPointsSync.cs
Normal file
92
Assets/AR/VideoPointsSync.cs
Normal file
@ -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)));
|
||||
}
|
||||
}
|
||||
11
Assets/AR/VideoPointsSync.cs.meta
Normal file
11
Assets/AR/VideoPointsSync.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe1742dfacafb6e429b9388feba5699a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Resources/UI/80206.json
Normal file
1
Assets/Resources/UI/80206.json
Normal file
File diff suppressed because one or more lines are too long
7
Assets/Resources/UI/80206.json.meta
Normal file
7
Assets/Resources/UI/80206.json.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 341c9bc6edccecd498b3d3b74b08f3b9
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Resources/UI/84288.json
Normal file
1
Assets/Resources/UI/84288.json
Normal file
File diff suppressed because one or more lines are too long
7
Assets/Resources/UI/84288.json.meta
Normal file
7
Assets/Resources/UI/84288.json.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2e696010ab476541b5d4458dbc3b21e
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Resources/UI/88019.json
Normal file
1
Assets/Resources/UI/88019.json
Normal file
File diff suppressed because one or more lines are too long
7
Assets/Resources/UI/88019.json.meta
Normal file
7
Assets/Resources/UI/88019.json.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 329bdb26604fbd6499707e6457df4921
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
494553
Assets/Resources/UI/ArData.json
Normal file
494553
Assets/Resources/UI/ArData.json
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/Resources/UI/ArData.json.meta
Normal file
7
Assets/Resources/UI/ArData.json.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 874a748024ffda74a841855f69348615
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
213633
Assets/Resources/UI/camera.json
Normal file
213633
Assets/Resources/UI/camera.json
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/Resources/UI/camera.json.meta
Normal file
7
Assets/Resources/UI/camera.json.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d018f8014dec174390f06f9fa947a05
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Resources/UI/route-84288.json
Normal file
1
Assets/Resources/UI/route-84288.json
Normal file
File diff suppressed because one or more lines are too long
7
Assets/Resources/UI/route-84288.json.meta
Normal file
7
Assets/Resources/UI/route-84288.json.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a1f568492ae0ed498af496a6a4fb796
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1
Assets/Resources/UI/route-88019.json
Normal file
1
Assets/Resources/UI/route-88019.json
Normal file
File diff suppressed because one or more lines are too long
7
Assets/Resources/UI/route-88019.json.meta
Normal file
7
Assets/Resources/UI/route-88019.json.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8553de40c8498114ebee6f2d9d3e8641
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
6450
Assets/Resources/UI/route.json
Normal file
6450
Assets/Resources/UI/route.json
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/Resources/UI/route.json.meta
Normal file
7
Assets/Resources/UI/route.json.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7611371c02fe34b43a5205f80056dd82
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
134577
Assets/Scenes/TestVideoPlay.unity
Normal file
134577
Assets/Scenes/TestVideoPlay.unity
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/Scenes/TestVideoPlay.unity.meta
Normal file
7
Assets/Scenes/TestVideoPlay.unity.meta
Normal file
@ -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);
|
||||
Debug.unityLogger.logEnabled = false;
|
||||
#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);
|
||||
TcpAddress = new IPEndPoint(IPAddress.Parse("47.97.84.8"), 21001);
|
||||
#endif
|
||||
|
||||
@ -17,4 +17,7 @@ EditorBuildSettings:
|
||||
- enabled: 1
|
||||
path: Assets/Scenes/VideoPlay.unity
|
||||
guid: f25b9f482e27079448d130ae1ed0ea34
|
||||
- enabled: 1
|
||||
path: Assets/Scenes/TestVideoPlay.unity
|
||||
guid: b5f405e85b6fce54eb64e445b8a7997f
|
||||
m_configObjects: {}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user