Move Debug & Camera control into SceneViewport

This commit is contained in:
miku-666
2024-10-06 19:03:36 +02:00
parent ea63bb58f9
commit dab56be662
8 changed files with 431 additions and 384 deletions

View File

@@ -26,8 +26,6 @@ namespace PckStudio.Rendering
{
internal class CubeMesh : GenericMesh<TextureVertex>
{
internal bool ShouldRender { get; } = true;
private Cube _cube;
public Vector3 Center => _cube.Center;
@@ -53,7 +51,7 @@ namespace PckStudio.Rendering
22, 23, 20
];
public override Matrix4 Transform => Matrix4.CreateScale(1f, -1f, -1f);
public override Matrix4 Transform => Matrix4.Identity;
internal static VertexBufferLayout VertexBufferLayout { get; } = new VertexBufferLayout().Add(ShaderDataType.Float3).Add(ShaderDataType.Float2);
@@ -62,25 +60,24 @@ namespace PckStudio.Rendering
}
private CubeMesh(string name, Cube cube, bool visible)
: base(name, OpenTK.Graphics.OpenGL.PrimitiveType.Triangles, VertexBufferLayout)
: base(name, visible, OpenTK.Graphics.OpenGL.PrimitiveType.Triangles, VertexBufferLayout)
{
ShouldRender = visible;
_cube = cube;
}
public CubeMesh SetName(string name)
{
_ = name ?? throw new ArgumentNullException(nameof(name));
return new CubeMesh(name, _cube, ShouldRender);
return new CubeMesh(name, _cube, Visible);
}
public CubeMesh SetCube(Cube cube)
{
_ = cube ?? throw new ArgumentNullException(nameof(cube));
return new CubeMesh(Name, cube, ShouldRender);
return new CubeMesh(Name, cube, Visible);
}
public CubeMesh SetVisible(bool visible) => new CubeMesh(Name, _cube, visible);
public override GenericMesh<TextureVertex> SetVisible(bool visible) => new CubeMesh(Name, _cube, visible);
public Cube GetCube() => _cube;
@@ -135,10 +132,5 @@ namespace PckStudio.Rendering
}
internal override IEnumerable<int> GetIndices() => IndicesData;
public override string ToString()
{
return base.ToString() + $" Render={ShouldRender}";
}
}
}

View File

@@ -37,39 +37,28 @@ namespace PckStudio.Rendering
}
}
internal class CubeMeshCollection : GenericMesh<TextureVertex>, ICollection<CubeMesh>
internal class CubeMeshCollection : GenericMesh<TextureVertex>, ICollection<GenericMesh<TextureVertex>>
{
private List<CubeMesh> cubes;
private List<GenericMesh<TextureVertex>> cubes;
private Dictionary<string, CubeMeshCollection> subCollection;
public bool FlipZMapping
{
get => _flipZMapping;
set
{
_flipZMapping = value;
//foreach (Cube cube in cubes)
//{
// cube.FlipZMapping = FlipZMapping;
//}
set => _flipZMapping = value;
}
}
public Vector3 Translation { get; }
public Vector3 Translation { get; set; }
public Vector3 Rotation { get; }
public Vector3 Pivot { get; }
private Vector3 _offset { get; set; } = Vector3.Zero;
public Vector3 Offset
{
get => _offset;
set
{
if (value != _offset)
{
_offset = value;
set => _offset = value;
}
}
}
public override Matrix4 Transform => Matrix4.CreateTranslation(Translation + _offset) * Matrix4.CreateScale(1f, -1f, -1f);
public override Matrix4 Transform => (Matrix4.CreateRotationX(MathHelper.DegreesToRadians(Rotation.X)) * Matrix4.CreateRotationY(MathHelper.DegreesToRadians(Rotation.Y)) * Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(Rotation.Z))).Pivoted(Translation + _offset, Pivot);
public int Count => cubes.Count;
@@ -77,32 +66,46 @@ namespace PckStudio.Rendering
private bool _flipZMapping = false;
internal CubeMeshCollection(string name) : base(name, PrimitiveType.Triangles, CubeMesh.VertexBufferLayout)
internal CubeMeshCollection(string name, bool visible = true) : base(name, visible, PrimitiveType.Triangles, CubeMesh.VertexBufferLayout)
{
cubes = new List<CubeMesh>(5);
cubes = new List<GenericMesh<TextureVertex>>(5);
subCollection = new Dictionary<string, CubeMeshCollection>();
}
internal CubeMeshCollection(string name, Vector3 translation, Vector3 pivot)
internal CubeMeshCollection(string name, Vector3 translation, Vector3 pivot, Vector3 rotation = default)
: this(name)
{
Translation = translation;
Pivot = pivot;
Rotation = rotation;
}
public override GenericMesh<TextureVertex> SetVisible(bool visible)
{
if (Visible == visible)
return this;
var mesh = new CubeMeshCollection(Name, visible);
mesh.cubes = this.cubes;
return mesh;
}
internal override IEnumerable<TextureVertex> GetVertices()
=> cubes.Where(c => c.ShouldRender).SelectMany(c => c.GetVertices());
=> cubes.Where(c => c.Visible).SelectMany(c =>
c.GetVertices().Select(vertex => new TextureVertex(Vector3.TransformPosition(vertex.Position, c.Transform), vertex.TexPosition))
);
internal override IEnumerable<int> GetIndices()
{
int offset = 0;
IEnumerable<int> selector(CubeMesh c)
IEnumerable<int> selector(GenericMesh<TextureVertex> c)
{
IEnumerable<int> result = c.GetIndices().Select(i => i + offset).ToArray();
int vertexCount = c.GetVertices().Count();
offset += vertexCount;
return result;
}
return cubes.Where(c => c.ShouldRender).SelectMany(selector);
return cubes.Where(c => c.Visible).SelectMany(selector);
}
internal void Add(Vector3 position, Vector3 size, Vector2 uv, float inflate = 0f, bool mirrorTexture = false)
@@ -117,6 +120,19 @@ namespace PckStudio.Rendering
Add(new CubeMesh(cube).SetName(name));
}
internal void AddSubCollection(string name, Vector3 translation, Vector3 pivot, Vector3 rotation = default)
{
var item = new CubeMeshCollection(name, translation, pivot, rotation);
Add(item);
subCollection.Add(name, item);
}
internal CubeMeshCollection GetCollection(string collectionName)
{
_ = collectionName ?? throw new ArgumentNullException(nameof(collectionName));
return ContainsCollection(collectionName) ? subCollection[collectionName] : null;
}
internal void Remove(int index)
{
if (!cubes.IndexInRange(index))
@@ -130,7 +146,9 @@ namespace PckStudio.Rendering
if (!cubes.IndexInRange(index))
throw new IndexOutOfRangeException();
cubes[index] = cubes[index].SetCube(new Cube(position, size, uv, inflate, mirrorTexture, FlipZMapping));
if (cubes[index] is CubeMesh cubeMesh)
cubes[index] = cubeMesh.SetCube(new Cube(position, size, uv, inflate, mirrorTexture, FlipZMapping));
}
internal Vector3 GetCenter(int index)
@@ -138,7 +156,7 @@ namespace PckStudio.Rendering
if (!cubes.IndexInRange(index))
throw new IndexOutOfRangeException();
return cubes[index].Center + Offset;
return cubes[index] is CubeMesh c ? c.Center + Offset : Vector3.Zero;
}
internal BoundingBox GetCubeBoundingBox(int index)

