Made it so the model load loads mtl files and textures, redid texture loading

This commit is contained in:
OusmBlueNinja 2024-12-29 22:25:16 -06:00
parent 8b44d35871
commit 17f847b561
79 changed files with 571309 additions and 637 deletions

Binary file not shown.

306
assets/models/sponza.mtl Normal file
View File

@ -0,0 +1,306 @@
# Blender MTL File: 'None'
# Material Count: 25
newmtl Material__25
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/lion.tga
map_Disp textures/lion_ddn.tga
map_Ka textures/lion.tga
newmtl Material__298
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/background.tga
map_Disp textures/background_ddn.tga
map_Ka textures/background.tga
newmtl Material__47
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
newmtl Material__57
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd textures/vase_plant.tga
map_d textures/vase_plant_mask.tga
map_Ka textures/vase_plant.tga
newmtl arch
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_arch_diff.tga
map_Ka textures/sponza_arch_diff.tga
map_Disp textures/sponza_arch_ddn.tga
newmtl bricks
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/spnza_bricks_a_diff.tga
map_Disp textures/spnza_bricks_a_ddn.tga
map_Ka textures/spnza_bricks_a_diff.tga
newmtl ceiling
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_ceiling_a_diff.tga
map_Ka textures/sponza_ceiling_a_diff.tga
map_Disp textures/sponza_ceiling_a_ddn.tga
newmtl chain
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd textures/chain_texture.tga
map_d textures/chain_texture_mask.tga
map_Disp textures/chain_texture_ddn.tga
map_Ka textures/chain_texture.tga
newmtl column_a
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_column_a_diff.tga
map_Disp textures/sponza_column_a_ddn.tga
map_Ka textures/sponza_column_a_diff.tga
newmtl column_b
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_column_b_diff.tga
map_Disp textures/sponza_column_b_ddn.tga
map_Ka textures/sponza_column_b_diff.tga
newmtl column_c
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_column_c_diff.tga
map_Disp textures/sponza_column_c_ddn.tga
map_Ka textures/sponza_column_c_diff.tga
newmtl details
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_details_diff.tga
map_Ka textures/sponza_details_diff.tga
map_Disp textures/sponza_details_ddn.tga
newmtl fabric_a
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_fabric_diff.tga
map_Ka textures/sponza_fabric_diff.tga
map_Disp textures/sponza_fabric_ddn.tga
newmtl fabric_c
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_curtain_diff.tga
map_Ka textures/sponza_curtain_diff.tga
map_Disp textures/sponza_curtain_ddn.tga
newmtl fabric_d
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_fabric_blue_diff.tga
map_Ka textures/sponza_fabric_blue_diff.tga
map_Disp textures/sponza_fabric_ddn.tga
newmtl fabric_e
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_fabric_green_diff.tga
map_Ka textures/sponza_fabric_green_diff.tga
map_Disp textures/sponza_fabric_ddn.tga
newmtl fabric_f
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_curtain_green_diff.tga
map_Ka textures/sponza_curtain_green_diff.tga
map_Disp textures/sponza_curtain_ddn.tga
newmtl fabric_g
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_curtain_blue_diff.tga
map_Ka textures/sponza_curtain_blue_diff.tga
map_Disp textures/sponza_curtain_ddn.tga
newmtl flagpole
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_flagpole_diff.tga
map_Ka textures/sponza_flagpole_diff.tga
map_Disp textures/sponza_flagpole_ddn.tga
newmtl floor
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_floor_a_diff.tga
map_Ka textures/sponza_floor_a_diff.tga
map_Disp textures/sponza_floor_a_ddn.tga
newmtl leaf
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd textures/sponza_thorn_diff.tga
map_d textures/sponza_thorn_mask.tga
map_Disp textures/sponza_thorn_ddn.tga
map_Ka textures/sponza_thorn_diff.tga
newmtl roof
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/sponza_roof_diff.tga
map_Ka textures/sponza_roof_diff.tga
map_Disp textures/sponza_roof_ddn.tga
newmtl vase
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/vase_dif.tga
map_Ka textures/vase_dif.tga
map_Disp textures/vase_ddn.tga
newmtl vase_hanging
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/vase_hanging.tga
map_Ka textures/vase_hanging.tga
map_Disp textures/vase_hanging_ddn.tga
newmtl vase_round
Ns 7.843137
Ka 0.000000 0.000000 0.000000
Kd 0.470400 0.470400 0.470400
Ks 0.000000 0.000000 0.000000
Ni 1.000000
d 0.000000
illum 2
map_Kd textures/vase_round.tga
map_Disp textures/vase_round_ddn.tga
map_Ka textures/vase_round.tga

569548
assets/models/sponza.obj Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

View File

@ -66,7 +66,7 @@ function OnUpdate(deltaTime)
-- Define the new rotation (spinning around the Y-axis) -- Define the new rotation (spinning around the Y-axis)
local rotation = { local rotation = {
x = -180, -- Preserving existing rotation on X-axis x = 0, -- Preserving existing rotation on X-axis
y = new_rotation, -- Updated rotation on Y-axis for spinning y = new_rotation, -- Updated rotation on Y-axis for spinning
z = 0 -- Preserving existing rotation on Z-axis z = 0 -- Preserving existing rotation on Z-axis
} }

View File

@ -1 +1 @@
return _T_Engine_Table return _T_Engine_Table -- This just returns the Global Table that the engine creates

View File

@ -0,0 +1,36 @@
#version 330
struct Textures {
sampler2D texture_diffuse;
sampler2D texture_specular;
sampler2D texture_normal;
// Add more as needed
};
uniform Textures uTextures;
in vec2 TexCoord;
in vec3 Normal;
in vec3 FragPos;
out vec4 FragColor;
void main()
{
// Example: Combine diffuse and specular textures
vec4 diffuseColor = texture(uTextures.texture_diffuse, TexCoord);
vec4 specularColor = texture(uTextures.texture_specular, TexCoord);
// Simple lighting calculation (for demonstration)
vec3 lightDir = normalize(vec3(0.5, 1.0, 0.3));
float diff = max(dot(Normal, lightDir), 0.0);
vec3 diffuse = diff * diffuseColor.rgb;
vec3 viewDir = normalize(-FragPos); // Assuming camera at origin
vec3 reflectDir = reflect(-lightDir, Normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = spec * specularColor.rgb;
vec3 result = diffuse + specular;
FragColor = vec4(result, diffuseColor.a);
}

View File

@ -0,0 +1,19 @@
#version 330
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCoord;
layout(location = 2) in vec3 aNormal;
uniform mat4 uMVP;
out vec2 TexCoord;
out vec3 Normal;
out vec3 FragPos;
void main()
{
gl_Position = uMVP * vec4(aPos, 1.0);
TexCoord = aTexCoord;
Normal = aNormal;
FragPos = vec3(uMVP * vec4(aPos, 1.0));
}

View File

@ -1,18 +1,48 @@
#version 330 core #version 330 core
in vec2 vUV; // UV from vertex shader // Struct to hold an array of diffuse textures
out vec4 FragColor; // Final color output struct TextureArray {
sampler2D texture_diffuse[32]; // Array of diffuse texture samplers
};
uniform vec4 uColor; // A user-set solid color // Uniforms
uniform sampler2D uTexture; // Optional texture uniform TextureArray uTextures; // Array of diffuse textures
uniform int uNumDiffuseTextures; // Number of active diffuse textures
// Input variables from the vertex shader
in vec2 TexCoords; // Texture coordinates
// Output fragment color
out vec4 FragColor;
void main() void main()
{ {
// Sample the texture. If you don't want texturing, remove this. // Define grid dimensions
vec4 texColor = texture(uTexture, vUV); const int gridCols = 8; // Number of columns in the grid
const int gridRows = 4; // Number of rows in the grid
// Multiply the texture by our uniform color. const float gridWidth = 1.0 / float(gridCols);
// If you want a pure color (no texture), just do: const float gridHeight = 1.0 / float(gridRows);
// FragColor = uColor;
FragColor = texColor * texColor; // Calculate grid cell indices based on TexCoords
int col = int(floor(TexCoords.x / gridWidth));
int row = int(floor(TexCoords.y / gridHeight));
// Clamp indices to grid boundaries to prevent out-of-range access
col = clamp(col, 0, gridCols - 1);
row = clamp(row, 0, gridRows - 1);
// Calculate texture index based on row and column
int texIndex = row * gridCols + col;
// Clamp texture index to the number of active textures
texIndex = clamp(texIndex, 0, uNumDiffuseTextures - 1);
// Calculate local texture coordinates within the grid cell
vec2 localTexCoords = fract(TexCoords / vec2(gridWidth, gridHeight));
// Sample the selected texture using localTexCoords
vec4 color = texture(uTextures.texture_diffuse[texIndex], localTexCoords);
// Set the final fragment color
FragColor = color;
} }

View File

@ -1,14 +1,30 @@
#version 330 core #version 330 core
layout(location = 0) in vec3 aPos; // Vertex position // Input vertex attributes (from the VAO)
layout(location = 1) in vec2 aUV; // Texture UV coordinate (optional) layout(location = 0) in vec3 aPos; // Vertex position
layout(location = 1) in vec3 aNormal; // Vertex normal
layout(location = 2) in vec2 aTexCoords; // Vertex texture coordinates
uniform mat4 uMVP; // Combined Model-View-Projection matrix // Uniforms
uniform mat4 uMVP; // Model-View-Projection matrix
uniform mat4 uModel; // Model matrix
out vec2 vUV; // Pass UV to the fragment shader // Output variables to the fragment shader
out vec2 TexCoords; // Passed texture coordinates
out vec3 Normal; // Passed normal vector
out vec3 FragPos; // Passed fragment position
void main() void main()
{ {
vUV = aUV; // Calculate the position of the vertex in clip space
gl_Position = uMVP * vec4(aPos, 1.0); gl_Position = uMVP * vec4(aPos, 1.0);
// Calculate the position of the vertex in world space
FragPos = vec3(uModel * vec4(aPos, 1.0));
// Calculate the normal vector in world space
Normal = mat3(transpose(inverse(uModel))) * aNormal;
// Pass through the texture coordinates
TexCoords = aTexCoords;
} }

View File

