Rename CubeRenderGroup to CubeBatchMesh

This commit is contained in:
miku-666
2024-02-07 17:02:18 +01:00
parent e8043155a8
commit 3d8dce1be2
3 changed files with 129 additions and 118 deletions

View File

@@ -153,7 +153,7 @@
<Compile Include="Rendering\Camera\Camera.cs" />
<Compile Include="Rendering\Camera\PerspectiveCamera.cs" />
<Compile Include="Rendering\CubeData.cs" />
<Compile Include="Rendering\CubeRenderGroup.cs" />
<Compile Include="Rendering\CubeBatchMesh.cs" />
<Compile Include="Rendering\FrameBuffer.cs" />
<Compile Include="Rendering\IndexBuffer.cs" />
<Compile Include="Rendering\IVertexLayout.cs" />

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2023-present miku-666
/* Copyright (c) 2024-present miku-666
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
@@ -17,7 +17,6 @@
**/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using OpenTK;
using OpenTK.Graphics.OpenGL;
@@ -26,18 +25,18 @@ using PckStudio.Internal;
namespace PckStudio.Rendering
{
internal class CubeRenderGroup : RenderGroup<TextureVertex>
internal class CubeBatchMesh : GenericMesh<TextureVertex>
{
private List<CubeData> cubes;
internal float Scale { get; set; } = 1f;
internal CubeRenderGroup(string name) : base(name, PrimitiveType.Triangles)
internal CubeBatchMesh(string name) : base(name, PrimitiveType.Triangles)
{
cubes = new List<CubeData>(5);
}
internal CubeRenderGroup(string name, float scale)
internal CubeBatchMesh(string name, float scale)
: this(name)
{
Scale = scale;
@@ -48,16 +47,16 @@ namespace PckStudio.Rendering
AddCube(skinBox.Pos.ToOpenTKVector(), skinBox.Size.ToOpenTKVector(), skinBox.UV.ToOpenTKVector(), skinBox.Scale + Scale, skinBox.Mirror, skinBox.Type == "HEAD");
}
internal void Clear()
internal void ClearData()
{
cubes.Clear();
ResetBuffers();
}
/// <summary>
/// Submits buffered data to the underlying graphics buffer
/// Uploads MeshData
/// </summary>
internal void Submit()
internal void UploadData()
{
ResetBuffers();
foreach (var cube in cubes)
@@ -71,6 +70,7 @@ namespace PckStudio.Rendering
indices.AddRange(indexStorage.Select(n => n + indicesOffset));
indicesOffset += cubeVertices.Length;
}
Submit();
}
internal void AddCube(Vector3 position, Vector3 size, Vector2 uv, float scale = 1f, bool mirrorTexture = false, bool flipZMapping = false)
@@ -90,7 +90,6 @@ namespace PckStudio.Rendering
cube.Uv = uv;
cube.Scale = scale;
cube.MirrorTexture = mirrorTexture;
Submit();
}
internal void SetEnabled(int index, bool enable)
@@ -99,7 +98,6 @@ namespace PckStudio.Rendering
throw new IndexOutOfRangeException();
cubes[index].ShouldRender = enable;
Submit();
}
}
}

View File

