diff --git a/Kav b/Kav index 2419a89..4c41506 160000 --- a/Kav +++ b/Kav @@ -1 +1 @@ -Subproject commit 2419a89d3245dc7d52f6b4301902f840ea10beaf +Subproject commit 4c4150620456c6625cf660d7a81571e4b1f7f9d5 diff --git a/KavTest.Core.sln b/KavTest.Core.sln index d4806a3..53a0da1 100644 --- a/KavTest.Core.sln +++ b/KavTest.Core.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KavTest.Core", "KavTest\KavTest.Core.csproj", "{4589302C-174A-4173-9654-CAA6CA1B5220}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "kav", "Kav\kav.csproj", "{08398000-DF30-465A-AE07-E11D108B8A74}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kav", "Kav\Kav.csproj", "{08398000-DF30-465A-AE07-E11D108B8A74}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/KavTest.Framework.sln b/KavTest.Framework.sln index 4cb6f06..2571b07 100644 --- a/KavTest.Framework.sln +++ b/KavTest.Framework.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNATemplate.Framework", "KavTest\KavTest.Framework.csproj", "{9ED076FA-32C3-4F1E-BB90-549B3A2FA46F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "kav", "Kav\kav.csproj", "{9B2EC2DE-7E2C-4768-B812-43AB4C7E31C5}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kav", "Kav\Kav.csproj", "{9B2EC2DE-7E2C-4768-B812-43AB4C7E31C5}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Smuggler", "Smuggler\Smuggler.csproj", "{06664804-2B01-46F5-B8EC-07E5E2C1EADC}" EndProject diff --git a/KavTest/Components/AngularVelocityComponent.cs b/KavTest/Components/AngularVelocityComponent.cs index d7bf1e5..6a44fcd 100644 --- a/KavTest/Components/AngularVelocityComponent.cs +++ b/KavTest/Components/AngularVelocityComponent.cs @@ -5,7 +5,7 @@ namespace KavTest.Components { public struct AngularVelocityComponent : IComponent { - public Vector3 AngularVelocity { get; } + public Vector3 AngularVelocity { get; } // should this be a quaternion? public AngularVelocityComponent(Vector3 angularVelocity) { diff --git a/KavTest/Components/CameraComponent.cs b/KavTest/Components/CameraComponent.cs index 7643ab3..764ed69 100644 --- a/KavTest/Components/CameraComponent.cs +++ b/KavTest/Components/CameraComponent.cs @@ -1,15 +1,15 @@ using Encompass; -using Kav; +using Microsoft.Xna.Framework; namespace KavTest.Components { public struct CameraComponent : IComponent { - public Camera Camera { get; } + public Matrix Projection { get; } - public CameraComponent(Camera camera) + public CameraComponent(Matrix projection) { - Camera = camera; + Projection = projection; } } } diff --git a/KavTest/Components/TransformComponent.cs b/KavTest/Components/Transform3DComponent.cs similarity index 100% rename from KavTest/Components/TransformComponent.cs rename to KavTest/Components/Transform3DComponent.cs diff --git a/KavTest/Content/rustysphere.glb b/KavTest/Content/rustysphere.glb new file mode 100644 index 0000000..db9e8e5 Binary files /dev/null and b/KavTest/Content/rustysphere.glb differ diff --git a/KavTest/Engines/AngularVelocityEngine.cs b/KavTest/Engines/AngularVelocityEngine.cs new file mode 100644 index 0000000..a8ce9fe --- /dev/null +++ b/KavTest/Engines/AngularVelocityEngine.cs @@ -0,0 +1,23 @@ +using Encompass; +using KavTest.Components; +using KavTest.Messages; +using Microsoft.Xna.Framework; + +namespace KavTest.Engines +{ + [Reads(typeof(AngularVelocityComponent))] + [Sends(typeof(LocalRotationMessage))] + public class AngularVelocityEngine : Engine + { + public override void Update(double dt) + { + foreach (var entity in ReadEntities()) + { + ref readonly var angularVelocityComponent = ref GetComponent(entity); + var angularVelocity = angularVelocityComponent.AngularVelocity * (float)dt; + + SendMessage(new LocalRotationMessage(entity, Quaternion.CreateFromYawPitchRoll(angularVelocity.X, angularVelocity.Y, angularVelocity.Z))); + } + } + } +} diff --git a/KavTest/Engines/CameraEngine.cs b/KavTest/Engines/CameraEngine.cs new file mode 100644 index 0000000..064c7c7 --- /dev/null +++ b/KavTest/Engines/CameraEngine.cs @@ -0,0 +1,25 @@ +using Encompass; +using KavTest.Components; +using KavTest.Messages; + +namespace KavTest.Engines +{ + [Reads(typeof(CameraComponent))] + [Receives(typeof(MoveCameraMessage))] + [Sends(typeof(LocalTranslationMessage))] + public class CameraEngine : Engine + { + public override void Update(double dt) + { + if (SomeComponent()) + { + var cameraEntity = ReadEntity(); + + foreach (var moveMessage in ReadMessages()) + { + SendMessage(new LocalTranslationMessage(cameraEntity, moveMessage.Translation * (float)dt)); + } + } + } + } +} diff --git a/KavTest/Engines/InputEngine.cs b/KavTest/Engines/InputEngine.cs new file mode 100644 index 0000000..94b31ec --- /dev/null +++ b/KavTest/Engines/InputEngine.cs @@ -0,0 +1,36 @@ +using Encompass; +using KavTest.Messages; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; + +namespace KavTest.Engines +{ + [Sends(typeof(MoveCameraMessage))] + public class InputEngine : Engine + { + public override void Update(double dt) + { + var keyboardState = Keyboard.GetState(); + + if (keyboardState.IsKeyDown(Keys.W)) + { + SendMessage(new MoveCameraMessage(new Vector3(0, 0, -5))); + } + + if (keyboardState.IsKeyDown(Keys.A)) + { + SendMessage(new MoveCameraMessage(new Vector3(-5, 0, 0))); + } + + if (keyboardState.IsKeyDown(Keys.S)) + { + SendMessage(new MoveCameraMessage(new Vector3(0, 0, 5))); + } + + if (keyboardState.IsKeyDown(Keys.D)) + { + SendMessage(new MoveCameraMessage(new Vector3(5, 0, 0))); + } + } + } +} diff --git a/KavTest/Engines/MotionEngine.cs b/KavTest/Engines/MotionEngine.cs new file mode 100644 index 0000000..96a54c8 --- /dev/null +++ b/KavTest/Engines/MotionEngine.cs @@ -0,0 +1,55 @@ +using Encompass; +using KavTest.Components; +using KavTest.Messages; +using Microsoft.Xna.Framework; + +namespace KavTest.Engines +{ + [Reads(typeof(Transform3DComponent))] + [Receives( + typeof(TranslationMessage), + typeof(LocalTranslationMessage), + typeof(LocalRotationMessage) + )] + [Writes(typeof(Transform3DComponent))] + public class MotionEngine : Engine + { + public override void Update(double dt) + { + foreach (var entity in ReadEntities()) + { + ref readonly var transformComponent = ref GetComponent(entity); + + Vector3 translation = Vector3.Zero; + Vector3 localTranslation = Vector3.Zero; + + Quaternion rotation = Quaternion.Identity; + Quaternion localRotation = Quaternion.Identity; + + foreach (var message in ReadMessagesWithEntity(entity)) + { + translation += message.Translation; + } + + foreach (var message in ReadMessagesWithEntity(entity)) + { + localTranslation += message.Translation; + } + + foreach (var message in ReadMessagesWithEntity(entity)) + { + localRotation *= message.Rotation; + } + + var newTransform = + transformComponent.Transform. + TranslateLocal(localTranslation). + RotateLocal(localRotation). + Translate(translation); + + + SetComponent(entity, new Transform3DComponent(newTransform)); + } + } + } +} diff --git a/KavTest/Engines/RotationEngine.cs b/KavTest/Engines/RotationEngine.cs deleted file mode 100644 index 6f7be9a..0000000 --- a/KavTest/Engines/RotationEngine.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Encompass; -using KavTest.Components; -using Microsoft.Xna.Framework; - -namespace KavTest.Engines -{ - [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)) - { - ref readonly var angularVelocityComponent = ref GetComponent(entity); - ref readonly var transformComponent = ref GetComponent(entity); - - var angularVelocity = angularVelocityComponent.AngularVelocity * (float)dt; - - SetComponent(entity, new Transform3DComponent(transformComponent.Transform.Rotate(angularVelocity))); - } - } - } - } -} diff --git a/KavTest/KavTest.Framework.csproj b/KavTest/KavTest.Framework.csproj index 0bf3791..2766f9f 100644 --- a/KavTest/KavTest.Framework.csproj +++ b/KavTest/KavTest.Framework.csproj @@ -30,7 +30,6 @@ - diff --git a/KavTest/KavTestGame.cs b/KavTest/KavTestGame.cs index e339a72..c6925d7 100644 --- a/KavTest/KavTestGame.cs +++ b/KavTest/KavTestGame.cs @@ -33,10 +33,13 @@ namespace KavTest { var rustyBallModel = ModelLoader.Load( GraphicsDevice, - Smuggler.Importer.ImportGLB(GraphicsDevice, File.OpenRead("Content/cube.glb")) + Smuggler.Importer.ImportGLB(GraphicsDevice, File.OpenRead("Content/rustysphere.glb")) ); - WorldBuilder.AddEngine(new RotationEngine()); + WorldBuilder.AddEngine(new InputEngine()); + WorldBuilder.AddEngine(new AngularVelocityEngine()); + WorldBuilder.AddEngine(new MotionEngine()); + WorldBuilder.AddEngine(new CameraEngine()); WorldBuilder.AddEngine(new RustyBallSpawner(rustyBallModel)); WorldBuilder.AddEngine(new LightBulbSpawner()); WorldBuilder.AddGeneralRenderer(new SceneRenderer(GraphicsDevice), 0); @@ -47,12 +50,12 @@ namespace KavTest )); WorldBuilder.SendMessage(new RustyBallSpawnMessage( - new Transform3D(new Vector3(-5, 0, 0)), + new Transform3D(new Vector3(-3, 0, 0)), new Vector3(-1, 1, -1) )); WorldBuilder.SendMessage(new RustyBallSpawnMessage( - new Transform3D(new Vector3(5, 0, 0)), + new Transform3D(new Vector3(3, 0, 0)), new Vector3(-1, 1, 1) )); @@ -62,11 +65,22 @@ namespace KavTest 300f )); - var cameraMatrix = Matrix.CreateLookAt(new Vector3(10, 0, 0), Vector3.Zero, Vector3.Up); + var cameraTransform = new Transform3D( + new Vector3(0, 0, -10), + Quaternion.CreateFromAxisAngle(Vector3.Up, MathHelper.Pi), + Vector3.One + ); + var cameraEntity = WorldBuilder.CreateEntity(); + WorldBuilder.SetComponent(cameraEntity, new Transform3DComponent( + cameraTransform + )); WorldBuilder.SetComponent(cameraEntity, new CameraComponent( - new Kav.Camera( - cameraMatrix + Matrix.CreatePerspectiveFieldOfView( + MathHelper.PiOver4, + 16f / 9f, + 0.1f, + 200f ) )); diff --git a/KavTest/Messages/LocalRotationMessage.cs b/KavTest/Messages/LocalRotationMessage.cs new file mode 100644 index 0000000..4f67699 --- /dev/null +++ b/KavTest/Messages/LocalRotationMessage.cs @@ -0,0 +1,17 @@ +using Encompass; +using Microsoft.Xna.Framework; + +namespace KavTest.Messages +{ + public struct LocalRotationMessage : IMessage, IHasEntity + { + public Entity Entity { get; } + public Quaternion Rotation { get; } + + public LocalRotationMessage(Entity entity, Quaternion rotation) + { + Entity = entity; + Rotation = rotation; + } + } +} diff --git a/KavTest/Messages/LocalTranslationMessage.cs b/KavTest/Messages/LocalTranslationMessage.cs new file mode 100644 index 0000000..4f14ebf --- /dev/null +++ b/KavTest/Messages/LocalTranslationMessage.cs @@ -0,0 +1,17 @@ +using Encompass; +using Microsoft.Xna.Framework; + +namespace KavTest.Messages +{ + public struct LocalTranslationMessage : IMessage, IHasEntity + { + public Entity Entity { get; } + public Vector3 Translation { get; } + + public LocalTranslationMessage(Entity entity, Vector3 translation) + { + Entity = entity; + Translation = translation; + } + } +} diff --git a/KavTest/Messages/MoveCameraMessage.cs b/KavTest/Messages/MoveCameraMessage.cs new file mode 100644 index 0000000..17dd5a9 --- /dev/null +++ b/KavTest/Messages/MoveCameraMessage.cs @@ -0,0 +1,15 @@ +using Encompass; +using Microsoft.Xna.Framework; + +namespace KavTest.Messages +{ + public struct MoveCameraMessage : IMessage + { + public Vector3 Translation { get; } + + public MoveCameraMessage(Vector3 translation) + { + Translation = translation; + } + } +} diff --git a/KavTest/Messages/TranslationMessage.cs b/KavTest/Messages/TranslationMessage.cs new file mode 100644 index 0000000..185a34e --- /dev/null +++ b/KavTest/Messages/TranslationMessage.cs @@ -0,0 +1,17 @@ +using Encompass; +using Microsoft.Xna.Framework; + +namespace KavTest.Messages +{ + public struct TranslationMessage : IMessage, IHasEntity + { + public Entity Entity { get; } + public Vector3 Translation { get; } + + public TranslationMessage(Entity entity, Vector3 translation) + { + Entity = entity; + Translation = translation; + } + } +} diff --git a/KavTest/Renderers/SceneRenderer.cs b/KavTest/Renderers/SceneRenderer.cs index d6612ea..c85a5b1 100644 --- a/KavTest/Renderers/SceneRenderer.cs +++ b/KavTest/Renderers/SceneRenderer.cs @@ -53,11 +53,18 @@ namespace KavTest.Renderers { if (SomeComponent()) { - var cameraComponent = ReadComponent(); + var cameraEntity = ReadEntity(); + var transformComponent = GetComponent(cameraEntity); + var cameraComponent = GetComponent(cameraEntity); + + var camera = new Kav.Camera( + transformComponent.Transform.TransformMatrix, + cameraComponent.Projection + ); Kav.Renderer.Render( GraphicsDevice, - cameraComponent.Camera, + camera, Models, PointLights ); diff --git a/KavTest/Utility/Transform3D.cs b/KavTest/Utility/Transform3D.cs index 35a25ed..e3a6710 100644 --- a/KavTest/Utility/Transform3D.cs +++ b/KavTest/Utility/Transform3D.cs @@ -4,57 +4,73 @@ namespace KavTest { public struct Transform3D : System.IEquatable { - public Matrix TransformMatrix { get; private set; } + public static Transform3D Identity = new Transform3D(Vector3.Zero, Quaternion.Identity, Vector3.One); - public Vector3 Position { get; private set; } + public Matrix TransformMatrix { get; } + public Vector3 Position { get; } + public Quaternion Orientation { get; } + public Vector3 Scale { get; } public Vector3 Forward { get { return TransformMatrix.Forward; } } + public Vector3 Right { get { return TransformMatrix.Right; } } + public Vector3 Up { get { return TransformMatrix.Up; } } public Transform3D(Vector3 position, Quaternion orientation, Vector3 scale) { Position = position; - TransformMatrix = CreateTransformMatrix(position, orientation, scale); + Orientation = orientation; + Scale = scale; + TransformMatrix = CreateTransformMatrix(Position, Orientation, Scale); + } + + public Transform3D(Vector3 position, Quaternion orientation) + { + Position = position; + Orientation = orientation; + Scale = Vector3.One; + 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; + Orientation = Quaternion.Identity; + Scale = Vector3.One; + TransformMatrix = CreateTransformMatrix(Position, Orientation, Scale); } public Transform3D WithPosition(Vector3 position) { - return Translate(position - TransformMatrix.Translation); + return Translate(position - Position); } public Transform3D Translate(Vector3 translation) { - return new Transform3D(Matrix.CreateTranslation(translation) * TransformMatrix); + return new Transform3D(Position + translation, Orientation, Scale); } - public Transform3D Rotate(Quaternion other) + public Transform3D TranslateLocal(Vector3 translation) { - return new Transform3D(Matrix.CreateFromQuaternion(other) * TransformMatrix); + return Translate(Vector3.Transform(translation, Orientation)); } - public Transform3D Rotate(float yaw, float pitch, float roll) + public Transform3D RotateLocal(Quaternion other) { - return Rotate(Quaternion.CreateFromYawPitchRoll( + return new Transform3D(Position, Orientation * other, Scale); + } + + public Transform3D RotateLocal(float yaw, float pitch, float roll) + { + return RotateLocal(Quaternion.CreateFromYawPitchRoll( yaw, pitch, roll )); } - public Transform3D Rotate(Vector3 eulerAngles) + public Transform3D RotateLocal(Vector3 eulerAngles) { - return Rotate(Quaternion.CreateFromYawPitchRoll( + return RotateLocal(Quaternion.CreateFromYawPitchRoll( eulerAngles.X, eulerAngles.Y, eulerAngles.Z @@ -63,9 +79,7 @@ namespace KavTest public Transform3D Compose(Transform3D other) { - return new Transform3D( - other.TransformMatrix * TransformMatrix - ); + return new Transform3D(Position + other.Position, Orientation * other.Orientation, Scale * other.Scale); } private static Matrix CreateTransformMatrix(Vector3 position, Quaternion orientation, Vector3 scale)