From d5906cac967e2ba9788459b2010a45318d51df5f Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Fri, 20 Oct 2023 21:50:52 +0200 Subject: [PATCH] [WIP] Added texture/Uv mapping from skinbox data --- PCK-Studio/Extensions/System.Numerics.cs | 21 + .../Forms/Skins-And-Textures/SkinPreview.cs | 3 +- .../generateModel.Designer.cs | 6 - .../Forms/Skins-And-Textures/generateModel.cs | 2 +- PCK-Studio/Forms/TestGL.Designer.cs | 7 +- PCK-Studio/Internal/SkinBOX.cs | 2 +- PCK-Studio/PckStudio.csproj | 19 +- PCK-Studio/Properties/Resources.Designer.cs | 87 ++-- PCK-Studio/Properties/Resources.resx | 8 +- PCK-Studio/Rendering/Camera.cs | 98 ++++ PCK-Studio/Rendering/IndexBuffer.cs | 2 +- PCK-Studio/Rendering/RenderBuffer.cs | 23 + PCK-Studio/Rendering/RenderGroup.cs | 90 ++++ PCK-Studio/Rendering/Renderer.cs | 8 +- PCK-Studio/Rendering/Renderer3D.cs | 456 +----------------- PCK-Studio/Rendering/Shader.cs | 2 +- ...D.Designer.cs => SkinRenderer.Designer.cs} | 40 +- PCK-Studio/Rendering/SkinRenderer.cs | 385 +++++++++++++++ PCK-Studio/Rendering/Texture2D.cs | 5 - .../Rendering/{Vertex.cs => TextureVertex.cs} | 8 +- PCK-Studio/Resources/fragment.glsl | 19 - PCK-Studio/Resources/shader/skinFragment.glsl | 13 + .../Resources/shader/skinVertexShader.glsl | 15 + PCK-Studio/Resources/vertexShader.glsl | 19 - 24 files changed, 744 insertions(+), 594 deletions(-) create mode 100644 PCK-Studio/Extensions/System.Numerics.cs create mode 100644 PCK-Studio/Rendering/Camera.cs create mode 100644 PCK-Studio/Rendering/RenderBuffer.cs create mode 100644 PCK-Studio/Rendering/RenderGroup.cs rename PCK-Studio/Rendering/{Renderer3D.Designer.cs => SkinRenderer.Designer.cs} (51%) create mode 100644 PCK-Studio/Rendering/SkinRenderer.cs rename PCK-Studio/Rendering/{Vertex.cs => TextureVertex.cs} (73%) delete mode 100644 PCK-Studio/Resources/fragment.glsl create mode 100644 PCK-Studio/Resources/shader/skinFragment.glsl create mode 100644 PCK-Studio/Resources/shader/skinVertexShader.glsl delete mode 100644 PCK-Studio/Resources/vertexShader.glsl diff --git a/PCK-Studio/Extensions/System.Numerics.cs b/PCK-Studio/Extensions/System.Numerics.cs new file mode 100644 index 00000000..80520983 --- /dev/null +++ b/PCK-Studio/Extensions/System.Numerics.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PckStudio.Extensions +{ + internal static class NumericsExtensions + { + internal static OpenTK.Vector3 ToOpenTKVector(this System.Numerics.Vector3 vector3) + { + return new OpenTK.Vector3(vector3.X, vector3.Y, vector3.Z); + } + + internal static OpenTK.Vector2 ToOpenTKVector(this System.Numerics.Vector2 vector3) + { + return new OpenTK.Vector2(vector3.X, vector3.Y); + } + } +} diff --git a/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs b/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs index c0ee08a3..5a2370a5 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs +++ b/PCK-Studio/Forms/Skins-And-Textures/SkinPreview.cs @@ -14,7 +14,6 @@ namespace PckStudio.Forms { InitializeComponent(); Texture = texture; - ModelView.Model = anim.GetFlag(SkinAnimFlag.SLIM_MODEL) ? Renderer3D.Models.Alex : Renderer3D.Models.Steve; //ModelView.ShowHead = !anim.GetFlag(SkinAnimFlag.HEAD_DISABLED); //ModelView.ShowHeadOverlay = !anim.GetFlag(SkinAnimFlag.HEAD_OVERLAY_DISABLED); @@ -36,7 +35,7 @@ namespace PckStudio.Forms public void RenderModel(Image source) { - ModelView.Texture = source as Bitmap; + //ModelView.Texture = source as Bitmap; } } } diff --git a/PCK-Studio/Forms/Skins-And-Textures/generateModel.Designer.cs b/PCK-Studio/Forms/Skins-And-Textures/generateModel.Designer.cs index 477cd96c..3384a257 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/generateModel.Designer.cs +++ b/PCK-Studio/Forms/Skins-And-Textures/generateModel.Designer.cs @@ -542,14 +542,8 @@ // resources.ApplyResources(this.renderer3D1, "renderer3D1"); this.renderer3D1.BackColor = System.Drawing.Color.DarkGray; - this.renderer3D1.CameraDistance = 72F; - this.renderer3D1.LookAngle = ((OpenTK.Vector2)(resources.GetObject("renderer3D1.LookAngle"))); - this.renderer3D1.Model = PckStudio.Rendering.Renderer3D.Models.Steve; this.renderer3D1.Name = "renderer3D1"; - this.renderer3D1.Rotation = ((OpenTK.Vector2)(resources.GetObject("renderer3D1.Rotation"))); - this.renderer3D1.Texture = null; this.renderer3D1.VSync = true; - this.renderer3D1.FieldOfView = 1D; // // uvPictureBox // diff --git a/PCK-Studio/Forms/Skins-And-Textures/generateModel.cs b/PCK-Studio/Forms/Skins-And-Textures/generateModel.cs index f3b04435..e28b468e 100644 --- a/PCK-Studio/Forms/Skins-And-Textures/generateModel.cs +++ b/PCK-Studio/Forms/Skins-And-Textures/generateModel.cs @@ -134,7 +134,7 @@ namespace PckStudio.Forms _file = file; if (file.Size > 0) { - uvPictureBox.Image = renderer3D1.Texture = file.GetTexture() as Bitmap; + uvPictureBox.Image = file.GetTexture(); } comboParent.Items.Clear(); comboParent.Items.AddRange(ValidModelBoxTypes); diff --git a/PCK-Studio/Forms/TestGL.Designer.cs b/PCK-Studio/Forms/TestGL.Designer.cs index 22c2192e..deb69f0c 100644 --- a/PCK-Studio/Forms/TestGL.Designer.cs +++ b/PCK-Studio/Forms/TestGL.Designer.cs @@ -28,7 +28,7 @@ /// private void InitializeComponent() { - this.renderer3D1 = new PckStudio.Rendering.Renderer3D(); + this.renderer3D1 = new PckStudio.Rendering.SkinRenderer(); this.SuspendLayout(); // // renderer3D1 @@ -36,12 +36,9 @@ this.renderer3D1.BackColor = System.Drawing.Color.Gray; this.renderer3D1.Dock = System.Windows.Forms.DockStyle.Fill; this.renderer3D1.Location = new System.Drawing.Point(0, 0); - this.renderer3D1.Model = PckStudio.Rendering.Renderer3D.Models.Steve; this.renderer3D1.Name = "renderer3D1"; this.renderer3D1.Size = new System.Drawing.Size(426, 428); - this.renderer3D1.Texture = global::PckStudio.Properties.Resources.classic_template; this.renderer3D1.TabIndex = 8; - this.renderer3D1.FieldOfView = 1D; // // TestGL // @@ -58,6 +55,6 @@ #endregion - private PckStudio.Rendering.Renderer3D renderer3D1; + private PckStudio.Rendering.SkinRenderer renderer3D1; } } \ No newline at end of file diff --git a/PCK-Studio/Internal/SkinBOX.cs b/PCK-Studio/Internal/SkinBOX.cs index 5f7c743f..8a88e28e 100644 --- a/PCK-Studio/Internal/SkinBOX.cs +++ b/PCK-Studio/Internal/SkinBOX.cs @@ -45,7 +45,7 @@ namespace PckStudio.Internal } public static SkinBOX FromString(string value) - { + { var arguments = value.Split(' '); if (arguments.Length < 9) { diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj index 671a47cd..6c612deb 100644 --- a/PCK-Studio/PckStudio.csproj +++ b/PCK-Studio/PckStudio.csproj @@ -136,6 +136,7 @@ + Form @@ -152,11 +153,20 @@ True Resources.resx + + + + + UserControl + + + SkinRenderer.cs + - + @@ -169,9 +179,6 @@ UserControl - - Renderer3D.cs - Component @@ -629,7 +636,7 @@ - + @@ -682,7 +689,7 @@ - + diff --git a/PCK-Studio/Properties/Resources.Designer.cs b/PCK-Studio/Properties/Resources.Designer.cs index 1ebfa5ea..ba5d465b 100644 --- a/PCK-Studio/Properties/Resources.Designer.cs +++ b/PCK-Studio/Properties/Resources.Designer.cs @@ -334,22 +334,6 @@ namespace PckStudio.Properties { } } - /// - /// Looks up a localized string similar to #version 330 core - /// - ///layout(location = 0) out vec4 color; - /// - ///void main() - ///{ - /// color = vec4(1.0, 0.0, 0.0, 1.0); - ///};. - /// - public static string fragmentShader { - get { - return ResourceManager.GetString("fragmentShader", resourceCulture); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -570,6 +554,33 @@ namespace PckStudio.Properties { } } + /// + /// Looks up a localized string similar to #version 330 core + /// + ///layout(location = 0) out vec4 color; + /// + ///uniform sampler2D u_Texture; + /// + ///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; + ///};. + /// + public static string skinFragment { + get { + return ResourceManager.GetString("skinFragment", resourceCulture); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -580,6 +591,34 @@ 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; + /// + ///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; + ///};. + /// + public static string skinVertexShader { + get { + return ResourceManager.GetString("skinVertexShader", resourceCulture); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -781,22 +820,6 @@ namespace PckStudio.Properties { } } - /// - /// Looks up a localized string similar to #version 330 core - /// - ///layout(location = 0) in vec2 position; - /// - ///void main() - ///{ - /// gl_Position = vec4(position.xy, 0.0, 0.0); - ///};. - /// - public static string vertexShader { - get { - return ResourceManager.GetString("vertexShader", resourceCulture); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/PCK-Studio/Properties/Resources.resx b/PCK-Studio/Properties/Resources.resx index 59fcd348..5e50a571 100644 --- a/PCK-Studio/Properties/Resources.resx +++ b/PCK-Studio/Properties/Resources.resx @@ -328,10 +328,10 @@ ..\..\ProjectLogo.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\vertexShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + ..\Resources\shader\skinFragment.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 - - ..\Resources\fragment.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + ..\Resources\shader\skinVertexShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 \ No newline at end of file diff --git a/PCK-Studio/Rendering/Camera.cs b/PCK-Studio/Rendering/Camera.cs new file mode 100644 index 00000000..a29cdd60 --- /dev/null +++ b/PCK-Studio/Rendering/Camera.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Media3D; +using OpenTK; + +namespace PckStudio.Rendering +{ + internal class Camera + { + public float Distance + { + get => _position.Z; + set + { + _position.Z = value; + } + } + + public Vector2 Position + { + get => _position.Xy; + set + { + _position.Xy = value; + } + } + + public Vector2 Rotation + { + get => _rotation; + set + { + _rotation.X = MathHelper.Clamp(value.X, -180f, 180f); + _rotation.Y = MathHelper.Clamp(value.Y, -180f, 180f); + } + } + + public float MinimumFov { get; set; } = 30f; + public float MaximumFov { get; set; } = 120f; + public float Fov + { + get => fov; + set => fov = MathHelper.Clamp(value, MinimumFov, MaximumFov); + } + + private Matrix4 viewProjection; + private Matrix4 viewMatrix; + private float fov; + + private Vector3 _position; + private Vector2 _rotation; + private Vector3 _target; + + public Camera(Vector2 position, float distance, Vector2 rotation, float fov) + { + _position = new Vector3(position) { Z = distance }; + _target = new Vector3(position); + Rotation = rotation; + Fov = fov; + } + + internal Matrix4 GetViewProjection() + { + return viewProjection; + } + + private void UpdateView() + { + var up = Vector3.UnitY; + + Matrix4 rotation = Matrix4.CreateFromAxisAngle(new Vector3(-1f, 0f, 0f), MathHelper.DegreesToRadians(Rotation.X)) + * Matrix4.CreateFromAxisAngle(new Vector3(0f, 1f, 0f), MathHelper.DegreesToRadians(Rotation.Y)); + + viewMatrix = Matrix4.LookAt(_position, _target, up) * rotation; + } + + internal void Update(float aspect) + { + UpdateView(); + var projection = Matrix4.CreatePerspectiveFieldOfView((float)MathHelper.DegreesToRadians(Fov), aspect, 1f, 100f); + viewProjection = viewMatrix * projection; + } + + internal void LookAt(Vector2 pos) + { + _target = new Vector3(pos); + Position = pos; + } + + public override string ToString() + { + return $"FOV: {Fov}\nPosition: {Position}\nRotation: {Rotation}"; + } + } +} diff --git a/PCK-Studio/Rendering/IndexBuffer.cs b/PCK-Studio/Rendering/IndexBuffer.cs index a9ce629a..dcf877e2 100644 --- a/PCK-Studio/Rendering/IndexBuffer.cs +++ b/PCK-Studio/Rendering/IndexBuffer.cs @@ -16,8 +16,8 @@ namespace PckStudio.Rendering public IndexBuffer(params uint[] indecies) { _id = GL.GenBuffer(); - Bind(); _count = indecies.Length; + Bind(); GL.BufferData(BufferTarget.ElementArrayBuffer, indecies.Length * sizeof(uint), indecies, BufferUsageHint.StaticDraw); } diff --git a/PCK-Studio/Rendering/RenderBuffer.cs b/PCK-Studio/Rendering/RenderBuffer.cs new file mode 100644 index 00000000..5b53ce77 --- /dev/null +++ b/PCK-Studio/Rendering/RenderBuffer.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OpenTK.Graphics.OpenGL; + +namespace PckStudio.Rendering +{ + internal class RenderBuffer + { + internal readonly VertexArray VertexArray; + internal readonly IndexBuffer IndexBuffer; + internal readonly PrimitiveType PrimitiveType; + + public RenderBuffer(VertexArray vertexArray, IndexBuffer indexBuffer, PrimitiveType primitiveType) + { + VertexArray = vertexArray; + IndexBuffer = indexBuffer; + PrimitiveType = primitiveType; + } + } +} diff --git a/PCK-Studio/Rendering/RenderGroup.cs b/PCK-Studio/Rendering/RenderGroup.cs new file mode 100644 index 00000000..2825af4e --- /dev/null +++ b/PCK-Studio/Rendering/RenderGroup.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OpenTK; +using OpenTK.Graphics.OpenGL; +using PckStudio.Extensions; +using PckStudio.Internal; + +namespace PckStudio.Rendering +{ + internal class RenderGroup + { + internal readonly string Name; + + private List vertices; + private List indices; + + private uint indicesOffset; + + internal RenderGroup(string name) + { + Name = name; + vertices = new List(); + indices = new List(); + indicesOffset = 0; + } + + internal RenderBuffer GetRenderBuffer() + { + var vertexData = vertices.ToArray(); + var buffer = new VertexBuffer(vertexData, vertexData.Length * TextureVertex.SizeInBytes); + var layout = new VertexBufferLayout(); + layout.Add(3); + layout.Add(2); + + var vertexArray = new VertexArray(); + + vertexArray.AddBuffer(buffer, layout); + + var indexBuffer = new IndexBuffer(indices.ToArray()); + + return new RenderBuffer(vertexArray, indexBuffer, PrimitiveType.Quads); + } + + internal void AddBox(SkinBOX skinBOX, Vector2 textureScale) + { + var position = skinBOX.Pos.ToOpenTKVector(); + var size = skinBOX.Size.ToOpenTKVector(); + var uv = skinBOX.UV.ToOpenTKVector(); + + var vertexData = new TextureVertex[] + { + new TextureVertex(new Vector3(position.X , size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z, uv.Y + size.Z) * textureScale), + new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z) * textureScale), + new TextureVertex(new Vector3(size.X + position.X, position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z + size.Y) * textureScale), + new TextureVertex(new Vector3(position.X , position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z, uv.Y + size.Z + size.Y) * textureScale), + + new TextureVertex(new Vector3(position.X , size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X * 2, uv.Y + size.Z) * textureScale), + new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X, uv.Y + size.Z) * textureScale), + new TextureVertex(new Vector3(size.X + position.X, position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X, uv.Y + size.Z + size.Y) * textureScale), + new TextureVertex(new Vector3(position.X , position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X * 2, uv.Y + size.Z + size.Y) * textureScale), + + new TextureVertex(new Vector3(position.X , size.Y + position.Y, position.Z), new Vector2(uv.X, uv.Y + size.Z) * textureScale), + new TextureVertex(new Vector3(position.X , position.Y, position.Z), new Vector2(uv.X, uv.Y + size.Z + size.Y) * textureScale), + new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y) * textureScale), + new TextureVertex(new Vector3(position.X , size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z, uv.Y) * textureScale), + + new TextureVertex(new Vector3(position.X , position.Y, position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y) * textureScale), + new TextureVertex(new Vector3(size.X + position.X, position.Y, position.Z), new Vector2(uv.X + size.Z + size.X * 2, uv.Y) * textureScale), + new TextureVertex(new Vector3(size.X + position.X, position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X * 2, uv.Y + size.Z) * textureScale), + new TextureVertex(new Vector3(position.X , position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z) * textureScale), + }; + + vertices.AddRange(vertexData); + + var indexStorage = new uint[] { + 0 + indicesOffset, 1 + indicesOffset, 2 + indicesOffset, 3 + indicesOffset, // Face 1 (Front) + 4 + indicesOffset, 5 + indicesOffset, 6 + indicesOffset, 7 + indicesOffset, // Face 2 (Back) + 0 + indicesOffset, 8 + indicesOffset, 9 + indicesOffset, 3 + indicesOffset, // Face 3 (Left) + 1 + indicesOffset, 5 + indicesOffset, 6 + indicesOffset, 2 + indicesOffset, // Face 4 (Right) + 0 + indicesOffset, 1 + indicesOffset, 10 + indicesOffset, 11 + indicesOffset, // Face 5(Top) + 12 + indicesOffset, 13 + indicesOffset, 14 + indicesOffset, 15 + indicesOffset// Face 6 (Bottom) + }; + indicesOffset += (uint)indexStorage.Length; + indices.AddRange(indexStorage); + } + } +} diff --git a/PCK-Studio/Rendering/Renderer.cs b/PCK-Studio/Rendering/Renderer.cs index 85e6c37b..ba943f37 100644 --- a/PCK-Studio/Rendering/Renderer.cs +++ b/PCK-Studio/Rendering/Renderer.cs @@ -9,12 +9,12 @@ namespace PckStudio.Rendering { internal static class Renderer { - public static void Draw(Shader shader, VertexArray va, IndexBuffer ib, PrimitiveType type) + public static void Draw(Shader shader, RenderBuffer renderBuffer) { shader.Bind(); - va.Bind(); - ib.Bind(); - GL.DrawElements(type, ib.GetCount(), DrawElementsType.UnsignedInt, 0); + renderBuffer.VertexArray.Bind(); + renderBuffer.IndexBuffer.Bind(); + GL.DrawElements(renderBuffer.PrimitiveType, renderBuffer.IndexBuffer.GetCount(), DrawElementsType.UnsignedInt, 0); } } } diff --git a/PCK-Studio/Rendering/Renderer3D.cs b/PCK-Studio/Rendering/Renderer3D.cs index f9443b2c..1653c917 100644 --- a/PCK-Studio/Rendering/Renderer3D.cs +++ b/PCK-Studio/Rendering/Renderer3D.cs @@ -26,468 +26,20 @@ https://github.com/KareemMAX/Minecraft-Skiner/blob/master/src/Minecraft%20skiner */ using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Drawing.Imaging; -using System.Linq; using System.Windows.Forms; -using PckStudio.Classes.Utils; -using Microsoft.VisualBasic; using OpenTK; -using OpenTK.Graphics.OpenGL; -using System.Diagnostics; -using PckStudio.Properties; -using System.Runtime.InteropServices; -using PckStudio.Extensions; -using Newtonsoft.Json.Linq; namespace PckStudio.Rendering { - public partial class Renderer3D : GLControl + internal class Renderer3D : GLControl { - private Bitmap _texture; - /// - /// The visible Texture on the renderer - /// - /// The visible Texture - [Description("The current Texture")] - [Category("Appearance")] - public Bitmap Texture - { - get => _texture; - set - { - if (shader is not null) - { - var texture = new Texture2D(value); - texture.Bind(1); - shader.SetUniform1("u_Texture", 1); - Refresh(); - } - TextureScaleValue = new Vector2(1f / value.Width, 1f / value.Height); - _texture = value; - } - } - - public enum Models - { - Steve, - Alex - } - /// - /// The rendered model - /// - /// The rendered model - [Description("The current player model")] - [Category("Appearance")] - public Models Model { get; set; } - - - private Vector2 _rotation = new Vector2(); - /// - /// Rotation - /// - /// Rotation - [Description("The rotation of the camera")] - [Category("Appearance")] - public Vector2 Rotation - { - get => _rotation; - set - { - value.X = MathHelper.Clamp(value.X, -90f, 90f); - value.Y = MathHelper.Clamp(value.Y, -180f, 180f); - _rotation = value; - } - } - - private double _fieldOfViewRadians = MinFOV; - - private const double MinFOVDegrees = 30d; - private const double MaxFOVDegrees = 90d; - - private static double MinFOV = MathHelper.DegreesToRadians(MinFOVDegrees); - private static double MaxFOV = MathHelper.DegreesToRadians(MaxFOVDegrees); - - [Description("The Field of View value (in Radians)")] - private double FieldOfViewRadians - { - get => _fieldOfViewRadians; - set => _fieldOfViewRadians = MathHelper.Clamp(value, MinFOV, MaxFOV); - } - - [Description("The Field of View (in Degrees)")] - [Category("Appearance")] - public double FieldOfView - { - get => MathHelper.RadiansToDegrees(_fieldOfViewRadians); - set => FieldOfViewRadians = MathHelper.DegreesToRadians(MathHelper.Clamp(value, MinFOVDegrees, MaxFOVDegrees)); - } - - private Vector2 _lookAngle = Vector2.Zero; - [Description("The offset from the orignal point (for zoom)")] - [Category("Appearance")] - public Vector2 LookAngle - { - get => _lookAngle; - set - { - value.X = MathHelper.Clamp(value.X, -8f, 8f); - value.Y = MathHelper.Clamp(value.Y, -16f, 16f); - _lookAngle = value; - } - } - - public float CameraDistance { get; set; } = 18f; - - private Matrix4 projection; - - private Matrix4 view; - - private Vector2 TextureScaleValue = new Vector2(1f / 64); - - private void GLDebugMessage(DebugSource source, DebugType type, int id, DebugSeverity severity, int length, IntPtr message, IntPtr userParam) - { - string msg = Marshal.PtrToStringAnsi(message, length); - Debug.WriteLine(source); - Debug.WriteLine(type); - Debug.WriteLine(severity); - Debug.WriteLine(id); - Debug.WriteLine(msg); - } - - private Shader shader; - - private VertexArray vertexArray; - private IndexBuffer indexBuffer; - private Matrix4 mvp; - - private bool IsMouseDown; - private bool IsRightMouseDown; - private bool IsMouseHidden; - private Point PreviousMouseLocation; - private Point MouseLoc; - - private Ray LastRay; - private Vector3 GlobalCameraPos; + protected Camera camera; public Renderer3D() { - InitializeComponent(); + VSync = true; + camera = new Camera(Vector2.Zero, 1f, Vector2.Zero, 30f); } - - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); - if (DesignMode) - return; - - MakeCurrent(); - - GL.DebugMessageCallback(GLDebugMessage, IntPtr.Zero); - - Trace.TraceInformation(GL.GetString(StringName.Version)); - - shader = Shader.Create(Resources.vertexShader, Resources.fragmentShader); - shader.Bind(); - - Texture = Resources.slim_template; - var bodyVertexData = new Vertex[] - { - // Face 1 - new Vertex(new Vector3(-4, 8, 2), Color.Red, new Vector2(TextureScaleValue.X * 20f, TextureScaleValue.Y * 20f)), - new Vertex(new Vector3( 4, 8, 2), Color.Red, new Vector2(TextureScaleValue.X * 28f, TextureScaleValue.Y * 20f)), - new Vertex(new Vector3( 4, -4, 2), Color.Red, new Vector2(TextureScaleValue.X * 28f, TextureScaleValue.Y * 32f)), - new Vertex(new Vector3(-4, -4, 2), Color.Red, new Vector2(TextureScaleValue.X * 20f, TextureScaleValue.Y * 32f)), - - // Face 2 - new Vertex(new Vector3(-4, 8, -2), Color.Red, new Vector2(TextureScaleValue.X * 40f, TextureScaleValue.Y * 20f)), - new Vertex(new Vector3( 4, 8, -2), Color.Red, new Vector2(TextureScaleValue.X * 32f, TextureScaleValue.Y * 20f)), - new Vertex(new Vector3( 4, -4, -2), Color.Red, new Vector2(TextureScaleValue.X * 32f, TextureScaleValue.Y * 32f)), - new Vertex(new Vector3(-4, -4, -2), Color.Red, new Vector2(TextureScaleValue.X * 40f, TextureScaleValue.Y * 32f)), - - // Face 3 - new Vertex(new Vector3(-4, 8, 2), Color.Red, new Vector2(TextureScaleValue.X * 20f, TextureScaleValue.Y * 20f)), - new Vertex(new Vector3(-4, 8, -2), Color.Red, new Vector2(TextureScaleValue.X * 16f, TextureScaleValue.Y * 20f)), - new Vertex(new Vector3(-4, -4, -2), Color.Red, new Vector2(TextureScaleValue.X * 16f, TextureScaleValue.Y * 32f)), - new Vertex(new Vector3(-4, -4, 2), Color.Red, new Vector2(TextureScaleValue.X * 20f, TextureScaleValue.Y * 32f)), - - // Face 4 - new Vertex(new Vector3( 4, 8, 2), Color.Red, new Vector2(TextureScaleValue.X * 28f, TextureScaleValue.Y * 20f)), - new Vertex(new Vector3( 4, 8, -2), Color.Red, new Vector2(TextureScaleValue.X * 32f, TextureScaleValue.Y * 20f)), - new Vertex(new Vector3( 4, -4, -2), Color.Red, new Vector2(TextureScaleValue.X * 32f, TextureScaleValue.Y * 32f)), - new Vertex(new Vector3( 4, -4, 2), Color.Red, new Vector2(TextureScaleValue.X * 28f, TextureScaleValue.Y * 32f)), - - // Face 5 - new Vertex(new Vector3(-4, 8, 2), Color.Red, new Vector2(TextureScaleValue.X * 20f, TextureScaleValue.Y * 20f)), - new Vertex(new Vector3( 4, 8, 2), Color.Red, new Vector2(TextureScaleValue.X * 28f, TextureScaleValue.Y * 20f)), - new Vertex(new Vector3( 4, 8, -2), Color.Red, new Vector2(TextureScaleValue.X * 28f, TextureScaleValue.Y * 16f)), - new Vertex(new Vector3(-4, 8, -2), Color.Red, new Vector2(TextureScaleValue.X * 20f, TextureScaleValue.Y * 16f)), - - // Face 6 - new Vertex(new Vector3(-4, -4, -2), Color.Red, new Vector2(TextureScaleValue.X * 28f, TextureScaleValue.Y * 16f)), - new Vertex(new Vector3( 4, -4, -2), Color.Red, new Vector2(TextureScaleValue.X * 36f, TextureScaleValue.Y * 16f)), - new Vertex(new Vector3( 4, -4, 2), Color.Red, new Vector2(TextureScaleValue.X * 36f, TextureScaleValue.Y * 20f)), - new Vertex(new Vector3(-4, -4, 2), Color.Red, new Vector2(TextureScaleValue.X * 28f, TextureScaleValue.Y * 20f)), - }; - - indexBuffer = new IndexBuffer( - 0, 1, 2, 3, - 4, 5, 6, 7, - 8, 9, 10, 11, - 12, 13, 14, 15, - 16, 17, 18, 19, - 20, 21, 22, 23 - ); - - vertexArray = new VertexArray(); - - int vertexSize = Marshal.SizeOf(typeof(Vertex)); - - var buffer = new VertexBuffer(bodyVertexData, bodyVertexData.Length * vertexSize); - var layout = new VertexBufferLayout(); - layout.Add(3); - layout.Add(4); - layout.Add(2); - - vertexArray.AddBuffer(buffer, layout); - - GLErrorCheck(); - } - - [Conditional("DEBUG")] - private void GLErrorCheck() - { - var error = GL.GetError(); - Debug.Assert(error == ErrorCode.NoError, error.ToString()); - } - - private void UpdateView() - { - var camera = new Vector3(LookAngle) { Z = CameraDistance }; - - var target = new Vector3(LookAngle); - - var up = new Vector3(0, 1f, 1f); - - view = Matrix4.LookAt(camera, target, up); - } - - private void UpdateProjection() - { - projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.Pow(FieldOfViewRadians, -1), Width / (float)Height, 1f, 100f); - } - - private void DrawBox(Vector3 scale, Vector3 position, Vector2 uv) - { - float[] Corner1 = { position.X, position.Y, position.Z }; - float[] Corner2 = { position.X + scale.X, position.Y, position.Z }; - float[] Corner3 = { position.X, position.Y + scale.Y, position.Z }; - float[] Corner4 = { position.X, position.Y, position.Z + scale.Z }; - float[] Corner5 = { position.X + scale.X, position.Y + scale.Y, position.Z }; - float[] Corner6 = { position.X, position.Y + scale.Y, position.Z + scale.Z }; - float[] Corner7 = { position.X + scale.X, position.Y, position.Z + scale.Z }; - float[] Corner8 = { position.X + scale.X, position.Y + scale.Y, position.Z + scale.Z }; - - GL.Color3(Color.Red); - // Face 1 - GL.Vertex3(Corner1); - GL.Vertex3(Corner3); - GL.Vertex3(Corner5); - GL.Vertex3(Corner2); - // Face 2 - GL.Vertex3(Corner1); - GL.Vertex3(Corner4); - GL.Vertex3(Corner7); - GL.Vertex3(Corner2); - // Face 3 - GL.Vertex3(Corner1); - GL.Vertex3(Corner4); - GL.Vertex3(Corner6); - GL.Vertex3(Corner3); - // Face 4 - GL.TexCoord2(uv.X, TextureScaleValue.Y * 8d); - GL.Vertex3(Corner4); - GL.TexCoord2(TextureScaleValue.X * 16d, TextureScaleValue.Y * 8d); - GL.Vertex3(Corner7); - GL.TexCoord2(TextureScaleValue.X * 16d, TextureScaleValue.Y * 16d); - GL.Vertex3(Corner8); - GL.TexCoord2(TextureScaleValue.X * 8d, TextureScaleValue.Y * 16d); - GL.Vertex3(Corner6); - // Face 5 - GL.Vertex3(Corner8); - GL.Vertex3(Corner6); - GL.Vertex3(Corner3); - GL.Vertex3(Corner5); - // Face 6 - GL.Vertex3(Corner2); - GL.Vertex3(Corner7); - GL.Vertex3(Corner8); - GL.Vertex3(Corner5); - } - - protected override void OnPaint(PaintEventArgs e) - { - if (DesignMode) - { - base.OnPaint(e); - return; - } - - UpdateProjection(); - UpdateView(); - - MakeCurrent(); - GL.Viewport(Size); - - Matrix4 transform = Matrix4.Identity; - Matrix4 scale = Matrix4.Identity; - Matrix4 rot = Matrix4.CreateFromAxisAngle(new Vector3(-1f, 0f, 0f), MathHelper.DegreesToRadians(Rotation.X)) - + Matrix4.CreateFromAxisAngle(new Vector3(0f, 1f, 0f), MathHelper.DegreesToRadians(Rotation.Y)); - - var model = transform * rot * scale; - - mvp = model * view * projection; - -#if DEBUG - debugLabel.Text = $"Rotation: {Rotation}\nFOV: {FieldOfView}\nView:\n{view}\nProjection:\n{projection}\nMVP:\n{mvp}"; -#endif - - shader.SetUniformMat4("u_MVP", ref mvp); - - GL.Enable(EnableCap.Texture2D); // Enable textures - //GL.Enable(EnableCap.DepthTest); // Enable correct Z Drawings - //GL.DepthFunc(DepthFunction.Less); // Enable correct Z Drawings - GL.Disable(EnableCap.Blend); // Disable transparent - GL.Disable(EnableCap.AlphaTest); // Disable transparent - - GL.ClearColor(BackColor); - GL.Clear(ClearBufferMask.ColorBufferBit); - GL.Clear(ClearBufferMask.DepthBufferBit); - - //GL.Enable(EnableCap.Blend); - //GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); - - //GL.Enable(EnableCap.AlphaTest); // Enable transparent - //GL.AlphaFunc(AlphaFunction.Greater, 0.4f); - - Renderer.Draw(shader, vertexArray, indexBuffer, PrimitiveType.Quads); - - SwapBuffers(); - return; - - GL.Disable(EnableCap.AlphaTest); // Disable transparent - } - -#if DEBUG - protected override bool ProcessDialogKey(Keys keyData) - { - switch (keyData) - { - case Keys.Escape: - debugLabel.Visible = !debugLabel.Visible; - return true; - case Keys.R: - Rotation = Vector2.Zero; - Refresh(); - return true; - case Keys.F1: - var fileDialog = new OpenFileDialog() - { - Filter = "texture|*.png", - }; - if (fileDialog.ShowDialog() == DialogResult.OK) - { - Texture = Image.FromFile(fileDialog.FileName) as Bitmap; - } - return true; - } - return base.ProcessDialogKey(keyData); - } -#endif - - protected override void OnMouseDown(MouseEventArgs e) - { - if (!IsMouseDown && 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 - if (!IsMouseHidden) // Hide the mouse - { - Cursor.Hide(); - IsMouseHidden = true; - } - MouseLoc = Cursor.Position; // Store the current mouse position to use it for the rotate action - IsMouseDown = true; - } - 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 - { - Cursor.Hide(); - IsMouseHidden = true; - } - MouseLoc = Cursor.Position; // Store the current mouse position to use it for the move action - IsRightMouseDown = true; - } - } - - protected override void OnMouseUp(MouseEventArgs e) - { - if (IsMouseHidden) - { - Cursor.Position = PreviousMouseLocation; - IsMouseDown = IsMouseHidden = IsRightMouseDown = false; - Cursor.Show(); - } - } - - private void Move_Tick(object sender, EventArgs e) - { - // Rotate the model - if (IsMouseDown) - { - float rotationYDelta = (float)Math.Round((Cursor.Position.X - MouseLoc.X) * 0.5f); - float rotationXDelta = (float)Math.Round(-(Cursor.Position.Y - MouseLoc.Y) * 0.5f); - Rotation += 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; - return; - } - // Move the model - if (IsRightMouseDown) - { - float deltaX = -(Cursor.Position.X - MouseLoc.X) * 0.05f / (float)FieldOfViewRadians; - float deltaY = (Cursor.Position.Y - MouseLoc.Y) * 0.05f / (float)FieldOfViewRadians; - LookAngle += 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; - } - } - - protected override void OnMouseWheel(MouseEventArgs e) - { - FieldOfViewRadians += e.Delta * 0.005d; - Refresh(); - base.OnMouseWheel(e); - } - - private Vector3 GetCameraPosition(Matrix4 view) - { - return Matrix4.Invert(view).ExtractTranslation(); - } - - private List MousePoints = new List(); - private List tmpMousePoints = new List(); - - public event TextureChangedEventHandler TextureChanged; - - public delegate void TextureChangedEventHandler(object sender, bool IsLeft); } } diff --git a/PCK-Studio/Rendering/Shader.cs b/PCK-Studio/Rendering/Shader.cs index 3e32aa43..52f22d6b 100644 --- a/PCK-Studio/Rendering/Shader.cs +++ b/PCK-Studio/Rendering/Shader.cs @@ -96,7 +96,7 @@ namespace PckStudio.Rendering GL.LinkProgram(programId); GL.ValidateProgram(programId); - Trace.TraceInformation(GL.GetProgramInfoLog(programId)); + Debug.WriteLine(GL.GetProgramInfoLog(programId), category: nameof(Shader)); GL.DeleteShader(vertexShader); GL.DeleteShader(fragmentShader); diff --git a/PCK-Studio/Rendering/Renderer3D.Designer.cs b/PCK-Studio/Rendering/SkinRenderer.Designer.cs similarity index 51% rename from PCK-Studio/Rendering/Renderer3D.Designer.cs rename to PCK-Studio/Rendering/SkinRenderer.Designer.cs index ddd4450b..a930ab2f 100644 --- a/PCK-Studio/Rendering/Renderer3D.Designer.cs +++ b/PCK-Studio/Rendering/SkinRenderer.Designer.cs @@ -1,9 +1,13 @@ using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; namespace PckStudio.Rendering { - public partial class Renderer3D + internal partial class SkinRenderer { [DebuggerNonUserCode()] protected override void Dispose(bool disposing) @@ -35,42 +39,14 @@ namespace PckStudio.Rendering moveTimer.Tick += new EventHandler(Move_Tick); SuspendLayout(); // - // timMove + // moveTimer // moveTimer.Enabled = true; - moveTimer.Interval = 20; -#if DEBUG - // - // debugLabel - // - debugLabel = new System.Windows.Forms.Label(); - debugLabel.Enabled = true; - debugLabel.Visible = false; - debugLabel.AutoSize = true; - debugLabel.Location = new System.Drawing.Point(0, 0); - debugLabel.BackColor = System.Drawing.Color.Transparent; - Controls.Add(debugLabel);; -#endif - // - // Renderer3D - // - Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - BackColor = System.Drawing.Color.LightGray; - Location = new System.Drawing.Point(0, 0); - Size = new System.Drawing.Size(150, 150); - TabIndex = 0; - VSync = true; - AutoScaleDimensions = new System.Drawing.SizeF(6.0f, 13.0f); - AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + moveTimer.Interval = 10; Name = "Renderer3D"; ResumeLayout(false); - } private System.Windows.Forms.Timer moveTimer; -#if DEBUG - private System.Windows.Forms.Label debugLabel; -#endif - } -} \ No newline at end of file +} diff --git a/PCK-Studio/Rendering/SkinRenderer.cs b/PCK-Studio/Rendering/SkinRenderer.cs new file mode 100644 index 00000000..00990b1b --- /dev/null +++ b/PCK-Studio/Rendering/SkinRenderer.cs @@ -0,0 +1,385 @@ +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 static System.Windows.Forms.VisualStyles.VisualStyleElement.Tab; +using System.Windows.Media.Media3D; +using PckStudio.Extensions; +using OpenTK.Graphics.OpenGL; +using System.Windows.Forms; +using System.ComponentModel; +using System.Drawing; +using System.Runtime.InteropServices; +using PckStudio.Properties; + +namespace PckStudio.Rendering +{ + internal partial class SkinRenderer : Renderer3D + { + /// + /// The visible Texture on the renderer + /// + /// The visible Texture + [Description("The current Texture")] + [Category("Appearance")] + public Bitmap Texture + { + get => _texture; + set + { + if (skinShader is not null) + { + var texture = new Texture2D(value); + texture.Bind(0); + skinShader.SetUniform1("u_Texture", 0); + Refresh(); + } + TextureScaleValue = new Vector2(1f / value.Width, 1f / value.Height); + _texture = value; + } + } + + private Vector2 _lookAngle = Vector2.Zero; + [Description("The offset from the orignal point (for zoom)")] + [Category("Appearance")] + public Vector2 LookAngle + { + get => _lookAngle; + set + { + _lookAngle = value; + camera.LookAt(value); + } + } + + private Vector2 TextureScaleValue = new Vector2(1f / 64); + + private void GLDebugMessage(DebugSource source, DebugType type, int id, DebugSeverity severity, int length, IntPtr message, IntPtr userParam) + { + string msg = Marshal.PtrToStringAnsi(message, length); + Debug.WriteLine(source); + Debug.WriteLine(type); + Debug.WriteLine(severity); + Debug.WriteLine(id); + Debug.WriteLine(msg); + } + + private Vector2 _modelRotation; + private Vector2 modelRotation + { + get => _modelRotation; + set + { + _modelRotation.X = MathHelper.Clamp(value.X, -5f, 5f); + _modelRotation.Y = MathHelper.Clamp(value.Y, -180f, 180f); + } + } + + private bool IsMouseDown; + private bool IsRightMouseDown; + private bool IsMouseHidden; + private Point PreviousMouseLocation; + private Point MouseLoc; + private Shader skinShader; + + private Dictionary renderGroups; + + private Bitmap _texture; + + public SkinRenderer() + { + InitializeComponent(); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + if (DesignMode) + return; + MakeCurrent(); + + camera = new Camera(new Vector2(0f, 1f), 36f, Vector2.Zero, 60f); + + camera.MinimumFov = 30f; + camera.MaximumFov = 90f; + + camera.LookAt(new Vector2(0f, 5f)); + + GL.DebugMessageCallback(GLDebugMessage, IntPtr.Zero); + + Trace.TraceInformation(GL.GetString(StringName.Version)); + + skinShader = Shader.Create(Resources.skinVertexShader, Resources.skinFragment); + skinShader.Bind(); + + Texture = Resources.slim_template; + + renderGroups = new Dictionary(6) + { + { "HEAD", new RenderGroup("HEAD") }, + { "BODY", new RenderGroup("BODY") }, + { "ARM0", new RenderGroup("ARM0") }, + { "ARM1", new RenderGroup("ARM1") }, + { "LEG0", new RenderGroup("LEG0") }, + { "LEG1", new RenderGroup("LEG1") } + }; + + var headbox = new SkinBOX("HEAD", new(-4, -8, -4), new(8, 8, 8), new( 0, 0)); + var bodybox = new SkinBOX("BODY", new(-4, 0, -2), new(8, 12, 4), new(16, 16)); + var arm0box = new SkinBOX("ARM0", new(-3, -2, -2), new(4, 12, 4), new(40, 16)); + var arm1box = new SkinBOX("ARM1", new(-1, -2, -2), new(4, 12, 4), new(32, 48)); + var leg0box = new SkinBOX("LEG0", new(-2, 0, -2), new(4, 12, 4), new( 0, 16)); + var leg1box = new SkinBOX("LEG1", new(-2, 0, -2), new(4, 12, 4), new(16, 48)); + + AddGroup(headbox, TextureScaleValue); + AddGroup(bodybox, TextureScaleValue); + AddGroup(arm0box, TextureScaleValue); + AddGroup(arm1box, TextureScaleValue); + AddGroup(leg0box, TextureScaleValue); + AddGroup(leg1box, TextureScaleValue); + + GLErrorCheck(); + } + + private void AddGroup(SkinBOX skinBox, Vector2 textureScaleValue) + { + if (!renderGroups.ContainsKey(skinBox.Type)) + throw new KeyNotFoundException(skinBox.Type); + + renderGroups[skinBox.Type].AddBox(skinBox, textureScaleValue); + } + + [Conditional("DEBUG")] + private void GLErrorCheck() + { + var error = GL.GetError(); + Debug.Assert(error == ErrorCode.NoError, error.ToString()); + } + + private RenderBuffer GetBox3D(SkinBOX skinBOX) + { + return GetBox3D(skinBOX.Pos.ToOpenTKVector(), skinBOX.Size.ToOpenTKVector(), skinBOX.UV.ToOpenTKVector()); + } + + private RenderBuffer GetBox3D(Vector3 position, Vector3 size, Vector2 uv) + { + var vertexData = new TextureVertex[] + { + new TextureVertex(new Vector3(position.X , size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z, uv.Y + size.Z) * TextureScaleValue), + new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z) * TextureScaleValue), + new TextureVertex(new Vector3(size.X + position.X, position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z + size.Y) * TextureScaleValue), + new TextureVertex(new Vector3(position.X , position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z, uv.Y + size.Z + size.Y) * TextureScaleValue), + + new TextureVertex(new Vector3(position.X , size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X * 2, uv.Y + size.Z) * TextureScaleValue), + new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X, uv.Y + size.Z) * TextureScaleValue), + new TextureVertex(new Vector3(size.X + position.X, position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X, uv.Y + size.Z + size.Y) * TextureScaleValue), + new TextureVertex(new Vector3(position.X , position.Y, position.Z), new Vector2(uv.X + size.Z * 2 + size.X * 2, uv.Y + size.Z + size.Y) * TextureScaleValue), + + new TextureVertex(new Vector3(position.X , size.Y + position.Y, position.Z), new Vector2(uv.X, uv.Y + size.Z) * TextureScaleValue), + new TextureVertex(new Vector3(position.X , position.Y, position.Z), new Vector2(uv.X, uv.Y + size.Z + size.Y) * TextureScaleValue), + new TextureVertex(new Vector3(size.X + position.X, size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y) * TextureScaleValue), + new TextureVertex(new Vector3(position.X , size.Y + position.Y, position.Z), new Vector2(uv.X + size.Z, uv.Y) * TextureScaleValue), + + new TextureVertex(new Vector3(position.X , position.Y, position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y) * TextureScaleValue), + new TextureVertex(new Vector3(size.X + position.X, position.Y, position.Z), new Vector2(uv.X + size.Z + size.X * 2, uv.Y) * TextureScaleValue), + new TextureVertex(new Vector3(size.X + position.X, position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X * 2, uv.Y + size.Z) * TextureScaleValue), + new TextureVertex(new Vector3(position.X , position.Y, size.Z + position.Z), new Vector2(uv.X + size.Z + size.X, uv.Y + size.Z) * TextureScaleValue), + }; + + var indexBuffer = new IndexBuffer( + 0, 1, 2, 3, // Face 1 (Front) + 4, 5, 6, 7, // Face 2 (Back) + 0, 8, 9, 3, // Face 3 (Left) + 1, 5, 6, 2, // Face 4 (Right) + 0, 1, 10, 11, // Face 5(Top) + 12, 13, 14, 15 // Face 6 (Bottom) + ); + + var buffer = new VertexBuffer(vertexData, vertexData.Length * TextureVertex.SizeInBytes); + var layout = new VertexBufferLayout(); + layout.Add(3); + layout.Add(4); + layout.Add(2); + + var vertexArray = new VertexArray(); + + vertexArray.AddBuffer(buffer, layout); + + return new RenderBuffer(vertexArray, indexBuffer, PrimitiveType.Quads); + } + + private Matrix4 GetModelFromSkinBOX(SkinBOX skinBox) + { + return Matrix4.CreateTranslation(skinBox.Pos.ToOpenTKVector()) * Matrix4.CreateScale(skinBox.Scale); + } + + protected override bool ProcessDialogKey(Keys keyData) + { + switch (keyData) + { + case Keys.R: + modelRotation = Vector2.Zero; + LookAngle = Vector2.Zero; + Refresh(); + return true; + case Keys.F1: + var fileDialog = new OpenFileDialog() + { + Filter = "texture|*.png", + }; + if (fileDialog.ShowDialog() == DialogResult.OK) + { + Texture = Image.FromFile(fileDialog.FileName) as Bitmap; + } + return true; + } + return base.ProcessDialogKey(keyData); + } + + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + if (DesignMode) + { + return; + } + + MakeCurrent(); + + camera.Update(Size.Width / (float)Size.Height); + + var viewProjection = camera.GetViewProjection(); + skinShader.SetUniformMat4("u_ViewProjection", ref viewProjection); + + GL.Viewport(Size); + + GL.ClearColor(BackColor); + GL.Clear(ClearBufferMask.ColorBufferBit); + GL.Clear(ClearBufferMask.DepthBufferBit); + + GL.Enable(EnableCap.Texture2D); // Enable textures + GL.Enable(EnableCap.DepthTest); // Enable correct Z Drawings + GL.DepthFunc(DepthFunction.Lequal); // Enable correct Z Drawings + GL.Disable(EnableCap.AlphaTest); // Disable transparent + + GL.Enable(EnableCap.Blend); + GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + + GL.Enable(EnableCap.AlphaTest); // Enable transparent + GL.AlphaFunc(AlphaFunction.Greater, 0.4f); + + Matrix4 transform = Matrix4.CreateTranslation(new Vector3(0f, 16f, 0f)); + Matrix4 rotation = Matrix4.CreateFromAxisAngle(new Vector3(-1f, 0f, 0f), MathHelper.DegreesToRadians(modelRotation.X)) + * Matrix4.CreateFromAxisAngle(new Vector3(0f, 1f, 0f), MathHelper.DegreesToRadians(modelRotation.Y)); + + var model = transform * rotation; + + skinShader.SetUniformMat4("u_Model", ref model); + Renderer.Draw(skinShader, renderGroups["HEAD"].GetRenderBuffer()); + + transform = Matrix4.CreateTranslation(new Vector3(0f, -4f, 0f)); + model = transform * rotation; + + skinShader.SetUniformMat4("u_Model", ref model); + Renderer.Draw(skinShader, renderGroups["BODY"].GetRenderBuffer()); + + transform = Matrix4.CreateTranslation(new Vector3(-5f, -2f, 0f)); + model = transform * rotation; + + skinShader.SetUniformMat4("u_Model", ref model); + Renderer.Draw(skinShader, renderGroups["ARM0"].GetRenderBuffer()); + + transform = Matrix4.CreateTranslation(new Vector3(5f, -2f, 0f)); + model = transform * rotation; + + skinShader.SetUniformMat4("u_Model", ref model); + Renderer.Draw(skinShader, renderGroups["ARM1"].GetRenderBuffer()); + + transform = Matrix4.CreateTranslation(new Vector3(-2f, -16f, 0f)); + model = transform * rotation; + + skinShader.SetUniformMat4("u_Model", ref model); + Renderer.Draw(skinShader, renderGroups["LEG0"].GetRenderBuffer()); + + transform = Matrix4.CreateTranslation(new Vector3(2f, -16f, 0f)); + model = transform * rotation; + + skinShader.SetUniformMat4("u_Model", ref model); + Renderer.Draw(skinShader, renderGroups["LEG1"].GetRenderBuffer()); + + SwapBuffers(); + } + + protected override void OnMouseWheel(MouseEventArgs e) + { + camera.Fov -= e.Delta / System.Windows.Input.Mouse.MouseWheelDeltaForOneLine; + Refresh(); + } + + protected override void OnMouseDown(MouseEventArgs e) + { + if (!IsMouseDown && 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 + if (!IsMouseHidden) // Hide the mouse + { + Cursor.Hide(); + IsMouseHidden = true; + } + MouseLoc = Cursor.Position; // Store the current mouse position to use it for the rotate action + IsMouseDown = true; + } + 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 + { + Cursor.Hide(); + IsMouseHidden = true; + } + MouseLoc = Cursor.Position; // Store the current mouse position to use it for the move action + IsRightMouseDown = true; + } + } + + protected override void OnMouseUp(MouseEventArgs e) + { + if (IsMouseHidden) + { + Cursor.Position = PreviousMouseLocation; + IsMouseDown = IsMouseHidden = IsRightMouseDown = false; + Cursor.Show(); + } + } + + private void Move_Tick(object sender, EventArgs e) + { + // Rotate the model + if (IsMouseDown) + { + float rotationYDelta = (float)Math.Round((Cursor.Position.X - MouseLoc.X) * 0.5f); + float rotationXDelta = (float)Math.Round(-(Cursor.Position.Y - MouseLoc.Y) * 0.5f); + modelRotation += 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; + return; + } + // Move the model + 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); + LookAngle += 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; + } + } + } +} diff --git a/PCK-Studio/Rendering/Texture2D.cs b/PCK-Studio/Rendering/Texture2D.cs index ffdfa784..2016c10b 100644 --- a/PCK-Studio/Rendering/Texture2D.cs +++ b/PCK-Studio/Rendering/Texture2D.cs @@ -51,11 +51,6 @@ namespace PckStudio.Rendering GL.BindTexture(TextureTarget.Texture2D, _id); } - public void Bind() - { - Bind(0); - } - [Conditional("DEBUG")] public void Unbind() { diff --git a/PCK-Studio/Rendering/Vertex.cs b/PCK-Studio/Rendering/TextureVertex.cs similarity index 73% rename from PCK-Studio/Rendering/Vertex.cs rename to PCK-Studio/Rendering/TextureVertex.cs index 8880a23f..682db8bf 100644 --- a/PCK-Studio/Rendering/Vertex.cs +++ b/PCK-Studio/Rendering/TextureVertex.cs @@ -11,17 +11,17 @@ using OpenTK.Graphics; namespace PckStudio.Rendering { [StructLayout(LayoutKind.Sequential, Pack = 4)] - internal struct Vertex + internal struct TextureVertex { - public Vertex(Vector3 position, Color4 color, Vector2 texPosition) + public static int SizeInBytes = Marshal.SizeOf(typeof(TextureVertex)); + + public TextureVertex(Vector3 position, Vector2 texPosition) { Position = position; - Color = color; TexPosition = texPosition; } internal Vector3 Position { get; set; } - internal Color4 Color { get; set; } internal Vector2 TexPosition { get; set; } } } diff --git a/PCK-Studio/Resources/fragment.glsl b/PCK-Studio/Resources/fragment.glsl deleted file mode 100644 index 0e178897..00000000 --- a/PCK-Studio/Resources/fragment.glsl +++ /dev/null @@ -1,19 +0,0 @@ -#version 330 core - -layout(location = 0) out vec4 color; - -uniform sampler2D u_Texture; - -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 = v_Color; - // color = vec4(v_TexCoord, 0.0, 1.0); - color = texColor; -}; \ No newline at end of file diff --git a/PCK-Studio/Resources/shader/skinFragment.glsl b/PCK-Studio/Resources/shader/skinFragment.glsl new file mode 100644 index 00000000..fdd6d42c --- /dev/null +++ b/PCK-Studio/Resources/shader/skinFragment.glsl @@ -0,0 +1,13 @@ +#version 330 core + +layout(location = 0) out vec4 color; + +uniform sampler2D u_Texture; + +in vec2 v_TexCoord; + +void main() +{ + vec4 texColor = texture(u_Texture, v_TexCoord); + color = texColor; +}; \ No newline at end of file diff --git a/PCK-Studio/Resources/shader/skinVertexShader.glsl b/PCK-Studio/Resources/shader/skinVertexShader.glsl new file mode 100644 index 00000000..4bc46529 --- /dev/null +++ b/PCK-Studio/Resources/shader/skinVertexShader.glsl @@ -0,0 +1,15 @@ +#version 330 core + +layout(location = 0) in vec4 vertexPosition; +layout(location = 1) in vec2 texCoord; + +uniform mat4 u_ViewProjection; +uniform mat4 u_Model; + +out vec2 v_TexCoord; + +void main() +{ + v_TexCoord = texCoord; + gl_Position = u_ViewProjection * u_Model * vertexPosition; +}; \ No newline at end of file diff --git a/PCK-Studio/Resources/vertexShader.glsl b/PCK-Studio/Resources/vertexShader.glsl deleted file mode 100644 index 439dc0d1..00000000 --- a/PCK-Studio/Resources/vertexShader.glsl +++ /dev/null @@ -1,19 +0,0 @@ -#version 330 core - -layout(location = 0) in vec4 vertexPosition; -layout(location = 1) in vec4 color; -layout(location = 2) in vec2 texCoord; - -uniform mat4 u_MVP; - -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_MVP * vertexPosition; -}; \ No newline at end of file