View File

@@ -24,19 +24,22 @@ SOFTWARE.
https://github.com/KareemMAX/Minecraft-Skiner
https://github.com/KareemMAX/Minecraft-Skiner/blob/master/src/Minecraft%20skiner/UserControls/Renderer3D.vb
*/
#define USE_FRAMEBUFFER
//#define USE_FRAMEBUFFER
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using PckStudio.Extensions;
using PckStudio.Properties;
using PckStudio.Rendering.Camera;
using PckStudio.Rendering.Shader;
using PckStudio.Rendering.Texture;
namespace PckStudio.Rendering
{
@@ -55,16 +58,39 @@ namespace PckStudio.Rendering
}
}
public new Color BackColor
{
get => base.BackColor;
set
{
base.BackColor = value;
if (!DesignMode)
{
Renderer.SetClearColor(value);
}
}
}
protected new bool DesignMode => base.DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime;
protected PerspectiveCamera Camera { get; }
protected virtual void OnUpdate(object sender, TimeSpan timestep)
{
SwapBuffers();
if (IsHandleCreated && !IsDisposed)
SwapBuffers();
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool LockMousePosition { get; set; } = false;
public float MouseSensetivity { get; set; } = 0.01f;
private Point PreviousMouseLocation;
private Point CurrentMouseLocation;
private int _refreshRate = 120;
private Timer _timer;
private Stopwatch _stopwatch;
private bool _initialized;
private ShaderLibrary _shaderLibrary;
@@ -75,6 +101,20 @@ namespace PckStudio.Rendering
private IndexBuffer _meshIndexBuffer;
private Dictionary<Type, VertexArray> _meshTypeVertexArray;
private bool IsMouseHidden
{
get => !Cursor.IsVisible();
set
{
if (value)
{
Cursor.Hide();
return;
}
Cursor.Show();
}
}
#if USE_FRAMEBUFFER
private FrameBuffer _framebuffer;
private Texture2D _framebufferTexture;
@@ -93,25 +133,30 @@ namespace PckStudio.Rendering
};
#endif
public SceneViewport() : base()
public SceneViewport(float fov, Vector3 camareaPosition = default)
#if DEBUG
: base(GraphicsMode.Default, 4, 6, GraphicsContextFlags.Debug)
#else
: base()
#endif
{
VSync = true;
_stopwatch = new Stopwatch();
_timer = new Timer();
_timer.Tick += TimerTick;
RefreshRate = _refreshRate;
Camera = new PerspectiveCamera(fov, camareaPosition);
_shaderLibrary = new ShaderLibrary();
if (!DesignMode)
{
_timer.Start();
_stopwatch.Start();
InitializeInternal();
}
RefreshRate = _refreshRate;
Camera = new PerspectiveCamera(60f, new Vector3(0f, 0f, 0f));
_shaderLibrary = new ShaderLibrary();
_initialized = false;
}
protected void Initialize()
private void InitializeInternal()
{
if (_initialized)
{
@@ -119,6 +164,8 @@ namespace PckStudio.Rendering
return;
}
MakeCurrent();
Trace.TraceInformation(GL.GetString(StringName.Version));
GL.DebugMessageCallback(DebugProc, IntPtr.Zero);
AddShader("Internal_colorShader", ShaderProgram.Create(Resources.plainColorVertexShader, Resources.plainColorFragmentShader));
var vao = new VertexArray();
VertexBufferLayout layout = new VertexBufferLayout();
@@ -144,27 +191,43 @@ namespace PckStudio.Rendering
GLErrorCheck();
}
#endif
InitializeDebugComponents();
InitializeDebugShaders();
_initialized = true;
}
protected override bool ProcessDialogKey(Keys keyData)
{
switch (keyData)
{
#if DEBUG
case Keys.Escape:
ReleaseMouse();
debugContextMenuStrip1.Show(this, Point.Empty);
return true;
#endif
}
return base.ProcessDialogKey(keyData);
}
protected override void Dispose(bool disposing)
{
if (DesignMode)
return;
if (disposing)
{
_timer.Stop();
_stopwatch.Stop();
_timer.Dispose();
MakeCurrent();
foreach (VertexArray va in _meshTypeVertexArray.Values)
{
va.Dispose();
}
_meshIndexBuffer.Dispose();
_boundingBoxDrawContext.IndexBuffer.Dispose();
_boundingBoxDrawContext.VertexArray.Dispose();
_shaderLibrary.Dispose();
}
MakeCurrent();
foreach (VertexArray va in _meshTypeVertexArray.Values)
{
va.Dispose();
}
_meshIndexBuffer.Dispose();
_boundingBoxDrawContext.IndexBuffer.Dispose();
_boundingBoxDrawContext.VertexArray.Dispose();
_shaderLibrary.Dispose();
_initialized = false;
base.Dispose(disposing);
}
@@ -175,8 +238,12 @@ namespace PckStudio.Rendering
protected ShaderProgram GetShader(string shaderName) => _shaderLibrary.GetShader(shaderName);
protected void DrawMesh<T>(GenericMesh<T> mesh, ShaderProgram shader) where T : struct
protected void DrawMesh<T>(GenericMesh<T> mesh, ShaderProgram shader, Matrix4 transform) where T : struct
{
Matrix4 viewProjection = Camera.GetViewProjection();
shader.Bind();
shader.SetUniformMat4("ViewProjection", ref viewProjection);
shader.SetUniformMat4("Transform", ref transform);
if (!_meshTypeVertexArray.ContainsKey(typeof(T)))
{
VertexArray vertexArray = new VertexArray();
@@ -213,6 +280,17 @@ namespace PckStudio.Rendering
Renderer.SetLineWidth(1f);
}
protected BoundingBox GetBounds(IEnumerable<BoundingBox> boundingBoxes)
{
return boundingBoxes.Aggregate((a, b) => new BoundingBox(Vector3.ComponentMin(a.Start, b.Start), Vector3.ComponentMax(a.End, b.End)));
}
void DebugProc(DebugSource source, DebugType type, int id, DebugSeverity severity, int length, IntPtr message, IntPtr userParam)
{
string dbgMessage = Marshal.PtrToStringAnsi(message, length);
Debug.WriteLine($"{source} {type} {severity}: {dbgMessage}");
}
[Conditional("DEBUG")]
protected void GLErrorCheck()
@@ -330,6 +408,9 @@ namespace PckStudio.Rendering
long tick = DateTime.UtcNow.Ticks - _lastTick;
Refresh();
_lastTick = DateTime.UtcNow.Ticks;
if (!HasValidContext)
MakeCurrent();
RenderDebug();
OnUpdate(sender, TimeSpan.FromTicks(tick));
}
@@ -345,5 +426,212 @@ namespace PckStudio.Rendering
}
Renderer.SetViewportSize(Camera.ViewportSize);
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
float mouseSensetivity = LockMousePosition ? MouseSensetivity : 64f * 3 * (1f / 56f) * MouseSensetivity;
float deltaX = (Cursor.Position.X - CurrentMouseLocation.X) * mouseSensetivity;
float deltaY = (Cursor.Position.Y - CurrentMouseLocation.Y) * mouseSensetivity;
switch (e.Button)
{
case MouseButtons.None:
case MouseButtons.Middle:
case MouseButtons.XButton1:
case MouseButtons.XButton2:
break;
case MouseButtons.Left:
Camera.Rotate(deltaX, deltaY);
goto default;
case MouseButtons.Right:
Camera.Pan(deltaX, deltaY);
goto default;
default:
if (LockMousePosition)
Cursor.Position = PointToScreen(new Point((int)Math.Round(Bounds.Width / 2d), (int)Math.Round(Bounds.Height / 2d)));
CurrentMouseLocation = Cursor.Position;
break;
}
}
protected override void OnMouseWheel(MouseEventArgs e)
{
Camera.Distance -= e.Delta / System.Windows.Input.Mouse.MouseWheelDeltaForOneLine;
}
protected override void OnMouseUp(MouseEventArgs e)
{
ReleaseMouse();
base.OnMouseUp(e);
}
protected void ReleaseMouse()
{
if (LockMousePosition)
{
Cursor.Position = PreviousMouseLocation;
if (IsMouseHidden)
IsMouseHidden = false;
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Right || e.Button == MouseButtons.Left)
{
CurrentMouseLocation = PreviousMouseLocation = Cursor.Position;
IsMouseHidden = LockMousePosition;
}
}
[Conditional("DEBUG")]
private void InitializeDebugShaders()
{
#if DEBUG
var plainColorVertexBufferLayout = new VertexBufferLayout();
plainColorVertexBufferLayout.Add(ShaderDataType.Float3);
plainColorVertexBufferLayout.Add(ShaderDataType.Float4);
// Debug point render
{
ColorVertex[] vertices = [
new ColorVertex(Vector3.Zero, Color.White),
];
VertexArray vao = new VertexArray();
var debugVBO = new VertexBuffer();
debugVBO.SetData(vertices);
vao.AddBuffer(debugVBO, plainColorVertexBufferLayout);
d_debugPointDrawContext = new DrawContext(vao, debugVBO.GenIndexBuffer(), PrimitiveType.Points);
}
// Debug line render
{
ColorVertex[] vertices = [
new ColorVertex(Vector3.Zero, Color.Red) , new ColorVertex(Vector3.UnitX, Color.Red),
new ColorVertex(Vector3.Zero, Color.Green), new ColorVertex(Vector3.UnitY, Color.Green),
new ColorVertex(Vector3.Zero, Color.Blue) , new ColorVertex(Vector3.UnitZ, Color.Blue),
];
VertexArray vao = new VertexArray();
var debugVBO = new VertexBuffer();
debugVBO.SetData(vertices);
vao.AddBuffer(debugVBO, plainColorVertexBufferLayout);
d_debugLineDrawContext = new DrawContext(vao, debugVBO.GenIndexBuffer(), PrimitiveType.Lines);
}
#endif
}
[Conditional("DEBUG")]
private void RenderDebug()
{
#if DEBUG
ShaderProgram colorShader = GetShader("Internal_colorShader");
Matrix4 viewProjection = Camera.GetViewProjection();
colorShader.SetUniformMat4("ViewProjection", ref viewProjection);
if (d_showFocalPoint)
{
GL.BlendFunc(BlendingFactor.SrcColor, BlendingFactor.SrcColor);
GL.DepthFunc(DepthFunction.Always);
GL.DepthMask(false);
GL.Enable(EnableCap.PointSmooth);
colorShader.Bind();
Matrix4 transform = Matrix4.CreateTranslation(Camera.FocalPoint).Inverted();
colorShader.SetUniformMat4("Transform", ref transform);
colorShader.SetUniform1("intensity", 0.75f);
colorShader.SetUniform4("baseColor", Color.DeepPink);
GL.PointSize(5f);
Renderer.Draw(colorShader, d_debugPointDrawContext);
GL.PointSize(1f);
GL.DepthMask(true);
GL.DepthFunc(DepthFunction.Less);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
}
if (d_showDirectionArrows)
{
GL.BlendFunc(BlendingFactor.SrcColor, BlendingFactor.SrcColor);
GL.DepthFunc(DepthFunction.Always);
GL.DepthMask(false);
GL.Enable(EnableCap.LineSmooth);
colorShader.Bind();
Matrix4 transform = Matrix4.CreateScale(1, -1, -1);
transform *= Matrix4.CreateTranslation(Vector3.Zero);
transform *= Matrix4.CreateScale(Camera.Distance / 4f).Inverted();
transform.Invert();
colorShader.SetUniformMat4("Transform", ref transform);
colorShader.SetUniform1("intensity", 0.75f);
colorShader.SetUniform4("baseColor", Color.White);
Renderer.SetLineWidth(2f);
Renderer.Draw(colorShader, d_debugLineDrawContext);
Renderer.SetLineWidth(1f);
GL.DepthMask(true);
GL.DepthFunc(DepthFunction.Less);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
}
d_debugLabel.Text = Camera.ToString();
#endif
}
[Conditional("DEBUG")]
private void InitializeDebugComponents()
{
#if DEBUG
debugContextMenuStrip1 = new ContextMenuStrip();
debugContextMenuStrip1.SuspendLayout();
SuspendLayout();
//
// contextMenuStrip1
//
debugContextMenuStrip1.Items.AddRange(new ToolStripItem[] {});
debugContextMenuStrip1.Name = "contextMenuStrip1";
debugContextMenuStrip1.Size = new Size(159, 48);
//
// debugLabel
//
d_debugLabel = new Label();
d_debugLabel.AutoSize = true;
d_debugLabel.Visible = false;
d_debugLabel.BackColor = Color.Transparent;
d_debugLabel.ForeColor = SystemColors.ControlLight;
d_debugLabel.Location = new Point(3, 4);
d_debugLabel.Name = "debugLabel";
d_debugLabel.Size = new Size(37, 13);
d_debugLabel.TabIndex = 2;
d_debugLabel.Text = "debug";
var debugCameraToolStripMenuItem = new ToolStripMenuItem("Show Camera debug information");
debugCameraToolStripMenuItem.CheckOnClick = true;
debugCameraToolStripMenuItem.Click += (s, e) => d_debugLabel.Visible = debugCameraToolStripMenuItem.Checked;
debugContextMenuStrip1.Items.Add(debugCameraToolStripMenuItem);
var debugShowFocalPointToolStripMenuItem = new ToolStripMenuItem("Show Camera Focal point");
debugShowFocalPointToolStripMenuItem.CheckOnClick = true;
debugShowFocalPointToolStripMenuItem.Click += (s, e) => d_showFocalPoint = debugShowFocalPointToolStripMenuItem.Checked;
debugContextMenuStrip1.Items.Add(debugShowFocalPointToolStripMenuItem);
var debugShowDirectionArrows = new ToolStripMenuItem("Show Direction Arrows");
debugShowDirectionArrows.CheckOnClick = true;
debugShowDirectionArrows.Click += (s, e) => d_showDirectionArrows = debugShowDirectionArrows.Checked;
debugContextMenuStrip1.Items.Add(debugShowDirectionArrows);
Controls.Add(d_debugLabel);
this.debugContextMenuStrip1.ResumeLayout(false);
#endif
}
#if DEBUG
private bool d_showFocalPoint;
private bool d_showDirectionArrows;
private DrawContext d_debugPointDrawContext;
private DrawContext d_debugLineDrawContext;
private Label d_debugLabel;
private ContextMenuStrip debugContextMenuStrip1;
#endif
}
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace PckStudio.Rendering
{

View File

@@ -85,13 +85,25 @@ namespace PckStudio.Rendering
[Category("Appearance")]
public Color HighlightlingColor { get; set; } = Color.Aqua;
public float MouseSensetivity { get; set; } = 0.01f;
public int SelectedIndex
{
get => selectedIndex;
get => selectedIndices.Length > 0 ? selectedIndices[0] : -1;
set
{
selectedIndex = value;
if (selectedIndices.Length <= 0)
selectedIndices = new int[1];
selectedIndices[0] = value;
if (CenterOnSelect)
CenterSelectedObject();
}
}
public int[] SelectedIndices
{
get => selectedIndices;
set
{
selectedIndices = value;
if (CenterOnSelect)
CenterSelectedObject();
}
@@ -172,33 +184,12 @@ namespace PckStudio.Rendering
};
private GuidelineMode guidelineMode { get; set; } = GuidelineMode.None;
private int selectedIndex = -1;
private int[] selectedIndices = Array.Empty<int>();
public Size TextureSize { get; private set; } = new Size(64, 64);
public Vector2 TillingFactor => new Vector2(1f / TextureSize.Width, 1f / TextureSize.Height);
private const float OverlayScale = 0.25f;
private bool IsMouseHidden
{
get => !Cursor.IsVisible();
set
{
if (value)
{
Cursor.Hide();
return;
}
Cursor.Show();
}
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool LockMousePosition { get; set; } = false;
private Point PreviousMouseLocation;
private Point CurrentMouseLocation;
private VertexBufferLayout plainColorVertexBufferLayout;
private SkinANIM _anim;
@@ -255,7 +246,7 @@ namespace PckStudio.Rendering
private bool initialized = false;
public SkinRenderer() : base()
public SkinRenderer() : base(fov: 60f)
{
InitializeSkinData();
InitializeCapeData();
@@ -278,7 +269,6 @@ namespace PckStudio.Rendering
InitializeArmorData();
InitializeCamera();
InitializeComponent();
InitializeDebug();
ANIM ??= new SkinANIM(SkinAnimMask.RESOLUTION_64x64);
ModelData = new ObservableCollection<SkinBOX>();
@@ -294,8 +284,6 @@ namespace PckStudio.Rendering
InitializeShaders();
Renderer.SetClearColor(BackColor);
GLErrorCheck();
base.Initialize();
GLErrorCheck();
initialized = true;
}
@@ -399,10 +387,6 @@ namespace PckStudio.Rendering
private void InitializeShaders()
{
MakeCurrent();
Trace.TraceInformation(GL.GetString(StringName.Version));
plainColorVertexBufferLayout = new VertexBufferLayout();
plainColorVertexBufferLayout.Add(ShaderDataType.Float3);
plainColorVertexBufferLayout.Add(ShaderDataType.Float4);
@@ -415,7 +399,7 @@ namespace PckStudio.Rendering
new ShaderSource(ShaderType.GeometryShader, Resources.texturedCubeGeometryShader)
);
cubeShader.Bind();
cubeShader.SetUniform1("u_Texture", 0);
cubeShader.SetUniform1("Texture", 0);
cubeShader.Validate();
AddShader("CubeShader", cubeShader);
GLErrorCheck();
@@ -597,8 +581,6 @@ namespace PckStudio.Rendering
GLErrorCheck();
}
InitializeDebugShaders();
}
private DrawContext GetGuidelineDrawContext()
@@ -772,13 +754,6 @@ namespace PckStudio.Rendering
{
switch (keyData)
{
#if DEBUG
case Keys.Escape:
ReleaseMouse();
var point = new Point(Parent.Location.X + Location.X, Parent.Location.Y + Location.Y);
debugContextMenuStrip1.Show(point);
return true;
#endif
case Keys.F3:
showWireFrame = !showWireFrame;
return true;
@@ -867,12 +842,12 @@ namespace PckStudio.Rendering
if (showWireFrame)
GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
Matrix4 transform = Matrix4.Identity;
Matrix4 transform = Matrix4.CreateScale(1f, -1f, -1f);
ShaderProgram cubeShader = GetShader("CubeShader");
cubeShader.Bind();
cubeShader.SetUniformMat4("u_ViewProjection", ref viewProjection);
cubeShader.SetUniform2("u_TexSize", TextureSize);
cubeShader.SetUniformMat4("ViewProjection", ref viewProjection);
cubeShader.SetUniform2("TexSize", TextureSize);
skinTexture.Bind();
@@ -923,7 +898,7 @@ namespace PckStudio.Rendering
if (_capeImage is not null)
{
cubeShader.SetUniform2("u_TexSize", new Vector2(64, 32));
cubeShader.SetUniform2("TexSize", new Vector2(64, 32));
capeTexture.Bind();
// Defines minimum Angle(in Degrees) of the cape
float capeMinimumRotationAngle = 7.5f;
@@ -942,7 +917,7 @@ namespace PckStudio.Rendering
if (ShowArmor && !ANIM.GetFlag(SkinAnimFlag.ALL_ARMOR_DISABLED))
{
armorTexture.Bind();
cubeShader.SetUniform2("u_TexSize", new Vector2(64, 64));
cubeShader.SetUniform2("TexSize", new Vector2(64, 64));
if (!ANIM.GetFlag(SkinAnimFlag.HEAD_DISABLED) || ANIM.GetFlag(SkinAnimFlag.FORCE_HEAD_ARMOR))
RenderPart(cubeShader, offsetSpecificMeshStorage["HELMET"], Matrix4.Identity, transform);
@@ -991,14 +966,13 @@ namespace PckStudio.Rendering
GL.DepthFunc(DepthFunction.Less);
}
if (ModelData.IndexInRange(SelectedIndex))
BoundingBox boundingBox = GetSelectedBoundingArea();
Matrix4 boundingBoxTransform = transform;
if (SelectedIndices.Length == 1 && ModelData.IndexInRange(SelectedIndices[0]))
{
SkinBOX box = ModelData[SelectedIndex];
float inflate = autoInflateOverlayParts && box.IsOverlayPart() ? box.Type == "HEADWEAR" ? OverlayScale * 2 : OverlayScale : 0f;
Cube cube = box.ToCube(inflate);
BoundingBox cubeBoundingBox = cube.GetBoundingBox();
SkinBOX box = ModelData[SelectedIndices[0]];
if (meshStorage.ContainsKey(box.Type))
{
@@ -1024,17 +998,14 @@ namespace PckStudio.Rendering
return Matrix4.Identity;
}
}
Matrix4 bbTransform = GetGroupTransform(box.Type);
bbTransform *= cubeMesh.Transform;
bbTransform *= transform;
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.SrcColor);
DrawBoundingBox(bbTransform, cubeBoundingBox, HighlightlingColor);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
boundingBoxTransform = GetGroupTransform(box.Type) * boundingBoxTransform;
}
}
}
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.SrcColor);
DrawBoundingBox(boundingBoxTransform, boundingBox, HighlightlingColor);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
}
// Ground plane
{
@@ -1052,70 +1023,31 @@ namespace PckStudio.Rendering
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
}
// Debug
RenderDebug();
FramebufferEnd();
}
protected override void OnMouseMove(MouseEventArgs e)
private BoundingBox GetSelectedBoundingArea()
{
base.OnMouseMove(e);
float mouseSensetivity = LockMousePosition ? MouseSensetivity : 64f * 3 * (1f/56f) * MouseSensetivity;
float deltaX = (Cursor.Position.X - CurrentMouseLocation.X) * mouseSensetivity;
float deltaY = (Cursor.Position.Y - CurrentMouseLocation.Y) * mouseSensetivity;
switch (e.Button)
IEnumerable<BoundingBox> GetBoundingBoxesFromSelectedIndices(IEnumerable<int> selectedIndices)
{
case MouseButtons.None:
case MouseButtons.Middle:
case MouseButtons.XButton1:
case MouseButtons.XButton2:
break;
case MouseButtons.Left:
Camera.Rotate(deltaX, deltaY);
goto default;
case MouseButtons.Right:
Camera.Pan(deltaX, deltaY);
goto default;
default:
if (LockMousePosition)
Cursor.Position = PointToScreen(new Point((int)Math.Round(Bounds.Width / 2d), (int)Math.Round(Bounds.Height / 2d)));
CurrentMouseLocation = Cursor.Position;
break;
}
}
protected override void OnMouseWheel(MouseEventArgs e)
{
Camera.Distance -= e.Delta / System.Windows.Input.Mouse.MouseWheelDeltaForOneLine;
}
protected override void OnMouseUp(MouseEventArgs e)
{
ReleaseMouse();
base.OnMouseUp(e);
}
private void ReleaseMouse()
{
if (LockMousePosition)
{
Cursor.Position = PreviousMouseLocation;
if (IsMouseHidden)
IsMouseHidden = false;
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Right || e.Button == MouseButtons.Left)
{
CurrentMouseLocation = PreviousMouseLocation = Cursor.Position;
IsMouseHidden = LockMousePosition;
foreach (var selectedIndex in selectedIndices)
{
if (!ModelData.IndexInRange(selectedIndex))
continue;
SkinBOX box = ModelData[selectedIndex];
if (!meshStorage.ContainsKey(box.Type))
continue;
float inflate = autoInflateOverlayParts && box.IsOverlayPart() ? box.Type == "HEADWEAR" ? OverlayScale * 2 : OverlayScale : 0f;
Cube cube = box.ToCube(inflate);
CubeMeshCollection cubeMesh = meshStorage[box.Type];
yield return cube.GetBoundingBox(cubeMesh.Transform);
}
yield break;
}
return SelectedIndices.Length >= 1 ? GetBounds(GetBoundingBoxesFromSelectedIndices(SelectedIndices)) : BoundingBox.Empty;
}
private void RenderBodyPart(ShaderProgram shader, Matrix4 partsMatrix, Matrix4 globalMatrix, params string[] partNames)
@@ -1129,8 +1061,7 @@ namespace PckStudio.Rendering
private void RenderPart<T>(ShaderProgram shader, GenericMesh<T> mesh, Matrix4 partMatrix, Matrix4 globalMatrix) where T : struct
{
Matrix4 transform = partMatrix * mesh.Transform * globalMatrix;
shader.SetUniformMat4("u_Transform", ref transform);
DrawMesh(mesh, shader);
DrawMesh(mesh, shader, transform);
}
protected override void OnUpdate(object sender, TimeSpan timestep)
@@ -1165,182 +1096,5 @@ namespace PckStudio.Rendering
AddCustomModelPart(item);
}
}
[Conditional("DEBUG")]
private void InitializeDebugShaders()
{
#if DEBUG
// Debug point render
{
ColorVertex[] vertices = [
new ColorVertex(Vector3.Zero, Color.White),
];
VertexArray vao = new VertexArray();
var debugVBO = new VertexBuffer();
debugVBO.SetData(vertices);
vao.AddBuffer(debugVBO, plainColorVertexBufferLayout);
d_debugPointDrawContext = new DrawContext(vao, debugVBO.GenIndexBuffer(), PrimitiveType.Points);
}
// Debug line render
{
ColorVertex[] vertices = [
new ColorVertex(Vector3.Zero, Color.Red) , new ColorVertex(Vector3.UnitX, Color.Red),
new ColorVertex(Vector3.Zero, Color.Green), new ColorVertex(Vector3.UnitY, Color.Green),
new ColorVertex(Vector3.Zero, Color.Blue) , new ColorVertex(Vector3.UnitZ, Color.Blue),
];
VertexArray vao = new VertexArray();
var debugVBO = new VertexBuffer();
debugVBO.SetData(vertices);
vao.AddBuffer(debugVBO, plainColorVertexBufferLayout);
d_debugLineDrawContext = new DrawContext(vao, debugVBO.GenIndexBuffer(), PrimitiveType.Lines);
}
#endif
}
[Conditional("DEBUG")]
private void RenderDebug()
{
#if DEBUG
ShaderProgram colorShader = GetShader("PlainColorShader");
Matrix4 viewProjection = Camera.GetViewProjection();
colorShader.SetUniformMat4("ViewProjection", ref viewProjection);
if (d_showFocalPoint)
{
GL.BlendFunc(BlendingFactor.DstAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.DepthFunc(DepthFunction.Always);
GL.DepthMask(false);
GL.Enable(EnableCap.PointSmooth);
colorShader.Bind();
Matrix4 transform = Matrix4.CreateTranslation(Camera.FocalPoint).Inverted();
colorShader.SetUniformMat4("Transform", ref transform);
colorShader.SetUniform1("intensity", 0.75f);
colorShader.SetUniform4("baseColor", Color.DeepPink);
GL.PointSize(5f);
Renderer.Draw(colorShader, d_debugPointDrawContext);
GL.PointSize(1f);
GL.DepthMask(true);
GL.DepthFunc(DepthFunction.Less);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
}
if (d_showDirectionArrows)
{
GL.BlendFunc(BlendingFactor.DstAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.DepthFunc(DepthFunction.Always);
GL.DepthMask(false);
GL.Enable(EnableCap.LineSmooth);
colorShader.Bind();
Matrix4 transform = Matrix4.CreateScale(1, -1, -1);
transform *= Matrix4.CreateTranslation(Vector3.Zero);
transform *= Matrix4.CreateScale(Camera.Distance / 4f).Inverted();
transform.Invert();
colorShader.SetUniformMat4("Transform", ref transform);
colorShader.SetUniform1("intensity", 0.75f);
colorShader.SetUniform4("baseColor", Color.White);
Renderer.SetLineWidth(2f);
Renderer.Draw(colorShader, d_debugLineDrawContext);
Renderer.SetLineWidth(1f);
GL.DepthMask(true);
GL.DepthFunc(DepthFunction.Less);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
}
d_debugLabel.Text = Camera.ToString();
#endif
}
[Conditional("DEBUG")]
private void InitializeDebug()
{
#if DEBUG
reToolStripMenuItem = new ToolStripMenuItem();
debugContextMenuStrip1 = new ContextMenuStrip(this.components);
guidelineModeToolStripMenuItem = new ToolStripMenuItem();
debugContextMenuStrip1.SuspendLayout();
SuspendLayout();
//
// contextMenuStrip1
//
debugContextMenuStrip1.Items.AddRange(new ToolStripItem[] {
reToolStripMenuItem,
guidelineModeToolStripMenuItem});
debugContextMenuStrip1.Name = "contextMenuStrip1";
debugContextMenuStrip1.Size = new Size(159, 48);
//
// reToolStripMenuItem
//
reToolStripMenuItem.Name = "reToolStripMenuItem";
reToolStripMenuItem.Size = new Size(158, 22);
reToolStripMenuItem.Text = "Re-Init";
reToolStripMenuItem.Click += new EventHandler(this.reInitToolStripMenuItem_Click);
//
// guidelineModeToolStripMenuItem
//
guidelineModeToolStripMenuItem.Name = "guidelineModeToolStripMenuItem";
guidelineModeToolStripMenuItem.Size = new Size(158, 22);
guidelineModeToolStripMenuItem.Text = "Guideline Mode";
guidelineModeToolStripMenuItem.Click += new EventHandler(this.guidelineModeToolStripMenuItem_Click);
//
// debugLabel
//
d_debugLabel = new Label();
d_debugLabel.AutoSize = true;
d_debugLabel.Visible = false;
d_debugLabel.BackColor = Color.Transparent;
d_debugLabel.ForeColor = SystemColors.ControlLight;
d_debugLabel.Location = new Point(3, 4);
d_debugLabel.Name = "debugLabel";
d_debugLabel.Size = new Size(37, 13);
d_debugLabel.TabIndex = 2;
d_debugLabel.Text = "debug";
var debugCameraToolStripMenuItem = new ToolStripMenuItem("Show Camera debug information");
debugCameraToolStripMenuItem.CheckOnClick = true;
debugCameraToolStripMenuItem.Click += (s, e) => d_debugLabel.Visible = debugCameraToolStripMenuItem.Checked;
debugContextMenuStrip1.Items.Add(debugCameraToolStripMenuItem);
var debugShowFocalPointToolStripMenuItem = new ToolStripMenuItem("Show Camera Focal point");
debugShowFocalPointToolStripMenuItem.CheckOnClick = true;
debugShowFocalPointToolStripMenuItem.Click += (s, e) => d_showFocalPoint = debugShowFocalPointToolStripMenuItem.Checked;
debugContextMenuStrip1.Items.Add(debugShowFocalPointToolStripMenuItem);
var debugShowDirectionArrows = new ToolStripMenuItem("Show Direction Arrows");
debugShowDirectionArrows.CheckOnClick = true;
debugShowDirectionArrows.Click += (s, e) => d_showDirectionArrows = debugShowDirectionArrows.Checked;
debugContextMenuStrip1.Items.Add(debugShowDirectionArrows);
Controls.Add(d_debugLabel);
this.debugContextMenuStrip1.ResumeLayout(false);
#endif
}
#if DEBUG
private bool d_showFocalPoint;
private bool d_showDirectionArrows;
private DrawContext d_debugPointDrawContext;
private DrawContext d_debugLineDrawContext;
private Label d_debugLabel;
private ToolStripMenuItem reToolStripMenuItem;
private ContextMenuStrip debugContextMenuStrip1;
private ToolStripMenuItem guidelineModeToolStripMenuItem;
private void reInitToolStripMenuItem_Click(object sender, EventArgs e)
{
ReInitialzeSkinData();
MakeCurrent();
}
private void guidelineModeToolStripMenuItem_Click(object sender, EventArgs e)
{
if (!Enum.IsDefined(typeof(GuidelineMode), ++guidelineMode))
{
guidelineMode = GuidelineMode.None;
}
guidelineModeToolStripMenuItem.Text = $"Guideline Mode: {guidelineMode}";
}
#endif
}
}

