Add Simple Guideline rendering

This commit is contained in:
miku-666
2024-02-19 18:58:14 +01:00
parent 0984efefce
commit c30e0d86ae
20 changed files with 561 additions and 177 deletions

View File

@@ -386,6 +386,7 @@
this.renderer3D1.RefreshRate = 50;
this.renderer3D1.Texture = null;
this.renderer3D1.VSync = true;
this.renderer3D1.TextureChanging += new System.EventHandler<PckStudio.Rendering.TextureChangingEventArgs>(renderer3D1_TextureChanging);
//
// uvPictureBox
//

View File

@@ -36,30 +36,22 @@ namespace PckStudio.Forms.Editor
PixelOffsetMode = PixelOffsetMode.HighQuality,
};
private CustomSkinEditor()
public CustomSkinEditor(PckFileData file)
{
InitializeComponent();
_file = file;
rng = new Random();
}
public CustomSkinEditor(PckFileData file) : this()
protected override void OnLoad(EventArgs e)
{
_file = file;
if (DesignMode)
return;
renderer3D1.RefreshRate = 50;
renderer3D1.Texture = null;
renderer3D1.VSync = true;
renderer3D1.TextureChanging += new System.EventHandler<PckStudio.Rendering.TextureChangingEventArgs>(renderer3D1_TextureChanging);
base.OnLoad(e);
renderer3D1.InitializeGL();
Controls.Add(renderer3D1);
rng = new Random();
if (_file.Size > 0)
{
renderer3D1.Texture = _file.GetTexture();
}
LoadModelData(file.Properties);
LoadModelData(_file.Properties);
}
private void LoadModelData(PckFileProperties properties)
@@ -77,7 +69,7 @@ namespace PckStudio.Forms.Editor
skinPartListBox.DataSource = skinPartListBindingSource;
skinPartListBox.DisplayMember = "Type";
skinOffsetListBindingSource = new BindingSource(renderer3D1.PartOffsets, null);
skinOffsetListBindingSource = new BindingSource(renderer3D1, null);
offsetListBox.DataSource = skinOffsetListBindingSource;
}
@@ -177,26 +169,26 @@ namespace PckStudio.Forms.Editor
string fileExtension = Path.GetExtension(openFileDialog.FileName);
if (fileExtension == ".csmb")
{
var reader = new CSMBFileReader();
CSMBFile csmbFile = reader.FromFile(openFileDialog.FileName);
LoadCsmb(csmbFile);
//var reader = new CSMBFileReader();
//CSMBFile csmbFile = reader.FromFile(openFileDialog.FileName);
//LoadCsmb(csmbFile);
}
}
}
private void LoadCsmb(CSMBFile csmbFile)
{
renderer3D1.ModelData.Clear();
foreach (var part in csmbFile.Parts)
{
renderer3D1.ModelData.Add(part);
}
//renderer3D1.ModelData.Clear();
//foreach (var part in csmbFile.Parts)
//{
// renderer3D1.ModelData.Add(part);
//}
renderer3D1.ResetOffsets();
foreach (var offset in csmbFile.Offsets)
{
renderer3D1.SetPartOffset(offset);
}
//renderer3D1.ResetOffsets();
//foreach (var offset in csmbFile.Offsets)
//{
// renderer3D1.SetPartOffset(offset);
//}
}
private void cloneToolStripMenuItem_Click(object sender, EventArgs e)

View File

