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
56 changes: 52 additions & 4 deletions .github/workflows/ost-source-ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Generated by `ost ci generate github` from openstrata.ci.yaml.
# Regenerate after editing the matrix; do not edit the jobs by hand.
# Generated by `ost ci generate github` from openstrata.ci.yaml, then extended
# with the repository-specific Jolt setup documented below. Regenerate after
# editing the matrix and reapply that setup before committing the workflow.
#
# Source CI: each job checks out the repo, obtains a digest-pinned runtime
# SDK artifact, and builds/tests/packages the bundle from source. On
Expand All @@ -11,6 +12,9 @@
#
# Fork-PR safety: this workflow never publishes, never promotes, and uses no
# secrets; keep it that way when editing the matrix.
#
# Repository additions retained after regeneration: build pinned Jolt beside
# the workspace and expose its install prefix to the generated `jolt` intent.
name: ost source ci

on:
Expand Down Expand Up @@ -166,7 +170,7 @@ jobs:
hosted: true
runner_profile: windows-hosted
verify: test
intent_flags: ""
intent_flags: "--intent jolt"
runtime_remote: "oci://ghcr.io/animu-sphere/openstrata-runtime-cy2026-usd@sha256:d3ff79a6f330558c3b9a427a927d340fe3dcab1fe89107faa0ea9f66a104b7bf"
host_python: "3.13"
host_packages_apt: ""
Expand All @@ -187,14 +191,54 @@ jobs:
hosted: true
runner_profile: linux-hosted
verify: test
intent_flags: ""
intent_flags: "--intent jolt"
runtime_remote: "oci://ghcr.io/animu-sphere/openstrata-runtime-cy2026-usd@sha256:8d2d599489ee623044f4360ad3a2b979e2966e6ad2f949e5aa9083570e59cc4f"
host_python: "3.13"
host_packages_apt: "libx11-dev libxt-dev"
host_packages_brew: ""
steps:
- name: Check out the repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Check out pinned Jolt Physics 5.5.0
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: jrouwe/JoltPhysics
ref: 23dadd0e603f1b321142d4c74df07fce85064989
path: .ci/jolt
- name: Build and install pinned Jolt Physics
shell: bash
run: |
set -euo pipefail
prefix="$GITHUB_WORKSPACE/.ci/jolt-install"
configure=(
-S .ci/jolt/Build
-B .ci/jolt-build
"-DCMAKE_INSTALL_PREFIX=$prefix"
-DCMAKE_BUILD_TYPE=Release
-DINTERPROCEDURAL_OPTIMIZATION=OFF
-DDOUBLE_PRECISION=OFF
-DCROSS_PLATFORM_DETERMINISTIC=OFF
-DENABLE_ALL_WARNINGS=OFF
-DGENERATE_DEBUG_SYMBOLS=OFF
-DDEBUG_RENDERER_IN_DEBUG_AND_RELEASE=OFF
-DPROFILER_IN_DEBUG_AND_RELEASE=OFF
-DUSE_STATIC_MSVC_RUNTIME_LIBRARY=OFF
-DTARGET_UNIT_TESTS=OFF
-DTARGET_HELLO_WORLD=OFF
-DTARGET_PERFORMANCE_TEST=OFF
-DTARGET_SAMPLES=OFF
-DTARGET_VIEWER=OFF
)
if [ "$RUNNER_OS" = "Windows" ]; then
configure+=(-A x64)
fi
cmake "${configure[@]}"
cmake --build .ci/jolt-build --config Release --target Jolt
cmake --install .ci/jolt-build --config Release
if [ "$RUNNER_OS" = "Windows" ]; then
prefix="$(cygpath -w "$prefix")"
fi
echo "JOLT_PREFIX=$prefix" >> "$GITHUB_ENV"
- name: Hosted runner billing notice
if: ${{ matrix.hosted }}
shell: bash
Expand Down Expand Up @@ -388,10 +432,14 @@ jobs:
run: ost plugin test --workspace --graph-only --json
- name: Build the workspace from source
shell: bash
env:
CMAKE_PREFIX_PATH: ${{ env.JOLT_PREFIX }}
run: ost build --target ${{ matrix.platform }} --profile ${{ matrix.profile }} ${{ matrix.intent_flags }}
- name: Run the workspace test suite
if: ${{ matrix.verify != 'build' }}
shell: bash
env:
CMAKE_PREFIX_PATH: ${{ env.JOLT_PREFIX }}
run: ost test --target ${{ matrix.platform }} --profile ${{ matrix.profile }} ${{ matrix.intent_flags }}
- name: Run the workspace verification pyramid
if: ${{ matrix.verify == 'pyramid' || matrix.verify == 'package' }}
Expand Down
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ usdphysics_assert_target_dependencies(
usdphysics_assert_target_dependencies(
TARGET physicsJolt
ALLOWED_PUBLIC physicsCore::physicsCore
ALLOWED_PRIVATE physicsCore::physicsCore)
"$<LINK_ONLY:Jolt::Jolt>"
"$<LINK_ONLY:Jolt>"
ALLOWED_PRIVATE physicsCore::physicsCore Jolt::Jolt Jolt)

