Properly implemented mirroring of skin parts and improved skin renderer class

This commit is contained in:
miku-666
2024-01-08 19:23:21 +01:00
parent afaaa99dbe
commit 0b154b0d3a
19 changed files with 650 additions and 979 deletions

View File

@@ -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);
}

View File

@@ -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<SkinBOX> 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;
}
}
}

View File

@@ -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<PckStudio.Rendering.TextureChangingEventArgs>(this.renderer3D1_TextureChanging);
//
// uvPictureBox
//

View File

@@ -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

View File

@@ -184,7 +184,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;label5.ZOrder" xml:space="preserve">
<value>31</value>
<value>29</value>
</data>
<metadata name="label3.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
@@ -217,7 +217,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;label3.ZOrder" xml:space="preserve">
<value>30</value>
<value>28</value>
</data>
<metadata name="label7.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
@@ -394,7 +394,7 @@
<value>$this</value>
</data>
<data name="&gt;&gt;buttonDone.ZOrder" xml:space="preserve">
<value>29</value>
<value>27</value>
</data>
<data name="labelView.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
@@ -424,66 +424,6 @@
<value>$this</value>
</data>
<data name="&gt;&gt;labelView.ZOrder" xml:space="preserve">
<value>28</value>
</data>
<data name="rotateRightBtn.FlatStyle" type="System.Windows.Forms.FlatStyle, System.Windows.Forms">
<value>Flat</value>
</data>
<data name="rotateRightBtn.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
<value>NoControl</value>
</data>
<data name="rotateRightBtn.Location" type="System.Drawing.Point, System.Drawing">
<value>554, 642</value>
</data>
<data name="rotateRightBtn.Size" type="System.Drawing.Size, System.Drawing">
<value>89, 23</value>
</data>
<data name="rotateRightBtn.TabIndex" type="System.Int32, mscorlib">
<value>100</value>
</data>
<data name="rotateRightBtn.Text" xml:space="preserve">
<value>Rotate Right</value>
</data>
<data name="&gt;&gt;rotateRightBtn.Name" xml:space="preserve">
<value>rotateRightBtn</value>
</data>
<data name="&gt;&gt;rotateRightBtn.Type" xml:space="preserve">
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;rotateRightBtn.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;rotateRightBtn.ZOrder" xml:space="preserve">
<value>27</value>
</data>
<data name="rotateLeftBtn.FlatStyle" type="System.Windows.Forms.FlatStyle, System.Windows.Forms">
<value>Flat</value>
</data>
<data name="rotateLeftBtn.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
<value>NoControl</value>
</data>
<data name="rotateLeftBtn.Location" type="System.Drawing.Point, System.Drawing">
<value>194, 643</value>
</data>
<data name="rotateLeftBtn.Size" type="System.Drawing.Size, System.Drawing">
<value>89, 23</value>
</data>
<data name="rotateLeftBtn.TabIndex" type="System.Int32, mscorlib">
<value>101</value>
</data>
<data name="rotateLeftBtn.Text" xml:space="preserve">
<value>Rotate Left</value>
</data>
<data name="&gt;&gt;rotateLeftBtn.Name" xml:space="preserve">
<value>rotateLeftBtn</value>
</data>
<data name="&gt;&gt;rotateLeftBtn.Type" xml:space="preserve">
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;rotateLeftBtn.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;rotateLeftBtn.ZOrder" xml:space="preserve">
<value>26</value>
</data>
<data name="tabArmor.Location" type="System.Drawing.Point, System.Drawing">
@@ -1434,23 +1374,16 @@
<data name="renderer3D1.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Bottom, Left, Right</value>
</data>
<data name="renderer3D1.CameraTarget" mimetype="application/x-microsoft.net.object.binary.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAElPcGVuVEssIFZlcnNpb249My4zLjMuMCwgQ3VsdHVyZT1uZXV0
cmFsLCBQdWJsaWNLZXlUb2tlbj1iYWQxOTlmZTg0ZWIzZGY0BQEAAAAOT3BlblRLLlZlY3RvcjICAAAA
AVgBWQAACwsCAAAAAAAAAAAAoEAL
</value>
</data>
<data name="renderer3D1.Location" type="System.Drawing.Point, System.Drawing">
<value>194, 59</value>
</data>
<data name="renderer3D1.LookAngle" mimetype="application/x-microsoft.net.object.binary.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAElPcGVuVEssIFZlcnNpb249My4zLjMuMCwgQ3VsdHVyZT1uZXV0
cmFsLCBQdWJsaWNLZXlUb2tlbj1iYWQxOTlmZTg0ZWIzZGY0BQEAAAAOT3BlblRLLlZlY3RvcjICAAAA
AVgBWQAACwsCAAAAAAAAAAAAAAAL
</value>
</data>
<data name="renderer3D1.Rotation" mimetype="application/x-microsoft.net.object.binary.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAElPcGVuVEssIFZlcnNpb249My4zLjMuMCwgQ3VsdHVyZT1uZXV0
cmFsLCBQdWJsaWNLZXlUb2tlbj1iYWQxOTlmZTg0ZWIzZGY0BQEAAAAOT3BlblRLLlZlY3RvcjICAAAA
AVgBWQAACwsCAAAAAAAAAAAAAAAL
</value>
</data>
<data name="renderer3D1.Size" type="System.Drawing.Size, System.Drawing">
<value>449, 574</value>
</data>
@@ -1461,7 +1394,7 @@
<value>renderer3D1</value>
</data>
<data name="&gt;&gt;renderer3D1.Type" xml:space="preserve">
<value>PckStudio.Rendering.Renderer3D, PCK-Studio, Version=7.0.0.0, Culture=neutral, PublicKeyToken=null</value>
<value>PckStudio.Rendering.SkinRenderer, PCK-Studio, Version=7.0.0.0, Culture=neutral, PublicKeyToken=null</value>
</data>
<data name="&gt;&gt;renderer3D1.Parent" xml:space="preserve">
<value>$this</value>
@@ -4014,9 +3947,6 @@
AP//AAA=
</value>
</data>
<data name="$this.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
<value>NoControl</value>
</data>
<data name="$this.MaximumSize" type="System.Drawing.Size, System.Drawing">
<value>1114, 1000</value>
</data>