@@ -267,15 +267,6 @@
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="contextMenuStrip1.Size" type="System.Drawing.Size, System.Drawing">
<value>152, 108</value>
</data>
<data name="&gt;&gt;contextMenuStrip1.Name" xml:space="preserve">
<value>contextMenuStrip1</value>
</data>
<data name="&gt;&gt;contextMenuStrip1.Type" xml:space="preserve">
<value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="createToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
@@ -348,6 +339,15 @@
<data name="changeColorToolStripMenuItem.Text" xml:space="preserve">
<value>Change Color</value>
</data>
<data name="contextMenuStrip1.Size" type="System.Drawing.Size, System.Drawing">
<value>152, 108</value>
</data>
<data name="&gt;&gt;contextMenuStrip1.Name" xml:space="preserve">
<value>contextMenuStrip1</value>
</data>
<data name="&gt;&gt;contextMenuStrip1.Type" xml:space="preserve">
<value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="buttonDone.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Bottom, Right</value>
</data>
@@ -963,51 +963,6 @@
<data name="metroTabControl1.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Bottom, Left</value>
</data>
<data name="&gt;&gt;skinPartsTabPage.Name" xml:space="preserve">
<value>skinPartsTabPage</value>
</data>
<data name="&gt;&gt;skinPartsTabPage.Type" xml:space="preserve">
<value>System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;skinPartsTabPage.Parent" xml:space="preserve">
<value>metroTabControl1</value>
</data>
<data name="&gt;&gt;skinPartsTabPage.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="&gt;&gt;skinOffsetsTabPage.Name" xml:space="preserve">
<value>skinOffsetsTabPage</value>
</data>
<data name="&gt;&gt;skinOffsetsTabPage.Type" xml:space="preserve">
<value>System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;skinOffsetsTabPage.Parent" xml:space="preserve">
<value>metroTabControl1</value>
</data>
<data name="&gt;&gt;skinOffsetsTabPage.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="metroTabControl1.Location" type="System.Drawing.Point, System.Drawing">
<value>23, 59</value>
</data>
<data name="metroTabControl1.Size" type="System.Drawing.Size, System.Drawing">
<value>165, 492</value>
</data>
<data name="metroTabControl1.TabIndex" type="System.Int32, mscorlib">
<value>166</value>
</data>
<data name="&gt;&gt;metroTabControl1.Name" xml:space="preserve">
<value>metroTabControl1</value>
</data>
<data name="&gt;&gt;metroTabControl1.Type" xml:space="preserve">
<value>MetroFramework.Controls.MetroTabControl, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a</value>
</data>
<data name="&gt;&gt;metroTabControl1.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;metroTabControl1.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="skinPartsTabPage.BackgroundImageLayout" type="System.Windows.Forms.ImageLayout, System.Windows.Forms">
<value>Center</value>
</data>
@@ -1035,6 +990,18 @@
<data name="&gt;&gt;skinPartsTabPage.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="offsetListBox.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<data name="offsetListBox.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 0</value>
</data>
<data name="offsetListBox.Size" type="System.Drawing.Size, System.Drawing">
<value>157, 450</value>
</data>
<data name="offsetListBox.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
</data>
<data name="&gt;&gt;offsetListBox.Name" xml:space="preserve">
<value>offsetListBox</value>
</data>
@@ -1071,29 +1038,26 @@
<data name="&gt;&gt;skinOffsetsTabPage.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="offsetListBox.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
<data name="metroTabControl1.Location" type="System.Drawing.Point, System.Drawing">
<value>23, 59</value>
</data>
<data name="offsetListBox.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 0</value>
<data name="metroTabControl1.Size" type="System.Drawing.Size, System.Drawing">
<value>165, 492</value>
</data>
<data name="offsetListBox.Size" type="System.Drawing.Size, System.Drawing">
<value>157, 450</value>
<data name="metroTabControl1.TabIndex" type="System.Int32, mscorlib">
<value>166</value>
</data>
<data name="offsetListBox.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
<data name="&gt;&gt;metroTabControl1.Name" xml:space="preserve">
<value>metroTabControl1</value>
</data>
<data name="&gt;&gt;offsetListBox.Name" xml:space="preserve">
<value>offsetListBox</value>
<data name="&gt;&gt;metroTabControl1.Type" xml:space="preserve">
<value>MetroFramework.Controls.MetroTabControl, MetroFramework, Version=1.4.0.0, Culture=neutral, PublicKeyToken=5f91a84759bf584a</value>
</data>
<data name="&gt;&gt;offsetListBox.Type" xml:space="preserve">
<value>System.Windows.Forms.ListBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<data name="&gt;&gt;metroTabControl1.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;offsetListBox.Parent" xml:space="preserve">
<value>skinOffsetsTabPage</value>
</data>
<data name="&gt;&gt;offsetListBox.ZOrder" xml:space="preserve">
<value>0</value>
<data name="&gt;&gt;metroTabControl1.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="renderer3D1.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>Top, Bottom, Left, Right</value>
@@ -3670,9 +3634,6 @@
AP//AAA=
</value>
</data>
<data name="$this.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
<value>NoControl</value>
</data>
<data name="$this.MinimumSize" type="System.Drawing.Size, System.Drawing">
<value>900, 600</value>
</data>

View File

