yes
This commit is contained in:
5
.gitignore
vendored
git.filemode.normal_file
5
.gitignore
vendored
git.filemode.normal_file
@@ -0,0 +1,5 @@
|
||||
*.o
|
||||
*.a
|
||||
Objects/
|
||||
*.spv
|
||||
Bin/
|
||||
28
Assets/Shaders/2DFragment.nzsl
git.filemode.normal_file
28
Assets/Shaders/2DFragment.nzsl
git.filemode.normal_file
@@ -0,0 +1,28 @@
|
||||
[nzsl_version("1.0")]
|
||||
module;
|
||||
|
||||
struct VertOut
|
||||
{
|
||||
[location(0)] color: vec4[f32],
|
||||
[location(1)] uv: vec2[f32]
|
||||
}
|
||||
|
||||
struct FragOut
|
||||
{
|
||||
[location(0)] color: vec4[f32]
|
||||
}
|
||||
|
||||
external
|
||||
{
|
||||
[set(1), binding(0)] u_texture: sampler2D[f32]
|
||||
}
|
||||
|
||||
[entry(frag)]
|
||||
fn main(input: VertOut) -> FragOut
|
||||
{
|
||||
let output: FragOut;
|
||||
output.color = input.color * u_texture.Sample(input.uv);
|
||||
if(output.color.w == 0.0)
|
||||
discard;
|
||||
return output;
|
||||
}
|
||||
46
Assets/Shaders/2DVertex.nzsl
git.filemode.normal_file
46
Assets/Shaders/2DVertex.nzsl
git.filemode.normal_file
@@ -0,0 +1,46 @@
|
||||
[nzsl_version("1.0")]
|
||||
module;
|
||||
|
||||
struct VertIn
|
||||
{
|
||||
[location(0)] pos: vec4[f32],
|
||||
[location(1)] color: vec4[f32], // unused
|
||||
[location(2)] normal: vec4[f32], // unused
|
||||
[location(3)] uv: vec2[f32]
|
||||
}
|
||||
|
||||
struct VertOut
|
||||
{
|
||||
[location(0)] color: vec4[f32],
|
||||
[location(1)] uv: vec2[f32],
|
||||
[builtin(position)] pos: vec4[f32]
|
||||
}
|
||||
|
||||
struct ViewerData
|
||||
{
|
||||
projection_matrix: mat4[f32]
|
||||
}
|
||||
|
||||
struct SpriteData
|
||||
{
|
||||
model_matrix: mat4[f32],
|
||||
color: vec4[f32],
|
||||
}
|
||||
|
||||
external
|
||||
{
|
||||
[set(0), binding(0)] viewer_data: uniform[ViewerData],
|
||||
model : push_constant[SpriteData]
|
||||
}
|
||||
|
||||
[entry(vert)]
|
||||
fn main(input: VertIn) -> VertOut
|
||||
{
|
||||
let position: vec4[f32] = vec4[f32](input.pos.xy, 0.0, 1.0);
|
||||
input.uv.x *= -1.0;
|
||||
let output: VertOut;
|
||||
output.uv = input.uv;
|
||||
output.color = model.color;
|
||||
output.pos = viewer_data.projection_matrix * model.model_matrix * position;
|
||||
return output;
|
||||
}
|
||||
60
Assets/Shaders/ForwardBasicFragment.nzsl
git.filemode.normal_file
60
Assets/Shaders/ForwardBasicFragment.nzsl
git.filemode.normal_file
@@ -0,0 +1,60 @@
|
||||
[nzsl_version("1.0")]
|
||||
module;
|
||||
|
||||
struct VertOut
|
||||
{
|
||||
[location(0)] color : vec4[f32],
|
||||
[location(1)] uv : vec2[f32],
|
||||
[location(2)] norm : vec4[f32],
|
||||
[location(3)] norm_mat : mat4[f32],
|
||||
[builtin(position)] pos: vec4[f32]
|
||||
}
|
||||
|
||||
struct FragmentData
|
||||
{
|
||||
dissolve_texture_factor: f32,
|
||||
dissolve_black_white_colors_factor: f32,
|
||||
dissolve_normals_colors_factor: f32,
|
||||
}
|
||||
|
||||
struct FragOut
|
||||
{
|
||||
[location(0)] color: vec4[f32]
|
||||
}
|
||||
|
||||
external
|
||||
{
|
||||
[set(1), binding(0)] u_albedo: sampler2D[f32],
|
||||
[set(1), binding(1)] u_fragment_data: uniform[FragmentData],
|
||||
}
|
||||
|
||||
fn Mixf32(a: f32, b: f32, t: f32) -> f32
|
||||
{
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
|
||||
fn MixVec4f32(a: vec4[f32], b: vec4[f32], t: f32) -> vec4[f32]
|
||||
{
|
||||
return vec4[f32](
|
||||
Mixf32(a.x, b.x, t),
|
||||
Mixf32(a.y, b.y, t),
|
||||
Mixf32(a.z, b.z, t),
|
||||
Mixf32(a.w, b.w, t)
|
||||
);
|
||||
}
|
||||
|
||||
[entry(frag)]
|
||||
fn main(input: VertOut) -> FragOut
|
||||
{
|
||||
let texture_color = u_albedo.Sample(input.uv);
|
||||
|
||||
let grey_scale_value: f32 = 0.3 * input.color.r + 0.59 * input.color.g + 0.11 * input.color.b;
|
||||
let grey_scale = vec4[f32](grey_scale_value, grey_scale_value, grey_scale_value, 1.0);
|
||||
input.color = MixVec4f32(input.color, grey_scale, u_fragment_data.dissolve_black_white_colors_factor);
|
||||
|
||||
input.color = MixVec4f32(input.color, abs(input.norm), u_fragment_data.dissolve_normals_colors_factor);
|
||||
|
||||
let output: FragOut;
|
||||
output.color = MixVec4f32(input.color, texture_color, u_fragment_data.dissolve_texture_factor);
|
||||
return output;
|
||||
}
|
||||
80
Assets/Shaders/ForwardDefaultFragment.nzsl
git.filemode.normal_file
80
Assets/Shaders/ForwardDefaultFragment.nzsl
git.filemode.normal_file
@@ -0,0 +1,80 @@
|
||||
[nzsl_version("1.0")]
|
||||
module;
|
||||
|
||||
struct VertOut
|
||||
{
|
||||
[location(0)] color: vec4[f32],
|
||||
[location(1)] uv: vec2[f32],
|
||||
[location(2)] norm: vec4[f32],
|
||||
[location(3)] transformed_norm: vec3[f32],
|
||||
[location(4)] frag_position: vec4[f32],
|
||||
[location(5)] camera_position: vec3[f32],
|
||||
[builtin(position)] pos: vec4[f32]
|
||||
}
|
||||
|
||||
struct FragmentData
|
||||
{
|
||||
dissolve_texture_factor: f32,
|
||||
dissolve_black_white_colors_factor: f32,
|
||||
dissolve_normals_colors_factor: f32,
|
||||
}
|
||||
|
||||
struct FragOut
|
||||
{
|
||||
[location(0)] color: vec4[f32]
|
||||
}
|
||||
|
||||
external
|
||||
{
|
||||
[set(1), binding(0)] u_albedo: sampler2D[f32],
|
||||
[set(1), binding(1)] u_fragment_data: uniform[FragmentData],
|
||||
}
|
||||
|
||||
fn Mixf32(a: f32, b: f32, t: f32) -> f32
|
||||
{
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
|
||||
fn MixVec4f32(a: vec4[f32], b: vec4[f32], t: f32) -> vec4[f32]
|
||||
{
|
||||
return vec4[f32](
|
||||
Mixf32(a.x, b.x, t),
|
||||
Mixf32(a.y, b.y, t),
|
||||
Mixf32(a.z, b.z, t),
|
||||
Mixf32(a.w, b.w, t)
|
||||
);
|
||||
}
|
||||
|
||||
[entry(frag)]
|
||||
fn main(input: VertOut) -> FragOut
|
||||
{
|
||||
if(input.color.a == 0.0)
|
||||
discard;
|
||||
|
||||
const ambient = vec3[f32](0.1, 0.1, 0.1);
|
||||
const directional_color = vec3[f32](5.0, 5.0, 5.0);
|
||||
const specular_strength = 0.5;
|
||||
let directional_vector = normalize(vec3[f32](0.85, 0.8, 0.75));
|
||||
|
||||
let directional: f32 = max(dot(input.transformed_norm.xyz, directional_vector), 0.0);
|
||||
|
||||
let view_dir: vec3[f32] = normalize(input.camera_position - input.frag_position.xyz);
|
||||
let reflect_dir: vec3[f32] = reflect(-directional_vector, input.norm.xyz);
|
||||
let spec: f32 = pow(max(dot(view_dir, reflect_dir), 0.0), 128.0);
|
||||
let specular: vec3[f32] = specular_strength * spec * directional_color;
|
||||
|
||||
let lighting: vec3[f32] = ambient + (directional_color * directional) + specular;
|
||||
|
||||
let grey_scale_value: f32 = 0.3 * input.color.r + 0.59 * input.color.g + 0.11 * input.color.b;
|
||||
let grey_scale = vec4[f32](grey_scale_value, grey_scale_value, grey_scale_value, 1.0);
|
||||
input.color = MixVec4f32(input.color, grey_scale, u_fragment_data.dissolve_black_white_colors_factor);
|
||||
|
||||
input.color = MixVec4f32(input.color, abs(input.norm), u_fragment_data.dissolve_normals_colors_factor);
|
||||
|
||||
let texture_color = u_albedo.Sample(input.uv) * u_fragment_data.dissolve_texture_factor;
|
||||
let final_color = MixVec4f32(input.color, texture_color, u_fragment_data.dissolve_texture_factor);
|
||||
|
||||
let output: FragOut;
|
||||
output.color = MixVec4f32(final_color, final_color * vec4[f32](lighting, 1.0), u_fragment_data.dissolve_texture_factor);
|
||||
return output;
|
||||
}
|
||||
49
Assets/Shaders/ForwardVertex.nzsl
git.filemode.normal_file
49
Assets/Shaders/ForwardVertex.nzsl
git.filemode.normal_file
@@ -0,0 +1,49 @@
|
||||
[nzsl_version("1.0")]
|
||||
module;
|
||||
|
||||
import ViewerData from ScopEngine.ViewerData;
|
||||
|
||||
struct VertIn
|
||||
{
|
||||
[location(0)] pos: vec4[f32],
|
||||
[location(1)] color: vec4[f32],
|
||||
[location(2)] normal: vec4[f32],
|
||||
[location(3)] uv: vec2[f32]
|
||||
}
|
||||
|
||||
struct VertOut
|
||||
{
|
||||
[location(0)] color: vec4[f32],
|
||||
[location(1)] uv: vec2[f32],
|
||||
[location(2)] norm: vec4[f32],
|
||||
[location(3)] transformed_norm: vec3[f32],
|
||||
[location(4)] frag_position: vec4[f32],
|
||||
[location(5)] camera_position: vec3[f32],
|
||||
[builtin(position)] pos: vec4[f32]
|
||||
}
|
||||
|
||||
struct ModelData
|
||||
{
|
||||
matrix: mat4[f32],
|
||||
normal: mat4[f32],
|
||||
}
|
||||
|
||||
external
|
||||
{
|
||||
[set(0), binding(0)] viewer_data: uniform[ViewerData],
|
||||
model: push_constant[ModelData]
|
||||
}
|
||||
|
||||
[entry(vert)]
|
||||
fn main(input: VertIn) -> VertOut
|
||||
{
|
||||
let output: VertOut;
|
||||
output.color = input.color;
|
||||
output.uv = input.uv;
|
||||
output.norm = normalize(input.normal);
|
||||
output.transformed_norm = mat3[f32](model.normal) * output.norm.xyz;
|
||||
output.frag_position = model.matrix * vec4[f32](input.pos.xyz, 1.0);
|
||||
output.camera_position = viewer_data.camera_position;
|
||||
output.pos = viewer_data.view_proj_matrix * output.frag_position;
|
||||
return output;
|
||||
}
|
||||
15
Assets/Shaders/Modules/ViewerData.nzsl
git.filemode.normal_file
15
Assets/Shaders/Modules/ViewerData.nzsl
git.filemode.normal_file
@@ -0,0 +1,15 @@
|
||||
[nzsl_version("1.0")]
|
||||
module ScopEngine.ViewerData;
|
||||
|
||||
[export]
|
||||
[layout(std140)]
|
||||
struct ViewerData
|
||||
{
|
||||
projection_matrix: mat4[f32],
|
||||
inv_projection_matrix: mat4[f32],
|
||||
view_matrix: mat4[f32],
|
||||
inv_view_matrix: mat4[f32],
|
||||
view_proj_matrix: mat4[f32],
|
||||
inv_view_proj_matrix: mat4[f32],
|
||||
camera_position: vec3[f32],
|
||||
}
|
||||
46
Assets/Shaders/ScreenFragment.nzsl
git.filemode.normal_file
46
Assets/Shaders/ScreenFragment.nzsl
git.filemode.normal_file
@@ -0,0 +1,46 @@
|
||||
[nzsl_version("1.0")]
|
||||
module;
|
||||
|
||||
struct VertOut
|
||||
{
|
||||
[location(0)] uv: vec2[f32]
|
||||
}
|
||||
|
||||
struct FragOut
|
||||
{
|
||||
[location(0)] color: vec4[f32]
|
||||
}
|
||||
|
||||
external
|
||||
{
|
||||
[set(0), binding(0)] u_texture: sampler2D[f32]
|
||||
}
|
||||
|
||||
option approximates_rgb: bool = false;
|
||||
|
||||
fn LinearTosRGB(color: vec3[f32]) -> vec3[f32]
|
||||
{
|
||||
const if(!approximates_rgb)
|
||||
{
|
||||
return select(
|
||||
color > (0.0031308).rrr,
|
||||
1.055 * pow(color, (1.0 / 2.4).rrr) - (0.055).rrr,
|
||||
12.92 * color
|
||||
);
|
||||
}
|
||||
else
|
||||
return pow(color, (1.0 / 2.2).rrr);
|
||||
}
|
||||
|
||||
option gamma_correction: bool = false;
|
||||
|
||||
[entry(frag)]
|
||||
fn main(input: VertOut) -> FragOut
|
||||
{
|
||||
let output: FragOut;
|
||||
const if(gamma_correction)
|
||||
output.color = vec4[f32](LinearTosRGB(u_texture.Sample(input.uv).xyz), 1.0);
|
||||
else
|
||||
output.color = u_texture.Sample(input.uv);
|
||||
return output;
|
||||
}
|
||||
31
Assets/Shaders/ScreenVertex.nzsl
git.filemode.normal_file
31
Assets/Shaders/ScreenVertex.nzsl
git.filemode.normal_file
@@ -0,0 +1,31 @@
|
||||
[nzsl_version("1.0")]
|
||||
module;
|
||||
|
||||
struct VertIn
|
||||
{
|
||||
[builtin(vertex_index)] vert_index: i32
|
||||
}
|
||||
|
||||
struct VertOut
|
||||
{
|
||||
[location(0)] uv: vec2[f32],
|
||||
[builtin(position)] position: vec4[f32]
|
||||
}
|
||||
|
||||
const vertices = array[vec2[f32]](
|
||||
vec2[f32](-1.0, -3.0),
|
||||
vec2[f32](-1.0, 1.0),
|
||||
vec2[f32]( 3.0, 1.0)
|
||||
);
|
||||
|
||||
[entry(vert)]
|
||||
fn main(input: VertIn) -> VertOut
|
||||
{
|
||||
let position = vertices[input.vert_index];
|
||||
|
||||
let output: VertOut;
|
||||
output.position = vec4[f32](position, 0.0, 1.0);
|
||||
output.uv = position * 0.5 + vec2[f32](0.5, 0.5);
|
||||
|
||||
return output;
|
||||
}
|
||||
28
Assets/Shaders/SkyboxFragment.nzsl
git.filemode.normal_file
28
Assets/Shaders/SkyboxFragment.nzsl
git.filemode.normal_file
@@ -0,0 +1,28 @@
|
||||
[nzsl_version("1.0")]
|
||||
module;
|
||||
|
||||
struct VertOut
|
||||
{
|
||||
[location(0)] uvw : vec3[f32]
|
||||
}
|
||||
|
||||
struct FragOut
|
||||
{
|
||||
[location(0)] color: vec4[f32],
|
||||
[builtin(frag_depth)] depth: f32
|
||||
}
|
||||
|
||||
external
|
||||
{
|
||||
[set(1), binding(0)] skybox: sampler_cube[f32]
|
||||
}
|
||||
|
||||
[entry(frag)]
|
||||
[depth_write(greater)]
|
||||
fn main(input: VertOut) -> FragOut
|
||||
{
|
||||
let output: FragOut;
|
||||
output.color = skybox.Sample(input.uvw);
|
||||
output.depth = 1.0;
|
||||
return output;
|
||||
}
|
||||
37
Assets/Shaders/SkyboxVertex.nzsl
git.filemode.normal_file
37
Assets/Shaders/SkyboxVertex.nzsl
git.filemode.normal_file
@@ -0,0 +1,37 @@
|
||||
[nzsl_version("1.0")]
|
||||
module;
|
||||
|
||||
import ViewerData from ScopEngine.ViewerData;
|
||||
|
||||
struct VertIn
|
||||
{
|
||||
[location(0)] pos: vec4[f32],
|
||||
[location(1)] color: vec4[f32],
|
||||
[location(2)] normal: vec4[f32],
|
||||
[location(3)] uv: vec2[f32]
|
||||
}
|
||||
|
||||
struct VertOut
|
||||
{
|
||||
[location(0)] uvw: vec3[f32],
|
||||
[builtin(position)] pos: vec4[f32]
|
||||
}
|
||||
|
||||
external
|
||||
{
|
||||
[set(0), binding(0)] viewer_data: uniform[ViewerData]
|
||||
}
|
||||
|
||||
[entry(vert)]
|
||||
fn main(input: VertIn) -> VertOut
|
||||
{
|
||||
// Set translation part to zero
|
||||
let rotation_matrix = viewer_data.view_matrix;
|
||||
rotation_matrix[3].xyz = vec3[f32](0.0, 0.0, 0.0);
|
||||
|
||||
let output: VertOut;
|
||||
output.uvw = input.pos.xyz;
|
||||
output.uvw.xy *= -1.0;
|
||||
output.pos = viewer_data.projection_matrix * rotation_matrix * input.pos;
|
||||
return output;
|
||||
}
|
||||
BIN
Assets/Vendors/nzslc.x86_64
git.filemode.executable_file
BIN
Assets/Vendors/nzslc.x86_64
git.filemode.executable_file
Binary file not shown.
140
Makefile
git.filemode.normal_file
140
Makefile
git.filemode.normal_file
@@ -0,0 +1,140 @@
|
||||
SRCS = $(wildcard $(addsuffix /*.cpp, ./Runtime/Sources/Core))
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./Runtime/Sources/Platform))
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./Runtime/Sources/Graphics))
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./Runtime/Sources/Graphics/Cameras))
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./Runtime/Sources/Graphics/Loaders))
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./Runtime/Sources/Renderer))
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./Runtime/Sources/Renderer/Memory))
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./Runtime/Sources/Renderer/Vulkan))
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./Runtime/Sources/Renderer/Pipelines))
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./Runtime/Sources/Renderer/RenderPasses))
|
||||
|
||||
SHADER_SRCS = $(wildcard $(addsuffix /*.nzsl, ./Assets/Shaders))
|
||||
|
||||
BIN_DIR = Bin
|
||||
OBJ_DIR = Objects
|
||||
SHADER_DIR = Assets/Shaders/Build
|
||||
SHADER_MODULE_DIR = Assets/Shaders/Modules
|
||||
|
||||
OBJS = $(addprefix $(OBJ_DIR)/, $(SRCS:.cpp=.o))
|
||||
SPVS = $(addprefix $(SHADER_DIR)/, $(SHADER_SRCS:.nzsl=.spv))
|
||||
|
||||
CXX = clang++
|
||||
CXXFLAGS = -std=c++20 -I Runtime/Includes -I Runtime/Sources -I ThirdParty/ -I ThirdParty/KVF -D KVF_IMPL_VK_NO_PROTOTYPES -D VK_NO_PROTOTYPES -fPIC
|
||||
|
||||
AR = ar rc
|
||||
|
||||
SH = sh -c
|
||||
|
||||
NZSLC = ./Assets/Vendors/nzslc.x86_64
|
||||
|
||||
LDFLAGS = -lSDL2
|
||||
|
||||
SHARED ?= false
|
||||
DEBUG ?= false
|
||||
|
||||
TPUT = tput -T xterm-256color
|
||||
_RESET := $(shell $(TPUT) sgr0)
|
||||
_BOLD := $(shell $(TPUT) bold)
|
||||
_ITALIC := $(shell $(TPUT) sitm)
|
||||
_UNDER := $(shell $(TPUT) smul)
|
||||
_GREEN := $(shell $(TPUT) setaf 2)
|
||||
_YELLOW := $(shell $(TPUT) setaf 3)
|
||||
_RED := $(shell $(TPUT) setaf 1)
|
||||
_GRAY := $(shell $(TPUT) setaf 8)
|
||||
_PURPLE := $(shell $(TPUT) setaf 5)
|
||||
|
||||
ifeq ($(DEBUG), true)
|
||||
CXXFLAGS += -g3 -D DEBUG -D IMGUI_IMPL_VULKAN_NO_PROTOTYPES -I ThirdParty/imgui
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./Runtime/Sources/Debug))
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./ThirdParty/imgui))
|
||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./ThirdParty/imgui/backends))
|
||||
MODE := $(_RESET)$(_PURPLE)$(_BOLD)Debug$(_RESET)$(_PURPLE)
|
||||
COLOR := $(_PURPLE)
|
||||
else
|
||||
MODE := $(_RESET)$(_GREEN)$(_BOLD)Release$(_RESET)$(_GREEN)
|
||||
COLOR := $(_GREEN)
|
||||
endif
|
||||
|
||||
ifeq ($(SHARED), true)
|
||||
NAME = engine.so
|
||||
else
|
||||
NAME = engine.a
|
||||
endif
|
||||
|
||||
RM = rm -rf
|
||||
|
||||
OBJS_TOTAL = $(words $(OBJS))
|
||||
N_OBJS := $(shell find $(OBJ_DIR) -type f -name '*.o' 2>/dev/null | wc -l)
|
||||
OBJS_TOTAL := $(shell echo $$(( $(OBJS_TOTAL) - $(N_OBJS) )))
|
||||
ifeq ($(OBJS_TOTAL), 0) # To avoid division per 0
|
||||
OBJS_TOTAL := 1
|
||||
endif
|
||||
CURR_OBJ = 0
|
||||
|
||||
$(OBJ_DIR)/%.o: %.cpp
|
||||
@$(eval CURR_OBJ=$(shell echo $$(( $(CURR_OBJ) + 1 ))))
|
||||
@$(eval PERCENT=$(shell echo $$(( $(CURR_OBJ) * 100 / $(OBJS_TOTAL) ))))
|
||||
@printf "$(COLOR)($(_BOLD)%3s%%$(_RESET)$(COLOR)) $(_RESET)Compiling $(_BOLD)$<$(_RESET)\n" "$(PERCENT)"
|
||||
@$(CXX) $(CXXFLAGS) $(COPTS) -c $< -o $@
|
||||
|
||||
all: _printbuildinfos $(NAME)
|
||||
|
||||
$(NAME): $(OBJ_DIR) $(BIN_DIR) shaders $(OBJS)
|
||||
@printf "Linking $(_BOLD)$(NAME)$(_RESET)\n"
|
||||
@$(CXX) -shared -o $(NAME) $(OBJS) $(LDFLAGS)
|
||||
ifeq ($(SHARED), true)
|
||||
@$(CXX) -o $(BIN_DIR)/$(NAME) $(OBJS) $(LDFLAGS) --shared
|
||||
else
|
||||
@$(AR) $(BIN_DIR)/$(NAME) $(OBJS)
|
||||
endif
|
||||
@printf "$(_BOLD)$(NAME)$(_RESET) compiled $(COLOR)$(_BOLD)successfully$(_RESET)\n"
|
||||
|
||||
SPVS_TOTAL = $(words $(SPVS))
|
||||
N_SPVS := $(shell find $(SHADERS_DIR) -type f -name '*.spv.h' 2>/dev/null | wc -l)
|
||||
SPVS_TOTAL := $(shell echo $$(( $(SPVS_TOTAL) - $(N_SPVS) )))
|
||||
ifeq ($(SPVS_TOTAL), 0) # Same
|
||||
SPVS_TOTAL := 1
|
||||
endif
|
||||
CURR_SPV = 0
|
||||
|
||||
$(SHADER_DIR)/%.spv: %.nzsl
|
||||
@$(eval CURR_SPV=$(shell echo $$(( $(CURR_SPV) + 1 ))))
|
||||
@$(eval PERCENT=$(shell echo $$(( $(CURR_SPV) * 100 / $(SPVS_TOTAL) ))))
|
||||
@printf "$(COLOR)($(_BOLD)%3s%%$(_RESET)$(COLOR)) $(_RESET)Compiling $(_BOLD)$<$(_RESET)\n" "$(PERCENT)"
|
||||
@$(NZSLC) --compile=spv $< -o $(SHADER_DIR) --optimize --module=$(SHADER_MODULE_DIR)
|
||||
|
||||
$(OBJ_DIR):
|
||||
@mkdir -p $(sort $(addprefix $(OBJ_DIR)/, $(dir $(SRCS))))
|
||||
|
||||
$(BIN_DIR):
|
||||
@mkdir -p $(BIN_DIR)
|
||||
|
||||
$(SHADER_DIR):
|
||||
@mkdir -p $(SHADER_DIR)
|
||||
|
||||
shaders: $(SHADER_DIR) $(SPVS)
|
||||
|
||||
_printbuildinfos:
|
||||
@printf "$(_PURPLE)$(_BOLD)ScopEngine $(_RESET)Compiling in $(_BOLD)$(MODE)$(_RESET) mode on $(_BOLD)$(OS)$(_RESET) | Using $(_BOLD)$(CXX) ($(shell $(CXX) --version | head -n 1))$(_RESET), flags: $(_BOLD)$(_ENABLEDFLAGS)$(_RESET)\n"
|
||||
|
||||
debug:
|
||||
@$(MAKE) all DEBUG=true -j$(shell nproc)
|
||||
|
||||
dependencies:
|
||||
@$(SH) Script/FetchDependencies.sh
|
||||
|
||||
clean-shaders:
|
||||
@$(RM) $(SHADER_DIR)
|
||||
|
||||
re-shaders: clean-shaders shaders
|
||||
|
||||
clean: clean-shaders
|
||||
@$(RM) $(OBJ_DIR)
|
||||
|
||||
fclean: clean
|
||||
@$(RM) $(BIN_DIR)
|
||||
|
||||
re: fclean all
|
||||
|
||||
.PHONY: all clean fclean re dependencies shaders clean-shaders re-shaders
|
||||
39
Runtime/Includes/Core/CLI.h
git.filemode.normal_file
39
Runtime/Includes/Core/CLI.h
git.filemode.normal_file
@@ -0,0 +1,39 @@
|
||||
#ifndef __SCOP_CLI__
|
||||
#define __SCOP_CLI__
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class CommandLineInterface
|
||||
{
|
||||
public:
|
||||
inline CommandLineInterface();
|
||||
|
||||
inline std::optional<std::string> GetOption(std::string_view option) const;
|
||||
inline std::optional<std::string> GetArgument(std::string_view arg) const;
|
||||
inline bool HasFlag(std::string_view flag) const;
|
||||
inline const std::string& GetCommand() const;
|
||||
|
||||
inline void Feed(int ac, char** av);
|
||||
|
||||
inline static CommandLineInterface& Get() noexcept;
|
||||
|
||||
inline ~CommandLineInterface();
|
||||
|
||||
private:
|
||||
static inline CommandLineInterface* s_instance = nullptr;
|
||||
|
||||
std::unordered_map<std::string, std::string> m_options;
|
||||
std::unordered_set<std::string> m_flags;
|
||||
std::unordered_set<std::string> m_args;
|
||||
std::string m_cmd;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Core/CLI.inl>
|
||||
|
||||
#endif
|
||||
72
Runtime/Includes/Core/CLI.inl
git.filemode.normal_file
72
Runtime/Includes/Core/CLI.inl
git.filemode.normal_file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include <Core/CLI.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
CommandLineInterface::CommandLineInterface()
|
||||
{
|
||||
s_instance = this;
|
||||
}
|
||||
|
||||
std::optional<std::string> CommandLineInterface::GetOption(std::string_view option) const
|
||||
{
|
||||
auto it = m_options.find(static_cast<std::string>(option));
|
||||
if(it == m_options.end())
|
||||
return std::nullopt;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::optional<std::string> CommandLineInterface::GetArgument(std::string_view arg) const
|
||||
{
|
||||
auto it = std::find(m_args.begin(), m_args.end(), arg);
|
||||
if(it == m_args.end())
|
||||
return std::nullopt;
|
||||
return *it;
|
||||
}
|
||||
|
||||
bool CommandLineInterface::HasFlag(std::string_view flag) const
|
||||
{
|
||||
return std::find(m_flags.begin(), m_flags.end(), flag) != m_flags.end();
|
||||
}
|
||||
|
||||
const std::string& CommandLineInterface::GetCommand() const
|
||||
{
|
||||
return m_cmd;
|
||||
}
|
||||
|
||||
void CommandLineInterface::Feed(int ac, char** av)
|
||||
{
|
||||
if(ac == 0 || av == nullptr)
|
||||
return;
|
||||
m_cmd = av[0];
|
||||
for(int i = 1; i < ac; i++)
|
||||
{
|
||||
std::string_view arg{ av[i] };
|
||||
if(arg.front() == '-')
|
||||
{
|
||||
arg.remove_prefix(1);
|
||||
if(arg.front() == '-') // in case of arg begenning with --
|
||||
arg.remove_prefix(1);
|
||||
std::size_t finder = arg.find_first_of('=');
|
||||
if(finder != std::string_view::npos)
|
||||
m_options.emplace(std::make_pair(arg.substr(0, finder), arg.substr(finder + 1)));
|
||||
else
|
||||
m_flags.emplace(arg);
|
||||
}
|
||||
else
|
||||
m_args.emplace(arg);
|
||||
}
|
||||
}
|
||||
|
||||
CommandLineInterface& CommandLineInterface::Get() noexcept
|
||||
{
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
CommandLineInterface::~CommandLineInterface()
|
||||
{
|
||||
s_instance = nullptr;
|
||||
}
|
||||
}
|
||||
67
Runtime/Includes/Core/Engine.h
git.filemode.normal_file
67
Runtime/Includes/Core/Engine.h
git.filemode.normal_file
@@ -0,0 +1,67 @@
|
||||
#ifndef __SCOP_CORE_ENGINE__
|
||||
#define __SCOP_CORE_ENGINE__
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
|
||||
#include <Platform/Window.h>
|
||||
#include <Platform/Inputs.h>
|
||||
#include <Renderer/Renderer.h>
|
||||
#include <Renderer/ScenesRenderer.h>
|
||||
#include <Renderer/RenderCore.h>
|
||||
#include <Core/Logs.h>
|
||||
#include <Graphics/Scene.h>
|
||||
#include <Core/CLI.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <Debug/ImGuiRenderer.h>
|
||||
#endif
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class ScopEngine
|
||||
{
|
||||
friend class Scene;
|
||||
|
||||
public:
|
||||
ScopEngine(int ac, char** av, const std::string& title, std::uint32_t width, std::uint32_t height, std::filesystem::path assets_path);
|
||||
|
||||
void Run();
|
||||
|
||||
[[nodiscard]] inline const Window& GetWindow() const noexcept { return m_window; }
|
||||
[[nodiscard]] inline std::filesystem::path GetAssetsPath() const { return m_assets_path; }
|
||||
|
||||
inline Scene& CreateMainScene(std::string_view name, SceneDescriptor desc) noexcept { p_main_scene = std::make_unique<Scene>(name, std::move(desc)); p_current_scene = p_main_scene.get(); return *p_main_scene; }
|
||||
inline NonOwningPtr<Scene> GetRootScene() const noexcept { return p_main_scene.get(); }
|
||||
|
||||
constexpr void Quit() noexcept { m_running = false; }
|
||||
|
||||
[[nodiscard]] static inline bool IsInit() noexcept { return s_instance != nullptr; }
|
||||
[[nodiscard]] static ScopEngine& Get() noexcept;
|
||||
|
||||
~ScopEngine();
|
||||
|
||||
private:
|
||||
inline void SwitchToScene(NonOwningPtr<Scene> current) noexcept { p_current_scene = current; m_scene_changed = true; }
|
||||
|
||||
private:
|
||||
static ScopEngine* s_instance;
|
||||
|
||||
Inputs m_inputs;
|
||||
Renderer m_renderer;
|
||||
#ifdef DEBUG
|
||||
ImGuiRenderer m_imgui;
|
||||
#endif
|
||||
CommandLineInterface m_cli;
|
||||
Window m_window;
|
||||
SceneRenderer m_scene_renderer;
|
||||
std::filesystem::path m_assets_path;
|
||||
std::unique_ptr<RenderCore> p_renderer_core;
|
||||
std::unique_ptr<Scene> p_main_scene;
|
||||
NonOwningPtr<Scene> p_current_scene;
|
||||
bool m_running = true;
|
||||
bool m_scene_changed = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
36
Runtime/Includes/Core/Enums.h
git.filemode.normal_file
36
Runtime/Includes/Core/Enums.h
git.filemode.normal_file
@@ -0,0 +1,36 @@
|
||||
#ifndef __SCOPE_CORE_ENUMS__
|
||||
#define __SCOPE_CORE_ENUMS__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
enum class LogType
|
||||
{
|
||||
Debug = 0,
|
||||
Message,
|
||||
Warning,
|
||||
Error,
|
||||
FatalError,
|
||||
|
||||
EndEnum
|
||||
};
|
||||
|
||||
constexpr std::size_t LogTypeCount = static_cast<std::size_t>(LogType::EndEnum);
|
||||
|
||||
enum class Event
|
||||
{
|
||||
SceneHasChangedEventCode,
|
||||
ResizeEventCode,
|
||||
FrameBeginEventCode,
|
||||
FatalErrorEventCode,
|
||||
QuitEventCode,
|
||||
MemoryChunkAllocationFailed,
|
||||
|
||||
EndEnum
|
||||
};
|
||||
|
||||
constexpr std::size_t EventCount = static_cast<std::size_t>(Event::EndEnum);
|
||||
}
|
||||
|
||||
#endif
|
||||
14
Runtime/Includes/Core/EventBase.h
git.filemode.normal_file
14
Runtime/Includes/Core/EventBase.h
git.filemode.normal_file
@@ -0,0 +1,14 @@
|
||||
#ifndef __SCOPE_CORE_BASE_EVENT__
|
||||
#define __SCOPE_CORE_BASE_EVENT__
|
||||
|
||||
#include <Core/Enums.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
struct EventBase
|
||||
{
|
||||
virtual Event What() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
25
Runtime/Includes/Core/EventBus.h
git.filemode.normal_file
25
Runtime/Includes/Core/EventBus.h
git.filemode.normal_file
@@ -0,0 +1,25 @@
|
||||
#ifndef __SCOPE_CORE_EVENT_BUS__
|
||||
#define __SCOPE_CORE_EVENT_BUS__
|
||||
|
||||
#include <Core/EventBase.h>
|
||||
#include <Core/EventListener.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class EventBus
|
||||
{
|
||||
public:
|
||||
EventBus() = delete;
|
||||
static void Send(const std::string& listener_name, const EventBase& event);
|
||||
static void SendBroadcast(const EventBase& event);
|
||||
inline static void RegisterListener(const EventListener& listener) { s_listeners.push_back(listener); }
|
||||
~EventBus() = delete;
|
||||
|
||||
private:
|
||||
inline static std::vector<EventListener> s_listeners;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
27
Runtime/Includes/Core/EventListener.h
git.filemode.normal_file
27
Runtime/Includes/Core/EventListener.h
git.filemode.normal_file
@@ -0,0 +1,27 @@
|
||||
#ifndef __SCOPE_CORE_EVENT_LISTENER__
|
||||
#define __SCOPE_CORE_EVENT_LISTENER__
|
||||
|
||||
#include <Core/EventBase.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class EventListener
|
||||
{
|
||||
public:
|
||||
EventListener() = delete;
|
||||
EventListener(std::function<void(const EventBase&)> functor, std::string name);
|
||||
|
||||
[[nodiscard]] inline const std::string& GetName() const { return m_name; }
|
||||
inline void Call(const EventBase& event) const noexcept { m_listen_functor(event); }
|
||||
|
||||
~EventListener() = default;
|
||||
|
||||
private:
|
||||
std::function<void(const EventBase&)> m_listen_functor;
|
||||
std::string m_name;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
22
Runtime/Includes/Core/Format.h
git.filemode.normal_file
22
Runtime/Includes/Core/Format.h
git.filemode.normal_file
@@ -0,0 +1,22 @@
|
||||
#ifndef __SCOPE_CORE_FORMAT__
|
||||
#define __SCOPE_CORE_FORMAT__
|
||||
|
||||
#include <type_traits>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T, typename = void>
|
||||
struct IsOstreamable : std::false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct IsOstreamable<T, std::void_t<decltype(std::declval<std::ostream>() << std::declval<T>())>> : std::true_type {};
|
||||
|
||||
template<typename... Args, std::enable_if_t<std::conjunction_v<IsOstreamable<Args>...>, int> = 0>
|
||||
auto Format(std::string_view format, const Args&... args);
|
||||
}
|
||||
|
||||
#include <Core/Format.inl>
|
||||
|
||||
#endif
|
||||
137
Runtime/Includes/Core/Format.inl
git.filemode.normal_file
137
Runtime/Includes/Core/Format.inl
git.filemode.normal_file
@@ -0,0 +1,137 @@
|
||||
#pragma once
|
||||
#include <Core/Format.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <ostream>
|
||||
|
||||
// TODO : make single functions that manages stringstreams and ostreams
|
||||
namespace Scop
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
template<typename It>
|
||||
void Format(std::stringstream& ss, It first, It last)
|
||||
{
|
||||
for(auto it = first; it != last; ++it)
|
||||
{
|
||||
switch(*it)
|
||||
{
|
||||
case '%':
|
||||
throw std::invalid_argument{"too few arguments"};
|
||||
case '/':
|
||||
++it;
|
||||
if(it == last)
|
||||
throw std::invalid_argument{"stray '/'"};
|
||||
[[fallthrough]];
|
||||
|
||||
default: ss << *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename It, typename T, typename... Args>
|
||||
void Format(std::stringstream& ss, It first, It last, const T& arg, const Args&... args)
|
||||
{
|
||||
for(auto it = first; it != last; ++it)
|
||||
{
|
||||
switch(*it)
|
||||
{
|
||||
case '%':
|
||||
ss << arg;
|
||||
return Format(ss, ++it, last, args...);
|
||||
case '/':
|
||||
++it;
|
||||
if(it == last)
|
||||
throw std::invalid_argument{"stray '/'"};
|
||||
[[fallthrough]];
|
||||
|
||||
default: ss << *it;
|
||||
}
|
||||
}
|
||||
throw std::invalid_argument{"too many arguments"};
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
void Format(std::ostream& os, It first, It last)
|
||||
{
|
||||
for(auto it = first; it != last; ++it)
|
||||
{
|
||||
switch(*it)
|
||||
{
|
||||
case '%':
|
||||
throw std::invalid_argument{"too few arguments"};
|
||||
case '/':
|
||||
++it;
|
||||
if(it == last)
|
||||
throw std::invalid_argument{"stray '/'"};
|
||||
[[fallthrough]];
|
||||
|
||||
default: os << *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename It, typename T, typename... Args>
|
||||
void Format(std::ostream& os, It first, It last, const T& arg, const Args&... args)
|
||||
{
|
||||
for(auto it = first; it != last; ++it)
|
||||
{
|
||||
switch(*it)
|
||||
{
|
||||
case '%':
|
||||
os << arg;
|
||||
return Format(os, ++it, last, args...);
|
||||
case '/':
|
||||
++it;
|
||||
if(it == last)
|
||||
throw std::invalid_argument{"stray '/'"};
|
||||
[[fallthrough]];
|
||||
|
||||
default: os << *it;
|
||||
}
|
||||
}
|
||||
throw std::invalid_argument{"too many arguments"};
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
struct Formatter
|
||||
{
|
||||
std::string_view format;
|
||||
std::tuple<const Args&...> args;
|
||||
};
|
||||
|
||||
template<typename... Args, std::size_t... Is>
|
||||
void FormatHelper(std::stringstream& ss, const Formatter<Args...>& formatter, std::index_sequence<Is...>)
|
||||
{
|
||||
Format(ss, formatter.format.begin(), formatter.format.end(),
|
||||
std::get<Is>(formatter.args)...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
std::stringstream& operator<<(std::stringstream& ss, const Formatter<Args...>& printer)
|
||||
{
|
||||
FormatHelper(ss, printer, std::index_sequence_for<Args...>{});
|
||||
return ss;
|
||||
}
|
||||
|
||||
template<typename... Args, std::size_t... Is>
|
||||
void FormatHelper(std::ostream& os, const Formatter<Args...>& formatter, std::index_sequence<Is...>)
|
||||
{
|
||||
Format(os, formatter.format.begin(), formatter.format.end(),
|
||||
std::get<Is>(formatter.args)...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
std::ostream& operator<<(std::ostream& os, const Formatter<Args...>& printer)
|
||||
{
|
||||
FormatHelper(os, printer, std::index_sequence_for<Args...>{});
|
||||
return os;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args, std::enable_if_t<std::conjunction_v<IsOstreamable<Args>...>, int>>
|
||||
auto Format(std::string_view format, const Args&... args)
|
||||
{
|
||||
return Internal::Formatter<Args...>{format, std::forward_as_tuple(args...)};
|
||||
}
|
||||
}
|
||||
74
Runtime/Includes/Core/Logs.h
git.filemode.normal_file
74
Runtime/Includes/Core/Logs.h
git.filemode.normal_file
@@ -0,0 +1,74 @@
|
||||
#ifndef __SCOPE_CORE_LOGS__
|
||||
#define __SCOPE_CORE_LOGS__
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <Core/Enums.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename... Args>
|
||||
void DebugLog(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
|
||||
|
||||
template<typename... Args>
|
||||
void Error(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
|
||||
|
||||
template<typename... Args>
|
||||
void Warning(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
|
||||
|
||||
template<typename... Args>
|
||||
void Message(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
|
||||
|
||||
template<typename... Args>
|
||||
void FatalError(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
|
||||
|
||||
template<typename... Args>
|
||||
void Verify(bool cond, unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
|
||||
|
||||
class Logs
|
||||
{
|
||||
public:
|
||||
Logs() = delete;
|
||||
|
||||
static void Report(LogType type, std::string message);
|
||||
static void Report(LogType type, unsigned int line, std::string_view file, std::string_view function, std::string message);
|
||||
|
||||
~Logs() = delete;
|
||||
};
|
||||
|
||||
#if defined(DEBUG)
|
||||
template<typename... Args>
|
||||
void Assert(bool cond, unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args);
|
||||
#else
|
||||
template<typename... Args>
|
||||
void Assert(bool cond, unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <Core/Logs.inl>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
#undef DebugLog
|
||||
#define DebugLog(...) DebugLog(__LINE__, __FILE__, __func__, __VA_ARGS__)
|
||||
|
||||
#undef Message
|
||||
#define Message(...) Message(__LINE__, __FILE__, __func__, __VA_ARGS__)
|
||||
|
||||
#undef Warning
|
||||
#define Warning(...) Warning(__LINE__, __FILE__, __func__, __VA_ARGS__)
|
||||
|
||||
#undef Error
|
||||
#define Error(...) Error(__LINE__, __FILE__, __func__, __VA_ARGS__)
|
||||
|
||||
#undef FatalError
|
||||
#define FatalError(...) FatalError(__LINE__, __FILE__, __func__, __VA_ARGS__)
|
||||
|
||||
#undef Verify
|
||||
#define Verify(cond, ...) Verify(cond, __LINE__, __FILE__, __func__, __VA_ARGS__)
|
||||
|
||||
#undef Assert
|
||||
#define Assert(cond, ...) Assert(cond, __LINE__, __FILE__, __func__, __VA_ARGS__)
|
||||
}
|
||||
|
||||
#endif
|
||||
126
Runtime/Includes/Core/Logs.inl
git.filemode.normal_file
126
Runtime/Includes/Core/Logs.inl
git.filemode.normal_file
@@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
#include <Core/Logs.h>
|
||||
|
||||
#include <Core/Format.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename... Args>
|
||||
void DebugLog(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
|
||||
{
|
||||
using namespace std::literals;
|
||||
try
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << Format(message, args...);
|
||||
Logs::Report(LogType::Debug, line, file, function, ss.str());
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Error(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
|
||||
{
|
||||
using namespace std::literals;
|
||||
try
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << Format(message, args...);
|
||||
Logs::Report(LogType::Error, line, file, function, ss.str());
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Warning(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
|
||||
{
|
||||
using namespace std::literals;
|
||||
try
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << Format(message, args...);
|
||||
Logs::Report(LogType::Warning, line, file, function, ss.str());
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Message(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
|
||||
{
|
||||
using namespace std::literals;
|
||||
try
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << Format(message, args...);
|
||||
Logs::Report(LogType::Message, line, file, function, ss.str());
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void FatalError(unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
|
||||
{
|
||||
using namespace std::literals;
|
||||
try
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << Format(message, args...);
|
||||
Logs::Report(LogType::FatalError, line, file, function, ss.str());
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void Verify(bool cond, unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
|
||||
{
|
||||
using namespace std::literals;
|
||||
if(cond)
|
||||
return;
|
||||
try
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << Format("Verification failed : %", message, args...);
|
||||
Logs::Report(LogType::FatalError, line, file, function, ss.str());
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
template<typename... Args>
|
||||
void Assert(bool cond, unsigned int line, std::string_view file, std::string_view function, std::string message, const Args&... args)
|
||||
{
|
||||
using namespace std::literals;
|
||||
if(cond)
|
||||
return;
|
||||
try
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << Format("Assertion failed : %", message, args...);
|
||||
Logs::Report(LogType::FatalError, line, file, function, ss.str());
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
Logs::Report(LogType::Error, "formatter exception catched in the log printer : "s + e.what());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
68
Runtime/Includes/Core/NativeScript.h
git.filemode.normal_file
68
Runtime/Includes/Core/NativeScript.h
git.filemode.normal_file
@@ -0,0 +1,68 @@
|
||||
#ifndef __SCOP_NATIVE_SCRIPT__
|
||||
#define __SCOP_NATIVE_SCRIPT__
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <Core/Script.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class NativeActorScript : public ActorScript
|
||||
{
|
||||
public:
|
||||
NativeActorScript(std::function<void(NonOwningPtr<class Actor>)> on_init, std::function<void(NonOwningPtr<class Scene>, NonOwningPtr<class Actor>, class Inputs&, float)> on_update, std::function<void(NonOwningPtr<class Actor>)> on_quit)
|
||||
: f_on_init(std::move(on_init)), f_on_update(std::move(on_update)), f_on_quit(std::move(on_quit))
|
||||
{}
|
||||
|
||||
inline void OnInit(NonOwningPtr<class Actor> actor) override { if(f_on_init) f_on_init(actor); }
|
||||
inline void OnUpdate(NonOwningPtr<class Scene> scene, NonOwningPtr<class Actor> actor, class Inputs& input, float delta) override { if(f_on_update) f_on_update(scene, actor, input, delta); }
|
||||
inline void OnQuit(NonOwningPtr<class Actor> actor) override { if(f_on_quit) f_on_quit(actor); }
|
||||
|
||||
~NativeActorScript() = default;
|
||||
|
||||
private:
|
||||
std::function<void(NonOwningPtr<class Actor>)> f_on_init;
|
||||
std::function<void(NonOwningPtr<class Scene>, NonOwningPtr<class Actor>, class Inputs&, float)> f_on_update;
|
||||
std::function<void(NonOwningPtr<class Actor>)> f_on_quit;
|
||||
};
|
||||
|
||||
class NativeSpriteScript : public SpriteScript
|
||||
{
|
||||
public:
|
||||
NativeSpriteScript(std::function<void(NonOwningPtr<class Sprite>)> on_init, std::function<void(NonOwningPtr<class Scene>, NonOwningPtr<class Sprite>, class Inputs&, float)> on_update, std::function<void(NonOwningPtr<class Sprite>)> on_quit)
|
||||
: f_on_init(std::move(on_init)), f_on_update(std::move(on_update)), f_on_quit(std::move(on_quit))
|
||||
{}
|
||||
|
||||
inline void OnInit(NonOwningPtr<class Sprite> sprite) override { if(f_on_init) f_on_init(sprite); }
|
||||
inline void OnUpdate(NonOwningPtr<class Scene> scene, NonOwningPtr<class Sprite> sprite, class Inputs& input, float delta) override { if(f_on_update) f_on_update(scene, sprite, input, delta); }
|
||||
inline void OnQuit(NonOwningPtr<class Sprite> sprite) override { if(f_on_quit) f_on_quit(sprite); }
|
||||
|
||||
~NativeSpriteScript() = default;
|
||||
|
||||
private:
|
||||
std::function<void(NonOwningPtr<class Sprite>)> f_on_init;
|
||||
std::function<void(NonOwningPtr<class Scene>, NonOwningPtr<class Sprite>, class Inputs&, float)> f_on_update;
|
||||
std::function<void(NonOwningPtr<class Sprite>)> f_on_quit;
|
||||
};
|
||||
|
||||
class NativeNarratorScript : public NarratorScript
|
||||
{
|
||||
public:
|
||||
NativeNarratorScript(std::function<void()> on_init, std::function<void(NonOwningPtr<class Scene>, class Inputs&, float)> on_update, std::function<void()> on_quit)
|
||||
: f_on_init(std::move(on_init)), f_on_update(std::move(on_update)), f_on_quit(std::move(on_quit))
|
||||
{}
|
||||
|
||||
inline void OnInit() override { if(f_on_init) f_on_init(); }
|
||||
inline void OnUpdate(NonOwningPtr<class Scene> scene, class Inputs& input, float delta) override { if(f_on_update) f_on_update(scene, input, delta); }
|
||||
inline void OnQuit() override { if(f_on_quit) f_on_quit(); }
|
||||
|
||||
~NativeNarratorScript() = default;
|
||||
|
||||
private:
|
||||
std::function<void()> f_on_init;
|
||||
std::function<void(NonOwningPtr<class Scene>, class Inputs&, float)> f_on_update;
|
||||
std::function<void()> f_on_quit;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
45
Runtime/Includes/Core/Script.h
git.filemode.normal_file
45
Runtime/Includes/Core/Script.h
git.filemode.normal_file
@@ -0,0 +1,45 @@
|
||||
#ifndef __SCOP_SCRIPT__
|
||||
#define __SCOP_SCRIPT__
|
||||
|
||||
#include <Utils/NonOwningPtr.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class ActorScript
|
||||
{
|
||||
public:
|
||||
ActorScript() = default;
|
||||
|
||||
virtual void OnInit(NonOwningPtr<class Actor> actor) = 0;
|
||||
virtual void OnUpdate(NonOwningPtr<class Scene> scene, NonOwningPtr<class Actor> actor, class Inputs& input, float delta) = 0;
|
||||
virtual void OnQuit(NonOwningPtr<class Actor> actor) = 0;
|
||||
|
||||
virtual ~ActorScript() = default;
|
||||
};
|
||||
|
||||
class SpriteScript
|
||||
{
|
||||
public:
|
||||
SpriteScript() = default;
|
||||
|
||||
virtual void OnInit(NonOwningPtr<class Sprite> sprite) = 0;
|
||||
virtual void OnUpdate(NonOwningPtr<class Scene> scene, NonOwningPtr<class Sprite> sprite, class Inputs& input, float delta) = 0;
|
||||
virtual void OnQuit(NonOwningPtr<class Sprite> sprite) = 0;
|
||||
|
||||
virtual ~SpriteScript() = default;
|
||||
};
|
||||
|
||||
class NarratorScript
|
||||
{
|
||||
public:
|
||||
NarratorScript() = default;
|
||||
|
||||
virtual void OnInit() = 0;
|
||||
virtual void OnUpdate(NonOwningPtr<class Scene> scene, class Inputs& input, float delta) = 0;
|
||||
virtual void OnQuit() = 0;
|
||||
|
||||
virtual ~NarratorScript() = default;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
19
Runtime/Includes/Core/UUID.h
git.filemode.normal_file
19
Runtime/Includes/Core/UUID.h
git.filemode.normal_file
@@ -0,0 +1,19 @@
|
||||
#ifndef __SCOP_CORE_UUID__
|
||||
#define __SCOP_CORE_UUID__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class UUID
|
||||
{
|
||||
public:
|
||||
UUID();
|
||||
inline operator std::uint64_t() const noexcept { return m_uuid; }
|
||||
|
||||
private:
|
||||
std::uint64_t m_uuid;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
39
Runtime/Includes/Debug/ImGuiRenderer.h
git.filemode.normal_file
39
Runtime/Includes/Debug/ImGuiRenderer.h
git.filemode.normal_file
@@ -0,0 +1,39 @@
|
||||
#ifndef __SCOP_IMGUI_RENDERER__
|
||||
#define __SCOP_IMGUI_RENDERER__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <kvf.h>
|
||||
#include <Renderer/RenderCore.h>
|
||||
#include <Renderer/Renderer.h>
|
||||
#include <Utils/NonOwningPtr.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class ImGuiRenderer
|
||||
{
|
||||
public:
|
||||
ImGuiRenderer(NonOwningPtr<Renderer> renderer);
|
||||
|
||||
void Init(class Inputs& inputs);
|
||||
void Destroy();
|
||||
|
||||
bool BeginFrame();
|
||||
void DisplayRenderStatistics();
|
||||
void EndFrame();
|
||||
|
||||
~ImGuiRenderer() = default;
|
||||
|
||||
private:
|
||||
void SetTheme();
|
||||
void CreateFramebuffers();
|
||||
|
||||
private:
|
||||
std::vector<VkFramebuffer> m_framebuffers;
|
||||
VkRenderPass m_renderpass = VK_NULL_HANDLE;
|
||||
VkDescriptorPool m_pool = VK_NULL_HANDLE;
|
||||
NonOwningPtr<Renderer> p_renderer;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
82
Runtime/Includes/Graphics/Actor.h
git.filemode.normal_file
82
Runtime/Includes/Graphics/Actor.h
git.filemode.normal_file
@@ -0,0 +1,82 @@
|
||||
#ifndef __SCOP_GRAPHICS_ACTOR__
|
||||
#define __SCOP_GRAPHICS_ACTOR__
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <Core/UUID.h>
|
||||
#include <Maths/Vec3.h>
|
||||
#include <Maths/Vec4.h>
|
||||
#include <Core/Script.h>
|
||||
#include <Maths/Quaternions.h>
|
||||
#include <Graphics/Model.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class Actor
|
||||
{
|
||||
friend Scene;
|
||||
|
||||
public:
|
||||
struct CustomPipeline
|
||||
{
|
||||
std::shared_ptr<GraphicPipeline> pipeline;
|
||||
std::shared_ptr<DescriptorSet> set;
|
||||
std::shared_ptr<UniformBuffer> data_uniform_buffer;
|
||||
CPUBuffer data;
|
||||
};
|
||||
|
||||
public:
|
||||
Actor();
|
||||
Actor(Model model);
|
||||
Actor(std::uint64_t uuid, Model model);
|
||||
|
||||
inline void AttachScript(std::shared_ptr<ActorScript> script) { p_script = script; }
|
||||
|
||||
inline void SetPosition(Vec3f position) noexcept { m_position = position; }
|
||||
inline void SetScale(Vec3f scale) noexcept { m_scale = scale; }
|
||||
inline void SetOrientation(Quatf orientation) noexcept { m_orientation = orientation; }
|
||||
inline void SetVisibility(bool show) noexcept { m_is_visible = show; }
|
||||
inline void SetIsOpaque(bool opaque) noexcept { m_is_opaque = opaque; }
|
||||
inline void SetCustomPipeline(CustomPipeline pipeline) { m_custom_pipeline = std::move(pipeline); }
|
||||
|
||||
[[nodiscard]] inline const Vec3f& GetPosition() const noexcept { return m_position; }
|
||||
[[nodiscard]] inline const Vec3f& GetScale() const noexcept { return m_scale; }
|
||||
[[nodiscard]] inline const Quatf& GetOrientation() const noexcept { return m_orientation; }
|
||||
[[nodiscard]] inline const Model& GetModel() const noexcept { return m_model; }
|
||||
[[nodiscard]] inline Model& GetModelRef() noexcept { return m_model; }
|
||||
[[nodiscard]] inline std::uint64_t GetUUID() const noexcept { return m_uuid; }
|
||||
[[nodiscard]] inline bool IsVisible() const noexcept { return m_is_visible; }
|
||||
[[nodiscard]] inline bool IsOpaque() const noexcept { return m_is_opaque; }
|
||||
[[nodiscard]] inline std::optional<CustomPipeline>& GetCustomPipeline() { return m_custom_pipeline; }
|
||||
|
||||
~Actor();
|
||||
|
||||
public:
|
||||
void Update(NonOwningPtr<class Scene> scene, class Inputs& input, float timestep);
|
||||
|
||||
private:
|
||||
Model m_model;
|
||||
Quatf m_orientation = Quatf::Identity();
|
||||
Vec3f m_position = Vec3f{ 0.0f, 0.0f, 0.0f };
|
||||
Vec3f m_scale = Vec3f{ 1.0f, 1.0f, 1.0f };
|
||||
std::shared_ptr<ActorScript> p_script;
|
||||
std::uint64_t m_uuid;
|
||||
std::optional<CustomPipeline> m_custom_pipeline;
|
||||
bool m_is_visible = true;
|
||||
bool m_is_opaque = true;
|
||||
};
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<Scop::Actor>
|
||||
{
|
||||
std::size_t operator()(const Scop::Actor& a) const noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(a.GetUUID());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
30
Runtime/Includes/Graphics/Cameras/Base.h
git.filemode.normal_file
30
Runtime/Includes/Graphics/Cameras/Base.h
git.filemode.normal_file
@@ -0,0 +1,30 @@
|
||||
#ifndef __SCOP_CAMERAS_BASE__
|
||||
#define __SCOP_CAMERAS_BASE__
|
||||
|
||||
#include <Maths/Mat4.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class BaseCamera
|
||||
{
|
||||
public:
|
||||
BaseCamera() = default;
|
||||
|
||||
virtual void Update(class Inputs& input, float aspect, float timestep) {};
|
||||
|
||||
[[nodiscard]] inline const Mat4f& GetView() const noexcept { return m_view; }
|
||||
[[nodiscard]] inline const Mat4f& GetProj() const noexcept { return m_proj; }
|
||||
|
||||
[[nodiscard]] virtual const Vec3f& GetPosition() const noexcept = 0;
|
||||
|
||||
virtual constexpr std::string GetCameraType() = 0;
|
||||
|
||||
virtual ~BaseCamera() = default;
|
||||
|
||||
protected:
|
||||
Mat4f m_view;
|
||||
Mat4f m_proj;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
53
Runtime/Includes/Graphics/Cameras/FirstPerson3D.h
git.filemode.normal_file
53
Runtime/Includes/Graphics/Cameras/FirstPerson3D.h
git.filemode.normal_file
@@ -0,0 +1,53 @@
|
||||
#ifndef __SCOP_CAMERAS_FIRST_PERSON_3D__
|
||||
#define __SCOP_CAMERAS_FIRST_PERSON_3D__
|
||||
|
||||
#include <Graphics/Cameras/Base.h>
|
||||
#include <Maths/Vec3.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class FirstPerson3D : public BaseCamera
|
||||
{
|
||||
public:
|
||||
FirstPerson3D();
|
||||
FirstPerson3D(Vec3f position, float fov = 90.0f, float speed = 50.0f);
|
||||
|
||||
void Update(class Inputs& input, float aspect, float timestep) override;
|
||||
|
||||
inline constexpr void EnableCamera() noexcept { m_inputs_blocked = false; }
|
||||
inline constexpr void DisableCamera() noexcept { m_inputs_blocked = true; }
|
||||
|
||||
[[nodiscard]] inline constexpr std::string GetCameraType() override { return "FirstPerson3D"; }
|
||||
[[nodiscard]] const Vec3f& GetPosition() const noexcept override { return m_position; }
|
||||
[[nodiscard]] const Vec3f& GetUp() const noexcept { return c_up; }
|
||||
[[nodiscard]] const Vec3f& GetLeft() const noexcept { return m_left; }
|
||||
[[nodiscard]] const Vec3f& GetTarget() const noexcept { return m_target; }
|
||||
[[nodiscard]] const Vec3f& GetDirection() const noexcept { return m_direction; }
|
||||
|
||||
~FirstPerson3D() = default;
|
||||
|
||||
private:
|
||||
void UpdateView();
|
||||
|
||||
private:
|
||||
const Vec3f c_up;
|
||||
Vec3f m_position;
|
||||
Vec3f m_left;
|
||||
Vec3f m_forward;
|
||||
Vec3f m_target;
|
||||
Vec3f m_direction;
|
||||
Vec3f m_mov;
|
||||
|
||||
float m_theta = 0.0;
|
||||
float m_phi = 0.0;
|
||||
|
||||
const float c_speed = 50.0f;
|
||||
const float c_sensivity = 0.7f;
|
||||
float m_speed_factor = 1.0f;
|
||||
float m_fov = 90.0f;
|
||||
|
||||
bool m_inputs_blocked = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
2833
Runtime/Includes/Graphics/DogicaTTF.h
git.filemode.normal_file
2833
Runtime/Includes/Graphics/DogicaTTF.h
git.filemode.normal_file
File diff suppressed because it is too large
Load Diff
20
Runtime/Includes/Graphics/Enums.h
git.filemode.normal_file
20
Runtime/Includes/Graphics/Enums.h
git.filemode.normal_file
@@ -0,0 +1,20 @@
|
||||
#ifndef __SCOP_GRAPHICS_ENUMS__
|
||||
#define __SCOP_GRAPHICS_ENUMS__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
enum class CullMode
|
||||
{
|
||||
None = 0,
|
||||
Back,
|
||||
Front,
|
||||
FrontAndBack,
|
||||
|
||||
EndEnum
|
||||
};
|
||||
constexpr std::size_t CullModeCount = static_cast<std::size_t>(CullMode::EndEnum);
|
||||
}
|
||||
|
||||
#endif
|
||||
61
Runtime/Includes/Graphics/Font.h
git.filemode.normal_file
61
Runtime/Includes/Graphics/Font.h
git.filemode.normal_file
@@ -0,0 +1,61 @@
|
||||
#ifndef __SCOP_FONT__
|
||||
#define __SCOP_FONT__
|
||||
|
||||
#include <variant>
|
||||
#include <filesystem>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <stb_truetype.h>
|
||||
|
||||
#include <Renderer/Image.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
constexpr const int RANGE = 1024;
|
||||
|
||||
class Font
|
||||
{
|
||||
public:
|
||||
Font(const std::filesystem::path& path, float scale) : m_build_data(path), m_name(path.string()), m_scale(scale) {}
|
||||
Font(const std::string& name, const std::vector<std::uint8_t>& ttf_data, float scale) : m_build_data(ttf_data), m_name(name), m_scale(scale) {}
|
||||
|
||||
void BuildFont();
|
||||
void Destroy();
|
||||
|
||||
inline const std::string& GetName() const { return m_name; }
|
||||
inline float GetScale() const noexcept { return m_scale; }
|
||||
inline const std::array<stbtt_packedchar, 96>& GetCharData() const { return m_cdata; }
|
||||
inline const Texture& GetTexture() const noexcept { return m_atlas; }
|
||||
inline bool operator==(const Font& rhs) const { return rhs.m_name == m_name && rhs.m_scale == m_scale; }
|
||||
inline bool operator!=(const Font& rhs) const { return rhs.m_name != m_name || rhs.m_scale != m_scale; }
|
||||
|
||||
inline ~Font() { Destroy(); }
|
||||
|
||||
private:
|
||||
std::array<stbtt_packedchar, 96> m_cdata;
|
||||
Texture m_atlas;
|
||||
std::variant<std::filesystem::path, std::vector<std::uint8_t>> m_build_data;
|
||||
std::string m_name;
|
||||
float m_scale;
|
||||
};
|
||||
|
||||
class FontRegistry
|
||||
{
|
||||
public:
|
||||
FontRegistry() = default;
|
||||
|
||||
inline void RegisterFont(std::shared_ptr<Font> font);
|
||||
inline void UnregisterFont(std::shared_ptr<Font> font);
|
||||
inline std::shared_ptr<Font> GetFont(const std::filesystem::path& name, float scale);
|
||||
inline void Reset();
|
||||
|
||||
~FontRegistry() = default;
|
||||
|
||||
private:
|
||||
std::unordered_set<std::shared_ptr<Font>> m_fonts_registry;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Graphics/Font.inl>
|
||||
|
||||
#endif
|
||||
31
Runtime/Includes/Graphics/Font.inl
git.filemode.normal_file
31
Runtime/Includes/Graphics/Font.inl
git.filemode.normal_file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include <Graphics/Font.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
void FontRegistry::RegisterFont(std::shared_ptr<Font> font)
|
||||
{
|
||||
m_fonts_registry.insert(font);
|
||||
}
|
||||
|
||||
void FontRegistry::UnregisterFont(std::shared_ptr<Font> font)
|
||||
{
|
||||
m_fonts_registry.erase(font);
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> FontRegistry::GetFont(const std::filesystem::path& name, float scale)
|
||||
{
|
||||
auto it = std::find_if(m_fonts_registry.begin(), m_fonts_registry.end(), [&name, scale](std::shared_ptr<Font> rhs)
|
||||
{
|
||||
return (name == rhs->GetName() && scale == rhs->GetScale());
|
||||
});
|
||||
return (it != m_fonts_registry.end() ? *it : nullptr);
|
||||
}
|
||||
|
||||
void FontRegistry::Reset()
|
||||
{
|
||||
for(auto& font: m_fonts_registry)
|
||||
font->Destroy();
|
||||
m_fonts_registry.clear();
|
||||
}
|
||||
}
|
||||
14
Runtime/Includes/Graphics/Loaders/BMP.h
git.filemode.normal_file
14
Runtime/Includes/Graphics/Loaders/BMP.h
git.filemode.normal_file
@@ -0,0 +1,14 @@
|
||||
#ifndef __SCOP_BMP_LOADER__
|
||||
#define __SCOP_BMP_LOADER__
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <Maths/Vec2.h>
|
||||
#include <Utils/Buffer.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
CPUBuffer LoadBMPFile(const std::filesystem::path& path, Vec2ui32& dimensions);
|
||||
}
|
||||
|
||||
#endif
|
||||
72
Runtime/Includes/Graphics/Loaders/OBJ.h
git.filemode.normal_file
72
Runtime/Includes/Graphics/Loaders/OBJ.h
git.filemode.normal_file
@@ -0,0 +1,72 @@
|
||||
#ifndef __SCOP_OBJ_LOADER__
|
||||
#define __SCOP_OBJ_LOADER__
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <filesystem>
|
||||
|
||||
#include <Maths/Vec2.h>
|
||||
#include <Maths/Vec3.h>
|
||||
#include <Maths/Vec4.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
struct ObjData
|
||||
{
|
||||
struct FaceVertex
|
||||
{
|
||||
FaceVertex() : v(-1), t(-1), n(-1) {}
|
||||
std::int32_t v;
|
||||
std::int32_t t;
|
||||
std::int32_t n;
|
||||
|
||||
inline bool operator<(const FaceVertex& rhs) const
|
||||
{
|
||||
return (v < rhs.v) || (v == rhs.v && t < rhs.t ) || (v == rhs.v && t == rhs.t && n < rhs.n);
|
||||
}
|
||||
inline bool operator==(const FaceVertex& rhs) const
|
||||
{
|
||||
return (v == rhs.v && t == rhs.t && n == rhs.n);
|
||||
}
|
||||
};
|
||||
|
||||
using FaceList = std::pair<std::vector<FaceVertex>, std::vector<std::uint32_t>>;
|
||||
|
||||
std::vector<Vec4f> color;
|
||||
std::vector<Vec3f> vertex;
|
||||
std::vector<Vec3f> normal;
|
||||
std::vector<Vec2f> tex_coord;
|
||||
|
||||
std::map<std::string, FaceList> faces;
|
||||
};
|
||||
|
||||
struct ObjModel
|
||||
{
|
||||
std::vector<Vec4f> color;
|
||||
std::vector<Vec3f> vertex;
|
||||
std::vector<Vec3f> normal;
|
||||
std::vector<Vec2f> tex_coord;
|
||||
|
||||
std::map<std::string, std::vector<std::uint32_t>> faces;
|
||||
};
|
||||
|
||||
std::optional<ObjData> LoadObjFromFile(const std::filesystem::path& path);
|
||||
void TesselateObjData(ObjData& data);
|
||||
ObjModel ConvertObjDataToObjModel(const ObjData& data);
|
||||
|
||||
template<typename T>
|
||||
inline std::istream& operator>>(std::istream& in, std::vector<T>& vec);
|
||||
|
||||
template<typename T>
|
||||
inline std::istream& operator>>(std::istream& in, std::set<T>& vec);
|
||||
|
||||
inline std::istream& operator>>(std::istream& in, ObjData::FaceVertex& f);
|
||||
}
|
||||
|
||||
#include <Graphics/Loaders/OBJ.inl>
|
||||
|
||||
#endif
|
||||
48
Runtime/Includes/Graphics/Loaders/OBJ.inl
git.filemode.normal_file
48
Runtime/Includes/Graphics/Loaders/OBJ.inl
git.filemode.normal_file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include <Graphics/Loaders/OBJ.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T>
|
||||
inline std::istream& operator>>(std::istream& in, std::vector<T>& vec)
|
||||
{
|
||||
T temp;
|
||||
if(in >> temp)
|
||||
vec.push_back(temp);
|
||||
return in;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::istream& operator>>(std::istream& in, std::set<T>& vec)
|
||||
{
|
||||
T temp;
|
||||
if(in >> temp)
|
||||
vec.insert(temp);
|
||||
return in;
|
||||
}
|
||||
|
||||
inline std::istream& operator>>(std::istream& in, ObjData::FaceVertex& f)
|
||||
{
|
||||
std::int32_t val;
|
||||
if(in >> f.v)
|
||||
{
|
||||
if(in.peek() == '/')
|
||||
{
|
||||
in.get();
|
||||
in >> f.t;
|
||||
in.clear();
|
||||
if(in.peek() == '/')
|
||||
{
|
||||
in.get();
|
||||
in >> f.n;
|
||||
in.clear();
|
||||
}
|
||||
}
|
||||
in.clear();
|
||||
f.v--;
|
||||
f.t--;
|
||||
f.n--;
|
||||
}
|
||||
return in;
|
||||
}
|
||||
}
|
||||
81
Runtime/Includes/Graphics/Material.h
git.filemode.normal_file
81
Runtime/Includes/Graphics/Material.h
git.filemode.normal_file
@@ -0,0 +1,81 @@
|
||||
#ifndef __SCOP_RENDERER_MATERIAL__
|
||||
#define __SCOP_RENDERER_MATERIAL__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <Core/EventBus.h>
|
||||
#include <Renderer/Image.h>
|
||||
#include <Renderer/Buffer.h>
|
||||
#include <Renderer/Descriptor.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
struct MaterialTextures
|
||||
{
|
||||
std::shared_ptr<Texture> albedo;
|
||||
};
|
||||
|
||||
struct MaterialData
|
||||
{
|
||||
float dissolve_texture_factor = 1.0f;
|
||||
float dissolve_black_white_colors_factor = 1.0f;
|
||||
float dissolve_normals_colors_factor = 0.0f;
|
||||
std::uint8_t __padding[4];
|
||||
};
|
||||
|
||||
class Material
|
||||
{
|
||||
friend class Model;
|
||||
|
||||
public:
|
||||
Material() { m_data_buffer.Init(sizeof(m_data)); SetupEventListener(); }
|
||||
Material(const MaterialTextures& textures) : m_textures(textures) { m_data_buffer.Init(sizeof(m_data)); SetupEventListener(); }
|
||||
|
||||
inline void SetMaterialData(const MaterialData& data) noexcept { m_data = data; }
|
||||
|
||||
~Material() { m_data_buffer.Destroy(); }
|
||||
|
||||
private:
|
||||
[[nodiscard]] inline bool IsSetInit() const noexcept { return p_set && p_set->IsInit(); }
|
||||
[[nodiscard]] inline VkDescriptorSet GetSet(std::size_t frame_index) const noexcept { return p_set->GetSet(frame_index); }
|
||||
|
||||
inline void SetupEventListener()
|
||||
{
|
||||
std::function<void(const EventBase&)> functor = [this](const EventBase& event)
|
||||
{
|
||||
if(event.What() == Event::FrameBeginEventCode)
|
||||
m_have_been_updated_this_frame = false;
|
||||
};
|
||||
EventBus::RegisterListener({ functor, "__ScopMaterial" + std::to_string(reinterpret_cast<std::uintptr_t>(this)) });
|
||||
}
|
||||
|
||||
inline void UpdateDescriptorSet(std::shared_ptr<DescriptorSet> set)
|
||||
{
|
||||
p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(set->GetShaderLayout(), set->GetShaderType());
|
||||
}
|
||||
|
||||
inline void Bind(std::size_t frame_index, VkCommandBuffer cmd)
|
||||
{
|
||||
if(m_have_been_updated_this_frame)
|
||||
return;
|
||||
p_set->SetImage(frame_index, 0, *m_textures.albedo);
|
||||
p_set->SetUniformBuffer(frame_index, 1, m_data_buffer.Get(frame_index));
|
||||
p_set->Update(frame_index, cmd);
|
||||
|
||||
static CPUBuffer buffer(sizeof(MaterialData));
|
||||
std::memcpy(buffer.GetData(), &m_data, buffer.GetSize());
|
||||
m_data_buffer.SetData(buffer, frame_index);
|
||||
|
||||
m_have_been_updated_this_frame = true;
|
||||
}
|
||||
|
||||
private:
|
||||
UniformBuffer m_data_buffer;
|
||||
MaterialTextures m_textures;
|
||||
MaterialData m_data;
|
||||
std::shared_ptr<DescriptorSet> p_set;
|
||||
bool m_have_been_updated_this_frame = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
72
Runtime/Includes/Graphics/Mesh.h
git.filemode.normal_file
72
Runtime/Includes/Graphics/Mesh.h
git.filemode.normal_file
@@ -0,0 +1,72 @@
|
||||
#ifndef __SCOPE_RENDERER_MESH__
|
||||
#define __SCOPE_RENDERER_MESH__
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include <Renderer/Vertex.h>
|
||||
#include <Renderer/Buffer.h>
|
||||
#include <Utils/Buffer.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class Mesh
|
||||
{
|
||||
public:
|
||||
struct SubMesh
|
||||
{
|
||||
MeshBuffer buffer;
|
||||
std::size_t index_size;
|
||||
std::size_t triangle_count = 0;
|
||||
|
||||
inline SubMesh(const std::vector<Vertex>& vertices, const std::vector<std::uint32_t>& indices, std::size_t index_size = 0)
|
||||
{
|
||||
CPUBuffer data(vertices.size() * sizeof(Vertex) + indices.size() * sizeof(std::uint32_t));
|
||||
std::memcpy(data.GetData(), vertices.data(), vertices.size() * sizeof(Vertex));
|
||||
std::memcpy(data.GetData() + vertices.size() * sizeof(Vertex), indices.data(), indices.size() * sizeof(std::uint32_t));
|
||||
buffer.Init(vertices.size() * sizeof(Vertex), indices.size() * sizeof(std::uint32_t), 0, std::move(data));
|
||||
this->index_size = index_size == 0 ? indices.size() : index_size;
|
||||
triangle_count = this->index_size / 3;
|
||||
}
|
||||
|
||||
inline void SetData(const std::vector<Vertex>& vertices, const std::vector<std::uint32_t>& indices, std::size_t index_size = 0)
|
||||
{
|
||||
CPUBuffer vertex_data(vertices.size() * sizeof(Scop::Vertex));
|
||||
std::memcpy(vertex_data.GetData(), vertices.data(), vertex_data.GetSize());
|
||||
CPUBuffer index_data(indices.size() * sizeof(std::uint32_t));
|
||||
std::memcpy(index_data.GetData(), indices.data(), index_data.GetSize());
|
||||
|
||||
buffer.SetVertexData(std::move(vertex_data));
|
||||
buffer.SetVertexData(std::move(index_data));
|
||||
|
||||
this->index_size = index_size == 0 ? indices.size() : index_size;
|
||||
triangle_count = this->index_size / 3;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
Mesh() = default;
|
||||
|
||||
void Draw(VkCommandBuffer cmd, std::size_t& drawcalls, std::size_t& polygondrawn) const noexcept;
|
||||
void Draw(VkCommandBuffer cmd, std::size_t& drawcalls, std::size_t& polygondrawn, std::size_t submesh_index) const noexcept;
|
||||
|
||||
inline std::size_t GetSubMeshCount() const { return m_sub_meshes.size(); }
|
||||
|
||||
inline void AddSubMesh(SubMesh mesh) { m_sub_meshes.emplace_back(std::move(mesh)); }
|
||||
[[nodiscard]] inline SubMesh& GetSubMesh(std::size_t index) { return m_sub_meshes.at(index); }
|
||||
inline void Reset()
|
||||
{
|
||||
for(auto& mesh : m_sub_meshes)
|
||||
mesh.buffer.Destroy();
|
||||
m_sub_meshes.clear();
|
||||
}
|
||||
|
||||
~Mesh();
|
||||
|
||||
private:
|
||||
std::vector<SubMesh> m_sub_meshes;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
21
Runtime/Includes/Graphics/MeshFactory.h
git.filemode.normal_file
21
Runtime/Includes/Graphics/MeshFactory.h
git.filemode.normal_file
@@ -0,0 +1,21 @@
|
||||
#ifndef __SCOP_MESH_FACTORY__
|
||||
#define __SCOP_MESH_FACTORY__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <Maths/Vec2.h>
|
||||
#include <Maths/Vec3.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
std::shared_ptr<class Mesh> CreateQuad();
|
||||
std::shared_ptr<class Mesh> CreateQuad(float x, float y, float width, float height);
|
||||
std::shared_ptr<class Mesh> CreateQuad(const Vec2f& position, const Vec2f& size);
|
||||
std::shared_ptr<class Mesh> CreateCube();
|
||||
std::shared_ptr<class Mesh> CreatePyramid();
|
||||
std::shared_ptr<class Mesh> CreateSphere(std::uint32_t x_segments = 32, std::uint32_t y_segments = 32);
|
||||
std::shared_ptr<class Mesh> CreateCapsule(float radius = 0.5f, float mid_height = 2.0f, int radial_degments = 64, int rings = 8);
|
||||
std::shared_ptr<class Mesh> CreatePlane(float width, float height, const Vec3f& normal);
|
||||
}
|
||||
|
||||
#endif
|
||||
48
Runtime/Includes/Graphics/Model.h
git.filemode.normal_file
48
Runtime/Includes/Graphics/Model.h
git.filemode.normal_file
@@ -0,0 +1,48 @@
|
||||
#ifndef __SCOPE_RENDERER_MODEL__
|
||||
#define __SCOPE_RENDERER_MODEL__
|
||||
|
||||
#include <memory>
|
||||
#include <filesystem>
|
||||
|
||||
#include <kvf.h>
|
||||
|
||||
#include <Maths/Vec3.h>
|
||||
#include <Graphics/Mesh.h>
|
||||
#include <Graphics/Material.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
// Only static meshes for now
|
||||
class Model
|
||||
{
|
||||
friend class ScopEngine;
|
||||
friend Model LoadModelFromObjFile(std::filesystem::path path) noexcept;
|
||||
|
||||
public:
|
||||
Model() = default;
|
||||
Model(std::shared_ptr<Mesh> mesh);
|
||||
|
||||
inline void SetMaterial(std::shared_ptr<Material> material, std::size_t mesh_index) { m_materials[mesh_index] = material; }
|
||||
inline std::size_t GetSubMeshCount() const { return p_mesh->GetSubMeshCount(); }
|
||||
|
||||
[[nodiscard]] inline std::shared_ptr<Material> GetMaterial(std::size_t mesh_index) { return m_materials[mesh_index]; }
|
||||
[[nodiscard]] inline std::vector<std::shared_ptr<Material>>& GetAllMaterials() { return m_materials; }
|
||||
[[nodiscard]] inline Vec3f GetCenter() const noexcept { return m_center; }
|
||||
[[nodiscard]] inline std::shared_ptr<Mesh> GetMesh() const { return p_mesh; }
|
||||
|
||||
void Draw(VkCommandBuffer cmd, std::shared_ptr<DescriptorSet> matrices_set, const class GraphicPipeline& pipeline, std::shared_ptr<DescriptorSet> set, std::size_t& drawcalls, std::size_t& polygondrawn, std::size_t frame_index) const;
|
||||
|
||||
~Model() = default;
|
||||
|
||||
private:
|
||||
inline static std::shared_ptr<Material> s_default_material = nullptr;
|
||||
|
||||
Vec3f m_center = { 0.0f, 0.0f, 0.0f };
|
||||
std::vector<std::shared_ptr<Material>> m_materials;
|
||||
std::shared_ptr<Mesh> p_mesh;
|
||||
};
|
||||
|
||||
Model LoadModelFromObjFile(std::filesystem::path path) noexcept;
|
||||
}
|
||||
|
||||
#endif
|
||||
53
Runtime/Includes/Graphics/Narrator.h
git.filemode.normal_file
53
Runtime/Includes/Graphics/Narrator.h
git.filemode.normal_file
@@ -0,0 +1,53 @@
|
||||
#ifndef __SCOP_GRAPHICS_NARRATOR__
|
||||
#define __SCOP_GRAPHICS_NARRATOR__
|
||||
|
||||
#include <Maths/Vec3.h>
|
||||
#include <Maths/Vec4.h>
|
||||
#include <Maths/Quaternions.h>
|
||||
#include <Core/Script.h>
|
||||
#include <Graphics/Model.h>
|
||||
#include <Core/UUID.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class Narrator
|
||||
{
|
||||
friend Scene;
|
||||
|
||||
public:
|
||||
Narrator() : m_uuid(UUID()) {}
|
||||
Narrator(std::uint64_t uuid) : m_uuid(uuid) {}
|
||||
inline void AttachScript(std::shared_ptr<NarratorScript> script) { p_script = script; }
|
||||
[[nodiscard]] inline std::uint64_t GetUUID() const noexcept { return m_uuid; }
|
||||
inline ~Narrator()
|
||||
{
|
||||
if(p_script)
|
||||
p_script->OnQuit();
|
||||
}
|
||||
|
||||
private:
|
||||
inline void Update(NonOwningPtr<class Scene> scene, class Inputs& input, float timestep)
|
||||
{
|
||||
if(p_script)
|
||||
p_script->OnUpdate(scene, input, timestep);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<NarratorScript> p_script;
|
||||
std::uint64_t m_uuid;
|
||||
};
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<Scop::Narrator>
|
||||
{
|
||||
std::size_t operator()(const Scop::Narrator& n) const noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(n.GetUUID());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
126
Runtime/Includes/Graphics/Scene.h
git.filemode.normal_file
126
Runtime/Includes/Graphics/Scene.h
git.filemode.normal_file
@@ -0,0 +1,126 @@
|
||||
#ifndef __SCOP_SCENE__
|
||||
#define __SCOP_SCENE__
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <Utils/NonOwningPtr.h>
|
||||
|
||||
#include <Graphics/Enums.h>
|
||||
#include <Graphics/Actor.h>
|
||||
#include <Graphics/Narrator.h>
|
||||
#include <Graphics/Sprite.h>
|
||||
#include <Renderer/Buffer.h>
|
||||
#include <Renderer/Descriptor.h>
|
||||
#include <Renderer/RenderCore.h>
|
||||
#include <Graphics/Cameras/Base.h>
|
||||
#include <Renderer/Pipelines/Shader.h>
|
||||
#include <Renderer/Pipelines/Graphics.h>
|
||||
#include <Graphics/Font.h>
|
||||
#include <Graphics/Text.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
struct SceneDescriptor
|
||||
{
|
||||
std::shared_ptr<Shader> fragment_shader;
|
||||
std::shared_ptr<Shader> post_process_shader = nullptr;
|
||||
std::shared_ptr<BaseCamera> camera;
|
||||
CullMode culling;
|
||||
std::size_t post_process_data_size = 0;
|
||||
bool render_3D_enabled = true;
|
||||
bool render_2D_enabled = true;
|
||||
bool render_skybox_enabled = true;
|
||||
bool render_post_process_enabled = false;
|
||||
};
|
||||
|
||||
class Scene
|
||||
{
|
||||
friend class ScopEngine;
|
||||
|
||||
public:
|
||||
struct ForwardData
|
||||
{
|
||||
std::shared_ptr<DescriptorSet> matrices_set;
|
||||
std::shared_ptr<DescriptorSet> albedo_set;
|
||||
std::shared_ptr<UniformBuffer> matrices_buffer;
|
||||
bool wireframe = false;
|
||||
};
|
||||
|
||||
struct PostProcessData
|
||||
{
|
||||
std::shared_ptr<DescriptorSet> set;
|
||||
std::shared_ptr<UniformBuffer> data_buffer;
|
||||
CPUBuffer data;
|
||||
};
|
||||
|
||||
public:
|
||||
Scene(std::string_view name, SceneDescriptor desc);
|
||||
Scene(std::string_view name, SceneDescriptor desc, NonOwningPtr<Scene> parent);
|
||||
|
||||
Actor& CreateActor(Model model) noexcept;
|
||||
Actor& CreateActor(std::string_view name, Model model);
|
||||
|
||||
Narrator& CreateNarrator() noexcept;
|
||||
Narrator& CreateNarrator(std::string_view name);
|
||||
|
||||
Sprite& CreateSprite(std::shared_ptr<Texture> texture) noexcept;
|
||||
Sprite& CreateSprite(std::string_view name, std::shared_ptr<Texture> texture);
|
||||
|
||||
Text& CreateText(std::string text) noexcept;
|
||||
Text& CreateText(std::string_view name, std::string text);
|
||||
|
||||
void LoadFont(std::filesystem::path path, float scale);
|
||||
|
||||
void RemoveActor(Actor& actor) noexcept;
|
||||
void RemoveNarrator(Narrator& narrator) noexcept;
|
||||
void RemoveSprite(Sprite& sprite) noexcept;
|
||||
void RemoveText(Text& text) noexcept;
|
||||
|
||||
[[nodiscard]] inline Scene& AddChildScene(std::string_view name, SceneDescriptor desc) { return m_scene_children.emplace_back(name, std::move(desc), this); }
|
||||
inline void AddSkybox(std::shared_ptr<CubeTexture> cubemap) { p_skybox = cubemap; }
|
||||
void SwitchToChild(std::string_view name) const noexcept;
|
||||
void SwitchToParent() const noexcept;
|
||||
|
||||
[[nodiscard]] inline ForwardData& GetForwardData() noexcept { return m_forward; }
|
||||
[[nodiscard]] inline PostProcessData& GetPostProcessData() noexcept { return m_post_process; }
|
||||
[[nodiscard]] inline const std::unordered_map<std::uint64_t, Actor>& GetActors() const noexcept { return m_actors; }
|
||||
[[nodiscard]] inline const std::unordered_map<std::uint64_t, Sprite>& GetSprites() const noexcept { return m_sprites; }
|
||||
[[nodiscard]] inline const std::unordered_map<std::uint64_t, Text>& GetTexts() const noexcept { return m_texts; }
|
||||
[[nodiscard]] inline const std::string& GetName() const noexcept { return m_name; }
|
||||
[[nodiscard]] inline GraphicPipeline& GetPipeline() noexcept { return m_pipeline; }
|
||||
[[nodiscard]] inline std::shared_ptr<BaseCamera> GetCamera() const { return m_descriptor.camera; }
|
||||
[[nodiscard]] inline DepthImage& GetDepth() noexcept { return m_depth; }
|
||||
[[nodiscard]] inline std::shared_ptr<Shader> GetFragmentShader() const { return m_descriptor.fragment_shader; }
|
||||
[[nodiscard]] inline std::shared_ptr<CubeTexture> GetSkybox() const { return p_skybox; }
|
||||
[[nodiscard]] inline const SceneDescriptor& GetDescription() const noexcept { return m_descriptor; }
|
||||
|
||||
~Scene() = default;
|
||||
|
||||
private:
|
||||
Scene() = default;
|
||||
void Init(NonOwningPtr<class Renderer> renderer);
|
||||
void Update(class Inputs& input, float delta, float aspect);
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
GraphicPipeline m_pipeline;
|
||||
ForwardData m_forward;
|
||||
PostProcessData m_post_process;
|
||||
DepthImage m_depth;
|
||||
SceneDescriptor m_descriptor;
|
||||
FontRegistry m_fonts_registry;
|
||||
std::shared_ptr<CubeTexture> p_skybox;
|
||||
std::unordered_map<std::uint64_t, Actor> m_actors;
|
||||
std::unordered_map<std::uint64_t, Text> m_texts;
|
||||
std::unordered_map<std::uint64_t, Sprite> m_sprites;
|
||||
std::unordered_map<std::uint64_t, Narrator> m_narrators;
|
||||
std::vector<Scene> m_scene_children;
|
||||
std::string m_name;
|
||||
NonOwningPtr<Scene> p_parent;
|
||||
std::shared_ptr<Font> p_bound_font;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
78
Runtime/Includes/Graphics/Sprite.h
git.filemode.normal_file
78
Runtime/Includes/Graphics/Sprite.h
git.filemode.normal_file
@@ -0,0 +1,78 @@
|
||||
#ifndef __SCOP_RENDERER_SPRITE__
|
||||
#define __SCOP_RENDERER_SPRITE__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <Maths/Vec2.h>
|
||||
#include <Maths/Vec4.h>
|
||||
#include <Core/Script.h>
|
||||
#include <Graphics/Mesh.h>
|
||||
#include <Renderer/Descriptor.h>
|
||||
#include <Renderer/Image.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class Sprite
|
||||
{
|
||||
friend class Render2DPass;
|
||||
|
||||
public:
|
||||
Sprite(std::shared_ptr<Texture> texture);
|
||||
Sprite(std::uint64_t uuid, std::shared_ptr<Texture> texture);
|
||||
|
||||
inline void AttachScript(std::shared_ptr<SpriteScript> script) { p_script = script; }
|
||||
void Update(NonOwningPtr<class Scene> scene, class Inputs& input, float timestep);
|
||||
|
||||
inline void SetColor(Vec4f color) noexcept { m_color = color; }
|
||||
inline void SetPosition(Vec2ui position) noexcept { m_position = position; }
|
||||
inline void SetScale(Vec2f scale) noexcept { m_scale = scale; }
|
||||
|
||||
[[nodiscard]] inline const Vec4f& GetColor() const noexcept { return m_color; }
|
||||
[[nodiscard]] inline const Vec2ui& GetPosition() const noexcept { return m_position; }
|
||||
[[nodiscard]] inline const Vec2f& GetScale() const noexcept { return m_scale; }
|
||||
[[nodiscard]] inline std::shared_ptr<Mesh> GetMesh() const { return p_mesh; }
|
||||
[[nodiscard]] inline std::shared_ptr<Texture> GetTexture() const { return p_texture; }
|
||||
[[nodiscard]] inline std::uint64_t GetUUID() const noexcept { return m_uuid; }
|
||||
|
||||
~Sprite();
|
||||
|
||||
private:
|
||||
[[nodiscard]] inline bool IsSetInit() const noexcept { return p_set && p_set->IsInit(); }
|
||||
[[nodiscard]] inline VkDescriptorSet GetSet(std::size_t frame_index) const noexcept { return p_set->GetSet(frame_index); }
|
||||
|
||||
inline void UpdateDescriptorSet(std::shared_ptr<DescriptorSet> set)
|
||||
{
|
||||
p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(set->GetShaderLayout(), set->GetShaderType());
|
||||
}
|
||||
|
||||
inline void Bind(std::size_t frame_index, VkCommandBuffer cmd)
|
||||
{
|
||||
p_set->SetImage(frame_index, 0, *p_texture);
|
||||
p_set->Update(frame_index, cmd);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DescriptorSet> p_set;
|
||||
std::shared_ptr<Texture> p_texture;
|
||||
std::shared_ptr<class SpriteScript> p_script;
|
||||
std::shared_ptr<Mesh> p_mesh;
|
||||
Vec4f m_color = Vec4f{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
Vec2ui m_position = Vec2ui{ 0, 0 };
|
||||
Vec2f m_scale = Vec2f{ 1.0f, 1.0f };
|
||||
std::uint64_t m_uuid;
|
||||
};
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<Scop::Sprite>
|
||||
{
|
||||
std::size_t operator()(const Scop::Sprite& s) const noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(s.GetUUID());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
56
Runtime/Includes/Graphics/Text.h
git.filemode.normal_file
56
Runtime/Includes/Graphics/Text.h
git.filemode.normal_file
@@ -0,0 +1,56 @@
|
||||
#ifndef __SCOP_TEXT__
|
||||
#define __SCOP_TEXT__
|
||||
|
||||
#include <Graphics/Font.h>
|
||||
#include <Graphics/Mesh.h>
|
||||
#include <Renderer/Descriptor.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class Text
|
||||
{
|
||||
friend class Render2DPass;
|
||||
|
||||
public:
|
||||
Text(std::uint64_t uuid, const std::string& text, std::shared_ptr<Font> font);
|
||||
|
||||
inline void SetColor(Vec4f color) noexcept { m_color = color; }
|
||||
inline void SetPosition(Vec2ui position) noexcept { m_position = position; }
|
||||
inline void SetScale(Vec2f scale) noexcept { m_scale = scale; }
|
||||
|
||||
[[nodiscard]] inline const std::string& GetText() const { return m_text; }
|
||||
[[nodiscard]] inline std::shared_ptr<Font> GetFont() const { return p_font; }
|
||||
[[nodiscard]] inline const Vec4f& GetColor() const noexcept { return m_color; }
|
||||
[[nodiscard]] inline const Vec2ui& GetPosition() const noexcept { return m_position; }
|
||||
[[nodiscard]] inline const Vec2f& GetScale() const noexcept { return m_scale; }
|
||||
[[nodiscard]] inline std::shared_ptr<Mesh> GetMesh() const { return p_mesh; }
|
||||
[[nodiscard]] inline std::uint64_t GetUUID() const noexcept { return m_uuid; }
|
||||
|
||||
virtual ~Text() = default;
|
||||
|
||||
private:
|
||||
[[nodiscard]] inline bool IsSetInit() const noexcept { return p_set && p_set->IsInit(); }
|
||||
[[nodiscard]] inline VkDescriptorSet GetSet(std::size_t frame_index) const noexcept { return p_set->GetSet(frame_index); }
|
||||
inline void UpdateDescriptorSet(std::shared_ptr<DescriptorSet> set)
|
||||
{
|
||||
p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(set->GetShaderLayout(), set->GetShaderType());
|
||||
}
|
||||
inline void Bind(std::size_t frame_index, VkCommandBuffer cmd)
|
||||
{
|
||||
p_set->SetImage(frame_index, 0, const_cast<Texture&>(p_font->GetTexture()));
|
||||
p_set->Update(frame_index, cmd);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<DescriptorSet> p_set;
|
||||
std::shared_ptr<Mesh> p_mesh;
|
||||
std::shared_ptr<Font> p_font;
|
||||
std::string m_text;
|
||||
Vec4f m_color = Vec4f{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
Vec2ui m_position = Vec2ui{ 0, 0 };
|
||||
Vec2f m_scale = Vec2f{ 1.0f, 1.0f };
|
||||
std::uint64_t m_uuid;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
108
Runtime/Includes/Maths/Angles.h
git.filemode.normal_file
108
Runtime/Includes/Maths/Angles.h
git.filemode.normal_file
@@ -0,0 +1,108 @@
|
||||
#ifndef __SCOP_ANGLES__
|
||||
#define __SCOP_ANGLES__
|
||||
|
||||
#include <Maths/Enums.h>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T> struct EulerAngles;
|
||||
template<typename T> struct Quat;
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
struct Angle
|
||||
{
|
||||
T value;
|
||||
|
||||
constexpr Angle() = default;
|
||||
constexpr Angle(T angle);
|
||||
template<typename U> constexpr explicit Angle(const Angle<Unit, U>& Angle);
|
||||
template<AngleUnit FromUnit> constexpr Angle(const Angle<FromUnit, T>& angle);
|
||||
constexpr Angle(const Angle&) = default;
|
||||
constexpr Angle(Angle&&) noexcept = default;
|
||||
~Angle() = default;
|
||||
|
||||
constexpr bool ApproxEqual(const Angle& angle) const;
|
||||
constexpr bool ApproxEqual(const Angle& angle, T max_difference) const;
|
||||
|
||||
T GetCos() const;
|
||||
T GetSin() const;
|
||||
std::pair<T, T> GetSinCos() const;
|
||||
T GetTan() const;
|
||||
|
||||
constexpr Angle& Normalize();
|
||||
|
||||
template<AngleUnit ToUnit> T To() const;
|
||||
template<AngleUnit ToUnit> Angle<ToUnit, T> ToAngle() const;
|
||||
constexpr T ToDegrees() const;
|
||||
constexpr Angle<AngleUnit::Degree, T> ToDegreeAngle() const;
|
||||
EulerAngles<T> ToEulerAngles() const;
|
||||
Quat<T> ToQuat() const;
|
||||
constexpr T ToRadians() const;
|
||||
constexpr Angle<AngleUnit::Radian, T> ToRadianAngle() const;
|
||||
std::string ToString() const;
|
||||
constexpr T ToTurns() const;
|
||||
constexpr Angle<AngleUnit::Turn, T> ToTurnAngle() const;
|
||||
|
||||
constexpr Angle& operator=(const Angle&) = default;
|
||||
constexpr Angle& operator=(Angle&&) noexcept = default;
|
||||
|
||||
constexpr Angle operator+() const;
|
||||
constexpr Angle operator-() const;
|
||||
|
||||
constexpr Angle operator+(Angle other) const;
|
||||
constexpr Angle operator-(Angle other) const;
|
||||
constexpr Angle operator*(T scalar) const;
|
||||
constexpr Angle operator/(T divider) const;
|
||||
|
||||
constexpr Angle& operator+=(Angle other);
|
||||
constexpr Angle& operator-=(Angle other);
|
||||
constexpr Angle& operator*=(T scalar);
|
||||
constexpr Angle& operator/=(T divider);
|
||||
|
||||
constexpr bool operator==(Angle other) const;
|
||||
constexpr bool operator!=(Angle other) const;
|
||||
constexpr bool operator<(Angle other) const;
|
||||
constexpr bool operator<=(Angle other) const;
|
||||
constexpr bool operator>(Angle other) const;
|
||||
constexpr bool operator>=(Angle other) const;
|
||||
|
||||
static constexpr bool ApproxEqual(const Angle& lhs, const Angle& rhs);
|
||||
static constexpr bool ApproxEqual(const Angle& lhs, const Angle& rhs, T max_difference);
|
||||
static constexpr Angle Clamp(Angle angle, Angle min, Angle max);
|
||||
template<AngleUnit FromUnit> static constexpr Angle From(T value);
|
||||
static constexpr Angle FromDegrees(T degrees);
|
||||
static constexpr Angle FromRadians(T radians);
|
||||
static constexpr Angle FromTurns(T turn);
|
||||
static constexpr Angle Zero();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using DegreeAngle = Angle<AngleUnit::Degree, T>;
|
||||
|
||||
using DegreeAngled = DegreeAngle<double>;
|
||||
using DegreeAnglef = DegreeAngle<float>;
|
||||
|
||||
template<typename T>
|
||||
using RadianAngle = Angle<AngleUnit::Radian, T>;
|
||||
|
||||
using RadianAngled = RadianAngle<double>;
|
||||
using RadianAnglef = RadianAngle<float>;
|
||||
|
||||
template<typename T>
|
||||
using TurnAngle = Angle<AngleUnit::Turn, T>;
|
||||
|
||||
using TurnAngled = TurnAngle<double>;
|
||||
using TurnAnglef = TurnAngle<float>;
|
||||
|
||||
template<AngleUnit Unit, typename T> Angle<Unit, T> operator*(T scale, Angle<Unit, T> angle);
|
||||
|
||||
template<AngleUnit Unit, typename T> Angle<Unit, T> operator/(T divider, Angle<Unit, T> angle);
|
||||
|
||||
template<AngleUnit Unit, typename T> std::ostream& operator<<(std::ostream& out, Angle<Unit, T> angle);
|
||||
}
|
||||
|
||||
#include <Maths/Angles.inl>
|
||||
|
||||
#endif
|
||||
488
Runtime/Includes/Maths/Angles.inl
git.filemode.normal_file
488
Runtime/Includes/Maths/Angles.inl
git.filemode.normal_file
@@ -0,0 +1,488 @@
|
||||
#pragma once
|
||||
#include <Maths/Angles.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include <Maths/Constants.h>
|
||||
#include <Maths/MathsUtils.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
template<AngleUnit From, AngleUnit To> struct AngleConversion;
|
||||
|
||||
template<AngleUnit Unit>
|
||||
struct AngleConversion<Unit, Unit>
|
||||
{
|
||||
template<typename T>
|
||||
static constexpr T Convert(T angle)
|
||||
{
|
||||
return angle;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AngleConversion<AngleUnit::Degree, AngleUnit::Radian>
|
||||
{
|
||||
template<typename T>
|
||||
static constexpr T Convert(T angle)
|
||||
{
|
||||
return DegreeToRadian(angle);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AngleConversion<AngleUnit::Degree, AngleUnit::Turn>
|
||||
{
|
||||
template<typename T>
|
||||
static constexpr T Convert(T angle)
|
||||
{
|
||||
return angle / T(360);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AngleConversion<AngleUnit::Radian, AngleUnit::Degree>
|
||||
{
|
||||
template<typename T>
|
||||
static constexpr T Convert(T angle)
|
||||
{
|
||||
return RadianToDegree(angle);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AngleConversion<AngleUnit::Radian, AngleUnit::Turn>
|
||||
{
|
||||
template<typename T>
|
||||
static constexpr T Convert(T angle)
|
||||
{
|
||||
return angle / Tau<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AngleConversion<AngleUnit::Turn, AngleUnit::Degree>
|
||||
{
|
||||
template<typename T>
|
||||
static constexpr T Convert(T angle)
|
||||
{
|
||||
return angle * T(360);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AngleConversion<AngleUnit::Turn, AngleUnit::Radian>
|
||||
{
|
||||
template<typename T>
|
||||
static constexpr T Convert(T angle)
|
||||
{
|
||||
return angle * Tau<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template<AngleUnit Unit> struct AngleUtils;
|
||||
|
||||
template<>
|
||||
struct AngleUtils<AngleUnit::Degree>
|
||||
{
|
||||
template<typename T>
|
||||
static constexpr T GetEpsilon()
|
||||
{
|
||||
return T(1e-4);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr T GetLimit()
|
||||
{
|
||||
return 360;
|
||||
}
|
||||
|
||||
template<typename T> static std::ostream& ToString(std::ostream& out, T value)
|
||||
{
|
||||
return out << "Angle(" << value << "deg)";
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AngleUtils<AngleUnit::Radian>
|
||||
{
|
||||
template<typename T>
|
||||
static constexpr T GetEpsilon()
|
||||
{
|
||||
return T(1e-5);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr T GetLimit()
|
||||
{
|
||||
return Tau<T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::ostream& ToString(std::ostream& out, T value)
|
||||
{
|
||||
return out << "Angle(" << value << "rad)";
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AngleUtils<AngleUnit::Turn>
|
||||
{
|
||||
template<typename T>
|
||||
static constexpr T GetEpsilon()
|
||||
{
|
||||
return T(1e-5);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr T GetLimit()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::ostream& ToString(std::ostream& out, T value)
|
||||
{
|
||||
return out << "Angle(" << value << "turn)";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void SinCos(T x, T* sin, T* cos)
|
||||
{
|
||||
double s, c;
|
||||
::sincos(x, &s, &c);
|
||||
|
||||
*sin = static_cast<T>(s);
|
||||
*cos = static_cast<T>(c);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SinCos(float x, float* s, float* c)
|
||||
{
|
||||
::sincosf(x, s, c);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SinCos(long double x, long double* s, long double* c)
|
||||
{
|
||||
::sincosl(x, s, c);
|
||||
}
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T>::Angle(T angle) :
|
||||
value(angle)
|
||||
{
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
template<typename U>
|
||||
constexpr Angle<Unit, T>::Angle(const Angle<Unit, U>& angle) :
|
||||
value(static_cast<T>(angle.value))
|
||||
{
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
template<AngleUnit FromUnit>
|
||||
constexpr Angle<Unit, T>::Angle(const Angle<FromUnit, T>& angle) :
|
||||
value(Internal::AngleConversion<FromUnit, Unit>::Convert(angle.value))
|
||||
{
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr bool Angle<Unit, T>::ApproxEqual(const Angle& angle) const
|
||||
{
|
||||
return ApproxEqual(angle, Internal::AngleUtils<Unit>::template GetEpsilon<T>());
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr bool Angle<Unit, T>::ApproxEqual(const Angle& angle, T maxDifference) const
|
||||
{
|
||||
return NumberEquals(value, angle.value, maxDifference);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
T Angle<Unit, T>::GetCos() const
|
||||
{
|
||||
return std::cos(ToRadians());
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
T Angle<Unit, T>::GetSin() const
|
||||
{
|
||||
return std::sin(ToRadians());
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
std::pair<T, T> Angle<Unit, T>::GetSinCos() const
|
||||
{
|
||||
T sin, cos;
|
||||
Internal::SinCos<T>(ToRadians(), &sin, &cos);
|
||||
|
||||
return std::make_pair(sin, cos);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
T Angle<Unit, T>::GetTan() const
|
||||
{
|
||||
return std::tan(ToRadians());
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T>& Angle<Unit, T>::Normalize()
|
||||
{
|
||||
constexpr T limit = Internal::AngleUtils<Unit>::template GetLimit<T>();
|
||||
constexpr T halfLimit = limit / T(2);
|
||||
|
||||
value = Mod(value + halfLimit, limit);
|
||||
if (value < T(0))
|
||||
value += limit;
|
||||
|
||||
value -= halfLimit;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
template<AngleUnit ToUnit>
|
||||
T Angle<Unit, T>::To() const
|
||||
{
|
||||
return Internal::AngleConversion<Unit, ToUnit>::Convert(value);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
template<AngleUnit ToUnit>
|
||||
Angle<ToUnit, T> Angle<Unit, T>::ToAngle() const
|
||||
{
|
||||
return Angle<ToUnit, T>(To<ToUnit>());
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr T Angle<Unit, T>::ToDegrees() const
|
||||
{
|
||||
return To<AngleUnit::Degree>();
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<AngleUnit::Degree, T> Angle<Unit, T>::ToDegreeAngle() const
|
||||
{
|
||||
return ToAngle<AngleUnit::Degree>();
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
EulerAngles<T> Angle<Unit, T>::ToEulerAngles() const
|
||||
{
|
||||
return EulerAngles<T>(0, 0, ToDegrees());
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
Quat<T> Angle<Unit, T>::ToQuat() const
|
||||
{
|
||||
auto halfAngle = Angle(*this) / 2.f;
|
||||
auto sincos = halfAngle.GetSinCos();
|
||||
return Quat<T>(sincos.second, 0, 0, sincos.first);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr T Angle<Unit, T>::ToRadians() const
|
||||
{
|
||||
return To<AngleUnit::Radian>();
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<AngleUnit::Radian, T> Angle<Unit, T>::ToRadianAngle() const
|
||||
{
|
||||
return ToAngle<AngleUnit::Radian>();
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
std::string Angle<Unit, T>::ToString() const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
Internal::AngleUtils<Unit>::ToString(oss, value);
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr T Angle<Unit, T>::ToTurns() const
|
||||
{
|
||||
return To<AngleUnit::Turn>(value);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<AngleUnit::Turn, T> Angle<Unit, T>::ToTurnAngle() const
|
||||
{
|
||||
return ToAngle<AngleUnit::Turn>();
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::operator-() const
|
||||
{
|
||||
return Angle(-value);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::operator+(Angle other) const
|
||||
{
|
||||
return Angle(value + other.value);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::operator-(Angle other) const
|
||||
{
|
||||
return Angle(value - other.value);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::operator*(T scalar) const
|
||||
{
|
||||
return Angle(value * scalar);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::operator/(T divider) const
|
||||
{
|
||||
return Angle(value / divider);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T>& Angle<Unit, T>::operator+=(Angle other)
|
||||
{
|
||||
value += other.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T>& Angle<Unit, T>::operator-=(Angle other)
|
||||
{
|
||||
value -= other.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T>& Angle<Unit, T>::operator*=(T scalar)
|
||||
{
|
||||
value *= scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T>& Angle<Unit, T>::operator/=(T divider)
|
||||
{
|
||||
value /= divider;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr bool Angle<Unit, T>::operator==(Angle other) const
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr bool Angle<Unit, T>::operator!=(Angle other) const
|
||||
{
|
||||
return value != other.value;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr bool Angle<Unit, T>::operator<(Angle other) const
|
||||
{
|
||||
return value < other.value;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr bool Angle<Unit, T>::operator<=(Angle other) const
|
||||
{
|
||||
return value <= other.value;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr bool Angle<Unit, T>::operator>(Angle other) const
|
||||
{
|
||||
return value > other.value;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr bool Angle<Unit, T>::operator>=(Angle other) const
|
||||
{
|
||||
return value >= other.value;
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr bool Angle<Unit, T>::ApproxEqual(const Angle& lhs, const Angle& rhs)
|
||||
{
|
||||
return lhs.ApproxEqual(rhs);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr bool Angle<Unit, T>::ApproxEqual(const Angle& lhs, const Angle& rhs, T maxDifference)
|
||||
{
|
||||
return lhs.ApproxEqual(rhs, maxDifference);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::Clamp(Angle angle, Angle min, Angle max)
|
||||
{
|
||||
return Angle(std::clamp(angle.value, min.value, max.value));
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
template<AngleUnit FromUnit>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::From(T value)
|
||||
{
|
||||
return Angle(Internal::AngleConversion<FromUnit, Unit>::Convert(value));
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::FromDegrees(T degrees)
|
||||
{
|
||||
return From<AngleUnit::Degree>(degrees);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::FromRadians(T radians)
|
||||
{
|
||||
return From<AngleUnit::Radian>(radians);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::FromTurns(T turns)
|
||||
{
|
||||
return From<AngleUnit::Turn>(turns);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
constexpr Angle<Unit, T> Angle<Unit, T>::Zero()
|
||||
{
|
||||
return Angle(0);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
Angle<Unit, T> operator/(T scale, Angle<Unit, T> angle)
|
||||
{
|
||||
return Angle<Unit, T>(scale / angle.value);
|
||||
}
|
||||
|
||||
template<AngleUnit Unit, typename T>
|
||||
std::ostream& operator<<(std::ostream& out, Angle<Unit, T> angle)
|
||||
{
|
||||
return Internal::AngleUtils<Unit>::ToString(out, angle.value);
|
||||
}
|
||||
|
||||
template<typename T, AngleUnit Unit>
|
||||
constexpr Angle<Unit, T> Clamp(Angle<Unit, T> value, T min, T max)
|
||||
{
|
||||
return std::max(std::min(value.value, max), min);
|
||||
}
|
||||
}
|
||||
87
Runtime/Includes/Maths/Constants.h
git.filemode.normal_file
87
Runtime/Includes/Maths/Constants.h
git.filemode.normal_file
@@ -0,0 +1,87 @@
|
||||
#ifndef __SCOP_MATHS_CONSTANTS__
|
||||
#define __SCOP_MATHS_CONSTANTS__
|
||||
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T> constexpr std::size_t BitCount = CHAR_BIT * sizeof(T);
|
||||
|
||||
template<typename T>
|
||||
struct MathConstants
|
||||
{
|
||||
static constexpr T Infinity()
|
||||
{
|
||||
static_assert(std::numeric_limits<T>::has_infinity);
|
||||
return std::numeric_limits<T>::infinity();
|
||||
}
|
||||
|
||||
static constexpr T Max()
|
||||
{
|
||||
return std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
static constexpr T Min()
|
||||
{
|
||||
return std::numeric_limits<T>::min();
|
||||
}
|
||||
|
||||
static constexpr T NaN()
|
||||
{
|
||||
static_assert(std::numeric_limits<T>::has_signaling_NaN);
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
|
||||
// Math constants
|
||||
static constexpr T HalfPi()
|
||||
{
|
||||
static_assert(std::is_floating_point_v<T>);
|
||||
return T(1.5707963267948966192313216916398);
|
||||
}
|
||||
|
||||
static constexpr T Pi()
|
||||
{
|
||||
static_assert(std::is_floating_point_v<T>);
|
||||
return T(3.1415926535897932384626433832795);
|
||||
}
|
||||
|
||||
static constexpr T Sqrt2()
|
||||
{
|
||||
static_assert(std::is_floating_point_v<T>);
|
||||
return T(1.4142135623730950488016887242097);
|
||||
}
|
||||
|
||||
static constexpr T Sqrt3()
|
||||
{
|
||||
static_assert(std::is_floating_point_v<T>);
|
||||
return T(1.7320508075688772935274463415059);
|
||||
}
|
||||
|
||||
static constexpr T Sqrt5()
|
||||
{
|
||||
static_assert(std::is_floating_point_v<T>);
|
||||
return T(2.2360679774997896964091736687313);
|
||||
}
|
||||
|
||||
static constexpr T Tau()
|
||||
{
|
||||
static_assert(std::is_floating_point_v<T>);
|
||||
return T(6.2831853071795864769252867665590);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T = void> constexpr auto Infinity() { return MathConstants<T>::Infinity(); }
|
||||
template<typename T = void> constexpr auto MaxValue() { return MathConstants<T>::Max(); }
|
||||
template<typename T = void> constexpr auto MinValue() { return MathConstants<T>::Min(); }
|
||||
template<typename T = void> constexpr auto NaN() { return MathConstants<T>::NaN(); }
|
||||
template<typename T = void> constexpr auto HalfPi() { return MathConstants<T>::HalfPi(); }
|
||||
template<typename T = void> constexpr auto Pi() { return MathConstants<T>::Pi(); }
|
||||
template<typename T = void> constexpr auto Sqrt2() { return MathConstants<T>::Sqrt2(); }
|
||||
template<typename T = void> constexpr auto Sqrt3() { return MathConstants<T>::Sqrt3(); }
|
||||
template<typename T = void> constexpr auto Sqrt5() { return MathConstants<T>::Sqrt5(); }
|
||||
template<typename T = void> constexpr auto Tau() { return MathConstants<T>::Tau(); }
|
||||
}
|
||||
|
||||
#endif
|
||||
20
Runtime/Includes/Maths/Enums.h
git.filemode.normal_file
20
Runtime/Includes/Maths/Enums.h
git.filemode.normal_file
@@ -0,0 +1,20 @@
|
||||
#ifndef __SCOP_MATHS_ENUMS__
|
||||
#define __SCOP_MATHS_ENUMS__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
enum class AngleUnit
|
||||
{
|
||||
Degree = 0,
|
||||
Radian,
|
||||
Turn,
|
||||
|
||||
EndEnum
|
||||
};
|
||||
|
||||
constexpr std::size_t AngleUnitCount = static_cast<std::size_t>(AngleUnit::EndEnum);
|
||||
}
|
||||
|
||||
#endif
|
||||
57
Runtime/Includes/Maths/EulerAngles.h
git.filemode.normal_file
57
Runtime/Includes/Maths/EulerAngles.h
git.filemode.normal_file
@@ -0,0 +1,57 @@
|
||||
#ifndef __SCOP_EULER_ANGLES__
|
||||
#define __SCOP_EULER_ANGLES__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <Maths/Angles.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T>
|
||||
struct EulerAngles
|
||||
{
|
||||
constexpr EulerAngles() = default;
|
||||
constexpr EulerAngles(DegreeAngle<T> P, DegreeAngle<T> Y, DegreeAngle<T> R);
|
||||
constexpr EulerAngles(const DegreeAngle<T> angles[3]);
|
||||
template<AngleUnit Unit> constexpr EulerAngles(const Angle<Unit, T>& angle);
|
||||
constexpr EulerAngles(const Quat<T>& quat);
|
||||
template<typename U> constexpr explicit EulerAngles(const EulerAngles<U>& angles);
|
||||
constexpr EulerAngles(const EulerAngles&) = default;
|
||||
constexpr EulerAngles(EulerAngles&&) = default;
|
||||
~EulerAngles() = default;
|
||||
|
||||
constexpr bool ApproxEqual(const EulerAngles& angles, T maxDifference = std::numeric_limits<T>::epsilon()) const;
|
||||
|
||||
constexpr EulerAngles& Normalize();
|
||||
|
||||
Quat<T> ToQuat() const;
|
||||
std::string ToString() const;
|
||||
|
||||
constexpr EulerAngles operator+(const EulerAngles& angles) const;
|
||||
constexpr EulerAngles operator-(const EulerAngles& angles) const;
|
||||
|
||||
constexpr EulerAngles& operator=(const EulerAngles&) = default;
|
||||
constexpr EulerAngles& operator=(EulerAngles&&) = default;
|
||||
|
||||
constexpr EulerAngles& operator+=(const EulerAngles& angles);
|
||||
constexpr EulerAngles& operator-=(const EulerAngles& angles);
|
||||
|
||||
constexpr bool operator==(const EulerAngles& angles) const;
|
||||
constexpr bool operator!=(const EulerAngles& angles) const;
|
||||
constexpr bool operator<(const EulerAngles& angles) const;
|
||||
constexpr bool operator<=(const EulerAngles& angles) const;
|
||||
constexpr bool operator>(const EulerAngles& angles) const;
|
||||
constexpr bool operator>=(const EulerAngles& angles) const;
|
||||
|
||||
static constexpr bool ApproxEqual(const EulerAngles& lhs, const EulerAngles& rhs, T maxDifference = std::numeric_limits<T>::epsilon());
|
||||
static constexpr EulerAngles Zero();
|
||||
|
||||
DegreeAngle<T> pitch, yaw, roll;
|
||||
};
|
||||
|
||||
using EulerAnglesf = EulerAngles<float>;
|
||||
}
|
||||
|
||||
#include <Maths/EulerAngles.inl>
|
||||
|
||||
#endif
|
||||
169
Runtime/Includes/Maths/EulerAngles.inl
git.filemode.normal_file
169
Runtime/Includes/Maths/EulerAngles.inl
git.filemode.normal_file
@@ -0,0 +1,169 @@
|
||||
#pragma once
|
||||
#include <Maths/EulerAngles.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T>
|
||||
constexpr EulerAngles<T>::EulerAngles(DegreeAngle<T> P, DegreeAngle<T> Y, DegreeAngle<T> R) :
|
||||
pitch(P), yaw(Y), roll(R)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
constexpr EulerAngles<T>::EulerAngles(const DegreeAngle<T> angles[3]) :
|
||||
EulerAngles(angles[0], angles[1], angles[2])
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
template<AngleUnit Unit>
|
||||
constexpr EulerAngles<T>::EulerAngles(const Angle<Unit, T>& angle) :
|
||||
EulerAngles(angle.ToEulerAngles())
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
constexpr EulerAngles<T>::EulerAngles(const Quat<T>& quat) :
|
||||
EulerAngles(quat.ToEulerAngles())
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr EulerAngles<T>::EulerAngles(const EulerAngles<U>& angles) :
|
||||
pitch(DegreeAngle<T>(angles.pitch)), yaw(DegreeAngle<T>(angles.yaw)), roll(DegreeAngle<T>(angles.roll))
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool EulerAngles<T>::ApproxEqual(const EulerAngles& angles, T maxDifference) const
|
||||
{
|
||||
return pitch.ApproxEqual(angles.pitch, maxDifference) && yaw.ApproxEqual(angles.yaw, maxDifference) && roll.ApproxEqual(angles.roll, maxDifference);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr EulerAngles<T>& EulerAngles<T>::Normalize()
|
||||
{
|
||||
pitch.Normalize();
|
||||
yaw.Normalize();
|
||||
roll.Normalize();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T> EulerAngles<T>::ToQuat() const
|
||||
{
|
||||
// XYZ
|
||||
auto [s1, c1] = (yaw / T(2.0)).GetSinCos();
|
||||
auto [s2, c2] = (roll / T(2.0)).GetSinCos();
|
||||
auto [s3, c3] = (pitch / T(2.0)).GetSinCos();
|
||||
|
||||
return Quat<T>(c1 * c2 * c3 - s1 * s2 * s3,
|
||||
s1 * s2 * c3 + c1 * c2 * s3,
|
||||
s1 * c2 * c3 + c1 * s2 * s3,
|
||||
c1 * s2 * c3 - s1 * c2 * s3);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string EulerAngles<T>::ToString() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << *this;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr EulerAngles<T> EulerAngles<T>::operator+(const EulerAngles& angles) const
|
||||
{
|
||||
return EulerAngles(pitch + angles.pitch, yaw + angles.yaw, roll + angles.roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr EulerAngles<T> EulerAngles<T>::operator-(const EulerAngles& angles) const
|
||||
{
|
||||
return EulerAngles(pitch - angles.pitch, yaw - angles.yaw, roll - angles.roll);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr EulerAngles<T>& EulerAngles<T>::operator+=(const EulerAngles& angles)
|
||||
{
|
||||
pitch += angles.pitch;
|
||||
yaw += angles.yaw;
|
||||
roll += angles.roll;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr EulerAngles<T>& EulerAngles<T>::operator-=(const EulerAngles& angles)
|
||||
{
|
||||
pitch -= angles.pitch;
|
||||
yaw -= angles.yaw;
|
||||
roll -= angles.roll;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool EulerAngles<T>::operator==(const EulerAngles& angles) const
|
||||
{
|
||||
return pitch == angles.pitch && yaw == angles.yaw && roll == angles.roll;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool EulerAngles<T>::operator!=(const EulerAngles& angles) const
|
||||
{
|
||||
return !operator==(angles);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool EulerAngles<T>::operator<(const EulerAngles& angles) const
|
||||
{
|
||||
if (pitch != angles.pitch)
|
||||
return pitch < angles.pitch;
|
||||
if (yaw != angles.yaw)
|
||||
return yaw < angles.yaw;
|
||||
return roll < angles.roll;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool EulerAngles<T>::operator<=(const EulerAngles& angles) const
|
||||
{
|
||||
if (pitch != angles.pitch)
|
||||
return pitch < angles.pitch;
|
||||
if (yaw != angles.yaw)
|
||||
return yaw < angles.yaw;
|
||||
return roll <= angles.roll;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool EulerAngles<T>::operator>(const EulerAngles& angles) const
|
||||
{
|
||||
if (pitch != angles.pitch)
|
||||
return pitch > angles.pitch;
|
||||
if (yaw != angles.yaw)
|
||||
return yaw > angles.yaw;
|
||||
return roll > angles.roll;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool EulerAngles<T>::operator>=(const EulerAngles& angles) const
|
||||
{
|
||||
if (pitch != angles.pitch)
|
||||
return pitch > angles.pitch;
|
||||
if (yaw != angles.yaw)
|
||||
return yaw > angles.yaw;
|
||||
return roll >= angles.roll;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool EulerAngles<T>::ApproxEqual(const EulerAngles& lhs, const EulerAngles& rhs, T maxDifference)
|
||||
{
|
||||
return lhs.ApproxEqual(rhs, maxDifference);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr EulerAngles<T> EulerAngles<T>::Zero()
|
||||
{
|
||||
return EulerAngles(0, 0, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const EulerAngles<T>& angles)
|
||||
{
|
||||
return out << "EulerAngles(" << angles.pitch << ", " << angles.yaw << ", " << angles.roll << ')';
|
||||
}
|
||||
}
|
||||
124
Runtime/Includes/Maths/Mat4.h
git.filemode.normal_file
124
Runtime/Includes/Maths/Mat4.h
git.filemode.normal_file
@@ -0,0 +1,124 @@
|
||||
#ifndef __SCOP_MAT4__
|
||||
#define __SCOP_MAT4__
|
||||
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <Maths/Angles.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T> struct Vec2;
|
||||
template<typename T> struct Vec3;
|
||||
template<typename T> struct Vec4;
|
||||
template<typename T> struct Quat;
|
||||
|
||||
template<typename T>
|
||||
struct Mat4
|
||||
{
|
||||
T m11, m12, m13, m14;
|
||||
T m21, m22, m23, m24;
|
||||
T m31, m32, m33, m34;
|
||||
T m41, m42, m43, m44;
|
||||
|
||||
constexpr Mat4() = default;
|
||||
constexpr Mat4(T r11, T r12, T r13, T r14,
|
||||
T r21, T r22, T r23, T r24,
|
||||
T r31, T r32, T r33, T r34,
|
||||
T r41, T r42, T r43, T r44);
|
||||
constexpr Mat4(const T& col_1, const T& col_2, const T& col_3, const T& col_4);
|
||||
constexpr Mat4(const Vec4<T>& col_1, const Vec4<T>& col_2, const Vec4<T>& col_3, const Vec4<T>& col_4);
|
||||
constexpr Mat4(const T matrix[16]);
|
||||
constexpr Mat4(const Mat4&) = default;
|
||||
constexpr Mat4(Mat4&&) = default;
|
||||
|
||||
constexpr Mat4& ApplyRotation(const Quat<T>& rotation);
|
||||
constexpr Mat4& ApplyScale(const Vec3<T>& scale);
|
||||
constexpr Mat4& ApplyTranslation(const Vec3<T>& translation);
|
||||
|
||||
constexpr bool ApproxEqual(const Mat4& vec, T max_difference = std::numeric_limits<T>::epsilon()) const;
|
||||
|
||||
constexpr Mat4& Concatenate(const Mat4& matrix);
|
||||
constexpr Mat4& ConcatenateTransform(const Mat4& matrix);
|
||||
|
||||
constexpr Vec4<T> GetColumn(std::size_t column) const;
|
||||
constexpr T GetDeterminant() const;
|
||||
constexpr T GetDeterminantTransform() const;
|
||||
constexpr bool GetInverse(Mat4* dest) const;
|
||||
constexpr bool GetInverseTransform(Mat4* dest) const;
|
||||
Quat<T> GetRotation() const;
|
||||
constexpr Vec4<T> GetRow(std::size_t row) const;
|
||||
constexpr Vec3<T> GetScale() const;
|
||||
constexpr Vec3<T> GetSquaredScale() const;
|
||||
constexpr Vec3<T> GetTranslation() const;
|
||||
constexpr void GetTransposed(Mat4* dest) const;
|
||||
|
||||
constexpr bool HasNegativeScale() const;
|
||||
constexpr bool HasScale() const;
|
||||
|
||||
constexpr Mat4& Inverse(bool* succeeded = nullptr);
|
||||
constexpr Mat4& InverseTransform(bool* succeeded = nullptr);
|
||||
|
||||
constexpr bool IsTransformMatrix() const;
|
||||
constexpr bool IsIdentity() const;
|
||||
|
||||
constexpr Mat4& SetRotation(const Quat<T>& rotation);
|
||||
constexpr Mat4& SetScale(const Vec3<T>& scale);
|
||||
constexpr Mat4& SetTranslation(const Vec3<T>& translation);
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
constexpr Vec2<T> Transform(const Vec2<T>& vector, T z = 0.0, T w = 1.0) const;
|
||||
constexpr Vec3<T> Transform(const Vec3<T>& vector, T w = 1.0) const;
|
||||
constexpr Vec4<T> Transform(const Vec4<T>& vector) const;
|
||||
|
||||
constexpr Mat4& Transpose();
|
||||
|
||||
constexpr T& operator()(std::size_t x, std::size_t y);
|
||||
constexpr const T& operator()(std::size_t x, std::size_t y) const;
|
||||
|
||||
constexpr T& operator[](std::size_t i);
|
||||
constexpr const T& operator[](std::size_t i) const;
|
||||
|
||||
constexpr Mat4& operator=(const Mat4&) = default;
|
||||
constexpr Mat4& operator=(Mat4&&) = default;
|
||||
|
||||
constexpr Mat4 operator*(const Mat4& matrix) const;
|
||||
constexpr Vec2<T> operator*(const Vec2<T>& vector) const;
|
||||
constexpr Vec3<T> operator*(const Vec3<T>& vector) const;
|
||||
constexpr Vec4<T> operator*(const Vec4<T>& vector) const;
|
||||
constexpr Mat4 operator*(T scalar) const;
|
||||
|
||||
constexpr Mat4& operator*=(const Mat4& matrix);
|
||||
constexpr Mat4& operator*=(T scalar);
|
||||
|
||||
constexpr bool operator==(const Mat4& mat) const;
|
||||
constexpr bool operator!=(const Mat4& mat) const;
|
||||
|
||||
static constexpr bool ApproxEqual(const Mat4& lhs, const Mat4& rhs, T max_difference = std::numeric_limits<T>::epsilon());
|
||||
static constexpr Mat4 Concatenate(const Mat4& left, const Mat4& right);
|
||||
static constexpr Mat4 ConcatenateTransform(const Mat4& left, const Mat4& right);
|
||||
static constexpr Mat4 Identity();
|
||||
static constexpr Mat4 LookAt(const Vec3<T>& eye, const Vec3<T>& target, const Vec3<T>& up = Vec3<T>::Up());
|
||||
static constexpr Mat4 Ortho(T left, T right, T top, T bottom, T zNear = -1.0, T zFar = 1.0);
|
||||
static Mat4 Perspective(RadianAngle<T> angle, T ratio, T zNear, T zFar);
|
||||
static constexpr Mat4 Rotate(const Quat<T>& rotation);
|
||||
static constexpr Mat4 Scale(const Vec3<T>& scale);
|
||||
static constexpr Mat4 Translate(const Vec3<T>& translation);
|
||||
static constexpr Mat4 Transform(const Vec3<T>& translation, const Quat<T>& rotation);
|
||||
static constexpr Mat4 Transform(const Vec3<T>& translation, const Quat<T>& rotation, const Vec3<T>& scale);
|
||||
static constexpr Mat4 TransformInverse(const Vec3<T>& translation, const Quat<T>& rotation);
|
||||
static constexpr Mat4 TransformInverse(const Vec3<T>& translation, const Quat<T>& rotation, const Vec3<T>& scale);
|
||||
static constexpr Mat4 Zero();
|
||||
|
||||
~Mat4() = default;
|
||||
};
|
||||
|
||||
using Mat4d = Mat4<double>;
|
||||
using Mat4f = Mat4<float>;
|
||||
}
|
||||
|
||||
#include <Maths/Mat4.inl>
|
||||
|
||||
#endif
|
||||
895
Runtime/Includes/Maths/Mat4.inl
git.filemode.normal_file
895
Runtime/Includes/Maths/Mat4.inl
git.filemode.normal_file
@@ -0,0 +1,895 @@
|
||||
#pragma once
|
||||
#include <Maths/Mat4.h>
|
||||
|
||||
#include <Core/Logs.h>
|
||||
#include <Maths/EulerAngles.h>
|
||||
#include <Maths/Quaternions.h>
|
||||
#include <Maths/Vec2.h>
|
||||
#include <Maths/Vec3.h>
|
||||
#include <Maths/Vec4.h>
|
||||
#include <Maths/MathsUtils.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T>
|
||||
constexpr Mat4<T>::Mat4(T r11, T r12, T r13, T r14,
|
||||
T r21, T r22, T r23, T r24,
|
||||
T r31, T r32, T r33, T r34,
|
||||
T r41, T r42, T r43, T r44) :
|
||||
m11(r11), m12(r12), m13(r13), m14(r14),
|
||||
m21(r21), m22(r22), m23(r23), m24(r24),
|
||||
m31(r31), m32(r32), m33(r33), m34(r34),
|
||||
m41(r41), m42(r42), m43(r43), m44(r44)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>::Mat4(const T matrix[16]) :
|
||||
Mat4(matrix[ 0], matrix[ 1], matrix[ 2], matrix[ 3],
|
||||
matrix[ 4], matrix[ 5], matrix[ 6], matrix[ 7],
|
||||
matrix[ 8], matrix[ 9], matrix[10], matrix[11],
|
||||
matrix[12], matrix[13], matrix[14], matrix[15])
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>::Mat4(const T& col_1, const T& col_2, const T& col_3, const T& col_4) :
|
||||
m11(col_1), m12(col_2), m13(col_3), m14(col_4),
|
||||
m21(col_1), m22(col_2), m23(col_3), m24(col_4),
|
||||
m31(col_1), m32(col_2), m33(col_3), m34(col_4),
|
||||
m41(col_1), m42(col_2), m43(col_3), m44(col_4)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>::Mat4(const Vec4<T>& col_1, const Vec4<T>& col_2, const Vec4<T>& col_3, const Vec4<T>& col_4) :
|
||||
m11(col_1.x), m12(col_2.x), m13(col_3.x), m14(col_4.x),
|
||||
m21(col_1.y), m22(col_2.y), m23(col_3.y), m24(col_4.y),
|
||||
m31(col_1.z), m32(col_2.z), m33(col_3.z), m34(col_4.z),
|
||||
m41(col_1.w), m42(col_2.w), m43(col_3.w), m44(col_4.w)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::ApplyRotation(const Quat<T>& rotation)
|
||||
{
|
||||
return Concatenate(Mat4<T>::Rotate(rotation));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::ApplyScale(const Vec3<T>& scale)
|
||||
{
|
||||
m11 *= scale.x;
|
||||
m12 *= scale.x;
|
||||
m13 *= scale.x;
|
||||
|
||||
m21 *= scale.y;
|
||||
m22 *= scale.y;
|
||||
m23 *= scale.y;
|
||||
|
||||
m31 *= scale.z;
|
||||
m32 *= scale.z;
|
||||
m33 *= scale.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::ApplyTranslation(const Vec3<T>& translation)
|
||||
{
|
||||
m41 += translation.x;
|
||||
m42 += translation.y;
|
||||
m43 += translation.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Mat4<T>::ApproxEqual(const Mat4& mat, T maxDifference) const
|
||||
{
|
||||
for(unsigned int i = 0; i < 16; ++i)
|
||||
if(!NumberEquals((&m11)[i], (&mat.m11)[i], maxDifference))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::Concatenate(const Mat4& matrix)
|
||||
{
|
||||
return operator=(Mat4(
|
||||
m11 * matrix.m11 + m12 * matrix.m21 + m13 * matrix.m31 + m14 * matrix.m41,
|
||||
m11 * matrix.m12 + m12 * matrix.m22 + m13 * matrix.m32 + m14 * matrix.m42,
|
||||
m11 * matrix.m13 + m12 * matrix.m23 + m13 * matrix.m33 + m14 * matrix.m43,
|
||||
m11 * matrix.m14 + m12 * matrix.m24 + m13 * matrix.m34 + m14 * matrix.m44,
|
||||
|
||||
m21 * matrix.m11 + m22 * matrix.m21 + m23 * matrix.m31 + m24 * matrix.m41,
|
||||
m21 * matrix.m12 + m22 * matrix.m22 + m23 * matrix.m32 + m24 * matrix.m42,
|
||||
m21 * matrix.m13 + m22 * matrix.m23 + m23 * matrix.m33 + m24 * matrix.m43,
|
||||
m21 * matrix.m14 + m22 * matrix.m24 + m23 * matrix.m34 + m24 * matrix.m44,
|
||||
|
||||
m31 * matrix.m11 + m32 * matrix.m21 + m33 * matrix.m31 + m34 * matrix.m41,
|
||||
m31 * matrix.m12 + m32 * matrix.m22 + m33 * matrix.m32 + m34 * matrix.m42,
|
||||
m31 * matrix.m13 + m32 * matrix.m23 + m33 * matrix.m33 + m34 * matrix.m43,
|
||||
m31 * matrix.m14 + m32 * matrix.m24 + m33 * matrix.m34 + m34 * matrix.m44,
|
||||
|
||||
m41 * matrix.m11 + m42 * matrix.m21 + m43 * matrix.m31 + m44 * matrix.m41,
|
||||
m41 * matrix.m12 + m42 * matrix.m22 + m43 * matrix.m32 + m44 * matrix.m42,
|
||||
m41 * matrix.m13 + m42 * matrix.m23 + m43 * matrix.m33 + m44 * matrix.m43,
|
||||
m41 * matrix.m14 + m42 * matrix.m24 + m43 * matrix.m34 + m44 * matrix.m44
|
||||
));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::ConcatenateTransform(const Mat4& matrix)
|
||||
{
|
||||
return operator=(Mat4(
|
||||
m11*matrix.m11 + m12*matrix.m21 + m13*matrix.m31,
|
||||
m11*matrix.m12 + m12*matrix.m22 + m13*matrix.m32,
|
||||
m11*matrix.m13 + m12*matrix.m23 + m13*matrix.m33,
|
||||
T(0.0),
|
||||
|
||||
m21*matrix.m11 + m22*matrix.m21 + m23*matrix.m31,
|
||||
m21*matrix.m12 + m22*matrix.m22 + m23*matrix.m32,
|
||||
m21*matrix.m13 + m22*matrix.m23 + m23*matrix.m33,
|
||||
T(0.0),
|
||||
|
||||
m31*matrix.m11 + m32*matrix.m21 + m33*matrix.m31,
|
||||
m31*matrix.m12 + m32*matrix.m22 + m33*matrix.m32,
|
||||
m31*matrix.m13 + m32*matrix.m23 + m33*matrix.m33,
|
||||
T(0.0),
|
||||
|
||||
m41*matrix.m11 + m42*matrix.m21 + m43*matrix.m31 + matrix.m41,
|
||||
m41*matrix.m12 + m42*matrix.m22 + m43*matrix.m32 + matrix.m42,
|
||||
m41*matrix.m13 + m42*matrix.m23 + m43*matrix.m33 + matrix.m43,
|
||||
T(1.0)
|
||||
));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Mat4<T>::GetColumn(std::size_t column) const
|
||||
{
|
||||
Assert(column < 4, "column index out of range");
|
||||
const T* ptr = &m11 + column * 4;
|
||||
return Vec4<T>(ptr[0], ptr[1], ptr[2], ptr[3]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Mat4<T>::GetDeterminant() const
|
||||
{
|
||||
T A = m22*(m33*m44 - m43*m34) - m32*(m23*m44 - m43*m24) + m42*(m23*m34 - m33*m24);
|
||||
T B = m12*(m33*m44 - m43*m34) - m32*(m13*m44 - m43*m14) + m42*(m13*m34 - m33*m14);
|
||||
T C = m12*(m23*m44 - m43*m24) - m22*(m13*m44 - m43*m14) + m42*(m13*m24 - m23*m14);
|
||||
T D = m12*(m23*m34 - m33*m24) - m22*(m13*m34 - m33*m14) + m32*(m13*m24 - m23*m14);
|
||||
|
||||
return m11*A - m21*B + m31*C - m41*D;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Mat4<T>::GetDeterminantTransform() const
|
||||
{
|
||||
T A = m22*m33 - m32*m23;
|
||||
T B = m12*m33 - m32*m13;
|
||||
T C = m12*m23 - m22*m13;
|
||||
|
||||
return m11*A - m21*B + m31*C;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Mat4<T>::GetInverse(Mat4* dest) const
|
||||
{
|
||||
Assert(dest, "destination matrix must be valid");
|
||||
|
||||
T det = GetDeterminant();
|
||||
if(det == T(0.0))
|
||||
return false;
|
||||
|
||||
// http://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
|
||||
T inv[16];
|
||||
inv[0] = m22 * m33 * m44 -
|
||||
m22 * m34 * m43 -
|
||||
m32 * m23 * m44 +
|
||||
m32 * m24 * m43 +
|
||||
m42 * m23 * m34 -
|
||||
m42 * m24 * m33;
|
||||
|
||||
inv[1] = -m12 * m33 * m44 +
|
||||
m12 * m34 * m43 +
|
||||
m32 * m13 * m44 -
|
||||
m32 * m14 * m43 -
|
||||
m42 * m13 * m34 +
|
||||
m42 * m14 * m33;
|
||||
|
||||
inv[2] = m12 * m23 * m44 -
|
||||
m12 * m24 * m43 -
|
||||
m22 * m13 * m44 +
|
||||
m22 * m14 * m43 +
|
||||
m42 * m13 * m24 -
|
||||
m42 * m14 * m23;
|
||||
|
||||
inv[3] = -m12 * m23 * m34 +
|
||||
m12 * m24 * m33 +
|
||||
m22 * m13 * m34 -
|
||||
m22 * m14 * m33 -
|
||||
m32 * m13 * m24 +
|
||||
m32 * m14 * m23;
|
||||
|
||||
inv[4] = -m21 * m33 * m44 +
|
||||
m21 * m34 * m43 +
|
||||
m31 * m23 * m44 -
|
||||
m31 * m24 * m43 -
|
||||
m41 * m23 * m34 +
|
||||
m41 * m24 * m33;
|
||||
|
||||
inv[5] = m11 * m33 * m44 -
|
||||
m11 * m34 * m43 -
|
||||
m31 * m13 * m44 +
|
||||
m31 * m14 * m43 +
|
||||
m41 * m13 * m34 -
|
||||
m41 * m14 * m33;
|
||||
|
||||
inv[6] = -m11 * m23 * m44 +
|
||||
m11 * m24 * m43 +
|
||||
m21 * m13 * m44 -
|
||||
m21 * m14 * m43 -
|
||||
m41 * m13 * m24 +
|
||||
m41 * m14 * m23;
|
||||
|
||||
inv[7] = m11 * m23 * m34 -
|
||||
m11 * m24 * m33 -
|
||||
m21 * m13 * m34 +
|
||||
m21 * m14 * m33 +
|
||||
m31 * m13 * m24 -
|
||||
m31 * m14 * m23;
|
||||
|
||||
inv[8] = m21 * m32 * m44 -
|
||||
m21 * m34 * m42 -
|
||||
m31 * m22 * m44 +
|
||||
m31 * m24 * m42 +
|
||||
m41 * m22 * m34 -
|
||||
m41 * m24 * m32;
|
||||
|
||||
inv[9] = -m11 * m32 * m44 +
|
||||
m11 * m34 * m42 +
|
||||
m31 * m12 * m44 -
|
||||
m31 * m14 * m42 -
|
||||
m41 * m12 * m34 +
|
||||
m41 * m14 * m32;
|
||||
|
||||
inv[10] = m11 * m22 * m44 -
|
||||
m11 * m24 * m42 -
|
||||
m21 * m12 * m44 +
|
||||
m21 * m14 * m42 +
|
||||
m41 * m12 * m24 -
|
||||
m41 * m14 * m22;
|
||||
|
||||
inv[11] = -m11 * m22 * m34 +
|
||||
m11 * m24 * m32 +
|
||||
m21 * m12 * m34 -
|
||||
m21 * m14 * m32 -
|
||||
m31 * m12 * m24 +
|
||||
m31 * m14 * m22;
|
||||
|
||||
inv[12] = -m21 * m32 * m43 +
|
||||
m21 * m33 * m42 +
|
||||
m31 * m22 * m43 -
|
||||
m31 * m23 * m42 -
|
||||
m41 * m22 * m33 +
|
||||
m41 * m23 * m32;
|
||||
|
||||
inv[13] = m11 * m32 * m43 -
|
||||
m11 * m33 * m42 -
|
||||
m31 * m12 * m43 +
|
||||
m31 * m13 * m42 +
|
||||
m41 * m12 * m33 -
|
||||
m41 * m13 * m32;
|
||||
|
||||
inv[14] = -m11 * m22 * m43 +
|
||||
m11 * m23 * m42 +
|
||||
m21 * m12 * m43 -
|
||||
m21 * m13 * m42 -
|
||||
m41 * m12 * m23 +
|
||||
m41 * m13 * m22;
|
||||
|
||||
inv[15] = m11 * m22 * m33 -
|
||||
m11 * m23 * m32 -
|
||||
m21 * m12 * m33 +
|
||||
m21 * m13 * m32 +
|
||||
m31 * m12 * m23 -
|
||||
m31 * m13 * m22;
|
||||
|
||||
T invDet = T(1.0) / det;
|
||||
for(unsigned int i = 0; i < 16; ++i)
|
||||
inv[i] *= invDet;
|
||||
|
||||
*dest = inv;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Mat4<T>::GetInverseTransform(Mat4* dest) const
|
||||
{
|
||||
Assert(dest, "destination matrix must be valid");
|
||||
|
||||
T det = GetDeterminantTransform();
|
||||
if(det == T(0.0))
|
||||
return false;
|
||||
|
||||
|
||||
// http://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
|
||||
T inv[16];
|
||||
inv[0] = m22 * m33 -
|
||||
m32 * m23;
|
||||
|
||||
inv[1] = -m12 * m33 +
|
||||
m32 * m13;
|
||||
|
||||
inv[2] = m12 * m23 -
|
||||
m22 * m13;
|
||||
|
||||
inv[3] = T(0.0);
|
||||
|
||||
inv[4] = -m21 * m33 +
|
||||
m31 * m23;
|
||||
|
||||
inv[5] = m11 * m33 -
|
||||
m31 * m13;
|
||||
|
||||
inv[6] = -m11 * m23 +
|
||||
m21 * m13;
|
||||
|
||||
inv[7] = T(0.0);
|
||||
|
||||
inv[8] = m21 * m32 -
|
||||
m31 * m22;
|
||||
|
||||
inv[9] = -m11 * m32 +
|
||||
m31 * m12;
|
||||
|
||||
inv[10] = m11 * m22 -
|
||||
m21 * m12;
|
||||
|
||||
inv[11] = T(0.0);
|
||||
|
||||
inv[12] = -m21 * m32 * m43 +
|
||||
m21 * m33 * m42 +
|
||||
m31 * m22 * m43 -
|
||||
m31 * m23 * m42 -
|
||||
m41 * m22 * m33 +
|
||||
m41 * m23 * m32;
|
||||
|
||||
inv[13] = m11 * m32 * m43 -
|
||||
m11 * m33 * m42 -
|
||||
m31 * m12 * m43 +
|
||||
m31 * m13 * m42 +
|
||||
m41 * m12 * m33 -
|
||||
m41 * m13 * m32;
|
||||
|
||||
inv[14] = -m11 * m22 * m43 +
|
||||
m11 * m23 * m42 +
|
||||
m21 * m12 * m43 -
|
||||
m21 * m13 * m42 -
|
||||
m41 * m12 * m23 +
|
||||
m41 * m13 * m22;
|
||||
|
||||
T invDet = T(1.0) / det;
|
||||
for(unsigned int i = 0; i < 16; ++i)
|
||||
inv[i] *= invDet;
|
||||
|
||||
inv[15] = T(1.0);
|
||||
|
||||
*dest = inv;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T> Mat4<T>::GetRotation() const
|
||||
{
|
||||
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuat/
|
||||
Quat<T> quat;
|
||||
|
||||
T trace = m11 + m22 + m33;
|
||||
if(trace > T(0.0))
|
||||
{
|
||||
T s = T(0.5) / std::sqrt(trace + T(1.0));
|
||||
quat.w = T(0.25) / s;
|
||||
quat.x = (m23 - m32) * s;
|
||||
quat.y = (m31 - m13) * s;
|
||||
quat.z = (m12 - m21) * s;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m11 > m22 && m11 > m33)
|
||||
{
|
||||
T s = T(2.0) * std::sqrt(T(1.0) + m11 - m22 - m33);
|
||||
|
||||
quat.w = (m23 - m32) / s;
|
||||
quat.x = T(0.25) * s;
|
||||
quat.y = (m21 + m12) / s;
|
||||
quat.z = (m31 + m13) / s;
|
||||
}
|
||||
else if(m22 > m33)
|
||||
{
|
||||
T s = T(2.0) * std::sqrt(T(1.0) + m22 - m11 - m33);
|
||||
|
||||
quat.w = (m31 - m13) / s;
|
||||
quat.x = (m21 + m12) / s;
|
||||
quat.y = T(0.25) * s;
|
||||
quat.z = (m32 + m23) / s;
|
||||
}
|
||||
else
|
||||
{
|
||||
T s = T(2.0) * std::sqrt(T(1.0) + m33 - m11 - m22);
|
||||
|
||||
quat.w = (m12 - m21) / s;
|
||||
quat.x = (m31 + m13) / s;
|
||||
quat.y = (m32 + m23) / s;
|
||||
quat.z = T(0.25) * s;
|
||||
}
|
||||
}
|
||||
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Mat4<T>::GetRow(std::size_t row) const
|
||||
{
|
||||
Assert(row < 4, "row index out of range");
|
||||
|
||||
const T* ptr = &m11;
|
||||
return Vec4<T>(ptr[row], ptr[row+4], ptr[row+8], ptr[row+12]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Mat4<T>::GetScale() const
|
||||
{
|
||||
Vec3<T> squaredScale = GetSquaredScale();
|
||||
return Vec3<T>(std::sqrt(squaredScale.x), std::sqrt(squaredScale.y), std::sqrt(squaredScale.z));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Mat4<T>::GetSquaredScale() const
|
||||
{
|
||||
return Vec3<T>(m11 * m11 + m12 * m12 + m13 * m13,
|
||||
m21 * m21 + m22 * m22 + m23 * m23,
|
||||
m31 * m31 + m32 * m32 + m33 * m33);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Mat4<T>::GetTranslation() const
|
||||
{
|
||||
return Vec3<T>(m41, m42, m43);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void Mat4<T>::GetTransposed(Mat4* dest) const
|
||||
{
|
||||
(*dest) = Mat4f(
|
||||
m11, m21, m31, m41,
|
||||
m12, m22, m32, m42,
|
||||
m13, m23, m33, m43,
|
||||
m14, m24, m34, m44
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Mat4<T>::HasNegativeScale() const
|
||||
{
|
||||
return GetDeterminant() < T(0.0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Mat4<T>::HasScale() const
|
||||
{
|
||||
T t = m11*m11 + m21*m21 + m31*m31;
|
||||
if(!NumberEquals(t, T(1.0)))
|
||||
return true;
|
||||
|
||||
t = m12*m12 + m22*m22 + m32*m32;
|
||||
if(!NumberEquals(t, T(1.0)))
|
||||
return true;
|
||||
|
||||
t = m13*m13 + m23*m23 + m33*m33;
|
||||
if(!NumberEquals(t, T(1.0)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::Inverse(bool* succeeded)
|
||||
{
|
||||
bool result = GetInverse(this);
|
||||
if(succeeded)
|
||||
*succeeded = result;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::InverseTransform(bool* succeeded)
|
||||
{
|
||||
bool result = GetInverseTransform(this);
|
||||
if(succeeded)
|
||||
*succeeded = result;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Mat4<T>::IsTransformMatrix() const
|
||||
{
|
||||
return NumberEquals(m14, T(0.0)) && NumberEquals(m24, T(0.0)) && NumberEquals(m34, T(0.0)) && NumberEquals(m44, T(1.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Mat4<T>::IsIdentity() const
|
||||
{
|
||||
return (NumberEquals(m11, T(1.0)) && NumberEquals(m12, T(0.0)) && NumberEquals(m13, T(0.0)) && NumberEquals(m14, T(0.0)) &&
|
||||
NumberEquals(m21, T(0.0)) && NumberEquals(m22, T(1.0)) && NumberEquals(m23, T(0.0)) && NumberEquals(m24, T(0.0)) &&
|
||||
NumberEquals(m31, T(0.0)) && NumberEquals(m32, T(0.0)) && NumberEquals(m33, T(1.0)) && NumberEquals(m34, T(0.0)) &&
|
||||
NumberEquals(m41, T(0.0)) && NumberEquals(m42, T(0.0)) && NumberEquals(m43, T(0.0)) && NumberEquals(m44, T(1.0)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::SetRotation(const Quat<T>& rotation)
|
||||
{
|
||||
T qw = rotation.w;
|
||||
T qx = rotation.x;
|
||||
T qy = rotation.y;
|
||||
T qz = rotation.z;
|
||||
|
||||
T qx2 = qx * qx;
|
||||
T qy2 = qy * qy;
|
||||
T qz2 = qz * qz;
|
||||
|
||||
m11 = T(1.0) - T(2.0) * qy2 - T(2.0) * qz2;
|
||||
m21 = T(2.0) * qx * qy - T(2.0) * qz * qw;
|
||||
m31 = T(2.0) * qx * qz + T(2.0) * qy * qw;
|
||||
|
||||
m12 = T(2.0) * qx * qy + T(2.0) * qz * qw;
|
||||
m22 = T(1.0) - T(2.0) * qx2 - T(2.0) * qz2;
|
||||
m32 = T(2.0) * qy * qz - T(2.0) * qx * qw;
|
||||
|
||||
m13 = T(2.0) * qx * qz - T(2.0) * qy * qw;
|
||||
m23 = T(2.0) * qy * qz + T(2.0) * qx * qw;
|
||||
m33 = T(1.0) - T(2.0) * qx2 - T(2.0) * qy2;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::SetScale(const Vec3<T>& scale)
|
||||
{
|
||||
m11 = scale.x;
|
||||
m22 = scale.y;
|
||||
m33 = scale.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::SetTranslation(const Vec3<T>& translation)
|
||||
{
|
||||
m41 = translation.x;
|
||||
m42 = translation.y;
|
||||
m43 = translation.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string Mat4<T>::ToString() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << *this;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Mat4<T>::Transform(const Vec2<T>& vector, T z, T w) const
|
||||
{
|
||||
return Vec2<T>(m11 * vector.x + m21 * vector.y + m31 * z + m41 * w,
|
||||
m12 * vector.x + m22 * vector.y + m32 * z + m42 * w);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Mat4<T>::Transform(const Vec3<T>& vector, T w) const
|
||||
{
|
||||
return Vec3<T>(m11 * vector.x + m21 * vector.y + m31 * vector.z + m41 * w,
|
||||
m12 * vector.x + m22 * vector.y + m32 * vector.z + m42 * w,
|
||||
m13 * vector.x + m23 * vector.y + m33 * vector.z + m43 * w);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Mat4<T>::Transform(const Vec4<T>& vector) const
|
||||
{
|
||||
return Vec4<T>(m11 * vector.x + m21 * vector.y + m31 * vector.z + m41 * vector.w,
|
||||
m12 * vector.x + m22 * vector.y + m32 * vector.z + m42 * vector.w,
|
||||
m13 * vector.x + m23 * vector.y + m33 * vector.z + m43 * vector.w,
|
||||
m14 * vector.x + m24 * vector.y + m34 * vector.z + m44 * vector.w);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::Transpose()
|
||||
{
|
||||
std::swap(m12, m21);
|
||||
std::swap(m13, m31);
|
||||
std::swap(m14, m41);
|
||||
std::swap(m23, m32);
|
||||
std::swap(m24, m42);
|
||||
std::swap(m34, m43);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T& Mat4<T>::operator()(std::size_t x, std::size_t y)
|
||||
{
|
||||
Assert(x <= 3, "index out of range");
|
||||
Assert(y <= 3, "index out of range");
|
||||
|
||||
return (&m11)[y*4 + x];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr const T& Mat4<T>::operator()(std::size_t x, std::size_t y) const
|
||||
{
|
||||
Assert(x <= 3, "index out of range");
|
||||
Assert(y <= 3, "index out of range");
|
||||
|
||||
return (&m11)[y*4+x];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T& Mat4<T>::operator[](std::size_t i)
|
||||
{
|
||||
Assert(i <= 16, "index out of range");
|
||||
|
||||
return (&m11)[i];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr const T& Mat4<T>::operator[](std::size_t i) const
|
||||
{
|
||||
Assert(i <= 16, "index out of range");
|
||||
|
||||
return (&m11)[i];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::operator*(const Mat4& matrix) const
|
||||
{
|
||||
Mat4 result(*this);
|
||||
return result.Concatenate(matrix);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Mat4<T>::operator*(const Vec2<T>& vector) const
|
||||
{
|
||||
return Transform(vector);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Mat4<T>::operator*(const Vec3<T>& vector) const
|
||||
{
|
||||
return Transform(vector);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Mat4<T>::operator*(const Vec4<T>& vector) const
|
||||
{
|
||||
return Transform(vector);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::operator*(T scalar) const
|
||||
{
|
||||
Mat4 mat;
|
||||
for(unsigned int i = 0; i < 16; ++i)
|
||||
mat[i] = (&m11)[i] * scalar;
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::operator*=(const Mat4& matrix)
|
||||
{
|
||||
Concatenate(matrix);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T>& Mat4<T>::operator*=(T scalar)
|
||||
{
|
||||
for(unsigned int i = 0; i < 16; ++i)
|
||||
(&m11)[i] *= scalar;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Mat4<T>::operator==(const Mat4& mat) const
|
||||
{
|
||||
for(unsigned int i = 0; i < 16; ++i)
|
||||
if((&m11)[i] != (&mat.m11)[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Mat4<T>::operator!=(const Mat4& mat) const
|
||||
{
|
||||
return !operator==(mat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Mat4<T>::ApproxEqual(const Mat4& lhs, const Mat4& rhs, T maxDifference)
|
||||
{
|
||||
return lhs.ApproxEqual(rhs, maxDifference);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::Concatenate(const Mat4& left, const Mat4& right)
|
||||
{
|
||||
Mat4 matrix(left); // Copy of left-hand side matrix
|
||||
matrix.Concatenate(right); // Concatenation with right-hand side
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::ConcatenateTransform(const Mat4& left, const Mat4& right)
|
||||
{
|
||||
Mat4 matrix(left); // Copy of left-hand side matrix
|
||||
matrix.ConcatenateTransform(right); // Affine concatenation with right-hand side
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::Identity()
|
||||
{
|
||||
return Mat4(
|
||||
T(1.0), T(0.0), T(0.0), T(0.0),
|
||||
T(0.0), T(1.0), T(0.0), T(0.0),
|
||||
T(0.0), T(0.0), T(1.0), T(0.0),
|
||||
T(0.0), T(0.0), T(0.0), T(1.0)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::LookAt(const Vec3<T>& eye, const Vec3<T>& target, const Vec3<T>& up)
|
||||
{
|
||||
Vec3<T> f = Vec3<T>::Normalize(target - eye);
|
||||
Vec3<T> s = Vec3<T>::Normalize(f.CrossProduct(up));
|
||||
Vec3<T> u = s.CrossProduct(f);
|
||||
|
||||
return Mat4(
|
||||
s.x, u.x, -f.x, T(0.0),
|
||||
s.y, u.y, -f.y, T(0.0),
|
||||
s.z, u.z, -f.z, T(0.0),
|
||||
-s.DotProduct(eye), -u.DotProduct(eye), f.DotProduct(eye), T(1.0)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::Ortho(T left, T right, T top, T bottom, T zNear, T zFar)
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb204942(v=vs.85).aspx
|
||||
return Mat4(
|
||||
T(2.0) / (right - left), T(0.0), T(0.0), T(0.0),
|
||||
T(0.0), T(2.0) / (top - bottom), T(0.0), T(0.0),
|
||||
T(0.0), T(0.0), T(1.0) / (zNear - zFar), T(0.0),
|
||||
(left + right) / (left - right), (top + bottom) / (bottom - top), zNear / (zNear - zFar), T(1.0)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Mat4<T> Mat4<T>::Perspective(RadianAngle<T> angle, T ratio, T zNear, T zFar)
|
||||
{
|
||||
angle /= T(2.0);
|
||||
|
||||
T yScale = std::abs(angle.GetTan());
|
||||
|
||||
return Mat4(
|
||||
T(1.0) / (ratio * yScale), T(0.0), T(0.0), T(0.0),
|
||||
T(0.0), T(-1.0) / (yScale), T(0.0), T(0.0),
|
||||
T(0.0), T(0.0), zFar / (zNear - zFar), T(-1.0),
|
||||
T(0.0), T(0.0), -(zNear * zFar) / (zFar - zNear), T(0.0)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::Rotate(const Quat<T>& rotation)
|
||||
{
|
||||
Mat4 matrix = Mat4::Identity();
|
||||
matrix.SetRotation(rotation);
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::Scale(const Vec3<T>& scale)
|
||||
{
|
||||
return Mat4(
|
||||
scale.x, T(0.0), T(0.0), T(0.0),
|
||||
T(0.0), scale.y, T(0.0), T(0.0),
|
||||
T(0.0), T(0.0), scale.z, T(0.0),
|
||||
T(0.0), T(0.0), T(0.0), T(1.0)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::Translate(const Vec3<T>& translation)
|
||||
{
|
||||
return Mat4(
|
||||
T(1.0), T(0.0), T(0.0), T(0.0),
|
||||
T(0.0), T(1.0), T(0.0), T(0.0),
|
||||
T(0.0), T(0.0), T(1.0), T(0.0),
|
||||
translation.x, translation.y, translation.z, T(1.0)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::Transform(const Vec3<T>& translation, const Quat<T>& rotation)
|
||||
{
|
||||
Mat4 mat = Mat4f::Identity();
|
||||
mat.SetRotation(rotation);
|
||||
mat.SetTranslation(translation);
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::Transform(const Vec3<T>& translation, const Quat<T>& rotation, const Vec3<T>& scale)
|
||||
{
|
||||
Mat4 mat = Transform(translation, rotation);
|
||||
mat.ApplyScale(scale);
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::TransformInverse(const Vec3<T>& translation, const Quat<T>& rotation)
|
||||
{
|
||||
// A view matrix must apply an inverse transformation of the 'world' matrix
|
||||
Quat<T> invRot = rotation.GetConjugate(); // Inverse of the rotation
|
||||
|
||||
return Transform(-(invRot * translation), invRot);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::TransformInverse(const Vec3<T>& translation, const Quat<T>& rotation, const Vec3<T>& scale)
|
||||
{
|
||||
return TransformInverse(translation, rotation).ApplyScale(T(1.0) / scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> Mat4<T>::Zero()
|
||||
{
|
||||
return Mat4(
|
||||
T(0.0), T(0.0), T(0.0), T(0.0),
|
||||
T(0.0), T(0.0), T(0.0), T(0.0),
|
||||
T(0.0), T(0.0), T(0.0), T(0.0),
|
||||
T(0.0), T(0.0), T(0.0), T(0.0)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const Mat4<T>& matrix)
|
||||
{
|
||||
return out << "Mat4(" << matrix.m11 << ", " << matrix.m12 << ", " << matrix.m13 << ", " << matrix.m14 << ",\n"
|
||||
<< " " << matrix.m21 << ", " << matrix.m22 << ", " << matrix.m23 << ", " << matrix.m24 << ",\n"
|
||||
<< " " << matrix.m31 << ", " << matrix.m32 << ", " << matrix.m33 << ", " << matrix.m34 << ",\n"
|
||||
<< " " << matrix.m41 << ", " << matrix.m42 << ", " << matrix.m43 << ", " << matrix.m44 << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Mat4<T> operator*(T scale, const Mat4<T>& matrix)
|
||||
{
|
||||
return matrix * scale;
|
||||
}
|
||||
}
|
||||
26
Runtime/Includes/Maths/MathsUtils.h
git.filemode.normal_file
26
Runtime/Includes/Maths/MathsUtils.h
git.filemode.normal_file
@@ -0,0 +1,26 @@
|
||||
#ifndef __SCOP_MATHS_UTILS__
|
||||
#define __SCOP_MATHS_UTILS__
|
||||
|
||||
#include <concepts>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T>
|
||||
[[nodiscard]] constexpr T Mod(T x, T y) noexcept;
|
||||
|
||||
template<std::floating_point T>
|
||||
[[nodiscard]] constexpr T DegreeToRadian(T degrees) noexcept;
|
||||
|
||||
template<std::floating_point T>
|
||||
[[nodiscard]] constexpr T RadianToDegree(T radians) noexcept;
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] constexpr T Clamp(T value, T min, T max) noexcept;
|
||||
|
||||
template<typename T, typename T2>
|
||||
[[nodiscard]] constexpr T Lerp(const T& from, const T& to, const T2& interpolation) noexcept;
|
||||
}
|
||||
|
||||
#include <Maths/MathsUtils.inl>
|
||||
|
||||
#endif
|
||||
47
Runtime/Includes/Maths/MathsUtils.inl
git.filemode.normal_file
47
Runtime/Includes/Maths/MathsUtils.inl
git.filemode.normal_file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include <Maths/MathsUtils.h>
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
#include <Maths/Constants.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T>
|
||||
[[nodiscard]] constexpr T Mod(T x, T y) noexcept
|
||||
{
|
||||
if constexpr(std::is_floating_point_v<T>)
|
||||
{
|
||||
if(!std::is_constant_evaluated())
|
||||
return x - static_cast<long long>(x / y) * y;
|
||||
else
|
||||
return std::fmod(x, y);
|
||||
}
|
||||
return x % y;
|
||||
}
|
||||
|
||||
template<std::floating_point T>
|
||||
[[nodiscard]] constexpr T DegreeToRadian(T degrees) noexcept
|
||||
{
|
||||
return degrees * (Pi<T>() / T(180.0));
|
||||
}
|
||||
|
||||
template<std::floating_point T>
|
||||
[[nodiscard]] constexpr T RadianToDegree(T radians) noexcept
|
||||
{
|
||||
return radians * (T(180.0) / Pi<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] constexpr T Clamp(T value, T min, T max) noexcept
|
||||
{
|
||||
return std::max(std::min(value, max), min);
|
||||
}
|
||||
|
||||
template<typename T, typename T2>
|
||||
[[nodiscard]] constexpr T Lerp(const T& from, const T& to, const T2& interpolation) noexcept
|
||||
{
|
||||
return static_cast<T>(from + interpolation * (to - from));
|
||||
}
|
||||
}
|
||||
91
Runtime/Includes/Maths/Quaternions.h
git.filemode.normal_file
91
Runtime/Includes/Maths/Quaternions.h
git.filemode.normal_file
@@ -0,0 +1,91 @@
|
||||
#ifndef __SCOP_QUATERNIONS__
|
||||
#define __SCOP_QUATERNIONS__
|
||||
|
||||
#include <Maths/Angles.h>
|
||||
#include <Maths/Vec3.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T>
|
||||
struct Quat
|
||||
{
|
||||
T w, x, y, z;
|
||||
|
||||
constexpr Quat() = default;
|
||||
constexpr Quat(T W, T X, T Y, T Z);
|
||||
template<AngleUnit Unit> Quat(const Angle<Unit, T>& angle);
|
||||
Quat(const EulerAngles<T>& angles);
|
||||
constexpr Quat(RadianAngle<T> angle, const Vec3<T>& axis);
|
||||
constexpr Quat(const T quat[4]);
|
||||
template<typename U> constexpr explicit Quat(const Quat<U>& quat);
|
||||
constexpr Quat(const Quat&) = default;
|
||||
constexpr Quat(Quat&&) = default;
|
||||
~Quat() = default;
|
||||
|
||||
RadianAngle<T> AngleBetween(const Quat& vec) const;
|
||||
constexpr bool ApproxEqual(const Quat& quat, T maxDifference = std::numeric_limits<T>::epsilon()) const;
|
||||
|
||||
Quat& ComputeW();
|
||||
constexpr Quat& Conjugate();
|
||||
|
||||
constexpr T DotProduct(const Quat& vec) const;
|
||||
|
||||
constexpr Quat GetConjugate() const;
|
||||
Quat GetInverse() const;
|
||||
Quat GetNormal(T* length = nullptr) const;
|
||||
|
||||
Quat& Inverse();
|
||||
|
||||
T Magnitude() const;
|
||||
|
||||
Quat& Normalize(T* length = nullptr);
|
||||
|
||||
constexpr T SquaredMagnitude() const;
|
||||
|
||||
RadianAngle<T> To2DAngle() const;
|
||||
EulerAngles<T> ToEulerAngles() const;
|
||||
std::string ToString() const;
|
||||
|
||||
constexpr Quat& operator=(const Quat& quat) = default;
|
||||
constexpr Quat& operator=(Quat&&) = default;
|
||||
|
||||
constexpr Quat operator+(const Quat& quat) const;
|
||||
constexpr Quat operator*(const Quat& quat) const;
|
||||
constexpr Vec3<T> operator*(const Vec3<T>& vec) const;
|
||||
constexpr Quat operator*(T scale) const;
|
||||
constexpr Quat operator/(const Quat& quat) const;
|
||||
|
||||
constexpr Quat& operator+=(const Quat& quat);
|
||||
constexpr Quat& operator*=(const Quat& quat);
|
||||
constexpr Quat& operator*=(T scale);
|
||||
constexpr Quat& operator/=(const Quat& quat);
|
||||
|
||||
constexpr bool operator==(const Quat& quat) const;
|
||||
constexpr bool operator!=(const Quat& quat) const;
|
||||
constexpr bool operator<(const Quat& quat) const;
|
||||
constexpr bool operator<=(const Quat& quat) const;
|
||||
constexpr bool operator>(const Quat& quat) const;
|
||||
constexpr bool operator>=(const Quat& quat) const;
|
||||
|
||||
static RadianAngle<T> AngleBetween(const Quat& lhs, const Quat& rhs);
|
||||
static constexpr bool ApproxEqual(const Quat& lhs, const Quat& rhs, T maxDifference = std::numeric_limits<T>::epsilon());
|
||||
static constexpr Quat Identity();
|
||||
static constexpr Quat Lerp(const Quat& from, const Quat& to, T interpolation);
|
||||
static Quat LookAt(const Vec3<T>& forward, const Vec3<T>& up);
|
||||
static Quat Normalize(const Quat& quat, T* length = nullptr);
|
||||
static Quat RotationBetween(const Vec3<T>& from, const Vec3<T>& to);
|
||||
static Quat RotateTowards(const Quat& from, const Quat& to, RadianAngle<T> maxRotation);
|
||||
static Quat Mirror(Quat quat, const Vec3<T>& axis);
|
||||
static Quat Slerp(const Quat& from, const Quat& to, T interpolation);
|
||||
static constexpr Quat Zero();
|
||||
};
|
||||
|
||||
using Quatd = Quat<double>;
|
||||
using Quatf = Quat<float>;
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const Quat<T>& quat);
|
||||
}
|
||||
|
||||
#include <Maths/Quaternions.inl>
|
||||
|
||||
#endif
|
||||
508
Runtime/Includes/Maths/Quaternions.inl
git.filemode.normal_file
508
Runtime/Includes/Maths/Quaternions.inl
git.filemode.normal_file
@@ -0,0 +1,508 @@
|
||||
#pragma once
|
||||
#include <Maths/Quaternions.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T>
|
||||
constexpr Quat<T>::Quat(T W, T X, T Y, T Z) : w(W), x(X), y(Y), z(Z)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
template<AngleUnit Unit>
|
||||
Quat<T>::Quat(const Angle<Unit, T>& angle) : Quat(angle.ToQuat())
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
Quat<T>::Quat(const EulerAngles<T>& angles) : Quat(angles.ToQuat())
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T>::Quat(RadianAngle<T> angle, const Vec3<T>& axis)
|
||||
{
|
||||
angle /= T(2.0);
|
||||
|
||||
Vec3<T> normalizedAxis = axis.GetNormal();
|
||||
|
||||
auto sincos = angle.GetSinCos();
|
||||
|
||||
w = sincos.second;
|
||||
x = normalizedAxis.x * sincos.first;
|
||||
y = normalizedAxis.y * sincos.first;
|
||||
z = normalizedAxis.z * sincos.first;
|
||||
|
||||
Normalize();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T>::Quat(const T quat[4]) : w(quat[0]), x(quat[1]), y(quat[2]), z(quat[3])
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr Quat<T>::Quat(const Quat<U>& quat) : w(static_cast<T>(quat.w)), x(static_cast<T>(quat.x)), y(static_cast<T>(quat.y)), z(static_cast<T>(quat.z))
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
RadianAngle<T> Quat<T>::AngleBetween(const Quat& quat) const
|
||||
{
|
||||
T alpha = Vec3<T>::DotProduct(Vec3<T>(x, y, z), Vec3<T>(quat.x, quat.y, quat.z));
|
||||
return std::acos(Scop::Clamp(alpha, T(-1.0), T(1.0)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Quat<T>::ApproxEqual(const Quat& quat, T maxDifference) const
|
||||
{
|
||||
return NumberEquals(w, quat.w, maxDifference) &&
|
||||
NumberEquals(x, quat.x, maxDifference) &&
|
||||
NumberEquals(y, quat.y, maxDifference) &&
|
||||
NumberEquals(z, quat.z, maxDifference);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T>& Quat<T>::ComputeW()
|
||||
{
|
||||
T t = T(1.0) - SquaredMagnitude();
|
||||
|
||||
if(t < T(0.0))
|
||||
w = T(0.0);
|
||||
else
|
||||
w = -std::sqrt(t);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T>& Quat<T>::Conjugate()
|
||||
{
|
||||
x = -x;
|
||||
y = -y;
|
||||
z = -z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Quat<T>::DotProduct(const Quat& quat) const
|
||||
{
|
||||
return w * quat.w + x * quat.x + y * quat.y + z * quat.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T> Quat<T>::GetConjugate() const
|
||||
{
|
||||
Quat<T> quat(*this);
|
||||
quat.Conjugate();
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T> Quat<T>::GetInverse() const
|
||||
{
|
||||
Quat<T> quat(*this);
|
||||
quat.Inverse();
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T> Quat<T>::GetNormal(T* length) const
|
||||
{
|
||||
Quat<T> quat(*this);
|
||||
quat.Normalize(length);
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T>& Quat<T>::Inverse()
|
||||
{
|
||||
T norm = SquaredMagnitude();
|
||||
if(norm > T(0.0))
|
||||
{
|
||||
T invNorm = T(1.0) / std::sqrt(norm);
|
||||
|
||||
w *= invNorm;
|
||||
x *= -invNorm;
|
||||
y *= -invNorm;
|
||||
z *= -invNorm;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Quat<T>::Magnitude() const
|
||||
{
|
||||
return std::sqrt(SquaredMagnitude());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T>& Quat<T>::Normalize(T* length)
|
||||
{
|
||||
T norm = std::sqrt(SquaredMagnitude());
|
||||
if(norm > T(0.0))
|
||||
{
|
||||
T invNorm = T(1.0) / norm;
|
||||
w *= invNorm;
|
||||
x *= invNorm;
|
||||
y *= invNorm;
|
||||
z *= invNorm;
|
||||
}
|
||||
|
||||
if(length)
|
||||
*length = norm;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Quat<T>::SquaredMagnitude() const
|
||||
{
|
||||
return w * w + x * x + y * y + z * z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RadianAngle<T> Quat<T>::To2DAngle() const
|
||||
{
|
||||
T siny_cosp = T(2.0) * (w * z + x * y);
|
||||
T cosy_cosp = T(1.0) - T(2.0) * (y * y + z * z);
|
||||
|
||||
return std::atan2(siny_cosp, cosy_cosp);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
EulerAngles<T> Quat<T>::ToEulerAngles() const
|
||||
{
|
||||
T test = x * y + z * w;
|
||||
if(test > T(0.499))
|
||||
// singularity at north pole
|
||||
return EulerAngles<T>(DegreeAngle<T>(T(0.0)), RadianAngle<T>(T(2.0) * std::atan2(x, w)), DegreeAngle<T>(T(90.0)));
|
||||
|
||||
if(test < T(-0.499))
|
||||
// singularity at south pole
|
||||
return EulerAngles<T>(DegreeAngle<T>(T(0.0)), RadianAngle<T>(T(-2.0) * std::atan2(x, w)), DegreeAngle<T>(T(-90.0)));
|
||||
|
||||
return EulerAngles<T>(RadianAngle<T>(std::atan2(T(2.0) * x * w - T(2.0) * y * z, T(1.0) - T(2.0) * x * x - T(2.0) * z * z)),
|
||||
RadianAngle<T>(std::atan2(T(2.0) * y * w - T(2.0) * x * z, T(1.0) - T(2.0) * y * y - T(2.0) * z * z)),
|
||||
RadianAngle<T>(std::asin(T(2.0) * test)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string Quat<T>::ToString() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << *this;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T> Quat<T>::operator+(const Quat& quat) const
|
||||
{
|
||||
Quat result;
|
||||
result.w = w + quat.w;
|
||||
result.x = x + quat.x;
|
||||
result.y = y + quat.y;
|
||||
result.z = z + quat.z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T> Quat<T>::operator*(const Quat& quat) const
|
||||
{
|
||||
Quat result;
|
||||
result.w = w * quat.w - x * quat.x - y * quat.y - z * quat.z;
|
||||
result.x = w * quat.x + x * quat.w + y * quat.z - z * quat.y;
|
||||
result.y = w * quat.y + y * quat.w + z * quat.x - x * quat.z;
|
||||
result.z = w * quat.z + z * quat.w + x * quat.y - y * quat.x;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Quat<T>::operator*(const Vec3<T>& vec) const
|
||||
{
|
||||
Vec3<T> quatVec(x, y, z);
|
||||
Vec3<T> uv = quatVec.CrossProduct(vec);
|
||||
Vec3<T> uuv = quatVec.CrossProduct(uv);
|
||||
uv *= T(2.0) * w;
|
||||
uuv *= T(2.0);
|
||||
|
||||
return vec + uv + uuv;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T> Quat<T>::operator*(T scale) const
|
||||
{
|
||||
return Quat(w * scale,
|
||||
x * scale,
|
||||
y * scale,
|
||||
z * scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T> Quat<T>::operator/(const Quat& quat) const
|
||||
{
|
||||
return quat.GetConjugate() * (*this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T>& Quat<T>::operator+=(const Quat& quat)
|
||||
{
|
||||
return operator=(operator+(quat));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T>& Quat<T>::operator*=(const Quat& quat)
|
||||
{
|
||||
return operator=(operator*(quat));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T>& Quat<T>::operator*=(T scale)
|
||||
{
|
||||
return operator=(operator*(scale));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T>& Quat<T>::operator/=(const Quat& quat)
|
||||
{
|
||||
return operator=(operator/(quat));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Quat<T>::operator==(const Quat& quat) const
|
||||
{
|
||||
return w == quat.w && x == quat.x && y == quat.y && z == quat.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Quat<T>::operator!=(const Quat& quat) const
|
||||
{
|
||||
return !operator==(quat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Quat<T>::operator<(const Quat& quat) const
|
||||
{
|
||||
if(w != quat.w)
|
||||
return w < quat.w;
|
||||
|
||||
if(x != quat.x)
|
||||
return x < quat.x;
|
||||
|
||||
if(y != quat.y)
|
||||
return y < quat.y;
|
||||
|
||||
if(z != quat.z)
|
||||
return z < quat.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Quat<T>::operator<=(const Quat& quat) const
|
||||
{
|
||||
if(w != quat.w)
|
||||
return w < quat.w;
|
||||
|
||||
if(x != quat.x)
|
||||
return x < quat.x;
|
||||
|
||||
if(y != quat.y)
|
||||
return y < quat.y;
|
||||
|
||||
if(z != quat.z)
|
||||
return z <= quat.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Quat<T>::operator>(const Quat& quat) const
|
||||
{
|
||||
if(w != quat.w)
|
||||
return w > quat.w;
|
||||
|
||||
if(x != quat.x)
|
||||
return x > quat.x;
|
||||
|
||||
if(y != quat.y)
|
||||
return y > quat.y;
|
||||
|
||||
if(z != quat.z)
|
||||
return z > quat.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Quat<T>::operator>=(const Quat& quat) const
|
||||
{
|
||||
if(w != quat.w)
|
||||
return w > quat.w;
|
||||
|
||||
if(x != quat.x)
|
||||
return x > quat.x;
|
||||
|
||||
if(y != quat.y)
|
||||
return y > quat.y;
|
||||
|
||||
if(z != quat.z)
|
||||
return z >= quat.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
RadianAngle<T> Quat<T>::AngleBetween(const Quat& lhs, const Quat& rhs)
|
||||
{
|
||||
return lhs.AngleBetween(rhs);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Quat<T>::ApproxEqual(const Quat& lhs, const Quat& rhs, T maxDifference)
|
||||
{
|
||||
return lhs.ApproxEqual(rhs, maxDifference);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T> Quat<T>::Identity()
|
||||
{
|
||||
return Quat(1, 0, 0, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T> Quat<T>::Lerp(const Quat& from, const Quat& to, T interpolation)
|
||||
{
|
||||
Quat interpolated;
|
||||
interpolated.w = Scop::Lerp(from.w, to.w, interpolation);
|
||||
interpolated.x = Scop::Lerp(from.x, to.x, interpolation);
|
||||
interpolated.y = Scop::Lerp(from.y, to.y, interpolation);
|
||||
interpolated.z = Scop::Lerp(from.z, to.z, interpolation);
|
||||
|
||||
return interpolated;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T> Quat<T>::LookAt(const Vec3<T>& forward, const Vec3<T>& up)
|
||||
{
|
||||
// From https://gamedev.stackexchange.com/questions/53129/quaternion-look-at-with-up-vector
|
||||
Vec3<T> forward_w = Vec3<T>::Forward();
|
||||
Vec3<T> axis = Vec3<T>::CrossProduct(forward, forward_w);
|
||||
RadianAngle<T> angle = std::acos(Vec3<T>::DotProduct(forward, forward_w));
|
||||
|
||||
Vec3<T> third = Vec3<T>::CrossProduct(axis, forward_w);
|
||||
if(Vec3<T>::DotProduct(third, forward) < 0)
|
||||
angle = -angle;
|
||||
|
||||
Quat<T> q1 = Quat(angle, axis);
|
||||
|
||||
Vec3<T> up_l = q1 * up;
|
||||
Vec3<T> right = Vec3<T>::Normalize(Vec3<T>::CrossProduct(forward, up));
|
||||
Vec3<T> up_w = Vec3<T>::Normalize(Vec3<T>::CrossProduct(right, forward));
|
||||
|
||||
Vec3<T> axis2 = Vec3<T>::CrossProduct(up_l, up_w);
|
||||
RadianAngle<T> angle2 = std::acos(Vec3<T>::DotProduct(forward, forward_w));
|
||||
|
||||
Quat<T> q2 = Quat(angle2, axis2);
|
||||
|
||||
return q2 * q1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T> Quat<T>::Normalize(const Quat& quat, T* length)
|
||||
{
|
||||
return quat.GetNormal(length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T> Quat<T>::RotationBetween(const Vec3<T>& from, const Vec3<T>& to)
|
||||
{
|
||||
T dot = from.DotProduct(to);
|
||||
if(dot < T(-0.999999))
|
||||
{
|
||||
Vec3<T> crossProduct;
|
||||
if(from.DotProduct(Vec3<T>::UnitX()) < T(0.999999))
|
||||
crossProduct = Vec3<T>::UnitX().CrossProduct(from);
|
||||
else
|
||||
crossProduct = Vec3<T>::UnitY().CrossProduct(from);
|
||||
|
||||
crossProduct.Normalize();
|
||||
return Quat(Pi<T>(), crossProduct);
|
||||
}
|
||||
else if(dot > T(0.999999))
|
||||
return Quat::Identity();
|
||||
else
|
||||
{
|
||||
T norm = std::sqrt(from.GetSquaredLength() * to.GetSquaredLength());
|
||||
Vec3<T> crossProduct = from.CrossProduct(to);
|
||||
|
||||
return Quat(norm + dot, crossProduct.x, crossProduct.y, crossProduct.z).GetNormal();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T> Quat<T>::RotateTowards(const Quat& from, const Quat& to, RadianAngle<T> maxRotation)
|
||||
{
|
||||
RadianAngle<T> rotationBetween = AngleBetween(from, to);
|
||||
if(rotationBetween < maxRotation)
|
||||
return to;
|
||||
|
||||
return Slerp(from, to, std::min(maxRotation.value / rotationBetween.value), 1.f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T> Quat<T>::Mirror(Quat quat, const Vec3<T>& axis)
|
||||
{
|
||||
T x = std::copysign(T(1.0), axis.x);
|
||||
T y = std::copysign(T(1.0), axis.y);
|
||||
T z = std::copysign(T(1.0), axis.z);
|
||||
|
||||
quat.x = y * z * quat.x;
|
||||
quat.y = x * z * quat.y;
|
||||
quat.z = x * y * quat.z;
|
||||
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Quat<T> Quat<T>::Slerp(const Quat& from, const Quat& to, T interpolation)
|
||||
{
|
||||
Quat q;
|
||||
|
||||
T cosOmega = from.DotProduct(to);
|
||||
if(cosOmega < T(0.0))
|
||||
{
|
||||
// We invert everything
|
||||
q = Quat(-to.w, -to.x, -to.y, -to.z);
|
||||
cosOmega = -cosOmega;
|
||||
}
|
||||
else
|
||||
q = Quat(to);
|
||||
|
||||
T k0, k1;
|
||||
if(cosOmega > T(0.9999))
|
||||
{
|
||||
// Linear interpolation to avoid division by zero
|
||||
k0 = T(1.0) - interpolation;
|
||||
k1 = interpolation;
|
||||
}
|
||||
else
|
||||
{
|
||||
T sinOmega = std::sqrt(T(1.0) - cosOmega*cosOmega);
|
||||
T omega = std::atan2(sinOmega, cosOmega);
|
||||
|
||||
// To avoid two divisions
|
||||
sinOmega = T(1.0)/sinOmega;
|
||||
|
||||
k0 = std::sin((T(1.0) - interpolation) * omega) * sinOmega;
|
||||
k1 = std::sin(interpolation*omega) * sinOmega;
|
||||
}
|
||||
|
||||
Quat result(k0 * from.w, k0 * from.x, k0 * from.y, k0 * from.z);
|
||||
return result += q * k1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Quat<T> Quat<T>::Zero()
|
||||
{
|
||||
return Quat(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const Quat<T>& quat)
|
||||
{
|
||||
return out << "Quat(" << quat.w << " | " << quat.x << ", " << quat.y << ", " << quat.z << ')';
|
||||
}
|
||||
}
|
||||
116
Runtime/Includes/Maths/Vec2.h
git.filemode.executable_file
116
Runtime/Includes/Maths/Vec2.h
git.filemode.executable_file
@@ -0,0 +1,116 @@
|
||||
#ifndef __SCOP_VEC2__
|
||||
#define __SCOP_VEC2__
|
||||
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
|
||||
#include <Core/Logs.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template <typename T> class Vec3;
|
||||
template <typename T> class Vec4;
|
||||
|
||||
template <typename T>
|
||||
struct Vec2
|
||||
{
|
||||
T x;
|
||||
T y;
|
||||
|
||||
constexpr Vec2() = default;
|
||||
constexpr Vec2(T X, T Y);
|
||||
constexpr explicit Vec2(T scale);
|
||||
template<typename U> constexpr explicit Vec2(const Vec2<U>& vec);
|
||||
constexpr Vec2(const Vec2&) = default;
|
||||
constexpr Vec2(Vec2&&) = default;
|
||||
constexpr explicit Vec2(const Vec3<T>& vec);
|
||||
constexpr explicit Vec2(const Vec4<T>& vec);
|
||||
|
||||
T AbsDotProduct(const Vec2& vec) const;
|
||||
constexpr bool ApproxEqual(const Vec2& vec, T max_difference = std::numeric_limits<T>::epsilon()) const;
|
||||
|
||||
template<typename U = T> U Distance(const Vec2& vec) const;
|
||||
constexpr T DotProduct(const Vec2& vec) const;
|
||||
|
||||
template<typename U = T> T GetLength() const;
|
||||
Vec2 GetNormal(T* length = nullptr) const;
|
||||
constexpr T GetSquaredLength() const;
|
||||
|
||||
constexpr Vec2& Maximize(const Vec2& vec);
|
||||
constexpr Vec2& Minimize(const Vec2& vec);
|
||||
|
||||
Vec2& Normalize(T* length = nullptr);
|
||||
|
||||
constexpr T SquaredDistance(const Vec2& vec) const;
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
constexpr T& operator[](std::size_t i);
|
||||
constexpr T operator[](std::size_t i) const;
|
||||
|
||||
constexpr const Vec2& operator+() const;
|
||||
constexpr Vec2 operator-() const;
|
||||
|
||||
constexpr Vec2 operator+(const Vec2& vec) const;
|
||||
constexpr Vec2 operator-(const Vec2& vec) const;
|
||||
constexpr Vec2 operator*(const Vec2& vec) const;
|
||||
constexpr Vec2 operator*(T scale) const;
|
||||
constexpr Vec2 operator/(const Vec2& vec) const;
|
||||
constexpr Vec2 operator/(T scale) const;
|
||||
constexpr Vec2 operator%(const Vec2& vec) const;
|
||||
constexpr Vec2 operator%(T mod) const;
|
||||
|
||||
constexpr Vec2& operator=(const Vec2&) = default;
|
||||
constexpr Vec2& operator=(Vec2&&) = default;
|
||||
|
||||
constexpr Vec2& operator+=(const Vec2& vec);
|
||||
constexpr Vec2& operator-=(const Vec2& vec);
|
||||
constexpr Vec2& operator*=(const Vec2& vec);
|
||||
constexpr Vec2& operator*=(T scale);
|
||||
constexpr Vec2& operator/=(const Vec2& vec);
|
||||
constexpr Vec2& operator/=(T scale);
|
||||
constexpr Vec2& operator%=(const Vec2& vec);
|
||||
constexpr Vec2& operator%=(T mod);
|
||||
|
||||
constexpr bool operator==(const Vec2& vec) const;
|
||||
constexpr bool operator!=(const Vec2& vec) const;
|
||||
constexpr bool operator<(const Vec2& vec) const;
|
||||
constexpr bool operator<=(const Vec2& vec) const;
|
||||
constexpr bool operator>(const Vec2& vec) const;
|
||||
constexpr bool operator>=(const Vec2& vec) const;
|
||||
|
||||
static constexpr Vec2 Apply(T(*func)(T), const Vec2& vec);
|
||||
static constexpr bool ApproxEqual(const Vec2& lhs, const Vec2& rhs, T max_difference = std::numeric_limits<T>::epsilon());
|
||||
template<typename U = T> static U Distance(const Vec2& vec1, const Vec2& vec2);
|
||||
static constexpr T DotProduct(const Vec2& vec1, const Vec2& vec2);
|
||||
static constexpr Vec2 Lerp(const Vec2& from, const Vec2& to, T interpolation);
|
||||
static Vec2 Normalize(const Vec2& vec);
|
||||
static constexpr Vec2 Unit();
|
||||
static constexpr Vec2 UnitX();
|
||||
static constexpr Vec2 UnitY();
|
||||
static constexpr Vec2 Zero();
|
||||
|
||||
~Vec2() = default;
|
||||
};
|
||||
|
||||
using Vec2d = Vec2<double>;
|
||||
using Vec2f = Vec2<float>;
|
||||
using Vec2i = Vec2<int>;
|
||||
using Vec2ui = Vec2<unsigned int>;
|
||||
using Vec2i32 = Vec2<std::int32_t>;
|
||||
using Vec2i64 = Vec2<std::int64_t>;
|
||||
using Vec2ui32 = Vec2<std::uint32_t>;
|
||||
using Vec2ui64 = Vec2<std::uint64_t>;
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const Vec2<T>& vec);
|
||||
|
||||
template<typename T> constexpr Vec2<T> operator*(T scale, const Vec2<T>& vec);
|
||||
template<typename T> constexpr Vec2<T> operator/(T scale, const Vec2<T>& vec);
|
||||
template<typename T> constexpr Vec2<T> operator%(T mod, const Vec2<T>& vec);
|
||||
}
|
||||
|
||||
#include <Maths/Vec2.inl>
|
||||
|
||||
#endif
|
||||
388
Runtime/Includes/Maths/Vec2.inl
git.filemode.executable_file
388
Runtime/Includes/Maths/Vec2.inl
git.filemode.executable_file
@@ -0,0 +1,388 @@
|
||||
#pragma once
|
||||
|
||||
#include <Maths/Vec2.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T>
|
||||
constexpr Vec2<T>::Vec2(T X, T Y) : x(X), y(Y) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>::Vec2(T scale) : x(scale), y(scale) {}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr Vec2<T>::Vec2(const Vec2<U>& vec) : x(static_cast<T>(vec.x)), y(static_cast<T>(vec.y)) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>::Vec2(const Vec3<T>& vec) : x(vec.x), y(vec.y) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>::Vec2(const Vec4<T>& vec) : x(vec.x), y(vec.y) {}
|
||||
|
||||
template<typename T>
|
||||
T Vec2<T>::AbsDotProduct(const Vec2& vec) const
|
||||
{
|
||||
return std::abs(x * vec.x) + std::abs(y * vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec2<T>::ApproxEqual(const Vec2& vec, T maxDifference) const
|
||||
{
|
||||
return NumberEquals(x, vec.x, maxDifference) && NumberEquals(y, vec.y, maxDifference);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
U Vec2<T>::Distance(const Vec2& vec) const
|
||||
{
|
||||
return static_cast<U>(std::sqrt(SquaredDistance(vec)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec2<T>::DotProduct(const Vec2& vec) const
|
||||
{
|
||||
return x * vec.x + y * vec.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
T Vec2<T>::GetLength() const
|
||||
{
|
||||
return static_cast<U>(std::sqrt(static_cast<U>(GetSquaredLength())));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec2<T> Vec2<T>::GetNormal(T* length) const
|
||||
{
|
||||
Vec2 vec(*this);
|
||||
vec.Normalize(length);
|
||||
return vec;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec2<T>::GetSquaredLength() const
|
||||
{
|
||||
return x * x + y * y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>& Vec2<T>::Maximize(const Vec2& vec)
|
||||
{
|
||||
if(vec.x > x)
|
||||
x = vec.x;
|
||||
if(vec.y > y)
|
||||
y = vec.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>& Vec2<T>::Minimize(const Vec2& vec)
|
||||
{
|
||||
if(vec.x < x)
|
||||
x = vec.x;
|
||||
if(vec.y < y)
|
||||
y = vec.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec2<T>& Vec2<T>::Normalize(T* length)
|
||||
{
|
||||
T norm = GetLength();
|
||||
if(norm > T(0.0))
|
||||
{
|
||||
T invNorm = T(1.0) / norm;
|
||||
x *= invNorm;
|
||||
y *= invNorm;
|
||||
}
|
||||
if(length)
|
||||
*length = norm;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec2<T>::SquaredDistance(const Vec2& vec) const
|
||||
{
|
||||
return (*this - vec).GetSquaredLength();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string Vec2<T>::ToString() const
|
||||
{
|
||||
return "Vec2(" + std::to_string(x) + ", " + std::to_string(y) + ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T& Vec2<T>::operator[](std::size_t i)
|
||||
{
|
||||
Scop::Assert(i < 2, "index out of range");
|
||||
return *(&x + i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec2<T>::operator[](std::size_t i) const
|
||||
{
|
||||
Scop::Assert(i < 2, "index out of range");
|
||||
return *(&x + i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr const Vec2<T>& Vec2<T>::operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::operator-() const
|
||||
{
|
||||
return Vec2(-x, -y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::operator+(const Vec2& vec) const
|
||||
{
|
||||
return Vec2(x + vec.x, y + vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::operator-(const Vec2& vec) const
|
||||
{
|
||||
return Vec2(x - vec.x, y - vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::operator*(const Vec2& vec) const
|
||||
{
|
||||
return Vec2(x * vec.x, y * vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::operator*(T scale) const
|
||||
{
|
||||
return Vec2(x * scale, y * scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::operator/(const Vec2& vec) const
|
||||
{
|
||||
return Vec2(x / vec.x, y / vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::operator/(T scale) const
|
||||
{
|
||||
return Vec2(x / scale, y / scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::operator%(const Vec2& vec) const
|
||||
{
|
||||
return Vec2(Mod(x, vec.x), Mod(y, vec.y));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::operator%(T mod) const
|
||||
{
|
||||
return Vec2(Mod(x, mod), Mod(y, mod));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>& Vec2<T>::operator+=(const Vec2& vec)
|
||||
{
|
||||
x += vec.x;
|
||||
y += vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>& Vec2<T>::operator-=(const Vec2& vec)
|
||||
{
|
||||
x -= vec.x;
|
||||
y -= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>& Vec2<T>::operator*=(const Vec2& vec)
|
||||
{
|
||||
x *= vec.x;
|
||||
y *= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>& Vec2<T>::operator*=(T scale)
|
||||
{
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>& Vec2<T>::operator/=(const Vec2& vec)
|
||||
{
|
||||
x /= vec.x;
|
||||
y /= vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>& Vec2<T>::operator/=(T scale)
|
||||
{
|
||||
x /= scale;
|
||||
y /= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>& Vec2<T>::operator%=(const Vec2& vec)
|
||||
{
|
||||
x = Mod(x, vec.x);
|
||||
y = Mod(y, vec.y);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T>& Vec2<T>::operator%=(T value)
|
||||
{
|
||||
x = Mod(x, value);
|
||||
y = Mod(y, value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec2<T>::operator==(const Vec2& vec) const
|
||||
{
|
||||
return x == vec.x && y == vec.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec2<T>::operator!=(const Vec2& vec) const
|
||||
{
|
||||
return !operator==(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec2<T>::operator<(const Vec2& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x < vec.x;
|
||||
|
||||
return y < vec.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec2<T>::operator<=(const Vec2& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x < vec.x;
|
||||
|
||||
return y <= vec.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec2<T>::operator>(const Vec2& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x > vec.x;
|
||||
|
||||
return y > vec.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec2<T>::operator>=(const Vec2& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x > vec.x;
|
||||
|
||||
return y >= vec.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::Apply(T(*func)(T), const Vec2& vec)
|
||||
{
|
||||
return Vec2(func(vec.x), func(vec.y));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec2<T>::ApproxEqual(const Vec2& lhs, const Vec2& rhs, T maxDifference)
|
||||
{
|
||||
return lhs.ApproxEqual(rhs, maxDifference);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
U Vec2<T>::Distance(const Vec2& vec1, const Vec2& vec2)
|
||||
{
|
||||
return vec1.Distance<U>(vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec2<T>::DotProduct(const Vec2& vec1, const Vec2& vec2)
|
||||
{
|
||||
return vec1.DotProduct(vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec2<T> Vec2<T>::Normalize(const Vec2& vec)
|
||||
{
|
||||
return vec.GetNormal();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::Unit()
|
||||
{
|
||||
return Vec2(1, 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::UnitX()
|
||||
{
|
||||
return Vec2(1, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::UnitY()
|
||||
{
|
||||
return Vec2(0, 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> Vec2<T>::Zero()
|
||||
{
|
||||
return Vec2(0, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const Vec2<T>& vec)
|
||||
{
|
||||
return out << "Vec2(" << vec.x << ", " << vec.y << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> operator*(T scale, const Vec2<T>& vec)
|
||||
{
|
||||
return Vec2<T>(scale * vec.x, scale * vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> operator/(T scale, const Vec2<T>& vec)
|
||||
{
|
||||
return Vec2<T>(scale / vec.x, scale / vec.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec2<T> operator%(T mod, const Vec2<T>& vec)
|
||||
{
|
||||
return Vec2<T>(Mod(mod, vec.x), Mod(mod, vec.y));
|
||||
}
|
||||
}
|
||||
133
Runtime/Includes/Maths/Vec3.h
git.filemode.executable_file
133
Runtime/Includes/Maths/Vec3.h
git.filemode.executable_file
@@ -0,0 +1,133 @@
|
||||
#ifndef __SCOP_VEC3__
|
||||
#define __SCOP_VEC3__
|
||||
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
|
||||
#include <Core/Logs.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T> class Vec2;
|
||||
template<typename T> class Vec4;
|
||||
|
||||
template<typename T>
|
||||
struct Vec3
|
||||
{
|
||||
T x;
|
||||
T y;
|
||||
T z;
|
||||
|
||||
constexpr Vec3() = default;
|
||||
constexpr Vec3(T X, T Y, T Z);
|
||||
constexpr Vec3(T X, const Vec2<T>& vec);
|
||||
constexpr explicit Vec3(T scale);
|
||||
constexpr Vec3(const Vec2<T>& vec, T Z = 0.0);
|
||||
template<typename U> constexpr explicit Vec3(const Vec3<U>& vec);
|
||||
constexpr Vec3(const Vec3&) = default;
|
||||
constexpr Vec3(Vec3&&) = default;
|
||||
constexpr explicit Vec3(const Vec4<T>& vec);
|
||||
|
||||
T AbsDotProduct(const Vec3& vec) const;
|
||||
constexpr bool ApproxEqual(const Vec3& vec, T max_difference = std::numeric_limits<T>::epsilon()) const;
|
||||
|
||||
constexpr Vec3 CrossProduct(const Vec3& vec) const;
|
||||
|
||||
template<typename U = T> U Distance(const Vec3& vec) const;
|
||||
constexpr T DotProduct(const Vec3& vec) const;
|
||||
|
||||
Vec3 GetAbs() const;
|
||||
template<typename U = T> U GetLength() const;
|
||||
Vec3 GetNormal(T* length = nullptr) const;
|
||||
constexpr T GetSquaredLength() const;
|
||||
|
||||
constexpr Vec3& Maximize(const Vec3& vec);
|
||||
constexpr Vec3& Minimize(const Vec3& vec);
|
||||
|
||||
Vec3& Normalize(T* length = nullptr);
|
||||
|
||||
constexpr T SquaredDistance(const Vec3& vec) const;
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
constexpr T& operator[](std::size_t i);
|
||||
constexpr const T& operator[](std::size_t i) const;
|
||||
|
||||
constexpr const Vec3& operator+() const;
|
||||
constexpr Vec3 operator-() const;
|
||||
|
||||
constexpr Vec3 operator+(const Vec3& vec) const;
|
||||
constexpr Vec3 operator-(const Vec3& vec) const;
|
||||
constexpr Vec3 operator*(const Vec3& vec) const;
|
||||
constexpr Vec3 operator*(T scale) const;
|
||||
constexpr Vec3 operator/(const Vec3& vec) const;
|
||||
constexpr Vec3 operator/(T scale) const;
|
||||
constexpr Vec3 operator%(const Vec3& vec) const;
|
||||
constexpr Vec3 operator%(T mod) const;
|
||||
|
||||
constexpr Vec3& operator=(const Vec3&) = default;
|
||||
constexpr Vec3& operator=(Vec3&&) = default;
|
||||
|
||||
constexpr Vec3& operator+=(const Vec3& vec);
|
||||
constexpr Vec3& operator-=(const Vec3& vec);
|
||||
constexpr Vec3& operator*=(const Vec3& vec);
|
||||
constexpr Vec3& operator*=(T scale);
|
||||
constexpr Vec3& operator/=(const Vec3& vec);
|
||||
constexpr Vec3& operator/=(T scale);
|
||||
constexpr Vec3& operator%=(const Vec3& vec);
|
||||
constexpr Vec3& operator%=(T mod);
|
||||
|
||||
constexpr bool operator==(const Vec3& vec) const;
|
||||
constexpr bool operator!=(const Vec3& vec) const;
|
||||
constexpr bool operator<(const Vec3& vec) const;
|
||||
constexpr bool operator<=(const Vec3& vec) const;
|
||||
constexpr bool operator>(const Vec3& vec) const;
|
||||
constexpr bool operator>=(const Vec3& vec) const;
|
||||
|
||||
static constexpr Vec3 Apply(T(*func)(T), const Vec3& vec);
|
||||
static constexpr bool ApproxEqual(const Vec3& lhs, const Vec3& rhs, T max_difference = std::numeric_limits<T>::epsilon());
|
||||
static constexpr Vec3 Backward();
|
||||
static constexpr Vec3 Clamp(const Vec3& vec, const Vec3& min, const Vec3& max);
|
||||
static constexpr Vec3 CrossProduct(const Vec3& vec1, const Vec3& vec2);
|
||||
template<typename U = T> static U Distance(const Vec3& vec1, const Vec3& vec2);
|
||||
static constexpr T DotProduct(const Vec3& vec1, const Vec3& vec2);
|
||||
static constexpr Vec3 Down();
|
||||
static constexpr Vec3 Forward();
|
||||
static constexpr Vec3 Left();
|
||||
static constexpr Vec3 Max(const Vec3& lhs, const Vec3& rhs);
|
||||
static constexpr Vec3 Min(const Vec3& lhs, const Vec3& rhs);
|
||||
static Vec3 Normalize(const Vec3& vec);
|
||||
static constexpr Vec3 Right();
|
||||
static constexpr T SquaredDistance(const Vec3& vec1, const Vec3& vec2);
|
||||
static constexpr Vec3 Unit();
|
||||
static constexpr Vec3 UnitX();
|
||||
static constexpr Vec3 UnitY();
|
||||
static constexpr Vec3 UnitZ();
|
||||
static constexpr Vec3 Up();
|
||||
static constexpr Vec3 Zero();
|
||||
|
||||
~Vec3() = default;
|
||||
};
|
||||
|
||||
using Vec3b = Vec3<std::uint8_t>;
|
||||
using Vec3d = Vec3<double>;
|
||||
using Vec3f = Vec3<float>;
|
||||
using Vec3i = Vec3<int>;
|
||||
using Vec3ui = Vec3<unsigned int>;
|
||||
using Vec3i32 = Vec3<std::int32_t>;
|
||||
using Vec3i64 = Vec3<std::int64_t>;
|
||||
using Vec3ui32 = Vec3<std::uint32_t>;
|
||||
using Vec3ui64 = Vec3<std::uint64_t>;
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const Vec3<T>& vec);
|
||||
|
||||
template<typename T> constexpr Vec3<T> operator*(T scale, const Vec3<T>& vec);
|
||||
template<typename T> constexpr Vec3<T> operator/(T scale, const Vec3<T>& vec);
|
||||
template<typename T> constexpr Vec3<T> operator%(T scale, const Vec3<T>& vec);
|
||||
}
|
||||
|
||||
#include <Maths/Vec3.inl>
|
||||
|
||||
#endif
|
||||
509
Runtime/Includes/Maths/Vec3.inl
git.filemode.executable_file
509
Runtime/Includes/Maths/Vec3.inl
git.filemode.executable_file
@@ -0,0 +1,509 @@
|
||||
#pragma once
|
||||
|
||||
#include <Maths/Vec3.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T>
|
||||
constexpr Vec3<T>::Vec3(T X, T Y, T Z) : x(X), y(Y), z(Z) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>::Vec3(T X, const Vec2<T>& vec) : x(X), y(vec.x), z(vec.y) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>::Vec3(T scale) : x(scale), y(scale), z(scale) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>::Vec3(const Vec2<T>& vec, T Z) : x(vec.x), y(vec.y), z(Z) {}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr Vec3<T>::Vec3(const Vec3<U>& vec) : x(static_cast<T>(vec.x)), y(static_cast<T>(vec.y)), z(static_cast<T>(vec.z)) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>::Vec3(const Vec4<T>& vec) : x(vec.x), y(vec.y), z(vec.z) {}
|
||||
|
||||
template<typename T>
|
||||
T Vec3<T>::AbsDotProduct(const Vec3& vec) const
|
||||
{
|
||||
return std::abs(x * vec.x) + std::abs(y * vec.y) + std::abs(z * vec.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec3<T>::ApproxEqual(const Vec3& vec, T maxDifference) const
|
||||
{
|
||||
return NumberEquals(x, vec.x, maxDifference) && NumberEquals(y, vec.y, maxDifference) && NumberEquals(z, vec.z, maxDifference);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::CrossProduct(const Vec3& vec) const
|
||||
{
|
||||
return Vec3(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
U Vec3<T>::Distance(const Vec3& vec) const
|
||||
{
|
||||
return static_cast<U>(std::sqrt(static_cast<U>(SquaredDistance(vec))));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec3<T>::DotProduct(const Vec3& vec) const
|
||||
{
|
||||
return x * vec.x + y * vec.y + z * vec.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec3<T> Vec3<T>::GetAbs() const
|
||||
{
|
||||
return Vec3(std::abs(x), std::abs(y), std::abs(z));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
U Vec3<T>::GetLength() const
|
||||
{
|
||||
return static_cast<U>(std::sqrt(static_cast<U>(GetSquaredLength())));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec3<T> Vec3<T>::GetNormal(T* length) const
|
||||
{
|
||||
Vec3 vec(*this);
|
||||
vec.Normalize(length);
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec3<T>::GetSquaredLength() const
|
||||
{
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>& Vec3<T>::Maximize(const Vec3& vec)
|
||||
{
|
||||
if (vec.x > x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y > y)
|
||||
y = vec.y;
|
||||
|
||||
if (vec.z > z)
|
||||
z = vec.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>& Vec3<T>::Minimize(const Vec3& vec)
|
||||
{
|
||||
if (vec.x < x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y < y)
|
||||
y = vec.y;
|
||||
|
||||
if (vec.z < z)
|
||||
z = vec.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec3<T>& Vec3<T>::Normalize(T* length)
|
||||
{
|
||||
T norm = GetLength();
|
||||
if (norm > T(0.0))
|
||||
{
|
||||
T invNorm = T(1.0) / norm;
|
||||
x *= invNorm;
|
||||
y *= invNorm;
|
||||
z *= invNorm;
|
||||
}
|
||||
|
||||
if (length)
|
||||
*length = norm;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec3<T>::SquaredDistance(const Vec3& vec) const
|
||||
{
|
||||
return (*this - vec).GetSquaredLength();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string Vec3<T>::ToString() const
|
||||
{
|
||||
return "Vec3(" + std::to_string(x) + ", " + std::to_string(y) + ", " + std::to_string(z) + ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T& Vec3<T>::operator[](std::size_t i)
|
||||
{
|
||||
Scop::Assert(i < 3, "index out of range");
|
||||
return *(&x + i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr const T& Vec3<T>::operator[](std::size_t i) const
|
||||
{
|
||||
Scop::Assert(i < 3, "index out of range");
|
||||
return *(&x + i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr const Vec3<T>& Vec3<T>::operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::operator-() const
|
||||
{
|
||||
return Vec3(-x, -y, -z);
|
||||
}
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::operator+(const Vec3& vec) const
|
||||
{
|
||||
return Vec3(x + vec.x, y + vec.y, z + vec.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::operator-(const Vec3& vec) const
|
||||
{
|
||||
return Vec3(x - vec.x, y - vec.y, z - vec.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::operator*(const Vec3& vec) const
|
||||
{
|
||||
return Vec3(x * vec.x, y * vec.y, z * vec.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::operator*(T scale) const
|
||||
{
|
||||
return Vec3(x * scale, y * scale, z * scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::operator/(const Vec3& vec) const
|
||||
{
|
||||
return Vec3(x / vec.x, y / vec.y, z / vec.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::operator/(T scale) const
|
||||
{
|
||||
return Vec3(x / scale, y / scale, z / scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::operator%(const Vec3& vec) const
|
||||
{
|
||||
return Vec3(Mod(x, vec.x), Mod(y, vec.y), Mod(z, vec.z));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::operator%(T mod) const
|
||||
{
|
||||
return Vec3(Mod(x, mod), Mod(y, mod), Mod(z, mod));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>& Vec3<T>::operator+=(const Vec3& vec)
|
||||
{
|
||||
x += vec.x;
|
||||
y += vec.y;
|
||||
z += vec.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>& Vec3<T>::operator-=(const Vec3& vec)
|
||||
{
|
||||
x -= vec.x;
|
||||
y -= vec.y;
|
||||
z -= vec.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>& Vec3<T>::operator*=(const Vec3& vec)
|
||||
{
|
||||
x *= vec.x;
|
||||
y *= vec.y;
|
||||
z *= vec.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>& Vec3<T>::operator*=(T scale)
|
||||
{
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
z *= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>& Vec3<T>::operator/=(const Vec3& vec)
|
||||
{
|
||||
x /= vec.x;
|
||||
y /= vec.y;
|
||||
z /= vec.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>& Vec3<T>::operator/=(T scale)
|
||||
{
|
||||
x /= scale;
|
||||
y /= scale;
|
||||
z /= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>& Vec3<T>::operator%=(const Vec3& vec)
|
||||
{
|
||||
x = Mod(x, vec.x);
|
||||
y = Mod(y, vec.y);
|
||||
z = Mod(z, vec.z);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T>& Vec3<T>::operator%=(T mod)
|
||||
{
|
||||
x = Mod(x, mod);
|
||||
y = Mod(y, mod);
|
||||
z = Mod(z, mod);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec3<T>::operator==(const Vec3& vec) const
|
||||
{
|
||||
return x == vec.x && y == vec.y && z == vec.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec3<T>::operator!=(const Vec3& vec) const
|
||||
{
|
||||
return !operator==(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec3<T>::operator<(const Vec3& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x < vec.x;
|
||||
|
||||
if (y != vec.y)
|
||||
return y < vec.y;
|
||||
|
||||
return z < vec.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec3<T>::operator<=(const Vec3& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x < vec.x;
|
||||
|
||||
if (y != vec.y)
|
||||
return y < vec.y;
|
||||
|
||||
return z <= vec.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec3<T>::operator>(const Vec3& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x > vec.x;
|
||||
|
||||
if (y != vec.y)
|
||||
return y > vec.y;
|
||||
|
||||
return z > vec.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec3<T>::operator>=(const Vec3& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x > vec.x;
|
||||
|
||||
if (y != vec.y)
|
||||
return y > vec.y;
|
||||
|
||||
return z >= vec.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::Apply(T(*func)(T), const Vec3& vec)
|
||||
{
|
||||
return Vec3(func(vec.x), func(vec.y), func(vec.z));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec3<T>::ApproxEqual(const Vec3& lhs, const Vec3& rhs, T maxDifference)
|
||||
{
|
||||
return lhs.ApproxEqual(rhs, maxDifference);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::CrossProduct(const Vec3& vec1, const Vec3& vec2)
|
||||
{
|
||||
return vec1.CrossProduct(vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec3<T>::DotProduct(const Vec3& vec1, const Vec3& vec2)
|
||||
{
|
||||
return vec1.DotProduct(vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::Backward()
|
||||
{
|
||||
return Vec3(0, 0, 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
U Vec3<T>::Distance(const Vec3& vec1, const Vec3& vec2)
|
||||
{
|
||||
return vec1.Distance<U>(vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::Down()
|
||||
{
|
||||
return Vec3(0, -1, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::Forward()
|
||||
{
|
||||
return Vec3(0, 0, -1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::Left()
|
||||
{
|
||||
return Vec3(-1, 0, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::Max(const Vec3& lhs, const Vec3& rhs)
|
||||
{
|
||||
Vec3 max = lhs;
|
||||
max.Maximize(rhs);
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::Min(const Vec3& lhs, const Vec3& rhs)
|
||||
{
|
||||
Vec3 min = lhs;
|
||||
min.Minimize(rhs);
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec3<T> Vec3<T>::Normalize(const Vec3& vec)
|
||||
{
|
||||
return vec.GetNormal();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::Right()
|
||||
{
|
||||
return Vec3(1, 0, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec3<T>::SquaredDistance(const Vec3& vec1, const Vec3& vec2)
|
||||
{
|
||||
return vec1.SquaredDistance(vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::Unit()
|
||||
{
|
||||
return Vec3(1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::UnitX()
|
||||
{
|
||||
return Vec3(1, 0, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::UnitY()
|
||||
{
|
||||
return Vec3(0, 1, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::UnitZ()
|
||||
{
|
||||
return Vec3(0, 0, 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::Up()
|
||||
{
|
||||
return Vec3(0, 1, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> Vec3<T>::Zero()
|
||||
{
|
||||
return Vec3(0, 0, 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const Vec3<T>& vec)
|
||||
{
|
||||
return out << "Vec3(" << vec.x << ", " << vec.y << ", " << vec.z << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> operator*(T scale, const Vec3<T>& vec)
|
||||
{
|
||||
return Vec3<T>(scale * vec.x, scale * vec.y, scale * vec.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> operator/(T scale, const Vec3<T>& vec)
|
||||
{
|
||||
return Vec3<T>(scale / vec.x, scale / vec.y, scale / vec.z);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec3<T> operator%(T mod, const Vec3<T>& vec)
|
||||
{
|
||||
return Vec3<T>(Mod(mod, vec.x), Mod(mod, vec.y), Mod(mod, vec.z));
|
||||
}
|
||||
}
|
||||
|
||||
115
Runtime/Includes/Maths/Vec4.h
git.filemode.executable_file
115
Runtime/Includes/Maths/Vec4.h
git.filemode.executable_file
@@ -0,0 +1,115 @@
|
||||
#ifndef __SCOP_VEC4__
|
||||
#define __SCOP_VEC4__
|
||||
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
|
||||
#include <Core/Logs.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T> class Vec2;
|
||||
template<typename T> class Vec3;
|
||||
|
||||
template<typename T>
|
||||
struct Vec4
|
||||
{
|
||||
T x;
|
||||
T y;
|
||||
T z;
|
||||
T w;
|
||||
|
||||
constexpr Vec4() = default;
|
||||
constexpr Vec4(T X, T Y, T Z, T W = 1.0);
|
||||
constexpr Vec4(T X, T Y, const Vec2<T>& vec);
|
||||
constexpr Vec4(T X, const Vec2<T>& vec, T W);
|
||||
constexpr Vec4(T X, const Vec3<T>& vec);
|
||||
constexpr explicit Vec4(T scale);
|
||||
constexpr Vec4(const Vec2<T>& vec, T Z = 0.0, T W = 1.0);
|
||||
constexpr Vec4(const Vec3<T>& vec, T W = 1.0);
|
||||
template<typename U> constexpr explicit Vec4(const Vec4<U>& vec);
|
||||
constexpr Vec4(const Vec4&) = default;
|
||||
constexpr Vec4(Vec4&&) = default;
|
||||
|
||||
T AbsDotProduct(const Vec4& vec) const;
|
||||
constexpr bool ApproxEqual(const Vec4& vec, T max_difference = std::numeric_limits<T>::epsilon()) const;
|
||||
|
||||
constexpr T DotProduct(const Vec4& vec) const;
|
||||
|
||||
Vec4 GetNormal(T* length = nullptr) const;
|
||||
|
||||
constexpr Vec4& Maximize(const Vec4& vec);
|
||||
constexpr Vec4& Minimize(const Vec4& vec);
|
||||
|
||||
Vec4& Normalize(T* length = nullptr);
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
constexpr Vec4& operator=(const Vec4&) = default;
|
||||
constexpr Vec4& operator=(Vec4&&) = default;
|
||||
|
||||
constexpr T& operator[](std::size_t i);
|
||||
constexpr const T& operator[](std::size_t i) const;
|
||||
|
||||
constexpr const Vec4& operator+() const;
|
||||
constexpr Vec4 operator-() const;
|
||||
|
||||
constexpr Vec4 operator+(const Vec4& vec) const;
|
||||
constexpr Vec4 operator-(const Vec4& vec) const;
|
||||
constexpr Vec4 operator*(const Vec4& vec) const;
|
||||
constexpr Vec4 operator*(T scale) const;
|
||||
constexpr Vec4 operator/(const Vec4& vec) const;
|
||||
constexpr Vec4 operator/(T scale) const;
|
||||
constexpr Vec4 operator%(const Vec4& vec) const;
|
||||
constexpr Vec4 operator%(T mod) const;
|
||||
|
||||
constexpr Vec4& operator+=(const Vec4& vec);
|
||||
constexpr Vec4& operator-=(const Vec4& vec);
|
||||
constexpr Vec4& operator*=(const Vec4& vec);
|
||||
constexpr Vec4& operator*=(T scale);
|
||||
constexpr Vec4& operator/=(const Vec4& vec);
|
||||
constexpr Vec4& operator/=(T scale);
|
||||
constexpr Vec4& operator%=(const Vec4& vec);
|
||||
constexpr Vec4& operator%=(T mod);
|
||||
|
||||
constexpr bool operator==(const Vec4& vec) const;
|
||||
constexpr bool operator!=(const Vec4& vec) const;
|
||||
constexpr bool operator<(const Vec4& vec) const;
|
||||
constexpr bool operator<=(const Vec4& vec) const;
|
||||
constexpr bool operator>(const Vec4& vec) const;
|
||||
constexpr bool operator>=(const Vec4& vec) const;
|
||||
|
||||
static constexpr Vec4 Apply(T(*func)(T), const Vec4& vec);
|
||||
static constexpr bool ApproxEqual(const Vec4& lhs, const Vec4& rhs, T max_difference = std::numeric_limits<T>::epsilon());
|
||||
static constexpr T DotProduct(const Vec4& vec1, const Vec4& vec2);
|
||||
static Vec4 Normalize(const Vec4& vec);
|
||||
static constexpr Vec4 UnitX();
|
||||
static constexpr Vec4 UnitY();
|
||||
static constexpr Vec4 UnitZ();
|
||||
static constexpr Vec4 Zero();
|
||||
|
||||
~Vec4() = default;
|
||||
};
|
||||
|
||||
using Vec4d = Vec4<double>;
|
||||
using Vec4f = Vec4<float>;
|
||||
using Vec4i = Vec4<int>;
|
||||
using Vec4ui = Vec4<unsigned int>;
|
||||
using Vec4i32 = Vec4<std::int32_t>;
|
||||
using Vec4i64 = Vec4<std::int64_t>;
|
||||
using Vec4ui32 = Vec4<std::uint32_t>;
|
||||
using Vec4ui64 = Vec4<std::uint64_t>;
|
||||
|
||||
template<typename T> std::ostream& operator<<(std::ostream& out, const Vec4<T>& vec);
|
||||
|
||||
template<typename T> constexpr Vec4<T> operator*(T scale, const Vec4<T>& vec);
|
||||
template<typename T> constexpr Vec4<T> operator/(T scale, const Vec4<T>& vec);
|
||||
template<typename T> constexpr Vec4<T> operator%(T mod, const Vec4<T>& vec);
|
||||
}
|
||||
|
||||
#include <Maths/Vec4.inl>
|
||||
|
||||
#endif
|
||||
|
||||
424
Runtime/Includes/Maths/Vec4.inl
git.filemode.executable_file
424
Runtime/Includes/Maths/Vec4.inl
git.filemode.executable_file
@@ -0,0 +1,424 @@
|
||||
#pragma once
|
||||
|
||||
#include <Maths/Vec4.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
template<typename T>
|
||||
constexpr Vec4<T>::Vec4(T X, T Y, T Z, T W) : x(X), y(Y), z(Z), w(W) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>::Vec4(T X, T Y, const Vec2<T>& vec) : x(X), y(Y), z(vec.x), w(vec.y) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>::Vec4(T X, const Vec2<T>& vec, T W) : x(X), y(vec.x), z(vec.y), w(W) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>::Vec4(T X, const Vec3<T>& vec) : x(X), y(vec.x), z(vec.y), w(vec.z) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>::Vec4(T scale) : x(scale), y(scale), z(scale), w(scale) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>::Vec4(const Vec2<T>& vec, T Z, T W) : x(vec.x), y(vec.y), z(Z), w(W) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>::Vec4(const Vec3<T>& vec, T W) : x(vec.x), y(vec.y), z(vec.z), w(W) {}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
constexpr Vec4<T>::Vec4(const Vec4<U>& vec) : x(static_cast<T>(vec.x)), y(static_cast<T>(vec.y)), z(static_cast<T>(vec.z)), w(static_cast<T>(vec.w)) {}
|
||||
|
||||
template<typename T>
|
||||
T Vec4<T>::AbsDotProduct(const Vec4& vec) const
|
||||
{
|
||||
return std::abs(x * vec.x) + std::abs(y * vec.y) + std::abs(z * vec.z) + std::abs(w * vec.w);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec4<T>::ApproxEqual(const Vec4& vec, T maxDifference) const
|
||||
{
|
||||
return NumberEquals(x, vec.x, maxDifference) && NumberEquals(y, vec.y, maxDifference) && NumberEquals(z, vec.z, maxDifference) && NumberEquals(w, vec.w, maxDifference);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec4<T>::DotProduct(const Vec4& vec) const
|
||||
{
|
||||
return x*vec.x + y*vec.y + z*vec.z + w*vec.w;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec4<T> Vec4<T>::GetNormal(T* length) const
|
||||
{
|
||||
Vec4<T> vec(*this);
|
||||
vec.Normalize(length);
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>& Vec4<T>::Maximize(const Vec4& vec)
|
||||
{
|
||||
if (vec.x > x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y > y)
|
||||
y = vec.y;
|
||||
|
||||
if (vec.z > z)
|
||||
z = vec.z;
|
||||
|
||||
if (vec.w > w)
|
||||
w = vec.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>& Vec4<T>::Minimize(const Vec4& vec)
|
||||
{
|
||||
if (vec.x < x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y < y)
|
||||
y = vec.y;
|
||||
|
||||
if (vec.z < z)
|
||||
z = vec.z;
|
||||
|
||||
if (vec.w < w)
|
||||
w = vec.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec4<T>& Vec4<T>::Normalize(T* length)
|
||||
{
|
||||
T invLength = T(1.0) / w;
|
||||
x *= invLength;
|
||||
y *= invLength;
|
||||
z *= invLength;
|
||||
|
||||
if (length)
|
||||
*length = w;
|
||||
|
||||
w = T(1.0);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string Vec4<T>::ToString() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << *this;
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T& Vec4<T>::operator[](std::size_t i)
|
||||
{
|
||||
Scop::Assert(i < 4, "index out of range");
|
||||
return *(&x + i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr const T& Vec4<T>::operator[](std::size_t i) const
|
||||
{
|
||||
Scop::Assert(i < 4, "index out of range");
|
||||
return *(&x + i);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr const Vec4<T>& Vec4<T>::operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::operator-() const
|
||||
{
|
||||
return Vec4(-x, -y, -z, -w);
|
||||
}
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::operator+(const Vec4& vec) const
|
||||
{
|
||||
return Vec4(x + vec.x, y + vec.y, z + vec.z, w + vec.w);
|
||||
}
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::operator-(const Vec4& vec) const
|
||||
{
|
||||
return Vec4(x - vec.x, y - vec.y, z - vec.z, w - vec.w);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::operator*(const Vec4& vec) const
|
||||
{
|
||||
return Vec4(x * vec.x, y * vec.y, z * vec.z, w * vec.w);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::operator*(T scale) const
|
||||
{
|
||||
return Vec4(x * scale, y * scale, z * scale, w * scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::operator/(const Vec4& vec) const
|
||||
{
|
||||
return Vec4(x / vec.x, y / vec.y, z / vec.z, w / vec.w);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::operator/(T scale) const
|
||||
{
|
||||
return Vec4(x / scale, y / scale, z / scale, w / scale);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::operator%(const Vec4& vec) const
|
||||
{
|
||||
return Vec4(Mod(x, vec.x), Mod(y, vec.y), Mod(z, vec.z), Mod(w, vec.w));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::operator%(T mod) const
|
||||
{
|
||||
return Vec4(Mod(x, mod), Mod(y, mod), Mod(z, mod), Mod(z, mod));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>& Vec4<T>::operator+=(const Vec4& vec)
|
||||
{
|
||||
x += vec.x;
|
||||
y += vec.y;
|
||||
z += vec.z;
|
||||
w += vec.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>& Vec4<T>::operator-=(const Vec4& vec)
|
||||
{
|
||||
x -= vec.x;
|
||||
y -= vec.y;
|
||||
z -= vec.z;
|
||||
w -= vec.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>& Vec4<T>::operator*=(const Vec4& vec)
|
||||
{
|
||||
x *= vec.x;
|
||||
y *= vec.y;
|
||||
z *= vec.z;
|
||||
w *= vec.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>& Vec4<T>::operator*=(T scale)
|
||||
{
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
z *= scale;
|
||||
w *= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>& Vec4<T>::operator/=(const Vec4& vec)
|
||||
{
|
||||
x /= vec.x;
|
||||
y /= vec.y;
|
||||
z /= vec.z;
|
||||
w /= vec.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>& Vec4<T>::operator/=(T scale)
|
||||
{
|
||||
x /= scale;
|
||||
y /= scale;
|
||||
z /= scale;
|
||||
w /= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>& Vec4<T>::operator%=(const Vec4& vec)
|
||||
{
|
||||
x = Mod(x, vec.x);
|
||||
y = Mod(y, vec.y);
|
||||
z = Mod(z, vec.z);
|
||||
w = Mod(w, vec.w);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T>& Vec4<T>::operator%=(T mod)
|
||||
{
|
||||
x = Mod(x, mod);
|
||||
y = Mod(y, mod);
|
||||
z = Mod(z, mod);
|
||||
w = Mod(w, mod);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec4<T>::operator==(const Vec4& vec) const
|
||||
{
|
||||
return x == vec.x && y == vec.y && z == vec.z && w == vec.w;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec4<T>::operator!=(const Vec4& vec) const
|
||||
{
|
||||
return !operator==(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec4<T>::operator<(const Vec4& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x < vec.x;
|
||||
|
||||
if (y != vec.y)
|
||||
return y < vec.y;
|
||||
|
||||
if (z != vec.z)
|
||||
return z < vec.z;
|
||||
|
||||
return w < vec.w;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec4<T>::operator<=(const Vec4& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x < vec.x;
|
||||
|
||||
if (y != vec.y)
|
||||
return y < vec.y;
|
||||
|
||||
if (z != vec.z)
|
||||
return z < vec.z;
|
||||
|
||||
return w <= vec.w;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec4<T>::operator>(const Vec4& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x > vec.x;
|
||||
|
||||
if (y != vec.y)
|
||||
return y > vec.y;
|
||||
|
||||
if (z != vec.z)
|
||||
return z > vec.z;
|
||||
|
||||
return w > vec.w;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec4<T>::operator>=(const Vec4& vec) const
|
||||
{
|
||||
if (x != vec.x)
|
||||
return x > vec.x;
|
||||
|
||||
if (y != vec.y)
|
||||
return y > vec.y;
|
||||
|
||||
if (z != vec.z)
|
||||
return z > vec.z;
|
||||
|
||||
return w >= vec.w;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::Apply(T(*func)(T), const Vec4& vec)
|
||||
{
|
||||
return Vec4(func(vec.x), func(vec.y), func(vec.z), func(vec.w));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool Vec4<T>::ApproxEqual(const Vec4& lhs, const Vec4& rhs, T maxDifference)
|
||||
{
|
||||
return lhs.ApproxEqual(rhs, maxDifference);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T Vec4<T>::DotProduct(const Vec4& vec1, const Vec4& vec2)
|
||||
{
|
||||
return vec1.DotProduct(vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec4<T> Vec4<T>::Normalize(const Vec4& vec)
|
||||
{
|
||||
return vec.GetNormal();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::UnitX()
|
||||
{
|
||||
return Vec4(1, 0, 0, 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::UnitY()
|
||||
{
|
||||
return Vec4(0, 1, 0, 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::UnitZ()
|
||||
{
|
||||
return Vec4(0, 0, 1, 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> Vec4<T>::Zero()
|
||||
{
|
||||
return Vec4(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const Vec4<T>& vec)
|
||||
{
|
||||
return out << "Vec4(" << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> operator*(T scale, const Vec4<T>& vec)
|
||||
{
|
||||
return Vec4<T>(scale * vec.x, scale * vec.y, scale * vec.z, scale * vec.w);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> operator/(T scale, const Vec4<T>& vec)
|
||||
{
|
||||
return Vec4<T>(scale / vec.x, scale / vec.y, scale / vec.z, scale / vec.w);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Vec4<T> operator%(T mod, const Vec4<T>& vec)
|
||||
{
|
||||
return Vec4<T>(Mod(mod, vec.x), Mod(mod, vec.y), Mod(mod, vec.z), Mod(mod, vec.w));
|
||||
}
|
||||
}
|
||||
|
||||
61
Runtime/Includes/Platform/Inputs.h
git.filemode.normal_file
61
Runtime/Includes/Platform/Inputs.h
git.filemode.normal_file
@@ -0,0 +1,61 @@
|
||||
#ifndef __SCOP_PLATFORM_INPUTS__
|
||||
#define __SCOP_PLATFORM_INPUTS__
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
using EventUpdateHook = std::function<void(SDL_Event*)>;
|
||||
|
||||
class Inputs
|
||||
{
|
||||
friend class ScopEngine;
|
||||
|
||||
public:
|
||||
Inputs();
|
||||
|
||||
[[nodiscard]] inline bool IsKeyPressed(const std::uint32_t button) const noexcept { return m_keys[button]; }
|
||||
[[nodiscard]] inline bool IsMouseButtonPressed(const std::uint8_t button) const noexcept { return m_mouse[button - 1]; }
|
||||
[[nodiscard]] inline bool IsMouseWheelUp() const noexcept { return m_is_mouse_wheel_up; }
|
||||
[[nodiscard]] inline bool IsMouseWheelDown() const noexcept { return m_is_mouse_wheel_down; }
|
||||
[[nodiscard]] inline std::int32_t GetX() const noexcept { return m_x; }
|
||||
[[nodiscard]] inline std::int32_t GetY() const noexcept { return m_y; }
|
||||
[[nodiscard]] inline std::int32_t GetXRel() const noexcept { return m_x_rel; }
|
||||
[[nodiscard]] inline std::int32_t GetYRel() const noexcept { return m_y_rel; }
|
||||
|
||||
inline void AddEventUpdateHook(const EventUpdateHook& hook) { m_hooks.push_back(hook); }
|
||||
|
||||
inline void GrabMouse() noexcept { SDL_SetRelativeMouseMode(SDL_TRUE); SDL_ShowCursor(SDL_DISABLE); m_is_mouse_grabbed = true; }
|
||||
inline void ReleaseMouse() noexcept { SDL_SetRelativeMouseMode(SDL_FALSE); SDL_ShowCursor(SDL_ENABLE); m_is_mouse_grabbed = false; }
|
||||
[[nodiscard]] inline bool IsMouseGrabbed() const noexcept { return m_is_mouse_grabbed; }
|
||||
|
||||
[[nodiscard]] inline bool HasRecievedCloseEvent() const noexcept { return m_has_recieved_close_event; }
|
||||
|
||||
~Inputs() = default;
|
||||
|
||||
private:
|
||||
void Update();
|
||||
|
||||
private:
|
||||
SDL_Event m_event;
|
||||
std::vector<EventUpdateHook> m_hooks;
|
||||
const std::uint8_t* m_keys;
|
||||
std::array<bool, 5> m_mouse; // 5 bytes, shitty padding, maybe fix
|
||||
std::int32_t m_keys_count = 0;
|
||||
std::int32_t m_x = 0;
|
||||
std::int32_t m_y = 0;
|
||||
std::int32_t m_x_rel = 0;
|
||||
std::int32_t m_y_rel = 0;
|
||||
bool m_has_recieved_close_event = false;
|
||||
bool m_is_mouse_grabbed = false;
|
||||
bool m_is_mouse_wheel_up = false;
|
||||
bool m_is_mouse_wheel_down = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
46
Runtime/Includes/Platform/Window.h
git.filemode.normal_file
46
Runtime/Includes/Platform/Window.h
git.filemode.normal_file
@@ -0,0 +1,46 @@
|
||||
#ifndef __SCOP_PLATFORM_WINDOW__
|
||||
#define __SCOP_PLATFORM_WINDOW__
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <Maths/Vec2.h>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class Window
|
||||
{
|
||||
friend class ScopEngine;
|
||||
public:
|
||||
Window(const std::string& title, std::uint32_t width, std::uint32_t height, bool hidden = false);
|
||||
|
||||
[[nodiscard]] inline const std::string& GetTitle() const noexcept { return m_title; }
|
||||
[[nodiscard]] inline std::uint32_t GetWidth() const noexcept { return m_width; }
|
||||
[[nodiscard]] inline std::uint32_t GetHeight() const noexcept { return m_height; }
|
||||
[[nodiscard]] inline SDL_Window* GetSDLWindow() const noexcept { return p_window; }
|
||||
|
||||
void FetchWindowInfos() noexcept;
|
||||
|
||||
[[nodiscard]] VkSurfaceKHR CreateVulkanSurface(VkInstance instance) const noexcept;
|
||||
[[nodiscard]] std::vector<const char*> GetRequiredVulkanInstanceExtentions() const noexcept;
|
||||
[[nodiscard]] Vec2ui GetVulkanDrawableSize() const noexcept;
|
||||
|
||||
~Window();
|
||||
|
||||
private:
|
||||
// Can only be called by the engine
|
||||
void Destroy() noexcept;
|
||||
|
||||
private:
|
||||
SDL_Window* p_window = nullptr;
|
||||
std::string m_title;
|
||||
std::uint32_t m_height = 0;
|
||||
std::uint32_t m_width = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
112
Runtime/Includes/Renderer/Buffer.h
git.filemode.normal_file
112
Runtime/Includes/Renderer/Buffer.h
git.filemode.normal_file
@@ -0,0 +1,112 @@
|
||||
#ifndef __SCOP_GPU_BUFFER__
|
||||
#define __SCOP_GPU_BUFFER__
|
||||
|
||||
#include <kvf.h>
|
||||
#include <Renderer/Enums.h>
|
||||
#include <Core/Logs.h>
|
||||
#include <Renderer/RenderCore.h>
|
||||
#include <Utils/Buffer.h>
|
||||
#include <Renderer/Memory/Block.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class GPUBuffer
|
||||
{
|
||||
public:
|
||||
GPUBuffer() = default;
|
||||
|
||||
void Init(BufferType type, VkDeviceSize size, VkBufferUsageFlags usage, CPUBuffer data, std::string_view name = {}, bool dedicated_alloc = false);
|
||||
void Destroy() noexcept;
|
||||
|
||||
bool CopyFrom(const GPUBuffer& buffer, std::size_t src_offset = 0, std::size_t dst_offset = 0) noexcept;
|
||||
|
||||
void Swap(GPUBuffer& buffer) noexcept;
|
||||
|
||||
[[nodiscard]] inline void* GetMap() const noexcept { return m_memory.map; }
|
||||
[[nodiscard]] inline VkBuffer operator()() const noexcept { return m_buffer; }
|
||||
[[nodiscard]] inline VkBuffer Get() const noexcept { return m_buffer; }
|
||||
[[nodiscard]] inline VkDeviceMemory GetMemory() const noexcept { return m_memory.memory; }
|
||||
[[nodiscard]] inline VkDeviceSize GetSize() const noexcept { return m_size; }
|
||||
[[nodiscard]] inline VkDeviceSize GetOffset() const noexcept { return 0; }
|
||||
|
||||
[[nodiscard]] inline static std::size_t GetBufferCount() noexcept { return s_buffer_count; }
|
||||
|
||||
[[nodiscard]] inline bool IsInit() const noexcept { return m_buffer != VK_NULL_HANDLE; }
|
||||
|
||||
~GPUBuffer() = default;
|
||||
|
||||
protected:
|
||||
void PushToGPU() noexcept;
|
||||
|
||||
protected:
|
||||
VkBuffer m_buffer = VK_NULL_HANDLE;
|
||||
MemoryBlock m_memory = NULL_MEMORY_BLOCK;
|
||||
VkDeviceSize m_size = 0;
|
||||
|
||||
private:
|
||||
void CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, std::string_view name, bool dedicated_alloc);
|
||||
|
||||
private:
|
||||
inline static std::size_t s_buffer_count = 0;
|
||||
|
||||
std::string m_name;
|
||||
|
||||
VkBufferUsageFlags m_usage = 0;
|
||||
VkMemoryPropertyFlags m_flags = 0;
|
||||
bool m_is_dedicated_alloc = false;
|
||||
};
|
||||
|
||||
class VertexBuffer : public GPUBuffer
|
||||
{
|
||||
public:
|
||||
inline void Init(std::uint32_t size, VkBufferUsageFlags additional_flags = 0, std::string_view name = {}) { GPUBuffer::Init(BufferType::LowDynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | additional_flags, {}, std::move(name)); }
|
||||
void SetData(CPUBuffer data);
|
||||
inline void Bind(VkCommandBuffer cmd) const noexcept { VkDeviceSize offset = 0; RenderCore::Get().vkCmdBindVertexBuffers(cmd, 0, 1, &m_buffer, &offset); }
|
||||
};
|
||||
|
||||
class IndexBuffer : public GPUBuffer
|
||||
{
|
||||
public:
|
||||
inline void Init(std::uint32_t size, VkBufferUsageFlags additional_flags = 0, std::string_view name = {}) { GPUBuffer::Init(BufferType::LowDynamic, size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | additional_flags, {}, std::move(name)); }
|
||||
void SetData(CPUBuffer data);
|
||||
inline void Bind(VkCommandBuffer cmd) const noexcept { RenderCore::Get().vkCmdBindIndexBuffer(cmd, m_buffer, 0, VK_INDEX_TYPE_UINT32); }
|
||||
};
|
||||
|
||||
class MeshBuffer : public GPUBuffer
|
||||
{
|
||||
public:
|
||||
inline void Init(std::uint32_t vertex_size, std::uint32_t index_size, VkBufferUsageFlags additional_flags = 0, CPUBuffer data = {}, std::string_view name = {})
|
||||
{
|
||||
m_vertex_offset = 0;
|
||||
m_index_offset = vertex_size;
|
||||
GPUBuffer::Init(BufferType::LowDynamic, vertex_size + index_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | additional_flags, std::move(data), std::move(name), false);
|
||||
}
|
||||
void SetVertexData(CPUBuffer data);
|
||||
void SetIndexData(CPUBuffer data);
|
||||
inline void BindVertex(VkCommandBuffer cmd) const noexcept { RenderCore::Get().vkCmdBindVertexBuffers(cmd, 0, 1, &m_buffer, &m_vertex_offset); }
|
||||
inline void BindIndex(VkCommandBuffer cmd) const noexcept { RenderCore::Get().vkCmdBindIndexBuffer(cmd, m_buffer, m_index_offset, VK_INDEX_TYPE_UINT32); }
|
||||
|
||||
private:
|
||||
VkDeviceSize m_vertex_offset;
|
||||
VkDeviceSize m_index_offset;
|
||||
};
|
||||
|
||||
class UniformBuffer
|
||||
{
|
||||
public:
|
||||
void Init(std::uint32_t size, std::string_view name = {});
|
||||
void SetData(CPUBuffer data, std::size_t frame_index);
|
||||
void Destroy() noexcept;
|
||||
|
||||
inline VkDeviceSize GetSize(int i) const noexcept { return m_buffers[i].GetSize(); }
|
||||
inline VkDeviceSize GetOffset(int i) const noexcept { return m_buffers[i].GetOffset(); }
|
||||
inline VkBuffer GetVk(int i) const noexcept { return m_buffers[i].Get(); }
|
||||
inline GPUBuffer& Get(int i) noexcept { return m_buffers[i]; }
|
||||
|
||||
private:
|
||||
std::array<GPUBuffer, MAX_FRAMES_IN_FLIGHT> m_buffers;
|
||||
std::array<void*, MAX_FRAMES_IN_FLIGHT> m_maps;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
93
Runtime/Includes/Renderer/Descriptor.h
git.filemode.normal_file
93
Runtime/Includes/Renderer/Descriptor.h
git.filemode.normal_file
@@ -0,0 +1,93 @@
|
||||
#ifndef __SCOP_DESCRIPTOR_SET__
|
||||
#define __SCOP_DESCRIPTOR_SET__
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
#include <kvf.h>
|
||||
#include <Utils/NonOwningPtr.h>
|
||||
#include <Renderer/RenderCore.h>
|
||||
#include <Renderer/Pipelines/Shader.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
struct Descriptor
|
||||
{
|
||||
NonOwningPtr<class GPUBuffer> storage_buffer_ptr;
|
||||
NonOwningPtr<class GPUBuffer> uniform_buffer_ptr;
|
||||
NonOwningPtr<class Image> image_ptr;
|
||||
VkDescriptorType type;
|
||||
std::uint32_t binding;
|
||||
};
|
||||
|
||||
class DescriptorPool
|
||||
{
|
||||
public:
|
||||
DescriptorPool() = default;
|
||||
|
||||
void Init() noexcept;
|
||||
void Destroy() noexcept;
|
||||
|
||||
std::shared_ptr<class DescriptorSet> RequestDescriptorSet(const ShaderSetLayout& layout, ShaderType shader_type);
|
||||
void ReturnDescriptorSet(std::shared_ptr<class DescriptorSet> set);
|
||||
|
||||
[[nodiscard]] inline VkDescriptorPool Get() const noexcept { return m_pool; }
|
||||
[[nodiscard]] inline std::size_t GetNumberOfSetsAllocated() const noexcept { return m_allocation_count; }
|
||||
|
||||
~DescriptorPool() = default;
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<class DescriptorSet>> m_free_sets;
|
||||
std::vector<std::shared_ptr<class DescriptorSet>> m_used_sets;
|
||||
VkDescriptorPool m_pool;
|
||||
std::size_t m_allocation_count = 0;
|
||||
};
|
||||
|
||||
class DescriptorPoolManager
|
||||
{
|
||||
public:
|
||||
DescriptorPoolManager() = default;
|
||||
|
||||
DescriptorPool& GetAvailablePool();
|
||||
void Destroy();
|
||||
|
||||
~DescriptorPoolManager() = default;
|
||||
|
||||
private:
|
||||
std::vector<DescriptorPool> m_pools;
|
||||
};
|
||||
|
||||
class DescriptorSet : public std::enable_shared_from_this<DescriptorSet>
|
||||
{
|
||||
friend DescriptorPool;
|
||||
|
||||
public:
|
||||
void SetImage(std::size_t i, std::uint32_t binding, class Image& image);
|
||||
void SetStorageBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer);
|
||||
void SetUniformBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer);
|
||||
void Update(std::size_t i, VkCommandBuffer cmd = VK_NULL_HANDLE) noexcept;
|
||||
|
||||
void ReturnDescriptorSetToPool();
|
||||
|
||||
[[nodiscard]] inline VkDescriptorSet GetSet(std::size_t i) const noexcept { return m_sets[i]; }
|
||||
[[nodiscard]] inline bool IsInit() const noexcept { return m_sets[0] != VK_NULL_HANDLE; }
|
||||
[[nodiscard]] inline VkDescriptorSetLayout GetVulkanLayout() const noexcept { return m_set_layout; }
|
||||
[[nodiscard]] inline const ShaderSetLayout& GetShaderLayout() const { return m_shader_layout; }
|
||||
[[nodiscard]] inline ShaderType GetShaderType() const noexcept { return m_shader_type; }
|
||||
|
||||
~DescriptorSet() = default;
|
||||
|
||||
private:
|
||||
DescriptorSet(DescriptorPool& pool, VkDescriptorSetLayout vulkan_layout, const ShaderSetLayout& layout, std::array<VkDescriptorSet, MAX_FRAMES_IN_FLIGHT> vulkan_sets, ShaderType shader_type);
|
||||
|
||||
private:
|
||||
ShaderSetLayout m_shader_layout;
|
||||
std::vector<Descriptor> m_descriptors;
|
||||
std::array<VkDescriptorSet, MAX_FRAMES_IN_FLIGHT> m_sets;
|
||||
VkDescriptorSetLayout m_set_layout;
|
||||
ShaderType m_shader_type;
|
||||
DescriptorPool& m_pool;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
31
Runtime/Includes/Renderer/Enums.h
git.filemode.normal_file
31
Runtime/Includes/Renderer/Enums.h
git.filemode.normal_file
@@ -0,0 +1,31 @@
|
||||
#ifndef __SCOP_RENDERER_ENUMS__
|
||||
#define __SCOP_RENDERER_ENUMS__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
enum class BufferType
|
||||
{
|
||||
Constant = 0,
|
||||
Staging,
|
||||
HighDynamic, // typically stored in RAM
|
||||
LowDynamic, // typically stored in VRAM
|
||||
|
||||
EndEnum
|
||||
};
|
||||
constexpr std::size_t BufferTypeCount = static_cast<std::size_t>(BufferType::EndEnum);
|
||||
|
||||
enum class ImageType
|
||||
{
|
||||
Color = 0,
|
||||
Cube,
|
||||
Depth,
|
||||
// Maybe add depth array
|
||||
|
||||
EndEnum
|
||||
};
|
||||
constexpr std::size_t ImageTypeCount = static_cast<std::size_t>(ImageType::EndEnum);
|
||||
}
|
||||
|
||||
#endif
|
||||
146
Runtime/Includes/Renderer/Image.h
git.filemode.normal_file
146
Runtime/Includes/Renderer/Image.h
git.filemode.normal_file
@@ -0,0 +1,146 @@
|
||||
#ifndef __SCOP_IMAGE__
|
||||
#define __SCOP_IMAGE__
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <kvf.h>
|
||||
|
||||
#include <Maths/Vec4.h>
|
||||
#include <Renderer/RenderCore.h>
|
||||
#include <Renderer/Buffer.h>
|
||||
#include <Utils/Buffer.h>
|
||||
#include <Renderer/Enums.h>
|
||||
#include <Renderer/Memory/Block.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class Image
|
||||
{
|
||||
public:
|
||||
Image() = default;
|
||||
|
||||
inline void Init(VkImage image, VkFormat format, std::uint32_t width, std::uint32_t height, VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED, std::string_view name = {}) noexcept
|
||||
{
|
||||
m_image = image;
|
||||
m_format = format;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_layout = layout;
|
||||
#ifdef SCOP_HAS_DEBUG_UTILS_FUNCTIONS
|
||||
VkDebugUtilsObjectNameInfoEXT name_info{};
|
||||
name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||
name_info.objectType = VK_OBJECT_TYPE_IMAGE;
|
||||
name_info.objectHandle = reinterpret_cast<std::uint64_t>(m_image);
|
||||
name_info.pObjectName = name.data();
|
||||
RenderCore::Get().vkSetDebugUtilsObjectNameEXT(RenderCore::Get().GetDevice(), &name_info);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Init(ImageType type, std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, bool is_multisampled = false, std::string_view name = {}, bool dedicated_alloc = false);
|
||||
void CreateImageView(VkImageViewType type, VkImageAspectFlags aspectFlags, int layer_count = 1) noexcept;
|
||||
void CreateSampler() noexcept;
|
||||
void TransitionLayout(VkImageLayout new_layout, VkCommandBuffer cmd = VK_NULL_HANDLE);
|
||||
void Clear(VkCommandBuffer cmd, Vec4f color);
|
||||
|
||||
void DestroySampler() noexcept;
|
||||
void DestroyImageView() noexcept;
|
||||
virtual void Destroy() noexcept;
|
||||
|
||||
[[nodiscard]] inline VkImage Get() const noexcept { return m_image; }
|
||||
[[nodiscard]] inline VkImage operator()() const noexcept { return m_image; }
|
||||
[[nodiscard]] inline VkDeviceMemory GetDeviceMemory() const noexcept { return m_memory.memory; }
|
||||
[[nodiscard]] inline VkImageView GetImageView() const noexcept { return m_image_view; }
|
||||
[[nodiscard]] inline VkFormat GetFormat() const noexcept { return m_format; }
|
||||
[[nodiscard]] inline VkImageTiling GetTiling() const noexcept { return m_tiling; }
|
||||
[[nodiscard]] inline VkImageLayout GetLayout() const noexcept { return m_layout; }
|
||||
[[nodiscard]] inline VkSampler GetSampler() const noexcept { return m_sampler; }
|
||||
[[nodiscard]] inline std::uint32_t GetWidth() const noexcept { return m_width; }
|
||||
[[nodiscard]] inline std::uint32_t GetHeight() const noexcept { return m_height; }
|
||||
[[nodiscard]] inline bool IsInit() const noexcept { return m_image != VK_NULL_HANDLE; }
|
||||
[[nodiscard]] inline ImageType GetType() const noexcept { return m_type; }
|
||||
|
||||
[[nodiscard]] inline static std::size_t GetImageCount() noexcept { return s_image_count; }
|
||||
|
||||
virtual ~Image() = default;
|
||||
|
||||
private:
|
||||
inline static std::size_t s_image_count = 0;
|
||||
|
||||
MemoryBlock m_memory = NULL_MEMORY_BLOCK;
|
||||
VkImage m_image = VK_NULL_HANDLE;
|
||||
VkImageView m_image_view = VK_NULL_HANDLE;
|
||||
VkSampler m_sampler = VK_NULL_HANDLE;
|
||||
VkFormat m_format;
|
||||
VkImageTiling m_tiling;
|
||||
VkImageLayout m_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
ImageType m_type;
|
||||
std::uint32_t m_width = 0;
|
||||
std::uint32_t m_height = 0;
|
||||
bool m_is_multisampled = false;
|
||||
};
|
||||
|
||||
class DepthImage : public Image
|
||||
{
|
||||
public:
|
||||
DepthImage() = default;
|
||||
inline void Init(std::uint32_t width, std::uint32_t height, bool is_multisampled = false, std::string_view name = {})
|
||||
{
|
||||
std::vector<VkFormat> candidates = { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT };
|
||||
VkFormat format = kvfFindSupportFormatInCandidates(RenderCore::Get().GetDevice(), candidates.data(), candidates.size(), VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
|
||||
Image::Init(ImageType::Depth, width, height, format, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, is_multisampled, std::move(name));
|
||||
Image::TransitionLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
Image::CreateImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
}
|
||||
~DepthImage() = default;
|
||||
};
|
||||
|
||||
class Texture : public Image
|
||||
{
|
||||
public:
|
||||
Texture() = default;
|
||||
Texture(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format = VK_FORMAT_R8G8B8A8_SRGB, bool is_multisampled = false, std::string_view name = {}, bool dedicated_alloc = false)
|
||||
{
|
||||
Init(std::move(pixels), width, height, format, is_multisampled, std::move(name), dedicated_alloc);
|
||||
}
|
||||
inline void Init(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format = VK_FORMAT_R8G8B8A8_SRGB, bool is_multisampled = false, std::string_view name = {}, bool dedicated_alloc = false)
|
||||
{
|
||||
Image::Init(ImageType::Color, width, height, format, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, is_multisampled, std::move(name), dedicated_alloc);
|
||||
Image::CreateImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
Image::CreateSampler();
|
||||
if(pixels)
|
||||
{
|
||||
TransitionLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
GPUBuffer staging_buffer;
|
||||
std::size_t size = width * height * kvfFormatSize(format);
|
||||
staging_buffer.Init(BufferType::Staging, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, pixels);
|
||||
VkCommandBuffer cmd = kvfCreateCommandBuffer(RenderCore::Get().GetDevice());
|
||||
kvfBeginCommandBuffer(cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||
kvfCopyBufferToImage(cmd, Image::Get(), staging_buffer.Get(), staging_buffer.GetOffset(), VK_IMAGE_ASPECT_COLOR_BIT, { width, height, 1 });
|
||||
RenderCore::Get().vkEndCommandBuffer(cmd);
|
||||
VkFence fence = kvfCreateFence(RenderCore::Get().GetDevice());
|
||||
kvfSubmitSingleTimeCommandBuffer(RenderCore::Get().GetDevice(), cmd, KVF_GRAPHICS_QUEUE, fence);
|
||||
kvfDestroyFence(RenderCore::Get().GetDevice(), fence);
|
||||
staging_buffer.Destroy();
|
||||
}
|
||||
if(!pixels)
|
||||
TransitionLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
else
|
||||
TransitionLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
~Texture() override { Destroy(); }
|
||||
};
|
||||
|
||||
class CubeTexture : public Image
|
||||
{
|
||||
public:
|
||||
CubeTexture() = default;
|
||||
CubeTexture(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format = VK_FORMAT_R8G8B8A8_SRGB, std::string_view name = {})
|
||||
{
|
||||
Init(std::move(pixels), width, height, format, std::move(name));
|
||||
}
|
||||
void Init(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format = VK_FORMAT_R8G8B8A8_SRGB, std::string_view name = {});
|
||||
~CubeTexture() override { Destroy(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
49
Runtime/Includes/Renderer/Memory/Block.h
git.filemode.normal_file
49
Runtime/Includes/Renderer/Memory/Block.h
git.filemode.normal_file
@@ -0,0 +1,49 @@
|
||||
#ifndef __SCOP_VULKAN_MEMORY_BLOCK__
|
||||
#define __SCOP_VULKAN_MEMORY_BLOCK__
|
||||
|
||||
#include <kvf.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class MemoryBlock
|
||||
{
|
||||
friend class MemoryChunk;
|
||||
|
||||
public:
|
||||
MemoryBlock() = default;
|
||||
|
||||
[[nodiscard]] inline bool operator==(const MemoryBlock& rhs) const noexcept
|
||||
{
|
||||
return memory == rhs.memory &&
|
||||
offset == rhs.offset &&
|
||||
size == rhs.size &&
|
||||
free == rhs.free &&
|
||||
map == rhs.map;
|
||||
}
|
||||
|
||||
inline void Swap(MemoryBlock& rhs) noexcept
|
||||
{
|
||||
std::swap(memory, rhs.memory);
|
||||
std::swap(offset, rhs.offset);
|
||||
std::swap(size, rhs.size);
|
||||
std::swap(map, rhs.map);
|
||||
std::swap(free, rhs.free);
|
||||
}
|
||||
|
||||
~MemoryBlock() = default;
|
||||
|
||||
public:
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
VkDeviceSize offset = 0;
|
||||
VkDeviceSize size = 0;
|
||||
void* map = nullptr; // useless if it's a GPU allocation
|
||||
|
||||
private:
|
||||
bool free = false;
|
||||
};
|
||||
|
||||
constexpr MemoryBlock NULL_MEMORY_BLOCK{};
|
||||
}
|
||||
|
||||
#endif
|
||||
39
Runtime/Includes/Renderer/Memory/Chunk.h
git.filemode.normal_file
39
Runtime/Includes/Renderer/Memory/Chunk.h
git.filemode.normal_file
@@ -0,0 +1,39 @@
|
||||
#ifndef __SCOP_VULKAN_MEMORY_CHUNK__
|
||||
#define __SCOP_VULKAN_MEMORY_CHUNK__
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
#include <Renderer/Memory/Block.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class MemoryChunk
|
||||
{
|
||||
public:
|
||||
MemoryChunk(VkDevice device, VkPhysicalDevice physical, VkDeviceSize size, std::int32_t memory_type_index, bool is_dedicated, std::uint32_t& vram_usage, std::uint32_t& vram_host_visible_usage);
|
||||
|
||||
[[nodiscard]] std::optional<MemoryBlock> Allocate(VkDeviceSize size, VkDeviceSize alignment);
|
||||
void Deallocate(const MemoryBlock& block);
|
||||
[[nodiscard]] inline bool Has(const MemoryBlock& block) const noexcept { return block.memory == m_memory; }
|
||||
[[nodiscard]] inline std::int32_t GetMemoryTypeIndex() const noexcept { return m_memory_type_index; }
|
||||
[[nodiscard]] inline bool IsDedicated() const noexcept { return m_is_dedicated; }
|
||||
[[nodiscard]] inline void* GetMap() const noexcept { return p_map; }
|
||||
[[nodiscard]] inline VkDeviceSize GetSize() const noexcept { return m_size; }
|
||||
|
||||
~MemoryChunk();
|
||||
|
||||
protected:
|
||||
std::vector<MemoryBlock> m_blocks;
|
||||
VkDevice m_device = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice m_physical = VK_NULL_HANDLE;
|
||||
VkDeviceMemory m_memory = VK_NULL_HANDLE;
|
||||
void* p_map = nullptr;
|
||||
VkDeviceSize m_size = 0;
|
||||
std::int32_t m_memory_type_index;
|
||||
bool m_is_dedicated;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
52
Runtime/Includes/Renderer/Memory/DeviceAllocator.h
git.filemode.normal_file
52
Runtime/Includes/Renderer/Memory/DeviceAllocator.h
git.filemode.normal_file
@@ -0,0 +1,52 @@
|
||||
#ifndef __SCOP_VULKAN_MEMORY_DEVICE_ALLOCATOR__
|
||||
#define __SCOP_VULKAN_MEMORY_DEVICE_ALLOCATOR__
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
|
||||
#include <Renderer/Memory/Block.h>
|
||||
#include <Renderer/Memory/Chunk.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
constexpr std::size_t SMALL_HEAP_MAX_SIZE = (1024ULL * 1024 * 1024); // 1GB
|
||||
constexpr std::size_t DEFAULT_LARGE_HEAP_BLOCK_SIZE = (256ULL * 1024 * 1024); // 256MiB
|
||||
constexpr std::uint32_t NEW_BLOCK_SIZE_SHIFT_MAX = 3;
|
||||
|
||||
class DeviceAllocator
|
||||
{
|
||||
public:
|
||||
DeviceAllocator() = default;
|
||||
|
||||
void AttachToDevice(VkDevice device, VkPhysicalDevice physical) noexcept;
|
||||
inline void DetachFromDevice() noexcept { m_chunks.clear(); m_device = VK_NULL_HANDLE; m_physical = VK_NULL_HANDLE; }
|
||||
[[nodiscard]] inline std::size_t GetAllocationsCount() const noexcept { return m_allocations_count; }
|
||||
|
||||
[[nodiscard]] MemoryBlock Allocate(VkDeviceSize size, VkDeviceSize alignment, std::int32_t memory_type_index, bool dedicated_chunk = false);
|
||||
void Deallocate(const MemoryBlock& block);
|
||||
|
||||
[[nodiscard]] inline std::uint32_t GetVramUsage() const noexcept { return m_vram_usage; }
|
||||
[[nodiscard]] inline std::uint32_t GetVramHostVisibleUsage() const noexcept { return m_vram_host_visible_usage; }
|
||||
|
||||
~DeviceAllocator() = default;
|
||||
|
||||
private:
|
||||
VkDeviceSize CalcPreferredChunkSize(std::uint32_t mem_type_index);
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<MemoryChunk>> m_chunks;
|
||||
VkPhysicalDeviceMemoryProperties m_mem_props;
|
||||
VkDevice m_device = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice m_physical = VK_NULL_HANDLE;
|
||||
std::size_t m_allocations_count = 0;
|
||||
std::mutex m_alloc_mutex;
|
||||
std::mutex m_dealloc_mutex;
|
||||
std::uint32_t m_vram_usage = 0;
|
||||
std::uint32_t m_vram_host_visible_usage = 0;
|
||||
bool m_last_chunk_creation_failed = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
82
Runtime/Includes/Renderer/Pipelines/Graphics.h
git.filemode.normal_file
82
Runtime/Includes/Renderer/Pipelines/Graphics.h
git.filemode.normal_file
@@ -0,0 +1,82 @@
|
||||
#ifndef __SCOP_GRAPHICS_PIPELINE__
|
||||
#define __SCOP_GRAPHICS_PIPELINE__
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <kvf.h>
|
||||
|
||||
#include <Graphics/Enums.h>
|
||||
#include <Renderer/Image.h>
|
||||
#include <Utils/NonOwningPtr.h>
|
||||
#include <Renderer/Pipelines/Shader.h>
|
||||
#include <Renderer/Pipelines/Pipeline.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
struct GraphicPipelineDescriptor
|
||||
{
|
||||
std::shared_ptr<Shader> vertex_shader;
|
||||
std::shared_ptr<Shader> fragment_shader;
|
||||
std::vector<NonOwningPtr<Texture>> color_attachments;
|
||||
NonOwningPtr<DepthImage> depth = nullptr;
|
||||
NonOwningPtr<class Renderer> renderer = nullptr;
|
||||
std::string name = {};
|
||||
CullMode culling = CullMode::Front;
|
||||
bool no_vertex_inputs = false;
|
||||
bool depth_test_equal = false;
|
||||
bool clear_color_attachments = true;
|
||||
bool wireframe = false;
|
||||
};
|
||||
|
||||
class GraphicPipeline : public Pipeline
|
||||
{
|
||||
friend class Render2DPass;
|
||||
friend class FinalPass;
|
||||
friend class ForwardPass;
|
||||
friend class PostProcessPass;
|
||||
friend class SkyboxPass;
|
||||
|
||||
public:
|
||||
GraphicPipeline() = default;
|
||||
|
||||
inline void Setup(GraphicPipelineDescriptor descriptor)
|
||||
{
|
||||
if(!descriptor.vertex_shader || !descriptor.fragment_shader)
|
||||
FatalError("Vulkan: invalid shaders");
|
||||
m_description = std::move(descriptor);
|
||||
}
|
||||
|
||||
bool BindPipeline(VkCommandBuffer command_buffer, std::size_t framebuffer_index, std::array<float, 4> clear) noexcept;
|
||||
void EndPipeline(VkCommandBuffer command_buffer) noexcept override;
|
||||
void Destroy() noexcept;
|
||||
|
||||
[[nodiscard]] inline VkPipeline GetPipeline() const override { return m_pipeline; }
|
||||
[[nodiscard]] inline VkPipelineLayout GetPipelineLayout() const override { return m_pipeline_layout; }
|
||||
[[nodiscard]] inline VkPipelineBindPoint GetPipelineBindPoint() const override { return VK_PIPELINE_BIND_POINT_GRAPHICS; }
|
||||
[[nodiscard]] inline bool IsPipelineBound() const noexcept { return s_bound_pipeline == this; }
|
||||
[[nodiscard]] inline GraphicPipelineDescriptor& GetDescription() noexcept { return m_description; }
|
||||
|
||||
inline ~GraphicPipeline() noexcept { Destroy(); }
|
||||
|
||||
private:
|
||||
void Init(GraphicPipelineDescriptor descriptor);
|
||||
void CreateFramebuffers(const std::vector<NonOwningPtr<Texture>>& render_targets, bool clear_attachments);
|
||||
void TransitionAttachments(VkCommandBuffer cmd = VK_NULL_HANDLE);
|
||||
|
||||
// Private override to remove access
|
||||
bool BindPipeline(VkCommandBuffer) noexcept override { return false; };
|
||||
|
||||
private:
|
||||
static inline GraphicPipeline* s_bound_pipeline = nullptr;
|
||||
|
||||
GraphicPipelineDescriptor m_description;
|
||||
std::vector<VkFramebuffer> m_framebuffers;
|
||||
std::vector<VkClearValue> m_clears;
|
||||
VkRenderPass m_renderpass = VK_NULL_HANDLE;
|
||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_pipeline_layout = VK_NULL_HANDLE;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
25
Runtime/Includes/Renderer/Pipelines/Pipeline.h
git.filemode.normal_file
25
Runtime/Includes/Renderer/Pipelines/Pipeline.h
git.filemode.normal_file
@@ -0,0 +1,25 @@
|
||||
#ifndef __SCOP_PIPELINE__
|
||||
#define __SCOP_PIPELINE__
|
||||
|
||||
#include <kvf.h>
|
||||
#include <Renderer/RenderCore.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class Pipeline
|
||||
{
|
||||
public:
|
||||
Pipeline() = default;
|
||||
|
||||
inline virtual bool BindPipeline(VkCommandBuffer command_buffer) noexcept { RenderCore::Get().vkCmdBindPipeline(command_buffer, GetPipelineBindPoint(), GetPipeline()); return true; }
|
||||
inline virtual void EndPipeline([[maybe_unused]] VkCommandBuffer command_buffer) noexcept {}
|
||||
|
||||
virtual VkPipeline GetPipeline() const = 0;
|
||||
virtual VkPipelineLayout GetPipelineLayout() const = 0;
|
||||
virtual VkPipelineBindPoint GetPipelineBindPoint() const = 0;
|
||||
|
||||
virtual ~Pipeline() = default;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
123
Runtime/Includes/Renderer/Pipelines/Shader.h
git.filemode.normal_file
123
Runtime/Includes/Renderer/Pipelines/Shader.h
git.filemode.normal_file
@@ -0,0 +1,123 @@
|
||||
#ifndef __SCOP_SHADER__
|
||||
#define __SCOP_SHADER__
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <kvf.h>
|
||||
|
||||
#include <Maths/Mat4.h>
|
||||
#include <Utils/NonOwningPtr.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
struct ShaderSetLayout
|
||||
{
|
||||
std::unordered_map<int, VkDescriptorType> binds;
|
||||
|
||||
ShaderSetLayout(std::unordered_map<int, VkDescriptorType> b) : binds(std::move(b)) {}
|
||||
|
||||
inline bool operator==(const ShaderSetLayout& rhs) const { return binds == rhs.binds; }
|
||||
};
|
||||
|
||||
struct ShaderPushConstantLayout
|
||||
{
|
||||
std::size_t offset;
|
||||
std::size_t size;
|
||||
|
||||
ShaderPushConstantLayout(std::size_t o, std::size_t s) : offset(o), size(s) {}
|
||||
};
|
||||
|
||||
struct ShaderLayout
|
||||
{
|
||||
std::unordered_map<int, ShaderSetLayout> set_layouts;
|
||||
std::vector<ShaderPushConstantLayout> push_constants;
|
||||
|
||||
ShaderLayout(std::unordered_map<int, ShaderSetLayout> s, std::vector<ShaderPushConstantLayout> pc) : set_layouts(std::move(s)), push_constants(std::move(pc)) {}
|
||||
};
|
||||
|
||||
enum class ShaderType
|
||||
{
|
||||
Vertex,
|
||||
Fragment,
|
||||
Compute
|
||||
};
|
||||
|
||||
struct ShaderPipelineLayoutPart
|
||||
{
|
||||
std::vector<VkPushConstantRange> push_constants;
|
||||
std::vector<VkDescriptorSetLayout> set_layouts;
|
||||
};
|
||||
|
||||
class Shader
|
||||
{
|
||||
public:
|
||||
Shader(const std::vector<std::uint32_t>& bytecode, ShaderType type, ShaderLayout layout, std::string shader_name = {});
|
||||
|
||||
[[nodiscard]] inline const ShaderLayout& GetShaderLayout() const { return m_layout; }
|
||||
[[nodiscard]] inline const std::vector<std::uint32_t>& GetByteCode() const noexcept { return m_bytecode; }
|
||||
[[nodiscard]] inline const ShaderPipelineLayoutPart& GetPipelineLayout() const noexcept { return m_pipeline_layout_part; }
|
||||
[[nodiscard]] inline VkShaderModule GetShaderModule() const noexcept { return m_module; }
|
||||
[[nodiscard]] inline VkShaderStageFlagBits GetShaderStage() const noexcept { return m_stage; }
|
||||
[[nodiscard]] inline NonOwningPtr<class GraphicPipeline> GetGraphicPipelineInUse() const noexcept { return p_pipeline_in_use; }
|
||||
|
||||
inline void SetPipelineInUse(NonOwningPtr<class GraphicPipeline> pipeline) noexcept { p_pipeline_in_use = pipeline; }
|
||||
|
||||
void Destroy();
|
||||
|
||||
~Shader();
|
||||
|
||||
private:
|
||||
void GeneratePipelineLayout(ShaderLayout layout);
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
ShaderLayout m_layout;
|
||||
ShaderPipelineLayoutPart m_pipeline_layout_part;
|
||||
std::vector<std::uint32_t> m_bytecode;
|
||||
std::vector<VkDescriptorSetLayout> m_set_layouts;
|
||||
VkShaderStageFlagBits m_stage;
|
||||
VkShaderModule m_module = VK_NULL_HANDLE;
|
||||
NonOwningPtr<class GraphicPipeline> p_pipeline_in_use = nullptr;
|
||||
};
|
||||
|
||||
std::shared_ptr<Shader> LoadShaderFromFile(const std::filesystem::path& filepath, ShaderType type, ShaderLayout layout);
|
||||
|
||||
static const ShaderLayout DefaultForwardVertexShaderLayout(
|
||||
{
|
||||
{ 0,
|
||||
ShaderSetLayout({
|
||||
{ 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
})
|
||||
}
|
||||
}, { ShaderPushConstantLayout({ 0, sizeof(Mat4f) * 2 }) }
|
||||
);
|
||||
|
||||
static const Scop::ShaderLayout DefaultShaderLayout(
|
||||
{
|
||||
{ 1,
|
||||
Scop::ShaderSetLayout({
|
||||
{ 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER }
|
||||
})
|
||||
}
|
||||
}, {}
|
||||
);
|
||||
|
||||
static const Scop::ShaderLayout PostProcessShaderLayout(
|
||||
{
|
||||
{ 0,
|
||||
Scop::ShaderSetLayout({
|
||||
{ 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER }
|
||||
})
|
||||
}
|
||||
}, {}
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
80
Runtime/Includes/Renderer/RenderCore.h
git.filemode.normal_file
80
Runtime/Includes/Renderer/RenderCore.h
git.filemode.normal_file
@@ -0,0 +1,80 @@
|
||||
#ifndef __SCOP_RENDER_CORE__
|
||||
#define __SCOP_RENDER_CORE__
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
#include <kvf.h>
|
||||
|
||||
#include <Renderer/Memory/DeviceAllocator.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
constexpr const int MAX_FRAMES_IN_FLIGHT = 3;
|
||||
|
||||
constexpr const int DEFAULT_VERTEX_SHADER_ID = 0;
|
||||
constexpr const int DEFAULT_FRAGMENT_SHADER_ID = 1;
|
||||
constexpr const int BASIC_FRAGMENT_SHADER_ID = 2;
|
||||
|
||||
std::optional<std::uint32_t> FindMemoryType(std::uint32_t type_filter, VkMemoryPropertyFlags properties, bool error = true);
|
||||
|
||||
#if defined(DEBUG) && defined(VK_EXT_debug_utils)
|
||||
#define SCOP_HAS_DEBUG_UTILS_FUNCTIONS
|
||||
#endif
|
||||
|
||||
class RenderCore
|
||||
{
|
||||
public:
|
||||
RenderCore();
|
||||
|
||||
[[nodiscard]] inline VkInstance GetInstance() const noexcept { return m_instance; }
|
||||
[[nodiscard]] inline VkInstance& GetInstanceRef() noexcept { return m_instance; }
|
||||
[[nodiscard]] inline VkDevice GetDevice() const noexcept { return m_device; }
|
||||
[[nodiscard]] inline VkPhysicalDevice GetPhysicalDevice() const noexcept { return m_physical_device; }
|
||||
[[nodiscard]] inline DeviceAllocator& GetAllocator() noexcept { return m_allocator; }
|
||||
[[nodiscard]] inline bool StackSubmits() const noexcept { return m_stack_submits; }
|
||||
[[nodiscard]] inline class DescriptorPoolManager& GetDescriptorPoolManager() noexcept { return *p_descriptor_pool_manager; }
|
||||
|
||||
[[nodiscard]] inline std::shared_ptr<class Shader> GetDefaultVertexShader() const { return m_internal_shaders[DEFAULT_VERTEX_SHADER_ID]; }
|
||||
[[nodiscard]] inline std::shared_ptr<class Shader> GetBasicFragmentShader() const { return m_internal_shaders[BASIC_FRAGMENT_SHADER_ID]; }
|
||||
[[nodiscard]] inline std::shared_ptr<class Shader> GetDefaultFragmentShader() const { return m_internal_shaders[DEFAULT_FRAGMENT_SHADER_ID]; }
|
||||
|
||||
inline void WaitDeviceIdle() const noexcept { vkDeviceWaitIdle(m_device); }
|
||||
inline void WaitQueueIdle(KvfQueueType queue) const noexcept { vkQueueWaitIdle(kvfGetDeviceQueue(m_device, queue)); }
|
||||
|
||||
inline static bool IsInit() noexcept { return s_instance != nullptr; }
|
||||
inline static RenderCore& Get() noexcept { return *s_instance; }
|
||||
|
||||
inline void ShouldStackSubmits(bool should) noexcept { m_stack_submits = should; }
|
||||
|
||||
#define SCOP_VULKAN_GLOBAL_FUNCTION(fn) PFN_##fn fn = nullptr;
|
||||
#define SCOP_VULKAN_INSTANCE_FUNCTION(fn) PFN_##fn fn = nullptr;
|
||||
#define SCOP_VULKAN_DEVICE_FUNCTION(fn) PFN_##fn fn = nullptr;
|
||||
#include <Renderer/Vulkan/VulkanDefs.h>
|
||||
#undef SCOP_VULKAN_GLOBAL_FUNCTION
|
||||
#undef SCOP_VULKAN_INSTANCE_FUNCTION
|
||||
#undef SCOP_VULKAN_DEVICE_FUNCTION
|
||||
|
||||
~RenderCore();
|
||||
|
||||
private:
|
||||
void LoadKVFGlobalVulkanFunctionPointers() const noexcept;
|
||||
void LoadKVFInstanceVulkanFunctionPointers() const noexcept;
|
||||
void LoadKVFDeviceVulkanFunctionPointers() const noexcept;
|
||||
|
||||
private:
|
||||
static RenderCore* s_instance;
|
||||
|
||||
std::array<std::shared_ptr<class Shader>, 3> m_internal_shaders;
|
||||
DeviceAllocator m_allocator;
|
||||
VkInstance m_instance = VK_NULL_HANDLE;
|
||||
VkDevice m_device = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice m_physical_device = VK_NULL_HANDLE;
|
||||
std::unique_ptr<class DescriptorPoolManager> p_descriptor_pool_manager;
|
||||
bool m_stack_submits = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
31
Runtime/Includes/Renderer/RenderPasses/2DPass.h
git.filemode.normal_file
31
Runtime/Includes/Renderer/RenderPasses/2DPass.h
git.filemode.normal_file
@@ -0,0 +1,31 @@
|
||||
#ifndef __SCOP_2D_PASS__
|
||||
#define __SCOP_2D_PASS__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <Renderer/Descriptor.h>
|
||||
#include <Renderer/Pipelines/Shader.h>
|
||||
#include <Renderer/Pipelines/Graphics.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class Render2DPass
|
||||
{
|
||||
public:
|
||||
Render2DPass() = default;
|
||||
void Init();
|
||||
void Pass(class Scene& scene, class Renderer& renderer, class Texture& render_target);
|
||||
void Destroy();
|
||||
~Render2DPass() = default;
|
||||
|
||||
private:
|
||||
GraphicPipeline m_pipeline;
|
||||
std::shared_ptr<DescriptorSet> p_viewer_data_set;
|
||||
std::shared_ptr<UniformBuffer> p_viewer_data_buffer;
|
||||
std::shared_ptr<DescriptorSet> p_texture_set;
|
||||
std::shared_ptr<Shader> p_vertex_shader;
|
||||
std::shared_ptr<Shader> p_fragment_shader;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
29
Runtime/Includes/Renderer/RenderPasses/FinalPass.h
git.filemode.normal_file
29
Runtime/Includes/Renderer/RenderPasses/FinalPass.h
git.filemode.normal_file
@@ -0,0 +1,29 @@
|
||||
#ifndef __SCOP_FINAL_PASS__
|
||||
#define __SCOP_FINAL_PASS__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <Renderer/Descriptor.h>
|
||||
#include <Renderer/Pipelines/Shader.h>
|
||||
#include <Renderer/Pipelines/Graphics.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class FinalPass
|
||||
{
|
||||
public:
|
||||
FinalPass() = default;
|
||||
void Init();
|
||||
void Pass(class Scene& scene, class Renderer& renderer, class Texture& render_target);
|
||||
void Destroy();
|
||||
~FinalPass() = default;
|
||||
|
||||
private:
|
||||
GraphicPipeline m_pipeline;
|
||||
std::shared_ptr<DescriptorSet> p_set;
|
||||
std::shared_ptr<Shader> p_vertex_shader;
|
||||
std::shared_ptr<Shader> p_fragment_shader;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
15
Runtime/Includes/Renderer/RenderPasses/ForwardPass.h
git.filemode.normal_file
15
Runtime/Includes/Renderer/RenderPasses/ForwardPass.h
git.filemode.normal_file
@@ -0,0 +1,15 @@
|
||||
#ifndef __SCOP_FORWARD_PASS__
|
||||
#define __SCOP_FORWARD_PASS__
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class ForwardPass
|
||||
{
|
||||
public:
|
||||
ForwardPass() = default;
|
||||
void Pass(class Scene& scene, class Renderer& renderer, class Texture& render_target);
|
||||
~ForwardPass() = default;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
32
Runtime/Includes/Renderer/RenderPasses/Passes.h
git.filemode.normal_file
32
Runtime/Includes/Renderer/RenderPasses/Passes.h
git.filemode.normal_file
@@ -0,0 +1,32 @@
|
||||
#ifndef __SCOP_PASSES__
|
||||
#define __SCOP_PASSES__
|
||||
|
||||
#include <Renderer/Image.h>
|
||||
#include <Renderer/RenderPasses/SkyboxPass.h>
|
||||
#include <Renderer/RenderPasses/ForwardPass.h>
|
||||
#include <Renderer/RenderPasses/FinalPass.h>
|
||||
#include <Renderer/RenderPasses/PostProcessPass.h>
|
||||
#include <Renderer/RenderPasses/2DPass.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class RenderPasses
|
||||
{
|
||||
public:
|
||||
RenderPasses() = default;
|
||||
void Init();
|
||||
void Pass(class Scene& scene, class Renderer& renderer);
|
||||
void Destroy();
|
||||
~RenderPasses() = default;
|
||||
|
||||
private:
|
||||
SkyboxPass m_skybox;
|
||||
Render2DPass m_2Dpass;
|
||||
PostProcessPass m_post_process;
|
||||
FinalPass m_final;
|
||||
Texture m_main_render_texture;
|
||||
ForwardPass m_forward;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
28
Runtime/Includes/Renderer/RenderPasses/PostProcessPass.h
git.filemode.normal_file
28
Runtime/Includes/Renderer/RenderPasses/PostProcessPass.h
git.filemode.normal_file
@@ -0,0 +1,28 @@
|
||||
#ifndef __SCOP_POST_PROCESS_PASS__
|
||||
#define __SCOP_POST_PROCESS_PASS__
|
||||
|
||||
#include <Renderer/Descriptor.h>
|
||||
#include <Renderer/Pipelines/Shader.h>
|
||||
#include <Renderer/Pipelines/Graphics.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class PostProcessPass
|
||||
{
|
||||
public:
|
||||
PostProcessPass() = default;
|
||||
void Init();
|
||||
void Pass(class Scene& scene, class Renderer& renderer, class Texture& render_target);
|
||||
void Destroy();
|
||||
|
||||
[[nodiscard]] inline Texture& GetProcessTexture() noexcept { return m_render_texture; }
|
||||
~PostProcessPass() = default;
|
||||
|
||||
private:
|
||||
GraphicPipeline m_pipeline;
|
||||
Texture m_render_texture;
|
||||
std::shared_ptr<Shader> p_vertex_shader;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
30
Runtime/Includes/Renderer/RenderPasses/SkyboxPass.h
git.filemode.normal_file
30
Runtime/Includes/Renderer/RenderPasses/SkyboxPass.h
git.filemode.normal_file
@@ -0,0 +1,30 @@
|
||||
#ifndef __SCOP_SKYBOX_PASS__
|
||||
#define __SCOP_SKYBOX_PASS__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <Renderer/Descriptor.h>
|
||||
#include <Renderer/Pipelines/Shader.h>
|
||||
#include <Renderer/Pipelines/Graphics.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class SkyboxPass
|
||||
{
|
||||
public:
|
||||
SkyboxPass() = default;
|
||||
void Init();
|
||||
void Pass(class Scene& scene, class Renderer& renderer, class Texture& render_target);
|
||||
void Destroy();
|
||||
~SkyboxPass() = default;
|
||||
|
||||
private:
|
||||
GraphicPipeline m_pipeline;
|
||||
std::shared_ptr<DescriptorSet> p_set;
|
||||
std::shared_ptr<Shader> p_vertex_shader;
|
||||
std::shared_ptr<Shader> p_fragment_shader;
|
||||
std::shared_ptr<class Mesh> m_cube;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
55
Runtime/Includes/Renderer/Renderer.h
git.filemode.normal_file
55
Runtime/Includes/Renderer/Renderer.h
git.filemode.normal_file
@@ -0,0 +1,55 @@
|
||||
#ifndef __SCOP_RENDERER__
|
||||
#define __SCOP_RENDERER__
|
||||
|
||||
#include <Platform/Window.h>
|
||||
#include <Utils/NonOwningPtr.h>
|
||||
#include <Renderer/Swapchain.h>
|
||||
#include <Renderer/RenderCore.h>
|
||||
#include <Renderer/Image.h>
|
||||
|
||||
#include <kvf.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <Core/EventBus.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
Renderer() = default;
|
||||
|
||||
void Init(NonOwningPtr<Window> window);
|
||||
|
||||
void BeginFrame();
|
||||
void EndFrame();
|
||||
|
||||
[[nodiscard]] inline VkSemaphore GetImageAvailableSemaphore(int index) const noexcept { return m_image_available_semaphores[index]; }
|
||||
[[nodiscard]] inline VkSemaphore GetRenderFinishedSemaphore(int index) const noexcept { return m_render_finished_semaphores[index]; }
|
||||
[[nodiscard]] inline VkCommandBuffer GetCommandBuffer(int index) const noexcept { return m_cmd_buffers[index]; }
|
||||
[[nodiscard]] inline VkCommandBuffer GetActiveCommandBuffer() const noexcept { return m_cmd_buffers[m_current_frame_index]; }
|
||||
[[nodiscard]] inline std::size_t& GetDrawCallsCounterRef() noexcept { return m_drawcalls; }
|
||||
[[nodiscard]] inline std::size_t& GetPolygonDrawnCounterRef() noexcept { return m_polygons_drawn; }
|
||||
[[nodiscard]] inline std::size_t GetCurrentFrameIndex() const noexcept { return m_current_frame_index; }
|
||||
[[nodiscard]] inline NonOwningPtr<Window> GetWindow() const noexcept { return p_window; }
|
||||
[[nodiscard]] inline const Swapchain& GetSwapchain() const noexcept { return m_swapchain; }
|
||||
|
||||
void Destroy() noexcept;
|
||||
|
||||
~Renderer() = default;
|
||||
|
||||
private:
|
||||
Swapchain m_swapchain;
|
||||
std::vector<VkSemaphore> m_render_finished_semaphores;
|
||||
std::array<VkSemaphore, MAX_FRAMES_IN_FLIGHT> m_image_available_semaphores;
|
||||
std::array<VkCommandBuffer, MAX_FRAMES_IN_FLIGHT> m_cmd_buffers;
|
||||
std::array<VkFence, MAX_FRAMES_IN_FLIGHT> m_cmd_fences;
|
||||
NonOwningPtr<Window> p_window;
|
||||
std::uint32_t m_current_frame_index = 0;
|
||||
std::size_t m_polygons_drawn = 0;
|
||||
std::size_t m_drawcalls = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
22
Runtime/Includes/Renderer/ScenesRenderer.h
git.filemode.normal_file
22
Runtime/Includes/Renderer/ScenesRenderer.h
git.filemode.normal_file
@@ -0,0 +1,22 @@
|
||||
#ifndef __SCOP_SCENES_RENDERER__
|
||||
#define __SCOP_SCENES_RENDERER__
|
||||
|
||||
#include <Renderer/RenderPasses/Passes.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class SceneRenderer
|
||||
{
|
||||
public:
|
||||
SceneRenderer() = default;
|
||||
void Init();
|
||||
void Render(class Scene& scene, class Renderer& renderer); // TODO : add RTT support
|
||||
void Destroy();
|
||||
~SceneRenderer() = default;
|
||||
|
||||
private:
|
||||
RenderPasses m_passes;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
43
Runtime/Includes/Renderer/Swapchain.h
git.filemode.normal_file
43
Runtime/Includes/Renderer/Swapchain.h
git.filemode.normal_file
@@ -0,0 +1,43 @@
|
||||
#ifndef __SCOP_SWAPCHAIN__
|
||||
#define __SCOP_SWAPCHAIN__
|
||||
|
||||
#include <Utils/NonOwningPtr.h>
|
||||
#include <Renderer/Image.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class Swapchain
|
||||
{
|
||||
public:
|
||||
Swapchain() = default;
|
||||
|
||||
void Init(NonOwningPtr<class Window> window);
|
||||
void AquireFrame(VkSemaphore signal);
|
||||
void Present(VkSemaphore wait) noexcept;
|
||||
void Destroy();
|
||||
|
||||
[[nodiscard]] inline VkSwapchainKHR Get() const noexcept { return m_swapchain; }
|
||||
[[nodiscard]] inline VkSurfaceKHR GetSurface() const noexcept { return m_surface; }
|
||||
[[nodiscard]] inline std::uint32_t GetImagesCount() const noexcept { return m_images_count; }
|
||||
[[nodiscard]] inline std::uint32_t GetMinImagesCount() const noexcept { return m_min_images_count; }
|
||||
[[nodiscard]] inline std::uint32_t GetImageIndex() const noexcept { return m_current_image_index; }
|
||||
[[nodiscard]] inline const std::vector<Image>& GetSwapchainImages() const { return m_swapchain_images; }
|
||||
|
||||
~Swapchain() = default;
|
||||
|
||||
private:
|
||||
void CreateSwapchain();
|
||||
|
||||
private:
|
||||
std::vector<Image> m_swapchain_images;
|
||||
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
|
||||
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
||||
NonOwningPtr<class Window> p_window;
|
||||
std::uint32_t m_images_count = 0;
|
||||
std::uint32_t m_min_images_count = 0;
|
||||
std::uint32_t m_current_image_index = 0;
|
||||
bool m_resize = false;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
29
Runtime/Includes/Renderer/Vertex.h
git.filemode.normal_file
29
Runtime/Includes/Renderer/Vertex.h
git.filemode.normal_file
@@ -0,0 +1,29 @@
|
||||
#ifndef __SCOP_VERTEX__
|
||||
#define __SCOP_VERTEX__
|
||||
|
||||
#include <kvf.h>
|
||||
#include <array>
|
||||
#include <Maths/Vec4.h>
|
||||
#include <Maths/Vec2.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
struct Vertex
|
||||
{
|
||||
alignas(16) Vec4f position = Vec4f{ 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
alignas(16) Vec4f color = Vec4f{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
alignas(16) Vec4f normal = Vec4f{ 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
alignas(16) Vec2f uv = Vec2f{ 0.0f, 0.0f };
|
||||
|
||||
Vertex() = default;
|
||||
Vertex(Vec4f p, Vec4f c, Vec4f n, Vec2f u) : position(std::move(p)), color(std::move(c)), normal(std::move(n)), uv(std::move(u)) {}
|
||||
Vertex(Vec4f p, Vec4f n, Vec2f u) : position(std::move(p)), normal(std::move(n)), uv(std::move(u)) {}
|
||||
|
||||
[[nodiscard]] inline static VkVertexInputBindingDescription GetBindingDescription();
|
||||
[[nodiscard]] inline static std::array<VkVertexInputAttributeDescription, 4> GetAttributeDescriptions();
|
||||
};
|
||||
}
|
||||
|
||||
#include <Renderer/Vertex.inl>
|
||||
|
||||
#endif
|
||||
41
Runtime/Includes/Renderer/Vertex.inl
git.filemode.normal_file
41
Runtime/Includes/Renderer/Vertex.inl
git.filemode.normal_file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include <Renderer/Vertex.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
VkVertexInputBindingDescription Vertex::GetBindingDescription()
|
||||
{
|
||||
VkVertexInputBindingDescription binding_description{};
|
||||
binding_description.binding = 0;
|
||||
binding_description.stride = sizeof(Vertex);
|
||||
binding_description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
return binding_description;
|
||||
}
|
||||
|
||||
std::array<VkVertexInputAttributeDescription, 4> Vertex::GetAttributeDescriptions()
|
||||
{
|
||||
std::array<VkVertexInputAttributeDescription, 4> attribute_descriptions;
|
||||
|
||||
attribute_descriptions[0].binding = 0;
|
||||
attribute_descriptions[0].location = 0;
|
||||
attribute_descriptions[0].format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
attribute_descriptions[0].offset = offsetof(Vertex, position);
|
||||
|
||||
attribute_descriptions[1].binding = 0;
|
||||
attribute_descriptions[1].location = 1;
|
||||
attribute_descriptions[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
attribute_descriptions[1].offset = offsetof(Vertex, color);
|
||||
|
||||
attribute_descriptions[2].binding = 0;
|
||||
attribute_descriptions[2].location = 2;
|
||||
attribute_descriptions[2].format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
attribute_descriptions[2].offset = offsetof(Vertex, normal);
|
||||
|
||||
attribute_descriptions[3].binding = 0;
|
||||
attribute_descriptions[3].location = 3;
|
||||
attribute_descriptions[3].format = VK_FORMAT_R32G32_SFLOAT;
|
||||
attribute_descriptions[3].offset = offsetof(Vertex, uv);
|
||||
|
||||
return attribute_descriptions;
|
||||
}
|
||||
}
|
||||
21
Runtime/Includes/Renderer/ViewerData.h
git.filemode.normal_file
21
Runtime/Includes/Renderer/ViewerData.h
git.filemode.normal_file
@@ -0,0 +1,21 @@
|
||||
#ifndef __SCOP_VIEWER_DATA__
|
||||
#define __SCOP_VIEWER_DATA__
|
||||
|
||||
#include <Maths/Mat4.h>
|
||||
#include <Maths/Vec3.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
struct ViewerData
|
||||
{
|
||||
Mat4f projection_matrix;
|
||||
Mat4f inv_projection_matrix;
|
||||
Mat4f view_matrix;
|
||||
Mat4f inv_view_matrix;
|
||||
Mat4f view_proj_matrix;
|
||||
Mat4f inv_view_proj_matrix;
|
||||
alignas(16) Vec3f camera_position;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
127
Runtime/Includes/Renderer/Vulkan/VulkanDefs.h
git.filemode.normal_file
127
Runtime/Includes/Renderer/Vulkan/VulkanDefs.h
git.filemode.normal_file
@@ -0,0 +1,127 @@
|
||||
// No header guard
|
||||
|
||||
#ifdef VK_VERSION_1_0
|
||||
#ifdef SCOP_VULKAN_GLOBAL_FUNCTION
|
||||
SCOP_VULKAN_GLOBAL_FUNCTION(vkCreateInstance)
|
||||
SCOP_VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceExtensionProperties)
|
||||
SCOP_VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceLayerProperties)
|
||||
SCOP_VULKAN_GLOBAL_FUNCTION(vkGetInstanceProcAddr)
|
||||
#endif
|
||||
|
||||
#ifdef SCOP_VULKAN_INSTANCE_FUNCTION
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkCreateDevice)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkDestroyInstance)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkEnumerateDeviceExtensionProperties)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkGetDeviceProcAddr)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFormatProperties)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceImageFormatProperties)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties)
|
||||
#ifdef DEBUG
|
||||
#ifdef VK_EXT_debug_utils
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkSetDebugUtilsObjectNameEXT)
|
||||
//SCOP_VULKAN_INSTANCE_FUNCTION(vkSetDebugUtilsObjectTagEXT)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SCOP_VULKAN_DEVICE_FUNCTION
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkAllocateCommandBuffers)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkAllocateDescriptorSets)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkAllocateMemory)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkBeginCommandBuffer)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkBindBufferMemory)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkBindImageMemory)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdBeginRenderPass)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdBindDescriptorSets)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdBindIndexBuffer)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdBindPipeline)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdBindVertexBuffers)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdClearAttachments)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdClearColorImage)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdClearDepthStencilImage)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdCopyBuffer)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdCopyBufferToImage)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdCopyImage)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdCopyImageToBuffer)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdDraw)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdDrawIndexed)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdEndRenderPass)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdPipelineBarrier)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdPushConstants)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdSetScissor)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCmdSetViewport)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateBuffer)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateCommandPool)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateDescriptorPool)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateDescriptorSetLayout)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateFence)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateFramebuffer)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateGraphicsPipelines)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateImage)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateImageView)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreatePipelineLayout)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateRenderPass)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateSampler)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateSemaphore)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateShaderModule)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyBuffer)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyCommandPool)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyDescriptorPool)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyDescriptorSetLayout)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyDevice)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyFence)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyFramebuffer)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyImage)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyImageView)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyPipeline)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyPipelineLayout)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyRenderPass)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroySampler)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroySemaphore)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroyShaderModule)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDeviceWaitIdle)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkEndCommandBuffer)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkFlushMappedMemoryRanges)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkFreeCommandBuffers)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkFreeMemory)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkGetBufferMemoryRequirements)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkGetDeviceMemoryCommitment)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkGetDeviceQueue)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkGetFenceStatus)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkGetImageMemoryRequirements)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkGetImageSubresourceLayout)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkInvalidateMappedMemoryRanges)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkMapMemory)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkQueueSubmit)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkQueueWaitIdle)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkResetCommandBuffer)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkResetDescriptorPool)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkResetEvent)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkResetFences)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkUnmapMemory)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkUpdateDescriptorSets)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkWaitForFences)
|
||||
#endif
|
||||
#endif
|
||||
#ifdef VK_KHR_swapchain
|
||||
#ifdef SCOP_VULKAN_DEVICE_FUNCTION
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkAcquireNextImageKHR)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkCreateSwapchainKHR)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkDestroySwapchainKHR)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkGetSwapchainImagesKHR)
|
||||
SCOP_VULKAN_DEVICE_FUNCTION(vkQueuePresentKHR)
|
||||
#endif
|
||||
#endif
|
||||
#ifdef VK_KHR_surface
|
||||
#ifdef SCOP_VULKAN_INSTANCE_FUNCTION
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkDestroySurfaceKHR)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceCapabilitiesKHR)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR)
|
||||
SCOP_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR)
|
||||
#endif
|
||||
#endif
|
||||
15
Runtime/Includes/ScopCore.h
git.filemode.normal_file
15
Runtime/Includes/ScopCore.h
git.filemode.normal_file
@@ -0,0 +1,15 @@
|
||||
#ifndef __SCOP_CORE__
|
||||
#define __SCOP_CORE__
|
||||
|
||||
#include <Core/Engine.h>
|
||||
#include <Core/CLI.h>
|
||||
#include <Core/EventBase.h>
|
||||
#include <Core/EventBus.h>
|
||||
#include <Core/EventListener.h>
|
||||
#include <Core/Format.h>
|
||||
#include <Core/Logs.h>
|
||||
#include <Core/NativeScript.h>
|
||||
#include <Core/Script.h>
|
||||
#include <Core/UUID.h>
|
||||
|
||||
#endif
|
||||
16
Runtime/Includes/ScopGraphics.h
git.filemode.normal_file
16
Runtime/Includes/ScopGraphics.h
git.filemode.normal_file
@@ -0,0 +1,16 @@
|
||||
#ifndef __SCOP_GRAPHICS__
|
||||
#define __SCOP_GRAPHICS__
|
||||
|
||||
#include <Graphics/Actor.h>
|
||||
#include <Graphics/Material.h>
|
||||
#include <Graphics/Mesh.h>
|
||||
#include <Graphics/Model.h>
|
||||
#include <Graphics/Scene.h>
|
||||
#include <Graphics/MeshFactory.h>
|
||||
#include <Graphics/Cameras/Base.h>
|
||||
#include <Graphics/Cameras/FirstPerson3D.h>
|
||||
#include <Graphics/Loaders/OBJ.h>
|
||||
#include <Graphics/Loaders/BMP.h>
|
||||
#include <Graphics/Narrator.h>
|
||||
|
||||
#endif
|
||||
14
Runtime/Includes/ScopMaths.h
git.filemode.normal_file
14
Runtime/Includes/ScopMaths.h
git.filemode.normal_file
@@ -0,0 +1,14 @@
|
||||
#ifndef __SCOP_MATHS__
|
||||
#define __SCOP_MATHS__
|
||||
|
||||
#include <Maths/Vec2.h>
|
||||
#include <Maths/Vec3.h>
|
||||
#include <Maths/Vec4.h>
|
||||
#include <Maths/MathsUtils.h>
|
||||
#include <Maths/Mat4.h>
|
||||
#include <Maths/Angles.h>
|
||||
#include <Maths/Constants.h>
|
||||
#include <Maths/EulerAngles.h>
|
||||
#include <Maths/Quaternions.h>
|
||||
|
||||
#endif
|
||||
7
Runtime/Includes/ScopPlatform.h
git.filemode.normal_file
7
Runtime/Includes/ScopPlatform.h
git.filemode.normal_file
@@ -0,0 +1,7 @@
|
||||
#ifndef __SCOP_PLATFORM__
|
||||
#define __SCOP_PLATFORM__
|
||||
|
||||
#include <Platform/Inputs.h>
|
||||
#include <Platform/Window.h>
|
||||
|
||||
#endif
|
||||
13
Runtime/Includes/ScopRenderer.h
git.filemode.normal_file
13
Runtime/Includes/ScopRenderer.h
git.filemode.normal_file
@@ -0,0 +1,13 @@
|
||||
#ifndef __SCOP_RENDERER__
|
||||
#define __SCOP_RENDERER__
|
||||
|
||||
#include <Renderer/Pipelines/Graphics.h>
|
||||
#include <Renderer/Pipelines/Pipeline.h>
|
||||
#include <Renderer/Pipelines/Shader.h>
|
||||
#include <Renderer/Image.h>
|
||||
#include <Renderer/RenderCore.h>
|
||||
#include <Renderer/Renderer.h>
|
||||
#include <Renderer/ScenesRenderer.h>
|
||||
#include <Renderer/Vertex.h>
|
||||
|
||||
#endif
|
||||
9
Runtime/Includes/ScopUtils.h
git.filemode.normal_file
9
Runtime/Includes/ScopUtils.h
git.filemode.normal_file
@@ -0,0 +1,9 @@
|
||||
#ifndef __SCOP_UTILS__
|
||||
#define __SCOP_UTILS__
|
||||
|
||||
#include <Utils/Ansi.h>
|
||||
#include <Utils/NonCopyable.h>
|
||||
#include <Utils/NonMovable.h>
|
||||
#include <Utils/NonOwningPtr.h>
|
||||
|
||||
#endif
|
||||
44
Runtime/Includes/Utils/Ansi.h
git.filemode.normal_file
44
Runtime/Includes/Utils/Ansi.h
git.filemode.normal_file
@@ -0,0 +1,44 @@
|
||||
#ifndef __SCOPE_UTILS_ANSI__
|
||||
#define __SCOPE_UTILS_ANSI__
|
||||
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
enum class Ansi : std::uint32_t
|
||||
{
|
||||
red = 31,
|
||||
green = 32,
|
||||
blue = 34,
|
||||
def = 0,
|
||||
black = 30,
|
||||
yellow = 33,
|
||||
magenta = 35,
|
||||
cyan = 36,
|
||||
white = 37,
|
||||
bg_red = 41,
|
||||
bg_green = 42,
|
||||
bg_blue = 44,
|
||||
bg_def = 0,
|
||||
bg_black = 40,
|
||||
bg_yellow = 43,
|
||||
bg_magenta = 45,
|
||||
bg_cyan = 46,
|
||||
bg_white = 47,
|
||||
reset = 0,
|
||||
bold = 1,
|
||||
underline = 4,
|
||||
inverse = 7,
|
||||
bold_off = 21,
|
||||
underline_off = 24,
|
||||
inverse_off = 27
|
||||
};
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, Scop::Ansi ansi)
|
||||
{
|
||||
return os << "\033[1;" << std::to_string(static_cast<std::uint32_t>(ansi)) << "m";
|
||||
}
|
||||
|
||||
#endif
|
||||
101
Runtime/Includes/Utils/Buffer.h
git.filemode.normal_file
101
Runtime/Includes/Utils/Buffer.h
git.filemode.normal_file
@@ -0,0 +1,101 @@
|
||||
#ifndef __SCOP_CPU_BUFFER__
|
||||
#define __SCOP_CPU_BUFFER__
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <Core/Logs.h>
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class CPUBuffer
|
||||
{
|
||||
public:
|
||||
CPUBuffer() {}
|
||||
CPUBuffer(std::size_t size) try : m_data(size > 0 ? std::make_unique<std::uint8_t[]>(size) : nullptr), m_size(size)
|
||||
{}
|
||||
catch(...)
|
||||
{
|
||||
FatalError("memory allocation for a CPU buffer failed");
|
||||
}
|
||||
|
||||
CPUBuffer(const CPUBuffer& other) try : m_data(other.m_size > 0 ? std::make_unique<std::uint8_t[]>(other.m_size) : nullptr), m_size(other.m_size)
|
||||
{
|
||||
if(m_data)
|
||||
std::memcpy(m_data.get(), other.m_data.get(), m_size);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FatalError("memory allocation for a CPU buffer failed");
|
||||
}
|
||||
|
||||
CPUBuffer& operator=(const CPUBuffer& other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
if(other.m_data)
|
||||
{
|
||||
std::unique_ptr<std::uint8_t[]> new_data;
|
||||
try
|
||||
{
|
||||
new_data = std::make_unique<std::uint8_t[]>(other.m_size);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FatalError("memory allocation for a CPU buffer failed");
|
||||
}
|
||||
std::memcpy(new_data.get(), other.m_data.get(), other.m_size);
|
||||
|
||||
m_data = std::move(new_data);
|
||||
m_size = other.m_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data.reset();
|
||||
m_size = 0;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline CPUBuffer Duplicate() const
|
||||
{
|
||||
CPUBuffer buffer(m_size);
|
||||
if(m_data)
|
||||
std::memcpy(buffer.GetData(), m_data.get(), m_size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline void Allocate(std::size_t size)
|
||||
{
|
||||
if(m_data != nullptr)
|
||||
FatalError("cannot allocate an already allocated CPU buffer");
|
||||
try
|
||||
{
|
||||
m_data = std::make_unique<std::uint8_t[]>(size);
|
||||
m_size = size;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
FatalError("memory allocation for a CPU buffer failed");
|
||||
}
|
||||
}
|
||||
|
||||
inline bool Empty() const { return m_size == 0; }
|
||||
|
||||
[[nodiscard]] inline std::size_t GetSize() const noexcept { return m_size; }
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] inline T* GetDataAs() const { return reinterpret_cast<T*>(m_data.get()); }
|
||||
[[nodiscard]] inline std::uint8_t* GetData() const { return m_data.get(); }
|
||||
inline operator bool() const { return (bool)m_data; }
|
||||
|
||||
~CPUBuffer() = default;
|
||||
|
||||
private:
|
||||
std::unique_ptr<std::uint8_t[]> m_data;
|
||||
std::size_t m_size = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
20
Runtime/Includes/Utils/NonCopyable.h
git.filemode.normal_file
20
Runtime/Includes/Utils/NonCopyable.h
git.filemode.normal_file
@@ -0,0 +1,20 @@
|
||||
#ifndef __SCOPE_UTILS_NON_COPYABLE__
|
||||
#define __SCOPE_UTILS_NON_COPYABLE__
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class NonCopyable
|
||||
{
|
||||
protected:
|
||||
NonCopyable() = default;
|
||||
virtual ~NonCopyable() = default;
|
||||
|
||||
public:
|
||||
NonCopyable(const NonCopyable&) = delete;
|
||||
NonCopyable(NonCopyable&&) noexcept = default;
|
||||
NonCopyable& operator=(const NonCopyable&) = delete;
|
||||
NonCopyable& operator=(NonCopyable&&) noexcept = default;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
20
Runtime/Includes/Utils/NonMovable.h
git.filemode.normal_file
20
Runtime/Includes/Utils/NonMovable.h
git.filemode.normal_file
@@ -0,0 +1,20 @@
|
||||
#ifndef __SCOPE_UTILS_NON_MOVABLE__
|
||||
#define __SCOPE_UTILS_NON_MOVABLE__
|
||||
|
||||
namespace Scop
|
||||
{
|
||||
class NonMovable
|
||||
{
|
||||
protected:
|
||||
NonMovable() = default;
|
||||
virtual ~NonMovable() = default;
|
||||
|
||||
public:
|
||||
NonMovable(const NonMovable&) = default;
|
||||
NonMovable(NonMovable&&) noexcept = delete;
|
||||
NonMovable& operator=(const NonMovable&) = default;
|
||||
NonMovable& operator=(NonMovable&&) noexcept = delete;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user