@ -67,32 +67,32 @@ Size=1920,1177
Collapsed=0 Collapsed=0
[Window][Inspector##InspectorWindow] [Window][Inspector##InspectorWindow]
Pos=1567,27 Pos=1536,27
Size=345,1142 Size=376,1142
Collapsed=0 Collapsed=0
DockId=0x00000016,0 DockId=0x00000016,0
[Window][Editor##EditorWindow] [Window][Editor##EditorWindow]
Pos=275,27 Pos=274,27
Size=1290,660 Size=1260,751
Collapsed=0 Collapsed=0
DockId=0x00000017,0 DockId=0x00000017,0
[Window][Performance##performance] [Window][Performance##performance]
Pos=8,720 Pos=8,594
Size=265,449 Size=264,575
Collapsed=0 Collapsed=0
DockId=0x00000014,0 DockId=0x0000001A,0
[Window][Logger##logger] [Window][Logger##logger]
Pos=275,689 Pos=274,780
Size=797,480 Size=612,389
Collapsed=0 Collapsed=0
DockId=0x0000001B,0 DockId=0x0000001B,0
[Window][Lua Text Editor##LuaEditor] [Window][Lua Text Editor##LuaEditor]
Pos=1074,689 Pos=888,780
Size=491,480 Size=646,389
Collapsed=0 Collapsed=0
DockId=0x0000001C,0 DockId=0x0000001C,0
@ -104,19 +104,19 @@ DockId=0x0000000F,0
[Window][Scene Window##SceneWindow] [Window][Scene Window##SceneWindow]
Pos=8,27 Pos=8,27
Size=265,691 Size=264,565
Collapsed=0 Collapsed=0
DockId=0x00000013,0 DockId=0x00000019,0
[Window][Game Objects] [Window][Game Objects]
Pos=182,27 Pos=182,27
Size=301,571 Size=301,571
Collapsed=0 Collapsed=0
DockId=0x0000001A,0 DockId=0x00000011,0
[Window][Profiler] [Window][Profiler]
Pos=932,689 Pos=889,689
Size=633,480 Size=676,480
Collapsed=0 Collapsed=0
DockId=0x0000001C,1 DockId=0x0000001C,1
@ -127,34 +127,34 @@ Column 2 Weight=0.6474
Column 3 Weight=1.0088 Column 3 Weight=1.0088
[Docking][Data] [Docking][Data]
DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=8,27 Size=1904,1142 Split=X Selected=0xF7365A5A DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=8,27 Size=1904,1142 Split=X Selected=0xF7365A5A
DockNode ID=0x00000015 Parent=0x14621557 SizeRef=1557,1142 Split=X DockNode ID=0x00000013 Parent=0x14621557 SizeRef=264,1142 Split=Y Selected=0x818D04BB
DockNode ID=0x00000011 Parent=0x00000015 SizeRef=265,1142 Split=X Selected=0x1D5D92B6 DockNode ID=0x00000019 Parent=0x00000013 SizeRef=264,565 HiddenTabBar=1 Selected=0x1D5D92B6
DockNode ID=0x00000019 Parent=0x00000011 SizeRef=172,571 Split=Y Selected=0x1D5D92B6 DockNode ID=0x0000001A Parent=0x00000013 SizeRef=264,575 Selected=0x818D04BB
DockNode ID=0x00000013 Parent=0x00000019 SizeRef=326,691 HiddenTabBar=1 Selected=0x1D5D92B6 DockNode ID=0x00000014 Parent=0x14621557 SizeRef=1638,1142 Split=X
DockNode ID=0x00000014 Parent=0x00000019 SizeRef=326,449 HiddenTabBar=1 Selected=0x818D04BB DockNode ID=0x00000015 Parent=0x00000014 SizeRef=1526,1142 Split=X
DockNode ID=0x0000001A Parent=0x00000011 SizeRef=301,571 Selected=0xD71D2CC1 DockNode ID=0x00000011 Parent=0x00000015 SizeRef=265,1142 Selected=0x1D5D92B6
DockNode ID=0x00000012 Parent=0x00000015 SizeRef=1290,1142 Split=X DockNode ID=0x00000012 Parent=0x00000015 SizeRef=1259,1142 Split=X
DockNode ID=0x00000009 Parent=0x00000012 SizeRef=364,1142 Split=Y Selected=0x3DC5AC3F DockNode ID=0x00000009 Parent=0x00000012 SizeRef=364,1142 Split=Y Selected=0x3DC5AC3F
DockNode ID=0x00000005 Parent=0x00000009 SizeRef=364,745 Split=Y Selected=0x3DC5AC3F DockNode ID=0x00000005 Parent=0x00000009 SizeRef=364,745 Split=Y Selected=0x3DC5AC3F
DockNode ID=0x0000000B Parent=0x00000005 SizeRef=364,452 HiddenTabBar=1 Selected=0x3DC5AC3F DockNode ID=0x0000000B Parent=0x00000005 SizeRef=364,452 HiddenTabBar=1 Selected=0x3DC5AC3F
DockNode ID=0x0000000C Parent=0x00000005 SizeRef=364,291 Selected=0xAE3C694A DockNode ID=0x0000000C Parent=0x00000005 SizeRef=364,291 Selected=0xAE3C694A
DockNode ID=0x00000006 Parent=0x00000009 SizeRef=364,395 HiddenTabBar=1 Selected=0x726D8899 DockNode ID=0x00000006 Parent=0x00000009 SizeRef=364,395 HiddenTabBar=1 Selected=0x726D8899
DockNode ID=0x0000000A Parent=0x00000012 SizeRef=1538,1142 Split=X DockNode ID=0x0000000A Parent=0x00000012 SizeRef=1538,1142 Split=X
DockNode ID=0x00000007 Parent=0x0000000A SizeRef=357,1142 Selected=0x7737E8B2 DockNode ID=0x00000007 Parent=0x0000000A SizeRef=357,1142 Selected=0x7737E8B2
DockNode ID=0x00000008 Parent=0x0000000A SizeRef=1545,1142 Split=X DockNode ID=0x00000008 Parent=0x0000000A SizeRef=1545,1142 Split=X
DockNode ID=0x00000001 Parent=0x00000008 SizeRef=1202,1142 Split=Y Selected=0xDF0EC458 DockNode ID=0x00000001 Parent=0x00000008 SizeRef=1202,1142 Split=Y Selected=0xDF0EC458
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1202,849 Split=Y Selected=0xDF0EC458 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1202,849 Split=Y Selected=0xDF0EC458
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=1202,571 Split=Y Selected=0xDFF75B3F DockNode ID=0x0000000D Parent=0x00000003 SizeRef=1202,571 Split=Y Selected=0xDFF75B3F
DockNode ID=0x00000017 Parent=0x0000000D SizeRef=1303,660 CentralNode=1 HiddenTabBar=1 Selected=0xDFF75B3F DockNode ID=0x00000017 Parent=0x0000000D SizeRef=1303,751 CentralNode=1 HiddenTabBar=1 Selected=0xDFF75B3F
DockNode ID=0x00000018 Parent=0x0000000D SizeRef=1303,480 Split=X Selected=0x9B5D3198 DockNode ID=0x00000018 Parent=0x0000000D SizeRef=1303,389 Split=X Selected=0x9B5D3198
DockNode ID=0x0000001B Parent=0x00000018 SizeRef=797,680 HiddenTabBar=1 Selected=0x1C0788A1 DockNode ID=0x0000001B Parent=0x00000018 SizeRef=612,680 HiddenTabBar=1 Selected=0x1C0788A1
DockNode ID=0x0000001C Parent=0x00000018 SizeRef=491,680 Selected=0x7D9E6BA2 DockNode ID=0x0000001C Parent=0x00000018 SizeRef=645,680 Selected=0x7D9E6BA2
DockNode ID=0x0000000E Parent=0x00000003 SizeRef=1202,569 Selected=0xE98146C5 DockNode ID=0x0000000E Parent=0x00000003 SizeRef=1202,569 Selected=0xE98146C5
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1202,291 Selected=0x9DD4E196 DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1202,291 Selected=0x9DD4E196
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=334,1142 HiddenTabBar=1 Selected=0x36DC96AB DockNode ID=0x00000002 Parent=0x00000008 SizeRef=334,1142 HiddenTabBar=1 Selected=0x36DC96AB
DockNode ID=0x00000016 Parent=0x14621557 SizeRef=345,1142 HiddenTabBar=1 Selected=0x8D0E8380 DockNode ID=0x00000016 Parent=0x00000014 SizeRef=376,1142 HiddenTabBar=1 Selected=0x8D0E8380
DockSpace ID=0xC6145A92 Pos=8,27 Size=1904,1142 Split=X DockSpace ID=0xC6145A92 Pos=8,27 Size=1904,1142 Split=X
DockNode ID=0x0000000F Parent=0xC6145A92 SizeRef=301,1142 Selected=0xA8433A03 DockNode ID=0x0000000F Parent=0xC6145A92 SizeRef=301,1142 Selected=0xA8433A03
DockNode ID=0x00000010 Parent=0xC6145A92 SizeRef=1601,1142 CentralNode=1 DockNode ID=0x00000010 Parent=0xC6145A92 SizeRef=1601,1142 CentralNode=1

87
scenes/Cool_Model.scene Normal file
View File

@ -0,0 +1,87 @@
Entities:
- ID: 1
Name: Gun
Components:
ScriptComponent:
ScriptPath: assets/scripts/BouncingItem.lua
Transform:
Position: [0, 1.79999995, 0]
Rotation: [0, 71.8000031, 0]
Scale: [0.00999999978, 0.00999999978, 0.00999999978]
Mesh:
vao: 4
indexCount: 786801
textures:
- id: 11
type: texture_diffuse
path: textures/lion.tga
- id: 12
type: texture_diffuse
path: textures/background.tga
- id: 13
type: texture_diffuse
path: textures/vase_plant.tga
- id: 14
type: texture_diffuse
path: textures/sponza_arch_diff.tga
- id: 15
type: texture_diffuse
path: textures/spnza_bricks_a_diff.tga
- id: 16
type: texture_diffuse
path: textures/sponza_ceiling_a_diff.tga
- id: 17
type: texture_diffuse
path: textures/chain_texture.tga
- id: 18
type: texture_diffuse
path: textures/sponza_column_a_diff.tga
- id: 19
type: texture_diffuse
path: textures/sponza_column_b_diff.tga
- id: 20
type: texture_diffuse
path: textures/sponza_column_c_diff.tga
- id: 21
type: texture_diffuse
path: textures/sponza_details_diff.tga
- id: 22
type: texture_diffuse
path: textures/sponza_fabric_diff.tga
- id: 23
type: texture_diffuse
path: textures/sponza_curtain_diff.tga
- id: 24
type: texture_diffuse
path: textures/sponza_fabric_blue_diff.tga
- id: 25
type: texture_diffuse
path: textures/sponza_fabric_green_diff.tga
- id: 26
type: texture_diffuse
path: textures/sponza_curtain_green_diff.tga
- id: 27
type: texture_diffuse
path: textures/sponza_curtain_blue_diff.tga
- id: 28
type: texture_diffuse
path: textures/sponza_flagpole_diff.tga
- id: 29
type: texture_diffuse
path: textures/sponza_floor_a_diff.tga
- id: 30
type: texture_diffuse
path: textures/sponza_thorn_diff.tga
- id: 31
type: texture_diffuse
path: textures/sponza_roof_diff.tga
- id: 32
type: texture_diffuse
path: textures/vase_dif.tga
- id: 33
type: texture_diffuse
path: textures/vase_hanging.tga
- id: 34
type: texture_diffuse
path: textures/vase_round.tga
MeshPath: assets/models/sponza.obj

View File

@ -2,113 +2,113 @@ Entities:
- ID: 0 - ID: 0
Name: Player Name: Player
Components: Components:
Transform:
Position: [0, 2.79999995, -12.6000004]
Rotation: [498.009338, 498.009338, 498.009338]
Scale: [1, 1, 1]
Mesh: Mesh:
vao: 2 vao: 2
indexCount: 15810 indexCount: 15810
textureID: 1 textureID: 1
MeshPath: assets/models/LowPolyFiatUNO.obj MeshPath: assets/models/LowPolyFiatUNO.obj
Transform:
Position: [0, 2.79999995, -12.6000004]
Rotation: [185.076614, 185.076614, 185.076614]
Scale: [1, 1, 1]
- ID: 2 - ID: 2
Name: Gun Name: Gun
Components: Components:
ScriptComponent: Transform:
ScriptPath: assets/scripts/BouncingItem.lua Position: [-2.5, 0.755197883, -0.300000012]
Rotation: [-180, 105.403984, 0]
Scale: [0.00499999989, 0.00499999989, 0.00499999989]
Mesh: Mesh:
vao: 5 vao: 5
indexCount: 116445 indexCount: 116445
textureID: 5 textureID: 5
MeshPath: assets/models/Ak-47.obj MeshPath: assets/models/Ak-47.obj
Transform: ScriptComponent:
Position: [-2.5, 0.806414127, -0.300000012] ScriptPath: assets/scripts/BouncingItem.lua
Rotation: [-180, 261.233307, 0]
Scale: [0.00499999989, 0.00499999989, 0.00499999989]
- ID: 3 - ID: 3
Name: Grass Box Top Name: Grass Box Top
Components: Components:
Transform:
Position: [-1.20000005, -3.4000001, -17.7000008]
Rotation: [-23.5, 15.8999996, -59.9000015]
Scale: [1, 1, 1]
Mesh: Mesh:
vao: 1 vao: 1
indexCount: 36 indexCount: 36
textureID: 4 textureID: 4
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
Transform:
Position: [-1.20000005, -3.4000001, -17.7000008]
Rotation: [-23.5, 15.8999996, -59.9000015]
Scale: [1, 1, 1]
- ID: 4 - ID: 4
Name: Bark Box Name: Bark Box
Components: Components:
Transform:
Position: [8.10000038, 0.800000012, -12]
Rotation: [-17.2999992, -16.1000004, -19.2999992]
Scale: [1, 1, 1]
Mesh: Mesh:
vao: 1 vao: 1
indexCount: 36 indexCount: 36
textureID: 5 textureID: 5
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
Transform:
Position: [8.10000038, 0.800000012, -12]
Rotation: [-17.2999992, -16.1000004, -19.2999992]
Scale: [1, 1, 1]
- ID: 5 - ID: 5
Name: Skybox Name: Skybox
Components: Components:
Transform:
Position: [0, 0, 43.2000008]
Rotation: [0, 0, 0]
Scale: [100, 100, 100]
Mesh: Mesh:
vao: 1 vao: 1
indexCount: 36 indexCount: 36
textureID: 7 textureID: 7
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
Transform:
Position: [0, 0, 43.2000008]
Rotation: [0, 0, 0]
Scale: [100, 100, 100]
- ID: 6 - ID: 6
Name: Null Texture Box Name: Null Texture Box
Components: Components:
Transform:
Position: [-6.5, -6, -18]
Rotation: [15.8000002, -18.2000008, -11.1000004]
Scale: [1, 1, 1]
Mesh: Mesh:
vao: 1 vao: 1
indexCount: 36 indexCount: 36
textureID: 3 textureID: 3
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
Transform:
Position: [-6.5, -6, -18]
Rotation: [15.8000002, -18.2000008, -11.1000004]
Scale: [1, 1, 1]
- ID: 7 - ID: 7
Name: Grass Box Bottom Name: Grass Box Bottom
Components: Components:
Transform:
Position: [6.5999999, 1.79999995, -23.8999996]
Rotation: [-16.1000004, -15.8999996, -35]
Scale: [1, 1, 1]
Mesh: Mesh:
vao: 1 vao: 1
indexCount: 36 indexCount: 36
textureID: 4 textureID: 4
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
Transform:
Position: [6.5999999, 1.79999995, -23.8999996]
Rotation: [-16.1000004, -15.8999996, -35]
Scale: [1, 1, 1]
- ID: 8 - ID: 8
Name: Wood Box Name: Wood Box
Components: Components:
Transform:
Position: [-7.80000019, 0.200000003, -29.7999992]
Rotation: [22.2999992, -32.7999992, 0]
Scale: [1, 1, 1]
Mesh: Mesh:
vao: 1 vao: 1
indexCount: 36 indexCount: 36
textureID: 1 textureID: 1
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
Transform:
Position: [-7.80000019, 0.200000003, -29.7999992]
Rotation: [22.2999992, -32.7999992, 0]
Scale: [1, 1, 1]
- ID: 9 - ID: 9
Name: Bricks Name: Bricks
Components: Components:
Transform:
Position: [5.5, -2.9000001, -19.5]
Rotation: [-41.4000015, -22.6000004, -52.2999992]
Scale: [1, 1, 1]
Mesh: Mesh:
vao: 1 vao: 1
indexCount: 36 indexCount: 36
textureID: 2 textureID: 2
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
Transform:
Position: [5.5, -2.9000001, -19.5]
Rotation: [-41.4000015, -22.6000004, -52.2999992]
Scale: [1, 1, 1]
- ID: 10 - ID: 10
Name: Script Name: Script
Components: Components:
@ -117,12 +117,31 @@ Entities:
- ID: 10 - ID: 10
Name: Gun Podium Name: Gun Podium
Components: Components:
Transform:
Position: [-2.5, 2, -0.300000012]
Rotation: [0, 0, 0]
Scale: [0.25, 1, 0.25]
Mesh: Mesh:
vao: 1 vao: 1
indexCount: 36 indexCount: 36
textureID: 4 textureID: 4
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
Transform:
Position: [-2.5, 2, -0.300000012]
Rotation: [0, 0, 0]
Scale: [0.25, 1, 0.25]
- ID: 11
Name: Camera
Components:
CameraComponent:
IsPerspective: true
DefaultRuntimeCamera: true
FOV: 45
AspectRatio: 1.77777779
NearPlane: 0.100000001
FarPlane: 1000
Mesh:
vao: 0
indexCount: 36
textureID: 0
MeshPath: assets/models/DefaultMesh.obj
Transform:
Position: [0, -0.100000001, 0.400000006]
Rotation: [15.3999996, -164.399994, 0]
Scale: [1, 1, 1]

View File

@ -1,121 +1,147 @@
Entities: Entities:
- ID: 0 - ID: 0
Name: Carrrrr Yeaaa Name: Player
Components: Components:
Transform: Transform:
Position: [0, 2.79999995, -12.6000004] Position: [0, 2.79999995, -12.6000004]
Rotation: [149.699997, -137.899994, -39.2999992] Rotation: [498.009338, 498.009338, 498.009338]
Scale: [1, 1, 1] Scale: [1, 1, 1]
Mesh: Mesh:
vao: 2 vao: 2
indexCount: 15810 indexCount: 15810
textureID: 1 textureID: 1
MeshPath: assets/models/LowPolyFiatUNO.obj MeshPath: assets/models/LowPolyFiatUNO.obj
- ID: 1
Name: Cube Yay
Components:
Transform:
Position: [-11.8999996, -2, -21.7999992]
Rotation: [-9, -18.6000004, -28.1000004]
Scale: [1, 1, 1]
Mesh:
vao: 5
indexCount: 36
textureID: 2
MeshPath: assets/models/DefaultMesh.obj
- ID: 2 - ID: 2
Name: Cube Yay 2 Name: Gun
Components: Components:
Transform: Transform:
Position: [7.80000019, -8.10000038, -20.6000004] Position: [-2.5, 0.755197883, -0.300000012]
Rotation: [-86.3000031, 0, -66] Rotation: [-180, 105.403984, 0]
Scale: [1, 1, 1] Scale: [0.00499999989, 0.00499999989, 0.00499999989]
Mesh: Mesh:
vao: 5 vao: 5
indexCount: 36 indexCount: 116445
textureID: 3 textureID: 5
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/Ak-47.obj
ScriptComponent:
ScriptPath: assets/scripts/BouncingItem.lua
- ID: 3 - ID: 3
Name: Cube Yay 3 Name: Grass Box Top
Components: Components:
Transform: Transform:
Position: [-1.20000005, -3.4000001, -17.7000008] Position: [-1.20000005, -3.4000001, -17.7000008]
Rotation: [-23.5, 15.8999996, -59.9000015] Rotation: [-23.5, 15.8999996, -59.9000015]
Scale: [1, 1, 1] Scale: [1, 1, 1]
Mesh: Mesh:
vao: 5 vao: 1
indexCount: 36 indexCount: 36
textureID: 4 textureID: 4
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
- ID: 4 - ID: 4
Name: Cube Yay 4 Name: Bark Box
Components: Components:
Transform: Transform:
Position: [8.10000038, 0.800000012, -12] Position: [8.10000038, 0.800000012, -12]
Rotation: [-17.2999992, -16.1000004, -19.2999992] Rotation: [-17.2999992, -16.1000004, -19.2999992]
Scale: [1, 1, 1] Scale: [1, 1, 1]
Mesh: Mesh:
vao: 5 vao: 1
indexCount: 36 indexCount: 36
textureID: 5 textureID: 5
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
- ID: 5 - ID: 5
Name: Colormap Name: Skybox
Components: Components:
Mesh: Mesh:
vao: 5 vao: 1
indexCount: 36 indexCount: 36
textureID: 6 textureID: 7
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
Transform: Transform:
Position: [0, 0, 0] Position: [0, 0, 43.2000008]
Rotation: [0, 0, -90] Rotation: [0, 0, 0]
Scale: [100, 100, 100] Scale: [100, 100, 100]
- ID: 6 - ID: 6
Name: Cube Yay 6 Name: Null Texture Box
Components: Components:
Transform: Transform:
Position: [-6.5, -6, -18] Position: [-6.5, -6, -18]
Rotation: [15.8000002, -18.2000008, -11.1000004] Rotation: [15.8000002, -18.2000008, -11.1000004]
Scale: [1, 1, 1] Scale: [1, 1, 1]
Mesh: Mesh:
vao: 5 vao: 1
indexCount: 36 indexCount: 36
textureID: 3 textureID: 3
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
- ID: 7 - ID: 7
Name: Cube Yay 7 Name: Grass Box Bottom
Components: Components:
Transform: Transform:
Position: [6.5, 1.79999995, -23.8999996] Position: [6.5999999, 1.79999995, -23.8999996]
Rotation: [-16.1000004, -15.8999996, -35] Rotation: [-16.1000004, -15.8999996, -35]
Scale: [1, 1, 1] Scale: [1, 1, 1]
Mesh: Mesh:
vao: 5 vao: 1
indexCount: 36 indexCount: 36
textureID: 4 textureID: 4
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
- ID: 8 - ID: 8
Name: Cube Yay 8 Name: Wood Box
Components: Components:
Transform: Transform:
Position: [-7.80000019, 0.200000003, -29.7999992] Position: [-7.80000019, 0.200000003, -29.7999992]
Rotation: [22.2999992, -32.7999992, 0] Rotation: [22.2999992, -32.7999992, 0]
Scale: [1, 1, 1] Scale: [1, 1, 1]
Mesh: Mesh:
vao: 5 vao: 1
indexCount: 36 indexCount: 36
textureID: 1 textureID: 1
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
- ID: 9 - ID: 9
Name: Cube Yay 9 Name: Bricks
Components: Components:
Transform: Transform:
Position: [5.5, -2.9000001, -19.5] Position: [5.5, -2.9000001, -19.5]
Rotation: [-41.4000015, -22.6000004, -52.2999992] Rotation: [-41.4000015, -22.6000004, -52.2999992]
Scale: [1, 1, 1] Scale: [1, 1, 1]
Mesh: Mesh:
vao: 5 vao: 1
indexCount: 36 indexCount: 36
textureID: 2 textureID: 2
MeshPath: assets/models/DefaultMesh.obj MeshPath: assets/models/DefaultMesh.obj
- ID: 10
Name: Script
Components:
ScriptComponent:
ScriptPath: assets/scripts/script.lua
- ID: 10
Name: Gun Podium
Components:
Mesh:
vao: 1
indexCount: 36
textureID: 4
MeshPath: assets/models/DefaultMesh.obj
Transform:
Position: [-2.5, 2, -0.300000012]
Rotation: [0, 0, 0]
Scale: [0.25, 1, 0.25]
- ID: 11
Name: Camera
Components:
CameraComponent:
IsPerspective: true
DefaultRuntimeCamera: true
FOV: 45
AspectRatio: 1.77777779
NearPlane: 0.100000001
FarPlane: 1000
Mesh:
vao: 0
indexCount: 36
textureID: 0
MeshPath: assets/models/DefaultMesh.obj
Transform:
Position: [0, -0.100000001, 0.400000006]
Rotation: [15.3999996, -164.399994, 0]
Scale: [1, 1, 1]

View File

@ -4,14 +4,16 @@
#include "GameObject.h" // Ensure this is included to access GameObject #include "GameObject.h" // Ensure this is included to access GameObject
#include "Transform.h" // Ensure Transform component is available #include "Transform.h" // Ensure Transform component is available
#include <iostream> #include <iostream>
#include <cassert>
#include "gcml.h"
// Constructor implementation // Constructor implementation
CameraComponent::CameraComponent() : CameraComponent::CameraComponent() : IsPerspective(true),
m_IsPerspective(true), FOV(45.0f), AspectRatio(16.0f / 9.0f),
m_FOV(45.0f), m_AspectRatio(16.0f / 9.0f), NearPlane(0.1f), FarPlane(100.0f),
m_NearPlane(0.1f), m_FarPlane(100.0f), Left(-1.0f), Right(1.0f), Bottom(-1.0f), Top(1.0f), DefaultRuntimeCamera(false),
m_Left(-1.0f), m_Right(1.0f), m_Bottom(-1.0f), m_Top(1.0f), m_ViewMatrix(1.0f), m_ProjectionMatrix(1.0f)
m_ViewMatrix(1.0f), m_ProjectionMatrix(1.0f)
{ {
UpdateProjectionMatrix(); UpdateProjectionMatrix();
} }
@ -33,27 +35,27 @@ const std::string &CameraComponent::GetStaticName()
return name; return name;
} }
YAML::Node CameraComponent::Serialize() YAML::Node CameraComponent::Serialize()
{ {
YAML::Node node; YAML::Node node;
node["IsPerspective"] = m_IsPerspective; node["IsPerspective"] = IsPerspective;
if (m_IsPerspective) node["DefaultRuntimeCamera"] = DefaultRuntimeCamera;
if (IsPerspective)
{ {
node["FOV"] = m_FOV; node["FOV"] = FOV;
node["AspectRatio"] = m_AspectRatio; node["AspectRatio"] = AspectRatio;
node["NearPlane"] = m_NearPlane; node["NearPlane"] = NearPlane;
node["FarPlane"] = m_FarPlane; node["FarPlane"] = FarPlane;
} }
else else
{ {
node["Left"] = m_Left; node["Left"] = Left;
node["Right"] = m_Right; node["Right"] = Right;
node["Bottom"] = m_Bottom; node["Bottom"] = Bottom;
node["Top"] = m_Top; node["Top"] = Top;
node["NearPlane"] = m_NearPlane; node["NearPlane"] = NearPlane;
node["FarPlane"] = m_FarPlane; node["FarPlane"] = FarPlane;
} }
return node; return node;
} }
@ -62,59 +64,63 @@ void CameraComponent::Deserialize(const YAML::Node &node)
{ {
if (node["IsPerspective"]) if (node["IsPerspective"])
{ {
m_IsPerspective = node["IsPerspective"].as<bool>(); IsPerspective = node["IsPerspective"].as<bool>();
} }
if (m_IsPerspective) if (node["DefaultRuntimeCamera"])
{
DefaultRuntimeCamera = node["DefaultRuntimeCamera"].as<bool>();
}
if (IsPerspective)
{ {
if (node["FOV"]) if (node["FOV"])
m_FOV = node["FOV"].as<float>(); FOV = node["FOV"].as<float>();
if (node["AspectRatio"]) if (node["AspectRatio"])
m_AspectRatio = node["AspectRatio"].as<float>(); AspectRatio = node["AspectRatio"].as<float>();
if (node["NearPlane"]) if (node["NearPlane"])
m_NearPlane = node["NearPlane"].as<float>(); NearPlane = node["NearPlane"].as<float>();
if (node["FarPlane"]) if (node["FarPlane"])
m_FarPlane = node["FarPlane"].as<float>(); FarPlane = node["FarPlane"].as<float>();
} }
else else
{ {
if (node["Left"]) if (node["Left"])
m_Left = node["Left"].as<float>(); Left = node["Left"].as<float>();
if (node["Right"]) if (node["Right"])
m_Right = node["Right"].as<float>(); Right = node["Right"].as<float>();
if (node["Bottom"]) if (node["Bottom"])
m_Bottom = node["Bottom"].as<float>(); Bottom = node["Bottom"].as<float>();
if (node["Top"]) if (node["Top"])
m_Top = node["Top"].as<float>(); Top = node["Top"].as<float>();
if (node["NearPlane"]) if (node["NearPlane"])
m_NearPlane = node["NearPlane"].as<float>(); NearPlane = node["NearPlane"].as<float>();
if (node["FarPlane"]) if (node["FarPlane"])
m_FarPlane = node["FarPlane"].as<float>(); FarPlane = node["FarPlane"].as<float>();
} }
UpdateProjectionMatrix(); UpdateProjectionMatrix();
UpdateViewMatrix();
} }
void CameraComponent::SetPerspective(float fov, float aspectRatio, float nearPlane, float farPlane) void CameraComponent::SetPerspective(float fov, float aspectRatio, float nearPlane, float farPlane)
{ {
m_IsPerspective = true; IsPerspective = true;
m_FOV = fov; FOV = fov;
m_AspectRatio = aspectRatio; AspectRatio = aspectRatio;
m_NearPlane = nearPlane; NearPlane = nearPlane;
m_FarPlane = farPlane; FarPlane = farPlane;
UpdateProjectionMatrix(); UpdateProjectionMatrix();
} }
void CameraComponent::SetOrthographic(float left, float right, float bottom, float top, float nearPlane, float farPlane) void CameraComponent::SetOrthographic(float left, float right, float bottom, float top, float nearPlane, float farPlane)
{ {
m_IsPerspective = false; IsPerspective = false;
m_Left = left; Left = left;
m_Right = right; Right = right;
m_Bottom = bottom; Bottom = bottom;
m_Top = top; Top = top;
m_NearPlane = nearPlane; NearPlane = nearPlane;
m_FarPlane = farPlane; FarPlane = farPlane;
UpdateProjectionMatrix(); UpdateProjectionMatrix();
} }
@ -128,45 +134,60 @@ const glm::mat4 &CameraComponent::GetProjectionMatrix() const
return m_ProjectionMatrix; return m_ProjectionMatrix;
} }
void CameraComponent::Update(float _deltaTime)
{
(void)_deltaTime; // Suppress unused parameter warning
UpdateViewMatrix();
UpdateProjectionMatrix();
}
void CameraComponent::UpdateViewMatrix() void CameraComponent::UpdateViewMatrix()
{ {
// Retrieve the Transform component from the owning GameObject
std::shared_ptr<TransformComponent> transform = owner->GetComponent<TransformComponent>(); if (m_Owner)
if (transform)
{ {
glm::vec3 position = transform->GetPosition();
glm::vec3 rotation = transform->GetRotation();
// Convert Euler angles to radians std::shared_ptr<TransformComponent> transform = m_Owner->GetComponent<TransformComponent>();
glm::vec3 rotRad = glm::radians(rotation);
// Calculate forward vector if (transform)
glm::vec3 forward; {
forward.x = cos(rotRad.y) * cos(rotRad.x); glm::vec3 position = transform->GetPosition();
forward.y = sin(rotRad.x); glm::vec3 rotation = transform->GetRotation();
forward.z = sin(rotRad.y) * cos(rotRad.x);
forward = glm::normalize(forward);
// Define up vector (assuming Y-up) // Convert Euler angles to radians
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); glm::vec3 rotRad = glm::radians(rotation);
m_ViewMatrix = glm::lookAt(position, position + forward, up); // Calculate forward vector
glm::vec3 forward;
forward.x = cos(rotRad.y) * cos(rotRad.x);
forward.y = sin(rotRad.x);
forward.z = sin(rotRad.y) * cos(rotRad.x);
forward = glm::normalize(forward);
// Define up vector (assuming Y-up)
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
m_ViewMatrix = glm::lookAt(position, position + forward, up);
}
else
{
DEBUG_PRINT("Transform component missing on GameObject: %s", m_Owner->name.c_str());
}
} }
else else
{ {
std::cerr << "Transform component missing on GameObject: " << m_Owner->name << std::endl; DEBUG_PRINT("Game Object has no parent");
} }
} }
void CameraComponent::UpdateProjectionMatrix() void CameraComponent::UpdateProjectionMatrix()
{ {
if (m_IsPerspective) if (IsPerspective)
{ {
m_ProjectionMatrix = glm::perspective(glm::radians(m_FOV), m_AspectRatio, m_NearPlane, m_FarPlane); m_ProjectionMatrix = glm::perspective(glm::radians(FOV), AspectRatio, NearPlane, FarPlane);
} }
else else
{ {
m_ProjectionMatrix = glm::ortho(m_Left, m_Right, m_Bottom, m_Top, m_NearPlane, m_FarPlane); m_ProjectionMatrix = glm::ortho(Left, Right, Bottom, Top, NearPlane, FarPlane);
} }
} }

View File

@ -16,40 +16,40 @@ public:
virtual ~CameraComponent(); virtual ~CameraComponent();
// Overridden methods from Component // Overridden methods from Component
virtual const std::string& GetName() const override; virtual const std::string &GetName() const override;
static const std::string& GetStaticName(); static const std::string &GetStaticName();
virtual YAML::Node Serialize() override; virtual YAML::Node Serialize() override;
virtual void Deserialize(const YAML::Node& node) override; virtual void Deserialize(const YAML::Node &node) override;
// Camera-specific methods // Camera-specific methods
void SetPerspective(float fov, float aspectRatio, float nearPlane, float farPlane); void SetPerspective(float fov, float aspectRatio, float nearPlane, float farPlane);
void SetOrthographic(float left, float right, float bottom, float top, float nearPlane, float farPlane); void SetOrthographic(float left, float right, float bottom, float top, float nearPlane, float farPlane);
const glm::mat4& GetViewMatrix() const; const glm::mat4 &GetViewMatrix() const;
const glm::mat4& GetProjectionMatrix() const; const glm::mat4 &GetProjectionMatrix() const;
// Projection parameters
bool IsPerspective;
float FOV;
float AspectRatio;
float NearPlane;
float FarPlane;
float Left;
float Right;
float Bottom;
float Top;
bool DefaultRuntimeCamera;
virtual void Update(float deltaTime) override;
private: private:
// Projection parameters
bool m_IsPerspective;
float m_FOV;
float m_AspectRatio;
float m_NearPlane;
float m_FarPlane;
float m_Left;
float m_Right;
float m_Bottom;
float m_Top;
// Matrices // Matrices
glm::mat4 m_ViewMatrix; glm::mat4 m_ViewMatrix;
glm::mat4 m_ProjectionMatrix; glm::mat4 m_ProjectionMatrix;
GameObject* owner;
// Update matrices // Update matrices
void UpdateViewMatrix(); void UpdateViewMatrix();
void UpdateProjectionMatrix(); void UpdateProjectionMatrix();

View File

@ -13,26 +13,28 @@ class Component
public: public:
// Constructor accepting a pointer to the owning GameObject // Constructor accepting a pointer to the owning GameObject
Component() {} Component() {}
// Virtual destructor // Virtual destructor
virtual ~Component() {} virtual ~Component() {}
// Pure virtual methods
virtual const std::string& GetName() const = 0;
void SetOwner(GameObject* owner) { // Pure virtual methods
virtual const std::string &GetName() const = 0;
m_Owner = owner;
void SetOwner(GameObject *owner)
{
m_Owner = owner;
} }
virtual void Update(float deltaTime) = 0;
// Serialization methods // Serialization methods
virtual YAML::Node Serialize() = 0; virtual YAML::Node Serialize() = 0;
virtual void Deserialize(const YAML::Node& node) = 0; virtual void Deserialize(const YAML::Node &node) = 0;
// Getter for the owning GameObject // Getter for the owning GameObject
GameObject* GetOwner() const { return m_Owner; } GameObject *GetOwner() const { return m_Owner; }
protected: protected:
GameObject* m_Owner; // Pointer to the owning GameObject GameObject *m_Owner; // Pointer to the owning GameObject
}; };

