Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
4.7 KiB

  1. using UnityEngine;
  2. using System.Collections;
  3. using System;
  4. using System.IO;
  5. using Oculus.Avatar;
  6. using System.Runtime.InteropServices;
  7. using System.Collections.Generic;
  8. public class RemoteLoopbackManager : MonoBehaviour
  9. {
  10. class PacketLatencyPair
  11. {
  12. public byte[] PacketData;
  13. public float FakeLatency;
  14. };
  15. public OvrAvatar LocalAvatar;
  16. public OvrAvatar LoopbackAvatar;
  17. [System.Serializable]
  18. public class SimulatedLatencySettings
  19. {
  20. [Range(0.0f, 0.5f)]
  21. public float FakeLatencyMax = 0.25f; //250 ms max latency
  22. [Range(0.0f, 0.5f)]
  23. public float FakeLatencyMin = 0.002f; //2ms min latency
  24. [Range(0.0f, 1.0f)]
  25. public float LatencyWeight = 0.25f; // How much the latest sample impacts the current latency
  26. [Range(0,10)]
  27. public int MaxSamples = 4; //How many samples in our window
  28. internal float AverageWindow = 0f;
  29. internal float LatencySum = 0f;
  30. internal LinkedList<float> LatencyValues = new LinkedList<float>();
  31. public float NextValue()
  32. {
  33. AverageWindow = LatencySum / (float)LatencyValues.Count;
  34. float RandomLatency = UnityEngine.Random.Range(FakeLatencyMin, FakeLatencyMax);
  35. float FakeLatency = AverageWindow * (1f - LatencyWeight) + LatencyWeight * RandomLatency;
  36. if (LatencyValues.Count >= MaxSamples)
  37. {
  38. LatencySum -= LatencyValues.First.Value;
  39. LatencyValues.RemoveFirst();
  40. }
  41. LatencySum += FakeLatency;
  42. LatencyValues.AddLast(FakeLatency);
  43. return FakeLatency;
  44. }
  45. };
  46. public SimulatedLatencySettings LatencySettings = new SimulatedLatencySettings();
  47. private int PacketSequence = 0;
  48. LinkedList<PacketLatencyPair> packetQueue = new LinkedList<PacketLatencyPair>();
  49. void Start()
  50. {
  51. LocalAvatar.RecordPackets = true;
  52. LocalAvatar.PacketRecorded += OnLocalAvatarPacketRecorded;
  53. float FirstValue = UnityEngine.Random.Range(LatencySettings.FakeLatencyMin, LatencySettings.FakeLatencyMax);
  54. LatencySettings.LatencyValues.AddFirst(FirstValue);
  55. LatencySettings.LatencySum += FirstValue;
  56. }
  57. void OnLocalAvatarPacketRecorded(object sender, OvrAvatar.PacketEventArgs args)
  58. {
  59. using (MemoryStream outputStream = new MemoryStream())
  60. {
  61. BinaryWriter writer = new BinaryWriter(outputStream);
  62. if (LocalAvatar.UseSDKPackets)
  63. {
  64. var size = CAPI.ovrAvatarPacket_GetSize(args.Packet.ovrNativePacket);
  65. byte[] data = new byte[size];
  66. CAPI.ovrAvatarPacket_Write(args.Packet.ovrNativePacket, size, data);
  67. writer.Write(PacketSequence++);
  68. writer.Write(size);
  69. writer.Write(data);
  70. }
  71. else
  72. {
  73. writer.Write(PacketSequence++);
  74. args.Packet.Write(outputStream);
  75. }
  76. SendPacketData(outputStream.ToArray());
  77. }
  78. }
  79. void Update()
  80. {
  81. if (packetQueue.Count > 0)
  82. {
  83. List<PacketLatencyPair> deadList = new List<PacketLatencyPair>();
  84. foreach (var packet in packetQueue)
  85. {
  86. packet.FakeLatency -= Time.deltaTime;
  87. if (packet.FakeLatency < 0f)
  88. {
  89. ReceivePacketData(packet.PacketData);
  90. deadList.Add(packet);
  91. }
  92. }
  93. foreach (var packet in deadList)
  94. {
  95. packetQueue.Remove(packet);
  96. }
  97. }
  98. }
  99. void SendPacketData(byte[] data)
  100. {
  101. PacketLatencyPair PacketPair = new PacketLatencyPair();
  102. PacketPair.PacketData = data;
  103. PacketPair.FakeLatency = LatencySettings.NextValue();
  104. packetQueue.AddLast(PacketPair);
  105. }
  106. void ReceivePacketData(byte[] data)
  107. {
  108. using (MemoryStream inputStream = new MemoryStream(data))
  109. {
  110. BinaryReader reader = new BinaryReader(inputStream);
  111. int sequence = reader.ReadInt32();
  112. OvrAvatarPacket avatarPacket;
  113. if (LoopbackAvatar.UseSDKPackets)
  114. {
  115. int size = reader.ReadInt32();
  116. byte[] sdkData = reader.ReadBytes(size);
  117. IntPtr packet = CAPI.ovrAvatarPacket_Read((UInt32)data.Length, sdkData);
  118. avatarPacket = new OvrAvatarPacket { ovrNativePacket = packet };
  119. }
  120. else
  121. {
  122. avatarPacket = OvrAvatarPacket.Read(inputStream);
  123. }
  124. LoopbackAvatar.GetComponent<OvrAvatarRemoteDriver>().QueuePacket(sequence, avatarPacket);
  125. }
  126. }
  127. }