diff --git a/Kav b/Kav index f0f0911..2419a89 160000 --- a/Kav +++ b/Kav @@ -1 +1 @@ -Subproject commit f0f09115f5dfbe34179bab33f60d07230aed9dd7 +Subproject commit 2419a89d3245dc7d52f6b4301902f840ea10beaf diff --git a/KavTest/Components/TransformComponent.cs b/KavTest/Components/TransformComponent.cs index 779c69b..9bd6d4d 100644 --- a/KavTest/Components/TransformComponent.cs +++ b/KavTest/Components/TransformComponent.cs @@ -1,13 +1,12 @@ using Encompass; -using Microsoft.Xna.Framework; namespace KavTest.Components { - public struct TransformComponent : IComponent + public struct Transform3DComponent : IComponent { - public Matrix Transform { get; } + public Transform3D Transform { get; } - public TransformComponent(Matrix transform) + public Transform3DComponent(Transform3D transform) { Transform = transform; } diff --git a/KavTest/Engines/RotationEngine.cs b/KavTest/Engines/RotationEngine.cs index fdeb567..6f7be9a 100644 --- a/KavTest/Engines/RotationEngine.cs +++ b/KavTest/Engines/RotationEngine.cs @@ -4,24 +4,22 @@ using Microsoft.Xna.Framework; namespace KavTest.Engines { - [Reads(typeof(TransformComponent), typeof(AngularVelocityComponent))] - [Writes(typeof(TransformComponent))] + [Reads(typeof(Transform3DComponent), typeof(AngularVelocityComponent))] + [Writes(typeof(Transform3DComponent))] public class RotationEngine : Engine { public override void Update(double dt) { foreach (var entity in ReadEntities()) { - if (HasComponent(entity)) + if (HasComponent(entity)) { ref readonly var angularVelocityComponent = ref GetComponent(entity); - ref readonly var transformComponent = ref GetComponent(entity); + ref readonly var transformComponent = ref GetComponent(entity); var angularVelocity = angularVelocityComponent.AngularVelocity * (float)dt; - var transform = transformComponent.Transform; - var newTransform = Matrix.Transform(transform, Quaternion.CreateFromYawPitchRoll(angularVelocity.X, angularVelocity.Y, angularVelocity.Z)); - SetComponent(entity, new TransformComponent(newTransform)); + SetComponent(entity, new Transform3DComponent(transformComponent.Transform.Rotate(angularVelocity))); } } } diff --git a/KavTest/Engines/Spawners/LightBulbSpawner.cs b/KavTest/Engines/Spawners/LightBulbSpawner.cs index ca8c814..295ac85 100644 --- a/KavTest/Engines/Spawners/LightBulbSpawner.cs +++ b/KavTest/Engines/Spawners/LightBulbSpawner.cs @@ -10,7 +10,7 @@ namespace KavTest.Spawners { var entity = CreateEntity(); - AddComponent(entity, new TransformComponent(message.Transform)); + AddComponent(entity, new Transform3DComponent(message.Transform)); AddComponent(entity, new PointLightComponent(message.Color, message.Intensity)); } } diff --git a/KavTest/Engines/Spawners/RustyBallSpawner.cs b/KavTest/Engines/Spawners/RustyBallSpawner.cs index 35e700c..1bd5dd9 100644 --- a/KavTest/Engines/Spawners/RustyBallSpawner.cs +++ b/KavTest/Engines/Spawners/RustyBallSpawner.cs @@ -18,9 +18,9 @@ namespace KavTest.Spawners { var entity = CreateEntity(); - AddComponent(entity, new TransformComponent(message.Transform)); + AddComponent(entity, new Transform3DComponent(message.Transform)); AddComponent(entity, new ModelComponent(RustyBallModel)); - AddComponent(entity, new AngularVelocityComponent(new Microsoft.Xna.Framework.Vector3(5, -2, 1))); + AddComponent(entity, new AngularVelocityComponent(message.AngularVelocity)); } } } diff --git a/KavTest/KavTestGame.cs b/KavTest/KavTestGame.cs index d3c86a9..e339a72 100644 --- a/KavTest/KavTestGame.cs +++ b/KavTest/KavTestGame.cs @@ -42,10 +42,22 @@ namespace KavTest WorldBuilder.AddGeneralRenderer(new SceneRenderer(GraphicsDevice), 0); WorldBuilder.SendMessage(new RustyBallSpawnMessage( - Matrix.CreateTranslation(0, 0, 0) + new Transform3D(new Vector3(0, 0, 0)), + new Vector3(1, 1, -1) )); + + WorldBuilder.SendMessage(new RustyBallSpawnMessage( + new Transform3D(new Vector3(-5, 0, 0)), + new Vector3(-1, 1, -1) + )); + + WorldBuilder.SendMessage(new RustyBallSpawnMessage( + new Transform3D(new Vector3(5, 0, 0)), + new Vector3(-1, 1, 1) + )); + WorldBuilder.SendMessage(new LightBulbSpawnMessage( - Matrix.CreateTranslation(10, 0, -5), + new Transform3D(new Vector3(0, 2, -5)), Color.White, 300f )); diff --git a/KavTest/Messages/LightBulbSpawnMessage.cs b/KavTest/Messages/LightBulbSpawnMessage.cs index 5f308d3..bb2704c 100644 --- a/KavTest/Messages/LightBulbSpawnMessage.cs +++ b/KavTest/Messages/LightBulbSpawnMessage.cs @@ -5,11 +5,11 @@ namespace KavTest.Messages { public struct LightBulbSpawnMessage : IMessage { - public Matrix Transform { get; } + public Transform3D Transform { get; } public Color Color { get; } public float Intensity { get; } - public LightBulbSpawnMessage(Matrix transform, Color color, float intensity) + public LightBulbSpawnMessage(Transform3D transform, Color color, float intensity) { Transform = transform; Color = color; diff --git a/KavTest/Messages/RustyBallSpawnMessage.cs b/KavTest/Messages/RustyBallSpawnMessage.cs index 455489d..323f23f 100644 --- a/KavTest/Messages/RustyBallSpawnMessage.cs +++ b/KavTest/Messages/RustyBallSpawnMessage.cs @@ -6,11 +6,13 @@ namespace KavTest.Messages { public struct RustyBallSpawnMessage : IMessage { - public Matrix Transform { get; } + public Transform3D Transform { get; } + public Vector3 AngularVelocity { get; } - public RustyBallSpawnMessage(Matrix transform) + public RustyBallSpawnMessage(Transform3D transform, Vector3 angularVelocity) { Transform = transform; + AngularVelocity = angularVelocity; } } } diff --git a/KavTest/Renderers/SceneRenderer.cs b/KavTest/Renderers/SceneRenderer.cs index b0ecc7b..d6612ea 100644 --- a/KavTest/Renderers/SceneRenderer.cs +++ b/KavTest/Renderers/SceneRenderer.cs @@ -17,10 +17,10 @@ namespace KavTest.Renderers { foreach (var entity in ReadEntitiesAsEnumerable()) { - var transformComponent = GetComponent(entity); + var transformComponent = GetComponent(entity); var modelComponent = GetComponent(entity); - modelComponent.Model.ApplyTransform(transformComponent.Transform); + modelComponent.Model.ApplyTransform(transformComponent.Transform.TransformMatrix); yield return modelComponent.Model; } } @@ -32,11 +32,11 @@ namespace KavTest.Renderers { foreach (var entity in ReadEntitiesAsEnumerable()) { - var transformComponent = GetComponent(entity); + var transformComponent = GetComponent(entity); var pointLightComponent = GetComponent(entity); yield return new PointLight( - transformComponent.Transform.Translation, + transformComponent.Transform.TransformMatrix.Translation, pointLightComponent.Color, pointLightComponent.Intensity ); diff --git a/KavTest/Utility/Transform3D.cs b/KavTest/Utility/Transform3D.cs new file mode 100644 index 0000000..35a25ed --- /dev/null +++ b/KavTest/Utility/Transform3D.cs @@ -0,0 +1,108 @@ +using Microsoft.Xna.Framework; + +namespace KavTest +{ + public struct Transform3D : System.IEquatable + { + public Matrix TransformMatrix { get; private set; } + + public Vector3 Position { get; private set; } + + public Vector3 Forward { get { return TransformMatrix.Forward; } } + + public Transform3D(Vector3 position, Quaternion orientation, Vector3 scale) + { + Position = position; + TransformMatrix = CreateTransformMatrix(position, orientation, scale); + } + + public Transform3D(Vector3 position) + { + Position = position; + TransformMatrix = CreateTransformMatrix(position, Quaternion.Identity, Vector3.One); + } + + public Transform3D(Matrix matrix) + { + Position = matrix.Translation; + TransformMatrix = matrix; + } + + public Transform3D WithPosition(Vector3 position) + { + return Translate(position - TransformMatrix.Translation); + } + + public Transform3D Translate(Vector3 translation) + { + return new Transform3D(Matrix.CreateTranslation(translation) * TransformMatrix); + } + + public Transform3D Rotate(Quaternion other) + { + return new Transform3D(Matrix.CreateFromQuaternion(other) * TransformMatrix); + } + + public Transform3D Rotate(float yaw, float pitch, float roll) + { + return Rotate(Quaternion.CreateFromYawPitchRoll( + yaw, + pitch, + roll + )); + } + + public Transform3D Rotate(Vector3 eulerAngles) + { + return Rotate(Quaternion.CreateFromYawPitchRoll( + eulerAngles.X, + eulerAngles.Y, + eulerAngles.Z + )); + } + + public Transform3D Compose(Transform3D other) + { + return new Transform3D( + other.TransformMatrix * TransformMatrix + ); + } + + private static Matrix CreateTransformMatrix(Vector3 position, Quaternion orientation, Vector3 scale) + { + return Matrix.CreateScale(scale) * + Matrix.CreateFromQuaternion(orientation) * + Matrix.CreateTranslation(position); + } + + public override bool Equals(object other) + { + if (other is Transform3D otherTransform) + { + return Equals(otherTransform); + } + + return false; + } + + public bool Equals(Transform3D other) + { + return TransformMatrix == other.TransformMatrix; + } + + public override int GetHashCode() + { + return TransformMatrix.GetHashCode(); + } + + public static bool operator ==(Transform3D a, Transform3D b) + { + return a.Equals(b); + } + + public static bool operator !=(Transform3D a, Transform3D b) + { + return !(a == b); + } + } +}