using System; using Oculus.Platform.Models; using UnityEngine; namespace Oculus.Platform.Samples.VrVoiceChat { public class P2PManager { private static readonly float UPDATE_DELAY = 0.1f; private ulong m_remoteID; private PeerConnectionState m_state; private float m_timeForNextUpdate; private static readonly byte PACKET_SIZE = 29; private static readonly byte PACKET_FORMAT; private readonly byte[] sendTransformBuffer = new byte[PACKET_SIZE]; private readonly byte[] receiveTransformBuffer = new byte[PACKET_SIZE]; private Vector3 receivedPosition; private Vector3 receivedPositionPrior; private Quaternion receivedRotation; private Quaternion receivedRotationPrior; private float receivedTime; public bool Connected { get { return m_state == PeerConnectionState.Connected; } } public bool ShouldSendHeadUpdate { get { return Time.time >= m_timeForNextUpdate && m_state == PeerConnectionState.Connected; } } public P2PManager(Transform initialHeadTransform) { receivedPositionPrior = (receivedPosition = initialHeadTransform.localPosition); receivedRotationPrior = (receivedRotation = initialHeadTransform.localRotation); Net.SetPeerConnectRequestCallback(PeerConnectRequestCallback); Net.SetConnectionStateChangedCallback(ConnectionStateChangedCallback); } public void ConnectTo(ulong userID) { m_remoteID = userID; if (PlatformManager.MyID < userID) { Net.Connect(userID); } } public void Disconnect() { if (m_remoteID != 0) { Net.Close(m_remoteID); m_remoteID = 0uL; m_state = PeerConnectionState.Unknown; } } private void PeerConnectRequestCallback(Message msg) { Debug.LogFormat("Connection request from {0}, authorized is {1}", msg.Data.ID, m_remoteID); if (msg.Data.ID == m_remoteID) { Net.Accept(msg.Data.ID); } } private void ConnectionStateChangedCallback(Message msg) { Debug.LogFormat("Connection state to {0} changed to {1}", msg.Data.ID, msg.Data.State); if (msg.Data.ID == m_remoteID) { m_state = msg.Data.State; if (m_state == PeerConnectionState.Timeout && PlatformManager.MyID < m_remoteID) { Net.Connect(m_remoteID); } } PlatformManager.SetBackgroundColorForState(); } public void SendHeadTransform(Transform headTransform) { m_timeForNextUpdate = Time.time + UPDATE_DELAY; sendTransformBuffer[0] = PACKET_FORMAT; int offset = 1; PackFloat(headTransform.localPosition.x, sendTransformBuffer, ref offset); PackFloat(headTransform.localPosition.y, sendTransformBuffer, ref offset); PackFloat(headTransform.localPosition.z, sendTransformBuffer, ref offset); PackFloat(headTransform.localRotation.x, sendTransformBuffer, ref offset); PackFloat(headTransform.localRotation.y, sendTransformBuffer, ref offset); PackFloat(headTransform.localRotation.z, sendTransformBuffer, ref offset); PackFloat(headTransform.localRotation.w, sendTransformBuffer, ref offset); Net.SendPacket(m_remoteID, sendTransformBuffer, SendPolicy.Unreliable); } private void PackFloat(float f, byte[] buf, ref int offset) { Buffer.BlockCopy(BitConverter.GetBytes(f), 0, buf, offset, 4); offset += 4; } public void GetRemoteHeadTransform(Transform headTransform) { bool flag = false; Packet packet; while ((packet = Net.ReadPacket()) != null) { if (packet.Size != PACKET_SIZE) { Debug.Log("Invalid packet size: " + packet.Size); continue; } packet.ReadBytes(receiveTransformBuffer); if (receiveTransformBuffer[0] != PACKET_FORMAT) { Debug.Log("Invalid packet type: " + packet.Size); } else { flag = true; } } if (flag) { receivedPositionPrior = receivedPosition; receivedPosition.x = BitConverter.ToSingle(receiveTransformBuffer, 1); receivedPosition.y = BitConverter.ToSingle(receiveTransformBuffer, 5); receivedPosition.z = BitConverter.ToSingle(receiveTransformBuffer, 9); receivedRotationPrior = receivedRotation; receivedRotation.x = BitConverter.ToSingle(receiveTransformBuffer, 13); receivedRotation.y = BitConverter.ToSingle(receiveTransformBuffer, 17) * -1f; receivedRotation.z = BitConverter.ToSingle(receiveTransformBuffer, 21); receivedRotation.w = BitConverter.ToSingle(receiveTransformBuffer, 25) * -1f; receivedTime = Time.time; } float t = Math.Min(Time.time - receivedTime, UPDATE_DELAY) / UPDATE_DELAY; headTransform.localPosition = Vector3.Lerp(receivedPositionPrior, receivedPosition, t); headTransform.localRotation = Quaternion.Slerp(receivedRotationPrior, receivedRotation, t); } } }