arcball transform system for camera

pull/1/head
cosmonaut 2020-08-06 14:21:34 -07:00
parent df59c033ef
commit a8e8402833
10 changed files with 138 additions and 19 deletions

2
FNA

@ -1 +1 @@
Subproject commit 9a8a84c3d427f47759a92342aaa8f7f08e751a64 Subproject commit c665d2e08c25fb63e58e987b7c1af75af22aa010

2
Kav

@ -1 +1 @@
Subproject commit d156fbc39a771ac990cbb809b82ba771464785a5 Subproject commit 55b1555df2ded543e623c8b5eb60d3a3fff9e32c

View File

@ -0,0 +1,14 @@
using Encompass;
namespace KavTest
{
public struct ArcballTransformComponent : IComponent
{
public ArcballTransform ArcballTransform { get; }
public ArcballTransformComponent(ArcballTransform arcballTransform)
{
ArcballTransform = arcballTransform;
}
}
}

View File

@ -4,9 +4,9 @@ using KavTest.Messages;
namespace KavTest.Engines namespace KavTest.Engines
{ {
[Reads(typeof(CameraComponent))] [Reads(typeof(CameraComponent), typeof(ArcballTransformComponent))]
[Receives(typeof(MoveCameraMessage))] [Receives(typeof(MoveCameraMessage), typeof(RotateCameraMessage))]
[Sends(typeof(LocalTranslationMessage))] [Writes(typeof(ArcballTransformComponent))]
public class CameraEngine : Engine public class CameraEngine : Engine
{ {
public override void Update(double dt) public override void Update(double dt)
@ -14,11 +14,21 @@ namespace KavTest.Engines
if (SomeComponent<CameraComponent>()) if (SomeComponent<CameraComponent>())
{ {
var cameraEntity = ReadEntity<CameraComponent>(); var cameraEntity = ReadEntity<CameraComponent>();
var arcballTransformComponent = GetComponent<ArcballTransformComponent>(cameraEntity);
var transform = arcballTransformComponent.ArcballTransform;
foreach (var moveMessage in ReadMessages<MoveCameraMessage>()) foreach (var moveMessage in ReadMessages<MoveCameraMessage>())
{ {
SendMessage(new LocalTranslationMessage(cameraEntity, moveMessage.Translation * (float)dt)); transform = transform.TranslateLocal(moveMessage.Translation * (float)dt);
} }
foreach (var rotateMessage in ReadMessages<RotateCameraMessage>())
{
transform = transform.RotateLocal(-rotateMessage.Yaw * 0.25f * (float)dt, rotateMessage.Pitch * 0.25f * (float)dt);
}
SetComponent(cameraEntity, new ArcballTransformComponent(transform));
} }
} }
} }

View File