View File

@ -32,6 +32,19 @@ void GameObject::AddComponent(const std::shared_ptr<Component> &component)
// std::cout << "Added " << component->GetName() << std::endl; // std::cout << "Added " << component->GetName() << std::endl;
} }
void GameObject::Update(float deltaTime) {
// Iterate using range-based for loop
for (const auto& [componentName, componentPtr] : components) {
if (componentPtr) { // Check if the pointer is valid
componentPtr->Update(deltaTime); // Call the Update method
} else {
DEBUG_PRINT("Warning: '%s' is not a valid pointer:", componentName.c_str());
}
}
}
std::shared_ptr<Component> GameObject::GetComponentByName(const std::string &name) const std::shared_ptr<Component> GameObject::GetComponentByName(const std::string &name) const
{ {
auto it = components.find(name); auto it = components.find(name);
@ -83,21 +96,27 @@ void GameObject::Deserialize(const YAML::Node &node)
if (compName == TransformComponent::GetStaticName()) if (compName == TransformComponent::GetStaticName())
{ {
auto transform = std::make_shared<TransformComponent>(); auto NewComponent = std::make_shared<TransformComponent>();
transform->Deserialize(compNode); NewComponent->Deserialize(compNode);
AddComponent(transform); AddComponent(NewComponent);
} }
else if (compName == MeshComponent::GetStaticName()) else if (compName == MeshComponent::GetStaticName())
{ {
auto mesh = std::make_shared<MeshComponent>(); auto NewComponent = std::make_shared<MeshComponent>();
mesh->Deserialize(compNode); NewComponent->Deserialize(compNode);
AddComponent(mesh); AddComponent(NewComponent);
} }
else if (compName == ScriptComponent::GetStaticName()) else if (compName == ScriptComponent::GetStaticName())
{ {
auto ScriptComp = std::make_shared<ScriptComponent>(); auto NewComponent = std::make_shared<ScriptComponent>();
ScriptComp->Deserialize(compNode); NewComponent->Deserialize(compNode);
AddComponent(ScriptComp); AddComponent(NewComponent);
}
else if (compName == CameraComponent::GetStaticName())
{
auto NewComponent = std::make_shared<CameraComponent>();
NewComponent->Deserialize(compNode);
AddComponent(NewComponent);
} }
else else
{ {

View File

@ -9,6 +9,7 @@
#include "Transform.h" #include "Transform.h"
#include "ScriptComponent.h" #include "ScriptComponent.h"
#include "Mesh.h" #include "Mesh.h"
#include "CameraComponent.h"
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
@ -30,6 +31,8 @@ public:
void AddComponent(const std::shared_ptr<Component> &component); void AddComponent(const std::shared_ptr<Component> &component);
std::shared_ptr<Component> GetComponentByName(const std::string &name) const; std::shared_ptr<Component> GetComponentByName(const std::string &name) const;
void Update(float deltaTime);
template <typename T> template <typename T>
std::shared_ptr<T> GetComponent() std::shared_ptr<T> GetComponent()
{ {

View File

@ -10,7 +10,7 @@ extern AssetManager g_AssetManager;
const std::string MeshComponent::name = "Mesh"; const std::string MeshComponent::name = "Mesh";
MeshComponent::MeshComponent() MeshComponent::MeshComponent()
: vao(0), indexCount(0), textureID(0), MeshPath("assets/models/DefaultMesh.obj") : vao(0), indexCount(0), MeshPath("assets/models/DefaultMesh.obj")
{ {
} }
@ -24,73 +24,111 @@ const std::string &MeshComponent::GetStaticName()
return name; return name;
} }
void MeshComponent::Update(float deltaTime)
{
return;
}
YAML::Node MeshComponent::Serialize() YAML::Node MeshComponent::Serialize()
{ {
YAML::Node node; YAML::Node node;
node["vao"] = static_cast<int>(vao); node["vao"] = static_cast<int>(vao);
node["indexCount"] = static_cast<int>(indexCount); node["indexCount"] = static_cast<int>(indexCount);
node["textureID"] = static_cast<int>(textureID);
node["MeshPath"] = static_cast<std::string>(MeshPath); // Serialize Textures
YAML::Node texturesNode;
for (const auto &texture : textures)
{
YAML::Node texNode;
texNode["id"] = static_cast<int>(texture.id);
texNode["type"] = texture.type;
texNode["path"] = texture.path;
texturesNode.push_back(texNode);
}
node["textures"] = texturesNode;
node["MeshPath"] = MeshPath;
return node; return node;
} }
void MeshComponent::Deserialize(const YAML::Node &node) void MeshComponent::Deserialize(const YAML::Node &node)
{ {
if (node["MeshPath"]) if (node["MeshPath"])
{ {
MeshPath = static_cast<std::string>(node["MeshPath"].as<std::string>()); MeshPath = node["MeshPath"].as<std::string>();
// g_AssetManager.DebugAssetMap();
DEBUG_PRINT("Loading Mesh: %s", MeshPath.c_str()); DEBUG_PRINT("Loading Mesh: %s", MeshPath.c_str());
Model *model = g_AssetManager.loadAsset<Model *>(AssetType::MODEL, MeshPath.c_str()); Model *model = g_AssetManager.loadAsset<Model *>(AssetType::MODEL, MeshPath.c_str());
DEBUG_PRINT("Model loaded successfully with %lld vertices and %lld indices.", model->vertices.size(), model->indices.size());
if (!model)
{
DEBUG_PRINT("Failed to load model: %s", MeshPath.c_str());
return;
}
DEBUG_PRINT("Model loaded successfully with %zu vertices and %zu indices.",
model->vertices.size(), model->indices.size());
// Assign VAO and index count
if (model->vao != 0) if (model->vao != 0)
{ {
vao = model->vao; vao = model->vao;
} }
else if (node["vao"]) else if (node["vao"])
{ {
vao = static_cast<int>(node["vao"].as<int>()); vao = node["vao"].as<int>();
} }
if (model->indices.size() != 0) if (model->indices.size() != 0)
{ {
indexCount = model->indices.size(); indexCount = static_cast<GLuint>(model->indices.size());
} }
else if (node["indexCount"]) else if (node["indexCount"])
{ {
indexCount = static_cast<int>(node["indexCount"].as<int>()); indexCount = node["indexCount"].as<int>();
} }
if (textureID != 0)
{
textureID = model->textureID; // Assign Textures
} if (!model->textures.empty())
else if (node["textureID"])
{ {
textureID = static_cast<int>(node["textureID"].as<int>()); textures = model->textures;
}
else if (node["textures"])
{
const YAML::Node &texturesNode = node["textures"];
for (const auto &texNode : texturesNode)
{
Texture texture;
texture.id = texNode["id"].as<int>();
texture.type = texNode["type"].as<std::string>();
texture.path = texNode["path"].as<std::string>();
textures.push_back(texture);
}
} }
} }
else else
{ {
if (node["vao"]) if (node["vao"])
{ {
vao = static_cast<int>(node["vao"].as<int>()); vao = node["vao"].as<int>();
} }
if (node["indexCount"]) if (node["indexCount"])
{ {
indexCount = static_cast<int>(node["indexCount"].as<int>()); indexCount = node["indexCount"].as<int>();
} }
if (node["textureID"]) if (node["textures"])
{ {
textureID = static_cast<int>(node["textureID"].as<int>()); const YAML::Node &texturesNode = node["textures"];
for (const auto &texNode : texturesNode)
{
Texture texture;
texture.id = texNode["id"].as<int>();
texture.type = texNode["type"].as<std::string>();
texture.path = texNode["path"].as<std::string>();
textures.push_back(texture);
}
} }
} }
} }

View File

@ -1,4 +1,3 @@
// Mesh.h // Mesh.h
#pragma once #pragma once
@ -7,14 +6,16 @@
#include <GL/glew.h> #include <GL/glew.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include <vector>
#include <string>
#include "Engine/AssetManager.h"
class MeshComponent : public Component class MeshComponent : public Component
{ {
public: public:
GLuint vao = 0; // Vertex Array Object GLuint vao = 0; // Vertex Array Object
GLuint indexCount = 0; // Number of indices to draw GLuint indexCount = 0; // Number of indices to draw
GLuint textureID = 0; // The texture handle std::vector<Texture> textures; // List of textures associated with the mesh
std::string MeshPath; std::string MeshPath;
@ -22,6 +23,8 @@ public:
virtual const std::string& GetName() const override; virtual const std::string& GetName() const override;
static const std::string& GetStaticName(); static const std::string& GetStaticName();
virtual void Update(float deltaTime) override;
// Serialization methods // Serialization methods
virtual YAML::Node Serialize() override; virtual YAML::Node Serialize() override;
virtual void Deserialize(const YAML::Node& node) override; virtual void Deserialize(const YAML::Node& node) override;

View File

@ -88,3 +88,10 @@ void ScriptComponent::Update(float deltaTime)
// Call the Update method of LuaManager // Call the Update method of LuaManager
m_LuaManager.Update(deltaTime); m_LuaManager.Update(deltaTime);
} }
void ScriptComponent::Init()
{
// Call the Update method of LuaManager
m_LuaManager.CallLuaFunction("OnInit");
}

View File

@ -26,7 +26,11 @@ public:
// Script management methods // Script management methods
bool Initialize(); bool Initialize();
void Update(float deltaTime); virtual void Update(float deltaTime);
void Init();
private: private:

View File

@ -22,6 +22,12 @@ const std::string& TransformComponent::GetStaticName()
return name; return name;
} }
void TransformComponent::Update(float _deltaTime)
{
(void)_deltaTime; // Suppress unused parameter warning
return;
}
YAML::Node TransformComponent::Serialize() YAML::Node TransformComponent::Serialize()
{ {
YAML::Node node; YAML::Node node;

View File

@ -12,29 +12,35 @@ public:
glm::vec3 rotation; glm::vec3 rotation;
glm::vec3 scale; glm::vec3 scale;
glm::vec3 GetPosition() const { glm::vec3 GetPosition() const
{
return position; return position;
} }
void SetPosition(float x, float y, float z) { void SetPosition(float x, float y, float z)
position = { x, y, z }; {
position = {x, y, z};
} }
glm::vec3 GetRotation() const { glm::vec3 GetRotation() const
{
return rotation; return rotation;
} }
void SetRotation(float x, float y, float z) { void SetRotation(float x, float y, float z)
rotation = { x, y, z }; {
rotation = {x, y, z};
} }
TransformComponent(); TransformComponent();
virtual const std::string& GetName() const override; virtual const std::string &GetName() const override;
static const std::string& GetStaticName(); static const std::string &GetStaticName();
virtual void Update(float deltaTime) override;
// Serialization methods // Serialization methods
virtual YAML::Node Serialize() override; virtual YAML::Node Serialize() override;
virtual void Deserialize(const YAML::Node& node) override; virtual void Deserialize(const YAML::Node &node) override;
private: private:
static const std::string name; static const std::string name;

View File

@ -49,6 +49,10 @@ SceneManager g_SceneManager;
std::vector<std::shared_ptr<GameObject>> g_GameObjects; std::vector<std::shared_ptr<GameObject>> g_GameObjects;
std::shared_ptr<CameraComponent> g_RuntimeCameraObject;
int g_GPU_Triangles_drawn_to_screen = 0; int g_GPU_Triangles_drawn_to_screen = 0;
GameObject *g_SelectedObject; // Pointer to the currently selected object GameObject *g_SelectedObject; // Pointer to the currently selected object
@ -145,51 +149,6 @@ void MyEngine::Run()
DEBUG_PRINT("Transition to Editor"); DEBUG_PRINT("Transition to Editor");
// Pseudocode:
int newId = g_GameObjects.size();
auto newGameObject = std::make_shared<GameObject>(newId, ("Default"));
DEBUG_PRINT("Created Default GameObject");
newGameObject->AddComponent(std::make_shared<TransformComponent>());
newGameObject->AddComponent(std::make_shared<MeshComponent>());
DEBUG_PRINT("Added Componenets");
// Suppose we loaded a VAO, an EBO with 36 indices for the cube,
// and a texture ID from the asset manager
auto mesh = newGameObject->GetComponent<MeshComponent>();
auto transform = newGameObject->GetComponent<TransformComponent>();
DEBUG_PRINT("Got pointers to Componenets");
if (mesh)
{
// printf("Got Valid Mesh Component\n");
Model *model = g_AssetManager.loadAsset<Model *>(AssetType::MODEL, "assets/models/DefaultMesh.obj");
mesh->vao = model->vao;
mesh->indexCount = model->indices.size();
mesh->textureID = g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/wood.png");
}
else
{
DEBUG_PRINT("Could not find Mesh Component\n");
}
if (transform)
{
// printf("Got Valid Transform Component\n");
transform->position = glm::vec3(0.f, 0.f, 0.f);
transform->rotation = glm::vec3(0.f, 0.5f, 0.f);
transform->scale = glm::vec3(1.f, 1.f, 1.f);
}
else
{
DEBUG_PRINT("Could not find Transform Component");
}
g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/bricks.png"); g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/bricks.png");
g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/default.png"); g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/default.png");
g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/lush_grass.png"); g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/lush_grass.png");
@ -216,7 +175,6 @@ void MyEngine::Run()
DEBUG_PRINT("Model loaded successfully with %lld vertices and %lld indices.", model4->vertices.size(), model4->indices.size()); DEBUG_PRINT("Model loaded successfully with %lld vertices and %lld indices.", model4->vertices.size(), model4->indices.size());
g_GameObjects.push_back(newGameObject);
DEBUG_PRINT("Put componenent into Global Componenets Subsystem"); DEBUG_PRINT("Put componenent into Global Componenets Subsystem");
// printf("%p\n", &g_GameObjects); // printf("%p\n", &g_GameObjects);
@ -262,12 +220,28 @@ void MyEngine::Run()
if (m_FirstTickGameRunning && m_GameRunning) if (m_FirstTickGameRunning && m_GameRunning)
{ {
ScopedTimer timer("SaveScene"); ScopedTimer timer("SaveScene");
m_FirstTickGameRunning = false; m_FirstTickGameRunning = false;
std::string savePath = createTempFolder().string() + "TesseractEngineTempScene.scene"; std::string savePath = createTempFolder().string() + "TesseractEngineTempScene.scene";
DEBUG_PRINT("Save path: %s", savePath.c_str()); DEBUG_PRINT("Save path: %s", savePath.c_str());
g_SceneManager.SaveScene(g_GameObjects, savePath); g_SceneManager.SaveScene(g_GameObjects, savePath);
ScopedTimer LUA_INIT_timer("GameObjectsScriptInit");
for (auto &Gameobject : g_GameObjects)
{
// Handle Components That Require Updates
std::shared_ptr<ScriptComponent> script = Gameobject->GetComponent<ScriptComponent>();
if (script)
{ // Null Checks
ScopedTimer Lua_timer("GameObjectLuaCall_INIT: " + Gameobject->name); // var has to be named that or it will be redecl
script->Init();
}
}
} }
if (!m_FirstTickGameRunning && !m_GameRunning) if (!m_FirstTickGameRunning && !m_GameRunning)
@ -291,14 +265,9 @@ void MyEngine::Run()
for (auto &Gameobject : g_GameObjects) for (auto &Gameobject : g_GameObjects)
{ {
// Handle Components That Require Updates
std::shared_ptr<ScriptComponent> script = Gameobject->GetComponent<ScriptComponent>();
if (script)
{ // Null Checks
ScopedTimer timer("GameObjectLuaCall: " + Gameobject->name);
script->Update(frame_delta); Gameobject->Update(frame_delta);
}
} }
} }

