From bda429b625f45a93bd0ed53536df9a6ae28f8048 Mon Sep 17 00:00:00 2001 From: NathanKell Date: Sun, 5 Nov 2023 16:49:26 -0800 Subject: [PATCH] Optimize rotation code: use got's improvements to SetPosRot and use a cache for modules so we don't have to look up each time. --- Source/Harmony/FlightGlobals.cs | 23 ++++++++++++++++ Source/Harmony/OrbitDriver.cs | 18 ++++-------- Source/Harmony/Vessel.cs | 16 +++-------- Source/RealismOverhaul.csproj | 1 + Source/VesselModuleRotationRO.cs | 47 +++++++++++++++++++++++++------- 5 files changed, 70 insertions(+), 35 deletions(-) create mode 100644 Source/Harmony/FlightGlobals.cs diff --git a/Source/Harmony/FlightGlobals.cs b/Source/Harmony/FlightGlobals.cs new file mode 100644 index 0000000000..be4dda3ec0 --- /dev/null +++ b/Source/Harmony/FlightGlobals.cs @@ -0,0 +1,23 @@ +using HarmonyLib; +using UnityEngine; + +namespace RealismOverhaul.Harmony +{ + [HarmonyPatch(typeof(FlightGlobals))] + internal class PatchFlightGlobals + { + [HarmonyPostfix] + [HarmonyPatch(nameof(FlightGlobals.OnSceneChange))] + internal static void Postfix_OnSceneChange() + { + VesselModuleRotationRO.ClearCache(); + } + + [HarmonyPostfix] + [HarmonyPatch(nameof(FlightGlobals.RemoveVessel))] + internal static void Postfix_RemoveVessel(Vessel vessel) + { + VesselModuleRotationRO.RemoveVessel(vessel); + } + } +} diff --git a/Source/Harmony/OrbitDriver.cs b/Source/Harmony/OrbitDriver.cs index 300cf359f3..af5a7781a8 100644 --- a/Source/Harmony/OrbitDriver.cs +++ b/Source/Harmony/OrbitDriver.cs @@ -34,29 +34,21 @@ internal static bool Prefix_updateFromParameters(OrbitDriver __instance, bool se UnityEngine.Object.Destroy(__instance.vessel.gameObject); return false; } - VesselModuleRotationRO mod = null; - foreach (var vm in __instance.vessel.vesselModules) - { - if (vm is VesselModuleRotationRO vmr) - { - mod = vmr; - break; - } - } + VesselModuleRotationRO vmr = VesselModuleRotationRO.GetModule(__instance.vessel); if (!__instance.reverse) { Vector3d offset = (QuaternionD)__instance.driverTransform.rotation * (Vector3d)__instance.vessel.localCoM; Vector3d pos = __instance.referenceBody.position + __instance.pos - offset; - if (mod != null) - mod.RailsUpdate(pos); + if (vmr != null) + vmr.RailsUpdate(pos); else __instance.vessel.SetPosition(pos); } else { __instance.referenceBody.position = ((Vector3d)__instance.driverTransform.position) - __instance.pos; - if (mod != null) - mod.RailsUpdate(__instance.vessel.vesselTransform.position); + if (vmr != null) + vmr.RailsUpdate(__instance.vessel.vesselTransform.position); } return false; diff --git a/Source/Harmony/Vessel.cs b/Source/Harmony/Vessel.cs index 8bd3747a8d..11dea1cc60 100644 --- a/Source/Harmony/Vessel.cs +++ b/Source/Harmony/Vessel.cs @@ -10,23 +10,15 @@ internal class PatchVessel [HarmonyPatch(nameof(Vessel.SetRotation), typeof(Quaternion), typeof(bool))] internal static bool Prefix_SetRotation(Vessel __instance, Quaternion rotation, bool setPos) { - VesselModuleRotationRO mod = null; - foreach (var vm in __instance.vesselModules) - { - if (vm is VesselModuleRotationRO vmr) - { - mod = vmr; - break; - } - } - if (mod == null) + VesselModuleRotationRO vmr = VesselModuleRotationRO.GetModule(__instance); + if (vmr == null) return true; - mod.StoreRot(rotation); + vmr.StoreRot(rotation); if (!setPos) return true; - mod.SetPosRot(rotation, __instance.transform.position); + vmr.SetPosRot(rotation, __instance.transform.position); return false; } diff --git a/Source/RealismOverhaul.csproj b/Source/RealismOverhaul.csproj index bfc6088044..db2c6ae5cb 100644 --- a/Source/RealismOverhaul.csproj +++ b/Source/RealismOverhaul.csproj @@ -39,6 +39,7 @@ + diff --git a/Source/VesselModuleRotationRO.cs b/Source/VesselModuleRotationRO.cs index 8fed2605ed..26cba87d59 100644 --- a/Source/VesselModuleRotationRO.cs +++ b/Source/VesselModuleRotationRO.cs @@ -1,5 +1,6 @@ using System; using UnityEngine; +using System.Collections.Generic; // Modified version of the VesselModule of the same name in MandatoryRCS by gotmachine @@ -125,24 +126,22 @@ private void SetRot() if (IgnoreRot(vessel)) return; - vessel.SetRotation(UnityRot(), true); + SetPosRot(UnityRot(), vessel.transform.position); } - public void SetPosRot(Quaternion rotation, Vector3d position) + public void SetPosRot(Quaternion rotation, Vector3 position) { if (!vessel.loaded) { - vessel.vesselTransform.rotation = rotation; - vessel.vesselTransform.position = position; + vessel.vesselTransform.SetPositionAndRotation(position, rotation); return; } - int count = vessel.parts.Count; - QuaternionD rotD = rotation; - for (int i = 0; i < count; i++) + + List parts = vessel.parts; + for (int i = parts.Count; i-- > 0;) { - Part part = vessel.parts[i]; - part.partTransform.rotation = rotation * part.orgRot; - part.partTransform.position = position + rotD * part.orgPos; + Part part = parts[i]; + part.transform.SetPositionAndRotation(position + rotation * part.orgPos, rotation * part.orgRot); } } @@ -654,5 +653,33 @@ private Quaternion FromToRotation(Vector3d fromv, Vector3d tov) //Stock FromToRo double norm = 1.0 / Math.Sqrt(cross.sqrMagnitude + wval * wval); return new QuaternionD(cross.x * norm, cross.y * norm, cross.z * norm, wval * norm); } + + private static readonly Dictionary _vesselCache = new Dictionary(); + + public static void ClearCache() { _vesselCache.Clear(); } + public static void RemoveVessel(Vessel v) { _vesselCache.Remove(v); } + + public static VesselModuleRotationRO GetModule(Vessel v) + { + if (_vesselCache.TryGetValue(v, out var vmr)) + return vmr; + + foreach (var vm in v.vesselModules) + { + if (vm is VesselModuleRotationRO vmr2) + { + vmr = vmr2; + break; + } + } + + // We only store if non-null. This is because the VM is added + // to all vessels, so if it's ever null this must be being run + // before the VM gets added, and we want to store it on next + // cache hit (i.e. after it's been added). + if (vmr != null) + _vesselCache[v] = vmr; + return vmr; + } } } \ No newline at end of file