ernie-renderer 0.2.0.dev45__tar.gz → 0.2.0.dev47__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ernie-renderer might be problematic. Click here for more details.
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/CMakeLists.txt +1 -1
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/PKG-INFO +1 -1
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/CMakeLists.txt +3 -0
- ernie_renderer-0.2.0.dev47/ernie/scene/animation.cpp +94 -0
- ernie_renderer-0.2.0.dev47/ernie/scene/edit_history.cpp +237 -0
- ernie_renderer-0.2.0.dev47/ernie/scene/edit_history.h +127 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/json.cpp +42 -4
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/json_value.h +2 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/reference.cpp +5 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/scene.cpp +23 -7
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/scene.h +44 -0
- ernie_renderer-0.2.0.dev47/ernie/scene/time_samples.cpp +96 -0
- ernie_renderer-0.2.0.dev47/ernie/scene/time_samples.h +50 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/CMakeLists.txt +2 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/scenes/rover.json +1 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/scenes/rover.saved.json +5 -0
- ernie_renderer-0.2.0.dev47/tests/scene/edit_history_test.cpp +115 -0
- ernie_renderer-0.2.0.dev47/tests/scene/time_samples_test.cpp +101 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/.clang-format +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/.clang-tidy +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/.dockerignore +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/.gersemirc +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/.gitattributes +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/.github/scripts/coverage_badge.py +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/.github/scripts/install-lavapipe-windows.sh +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/.github/workflows/ci.yml +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/.gitignore +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/.pre-commit-config.yaml +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/CMakePresets.json +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/Dockerfile +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/LICENSE +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/README.md +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/benchmarks/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/benchmarks/bench.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/benchmarks/main.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/benchmarks/scene/extents.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/benchmarks/scene/storage.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/ErnieConfig.cmake.in +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/ErnieFetch.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/ErnieInstall.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/ErniePackaging.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/ErnieTesting.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/ernie.pc.in +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/third_party/bc7enc.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/third_party/dlpack.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/third_party/glm.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/third_party/googletest.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/third_party/json.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/third_party/nanobind.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/third_party/openexr.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/third_party/stb.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/third_party/tracy.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/third_party/volk.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/cmake/third_party/vulkan_headers.cmake +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/docs/README.md +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/docs/index.md +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/docs/requirements.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/app/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/app/main.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/device/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/device/vulkan_devices.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/device/vulkan_devices.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/geometry/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/geometry/bounds.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/graph/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/io/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/io/ies.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/io/ies.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/io/image.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/io/image.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/io/nanovdb.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/io/nanovdb.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/io/raster.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/io/raster.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/io/texture.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/io/texture.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/astronomy.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/astronomy.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/atmosphere.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/atmosphere.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/cloud.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/cloud.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/constants.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/reflectance_library.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/reflectance_library.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/reflectance_table.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/regolith.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/regolith.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/scattering.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/scattering.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/solar.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/solar.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/solar_table.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/spectrum.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/physics/spectrum.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/python/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/python/ernie/__init__.py +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/python/module.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/render/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/convert.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/extent_cache.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/extent_cache.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/holder_index.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/holder_index.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/inherit.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/json.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/path.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/path.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/reference.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schema.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schema.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/camera.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/camera.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/collection.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/collection.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/geom.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/geom.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/instancer.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/instancer.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/laser.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/laser.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/lux.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/lux.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/mesh.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/mesh.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/planet.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/planet.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/registry.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/render.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/render.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/shade.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/shade.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/vol.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/schemas/vol.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/storage.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/storage.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/tokens.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/usd_plugin.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/validate.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/value.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/view.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/view.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/xform.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/scene/xform.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/algorithm.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/bytes.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/disk_cache.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/disk_cache.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/file.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/file.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/glm.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/hash_index.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/linear_algebra.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/log.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/log.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/math.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/noise.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/noise.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/numbers.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/parallel.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/profiler.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/profiler.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/random.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/tensor.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/tensor.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/text.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/version.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/version.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/ernie/util/worker_pool.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/mkdocs.yml +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/pyproject.toml +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/common.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/consumer/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/consumer/main.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/device/vulkan_devices_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/exr/README.md +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/exr/make_exr.py +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/exr/rgb_float_zip.exr +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/exr/rgba_half_window.exr +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/exr/y_half_zips.exr +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/ies/README.md +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/ies/downlight_quadrant.ies +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/ies/floodlight_type_b.ies +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/ies/lamp.tilt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/images/grey16.png +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/ktx2/README.md +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/ktx2/quadrants_etc1s.ktx2 +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/ktx2/quadrants_uastc_zstd.ktx2 +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/ktx2/tilted_normal_etc1s.ktx2 +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/ktx2/tilted_normal_uastc.ktx2 +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/scenes/README.md +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/scenes/invalid/problems.expected +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/scenes/invalid/problems.json +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/tiff/README.md +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/tiff/float_deflate_predictor3.tif +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/tiff/float_raw.tif +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/tiff/int16_bigtiff_bigendian.tif +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/tiff/rgb_lzw_predictor2.tif +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/tiff/rgb_planar_lzw.tif +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/tiff/rgb_planar_raw.tif +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/tiff/rgb_tiled_deflate.tif +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/volumes/cube.nvdb +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/fixtures/volumes/make_nvdb.py +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/geometry/bounds_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/io/ies_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/io/image_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/io/nanovdb_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/io/raster_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/io/texture_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/physics/astronomy_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/physics/atmosphere_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/physics/cloud_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/physics/reflectance_library_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/physics/regolith_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/physics/scattering_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/physics/solar_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/physics/spectrum_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/python/test_package.py +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/python/test_scene_schema.py +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/api_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/extent_cache_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/holder_index_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/inherit_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/instancer_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/json_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/lux_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/mesh_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/path_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/planet_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/reference_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/render_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/scene_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/schema_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/shade_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/storage_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/vol_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/scene/xform_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/algorithm_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/bytes_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/disk_cache_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/file_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/hash_index_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/linear_algebra_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/log_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/math_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/noise_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/parallel_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/profiler_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/random_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/tensor_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/text_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/version_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/tests/util/worker_pool_test.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/CMakeLists.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/LICENSE +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/LICENSES/Apache-2.0.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/LICENSES/BSD-3-clause.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/LICENSES/MIT.txt +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/NOTICE +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/README.md +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_astc_cfgs.inl +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_astc_hdr_core.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_astc_helpers.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_containers.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_containers_impl.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_dds_transcoder.inl +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_etc1_mods.inl +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_file_headers.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_idct.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder.cpp +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_internal.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_tables_astc.inc +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_tables_astc_0_255.inc +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_tables_atc_55.inc +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_tables_atc_56.inc +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_tables_bc7_m5_alpha.inc +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_tables_bc7_m5_color.inc +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_tables_dxt1_5.inc +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_tables_dxt1_6.inc +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_tables_pvrtc2_45.inc +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_tables_pvrtc2_alpha_33.inc +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_transcoder_uastc.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_xbc7_decoder.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/transcoder/basisu_xbc7_decoder.inl +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/zstd/LICENSE +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/zstd/zstd.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/basisu/zstd/zstd_errors.h +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/nanovdb/LICENSE +0 -0
- {ernie_renderer-0.2.0.dev45 → ernie_renderer-0.2.0.dev47}/third_party/nanovdb/PNanoVDB.h +0 -0
|
@@ -15,7 +15,7 @@ project(
|
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
# Pre-release suffix such as .dev12, written by CI.
|
|
18
|
-
set(ERNIE_VERSION_SUFFIX ".
|
|
18
|
+
set(ERNIE_VERSION_SUFFIX ".dev47" CACHE STRING "Pre-release suffix of Ernie's version")
|
|
19
19
|
set(ERNIE_VERSION "${PROJECT_VERSION}${ERNIE_VERSION_SUFFIX}")
|
|
20
20
|
|
|
21
21
|
option(ERNIE_BUILD_TESTS "Build Ernie's tests" OFF)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ernie-renderer
|
|
3
|
-
Version: 0.2.0.
|
|
3
|
+
Version: 0.2.0.dev47
|
|
4
4
|
Summary: Efficient Renderer for Natural and Interplanetary Environments: a physically based, spectral Vulkan ray tracer
|
|
5
5
|
Author: Alex Maietta
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
add_library(
|
|
3
3
|
ernie_scene
|
|
4
4
|
OBJECT
|
|
5
|
+
animation.cpp
|
|
6
|
+
edit_history.cpp
|
|
5
7
|
extent_cache.cpp
|
|
6
8
|
holder_index.cpp
|
|
7
9
|
inherit.cpp
|
|
@@ -11,6 +13,7 @@ add_library(
|
|
|
11
13
|
schema.cpp
|
|
12
14
|
scene.cpp
|
|
13
15
|
storage.cpp
|
|
16
|
+
time_samples.cpp
|
|
14
17
|
usd_plugin.cpp
|
|
15
18
|
validate.cpp
|
|
16
19
|
view.cpp
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
/// @file animation.cpp
|
|
3
|
+
/// @brief Time-sampled attributes: their sparse samples per prim, and the clock that evaluates
|
|
4
|
+
/// them into the columns.
|
|
5
|
+
#include "ernie/scene/scene.h"
|
|
6
|
+
|
|
7
|
+
#include <algorithm>
|
|
8
|
+
|
|
9
|
+
namespace ernie {
|
|
10
|
+
|
|
11
|
+
void Scene::SetAt(PrimId prim, std::string_view attribute, double time, const Value& value) {
|
|
12
|
+
TimeSample sample{time, {}, {}};
|
|
13
|
+
Author(prim, attribute, value, &sample.value);
|
|
14
|
+
AddSample(prim, attribute, std::move(sample));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
void Scene::WriteAt(PrimId prim, std::string_view attribute, double time, Tensor array) {
|
|
18
|
+
CheckArray(prim, attribute, array);
|
|
19
|
+
AddSample(prim, attribute, {time, {}, std::move(array)});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void Scene::AddSample(PrimId prim, std::string_view attribute, TimeSample sample) {
|
|
23
|
+
const AttributeId token = store_.Tokens().Intern(attribute);
|
|
24
|
+
Animated& animated = animated_[prim.slot];
|
|
25
|
+
animated.prim = prim;
|
|
26
|
+
std::vector<TimeSample>& samples = animated.samples[token];
|
|
27
|
+
// Samples are all values or all arrays: one of the other kind replaces them.
|
|
28
|
+
if (!samples.empty() && samples.front().tensor.Empty() != sample.tensor.Empty()) {
|
|
29
|
+
samples.clear();
|
|
30
|
+
}
|
|
31
|
+
const auto at = std::ranges::lower_bound(samples, sample.time, {}, &TimeSample::time);
|
|
32
|
+
if (at != samples.end() && at->time == sample.time) {
|
|
33
|
+
*at = std::move(sample);
|
|
34
|
+
} else {
|
|
35
|
+
samples.insert(at, std::move(sample));
|
|
36
|
+
}
|
|
37
|
+
Evaluate(prim, token, samples);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
std::span<const TimeSample> Scene::Samples(PrimId prim, std::string_view attribute) const {
|
|
41
|
+
const auto animated = animated_.find(prim.slot);
|
|
42
|
+
const std::optional<Token> token = store_.Tokens().Find(attribute);
|
|
43
|
+
if (animated == animated_.end() || animated->second.prim != prim || !token) {
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
46
|
+
const auto samples = animated->second.samples.find(*token);
|
|
47
|
+
return samples == animated->second.samples.end() ? std::span<const TimeSample>()
|
|
48
|
+
: std::span(samples->second);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
std::optional<Value> Scene::GetAt(PrimId prim, std::string_view attribute, double time) const {
|
|
52
|
+
const std::span<const TimeSample> samples = Samples(prim, attribute);
|
|
53
|
+
if (samples.empty()) {
|
|
54
|
+
return Get(prim, attribute);
|
|
55
|
+
}
|
|
56
|
+
Value value = ernie::Evaluate(samples, time).value;
|
|
57
|
+
return value.Empty() ? std::nullopt : std::optional(std::move(value));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
bool Scene::ClearSamples(PrimId prim, std::string_view attribute) {
|
|
61
|
+
const auto animated = animated_.find(prim.slot);
|
|
62
|
+
const std::optional<Token> token = store_.Tokens().Find(attribute);
|
|
63
|
+
if (animated == animated_.end() || !token || animated->second.samples.erase(*token) == 0) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
if (animated->second.samples.empty()) {
|
|
67
|
+
animated_.erase(animated);
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
void Scene::SetTime(double timeCode) {
|
|
73
|
+
time_ = timeCode;
|
|
74
|
+
for (const auto& [slot, animated] : animated_) {
|
|
75
|
+
for (const auto& [attribute, samples] : animated.samples) {
|
|
76
|
+
Evaluate(animated.prim, attribute, samples);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
void Scene::Evaluate(PrimId prim, AttributeId attribute, std::span<const TimeSample> samples) {
|
|
82
|
+
const std::string_view name = store_.Tokens().Text(attribute);
|
|
83
|
+
TimeSample now = ernie::Evaluate(samples, time_);
|
|
84
|
+
if (!now.tensor.Empty()) {
|
|
85
|
+
const Tensor* current = Read(prim, name);
|
|
86
|
+
if (current == nullptr || current->Data() != now.tensor.Data()) {
|
|
87
|
+
store_.Set(prim, attribute, std::move(now.tensor));
|
|
88
|
+
}
|
|
89
|
+
} else if (Get(prim, name) != now.value) {
|
|
90
|
+
Author(prim, name, now.value);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
} // namespace ernie
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
/// @file edit_history.cpp
|
|
3
|
+
/// @brief Recording edits as steps of before and after states, and applying them either way.
|
|
4
|
+
#include "ernie/scene/edit_history.h"
|
|
5
|
+
|
|
6
|
+
#include <stdexcept>
|
|
7
|
+
|
|
8
|
+
namespace ernie {
|
|
9
|
+
|
|
10
|
+
void EditHistory::Set(Scene& scene, const Path& path,
|
|
11
|
+
std::vector<std::pair<std::string, Value>> edits, bool open) {
|
|
12
|
+
const PrimId prim = scene.Require(path);
|
|
13
|
+
Step step{.path = path, .open = open};
|
|
14
|
+
try {
|
|
15
|
+
for (auto& [name, value] : edits) {
|
|
16
|
+
Cell before = Capture(scene, prim, name);
|
|
17
|
+
scene.Set(prim, name, std::move(value));
|
|
18
|
+
step.attributes.push_back({name, {std::move(before), Capture(scene, prim, name)}});
|
|
19
|
+
}
|
|
20
|
+
} catch (...) {
|
|
21
|
+
// What applied before the rejected edit stays undoable.
|
|
22
|
+
if (!step.attributes.empty()) {
|
|
23
|
+
Push(std::move(step));
|
|
24
|
+
}
|
|
25
|
+
throw;
|
|
26
|
+
}
|
|
27
|
+
const auto same = [&](const Step& last) {
|
|
28
|
+
if (last.structural || !last.open || last.path != path ||
|
|
29
|
+
last.attributes.size() != step.attributes.size()) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
for (std::size_t i = 0; i < last.attributes.size(); ++i) {
|
|
33
|
+
if (last.attributes[i].first != step.attributes[i].first) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
};
|
|
39
|
+
if (open && open_ && next_ == steps_.size() && !steps_.empty() && same(steps_.back())) {
|
|
40
|
+
for (std::size_t i = 0; i < step.attributes.size(); ++i) {
|
|
41
|
+
steps_.back().attributes[i].second.second = std::move(step.attributes[i].second.second);
|
|
42
|
+
}
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
Push(std::move(step));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void EditHistory::Clear(Scene& scene, const Path& path, std::string_view attribute) {
|
|
49
|
+
const PrimId prim = scene.Require(path);
|
|
50
|
+
const std::string name(attribute);
|
|
51
|
+
Cell before = Capture(scene, prim, name);
|
|
52
|
+
scene.Clear(prim, attribute);
|
|
53
|
+
Step step{.path = path};
|
|
54
|
+
step.attributes.push_back({name, {std::move(before), Capture(scene, prim, name)}});
|
|
55
|
+
Push(std::move(step));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
void EditHistory::Define(Scene& scene, const Path& path, std::string_view type) {
|
|
59
|
+
if (scene.Has(path)) {
|
|
60
|
+
throw std::invalid_argument("'" + path.String() + "' has a prim already");
|
|
61
|
+
}
|
|
62
|
+
scene.Define(path, type);
|
|
63
|
+
Push({.path = path, .after = Snapshot(scene, path), .structural = true});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
bool EditHistory::Remove(Scene& scene, const Path& path) {
|
|
67
|
+
if (!scene.Has(path)) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
Step step{.path = path, .before = Snapshot(scene, path), .structural = true};
|
|
71
|
+
scene.Remove(path);
|
|
72
|
+
Push(std::move(step));
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
void EditHistory::Add(Scene& scene, const Scene& source, const Path& path) {
|
|
77
|
+
if (!source.Has(path) || scene.Has(path)) {
|
|
78
|
+
throw std::invalid_argument("Cannot add '" + path.String() +
|
|
79
|
+
"': the source has no prim there or the scene has one");
|
|
80
|
+
}
|
|
81
|
+
Step step{.path = path, .after = Snapshot(source, path), .structural = true};
|
|
82
|
+
Restore(scene, step.after);
|
|
83
|
+
Push(std::move(step));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
void EditHistory::BeginGroup() {
|
|
87
|
+
if (groupDepth_++ == 0) {
|
|
88
|
+
group_ = nextGroup_++;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
void EditHistory::EndGroup() {
|
|
93
|
+
if (groupDepth_ > 0 && --groupDepth_ == 0) {
|
|
94
|
+
group_ = 0;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
bool EditHistory::Undo(Scene& scene) {
|
|
99
|
+
return Move(scene, false);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
bool EditHistory::Redo(Scene& scene) {
|
|
103
|
+
return Move(scene, true);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
std::string EditHistory::UndoLabel() const {
|
|
107
|
+
return CanUndo() ? Label(steps_[next_ - 1]) : std::string();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
std::string EditHistory::RedoLabel() const {
|
|
111
|
+
return CanRedo() ? Label(steps_[next_]) : std::string();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
void EditHistory::Reset() {
|
|
115
|
+
*this = EditHistory();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
EditHistory::Cell EditHistory::Capture(const Scene& scene, PrimId prim,
|
|
119
|
+
const std::string& attribute) {
|
|
120
|
+
Cell cell;
|
|
121
|
+
const std::span<const TimeSample> samples = scene.Samples(prim, attribute);
|
|
122
|
+
cell.samples.assign(samples.begin(), samples.end());
|
|
123
|
+
if (const Tensor* array = scene.Read(prim, attribute)) {
|
|
124
|
+
cell.array = *array;
|
|
125
|
+
} else {
|
|
126
|
+
cell.value = scene.Get(prim, attribute);
|
|
127
|
+
}
|
|
128
|
+
return cell;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
void EditHistory::Apply(Scene& scene, PrimId prim, const std::string& attribute, const Cell& cell) {
|
|
132
|
+
if (!cell.samples.empty()) {
|
|
133
|
+
scene.ClearSamples(prim, attribute);
|
|
134
|
+
for (const TimeSample& sample : cell.samples) {
|
|
135
|
+
sample.tensor.Empty() ? scene.SetAt(prim, attribute, sample.time, sample.value)
|
|
136
|
+
: scene.WriteAt(prim, attribute, sample.time, sample.tensor);
|
|
137
|
+
}
|
|
138
|
+
} else if (!cell.array.Empty()) {
|
|
139
|
+
scene.Write(prim, attribute, cell.array);
|
|
140
|
+
} else if (cell.value) {
|
|
141
|
+
scene.Set(prim, attribute, *cell.value);
|
|
142
|
+
} else {
|
|
143
|
+
scene.Clear(prim, attribute);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
std::vector<EditHistory::PrimSnapshot> EditHistory::Snapshot(const Scene& scene, const Path& path) {
|
|
148
|
+
std::vector<PrimSnapshot> prims;
|
|
149
|
+
std::vector<Path> pending{path};
|
|
150
|
+
while (!pending.empty()) {
|
|
151
|
+
const Path next = std::move(pending.back());
|
|
152
|
+
pending.pop_back();
|
|
153
|
+
const PrimId prim = scene.Require(next);
|
|
154
|
+
PrimSnapshot& snapshot = prims.emplace_back();
|
|
155
|
+
snapshot.path = next;
|
|
156
|
+
snapshot.type = std::string(scene.TypeName(prim));
|
|
157
|
+
snapshot.apis = scene.AppliedApis(prim);
|
|
158
|
+
for (const std::string& name : scene.Attributes(next)) {
|
|
159
|
+
snapshot.attributes.emplace(name, Capture(scene, prim, name));
|
|
160
|
+
}
|
|
161
|
+
const std::vector<Path> children = scene.Children(next);
|
|
162
|
+
pending.insert(pending.end(), children.rbegin(), children.rend());
|
|
163
|
+
}
|
|
164
|
+
return prims;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
void EditHistory::Restore(Scene& scene, const std::vector<PrimSnapshot>& prims) {
|
|
168
|
+
for (const PrimSnapshot& snapshot : prims) {
|
|
169
|
+
const PrimId prim = scene.Define(snapshot.path, snapshot.type);
|
|
170
|
+
for (const std::string& api : snapshot.apis) {
|
|
171
|
+
if (!scene.HasApi(prim, api)) {
|
|
172
|
+
scene.ApplyApi(prim, api);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
for (const auto& [name, cell] : snapshot.attributes) {
|
|
176
|
+
Apply(scene, prim, name, cell);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
void EditHistory::Apply(Scene& scene, const Step& step, bool forward) {
|
|
182
|
+
if (step.structural) {
|
|
183
|
+
scene.Remove(step.path);
|
|
184
|
+
Restore(scene, forward ? step.after : step.before);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// Edits of a prim removed since are skipped.
|
|
188
|
+
const std::optional<PrimId> prim = scene.Find(step.path);
|
|
189
|
+
if (!prim) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
for (std::size_t i = 0; i < step.attributes.size(); ++i) {
|
|
193
|
+
const auto& [name, states] = step.attributes[forward ? i : step.attributes.size() - 1 - i];
|
|
194
|
+
Apply(scene, *prim, name, forward ? states.second : states.first);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
void EditHistory::Push(Step step) {
|
|
199
|
+
steps_.resize(next_);
|
|
200
|
+
step.group = groupDepth_ > 0 ? group_ : 0;
|
|
201
|
+
open_ = step.open;
|
|
202
|
+
steps_.push_back(std::move(step));
|
|
203
|
+
next_ = steps_.size();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
bool EditHistory::Move(Scene& scene, bool forward) {
|
|
207
|
+
open_ = false;
|
|
208
|
+
if (forward ? !CanRedo() : !CanUndo()) {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
const std::uint64_t group = steps_[forward ? next_ : next_ - 1].group;
|
|
212
|
+
do {
|
|
213
|
+
if (forward) {
|
|
214
|
+
Apply(scene, steps_[next_++], true);
|
|
215
|
+
} else {
|
|
216
|
+
Apply(scene, steps_[--next_], false);
|
|
217
|
+
}
|
|
218
|
+
} while (group != 0 && (forward ? CanRedo() && steps_[next_].group == group
|
|
219
|
+
: CanUndo() && steps_[next_ - 1].group == group));
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
std::string EditHistory::Label(const Step& step) {
|
|
224
|
+
if (step.structural) {
|
|
225
|
+
return (step.before.empty() ? "Add "
|
|
226
|
+
: step.after.empty() ? "Remove "
|
|
227
|
+
: "Change ") +
|
|
228
|
+
step.path.String();
|
|
229
|
+
}
|
|
230
|
+
std::string label = step.path.String();
|
|
231
|
+
for (const auto& [name, states] : step.attributes) {
|
|
232
|
+
label += " " + name;
|
|
233
|
+
}
|
|
234
|
+
return label;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
} // namespace ernie
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
/// @file edit_history.h
|
|
3
|
+
/// @brief Undo and redo of scene edits, for the viewer.
|
|
4
|
+
///
|
|
5
|
+
/// References:
|
|
6
|
+
/// - E. Gamma, R. Helm, R. Johnson and J. Vlissides, "Design Patterns", the Command pattern,
|
|
7
|
+
/// Addison-Wesley, 1994.
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "ernie/scene/scene.h"
|
|
11
|
+
|
|
12
|
+
#include <cstddef>
|
|
13
|
+
#include <cstdint>
|
|
14
|
+
#include <map>
|
|
15
|
+
#include <optional>
|
|
16
|
+
#include <string>
|
|
17
|
+
#include <string_view>
|
|
18
|
+
#include <utility>
|
|
19
|
+
#include <vector>
|
|
20
|
+
|
|
21
|
+
namespace ernie {
|
|
22
|
+
|
|
23
|
+
/// @brief Undo and redo for the edits made through it: attributes set or cleared, prims defined,
|
|
24
|
+
/// removed with their descendants, or copied in. Each step records what it changes, so `Undo`
|
|
25
|
+
/// puts it back and `Redo` does it again.
|
|
26
|
+
///
|
|
27
|
+
/// Continuous edits, as dragging a slider or a gizmo, merge into one step: an `open` edit of the
|
|
28
|
+
/// same attributes as the last step updates it until `Close`. Edits between `BeginGroup` and
|
|
29
|
+
/// `EndGroup` undo and redo together. Edits made to the scene directly are not recorded.
|
|
30
|
+
class EditHistory {
|
|
31
|
+
public:
|
|
32
|
+
/// @brief Sets attributes of a prim as one step, dropping the undone steps. With `open`, merges
|
|
33
|
+
/// into the last step if that is an open edit of the same attributes.
|
|
34
|
+
/// @throws std::invalid_argument as `Scene::Set`.
|
|
35
|
+
void Set(Scene& scene, const Path& path, std::vector<std::pair<std::string, Value>> edits,
|
|
36
|
+
bool open = false);
|
|
37
|
+
void Set(Scene& scene, const Path& path, std::string_view attribute, Value value,
|
|
38
|
+
bool open = false) {
|
|
39
|
+
Set(scene, path, {{std::string(attribute), std::move(value)}}, open);
|
|
40
|
+
}
|
|
41
|
+
/// @brief Unauthors an attribute, back to its fallback.
|
|
42
|
+
void Clear(Scene& scene, const Path& path, std::string_view attribute);
|
|
43
|
+
/// @brief Defines a new prim; undoing removes it.
|
|
44
|
+
/// @throws std::invalid_argument as `Scene::Define`, or if a prim is there already.
|
|
45
|
+
void Define(Scene& scene, const Path& path, std::string_view type);
|
|
46
|
+
/// @brief Removes a prim and its descendants; undoing restores them, sharing their arrays.
|
|
47
|
+
/// @return Whether there was a prim.
|
|
48
|
+
bool Remove(Scene& scene, const Path& path);
|
|
49
|
+
/// @brief Copies a prim of `source` and its descendants to the same path of `scene`, as for
|
|
50
|
+
/// prims authored in a scratch scene first; undoing removes them.
|
|
51
|
+
/// @throws std::invalid_argument if `source` has no prim at `path` or `scene` has one.
|
|
52
|
+
void Add(Scene& scene, const Scene& source, const Path& path);
|
|
53
|
+
|
|
54
|
+
/// Groups the edits until `EndGroup` into one step. Groups nest; the outermost counts.
|
|
55
|
+
void BeginGroup();
|
|
56
|
+
void EndGroup();
|
|
57
|
+
/// Ends the open step, so the next edit starts a new one.
|
|
58
|
+
void Close() {
|
|
59
|
+
open_ = false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
bool CanUndo() const {
|
|
63
|
+
return next_ > 0;
|
|
64
|
+
}
|
|
65
|
+
bool CanRedo() const {
|
|
66
|
+
return next_ < steps_.size();
|
|
67
|
+
}
|
|
68
|
+
/// @brief Undoes the last step or group; edits of prims removed since are skipped.
|
|
69
|
+
/// @return Whether there was one.
|
|
70
|
+
bool Undo(Scene& scene);
|
|
71
|
+
bool Redo(Scene& scene);
|
|
72
|
+
/// @return What `Undo` or `Redo` would do, as "/World/Cube xformOp:translate".
|
|
73
|
+
std::string UndoLabel() const;
|
|
74
|
+
std::string RedoLabel() const;
|
|
75
|
+
/// Forgets every step, as when the viewer switches scenes.
|
|
76
|
+
void Reset();
|
|
77
|
+
/// @return The steps recorded, a group's edits each counted.
|
|
78
|
+
std::size_t Size() const {
|
|
79
|
+
return steps_.size();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private:
|
|
83
|
+
/// One attribute's authored state: unset, a value, an array or time samples.
|
|
84
|
+
struct Cell {
|
|
85
|
+
std::optional<Value> value;
|
|
86
|
+
Tensor array;
|
|
87
|
+
std::vector<TimeSample> samples;
|
|
88
|
+
};
|
|
89
|
+
/// One prim of a subtree, enough to define it again.
|
|
90
|
+
struct PrimSnapshot {
|
|
91
|
+
Path path;
|
|
92
|
+
std::string type;
|
|
93
|
+
std::vector<std::string> apis;
|
|
94
|
+
std::map<std::string, Cell> attributes;
|
|
95
|
+
};
|
|
96
|
+
struct Step {
|
|
97
|
+
Path path;
|
|
98
|
+
/// Attribute steps: each attribute's state before and after.
|
|
99
|
+
std::vector<std::pair<std::string, std::pair<Cell, Cell>>> attributes;
|
|
100
|
+
/// Structure steps: the subtree at `path` before and after, parents first; empty for none.
|
|
101
|
+
std::vector<PrimSnapshot> before;
|
|
102
|
+
std::vector<PrimSnapshot> after;
|
|
103
|
+
bool structural = false;
|
|
104
|
+
bool open = false;
|
|
105
|
+
/// Steps of one non-zero group undo together.
|
|
106
|
+
std::uint64_t group = 0;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
static Cell Capture(const Scene& scene, PrimId prim, const std::string& attribute);
|
|
110
|
+
static void Apply(Scene& scene, PrimId prim, const std::string& attribute, const Cell& cell);
|
|
111
|
+
static std::vector<PrimSnapshot> Snapshot(const Scene& scene, const Path& path);
|
|
112
|
+
static void Restore(Scene& scene, const std::vector<PrimSnapshot>& prims);
|
|
113
|
+
static void Apply(Scene& scene, const Step& step, bool forward);
|
|
114
|
+
void Push(Step step);
|
|
115
|
+
bool Move(Scene& scene, bool forward);
|
|
116
|
+
static std::string Label(const Step& step);
|
|
117
|
+
|
|
118
|
+
std::vector<Step> steps_;
|
|
119
|
+
/// Steps before it are done; from it on, undone.
|
|
120
|
+
std::size_t next_ = 0;
|
|
121
|
+
bool open_ = false;
|
|
122
|
+
int groupDepth_ = 0;
|
|
123
|
+
std::uint64_t group_ = 0;
|
|
124
|
+
std::uint64_t nextGroup_ = 1;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
} // namespace ernie
|
|
@@ -201,8 +201,13 @@ XformOps ReadXform(const Json& json) {
|
|
|
201
201
|
return xform;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
+
/// Authors an attribute's value, or with `time` its sample there.
|
|
204
205
|
void LoadAttribute(Scene& scene, PrimId prim, const std::string& name, const Json& json,
|
|
205
|
-
std::span<const Tensor> arrays) {
|
|
206
|
+
std::span<const Tensor> arrays, std::optional<double> time = std::nullopt) {
|
|
207
|
+
const auto write = [&](Tensor array) {
|
|
208
|
+
time ? scene.WriteAt(prim, name, *time, std::move(array))
|
|
209
|
+
: scene.Write(prim, name, std::move(array));
|
|
210
|
+
};
|
|
206
211
|
const AttributeDef* def = scene.Declaration(prim, name);
|
|
207
212
|
if (json.is_object() && json.contains(kArray)) {
|
|
208
213
|
const auto index = json[kArray].get<std::size_t>();
|
|
@@ -210,14 +215,31 @@ void LoadAttribute(Scene& scene, PrimId prim, const std::string& name, const Jso
|
|
|
210
215
|
throw std::invalid_argument("names array " + std::to_string(index) + " of " +
|
|
211
216
|
std::to_string(arrays.size()));
|
|
212
217
|
}
|
|
213
|
-
|
|
218
|
+
write(arrays[index]);
|
|
214
219
|
return;
|
|
215
220
|
}
|
|
216
221
|
const ColumnType type = def != nullptr ? def->type : Infer(name, json);
|
|
217
222
|
if (type == ColumnType::Tensor) {
|
|
218
|
-
|
|
223
|
+
write(ReadTensor(json, def != nullptr ? &def->meta : nullptr));
|
|
219
224
|
} else {
|
|
220
|
-
|
|
225
|
+
const Value value = ReadValue(json, type);
|
|
226
|
+
time ? scene.SetAt(prim, name, *time, value) : scene.Set(prim, name, value);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/// Authors an attribute's samples: `"radius.timeSamples": {"0": 1, "24": 2}`, as USD writes them.
|
|
231
|
+
void LoadSamples(Scene& scene, PrimId prim, const std::string& name, const Json& json,
|
|
232
|
+
std::span<const Tensor> arrays) {
|
|
233
|
+
if (!json.is_object()) {
|
|
234
|
+
throw std::invalid_argument("maps time codes to values");
|
|
235
|
+
}
|
|
236
|
+
for (const auto& [time, value] : json.items()) {
|
|
237
|
+
std::size_t end = 0;
|
|
238
|
+
const double code = std::stod(time, &end);
|
|
239
|
+
if (end != time.size()) {
|
|
240
|
+
throw std::invalid_argument("'" + time + "' is no time code");
|
|
241
|
+
}
|
|
242
|
+
LoadAttribute(scene, prim, name, value, arrays, code);
|
|
221
243
|
}
|
|
222
244
|
}
|
|
223
245
|
|
|
@@ -282,6 +304,9 @@ void LoadPrim(Scene& scene, const Path& path, const Json& json, std::span<const
|
|
|
282
304
|
Attempt(problems, path, key, [&] {
|
|
283
305
|
if (key == kXform) {
|
|
284
306
|
SetXform(scene, path, ReadXform(value));
|
|
307
|
+
} else if (key.ends_with(kTimeSamples)) {
|
|
308
|
+
LoadSamples(scene, prim, key.substr(0, key.size() - kTimeSamples.size()), value,
|
|
309
|
+
arrays);
|
|
285
310
|
} else {
|
|
286
311
|
LoadAttribute(scene, prim, key, value, arrays);
|
|
287
312
|
}
|
|
@@ -394,6 +419,15 @@ Json WriteTensor(const Tensor& tensor) {
|
|
|
394
419
|
return nest(nest, 0);
|
|
395
420
|
}
|
|
396
421
|
|
|
422
|
+
Json WriteSamples(std::span<const TimeSample> samples) {
|
|
423
|
+
Json json = Json::object();
|
|
424
|
+
for (const TimeSample& sample : samples) {
|
|
425
|
+
json[Finite(sample.time).dump()] =
|
|
426
|
+
sample.tensor.Empty() ? WriteValue(sample.value) : WriteTensor(sample.tensor);
|
|
427
|
+
}
|
|
428
|
+
return json;
|
|
429
|
+
}
|
|
430
|
+
|
|
397
431
|
/// Prints JSON with 2-space indents, keeping arrays of scalars on one line.
|
|
398
432
|
void Print(const Json& json, std::size_t indent, std::string& out) {
|
|
399
433
|
const std::string pad(indent + 2, ' ');
|
|
@@ -503,6 +537,10 @@ std::string SaveScene(const Scene& scene) {
|
|
|
503
537
|
const Tensor* tensor = scene.Read(prim, name);
|
|
504
538
|
json[name] =
|
|
505
539
|
tensor != nullptr ? WriteTensor(*tensor) : WriteValue(*scene.Get(prim, name));
|
|
540
|
+
if (const std::span<const TimeSample> samples = scene.Samples(prim, name);
|
|
541
|
+
!samples.empty()) {
|
|
542
|
+
json[name + std::string(kTimeSamples)] = WriteSamples(samples);
|
|
543
|
+
}
|
|
506
544
|
} catch (const std::exception& error) {
|
|
507
545
|
throw std::invalid_argument(
|
|
508
546
|
SceneProblem{path.String(), name, error.what()}.Message());
|
|
@@ -20,6 +20,8 @@ inline constexpr std::string_view kTypeName = "typeName";
|
|
|
20
20
|
inline constexpr std::string_view kApis = "apiSchemas";
|
|
21
21
|
inline constexpr std::string_view kXform = "xform";
|
|
22
22
|
inline constexpr std::string_view kArray = "$array";
|
|
23
|
+
/// The suffix of an attribute's samples by time code, as USD's text format writes them.
|
|
24
|
+
inline constexpr std::string_view kTimeSamples = ".timeSamples";
|
|
23
25
|
|
|
24
26
|
/// @return A value as scene files write it: vectors as arrays, quaternions as [w, x, y, z],
|
|
25
27
|
/// matrices as 4 rows, paths as strings, floats in their shortest form.
|
|
@@ -239,6 +239,11 @@ Json PrimSchema() {
|
|
|
239
239
|
{{kTypeName, {{"enum", Names(SchemaKind::Concrete)}}},
|
|
240
240
|
{kApis, ArrayOf(api)},
|
|
241
241
|
{kXform, Ref("XformOps")}}},
|
|
242
|
+
{"patternProperties",
|
|
243
|
+
{{Literal(kTimeSamples) + "$",
|
|
244
|
+
{{"type", "object"},
|
|
245
|
+
{"description", "The attribute's values by time code."},
|
|
246
|
+
{"propertyNames", {{"pattern", "^-?[0-9]+(\\.[0-9]+)?([eE][-+]?[0-9]+)?$"}}}}}}},
|
|
242
247
|
{"allOf", std::move(conditions)},
|
|
243
248
|
{"unevaluatedProperties", false}};
|
|
244
249
|
}
|
|
@@ -80,6 +80,7 @@ bool Scene::Remove(const Path& path) {
|
|
|
80
80
|
const PathId next = pending.back();
|
|
81
81
|
pending.pop_back();
|
|
82
82
|
if (const std::optional<PrimId> prim = store_.Find(next)) {
|
|
83
|
+
animated_.erase(prim->slot);
|
|
83
84
|
store_.Remove(*prim);
|
|
84
85
|
}
|
|
85
86
|
store_.Paths().ForEachChild(next, [&](PathId child) { pending.push_back(child); });
|
|
@@ -137,6 +138,15 @@ std::vector<Path> Scene::Prims(std::string_view type) const {
|
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
void Scene::Set(PrimId prim, std::string_view attribute, const Value& value) {
|
|
141
|
+
ClearSamples(prim, attribute);
|
|
142
|
+
Author(prim, attribute, value);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
void Scene::Set(const Path& path, std::string_view attribute, const Value& value) {
|
|
146
|
+
Set(Require(path), attribute, value);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
void Scene::Author(PrimId prim, std::string_view attribute, const Value& value, Value* checked) {
|
|
140
150
|
const AttributeId token = store_.Tokens().Intern(attribute);
|
|
141
151
|
const AttributeDef* def = Declared(store_.PrimBucket(prim), token);
|
|
142
152
|
if (def != nullptr) {
|
|
@@ -149,17 +159,23 @@ void Scene::Set(PrimId prim, std::string_view attribute, const Value& value) {
|
|
|
149
159
|
throw std::invalid_argument(Describe(*this, prim) + ": '" + std::string(attribute) +
|
|
150
160
|
"' takes another type of value");
|
|
151
161
|
}
|
|
152
|
-
|
|
162
|
+
if (checked != nullptr) {
|
|
163
|
+
*checked = ToValue(store_.Paths(), *element);
|
|
164
|
+
} else {
|
|
165
|
+
store_.Set(prim, token, std::move(*element));
|
|
166
|
+
}
|
|
153
167
|
});
|
|
154
168
|
}
|
|
155
169
|
|
|
156
|
-
void Scene::
|
|
157
|
-
|
|
170
|
+
void Scene::Write(PrimId prim, std::string_view attribute, Tensor array) {
|
|
171
|
+
ClearSamples(prim, attribute);
|
|
172
|
+
CheckArray(prim, attribute, array);
|
|
173
|
+
store_.Set(prim, store_.Tokens().Intern(attribute), std::move(array));
|
|
158
174
|
}
|
|
159
175
|
|
|
160
|
-
void Scene::
|
|
161
|
-
const
|
|
162
|
-
const AttributeDef* def = Declared(store_.PrimBucket(prim), token);
|
|
176
|
+
void Scene::CheckArray(PrimId prim, std::string_view attribute, const Tensor& array) const {
|
|
177
|
+
const std::optional<Token> token = store_.Tokens().Find(attribute);
|
|
178
|
+
const AttributeDef* def = token ? Declared(store_.PrimBucket(prim), *token) : nullptr;
|
|
163
179
|
if (def == nullptr && !TakesUndeclared(prim, attribute)) {
|
|
164
180
|
throw std::invalid_argument(Describe(*this, prim) + " has no attribute '" +
|
|
165
181
|
std::string(attribute) + "'");
|
|
@@ -167,7 +183,6 @@ void Scene::Write(PrimId prim, std::string_view attribute, Tensor array) {
|
|
|
167
183
|
if (def != nullptr) {
|
|
168
184
|
ValidateArray(*def, attribute, array, PrimPath(prim));
|
|
169
185
|
}
|
|
170
|
-
store_.Set(prim, token, std::move(array));
|
|
171
186
|
}
|
|
172
187
|
|
|
173
188
|
const Tensor* Scene::Read(PrimId prim, std::string_view attribute) const {
|
|
@@ -199,6 +214,7 @@ std::optional<Value> Scene::Get(const Path& path, std::string_view attribute) co
|
|
|
199
214
|
}
|
|
200
215
|
|
|
201
216
|
bool Scene::Clear(PrimId prim, std::string_view attribute) {
|
|
217
|
+
ClearSamples(prim, attribute);
|
|
202
218
|
const Column* column = AuthoredColumn(prim, attribute);
|
|
203
219
|
if (column != nullptr) {
|
|
204
220
|
store_.Clear(prim, column->attribute);
|