Better Transform component and edit gui

This commit is contained in:
Simon Lübeß
2022-04-09 12:35:36 +02:00
parent c7fde476e8
commit af37154071
18 changed files with 341 additions and 208 deletions
+10
View File
@@ -3,6 +3,7 @@ using GlitchyEngine.Events;
using GlitchyEngine.ImGui;
using GlitchyEngine.Renderer;
using GlitchyEngine.Debug;
using GlitchyEngine.Content;
namespace GlitchyEngine
{
@@ -24,12 +25,16 @@ namespace GlitchyEngine
#endif
private GameTime _gameTime;
private IContentManager _contentManager;
public bool IsRunning => _running;
public Window Window => _window;
public EffectLibrary EffectLibrary => _effectLibrary;
public IContentManager ContentManager => _contentManager;
public bool IsMinimized => _isMinimized;
[Inline]
@@ -51,6 +56,8 @@ namespace GlitchyEngine
_rendererApi = new RendererAPI();
_rendererApi.Context = _window.Context;
_contentManager = new ContentManager("./content");
SamplerStateManager.Init();
RenderCommand.RendererAPI = _rendererApi;
@@ -73,6 +80,9 @@ namespace GlitchyEngine
Renderer.Deinit();
delete _effectLibrary;
delete _contentManager;
delete _rendererApi;
delete _window;
@@ -1,5 +1,6 @@
using GlitchyEngine.Math;
using GlitchyEngine.Renderer;
using System;
namespace ImGui
{
@@ -21,6 +22,10 @@ namespace ImGui
// Wouldn't be necesseary if RenderTarget2D was Texture2D
public static extern void Image(RenderTarget2D texture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero);
public static void TextUnformatted(StringView text) => TextUnformattedImpl(text.Ptr, text.Ptr + text.Length);
public static void PushID(StringView id) => PushID(id.Ptr, id.Ptr + id.Length);
/// Releases references that accumulated calls like ImGui::Image
protected internal static extern void CleanupFrame();
+2 -2
View File
@@ -18,10 +18,10 @@ namespace GlitchyEngine.Math
public const float PiOverFour = 0.785398163f;
/// Converts radians to degrees
const float RadToDeg = 180.0f / Pi;
public const float RadToDeg = 180.0f / Pi;
/// Converts radians to degrees
const float DegToRad = Pi / 180.0f;
public const float DegToRad = Pi / 180.0f;
// Converts the given radians to degrees
public static float ToDegrees(float radians)
+43 -13
View File
@@ -314,35 +314,65 @@ namespace GlitchyEngine.Math
return result;
}
public static Vector3 ToEulerAngles(Quaternion q1)
public static Vector3 ToEulerAngles(Quaternion q)
{
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/
Vector3 result;
float sqw = q1.W*q1.W;
float sqx = q1.X*q1.X;
float sqy = q1.Y*q1.Y;
float sqz = q1.Z*q1.Z;
float sqw = q.W*q.W;
float sqx = q.X*q.X;
float sqy = q.Y*q.Y;
float sqz = q.Z*q.Z;
float unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
float test = q1.X*q1.Y + q1.Z*q1.W;
if (test > 0.499f*unit) { // singularity at north pole
result.Y = 2.0f * Math.Atan2(q1.X,q1.W);
float test = q.X*q.Y + q.Z*q.W;
if (test > 0.4999f*unit) { // singularity at north pole
result.Y = 2.0f * Math.Atan2(q.X,q.W);
result.Z = Math.PI_f / 2.0f;
result.X = 0.0f;
return result;
}
if (test < -0.499f*unit) { // singularity at south pole
result.Y = -2.0f * Math.Atan2(q1.X,q1.W);
if (test < -0.4999f*unit) { // singularity at south pole
result.Y = -2.0f * Math.Atan2(q.X,q.W);
result.Z = -Math.PI_f / 2.0f;
result.X = 0.0f;
return result;
}
result.Y = Math.Atan2(2*q1.Y*q1.W-2*q1.X*q1.Z , sqx - sqy - sqz + sqw);
result.Y = Math.Atan2(2*q.Y*q.W-2*q.X*q.Z , sqx - sqy - sqz + sqw);
result.Z = Math.Asin(2*test/unit);
result.X = Math.Atan2(2*q1.X*q1.W-2*q1.Y*q1.Z , -sqx + sqy - sqz + sqw);
result.X = Math.Atan2(2*q.X*q.W-2*q.Y*q.Z , -sqx + sqy - sqz + sqw);
return result;
//return .(q.Pitch(), q.Yaw(), q.Roll());
}
/*
public float Pitch()
{
float y = 2.0f * (Y * Z + W * X);
float x = W * W - X * X - Y * Y + Z * Z;
if (Vector2(x, y).Equals(.Zero)) //avoid atan2(0,0) - handle singularity - Matiis
return 2.0f * Math.Atan2(X, W);
return Math.Atan2(y, x);
}
public float Yaw()
{
return Math.Asin(Math.Clamp(-2.0f * (X * Z - W * Y), -1.0f, 1.0f));
}
public float Roll()
{
float y = 2.0f * (X * Y + W * Z);
float x = W * W + X * X - Y * Y - Z * Z;
if (Vector2(x, y).Equals(.Zero)) //avoid atan2(0,0) - handle singularity - Matiis
return 0;
return Math.Atan2(y, x);
}
*/
}
}
+5
View File
@@ -284,5 +284,10 @@ namespace GlitchyEngine.Math
[Inline]
public static explicit operator Self(float value) => Self(value);
public bool Equals(Vector2 v, float epsilon = Math.[Friend]sMachineEpsilonFloat)
{
return (Math.Abs(v.X - X) < epsilon) && (Math.Abs(v.Y - Y) < epsilon);
}
}
}
+10 -21
View File
@@ -13,36 +13,25 @@ namespace GlitchyEngine.World
}
}
struct SimpleTransformComponent
{
public EcsEntity Parent = .InvalidEntity;
public Matrix Transform = Matrix.Identity;
public this()
{
}
public this(Matrix transform)
{
Transform = transform;
}
}
struct SpriterRendererComponent
struct SpriterRendererComponent : IDisposableComponent
{
public Texture2D Sprite = null;
public ColorRGBA Color = .White;
public this()
{
}
public this(ColorRGBA color)
{
Color = color;
}
public void Dispose()
{
Sprite?.ReleaseRef();
}
}
struct SceneCamera : Camera
@@ -229,7 +218,7 @@ namespace GlitchyEngine.World
private void CalculateProjection() mut
{
if (_projectionType case .Orthographic)//(let nearPlane, let farPlane, let projectionHeight))
if (_projectionType case .Orthographic)
{
float halfHeight = _orthographicHeight / 2.0f;
float halfWidth = halfHeight * _aspectRatio;
@@ -237,11 +226,11 @@ namespace GlitchyEngine.World
_projection = Matrix.OrthographicProjectionOffCenter(-halfWidth, halfWidth, halfHeight, -halfHeight,
_orthographicNearPlane, _orthographicFarPlane);
}
else if (_projectionType case .Perspective)//(let nearPlane, let farPlane, let fovY))
else if (_projectionType case .Perspective)
{
_projection = Matrix.PerspectiveProjection(_perspectiveFovY, _aspectRatio, _perspectiveNearPlane, _perspectiveFarPlane);
}
else if (_projectionType case .InfinitePerspective)//(let nearPlane, let fovY))
else if (_projectionType case .InfinitePerspective)
{
_projection = Matrix.InfinitePerspectiveProjection(_perspectiveFovY, _aspectRatio, _perspectiveNearPlane);
}
+12 -9
View File
@@ -16,7 +16,10 @@ namespace GlitchyEngine.World
entity.AddComponent<SpriterRendererComponent>(.(ColorRGBA(0.2f, 0.9f, 0.15f)));
Entity entity2 = CreateEntity("Red Square");
entity2.AddComponent<SpriterRendererComponent>(.(ColorRGBA(0.95f, 0.1f, 0.3f)));
var v = entity2.AddComponent<SpriterRendererComponent>(.(ColorRGBA(0.95f, 0.1f, 0.3f)));
v.Sprite = new Texture2D("Textures/rocket.png");
v.Sprite.SamplerState = SamplerStateManager.PointClamp;
}
public ~this()
@@ -25,7 +28,7 @@ namespace GlitchyEngine.World
public void Update(GameTime gameTime)
{
//TransformSystem.Update(_ecsWorld);
TransformSystem.Update(_ecsWorld);
for (var (entity, script) in _ecsWorld.Enumerate<NativeScriptComponent>())
{
@@ -40,25 +43,25 @@ namespace GlitchyEngine.World
}
Camera* primaryCamera = null;
Matrix* primaryCameraTransform = null;
Matrix primaryCameraTransform = default;
for (var (entity, transform, camera) in _ecsWorld.Enumerate<SimpleTransformComponent, CameraComponent>())
for (var (entity, transform, camera) in _ecsWorld.Enumerate<TransformComponent, CameraComponent>())
{
if (camera.Primary)
{
primaryCamera = &camera.Camera;
primaryCameraTransform = &transform.Transform;
primaryCameraTransform = transform.WorldTransform;
}
}
// Sprite renderer
if (primaryCamera != null)
{
Renderer2D.BeginScene(*primaryCamera, *primaryCameraTransform);
Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform);
for (var (entity, transform, sprite) in _ecsWorld.Enumerate<SimpleTransformComponent, SpriterRendererComponent>())
for (var (entity, transform, sprite) in _ecsWorld.Enumerate<TransformComponent, SpriterRendererComponent>())
{
Renderer2D.DrawQuad(transform.Transform, sprite.Color);
Renderer2D.DrawQuad(transform.WorldTransform, sprite.Sprite, sprite.Color);
}
Renderer2D.EndScene();
@@ -68,7 +71,7 @@ namespace GlitchyEngine.World
public Entity CreateEntity(String name = "")
{
Entity entity = Entity(_ecsWorld.NewEntity(), this);
entity.AddComponent<SimpleTransformComponent>(.(.Identity));
entity.AddComponent<TransformComponent>();
let nameComponent = entity.AddComponent<DebugNameComponent>();
nameComponent.SetName(name.IsEmpty ? "Entity" : name);
@@ -4,6 +4,8 @@ namespace GlitchyEngine.World
{
internal Entity _entity;
protected TransformComponent* transform => GetComponent<TransformComponent>();
public T* AddComponent<T>(T value = T()) where T: struct, new
{
return _entity.AddComponent<T>(value);
+39 -13
View File
@@ -4,9 +4,13 @@ namespace GlitchyEngine.World
{
public struct TransformComponent
{
Vector3 _position = .Zero;
Quaternion _rotation = .Identity;
Vector3 _scale = .One;
EcsEntity _parent = .InvalidEntity;
Vector3 _position = .(0, 0, 0);
Quaternion _rotation = .(0, 0, 0, 1);
Vector3 _scale = .(1, 1, 1);
Vector3 _editorRotationEuler = .Zero;
Matrix _localTransform = .Identity;
public bool IsDirty = false;
@@ -16,6 +20,19 @@ namespace GlitchyEngine.World
/// The frame when the transform was recalculated
public uint Frame;
public EcsEntity Parent
{
get => _parent;
set mut
{
if (_parent == value)
return;
_parent = value;
IsDirty = true;
}
}
public Matrix LocalTransform
{
get => _localTransform;
@@ -55,6 +72,24 @@ namespace GlitchyEngine.World
_rotation = value;
IsDirty = true;
_editorRotationEuler = Quaternion.ToEulerAngles(_rotation);
}
}
/// Allows the user to edit the euler angles in the editor without rotations getting funky because of singularities or ambiguity of angles.
internal Vector3 EditorRotationEuler
{
get => _editorRotationEuler;
set mut
{
if (_editorRotationEuler == value)
return;
_editorRotationEuler = value;
_rotation = Quaternion.FromEulerAngles(_editorRotationEuler.Y, _editorRotationEuler.X, _editorRotationEuler.Z);
IsDirty = true;
}
}
@@ -65,16 +100,7 @@ namespace GlitchyEngine.World
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;
IsDirty = true;
}
set mut => Rotation = Quaternion.FromEulerAngles(value.Y, value.X, value.Z);
}
/**
+5 -7
View File
@@ -26,7 +26,7 @@ namespace GlitchyEngine.World
transform.Frame = _frame;
var parent = world.GetComponent<ParentComponent>(entity);
//var parent = world.GetComponent<ParentComponent>(entity);
if(transform.IsDirty)
{
@@ -35,18 +35,16 @@ namespace GlitchyEngine.World
transform.IsDirty = false;
if(parent == null)
if(transform.Parent == EcsEntity.InvalidEntity)
{
transform.WorldTransform = transform.LocalTransform;
}
}
if(parent != null)
if(transform.Parent != EcsEntity.InvalidEntity)
{
var parentEntity = parent.Entity;
var parentTransform = world.GetComponent<TransformComponent>(parentEntity);
UpdateEntity(parentEntity, parentTransform, world);
var parentTransform = world.GetComponent<TransformComponent>(transform.Parent);
UpdateEntity(transform.Parent, parentTransform, world);
// TODO: I think we unnecessarily recalculate world transform every frame
// Parent transform is newer than our transform or was updated this frame