View File

@ -147,14 +147,61 @@ Shader *LoadShaderFromList(const std::string &path)
return newShader; return newShader;
} }
// case AssetType::SOUND:
//{
// std::cout << "[AssetManager] Loading SOUND from: " << path << std::endl;
// // Stub or real code to load .wav / .ogg
// return (void *)0xAAAA8888; // placeholder
// }
Model *LoadModelFromList(const std::string &path)
GLuint LoadTexture(const std::string &path, const std::string &directory)
{
std::string fullPath = directory + path;
int width, height, channels;
unsigned char *data = stbi_load(fullPath.c_str(), &width, &height, &channels, 0);
if (!data)
{
std::cerr << "[AssetManager] failed to load texture: " << fullPath << " " << stbi_failure_reason() << std::endl;
return 0;
}
GLenum format;
if (channels == 1)
format = GL_RED;
else if (channels == 3)
format = GL_RGB;
else if (channels == 4)
format = GL_RGBA;
else
format = GL_RGB; // Default fallback
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0,
format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
// Set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(data);
return textureID;
}
Model* LoadModelFromList(const std::string &path)
{ {
// -------------------------------------------- // --------------------------------------------
// Load an OBJ model // Load an OBJ model
@ -164,7 +211,7 @@ Model *LoadModelFromList(const std::string &path)
std::ifstream objFile(path); std::ifstream objFile(path);
if (!objFile.is_open()) if (!objFile.is_open())
{ {
DEBUG_PRINT("[AssetManager] Failed to open OBJ file: %s\n", path.c_str()); std::cerr << "[AssetManager] Failed to open OBJ file: " << path << std::endl;
return nullptr; return nullptr;
} }
@ -173,6 +220,14 @@ Model *LoadModelFromList(const std::string &path)
std::vector<float> temp_normals; std::vector<float> temp_normals;
std::vector<unsigned int> vertexIndices, texCoordIndices, normalIndices; std::vector<unsigned int> vertexIndices, texCoordIndices, normalIndices;
// Preallocate vectors with estimated sizes for performance
temp_positions.reserve(1000);
temp_texCoords.reserve(500);
temp_normals.reserve(500);
vertexIndices.reserve(3000);
texCoordIndices.reserve(3000);
normalIndices.reserve(3000);
std::string directory; std::string directory;
size_t lastSlash = path.find_last_of("/\\"); size_t lastSlash = path.find_last_of("/\\");
if (lastSlash != std::string::npos) if (lastSlash != std::string::npos)
@ -180,12 +235,15 @@ Model *LoadModelFromList(const std::string &path)
else else
directory = ""; directory = "";
DEBUG_PRINT("[AssetManager] Asset Directory: %s", directory.c_str()); std::cout << "[AssetManager] Asset Directory: " << directory << std::endl;
std::string line; std::string line;
std::string mtlFileName; std::string mtlFileName;
while (std::getline(objFile, line)) while (std::getline(objFile, line))
{ {
if (line.empty() || line[0] == '#')
continue; // Skip empty lines and comments
std::istringstream iss(line); std::istringstream iss(line);
std::string prefix; std::string prefix;
iss >> prefix; iss >> prefix;
@ -193,8 +251,9 @@ Model *LoadModelFromList(const std::string &path)
{ {
float x, y, z; float x, y, z;
iss >> x >> y >> z; iss >> x >> y >> z;
// Flip the model vertically by inverting the y-axis
temp_positions.push_back(x); temp_positions.push_back(x);
temp_positions.push_back(y); temp_positions.push_back(-y); // Inverted
temp_positions.push_back(z); temp_positions.push_back(z);
} }
else if (prefix == "vt") else if (prefix == "vt")
@ -208,8 +267,9 @@ Model *LoadModelFromList(const std::string &path)
{ {
float nx, ny, nz; float nx, ny, nz;
iss >> nx >> ny >> nz; iss >> nx >> ny >> nz;
// Invert the y-axis for normals as well
temp_normals.push_back(nx); temp_normals.push_back(nx);
temp_normals.push_back(ny); temp_normals.push_back(-ny); // Inverted
temp_normals.push_back(nz); temp_normals.push_back(nz);
} }
else if (prefix == "f") else if (prefix == "f")
@ -250,7 +310,7 @@ Model *LoadModelFromList(const std::string &path)
faceVertices.emplace_back(vIdx, tIdx, nIdx); faceVertices.emplace_back(vIdx, tIdx, nIdx);
} }
// Triangulate if the face has more than 3 vertices (optional) // Triangulate if the face has more than 3 vertices
for (size_t i = 1; i + 1 < faceVertices.size(); ++i) for (size_t i = 1; i + 1 < faceVertices.size(); ++i)
{ {
vertexIndices.push_back(std::get<0>(faceVertices[0])); vertexIndices.push_back(std::get<0>(faceVertices[0]));
@ -266,7 +326,6 @@ Model *LoadModelFromList(const std::string &path)
normalIndices.push_back(std::get<2>(faceVertices[i + 1])); normalIndices.push_back(std::get<2>(faceVertices[i + 1]));
} }
} }
else if (prefix == "mtllib") else if (prefix == "mtllib")
{ {
iss >> mtlFileName; iss >> mtlFileName;
@ -276,52 +335,123 @@ Model *LoadModelFromList(const std::string &path)
objFile.close(); objFile.close();
// Load MTL file if specified // Load MTL file if specified
std::string texturePath; std::vector<Texture> textures;
if (!mtlFileName.empty()) if (!mtlFileName.empty())
{ {
std::ifstream mtlFile(directory + mtlFileName); std::ifstream mtlFile(directory + mtlFileName);
if (mtlFile.is_open()) if (mtlFile.is_open())
{ {
while (std::getline(mtlFile, line)) std::string mtlLine;
std::string currentMaterial;
std::unordered_map<std::string, std::string> materialTextures;
while (std::getline(mtlFile, mtlLine))
{ {
std::istringstream mtlIss(line); if (mtlLine.empty() || mtlLine[0] == '#')
continue; // Skip comments and empty lines
std::istringstream mtlIss(mtlLine);
std::string mtlPrefix; std::string mtlPrefix;
mtlIss >> mtlPrefix; mtlIss >> mtlPrefix;
if (mtlPrefix == "map_Kd")
if (mtlPrefix == "newmtl")
{ {
mtlIss >> texturePath; mtlIss >> currentMaterial;
break; // Assuming only one texture map for simplicity
} }
else if (mtlPrefix == "map_Kd")
{
std::string texturePath;
mtlIss >> texturePath;
if (!texturePath.empty())
{
GLuint texID = LoadTexture(texturePath, directory);
if (texID != 0)
{
Texture texture;
texture.id = texID;
texture.type = "texture_diffuse";
texture.path = texturePath;
textures.push_back(texture);
}
}
}
else if (mtlPrefix == "map_Ks")
{
std::string texturePath;
mtlIss >> texturePath;
if (!texturePath.empty())
{
GLuint texID = LoadTexture(texturePath, directory);
if (texID != 0)
{
Texture texture;
texture.id = texID;
texture.type = "texture_specular";
texture.path = texturePath;
textures.push_back(texture);
}
}
}
else if (mtlPrefix == "map_Bump" || mtlPrefix == "map_bump" || mtlPrefix == "bump")
{
std::string texturePath;
mtlIss >> texturePath;
if (!texturePath.empty())
{
GLuint texID = LoadTexture(texturePath, directory);
if (texID != 0)
{
Texture texture;
texture.id = texID;
texture.type = "texture_normal";
texture.path = texturePath;
textures.push_back(texture);
}
}
}
// Add more texture types as needed
} }
mtlFile.close(); mtlFile.close();
} }
else else
{ {
DEBUG_PRINT("[AssetManager] Failed to open MTL file: %s", mtlFileName.c_str()); std::cerr << "[AssetManager] Failed to open MTL file: " << mtlFileName << std::endl;
} }
} }
if (texturePath.empty())
{
DEBUG_PRINT("[AssetManager] No texture found for OBJ: %s", path.c_str());
}
else else
{ {
DEBUG_PRINT("[AssetManager] Texture for OBJ: %s%s", directory.c_str(), texturePath.c_str()); std::cout << "[AssetManager] No MTL file specified for OBJ: " << path << std::endl;
}
if (textures.empty())
{
std::cout << "[AssetManager] No textures found for OBJ: " << path << std::endl;
}
else
{
std::cout << "[AssetManager] Loaded " << textures.size() << " textures for OBJ: " << path << std::endl;
} }
// Create Model object // Create Model object
Model *model = new Model(); Model *model = new Model();
model->textures = textures;
// Populate vertices // Populate vertices with unique vertices
std::unordered_map<std::string, unsigned int> uniqueVertices; std::unordered_map<std::string, unsigned int> uniqueVertices;
uniqueVertices.reserve(vertexIndices.size());
model->vertices.reserve(vertexIndices.size());
model->indices.reserve(vertexIndices.size());
for (size_t i = 0; i < vertexIndices.size(); ++i) for (size_t i = 0; i < vertexIndices.size(); ++i)
{ {
std::ostringstream keyStream; std::ostringstream keyStream;
keyStream << vertexIndices[i] << "/" << texCoordIndices[i] << "/" << normalIndices[i]; keyStream << vertexIndices[i] << "/" << texCoordIndices[i] << "/" << normalIndices[i];
std::string key = keyStream.str(); std::string key = keyStream.str();
if (uniqueVertices.find(key) == uniqueVertices.end()) auto it = uniqueVertices.find(key);
if (it == uniqueVertices.end())
{ {
Vertex vertex; Vertex vertex;
// OBJ indices are 1-based // OBJ indices are 1-based
@ -329,7 +459,7 @@ Model *LoadModelFromList(const std::string &path)
vertex.position[1] = temp_positions[(vertexIndices[i] - 1) * 3 + 1]; vertex.position[1] = temp_positions[(vertexIndices[i] - 1) * 3 + 1];
vertex.position[2] = temp_positions[(vertexIndices[i] - 1) * 3 + 2]; vertex.position[2] = temp_positions[(vertexIndices[i] - 1) * 3 + 2];
if (!temp_texCoords.empty()) if (!temp_texCoords.empty() && texCoordIndices[i] > 0)
{ {
vertex.texCoord[0] = temp_texCoords[(texCoordIndices[i] - 1) * 2]; vertex.texCoord[0] = temp_texCoords[(texCoordIndices[i] - 1) * 2];
vertex.texCoord[1] = temp_texCoords[(texCoordIndices[i] - 1) * 2 + 1]; vertex.texCoord[1] = temp_texCoords[(texCoordIndices[i] - 1) * 2 + 1];
@ -340,7 +470,7 @@ Model *LoadModelFromList(const std::string &path)
vertex.texCoord[1] = 0.0f; vertex.texCoord[1] = 0.0f;
} }
if (!temp_normals.empty()) if (!temp_normals.empty() && normalIndices[i] > 0)
{ {
vertex.normal[0] = temp_normals[(normalIndices[i] - 1) * 3]; vertex.normal[0] = temp_normals[(normalIndices[i] - 1) * 3];
vertex.normal[1] = temp_normals[(normalIndices[i] - 1) * 3 + 1]; vertex.normal[1] = temp_normals[(normalIndices[i] - 1) * 3 + 1];
@ -360,7 +490,7 @@ Model *LoadModelFromList(const std::string &path)
} }
else else
{ {
model->indices.push_back(uniqueVertices[key]); model->indices.push_back(it->second);
} }
} }
@ -379,56 +509,17 @@ Model *LoadModelFromList(const std::string &path)
// Vertex positions // Vertex positions
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
// Texture coordinates // Texture coordinates
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(3 * sizeof(float))); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(3 * sizeof(float)));
// Normals // Normals
glEnableVertexAttribArray(2); glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(5 * sizeof(float))); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(5 * sizeof(float)));
glBindVertexArray(0); glBindVertexArray(0);
// Load texture if available // The textures are already loaded and stored in the model->textures vector
if (!texturePath.empty())
{
int width, height, channels;
unsigned char *data = stbi_load((directory + texturePath).c_str(), &width, &height, &channels, 0);
if (!data)
{
DEBUG_PRINT("[AssetManager] stb_image failed to load texture: %s", (directory + texturePath).c_str());
}
else
{
GLenum format = GL_RGBA;
if (channels == 1)
format = GL_RED;
else if (channels == 3)
format = GL_RGB;
// if channels == 4, already GL_RGBA
glGenTextures(1, &model->textureID);
glBindTexture(GL_TEXTURE_2D, model->textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0,
format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
// Set texture params
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(data);
}
}
else
{
model->textureID = 0; // No texture
}
// Return the Model pointer as void*
return model; return model;
} }

