diff --git a/PCK-Studio/Extensions/BoundingBoxExtensions.cs b/PCK-Studio/Extensions/BoundingBoxExtensions.cs new file mode 100644 index 00000000..a02878e0 --- /dev/null +++ b/PCK-Studio/Extensions/BoundingBoxExtensions.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using PckStudio.Rendering; + +namespace PckStudio.Extensions +{ + internal static class BoundingBoxExtensions + { + public static BoundingBox GetEnclosingBoundingBox(this IEnumerable boundingBoxes) + { + return boundingBoxes.DefaultIfEmpty().Aggregate((a, b) => new BoundingBox(OpenTK.Vector3.ComponentMin(a.Start, b.Start), OpenTK.Vector3.ComponentMax(a.End, b.End))); + } + } +} diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj index 0afcf9e1..5060c46c 100644 --- a/PCK-Studio/PckStudio.csproj +++ b/PCK-Studio/PckStudio.csproj @@ -136,6 +136,7 @@ + diff --git a/PCK-Studio/Rendering/BoundingBox.cs b/PCK-Studio/Rendering/BoundingBox.cs index bd7006b8..b7fd9bc9 100644 --- a/PCK-Studio/Rendering/BoundingBox.cs +++ b/PCK-Studio/Rendering/BoundingBox.cs @@ -29,45 +29,56 @@ namespace PckStudio.Rendering { } - - public ColorVertex[] GetVertices() + public OpenTK.Matrix4 GetTransform() { - OpenTK.Vector3 s = Start; - OpenTK.Vector3 e = End; - return [ - new ColorVertex(new OpenTK.Vector3(s.X, e.Y, e.Z)), - new ColorVertex(new OpenTK.Vector3(e.X, e.Y, e.Z)), - new ColorVertex(new OpenTK.Vector3(e.X, s.Y, e.Z)), - new ColorVertex(new OpenTK.Vector3(s.X, s.Y, e.Z)), - new ColorVertex(new OpenTK.Vector3(s.X, e.Y, s.Z)), - new ColorVertex(new OpenTK.Vector3(e.X, e.Y, s.Z)), - new ColorVertex(new OpenTK.Vector3(e.X, s.Y, s.Z)), - new ColorVertex(new OpenTK.Vector3(s.X, s.Y, s.Z)), + return OpenTK.Matrix4.CreateScale(Volume) * OpenTK.Matrix4.CreateTranslation(Start); + } + + private static readonly ColorVertex[] _vertices = [ + new ColorVertex(new OpenTK.Vector3(0f, 1f, 1f)), + new ColorVertex(new OpenTK.Vector3(1f, 1f, 1f)), + new ColorVertex(new OpenTK.Vector3(1f, 0f, 1f)), + new ColorVertex(new OpenTK.Vector3(0f, 0f, 1f)), + new ColorVertex(new OpenTK.Vector3(0f, 1f, 0f)), + new ColorVertex(new OpenTK.Vector3(1f, 1f, 0f)), + new ColorVertex(new OpenTK.Vector3(1f, 0f, 0f)), + new ColorVertex(new OpenTK.Vector3(0f, 0f, 0f)), ]; - } - public static int[] GetIndecies() - { - return [0, 1, - 1, 2, - 2, 3, - 3, 0, + private static readonly int[] _indecies = [ + 0, 1, + 1, 2, + 2, 3, + 3, 0, - 4, 5, - 5, 6, - 6, 7, - 7, 4, + 4, 5, + 5, 6, + 6, 7, + 7, 4, - 0, 4, - 1, 5, - 2, 6, - 3, 7 + 0, 4, + 1, 5, + 2, 6, + 3, 7 ]; - } - - public static BoundingBox GetEnclosingBoundingBox(IEnumerable boundingBoxes) + + public static ColorVertex[] GetVertices() { - return boundingBoxes.DefaultIfEmpty().Aggregate((a, b) => new BoundingBox(OpenTK.Vector3.ComponentMin(a.Start, b.Start), OpenTK.Vector3.ComponentMax(a.End, b.End))); + return _vertices; + //OpenTK.Vector3 s = Start; // 0, 0, 0 + //OpenTK.Vector3 e = End; // 1, 1, 1 + //return [ + // new ColorVertex(new OpenTK.Vector3(s.X, e.Y, e.Z)), + // new ColorVertex(new OpenTK.Vector3(e.X, e.Y, e.Z)), + // new ColorVertex(new OpenTK.Vector3(e.X, s.Y, e.Z)), + // new ColorVertex(new OpenTK.Vector3(s.X, s.Y, e.Z)), + // new ColorVertex(new OpenTK.Vector3(s.X, e.Y, s.Z)), + // new ColorVertex(new OpenTK.Vector3(e.X, e.Y, s.Z)), + // new ColorVertex(new OpenTK.Vector3(e.X, s.Y, s.Z)), + // new ColorVertex(new OpenTK.Vector3(s.X, s.Y, s.Z)), + //]; } + + public static int[] GetIndecies() => _indecies; } } diff --git a/PCK-Studio/Rendering/CubeMeshCollection.cs b/PCK-Studio/Rendering/CubeMeshCollection.cs index 1e8a87d3..b14c6a9e 100644 --- a/PCK-Studio/Rendering/CubeMeshCollection.cs +++ b/PCK-Studio/Rendering/CubeMeshCollection.cs @@ -178,10 +178,10 @@ namespace PckStudio.Rendering public override BoundingBox GetBounds(Matrix4 transform) { - IEnumerable boundingBoxes = cubes + return cubes .Where(c => c.Visible) .Select(c => c.GetBounds(GetTransform() * transform)) - return BoundingBox.GetEnclosingBoundingBox(boundingBoxes); + .GetEnclosingBoundingBox(); } internal Vector3 GetFaceCenter(int index, Cube.Face face) diff --git a/PCK-Studio/Rendering/ModelRenderer.cs b/PCK-Studio/Rendering/ModelRenderer.cs index ab09399d..a4c88399 100644 --- a/PCK-Studio/Rendering/ModelRenderer.cs +++ b/PCK-Studio/Rendering/ModelRenderer.cs @@ -96,11 +96,10 @@ namespace PckStudio.Rendering { _rootCollection?.Clear(); - IEnumerable allBoxes = model.GetParts() - .SelectMany(p => p.GetBoxes().Select(b => new BoundingBox(b.Position + p.Translation, b.Position + p.Translation + b.Size))); + _maxBounds = model.GetParts() + .SelectMany(p => p.GetBoxes().Select(b => new BoundingBox(b.Position + p.Translation, b.Position + p.Translation + b.Size))) + .GetEnclosingBoundingBox(); - _maxBounds = BoundingBox.GetEnclosingBoundingBox(allBoxes); - if (!GameModelImporter.ModelMetaData.TryGetValue(model.Name, out JsonModelMetaData modelMetaData)) { Trace.TraceError($"[{nameof(ModelRenderer)}@{nameof(LoadModel)}] : Couldn't get meta data for model: '{model.Name}'"); @@ -139,10 +138,10 @@ namespace PckStudio.Rendering if (Context.IsCurrent) { - ShaderProgram shader = GetShader("CubeShader"); - shader.Bind(); - shader.SetUniform2("TexSize", model.TextureSize); - } + ShaderProgram shader = GetShader("CubeShader"); + shader.Bind(); + shader.SetUniform2("TexSize", model.TextureSize); + } } public override void ResetCamera(Vector3 offset) diff --git a/PCK-Studio/Rendering/SceneViewport.cs b/PCK-Studio/Rendering/SceneViewport.cs index 72408d2b..33558f74 100644 --- a/PCK-Studio/Rendering/SceneViewport.cs +++ b/PCK-Studio/Rendering/SceneViewport.cs @@ -167,7 +167,8 @@ namespace PckStudio.Rendering VertexBufferLayout layout = new VertexBufferLayout(); layout.Add(ShaderDataType.Float3); layout.Add(ShaderDataType.Float4); - vao.AddNewBuffer(layout); + int id = vao.AddNewBuffer(layout); + vao.GetBuffer(id).SetData(BoundingBox.GetVertices()); var ibo = IndexBuffer.Create(BoundingBox.GetIndecies()); _boundingBoxDrawContext = new DrawContext(vao, ibo, PrimitiveType.Lines); @@ -267,6 +268,7 @@ namespace PckStudio.Rendering colorShader.Bind(); Matrix4 viewProjection = Camera.GetViewProjection(); colorShader.SetUniformMat4("ViewProjection", ref viewProjection); + transform = boundingBox.GetTransform() * transform; colorShader.SetUniformMat4("Transform", ref transform); colorShader.SetUniform4("BlendColor", color); colorShader.SetUniform1("Intensity", 0.6f); @@ -276,7 +278,6 @@ namespace PckStudio.Rendering GL.DepthFunc(DepthFunction.Always); Renderer.SetLineWidth(2f); - _boundingBoxDrawContext.VertexArray.GetBuffer(0).SetData(boundingBox.GetVertices()); Renderer.Draw(colorShader, _boundingBoxDrawContext); GL.DepthFunc(DepthFunction.Less); diff --git a/PCK-Studio/Rendering/SkinRenderer.cs b/PCK-Studio/Rendering/SkinRenderer.cs index c7cb5c59..08c1183c 100644 --- a/PCK-Studio/Rendering/SkinRenderer.cs +++ b/PCK-Studio/Rendering/SkinRenderer.cs @@ -505,7 +505,7 @@ namespace PckStudio.Rendering void AddOutline(BoundingBox boundingBox, ref List vertices, ref List indices) { int offset = vertices.Count; - vertices.AddRange(boundingBox.GetVertices()); + vertices.AddRange(BoundingBox.GetVertices().Select(vert => new ColorVertex(Vector3.TransformPosition(vert.Position, boundingBox.GetTransform()), vert.Color))); indices.AddRange(BoundingBox.GetIndecies().Select(i => i + offset)); } @@ -689,7 +689,7 @@ namespace PckStudio.Rendering private void CalculateSkinBounds() { - _skinBounds = BoundingBox.GetEnclosingBoundingBox(meshStorage.Values.Select(item => item.GetBounds(Matrix4.Identity))); + _skinBounds = meshStorage.Values.Select(item => item.GetBounds(Matrix4.Identity)).GetEnclosingBoundingBox(); } private void AddCustomModelPart(SkinBOX skinBox) @@ -829,7 +829,7 @@ namespace PckStudio.Rendering GL.DepthMask(true); GL.DepthFunc(DepthFunction.Less); } - + ShaderProgram lineShader = GetShader("PlainColorShader"); // Render (custom) skin @@ -846,7 +846,7 @@ namespace PckStudio.Rendering if (showWireFrame) GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); - Matrix4 transform = Matrix4.CreateScale(1f, -1f, -1f); + Matrix4 renderTransform = Matrix4.CreateScale(1f, -1f, -1f); ShaderProgram cubeShader = GetShader("CubeShader"); cubeShader.Bind(); @@ -863,8 +863,8 @@ namespace PckStudio.Rendering { if (ANIM.GetFlag(SkinAnimFlag.DINNERBONE)) { - transform *= Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(-180f)); - transform = transform.Pivoted(head.GetFaceCenter(0, Cube.Face.Top), Vector3.UnitY * 12f); + renderTransform *= Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(-180f)); + renderTransform = Matrix4.CreateTranslation(head.GetFaceCenter(0, Cube.Face.Top)) * renderTransform.Pivoted(Vector3.UnitY * 12f); } if (!ANIM.GetFlag(SkinAnimFlag.STATIC_ARMS)) @@ -893,12 +893,11 @@ namespace PckStudio.Rendering armLeftMatrix = LeftArmMatrix * armLeftMatrix; } - RenderBodyPart(cubeShader, Matrix4.Identity, transform, "HEAD", "HEADWEAR"); - RenderBodyPart(cubeShader, Matrix4.Identity, transform, "BODY", "JACKET"); - RenderBodyPart(cubeShader, armRightMatrix, transform, "ARM0", "SLEEVE0"); - RenderBodyPart(cubeShader, armLeftMatrix, transform, "ARM1", "SLEEVE1"); - RenderBodyPart(cubeShader, legRightMatrix, transform, "LEG0", "PANTS0"); - RenderBodyPart(cubeShader, legLeftMatrix, transform, "LEG1", "PANTS1"); + RenderBodyPart(cubeShader, Matrix4.Identity, renderTransform, "HEAD", "HEADWEAR", "BODY", "JACKET"); + RenderBodyPart(cubeShader, armRightMatrix, renderTransform, "ARM0", "SLEEVE0"); + RenderBodyPart(cubeShader, armLeftMatrix, renderTransform, "ARM1", "SLEEVE1"); + RenderBodyPart(cubeShader, legRightMatrix, renderTransform, "LEG0", "PANTS0"); + RenderBodyPart(cubeShader, legLeftMatrix, renderTransform, "LEG1", "PANTS1"); if (_capeImage is not null) { @@ -914,7 +913,7 @@ namespace PckStudio.Rendering Matrix4 partMatrix = Matrix4.CreateRotationY(MathHelper.DegreesToRadians(180f)) * Matrix4.CreateRotationX(MathHelper.DegreesToRadians(capeRotation)); - RenderPart(cubeShader, cape, partMatrix, transform); + RenderPart(cubeShader, cape, partMatrix, renderTransform); } // Armor rendering @@ -923,33 +922,33 @@ namespace PckStudio.Rendering armorTexture.Bind(); cubeShader.SetUniform2("TexSize", new Vector2(64, 64)); if (!ANIM.GetFlag(SkinAnimFlag.HEAD_DISABLED) || ANIM.GetFlag(SkinAnimFlag.FORCE_HEAD_ARMOR)) - RenderPart(cubeShader, offsetSpecificMeshStorage["HELMET"], Matrix4.Identity, transform); + RenderPart(cubeShader, offsetSpecificMeshStorage["HELMET"], Matrix4.Identity, renderTransform); if (!ANIM.GetFlag(SkinAnimFlag.BODY_DISABLED) || ANIM.GetFlag(SkinAnimFlag.FORCE_BODY_ARMOR)) - RenderPart(cubeShader, offsetSpecificMeshStorage["CHEST"], Matrix4.Identity, transform); + RenderPart(cubeShader, offsetSpecificMeshStorage["CHEST"], Matrix4.Identity, renderTransform); if (!ANIM.GetFlag(SkinAnimFlag.RIGHT_ARM_DISABLED) || ANIM.GetFlag(SkinAnimFlag.FORCE_RIGHT_ARM_ARMOR)) - RenderPart(cubeShader, offsetSpecificMeshStorage["SHOULDER0"], armRightMatrix, transform); + RenderPart(cubeShader, offsetSpecificMeshStorage["SHOULDER0"], armRightMatrix, renderTransform); if (!ANIM.GetFlag(SkinAnimFlag.LEFT_ARM_DISABLED) || ANIM.GetFlag(SkinAnimFlag.FORCE_LEFT_ARM_ARMOR)) - RenderPart(cubeShader, offsetSpecificMeshStorage["SHOULDER1"], armLeftMatrix, transform); + RenderPart(cubeShader, offsetSpecificMeshStorage["SHOULDER1"], armLeftMatrix, renderTransform); bool showRightLegArmor = !ANIM.GetFlag(SkinAnimFlag.RIGHT_LEG_DISABLED) || ANIM.GetFlag(SkinAnimFlag.FORCE_RIGHT_LEG_ARMOR); if (showRightLegArmor) { - RenderPart(cubeShader, offsetSpecificMeshStorage["PANTS0"], legRightMatrix, transform); - RenderPart(cubeShader, offsetSpecificMeshStorage["BOOT0"], legRightMatrix, transform); + RenderPart(cubeShader, offsetSpecificMeshStorage["PANTS0"], legRightMatrix, renderTransform); + RenderPart(cubeShader, offsetSpecificMeshStorage["BOOT0"], legRightMatrix, renderTransform); } bool showLeftLegArmor = !ANIM.GetFlag(SkinAnimFlag.LEFT_LEG_DISABLED) || ANIM.GetFlag(SkinAnimFlag.FORCE_LEFT_LEG_ARMOR); if (showLeftLegArmor) { - RenderPart(cubeShader, offsetSpecificMeshStorage["PANTS1"], legLeftMatrix, transform); - RenderPart(cubeShader, offsetSpecificMeshStorage["BOOT1"], legLeftMatrix, transform); + RenderPart(cubeShader, offsetSpecificMeshStorage["PANTS1"], legLeftMatrix, renderTransform); + RenderPart(cubeShader, offsetSpecificMeshStorage["BOOT1"], legLeftMatrix, renderTransform); } if (showRightLegArmor && showLeftLegArmor) - RenderPart(cubeShader, offsetSpecificMeshStorage["WAIST"], Matrix4.Identity, transform); + RenderPart(cubeShader, offsetSpecificMeshStorage["WAIST"], Matrix4.Identity, renderTransform); } if (showWireFrame) @@ -961,7 +960,7 @@ namespace PckStudio.Rendering GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); lineShader.Bind(); lineShader.SetUniformMat4("ViewProjection", ref viewProjection); - lineShader.SetUniformMat4("Transform", ref transform); + lineShader.SetUniformMat4("Transform", ref renderTransform); lineShader.SetUniform1("Intensity", 1f); lineShader.SetUniform4("BlendColor", GuideLineColor); Renderer.SetLineWidth(2.5f); @@ -972,7 +971,7 @@ namespace PckStudio.Rendering BoundingBox boundingBox = GetSelectedBoundingArea(); - Matrix4 boundingBoxTransform = transform; + Matrix4 boundingBoxRenderTransform = renderTransform; if (SelectedIndices.Length == 1 && ModelData.IndexInRange(SelectedIndices[0])) { @@ -1002,19 +1001,19 @@ namespace PckStudio.Rendering return Matrix4.Identity; } } - boundingBoxTransform = GetGroupTransform(box.Type) * boundingBoxTransform; + boundingBoxRenderTransform = GetGroupTransform(box.Type) * cubeMesh.GetTransform() * renderTransform; } } GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.SrcColor); - DrawBoundingBox(boundingBoxTransform, boundingBox, HighlightlingColor); + DrawBoundingBox(boundingBoxRenderTransform, boundingBox, HighlightlingColor); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); // Show skin bounds if (ShowBoundingBox) { - GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.SrcColor); - DrawBoundingBox(transform, _skinBounds, Color.BurlyWood); + GL.BlendFunc(BlendingFactor.SrcColor, BlendingFactor.SrcAlpha); + DrawBoundingBox(renderTransform, _skinBounds, Color.BurlyWood); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); } } @@ -1056,10 +1055,10 @@ namespace PckStudio.Rendering Cube cube = box.ToCube(inflate); CubeMeshCollection cubeMesh = meshStorage[box.Type]; yield return cube.GetBoundingBox(cubeMesh.GetTransform()); - } + } yield break; } - return BoundingBox.GetEnclosingBoundingBox(GetBoundingBoxesFromSelectedIndices(SelectedIndices)); + return GetBoundingBoxesFromSelectedIndices(SelectedIndices).GetEnclosingBoundingBox(); } private void RenderBodyPart(ShaderProgram shader, Matrix4 partsMatrix, Matrix4 globalMatrix, params string[] partNames)