mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-03 14:59:23 +00:00
[RelativeSync] attempt at fixing jitter (it did not work, it is very broken)
This commit is contained in:
parent
c46bc61619
commit
85e3499615
6 changed files with 305 additions and 230 deletions
|
@ -15,6 +15,7 @@ public class RelativeSyncMod : MelonMod
|
|||
ModNetwork.Subscribe();
|
||||
|
||||
ApplyPatches(typeof(NetworkRootDataUpdatePatches));
|
||||
ApplyPatches(typeof(CVRSpawnablePatches));
|
||||
|
||||
ApplyPatches(typeof(PlayerSetupPatches));
|
||||
ApplyPatches(typeof(PuppetMasterPatches));
|
||||
|
|
|
@ -3,149 +3,154 @@ using ABI_RC.Systems.ModNetwork;
|
|||
using DarkRift;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.RelativeSync.Networking
|
||||
namespace NAK.RelativeSync.Networking;
|
||||
|
||||
public static class ModNetwork
|
||||
{
|
||||
public static class ModNetwork
|
||||
public static bool Debug_NetworkInbound = false;
|
||||
public static bool Debug_NetworkOutbound = false;
|
||||
|
||||
private static bool _isSubscribedToModNetwork;
|
||||
|
||||
private struct MovementParentSyncData
|
||||
{
|
||||
public static bool Debug_NetworkInbound = false;
|
||||
public static bool Debug_NetworkOutbound = false;
|
||||
|
||||
private static bool _isSubscribedToModNetwork;
|
||||
|
||||
private struct RelativeSyncData
|
||||
{
|
||||
public bool HasSyncedThisData;
|
||||
public int MarkerHash;
|
||||
public Vector3 Position;
|
||||
public Vector3 Rotation;
|
||||
}
|
||||
|
||||
private static RelativeSyncData _latestRelativeSyncData;
|
||||
|
||||
#region Constants
|
||||
|
||||
private const string ModId = "MelonMod.NAK.RelativeSync";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Enums
|
||||
|
||||
private enum MessageType : byte
|
||||
{
|
||||
SyncPosition = 0,
|
||||
RelativeSyncStatus = 1
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mod Network Internals
|
||||
|
||||
internal static void Subscribe()
|
||||
{
|
||||
ModNetworkManager.Subscribe(ModId, OnMessageReceived);
|
||||
|
||||
_isSubscribedToModNetwork = ModNetworkManager.IsSubscribed(ModId);
|
||||
if (!_isSubscribedToModNetwork)
|
||||
Debug.LogError("Failed to subscribe to Mod Network!");
|
||||
}
|
||||
|
||||
internal static void SendRelativeSyncUpdate()
|
||||
{
|
||||
if (!_isSubscribedToModNetwork)
|
||||
return;
|
||||
|
||||
if (!_latestRelativeSyncData.HasSyncedThisData)
|
||||
{
|
||||
SendMessage(MessageType.SyncPosition, _latestRelativeSyncData.MarkerHash,
|
||||
_latestRelativeSyncData.Position, _latestRelativeSyncData.Rotation);
|
||||
_latestRelativeSyncData.HasSyncedThisData = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetLatestRelativeSync(int markerHash, Vector3 position, Vector3 rotation)
|
||||
{
|
||||
// check if the data has changed
|
||||
if (_latestRelativeSyncData.MarkerHash == markerHash
|
||||
&& _latestRelativeSyncData.Position == position
|
||||
&& _latestRelativeSyncData.Rotation == rotation)
|
||||
return; // no need to update
|
||||
|
||||
_latestRelativeSyncData.HasSyncedThisData = false; // reset
|
||||
_latestRelativeSyncData.MarkerHash = markerHash;
|
||||
_latestRelativeSyncData.Position = position;
|
||||
_latestRelativeSyncData.Rotation = rotation;
|
||||
}
|
||||
|
||||
private static void SendMessage(MessageType messageType, int markerHash, Vector3 position, Vector3 rotation)
|
||||
{
|
||||
if (!IsConnectedToGameNetwork())
|
||||
return;
|
||||
|
||||
using ModNetworkMessage modMsg = new(ModId);
|
||||
modMsg.Write((byte)messageType);
|
||||
modMsg.Write(markerHash);
|
||||
modMsg.Write(position);
|
||||
modMsg.Write(rotation);
|
||||
modMsg.Send();
|
||||
}
|
||||
|
||||
private static void OnMessageReceived(ModNetworkMessage msg)
|
||||
{
|
||||
msg.Read(out byte msgTypeRaw);
|
||||
|
||||
if (!Enum.IsDefined(typeof(MessageType), msgTypeRaw))
|
||||
return;
|
||||
|
||||
switch ((MessageType)msgTypeRaw)
|
||||
{
|
||||
case MessageType.SyncPosition:
|
||||
msg.Read(out int markerHash);
|
||||
msg.Read(out Vector3 receivedPosition);
|
||||
msg.Read(out Vector3 receivedRotation);
|
||||
OnNetworkPositionUpdateReceived(msg.Sender, markerHash, receivedPosition, receivedRotation);
|
||||
break;
|
||||
// case MessageType.RelativeSyncStatus:
|
||||
// msg.Read(out string guidStr);
|
||||
// msg.Read(out bool isRelativeSync);
|
||||
// System.Guid guid = new System.Guid(guidStr);
|
||||
// OnRelativeSyncStatusReceived(msg.Sender, guid, isRelativeSync);
|
||||
// break;
|
||||
default:
|
||||
Debug.LogError($"Invalid message type received from: {msg.Sender}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public static void SendNetworkPosition(int markerHash, Vector3 newPosition, Vector3 newRotation)
|
||||
{
|
||||
SetLatestRelativeSync(markerHash, newPosition, newRotation);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private static bool IsConnectedToGameNetwork()
|
||||
{
|
||||
return NetworkManager.Instance != null
|
||||
&& NetworkManager.Instance.GameNetwork != null
|
||||
&& NetworkManager.Instance.GameNetwork.ConnectionState == ConnectionState.Connected;
|
||||
}
|
||||
|
||||
private static void OnNetworkPositionUpdateReceived(string sender, int markerHash, Vector3 position, Vector3 rotation)
|
||||
{
|
||||
RelativeSyncManager.ApplyRelativeSync(sender, markerHash, position, rotation);
|
||||
}
|
||||
|
||||
private static void OnRelativeSyncStatusReceived(string sender, System.Guid guid, bool isRelativeSync)
|
||||
{
|
||||
// todo: implement
|
||||
}
|
||||
|
||||
#endregion
|
||||
public bool HasSyncedThisData;
|
||||
public int MarkerHash;
|
||||
public Vector3 RootPosition;
|
||||
public Vector3 RootRotation;
|
||||
public Vector3 HipPosition;
|
||||
public Vector3 HipRotation;
|
||||
}
|
||||
|
||||
private static MovementParentSyncData _latestMovementParentSyncData;
|
||||
|
||||
#region Constants
|
||||
|
||||
private const string ModId = "MelonMod.NAK.RelativeSync";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Enums
|
||||
|
||||
private enum MessageType : byte
|
||||
{
|
||||
MovementParentOrChair = 0
|
||||
//RelativePickup = 1,
|
||||
//RelativeAttachment = 2,
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mod Network Internals
|
||||
|
||||
internal static void Subscribe()
|
||||
{
|
||||
ModNetworkManager.Subscribe(ModId, OnMessageReceived);
|
||||
|
||||
_isSubscribedToModNetwork = ModNetworkManager.IsSubscribed(ModId);
|
||||
if (!_isSubscribedToModNetwork)
|
||||
Debug.LogError("Failed to subscribe to Mod Network!");
|
||||
}
|
||||
|
||||
// Called right after NetworkRootDataUpdate.Submit()
|
||||
internal static void SendRelativeSyncUpdate()
|
||||
{
|
||||
if (!_isSubscribedToModNetwork)
|
||||
return;
|
||||
|
||||
if (_latestMovementParentSyncData.HasSyncedThisData)
|
||||
return;
|
||||
|
||||
SendMessage(MessageType.MovementParentOrChair, _latestMovementParentSyncData.MarkerHash,
|
||||
_latestMovementParentSyncData.RootPosition, _latestMovementParentSyncData.RootRotation,
|
||||
_latestMovementParentSyncData.HipPosition, _latestMovementParentSyncData.HipRotation);
|
||||
|
||||
_latestMovementParentSyncData.HasSyncedThisData = true;
|
||||
}
|
||||
|
||||
public static void SetLatestRelativeSync(
|
||||
int markerHash,
|
||||
Vector3 position, Vector3 rotation,
|
||||
Vector3 hipPosition, Vector3 hipRotation)
|
||||
{
|
||||
// check if the data has changed
|
||||
if (_latestMovementParentSyncData.MarkerHash == markerHash
|
||||
&& _latestMovementParentSyncData.RootPosition == position
|
||||
&& _latestMovementParentSyncData.RootRotation == rotation
|
||||
&& _latestMovementParentSyncData.HipPosition == hipPosition
|
||||
&& _latestMovementParentSyncData.HipRotation == hipRotation)
|
||||
return; // no need to update (shocking)
|
||||
|
||||
_latestMovementParentSyncData.HasSyncedThisData = false; // reset
|
||||
_latestMovementParentSyncData.MarkerHash = markerHash;
|
||||
_latestMovementParentSyncData.RootPosition = position;
|
||||
_latestMovementParentSyncData.RootRotation = rotation;
|
||||
_latestMovementParentSyncData.HipPosition = hipPosition;
|
||||
_latestMovementParentSyncData.HipRotation = hipRotation;
|
||||
}
|
||||
|
||||
private static void SendMessage(MessageType messageType, int markerHash, Vector3 position, Vector3 rotation,
|
||||
Vector3 hipPosition, Vector3 hipRotation)
|
||||
{
|
||||
if (!IsConnectedToGameNetwork())
|
||||
return;
|
||||
|
||||
using ModNetworkMessage modMsg = new(ModId);
|
||||
modMsg.Write((byte)messageType);
|
||||
modMsg.Write(markerHash);
|
||||
modMsg.Write(position);
|
||||
modMsg.Write(rotation);
|
||||
modMsg.Write(hipPosition);
|
||||
modMsg.Write(hipRotation);
|
||||
modMsg.Send();
|
||||
|
||||
if (Debug_NetworkOutbound)
|
||||
Debug.Log(
|
||||
$"[Outbound] MessageType: {messageType}, MarkerHash: {markerHash}, Position: {position}, Rotation: {rotation}, HipPosition: {hipPosition}, HipRotation: {hipRotation}");
|
||||
}
|
||||
|
||||
private static void OnMessageReceived(ModNetworkMessage msg)
|
||||
{
|
||||
msg.Read(out byte msgTypeRaw);
|
||||
|
||||
if (!Enum.IsDefined(typeof(MessageType), msgTypeRaw))
|
||||
return;
|
||||
|
||||
switch ((MessageType)msgTypeRaw)
|
||||
{
|
||||
case MessageType.MovementParentOrChair:
|
||||
msg.Read(out int markerHash);
|
||||
msg.Read(out Vector3 receivedPosition);
|
||||
msg.Read(out Vector3 receivedRotation);
|
||||
msg.Read(out Vector3 receivedHipPosition);
|
||||
msg.Read(out Vector3 receivedHipRotation);
|
||||
|
||||
OnNetworkPositionUpdateReceived(msg.Sender, markerHash, receivedPosition, receivedRotation, receivedHipPosition, receivedHipRotation);
|
||||
if (Debug_NetworkInbound)
|
||||
Debug.Log($"[Inbound] Sender: {msg.Sender}, MarkerHash: {markerHash}, Position: {receivedPosition}, Rotation: {receivedRotation}, HipPosition: {receivedHipPosition}, HipRotation: {receivedHipRotation}");
|
||||
break;
|
||||
default:
|
||||
Debug.LogError($"Invalid message type received from: {msg.Sender}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private static bool IsConnectedToGameNetwork()
|
||||
{
|
||||
return NetworkManager.Instance != null
|
||||
&& NetworkManager.Instance.GameNetwork != null
|
||||
&& NetworkManager.Instance.GameNetwork.ConnectionState == ConnectionState.Connected;
|
||||
}
|
||||
|
||||
private static void OnNetworkPositionUpdateReceived(string sender, int markerHash, Vector3 position,
|
||||
Vector3 rotation, Vector3 hipPosition, Vector3 hipRotation)
|
||||
{
|
||||
RelativeSyncManager.ApplyRelativeSync(sender, markerHash, position, rotation, hipPosition, hipRotation);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
|
@ -58,4 +58,25 @@ internal static class NetworkRootDataUpdatePatches
|
|||
{
|
||||
ModNetwork.SendRelativeSyncUpdate(); // Send the relative sync update after the network root data update
|
||||
}
|
||||
}
|
||||
|
||||
internal static class CVRSpawnablePatches
|
||||
{
|
||||
private static bool _allowUpdate;
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(CVRSpawnable), nameof(CVRSpawnable.Update))]
|
||||
private static bool Prefix_CVRSpawnable_Update()
|
||||
{
|
||||
return _allowUpdate;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(CVRSpawnable), nameof(CVRSpawnable.FixedUpdate))]
|
||||
private static void Postfix_CVRSpawnable_FixedUpdate(ref CVRSpawnable __instance)
|
||||
{
|
||||
_allowUpdate = true;
|
||||
__instance.Update();
|
||||
_allowUpdate = false;
|
||||
}
|
||||
}
|
|
@ -6,16 +6,13 @@ namespace NAK.RelativeSync.Components;
|
|||
[DefaultExecutionOrder(int.MaxValue)] // make sure this runs after NetIKController
|
||||
public class RelativeSyncController : MonoBehaviour
|
||||
{
|
||||
private static float MaxMagnitude = 750000000000f;
|
||||
|
||||
private const float MaxMagnitude = 750000000000f;
|
||||
|
||||
private float _updateInterval = 0.05f;
|
||||
private float _lastUpdate;
|
||||
|
||||
private string _userId;
|
||||
private PuppetMaster puppetMaster { get; set; }
|
||||
private NetIKController netIkController { get; set; }
|
||||
|
||||
// private bool _syncMarkerChangedSinceLastSync;
|
||||
private RelativeSyncMarker _relativeSyncMarker;
|
||||
|
||||
private RelativeSyncData _relativeSyncData;
|
||||
|
@ -26,7 +23,6 @@ public class RelativeSyncController : MonoBehaviour
|
|||
private void Start()
|
||||
{
|
||||
puppetMaster = GetComponent<PuppetMaster>();
|
||||
netIkController = GetComponent<NetIKController>();
|
||||
|
||||
_userId = puppetMaster._playerDescriptor.ownerId;
|
||||
RelativeSyncManager.RelativeSyncControllers.Add(_userId, this);
|
||||
|
@ -50,66 +46,76 @@ public class RelativeSyncController : MonoBehaviour
|
|||
return;
|
||||
|
||||
Transform avatarTransform = animator.transform;
|
||||
|
||||
Vector3 worldRootPos = avatarTransform.position;
|
||||
Quaternion worldRootRot = avatarTransform.rotation;
|
||||
|
||||
Vector3 relativeHipPos = default;
|
||||
Quaternion relativeHipRot = default;
|
||||
Transform hipTrans = animator.GetBoneTransform(HumanBodyBones.Hips);
|
||||
if (hipTrans != null)
|
||||
{
|
||||
Vector3 hipPos = hipTrans.position;
|
||||
Quaternion hipRot = hipTrans.rotation;
|
||||
|
||||
relativeHipPos = Quaternion.Inverse(worldRootRot) * (hipPos - worldRootPos);
|
||||
relativeHipRot = Quaternion.Inverse(worldRootRot) * hipRot;
|
||||
}
|
||||
Transform hipTrans = (animator.avatar != null && animator.isHuman)
|
||||
? animator.GetBoneTransform(HumanBodyBones.Hips) : null;
|
||||
|
||||
// TODO: handle the case where hip is not synced but is found on remote client
|
||||
|
||||
float lerp = Mathf.Min((Time.time - _lastUpdate) / _updateInterval, 1f);
|
||||
|
||||
Vector3 targetLocalPosition = _relativeSyncData.LocalRootPosition;
|
||||
Quaternion targetLocalRotation = Quaternion.Euler(_relativeSyncData.LocalRootRotation);
|
||||
Transform targetTransform = _relativeSyncMarker.transform;
|
||||
ApplyRelativeRotation(avatarTransform, hipTrans, lerp);
|
||||
ApplyRelativePosition(hipTrans, lerp);
|
||||
|
||||
avatarTransform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); // idk if needed
|
||||
}
|
||||
|
||||
if (_relativeSyncMarker.ApplyRelativeRotation && _relativeSyncData.LocalRootRotation.sqrMagnitude < MaxMagnitude)
|
||||
private void ApplyRelativeRotation(Transform avatarTransform, Transform hipTransform, float lerp)
|
||||
{
|
||||
if (!_relativeSyncMarker.ApplyRelativeRotation ||
|
||||
!(_relativeSyncData.LocalRootRotation.sqrMagnitude < MaxMagnitude))
|
||||
return; // not applying relative rotation or data is invalid
|
||||
|
||||
Quaternion markerRotation = _relativeSyncMarker.transform.rotation;
|
||||
Quaternion lastWorldRotation = markerRotation * Quaternion.Euler(_lastSyncData.LocalRootRotation);
|
||||
Quaternion worldRotation = markerRotation * Quaternion.Euler(_relativeSyncData.LocalRootRotation);
|
||||
|
||||
Quaternion lastWorldHipRotation = markerRotation * Quaternion.Euler(_lastSyncData.LocalHipRotation);
|
||||
Quaternion worldHipRotation = markerRotation * Quaternion.Euler(_relativeSyncData.LocalHipRotation);
|
||||
|
||||
if (_relativeSyncMarker.OnlyApplyRelativeHeading)
|
||||
{
|
||||
Quaternion rotation = targetTransform.rotation;
|
||||
Quaternion worldRotation = rotation * targetLocalRotation;
|
||||
Quaternion lastRotation = rotation * Quaternion.Euler(_lastSyncData.LocalRootRotation);
|
||||
|
||||
if (_relativeSyncMarker.OnlyApplyRelativeHeading)
|
||||
Vector3 currentWorldUp = avatarTransform.up;
|
||||
|
||||
Vector3 currentForward = lastWorldRotation * Vector3.forward;
|
||||
Vector3 targetForward = worldRotation * Vector3.forward;
|
||||
currentForward = Vector3.ProjectOnPlane(currentForward, currentWorldUp).normalized;
|
||||
targetForward = Vector3.ProjectOnPlane(targetForward, currentWorldUp).normalized;
|
||||
lastWorldRotation = Quaternion.LookRotation(currentForward, currentWorldUp);
|
||||
worldRotation = Quaternion.LookRotation(targetForward, currentWorldUp);
|
||||
|
||||
if (hipTransform != null)
|
||||
{
|
||||
Vector3 currentForward = lastRotation * Vector3.forward;
|
||||
Vector3 targetForward = worldRotation * Vector3.forward;
|
||||
Vector3 currentWorldUp = avatarTransform.up; // up direction of player before we touch it
|
||||
|
||||
// project forward vectors to the ground plane
|
||||
currentForward = lastWorldHipRotation * Vector3.forward;
|
||||
targetForward = worldHipRotation * Vector3.forward;
|
||||
currentForward = Vector3.ProjectOnPlane(currentForward, currentWorldUp).normalized;
|
||||
targetForward = Vector3.ProjectOnPlane(targetForward, currentWorldUp).normalized;
|
||||
|
||||
lastRotation = Quaternion.LookRotation(currentForward, currentWorldUp);
|
||||
worldRotation = Quaternion.LookRotation(targetForward, currentWorldUp);
|
||||
lastWorldHipRotation = Quaternion.LookRotation(currentForward, currentWorldUp);
|
||||
worldHipRotation = Quaternion.LookRotation(targetForward, currentWorldUp);
|
||||
}
|
||||
|
||||
transform.rotation = Quaternion.Slerp(lastRotation, worldRotation, lerp);
|
||||
}
|
||||
|
||||
if (_relativeSyncMarker.ApplyRelativePosition && _relativeSyncData.LocalRootPosition.sqrMagnitude < MaxMagnitude)
|
||||
{
|
||||
Vector3 worldPosition = targetTransform.TransformPoint(targetLocalPosition);
|
||||
transform.position = Vector3.Lerp(targetTransform.TransformPoint(_lastSyncData.LocalRootPosition), worldPosition, lerp);
|
||||
}
|
||||
transform.rotation = Quaternion.Slerp(lastWorldRotation, worldRotation, lerp);
|
||||
if (hipTransform != null) hipTransform.rotation = Quaternion.Slerp(lastWorldHipRotation, worldHipRotation, lerp);
|
||||
}
|
||||
|
||||
// negate avatar transform movement
|
||||
avatarTransform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
|
||||
private void ApplyRelativePosition(Transform hipTransform, float lerp)
|
||||
{
|
||||
if (!_relativeSyncMarker.ApplyRelativePosition ||
|
||||
!(_relativeSyncData.LocalRootPosition.sqrMagnitude < MaxMagnitude))
|
||||
return; // not applying relative position or data is invalid
|
||||
|
||||
// fix hip syncing because it is not relative to root, it is synced in world space -_-
|
||||
if (hipTrans != null)
|
||||
{
|
||||
hipTrans.position = transform.position + transform.rotation * relativeHipPos;
|
||||
hipTrans.rotation = transform.rotation * relativeHipRot;
|
||||
}
|
||||
Transform targetTransform = _relativeSyncMarker.transform;
|
||||
|
||||
Vector3 lastWorldPosition = targetTransform.TransformPoint(_lastSyncData.LocalRootPosition);
|
||||
Vector3 worldPosition = targetTransform.TransformPoint(_relativeSyncData.LocalRootPosition);
|
||||
transform.position = Vector3.Lerp(lastWorldPosition, worldPosition, lerp);
|
||||
|
||||
if (hipTransform == null)
|
||||
return;
|
||||
|
||||
Vector3 lastWorldHipPosition = targetTransform.TransformPoint(_lastSyncData.LocalHipPosition);
|
||||
Vector3 worldHipPosition = targetTransform.TransformPoint(_relativeSyncData.LocalHipPosition);
|
||||
hipTransform.position = Vector3.Lerp(lastWorldHipPosition, worldHipPosition, lerp);
|
||||
}
|
||||
|
||||
#endregion Unity Events
|
||||
|
@ -124,21 +130,28 @@ public class RelativeSyncController : MonoBehaviour
|
|||
_relativeSyncMarker = target;
|
||||
|
||||
// calculate relative position and rotation so lerp can smooth it out (hack)
|
||||
if (_relativeSyncMarker != null)
|
||||
{
|
||||
Transform avatarTransform = puppetMaster._animator.transform;
|
||||
Transform markerTransform = _relativeSyncMarker.transform;
|
||||
Vector3 localPosition = markerTransform.InverseTransformPoint(avatarTransform.position);
|
||||
Quaternion localRotation = Quaternion.Inverse(markerTransform.rotation) * avatarTransform.rotation;
|
||||
if (_relativeSyncMarker == null)
|
||||
return;
|
||||
|
||||
Animator avatarAnimator = puppetMaster._animator;
|
||||
if (avatarAnimator == null)
|
||||
return; // i dont care to bother
|
||||
|
||||
RelativeSyncManager.GetRelativeAvatarPositionsFromMarker(
|
||||
avatarAnimator, _relativeSyncMarker.transform,
|
||||
out Vector3 relativePosition, out Vector3 relativeRotation,
|
||||
out Vector3 relativeHipPosition, out Vector3 relativeHipRotation);
|
||||
|
||||
// set last sync data to current position and rotation so we don't lerp from the last marker
|
||||
_lastSyncData.LocalRootPosition = localPosition;
|
||||
_lastSyncData.LocalRootRotation = localRotation.eulerAngles;
|
||||
//Debug.Log($"SetRelativeSyncMarker: {_relativeSyncMarker.name}");
|
||||
}
|
||||
// set last sync data to current position and rotation so we don't lerp from the last marker
|
||||
_lastSyncData.LocalRootPosition = relativePosition;
|
||||
_lastSyncData.LocalRootRotation = relativeRotation;
|
||||
_lastSyncData.LocalHipPosition = relativeHipPosition;
|
||||
_lastSyncData.LocalHipRotation = relativeHipRotation;
|
||||
}
|
||||
|
||||
public void SetRelativePositions(Vector3 position, Vector3 rotation)
|
||||
public void SetRelativePositions(
|
||||
Vector3 position, Vector3 rotation,
|
||||
Vector3 hipPosition, Vector3 hipRotation)
|
||||
{
|
||||
// calculate update interval
|
||||
float prevUpdate = _lastUpdate;
|
||||
|
@ -146,19 +159,22 @@ public class RelativeSyncController : MonoBehaviour
|
|||
_updateInterval = _lastUpdate - prevUpdate;
|
||||
|
||||
// cycle last sync data
|
||||
_lastSyncData.LocalRootPosition = _relativeSyncData.LocalRootPosition;
|
||||
_lastSyncData.LocalRootRotation = _relativeSyncData.LocalRootRotation;
|
||||
_lastSyncData = _relativeSyncData;
|
||||
|
||||
// set new sync data
|
||||
_relativeSyncData.LocalRootPosition = position;
|
||||
_relativeSyncData.LocalRootRotation = rotation;
|
||||
_relativeSyncData.LocalHipPosition = hipPosition;
|
||||
_relativeSyncData.LocalHipRotation = hipRotation;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
public struct RelativeSyncData
|
||||
private struct RelativeSyncData
|
||||
{
|
||||
public Vector3 LocalRootPosition;
|
||||
public Vector3 LocalRootRotation;
|
||||
public Vector3 LocalHipPosition;
|
||||
public Vector3 LocalHipRotation;
|
||||
}
|
||||
}
|
|
@ -37,8 +37,20 @@ public class RelativeSyncMonitor : MonoBehaviour
|
|||
}
|
||||
|
||||
_lastRelativeSyncMarker = _relativeSyncMarker;
|
||||
|
||||
SendCurrentPositionAndRotation();
|
||||
|
||||
Animator avatarAnimator = PlayerSetup.Instance._animator;
|
||||
if (avatarAnimator == null)
|
||||
return; // i dont care to bother
|
||||
|
||||
RelativeSyncManager.GetRelativeAvatarPositionsFromMarker(
|
||||
avatarAnimator, _relativeSyncMarker.transform,
|
||||
out Vector3 relativePosition, out Vector3 relativeRotation,
|
||||
out Vector3 relativeHipPosition, out Vector3 relativeHipRotation);
|
||||
|
||||
ModNetwork.SetLatestRelativeSync(
|
||||
_relativeSyncMarker.pathHash,
|
||||
relativePosition, relativeRotation,
|
||||
relativeHipPosition, relativeHipRotation);
|
||||
}
|
||||
|
||||
private void CheckForRelativeSyncMarker()
|
||||
|
@ -60,23 +72,10 @@ public class RelativeSyncMonitor : MonoBehaviour
|
|||
// none found
|
||||
_relativeSyncMarker = null;
|
||||
}
|
||||
|
||||
private void SendCurrentPositionAndRotation()
|
||||
{
|
||||
// because our syncing is retarded, we need to sync relative from the avatar root...
|
||||
Transform avatarRoot = PlayerSetup.Instance._avatar.transform;
|
||||
Vector3 avatarRootPosition = avatarRoot.position; // PlayerSetup.Instance.GetPlayerPosition()
|
||||
Quaternion avatarRootRotation = avatarRoot.rotation; // PlayerSetup.Instance.GetPlayerRotation()
|
||||
|
||||
Transform markerTransform = _relativeSyncMarker.transform;
|
||||
Vector3 localPosition = markerTransform.InverseTransformPoint(avatarRootPosition);
|
||||
Quaternion localRotation = Quaternion.Inverse(markerTransform.rotation) * avatarRootRotation;
|
||||
|
||||
ModNetwork.SendNetworkPosition(_relativeSyncMarker.pathHash, localPosition, localRotation.eulerAngles);
|
||||
}
|
||||
|
||||
|
||||
private void SendEmptyPositionAndRotation()
|
||||
{
|
||||
ModNetwork.SendNetworkPosition(RelativeSyncManager.NoTarget, Vector3.zero, Vector3.zero);
|
||||
ModNetwork.SetLatestRelativeSync(RelativeSyncManager.NoTarget,
|
||||
Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero);
|
||||
}
|
||||
}
|
|
@ -12,7 +12,10 @@ public static class RelativeSyncManager
|
|||
public static readonly Dictionary<int, RelativeSyncMarker> RelativeSyncTransforms = new();
|
||||
public static readonly Dictionary<string, RelativeSyncController> RelativeSyncControllers = new();
|
||||
|
||||
public static void ApplyRelativeSync(string userId, int target, Vector3 position, Vector3 rotation)
|
||||
public static void ApplyRelativeSync(
|
||||
string userId, int target,
|
||||
Vector3 position, Vector3 rotation,
|
||||
Vector3 hipPosition, Vector3 hipRotation)
|
||||
{
|
||||
if (!RelativeSyncControllers.TryGetValue(userId, out RelativeSyncController controller))
|
||||
if (CVRPlayerManager.Instance.GetPlayerPuppetMaster(userId, out PuppetMaster pm))
|
||||
|
@ -20,6 +23,7 @@ public static class RelativeSyncManager
|
|||
|
||||
if (controller == null)
|
||||
{
|
||||
// TODO: if someone somehow constantly fails this, we should nuke them into orbit
|
||||
RelativeSyncMod.Logger.Error($"Failed to apply relative sync for user {userId}");
|
||||
return;
|
||||
}
|
||||
|
@ -28,7 +32,36 @@ public static class RelativeSyncManager
|
|||
RelativeSyncMarker syncMarker = null;
|
||||
if (target != NoTarget) RelativeSyncTransforms.TryGetValue(target, out syncMarker);
|
||||
|
||||
controller.SetRelativePositions(position, rotation);
|
||||
controller.SetRelativePositions(position, rotation, hipPosition, hipRotation);
|
||||
controller.SetRelativeSyncMarker(syncMarker);
|
||||
}
|
||||
|
||||
public static void GetRelativeAvatarPositionsFromMarker(
|
||||
Animator avatarAnimator, Transform markerTransform,
|
||||
out Vector3 relativePosition, out Vector3 relativeRotation,
|
||||
out Vector3 relativeHipPosition, out Vector3 relativeHipRotation)
|
||||
{
|
||||
Transform avatarTransform = avatarAnimator.transform;
|
||||
|
||||
// because our syncing is retarded, we need to sync relative from the avatar root...
|
||||
Vector3 avatarRootPosition = avatarTransform.position; // PlayerSetup.Instance.GetPlayerPosition()
|
||||
Quaternion avatarRootRotation = avatarTransform.rotation; // PlayerSetup.Instance.GetPlayerRotation()
|
||||
|
||||
relativePosition = markerTransform.InverseTransformPoint(avatarRootPosition);
|
||||
relativeRotation = (Quaternion.Inverse(markerTransform.rotation) * avatarRootRotation).eulerAngles;
|
||||
|
||||
Transform hipTrans = (avatarAnimator.avatar != null && avatarAnimator.isHuman)
|
||||
? avatarAnimator.GetBoneTransform(HumanBodyBones.Hips) : null;
|
||||
|
||||
if (hipTrans == null)
|
||||
{
|
||||
relativeHipPosition = Vector3.zero;
|
||||
relativeHipRotation = Vector3.zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
relativeHipPosition = markerTransform.InverseTransformPoint(hipTrans.position);
|
||||
relativeHipRotation = (Quaternion.Inverse(markerTransform.rotation) * hipTrans.rotation).eulerAngles;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue