mirror of
https://github.com/seekrs/MacroLibX.git
synced 2026-01-11 14:43:34 +00:00
release 2.0 (#110)
This commit is contained in:
6
.github/workflows/linux_clang.yml
vendored
6
.github/workflows/linux_clang.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest]
|
os: [ubuntu-24.04]
|
||||||
arch: [x86_64]
|
arch: [x86_64]
|
||||||
mode: [release]
|
mode: [release]
|
||||||
|
|
||||||
@@ -21,10 +21,6 @@ jobs:
|
|||||||
if: "!contains(github.event.head_commit.message, 'ci skip')"
|
if: "!contains(github.event.head_commit.message, 'ci skip')"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Get current date as package key
|
|
||||||
id: cache_key
|
|
||||||
run: echo "key=$(date +'%W')" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|||||||
6
.github/workflows/linux_gcc.yml
vendored
6
.github/workflows/linux_gcc.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest]
|
os: [ubuntu-24.04]
|
||||||
arch: [x86_64]
|
arch: [x86_64]
|
||||||
mode: [release]
|
mode: [release]
|
||||||
|
|
||||||
@@ -21,10 +21,6 @@ jobs:
|
|||||||
if: "!contains(github.event.head_commit.message, 'ci skip')"
|
if: "!contains(github.event.head_commit.message, 'ci skip')"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Get current date as package key
|
|
||||||
id: cache_key
|
|
||||||
run: echo "key=$(date +'%W')" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/macos_x86.yml
vendored
4
.github/workflows/macos_x86.yml
vendored
@@ -21,10 +21,6 @@ jobs:
|
|||||||
if: "!contains(github.event.head_commit.message, 'ci skip')"
|
if: "!contains(github.event.head_commit.message, 'ci skip')"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Get current date as package key
|
|
||||||
id: cache_key
|
|
||||||
run: echo "key=$(date +'%W')" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/windows.yml
vendored
4
.github/workflows/windows.yml
vendored
@@ -50,7 +50,3 @@ jobs:
|
|||||||
# Build the mlx
|
# Build the mlx
|
||||||
- name: Build MacroLibX
|
- name: Build MacroLibX
|
||||||
run: xmake --yes
|
run: xmake --yes
|
||||||
|
|
||||||
# Build the example
|
|
||||||
- name: Build Example
|
|
||||||
run: xmake build --yes Test
|
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -11,8 +11,11 @@
|
|||||||
*.tmp
|
*.tmp
|
||||||
*.ilk
|
*.ilk
|
||||||
*.pdb
|
*.pdb
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
*.sym
|
||||||
*.exe
|
*.exe
|
||||||
*vgcore
|
*vgcore.*
|
||||||
*.gdb_history
|
*.gdb_history
|
||||||
.vs/
|
.vs/
|
||||||
.xmake/
|
.xmake/
|
||||||
|
|||||||
183
Makefile
183
Makefile
@@ -1,131 +1,178 @@
|
|||||||
# **************************************************************************** #
|
NAME = libmlx.so
|
||||||
# #
|
MAKE = make --no-print-directory
|
||||||
# ::: :::::::: #
|
|
||||||
# Makefile :+: :+: :+: #
|
|
||||||
# +:+ +:+ +:+ #
|
|
||||||
# By: kiroussa <oss@xtrm.me> +#+ +:+ +#+ #
|
|
||||||
# +#+#+#+#+#+ +#+ #
|
|
||||||
# Created: 2022/10/04 16:43:41 by maldavid #+# #+# #
|
|
||||||
# Updated: 2024/04/24 14:59:23 by kiroussa ### ########.fr #
|
|
||||||
# #
|
|
||||||
# **************************************************************************** #
|
|
||||||
|
|
||||||
NAME = libmlx.so
|
OS ?= $(shell uname -s)
|
||||||
MAKE = make --no-print-directory
|
DEBUG ?= false
|
||||||
|
TOOLCHAIN ?= clang
|
||||||
|
IMAGES_OPTIMIZED ?= true
|
||||||
|
FORCE_INTEGRATED_GPU ?= false
|
||||||
|
GRAPHICS_MEMORY_DUMP ?= false
|
||||||
|
PROFILER ?= false
|
||||||
|
FORCE_WAYLAND ?= false
|
||||||
|
DISABLE_ALL_SAFETIES ?= false
|
||||||
|
_ENABLEDFLAGS =
|
||||||
|
|
||||||
OS ?= $(shell uname -s)
|
SRCS = $(wildcard $(addsuffix /*.cpp, runtime/Sources/Core))
|
||||||
DEBUG ?= false
|
SRCS += $(wildcard $(addsuffix /*.cpp, runtime/Sources/Graphics))
|
||||||
TOOLCHAIN ?= clang
|
SRCS += $(wildcard $(addsuffix /*.cpp, runtime/Sources/Platform))
|
||||||
IMAGES_OPTIMIZED ?= true
|
SRCS += $(wildcard $(addsuffix /*.cpp, runtime/Sources/Renderer))
|
||||||
FORCE_INTEGRATED_GPU ?= false
|
SRCS += $(wildcard $(addsuffix /*.cpp, runtime/Sources/Renderer/Vulkan))
|
||||||
GRAPHICS_MEMORY_DUMP ?= false
|
SRCS += $(wildcard $(addsuffix /*.cpp, runtime/Sources/Renderer/Pipelines))
|
||||||
PROFILER ?= false
|
SRCS += $(wildcard $(addsuffix /*.cpp, runtime/Sources/Renderer/RenderPasses))
|
||||||
_ENABLEDFLAGS =
|
|
||||||
|
|
||||||
SRCS = $(wildcard $(addsuffix /*.cpp, src/core))
|
OBJ_DIR = objs/make/$(shell echo $(OS) | tr '[:upper:]' '[:lower:]')
|
||||||
SRCS += $(wildcard $(addsuffix /*.cpp, src/platform))
|
OBJS := $(addprefix $(OBJ_DIR)/, $(SRCS:.cpp=.o))
|
||||||
SRCS += $(wildcard $(addsuffix /*.cpp, src/renderer))
|
|
||||||
SRCS += $(wildcard $(addsuffix /*.cpp, src/renderer/**))
|
|
||||||
|
|
||||||
OBJ_DIR = objs/make/$(shell echo $(OS) | tr '[:upper:]' '[:lower:]')
|
SHADERS_DIR = runtime/Includes/Embedded
|
||||||
OBJS := $(addprefix $(OBJ_DIR)/, $(SRCS:.cpp=.o))
|
SHADERS_SRCS = $(wildcard $(addsuffix /*.nzsl, $(SHADERS_DIR)))
|
||||||
|
SPVS = $(SHADERS_SRCS:.nzsl=.spv.h)
|
||||||
|
|
||||||
CXX = clang++
|
CXX = clang++
|
||||||
CXXFLAGS = -std=c++17 -O3 -fPIC -Wall -Wextra -Werror -DSDL_MAIN_HANDLED
|
CXXFLAGS = -std=c++20 -fPIC -Wall -Wextra -DSDL_MAIN_HANDLED
|
||||||
INCLUDES = -I./includes -I./src -I./third_party
|
INCLUDES = -I./includes -I./runtime/Includes -I./runtime/Sources -I./third_party
|
||||||
|
|
||||||
|
CXXPCHFLAGS = -xc++-header -std=c++20 -Wall -Wextra
|
||||||
|
|
||||||
|
PCH_SOURCE = runtime/Includes/PreCompiled.h
|
||||||
|
GCH = runtime/Includes/PreCompiled.h.gch
|
||||||
|
CCH = runtime/Includes/PreCompiled.h.pch
|
||||||
|
PCH =
|
||||||
|
|
||||||
|
NZSLC ?= nzslc
|
||||||
|
|
||||||
ifeq ($(TOOLCHAIN), gcc)
|
ifeq ($(TOOLCHAIN), gcc)
|
||||||
CXX = g++
|
CXX = g++
|
||||||
CXXFLAGS += -Wno-error=cpp
|
PCH = $(GCH)
|
||||||
|
CXXFLAGS += -Wno-error=cpp
|
||||||
else
|
else
|
||||||
CXXFLAGS += -Wno-error=#warning
|
PCH = $(CCH)
|
||||||
|
CXXFLAGS += -Wno-error=#warning -include-pch $(PCH)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OS), Darwin)
|
ifeq ($(OS), Darwin)
|
||||||
LDFLAGS += -L /opt/homebrew/lib -lSDL2
|
LDFLAGS += -L /opt/homebrew/Cellar/lib -L /usr/local/Cellar -L /opt/homebrew/lib -lSDL2
|
||||||
CXXFLAGS += -I /opt/homebrew/include
|
INCLUDES += -I /opt/homebrew/Cellar/include -I /usr/local/Cellar/include -I /opt/homebrew/include
|
||||||
NAME = libmlx.dylib
|
NAME = libmlx.dylib
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(DEBUG), true)
|
ifeq ($(DEBUG), true)
|
||||||
CXXFLAGS += -g3 -D DEBUG
|
CXXFLAGS += -g3 -O0 -D DEBUG
|
||||||
LDFLAGS += -rdynamic
|
LDFLAGS += -rdynamic
|
||||||
|
else
|
||||||
|
CXXFLAGS += -O3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(FORCE_INTEGRATED_GPU), true)
|
ifeq ($(FORCE_INTEGRATED_GPU), true)
|
||||||
_ENABLEDFLAGS += FORCE_INTEGRATED_GPU
|
_ENABLEDFLAGS += FORCE_INTEGRATED_GPU
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(IMAGES_OPTIMIZED), true)
|
ifeq ($(IMAGES_OPTIMIZED), true)
|
||||||
_ENABLEDFLAGS += IMAGE_OPTIMIZED
|
_ENABLEDFLAGS += IMAGE_OPTIMIZED
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(GRAPHICS_MEMORY_DUMP), true)
|
ifeq ($(GRAPHICS_MEMORY_DUMP), true)
|
||||||
_ENABLEDFLAGS += GRAPHICS_MEMORY_DUMP
|
_ENABLEDFLAGS += GRAPHICS_MEMORY_DUMP
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(PROFILER), true)
|
ifeq ($(PROFILER), true)
|
||||||
_ENABLEDFLAGS += PROFILER
|
_ENABLEDFLAGS += PROFILER
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CXXFLAGS += $(addprefix -D, $(_ENABLEDFLAGS))
|
ifeq ($(FORCE_WAYLAND), true)
|
||||||
|
_ENABLEDFLAGS += FORCE_WAYLAND
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(DISABLE_ALL_SAFETIES), true)
|
||||||
|
_ENABLEDFLAGS += DISABLE_ALL_SAFETIES
|
||||||
|
endif
|
||||||
|
|
||||||
|
CXXFLAGS += $(addprefix -D, $(_ENABLEDFLAGS))
|
||||||
|
|
||||||
RM = rm -rf
|
RM = rm -rf
|
||||||
|
|
||||||
TPUT = tput -T xterm-256color
|
TPUT = tput -T xterm-256color
|
||||||
_RESET := $(shell $(TPUT) sgr0)
|
_RESET := $(shell $(TPUT) sgr0)
|
||||||
_BOLD := $(shell $(TPUT) bold)
|
_BOLD := $(shell $(TPUT) bold)
|
||||||
_ITALIC := $(shell $(TPUT) sitm)
|
_ITALIC := $(shell $(TPUT) sitm)
|
||||||
_UNDER := $(shell $(TPUT) smul)
|
_UNDER := $(shell $(TPUT) smul)
|
||||||
_GREEN := $(shell $(TPUT) setaf 2)
|
_GREEN := $(shell $(TPUT) setaf 2)
|
||||||
_YELLOW := $(shell $(TPUT) setaf 3)
|
_YELLOW := $(shell $(TPUT) setaf 3)
|
||||||
_RED := $(shell $(TPUT) setaf 1)
|
_RED := $(shell $(TPUT) setaf 1)
|
||||||
_GRAY := $(shell $(TPUT) setaf 8)
|
_GRAY := $(shell $(TPUT) setaf 8)
|
||||||
_PURPLE := $(shell $(TPUT) setaf 5)
|
_PURPLE := $(shell $(TPUT) setaf 5)
|
||||||
|
|
||||||
ifeq ($(DEBUG), true)
|
ifeq ($(DEBUG), true)
|
||||||
MODE := $(_RESET)$(_PURPLE)$(_BOLD)Debug$(_RESET)$(_PURPLE)
|
MODE := $(_RESET)$(_PURPLE)$(_BOLD)Debug$(_RESET)$(_PURPLE)
|
||||||
COLOR := $(_PURPLE)
|
COLOR := $(_PURPLE)
|
||||||
else
|
else
|
||||||
MODE := $(_RESET)$(_GREEN)$(_BOLD)Release$(_RESET)$(_GREEN)
|
MODE := $(_RESET)$(_GREEN)$(_BOLD)Release$(_RESET)$(_GREEN)
|
||||||
COLOR := $(_GREEN)
|
COLOR := $(_GREEN)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OBJS_TOTAL = $(words $(OBJS))
|
OBJS_TOTAL = $(words $(OBJS))
|
||||||
N_OBJS := $(shell find $(OBJ_DIR) -type f -name '*.o' 2>/dev/null | wc -l)
|
N_OBJS := $(shell find $(OBJ_DIR) -type f -name '*.o' 2>/dev/null | wc -l)
|
||||||
OBJS_TOTAL := $(shell echo $$(( $(OBJS_TOTAL) - $(N_OBJS) )))
|
OBJS_TOTAL := $(shell echo $$(( $(OBJS_TOTAL) - $(N_OBJS) )))
|
||||||
CURR_OBJ = 0
|
ifeq ($(OBJS_TOTAL), 0) # To avoid division per 0
|
||||||
|
OBJS_TOTAL := 1
|
||||||
|
endif
|
||||||
|
CURR_OBJ = 0
|
||||||
|
|
||||||
$(OBJ_DIR)/%.o: %.cpp
|
$(OBJ_DIR)/%.o: %.cpp $(PCH)
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
@$(eval CURR_OBJ=$(shell echo $$(( $(CURR_OBJ) + 1 ))))
|
@$(eval CURR_OBJ=$(shell echo $$(( $(CURR_OBJ) + 1 ))))
|
||||||
@$(eval PERCENT=$(shell echo $$(( $(CURR_OBJ) * 100 / $(OBJS_TOTAL) ))))
|
@$(eval PERCENT=$(shell echo $$(( $(CURR_OBJ) * 100 / $(OBJS_TOTAL) ))))
|
||||||
@printf "$(COLOR)($(_BOLD)%3s%%$(_RESET)$(COLOR)) $(_RESET)Compiling $(_BOLD)$<$(_RESET)\n" "$(PERCENT)"
|
@printf "$(COLOR)($(_BOLD)%3s%%$(_RESET)$(COLOR)) $(_RESET)Compiling $(_BOLD)$<$(_RESET)\n" "$(PERCENT)"
|
||||||
@$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
|
@$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
|
||||||
|
|
||||||
all: _printbuildinfos
|
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
|
||||||
|
|
||||||
|
%.spv.h: %.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-header $< -o $(SHADERS_DIR) --optimize
|
||||||
|
|
||||||
|
all: _printbuildinfos
|
||||||
@$(MAKE) $(NAME)
|
@$(MAKE) $(NAME)
|
||||||
|
|
||||||
$(NAME): $(OBJS)
|
$(PCH):
|
||||||
|
@printf "$(COLOR)($(_BOLD)%3s%%$(_RESET)$(COLOR)) $(_RESET)Compiling $(_BOLD)PreCompiled header$(_RESET)\n" "0"
|
||||||
|
@$(CXX) $(CXXPCHFLAGS) $(INCLUDES) $(PCH_SOURCE) -o $(PCH)
|
||||||
|
|
||||||
|
$(NAME): $(OBJS)
|
||||||
@printf "Linking $(_BOLD)$(NAME)$(_RESET)\n"
|
@printf "Linking $(_BOLD)$(NAME)$(_RESET)\n"
|
||||||
@$(CXX) -shared -o $(NAME) $(OBJS) $(LDFLAGS)
|
@$(CXX) -shared -o $(NAME) $(OBJS) $(LDFLAGS)
|
||||||
@printf "$(_BOLD)$(NAME)$(_RESET) compiled $(COLOR)$(_BOLD)successfully$(_RESET)\n"
|
@printf "$(_BOLD)$(NAME)$(_RESET) compiled $(COLOR)$(_BOLD)successfully$(_RESET)\n"
|
||||||
|
|
||||||
_printbuildinfos:
|
_printbuildinfos:
|
||||||
@printf "$(_PURPLE)$(_BOLD)MacroLibX $(_RESET)Compiling in $(_BOLD)$(MODE)$(_RESET) mode on $(_BOLD)$(OS)$(_RESET) | Using $(_BOLD)$(CXX)$(_RESET), flags: $(_BOLD)$(_ENABLEDFLAGS)$(_RESET)\n"
|
@printf "$(_PURPLE)$(_BOLD)MacroLibX $(_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:
|
debug:
|
||||||
@$(MAKE) all DEBUG=true -j$(shell nproc)
|
@$(MAKE) all DEBUG=true -j$(shell nproc)
|
||||||
|
|
||||||
|
clean-shaders:
|
||||||
|
@$(RM) $(SPVS)
|
||||||
|
|
||||||
|
shaders: clean-shaders $(SPVS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@$(RM) $(OBJ_DIR)
|
@$(RM) $(OBJ_DIR)
|
||||||
@printf "Cleaned $(_BOLD)$(OBJ_DIR)$(_RESET)\n"
|
@printf "Cleaned $(_BOLD)$(OBJ_DIR)$(_RESET)\n"
|
||||||
|
@$(RM) $(GCH)
|
||||||
|
@$(RM) $(CCH)
|
||||||
|
@printf "Cleaned pre compiled header\n"
|
||||||
|
|
||||||
fclean: clean
|
fclean: clean
|
||||||
@$(RM) $(NAME)
|
@$(RM) $(NAME)
|
||||||
@printf "Cleaned $(_BOLD)$(NAME)$(_RESET)\n"
|
@printf "Cleaned $(_BOLD)$(NAME)$(_RESET)\n"
|
||||||
|
|
||||||
re: fclean _printbuildinfos
|
re: fclean _printbuildinfos
|
||||||
@$(MAKE) $(NAME)
|
@$(MAKE) $(NAME)
|
||||||
|
|
||||||
.PHONY: all clean debug fclean re
|
.PHONY: all clean debug shaders clean-shaders fclean re
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ And you can enjoy your project
|
|||||||
### 📦 Compile mode
|
### 📦 Compile mode
|
||||||
By default the mlx is built in release mode but you can switch to debug by using `make DEBUG=true`.
|
By default the mlx is built in release mode but you can switch to debug by using `make DEBUG=true`.
|
||||||
|
|
||||||
|
### 🦺 Safety
|
||||||
|
MacroLibX has a strong safety support, mainly by checking every pointer that you pass to it. But this safety has a cost that can be avoided by enabling `DISABLE_ALL_SAFETIES=true` before compiling but don't be afraid to recieve segmentation faults from the mlx.
|
||||||
|
|
||||||
### 🛠️ Set the toolchain
|
### 🛠️ Set the toolchain
|
||||||
If you want to use `GCC` to build the mlx you can use `make TOOLCHAIN=gcc`
|
If you want to use `GCC` to build the mlx you can use `make TOOLCHAIN=gcc`
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ Just as the Makfile build system, you can configure how xmake should build the M
|
|||||||
### 📦 Compile mode
|
### 📦 Compile mode
|
||||||
You can configure xmake to build the mlx in debug mode or in release mode (release mode is enabled by default). To do so you can use `xmake config --mode=debug` or `xmake config --mode=release`.
|
You can configure xmake to build the mlx in debug mode or in release mode (release mode is enabled by default). To do so you can use `xmake config --mode=debug` or `xmake config --mode=release`.
|
||||||
|
|
||||||
|
### 🦺 Safety
|
||||||
|
MacroLibX has a strong safety support, mainly by checking every pointer that you pass to it. But this safety has a cost that can be avoided by enabling `xmake config --disable_all_safeties=y` before compiling but don't be afraid to recieve segmentation faults from the mlx.
|
||||||
|
|
||||||
### 🛠️ Set the toolchain
|
### 🛠️ Set the toolchain
|
||||||
To change the compilation toolchain you can use `xmake config --toolchain=[gcc|clang|...]`
|
To change the compilation toolchain you can use `xmake config --toolchain=[gcc|clang|...]`
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
12
compile_flags.txt
git.filemode.normal_file
12
compile_flags.txt
git.filemode.normal_file
@@ -0,0 +1,12 @@
|
|||||||
|
-xc++
|
||||||
|
-std=c++20
|
||||||
|
-Iruntime/Includes
|
||||||
|
-Iruntime/Sources
|
||||||
|
-Iincludes
|
||||||
|
-Ithird_party
|
||||||
|
-DMLX_BUILD
|
||||||
|
-DSDL_MAIN_HANDLED
|
||||||
|
-DDEBUG
|
||||||
|
-DIMAGE_OPTIMIZED
|
||||||
|
-D_REENTRANT
|
||||||
|
-isystem/usr/include/SDL2
|
||||||
@@ -5,8 +5,7 @@ if [ -e a.out ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $(uname -s) = 'Darwin' ]; then
|
if [ $(uname -s) = 'Darwin' ]; then
|
||||||
clang main.c ../libmlx.dylib -L /opt/homebrew/lib -lSDL2 -g;
|
clang main.c ../libmlx.dylib -L /opt/homebrew/lib -lSDL2 -lm -g;
|
||||||
else
|
else
|
||||||
clang main.c ../libmlx.so -lSDL2 -g -Wall -Wextra -Werror;
|
clang main.c ../libmlx.so -lSDL2 -lm -g -Wall -Wextra -Werror;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
161
example/main.c
161
example/main.c
@@ -1,74 +1,72 @@
|
|||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* main.c :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2022/10/04 17:55:21 by maldavid #+# #+# */
|
|
||||||
/* Updated: 2024/03/25 16:16:07 by maldavid ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
#include "../includes/mlx.h"
|
#include "../includes/mlx.h"
|
||||||
|
#include "../includes/mlx_extended.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
void* mlx;
|
mlx_context mlx;
|
||||||
void* win;
|
mlx_window win;
|
||||||
void* logo_png;
|
mlx_image logo_png;
|
||||||
void* logo_jpg;
|
mlx_image logo_jpg;
|
||||||
void* logo_bmp;
|
mlx_image logo_bmp;
|
||||||
void* img;
|
mlx_image img;
|
||||||
} mlx_t;
|
} mlx_t;
|
||||||
|
|
||||||
//void* img = NULL;
|
#define CIRCLE_RADIUS 50
|
||||||
|
#define CIRCLE_DIAMETER (CIRCLE_RADIUS + CIRCLE_RADIUS)
|
||||||
|
|
||||||
int update(void* param)
|
static mlx_color pixels_circle[CIRCLE_DIAMETER * CIRCLE_DIAMETER] = { 0 };
|
||||||
|
|
||||||
|
#define THRESHOLD 200
|
||||||
|
|
||||||
|
void update(void* param)
|
||||||
{
|
{
|
||||||
static int i = 0;
|
static int i = 0;
|
||||||
mlx_t* mlx = (mlx_t*)param;
|
mlx_t* mlx = (mlx_t*)param;
|
||||||
|
|
||||||
if(i == 200)
|
if(i > THRESHOLD)
|
||||||
mlx_clear_window(mlx->mlx, mlx->win);
|
{
|
||||||
/*
|
mlx_clear_window(mlx->mlx, mlx->win, (mlx_color){ .rgba = 0x334D4DFF });
|
||||||
if(img)
|
mlx_put_transformed_image_to_window(mlx->mlx, mlx->win, mlx->logo_bmp, 220, 40, 0.5f, 0.5f, i);
|
||||||
mlx_destroy_image(mlx->mlx,img);
|
}
|
||||||
img = mlx_new_image(mlx->mlx, 800, 800);
|
|
||||||
mlx_set_image_pixel(mlx->mlx, img, 4, 4, 0xFF00FF00);
|
if(i >= THRESHOLD + THRESHOLD / 4)
|
||||||
mlx_put_image_to_window(mlx->mlx, mlx->win, img, 0, 0);
|
mlx_set_font_scale(mlx->mlx, "default", 16.f);
|
||||||
*/
|
|
||||||
if(i >= 250)
|
|
||||||
mlx_set_font_scale(mlx->mlx, mlx->win, "default", 16.f);
|
|
||||||
else
|
else
|
||||||
mlx_set_font_scale(mlx->mlx, mlx->win, "default", 6.f);
|
mlx_set_font_scale(mlx->mlx, "default", 6.f);
|
||||||
mlx_string_put(mlx->mlx, mlx->win, 160, 120, 0xFFFF2066, "this text should be hidden");
|
|
||||||
|
mlx_string_put(mlx->mlx, mlx->win, 160, 120, (mlx_color){ .rgba = 0xFF2066FF }, "this text should be behind");
|
||||||
|
|
||||||
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo_png, 100, 100);
|
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo_png, 100, 100);
|
||||||
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo_jpg, 210, 150);
|
|
||||||
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo_bmp, 220, 40);
|
|
||||||
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->img, 150, 60);
|
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->img, 150, 60);
|
||||||
|
|
||||||
mlx_set_font(mlx->mlx, mlx->win, "default");
|
mlx_set_font(mlx->mlx, "default");
|
||||||
mlx_string_put(mlx->mlx, mlx->win, 20, 50, 0xFFFFFFFF, "that's a text");
|
mlx_string_put(mlx->mlx, mlx->win, 20, 50, (mlx_color){ .rgba = 0xFFFFFFFF }, "that's a text");
|
||||||
|
|
||||||
int color = 0;
|
uint32_t color = 0;
|
||||||
for(int j = 0; j < 400; j++)
|
for(int j = 0; j < 400; j++)
|
||||||
{
|
{
|
||||||
mlx_pixel_put(mlx->mlx, mlx->win, j, j, 0xFFFF0000 + color);
|
mlx_pixel_put(mlx->mlx, mlx->win, j, j, (mlx_color){ .rgba = 0x0000FFFF + (color << 24) });
|
||||||
mlx_pixel_put(mlx->mlx, mlx->win, 399 - j, j, 0xFF0000FF);
|
mlx_pixel_put(mlx->mlx, mlx->win, 399 - j, j, (mlx_color){ .rgba = 0x0000FFFF });
|
||||||
color += (color < 255);
|
color += (color < 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
if(i < THRESHOLD)
|
||||||
return 0;
|
mlx_put_transformed_image_to_window(mlx->mlx, mlx->win, mlx->logo_jpg, 210, 150, 0.5f, 2.0f, 0.0f);
|
||||||
|
else
|
||||||
|
mlx_put_transformed_image_to_window(mlx->mlx, mlx->win, mlx->logo_jpg, 210, 150, fabs(sin(i / 100.0f)), fabs(cos(i / 100.0f) * 2.0f), 0.0f);
|
||||||
|
mlx_set_font_scale(mlx->mlx, "default", 8.f);
|
||||||
|
mlx_string_put(mlx->mlx, mlx->win, 210, 175, (mlx_color){ .rgba = 0xFFAF2BFF }, "hidden");
|
||||||
|
|
||||||
|
mlx_pixel_put_region(mlx->mlx, mlx->win, 200, 170, CIRCLE_DIAMETER, CIRCLE_DIAMETER, pixels_circle);
|
||||||
|
|
||||||
|
i++; // Will overflow and I don't care
|
||||||
}
|
}
|
||||||
|
|
||||||
void* create_image(mlx_t* mlx)
|
mlx_image create_image(mlx_t* mlx)
|
||||||
{
|
{
|
||||||
unsigned char pixel[4];
|
mlx_image img = mlx_new_image(mlx->mlx, 100, 100);
|
||||||
void* img = mlx_new_image(mlx->mlx, 100, 100);
|
|
||||||
for(int i = 0, j = 0, k = 0; i < (100 * 100) * 4; i += 4, j++)
|
for(int i = 0, j = 0, k = 0; i < (100 * 100) * 4; i += 4, j++)
|
||||||
{
|
{
|
||||||
if(j >= 100)
|
if(j >= 100)
|
||||||
@@ -78,17 +76,19 @@ void* create_image(mlx_t* mlx)
|
|||||||
}
|
}
|
||||||
if(i < 10000 || i > 20000)
|
if(i < 10000 || i > 20000)
|
||||||
{
|
{
|
||||||
pixel[0] = i;
|
mlx_color pixel = {
|
||||||
pixel[1] = j;
|
.r = (uint8_t)k,
|
||||||
pixel[2] = k;
|
.g = (uint8_t)j,
|
||||||
pixel[3] = 0x99;
|
.b = (uint8_t)i,
|
||||||
mlx_set_image_pixel(mlx->mlx, img, j, k, *((int *)pixel));
|
.a = 0x99
|
||||||
|
};
|
||||||
|
mlx_set_image_pixel(mlx->mlx, img, j, k, pixel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
int key_hook(int key, void* param)
|
void key_hook(int key, void* param)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
@@ -101,13 +101,13 @@ int key_hook(int key, void* param)
|
|||||||
mlx_loop_end(mlx->mlx);
|
mlx_loop_end(mlx->mlx);
|
||||||
break;
|
break;
|
||||||
case 22 : // (S)how
|
case 22 : // (S)how
|
||||||
mlx_mouse_show();
|
mlx_mouse_show(mlx->mlx);
|
||||||
break;
|
break;
|
||||||
case 11 : // (H)ide
|
case 11 : // (H)ide
|
||||||
mlx_mouse_hide();
|
mlx_mouse_hide(mlx->mlx);
|
||||||
break;
|
break;
|
||||||
case 6 : // (C)lear
|
case 6 : // (C)lear
|
||||||
mlx_clear_window(mlx->mlx, mlx->win);
|
mlx_clear_window(mlx->mlx, mlx->win, (mlx_color){ .rgba = 0x334D4DFF });
|
||||||
break;
|
break;
|
||||||
case 79 : // RIGHT KEY
|
case 79 : // RIGHT KEY
|
||||||
mlx_mouse_move(mlx->mlx, mlx->win, x + 10, y);
|
mlx_mouse_move(mlx->mlx, mlx->win, x + 10, y);
|
||||||
@@ -124,16 +124,16 @@ int key_hook(int key, void* param)
|
|||||||
|
|
||||||
default : break;
|
default : break;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int window_hook(int event, void* param)
|
void window_hook(int event, void* param)
|
||||||
{
|
{
|
||||||
if(event == 0)
|
if(event == 0)
|
||||||
mlx_loop_end(((mlx_t*)param)->mlx);
|
mlx_loop_end(((mlx_t*)param)->mlx);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
mlx_t mlx;
|
mlx_t mlx;
|
||||||
@@ -141,42 +141,55 @@ int main(void)
|
|||||||
int h;
|
int h;
|
||||||
int dummy;
|
int dummy;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for(int j = 0; j < CIRCLE_DIAMETER; j++)
|
||||||
|
{
|
||||||
|
for(int k = 0; k < CIRCLE_DIAMETER; k++, i++)
|
||||||
|
{
|
||||||
|
if((CIRCLE_RADIUS - j) * (CIRCLE_RADIUS - j) + (CIRCLE_RADIUS - k) * (CIRCLE_RADIUS - k) < CIRCLE_RADIUS * CIRCLE_RADIUS)
|
||||||
|
pixels_circle[i] = (mlx_color){ .rgba = 0xA10000FF + ((j * k * i) << 8) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mlx.mlx = mlx_init();
|
mlx.mlx = mlx_init();
|
||||||
mlx.win = mlx_new_window(mlx.mlx, 400, 400, "My window");
|
|
||||||
|
mlx_window_create_info info = { 0 };
|
||||||
|
info.title = "My window";
|
||||||
|
info.width = 400;
|
||||||
|
info.height = 400;
|
||||||
|
info.is_resizable = true;
|
||||||
|
mlx.win = mlx_new_window(mlx.mlx, &info);
|
||||||
|
|
||||||
|
mlx_get_screen_size(mlx.mlx, mlx.win, &w, &h);
|
||||||
|
printf("screen size : %dx%d\n", w, h);
|
||||||
|
|
||||||
mlx_set_fps_goal(mlx.mlx, 60);
|
mlx_set_fps_goal(mlx.mlx, 60);
|
||||||
|
|
||||||
mlx_on_event(mlx.mlx, mlx.win, MLX_KEYDOWN, key_hook, &mlx);
|
mlx_on_event(mlx.mlx, mlx.win, MLX_KEYDOWN, key_hook, &mlx);
|
||||||
mlx_on_event(mlx.mlx, mlx.win, MLX_WINDOW_EVENT, window_hook, &mlx);
|
mlx_on_event(mlx.mlx, mlx.win, MLX_WINDOW_EVENT, window_hook, &mlx);
|
||||||
|
|
||||||
mlx.logo_png = mlx_png_file_to_image(mlx.mlx, "42_logo.png", &dummy, &dummy);
|
mlx.logo_bmp = mlx_new_image_from_file(mlx.mlx, "42_logo.bmp", &dummy, &dummy);
|
||||||
mlx.logo_bmp = mlx_bmp_file_to_image(mlx.mlx, "42_logo.bmp", &dummy, &dummy);
|
mlx.logo_png = mlx_new_image_from_file(mlx.mlx, "42_logo.png", &dummy, &dummy);
|
||||||
mlx.logo_jpg = mlx_jpg_file_to_image(mlx.mlx, "42_logo.jpg", &dummy, &dummy);
|
mlx.logo_jpg = mlx_new_image_from_file(mlx.mlx, "42_logo.jpg", &dummy, &dummy);
|
||||||
|
|
||||||
mlx_pixel_put(mlx.mlx, mlx.win, 200, 10, 0xFFFF00FF);
|
mlx_pixel_put(mlx.mlx, mlx.win, 200, 10, (mlx_color){ .rgba = 0xFF00FFFF });
|
||||||
mlx_put_image_to_window(mlx.mlx, mlx.win, mlx.logo_png, 10, 190);
|
mlx_put_image_to_window(mlx.mlx, mlx.win, mlx.logo_png, 0, 0);
|
||||||
|
|
||||||
mlx.img = create_image(&mlx);
|
mlx.img = create_image(&mlx);
|
||||||
|
|
||||||
|
mlx_set_font_scale(mlx.mlx, "font.ttf", 16.f);
|
||||||
|
mlx_string_put(mlx.mlx, mlx.win, 20, 20, (mlx_color){ .rgba = 0x0020FFFF }, "that text will disappear");
|
||||||
|
|
||||||
mlx_string_put(mlx.mlx, mlx.win, 0, 10, 0xFFFFFF00, "fps:");
|
mlx_add_loop_hook(mlx.mlx, update, &mlx);
|
||||||
mlx_string_put(mlx.mlx, mlx.win, 0, 20, 0xFFFFFFFF, "fps:");
|
|
||||||
|
|
||||||
mlx_set_font_scale(mlx.mlx, mlx.win, "font.ttf", 16.f);
|
|
||||||
mlx_string_put(mlx.mlx, mlx.win, 20, 20, 0xFF0020FF, "that text will disappear");
|
|
||||||
|
|
||||||
mlx_loop_hook(mlx.mlx, update, &mlx);
|
|
||||||
mlx_loop(mlx.mlx);
|
mlx_loop(mlx.mlx);
|
||||||
|
|
||||||
mlx_get_screens_size(mlx.mlx, mlx.win, &w, &h);
|
|
||||||
printf("screen size : %dx%d\n", w, h);
|
|
||||||
|
|
||||||
mlx_destroy_image(mlx.mlx, mlx.logo_png);
|
mlx_destroy_image(mlx.mlx, mlx.logo_png);
|
||||||
mlx_destroy_image(mlx.mlx, mlx.logo_jpg);
|
mlx_destroy_image(mlx.mlx, mlx.logo_jpg);
|
||||||
mlx_destroy_image(mlx.mlx, mlx.logo_bmp);
|
mlx_destroy_image(mlx.mlx, mlx.logo_bmp);
|
||||||
mlx_destroy_image(mlx.mlx, mlx.img);
|
mlx_destroy_image(mlx.mlx, mlx.img);
|
||||||
mlx_destroy_window(mlx.mlx, mlx.win);
|
mlx_destroy_window(mlx.mlx, mlx.win);
|
||||||
mlx_destroy_display(mlx.mlx);
|
|
||||||
|
|
||||||
|
mlx_destroy_context(mlx.mlx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
11
in_depth_features/build.sh
git.filemode.executable_file
11
in_depth_features/build.sh
git.filemode.executable_file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -e a.out ]; then
|
||||||
|
rm a.out
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $(uname -s) = 'Darwin' ]; then
|
||||||
|
clang main.c ../../libmlx.dylib -L /opt/homebrew/lib -lSDL2 -lm -g;
|
||||||
|
else
|
||||||
|
clang main.c ../../libmlx.so -lSDL2 -g -Wall -Wextra -Werror -lm;
|
||||||
|
fi
|
||||||
99
in_depth_features/main.c
git.filemode.normal_file
99
in_depth_features/main.c
git.filemode.normal_file
@@ -0,0 +1,99 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "../../includes/mlx.h"
|
||||||
|
#include "../../includes/mlx_extended.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
mlx_context mlx;
|
||||||
|
mlx_window win;
|
||||||
|
mlx_image render_target;
|
||||||
|
mlx_window render_target_window;
|
||||||
|
} mlx_t;
|
||||||
|
|
||||||
|
void update(void* param)
|
||||||
|
{
|
||||||
|
mlx_t* mlx = (mlx_t*)param;
|
||||||
|
|
||||||
|
mlx_clear_window(mlx->mlx, mlx->win, (mlx_color){ .rgba = 0x334D4DFF });
|
||||||
|
|
||||||
|
mlx_string_put(mlx->mlx, mlx->win, 160, 120, (mlx_color){ .rgba = 0xFF2066FF }, "text");
|
||||||
|
mlx_string_put(mlx->mlx, mlx->win, 20, 50, (mlx_color){ .rgba = 0xFFFFFFFF }, "that's a text");
|
||||||
|
|
||||||
|
for(int j = 0, color = 0; j < 400; j++)
|
||||||
|
{
|
||||||
|
mlx_pixel_put(mlx->mlx, mlx->win, j, j, (mlx_color){ .rgba = 0xFF0000FF + (color << 8) });
|
||||||
|
mlx_pixel_put(mlx->mlx, mlx->win, 399 - j, j, (mlx_color){ .rgba = 0x0000FFFF });
|
||||||
|
color += (color < 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j = 0; j < 20; j++)
|
||||||
|
{
|
||||||
|
for(int k = 0; k < 20; k++)
|
||||||
|
mlx_pixel_put(mlx->mlx, mlx->win, 220 + j, 160 + k, (mlx_color){ .rgba = 0xFF0000FF });
|
||||||
|
}
|
||||||
|
|
||||||
|
mlx_string_put(mlx->mlx, mlx->render_target_window, 20, 20, (mlx_color){ .rgba = 0xAF2BFFFF }, "yippeeee");
|
||||||
|
for(int j = 0, color = 0; j < 200; j++)
|
||||||
|
{
|
||||||
|
mlx_pixel_put(mlx->mlx, mlx->render_target_window, j, j, (mlx_color){ .rgba = 0xFF0000FF + (color << 8) });
|
||||||
|
mlx_pixel_put(mlx->mlx, mlx->render_target_window, 199 - j, j, (mlx_color){ .rgba = 0x0000FFFF });
|
||||||
|
color += (color < 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i = 0;
|
||||||
|
i++;
|
||||||
|
mlx_put_transformed_image_to_window(mlx->mlx, mlx->win, mlx->render_target, 5, 100, 1.0f, 1.0f, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void key_hook(int key, void* param)
|
||||||
|
{
|
||||||
|
mlx_t* mlx = (mlx_t*)param;
|
||||||
|
if(key == 41)
|
||||||
|
mlx_loop_end(mlx->mlx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_hook(int event, void* param)
|
||||||
|
{
|
||||||
|
if(event == 0)
|
||||||
|
mlx_loop_end(((mlx_t*)param)->mlx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
mlx_t mlx;
|
||||||
|
|
||||||
|
mlx.mlx = mlx_init();
|
||||||
|
|
||||||
|
mlx_set_fps_goal(mlx.mlx, 60);
|
||||||
|
|
||||||
|
mlx_window_create_info info = { 0 };
|
||||||
|
info.title = "My window";
|
||||||
|
info.width = 400;
|
||||||
|
info.height = 400;
|
||||||
|
info.is_resizable = true;
|
||||||
|
mlx.win = mlx_new_window(mlx.mlx, &info);
|
||||||
|
|
||||||
|
mlx.render_target = mlx_new_image(mlx.mlx, 200, 200);
|
||||||
|
info.render_target = mlx.render_target;
|
||||||
|
info.title = NULL;
|
||||||
|
info.width = 200;
|
||||||
|
info.height = 200;
|
||||||
|
mlx.render_target_window = mlx_new_window(mlx.mlx, &info);
|
||||||
|
mlx_clear_window(mlx.mlx, mlx.render_target_window, (mlx_color){ .rgba = 0xC16868FF });
|
||||||
|
|
||||||
|
mlx_on_event(mlx.mlx, mlx.win, MLX_KEYDOWN, key_hook, &mlx);
|
||||||
|
mlx_on_event(mlx.mlx, mlx.win, MLX_WINDOW_EVENT, window_hook, &mlx);
|
||||||
|
|
||||||
|
mlx_add_loop_hook(mlx.mlx, update, &mlx);
|
||||||
|
mlx_loop(mlx.mlx);
|
||||||
|
|
||||||
|
mlx_destroy_window(mlx.mlx, mlx.win);
|
||||||
|
|
||||||
|
mlx_destroy_window(mlx.mlx, mlx.render_target_window);
|
||||||
|
mlx_destroy_image(mlx.mlx, mlx.render_target);
|
||||||
|
|
||||||
|
mlx_destroy_context(mlx.mlx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
4
in_depth_features/run.sh
git.filemode.executable_file
4
in_depth_features/run.sh
git.filemode.executable_file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
bash ./build.sh
|
||||||
|
./a.out
|
||||||
656
includes/mlx.h
656
includes/mlx.h
@@ -3,26 +3,283 @@
|
|||||||
/* ::: :::::::: */
|
/* ::: :::::::: */
|
||||||
/* mlx.h :+: :+: :+: */
|
/* mlx.h :+: :+: :+: */
|
||||||
/* +:+ +:+ +:+ */
|
/* +:+ +:+ +:+ */
|
||||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
/* By: maldavid <contact@kbz8.me> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2022/10/04 16:56:35 by maldavid #+# #+# */
|
/* Created: 2022/10/04 16:56:35 by maldavid #+# #+# */
|
||||||
/* Updated: 2024/09/12 01:28:12 by tdelage ### ########.fr */
|
/* Updated: 2025/01/05 22:44:22 by maldavid ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
// MacroLibX official repo https://github.com/seekrs/MacroLibX
|
// MacroLibX official repo https://github.com/seekrs/MacroLibX
|
||||||
// MacroLibX official website https://macrolibx.kbz8.me/
|
// MacroLibX official website https://macrolibx.kbz8.me/
|
||||||
|
|
||||||
#ifndef __MACRO_LIB_X_H__
|
#ifndef MACROLIB_X_H
|
||||||
#define __MACRO_LIB_X_H__
|
#define MACROLIB_X_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include "mlx_profile.h"
|
#include "mlx_profile.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum
|
|
||||||
|
/* MLX types */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opaque handle that represents the MLX context
|
||||||
|
*/
|
||||||
|
MLX_DEFINE_HANDLE(mlx_context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opaque handle that represents a MLX window
|
||||||
|
*/
|
||||||
|
MLX_DEFINE_HANDLE(mlx_window);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opaque handle that represents a MLX image
|
||||||
|
*/
|
||||||
|
MLX_DEFINE_HANDLE(mlx_image);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Union representing RGBA color with access to each part as bytes
|
||||||
|
*/
|
||||||
|
typedef union mlx_color
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
#if MLX_BYTEORDER == MLX_LITTLE_ENDIAN
|
||||||
|
uint8_t a;
|
||||||
|
uint8_t b;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t r;
|
||||||
|
#else
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
uint8_t a;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
uint32_t rgba;
|
||||||
|
} mlx_color;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* MLX backend related functions */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the MLX internal application
|
||||||
|
*
|
||||||
|
* @return (mlx_context) An opaque handler to the internal MLX application or NULL (0x0) in case of error
|
||||||
|
*/
|
||||||
|
MLX_API mlx_context mlx_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Caps the FPS
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param fps The FPS cap or 0 for vsync
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_set_fps_goal(mlx_context mlx, int fps);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy internal MLX application
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_destroy_context(mlx_context mlx);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Window related functions */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Descriptor structure for window creation
|
||||||
|
*
|
||||||
|
* Note: if a valid mlx_image is passed as render_target, this window will not be a real system window
|
||||||
|
* and will rather act as a gate to use any draw function to draw directly on an image.
|
||||||
|
*
|
||||||
|
* Ex: you could use mlx_string_put or mlx_pixel_put to draw on a given image and then use this image
|
||||||
|
* with mlx_put_image_to_window to render it on a real window.
|
||||||
|
*
|
||||||
|
* See experimental/RenderToTexture/main.c for a concrete example.
|
||||||
|
*/
|
||||||
|
typedef struct mlx_window_create_info
|
||||||
|
{
|
||||||
|
mlx_image render_target;
|
||||||
|
const char* title;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
bool is_fullscreen;
|
||||||
|
bool is_resizable;
|
||||||
|
} mlx_window_create_info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a new window
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param info Pointer to a descriptor structure
|
||||||
|
*
|
||||||
|
* @return (mlx_widnow) An opaque handler to the internal MLX window or NULL (0x0) in case of error
|
||||||
|
*/
|
||||||
|
MLX_API mlx_window mlx_new_window(mlx_context mlx, const mlx_window_create_info* info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroys internal window
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_destroy_window(mlx_context mlx, mlx_window win);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets window position
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to move
|
||||||
|
* @param x New x position
|
||||||
|
* @param y New y position
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_set_window_position(mlx_context mlx, mlx_window win, int x, int y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets window size
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to move
|
||||||
|
* @param width New width
|
||||||
|
* @param height New height
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_set_window_size(mlx_context mlx, mlx_window win, int width, int height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets window title
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to move
|
||||||
|
* @param title New title
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_set_window_title(mlx_context mlx, mlx_window win, const char* title);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables/Disables window fullscreen mode
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to move
|
||||||
|
* @param enable Switch or not to fullscreen
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_set_window_fullscreen(mlx_context mlx, mlx_window win, bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets window position
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to move
|
||||||
|
* @param x Pointers to get position of the window
|
||||||
|
* @param y Pointers to get position of the window
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_get_window_position(mlx_context mlx, mlx_window win, int* x, int* y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets window size
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to move
|
||||||
|
* @param x Pointers to get size of the window
|
||||||
|
* @param y Pointers to get size of the window
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_get_window_size(mlx_context mlx, mlx_window win, int* x, int* y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears the given window (resets all rendered data)
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_clear_window(mlx_context mlx, mlx_window win, mlx_color color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the size of the screen the given window is on
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to choose screen the window is on
|
||||||
|
* @param w Get width size
|
||||||
|
* @param h Get height size
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_get_screen_size(mlx_context mlx, mlx_window win, int* w, int* h);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Loop related functions */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gives another function to be executed at each loop turn
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param f The function
|
||||||
|
* @param param Param to give to the function passed
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_add_loop_hook(mlx_context mlx, void(*f)(void*), void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts the internal main loop
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_loop(mlx_context mlx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Ends the internal run loop
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_loop_end(mlx_context mlx);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Events related functions */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Shows mouse cursor
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_mouse_show(mlx_context mlx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Hides mouse cursor
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_mouse_hide(mlx_context mlx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Moves cursor to givent position
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window from which cursor moves
|
||||||
|
* @param x X coordinate
|
||||||
|
* @param y Y coordinate
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_mouse_move(mlx_context mlx, mlx_window win, int x, int y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get cursor's position
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param x Get x coordinate
|
||||||
|
* @param y Get y coordinate
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_mouse_get_pos(mlx_context mlx, int* x, int* y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of event
|
||||||
|
*/
|
||||||
|
typedef enum mlx_event_type
|
||||||
{
|
{
|
||||||
MLX_KEYDOWN = 0,
|
MLX_KEYDOWN = 0,
|
||||||
MLX_KEYUP = 1,
|
MLX_KEYUP = 1,
|
||||||
@@ -32,355 +289,154 @@ typedef enum
|
|||||||
MLX_WINDOW_EVENT = 5
|
MLX_WINDOW_EVENT = 5
|
||||||
} mlx_event_type;
|
} mlx_event_type;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes the MLX internal application
|
* @brief Gives a function to be executed on event type, does not override previous functions
|
||||||
*
|
*
|
||||||
* @return (void*) An opaque pointer to the internal MLX application or NULL (0x0) in case of error
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window
|
||||||
|
* @param event Event type (see union on top of this file)
|
||||||
|
* @param f Function to be executed
|
||||||
|
* @param param Parameter given to the function
|
||||||
*/
|
*/
|
||||||
MLX_API void* mlx_init();
|
MLX_API void mlx_on_event(mlx_context mlx, mlx_window win, mlx_event_type event, void(*f)(int, void*), void* param);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Pixels drawing related functions */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new window
|
* @brief Put a pixel in the window
|
||||||
*
|
*
|
||||||
* @param mlx Internal MLX application
|
* @param mlx Internal MLX application
|
||||||
* @param w Width of the window
|
* @param win Internal window
|
||||||
* @param h Height of the window
|
* @param x X coordinate
|
||||||
* @param title Title of the window
|
* @param y Y coordinate
|
||||||
*
|
* @param color Color of the pixel
|
||||||
* @return (void*) An opaque pointer to the internal MLX window or NULL (0x0) in case of error
|
|
||||||
*/
|
*/
|
||||||
MLX_API void* mlx_new_window(void* mlx, int w, int h, const char* title);
|
MLX_API void mlx_pixel_put(mlx_context mlx, mlx_window win, int x, int y, mlx_color color);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Images related functions */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new window
|
* @brief Create a new empty image
|
||||||
*
|
*
|
||||||
* @param mlx Internal MLX application
|
* @param mlx Internal MLX application
|
||||||
* @param win Internal window to move
|
* @param width Width of the image
|
||||||
* @param x New x position
|
* @param height Height of the image
|
||||||
* @param y New y position
|
|
||||||
*
|
*
|
||||||
|
* @return (mlx_image) An opaque handler to the internal image or NULL (0x0) in case of error
|
||||||
*/
|
*/
|
||||||
MLX_API void mlx_set_window_position(void *mlx, void *win, int x, int y);
|
MLX_API mlx_image mlx_new_image(mlx_context mlx, int width, int height);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gives a function to be executed at each loop turn
|
* @brief Create a new image from a png/jpg/bmp file
|
||||||
*
|
*
|
||||||
* @param mlx Internal MLX application
|
* @param mlx Internal MLX application
|
||||||
* @param f The function
|
* @param filename Path to the png file
|
||||||
* @param param Param to give to the function passed
|
* @param width Get the width of the image
|
||||||
|
* @param heigth Get the height of the image
|
||||||
*
|
*
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
* @return (mlx_image) An opaque handler to the internal image or NULL (0x0) in case of error
|
||||||
*/
|
*/
|
||||||
MLX_API int mlx_loop_hook(void* mlx, int (*f)(void*), void* param);
|
MLX_API mlx_image mlx_new_image_from_file(mlx_context mlx, char* filename, int* width, int* height);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Starts the internal main loop
|
* @brief Destroys internal image
|
||||||
*
|
*
|
||||||
* @param mlx Internal MLX application
|
* @param mlx Internal MLX application
|
||||||
*
|
* @param img Internal image
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
*/
|
||||||
MLX_API int mlx_loop(void* mlx);
|
MLX_API void mlx_destroy_image(mlx_context mlx, mlx_image image);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Ends the internal main loop
|
* @brief Get image pixel data
|
||||||
*
|
*
|
||||||
* @param mlx Internal MLX application
|
* @param mlx Internal MLX application
|
||||||
|
* @param img Internal image
|
||||||
|
* @param x X coordinate in the image
|
||||||
|
* @param y Y coordinate in the image
|
||||||
*
|
*
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
* @return (int) Return the pixel data
|
||||||
*/
|
|
||||||
MLX_API int mlx_loop_end(void* mlx);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Shows mouse cursor
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_mouse_show();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Hides mouse cursor
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_mouse_hide();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Moves cursor to given position
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param win Internal window from which cursor moves
|
|
||||||
* @param x X coordinate
|
|
||||||
* @param y Y coordinate
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_mouse_move(void* mlx, void* win, int x, int y);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get cursor's position
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param x Get x coordinate
|
|
||||||
* @param y Get y coordinate
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_mouse_get_pos(void* mlx, int* x, int* y);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Gives a function to be executed on event type
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param win Internal window
|
|
||||||
* @param event Event type (see union on top of this file)
|
|
||||||
* @param f Function to be executed
|
|
||||||
* @param param Parameter given to the function
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_on_event(void* mlx, void* win, mlx_event_type event, int (*f)(int, void*), void* param);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Put a pixel in the window
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param win Internal window
|
|
||||||
* @param x X coordinate
|
|
||||||
* @param y Y coordinate
|
|
||||||
* @param color Color of the pixel (coded on 4 bytes in an int, 0xAARRGGBB)
|
|
||||||
*
|
|
||||||
* Note : If your're reading pixel colors from an image, don't forget to shift them
|
|
||||||
* one byte to the right as image pixels are encoded as 0xRRGGBBAA and pixel put takes 0xAARRGGBB.
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_pixel_put(void* mlx, void* win, int x, int y, int color);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new empty image
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param width Width of the image
|
|
||||||
* @param height Height of the image
|
|
||||||
*
|
|
||||||
* @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error
|
|
||||||
*/
|
|
||||||
MLX_API void* mlx_new_image(void* mlx, int width, int height);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get image pixel data
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param img Internal image
|
|
||||||
* @param x X coordinate in the image
|
|
||||||
* @param y Y coordinate in the image
|
|
||||||
*
|
|
||||||
* @return (int) Return the pixel data
|
|
||||||
*
|
*
|
||||||
* /!\ If you run into glitches when writing or reading pixels from images /!\
|
* /!\ If you run into glitches when writing or reading pixels from images /!\
|
||||||
* You need to add IMAGES_OPTIMIZED=false to your make mlx command
|
* You need to add IMAGES_OPTIMIZED=false to your make mlx command
|
||||||
* ```
|
* ```
|
||||||
* ~ git clone https://github.com/seekrs/MacroLibX.git
|
* ~ git clone https://github.com/seekrs/MacroLibX.git
|
||||||
* ~ cd MacroLibX
|
* ~ cd MacroLibX
|
||||||
* ~ make IMAGES_OPTIMIZED=false
|
* ~ make IMAGES_OPTIMIZED=false
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
MLX_API int mlx_get_image_pixel(void* mlx, void* img, int x, int y);
|
MLX_API mlx_color mlx_get_image_pixel(mlx_context mlx, mlx_image image, int x, int y);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set image pixel data
|
* @brief Set image pixel data
|
||||||
*
|
*
|
||||||
* @param mlx Internal MLX application
|
* @param mlx Internal MLX application
|
||||||
* @param img Internal image
|
* @param img Internal image
|
||||||
* @param x X coordinate in the image
|
* @param x X coordinate in the image
|
||||||
* @param y Y coordinate in the image
|
* @param y Y coordinate in the image
|
||||||
* @param color Color of the pixel to set
|
* @param color Color of the pixel to set
|
||||||
*
|
|
||||||
* @return (void)
|
|
||||||
*
|
*
|
||||||
* /!\ If you run into glitches when writing or reading pixels from images /!\
|
* /!\ If you run into glitches when writing or reading pixels from images /!\
|
||||||
* You need to add IMAGES_OPTIMIZED=false to your make mlx command
|
* You need to add IMAGES_OPTIMIZED=false to your make mlx command
|
||||||
* ```
|
* ```
|
||||||
* ~ git clone https://github.com/seekrs/MacroLibX.git
|
* ~ git clone https://github.com/seekrs/MacroLibX.git
|
||||||
* ~ cd MacroLibX
|
* ~ cd MacroLibX
|
||||||
* ~ make IMAGES_OPTIMIZED=false
|
* ~ make IMAGES_OPTIMIZED=false
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
MLX_API void mlx_set_image_pixel(void* mlx, void* img, int x, int y, int color);
|
MLX_API void mlx_set_image_pixel(mlx_context mlx, mlx_image image, int x, int y, mlx_color color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Put image to the given window
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window
|
||||||
|
* @param img Internal image
|
||||||
|
* @param x X coordinate
|
||||||
|
* @param y Y coordinate
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_put_image_to_window(mlx_context mlx, mlx_window win, mlx_image image, int x, int y);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Strings drawing related functions */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Put image to the given window
|
* @brief Put text in given window
|
||||||
*
|
*
|
||||||
* @param mlx Internal MLX application
|
* @param mlx Internal MLX application
|
||||||
* @param win Internal window
|
* @param win Internal window
|
||||||
* @param img Internal image
|
* @param x X coordinate
|
||||||
* @param x X coordinate
|
* @param y Y coordinate
|
||||||
* @param y Y coordinate
|
* @param color Color of the pixel
|
||||||
*
|
* @param str Text to put
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
*/
|
||||||
MLX_API int mlx_put_image_to_window(void* mlx, void* win, void* img, int x, int y);
|
MLX_API void mlx_string_put(mlx_context mlx, mlx_window win, int x, int y, mlx_color color, char* str);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroys internal image
|
* @brief Loads a font to be used by `mlx_string_put`
|
||||||
*
|
*
|
||||||
* @param mlx Internal MLX application
|
* @param mlx Internal MLX application
|
||||||
* @param img Internal image
|
* @param win Internal window
|
||||||
*
|
* @param filepath Filepath to the font or "default" to reset to the embedded font
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
*/
|
||||||
MLX_API int mlx_destroy_image(void* mlx, void* img);
|
MLX_API void mlx_set_font(mlx_context mlx, char* filepath);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a new image from a png file
|
* @brief Loads a font to be used by `mlx_string_put` and scales it
|
||||||
*
|
*
|
||||||
* @param mlx Internal MLX application
|
* @param mlx Internal MLX application
|
||||||
* @param filename Path to the png file
|
* @param win Internal window
|
||||||
* @param width Get the width of the image
|
* @param filepath Filepath to the font or "default" to reset to the embedded font
|
||||||
* @param heigth Get the height of the image
|
* @param scale Scale to apply to the font
|
||||||
*
|
|
||||||
* @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error
|
|
||||||
*/
|
*/
|
||||||
MLX_API void* mlx_png_file_to_image(void* mlx, char* filename, int* width, int* height);
|
MLX_API void mlx_set_font_scale(mlx_context mlx, char* filepath, float scale);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new image from a jpg file
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param filename Path to the jpg file
|
|
||||||
* @param width Get the width of the image
|
|
||||||
* @param heigth Get the height of the image
|
|
||||||
*
|
|
||||||
* @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error
|
|
||||||
*/
|
|
||||||
MLX_API void* mlx_jpg_file_to_image(void* mlx, char* filename, int* width, int* height);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a new image from a bmp file
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param filename Path to the bmp file
|
|
||||||
* @param width Get the width of the image
|
|
||||||
* @param heigth Get the height of the image
|
|
||||||
*
|
|
||||||
* @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error
|
|
||||||
*/
|
|
||||||
MLX_API void* mlx_bmp_file_to_image(void* mlx, char* filename, int* width, int* height);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Put text in given window
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param win Internal window
|
|
||||||
* @param x X coordinate
|
|
||||||
* @param y Y coordinate
|
|
||||||
* @param color Color of the pixel (coded on 4 bytes in an int, 0xAARRGGBB)
|
|
||||||
* @param str Text to put
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_string_put(void* mlx, void* win, int x, int y, int color, char* str);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Loads a font to be used by `mlx_string_put`
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param win Internal window
|
|
||||||
* @param filepath Filepath to the font or "default" to reset to the embedded font
|
|
||||||
*
|
|
||||||
* @return (void)
|
|
||||||
*/
|
|
||||||
MLX_API void mlx_set_font(void* mlx, void* win, char* filepath);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Loads a font to be used by `mlx_string_put` and scales it
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param win Internal window
|
|
||||||
* @param filepath Filepath to the font or "default" to reset to the embedded font
|
|
||||||
* @param scale Scale to apply to the font
|
|
||||||
*
|
|
||||||
* @return (void)
|
|
||||||
*/
|
|
||||||
MLX_API void mlx_set_font_scale(void* mlx, void* win, char* filepath, float scale);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Clears the given window (resets all rendered data)
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param win Internal window
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_clear_window(void* mlx, void* win);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroys internal window
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param win Internal window
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_destroy_window(void* mlx, void* win);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroy internal MLX application
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_destroy_display(void* mlx);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the size of the screen the given window is on
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param win Internal window
|
|
||||||
* @param w Get width size
|
|
||||||
* @param h Get height size
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0, made this to copy the behaviour of the original MLX
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_get_screens_size(void* mlx, void* win, int* w, int* h);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Caps the FPS
|
|
||||||
*
|
|
||||||
* @param mlx Internal MLX application
|
|
||||||
* @param fps The FPS cap
|
|
||||||
*
|
|
||||||
* @return (int) Always return 0
|
|
||||||
*/
|
|
||||||
MLX_API int mlx_set_fps_goal(void* mlx, int fps);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
178
includes/mlx_extended.h
git.filemode.normal_file
178
includes/mlx_extended.h
git.filemode.normal_file
@@ -0,0 +1,178 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* mlx_extended.h :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: maldavid <contact@kbz8.me> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2024/12/14 16:17:10 by maldavid #+# #+# */
|
||||||
|
/* Updated: 2025/01/08 12:37:15 by maldavid ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
// MacroLibX official repo https://github.com/seekrs/MacroLibX
|
||||||
|
// MacroLibX official website https://macrolibx.kbz8.me/
|
||||||
|
|
||||||
|
#ifndef MACROLIB_X_EXTENDED_H
|
||||||
|
#define MACROLIB_X_EXTENDED_H
|
||||||
|
|
||||||
|
#include "mlx.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Window related functions */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets maximum window size
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to move
|
||||||
|
* @param x New x maximum size
|
||||||
|
* @param y New y maximum size
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_set_window_max_size(mlx_context mlx, mlx_window win, int x, int y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets minimum window size
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to move
|
||||||
|
* @param x New x minimum size
|
||||||
|
* @param y New y minimum size
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_set_window_min_size(mlx_context mlx, mlx_window win, int x, int y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximizes a window
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to move
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_maximise_window(mlx_context mlx, mlx_window win);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Minimizes a window
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to move
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_minimize_window(mlx_context mlx, mlx_window win);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Restore window to formal size
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window to move
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_restore_window(mlx_context mlx, mlx_window win);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Pixels drawing related functions */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Put an array of pixels in the window
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window
|
||||||
|
* @param x X coordinate
|
||||||
|
* @param y Y coordinate
|
||||||
|
* @param pixels Array of pixels
|
||||||
|
* @param pixels_number Number of pixels
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_pixel_put_array(mlx_context mlx, mlx_window win, int x, int y, mlx_color* pixels, size_t pixels_number);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Put a region of pixels in the window
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window
|
||||||
|
* @param x X coordinate
|
||||||
|
* @param y Y coordinate
|
||||||
|
* @param w Width
|
||||||
|
* @param h Height
|
||||||
|
* @param pixels Array of pixels
|
||||||
|
*
|
||||||
|
* Note: it is responsability of the user to make sure the size of `pixels` is
|
||||||
|
* big enough for the given region.
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_pixel_put_region(mlx_context mlx, mlx_window win, int x, int y, int w, int h, mlx_color* pixels);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Images related functions */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get image region
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param img Internal image
|
||||||
|
* @param x X coordinate in the image
|
||||||
|
* @param y Y coordinate in the image
|
||||||
|
* @param w Width of the region
|
||||||
|
* @param y Height of the region
|
||||||
|
* @param dst Array of pixels to copy to
|
||||||
|
*
|
||||||
|
* Note: it is responsability of the user to make sure the size of `dst` is
|
||||||
|
* big enough for the given region.
|
||||||
|
*
|
||||||
|
* /!\ If you run into glitches when writing or reading pixels from images /!\
|
||||||
|
* You need to add IMAGES_OPTIMIZED=false to your make mlx command
|
||||||
|
* ```
|
||||||
|
* ~ git clone https://github.com/seekrs/MacroLibX.git
|
||||||
|
* ~ cd MacroLibX
|
||||||
|
* ~ make IMAGES_OPTIMIZED=false
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_get_image_region(mlx_context mlx, mlx_image image, int x, int y, int w, int h, mlx_color* dst);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set image region
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param img Internal image
|
||||||
|
* @param x X coordinate in the image
|
||||||
|
* @param y Y coordinate in the image
|
||||||
|
* @param w Width of the region
|
||||||
|
* @param y Height of the region
|
||||||
|
* @param pixels Array of pixels to copy from
|
||||||
|
*
|
||||||
|
* Note: it is responsability of the user to make sure the size of `pixels` is
|
||||||
|
* big enough for the given region.
|
||||||
|
*
|
||||||
|
* /!\ If you run into glitches when writing or reading pixels from images /!\
|
||||||
|
* You need to add IMAGES_OPTIMIZED=false to your make mlx command
|
||||||
|
* ```
|
||||||
|
* ~ git clone https://github.com/seekrs/MacroLibX.git
|
||||||
|
* ~ cd MacroLibX
|
||||||
|
* ~ make IMAGES_OPTIMIZED=false
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_set_image_region(mlx_context mlx, mlx_image image, int x, int y, int w, int h, mlx_color* pixels);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transform and put image to the given window
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window
|
||||||
|
* @param img Internal image
|
||||||
|
* @param x X coordinate
|
||||||
|
* @param y Y coordinate
|
||||||
|
* @param scale_x Scale x of the image
|
||||||
|
* @param scale_y Scale y of the image
|
||||||
|
* @param angle Rotation angle of the image (clockwise)
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_put_transformed_image_to_window(mlx_context mlx, mlx_window win, mlx_image image, int x, int y, float scale_x, float scale_y, float angle);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -6,12 +6,12 @@
|
|||||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2023/11/10 08:49:17 by maldavid #+# #+# */
|
/* Created: 2023/11/10 08:49:17 by maldavid #+# #+# */
|
||||||
/* Updated: 2024/01/03 15:33:35 by maldavid ### ########.fr */
|
/* Updated: 2025/01/07 00:17:45 by maldavid ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
#ifndef __MLX_PROFILE__
|
#ifndef MACROLIBX_PROFILE_H
|
||||||
#define __MLX_PROFILE__
|
#define MACROLIBX_PROFILE_H
|
||||||
|
|
||||||
// Try to identify the compiler
|
// Try to identify the compiler
|
||||||
#if defined(__BORLANDC__)
|
#if defined(__BORLANDC__)
|
||||||
@@ -49,6 +49,14 @@
|
|||||||
#define MLX_PLAT_MACOS
|
#define MLX_PLAT_MACOS
|
||||||
#elif defined(unix) || defined(__unix__) || defined(__unix)
|
#elif defined(unix) || defined(__unix__) || defined(__unix)
|
||||||
#define MLX_PLAT_UNIX
|
#define MLX_PLAT_UNIX
|
||||||
|
#elif defined(__sun) && defined(__SVR4)
|
||||||
|
#define MLX_PLAT_SOLARIS
|
||||||
|
#elif defined(__OpenBSD__)
|
||||||
|
#define MLX_PLAT_OPENBSD
|
||||||
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||||
|
#define MLX_PLAT_FREEBSD
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
#define MLX_PLAT_NETBSD
|
||||||
#else
|
#else
|
||||||
#error "Unknown environment (not Windows, not Linux, not MacOS, not Unix)"
|
#error "Unknown environment (not Windows, not Linux, not MacOS, not Unix)"
|
||||||
#endif
|
#endif
|
||||||
@@ -121,27 +129,86 @@
|
|||||||
|
|
||||||
#if defined(MLX_PLAT_WINDOWS)
|
#if defined(MLX_PLAT_WINDOWS)
|
||||||
#define VK_USE_PLATFORM_WIN32_KHR
|
#define VK_USE_PLATFORM_WIN32_KHR
|
||||||
#ifdef __cplusplus
|
#define VULKAN_LIB_NAME "vulkan-1.dll"
|
||||||
constexpr const char* VULKAN_LIB_NAME = "vulkan-1.dll";
|
|
||||||
#endif
|
|
||||||
#elif defined(MLX_PLAT_MACOS)
|
#elif defined(MLX_PLAT_MACOS)
|
||||||
#define VK_USE_PLATFORM_MACOS_MVK
|
#define VK_USE_PLATFORM_MACOS_MVK
|
||||||
#define VK_USE_PLATFORM_METAL_EXT
|
#define VK_USE_PLATFORM_METAL_EXT
|
||||||
#ifdef __cplusplus
|
#define VULKAN_LIB_NAME "libvulkan.dylib / libvulkan.1.dylib / libMoltenVK.dylib"
|
||||||
constexpr const char* VULKAN_LIB_NAME = "libvulkan.dylib / libvulkan.1.dylib / libMoltenVK.dylib";
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#define VK_USE_PLATFORM_XLIB_KHR
|
#define VK_USE_PLATFORM_XLIB_KHR
|
||||||
#define VK_USE_PLATFORM_WAYLAND_KHR
|
#define VK_USE_PLATFORM_WAYLAND_KHR
|
||||||
#ifdef __cplusplus
|
#define VULKAN_LIB_NAME "libvulkan.so / libvulkan.so.1"
|
||||||
constexpr const char* VULKAN_LIB_NAME = "libvulkan.so / libvulkan.so.1";
|
#endif
|
||||||
|
|
||||||
|
#if !defined(MLX_FORCEINLINE)
|
||||||
|
#if defined(MLX_COMPILER_CLANG) || defined(MLX_COMPILER_GCC)
|
||||||
|
#define MLX_FORCEINLINE __attribute__((always_inline)) inline
|
||||||
|
#elif defined(MLX_COMPILER_MSVC)
|
||||||
|
#define MLX_FORCEINLINE __forceinline
|
||||||
|
#else
|
||||||
|
#define MLX_FORCEINLINE inline
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MLX_LITTLE_ENDIAN 1234
|
||||||
|
#define MLX_BIG_ENDIAN 4321
|
||||||
|
|
||||||
|
#ifndef MLX_BYTEORDER
|
||||||
|
#if defined(MLX_PLAT_LINUX)
|
||||||
|
#include <endian.h>
|
||||||
|
#define MLX_BYTEORDER __BYTE_ORDER
|
||||||
|
#elif defined(MLX_PLAT_SOLARIS)
|
||||||
|
#include <sys/byteorder.h>
|
||||||
|
#if defined(_LITTLE_ENDIAN)
|
||||||
|
#define MLX_BYTEORDER MLX_LITTLE_ENDIAN
|
||||||
|
#elif defined(_BIG_ENDIAN)
|
||||||
|
#define MLX_BYTEORDER MLX_BIG_ENDIAN
|
||||||
|
#else
|
||||||
|
#error Unsupported endianness
|
||||||
|
#endif
|
||||||
|
#elif defined(MLX_PLAT_OPENBSD) || defined(__DragonFly__)
|
||||||
|
#include <endian.h>
|
||||||
|
#define MLX_BYTEORDER BYTE_ORDER
|
||||||
|
#elif defined(MLX_PLAT_FREEBSD) || defined(MLX_PLAT_NETBSD)
|
||||||
|
#include <sys/endian.h>
|
||||||
|
#define MLX_BYTEORDER BYTE_ORDER
|
||||||
|
#elif defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__BYTE_ORDER__)
|
||||||
|
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||||
|
#define MLX_BYTEORDER MLX_LITTLE_ENDIAN
|
||||||
|
#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||||
|
#define MLX_BYTEORDER MLX_BIG_ENDIAN
|
||||||
|
#else
|
||||||
|
#error Unsupported endianness
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if defined(__hppa__) || \
|
||||||
|
defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
|
||||||
|
(defined(__MIPS__) && defined(__MIPSEB__)) || \
|
||||||
|
defined(__ppc__) || defined(__POWERPC__) || defined(__powerpc__) || defined(__PPC__) || \
|
||||||
|
defined(__sparc__) || defined(__sparc)
|
||||||
|
#define MLX_BYTEORDER MLX_BIG_ENDIAN
|
||||||
|
#else
|
||||||
|
#define MLX_BYTEORDER MLX_LITTLE_ENDIAN
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MLX_MAKE_VERSION(major, minor, patch) ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch)))
|
||||||
|
|
||||||
|
#define MLX_VERSION_MAJOR(version) (((uint32_t)(version) >> 22U) & 0x7FU)
|
||||||
|
#define MLX_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU)
|
||||||
|
#define MLX_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU)
|
||||||
|
|
||||||
|
#define MLX_DEFINE_HANDLE(object) typedef struct object##_handler* object
|
||||||
|
|
||||||
|
#define MLX_VERSION MLX_MAKE_VERSION(2, 0, 0)
|
||||||
|
#define MLX_TARGET_VULKAN_API_VERSION MLX_MAKE_VERSION(1, 0, 0)
|
||||||
|
|
||||||
// Checking common assumptions
|
// Checking common assumptions
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
static_assert(CHAR_BIT == 8, "CHAR_BIT is expected to be 8");
|
static_assert(CHAR_BIT == 8, "CHAR_BIT is expected to be 8");
|
||||||
|
|
||||||
@@ -159,7 +226,6 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#endif
|
#endif
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
static_assert(CHAR_BIT == 8, "CHAR_BIT is expected to be 8");
|
static_assert(CHAR_BIT == 8, "CHAR_BIT is expected to be 8");
|
||||||
|
|
||||||
@@ -176,7 +242,6 @@
|
|||||||
#define STATIC_ASSERT(COND, MSG) typedef char static_assertion___##MSG[(COND)?1:-1]
|
#define STATIC_ASSERT(COND, MSG) typedef char static_assertion___##MSG[(COND)?1:-1]
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
STATIC_ASSERT(CHAR_BIT == 8, CHAR_BIT_is_expected_to_be_8);
|
STATIC_ASSERT(CHAR_BIT == 8, CHAR_BIT_is_expected_to_be_8);
|
||||||
|
|
||||||
|
|||||||
73
runtime/Includes/Core/Application.h
git.filemode.normal_file
73
runtime/Includes/Core/Application.h
git.filemode.normal_file
@@ -0,0 +1,73 @@
|
|||||||
|
#ifndef __MLX_APPLICATION__
|
||||||
|
#define __MLX_APPLICATION__
|
||||||
|
|
||||||
|
#include <Core/Graphics.h>
|
||||||
|
#include <Platform/Inputs.h>
|
||||||
|
#include <Core/ImagesRegistry.h>
|
||||||
|
#include <Core/SDLManager.h>
|
||||||
|
#include <Core/Memory.h>
|
||||||
|
#include <Core/Fps.h>
|
||||||
|
#include <Graphics/Font.h>
|
||||||
|
#include <Graphics/Mesh.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class Application
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Application();
|
||||||
|
|
||||||
|
inline void GetMousePos(int* x, int* y) noexcept;
|
||||||
|
inline void GetScreenSize(mlx_window win, int* w, int* h) noexcept;
|
||||||
|
inline void SetFPSCap(std::uint32_t fps) noexcept;
|
||||||
|
|
||||||
|
inline void OnEvent(mlx_window win, int event, void(*f)(int, void*), void* param) noexcept;
|
||||||
|
|
||||||
|
inline mlx_window NewGraphicsSuport(const mlx_window_create_info* info);
|
||||||
|
inline NonOwningPtr<GraphicsSupport> GetGraphicsSupport(mlx_window win);
|
||||||
|
inline void DestroyGraphicsSupport(mlx_window win);
|
||||||
|
|
||||||
|
mlx_image NewTexture(int w, int h);
|
||||||
|
mlx_image NewStbTexture(char* file, int* w, int* h); // stb textures are image files (png, jpg, bpm, ...)
|
||||||
|
inline NonOwningPtr<Texture> GetTexture(mlx_image image);
|
||||||
|
void DestroyTexture(mlx_image img);
|
||||||
|
|
||||||
|
inline void AddLoopHook(void(*f)(void*), void* param);
|
||||||
|
inline void LoopEnd() noexcept;
|
||||||
|
|
||||||
|
inline void LoadFont(const std::filesystem::path& filepath, float scale);
|
||||||
|
|
||||||
|
void Run() noexcept;
|
||||||
|
|
||||||
|
~Application();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Hook
|
||||||
|
{
|
||||||
|
std::function<void(void*)> fn;
|
||||||
|
void* param;
|
||||||
|
|
||||||
|
Hook(std::function<void(void*)> fn, void* param) : fn(fn), param(param) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<MemManager> p_mem_manager; // Putting ptr here to initialise them before inputs, even if it f*cks the padding
|
||||||
|
std::unique_ptr<SDLManager> p_sdl_manager;
|
||||||
|
FpsManager m_fps;
|
||||||
|
Inputs m_in;
|
||||||
|
FontRegistry m_font_registry;
|
||||||
|
ImageRegistry m_image_registry;
|
||||||
|
MeshRegistry m_mesh_registry;
|
||||||
|
std::vector<std::unique_ptr<GraphicsSupport>> m_graphics;
|
||||||
|
std::vector<Hook> m_hooks;
|
||||||
|
std::shared_ptr<Font> p_last_font_bound;
|
||||||
|
std::unique_ptr<RenderCore> p_render_core;
|
||||||
|
#ifdef PROFILER
|
||||||
|
std::unique_ptr<Profiler> p_profiler;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Core/Application.inl>
|
||||||
|
|
||||||
|
#endif // __MLX_APPLICATION__
|
||||||
142
runtime/Includes/Core/Application.inl
git.filemode.normal_file
142
runtime/Includes/Core/Application.inl
git.filemode.normal_file
@@ -0,0 +1,142 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Core/Application.h>
|
||||||
|
#include <Core/Handles.h>
|
||||||
|
#include <Embedded/DogicaTTF.h>
|
||||||
|
|
||||||
|
#ifndef DISABLE_ALL_SAFETIES
|
||||||
|
#define CHECK_WINDOW_PTR(win, retval) \
|
||||||
|
if(win == nullptr) \
|
||||||
|
{ \
|
||||||
|
Error("invalid window handle (NULL)"); \
|
||||||
|
return retval; \
|
||||||
|
} \
|
||||||
|
else if(std::find_if(m_graphics.begin(), m_graphics.end(), [win](const std::unique_ptr<GraphicsSupport>& gs){ return gs && win->id == gs->GetID(); }) == m_graphics.end()) \
|
||||||
|
{ \
|
||||||
|
Error("invalid window handle"); \
|
||||||
|
return retval; \
|
||||||
|
} else {}
|
||||||
|
|
||||||
|
#define CHECK_IMAGE_PTR(img, retval) \
|
||||||
|
if(img == nullptr) \
|
||||||
|
{ \
|
||||||
|
Error("invalid image handle (NULL)"); \
|
||||||
|
return retval; \
|
||||||
|
} \
|
||||||
|
else if(!m_image_registry.IsTextureKnown(image->texture)) \
|
||||||
|
{ \
|
||||||
|
Error("invalid image handle"); \
|
||||||
|
return retval; \
|
||||||
|
} else {}
|
||||||
|
#else
|
||||||
|
#define CHECK_WINDOW_PTR(win, retval)
|
||||||
|
#define CHECK_IMAGE_PTR(img, retval)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
void Application::GetMousePos(int* x, int* y) noexcept
|
||||||
|
{
|
||||||
|
*x = m_in.GetX();
|
||||||
|
*y = m_in.GetY();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::OnEvent(mlx_window win, int event, void(*f)(int, void*), void* param) noexcept
|
||||||
|
{
|
||||||
|
CHECK_WINDOW_PTR(win, );
|
||||||
|
if(!m_graphics[win->id]->HasWindow())
|
||||||
|
return;
|
||||||
|
m_in.OnEvent(m_graphics[win->id]->GetWindow()->GetID(), event, f, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::SetFPSCap(std::uint32_t fps) noexcept
|
||||||
|
{
|
||||||
|
if(fps == 0)
|
||||||
|
{
|
||||||
|
SDL_DisplayMode mode;
|
||||||
|
if(!SDL_GetCurrentDisplayMode(1, &mode))
|
||||||
|
return;
|
||||||
|
fps = mode.refresh_rate;
|
||||||
|
}
|
||||||
|
m_fps.SetMaxFPS(fps);
|
||||||
|
}
|
||||||
|
|
||||||
|
mlx_window Application::NewGraphicsSuport(const mlx_window_create_info* info)
|
||||||
|
{
|
||||||
|
MLX_PROFILE_FUNCTION();
|
||||||
|
if(!info)
|
||||||
|
{
|
||||||
|
Error("invalid window create info (NULL)");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
mlx_window window;
|
||||||
|
try { window = new mlx_window_handler; }
|
||||||
|
catch(...) { return nullptr; }
|
||||||
|
|
||||||
|
m_graphics.emplace_back(std::make_unique<GraphicsSupport>(info, m_graphics.size()));
|
||||||
|
if(m_graphics.back()->HasWindow())
|
||||||
|
m_in.RegisterWindow(m_graphics.back()->GetWindow());
|
||||||
|
m_graphics.back()->GetScene().BindFont(p_last_font_bound);
|
||||||
|
window->id = m_graphics.back()->GetID();
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
NonOwningPtr<GraphicsSupport> Application::GetGraphicsSupport(mlx_window win)
|
||||||
|
{
|
||||||
|
CHECK_WINDOW_PTR(win, nullptr);
|
||||||
|
return m_graphics[win->id].get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::DestroyGraphicsSupport(mlx_window win)
|
||||||
|
{
|
||||||
|
MLX_PROFILE_FUNCTION();
|
||||||
|
CHECK_WINDOW_PTR(win, );
|
||||||
|
m_graphics[win->id].reset();
|
||||||
|
delete win;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::LoadFont(const std::filesystem::path& filepath, float scale)
|
||||||
|
{
|
||||||
|
MLX_PROFILE_FUNCTION();
|
||||||
|
std::shared_ptr<Font> font = m_font_registry.GetFont(filepath, scale);
|
||||||
|
if(!font)
|
||||||
|
{
|
||||||
|
if(filepath.string() == "default")
|
||||||
|
font = std::make_shared<Font>("default", dogica_ttf, scale);
|
||||||
|
else
|
||||||
|
font = std::make_shared<Font>(filepath, scale);
|
||||||
|
font->BuildFont();
|
||||||
|
m_font_registry.RegisterFont(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
p_last_font_bound = font;
|
||||||
|
|
||||||
|
for(auto& gs : m_graphics)
|
||||||
|
{
|
||||||
|
if(gs)
|
||||||
|
gs->GetScene().BindFont(font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NonOwningPtr<Texture> Application::GetTexture(mlx_image image)
|
||||||
|
{
|
||||||
|
CHECK_IMAGE_PTR(image, nullptr);
|
||||||
|
NonOwningPtr<Texture> texture = image->texture;
|
||||||
|
if(!texture->IsInit())
|
||||||
|
{
|
||||||
|
Error("trying to use a texture that has been destroyed");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::AddLoopHook(void(*f)(void*), void* param)
|
||||||
|
{
|
||||||
|
m_hooks.emplace_back(f, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::LoopEnd() noexcept
|
||||||
|
{
|
||||||
|
m_in.Finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
31
runtime/Includes/Core/Enums.h
git.filemode.normal_file
31
runtime/Includes/Core/Enums.h
git.filemode.normal_file
@@ -0,0 +1,31 @@
|
|||||||
|
#ifndef __MLX_CORE_ENUMS__
|
||||||
|
#define __MLX_CORE_ENUMS__
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
enum class LogType
|
||||||
|
{
|
||||||
|
Message = 0,
|
||||||
|
Warning,
|
||||||
|
Error,
|
||||||
|
FatalError,
|
||||||
|
Debug,
|
||||||
|
|
||||||
|
EndEnum
|
||||||
|
};
|
||||||
|
constexpr std::size_t LogTypeCount = static_cast<std::size_t>(LogType::EndEnum);
|
||||||
|
|
||||||
|
enum class Event
|
||||||
|
{
|
||||||
|
ResizeEventCode = 56,
|
||||||
|
FrameBeginEventCode = 57,
|
||||||
|
FatalErrorEventCode = 168,
|
||||||
|
|
||||||
|
EndEnum
|
||||||
|
};
|
||||||
|
constexpr std::size_t EventCount = static_cast<std::size_t>(Event::EndEnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
12
runtime/Includes/Core/EventBase.h
git.filemode.normal_file
12
runtime/Includes/Core/EventBase.h
git.filemode.normal_file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef __MLX_BASE_EVENT__
|
||||||
|
#define __MLX_BASE_EVENT__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
struct EventBase
|
||||||
|
{
|
||||||
|
virtual Event What() const = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
23
runtime/Includes/Core/EventBus.h
git.filemode.normal_file
23
runtime/Includes/Core/EventBus.h
git.filemode.normal_file
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef __MLX_EVENT_BUS__
|
||||||
|
#define __MLX_EVENT_BUS__
|
||||||
|
|
||||||
|
#include <Core/EventBase.h>
|
||||||
|
#include <Core/EventListener.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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
|
||||||
25
runtime/Includes/Core/EventListener.h
git.filemode.normal_file
25
runtime/Includes/Core/EventListener.h
git.filemode.normal_file
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef __MLX_EVENT_LISTENER__
|
||||||
|
#define __MLX_EVENT_LISTENER__
|
||||||
|
|
||||||
|
#include <Core/EventBase.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class EventListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EventListener() = delete;
|
||||||
|
EventListener(std::function<void(const EventBase&)> functor, std::string name);
|
||||||
|
|
||||||
|
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
|
||||||
18
runtime/Includes/Core/Format.h
git.filemode.normal_file
18
runtime/Includes/Core/Format.h
git.filemode.normal_file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef __MLX_FORMAT__
|
||||||
|
#define __MLX_FORMAT__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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
|
||||||
133
runtime/Includes/Core/Format.inl
git.filemode.normal_file
133
runtime/Includes/Core/Format.inl
git.filemode.normal_file
@@ -0,0 +1,133 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Core/Format.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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...)};
|
||||||
|
}
|
||||||
|
}
|
||||||
27
runtime/Includes/Core/Fps.h
git.filemode.normal_file
27
runtime/Includes/Core/Fps.h
git.filemode.normal_file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef __MLX_FPS__
|
||||||
|
#define __MLX_FPS__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class FpsManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FpsManager() = default;
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
bool Update();
|
||||||
|
inline void SetMaxFPS(std::uint32_t fps) noexcept { m_max_fps = fps; m_ns = 1000000000.0 / fps; }
|
||||||
|
|
||||||
|
~FpsManager() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_ns = 1000000000.0 / 1'337'000.0;
|
||||||
|
std::int64_t m_fps_before = 0;
|
||||||
|
std::int64_t m_fps_now = 0;
|
||||||
|
std::int64_t m_timer = 0;
|
||||||
|
std::uint32_t m_max_fps = 1'337'000;
|
||||||
|
std::uint32_t m_fps_elapsed_time = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
59
runtime/Includes/Core/Graphics.h
git.filemode.normal_file
59
runtime/Includes/Core/Graphics.h
git.filemode.normal_file
@@ -0,0 +1,59 @@
|
|||||||
|
#ifndef __MLX_GRAPHICS__
|
||||||
|
#define __MLX_GRAPHICS__
|
||||||
|
|
||||||
|
#include <mlx.h>
|
||||||
|
#include <Platform/Window.h>
|
||||||
|
#include <Renderer/Renderer.h>
|
||||||
|
#include <Graphics/Scene.h>
|
||||||
|
#include <Graphics/Sprite.h>
|
||||||
|
#include <Graphics/PutPixelManager.h>
|
||||||
|
#include <Renderer/ScenesRenderer.h>
|
||||||
|
#include <Maths/Mat4.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class GraphicsSupport : public NonCopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GraphicsSupport(const mlx_window_create_info* info, int id);
|
||||||
|
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE int& GetID() noexcept { return m_id; }
|
||||||
|
[[nodiscard]] inline std::shared_ptr<Window> GetWindow() { return p_window; }
|
||||||
|
|
||||||
|
void Render() noexcept;
|
||||||
|
|
||||||
|
void ResetRenderData(mlx_color color) noexcept;
|
||||||
|
|
||||||
|
void PixelPut(int x, int y, mlx_color color) noexcept;
|
||||||
|
void PixelPutArray(int x, int y, mlx_color* color, std::size_t pixels_size) noexcept;
|
||||||
|
void PixelPutRegion(int x, int y, int w, int h, mlx_color* color) noexcept;
|
||||||
|
void StringPut(int x, int y, mlx_color color, std::string str);
|
||||||
|
void TexturePut(NonOwningPtr<class Texture> texture, int x, int y, float scale_x, float scale_y, float angle);
|
||||||
|
|
||||||
|
inline void TryEraseSpritesInScene(NonOwningPtr<Texture> texture) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE bool HasWindow() const noexcept { return m_has_window; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE Renderer& GetRenderer() { return m_renderer; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE Scene& GetScene() { return *p_scene; }
|
||||||
|
|
||||||
|
~GraphicsSupport();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Renderer m_renderer;
|
||||||
|
SceneRenderer m_scene_renderer;
|
||||||
|
PutPixelManager m_put_pixel_manager;
|
||||||
|
std::shared_ptr<Window> p_window;
|
||||||
|
std::unique_ptr<Scene> p_scene;
|
||||||
|
|
||||||
|
std::uint64_t m_draw_layer = 0;
|
||||||
|
|
||||||
|
int m_id;
|
||||||
|
|
||||||
|
bool m_has_window;
|
||||||
|
bool m_pixelput_called = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Core/Graphics.inl>
|
||||||
|
|
||||||
|
#endif
|
||||||
11
runtime/Includes/Core/Graphics.inl
git.filemode.normal_file
11
runtime/Includes/Core/Graphics.inl
git.filemode.normal_file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Core/Graphics.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
void GraphicsSupport::TryEraseSpritesInScene(NonOwningPtr<Texture> texture) noexcept
|
||||||
|
{
|
||||||
|
MLX_PROFILE_FUNCTION();
|
||||||
|
p_scene->TryEraseSpriteFromTexture(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
runtime/Includes/Core/Handles.h
git.filemode.normal_file
22
runtime/Includes/Core/Handles.h
git.filemode.normal_file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef __MLX_HANDLES__
|
||||||
|
#define __MLX_HANDLES__
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
struct mlx_context_handler
|
||||||
|
{
|
||||||
|
mlx::NonOwningPtr<mlx::Application> app;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mlx_window_handler
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mlx_image_handler
|
||||||
|
{
|
||||||
|
mlx::NonOwningPtr<mlx::Texture> texture;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
24
runtime/Includes/Core/ImagesRegistry.h
git.filemode.normal_file
24
runtime/Includes/Core/ImagesRegistry.h
git.filemode.normal_file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef __MLX_CORE_IMAGES_REGISTRY__
|
||||||
|
#define __MLX_CORE_IMAGES_REGISTRY__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class ImageRegistry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImageRegistry() = default;
|
||||||
|
|
||||||
|
inline void RegisterTexture(NonOwningPtr<class Texture> texture);
|
||||||
|
inline void UnregisterTexture(NonOwningPtr<class Texture> texture);
|
||||||
|
inline bool IsTextureKnown(NonOwningPtr<class Texture> texture);
|
||||||
|
|
||||||
|
~ImageRegistry() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_set<NonOwningPtr<class Texture>> m_textures_registry;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Core/ImagesRegistry.inl>
|
||||||
|
|
||||||
|
#endif
|
||||||
20
runtime/Includes/Core/ImagesRegistry.inl
git.filemode.normal_file
20
runtime/Includes/Core/ImagesRegistry.inl
git.filemode.normal_file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Core/ImagesRegistry.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
void ImageRegistry::RegisterTexture(NonOwningPtr<class Texture> texture)
|
||||||
|
{
|
||||||
|
m_textures_registry.insert(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageRegistry::UnregisterTexture(NonOwningPtr<class Texture> texture)
|
||||||
|
{
|
||||||
|
m_textures_registry.erase(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImageRegistry::IsTextureKnown(NonOwningPtr<class Texture> texture)
|
||||||
|
{
|
||||||
|
return m_textures_registry.find(texture) != m_textures_registry.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
72
runtime/Includes/Core/Logs.h
git.filemode.normal_file
72
runtime/Includes/Core/Logs.h
git.filemode.normal_file
@@ -0,0 +1,72 @@
|
|||||||
|
#ifndef __MLX_LOGS__
|
||||||
|
#define __MLX_LOGS__
|
||||||
|
|
||||||
|
#include <Core/Enums.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef 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([[maybe_unused]] bool cond, [[maybe_unused]] unsigned int line, [[maybe_unused]] std::string_view file, [[maybe_unused]] std::string_view function, [[maybe_unused]] std::string message, [[maybe_unused]] const Args&... args) {}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Core/Logs.inl>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
#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
|
||||||
124
runtime/Includes/Core/Logs.inl
git.filemode.normal_file
124
runtime/Includes/Core/Logs.inl
git.filemode.normal_file
@@ -0,0 +1,124 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Core/Logs.h>
|
||||||
|
#include <Core/Format.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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, line, file, function, "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, line, file, function, "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, line, file, function, "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, line, file, function, "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::FatalError, line, file, function, "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::FatalError, line, file, function, "formatter exception catched in the log printer: "s + e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef 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::FatalError, line, file, function, "formatter exception catched in the log printer: "s + e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
40
runtime/Includes/Core/Memory.h
git.filemode.normal_file
40
runtime/Includes/Core/Memory.h
git.filemode.normal_file
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef __MLX_MEMORY__
|
||||||
|
#define __MLX_MEMORY__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class MemManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MemManager();
|
||||||
|
|
||||||
|
static void* Malloc(std::size_t size);
|
||||||
|
static void* AlignedMalloc(std::size_t alignment, std::size_t size);
|
||||||
|
static void* Calloc(std::size_t n, std::size_t size);
|
||||||
|
static void* AlignedCalloc(std::size_t alignment, std::size_t n, std::size_t size);
|
||||||
|
static void* Realloc(void* ptr, std::size_t size);
|
||||||
|
static void* AlignedRealloc(void* ptr, std::size_t alignment, std::size_t size);
|
||||||
|
static void Free(void* ptr);
|
||||||
|
|
||||||
|
static inline bool IsInit() noexcept { return s_instance != nullptr; }
|
||||||
|
static inline MemManager& Get() noexcept { return *s_instance; }
|
||||||
|
|
||||||
|
~MemManager();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Descriptor
|
||||||
|
{
|
||||||
|
void* ptr;
|
||||||
|
std::size_t size;
|
||||||
|
bool aligned;
|
||||||
|
|
||||||
|
Descriptor(void* ptr, std::size_t size, bool aligned) : ptr(ptr), size(size), aligned(aligned) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
static MemManager* s_instance;
|
||||||
|
inline static std::vector<Descriptor> s_blocks;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
126
runtime/Includes/Core/Profiler.h
git.filemode.normal_file
126
runtime/Includes/Core/Profiler.h
git.filemode.normal_file
@@ -0,0 +1,126 @@
|
|||||||
|
#ifndef __MLX_PROFILER__
|
||||||
|
#define __MLX_PROFILER__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
using FloatingPointMilliseconds = std::chrono::duration<double, std::milli>;
|
||||||
|
|
||||||
|
struct ProfileResult
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
FloatingPointMilliseconds elapsed_time;
|
||||||
|
std::thread::id thread_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Profiler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Profiler(const Profiler&) = delete;
|
||||||
|
Profiler(Profiler&&) = delete;
|
||||||
|
Profiler() { BeginRuntimeSession(); s_instance = this; }
|
||||||
|
|
||||||
|
void AppendProfileData(ProfileResult&& result);
|
||||||
|
|
||||||
|
inline static bool IsInit() noexcept { return s_instance != nullptr; }
|
||||||
|
inline static Profiler& Get() noexcept { return *s_instance; }
|
||||||
|
|
||||||
|
~Profiler();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void BeginRuntimeSession();
|
||||||
|
void WriteProfile(const ProfileResult& result);
|
||||||
|
void EndRuntimeSession();
|
||||||
|
inline void WriteHeader()
|
||||||
|
{
|
||||||
|
m_output_stream << "{\"profileData\":[{}";
|
||||||
|
m_output_stream.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void WriteFooter()
|
||||||
|
{
|
||||||
|
m_output_stream << "]}";
|
||||||
|
m_output_stream.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Profiler* s_instance;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::pair<std::size_t, ProfileResult>> m_profile_data;
|
||||||
|
std::ofstream m_output_stream;
|
||||||
|
std::mutex m_mutex;
|
||||||
|
bool m_runtime_session_began = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ProfilerTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProfilerTimer(const char* name) : m_name(name)
|
||||||
|
{
|
||||||
|
m_start_timepoint = std::chrono::steady_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Stop()
|
||||||
|
{
|
||||||
|
auto end_timepoint = std::chrono::steady_clock::now();
|
||||||
|
auto high_res_start = FloatingPointMilliseconds{ m_start_timepoint.time_since_epoch() };
|
||||||
|
auto elapsed_time = std::chrono::time_point_cast<std::chrono::milliseconds>(end_timepoint).time_since_epoch() - std::chrono::time_point_cast<std::chrono::milliseconds>(m_start_timepoint).time_since_epoch();
|
||||||
|
|
||||||
|
Profiler::Get().AppendProfileData({ m_name, elapsed_time, std::this_thread::get_id() });
|
||||||
|
|
||||||
|
m_stopped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ProfilerTimer()
|
||||||
|
{
|
||||||
|
if(!m_stopped)
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock> m_start_timepoint;
|
||||||
|
const char* m_name;
|
||||||
|
bool m_stopped = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ProfilerUtils
|
||||||
|
{
|
||||||
|
template <std::size_t N>
|
||||||
|
struct ChangeResult
|
||||||
|
{
|
||||||
|
char data[N];
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::size_t N, std::size_t K>
|
||||||
|
constexpr auto CleanupOutputString(const char(&expr)[N], const char(&remove)[K])
|
||||||
|
{
|
||||||
|
ChangeResult<N> result = {};
|
||||||
|
|
||||||
|
std::size_t src_index = 0;
|
||||||
|
std::size_t dst_index = 0;
|
||||||
|
while(src_index < N)
|
||||||
|
{
|
||||||
|
std::size_t match_index = 0;
|
||||||
|
while(match_index < K - 1 && src_index + match_index < N - 1 && expr[src_index + match_index] == remove[match_index])
|
||||||
|
match_index++;
|
||||||
|
if(match_index == K - 1)
|
||||||
|
src_index += match_index;
|
||||||
|
result.data[dst_index++] = expr[src_index] == '"' ? '\'' : expr[src_index];
|
||||||
|
src_index++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PROFILER
|
||||||
|
#define MLX_PROFILE_SCOPE_LINE2(name, line) constexpr auto fixed_name_##line = ::mlx::ProfilerUtils::CleanupOutputString(name, "__cdecl ");\
|
||||||
|
::mlx::ProfilerTimer timer##line(fixed_name_##line.data)
|
||||||
|
#define MLX_PROFILE_SCOPE_LINE(name, line) MLX_PROFILE_SCOPE_LINE2(name, line)
|
||||||
|
#define MLX_PROFILE_SCOPE(name) MLX_PROFILE_SCOPE_LINE(name, __LINE__)
|
||||||
|
#define MLX_PROFILE_FUNCTION() MLX_PROFILE_SCOPE(MLX_FUNC_SIG)
|
||||||
|
#else
|
||||||
|
#define MLX_PROFILE_SCOPE(name)
|
||||||
|
#define MLX_PROFILE_FUNCTION()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
58
runtime/Includes/Core/SDLManager.h
git.filemode.normal_file
58
runtime/Includes/Core/SDLManager.h
git.filemode.normal_file
@@ -0,0 +1,58 @@
|
|||||||
|
#ifndef __MLX_SDL_MANAGER__
|
||||||
|
#define __MLX_SDL_MANAGER__
|
||||||
|
|
||||||
|
#include <mlx.h>
|
||||||
|
#include <Maths/Vec2.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class SDLManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SDLManager();
|
||||||
|
|
||||||
|
Handle CreateWindow(const mlx_window_create_info* info, std::int32_t& id, bool hidden);
|
||||||
|
void DestroyWindow(Handle window) noexcept;
|
||||||
|
|
||||||
|
void InputsFetcher(std::function<void(mlx_event_type, int, int)> functor);
|
||||||
|
|
||||||
|
VkSurfaceKHR CreateVulkanSurface(Handle window, VkInstance instance) const noexcept;
|
||||||
|
std::vector<const char*> GetRequiredVulkanInstanceExtentions(Handle window) const noexcept;
|
||||||
|
Vec2ui GetVulkanDrawableSize(Handle window) const noexcept;
|
||||||
|
void MoveMouseOnWindow(Handle window, int x, int y) const noexcept;
|
||||||
|
void GetScreenSizeWindowIsOn(Handle window, int* x, int* y) const noexcept;
|
||||||
|
void SetWindowPosition(Handle window, int x, int y) const noexcept;
|
||||||
|
void SetWindowSize(Handle window, int x, int y) const noexcept;
|
||||||
|
void SetWindowTitle(Handle window, std::string_view title) const noexcept;
|
||||||
|
void SetWindowFullscreen(Handle window, bool enable) const noexcept;
|
||||||
|
void SetWindowMaxSize(Handle window, int x, int y) const noexcept;
|
||||||
|
void SetWindowMinSize(Handle window, int x, int y) const noexcept;
|
||||||
|
void MaximizeWindow(Handle window) const noexcept;
|
||||||
|
void MinimizeWindow(Handle window) const noexcept;
|
||||||
|
void RestoreWindow(Handle window) const noexcept;
|
||||||
|
|
||||||
|
void GetWindowPosition(Handle window, int* x, int* y) const noexcept;
|
||||||
|
void GetWindowSize(Handle window, int* x, int* y) const noexcept;
|
||||||
|
|
||||||
|
static void HideCursor() noexcept;
|
||||||
|
static void ShowCursor() noexcept;
|
||||||
|
|
||||||
|
std::int32_t GetX() const noexcept;
|
||||||
|
std::int32_t GetY() const noexcept;
|
||||||
|
std::int32_t GetXRel() const noexcept;
|
||||||
|
std::int32_t GetYRel() const noexcept;
|
||||||
|
|
||||||
|
inline static bool IsInit() noexcept { return s_instance != nullptr; }
|
||||||
|
inline static SDLManager& Get() noexcept { return *s_instance; }
|
||||||
|
|
||||||
|
~SDLManager();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static SDLManager* s_instance;
|
||||||
|
|
||||||
|
std::unordered_set<Handle> m_windows_registry;
|
||||||
|
bool m_drop_sdl_responsability = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#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 __MLX_UUID__
|
||||||
|
#define __MLX_UUID__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class UUID
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UUID();
|
||||||
|
UUID(std::uint64_t uuid);
|
||||||
|
|
||||||
|
inline operator std::uint64_t() const { return m_uuid; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::uint64_t m_uuid;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,20 +1,6 @@
|
|||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* dogica_ttf.h :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2023/04/11 16:20:25 by maldavid #+# #+# */
|
|
||||||
/* Updated: 2023/12/14 16:54:12 by maldavid ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#ifndef __MLX_DOGICA_TTF__
|
#ifndef __MLX_DOGICA_TTF__
|
||||||
#define __MLX_DOGICA_TTF__
|
#define __MLX_DOGICA_TTF__
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
constexpr const unsigned int dogica_ttf_len = 33860;
|
constexpr const unsigned int dogica_ttf_len = 33860;
|
||||||
|
|
||||||
static const std::vector<unsigned char> dogica_ttf = {
|
static const std::vector<unsigned char> dogica_ttf = {
|
||||||
@@ -1,20 +1,6 @@
|
|||||||
/* ************************************************************************** */
|
|
||||||
/* */
|
|
||||||
/* ::: :::::::: */
|
|
||||||
/* icon_mlx.h :+: :+: :+: */
|
|
||||||
/* +:+ +:+ +:+ */
|
|
||||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
|
||||||
/* +#+#+#+#+#+ +#+ */
|
|
||||||
/* Created: 2023/11/25 11:23:16 by maldavid #+# #+# */
|
|
||||||
/* Updated: 2023/11/25 11:55:51 by maldavid ### ########.fr */
|
|
||||||
/* */
|
|
||||||
/* ************************************************************************** */
|
|
||||||
|
|
||||||
#ifndef __ICON_MLX__
|
#ifndef __ICON_MLX__
|
||||||
#define __ICON_MLX__
|
#define __ICON_MLX__
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
constexpr const int logo_mlx_height = 125;
|
constexpr const int logo_mlx_height = 125;
|
||||||
constexpr const int logo_mlx_width = 125;
|
constexpr const int logo_mlx_width = 125;
|
||||||
constexpr const int logo_mlx_size = logo_mlx_height * logo_mlx_width * 4;
|
constexpr const int logo_mlx_size = logo_mlx_height * logo_mlx_width * 4;
|
||||||
28
runtime/Includes/Embedded/Shader2DFragment.nzsl
git.filemode.normal_file
28
runtime/Includes/Embedded/Shader2DFragment.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;
|
||||||
|
}
|
||||||
44
runtime/Includes/Embedded/Shader2DFragment.spv.h
git.filemode.normal_file
44
runtime/Includes/Embedded/Shader2DFragment.spv.h
git.filemode.normal_file
@@ -0,0 +1,44 @@
|
|||||||
|
3,2,35,7,0,0,1,0,39,0,0,0,51,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,14,0,
|
||||||
|
3,0,0,0,0,0,1,0,0,0,15,0,8,0,4,0,0,0,28,0,0,0,109,97,105,110,0,0,0,0,
|
||||||
|
10,0,0,0,16,0,0,0,22,0,0,0,16,0,3,0,28,0,0,0,7,0,0,0,3,0,3,0,0,0,
|
||||||
|
0,0,100,0,0,0,5,0,4,0,19,0,0,0,86,101,114,116,79,117,116,0,6,0,5,0,19,0,0,0,
|
||||||
|
0,0,0,0,99,111,108,111,114,0,0,0,6,0,4,0,19,0,0,0,1,0,0,0,117,118,0,0,5,0,
|
||||||
|
4,0,23,0,0,0,70,114,97,103,79,117,116,0,6,0,5,0,23,0,0,0,0,0,0,0,99,111,108,111,
|
||||||
|
114,0,0,0,5,0,5,0,5,0,0,0,117,95,116,101,120,116,117,114,101,0,0,0,5,0,4,0,10,0,
|
||||||
|
0,0,99,111,108,111,114,0,0,0,5,0,3,0,16,0,0,0,117,118,0,0,5,0,4,0,22,0,0,0,
|
||||||
|
99,111,108,111,114,0,0,0,5,0,4,0,28,0,0,0,109,97,105,110,0,0,0,0,71,0,4,0,5,0,
|
||||||
|
0,0,33,0,0,0,0,0,0,0,71,0,4,0,5,0,0,0,34,0,0,0,1,0,0,0,71,0,4,0,
|
||||||
|
10,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,16,0,0,0,30,0,0,0,1,0,0,0,71,0,
|
||||||
|
4,0,22,0,0,0,30,0,0,0,0,0,0,0,72,0,5,0,19,0,0,0,0,0,0,0,35,0,0,0,
|
||||||
|
0,0,0,0,72,0,5,0,19,0,0,0,1,0,0,0,35,0,0,0,16,0,0,0,72,0,5,0,23,0,
|
||||||
|
0,0,0,0,0,0,35,0,0,0,0,0,0,0,22,0,3,0,1,0,0,0,32,0,0,0,25,0,9,0,
|
||||||
|
2,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
|
||||||
|
0,0,27,0,3,0,3,0,0,0,2,0,0,0,32,0,4,0,4,0,0,0,0,0,0,0,3,0,0,0,
|
||||||
|
19,0,2,0,6,0,0,0,33,0,3,0,7,0,0,0,6,0,0,0,23,0,4,0,8,0,0,0,1,0,
|
||||||
|
0,0,4,0,0,0,32,0,4,0,9,0,0,0,1,0,0,0,8,0,0,0,21,0,4,0,11,0,0,0,
|
||||||
|
32,0,0,0,1,0,0,0,43,0,4,0,11,0,0,0,12,0,0,0,0,0,0,0,32,0,4,0,13,0,
|
||||||
|
0,0,7,0,0,0,8,0,0,0,23,0,4,0,14,0,0,0,1,0,0,0,2,0,0,0,32,0,4,0,
|
||||||
|
15,0,0,0,1,0,0,0,14,0,0,0,43,0,4,0,11,0,0,0,17,0,0,0,1,0,0,0,32,0,
|
||||||
|
4,0,18,0,0,0,7,0,0,0,14,0,0,0,30,0,4,0,19,0,0,0,8,0,0,0,14,0,0,0,
|
||||||
|
32,0,4,0,20,0,0,0,7,0,0,0,19,0,0,0,32,0,4,0,21,0,0,0,3,0,0,0,8,0,
|
||||||
|
0,0,30,0,3,0,23,0,0,0,8,0,0,0,32,0,4,0,24,0,0,0,7,0,0,0,23,0,0,0,
|
||||||
|
43,0,4,0,11,0,0,0,25,0,0,0,3,0,0,0,43,0,4,0,1,0,0,0,26,0,0,0,0,0,
|
||||||
|
0,0,20,0,2,0,27,0,0,0,59,0,4,0,4,0,0,0,5,0,0,0,0,0,0,0,59,0,4,0,
|
||||||
|
9,0,0,0,10,0,0,0,1,0,0,0,59,0,4,0,15,0,0,0,16,0,0,0,1,0,0,0,59,0,
|
||||||
|
4,0,21,0,0,0,22,0,0,0,3,0,0,0,54,0,5,0,6,0,0,0,28,0,0,0,0,0,0,0,
|
||||||
|
7,0,0,0,248,0,2,0,29,0,0,0,59,0,4,0,24,0,0,0,30,0,0,0,7,0,0,0,59,0,
|
||||||
|
4,0,20,0,0,0,31,0,0,0,7,0,0,0,65,0,5,0,13,0,0,0,32,0,0,0,31,0,0,0,
|
||||||
|
12,0,0,0,63,0,3,0,32,0,0,0,10,0,0,0,65,0,5,0,18,0,0,0,33,0,0,0,31,0,
|
||||||
|
0,0,17,0,0,0,63,0,3,0,33,0,0,0,16,0,0,0,65,0,5,0,13,0,0,0,34,0,0,0,
|
||||||
|
31,0,0,0,12,0,0,0,61,0,4,0,8,0,0,0,35,0,0,0,34,0,0,0,61,0,4,0,3,0,
|
||||||
|
0,0,36,0,0,0,5,0,0,0,65,0,5,0,18,0,0,0,37,0,0,0,31,0,0,0,17,0,0,0,
|
||||||
|
61,0,4,0,14,0,0,0,38,0,0,0,37,0,0,0,87,0,5,0,8,0,0,0,39,0,0,0,36,0,
|
||||||
|
0,0,38,0,0,0,133,0,5,0,8,0,0,0,40,0,0,0,35,0,0,0,39,0,0,0,65,0,5,0,
|
||||||
|
13,0,0,0,41,0,0,0,30,0,0,0,12,0,0,0,62,0,3,0,41,0,0,0,40,0,0,0,65,0,
|
||||||
|
5,0,13,0,0,0,45,0,0,0,30,0,0,0,12,0,0,0,61,0,4,0,8,0,0,0,46,0,0,0,
|
||||||
|
45,0,0,0,81,0,5,0,1,0,0,0,47,0,0,0,46,0,0,0,3,0,0,0,180,0,5,0,27,0,
|
||||||
|
0,0,48,0,0,0,47,0,0,0,26,0,0,0,247,0,3,0,42,0,0,0,0,0,0,0,250,0,4,0,
|
||||||
|
48,0,0,0,43,0,0,0,44,0,0,0,248,0,2,0,43,0,0,0,252,0,1,0,248,0,2,0,44,0,
|
||||||
|
0,0,249,0,2,0,42,0,0,0,248,0,2,0,42,0,0,0,61,0,4,0,23,0,0,0,49,0,0,0,
|
||||||
|
30,0,0,0,81,0,5,0,8,0,0,0,50,0,0,0,49,0,0,0,0,0,0,0,62,0,3,0,22,0,
|
||||||
|
0,0,50,0,0,0,253,0,1,0,56,0,1,0
|
||||||
44
runtime/Includes/Embedded/Shader2DVertex.nzsl
git.filemode.normal_file
44
runtime/Includes/Embedded/Shader2DVertex.nzsl
git.filemode.normal_file
@@ -0,0 +1,44 @@
|
|||||||
|
[nzsl_version("1.0")]
|
||||||
|
module;
|
||||||
|
|
||||||
|
struct VertIn
|
||||||
|
{
|
||||||
|
[location(0)] pos: vec4[f32],
|
||||||
|
[location(1)] 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 *= -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;
|
||||||
|
}
|
||||||
72
runtime/Includes/Embedded/Shader2DVertex.spv.h
git.filemode.normal_file
72
runtime/Includes/Embedded/Shader2DVertex.spv.h
git.filemode.normal_file
@@ -0,0 +1,72 @@
|
|||||||
|
3,2,35,7,0,0,1,0,39,0,0,0,71,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,14,0,
|
||||||
|
3,0,0,0,0,0,1,0,0,0,15,0,10,0,0,0,0,0,35,0,0,0,109,97,105,110,0,0,0,0,
|
||||||
|
13,0,0,0,19,0,0,0,25,0,0,0,27,0,0,0,28,0,0,0,3,0,3,0,0,0,0,0,100,0,
|
||||||
|
0,0,5,0,5,0,4,0,0,0,86,105,101,119,101,114,68,97,116,97,0,0,6,0,8,0,4,0,0,0,
|
||||||
|
0,0,0,0,112,114,111,106,101,99,116,105,111,110,95,109,97,116,114,105,120,0,0,0,5,0,5,0,7,0,
|
||||||
|
0,0,83,112,114,105,116,101,68,97,116,97,0,0,6,0,7,0,7,0,0,0,0,0,0,0,109,111,100,101,
|
||||||
|
108,95,109,97,116,114,105,120,0,0,0,0,6,0,5,0,7,0,0,0,1,0,0,0,99,111,108,111,114,0,
|
||||||
|
0,0,5,0,4,0,22,0,0,0,86,101,114,116,73,110,0,0,6,0,4,0,22,0,0,0,0,0,0,0,
|
||||||
|
112,111,115,0,6,0,4,0,22,0,0,0,1,0,0,0,117,118,0,0,5,0,4,0,29,0,0,0,86,101,
|
||||||
|
114,116,79,117,116,0,6,0,5,0,29,0,0,0,0,0,0,0,99,111,108,111,114,0,0,0,6,0,4,0,
|
||||||
|
29,0,0,0,1,0,0,0,117,118,0,0,6,0,4,0,29,0,0,0,2,0,0,0,112,111,115,0,5,0,
|
||||||
|
5,0,6,0,0,0,118,105,101,119,101,114,95,100,97,116,97,0,5,0,4,0,9,0,0,0,109,111,100,101,
|
||||||
|
108,0,0,0,5,0,3,0,13,0,0,0,112,111,115,0,5,0,3,0,19,0,0,0,117,118,0,0,5,0,
|
||||||
|
4,0,25,0,0,0,99,111,108,111,114,0,0,0,5,0,3,0,27,0,0,0,117,118,0,0,5,0,5,0,
|
||||||
|
28,0,0,0,112,111,115,105,116,105,111,110,0,0,0,0,5,0,4,0,35,0,0,0,109,97,105,110,0,0,
|
||||||
|
0,0,71,0,4,0,6,0,0,0,33,0,0,0,0,0,0,0,71,0,4,0,6,0,0,0,34,0,0,0,
|
||||||
|
0,0,0,0,71,0,4,0,28,0,0,0,11,0,0,0,0,0,0,0,71,0,4,0,13,0,0,0,30,0,
|
||||||
|
0,0,0,0,0,0,71,0,4,0,19,0,0,0,30,0,0,0,1,0,0,0,71,0,4,0,25,0,0,0,
|
||||||
|
30,0,0,0,0,0,0,0,71,0,4,0,27,0,0,0,30,0,0,0,1,0,0,0,71,0,3,0,4,0,
|
||||||
|
0,0,2,0,0,0,72,0,4,0,4,0,0,0,0,0,0,0,5,0,0,0,72,0,5,0,4,0,0,0,
|
||||||
|
0,0,0,0,7,0,0,0,16,0,0,0,72,0,5,0,4,0,0,0,0,0,0,0,35,0,0,0,0,0,
|
||||||
|
0,0,71,0,3,0,7,0,0,0,2,0,0,0,72,0,4,0,7,0,0,0,0,0,0,0,5,0,0,0,
|
||||||
|
72,0,5,0,7,0,0,0,0,0,0,0,7,0,0,0,16,0,0,0,72,0,5,0,7,0,0,0,0,0,
|
||||||
|
0,0,35,0,0,0,0,0,0,0,72,0,5,0,7,0,0,0,1,0,0,0,35,0,0,0,64,0,0,0,
|
||||||
|
72,0,5,0,22,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,72,0,5,0,22,0,0,0,1,0,
|
||||||
|
0,0,35,0,0,0,16,0,0,0,72,0,5,0,29,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,
|
||||||
|
72,0,5,0,29,0,0,0,1,0,0,0,35,0,0,0,16,0,0,0,72,0,5,0,29,0,0,0,2,0,
|
||||||
|
0,0,35,0,0,0,32,0,0,0,22,0,3,0,1,0,0,0,32,0,0,0,23,0,4,0,2,0,0,0,
|
||||||
|
1,0,0,0,4,0,0,0,24,0,4,0,3,0,0,0,2,0,0,0,4,0,0,0,30,0,3,0,4,0,
|
||||||
|
0,0,3,0,0,0,32,0,4,0,5,0,0,0,2,0,0,0,4,0,0,0,30,0,4,0,7,0,0,0,
|
||||||
|
3,0,0,0,2,0,0,0,32,0,4,0,8,0,0,0,9,0,0,0,7,0,0,0,19,0,2,0,10,0,
|
||||||
|
0,0,33,0,3,0,11,0,0,0,10,0,0,0,32,0,4,0,12,0,0,0,1,0,0,0,2,0,0,0,
|
||||||
|
21,0,4,0,14,0,0,0,32,0,0,0,1,0,0,0,43,0,4,0,14,0,0,0,15,0,0,0,0,0,
|
||||||
|
0,0,32,0,4,0,16,0,0,0,7,0,0,0,2,0,0,0,23,0,4,0,17,0,0,0,1,0,0,0,
|
||||||
|
2,0,0,0,32,0,4,0,18,0,0,0,1,0,0,0,17,0,0,0,43,0,4,0,14,0,0,0,20,0,
|
||||||
|
0,0,1,0,0,0,32,0,4,0,21,0,0,0,7,0,0,0,17,0,0,0,30,0,4,0,22,0,0,0,
|
||||||
|
2,0,0,0,17,0,0,0,32,0,4,0,23,0,0,0,7,0,0,0,22,0,0,0,32,0,4,0,24,0,
|
||||||
|
0,0,3,0,0,0,2,0,0,0,32,0,4,0,26,0,0,0,3,0,0,0,17,0,0,0,30,0,5,0,
|
||||||
|
29,0,0,0,2,0,0,0,17,0,0,0,2,0,0,0,43,0,4,0,1,0,0,0,30,0,0,0,0,0,
|
||||||
|
0,0,43,0,4,0,1,0,0,0,31,0,0,0,0,0,128,63,43,0,4,0,1,0,0,0,32,0,0,0,
|
||||||
|
0,0,128,191,32,0,4,0,33,0,0,0,7,0,0,0,29,0,0,0,43,0,4,0,14,0,0,0,34,0,
|
||||||
|
0,0,2,0,0,0,32,0,4,0,53,0,0,0,9,0,0,0,2,0,0,0,32,0,4,0,57,0,0,0,
|
||||||
|
2,0,0,0,3,0,0,0,32,0,4,0,60,0,0,0,9,0,0,0,3,0,0,0,59,0,4,0,5,0,
|
||||||
|
0,0,6,0,0,0,2,0,0,0,59,0,4,0,8,0,0,0,9,0,0,0,9,0,0,0,59,0,4,0,
|
||||||
|
12,0,0,0,13,0,0,0,1,0,0,0,59,0,4,0,18,0,0,0,19,0,0,0,1,0,0,0,59,0,
|
||||||
|
4,0,24,0,0,0,25,0,0,0,3,0,0,0,59,0,4,0,26,0,0,0,27,0,0,0,3,0,0,0,
|
||||||
|
59,0,4,0,24,0,0,0,28,0,0,0,3,0,0,0,54,0,5,0,10,0,0,0,35,0,0,0,0,0,
|
||||||
|
0,0,11,0,0,0,248,0,2,0,36,0,0,0,59,0,4,0,16,0,0,0,37,0,0,0,7,0,0,0,
|
||||||
|
59,0,4,0,33,0,0,0,38,0,0,0,7,0,0,0,59,0,4,0,23,0,0,0,39,0,0,0,7,0,
|
||||||
|
0,0,65,0,5,0,16,0,0,0,40,0,0,0,39,0,0,0,15,0,0,0,63,0,3,0,40,0,0,0,
|
||||||
|
13,0,0,0,65,0,5,0,21,0,0,0,41,0,0,0,39,0,0,0,20,0,0,0,63,0,3,0,41,0,
|
||||||
|
0,0,19,0,0,0,65,0,5,0,16,0,0,0,42,0,0,0,39,0,0,0,15,0,0,0,61,0,4,0,
|
||||||
|
2,0,0,0,43,0,0,0,42,0,0,0,79,0,7,0,17,0,0,0,44,0,0,0,43,0,0,0,43,0,
|
||||||
|
0,0,0,0,0,0,1,0,0,0,80,0,6,0,2,0,0,0,45,0,0,0,44,0,0,0,30,0,0,0,
|
||||||
|
31,0,0,0,62,0,3,0,37,0,0,0,45,0,0,0,65,0,5,0,21,0,0,0,46,0,0,0,39,0,
|
||||||
|
0,0,20,0,0,0,61,0,4,0,17,0,0,0,47,0,0,0,46,0,0,0,142,0,5,0,17,0,0,0,
|
||||||
|
48,0,0,0,47,0,0,0,32,0,0,0,65,0,5,0,21,0,0,0,49,0,0,0,39,0,0,0,20,0,
|
||||||
|
0,0,62,0,3,0,49,0,0,0,48,0,0,0,65,0,5,0,21,0,0,0,50,0,0,0,39,0,0,0,
|
||||||
|
20,0,0,0,61,0,4,0,17,0,0,0,51,0,0,0,50,0,0,0,65,0,5,0,21,0,0,0,52,0,
|
||||||
|
0,0,38,0,0,0,20,0,0,0,62,0,3,0,52,0,0,0,51,0,0,0,65,0,5,0,53,0,0,0,
|
||||||
|
54,0,0,0,9,0,0,0,20,0,0,0,61,0,4,0,2,0,0,0,55,0,0,0,54,0,0,0,65,0,
|
||||||
|
5,0,16,0,0,0,56,0,0,0,38,0,0,0,15,0,0,0,62,0,3,0,56,0,0,0,55,0,0,0,
|
||||||
|
65,0,5,0,57,0,0,0,58,0,0,0,6,0,0,0,15,0,0,0,61,0,4,0,3,0,0,0,59,0,
|
||||||
|
0,0,58,0,0,0,65,0,5,0,60,0,0,0,61,0,0,0,9,0,0,0,15,0,0,0,61,0,4,0,
|
||||||
|
3,0,0,0,62,0,0,0,61,0,0,0,146,0,5,0,3,0,0,0,63,0,0,0,59,0,0,0,62,0,
|
||||||
|
0,0,61,0,4,0,2,0,0,0,64,0,0,0,37,0,0,0,145,0,5,0,2,0,0,0,65,0,0,0,
|
||||||
|
63,0,0,0,64,0,0,0,65,0,5,0,16,0,0,0,66,0,0,0,38,0,0,0,34,0,0,0,62,0,
|
||||||
|
3,0,66,0,0,0,65,0,0,0,61,0,4,0,29,0,0,0,67,0,0,0,38,0,0,0,81,0,5,0,
|
||||||
|
2,0,0,0,68,0,0,0,67,0,0,0,0,0,0,0,62,0,3,0,25,0,0,0,68,0,0,0,81,0,
|
||||||
|
5,0,17,0,0,0,69,0,0,0,67,0,0,0,1,0,0,0,62,0,3,0,27,0,0,0,69,0,0,0,
|
||||||
|
81,0,5,0,2,0,0,0,70,0,0,0,67,0,0,0,2,0,0,0,62,0,3,0,28,0,0,0,70,0,
|
||||||
|
0,0,253,0,1,0,56,0,1,0
|
||||||
46
runtime/Includes/Embedded/ShaderScreenFragment.nzsl
git.filemode.normal_file
46
runtime/Includes/Embedded/ShaderScreenFragment.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
runtime/Includes/Embedded/ShaderScreenFragment.spv.h
git.filemode.normal_file
31
runtime/Includes/Embedded/ShaderScreenFragment.spv.h
git.filemode.normal_file
@@ -0,0 +1,31 @@
|
|||||||
|
3,2,35,7,0,0,1,0,39,0,0,0,34,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,14,0,
|
||||||
|
3,0,0,0,0,0,1,0,0,0,15,0,7,0,4,0,0,0,21,0,0,0,109,97,105,110,0,0,0,0,
|
||||||
|
10,0,0,0,18,0,0,0,16,0,3,0,21,0,0,0,7,0,0,0,3,0,3,0,0,0,0,0,100,0,
|
||||||
|
0,0,5,0,4,0,14,0,0,0,86,101,114,116,79,117,116,0,6,0,4,0,14,0,0,0,0,0,0,0,
|
||||||
|
117,118,0,0,5,0,4,0,19,0,0,0,70,114,97,103,79,117,116,0,6,0,5,0,19,0,0,0,0,0,
|
||||||
|
0,0,99,111,108,111,114,0,0,0,5,0,5,0,5,0,0,0,117,95,116,101,120,116,117,114,101,0,0,0,
|
||||||
|
5,0,3,0,10,0,0,0,117,118,0,0,5,0,4,0,18,0,0,0,99,111,108,111,114,0,0,0,5,0,
|
||||||
|
4,0,21,0,0,0,109,97,105,110,0,0,0,0,71,0,4,0,5,0,0,0,33,0,0,0,0,0,0,0,
|
||||||
|
71,0,4,0,5,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,10,0,0,0,30,0,0,0,0,0,
|
||||||
|
0,0,71,0,4,0,18,0,0,0,30,0,0,0,0,0,0,0,72,0,5,0,14,0,0,0,0,0,0,0,
|
||||||
|
35,0,0,0,0,0,0,0,72,0,5,0,19,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,22,0,
|
||||||
|
3,0,1,0,0,0,32,0,0,0,25,0,9,0,2,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,27,0,3,0,3,0,0,0,2,0,0,0,32,0,
|
||||||
|
4,0,4,0,0,0,0,0,0,0,3,0,0,0,19,0,2,0,6,0,0,0,33,0,3,0,7,0,0,0,
|
||||||
|
6,0,0,0,23,0,4,0,8,0,0,0,1,0,0,0,2,0,0,0,32,0,4,0,9,0,0,0,1,0,
|
||||||
|
0,0,8,0,0,0,21,0,4,0,11,0,0,0,32,0,0,0,1,0,0,0,43,0,4,0,11,0,0,0,
|
||||||
|
12,0,0,0,0,0,0,0,32,0,4,0,13,0,0,0,7,0,0,0,8,0,0,0,30,0,3,0,14,0,
|
||||||
|
0,0,8,0,0,0,32,0,4,0,15,0,0,0,7,0,0,0,14,0,0,0,23,0,4,0,16,0,0,0,
|
||||||
|
1,0,0,0,4,0,0,0,32,0,4,0,17,0,0,0,3,0,0,0,16,0,0,0,30,0,3,0,19,0,
|
||||||
|
0,0,16,0,0,0,32,0,4,0,20,0,0,0,7,0,0,0,19,0,0,0,32,0,4,0,31,0,0,0,
|
||||||
|
7,0,0,0,16,0,0,0,59,0,4,0,4,0,0,0,5,0,0,0,0,0,0,0,59,0,4,0,9,0,
|
||||||
|
0,0,10,0,0,0,1,0,0,0,59,0,4,0,17,0,0,0,18,0,0,0,3,0,0,0,54,0,5,0,
|
||||||
|
6,0,0,0,21,0,0,0,0,0,0,0,7,0,0,0,248,0,2,0,22,0,0,0,59,0,4,0,20,0,
|
||||||
|
0,0,23,0,0,0,7,0,0,0,59,0,4,0,15,0,0,0,24,0,0,0,7,0,0,0,65,0,5,0,
|
||||||
|
13,0,0,0,25,0,0,0,24,0,0,0,12,0,0,0,63,0,3,0,25,0,0,0,10,0,0,0,61,0,
|
||||||
|
4,0,3,0,0,0,26,0,0,0,5,0,0,0,65,0,5,0,13,0,0,0,27,0,0,0,24,0,0,0,
|
||||||
|
12,0,0,0,61,0,4,0,8,0,0,0,28,0,0,0,27,0,0,0,87,0,5,0,16,0,0,0,29,0,
|
||||||
|
0,0,26,0,0,0,28,0,0,0,65,0,5,0,31,0,0,0,30,0,0,0,23,0,0,0,12,0,0,0,
|
||||||
|
62,0,3,0,30,0,0,0,29,0,0,0,61,0,4,0,19,0,0,0,32,0,0,0,23,0,0,0,81,0,
|
||||||
|
5,0,16,0,0,0,33,0,0,0,32,0,0,0,0,0,0,0,62,0,3,0,18,0,0,0,33,0,0,0,
|
||||||
|
253,0,1,0,56,0,1,0
|
||||||
31
runtime/Includes/Embedded/ShaderScreenVertex.nzsl
git.filemode.normal_file
31
runtime/Includes/Embedded/ShaderScreenVertex.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;
|
||||||
|
}
|
||||||
48
runtime/Includes/Embedded/ShaderScreenVertex.spv.h
git.filemode.normal_file
48
runtime/Includes/Embedded/ShaderScreenVertex.spv.h
git.filemode.normal_file
@@ -0,0 +1,48 @@
|
|||||||
|
3,2,35,7,0,0,1,0,39,0,0,0,59,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,14,0,
|
||||||
|
3,0,0,0,0,0,1,0,0,0,15,0,8,0,0,0,0,0,37,0,0,0,109,97,105,110,0,0,0,0,
|
||||||
|
20,0,0,0,26,0,0,0,29,0,0,0,3,0,3,0,0,0,0,0,100,0,0,0,5,0,4,0,23,0,
|
||||||
|
0,0,86,101,114,116,73,110,0,0,6,0,6,0,23,0,0,0,0,0,0,0,118,101,114,116,95,105,110,100,
|
||||||
|
101,120,0,0,5,0,4,0,30,0,0,0,86,101,114,116,79,117,116,0,6,0,4,0,30,0,0,0,0,0,
|
||||||
|
0,0,117,118,0,0,6,0,6,0,30,0,0,0,1,0,0,0,112,111,115,105,116,105,111,110,0,0,0,0,
|
||||||
|
5,0,5,0,15,0,0,0,118,101,114,116,105,99,101,115,0,0,0,0,5,0,6,0,20,0,0,0,118,101,
|
||||||
|
114,116,101,120,95,105,110,100,101,120,0,0,0,0,5,0,3,0,26,0,0,0,117,118,0,0,5,0,5,0,
|
||||||
|
29,0,0,0,112,111,115,105,116,105,111,110,0,0,0,0,5,0,4,0,37,0,0,0,109,97,105,110,0,0,
|
||||||
|
0,0,71,0,4,0,20,0,0,0,11,0,0,0,42,0,0,0,71,0,4,0,29,0,0,0,11,0,0,0,
|
||||||
|
0,0,0,0,71,0,4,0,26,0,0,0,30,0,0,0,0,0,0,0,72,0,5,0,23,0,0,0,0,0,
|
||||||
|
0,0,35,0,0,0,0,0,0,0,72,0,5,0,30,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,
|
||||||
|
72,0,5,0,30,0,0,0,1,0,0,0,35,0,0,0,16,0,0,0,22,0,3,0,1,0,0,0,32,0,
|
||||||
|
0,0,23,0,4,0,2,0,0,0,1,0,0,0,2,0,0,0,21,0,4,0,3,0,0,0,32,0,0,0,
|
||||||
|
0,0,0,0,43,0,4,0,3,0,0,0,4,0,0,0,3,0,0,0,28,0,4,0,5,0,0,0,2,0,
|
||||||
|
0,0,4,0,0,0,32,0,4,0,6,0,0,0,6,0,0,0,5,0,0,0,43,0,4,0,1,0,0,0,
|
||||||
|
7,0,0,0,0,0,128,191,43,0,4,0,1,0,0,0,8,0,0,0,0,0,64,192,44,0,5,0,2,0,
|
||||||
|
0,0,9,0,0,0,7,0,0,0,8,0,0,0,43,0,4,0,1,0,0,0,10,0,0,0,0,0,128,63,
|
||||||
|
44,0,5,0,2,0,0,0,11,0,0,0,7,0,0,0,10,0,0,0,43,0,4,0,1,0,0,0,12,0,
|
||||||
|
0,0,0,0,64,64,44,0,5,0,2,0,0,0,13,0,0,0,12,0,0,0,10,0,0,0,44,0,6,0,
|
||||||
|
5,0,0,0,14,0,0,0,9,0,0,0,11,0,0,0,13,0,0,0,19,0,2,0,16,0,0,0,33,0,
|
||||||
|
3,0,17,0,0,0,16,0,0,0,21,0,4,0,18,0,0,0,32,0,0,0,1,0,0,0,32,0,4,0,
|
||||||
|
19,0,0,0,1,0,0,0,18,0,0,0,43,0,4,0,18,0,0,0,21,0,0,0,0,0,0,0,32,0,
|
||||||
|
4,0,22,0,0,0,7,0,0,0,18,0,0,0,30,0,3,0,23,0,0,0,18,0,0,0,32,0,4,0,
|
||||||
|
24,0,0,0,7,0,0,0,23,0,0,0,32,0,4,0,25,0,0,0,3,0,0,0,2,0,0,0,23,0,
|
||||||
|
4,0,27,0,0,0,1,0,0,0,4,0,0,0,32,0,4,0,28,0,0,0,3,0,0,0,27,0,0,0,
|
||||||
|
30,0,4,0,30,0,0,0,2,0,0,0,27,0,0,0,32,0,4,0,31,0,0,0,7,0,0,0,2,0,
|
||||||
|
0,0,32,0,4,0,32,0,0,0,7,0,0,0,30,0,0,0,43,0,4,0,18,0,0,0,33,0,0,0,
|
||||||
|
1,0,0,0,43,0,4,0,1,0,0,0,34,0,0,0,0,0,0,0,43,0,4,0,1,0,0,0,35,0,
|
||||||
|
0,0,0,0,0,63,44,0,5,0,2,0,0,0,36,0,0,0,35,0,0,0,35,0,0,0,32,0,4,0,
|
||||||
|
45,0,0,0,6,0,0,0,2,0,0,0,32,0,4,0,51,0,0,0,7,0,0,0,27,0,0,0,59,0,
|
||||||
|
5,0,6,0,0,0,15,0,0,0,6,0,0,0,14,0,0,0,59,0,4,0,19,0,0,0,20,0,0,0,
|
||||||
|
1,0,0,0,59,0,4,0,25,0,0,0,26,0,0,0,3,0,0,0,59,0,4,0,28,0,0,0,29,0,
|
||||||
|
0,0,3,0,0,0,54,0,5,0,16,0,0,0,37,0,0,0,0,0,0,0,17,0,0,0,248,0,2,0,
|
||||||
|
38,0,0,0,59,0,4,0,31,0,0,0,39,0,0,0,7,0,0,0,59,0,4,0,32,0,0,0,40,0,
|
||||||
|
0,0,7,0,0,0,59,0,4,0,24,0,0,0,41,0,0,0,7,0,0,0,65,0,5,0,22,0,0,0,
|
||||||
|
42,0,0,0,41,0,0,0,21,0,0,0,63,0,3,0,42,0,0,0,20,0,0,0,65,0,5,0,22,0,
|
||||||
|
0,0,43,0,0,0,41,0,0,0,21,0,0,0,61,0,4,0,18,0,0,0,44,0,0,0,43,0,0,0,
|
||||||
|
65,0,5,0,45,0,0,0,46,0,0,0,15,0,0,0,44,0,0,0,61,0,4,0,2,0,0,0,47,0,
|
||||||
|
0,0,46,0,0,0,62,0,3,0,39,0,0,0,47,0,0,0,61,0,4,0,2,0,0,0,48,0,0,0,
|
||||||
|
39,0,0,0,80,0,6,0,27,0,0,0,49,0,0,0,48,0,0,0,34,0,0,0,10,0,0,0,65,0,
|
||||||
|
5,0,51,0,0,0,50,0,0,0,40,0,0,0,33,0,0,0,62,0,3,0,50,0,0,0,49,0,0,0,
|
||||||
|
61,0,4,0,2,0,0,0,52,0,0,0,39,0,0,0,142,0,5,0,2,0,0,0,53,0,0,0,52,0,
|
||||||
|
0,0,35,0,0,0,129,0,5,0,2,0,0,0,54,0,0,0,53,0,0,0,36,0,0,0,65,0,5,0,
|
||||||
|
31,0,0,0,55,0,0,0,40,0,0,0,21,0,0,0,62,0,3,0,55,0,0,0,54,0,0,0,61,0,
|
||||||
|
4,0,30,0,0,0,56,0,0,0,40,0,0,0,81,0,5,0,2,0,0,0,57,0,0,0,56,0,0,0,
|
||||||
|
0,0,0,0,62,0,3,0,26,0,0,0,57,0,0,0,81,0,5,0,27,0,0,0,58,0,0,0,56,0,
|
||||||
|
0,0,1,0,0,0,62,0,3,0,29,0,0,0,58,0,0,0,253,0,1,0,56,0,1,0
|
||||||
58
runtime/Includes/Graphics/Drawable.h
git.filemode.normal_file
58
runtime/Includes/Graphics/Drawable.h
git.filemode.normal_file
@@ -0,0 +1,58 @@
|
|||||||
|
#ifndef __MLX_DRAWABLE__
|
||||||
|
#define __MLX_DRAWABLE__
|
||||||
|
|
||||||
|
#include <Graphics/Enums.h>
|
||||||
|
#include <Maths/Quaternions.h>
|
||||||
|
#include <Maths/EulerAngles.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class Drawable
|
||||||
|
{
|
||||||
|
friend class Render2DPass;
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline Drawable(DrawableType type) : m_type(type) {}
|
||||||
|
|
||||||
|
inline void SetColor(Vec4f color) noexcept { m_color = std::move(color); }
|
||||||
|
inline void SetPosition(Vec2f position) noexcept { m_position = std::move(position); }
|
||||||
|
inline void SetScale(Vec2f scale) noexcept { m_scale = std::move(scale); }
|
||||||
|
inline void SetRotation(float rotation) noexcept { m_rotation = EulerAnglesf{ 0.0f, 0.0f, rotation }; }
|
||||||
|
inline void SetCenter(Vec2f center) noexcept { m_center = std::move(center); }
|
||||||
|
|
||||||
|
inline virtual void Update([[maybe_unused]] VkCommandBuffer cmd) {}
|
||||||
|
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE const Vec4f& GetColor() const noexcept { return m_color; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE const Vec2f& GetPosition() const noexcept { return m_position; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE const Vec2f& GetScale() const noexcept { return m_scale; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE const Quatf& GetRotation() const noexcept { return m_rotation; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE const Vec2f& GetCenter() const noexcept { return m_center; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE std::shared_ptr<Mesh> GetMesh() const { return p_mesh; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE DrawableType GetType() const noexcept { return m_type; }
|
||||||
|
|
||||||
|
inline virtual ~Drawable() { if(p_set) p_set->ReturnDescriptorSetToPool(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
[[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 ? p_set->GetSet(frame_index) : VK_NULL_HANDLE; }
|
||||||
|
|
||||||
|
inline void UpdateDescriptorSet(std::shared_ptr<DescriptorSet> set)
|
||||||
|
{
|
||||||
|
p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(set->GetShaderLayout(), set->GetShaderType());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Bind(std::size_t frame_index, VkCommandBuffer cmd) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<DescriptorSet> p_set;
|
||||||
|
std::shared_ptr<Mesh> p_mesh;
|
||||||
|
Quatf m_rotation = Quatf::Identity();
|
||||||
|
Vec4f m_color = Vec4f{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
Vec2f m_position = Vec2f{ 0.0f, 0.0f };
|
||||||
|
Vec2f m_scale = Vec2f{ 1.0f, 1.0f };
|
||||||
|
Vec2f m_center = Vec2f{ 0.0f, 0.0f };
|
||||||
|
DrawableType m_type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
13
runtime/Includes/Graphics/Enums.h
git.filemode.normal_file
13
runtime/Includes/Graphics/Enums.h
git.filemode.normal_file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef __MLX_GRAPHICS_ENUMS__
|
||||||
|
#define __MLX_GRAPHICS_ENUMS__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
enum class DrawableType
|
||||||
|
{
|
||||||
|
Sprite,
|
||||||
|
Text
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
53
runtime/Includes/Graphics/Font.h
git.filemode.normal_file
53
runtime/Includes/Graphics/Font.h
git.filemode.normal_file
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef __MLX_FONT__
|
||||||
|
#define __MLX_FONT__
|
||||||
|
|
||||||
|
#include <Renderer/Image.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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 mlx
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
68
runtime/Includes/Graphics/Mesh.h
git.filemode.normal_file
68
runtime/Includes/Graphics/Mesh.h
git.filemode.normal_file
@@ -0,0 +1,68 @@
|
|||||||
|
#ifndef __MLX_RENDERER_MESH__
|
||||||
|
#define __MLX_RENDERER_MESH__
|
||||||
|
|
||||||
|
#include <Renderer/Vertex.h>
|
||||||
|
#include <Renderer/Buffer.h>
|
||||||
|
#include <Utils/Buffer.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct SubMesh
|
||||||
|
{
|
||||||
|
struct NoBuild {};
|
||||||
|
|
||||||
|
VertexBuffer vbo;
|
||||||
|
IndexBuffer ibo;
|
||||||
|
std::vector<Vertex> vertex_data;
|
||||||
|
std::vector<std::uint32_t> index_data;
|
||||||
|
std::size_t triangle_count = 0;
|
||||||
|
|
||||||
|
inline SubMesh(const std::vector<Vertex>& vertices, const std::vector<std::uint32_t>& indices);
|
||||||
|
inline SubMesh(const std::vector<Vertex>& vertices, const std::vector<std::uint32_t>& indices, NoBuild);
|
||||||
|
};
|
||||||
|
|
||||||
|
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); }
|
||||||
|
|
||||||
|
~Mesh();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<SubMesh> m_sub_meshes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A registry just to avoid destroying meshes when clearing a window
|
||||||
|
class MeshRegistry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline MeshRegistry();
|
||||||
|
|
||||||
|
inline void RegisterMesh(std::shared_ptr<Mesh> mesh);
|
||||||
|
inline std::shared_ptr<Mesh> FindMesh(const std::vector<Mesh::SubMesh>& sub_meshes);
|
||||||
|
inline void UnregisterMesh(std::shared_ptr<Mesh> mesh);
|
||||||
|
inline void Reset();
|
||||||
|
|
||||||
|
inline static bool IsInit() noexcept { return s_instance != nullptr; }
|
||||||
|
inline static MeshRegistry& Get() noexcept { return *s_instance; }
|
||||||
|
|
||||||
|
inline ~MeshRegistry();
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline static MeshRegistry* s_instance = nullptr;
|
||||||
|
std::unordered_set<std::shared_ptr<Mesh>> m_meshes_registry;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Graphics/Mesh.inl>
|
||||||
|
|
||||||
|
#endif
|
||||||
77
runtime/Includes/Graphics/Mesh.inl
git.filemode.normal_file
77
runtime/Includes/Graphics/Mesh.inl
git.filemode.normal_file
@@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Graphics/Mesh.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
Mesh::SubMesh::SubMesh(const std::vector<Vertex>& vertices, const std::vector<std::uint32_t>& indices) : vertex_data(vertices), index_data(indices)
|
||||||
|
{
|
||||||
|
CPUBuffer vb(vertices.size() * sizeof(Vertex));
|
||||||
|
std::memcpy(vb.GetData(), vertices.data(), vb.GetSize());
|
||||||
|
vbo.Init(vb.GetSize(), 0, "mlx_mesh");
|
||||||
|
vbo.SetData(std::move(vb));
|
||||||
|
|
||||||
|
CPUBuffer ib(indices.size() * sizeof(std::uint32_t));
|
||||||
|
std::memcpy(ib.GetData(), indices.data(), ib.GetSize());
|
||||||
|
ibo.Init(ib.GetSize(), 0, "mlx_mesh");
|
||||||
|
ibo.SetData(std::move(ib));
|
||||||
|
|
||||||
|
triangle_count = vertices.size() / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh::SubMesh::SubMesh(const std::vector<Vertex>& vertices, const std::vector<std::uint32_t>& indices, NoBuild) : vertex_data(vertices), index_data(indices) {}
|
||||||
|
|
||||||
|
MeshRegistry::MeshRegistry()
|
||||||
|
{
|
||||||
|
s_instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshRegistry::RegisterMesh(std::shared_ptr<Mesh> mesh)
|
||||||
|
{
|
||||||
|
m_meshes_registry.insert(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Mesh> MeshRegistry::FindMesh(const std::vector<Mesh::SubMesh>& sub_meshes)
|
||||||
|
{
|
||||||
|
for(const std::shared_ptr<Mesh>& mesh : m_meshes_registry)
|
||||||
|
{
|
||||||
|
if(mesh->GetSubMeshCount() != sub_meshes.size()) // If the number of submeshes is different than the one we want to find no need to test
|
||||||
|
continue;
|
||||||
|
bool found = true;
|
||||||
|
for(std::size_t i = 0; i < sub_meshes.size(); i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const Mesh::SubMesh& registered_sub_mesh = mesh->GetSubMesh(i);
|
||||||
|
if(registered_sub_mesh.vertex_data != sub_meshes[i].vertex_data || registered_sub_mesh.index_data != sub_meshes[i].index_data)
|
||||||
|
{
|
||||||
|
found = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
found = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(found)
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshRegistry::UnregisterMesh(std::shared_ptr<Mesh> mesh)
|
||||||
|
{
|
||||||
|
m_meshes_registry.erase(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshRegistry::Reset()
|
||||||
|
{
|
||||||
|
m_meshes_registry.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshRegistry::~MeshRegistry()
|
||||||
|
{
|
||||||
|
s_instance = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
runtime/Includes/Graphics/PutPixelManager.h
git.filemode.normal_file
32
runtime/Includes/Graphics/PutPixelManager.h
git.filemode.normal_file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef __MLX_PUT_PIXEL_MANAGER__
|
||||||
|
#define __MLX_PUT_PIXEL_MANAGER__
|
||||||
|
|
||||||
|
#include <Renderer/Image.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class PutPixelManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PutPixelManager(NonOwningPtr<class Renderer> renderer) : p_renderer(renderer) {}
|
||||||
|
|
||||||
|
// Returns a valid pointer when a new texture has been created
|
||||||
|
NonOwningPtr<Texture> DrawPixel(int x, int y, std::uint64_t draw_layer, mlx_color color);
|
||||||
|
NonOwningPtr<Texture> DrawPixelsArray(int x, int y, std::uint64_t draw_layer, mlx_color* pixels, std::size_t pixels_size);
|
||||||
|
NonOwningPtr<Texture> DrawPixelsRegion(int x, int y, int w, int h, std::uint64_t draw_layer, mlx_color* pixels);
|
||||||
|
void ResetRenderData();
|
||||||
|
|
||||||
|
~PutPixelManager() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
NonOwningPtr<Texture> GetLayer(std::uint64_t draw_layer, bool& is_newlayer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::uint64_t, NonOwningPtr<Texture>> m_placements;
|
||||||
|
std::vector<std::unique_ptr<Texture>> m_textures;
|
||||||
|
NonOwningPtr<class Renderer> p_renderer;
|
||||||
|
std::size_t m_current_texture_index = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
50
runtime/Includes/Graphics/Scene.h
git.filemode.normal_file
50
runtime/Includes/Graphics/Scene.h
git.filemode.normal_file
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef __MLX_SCENE__
|
||||||
|
#define __MLX_SCENE__
|
||||||
|
|
||||||
|
#include <Renderer/Renderer.h>
|
||||||
|
#include <Graphics/Text.h>
|
||||||
|
#include <Graphics/Font.h>
|
||||||
|
#include <Graphics/Sprite.h>
|
||||||
|
#include <Graphics/Drawable.h>
|
||||||
|
#include <Renderer/ViewerData.h>
|
||||||
|
#include <Maths/Vec4.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class Scene
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Scene() = default;
|
||||||
|
|
||||||
|
Sprite& CreateSprite(NonOwningPtr<class Texture> texture) noexcept;
|
||||||
|
NonOwningPtr<Sprite> GetSpriteFromTexturePositionScaleRotation(NonOwningPtr<Texture> texture, const Vec2f& position, float scale_x, float scale_y, float rotation) const;
|
||||||
|
void TryEraseSpriteFromTexture(NonOwningPtr<Texture> texture);
|
||||||
|
bool IsTextureAtGivenDrawLayer(NonOwningPtr<Texture> texture, std::uint64_t draw_layer) const;
|
||||||
|
|
||||||
|
Text& CreateText(const std::string& text) noexcept;
|
||||||
|
NonOwningPtr<Text> GetTextFromPositionAndColor(const std::string& text, const Vec2f& position, const Vec4f& color) const;
|
||||||
|
bool IsTextAtGivenDrawLayer(const std::string& text, std::uint64_t draw_layer) const;
|
||||||
|
|
||||||
|
inline void BindFont(std::shared_ptr<Font> font) { Verify((bool)font, "invalid fond pointer"); p_bound_font = font; }
|
||||||
|
|
||||||
|
void BringToDrawLayer(NonOwningPtr<Drawable> drawable, std::uint64_t draw_layer);
|
||||||
|
|
||||||
|
inline void ResetScene(Vec4f clear) { m_drawables.clear(); m_clear_color = std::move(clear); m_has_scene_changed = true; }
|
||||||
|
inline const Vec4f& GetClearColor() const noexcept { return m_clear_color; }
|
||||||
|
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE const std::vector<std::shared_ptr<Drawable>>& GetDrawables() const noexcept { return m_drawables; }
|
||||||
|
|
||||||
|
inline void ResetChangeChecker() noexcept { m_has_scene_changed = false; }
|
||||||
|
inline bool HasSceneChanged() const noexcept { return m_has_scene_changed; }
|
||||||
|
|
||||||
|
~Scene() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::shared_ptr<Drawable>> m_drawables;
|
||||||
|
std::shared_ptr<Font> p_bound_font;
|
||||||
|
Vec4f m_clear_color = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
bool m_has_scene_changed = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
45
runtime/Includes/Graphics/Sprite.h
git.filemode.normal_file
45
runtime/Includes/Graphics/Sprite.h
git.filemode.normal_file
@@ -0,0 +1,45 @@
|
|||||||
|
#ifndef __MLX_SPRITE__
|
||||||
|
#define __MLX_SPRITE__
|
||||||
|
|
||||||
|
#include <Maths/Vec3.h>
|
||||||
|
#include <Maths/Vec4.h>
|
||||||
|
#include <Graphics/Mesh.h>
|
||||||
|
#include <Renderer/Descriptor.h>
|
||||||
|
#include <Renderer/Image.h>
|
||||||
|
#include <Graphics/Drawable.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class Sprite : public Drawable
|
||||||
|
{
|
||||||
|
friend class Render2DPass;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Sprite(NonOwningPtr<Texture> texture);
|
||||||
|
Sprite(std::shared_ptr<Mesh> mesh, NonOwningPtr<Texture> texture);
|
||||||
|
|
||||||
|
MLX_FORCEINLINE void Update(VkCommandBuffer cmd) override
|
||||||
|
{
|
||||||
|
Verify((bool)p_texture, "a sprite has no texture attached (internal mlx issue, please report to the devs)");
|
||||||
|
p_texture->Update(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE NonOwningPtr<Texture> GetTexture() const { return p_texture; }
|
||||||
|
|
||||||
|
inline ~Sprite() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline void Bind(std::size_t frame_index, VkCommandBuffer cmd) override
|
||||||
|
{
|
||||||
|
if(!p_set)
|
||||||
|
return;
|
||||||
|
p_set->SetImage(frame_index, 0, *p_texture);
|
||||||
|
p_set->Update(frame_index, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
NonOwningPtr<Texture> p_texture;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
40
runtime/Includes/Graphics/Text.h
git.filemode.normal_file
40
runtime/Includes/Graphics/Text.h
git.filemode.normal_file
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef __MLX_TEXT__
|
||||||
|
#define __MLX_TEXT__
|
||||||
|
|
||||||
|
#include <Graphics/Font.h>
|
||||||
|
#include <Graphics/Mesh.h>
|
||||||
|
#include <Graphics/Drawable.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class Text : public Drawable
|
||||||
|
{
|
||||||
|
friend class Render2DPass;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Text(const std::string& text, std::shared_ptr<Font> font);
|
||||||
|
inline Text(const std::string& text, std::shared_ptr<Font> font, std::shared_ptr<Mesh> mesh) : Drawable(DrawableType::Text) { Init(text, font, mesh); }
|
||||||
|
|
||||||
|
[[nodiscard]] inline const std::string& GetText() const { return m_text; }
|
||||||
|
[[nodiscard]] inline std::shared_ptr<Font> GetFont() const { return p_font; }
|
||||||
|
|
||||||
|
virtual ~Text() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Init(const std::string& text, std::shared_ptr<Font> font, std::shared_ptr<Mesh> mesh);
|
||||||
|
|
||||||
|
inline void Bind(std::size_t frame_index, VkCommandBuffer cmd) override
|
||||||
|
{
|
||||||
|
if(!p_set)
|
||||||
|
return;
|
||||||
|
p_set->SetImage(frame_index, 0, const_cast<Texture&>(p_font->GetTexture()));
|
||||||
|
p_set->Update(frame_index, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Font> p_font;
|
||||||
|
std::string m_text;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
106
runtime/Includes/Maths/Angles.h
git.filemode.normal_file
106
runtime/Includes/Maths/Angles.h
git.filemode.normal_file
@@ -0,0 +1,106 @@
|
|||||||
|
#ifndef __MLX_ANGLES__
|
||||||
|
#define __MLX_ANGLES__
|
||||||
|
|
||||||
|
#include <Maths/Enums.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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
|
||||||
493
runtime/Includes/Maths/Angles.inl
git.filemode.normal_file
493
runtime/Includes/Maths/Angles.inl
git.filemode.normal_file
@@ -0,0 +1,493 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Maths/Angles.h>
|
||||||
|
|
||||||
|
#include <Maths/Constants.h>
|
||||||
|
#include <Maths/MathsUtils.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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)";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef MLX_PLAT_LINUX
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<typename T>
|
||||||
|
void SinCos(T x, T* sin, T* cos)
|
||||||
|
{
|
||||||
|
*sin = std::sin(x);
|
||||||
|
*cos = std::cos(x);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
83
runtime/Includes/Maths/Constants.h
git.filemode.normal_file
83
runtime/Includes/Maths/Constants.h
git.filemode.normal_file
@@ -0,0 +1,83 @@
|
|||||||
|
#ifndef __MLX_MATHS_CONSTANTS__
|
||||||
|
#define __MLX_MATHS_CONSTANTS__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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
|
||||||
18
runtime/Includes/Maths/Enums.h
git.filemode.normal_file
18
runtime/Includes/Maths/Enums.h
git.filemode.normal_file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef __MLX_MATHS_ENUMS__
|
||||||
|
#define __MLX_MATHS_ENUMS__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
enum class AngleUnit
|
||||||
|
{
|
||||||
|
Degree = 0,
|
||||||
|
Radian,
|
||||||
|
Turn,
|
||||||
|
|
||||||
|
EndEnum
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::size_t AngleUnitCount = static_cast<std::size_t>(AngleUnit::EndEnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
55
runtime/Includes/Maths/EulerAngles.h
git.filemode.normal_file
55
runtime/Includes/Maths/EulerAngles.h
git.filemode.normal_file
@@ -0,0 +1,55 @@
|
|||||||
|
#ifndef __MLX_EULER_ANGLES__
|
||||||
|
#define __MLX_EULER_ANGLES__
|
||||||
|
|
||||||
|
#include <Maths/Angles.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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 mlx
|
||||||
|
{
|
||||||
|
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 << ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
118
runtime/Includes/Maths/Mat4.h
git.filemode.normal_file
118
runtime/Includes/Maths/Mat4.h
git.filemode.normal_file
@@ -0,0 +1,118 @@
|
|||||||
|
#ifndef __MLX_MAT4__
|
||||||
|
#define __MLX_MAT4__
|
||||||
|
|
||||||
|
#include <Maths/Angles.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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 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 z_near = -1.0, T zFar = 1.0);
|
||||||
|
static Mat4 Perspective(RadianAngle<T> angle, T ratio, T z_near, T z_far);
|
||||||
|
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
|
||||||
875
runtime/Includes/Maths/Mat4.inl
git.filemode.normal_file
875
runtime/Includes/Maths/Mat4.inl
git.filemode.normal_file
@@ -0,0 +1,875 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Maths/Mat4.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>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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<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 = 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
runtime/Includes/Maths/MathsUtils.h
git.filemode.normal_file
24
runtime/Includes/Maths/MathsUtils.h
git.filemode.normal_file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef __MLX_MATHS_UTILS__
|
||||||
|
#define __MLX_MATHS_UTILS__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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
|
||||||
44
runtime/Includes/Maths/MathsUtils.inl
git.filemode.normal_file
44
runtime/Includes/Maths/MathsUtils.inl
git.filemode.normal_file
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Maths/MathsUtils.h>
|
||||||
|
|
||||||
|
#include <Maths/Constants.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
92
runtime/Includes/Maths/Quaternions.h
git.filemode.normal_file
92
runtime/Includes/Maths/Quaternions.h
git.filemode.normal_file
@@ -0,0 +1,92 @@
|
|||||||
|
#ifndef __MLX_QUATERNIONS__
|
||||||
|
#define __MLX_QUATERNIONS__
|
||||||
|
|
||||||
|
#include <Maths/Angles.h>
|
||||||
|
#include <Maths/Vec3.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
RadianAngle<T> AngleBetween(const Quat& vec) const;
|
||||||
|
constexpr bool ApproxEqual(const Quat& quat, T max_difference = 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 max_difference = 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> max_rotation);
|
||||||
|
static Quat Mirror(Quat quat, const Vec3<T>& axis);
|
||||||
|
static Quat Slerp(const Quat& from, const Quat& to, T interpolation);
|
||||||
|
static constexpr Quat Zero();
|
||||||
|
|
||||||
|
~Quat() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 mlx
|
||||||
|
{
|
||||||
|
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(mlx::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 = mlx::Lerp(from.w, to.w, interpolation);
|
||||||
|
interpolated.x = mlx::Lerp(from.x, to.x, interpolation);
|
||||||
|
interpolated.y = mlx::Lerp(from.y, to.y, interpolation);
|
||||||
|
interpolated.z = mlx::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 << ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
1
runtime/Includes/Maths/Readme.md
git.filemode.normal_file
1
runtime/Includes/Maths/Readme.md
git.filemode.normal_file
@@ -0,0 +1 @@
|
|||||||
|
Highly inspired by [Nazara Maths library](https://github.com/NazaraEngine/NazaraEngine/tree/main/include/Nazara/Math)
|
||||||
109
runtime/Includes/Maths/Vec2.h
git.filemode.executable_file
109
runtime/Includes/Maths/Vec2.h
git.filemode.executable_file
@@ -0,0 +1,109 @@
|
|||||||
|
#ifndef __MLX_VEC2__
|
||||||
|
#define __MLX_VEC2__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
template <typename T> struct Vec3;
|
||||||
|
template <typename T> struct Vec4;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Vec2
|
||||||
|
{
|
||||||
|
union { T x, r, s; };
|
||||||
|
union { T y, g, t; };
|
||||||
|
|
||||||
|
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 // __AK_VEC2__
|
||||||
387
runtime/Includes/Maths/Vec2.inl
git.filemode.executable_file
387
runtime/Includes/Maths/Vec2.inl
git.filemode.executable_file
@@ -0,0 +1,387 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Maths/Vec2.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
mlx::Assert(i < 2, "index out of range");
|
||||||
|
return *(&x + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T Vec2<T>::operator[](std::size_t i) const
|
||||||
|
{
|
||||||
|
mlx::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));
|
||||||
|
}
|
||||||
|
}
|
||||||
126
runtime/Includes/Maths/Vec3.h
git.filemode.executable_file
126
runtime/Includes/Maths/Vec3.h
git.filemode.executable_file
@@ -0,0 +1,126 @@
|
|||||||
|
#ifndef __MLX_VEC3__
|
||||||
|
#define __MLX_VEC3__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
template<typename T> struct Vec2;
|
||||||
|
template<typename T> struct Vec4;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Vec3
|
||||||
|
{
|
||||||
|
union { T x, r, s; };
|
||||||
|
union { T y, g, t; };
|
||||||
|
union { T z, b, p; };
|
||||||
|
|
||||||
|
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 // __AK_VEC3__
|
||||||
508
runtime/Includes/Maths/Vec3.inl
git.filemode.executable_file
508
runtime/Includes/Maths/Vec3.inl
git.filemode.executable_file
@@ -0,0 +1,508 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Maths/Vec3.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
mlx::Assert(i < 3, "index out of range");
|
||||||
|
return *(&x + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr const T& Vec3<T>::operator[](std::size_t i) const
|
||||||
|
{
|
||||||
|
mlx::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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
108
runtime/Includes/Maths/Vec4.h
git.filemode.executable_file
108
runtime/Includes/Maths/Vec4.h
git.filemode.executable_file
@@ -0,0 +1,108 @@
|
|||||||
|
#ifndef __MLX_VEC4__
|
||||||
|
#define __MLX_VEC4__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
template<typename T> struct Vec2;
|
||||||
|
template<typename T> struct Vec3;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Vec4
|
||||||
|
{
|
||||||
|
union { T x, r, s; };
|
||||||
|
union { T y, g, t; };
|
||||||
|
union { T z, b, p; };
|
||||||
|
union { T w, a, q; };
|
||||||
|
|
||||||
|
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 // __AK_VEC4__
|
||||||
|
|
||||||
423
runtime/Includes/Maths/Vec4.inl
git.filemode.executable_file
423
runtime/Includes/Maths/Vec4.inl
git.filemode.executable_file
@@ -0,0 +1,423 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Maths/Vec4.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
mlx::Assert(i < 4, "index out of range");
|
||||||
|
return *(&x + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr const T& Vec4<T>::operator[](std::size_t i) const
|
||||||
|
{
|
||||||
|
mlx::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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
52
runtime/Includes/Platform/Inputs.h
git.filemode.normal_file
52
runtime/Includes/Platform/Inputs.h
git.filemode.normal_file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef __MLX_INPUTS__
|
||||||
|
#define __MLX_INPUTS__
|
||||||
|
|
||||||
|
#include <mlx.h>
|
||||||
|
#include <mlx_profile.h>
|
||||||
|
#include <Platform/Window.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class Inputs
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Hook
|
||||||
|
{
|
||||||
|
std::function<void(int, void*)> fn;
|
||||||
|
void* param = nullptr;
|
||||||
|
|
||||||
|
Hook(std::function<void(int, void*)> fn, void* param) : fn(fn), param(param) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
Inputs() = default;
|
||||||
|
|
||||||
|
void FetchInputs();
|
||||||
|
|
||||||
|
inline void RegisterWindow(std::shared_ptr<Window> window) { m_windows[window->GetID()] = window; }
|
||||||
|
|
||||||
|
std::int32_t GetX() const noexcept;
|
||||||
|
std::int32_t GetY() const noexcept;
|
||||||
|
std::int32_t GetXRel() const noexcept;
|
||||||
|
std::int32_t GetYRel() const noexcept;
|
||||||
|
|
||||||
|
inline bool IsMouseMoving() const noexcept { return GetXRel() || GetYRel(); }
|
||||||
|
MLX_FORCEINLINE bool IsRunning() const noexcept { return m_run; }
|
||||||
|
MLX_FORCEINLINE constexpr void Finish() noexcept { m_run = false; }
|
||||||
|
MLX_FORCEINLINE constexpr void Run() noexcept { m_run = true; }
|
||||||
|
|
||||||
|
inline void OnEvent(std::uint32_t id, int event, void(*f)(int, void*), void* param) noexcept
|
||||||
|
{
|
||||||
|
m_events_hooks[id][event].emplace_back(f, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Inputs() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::uint32_t, std::shared_ptr<Window>> m_windows;
|
||||||
|
std::unordered_map<std::uint32_t, std::array<std::vector<Hook>, 6>> m_events_hooks;
|
||||||
|
bool m_run = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
54
runtime/Includes/Platform/Window.h
git.filemode.normal_file
54
runtime/Includes/Platform/Window.h
git.filemode.normal_file
@@ -0,0 +1,54 @@
|
|||||||
|
#ifndef __MLX_WINDOW__
|
||||||
|
#define __MLX_WINDOW__
|
||||||
|
|
||||||
|
#include <mlx.h>
|
||||||
|
#include <Maths/Vec2.h>
|
||||||
|
#include <Core/SDLManager.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class Window
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Window(const mlx_window_create_info* info, bool hidden = false);
|
||||||
|
|
||||||
|
MLX_FORCEINLINE Handle GetWindowHandle() const noexcept { return p_window; }
|
||||||
|
MLX_FORCEINLINE int GetWidth() noexcept { SDLManager::Get().GetWindowSize(p_window, &m_width, &m_height); return m_width; }
|
||||||
|
MLX_FORCEINLINE int GetHeight() noexcept { SDLManager::Get().GetWindowSize(p_window, &m_width, &m_height); return m_height; }
|
||||||
|
MLX_FORCEINLINE std::uint32_t GetID() const noexcept { return m_id; }
|
||||||
|
MLX_FORCEINLINE const std::string& GetName() const { return m_name; }
|
||||||
|
|
||||||
|
MLX_FORCEINLINE void MoveMouse(int x, int y) { SDLManager::Get().MoveMouseOnWindow(p_window, x, y); }
|
||||||
|
MLX_FORCEINLINE void GetScreenSizeWindowIsOn(int* x, int* y) { SDLManager::Get().GetScreenSizeWindowIsOn(p_window, x, y); }
|
||||||
|
|
||||||
|
MLX_FORCEINLINE void SetPosition(int x, int y) { SDLManager::Get().SetWindowPosition(p_window, x, y); }
|
||||||
|
MLX_FORCEINLINE void SetSize(int x, int y) { SDLManager::Get().SetWindowSize(p_window, x, y); m_width = x; m_height = y; }
|
||||||
|
MLX_FORCEINLINE void SetTitle(std::string title) { SDLManager::Get().SetWindowTitle(p_window, title); m_name = std::move(title); }
|
||||||
|
MLX_FORCEINLINE void SetFullscreen(bool enable) { SDLManager::Get().SetWindowFullscreen(p_window, enable); }
|
||||||
|
MLX_FORCEINLINE void SetMaxSize(int x, int y) { SDLManager::Get().SetWindowMaxSize(p_window, x, y); }
|
||||||
|
MLX_FORCEINLINE void SetMinSize(int x, int y) { SDLManager::Get().SetWindowMinSize(p_window, x, y); }
|
||||||
|
MLX_FORCEINLINE void Maximize() { SDLManager::Get().MaximizeWindow(p_window); }
|
||||||
|
MLX_FORCEINLINE void Minimize() { SDLManager::Get().MinimizeWindow(p_window); }
|
||||||
|
MLX_FORCEINLINE void Restore() { SDLManager::Get().RestoreWindow(p_window); }
|
||||||
|
|
||||||
|
MLX_FORCEINLINE void GetPosition(int* x, int* y) { SDLManager::Get().GetWindowPosition(p_window, x, y); }
|
||||||
|
MLX_FORCEINLINE void GetSize(int* x, int* y) { *x = GetWidth(); *y = GetHeight(); }
|
||||||
|
|
||||||
|
MLX_FORCEINLINE VkSurfaceKHR CreateVulkanSurface(VkInstance instance) const noexcept { return SDLManager::Get().CreateVulkanSurface(p_window, instance); }
|
||||||
|
MLX_FORCEINLINE std::vector<const char*> GetRequiredVulkanInstanceExtentions() const noexcept { return SDLManager::Get().GetRequiredVulkanInstanceExtentions(p_window); }
|
||||||
|
MLX_FORCEINLINE Vec2ui GetVulkanDrawableSize() const noexcept { return SDLManager::Get().GetVulkanDrawableSize(p_window); }
|
||||||
|
|
||||||
|
void Destroy() noexcept;
|
||||||
|
|
||||||
|
~Window() { Destroy(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_name;
|
||||||
|
Handle p_window = nullptr;
|
||||||
|
std::int32_t m_id;
|
||||||
|
int m_width = 0;
|
||||||
|
int m_height = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
121
runtime/Includes/PreCompiled.h
git.filemode.normal_file
121
runtime/Includes/PreCompiled.h
git.filemode.normal_file
@@ -0,0 +1,121 @@
|
|||||||
|
#ifndef __MLX_PRE_COMPILED_HEADER__
|
||||||
|
#define __MLX_PRE_COMPILED_HEADER__
|
||||||
|
|
||||||
|
#define VK_NO_PROTOTYPES
|
||||||
|
|
||||||
|
#include <mlx_profile.h>
|
||||||
|
#include <mlx.h>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_vulkan.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <chrono>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
|
#include <set>
|
||||||
|
#include <random>
|
||||||
|
#include <concepts>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iterator>
|
||||||
|
#include <stb_truetype.h>
|
||||||
|
#include <variant>
|
||||||
|
#include <bit>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <string_view>
|
||||||
|
#include <sstream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
|
// Experimentals
|
||||||
|
#if __has_include(<format>)
|
||||||
|
#include <format>
|
||||||
|
#elif __has_include(<experimental/format>)
|
||||||
|
#include <experimental/format>
|
||||||
|
#else
|
||||||
|
#error <format> header not present in this STL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MLX_PLAT_WINDOWS
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MLX_PLAT_LINUX
|
||||||
|
#include <math.h> // sincos
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Core/Memory.h>
|
||||||
|
#include <Core/Logs.h>
|
||||||
|
|
||||||
|
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||||
|
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
|
||||||
|
#define VMA_VULKAN_VERSION 1000000
|
||||||
|
#define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) (mlx::MemManager::AlignedMalloc(alignment, size))
|
||||||
|
#define VMA_SYSTEM_ALIGNED_FREE(ptr) (mlx::MemManager::Free(ptr))
|
||||||
|
//#define VMA_ASSERT(expr) (mlx::Assert(expr, "VMA Assertion: " #expr))
|
||||||
|
#define VMA_ASSERT(expr) ((void)0)
|
||||||
|
#define VMA_ASSERT_LEAK(expr) ((void)0) // Because why not
|
||||||
|
|
||||||
|
#ifdef MLX_COMPILER_CLANG
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Weverything"
|
||||||
|
#include <vma.h>
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#elif defined(MLX_COMPILER_GCC)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||||
|
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
#pragma GCC diagnostic ignored "-Wparentheses"
|
||||||
|
#include <vma.h>
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#else
|
||||||
|
#include <vma.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Utils/AntiX11.h>
|
||||||
|
#include <Utils/AntiWindows.h>
|
||||||
|
|
||||||
|
#define KVF_IMPL_VK_NO_PROTOTYPES
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define KVF_ENABLE_VALIDATION_LAYERS
|
||||||
|
#endif
|
||||||
|
#include <kvf.h>
|
||||||
|
|
||||||
|
#include <Core/EventBus.h>
|
||||||
|
#include <Core/Profiler.h>
|
||||||
|
#include <Utils/NonOwningPtr.h>
|
||||||
|
#include <Utils/NonCopyable.h>
|
||||||
|
|
||||||
|
constexpr const int RANGE = 1024;
|
||||||
|
|
||||||
|
using Handle = void*;
|
||||||
|
|
||||||
|
#endif
|
||||||
87
runtime/Includes/Renderer/Buffer.h
git.filemode.normal_file
87
runtime/Includes/Renderer/Buffer.h
git.filemode.normal_file
@@ -0,0 +1,87 @@
|
|||||||
|
#ifndef __MLX_GPU_BUFFER__
|
||||||
|
#define __MLX_GPU_BUFFER__
|
||||||
|
|
||||||
|
#include <Renderer/Enums.h>
|
||||||
|
#include <Renderer/RenderCore.h>
|
||||||
|
#include <Utils/Buffer.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class GPUBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GPUBuffer() = default;
|
||||||
|
|
||||||
|
void Init(BufferType type, VkDeviceSize size, VkBufferUsageFlags usage, CPUBuffer data, [[maybe_unused]] std::string_view debug_name);
|
||||||
|
void Destroy() noexcept;
|
||||||
|
|
||||||
|
bool CopyFrom(const GPUBuffer& buffer) noexcept;
|
||||||
|
|
||||||
|
void Swap(GPUBuffer& buffer) noexcept;
|
||||||
|
|
||||||
|
template<typename T = void*>
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE T GetMap() const noexcept { return reinterpret_cast<T>(p_map); }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkBuffer Get() const noexcept { return m_buffer; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VmaAllocation GetAllocation() const noexcept { return m_allocation; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkDeviceSize GetSize() const noexcept { return m_size; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkDeviceSize GetOffset() const noexcept { return m_offset; }
|
||||||
|
|
||||||
|
[[nodiscard]] inline bool IsInit() const noexcept { return m_buffer != VK_NULL_HANDLE; }
|
||||||
|
|
||||||
|
~GPUBuffer() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void PushToGPU() noexcept;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::string m_debug_name;
|
||||||
|
#endif
|
||||||
|
VkBuffer m_buffer = VK_NULL_HANDLE;
|
||||||
|
VmaAllocation m_allocation;
|
||||||
|
VkDeviceSize m_offset = 0;
|
||||||
|
VkDeviceSize m_size = 0;
|
||||||
|
void* p_map = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VmaAllocationCreateInfo alloc_info, [[maybe_unused]] std::string_view debug_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
VkBufferUsageFlags m_usage = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VertexBuffer : public GPUBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline void Init(std::uint32_t size, VkBufferUsageFlags additional_flags, [[maybe_unused]] std::string_view debug_name) { GPUBuffer::Init(BufferType::LowDynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | additional_flags, {}, std::move(debug_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, [[maybe_unused]] std::string_view debug_name) { GPUBuffer::Init(BufferType::LowDynamic, size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | additional_flags, {}, std::move(debug_name)); }
|
||||||
|
void SetData(CPUBuffer data);
|
||||||
|
inline void Bind(VkCommandBuffer cmd) const noexcept { RenderCore::Get().vkCmdBindIndexBuffer(cmd, m_buffer, 0, VK_INDEX_TYPE_UINT32); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class UniformBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init(std::uint32_t size, [[maybe_unused]] std::string_view debug_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
|
||||||
89
runtime/Includes/Renderer/Descriptor.h
git.filemode.normal_file
89
runtime/Includes/Renderer/Descriptor.h
git.filemode.normal_file
@@ -0,0 +1,89 @@
|
|||||||
|
#ifndef __MLX_DESCRIPTOR_SET__
|
||||||
|
#define __MLX_DESCRIPTOR_SET__
|
||||||
|
|
||||||
|
#include <Renderer/Enums.h>
|
||||||
|
#include <Renderer/RenderCore.h>
|
||||||
|
#include <Renderer/Pipelines/Shader.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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]] MLX_FORCEINLINE 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]] MLX_FORCEINLINE bool IsInit() const noexcept { return m_sets[0] != VK_NULL_HANDLE; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkDescriptorSetLayout GetVulkanLayout() const noexcept { return m_set_layout; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE const ShaderSetLayout& GetShaderLayout() const { return m_shader_layout; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE 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
|
||||||
32
runtime/Includes/Renderer/Enums.h
git.filemode.normal_file
32
runtime/Includes/Renderer/Enums.h
git.filemode.normal_file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef __MLX_RENDERER_ENUMS__
|
||||||
|
#define __MLX_RENDERER_ENUMS__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
|
||||||
|
EndEnum
|
||||||
|
};
|
||||||
|
constexpr std::size_t ImageTypeCount = static_cast<std::size_t>(ImageType::EndEnum);
|
||||||
|
|
||||||
|
enum class ShaderType
|
||||||
|
{
|
||||||
|
Vertex,
|
||||||
|
Fragment
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
108
runtime/Includes/Renderer/Image.h
git.filemode.normal_file
108
runtime/Includes/Renderer/Image.h
git.filemode.normal_file
@@ -0,0 +1,108 @@
|
|||||||
|
#ifndef __MLX_IMAGE__
|
||||||
|
#define __MLX_IMAGE__
|
||||||
|
|
||||||
|
#include <Maths/Vec4.h>
|
||||||
|
#include <Renderer/RenderCore.h>
|
||||||
|
#include <Renderer/Buffer.h>
|
||||||
|
#include <Utils/Buffer.h>
|
||||||
|
#include <Renderer/Enums.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class Image
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Image() = default;
|
||||||
|
|
||||||
|
inline void Init(VkImage image, VkFormat format, std::uint32_t width, std::uint32_t height, VkImageLayout layout, [[maybe_unused]] std::string_view debug_name) noexcept
|
||||||
|
{
|
||||||
|
m_image = image;
|
||||||
|
m_format = format;
|
||||||
|
m_width = width;
|
||||||
|
m_height = height;
|
||||||
|
m_layout = layout;
|
||||||
|
#ifdef DEBUG
|
||||||
|
m_debug_name = std::move(debug_name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init(ImageType type, std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, bool is_multisampled, std::string_view debug_name);
|
||||||
|
void CreateImageView(VkImageViewType type, VkImageAspectFlags aspectFlags, int layer_count = 1) noexcept;
|
||||||
|
void CreateSampler() noexcept;
|
||||||
|
void TransitionLayout(VkImageLayout new_layout, VkCommandBuffer cmd = VK_NULL_HANDLE);
|
||||||
|
virtual void Clear(VkCommandBuffer cmd, Vec4f color);
|
||||||
|
|
||||||
|
void DestroySampler() noexcept;
|
||||||
|
void DestroyImageView() noexcept;
|
||||||
|
virtual void Destroy() noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkImage Get() const noexcept { return m_image; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VmaAllocation GetAllocation() const noexcept { return m_allocation; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkImageView GetImageView() const noexcept { return m_image_view; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkFormat GetFormat() const noexcept { return m_format; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkImageTiling GetTiling() const noexcept { return m_tiling; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkImageLayout GetLayout() const noexcept { return m_layout; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkSampler GetSampler() const noexcept { return m_sampler; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE std::uint32_t GetWidth() const noexcept { return m_width; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE std::uint32_t GetHeight() const noexcept { return m_height; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE bool IsInit() const noexcept { return m_image != VK_NULL_HANDLE; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE ImageType GetType() const noexcept { return m_type; }
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE const std::string& GetDebugName() const { return m_debug_name; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
virtual ~Image() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::string m_debug_name;
|
||||||
|
#endif
|
||||||
|
VmaAllocation m_allocation;
|
||||||
|
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 Texture: public Image
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Texture() = default;
|
||||||
|
Texture(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format, bool is_multisampled, [[maybe_unused]] std::string_view debug_name)
|
||||||
|
{
|
||||||
|
Init(std::move(pixels), width, height, format, is_multisampled, std::move(debug_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format, bool is_multisampled, [[maybe_unused]] std::string_view debug_name);
|
||||||
|
void Destroy() noexcept override;
|
||||||
|
|
||||||
|
void SetPixel(int x, int y, mlx_color color) noexcept;
|
||||||
|
void SetRegion(int x, int y, int w, int h, mlx_color* color) noexcept;
|
||||||
|
void SetLinearRegion(int x, int y, std::size_t len, mlx_color* color) noexcept;
|
||||||
|
mlx_color GetPixel(int x, int y) noexcept;
|
||||||
|
void GetRegion(int x, int y, int w, int h, mlx_color* dst) noexcept;
|
||||||
|
void Clear(VkCommandBuffer cmd, Vec4f color) override;
|
||||||
|
|
||||||
|
void Update(VkCommandBuffer cmd);
|
||||||
|
|
||||||
|
~Texture() override { Destroy(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OpenCPUBuffer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::optional<GPUBuffer> m_staging_buffer;
|
||||||
|
bool m_has_been_modified = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Texture* StbTextureLoad(const std::filesystem::path& file, int* w, int* h);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
36
runtime/Includes/Renderer/Memory.h
git.filemode.normal_file
36
runtime/Includes/Renderer/Memory.h
git.filemode.normal_file
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef __MLX_VK_MEMORY__
|
||||||
|
#define __MLX_VK_MEMORY__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class GPUAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GPUAllocator() = default;
|
||||||
|
|
||||||
|
void Init(const VkAllocationCallbacks* callbacks) noexcept;
|
||||||
|
void Destroy() noexcept;
|
||||||
|
|
||||||
|
VmaAllocation CreateBuffer(const VkBufferCreateInfo* binfo, const VmaAllocationCreateInfo* vinfo, VkBuffer& buffer, const char* name = nullptr) noexcept;
|
||||||
|
void DestroyBuffer(VmaAllocation allocation, VkBuffer buffer, const char* name) noexcept;
|
||||||
|
|
||||||
|
VmaAllocation CreateImage(const VkImageCreateInfo* iminfo, const VmaAllocationCreateInfo* vinfo, VkImage& image, const char* name = nullptr) noexcept;
|
||||||
|
void DestroyImage(VmaAllocation allocation, VkImage image, const char* name) noexcept;
|
||||||
|
|
||||||
|
void MapMemory(VmaAllocation allocation, void** data) noexcept;
|
||||||
|
void UnmapMemory(VmaAllocation allocation) noexcept;
|
||||||
|
|
||||||
|
void DumpMemoryToJson();
|
||||||
|
|
||||||
|
void Flush(VmaAllocation allocation, VkDeviceSize size, VkDeviceSize offset) noexcept;
|
||||||
|
|
||||||
|
~GPUAllocator() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VmaAllocator m_allocator;
|
||||||
|
std::int32_t m_active_buffers_allocations = 0;
|
||||||
|
std::int32_t m_active_images_allocations = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
60
runtime/Includes/Renderer/Pipelines/Graphics.h
git.filemode.normal_file
60
runtime/Includes/Renderer/Pipelines/Graphics.h
git.filemode.normal_file
@@ -0,0 +1,60 @@
|
|||||||
|
#ifndef __MLX_GRAPHICS_PIPELINE__
|
||||||
|
#define __MLX_GRAPHICS_PIPELINE__
|
||||||
|
|
||||||
|
#include <Renderer/Image.h>
|
||||||
|
#include <Utils/NonOwningPtr.h>
|
||||||
|
#include <Renderer/Pipelines/Shader.h>
|
||||||
|
#include <Renderer/Pipelines/Pipeline.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
struct GraphicPipelineDescriptor
|
||||||
|
{
|
||||||
|
std::shared_ptr<Shader> vertex_shader;
|
||||||
|
std::shared_ptr<Shader> fragment_shader;
|
||||||
|
std::vector<NonOwningPtr<Texture>> color_attachments;
|
||||||
|
NonOwningPtr<class Renderer> renderer = nullptr;
|
||||||
|
bool clear_color_attachments = true;
|
||||||
|
bool no_vertex_inputs = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GraphicPipeline : public Pipeline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GraphicPipeline() = default;
|
||||||
|
|
||||||
|
void Init(const GraphicPipelineDescriptor& descriptor, std::string_view debug_name);
|
||||||
|
bool BindPipeline(VkCommandBuffer cmd, std::size_t framebuffer_index, std::array<float, 4> clear) noexcept;
|
||||||
|
void EndPipeline(VkCommandBuffer cmd) 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; }
|
||||||
|
|
||||||
|
~GraphicPipeline() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
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:
|
||||||
|
std::vector<NonOwningPtr<Texture>> m_attachments;
|
||||||
|
std::vector<VkFramebuffer> m_framebuffers;
|
||||||
|
std::vector<VkClearValue> m_clears;
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::string m_debug_name;
|
||||||
|
#endif
|
||||||
|
std::shared_ptr<Shader> p_vertex_shader;
|
||||||
|
std::shared_ptr<Shader> p_fragment_shader;
|
||||||
|
VkRenderPass m_renderpass = VK_NULL_HANDLE;
|
||||||
|
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||||
|
VkPipelineLayout m_pipeline_layout = VK_NULL_HANDLE;
|
||||||
|
NonOwningPtr<class Renderer> p_renderer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
22
runtime/Includes/Renderer/Pipelines/Pipeline.h
git.filemode.normal_file
22
runtime/Includes/Renderer/Pipelines/Pipeline.h
git.filemode.normal_file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef __MLX_PIPELINE__
|
||||||
|
#define __MLX_PIPELINE__
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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
|
||||||
65
runtime/Includes/Renderer/Pipelines/Shader.h
git.filemode.normal_file
65
runtime/Includes/Renderer/Pipelines/Shader.h
git.filemode.normal_file
@@ -0,0 +1,65 @@
|
|||||||
|
#ifndef __MLX_SHADER__
|
||||||
|
#define __MLX_SHADER__
|
||||||
|
|
||||||
|
#include <Renderer/Enums.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
struct ShaderSetLayout
|
||||||
|
{
|
||||||
|
std::vector<std::pair<int, VkDescriptorType>> binds;
|
||||||
|
|
||||||
|
ShaderSetLayout(std::vector<std::pair<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::vector<std::pair<int, ShaderSetLayout>> set_layouts;
|
||||||
|
std::vector<ShaderPushConstantLayout> push_constants;
|
||||||
|
|
||||||
|
ShaderLayout(std::vector<std::pair<int, ShaderSetLayout> > s, std::vector<ShaderPushConstantLayout> pc) : set_layouts(std::move(s)), push_constants(std::move(pc)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ShaderPipelineLayoutPart
|
||||||
|
{
|
||||||
|
std::vector<VkPushConstantRange> push_constants;
|
||||||
|
std::vector<VkDescriptorSetLayout> set_layouts;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Shader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Shader(const std::vector<std::uint8_t>& bytecode, ShaderType type, ShaderLayout layout);
|
||||||
|
|
||||||
|
[[nodiscard]] inline const ShaderLayout& GetShaderLayout() const { return m_layout; }
|
||||||
|
[[nodiscard]] inline const std::vector<std::uint8_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; }
|
||||||
|
|
||||||
|
~Shader();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GeneratePipelineLayout(ShaderLayout layout);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ShaderLayout m_layout;
|
||||||
|
ShaderPipelineLayoutPart m_pipeline_layout_part;
|
||||||
|
std::vector<std::uint8_t> m_bytecode;
|
||||||
|
std::vector<VkDescriptorSetLayout> m_set_layouts;
|
||||||
|
VkShaderStageFlagBits m_stage;
|
||||||
|
VkShaderModule m_module = VK_NULL_HANDLE;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
58
runtime/Includes/Renderer/RenderCore.h
git.filemode.normal_file
58
runtime/Includes/Renderer/RenderCore.h
git.filemode.normal_file
@@ -0,0 +1,58 @@
|
|||||||
|
#ifndef __MLX_RENDER_CORE__
|
||||||
|
#define __MLX_RENDER_CORE__
|
||||||
|
|
||||||
|
constexpr const int MAX_FRAMES_IN_FLIGHT = 2;
|
||||||
|
|
||||||
|
#include <Renderer/Memory.h>
|
||||||
|
#include <Renderer/Descriptor.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
#if defined(DEBUG) && defined(VK_EXT_debug_utils)
|
||||||
|
#define MLX_HAS_DEBUG_UTILS_FUNCTIONS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class RenderCore
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RenderCore();
|
||||||
|
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkInstance GetInstance() const noexcept { return m_instance; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkInstance& GetInstanceRef() noexcept { return m_instance; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkDevice GetDevice() const noexcept { return m_device; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE VkPhysicalDevice GetPhysicalDevice() const noexcept { return m_physical_device; }
|
||||||
|
[[nodiscard]] MLX_FORCEINLINE GPUAllocator& GetAllocator() noexcept { return m_allocator; }
|
||||||
|
[[nodiscard]] inline DescriptorPoolManager& GetDescriptorPoolManager() noexcept { return m_descriptor_pool_manager; }
|
||||||
|
|
||||||
|
inline void WaitDeviceIdle() const noexcept { vkDeviceWaitIdle(m_device); }
|
||||||
|
|
||||||
|
inline static bool IsInit() noexcept { return s_instance != nullptr; }
|
||||||
|
inline static RenderCore& Get() noexcept { return *s_instance; }
|
||||||
|
|
||||||
|
#define MLX_VULKAN_GLOBAL_FUNCTION(fn) PFN_##fn fn = nullptr;
|
||||||
|
#define MLX_VULKAN_INSTANCE_FUNCTION(fn) PFN_##fn fn = nullptr;
|
||||||
|
#define MLX_VULKAN_DEVICE_FUNCTION(fn) PFN_##fn fn = nullptr;
|
||||||
|
#include <Renderer/Vulkan/VulkanDefs.h>
|
||||||
|
#undef MLX_VULKAN_GLOBAL_FUNCTION
|
||||||
|
#undef MLX_VULKAN_INSTANCE_FUNCTION
|
||||||
|
#undef MLX_VULKAN_DEVICE_FUNCTION
|
||||||
|
|
||||||
|
~RenderCore();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void LoadKVFGlobalVulkanFunctionPointers() const noexcept;
|
||||||
|
void LoadKVFInstanceVulkanFunctionPointers() const noexcept;
|
||||||
|
void LoadKVFDeviceVulkanFunctionPointers() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static RenderCore* s_instance;
|
||||||
|
|
||||||
|
DescriptorPoolManager m_descriptor_pool_manager;
|
||||||
|
GPUAllocator m_allocator;
|
||||||
|
VkInstance m_instance = VK_NULL_HANDLE;
|
||||||
|
VkDevice m_device = VK_NULL_HANDLE;
|
||||||
|
VkPhysicalDevice m_physical_device = VK_NULL_HANDLE;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
29
runtime/Includes/Renderer/RenderPasses/2DPass.h
git.filemode.normal_file
29
runtime/Includes/Renderer/RenderPasses/2DPass.h
git.filemode.normal_file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef __MLX_2D_PASS__
|
||||||
|
#define __MLX_2D_PASS__
|
||||||
|
|
||||||
|
#include <Renderer/RenderCore.h>
|
||||||
|
#include <Renderer/Pipelines/Shader.h>
|
||||||
|
#include <Renderer/Pipelines/Graphics.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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
|
||||||
27
runtime/Includes/Renderer/RenderPasses/FinalPass.h
git.filemode.normal_file
27
runtime/Includes/Renderer/RenderPasses/FinalPass.h
git.filemode.normal_file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef __MLX_FINAL_PASS__
|
||||||
|
#define __MLX_FINAL_PASS__
|
||||||
|
|
||||||
|
#include <Renderer/RenderCore.h>
|
||||||
|
#include <Renderer/Pipelines/Shader.h>
|
||||||
|
#include <Renderer/Pipelines/Graphics.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class FinalPass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FinalPass() = default;
|
||||||
|
void Init();
|
||||||
|
void Pass(class Scene& scene, class Renderer& renderer, class Texture& render_target, NonOwningPtr<class Texture> final_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
|
||||||
29
runtime/Includes/Renderer/RenderPasses/Passes.h
git.filemode.normal_file
29
runtime/Includes/Renderer/RenderPasses/Passes.h
git.filemode.normal_file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef __MLX_PASSES__
|
||||||
|
#define __MLX_PASSES__
|
||||||
|
|
||||||
|
#include <Renderer/Image.h>
|
||||||
|
#include <Renderer/RenderPasses/FinalPass.h>
|
||||||
|
#include <Renderer/RenderPasses/2DPass.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class RenderPasses
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RenderPasses() = default;
|
||||||
|
|
||||||
|
void Init(NonOwningPtr<class Texture> render_target);
|
||||||
|
void Pass(class Scene& scene, class Renderer& renderer, const Vec4f& clear_color);
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
~RenderPasses() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Render2DPass m_2Dpass;
|
||||||
|
FinalPass m_final;
|
||||||
|
Texture m_main_render_texture;
|
||||||
|
NonOwningPtr<class Texture> p_render_target;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
53
runtime/Includes/Renderer/Renderer.h
git.filemode.normal_file
53
runtime/Includes/Renderer/Renderer.h
git.filemode.normal_file
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef __MLX_RENDERER__
|
||||||
|
#define __MLX_RENDERER__
|
||||||
|
|
||||||
|
#include <Platform/Window.h>
|
||||||
|
#include <Utils/NonOwningPtr.h>
|
||||||
|
#include <Renderer/RenderCore.h>
|
||||||
|
#include <Renderer/Image.h>
|
||||||
|
#include <Core/EventBus.h>
|
||||||
|
#include <Renderer/Swapchain.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class Renderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Renderer() = default;
|
||||||
|
|
||||||
|
void Init(NonOwningPtr<Window> window);
|
||||||
|
void Init(NonOwningPtr<Texture> render_target);
|
||||||
|
|
||||||
|
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 NonOwningPtr<Texture> GetRenderTarget() const noexcept { return p_render_target; }
|
||||||
|
[[nodiscard]] inline const Swapchain& GetSwapchain() const noexcept { return m_swapchain; }
|
||||||
|
|
||||||
|
void Destroy() noexcept;
|
||||||
|
|
||||||
|
~Renderer() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Swapchain m_swapchain;
|
||||||
|
std::array<VkSemaphore, MAX_FRAMES_IN_FLIGHT> m_image_available_semaphores;
|
||||||
|
std::array<VkSemaphore, MAX_FRAMES_IN_FLIGHT> m_render_finished_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;
|
||||||
|
NonOwningPtr<Texture> p_render_target;
|
||||||
|
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 __MLX_SCENES_RENDERER__
|
||||||
|
#define __MLX_SCENES_RENDERER__
|
||||||
|
|
||||||
|
#include <Renderer/RenderPasses/Passes.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
class SceneRenderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SceneRenderer() = default;
|
||||||
|
void Init(NonOwningPtr<class Texture> render_target);
|
||||||
|
void Render(class Scene& scene, class Renderer& renderer);
|
||||||
|
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 __MLX_SWAPCHAIN__
|
||||||
|
#define __MLX_SWAPCHAIN__
|
||||||
|
|
||||||
|
#include <Utils/NonOwningPtr.h>
|
||||||
|
#include <Renderer/Image.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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
|
||||||
26
runtime/Includes/Renderer/Vertex.h
git.filemode.normal_file
26
runtime/Includes/Renderer/Vertex.h
git.filemode.normal_file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __MLX_VERTEX__
|
||||||
|
#define __MLX_VERTEX__
|
||||||
|
|
||||||
|
#include <Maths/Vec4.h>
|
||||||
|
#include <Maths/Vec2.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
struct Vertex
|
||||||
|
{
|
||||||
|
alignas(16) Vec4f position = Vec4f{ 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
alignas(16) Vec2f uv = Vec2f{ 0.0f, 0.0f };
|
||||||
|
|
||||||
|
Vertex() = default;
|
||||||
|
inline Vertex(Vec4f p, Vec2f u) : position(std::move(p)), uv(std::move(u)) {}
|
||||||
|
|
||||||
|
[[nodiscard]] inline bool operator==(const Vertex& rhs) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline static VkVertexInputBindingDescription GetBindingDescription();
|
||||||
|
[[nodiscard]] inline static std::array<VkVertexInputAttributeDescription, 2> GetAttributeDescriptions();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Renderer/Vertex.inl>
|
||||||
|
|
||||||
|
#endif
|
||||||
36
runtime/Includes/Renderer/Vertex.inl
git.filemode.normal_file
36
runtime/Includes/Renderer/Vertex.inl
git.filemode.normal_file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Renderer/Vertex.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
bool Vertex::operator==(const Vertex& rhs) const noexcept
|
||||||
|
{
|
||||||
|
return position == rhs.position && uv == rhs.uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, 2> Vertex::GetAttributeDescriptions()
|
||||||
|
{
|
||||||
|
std::array<VkVertexInputAttributeDescription, 2> 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_R32G32_SFLOAT;
|
||||||
|
attribute_descriptions[1].offset = offsetof(Vertex, uv);
|
||||||
|
|
||||||
|
return attribute_descriptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
runtime/Includes/Renderer/ViewerData.h
git.filemode.normal_file
14
runtime/Includes/Renderer/ViewerData.h
git.filemode.normal_file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef __MLX_VIEWER_DATA__
|
||||||
|
#define __MLX_VIEWER_DATA__
|
||||||
|
|
||||||
|
#include <Maths/Mat4.h>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
struct ViewerData
|
||||||
|
{
|
||||||
|
Mat4f projection_matrix;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#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 MLX_VULKAN_GLOBAL_FUNCTION
|
||||||
|
MLX_VULKAN_GLOBAL_FUNCTION(vkCreateInstance)
|
||||||
|
MLX_VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceExtensionProperties)
|
||||||
|
MLX_VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceLayerProperties)
|
||||||
|
MLX_VULKAN_GLOBAL_FUNCTION(vkGetInstanceProcAddr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MLX_VULKAN_INSTANCE_FUNCTION
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkCreateDevice)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkDestroyInstance)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkEnumerateDeviceExtensionProperties)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkGetDeviceProcAddr)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFormatProperties)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceImageFormatProperties)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties)
|
||||||
|
#ifdef DEBUG
|
||||||
|
#ifdef VK_EXT_debug_utils
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkSetDebugUtilsObjectNameEXT)
|
||||||
|
//MLX_VULKAN_INSTANCE_FUNCTION(vkSetDebugUtilsObjectTagEXT)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MLX_VULKAN_DEVICE_FUNCTION
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkAllocateCommandBuffers)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkAllocateDescriptorSets)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkAllocateMemory)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkBeginCommandBuffer)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkBindBufferMemory)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkBindImageMemory)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdBeginRenderPass)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdBindDescriptorSets)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdBindIndexBuffer)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdBindPipeline)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdBindVertexBuffers)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdClearAttachments)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdClearColorImage)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdClearDepthStencilImage)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdCopyBuffer)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdCopyBufferToImage)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdCopyImage)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdCopyImageToBuffer)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdDraw)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdDrawIndexed)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdEndRenderPass)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdPipelineBarrier)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdPushConstants)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdSetScissor)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCmdSetViewport)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateBuffer)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateCommandPool)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateDescriptorPool)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateDescriptorSetLayout)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateFence)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateFramebuffer)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateGraphicsPipelines)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateImage)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateImageView)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreatePipelineLayout)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateRenderPass)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateSampler)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateSemaphore)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateShaderModule)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyBuffer)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyCommandPool)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyDescriptorPool)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyDescriptorSetLayout)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyDevice)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyFence)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyFramebuffer)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyImage)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyImageView)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyPipeline)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyPipelineLayout)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyRenderPass)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroySampler)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroySemaphore)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroyShaderModule)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDeviceWaitIdle)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkEndCommandBuffer)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkFlushMappedMemoryRanges)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkFreeCommandBuffers)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkFreeMemory)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkGetBufferMemoryRequirements)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkGetDeviceMemoryCommitment)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkGetDeviceQueue)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkGetFenceStatus)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkGetImageMemoryRequirements)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkGetImageSubresourceLayout)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkInvalidateMappedMemoryRanges)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkMapMemory)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkQueueSubmit)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkQueueWaitIdle)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkResetCommandBuffer)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkResetDescriptorPool)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkResetEvent)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkResetFences)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkUnmapMemory)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkUpdateDescriptorSets)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkWaitForFences)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef VK_KHR_swapchain
|
||||||
|
#ifdef MLX_VULKAN_DEVICE_FUNCTION
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkAcquireNextImageKHR)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkCreateSwapchainKHR)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkDestroySwapchainKHR)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkGetSwapchainImagesKHR)
|
||||||
|
MLX_VULKAN_DEVICE_FUNCTION(vkQueuePresentKHR)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef VK_KHR_surface
|
||||||
|
#ifdef MLX_VULKAN_INSTANCE_FUNCTION
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkDestroySurfaceKHR)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceCapabilitiesKHR)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR)
|
||||||
|
MLX_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR)
|
||||||
|
#endif
|
||||||
|
#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 __MLX_ANSI__
|
||||||
|
#define __MLX_ANSI__
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace mlx
|
||||||
|
{
|
||||||
|
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, Ansi ansi)
|
||||||
|
{
|
||||||
|
return os << "\033[1;" << std::to_string(static_cast<std::uint32_t>(ansi)) << "m";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user