View File

@ -34,17 +34,18 @@ struct Vertex
float normal[3]; float normal[3];
}; };
struct Model // Define a Texture structure
{ struct Texture {
GLuint id;
std::string type;
std::string path;
};
struct Model {
std::vector<Vertex> vertices; std::vector<Vertex> vertices;
std::vector<unsigned int> indices; std::vector<unsigned int> indices;
GLuint vao; std::vector<Texture> textures;
GLuint vbo; GLuint vao, vbo, ebo;
GLuint ebo;
GLuint textureID;
Model()
: vao(0), vbo(0), ebo(0), textureID(0) {}
}; };
// The main AssetManager // The main AssetManager

View File

@ -220,6 +220,76 @@ void LuaManager::Update(float deltaTime)
} }
} }
// Update function called every frame
void LuaManager::CallLuaFunction(std::string functionName)
{
if (!m_LuaState)
{
if (g_LoggerWindow)
{
g_LoggerWindow->AddLog("LuaManager: Lua state is not initialized.", std::optional<ImVec4>(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)));
}
else
{
DEBUG_PRINT("LuaManager: Lua state is not initialized.");
}
return;
}
// Push the 'OnUpdate' function onto the stack
lua_getglobal(m_LuaState, functionName.c_str());
if (!lua_isfunction(m_LuaState, -1))
{
DEBUG_PRINT("LuaManager: 'OnUpdate' is not a function.");
return;
}
// Call the function with 0 argument and 0 return values
if (lua_pcall(m_LuaState, 0, 0, 0) != LUA_OK)
{
const char *luaError = lua_tostring(m_LuaState, -1);
if (luaError)
{
std::string errorMsg(luaError);
// Prevent duplicate error logs
if (errorMsg != m_LastErrorMessage)
{
if (g_LoggerWindow)
{
std::string formattedError = "LuaManager Error in " + functionName + ": " + errorMsg;
ImVec4 redColor = ImVec4(1.0f, 0.0f, 0.0f, 1.0f);
g_LoggerWindow->AddLog(formattedError.c_str(), std::optional<ImVec4>(redColor));
}
else
{
DEBUG_PRINT("LuaManager Error in OnUpdate: %s", errorMsg.c_str());
}
m_LastErrorMessage = errorMsg;
}
}
else
{
if (g_LoggerWindow)
{
g_LoggerWindow->AddLog("LuaManager: Unknown error in %s.", std::optional<ImVec4>(ImVec4(1.0f, 0.0f, 0.0f, 1.0f)), functionName.c_str());
}
else
{
DEBUG_PRINT("LuaManager: Unknown error in %s.", functionName.c_str());
}
}
lua_pop(m_LuaState, 1); // Remove error message from stack
return;
}
else
{
// Reset last error message on successful call
m_LastErrorMessage.clear();
}
}
// Binding function to log messages from Lua // Binding function to log messages from Lua
int LuaManager::Lua_Engine_Log(lua_State *L) int LuaManager::Lua_Engine_Log(lua_State *L)
{ {
@ -322,7 +392,6 @@ int LuaManager::Lua_GetGameObjectByTag(lua_State *L)
return 1; // Return the GameObject userdata return 1; // Return the GameObject userdata
} }
// Binding function to retrieve a Component by name from a GameObject // Binding function to retrieve a Component by name from a GameObject
int LuaManager::Lua_GameObject_GetComponent(lua_State *L) int LuaManager::Lua_GameObject_GetComponent(lua_State *L)
{ {
@ -354,7 +423,6 @@ int LuaManager::Lua_GameObject_GetComponent(lua_State *L)
return 1; return 1;
} }
// Determine which metatable to use based on the component type // Determine which metatable to use based on the component type
if (strcmp(componentNameStr, "Transform") == 0) if (strcmp(componentNameStr, "Transform") == 0)
{ {
@ -400,7 +468,6 @@ int LuaManager::Lua_GameObject_GetComponent(lua_State *L)
// Set the metatable for the userdata // Set the metatable for the userdata
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
return 1; // Return the Component userdata return 1; // Return the Component userdata
} }
@ -518,7 +585,6 @@ int LuaManager::Lua_TransformComponent_GetRotation(lua_State *L)
return 1; // Return the position table return 1; // Return the position table
} }
// Binding function to set a TransformComponent's position // Binding function to set a TransformComponent's position
int LuaManager::Lua_TransformComponent_SetRotation(lua_State *L) int LuaManager::Lua_TransformComponent_SetRotation(lua_State *L)
{ {
@ -561,31 +627,7 @@ int LuaManager::Lua_TransformComponent_SetRotation(lua_State *L)
return 0; // No return values return 0; // No return values
} }
// Binding function to retrieve a MeshComponent's mesh data
int LuaManager::Lua_MeshComponent_GetMeshData(lua_State *L)
{
// Ensure the first argument is a userdata with MeshComponentMetaTable
MeshComponent **udata = (MeshComponent **)luaL_checkudata(L, 1, "MeshComponentMetaTable");
if (udata == nullptr || *udata == nullptr)
{
lua_pushstring(L, "Invalid MeshComponent.");
lua_error(L);
return 0;
}
// Example: Push mesh data as a table
// Ensure MeshData is defined appropriately in MeshComponent
GLuint ID = (*udata)->textureID; // Assume MeshData is a struct with relevant fields
lua_newtable(L);
lua_pushnumber(L, ID);
lua_setfield(L, -2, "vertexData");
// lua_pushstring(L, ID.indexData.c_str());
// lua_setfield(L, -2, "indexData");
// Add more mesh data fields as needed
return 1; // Return the mesh data table
}
// Binding function to retrieve a ScriptComponent's script path // Binding function to retrieve a ScriptComponent's script path
int LuaManager::Lua_ScriptComponent_GetScriptPath(lua_State *L) int LuaManager::Lua_ScriptComponent_GetScriptPath(lua_State *L)
@ -700,10 +742,6 @@ void LuaManager::RegisterMeshComponentMetaTable()
luaL_getmetatable(m_LuaState, "ComponentMetaTable"); luaL_getmetatable(m_LuaState, "ComponentMetaTable");
lua_setfield(m_LuaState, -2, "__base"); lua_setfield(m_LuaState, -2, "__base");
// Add methods specific to MeshComponent
lua_pushcfunction(m_LuaState, Lua_MeshComponent_GetMeshData);
lua_setfield(m_LuaState, -2, "GetMeshData");
// Add more Mesh-specific methods as needed // Add more Mesh-specific methods as needed
lua_settable(m_LuaState, -3); // Set __index to the table with methods lua_settable(m_LuaState, -3); // Set __index to the table with methods

