From 8955828520b49b3361135e7bff2a4f01df2f5949 Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Fri, 1 Mar 2024 15:19:33 +0100 Subject: [PATCH] SkinRenderer - Add simple single selected box outline rendering --- .../Forms/Editor/CustomSkinEditor.Designer.cs | 25 ++-- PCK-Studio/Forms/Editor/CustomSkinEditor.cs | 6 + PCK-Studio/Forms/Editor/CustomSkinEditor.resx | 132 +++++++++++------- PCK-Studio/PckStudio.csproj | 1 + PCK-Studio/Rendering/BoundingBox.cs | 21 +++ PCK-Studio/Rendering/ColorVertex.cs | 5 + PCK-Studio/Rendering/SceneViewport.cs | 73 ++++++++++ PCK-Studio/Rendering/SkinRenderer.cs | 48 +++++++ 8 files changed, 252 insertions(+), 59 deletions(-) create mode 100644 PCK-Studio/Rendering/BoundingBox.cs diff --git a/PCK-Studio/Forms/Editor/CustomSkinEditor.Designer.cs b/PCK-Studio/Forms/Editor/CustomSkinEditor.Designer.cs index 22bdf208..55f32a05 100644 --- a/PCK-Studio/Forms/Editor/CustomSkinEditor.Designer.cs +++ b/PCK-Studio/Forms/Editor/CustomSkinEditor.Designer.cs @@ -47,7 +47,7 @@ this.outlineColorButton = new MetroFramework.Controls.MetroButton(); this.generateTextureCheckBox = new MetroFramework.Controls.MetroCheckBox(); this.checkGuide = new MetroFramework.Controls.MetroCheckBox(); - this.checkBoxArmor = new MetroFramework.Controls.MetroCheckBox(); + this.showArmorCheckbox = new MetroFramework.Controls.MetroCheckBox(); this.SizeXUpDown = new System.Windows.Forms.NumericUpDown(); this.SizeYUpDown = new System.Windows.Forms.NumericUpDown(); this.SizeZUpDown = new System.Windows.Forms.NumericUpDown(); @@ -214,12 +214,13 @@ this.checkGuide.UseSelectable = true; this.checkGuide.CheckedChanged += new System.EventHandler(this.checkGuide_CheckedChanged); // - // checkBoxArmor + // showArmorCheckbox // - resources.ApplyResources(this.checkBoxArmor, "checkBoxArmor"); - this.checkBoxArmor.Name = "checkBoxArmor"; - this.checkBoxArmor.Theme = MetroFramework.MetroThemeStyle.Dark; - this.checkBoxArmor.UseSelectable = true; + resources.ApplyResources(this.showArmorCheckbox, "showArmorCheckbox"); + this.showArmorCheckbox.Name = "showArmorCheckbox"; + this.showArmorCheckbox.Theme = MetroFramework.MetroThemeStyle.Dark; + this.showArmorCheckbox.UseSelectable = true; + this.showArmorCheckbox.CheckedChanged += new System.EventHandler(this.showArmorCheckbox_CheckedChanged); // // SizeXUpDown // @@ -351,9 +352,9 @@ // // metroTabControl1 // - resources.ApplyResources(this.metroTabControl1, "metroTabControl1"); this.metroTabControl1.Controls.Add(this.skinPartsTabPage); this.metroTabControl1.Controls.Add(this.skinOffsetsTabPage); + resources.ApplyResources(this.metroTabControl1, "metroTabControl1"); this.metroTabControl1.Name = "metroTabControl1"; this.metroTabControl1.SelectedIndex = 0; this.metroTabControl1.Style = MetroFramework.MetroColorStyle.Pink; @@ -362,8 +363,8 @@ // // skinPartsTabPage // - resources.ApplyResources(this.skinPartsTabPage, "skinPartsTabPage"); this.skinPartsTabPage.Controls.Add(this.skinPartListBox); + resources.ApplyResources(this.skinPartsTabPage, "skinPartsTabPage"); this.skinPartsTabPage.Name = "skinPartsTabPage"; // // skinOffsetsTabPage @@ -380,12 +381,14 @@ // // renderer3D1 // + resources.ApplyResources(this.renderer3D1, "renderer3D1"); this.renderer3D1.BackColor = System.Drawing.Color.DimGray; this.renderer3D1.ClampModel = false; - resources.ApplyResources(this.renderer3D1, "renderer3D1"); + this.renderer3D1.MouseSensetivity = 0.01F; this.renderer3D1.Name = "renderer3D1"; this.renderer3D1.OutlineColor = System.Drawing.Color.Empty; this.renderer3D1.RefreshRate = 50; + this.renderer3D1.ShowArmor = false; this.renderer3D1.ShowGuideLines = false; this.renderer3D1.Texture = null; this.renderer3D1.VSync = true; @@ -417,7 +420,7 @@ this.Controls.Add(this.SizeZUpDown); this.Controls.Add(this.SizeYUpDown); this.Controls.Add(this.SizeXUpDown); - this.Controls.Add(this.checkBoxArmor); + this.Controls.Add(this.showArmorCheckbox); this.Controls.Add(this.checkGuide); this.Controls.Add(this.generateTextureCheckBox); this.Controls.Add(this.outlineColorButton); @@ -468,7 +471,7 @@ private MetroFramework.Controls.MetroButton buttonEXPORT; private MetroFramework.Controls.MetroCheckBox generateTextureCheckBox; private MetroFramework.Controls.MetroCheckBox checkGuide; - private MetroFramework.Controls.MetroCheckBox checkBoxArmor; + private MetroFramework.Controls.MetroCheckBox showArmorCheckbox; private System.Windows.Forms.NumericUpDown SizeXUpDown; private System.Windows.Forms.NumericUpDown SizeYUpDown; private System.Windows.Forms.NumericUpDown SizeZUpDown; diff --git a/PCK-Studio/Forms/Editor/CustomSkinEditor.cs b/PCK-Studio/Forms/Editor/CustomSkinEditor.cs index 3f759cd3..51cbfc34 100644 --- a/PCK-Studio/Forms/Editor/CustomSkinEditor.cs +++ b/PCK-Studio/Forms/Editor/CustomSkinEditor.cs @@ -285,6 +285,7 @@ namespace PckStudio.Forms.Editor int scale = 4; if (skinPartListBox.SelectedItem is SkinBOX box) { + renderer3D1.SelectedIndex = skinPartListBox.SelectedIndex; uvPictureBox.Image = new Bitmap(uvPictureBox.BackgroundImage.Width * scale, uvPictureBox.BackgroundImage.Height * scale); using (Graphics g = Graphics.FromImage(uvPictureBox.Image)) { @@ -322,6 +323,11 @@ namespace PckStudio.Forms.Editor { outlineColorButton.Visible = renderer3D1.ShowGuideLines = checkGuide.Checked; } + + private void showArmorCheckbox_CheckedChanged(object sender, EventArgs e) + { + renderer3D1.ShowArmor = showArmorCheckbox.Checked; + } } class CSMJObject diff --git a/PCK-Studio/Forms/Editor/CustomSkinEditor.resx b/PCK-Studio/Forms/Editor/CustomSkinEditor.resx index 327c7aaa..abd45aa3 100644 --- a/PCK-Studio/Forms/Editor/CustomSkinEditor.resx +++ b/PCK-Studio/Forms/Editor/CustomSkinEditor.resx @@ -267,6 +267,15 @@ 17, 17 + + 152, 108 + + + contextMenuStrip1 + + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO @@ -339,15 +348,6 @@ Change Color - - 152, 108 - - - contextMenuStrip1 - - - System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Bottom, Right @@ -579,34 +579,34 @@ 16 - + Bottom, Right - + True - + 627, 503 - - 129, 15 + + 89, 15 - + 149 - - Show Armor Offsets + + Show Armor - - checkBoxArmor + + showArmorCheckbox - + MetroFramework.Controls.MetroCheckBox, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a - + $this - + 15 @@ -960,6 +960,51 @@ 2 + + skinPartsTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + metroTabControl1 + + + 0 + + + skinOffsetsTabPage + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + metroTabControl1 + + + 1 + + + 23, 59 + + + 161, 488 + + + 1 + + + metroTabControl1 + + + MetroFramework.Controls.MetroTabControl, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a + + + $this + + + 1 + 4, 38 @@ -984,18 +1029,6 @@ 0 - - Fill - - - 0, 0 - - - 153, 446 - - - 0 - offsetListBox @@ -1032,26 +1065,29 @@ 1 - - 23, 59 + + Fill - - 161, 488 + + 0, 0 - - 1 + + 153, 446 - - metroTabControl1 + + 0 - - MetroFramework.Controls.MetroTabControl, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a + + offsetListBox - - $this + + System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 1 + + skinOffsetsTabPage + + + 0 Top, Bottom, Left, Right diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj index 35e5d6a6..c10757d5 100644 --- a/PCK-Studio/PckStudio.csproj +++ b/PCK-Studio/PckStudio.csproj @@ -150,6 +150,7 @@ True Resources.resx + diff --git a/PCK-Studio/Rendering/BoundingBox.cs b/PCK-Studio/Rendering/BoundingBox.cs new file mode 100644 index 00000000..eb1b1590 --- /dev/null +++ b/PCK-Studio/Rendering/BoundingBox.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OpenTK; + +namespace PckStudio.Rendering +{ + internal struct BoundingBox + { + public readonly Vector3 Start; + public readonly Vector3 End; + + public BoundingBox(Vector3 start, Vector3 end) + { + Start = start; + End = end; + } + } +} diff --git a/PCK-Studio/Rendering/ColorVertex.cs b/PCK-Studio/Rendering/ColorVertex.cs index d465e846..7ad41069 100644 --- a/PCK-Studio/Rendering/ColorVertex.cs +++ b/PCK-Studio/Rendering/ColorVertex.cs @@ -17,6 +17,11 @@ namespace PckStudio.Rendering Position = position; Color = color; } + + public ColorVertex(Vector3 position) + : this(position, System.Drawing.Color.White) + { + } public Vector3 Position { get; set; } public Color4 Color { get; set; } diff --git a/PCK-Studio/Rendering/SceneViewport.cs b/PCK-Studio/Rendering/SceneViewport.cs index 6c65fe28..927f8092 100644 --- a/PCK-Studio/Rendering/SceneViewport.cs +++ b/PCK-Studio/Rendering/SceneViewport.cs @@ -26,9 +26,13 @@ https://github.com/KareemMAX/Minecraft-Skiner/blob/master/src/Minecraft%20skiner */ using System; +using System.Drawing; using System.Windows.Forms; using OpenTK; +using OpenTK.Graphics.OpenGL; +using PckStudio.Properties; using PckStudio.Rendering.Camera; +using PckStudio.Rendering.Shader; namespace PckStudio.Rendering { @@ -53,6 +57,37 @@ namespace PckStudio.Rendering private int refreshRate = 60; private Timer timer; + private VertexArray VAO; + private VertexBuffer VBO; + private IndexBuffer IBO; + private ShaderProgram colorShader; + + protected void Init() + { + colorShader = ShaderProgram.Create(Resources.plainColorVertexShader, Resources.plainColorFragmentShader); + VAO = new VertexArray(); + VBO = new VertexBuffer(); + IBO = IndexBuffer.Create( + 0, 1, + 1, 2, + 2, 3, + 3, 0, + + 4, 5, + 5, 6, + 6, 7, + 7, 4, + + 0, 4, + 1, 5, + 2, 6, + 3, 7); + VertexBufferLayout layout = new VertexBufferLayout(); + layout.Add(ShaderDataType.Float3); + layout.Add(ShaderDataType.Float4); + VAO.AddBuffer(VBO, layout); + } + public SceneViewport() : base() { timer = new Timer(); @@ -64,6 +99,44 @@ namespace PckStudio.Rendering VSync = true; } + + protected void DrawBoundingBox(Matrix4 transform, BoundingBox boundingBox, Color color) + { + colorShader.Bind(); + Matrix4 viewProjection = Camera.GetViewProjection(); + colorShader.SetUniformMat4("ViewProjection", ref viewProjection); + colorShader.SetUniformMat4("Transform", ref transform); + colorShader.SetUniform4("baseColor", color); + colorShader.SetUniform1("intensity", 0.6f); + + GL.Enable(EnableCap.LineSmooth); + + GL.DepthFunc(DepthFunction.Always); + + Renderer.SetLineWidth(2f); + + Vector3 s = boundingBox.Start; + Vector3 e = boundingBox.End; + + ColorVertex[] vertices = [ + new ColorVertex(new Vector3(s.X, e.Y, e.Z)), + new ColorVertex(new Vector3(e.X, e.Y, e.Z)), + new ColorVertex(new Vector3(e.X, s.Y, e.Z)), + new ColorVertex(new Vector3(s.X, s.Y, e.Z)), + new ColorVertex(new Vector3(s.X, e.Y, s.Z)), + new ColorVertex(new Vector3(e.X, e.Y, s.Z)), + new ColorVertex(new Vector3(e.X, s.Y, s.Z)), + new ColorVertex(new Vector3(s.X, s.Y, s.Z)), + ]; + + VAO.Bind(); + VBO.SetData(vertices); + IBO.Bind(); + GL.DrawElements(PrimitiveType.Lines, IBO.GetCount(), DrawElementsType.UnsignedInt, 0); + GL.DepthFunc(DepthFunction.Less); + Renderer.SetLineWidth(1f); + } + private void TimerTick(object sender, EventArgs e) { OnTimerTick?.Invoke(sender, e); diff --git a/PCK-Studio/Rendering/SkinRenderer.cs b/PCK-Studio/Rendering/SkinRenderer.cs index ddfe9342..9bf656f8 100644 --- a/PCK-Studio/Rendering/SkinRenderer.cs +++ b/PCK-Studio/Rendering/SkinRenderer.cs @@ -77,6 +77,7 @@ namespace PckStudio.Rendering } public float MouseSensetivity { get; set; } = 0.01f; + public int SelectedIndex { get; set; } = -1; public bool ClampModel { get; set; } = false; public bool ShowArmor { get; set; } = false; @@ -288,6 +289,8 @@ namespace PckStudio.Rendering cubeMesh.UploadData(); } GLErrorCheck(); + base.Init(); + GLErrorCheck(); initialized = true; } @@ -1029,10 +1032,55 @@ namespace PckStudio.Rendering GL.BlendFunc(BlendingFactor.DstAlpha, BlendingFactor.OneMinusSrcAlpha); GL.DepthFunc(DepthFunction.Less); } + + if (ModelData.IndexInRange(SelectedIndex)) + { + SkinBOX box = ModelData[SelectedIndex]; + var cubeBoundingBox = Cube.FromSkinBox(box).GetBoundingBox(); + + if (meshStorage.ContainsKey(box.Type)) + { + var cubeMesh = meshStorage[box.Type]; + + Matrix4 GetGroupTransform(string type) + { + switch (type) + { + case "ARM0": + case "SLEEVE0": + return RightArmMatrix * armRightMatrix; + case "ARM1": + case "SLEEVE1": + return LeftArmMatrix * armLeftMatrix; + case "LEG0": + case "PANTS0": + return legRightMatrix; + case "LEG1": + case "PANTS1": + return legLeftMatrix; + default: + return Matrix4.Identity; + } + } + + transform *= GetGroupTransform(box.Type); + Vector3 translation = cubeMesh.Translation - cubeMesh.Offset; + Vector3 pivot = cubeMesh.Pivot + cubeMesh.Offset; + transform = Pivot(translation, pivot, transform); + } + + GL.BlendFunc(BlendingFactor.DstAlpha, BlendingFactor.OneMinusSrcAlpha); + base.DrawBoundingBox(transform, cubeBoundingBox, Color.Red); + GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + } } + // Ground plane { + GL.Enable(EnableCap.DepthTest); + GL.Enable(EnableCap.AlphaTest); // Enable transparent + GL.AlphaFunc(AlphaFunction.Always, 0.0f); GL.BlendFunc(BlendingFactor.DstAlpha, BlendingFactor.OneMinusSrcAlpha); lineShader.Bind(); lineShader.SetUniformMat4("ViewProjection", ref viewProjection);