diff --git a/Nerfed.Editor/Program.cs b/Nerfed.Editor/Program.cs index 28f6de0..b9459e7 100644 --- a/Nerfed.Editor/Program.cs +++ b/Nerfed.Editor/Program.cs @@ -1,5 +1,6 @@ using MoonTools.ECS; using Nerfed.Runtime; +using Nerfed.Runtime.Components; using Nerfed.Runtime.Systems; using System.Numerics; @@ -23,7 +24,7 @@ private static void Main(string[] args) private static void HandleOnInitialize() { systems.Add(new ParentSystem(world)); - systems.Add(new TransformSystem(world)); + systems.Add(new LocalToWorldSystem(world)); Entity ent1 = world.CreateEntity(); world.Set(ent1, new LocalTransform(new Vector3(1, 0, 0), Quaternion.Identity, Vector3.One)); diff --git a/Nerfed.Runtime/Systems/TransformSystem.cs b/Nerfed.Runtime/Systems/LocalToWorldSystem.cs similarity index 65% rename from Nerfed.Runtime/Systems/TransformSystem.cs rename to Nerfed.Runtime/Systems/LocalToWorldSystem.cs index 4d5fc8b..741c703 100644 --- a/Nerfed.Runtime/Systems/TransformSystem.cs +++ b/Nerfed.Runtime/Systems/LocalToWorldSystem.cs @@ -3,13 +3,21 @@ using Nerfed.Runtime.Util; using System.Numerics; +// TODO: +// Explore if having a WorldTransform and LocalTransfom component each holding position, rotation, scale values and the matricies is useful. +// Often you need to either get or set these values. +// If so, we probably need a utility funciton to do so. Since changing these values means that we need to update all the related data + children as well. + +// TODO: +// When modifying transform all the children need to be updated as well. + namespace Nerfed.Runtime.Systems { - public class TransformSystem : MoonTools.ECS.System + public class LocalToWorldSystem : MoonTools.ECS.System { private readonly Filter rootEntitiesFilter; - public TransformSystem(World world) : base(world) + public LocalToWorldSystem(World world) : base(world) { rootEntitiesFilter = FilterBuilder.Include().Exclude().Build(); } @@ -27,8 +35,8 @@ public override void Update(TimeSpan delta) private void UpdateWorldTransform(in Entity entity, in Matrix4x4 parentLocalToWorld) { // TODO: Only update dirty transforms. - // Maybe store the local transform matrix. - // If something is dirty all the children need to update their localToWorld matrix. + // If a parent is dirty all the children need to update their localToWorld matrix. + // How do we check if something is dirty? How do we know if a LocalTransform has been changed? LocalTransform localTransform = Get(entity); Matrix4x4 localToWorldMatrix = Matrix4x4.Multiply(parentLocalToWorld, localTransform.TRS()); diff --git a/Nerfed.Runtime/Util/Transform.cs b/Nerfed.Runtime/Util/Transform.cs index 6885538..d4d83be 100644 --- a/Nerfed.Runtime/Util/Transform.cs +++ b/Nerfed.Runtime/Util/Transform.cs @@ -1,4 +1,6 @@ -using Nerfed.Runtime.Components; +using MoonTools.ECS; +using Nerfed.Runtime.Components; +using System.Collections.Generic; using System.Numerics; namespace Nerfed.Runtime.Util @@ -21,5 +23,36 @@ public static Matrix4x4 TRS(in this LocalTransform localTransform) Matrix4x4.CreateFromQuaternion(localTransform.rotation) * Matrix4x4.CreateTranslation(localTransform.position); } + + // Force update the transform data of an entity (and children). + // Useful for when you need precise up to date transform data. + public static void ForceUpdateLocalToWorld(in World world, in Entity entity) + { + Matrix4x4 parentLocalToWorldMatrix = Matrix4x4.Identity; + + if (world.Has(entity)) + { + Entity parent = world.Get(entity).parentEntity; + parentLocalToWorldMatrix = world.Get(parent).localToWorldMatrix; + } + + ForceUpdateLocalToWorld(world, entity, parentLocalToWorldMatrix); + } + + private static void ForceUpdateLocalToWorld(in World world, in Entity entity, in Matrix4x4 parentLocalToWorldMatrix) + { + LocalTransform localTransform = world.Get(entity); + Matrix4x4 localToWorldMatrix = Matrix4x4.Multiply(parentLocalToWorldMatrix, localTransform.TRS()); + LocalToWorld localToWorld = new(localToWorldMatrix); + world.Set(entity, localToWorld); + + Log.Info($"Entity {entity} | local position {localTransform.position} | world position {localToWorldMatrix.Translation}"); + + ReverseSpanEnumerator childEntities = world.OutRelations(entity); + foreach (Entity childEntity in childEntities) + { + ForceUpdateLocalToWorld(world, childEntity, parentLocalToWorldMatrix); + } + } } } \ No newline at end of file