if(USDPHYSICS_BUILD_TESTS)
add_subdirectory(tests)
Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

Backend-neutral physics runtime components for OpenUSD-based applications.

> **Status: Phase 1 core extraction complete.** The repository builds and
> installs `physicsCore` and `physicsJolt`; neutral rigid-transform values,
> typed handles, validated box/body/fixed-constraint descriptors, the
> single-owner world contract, and optional segment and ground queries are
> implemented. An OpenUSD bridge and a solver backend are not. The
> **Status (2026-09-23): Phase 2 backend extraction in progress.** The
> repository builds and installs `physicsCore` and `physicsJolt`; the neutral
> core contract and a Jolt-backed world with fixed stepping, changed state,
> segment queries, and ground queries are implemented. The Jolt-required
> OpenStrata intent passes
> locally; hosted Phase 2 evidence and an OpenUSD bridge remain. The
> [capability matrix](docs/reference/CAPABILITY_MATRIX.md) is the only page
> that states what exists, and the [current roadmap](docs/roadmap/current.md)
> states what comes next.
Expand Down Expand Up @@ -57,7 +58,7 @@ their backend.
| Component | Kind | Role | State |
| --- | --- | --- | --- |
| `physicsCore` | plain C++ library | Handles, descriptors, world lifecycle, state, and optional query contracts; no OpenUSD and no backend SDK | Phase 1 contract implemented and installed |
| `physicsJolt` | plain C++ library | First rigid-body backend implementing `physicsCore` | package scaffold present; backend unavailable |
| `physicsJolt` | plain C++ library | First rigid-body backend implementing `physicsCore` | Phase 2 implementation present; hosted evidence pending |
| `physicsUsd` | OpenUSD-facing C++ library | Translate standard `UsdPhysics` declarations to runtime descriptors and maintain transient prim/resource mappings | planned |
| `secondaryMotion` | plain C++ library | Solver-neutral spring-chain and collider contracts | deferred until the rigid-body boundary is extracted |
| `secondaryMotionVerlet` | plain C++ library | First deterministic CPU secondary-motion solver | deferred until a real VRM integration slice requires it |
Expand Down
42 changes: 40 additions & 2 deletions backends/physicsJolt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ endif()

project(physicsJolt
VERSION ${_physics_jolt_version}
DESCRIPTION "Jolt backend package scaffold for physicsCore"
DESCRIPTION "Jolt Physics backend for physicsCore"
LANGUAGES CXX)

if(NOT DEFINED PHYSICSJOLT_BUILD_TESTS)
Expand All @@ -27,7 +27,41 @@ if(NOT TARGET physicsCore::physicsCore)
find_package(physicsCore CONFIG REQUIRED)
endif()

