diff --git a/SMCode/SM.Base/Drawing/DrawingBasis.cs b/SMCode/SM.Base/Drawing/DrawingBasis.cs index 8dd4796..a0f0ced 100644 --- a/SMCode/SM.Base/Drawing/DrawingBasis.cs +++ b/SMCode/SM.Base/Drawing/DrawingBasis.cs @@ -96,7 +96,7 @@ namespace SM.Base.Drawing { base.DrawContext(ref context); Transform.LastMaster = context.ModelMatrix; - context.ModelMatrix = Transform.MergeMatrix(context.ModelMatrix); + context.ModelMatrix = Transform.InWorldSpace; } } } \ No newline at end of file diff --git a/SMCode/SM.Base/Drawing/GenericTransformation.cs b/SMCode/SM.Base/Drawing/GenericTransformation.cs index 8cd032f..13a047b 100644 --- a/SMCode/SM.Base/Drawing/GenericTransformation.cs +++ b/SMCode/SM.Base/Drawing/GenericTransformation.cs @@ -18,6 +18,8 @@ namespace SM.Base.Drawing public Matrix4 LastMaster { get; internal set; } + public Matrix4 InWorldSpace => MergeMatrix(LastMaster); + /// /// Contains the current model matrix. /// diff --git a/SMCode/SM.Base/PostEffects/BloomEffect.cs b/SMCode/SM.Base/PostEffects/BloomEffect.cs index d4af620..7c638e2 100644 --- a/SMCode/SM.Base/PostEffects/BloomEffect.cs +++ b/SMCode/SM.Base/PostEffects/BloomEffect.cs @@ -15,7 +15,9 @@ namespace SM.Base.PostEffects { private static BezierCurve _defaultCurve = new BezierCurve(Vector2.UnitY, new Vector2(0.32f, 1), new Vector2(0.432f, 0), new Vector2(1,0)); - private const float _textureScale = .75f; + private const float _defaultTextureScale = .75f; + + private float _textureScale = .75f; private Framebuffer _bloomBuffer1; private Framebuffer _bloomBuffer2; @@ -56,10 +58,11 @@ namespace SM.Base.PostEffects public int WeightCurvePickAmount = 4; - public BloomEffect(Framebuffer source = null, bool hdr = false) + public BloomEffect(Framebuffer source = null, bool hdr = false, float? textureScale = null) { _source = source; _hdr = hdr; + _textureScale = textureScale.GetValueOrDefault(_defaultTextureScale); WeightCurve = _defaultCurve; } diff --git a/SMCode/SM.Base/SM.Base.csproj b/SMCode/SM.Base/SM.Base.csproj index b1f312b..6faa593 100644 --- a/SMCode/SM.Base/SM.Base.csproj +++ b/SMCode/SM.Base/SM.Base.csproj @@ -73,6 +73,7 @@ + @@ -116,6 +117,7 @@ + diff --git a/SMCode/SM.Base/Utility/Ray.cs b/SMCode/SM.Base/Utility/Ray.cs new file mode 100644 index 0000000..de3568c --- /dev/null +++ b/SMCode/SM.Base/Utility/Ray.cs @@ -0,0 +1,66 @@ +using System; +using System.Windows; +using OpenTK; +using SM.Base.Drawing; +using SM.Base.Scene; +using SM.OGL.Mesh; + +namespace SM.Utility +{ + public struct Ray + { + public Vector3 Position; + public Vector3 Direction; + + public Ray(Vector3 position, Vector3 direction) + { + Position = position; + Direction = direction.Normalized(); + } + + public bool ObjectIntersection(BoundingBox box, Matrix4 modelMatrix, out float distance) + { + distance = 0.0f; + float tMin = 0.0f; + float tMax = 100000.0f; + + Vector3 delta = modelMatrix.Row3.Xyz - Position; + + for (int i = 0; i < 3; i++) + { + Vector3 axis = new Vector3(modelMatrix[i, 0], modelMatrix[i, 1], modelMatrix[i, 2]); + + float e = Vector3.Dot(axis, delta); + float f = Vector3.Dot(Direction, axis); + + if (Math.Abs(f) > 0.001f) + { + + float t1 = (e + box.Min[i]) / f; + float t2 = (e + box.Max[i]) / f; + + if (t1 > t2) + { + float w = t1; + t1 = t2; + t2 = w; + } + + if (t2 < tMax) tMax = t2; + if (t1 > tMin) tMin = t1; + + if (tMax < tMin) + return false; + } + else + { + if (-e + box.Min[i] > 0.0f || -e + box.Max[i] < 0.0f) + return false; + } + } + + distance = tMin; + return true; + } + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Utility/Util.cs b/SMCode/SM.Base/Utility/Util.cs index eb1d275..f36121e 100644 --- a/SMCode/SM.Base/Utility/Util.cs +++ b/SMCode/SM.Base/Utility/Util.cs @@ -1,4 +1,6 @@ -namespace SM.Utility +using System; + +namespace SM.Utility { public class Util { @@ -11,5 +13,11 @@ } obj.Activate(); } + + public static void CallGarbageCollector() + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + } } } \ No newline at end of file diff --git a/SMCode/SM.Base/Window/GLWindow.cs b/SMCode/SM.Base/Window/GLWindow.cs index d50c183..6f2521a 100644 --- a/SMCode/SM.Base/Window/GLWindow.cs +++ b/SMCode/SM.Base/Window/GLWindow.cs @@ -1,4 +1,6 @@ using System; +using System.Windows; +using System.Windows.Forms; using OpenTK; using OpenTK.Graphics; using OpenTK.Input; @@ -11,6 +13,8 @@ namespace SM.Base.Windows { public class GLWindow : GameWindow, IGenericWindow { + private Vector2 _flagWindowSize; + public bool Loading { get; private set; } = true; public float AspectRatio { get; set; } @@ -30,12 +34,17 @@ namespace SM.Base.Windows public GenericScene CurrentScene { get; private set; } public RenderPipeline CurrentRenderPipeline { get; private set; } - public GLWindow() : this(1280, 720, "Generic OpenGL Title", GameWindowFlags.Default) {} + public WindowFlags WindowFlags; + + public GLWindow() : this(1280, 720, "Generic OpenGL Title", WindowFlags.Window) {} - public GLWindow(int width, int height, string title, GameWindowFlags flags, VSyncMode vSync = VSyncMode.On) : - base(width, height, default, title, flags, DisplayDevice.Default, GLSettings.ForcedVersion.MajorVersion, GLSettings.ForcedVersion.MinorVersion, GraphicsContextFlags.Default) + public GLWindow(int width, int height, string title, WindowFlags flags, VSyncMode vSync = VSyncMode.On) : + base(width, height, default, title, (GameWindowFlags)flags, DisplayDevice.Default, GLSettings.ForcedVersion.MajorVersion, GLSettings.ForcedVersion.MinorVersion, GraphicsContextFlags.Default) { VSync = vSync; + _flagWindowSize = new Vector2(width, height); + + ChangeWindowFlag(flags); } protected override void OnLoad(EventArgs e) @@ -52,6 +61,8 @@ namespace SM.Base.Windows WindowCode.Resize(this); + if (WindowFlags == WindowFlags.Window) _flagWindowSize = WindowSize; + if (Loading) { Loading = false; @@ -125,5 +136,40 @@ namespace SM.Base.Windows public void TriggerLoad() => Load?.Invoke(this); public void TriggerResize() => Resize?.Invoke(this); + + public void ChangeWindowFlag(WindowFlags newFlag) + { + WindowFlags = newFlag; + + switch (newFlag) + { + case WindowFlags.Window: + Width = (int)_flagWindowSize.X; + Height = (int)_flagWindowSize.Y; + + WindowBorder = WindowBorder.Resizable; + break; + case WindowFlags.BorderlessWindow: + WindowBorder = WindowBorder.Hidden; + + X = Screen.PrimaryScreen.Bounds.Left; + Y = Screen.PrimaryScreen.Bounds.Top; + Width = Screen.PrimaryScreen.Bounds.Width; + Height = Screen.PrimaryScreen.Bounds.Height; + + break; + case WindowFlags.ExclusiveFullscreen: + break; + default: + throw new ArgumentOutOfRangeException(nameof(newFlag), newFlag, null); + } + + if (newFlag == WindowFlags.BorderlessWindow) + { + WindowBorder = WindowBorder.Hidden; + X = Screen.PrimaryScreen.Bounds.X; + Y = Screen.PrimaryScreen.Bounds.Y; + } + } } } \ No newline at end of file diff --git a/SMCode/SM.Base/Window/WindowCode.cs b/SMCode/SM.Base/Window/WindowCode.cs index 69d87ac..a232672 100644 --- a/SMCode/SM.Base/Window/WindowCode.cs +++ b/SMCode/SM.Base/Window/WindowCode.cs @@ -94,6 +94,8 @@ namespace SM.Base.Windows SMRenderer.CurrentFrame++; + GLObject.DisposeMarkedObjects(); + Deltatime.RenderDelta = deltatime; var drawContext = new DrawContext() { diff --git a/SMCode/SM.Base/Window/WindowFlags.cs b/SMCode/SM.Base/Window/WindowFlags.cs new file mode 100644 index 0000000..93cf62a --- /dev/null +++ b/SMCode/SM.Base/Window/WindowFlags.cs @@ -0,0 +1,9 @@ +namespace SM.Base.Windows +{ + public enum WindowFlags + { + Window = 0, + BorderlessWindow = 2, + ExclusiveFullscreen = 1 + } +} \ No newline at end of file diff --git a/SMCode/SM.OGL/Framebuffer/Framebuffer.cs b/SMCode/SM.OGL/Framebuffer/Framebuffer.cs index 1bb426e..0c7e364 100644 --- a/SMCode/SM.OGL/Framebuffer/Framebuffer.cs +++ b/SMCode/SM.OGL/Framebuffer/Framebuffer.cs @@ -116,9 +116,11 @@ namespace SM.OGL.Framebuffer /// public override void Dispose() { - base.Dispose(); + foreach (var attachment in ColorAttachments.Values) attachment.Dispose(); GL.DeleteFramebuffer(this); + base.Dispose(); + } /// @@ -180,6 +182,7 @@ namespace SM.OGL.Framebuffer Framebuffer buffer = new Framebuffer() { _canBeCompiled = false, + ReportAsNotCompiled = true }; switch (target) { diff --git a/SMCode/SM.OGL/GLObject.cs b/SMCode/SM.OGL/GLObject.cs index 64a4903..0afaf59 100644 --- a/SMCode/SM.OGL/GLObject.cs +++ b/SMCode/SM.OGL/GLObject.cs @@ -1,6 +1,9 @@ #region usings +using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.InteropServices; using OpenTK.Graphics.OpenGL4; #endregion @@ -12,11 +15,15 @@ namespace SM.OGL /// public abstract class GLObject { + private static List _disposableObjects = new List(); + + protected bool ReportAsNotCompiled; + /// /// Contains the OpenGL ID /// protected int _id = -1; - + /// /// If true, the system will call "Compile()", when "ID" is tried to get, but the id is still -1. /// @@ -25,7 +32,7 @@ namespace SM.OGL /// /// Checks if the object was compiled. /// - public bool WasCompiled => _id > 0; + public bool WasCompiled => _id > 0 && !ReportAsNotCompiled; /// /// Returns the id for this object. @@ -64,7 +71,7 @@ namespace SM.OGL /// public virtual void Dispose() { - + _id = -1; } /// @@ -87,6 +94,15 @@ namespace SM.OGL if (GLSystem.Debugging) GL.ObjectLabel(TypeIdentifier, _id, name.Length, name); } + public static void DisposeMarkedObjects() + { + foreach (GLObject o in _disposableObjects) + { + o.Dispose(); + } + _disposableObjects.Clear(); + } + /// /// Returns the ID for the object. /// @@ -95,5 +111,10 @@ namespace SM.OGL { return glo.ID; } + + ~GLObject() + { + if (WasCompiled) _disposableObjects.Add(this); + } } } \ No newline at end of file diff --git a/SMCode/SM.OGL/Mesh/BoundingBox.cs b/SMCode/SM.OGL/Mesh/BoundingBox.cs index d5b97f4..36c9de3 100644 --- a/SMCode/SM.OGL/Mesh/BoundingBox.cs +++ b/SMCode/SM.OGL/Mesh/BoundingBox.cs @@ -65,6 +65,21 @@ namespace SM.OGL.Mesh public Vector3 Get(Matrix4 transformation, bool xyz) => Get(transformation, xyz, xyz, xyz); + public void GetBounds(Matrix4 transformation, out Vector3 min, out Vector3 max) + { + min = Get(transformation, false); + max = Get(transformation, true); + + for (int i = 0; i < 3; i++) + { + float newmin = Math.Min(min[i], max[i]); + float newmax = Math.Max(min[i], max[i]); + + min[i] = newmin; + max[i] = newmax; + } + } + public void Update(GenericMesh mesh) { int pos = 0; diff --git a/SMCode/SM.OGL/Mesh/GenericMesh.cs b/SMCode/SM.OGL/Mesh/GenericMesh.cs index 99948c8..6f35434 100644 --- a/SMCode/SM.OGL/Mesh/GenericMesh.cs +++ b/SMCode/SM.OGL/Mesh/GenericMesh.cs @@ -99,5 +99,11 @@ namespace SM.OGL.Mesh GL.BindVertexArray(0); } + + public override void Dispose() + { + GL.DeleteVertexArray(_id); + base.Dispose(); + } } } \ No newline at end of file diff --git a/SMCode/SM.OGL/Shaders/GenericShader.cs b/SMCode/SM.OGL/Shaders/GenericShader.cs index d0b6cf2..948f630 100644 --- a/SMCode/SM.OGL/Shaders/GenericShader.cs +++ b/SMCode/SM.OGL/Shaders/GenericShader.cs @@ -119,7 +119,8 @@ namespace SM.OGL.Shaders public override void Dispose() { - GL.DeleteShader(this); + GL.DeleteProgram(this); + base.Dispose(); } /// diff --git a/SMCode/SM.OGL/Shaders/ShaderFile.cs b/SMCode/SM.OGL/Shaders/ShaderFile.cs index d649094..6f10cde 100644 --- a/SMCode/SM.OGL/Shaders/ShaderFile.cs +++ b/SMCode/SM.OGL/Shaders/ShaderFile.cs @@ -79,5 +79,12 @@ namespace SM.OGL.Shaders for (var i = 0; i < GLSLExtensions.Count; i++) GLSLExtensions[i].Compile(shader, type); } + + public override void Dispose() + { + GL.DeleteShader(this); + + base.Dispose(); + } } } \ No newline at end of file diff --git a/SMCode/SM.OGL/Texture/TextureBase.cs b/SMCode/SM.OGL/Texture/TextureBase.cs index 2f0a107..815b298 100644 --- a/SMCode/SM.OGL/Texture/TextureBase.cs +++ b/SMCode/SM.OGL/Texture/TextureBase.cs @@ -46,8 +46,8 @@ namespace SM.OGL.Texture public override void Dispose() { - base.Dispose(); GL.DeleteTexture(_id); + base.Dispose(); } } } \ No newline at end of file diff --git a/SMCode/SM2D/Controls/Mouse2D.cs b/SMCode/SM2D/Controls/Mouse2D.cs index 5c95095..4af280a 100644 --- a/SMCode/SM2D/Controls/Mouse2D.cs +++ b/SMCode/SM2D/Controls/Mouse2D.cs @@ -1,8 +1,10 @@ using System.Collections.Generic; +using System.Windows.Controls; using OpenTK; using SM.Base.Controls; using SM.Base.Drawing; using SM.Base.Scene; +using SM.Utility; using SM2D.Scene; using SM2D.Types; @@ -43,21 +45,30 @@ namespace SM2D.Controls where TObject : IModelItem, ITransformItem { clickedObj = default; + bool success = false; - foreach (TObject obj in checkingObjects) + float distance = -10; + + foreach (TObject item in checkingObjects) { - Vector3 min = obj.Mesh.BoundingBox.Get(obj.Transform.MergeMatrix(obj.Transform.LastMaster), false); - Vector3 max = obj.Mesh.BoundingBox.Get(obj.Transform.MergeMatrix(obj.Transform.LastMaster), true); + Matrix4 worldPos = item.Transform.InWorldSpace; + item.Mesh.BoundingBox.GetBounds(worldPos, out Vector3 min, out Vector3 max); if (mousePos.X > min.X && mousePos.X < max.X && mousePos.Y > min.Y && mousePos.Y < max.Y) { - clickedObj = obj; - return true; + // if z is greater than distance + if (worldPos[3, 2] > distance) + { + clickedObj = item; + distance = worldPos[3, 2]; + } + + success = true; } } - return false; + return success; } } } \ No newline at end of file diff --git a/SMCode/SM2D/Scene/Camera.cs b/SMCode/SM2D/Scene/Camera.cs index f042af5..b66619b 100644 --- a/SMCode/SM2D/Scene/Camera.cs +++ b/SMCode/SM2D/Scene/Camera.cs @@ -1,6 +1,7 @@ #region usings using System; +using System.Runtime.Serialization.Formatters; using OpenTK; using SM.Base; using SM.Base.Scene; @@ -14,6 +15,7 @@ namespace SM2D.Scene public class Camera : GenericCamera { internal static int ResizeCounter = 0; + internal static float Distance = 2F; private int _resizeCounter = 0; private bool _updateWorldScale = false; @@ -38,7 +40,7 @@ namespace SM2D.Scene protected override Matrix4 ViewCalculation(IGenericWindow window) { - return Matrix4.LookAt(Position.X, Position.Y, 2f, Position.X, Position.Y, 0f, 0, 1, 0); + return Matrix4.LookAt(Position.X, Position.Y, Distance, Position.X, Position.Y, 0f, 0, 1, 0); } protected override bool WorldCalculation(IGenericWindow window, out Matrix4 world)