@@ -15,11 +15,21 @@ namespace PckStudio.Forms
set => ModelView.ANIM = value;
}
public SkinPreview(Image texture, IEnumerable<SkinBOX> modelData)
private Image texture;
private IEnumerable<SkinBOX> data;
public SkinPreview(Image image, IEnumerable<SkinBOX> modelData)
{
InitializeComponent();
texture = image;
data = modelData;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
ModelView.InitializeGL();
foreach (var item in modelData)
foreach (var item in data)
{
ModelView.ModelData.Add(item);
}

View File

@@ -158,6 +158,7 @@
<Compile Include="Rendering\IndexBuffer.cs" />
<Compile Include="Rendering\IVertexLayout.cs" />
<Compile Include="Rendering\DrawContext.cs" />
<Compile Include="Rendering\LineVertex.cs" />
<Compile Include="Rendering\Renderer.cs" />
<Compile Include="Rendering\GenericMesh.cs" />
<Compile Include="Rendering\Shader\ShaderLibrary.cs" />
@@ -646,6 +647,8 @@
<ItemGroup>
<None Include="Resources\shader\framebufferFragmentShader.glsl" />
<None Include="Resources\shader\framebufferVertexShader.glsl" />
<None Include="Resources\shader\lineFragmentShader.glsl" />
<None Include="Resources\shader\lineVertexShader.glsl" />
<None Include="Resources\shader\skinGeometryShader.glsl" />
<None Include="Resources\shader\skyboxFragmentShader.glsl" />
<None Include="Resources\shader\skyboxVertexShader.glsl" />

View File

@@ -355,7 +355,8 @@ namespace PckStudio.Properties {
///
///void main()
///{
/// color = texture(screenTexture, texCoords);
/// vec3 texColor = texture(screenTexture, texCoords).rgb;
/// color = vec4(texColor, 1.0);
///}.
/// </summary>
public static string framebufferFragmentShader {
@@ -444,6 +445,42 @@ namespace PckStudio.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to #version 330 core
///
///layout(location = 0) in vec4 a_Pos;
///
///uniform mat4 ViewProjection;
///
///void main()
///{
/// gl_Position = ViewProjection * a_Pos;
///};.
/// </summary>
public static string lineFragmentShader {
get {
return ResourceManager.GetString("lineFragmentShader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to #version 330 core
///
///layout(location = 0) out vec4 FragColor;
///
///uniform vec4 color;
///
///void main()
///{
/// FragColor = color;
///}.
/// </summary>
public static string lineVertexShader {
get {
return ResourceManager.GetString("lineVertexShader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -611,12 +648,12 @@ namespace PckStudio.Properties {
///
///uniform sampler2D u_Texture;
///
///in vec2 o_TexScale;
///in vec2 o_TillingFactor;
///in vec2 o_TexCoord;
///
///void main()
///{
/// color = texture(u_Texture, o_TexCoord * o_TexScale);
/// color = texture(u_Texture, o_TexCoord * o_TillingFactor);
///};.
/// </summary>
public static string skinFragmentShader {
@@ -634,7 +671,7 @@ namespace PckStudio.Properties {
///uniform vec2 u_TexSize;
///
///out vec2 o_TexCoord;
///out vec2 o_TexScale;
///out vec2 o_TillingFactor;
///
///in geometryData
///{
@@ -651,7 +688,7 @@ namespace PckStudio.Properties {
/// gl_Position = gl_in[0].gl_Position;
/// o_TexCoord = dataIn[0].TexCoord;
/// if (isXBad)
/// o_TexCoord.x = mod(o_TexCoord.x, u_TexSize.x); [rest of string was truncated]&quot;;.
/// o_TexCoord.x = mod(o_TexCoord.x, u_TexSiz [rest of string was truncated]&quot;;.
/// </summary>
public static string skinGeometryShader {
get {
@@ -677,7 +714,7 @@ namespace PckStudio.Properties {
///layout(location = 2) in float scale;
///
///uniform mat4 u_ViewProjection;
///uniform mat4 u_Model;
///uniform mat4 u_Transform;
///
///out geometryData
///{
@@ -687,9 +724,8 @@ namespace PckStudio.Properties {
///void main()
///{
/// dataOut.TexCoord = texCoord;
/// 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;
/// vec4 invertedVertex = vec4(vertexPosition.x, vertexPosition.yz * -1.0, 1.0);
/// gl_Position = u_ViewProjection * u_Transform * invertedVertex * scale;
///};.
/// </summary>
public static string skinVertexShader {
@@ -724,15 +760,15 @@ namespace PckStudio.Properties {
///
///layout(location = 0) in vec4 a_Pos;
///
///uniform mat4 viewProjection;
///uniform mat4 ViewProjection;
///
///out vec3 texCoords;
///
///void main()
///{
/// vec4 pos = viewProjection * a_Pos;
/// vec4 pos = ViewProjection * a_Pos;
/// gl_Position = vec4(pos.x, pos.y, pos.ww);
/// texCoords = vec3(a_Pos.x, a_Pos.y, -a_Pos.z);
/// texCoords = vec3(a_Pos.xy, -a_Pos.z);
///};.
/// </summary>
public static string skyboxVertexShader {

View File

@@ -352,4 +352,10 @@
<data name="framebufferVertexShader" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\shader\framebufferVertexShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="lineFragmentShader" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\shader\lineFragmentShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="lineVertexShader" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\shader\lineVertexShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
</root>

View File

@@ -30,6 +30,8 @@ namespace PckStudio.Rendering
private List<CubeData> cubes;
internal float Scale { get; set; } = 1f;
public Vector3 Translation { get; set; } = Vector3.Zero;
public Vector3 Pivot { get; set; } = Vector3.Zero;
internal CubeBatchMesh(string name) : base(name, PrimitiveType.Triangles)
{
@@ -44,7 +46,9 @@ namespace PckStudio.Rendering
internal void AddSkinBox(SkinBOX skinBox)
{
AddCube(skinBox.Pos.ToOpenTKVector(), skinBox.Size.ToOpenTKVector(), skinBox.UV.ToOpenTKVector(), skinBox.Scale + Scale, skinBox.Mirror, skinBox.Type == "HEAD");
AddCube(skinBox.Pos.ToOpenTKVector(), skinBox.Size.ToOpenTKVector(), skinBox.UV.ToOpenTKVector(), skinBox.Scale + Scale, skinBox.Mirror,
skinBox.Type == "HEAD" ||
skinBox.Type == "HEADWEAR");
}
internal void ClearData()
@@ -92,6 +96,41 @@ namespace PckStudio.Rendering
cube.MirrorTexture = mirrorTexture;
}
private Vector3 Transform
{
get
{
Vector3 offset = Translation;
offset.Xz -= Pivot.Xz / 2f;
return -offset;
}
}
internal Vector3 GetCenter(int index)
{
if (!cubes.IndexInRange(index))
throw new IndexOutOfRangeException();
return cubes[index].Center + Transform;
}
internal Vector3[] GetCubical(int index)
{
if (!cubes.IndexInRange(index))
throw new IndexOutOfRangeException();
CubeData cube = cubes[index];
return cube.GetOutline().Select(pos => pos + Transform).ToArray();
}
internal Vector3 GetFaceCenter(int index, CubeData.CubeFace face)
{
if (!cubes.IndexInRange(index))
throw new IndexOutOfRangeException();
return cubes[index].GetFaceCenter(face) + Transform;
}
internal void SetEnabled(int index, bool enable)
{
if (!cubes.IndexInRange(index))

View File

@@ -106,6 +106,99 @@ namespace PckStudio.Rendering
}
}
internal Vector3 Center => Position + Size / 2f;
internal enum CubeFace
{
Back,
Front,
Top,
Bottom,
Left,
Right
}
internal Vector3 GetFaceCenter(CubeFace face)
{
var result = Center;
switch (face)
{
case CubeFace.Top:
result.Y -= Size.Y / 2f;
return result;
case CubeFace.Bottom:
result.Y += Size.Y / 2f;
return result;
case CubeFace.Back:
result.Z -= Size.Z / 2f;
return result;
case CubeFace.Front:
result.Z += Size.Z / 2f;
return result;
case CubeFace.Left:
result.X -= Size.X / 2f;
return result;
case CubeFace.Right:
result.X += Size.X / 2f;
return result;
default:
return result;
}
}
internal Vector3[] GetOutline()
{
List<Vector3> verts = new List<Vector3>();
Vector3 bottomRightBack = vertices[0].Position;
Vector3 bottomLeftBack = vertices[1].Position;
Vector3 topLeftBack = vertices[2].Position;
Vector3 topRightBack = vertices[3].Position;
Vector3 bottomRightFront = vertices[4].Position;
Vector3 bottomLeftFront = vertices[5].Position;
Vector3 topLeftFront = vertices[6].Position;
Vector3 topRightFront = vertices[7].Position;
return [
topLeftBack,
topLeftFront,
topLeftBack,
topRightBack,
topRightBack,
topRightFront,
topLeftFront,
topRightFront,
bottomLeftBack,
bottomLeftFront,
bottomLeftBack,
bottomRightBack,
bottomRightBack,
bottomRightFront,
bottomLeftFront,
bottomRightFront,
topLeftFront,
bottomLeftFront,
topRightFront,
bottomRightFront,
topLeftBack,
bottomLeftBack,
topRightBack,
bottomRightBack,
];
}
private void UpdateVertices()
{
vertices = GetCubeVertexData(Position, Size, Uv, Scale, MirrorTexture, FlipZMapping);

View File

@@ -35,7 +35,7 @@ namespace PckStudio.Rendering
protected int indicesOffset;
private VertexArray vertexArray;
private VertexBuffer<T> vertexBuffer;
private VertexBuffer vertexBuffer;
private IndexBuffer indexBuffer;
private readonly VertexBufferLayout _layout;
private readonly PrimitiveType drawType;
@@ -65,7 +65,8 @@ namespace PckStudio.Rendering
vertexArray ??= new VertexArray();
var vertexData = vertices.ToArray();
vertexBuffer = new VertexBuffer<T>(vertexData, vertexData.Length * SizeInBytes);
vertexBuffer = new VertexBuffer(vertexData.Length * SizeInBytes);
vertexBuffer.SetData(vertexData);
vertexArray.AddBuffer(vertexBuffer, _layout);

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using OpenTK.Graphics;
namespace PckStudio.Rendering
{
[StructLayout(LayoutKind.Sequential, Size = 28)]
internal struct LineVertex
{
public LineVertex(Vector3 position, Color4 color)
{
Position = position;
Color = color;
}
public Vector3 Position { get; set; }
public Color4 Color { get; set; }
}
}

View File

@@ -41,5 +41,10 @@ namespace PckStudio.Rendering
{
GL.ClearColor(color);
}
public static void SetLineWidth(float width)
{
GL.LineWidth(width);
}
}
}

View File

@@ -37,6 +37,7 @@ namespace PckStudio.Rendering
this.components = new System.ComponentModel.Container();
this.reToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.guidelineModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenuStrip1.SuspendLayout();
this.SuspendLayout();
//
@@ -50,9 +51,17 @@ namespace PckStudio.Rendering
// contextMenuStrip1
//
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.reToolStripMenuItem});
this.reToolStripMenuItem,
this.guidelineModeToolStripMenuItem});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(181, 48);
this.contextMenuStrip1.Size = new System.Drawing.Size(181, 70);
//
// guidelineModeToolStripMenuItem
//
this.guidelineModeToolStripMenuItem.Name = "guidelineModeToolStripMenuItem";
this.guidelineModeToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
this.guidelineModeToolStripMenuItem.Text = "Guideline Mode";
this.guidelineModeToolStripMenuItem.Click += new System.EventHandler(this.guidelineModeToolStripMenuItem_Click);
//
// SkinRenderer
//
@@ -64,5 +73,6 @@ namespace PckStudio.Rendering
}
private System.Windows.Forms.ToolStripMenuItem reToolStripMenuItem;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem guidelineModeToolStripMenuItem;
}
}

View File

@@ -64,6 +64,19 @@ namespace PckStudio.Rendering
}
public bool ClampModel { get; set; } = false;
public bool ShowGuideLines
{
get => guidelineMode != GuidelineMode.None;
set
{
if (value)
{
guidelineMode = GuidelineMode.Cubical;
return;
}
guidelineMode = GuidelineMode.None;
}
}
[Description("Event that gets fired when the Texture is changing")]
[Category("Property Chnaged")]
@@ -110,6 +123,16 @@ namespace PckStudio.Rendering
return bmp;
}
private enum GuidelineMode
{
None = -1,
Cubical,
Skeleton
};
private GuidelineMode guidelineMode { get; set; } = GuidelineMode.None;
private Vector2 _globalModelRotation;
private Vector2 GlobalModelRotation
{
@@ -151,6 +174,9 @@ namespace PckStudio.Rendering
private ShaderProgram framebufferShader;
private VertexArray framebufferVAO;
#endif
private DrawContext _cubicalDrawContext;
private DrawContext _skeletonDrawContext;
private DrawContext _skyboxRenderBuffer;
private CubeTexture _skyboxTexture;
private float skyboxRotation = 0f;
@@ -179,12 +205,8 @@ namespace PckStudio.Rendering
private bool showWireFrame = false;
private Matrix4 HeadMatrix { get; set; } = Matrix4.Identity;
private Matrix4 BodyMatrix { get; set; } = Matrix4.Identity;
private Matrix4 RightArmMatrix { get; set; } = Matrix4.CreateFromAxisAngle(Vector3.UnitZ, 25f);
private Matrix4 LeftArmMatrix { get; set; } = Matrix4.CreateFromAxisAngle(Vector3.UnitZ, -25f);
private Matrix4 RightLegMatrix { get; set; } = Matrix4.Identity;
private Matrix4 LeftLegMatrix { get; set; } = Matrix4.Identity;
private static Vector3[] cubeVertices = new Vector3[]
{
@@ -265,7 +287,7 @@ namespace PckStudio.Rendering
InitializeCamera();
InitializeComponent();
_shaders = new ShaderLibrary();
ANIM ??= new SkinANIM(SkinAnimMask.RESOLUTION_64x64);
OnTimerTick = AnimationTick;
@@ -304,27 +326,43 @@ namespace PckStudio.Rendering
bodyOverlay.AddCube(new(-4, 0, -2), new(8, 12, 4), new(16, 32), scale: OverlayScale);
rightArm ??= new CubeBatchMesh("Right Arm");
rightArm.Pivot = new Vector3(4f, 2f, 0f);
rightArm.Translation = new Vector3(-5f, -2f, 0f);
rightArm.AddCube(new(-3, -2, -2), new(4, 12, 4), new(40, 16));
rightArmOverlay ??= new CubeBatchMesh("Right Arm Overlay", OverlayScale);
rightArmOverlay.Pivot = new Vector3(4f, 2f, 0f);
rightArmOverlay.Translation = new Vector3(-5f, -2f, 0f);
rightArmOverlay.AddCube(new(-3, -2, -2), new(4, 12, 4), new(40, 32), scale: OverlayScale);
leftArm ??= new CubeBatchMesh("Left Arm");
leftArm.Pivot = new Vector3(-4f, 2f, 0f);
leftArm.Translation = new Vector3(5f, -2f, 0f);
leftArm.AddCube(new(-1, -2, -2), new(4, 12, 4), new(32, 48));
leftArmOverlay ??= new CubeBatchMesh("Left Arm Overlay", OverlayScale);
leftArmOverlay.Pivot = new Vector3(-4f, 2f, 0f);
leftArmOverlay.Translation = new Vector3(5f, -2f, 0f);
leftArmOverlay.AddCube(new(-1, -2, -2), new(4, 12, 4), new(48, 48), scale: OverlayScale);
rightLeg ??= new CubeBatchMesh("Right Leg");
rightLeg.Pivot = new Vector3(0f, 12f, 0f);
rightLeg.Translation = new Vector3(-2f, -12f, 0f);
rightLeg.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 16));
rightLegOverlay ??= new CubeBatchMesh("Right Leg Overlay", OverlayScale);
rightLegOverlay.Pivot = new Vector3(0f, 12f, 0f);
rightLegOverlay.Translation = new Vector3(-2f, -12f, 0f);
rightLegOverlay.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 32), scale: OverlayScale);
leftLeg ??= new CubeBatchMesh("Left Leg");
leftLeg.Pivot = new Vector3(0f, 12f, 0f);
leftLeg.Translation = new Vector3(2f, -12f, 0f);
leftLeg.AddCube(new(-2, 0, -2), new(4, 12, 4), new(16, 48));
leftLegOverlay ??= new CubeBatchMesh("Left Leg Overlay", OverlayScale);
leftLegOverlay.Pivot = new Vector3(0f, 12f, 0f);
leftLegOverlay.Translation = new Vector3(2f, -12f, 0f);
leftLegOverlay.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 48), scale: OverlayScale);
}
@@ -362,9 +400,10 @@ namespace PckStudio.Rendering
}
// Skybox shader
{
{
var skyboxVAO = new VertexArray();
var skyboxVBO = new VertexBuffer<Vector3>(cubeVertices, cubeVertices.Length * Vector3.SizeInBytes);
var skyboxVBO = new VertexBuffer();
skyboxVBO.SetData(cubeVertices);
var vboLayout = new VertexBufferLayout();
vboLayout.Add<float>(3);
skyboxVAO.AddBuffer(skyboxVBO, vboLayout);
@@ -428,6 +467,90 @@ namespace PckStudio.Rendering
GLErrorCheck();
}
#endif
// Line Shader
{
var lineShader = ShaderProgram.Create(Resources.lineVertexShader, Resources.lineFragmentShader);
lineShader.Bind();
lineShader.SetUniform4("baseColor", Color.WhiteSmoke);
lineShader.Validate();
_shaders.AddShader("LineShader", lineShader);
Color lineColor = Color.Aquamarine;
// Cubical draw context
{
VertexArray lineVAO = new VertexArray();
List<LineVertex> vertices = new List<LineVertex>(24 * 6);
vertices.AddRange(head.GetCubical(0).Select(pos => new LineVertex(pos, lineColor)));
vertices.AddRange(body.GetCubical(0).Select(pos => new LineVertex(pos, lineColor)));
vertices.AddRange(rightArm.GetCubical(0).Select(pos => new LineVertex(pos, lineColor)));
vertices.AddRange(leftArm.GetCubical(0).Select(pos => new LineVertex(pos, lineColor)));
vertices.AddRange(rightLeg.GetCubical(0).Select(pos => new LineVertex(pos, lineColor)));
vertices.AddRange(leftLeg.GetCubical(0).Select(pos => new LineVertex(pos, lineColor)));
VertexBuffer buffer = new VertexBuffer();
buffer.SetData(vertices.ToArray());
VertexBufferLayout layout = new VertexBufferLayout();
layout.Add<float>(3);
layout.Add<float>(4);
lineVAO.AddBuffer(buffer, layout);
lineVAO.Bind();
_cubicalDrawContext = new DrawContext(lineVAO, buffer.GenIndexBuffer(), PrimitiveType.Lines);
}
GLErrorCheck();
// Skeleton draw context
{
VertexArray lineVAO = new VertexArray();
Vector3 bodyCenterTop = body.GetFaceCenter(0, CubeData.CubeFace.Top);
Vector3 bodyCenterBottom = body.GetFaceCenter(0, CubeData.CubeFace.Bottom);
LineVertex[] data = [
new LineVertex(head.GetFaceCenter(0, CubeData.CubeFace.Top), lineColor),
new LineVertex(bodyCenterTop, lineColor),
new LineVertex(rightArm.GetFaceCenter(0, CubeData.CubeFace.Bottom), lineColor),
new LineVertex(rightArm.GetFaceCenter(0, CubeData.CubeFace.Top), lineColor),
new LineVertex(rightArm.GetFaceCenter(0, CubeData.CubeFace.Top), lineColor),
new LineVertex(bodyCenterTop, lineColor),
new LineVertex(leftArm.GetFaceCenter(0, CubeData.CubeFace.Bottom), lineColor),
new LineVertex(leftArm.GetFaceCenter(0, CubeData.CubeFace.Top), lineColor),
new LineVertex(leftArm.GetFaceCenter(0, CubeData.CubeFace.Top), lineColor),
new LineVertex(bodyCenterTop, lineColor),
new LineVertex(rightLeg.GetFaceCenter(0, CubeData.CubeFace.Bottom), lineColor),
new LineVertex(rightLeg.GetFaceCenter(0, CubeData.CubeFace.Top), lineColor),
new LineVertex(rightLeg.GetFaceCenter(0, CubeData.CubeFace.Top), lineColor),
new LineVertex(bodyCenterBottom, lineColor),
new LineVertex(bodyCenterBottom, lineColor),
new LineVertex(bodyCenterTop, lineColor),
new LineVertex(leftLeg.GetFaceCenter(0, CubeData.CubeFace.Bottom), lineColor),
new LineVertex(leftLeg.GetFaceCenter(0, CubeData.CubeFace.Top), lineColor),
new LineVertex(leftLeg.GetFaceCenter(0, CubeData.CubeFace.Top), lineColor),
new LineVertex(bodyCenterBottom, lineColor),
new LineVertex(bodyCenterBottom, lineColor),
new LineVertex(bodyCenterTop, lineColor),
];
VertexBuffer buffer = new VertexBuffer();
buffer.SetData(data);
VertexBufferLayout layout = new VertexBufferLayout();
layout.Add<float>(3);
layout.Add<float>(4);
lineVAO.AddBuffer(buffer, layout);
lineVAO.Bind();
_skeletonDrawContext = new DrawContext(lineVAO, buffer.GenIndexBuffer(), PrimitiveType.Lines);
}
GLErrorCheck();
}
}
private DrawContext GetGuidelineDrawContext()
{
return guidelineMode == GuidelineMode.Skeleton ? _skeletonDrawContext : _cubicalDrawContext;
}
protected virtual void OnTextureChanging(object sender, TextureChangingEventArgs e)
@@ -462,7 +585,8 @@ namespace PckStudio.Rendering
GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, RenderbufferTarget.Renderbuffer, rbo);
framebufferVAO = new VertexArray();
VertexBuffer<Vector4> vertexBuffer = new VertexBuffer<Vector4>(rectVertices, rectVertices.Length * Vector4.SizeInBytes);
VertexBuffer vertexBuffer = new VertexBuffer();
vertexBuffer.SetData(rectVertices);
VertexBufferLayout layout = new VertexBufferLayout();
layout.Add<float>(4);
framebufferVAO.AddBuffer(vertexBuffer, layout);
@@ -677,17 +801,36 @@ namespace PckStudio.Rendering
return;
}
MakeCurrent();
MakeCurrent();
#if USE_FRAMEBUFFER
framebuffer.Bind();
#endif
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Enable(EnableCap.DepthTest); // Enable correct Z Drawings
GL.Enable(EnableCap.LineSmooth);
Matrix4 viewProjection = Camera.GetViewProjection();
// Render Skybox
{
GL.DepthFunc(DepthFunction.Lequal);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
var skyboxShader = _shaders.GetShader("SkyboxShader");
skyboxShader.Bind();
_skyboxTexture.Bind();
var view = new Matrix4(new Matrix3(Matrix4.LookAt(Camera.WorldPosition, Camera.WorldPosition + Camera.Orientation, Camera.Up)))
* Matrix4.CreateRotationY(MathHelper.DegreesToRadians(skyboxRotation));
var proj = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(Camera.Fov), AspectRatio, 1f, 1000f);
var viewproj = view * proj;
skyboxShader.SetUniformMat4("ViewProjection", ref viewproj);
Renderer.Draw(skyboxShader, _skyboxRenderBuffer);
GL.DepthFunc(DepthFunction.Less);
}
// Render (custom) skin
{
var viewProjection = Camera.GetViewProjection();
var skinShader = _shaders.GetShader("SkinShader");
skinShader.Bind();
skinShader.SetUniformMat4("u_ViewProjection", ref viewProjection);
@@ -749,29 +892,29 @@ namespace PckStudio.Rendering
}
bool slimModel = ANIM.GetFlag(SkinAnimFlag.SLIM_MODEL);
RenderBodyPart(skinShader, new Vector3(0f, 0f, 0f), new Vector3(0f), HeadMatrix, modelMatrix, "HEAD", "HEADWEAR");
RenderBodyPart(skinShader, new Vector3(0f, 0f, 0f), new Vector3(0f), BodyMatrix, modelMatrix, "BODY", "JACKET");
RenderBodyPart(skinShader, new Vector3(4f, 2f, 0f), new Vector3(slimModel ? -4f : -5f, -2f, 0f), RightArmMatrix * armRightMatrix, modelMatrix, "ARM0", "SLEEVE0");
RenderBodyPart(skinShader, new Vector3(-4f, 2f, 0f), new Vector3(5f, -2f, 0f), LeftArmMatrix * armLeftMatrix, modelMatrix, "ARM1", "SLEEVE1");
RenderBodyPart(skinShader, new Vector3(0f, 12f, 0f), new Vector3(-2f, -12f, 0f), RightLegMatrix * legRightMatrix, modelMatrix, "LEG0", "PANTS0");
RenderBodyPart(skinShader, new Vector3(0f, 12f, 0f), new Vector3(2f, -12f, 0f), LeftLegMatrix * legLeftMatrix, modelMatrix, "LEG1", "PANTS1");
}
// Render Skybox
{
GL.DepthFunc(DepthFunction.Lequal);
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
var skyboxShader = _shaders.GetShader("SkyboxShader");
skyboxShader.Bind();
_skyboxTexture.Bind();
rightArm.Translation = rightArmOverlay.Translation = new Vector3(slimModel ? -4f : -5f, -2f, 0f);
var view = new Matrix4(new Matrix3(Matrix4.LookAt(Camera.WorldPosition, Camera.WorldPosition + Camera.Orientation, Camera.Up)))
* Matrix4.CreateRotationY(MathHelper.DegreesToRadians(skyboxRotation));
var proj = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(Camera.Fov), AspectRatio, 1f, 1000f);
var viewproj = view * proj;
skyboxShader.SetUniformMat4("ViewProjection", ref viewproj);
Renderer.Draw(skyboxShader, _skyboxRenderBuffer);
GL.DepthFunc(DepthFunction.Less);
RenderBodyPart(skinShader, Matrix4.Identity, modelMatrix, "HEAD", "HEADWEAR");
RenderBodyPart(skinShader, Matrix4.Identity, modelMatrix, "BODY", "JACKET");
RenderBodyPart(skinShader, RightArmMatrix * armRightMatrix, modelMatrix, "ARM0", "SLEEVE0");
RenderBodyPart(skinShader, LeftArmMatrix * armLeftMatrix, modelMatrix, "ARM1", "SLEEVE1");
RenderBodyPart(skinShader, legRightMatrix, modelMatrix, "LEG0", "PANTS0");
RenderBodyPart(skinShader, legLeftMatrix, modelMatrix, "LEG1", "PANTS1");
// render lines
if (ShowGuideLines)
{
GL.DepthFunc(DepthFunction.Always);
var shader = _shaders.GetShader("LineShader");
shader.Bind();
shader.SetUniformMat4("ViewProjection", ref viewProjection);
shader.SetUniformMat4("Transform", ref modelMatrix);
Renderer.SetLineWidth(2.5f);
Renderer.Draw(shader, GetGuidelineDrawContext());
//GL.DepthFunc(DepthFunction.Less);
Renderer.SetLineWidth(1f);
}
}
#if USE_FRAMEBUFFER
@@ -837,23 +980,26 @@ namespace PckStudio.Rendering
base.OnMouseUp(e);
}
private void RenderBodyPart(ShaderProgram shader, Vector3 pivot, Vector3 translation, Matrix4 partMatrix, Matrix4 globalMatrix, params string[] additionalData)
private void RenderBodyPart(ShaderProgram shader, Matrix4 partMatrix, Matrix4 globalMatrix, params string[] additionalData)
{
foreach (var data in additionalData)
{
RenderPart(shader, data, pivot, translation, partMatrix, globalMatrix);
RenderPart(shader, data, partMatrix, globalMatrix);
}
}
private void RenderPart(ShaderProgram shader, string name, Vector3 pivot, Vector3 translation, Matrix4 partMatrix, Matrix4 globalMatrix)
private void RenderPart(ShaderProgram shader, string name, Matrix4 partMatrix, Matrix4 globalMatrix)
{
CubeBatchMesh cubeMesh = meshStorage[name];
Vector3 translation = cubeMesh.Translation;
Vector3 pivot = cubeMesh.Pivot;
float yOffset = GetOffset(name);
translation.Y -= yOffset;
pivot.Y += yOffset;
Matrix4 model = Pivot(translation, pivot, partMatrix);
model *= globalMatrix;
_skinShader.SetUniformMat4("u_Model", ref model);
Matrix4 transform = Matrix4.CreateScale(cubeMesh.Scale);
transform *= Pivot(translation, pivot, partMatrix);
transform *= globalMatrix;
shader.SetUniformMat4("u_Transform", ref transform);
cubeMesh.Draw(shader);
}
@@ -901,5 +1047,14 @@ namespace PckStudio.Rendering
MakeCurrent();
UploadMeshData();
}
private void guidelineModeToolStripMenuItem_Click(object sender, EventArgs e)
{
if (!Enum.IsDefined(typeof(GuidelineMode), ++guidelineMode))
{
guidelineMode = GuidelineMode.None;
}
guidelineModeToolStripMenuItem.Text = $"Guideline Mode: {guidelineMode}";
}
}
}