add_library(physicsJolt STATIC src/availability.cpp)
option(PHYSICSJOLT_REQUIRE_JOLT
"Fail configuration when Jolt Physics is unavailable" OFF)

set(PHYSICSJOLT_BACKEND_TARGET "")
find_package(Jolt CONFIG QUIET)
if(TARGET Jolt::Jolt)
set(PHYSICSJOLT_BACKEND_TARGET Jolt::Jolt)
elseif(TARGET Jolt)
set(PHYSICSJOLT_BACKEND_TARGET Jolt)
endif()

if(PHYSICSJOLT_REQUIRE_JOLT AND NOT PHYSICSJOLT_BACKEND_TARGET)
message(FATAL_ERROR
"physicsJolt requires Jolt Physics 5.5.0, but no Jolt CMake target was found")
endif()

if(PHYSICSJOLT_BACKEND_TARGET)
set(_physics_jolt_source src/jolt_world.cpp)
set(_physics_jolt_backend_label "${PHYSICSJOLT_BACKEND_TARGET}")
set(PHYSICSJOLT_BACKEND_AVAILABLE ON)
set(PHYSICSJOLT_FIND_JOLT_DEPENDENCY "find_dependency(Jolt CONFIG)")
get_target_property(PHYSICSJOLT_JOLT_INTERFACE_COMPILE_DEFINITIONS
${PHYSICSJOLT_BACKEND_TARGET} INTERFACE_COMPILE_DEFINITIONS)
if(PHYSICSJOLT_JOLT_INTERFACE_COMPILE_DEFINITIONS MATCHES "-NOTFOUND$")
set(PHYSICSJOLT_JOLT_INTERFACE_COMPILE_DEFINITIONS "")
endif()
else()
set(_physics_jolt_source src/availability.cpp)
set(_physics_jolt_backend_label "unavailable")
set(PHYSICSJOLT_BACKEND_AVAILABLE OFF)
set(PHYSICSJOLT_FIND_JOLT_DEPENDENCY "")
set(PHYSICSJOLT_JOLT_INTERFACE_COMPILE_DEFINITIONS "")
endif()

add_library(physicsJolt STATIC ${_physics_jolt_source})
add_library(physicsJolt::physicsJolt ALIAS physicsJolt)
set_target_properties(physicsJolt PROPERTIES
EXPORT_NAME physicsJolt
Expand All @@ -37,6 +71,10 @@ target_include_directories(physicsJolt PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:include>")
target_link_libraries(physicsJolt PUBLIC physicsCore::physicsCore)
if(PHYSICSJOLT_BACKEND_TARGET)
target_link_libraries(physicsJolt PRIVATE ${PHYSICSJOLT_BACKEND_TARGET})
endif()
message(STATUS "physicsJolt: backend ${_physics_jolt_backend_label}")

include(GNUInstallDirs)
install(TARGETS physicsJolt
Expand Down
62 changes: 62 additions & 0 deletions backends/physicsJolt/cmake/physicsJoltConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,67 @@ include(CMakeFindDependencyMacro)
if(NOT TARGET physicsCore::physicsCore)
find_dependency(physicsCore CONFIG)
endif()
@PHYSICSJOLT_FIND_JOLT_DEPENDENCY@

set(_physicsJolt_requires_jolt @PHYSICSJOLT_BACKEND_AVAILABLE@)
if(_physicsJolt_requires_jolt)
set(_physicsJolt_jolt_target [==[@PHYSICSJOLT_BACKEND_TARGET@]==])
if(NOT TARGET "${_physicsJolt_jolt_target}")
message(FATAL_ERROR
"physicsJolt requires the Jolt target '${_physicsJolt_jolt_target}'")
endif()

get_target_property(_physicsJolt_actual_jolt_definitions
"${_physicsJolt_jolt_target}" INTERFACE_COMPILE_DEFINITIONS)
if(_physicsJolt_actual_jolt_definitions MATCHES "-NOTFOUND$")
set(_physicsJolt_actual_jolt_definitions "")
endif()
set(_physicsJolt_expected_jolt_definitions
[==[@PHYSICSJOLT_JOLT_INTERFACE_COMPILE_DEFINITIONS@]==])
if(NOT "${_physicsJolt_actual_jolt_definitions}" STREQUAL
"${_physicsJolt_expected_jolt_definitions}")
message(FATAL_ERROR
"physicsJolt found a Jolt package with incompatible ABI compile definitions")
endif()

get_target_property(_physicsJolt_jolt_includes
"${_physicsJolt_jolt_target}" INTERFACE_INCLUDE_DIRECTORIES)
set(_physicsJolt_jolt_core_header "")
foreach(_physicsJolt_include IN LISTS _physicsJolt_jolt_includes)
if(NOT _physicsJolt_include MATCHES "^\\$<" AND
EXISTS "${_physicsJolt_include}/Jolt/Core/Core.h")
set(_physicsJolt_jolt_core_header
"${_physicsJolt_include}/Jolt/Core/Core.h")
break()
endif()
endforeach()
if(NOT _physicsJolt_jolt_core_header)
message(FATAL_ERROR
"physicsJolt could not verify the discovered Jolt package version")
endif()
file(STRINGS "${_physicsJolt_jolt_core_header}"
_physicsJolt_jolt_version_lines
REGEX "^#[ \t]*define[ \t]+JPH_VERSION_(MAJOR|MINOR|PATCH)[ \t]+[0-9]+")
foreach(_physicsJolt_required_version IN ITEMS
"JPH_VERSION_MAJOR 5"
"JPH_VERSION_MINOR 5"
"JPH_VERSION_PATCH 0")
string(REPLACE " " "[ \\t]+" _physicsJolt_version_pattern
"${_physicsJolt_required_version}")
set(_physicsJolt_version_matches FALSE)
foreach(_physicsJolt_version_line IN LISTS _physicsJolt_jolt_version_lines)
if(_physicsJolt_version_line MATCHES
"${_physicsJolt_version_pattern}([ \\t]|$)")
set(_physicsJolt_version_matches TRUE)
break()
endif()
endforeach()
if(NOT _physicsJolt_version_matches)
message(FATAL_ERROR
"physicsJolt requires Jolt Physics 5.5.0 exactly")
endif()
endforeach()
endif()

include("${CMAKE_CURRENT_LIST_DIR}/physicsJoltTargets.cmake")
check_required_components(physicsJolt)
11 changes: 9 additions & 2 deletions backends/physicsJolt/include/usd_physics/jolt/availability.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
#pragma once

#include "usd_physics/core/world.h"

#include <memory>

namespace usd_physics::jolt {

// Phase 0 installs the package boundary, not a solver. This function remains
// false until the Phase 2 Jolt implementation is linked into this component.
// Reports whether this package was built with its private Jolt dependency.
[[nodiscard]] bool backendAvailable() noexcept;

// Constructs a Jolt-backed world when the backend is available. A package
// built without Jolt throws PhysicsErrorCode::backendUnavailable here.
[[nodiscard]] std::unique_ptr<core::PhysicsWorld> createWorld();

} // namespace usd_physics::jolt
2 changes: 1 addition & 1 deletion backends/physicsJolt/openstrata.library.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ package_contract:
public_headers: [include/usd_physics/jolt/**]
consumer:
include: usd_physics/jolt/availability.h
symbol: usd_physics::jolt::backendAvailable
symbol: usd_physics::jolt::createWorld
7 changes: 7 additions & 0 deletions backends/physicsJolt/src/availability.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
#include "usd_physics/jolt/availability.h"

#include "usd_physics/core/errors.h"

namespace usd_physics::jolt {

bool backendAvailable() noexcept {
return false;
}

std::unique_ptr<core::PhysicsWorld> createWorld() {
throw core::PhysicsError{core::PhysicsErrorCode::backendUnavailable,
"physicsJolt was built without Jolt Physics"};
}

} // namespace usd_physics::jolt
Loading
Loading