From 0b154b0d3a0f88c044ae3ccb1e14ec32bad9a90f Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Mon, 8 Jan 2024 19:23:21 +0100 Subject: [PATCH] Properly implemented mirroring of skin parts and improved skin renderer class --- .../SkinPreview.Designer.cs | 1 - .../Forms/Skins-And-Textures/SkinPreview.cs | 19 +- .../generateModel.Designer.cs | 7 +- .../Forms/Skins-And-Textures/generateModel.cs | 624 +----------------- .../Skins-And-Textures/generateModel.resx | 92 +-- PCK-Studio/MainForm.cs | 5 - PCK-Studio/PckStudio.csproj | 6 +- PCK-Studio/Properties/Resources.Designer.cs | 21 +- PCK-Studio/Properties/Resources.resx | 6 +- PCK-Studio/Rendering/CubeRenderGroup.cs | 245 +++++-- PCK-Studio/Rendering/RenderGroup.cs | 18 +- PCK-Studio/Rendering/SkinRenderer.Designer.cs | 48 +- PCK-Studio/Rendering/SkinRenderer.cs | 345 +++++----- PCK-Studio/Rendering/SkinRenderer.resx | 129 ++++ .../Rendering/TextureChangingEventArgs.cs | 32 + PCK-Studio/Rendering/TextureVertex.cs | 23 +- PCK-Studio/Rendering/VertexBufferLayout.cs | 3 +- ...nFragment.glsl => skinFragmentShader.glsl} | 0 .../Resources/shader/skinVertexShader.glsl | 5 +- 19 files changed, 650 insertions(+), 979 deletions(-) create mode 100644 PCK-Studio/Rendering/SkinRenderer.resx create mode 100644 PCK-Studio/Rendering/TextureChangingEventArgs.cs rename PCK-Studio/Resources/shader/{skinFragment.glsl => skinFragmentShader.glsl} (100%) diff --git a/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.Designer.cs b/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.Designer.cs index 9b5752fc..afa3cb3a 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.Designer.cs +++ b/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.Designer.cs @@ -56,7 +56,6 @@ namespace PckStudio.Forms this.Name = "SkinPreview"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "SkinPreview"; - this.Load += new System.EventHandler(this.SkinPreview_Load); this.ResumeLayout(false); } diff --git a/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs b/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs index 76984fcb..aa1dc130 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs +++ b/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs @@ -9,26 +9,17 @@ namespace PckStudio.Forms { public partial class SkinPreview : Form { - public SkinANIM ANIM { get; set; } - - private Image _texture; - - public SkinPreview() + public SkinANIM ANIM { - InitializeComponent(); + get => ModelView.ANIM; + set => ModelView.ANIM = value; } public SkinPreview(Image texture, IEnumerable modelData) - : this() { - _texture = texture; + InitializeComponent(); ModelView.ModelData.AddRange(modelData); + ModelView.Texture = texture; } - - private void SkinPreview_Load(object sender, EventArgs e) - { - ModelView.ANIM = ANIM; - ModelView.Texture = _texture as Bitmap; - } } } diff --git a/PCK-Studio/Forms/Skins-And-Textures/generateModel.Designer.cs b/PCK-Studio/Forms/Skins-And-Textures/generateModel.Designer.cs index e6e161c7..a6b0c538 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/generateModel.Designer.cs +++ b/PCK-Studio/Forms/Skins-And-Textures/generateModel.Designer.cs @@ -35,6 +35,7 @@ System.Windows.Forms.Label label3; System.Windows.Forms.Label label7; System.Windows.Forms.Label labelTextureMappingPreview; + PckStudio.Internal.SkinANIM skinANIM1 = new PckStudio.Internal.SkinANIM(); this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); this.createToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.cloneToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -351,7 +352,6 @@ this.checkGuide.Name = "checkGuide"; this.checkGuide.Theme = MetroFramework.MetroThemeStyle.Dark; this.checkGuide.UseSelectable = true; - this.checkGuide.CheckedChanged += new System.EventHandler(this.Render); // // checkBoxArmor // @@ -359,7 +359,6 @@ this.checkBoxArmor.Name = "checkBoxArmor"; this.checkBoxArmor.Theme = MetroFramework.MetroThemeStyle.Dark; this.checkBoxArmor.UseSelectable = true; - this.checkBoxArmor.CheckedChanged += new System.EventHandler(this.Render); // // SizeXUpDown // @@ -523,9 +522,13 @@ // renderer3D1 // resources.ApplyResources(this.renderer3D1, "renderer3D1"); + this.renderer3D1.ANIM = skinANIM1; this.renderer3D1.BackColor = System.Drawing.Color.DarkGray; + this.renderer3D1.CameraTarget = ((OpenTK.Vector2)(resources.GetObject("renderer3D1.CameraTarget"))); this.renderer3D1.Name = "renderer3D1"; + this.renderer3D1.Texture = null; this.renderer3D1.VSync = true; + this.renderer3D1.TextureChanging += new System.EventHandler(this.renderer3D1_TextureChanging); // // uvPictureBox // diff --git a/PCK-Studio/Forms/Skins-And-Textures/generateModel.cs b/PCK-Studio/Forms/Skins-And-Textures/generateModel.cs index 9cf03907..df13f7aa 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/generateModel.cs +++ b/PCK-Studio/Forms/Skins-And-Textures/generateModel.cs @@ -20,7 +20,6 @@ using System.Text; namespace PckStudio.Forms { - //[Obsolete] public partial class generateModel : MetroForm { private Image _previewImage; @@ -114,17 +113,16 @@ namespace PckStudio.Forms public generateModel(PckFileData file) { - //MessageBox.Show(this, "This feature is now considered deprecated and will no longer recieve updates. A better alternative is currently under development. Use at your own risk.", "Deprecated Feature", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); InitializeComponent(); _file = file; if (_file.Size > 0) { - uvPictureBox.Image = renderer3D1.Texture = _file.GetTexture() as Bitmap; + uvPictureBox.Image = renderer3D1.Texture = _file.GetTexture(); } comboParent.Items.Clear(); comboParent.Items.AddRange(ValidModelBoxTypes); - LoadData(file.Properties); + LoadModelData(file.Properties); } private static readonly Regex sWhitespace = new Regex(@"\s+"); @@ -133,10 +131,15 @@ namespace PckStudio.Forms return sWhitespace.Replace(input, replacement); } - private void LoadData(PckFileProperties properties) + private void LoadModelData(PckFileProperties properties) { renderer3D1.ANIM = properties.GetPropertyValue("ANIM", SkinANIM.FromString); - renderer3D1.ModelData.AddRange(properties.GetProperties("BOX").Select(kv => SkinBOX.FromString(kv.Value))); + var boxProperties = properties.GetProperties("BOX"); + var data = boxProperties.Select(kv => SkinBOX.FromString(kv.Value)); + listViewBoxes.Items.AddRange(data.Select(box => new ListViewItem(box.ToString())).ToArray()); + renderer3D1.ModelData.AddRange(data); + renderer3D1.UploadModelData(); + properties.GetProperties("OFFSET").All(kv => { string[] offset = ReplaceWhitespace(kv.Value, ",").TrimEnd('\n', '\r', ' ').Split(','); if (offset.Length < 3) @@ -162,352 +165,6 @@ namespace PckStudio.Forms listViewBoxes.SelectedItems[0].BeginEdit(); } - private void Render(object sender, EventArgs e) - { - //buttonTemplate.Enabled = listViewBoxes.Items.Count == 0; - //OrganizesZLayer(); - //Bitmap bitmapModelPreview = new Bitmap(displayBox.Width, displayBox.Height); // Creates Model Display layer - //using (Graphics graphics = Graphics.FromImage(bitmapModelPreview)) - //{ - // graphics.ApplyConfig(_graphicsConfig); - // graphics.Clear(_backgroundColor); - - // float headbodyY = (displayBox.Height / 2) + 25; // 25 - // float armY = (displayBox.Height / 2) + 35; // -60; - // float legY = (displayBox.Height / 2) + 85; // -80; - // float groundLevel = (displayBox.Height / 2) + 145; - // graphics.DrawLine(Pens.White, 0, groundLevel, displayBox.Width, groundLevel); - // float renderScale = uvPictureBox.Image.Width / 64; // used for displaying larger graphics properly; 64 is the base skin width for all models - - // // Chooses Render settings based on current direction - // foreach (ListViewItem listViewItem in listViewBoxes.Items) - // { - // if (!(listViewItem.Tag is SkinBOX part)) - // continue; - // float x = displayBox.Width / 2; - // float y = 0; - - // switch (direction) - // { - // case ViewDirection.front: - // { - // //Sets X & Y based on model part class - // // listViewItem.Text -> part.Type - // // listViewItem.SubItems[1] -> part.Pos.X - // // listViewItem.SubItems[2] -> part.Pos.Y - // // listViewItem.SubItems[3] -> part.Pos.Z - // // listViewItem.SubItems[4] -> part.Size.X - // // listViewItem.SubItems[5] -> part.Size.Y - // // listViewItem.SubItems[6] -> part.Size.Z - // // listViewItem.SubItems[7] -> part.U - // // listViewItem.SubItems[8] -> part.V - // switch (part.Type) - // { - // case "HEAD": - // case "HEADWEAR": - // case "HELMET": - // y = headbodyY + int.Parse(offsetHead.Text) * 5; - // break; - // case "BODY": - // case "JACKET": - // case "CHEST": - // case "BODYARMOR": - // case "BELT": - // case "WAIST": - // y = headbodyY + int.Parse(offsetBody.Text) * 5; - // break; - - // case "ARM0": - // case "ARMARMOR0": - // case "SLEEVE0": - // case "SHOULDER0": - // x -= 25; - // y = armY + int.Parse(offsetArms.Text) * 5; - // break; - - // case "ARM1": - // case "ARMARMOR1": - // case "SLEEVE1": - // case "SHOULDER1": - // x += 25; - // y = armY + int.Parse(offsetArms.Text) * 5; - // break; - - // case "LEG0": - // case "PANTS0": - // case "SOCK0": - // case "LEGGING0": - // case "BOOT0": - // x -= 10; - // y = legY + int.Parse(offsetLegs.Text) * 5; - // break; - - // case "LEG1": - // case "PANTS1": - // case "SOCK1": - // case "LEGGING1": - // case "BOOT1": - // x += 10; - // y = legY + int.Parse(offsetLegs.Text) * 5; - // break; - // } - - // // Maps imported Texture if texture generation is disabled - // if (!generateTextureCheckBox.Checked) - // { - // RectangleF destRect = new RectangleF( - // x + part.Pos.X * 5, - // y + part.Pos.Y * 5, - // part.Size.X * 5, - // part.Size.Y * 5); - // RectangleF srcRect = new RectangleF( - // (part.UV.X + part.Size.Z) * renderScale, - // (part.UV.Y + part.Size.Z) * renderScale, - // part.Size.X * renderScale, - // part.Size.Y * renderScale); - // graphics.DrawImage(uvPictureBox.Image, destRect, srcRect, GraphicsUnit.Pixel); - // } - // else - // { - // graphics.FillRectangle(new SolidBrush(listViewItem.ForeColor), x + part.Pos.X * 5, y + part.Pos.Y * 5, part.Size.X * 5, part.Size.Y * 5); - // } - - // break; - // } - - // case ViewDirection.left: - // { - // //Sets X & Y based on model part class - // switch (part.Type) - // { - // case "HEAD": - // case "HEADWEAR": - // case "HELMET": - // y = headbodyY + int.Parse(offsetHead.Text) * 5; - // break; - // case "BODY": - // case "JACKET": - // case "CHEST": - // case "BODYARMOR": - // case "BELT": - // case "WAIST": - // y = headbodyY + int.Parse(offsetBody.Text) * 5; - // break; - - // case "ARM0": - // case "ARMARMOR0": - // case "SLEEVE0": - // case "SHOULDER0": - // y = armY + int.Parse(offsetArms.Text) * 5; - // break; - - // case "ARM1": - // case "ARMARMOR1": - // case "SLEEVE1": - // case "SHOULDER1": - // y = armY + int.Parse(offsetArms.Text) * 5; - // break; - - // case "LEG0": - // case "PANTS0": - // case "SOCK0": - // case "LEGGING0": - // case "BOOT0": - // y = legY + int.Parse(offsetLegs.Text) * 5; - // break; - - // case "LEG1": - // case "PANTS1": - // case "SOCK1": - // case "LEGGING1": - // case "BOOT1": - // y = legY + int.Parse(offsetLegs.Text) * 5; - // break; - // } - - // // Maps imported Texture if auto texture is disabled - // if (!generateTextureCheckBox.Checked) - // { - // RectangleF destRect = new RectangleF( - // x + part.Pos.Z * 5, - // y + part.Pos.Y * 5, - // part.Size.Z * 5, - // part.Size.Y * 5); - // RectangleF srcRect = new RectangleF( - // (part.UV.X + part.Size.Z + part.Size.X) * renderScale, - // (part.UV.Y + part.Size.Z) * renderScale, - // part.Size.Z * renderScale, - // part.Size.Y * renderScale); - // graphics.DrawImage(uvPictureBox.Image, destRect, srcRect, GraphicsUnit.Pixel); - // } - // else - // { - // //Draws Part - // graphics.FillRectangle(new SolidBrush(listViewItem.ForeColor), x + part.Pos.Z * 5, y + part.Pos.Y * 5, part.Size.Z * 5, part.Size.Y * 5); - // } - // bitmapModelPreview.RotateFlip(RotateFlipType.RotateNoneFlipX); - // break; - // } - - // case ViewDirection.back: - // { - // //Sets X & Y based on model part class - // switch (part.Type) - // { - // case "HEAD": - // case "HEADWEAR": - // case "HELMET": - // y = headbodyY + int.Parse(offsetHead.Text) * 5; - // break; - // case "BODY": - // case "JACKET": - // case "CHEST": - // case "BODYARMOR": - // case "BELT": - // case "WAIST": - // y = headbodyY + int.Parse(offsetBody.Text) * 5; - // break; - - // case "ARM0": - // case "ARMARMOR0": - // case "SLEEVE0": - // case "SHOULDER0": - // x -= 25; - // y = armY + int.Parse(offsetArms.Text) * 5; - // break; - - // case "ARM1": - // case "ARMARMOR1": - // case "SLEEVE1": - // case "SHOULDER1": - // x += 25; - // y = armY + int.Parse(offsetArms.Text) * 5; - // break; - - // case "LEG0": - // case "PANTS0": - // case "SOCK0": - // case "LEGGING0": - // case "BOOT0": - // x -= 10; - // y = legY + int.Parse(offsetLegs.Text) * 5; - // break; - - // case "LEG1": - // case "PANTS1": - // case "SOCK1": - // case "LEGGING1": - // case "BOOT1": - // x += 10; - // y = legY + int.Parse(offsetLegs.Text) * 5; - // break; - // } - - // //Maps imported Texture if auto texture is disabled - // if (!generateTextureCheckBox.Checked) - // { - // RectangleF destRect = new RectangleF( - // x + part.Pos.X * 5, - // y + part.Pos.Y * 5, - // part.Size.X * 5, - // part.Size.Y * 5); - // RectangleF srcRect = new RectangleF( - // (part.UV.X + part.Size.Z * 2 + part.Size.X) * renderScale, - // (part.UV.Y + part.Size.Z) * renderScale, - // part.Size.X * renderScale, - // part.Size.Y * renderScale); - // graphics.DrawImage(uvPictureBox.Image, destRect, srcRect, GraphicsUnit.Pixel); - // } - // else - // { - // //Draws Part - // graphics.FillRectangle(new SolidBrush(listViewItem.ForeColor), x + part.Pos.X * 5, y + part.Pos.Y * 5, part.Size.X * 5, part.Size.Y * 5); - // } - // bitmapModelPreview.RotateFlip(RotateFlipType.RotateNoneFlipX); - // break; - // } - - // case ViewDirection.right: - // //Sets X & Y based on model part class - // switch (part.Type) - // { - // case "HEAD": - // case "HEADWEAR": - // case "HELMET": - // y = headbodyY + int.Parse(offsetHead.Text) * 5; - // break; - // case "BODY": - // case "JACKET": - // case "CHEST": - // case "BODYARMOR": - // case "BELT": - // case "WAIST": - // y = headbodyY + int.Parse(offsetBody.Text) * 5; - // break; - - // case "ARM0": - // case "ARMARMOR0": - // case "SLEEVE0": - // case "SHOULDER0": - // y = armY + int.Parse(offsetArms.Text) * 5; - // break; - - // case "ARM1": - // case "ARMARMOR1": - // case "SLEEVE1": - // case "SHOULDER1": - // y = armY + int.Parse(offsetArms.Text) * 5; - // break; - - // case "LEG0": - // case "PANTS0": - // case "SOCK0": - // case "LEGGING0": - // case "BOOT0": - // y = legY + int.Parse(offsetLegs.Text) * 5; - // break; - - // case "LEG1": - // case "PANTS1": - // case "SOCK1": - // case "LEGGING1": - // case "BOOT1": - // y = legY + int.Parse(offsetLegs.Text) * 5; - // break; - // } - // //Maps imported Texture if auto texture is disabled - // if (!generateTextureCheckBox.Checked) - // { - // RectangleF destRect = new RectangleF( - // x + part.Pos.Z * 5, - // y + part.Pos.Y * 5, - // part.Size.Z * 5, - // part.Size.Y * 5); - // RectangleF srcRect = new RectangleF( - // (part.UV.X + part.Size.Z + part.Size.X) * renderScale, - // (part.UV.Y + part.Size.Z) * renderScale, - // part.Size.Z * renderScale, - // part.Size.Y * renderScale); - // graphics.DrawImage(uvPictureBox.Image, destRect, srcRect, GraphicsUnit.Pixel); - // } - // else - // { - // //Draws Part - // graphics.FillRectangle(new SolidBrush(listViewItem.ForeColor), x + part.Pos.Z * 5, y + part.Pos.Y * 5, part.Size.Z * 5, part.Size.Y * 5); - // } - // break; - // } - // } - - // if (checkBoxArmor.Checked) - // DrawArmorOffsets(graphics); - // // draw last to be on top - // if (checkGuide.Checked) - // DrawGuideLines(graphics); - //} - //displayBox.Image = bitmapModelPreview; - } - private void GenerateUVTextureMap() { Random rng = new Random(); @@ -535,259 +192,6 @@ namespace PckStudio.Forms uvPictureBox.Invalidate(); } - // Checks and sets Z layering - private void OrganizesZLayer() - { - throw new NotImplementedException(); - //foreach (ListViewItem listViewItem in listViewBoxes.Items) - // listViewItem.SubItems.Add("unchecked"); - - //float surfaceCenter = displayBox.Width / 2; - - //switch (direction) - //{ - // case ViewDirection.front: - // { - // foreach (ListViewItem listViewItemCurrent in listViewBoxes.Items) - // { - // if (listViewItemCurrent.SubItems[9].Text == "unchecked") - // { - // float x = 0; - // if (listViewItemCurrent.Text == "HEAD") - // x = surfaceCenter; - // else if (listViewItemCurrent.Text == "BODY") - // x = surfaceCenter; - // else if (listViewItemCurrent.Text == "ARM0") - // x = 178; - // else if (listViewItemCurrent.Text == "ARM1") - // x = 228; - // else if (listViewItemCurrent.Text == "LEG0") - // x = 193; - // else if (listViewItemCurrent.Text == "LEG1") - // x = 213; - - // bool flag = false; - // int index = listViewItemCurrent.Index; - // foreach (ListViewItem listViewItemComparing in listViewBoxes.Items) - // { - // var val1 = double.Parse(listViewItemCurrent.SubItems[3].Text) + double.Parse(listViewItemCurrent.SubItems[6].Text); - // var val2 = double.Parse(listViewItemComparing.SubItems[3].Text) + double.Parse(listViewItemComparing.SubItems[6].Text); - // if (listViewItemComparing.SubItems[9].Text == "unchecked" && - // val1 < val2) - // { - // if (listViewItemComparing.Index < listViewBoxes.Items.Count + 1) - // { - // index = listViewItemComparing.Index + 1; - // flag = true; - // } - // } - // } - // listViewItemCurrent.SubItems[9].Text = "checked"; - // if (flag) - // { - // ListViewItem listViewItem2 = (ListViewItem)listViewItemCurrent.Clone(); - // listViewBoxes.Items.Insert(index, listViewItem2); - // listViewItemCurrent.Remove(); - // } - // } - // } - // } - // break; - // case ViewDirection.right: - // { - // int checkedItems = 0; - // do - // { - // foreach (ListViewItem listViewItemCurrent in listViewBoxes.Items) - // { - // if (listViewItemCurrent.SubItems[listViewItemCurrent.SubItems.Count - 1].Text == "unchecked") - // { - // float x = 0; - // if (listViewItemCurrent.Text == "HEAD") - // x = surfaceCenter; - // else if (listViewItemCurrent.Text == "BODY") - // x = surfaceCenter; - // else if (listViewItemCurrent.Text == "ARM0") - // x = 178; - // else if (listViewItemCurrent.Text == "ARM1") - // x = 228; - // else if (listViewItemCurrent.Text == "LEG0") - // x = 193; - // else if (listViewItemCurrent.Text == "LEG1") - // x = 213; - // bool flag = false; - // int index = listViewItemCurrent.Index; - // foreach (ListViewItem listViewItem2 in listViewBoxes.Items) - // { - // if (listViewItem2.SubItems[9].Text == "unchecked") - // { - // int y = 0; - // if (listViewItem2.Text == "HEAD") - // y = (int)surfaceCenter; - // else if (listViewItem2.Text == "BODY") - // y = (int)surfaceCenter; - // else if (listViewItem2.Text == "ARM0") - // y = 178; - // else if (listViewItem2.Text == "ARM1") - // y = 228; - // else if (listViewItem2.Text == "LEG0") - // y = 193; - // else if (listViewItem2.Text == "LEG1") - // y = 213; - // if ((int)double.Parse(listViewItemCurrent.SubItems[1].Text) + (int)double.Parse(listViewItemCurrent.SubItems[4].Text) - x > (int)double.Parse(listViewItem2.SubItems[1].Text) + (int)double.Parse(listViewItem2.SubItems[4].Text) + y && listViewItem2.Index + 1 < this.listViewBoxes.Items.Count + 1) - // { - // index = listViewItem2.Index + 1; - // flag = true; - // } - // } - // } - // listViewItemCurrent.SubItems[9].Text = "checked"; - // checkedItems += 1; - // if (flag) - // { - // ListViewItem listViewItem2 = (ListViewItem)listViewItemCurrent.Clone(); - // listViewBoxes.Items.Insert(index, listViewItem2); - // if (listViewBoxes.SelectedItems.Count != 0) - // { - // //if (selected.Index == listViewItem1.Index) - // //{ - // // selected = listViewItem2; - // //} - // } - // listViewItemCurrent.Remove(); - // } - // } - // else - // { - // checkedItems += 1; - // } - // } - // } while (checkedItems < listViewBoxes.Items.Count); - // } - // break; - // case ViewDirection.back: - // { - // int checkedItems = 0; - // do - // { - // foreach (ListViewItem listViewItemCurrent in listViewBoxes.Items) - // { - // if (listViewItemCurrent.SubItems[listViewItemCurrent.SubItems.Count - 1].Text == "unchecked") - // { - // bool flag = false; - // int index = listViewItemCurrent.Index; - // foreach (ListViewItem listViewItemComparing in listViewBoxes.Items) - // { - // if (listViewItemComparing.SubItems[9].Text == "unchecked" && (int)double.Parse(listViewItemCurrent.SubItems[3].Text) + (int)double.Parse(listViewItemCurrent.SubItems[6].Text) > (int)double.Parse(listViewItemComparing.SubItems[3].Text) + (int)double.Parse(listViewItemComparing.SubItems[6].Text)) - // { - // if (listViewItemComparing.Index < listViewBoxes.Items.Count + 1) - // { - // index = listViewItemComparing.Index + 1; - // flag = true; - // } - // } - // } - // listViewItemCurrent.SubItems[9].Text = "checked"; - // checkedItems += 1; - // if (flag) - // { - // ListViewItem listViewItem2 = (ListViewItem)listViewItemCurrent.Clone(); - // listViewBoxes.Items.Insert(index, listViewItem2); - // if (listViewBoxes.SelectedItems.Count != 0) - // { - // //if (selected.Index == listViewItemCurrent.Index) - // //{ - // // selected = listViewItem2; - // //} - // } - // listViewItemCurrent.Remove(); - // } - // } - // else - // { - // checkedItems += 1; - // } - // } - // } while (checkedItems < listViewBoxes.Items.Count); - // } - // break; - // case ViewDirection.left: - // { - // int checkedItems = 0; - // do - // { - // foreach (ListViewItem listViewItemCurrent in listViewBoxes.Items) - // { - // if (listViewItemCurrent.SubItems[listViewItemCurrent.SubItems.Count - 1].Text == "unchecked") - // { - // float x = 0; - // if (listViewItemCurrent.Text == "HEAD") - // x = surfaceCenter; - // else if (listViewItemCurrent.Text == "BODY") - // x = surfaceCenter; - // else if (listViewItemCurrent.Text == "ARM0") - // x = 178; - // else if (listViewItemCurrent.Text == "ARM1") - // x = 228; - // else if (listViewItemCurrent.Text == "LEG0") - // x = 193; - // else if (listViewItemCurrent.Text == "LEG1") - // x = 213; - // bool flag = false; - // int index = listViewItemCurrent.Index; - // foreach (ListViewItem listViewItem2 in listViewBoxes.Items) - // { - // if (listViewItem2.SubItems[9].Text == "unchecked") - // { - // int y = 0; - // if (listViewItem2.Text == "HEAD") - // y = (int)surfaceCenter; - // else if (listViewItem2.Text == "BODY") - // y = (int)surfaceCenter; - // else if (listViewItem2.Text == "ARM0") - // y = 178; - // else if (listViewItem2.Text == "ARM1") - // y = 228; - // else if (listViewItem2.Text == "LEG0") - // y = 193; - // else if (listViewItem2.Text == "LEG1") - // y = 213; - // if ((int)double.Parse(listViewItemCurrent.SubItems[1].Text) + (int)double.Parse(listViewItemCurrent.SubItems[4].Text) + x < (int)double.Parse(listViewItem2.SubItems[1].Text) + (int)double.Parse(listViewItem2.SubItems[4].Text) + y && listViewItem2.Index + 1 < this.listViewBoxes.Items.Count + 1) - // { - // index = listViewItem2.Index + 1; - // flag = true; - // } - // } - // } - // listViewItemCurrent.SubItems[9].Text = "checked"; - // checkedItems += 1; - // if (flag == true) - // { - // ListViewItem listViewItem2 = (ListViewItem)listViewItemCurrent.Clone(); - // listViewBoxes.Items.Insert(index, listViewItem2); - // if (listViewBoxes.SelectedItems.Count != 0) - // { - // //if (selected.Index == listViewItem1.Index) - // //{ - // // selected = listViewItem2; - // //} - // } - // listViewItemCurrent.Remove(); - // } - // } - // else - // { - // checkedItems += 1; - // } - // } - // } while (checkedItems < listViewBoxes.Items.Count); - // } - // break; - // default: - // break; - //} - } - private void DrawGuideLines(Graphics g) { throw new NotImplementedException(); @@ -1024,7 +428,10 @@ namespace PckStudio.Forms { _file.Properties.Add("BOX", part); } - Close(); + var img = new Bitmap(renderer3D1.Size.Width, renderer3D1.Size.Height); + renderer3D1.DrawToBitmap(img, renderer3D1.Bounds); + _previewImage = img; + DialogResult = DialogResult.OK; } // Trigger Dialog to select model part/item color @@ -1352,6 +759,11 @@ namespace PckStudio.Forms } return sb.ToString(); } + + private void renderer3D1_TextureChanging(object sender, Rendering.TextureChangingEventArgs e) + { + uvPictureBox.Image = e.NewTexture; + } } class CSMJObject diff --git a/PCK-Studio/Forms/Skins-And-Textures/generateModel.resx b/PCK-Studio/Forms/Skins-And-Textures/generateModel.resx index f3549bdb..a86ee9ab 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/generateModel.resx +++ b/PCK-Studio/Forms/Skins-And-Textures/generateModel.resx @@ -184,7 +184,7 @@ $this - 31 + 29 False @@ -217,7 +217,7 @@ $this - 30 + 28 False @@ -394,7 +394,7 @@ $this - 29 + 27 True @@ -424,66 +424,6 @@ $this - 28 - - - Flat - - - NoControl - - - 554, 642 - - - 89, 23 - - - 100 - - - Rotate Right - - - rotateRightBtn - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 27 - - - Flat - - - NoControl - - - 194, 643 - - - 89, 23 - - - 101 - - - Rotate Left - - - rotateLeftBtn - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - 26 @@ -1434,23 +1374,16 @@ Top, Bottom, Left, Right + + + AAEAAAD/////AQAAAAAAAAAMAgAAAElPcGVuVEssIFZlcnNpb249My4zLjMuMCwgQ3VsdHVyZT1uZXV0 + cmFsLCBQdWJsaWNLZXlUb2tlbj1iYWQxOTlmZTg0ZWIzZGY0BQEAAAAOT3BlblRLLlZlY3RvcjICAAAA + AVgBWQAACwsCAAAAAAAAAAAAoEAL + + 194, 59 - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElPcGVuVEssIFZlcnNpb249My4zLjMuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1iYWQxOTlmZTg0ZWIzZGY0BQEAAAAOT3BlblRLLlZlY3RvcjICAAAA - AVgBWQAACwsCAAAAAAAAAAAAAAAL - - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAElPcGVuVEssIFZlcnNpb249My4zLjMuMCwgQ3VsdHVyZT1uZXV0 - cmFsLCBQdWJsaWNLZXlUb2tlbj1iYWQxOTlmZTg0ZWIzZGY0BQEAAAAOT3BlblRLLlZlY3RvcjICAAAA - AVgBWQAACwsCAAAAAAAAAAAAAAAL - - 449, 574 @@ -1461,7 +1394,7 @@ renderer3D1 - PckStudio.Rendering.Renderer3D, PCK-Studio, Version=7.0.0.0, Culture=neutral, PublicKeyToken=null + PckStudio.Rendering.SkinRenderer, PCK-Studio, Version=7.0.0.0, Culture=neutral, PublicKeyToken=null $this @@ -4014,9 +3947,6 @@ AP//AAA= - - NoControl - 1114, 1000 diff --git a/PCK-Studio/MainForm.cs b/PCK-Studio/MainForm.cs index 6d2e91cb..cabd5d12 100644 --- a/PCK-Studio/MainForm.cs +++ b/PCK-Studio/MainForm.cs @@ -427,11 +427,6 @@ namespace PckStudio public void HandleSkinFile(PckFileData file) { - var renderForm = new SkinPreview(file.GetTexture(), file.Properties.GetProperties("BOX").Select(kv => SkinBOX.FromString(kv.Value))); - renderForm.ANIM = file.Properties.GetPropertyValue("ANIM", SkinANIM.FromString); - renderForm.ShowDialog(); - return; - if (file.Properties.HasProperty("BOX")) { using generateModel generate = new generateModel(file); diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj index 72dcfa5e..fe909545 100644 --- a/PCK-Studio/PckStudio.csproj +++ b/PCK-Studio/PckStudio.csproj @@ -164,6 +164,7 @@ SkinRenderer.cs + @@ -615,6 +616,9 @@ Designer Resources.Designer.cs + + SkinRenderer.cs + @@ -684,7 +688,7 @@ - + diff --git a/PCK-Studio/Properties/Resources.Designer.cs b/PCK-Studio/Properties/Resources.Designer.cs index ba5d465b..a5516225 100644 --- a/PCK-Studio/Properties/Resources.Designer.cs +++ b/PCK-Studio/Properties/Resources.Designer.cs @@ -560,24 +560,18 @@ namespace PckStudio.Properties { ///layout(location = 0) out vec4 color; /// ///uniform sampler2D u_Texture; + ///uniform vec2 u_TexScale; /// ///in vec2 v_TexCoord; - ///in vec4 v_VertexPos; - ///in vec4 v_Color; /// ///void main() ///{ - /// vec4 texColor = texture(u_Texture, v_TexCoord); - /// // color = vec4(v_VertexPos.xyz, 1.0); - /// // color = vec4(v_TexCoord, 0.0, 1.0) * vec4(v_VertexPos.xyz, 1.0); - /// // color = vec4(v_TexCoord, 0.0, 1.0); - /// color = v_Color; - /// color = texColor; + /// color = texture(u_Texture, v_TexCoord * u_TexScale); ///};. /// - public static string skinFragment { + public static string skinFragmentShader { get { - return ResourceManager.GetString("skinFragment", resourceCulture); + return ResourceManager.GetString("skinFragmentShader", resourceCulture); } } @@ -595,21 +589,16 @@ namespace PckStudio.Properties { /// Looks up a localized string similar to #version 330 core /// ///layout(location = 0) in vec4 vertexPosition; - ///layout(location = 1) in vec4 color; - ///layout(location = 2) in vec2 texCoord; + ///layout(location = 1) in vec2 texCoord; /// ///uniform mat4 u_ViewProjection; ///uniform mat4 u_Model; /// ///out vec2 v_TexCoord; - ///out vec4 v_VertexPos; - ///out vec4 v_Color; /// ///void main() ///{ /// v_TexCoord = texCoord; - /// v_Color = color; - /// v_VertexPos = vertexPosition; /// gl_Position = u_ViewProjection * u_Model * vertexPosition; ///};. /// diff --git a/PCK-Studio/Properties/Resources.resx b/PCK-Studio/Properties/Resources.resx index 5e50a571..6d7bce1d 100644 --- a/PCK-Studio/Properties/Resources.resx +++ b/PCK-Studio/Properties/Resources.resx @@ -328,10 +328,10 @@ ..\..\ProjectLogo.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\shader\skinFragment.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 - ..\Resources\shader\skinVertexShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + ..\Resources\shader\skinFragmentShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + \ No newline at end of file diff --git a/PCK-Studio/Rendering/CubeRenderGroup.cs b/PCK-Studio/Rendering/CubeRenderGroup.cs index 5da7a714..c94a1a55 100644 --- a/PCK-Studio/Rendering/CubeRenderGroup.cs +++ b/PCK-Studio/Rendering/CubeRenderGroup.cs @@ -15,11 +15,11 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. **/ -using System; +using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; using System.Linq; -using System.Text; -using System.Threading.Tasks; using OpenTK; using OpenTK.Graphics.OpenGL; using PckStudio.Extensions; @@ -29,75 +29,212 @@ namespace PckStudio.Rendering { internal class CubeRenderGroup : RenderGroup { - private const int vertexCountPerCube = 16; - internal CubeRenderGroup(string name) - : base(name, new VertexBufferLayout().Add(3).Add(2), PrimitiveType.Quads) + private class CubeData { + internal const int vertexCountPerCube = 24; + internal bool Enabled { get; set; } = true; + internal Vector3 Position { get; set; } = Vector3.Zero; + internal Vector3 Size { get; set; } = Vector3.One; + internal Vector2 Uv { get; set; } = Vector2.Zero; + internal float Scale { get; set; } = 1f; + internal bool MirrorTexture { get; set; } = false; + internal bool FlipZMapping { get; set; } = false; + + private static uint[] indicesData = new uint[] { + // Face 1 (Back) + 0, 1, 2, 3, + // Face 2 (Front) + 4, 5, 6, 7, + // Face 3 (Top) + 8, 9, 10, 11, + // Face 4 (Bottom) + 12, 13, 14, 15, + // Face 5 (Left) + 16, 17, 18, 19, + // Face 6 (Right) + 20, 21, 22, 23, + }; + + /// + /// + /// + /// + /// + /// + /// + /// + /// Flips the bottom face mapping of the uv mapping + public CubeData(bool enabled, Vector3 position, Vector3 size, Vector2 uv, float scale, bool mirrorTexture, bool flipZMapping) + { + Enabled = enabled; + Position = position; + Size = size; + Uv = uv; + Scale = scale; + MirrorTexture = mirrorTexture; + FlipZMapping = flipZMapping; + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// Flips the bottom face mapping of the uv mapping + public CubeData(Vector3 position, Vector3 size, Vector2 uv, float scale, bool mirrorTexture, bool flipZMapping) + : this(true, position, size, uv, scale, mirrorTexture, flipZMapping) + { + } + + internal enum CubeFace + { + Back, + Front, + Top, + Bottom, + Left, + Right, + } + + internal static TextureVertex[] GetCubeVertexData(Vector3 position, Vector3 size, Vector2 uv, float scale = 1f, bool mirrorTexture = false, bool flipZMapping = false) + { + int mirror = mirrorTexture ? 1 : 0; + return + [ + // Back + new TextureVertex(new Vector3(position.X , size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z * 2 + size.X + size.X * (1 - mirror), uv.Y + size.Z + size.Y), scale), + new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z * 2 + size.X + size.X * mirror , uv.Y + size.Z + size.Y), scale), + new TextureVertex(new Vector3(size.X + position.X, position.Y , size.Z + position.Z), new Vector2(uv.X + size.Z * 2 + size.X + size.X * mirror , uv.Y + size.Z ), scale), + new TextureVertex(new Vector3(position.X , position.Y , size.Z + position.Z), new Vector2(uv.X + size.Z * 2 + size.X + size.X * (1 - mirror), uv.Y + size.Z ), scale), + + // Front + new TextureVertex(new Vector3(position.X , size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z + size.X * mirror , uv.Y + size.Z + size.Y), scale), + new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z + size.X * (1 - mirror), uv.Y + size.Z + size.Y), scale), + new TextureVertex(new Vector3(size.X + position.X, position.Y , position.Z), new Vector2(uv.X + size.Z + size.X * (1 - mirror), uv.Y + size.Z ), scale), + new TextureVertex(new Vector3(position.X , position.Y , position.Z), new Vector2(uv.X + size.Z + size.X * mirror , uv.Y + size.Z ), scale), + + // Top + new TextureVertex(new Vector3(position.X , position.Y, position.Z), new Vector2(uv.X + size.Z + size.X * mirror , uv.Y + size.Z), scale), + new TextureVertex(new Vector3(position.X , position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X * mirror , uv.Y ), scale), + new TextureVertex(new Vector3(size.X + position.X, position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X * (1 - mirror), uv.Y ), scale), + new TextureVertex(new Vector3(size.X + position.X, position.Y, position.Z), new Vector2(uv.X + size.Z + size.X * (1 - mirror), uv.Y + size.Z), scale), + + // Bottom + new TextureVertex(new Vector3(position.X + size.X, size.Y + position.Y, position.Z ), new Vector2(uv.X + size.Z + size.X + size.X * (1 - mirror), uv.Y + ( flipZMapping ? size.Z : 0)), scale), + new TextureVertex(new Vector3(position.X + size.X, size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X + size.X * (1 - mirror), uv.Y + (!flipZMapping ? size.Z : 0)), scale), + new TextureVertex(new Vector3(position.X , size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X + size.X * mirror , uv.Y + (!flipZMapping ? size.Z : 0)), scale), + new TextureVertex(new Vector3(position.X , size.Y + position.Y, position.Z ), new Vector2(uv.X + size.Z + size.X + size.X * mirror , uv.Y + ( flipZMapping ? size.Z : 0)), scale), + + // Left + new TextureVertex(new Vector3((1 - mirror) * size.X + position.X, position.Y , position.Z ), new Vector2(uv.X + size.X + size.Z , uv.Y + size.Z ), scale), + new TextureVertex(new Vector3((1 - mirror) * size.X + position.X, size.Y + position.Y, position.Z ), new Vector2(uv.X + size.X + size.Z , uv.Y + size.Z + size.Y), scale), + new TextureVertex(new Vector3((1 - mirror) * size.X + position.X, size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X + size.X + size.Z * 2, uv.Y + size.Z + size.Y), scale), + new TextureVertex(new Vector3((1 - mirror) * size.X + position.X, position.Y , size.Z + position.Z), new Vector2(uv.X + size.X + size.Z * 2, uv.Y + size.Z ), scale), + + // Right + new TextureVertex(new Vector3(mirror * size.X + position.X, position.Y , position.Z ), new Vector2(uv.X + size.Z, uv.Y + size.Z ), scale), + new TextureVertex(new Vector3(mirror * size.X + position.X, size.Y + position.Y, position.Z ), new Vector2(uv.X + size.Z, uv.Y + size.Z + size.Y), scale), + new TextureVertex(new Vector3(mirror * size.X + position.X, size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X , uv.Y + size.Z + size.Y), scale), + new TextureVertex(new Vector3(mirror * size.X + position.X, position.Y , size.Z + position.Z), new Vector2(uv.X , uv.Y + size.Z ), scale), + ]; + } + + internal TextureVertex[] GetVertices() + { + return GetCubeVertexData(Position, Size, Uv, Scale, MirrorTexture, FlipZMapping); + } + + [Conditional("DEBUG")] + internal void GetMappedTextureUv(CubeFace face) + { + var indices = GetIndices(); + var faceInices = indices.Skip((int)face * 4).Take(4).ToArray(); + var vertices = GetVertices(); + var uv0 = vertices[faceInices[0]].TexPosition; + var uv1 = vertices[faceInices[1]].TexPosition; + var uv2 = vertices[faceInices[2]].TexPosition; + var uv3 = vertices[faceInices[3]].TexPosition; + Debug.WriteLine("----------"); + Debug.WriteLine(uv0); + Debug.WriteLine(uv1); + Debug.WriteLine(uv2); + Debug.WriteLine(uv3); + } + + internal uint[] GetIndices() + { + return indicesData; + } + } + + private List cubes; + + internal CubeRenderGroup(string name) : base(name, PrimitiveType.Quads) + { + cubes = new List(5); } internal void AddSkinBox(SkinBOX skinBox) { - AddCube(skinBox.Pos.ToOpenTKVector(), skinBox.Size.ToOpenTKVector(), skinBox.UV.ToOpenTKVector(), skinBox.Scale, skinBox.Mirror); + AddCube(skinBox.Pos.ToOpenTKVector(), skinBox.Size.ToOpenTKVector(), skinBox.UV.ToOpenTKVector(), skinBox.Scale + 1f, skinBox.Mirror, skinBox.Type == "HEAD"); } - internal void AddCube(Vector3 position, Vector3 size, Vector2 uv, float scale = 0f, bool mirror = false) + internal void Clear() { - var vertexData = GetCubeVertexData(position, size, uv, scale, mirror); - - vertices.AddRange(vertexData); - - var indexStorage = new uint[] { - // Face 1 (Front) - 0, 1, 2, 3, - // Face 2 (Back) - 4, 5, 6, 7, - // Face 3 (Right) - 4, 8, 9, 7, - // Face 4 (Left) - 1, 5, 6, 2, - // Face 5 (Top) - 10, 11, 4, 5, - // Face 6 (Bottom) - 12, 13, 14, 15 - }; - indices.AddRange(indexStorage.Select(n => n + indicesOffset)); - indicesOffset += vertexCountPerCube; + cubes.Clear(); + ResetBuffers(); } - internal void ReplaceCube(int index, Vector3 position, Vector3 size, Vector2 uv, float scale = 0f, bool mirror = false) + /// + /// Submits buffered data to the underlying graphics buffer + /// + internal void Submit() { - if (index * vertexCountPerCube > vertices.Count || index < 0) + ResetBuffers(); + foreach (var cube in cubes) + { + if (!cube.Enabled) + continue; + + vertices.AddRange(cube.GetVertices()); + var indexStorage = cube.GetIndices(); + indices.AddRange(indexStorage.Select(n => n + indicesOffset)); + indicesOffset += CubeData.vertexCountPerCube; + } + } + + internal void AddCube(Vector3 position, Vector3 size, Vector2 uv, float scale = 1f, bool mirrorTexture = false, bool flipZMapping = false) + { + var cube = new CubeData(position, size, uv, scale, mirrorTexture, flipZMapping); + cubes.Add(cube); + //cube.GetMappedTextureUv(CubeData.CubeFace.Right); + } + + internal void ReplaceCube(int index, Vector3 position, Vector3 size, Vector2 uv, float scale = 1f, bool mirrorTexture = false) + { + if (!cubes.IndexInRange(index)) throw new IndexOutOfRangeException(); - vertices.InsertRange(index * vertexCountPerCube, GetCubeVertexData(position, size, uv, scale, mirror)); + var cube = cubes[index]; + cube.Position = position; + cube.Size = size; + cube.Uv = uv; + cube.Scale = scale; + cube.MirrorTexture = mirrorTexture; + Submit(); } - // TODO: add mirroring support - private TextureVertex[] GetCubeVertexData(Vector3 position, Vector3 size, Vector2 uv, float scale, bool mirror) + internal void SetEnabled(int index, bool enable) { - return new TextureVertex[] - { - new TextureVertex(new Vector3(position.X , size.Y + position.Y, -(size.Z + position.Z)) * (scale + 1f), new Vector2(uv.X + size.Z * 2 + size.X * 2, uv.Y + size.Z)), - new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, -(size.Z + position.Z)) * (scale + 1f), new Vector2(uv.X + size.Z * 2 + size.X, uv.Y + size.Z)), - new TextureVertex(new Vector3(size.X + position.X, position.Y , -(size.Z + position.Z)) * (scale + 1f), new Vector2(uv.X + size.Z * 2 + size.X, uv.Y + size.Z + size.Y)), - new TextureVertex(new Vector3(position.X , position.Y , -(size.Z + position.Z)) * (scale + 1f), new Vector2(uv.X + size.Z * 2 + size.X * 2, uv.Y + size.Z + size.Y)), + if (!cubes.IndexInRange(index)) + throw new IndexOutOfRangeException(); - new TextureVertex(new Vector3(position.X , size.Y + position.Y, -position.Z ) * (scale + 1f), new Vector2(uv.X + size.Z, uv.Y + size.Z)), - new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, -position.Z ) * (scale + 1f), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z)), - new TextureVertex(new Vector3(size.X + position.X, position.Y , -position.Z ) * (scale + 1f), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z + size.Y)), - new TextureVertex(new Vector3(position.X , position.Y , -position.Z ) * (scale + 1f), new Vector2(uv.X + size.Z, uv.Y + size.Z + size.Y)), - - new TextureVertex(new Vector3(position.X , size.Y + position.Y, -(size.Z + position.Z)) * (scale + 1f), new Vector2(uv.X, uv.Y + size.Z)), - new TextureVertex(new Vector3(position.X , position.Y , -(size.Z + position.Z)) * (scale + 1f), new Vector2(uv.X, uv.Y + size.Z + size.Y)), - new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, -(size.Z + position.Z)) * (scale + 1f), new Vector2(uv.X + size.Z + size.X, uv.Y)), - new TextureVertex(new Vector3(position.X , size.Y + position.Y, -(size.Z + position.Z)) * (scale + 1f), new Vector2(uv.X + size.Z, uv.Y)), - - new TextureVertex(new Vector3(size.X + position.X, position.Y , -position.Z ) * (scale + 1f), new Vector2(uv.X + size.Z + size.X * 2, uv.Y)), - new TextureVertex(new Vector3(position.X , position.Y , -position.Z ) * (scale + 1f), new Vector2(uv.X + size.Z + size.X, uv.Y)), - new TextureVertex(new Vector3(position.X , position.Y , -(size.Z + position.Z)) * (scale + 1f), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z)), - new TextureVertex(new Vector3(size.X + position.X, position.Y , -(size.Z + position.Z)) * (scale + 1f), new Vector2(uv.X + size.Z + size.X * 2, uv.Y + size.Z)), - }; + cubes[index].Enabled = enable; + Submit(); } } } diff --git a/PCK-Studio/Rendering/RenderGroup.cs b/PCK-Studio/Rendering/RenderGroup.cs index 77bc294c..a15873f9 100644 --- a/PCK-Studio/Rendering/RenderGroup.cs +++ b/PCK-Studio/Rendering/RenderGroup.cs @@ -15,38 +15,44 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. **/ -using System; +using System; using System.Collections.Generic; using System.Runtime.InteropServices; using OpenTK.Graphics.OpenGL; namespace PckStudio.Rendering { - internal class RenderGroup where T : struct + internal class RenderGroup where T : struct, IVertexLayout { internal string Name { get; } - internal static int SizeInBytes = Marshal.SizeOf(); + internal readonly int SizeInBytes = Marshal.SizeOf(); protected List vertices; protected List indices; protected uint indicesOffset; - private VertexArray vertexArray; private VertexBuffer vertexBuffer; private IndexBuffer indexBuffer; private readonly VertexBufferLayout _layout; private readonly PrimitiveType drawType; - internal RenderGroup(string name, VertexBufferLayout layout, PrimitiveType type) + internal RenderGroup(string name, PrimitiveType type) { Name = name; drawType = type; indicesOffset = 0; vertices = new List(10); indices = new List(10); - _layout = layout; + _layout = new T().GetLayout(); + } + + protected void ResetBuffers() + { + indicesOffset = 0; + vertices.Clear(); + indices.Clear(); } internal RenderBuffer GetRenderBuffer() diff --git a/PCK-Studio/Rendering/SkinRenderer.Designer.cs b/PCK-Studio/Rendering/SkinRenderer.Designer.cs index 07aaebae..90b82221 100644 --- a/PCK-Studio/Rendering/SkinRenderer.Designer.cs +++ b/PCK-Studio/Rendering/SkinRenderer.Designer.cs @@ -34,27 +34,51 @@ namespace PckStudio.Rendering [DebuggerStepThrough()] private void InitializeComponent() { - components = new System.ComponentModel.Container(); - moveTimer = new System.Windows.Forms.Timer(components); - animationTimer = new System.Windows.Forms.Timer(components); - moveTimer.Tick += new EventHandler(moveTimer_Tick); - animationTimer.Tick += new EventHandler(animationTimer_Tick); - SuspendLayout(); + this.components = new System.ComponentModel.Container(); + this.moveTimer = new System.Windows.Forms.Timer(this.components); + this.animationTimer = new System.Windows.Forms.Timer(this.components); + this.reToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.contextMenuStrip1.SuspendLayout(); + this.SuspendLayout(); // // moveTimer // - moveTimer.Enabled = true; - moveTimer.Interval = 10; + this.moveTimer.Enabled = true; + this.moveTimer.Interval = 10; + this.moveTimer.Tick += new System.EventHandler(this.moveTimer_Tick); // // animationTimer // - animationTimer.Enabled = false; - animationTimer.Interval = 50; - Name = "Renderer3D"; - ResumeLayout(false); + this.animationTimer.Interval = 50; + this.animationTimer.Tick += new System.EventHandler(this.animationTimer_Tick); + // + // reToolStripMenuItem + // + this.reToolStripMenuItem.Name = "reToolStripMenuItem"; + this.reToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.reToolStripMenuItem.Text = "Re-Init"; + this.reToolStripMenuItem.Click += new System.EventHandler(this.reInitToolStripMenuItem_Click); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.reToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(181, 48); + // + // SkinRenderer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.Name = "SkinRenderer"; + this.contextMenuStrip1.ResumeLayout(false); + this.ResumeLayout(false); + } private System.Windows.Forms.Timer moveTimer; private System.Windows.Forms.Timer animationTimer; + private System.Windows.Forms.ToolStripMenuItem reToolStripMenuItem; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; } } diff --git a/PCK-Studio/Rendering/SkinRenderer.cs b/PCK-Studio/Rendering/SkinRenderer.cs index 6d1021d7..4e5ab7e0 100644 --- a/PCK-Studio/Rendering/SkinRenderer.cs +++ b/PCK-Studio/Rendering/SkinRenderer.cs @@ -15,12 +15,9 @@ * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. **/ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using OpenTK; using PckStudio.Internal; using PckStudio.Extensions; @@ -31,8 +28,6 @@ using System.Drawing; using System.Runtime.InteropServices; using PckStudio.Properties; using PckStudio.Forms.Editor; -using System.Windows.Media.Imaging; -using System.Xml.Linq; namespace PckStudio.Rendering { @@ -44,10 +39,33 @@ namespace PckStudio.Rendering /// The visible Texture [Description("The current Texture")] [Category("Appearance")] - public Bitmap Texture { get; set; } + public Image Texture + { + get => _texture; + set + { + var args = new TextureChangingEventArgs(value); + Events[nameof(TextureChanging)]?.DynamicInvoke(this, args); + if (!args.Cancel) + { + RenderTexture = _texture = value; + } + } + } + + [Description("Event that gets fired when the Texture is changing")] + [Category("Property Chnaged")] + [Browsable(true)] + public event EventHandler TextureChanging + { + add => Events.AddHandler(nameof(TextureChanging), value); + remove => Events.RemoveHandler(nameof(TextureChanging), value); + } + [Description("Anim flags for special effects applied to the skin")] [Category("Appearance")] + [Browsable(true)] public SkinANIM ANIM { get => _anim; @@ -92,20 +110,21 @@ namespace PckStudio.Rendering } private Vector2 UvTranslation = new Vector2(1f / 64); - private const float OverlayScale = 0.1f; + private const float OverlayScale = 1.12f; - private bool IsLeftMouseDown; - private bool IsRightMouseDown; + private bool _IsLeftMouseDown; + private bool _IsRightMouseDown; - private Bitmap RenderTexture + private Image RenderTexture { set { - if (HasValidContext && skinShader is not null) + if (HasValidContext && _skinShader is not null) { + UvTranslation = value.Width == value.Height ? new Vector2(1f / 64) : new Vector2(1f / 64, 1f / 32); var texture = new Texture2D(value); texture.Bind(0); - skinShader.SetUniform1("u_Texture", 0); + _skinShader.SetUniform1("u_Texture", 0); Refresh(); } } @@ -124,36 +143,33 @@ namespace PckStudio.Rendering } } private Point PreviousMouseLocation; - private Point MouseLoc; + private Point CurrentMouseLocation; - private Shader skinShader; + private Shader _skinShader; private SkinANIM _anim; + private Image _texture; private Dictionary additionalModelRenderGroups; - private CubeRenderGroup head; - private CubeRenderGroup headOverlay; private CubeRenderGroup body; - private CubeRenderGroup bodyOverlay; private CubeRenderGroup rightArm; - private CubeRenderGroup rightArmOverlay; private CubeRenderGroup leftArm; - private CubeRenderGroup leftArmOverlay; private CubeRenderGroup rightLeg; - private CubeRenderGroup rightLegOverlay; private CubeRenderGroup leftLeg; - private CubeRenderGroup leftLegOverlay; private float animationRot; private float animationRotStep = 1f; +#if DEBUG + private bool showWireFrame = false; +#endif + public SkinRenderer() : base() { InitializeComponent(); InitializeCamera(); InitializeSkinData(); - _anim = new SkinANIM(); // use backing field to not raise OnANIMUpdate additionalModelRenderGroups = new Dictionary(6) { { "HEAD", new CubeRenderGroup("HEAD") }, @@ -184,41 +200,35 @@ namespace PckStudio.Rendering private void InitializeSkinData() { - head = new CubeRenderGroup("Head"); - head.AddCube(new(-4, -8, -4), new(8, 8, 8), new(0, 0)); + head ??= new CubeRenderGroup("Head"); + head.AddCube(new(-4, -8, -4), new(8, 8, 8), new(0, 0), flipZMapping: true); + head.AddCube(new(-4, -8, -4), new(8, 8, 8), new(32, 0), flipZMapping: true, scale: OverlayScale); + head.Submit(); - headOverlay = new CubeRenderGroup("Head overlay"); - headOverlay.AddCube(new(-4, -8, -4), new(8, 8, 8), new(32, 0), scale: OverlayScale); - - body = new CubeRenderGroup("Body"); + body ??= new CubeRenderGroup("Body"); body.AddCube(new(-4, 0, -2), new(8, 12, 4), new(16, 16)); + body.AddCube(new(-4, 0, -2), new(8, 12, 4), new(16, 32), scale: OverlayScale); + body.Submit(); - bodyOverlay = new CubeRenderGroup("Body overlay"); - bodyOverlay.AddCube(new(-4, 0, -2), new(8, 12, 4), new(16, 32), scale: OverlayScale); - - rightArm = new CubeRenderGroup("Right arm"); + rightArm ??= new CubeRenderGroup("Right arm"); rightArm.AddCube(new(-3, -2, -2), new(4, 12, 4), new(40, 16)); + rightArm.AddCube(new(-3, -2, -2), new(4, 12, 4), new(40, 32), scale: OverlayScale); + rightArm.Submit(); - rightArmOverlay = new CubeRenderGroup("Right arm overlay"); - rightArmOverlay.AddCube(new(-3, -2, -2), new(4, 12, 4), new(40, 32), scale: OverlayScale); - - leftArm = new CubeRenderGroup("Left arm"); + leftArm ??= new CubeRenderGroup("Left arm"); leftArm.AddCube(new(-1, -2, -2), new(4, 12, 4), new(32, 48)); + leftArm.AddCube(new(-1, -2, -2), new(4, 12, 4), new(48, 48), scale: OverlayScale); + leftArm.Submit(); - leftArmOverlay = new CubeRenderGroup("Left arm overlay"); - leftArmOverlay.AddCube(new(-1, -2, -2), new(4, 12, 4), new(48, 48), scale: OverlayScale); - - rightLeg = new CubeRenderGroup("Right leg"); + rightLeg ??= new CubeRenderGroup("Right leg"); rightLeg.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 16)); + rightLeg.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 32), scale: OverlayScale); + rightLeg.Submit(); - rightLegOverlay = new CubeRenderGroup("Right leg overlay"); - rightLegOverlay.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 32), scale: OverlayScale); - - leftLeg = new CubeRenderGroup("Left leg"); + leftLeg ??= new CubeRenderGroup("Left leg"); leftLeg.AddCube(new(-2, 0, -2), new(4, 12, 4), new(16, 48)); - - leftLegOverlay = new CubeRenderGroup("Left leg overlay"); - leftLegOverlay.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 48), scale: OverlayScale); + leftLeg.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 48), scale: OverlayScale); + leftLeg.Submit(); } protected override void OnLoad(EventArgs e) @@ -226,30 +236,33 @@ namespace PckStudio.Rendering base.OnLoad(e); if (DesignMode) return; + + // use backing field to not raise OnANIMUpdate + _anim ??= new SkinANIM(); MakeCurrent(); Trace.TraceInformation(GL.GetString(StringName.Version)); GL.DebugMessageCallback(GLDebugMessage, IntPtr.Zero); - skinShader = Shader.Create(Resources.skinVertexShader, Resources.skinFragment); - skinShader.Bind(); + _skinShader = Shader.Create(Resources.skinVertexShader, Resources.skinFragmentShader); + _skinShader.Bind(); Texture ??= Resources.classic_template; RenderTexture = Texture; - foreach (var item in ModelData) - { - AddCustomModelPart(item); - } + UploadModelData(); GLErrorCheck(); } - public void Reload() + public void UploadModelData() { - additionalModelRenderGroups.Clear(); + foreach (var group in additionalModelRenderGroups.Values) + { + group.Clear(); + } foreach (var item in ModelData) { AddCustomModelPart(item); @@ -277,12 +290,21 @@ namespace PckStudio.Rendering switch (keyData) { case Keys.Escape: - if (IsMouseHidden || IsLeftMouseDown || IsRightMouseDown) + if (IsMouseHidden || _IsLeftMouseDown || _IsRightMouseDown) { - IsMouseHidden = IsRightMouseDown = IsLeftMouseDown = false; + IsMouseHidden = _IsRightMouseDown = _IsLeftMouseDown = false; Cursor.Position = PreviousMouseLocation; } - break; + var point = new Point(Parent.Location.X + Location.X, Parent.Location.Y + Location.Y); + contextMenuStrip1.Show(point); + return true; +#if DEBUG + case Keys.W: + GL.PolygonMode(MaterialFace.FrontAndBack, showWireFrame ? PolygonMode.Line : PolygonMode.Fill); + Refresh(); + showWireFrame = !showWireFrame; + return true; +#endif case Keys.R: GlobalModelRotation = Vector2.Zero; CameraTarget = Vector2.Zero; @@ -295,16 +317,15 @@ namespace PckStudio.Rendering }; if (fileDialog.ShowDialog() == DialogResult.OK) { - RenderTexture = Texture = Image.FromFile(fileDialog.FileName) as Bitmap; - } - return true; - case Keys.F3: - foreach (var item in ModelData) - { - Debug.WriteLine(item); + Texture = Image.FromFile(fileDialog.FileName); } return true; case Keys.A: + if (IsMouseHidden || _IsLeftMouseDown || _IsRightMouseDown) + { + IsMouseHidden = _IsRightMouseDown = _IsLeftMouseDown = false; + Cursor.Position = PreviousMouseLocation; + } { using var animeditor = new ANIMEditor(ANIM); if (animeditor.ShowDialog() == DialogResult.OK) @@ -320,15 +341,29 @@ namespace PckStudio.Rendering private void OnANIMUpdate() { + head.SetEnabled(0, !ANIM.GetFlag(SkinAnimFlag.HEAD_DISABLED)); + head.SetEnabled(1, !ANIM.GetFlag(SkinAnimFlag.HEAD_OVERLAY_DISABLED)); + + body.SetEnabled(0, !ANIM.GetFlag(SkinAnimFlag.BODY_DISABLED)); + rightArm.SetEnabled(0, !ANIM.GetFlag(SkinAnimFlag.RIGHT_ARM_DISABLED)); + leftArm.SetEnabled(0, !ANIM.GetFlag(SkinAnimFlag.LEFT_ARM_DISABLED)); + rightLeg.SetEnabled(0, !ANIM.GetFlag(SkinAnimFlag.RIGHT_LEG_DISABLED)); + leftLeg.SetEnabled(0, !ANIM.GetFlag(SkinAnimFlag.LEFT_LEG_DISABLED)); + bool slim = ANIM.GetFlag(SkinAnimFlag.SLIM_MODEL); if (slim || ANIM.GetFlag(SkinAnimFlag.RESOLUTION_64x64)) { - int slimValue = slim ? 3 : 4; UvTranslation = new Vector2(1f / 64); + body.SetEnabled(1, !ANIM.GetFlag(SkinAnimFlag.BODY_OVERLAY_DISABLED)); + rightArm.SetEnabled(1, !ANIM.GetFlag(SkinAnimFlag.RIGHT_ARM_OVERLAY_DISABLED)); + leftArm.SetEnabled(1, !ANIM.GetFlag(SkinAnimFlag.LEFT_ARM_OVERLAY_DISABLED)); + rightLeg.SetEnabled(1, !ANIM.GetFlag(SkinAnimFlag.RIGHT_LEG_OVERLAY_DISABLED)); + leftLeg.SetEnabled(1, !ANIM.GetFlag(SkinAnimFlag.LEFT_LEG_OVERLAY_DISABLED)); + + int slimValue = slim ? 3 : 4; rightArm.ReplaceCube(0, new(-3, -2, -2), new(slimValue, 12, 4), new(40, 16)); - rightArmOverlay.ReplaceCube(0, new(-3, -2, -2), new(slimValue, 12, 4), new(40, 32), scale: OverlayScale); leftArm.ReplaceCube(0, new(-1, -2, -2), new(slimValue, 12, 4), new(32, 48)); - leftArmOverlay.ReplaceCube(0, new(-1, -2, -2), new(slimValue, 12, 4), new(48, 48), scale: OverlayScale); + leftArm.ReplaceCube(1, new(-1, -2, -2), new(slimValue, 12, 4), new(48, 48), scale: OverlayScale); rightLeg.ReplaceCube(0, new(-2, 0, -2), new(4, 12, 4), new(0, 16)); leftLeg.ReplaceCube(0, new(-2, 0, -2), new(4, 12, 4), new(16, 48)); @@ -336,11 +371,12 @@ namespace PckStudio.Rendering } UvTranslation = new Vector2(1f / 64, 1f / 32); rightArm.ReplaceCube(0, new(-3, -2, -2), new(4, 12, 4), new(40, 16)); - leftArm.ReplaceCube(0, new(-1, -2, -2), new(4, 12, 4), new(40, 16)); + leftArm.ReplaceCube(0, new(-1, -2, -2), new(4, 12, 4), new(40, 16), mirrorTexture: true); rightLeg.ReplaceCube(0, new(-2, 0, -2), new(4, 12, 4), new(0, 16)); - leftLeg.ReplaceCube(0, new(-2, 0, -2), new(4, 12, 4), new(0, 16)); - rightArmOverlay.ReplaceCube(0, new(-3, -2, -2), new(4, 12, 4), new(40, 32), scale: OverlayScale); - leftArmOverlay.ReplaceCube(0, new(-1, -2, -2), new(4, 12, 4), new(40, 32), scale: OverlayScale); + leftLeg.ReplaceCube(0, new(-2, 0, -2), new(4, 12, 4), new(0, 16), mirrorTexture: true); + + rightArm.SetEnabled(1, false); + leftArm.SetEnabled(1, false); } protected override void OnPaint(PaintEventArgs e) @@ -356,8 +392,8 @@ namespace PckStudio.Rendering camera.Update(Size.Width / (float)Size.Height); var viewProjection = camera.GetViewProjection(); - skinShader.SetUniformMat4("u_ViewProjection", ref viewProjection); - skinShader.SetUniform2("u_TexScale", UvTranslation); + _skinShader.SetUniformMat4("u_ViewProjection", ref viewProjection); + _skinShader.SetUniform2("u_TexScale", UvTranslation); GL.Viewport(Size); @@ -375,9 +411,9 @@ namespace PckStudio.Rendering GL.Enable(EnableCap.AlphaTest); // Enable transparent GL.AlphaFunc(AlphaFunction.Greater, 0.4f); - Matrix4 modelMatrix = - Matrix4.CreateFromAxisAngle(-Vector3.UnitX, MathHelper.DegreesToRadians(GlobalModelRotation.X)) - * Matrix4.CreateFromAxisAngle(Vector3.UnitY, MathHelper.DegreesToRadians(GlobalModelRotation.Y)); + Matrix4 modelMatrix = Matrix4.CreateTranslation(0f, 4f, 0f) + * Matrix4.CreateFromAxisAngle(-Vector3.UnitX, MathHelper.DegreesToRadians(GlobalModelRotation.X)) + * Matrix4.CreateFromAxisAngle( Vector3.UnitY, MathHelper.DegreesToRadians(GlobalModelRotation.Y)); RenderSkin(modelMatrix); @@ -394,96 +430,52 @@ namespace PckStudio.Rendering private void RenderSkin(Matrix4 modelMatrix) { - if (!ANIM.GetFlag(SkinAnimFlag.HEAD_DISABLED)) - { - RenderSkinPart(head.GetRenderBuffer(), new Vector3(0f, 16f, 0f), modelMatrix); - } - - if (!ANIM.GetFlag(SkinAnimFlag.HEAD_OVERLAY_DISABLED)) - { - RenderSkinPart(headOverlay.GetRenderBuffer(), new Vector3(0f, 16f + OverlayScale, 0f), modelMatrix); - } - - if (!ANIM.GetFlag(SkinAnimFlag.BODY_DISABLED)) - { - RenderSkinPart(body.GetRenderBuffer(), new Vector3(0f, -4f, 0f), modelMatrix); - } - bool slimModel = ANIM.GetFlag(SkinAnimFlag.SLIM_MODEL); - var extraRightRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitY, MathHelper.DegreesToRadians(animationRot)); - var extraLeftRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitY, MathHelper.DegreesToRadians(-animationRot)); - var translationRight = new Vector3(slimModel ? -4f : -5f, -2f, 0f); - var translationLeft = new Vector3(5f, -2f, 0f); + + const float rotationAngle = 2.5f; + var extraLegRightRotation = Matrix4.Identity; + var extraLegLeftRotation = Matrix4.Identity; + var extraArmRightRotation = Matrix4.Identity; + var extraArmLeftRotation = Matrix4.Identity; + + if (!ANIM.GetFlag(SkinAnimFlag.STATIC_ARMS)) + { + extraArmRightRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitZ, MathHelper.DegreesToRadians(-rotationAngle)); + extraArmLeftRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitZ, MathHelper.DegreesToRadians(rotationAngle)); + } + + if (!ANIM.GetFlag(SkinAnimFlag.STATIC_LEGS)) + { + extraLegRightRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-rotationAngle)); + extraLegLeftRotation = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(rotationAngle)); + } + if (ANIM.GetFlag(SkinAnimFlag.ZOMBIE_ARMS)) { - extraRightRotation *= Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-90f)); - extraLeftRotation *= Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-90f)); - translationRight.Yz = translationLeft.Yz = new Vector2(-8f, 6f); + var rotation = Matrix4.CreateFromAxisAngle(Vector3.UnitX, MathHelper.DegreesToRadians(-90f)); + extraArmRightRotation *= rotation; + extraArmLeftRotation *= rotation; } - if (!ANIM.GetFlag(SkinAnimFlag.RIGHT_ARM_DISABLED)) - { - RenderSkinPart(rightArm.GetRenderBuffer(), translationRight, extraRightRotation * modelMatrix); - } - - if (!ANIM.GetFlag(SkinAnimFlag.LEFT_ARM_DISABLED)) - { - RenderSkinPart(leftArm.GetRenderBuffer(), translationLeft, extraLeftRotation * modelMatrix); - } - - if (!ANIM.GetFlag(SkinAnimFlag.RIGHT_LEG_DISABLED)) - { - RenderSkinPart(rightLeg.GetRenderBuffer(), new Vector3(-2f, -16f, 0f), modelMatrix); - } - - if (!ANIM.GetFlag(SkinAnimFlag.LEFT_LEG_DISABLED)) - { - RenderSkinPart(leftLeg.GetRenderBuffer(), new Vector3(2f, -16f, 0f), modelMatrix); - } - - if (ANIM.GetFlag(SkinAnimFlag.RESOLUTION_64x64) || slimModel) - { - if (!ANIM.GetFlag(SkinAnimFlag.BODY_OVERLAY_DISABLED)) - { - RenderSkinPart(bodyOverlay.GetRenderBuffer(), new Vector3(0f, -4f + OverlayScale, 0f), modelMatrix); + RenderSkinPart(head.GetRenderBuffer() , new Vector3(0f, 0f, 0f), modelMatrix); + RenderSkinPart(body.GetRenderBuffer() , new Vector3(0f, 0f, 0f), modelMatrix); + RenderSkinPart(rightArm.GetRenderBuffer(), new Vector3(slimModel ? -4f : -5f, -2f, 0f), extraArmRightRotation * modelMatrix); + RenderSkinPart(leftArm.GetRenderBuffer() , new Vector3(5f, -2f, 0f) , extraArmLeftRotation * modelMatrix); + RenderSkinPart(rightLeg.GetRenderBuffer(), new Vector3(-2f, -12f, 0f), extraLegRightRotation * modelMatrix); + RenderSkinPart(leftLeg.GetRenderBuffer() , new Vector3( 2f, -12f, 0f), extraLegLeftRotation * modelMatrix); } - if (!ANIM.GetFlag(SkinAnimFlag.RIGHT_ARM_OVERLAY_DISABLED)) - { - RenderSkinPart(rightArmOverlay.GetRenderBuffer(), translationRight, extraRightRotation * modelMatrix); - } - - if (!ANIM.GetFlag(SkinAnimFlag.LEFT_ARM_OVERLAY_DISABLED)) - { - RenderSkinPart(leftArmOverlay.GetRenderBuffer(), translationLeft, extraLeftRotation * modelMatrix); - } - - if (!ANIM.GetFlag(SkinAnimFlag.RIGHT_LEG_OVERLAY_DISABLED)) - { - RenderSkinPart(rightLegOverlay.GetRenderBuffer(), new Vector3(-2f, -16f, 0f), modelMatrix); - } - - if (!ANIM.GetFlag(SkinAnimFlag.LEFT_LEG_OVERLAY_DISABLED)) - { - RenderSkinPart(leftLegOverlay.GetRenderBuffer(), new Vector3(2f, -16f, 0f), modelMatrix); - } - } - } - private void RenderSkinPart(RenderBuffer buffer, Vector3 translation, Matrix4 rotation) { var transform = Matrix4.CreateTranslation(translation); var model = transform * rotation; - skinShader.SetUniformMat4("u_Model", ref model); - Renderer.Draw(skinShader, buffer); + _skinShader.SetUniformMat4("u_Model", ref model); + Renderer.Draw(_skinShader, buffer); } private void RenderAdditionalModelData(string name, Vector3 translation, Matrix4 rotation) { - var transform = Matrix4.CreateTranslation(translation); - var model = transform * rotation; - skinShader.SetUniformMat4("u_Model", ref model); - Renderer.Draw(skinShader, additionalModelRenderGroups[name].GetRenderBuffer()); + RenderSkinPart(additionalModelRenderGroups[name].GetRenderBuffer(), translation, rotation); } protected override void OnMouseWheel(MouseEventArgs e) @@ -494,7 +486,8 @@ namespace PckStudio.Rendering protected override void OnMouseDown(MouseEventArgs e) { - if (!IsLeftMouseDown && e.Button == MouseButtons.Left) + base.OnMouseDown(e); + if (!_IsLeftMouseDown && e.Button == MouseButtons.Left) { // If the ray didn't hit the model then rotate the model PreviousMouseLocation = Cursor.Position; // Store the old mouse position to reset it when the action is over @@ -502,18 +495,18 @@ namespace PckStudio.Rendering { IsMouseHidden = true; } - MouseLoc = Cursor.Position; // Store the current mouse position to use it for the rotate action - IsLeftMouseDown = true; + CurrentMouseLocation = Cursor.Position; // Store the current mouse position to use it for the rotate action + _IsLeftMouseDown = true; } - else if (!IsRightMouseDown && e.Button == MouseButtons.Right) + else if (!_IsRightMouseDown && e.Button == MouseButtons.Right) { PreviousMouseLocation = Cursor.Position; // Store the old mouse position to reset it when the action is over if (!IsMouseHidden) // Hide the mouse { IsMouseHidden = true; } - MouseLoc = Cursor.Position; // Store the current mouse position to use it for the move action - IsRightMouseDown = true; + CurrentMouseLocation = Cursor.Position; // Store the current mouse position to use it for the move action + _IsRightMouseDown = true; } } @@ -522,8 +515,9 @@ namespace PckStudio.Rendering if (IsMouseHidden) { Cursor.Position = PreviousMouseLocation; - IsMouseHidden = IsLeftMouseDown = IsRightMouseDown = false; + IsMouseHidden = _IsLeftMouseDown = _IsRightMouseDown = false; } + base.OnMouseUp(e); } private void animationTimer_Tick(object sender, EventArgs e) @@ -547,26 +541,41 @@ namespace PckStudio.Rendering } // Rotate the model - if (IsLeftMouseDown) + if (_IsLeftMouseDown) { - float rotationYDelta = (float)Math.Round((Cursor.Position.X - MouseLoc.X) * 0.5f); - float rotationXDelta = (float)Math.Round(-(Cursor.Position.Y - MouseLoc.Y) * 0.5f); + float rotationYDelta = (float)Math.Round((Cursor.Position.X - CurrentMouseLocation.X) * 0.5f); + float rotationXDelta = (float)Math.Round(-(Cursor.Position.Y - CurrentMouseLocation.Y) * 0.5f); GlobalModelRotation += new Vector2(rotationXDelta, rotationYDelta); Refresh(); Cursor.Position = new Point((int)Math.Round(Screen.PrimaryScreen.Bounds.Width / 2d), (int)Math.Round(Screen.PrimaryScreen.Bounds.Height / 2d)); - MouseLoc = Cursor.Position; + CurrentMouseLocation = Cursor.Position; return; } // Move the model - if (IsRightMouseDown) + if (_IsRightMouseDown) { - float deltaX = -(Cursor.Position.X - MouseLoc.X) * 0.05f / (float)MathHelper.DegreesToRadians(camera.Fov); - float deltaY = (Cursor.Position.Y - MouseLoc.Y) * 0.05f / (float)MathHelper.DegreesToRadians(camera.Fov); + float deltaX = -(Cursor.Position.X - CurrentMouseLocation.X) * 0.05f / (float)MathHelper.DegreesToRadians(camera.Fov); + float deltaY = (Cursor.Position.Y - CurrentMouseLocation.Y) * 0.05f / (float)MathHelper.DegreesToRadians(camera.Fov); CameraTarget += new Vector2(deltaX, deltaY); Refresh(); Cursor.Position = new Point((int)Math.Round(Screen.PrimaryScreen.Bounds.Width / 2d), (int)Math.Round(Screen.PrimaryScreen.Bounds.Height / 2d)); - MouseLoc = Cursor.Position; + CurrentMouseLocation = Cursor.Position; } + } + + private void reInitToolStripMenuItem_Click(object sender, EventArgs e) + { + head.Clear(); + body.Clear(); + rightArm.Clear(); + leftArm.Clear(); + rightLeg.Clear(); + leftLeg.Clear(); + + InitializeSkinData(); + + OnANIMUpdate(); + Refresh(); } } } \ No newline at end of file diff --git a/PCK-Studio/Rendering/SkinRenderer.resx b/PCK-Studio/Rendering/SkinRenderer.resx new file mode 100644 index 00000000..986e3e38 --- /dev/null +++ b/PCK-Studio/Rendering/SkinRenderer.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 131, 17 + + + 269, 17 + + \ No newline at end of file diff --git a/PCK-Studio/Rendering/TextureChangingEventArgs.cs b/PCK-Studio/Rendering/TextureChangingEventArgs.cs new file mode 100644 index 00000000..f04469f9 --- /dev/null +++ b/PCK-Studio/Rendering/TextureChangingEventArgs.cs @@ -0,0 +1,32 @@ +/* Copyright (c) 2023-present miku-666 + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1.The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. +**/ +using System.ComponentModel; +using System.Drawing; + +namespace PckStudio.Rendering +{ + public class TextureChangingEventArgs : CancelEventArgs + { + public Image NewTexture { get; set; } + + public TextureChangingEventArgs(Image newTexture) : base() + { + NewTexture = newTexture; + } + } +} \ No newline at end of file diff --git a/PCK-Studio/Rendering/TextureVertex.cs b/PCK-Studio/Rendering/TextureVertex.cs index 413b797c..bb62ecc5 100644 --- a/PCK-Studio/Rendering/TextureVertex.cs +++ b/PCK-Studio/Rendering/TextureVertex.cs @@ -10,23 +10,32 @@ using OpenTK.Graphics; namespace PckStudio.Rendering { - [StructLayout(LayoutKind.Sequential, Pack = 4)] + [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 20)] internal struct TextureVertex : IVertexLayout { - public static int SizeInBytes = Marshal.SizeOf(typeof(TextureVertex)); + internal Vector3 Position { get; set; } + internal Vector2 TexPosition { get; set; } + internal float Scale { get; set; } public TextureVertex(Vector3 position, Vector2 texPosition) + : this(position, texPosition, 1f) + { + } + + public TextureVertex(Vector3 position, Vector2 texPosition, float scale) { Position = position; TexPosition = texPosition; - } - - internal Vector3 Position { get; set; } - internal Vector2 TexPosition { get; set; } + Scale = scale; + } public VertexBufferLayout GetLayout() { - return new VertexBufferLayout().Add(3).Add(2); + var layout = new VertexBufferLayout(); + layout.Add(3); + layout.Add(2); + layout.Add(1); + return layout; } } } diff --git a/PCK-Studio/Rendering/VertexBufferLayout.cs b/PCK-Studio/Rendering/VertexBufferLayout.cs index b5f9261c..c9f902ac 100644 --- a/PCK-Studio/Rendering/VertexBufferLayout.cs +++ b/PCK-Studio/Rendering/VertexBufferLayout.cs @@ -50,7 +50,7 @@ namespace PckStudio.Rendering return elements.AsReadOnly(); } - public VertexBufferLayout Add(int count) + public void Add(int count) { if (typeof(T).Equals(typeof(float))) { @@ -67,7 +67,6 @@ namespace PckStudio.Rendering elements.Add(new VertexBufferElement(VertexAttribPointerType.UnsignedInt, count, false)); stride += count * VertexBufferElement.GetStrideSize(VertexAttribPointerType.UnsignedInt); } - return this; } internal int GetStride() diff --git a/PCK-Studio/Resources/shader/skinFragment.glsl b/PCK-Studio/Resources/shader/skinFragmentShader.glsl similarity index 100% rename from PCK-Studio/Resources/shader/skinFragment.glsl rename to PCK-Studio/Resources/shader/skinFragmentShader.glsl diff --git a/PCK-Studio/Resources/shader/skinVertexShader.glsl b/PCK-Studio/Resources/shader/skinVertexShader.glsl index 4bc46529..41f8b276 100644 --- a/PCK-Studio/Resources/shader/skinVertexShader.glsl +++ b/PCK-Studio/Resources/shader/skinVertexShader.glsl @@ -2,6 +2,7 @@ layout(location = 0) in vec4 vertexPosition; layout(location = 1) in vec2 texCoord; +layout(location = 2) in float scale; uniform mat4 u_ViewProjection; uniform mat4 u_Model; @@ -11,5 +12,7 @@ out vec2 v_TexCoord; void main() { v_TexCoord = texCoord; - gl_Position = u_ViewProjection * u_Model * vertexPosition; + vec4 scaledVertex = scale * vertexPosition; + vec4 invertedVertex = vec4(scaledVertex.x, scaledVertex.y * -1.0, scaledVertex.z * -1.0, 1.0); + gl_Position = u_ViewProjection * u_Model * invertedVertex; }; \ No newline at end of file