Editor camera and Editor/Runtime scene update separation

This commit is contained in:
Simon Lübeß
2022-05-17 19:06:28 +02:00
parent ccea61fb79
commit 5d8a4ad3a7
10 changed files with 486 additions and 126 deletions
+3
View File
@@ -30,6 +30,9 @@ namespace GlitchyEngine
public static extern Point GetMousePosition();
public static extern int32 GetMouseX();
public static extern int32 GetMouseY();
// TODO: Should Input be able to set mousepos?
public static extern void SetMousePosition(Point pos);
public static extern bool WasMouseButtonPressed(MouseButton button);
public static extern bool WasMouseButtonReleased(MouseButton button);
@@ -5,6 +5,7 @@ using GlitchyEngine.Events;
using DirectX.Windows.VirtualKeyCodes;
using DirectX.Windows;
using GlitchyEngine.Math;
using System.Interop;
using static System.Windows;
namespace GlitchyEngine
@@ -154,11 +155,15 @@ namespace GlitchyEngine
public override static Point GetMouseMovement() => CurrentState.CursorPositionDifference;
public override static void SetMousePosition(Point pos) => SetCursorPos(pos.X, pos.Y);
//[CLink, CallingConvention(.Stdcall)]
//static extern int16 GetKeyState(int32 keycode);
[CLink, CallingConvention(.Stdcall)]
static extern IntBool GetCursorPos(out Point p);
[CLink, CallingConvention(.Stdcall)]
static extern IntBool SetCursorPos(c_int x, c_int y);
[CLink, CallingConvention(.Stdcall)]
static extern IntBool ScreenToClient(HWnd hWnd, ref Point p);
public override static void NewFrame()
+11
View File
@@ -288,6 +288,17 @@ namespace GlitchyEngine.Renderer
_sceneConstants.CompositionTarget = finalTarget;
}
public static void BeginScene(EditorCamera camera, RenderTarget2D finalTarget)
{
Debug.Profiler.ProfileRendererFunction!();
Matrix viewProjection = camera.Projection * camera.View;
_sceneConstants.ViewProjection = viewProjection;
_sceneConstants.CameraPosition = camera.Position;
_sceneConstants.CameraTarget = camera.RenderTarget;
_sceneConstants.CompositionTarget = finalTarget;
}
public static int SortMeshes(SubmittedMesh left, SubmittedMesh right)
{
// TODO: Once Material "inheritance" is ready we could perhaps check how similar materials are (e.g. shared textures/variables/etc...)
+42
View File
@@ -444,6 +444,48 @@ namespace GlitchyEngine.Renderer
s_drawOrder = drawOrder;
#if DEBUG
s_sceneRunning = true;
#endif
}
public static void BeginScene(EditorCamera camera, DrawOrder drawOrder = .SortByTexture, Effect effect = null, Effect circleEffect = null)
{
Debug.Profiler.ProfileRendererFunction!();
#if DEBUG
Log.EngineLogger.AssertDebug(s_initialized, "Renderer2D was not initialized.");
Log.EngineLogger.AssertDebug(!s_sceneRunning, "You have to call EndScene before you can make another call to BeginScene.");
#endif
//s_textureColorEffect.Bind(Renderer._context);
s_currentEffect?.ReleaseRef();
if(effect != null)
{
s_currentEffect = effect..AddRef();
}
else
{
s_currentEffect = s_batchEffect..AddRef();
}
s_currentCircleEffect?.ReleaseRef();
if(circleEffect != null)
{
s_currentCircleEffect = effect..AddRef();
}
else
{
s_currentCircleEffect = s_circleBatchEffect..AddRef();
}
Matrix viewProjection = camera.Projection * camera.View;
s_currentEffect.Variables["ViewProjection"].SetData(viewProjection);
s_currentCircleEffect.Variables["ViewProjection"].SetData(viewProjection);
s_drawOrder = drawOrder;
#if DEBUG
s_sceneRunning = true;
#endif
+328
View File
@@ -0,0 +1,328 @@
using GlitchyEngine;
using GlitchyEngine.Renderer;
using GlitchyEngine.Math;
using System;
using GlitchyEngine.Events;
namespace GlitchyEngine.World
{
struct EditorCamera : Camera, IDisposable
{
private Vector3 _position;
private Quaternion _rotation;
private Vector3 _focalPosition = .Zero;
private float _focalDistance = 5.0f;
private float _cameraTranslationSpeed = 2.0f;
private float _cameraRotationSpeedX = 0.001f;
private float _cameraRotationSpeedY = 0.001f;
private float _cameraFastFactor = 10f;
private Matrix _view;
private float _fovY;
private float _nearPlane;
private float _aspectRatio;
private RenderTarget2D _renderTarget = null;
internal bool BindMouse;
internal uint8 MouseCooldown;
private bool _isAltMode = false;
public Matrix View => _view;
public RenderTarget2D RenderTarget
{
get => _renderTarget;
set mut
{
if (_renderTarget == value)
return;
SetReference!(_renderTarget, value);
}
}
public Vector3 Position
{
get => _position;
set mut
{
if (_position == value)
return;
_position = value;
UpdateView();
}
}
public Quaternion Rotation
{
get => _rotation;
set mut
{
if (_rotation == value)
return;
_rotation = value;
UpdateView();
}
}
public Vector3 RotationEuler
{
get => Quaternion.ToEulerAngles(_rotation);
set mut
{
Quaternion quat = Quaternion.FromEulerAngles(value.Y, value.X, value.Z);
if (_rotation == quat)
return;
_rotation = quat;
UpdateView();
}
}
public (Vector3 Axis, float Angle) RotationAxisAngle
{
get => _rotation.ToAxisAngle();
set mut
{
Quaternion quat = Quaternion.FromAxisAngle(value.Axis, value.Angle);
if (_rotation == quat)
return;
_rotation = quat;
UpdateView();
}
}
public float FovY
{
get => _fovY;
set mut
{
if (_fovY == value)
return;
_fovY = value;
UpdateProjection();
}
}
public float NearPlane
{
get => _nearPlane;
set mut
{
if (_nearPlane == value)
return;
_nearPlane = value;
UpdateProjection();
}
}
public float AspectRatio
{
get => _aspectRatio;
set mut
{
if (_aspectRatio == value)
return;
_aspectRatio = value;
UpdateProjection();
}
}
public this(Vector3 position, Quaternion rotation, float fovY, float nearPlane, float aspectRatio)
{
_position = position;
_rotation = rotation;
_fovY = fovY;
_nearPlane = nearPlane;
_aspectRatio = aspectRatio;
UpdateView();
UpdateProjection();
}
public void Update(GameTime gameTime) mut
{
Debug.Profiler.ProfileFunction!();
BindMouse = false;
if (Input.IsKeyPressed(.Alt))
{
AltController(gameTime);
_isAltMode = true;
}
else
{
FirstPersonController(gameTime);
_isAltMode = false;
}
if (MouseCooldown != 0)
MouseCooldown--;
}
void FirstPersonController(GameTime gameTime) mut
{
if (!Input.IsMouseButtonPressed(.RightButton))
return;
BindMouse = true;
bool transformChanged = false;
Vector3 movement = .();
if(Input.IsKeyPressed(Key.W))
movement.Z += 1;
if(Input.IsKeyPressed(Key.S))
movement.Z -= 1;
if(Input.IsKeyPressed(Key.A))
movement.X -= 1;
if(Input.IsKeyPressed(Key.D))
movement.X += 1;
if(Input.IsKeyPressed(Key.Space))
movement.Y += 1;
if(Input.IsKeyPressed(Key.Control))
movement.Y -= 1;
if(movement != .Zero)
{
movement.Normalize();
if(Input.IsKeyPressed(Key.Shift))
movement *= _cameraFastFactor;
movement *= (float)(gameTime.DeltaTime) * _cameraTranslationSpeed;
Vector4 delta = Vector4(movement, 1.0f) * _view;
_position += delta.XYZ;
transformChanged = true;
}
// Camera rotation
var mouseDelta = Input.GetMouseMovement();
float rotY = mouseDelta.X * _cameraRotationSpeedX;
float rotX = mouseDelta.Y * _cameraRotationSpeedY;
if (MouseCooldown == 0 && rotY != 0 && rotX != 0)
{
Vector3 rotationEuler = RotationEuler + Vector3(rotX, rotY, 0);
_rotation = Quaternion.FromEulerAngles(rotationEuler.Y, rotationEuler.X, rotationEuler.Z);
transformChanged = true;
}
if (transformChanged)
UpdateView();
}
private float GetZoomSpeed()
{
float dist = _focalDistance * 0.2f;
dist = Math.Max(dist, 0.0f);
float speed = Math.Pow(dist, 1.5f);
speed = Math.Min(speed, 100.0f);
return speed;
}
void AltController(GameTime gameTime) mut
{
bool transformChanged = false;
BindMouse = Input.IsMouseButtonPressed(.LeftButton) || Input.IsMouseButtonPressed(.RightButton);
var mouseDelta = Input.GetMouseMovement();
if (MouseCooldown == 0 && Input.IsMouseButtonPressed(.LeftButton) && mouseDelta != .())
{
Vector2 movement = .(
-mouseDelta.X,
mouseDelta.Y);
movement *= (float)(gameTime.DeltaTime) * _cameraTranslationSpeed * GetZoomSpeed();
Vector4 delta = Vector4(movement, 0.0f, 1.0f) * _view;
_focalPosition += delta.XYZ;
transformChanged = true;
}
if (MouseCooldown == 0 && Input.IsMouseButtonPressed(.RightButton) && mouseDelta != .())
{
float rotY = mouseDelta.X * _cameraRotationSpeedX;
float rotX = mouseDelta.Y * _cameraRotationSpeedY;
Vector3 rotationEuler = RotationEuler + Vector3(rotX, rotY, 0);
_rotation = Quaternion.FromEulerAngles(rotationEuler.Y, rotationEuler.X, rotationEuler.Z);
transformChanged = true;
}
if (transformChanged)
UpdateView();
}
private void UpdateView() mut
{
Matrix viewRotation = Matrix.RotationQuaternion(Quaternion.Inverse(_rotation));
Vector4 offset = Vector4(0, 0, -_focalDistance, 1.0f) * viewRotation;
if (_isAltMode)
_position = _focalPosition + offset.XYZ;
else
_focalPosition = _position - offset.XYZ;
_view = viewRotation * Matrix.Translation(-_position);
//_view = (Matrix.Translation(_position) * Matrix.RotationQuaternion(_rotation)).Invert();
}
private void UpdateProjection() mut
{
_projection = Matrix.InfinitePerspectiveProjection(_fovY, _aspectRatio, _nearPlane);
}
public void OnViewportResize(uint32 sizeX, uint32 sizeY) mut
{
_aspectRatio = (float)sizeX / sizeY;
UpdateProjection();
}
public bool OnMouseScrolled(MouseScrolledEvent event) mut
{
if (_isAltMode)
{
_focalDistance = Math.Max(_focalDistance - GetZoomSpeed() * event.YOffset, 0.01f);
UpdateView();
return true;
}
return false;
}
public void Dispose()
{
_renderTarget?.ReleaseRef();
}
}
}
+41 -3
View File
@@ -48,8 +48,10 @@ namespace GlitchyEngine.World
{
}
public void Update(GameTime gameTime, RenderTarget2D finalTarget)
public void UpdateRuntime(GameTime gameTime, RenderTarget2D finalTarget)
{
Debug.Profiler.ProfileRendererFunction!();
TransformSystem.Update(_ecsWorld);
for (var (entity, script) in _ecsWorld.Enumerate<NativeScriptComponent>())
@@ -88,9 +90,9 @@ namespace GlitchyEngine.World
Renderer.Submit(mesh.Mesh, meshRenderer.Material, transform.WorldTransform);
}
for (var (entity, transform, camera) in _ecsWorld.Enumerate<TransformComponent, LightComponent>())
for (var (entity, transform, light) in _ecsWorld.Enumerate<TransformComponent, LightComponent>())
{
Renderer.Submit(camera.SceneLight, transform.WorldTransform);
Renderer.Submit(light.SceneLight, transform.WorldTransform);
}
Renderer.EndScene();
@@ -109,6 +111,42 @@ namespace GlitchyEngine.World
}
}
public void UpdateEditor(GameTime gameTime, EditorCamera camera, RenderTarget2D viewportTarget)
{
Debug.Profiler.ProfileRendererFunction!();
viewportTarget.AddRef();
TransformSystem.Update(_ecsWorld);
// 3D render
Renderer.BeginScene(camera, viewportTarget);
for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
{
Renderer.Submit(mesh.Mesh, meshRenderer.Material, transform.WorldTransform);
}
for (var (entity, transform, light) in _ecsWorld.Enumerate<TransformComponent, LightComponent>())
{
Renderer.Submit(light.SceneLight, transform.WorldTransform);
}
Renderer.EndScene();
// Sprite renderer
Renderer2D.BeginScene(camera);
for (var (entity, transform, sprite) in _ecsWorld.Enumerate<TransformComponent, SpriterRendererComponent>())
{
Renderer2D.DrawQuad(transform.WorldTransform, sprite.Sprite, sprite.Color);
}
Renderer2D.EndScene();
viewportTarget.ReleaseRef();
}
/// Creates a new Entity with the given name.
public Entity CreateEntity(String name = "")
{