Made it so the model load loads mtl files and textures, redid texture loading
BIN
assets/models/Sponza-master.zip
Normal file
306
assets/models/sponza.mtl
Normal 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
BIN
assets/models/textures/Thumbs.db
Normal file
BIN
assets/models/textures/background.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/background_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/chain_texture.tga
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
assets/models/textures/chain_texture_ddn.tga
Normal file
After Width: | Height: | Size: 768 KiB |
BIN
assets/models/textures/lion.tga
Normal file
After Width: | Height: | Size: 4.0 MiB |
BIN
assets/models/textures/lion2_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/lion_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/spnza_bricks_a_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/spnza_bricks_a_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_arch_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_arch_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_ceiling_a_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_ceiling_a_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_column_a_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_column_a_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_column_b_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_column_b_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_column_c_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_column_c_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_curtain_blue_diff.tga
Normal file
After Width: | Height: | Size: 12 MiB |
BIN
assets/models/textures/sponza_curtain_ddn.tga
Normal file
After Width: | Height: | Size: 12 MiB |
BIN
assets/models/textures/sponza_curtain_diff.tga
Normal file
After Width: | Height: | Size: 12 MiB |
BIN
assets/models/textures/sponza_curtain_green_diff.tga
Normal file
After Width: | Height: | Size: 12 MiB |
BIN
assets/models/textures/sponza_details_ddn.tga
Normal file
After Width: | Height: | Size: 4.0 MiB |
BIN
assets/models/textures/sponza_details_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_fabric_blue_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_fabric_ddn.tga
Normal file
After Width: | Height: | Size: 4.0 MiB |
BIN
assets/models/textures/sponza_fabric_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_fabric_green_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_flagpole_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_flagpole_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_floor_a_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_floor_a_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_roof_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_roof_diff.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/sponza_thorn_ddn.tga
Normal file
After Width: | Height: | Size: 192 KiB |
BIN
assets/models/textures/sponza_thorn_diff.tga
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
assets/models/textures/vase_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/vase_dif.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/vase_hanging.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/vase_hanging_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/vase_plant.tga
Normal file
After Width: | Height: | Size: 4.0 MiB |
BIN
assets/models/textures/vase_round.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
assets/models/textures/vase_round_ddn.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
@ -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
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
return _T_Engine_Table
|
return _T_Engine_Table -- This just returns the Global Table that the engine creates
|
36
assets/shaders/LitMaterial.frag
Normal 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);
|
||||||
|
}
|
19
assets/shaders/LitMaterial.vert
Normal 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));
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
92
imgui.ini
@ -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
@ -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
|
@ -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]
|
@ -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]
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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()
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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;
|
||||||
|
@ -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");
|
||||||
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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);
|
||||||
};
|
};
|
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|