From 184480243f16b24ebf11a35b60be01c71277c5f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Fri, 24 Mar 2023 19:13:32 +0100 Subject: [PATCH] Collider rendering --- GlitchyEditor/src/EditorLayer.bf | 15 +- GlitchyEngine/src/Math/MathDefs.bf | 1 - GlitchyEngine/src/Math/Matrix.bf | 877 ++++++++++++++++++++ GlitchyEngine/src/Math/MatrixExtension.bf | 89 -- GlitchyEngine/src/Math/Quaternion.bf | 2 +- GlitchyEngine/src/Renderer/DebugRenderer.bf | 22 +- GlitchyEngine/src/World/Scene.bf | 22 +- 7 files changed, 922 insertions(+), 106 deletions(-) create mode 100644 GlitchyEngine/src/Math/Matrix.bf delete mode 100644 GlitchyEngine/src/Math/MatrixExtension.bf diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index ee89ab6..33bc16d 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -231,7 +231,7 @@ namespace GlitchyEditor return Math.Clamp(1.5f - Vector3.Distance(_editor.CurrentCamera.Position, pos) / 50, 0, 1); } - for (var (entity, transform, camera) in _activeScene.[Friend]_ecsWorld.Enumerate()) + for (var (entity, transform, camera) in _activeScene.GetEntities()) { if (_editor.EntityHierarchyWindow.SelectedEntities.Contains(.(entity, _activeScene))) { @@ -245,7 +245,7 @@ namespace GlitchyEditor //Renderer2D.DrawQuad(world, _iconCamera, .White, .(0, 0, 1, 1), entity.Index); } - for (var (entity, transform, light) in _activeScene.[Friend]_ecsWorld.Enumerate()) + for (var (entity, transform, light) in _activeScene.GetEntities()) { if (_editor.EntityHierarchyWindow.SelectedEntities.Contains(.(entity, _activeScene))) { @@ -263,7 +263,16 @@ namespace GlitchyEditor float alpha = CalculateAlpha(transform.WorldTransform.Translation); Renderer2D.DrawQuad(world, _editorIcons.DirectionalLight, ColorRGBA(light.SceneLight.Color.R * alpha, light.SceneLight.Color.G * alpha, light.SceneLight.Color.B * alpha, alpha), .(0, 0, 1, 1), entity.Index); - //Renderer2D.DrawQuad(world, _iconDirectionalLight, ColorRGBA(light.SceneLight.Color, alpha), .(0, 0, 1, 1), entity.Index); + } + + for (var (entity, transform, collider) in _activeScene.GetEntities()) + { + Renderer2D.DrawRect(transform.WorldTransform * Matrix.Translation(collider.Offset.X, collider.Offset.Y, 0) * Matrix.Scaling(collider.Size.X * 2, collider.Size.Y * 2, 0)); + } + + for (var (entity, transform, collider) in _activeScene.GetEntities()) + { + Renderer2D.DrawCircle(transform.WorldTransform * Matrix.Translation(collider.Offset.X, collider.Offset.Y, 0) * Matrix.Scaling(collider.Radius * 2), (Texture2D)null, ColorRGBA(0f, 1f, 0f), 0.01f); } } diff --git a/GlitchyEngine/src/Math/MathDefs.bf b/GlitchyEngine/src/Math/MathDefs.bf index 5afe42a..0c66dfa 100644 --- a/GlitchyEngine/src/Math/MathDefs.bf +++ b/GlitchyEngine/src/Math/MathDefs.bf @@ -4,5 +4,4 @@ namespace GlitchyEngine.Math { typealias Matrix3x3 = DirectX.Math.Matrix3x3; typealias Matrix4x3 = DirectX.Math.Matrix4x3; - typealias Matrix = DirectX.Math.Matrix; } diff --git a/GlitchyEngine/src/Math/Matrix.bf b/GlitchyEngine/src/Math/Matrix.bf new file mode 100644 index 0000000..ff6ca60 --- /dev/null +++ b/GlitchyEngine/src/Math/Matrix.bf @@ -0,0 +1,877 @@ +using System; + +namespace GlitchyEngine.Math; + +/** + * Represents a 4 by 4 column-major matrix. + */ +[Union] +public struct Matrix +{ + public struct Values + { + public float _11, _21, _31, _41, + _12, _22, _32, _42, + _13, _23, _33, _43, + _14, _24, _34, _44; + } + + public const Matrix Zero = .(); + public const Matrix Identity = .(.UnitX, .UnitY, .UnitZ, .UnitW); + + public using Values V; + public float[4][4] Values; + public Vector4[4] Columns; + + /// Creates a new zero-matrix. + public this() => this = default; + + /** + * Initializes a new Matrix. + * @param value The value that will be assigned to all components. + */ + /// Creates a new matrix. + public this(float value) + { + this = ?; + _11 = _12 = _13 = _14 = + _21 = _22 = _23 = _24 = + _31 = _32 = _33 = _34 = + _41 = _42 = _43 = _44 = value; + } + + /// Creates a new matrix and initializes it with the given entries. + public this(float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) + { + Values[0][0] = m00; Values[0][1] = m10; Values[0][2] = m20; Values[0][3] = m30; + Values[1][0] = m01; Values[1][1] = m11; Values[1][2] = m21; Values[1][3] = m31; + Values[2][0] = m02; Values[2][1] = m12; Values[2][2] = m22; Values[2][3] = m32; + Values[3][0] = m03; Values[3][1] = m13; Values[3][2] = m23; Values[3][3] = m33; + } + + /// Creates a new matrix and initializes it with the given column-vectors. + public this(Vector4 c0, Vector4 c1, Vector4 c2, Vector4 c3) + { + Columns[0] = c0; + Columns[1] = c1; + Columns[2] = c2; + Columns[3] = c3; + } + + public ref Vector3 Right + { + [Inline] + get + { +#unwarn + return ref *(Vector3*)&Columns[0]; + } + } + + public ref Vector3 Up + { + [Inline] + get + { +#unwarn + return ref *(Vector3*)&Columns[1]; + } + } + + public ref Vector3 Forward + { + [Inline] + get + { +#unwarn + return ref *(Vector3*)&Columns[2]; + } + } + + public ref Vector3 Translation + { + [Inline] + get + { +#unwarn + return ref *(Vector3*)&Columns[3]; + } + } + + public Vector3 Scale + { + [Inline] + get => .(_11, _22, _33); + + [Inline] + set mut + { + _11 = value.X; + _22 = value.Y; + _33 = value.Z; + } + } + + public ref float this[int row, int column] + { + get + { +#unwarn + return ref *(float*)&Values[column][row]; + } + + [Checked] + get + { + if(column < 0 || column > 3 || row < 0 || row > 3) + Internal.ThrowIndexOutOfRange(); + +#unwarn + return ref *(float*)&Values[column][row]; + } + } + + public ref Vector4 this[int column] + { + get + { +#unwarn + return ref *(Vector4*)&Columns[column]; + } + + + [Checked] + get + { + if(column < 0 || column > 3) + Internal.ThrowIndexOutOfRange(); + +#unwarn + return ref *(Vector4*)&Columns[column]; + } + } + + // + // Assignment Operators + // + + // Addition + + public void operator +=(Matrix value) mut + { + Columns[0] += value.Columns[0]; + Columns[1] += value.Columns[1]; + Columns[2] += value.Columns[2]; + Columns[3] += value.Columns[3]; + } + + // Matrix + Scalar : Matrix + Scalar * Identity + public void operator +=(float scalar) mut + { + _11 += scalar; + _22 += scalar; + _33 += scalar; + _44 += scalar; + } + + // Subtraction + + public void operator -=(Matrix value) mut + { + Columns[0] -= value.Columns[0]; + Columns[1] -= value.Columns[1]; + Columns[2] -= value.Columns[2]; + Columns[3] -= value.Columns[3]; + } + + // Matrix - Scalar : Matrix - Scalar * Identity + public void operator -=(float scalar) mut + { + _11 -= scalar; + _22 -= scalar; + _33 -= scalar; + _44 -= scalar; + } + + // Multiplication + + public void operator *=(float scalar) mut + { + Columns[0] *= scalar; + Columns[1] *= scalar; + Columns[2] *= scalar; + Columns[3] *= scalar; + } + + public void operator *=(Matrix value) mut + { + this = this * value; + } + + // Divide + + public void operator /=(float scalar) mut + { + float inv = 1.0f / scalar; + Columns[0] *= inv; + Columns[1] *= inv; + Columns[2] *= inv; + Columns[3] *= inv; + } + + // + // Operators + // + + // Addition + + public static Matrix operator +(Matrix left, Matrix right) + { + return .(left.Columns[0] + right.Columns[0], + left.Columns[1] + right.Columns[1], + left.Columns[2] + right.Columns[2], + left.Columns[3] + right.Columns[3]); + } + + public static Matrix operator +(Matrix left, float right) + { + Matrix result = left; + result._11 += right; + result._22 += right; + result._33 += right; + result._44 += right; + + return result; + } + + public static Matrix operator +(float left, Matrix right) + { + Matrix result = right; + result._11 += left; + result._22 += left; + result._33 += left; + result._44 += left; + + return result; + } + + // Subtraction + + public static Matrix operator -(Matrix left, Matrix right) + { + return .(left.Columns[0] - right.Columns[0], + left.Columns[1] - right.Columns[1], + left.Columns[2] - right.Columns[2], + left.Columns[3] - right.Columns[3]); + } + + public static Matrix operator -(Matrix value, float scalar) + { + Matrix result = value; + result._11 -= scalar; + result._22 -= scalar; + result._33 -= scalar; + result._44 -= scalar; + + return result; + } + + public static Matrix operator -(float scalar, Matrix value) + { + Matrix result = value; + result._11 -= scalar; + result._22 -= scalar; + result._33 -= scalar; + result._44 -= scalar; + + return result; + } + + public static Matrix operator -(Matrix value) + { + return .(-value.Columns[0], + -value.Columns[1], + -value.Columns[2], + -value.Columns[3]); + } + + // Multiplication + + public static Matrix operator *(Matrix left, Matrix right) + { +#unwarn + var l = &left.V; +#unwarn + var r = &right.V; + + Matrix result = ?; + + result._11 = (l._11 * r._11) + (l._12 * r._21) + (l._13 * r._31) + (l._14 * r._41); + result._12 = (l._11 * r._12) + (l._12 * r._22) + (l._13 * r._32) + (l._14 * r._42); + result._13 = (l._11 * r._13) + (l._12 * r._23) + (l._13 * r._33) + (l._14 * r._43); + result._14 = (l._11 * r._14) + (l._12 * r._24) + (l._13 * r._34) + (l._14 * r._44); + + result._21 = (l._21 * r._11) + (l._22 * r._21) + (l._23 * r._31) + (l._24 * r._41); + result._22 = (l._21 * r._12) + (l._22 * r._22) + (l._23 * r._32) + (l._24 * r._42); + result._23 = (l._21 * r._13) + (l._22 * r._23) + (l._23 * r._33) + (l._24 * r._43); + result._24 = (l._21 * r._14) + (l._22 * r._24) + (l._23 * r._34) + (l._24 * r._44); + + result._31 = (l._31 * r._11) + (l._32 * r._21) + (l._33 * r._31) + (l._34 * r._41); + result._32 = (l._31 * r._12) + (l._32 * r._22) + (l._33 * r._32) + (l._34 * r._42); + result._33 = (l._31 * r._13) + (l._32 * r._23) + (l._33 * r._33) + (l._34 * r._43); + result._34 = (l._31 * r._14) + (l._32 * r._24) + (l._33 * r._34) + (l._34 * r._44); + + result._41 = (l._41 * r._11) + (l._42 * r._21) + (l._43 * r._31) + (l._44 * r._41); + result._42 = (l._41 * r._12) + (l._42 * r._22) + (l._43 * r._32) + (l._44 * r._42); + result._43 = (l._41 * r._13) + (l._42 * r._23) + (l._43 * r._33) + (l._44 * r._43); + result._44 = (l._41 * r._14) + (l._42 * r._24) + (l._43 * r._34) + (l._44 * r._44); + + return result; + } + + public static Matrix operator *(Matrix value, float scalar) + { + return .(value.Columns[0] * scalar, + value.Columns[1] * scalar, + value.Columns[2] * scalar, + value.Columns[3] * scalar); + } + + public static Matrix operator *(float scalar, Matrix value) + { + return .(value.Columns[0] * scalar, + value.Columns[1] * scalar, + value.Columns[2] * scalar, + value.Columns[3] * scalar); + } + + /** + * Multiplies a matrix and a column-vector resulting in a column vector. + */ + public static Vector4 operator *(Matrix matrix, Vector4 columnVector) + { +#unwarn + var m = &matrix.V; + + Vector4 result = ?; + result.X = (m._11 * columnVector.X) + (m._12 * columnVector.Y) + (m._13 * columnVector.Z) + (m._14 * columnVector.W); + result.Y = (m._21 * columnVector.X) + (m._22 * columnVector.Y) + (m._23 * columnVector.Z) + (m._24 * columnVector.W); + result.Z = (m._31 * columnVector.X) + (m._32 * columnVector.Y) + (m._33 * columnVector.Z) + (m._34 * columnVector.W); + result.W = (m._41 * columnVector.X) + (m._42 * columnVector.Y) + (m._43 * columnVector.Z) + (m._44 * columnVector.W); + return result; + } + + /** + * Multiplies a row-vector and a matrix resulting in a row vector. + */ + public static Vector4 operator *(Vector4 rowVector, Matrix matrix) + { +#unwarn + var m = &matrix.V; + + Vector4 result = ?; + result.X = (rowVector.X * m._11) + (rowVector.Y * m._21) + (rowVector.Z * m._31) + (rowVector.W * m._41); + result.Y = (rowVector.X * m._12) + (rowVector.Y * m._22) + (rowVector.Z * m._32) + (rowVector.W * m._42); + result.Z = (rowVector.X * m._13) + (rowVector.Y * m._23) + (rowVector.Z * m._33) + (rowVector.W * m._43); + result.W = (rowVector.X * m._14) + (rowVector.Y * m._24) + (rowVector.Z * m._34) + (rowVector.W * m._44); + return result; + } + + // Divison + + public static Matrix operator /(Matrix m, float s) + { + float f = 1 / s; + Matrix M = m; + + return .(M.Columns[0] * f, M.Columns[1] * f, M.Columns[2] * f, M.Columns[3] * f); + } + + public static Matrix Scaling(float scale) + { + return .(scale, 0, 0, 0, + 0, scale, 0, 0, + 0, 0, scale, 0, + 0, 0, 0, 1); + } + + public static Matrix Scaling(float scaleX, float scaleY, float scaleZ) + { + return .(scaleX, 0, 0, 0, + 0, scaleY, 0, 0, + 0, 0, scaleZ, 0, + 0, 0, 0, 1); + } + + public static Matrix Scaling(Vector3 scale) + { + return .(scale.X, 0, 0, 0, + 0, scale.Y, 0, 0, + 0, 0, scale.Z, 0, + 0, 0, 0, 1); + } + + public static Matrix Translation(float x, float y, float z) + { + return .(1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1); + } + + public static Matrix Translation(Vector3 translation) + { + return .(1, 0, 0, translation.X, + 0, 1, 0, translation.Y, + 0, 0, 1, translation.Z, + 0, 0, 0, 1); + } + + public static Matrix RotationX(float rot) + { + float sin = Math.Sin(rot); + float cos = Math.Cos(rot); + + return .(1, 0, 0, 0, + 0, cos, -sin, 0, + 0, sin, cos, 0, + 0, 0, 0, 1); + } + + public static Matrix RotationY(float rot) + { + float sin = Math.Sin(rot); + float cos = Math.Cos(rot); + + return .(cos, 0, sin, 0, + 0, 1, 0, 0, + -sin, 0, cos, 0, + 0, 0, 0, 1); + } + + public static Matrix RotationZ(float rot) + { + float sin = Math.Sin(rot); + float cos = Math.Cos(rot); + + return .(cos, -sin, 0, 0, + sin, cos, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); + } + + /** + * Calculates a view Matrix that is located at specified postion and looks at the given target. + * @param position The cameras position. + * @param target The point the camera looks at. + * @param up A vector defining the up direction of the camera. + * @returns a view matrix. + */ + public static Matrix LookAt(Vector3 position, Vector3 target, Vector3 up) + { + Vector3 forward = target - position; + forward.Normalize(); + + Vector3 right = Vector3.Cross(up, forward); + right.Normalize(); + + Vector3 newUp = Vector3.Cross(forward, right); + newUp.Normalize(); + + Matrix result = .Identity; + + result.Forward = forward; + result.Up = up; + result.Right = right; + result.Translation.X = -Vector3.Dot(position, right); + result.Translation.Y = -Vector3.Dot(position, up); + result.Translation.Z = -Vector3.Dot(position, forward); + + return result; + } + + /// Returns the transpose of this matrix + [DisableChecks] + public Matrix Transpose() + { + return .(_11, _21, _31, _41, + _12, _22, _32, _42, + _13, _23, _33, _43, + _14, _24, _34, _44); + } + + /** + Calculates the inverse of the matrix. + */ + [DisableChecks] + public float Determinant() mut + { + // From: Lengyel, Eric. Foundations of Game Engine Development, Volume 1: Mathematics (S.61). Kindle-Version. + + Vector3 a = *(Vector3*)&Columns[0]; + Vector3 b = *(Vector3*)&Columns[1]; + Vector3 c = *(Vector3*)&Columns[2]; + Vector3 d = *(Vector3*)&Columns[3]; + + float x = this[3, 0]; + float y = this[3, 1]; + float z = this[3, 2]; + float w = this[3, 3]; + + Vector3 s = Vector3.Cross(a, b); + Vector3 t = Vector3.Cross(c, d); + Vector3 u = y * a - x * b; + Vector3 v = w * c - z * d; + + return Vector3.Dot(s, v) + Vector3.Dot(t, u); + } + + /** + Calculates the inverse of the matrix. + */ + public Matrix Invert() + { + // From: Lengyel, Eric. Foundations of Game Engine Development, Volume 1: Mathematics (S.61). Kindle-Version. + +#unwarn + Vector3 a = *(Vector3*)&Columns[0]; +#unwarn + Vector3 b = *(Vector3*)&Columns[1]; +#unwarn + Vector3 c = *(Vector3*)&Columns[2]; +#unwarn + Vector3 d = *(Vector3*)&Columns[3]; + + float x = this[3, 0]; + float y = this[3, 1]; + float z = this[3, 2]; + float w = this[3, 3]; + + Vector3 s = Vector3.Cross(a, b); + Vector3 t = Vector3.Cross(c, d); + Vector3 u = y * a - x * b; + Vector3 v = w * c - z * d; + + float invDet = 1.0f / (Vector3.Dot(s, v) + Vector3.Dot(t, u)); + + s *= invDet; + t *= invDet; + u *= invDet; + v *= invDet; + + Vector3 r0 = Vector3.Cross(b, v) + t * y; + Vector3 r1 = Vector3.Cross(v, a) - t * x; + Vector3 r2 = Vector3.Cross(d, u) + s * w; + Vector3 r3 = Vector3.Cross(u, c) - s * z; + return .(r0.X, r0.Y, r0.Z, -Vector3.Dot(b, t), + r1.X, r1.Y, r1.Z, Vector3.Dot(a, t), + r2.X, r2.Y, r2.Z, -Vector3.Dot(d, s), + r3.X, r3.Y, r3.Z, Vector3.Dot(c, s)); + } + + /// Calculates the inverse of the matrix. + public static Matrix Invert(in Matrix matrix) + { + // From: Lengyel, Eric. Foundations of Game Engine Development, Volume 1: Mathematics (S.61). Kindle-Version. + +#unwarn + Vector3 a = *(Vector3*)&matrix.Columns[0]; +#unwarn + Vector3 b = *(Vector3*)&matrix.Columns[1]; +#unwarn + Vector3 c = *(Vector3*)&matrix.Columns[2]; +#unwarn + Vector3 d = *(Vector3*)&matrix.Columns[3]; + + float x = matrix[3, 0]; + float y = matrix[3, 1]; + float z = matrix[3, 2]; + float w = matrix[3, 3]; + + Vector3 s = Vector3.Cross(a, b); + Vector3 t = Vector3.Cross(c, d); + Vector3 u = y * a - x * b; + Vector3 v = w * c - z * d; + + float invDet = 1.0f / (Vector3.Dot(s, v) + Vector3.Dot(t, u)); + + s *= invDet; + t *= invDet; + u *= invDet; + v *= invDet; + + Vector3 r0 = Vector3.Cross(b, v) + t * y; + Vector3 r1 = Vector3.Cross(v, a) - t * x; + Vector3 r2 = Vector3.Cross(d, u) + s * w; + Vector3 r3 = Vector3.Cross(u, c) - s * z; + return .(r0.X, r0.Y, r0.Z, -Vector3.Dot(b, t), + r1.X, r1.Y, r1.Z, Vector3.Dot(a, t), + r2.X, r2.Y, r2.Z, -Vector3.Dot(d, s), + r3.X, r3.Y, r3.Z, Vector3.Dot(c, s)); + } + + /** + * Creates a perspective projection matrix. + * @param fovY The vertical field of view. + * @param aspectRation The aspect ratio of the viewport. + * @param nearPlane The distance to the near plane. + * @param farPlane The distance to the far plane. + */ + public static Matrix PerspectiveProjection(float fovY, float aspectRatio, float nearPlane, float farPlane) + { + // Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite82). . Kindle-Version. + + float g = 1.0f / Math.Tan(fovY * 0.5f); + float k = farPlane / (farPlane - nearPlane); + + return .(g / aspectRatio, 0, 0, 0, + 0, g, 0, 0, + 0, 0, k, -nearPlane * k, + 0, 0, 1, 0); + } + + /** + * Creates a perspective projection matrix with reversed near- and far plane. + * (i.e. Points on near plane have z-value of 1 and points of far plane have z-value of 0) + * @param fovY The vertical field of view. + * @param aspectRation The aspect ratio of the viewport. + * @param nearPlane The distance to the near plane. + * @param farPlane The distance to the far plane. + */ + public static Matrix ReversedPerspectiveProjection(float fovY, float aspectRatio, float nearPlane, float farPlane) + { + // Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite86). . Kindle-Version. + + float g = 1.0f / Math.Tan(fovY * 0.5f); + float k = nearPlane / (nearPlane - farPlane); + + return .(g / aspectRatio, 0, 0, 0, + 0, g, 0, 0, + 0, 0, k, -farPlane * k, + 0, 0, 1, 0); + } + + /** + * Creates a perspective projection matrix with a far plane at infinity. + * @param fovY The vertical field of view. + * @param aspectRation The aspect ratio of the viewport. + * @param nearPlane The distance to the near plane. + * @param ε An offset to account for floating point round-off errors at infinity. + * Note: Use a tiny value significant compared to the floating-point value of one. + */ + public static Matrix InfinitePerspectiveProjection(float fovY, float aspectRatio, float nearPlane, float ε = 1e-6f) + { + // Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite83). . Kindle-Version. + + float g = 1.0f / Math.Tan(fovY * 0.5f); + + float f = 1 - ε; + + return .(g / aspectRatio, 0, 0, 0, + 0, g, 0, 0, + 0, 0, f, -nearPlane * f, + 0, 0, 1, 0); + } + + /** + * Creates a perspective projection matrix with a far plane at infinity with reversed near- and far plane. + * (i.e. Points on near plane have z-value of 1 and points of far plane have z-value of 0) + * @param fovY The vertical field of view. + * @param aspectRation The aspect ratio of the viewport. + * @param nearPlane The distance to the near plane. + * @param ε An offset to account for floating point round-off errors at infinity. + * Note: Use a tiny value significant compared to the floating-point value of one. + */ + public static Matrix ReversedInfinitePerspectiveProjection(float fovY, float aspectRatio, float nearPlane, float ε = 1e-6f) + { + // Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite88). . Kindle-Version. + + float g = 1.0f / Math.Tan(fovY * 0.5f); + + return .(g / aspectRatio, 0, 0, 0, + 0, g, 0, 0, + 0, 0, ε, nearPlane * (1 - ε), + 0, 0, 1, 0); + } + + /** + * Creates an orthographic projection matrix with the camera centered at the near-plane. + * @param width The width of the view volume. + * @param height The height of the view volume. + * @param depth The depth of the view volume. + */ + public static Matrix OrthographicProjection(float width, float height, float depth) + { + // Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite91). . Kindle-Version. + return .(2.0f / width, 0, 0, 0, + 0, 2.0f/height, 0, 0, + 0, 0, 1.0f / depth, 0, + 0, 0, 0, 1); + } + + /** + * Creates an orthographic projection matrix. + * @param left The left side of the view volume. + * @param right The right side of the view volume. + * @param top The top side of the view volume. + * @param bottom The bottom side of the view volume. + * @param near The near plane of the view volume. + * @param far The far plane of the view volume. + */ + public static Matrix OrthographicProjectionOffCenter(float left, float right, float top, float bottom, float near, float far) + { + // Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite91). . Kindle-Version. + + float w_inv = 1.0f / (right - left); + float h_inv = 1.0f / (top - bottom); + float d_inv = 1.0f / (far - near); + + return .(2.0f * w_inv, 0.0f, 0.0f, -(right + left) * w_inv, + 0.0f, 2.0f * h_inv, 0.0f, -(bottom + top) * h_inv, + 0.0f, 0.0f, d_inv, -near * d_inv, + 0.0f, 0.0f, 0.0f, 1.0f); + } + + public static bool operator ==(Matrix left, Matrix right) + { + return Matrix.Equals(left, right); + } + + public static bool operator !=(Matrix left, Matrix right) + { + return !Matrix.Equals(left, right); + } + + public static bool Equals(Matrix left, Matrix right) + { + return left.Values == right.Values; + } + + public static explicit operator Matrix3x3(Matrix value) + { + return .(value.Right, value.Up, value.Forward); + } + + public static void Exponent(ref Matrix matrix, int exponent, out Matrix result) + { + if(exponent == 0) + result = .Identity; + else if(exponent == 1) + result = matrix; + else if(exponent > 1) + { + result = .Identity; + Matrix b = matrix; + + var exponent; + + for(;exponent > 0;) + { + if(exponent & 1 > 0) + result *= b; + + exponent >>= 1; + + if(exponent > 0) + b *= b; + } + + } + else // Exponent < 0 + { + Matrix m = matrix.Invert(); + Exponent(ref m, -exponent, out result); + } + } + + /** + * Orthogonalizes the matrix. + */ + public void Orthogonalize() mut + { + Columns[1] -= .Project(Columns[1], Columns[0]); + Columns[2] -= .Project(Columns[2], Columns[0]) + .Project(Columns[2], Columns[1]); + Columns[3] -= .Project(Columns[3], Columns[0]) + .Project(Columns[3], Columns[1]) + .Project(Columns[3], Columns[2]); + } + + /** + * Orthonormalizes the matrix. + */ + public void Orthonormalize() mut + { + Columns[0].Normalize(); + Columns[1] = .Normalize(.Reject(Columns[1], Columns[0])); + Columns[2] = .Normalize(.Reject(.Reject(Columns[2], Columns[0]), Columns[1])); + Columns[3] = .Normalize(.Reject(.Reject(.Reject(Columns[2], Columns[0]), Columns[1]), Columns[2])); + } + public static Self RotationQuaternion(Quaternion rotation) + { + float xSq = 2 * rotation.X * rotation.X; + float ySq = 2 * rotation.Y * rotation.Y; + float zSq = 2 * rotation.Z * rotation.Z; + + float xy = 2 * rotation.X * rotation.Y; + float xz = 2 * rotation.X * rotation.Z; + float xw = 2 * rotation.X * rotation.W; + float yz = 2 * rotation.Y * rotation.Z; + float yw = 2 * rotation.Y * rotation.W; + float zw = 2 * rotation.Z * rotation.W; + + Self result = ?; + + result._11 = 1 - ySq - zSq; + result._21 = xy + zw; + result._31 = xz - yw; + result._41 = 0; + + result._12 = xy - zw; + result._22 = 1 - xSq - zSq; + result._32 = yz + xw; + result._42 = 0; + + result._13 = xz + yw; + result._23 = yz - xw; + result._33 = 1 - xSq - ySq; + result._43 = 0; + + result._14 = 0; + result._24 = 0; + result._34 = 0; + result._44 = 1; + + return result; + } + + public static void Decompose(Self matrix, out Vector3 position, out Quaternion rotation, out Vector3 scale) + { + var matrix; + + // Translation -> get last column + position = matrix.Translation; + // Zero translation for next step + matrix.Translation = .Zero; + + // TODO: this doesn't detect mirroring + + // Extract scaling from matrix + scale.X = (*(Vector3*)&matrix.Columns[0]).Magnitude(); + scale.Y = (*(Vector3*)&matrix.Columns[1]).Magnitude(); + scale.Z = (*(Vector3*)&matrix.Columns[2]).Magnitude(); + + if(MathHelper.IsZero(scale.X) || MathHelper.IsZero(scale.Y) || MathHelper.IsZero(scale.Z)) + { + rotation = .Identity; + return; + } + + // Remove scale from matrix (normalize the columns) + matrix.Columns[0] /= scale.X; + matrix.Columns[1] /= scale.Y; + matrix.Columns[2] /= scale.Z; + + rotation = Quaternion.FromMatrix(matrix); + } +} diff --git a/GlitchyEngine/src/Math/MatrixExtension.bf b/GlitchyEngine/src/Math/MatrixExtension.bf deleted file mode 100644 index b2ce8b1..0000000 --- a/GlitchyEngine/src/Math/MatrixExtension.bf +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using GlitchyEngine.Math; -using GlitchyEngine; - -namespace DirectX.Math -{ - extension Matrix - { - typealias Vec3 = GlitchyEngine.Math.Vector3; - - public static Self RotationQuaternion(Quaternion rotation) - { - float xSq = 2 * rotation.X * rotation.X; - float ySq = 2 * rotation.Y * rotation.Y; - float zSq = 2 * rotation.Z * rotation.Z; - - float xy = 2 * rotation.X * rotation.Y; - float xz = 2 * rotation.X * rotation.Z; - float xw = 2 * rotation.X * rotation.W; - float yz = 2 * rotation.Y * rotation.Z; - float yw = 2 * rotation.Y * rotation.W; - float zw = 2 * rotation.Z * rotation.W; - - Self result = ?; - - result.V._11 = 1 - ySq - zSq; - result.V._21 = xy + zw; - result.V._31 = xz - yw; - result.V._41 = 0; - - result.V._12 = xy - zw; - result.V._22 = 1 - xSq - zSq; - result.V._32 = yz + xw; - result.V._42 = 0; - - result.V._13 = xz + yw; - result.V._23 = yz - xw; - result.V._33 = 1 - xSq - ySq; - result.V._43 = 0; - - result.V._14 = 0; - result.V._24 = 0; - result.V._34 = 0; - result.V._44 = 1; - - return result; - } - - public static void Decompose(Self matrix, out Vec3 position, out Quaternion rotation, out Vec3 scale) - { - var matrix; - - // Translation -> get last column - position = matrix.Translation; - // Zero translation for next step - matrix.Translation = .Zero; - - // TODO: this doesn't detect mirroring - - // Extract scaling from matrix - scale.X = (*(Vec3*)&matrix.Columns[0]).Magnitude(); - scale.Y = (*(Vec3*)&matrix.Columns[1]).Magnitude(); - scale.Z = (*(Vec3*)&matrix.Columns[2]).Magnitude(); - - if(MathHelper.IsZero(scale.X) || MathHelper.IsZero(scale.Y) || MathHelper.IsZero(scale.Z)) - { - rotation = .Identity; - return; - } - - // Remove scale from matrix (normalize the columns) - matrix.Columns[0] /= scale.X; - matrix.Columns[1] /= scale.Y; - matrix.Columns[2] /= scale.Z; - - rotation = Quaternion.FromMatrix(matrix); - } - - /*[Test] - static void TestQuaternionToMatrix() - { - // Rotation around Z-Axis by 90° - Quaternion quat = .(0, 0, 0.707107f, 0.707107f); - quat.Normalize(); - - - }*/ - } -} diff --git a/GlitchyEngine/src/Math/Quaternion.bf b/GlitchyEngine/src/Math/Quaternion.bf index 39e3d5e..9e55d76 100644 --- a/GlitchyEngine/src/Math/Quaternion.bf +++ b/GlitchyEngine/src/Math/Quaternion.bf @@ -144,7 +144,7 @@ namespace GlitchyEngine.Math { // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ - var m = matrix.V; + var m = matrix; Quaternion result = ?; diff --git a/GlitchyEngine/src/Renderer/DebugRenderer.bf b/GlitchyEngine/src/Renderer/DebugRenderer.bf index dacd911..28d056d 100644 --- a/GlitchyEngine/src/Renderer/DebugRenderer.bf +++ b/GlitchyEngine/src/Renderer/DebugRenderer.bf @@ -111,15 +111,15 @@ namespace GlitchyEngine.Renderer Vector4[8] corners; // Perspective - if(projection.V._43 != 0.0f) + if(projection._43 != 0.0f) { // near plane for perspective projection, far plane if reversed - float d1 = -projection.V._34 / projection.V._33; + float d1 = -projection._34 / projection._33; - float d2 = projection.V._34 / (1.0f - projection.V._33); + float d2 = projection._34 / (1.0f - projection._33); - float gOverS = projection.V._11; - float g = projection.V._22; + float gOverS = projection._11; + float g = projection._22; //var corners = //(Vector4*)&_vbFrustum.Data; @@ -158,14 +158,14 @@ namespace GlitchyEngine.Renderer } else { - float l = -(projection.V._14 + 1.0f) / projection.V._11; - float r = (1.0f - projection.V._14) / projection.V._11; + float l = -(projection._14 + 1.0f) / projection._11; + float r = (1.0f - projection._14) / projection._11; - float t = -(projection.V._24 + 1.0f) / projection.V._22; - float b = (1.0f - projection.V._24) / projection.V._22; + float t = -(projection._24 + 1.0f) / projection._22; + float b = (1.0f - projection._24) / projection._22; - float n = -projection.V._34 / projection.V._33; - float f = (1 - projection.V._34) / projection.V._33; + float n = -projection._34 / projection._33; + float f = (1 - projection._34) / projection._33; //var corners = (Vector4*)&_vbFrustum.Data; corners[0] = .(r, t, n, 1.0f); diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index 1a6e486..4cff69a 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -491,5 +491,25 @@ namespace GlitchyEngine.World handler(entity, componentType, component); } } + + public WorldEnumerator GetEntities() where TComponent : struct + { + return _ecsWorld.Enumerate(); + } + + public WorldEnumerator GetEntities() + where TComponent1 : struct + where TComponent2 : struct + { + return _ecsWorld.Enumerate(); + } + + public WorldEnumerator GetEntities() + where TComponent1 : struct + where TComponent2 : struct + where TComponent3 : struct + { + return _ecsWorld.Enumerate(); + } } -} \ No newline at end of file +}