diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml
index 6681f8cc..865e37d4 100644
--- a/.github/workflows/cmake-multi-platform.yml
+++ b/.github/workflows/cmake-multi-platform.yml
@@ -8,37 +8,121 @@ on:
env:
BUILD_TYPE: Release
+ ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: "true"
+ ACTIONS_RUNNER_FORCE_NODE24: "true"
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
build:
+ runs-on: ${{ matrix.os }}
strategy:
+ fail-fast: false
matrix:
- os: [windows-2025, ubuntu-latest]
-
- runs-on: ${{ matrix.os }}
+ include:
+ - name: Windows
+ os: windows-latest
+ target: windows
+ - name: Linux
+ os: ubuntu-latest
+ target: linux
+ - name: Web (WASM)
+ os: ubuntu-22.04
+ target: web
steps:
- - uses: actions/checkout@v4
+ - name: Checkout code
+ uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- - name: Ensure submodules are up-to-date
- run: git submodule update --init --recursive
-
- - name: Check submodulesversions
- run: git submodule status
-
+ # ------------------------------------------------------------------------
+ # Linux Dependencies
+ # ------------------------------------------------------------------------
- name: Install dependencies (Linux)
- if: runner.os == 'Linux'
- run: sudo apt update && sudo apt install -y cmake g++ make xorg-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev
+ if: matrix.target == 'linux'
+ run: sudo apt update && sudo apt install -y cmake g++ make xorg-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev xvfb
- - name: Configure CMake
- run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+ # ------------------------------------------------------------------------
+ # Web / Emscripten Dependencies
+ # ------------------------------------------------------------------------
+ - name: Setup Emscripten (Web)
+ if: matrix.target == 'web'
+ uses: mymindstorm/setup-emsdk@v14
+ with:
+ version: latest
+
+ # ------------------------------------------------------------------------
+ # Desktop Builds (Windows & Linux)
+ # ------------------------------------------------------------------------
+ - name: Configure CMake (Desktop)
+ if: matrix.target != 'web'
+ run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DWEIRD_ENGINE_BUILD_EXAMPLES=ON -DWEIRD_TEST_HOOKS=ON
- - name: Build
+ - name: Build (Desktop)
+ if: matrix.target != 'web'
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- - name: Test
- working-directory: ${{github.workspace}}/build
- run: ctest -C ${{env.BUILD_TYPE}}
+ - name: Test (Linux)
+ if: matrix.target == 'linux'
+ working-directory: ${{github.workspace}}/build/examples/sample-scenes
+ env:
+ WEIRD_AUTO_QUIT_SECONDS: 3
+ WEIRD_SCREENSHOT_FRAME: 10
+ run: xvfb-run -a ./WeirdSamples
+
+ - name: Upload Test Artifacts (Linux)
+ if: matrix.target == 'linux' && always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: test-artifacts-${{ matrix.target }}
+ path: |
+ ${{github.workspace}}/build/examples/sample-scenes/log.txt
+ ${{github.workspace}}/build/examples/sample-scenes/screenshot_*.bmp
+ ${{github.workspace}}/build/examples/sample-scenes/Release/log.txt
+ ${{github.workspace}}/build/examples/sample-scenes/Release/screenshot_*.bmp
+
+ # ------------------------------------------------------------------------
+ # Web Build (Emscripten / WASM)
+ # ------------------------------------------------------------------------
+ - name: Build WeirdSamples for Web
+ if: matrix.target == 'web'
+ run: |
+ mkdir build && cd build
+ emcmake cmake .. \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DWEIRD_ENGINE_BUILD_EXAMPLES=ON \
+ -DBUILD_WEB=ON \
+ -DCMAKE_C_FLAGS="-pthread" \
+ -DCMAKE_CXX_FLAGS="-pthread" \
+ -DCMAKE_EXECUTABLE_SUFFIX=".html" \
+ -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 --preload-file ${{github.workspace}}/examples/sample-scenes/assets@/assets --preload-file ${{github.workspace}}/src/weird-renderer/fonts@/fonts --preload-file ${{github.workspace}}/src/weird-renderer/shaders@/shaders"
+ emmake make WeirdSamples
+
+ - name: Prepare Web Artifact
+ if: matrix.target == 'web'
+ run: |
+ mkdir -p game_export
+ # Copy generated outputs (index.* or WeirdSamples.*)
+ cp build/examples/sample-scenes/index.* game_export/ 2>/dev/null || true
+ cp build/examples/sample-scenes/WeirdSamples.* game_export/ 2>/dev/null || true
+
+ # Guarantee index.html exists in game_export/
+ if [ ! -f game_export/index.html ]; then
+ if [ -f game_export/WeirdSamples.html ]; then
+ cp game_export/WeirdSamples.html game_export/index.html
+ elif [ -f game_export/index.js ]; then
+ echo '
WeirdEngine Web' > game_export/index.html
+ fi
+ fi
+
+ cp -r build/examples/sample-scenes/assets game_export/ 2>/dev/null || true
+ cp -r build/examples/sample-scenes/fonts game_export/ 2>/dev/null || true
+ cp -r build/examples/sample-scenes/shaders game_export/ 2>/dev/null || true
+
+ - name: Upload Web Artifact
+ if: matrix.target == 'web'
+ uses: actions/upload-artifact@v4
+ with:
+ name: weird-engine-web-sample
+ path: game_export/
diff --git a/.github/workflows/deploy-itch.yml b/.github/workflows/deploy-itch.yml
new file mode 100644
index 00000000..04e7d060
--- /dev/null
+++ b/.github/workflows/deploy-itch.yml
@@ -0,0 +1,74 @@
+name: Deploy to itch.io
+
+on:
+ # Run manually from the Actions tab
+ workflow_dispatch:
+ # Optionally also run when you push a version tag (e.g. v1.0)
+ # push:
+ # tags:
+ # - 'v*'
+
+env:
+ BUILD_TYPE: Release
+
+jobs:
+ build-and-deploy:
+ name: Build Web & Push to itch.io
+ runs-on: ubuntu-22.04
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ fetch-depth: 0
+
+ # ------------------------------------------------------------------------
+ # Build the Web (Emscripten / WASM) version
+ # ------------------------------------------------------------------------
+ - name: Setup Emscripten
+ uses: mymindstorm/setup-emsdk@v14
+ with:
+ version: latest
+
+ - name: Build WeirdSamples for Web
+ run: |
+ mkdir build && cd build
+ emcmake cmake .. \
+ -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
+ -DWEIRD_ENGINE_BUILD_EXAMPLES=ON \
+ -DBUILD_WEB=ON \
+ -DCMAKE_C_FLAGS="-pthread" \
+ -DCMAKE_CXX_FLAGS="-pthread" \
+ -DCMAKE_EXECUTABLE_SUFFIX=".html" \
+ -DCMAKE_EXE_LINKER_FLAGS="-pthread -sPTHREAD_POOL_SIZE=4 -sINITIAL_MEMORY=33554432 -sMAX_WEBGL_VERSION=2 -sMIN_WEBGL_VERSION=2 --preload-file ${{github.workspace}}/examples/sample-scenes/assets@/assets --preload-file ${{github.workspace}}/src/weird-renderer/fonts@/fonts --preload-file ${{github.workspace}}/src/weird-renderer/shaders@/shaders"
+ emmake make WeirdSamples
+
+ - name: Prepare Web Artifact
+ run: |
+ mkdir -p game_export
+ cp build/examples/sample-scenes/index.* game_export/ 2>/dev/null || true
+ cp build/examples/sample-scenes/WeirdSamples.* game_export/ 2>/dev/null || true
+
+ if [ ! -f game_export/index.html ]; then
+ if [ -f game_export/WeirdSamples.html ]; then
+ cp game_export/WeirdSamples.html game_export/index.html
+ elif [ -f game_export/index.js ]; then
+ echo 'WeirdEngine Web' > game_export/index.html
+ fi
+ fi
+
+ cp -r build/examples/sample-scenes/assets game_export/ 2>/dev/null || true
+ cp -r build/examples/sample-scenes/fonts game_export/ 2>/dev/null || true
+ cp -r build/examples/sample-scenes/shaders game_export/ 2>/dev/null || true
+
+ # ------------------------------------------------------------------------
+ # Publish to itch.io via Butler
+ # ------------------------------------------------------------------------
+ - name: Setup Butler
+ uses: remarkablegames/setup-butler@v2
+
+ - name: Push to itch.io
+ env:
+ BUTLER_API_KEY: ${{ secrets.BUTLER_API_KEY }}
+ run: butler push ./game_export/ damaca/weird-engine:html
\ No newline at end of file
diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml
new file mode 100644
index 00000000..afa5ddec
--- /dev/null
+++ b/.github/workflows/format.yml
@@ -0,0 +1,22 @@
+name: Clang Format Check
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ format-check:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.x'
+
+ - name: Run pre-commit
+ uses: pre-commit/action@v3.0.1
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 00000000..254c2d21
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,8 @@
+repos:
+ - repo: https://github.com/pre-commit/mirrors-clang-format
+ rev: v18.1.8 # Force this exact version for everyone
+ hooks:
+ - id: clang-format
+ # Removed types_or to ensure it catches custom shader extensions (.frag, .vert)
+ files: \.(h|cpp|glsl|frag|vert)$
+ exclude: ^(third-party|build|build-muos|dist-muos|\.git)/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9f2fac9c..fdd20ec3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10)
project(WeirdEngine)
-execute_process(COMMAND git submodule update --init --recursive)
+execute_process(COMMAND git submodule update --init --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -60,6 +60,10 @@ target_include_directories(imgui
${IMGUI_DIR}/backends
${CMAKE_CURRENT_SOURCE_DIR}/third-party/SDL/include
)
+target_link_libraries(imgui PRIVATE glad)
+if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN)
+ target_link_libraries(imgui PRIVATE GLESv2 EGL dl)
+endif()
endif()
target_include_directories(${PROJECT_NAME}
@@ -78,37 +82,41 @@ target_include_directories(glad
# SDL3 setup
# FORCE SDL3 to build as a STATIC library.
-# This prevents the creation of libSDL3.so and embeds the code
-# directly into your engine/game.
-set(SDL_SHARED ON CACHE BOOL "Build SDL shared library" FORCE)
-set(SDL_STATIC OFF CACHE BOOL "Build SDL static library" FORCE)
-set(SDL_DEPS_SHARED ON CACHE BOOL "Load dependencies dynamically" FORCE)
-set(SDL_KMSDRM_SHARED ON CACHE BOOL "Dynamically load KMS DRM support" FORCE)
+set(SDL_SHARED OFF CACHE BOOL "Build SDL shared library" FORCE)
+set(SDL_STATIC ON CACHE BOOL "Build SDL static library" FORCE)
+
+if(EMSCRIPTEN)
+ set(SDL_DEPS_SHARED OFF CACHE BOOL "Load dependencies dynamically" FORCE)
+ set(SDL_KMSDRM_SHARED OFF CACHE BOOL "Dynamically load KMS DRM support" FORCE)
+else()
+ set(SDL_DEPS_SHARED ON CACHE BOOL "Load dependencies dynamically" FORCE)
+ set(SDL_KMSDRM_SHARED ON CACHE BOOL "Dynamically load KMS DRM support" FORCE)
+endif()
# Add dependencies
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/third-party/SDL)
# Force SDL3 to dynamically load KMSDRM libraries via dlopen instead of hard-linking.
# This is necessary because cmake_dependent_option overrides our FORCE cache entries.
-if(TARGET SDL3-shared)
- target_compile_definitions(SDL3-shared PRIVATE
+if(TARGET SDL3-static AND CMAKE_SYSTEM_NAME MATCHES "Linux")
+ target_compile_definitions(SDL3-static PRIVATE
"SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC=\"libdrm.so.2\""
"SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM=\"libgbm.so.1\""
)
# Keep the include directories for compilation but remove link dependencies
- target_include_directories(SDL3-shared PRIVATE
+ target_include_directories(SDL3-static PRIVATE
/usr/include/libdrm
/usr/include
)
# Remove the hard link dependencies that SDL added
- get_target_property(_libs SDL3-shared LINK_LIBRARIES)
+ get_target_property(_libs SDL3-static LINK_LIBRARIES)
if(_libs)
list(FILTER _libs EXCLUDE REGEX "PC_LIBDRM|PC_GBM")
- set_target_properties(SDL3-shared PROPERTIES LINK_LIBRARIES "${_libs}")
+ set_target_properties(SDL3-static PROPERTIES LINK_LIBRARIES "${_libs}")
endif()
- get_target_property(_iface_libs SDL3-shared INTERFACE_LINK_LIBRARIES)
+ get_target_property(_iface_libs SDL3-static INTERFACE_LINK_LIBRARIES)
if(_iface_libs)
list(FILTER _iface_libs EXCLUDE REGEX "PC_LIBDRM|PC_GBM")
- set_target_properties(SDL3-shared PROPERTIES INTERFACE_LINK_LIBRARIES "${_iface_libs}")
+ set_target_properties(SDL3-static PROPERTIES INTERFACE_LINK_LIBRARIES "${_iface_libs}")
endif()
endif()
# add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/third-party/SDL_image)
@@ -144,11 +152,12 @@ target_include_directories(glad
PUBLIC
SDL3::SDL3
PRIVATE
- GLESv2
- EGL
- dl
glad
)
+ if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN)
+ target_link_libraries(${PROJECT_NAME} PRIVATE GLESv2 EGL dl)
+ endif()
+
if(NOT WEIRD_DISABLE_IMGUI)
target_link_libraries(${PROJECT_NAME} PUBLIC imgui)
else()
@@ -161,6 +170,10 @@ endif()
# Shaders
+if(EMSCRIPTEN)
+ set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "Load shaders/assets from runtime folder instead of source tree" FORCE)
+endif()
+
option(WEIRD_ENGINE_USE_RUNTIME_ASSETS
"Load shaders/assets from runtime folder instead of source tree"
OFF
@@ -210,3 +223,9 @@ if(WEIRD_ENGINE_BUILD_EXAMPLES)
add_subdirectory(examples/opengl-experiments)
add_subdirectory(examples/sample-scenes)
endif()
+
+# Tools
+option(WEIRD_ENGINE_BUILD_TOOLS "Build tool projects" OFF)
+if(WEIRD_ENGINE_BUILD_TOOLS)
+ add_subdirectory(tools)
+endif()
diff --git a/examples/3d-experiments/CMakeLists.txt b/examples/3d-experiments/CMakeLists.txt
index bb0c8448..978b697c 100644
--- a/examples/3d-experiments/CMakeLists.txt
+++ b/examples/3d-experiments/CMakeLists.txt
@@ -1,36 +1,80 @@
cmake_minimum_required(VERSION 3.10)
+
+# ==============================================================================
+# 1. Project Configuration
+# ==============================================================================
project(Weird3D)
+# Path to the WeirdEngine directory. Change this depending on where your project is located.
+# Examples inside weird-engine use "../../"
+# External projects usually use "../weird-engine/" or similar.
+set(WEIRD_ENGINE_LOCAL_PATH "../../")
+# ==============================================================================
+
# Create folders if they don't exist
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src")
-set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF) # Ensure strictly standard C++
# Option to switch between local and online version of WeirdEngine
option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON)
-# Set paths for the local WeirdEngine
-set(WEIRD_ENGINE_LOCAL_PATH "../../")
+# Option to build for web (Emscripten)
+option(BUILD_WEB "Build for web using Emscripten" OFF)
+
+# Option to build for standalone deployment
+option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF)
+
+# Auto-detect Emscripten toolchain or explicit BUILD_WEB flag
+if(EMSCRIPTEN OR BUILD_WEB)
+ set(BUILD_WEB ON CACHE BOOL "" FORCE)
+ set(BUILD_WEB ON)
+ set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE)
+ set(DEPLOY_STANDALONE ON)
+endif()
+
+if(DEPLOY_STANDALONE)
+ message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.")
+ # Force the engine to expect runtime assets
+ set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "" FORCE)
+else()
+ message(STATUS ">> DEV MODE: Assets read directly from source folder.")
+endif()
+# -------------------------------------------------------------------------
+# INCLUDE ENGINE & CAPTURE SOURCE PATH
+# -------------------------------------------------------------------------
if(NOT TARGET WeirdEngine)
if(USE_LOCAL_WEIRD_ENGINE)
# Use the local version of WeirdEngine
- message(STATUS "Using local version of WeirdEngine")
+ message(STATUS "Using local version of WeirdEngine at ${WEIRD_ENGINE_LOCAL_PATH}")
add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine)
+
+ # Resolve the local path to an absolute path for copying files later
+ get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE)
else()
# Fetch WeirdEngine from GitHub
message(STATUS "Using online version of WeirdEngine")
+ set(WEIRD_ENGINE_GIT_REF "main")
+
include(FetchContent)
FetchContent_Declare(
WeirdEngine
GIT_REPOSITORY https://github.com/damacaa/weird-engine
- GIT_TAG main
+ GIT_TAG ${WEIRD_ENGINE_GIT_REF}
)
FetchContent_MakeAvailable(WeirdEngine)
+
+ # FetchContent defines _SOURCE_DIR (usually lowercase)
+ set(WEIRD_ENGINE_REAL_SOURCE "${weirdengine_SOURCE_DIR}")
endif()
+else()
+ # WeirdEngine already defined (built from root); resolve its source path
+ get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE)
endif()
# Glob source files and header files from the proper directories.
@@ -49,48 +93,79 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU
# Add executable including both sources and headers.
add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS})
+if(BUILD_WEB)
+ set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html")
+endif()
+
# Set include directories.
-target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
-target_include_directories(${PROJECT_NAME} PRIVATE
- ${CMAKE_BINARY_DIR}/weird-engine/include
- ${CMAKE_BINARY_DIR}/weird-engine/third-party/include
-)
+target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
# Link to WeirdEngine.
target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine)
# Set Asset Path Macro
-# Define the assets path variable
-set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
-# set(ASSETS_PATH "./assets") # Set the asset path macro in release mode to a relative path that assumes the assets folder is in the same directory as the game executable
+if(DEPLOY_STANDALONE)
+ set(ASSETS_PATH "./assets/")
+else()
+ set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
+endif()
-# Print the assets path for debugging or confirmation
message(STATUS "Assets path: ${ASSETS_PATH}")
-
-# Use the variable in target_compile_definitions
target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${ASSETS_PATH}")
if (MINGW)
target_link_options(${PROJECT_NAME} PRIVATE -static -static-libgcc -static-libstdc++)
endif()
-# ----------------------------------------------------------
-# Helper function to assign source groups based on folder structure.
+# -------------------------------------------------------------------------
+# POST BUILD COMMANDS (DLLs + Assets + Fonts + Shaders)
+# -------------------------------------------------------------------------
+if(DEPLOY_STANDALONE)
+ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ # 1. Copy Project ASSETS folder -> Build/assets
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${CMAKE_CURRENT_SOURCE_DIR}/assets"
+ "$/assets"
+
+ # 2. Copy WeirdEngine FONTS -> Build/fonts
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts"
+ "$/fonts"
+
+ # 3. Copy WeirdEngine SHADERS -> Build/shaders
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders"
+ "$/shaders"
+
+ COMMENT "Copying Game Assets, Engine Fonts, and Engine Shaders"
+ )
+
+ if(BUILD_WEB)
+ # For web builds, copy index.html if it exists
+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html")
+ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html"
+ "$/index.html"
+ COMMENT "Copying index.html for web build"
+ )
+ endif()
+ endif()
+endif()
+
+# -------------------------------------------------------------------------
+# SOURCE GROUPS
+# -------------------------------------------------------------------------
function(assign_source_groups TARGET)
foreach(source_file IN LISTS ARGN)
- # Get the full path to the file's directory.
get_filename_component(FILE_PATH "${source_file}" PATH)
- # Compute the path relative to the project's root.
file(RELATIVE_PATH REL_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${FILE_PATH}")
- # Replace forward slashes with backslashes for Visual Studio filter naming.
string(REPLACE "/" "\\" FILTER_PATH "${REL_PATH}")
if(FILTER_PATH STREQUAL "")
set(FILTER_PATH "Root")
endif()
- # Assign the file to the computed filter.
source_group("${FILTER_PATH}" FILES "${source_file}")
endforeach()
endfunction()
-# Assign source groups for all your files.
assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS})
diff --git a/examples/3d-experiments/include/Classic.h b/examples/3d-experiments/include/Classic.h
index 3533f261..27eb98a0 100644
--- a/examples/3d-experiments/include/Classic.h
+++ b/examples/3d-experiments/include/Classic.h
@@ -18,10 +18,10 @@ class ClassicScene : public Scene3D
auto& redMat = createMaterial();
redMat.color = vec4(.8f, 0.2f, 0.2f, 1.0f);
-
+
auto& orangeMat = createMaterial();
orangeMat.color = vec4(.95f, 0.4f, 0.1f, 1.0f);
-
+
auto& floorMaterial = createMaterial();
floorMaterial.color = vec4(1.0f, 1.0f, 1.0f, 1.0f);
floorMaterial.secondaryColor = vec4(0.4f, 0.4f, 0.6f, 1.0f);
@@ -64,8 +64,8 @@ class ClassicScene : public Scene3D
Entity start = addShape(DefaultShapes3D::PLANE, vars1, floorMaterial, CombinationType::Addition, false);
}
- getLigths().push_back(
- Light{0, glm::vec3(0.0f, 3.0f, 0.0f), 0, glm::vec3(0.35f, 0.45f, 0.5f), glm::vec4(1.0f, 0.95f, 0.9f, 2.0f)});
+ getLigths().push_back(Light{0, glm::vec3(0.0f, 3.0f, 0.0f), 0, glm::vec3(0.35f, 0.45f, 0.5f),
+ glm::vec4(1.0f, 0.95f, 0.9f, 2.0f)});
ecs.getComponent(m_mainCamera).position = vec3(0, 2, 10);
}
diff --git a/examples/3d-experiments/include/CornellBox.h b/examples/3d-experiments/include/CornellBox.h
index e15d9924..064fde3b 100644
--- a/examples/3d-experiments/include/CornellBox.h
+++ b/examples/3d-experiments/include/CornellBox.h
@@ -11,7 +11,7 @@ using namespace WeirdEngine;
class CornellBox : public Scene3D
{
public:
- CornellBox(){};
+ CornellBox() {};
private:
// Inherited via Scene
diff --git a/examples/3d-experiments/include/MaterialShowcase.h b/examples/3d-experiments/include/MaterialShowcase.h
index 9a43bc18..fbc7d880 100644
--- a/examples/3d-experiments/include/MaterialShowcase.h
+++ b/examples/3d-experiments/include/MaterialShowcase.h
@@ -11,17 +11,14 @@ using namespace WeirdEngine;
class MaterialShowcaseScene : public Scene3D
{
public:
- MaterialShowcaseScene(){};
+ MaterialShowcaseScene() {};
private:
-
// Inherited via Scene
void onStart(ECSManager& ecs) override
{
m_debugFly = true;
-
-
{
Entity entity = ecs.createEntity();
Transform& t = ecs.addComponent(entity);
@@ -35,20 +32,19 @@ class MaterialShowcaseScene : public Scene3D
auto& sdf = ecs.addComponent(entity);
sdf.materialId = mat.id;
}
-
+
std::vector randomMats;
vec4 colors[] = {
- vec4(.95f, 0.4f, 0.1f, 1.0f), // Orange
- vec4(0.5f, 0.0f, 1.0f, 1.0f), // Purple
- vec4(0.0f, .9f, .9f, 1.0f), // Cyan
- vec4(0.5f, 1.0f, 0.5f, 1.0f), // Light Green
- vec4(1.0f, 0.3f, .6f, 1.0f), // Magenta
- vec4(1.0f, 0.5f, 0.5f, 1.0f), // Pink
- vec4(0.5f, 0.5f, 1.0f, 1.0f), // Light Blue
- vec4(0.4f, 0.25f, 0.1f, 1.0f) // Brown
+ vec4(.95f, 0.4f, 0.1f, 1.0f), // Orange
+ vec4(0.5f, 0.0f, 1.0f, 1.0f), // Purple
+ vec4(0.0f, .9f, .9f, 1.0f), // Cyan
+ vec4(0.5f, 1.0f, 0.5f, 1.0f), // Light Green
+ vec4(1.0f, 0.3f, .6f, 1.0f), // Magenta
+ vec4(1.0f, 0.5f, 0.5f, 1.0f), // Pink
+ vec4(0.5f, 0.5f, 1.0f, 1.0f), // Light Blue
+ vec4(0.4f, 0.25f, 0.1f, 1.0f) // Brown
};
-
{
auto& mat = createMaterial();
mat.color = vec4(.95f, 0.4f, 0.1f, 1.0f);
@@ -67,7 +63,7 @@ class MaterialShowcaseScene : public Scene3D
mat.roughness = 0.99f;
mat.pattern = MaterialPattern::Checkers;
mat.secondaryColor = mat.color * 0.8f;
-
+
randomMats.push_back(mat.id);
}
@@ -75,11 +71,11 @@ class MaterialShowcaseScene : public Scene3D
auto& mat = createMaterial();
mat.color = vec4(1.0f, 0.3f, .6f, 1.0f);
mat.secondaryColor = vec4(1.0f, 0.2f, 0.05f, 1.0f);
-
+
mat.metallic = 0.5f;
mat.roughness = 0.05f;
mat.pattern = MaterialPattern::Waves;
-
+
randomMats.push_back(mat.id);
}
@@ -90,7 +86,7 @@ class MaterialShowcaseScene : public Scene3D
mat.roughness = 0.99f;
mat.pattern = MaterialPattern::Checkers;
mat.secondaryColor = mat.color * 0.8f;
-
+
randomMats.push_back(mat.id);
}
@@ -102,7 +98,7 @@ class MaterialShowcaseScene : public Scene3D
mat.roughness = 0.001f;
mat.pattern = MaterialPattern::PerlinNoise;
mat.patternScale = 5.0f;
-
+
randomMats.push_back(mat.id);
}
@@ -111,13 +107,11 @@ class MaterialShowcaseScene : public Scene3D
mat.color = vec4(0.85f, 0.7f, 0.1f, 0.5f);
mat.metallic = 0.5f;
mat.roughness = 0.0f;
-
+
randomMats.push_back(mat.id);
}
-
-
- for (size_t i = 0; i < randomMats.size(); i++)
+ for (size_t i = 0; i < randomMats.size(); i++)
{
Entity entity = ecs.createEntity();
Transform& t = ecs.addComponent(entity);
@@ -145,7 +139,7 @@ class MaterialShowcaseScene : public Scene3D
mirrorMaterial.roughness = 0.0f;
{
-
+
std::shared_ptr box = std::make_shared();
auto boxId = registerSDF(box);
@@ -161,8 +155,8 @@ class MaterialShowcaseScene : public Scene3D
Entity start = addShape(boxId, vars1, mirrorMaterial, CombinationType::Addition, false);
}
- getLigths().push_back(
- Light{0, glm::vec3(0.0f, 0.0f, 0.0f), 0, normalize(glm::vec3(0.0f, 0.4f, 1.0f)), glm::vec4(1.0f, 1.0f, 1.0f, 0.5f)});
+ getLigths().push_back(Light{0, glm::vec3(0.0f, 0.0f, 0.0f), 0, normalize(glm::vec3(0.0f, 0.4f, 1.0f)),
+ glm::vec4(1.0f, 1.0f, 1.0f, 0.5f)});
// getLigths().push_back(
// Light{1, glm::vec3(0.0f, 0.0f, 0.0f), 0, glm::vec3(0.35f, 0.45f, 0.5f), glm::vec4(0.0f, 1.0f, 0.0f, 1.0f)});
diff --git a/examples/3d-experiments/src/index.html b/examples/3d-experiments/src/index.html
new file mode 100644
index 00000000..99a4611e
--- /dev/null
+++ b/examples/3d-experiments/src/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+ Weird3D
+
+
+
+
+
+
+
+
+
diff --git a/examples/3d-experiments/src/main.cpp b/examples/3d-experiments/src/main.cpp
index 07236aa8..8bc976e7 100644
--- a/examples/3d-experiments/src/main.cpp
+++ b/examples/3d-experiments/src/main.cpp
@@ -4,8 +4,8 @@
#include
#include "Classic.h"
-#include "MaterialShowcase.h"
#include "CornellBox.h"
+#include "MaterialShowcase.h"
int main(int argc, char* argv[])
{
@@ -31,8 +31,6 @@ int main(int argc, char* argv[])
displaySettings.colorPalette[DisplaySettings::Orange].a = 1.0f;
-
-
PhysicsSettings physicsSettings{};
AudioSettings audioSettings{};
diff --git a/examples/empty-project/CMakeLists.txt b/examples/empty-project/CMakeLists.txt
index 2f8b4197..a0239686 100644
--- a/examples/empty-project/CMakeLists.txt
+++ b/examples/empty-project/CMakeLists.txt
@@ -1,44 +1,90 @@
cmake_minimum_required(VERSION 3.10)
+
+# ==============================================================================
+# 1. Project Configuration
+# ==============================================================================
project(WeirdGame)
+# Path to the WeirdEngine directory. Change this depending on where your project is located.
+# Examples inside weird-engine use "../../"
+# External projects usually use "../weird-engine/" or similar.
+set(WEIRD_ENGINE_LOCAL_PATH "../../")
+# ==============================================================================
+
# Create folders if they don't exist
-file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/assets")
-file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/include")
-file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/src")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src")
-set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF) # Ensure strictly standard C++
# Option to switch between local and online version of WeirdEngine
option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON)
-# Set paths for the local WeirdEngine
-set(WEIRD_ENGINE_LOCAL_PATH "../../")
+# Option to build for web (Emscripten)
+option(BUILD_WEB "Build for web using Emscripten" OFF)
+
+# Option to build for standalone deployment
+option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF)
-if(USE_LOCAL_WEIRD_ENGINE)
- # Use the local version of WeirdEngine
- message(STATUS "Using local version of WeirdEngine")
- add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine)
+# Auto-detect Emscripten toolchain or explicit BUILD_WEB flag
+if(EMSCRIPTEN OR BUILD_WEB)
+ set(BUILD_WEB ON CACHE BOOL "" FORCE)
+ set(BUILD_WEB ON)
+ set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE)
+ set(DEPLOY_STANDALONE ON)
+endif()
+
+if(DEPLOY_STANDALONE)
+ message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.")
+ # Force the engine to expect runtime assets
+ set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "" FORCE)
else()
- # Fetch WeirdEngine from GitHub
- message(STATUS "Using online version of WeirdEngine")
- include(FetchContent)
- FetchContent_Declare(
- WeirdEngine
- GIT_REPOSITORY https://github.com/damacaa/weird-engine
- GIT_TAG main
- )
- FetchContent_MakeAvailable(WeirdEngine)
+ message(STATUS ">> DEV MODE: Assets read directly from source folder.")
+endif()
+
+# -------------------------------------------------------------------------
+# INCLUDE ENGINE & CAPTURE SOURCE PATH
+# -------------------------------------------------------------------------
+if(NOT TARGET WeirdEngine)
+ if(USE_LOCAL_WEIRD_ENGINE)
+ # Use the local version of WeirdEngine
+ message(STATUS "Using local version of WeirdEngine at ${WEIRD_ENGINE_LOCAL_PATH}")
+ add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine)
+
+ # Resolve the local path to an absolute path for copying files later
+ get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE)
+ else()
+ # Fetch WeirdEngine from GitHub
+ message(STATUS "Using online version of WeirdEngine")
+ set(WEIRD_ENGINE_GIT_REF "main")
+
+ include(FetchContent)
+ FetchContent_Declare(
+ WeirdEngine
+ GIT_REPOSITORY https://github.com/damacaa/weird-engine
+ GIT_TAG ${WEIRD_ENGINE_GIT_REF}
+ )
+ FetchContent_MakeAvailable(WeirdEngine)
+
+ # FetchContent defines _SOURCE_DIR (usually lowercase)
+ set(WEIRD_ENGINE_REAL_SOURCE "${weirdengine_SOURCE_DIR}")
+ endif()
+else()
+ # WeirdEngine already defined (built from root); resolve its source path
+ get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE)
endif()
# Glob source files and header files from the proper directories.
-file(GLOB_RECURSE WEIRDGAME_SOURCES "${CMAKE_SOURCE_DIR}/src/*.cpp")
+file(GLOB_RECURSE WEIRDGAME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
file(GLOB_RECURSE WEIRDGAME_HEADERS
- "${CMAKE_SOURCE_DIR}/include/*.h"
- "${CMAKE_SOURCE_DIR}/include/*.hpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp"
)
file(GLOB_RECURSE WEIRDGAME_ASSETS
- "${CMAKE_SOURCE_DIR}/assets/*.*"
+ "${CMAKE_CURRENT_SOURCE_DIR}/assets/*.*"
)
# Mark headers as header-only so that Visual Studio treats them appropriately.
@@ -47,48 +93,79 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU
# Add executable including both sources and headers.
add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS})
+if(BUILD_WEB)
+ set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html")
+endif()
+
# Set include directories.
-target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include)
-target_include_directories(${PROJECT_NAME} PRIVATE
- ${CMAKE_BINARY_DIR}/weird-engine/include
- ${CMAKE_BINARY_DIR}/weird-engine/third-party/include
-)
+target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
# Link to WeirdEngine.
target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine)
# Set Asset Path Macro
-# Define the assets path variable
-set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
-# set(ASSETS_PATH "./assets") # Set the asset path macro in release mode to a relative path that assumes the assets folder is in the same directory as the game executable
+if(DEPLOY_STANDALONE)
+ set(ASSETS_PATH "./assets/")
+else()
+ set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
+endif()
-# Print the assets path for debugging or confirmation
message(STATUS "Assets path: ${ASSETS_PATH}")
-
-# Use the variable in target_compile_definitions
target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${ASSETS_PATH}")
if (MINGW)
target_link_options(${PROJECT_NAME} PRIVATE -static -static-libgcc -static-libstdc++)
endif()
-# ----------------------------------------------------------
-# Helper function to assign source groups based on folder structure.
+# -------------------------------------------------------------------------
+# POST BUILD COMMANDS (DLLs + Assets + Fonts + Shaders)
+# -------------------------------------------------------------------------
+if(DEPLOY_STANDALONE)
+ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ # 1. Copy Project ASSETS folder -> Build/assets
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${CMAKE_CURRENT_SOURCE_DIR}/assets"
+ "$/assets"
+
+ # 2. Copy WeirdEngine FONTS -> Build/fonts
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts"
+ "$/fonts"
+
+ # 3. Copy WeirdEngine SHADERS -> Build/shaders
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders"
+ "$/shaders"
+
+ COMMENT "Copying Game Assets, Engine Fonts, and Engine Shaders"
+ )
+
+ if(BUILD_WEB)
+ # For web builds, copy index.html if it exists
+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html")
+ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html"
+ "$/index.html"
+ COMMENT "Copying index.html for web build"
+ )
+ endif()
+ endif()
+endif()
+
+# -------------------------------------------------------------------------
+# SOURCE GROUPS
+# -------------------------------------------------------------------------
function(assign_source_groups TARGET)
foreach(source_file IN LISTS ARGN)
- # Get the full path to the file's directory.
get_filename_component(FILE_PATH "${source_file}" PATH)
- # Compute the path relative to the project's root.
- file(RELATIVE_PATH REL_PATH "${CMAKE_SOURCE_DIR}" "${FILE_PATH}")
- # Replace forward slashes with backslashes for Visual Studio filter naming.
+ file(RELATIVE_PATH REL_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${FILE_PATH}")
string(REPLACE "/" "\\" FILTER_PATH "${REL_PATH}")
if(FILTER_PATH STREQUAL "")
set(FILTER_PATH "Root")
endif()
- # Assign the file to the computed filter.
source_group("${FILTER_PATH}" FILES "${source_file}")
endforeach()
endfunction()
-# Assign source groups for all your files.
assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS})
diff --git a/examples/empty-project/src/index.html b/examples/empty-project/src/index.html
new file mode 100644
index 00000000..a02843cd
--- /dev/null
+++ b/examples/empty-project/src/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+ WeirdGame
+
+
+
+
+
+
+
+
+
diff --git a/examples/empty-project/src/main.cpp b/examples/empty-project/src/main.cpp
index 5b16b84f..e76cab1e 100644
--- a/examples/empty-project/src/main.cpp
+++ b/examples/empty-project/src/main.cpp
@@ -13,9 +13,7 @@ class EmptyScene : public Scene2D
}
private:
- void onStart() override
- {
- }
+ void onStart() override {}
void onUpdate(float delta) override {}
void onCreate() override {}
diff --git a/examples/opengl-experiments/CMakeLists.txt b/examples/opengl-experiments/CMakeLists.txt
index 606a485a..96079282 100644
--- a/examples/opengl-experiments/CMakeLists.txt
+++ b/examples/opengl-experiments/CMakeLists.txt
@@ -1,36 +1,80 @@
cmake_minimum_required(VERSION 3.10)
+
+# ==============================================================================
+# 1. Project Configuration
+# ==============================================================================
project(OpenGLExperiments)
+# Path to the WeirdEngine directory. Change this depending on where your project is located.
+# Examples inside weird-engine use "../../"
+# External projects usually use "../weird-engine/" or similar.
+set(WEIRD_ENGINE_LOCAL_PATH "../../")
+# ==============================================================================
+
# Create folders if they don't exist
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src")
-set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF) # Ensure strictly standard C++
# Option to switch between local and online version of WeirdEngine
option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON)
-# Set paths for the local WeirdEngine
-set(WEIRD_ENGINE_LOCAL_PATH "../../")
+# Option to build for web (Emscripten)
+option(BUILD_WEB "Build for web using Emscripten" OFF)
+
+# Option to build for standalone deployment
+option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF)
+
+# Auto-detect Emscripten toolchain or explicit BUILD_WEB flag
+if(EMSCRIPTEN OR BUILD_WEB)
+ set(BUILD_WEB ON CACHE BOOL "" FORCE)
+ set(BUILD_WEB ON)
+ set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE)
+ set(DEPLOY_STANDALONE ON)
+endif()
+
+if(DEPLOY_STANDALONE)
+ message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.")
+ # Force the engine to expect runtime assets
+ set(WEIRD_ENGINE_USE_RUNTIME_ASSETS ON CACHE BOOL "" FORCE)
+else()
+ message(STATUS ">> DEV MODE: Assets read directly from source folder.")
+endif()
+# -------------------------------------------------------------------------
+# INCLUDE ENGINE & CAPTURE SOURCE PATH
+# -------------------------------------------------------------------------
if(NOT TARGET WeirdEngine)
if(USE_LOCAL_WEIRD_ENGINE)
# Use the local version of WeirdEngine
- message(STATUS "Using local version of WeirdEngine")
+ message(STATUS "Using local version of WeirdEngine at ${WEIRD_ENGINE_LOCAL_PATH}")
add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine)
+
+ # Resolve the local path to an absolute path for copying files later
+ get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE)
else()
# Fetch WeirdEngine from GitHub
message(STATUS "Using online version of WeirdEngine")
+ set(WEIRD_ENGINE_GIT_REF "main")
+
include(FetchContent)
FetchContent_Declare(
WeirdEngine
GIT_REPOSITORY https://github.com/damacaa/weird-engine
- GIT_TAG main
+ GIT_TAG ${WEIRD_ENGINE_GIT_REF}
)
FetchContent_MakeAvailable(WeirdEngine)
+
+ # FetchContent defines _SOURCE_DIR (usually lowercase)
+ set(WEIRD_ENGINE_REAL_SOURCE "${weirdengine_SOURCE_DIR}")
endif()
+else()
+ # WeirdEngine already defined (built from root); resolve its source path
+ get_filename_component(WEIRD_ENGINE_REAL_SOURCE "${WEIRD_ENGINE_LOCAL_PATH}" ABSOLUTE)
endif()
# Glob source files and header files from the proper directories.
@@ -49,48 +93,79 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU
# Add executable including both sources and headers.
add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS})
+if(BUILD_WEB)
+ set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html")
+endif()
+
# Set include directories.
-target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
-target_include_directories(${PROJECT_NAME} PRIVATE
- ${CMAKE_BINARY_DIR}/weird-engine/include
- ${CMAKE_BINARY_DIR}/weird-engine/third-party/include
-)
+target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
# Link to WeirdEngine.
target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine)
# Set Asset Path Macro
-# Define the assets path variable
-set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
-# set(ASSETS_PATH "./assets") # Set the asset path macro in release mode to a relative path that assumes the assets folder is in the same directory as the game executable
+if(DEPLOY_STANDALONE)
+ set(ASSETS_PATH "./assets/")
+else()
+ set(ASSETS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
+endif()
-# Print the assets path for debugging or confirmation
message(STATUS "Assets path: ${ASSETS_PATH}")
-
-# Use the variable in target_compile_definitions
target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${ASSETS_PATH}")
if (MINGW)
target_link_options(${PROJECT_NAME} PRIVATE -static -static-libgcc -static-libstdc++)
endif()
-# ----------------------------------------------------------
-# Helper function to assign source groups based on folder structure.
+# -------------------------------------------------------------------------
+# POST BUILD COMMANDS (DLLs + Assets + Fonts + Shaders)
+# -------------------------------------------------------------------------
+if(DEPLOY_STANDALONE)
+ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ # 1. Copy Project ASSETS folder -> Build/assets
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${CMAKE_CURRENT_SOURCE_DIR}/assets"
+ "$/assets"
+
+ # 2. Copy WeirdEngine FONTS -> Build/fonts
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts"
+ "$/fonts"
+
+ # 3. Copy WeirdEngine SHADERS -> Build/shaders
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders"
+ "$/shaders"
+
+ COMMENT "Copying Game Assets, Engine Fonts, and Engine Shaders"
+ )
+
+ if(BUILD_WEB)
+ # For web builds, copy index.html if it exists
+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html")
+ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html"
+ "$/index.html"
+ COMMENT "Copying index.html for web build"
+ )
+ endif()
+ endif()
+endif()
+
+# -------------------------------------------------------------------------
+# SOURCE GROUPS
+# -------------------------------------------------------------------------
function(assign_source_groups TARGET)
foreach(source_file IN LISTS ARGN)
- # Get the full path to the file's directory.
get_filename_component(FILE_PATH "${source_file}" PATH)
- # Compute the path relative to the project's root.
file(RELATIVE_PATH REL_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${FILE_PATH}")
- # Replace forward slashes with backslashes for Visual Studio filter naming.
string(REPLACE "/" "\\" FILTER_PATH "${REL_PATH}")
if(FILTER_PATH STREQUAL "")
set(FILTER_PATH "Root")
endif()
- # Assign the file to the computed filter.
source_group("${FILTER_PATH}" FILES "${source_file}")
endforeach()
endfunction()
-# Assign source groups for all your files.
assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS})
diff --git a/examples/opengl-experiments/assets/fire/shaders/fireParticles.vert b/examples/opengl-experiments/assets/fire/shaders/fireParticles.vert
index dc2dd66e..c94201c8 100644
--- a/examples/opengl-experiments/assets/fire/shaders/fireParticles.vert
+++ b/examples/opengl-experiments/assets/fire/shaders/fireParticles.vert
@@ -35,10 +35,10 @@ void main()
float maxHeight = 1.5 + (fract(instanceId * 123.45678) - 0.5); // Constant + random offset
float y = plateauFunction(2.0 * delta, maxHeight, 0.8);
- float distanceToCenterXZ = 0.1 + (0.3 * smoothstep(0.0, 1.0, sqrt(1.5 * delta))); // TODO: find an alternative to sqrt
+ float distanceToCenterXZ =
+ 0.1 + (0.3 * smoothstep(0.0, 1.0, sqrt(1.5 * delta))); // TODO: find an alternative to sqrt
- vec3 offset =
- vec3(distanceToCenterXZ * sin(u_time + instanceId), y, distanceToCenterXZ * cos(u_time + instanceId));
+ vec3 offset = vec3(distanceToCenterXZ * sin(u_time + instanceId), y, distanceToCenterXZ * cos(u_time + instanceId));
v_worldPos = vec3(u_model * vec4(2.0 * (1.0 - delta * delta) * in_position, 1.0)) + offset;
v_normal = u_normalMatrix * in_normal;
diff --git a/examples/opengl-experiments/assets/fire/shaders/flame.frag b/examples/opengl-experiments/assets/fire/shaders/flame.frag
index 7da2fa70..8931871d 100644
--- a/examples/opengl-experiments/assets/fire/shaders/flame.frag
+++ b/examples/opengl-experiments/assets/fire/shaders/flame.frag
@@ -17,9 +17,9 @@ uniform sampler2D t_flameShape;
const int NUM_STOPS = 4;
const vec3 colors[NUM_STOPS] = vec3[](vec3(0.1, 0.1, 0.1), // Grey
- vec3(0.8, 0.3, 0.2), // Red
- vec3(1.1, 0.7, 0.2), // Orange
- vec3(1.2, 1.2, 1.2) // White
+ vec3(0.8, 0.3, 0.2), // Red
+ vec3(1.1, 0.7, 0.2), // Orange
+ vec3(1.2, 1.2, 1.2) // White
);
const float stops[NUM_STOPS] = float[](0.0, 0.7, 0.9, 1.0);
diff --git a/examples/opengl-experiments/assets/lines/combination.frag b/examples/opengl-experiments/assets/lines/combination.frag
index 296ada61..f94e1bfc 100644
--- a/examples/opengl-experiments/assets/lines/combination.frag
+++ b/examples/opengl-experiments/assets/lines/combination.frag
@@ -12,9 +12,9 @@ uniform sampler2D t_lines;
const int NUM_STOPS = 4;
const vec3 colors[NUM_STOPS] = vec3[](vec3(0.82, 0.74, 0.88), // Muted lavender
- vec3(0.78, 0.94, 0.76), // Pale pistachio
- vec3(0.98, 0.85, 0.72), // Dusty pastel orange
- vec3(0.68, 0.96, 0.95) // Soft cyan mist
+ vec3(0.78, 0.94, 0.76), // Pale pistachio
+ vec3(0.98, 0.85, 0.72), // Dusty pastel orange
+ vec3(0.68, 0.96, 0.95) // Soft cyan mist
);
const float stops[NUM_STOPS] = float[](0.0, 0.33, 0.66, 1.0);
diff --git a/examples/opengl-experiments/assets/water/shaders/water.frag b/examples/opengl-experiments/assets/water/shaders/water.frag
index 5da45fba..8861958b 100644
--- a/examples/opengl-experiments/assets/water/shaders/water.frag
+++ b/examples/opengl-experiments/assets/water/shaders/water.frag
@@ -10,41 +10,40 @@ in vec3 v_normal;
in vec3 v_color;
in vec2 v_texCoord;
-uniform vec3 u_camPos;
+uniform vec3 u_camPos;
uniform float u_time;
// Screen-space scene snapshot (taken before this draw call)
uniform sampler2D u_sceneColor;
uniform sampler2D u_sceneDepth;
-uniform vec2 u_screenSize;
+uniform vec2 u_screenSize;
// Light array – same layout as sdf_raymarching.frag
struct Light
{
vec3 position;
vec3 direction;
- vec4 color; // .rgb = tint, .a = intensity
- int type; // 0 = directional, 1 = point, 2 = spot/cone
+ vec4 color; // .rgb = tint, .a = intensity
+ int type; // 0 = directional, 1 = point, 2 = spot/cone
};
#define MAX_LIGHTS 8
-uniform int u_numLights;
+uniform int u_numLights;
uniform Light u_lights[MAX_LIGHTS];
// Water material
-const vec3 u_shallowColor = vec3(0.05, 0.35, 0.55);
-const vec3 u_deepColor = vec3(0.01, 0.10, 0.25);
-const float u_metallic = 0.02; // F0 for water (Fresnel base ~2%)
-const float u_fresnelPower = 5.0;
-const float u_specExponent = 512.0;
-const float u_absorptionRate = 2.0; // light absorbed per world-unit of depth
-const float u_foamBand = 0.25; // max foam band width (world units)
+const vec3 u_shallowColor = vec3(0.05, 0.35, 0.55);
+const vec3 u_deepColor = vec3(0.01, 0.10, 0.25);
+const float u_metallic = 0.02; // F0 for water (Fresnel base ~2%)
+const float u_fresnelPower = 5.0;
+const float u_specExponent = 512.0;
+const float u_absorptionRate = 2.0; // light absorbed per world-unit of depth
+const float u_foamBand = 0.25; // max foam band width (world units)
// ── Perlin noise ─────────────────────────────────────────────────────────────
vec2 _hash22(vec2 p)
{
- p = vec2(dot(p, vec2(127.1, 311.7)),
- dot(p, vec2(269.5, 183.3)));
+ p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));
return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);
}
@@ -53,18 +52,23 @@ float _perlin(vec2 p)
vec2 i = floor(p);
vec2 f = fract(p);
vec2 u = f * f * (3.0 - 2.0 * f); // Hermite smoothstep
- return mix(
- mix(dot(_hash22(i + vec2(0.0, 0.0)), f - vec2(0.0, 0.0)),
- dot(_hash22(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0)), u.x),
- mix(dot(_hash22(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0)),
- dot(_hash22(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0)), u.x), u.y);
+ return mix(mix(dot(_hash22(i + vec2(0.0, 0.0)), f - vec2(0.0, 0.0)),
+ dot(_hash22(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0)), u.x),
+ mix(dot(_hash22(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0)),
+ dot(_hash22(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0)), u.x),
+ u.y);
}
// Fractal Brownian Motion – returns [0, 1]
float fbm(vec2 p)
{
float v = 0.0, a = 0.5, s = 1.0;
- for (int i = 0; i < 4; i++) { v += a * _perlin(p * s); s *= 2.1; a *= 0.5; }
+ for (int i = 0; i < 4; i++)
+ {
+ v += a * _perlin(p * s);
+ s *= 2.1;
+ a *= 0.5;
+ }
return v * 0.5 + 0.5;
}
@@ -84,10 +88,10 @@ float linearizeDepth(float d)
vec3 getSkyColor(vec3 dir)
{
- float t = max(dir.y, 0.0);
- vec3 zenithColor = vec3(0.05, 0.25, 0.7);
- vec3 horizonColor = vec3(0.5, 0.6, 0.7);
- vec3 groundColor = vec3(0.1, 0.1, 0.12);
+ float t = max(dir.y, 0.0);
+ vec3 zenithColor = vec3(0.05, 0.25, 0.7);
+ vec3 horizonColor = vec3(0.5, 0.6, 0.7);
+ vec3 groundColor = vec3(0.1, 0.1, 0.12);
vec3 sky = mix(horizonColor, zenithColor, pow(t, 0.4));
if (dir.y < 0.0)
@@ -99,7 +103,7 @@ vec3 getSkyColor(vec3 dir)
{
float sun = max(dot(dir, normalize(u_lights[i].direction)), 0.0);
sky += vec3(1.0, 0.85, 0.6) * pow(sun, 4000.0) * 2.0;
- sky += vec3(1.0, 0.6, 0.2) * pow(sun, 200.0) * 0.4;
+ sky += vec3(1.0, 0.6, 0.2) * pow(sun, 200.0) * 0.4;
sky *= u_lights[i].color.w > 0.0 ? 1.0 : 0.0;
}
}
@@ -110,8 +114,8 @@ vec3 getSkyColor(vec3 dir)
vec3 surfaceLighting(vec3 p, vec3 rd, vec3 albedo, vec3 N)
{
- vec3 V = -rd;
- float f0 = u_metallic;
+ vec3 V = -rd;
+ float f0 = u_metallic;
float fresnel = f0 + (1.0 - f0) * pow(clamp(1.0 - dot(V, N), 0.0, 1.0), u_fresnelPower);
vec3 directLighting = vec3(0.0);
@@ -119,7 +123,7 @@ vec3 surfaceLighting(vec3 p, vec3 rd, vec3 albedo, vec3 N)
for (int i = 0; i < u_numLights; i++)
{
Light light = u_lights[i];
- vec3 L;
+ vec3 L;
float attenuation = 1.0;
if (light.type == 0)
@@ -128,32 +132,31 @@ vec3 surfaceLighting(vec3 p, vec3 rd, vec3 albedo, vec3 N)
}
else if (light.type == 1)
{
- vec3 lv = light.position - p;
+ vec3 lv = light.position - p;
float dist = length(lv);
- L = normalize(lv);
+ L = normalize(lv);
attenuation = 10.0 / (3.0 * dist * dist + 0.7 * dist + 1.0);
}
else
{
- vec3 lv = light.position - p;
+ vec3 lv = light.position - p;
float dist = length(lv);
- L = normalize(lv);
+ L = normalize(lv);
attenuation = 10.0 / (3.0 * dist * dist + 0.7 * dist + 1.0);
- attenuation *= smoothstep(0.80, 0.95,
- dot(normalize(lv), normalize(light.direction)));
+ attenuation *= smoothstep(0.80, 0.95, dot(normalize(lv), normalize(light.direction)));
}
- vec3 diffuse = albedo * max(dot(N, L), 0.0) * (1.0 - fresnel);
- vec3 H = normalize(L + V);
- float specPow = pow(max(dot(N, H), 0.0), u_specExponent);
- vec3 specular = vec3(5.0) * specPow * fresnel;
+ vec3 diffuse = albedo * max(dot(N, L), 0.0) * (1.0 - fresnel);
+ vec3 H = normalize(L + V);
+ float specPow = pow(max(dot(N, H), 0.0), u_specExponent);
+ vec3 specular = vec3(5.0) * specPow * fresnel;
directLighting += (diffuse + specular) * attenuation * light.color.rgb * light.color.a;
}
- vec3 R = reflect(rd, N);
+ vec3 R = reflect(rd, N);
vec3 reflectionColor = getSkyColor(R);
- vec3 ambient = albedo * 0.1 + reflectionColor * fresnel;
+ vec3 ambient = albedo * 0.1 + reflectionColor * fresnel;
return directLighting + ambient;
}
@@ -162,14 +165,14 @@ vec3 surfaceLighting(vec3 p, vec3 rd, vec3 albedo, vec3 N)
void main()
{
- vec3 N = normalize(v_normal);
- vec3 rd = normalize(v_worldPos - u_camPos);
+ vec3 N = normalize(v_normal);
+ vec3 rd = normalize(v_worldPos - u_camPos);
vec2 screenUV = gl_FragCoord.xy / u_screenSize;
// ── Sample scene depth and compute underwater depth ───────────────────────
- float rawDepth = texture(u_sceneDepth, screenUV).r;
- bool hasGeom = rawDepth < 0.9999; // false = sky / far-plane background
+ float rawDepth = texture(u_sceneDepth, screenUV).r;
+ bool hasGeom = rawDepth < 0.9999; // false = sky / far-plane background
// Linear depth avoids the banding caused by perspective non-linearity in
// the depth buffer; the difference is the actual view-space distance
@@ -188,7 +191,7 @@ void main()
sceneColor = texture(u_sceneColor, refractUV).rgb;
// Exponential light absorption: deeper objects are tinted toward deep water colour
float absorption = exp(-underwaterDepth * u_absorptionRate);
- sceneColor = mix(u_deepColor * 0.3, sceneColor, absorption);
+ sceneColor = mix(u_deepColor * 0.3, sceneColor, absorption);
}
else
{
@@ -196,18 +199,18 @@ void main()
// so distant views through the water look naturally blue rather than showing
// the opaque background colour baked into the scene snapshot.
vec3 refractDir = refract(rd, N, 1.0 / 1.33); // water IOR ≈ 1.33
- sceneColor = getSkyColor(refractDir);
+ sceneColor = getSkyColor(refractDir);
}
// ── Water surface colour ─────────────────────────────────────────────────
- float depthFactor = clamp(abs(v_worldPos.y) * 2.0, 0.0, 1.0);
- vec3 waterAlbedo = mix(u_shallowColor, u_deepColor, depthFactor);
- vec3 surfaceColor = surfaceLighting(v_worldPos, rd, waterAlbedo, N);
+ float depthFactor = clamp(abs(v_worldPos.y) * 2.0, 0.0, 1.0);
+ vec3 waterAlbedo = mix(u_shallowColor, u_deepColor, depthFactor);
+ vec3 surfaceColor = surfaceLighting(v_worldPos, rd, waterAlbedo, N);
// Fresnel: grazing angles are near-fully reflective; normal incidence is mostly transparent
- float f0 = u_metallic;
+ float f0 = u_metallic;
float fresnel = f0 + (1.0 - f0) * pow(clamp(1.0 - dot(-rd, N), 0.0, 1.0), u_fresnelPower);
- float alpha = mix(0.4, 1.0, fresnel); // [0.4 .. 1.0]
+ float alpha = mix(0.4, 1.0, fresnel); // [0.4 .. 1.0]
// ── Composite: water surface over (absorbed) scene colour ────────────────
vec3 finalColor = mix(sceneColor, surfaceColor, alpha);
@@ -221,13 +224,12 @@ void main()
// float foam = 1.0 - smoothstep(0.0, bandMax, underwaterDepth);
// foam *= smoothstep(-0.2, 0.04, underwaterDepth); // fade above surface
-
// vec3 foamColor = vec3(1.0);
// finalColor = mix(finalColor, foamColor, foam);
// }
- //finalColor = vec3((sceneLinearZ) - 2.5);
- // finalColor = vec3(underwaterDepth);
+ // finalColor = vec3((sceneLinearZ) - 2.5);
+ // finalColor = vec3(underwaterDepth);
// Output fully opaque – compositing was done manually above
FragColor = vec4(finalColor, 1.0);
diff --git a/examples/opengl-experiments/assets/water/shaders/water.vert b/examples/opengl-experiments/assets/water/shaders/water.vert
index 9ed2410c..db420669 100644
--- a/examples/opengl-experiments/assets/water/shaders/water.vert
+++ b/examples/opengl-experiments/assets/water/shaders/water.vert
@@ -13,8 +13,8 @@ out vec3 v_color;
out vec2 v_texCoord;
// Uniforms
-uniform mat4 u_model;
-uniform mat4 u_camMatrix;
+uniform mat4 u_model;
+uniform mat4 u_camMatrix;
uniform float u_time;
// ── Gerstner wave ─────────────────────────────────────────────────────────────
@@ -29,16 +29,16 @@ uniform float u_time;
struct GerstnerOut
{
- vec3 displacement; // vertex offset (x, y, z)
- vec3 dPos_dx; // ∂P/∂x – used to build the normal
- vec3 dPos_dz; // ∂P/∂z
+ vec3 displacement; // vertex offset (x, y, z)
+ vec3 dPos_dx; // ∂P/∂x – used to build the normal
+ vec3 dPos_dz; // ∂P/∂z
};
GerstnerOut gerstner(vec2 xz, vec2 dir, float wavelength, float amplitude, float steepness)
{
- float k = 6.28318 / wavelength; // wavenumber
- float c = sqrt(9.81 / k); // deep-water phase speed
- float f = k * dot(dir, xz) - c * u_time;
+ float k = 6.28318 / wavelength; // wavenumber
+ float c = sqrt(9.81 / k); // deep-water phase speed
+ float f = k * dot(dir, xz) - c * u_time;
float sinF = sin(f);
float cosF = cos(f);
@@ -46,30 +46,23 @@ GerstnerOut gerstner(vec2 xz, vec2 dir, float wavelength, float amplitude, float
float Q = steepness;
GerstnerOut o;
- o.displacement = vec3(
- Q * amplitude * dir.x * cosF,
- amplitude * sinF,
- Q * amplitude * dir.y * cosF
- );
+ o.displacement = vec3(Q * amplitude * dir.x * cosF, amplitude * sinF, Q * amplitude * dir.y * cosF);
// Partial derivatives of the displaced position (for normal computation)
float WA = k * amplitude;
- o.dPos_dx = vec3(
- -Q * WA * dir.x * dir.x * sinF,
- WA * dir.x * cosF,
- -Q * WA * dir.x * dir.y * sinF
- );
- o.dPos_dz = vec3(
- -Q * WA * dir.x * dir.y * sinF,
- WA * dir.y * cosF,
- -Q * WA * dir.y * dir.y * sinF
- );
+ o.dPos_dx = vec3(-Q * WA * dir.x * dir.x * sinF, WA * dir.x * cosF, -Q * WA * dir.x * dir.y * sinF);
+ o.dPos_dz = vec3(-Q * WA * dir.x * dir.y * sinF, WA * dir.y * cosF, -Q * WA * dir.y * dir.y * sinF);
return o;
}
// ── Rotate a 2-D point ────────────────────────────────────────────────────────
-vec2 rot2(vec2 p, float a) { float c = cos(a); float s = sin(a); return vec2(c*p.x - s*p.y, s*p.x + c*p.y); }
+vec2 rot2(vec2 p, float a)
+{
+ float c = cos(a);
+ float s = sin(a);
+ return vec2(c * p.x - s * p.y, s * p.x + c * p.y);
+}
void main()
{
@@ -79,55 +72,66 @@ void main()
// Use six sinusoids whose spatial periods have no common rational factor.
// Frequencies chosen as prime-like irrational multiples so the warp pattern
// never tiles at any human-visible scale.
- float t = u_time;
+ float t = u_time;
vec2 warp = vec2(
- sin(xz.x * 0.1731 + xz.y * 0.0893 + t * 0.071) * 1.6
- + cos(xz.x * 0.2473 - xz.y * 0.1337 + t * 0.043) * 0.9,
- cos(xz.x * 0.0971 + xz.y * 0.2011 + t * 0.059) * 1.4
- + sin(xz.x * 0.1619 - xz.y * 0.3001 + t * 0.037) * 0.7
- );
+ sin(xz.x * 0.1731 + xz.y * 0.0893 + t * 0.071) * 1.6 + cos(xz.x * 0.2473 - xz.y * 0.1337 + t * 0.043) * 0.9,
+ cos(xz.x * 0.0971 + xz.y * 0.2011 + t * 0.059) * 1.4 + sin(xz.x * 0.1619 - xz.y * 0.3001 + t * 0.037) * 0.7);
vec2 xzW = xz + warp;
// ── Wave cascade A – primary swell direction ──────────────────────────────
- vec3 totalDisp = vec3(0.0);
+ vec3 totalDisp = vec3(0.0);
vec3 total_dpdx = vec3(1.0, 0.0, 0.0);
vec3 total_dpdz = vec3(0.0, 0.0, 1.0);
- GerstnerOut g0 = gerstner(xzW, normalize(vec2( 1.0, 0.4)), 8.09, 0.110, 0.55);
- totalDisp += g0.displacement; total_dpdx += g0.dPos_dx; total_dpdz += g0.dPos_dz;
+ GerstnerOut g0 = gerstner(xzW, normalize(vec2(1.0, 0.4)), 8.09, 0.110, 0.55);
+ totalDisp += g0.displacement;
+ total_dpdx += g0.dPos_dx;
+ total_dpdz += g0.dPos_dz;
- GerstnerOut g1 = gerstner(xzW, normalize(vec2(-0.5, 1.0)), 5.00, 0.075, 0.45);
- totalDisp += g1.displacement; total_dpdx += g1.dPos_dx; total_dpdz += g1.dPos_dz;
+ GerstnerOut g1 = gerstner(xzW, normalize(vec2(-0.5, 1.0)), 5.00, 0.075, 0.45);
+ totalDisp += g1.displacement;
+ total_dpdx += g1.dPos_dx;
+ total_dpdz += g1.dPos_dz;
- GerstnerOut g2 = gerstner(xzW, normalize(vec2( 0.4, -1.0)), 3.09, 0.040, 0.30);
- totalDisp += g2.displacement; total_dpdx += g2.dPos_dx; total_dpdz += g2.dPos_dz;
+ GerstnerOut g2 = gerstner(xzW, normalize(vec2(0.4, -1.0)), 3.09, 0.040, 0.30);
+ totalDisp += g2.displacement;
+ total_dpdx += g2.dPos_dx;
+ total_dpdz += g2.dPos_dz;
// ── Wave cascade B – evaluated in a rotated frame ─────────────────────────
// Rotation by sqrt(2) radians ≈ 81.03° – irrational, so cascade B can never
// constructively align with cascade A at any finite scale.
vec2 xzR = rot2(xzW, 1.41421356);
- GerstnerOut g3 = gerstner(xzR, normalize(vec2( 1.0, 0.3)), 4.72, 0.055, 0.40);
- totalDisp += g3.displacement; total_dpdx += g3.dPos_dx; total_dpdz += g3.dPos_dz;
+ GerstnerOut g3 = gerstner(xzR, normalize(vec2(1.0, 0.3)), 4.72, 0.055, 0.40);
+ totalDisp += g3.displacement;
+ total_dpdx += g3.dPos_dx;
+ total_dpdz += g3.dPos_dz;
- GerstnerOut g4 = gerstner(xzR, normalize(vec2(-0.7, 1.0)), 2.62, 0.030, 0.28);
- totalDisp += g4.displacement; total_dpdx += g4.dPos_dx; total_dpdz += g4.dPos_dz;
+ GerstnerOut g4 = gerstner(xzR, normalize(vec2(-0.7, 1.0)), 2.62, 0.030, 0.28);
+ totalDisp += g4.displacement;
+ total_dpdx += g4.dPos_dx;
+ total_dpdz += g4.dPos_dz;
xzR = rot2(xzW, 2.123457);
- GerstnerOut g5 = gerstner(xzR, normalize(vec2( 0.9, -0.6)), 1.62, 0.015, 0.18);
- totalDisp += g5.displacement; total_dpdx += g5.dPos_dx; total_dpdz += g5.dPos_dz;
+ GerstnerOut g5 = gerstner(xzR, normalize(vec2(0.9, -0.6)), 1.62, 0.015, 0.18);
+ totalDisp += g5.displacement;
+ total_dpdx += g5.dPos_dx;
+ total_dpdz += g5.dPos_dz;
- GerstnerOut g6 = gerstner(xzR, normalize(vec2(-1.0, -0.3)), 1.00, 0.008, 0.12);
- totalDisp += g6.displacement; total_dpdx += g6.dPos_dx; total_dpdz += g6.dPos_dz;
+ GerstnerOut g6 = gerstner(xzR, normalize(vec2(-1.0, -0.3)), 1.00, 0.008, 0.12);
+ totalDisp += g6.displacement;
+ total_dpdx += g6.dPos_dx;
+ total_dpdz += g6.dPos_dz;
vec3 pos = in_position + totalDisp;
vec3 waveNormal = normalize(cross(total_dpdz, total_dpdx));
v_worldPos = vec3(u_model * vec4(pos, 1.0));
- v_normal = waveNormal;
- v_color = in_color;
+ v_normal = waveNormal;
+ v_color = in_color;
v_texCoord = in_texCoord;
gl_Position = u_camMatrix * vec4(v_worldPos, 1.0);
diff --git a/examples/opengl-experiments/include/Fire.h b/examples/opengl-experiments/include/Fire.h
index 1fbd6aac..96dc2803 100644
--- a/examples/opengl-experiments/include/Fire.h
+++ b/examples/opengl-experiments/include/Fire.h
@@ -6,7 +6,7 @@ using namespace WeirdEngine;
class FireScene : public Scene3D
{
public:
- FireScene(){};
+ FireScene() {};
private:
Shader m_flameShader;
@@ -58,12 +58,9 @@ class FireScene : public Scene3D
m_heatDistortionShader =
Shader(SHADERS_PATH "3d/geometry.vert", ASSETS_PATH "fire/shaders/heatDistortion.frag");
+ getLigths().push_back(Light{0, glm::vec3(0.0f), 0, glm::vec3(0.0f), glm::vec4(0.0f)});
getLigths().push_back(
- Light{0, glm::vec3(0.0f), 0, glm::vec3(0.0f), glm::vec4(0.0f)}
- );
- getLigths().push_back(
- Light{1, glm::vec3(0.0f, 1.0f, 0.0f), 0, glm::vec3(0.0f), glm::vec4(1.0f, 0.95f, 0.9f, 2.0f)}
- );
+ Light{1, glm::vec3(0.0f, 1.0f, 0.0f), 0, glm::vec3(0.0f), glm::vec4(1.0f, 0.95f, 0.9f, 2.0f)});
// Load meshes
// Quad geom
@@ -309,7 +306,7 @@ class FireScene : public Scene3D
m_renderPlane.draw(m_backgroundShader);
-glEnable(GL_DEPTH_TEST);
+ glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
// Render stuff
diff --git a/examples/opengl-experiments/include/Lines.h b/examples/opengl-experiments/include/Lines.h
index 3cf82d7f..b4ce3e7c 100644
--- a/examples/opengl-experiments/include/Lines.h
+++ b/examples/opengl-experiments/include/Lines.h
@@ -8,7 +8,7 @@ using namespace WeirdEngine;
class LinesScene : public Scene3D
{
public:
- LinesScene(){};
+ LinesScene() {};
private:
uint16_t m_whiteMatId;
@@ -26,7 +26,7 @@ class LinesScene : public Scene3D
void onCreate() override
{
-
+
{
auto& whiteMat = createMaterial();
m_whiteMatId = whiteMat.id;
@@ -47,8 +47,7 @@ class LinesScene : public Scene3D
m_lineTexture = new Texture(Display::rWidth, Display::rHeight, Texture::TextureType::Data);
m_lineRender->bindColorTextureToFrameBuffer(*m_lineTexture);
- m_combinationShader =
- new Shader(SHADERS_PATH "common/screen_plane.vert", ASSETS_PATH "lines/combination.frag");
+ m_combinationShader = new Shader(SHADERS_PATH "common/screen_plane.vert", ASSETS_PATH "lines/combination.frag");
}
// Inherited via Scene
diff --git a/examples/opengl-experiments/include/Water.h b/examples/opengl-experiments/include/Water.h
index f77de2e3..781cfddf 100644
--- a/examples/opengl-experiments/include/Water.h
+++ b/examples/opengl-experiments/include/Water.h
@@ -1,14 +1,14 @@
#pragma once
-#include
#include "WaterPlane.h"
+#include
using namespace WeirdEngine;
class WaterScene : public Scene3D
{
public:
- WaterScene(){};
+ WaterScene() {};
private:
Shader m_waterShader;
@@ -18,10 +18,10 @@ class WaterScene : public Scene3D
// Scene snapshot – taken each frame before the water draw to avoid
// reading from and writing to the same framebuffer attachment.
RenderTarget m_snapshotRender;
- Texture m_snapshotColor;
- Texture m_snapshotDepth;
- int m_snapshotW = 0;
- int m_snapshotH = 0;
+ Texture m_snapshotColor;
+ Texture m_snapshotDepth;
+ int m_snapshotW = 0;
+ int m_snapshotH = 0;
WaterPlane m_waterPlane;
@@ -33,8 +33,8 @@ class WaterScene : public Scene3D
m_snapshotColor.dispose();
m_snapshotDepth.dispose();
}
- m_snapshotColor = Texture(w, h, Texture::TextureType::Data);
- m_snapshotDepth = Texture(w, h, Texture::TextureType::Depth);
+ m_snapshotColor = Texture(w, h, Texture::TextureType::Data);
+ m_snapshotDepth = Texture(w, h, Texture::TextureType::Depth);
m_snapshotRender = RenderTarget(false);
m_snapshotRender.bindColorTextureToFrameBuffer(m_snapshotColor);
m_snapshotRender.bindDepthTextureToFrameBuffer(m_snapshotDepth);
@@ -42,14 +42,12 @@ class WaterScene : public Scene3D
m_snapshotH = h;
}
-
// -------------------------------------------------------------------------
void onCreate() override
{
- m_waterShader = Shader(ASSETS_PATH "water/shaders/water.vert",
- ASSETS_PATH "water/shaders/water.frag");
+ m_waterShader = Shader(ASSETS_PATH "water/shaders/water.vert", ASSETS_PATH "water/shaders/water.frag");
getLigths().push_back(Light{0, glm::vec3(0.0f, 0.0f, 0.0f), 0, normalize(glm::vec3(0.0f, 0.4f, 1.0f)),
glm::vec4(1.0f, 1.0f, 1.0f, 0.5f)});
@@ -102,7 +100,7 @@ class WaterScene : public Scene3D
MeshRenderer& mr = ecs.addComponent(entity);
auto id = m_resourceManager.getMeshId(ASSETS_PATH "monkey/demo.gltf", entity, true);
mr.mesh = id;
-
+
ecs.addComponent(entity);
}
@@ -120,31 +118,28 @@ class WaterScene : public Scene3D
m_time += delta;
-
const auto& floatables = ecs.getComponentArray();
- for(int i = 0; i < floatables->getSize(); i++)
+ for (int i = 0; i < floatables->getSize(); i++)
{
auto& floatable = floatables->getDataAtIdx(i);
// Keep the dot riding the water surface
Transform& transform = ecs.getComponent(floatables->getEntityAtIdx(i));
- glm::vec2 flatPos = { transform.position.x, transform.position.z };
+ glm::vec2 flatPos = {transform.position.x, transform.position.z};
float centerHeight = m_waterPlane.waterHeightAt(flatPos, m_time);
transform.position.y = centerHeight;
// Derive surface normal via central finite difference, then drift along it
const float fdStep = 0.05f;
float heightPlusX = m_waterPlane.waterHeightAt(flatPos + glm::vec2(fdStep, 0.0f), m_time);
- float heightPlusZ = m_waterPlane.waterHeightAt(flatPos + glm::vec2(0.0f, fdStep), m_time);
+ float heightPlusZ = m_waterPlane.waterHeightAt(flatPos + glm::vec2(0.0f, fdStep), m_time);
- glm::vec3 surfaceNormal = glm::normalize(glm::vec3(heightPlusX - centerHeight, fdStep, heightPlusZ - centerHeight));
+ glm::vec3 surfaceNormal =
+ glm::normalize(glm::vec3(heightPlusX - centerHeight, fdStep, heightPlusZ - centerHeight));
transform.position.x += surfaceNormal.x * delta * floatable.buoyancy;
transform.position.z += surfaceNormal.z * delta * floatable.buoyancy;
}
-
-
-
}
void onRender(WeirdRenderer::RenderTarget& renderTarget) override
@@ -154,7 +149,6 @@ class WaterScene : public Scene3D
auto& lights = getLigths();
-
// ── Snapshot the current scene colour + depth ────────────────────────
// We need to read from these textures while drawing the water plane,
// so we must copy them to separate textures first to avoid a feedback loop.
@@ -180,28 +174,28 @@ class WaterScene : public Scene3D
glDisable(GL_BLEND);
m_waterShader.use();
- m_waterShader.setUniform("u_time", time);
- m_waterShader.setUniform("u_camPos", sceneCamera.position);
+ m_waterShader.setUniform("u_time", time);
+ m_waterShader.setUniform("u_camPos", sceneCamera.position);
m_waterShader.setUniform("u_camMatrix", sceneCamera.cameraMatrix);
- m_waterShader.setUniform("u_near", sceneCamera.nearPlane);
- m_waterShader.setUniform("u_far", sceneCamera.farPlane);
+ m_waterShader.setUniform("u_near", sceneCamera.nearPlane);
+ m_waterShader.setUniform("u_far", sceneCamera.farPlane);
// Scene snapshot textures for underwater effects
- m_waterShader.setUniform("u_sceneColor", 0);
+ m_waterShader.setUniform("u_sceneColor", 0);
m_snapshotColor.bind(0);
- m_waterShader.setUniform("u_sceneDepth", 1);
+ m_waterShader.setUniform("u_sceneDepth", 1);
m_snapshotDepth.bind(1);
- m_waterShader.setUniform("u_screenSize", glm::vec2((float)w, (float)h));
+ m_waterShader.setUniform("u_screenSize", glm::vec2((float)w, (float)h));
int numLights = (std::min)((int)lights.size(), 8);
m_waterShader.setUniform("u_numLights", numLights);
for (int i = 0; i < numLights; i++)
{
std::string prefix = "u_lights[" + std::to_string(i) + "].";
- m_waterShader.setUniform(prefix + "position", lights[i].position);
+ m_waterShader.setUniform(prefix + "position", lights[i].position);
m_waterShader.setUniform(prefix + "direction", lights[i].rotation);
- m_waterShader.setUniform(prefix + "color", lights[i].color);
- m_waterShader.setUniform(prefix + "type", (int)lights[i].type);
+ m_waterShader.setUniform(prefix + "color", lights[i].color);
+ m_waterShader.setUniform(prefix + "type", (int)lights[i].type);
}
glm::mat4 waterModel = glm::mat4(1.0f);
diff --git a/examples/opengl-experiments/include/WaterPlane.h b/examples/opengl-experiments/include/WaterPlane.h
index 256abda1..d9577d32 100644
--- a/examples/opengl-experiments/include/WaterPlane.h
+++ b/examples/opengl-experiments/include/WaterPlane.h
@@ -1,8 +1,8 @@
#pragma once
-#include
#include
#include
+#include
namespace WeirdEngine
{
@@ -17,9 +17,9 @@ namespace WeirdEngine
void build()
{
- const int verts = GRID_SIZE + 1;
- const float step = GRID_WORLD / static_cast(GRID_SIZE);
- const float half = GRID_WORLD * 0.5f;
+ const int verts = GRID_SIZE + 1;
+ const float step = GRID_WORLD / static_cast(GRID_SIZE);
+ const float half = GRID_WORLD * 0.5f;
std::vector vertices;
vertices.reserve(static_cast(verts * verts));
@@ -30,10 +30,9 @@ namespace WeirdEngine
{
WaterVertex v{};
v.position = glm::vec3(x * step - half, 0.0f, z * step - half);
- v.normal = glm::vec3(0.0f, 1.0f, 0.0f);
- v.color = glm::vec3(1.0f);
- v.texCoord = glm::vec2(static_cast(x) / GRID_SIZE,
- static_cast(z) / GRID_SIZE);
+ v.normal = glm::vec3(0.0f, 1.0f, 0.0f);
+ v.color = glm::vec3(1.0f);
+ v.texCoord = glm::vec2(static_cast(x) / GRID_SIZE, static_cast(z) / GRID_SIZE);
vertices.push_back(v);
}
}
@@ -45,13 +44,17 @@ namespace WeirdEngine
{
for (int x = 0; x < GRID_SIZE; ++x)
{
- GLuint tl = static_cast( z * verts + x );
- GLuint tr = static_cast( z * verts + x + 1);
- GLuint bl = static_cast((z + 1) * verts + x );
+ GLuint tl = static_cast(z * verts + x);
+ GLuint tr = static_cast(z * verts + x + 1);
+ GLuint bl = static_cast((z + 1) * verts + x);
GLuint br = static_cast((z + 1) * verts + x + 1);
- indices.push_back(tl); indices.push_back(bl); indices.push_back(tr);
- indices.push_back(tr); indices.push_back(bl); indices.push_back(br);
+ indices.push_back(tl);
+ indices.push_back(bl);
+ indices.push_back(tr);
+ indices.push_back(tr);
+ indices.push_back(bl);
+ indices.push_back(br);
}
}
@@ -64,13 +67,11 @@ namespace WeirdEngine
glBindVertexArray(m_waterVAO);
glBindBuffer(GL_ARRAY_BUFFER, m_waterVBO);
- glBufferData(GL_ARRAY_BUFFER,
- static_cast(vertices.size() * sizeof(WaterVertex)),
+ glBufferData(GL_ARRAY_BUFFER, static_cast(vertices.size() * sizeof(WaterVertex)),
vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_waterEBO);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER,
- static_cast(indices.size() * sizeof(GLuint)),
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, static_cast(indices.size() * sizeof(GLuint)),
indices.data(), GL_STATIC_DRAW);
// layout(location = 0) in vec3 in_position
@@ -98,9 +99,21 @@ namespace WeirdEngine
void free()
{
- if (m_waterVAO) { glDeleteVertexArrays(1, &m_waterVAO); m_waterVAO = 0; }
- if (m_waterVBO) { glDeleteBuffers(1, &m_waterVBO); m_waterVBO = 0; }
- if (m_waterEBO) { glDeleteBuffers(1, &m_waterEBO); m_waterEBO = 0; }
+ if (m_waterVAO)
+ {
+ glDeleteVertexArrays(1, &m_waterVAO);
+ m_waterVAO = 0;
+ }
+ if (m_waterVBO)
+ {
+ glDeleteBuffers(1, &m_waterVBO);
+ m_waterVBO = 0;
+ }
+ if (m_waterEBO)
+ {
+ glDeleteBuffers(1, &m_waterEBO);
+ m_waterEBO = 0;
+ }
}
void draw(WeirdRenderer::Shader& shader, const glm::mat4& model)
@@ -114,8 +127,7 @@ namespace WeirdEngine
static glm::vec2 rot2(glm::vec2 p, float a)
{
- return { p.x * cosf(a) - p.y * sinf(a),
- p.x * sinf(a) + p.y * cosf(a) };
+ return {p.x * cosf(a) - p.y * sinf(a), p.x * sinf(a) + p.y * cosf(a)};
}
static float gerstnerY(glm::vec2 xz, glm::vec2 dir, float wavelength, float amplitude, float t)
@@ -128,25 +140,23 @@ namespace WeirdEngine
float waterHeightAt(glm::vec2 xz, float t) const
{
// Domain warp (matches shader)
- glm::vec2 warp = {
- sinf(xz.x * 0.1731f + xz.y * 0.0893f + t * 0.071f) * 1.6f
- + cosf(xz.x * 0.2473f - xz.y * 0.1337f + t * 0.043f) * 0.9f,
- cosf(xz.x * 0.0971f + xz.y * 0.2011f + t * 0.059f) * 1.4f
- + sinf(xz.x * 0.1619f - xz.y * 0.3001f + t * 0.037f) * 0.7f
- };
+ glm::vec2 warp = {sinf(xz.x * 0.1731f + xz.y * 0.0893f + t * 0.071f) * 1.6f +
+ cosf(xz.x * 0.2473f - xz.y * 0.1337f + t * 0.043f) * 0.9f,
+ cosf(xz.x * 0.0971f + xz.y * 0.2011f + t * 0.059f) * 1.4f +
+ sinf(xz.x * 0.1619f - xz.y * 0.3001f + t * 0.037f) * 0.7f};
glm::vec2 xzW = xz + warp;
glm::vec2 xzR = rot2(xzW, 1.41421356f);
float y = 0.0f;
// Cascade A
- y += gerstnerY(xzW, glm::normalize(glm::vec2( 1.0f, 0.4f)), 8.09f, 0.110f, t);
- y += gerstnerY(xzW, glm::normalize(glm::vec2(-0.5f, 1.0f)), 5.00f, 0.075f, t);
- y += gerstnerY(xzW, glm::normalize(glm::vec2( 0.4f, -1.0f)), 3.09f, 0.040f, t);
+ y += gerstnerY(xzW, glm::normalize(glm::vec2(1.0f, 0.4f)), 8.09f, 0.110f, t);
+ y += gerstnerY(xzW, glm::normalize(glm::vec2(-0.5f, 1.0f)), 5.00f, 0.075f, t);
+ y += gerstnerY(xzW, glm::normalize(glm::vec2(0.4f, -1.0f)), 3.09f, 0.040f, t);
// Cascade B (rotated frame)
- y += gerstnerY(xzR, glm::normalize(glm::vec2( 1.0f, 0.3f)), 4.72f, 0.055f, t);
- y += gerstnerY(xzR, glm::normalize(glm::vec2(-0.7f, 1.0f)), 2.62f, 0.030f, t);
- y += gerstnerY(xzR, glm::normalize(glm::vec2( 0.9f, -0.6f)), 1.62f, 0.015f, t);
- y += gerstnerY(xzR, glm::normalize(glm::vec2(-1.0f, -0.3f)), 1.00f, 0.008f, t);
+ y += gerstnerY(xzR, glm::normalize(glm::vec2(1.0f, 0.3f)), 4.72f, 0.055f, t);
+ y += gerstnerY(xzR, glm::normalize(glm::vec2(-0.7f, 1.0f)), 2.62f, 0.030f, t);
+ y += gerstnerY(xzR, glm::normalize(glm::vec2(0.9f, -0.6f)), 1.62f, 0.015f, t);
+ y += gerstnerY(xzR, glm::normalize(glm::vec2(-1.0f, -0.3f)), 1.00f, 0.008f, t);
return y;
}
@@ -164,7 +174,7 @@ namespace WeirdEngine
GLuint m_waterEBO = 0;
GLsizei m_waterIndexCount = 0;
- static constexpr int GRID_SIZE = 512;
+ static constexpr int GRID_SIZE = 512;
static constexpr float GRID_WORLD = 200.0f;
};
-}
+} // namespace WeirdEngine
diff --git a/examples/opengl-experiments/src/index.html b/examples/opengl-experiments/src/index.html
new file mode 100644
index 00000000..8d27b742
--- /dev/null
+++ b/examples/opengl-experiments/src/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+ WeirdOpenGL
+
+
+
+
+
+
+
+
+
diff --git a/examples/opengl-experiments/src/main.cpp b/examples/opengl-experiments/src/main.cpp
index 097d1588..2c90ee3c 100644
--- a/examples/opengl-experiments/src/main.cpp
+++ b/examples/opengl-experiments/src/main.cpp
@@ -31,8 +31,6 @@ int main(int argc, char* argv[])
displaySettings.colorPalette[DisplaySettings::Orange].a = 1.0f;
-
-
PhysicsSettings physicsSettings{};
AudioSettings audioSettings{};
diff --git a/examples/sample-scenes/CMakeLists.txt b/examples/sample-scenes/CMakeLists.txt
index 49e2a253..f2503d4b 100644
--- a/examples/sample-scenes/CMakeLists.txt
+++ b/examples/sample-scenes/CMakeLists.txt
@@ -1,6 +1,16 @@
cmake_minimum_required(VERSION 3.10)
+
+# ==============================================================================
+# 1. Project Configuration
+# ==============================================================================
project(WeirdSamples)
+# Path to the WeirdEngine directory. Change this depending on where your project is located.
+# Examples inside weird-engine use "../../"
+# External projects usually use "../weird-engine/" or similar.
+set(WEIRD_ENGINE_LOCAL_PATH "../../")
+# ==============================================================================
+
# Create folders if they don't exist
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include")
@@ -12,12 +22,21 @@ set(CMAKE_CXX_EXTENSIONS OFF) # Ensure strictly standard C++
# Option to switch between local and online version of WeirdEngine
option(USE_LOCAL_WEIRD_ENGINE "Use local version of WeirdEngine" ON)
-# Set paths for the local WeirdEngine
-set(WEIRD_ENGINE_LOCAL_PATH "../../")
+
+# Option to build for web (Emscripten)
+option(BUILD_WEB "Build for web using Emscripten" OFF)
# Option to build for standalone deployment
option(DEPLOY_STANDALONE "Configure paths and copy assets for a standalone distribution" OFF)
+# Auto-detect Emscripten toolchain or explicit BUILD_WEB flag
+if(EMSCRIPTEN OR BUILD_WEB)
+ set(BUILD_WEB ON CACHE BOOL "" FORCE)
+ set(BUILD_WEB ON)
+ set(DEPLOY_STANDALONE ON CACHE BOOL "" FORCE)
+ set(DEPLOY_STANDALONE ON)
+endif()
+
if(DEPLOY_STANDALONE)
message(STATUS ">> DEPLOY MODE: Assets will be copied to output. Paths set to relative.")
# Force the engine to expect runtime assets
@@ -32,7 +51,7 @@ endif()
if(NOT TARGET WeirdEngine)
if(USE_LOCAL_WEIRD_ENGINE)
# Use the local version of WeirdEngine
- message(STATUS "Using local version of WeirdEngine")
+ message(STATUS "Using local version of WeirdEngine at ${WEIRD_ENGINE_LOCAL_PATH}")
add_subdirectory(${WEIRD_ENGINE_LOCAL_PATH} ${CMAKE_BINARY_DIR}/weird-engine)
# Resolve the local path to an absolute path for copying files later
@@ -40,11 +59,13 @@ if(NOT TARGET WeirdEngine)
else()
# Fetch WeirdEngine from GitHub
message(STATUS "Using online version of WeirdEngine")
+ set(WEIRD_ENGINE_GIT_REF "main")
+
include(FetchContent)
FetchContent_Declare(
WeirdEngine
GIT_REPOSITORY https://github.com/damacaa/weird-engine
- GIT_TAG main
+ GIT_TAG ${WEIRD_ENGINE_GIT_REF}
)
FetchContent_MakeAvailable(WeirdEngine)
@@ -72,14 +93,17 @@ set_source_files_properties(${WEIRDGAME_HEADERS} PROPERTIES HEADER_FILE_ONLY TRU
# Add executable including both sources and headers.
add_executable(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS})
+if(BUILD_WEB)
+ set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "index" SUFFIX ".html")
+endif()
+
# Set include directories.
-target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
+target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
# Link to WeirdEngine.
target_link_libraries(${PROJECT_NAME} PRIVATE WeirdEngine)
# Set Asset Path Macro
-
if(DEPLOY_STANDALONE)
set(ASSETS_PATH "./assets/")
else()
@@ -96,30 +120,38 @@ endif()
# -------------------------------------------------------------------------
# POST BUILD COMMANDS (DLLs + Assets + Fonts + Shaders)
# -------------------------------------------------------------------------
-add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
- # 1. Copy DLLs (SDL3)
- # COMMAND ${CMAKE_COMMAND} -E copy_if_different
- # $
- # $
-
- # 2. Copy Project ASSETS folder -> Build/assets
- COMMAND ${CMAKE_COMMAND} -E copy_directory
- "${CMAKE_CURRENT_SOURCE_DIR}/assets"
- "$/assets"
-
- # 3. Copy WeirdEngine FONTS -> Build/fonts
- # We look into the captured WEIRD_ENGINE_REAL_SOURCE/src/weird-renderer/fonts
- COMMAND ${CMAKE_COMMAND} -E copy_directory
- "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts"
- "$/fonts"
-
- # 4. Copy WeirdEngine SHADERS -> Build/shaders
- COMMAND ${CMAKE_COMMAND} -E copy_directory
- "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders"
- "$/shaders"
-
- COMMENT "Copying Runtime DLLs, Game Assets, Engine Fonts, and Engine Shaders"
-)
+if(DEPLOY_STANDALONE)
+ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ # 1. Copy Project ASSETS folder -> Build/assets
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${CMAKE_CURRENT_SOURCE_DIR}/assets"
+ "$/assets"
+
+ # 2. Copy WeirdEngine FONTS -> Build/fonts
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/fonts"
+ "$/fonts"
+
+ # 3. Copy WeirdEngine SHADERS -> Build/shaders
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ "${WEIRD_ENGINE_REAL_SOURCE}/src/weird-renderer/shaders"
+ "$/shaders"
+
+ COMMENT "Copying Game Assets, Engine Fonts, and Engine Shaders"
+ )
+
+ if(BUILD_WEB)
+ # For web builds, copy index.html if it exists
+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html")
+ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${CMAKE_CURRENT_SOURCE_DIR}/src/index.html"
+ "$/index.html"
+ COMMENT "Copying index.html for web build"
+ )
+ endif()
+ endif()
+endif()
# -------------------------------------------------------------------------
# SOURCE GROUPS
@@ -136,4 +168,4 @@ function(assign_source_groups TARGET)
endforeach()
endfunction()
-assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS})
\ No newline at end of file
+assign_source_groups(${PROJECT_NAME} ${WEIRDGAME_SOURCES} ${WEIRDGAME_HEADERS} ${WEIRDGAME_ASSETS})
diff --git a/examples/sample-scenes/assets/Organisms/man.weird b/examples/sample-scenes/assets/Organisms/man.weird
new file mode 100644
index 00000000..e7c653b8
--- /dev/null
+++ b/examples/sample-scenes/assets/Organisms/man.weird
@@ -0,0 +1,753 @@
+{
+ "camera": {
+ "position": [
+ -3.5375001430511475,
+ 1.024999976158142,
+ 15.000022888183594
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ -1.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ },
+ "entities": [
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 15
+ },
+ "id": 33,
+ "rigidBody2D": {
+ "physicsPosition": [
+ 0.0,
+ 0.0
+ ],
+ "simulationId": 0
+ },
+ "transform": {
+ "position": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 15
+ },
+ "id": 34,
+ "rigidBody2D": {
+ "physicsPosition": [
+ -1.0,
+ 0.0
+ ],
+ "simulationId": 1
+ },
+ "transform": {
+ "position": [
+ -1.0,
+ 0.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 15
+ },
+ "id": 35,
+ "rigidBody2D": {
+ "physicsPosition": [
+ -1.0,
+ -1.0
+ ],
+ "simulationId": 2
+ },
+ "transform": {
+ "position": [
+ -1.0,
+ -1.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 15
+ },
+ "id": 36,
+ "rigidBody2D": {
+ "physicsPosition": [
+ -1.0,
+ -2.0
+ ],
+ "simulationId": 3
+ },
+ "transform": {
+ "position": [
+ -1.0,
+ -2.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 15
+ },
+ "id": 37,
+ "rigidBody2D": {
+ "physicsPosition": [
+ 1.0,
+ 0.0
+ ],
+ "simulationId": 4
+ },
+ "transform": {
+ "position": [
+ 1.0,
+ 0.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 15
+ },
+ "id": 38,
+ "rigidBody2D": {
+ "physicsPosition": [
+ 1.0,
+ -1.0
+ ],
+ "simulationId": 5
+ },
+ "transform": {
+ "position": [
+ 1.0,
+ -1.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 15
+ },
+ "id": 39,
+ "rigidBody2D": {
+ "physicsPosition": [
+ 1.0,
+ -2.0
+ ],
+ "simulationId": 6
+ },
+ "transform": {
+ "position": [
+ 1.0,
+ -2.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 11
+ },
+ "id": 40,
+ "rigidBody2D": {
+ "physicsPosition": [
+ 0.0,
+ 2.0
+ ],
+ "simulationId": 7
+ },
+ "transform": {
+ "position": [
+ 0.0,
+ 2.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 8
+ },
+ "id": 41,
+ "rigidBody2D": {
+ "physicsPosition": [
+ -1.0,
+ 1.0
+ ],
+ "simulationId": 8
+ },
+ "transform": {
+ "position": [
+ -1.0,
+ 1.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 8
+ },
+ "id": 42,
+ "rigidBody2D": {
+ "physicsPosition": [
+ 1.0,
+ 1.0
+ ],
+ "simulationId": 9
+ },
+ "transform": {
+ "position": [
+ 1.0,
+ 1.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 8
+ },
+ "id": 43,
+ "rigidBody2D": {
+ "physicsPosition": [
+ 0.0,
+ 1.0
+ ],
+ "simulationId": 10
+ },
+ "transform": {
+ "position": [
+ 0.0,
+ 1.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 8
+ },
+ "id": 44,
+ "rigidBody2D": {
+ "physicsPosition": [
+ 2.0,
+ 1.0
+ ],
+ "simulationId": 11
+ },
+ "transform": {
+ "position": [
+ 2.0,
+ 1.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 8
+ },
+ "id": 45,
+ "rigidBody2D": {
+ "physicsPosition": [
+ 3.0,
+ 1.0
+ ],
+ "simulationId": 12
+ },
+ "transform": {
+ "position": [
+ 3.0,
+ 1.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 11
+ },
+ "id": 46,
+ "rigidBody2D": {
+ "physicsPosition": [
+ 4.0,
+ 1.0
+ ],
+ "simulationId": 13
+ },
+ "transform": {
+ "position": [
+ 4.0,
+ 1.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 8
+ },
+ "id": 47,
+ "rigidBody2D": {
+ "physicsPosition": [
+ -2.0,
+ 1.0
+ ],
+ "simulationId": 14
+ },
+ "transform": {
+ "position": [
+ -2.0,
+ 1.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 8
+ },
+ "id": 48,
+ "rigidBody2D": {
+ "physicsPosition": [
+ -3.0,
+ 1.0
+ ],
+ "simulationId": 15
+ },
+ "transform": {
+ "position": [
+ -3.0,
+ 1.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ },
+ {
+ "dot": {
+ "isStatic": false,
+ "materialId": 11
+ },
+ "id": 49,
+ "rigidBody2D": {
+ "physicsPosition": [
+ -4.0,
+ 1.0
+ ],
+ "simulationId": 16
+ },
+ "transform": {
+ "position": [
+ -4.0,
+ 1.0,
+ 0.0
+ ],
+ "rotation": [
+ 0.0,
+ 0.0,
+ 0.0
+ ],
+ "scale": [
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+ }
+ ],
+ "physics": {
+ "distanceConstraints": [
+ {
+ "A": 1,
+ "B": 0,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 0,
+ "B": 4,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 4,
+ "B": 9,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 9,
+ "B": 10,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 10,
+ "B": 7,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 10,
+ "B": 8,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 8,
+ "B": 1,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 10,
+ "B": 0,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 1,
+ "B": 10,
+ "distance": 1.4142135381698608,
+ "k": 1.0
+ },
+ {
+ "A": 8,
+ "B": 0,
+ "distance": 1.4142135381698608,
+ "k": 1.0
+ },
+ {
+ "A": 0,
+ "B": 9,
+ "distance": 1.4142135381698608,
+ "k": 1.0
+ },
+ {
+ "A": 10,
+ "B": 4,
+ "distance": 1.4142135381698608,
+ "k": 1.0
+ },
+ {
+ "A": 7,
+ "B": 8,
+ "distance": 1.4142135381698608,
+ "k": 1.0
+ },
+ {
+ "A": 7,
+ "B": 9,
+ "distance": 1.4142135381698608,
+ "k": 1.0
+ },
+ {
+ "A": 9,
+ "B": 11,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 11,
+ "B": 12,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 12,
+ "B": 13,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 8,
+ "B": 14,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 14,
+ "B": 15,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 15,
+ "B": 16,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 1,
+ "B": 2,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 2,
+ "B": 3,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 4,
+ "B": 5,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 5,
+ "B": 6,
+ "distance": 1.0,
+ "k": 1.0
+ },
+ {
+ "A": 16,
+ "B": 7,
+ "distance": 4.123105525970459,
+ "k": 0.0024806864093989134
+ },
+ {
+ "A": 7,
+ "B": 13,
+ "distance": 4.123105525970459,
+ "k": 0.0024806864093989134
+ },
+ {
+ "A": 3,
+ "B": 14,
+ "distance": 3.1622776985168457,
+ "k": 0.0024806864093989134
+ },
+ {
+ "A": 3,
+ "B": 0,
+ "distance": 2.2360680103302,
+ "k": 0.0024806864093989134
+ },
+ {
+ "A": 0,
+ "B": 6,
+ "distance": 2.2360680103302,
+ "k": 0.0024806864093989134
+ },
+ {
+ "A": 6,
+ "B": 13,
+ "distance": 4.242640495300293,
+ "k": 0.0024806864093989134
+ },
+ {
+ "A": 6,
+ "B": 11,
+ "distance": 3.1622776985168457,
+ "k": 0.0024806864093989134
+ },
+ {
+ "A": 3,
+ "B": 16,
+ "distance": 4.242640495300293,
+ "k": 0.0024806864093989134
+ }
+ ],
+ "fixedObjects": [],
+ "gravitationalConstraints": []
+ },
+ "tags": [
+ {
+ "entityId": 40,
+ "name": "head"
+ }
+ ],
+ "version": 1
+}
\ No newline at end of file
diff --git a/examples/sample-scenes/include/AquariumScene.h b/examples/sample-scenes/include/AquariumScene.h
index fb351791..aaf604ef 100644
--- a/examples/sample-scenes/include/AquariumScene.h
+++ b/examples/sample-scenes/include/AquariumScene.h
@@ -379,9 +379,8 @@ class AquariumScene : public Scene2D
ecs.destroyEntity(foodEntity);
Entity lastSeg = eel.segments.back();
- Entity prevSeg = eel.segments.size() > 1
- ? eel.segments[eel.segments.size() - 2]
- : eel.segments[0];
+ Entity prevSeg =
+ eel.segments.size() > 1 ? eel.segments[eel.segments.size() - 2] : eel.segments[0];
auto& lastT = transformArray->getDataFromEntity(lastSeg);
auto& prevT = transformArray->getDataFromEntity(prevSeg);
@@ -398,8 +397,8 @@ class AquariumScene : public Scene2D
lastT.position.y + tailDir.y * eel.segmentSpacing, 0.0f);
auto& nd = ecs.addComponent(newSeg);
- nd.materialId = static_cast(eel.baseMaterial +
- static_cast(eel.segments.size() % 4));
+ nd.materialId =
+ static_cast(eel.baseMaterial + static_cast(eel.segments.size() % 4));
ecs.addComponent(newSeg);
@@ -610,8 +609,8 @@ class AquariumScene : public Scene2D
if (length(cohesion) > 0.001f)
cohesion = normalize(cohesion) * fd.maxSpeed - fd.velocity;
- boidsForce = separation * fd.separationWeight + alignment * fd.alignmentWeight +
- cohesion * fd.cohesionWeight;
+ boidsForce =
+ separation * fd.separationWeight + alignment * fd.alignmentWeight + cohesion * fd.cohesionWeight;
}
if (seekingMate && closestMateDistSq > 0.000001f && closestMateDistSq < MATE_RADIUS * MATE_RADIUS)
diff --git a/examples/sample-scenes/include/CollisionHandling.h b/examples/sample-scenes/include/CollisionHandling.h
index 47998d9b..489949ee 100644
--- a/examples/sample-scenes/include/CollisionHandling.h
+++ b/examples/sample-scenes/include/CollisionHandling.h
@@ -8,7 +8,7 @@ using namespace WeirdEngine;
class CollisionHandlingScene : public Scene2D
{
public:
- CollisionHandlingScene(){};
+ CollisionHandlingScene() {};
private:
// Inherited via Scene
@@ -21,8 +21,8 @@ class CollisionHandlingScene : public Scene2D
for (size_t i = 0; i < 10; i++)
{
- float y = 10 + i;
- float x = 2 * i;
+ float y = 10.0f + static_cast(i);
+ float x = 2.0f * static_cast(i);
int material = 4 + (i % 12);
diff --git a/examples/sample-scenes/include/DestroyScene.h b/examples/sample-scenes/include/DestroyScene.h
index ee4bbe77..731b274a 100644
--- a/examples/sample-scenes/include/DestroyScene.h
+++ b/examples/sample-scenes/include/DestroyScene.h
@@ -1,7 +1,7 @@
#pragma once
-#include
#include
+#include
#include "globals.h"
#include "weird-physics/components/DistanceConstraint.h"
@@ -52,101 +52,101 @@ class DestroyScene : public Scene2D
switch (action)
{
- case 0:
- {
- if (m_testBalls.size() < 1000)
+ case 0:
{
- for (int j = 0; j < 10; ++j)
+ if (m_testBalls.size() < 1000)
{
- Entity e = ecs.createEntity();
- auto& t = ecs.addComponent(e);
- t.position = vec3((std::rand() % 200) - 100.0f, (std::rand() % 100) - 50.0f, 0.0f);
- ecs.setComponentDirty(t);
- auto& ui = ecs.addComponent(e);
- ui.materialId = 4 + (e % 12);
- auto& rb = ecs.addComponent(e);
- m_testBalls.push_back(e);
+ for (int j = 0; j < 10; ++j)
+ {
+ Entity e = ecs.createEntity();
+ auto& t = ecs.addComponent(e);
+ t.position = vec3((std::rand() % 200) - 100.0f, (std::rand() % 100) - 50.0f, 0.0f);
+ ecs.setComponentDirty(t);
+ auto& ui = ecs.addComponent(e);
+ ui.materialId = 4 + (e % 12);
+ auto& rb = ecs.addComponent(e);
+ m_testBalls.push_back(e);
+ }
}
+ break;
}
- break;
- }
- case 1:
- {
- if (m_testShapes.size() < 20)
+ case 1:
{
- float x = (std::rand() % 200) - 100.0f;
- float y = (std::rand() % 100) - 50.0f;
- float w = (float)(std::rand() % 4 + 1);
- float h = (float)(std::rand() % 4 + 1);
- float variables[8]{w, y, x, h, 0.0f, 0.0f, 0.0f, 0.0f};
- uint16_t material = std::rand() % 16;
- Entity shape = addShape(DefaultShapes::BOX, variables, material, CombinationType::Addition);
- m_testShapes.push_back(shape);
+ if (m_testShapes.size() < 20)
+ {
+ float x = (std::rand() % 200) - 100.0f;
+ float y = (std::rand() % 100) - 50.0f;
+ float w = (float)(std::rand() % 4 + 1);
+ float h = (float)(std::rand() % 4 + 1);
+ float variables[8]{w, y, x, h, 0.0f, 0.0f, 0.0f, 0.0f};
+ uint16_t material = std::rand() % 16;
+ Entity shape = addShape(DefaultShapes::BOX, variables, material, CombinationType::Addition);
+ m_testShapes.push_back(shape);
+ }
+ break;
}
- break;
- }
- case 2:
- {
- if (m_testBalls.size() >= 2 && m_testConstraints.size() < 50)
+ case 2:
{
- int idx1 = std::rand() % m_testBalls.size();
- int idx2 = std::rand() % m_testBalls.size();
- if (idx1 != idx2)
+ if (m_testBalls.size() >= 2 && m_testConstraints.size() < 50)
{
- Entity constraintEnt = ecs.createEntity();
- if (std::rand() % 2 == 0)
+ int idx1 = std::rand() % m_testBalls.size();
+ int idx2 = std::rand() % m_testBalls.size();
+ if (idx1 != idx2)
{
- auto& constraint = ecs.addComponent(constraintEnt);
- constraint.entityA = m_testBalls[idx1];
- constraint.entityB = m_testBalls[idx2];
- constraint.distance = 3.0f + (std::rand() % 5);
+ Entity constraintEnt = ecs.createEntity();
+ if (std::rand() % 2 == 0)
+ {
+ auto& constraint = ecs.addComponent(constraintEnt);
+ constraint.entityA = m_testBalls[idx1];
+ constraint.entityB = m_testBalls[idx2];
+ constraint.distance = 3.0f + (std::rand() % 5);
+ }
+ else
+ {
+ auto& spring = ecs.addComponent(constraintEnt);
+ spring.entityA = m_testBalls[idx1];
+ spring.entityB = m_testBalls[idx2];
+ spring.restDistance = 3.0f + (std::rand() % 5);
+ spring.stiffness = 5.0f;
+ }
+ m_testConstraints.push_back(constraintEnt);
}
- else
- {
- auto& spring = ecs.addComponent(constraintEnt);
- spring.entityA = m_testBalls[idx1];
- spring.entityB = m_testBalls[idx2];
- spring.restDistance = 3.0f + (std::rand() % 5);
- spring.stiffness = 5.0f;
- }
- m_testConstraints.push_back(constraintEnt);
}
+ break;
}
- break;
- }
- case 3:
- {
- if (!m_testShapes.empty())
+ case 3:
{
- int idx = std::rand() % m_testShapes.size();
- ecs.destroyEntity(m_testShapes[idx]);
- m_testShapes[idx] = m_testShapes.back();
- m_testShapes.pop_back();
+ if (!m_testShapes.empty())
+ {
+ int idx = std::rand() % m_testShapes.size();
+ ecs.destroyEntity(m_testShapes[idx]);
+ m_testShapes[idx] = m_testShapes.back();
+ m_testShapes.pop_back();
+ }
+ break;
}
- break;
- }
- case 4:
- {
- if (!m_testBalls.empty())
+ case 4:
{
- int idx = std::rand() % m_testBalls.size();
- ecs.destroyEntity(m_testBalls[idx]);
- m_testBalls[idx] = m_testBalls.back();
- m_testBalls.pop_back();
+ if (!m_testBalls.empty())
+ {
+ int idx = std::rand() % m_testBalls.size();
+ ecs.destroyEntity(m_testBalls[idx]);
+ m_testBalls[idx] = m_testBalls.back();
+ m_testBalls.pop_back();
+ }
+ break;
}
- break;
- }
- case 5:
- {
- if (!m_testConstraints.empty())
+ case 5:
{
- int idx = std::rand() % m_testConstraints.size();
- ecs.destroyEntity(m_testConstraints[idx]);
- m_testConstraints[idx] = m_testConstraints.back();
- m_testConstraints.pop_back();
+ if (!m_testConstraints.empty())
+ {
+ int idx = std::rand() % m_testConstraints.size();
+ ecs.destroyEntity(m_testConstraints[idx]);
+ m_testConstraints[idx] = m_testConstraints.back();
+ m_testConstraints.pop_back();
+ }
+ break;
}
- break;
- }
}
}
}
@@ -154,7 +154,8 @@ class DestroyScene : public Scene2D
void onEntityCollision(ECSManager& ecs, WeirdEngine::EntityCollisionEvent& event) override
{
- if (std::rand() % 5 != 0) return;
+ if (std::rand() % 5 != 0)
+ return;
Entity a = event.entityA;
@@ -164,7 +165,7 @@ class DestroyScene : public Scene2D
ecs.addComponent(a);
ecs.getComponent(a).collisionCount++;
}
-
+
playSound({0.02f, 400.0f + (std::rand() % 200), false, vec3(0.0f), 1});
}
diff --git a/examples/sample-scenes/include/ImageScene.h b/examples/sample-scenes/include/ImageScene.h
index ae8ec5d1..8fddbb95 100644
--- a/examples/sample-scenes/include/ImageScene.h
+++ b/examples/sample-scenes/include/ImageScene.h
@@ -10,7 +10,7 @@ using namespace WeirdEngine;
class ImageScene : public Scene2D
{
public:
- ImageScene(){};
+ ImageScene() {};
private:
std::string binaryString;
@@ -48,7 +48,7 @@ class ImageScene : public Scene2D
float y;
int material = 0;
- x = 15 + sin(i);
+ x = 15.0f + static_cast(sin(i));
y = 10 + (1.0f * i);
std::string materialId;
@@ -188,8 +188,8 @@ class ImageScene : public Scene2D
Entity rbOwner = components->getEntityAtIdx(i);
Transform& t = ecs.getComponent(rbOwner);
- int x = floor(t.position.x);
- int y = floor(30 - t.position.y);
+ int x = static_cast(floor(t.position.x));
+ int y = static_cast(floor(30.0f - t.position.y));
vec2 uv = vec2(x, y) / 30.0f;
diff --git a/examples/sample-scenes/include/LifeScene.h b/examples/sample-scenes/include/LifeScene.h
index 693d513c..8f7c2b45 100644
--- a/examples/sample-scenes/include/LifeScene.h
+++ b/examples/sample-scenes/include/LifeScene.h
@@ -4,8 +4,8 @@
#include
-#include
#include "weird-physics/components/GlobalPhysicsSettings.h"
+#include
#include "globals.h"
@@ -23,7 +23,7 @@ struct Head
class LifeScene : public Scene2D
{
public:
- LifeScene(){};
+ LifeScene() {};
private:
// Inherited via Scene
@@ -44,7 +44,7 @@ class LifeScene : public Scene2D
for (const auto& entry : std::filesystem::directory_iterator(organismsDir))
{
- Logger::log(entry.path());
+ Logger::log(entry.path().string());
if (!entry.is_regular_file() || entry.path().extension() != ".weird")
continue;
@@ -86,8 +86,8 @@ class LifeScene : public Scene2D
}
}
- ecs.getComponent(m_mainCamera).position = g_cameraPositon;
- }
+ ecs.getComponent(m_mainCamera).position = g_cameraPositon;
+ }
void onUpdate(float delta, ECSManager& ecs) override
{
diff --git a/examples/sample-scenes/include/MouseCollisionScene.h b/examples/sample-scenes/include/MouseCollisionScene.h
index 93fe7763..3d05d5f9 100644
--- a/examples/sample-scenes/include/MouseCollisionScene.h
+++ b/examples/sample-scenes/include/MouseCollisionScene.h
@@ -5,12 +5,18 @@
#include "globals.h"
using namespace WeirdEngine;
+
class MouseCollisionScene : public Scene2D
{
public:
- MouseCollisionScene(){};
+ MouseCollisionScene() {};
private:
+ struct CollisionCounter
+ {
+ int count;
+ };
+
Entity m_cursorShape;
// Inherited via Scene
@@ -22,7 +28,7 @@ class MouseCollisionScene : public Scene2D
for (size_t i = 0; i < 9900; i++)
{
- float y = (int)(i / 20);
+ float y = static_cast(i / 20);
float x = 5 + (i % 20) + sin(y);
int material = 4 + (i % 12);
@@ -38,9 +44,10 @@ class MouseCollisionScene : public Scene2D
}
Dot& dot = ecs.addComponent(entity);
- dot.materialId = material;
+ dot.materialId = 0;
RigidBody2D& rb = ecs.addComponent(entity);
+ CollisionCounter& counter = ecs.addComponent(entity);
}
// Floor
@@ -95,4 +102,50 @@ class MouseCollisionScene : public Scene2D
ecs.setComponentDirty(cs);
}
}
+
+ void onEntityCollision(ECSManager& ecs, WeirdEngine::EntityCollisionEvent& event) override
+ {
+ if (ecs.hasComponent(event.entityA))
+ {
+ auto& counter = ecs.getComponent(event.entityA);
+ counter.count++;
+
+ constexpr int COLLISIONS_PER_MATERIAL = 50;
+ if (counter.count <= 10 * COLLISIONS_PER_MATERIAL && counter.count % COLLISIONS_PER_MATERIAL == 0)
+ {
+ auto& dot = ecs.getComponent(event.entityA);
+ dot.materialId++;
+
+ if (counter.count == 10 * COLLISIONS_PER_MATERIAL)
+ dot.materialId = 0;
+ }
+ }
+
+ if (ecs.hasComponent(event.entityB))
+ {
+ auto& counter = ecs.getComponent(event.entityB);
+ counter.count++;
+
+ constexpr int COLLISIONS_PER_MATERIAL = 50;
+ if (counter.count <= 10 * COLLISIONS_PER_MATERIAL && counter.count % COLLISIONS_PER_MATERIAL == 0)
+ {
+ auto& dot = ecs.getComponent(event.entityB);
+ dot.materialId++;
+
+ if (counter.count == 10 * COLLISIONS_PER_MATERIAL)
+ dot.materialId = 0;
+ }
+ }
+ }
+
+ void onEntityShapeCollision(ECSManager& ecs, WeirdEngine::EntityShapeCollisionEvent& event) override
+ {
+ if (ecs.hasComponent(event.entity))
+ {
+ auto& counter = ecs.getComponent(event.entity);
+ counter.count = 0;
+ auto& dot = ecs.getComponent(event.entity);
+ dot.materialId = 0;
+ }
+ }
};
diff --git a/examples/sample-scenes/include/RopeScene.h b/examples/sample-scenes/include/RopeScene.h
index 431ca49c..9247159e 100644
--- a/examples/sample-scenes/include/RopeScene.h
+++ b/examples/sample-scenes/include/RopeScene.h
@@ -10,8 +10,7 @@ using namespace WeirdEngine;
class RopeScene : public Scene2D
{
public:
- RopeScene(){
- }
+ RopeScene() {}
private:
Entity m_star = INVALID_ENTITY;
@@ -116,7 +115,7 @@ class RopeScene : public Scene2D
addShape(DefaultShapes::SINE, vars0, 3);
float vars1[8] = {25.0f, 10.0f, 5.0f, 0.5f, 13.0f, 5.0f}; // Custom shape
- // m_star = addShape(DefaultShapes::STAR, vars1, 3);
+ m_star = addShape(DefaultShapes::STAR, vars1, 3);
float vars3[8] = {15.0f, -98.0f, 15.0f, 100.0f};
addShape(DefaultShapes::BOX, vars3, 3, CombinationType::Addition);
@@ -161,13 +160,14 @@ class RopeScene : public Scene2D
}
// Animate custom shape over time
- if(m_star != INVALID_ENTITY)
+ if (m_star != INVALID_ENTITY)
{
- // Instead of getSimulation().getSimulationTime(), we can just use getTime() if Scene provides it, or track delta.
+ // Instead of getSimulation().getSimulationTime(), we can just use getTime() if Scene provides it, or track
+ // delta.
static float animTime = 0.0f;
animTime += delta;
auto& cs = ecs.getComponent(m_star);
- cs.parameters[4] = static_cast(std::floor(animTime)) % 5 + 2;
+ cs.parameters[4] = static_cast((static_cast(std::floor(animTime)) % 5) + 2);
cs.parameters[3] = std::sin(3.1416f * animTime);
ecs.setComponentDirty(cs);
}
@@ -239,7 +239,7 @@ class RopeScene : public Scene2D
[&](Entity e, RigidBody2D& rb, Transform& t)
{
vec2 force(0, -0.001f * (t.position.y * t.position.y));
- force.x += t.position.x < 0.0f ? - t.position.x : 0.0f;
+ force.x += t.position.x < 0.0f ? -t.position.x : 0.0f;
force.x -= t.position.x > 30.0f ? t.position.x - 30.0f : 0.0f;
force.x = 10.0f / delta * glm::clamp(force.x, -1.0f, 1.0f);
diff --git a/examples/sample-scenes/include/ShapesCombinations.h b/examples/sample-scenes/include/ShapesCombinations.h
index 34f07cdf..958aefe8 100644
--- a/examples/sample-scenes/include/ShapesCombinations.h
+++ b/examples/sample-scenes/include/ShapesCombinations.h
@@ -11,8 +11,7 @@ using namespace WeirdEngine;
class ShapeCombinatiosScene : public Scene2D
{
public:
- ShapeCombinatiosScene(){
- }
+ ShapeCombinatiosScene() {}
private:
Entity m_circle = INVALID_ENTITY;
@@ -35,11 +34,11 @@ class ShapeCombinatiosScene : public Scene2D
std::random_device rd;
std::mt19937 gen(rd());
float range = 20.0f;
- std::uniform_real_distribution<> distrib(-range, range);
+ std::uniform_real_distribution distrib(-range, range);
// Boxes
{
- std::uniform_real_distribution<> distribY(0, 5);
+ std::uniform_real_distribution distribY(0.0f, 5.0f);
for (int i = 0; i < 0; ++i)
{
@@ -116,7 +115,7 @@ class ShapeCombinatiosScene : public Scene2D
float halfHeight = Display::height / 2.0f;
m_initialMousePositionInWorld =
- ECS::Camera::screenPositionToWorldPosition2D(cameraTransform, vec2(halfWidth, halfHeight));
+ ECS::Camera::screenPositionToWorldPosition2D(cameraTransform, vec2(halfWidth, halfHeight));
}
if (Input::GetMouseButton(Input::RightClick))
diff --git a/examples/sample-scenes/include/TextScene.h b/examples/sample-scenes/include/TextScene.h
new file mode 100644
index 00000000..7774a40e
--- /dev/null
+++ b/examples/sample-scenes/include/TextScene.h
@@ -0,0 +1,168 @@
+#pragma once
+
+#include
+
+#include "globals.h"
+#include "weird-renderer/core/Display.h"
+
+using namespace WeirdEngine;
+
+class TextScene : public Scene2D
+{
+public:
+ TextScene() {};
+
+private:
+ Entity m_counterText = INVALID_ENTITY;
+ Entity m_centerText = INVALID_ENTITY;
+ Entity m_leftText = INVALID_ENTITY;
+ Entity m_rightText = INVALID_ENTITY;
+ Entity m_worldText = INVALID_ENTITY;
+ Entity m_worldMouseText = INVALID_ENTITY;
+ Entity m_nonResponsiveText = INVALID_ENTITY;
+
+ int m_counter = 0;
+ int m_lastResolutionHash = 0;
+
+ void onStart(ECSManager& ecs) override
+ {
+ m_debugInput = true;
+ m_debugFly = true;
+
+ {
+ float vars[8] = {15.0f, -50.0f, 250.0f, 50.0f};
+ addShape(DefaultShapes::BOX, vars, DisplaySettings::LightGray, CombinationType::SmoothAddition);
+ }
+
+ ecs.getComponent(m_mainCamera).position = g_cameraPositon;
+ m_lastResolutionHash = Display::width + Display::height;
+
+ {
+ m_worldText = ecs.createEntity();
+ auto& t = ecs.addComponent(m_worldText);
+ t.position = vec3(15.0f, 12.0f, 0.0f);
+
+ auto& text = ecs.addComponent(m_worldText);
+ text.text = "WORLD TEXT";
+ text.material = DisplaySettings::Cyan;
+ text.horizontalAlignment = TextRenderer::HorizontalAlignment::Center;
+ text.verticalAlignment = TextRenderer::VerticalAlignment::Top;
+ }
+
+ {
+ m_worldMouseText = ecs.createEntity();
+ auto& t = ecs.addComponent(m_worldMouseText);
+ t.position = vec3(0.0f, 0.0f, 0.0f);
+
+ auto& text = ecs.addComponent(m_worldMouseText);
+ text.text = "WORLD MOUSE";
+ text.material = DisplaySettings::LightBlue;
+ text.horizontalAlignment = TextRenderer::HorizontalAlignment::Left;
+ text.verticalAlignment = TextRenderer::VerticalAlignment::Top;
+ }
+
+ {
+ m_counterText = ecs.createEntity();
+ auto& t = ecs.addComponent(m_counterText);
+ t.position = vec3(static_cast(Display::width) * 0.5f, 50.0f, 0.0f);
+
+ auto& text = ecs.addComponent(m_counterText);
+ text.text = "0";
+ text.material = DisplaySettings::LightGreen;
+ text.horizontalAlignment = TextRenderer::HorizontalAlignment::Left;
+ text.verticalAlignment = TextRenderer::VerticalAlignment::Bottom;
+ }
+
+ {
+ m_centerText = ecs.createEntity();
+ auto& t = ecs.addComponent(m_centerText);
+ t.position = vec3(static_cast(Display::width) * 0.5f, 20.0f, 0.0f);
+
+ auto& text = ecs.addComponent(m_centerText);
+ text.text = "CENTERED";
+ text.material = DisplaySettings::Yellow;
+ text.horizontalAlignment = TextRenderer::HorizontalAlignment::Center;
+ text.verticalAlignment = TextRenderer::VerticalAlignment::Bottom;
+ }
+
+ {
+ m_leftText = ecs.createEntity();
+ auto& t = ecs.addComponent(m_leftText);
+ t.position = vec3(10.0f, 20.0f, 0.0f);
+
+ auto& text = ecs.addComponent(m_leftText);
+ text.text = "LEFT";
+ text.material = DisplaySettings::Orange;
+ text.horizontalAlignment = TextRenderer::HorizontalAlignment::Left;
+ text.verticalAlignment = TextRenderer::VerticalAlignment::Bottom;
+ }
+
+ {
+ m_rightText = ecs.createEntity();
+ auto& t = ecs.addComponent(m_rightText);
+ t.position = vec3(static_cast(Display::width) - 10.0f, 20.0f, 0.0f);
+
+ auto& text = ecs.addComponent(m_rightText);
+ text.text = "RIGHT";
+ text.material = DisplaySettings::Magenta;
+ text.horizontalAlignment = TextRenderer::HorizontalAlignment::Right;
+ text.verticalAlignment = TextRenderer::VerticalAlignment::Bottom;
+ }
+
+ {
+ m_nonResponsiveText = ecs.createEntity();
+ auto& t = ecs.addComponent(m_nonResponsiveText);
+ t.position =
+ vec3(static_cast(Display::width) - 10.0f, static_cast(Display::height) - 10.0f, 0.0f);
+
+ auto& text = ecs.addComponent(m_nonResponsiveText);
+ text.text = "STUCK";
+ text.material = DisplaySettings::Red;
+ text.horizontalAlignment = TextRenderer::HorizontalAlignment::Right;
+ text.verticalAlignment = TextRenderer::VerticalAlignment::Top;
+ }
+ }
+
+ void onUpdate(float delta, ECSManager& ecs) override
+ {
+ if (Input::GetKeyDown(Input::Q) || Input::GetGamepadButtonDown(Input::GamepadButton::North))
+ {
+ setSceneComplete();
+ }
+
+ m_counter++;
+ {
+ auto& text = ecs.getComponent(m_counterText);
+ text.text = std::to_string(m_counter);
+ ecs.setComponentDirty(text);
+
+ auto& t = ecs.getComponent(m_counterText);
+ t.position.x = Input::GetMouseX() + 20.0f;
+ t.position.y = Input::GetMouseY() + 10.0f;
+ }
+
+ {
+ auto& cameraTransform = ecs.getComponent(m_mainCamera);
+ vec2 mouseScreen = vec2(Input::GetMouseX() + 20.0f, Input::GetMouseY() - 10.0f);
+ vec2 mouseWorld = ECS::Camera::screenPositionToWorldPosition2D(cameraTransform, mouseScreen);
+
+ auto& t = ecs.getComponent(m_worldMouseText);
+ t.position.x = mouseWorld.x;
+ t.position.y = mouseWorld.y;
+ ecs.setComponentDirty(t);
+ }
+
+ int hash = Display::width + Display::height;
+ if (hash != m_lastResolutionHash)
+ {
+ m_lastResolutionHash = hash;
+
+ float halfW = static_cast(Display::width) * 0.5f;
+
+ ecs.getComponent(m_counterText).position = vec3(halfW, 20.0f, 0.0f);
+ ecs.getComponent(m_centerText).position = vec3(halfW, 40.0f, 0.0f);
+ ecs.getComponent(m_rightText).position =
+ vec3(static_cast(Display::width) - 10.0f, 20.0f, 0.0f);
+ }
+ }
+};
\ No newline at end of file
diff --git a/examples/sample-scenes/include/WalkScene.h b/examples/sample-scenes/include/WalkScene.h
index ffe0aa41..d0c76fa9 100644
--- a/examples/sample-scenes/include/WalkScene.h
+++ b/examples/sample-scenes/include/WalkScene.h
@@ -24,10 +24,9 @@ struct Foot
class WalkScene : public Scene2D
{
public:
- WalkScene(){};
+ WalkScene() {};
private:
-
Entity m_head;
// Inherited via Scene
@@ -61,9 +60,9 @@ class WalkScene : public Scene2D
m_head = tags["head"];
-
float boundsVars2[8]{0.0f, -24.0f, 200.0f, 20.0f};
- Entity inside = addShape(DefaultShapes::BOX, boundsVars2, DisplaySettings::LightGreen, CombinationType::Addition);
+ Entity inside =
+ addShape(DefaultShapes::BOX, boundsVars2, DisplaySettings::LightGreen, CombinationType::Addition);
ecs.getComponent(m_mainCamera).position = g_cameraPositon;
@@ -97,9 +96,9 @@ class WalkScene : public Scene2D
auto& foot = componentArray->getDataAtIdx(i);
auto& rb = rigidBodies->getDataFromEntity(componentArray->getEntityAtIdx(i));
- if(i != m_currentFoot)
+ if (i != m_currentFoot)
{
- if(foot.onFloor)
+ if (foot.onFloor)
{
rb.isFixed = true;
ecs.setComponentDirty(rb);
@@ -133,7 +132,7 @@ class WalkScene : public Scene2D
{
foot.stepStarted = false;
m_currentFoot = (m_currentFoot + 1) % componentArray->getSize();
- // WeirdEngine::Logger::Log("Switching foot: " + std::to_string(m_currentFoot));
+ // WeirdEngine::Logger::log("Switching foot: " + std::to_string(m_currentFoot));
}
else
{
@@ -152,7 +151,7 @@ class WalkScene : public Scene2D
f = (foot.direction + vec2(0.0f, -10.0f * foot.t)) * foot.forceMagnitude * foot.t;
}
- if(m_feetTouching)
+ if (m_feetTouching)
f.x = 0.0f;
rb.pendingImpulseForce += f;
@@ -164,7 +163,7 @@ class WalkScene : public Scene2D
}
}
}
-
+
m_feetTouching = false;
}
diff --git a/examples/sample-scenes/src/index.html b/examples/sample-scenes/src/index.html
new file mode 100644
index 00000000..0fd56092
--- /dev/null
+++ b/examples/sample-scenes/src/index.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+ WeirdSamples
+
+
+
+
+
+
+
+
+
diff --git a/examples/sample-scenes/src/main.cpp b/examples/sample-scenes/src/main.cpp
index 348e1bd4..19f07eb5 100644
--- a/examples/sample-scenes/src/main.cpp
+++ b/examples/sample-scenes/src/main.cpp
@@ -9,11 +9,10 @@
#include "MouseCollisionScene.h"
#include "RopeScene.h"
#include "ShapesCombinations.h"
+#include "TextScene.h"
#include "WalkScene.h"
#include "globals.h"
-#include "MoleculeEditor.h"
-#include "SceneLoadExample.h"
#include "weird-renderer/core/Display.h"
WeirdEngine::vec3 g_cameraPositon = vec3(15.0f, 7.5f, 35.0f);
@@ -24,19 +23,19 @@ int main(int argc, char* argv[])
sceneManager.registerScene("shapes");
sceneManager.registerScene("rope");
- // sceneManager.registerScene("cursor-collision");
- // sceneManager.registerScene("image");
- // sceneManager.registerScene("collision-handling");
- // sceneManager.registerScene("destroy-test");
- // sceneManager.registerScene("scene-editor", ASSETS_PATH "example.weird");
- // sceneManager.registerScene("molecule-editor");
+ sceneManager.registerScene("text");
sceneManager.registerScene("life");
+ sceneManager.registerScene("cursor-collision");
+ sceneManager.registerScene("destroy-test");
+
+ // sceneManager.registerScene("collision-handling");
+ // sceneManager.registerScene("image");
// sceneManager.registerScene("walk");
// sceneManager.registerScene("aquarium");
DisplaySettings displaySettings{};
- displaySettings.width = 640;
- displaySettings.height = 480;
+ displaySettings.width = 800;
+ displaySettings.height = 800;
displaySettings.fullscreen = false;
displaySettings.colorPalette[DisplaySettings::Yellow].a = 0.25f;
displaySettings.distanceSampleScale = 0.5f;
diff --git a/include/weird-engine.h b/include/weird-engine.h
index bdbfbf42..0bcc52c6 100644
--- a/include/weird-engine.h
+++ b/include/weird-engine.h
@@ -15,8 +15,8 @@
#endif
#include "weird-engine/Input.h"
-#include "weird-engine/Profiler.h"
#include "weird-engine/Logger.h"
+#include "weird-engine/Profiler.h"
#include "weird-engine/SceneManager.h"
#include "weird-renderer/core/Renderer.h"
#include "weird-renderer/core/SDLInitializer.h"
@@ -40,7 +40,6 @@ extern "C"
#define SHADERS_PATH
#endif // !SHADERS_PATH
-
#include "weird-physics/PhysicsSettings.h"
#include "weird-renderer/audio/AudioEngine.h"
#include "weird-renderer/audio/AudioSettings.h"
@@ -82,7 +81,8 @@ namespace WeirdEngine
inline void runFrame(RuntimeContext& ctx)
{
// Measure time
- ctx.time = static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency());
+ ctx.time =
+ static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency());
ctx.delta = ctx.time - ctx.prevTime;
ctx.timeDiff += ctx.delta;
ctx.prevTime = ctx.time;
@@ -111,8 +111,8 @@ namespace WeirdEngine
ctx.totalFrames++;
if (ctx.totalFrames % 120 == 0)
{
- std::cout << "[WeirdEngine] frame " << ctx.totalFrames
- << " (t=" << (ctx.time - ctx.startTime) << "s)" << std::endl;
+ std::cout << "[WeirdEngine] frame " << ctx.totalFrames << " (t=" << (ctx.time - ctx.startTime) << "s)"
+ << std::endl;
}
if (ctx.autoQuitAt > 0.0 && ctx.time >= ctx.autoQuitAt)
{
@@ -139,14 +139,14 @@ namespace WeirdEngine
Input::suppressKeyboardInput();
}
#endif
-
+
SDL_Event event;
while (SDL_PollEvent(&event))
{
#ifndef WEIRD_DISABLE_IMGUI
ImGui_ImplSDL3_ProcessEvent(&event);
#endif
-
+
if (event.type == SDL_EVENT_QUIT)
{
ctx.quit = true;
@@ -155,9 +155,10 @@ namespace WeirdEngine
{
int newWidth = event.window.data1;
int newHeight = event.window.data2;
-
- WeirdEngine::Logger::log("Window resized to: " + std::to_string(newWidth) + "x" + std::to_string(newHeight));
-
+
+ WeirdEngine::Logger::log("Window resized to: " + std::to_string(newWidth) + "x" +
+ std::to_string(newHeight));
+
ctx.renderer.setWindowSize(newWidth, newHeight);
newResolution = true;
}
@@ -222,7 +223,7 @@ namespace WeirdEngine
if (g_emscriptenEnv->runtimeContext->quit)
{
- WeirdEngine::Logger::Log("Quitting...");
+ WeirdEngine::Logger::log("Quitting...");
// Clean up heap-allocated resources
if (g_emscriptenEnv->runtimeContext != nullptr)
{
@@ -259,16 +260,14 @@ namespace WeirdEngine
if (arg == "--fullscreen" || arg == "-f")
{
displaySettings.fullscreen = true;
- }else if ((arg == "--scene" || arg == "-s") && i + 1 < argc)
+ }
+ else if ((arg == "--scene" || arg == "-s") && i + 1 < argc)
{
startupScene = argv[++i]; // Get the next argument as the scene name
WeirdEngine::Logger::log("Startup scene set to: " + startupScene);
}
}
-
-
-
sceneManager.setPhysicsSettings(physicsSettings);
AudioEngine& audioEngine = AudioEngine::getInstance();
@@ -277,11 +276,12 @@ namespace WeirdEngine
#ifdef __EMSCRIPTEN__
// In Emscripten, allocate all resources on the heap to prevent stack unwinding issues
Detail::g_emscriptenEnv = new Detail::EmscriptenRuntimeEnvironment();
-
+
// Create SDLInitializer and Renderer on the heap
try
{
- Detail::g_emscriptenEnv->sdlInitializer = new SDLInitializer(displaySettings, Detail::g_windowHandle, audioEngine);
+ Detail::g_emscriptenEnv->sdlInitializer =
+ new SDLInitializer(displaySettings, Detail::g_windowHandle, audioEngine);
Detail::g_emscriptenEnv->renderer = new Renderer(displaySettings, Detail::g_windowHandle);
}
catch (...)
@@ -311,12 +311,10 @@ namespace WeirdEngine
}
// Time - create RuntimeContext with references to heap-allocated objects
- Detail::g_emscriptenEnv->runtimeContext = new Detail::RuntimeContext{
- sceneManager,
- *Detail::g_emscriptenEnv->renderer,
- audioEngine
- };
- Detail::g_emscriptenEnv->runtimeContext->time = static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency());
+ Detail::g_emscriptenEnv->runtimeContext =
+ new Detail::RuntimeContext{sceneManager, *Detail::g_emscriptenEnv->renderer, audioEngine};
+ Detail::g_emscriptenEnv->runtimeContext->time =
+ static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency());
Detail::g_emscriptenEnv->runtimeContext->prevTime = Detail::g_emscriptenEnv->runtimeContext->time;
#ifdef WEIRD_TEST_HOOKS
Detail::g_emscriptenEnv->runtimeContext->startTime = Detail::g_emscriptenEnv->runtimeContext->time;
@@ -339,7 +337,8 @@ namespace WeirdEngine
// Time
Detail::RuntimeContext runtimeContext{sceneManager, renderer, audioEngine};
- runtimeContext.time = static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency());
+ runtimeContext.time =
+ static_cast(SDL_GetPerformanceCounter()) / static_cast(SDL_GetPerformanceFrequency());
runtimeContext.prevTime = runtimeContext.time;
#ifdef WEIRD_TEST_HOOKS
runtimeContext.startTime = runtimeContext.time;
diff --git a/include/weird-engine/Background.h b/include/weird-engine/Background.h
index ac976368..729d1e4b 100644
--- a/include/weird-engine/Background.h
+++ b/include/weird-engine/Background.h
@@ -5,22 +5,24 @@
namespace WeirdEngine
{
- enum class BackgroundType {
- Solid,
- Grid,
- Sky,
- Custom
- };
+ enum class BackgroundType
+ {
+ Solid,
+ Grid,
+ Sky,
+ Custom
+ };
- struct BackgroundParams {
- BackgroundType type = BackgroundType::Grid;
-
- glm::vec4 primaryColor{0.7f, 0.7f, 0.71f, 1.0f};
- glm::vec4 secondaryColor{0.55f, 0.55f, 0.58f, 1.0f};
- float scale = 1.0f;
- float intensity = 1.0f;
- bool isDirty = true;
+ struct BackgroundParams
+ {
+ BackgroundType type = BackgroundType::Grid;
- std::string customShaderCode = "";
- };
-}
+ glm::vec4 primaryColor{0.7f, 0.7f, 0.71f, 1.0f};
+ glm::vec4 secondaryColor{0.55f, 0.55f, 0.58f, 1.0f};
+ float scale = 1.0f;
+ float intensity = 1.0f;
+ bool isDirty = true;
+
+ std::string customShaderCode = "";
+ };
+} // namespace WeirdEngine
diff --git a/include/weird-engine/Input.h b/include/weird-engine/Input.h
index 59bf1c56..dd7763f0 100644
--- a/include/weird-engine/Input.h
+++ b/include/weird-engine/Input.h
@@ -1,13 +1,13 @@
#pragma once
+#include
#include
#include
#include
-#include
-#include
-#include "weird-renderer/core/Display.h"
#include "weird-engine/Logger.h"
+#include "weird-renderer/core/Display.h"
+#include
///
/// Stores the state of every key in the keyboard and mouse.
@@ -66,7 +66,8 @@ namespace WeirdEngine
delete[] m_gamepadAxisTable;
for (auto pad : m_gamepads)
{
- if (pad) SDL_CloseGamepad(pad);
+ if (pad)
+ SDL_CloseGamepad(pad);
}
}
@@ -273,11 +274,11 @@ namespace WeirdEngine
auto& instance = getInstance();
for (int i = 0; i < 5; ++i)
{
- if (instance.m_mouseKeysTable[i] > NOT_PRESSED) // IS_PRESSED or FIRST_PRESSED
- instance.m_mouseKeysTable[i] = RELEASED_THIS_FRAME; // fire key-up
+ if (instance.m_mouseKeysTable[i] > NOT_PRESSED) // IS_PRESSED or FIRST_PRESSED
+ instance.m_mouseKeysTable[i] = RELEASED_THIS_FRAME; // fire key-up
else if (instance.m_mouseKeysTable[i] == RELEASED_THIS_FRAME)
- instance.m_mouseKeysTable[i] = NOT_PRESSED; // clear existing key-up
- // NOT_PRESSED stays NOT_PRESSED — no spurious key-ups
+ instance.m_mouseKeysTable[i] = NOT_PRESSED; // clear existing key-up
+ // NOT_PRESSED stays NOT_PRESSED — no spurious key-ups
}
}
@@ -286,11 +287,11 @@ namespace WeirdEngine
auto& instance = getInstance();
for (int i = 0; i < SDL_SCANCODE_COUNT; ++i)
{
- if (instance.m_keyTable[i] > NOT_PRESSED) // IS_PRESSED or FIRST_PRESSED
- instance.m_keyTable[i] = RELEASED_THIS_FRAME; // fire key-up
+ if (instance.m_keyTable[i] > NOT_PRESSED) // IS_PRESSED or FIRST_PRESSED
+ instance.m_keyTable[i] = RELEASED_THIS_FRAME; // fire key-up
else if (instance.m_keyTable[i] == RELEASED_THIS_FRAME)
- instance.m_keyTable[i] = NOT_PRESSED; // clear existing key-up
- // NOT_PRESSED stays NOT_PRESSED — no spurious key-ups
+ instance.m_keyTable[i] = NOT_PRESSED; // clear existing key-up
+ // NOT_PRESSED stays NOT_PRESSED — no spurious key-ups
}
}
@@ -321,8 +322,8 @@ namespace WeirdEngine
enum GamepadButton
{
South = SDL_GAMEPAD_BUTTON_SOUTH, // A
- East = SDL_GAMEPAD_BUTTON_EAST, // B
- West = SDL_GAMEPAD_BUTTON_WEST, // X
+ East = SDL_GAMEPAD_BUTTON_EAST, // B
+ West = SDL_GAMEPAD_BUTTON_WEST, // X
North = SDL_GAMEPAD_BUTTON_NORTH, // Y
Back = SDL_GAMEPAD_BUTTON_BACK,
Guide = SDL_GAMEPAD_BUTTON_GUIDE,
@@ -418,9 +419,8 @@ namespace WeirdEngine
SDL_GUIDToString(SDL_GetGamepadGUIDForID(id), guid, sizeof(guid));
const char* mapping = SDL_GetGamepadMapping(pad);
- Logger::log("Gamepad connected: " + std::string(name ? name : "Unknown")
- + " [GUID: " + std::string(guid) + "]"
- + " mapping: " + std::string(mapping ? mapping : "(none)"));
+ Logger::log("Gamepad connected: " + std::string(name ? name : "Unknown") + " [GUID: " +
+ std::string(guid) + "]" + " mapping: " + std::string(mapping ? mapping : "(none)"));
}
break;
}
diff --git a/include/weird-engine/Logger.h b/include/weird-engine/Logger.h
index e1a622b1..10bb8184 100644
--- a/include/weird-engine/Logger.h
+++ b/include/weird-engine/Logger.h
@@ -1,36 +1,36 @@
#pragma once
+#include
#include
#include
-#include
namespace WeirdEngine
{
- enum class LogLevel
- {
- Info,
- Warning,
- Error
- };
+ enum class LogLevel
+ {
+ Info,
+ Warning,
+ Error
+ };
- struct LogMessage
- {
- LogLevel level;
- std::string message;
- };
+ struct LogMessage
+ {
+ LogLevel level;
+ std::string message;
+ };
- class Logger
- {
- public:
- static void log(const std::string& message);
- static void warning(const std::string& message);
- static void error(const std::string& message);
+ class Logger
+ {
+ public:
+ static void log(const std::string& message);
+ static void warning(const std::string& message);
+ static void error(const std::string& message);
- static bool s_enableConsoleOutput;
- static void drawImGuiConsole();
+ static bool s_enableConsoleOutput;
+ static void drawImGuiConsole();
- private:
- static std::vector s_messages;
- static std::mutex s_mutex;
- };
-}
+ private:
+ static std::vector s_messages;
+ static std::mutex s_mutex;
+ };
+} // namespace WeirdEngine
diff --git a/include/weird-engine/Material3D.h b/include/weird-engine/Material3D.h
index 13819200..1a4384c7 100644
--- a/include/weird-engine/Material3D.h
+++ b/include/weird-engine/Material3D.h
@@ -21,4 +21,4 @@ namespace WeirdEngine
MaterialPattern pattern = MaterialPattern::None;
float patternScale = 1.0f;
};
-}
+} // namespace WeirdEngine
diff --git a/include/weird-engine/Profiler.h b/include/weird-engine/Profiler.h
index ccf4dee2..e481f90b 100644
--- a/include/weird-engine/Profiler.h
+++ b/include/weird-engine/Profiler.h
@@ -1,13 +1,13 @@
#pragma once
+#include "weird-engine/Logger.h"
#include
+#include
+#include
#include
#include
+#include
#include
#include
-#include
-#include
-#include
-#include "weird-engine/Logger.h"
namespace WeirdEngine
{
@@ -56,13 +56,22 @@ namespace WeirdEngine
m_pendingRealtimeEnable = false;
}
- bool isRealtime() const { return m_realtimeMode; }
+ bool isRealtime() const
+ {
+ return m_realtimeMode;
+ }
- double getUnaccountedThreshold() const { return m_unaccountedThresholdPct; }
- void setUnaccountedThreshold(double threshold) { m_unaccountedThresholdPct = threshold; }
+ double getUnaccountedThreshold() const
+ {
+ return m_unaccountedThresholdPct;
+ }
+ void setUnaccountedThreshold(double threshold)
+ {
+ m_unaccountedThresholdPct = threshold;
+ }
- const std::vector& getLastFrameStats() const
- {
+ const std::vector& getLastFrameStats() const
+ {
if (m_paused && m_historyEnabled && !m_historyBuffer.empty())
{
if (m_playbackIndex >= 0 && m_playbackIndex < m_historyBuffer.size())
@@ -70,7 +79,7 @@ namespace WeirdEngine
return m_historyBuffer[m_playbackIndex];
}
}
- return m_lastFrameStats;
+ return m_lastFrameStats;
}
void setHistoryEnabled(bool enabled)
@@ -85,16 +94,40 @@ namespace WeirdEngine
}
}
}
- bool isHistoryEnabled() const { return m_historyEnabled; }
- int getHistoryCapturedCount() const { return (int)m_historyBuffer.size(); }
- int getHistoryCapacity() const { return m_historyCapacity; }
+ bool isHistoryEnabled() const
+ {
+ return m_historyEnabled;
+ }
+ int getHistoryCapturedCount() const
+ {
+ return (int)m_historyBuffer.size();
+ }
+ int getHistoryCapacity() const
+ {
+ return m_historyCapacity;
+ }
- void pause() { m_pendingPause = true; }
- void resume() { m_pendingResume = true; }
- bool isPaused() const { return m_paused; }
+ void pause()
+ {
+ m_pendingPause = true;
+ }
+ void resume()
+ {
+ m_pendingResume = true;
+ }
+ bool isPaused() const
+ {
+ return m_paused;
+ }
- int getPlaybackIndex() const { return m_playbackIndex; }
- void setPlaybackIndex(int idx) { m_playbackIndex = idx; }
+ int getPlaybackIndex() const
+ {
+ return m_playbackIndex;
+ }
+ void setPlaybackIndex(int idx)
+ {
+ m_playbackIndex = idx;
+ }
double getReportProgressSeconds() const
{
@@ -107,8 +140,14 @@ namespace WeirdEngine
return 0.0;
}
- bool isReportFinished() const { return m_reportFinished; }
- bool isRecordingReport() const { return m_recording && !m_realtimeMode; }
+ bool isReportFinished() const
+ {
+ return m_reportFinished;
+ }
+ bool isRecordingReport() const
+ {
+ return m_recording && !m_realtimeMode;
+ }
std::string getReportString() const
{
@@ -116,7 +155,7 @@ namespace WeirdEngine
ss << "Profiler Average Report\n";
ss << "=======================\n";
const auto& stats = getLastFrameStats();
-
+
double topMs = 0.0;
for (const auto& s : stats)
{
@@ -126,15 +165,18 @@ namespace WeirdEngine
break;
}
}
- if (topMs <= 0.0) topMs = 1.0;
+ if (topMs <= 0.0)
+ topMs = 1.0;
for (const auto& s : stats)
{
- if (s.count == 0 || s.depth == 0) continue;
+ if (s.count == 0 || s.depth == 0)
+ continue;
double avgMs = s.totalTimeMs / s.count;
float fraction = (float)(avgMs / topMs);
fraction = std::min(1.0f, std::max(0.0f, fraction));
- for (int i = 1; i < s.depth; ++i) ss << " ";
+ for (int i = 1; i < s.depth; ++i)
+ ss << " ";
ss << s.name << ": ";
ss << std::fixed << std::setprecision(3) << avgMs << " ms (";
ss << std::fixed << std::setprecision(1) << (fraction * 100.0f) << "%)\n";
@@ -245,7 +287,8 @@ namespace WeirdEngine
int parentIdx = m_stack.empty() ? -1 : m_stack.back().statIndex;
int statIndex = -1;
- if (m_currentIndex < m_stats.size() && m_stats[m_currentIndex].name == name && m_stats[m_currentIndex].parentIndex == parentIdx)
+ if (m_currentIndex < m_stats.size() && m_stats[m_currentIndex].name == name &&
+ m_stats[m_currentIndex].parentIndex == parentIdx)
{
statIndex = m_currentIndex;
m_currentIndex++;
@@ -255,10 +298,11 @@ namespace WeirdEngine
bool found = false;
for (size_t i = 0; i < m_stats.size(); ++i)
{
- if (m_stats[i].name == name && m_stats[i].depth == m_currentDepth && m_stats[i].parentIndex == parentIdx)
+ if (m_stats[i].name == name && m_stats[i].depth == m_currentDepth &&
+ m_stats[i].parentIndex == parentIdx)
{
- statIndex = i;
- m_currentIndex = i + 1;
+ statIndex = static_cast(i);
+ m_currentIndex = static_cast(i + 1);
found = true;
break;
}
@@ -266,8 +310,8 @@ namespace WeirdEngine
if (!found)
{
m_stats.push_back({name, m_currentDepth, 0.0, 0, parentIdx});
- statIndex = m_stats.size() - 1;
- m_currentIndex = m_stats.size();
+ statIndex = static_cast(m_stats.size() - 1);
+ m_currentIndex = static_cast(m_stats.size());
}
}
@@ -300,7 +344,8 @@ namespace WeirdEngine
}
private:
- void injectOthersRange(size_t start, size_t end, const std::vector& inStats, std::vector& outStats)
+ void injectOthersRange(size_t start, size_t end, const std::vector& inStats,
+ std::vector& outStats)
{
size_t i = start;
while (i < end)
@@ -324,7 +369,8 @@ namespace WeirdEngine
injectOthersRange(i + 1, subEnd, inStats, outStats);
double unaccountedMs = stat.totalTimeMs - childrenTotalMs;
- double unaccountedPctOfScope = stat.totalTimeMs > 0.0 ? (unaccountedMs / stat.totalTimeMs) * 100.0 : 0.0;
+ double unaccountedPctOfScope =
+ stat.totalTimeMs > 0.0 ? (unaccountedMs / stat.totalTimeMs) * 100.0 : 0.0;
if (unaccountedPctOfScope > m_unaccountedThresholdPct)
{
outStats.push_back({"Others", stat.depth + 1, unaccountedMs, stat.count, stat.parentIndex});
@@ -335,8 +381,6 @@ namespace WeirdEngine
}
}
-
-
struct StackItem
{
int statIndex;
@@ -379,6 +423,7 @@ namespace WeirdEngine
if (m_active)
Profiler::get().endScope();
}
+
private:
bool m_active;
};
diff --git a/include/weird-engine/ResourceManager.h b/include/weird-engine/ResourceManager.h
index 1af91802..4124109d 100644
--- a/include/weird-engine/ResourceManager.h
+++ b/include/weird-engine/ResourceManager.h
@@ -43,7 +43,8 @@ namespace WeirdEngine
json m_json;
// Loads a single mesh by its index, applying the given node world transform
- void loadMesh(const char* file, unsigned int indMesh, std::vector& meshes, glm::mat4 transform = glm::mat4(1.0f));
+ void loadMesh(const char* file, unsigned int indMesh, std::vector& meshes,
+ glm::mat4 transform = glm::mat4(1.0f));
// Traverses a node recursively, so it essentially traverses all connected nodes
void traverseNode(const char* file, unsigned int nextNode, std::vector& meshes,
diff --git a/include/weird-engine/Scene.h b/include/weird-engine/Scene.h
index e55da956..49d28af7 100644
--- a/include/weird-engine/Scene.h
+++ b/include/weird-engine/Scene.h
@@ -10,10 +10,10 @@
#include "weird-renderer/core/RenderTarget.h"
#include "weird-renderer/resources/DrawCommand.h"
+#include "weird-engine/Background.h"
+#include "weird-engine/Material3D.h"
#include "weird-physics/PhysicsSettings.h"
#include "weird-physics/Simulation2D.h"
-#include "weird-engine/Material3D.h"
-#include "weird-engine/Background.h"
#include
#include
@@ -68,15 +68,30 @@ namespace WeirdEngine
WeirdRenderer::Camera& getCamera();
std::vector& getLigths();
- Simulation2D& getSimulation2D() { return m_simulation2D; }
+ Simulation2D& getSimulation2D()
+ {
+ return m_simulation2D;
+ }
Material3D& createMaterial();
- Material3D& getMaterial(int index) { return m_materials[index]; }
- const Material3D* getMaterials() const { return m_materials; }
+ Material3D& getMaterial(int index)
+ {
+ return m_materials[index];
+ }
+ const Material3D* getMaterials() const
+ {
+ return m_materials;
+ }
- BackgroundParams& getBackground() { return m_background; }
- const BackgroundParams& getBackground() const { return m_background; }
+ BackgroundParams& getBackground()
+ {
+ return m_background;
+ }
+ const BackgroundParams& getBackground() const
+ {
+ return m_background;
+ }
float getTime();
@@ -120,7 +135,8 @@ namespace WeirdEngine
};
// Physics queries
- RaymarchResult raymarch(glm::vec2 origin, glm::vec2 direction, float epsilon = 0.001f, float maxDistance = 150.0f);
+ RaymarchResult raymarch(glm::vec2 origin, glm::vec2 direction, float epsilon = 0.001f,
+ float maxDistance = 150.0f);
void renderImGui();
void renderPhysicsStatsUI();
@@ -135,12 +151,12 @@ namespace WeirdEngine
virtual void onUpdate(float delta, ECSManager& ecs) = 0;
virtual void onRender(WeirdRenderer::RenderTarget& renderTarget) {};
virtual void onImGuiRender() {};
-
+
// Physics thread callbacks (No m_ecs access recommended!)
virtual void onPhysicsStep(Simulation2D& simulation) {};
virtual void onCollision(Simulation2D& simulation, WeirdEngine::CollisionEvent& event) {};
virtual void onShapeCollision(Simulation2D& simulation, WeirdEngine::ShapeCollisionEvent& event) {};
-
+
// Main thread callbacks (m_ecs is safe to use here) // ARE YOU SURE???
virtual void onEntityCollision(ECSManager& ecs, WeirdEngine::EntityCollisionEvent& event) {};
virtual void onEntityShapeCollision(ECSManager& ecs, WeirdEngine::EntityShapeCollisionEvent& event) {};
@@ -154,7 +170,7 @@ namespace WeirdEngine
Entity m_mainCamera;
ResourceManager m_resourceManager;
-
+
Material3D m_materials[16];
uint16_t m_materialCount = 0;
@@ -169,7 +185,7 @@ namespace WeirdEngine
{
return addShape(shapeId, variables, material.id, combination, hasCollision, group);
}
-
+
Entity addUIShape(ShapeId shapeId, float* variables, uint16_t material,
CombinationType combination = CombinationType::Addition, int group = 0);
Entity addUIShape(ShapeId shapeId, float* variables, const Material3D& material,
@@ -204,7 +220,8 @@ namespace WeirdEngine
SDFRenderSystemContext m_3DWorldRenderContext;
SDFRenderSystemContext m_UIRenderContext;
// Resolve a physics SimulationID to the owning entity.
- Entity getEntityForSimulationId(SimulationID simulationId, std::shared_ptr> rigidBodies);
+ Entity getEntityForSimulationId(SimulationID simulationId,
+ std::shared_ptr> rigidBodies);
bool m_debugFly = false;
bool m_debugInput = false;
@@ -224,7 +241,7 @@ namespace WeirdEngine
// Path to a .weird file to load when the scene starts (set via setSceneFilePath or registerScene)
std::string m_sceneFilePath;
-
+
BackgroundParams m_background;
private:
@@ -262,18 +279,27 @@ namespace WeirdEngine
class Scene2D : public Scene
{
public:
- Scene2D() { m_renderMode = RenderMode::RayMarching2D; }
+ Scene2D()
+ {
+ m_renderMode = RenderMode::RayMarching2D;
+ }
};
class Scene3D : public Scene
{
public:
- Scene3D() { m_renderMode = RenderMode::RayMarching3D; }
+ Scene3D()
+ {
+ m_renderMode = RenderMode::RayMarching3D;
+ }
};
class SceneBoth : public Scene
{
public:
- SceneBoth() { m_renderMode = RenderMode::RayMarchingBoth; }
+ SceneBoth()
+ {
+ m_renderMode = RenderMode::RayMarchingBoth;
+ }
};
} // namespace WeirdEngine
diff --git a/include/weird-engine/ecs/ComponentArray.h b/include/weird-engine/ecs/ComponentArray.h
index 5c043aec..15ee544d 100644
--- a/include/weird-engine/ecs/ComponentArray.h
+++ b/include/weird-engine/ecs/ComponentArray.h
@@ -129,7 +129,8 @@ namespace WeirdEngine
bool isEntityDirty(Entity entity)
{
- if (!hasData(entity)) return false;
+ if (!hasData(entity))
+ return false;
return dirtyFlags[entityToIndexMap[entity]];
}
@@ -148,7 +149,7 @@ namespace WeirdEngine
// Function to get the size of the array
int getSize() const
{
- return size;
+ return static_cast(size);
}
private:
diff --git a/include/weird-engine/ecs/ECS.h b/include/weird-engine/ecs/ECS.h
index 559918cd..72964bdd 100644
--- a/include/weird-engine/ecs/ECS.h
+++ b/include/weird-engine/ecs/ECS.h
@@ -8,15 +8,15 @@
#include
#include
#include
+#include
#include
#include
+#include
#include
#include
-#include
-#include
#if defined(__GNUC__) || defined(__clang__)
-#include
#include
+#include
#endif
namespace WeirdEngine
@@ -128,8 +128,7 @@ namespace WeirdEngine
// =====================================================================
// Primary form: lambda receives (Entity e, T&...)
- template
- void forEach(Func&& func)
+ template void forEach(Func&& func)
{
// Grab all the component arrays up front
auto arrays = std::make_tuple(getComponentArray()...);
@@ -140,8 +139,9 @@ namespace WeirdEngine
size_t smallestIdx = 0;
size_t idx = 0;
((void)(getComponentArray()->getSize() < smallestSize
- ? (smallestSize = getComponentArray()->getSize(), smallestIdx = idx++, true)
- : (idx++, false)), ...);
+ ? (smallestSize = getComponentArray()->getSize(), smallestIdx = idx++, true)
+ : (idx++, false)),
+ ...);
// Dispatch to the driver that iterates the smallest array
idx = 0;
@@ -149,7 +149,6 @@ namespace WeirdEngine
}
private:
-
// Driver: called once per type in the pack. Only the one matching
// smallestIdx actually runs the loop; the others return false.
template
@@ -177,7 +176,6 @@ namespace WeirdEngine
}
public:
-
template void registerComponent()
{
@@ -255,19 +253,24 @@ namespace WeirdEngine
private:
template void cacheComponentName(size_t id)
{
- if (m_componentNames.find(id) != m_componentNames.end()) return;
+ if (m_componentNames.find(id) != m_componentNames.end())
+ return;
const char* rawName = typeid(T).name();
std::string finalName;
#if defined(__GNUC__) || defined(__clang__)
int status = -4;
char* demangled = abi::__cxa_demangle(rawName, nullptr, nullptr, &status);
- if (status == 0 && demangled) {
+ if (status == 0 && demangled)
+ {
finalName = demangled;
std::free(demangled);
- } else {
+ }
+ else
+ {
finalName = rawName;
- if (demangled) std::free(demangled);
+ if (demangled)
+ std::free(demangled);
}
#else
finalName = rawName;
@@ -275,12 +278,16 @@ namespace WeirdEngine
// Strip namespaces (e.g. "WeirdEngine::Transform" -> "Transform")
size_t colonPos = finalName.rfind("::");
- if (colonPos != std::string::npos) {
+ if (colonPos != std::string::npos)
+ {
finalName = finalName.substr(colonPos + 2);
- } else {
+ }
+ else
+ {
// Strip "class " or "struct " prefixes if there was no namespace (mostly for MSVC)
size_t spacePos = finalName.rfind(" ");
- if (spacePos != std::string::npos) {
+ if (spacePos != std::string::npos)
+ {
finalName = finalName.substr(spacePos + 1);
}
}
diff --git a/include/weird-engine/math/Default2DSDFs.h b/include/weird-engine/math/Default2DSDFs.h
index 12a197e3..e268cd50 100644
--- a/include/weird-engine/math/Default2DSDFs.h
+++ b/include/weird-engine/math/Default2DSDFs.h
@@ -19,56 +19,49 @@ namespace WeirdEngine
{
namespace DefaultShapes
{
- inline auto var(uint8_t index) { return std::make_shared(index); }
+ inline auto var(uint8_t index)
+ {
+ return std::make_shared(index);
+ }
inline const uint16_t CIRCLE = Scene::registerDefaultSDF(std::make_shared(
- var(Primitives::Circle::POS_X), var(Primitives::Circle::POS_Y), var(Primitives::Circle::RADIUS)
- ));
+ var(Primitives::Circle::POS_X), var(Primitives::Circle::POS_Y), var(Primitives::Circle::RADIUS)));
inline const uint16_t CIRCLE_LINE = Scene::registerDefaultSDF(std::make_shared(
- std::make_shared(var(Primitives::Circle::POS_X), var(Primitives::Circle::POS_Y), var(Primitives::Circle::RADIUS)),
- var(Primitives::Circle::RADIUS + 1)
- ));
+ std::make_shared(var(Primitives::Circle::POS_X), var(Primitives::Circle::POS_Y),
+ var(Primitives::Circle::RADIUS)),
+ var(Primitives::Circle::RADIUS + 1)));
- inline const uint16_t BOX = Scene::registerDefaultSDF(std::make_shared(
- var(Primitives::Box::POS_X), var(Primitives::Box::POS_Y),
- var(Primitives::Box::SIZE_X), var(Primitives::Box::SIZE_Y)
- ));
+ inline const uint16_t BOX = Scene::registerDefaultSDF(
+ std::make_shared(var(Primitives::Box::POS_X), var(Primitives::Box::POS_Y),
+ var(Primitives::Box::SIZE_X), var(Primitives::Box::SIZE_Y)));
inline const uint16_t BOX_LINE = Scene::registerDefaultSDF(std::make_shared(
std::make_shared(var(Primitives::Box::POS_X), var(Primitives::Box::POS_Y),
var(Primitives::Box::SIZE_X), var(Primitives::Box::SIZE_Y)),
- var(Primitives::Box::SIZE_Y + 1)
- ));
+ var(Primitives::Box::SIZE_Y + 1)));
inline const uint16_t TRIANGLE = Scene::registerDefaultSDF(std::make_shared(
- var(Primitives::Triangle::POS_X), var(Primitives::Triangle::POS_Y),
- var(Primitives::Triangle::SIZE_X), var(Primitives::Triangle::SIZE_Y),
- var(Primitives::Triangle::ROTATION)
- ));
+ var(Primitives::Triangle::POS_X), var(Primitives::Triangle::POS_Y), var(Primitives::Triangle::SIZE_X),
+ var(Primitives::Triangle::SIZE_Y), var(Primitives::Triangle::ROTATION)));
inline const uint16_t TRIANGLE_LINE = Scene::registerDefaultSDF(std::make_shared(
std::make_shared(var(Primitives::Triangle::POS_X), var(Primitives::Triangle::POS_Y),
var(Primitives::Triangle::SIZE_X), var(Primitives::Triangle::SIZE_Y),
var(Primitives::Triangle::ROTATION)),
- var(Primitives::Triangle::ROTATION + 1)
- ));
+ var(Primitives::Triangle::ROTATION + 1)));
inline const uint16_t LINE = Scene::registerDefaultSDF(std::make_shared(
- var(Primitives::Line::POS_A_X), var(Primitives::Line::POS_A_Y),
- var(Primitives::Line::POS_B_X), var(Primitives::Line::POS_B_Y),
- var(Primitives::Line::WIDTH)
- ));
+ var(Primitives::Line::POS_A_X), var(Primitives::Line::POS_A_Y), var(Primitives::Line::POS_B_X),
+ var(Primitives::Line::POS_B_Y), var(Primitives::Line::WIDTH)));
inline const uint16_t RAMP = Scene::registerDefaultSDF(std::make_shared(
- var(Primitives::Ramp::POS_X), var(Primitives::Ramp::POS_Y),
- var(Primitives::Ramp::WIDTH), var(Primitives::Ramp::HEIGHT), var(Primitives::Ramp::SKEW)
- ));
+ var(Primitives::Ramp::POS_X), var(Primitives::Ramp::POS_Y), var(Primitives::Ramp::WIDTH),
+ var(Primitives::Ramp::HEIGHT), var(Primitives::Ramp::SKEW)));
inline const uint16_t SINE = Scene::registerDefaultSDF(std::make_shared