using GlitchyEngine.Math; using GlitchyEngine.World; using System; namespace GlitchyEngine.Renderer { /// Provides functionality for debugging public static class DebugRenderer { private static GeometryBinding CoordinateCross; public static bool DrawEntityTransforms = true; public static void Init() { CreateCoordinateCross(); } private static void CreateCoordinateCross() { CoordinateCross = new GeometryBinding(); //CoordinateCross.PrimitiveTopology } public static void Deinit() { CoordinateCross.ReleaseRef(); } /** * Draws a coordinate cross for the given matrix. * @param transform The transform matrix. * @param length Can be used to set a fixed length for the rendered lines that represent the axes. * Set to 0 if you want transform to affect the length of the lines. */ public static void DrawCoordinateCross(Matrix transform, float length = 0.0f) { var transform; if(length != 0.0f) { transform.Columns[0]..Normalize() *= length; transform.Columns[1]..Normalize() *= length; transform.Columns[2]..Normalize() *= length; } Renderer.DrawLine(.Zero, .Right, .Red, transform); Renderer.DrawLine(.Zero, .Up, .Lime, transform); Renderer.DrawLine(.Zero, .Forward, .Blue, transform); } //static GeometryBinding _frustumGeometry; //static VertexBuffer _frustumVertices; /** * Draws the view frustum for the given camera transform and projection. * @param worldTransform The cameras transform matrix. * @param projection The cameras projection matrix. * @param observerVP The view projection of the rendering camera. * @param color The color of the frustum. */ public static void DrawViewFrustum(Matrix worldTransform, Matrix projection, Matrix observerVP, ColorRGBA color = .Red) { /*if (_frustumGeometry == null) { _frustumGeometry = new GeometryBinding(); _frustumGeometry.SetPrimitiveTopology(.LineList); _frustumVertices = new VertexBuffer(typeof(Vector4), 8, .Dynamic, .Write); _frustumGeometry.SetVertexBufferSlot(_frustumVertices, 0); using (IndexBuffer indexBuffer = new IndexBuffer(24, .Immutable)) { uint16[24] indices = .( 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7); indexBuffer.SetData(indices); _frustumGeometry.SetIndexBuffer(indexBuffer); } }*/ uint16[24] indices = .( 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7); Vector4[8] corners; // Perspective if(projection.V._43 != 0.0f) { // near plane for perspective projection, far plane if reversed float d1 = -projection.V._34 / projection.V._33; float d2 = projection.V._34 / (1.0f - projection.V._33); float gOverS = projection.V._11; float g = projection.V._22; //var corners = //(Vector4*)&_vbFrustum.Data; if(Math.Abs(d1) >= 10000) { d1 = 10.0f; corners[0] = .( d1 / gOverS, d1 / g , d1, 0.0f); corners[1] = .( corners[0].X, -corners[0].Y, d1, 0.0f); corners[2] = .(-corners[0].X, -corners[0].Y, d1, 0.0f); corners[3] = .(-corners[0].X, corners[0].Y, d1, 0.0f); } else { corners[0] = .( d1 / gOverS, d1 / g , d1, 1.0f); corners[1] = .( corners[0].X, -corners[0].Y, d1, 1.0f); corners[2] = .(-corners[0].X, -corners[0].Y, d1, 1.0f); corners[3] = .(-corners[0].X, corners[0].Y, d1, 1.0f); } if(Math.Abs(d2) >= 10000) { d2 = 10.0f; corners[4] = .( d2 / gOverS, d2 / g , d2, 0.0f); corners[5] = .( corners[4].X, -corners[4].Y, d2, 0.0f); corners[6] = .(-corners[4].X, -corners[4].Y, d2, 0.0f); corners[7] = .(-corners[4].X, corners[4].Y, d2, 0.0f); } else { corners[4] = .( d2 / gOverS, d2 / g , d2, 1.0f); corners[5] = .( corners[4].X, -corners[4].Y, d2, 1.0f); corners[6] = .(-corners[4].X, -corners[4].Y, d2, 1.0f); corners[7] = .(-corners[4].X, corners[4].Y, d2, 1.0f); } } else { float l = -(projection.V._14 + 1.0f) / projection.V._11; float r = (1.0f - projection.V._14) / projection.V._11; float t = -(projection.V._24 + 1.0f) / projection.V._22; float b = (1.0f - projection.V._24) / projection.V._22; float n = -projection.V._34 / projection.V._33; float f = (1 - projection.V._34) / projection.V._33; //var corners = (Vector4*)&_vbFrustum.Data; corners[0] = .(r, t, n, 1.0f); corners[1] = .(r, b, n, 1.0f); corners[2] = .(l, b, n, 1.0f); corners[3] = .(l, t, n, 1.0f); corners[4] = .(r, t, f, 1.0f); corners[5] = .(r, b, f, 1.0f); corners[6] = .(l, b, f, 1.0f); corners[7] = .(l, t, f, 1.0f); } for (int i = 0; i < indices.Count; i += 2) { uint16 index0 = indices[i]; uint16 index1 = indices[i + 1]; Renderer.DrawLine(corners[index0], corners[index1], color, worldTransform, observerVP); } } public static void Render(EcsWorld world) { if(DrawEntityTransforms) { for(var (entity, transform) in world.Enumerate()) { DrawCoordinateCross(transform.WorldTransform); } } } } }