View File

@ -55,6 +55,10 @@ public:
*/ */
void Update(float deltaTime); void Update(float deltaTime);
void CallLuaFunction(std::string functionName);
private: private:
// Lua state // Lua state
std::string ScriptPath; std::string ScriptPath;

View File

@ -8,6 +8,7 @@
extern std::vector<GameObject> g_GameObjects; extern std::vector<GameObject> g_GameObjects;
extern GameObject *g_SelectedObject; // Pointer to the currently selected object extern GameObject *g_SelectedObject; // Pointer to the currently selected object
extern std::shared_ptr<CameraComponent> g_RuntimeCameraObject;
extern LoggerWindow *g_LoggerWindow; extern LoggerWindow *g_LoggerWindow;
@ -73,7 +74,6 @@ void InspectorWindow::Show()
// 2) ADD COMPONENT SECTION // 2) ADD COMPONENT SECTION
// =========================== // ===========================
ImGui::Text("Add Component:"); ImGui::Text("Add Component:");
ImGui::SameLine(); ImGui::SameLine();
@ -154,7 +154,6 @@ void InspectorWindow::Show()
ImGui::Separator(); ImGui::Separator();
// =========================== // ===========================
// 1) TRANSFORM // 1) TRANSFORM
// =========================== // ===========================
@ -162,6 +161,7 @@ void InspectorWindow::Show()
std::shared_ptr<TransformComponent> transform = g_SelectedObject->GetComponent<TransformComponent>(); std::shared_ptr<TransformComponent> transform = g_SelectedObject->GetComponent<TransformComponent>();
std::shared_ptr<MeshComponent> mesh = g_SelectedObject->GetComponent<MeshComponent>(); std::shared_ptr<MeshComponent> mesh = g_SelectedObject->GetComponent<MeshComponent>();
std::shared_ptr<ScriptComponent> script = g_SelectedObject->GetComponent<ScriptComponent>(); std::shared_ptr<ScriptComponent> script = g_SelectedObject->GetComponent<ScriptComponent>();
std::shared_ptr<CameraComponent> camera = g_SelectedObject->GetComponent<CameraComponent>();
// Color the Transform header // Color the Transform header
@ -376,52 +376,292 @@ void InspectorWindow::Show()
} }
} }
if (camera)
{
// Styling: Set text color to white for the header
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
// Create a collapsing header for the Camera component
bool cameraOpen = ImGui::CollapsingHeader("Camera##CamerInspector", ImGuiTreeNodeFlags_DefaultOpen);
ImGui::PopStyleColor(); // Revert text color
if (cameraOpen)
{
// Edit Field of View (FOV)
if (ImGui::InputFloat("Field of View°", &camera->FOV, 1.0f, 10.0f, "%.1f"))
{
// Optionally, validate or clamp FOV values
if (camera->FOV < 1.0f)
camera->FOV = 1.0f;
if (camera->FOV > 179.0f)
camera->FOV = 179.0f;
}
// Edit Near Plane
if (ImGui::InputFloat("Near Plane", &camera->NearPlane, 0.1f, 1.0f, "%.2f"))
{
// Clamp Near Plane to a minimum value to prevent rendering issues
if (camera->NearPlane < 0.1f)
camera->NearPlane = 0.1f;
// Ensure Near Plane is always less than Far Plane
if (camera->NearPlane >= camera->FarPlane)
camera->NearPlane = camera->FarPlane - 0.1f;
}
// Edit Far Plane
if (ImGui::InputFloat("Far Plane", &camera->FarPlane, 10.0f, 100.0f, "%.2f"))
{
// Clamp Far Plane to a minimum value greater than Near Plane
if (camera->FarPlane <= camera->NearPlane)
camera->FarPlane = camera->NearPlane + 0.1f;
}
// Edit Aspect Ratio
if (ImGui::InputFloat("Aspect Ratio", &camera->AspectRatio, 0.01f, 0.1f, "%.2f"))
{
// Optionally, validate or clamp Aspect Ratio values
if (camera->AspectRatio <= 0.0f)
camera->AspectRatio = 1.77f; // Default to 16:9
}
// *** Begin Changed Code ***
// Replace the "Orthographic" Checkbox with a "Perspective" Switch
// Determine if the current camera is in perspective mode
bool isPerspective = camera->IsPerspective;
// Render the switch (styled checkbox to resemble a switch)
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 2));
if (ImGui::Checkbox("Perspective", &isPerspective))
{
camera->IsPerspective = isPerspective;
if (isPerspective)
{
// Set to Perspective Projection
// Use existing camera properties or set to default values
camera->SetPerspective(camera->FOV, camera->AspectRatio, camera->NearPlane, camera->FarPlane);
}
else
{
// Set to Orthographic Projection
// Define orthographic boundaries based on current aspect ratio or set to default values
float orthoLeft = -camera->AspectRatio;
float orthoRight = camera->AspectRatio;
float orthoBottom = -1.0f;
float orthoTop = 1.0f;
camera->SetOrthographic(orthoLeft, orthoRight, orthoBottom, orthoTop, camera->NearPlane, camera->FarPlane);
}
// Update the global primary camera if needed
g_RuntimeCameraObject = camera;
// Log the projection mode change
std::string projectionMode = isPerspective ? "Perspective" : "Orthographic";
g_LoggerWindow->AddLog("Changed Projection Mode to %s for Camera: %s",
ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
projectionMode.c_str(),
g_SelectedObject->name.c_str());
}
ImGui::PopStyleVar();
// Optional: Add a tooltip for the Perspective switch
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Toggle between Perspective and Orthographic projection modes.");
ImGui::EndTooltip();
}
// *** End Changed Code ***
// Add more camera properties here as needed
ImGui::Spacing();
// Replace the "Set as Primary" Button with a Checkbox
// Determine if the current camera is the primary camera
bool isPrimary = (g_RuntimeCameraObject == camera);
// Render the Checkbox
if (ImGui::Checkbox("Primary", &isPrimary))
{
if (isPrimary)
{
// Assign the current camera as the primary camera
g_RuntimeCameraObject = camera;
camera->DefaultRuntimeCamera = true;
// unset other cameras' DefaultRuntimeCamera flags
//! Not used because I don't want to
/*
for (auto& [name, cam] : allCameras)
{
if (cam != camera)
cam->DefaultRuntimeCamera = false;
}
*/
// Log the event
g_LoggerWindow->AddLog("Set Primary Camera: %s", ImVec4(0.0f, 1.0f, 0.0f, 1.0f), g_SelectedObject->name.c_str());
}
else
{
// If unchecked and this camera was the primary, unset it
if (g_RuntimeCameraObject == camera)
g_RuntimeCameraObject.reset(); // Assuming SharedPtr has a reset method
camera->DefaultRuntimeCamera = false;
// Log the event
g_LoggerWindow->AddLog("Unset Primary Camera: %s", ImVec4(1.0f, 0.0f, 0.0f, 1.0f), g_SelectedObject->name.c_str());
}
}
//// Optional: Indicate if this camera is currently the primary camera
// if (g_RuntimeCameraObject == camera)
//{
// ImGui::SameLine();
// ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "(Primary)");
// }
}
}
// Inside your RenderWindow.cpp or the relevant ImGui rendering function
if (mesh && g_SelectedObject) if (mesh && g_SelectedObject)
{ {
// Transform* transform = &g_SelectedObject->transform;
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
bool meshOpen = ImGui::CollapsingHeader("Mesh##Main", ImGuiTreeNodeFlags_DefaultOpen); bool meshOpen = ImGui::CollapsingHeader("Mesh##Main", ImGuiTreeNodeFlags_DefaultOpen);
ImGui::PopStyleColor(); ImGui::PopStyleColor();
// printf("%p\n", &transform);
if (meshOpen) if (meshOpen)
{ {
// --- VAO ---
int vao = static_cast<int>(mesh->vao); int vao = static_cast<int>(mesh->vao);
if (ImGui::InputInt("vao", &vao, 1, 0)) if (ImGui::InputInt("VAO", &vao, 1, 0))
{ {
mesh->vao = static_cast<GLuint>(vao); mesh->vao = static_cast<GLuint>(vao);
} }
// --- Index Count ---
int indexCount = static_cast<int>(mesh->indexCount); int indexCount = static_cast<int>(mesh->indexCount);
if (ImGui::InputInt("indexCount", &indexCount, 1, 0)) if (ImGui::InputInt("Index Count", &indexCount, 1, 0))
{ {
mesh->indexCount = static_cast<GLuint>(indexCount); mesh->indexCount = static_cast<GLuint>(indexCount);
} }
int textureID = static_cast<int>(mesh->textureID); // --- Mesh Path ---
if (ImGui::InputInt("textureID", &textureID, 1, 0))
{
mesh->textureID = static_cast<GLuint>(textureID);
}
// Define a maximum buffer size
const size_t BUFFER_SIZE = 256; const size_t BUFFER_SIZE = 256;
// Allocate a buffer and initialize it with the current string
char buffer[BUFFER_SIZE]; char buffer[BUFFER_SIZE];
strncpy(buffer, mesh->MeshPath.c_str(), BUFFER_SIZE - 1); strncpy(buffer, mesh->MeshPath.c_str(), BUFFER_SIZE - 1);
buffer[BUFFER_SIZE - 1] = '\0'; // Ensure null-termination buffer[BUFFER_SIZE - 1] = '\0'; // Ensure null-termination
// Render the InputText widget
if (ImGui::InputText(mesh->MeshPath.c_str(), buffer, BUFFER_SIZE)) if (ImGui::InputText("Mesh Path", buffer, BUFFER_SIZE))
{ {
// Update the string if user made changes
mesh->MeshPath = buffer; mesh->MeshPath = buffer;
// Optionally, trigger reloading the mesh if the path changes
// e.g., g_AssetManager.loadAsset<Model *>(AssetType::MODEL, mesh->MeshPath.c_str());
} }
// --- Textures ---
ImGui::Separator();
ImGui::Text("Textures:");
// Display list of textures
float availableWidth = ImGui::GetContentRegionAvail().x; float availableWidth = ImGui::GetContentRegionAvail().x;
ImGui::Image(mesh->textureID, ImVec2(availableWidth, availableWidth), ImVec2(0, 0), ImVec2(1, 1)); for (size_t i = 0; i < mesh->textures.size(); ++i)
{
Texture &texture = mesh->textures[i];
// Create a unique identifier for each texture section
std::string header = "Texture " + std::to_string(i + 1) + "##" + std::to_string(i);
// Collapsing header for each texture
if (ImGui::CollapsingHeader(header.c_str(), ImGuiTreeNodeFlags_DefaultOpen))
{
// --- Texture Type ---
char typeBuffer[32];
strncpy(typeBuffer, texture.type.c_str(), sizeof(typeBuffer) - 1);
typeBuffer[sizeof(typeBuffer) - 1] = '\0';
if (ImGui::InputText(("Type##" + std::to_string(i)).c_str(), typeBuffer, sizeof(typeBuffer)))
{
texture.type = std::string(typeBuffer);
// Optionally, validate the type or restrict it to certain values
}
// --- Texture ID ---
int texID = static_cast<int>(texture.id);
if (ImGui::InputInt(("Texture ID##" + std::to_string(i)).c_str(), &texID, 1, 0))
{
texture.id = static_cast<GLuint>(texID);
}
// --- Texture Path ---
char pathBuffer[256];
strncpy(pathBuffer, texture.path.c_str(), sizeof(pathBuffer) - 1);
pathBuffer[sizeof(pathBuffer) - 1] = '\0';
if (ImGui::InputText(("Path##" + std::to_string(i)).c_str(), pathBuffer, sizeof(pathBuffer)))
{
texture.path = std::string(pathBuffer);
// Optionally, trigger reloading the texture if the path changes
// e.g., texture.id = g_AssetManager.loadTexture(texture.path, directory);
}
// --- Texture Preview ---
if (texture.id != 0)
{
// Retrieve the texture's width and height if needed
// For demonstration, using a fixed size
ImGui::Image(static_cast<ImTextureID>(texture.id), ImVec2(availableWidth, availableWidth), ImVec2(0, 0), ImVec2(1, 1));
}
else
{
ImGui::Text("No texture bound.");
}
// --- Remove Texture Button ---
std::string removeButtonLabel = "Remove##" + std::to_string(i);
if (ImGui::Button(removeButtonLabel.c_str()))
{
mesh->textures.erase(mesh->textures.begin() + i);
// Adjust index after removal
ImGui::TreePop();
break; // Exit the loop as the current index is invalidated
}
ImGui::Separator();
}
}
// --- Add New Texture Button ---
// if (ImGui::Button("Add Texture"))
//{
// // Define default values for the new texture
// Texture newTexture;
// newTexture.id = 0; // Assign a default or invalid texture ID
// newTexture.type = "texture_diffuse"; // Default type
// newTexture.path = "path/to/texture.png"; // Default path
//
// mesh->textures.push_back(newTexture);
//}
//
// --- Display All Textures ---
// Optionally, display all textures in a separate section or after the list
} }
} }
ImGui::Spacing(); ImGui::Spacing();
if (script && g_SelectedObject) if (script && g_SelectedObject)
@ -444,7 +684,6 @@ void InspectorWindow::Show()
buffer[BUFFER_SIZE - 1] = '\0'; // Ensure null-termination buffer[BUFFER_SIZE - 1] = '\0'; // Ensure null-termination
// Render the InputText widget // Render the InputText widget
if (ImGui::InputText("Script Path", buffer, BUFFER_SIZE)) if (ImGui::InputText("Script Path", buffer, BUFFER_SIZE))
{ {
@ -458,6 +697,7 @@ void InspectorWindow::Show()
if (script->Initialize()) if (script->Initialize())
{ {
script->Init();
g_LoggerWindow->AddLog("Reloaded Script: %s", ImVec4(0.0f, 1.0f, 0.0f, 1.0f), script->ScriptPath.c_str()); g_LoggerWindow->AddLog("Reloaded Script: %s", ImVec4(0.0f, 1.0f, 0.0f, 1.0f), script->ScriptPath.c_str());
} }
} }

