Skip to content

Commit dee99eb

Browse files
authored
Merge pull request #382 from gpx1000/gltf-tutorial
Add Advanced glTF tutorial
2 parents 9edac41 + 72f8b8f commit dee99eb

83 files changed

Lines changed: 33715 additions & 5 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
name: Advanced glTF Example CI
2+
3+
on:
4+
push:
5+
paths:
6+
- 'attachments/advanced_gltf/**'
7+
- 'attachments/simple_engine/**'
8+
- '.github/workflows/advanced_gltf_example_ci.yml'
9+
pull_request:
10+
paths:
11+
- 'attachments/advanced_gltf/**'
12+
- 'attachments/simple_engine/**'
13+
- '.github/workflows/advanced_gltf_example_ci.yml'
14+
workflow_dispatch:
15+
16+
jobs:
17+
build:
18+
name: Build (${{ matrix.os }})
19+
runs-on: ${{ matrix.os }}
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
os: [ubuntu-latest, windows-latest]
24+
25+
defaults:
26+
run:
27+
working-directory: attachments/advanced_gltf
28+
29+
steps:
30+
- name: Checkout
31+
uses: actions/checkout@v4
32+
33+
# -----------------------------------------------------------------------
34+
# Linux toolchain
35+
# -----------------------------------------------------------------------
36+
- name: Install Clang + Ninja + ccache (Linux)
37+
if: runner.os == 'Linux'
38+
shell: bash
39+
run: |
40+
set -euo pipefail
41+
sudo apt-get update
42+
sudo apt-get install -y clang ninja-build ccache spirv-tools
43+
44+
- name: Select Clang toolchain (Linux)
45+
if: runner.os == 'Linux'
46+
shell: bash
47+
run: |
48+
echo "CC=clang" >> "$GITHUB_ENV"
49+
echo "CXX=clang++" >> "$GITHUB_ENV"
50+
51+
# -----------------------------------------------------------------------
52+
# Windows toolchain
53+
# -----------------------------------------------------------------------
54+
- name: Set up MSVC dev environment (Windows)
55+
if: runner.os == 'Windows'
56+
uses: ilammy/msvc-dev-cmd@v1
57+
58+
- name: Set up Ninja + sccache (Windows)
59+
if: runner.os == 'Windows'
60+
shell: pwsh
61+
run: |
62+
choco install -y ninja sccache
63+
$chocoBin = "C:\ProgramData\chocolatey\bin"
64+
if (Test-Path $chocoBin) {
65+
$chocoBin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
66+
}
67+
"SCCACHE_DIR=$env:LOCALAPPDATA\Mozilla\sccache" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
68+
69+
# -----------------------------------------------------------------------
70+
# Compiler cache
71+
# -----------------------------------------------------------------------
72+
- name: ccache (Linux)
73+
if: runner.os == 'Linux'
74+
uses: actions/cache@v4
75+
with:
76+
path: ~/.cache/ccache
77+
key: ${{ runner.os }}-advanced-gltf-ccache-${{ github.sha }}
78+
restore-keys: ${{ runner.os }}-advanced-gltf-ccache-
79+
80+
- name: sccache (Windows)
81+
if: runner.os == 'Windows'
82+
uses: actions/cache@v4
83+
with:
84+
path: ${{ env.SCCACHE_DIR }}
85+
key: ${{ runner.os }}-advanced-gltf-sccache-${{ github.sha }}
86+
restore-keys: ${{ runner.os }}-advanced-gltf-sccache-
87+
88+
# -----------------------------------------------------------------------
89+
# Vulkan SDK — provides slangc + headers; reuses same cache keys as
90+
# simple_engine_ci so the two workflows share cached SDK tarballs.
91+
# -----------------------------------------------------------------------
92+
- name: Cache Vulkan SDK (Windows)
93+
if: runner.os == 'Windows'
94+
id: cache-vulkan-windows
95+
uses: actions/cache@v4
96+
with:
97+
path: C:\VulkanSDK
98+
key: ${{ runner.os }}-vulkan-sdk
99+
100+
- name: Install Vulkan SDK (Windows)
101+
if: runner.os == 'Windows'
102+
shell: pwsh
103+
run: |
104+
$ErrorActionPreference = 'Stop'
105+
if ("${{ steps.cache-vulkan-windows.outputs.cache-hit }}" -ne "true") {
106+
choco install -y aria2
107+
$installer = Join-Path $env:TEMP "vulkan-sdk.exe"
108+
aria2c --split=8 --max-connection-per-server=8 --min-split-size=1M `
109+
--dir="$env:TEMP" --out="vulkan-sdk.exe" `
110+
"https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-sdk.exe"
111+
Start-Process -FilePath $installer `
112+
-ArgumentList "--accept-licenses --default-answer --confirm-command install" `
113+
-Wait -NoNewWindow
114+
}
115+
$vulkanPath = Get-ChildItem "C:\VulkanSDK" |
116+
Sort-Object Name -Descending | Select-Object -First 1 -ExpandProperty FullName
117+
"VULKAN_SDK=$vulkanPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
118+
"$vulkanPath\Bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
119+
"CMAKE_PREFIX_PATH=$vulkanPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
120+
"Vulkan_INCLUDE_DIR=$vulkanPath\Include" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
121+
"Vulkan_LIBRARY=$vulkanPath\Lib\vulkan-1.lib" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
122+
123+
- name: Cache Vulkan SDK (Linux)
124+
if: runner.os == 'Linux'
125+
id: cache-vulkan-linux
126+
uses: actions/cache@v4
127+
with:
128+
path: ${{ runner.temp }}/VulkanSDK
129+
key: ${{ runner.os }}-vulkan-sdk
130+
131+
- name: Install Vulkan SDK (Linux)
132+
if: runner.os == 'Linux'
133+
shell: bash
134+
run: |
135+
set -euo pipefail
136+
SDK_DIR="${RUNNER_TEMP}/VulkanSDK"
137+
138+
if [ "${{ steps.cache-vulkan-linux.outputs.cache-hit }}" != "true" ]; then
139+
SDK_TGZ="${RUNNER_TEMP}/vulkan-sdk.tar.xz"
140+
download_ok=0
141+
for url in \
142+
"https://sdk.lunarg.com/sdk/download/latest/linux/vulkan-sdk.tar.xz" \
143+
"https://sdk.lunarg.com/sdk/download/latest/linux/vulkansdk-linux-x86_64.tar.xz"
144+
do
145+
if curl -L --fail -o "$SDK_TGZ" "$url"; then
146+
download_ok=1; break
147+
fi
148+
done
149+
[ "$download_ok" -eq 1 ] || { echo "Vulkan SDK download failed" >&2; exit 1; }
150+
rm -rf "$SDK_DIR"; mkdir -p "$SDK_DIR"
151+
tar -xJf "$SDK_TGZ" -C "$SDK_DIR"
152+
fi
153+
154+
VULKAN_SDK_PATH="$(find "$SDK_DIR" -maxdepth 1 -type d -name '1.*' | sort -r | head -n 1)"
155+
SDK_SYSROOT="$VULKAN_SDK_PATH"
156+
[ -d "$VULKAN_SDK_PATH/x86_64" ] && SDK_SYSROOT="$VULKAN_SDK_PATH/x86_64"
157+
158+
echo "VULKAN_SDK=$VULKAN_SDK_PATH" >> "$GITHUB_ENV"
159+
echo "VULKAN_SDK_SYSROOT=$SDK_SYSROOT" >> "$GITHUB_ENV"
160+
echo "CMAKE_PREFIX_PATH=$SDK_SYSROOT" >> "$GITHUB_ENV"
161+
echo "Vulkan_INCLUDE_DIR=$SDK_SYSROOT/include" >> "$GITHUB_ENV"
162+
163+
for libname in libvulkan.so libvulkan.so.1; do
164+
if [ -f "$SDK_SYSROOT/lib/$libname" ]; then
165+
echo "Vulkan_LIBRARY=$SDK_SYSROOT/lib/$libname" >> "$GITHUB_ENV"; break
166+
fi
167+
done
168+
169+
[ -d "$VULKAN_SDK_PATH/bin" ] && echo "$VULKAN_SDK_PATH/bin" >> "$GITHUB_PATH"
170+
[ -d "$SDK_SYSROOT/bin" ] && echo "$SDK_SYSROOT/bin" >> "$GITHUB_PATH"
171+
172+
if command -v slangc >/dev/null 2>&1; then
173+
echo "SLANGC_EXECUTABLE=$(command -v slangc)" >> "$GITHUB_ENV"
174+
fi
175+
176+
compat_dir="${RUNNER_TEMP}/slang-compat"
177+
mkdir -p "$compat_dir"
178+
pthread_path="$(ldconfig -p | awk '/libpthread\.so\.0/{print $NF; exit 0}' || true)"
179+
if [ -n "${pthread_path:-}" ] && [ -f "$pthread_path" ]; then
180+
ln -sf "$pthread_path" "$compat_dir/libpthread.so"
181+
fi
182+
echo "LD_LIBRARY_PATH=$compat_dir:${SDK_SYSROOT}/lib:${VULKAN_SDK_PATH}/lib:${LD_LIBRARY_PATH:-}" >> "$GITHUB_ENV"
183+
184+
# -----------------------------------------------------------------------
185+
# simple_engine system dependencies
186+
# The advanced_gltf project links against SimpleEngineLib which is built
187+
# from simple_engine's sources, so we need the same library dependencies.
188+
# -----------------------------------------------------------------------
189+
- name: Install simple_engine dependencies (Linux)
190+
if: runner.os == 'Linux'
191+
shell: bash
192+
run: bash ../simple_engine/install_dependencies_linux.sh
193+
194+
- name: Set up vcpkg (Windows)
195+
if: runner.os == 'Windows'
196+
shell: pwsh
197+
run: |
198+
$vcpkgRoot = "C:\vcpkg"
199+
if (-not (Test-Path $vcpkgRoot)) {
200+
git clone https://github.com/microsoft/vcpkg.git $vcpkgRoot
201+
& "$vcpkgRoot\bootstrap-vcpkg.bat" -disableMetrics
202+
}
203+
"$vcpkgRoot" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
204+
"VCPKG_ROOT=$vcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
205+
206+
- name: Install simple_engine dependencies (Windows)
207+
if: runner.os == 'Windows'
208+
shell: cmd
209+
run: call ..\simple_engine\install_dependencies_windows.bat
210+
211+
# -----------------------------------------------------------------------
212+
# FetchContent dependency cache (Jolt only; simple_engine deps are system-installed)
213+
# -----------------------------------------------------------------------
214+
- name: Cache FetchContent (Linux)
215+
if: runner.os == 'Linux'
216+
uses: actions/cache@v4
217+
with:
218+
path: attachments/advanced_gltf/build/_deps
219+
key: ${{ runner.os }}-advanced-gltf-deps-v1
220+
restore-keys: ${{ runner.os }}-advanced-gltf-deps-
221+
222+
- name: Cache FetchContent (Windows)
223+
if: runner.os == 'Windows'
224+
uses: actions/cache@v4
225+
with:
226+
path: attachments/advanced_gltf/build/_deps
227+
key: ${{ runner.os }}-advanced-gltf-deps-v1
228+
restore-keys: ${{ runner.os }}-advanced-gltf-deps-
229+
230+
# -----------------------------------------------------------------------
231+
# Configure
232+
# -----------------------------------------------------------------------
233+
- name: Configure (Linux)
234+
if: runner.os == 'Linux'
235+
shell: bash
236+
run: |
237+
set -euo pipefail
238+
extra_args=()
239+
[ -n "${Vulkan_INCLUDE_DIR:-}" ] && extra_args+=("-DVulkan_INCLUDE_DIR=${Vulkan_INCLUDE_DIR}")
240+
[ -n "${Vulkan_LIBRARY:-}" ] && extra_args+=("-DVulkan_LIBRARY=${Vulkan_LIBRARY}")
241+
[ -n "${SLANGC_EXECUTABLE:-}" ] && extra_args+=("-DSLANGC_EXECUTABLE=${SLANGC_EXECUTABLE}")
242+
243+
cmake -S . -B build -G Ninja \
244+
-DCMAKE_BUILD_TYPE=Release \
245+
-DCMAKE_C_COMPILER=clang \
246+
-DCMAKE_CXX_COMPILER=clang++ \
247+
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
248+
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
249+
-DCMAKE_PREFIX_PATH="${VULKAN_SDK_SYSROOT:-}" \
250+
"${extra_args[@]}"
251+
252+
- name: Configure (Windows)
253+
if: runner.os == 'Windows'
254+
shell: pwsh
255+
run: |
256+
$extra = @()
257+
if ($env:Vulkan_INCLUDE_DIR) { $extra += "-DVulkan_INCLUDE_DIR=$env:Vulkan_INCLUDE_DIR" }
258+
if ($env:Vulkan_LIBRARY) { $extra += "-DVulkan_LIBRARY=$env:Vulkan_LIBRARY" }
259+
if ($env:VCPKG_ROOT) { $extra += "-DCMAKE_TOOLCHAIN_FILE=$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" }
260+
261+
cmake -S . -B build -G Ninja `
262+
-DCMAKE_BUILD_TYPE=Release `
263+
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache `
264+
-DCMAKE_C_COMPILER_LAUNCHER=sccache `
265+
$extra
266+
267+
# -----------------------------------------------------------------------
268+
# Build — the tutorial executable + all shader compilation targets
269+
# -----------------------------------------------------------------------
270+
- name: Build
271+
run: cmake --build build --target AdvancedGLTF --parallel 4
272+
273+
- name: Verify shaders compiled
274+
shell: bash
275+
run: |
276+
set -euo pipefail
277+
missing=0
278+
for spv in \
279+
build/shaders/skinning.spv \
280+
build/shaders/morph_accumulate.spv \
281+
build/shaders/pbr_heatmap_vertex.spv \
282+
"build/shaders/pbr_heatmap_fragment_dominant_bone.spv" \
283+
"build/shaders/pbr_heatmap_fragment_weight_distribution.spv"
284+
do
285+
if [ -f "$spv" ]; then
286+
echo " OK $spv"
287+
else
288+
echo " MISSING $spv" >&2
289+
missing=$((missing + 1))
290+
fi
291+
done
292+
[ "$missing" -eq 0 ] || { echo "$missing shader(s) missing" >&2; exit 1; }
293+
294+
- name: Cache stats
295+
if: always()
296+
shell: bash
297+
run: |
298+
command -v ccache >/dev/null 2>&1 && ccache -s || true
299+
command -v sccache >/dev/null 2>&1 && sccache -s || true
300+
301+
# ---------------------------------------------------------------------------
302+
# Validate Python asset tool (no deps beyond stdlib)
303+
# ---------------------------------------------------------------------------
304+
validate-python-tool:
305+
name: Validate add_physics_extras.py
306+
runs-on: ubuntu-latest
307+
steps:
308+
- name: Checkout
309+
uses: actions/checkout@v4
310+
311+
- name: Syntax check
312+
run: python3 -m py_compile attachments/advanced_gltf/assets/add_physics_extras.py
313+
314+
- name: Download SimpleSkin and annotate
315+
shell: bash
316+
run: |
317+
set -euo pipefail
318+
# Fetch a minimal CC0 glTF that has a skin (SimpleSkin from Khronos samples)
319+
curl -fsSL \
320+
"https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Assets/main/Models/SimpleSkin/glTF/SimpleSkin.gltf" \
321+
-o /tmp/SimpleSkin.gltf
322+
323+
python3 attachments/advanced_gltf/assets/add_physics_extras.py \
324+
/tmp/SimpleSkin.gltf \
325+
/tmp/SimpleSkin_physics.gltf
326+
327+
# Verify extras were written
328+
python3 -c "
329+
import json, sys
330+
with open('/tmp/SimpleSkin_physics.gltf') as f:
331+
g = json.load(f)
332+
joints = set()
333+
for skin in g.get('skins', []):
334+
joints.update(skin.get('joints', []))
335+
for idx in joints:
336+
node = g['nodes'][idx]
337+
extras = node.get('extras', {})
338+
if 'collider' not in extras:
339+
sys.exit(f'Node {idx} ({node.get(\"name\",\"?\")}) missing collider extras')
340+
if 'constraint' not in extras:
341+
sys.exit(f'Node {idx} ({node.get(\"name\",\"?\")}) missing constraint extras')
342+
print(f'All {len(joints)} joint(s) annotated correctly.')
343+
"

REUSE.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ path = [
7070
"attachments/simple_engine/**",
7171
"attachments/ml_inference/**",
7272
"attachments/compute/**",
73+
"attachments/advanced_gltf/**",
7374
"en/Synchronization/**",
7475
"en/ML_Inference/**",
76+
"en/Advanced_glTF/**",
7577
"en/AI_Assisted_Vulkan/**",
7678
"en/Advanced_Vulkan_Compute/**",
7779
"scripts/**",

0 commit comments

Comments
 (0)