View File

@@ -2,12 +2,12 @@
layout(location = 0) out vec4 color;
uniform sampler2D u_Texture;
uniform sampler2D Texture;
in vec2 o_TillingFactor;
in vec2 o_TexCoord;
void main()
{
color = texture(u_Texture, o_TexCoord * o_TillingFactor);
color = texture(Texture, o_TexCoord * o_TillingFactor);
};

View File

@@ -3,7 +3,7 @@
layout (triangles) in;
layout (triangle_strip, max_vertices=3) out;
uniform vec2 u_TexSize;
uniform vec2 TexSize;
out vec2 o_TexCoord;
out vec2 o_TillingFactor;
@@ -16,32 +16,32 @@ in geometryData
void FixUV()
{
bool isXBad =
dataIn[0].TexCoord.x >= u_TexSize.x &&
dataIn[1].TexCoord.x >= u_TexSize.x &&
dataIn[2].TexCoord.x >= u_TexSize.x;
dataIn[0].TexCoord.x >= TexSize.x &&
dataIn[1].TexCoord.x >= TexSize.x &&
dataIn[2].TexCoord.x >= TexSize.x;
gl_Position = gl_in[0].gl_Position;
o_TexCoord = dataIn[0].TexCoord;
if (isXBad)
o_TexCoord.x = mod(o_TexCoord.x, u_TexSize.x);
o_TexCoord.x = mod(o_TexCoord.x, TexSize.x);
EmitVertex();
gl_Position = gl_in[1].gl_Position;
o_TexCoord = dataIn[1].TexCoord;
if (isXBad)
o_TexCoord.x = mod(o_TexCoord.x, u_TexSize.x);
o_TexCoord.x = mod(o_TexCoord.x, TexSize.x);
EmitVertex();
gl_Position = gl_in[2].gl_Position;
o_TexCoord = dataIn[2].TexCoord;
if (isXBad)
o_TexCoord.x = mod(o_TexCoord.x, u_TexSize.x);
o_TexCoord.x = mod(o_TexCoord.x, TexSize.x);
EmitVertex();
}
void main()
{
o_TillingFactor = 1.0 / u_TexSize;
o_TillingFactor = 1.0 / TexSize;
FixUV();
EndPrimitive();
};

View File

@@ -3,8 +3,8 @@
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 texCoord;
uniform mat4 u_ViewProjection;
uniform mat4 u_Transform;
uniform mat4 ViewProjection;
uniform mat4 Transform;
out geometryData
{
@@ -14,5 +14,5 @@ out geometryData
void main()
{
dataOut.TexCoord = texCoord;
gl_Position = u_ViewProjection * u_Transform * vec4(vertexPosition, 1.0);
gl_Position = ViewProjection * Transform * vec4(vertexPosition, 1.0);
};