View File

@ -13,43 +13,20 @@ ProfilerWindow::ProfilerWindow()
} }
// Calculate moving average
std::vector<float> ProfilerWindow::MovingAverage(const std::deque<double>& data, size_t window)
{
std::vector<float> averages;
if (data.size() < window)
window = data.size();
for (size_t i = 0; i <= data.size() - window; ++i)
{
double sum = 0.0; std::vector<float> ProfilerWindow::ExponentialMovingAverage(const std::deque<double>& data, float alpha) {
for (size_t j = i; j < i + window; ++j) std::vector<float> ema;
sum += data[j]; ema.reserve(data.size());
averages.push_back(static_cast<float>(sum / window)); float prev = 0.0f;
for (const auto& val : data) {
prev = alpha * static_cast<float>(val) + (1.0f - alpha) * prev;
ema.push_back(prev);
} }
return averages; return ema;
} }
std::vector<float> ProfilerWindow::ExponentialMovingAverage(const std::deque<double>& data, float alpha)
{
std::vector<float> smoothedData;
if (data.empty())
return smoothedData;
float ema = static_cast<float>(data[0]); // Initialize EMA with the first value
smoothedData.push_back(ema);
for (size_t i = 1; i < data.size(); ++i)
{
ema = alpha * static_cast<float>(data[i]) + (1 - alpha) * ema;
smoothedData.push_back(ema);
}
return smoothedData;
}
// Update the history data structures with the latest profiling data
void ProfilerWindow::UpdateHistory(const std::unordered_map<std::string, ProfileResult>& data, double totalFrameTime) void ProfilerWindow::UpdateHistory(const std::unordered_map<std::string, ProfileResult>& data, double totalFrameTime)
{ {
// Update total frame time history // Update total frame time history
@ -57,8 +34,6 @@ void ProfilerWindow::UpdateHistory(const std::unordered_map<std::string, Profile
if (m_TotalFrameTimeHistory.size() > MaxFrameHistory) if (m_TotalFrameTimeHistory.size() > MaxFrameHistory)
m_TotalFrameTimeHistory.pop_front(); m_TotalFrameTimeHistory.pop_front();
// Debug: Print the size of m_TotalFrameTimeHistory
// Update each function's profiling history // Update each function's profiling history
for (const auto& [name, result] : data) for (const auto& [name, result] : data)
{ {
@ -74,10 +49,43 @@ void ProfilerWindow::UpdateHistory(const std::unordered_map<std::string, Profile
history.averageTimeHistory.push_back(average); history.averageTimeHistory.push_back(average);
if (history.averageTimeHistory.size() > ProfileHistory::MaxHistory) if (history.averageTimeHistory.size() > ProfileHistory::MaxHistory)
history.averageTimeHistory.pop_front(); history.averageTimeHistory.pop_front();
// Update call count history
history.callCountHistory.push_back(result.CallCount);
if (history.callCountHistory.size() > ProfileHistory::MaxHistory)
history.callCountHistory.pop_front();
}
// Ensure that functions not present in the current frame retain their last TotalTime and AverageTime
for (auto& [name, history] : m_ProfileHistories)
{
if (data.find(name) == data.end())
{
// Retain last TotalTime and AverageTime by pushing back the last value again
if (!history.totalTimeHistory.empty())
history.totalTimeHistory.push_back(history.totalTimeHistory.back());
else
history.totalTimeHistory.push_back(0.0);
if (!history.averageTimeHistory.empty())
history.averageTimeHistory.push_back(history.averageTimeHistory.back());
else
history.averageTimeHistory.push_back(0.0);
// Update call count history with zero for this frame
history.callCountHistory.push_back(0);
// Maintain history sizes
if (history.totalTimeHistory.size() > ProfileHistory::MaxHistory)
history.totalTimeHistory.pop_front();
if (history.averageTimeHistory.size() > ProfileHistory::MaxHistory)
history.averageTimeHistory.pop_front();
if (history.callCountHistory.size() > ProfileHistory::MaxHistory)
history.callCountHistory.pop_front();
}
} }
} }
// Render the profiler window with table and graphs
void ProfilerWindow::Show() void ProfilerWindow::Show()
{ {
// Check if it's time to update the profiler data // Check if it's time to update the profiler data
@ -91,8 +99,8 @@ void ProfilerWindow::Show()
m_LastUpdateTime = now; m_LastUpdateTime = now;
} }
// Begin ImGui window // Begin ImGui window with improved styling
ImGui::Begin("Profiler"); ImGui::Begin("Profiler", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_HorizontalScrollbar);
const auto& data = Profiler::Get().GetLastFrameData(); const auto& data = Profiler::Get().GetLastFrameData();
@ -120,62 +128,72 @@ void ProfilerWindow::Show()
} }
// Render profiling data table // Render profiling data table
RenderTable(data); RenderTable();
// Render profiling graphs // Render profiling graphs
//RenderGraphs(); RenderGraphs();
// Display total frame time (from the last update) // Display total frame time (from the last update)
if (!m_TotalFrameTimeHistory.empty()) if (!m_TotalFrameTimeHistory.empty())
{ {
double lastTotalFrameTime = m_TotalFrameTimeHistory.back(); double lastTotalFrameTime = m_TotalFrameTimeHistory.back();
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Total Frame Time: %.3f µs", lastTotalFrameTime); ImGui::TextColored(ImVec4(0.4f, 0.7f, 0.0f, 1.0f), "Total Frame Time: %.3f µs", lastTotalFrameTime);
} }
ImGui::End(); ImGui::End();
} }
// Render the profiling data table void ProfilerWindow::RenderTable()
void ProfilerWindow::RenderTable(const std::unordered_map<std::string, ProfileResult>& data)
{ {
// Sort functions by total time descending // Collect all profiling histories
std::vector<std::pair<std::string, ProfileResult>> sortedData(data.begin(), data.end()); std::vector<std::pair<std::string, ProfileHistory>> allData(m_ProfileHistories.begin(), m_ProfileHistories.end());
std::sort(sortedData.begin(), sortedData.end(),
[](const std::pair<std::string, ProfileResult>& a, const std::pair<std::string, ProfileResult>& b) -> bool { // Sort functions by last Total Time descending
return a.second.TotalTime > b.second.TotalTime; std::sort(allData.begin(), allData.end(),
[](const std::pair<std::string, ProfileHistory>& a, const std::pair<std::string, ProfileHistory>& b) -> bool {
return a.second.totalTimeHistory.back() > b.second.totalTimeHistory.back();
}); });
// Add a filter input // Add a filter input with enhanced styling
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 2));
static char filterBuffer[128] = ""; static char filterBuffer[128] = "";
ImGui::InputText("Filter", filterBuffer, IM_ARRAYSIZE(filterBuffer)); ImGui::InputTextWithHint("##Filter", "Filter functions...", filterBuffer, IM_ARRAYSIZE(filterBuffer));
ImGui::PopStyleVar();
// Convert filter to string // Convert filter to string
std::string filterStr = filterBuffer; std::string filterStr = filterBuffer;
// Filtered data // Filtered data
std::vector<std::pair<std::string, ProfileResult>> filteredData; std::vector<std::pair<std::string, ProfileHistory>> filteredData;
for (const auto& [name, result] : sortedData) for (const auto& [name, history] : allData)
{ {
if (filterStr.empty() || name.find(filterStr) != std::string::npos) if (filterStr.empty() || name.find(filterStr) != std::string::npos)
filteredData.emplace_back(name, result); filteredData.emplace_back(name, history);
} }
// Define threshold for highlighting (e.g., 1000 µs) // Define threshold for highlighting (e.g., 1000 µs)
const double highlightThreshold = 1000.0; const double highlightThreshold = 1000.0;
// Table with sorted data // Improved table with sorting indicators and better aesthetics
if (ImGui::BeginTable("ProfilerTable", 4, ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable)) if (ImGui::BeginTable("ProfilerTable", 4, ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY, ImVec2(0, 300)))
{ {
// Set up columns with sortable headers
ImGui::TableSetupColumn("Function", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("Function", ImGuiTableColumnFlags_None);
ImGui::TableSetupColumn("Total Time (µs)", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("Total Time (µs)", ImGuiTableColumnFlags_None);
ImGui::TableSetupColumn("Average Time (µs)", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("Average Time (µs)", ImGuiTableColumnFlags_None);
ImGui::TableSetupColumn("Calls", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("Calls (This Frame)", ImGuiTableColumnFlags_None);
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
for (const auto& [name, result] : filteredData) // Alternate row colors for better readability
bool rowBg = false;
for (const auto& [name, history] : filteredData)
{ {
ImGui::TableNextRow(); ImGui::TableNextRow();
rowBg = !rowBg;
if (rowBg)
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, ImColor(0.1f, 0.1f, 0.1f, 1.0f));
// Function Name with tooltip // Function Name with tooltip
ImGui::TableSetColumnIndex(0); ImGui::TableSetColumnIndex(0);
@ -183,70 +201,58 @@ void ProfilerWindow::RenderTable(const std::unordered_map<std::string, ProfileRe
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
{ {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
ImGui::Text("Total Time: %.3f µs", result.TotalTime); ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f), "Function: %s", name.c_str());
double average = result.CallCount > 0 ? result.TotalTime / result.CallCount : 0.0; ImGui::Text("Total Time: %.3f µs", history.totalTimeHistory.back());
ImGui::Text("Average Time: %.3f µs", average); ImGui::Text("Average Time: %.3f µs", history.averageTimeHistory.back());
ImGui::Text("Call Count: %d", result.CallCount); ImGui::Text("Call Count (this frame): %d", history.callCountHistory.back());
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
// Total Time with color coding // Total Time with color coding
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
if (result.TotalTime > highlightThreshold) if (history.totalTimeHistory.back() > highlightThreshold)
ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "%.3f", result.TotalTime); ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "%.3f", history.totalTimeHistory.back());
else else
ImGui::Text("%.3f", result.TotalTime); ImGui::Text("%.3f", history.totalTimeHistory.back());
// Average Time // Average Time
ImGui::TableSetColumnIndex(2); ImGui::TableSetColumnIndex(2);
double average = result.CallCount > 0 ? result.TotalTime / result.CallCount : 0.0; ImGui::Text("%.3f", history.averageTimeHistory.back());
ImGui::Text("%.3f", average);
// Call Count // Call Count (This Frame)
ImGui::TableSetColumnIndex(3); ImGui::TableSetColumnIndex(3);
ImGui::Text("%d", result.CallCount); ImGui::Text("%d", history.callCountHistory.back());
} }
ImGui::EndTable(); ImGui::EndTable();
} }
} }
void ProfilerWindow::RenderGraphs() void ProfilerWindow::RenderGraphs()
{ {
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Profiling Graphs (Unified Multi-Line Plot)"); ImGui::TextColored(ImVec4(0.0f, 0.7f, 0.9f, 1.0f), "Profiling Graphs (Top 5 Functions)");
const auto& data = Profiler::Get().GetLastFrameData();
std::vector<std::pair<std::string, ProfileResult>> sortedData;
// Collect and sort functions by total time used
for (const auto& [name, result] : data)
{
sortedData.emplace_back(name, result);
}
// Collect and sort functions by last Total Time descending
std::vector<std::pair<std::string, ProfileHistory>> sortedData(m_ProfileHistories.begin(), m_ProfileHistories.end());
std::sort(sortedData.begin(), sortedData.end(), std::sort(sortedData.begin(), sortedData.end(),
[](const std::pair<std::string, ProfileResult>& a, const std::pair<std::string, ProfileResult>& b) -> bool { [](const std::pair<std::string, ProfileHistory>& a, const std::pair<std::string, ProfileHistory>& b) -> bool {
return a.second.TotalTime > b.second.TotalTime; return a.second.totalTimeHistory.back() > b.second.totalTimeHistory.back();
}); });
size_t displayCount = std::min<size_t>(5, sortedData.size()); // Limit to top 5 functions size_t displayCount = std::min<size_t>(5, sortedData.size()); // Limit to top 5 functions
// Prepare data for the unified plot // Prepare data for the unified plot with EMA smoothing
std::vector<std::vector<float>> plotData(displayCount); std::vector<std::vector<float>> plotData(displayCount);
std::vector<std::string> functionNames; std::vector<std::string> functionNames;
float alpha = 0.2f; // Smoothing factor for EMA float alpha = 0.2f; // Smoothing factor for EMA
for (size_t i = 0; i < displayCount; ++i) for (size_t i = 0; i < displayCount; ++i)
{ {
const auto& [name, result] = sortedData[i]; const auto& [name, history] = sortedData[i];
functionNames.push_back(name); functionNames.push_back(name);
// Smooth each function's data using EMA // Smooth each function's data using EMA
const auto& history = m_ProfileHistories[name];
plotData[i] = ExponentialMovingAverage(history.totalTimeHistory, alpha); plotData[i] = ExponentialMovingAverage(history.totalTimeHistory, alpha);
} }
@ -265,33 +271,40 @@ void ProfilerWindow::RenderGraphs()
// Prepare the combined graph // Prepare the combined graph
if (maxHistorySize > 0) if (maxHistorySize > 0)
{ {
std::vector<float> combinedGraph(maxHistorySize, 0.0f);
// Render a single unified graph with multi-line data
ImVec2 graphSize = ImVec2(0, 200); // Graph dimensions ImVec2 graphSize = ImVec2(0, 200); // Graph dimensions
ImGui::PlotLines( // Begin child region for better layout control
"##UnifiedGraph", ImGui::BeginChild("GraphChild", graphSize, false, ImGuiWindowFlags_NoScrollbar);
[](void* data, int idx) -> float {
auto* plotData = static_cast<std::vector<std::vector<float>>*>(data);
float value = 0.0f;
for (const auto& series : *plotData) // Plot each function's history as separate lines with unique colors
{ for (size_t i = 0; i < displayCount; ++i)
if (idx < series.size()) {
value += series[idx]; ImU32 color = ImColor::HSV(static_cast<float>(i) / displayCount, 0.6f, 0.9f);
} ImGui::PushStyleColor(ImGuiCol_PlotLines, color);
ImGui::PlotLines(
functionNames[i].c_str(),
plotData[i].data(),
static_cast<int>(plotData[i].size()),
0,
nullptr,
0.0f,
static_cast<float>(maxValue) * 1.1f, // Add some padding to the max value
ImVec2(0, 100)
);
ImGui::PopStyleColor();
}
return value; ImGui::EndChild();
},
static_cast<void*>(&plotData), static_cast<int>(maxHistorySize), 0, nullptr, 0.0f, maxValue, graphSize);
// Add a legend for the lines // Add a legend for the lines
ImGui::Separator(); ImGui::Separator();
for (size_t i = 0; i < functionNames.size(); ++i) for (size_t i = 0; i < functionNames.size(); ++i)
{ {
ImVec4 lineColor = ImVec4(0.2f + 0.2f * i, 0.2f, 1.0f - 0.2f * i, 1.0f); ImVec4 lineColor = ImColor::HSV(static_cast<float>(i) / displayCount, 0.6f, 0.9f);
ImGui::TextColored(lineColor, "%s", functionNames[i].c_str()); ImGui::SameLine();
ImGui::ColorButton(("##Color" + std::to_string(i)).c_str(), lineColor, ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop | ImGuiColorEditFlags_NoBorder, ImVec2(10, 10));
ImGui::SameLine();
ImGui::TextUnformatted(functionNames[i].c_str());
} }
} }
} }

