powerfun-unity/Assets/AR/ARGameObject.cs
2023-04-18 17:10:48 +08:00

215 lines
8.5 KiB
C#

using UnityEngine;
namespace Assets.AR
{
public class ARGameObject : MonoBehaviour
{
public string Hash;
public const int Layer = 1;
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 ARVideoTransform[] TimeTransforms { get; set; }
public string CustomUrl { get; set; }
public string ArName { get; set; }
public int UserId { 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 bool IsMain { 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 DeltaDistance { get; set; }
public float NextDistance { get; set; }
public float Distance
{
get => this.distance;
set
{
if (this.distance == value)
return;
this.distance = value;
this.SetFrame();
}
}
public virtual void UpdateTransform()
{
if (this.Route == null)
return;
var cameraRotation = this.GetCameraRotation(this.frame);
var 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 UpdateByTimeDefinitions(float currentFrame)
{
if (this.TimeTransforms == null || this.TimeTransforms.Length == 0)
return;
if (this.nextTimeDefIndex > this.TimeTransforms.Length - 1)
this.nextTimeDefIndex = 0;
if (this.nextTimeDefIndex > 0 && (double)this.TimeTransforms[this.nextTimeDefIndex - 1].Frame > (double)currentFrame)
this.nextTimeDefIndex = 0;
while (this.nextTimeDefIndex < this.TimeTransforms.Length - 1 && (double)this.TimeTransforms[this.nextTimeDefIndex].Frame <= (double)currentFrame)
++this.nextTimeDefIndex;
if (this.nextTimeDefIndex == 0)
{
this.Distance = this.TimeTransforms[0].Distance;
this.PositionOffset = this.TimeTransforms[0].PositionOffset;
this.Scale = this.TimeTransforms[0].Scale;
this.RotationOffset = this.TimeTransforms[0].RotationOffset;
}
else
{
var t = Mathf.Clamp01((currentFrame - (float)this.TimeTransforms[this.nextTimeDefIndex - 1].Frame) / (float)(this.TimeTransforms[this.nextTimeDefIndex].Frame - this.TimeTransforms[this.nextTimeDefIndex - 1].Frame));
this.Distance = Mathf.Lerp(this.TimeTransforms[this.nextTimeDefIndex - 1].Distance, this.TimeTransforms[this.nextTimeDefIndex].Distance, t);
this.PositionOffset = Vector3.Lerp(this.TimeTransforms[this.nextTimeDefIndex - 1].PositionOffset, this.TimeTransforms[this.nextTimeDefIndex].PositionOffset, t);
this.Scale = Vector3.Lerp(this.TimeTransforms[this.nextTimeDefIndex - 1].Scale, this.TimeTransforms[this.nextTimeDefIndex].Scale, t);
this.RotationOffset = Vector3.Lerp(this.TimeTransforms[this.nextTimeDefIndex - 1].RotationOffset, this.TimeTransforms[this.nextTimeDefIndex].RotationOffset, t);
}
}
public void UpdateOffsets()
{
if (this.Route == null || this.VideoSync == null)
return;
var quaternion = Quaternion.Inverse(this.GetCameraRotation(this.frame));
var 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 (this.ManualVisibility > 0.0)
{
visibilityFront = this.ManualVisibility;
visibilityRear = this.ManualVisibility;
}
var deltaVisibility = Time.deltaTime * 5f;
var a = this.GetVisibilityParameter(this.frame, videoFrame, visibilityRear, visibilityFront, deltaVisibility);
if (multiLap && (double)a <= 0.0)
{
var 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 (objectFrame < videoFrame - visibilityRear)
return 0.0f;
if (visibilityFront <= 0.0)
return 1f;
if (this.ManualVisibility == -1.0)
return Mathf.Clamp(0.0f, this.lastVisibilityLevel - deltaVisibility, this.lastVisibilityLevel + deltaVisibility);
float num1;
if (objectFrame > videoFrame)
{
var num2 = (float)(videoFrame + visibilityFront - 0.5 * this.FrameRate);
var num3 = videoFrame + visibilityFront;
num1 = 1f - Mathf.Clamp01((float)((objectFrame - num2) / (num3 - num2)));
}
else
{
var num4 = videoFrame - visibilityRear;
var num5 = (float)(videoFrame - visibilityRear + 0.5 *this.FrameRate);
num1 = Mathf.Clamp01((float)((objectFrame - num4) / (num5 - num4)));
}
return Mathf.Clamp(num1, this.lastVisibilityLevel - deltaVisibility, this.lastVisibilityLevel + deltaVisibility);
}
}
}