@ -1,16 +1,35 @@
using Encompass; using Encompass;
using KavTest.Components;
using KavTest.Messages; using KavTest.Messages;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
namespace KavTest.Engines namespace KavTest.Engines
{ {
[Sends(typeof(MoveCameraMessage))] [Reads(typeof(CameraComponent))]
[Sends(
typeof(MoveCameraMessage),
typeof(RotateCameraMessage)
)]
public class InputEngine : Engine public class InputEngine : Engine
{ {
private int centerX;
private int centerY;
public InputEngine(int centerX, int centerY)
{
System.Console.WriteLine(centerX);
System.Console.WriteLine(centerY);
this.centerX = centerX;
this.centerY = centerY;
Mouse.SetPosition(centerX, centerY);
System.Console.WriteLine(Mouse.GetState().X);
}
public override void Update(double dt) public override void Update(double dt)
{ {
var keyboardState = Keyboard.GetState(); var keyboardState = Keyboard.GetState();
var mouseState = Mouse.GetState();
if (keyboardState.IsKeyDown(Keys.W)) if (keyboardState.IsKeyDown(Keys.W))
{ {
@ -31,6 +50,15 @@ namespace KavTest.Engines
{ {
SendMessage(new MoveCameraMessage(new Vector3(5, 0, 0))); SendMessage(new MoveCameraMessage(new Vector3(5, 0, 0)));
} }
var mouseMovement = new Vector2(centerX - mouseState.X, centerY - mouseState.Y);
Mouse.SetPosition(centerX, centerY);
if (SomeComponent<CameraComponent>())
{
var cameraEntity = ReadEntity<CameraComponent>();
SendMessage(new RotateCameraMessage(cameraEntity, mouseMovement.X, mouseMovement.Y));
}
} }
} }
} }

View File

@ -36,7 +36,7 @@ namespace KavTest
Smuggler.Importer.ImportGLB(GraphicsDevice, File.OpenRead("Content/rustysphere.glb")) Smuggler.Importer.ImportGLB(GraphicsDevice, File.OpenRead("Content/rustysphere.glb"))
); );
WorldBuilder.AddEngine(new InputEngine()); WorldBuilder.AddEngine(new InputEngine(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2));
WorldBuilder.AddEngine(new AngularVelocityEngine()); WorldBuilder.AddEngine(new AngularVelocityEngine());
WorldBuilder.AddEngine(new MotionEngine()); WorldBuilder.AddEngine(new MotionEngine());
WorldBuilder.AddEngine(new CameraEngine()); WorldBuilder.AddEngine(new CameraEngine());
@ -65,15 +65,13 @@ namespace KavTest
300f 300f
)); ));
var cameraTransform = new Transform3D(
new Vector3(0, 0, -10),
Quaternion.CreateFromAxisAngle(Vector3.Up, MathHelper.Pi),
Vector3.One
);
var cameraEntity = WorldBuilder.CreateEntity(); var cameraEntity = WorldBuilder.CreateEntity();
WorldBuilder.SetComponent(cameraEntity, new Transform3DComponent( WorldBuilder.SetComponent(cameraEntity, new ArcballTransformComponent(
cameraTransform new ArcballTransform(
new Vector3(0, 0, -10),
MathHelper.Pi,
0
)
)); ));
WorldBuilder.SetComponent(cameraEntity, new CameraComponent( WorldBuilder.SetComponent(cameraEntity, new CameraComponent(
Matrix.CreatePerspectiveFieldOfView( Matrix.CreatePerspectiveFieldOfView(

View File

@ -0,0 +1,18 @@
using Encompass;
namespace KavTest
{
public struct RotateCameraMessage : IMessage, IHasEntity
{
public Entity Entity { get; }
public float Yaw { get; }
public float Pitch { get; }
public RotateCameraMessage(Entity entity, float yaw, float pitch)
{
Entity = entity;
Yaw = yaw;
Pitch = pitch;
}
}
}

View File

@ -54,11 +54,11 @@ namespace KavTest.Renderers
if (SomeComponent<CameraComponent>()) if (SomeComponent<CameraComponent>())
{ {
var cameraEntity = ReadEntity<CameraComponent>(); var cameraEntity = ReadEntity<CameraComponent>();
var transformComponent = GetComponent<Transform3DComponent>(cameraEntity); var transformComponent = GetComponent<ArcballTransformComponent>(cameraEntity);
var cameraComponent = GetComponent<CameraComponent>(cameraEntity); var cameraComponent = GetComponent<CameraComponent>(cameraEntity);
var camera = new Kav.Camera( var camera = new Kav.Camera(
transformComponent.Transform.TransformMatrix, transformComponent.ArcballTransform.TransformMatrix,
cameraComponent.Projection cameraComponent.Projection
); );

View File

@ -0,0 +1,51 @@
using Microsoft.Xna.Framework;
namespace KavTest
{
public struct ArcballTransform
{
public Vector3 Position { get; }
public float Yaw { get; }
public float Pitch { get; }
private Matrix RotationMatrix { get; }
public Matrix TransformMatrix { get; }
public Vector3 Forward { get { return TransformMatrix.Forward; } }
public Vector3 Right { get { return TransformMatrix.Right; } }
public Vector3 Up { get { return TransformMatrix.Up; } }
public ArcballTransform(Vector3 position, float yaw, float pitch)
{
Position = position;
Yaw = yaw;
Pitch = pitch;
RotationMatrix = CreateRotationMatrix(Yaw, Pitch);
TransformMatrix = CreateTransformMatrix(Position, RotationMatrix);
}
public ArcballTransform RotateLocal(float deltaYaw, float deltaPitch)
{
return new ArcballTransform(Position, Yaw + deltaYaw, Pitch + deltaPitch);
}
public ArcballTransform TranslateLocal(Vector3 localTranslation)
{
var worldTranslation = Vector3.Transform(localTranslation, RotationMatrix);
return new ArcballTransform(Position + worldTranslation, Yaw, Pitch);
}
private static Matrix CreateRotationMatrix(float yaw, float pitch)
{
return
Matrix.CreateRotationX(pitch) *
Matrix.CreateRotationY(yaw);
}
private static Matrix CreateTransformMatrix(Vector3 position, Matrix rotation)
{
return
rotation *
Matrix.CreateTranslation(position);
}
}
}

@ -1 +1 @@
Subproject commit 0a30dab3c2a8ef4ce435af8123bcb64efe4926d8 Subproject commit bdd9f595493609444d8ebb31b9d07b7ef320eafb