View File

@ -9,35 +9,31 @@
class ProfilerWindow class ProfilerWindow
{ {
public: public:
ProfilerWindow(); ProfilerWindow();
~ProfilerWindow() = default;
// Render the profiler window void UpdateHistory(const std::unordered_map<std::string, ProfileResult> &data, double totalFrameTime);
void Show(); void Show();
void RenderTable();
void RenderGraphs();
private: private:
struct ProfileHistory struct ProfileHistory
{ {
std::deque<double> totalTimeHistory;
std::deque<double> averageTimeHistory;
static const size_t MaxHistory = 100; static const size_t MaxHistory = 100;
std::deque<double> totalTimeHistory; // Last N total times
std::deque<double> averageTimeHistory; // Last N average times
std::deque<int> callCountHistory; // Last N call counts
}; };
std::unordered_map<std::string, ProfileHistory> m_ProfileHistories; std::unordered_map<std::string, ProfileHistory> m_ProfileHistories;
std::deque<double> m_TotalFrameTimeHistory; std::deque<double> m_TotalFrameTimeHistory;
static const size_t MaxFrameHistory = 100; static const size_t MaxFrameHistory = 100;
// Timing variables for update throttling
double m_UpdateInterval; // Interval in seconds (0.1)
std::chrono::steady_clock::time_point m_LastUpdateTime; std::chrono::steady_clock::time_point m_LastUpdateTime;
double m_UpdateInterval; // In seconds
// Helper functions // Helper function for Exponential Moving Average
void UpdateHistory(const std::unordered_map<std::string, ProfileResult> &data, double totalFrameTime);
void RenderTable(const std::unordered_map<std::string, ProfileResult> &data);
void RenderGraphs();
// Helper for data smoothing
std::vector<float> MovingAverage(const std::deque<double> &data, size_t window);
std::vector<float> ExponentialMovingAverage(const std::deque<double> &data, float alpha); std::vector<float> ExponentialMovingAverage(const std::deque<double> &data, float alpha);
}; };

View File

@ -28,6 +28,10 @@ extern std::vector<std::shared_ptr<GameObject>> g_GameObjects;
extern AssetManager g_AssetManager; extern AssetManager g_AssetManager;
extern std::shared_ptr<CameraComponent> g_RuntimeCameraObject;
extern int g_GPU_Triangles_drawn_to_screen; extern int g_GPU_Triangles_drawn_to_screen;
// Example cube data (position + UVs) // Example cube data (position + UVs)
@ -284,7 +288,7 @@ void RenderWindow::Show(bool *GameRunning)
m_LastHeight = h; m_LastHeight = h;
} }
RenderSceneToFBO(); RenderSceneToFBO(GameRunning);
ImGui::Image(m_FBO.GetTextureID(), size, ImVec2(0, 0), ImVec2(1, 1)); ImGui::Image(m_FBO.GetTextureID(), size, ImVec2(0, 0), ImVec2(1, 1));
} }
@ -361,64 +365,104 @@ void RenderWindow::InitGLResources()
// ---------------------------------------------------- // ----------------------------------------------------
} }
void RenderWindow::RenderSceneToFBO()
{
m_RotationAngle += 0.001f; // spin per frame void CheckOpenGLError(const std::string &location)
{
GLenum err;
bool hasError = false;
while ((err = glGetError()) != GL_NO_ERROR)
{
std::cerr << "[OpenGL Error] (" << err << ") at " << location << std::endl;
hasError = true;
}
if (hasError)
{
// Optionally, you can throw an exception or handle the error as needed
}
}
void RenderWindow::RenderSceneToFBO(bool *GameRunning)
{
m_RotationAngle += 0.001f; // Spin per frame
// Bind the FBO // Bind the FBO
m_FBO.Bind(); m_FBO.Bind();
glViewport(0, 0, m_LastWidth, m_LastHeight); glViewport(0, 0, m_LastWidth, m_LastHeight);
CheckOpenGLError("After glViewport");
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
CheckOpenGLError("After glEnable(GL_DEPTH_TEST)");
glClearColor(0.f, 0.f, 0.f, 1.f); glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
CheckOpenGLError("After glClear");
// Use our loaded shader // Use our loaded shader
if (!m_ShaderPtr) if (!m_ShaderPtr)
{
std::cerr << "[RenderWindow] Shader pointer is null. Cannot render." << std::endl;
m_FBO.Unbind();
return; // Can't render without a shader return; // Can't render without a shader
}
m_ShaderPtr->Use(); m_ShaderPtr->Use();
GLuint programID = m_ShaderPtr->GetProgramID(); GLuint programID = m_ShaderPtr->GetProgramID();
CheckOpenGLError("After shader use");
// Define view and projection matrices once // Define view and projection matrices once
glm::mat4 view = glm::translate(glm::mat4(1.f), glm::vec3(0.f, 0.f, -5.f)); std::shared_ptr<CameraComponent> activeCamera = nullptr;
float aspect = (m_LastHeight != 0) ? (float)m_LastWidth / (float)m_LastHeight : 1.0f;
glm::mat4 proj = glm::perspective(glm::radians(CAM_FOV), aspect, CAM_NEAR_PLAIN, CAM_FAR_PLAIN); glm::mat4 view;
glm::mat4 proj;
if (*GameRunning && g_RuntimeCameraObject)
{
activeCamera = g_RuntimeCameraObject;
}
// Ensure that an active camera is available
if (activeCamera)
{
// Obtain view and projection matrices from the active camera
view = activeCamera->GetViewMatrix();
proj = activeCamera->GetProjectionMatrix();
}
else
{
// Fallback to default view and projection if no camera is available
view = glm::translate(glm::mat4(1.f), glm::vec3(0.f, 0.f, -5.f));
float aspect = (m_LastHeight != 0) ? (float)m_LastWidth / (float)m_LastHeight : 1.0f;
proj = glm::perspective(glm::radians(CAM_FOV), aspect, CAM_NEAR_PLAIN, CAM_FAR_PLAIN);
}
// Iterate over each GameObject and render it // Iterate over each GameObject and render it
for (auto &obj : g_GameObjects) for (auto &obj : g_GameObjects)
{ {
// -----------------------------------
// 1) Build MVP from transform
// -----------------------------------
glm::mat4 model = glm::mat4(1.f); glm::mat4 model = glm::mat4(1.f);
std::shared_ptr<TransformComponent> transform = obj->GetComponent<TransformComponent>(); std::shared_ptr<TransformComponent> transform = obj->GetComponent<TransformComponent>();
std::shared_ptr<MeshComponent> mesh = obj->GetComponent<MeshComponent>(); std::shared_ptr<MeshComponent> mesh = obj->GetComponent<MeshComponent>();
if (transform && mesh) if (transform && mesh)
{ {
// Validate VAO
if (mesh->vao == 0)
{
std::cerr << "[RenderWindow] Warning: Mesh VAO is not initialized." << std::endl;
continue;
}
// Translate // Update triangle count
g_GPU_Triangles_drawn_to_screen += static_cast<int>(mesh->indexCount); g_GPU_Triangles_drawn_to_screen += static_cast<int>(mesh->indexCount);
// Apply transformations
model = glm::translate(model, transform->position); model = glm::translate(model, transform->position);
// Rotate around X, Y, Z
// transform->rotation.x += m_RotationAngle;
model = glm::rotate(model, glm::radians(transform->rotation.x), glm::vec3(1.f, 0.f, 0.f)); model = glm::rotate(model, glm::radians(transform->rotation.x), glm::vec3(1.f, 0.f, 0.f));
model = glm::rotate(model, glm::radians(transform->rotation.y), glm::vec3(0.f, 1.f, 0.f)); model = glm::rotate(model, glm::radians(transform->rotation.y), glm::vec3(0.f, 1.f, 0.f));
model = glm::rotate(model, glm::radians(transform->rotation.z), glm::vec3(0.f, 0.f, 1.f)); model = glm::rotate(model, glm::radians(transform->rotation.z), glm::vec3(0.f, 0.f, 1.f));
// Scale
model = glm::scale(model, transform->scale); model = glm::scale(model, transform->scale);
// Compute MVP // Compute MVP
@ -426,31 +470,111 @@ void RenderWindow::RenderSceneToFBO()
// Pass MVP to the shader // Pass MVP to the shader
GLint mvpLoc = glGetUniformLocation(programID, "uMVP"); GLint mvpLoc = glGetUniformLocation(programID, "uMVP");
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, glm::value_ptr(mvp)); if(mvpLoc != -1)
{
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, glm::value_ptr(mvp));
}
else
{
std::cerr << "[RenderWindow] Warning: Uniform 'uMVP' not found in shader." << std::endl;
}
// Pass Model matrix to the shader
GLint modelLoc = glGetUniformLocation(programID, "uModel");
if(modelLoc != -1)
{
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
}
else
{
std::cerr << "[RenderWindow] Warning: Uniform 'uModel' not found in shader." << std::endl;
}
// ----------------------------------- // -----------------------------------
// 2) Bind the object's texture // 2) Bind the object's diffuse textures
// ----------------------------------- // -----------------------------------
glActiveTexture(GL_TEXTURE0); // Define the maximum number of diffuse textures as per the shader
glBindTexture(GL_TEXTURE_2D, mesh->textureID); const int MAX_DIFFUSE = 32; // Must match the shader's MAX_DIFFUSE
int textureUnit = 0;
// Set the sampler uniform to texture unit 0 // Iterate through all textures and bind those with type "texture_diffuse"
GLint texLoc = glGetUniformLocation(programID, "uTexture"); for (const auto &texture : mesh->textures)
glUniform1i(texLoc, 0); {
if (texture.type == "texture_diffuse")
{
if (textureUnit >= MAX_DIFFUSE)
{
std::cerr << "[RenderWindow] Warning: Exceeded maximum number of diffuse textures ("
<< MAX_DIFFUSE << ") for shader." << std::endl;
break; // Prevent exceeding the array bounds in the shader
}
// Activate the appropriate texture unit
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_2D, texture.id);
CheckOpenGLError("After glBindTexture");
// Construct the uniform name dynamically (e.g., "uTextures.texture_diffuse[0]")
std::string uniformName = "uTextures.texture_diffuse[" + std::to_string(textureUnit) + "]";
GLint texLoc = glGetUniformLocation(programID, uniformName.c_str());
if (texLoc != -1)
{
glUniform1i(texLoc, textureUnit);
CheckOpenGLError("After glUniform1i for texture");
}
else
{
std::cerr << "[RenderWindow] Warning: Uniform '" << uniformName
<< "' not found in shader." << std::endl;
}
textureUnit++;
}
}
// Assign default texture to unused texture slots
for(int i = textureUnit; i < MAX_DIFFUSE; ++i)
{
std::string uniformName = "uTextures.texture_diffuse[" + std::to_string(i) + "]";
GLint texLoc = glGetUniformLocation(programID, uniformName.c_str());
if(texLoc != -1)
{
glUniform1i(texLoc, 0); // Assign texture unit 0 (ensure texture 0 is a valid default)
CheckOpenGLError("After glUniform1i for default texture");
}
}
// Set the number of active diffuse textures
GLint numDiffuseLoc = glGetUniformLocation(programID, "uNumDiffuseTextures");
if(numDiffuseLoc != -1)
{
glUniform1i(numDiffuseLoc, textureUnit);
CheckOpenGLError("After glUniform1i for uNumDiffuseTextures");
}
else
{
std::cerr << "[RenderWindow] Warning: Uniform 'uNumDiffuseTextures' not found in shader." << std::endl;
}
// ----------------------------------- // -----------------------------------
// 3) Draw the object's mesh // 3) Draw the object's mesh
// ----------------------------------- // -----------------------------------
glBindVertexArray(mesh->vao); glBindVertexArray(mesh->vao);
glDrawElements(GL_TRIANGLES, mesh->indexCount, GL_UNSIGNED_INT, nullptr); glDrawElements(GL_TRIANGLES, mesh->indexCount, GL_UNSIGNED_INT, nullptr);
// Unbind for cleanliness
glBindVertexArray(0); glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0); CheckOpenGLError("After glDrawElements");
// Reset active texture
glActiveTexture(GL_TEXTURE0);
CheckOpenGLError("After glActiveTexture(GL_TEXTURE0)");
} }
} }
// Cleanup // Cleanup
glUseProgram(0); glUseProgram(0);
CheckOpenGLError("After glUseProgram(0)");
m_FBO.Unbind(); m_FBO.Unbind();
CheckOpenGLError("After FBO Unbind");
} }

View File

@ -12,7 +12,7 @@ public:
private: private:
void InitGLResources(); void InitGLResources();
void RenderSceneToFBO(); void RenderSceneToFBO(bool *GameRunning);
// Offscreen render target // Offscreen render target
FBO m_FBO; FBO m_FBO;