View File

@@ -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);

View File

@@ -164,6 +164,7 @@
<DependentUpon>SkinRenderer.cs</DependentUpon>
</Compile>
<Compile Include="Rendering\Texture2D.cs" />
<Compile Include="Rendering\TextureChangingEventArgs.cs" />
<Compile Include="Rendering\TextureVertex.cs" />
<Compile Include="Rendering\VertexArray.cs" />
<Compile Include="Rendering\VertexBuffer.cs" />
@@ -615,6 +616,9 @@
<SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Rendering\SkinRenderer.resx">
<DependentUpon>SkinRenderer.cs</DependentUpon>
</EmbeddedResource>
<None Include="CommunityKey.snk" />
<None Include="Properties\app.manifest" />
<None Include="Properties\Settings.settings">
@@ -684,7 +688,7 @@
<None Include="Resources\iconImageList\ENTITY MATERIALS ICON.png" />
<None Include="Resources\iconImageList\blank.png" />
<None Include="Resources\entities.png" />
<None Include="Resources\shader\skinFragment.glsl" />
<None Include="Resources\shader\skinFragmentShader.glsl" />
<Content Include="Resources\icons\file_delete.png" />
<Content Include="Resources\icons\file_empty.png" />
<None Include="Resources\icons\file_export.png" />

View File

@@ -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);
///};.
/// </summary>
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;
///};.
/// </summary>

View File

@@ -328,10 +328,10 @@
<data name="ProjectLogo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\ProjectLogo.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="skinFragment" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\shader\skinFragment.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="skinVertexShader" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\shader\skinVertexShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="skinFragmentShader" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\shader\skinFragmentShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
</root>

View File

@@ -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<TextureVertex>
{
private const int vertexCountPerCube = 16;
internal CubeRenderGroup(string name)
: base(name, new VertexBufferLayout().Add<float>(3).Add<float>(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,
};
/// <summary>
///
/// </summary>
/// <param name="position"></param>
/// <param name="size"></param>
/// <param name="uv"></param>
/// <param name="scale"></param>
/// <param name="mirrorTexture"></param>
/// <param name="flipZMapping">Flips the bottom face mapping of the uv mapping</param>
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;
}
/// <summary>
///
/// </summary>
/// <param name="position"></param>
/// <param name="size"></param>
/// <param name="uv"></param>
/// <param name="scale"></param>
/// <param name="mirrorTexture"></param>
/// <param name="flipZMapping">Flips the bottom face mapping of the uv mapping</param>
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<CubeData> cubes;
internal CubeRenderGroup(string name) : base(name, PrimitiveType.Quads)
{
cubes = new List<CubeData>(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)
/// <summary>
/// Submits buffered data to the underlying graphics buffer
/// </summary>
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();
}
}
}

View File

@@ -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<T> where T : struct
internal class RenderGroup<T> where T : struct, IVertexLayout
{
internal string Name { get; }
internal static int SizeInBytes = Marshal.SizeOf<T>();
internal readonly int SizeInBytes = Marshal.SizeOf<T>();
protected List<T> vertices;
protected List<uint> indices;
protected uint indicesOffset;
private VertexArray vertexArray;
private VertexBuffer<T> 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<T>(10);
indices = new List<uint>(10);
_layout = layout;
_layout = new T().GetLayout();
}
protected void ResetBuffers()
{
indicesOffset = 0;
vertices.Clear();
indices.Clear();
}
internal RenderBuffer GetRenderBuffer()

View File

@@ -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;
}
}

View File

@@ -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
/// <returns>The visible Texture</returns>
[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<TextureChangingEventArgs> 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<string, CubeRenderGroup> 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<string, CubeRenderGroup>(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();
}
}
}

View File

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="moveTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="animationTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>131, 17</value>
</metadata>
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>269, 17</value>
</metadata>
</root>

View File

@@ -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;
}
}
}

View File

@@ -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<float>(3).Add<float>(2);
var layout = new VertexBufferLayout();
layout.Add<float>(3);
layout.Add<float>(2);
layout.Add<float>(1);
return layout;
}
}
}

View File

@@ -50,7 +50,7 @@ namespace PckStudio.Rendering
return elements.AsReadOnly();
}
public VertexBufferLayout Add<T>(int count)
public void Add<T>(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()

View File

@@ -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;
};