diff --git a/GlitchyEngine/src/Renderer/Renderer.bf b/GlitchyEngine/src/Renderer/Renderer.bf index 4738b04..3e2750d 100644 --- a/GlitchyEngine/src/Renderer/Renderer.bf +++ b/GlitchyEngine/src/Renderer/Renderer.bf @@ -72,7 +72,7 @@ namespace GlitchyEngine.Renderer var camera = world.GetComponent(cameraEntity); var transform = world.GetComponent(cameraEntity); - var trans = transform.Transform; + var trans = transform.WorldTransform; var view = trans.Invert(); var proj = camera.Projection; diff --git a/GlitchyEngine/src/World/EcsWorld.bf b/GlitchyEngine/src/World/EcsWorld.bf index c034cf4..1077f45 100644 --- a/GlitchyEngine/src/World/EcsWorld.bf +++ b/GlitchyEngine/src/World/EcsWorld.bf @@ -221,8 +221,9 @@ namespace GlitchyEngine.World Entity entity = world.NewEntity(); TransformComponent* myComp = world.AssignComponent(entity); - myComp.Transform = Matrix.Identity; + myComp.LocalTransform = Matrix.Identity; + #unwarn TransformComponent gotComp = *world.GetComponent(entity); world.RemoveComponent(entity); diff --git a/GlitchyEngine/src/World/ParentComponent.bf b/GlitchyEngine/src/World/ParentComponent.bf new file mode 100644 index 0000000..a6ece24 --- /dev/null +++ b/GlitchyEngine/src/World/ParentComponent.bf @@ -0,0 +1,10 @@ +namespace GlitchyEngine.World +{ + /** + * A Component that allows to specify a parent entity. + */ + public struct ParentComponent + { + public Entity Entity; + } +} diff --git a/GlitchyEngine/src/World/TransformComponent.bf b/GlitchyEngine/src/World/TransformComponent.bf index 97ca31e..78dae5e 100644 --- a/GlitchyEngine/src/World/TransformComponent.bf +++ b/GlitchyEngine/src/World/TransformComponent.bf @@ -8,17 +8,20 @@ namespace GlitchyEngine.World Vector3 _rotation = .Zero; Vector3 _scale = .One; - Matrix _transform; - bool _dirty; + Matrix _localTransform; + public bool IsDirty; - public Matrix Transform + public Matrix WorldTransform; + + /// The frame when the transform was recalculated + public uint Frame; + + public Matrix LocalTransform { - get mut - { - return _transform; - } - set mut => _transform = value; + get => _localTransform; + set mut => _localTransform = value; } + public Vector3 Position { get => _position; @@ -28,7 +31,7 @@ namespace GlitchyEngine.World return; _position = value; - _dirty = true; + IsDirty = true; } } @@ -41,7 +44,7 @@ namespace GlitchyEngine.World return; _rotation = value; - _dirty = true; + IsDirty = true; } } @@ -54,17 +57,8 @@ namespace GlitchyEngine.World return; _scale = value; - _dirty = true; + IsDirty = true; } } - - public void Update() mut - { - if(!_dirty) - return; - _transform = .Translation(_position) * .RotationX(_rotation.X) * - .RotationY(_rotation.Y) * .RotationZ(_rotation.Z) * .Scaling(_scale); - _dirty = false; - } } } diff --git a/GlitchyEngine/src/World/TransformSystem.bf b/GlitchyEngine/src/World/TransformSystem.bf new file mode 100644 index 0000000..4dc593b --- /dev/null +++ b/GlitchyEngine/src/World/TransformSystem.bf @@ -0,0 +1,57 @@ +namespace GlitchyEngine.World +{ + public static class TransformSystem + { + static uint _frame; + + public static void Update(EcsWorld world) + { + _frame++; + + for(var entity in world.Enumerate(typeof(TransformComponent))) + { + UpdateEntity(entity, world); + } + } + + private static TransformComponent* UpdateEntity(Entity entity, EcsWorld world) + { + // Todo: this probably needs a rewrite as it may scale poorly with deep hierarchies! + + var transform = world.GetComponent(entity); + + // If tranform was updated this frame -> skip + if(transform.Frame == _frame) + return transform; + + var parent = world.GetComponent(entity); + + if(transform.IsDirty) + { + transform.LocalTransform = .Translation(transform.Position) * .RotationX(transform.Rotation.X) * + .RotationY(transform.Rotation.Y) * .RotationZ(transform.Rotation.Z) * .Scaling(transform.Scale); + transform.Frame = _frame; + transform.IsDirty = false; + + if(parent == null) + { + transform.WorldTransform = transform.LocalTransform; + } + } + + if(parent != null) + { + var parentTransform = UpdateEntity(parent.Entity, world); + + // Parent transform is newer than our transform or was updated this frame + if(parentTransform.Frame >= transform.Frame) + { + transform.WorldTransform = parentTransform.WorldTransform * transform.LocalTransform; + transform.Frame = parentTransform.Frame; + } + } + + return transform; + } + } +} diff --git a/Sandbox/src/SandboxApp.bf b/Sandbox/src/SandboxApp.bf index cddbf32..2d8633d 100644 --- a/Sandbox/src/SandboxApp.bf +++ b/Sandbox/src/SandboxApp.bf @@ -270,23 +270,54 @@ namespace Sandbox */ } + Entity evenCrazierParent; + Entity crazyParent; + void InitEcs() { _world.Register(); + _world.Register(); _world.Register(); _world.Register(); + Entity[20][20] entities; + for(int x < 20) for(int y < 20) { Entity entity = _world.NewEntity(); + entities[x][y] = entity; + var transform = _world.AssignComponent(entity); - transform.Transform = Matrix.Translation(x * 0.2f, y * 0.2f, 0) * Matrix.Scaling(0.1f); + transform.LocalTransform = Matrix.Translation(x * 0.2f, y * 0.2f, 0) * Matrix.Scaling(0.1f); var mesh = _world.AssignComponent(entity); mesh.Mesh = _quadGeometryBinding; } + + crazyParent = _world.NewEntity(); + evenCrazierParent = _world.NewEntity(); + + var crazyTransform = _world.AssignComponent(evenCrazierParent); + crazyTransform.Position = .Zero; + crazyTransform.Scale = .One; + crazyTransform.Rotation = .Zero; + + var pp = _world.AssignComponent(crazyParent); + pp.Entity = evenCrazierParent; + + crazyTransform = _world.AssignComponent(crazyParent); + crazyTransform.Position = .Zero; + crazyTransform.Scale = .(2.0f, 2.0f, 2.0f); + crazyTransform.Rotation = .Zero; + + for(int x < 20) + for(int y < 20) + { + var parent = _world.AssignComponent(entities[x][y]); + parent.Entity = crazyParent; + } } float f = 0.0f; @@ -387,39 +418,19 @@ namespace Sandbox } } - /* - // Draw bind pose - for(Joint joint in Skeleton.Joints) - { - Matrix bindPose = joint.InverseBindPose.Invert(); - - if(joint.ParentID != uint8.MaxValue) - { - Vector3 start = bindPose.Translation; - - Matrix parentBindPose = Skeleton.Joints[joint.ParentID].InverseBindPose.Invert(); - - Vector3 end = parentBindPose.Translation; - - Renderer.DrawLine(start, end, .White); - } - - Renderer.DrawLine(.Zero, Vector3(0.1f, 0, 0), .Red, bindPose); - Renderer.DrawLine(.Zero, Vector3(0, 0.1f, 0), .Lime, bindPose); - Renderer.DrawLine(.Zero, Vector3(0, 0, 0.1f), .Blue, bindPose); - } - */ testEffect.ReleaseRef(); } _context.SetRasterizerState(_rasterizerState); - - for(var entity in _world.Enumerate(typeof(TransformComponent))) - { - var transform = _world.GetComponent(entity); - transform.Update(); - } + var crazyTransform = _world.GetComponent(evenCrazierParent); + crazyTransform.Rotation += .((float)gameTime.FrameTime.TotalSeconds / 2, 0, 0); + + crazyTransform = _world.GetComponent(crazyParent); + crazyTransform.Rotation += .(0, (float)gameTime.FrameTime.TotalSeconds, 0); + + TransformSystem.Update(_world); + int i = 0; for(var entity in _world.Enumerate(typeof(TransformComponent), typeof(MeshComponent))) { @@ -433,7 +444,7 @@ namespace Sandbox var transform = _world.GetComponent(entity); var mesh = _world.GetComponent(entity); - Renderer.Submit(mesh.Mesh, basicEffect, transform.Transform); + Renderer.Submit(mesh.Mesh, basicEffect, transform.WorldTransform); } basicEffect.Variables["BaseColor"].SetData(_squareColor1); diff --git a/Sandbox/src/SandboxApp2D.bf b/Sandbox/src/SandboxApp2D.bf index 7e7468b..acc8e20 100644 --- a/Sandbox/src/SandboxApp2D.bf +++ b/Sandbox/src/SandboxApp2D.bf @@ -244,7 +244,8 @@ namespace Sandbox movement *= (float)(gameTime.FrameTime.TotalSeconds); cameraTransform.Position += .(movement, 0); - cameraTransform.Update(); + Runtime.NotImplemented(); + //cameraTransform.Update(); } var camera = _world.GetComponent(_cameraEntity);