Fixed Button texture swapping. Fixed Button scripts on scene change. Added buttons to scenes. Added SHEDITOR define for Managed #341
|
@ -363,8 +363,6 @@ MigrationBackup/
|
||||||
|
|
||||||
*.filters
|
*.filters
|
||||||
|
|
||||||
Assets/Editor/Layouts/UserLayout.ini
|
|
||||||
|
|
||||||
JSON/Schemas/Catalog/
|
JSON/Schemas/Catalog/
|
||||||
|
|
||||||
Assets/Editor/Editor.SHConfig
|
Assets/Editor/Editor.SHConfig
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Start in Fullscreen: false
|
Start in Fullscreen: false
|
||||||
Starting Scene ID: 87244611
|
Starting Scene ID: 97158628
|
||||||
Window Size: {x: 1920, y: 1080}
|
Window Size: {x: 1920, y: 1080}
|
||||||
Window Title: SHADE Engine
|
Window Title: SHADE Engine
|
|
@ -1 +1,96 @@
|
||||||
|
7
|
||||||
|
Controller Look Horizontal
|
||||||
0
|
0
|
||||||
|
0
|
||||||
|
5
|
||||||
|
0.2
|
||||||
|
5
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
1
|
||||||
|
18
|
||||||
|
0
|
||||||
|
Controller Look Vertical
|
||||||
|
0
|
||||||
|
0
|
||||||
|
5
|
||||||
|
0.2
|
||||||
|
5
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
1
|
||||||
|
19
|
||||||
|
0
|
||||||
|
Horizontal
|
||||||
|
0
|
||||||
|
0
|
||||||
|
5
|
||||||
|
0.2
|
||||||
|
5
|
||||||
|
1
|
||||||
|
2
|
||||||
|
39
|
||||||
|
68
|
||||||
|
2
|
||||||
|
37
|
||||||
|
65
|
||||||
|
2
|
||||||
|
3
|
||||||
|
16
|
||||||
|
1
|
||||||
|
2
|
||||||
|
Jump
|
||||||
|
0
|
||||||
|
0
|
||||||
|
1000
|
||||||
|
0.2
|
||||||
|
1000
|
||||||
|
0
|
||||||
|
1
|
||||||
|
32
|
||||||
|
0
|
||||||
|
1
|
||||||
|
10
|
||||||
|
0
|
||||||
|
Mouse Look Horizontal
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0.2
|
||||||
|
1
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
Mouse Look Vertical
|
||||||
|
2
|
||||||
|
0
|
||||||
|
1
|
||||||
|
0.2
|
||||||
|
1
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
Vertical
|
||||||
|
0
|
||||||
|
0
|
||||||
|
5
|
||||||
|
0.2
|
||||||
|
5
|
||||||
|
1
|
||||||
|
2
|
||||||
|
38
|
||||||
|
87
|
||||||
|
2
|
||||||
|
40
|
||||||
|
83
|
||||||
|
2
|
||||||
|
0
|
||||||
|
17
|
||||||
|
1
|
||||||
|
1
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
Start Maximized: true
|
|
||||||
Working Scene ID: 97161771
|
|
||||||
Window Size: {x: 1920, y: 1080}
|
|
||||||
Style: 0
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
[Window][MainStatusBar]
|
||||||
|
Pos=0,989
|
||||||
|
Size=1920,20
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][SHEditorMenuBar]
|
||||||
|
Pos=0,48
|
||||||
|
Size=1920,941
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Hierarchy Panel]
|
||||||
|
Pos=0,187
|
||||||
|
Size=300,802
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000004,0
|
||||||
|
|
||||||
|
[Window][Debug##Default]
|
||||||
|
Pos=60,60
|
||||||
|
Size=400,400
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Inspector]
|
||||||
|
Pos=1604,48
|
||||||
|
Size=316,941
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000006,0
|
||||||
|
|
||||||
|
[Window][Profiler]
|
||||||
|
Pos=0,48
|
||||||
|
Size=300,137
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000003,0
|
||||||
|
|
||||||
|
[Window][Viewport]
|
||||||
|
Pos=227,48
|
||||||
|
Size=1457,1012
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌð‡Žoû]
|
||||||
|
Pos=60,60
|
||||||
|
Size=32,64
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ]
|
||||||
|
Pos=60,60
|
||||||
|
Size=999,581
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ð‡–oû]
|
||||||
|
Pos=60,60
|
||||||
|
Size=32,64
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌ]
|
||||||
|
Pos=60,60
|
||||||
|
Size=553,422
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][]
|
||||||
|
Pos=60,60
|
||||||
|
Size=770,394
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ Viewport]
|
||||||
|
Pos=227,48
|
||||||
|
Size=1457,1012
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][ Viewport]
|
||||||
|
Pos=227,48
|
||||||
|
Size=1457,1012
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][î<>‹ Viewport]
|
||||||
|
Pos=302,48
|
||||||
|
Size=1300,836
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][V]
|
||||||
|
Pos=310,722
|
||||||
|
Size=1501,338
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,0
|
||||||
|
|
||||||
|
[Window][p›£€Ê]
|
||||||
|
Pos=310,750
|
||||||
|
Size=1501,310
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000A,0
|
||||||
|
|
||||||
|
[Window][ Asset Browser]
|
||||||
|
Pos=302,886
|
||||||
|
Size=1300,103
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000C,0
|
||||||
|
|
||||||
|
[Window][Material Inspector]
|
||||||
|
Pos=1604,48
|
||||||
|
Size=316,941
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000006,1
|
||||||
|
|
||||||
|
[Window][Save scene as...]
|
||||||
|
Pos=1197,693
|
||||||
|
Size=165,120
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Create New Asset]
|
||||||
|
Pos=896,472
|
||||||
|
Size=464,144
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Collider Tag Panel]
|
||||||
|
Pos=60,60
|
||||||
|
Size=625,744
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Input Bindings Panel]
|
||||||
|
Pos=60,60
|
||||||
|
Size=154,204
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][Save Scene As]
|
||||||
|
Pos=877,444
|
||||||
|
Size=165,120
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Table][0x9D40AE32,17]
|
||||||
|
Column 0 Weight=1.0000
|
||||||
|
Column 1 Weight=1.0000
|
||||||
|
Column 2 Weight=1.0000
|
||||||
|
Column 3 Weight=1.0000
|
||||||
|
Column 4 Weight=1.0000
|
||||||
|
Column 5 Weight=1.0000
|
||||||
|
Column 6 Weight=1.0000
|
||||||
|
Column 7 Weight=1.0000
|
||||||
|
Column 8 Weight=1.0000
|
||||||
|
Column 9 Weight=1.0000
|
||||||
|
Column 10 Weight=1.0000
|
||||||
|
Column 11 Weight=1.0000
|
||||||
|
Column 12 Weight=1.0000
|
||||||
|
Column 13 Weight=1.0000
|
||||||
|
Column 14 Weight=1.0000
|
||||||
|
Column 15 Weight=1.0000
|
||||||
|
Column 16 Weight=1.0000
|
||||||
|
|
||||||
|
[Docking][Data]
|
||||||
|
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=0,71 Size=1920,941 Split=X
|
||||||
|
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1602,1036 Split=X
|
||||||
|
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=300,1036 Split=Y Selected=0x1E6EB881
|
||||||
|
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881
|
||||||
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,863 Selected=0xE096E5AE
|
||||||
|
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1300,1036 Split=Y Selected=0xB41284E7
|
||||||
|
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1501,672 Split=Y Selected=0xB41284E7
|
||||||
|
DockNode ID=0x00000009 Parent=0x00000007 SizeRef=1501,700 Split=Y Selected=0xB41284E7
|
||||||
|
DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,836 CentralNode=1 Selected=0xB41284E7
|
||||||
|
DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,103 Selected=0xB128252A
|
||||||
|
DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6
|
||||||
|
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532
|
||||||
|
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=316,1036 Selected=0xE7039252
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
- VertexShader: 47911992
|
||||||
|
FragmentShader: 46377769
|
||||||
|
SubPass: G-Buffer Write
|
||||||
|
Properties:
|
||||||
|
data.color: {x: 1, y: 1, z: 1, w: 1}
|
||||||
|
data.textureIndex: 58303057
|
||||||
|
data.alpha: 0
|
||||||
|
data.beta: {x: 1, y: 1, z: 1}
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: AnimatedBag
|
||||||
|
ID: 117923942
|
||||||
|
Type: 7
|
|
@ -0,0 +1,8 @@
|
||||||
|
- VertexShader: 47911992
|
||||||
|
FragmentShader: 46377769
|
||||||
|
SubPass: G-Buffer Write
|
||||||
|
Properties:
|
||||||
|
data.color: {x: 1, y: 1, z: 1, w: 1}
|
||||||
|
data.textureIndex: 64651793
|
||||||
|
data.alpha: 0
|
||||||
|
data.beta: {x: 1, y: 1, z: 1}
|
|
@ -0,0 +1,3 @@
|
||||||
|
Name: AnimatedRaccoon
|
||||||
|
ID: 128805346
|
||||||
|
Type: 7
|
|
@ -1,6 +1,6 @@
|
||||||
- VertexShader: 46580970
|
- VertexShader: 46580970
|
||||||
FragmentShader: 35983630
|
FragmentShader: 35983630
|
||||||
SubPass: G-Buffer Write
|
SubPass: UI
|
||||||
Properties:
|
Properties:
|
||||||
data.color: {x: 1, y: 1, z: 1, w: 1}
|
data.color: {x: 1, y: 1, z: 1, w: 1}
|
||||||
data.textureIndex: 54324293
|
data.textureIndex: 54324293
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
- VertexShader: 46580970
|
- VertexShader: 46580970
|
||||||
FragmentShader: 35983630
|
FragmentShader: 35983630
|
||||||
SubPass: G-Buffer Write
|
SubPass: UI
|
||||||
Properties:
|
Properties:
|
||||||
data.color: {x: 1, y: 1, z: 1, w: 1}
|
data.color: {x: 1, y: 1, z: 1, w: 1}
|
||||||
data.textureIndex: 54429632
|
data.textureIndex: 54429632
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
- VertexShader: 46580970
|
- VertexShader: 46580970
|
||||||
FragmentShader: 35983630
|
FragmentShader: 35983630
|
||||||
SubPass: G-Buffer Write
|
SubPass: UI
|
||||||
Properties:
|
Properties:
|
||||||
data.color: {x: 1, y: 1, z: 1, w: 1}
|
data.color: {x: 1, y: 1, z: 1, w: 1}
|
||||||
data.textureIndex: 57302694
|
data.textureIndex: 57302694
|
||||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -0,0 +1,7 @@
|
||||||
|
Name: BoneIKTest4
|
||||||
|
ID: 81814706
|
||||||
|
Type: 4
|
||||||
|
Sub Assets:
|
||||||
|
Name: Cube
|
||||||
|
ID: 137599708
|
||||||
|
Type: 8
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -4,6 +4,7 @@ using System;
|
||||||
|
|
||||||
public class SoundsBoard : Script
|
public class SoundsBoard : Script
|
||||||
{
|
{
|
||||||
|
AudioClipHandler test;
|
||||||
protected override void awake()
|
protected override void awake()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -31,13 +32,21 @@ event:/Homeowner/homeowner_humming
|
||||||
event:/Homeowner/homeowner_footsteps
|
event:/Homeowner/homeowner_footsteps
|
||||||
event:/Homeowner/homeowner_detect_raccoon
|
event:/Homeowner/homeowner_detect_raccoon
|
||||||
*/
|
*/
|
||||||
|
test = Audio.CreateAudioClip("event:/Music/player_undetected");
|
||||||
|
Audio.AddAudioClipToSFXChannelGroup(test);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void start()
|
||||||
|
{
|
||||||
|
test.Play();
|
||||||
}
|
}
|
||||||
protected override void update()
|
protected override void update()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (Input.GetKeyDown(Input.KeyCode.Q))
|
if (Input.GetKeyDown(Input.KeyCode.Q))
|
||||||
Audio.PlayBGMOnce2D("event:/UI/mouse_down_element");
|
test.Play();
|
||||||
if (Input.GetKeyDown(Input.KeyCode.W))
|
if (Input.GetKeyDown(Input.KeyCode.W))
|
||||||
Audio.PlayBGMOnce2D("event:/UI/mouse_down_empty");
|
test.Stop(true);
|
||||||
if (Input.GetKeyDown(Input.KeyCode.E))
|
if (Input.GetKeyDown(Input.KeyCode.E))
|
||||||
Audio.PlayBGMOnce2D("event:/UI/mouse_enter_element");
|
Audio.PlayBGMOnce2D("event:/UI/mouse_enter_element");
|
||||||
if (Input.GetKeyDown(Input.KeyCode.R))
|
if (Input.GetKeyDown(Input.KeyCode.R))
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
#version 450
|
||||||
|
#extension GL_KHR_vulkan_glsl : enable
|
||||||
|
|
||||||
|
//#include "ShaderDescriptorDefinitions.glsl"
|
||||||
|
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 aVertexPos;
|
||||||
|
layout(location = 1) in vec2 aUV;
|
||||||
|
layout(location = 2) in vec3 aNormal;
|
||||||
|
layout(location = 3) in vec3 aTangent;
|
||||||
|
layout(location = 4) in mat4 worldTransform;
|
||||||
|
layout(location = 8) in uvec2 integerData;
|
||||||
|
layout(location = 9) in uvec4 aBoneIndices;
|
||||||
|
layout(location = 10) in vec4 aBoneWeights;
|
||||||
|
layout(location = 11) in uint firstBoneIndex;
|
||||||
|
|
||||||
|
layout(location = 0) out struct
|
||||||
|
{
|
||||||
|
vec4 vertPos; // location 0
|
||||||
|
vec2 uv; // location = 1
|
||||||
|
vec4 normal; // location = 2
|
||||||
|
vec4 worldPos; // location = 3
|
||||||
|
} Out;
|
||||||
|
|
||||||
|
// material stuff
|
||||||
|
layout(location = 4) out struct
|
||||||
|
{
|
||||||
|
int materialIndex;
|
||||||
|
uint eid;
|
||||||
|
uint lightLayerIndex;
|
||||||
|
|
||||||
|
} Out2;
|
||||||
|
|
||||||
|
layout(set = 1, binding = 0) uniform CameraData
|
||||||
|
{
|
||||||
|
vec4 position;
|
||||||
|
mat4 vpMat;
|
||||||
|
mat4 viewMat;
|
||||||
|
mat4 projMat;
|
||||||
|
} cameraData;
|
||||||
|
|
||||||
|
layout (std430, set = 2, binding = 1) buffer AnimBoneMatrices
|
||||||
|
{
|
||||||
|
mat4 data[];
|
||||||
|
} BoneMatrices;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Out2.materialIndex = gl_InstanceIndex;
|
||||||
|
Out2.eid = integerData[0];
|
||||||
|
Out2.lightLayerIndex = integerData[1];
|
||||||
|
|
||||||
|
// for transforming gBuffer position and normal data
|
||||||
|
mat4 modelViewMat = cameraData.viewMat * worldTransform;
|
||||||
|
|
||||||
|
// gBuffer position will be in view space
|
||||||
|
Out.vertPos = modelViewMat * vec4(aVertexPos, 1.0f);
|
||||||
|
|
||||||
|
Out.worldPos = worldTransform * vec4 (aVertexPos, 1.0f);
|
||||||
|
|
||||||
|
// uvs for texturing in fragment shader
|
||||||
|
Out.uv = aUV;
|
||||||
|
|
||||||
|
mat3 transposeInv = mat3 (transpose(inverse(modelViewMat)));
|
||||||
|
|
||||||
|
// normals are also in view space
|
||||||
|
Out.normal.rgb = transposeInv * aNormal.rgb;
|
||||||
|
Out.normal.rgb = normalize (Out.normal.rgb);
|
||||||
|
|
||||||
|
// Compute bone matrix
|
||||||
|
mat4 boneMatrix = BoneMatrices.data[firstBoneIndex + aBoneIndices[0]] * aBoneWeights[0];
|
||||||
|
boneMatrix += BoneMatrices.data[firstBoneIndex + aBoneIndices[1]] * aBoneWeights[1];
|
||||||
|
boneMatrix += BoneMatrices.data[firstBoneIndex + aBoneIndices[2]] * aBoneWeights[2];
|
||||||
|
boneMatrix += BoneMatrices.data[firstBoneIndex + aBoneIndices[3]] * aBoneWeights[3];
|
||||||
|
|
||||||
|
// clip space for rendering
|
||||||
|
gl_Position = cameraData.vpMat * worldTransform * boneMatrix * vec4 (aVertexPos, 1.0f);
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
Name: Anim_VS
|
||||||
|
ID: 47911992
|
||||||
|
Type: 2
|
|
@ -17,7 +17,6 @@ layout(location = 0) in struct
|
||||||
vec2 uv; // location = 1
|
vec2 uv; // location = 1
|
||||||
vec4 normal; // location = 2
|
vec4 normal; // location = 2
|
||||||
vec4 worldPos; // location = 3
|
vec4 worldPos; // location = 3
|
||||||
|
|
||||||
} In;
|
} In;
|
||||||
|
|
||||||
// material stuff
|
// material stuff
|
||||||
|
|
|
@ -10,7 +10,9 @@ layout(location = 2) in vec3 aNormal;
|
||||||
layout(location = 3) in vec3 aTangent;
|
layout(location = 3) in vec3 aTangent;
|
||||||
layout(location = 4) in mat4 worldTransform;
|
layout(location = 4) in mat4 worldTransform;
|
||||||
layout(location = 8) in uvec2 integerData;
|
layout(location = 8) in uvec2 integerData;
|
||||||
|
layout(location = 9) in uvec4 aBoneIndices;
|
||||||
|
layout(location = 10) in vec4 aBoneWeights;
|
||||||
|
layout(location = 11) in uint firstBoneIndex;
|
||||||
|
|
||||||
layout(location = 0) out struct
|
layout(location = 0) out struct
|
||||||
{
|
{
|
||||||
|
|
Binary file not shown.
|
@ -33,18 +33,11 @@ layout (std430, set = 2, binding = 0) buffer MaterialProperties // For mater
|
||||||
MatPropData data[];
|
MatPropData data[];
|
||||||
} MatProp;
|
} MatProp;
|
||||||
|
|
||||||
layout(location = 0) out vec4 position;
|
layout(location = 0) out vec4 fragColor;
|
||||||
layout(location = 1) out uint outEntityID;
|
layout(location = 1) out uint outEntityID;
|
||||||
layout(location = 2) out uint lightLayerIndices;
|
|
||||||
layout(location = 3) out vec4 normals;
|
|
||||||
layout(location = 4) out vec4 albedo;
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
position = In.vertPos;
|
fragColor = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv);
|
||||||
normals = In.normal;
|
|
||||||
albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv);
|
|
||||||
|
|
||||||
outEntityID = In2.eid;
|
outEntityID = In2.eid;
|
||||||
lightLayerIndices = In2.lightLayerIndex;
|
|
||||||
}
|
}
|
Binary file not shown.
|
@ -34,6 +34,7 @@
|
||||||
#include "Physics/System/SHPhysicsDebugDrawSystem.h"
|
#include "Physics/System/SHPhysicsDebugDrawSystem.h"
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
#include "UI/SHUISystem.h"
|
#include "UI/SHUISystem.h"
|
||||||
|
#include "Animation/SHAnimationSystem.h"
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||||
|
@ -47,6 +48,7 @@
|
||||||
|
|
||||||
#include "Tools/Logger/SHLogger.h"
|
#include "Tools/Logger/SHLogger.h"
|
||||||
#include "Tools/SHDebugDraw.h"
|
#include "Tools/SHDebugDraw.h"
|
||||||
|
#include "Resource/SHResourceManager.h"
|
||||||
|
|
||||||
using namespace SHADE;
|
using namespace SHADE;
|
||||||
|
|
||||||
|
@ -95,6 +97,7 @@ namespace Sandbox
|
||||||
// Link up SHDebugDraw
|
// Link up SHDebugDraw
|
||||||
SHSystemManager::CreateSystem<SHDebugDrawSystem>();
|
SHSystemManager::CreateSystem<SHDebugDrawSystem>();
|
||||||
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
||||||
|
SHSystemManager::CreateSystem<SHAnimationSystem>();
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
SDL_Init(SDL_INIT_VIDEO);
|
SDL_Init(SDL_INIT_VIDEO);
|
||||||
|
@ -141,7 +144,7 @@ namespace Sandbox
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();
|
SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();
|
||||||
#endif
|
#endif
|
||||||
|
SHSystemManager::RegisterRoutine<SHAnimationSystem, SHAnimationSystem::UpdateRoutine>();
|
||||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::RenderRoutine>();
|
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::RenderRoutine>();
|
||||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::EndRoutine>();
|
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::EndRoutine>();
|
||||||
|
|
||||||
|
@ -149,6 +152,7 @@ namespace Sandbox
|
||||||
SHComponentManager::CreateComponentSparseSet<SHColliderComponent>();
|
SHComponentManager::CreateComponentSparseSet<SHColliderComponent>();
|
||||||
SHComponentManager::CreateComponentSparseSet<SHTransformComponent>();
|
SHComponentManager::CreateComponentSparseSet<SHTransformComponent>();
|
||||||
SHComponentManager::CreateComponentSparseSet<SHRenderable>();
|
SHComponentManager::CreateComponentSparseSet<SHRenderable>();
|
||||||
|
SHComponentManager::CreateComponentSparseSet<SHAnimatorComponent>();
|
||||||
//SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
|
//SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
|
||||||
|
|
||||||
SHAssetManager::Load();
|
SHAssetManager::Load();
|
||||||
|
@ -170,6 +174,10 @@ namespace Sandbox
|
||||||
|
|
||||||
// Link up SHDebugDraw
|
// Link up SHDebugDraw
|
||||||
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
||||||
|
|
||||||
|
auto clip = SHResourceManager::LoadOrGet<SHAnimationClip>(77816045);
|
||||||
|
auto rig = SHResourceManager::LoadOrGet<SHRig>(77816045);
|
||||||
|
int i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SBApplication::Update(void)
|
void SBApplication::Update(void)
|
||||||
|
@ -232,7 +240,13 @@ namespace Sandbox
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Unload scenes
|
||||||
SHSceneManager::Exit();
|
SHSceneManager::Exit();
|
||||||
|
|
||||||
|
// Free all remaining resources
|
||||||
|
SHResourceManager::UnloadAll();
|
||||||
|
|
||||||
|
// Shut down engine
|
||||||
SHSystemManager::Exit();
|
SHSystemManager::Exit();
|
||||||
SHAssetManager::Exit();
|
SHAssetManager::Exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHAnimationClip.cpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 20, 2022
|
||||||
|
\brief Contains the function definitions of the SHAnimationClip class.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Pre-compiled Header
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "SHAnimationClip.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
SHAnimationClip::SHAnimationClip(const SHAnimAsset& asset)
|
||||||
|
: ticksPerSecond { static_cast<int>(asset.ticksPerSecond) }
|
||||||
|
, totalTime { static_cast<float>(asset.duration) / static_cast<int>(asset.ticksPerSecond) }
|
||||||
|
{
|
||||||
|
// Populate keyframes
|
||||||
|
for (const auto& channel : asset.nodeChannels)
|
||||||
|
{
|
||||||
|
// Create a channel
|
||||||
|
Channel newChannel;
|
||||||
|
newChannel.Name = std::string(channel.name);
|
||||||
|
newChannel.PositionKeyFrames.reserve(channel.positionKeys.size());
|
||||||
|
newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size());
|
||||||
|
newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size());
|
||||||
|
|
||||||
|
// Populate Keyframes
|
||||||
|
for (const auto& posKey : channel.positionKeys)
|
||||||
|
{
|
||||||
|
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(posKey.time), posKey.value});
|
||||||
|
}
|
||||||
|
for (const auto& rotKey : channel.rotationKeys)
|
||||||
|
{
|
||||||
|
newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ static_cast<int>(rotKey.time), rotKey.value});
|
||||||
|
}
|
||||||
|
for (const auto& scaleKey : channel.scaleKeys)
|
||||||
|
{
|
||||||
|
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(scaleKey.time), scaleKey.value});
|
||||||
|
}
|
||||||
|
|
||||||
|
newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() });
|
||||||
|
|
||||||
|
// Insert the channel
|
||||||
|
channels.emplace_back(std::move(newChannel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHAnimationClip.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Dec 12, 2022
|
||||||
|
\brief Contains the definition of the SHAnimationClip struct and related types.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Project Includes
|
||||||
|
#include "SH_API.h"
|
||||||
|
#include "Math/SHMatrix.h"
|
||||||
|
#include "Assets/Asset Types/Models/SHAnimationAsset.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Defines a single key frame in an animation for a specific type of data.
|
||||||
|
/// </summary>
|
||||||
|
template<typename T>
|
||||||
|
struct SHAnimationKeyFrame
|
||||||
|
{
|
||||||
|
int FrameIndex;
|
||||||
|
T Data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a animation clip of a 3D animation that is made for a specific model
|
||||||
|
/// rig.
|
||||||
|
/// </summary>
|
||||||
|
class SH_API SHAnimationClip
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the animations of a single bone in a rig.
|
||||||
|
/// </summary>
|
||||||
|
struct Channel
|
||||||
|
{
|
||||||
|
std::string Name;
|
||||||
|
std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
|
||||||
|
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
|
||||||
|
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;
|
||||||
|
int MaxFrames;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an SHAnimation Clip from a specified SHAnimAsset.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset">Animation asset to load.</param>
|
||||||
|
explicit SHAnimationClip(const SHAnimAsset& asset);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
const std::vector<Channel>& GetChannels() const noexcept { return channels; }
|
||||||
|
int GetTicksPerSecond() const noexcept { return ticksPerSecond; }
|
||||||
|
float GetTotalTime() const noexcept { return totalTime; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
std::vector<Channel> channels;
|
||||||
|
int ticksPerSecond;
|
||||||
|
float totalTime;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHAnimationSystem.cpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 20, 2022
|
||||||
|
\brief Contains the function definitions of the SHAnimationSystem class.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Header
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Include
|
||||||
|
#include "SHAnimationSystem.h"
|
||||||
|
// Project Includes
|
||||||
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
|
#include "SHAnimatorComponent.h"
|
||||||
|
#include "ECS_Base/General/SHFamily.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* System Routine Functions - UpdateRoutine */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
SHAnimationSystem::UpdateRoutine::UpdateRoutine()
|
||||||
|
: SHSystemRoutine("Animation System Update", true)
|
||||||
|
{
|
||||||
|
SHFamilyID<SHSystem>::GetID<SHAnimationSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAnimationSystem::UpdateRoutine::Execute(double dt) noexcept
|
||||||
|
{
|
||||||
|
auto& animators = SHComponentManager::GetDense<SHAnimatorComponent>();
|
||||||
|
for (auto& animator : animators)
|
||||||
|
{
|
||||||
|
animator.Update(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* SHSystem Overrides */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHAnimationSystem::Init(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAnimationSystem::Exit(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHAnimationSystem.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 20, 2022
|
||||||
|
\brief Contains the definition of the SHAnimationSystem class and related types.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Project Includes
|
||||||
|
#include "SH_API.h"
|
||||||
|
#include "ECS_Base/System/SHSystem.h"
|
||||||
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// System that is responsible for updating all animations.
|
||||||
|
/// </summary>
|
||||||
|
class SH_API SHAnimationSystem : public SHSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Responsible for updating the playback of all animator components and computing
|
||||||
|
/// the required bone matrices.
|
||||||
|
/// </summary>
|
||||||
|
class SH_API UpdateRoutine final : public SHSystemRoutine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UpdateRoutine();
|
||||||
|
void Execute(double dt) noexcept override final;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
SHAnimationSystem() = default;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* SHSystem Overrides */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
virtual void Init(void) override final;
|
||||||
|
virtual void Exit(void) override final;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHAnimatorComponent.cpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 20, 2022
|
||||||
|
\brief Contains the definition of functions of the SHAnimatorComponent Component
|
||||||
|
class.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Header
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Include
|
||||||
|
#include "SHAnimatorComponent.h"
|
||||||
|
// STL Includes
|
||||||
|
#include <queue>
|
||||||
|
// Project Includes
|
||||||
|
#include "SHRig.h"
|
||||||
|
#include "Math/SHMatrix.h"
|
||||||
|
#include "SHAnimationClip.h"
|
||||||
|
#include "Graphics/SHVkUtil.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
||||||
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
#include "Tools/SHDebugDraw.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
void SHAnimatorComponent::Play()
|
||||||
|
{
|
||||||
|
isPlaying = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAnimatorComponent::Play(Handle<SHAnimationClip> clip)
|
||||||
|
{
|
||||||
|
currClip = clip;
|
||||||
|
currPlaybackTime = 0.0f;
|
||||||
|
Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAnimatorComponent::PlayFromStart()
|
||||||
|
{
|
||||||
|
isPlaying = true;
|
||||||
|
currPlaybackTime = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAnimatorComponent::Pause()
|
||||||
|
{
|
||||||
|
isPlaying = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAnimatorComponent::Stop()
|
||||||
|
{
|
||||||
|
isPlaying = false;
|
||||||
|
currPlaybackTime = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
void SHAnimatorComponent::SetRig(Handle<SHRig> newRig)
|
||||||
|
{
|
||||||
|
// Same rig, don't bother
|
||||||
|
if (rig == newRig)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rig = newRig;
|
||||||
|
|
||||||
|
// Populate bone matrices based on new rig's default pose
|
||||||
|
boneMatrices.clear();
|
||||||
|
if (rig)
|
||||||
|
{
|
||||||
|
std::fill_n(std::back_inserter(boneMatrices), rig->GetNodeCount(), SHMatrix::Identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAnimatorComponent::SetClip(Handle<SHAnimationClip> newClip)
|
||||||
|
{
|
||||||
|
// No change
|
||||||
|
if (currClip == newClip)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Set parameters
|
||||||
|
currClip = newClip;
|
||||||
|
secsPerTick = 1.0f / currClip->GetTicksPerSecond();
|
||||||
|
|
||||||
|
// Build channel map
|
||||||
|
channelMap.clear();
|
||||||
|
if (currClip)
|
||||||
|
{
|
||||||
|
for (const auto& channel : currClip->GetChannels())
|
||||||
|
{
|
||||||
|
channelMap.emplace(channel.Name, &channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rig && currClip)
|
||||||
|
{
|
||||||
|
updatePoseWithClip(0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Update Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
void SHAnimatorComponent::Update(float dt)
|
||||||
|
{
|
||||||
|
// Nothing to animate
|
||||||
|
if (!currClip || !isPlaying || !rig)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Update time on the playback
|
||||||
|
currPlaybackTime += dt;
|
||||||
|
if (currPlaybackTime > currClip->GetTotalTime())
|
||||||
|
{
|
||||||
|
currPlaybackTime = currPlaybackTime - currClip->GetTotalTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset all matrices
|
||||||
|
for (auto& mat : boneMatrices)
|
||||||
|
{
|
||||||
|
mat = SHMatrix::Identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Play the clip
|
||||||
|
updatePoseWithClip(currPlaybackTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
void SHAnimatorComponent::updatePoseWithClip(float poseTime)
|
||||||
|
{
|
||||||
|
// Get closest frame index
|
||||||
|
const int CLOSEST_FRAME_IDX = static_cast<int>(std::floorf(poseTime * currClip->GetTicksPerSecond()));
|
||||||
|
updatePoseWithClip(CLOSEST_FRAME_IDX, poseTime, rig->GetRootNode(), SHMatrix::Identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAnimatorComponent::updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
|
||||||
|
{
|
||||||
|
// Check if there is a channel for this node
|
||||||
|
const std::string& BONE_NAME = rig->GetName(node);
|
||||||
|
SHMatrix transformMatrix = node->TransformMatrix;
|
||||||
|
if (channelMap.contains(BONE_NAME))
|
||||||
|
{
|
||||||
|
const auto CHANNEL = channelMap[BONE_NAME];
|
||||||
|
transformMatrix = SHMatrix::Transform
|
||||||
|
(
|
||||||
|
getInterpolatedValue(CHANNEL->PositionKeyFrames, closestFrameIndex, poseTime),
|
||||||
|
getInterpolatedValue(CHANNEL->RotationKeyFrames, closestFrameIndex, poseTime),
|
||||||
|
getInterpolatedValue(CHANNEL->ScaleKeyFrames, closestFrameIndex, poseTime)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply parent's transformation
|
||||||
|
transformMatrix = transformMatrix * parentMatrix;
|
||||||
|
|
||||||
|
// Apply transformations to this node
|
||||||
|
const int BONE_MTX_IDX = rig->GetNodeIndex(node);
|
||||||
|
std::optional<SHVec3> position;
|
||||||
|
if (BONE_MTX_IDX >= 0)
|
||||||
|
{
|
||||||
|
boneMatrices[BONE_MTX_IDX] = node->OffsetMatrix * transformMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply pose to children
|
||||||
|
for (auto& child : node->Children)
|
||||||
|
{
|
||||||
|
updatePoseWithClip(closestFrameIndex, poseTime, child, transformMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
/* RTTR Registration */
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
RTTR_REGISTRATION
|
||||||
|
{
|
||||||
|
using namespace SHADE;
|
||||||
|
using namespace rttr;
|
||||||
|
|
||||||
|
registration::class_<SHAnimatorComponent>("Animator Component");
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHAnimatorComponent.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 20, 2022
|
||||||
|
\brief Contains the definition of the SHAnimatorComponent class and related
|
||||||
|
types.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// STL Includes
|
||||||
|
#include <vector>
|
||||||
|
// External Dependencies
|
||||||
|
#include <rttr/registration>
|
||||||
|
// Project Includes
|
||||||
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
|
#include "Resource/SHHandle.h"
|
||||||
|
#include "Math/SHMatrix.h"
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/SHQuaternion.h"
|
||||||
|
#include "SHAnimationClip.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Forward Declarations */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
class SHRig;
|
||||||
|
struct SHRigNode;
|
||||||
|
class SHAnimationClip;
|
||||||
|
class SHVkBuffer;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Component that holds and controls the animation related properties of a skinned
|
||||||
|
/// mesh.
|
||||||
|
/// </summary>
|
||||||
|
class SH_API SHAnimatorComponent final : public SHComponent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Plays the currently loaded animation from the last time.
|
||||||
|
/// </summary>
|
||||||
|
void Play();
|
||||||
|
/// <summary>
|
||||||
|
/// Plays the specified animation clip from the start.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clip"></param>
|
||||||
|
void Play(Handle<SHAnimationClip> clip);
|
||||||
|
/// <summary>
|
||||||
|
/// Plays the currently loaded animation clip from the start.
|
||||||
|
/// </summary>
|
||||||
|
void PlayFromStart();
|
||||||
|
/// <summary>
|
||||||
|
/// Pauses the animation at the current time.
|
||||||
|
/// </summary>
|
||||||
|
void Pause();
|
||||||
|
/// <summary>
|
||||||
|
/// Stops the animation and resets the play time back to 0.
|
||||||
|
/// </summary>
|
||||||
|
void Stop();
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Setter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the animation rig for this animator.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newRig">Rig to use.</param>
|
||||||
|
void SetRig(Handle<SHRig> newRig);
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the animation clip of this animator without playing it.
|
||||||
|
/// This will set the pose of the model to it's initial pose.
|
||||||
|
/// If the clip is the same as the current clip, nothing happens.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newClip">Clip to use.</param>
|
||||||
|
void SetClip(Handle<SHAnimationClip> newClip);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves all the bone matrices of this animator.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Reference to a vector of the bone matrices.</returns>
|
||||||
|
const std::vector<SHMatrix>& GetBoneMatrices() const noexcept { return boneMatrices; }
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve the currently set model rig.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Handle to the currently set rig.</returns>
|
||||||
|
Handle<SHRig> GetRig() const noexcept { return rig; }
|
||||||
|
/// <summary>
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve the currently set animation clip.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Handle to the currently set animation clip.</returns>
|
||||||
|
Handle<SHAnimationClip> GetCurrentClip() const noexcept { return currClip; }
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if an animation is currently playing.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if an animation clip is currently playing.</returns>
|
||||||
|
bool IsPlaying() const { return isPlaying; }
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Update Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the current state of the animation if one is specified based on the
|
||||||
|
/// current animation clip and frames. This will update the bone matrices.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dt">Time passed since the last frame.</param>
|
||||||
|
void Update(float dt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
// Resources
|
||||||
|
Handle<SHRig> rig;
|
||||||
|
Handle<SHAnimationClip> currClip;
|
||||||
|
// Playback Tracking
|
||||||
|
float currPlaybackTime = 0.0f;
|
||||||
|
bool isPlaying = true;
|
||||||
|
// Useful Cached Data
|
||||||
|
float secsPerTick = 0.0f;
|
||||||
|
// Buffer
|
||||||
|
std::vector<SHMatrix> boneMatrices;
|
||||||
|
// Caches
|
||||||
|
std::unordered_map<std::string, const SHAnimationClip::Channel*> channelMap;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void updatePoseWithClip(float poseTime);
|
||||||
|
void updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
|
||||||
|
template<typename T>
|
||||||
|
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* RTTR */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
RTTR_ENABLE()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "SHAnimatorComponent.hpp"
|
|
@ -0,0 +1,82 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHAnimatorComponent.hpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Jan 10, 2023
|
||||||
|
\brief Contains the definition of function templates of the SHAnimatorComponent
|
||||||
|
Component class.
|
||||||
|
|
||||||
|
Copyright (C) 2023 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Primary Include
|
||||||
|
#include "SHAnimatorComponent.h"
|
||||||
|
// Project Includes
|
||||||
|
#include "SHRig.h"
|
||||||
|
#include "Math/SHMatrix.h"
|
||||||
|
#include "SHAnimationClip.h"
|
||||||
|
#include "Graphics/SHVkUtil.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
||||||
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
template<typename T>
|
||||||
|
T SHAnimatorComponent::getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime)
|
||||||
|
{
|
||||||
|
// Only allow SHVec3 and SHQuaternion
|
||||||
|
static_assert(std::is_same_v<T, SHVec3> || std::is_same_v<T, SHQuaternion>, "Only interpolation for SHVec3 and SHQuaternion is allowed.");
|
||||||
|
|
||||||
|
// Find the key frames that surround the current frame index
|
||||||
|
auto firstKeyFrame = keyframes.end();
|
||||||
|
auto nextKeyFrame = keyframes.end();
|
||||||
|
for (auto iter = keyframes.begin(); iter != keyframes.end(); ++iter)
|
||||||
|
{
|
||||||
|
const auto& KEYFRAME = *iter;
|
||||||
|
|
||||||
|
if (KEYFRAME.FrameIndex <= closestFrameIndex)
|
||||||
|
{
|
||||||
|
firstKeyFrame = iter;
|
||||||
|
}
|
||||||
|
else // KEYFRAME.FrameIndex > closestFrameIndex
|
||||||
|
{
|
||||||
|
nextKeyFrame = iter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edge Cases
|
||||||
|
if (firstKeyFrame == keyframes.end())
|
||||||
|
{
|
||||||
|
// No keyframes at all, means no changes
|
||||||
|
if (nextKeyFrame == keyframes.end())
|
||||||
|
return T();
|
||||||
|
// Out of range, clamp to the back
|
||||||
|
else
|
||||||
|
return nextKeyFrame->Data;
|
||||||
|
}
|
||||||
|
// At the back, so no keyframes will follow
|
||||||
|
else if (nextKeyFrame == keyframes.end())
|
||||||
|
{
|
||||||
|
return firstKeyFrame->Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get interpolated vector
|
||||||
|
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick;
|
||||||
|
const float NEXT_FRAME_TIME = nextKeyFrame->FrameIndex * secsPerTick;
|
||||||
|
const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME);
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<T, SHQuaternion>)
|
||||||
|
{
|
||||||
|
return SHQuaternion::Slerp(firstKeyFrame->Data, nextKeyFrame->Data, NORMALISED_TIME);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, SHVec3>)
|
||||||
|
{
|
||||||
|
return SHVec3::Lerp(firstKeyFrame->Data, nextKeyFrame->Data, NORMALISED_TIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHRig.cpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 20, 2022
|
||||||
|
\brief Contains the function definitions of the SHRig class.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Pre-compiled Header
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "SHRig.h"
|
||||||
|
// STL Includes
|
||||||
|
#include <stack>
|
||||||
|
// Project Headers
|
||||||
|
#include "Assets/Asset Types/Models/SHRigAsset.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
SHRig::SHRig(const SHRigAsset& asset, SHResourceLibrary<SHRigNode>& nodeStore)
|
||||||
|
{
|
||||||
|
// Don't bother if empty
|
||||||
|
if (asset.root == nullptr)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("[SHRig] Attempted to load an invalid rig with no root.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do a recursive depth first traversal to populate the rig
|
||||||
|
rootNode = recurseCreateNode(asset, asset.root, nodeStore);
|
||||||
|
if (rootNode)
|
||||||
|
{
|
||||||
|
globalInverseMatrix = SHMatrix::Inverse(rootNode->TransformMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SHRig::SHRig(SHRig&& rhs)
|
||||||
|
: rootNode { rhs.rootNode }
|
||||||
|
, nodeNames { std::move(rhs.nodeNames) }
|
||||||
|
, nodesByName { std::move(rhs.nodesByName) }
|
||||||
|
, nodes { std::move(rhs.nodes) }
|
||||||
|
, nodeIndexMap { std::move(rhs.nodeIndexMap) }
|
||||||
|
, globalInverseMatrix { std::move(rhs.globalInverseMatrix) }
|
||||||
|
{
|
||||||
|
rhs.rootNode = {};
|
||||||
|
}
|
||||||
|
SHRig::~SHRig()
|
||||||
|
{
|
||||||
|
// Unload all nodes
|
||||||
|
for (auto node : nodes)
|
||||||
|
{
|
||||||
|
if (node)
|
||||||
|
node.Free();
|
||||||
|
}
|
||||||
|
nodes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
SHRig& SHRig::operator=(SHRig&& rhs)
|
||||||
|
{
|
||||||
|
rootNode = rhs.rootNode;
|
||||||
|
nodeNames = std::move(rhs.nodeNames);
|
||||||
|
nodesByName = std::move(rhs.nodesByName);
|
||||||
|
nodes = std::move(rhs.nodes);
|
||||||
|
nodeIndexMap = std::move(rhs.nodeIndexMap);
|
||||||
|
globalInverseMatrix = std::move(rhs.globalInverseMatrix);
|
||||||
|
|
||||||
|
rhs.rootNode = {};
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
const std::string& SHRig::GetName(Handle<SHRigNode> node) const noexcept
|
||||||
|
{
|
||||||
|
static const std::string EMPTY_STRING = "";
|
||||||
|
|
||||||
|
if (nodeNames.contains(node))
|
||||||
|
return nodeNames.at(node);
|
||||||
|
|
||||||
|
return EMPTY_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<SHRigNode> SHRig::GetNode(const std::string& name) const noexcept
|
||||||
|
{
|
||||||
|
if (nodesByName.contains(name))
|
||||||
|
return nodesByName.at(name);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
int SHRig::GetNodeCount() const noexcept
|
||||||
|
{
|
||||||
|
return static_cast<int>(nodes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int SHRig::GetNodeIndex(Handle<SHRigNode> node) const noexcept
|
||||||
|
{
|
||||||
|
if (nodeIndexMap.contains(node))
|
||||||
|
{
|
||||||
|
return nodeIndexMap.at(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
Handle<SHRigNode> SHRig::recurseCreateNode(const SHRigAsset& asset, const SHRigNodeAsset* sourceNode, SHResourceLibrary<SHRigNode>& nodeStore)
|
||||||
|
{
|
||||||
|
// Construct the node
|
||||||
|
auto newNode = nodeStore.Create();
|
||||||
|
|
||||||
|
// Fill the node with data
|
||||||
|
const auto& NODE_DATA = asset.nodeDataCollection.at(sourceNode->idRef);
|
||||||
|
newNode->OffsetMatrix = SHMatrix::Transpose(NODE_DATA.offset);
|
||||||
|
newNode->TransformMatrix = SHMatrix::Transpose(NODE_DATA.transform);
|
||||||
|
|
||||||
|
// Populate maps
|
||||||
|
if (!NODE_DATA.name.empty())
|
||||||
|
{
|
||||||
|
nodeNames.emplace(newNode, NODE_DATA.name);
|
||||||
|
nodesByName.emplace(NODE_DATA.name, newNode);
|
||||||
|
}
|
||||||
|
nodeIndexMap.emplace(newNode, sourceNode->idRef);
|
||||||
|
nodes.emplace_back(newNode);
|
||||||
|
|
||||||
|
// Fill child nodes
|
||||||
|
for (const auto& child : sourceNode->children)
|
||||||
|
{
|
||||||
|
// Ignore nulls
|
||||||
|
if (child == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Recursively create children
|
||||||
|
auto childNode = recurseCreateNode(asset, child, nodeStore); // Not sure why this works but it is required for
|
||||||
|
newNode->Children.emplace_back(childNode); // the emplace_back operation to not crash
|
||||||
|
}
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHRig.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 20, 2022
|
||||||
|
\brief Contains the definition of the SHRig struct and related types.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// STL Includes
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
// Project Includes
|
||||||
|
#include "SH_API.h"
|
||||||
|
#include "Math/SHMatrix.h"
|
||||||
|
#include "Resource/SHHandle.h"
|
||||||
|
#include "Resource/SHResourceLibrary.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Forward Declarations */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
struct SHRigAsset;
|
||||||
|
struct SHRigNodeAsset;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
struct SHRigNode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Matrix that performs a transformation from local space to bone (node) space.
|
||||||
|
/// </summary>
|
||||||
|
SHMatrix OffsetMatrix;
|
||||||
|
/// <summary>
|
||||||
|
/// Matrix that performs a transformation from bone (node) space to local space.
|
||||||
|
/// </summary>
|
||||||
|
SHMatrix TransformMatrix;
|
||||||
|
/// <summary>
|
||||||
|
/// Child nodes of this node.
|
||||||
|
/// </summary>
|
||||||
|
std::vector<Handle<SHRigNode>> Children;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an animation skeletal rig for a model.
|
||||||
|
/// </summary>
|
||||||
|
class SH_API SHRig
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors/Destructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a rig from a SHRigAsset.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset">
|
||||||
|
/// SHRigAsset to load.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="nodeStore">
|
||||||
|
/// Reference to a ResourceLibrary to use to create the rig's nodes.
|
||||||
|
/// </param>
|
||||||
|
explicit SHRig(const SHRigAsset& asset, SHResourceLibrary<SHRigNode>& nodeStore);
|
||||||
|
/// <summary>
|
||||||
|
/// Move Constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rhs>SHRig to move from.</param>
|
||||||
|
SHRig(SHRig&& rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Default destructor.
|
||||||
|
/// </summary>
|
||||||
|
~SHRig();
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Operator Overloads */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Move assignment operator.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rhs>SHRig to move from.</param>
|
||||||
|
/// <returns>Reference to this object.</returns>
|
||||||
|
SHRig& operator=(SHRig&& rhs);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the name of a node.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node">Node to get the name of.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Name of the node. If it does not have a name or is invalid, an empty string will
|
||||||
|
/// be provided.
|
||||||
|
/// </returns>
|
||||||
|
const std::string& GetName(Handle<SHRigNode> node) const noexcept;
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the root node of the rig.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Handle to the root node of the rig.</returns>
|
||||||
|
Handle<SHRigNode> GetRootNode() const noexcept { return rootNode; }
|
||||||
|
const SHMatrix& GetGlobalInverseMatrix() const noexcept { return globalInverseMatrix; }
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a node via name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">Name of the node to retrieve.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Node with the specified name. If it does not have a name or is invalid, an empty
|
||||||
|
/// handle will be provided.
|
||||||
|
/// </returns>
|
||||||
|
Handle<SHRigNode> GetNode(const std::string& name) const noexcept;
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of nodes in the rig. This matches the number of bone matrices
|
||||||
|
/// needed.
|
||||||
|
/// </summary>
|
||||||
|
int GetNodeCount() const noexcept;
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the index in the node storage.
|
||||||
|
/// </summary>
|
||||||
|
int GetNodeIndex(Handle<SHRigNode> node) const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
Handle<SHRigNode> rootNode;
|
||||||
|
std::unordered_map<Handle<SHRigNode>, std::string> nodeNames;
|
||||||
|
std::unordered_map<std::string, Handle<SHRigNode>> nodesByName;
|
||||||
|
std::vector<Handle<SHRigNode>> nodes;
|
||||||
|
std::unordered_map<Handle<SHRigNode>, int> nodeIndexMap;
|
||||||
|
SHMatrix globalInverseMatrix;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
Handle<SHRigNode> recurseCreateNode(const SHRigAsset& asset, const SHRigNodeAsset* sourceNode, SHResourceLibrary<SHRigNode>& nodeStore);
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAnimationAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/SHMath.h"
|
||||||
|
#include "Assets/Asset Types/SHAssetData.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
enum class SHAnimationBehaviour : uint8_t
|
||||||
|
{
|
||||||
|
DEFAULT = 0x0,
|
||||||
|
CONSTANT = 0x1,
|
||||||
|
LINEAR = 0x2,
|
||||||
|
REPEAT = 0x3
|
||||||
|
};
|
||||||
|
|
||||||
|
// Smallest data containers
|
||||||
|
struct PositionKey
|
||||||
|
{
|
||||||
|
float time;
|
||||||
|
SHVec3 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RotationKey
|
||||||
|
{
|
||||||
|
float time;
|
||||||
|
SHVec4 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ScaleKey
|
||||||
|
{
|
||||||
|
float time;
|
||||||
|
SHVec3 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Headers for read/write
|
||||||
|
struct SHAnimNodeInfo
|
||||||
|
{
|
||||||
|
uint32_t charCount;
|
||||||
|
uint32_t posKeyCount;
|
||||||
|
uint32_t rotKeyCount;
|
||||||
|
uint32_t scaKeyCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SHAnimDataHeader
|
||||||
|
{
|
||||||
|
uint32_t charCount;
|
||||||
|
uint32_t animNodeCount;
|
||||||
|
std::vector<SHAnimNodeInfo> nodeHeaders;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Main data containers
|
||||||
|
struct SHAnimData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
SHAnimationBehaviour pre;
|
||||||
|
SHAnimationBehaviour post;
|
||||||
|
|
||||||
|
std::vector<PositionKey> positionKeys;
|
||||||
|
std::vector<RotationKey> rotationKeys;
|
||||||
|
std::vector<ScaleKey> scaleKeys;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SH_API SHAnimAsset : SHAssetData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
double duration;
|
||||||
|
double ticksPerSecond;
|
||||||
|
|
||||||
|
std::vector<SHAnimData> nodeChannels;
|
||||||
|
//std::vector<aiMeshAnim*> meshChannels;
|
||||||
|
//std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file SHMeshAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 19 November 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction
|
||||||
|
* or disclosure of this file or its contents without the prior
|
||||||
|
* written consent of Digipen Institute of Technology is prohibited.
|
||||||
|
******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/SHMath.h"
|
||||||
|
#include "Assets/Asset Types/SHAssetData.h"
|
||||||
|
#include "Math/Vector/SHVec4U.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
constexpr int BONE_INDEX_ALIGHTMENT = 4;
|
||||||
|
|
||||||
|
struct SHMeshDataHeader
|
||||||
|
{
|
||||||
|
uint32_t vertexCount;
|
||||||
|
uint32_t indexCount;
|
||||||
|
uint32_t charCount;
|
||||||
|
uint32_t boneCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MeshBoneInfo
|
||||||
|
{
|
||||||
|
uint32_t charCount;
|
||||||
|
uint32_t weightCount; // Size should be same as boneCount
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BoneWeight
|
||||||
|
{
|
||||||
|
uint32_t index;
|
||||||
|
float weight;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MeshBone
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
SHMatrix offset;
|
||||||
|
std::vector<BoneWeight> weights;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SH_API SHMeshAsset : SHAssetData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::vector<SHVec3> VertexPositions;
|
||||||
|
std::vector<SHVec3> VertexTangents;
|
||||||
|
std::vector<SHVec3> VertexNormals;
|
||||||
|
std::vector<SHVec2> VertexTexCoords;
|
||||||
|
std::vector<uint32_t> Indices;
|
||||||
|
std::vector<SHVec4U> VertexBoneIndices;
|
||||||
|
std::vector<SHVec4> VertexBoneWeights;
|
||||||
|
uint32_t BoneCount;
|
||||||
|
};
|
||||||
|
}
|
|
@ -13,36 +13,28 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Math/SHMath.h"
|
|
||||||
#include "SHAssetData.h"
|
#include "Assets/Asset Types/Models/SHAnimationAsset.h"
|
||||||
|
#include "Assets/Asset Types/Models/SHMeshAsset.h"
|
||||||
|
#include "Assets/Asset Types/Models/SHRigAsset.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SHMeshAssetHeader
|
|
||||||
{
|
|
||||||
uint32_t vertexCount;
|
|
||||||
uint32_t indexCount;
|
|
||||||
std::string name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SHModelAssetHeader
|
struct SHModelAssetHeader
|
||||||
{
|
{
|
||||||
size_t meshCount;
|
size_t meshCount;
|
||||||
};
|
size_t animCount;
|
||||||
|
|
||||||
struct SH_API SHMeshData : SHAssetData
|
|
||||||
{
|
|
||||||
SHMeshAssetHeader header;
|
|
||||||
std::vector<SHVec3> VertexPositions;
|
|
||||||
std::vector<SHVec3> VertexTangents;
|
|
||||||
std::vector<SHVec3> VertexNormals;
|
|
||||||
std::vector<SHVec2> VertexTexCoords;
|
|
||||||
std::vector<uint32_t> Indices;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SH_API SHModelAsset : SHAssetData
|
struct SH_API SHModelAsset : SHAssetData
|
||||||
{
|
{
|
||||||
SHModelAssetHeader header;
|
SHModelAssetHeader header;
|
||||||
std::vector<SHMeshData*> subMeshes;
|
SHRigAsset rig;
|
||||||
|
|
||||||
|
std::vector<SHMeshDataHeader> meshHeaders;
|
||||||
|
std::vector<SHAnimDataHeader> animHeaders;
|
||||||
|
|
||||||
|
std::vector<SHMeshAsset*> meshes;
|
||||||
|
std::vector<SHAnimAsset*> anims;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHRigAsset.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHRigAsset::~SHRigAsset()
|
||||||
|
{
|
||||||
|
if (root != nullptr)
|
||||||
|
delete[] root;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file SHRigAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 19 November 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction
|
||||||
|
* or disclosure of this file or its contents without the prior
|
||||||
|
* written consent of Digipen Institute of Technology is prohibited.
|
||||||
|
******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/SHMath.h"
|
||||||
|
#include "Assets/Asset Types/SHAssetData.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHRigDataHeader
|
||||||
|
{
|
||||||
|
uint32_t nodeCount;
|
||||||
|
std::vector<uint32_t> charCounts;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SHRigNodeData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
SHMatrix transform;
|
||||||
|
SHMatrix offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SHRigNodeAsset
|
||||||
|
{
|
||||||
|
uint32_t idRef;
|
||||||
|
std::vector<SHRigNodeAsset*> children;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SH_API SHRigAsset : SHAssetData
|
||||||
|
{
|
||||||
|
~SHRigAsset();
|
||||||
|
|
||||||
|
SHRigDataHeader header;
|
||||||
|
std::vector<SHRigNodeData> nodeDataCollection;
|
||||||
|
SHRigNodeAsset* root;
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,30 +0,0 @@
|
||||||
/*************************************************************************//**
|
|
||||||
* \file SHAnimationAsset.h
|
|
||||||
* \author Loh Xiao Qi
|
|
||||||
* \date October 2022
|
|
||||||
* \brief
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
|
||||||
* disclosure of this file or its contents without the prior written consent
|
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
|
||||||
*****************************************************************************/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <assimp/anim.h>
|
|
||||||
#include "SHAssetData.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
struct SH_API SHAnimationAsset : SHAssetData
|
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
|
|
||||||
std::vector<aiNodeAnim*> nodeChannels;
|
|
||||||
std::vector<aiMeshAnim*> meshChannels;
|
|
||||||
std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
|
||||||
|
|
||||||
double duration;
|
|
||||||
double ticksPerSecond;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SHModelAsset.h"
|
#include "Models/SHModelAsset.h"
|
||||||
#include "SHTextureAsset.h"
|
#include "SHTextureAsset.h"
|
|
@ -13,73 +13,321 @@
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
#include "SHModelLoader.h"
|
#include "SHModelLoader.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
void SHModelLoader::ReadHeader(std::ifstream& file, SHMeshLoaderHeader& header) noexcept
|
void SHModelLoader::ReadHeaders(FileReference file, SHModelAsset& asset)
|
||||||
{
|
{
|
||||||
file.read(
|
file.read(
|
||||||
reinterpret_cast<char*>(&header),
|
reinterpret_cast<char*>(&asset.header),
|
||||||
sizeof(SHMeshLoaderHeader)
|
sizeof(asset.header)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (asset.header.meshCount > 0)
|
||||||
|
{
|
||||||
|
asset.meshHeaders.resize(asset.header.meshCount);
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(asset.meshHeaders.data()),
|
||||||
|
asset.header.meshCount * sizeof(SHMeshDataHeader)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asset.header.animCount > 0)
|
||||||
|
{
|
||||||
|
asset.animHeaders.resize(asset.header.animCount);
|
||||||
|
for (auto i {0}; i < asset.header.animCount; ++i)
|
||||||
|
{
|
||||||
|
auto& animHeader = asset.animHeaders[i];
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(&animHeader.charCount),
|
||||||
|
sizeof(uint32_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(&animHeader.animNodeCount),
|
||||||
|
sizeof(uint32_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
animHeader.nodeHeaders.resize(animHeader.animNodeCount);
|
||||||
|
for (auto j {0}; j < animHeader.animNodeCount; ++j)
|
||||||
|
{
|
||||||
|
auto& nodeHeader = animHeader.nodeHeaders[j];
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(&nodeHeader),
|
||||||
|
sizeof(SHAnimNodeInfo)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHModelLoader::ReadData(FileReference file, SHModelAsset& asset)
|
||||||
|
{
|
||||||
|
ReadMeshData(file, asset.meshHeaders, asset.meshes);
|
||||||
|
ReadAnimData(file, asset.animHeaders, asset.anims);
|
||||||
|
|
||||||
|
// Not eof yet, animation exists
|
||||||
|
if (file.peek() != EOF)
|
||||||
|
{
|
||||||
|
ReadRigHeader(file, asset.rig.header);
|
||||||
|
ReadRigData(file, asset.rig.header, asset.rig.nodeDataCollection);
|
||||||
|
ReadRigTree(file, asset.rig.header, asset.rig.root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHModelLoader::ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data)
|
||||||
|
{
|
||||||
|
data.name.resize(info.charCount);
|
||||||
|
file.read(
|
||||||
|
data.name.data(),
|
||||||
|
info.charCount
|
||||||
|
);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(&data.pre),
|
||||||
|
sizeof(SHAnimationBehaviour)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(&data.post),
|
||||||
|
sizeof(SHAnimationBehaviour)
|
||||||
|
);
|
||||||
|
|
||||||
|
uint32_t keySize {0};
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(&keySize),
|
||||||
|
sizeof(uint32_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
data.positionKeys.resize(keySize);
|
||||||
|
data.rotationKeys.resize(keySize);
|
||||||
|
data.scaleKeys.resize(keySize);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(data.positionKeys.data()),
|
||||||
|
sizeof(PositionKey) * keySize
|
||||||
|
);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(data.rotationKeys.data()),
|
||||||
|
sizeof(RotationKey) * keySize
|
||||||
|
);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(data.scaleKeys.data()),
|
||||||
|
sizeof(ScaleKey) * keySize
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHModelLoader::ReadData(std::ifstream& file, SHMeshLoaderHeader const& header, SHMeshData& data) noexcept
|
void SHModelLoader::ReadRigHeader(FileReference file, SHRigDataHeader& header)
|
||||||
{
|
{
|
||||||
auto const vertexVec3Byte{ sizeof(SHVec3) * header.vertexCount };
|
file.read(
|
||||||
auto const vertexVec2Byte{ sizeof(SHVec2) * header.vertexCount };
|
reinterpret_cast<char*>(&header.nodeCount),
|
||||||
|
sizeof(uint32_t)
|
||||||
|
);
|
||||||
|
|
||||||
data.VertexPositions.resize(header.vertexCount);
|
header.charCounts.resize(header.nodeCount);
|
||||||
data.VertexTangents.resize(header.vertexCount);
|
file.read(
|
||||||
data.VertexNormals.resize(header.vertexCount);
|
reinterpret_cast<char*>(header.charCounts.data()),
|
||||||
data.VertexTexCoords.resize(header.vertexCount);
|
sizeof(uint32_t) * header.nodeCount
|
||||||
data.Indices.resize(header.indexCount);
|
);
|
||||||
data.header.name.resize(header.charCount);
|
|
||||||
|
|
||||||
file.read(data.header.name.data(), header.charCount);
|
|
||||||
file.read(reinterpret_cast<char*>(data.VertexPositions.data()), vertexVec3Byte);
|
|
||||||
file.read(reinterpret_cast<char*>(data.VertexTangents.data()), vertexVec3Byte);
|
|
||||||
file.read(reinterpret_cast<char*>(data.VertexNormals.data()), vertexVec3Byte);
|
|
||||||
file.read(reinterpret_cast<char*>(data.VertexTexCoords.data()), vertexVec2Byte);
|
|
||||||
file.read(reinterpret_cast<char*>(data.Indices.data()), sizeof(uint32_t) * header.indexCount);
|
|
||||||
|
|
||||||
data.header.vertexCount = header.vertexCount;
|
|
||||||
data.header.indexCount = header.indexCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHModelLoader::LoadSHMesh(AssetPath path, SHModelAsset& model) noexcept
|
void SHModelLoader::ReadRigData(FileReference file, SHRigDataHeader const& header, std::vector<SHRigNodeData>& data)
|
||||||
{
|
{
|
||||||
|
data.resize(header.nodeCount);
|
||||||
|
|
||||||
|
for (auto i {0}; i < header.nodeCount; ++i)
|
||||||
|
{
|
||||||
|
data[i].name.resize(header.charCounts[i]);
|
||||||
|
file.read(
|
||||||
|
data[i].name.data(),
|
||||||
|
header.charCounts[i]
|
||||||
|
);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(&data[i].transform),
|
||||||
|
sizeof(SHMatrix)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(&data[i].offset),
|
||||||
|
sizeof(SHMatrix)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHModelLoader::ReadRigTree(FileReference file, SHRigDataHeader const& header, SHRigNodeAsset*& root)
|
||||||
|
{
|
||||||
|
// Read All nodes into one contiguous data block
|
||||||
|
struct NodeTemp
|
||||||
|
{
|
||||||
|
uint32_t id, numChild;
|
||||||
|
};
|
||||||
|
|
||||||
|
NodeTemp* dst = new NodeTemp[header.nodeCount];
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(dst),
|
||||||
|
sizeof(NodeTemp) * header.nodeCount
|
||||||
|
);
|
||||||
|
|
||||||
|
// Build and populate tree
|
||||||
|
SHRigNodeAsset* nodePool = new SHRigNodeAsset[header.nodeCount];
|
||||||
|
root = nodePool;
|
||||||
|
|
||||||
|
std::queue<std::pair<SHRigNodeAsset*, NodeTemp*>> nodeQueue;
|
||||||
|
nodeQueue.emplace(std::make_pair(nodePool, dst));
|
||||||
|
|
||||||
|
SHRigNodeAsset* depthPtr = nodePool + 1;
|
||||||
|
NodeTemp* depthTempPtr = dst + 1;
|
||||||
|
|
||||||
|
while(!nodeQueue.empty())
|
||||||
|
{
|
||||||
|
auto currPair = nodeQueue.front();
|
||||||
|
nodeQueue.pop();
|
||||||
|
auto currNode = currPair.first;
|
||||||
|
auto currTemp = currPair.second;
|
||||||
|
|
||||||
|
currNode->idRef = currTemp->id;
|
||||||
|
|
||||||
|
for (auto i{0}; i < currTemp->numChild; ++i)
|
||||||
|
{
|
||||||
|
currNode->children.push_back(depthPtr);
|
||||||
|
nodeQueue.emplace(depthPtr++, depthTempPtr++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHModelLoader::ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers,
|
||||||
|
std::vector<SHMeshAsset*>& meshes)
|
||||||
|
{
|
||||||
|
meshes.resize(headers.size());
|
||||||
|
for (auto i {0}; i < headers.size(); ++i)
|
||||||
|
{
|
||||||
|
auto const& header = headers[i];
|
||||||
|
auto& data = *new SHMeshAsset;
|
||||||
|
|
||||||
|
auto const vertexVec3Byte{ sizeof(SHVec3) * header.vertexCount };
|
||||||
|
auto const vertexVec2Byte{ sizeof(SHVec2) * header.vertexCount };
|
||||||
|
|
||||||
|
data.name.resize(header.charCount);
|
||||||
|
data.VertexPositions.resize(header.vertexCount);
|
||||||
|
data.VertexTangents.resize(header.vertexCount);
|
||||||
|
data.VertexNormals.resize(header.vertexCount);
|
||||||
|
data.VertexTexCoords.resize(header.vertexCount);
|
||||||
|
data.Indices.resize(header.indexCount);
|
||||||
|
data.BoneCount = header.boneCount;
|
||||||
|
|
||||||
|
file.read(data.name.data(), header.charCount);
|
||||||
|
file.read(reinterpret_cast<char*>(data.VertexPositions.data()), vertexVec3Byte);
|
||||||
|
file.read(reinterpret_cast<char*>(data.VertexTangents.data()), vertexVec3Byte);
|
||||||
|
file.read(reinterpret_cast<char*>(data.VertexNormals.data()), vertexVec3Byte);
|
||||||
|
file.read(reinterpret_cast<char*>(data.VertexTexCoords.data()), vertexVec2Byte);
|
||||||
|
file.read(reinterpret_cast<char*>(data.Indices.data()), sizeof(uint32_t) * header.indexCount);
|
||||||
|
|
||||||
|
if (header.boneCount)
|
||||||
|
{
|
||||||
|
std::vector<MeshBoneInfo> boneInfos(header.boneCount);
|
||||||
|
std::vector<MeshBone> bones(header.boneCount);
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(boneInfos.data()), sizeof(MeshBoneInfo) * header.boneCount);
|
||||||
|
|
||||||
|
for (auto i{ 0 }; i < header.boneCount; ++i)
|
||||||
|
{
|
||||||
|
auto& bone = bones[i];
|
||||||
|
auto const& info = boneInfos[i];
|
||||||
|
|
||||||
|
bone.name.resize(info.charCount);
|
||||||
|
file.read(bone.name.data(), info.charCount);
|
||||||
|
file.read(reinterpret_cast<char*>(&bone.offset), sizeof(SHMatrix));
|
||||||
|
|
||||||
|
bone.weights.resize(info.weightCount);
|
||||||
|
file.read(reinterpret_cast<char*>(bone.weights.data()), sizeof(BoneWeight) * info.weightCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.VertexBoneIndices.resize(header.vertexCount);
|
||||||
|
data.VertexBoneWeights.resize(header.vertexCount);
|
||||||
|
|
||||||
|
for (uint32_t boneIndex{0}; boneIndex < bones.size(); ++boneIndex)
|
||||||
|
{
|
||||||
|
auto const& bone = bones[boneIndex];
|
||||||
|
for (auto const& weight : bone.weights)
|
||||||
|
{
|
||||||
|
auto& boneIndices = data.VertexBoneIndices[weight.index];
|
||||||
|
auto& boneWeight = data.VertexBoneWeights[weight.index];
|
||||||
|
|
||||||
|
for (auto j{0}; j < BONE_INDEX_ALIGHTMENT; ++j)
|
||||||
|
{
|
||||||
|
if (boneWeight[j] == 0.f)
|
||||||
|
{
|
||||||
|
boneIndices[j] = boneIndex;
|
||||||
|
boneWeight[j] = weight.weight;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
meshes[i] = &data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHModelLoader::ReadAnimData(FileReference file, std::vector<SHAnimDataHeader> const& headers,
|
||||||
|
std::vector<SHAnimAsset*>& anims)
|
||||||
|
{
|
||||||
|
anims.resize(headers.size());
|
||||||
|
for (auto i {0}; i < headers.size(); ++i)
|
||||||
|
{
|
||||||
|
auto const& header = headers[i];
|
||||||
|
auto& animAsset = *new SHAnimAsset;
|
||||||
|
|
||||||
|
animAsset.name.resize(header.charCount);
|
||||||
|
file.read(
|
||||||
|
animAsset.name.data(),
|
||||||
|
header.charCount
|
||||||
|
);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(&animAsset.duration),
|
||||||
|
sizeof(double)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(&animAsset.ticksPerSecond),
|
||||||
|
sizeof(double)
|
||||||
|
);
|
||||||
|
|
||||||
|
animAsset.nodeChannels.resize(header.animNodeCount);
|
||||||
|
for (auto i {0}; i < header.animNodeCount; ++i)
|
||||||
|
{
|
||||||
|
ReadAnimNode(file, header.nodeHeaders[i], animAsset.nodeChannels[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
anims[i] = &animAsset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SHAssetData* SHModelLoader::Load(AssetPath path)
|
||||||
|
{
|
||||||
|
auto result = new SHModelAsset();
|
||||||
|
|
||||||
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
||||||
if (!file.is_open())
|
if (!file.is_open())
|
||||||
{
|
{
|
||||||
SHLOG_ERROR("[Model Loader] Unable to open SHModel File: {}", path.string());
|
SHLOG_ERROR("[Model Loader] Unable to open SHModel File: {}", path.string());
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
file.seekg(0);
|
ReadHeaders(file, *result);
|
||||||
|
ReadData(file, *result);
|
||||||
|
|
||||||
file.read(
|
|
||||||
reinterpret_cast<char*>(&model.header),
|
|
||||||
sizeof(SHModelAssetHeader)
|
|
||||||
);
|
|
||||||
|
|
||||||
std::vector<SHMeshLoaderHeader> headers(model.header.meshCount);
|
|
||||||
model.subMeshes.resize(model.header.meshCount);
|
|
||||||
|
|
||||||
for (auto i{ 0 }; i < model.header.meshCount; ++i)
|
|
||||||
{
|
|
||||||
model.subMeshes[i] = new SHMeshData();
|
|
||||||
ReadHeader(file, headers[i]);
|
|
||||||
ReadData(file, headers[i], *model.subMeshes[i]);
|
|
||||||
}
|
|
||||||
file.close();
|
file.close();
|
||||||
}
|
|
||||||
|
|
||||||
SHAssetData* SHModelLoader::Load(AssetPath path)
|
|
||||||
{
|
|
||||||
auto result = new SHModelAsset();
|
|
||||||
|
|
||||||
LoadSHMesh(path, *result);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Assets/Asset Types/SHModelAsset.h"
|
#include "Assets/Asset Types/Models/SHModelAsset.h"
|
||||||
#include "SHAssetLoader.h"
|
#include "SHAssetLoader.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
@ -18,19 +18,20 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
class SHModelLoader : public SHAssetLoader
|
class SHModelLoader : public SHAssetLoader
|
||||||
{
|
{
|
||||||
struct SHMeshLoaderHeader
|
using FileReference = std::ifstream&;
|
||||||
{
|
|
||||||
uint32_t vertexCount;
|
|
||||||
uint32_t indexCount;
|
|
||||||
uint32_t charCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
void ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data);
|
||||||
|
|
||||||
void ReadHeader(std::ifstream& file, SHMeshLoaderHeader& header) noexcept;
|
void ReadRigHeader(FileReference file, SHRigDataHeader& header);
|
||||||
void ReadData(std::ifstream& file, SHMeshLoaderHeader const& header, SHMeshData& data) noexcept;
|
void ReadRigData(FileReference file, SHRigDataHeader const& header, std::vector<SHRigNodeData>& data);
|
||||||
|
void ReadRigTree(FileReference file, SHRigDataHeader const& header, SHRigNodeAsset*& root);
|
||||||
|
|
||||||
|
void ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers, std::vector<SHMeshAsset*>& meshes);
|
||||||
|
void ReadAnimData(FileReference file, std::vector<SHAnimDataHeader> const& headers, std::vector<SHAnimAsset*>& anims);
|
||||||
|
|
||||||
|
void ReadHeaders(FileReference file, SHModelAsset& asset);
|
||||||
|
void ReadData(FileReference file, SHModelAsset& asset);
|
||||||
public:
|
public:
|
||||||
void LoadSHMesh(AssetPath path, SHModelAsset& model) noexcept;
|
|
||||||
SHAssetData* Load(AssetPath path) override;
|
SHAssetData* Load(AssetPath path) override;
|
||||||
void Write(SHAssetData const* data, AssetPath path) override;
|
void Write(SHAssetData const* data, AssetPath path) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "Libraries/Compilers/SHShaderSourceCompiler.h"
|
#include "Libraries/Compilers/SHShaderSourceCompiler.h"
|
||||||
|
|
||||||
#include "Filesystem/SHFileSystem.h"
|
#include "Filesystem/SHFileSystem.h"
|
||||||
|
#include <rttr/registration.h>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -492,8 +493,8 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::Load() noexcept
|
void SHAssetManager::Load() noexcept
|
||||||
{
|
{
|
||||||
BuildAssetCollection();
|
|
||||||
InitLoaders();
|
InitLoaders();
|
||||||
|
BuildAssetCollection();
|
||||||
//CompileAll();
|
//CompileAll();
|
||||||
//LoadAllData();
|
//LoadAllData();
|
||||||
}
|
}
|
||||||
|
@ -549,7 +550,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
assetData.emplace(
|
assetData.emplace(
|
||||||
parent.subAssets[i]->id,
|
parent.subAssets[i]->id,
|
||||||
parentModel->subMeshes[i]
|
parentModel->meshes[i]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -607,10 +608,10 @@ namespace SHADE
|
||||||
|
|
||||||
SHModelAsset* const data = reinterpret_cast<SHModelAsset*>(LoadData(newAsset));
|
SHModelAsset* const data = reinterpret_cast<SHModelAsset*>(LoadData(newAsset));
|
||||||
assetData.emplace(newAsset.id, data);
|
assetData.emplace(newAsset.id, data);
|
||||||
for(auto const& subMesh : data->subMeshes)
|
for(auto const& subMesh : data->meshes)
|
||||||
{
|
{
|
||||||
SHAsset subAsset{
|
SHAsset subAsset{
|
||||||
.name = subMesh->header.name,
|
.name = subMesh->name,
|
||||||
.id = GenerateAssetID(AssetType::MESH),
|
.id = GenerateAssetID(AssetType::MESH),
|
||||||
.type = AssetType::MESH,
|
.type = AssetType::MESH,
|
||||||
.isSubAsset = true,
|
.isSubAsset = true,
|
||||||
|
@ -733,3 +734,25 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace rttr
|
||||||
|
{
|
||||||
|
using namespace SHADE;
|
||||||
|
RTTR_REGISTRATION
|
||||||
|
{
|
||||||
|
registration::enumeration<AssetType>("Asset Type")
|
||||||
|
(
|
||||||
|
value("Invalid", AssetType::INVALID),
|
||||||
|
value("Shader", AssetType::SHADER),
|
||||||
|
value("Shader [Built-In]", AssetType::SHADER_BUILT_IN),
|
||||||
|
value("Texture", AssetType::TEXTURE),
|
||||||
|
value("Model", AssetType::MODEL),
|
||||||
|
value("Scene", AssetType::SCENE),
|
||||||
|
value("Prefab", AssetType::PREFAB),
|
||||||
|
value("Material", AssetType::MATERIAL),
|
||||||
|
value("Mesh", AssetType::MESH),
|
||||||
|
value("Script", AssetType::SCRIPT),
|
||||||
|
value("Font", AssetType::FONT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,11 @@ namespace SHADE
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T* const> SHAssetManager::GetData(AssetID id) noexcept
|
std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T* const> SHAssetManager::GetData(AssetID id) noexcept
|
||||||
{
|
{
|
||||||
|
if (id == 0)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (!assetData.contains(id))
|
if (!assetData.contains(id))
|
||||||
{
|
{
|
||||||
for (auto const& asset : std::ranges::views::values(assetCollection))
|
for (auto const& asset : std::ranges::views::values(assetCollection))
|
||||||
|
|
|
@ -125,14 +125,29 @@ namespace SHADE
|
||||||
SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID());
|
SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID());
|
||||||
if (listenerTransform)
|
if (listenerTransform)
|
||||||
{
|
{
|
||||||
listener.SetPos(listenerTransform->GetLocalPosition());
|
listener.SetPos(listenerTransform->GetWorldPosition()); // TODO: Clean up listener
|
||||||
listener.SetForward({ (listenerTransform->GetLocalScale()[0] > 0.f) ? 1.f : -1.f, 0.f, 0.f });
|
listener.SetForward({ (listenerTransform->GetLocalScale()[0] > 0.f) ? 1.f : -1.f, 0.f, 0.f }); //TODO: USE CORRECT FORWARD
|
||||||
FMOD_VECTOR pos = { listener.pos[0] ,listener.pos[1] ,0.f };
|
FMOD_VECTOR pos = { listener.pos[0] ,listener.pos[1] ,0.f };
|
||||||
FMOD_VECTOR forward = { listener.forward[0] ,listener.forward[1] ,listener.forward[2] };
|
FMOD_VECTOR forward = { listener.forward[0] ,listener.forward[1] ,listener.forward[2] };
|
||||||
FMOD_VECTOR up = { listener.up[0] ,listener.up[1] ,listener.up[2] };
|
FMOD_VECTOR up = { listener.up[0] ,listener.up[1] ,listener.up[2] };
|
||||||
fmodSystem->set3DListenerAttributes(0, &pos, nullptr, &forward, &up);
|
fmodSystem->set3DListenerAttributes(0, &pos, nullptr, &forward, &up);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto [begin, end] = audioClipLibrary.GetDenseAccess();
|
||||||
|
for(auto it = begin; it != end; ++it)
|
||||||
|
{
|
||||||
|
if(it->instance && (it->transformRef != MAX_EID))
|
||||||
|
{
|
||||||
|
if(SHTransformComponent* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(it->transformRef))
|
||||||
|
{
|
||||||
|
FMOD_3D_ATTRIBUTES attribs{}; //TODO: Set other attribs
|
||||||
|
auto pos = transformComponent->GetWorldPosition();
|
||||||
|
attribs.position = {pos.x, pos.y, pos.z};
|
||||||
|
it->instance->set3DAttributes(&attribs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAudioSystem::AudioRoutine::AudioRoutine()
|
SHAudioSystem::AudioRoutine::AudioRoutine()
|
||||||
|
@ -325,27 +340,83 @@ namespace SHADE
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioClip* SHAudioSystem::CreateAudioClip(const char* path)
|
Handle<AudioClip> SHAudioSystem::CreateAudioClip(const char* path)
|
||||||
{
|
{
|
||||||
AudioClipID newID{};
|
Handle<AudioClip> audioClipHandle{};
|
||||||
AudioClip* clip = nullptr;
|
|
||||||
auto it = eventMap.find(path);
|
if(auto it = eventMap.find(path); it != eventMap.end())
|
||||||
if (it != eventMap.end())
|
|
||||||
{
|
{
|
||||||
FMOD::Studio::EventInstance* event = nullptr;
|
audioClipHandle = audioClipLibrary.Create();
|
||||||
it->second->createInstance(&event);
|
it->second->createInstance(&audioClipHandle->instance);
|
||||||
if (event)
|
|
||||||
{
|
|
||||||
//event->start();
|
|
||||||
newID = clipID;
|
|
||||||
clipID++;
|
|
||||||
eventInstances.emplace(newID, AudioClip(newID, event));
|
|
||||||
clip = &eventInstances[newID];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return clip;
|
|
||||||
|
return audioClipHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHAudioSystem::AddAudioClipToBGMChannelGroup(Handle<AudioClip> handle)
|
||||||
|
{
|
||||||
|
if(!handle->instance)
|
||||||
|
return;
|
||||||
|
FMOD::ChannelGroup* channelGroup;
|
||||||
|
handle->instance->getChannelGroup(&channelGroup);
|
||||||
|
|
||||||
|
if(!channelGroup)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Event instance has no channel group")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bgmChannelGroup->addGroup(channelGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAudioSystem::AddAudioClipToSFXChannelGroup(Handle<AudioClip> handle)
|
||||||
|
{
|
||||||
|
if (!handle->instance)
|
||||||
|
return;
|
||||||
|
FMOD::ChannelGroup* channelGroup;
|
||||||
|
handle->instance->getChannelGroup(&channelGroup);
|
||||||
|
|
||||||
|
if (!channelGroup)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Event instance has no channel group")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sfxChannelGroup->addGroup(channelGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAudioSystem::AttachAudioClipToObject(Handle<AudioClip> handle, EntityID eid)
|
||||||
|
{
|
||||||
|
if (auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
|
||||||
|
{
|
||||||
|
handle->transformRef = eid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAudioSystem::DetachAudioClipFromObject(Handle<AudioClip> handle)
|
||||||
|
{
|
||||||
|
handle->transformRef = MAX_EID;
|
||||||
|
}
|
||||||
|
|
||||||
|
//AudioClip* SHAudioSystem::CreateAudioClip(const char* path)
|
||||||
|
//{
|
||||||
|
// AudioClipID newID{};
|
||||||
|
// AudioClip* clip = nullptr;
|
||||||
|
// auto it = eventMap.find(path);
|
||||||
|
// if (it != eventMap.end())
|
||||||
|
// {
|
||||||
|
// FMOD::Studio::EventInstance* event = nullptr;
|
||||||
|
// it->second->createInstance(&event);
|
||||||
|
// if (event)
|
||||||
|
// {
|
||||||
|
// //event->start();
|
||||||
|
// newID = clipID;
|
||||||
|
// clipID++;
|
||||||
|
// eventInstances.emplace(newID, AudioClip(newID, event));
|
||||||
|
// clip = &eventInstances[newID];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return clip;
|
||||||
|
//}
|
||||||
|
|
||||||
//std::vector<const char*> SHAudioSystem::GetAllEvents()
|
//std::vector<const char*> SHAudioSystem::GetAllEvents()
|
||||||
//{
|
//{
|
||||||
// int count{};
|
// int count{};
|
||||||
|
@ -489,41 +560,39 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioClip::AudioClip(AudioClipID clipID, FMOD::Studio::EventInstance* inst)
|
void AudioClip::Play()
|
||||||
:instance(inst), id(clipID)
|
|
||||||
{
|
{
|
||||||
}
|
if(!instance)
|
||||||
|
|
||||||
AudioClip::~AudioClip()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioClip::Play(bool isSfx)
|
|
||||||
{
|
|
||||||
if (!instance)
|
|
||||||
return;
|
return;
|
||||||
instance->start();
|
instance->start();
|
||||||
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
|
|
||||||
instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClip::Play(SHVec3 position, bool isSfx)
|
//void AudioClip::Play(bool isSfx)
|
||||||
{
|
//{
|
||||||
if (!instance)
|
// if (!instance)
|
||||||
return;
|
// return;
|
||||||
instance->start();
|
// instance->start();
|
||||||
FMOD_3D_ATTRIBUTES attributes{ {} };
|
// auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
|
||||||
attributes.forward.z = 1.0f;
|
// instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume()));
|
||||||
attributes.up.y = 1.0f;
|
//}
|
||||||
|
|
||||||
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
|
//void AudioClip::Play(SHVec3 position, bool isSfx)
|
||||||
SHVec3 listenerPos = audioSystem->GetListenerPosition();
|
//{
|
||||||
attributes.position.x = position[0];
|
// if (!instance)
|
||||||
attributes.position.y = position[1];
|
// return;
|
||||||
attributes.position.z = listenerPos[2];
|
// instance->start();
|
||||||
instance->set3DAttributes(&attributes);
|
// FMOD_3D_ATTRIBUTES attributes{ {} };
|
||||||
instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume()));
|
// attributes.forward.z = 1.0f;
|
||||||
}
|
// attributes.up.y = 1.0f;
|
||||||
|
|
||||||
|
// auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
|
||||||
|
// SHVec3 listenerPos = audioSystem->GetListenerPosition();
|
||||||
|
// attributes.position.x = position[0];
|
||||||
|
// attributes.position.y = position[1];
|
||||||
|
// attributes.position.z = listenerPos[2];
|
||||||
|
// instance->set3DAttributes(&attributes);
|
||||||
|
// instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume()));
|
||||||
|
//}
|
||||||
|
|
||||||
void AudioClip::Stop(bool fadeOut)
|
void AudioClip::Stop(bool fadeOut)
|
||||||
{
|
{
|
||||||
|
@ -557,12 +626,12 @@ namespace SHADE
|
||||||
instance->setParameterByName(paramName, value);
|
instance->setParameterByName(paramName, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioClip::SetParameterLabel(const char* paramName, const char* label)
|
//void AudioClip::SetParameterLabel(const char* paramName, const char* label)
|
||||||
{
|
//{
|
||||||
if (!instance)
|
// if (!instance)
|
||||||
return;
|
// return;
|
||||||
instance->setParameterByNameWithLabel(paramName, label);
|
// instance->setParameterByNameWithLabel(paramName, label);
|
||||||
}
|
//}
|
||||||
|
|
||||||
float AudioClip::GetParameterValue(const char* paramName)
|
float AudioClip::GetParameterValue(const char* paramName)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "Events/SHEvent.h"
|
#include "Events/SHEvent.h"
|
||||||
|
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
#include <Resource/SHResourceLibrary.h>
|
||||||
#define AUDIO_SYS_MAX_CHANNELS 1024
|
#define AUDIO_SYS_MAX_CHANNELS 1024
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -22,27 +23,22 @@ namespace SHADE
|
||||||
|
|
||||||
class SHAudioListenerComponent;
|
class SHAudioListenerComponent;
|
||||||
|
|
||||||
typedef uint64_t AudioClipID;
|
class SH_API AudioClip
|
||||||
|
|
||||||
class AudioClip
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AudioClip() = default;
|
void Play();
|
||||||
AudioClip(AudioClipID clipID, FMOD::Studio::EventInstance* inst);
|
//void Play(SHVec3 position);
|
||||||
~AudioClip();
|
|
||||||
void Play(bool isSfx = true);
|
|
||||||
void Play(SHVec3 position, bool isSfx = true);
|
|
||||||
void Stop(bool fadeOut = true);
|
void Stop(bool fadeOut = true);
|
||||||
|
|
||||||
void SetPause(bool pause);
|
void SetPause(bool pause);
|
||||||
bool IsPaused();
|
bool IsPaused();
|
||||||
void SetParameter(const char* paramName, float value);
|
void SetParameter(const char* paramName, float value);
|
||||||
void SetParameterLabel(const char* paramName, const char* label);
|
//void SetParameterLabel(const char* paramName, const char* label);
|
||||||
float GetParameterValue(const char* paramName);
|
float GetParameterValue(const char* paramName);
|
||||||
friend class SHAudioSystem;
|
friend class SHAudioSystem;
|
||||||
private:
|
private:
|
||||||
FMOD::Studio::EventInstance* instance;
|
FMOD::Studio::EventInstance* instance = nullptr;
|
||||||
AudioClipID id;
|
EntityID transformRef = MAX_EID;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SH_API SHAudioSystem : public SHSystem
|
class SH_API SHAudioSystem : public SHSystem
|
||||||
|
@ -62,7 +58,7 @@ namespace SHADE
|
||||||
void Exit();
|
void Exit();
|
||||||
|
|
||||||
int GetAvailableChannelIndex();
|
int GetAvailableChannelIndex();
|
||||||
/*std::vector<SHSound>::size_type CreateSound(const char* filepath, bool loop = false);*/
|
|
||||||
void PlaySFX(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f);
|
void PlaySFX(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f);
|
||||||
void PlayBGM(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f);
|
void PlayBGM(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f);
|
||||||
void PlayEventOnce(const char* path, bool isSFX = true, EntityID eid = MAX_EID, bool spatial = false);
|
void PlayEventOnce(const char* path, bool isSFX = true, EntityID eid = MAX_EID, bool spatial = false);
|
||||||
|
@ -71,9 +67,15 @@ namespace SHADE
|
||||||
void StopAllSounds();
|
void StopAllSounds();
|
||||||
|
|
||||||
std::optional<FMOD_GUID> GetEventGUID(const char* path);
|
std::optional<FMOD_GUID> GetEventGUID(const char* path);
|
||||||
AudioClip* CreateAudioClip(const char* path);
|
//AudioClip* CreateAudioClip(const char* path);
|
||||||
//std::vector<const char*> GetAllEvents();
|
//AUDIO CLIP
|
||||||
|
Handle<AudioClip> CreateAudioClip(const char* path);
|
||||||
|
void AddAudioClipToBGMChannelGroup(Handle<AudioClip> handle);
|
||||||
|
void AddAudioClipToSFXChannelGroup(Handle<AudioClip> handle);
|
||||||
|
|
||||||
|
void AttachAudioClipToObject(Handle<AudioClip> handle, EntityID eid);
|
||||||
|
void DetachAudioClipFromObject(Handle<AudioClip> handle);
|
||||||
|
///
|
||||||
float GetBgmVolume();
|
float GetBgmVolume();
|
||||||
float GetSfxVolume();
|
float GetSfxVolume();
|
||||||
float GetMasterVolume();
|
float GetMasterVolume();
|
||||||
|
@ -84,6 +86,7 @@ namespace SHADE
|
||||||
bool GetPaused() const;
|
bool GetPaused() const;
|
||||||
SHVec3 GetListenerPosition();
|
SHVec3 GetListenerPosition();
|
||||||
void LoadBank(const char* path);
|
void LoadBank(const char* path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FMOD::Studio::System* fmodStudioSystem;
|
FMOD::Studio::System* fmodStudioSystem;
|
||||||
FMOD::System* fmodSystem;
|
FMOD::System* fmodSystem;
|
||||||
|
@ -95,7 +98,9 @@ namespace SHADE
|
||||||
//std::unordered_map<ResourceID, SHBank> bankMap;
|
//std::unordered_map<ResourceID, SHBank> bankMap;
|
||||||
std::unordered_map<std::string, SHBank> bankMap;
|
std::unordered_map<std::string, SHBank> bankMap;
|
||||||
std::unordered_map<std::string, FMOD::Studio::EventDescription*> eventMap;
|
std::unordered_map<std::string, FMOD::Studio::EventDescription*> eventMap;
|
||||||
std::unordered_map<AudioClipID, AudioClip> eventInstances;
|
//std::unordered_map<AudioClipID, AudioClip> eventInstances;
|
||||||
|
SHResourceLibrary<AudioClip> audioClipLibrary{};
|
||||||
|
|
||||||
FMOD::ChannelGroup* bgmChannelGroup, * sfxChannelGroup, * masterGroup;
|
FMOD::ChannelGroup* bgmChannelGroup, * sfxChannelGroup, * masterGroup;
|
||||||
FMOD::Channel* audioChannels[AUDIO_SYS_MAX_CHANNELS];
|
FMOD::Channel* audioChannels[AUDIO_SYS_MAX_CHANNELS];
|
||||||
FMOD_RESULT result;
|
FMOD_RESULT result;
|
||||||
|
@ -105,7 +110,6 @@ namespace SHADE
|
||||||
SHBank masterBank, stringsBank, musicBank, sfxBank; //To do: change to map of banks loaded by resource manager
|
SHBank masterBank, stringsBank, musicBank, sfxBank; //To do: change to map of banks loaded by resource manager
|
||||||
|
|
||||||
std::vector<SHAudioListenerComponent>* denseListener;
|
std::vector<SHAudioListenerComponent>* denseListener;
|
||||||
AudioClipID clipID = 0;
|
|
||||||
|
|
||||||
SHEventHandle onPlay(SHEventPtr onStopEvent);
|
SHEventHandle onPlay(SHEventPtr onStopEvent);
|
||||||
SHEventHandle onStop(SHEventPtr onStopEvent);
|
SHEventHandle onStop(SHEventPtr onStopEvent);
|
||||||
|
|
|
@ -314,7 +314,7 @@ namespace SHADE
|
||||||
camera.orthoProjMatrix(3, 3) = 1.0f;
|
camera.orthoProjMatrix(3, 3) = 1.0f;
|
||||||
|
|
||||||
//camera.perspProjMatrix = SHMatrix::OrthographicLH(9.0f, 9.0f, 0.1f, 20.0f);
|
//camera.perspProjMatrix = SHMatrix::OrthographicLH(9.0f, 9.0f, 0.1f, 20.0f);
|
||||||
camera.orthoProjMatrix = SHMatrix::OrthographicRH(camera.GetWidth(), camera.GetHeight(), camera.GetNear(), camera.GetFar());
|
//camera.orthoProjMatrix = SHMatrix::OrthographicLH(camera.GetWidth(), camera.GetHeight(), camera.GetNear(), camera.GetFar());
|
||||||
//camera.perspProjMatrix = SHMatrix::OrthographicLH(5.0f, 5.0f, 0.1f, 20.0f);
|
//camera.perspProjMatrix = SHMatrix::OrthographicLH(5.0f, 5.0f, 0.1f, 20.0f);
|
||||||
//camera.projMatrix.Transpose();
|
//camera.projMatrix.Transpose();
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
||||||
#include "Scripting/SHVSUtilities.h"
|
#include "Scripting/SHVSUtilities.h"
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
|
#include "Tools/Utilities/SHStringUtilities.h"
|
||||||
|
#include <filesystem>
|
||||||
|
#include <rttr/type>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -27,6 +30,13 @@ namespace SHADE
|
||||||
void SHAssetBrowser::Init()
|
void SHAssetBrowser::Init()
|
||||||
{
|
{
|
||||||
SHEditorWindow::Init();
|
SHEditorWindow::Init();
|
||||||
|
rttr::array_range<rttr::string_view> typeNames = typeEnumAlign.get_names();
|
||||||
|
|
||||||
|
for(auto const& name : typeNames)
|
||||||
|
{
|
||||||
|
uint64_t val = typeEnumAlign.name_to_value(name).to_uint64();
|
||||||
|
typeFilters[val] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetBrowser::Update()
|
void SHAssetBrowser::Update()
|
||||||
|
@ -34,7 +44,10 @@ namespace SHADE
|
||||||
SHEditorWindow::Update();
|
SHEditorWindow::Update();
|
||||||
if (Begin())
|
if (Begin())
|
||||||
{
|
{
|
||||||
RecursivelyDrawTree(rootFolder);
|
for(auto subFolder : rootFolder->subFolders)
|
||||||
|
{
|
||||||
|
RecursivelyDrawTree(subFolder);
|
||||||
|
}
|
||||||
DrawMenuBar();
|
DrawMenuBar();
|
||||||
DrawCurrentFolder();
|
DrawCurrentFolder();
|
||||||
DrawAssetBeingCreated();
|
DrawAssetBeingCreated();
|
||||||
|
@ -50,6 +63,11 @@ namespace SHADE
|
||||||
refreshQueued = true;
|
refreshQueued = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::SetScrollTo(AssetID assetid)
|
||||||
|
{
|
||||||
|
assetToScrollTo = assetid;
|
||||||
|
}
|
||||||
|
|
||||||
void SHAssetBrowser::Refresh() noexcept
|
void SHAssetBrowser::Refresh() noexcept
|
||||||
{
|
{
|
||||||
SHAssetManager::RefreshDirectory();
|
SHAssetManager::RefreshDirectory();
|
||||||
|
@ -69,6 +87,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
isAssetBeingCreated = true;
|
isAssetBeingCreated = true;
|
||||||
}
|
}
|
||||||
|
DrawAssetBrowserFilter();
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,13 +100,34 @@ namespace SHADE
|
||||||
auto files = folder->files;
|
auto files = folder->files;
|
||||||
const bool isSelected = std::ranges::find(selectedFolders, folder) != selectedFolders.end();
|
const bool isSelected = std::ranges::find(selectedFolders, folder) != selectedFolders.end();
|
||||||
ImGuiTreeNodeFlags flags = (subFolders.empty() && files.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow;
|
ImGuiTreeNodeFlags flags = (subFolders.empty() && files.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow;
|
||||||
|
if(!filter.empty() && (!subFolders.empty() || !files.empty()))
|
||||||
|
{
|
||||||
|
ImGui::SetNextItemOpen(true);
|
||||||
|
}
|
||||||
if (isSelected)
|
if (isSelected)
|
||||||
flags |= ImGuiTreeNodeFlags_Selected;
|
flags |= ImGuiTreeNodeFlags_Selected;
|
||||||
if (folder == rootFolder)
|
if (folder == rootFolder)
|
||||||
flags |= ImGuiTreeNodeFlags_DefaultOpen;
|
flags |= ImGuiTreeNodeFlags_DefaultOpen;
|
||||||
|
|
||||||
bool isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data());
|
if(assetToScrollTo != 0)
|
||||||
ImGuiID folderID = ImGui::GetItemID();
|
{
|
||||||
|
if(auto asset = SHAssetManager::GetAsset(assetToScrollTo))
|
||||||
|
{
|
||||||
|
if(!asset->path.empty())
|
||||||
|
{
|
||||||
|
ImGui::SetNextItemOpen(SHStringUtilities::StringFindInsensitive(asset->path.string(), folder->name.data()) != std::string::npos);
|
||||||
|
}
|
||||||
|
else if(auto parent = SHAssetManager::GetAsset(asset->parent))
|
||||||
|
{
|
||||||
|
ImGui::SetNextItemOpen(SHStringUtilities::StringFindInsensitive(parent->path.string(), folder->name.data()) != std::string::npos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOpen = false;
|
||||||
|
if(filter.empty())
|
||||||
|
isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data());
|
||||||
|
|
||||||
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
|
||||||
//if (ImGui::BeginPopupContextItem())
|
//if (ImGui::BeginPopupContextItem())
|
||||||
|
@ -101,7 +141,7 @@ namespace SHADE
|
||||||
selectedFolders.push_back(folder);
|
selectedFolders.push_back(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOpen)
|
if (isOpen || !filter.empty())
|
||||||
{
|
{
|
||||||
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
|
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
|
||||||
const float horizontalOffset = 0.0f;
|
const float horizontalOffset = 0.0f;
|
||||||
|
@ -127,7 +167,8 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
|
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
|
||||||
|
|
||||||
ImGui::TreePop();
|
if(filter.empty())
|
||||||
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
return nodeRect;
|
return nodeRect;
|
||||||
}
|
}
|
||||||
|
@ -167,8 +208,26 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf;
|
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf;
|
||||||
static constexpr std::string_view icon = ICON_MD_FILE_PRESENT;
|
static constexpr std::string_view icon = ICON_MD_FILE_PRESENT;
|
||||||
|
bool highlighted = false;
|
||||||
|
if (!filter.empty())
|
||||||
|
{
|
||||||
|
if (SHStringUtilities::StringFindInsensitive(file.name.data(), filter) == std::string::npos)
|
||||||
|
{
|
||||||
|
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
highlighted = true;
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, highlightedColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
ImGui::PushID(file.name.data());
|
ImGui::PushID(file.name.data());
|
||||||
|
|
||||||
bool const isOpen = ImGui::TreeNodeEx(file.name.data(), flags, "%s %s%s", icon.data(), file.name.data(), file.ext.data());
|
bool const isOpen = ImGui::TreeNodeEx(file.name.data(), flags, "%s %s%s", icon.data(), file.name.data(), file.ext.data());
|
||||||
|
if(highlighted)
|
||||||
|
{
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
if(ImGui::BeginPopupContextItem())
|
if(ImGui::BeginPopupContextItem())
|
||||||
{
|
{
|
||||||
|
@ -194,6 +253,27 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if (asset == nullptr)
|
if (asset == nullptr)
|
||||||
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
|
||||||
|
if (!typeFilters[static_cast<uint64_t>(asset->type)])
|
||||||
|
{
|
||||||
|
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool highlighted = false;
|
||||||
|
if(!filter.empty())
|
||||||
|
{
|
||||||
|
ImGui::SetNextItemOpen(true);
|
||||||
|
if(SHStringUtilities::StringFindInsensitive(asset->name.data(), filter) == std::string::npos)
|
||||||
|
{
|
||||||
|
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
highlighted = true;
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, highlightedColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end();
|
const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end();
|
||||||
ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf;
|
ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf;
|
||||||
if (isSelected)
|
if (isSelected)
|
||||||
|
@ -215,7 +295,33 @@ namespace SHADE
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(assetToScrollTo != 0)
|
||||||
|
{
|
||||||
|
if(asset->id == assetToScrollTo)
|
||||||
|
{
|
||||||
|
ImGui::SetScrollHereY();
|
||||||
|
selectedAssets.clear();
|
||||||
|
selectedAssets.push_back(asset->id);
|
||||||
|
assetToScrollTo = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto const& subAsset : asset->subAssets)
|
||||||
|
{
|
||||||
|
if(subAsset->id == assetToScrollTo)
|
||||||
|
{
|
||||||
|
ImGui::SetNextItemOpen(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s%s", icon.data(), asset->name.data(), ext.data());
|
bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s%s", icon.data(), asset->name.data(), ext.data());
|
||||||
|
|
||||||
|
if(highlighted)
|
||||||
|
{
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
if (SHDragDrop::BeginSource())
|
if (SHDragDrop::BeginSource())
|
||||||
{
|
{
|
||||||
|
@ -339,4 +445,43 @@ namespace SHADE
|
||||||
// QueueRefresh();
|
// QueueRefresh();
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::DrawAssetBrowserFilter()
|
||||||
|
{
|
||||||
|
if (ImGui::InputTextWithHint("##hierarchyPanelFilter", "Filter", &filter))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
if (ImGui::Button("x"))
|
||||||
|
{
|
||||||
|
filter.clear();
|
||||||
|
}
|
||||||
|
if(ImGui::BeginMenu("Type"))
|
||||||
|
{
|
||||||
|
if (ImGui::Button("All"))
|
||||||
|
{
|
||||||
|
for (auto& [id, value] : typeFilters)
|
||||||
|
value = true;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("None"))
|
||||||
|
{
|
||||||
|
for (auto& [id, value] : typeFilters)
|
||||||
|
value = false;
|
||||||
|
}
|
||||||
|
for (auto& [id, value] : typeFilters)
|
||||||
|
{
|
||||||
|
if(ImGui::Checkbox(typeEnumAlign.value_to_name(id).data(), &value))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
if(ImGui::IsItemClicked(ImGuiMouseButton_Right))
|
||||||
|
{
|
||||||
|
for (auto& [id2, value2] : typeFilters)
|
||||||
|
value2 = false;
|
||||||
|
value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,18 +4,21 @@
|
||||||
#include "Assets/SHAsset.h"
|
#include "Assets/SHAsset.h"
|
||||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||||
#include "Filesystem/SHFolder.h"
|
#include "Filesystem/SHFolder.h"
|
||||||
|
#include <rttr/enumeration.h>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHAssetBrowser final : public SHEditorWindow
|
class SHAssetBrowser final : public SHEditorWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static constexpr ImVec4 highlightedColor = ImVec4(0.f, 0.7f, 0.0f, 1.0f);
|
||||||
SHAssetBrowser();
|
SHAssetBrowser();
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
void QueueRefresh() noexcept;
|
void QueueRefresh() noexcept;
|
||||||
|
void SetScrollTo(AssetID assetid);
|
||||||
private:
|
private:
|
||||||
void DrawMenuBar();
|
void DrawMenuBar();
|
||||||
ImRect RecursivelyDrawTree(FolderPointer folder);
|
ImRect RecursivelyDrawTree(FolderPointer folder);
|
||||||
|
@ -23,6 +26,7 @@ namespace SHADE
|
||||||
ImRect DrawFile(SHFile& file) noexcept;
|
ImRect DrawFile(SHFile& file) noexcept;
|
||||||
ImRect DrawAsset(SHAsset const* const asset, FileExt const& ext = "") noexcept;
|
ImRect DrawAsset(SHAsset const* const asset, FileExt const& ext = "") noexcept;
|
||||||
void DrawAssetBeingCreated() noexcept;
|
void DrawAssetBeingCreated() noexcept;
|
||||||
|
void DrawAssetBrowserFilter();
|
||||||
|
|
||||||
void Refresh() noexcept;
|
void Refresh() noexcept;
|
||||||
|
|
||||||
|
@ -30,9 +34,13 @@ namespace SHADE
|
||||||
std::vector<FolderPointer> selectedFolders;
|
std::vector<FolderPointer> selectedFolders;
|
||||||
std::vector<AssetID> selectedAssets;
|
std::vector<AssetID> selectedAssets;
|
||||||
static constexpr float tileWidth = 50.0f;
|
static constexpr float tileWidth = 50.0f;
|
||||||
|
static constexpr std::string_view newAssetPopup = "Create New Asset";
|
||||||
|
std::string nameOfAssetBeingCreated, filter;
|
||||||
|
rttr::enumeration typeEnumAlign = rttr::type::get<AssetType>().get_enumeration();
|
||||||
|
std::unordered_map<uint64_t, bool> typeFilters;
|
||||||
|
|
||||||
|
AssetID assetToScrollTo = 0;
|
||||||
bool refreshQueued = false;
|
bool refreshQueued = false;
|
||||||
bool isAssetBeingCreated = false;
|
bool isAssetBeingCreated = false;
|
||||||
static constexpr std::string_view newAssetPopup = "Create New Asset";
|
|
||||||
std::string nameOfAssetBeingCreated;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,9 +57,13 @@ namespace SHADE
|
||||||
skipFrame = false;
|
skipFrame = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DrawMenuBar();
|
|
||||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
|
DrawMenuBar();
|
||||||
|
if(wasFilterChanged && !filter.empty())
|
||||||
|
{
|
||||||
|
filterHighlightedEntities.clear();
|
||||||
|
filterOpenEntities.clear();
|
||||||
|
}
|
||||||
if (const auto root = sceneGraph.GetRoot())
|
if (const auto root = sceneGraph.GetRoot())
|
||||||
{
|
{
|
||||||
auto const& children = root->GetChildren();
|
auto const& children = root->GetChildren();
|
||||||
|
@ -67,7 +71,13 @@ namespace SHADE
|
||||||
for (const auto child : children)
|
for (const auto child : children)
|
||||||
{
|
{
|
||||||
if (child)
|
if (child)
|
||||||
|
{
|
||||||
|
if(wasFilterChanged && !filter.empty())
|
||||||
|
{
|
||||||
|
EntityFilterCheck(child);
|
||||||
|
}
|
||||||
RecursivelyDrawEntityNode(child);
|
RecursivelyDrawEntityNode(child);
|
||||||
|
}
|
||||||
if (skipFrame)
|
if (skipFrame)
|
||||||
{
|
{
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
@ -177,9 +187,10 @@ namespace SHADE
|
||||||
|
|
||||||
void SHHierarchyPanel::DrawHierarchyPanelFilter() noexcept
|
void SHHierarchyPanel::DrawHierarchyPanelFilter() noexcept
|
||||||
{
|
{
|
||||||
|
wasFilterChanged = false;
|
||||||
if(ImGui::InputTextWithHint("##hierarchyPanelFilter", "Filter", &filter))
|
if(ImGui::InputTextWithHint("##hierarchyPanelFilter", "Filter", &filter))
|
||||||
{
|
{
|
||||||
|
wasFilterChanged = true;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("x"))
|
if(ImGui::Button("x"))
|
||||||
|
@ -204,24 +215,65 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
result |= SHComponentManager::HasComponent<SHTransformComponent>(eid);
|
result |= SHComponentManager::HasComponent<SHTransformComponent>(eid);
|
||||||
}
|
}
|
||||||
//result |= SHStringUtilities::StringFindInsensitive(rttr::type::get<SHColliderComponent>().get_name().data(), filter) != std::string::npos;
|
if(SHStringUtilities::StringFindInsensitive(rttr::type::get<SHColliderComponent>().get_name().data(), filter) != std::string::npos)
|
||||||
//result |= SHStringUtilities::StringFindInsensitive(rttr::type::get<SHRigidBodyComponent>().get_name().data(), filter) != std::string::npos;
|
{
|
||||||
//result |= SHStringUtilities::StringFindInsensitive(rttr::type::get<SHCameraComponent>().get_name().data(), filter) != std::string::npos;
|
result |= SHComponentManager::HasComponent<SHColliderComponent>(eid);
|
||||||
//result |= SHStringUtilities::StringFindInsensitive(rttr::type::get<SHCameraArmComponent>().get_name().data(), filter) != std::string::npos;
|
}
|
||||||
//result |= SHStringUtilities::StringFindInsensitive(rttr::type::get<SHRenderable>().get_name().data(), filter) != std::string::npos;
|
if(SHStringUtilities::StringFindInsensitive(rttr::type::get<SHRigidBodyComponent>().get_name().data(), filter) != std::string::npos)
|
||||||
//result |= SHStringUtilities::StringFindInsensitive(rttr::type::get<SHLightComponent>().get_name().data(), filter) != std::string::npos;
|
{
|
||||||
//result |= SHStringUtilities::StringFindInsensitive(rttr::type::get<SHTextRenderableComponent>().get_name().data(), filter) != std::string::npos;
|
result |= SHComponentManager::HasComponent<SHRigidBodyComponent>(eid);
|
||||||
//result |= SHStringUtilities::StringFindInsensitive(rttr::type::get<SHUIComponent>().get_name().data(), filter) != std::string::npos;
|
}
|
||||||
//result |= SHStringUtilities::StringFindInsensitive(rttr::type::get<SHButtonComponent>().get_name().data(), filter) != std::string::npos;
|
if(SHStringUtilities::StringFindInsensitive(rttr::type::get<SHCameraComponent>().get_name().data(), filter) != std::string::npos)
|
||||||
//result |= SHStringUtilities::StringFindInsensitive(rttr::type::get<SHCanvasComponent>().get_name().data(), filter) != std::string::npos;
|
{
|
||||||
|
result |= SHComponentManager::HasComponent<SHCameraComponent>(eid);
|
||||||
|
}
|
||||||
|
if(SHStringUtilities::StringFindInsensitive(rttr::type::get<SHCameraArmComponent>().get_name().data(), filter) != std::string::npos)
|
||||||
|
{
|
||||||
|
result |= SHComponentManager::HasComponent<SHCameraArmComponent>(eid);
|
||||||
|
}
|
||||||
|
if(SHStringUtilities::StringFindInsensitive(rttr::type::get<SHRenderable>().get_name().data(), filter) != std::string::npos)
|
||||||
|
{
|
||||||
|
result |= SHComponentManager::HasComponent<SHRenderable>(eid);
|
||||||
|
}
|
||||||
|
if(SHStringUtilities::StringFindInsensitive(rttr::type::get<SHLightComponent>().get_name().data(), filter) != std::string::npos)
|
||||||
|
{
|
||||||
|
result |= SHComponentManager::HasComponent<SHLightComponent>(eid);
|
||||||
|
}
|
||||||
|
if(SHStringUtilities::StringFindInsensitive(rttr::type::get<SHTextRenderableComponent>().get_name().data(), filter) != std::string::npos)
|
||||||
|
{
|
||||||
|
result |= SHComponentManager::HasComponent<SHTextRenderableComponent>(eid);
|
||||||
|
}
|
||||||
|
if(SHStringUtilities::StringFindInsensitive(rttr::type::get<SHUIComponent>().get_name().data(), filter) != std::string::npos)
|
||||||
|
{
|
||||||
|
result |= SHComponentManager::HasComponent<SHUIComponent>(eid);
|
||||||
|
}
|
||||||
|
if(SHStringUtilities::StringFindInsensitive(rttr::type::get<SHButtonComponent>().get_name().data(), filter) != std::string::npos)
|
||||||
|
{
|
||||||
|
result |= SHComponentManager::HasComponent<SHButtonComponent>(eid);
|
||||||
|
}
|
||||||
|
if(SHStringUtilities::StringFindInsensitive(rttr::type::get<SHCanvasComponent>().get_name().data(), filter) != std::string::npos)
|
||||||
|
{
|
||||||
|
result |= SHComponentManager::HasComponent<SHCanvasComponent>(eid);
|
||||||
|
}
|
||||||
|
|
||||||
//std::vector<SHSceneNode*> const& children = entityNode->GetChildren();
|
if(result)
|
||||||
|
{
|
||||||
|
filterHighlightedEntities.push_back(eid);
|
||||||
|
}
|
||||||
|
|
||||||
//for (auto const& child : children)
|
std::vector<SHSceneNode*> const& children = entityNode->GetChildren();
|
||||||
//{
|
|
||||||
// result |= EntityFilterCheck(child);
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
bool open = false;
|
||||||
|
for (auto const& child : children)
|
||||||
|
{
|
||||||
|
open |= EntityFilterCheck(child);
|
||||||
|
}
|
||||||
|
result |= open;
|
||||||
|
|
||||||
|
if(open)
|
||||||
|
{
|
||||||
|
filterOpenEntities.push_back(eid);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,31 +297,27 @@ namespace SHADE
|
||||||
|
|
||||||
const bool isSelected = (std::ranges::find(editor->selectedEntities, eid) != editor->selectedEntities.end());
|
const bool isSelected = (std::ranges::find(editor->selectedEntities, eid) != editor->selectedEntities.end());
|
||||||
|
|
||||||
bool highlighted = false;
|
bool highlighted = false, open = false;
|
||||||
//if(!filter.empty())
|
if(!filter.empty())
|
||||||
//{
|
{
|
||||||
// highlighted = EntityFilterCheck(currentNode);
|
highlighted = (std::ranges::find(filterHighlightedEntities, eid) != filterHighlightedEntities.end());
|
||||||
// if (highlighted)
|
if(open = std::ranges::find(filterOpenEntities, eid) != filterOpenEntities.end())
|
||||||
// {
|
{
|
||||||
// ImGui::PushStyleColor(ImGuiCol_Text, highlightedColor);
|
ImGui::SetNextItemOpen(true);
|
||||||
//
|
}
|
||||||
// ImGui::SetNextItemOpen(true);
|
|
||||||
//
|
if(!open && !highlighted)
|
||||||
//
|
{
|
||||||
// }
|
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
// else
|
}
|
||||||
// {
|
ImGui::PushStyleColor(ImGuiCol_Text, highlighted ? highlightedColor : ImVec4(0.5f, 0.5f, 0.5f, 1.f ));
|
||||||
//
|
}
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
const ImGuiTreeNodeFlags nodeFlags = ((isSelected) ? ImGuiTreeNodeFlags_Selected : 0) | ((children.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow);
|
const ImGuiTreeNodeFlags nodeFlags = ((isSelected) ? ImGuiTreeNodeFlags_Selected : 0) | ((children.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow);
|
||||||
|
|
||||||
|
|
||||||
//Draw Node
|
//Draw Node
|
||||||
bool isNodeOpen = ImGui::TreeNodeEx(reinterpret_cast<void*>(eid), nodeFlags, "%u: %s", SHEntityManager::GetEntityIndex(eid), entity->name.c_str());
|
bool isNodeOpen = ImGui::TreeNodeEx(reinterpret_cast<void*>(eid), nodeFlags, "%u: %s", SHEntityManager::GetEntityIndex(eid), entity->name.c_str());
|
||||||
|
|
||||||
if (highlighted)
|
if(!filter.empty())
|
||||||
{
|
{
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHSceneNode;
|
class SHSceneNode;
|
||||||
constexpr ImVec4 highlightedColor = ImVec4(0.f, 0.7f, 0.0f, 1.0f);
|
|
||||||
|
|
||||||
class SHHierarchyPanel final : public SHEditorWindow
|
class SHHierarchyPanel final : public SHEditorWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static constexpr ImVec4 highlightedColor = ImVec4(0.f, 0.7f, 0.0f, 1.0f);
|
||||||
SHHierarchyPanel();
|
SHHierarchyPanel();
|
||||||
void Init() override;
|
void Init() override;
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
@ -44,7 +44,8 @@ namespace SHADE
|
||||||
std::string filter;
|
std::string filter;
|
||||||
bool isAnyNodeSelected = false;
|
bool isAnyNodeSelected = false;
|
||||||
EntityID scrollTo = MAX_EID;
|
EntityID scrollTo = MAX_EID;
|
||||||
std::vector<EntityID> draggingEntities;
|
std::vector<EntityID> draggingEntities, filterOpenEntities, filterHighlightedEntities;
|
||||||
|
bool wasFilterChanged = false;
|
||||||
|
|
||||||
};//class SHHierarchyPanel
|
};//class SHHierarchyPanel
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,546 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHInputBindingsPanel.h"
|
||||||
|
#include "Input/SHInputManager.h"
|
||||||
|
#include "Editor/SHEditorWidgets.hpp"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
//Vectors containing data for elements for different bindings
|
||||||
|
static std::vector<std::string> bindingRenames;
|
||||||
|
|
||||||
|
//Flags to prevent unwanted editing of bindings
|
||||||
|
static size_t positiveKeyListeningFor;
|
||||||
|
static bool positiveKeyListening;
|
||||||
|
|
||||||
|
static size_t negativeKeyListeningFor;
|
||||||
|
static bool negativeKeyListening;
|
||||||
|
|
||||||
|
static size_t positiveControllerListeningFor;
|
||||||
|
static bool positiveControllerListening;
|
||||||
|
|
||||||
|
static size_t negativeControllerListeningFor;
|
||||||
|
static bool negativeControllerListening;
|
||||||
|
|
||||||
|
//Internal Helper function
|
||||||
|
void resizeVectors(size_t newSize)
|
||||||
|
{
|
||||||
|
bindingRenames.resize(newSize);
|
||||||
|
for (auto& s : bindingRenames)
|
||||||
|
s.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Internal Helper function
|
||||||
|
std::string labelConcat(char const* label, size_t entryNumber)
|
||||||
|
{
|
||||||
|
std::string concat = label;
|
||||||
|
concat += std::to_string(entryNumber);
|
||||||
|
return concat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHInputBindingsPanel::Init()
|
||||||
|
{
|
||||||
|
SHEditorWindow::Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHInputBindingsPanel::Update()
|
||||||
|
{
|
||||||
|
if (SHEditorWindow::Begin())
|
||||||
|
{
|
||||||
|
//ImGui::ShowDemoWindow();
|
||||||
|
|
||||||
|
//Binding count
|
||||||
|
ImGui::Text("Binding Count: %d", SHInputManager::CountBindings());
|
||||||
|
|
||||||
|
//Binding file name
|
||||||
|
static std::string bindingFileName;
|
||||||
|
ImGui::InputText("Binding File Path", &bindingFileName);
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(".SHConfig will be appeneded to file name");
|
||||||
|
ImGui::Text("If no name is provided, saves to or loads from \"Assets/Bindings.SHConfig\"");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Save bindings to...
|
||||||
|
if (ImGui::Button("Save Bindings"))
|
||||||
|
{
|
||||||
|
if (bindingFileName.empty())
|
||||||
|
{
|
||||||
|
SHInputManager::SaveBindings();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string filePath = std::string(ASSET_ROOT);
|
||||||
|
filePath += "/";
|
||||||
|
filePath += bindingFileName;
|
||||||
|
filePath += ".SHConfig";
|
||||||
|
SHInputManager::SaveBindings(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load bindings from...
|
||||||
|
if (ImGui::Button("Load Bindings"))
|
||||||
|
{
|
||||||
|
if (bindingFileName.empty())
|
||||||
|
{
|
||||||
|
SHInputManager::LoadBindings();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string filePath = std::string(ASSET_ROOT);
|
||||||
|
filePath += "/";
|
||||||
|
filePath += bindingFileName;
|
||||||
|
filePath += ".SHConfig";
|
||||||
|
SHInputManager::LoadBindings(filePath);
|
||||||
|
}
|
||||||
|
resizeVectors(SHInputManager::CountBindings());
|
||||||
|
}
|
||||||
|
|
||||||
|
//Button to add new binding
|
||||||
|
if (ImGui::Button("Add New Binding"))
|
||||||
|
{
|
||||||
|
std::string newBindingName = "Binding" + std::to_string(SHInputManager::CountBindings());
|
||||||
|
SHInputManager::AddBinding(newBindingName);
|
||||||
|
resizeVectors(SHInputManager::CountBindings());
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Add a new binding to the list");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Ensure unique label for entries
|
||||||
|
size_t entryNumber = 0;
|
||||||
|
|
||||||
|
//Listing for each binding
|
||||||
|
for (auto& binding : SHInputManager::GetBindings())
|
||||||
|
{
|
||||||
|
if (ImGui::CollapsingHeader(binding.first.c_str()))
|
||||||
|
{
|
||||||
|
//Modifiable binding name
|
||||||
|
ImGui::Text("Binding Name: %s", binding.first.c_str());
|
||||||
|
ImGui::InputText(labelConcat("##bindingModifyName", entryNumber).c_str(), &bindingRenames[entryNumber]);
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button(labelConcat("Rename##bindingRename", entryNumber).c_str()))
|
||||||
|
{
|
||||||
|
SHInputManager::RenameBinding(binding.first, bindingRenames[entryNumber]);
|
||||||
|
bindingRenames[entryNumber].clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::Button(labelConcat("Delete Binding##", entryNumber).c_str()))
|
||||||
|
{
|
||||||
|
SHInputManager::RemoveBinding(binding.first);
|
||||||
|
resizeVectors(SHInputManager::CountBindings());
|
||||||
|
ImGui::End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Delete this binding from the list");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Binding value test
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
float val = SHInputManager::GetBindingAxis(binding.first);
|
||||||
|
ImGui::SliderFloat(labelConcat("Value##", entryNumber).c_str(), &val, -1.0f, 1.0f);
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Test the current value of the binding");
|
||||||
|
ImGui::Text("For mouse movement/wheel inputs, will be multiplied by Sensitivity, with 0 being neutral (no input detected)");
|
||||||
|
ImGui::Text("Between -1 and 1 for other inputs, with 0 still being neutral (no input detected)");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
float rawVal = SHInputManager::GetBindingAxisRaw(binding.first);
|
||||||
|
ImGui::SliderFloat(labelConcat("Raw Value##", entryNumber).c_str(), &rawVal, -1.0f, 1.0f);
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Test the current value of the binding");
|
||||||
|
ImGui::Text("Raw value means it will be fixed among -1, 0 and 1 for non-mouse movement/wheel inputs");
|
||||||
|
ImGui::Text("No difference between this and Value for mouse movement/wheel inputs");
|
||||||
|
ImGui::Text("But for other inputs, does not consider smoothing options such as gravity and sensitivity");
|
||||||
|
ImGui::Text("If both positive and negative input is detected, returns neutral 0");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Binding Type Combo Box
|
||||||
|
int bindingType = static_cast<int>(SHInputManager::GetBindingType(binding.first));
|
||||||
|
if (ImGui::Combo(labelConcat("Input Type##", entryNumber).c_str(), &bindingType, "Keyboard / Mouse Buttons / Controller\0Mouse Horizontal\0Mouse Vertical\0Mouse Scroll Wheel"))
|
||||||
|
SHInputManager::SetBindingType(binding.first, static_cast<SHInputManager::SH_BINDINGTYPE>(bindingType));
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Which of the four types the binding uses");
|
||||||
|
ImGui::Text("Keyboard / Mouse Buttons / Controller = Keys, mouse buttons and ALL controller inputs");
|
||||||
|
ImGui::Text("Mouse Horizontal = Horizontal movement of the mouse");
|
||||||
|
ImGui::Text("Mouse Vertical = Vertical movement of the mouse");
|
||||||
|
ImGui::Text("Mouse Scroll Wheel = The scroll wheel found at the middle of most mouses");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Inversion
|
||||||
|
bool bindingInvert = SHInputManager::GetBindingInverted(binding.first);
|
||||||
|
if (ImGui::Checkbox(labelConcat("Inverted##", entryNumber).c_str(), &bindingInvert))
|
||||||
|
SHInputManager::SetBindingInverted(binding.first, bindingInvert);
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("If inverted:");
|
||||||
|
ImGui::Text("Positive inputs mean negative value of the binding");
|
||||||
|
ImGui::Text("Negative inputs mean positive value of the binding");
|
||||||
|
ImGui::Text("Mouse moving up / right means negative value of the binding");
|
||||||
|
ImGui::Text("Scrolling the mouse wheel up means negative value of the binding");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Sensitivity
|
||||||
|
double bindingSensitivity = SHInputManager::GetBindingSensitivity(binding.first);
|
||||||
|
if (ImGui::InputDouble(labelConcat("Sensitivity##", entryNumber).c_str(), &bindingSensitivity))
|
||||||
|
SHInputManager::SetBindingSensitivity(binding.first, bindingSensitivity);
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Value multiplier for mouse movement and scrolling");
|
||||||
|
ImGui::Text("For other digital inputs, serves as a rate of how fast axis value goes to maximum positive/negative");
|
||||||
|
//ImGui::Text("For other analog inputs, serves as a multiplier, but axis value magnitude will still be capped at 1");
|
||||||
|
ImGui::Text("Irrelevant for other analog inputs");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Below this section is only for KB/M type bindings
|
||||||
|
//Not relevant for mouse movement and scrolling
|
||||||
|
if (SHInputManager::GetBindingType(binding.first) == SHInputManager::SH_BINDINGTYPE::KB_MB_CONTROLLER)
|
||||||
|
{
|
||||||
|
//Dead
|
||||||
|
float bindingDead = static_cast<float>(SHInputManager::GetBindingDead(binding.first));
|
||||||
|
if (ImGui::SliderFloat(labelConcat("Deadzone##", entryNumber).c_str(), &bindingDead, 0.0f, 1.0f))
|
||||||
|
SHInputManager::SetBindingDead(binding.first, static_cast<double>(bindingDead));
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Any positive or negative analog input with magnitude less than this will be registered as neutral");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Gravity
|
||||||
|
double bindingGravity = SHInputManager::GetBindingGravity(binding.first);
|
||||||
|
if (ImGui::InputDouble(labelConcat("Gravity##", entryNumber).c_str(), &bindingGravity))
|
||||||
|
SHInputManager::SetBindingGravity(binding.first, static_cast<double>(bindingGravity));
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("The rate at which the value moves to neutral if no input in the direction is read");
|
||||||
|
ImGui::TextColored(ImVec4{ 1.0f, 0.5f, 0.5f, 1.0f }, "Should be non-negative");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Snap
|
||||||
|
bool bindingSnap = SHInputManager::GetBindingSnap(binding.first);
|
||||||
|
if (ImGui::Checkbox(labelConcat("Snap##", entryNumber).c_str(), &bindingSnap))
|
||||||
|
SHInputManager::SetBindingSnap(binding.first, bindingSnap);
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("If no other input on the axis is present and a input is made in the opposite direction of the current value,");
|
||||||
|
ImGui::Text("the binding's value will jump to neutral 0 before resuming in the input direction");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t keycodeIndex = 0;
|
||||||
|
//Positive key codes
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Text("Positive Key Codes:");
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("When this keyboard or mouse button is held, causes the value to go positive, or negative when inverted");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
//Button to ask for inputs
|
||||||
|
if (!positiveKeyListening)
|
||||||
|
{
|
||||||
|
if (ImGui::Button(labelConcat("New##positiveKeyCode", entryNumber).c_str()))
|
||||||
|
{
|
||||||
|
positiveKeyListening = true;
|
||||||
|
positiveKeyListeningFor = entryNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (positiveKeyListeningFor == entryNumber)
|
||||||
|
{
|
||||||
|
//Listening for inputs
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.4f, 0.4f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 0.5f, 0.5f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.6f, 0.3f, 0.3f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
|
ImGui::Button(labelConcat("PRESS##positiveKeyCode", entryNumber).c_str());
|
||||||
|
ImGui::PopStyleColor(4);
|
||||||
|
|
||||||
|
SHInputManager::SH_KEYCODE k;
|
||||||
|
if (SHInputManager::AnyKey(&k))
|
||||||
|
{
|
||||||
|
positiveKeyListening = false;
|
||||||
|
SHInputManager::AddBindingPositiveKeyCode(binding.first, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Not listening
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::Button(labelConcat("New##positiveKeyCode", entryNumber).c_str());
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//List and remove bindings
|
||||||
|
ImGui::Indent();
|
||||||
|
keycodeIndex = 0;
|
||||||
|
for (auto& k : binding.second.positiveKeyCodes)
|
||||||
|
{
|
||||||
|
//ImGui::Text("%d", static_cast<int>(k));
|
||||||
|
ImGui::Text(SHInputManager::GetKeyCodeName(k).c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
|
std::string labelString = "X##KeyPositive";
|
||||||
|
labelString += binding.first;
|
||||||
|
|
||||||
|
//Delete button
|
||||||
|
if (ImGui::SmallButton(labelConcat(labelString.c_str(), keycodeIndex).c_str()))
|
||||||
|
{
|
||||||
|
SHInputManager::RemoveBindingPositiveKeyCode(binding.first, k);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++keycodeIndex;
|
||||||
|
}
|
||||||
|
ImGui::Unindent();
|
||||||
|
|
||||||
|
|
||||||
|
//Negative key codes
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Text("Negative Key Codes:");
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("When this keyboard or mouse button is held, causes the value to go negative, or positive when inverted");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
//Button to ask for inputs
|
||||||
|
if (!negativeKeyListening)
|
||||||
|
{
|
||||||
|
if (ImGui::Button(labelConcat("New##negativeKeyCode", entryNumber).c_str()))
|
||||||
|
{
|
||||||
|
negativeKeyListening = true;
|
||||||
|
negativeKeyListeningFor = entryNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (negativeKeyListeningFor == entryNumber)
|
||||||
|
{
|
||||||
|
//Listening for inputs
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.4f, 0.4f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 0.5f, 0.5f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.6f, 0.3f, 0.3f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
|
ImGui::Button(labelConcat("PRESS##negativeKeyCode", entryNumber).c_str());
|
||||||
|
ImGui::PopStyleColor(4);
|
||||||
|
|
||||||
|
SHInputManager::SH_KEYCODE k;
|
||||||
|
if (SHInputManager::AnyKey(&k))
|
||||||
|
{
|
||||||
|
negativeKeyListening = false;
|
||||||
|
SHInputManager::AddBindingNegativeKeyCode(binding.first, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Not listening
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::Button(labelConcat("New##negativeKeyCode", entryNumber).c_str());
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//List and remove bindings
|
||||||
|
ImGui::Indent();
|
||||||
|
keycodeIndex = 0;
|
||||||
|
for (auto& k : binding.second.negativeKeyCodes)
|
||||||
|
{
|
||||||
|
//ImGui::Text("%d", static_cast<int>(k));
|
||||||
|
ImGui::Text(SHInputManager::GetKeyCodeName(k).c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
|
std::string labelString = "X##KeyNegative";
|
||||||
|
labelString += binding.first;
|
||||||
|
|
||||||
|
//Delete button
|
||||||
|
if (ImGui::SmallButton(labelConcat(labelString.c_str(), keycodeIndex).c_str()))
|
||||||
|
{
|
||||||
|
SHInputManager::RemoveBindingNegativeKeyCode(binding.first, k);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++keycodeIndex;
|
||||||
|
}
|
||||||
|
ImGui::Unindent();
|
||||||
|
|
||||||
|
//Positive controller codes
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Text("Positive Controller Codes:");
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("When this controller button is held, causes the value to go positive, or negative when inverted");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
//Button to ask for inputs
|
||||||
|
if (!positiveControllerListening)
|
||||||
|
{
|
||||||
|
if (ImGui::Button(labelConcat("New##positiveControllerCode", entryNumber).c_str()))
|
||||||
|
{
|
||||||
|
positiveControllerListening = true;
|
||||||
|
positiveControllerListeningFor = entryNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (positiveControllerListeningFor == entryNumber)
|
||||||
|
{
|
||||||
|
//Listening for inputs
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.4f, 0.4f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 0.5f, 0.5f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.6f, 0.3f, 0.3f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
|
ImGui::Button(labelConcat("PRESS##positiveControllerCode", entryNumber).c_str());
|
||||||
|
ImGui::PopStyleColor(4);
|
||||||
|
|
||||||
|
SHInputManager::SH_CONTROLLERCODE c;
|
||||||
|
if (SHInputManager::AnyControllerInput(&c))
|
||||||
|
{
|
||||||
|
positiveControllerListening = false;
|
||||||
|
SHInputManager::AddBindingPositiveControllerCode(binding.first, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Not listening
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::Button(labelConcat("New##positiveControllerCode", entryNumber).c_str());
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//List and remove bindings
|
||||||
|
ImGui::Indent();
|
||||||
|
keycodeIndex = 0;
|
||||||
|
for (auto& c : binding.second.positiveControllerCodes)
|
||||||
|
{
|
||||||
|
//ImGui::Text("%d", static_cast<int>(k));
|
||||||
|
ImGui::Text(SHInputManager::GetControllerCodeName(c).c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
|
std::string labelString = "X##ControllerPositive";
|
||||||
|
labelString += binding.first;
|
||||||
|
|
||||||
|
//Delete button
|
||||||
|
if (ImGui::SmallButton(labelConcat(labelString.c_str(), keycodeIndex).c_str()))
|
||||||
|
{
|
||||||
|
SHInputManager::RemoveBindingPositiveControllerCode(binding.first, c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++keycodeIndex;
|
||||||
|
}
|
||||||
|
ImGui::Unindent();
|
||||||
|
|
||||||
|
//Negative controller codes
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Text("Negative Controller Codes:");
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("When this controller button is pressed, causes the value to go negative, or positive when inverted");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
//Button to ask for inputs
|
||||||
|
if (!negativeControllerListening)
|
||||||
|
{
|
||||||
|
if (ImGui::Button(labelConcat("New##negativeControllerCode", entryNumber).c_str()))
|
||||||
|
{
|
||||||
|
negativeControllerListening = true;
|
||||||
|
negativeControllerListeningFor = entryNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (negativeControllerListeningFor == entryNumber)
|
||||||
|
{
|
||||||
|
//Listening for inputs
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.4f, 0.4f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 0.5f, 0.5f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.6f, 0.3f, 0.3f, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
|
ImGui::Button(labelConcat("PRESS##negativeControllerCode", entryNumber).c_str());
|
||||||
|
ImGui::PopStyleColor(4);
|
||||||
|
|
||||||
|
SHInputManager::SH_CONTROLLERCODE c;
|
||||||
|
if (SHInputManager::AnyControllerInput(&c))
|
||||||
|
{
|
||||||
|
negativeControllerListening = false;
|
||||||
|
SHInputManager::AddBindingNegativeControllerCode(binding.first, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Not listening
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::Button(labelConcat("New##negativeControllerCode", entryNumber).c_str());
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//List and remove bindings
|
||||||
|
ImGui::Indent();
|
||||||
|
keycodeIndex = 0;
|
||||||
|
for (auto& c : binding.second.negativeControllerCodes)
|
||||||
|
{
|
||||||
|
//ImGui::Text("%d", static_cast<int>(k));
|
||||||
|
ImGui::Text(SHInputManager::GetControllerCodeName(c).c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
|
std::string labelString = "X##ControllerNegative";
|
||||||
|
labelString += binding.first;
|
||||||
|
|
||||||
|
//Delete button
|
||||||
|
if (ImGui::SmallButton(labelConcat(labelString.c_str(), keycodeIndex).c_str()))
|
||||||
|
{
|
||||||
|
SHInputManager::RemoveBindingNegativeControllerCode(binding.first, c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++keycodeIndex;
|
||||||
|
}
|
||||||
|
ImGui::Unindent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++entryNumber; //Next entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHInputBindingsPanel::Exit()
|
||||||
|
{
|
||||||
|
SHEditorWindow::Exit();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SH_API SHInputBindingsPanel final : public SHEditorWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SHInputBindingsPanel() : SHEditorWindow("Input Bindings Panel", ImGuiWindowFlags_MenuBar) {}
|
||||||
|
|
||||||
|
void Init() override;
|
||||||
|
void Update() override;
|
||||||
|
void Exit() override;
|
||||||
|
};
|
||||||
|
}
|
|
@ -22,6 +22,10 @@
|
||||||
#include "Serialization/SHSerializationHelper.hpp"
|
#include "Serialization/SHSerializationHelper.hpp"
|
||||||
#include "Tools/Utilities/SHClipboardUtilities.h"
|
#include "Tools/Utilities/SHClipboardUtilities.h"
|
||||||
#include "SHInspectorCommands.h"
|
#include "SHInspectorCommands.h"
|
||||||
|
#include "Physics/Collision/SHCollisionTagMatrix.h"
|
||||||
|
#include "Animation/SHAnimatorComponent.h"
|
||||||
|
#include "../SHEditorWindowManager.h"
|
||||||
|
#include "../AssetBrowser/SHAssetBrowser.h"
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -500,6 +504,15 @@ namespace SHADE
|
||||||
SHResourceManager::FinaliseChanges();
|
SHResourceManager::FinaliseChanges();
|
||||||
}, SHDragDrop::DRAG_RESOURCE);
|
}, SHDragDrop::DRAG_RESOURCE);
|
||||||
|
|
||||||
|
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
if(Handle<SHMesh> const& mesh = component->GetMesh())
|
||||||
|
{
|
||||||
|
AssetID assetID = SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0);
|
||||||
|
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const auto MAT_NAME = mat ? SHResourceManager::GetAssetName<SHMaterial>(mat->GetBaseMaterial()).value_or("") : "";
|
const auto MAT_NAME = mat ? SHResourceManager::GetAssetName<SHMaterial>(mat->GetBaseMaterial()).value_or("") : "";
|
||||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Material", MAT_NAME,
|
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Material", MAT_NAME,
|
||||||
[component]()
|
[component]()
|
||||||
|
@ -519,6 +532,15 @@ namespace SHADE
|
||||||
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||||
component->SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(SHResourceManager::LoadOrGet<SHMaterial>(id)));
|
component->SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(SHResourceManager::LoadOrGet<SHMaterial>(id)));
|
||||||
}, SHDragDrop::DRAG_RESOURCE);
|
}, SHDragDrop::DRAG_RESOURCE);
|
||||||
|
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
if(Handle<SHMaterialInstance> const& mat = component->GetMaterial())
|
||||||
|
{
|
||||||
|
AssetID assetID = SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0);
|
||||||
|
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -556,7 +578,14 @@ namespace SHADE
|
||||||
component->SetFont(SHResourceManager::LoadOrGet<SHFont>(id));
|
component->SetFont(SHResourceManager::LoadOrGet<SHFont>(id));
|
||||||
SHResourceManager::FinaliseChanges();
|
SHResourceManager::FinaliseChanges();
|
||||||
}, SHDragDrop::DRAG_RESOURCE);
|
}, SHDragDrop::DRAG_RESOURCE);
|
||||||
|
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
if (Handle<SHFont> const& font = component->GetFont())
|
||||||
|
{
|
||||||
|
AssetID assetID = SHResourceManager::GetAssetID<SHFont>(font).value_or(0);
|
||||||
|
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||||
|
}
|
||||||
|
}
|
||||||
SHEditorWidgets::InputText("Text",
|
SHEditorWidgets::InputText("Text",
|
||||||
[component](void)
|
[component](void)
|
||||||
{
|
{
|
||||||
|
@ -574,4 +603,75 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
static void DrawComponent(SHAnimatorComponent* component)
|
||||||
|
{
|
||||||
|
if (!component)
|
||||||
|
return;
|
||||||
|
ImGui::PushID(SHFamilyID<SHComponent>::GetID<SHAnimatorComponent>());
|
||||||
|
const auto componentType = rttr::type::get(*component);
|
||||||
|
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
||||||
|
{
|
||||||
|
DrawContextMenu(component);
|
||||||
|
Handle<SHRig> const& rig = component->GetRig();
|
||||||
|
const auto RIG_NAME = rig ? SHResourceManager::GetAssetName<SHRig>(rig).value_or("") : "";
|
||||||
|
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Rig", RIG_NAME, [component]()
|
||||||
|
{
|
||||||
|
Handle<SHRig> const& rig = component->GetRig();
|
||||||
|
return SHResourceManager::GetAssetID<SHRig>(rig).value_or(0);
|
||||||
|
},
|
||||||
|
[component](AssetID const& id)
|
||||||
|
{
|
||||||
|
if (SHAssetManager::GetType(id) != AssetType::MODEL)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
component->SetRig(SHResourceManager::LoadOrGet<SHRig>(id));
|
||||||
|
SHResourceManager::FinaliseChanges();
|
||||||
|
}, SHDragDrop::DRAG_RESOURCE);
|
||||||
|
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
if (Handle<SHRig> const& rig = component->GetRig())
|
||||||
|
{
|
||||||
|
AssetID assetID = SHResourceManager::GetAssetID<SHRig>(rig).value_or(0);
|
||||||
|
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Handle<SHAnimationClip> const& clip = component->GetCurrentClip();
|
||||||
|
const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName<SHAnimationClip>(clip).value_or("") : "";
|
||||||
|
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME,
|
||||||
|
[component]()
|
||||||
|
{
|
||||||
|
Handle<SHAnimationClip> const& clip = component->GetCurrentClip();
|
||||||
|
return SHResourceManager::GetAssetID<SHAnimationClip>(clip).value_or(0);
|
||||||
|
},
|
||||||
|
[component](AssetID const& id)
|
||||||
|
{
|
||||||
|
if (SHAssetManager::GetType(id) != AssetType::MODEL)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
component->SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(id));
|
||||||
|
}, SHDragDrop::DRAG_RESOURCE);
|
||||||
|
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
if (Handle<SHAnimationClip> const& clip = component->GetCurrentClip())
|
||||||
|
{
|
||||||
|
AssetID assetID = SHResourceManager::GetAssetID<SHAnimationClip>(clip).value_or(0);
|
||||||
|
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawContextMenu(component);
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,13 @@
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
template<typename Component>
|
||||||
|
void EnsureComponent(EntityID eid)
|
||||||
|
{
|
||||||
|
if(SHComponentManager::GetComponent_s<Component>(eid) == nullptr)
|
||||||
|
SHComponentManager::AddComponent<Component>(eid);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
bool DrawAddComponentButton(EntityID const& eid)
|
bool DrawAddComponentButton(EntityID const& eid)
|
||||||
{
|
{
|
||||||
|
@ -49,9 +56,13 @@ namespace SHADE
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ComponentType, typename EnforcedComponent, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true, std::enable_if_t<std::is_base_of_v<SHComponent, EnforcedComponent>, bool> = true>
|
template <typename ComponentType, typename ... EnforcedComponents>
|
||||||
bool DrawAddComponentWithEnforcedComponentButton(EntityID const& eid)
|
bool DrawAddComponentWithEnforcedComponentButton(EntityID const& eid)
|
||||||
{
|
{
|
||||||
|
// Only make sure components are passed here
|
||||||
|
static_assert(std::is_base_of_v<SHComponent, ComponentType>, "");
|
||||||
|
//(static_assert(std::is_base_of_v<SHComponent, EnforcedComponents>, ""), ...);
|
||||||
|
|
||||||
bool selected = false;
|
bool selected = false;
|
||||||
if (!SHComponentManager::HasComponent<ComponentType>(eid))
|
if (!SHComponentManager::HasComponent<ComponentType>(eid))
|
||||||
{
|
{
|
||||||
|
@ -59,9 +70,8 @@ namespace SHADE
|
||||||
|
|
||||||
if(selected = ImGui::Selectable(std::format("Add {}", componentName).data()); selected)
|
if(selected = ImGui::Selectable(std::format("Add {}", componentName).data()); selected)
|
||||||
{
|
{
|
||||||
if(SHComponentManager::GetComponent_s<EnforcedComponent>(eid) == nullptr)
|
// Ensure that all required components are present
|
||||||
SHComponentManager::AddComponent<EnforcedComponent>(eid);
|
(EnsureComponent<EnforcedComponents>(eid), ...);
|
||||||
|
|
||||||
SHComponentManager::AddComponent<ComponentType>(eid);
|
SHComponentManager::AddComponent<ComponentType>(eid);
|
||||||
}
|
}
|
||||||
if(ImGui::IsItemHovered())
|
if(ImGui::IsItemHovered())
|
||||||
|
@ -70,9 +80,8 @@ namespace SHADE
|
||||||
ImGui::Text("Adds", componentName); ImGui::SameLine();
|
ImGui::Text("Adds", componentName); ImGui::SameLine();
|
||||||
ImGui::TextColored(ImGuiColors::green, "%s", componentName); ImGui::SameLine();
|
ImGui::TextColored(ImGuiColors::green, "%s", componentName); ImGui::SameLine();
|
||||||
ImGui::Text("to this entity", componentName);
|
ImGui::Text("to this entity", componentName);
|
||||||
ImGui::Text("Adds"); ImGui::SameLine();
|
ImGui::Text("Adds the following components if the entity does not already have it: ");
|
||||||
ImGui::TextColored(ImGuiColors::red, "%s", rttr::type::get<EnforcedComponent>().get_name().data()); ImGui::SameLine();
|
(ImGui::TextColored(ImGuiColors::red, "%s", rttr::type::get<EnforcedComponents>().get_name().data()), ...);
|
||||||
ImGui::Text("if the entity does not already have it");
|
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,6 +127,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
DrawComponent(renderableComponent);
|
DrawComponent(renderableComponent);
|
||||||
}
|
}
|
||||||
|
if (auto animatorComponent = SHComponentManager::GetComponent_s<SHAnimatorComponent>(eid))
|
||||||
|
{
|
||||||
|
DrawComponent(animatorComponent);
|
||||||
|
}
|
||||||
if(auto colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(eid))
|
if(auto colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(eid))
|
||||||
{
|
{
|
||||||
DrawComponent(colliderComponent);
|
DrawComponent(colliderComponent);
|
||||||
|
@ -179,6 +192,7 @@ namespace SHADE
|
||||||
DrawAddComponentWithEnforcedComponentButton<SHRigidBodyComponent, SHTransformComponent>(eid);
|
DrawAddComponentWithEnforcedComponentButton<SHRigidBodyComponent, SHTransformComponent>(eid);
|
||||||
DrawAddComponentWithEnforcedComponentButton<SHColliderComponent, SHTransformComponent>(eid);
|
DrawAddComponentWithEnforcedComponentButton<SHColliderComponent, SHTransformComponent>(eid);
|
||||||
DrawAddComponentWithEnforcedComponentButton<SHTextRenderableComponent, SHTransformComponent>(eid);
|
DrawAddComponentWithEnforcedComponentButton<SHTextRenderableComponent, SHTransformComponent>(eid);
|
||||||
|
DrawAddComponentWithEnforcedComponentButton<SHAnimatorComponent, SHTransformComponent, SHRenderable>(eid);
|
||||||
|
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "Serialization/SHSerializationHelper.hpp"
|
#include "Serialization/SHSerializationHelper.hpp"
|
||||||
#include "SHMaterialInspector.h"
|
#include "SHMaterialInspector.h"
|
||||||
#include "Editor/SHImGuiHelpers.hpp"
|
#include "Editor/SHImGuiHelpers.hpp"
|
||||||
#include <imgui.h>
|
|
||||||
|
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
#include "Editor/IconsMaterialDesign.h"
|
#include "Editor/IconsMaterialDesign.h"
|
||||||
|
@ -89,11 +92,17 @@ namespace SHADE
|
||||||
if (vertShader && fragShader && gfxSystem)
|
if (vertShader && fragShader && gfxSystem)
|
||||||
{
|
{
|
||||||
// - Retrieve pipeline from pipeline library
|
// - Retrieve pipeline from pipeline library
|
||||||
auto renderPass = gfxSystem->GetPrimaryRenderpass();
|
auto subPass = gfxSystem->GetUsableSubpass(currentMatSpec->subpassName);
|
||||||
auto subPass = renderPass->GetSubpass(currentMatSpec->subpassName);
|
if (subPass)
|
||||||
auto pipeline = renderPass->GetOrCreatePipeline({ vertShader, fragShader }, subPass);
|
{
|
||||||
// - Set Pipeline
|
// Set Pipeline if valid
|
||||||
matHandle->SetPipeline(pipeline);
|
auto pipeline = subPass->GetParentNode()->GetOrCreatePipeline({vertShader, fragShader}, subPass);
|
||||||
|
matHandle->SetPipeline(pipeline);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("[SHMaterialInspector] Failed to find material subpass of type \"{}\"", currentMatSpec->subpassName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +185,7 @@ namespace SHADE
|
||||||
const std::string VERT_SHADER_NAME = VERT_SHADER_INFO ? VERT_SHADER_INFO->name : "Unknown Shader";
|
const std::string VERT_SHADER_NAME = VERT_SHADER_INFO ? VERT_SHADER_INFO->name : "Unknown Shader";
|
||||||
isDirty |= SHEditorWidgets::DragDropReadOnlyField<AssetID>
|
isDirty |= SHEditorWidgets::DragDropReadOnlyField<AssetID>
|
||||||
(
|
(
|
||||||
"Fragment Shader", VERT_SHADER_NAME.data(),
|
"Vertex Shader", VERT_SHADER_NAME.data(),
|
||||||
[this]() { return currentMatSpec->vertexShader; },
|
[this]() { return currentMatSpec->vertexShader; },
|
||||||
[this](const AssetID& id) { currentMatSpec->vertexShader = id; },
|
[this](const AssetID& id) { currentMatSpec->vertexShader = id; },
|
||||||
SHDragDrop::DRAG_RESOURCE
|
SHDragDrop::DRAG_RESOURCE
|
||||||
|
@ -191,6 +200,37 @@ namespace SHADE
|
||||||
SHDragDrop::DRAG_RESOURCE
|
SHDragDrop::DRAG_RESOURCE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Subpass
|
||||||
|
const auto& SP_NAMES = SHGraphicsConstants::RenderGraphEntityNames::USABLE_SUBPASSES;
|
||||||
|
ImGui::Text("Subpass");
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::BeginCombo("##", currentMatSpec->subpassName.data(), ImGuiComboFlags_None))
|
||||||
|
{
|
||||||
|
for (const auto& NAME : SP_NAMES)
|
||||||
|
{
|
||||||
|
const bool IS_SELECTED = currentMatSpec->subpassName == NAME;
|
||||||
|
if (ImGui::Selectable(NAME.data(), IS_SELECTED))
|
||||||
|
{
|
||||||
|
isDirty = true;
|
||||||
|
SHCommandManager::PerformCommand
|
||||||
|
(
|
||||||
|
std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>
|
||||||
|
(
|
||||||
|
currentMatSpec->subpassName,
|
||||||
|
std::string(NAME),
|
||||||
|
[&](const std::string& newName){ currentMatSpec->subpassName = newName; }
|
||||||
|
)),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (IS_SELECTED)
|
||||||
|
{
|
||||||
|
ImGui::SetItemDefaultFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
// Load the shader to access it's data
|
// Load the shader to access it's data
|
||||||
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->fragShader);
|
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->fragShader);
|
||||||
if (!fragShader)
|
if (!fragShader)
|
||||||
|
@ -201,8 +241,8 @@ namespace SHADE
|
||||||
// Get interface for the shader combination
|
// Get interface for the shader combination
|
||||||
auto interface = fragShader->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface
|
auto interface = fragShader->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface
|
||||||
(
|
(
|
||||||
mappings.at(SHPredefinedDescriptorTypes::MATERIALS),
|
mappings.at(SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH),
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA
|
||||||
);
|
);
|
||||||
if (!interface)
|
if (!interface)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -7,3 +7,4 @@
|
||||||
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
|
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
|
||||||
#include "MaterialInspector/SHMaterialInspector.h" //Material Inspector
|
#include "MaterialInspector/SHMaterialInspector.h" //Material Inspector
|
||||||
#include "ColliderTagPanel/SHColliderTagPanel.h" //Collider Tag Panel
|
#include "ColliderTagPanel/SHColliderTagPanel.h" //Collider Tag Panel
|
||||||
|
#include "InputBindings/SHInputBindingsPanel.h" //Input Bindings
|
|
@ -97,7 +97,9 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
editorConfig = &SHConfigurationManager::LoadEditorConfig();
|
editorConfig = &SHConfigurationManager::LoadEditorConfig();
|
||||||
|
#endif
|
||||||
|
|
||||||
//Add editor windows
|
//Add editor windows
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
|
||||||
|
@ -106,6 +108,7 @@ namespace SHADE
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHMaterialInspector>();
|
SHEditorWindowManager::CreateEditorWindow<SHMaterialInspector>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHColliderTagPanel>();
|
SHEditorWindowManager::CreateEditorWindow<SHColliderTagPanel>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
||||||
|
SHEditorWindowManager::CreateEditorWindow<SHInputBindingsPanel>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
||||||
|
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
||||||
|
@ -130,8 +133,9 @@ namespace SHADE
|
||||||
|
|
||||||
InitBackend();
|
InitBackend();
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
SetStyle(static_cast<Style>(editorConfig->style));
|
SetStyle(static_cast<Style>(editorConfig->style));
|
||||||
|
#endif // SHEDITOR
|
||||||
|
|
||||||
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
|
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
|
||||||
{
|
{
|
||||||
|
@ -339,13 +343,18 @@ namespace SHADE
|
||||||
ImGui_ImplSDL2_Shutdown();
|
ImGui_ImplSDL2_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
editorConfig->startMaximized = shWindow->GetWindowData().isMaximised;
|
editorConfig->startMaximized = shWindow->GetWindowData().isMaximised;
|
||||||
SHConfigurationManager::SaveEditorConfig();
|
SHConfigurationManager::SaveEditorConfig();
|
||||||
|
#endif // SHEDITOR
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditor::SetStyle(Style style)
|
void SHEditor::SetStyle(Style style)
|
||||||
{
|
{
|
||||||
|
#ifdef SHEDITOR
|
||||||
editorConfig->style = static_cast<uint32_t>(style);
|
editorConfig->style = static_cast<uint32_t>(style);
|
||||||
|
#endif // SHEDITOR
|
||||||
|
|
||||||
switch (style)
|
switch (style)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -549,7 +558,10 @@ namespace SHADE
|
||||||
|
|
||||||
SHSceneManager::SetCurrentSceneName(newSceneName);
|
SHSceneManager::SetCurrentSceneName(newSceneName);
|
||||||
SHSceneManager::SetCurrentSceneAssetID(SHAssetManager::CreateNewAsset(AssetType::SCENE, newSceneName));
|
SHSceneManager::SetCurrentSceneAssetID(SHAssetManager::CreateNewAsset(AssetType::SCENE, newSceneName));
|
||||||
|
#ifdef SHEDITOR
|
||||||
editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID();
|
editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID();
|
||||||
|
#endif // SHEDITOR
|
||||||
|
|
||||||
}
|
}
|
||||||
//Get data, if data is null, asset doesn't exist, prompt for a name and create a new asset with the name
|
//Get data, if data is null, asset doesn't exist, prompt for a name and create a new asset with the name
|
||||||
|
|
||||||
|
@ -558,7 +570,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if(shWindow->IsUnsavedChanges())
|
if(shWindow->IsUnsavedChanges())
|
||||||
shWindow->ToggleUnsavedChanges();
|
shWindow->ToggleUnsavedChanges();
|
||||||
|
#ifdef SHEDITOR
|
||||||
editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID();
|
editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID();
|
||||||
|
#endif // SHEDITOR
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -623,7 +638,11 @@ namespace SHADE
|
||||||
editorState = SHEditor::State::STOP;
|
editorState = SHEditor::State::STOP;
|
||||||
SHCommandManager::SwapStacks();
|
SHCommandManager::SwapStacks();
|
||||||
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
|
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
LoadScene(editorConfig->workingSceneID);
|
LoadScene(editorConfig->workingSceneID);
|
||||||
|
#endif // SHEDITOR
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditor::ProcessShortcuts()
|
void SHEditor::ProcessShortcuts()
|
||||||
|
@ -678,7 +697,9 @@ namespace SHADE
|
||||||
if(width > 0 && height > 0)
|
if(width > 0 && height > 0)
|
||||||
{
|
{
|
||||||
auto [width, height] = shWindow->GetWindowSize();
|
auto [width, height] = shWindow->GetWindowSize();
|
||||||
|
#ifdef SHEditor
|
||||||
editorConfig->windowSize = { static_cast<float>(width), static_cast<float>(height) };
|
editorConfig->windowSize = { static_cast<float>(width), static_cast<float>(height) };
|
||||||
|
#endif // SHEditor
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,9 @@ namespace SHADE
|
||||||
std::vector<EntityID> selectedEntities;
|
std::vector<EntityID> selectedEntities;
|
||||||
|
|
||||||
State editorState = State::STOP;
|
State editorState = State::STOP;
|
||||||
|
#ifdef SHEDITOR
|
||||||
SHEditorConfig* editorConfig;
|
SHEditorConfig* editorConfig;
|
||||||
|
#endif // SHEDITOR
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -98,9 +98,9 @@ namespace SHADE
|
||||||
static bool IsItemHovered();
|
static bool IsItemHovered();
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* ImGui Wrapper Functions - Menu */
|
/* ImGui Wrapper Functions - Menu */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
static bool BeginMenu(const std::string& label);
|
static bool BeginMenu(const std::string& label);
|
||||||
static bool BeginMenu(const std::string& label, const char* icon);
|
static bool BeginMenu(const std::string& label, const char* icon);
|
||||||
static void EndMenu();
|
static void EndMenu();
|
||||||
static void BeginTooltip();
|
static void BeginTooltip();
|
||||||
|
@ -164,8 +164,8 @@ namespace SHADE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="title">Text to display.</param>
|
/// <param name="title">Text to display.</param>
|
||||||
/// <returns>True if button was pressed.</returns>
|
/// <returns>True if button was pressed.</returns>
|
||||||
static bool Button(const std::string& title);
|
static bool Button(const std::string& title);
|
||||||
static bool Selectable(const std::string& label);
|
static bool Selectable(const std::string& label);
|
||||||
static bool Selectable(const std::string& label, const char* icon);
|
static bool Selectable(const std::string& label, const char* icon);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a checkbox widget for boolean input.
|
/// Creates a checkbox widget for boolean input.
|
||||||
|
|
|
@ -424,7 +424,7 @@ namespace SHADE
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::PushID(label.data());
|
ImGui::PushID(label.data());
|
||||||
TextLabel(label);
|
TextLabel(label);
|
||||||
bool changed = ImGui::InputText("##inputText", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr);
|
bool changed = ImGui::InputText("##inputText", &text, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_AutoSelectAll, nullptr, nullptr);
|
||||||
if(SHDragDrop::BeginTarget())
|
if(SHDragDrop::BeginTarget())
|
||||||
{
|
{
|
||||||
if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag))
|
if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag))
|
||||||
|
|
|
@ -105,6 +105,12 @@ namespace SHADE
|
||||||
std::vector<SHAsset> assets;
|
std::vector<SHAsset> assets;
|
||||||
|
|
||||||
// Get all subfolders/files in this current folder
|
// Get all subfolders/files in this current folder
|
||||||
|
if (!std::filesystem::exists(std::filesystem::path(folder->path)))
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[Asset Manager] Path to build directory does not exist!: {}", folder->path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& dirEntry : std::filesystem::directory_iterator(folder->path))
|
for (auto& dirEntry : std::filesystem::directory_iterator(folder->path))
|
||||||
{
|
{
|
||||||
auto path = dirEntry.path();
|
auto path = dirEntry.path();
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace SHADE
|
||||||
enum class SH_PHYSICAL_DEVICE_TYPE
|
enum class SH_PHYSICAL_DEVICE_TYPE
|
||||||
{
|
{
|
||||||
BEST,
|
BEST,
|
||||||
|
DEDICATED,
|
||||||
};
|
};
|
||||||
|
|
||||||
class SHVkPhysicalDevice
|
class SHVkPhysicalDevice
|
||||||
|
|
|
@ -160,9 +160,31 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return bestDevice;
|
return bestDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::PhysicalDevice SHVkPhysicalDeviceLibrary::GetFirstDedicatedDevice(uint32_t apiVersion /*= SHVulkanAPIVersion::V_1_2*/)
|
||||||
|
{
|
||||||
|
if (!queried || physicalDevices.empty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
for (auto const& device : physicalDevices)
|
||||||
|
{
|
||||||
|
// Check for API version and device type. Ignore if queried device doesn't support version passed in
|
||||||
|
if (device.getProperties().apiVersion < static_cast<uint32_t>(apiVersion))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//VkDeviceSize biggestDeviceHeapSize = device.getMemoryProperties().;
|
||||||
|
if (device.getProperties().deviceType == vk::PhysicalDeviceType::eDiscreteGpu)
|
||||||
|
return device;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
|
||||||
|
@ -181,10 +203,10 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
SHLOG_TRACE("Successfully queried Physical Devices:");
|
SHLOG_INFO("Successfully queried Physical Devices:");
|
||||||
for (auto const& device : physicalDevices)
|
for (auto const& device : physicalDevices)
|
||||||
{
|
{
|
||||||
SHLOG_TRACE(std::string_view (std::string("\t-") + GetDeviceTypeName(device.getProperties().deviceType) + device.getProperties().deviceName.operator std::string()));
|
SHLOG_INFO(std::string_view (std::string("\t-") + GetDeviceTypeName(device.getProperties().deviceType) + device.getProperties().deviceName.operator std::string()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace SHADE
|
||||||
static void QueryPhysicalDevices(bool printInfo) noexcept;
|
static void QueryPhysicalDevices(bool printInfo) noexcept;
|
||||||
//static std::vector<std::shared_ptr<SHPhysicalDevice>> GetDevicesByType(VkPhysicalDeviceType gpuType, SHVulkanAPIVersion apiVersion = SHVulkanAPIVersion::V_1_2) noexcept;
|
//static std::vector<std::shared_ptr<SHPhysicalDevice>> GetDevicesByType(VkPhysicalDeviceType gpuType, SHVulkanAPIVersion apiVersion = SHVulkanAPIVersion::V_1_2) noexcept;
|
||||||
static vk::PhysicalDevice GetBestDevice(uint32_t apiVersion = VK_API_VERSION_1_3);
|
static vk::PhysicalDevice GetBestDevice(uint32_t apiVersion = VK_API_VERSION_1_3);
|
||||||
|
static vk::PhysicalDevice GetFirstDedicatedDevice(uint32_t apiVersion = VK_API_VERSION_1_3);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,6 +213,8 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
case SH_PHYSICAL_DEVICE_TYPE::BEST:
|
case SH_PHYSICAL_DEVICE_TYPE::BEST:
|
||||||
return resourceManager.Create<SHVkPhysicalDevice>(SHVkPhysicalDeviceLibrary::GetBestDevice());
|
return resourceManager.Create<SHVkPhysicalDevice>(SHVkPhysicalDeviceLibrary::GetBestDevice());
|
||||||
|
case SH_PHYSICAL_DEVICE_TYPE::DEDICATED:
|
||||||
|
return resourceManager.Create<SHVkPhysicalDevice>(SHVkPhysicalDeviceLibrary::GetFirstDedicatedDevice());
|
||||||
default:
|
default:
|
||||||
return resourceManager.Create<SHVkPhysicalDevice>(SHVkPhysicalDeviceLibrary::GetBestDevice());
|
return resourceManager.Create<SHVkPhysicalDevice>(SHVkPhysicalDeviceLibrary::GetBestDevice());
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,48 +29,59 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
||||||
#include "Scene/SHSceneManager.h"
|
#include "Scene/SHSceneManager.h"
|
||||||
#include "UI/SHUIComponent.h"
|
#include "UI/SHUIComponent.h"
|
||||||
|
#include "Animation/SHAnimatorComponent.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* SHBatch - Usage Functions */
|
/* SHBatch - Constructors/Destructors */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
||||||
: pipeline{ pipeline }
|
: pipeline{ pipeline }
|
||||||
{
|
{
|
||||||
if (!pipeline)
|
if (!pipeline)
|
||||||
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
||||||
|
|
||||||
|
// Check the pipeline and flag it depending on whether or not it is animated
|
||||||
|
isAnimated = checkIfIsAnimatedPipeline(pipeline);
|
||||||
|
|
||||||
// Mark all as dirty
|
// Mark all as dirty
|
||||||
setAllDirtyFlags();
|
setAllDirtyFlags();
|
||||||
}
|
}
|
||||||
|
|
||||||
SHBatch::SHBatch(SHBatch&& rhs)
|
SHBatch::SHBatch(SHBatch&& rhs)
|
||||||
: device { rhs.device }
|
: device { rhs.device }
|
||||||
, pipeline { rhs.pipeline }
|
, isAnimated { rhs.isAnimated }
|
||||||
, referencedMatInstances { std::move(rhs.referencedMatInstances) }
|
, pipeline { rhs.pipeline }
|
||||||
, matBufferDirty { std::move(rhs.matBufferDirty) }
|
, referencedMatInstances { std::move(rhs.referencedMatInstances) }
|
||||||
, subBatches { std::move(rhs.subBatches) }
|
, matBufferDirty { std::move(rhs.matBufferDirty) }
|
||||||
, isDirty { std::move(rhs.isDirty) }
|
, subBatches { std::move(rhs.subBatches) }
|
||||||
, drawData { std::move(rhs.drawData) }
|
, isDirty { std::move(rhs.isDirty) }
|
||||||
, transformData { std::move(rhs.transformData) }
|
, drawData { std::move(rhs.drawData) }
|
||||||
, instancedIntegerData { std::move(rhs.instancedIntegerData) }
|
, transformData { std::move(rhs.transformData) }
|
||||||
, matPropsData { std::move(rhs.matPropsData) }
|
, instancedIntegerData { std::move(rhs.instancedIntegerData) }
|
||||||
, matPropsDataSize { rhs.matPropsDataSize }
|
, matPropsData { std::move(rhs.matPropsData) }
|
||||||
, singleMatPropAlignedSize { rhs.singleMatPropAlignedSize }
|
, matPropsDataSize { rhs.matPropsDataSize }
|
||||||
, singleMatPropSize { rhs.singleMatPropSize }
|
, singleMatPropAlignedSize { rhs.singleMatPropAlignedSize }
|
||||||
, isCPUBuffersDirty { rhs.isCPUBuffersDirty }
|
, singleMatPropSize { rhs.singleMatPropSize }
|
||||||
, drawDataBuffer { rhs.drawDataBuffer }
|
, boneMatrixData { std::move(rhs.boneMatrixData) }
|
||||||
, transformDataBuffer { rhs.transformDataBuffer }
|
, boneMatrixIndices { std::move(rhs.boneMatrixIndices) }
|
||||||
, instancedIntegerBuffer { rhs.instancedIntegerBuffer }
|
, isCPUBuffersDirty { rhs.isCPUBuffersDirty }
|
||||||
, matPropsBuffer { rhs.matPropsBuffer }
|
, drawDataBuffer { rhs.drawDataBuffer }
|
||||||
, matPropsDescSet { rhs.matPropsDescSet }
|
, transformDataBuffer { rhs.transformDataBuffer }
|
||||||
|
, instancedIntegerBuffer { rhs.instancedIntegerBuffer }
|
||||||
|
, matPropsBuffer { rhs.matPropsBuffer }
|
||||||
|
, boneMatrixBuffer { rhs.boneMatrixBuffer }
|
||||||
|
, boneMatrixFirstIndexBuffer { rhs.boneMatrixFirstIndexBuffer }
|
||||||
|
, instanceDataDescSet { rhs.instanceDataDescSet }
|
||||||
{
|
{
|
||||||
rhs.drawDataBuffer = {};
|
rhs.drawDataBuffer = {};
|
||||||
rhs.transformDataBuffer = {};
|
rhs.transformDataBuffer = {};
|
||||||
rhs.instancedIntegerBuffer = {};
|
rhs.instancedIntegerBuffer = {};
|
||||||
rhs.matPropsBuffer = {};
|
rhs.matPropsBuffer = {};
|
||||||
rhs.matPropsDescSet = {};
|
rhs.boneMatrixBuffer = {};
|
||||||
|
rhs.boneMatrixFirstIndexBuffer = {};
|
||||||
|
rhs.instanceDataDescSet = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
SHBatch& SHBatch::operator=(SHBatch&& rhs)
|
SHBatch& SHBatch::operator=(SHBatch&& rhs)
|
||||||
|
@ -78,32 +89,39 @@ namespace SHADE
|
||||||
if (this == &rhs)
|
if (this == &rhs)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
device = rhs.device ;
|
device = rhs.device ;
|
||||||
pipeline = rhs.pipeline ;
|
isAnimated = rhs.isAnimated ;
|
||||||
referencedMatInstances = std::move(rhs.referencedMatInstances);
|
pipeline = rhs.pipeline ;
|
||||||
matBufferDirty = std::move(rhs.matBufferDirty) ;
|
referencedMatInstances = std::move(rhs.referencedMatInstances);
|
||||||
subBatches = std::move(rhs.subBatches) ;
|
matBufferDirty = std::move(rhs.matBufferDirty) ;
|
||||||
isDirty = std::move(rhs.isDirty) ;
|
subBatches = std::move(rhs.subBatches) ;
|
||||||
drawData = std::move(rhs.drawData) ;
|
isDirty = std::move(rhs.isDirty) ;
|
||||||
transformData = std::move(rhs.transformData) ;
|
drawData = std::move(rhs.drawData) ;
|
||||||
instancedIntegerData = std::move(rhs.instancedIntegerData) ;
|
transformData = std::move(rhs.transformData) ;
|
||||||
matPropsData = std::move(rhs.matPropsData) ;
|
instancedIntegerData = std::move(rhs.instancedIntegerData) ;
|
||||||
matPropsDataSize = rhs.matPropsDataSize ;
|
matPropsData = std::move(rhs.matPropsData) ;
|
||||||
singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ;
|
matPropsDataSize = rhs.matPropsDataSize ;
|
||||||
singleMatPropSize = rhs.singleMatPropSize ;
|
singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ;
|
||||||
isCPUBuffersDirty = rhs.isCPUBuffersDirty ;
|
singleMatPropSize = rhs.singleMatPropSize ;
|
||||||
drawDataBuffer = rhs.drawDataBuffer ;
|
boneMatrixData = std::move(rhs.boneMatrixData) ;
|
||||||
transformDataBuffer = rhs.transformDataBuffer ;
|
boneMatrixIndices = std::move(rhs.boneMatrixIndices) ;
|
||||||
instancedIntegerBuffer = rhs.instancedIntegerBuffer ;
|
isCPUBuffersDirty = rhs.isCPUBuffersDirty ;
|
||||||
matPropsBuffer = rhs.matPropsBuffer ;
|
drawDataBuffer = rhs.drawDataBuffer ;
|
||||||
matPropsDescSet = rhs.matPropsDescSet ;
|
transformDataBuffer = rhs.transformDataBuffer ;
|
||||||
|
instancedIntegerBuffer = rhs.instancedIntegerBuffer ;
|
||||||
|
matPropsBuffer = rhs.matPropsBuffer ;
|
||||||
|
boneMatrixBuffer = rhs.boneMatrixBuffer ;
|
||||||
|
boneMatrixFirstIndexBuffer = rhs.boneMatrixFirstIndexBuffer ;
|
||||||
|
instanceDataDescSet = rhs.instanceDataDescSet ;
|
||||||
|
|
||||||
// Unset values
|
// Unset values
|
||||||
rhs.drawDataBuffer = {};
|
rhs.drawDataBuffer = {};
|
||||||
rhs.transformDataBuffer = {};
|
rhs.transformDataBuffer = {};
|
||||||
rhs.instancedIntegerBuffer = {};
|
rhs.instancedIntegerBuffer = {};
|
||||||
rhs.matPropsBuffer = {};
|
rhs.matPropsBuffer = {};
|
||||||
rhs.matPropsDescSet = {};
|
rhs.boneMatrixBuffer = {};
|
||||||
|
rhs.boneMatrixFirstIndexBuffer = {};
|
||||||
|
rhs.instanceDataDescSet = {};
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -121,11 +139,14 @@ namespace SHADE
|
||||||
instancedIntegerBuffer[i].Free();
|
instancedIntegerBuffer[i].Free();
|
||||||
if (matPropsBuffer[i])
|
if (matPropsBuffer[i])
|
||||||
matPropsBuffer[i].Free();
|
matPropsBuffer[i].Free();
|
||||||
if (matPropsDescSet[i])
|
if (instanceDataDescSet[i])
|
||||||
matPropsDescSet[i].Free();
|
instanceDataDescSet[i].Free();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* SHBatch - Usage Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
void SHBatch::Add(const SHRenderable* renderable)
|
void SHBatch::Add(const SHRenderable* renderable)
|
||||||
{
|
{
|
||||||
// Ignore if null
|
// Ignore if null
|
||||||
|
@ -285,7 +306,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer to GPU
|
// Transfer to GPU
|
||||||
rebuildMaterialBuffers(frameIndex, descPool);
|
rebuildDescriptorSetBuffers(frameIndex, descPool);
|
||||||
|
|
||||||
// This frame is updated
|
// This frame is updated
|
||||||
matBufferDirty[frameIndex] = false;
|
matBufferDirty[frameIndex] = false;
|
||||||
|
@ -359,21 +380,86 @@ namespace SHADE
|
||||||
|
|
||||||
// Populate on the CPU
|
// Populate on the CPU
|
||||||
for (auto& subBatch : subBatches)
|
for (auto& subBatch : subBatches)
|
||||||
for (auto rendId : subBatch.Renderables)
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
{
|
||||||
|
auto* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
||||||
{
|
{
|
||||||
auto* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
rendId,
|
||||||
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
renderable->GetLightLayer()
|
||||||
{
|
});
|
||||||
rendId,
|
}
|
||||||
renderable->GetLightLayer()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer to GPU
|
// Transfer to GPU
|
||||||
if (instancedIntegerBuffer[frameIndex] && !drawData.empty())
|
if (instancedIntegerBuffer[frameIndex] && !drawData.empty())
|
||||||
instancedIntegerBuffer[frameIndex]->WriteToMemory(instancedIntegerData.data(), static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData)), 0, 0);
|
instancedIntegerBuffer[frameIndex]->WriteToMemory(instancedIntegerData.data(), static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData)), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::UpdateAnimationBuffer(uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
// Ignore if not animated batch
|
||||||
|
if (!isAnimated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Frame Index check
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Attempted to update animation buffers with an invalid frame index.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset Animation Matrix Data
|
||||||
|
boneMatrixData.clear();
|
||||||
|
boneMatrixIndices.clear();
|
||||||
|
|
||||||
|
// Add the first identity matrix into the bone matrix data
|
||||||
|
boneMatrixData.emplace_back(SHMatrix::Identity); // This kills the GPU
|
||||||
|
|
||||||
|
// Populate on the CPU
|
||||||
|
for (auto& subBatch : subBatches)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
{
|
||||||
|
// Get resources
|
||||||
|
auto animator = SHComponentManager::GetComponent_s<SHAnimatorComponent>(rendId);
|
||||||
|
auto renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
auto mesh = renderable->GetMesh();
|
||||||
|
|
||||||
|
// Mark start
|
||||||
|
boneMatrixIndices.emplace_back(static_cast<uint32_t>(boneMatrixData.size()));
|
||||||
|
|
||||||
|
// Add matrices
|
||||||
|
const int BONE_COUNT = static_cast<int>(mesh->BoneCount);
|
||||||
|
int extraMatricesToAdd = BONE_COUNT;
|
||||||
|
if (animator)
|
||||||
|
{
|
||||||
|
// Add matrices
|
||||||
|
const auto& MATRICES = animator->GetBoneMatrices();
|
||||||
|
if (MATRICES.size() <= BONE_COUNT)
|
||||||
|
{
|
||||||
|
boneMatrixData.insert(boneMatrixData.end(), MATRICES.cbegin(), MATRICES.cend());
|
||||||
|
extraMatricesToAdd = std::max({0, BONE_COUNT - static_cast<int>(MATRICES.size())});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we need to patch up with more matrices, add it
|
||||||
|
if (extraMatricesToAdd > 0)
|
||||||
|
{
|
||||||
|
boneMatrixData.insert(boneMatrixData.end(), extraMatricesToAdd, SHMatrix::Identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update GPU Buffers
|
||||||
|
if (!boneMatrixIndices.empty())
|
||||||
|
{
|
||||||
|
const uint32_t BMI_DATA_BYTES = static_cast<uint32_t>(boneMatrixIndices.size() * sizeof(uint32_t));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, boneMatrixFirstIndexBuffer[frameIndex], boneMatrixIndices.data(), BMI_DATA_BYTES,
|
||||||
|
vk::BufferUsageFlagBits::eVertexBuffer,
|
||||||
|
"Batch Instance Bone Matrix First Index Buffer"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
rebuildBoneMatrixDescSetBuffer(frameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
||||||
|
@ -410,14 +496,23 @@ namespace SHADE
|
||||||
// - EID data
|
// - EID data
|
||||||
instancedIntegerData.reserve(numTotalElements);
|
instancedIntegerData.reserve(numTotalElements);
|
||||||
instancedIntegerData.clear();
|
instancedIntegerData.clear();
|
||||||
|
// - Bone Data
|
||||||
|
if (isAnimated)
|
||||||
|
{
|
||||||
|
boneMatrixData.clear();
|
||||||
|
boneMatrixIndices.clear();
|
||||||
|
boneMatrixIndices.reserve(numTotalElements);
|
||||||
|
|
||||||
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
// Add the first identity matrix into the bone matrix data
|
||||||
|
boneMatrixData.emplace_back(SHMatrix::Identity);
|
||||||
|
}
|
||||||
|
|
||||||
// - Material Properties Data
|
// - Material Properties Data
|
||||||
|
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||||
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
||||||
(
|
(
|
||||||
descMappings.at(SHPredefinedDescriptorTypes::MATERIALS),
|
descMappings.at(SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH),
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA,
|
||||||
vk::ShaderStageFlagBits::eFragment
|
vk::ShaderStageFlagBits::eFragment
|
||||||
);
|
);
|
||||||
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
|
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
|
||||||
|
@ -444,13 +539,13 @@ namespace SHADE
|
||||||
if (CURR_INSTANCES > 0)
|
if (CURR_INSTANCES > 0)
|
||||||
{
|
{
|
||||||
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
||||||
{
|
{
|
||||||
.indexCount = subBatch.Mesh->IndexCount,
|
.indexCount = subBatch.Mesh->IndexCount,
|
||||||
.instanceCount = CURR_INSTANCES,
|
.instanceCount = CURR_INSTANCES,
|
||||||
.firstIndex = subBatch.Mesh->FirstIndex,
|
.firstIndex = subBatch.Mesh->FirstIndex,
|
||||||
.vertexOffset = subBatch.Mesh->FirstVertex,
|
.vertexOffset = subBatch.Mesh->FirstVertex,
|
||||||
.firstInstance = nextInstanceIndex
|
.firstInstance = nextInstanceIndex
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
nextInstanceIndex += CURR_INSTANCES;
|
nextInstanceIndex += CURR_INSTANCES;
|
||||||
|
|
||||||
|
@ -503,9 +598,36 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
}
|
}
|
||||||
//propsCurrPtr += singleMatPropAlignedSize;
|
|
||||||
propsCurrPtr += singleMatPropSize;
|
propsCurrPtr += singleMatPropSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bone Data
|
||||||
|
if (isAnimated)
|
||||||
|
{
|
||||||
|
// Mark start
|
||||||
|
boneMatrixIndices.emplace_back(static_cast<uint32_t>(boneMatrixData.size()));
|
||||||
|
|
||||||
|
auto animator = SHComponentManager::GetComponent_s<SHAnimatorComponent>(rendId);
|
||||||
|
auto mesh = renderable->GetMesh();
|
||||||
|
const int BONE_COUNT = static_cast<int>(mesh->BoneCount);
|
||||||
|
int extraMatricesToAdd = BONE_COUNT;
|
||||||
|
if (animator)
|
||||||
|
{
|
||||||
|
// Add matrices
|
||||||
|
const auto& MATRICES = animator->GetBoneMatrices();
|
||||||
|
if (MATRICES.size() <= BONE_COUNT)
|
||||||
|
{
|
||||||
|
boneMatrixData.insert(boneMatrixData.end(), MATRICES.cbegin(), MATRICES.cend());
|
||||||
|
extraMatricesToAdd = std::max({0, BONE_COUNT - static_cast<int>(MATRICES.size())});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we need to patch up with more matrices, add it
|
||||||
|
if (extraMatricesToAdd > 0)
|
||||||
|
{
|
||||||
|
boneMatrixData.insert(boneMatrixData.end(), extraMatricesToAdd, SHMatrix::Identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,8 +662,19 @@ namespace SHADE
|
||||||
BuffUsage::eVertexBuffer,
|
BuffUsage::eVertexBuffer,
|
||||||
"Batch Instance Data Buffer"
|
"Batch Instance Data Buffer"
|
||||||
);
|
);
|
||||||
// - Material Properties Buffer
|
// - Bone Matrix Indices
|
||||||
rebuildMaterialBuffers(frameIndex, descPool);
|
if (isAnimated && !boneMatrixIndices.empty())
|
||||||
|
{
|
||||||
|
const uint32_t BMI_DATA_BYTES = static_cast<uint32_t>(boneMatrixIndices.size() * sizeof(uint32_t));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, boneMatrixFirstIndexBuffer[frameIndex], boneMatrixIndices.data(), BMI_DATA_BYTES,
|
||||||
|
BuffUsage::eVertexBuffer,
|
||||||
|
"Batch Instance Bone Matrix First Index Buffer"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// - Material and bone buffers/descriptor sets
|
||||||
|
rebuildDescriptorSetBuffers(frameIndex, descPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark this frame as no longer dirty
|
// Mark this frame as no longer dirty
|
||||||
|
@ -551,7 +684,7 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* SHBatch - Usage Functions */
|
/* SHBatch - Usage Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline/* = true*/)
|
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline)
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
{
|
{
|
||||||
|
@ -564,7 +697,11 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Bind all required objects before drawing
|
// Bind all required objects before drawing
|
||||||
static std::array<uint32_t, 1> dynamicOffset{ 0 };
|
std::vector<uint32_t> dynamicOffset{ 0 };
|
||||||
|
if (isAnimated && !boneMatrixData.empty())
|
||||||
|
{
|
||||||
|
dynamicOffset.emplace_back(0);
|
||||||
|
}
|
||||||
cmdBuffer->BeginLabeledSegment("SHBatch for Pipeline #" + std::to_string(pipeline.GetId().Data.Index));
|
cmdBuffer->BeginLabeledSegment("SHBatch for Pipeline #" + std::to_string(pipeline.GetId().Data.Index));
|
||||||
|
|
||||||
if (bindBatchPipeline)
|
if (bindBatchPipeline)
|
||||||
|
@ -572,16 +709,24 @@ namespace SHADE
|
||||||
|
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
|
||||||
if (matPropsDescSet[frameIndex])
|
if (isAnimated && boneMatrixFirstIndexBuffer[frameIndex])
|
||||||
{
|
{
|
||||||
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::BONE_MATRIX_FIRST_INDEX, boneMatrixFirstIndexBuffer[frameIndex], 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// HACK: Bind the transform buffer instead since we won't use it anyways, but we must bind something
|
||||||
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::BONE_MATRIX_FIRST_INDEX, transformDataBuffer[frameIndex], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||||
|
if (instanceDataDescSet[frameIndex])
|
||||||
|
{
|
||||||
cmdBuffer->BindDescriptorSet
|
cmdBuffer->BindDescriptorSet
|
||||||
(
|
(
|
||||||
matPropsDescSet[frameIndex],
|
instanceDataDescSet[frameIndex],
|
||||||
SH_PIPELINE_TYPE::GRAPHICS,
|
SH_PIPELINE_TYPE::GRAPHICS,
|
||||||
//SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
descMappings.at(SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH),
|
||||||
descMappings.at(SHPredefinedDescriptorTypes::MATERIALS),
|
|
||||||
dynamicOffset
|
dynamicOffset
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -624,49 +769,128 @@ namespace SHADE
|
||||||
isCPUBuffersDirty = true;
|
isCPUBuffersDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
void SHBatch::rebuildDescriptorSetBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||||
{
|
{
|
||||||
if (matPropsData && !drawData.empty())
|
// Using Declarations and constants
|
||||||
{
|
using BuffUsage = vk::BufferUsageFlagBits;
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
using PreDefDescLayoutType = SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes;
|
||||||
(
|
|
||||||
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
|
||||||
vk::BufferUsageFlagBits::eStorageBuffer,
|
|
||||||
"Batch Material Data"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!matPropsDescSet[frameIndex])
|
|
||||||
|
/* Create Descriptor Sets if Needed */
|
||||||
|
PreDefDescLayoutType layoutTypes = {};
|
||||||
|
if (matPropsData)
|
||||||
|
{
|
||||||
|
layoutTypes = PreDefDescLayoutType::MATERIALS;
|
||||||
|
}
|
||||||
|
if (!boneMatrixData.empty())
|
||||||
|
{
|
||||||
|
layoutTypes = PreDefDescLayoutType::MATERIAL_AND_BONES;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool MUST_BUILD_BONE_DESC = isAnimated && !boneMatrixData.empty();
|
||||||
|
|
||||||
|
if (matPropsData || MUST_BUILD_BONE_DESC)
|
||||||
|
{
|
||||||
|
// Make sure that we have a descriptor set if we don't already have one
|
||||||
|
if (!instanceDataDescSet[frameIndex])
|
||||||
{
|
{
|
||||||
matPropsDescSet[frameIndex] = descPool->Allocate
|
instanceDataDescSet[frameIndex] = descPool->Allocate
|
||||||
(
|
(
|
||||||
SHGraphicsPredefinedData::GetPredefinedDescSetLayouts(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::MATERIALS),
|
SHGraphicsPredefinedData::GetPredefinedDescSetLayouts(layoutTypes),
|
||||||
{ 0 }
|
{ 0 }
|
||||||
);
|
);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
const auto& DESC_SETS = matPropsDescSet[frameIndex]->GetVkHandle();
|
const auto& DESC_SETS = instanceDataDescSet[frameIndex]->GetVkHandle();
|
||||||
for (auto descSet : DESC_SETS)
|
for (auto descSet : DESC_SETS)
|
||||||
{
|
{
|
||||||
SET_VK_OBJ_NAME(device, vk::ObjectType::eDescriptorSet, descSet, "[Descriptor Set] Batch Material Data");
|
SET_VK_OBJ_NAME(device, vk::ObjectType::eDescriptorSet, descSet, "[Descriptor Set] Batch Material Data");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr uint32_t MATERIAL_DESC_SET_INDEX = 0;
|
/* Material Data */
|
||||||
|
if (matPropsData && !drawData.empty())
|
||||||
|
{
|
||||||
|
// Update GPU buffer
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||||
|
BuffUsage::eStorageBuffer,
|
||||||
|
"Batch Material Data"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update descriptor set buffer
|
||||||
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
|
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
|
||||||
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer
|
instanceDataDescSet[frameIndex]->ModifyWriteDescBuffer
|
||||||
(
|
(
|
||||||
MATERIAL_DESC_SET_INDEX,
|
MATERIAL_DESC_SET_INDEX,
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA,
|
||||||
bufferList,
|
bufferList,
|
||||||
0, static_cast<uint32_t>(matPropsDataSize)
|
0, static_cast<uint32_t>(matPropsDataSize)
|
||||||
);
|
);
|
||||||
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
|
||||||
|
// Update the descriptor set buffer
|
||||||
|
instanceDataDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
||||||
(
|
(
|
||||||
MATERIAL_DESC_SET_INDEX,
|
MATERIAL_DESC_SET_INDEX,
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Animation Bone Data */
|
||||||
|
if (MUST_BUILD_BONE_DESC)
|
||||||
|
{
|
||||||
|
rebuildBoneMatrixDescSetBuffer(frameIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHBatch::rebuildBoneMatrixDescSetBuffer(uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
using BuffUsage = vk::BufferUsageFlagBits;
|
||||||
|
// Update GPU Buffers
|
||||||
|
const uint32_t BONE_MTX_DATA_BYTES = static_cast<uint32_t>(boneMatrixData.size() * sizeof(SHMatrix));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, boneMatrixBuffer[frameIndex], boneMatrixData.data(), BONE_MTX_DATA_BYTES,
|
||||||
|
BuffUsage::eStorageBuffer,
|
||||||
|
"Batch Bone Matrix Buffer"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update descriptor set buffer
|
||||||
|
std::array<Handle<SHVkBuffer>, 1> bufferList = { boneMatrixBuffer[frameIndex] };
|
||||||
|
instanceDataDescSet[frameIndex]->ModifyWriteDescBuffer
|
||||||
|
(
|
||||||
|
MATERIAL_DESC_SET_INDEX,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::PER_INST_BONE_DATA,
|
||||||
|
bufferList,
|
||||||
|
0,
|
||||||
|
static_cast<uint32_t>(boneMatrixData.size() * sizeof(SHMatrix))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update the descriptor set buffer
|
||||||
|
instanceDataDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
||||||
|
(
|
||||||
|
MATERIAL_DESC_SET_INDEX,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::PER_INST_BONE_DATA
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHBatch::checkIfIsAnimatedPipeline(Handle<SHVkPipeline> pipeline)
|
||||||
|
{
|
||||||
|
if (!pipeline || !pipeline->GetPipelineLayout())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Grab the pipeline descriptor set layouts
|
||||||
|
auto pipelineDescLayouts = pipeline->GetPipelineLayout()->GetDescriptorSetLayoutsPipeline();
|
||||||
|
|
||||||
|
// Check if they contain the material and bones layout, that indicates it is
|
||||||
|
using GfxPreDef = SHGraphicsPredefinedData;
|
||||||
|
using GfxPreDefType = GfxPreDef::PredefinedDescSetLayoutTypes;
|
||||||
|
const Handle<SHVkDescriptorSetLayout> BONE_DESC_SET_LAYOUT = GfxPreDef::GetPredefinedDescSetLayouts(GfxPreDefType::MATERIAL_AND_BONES)[0];
|
||||||
|
return std::find_if(pipelineDescLayouts.begin(), pipelineDescLayouts.end(), [BONE_DESC_SET_LAYOUT](Handle<SHVkDescriptorSetLayout> layout)
|
||||||
|
{
|
||||||
|
return BONE_DESC_SET_LAYOUT == layout;
|
||||||
|
}) != pipelineDescLayouts.end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,116 +27,132 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Forward Declarations */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
class SHVkBuffer;
|
||||||
|
class SHVkCommandBuffer;
|
||||||
|
class SHVkPipeline;
|
||||||
|
class SHMesh;
|
||||||
|
class SHRenderable;
|
||||||
|
class SHVkLogicalDevice;
|
||||||
|
class SHMaterialInstance;
|
||||||
|
class SHVkDescriptorSetGroup;
|
||||||
|
class SHVkDescriptorPool;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/*************************************************************************************/
|
||||||
|
/*!
|
||||||
|
\brief
|
||||||
|
Describes a segment of the sub batch operation.
|
||||||
|
*/
|
||||||
|
/*************************************************************************************/
|
||||||
|
struct SHSubBatch
|
||||||
|
{
|
||||||
|
public:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Forward Declarations */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
class SHVkBuffer;
|
Handle<SHMesh> Mesh;
|
||||||
class SHVkCommandBuffer;
|
std::unordered_set<EntityID> Renderables;
|
||||||
class SHVkPipeline;
|
};
|
||||||
class SHMesh;
|
/*************************************************************************************/
|
||||||
class SHRenderable;
|
/*!
|
||||||
class SHVkLogicalDevice;
|
\brief
|
||||||
class SHMaterialInstance;
|
Describes a segment of the sub batch operation.
|
||||||
class SHVkDescriptorSetGroup;
|
*/
|
||||||
class SHVkDescriptorPool;
|
/*************************************************************************************/
|
||||||
|
class SHBatch
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructor/Destructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
SHBatch(Handle<SHVkPipeline> pipeline);
|
||||||
|
SHBatch(const SHBatch&) = delete;
|
||||||
|
SHBatch(SHBatch&& rhs);
|
||||||
|
SHBatch& operator=(const SHBatch&) = delete;
|
||||||
|
SHBatch& operator=(SHBatch&& rhs);
|
||||||
|
~SHBatch();
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Usage Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/***********************************************************************************/
|
void Add(const SHRenderable* renderable);
|
||||||
/*!
|
void Remove(const SHRenderable* renderable);
|
||||||
\brief
|
void Clear();
|
||||||
Describes a segment of the sub batch operation.
|
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||||
*/
|
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||||
/***********************************************************************************/
|
void UpdateInstancedIntegerBuffer(uint32_t frameIndex);
|
||||||
struct SHSubBatch
|
void UpdateAnimationBuffer(uint32_t frameIndex);
|
||||||
{
|
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex);
|
||||||
public:
|
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline);
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
Handle<SHMesh> Mesh;
|
|
||||||
std::unordered_set<EntityID> Renderables;
|
|
||||||
};
|
|
||||||
/***********************************************************************************/
|
|
||||||
/*!
|
|
||||||
\brief
|
|
||||||
Describes a segment of the sub batch operation.
|
|
||||||
*/
|
|
||||||
/***********************************************************************************/
|
|
||||||
class SHBatch
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
/* Constructor/Destructors */
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
SHBatch(Handle<SHVkPipeline> pipeline);
|
|
||||||
SHBatch(const SHBatch&) = delete;
|
|
||||||
SHBatch(SHBatch&& rhs);
|
|
||||||
SHBatch& operator=(const SHBatch&) = delete;
|
|
||||||
SHBatch& operator=(SHBatch&& rhs);
|
|
||||||
~SHBatch();
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Usage Functions */
|
/* Getter Functions */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
void Add(const SHRenderable* renderable);
|
Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; };
|
||||||
void Remove(const SHRenderable* renderable);
|
bool IsEmpty() const noexcept { return subBatches.empty(); }
|
||||||
void Clear();
|
Handle<SHVkBuffer> GetTransformBuffer(uint32_t frameIndex) const noexcept;
|
||||||
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
Handle<SHVkBuffer> GetMDIBuffer(uint32_t frameIndex) const noexcept;
|
||||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
bool IsAnimated() const noexcept { return isAnimated; }
|
||||||
void UpdateInstancedIntegerBuffer(uint32_t frameIndex);
|
|
||||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
|
|
||||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline = true);
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
private:
|
||||||
/* Getter Functions */
|
/*---------------------------------------------------------------------------------*/
|
||||||
/*-----------------------------------------------------------------------------*/
|
/* Type Definition */
|
||||||
Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; };
|
/*---------------------------------------------------------------------------------*/
|
||||||
bool IsEmpty() const noexcept { return subBatches.empty(); }
|
using TripleBool = std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||||
Handle<SHVkBuffer> GetTransformBuffer(uint32_t frameIndex) const noexcept;
|
using TripleBuffer = std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||||
Handle<SHVkBuffer> GetMDIBuffer(uint32_t frameIndex) const noexcept;
|
using TripleDescSet = std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||||
|
|
||||||
private:
|
/*---------------------------------------------------------------------------------*/
|
||||||
/*-----------------------------------------------------------------------------*/
|
/* Constants */
|
||||||
/* Type Definition */
|
/*---------------------------------------------------------------------------------*/
|
||||||
/*-----------------------------------------------------------------------------*/
|
static constexpr uint32_t MATERIAL_DESC_SET_INDEX = 0;
|
||||||
using TripleBool = std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
|
||||||
using TripleBuffer = std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
|
||||||
using TripleDescSet = std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
// Resources
|
// Resources
|
||||||
Handle<SHVkLogicalDevice> device;
|
Handle<SHVkLogicalDevice> device;
|
||||||
// Batch Properties
|
// Config
|
||||||
Handle<SHVkPipeline> pipeline;
|
bool isAnimated; // Whether the material supports animation
|
||||||
std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances;
|
// Batch Properties
|
||||||
TripleBool matBufferDirty;
|
Handle<SHVkPipeline> pipeline;
|
||||||
// Batch Tree
|
std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances;
|
||||||
std::vector<SHSubBatch> subBatches;
|
TripleBool matBufferDirty;
|
||||||
TripleBool isDirty;
|
// Batch Tree
|
||||||
// CPU Buffers
|
std::vector<SHSubBatch> subBatches;
|
||||||
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
TripleBool isDirty;
|
||||||
std::vector<SHMatrix> transformData;
|
// CPU Buffers
|
||||||
std::vector<SHInstancedIntegerData> instancedIntegerData;
|
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
||||||
std::unique_ptr<char> matPropsData;
|
std::vector<SHMatrix> transformData;
|
||||||
Byte matPropsDataSize = 0;
|
std::vector<SHInstancedIntegerData> instancedIntegerData;
|
||||||
Byte singleMatPropAlignedSize = 0;
|
std::unique_ptr<char> matPropsData;
|
||||||
Byte singleMatPropSize = 0;
|
Byte matPropsDataSize = 0;
|
||||||
bool isCPUBuffersDirty = true;
|
Byte singleMatPropAlignedSize = 0;
|
||||||
// GPU Buffers
|
Byte singleMatPropSize = 0;
|
||||||
TripleBuffer drawDataBuffer;
|
std::vector<SHMatrix> boneMatrixData; // 0th element is always an identity matrix
|
||||||
TripleBuffer transformDataBuffer;
|
std::vector<uint32_t> boneMatrixIndices;
|
||||||
TripleBuffer instancedIntegerBuffer;
|
bool isCPUBuffersDirty = true;
|
||||||
TripleBuffer matPropsBuffer;
|
// GPU Buffers
|
||||||
TripleDescSet matPropsDescSet;
|
TripleBuffer drawDataBuffer;
|
||||||
|
TripleBuffer transformDataBuffer;
|
||||||
|
TripleBuffer instancedIntegerBuffer;
|
||||||
|
TripleBuffer matPropsBuffer;
|
||||||
|
TripleBuffer boneMatrixBuffer;
|
||||||
|
TripleBuffer boneMatrixFirstIndexBuffer; // Instanced buffer, indicates where the first bone matrix is
|
||||||
|
TripleDescSet instanceDataDescSet;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
void setAllDirtyFlags();
|
void setAllDirtyFlags();
|
||||||
void rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
void rebuildDescriptorSetBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||||
};
|
void rebuildBoneMatrixDescSetBuffer(uint32_t frameIndex);
|
||||||
|
static bool checkIfIsAnimatedPipeline(Handle<SHVkPipeline> pipeline);
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
batch.UpdateMaterialBuffer(frameIndex, descPool);
|
batch.UpdateMaterialBuffer(frameIndex, descPool);
|
||||||
batch.UpdateTransformBuffer(frameIndex);
|
batch.UpdateTransformBuffer(frameIndex);
|
||||||
|
batch.UpdateAnimationBuffer(frameIndex);
|
||||||
batch.UpdateInstancedIntegerBuffer(frameIndex);
|
batch.UpdateInstancedIntegerBuffer(frameIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,19 @@ namespace SHADE
|
||||||
|
|
||||||
void SHGraphicsPredefinedData::InitDescMappings(void) noexcept
|
void SHGraphicsPredefinedData::InitDescMappings(void) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descMappings.AddMappings
|
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descMappings.AddMappings
|
||||||
({
|
({
|
||||||
{SHPredefinedDescriptorTypes::STATIC_DATA, 0},
|
{SHPredefinedDescriptorTypes::STATIC_DATA, 0},
|
||||||
{SHPredefinedDescriptorTypes::CAMERA, 1},
|
{SHPredefinedDescriptorTypes::CAMERA, 1},
|
||||||
{SHPredefinedDescriptorTypes::MATERIALS, 2},
|
{SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH, 2},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING_ANIM)].descMappings.AddMappings
|
||||||
|
({
|
||||||
|
{SHPredefinedDescriptorTypes::STATIC_DATA, 0},
|
||||||
|
{SHPredefinedDescriptorTypes::CAMERA, 1},
|
||||||
|
{SHPredefinedDescriptorTypes::PER_INSTANCE_ANIM_BATCH, 2},
|
||||||
|
});
|
||||||
|
|
||||||
perSystemData[SHUtilities::ConvertEnum(SystemType::TEXT_RENDERING)].descMappings.AddMappings
|
perSystemData[SHUtilities::ConvertEnum(SystemType::TEXT_RENDERING)].descMappings.AddMappings
|
||||||
({
|
({
|
||||||
|
@ -50,9 +56,13 @@ namespace SHADE
|
||||||
|
|
||||||
void SHGraphicsPredefinedData::InitDummyPipelineLayouts(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
void SHGraphicsPredefinedData::InitDummyPipelineLayouts(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||||
{
|
{
|
||||||
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].dummyPipelineLayout = logicalDevice->CreatePipelineLayoutDummy(SHPipelineLayoutParamsDummy{ perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descSetLayouts });
|
for (int i = 0; i < SYSTEM_TYPE_COUNT; ++i)
|
||||||
perSystemData[SHUtilities::ConvertEnum(SystemType::TEXT_RENDERING)].dummyPipelineLayout = logicalDevice->CreatePipelineLayoutDummy(SHPipelineLayoutParamsDummy{ perSystemData[SHUtilities::ConvertEnum(SystemType::TEXT_RENDERING)].descSetLayouts });
|
{
|
||||||
perSystemData[SHUtilities::ConvertEnum(SystemType::RENDER_GRAPH_NODE_COMPUTE)].dummyPipelineLayout = logicalDevice->CreatePipelineLayoutDummy(SHPipelineLayoutParamsDummy{ perSystemData[SHUtilities::ConvertEnum(SystemType::RENDER_GRAPH_NODE_COMPUTE)].descSetLayouts });
|
perSystemData[i].dummyPipelineLayout = logicalDevice->CreatePipelineLayoutDummy
|
||||||
|
(
|
||||||
|
SHPipelineLayoutParamsDummy { perSystemData[i].descSetLayouts }
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -124,8 +134,8 @@ namespace SHADE
|
||||||
SHVkDescriptorSetLayout::Binding materialDataBinding
|
SHVkDescriptorSetLayout::Binding materialDataBinding
|
||||||
{
|
{
|
||||||
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
.Stage = vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eVertex,
|
.Stage = vk::ShaderStageFlagBits::eFragment,
|
||||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA,
|
||||||
.DescriptorCount = 1,
|
.DescriptorCount = 1,
|
||||||
};
|
};
|
||||||
Handle<SHVkDescriptorSetLayout> materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout({ materialDataBinding });
|
Handle<SHVkDescriptorSetLayout> materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout({ materialDataBinding });
|
||||||
|
@ -166,12 +176,24 @@ namespace SHADE
|
||||||
Handle<SHVkDescriptorSetLayout> shadowMapDescLayout = logicalDevice->CreateDescriptorSetLayout({ shadowMapBinding });
|
Handle<SHVkDescriptorSetLayout> shadowMapDescLayout = logicalDevice->CreateDescriptorSetLayout({ shadowMapBinding });
|
||||||
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, shadowMapDescLayout->GetVkHandle(), "[Descriptor Set Layout] Shadow Maps");
|
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, shadowMapDescLayout->GetVkHandle(), "[Descriptor Set Layout] Shadow Maps");
|
||||||
|
|
||||||
|
// For per instance data (transforms, materials, etc.)
|
||||||
|
SHVkDescriptorSetLayout::Binding boneDataBinding
|
||||||
|
{
|
||||||
|
.Type = vk::DescriptorType::eStorageBufferDynamic,
|
||||||
|
.Stage = vk::ShaderStageFlagBits::eVertex,
|
||||||
|
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::PER_INST_BONE_DATA,
|
||||||
|
.DescriptorCount = 1,
|
||||||
|
};
|
||||||
|
Handle<SHVkDescriptorSetLayout> materialBoneDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout({ materialDataBinding, boneDataBinding });
|
||||||
|
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, materialBoneDataPerInstanceLayout->GetVkHandle(), "[Descriptor Set Layout] Material and Bone Globals");
|
||||||
|
|
||||||
predefinedLayouts.push_back(staticGlobalLayout);
|
predefinedLayouts.push_back(staticGlobalLayout);
|
||||||
predefinedLayouts.push_back(lightDataDescSetLayout);
|
predefinedLayouts.push_back(lightDataDescSetLayout);
|
||||||
predefinedLayouts.push_back(cameraDataGlobalLayout);
|
predefinedLayouts.push_back(cameraDataGlobalLayout);
|
||||||
predefinedLayouts.push_back(materialDataPerInstanceLayout);
|
predefinedLayouts.push_back(materialDataPerInstanceLayout);
|
||||||
predefinedLayouts.push_back(fontDataDescSetLayout);
|
predefinedLayouts.push_back(fontDataDescSetLayout);
|
||||||
predefinedLayouts.push_back(shadowMapDescLayout);
|
predefinedLayouts.push_back(shadowMapDescLayout);
|
||||||
|
predefinedLayouts.push_back(materialBoneDataPerInstanceLayout);
|
||||||
|
|
||||||
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descSetLayouts = GetPredefinedDescSetLayouts
|
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descSetLayouts = GetPredefinedDescSetLayouts
|
||||||
(
|
(
|
||||||
|
@ -180,6 +202,13 @@ namespace SHADE
|
||||||
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::MATERIALS
|
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::MATERIALS
|
||||||
);
|
);
|
||||||
|
|
||||||
|
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING_ANIM)].descSetLayouts = GetPredefinedDescSetLayouts
|
||||||
|
(
|
||||||
|
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA |
|
||||||
|
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::CAMERA |
|
||||||
|
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::MATERIAL_AND_BONES
|
||||||
|
);
|
||||||
|
|
||||||
perSystemData[SHUtilities::ConvertEnum(SystemType::TEXT_RENDERING)].descSetLayouts = GetPredefinedDescSetLayouts
|
perSystemData[SHUtilities::ConvertEnum(SystemType::TEXT_RENDERING)].descSetLayouts = GetPredefinedDescSetLayouts
|
||||||
(
|
(
|
||||||
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA |
|
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA |
|
||||||
|
@ -197,12 +226,15 @@ namespace SHADE
|
||||||
|
|
||||||
void SHGraphicsPredefinedData::InitPredefinedVertexInputState(void) noexcept
|
void SHGraphicsPredefinedData::InitPredefinedVertexInputState(void) noexcept
|
||||||
{
|
{
|
||||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // positions at binding 0
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Attribute positions at binding 0
|
||||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_2D) }); // UVs at binding 1
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_2D) }); // Attribute UVs at binding 1
|
||||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Normals at binding 2
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Attribute Normals at binding 2
|
||||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Attribute Tangents at binding 3
|
||||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots)
|
defaultVertexInputState.AddBinding(true , true , { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Instanced Transform at binding 4 - 7 (4 slots)
|
||||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_2D) }); // Instanced integer data at index 8
|
defaultVertexInputState.AddBinding(true , true , { SHVertexAttribute(SHAttribFormat::UINT32_2D) }); // Instanced integer data at index 8
|
||||||
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::UINT32_4D) }); // Attribute bone indices at index 9
|
||||||
|
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_4D) }); // Attribute bone weights at index 10
|
||||||
|
defaultVertexInputState.AddBinding(true , true , { SHVertexAttribute(SHAttribFormat::UINT32_1D) }); // Instance bone matrix first index at index 11
|
||||||
|
|
||||||
shadowMapVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D)});
|
shadowMapVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D)});
|
||||||
shadowMapVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }, 4, 4); // Transform at binding 4 - 7 (4 slots)
|
shadowMapVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }, 4, 4); // Transform at binding 4 - 7 (4 slots)
|
||||||
|
@ -256,12 +288,24 @@ namespace SHADE
|
||||||
return static_cast<SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes>(static_cast<uint64_t>(lhs) | static_cast<uint64_t>(rhs));
|
return static_cast<SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes>(static_cast<uint64_t>(lhs) | static_cast<uint64_t>(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHADE::SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes& operator|=(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes& lhs, SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes rhs) noexcept
|
||||||
|
{
|
||||||
|
lhs = lhs | rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes operator&(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes lhs, SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes rhs) noexcept
|
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes operator&(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes lhs, SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes rhs) noexcept
|
||||||
{
|
{
|
||||||
return static_cast<SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes>(static_cast<uint64_t>(lhs) & static_cast<uint64_t>(rhs));
|
return static_cast<SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes>(static_cast<uint64_t>(lhs) & static_cast<uint64_t>(rhs));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHADE::SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes& operator&=(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes& lhs, SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes rhs) noexcept
|
||||||
|
{
|
||||||
|
lhs = lhs & rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
//SHGraphicsPredefinedData::PerSystem const& SHGraphicsPredefinedData::GetBatchingSystemData(void) noexcept
|
//SHGraphicsPredefinedData::PerSystem const& SHGraphicsPredefinedData::GetBatchingSystemData(void) noexcept
|
||||||
//{
|
//{
|
||||||
// return batchingSystemData;
|
// return batchingSystemData;
|
||||||
|
|
|
@ -23,21 +23,24 @@ namespace SHADE
|
||||||
// This enum is mainly to initialize a bit field to retrieve bit fields from SHPRedefinedData
|
// This enum is mainly to initialize a bit field to retrieve bit fields from SHPRedefinedData
|
||||||
enum class PredefinedDescSetLayoutTypes : uint64_t
|
enum class PredefinedDescSetLayoutTypes : uint64_t
|
||||||
{
|
{
|
||||||
STATIC_DATA = 0x01,
|
STATIC_DATA = 0b00000001,
|
||||||
LIGHTS = 0x02,
|
LIGHTS = 0b00000010,
|
||||||
CAMERA = 0x04,
|
CAMERA = 0b00000100,
|
||||||
MATERIALS = 0x08,
|
MATERIALS = 0b00001000,
|
||||||
FONT = 0x10,
|
FONT = 0b00010000,
|
||||||
SHADOW = 0x20,
|
SHADOW = 0b00100000,
|
||||||
|
MATERIAL_AND_BONES = 0b01000000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SystemType
|
enum class SystemType
|
||||||
{
|
{
|
||||||
BATCHING = 0,
|
BATCHING = 0,
|
||||||
|
BATCHING_ANIM,
|
||||||
TEXT_RENDERING,
|
TEXT_RENDERING,
|
||||||
RENDER_GRAPH_NODE_COMPUTE,
|
RENDER_GRAPH_NODE_COMPUTE,
|
||||||
NUM_TYPES
|
NUM_TYPES
|
||||||
};
|
};
|
||||||
|
static constexpr int SYSTEM_TYPE_COUNT = static_cast<int>(SystemType::NUM_TYPES);
|
||||||
|
|
||||||
struct PerSystem
|
struct PerSystem
|
||||||
{
|
{
|
||||||
|
@ -103,5 +106,7 @@ namespace SHADE
|
||||||
|
|
||||||
};
|
};
|
||||||
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes operator| (SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes lhs, SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes rhs) noexcept;
|
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes operator| (SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes lhs, SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes rhs) noexcept;
|
||||||
|
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes& operator|=(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes& lhs, SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes rhs) noexcept;
|
||||||
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes operator& (SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes lhs, SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes rhs) noexcept;
|
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes operator& (SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes lhs, SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes rhs) noexcept;
|
||||||
|
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes& operator&=(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes& lhs, SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes rhs) noexcept;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,8 @@ namespace SHADE
|
||||||
STATIC_DATA,
|
STATIC_DATA,
|
||||||
LIGHTS,
|
LIGHTS,
|
||||||
CAMERA,
|
CAMERA,
|
||||||
MATERIALS,
|
PER_INSTANCE_BATCH,
|
||||||
|
PER_INSTANCE_ANIM_BATCH,
|
||||||
FONT,
|
FONT,
|
||||||
RENDER_GRAPH_NODE_COMPUTE_RESOURCE,
|
RENDER_GRAPH_NODE_COMPUTE_RESOURCE,
|
||||||
RENDER_GRAPH_RESOURCE,
|
RENDER_GRAPH_RESOURCE,
|
||||||
|
|
|
@ -14,7 +14,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
// STL Includes
|
// STL Includes
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Assets/Asset Types/SHModelAsset.h"
|
#include "Assets/Asset Types/Models/SHModelAsset.h"
|
||||||
#include "../Meshes/SHPrimitiveGenerator.h"
|
#include "../Meshes/SHPrimitiveGenerator.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "SHGraphicsSystem.h"
|
#include "SHGraphicsSystem.h"
|
||||||
|
|
|
@ -13,6 +13,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
|
|
||||||
// STL Includes
|
// STL Includes
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -114,7 +115,14 @@ namespace SHADE
|
||||||
static constexpr std::string_view DEFERRED_COMPOSITE_COMPUTE = "Deferred Composite";
|
static constexpr std::string_view DEFERRED_COMPOSITE_COMPUTE = "Deferred Composite";
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr std::string_view GBUFFER_WRITE_SUBPASS = "G-Buffer Write";
|
||||||
|
static constexpr std::string_view UI_SUBPASS = "UI";
|
||||||
|
|
||||||
|
static constexpr std::array USABLE_SUBPASSES =
|
||||||
|
{
|
||||||
|
GBUFFER_WRITE_SUBPASS,
|
||||||
|
UI_SUBPASS
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DescriptorSetBindings
|
struct DescriptorSetBindings
|
||||||
|
@ -161,7 +169,15 @@ namespace SHADE
|
||||||
DescriptorSet binding for per instance material values.
|
DescriptorSet binding for per instance material values.
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
static constexpr uint32_t BATCHED_PER_INST_DATA = 0;
|
static constexpr uint32_t PER_INST_MATERIAL_DATA = 0;
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
\brief
|
||||||
|
DescriptorSet binding for per instance bone values.
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
static constexpr uint32_t PER_INST_BONE_DATA = 1;
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
@ -191,6 +207,14 @@ namespace SHADE
|
||||||
static constexpr uint32_t SHADOW_MAP_IMAGE_SAMPLER_DATA = 0;
|
static constexpr uint32_t SHADOW_MAP_IMAGE_SAMPLER_DATA = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
\brief
|
||||||
|
Descriptor set binding for bone matrix data.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
static constexpr uint32_t BONE_MATRIX_DATA = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VertexBufferBindings
|
struct VertexBufferBindings
|
||||||
|
@ -237,6 +261,27 @@ namespace SHADE
|
||||||
*/
|
*/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
static constexpr uint32_t INTEGER_DATA = 5;
|
static constexpr uint32_t INTEGER_DATA = 5;
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
\brief
|
||||||
|
Vertex buffer bindings for the bone indices buffer.
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
static constexpr uint32_t BONE_INDICES = 6;
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
\brief
|
||||||
|
Vertex buffer bindings for the bone weights buffer.
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
static constexpr uint32_t BONE_WEIGHTS = 7;
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
\brief
|
||||||
|
Vertex buffer bindings for the bone matrix first index buffer.
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
static constexpr uint32_t BONE_MATRIX_FIRST_INDEX = 8;
|
||||||
|
|
||||||
static constexpr uint32_t CALCULATED_GLYPH_POSITION = 0;
|
static constexpr uint32_t CALCULATED_GLYPH_POSITION = 0;
|
||||||
static constexpr uint32_t GLYPH_INDEX = 1;
|
static constexpr uint32_t GLYPH_INDEX = 1;
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace SHADE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get Physical Device
|
// Get Physical Device
|
||||||
physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::BEST);
|
physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::DEDICATED);
|
||||||
if (!physicalDevice->GetVkPhysicalDevice())
|
if (!physicalDevice->GetVkPhysicalDevice())
|
||||||
{
|
{
|
||||||
throw std::runtime_error("[Graphics System] No supported Vulkan 1.3 compatible GPU was detected!");
|
throw std::runtime_error("[Graphics System] No supported Vulkan 1.3 compatible GPU was detected!");
|
||||||
|
@ -127,15 +127,19 @@ namespace SHADE
|
||||||
|
|
||||||
SHFreetypeInstance::Init();
|
SHFreetypeInstance::Init();
|
||||||
|
|
||||||
SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl", false);
|
//SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl", false);
|
||||||
SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl", false);
|
//SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl", false);
|
||||||
SHAssetManager::CompileAsset("../../Assets/Shaders/SSAOBlur_CS.glsl", false);
|
//SHAssetManager::CompileAsset("../../Assets/Shaders/SSAOBlur_CS.glsl", false);
|
||||||
SHAssetManager::CompileAsset("../../Assets/Shaders/PureCopy_CS.glsl", false);
|
//SHAssetManager::CompileAsset("../../Assets/Shaders/PureCopy_CS.glsl", false);
|
||||||
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl", false);
|
//SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl", false);
|
||||||
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_FS.glsl", false);
|
//SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_FS.glsl", false);
|
||||||
|
//SHAssetManager::CompileAsset("../../Assets/Shaders/UI_VS.glsl", false);
|
||||||
|
//SHAssetManager::CompileAsset("../../Assets/Shaders/UI_FS.glsl", false);
|
||||||
|
//SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false);
|
||||||
|
|
||||||
// Load Built In Shaders
|
// Load Built In Shaders
|
||||||
static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT);
|
static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT);
|
||||||
|
static constexpr AssetID VS_ANIM = 47911992; animtVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_ANIM);
|
||||||
static constexpr AssetID FS_DEFAULT = 46377769; defaultFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEFAULT);
|
static constexpr AssetID FS_DEFAULT = 46377769; defaultFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEFAULT);
|
||||||
static constexpr AssetID VS_DEBUG = 48002439; debugVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEBUG);
|
static constexpr AssetID VS_DEBUG = 48002439; debugVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEBUG);
|
||||||
static constexpr AssetID FS_DEBUG = 36671027; debugFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEBUG);
|
static constexpr AssetID FS_DEBUG = 36671027; debugFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEBUG);
|
||||||
|
@ -231,7 +235,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* G-BUFFER SUBPASS INIT */
|
/* G-BUFFER SUBPASS INIT */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write", worldViewport, worldRenderer);
|
auto gBufferSubpass = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data(), worldViewport, worldRenderer);
|
||||||
gBufferSubpass->AddColorOutput("Position");
|
gBufferSubpass->AddColorOutput("Position");
|
||||||
gBufferSubpass->AddColorOutput("Entity ID");
|
gBufferSubpass->AddColorOutput("Entity ID");
|
||||||
gBufferSubpass->AddColorOutput("Light Layer Indices");
|
gBufferSubpass->AddColorOutput("Light Layer Indices");
|
||||||
|
@ -240,6 +244,7 @@ namespace SHADE
|
||||||
gBufferSubpass->AddColorOutput("Position World Space");
|
gBufferSubpass->AddColorOutput("Position World Space");
|
||||||
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL);
|
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL);
|
||||||
|
|
||||||
|
usableSubpassesMapping.emplace (std::string (SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data()), gBufferSubpass);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* SSAO PASS AND DATA INIT */
|
/* SSAO PASS AND DATA INIT */
|
||||||
|
@ -318,7 +323,7 @@ namespace SHADE
|
||||||
/* SCREEN SPACE PASS */
|
/* SCREEN SPACE PASS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
auto screenSpaceNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data(), {"Scene", "Entity ID"}, {SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data()});
|
auto screenSpaceNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data(), {"Scene", "Entity ID"}, {SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data()});
|
||||||
auto uiSubpass = screenSpaceNode->AddSubpass("UI", worldViewport, screenRenderer);
|
auto uiSubpass = screenSpaceNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::UI_SUBPASS.data(), worldViewport, screenRenderer);
|
||||||
uiSubpass->AddColorOutput("Scene");
|
uiSubpass->AddColorOutput("Scene");
|
||||||
uiSubpass->AddColorOutput("Entity ID");
|
uiSubpass->AddColorOutput("Entity ID");
|
||||||
uiSubpass->AddExteriorDrawCalls([=](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
uiSubpass->AddExteriorDrawCalls([=](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
||||||
|
@ -326,6 +331,8 @@ namespace SHADE
|
||||||
textRenderingSubSystem->Render(cmdBuffer, renderer, frameIndex);
|
textRenderingSubSystem->Render(cmdBuffer, renderer, frameIndex);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
usableSubpassesMapping.emplace(SHGraphicsConstants::RenderGraphEntityNames::UI_SUBPASS.data(), uiSubpass);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* RENDER TO SWAPCHAIN IMAGE FOR PRESENT PASS */
|
/* RENDER TO SWAPCHAIN IMAGE FOR PRESENT PASS */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
@ -420,7 +427,7 @@ namespace SHADE
|
||||||
|
|
||||||
// initialize the text renderer
|
// initialize the text renderer
|
||||||
auto uiNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data());
|
auto uiNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data());
|
||||||
textRenderingSubSystem->Init(device, uiNode->GetRenderpass(), uiNode->GetSubpass("UI"), descPool, textVS, textFS);
|
textRenderingSubSystem->Init(device, uiNode->GetRenderpass(), uiNode->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::UI_SUBPASS), descPool, textVS, textFS);
|
||||||
|
|
||||||
SHGlobalDescriptorSets::SetLightingSubSystem(lightingSubSystem);
|
SHGlobalDescriptorSets::SetLightingSubSystem(lightingSubSystem);
|
||||||
|
|
||||||
|
@ -447,9 +454,15 @@ namespace SHADE
|
||||||
defaultMaterial = AddMaterial
|
defaultMaterial = AddMaterial
|
||||||
(
|
(
|
||||||
defaultVertShader, defaultFragShader,
|
defaultVertShader, defaultFragShader,
|
||||||
renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass("G-Buffer Write")
|
renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS)
|
||||||
);
|
);
|
||||||
defaultMaterial->SetProperty("data.textureIndex", defaultTexture->TextureArrayIndex);
|
defaultMaterial->SetProperty("data.textureIndex", defaultTexture->TextureArrayIndex);
|
||||||
|
defaultAnimMaterial = AddMaterial
|
||||||
|
(
|
||||||
|
animtVertShader, defaultFragShader,
|
||||||
|
renderGraph->GetNode("G-Buffer")->GetSubpass("G-Buffer Write")
|
||||||
|
);
|
||||||
|
defaultAnimMaterial->SetProperty("data.textureIndex", defaultTexture->TextureArrayIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -525,6 +538,8 @@ namespace SHADE
|
||||||
std::make_pair(meshLibrary.GetVertexTexCoordsBuffer(), SHGraphicsConstants::VertexBufferBindings::TEX_COORD),
|
std::make_pair(meshLibrary.GetVertexTexCoordsBuffer(), SHGraphicsConstants::VertexBufferBindings::TEX_COORD),
|
||||||
std::make_pair(meshLibrary.GetVertexNormalsBuffer(), SHGraphicsConstants::VertexBufferBindings::NORMAL),
|
std::make_pair(meshLibrary.GetVertexNormalsBuffer(), SHGraphicsConstants::VertexBufferBindings::NORMAL),
|
||||||
std::make_pair(meshLibrary.GetVertexTangentsBuffer(), SHGraphicsConstants::VertexBufferBindings::TANGENT),
|
std::make_pair(meshLibrary.GetVertexTangentsBuffer(), SHGraphicsConstants::VertexBufferBindings::TANGENT),
|
||||||
|
std::make_pair(meshLibrary.GetVertexBoneIndicesBuffer(), SHGraphicsConstants::VertexBufferBindings::BONE_INDICES),
|
||||||
|
std::make_pair(meshLibrary.GetVertexBoneWeightsBuffer(), SHGraphicsConstants::VertexBufferBindings::BONE_WEIGHTS),
|
||||||
std::make_pair(meshLibrary.GetIndexBuffer(), 0),
|
std::make_pair(meshLibrary.GetIndexBuffer(), 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -564,32 +579,24 @@ namespace SHADE
|
||||||
else
|
else
|
||||||
renderer->UpdateData(frameIndex);
|
renderer->UpdateData(frameIndex);
|
||||||
#else
|
#else
|
||||||
renderers[renIndex]->UpdateDataAndBind(frameIndex);
|
renderer->UpdateData(frameIndex);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::B))
|
//if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::B))
|
||||||
{
|
//{
|
||||||
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
// auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
||||||
for (auto& comp : lightComps)
|
// for (auto& comp : lightComps)
|
||||||
{
|
// {
|
||||||
comp.SetEnableShadow(true);
|
// comp.SetEnableShadow(true);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
renderGraph->Begin(frameIndex);
|
renderGraph->Begin(frameIndex);
|
||||||
auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex);
|
auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex);
|
||||||
|
|
||||||
// Bind all the buffers required for meshes
|
|
||||||
for (auto& [buffer, bindingPoint] : MESH_DATA)
|
|
||||||
{
|
|
||||||
if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eVertexBuffer)
|
|
||||||
cmdBuffer->BindVertexBuffer(bindingPoint, buffer, 0);
|
|
||||||
else if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eIndexBuffer)
|
|
||||||
cmdBuffer->BindIndexBuffer(buffer, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderGraph->Execute(frameIndex, descPool);
|
renderGraph->Execute(frameIndex, descPool, MESH_DATA);
|
||||||
renderGraph->End(frameIndex);
|
renderGraph->End(frameIndex);
|
||||||
|
|
||||||
graphicsQueue->SubmitCommandBuffer
|
graphicsQueue->SubmitCommandBuffer
|
||||||
|
@ -765,7 +772,7 @@ namespace SHADE
|
||||||
auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightEnableShadowEvent>*>(eventPtr.get())->data;
|
auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightEnableShadowEvent>*>(eventPtr.get())->data;
|
||||||
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity);
|
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity);
|
||||||
std::string resourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity);
|
std::string resourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity);
|
||||||
Handle<SHSubpass> companionSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass("G-Buffer Write");
|
Handle<SHSubpass> companionSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS);
|
||||||
|
|
||||||
if (EVENT_DATA->generateRenderer)
|
if (EVENT_DATA->generateRenderer)
|
||||||
{
|
{
|
||||||
|
@ -800,7 +807,12 @@ namespace SHADE
|
||||||
rasterState.cull_mode = vk::CullModeFlagBits::eBack;
|
rasterState.cull_mode = vk::CullModeFlagBits::eBack;
|
||||||
|
|
||||||
tempLibrary.Init(device);
|
tempLibrary.Init(device);
|
||||||
tempLibrary.CreateGraphicsPipelines({ shadowMapVS, {} }, shadowMapNode->GetRenderpass(), newSubpass, SHGraphicsPredefinedData::GetShadowMapViState(), rasterState);
|
tempLibrary.CreateGraphicsPipelines
|
||||||
|
(
|
||||||
|
{ shadowMapVS, {} }, shadowMapNode->GetRenderpass(), newSubpass,
|
||||||
|
SHGraphicsPredefinedData::SystemType::BATCHING,
|
||||||
|
SHGraphicsPredefinedData::GetShadowMapViState(), rasterState
|
||||||
|
);
|
||||||
shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, {} });
|
shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, {} });
|
||||||
}
|
}
|
||||||
newSubpass->SetCompanionSubpass(companionSubpass, shadowMapPipeline); // set companion subpass and pipeline
|
newSubpass->SetCompanionSubpass(companionSubpass, shadowMapPipeline); // set companion subpass and pipeline
|
||||||
|
@ -865,9 +877,9 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Mesh Registration Functions */
|
/* Mesh Registration Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
SHADE::Handle<SHADE::SHMesh> SHGraphicsSystem::AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices)
|
SHADE::Handle<SHADE::SHMesh> SHGraphicsSystem::AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices, const SHMesh::VertexBoneIndices* const boneIndices, const SHMesh::VertexWeights* const boneWeights, uint32_t boneCount)
|
||||||
{
|
{
|
||||||
return meshLibrary.AddMesh(vertexCount, positions, texCoords, tangents, normals, indexCount, indices);
|
return meshLibrary.AddMesh(vertexCount, positions, texCoords, tangents, normals, boneIndices, boneWeights, indexCount, indices, boneCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHGraphicsSystem::RemoveMesh(Handle<SHMesh> mesh)
|
void SHGraphicsSystem::RemoveMesh(Handle<SHMesh> mesh)
|
||||||
|
@ -1182,6 +1194,16 @@ namespace SHADE
|
||||||
return fontLibrary;
|
return fontLibrary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Handle <SHSubpass> SHGraphicsSystem::GetUsableSubpass(std::string const& subpassName) const noexcept
|
||||||
|
{
|
||||||
|
if (usableSubpassesMapping.contains(subpassName))
|
||||||
|
{
|
||||||
|
return usableSubpassesMapping.at (subpassName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
Handle<SHVkPipeline> SHGraphicsSystem::createDebugDrawPipeline(Handle<SHVkRenderpass> renderPass, Handle<SHSubpass> subpass, bool filled, bool triMesh, bool instanced)
|
Handle<SHVkPipeline> SHGraphicsSystem::createDebugDrawPipeline(Handle<SHVkRenderpass> renderPass, Handle<SHSubpass> subpass, bool filled, bool triMesh, bool instanced)
|
||||||
{
|
{
|
||||||
auto pipelineLayout = resourceManager.Create<SHVkPipelineLayout>
|
auto pipelineLayout = resourceManager.Create<SHVkPipelineLayout>
|
||||||
|
|
|
@ -230,7 +230,7 @@ namespace SHADE
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/*******************************************************************************/
|
/*******************************************************************************/
|
||||||
Handle<SHMesh> AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices);
|
Handle<SHMesh> AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices, const SHMesh::VertexBoneIndices* const boneIndices = nullptr, const SHMesh::VertexWeights* const boneWeights = nullptr, uint32_t boneCount = 0);
|
||||||
/*******************************************************************************/
|
/*******************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
|
||||||
|
@ -399,6 +399,7 @@ namespace SHADE
|
||||||
uint32_t GetCurrentFrameIndex(void) const noexcept { return renderContext.GetCurrentFrame(); }
|
uint32_t GetCurrentFrameIndex(void) const noexcept { return renderContext.GetCurrentFrame(); }
|
||||||
SHFontLibrary const& GetFontLibrary (void) const noexcept;
|
SHFontLibrary const& GetFontLibrary (void) const noexcept;
|
||||||
const SHMeshLibrary& GetMeshLibrary() const noexcept { return meshLibrary; };
|
const SHMeshLibrary& GetMeshLibrary() const noexcept { return meshLibrary; };
|
||||||
|
Handle <SHSubpass> GetUsableSubpass(std::string const& subpassName) const noexcept;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Getters */
|
/* Getters */
|
||||||
|
@ -455,6 +456,7 @@ namespace SHADE
|
||||||
|
|
||||||
// Built-In Shaders
|
// Built-In Shaders
|
||||||
Handle<SHVkShaderModule> defaultVertShader;
|
Handle<SHVkShaderModule> defaultVertShader;
|
||||||
|
Handle<SHVkShaderModule> animtVertShader;
|
||||||
Handle<SHVkShaderModule> defaultFragShader;
|
Handle<SHVkShaderModule> defaultFragShader;
|
||||||
Handle<SHVkShaderModule> debugVertShader;
|
Handle<SHVkShaderModule> debugVertShader;
|
||||||
Handle<SHVkShaderModule> debugFragShader;
|
Handle<SHVkShaderModule> debugFragShader;
|
||||||
|
@ -473,6 +475,7 @@ namespace SHADE
|
||||||
|
|
||||||
// Built-In Materials
|
// Built-In Materials
|
||||||
Handle<SHMaterial> defaultMaterial;
|
Handle<SHMaterial> defaultMaterial;
|
||||||
|
Handle<SHMaterial> defaultAnimMaterial;
|
||||||
Handle<SHVkPipeline> debugDrawPipeline;
|
Handle<SHVkPipeline> debugDrawPipeline;
|
||||||
Handle<SHVkPipeline> debugDrawDepthPipeline;
|
Handle<SHVkPipeline> debugDrawDepthPipeline;
|
||||||
Handle<SHVkPipeline> debugDrawLineMeshPipeline;
|
Handle<SHVkPipeline> debugDrawLineMeshPipeline;
|
||||||
|
@ -507,6 +510,8 @@ namespace SHADE
|
||||||
uint32_t resizeHeight = 1;
|
uint32_t resizeHeight = 1;
|
||||||
bool restoredFromMinimize = false;
|
bool restoredFromMinimize = false;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, Handle<SHSubpass>> usableSubpassesMapping{};
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -100,9 +100,9 @@ namespace SHADE
|
||||||
auto const& mappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
auto const& mappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||||
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
||||||
(
|
(
|
||||||
mappings.at (SHPredefinedDescriptorTypes::MATERIALS),
|
mappings.at (SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH),
|
||||||
//SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
//SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA,
|
||||||
vk::ShaderStageFlagBits::eFragment
|
vk::ShaderStageFlagBits::eFragment
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,9 +81,9 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
return baseMaterial->GetPipeline()->GetPipelineLayout()->GetShaderBlockInterface
|
return baseMaterial->GetPipeline()->GetPipelineLayout()->GetShaderBlockInterface
|
||||||
(
|
(
|
||||||
SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING).at(SHPredefinedDescriptorTypes::MATERIALS),
|
SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING).at(SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH),
|
||||||
//SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
//SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA,
|
||||||
vk::ShaderStageFlagBits::eFragment
|
vk::ShaderStageFlagBits::eFragment
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,187 +20,252 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
SHADE::Handle<SHADE::SHMesh> SHMeshLibrary::AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices)
|
SHADE::Handle<SHADE::SHMesh> SHMeshLibrary::AddMesh
|
||||||
{
|
(
|
||||||
isDirty = true;
|
uint32_t vertexCount, const SHMesh::VertexPosition* const positions,
|
||||||
|
const SHMesh::VertexTexCoord* const texCoords,
|
||||||
|
const SHMesh::VertexTangent* const tangents,
|
||||||
|
const SHMesh::VertexNormal* const normals,
|
||||||
|
const SHMesh::VertexBoneIndices* const boneIndices,
|
||||||
|
const SHMesh::VertexWeights* const boneWeights,
|
||||||
|
uint32_t indexCount, const SHMesh::Index* const indices,
|
||||||
|
uint32_t boneCount)
|
||||||
|
{
|
||||||
|
isDirty = true;
|
||||||
|
|
||||||
auto handle = meshes.Create();
|
auto handle = meshes.Create();
|
||||||
meshAddJobs.emplace_back( MeshAddJob
|
meshAddJobs.emplace_back(MeshAddJob
|
||||||
{
|
|
||||||
vertexCount,
|
|
||||||
positions,
|
|
||||||
texCoords,
|
|
||||||
tangents,
|
|
||||||
normals,
|
|
||||||
indexCount,
|
|
||||||
indices,
|
|
||||||
handle
|
|
||||||
});
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHMeshLibrary::RemoveMesh(Handle<SHMesh> mesh)
|
|
||||||
{
|
{
|
||||||
if (!mesh)
|
vertexCount,
|
||||||
throw std::invalid_argument("Attempted to remove a Mesh that did not belong to the Mesh Library!");
|
positions,
|
||||||
|
texCoords,
|
||||||
|
tangents,
|
||||||
|
normals,
|
||||||
|
boneIndices,
|
||||||
|
boneWeights,
|
||||||
|
indexCount,
|
||||||
|
indices,
|
||||||
|
boneCount,
|
||||||
|
handle
|
||||||
|
});
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
meshRemoveJobs.emplace_back(mesh);
|
void SHMeshLibrary::RemoveMesh(Handle<SHMesh> mesh)
|
||||||
isDirty = true;
|
{
|
||||||
|
if (!mesh)
|
||||||
|
throw std::invalid_argument("Attempted to remove a Mesh that did not belong to the Mesh Library!");
|
||||||
|
|
||||||
|
meshRemoveJobs.emplace_back(mesh);
|
||||||
|
isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHMeshLibrary::BuildBuffers(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer)
|
||||||
|
{
|
||||||
|
// No changes
|
||||||
|
if (!isDirty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Remove
|
||||||
|
if (!meshRemoveJobs.empty())
|
||||||
|
{
|
||||||
|
// - Remove from order list
|
||||||
|
for (const auto& meshToRemove : meshRemoveJobs)
|
||||||
|
{
|
||||||
|
auto searchResult = std::find(meshOrder.begin(), meshOrder.end(), meshToRemove);
|
||||||
|
// Shouldn't happen, ignore
|
||||||
|
if (searchResult == meshOrder.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Remove from mesh list
|
||||||
|
meshOrder.erase(searchResult);
|
||||||
|
}
|
||||||
|
meshRemoveJobs.clear();
|
||||||
|
// - Shift existing elements in to close up the gaps
|
||||||
|
int32_t nextVertInsertPoint = 0;
|
||||||
|
uint32_t nextIdxInsertPoint = 0;
|
||||||
|
for (auto& mesh : meshOrder)
|
||||||
|
{
|
||||||
|
// Check if already in the correct place
|
||||||
|
if (nextVertInsertPoint != mesh->FirstVertex)
|
||||||
|
{
|
||||||
|
/* There's a gap, we need to shift */
|
||||||
|
// Vertices
|
||||||
|
vertPosStorage.erase(vertPosStorage.begin() + nextVertInsertPoint, vertPosStorage.begin() + mesh->FirstVertex);
|
||||||
|
vertTexCoordStorage.erase(vertTexCoordStorage.begin() + nextVertInsertPoint, vertTexCoordStorage.begin() + mesh->FirstVertex);
|
||||||
|
vertTangentStorage.erase(vertTangentStorage.begin() + nextVertInsertPoint, vertTangentStorage.begin() + mesh->FirstVertex);
|
||||||
|
vertNormalStorage.erase(vertNormalStorage.begin() + nextVertInsertPoint, vertNormalStorage.begin() + mesh->FirstVertex);
|
||||||
|
vertBoneIdxStorage.erase(vertBoneIdxStorage.begin() + nextVertInsertPoint, vertBoneIdxStorage.begin() + mesh->FirstVertex);
|
||||||
|
vertBoneWeightStorage.erase(vertBoneWeightStorage.begin() + nextVertInsertPoint, vertBoneWeightStorage.begin() + mesh->FirstVertex);
|
||||||
|
// - Update mesh data
|
||||||
|
mesh->FirstVertex = nextVertInsertPoint;
|
||||||
|
|
||||||
|
// Indices
|
||||||
|
indexStorage.erase(indexStorage.begin() + nextIdxInsertPoint, indexStorage.begin() + mesh->FirstIndex);
|
||||||
|
// - Update mesh data
|
||||||
|
mesh->FirstIndex = nextIdxInsertPoint;
|
||||||
|
|
||||||
|
// Prepare for next
|
||||||
|
nextVertInsertPoint += mesh->VertexCount;
|
||||||
|
nextIdxInsertPoint += mesh->IndexCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHMeshLibrary::BuildBuffers(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer)
|
// Add
|
||||||
|
if (!meshAddJobs.empty())
|
||||||
{
|
{
|
||||||
// No changes
|
// - Compute updated size
|
||||||
if (!isDirty)
|
size_t newVertElems = vertPosStorage.size();
|
||||||
return;
|
size_t newIdxElems = indexStorage.size();
|
||||||
|
for (const auto& addJob : meshAddJobs)
|
||||||
// Remove
|
{
|
||||||
if (!meshRemoveJobs.empty())
|
newVertElems += addJob.VertexCount;
|
||||||
|
newIdxElems += addJob.IndexCount;
|
||||||
|
}
|
||||||
|
// - Reserve new memory
|
||||||
|
vertPosStorage.reserve(newVertElems);
|
||||||
|
vertTexCoordStorage.reserve(newVertElems);
|
||||||
|
vertTangentStorage.reserve(newVertElems);
|
||||||
|
vertNormalStorage.reserve(newVertElems);
|
||||||
|
vertBoneIdxStorage.reserve(newVertElems);
|
||||||
|
vertBoneWeightStorage.reserve(newVertElems);
|
||||||
|
indexStorage.reserve(newIdxElems);
|
||||||
|
// - Append new data
|
||||||
|
for (auto& addJob : meshAddJobs)
|
||||||
|
{
|
||||||
|
// Update handle
|
||||||
|
SHMesh& meshData = *addJob.Handle;
|
||||||
|
meshData = SHMesh
|
||||||
{
|
{
|
||||||
// - Remove from order list
|
.FirstVertex = static_cast<int32_t>(vertPosStorage.size()),
|
||||||
for (const auto& meshToRemove : meshRemoveJobs)
|
.VertexCount = static_cast<uint32_t>(addJob.VertexCount),
|
||||||
{
|
.FirstIndex = static_cast<uint32_t>(indexStorage.size()),
|
||||||
auto searchResult = std::find(meshOrder.begin(), meshOrder.end(), meshToRemove);
|
.IndexCount = static_cast<uint32_t>(addJob.IndexCount),
|
||||||
// Shouldn't happen, ignore
|
.BoneCount = addJob.BoneCount
|
||||||
if (searchResult == meshOrder.end())
|
};
|
||||||
continue;
|
|
||||||
|
|
||||||
// Remove from mesh list
|
// Copy into storage
|
||||||
meshOrder.erase(searchResult);
|
vertPosStorage.insert
|
||||||
}
|
(
|
||||||
meshRemoveJobs.clear();
|
vertPosStorage.end(),
|
||||||
// - Shift existing elements in to close up the gaps
|
addJob.VertexPositions, addJob.VertexPositions + addJob.VertexCount
|
||||||
int32_t nextVertInsertPoint = 0;
|
);
|
||||||
uint32_t nextIdxInsertPoint = 0;
|
vertTexCoordStorage.insert
|
||||||
for (auto& mesh : meshOrder)
|
(
|
||||||
{
|
vertTexCoordStorage.end(),
|
||||||
// Check if already in the correct place
|
addJob.VertexTexCoords, addJob.VertexTexCoords + addJob.VertexCount
|
||||||
if (nextVertInsertPoint != mesh->FirstVertex)
|
);
|
||||||
{
|
vertTangentStorage.insert
|
||||||
/* There's a gap, we need to shift */
|
(
|
||||||
// Vertices
|
vertTangentStorage.end(),
|
||||||
vertPosStorage.erase(vertPosStorage.begin() + nextVertInsertPoint, vertPosStorage.begin() + mesh->FirstVertex);
|
addJob.VertexTangents, addJob.VertexTangents + addJob.VertexCount
|
||||||
vertTexCoordStorage.erase(vertTexCoordStorage.begin() + nextVertInsertPoint, vertTexCoordStorage.begin() + mesh->FirstVertex);
|
);
|
||||||
vertTangentStorage.erase(vertTangentStorage.begin() + nextVertInsertPoint, vertTangentStorage.begin() + mesh->FirstVertex);
|
vertNormalStorage.insert
|
||||||
vertNormalStorage.erase(vertNormalStorage.begin() + nextVertInsertPoint, vertNormalStorage.begin() + mesh->FirstVertex);
|
(
|
||||||
// - Update mesh data
|
vertNormalStorage.end(),
|
||||||
mesh->FirstVertex = nextVertInsertPoint;
|
addJob.VertexNormals, addJob.VertexNormals + addJob.VertexCount
|
||||||
|
);
|
||||||
// Indices
|
if (addJob.VertexBoneIndices)
|
||||||
indexStorage.erase(indexStorage.begin() + nextIdxInsertPoint, indexStorage.begin() + mesh->FirstIndex);
|
|
||||||
// - Update mesh data
|
|
||||||
mesh->FirstIndex = nextIdxInsertPoint;
|
|
||||||
|
|
||||||
// Prepare for next
|
|
||||||
nextVertInsertPoint += mesh->VertexCount;
|
|
||||||
nextIdxInsertPoint += mesh->IndexCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add
|
|
||||||
if (!meshAddJobs.empty())
|
|
||||||
{
|
{
|
||||||
// - Compute updated size
|
vertBoneIdxStorage.insert
|
||||||
size_t newVertElems = vertPosStorage.size();
|
(
|
||||||
size_t newIdxElems = indexStorage.size();
|
vertBoneIdxStorage.end(),
|
||||||
for (const auto& addJob : meshAddJobs)
|
addJob.VertexBoneIndices, addJob.VertexBoneIndices + addJob.VertexCount
|
||||||
{
|
);
|
||||||
newVertElems += addJob.VertexCount;
|
|
||||||
newIdxElems += addJob.IndexCount;
|
|
||||||
}
|
|
||||||
// - Reserve new memory
|
|
||||||
vertPosStorage .reserve(newVertElems);
|
|
||||||
vertTexCoordStorage.reserve(newVertElems);
|
|
||||||
vertTangentStorage .reserve(newVertElems);
|
|
||||||
vertNormalStorage .reserve(newVertElems);
|
|
||||||
indexStorage .reserve(newIdxElems);
|
|
||||||
// - Append new data
|
|
||||||
for (auto& addJob : meshAddJobs)
|
|
||||||
{
|
|
||||||
// Update handle
|
|
||||||
SHMesh& meshData = *addJob.Handle;
|
|
||||||
meshData = SHMesh
|
|
||||||
{
|
|
||||||
.FirstVertex = static_cast<int32_t>(vertPosStorage.size()),
|
|
||||||
.VertexCount = static_cast<uint32_t>(addJob.VertexCount),
|
|
||||||
.FirstIndex = static_cast<uint32_t>(indexStorage.size()),
|
|
||||||
.IndexCount = static_cast<uint32_t>(addJob.IndexCount),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Copy into storage
|
|
||||||
vertPosStorage.insert
|
|
||||||
(
|
|
||||||
vertPosStorage.end(),
|
|
||||||
addJob.VertexPositions, addJob.VertexPositions + addJob.VertexCount
|
|
||||||
);
|
|
||||||
vertTexCoordStorage.insert
|
|
||||||
(
|
|
||||||
vertTexCoordStorage.end(),
|
|
||||||
addJob.VertexTexCoords, addJob.VertexTexCoords + addJob.VertexCount
|
|
||||||
);
|
|
||||||
vertTangentStorage.insert
|
|
||||||
(
|
|
||||||
vertTangentStorage.end(),
|
|
||||||
addJob.VertexTangents, addJob.VertexTangents + addJob.VertexCount
|
|
||||||
);
|
|
||||||
vertNormalStorage.insert
|
|
||||||
(
|
|
||||||
vertNormalStorage.end(),
|
|
||||||
addJob.VertexNormals, addJob.VertexNormals + addJob.VertexCount
|
|
||||||
);
|
|
||||||
indexStorage.insert
|
|
||||||
(
|
|
||||||
indexStorage.end(),
|
|
||||||
addJob.Indices, addJob.Indices + addJob.IndexCount
|
|
||||||
);
|
|
||||||
}
|
|
||||||
meshAddJobs.clear();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Send to GPU
|
{
|
||||||
using BuffUsage = vk::BufferUsageFlagBits;
|
vertBoneIdxStorage.resize(vertBoneIdxStorage.size() + addJob.VertexCount);
|
||||||
SHVkUtil::EnsureBufferAndCopyData
|
}
|
||||||
(
|
if (addJob.VertexBoneWeights)
|
||||||
device, cmdBuffer, vertPosBuffer,
|
{
|
||||||
vertPosStorage.data(),
|
vertBoneWeightStorage.insert
|
||||||
static_cast<uint32_t>(vertPosStorage.size()) * sizeof(SHMesh::VertexPosition),
|
(
|
||||||
BuffUsage::eVertexBuffer,
|
vertBoneWeightStorage.end(),
|
||||||
"Mesh Library Vertex Positions"
|
addJob.VertexBoneWeights, addJob.VertexBoneWeights + addJob.VertexCount
|
||||||
);
|
);
|
||||||
SHVkUtil::EnsureBufferAndCopyData
|
}
|
||||||
(
|
else
|
||||||
device, cmdBuffer, vertTexCoordBuffer,
|
{
|
||||||
vertTexCoordStorage.data(),
|
const auto OG_SIZE = vertBoneWeightStorage.size();
|
||||||
static_cast<uint32_t>(vertTexCoordStorage.size()) * sizeof(SHMesh::VertexTexCoord),
|
vertBoneWeightStorage.resize(vertBoneWeightStorage.size() + addJob.VertexCount);
|
||||||
BuffUsage::eVertexBuffer,
|
std::fill_n(vertBoneWeightStorage.begin() + OG_SIZE, addJob.VertexCount, SHVec4(1.0f, 0.0f, 0.0f, 0.0f));
|
||||||
"Mesh Library Vertex TexCoords"
|
}
|
||||||
);
|
indexStorage.insert
|
||||||
SHVkUtil::EnsureBufferAndCopyData
|
(
|
||||||
(
|
indexStorage.end(),
|
||||||
device, cmdBuffer, vertTangentBuffer,
|
addJob.Indices, addJob.Indices + addJob.IndexCount
|
||||||
vertTangentStorage.data(),
|
);
|
||||||
static_cast<uint32_t>(vertTangentStorage.size()) * sizeof(SHMesh::VertexTangent),
|
}
|
||||||
BuffUsage::eVertexBuffer,
|
meshAddJobs.clear();
|
||||||
"Mesh Library Vertex Tangents"
|
|
||||||
);
|
|
||||||
SHVkUtil::EnsureBufferAndCopyData
|
|
||||||
(
|
|
||||||
device, cmdBuffer, vertNormalBuffer,
|
|
||||||
vertNormalStorage.data(),
|
|
||||||
static_cast<uint32_t>(vertNormalStorage.size()) * sizeof(SHMesh::VertexNormal),
|
|
||||||
BuffUsage::eVertexBuffer,
|
|
||||||
"Mesh Library Vertex Normals"
|
|
||||||
);
|
|
||||||
SHVkUtil::EnsureBufferAndCopyData
|
|
||||||
(
|
|
||||||
device, cmdBuffer, indexBuffer,
|
|
||||||
indexStorage.data(),
|
|
||||||
static_cast<uint32_t>(indexStorage.size()) * sizeof(SHMesh::Index),
|
|
||||||
BuffUsage::eIndexBuffer,
|
|
||||||
"Mesh Library Indices"
|
|
||||||
);
|
|
||||||
|
|
||||||
isDirty = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send to GPU
|
||||||
|
using BuffUsage = vk::BufferUsageFlagBits;
|
||||||
|
SHVkUtil::EnsureBufferAndCopyData
|
||||||
|
(
|
||||||
|
device, cmdBuffer, vertPosBuffer,
|
||||||
|
vertPosStorage.data(),
|
||||||
|
static_cast<uint32_t>(vertPosStorage.size()) * sizeof(SHMesh::VertexPosition),
|
||||||
|
BuffUsage::eVertexBuffer,
|
||||||
|
"Mesh Library Vertex Positions"
|
||||||
|
);
|
||||||
|
SHVkUtil::EnsureBufferAndCopyData
|
||||||
|
(
|
||||||
|
device, cmdBuffer, vertTexCoordBuffer,
|
||||||
|
vertTexCoordStorage.data(),
|
||||||
|
static_cast<uint32_t>(vertTexCoordStorage.size()) * sizeof(SHMesh::VertexTexCoord),
|
||||||
|
BuffUsage::eVertexBuffer,
|
||||||
|
"Mesh Library Vertex TexCoords"
|
||||||
|
);
|
||||||
|
SHVkUtil::EnsureBufferAndCopyData
|
||||||
|
(
|
||||||
|
device, cmdBuffer, vertTangentBuffer,
|
||||||
|
vertTangentStorage.data(),
|
||||||
|
static_cast<uint32_t>(vertTangentStorage.size()) * sizeof(SHMesh::VertexTangent),
|
||||||
|
BuffUsage::eVertexBuffer,
|
||||||
|
"Mesh Library Vertex Tangents"
|
||||||
|
);
|
||||||
|
SHVkUtil::EnsureBufferAndCopyData
|
||||||
|
(
|
||||||
|
device, cmdBuffer, vertNormalBuffer,
|
||||||
|
vertNormalStorage.data(),
|
||||||
|
static_cast<uint32_t>(vertNormalStorage.size()) * sizeof(SHMesh::VertexNormal),
|
||||||
|
BuffUsage::eVertexBuffer,
|
||||||
|
"Mesh Library Vertex Normals"
|
||||||
|
);
|
||||||
|
if (!vertBoneIdxStorage.empty())
|
||||||
|
{
|
||||||
|
SHVkUtil::EnsureBufferAndCopyData
|
||||||
|
(
|
||||||
|
device, cmdBuffer, vertBoneIdxBuffer,
|
||||||
|
vertBoneIdxStorage.data(),
|
||||||
|
static_cast<uint32_t>(vertBoneIdxStorage.size()) * sizeof(SHMesh::VertexBoneIndices),
|
||||||
|
BuffUsage::eVertexBuffer,
|
||||||
|
"Mesh Library Vertex Bone Indices"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!vertBoneWeightStorage.empty())
|
||||||
|
{
|
||||||
|
SHVkUtil::EnsureBufferAndCopyData
|
||||||
|
(
|
||||||
|
device, cmdBuffer, vertBoneWeightBuffer,
|
||||||
|
vertBoneWeightStorage.data(),
|
||||||
|
static_cast<uint32_t>(vertBoneWeightStorage.size()) * sizeof(SHMesh::VertexWeights),
|
||||||
|
BuffUsage::eVertexBuffer,
|
||||||
|
"Mesh Library Vertex Bone Weights"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
SHVkUtil::EnsureBufferAndCopyData
|
||||||
|
(
|
||||||
|
device, cmdBuffer, indexBuffer,
|
||||||
|
indexStorage.data(),
|
||||||
|
static_cast<uint32_t>(indexStorage.size()) * sizeof(SHMesh::Index),
|
||||||
|
BuffUsage::eIndexBuffer,
|
||||||
|
"Mesh Library Indices"
|
||||||
|
);
|
||||||
|
|
||||||
|
isDirty = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,170 +19,191 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Resource/SHResourceLibrary.h"
|
#include "Resource/SHResourceLibrary.h"
|
||||||
#include "Math/Vector/SHVec2.h"
|
#include "Math/Vector/SHVec2.h"
|
||||||
#include "Math/Vector/SHVec3.h"
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
#include "Math/Vector/SHVec4U.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Forward Declarations */
|
/* Forward Declarations */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
class SHVkBuffer;
|
class SHVkBuffer;
|
||||||
class SHVkLogicalDevice;
|
class SHVkLogicalDevice;
|
||||||
class SHVkCommandBuffer;
|
class SHVkCommandBuffer;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
\brief
|
||||||
|
Represents a single mesh that is stored in a SHMeshLibrary.
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
class SHMesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
using Index = uint32_t;
|
||||||
|
using VertexPosition = SHVec3;
|
||||||
|
using VertexTexCoord = SHVec2;
|
||||||
|
using VertexTangent = SHVec3;
|
||||||
|
using VertexNormal = SHVec3;
|
||||||
|
using VertexBoneIndices = SHVec4U;
|
||||||
|
using VertexWeights = SHVec4;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
int32_t FirstVertex;
|
||||||
|
uint32_t VertexCount;
|
||||||
|
uint32_t FirstIndex;
|
||||||
|
uint32_t IndexCount;
|
||||||
|
uint32_t BoneCount;
|
||||||
|
};
|
||||||
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
\brief
|
||||||
|
Manages storage for all Meshes in the Graphics System as a single set of Vertex
|
||||||
|
and Index Buffers.
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
class SHMeshLibrary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/*******************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
\brief
|
|
||||||
Represents a single mesh that is stored in a SHMeshLibrary.
|
|
||||||
*/
|
|
||||||
/***********************************************************************************/
|
|
||||||
class SHMesh
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
using Index = uint32_t;
|
|
||||||
using VertexPosition = SHVec3;
|
|
||||||
using VertexTexCoord = SHVec2;
|
|
||||||
using VertexTangent = SHVec3;
|
|
||||||
using VertexNormal = SHVec3;
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
\brief
|
||||||
/* Data Members */
|
Adds a mesh to the Mesh Library. But this does not mean that the meshes have
|
||||||
/*-----------------------------------------------------------------------------*/
|
been added yet. A call to "BuildBuffers()" is required to transfer all
|
||||||
int32_t FirstVertex;
|
meshes into the GPU.
|
||||||
uint32_t VertexCount;
|
|
||||||
uint32_t FirstIndex;
|
\param vertexCount
|
||||||
uint32_t IndexCount;
|
Number of vertices in this Mesh.
|
||||||
};
|
\param positions
|
||||||
/***********************************************************************************/
|
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
|
||||||
|
positions.
|
||||||
|
\param texCoords
|
||||||
|
Pointer to the first in a contiguous array of SHMathVec2s that define vertex
|
||||||
|
texture coordinates.
|
||||||
|
\param tangents
|
||||||
|
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
|
||||||
|
tangents.
|
||||||
|
\param normals
|
||||||
|
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
|
||||||
|
normals.
|
||||||
|
\param indexCount
|
||||||
|
Number of indices in this mesh.
|
||||||
|
\param indices
|
||||||
|
Pointer to the first in a contiguous array of uint32_ts that define mesh
|
||||||
|
indicies.
|
||||||
|
|
||||||
|
\return
|
||||||
|
Handle to the created Mesh. This is not valid to be used until a call to
|
||||||
|
BuildBuffers().
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*******************************************************************************/
|
||||||
|
Handle<SHMesh> AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions,
|
||||||
|
const SHMesh::VertexTexCoord* const texCoords,
|
||||||
|
const SHMesh::VertexTangent* const tangents,
|
||||||
|
const SHMesh::VertexNormal* const normals,
|
||||||
|
const SHMesh::VertexBoneIndices* const boneIndices,
|
||||||
|
const SHMesh::VertexWeights* const boneWeights,
|
||||||
|
uint32_t indexCount, const SHMesh::Index* const indices,
|
||||||
|
uint32_t boneCount);
|
||||||
|
/*******************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
\brief
|
|
||||||
Manages storage for all Meshes in the Graphics System as a single set of Vertex
|
\brief
|
||||||
and Index Buffers.
|
Removes a mesh from the MeshLibrary. But this does not mean that the meshes
|
||||||
|
have been removed yet. A call to "BuildBuffers()" is required to finalise all
|
||||||
|
changes.
|
||||||
|
|
||||||
|
\param mesh
|
||||||
|
Handle to the mesh to remove.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
/***********************************************************************************/
|
/*******************************************************************************/
|
||||||
class SHMeshLibrary
|
void RemoveMesh(Handle<SHMesh> mesh);
|
||||||
|
/***************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Finalises all changes to the MeshLibrary into the GPU buffers.
|
||||||
|
|
||||||
|
\param device
|
||||||
|
Device used to create and update the buffers.
|
||||||
|
\param cmdBuffer
|
||||||
|
Command buffer used to set up transfers of data in the GPU memory. This
|
||||||
|
call must be preceded by calls to cmdBuffer's BeginRecording() and ended
|
||||||
|
with EndRecording(). Do recall to also submit the cmdBuffer to a transfer
|
||||||
|
queue.
|
||||||
|
*/
|
||||||
|
/***************************************************************************/
|
||||||
|
void BuildBuffers(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Getter Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
Handle<SHVkBuffer> GetVertexPositionsBuffer() const noexcept { return vertPosBuffer; }
|
||||||
|
Handle<SHVkBuffer> GetVertexTexCoordsBuffer() const noexcept { return vertTexCoordBuffer; }
|
||||||
|
Handle<SHVkBuffer> GetVertexTangentsBuffer() const noexcept { return vertTangentBuffer; }
|
||||||
|
Handle<SHVkBuffer> GetVertexNormalsBuffer() const noexcept { return vertNormalBuffer; }
|
||||||
|
Handle<SHVkBuffer> GetVertexBoneIndicesBuffer() const noexcept { return vertBoneIdxBuffer; }
|
||||||
|
Handle<SHVkBuffer> GetVertexBoneWeightsBuffer() const noexcept { return vertBoneWeightBuffer; }
|
||||||
|
Handle<SHVkBuffer> GetIndexBuffer() const noexcept { return indexBuffer; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Type Definition */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
struct MeshAddJob
|
||||||
{
|
{
|
||||||
public:
|
uint32_t VertexCount = 0;
|
||||||
/*-----------------------------------------------------------------------------*/
|
const SHMesh::VertexPosition* VertexPositions = nullptr;
|
||||||
/* Usage Functions */
|
const SHMesh::VertexTexCoord* VertexTexCoords = nullptr;
|
||||||
/*-----------------------------------------------------------------------------*/
|
const SHMesh::VertexTangent* VertexTangents = nullptr;
|
||||||
/*******************************************************************************/
|
const SHMesh::VertexNormal* VertexNormals = nullptr;
|
||||||
/*!
|
const SHMesh::VertexBoneIndices* VertexBoneIndices = nullptr;
|
||||||
|
const SHMesh::VertexWeights* VertexBoneWeights = nullptr;
|
||||||
\brief
|
uint32_t IndexCount = 0;
|
||||||
Adds a mesh to the Mesh Library. But this does not mean that the meshes have
|
const SHMesh::Index* Indices = nullptr;
|
||||||
been added yet. A call to "BuildBuffers()" is required to transfer all
|
uint32_t BoneCount = 0;
|
||||||
meshes into the GPU.
|
Handle<SHMesh> Handle;
|
||||||
|
|
||||||
\param vertexCount
|
|
||||||
Number of vertices in this Mesh.
|
|
||||||
\param positions
|
|
||||||
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
|
|
||||||
positions.
|
|
||||||
\param texCoords
|
|
||||||
Pointer to the first in a contiguous array of SHMathVec2s that define vertex
|
|
||||||
texture coordinates.
|
|
||||||
\param tangents
|
|
||||||
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
|
|
||||||
tangents.
|
|
||||||
\param normals
|
|
||||||
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
|
|
||||||
normals.
|
|
||||||
\param indexCount
|
|
||||||
Number of indices in this mesh.
|
|
||||||
\param indices
|
|
||||||
Pointer to the first in a contiguous array of uint32_ts that define mesh
|
|
||||||
indicies.
|
|
||||||
|
|
||||||
\return
|
|
||||||
Handle to the created Mesh. This is not valid to be used until a call to
|
|
||||||
BuildBuffers().
|
|
||||||
|
|
||||||
*/
|
|
||||||
/*******************************************************************************/
|
|
||||||
Handle<SHMesh> AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices);
|
|
||||||
/*******************************************************************************/
|
|
||||||
/*!
|
|
||||||
|
|
||||||
\brief
|
|
||||||
Removes a mesh from the MeshLibrary. But this does not mean that the meshes
|
|
||||||
have been removed yet. A call to "BuildBuffers()" is required to finalise all
|
|
||||||
changes.
|
|
||||||
|
|
||||||
\param mesh
|
|
||||||
Handle to the mesh to remove.
|
|
||||||
|
|
||||||
*/
|
|
||||||
/*******************************************************************************/
|
|
||||||
void RemoveMesh(Handle<SHMesh> mesh);
|
|
||||||
/***************************************************************************/
|
|
||||||
/*!
|
|
||||||
|
|
||||||
\brief
|
|
||||||
Finalises all changes to the MeshLibrary into the GPU buffers.
|
|
||||||
|
|
||||||
\param device
|
|
||||||
Device used to create and update the buffers.
|
|
||||||
\param cmdBuffer
|
|
||||||
Command buffer used to set up transfers of data in the GPU memory. This
|
|
||||||
call must be preceded by calls to cmdBuffer's BeginRecording() and ended
|
|
||||||
with EndRecording(). Do recall to also submit the cmdBuffer to a transfer
|
|
||||||
queue.
|
|
||||||
*/
|
|
||||||
/***************************************************************************/
|
|
||||||
void BuildBuffers(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer);
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
/* Getter Functions */
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
Handle<SHVkBuffer> GetVertexPositionsBuffer() const noexcept { return vertPosBuffer; }
|
|
||||||
Handle<SHVkBuffer> GetVertexTexCoordsBuffer() const noexcept { return vertTexCoordBuffer; }
|
|
||||||
Handle<SHVkBuffer> GetVertexTangentsBuffer() const noexcept { return vertTangentBuffer; }
|
|
||||||
Handle<SHVkBuffer> GetVertexNormalsBuffer() const noexcept { return vertNormalBuffer; }
|
|
||||||
Handle<SHVkBuffer> GetIndexBuffer() const { return indexBuffer; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
/* Type Definition */
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
struct MeshAddJob
|
|
||||||
{
|
|
||||||
uint32_t VertexCount = 0;
|
|
||||||
const SHMesh::VertexPosition* VertexPositions = nullptr;
|
|
||||||
const SHMesh::VertexTexCoord* VertexTexCoords = nullptr;
|
|
||||||
const SHMesh::VertexTangent * VertexTangents = nullptr;
|
|
||||||
const SHMesh::VertexNormal * VertexNormals = nullptr;
|
|
||||||
uint32_t IndexCount = 0;
|
|
||||||
const SHMesh::Index * Indices = nullptr;
|
|
||||||
Handle<SHMesh> Handle;
|
|
||||||
};
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
// Manipulation Queues
|
|
||||||
std::vector<MeshAddJob> meshAddJobs;
|
|
||||||
std::vector<Handle<SHMesh>> meshRemoveJobs;
|
|
||||||
// Tracking
|
|
||||||
SHResourceLibrary<SHMesh> meshes{};
|
|
||||||
std::vector<Handle<SHMesh>> meshOrder;
|
|
||||||
// CPU Storage
|
|
||||||
std::vector<SHMesh::VertexPosition> vertPosStorage;
|
|
||||||
std::vector<SHMesh::VertexTexCoord> vertTexCoordStorage;
|
|
||||||
std::vector<SHMesh::VertexTangent> vertTangentStorage;
|
|
||||||
std::vector<SHMesh::VertexNormal> vertNormalStorage;
|
|
||||||
std::vector<SHMesh::Index> indexStorage;
|
|
||||||
// GPU Storage
|
|
||||||
Handle<SHVkBuffer> vertPosBuffer{};
|
|
||||||
Handle<SHVkBuffer> vertTexCoordBuffer{};
|
|
||||||
Handle<SHVkBuffer> vertTangentBuffer{};
|
|
||||||
Handle<SHVkBuffer> vertNormalBuffer{};
|
|
||||||
Handle<SHVkBuffer> indexBuffer {};
|
|
||||||
// Flags
|
|
||||||
bool isDirty = true;
|
|
||||||
};
|
};
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
// Manipulation Queues
|
||||||
|
std::vector<MeshAddJob> meshAddJobs;
|
||||||
|
std::vector<Handle<SHMesh>> meshRemoveJobs;
|
||||||
|
// Tracking
|
||||||
|
SHResourceLibrary<SHMesh> meshes;
|
||||||
|
std::vector<Handle<SHMesh>> meshOrder;
|
||||||
|
// CPU Storage
|
||||||
|
std::vector<SHMesh::VertexPosition> vertPosStorage;
|
||||||
|
std::vector<SHMesh::VertexTexCoord> vertTexCoordStorage;
|
||||||
|
std::vector<SHMesh::VertexTangent> vertTangentStorage;
|
||||||
|
std::vector<SHMesh::VertexNormal> vertNormalStorage;
|
||||||
|
std::vector<SHMesh::VertexBoneIndices> vertBoneIdxStorage; // Must be in multiples of 4
|
||||||
|
std::vector<SHMesh::VertexWeights> vertBoneWeightStorage;
|
||||||
|
std::vector<SHMesh::Index> indexStorage;
|
||||||
|
// GPU Storage
|
||||||
|
Handle<SHVkBuffer> vertPosBuffer{};
|
||||||
|
Handle<SHVkBuffer> vertTexCoordBuffer{};
|
||||||
|
Handle<SHVkBuffer> vertTangentBuffer{};
|
||||||
|
Handle<SHVkBuffer> vertNormalBuffer{};
|
||||||
|
Handle<SHVkBuffer> vertBoneIdxBuffer{};
|
||||||
|
Handle<SHVkBuffer> vertBoneWeightBuffer{};
|
||||||
|
Handle<SHVkBuffer> indexBuffer{};
|
||||||
|
// Flags
|
||||||
|
bool isDirty = true;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,18 +25,18 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Static Member Definitions */
|
/* Static Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
SHMeshData SHPrimitiveGenerator::cubeMesh;
|
SHMeshAsset SHPrimitiveGenerator::cubeMesh;
|
||||||
SHMeshData SHPrimitiveGenerator::sphereMesh;
|
SHMeshAsset SHPrimitiveGenerator::sphereMesh;
|
||||||
SHMeshData SHPrimitiveGenerator::lineCubeMesh;
|
SHMeshAsset SHPrimitiveGenerator::lineCubeMesh;
|
||||||
SHMeshData SHPrimitiveGenerator::lineCircleMesh;
|
SHMeshAsset SHPrimitiveGenerator::lineCircleMesh;
|
||||||
SHMeshData SHPrimitiveGenerator::lineCapsuleCapMesh;
|
SHMeshAsset SHPrimitiveGenerator::lineCapsuleCapMesh;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Primitive Generation Functions */
|
/* Primitive Generation Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
SHMeshData SHPrimitiveGenerator::Cube() noexcept
|
SHMeshAsset SHPrimitiveGenerator::Cube() noexcept
|
||||||
{
|
{
|
||||||
SHMeshData mesh;
|
SHMeshAsset mesh;
|
||||||
|
|
||||||
mesh.VertexPositions =
|
mesh.VertexPositions =
|
||||||
{
|
{
|
||||||
|
@ -221,9 +221,9 @@ namespace SHADE
|
||||||
return addMeshDataTo(cubeMesh, gfxSystem);
|
return addMeshDataTo(cubeMesh, gfxSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMeshData SHPrimitiveGenerator::Sphere() noexcept
|
SHMeshAsset SHPrimitiveGenerator::Sphere() noexcept
|
||||||
{
|
{
|
||||||
SHMeshData meshData;
|
SHMeshAsset meshData;
|
||||||
|
|
||||||
const int LAT_SLICES = 12;
|
const int LAT_SLICES = 12;
|
||||||
const int LONG_SLICES = 12;
|
const int LONG_SLICES = 12;
|
||||||
|
@ -288,9 +288,9 @@ namespace SHADE
|
||||||
return addMeshDataTo(sphereMesh, gfxSystem);
|
return addMeshDataTo(sphereMesh, gfxSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMeshData SHPrimitiveGenerator::LineCube() noexcept
|
SHMeshAsset SHPrimitiveGenerator::LineCube() noexcept
|
||||||
{
|
{
|
||||||
SHMeshData mesh;
|
SHMeshAsset mesh;
|
||||||
|
|
||||||
mesh.VertexPositions =
|
mesh.VertexPositions =
|
||||||
{
|
{
|
||||||
|
@ -347,9 +347,9 @@ namespace SHADE
|
||||||
return addMeshDataTo(lineCubeMesh, gfxSystem);
|
return addMeshDataTo(lineCubeMesh, gfxSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMeshData SHPrimitiveGenerator::LineCircle() noexcept
|
SHMeshAsset SHPrimitiveGenerator::LineCircle() noexcept
|
||||||
{
|
{
|
||||||
SHMeshData mesh;
|
SHMeshAsset mesh;
|
||||||
|
|
||||||
// Generate points of the circle
|
// Generate points of the circle
|
||||||
static constexpr int SPLITS = 36;
|
static constexpr int SPLITS = 36;
|
||||||
|
@ -393,9 +393,9 @@ namespace SHADE
|
||||||
return addMeshDataTo(lineCircleMesh, gfxSystem);
|
return addMeshDataTo(lineCircleMesh, gfxSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHADE::SHMeshData SHPrimitiveGenerator::LineCapsuleCap() noexcept
|
SHMeshAsset SHPrimitiveGenerator::LineCapsuleCap() noexcept
|
||||||
{
|
{
|
||||||
SHMeshData mesh;
|
SHMeshAsset mesh;
|
||||||
|
|
||||||
// Have multiple semi-circles for the cap
|
// Have multiple semi-circles for the cap
|
||||||
static constexpr int SPLITS = 36;
|
static constexpr int SPLITS = 36;
|
||||||
|
@ -454,7 +454,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
SHADE::Handle<SHADE::SHMesh> SHPrimitiveGenerator::addMeshDataTo(const SHMeshData& meshData, SHMeshLibrary& meshLibrary) noexcept
|
SHADE::Handle<SHADE::SHMesh> SHPrimitiveGenerator::addMeshDataTo(const SHMeshAsset& meshData, SHMeshLibrary& meshLibrary) noexcept
|
||||||
{
|
{
|
||||||
return meshLibrary.AddMesh
|
return meshLibrary.AddMesh
|
||||||
(
|
(
|
||||||
|
@ -463,12 +463,15 @@ namespace SHADE
|
||||||
meshData.VertexTexCoords.data(),
|
meshData.VertexTexCoords.data(),
|
||||||
meshData.VertexTangents.data(),
|
meshData.VertexTangents.data(),
|
||||||
meshData.VertexNormals.data(),
|
meshData.VertexNormals.data(),
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
static_cast<uint32_t>(meshData.Indices.size()),
|
static_cast<uint32_t>(meshData.Indices.size()),
|
||||||
meshData.Indices.data()
|
meshData.Indices.data(),
|
||||||
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHADE::Handle<SHADE::SHMesh> SHPrimitiveGenerator::addMeshDataTo(const SHMeshData& meshData, SHGraphicsSystem& gfxSystem) noexcept
|
SHADE::Handle<SHADE::SHMesh> SHPrimitiveGenerator::addMeshDataTo(const SHMeshAsset& meshData, SHGraphicsSystem& gfxSystem) noexcept
|
||||||
{
|
{
|
||||||
return gfxSystem.AddMesh
|
return gfxSystem.AddMesh
|
||||||
(
|
(
|
||||||
|
|
|
@ -12,10 +12,11 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Math/SHMath.h"
|
|
||||||
#include "Assets/Asset Types/SHModelAsset.h"
|
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
|
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
#include "Math/SHMath.h"
|
||||||
|
#include "Assets/Asset Types/Models/SHModelAsset.h"
|
||||||
|
#include "Assets/Asset Types/Models/SHMeshAsset.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -47,13 +48,13 @@ namespace SHADE
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
\brief
|
\brief
|
||||||
Produces a cube and stores the data in a SHMeshData object.
|
Produces a cube and stores the data in a SHMeshAsset object.
|
||||||
|
|
||||||
\return
|
\return
|
||||||
SHMeshData object containing vertex data for the cube.
|
SHMeshAsset object containing vertex data for the cube.
|
||||||
*/
|
*/
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
[[nodiscard]] static SHMeshData Cube() noexcept;
|
[[nodiscard]] static SHMeshAsset Cube() noexcept;
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
\brief
|
\brief
|
||||||
|
@ -83,13 +84,13 @@ namespace SHADE
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
\brief
|
\brief
|
||||||
Produces a sphere and stores the data in a SHMeshData object.
|
Produces a sphere and stores the data in a SHMeshAsset object.
|
||||||
|
|
||||||
\return
|
\return
|
||||||
SHMeshData object containing vertex data for the sphere.
|
SHMeshAsset object containing vertex data for the sphere.
|
||||||
*/
|
*/
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
[[nodiscard]] static SHMeshData Sphere() noexcept;
|
[[nodiscard]] static SHMeshAsset Sphere() noexcept;
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
\brief
|
\brief
|
||||||
|
@ -120,13 +121,13 @@ namespace SHADE
|
||||||
/*!
|
/*!
|
||||||
\brief
|
\brief
|
||||||
Produces a cube that is comprised only of lines with no diagonal lines and store
|
Produces a cube that is comprised only of lines with no diagonal lines and store
|
||||||
the data in a SHMeshData object.
|
the data in a SHMeshAsset object.
|
||||||
|
|
||||||
\return
|
\return
|
||||||
SHMeshData object containing vertex data for the line cube.
|
SHMeshAsset object containing vertex data for the line cube.
|
||||||
*/
|
*/
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
[[nodiscard]] static SHMeshData LineCube() noexcept;
|
[[nodiscard]] static SHMeshAsset LineCube() noexcept;
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
\brief
|
\brief
|
||||||
|
@ -158,13 +159,13 @@ namespace SHADE
|
||||||
/*!
|
/*!
|
||||||
\brief
|
\brief
|
||||||
Produces a circle that is comprised only of lines with no diagonal lines and
|
Produces a circle that is comprised only of lines with no diagonal lines and
|
||||||
store the data in a SHMeshData object.
|
store the data in a SHMeshAsset object.
|
||||||
|
|
||||||
\return
|
\return
|
||||||
SHMeshData object containing vertex data for the line circle.
|
SHMeshAsset object containing vertex data for the line circle.
|
||||||
*/
|
*/
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
[[nodiscard]] static SHMeshData LineCircle() noexcept;
|
[[nodiscard]] static SHMeshAsset LineCircle() noexcept;
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
\brief
|
\brief
|
||||||
|
@ -204,7 +205,7 @@ namespace SHADE
|
||||||
SHMeshData object containing vertex data for the line circle.
|
SHMeshData object containing vertex data for the line circle.
|
||||||
*/
|
*/
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
[[nodiscard]] static SHMeshData LineCapsuleCap() noexcept;
|
[[nodiscard]] static SHMeshAsset LineCapsuleCap() noexcept;
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
\brief
|
\brief
|
||||||
|
@ -239,16 +240,16 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
static Handle<SHMesh> addMeshDataTo(const SHMeshData& meshData, SHMeshLibrary& meshLibrary) noexcept;
|
static Handle<SHMesh> addMeshDataTo(const SHMeshAsset& meshData, SHMeshLibrary& meshLibrary) noexcept;
|
||||||
static Handle<SHMesh> addMeshDataTo(const SHMeshData& meshData, SHGraphicsSystem& gfxSystem) noexcept;
|
static Handle<SHMesh> addMeshDataTo(const SHMeshAsset& meshData, SHGraphicsSystem& gfxSystem) noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
static SHMeshData cubeMesh;
|
static SHMeshAsset cubeMesh;
|
||||||
static SHMeshData sphereMesh;
|
static SHMeshAsset sphereMesh;
|
||||||
static SHMeshData lineCubeMesh;
|
static SHMeshAsset lineCubeMesh;
|
||||||
static SHMeshData lineCircleMesh;
|
static SHMeshAsset lineCircleMesh;
|
||||||
static SHMeshData lineCapsuleCapMesh;
|
static SHMeshAsset lineCapsuleCapMesh;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
|
||||||
Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass, SHVertexInputState const& viState/* = SHGraphicsPredefinedData::GetDefaultViState()*/, SHRasterizationState const& rasterState) noexcept
|
Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass, SHGraphicsPredefinedData::SystemType systemType, SHVertexInputState const& viState, SHRasterizationState const& rasterState) noexcept
|
||||||
{
|
{
|
||||||
std::vector<Handle<SHVkShaderModule>> modules{};
|
std::vector<Handle<SHVkShaderModule>> modules{};
|
||||||
if (vsFsPair.first)
|
if (vsFsPair.first)
|
||||||
|
@ -17,8 +17,8 @@ namespace SHADE
|
||||||
|
|
||||||
SHPipelineLayoutParams params
|
SHPipelineLayoutParams params
|
||||||
{
|
{
|
||||||
.shaderModules = std::move(modules),
|
.shaderModules = {vsFsPair.first, vsFsPair.second},
|
||||||
.predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::BATCHING).descSetLayouts
|
.predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(systemType).descSetLayouts
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create the pipeline layout
|
// Create the pipeline layout
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace SHADE
|
||||||
std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair,
|
std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair,
|
||||||
Handle<SHVkRenderpass> renderpass,
|
Handle<SHVkRenderpass> renderpass,
|
||||||
Handle<SHSubpass> subpass,
|
Handle<SHSubpass> subpass,
|
||||||
|
SHGraphicsPredefinedData::SystemType systemType,
|
||||||
SHVertexInputState const& viState = SHGraphicsPredefinedData::GetDefaultViState(),
|
SHVertexInputState const& viState = SHGraphicsPredefinedData::GetDefaultViState(),
|
||||||
SHRasterizationState const& rasterState = SHRasterizationState{}
|
SHRasterizationState const& rasterState = SHRasterizationState{}
|
||||||
) noexcept;
|
) noexcept;
|
||||||
|
|
|
@ -565,7 +565,7 @@ namespace SHADE
|
||||||
|
|
||||||
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
|
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
|
||||||
// better way to manage these
|
// better way to manage these
|
||||||
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept
|
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool, const std::initializer_list<std::pair<Handle<SHVkBuffer>, uint32_t>> MESH_DATA) noexcept
|
||||||
{
|
{
|
||||||
auto cmdBuffer = commandBuffers[frameIndex];
|
auto cmdBuffer = commandBuffers[frameIndex];
|
||||||
cmdBuffer->BeginLabeledSegment(name);
|
cmdBuffer->BeginLabeledSegment(name);
|
||||||
|
@ -578,6 +578,7 @@ namespace SHADE
|
||||||
|
|
||||||
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||||
|
|
||||||
|
|
||||||
for (auto& node : nodes)
|
for (auto& node : nodes)
|
||||||
{
|
{
|
||||||
if (node->renderpass)
|
if (node->renderpass)
|
||||||
|
@ -585,6 +586,15 @@ namespace SHADE
|
||||||
// bind static global data
|
// bind static global data
|
||||||
SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
|
SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
|
||||||
|
|
||||||
|
// Bind all the buffers required for meshes
|
||||||
|
for (auto& [buffer, bindingPoint] : MESH_DATA)
|
||||||
|
{
|
||||||
|
if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eVertexBuffer)
|
||||||
|
cmdBuffer->BindVertexBuffer(bindingPoint, buffer, 0);
|
||||||
|
else if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eIndexBuffer)
|
||||||
|
cmdBuffer->BindIndexBuffer(buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
node->Execute(cmdBuffer, descPool, frameIndex);
|
node->Execute(cmdBuffer, descPool, frameIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue