diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index b8116ed5d..16e12106b 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -44,7 +44,7 @@ jobs: # grl-snam-weights lands here; --preload-file bakes the trained CoefMLP into # nav_city_swarm.data so the browser swarm drives with the published policy. CVC_WASM_NAV_WEIGHTS: /opt/cvc-wasm/deps-wasm-mt/share/grl-snam-weights/coef_sdf.cvcnav - DEMOS: 'terrain_lab lsystem_forest lsystem_coast volren_bunny volslice_bunny nav_city_swarm nav_city_drive nav_fog_ghost' + DEMOS: 'terrain_lab lsystem_forest lsystem_coast volren_bunny volren_bunny_ari volslice_bunny volslice_bunny_ari nav_city_swarm nav_city_drive nav_fog_ghost' steps: - name: Checkout master uses: actions/checkout@v4 diff --git a/src/cvcGL/examples/CMakeLists.txt b/src/cvcGL/examples/CMakeLists.txt index 6fdac1a48..9c3b8e551 100644 --- a/src/cvcGL/examples/CMakeLists.txt +++ b/src/cvcGL/examples/CMakeLists.txt @@ -124,6 +124,24 @@ endif() if(EMSCRIPTEN) set(_wasm_demos lsystem_forest lsystem_coast terrain_lab bunny_shadow volren_bunny volslice_bunny nav_city_swarm nav_city_drive nav_fog_ghost) set(_wasm_extra_demos ariadne_hello) + + # Ariadne (.ari) demos as wasm: build the generic ariadne_hello host once per document, with that + # .ari baked in as the default doc (CVC_ARIADNE_WASM_DOC) and the shared component library embedded + # in MEMFS (--embed-file), so a pure-DSL demo runs in the browser with no argv. Distinct slugs + # (_ari) so they sit ALONGSIDE the C++ volren_bunny/volslice_bunny demos, not replacing them. + # This is also the path for every future .ari demo (A/V, lsystem, …) to reach the web gallery. + get_filename_component(_CVC_ARIADNE_COMPONENTS + "${CMAKE_CURRENT_SOURCE_DIR}/../../cvc/ariadne/components" ABSOLUTE) + foreach(_ari volren_bunny volslice_bunny) + add_executable(${_ari}_ari ariadne_hello.cpp) + target_link_libraries(${_ari}_ari PRIVATE cvcGL ${VTK_LIBRARIES}) + vtk_module_autoinit(TARGETS ${_ari}_ari MODULES ${VTK_LIBRARIES}) + target_compile_definitions(${_ari}_ari PRIVATE CVC_ARIADNE_WASM_DOC="/${_ari}.ari") + target_link_options(${_ari}_ari PRIVATE + "--embed-file=${CMAKE_CURRENT_SOURCE_DIR}/${_ari}.ari@/${_ari}.ari" + "--embed-file=${_CVC_ARIADNE_COMPONENTS}@/components") + list(APPEND _wasm_demos ${_ari}_ari) + endforeach() # Optional runtime asset bundle for nav_city_swarm (Austin: terrain.json + # buildings.glb + satellite.png). When CVC_WASM_BUNDLE is set to a scene dir, # its contents are preloaded to /bundle and, if the sibling shared/Humvee.glb diff --git a/src/cvcGL/examples/ariadne_hello.cpp b/src/cvcGL/examples/ariadne_hello.cpp index d9c5a4b19..ae2ebe9cb 100644 --- a/src/cvcGL/examples/ariadne_hello.cpp +++ b/src/cvcGL/examples/ariadne_hello.cpp @@ -17,6 +17,9 @@ #include #include #include +#ifdef __EMSCRIPTEN__ +#include // emscripten_sleep — yield the asyncify main loop to the browser +#endif #include #include #include // register_cvc_uri_handler — the cvc:// component-library import path @@ -76,6 +79,16 @@ int main(int argc, char **argv) { else if (a[0] != '-' && docPath.empty()) docPath = a; } + // A wasm demo build bakes in its own .ari (CVC_ARIADNE_WASM_DOC) and embeds the component library + // in MEMFS (see the examples CMake --embed-file). With no argv in the browser, default to that + // doc and add the MEMFS root to the search path so `cvc://components/*.ari` resolves at + // /components. +#ifdef CVC_ARIADNE_WASM_DOC + if (docPath.empty()) { + docPath = CVC_ARIADNE_WASM_DOC; + componentPaths.push_back("/"); + } +#endif // The cvc:// component-library import path (import: cvc://components/foo.ari), resolved against // CVC_ARIADNE_PATH + any --component-path dirs + the install datadir + cwd. Register before load. cvc::ariadne::register_cvc_uri_handler(componentPaths); diff --git a/src/cvcGL/examples/wasm/build-wasm-demo.sh b/src/cvcGL/examples/wasm/build-wasm-demo.sh index a11b1baad..11a23fca9 100755 --- a/src/cvcGL/examples/wasm/build-wasm-demo.sh +++ b/src/cvcGL/examples/wasm/build-wasm-demo.sh @@ -74,6 +74,42 @@ EOF_EMCFG echo "build-wasm-demo: shared emsdk cache not writable by $(id -un); using seeded per-user cache ${_em_cache}" fi +# yaml-cpp for wasm — the Ariadne .ari loader's only extra dependency (src/cvc/ +# CMakeLists.txt: find_package(yaml-cpp) → CVC_ARIADNE_HAVE_YAML). It is NOT in +# the cvcpkg wasm catalog (published linux/macos/win/bsd only), so without this +# the loader silently compiles to a stub and the .ari demos (volren_bunny_ari, +# volslice_bunny_ari) deploy BLANK. Build it from the pinned upstream tarball +# into CVC_WASM_DEPS, STATIC, and pthread-matched to the module so the emscripten +# link doesn't reject mixed -pthread objects. Idempotent: skipped once installed. +if [ ! -f "${CVC_WASM_DEPS}/lib/cmake/yaml-cpp/yaml-cpp-config.cmake" ] \ + && [ ! -f "${CVC_WASM_DEPS}/share/cmake/yaml-cpp/yaml-cpp-config.cmake" ]; then + echo "build-wasm-demo: yaml-cpp not in ${CVC_WASM_DEPS}; building it for wasm from source" + _yc_ver=0.8.0 + _yc_sha=fbe74bbdcee21d656715688706da3c8becfd946d92cd44705cc6098bb23b3a16 + _yc_work="${BUILD_DIR}/_yaml-cpp" + _yc_src="${_yc_work}/yaml-cpp-${_yc_ver}" + _yc_tar="${_yc_work}/yaml-cpp-${_yc_ver}.tar.gz" + mkdir -p "${_yc_work}" + if [ ! -d "${_yc_src}" ]; then + curl -fL "https://github.com/jbeder/yaml-cpp/archive/refs/tags/${_yc_ver}.tar.gz" \ + -o "${_yc_tar}" + echo "${_yc_sha} ${_yc_tar}" | sha256sum -c - + tar -xzf "${_yc_tar}" -C "${_yc_work}" + fi + _yc_pthread="" + [[ "${PTHREAD}" == "ON" ]] && _yc_pthread="-pthread" + emcmake cmake -G Ninja -S "${_yc_src}" -B "${_yc_work}/build" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="${CVC_WASM_DEPS}" \ + -DYAML_CPP_BUILD_TESTS=OFF \ + -DYAML_CPP_BUILD_TOOLS=OFF \ + -DYAML_CPP_BUILD_CONTRIB=OFF \ + -DYAML_BUILD_SHARED_LIBS=OFF \ + -DCMAKE_CXX_FLAGS="${_yc_pthread}" \ + -DCMAKE_C_FLAGS="${_yc_pthread}" + cmake --build "${_yc_work}/build" --target install +fi + emcmake cmake -G Ninja -S "${REPO_ROOT}" -B "${BUILD_DIR}" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_FIND_ROOT_PATH="${CVC_WASM_DEPS}" \ diff --git a/src/cvcGL/examples/wasm/demos.json b/src/cvcGL/examples/wasm/demos.json index b82acab4b..812c47310 100644 --- a/src/cvcGL/examples/wasm/demos.json +++ b/src/cvcGL/examples/wasm/demos.json @@ -6,7 +6,9 @@ "lsystem_forest", "lsystem_coast", "volren_bunny", + "volren_bunny_ari", "volslice_bunny", + "volslice_bunny_ari", "nav_city_swarm", "nav_city_drive", "nav_fog_ghost", @@ -66,6 +68,18 @@ "blurb": "The classic view-aligned slice compositor from VolumeRover2, ported to cvc::volslice: the bunny's signed-distance volume windowed into a byte texture and colored by a 256-entry transfer function, hundreds of camera-facing slices blended back to front. Add up to nine bunnies — each is its own scene-graph volume node, depth-sorted per frame — and drive quality, near-plane peel, the value window and spacing-corrected opacity live in the panel.", "thumb": "img/volslice_bunny.jpg" + }, + "volren_bunny_ari": { + "desc": "the volren bunny, built entirely in the Ariadne UI DSL (.ari)", + "blurb": + "The same CPU-raycast bunny, rebuilt in the Ariadne UI DSL: the scene, lighting rig and raycast control panel are all declared in one .ari document — no demo-specific C++, just the generic host. The volume is computed live as the signed distance field of the embedded Stanford mesh via a single DSL source (source: { sdf: { mesh } }), and the controls are reusable .ari components shared with the other bunny demos.", + "thumb": "img/volren_bunny_ari.jpg" + }, + "volslice_bunny_ari": { + "desc": "the volslice bunny, built entirely in the Ariadne UI DSL (.ari)", + "blurb": + "The slice-based bunny, rebuilt in the Ariadne UI DSL: scene, transfer function, lighting and the slice control panel declared in one .ari document, driven by the generic host — no demo-specific C++. The volume is the signed distance field of the embedded Stanford mesh (source: { sdf: { mesh } }), and the controls are reusable .ari components.", + "thumb": "img/volslice_bunny_ari.jpg" } } } diff --git a/src/cvcGL/examples/wasm/gallery-assets/img/volren_bunny_ari.jpg b/src/cvcGL/examples/wasm/gallery-assets/img/volren_bunny_ari.jpg new file mode 100644 index 000000000..c6ca954b2 Binary files /dev/null and b/src/cvcGL/examples/wasm/gallery-assets/img/volren_bunny_ari.jpg differ diff --git a/src/cvcGL/examples/wasm/gallery-assets/img/volslice_bunny_ari.jpg b/src/cvcGL/examples/wasm/gallery-assets/img/volslice_bunny_ari.jpg new file mode 100644 index 000000000..aa35f5c7e Binary files /dev/null and b/src/cvcGL/examples/wasm/gallery-assets/img/volslice_bunny_ari.jpg differ