@@ -79,6 +79,8 @@ namespace PckStudio.Rendering
{
_anim = value;
OnANIMUpdate();
MakeCurrent();
UploadMeshData();
}
}
@@ -148,22 +150,22 @@ namespace PckStudio.Rendering
private float skyboxRotation = 0f;
private float skyboxRotationStep = 0.5f;
private Dictionary<string, CubeRenderGroup> additionalModelRenderGroups;
private Dictionary<string, CubeBatchMesh> meshStorage;
private Dictionary<string, float> partOffset;
private CubeRenderGroup head;
private CubeRenderGroup body;
private CubeRenderGroup rightArm;
private CubeRenderGroup leftArm;
private CubeRenderGroup rightLeg;
private CubeRenderGroup leftLeg;
private CubeBatchMesh head;
private CubeBatchMesh body;
private CubeBatchMesh rightArm;
private CubeBatchMesh leftArm;
private CubeBatchMesh rightLeg;
private CubeBatchMesh leftLeg;
private CubeRenderGroup headOverlay;
private CubeRenderGroup bodyOverlay;
private CubeRenderGroup rightArmOverlay;
private CubeRenderGroup leftArmOverlay;
private CubeRenderGroup rightLegOverlay;
private CubeRenderGroup leftLegOverlay;
private CubeBatchMesh headOverlay;
private CubeBatchMesh bodyOverlay;
private CubeBatchMesh rightArmOverlay;
private CubeBatchMesh leftArmOverlay;
private CubeBatchMesh rightLegOverlay;
private CubeBatchMesh leftLegOverlay;
private float animationCurrentRotationAngle;
private float animationRotationStep = 0.5f;
@@ -204,16 +206,8 @@ namespace PckStudio.Rendering
public SkinRenderer() : base()
{
InitializeCamera();
InitializeSkinData();
InitializeShaders();
InitializeComponent();
ANIM ??= new SkinANIM(SkinAnimMask.RESOLUTION_64x64);
OnTimerTick = AnimationTick;
ModelData = new ObservableCollection<SkinBOX>();
ModelData.CollectionChanged += ModelData_CollectionChanged;
additionalModelRenderGroups = new Dictionary<string, CubeRenderGroup>(6)
meshStorage = new Dictionary<string, CubeBatchMesh>()
{
{ "HEAD", head },
{ "BODY", body },
@@ -229,12 +223,11 @@ namespace PckStudio.Rendering
{ "PANTS0" , rightLegOverlay },
{ "PANTS1" , leftLegOverlay },
{ "BODYARMOR", new CubeRenderGroup("BODYARMOR") },
{ "BELT", new CubeRenderGroup("BELT") },
{ "ARMARMOR0", new CubeRenderGroup("ARMARMOR0") },
{ "ARMARMOR1", new CubeRenderGroup("ARMARMOR1") },
{ "BODYARMOR", new CubeBatchMesh("BODYARMOR") },
{ "BELT", new CubeBatchMesh("BELT") },
{ "ARMARMOR0", new CubeBatchMesh("ARMARMOR0") },
{ "ARMARMOR1", new CubeBatchMesh("ARMARMOR1") },
};
partOffset = new Dictionary<string, float>()
{
{ "HEAD", 0f },
@@ -262,6 +255,18 @@ namespace PckStudio.Rendering
{ "TOOL0" , 0f },
{ "TOOL1" , 0f },
};
InitializeCamera();
InitializeComponent();
MakeCurrent();
InitializeShaders();
InitializeFramebuffer();
UploadMeshData();
ANIM ??= new SkinANIM(SkinAnimMask.RESOLUTION_64x64);
OnTimerTick = AnimationTick;
ModelData = new ObservableCollection<SkinBOX>();
ModelData.CollectionChanged += ModelData_CollectionChanged;
}
// TODO: calculate CameraDistance based on model size
@@ -278,53 +283,41 @@ namespace PckStudio.Rendering
private void InitializeSkinData()
{
head ??= new CubeRenderGroup("Head");
head ??= new CubeBatchMesh("Head");
head.AddCube(new(-4, -8, -4), new(8, 8, 8), new(0, 0), flipZMapping: true);
head.Submit();
headOverlay ??= new CubeRenderGroup("Head Overlay", OverlayScale);
headOverlay ??= new CubeBatchMesh("Head Overlay", OverlayScale);
headOverlay.AddCube(new(-4, -8, -4), new(8, 8, 8), new(32, 0), flipZMapping: true, scale: OverlayScale);
headOverlay.Submit();
body ??= new CubeRenderGroup("Body");
body ??= new CubeBatchMesh("Body");
body.AddCube(new(-4, 0, -2), new(8, 12, 4), new(16, 16));
body.Submit();
bodyOverlay ??= new CubeRenderGroup("Body Overlay", OverlayScale);
bodyOverlay ??= new CubeBatchMesh("Body Overlay", OverlayScale);
bodyOverlay.AddCube(new(-4, 0, -2), new(8, 12, 4), new(16, 32), scale: OverlayScale);
bodyOverlay.Submit();
rightArm ??= new CubeRenderGroup("Right Arm");
rightArm ??= new CubeBatchMesh("Right Arm");
rightArm.AddCube(new(-3, -2, -2), new(4, 12, 4), new(40, 16));
rightArm.Submit();
rightArmOverlay ??= new CubeRenderGroup("Right Arm Overlay", OverlayScale);
rightArmOverlay ??= new CubeBatchMesh("Right Arm Overlay", OverlayScale);
rightArmOverlay.AddCube(new(-3, -2, -2), new(4, 12, 4), new(40, 32), scale: OverlayScale);
rightArmOverlay.Submit();
leftArm ??= new CubeRenderGroup("Left Arm");
leftArm ??= new CubeBatchMesh("Left Arm");
leftArm.AddCube(new(-1, -2, -2), new(4, 12, 4), new(32, 48));
leftArm.Submit();
leftArmOverlay ??= new CubeRenderGroup("Left Arm Overlay", OverlayScale);
leftArmOverlay ??= new CubeBatchMesh("Left Arm Overlay", OverlayScale);
leftArmOverlay.AddCube(new(-1, -2, -2), new(4, 12, 4), new(48, 48), scale: OverlayScale);
leftArmOverlay.Submit();
rightLeg ??= new CubeRenderGroup("Right Leg");
rightLeg ??= new CubeBatchMesh("Right Leg");
rightLeg.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 16));
rightLeg.Submit();
rightLegOverlay ??= new CubeRenderGroup("Right Leg Overlay", OverlayScale);
rightLegOverlay ??= new CubeBatchMesh("Right Leg Overlay", OverlayScale);
rightLegOverlay.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 32), scale: OverlayScale);
rightLegOverlay.Submit();
leftLeg ??= new CubeRenderGroup("Left Leg");
leftLeg ??= new CubeBatchMesh("Left Leg");
leftLeg.AddCube(new(-2, 0, -2), new(4, 12, 4), new(16, 48));
leftLeg.Submit();
leftLegOverlay ??= new CubeRenderGroup("Left Leg Overlay", OverlayScale);
leftLegOverlay ??= new CubeBatchMesh("Left Leg Overlay", OverlayScale);
leftLegOverlay.AddCube(new(-2, 0, -2), new(4, 12, 4), new(0, 48), scale: OverlayScale);
leftLegOverlay.Submit();
}
private void InitializeShaders()
@@ -439,14 +432,8 @@ namespace PckStudio.Rendering
}
}
protected override void OnLoad(EventArgs e)
private void InitializeFramebuffer()
{
base.OnLoad(e);
MakeCurrent();
// Initialize framebuffer
{
framebuffer = new FrameBuffer();
framebuffer.Bind();
framebufferTexture = new Texture2D(0);
@@ -480,6 +467,14 @@ namespace PckStudio.Rendering
}
}
private void UploadMeshData()
{
foreach (var cubeMesh in meshStorage?.Values)
{
cubeMesh?.UploadData();
}
}
public void SetPartOffset(SkinPartOffset offset)
{
SetPartOffset(offset.Type, offset.Value);
@@ -489,7 +484,7 @@ namespace PckStudio.Rendering
{
if (!partOffset.ContainsKey(name))
{
Debug.WriteLine($"'{name}' is not inside {nameof(partOffset)}");
Trace.TraceInformation($"[{nameof(SetPartOffset)}]: '{name}' is not inside {nameof(partOffset)}");
return;
}
partOffset[name] = value;
@@ -502,26 +497,32 @@ namespace PckStudio.Rendering
private void ModelData_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action != NotifyCollectionChangedAction.Move &&
e.Action != NotifyCollectionChangedAction.Reset)
// TODO: dont re-initialize everytime..
switch (e.Action)
{
UpdateModelData();
case NotifyCollectionChangedAction.Add:
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Replace:
ReInitialzeSkinData();
goto default;
case NotifyCollectionChangedAction.Move:
break;
case NotifyCollectionChangedAction.Reset:
break;
default:
MakeCurrent();
UploadMeshData();
break;
}
}
public void UpdateModelData()
{
ReInitialzeSkinData();
}
private void AddCustomModelPart(SkinBOX skinBox)
{
if (!additionalModelRenderGroups.ContainsKey(skinBox.Type))
if (!meshStorage.ContainsKey(skinBox.Type))
throw new KeyNotFoundException(skinBox.Type);
CubeRenderGroup group = additionalModelRenderGroups[skinBox.Type];
group.AddSkinBox(skinBox);
group.Submit();
CubeBatchMesh cubeMesh = meshStorage[skinBox.Type];
cubeMesh.AddSkinBox(skinBox);
}
[Conditional("DEBUG")]
@@ -624,11 +625,11 @@ namespace PckStudio.Rendering
if (!IsHandleCreated)
return;
MakeCurrent();
{
framebuffer.Bind();
framebufferTexture.Bind();
Size texSize = new Size(Size.Width, Size.Height);
framebufferTexture.SetSize(texSize);
framebufferTexture.SetSize(Size);
framebufferTexture.Unbind();
int rbo = GL.GenRenderbuffer();
@@ -644,6 +645,8 @@ namespace PckStudio.Rendering
framebuffer.Unbind();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
@@ -761,37 +764,6 @@ namespace PckStudio.Rendering
SwapBuffers();
}
private void RenderBodyPart(Vector3 pivot, Vector3 translation, Matrix4 partMatrix, Matrix4 globalMatrix, params string[] additionalData)
{
foreach (var data in additionalData)
{
RenderPart(data, pivot, translation, partMatrix, globalMatrix);
}
}
private void RenderPart(string name, Vector3 pivot, Vector3 translation, Matrix4 partMatrix, Matrix4 globalMatrix)
{
CubeRenderGroup renderGroup = additionalModelRenderGroups[name];
float yOffset = GetOffset(name);
translation.Y -= yOffset;
pivot.Y += yOffset;
renderGroup.Submit();
RenderBuffer buffer = renderGroup.GetRenderBuffer();
Matrix4 model = Pivot(translation, pivot, partMatrix);
model *= globalMatrix;
_skinShader.SetUniformMat4("u_Model", ref model);
Renderer.Draw(_skinShader, buffer);
}
private static Matrix4 Pivot(Vector3 translation, Vector3 pivot, Matrix4 target)
{
var model = Matrix4.CreateTranslation(translation);
model *= Matrix4.CreateTranslation(pivot);
model *= target;
model *= Matrix4.CreateTranslation(pivot).Inverted();
return model;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
@@ -841,6 +813,40 @@ namespace PckStudio.Rendering
base.OnMouseUp(e);
}
private void RenderBodyPart(Vector3 pivot, Vector3 translation, Matrix4 partMatrix, Matrix4 globalMatrix, params string[] additionalData)
{
foreach (var data in additionalData)
{
RenderPart(data, pivot, translation, partMatrix, globalMatrix);
}
}
private void RenderPart(string name, Vector3 pivot, Vector3 translation, Matrix4 partMatrix, Matrix4 globalMatrix)
{
RenderPart(_skinShader, name, pivot, translation, partMatrix, globalMatrix);
}
private void RenderPart(ShaderProgram shader, string name, Vector3 pivot, Vector3 translation, Matrix4 partMatrix, Matrix4 globalMatrix)
{
CubeBatchMesh cubeMesh = meshStorage[name];
float yOffset = GetOffset(name);
translation.Y -= yOffset;
pivot.Y += yOffset;
Matrix4 model = Pivot(translation, pivot, partMatrix);
model *= globalMatrix;
_skinShader.SetUniformMat4("u_Model", ref model);
cubeMesh.Draw(shader);
}
private static Matrix4 Pivot(Vector3 translation, Vector3 pivot, Matrix4 target)
{
var model = Matrix4.CreateTranslation(translation);
model *= Matrix4.CreateTranslation(pivot);
model *= target;
model *= Matrix4.CreateTranslation(pivot).Inverted();
return model;
}
private void AnimationTick(object sender, EventArgs e)
{
skyboxRotation += skyboxRotationStep;
@@ -852,22 +858,29 @@ namespace PckStudio.Rendering
private void ReInitialzeSkinData()
{
foreach (var renderGroup in additionalModelRenderGroups.Values)
foreach (var mesh in meshStorage.Values)
{
renderGroup.Clear();
mesh.ClearData();
}
InitializeSkinData();
UpdateModelData();
OnANIMUpdate();
}
private void UpdateModelData()
{
foreach (var item in ModelData)
{
AddCustomModelPart(item);
}
OnANIMUpdate();
}
private void reInitToolStripMenuItem_Click(object sender, EventArgs e)
{
ReInitialzeSkinData();
MakeCurrent();
UploadMeshData();
}
}
}