From 05ebf400e49beefbb8976627a6b692155e30875c Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Sun, 6 Oct 2024 19:24:23 +0200 Subject: [PATCH] Add ModelRenderer --- .../Forms/Editor/ModelEditor.Designer.cs | 91 ++++++- PCK-Studio/Forms/Editor/ModelEditor.cs | 102 ++++++-- PCK-Studio/Forms/Editor/ModelEditor.resx | 3 + PCK-Studio/PckStudio.csproj | 9 + .../Rendering/ModelRenderer.Designer.cs | 42 ++++ PCK-Studio/Rendering/ModelRenderer.cs | 233 ++++++++++++++++++ PCK-Studio/Rendering/ModelRenderer.resx | 120 +++++++++ 7 files changed, 579 insertions(+), 21 deletions(-) create mode 100644 PCK-Studio/Rendering/ModelRenderer.Designer.cs create mode 100644 PCK-Studio/Rendering/ModelRenderer.cs create mode 100644 PCK-Studio/Rendering/ModelRenderer.resx diff --git a/PCK-Studio/Forms/Editor/ModelEditor.Designer.cs b/PCK-Studio/Forms/Editor/ModelEditor.Designer.cs index a2a697b3..5bc93941 100644 --- a/PCK-Studio/Forms/Editor/ModelEditor.Designer.cs +++ b/PCK-Studio/Forms/Editor/ModelEditor.Designer.cs @@ -36,9 +36,15 @@ this.removeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.menuStrip1 = new System.Windows.Forms.MenuStrip(); this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.importToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.modelViewport = new PckStudio.Rendering.ModelRenderer(); + this.namedTexturesTreeView = new System.Windows.Forms.TreeView(); + this.textureImageList = new System.Windows.Forms.ImageList(this.components); this.modelContextMenu.SuspendLayout(); this.menuStrip1.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); this.SuspendLayout(); // // modelTreeView @@ -50,10 +56,12 @@ this.modelTreeView.BorderStyle = System.Windows.Forms.BorderStyle.None; this.modelTreeView.ContextMenuStrip = this.modelContextMenu; this.modelTreeView.ForeColor = System.Drawing.SystemColors.Window; - this.modelTreeView.Location = new System.Drawing.Point(20, 87); + this.modelTreeView.HideSelection = false; + this.modelTreeView.Location = new System.Drawing.Point(3, 3); this.modelTreeView.Name = "modelTreeView"; this.modelTreeView.PathSeparator = "."; - this.modelTreeView.Size = new System.Drawing.Size(335, 368); + this.tableLayoutPanel1.SetRowSpan(this.modelTreeView, 2); + this.modelTreeView.Size = new System.Drawing.Size(239, 340); this.modelTreeView.TabIndex = 0; this.modelTreeView.BeforeSelect += new System.Windows.Forms.TreeViewCancelEventHandler(this.modelTreeView_BeforeSelect); // @@ -95,7 +103,7 @@ this.fileToolStripMenuItem}); this.menuStrip1.Location = new System.Drawing.Point(20, 60); this.menuStrip1.Name = "menuStrip1"; - this.menuStrip1.Size = new System.Drawing.Size(335, 24); + this.menuStrip1.Size = new System.Drawing.Size(510, 24); this.menuStrip1.TabIndex = 1; this.menuStrip1.Text = "menuStrip1"; // @@ -103,30 +111,93 @@ // this.fileToolStripMenuItem.BackColor = System.Drawing.Color.Transparent; this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.importToolStripMenuItem1, this.saveToolStripMenuItem}); this.fileToolStripMenuItem.ForeColor = System.Drawing.SystemColors.Control; this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); this.fileToolStripMenuItem.Text = "File"; // + // importToolStripMenuItem1 + // + this.importToolStripMenuItem1.Name = "importToolStripMenuItem1"; + this.importToolStripMenuItem1.Size = new System.Drawing.Size(110, 22); + this.importToolStripMenuItem1.Text = "Import"; + this.importToolStripMenuItem1.Click += new System.EventHandler(this.importToolStripMenuItem1_Click); + // // saveToolStripMenuItem // this.saveToolStripMenuItem.Name = "saveToolStripMenuItem"; - this.saveToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.saveToolStripMenuItem.Size = new System.Drawing.Size(110, 22); this.saveToolStripMenuItem.Text = "Save"; this.saveToolStripMenuItem.Click += new System.EventHandler(this.saveToolStripMenuItem_Click); // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 2; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Controls.Add(this.modelTreeView, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.modelViewport, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.namedTexturesTreeView, 1, 1); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(20, 84); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 60F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 40F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(510, 346); + this.tableLayoutPanel1.TabIndex = 2; + // + // modelViewport + // + this.modelViewport.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(30)))), ((int)(((byte)(30))))); + this.modelViewport.Dock = System.Windows.Forms.DockStyle.Fill; + this.modelViewport.Location = new System.Drawing.Point(248, 3); + this.modelViewport.MouseSensetivity = 0.01F; + this.modelViewport.Name = "modelViewport"; + this.modelViewport.RefreshRate = 120; + this.modelViewport.Size = new System.Drawing.Size(259, 201); + this.modelViewport.TabIndex = 1; + this.modelViewport.VSync = true; + // + // namedTexturesTreeView + // + this.namedTexturesTreeView.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20))))); + this.namedTexturesTreeView.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.namedTexturesTreeView.Dock = System.Windows.Forms.DockStyle.Fill; + this.namedTexturesTreeView.ForeColor = System.Drawing.SystemColors.Window; + this.namedTexturesTreeView.FullRowSelect = true; + this.namedTexturesTreeView.HideSelection = false; + this.namedTexturesTreeView.ImageIndex = 0; + this.namedTexturesTreeView.ImageList = this.textureImageList; + this.namedTexturesTreeView.Location = new System.Drawing.Point(248, 210); + this.namedTexturesTreeView.Name = "namedTexturesTreeView"; + this.namedTexturesTreeView.SelectedImageIndex = 0; + this.namedTexturesTreeView.ShowLines = false; + this.namedTexturesTreeView.ShowPlusMinus = false; + this.namedTexturesTreeView.ShowRootLines = false; + this.namedTexturesTreeView.Size = new System.Drawing.Size(259, 133); + this.namedTexturesTreeView.TabIndex = 2; + this.namedTexturesTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.namedTexturesTreeView_AfterSelect); + // + // textureImageList + // + this.textureImageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit; + this.textureImageList.ImageSize = new System.Drawing.Size(36, 36); + this.textureImageList.TransparentColor = System.Drawing.Color.Transparent; + // // ModelEditor // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(375, 475); + this.ClientSize = new System.Drawing.Size(550, 450); + this.Controls.Add(this.tableLayoutPanel1); this.Controls.Add(this.menuStrip1); - this.Controls.Add(this.modelTreeView); this.MainMenuStrip = this.menuStrip1; this.MaximizeBox = false; this.MinimizeBox = false; - this.MinimumSize = new System.Drawing.Size(375, 475); + this.MinimumSize = new System.Drawing.Size(550, 450); this.Name = "ModelEditor"; this.Style = MetroFramework.MetroColorStyle.Silver; this.Text = "ModelEditor"; @@ -134,6 +205,7 @@ this.modelContextMenu.ResumeLayout(false); this.menuStrip1.ResumeLayout(false); this.menuStrip1.PerformLayout(); + this.tableLayoutPanel1.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -148,6 +220,11 @@ private System.Windows.Forms.ToolStripMenuItem removeToolStripMenuItem; private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem importToolStripMenuItem1; private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private Rendering.ModelRenderer modelViewport; + private System.Windows.Forms.TreeView namedTexturesTreeView; + private System.Windows.Forms.ImageList textureImageList; } } \ No newline at end of file diff --git a/PCK-Studio/Forms/Editor/ModelEditor.cs b/PCK-Studio/Forms/Editor/ModelEditor.cs index 5a08a163..db050279 100644 --- a/PCK-Studio/Forms/Editor/ModelEditor.cs +++ b/PCK-Studio/Forms/Editor/ModelEditor.cs @@ -11,7 +11,9 @@ using OMI.Formats.Model; using MetroFramework.Forms; using PckStudio.Internal; +using PckStudio.Internal.Json; using PckStudio.Internal.App; +using PckStudio.Extensions; namespace PckStudio.Forms.Editor { @@ -142,7 +144,7 @@ namespace PckStudio.Forms.Editor private static IEnumerable GetModelPartNodes(IEnumerable parts) => parts.Select(ModelPartNode.Create); internal static ModelNode Create(Model model) => new ModelNode(model); - } + } private class ModelPartNode : TreeNode { @@ -161,7 +163,7 @@ namespace PckStudio.Forms.Editor private static IEnumerable GetModelBoxNodes(IEnumerable boxes) => boxes.Select(ModelBoxNode.Create); internal static ModelPartNode Create(ModelPart part) => new ModelPartNode(part); - } + } private class ModelBoxNode : TreeNode { @@ -177,6 +179,20 @@ namespace PckStudio.Forms.Editor internal static ModelBoxNode Create(ModelBox modelBox) => new ModelBoxNode(modelBox); } + private class NamedTextureTreeNode : TreeNode + { + private readonly NamedTexture _namedTexture; + + public NamedTextureTreeNode(NamedTexture namedTexture) + : base(namedTexture.Name) + { + Tag = namedTexture; + _namedTexture = namedTexture; + } + + public Image GetTexture() => _namedTexture.Texture; + } + protected override void OnLoad(EventArgs e) { base.OnLoad(e); @@ -200,18 +216,6 @@ namespace PckStudio.Forms.Editor openFileDialog.FileName = model.Name; openFileDialog.Filter = GameModelImporter.Default.SupportedModelFileFormatsFilter; - IEnumerable GetModelTextures(string modelName) - { - if (!GameModelImporter.ModelMetaData.ContainsKey(modelName) || GameModelImporter.ModelMetaData[modelName]?.TextureLocations?.Length <= 0) - yield break; - foreach (var textureLocation in GameModelImporter.ModelMetaData[modelName].TextureLocations) - { - if (_tryGetTexture(textureLocation, out Image img)) - yield return new NamedTexture(Path.GetFileName(textureLocation), img); - } - yield break; - } - if (openFileDialog.ShowDialog(this) == DialogResult.OK) { IEnumerable textures = GetModelTextures(model.Name); @@ -226,11 +230,81 @@ namespace PckStudio.Forms.Editor exportToolStripMenuItem.Visible = e.Node is ModelNode; editToolStripMenuItem.Visible = e.Node is ModelBoxNode; removeToolStripMenuItem.Visible = e.Node is ModelPartNode || e.Node is ModelBoxNode; + if (e.Node is ModelNode modelNode) + { + NamedTexture[] textures = GetModelTextures(modelNode.Model.Name).ToArray(); + + textureImageList.Images.Clear(); + namedTexturesTreeView.Nodes.Clear(); + + foreach ((int i, NamedTexture item) in textures.enumerate()) + { + textureImageList.Images.Add(item.Texture); + namedTexturesTreeView.Nodes.Add(new NamedTextureTreeNode(item) { ImageIndex = i, SelectedImageIndex = i }); + } + if (textures.Length != 0) + modelViewport.Texture = textures[0].Texture; + + modelViewport.Model = modelNode.Model; + } + } + + private IEnumerable GetModelTextures(string modelName) + { + if (!GameModelImporter.ModelMetaData.ContainsKey(modelName) || GameModelImporter.ModelMetaData[modelName]?.TextureLocations?.Length <= 0) + yield break; + foreach (var textureLocation in GameModelImporter.ModelMetaData[modelName].TextureLocations) + { + if (_tryGetTexture(textureLocation, out Image img)) + yield return new NamedTexture(Path.GetFileName(textureLocation), img); + } + yield break; + } + + private void importToolStripMenuItem1_Click(object sender, EventArgs e) + { + OpenFileDialog fileDialog = new OpenFileDialog(); + fileDialog.Filter = GameModelImporter.Default.SupportedModelFileFormatsFilter; + fileDialog.Title = "Select model"; + if (fileDialog.ShowDialog() == DialogResult.OK) + { + GameModelInfo modelInfo = GameModelImporter.Default.Import(fileDialog.FileName); + if (modelInfo is null) + { + MessageBox.Show("Import failed.", ProductName); + return; + } + + if (!GameModelImporter.ModelMetaData.TryGetValue(modelInfo.Model.Name, out JsonModelMetaData modelMetaData)) + { + MessageBox.Show($"Couldn't get model meta data for: '{modelInfo.Model.Name}'.", ProductName); + return; + } + + //if (models.Version < modelInfo.ModelVersion) + //{ + // MessageBox.Show("Model container version does not match with the model version.", ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + // return; + //} + + _models.Add(modelInfo.Model); + + foreach (NamedTexture texture in modelInfo.Textures) + { + _trySetTexture(texture.Name, texture.Texture); + } + } } private void saveToolStripMenuItem_Click(object sender, EventArgs e) { DialogResult = DialogResult.OK; } + + private void namedTexturesTreeView_AfterSelect(object sender, TreeViewEventArgs e) + { + if (namedTexturesTreeView.SelectedNode is NamedTextureTreeNode namedTextureNode) + modelViewport.Texture = namedTextureNode.GetTexture(); + } } } diff --git a/PCK-Studio/Forms/Editor/ModelEditor.resx b/PCK-Studio/Forms/Editor/ModelEditor.resx index 2c9d3fce..25aecfae 100644 --- a/PCK-Studio/Forms/Editor/ModelEditor.resx +++ b/PCK-Studio/Forms/Editor/ModelEditor.resx @@ -120,6 +120,9 @@ 17, 17 + + 293, 17 + 178, 17 diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj index 9ef9405a..9ef35daa 100644 --- a/PCK-Studio/PckStudio.csproj +++ b/PCK-Studio/PckStudio.csproj @@ -217,6 +217,12 @@ + + UserControl + + + ModelRenderer.cs + @@ -612,6 +618,9 @@ Designer Resources.Designer.cs + + ModelRenderer.cs + SkinRenderer.cs diff --git a/PCK-Studio/Rendering/ModelRenderer.Designer.cs b/PCK-Studio/Rendering/ModelRenderer.Designer.cs new file mode 100644 index 00000000..a818e6c1 --- /dev/null +++ b/PCK-Studio/Rendering/ModelRenderer.Designer.cs @@ -0,0 +1,42 @@ +using System.Diagnostics; + +namespace PckStudio.Rendering +{ + partial class ModelRenderer + { + [DebuggerNonUserCode()] + protected override void Dispose(bool disposing) + { + try + { + if (disposing && components is not null) + { + components.Dispose(); + } + } + finally + { + base.Dispose(disposing); + } + } + + // Required by the Windows Form Designer + private System.ComponentModel.IContainer components; + + // NOTE: The following procedure is required by the Windows Form Designer + // It can be modified using the Windows Form Designer. + // Do not modify it using the code editor. + [DebuggerStepThrough()] + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + // + // ModelRenderer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.Name = "ModelRenderer"; + this.ResumeLayout(false); + this.PerformLayout(); + } + } +} diff --git a/PCK-Studio/Rendering/ModelRenderer.cs b/PCK-Studio/Rendering/ModelRenderer.cs new file mode 100644 index 00000000..b3f7e46a --- /dev/null +++ b/PCK-Studio/Rendering/ModelRenderer.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using OMI.Formats.Model; +using OpenTK; +using OpenTK.Graphics.OpenGL; +using PckStudio.Extensions; +using PckStudio.Internal; +using PckStudio.Internal.Json; +using PckStudio.Properties; +using PckStudio.Rendering.Shader; +using PckStudio.Rendering.Texture; + +namespace PckStudio.Rendering +{ + internal partial class ModelRenderer : SceneViewport + { + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Model Model + { + get => _model; + set + { + _model = value; + InitModelRender(_model); + } + } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Image Texture + { + get => _modelTexture; + set + { + var args = new TextureChangingEventArgs(value); + Events[nameof(ModelTextureChanging)]?.DynamicInvoke(this, args); + OnModelTextureChanging(this, args); + if (!args.Cancel) + { + _modelTexture = value; + } + } + } + + [Description("Event that gets fired when the skin texture is changing")] + [Category("Property Chnaged")] + [Browsable(true)] + public event EventHandler ModelTextureChanging + { + add => Events.AddHandler(nameof(ModelTextureChanging), value); + remove => Events.RemoveHandler(nameof(ModelTextureChanging), value); + } + + private BoundingBox _maxBounds; + private Model _model; + private Image _modelTexture; + private Texture2D _modelRenderTexture; + private List _rootCollection; + + public ModelRenderer() : base(fov: 60f) + { + InitializeComponent(); + _rootCollection = new List(5); + if (DesignMode) + return; + InitializeShaders(); + } + + private void InitializeShaders() + { + if (!Context.IsCurrent) + MakeCurrent(); + + // render texture + { + _modelRenderTexture = new Texture2D(0); + _modelRenderTexture.PixelFormat = PixelFormat.Bgra; + _modelRenderTexture.InternalPixelFormat = PixelInternalFormat.Rgba8; + _modelRenderTexture.MinFilter = TextureMinFilter.Nearest; + _modelRenderTexture.MagFilter = TextureMagFilter.Nearest; + _modelRenderTexture.WrapS = TextureWrapMode.Repeat; + _modelRenderTexture.WrapT = TextureWrapMode.Repeat; + } + + // cubeShader + { + var cubeShader = ShaderProgram.Create( + new ShaderSource(ShaderType.VertexShader, Resources.texturedCubeVertexShader), + new ShaderSource(ShaderType.FragmentShader, Resources.texturedCubeFragmentShader), + new ShaderSource(ShaderType.GeometryShader, Resources.texturedCubeGeometryShader) + ); + cubeShader.Bind(); + cubeShader.SetUniform1("Texture", 0); + cubeShader.Validate(); + AddShader("CubeShader", cubeShader); + } + } + + private void InitModelRender(Model model) + { + _rootCollection?.Clear(); + + IEnumerable allBoxes = model.GetParts() + .SelectMany(p => p.GetBoxes() + .Select(b => new ModelBox(b.Position + p.Translation, b.Size, System.Numerics.Vector2.Zero, 0f, false))) + .Select(b => new BoundingBox(b.Position, b.Position + b.Size)); + + _maxBounds = GetBounds(allBoxes); + + Vector3 center = (_maxBounds.Start + _maxBounds.End) / 2f; + + Camera.FocalPoint = center; + Camera.Distance = _maxBounds.Volume.Length * 1.3f; + Camera.Yaw = 45f; + Camera.Pitch = 25f; + + if (!GameModelImporter.ModelMetaData.TryGetValue(model.Name, out JsonModelMetaData modelMetaData)) + { + Trace.TraceError($"[{nameof(ModelRenderer)}@{nameof(InitModelRender)}] : Couldn't get meta data for model: '{model.Name}'"); + return; + } + + if (modelMetaData.RootParts.Length == 0) + { + modelMetaData = new JsonModelMetaData() + { + TextureLocations = modelMetaData.TextureLocations, + RootParts = model.GetParts().Select(p => new ModelMetaDataPart() { Name = p.Name }).ToArray() + }; + } + + foreach (ModelMetaDataPart metaDataPart in modelMetaData.RootParts) + { + if (!model.TryGetPart(metaDataPart.Name, out ModelPart modelPart)) + { + Trace.TraceError($"[{nameof(ModelRenderer)}@{nameof(InitModelRender)}] : Failed to find part: '{metaDataPart.Name}'"); + } + + Vector3 translation = modelPart.Translation.ToOpenTKVector(); + + var cubeMeshCollection = new CubeMeshCollection(modelPart.Name, translation, translation, modelPart.Rotation.ToOpenTKVector() + modelPart.AdditionalRotation.ToOpenTKVector()); + cubeMeshCollection.FlipZMapping = true; + foreach (ModelBox boxes in modelPart.GetBoxes()) + { + cubeMeshCollection.AddNamed(modelPart.Name, boxes.Position.ToOpenTKVector() /*+ modelPart.Translation.ToOpenTKVector()*/, boxes.Size.ToOpenTKVector(), boxes.Uv.ToOpenTKVector(), boxes.Inflate, boxes.Mirror); + } + + RetriveChildMeshes(metaDataParts: metaDataPart.Children).ForEach(cubeMeshCollection.Add); + + _rootCollection.Add(cubeMeshCollection); + } + + MakeCurrent(); + ShaderProgram shader = GetShader("CubeShader"); + + shader.SetUniform2("TexSize", model.TextureSize); + } + + private static CubeMesh ToCubeMesh(ModelBox box) => ToCubeMesh(box, Vector3.Zero); + private static CubeMesh ToCubeMesh(ModelBox box, Vector3 translation) + => new CubeMesh(new Cube(translation + box.Position.ToOpenTKVector(), box.Size.ToOpenTKVector(), box.Uv.ToOpenTKVector(), box.Inflate, box.Mirror, true)); + + private List> RetriveChildMeshes(ModelMetaDataPart[] metaDataParts) + { + List> meshes = new List>(); + foreach (ModelMetaDataPart metaDataPart in metaDataParts) + { + if (!Model.TryGetPart(metaDataPart.Name, out ModelPart modelPart)) + { + Trace.TraceError($"[{nameof(ModelRenderer)}@{nameof(RetriveChildMeshes)}] : Failed to find part: '{metaDataPart.Name}'"); + } + Vector3 translation = modelPart.Translation.ToOpenTKVector(); + meshes.AddRange(modelPart.GetBoxes().Select(b => ToCubeMesh(b, translation))); + meshes.AddRange(RetriveChildMeshes(metaDataPart.Children)); + } + return meshes; + } + + protected virtual void OnModelTextureChanging(object sender, TextureChangingEventArgs e) + { + if (e.NewTexture is null) + e.Cancel = true; + + if (e.Cancel) + return; + if (!Context.IsCurrent) + MakeCurrent(); + _modelRenderTexture.SetTexture(e.NewTexture); + GLErrorCheck(); + } + + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + if (DesignMode) + return; + if (!Context.IsCurrent) + MakeCurrent(); + + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + GL.Enable(EnableCap.DepthTest); // Enable correct Z Drawings + + GL.Enable(EnableCap.Texture2D); // Enable textures + + GL.Enable(EnableCap.Blend); + GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + + GL.Enable(EnableCap.AlphaTest); // Enable transparent + GL.AlphaFunc(AlphaFunction.Greater, 0.0f); + GL.DepthFunc(DepthFunction.Lequal); + + ShaderProgram shader = GetShader("CubeShader"); + + _modelRenderTexture.Bind(); + + DrawBoundingBox(Matrix4.CreateScale(1f, -1f, -1f), _maxBounds, Color.Red); + + foreach (CubeMeshCollection item in _rootCollection) + { + DrawMesh(item, shader, item.Transform * Matrix4.CreateScale(1f, -1f, -1f)); + } + } + } +} diff --git a/PCK-Studio/Rendering/ModelRenderer.resx b/PCK-Studio/Rendering/ModelRenderer.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/PCK-Studio/Rendering/ModelRenderer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + \ No newline at end of file