View File

@@ -17,7 +17,7 @@ namespace PckStudio.Rendering
_id = GL.GenVertexArray();
}
public void AddBuffer<T>(VertexBuffer<T> buffer, VertexBufferLayout layout) where T : struct
public void AddBuffer(VertexBuffer buffer, VertexBufferLayout layout)
{
Bind();
buffer.Bind();

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Markup;
@@ -10,25 +11,41 @@ using OpenTK.Graphics.OpenGL;
namespace PckStudio.Rendering
{
internal struct VertexBuffer<T> : IDisposable where T : struct
internal struct VertexBuffer : IDisposable
{
private int _id;
private int _count;
private int _size;
#if DEBUG
private T[] __data;
#endif
public VertexBuffer(T[] data, int size)
public VertexBuffer()
{
#if DEBUG
__data = data;
#endif
_id = GL.GenBuffer();
_size = 0;
}
public VertexBuffer(int size) : this()
{
_size = size;
Bind();
GL.BufferData(BufferTarget.ArrayBuffer, size, data, BufferUsageHint.StaticDraw);
GL.BufferData(BufferTarget.ArrayBuffer, size, IntPtr.Zero, BufferUsageHint.StaticDraw);
Unbind();
}
public void SetData<T>(T[] data) where T : struct
{
int sizeofT = Marshal.SizeOf<T>();
_count = data.Length;
Bind();
int size = sizeofT * _count;
if (_size == 0)
{
GL.BufferData(BufferTarget.ArrayBuffer, size, data, BufferUsageHint.StaticDraw);
_size = size;
return;
}
GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, size, data);
}
public void Bind()
{
GL.BindBuffer(BufferTarget.ArrayBuffer, _id);
@@ -44,5 +61,10 @@ namespace PckStudio.Rendering
Unbind();
GL.DeleteBuffer(_id);
}
internal IndexBuffer GenIndexBuffer()
{
return IndexBuffer.Create(Enumerable.Range(0, _count).ToArray());
}
}
}

