Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
name: Build & Test / ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- name: Linux
os: ubuntu-22.04
qt-arch: ""
- name: Windows
os: windows-latest
qt-arch: win64_msvc2022_64
- name: macOS
os: macos-latest
qt-arch: clang_64

steps:
- uses: actions/checkout@v4

- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: "6.10.2"
arch: ${{ matrix.qt-arch }}
modules: "qtmultimedia"
cache: true

- name: Platform dependencies (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update -q
sudo apt-get install -y ninja-build libeigen3-dev libgl1-mesa-dev libglu1-mesa-dev

- name: Platform dependencies (macOS)
if: runner.os == 'macOS'
run: brew install ninja eigen

- name: Platform dependencies (Windows)
if: runner.os == 'Windows'
run: choco install ninja --no-progress

- name: Set up MSVC (Windows)
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1

- name: Configure
run: cmake --preset test

- name: Build
run: cmake --build --preset test

- name: Test
run: ctest --preset test
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
build/
sounds/
dist/
dist/
*_out.txt
*_output.txt
CLAUDE.md
111 changes: 107 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,20 @@ if(NOT Eigen3_FOUND)
GIT_TAG 3.4.0
GIT_SHALLOW TRUE
)
set(EIGEN_BUILD_DOC OFF CACHE BOOL "" FORCE)
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
set(EIGEN_BUILD_PKGCONFIG OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(eigen)
# Use Populate (not MakeAvailable) to skip Eigen's CMakeLists.txt entirely.
# MakeAvailable triggers BLAS detection which calls enable_language(Fortran)
# and fails on CI runners that have a broken gfortran in PATH.
# Eigen is header-only for our use; no Fortran is needed.
FetchContent_GetProperties(eigen)
if(NOT eigen_POPULATED)
if(POLICY CMP0168)
cmake_policy(SET CMP0168 OLD) # suppress FetchContent_Populate deprecation (CMake 3.30+)
endif()
FetchContent_Populate(eigen)
endif()
add_library(Eigen3::Eigen INTERFACE IMPORTED GLOBAL)
target_include_directories(Eigen3::Eigen INTERFACE "${eigen_SOURCE_DIR}")
set(EIGEN3_INCLUDE_DIR "${eigen_SOURCE_DIR}")
endif()

find_package(OpenMP)
Expand Down Expand Up @@ -67,6 +77,7 @@ set(SOURCES
src/acoustics/RoomImpulseResponse.cpp
src/acoustics/Wall.cpp
src/acoustics/SimulationWorker.cpp
src/acoustics/RenderExports.cpp
src/acoustics/SimulationQueue.cpp
src/acoustics/AcousticMetrics.cpp
src/acoustics/dg/DGBasis2D.cpp
Expand Down Expand Up @@ -121,6 +132,9 @@ set(HEADERS
src/acoustics/RoomImpulseResponse.h
src/acoustics/Wall.h
src/acoustics/SimulationWorker.h
src/acoustics/RenderOptions.h
src/acoustics/RenderExports.h
src/acoustics/RenderPipeline.h
src/acoustics/SimulationQueue.h
src/acoustics/AcousticMetrics.h
src/acoustics/dg/DGTypes.h
Expand Down Expand Up @@ -221,5 +235,94 @@ install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

# ── Headless CLI render tool ─────────────────────────────────────────────────
set(CLI_SOURCES
src/cli/main.cpp
src/core/Material.cpp
src/core/MaterialLoader.cpp
src/core/SoundSource.cpp
src/core/Listener.cpp
src/core/PlacedPoint.cpp
src/core/ProjectFile.cpp
src/scene/SceneManager.cpp
src/rendering/Camera.cpp
src/rendering/MeshData.cpp
src/rendering/SurfaceGrouper.cpp
src/rendering/RayPicking.cpp
src/rendering/MeshSimplifier.cpp
src/rendering/TextureManager.cpp
src/acoustics/AcousticSimulator.cpp
src/acoustics/Bvh.cpp
src/acoustics/ImageSourceMethod.cpp
src/acoustics/RayTracer.cpp
src/acoustics/RoomImpulseResponse.cpp
src/acoustics/Wall.cpp
src/acoustics/SimulationWorker.cpp
src/acoustics/RenderExports.cpp
src/acoustics/RenderPipeline.cpp
src/acoustics/AcousticMetrics.cpp
src/acoustics/dg/DGBasis2D.cpp
src/acoustics/dg/DGBasis3D.cpp
src/acoustics/dg/DGMesh2D.cpp
src/acoustics/dg/DGMesh3D.cpp
src/acoustics/dg/DGAcoustics2D.cpp
src/acoustics/dg/DGAcoustics3D.cpp
src/acoustics/dg/DGSolver.cpp
src/acoustics/dg/DGGpuCompute.cpp
src/audio/AudioFile.cpp
src/audio/SignalProcessing.cpp
src/utils/ResourcePath.cpp
)

add_executable(SeicheCLI ${CLI_SOURCES})

target_include_directories(SeicheCLI PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
${EIGEN3_INCLUDE_DIR}
)

target_link_libraries(SeicheCLI PRIVATE
Qt6::Widgets
Qt6::OpenGL
Qt6::OpenGLWidgets
Qt6::Multimedia
Qt6::Svg
Eigen3::Eigen
)

if(OpenMP_CXX_FOUND)
target_link_libraries(SeicheCLI PRIVATE OpenMP::OpenMP_CXX)
endif()

if(SNDFILE_LIBRARIES)
target_include_directories(SeicheCLI PRIVATE ${SNDFILE_INCLUDE_DIRS})
target_link_libraries(SeicheCLI PRIVATE ${SNDFILE_LIBRARIES})
target_compile_definitions(SeicheCLI PRIVATE HAS_SNDFILE)
endif()

if(FFTW3_LIBRARIES)
target_include_directories(SeicheCLI PRIVATE ${FFTW3_INCLUDE_DIRS})
target_link_libraries(SeicheCLI PRIVATE ${FFTW3_LIBRARIES})
target_compile_definitions(SeicheCLI PRIVATE HAS_FFTW3)
endif()

if(WIN32)
target_link_libraries(SeicheCLI PRIVATE opengl32 glu32)
elseif(APPLE)
find_package(OpenGL REQUIRED)
target_link_libraries(SeicheCLI PRIVATE OpenGL::GL OpenGL::GLU)
else()
find_package(OpenGL REQUIRED)
target_link_libraries(SeicheCLI PRIVATE OpenGL::GL OpenGL::GLU)
endif()

target_compile_definitions(SeicheCLI PRIVATE _USE_MATH_DEFINES)

install(TARGETS SeicheCLI
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

enable_testing()
add_subdirectory(tests)
62 changes: 62 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"version": 6,
"cmakeMinimumRequired": { "major": 3, "minor": 21, "patch": 0 },
"configurePresets": [
{
"name": "base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}"
},
{
"name": "debug",
"inherits": "base",
"displayName": "Debug",
"description": "Debug build with symbols and assertions",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "release",
"inherits": "base",
"displayName": "Release",
"description": "Optimised release build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "test",
"inherits": "debug",
"displayName": "Test",
"description": "Debug build used for running the Qt test suite"
}
],
"buildPresets": [
{
"name": "debug",
"configurePreset": "debug"
},
{
"name": "release",
"configurePreset": "release"
},
{
"name": "test",
"configurePreset": "test"
}
],
"testPresets": [
{
"name": "test",
"configurePreset": "test",
"output": {
"outputOnFailure": true
},
"environment": {
"QT_QPA_PLATFORM": "offscreen"
}
}
]
}
47 changes: 42 additions & 5 deletions build_macos.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,43 @@
cmake -S . -B build \
-DCMAKE_PREFIX_PATH="<path/to/Qt/6.x/macos>" \
-DCMAKE_BUILD_TYPE=Release \
-G Ninja
#!/usr/bin/env bash
set -euo pipefail

cmake --build build
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

QT_PREFIX_PATH="${QT_PREFIX_PATH:-}"
CMAKE_GENERATOR="${CMAKE_GENERATOR:-Ninja}"

# Auto-detect Qt prefix from macdeployqt if not explicitly set
if [[ -z "${QT_PREFIX_PATH}" ]]; then
if command -v macdeployqt >/dev/null 2>&1; then
QT_PREFIX_PATH="$(cd "$(dirname "$(command -v macdeployqt)")/.." && pwd)"
fi
fi

if [[ -z "${QT_PREFIX_PATH}" ]]; then
echo "Error: QT_PREFIX_PATH is not set and could not be inferred from macdeployqt." >&2
echo "Set QT_PREFIX_PATH to your Qt macOS prefix (e.g. ~/Qt/6.x/macos)." >&2
exit 1
fi

if [[ ! -d "${QT_PREFIX_PATH}" ]]; then
echo "Error: QT_PREFIX_PATH does not exist: ${QT_PREFIX_PATH}" >&2
exit 1
fi

# Optionally pass Qt6_DIR if available
CMAKE_QT6_DIR_ARGS=()
if [[ -n "${Qt6_DIR:-}" && -d "${Qt6_DIR}" ]]; then
CMAKE_QT6_DIR_ARGS=( -DQt6_DIR="${Qt6_DIR}" )
elif [[ -d "${QT_PREFIX_PATH}/lib/cmake/Qt6" ]]; then
CMAKE_QT6_DIR_ARGS=( -DQt6_DIR="${QT_PREFIX_PATH}/lib/cmake/Qt6" )
fi

cmake -S "${REPO_ROOT}" -B "${REPO_ROOT}/build" \
-DCMAKE_PREFIX_PATH="${QT_PREFIX_PATH}" \
-DCMAKE_BUILD_TYPE=Release \
-G "${CMAKE_GENERATOR}" \
"${CMAKE_QT6_DIR_ARGS[@]}"

cmake --build "${REPO_ROOT}/build" --config Release

echo "Build complete. Run: ./build/Seiche.app/Contents/MacOS/Seiche"
10 changes: 8 additions & 2 deletions build_windows.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail

QT_ROOT="C:/Qt/6.10.2/mingw_64"
MINGW_BIN="C:/Qt/Tools/mingw1310_64/bin"
QT_ROOT="${QT_ROOT:-C:/Qt/6.10.2/mingw_64}"
MINGW_BIN="${MINGW_BIN:-C:/Qt/Tools/mingw1310_64/bin}"
QT_CMAKE="${QT_CMAKE:-C:/Qt/Tools/CMake_64/bin}"
QT_NINJA="${QT_NINJA:-C:/Qt/Tools/Ninja}"

# Prefer Qt-bundled cmake/ninja and the project's MinGW over anything else
# (avoids conflicts with e.g. Strawberry Perl's cmake).
export PATH="${QT_CMAKE}:${QT_NINJA}:${MINGW_BIN}:${PATH}"

# rm -rf build

Expand Down
Loading
Loading