View File

@@ -0,0 +1,12 @@
#version 330 core
layout(location = 0) out vec4 FragColor;
uniform vec4 baseColor;
in vec4 color;
void main()
{
FragColor = color * baseColor;
}

View File

@@ -0,0 +1,15 @@
#version 330 core
layout(location = 0) in vec4 a_Pos;
layout(location = 1) in vec4 a_Color;
uniform mat4 ViewProjection;
uniform mat4 Transform;
out vec4 color;
void main()
{
color = a_Color;
gl_Position = ViewProjection * Transform * vec4(a_Pos.x, a_Pos.yz * -1.0, 1.0);
};

View File

@@ -5,7 +5,7 @@ layout(location = 1) in vec2 texCoord;
layout(location = 2) in float scale;
uniform mat4 u_ViewProjection;
uniform mat4 u_Model;
uniform mat4 u_Transform;
out geometryData
{
@@ -15,7 +15,6 @@ out geometryData
void main()
{
dataOut.TexCoord = texCoord;
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;
vec4 invertedVertex = vec4(vertexPosition.x, vertexPosition.yz * -1.0, 1.0);
gl_Position = u_ViewProjection * u_Transform * invertedVertex * scale;
};

View File

@@ -2,13 +2,13 @@
layout(location = 0) in vec4 a_Pos;
uniform mat4 viewProjection;
uniform mat4 ViewProjection;
out vec3 texCoords;
void main()
{
vec4 pos = viewProjection * a_Pos;
vec4 pos = ViewProjection * a_Pos;
gl_Position = vec4(pos.x, pos.y, pos.ww);
texCoords = vec3(a_Pos.x, a_Pos.y, -a_Pos.z);
texCoords = vec3(a_Pos.xy, -a_Pos.z);
};