ernie-renderer 0.2.0.dev21__tar.gz → 0.2.0.dev22__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.

Files changed (241) hide show
  1. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/CMakeLists.txt +1 -1
  2. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/PKG-INFO +1 -1
  3. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/CMakeLists.txt +2 -0
  4. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/scene.cpp +70 -21
  5. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/scene.h +19 -2
  6. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/schema.cpp +32 -2
  7. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/schema.h +19 -1
  8. ernie_renderer-0.2.0.dev22/ernie/scene/schemas/collection.cpp +11 -0
  9. ernie_renderer-0.2.0.dev22/ernie/scene/schemas/collection.h +46 -0
  10. ernie_renderer-0.2.0.dev22/ernie/scene/schemas/registry.cpp +23 -0
  11. ernie_renderer-0.2.0.dev22/ernie/scene/schemas/shade.cpp +12 -0
  12. ernie_renderer-0.2.0.dev22/ernie/scene/schemas/shade.h +27 -0
  13. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/storage.cpp +14 -4
  14. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/storage.h +3 -0
  15. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/view.cpp +21 -5
  16. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/view.h +56 -14
  17. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/CMakeLists.txt +1 -0
  18. ernie_renderer-0.2.0.dev22/tests/scene/api_test.cpp +91 -0
  19. ernie_renderer-0.2.0.dev21/ernie/scene/schemas/registry.cpp +0 -18
  20. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/.clang-format +0 -0
  21. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/.clang-tidy +0 -0
  22. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/.dockerignore +0 -0
  23. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/.gersemirc +0 -0
  24. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/.gitattributes +0 -0
  25. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/.github/scripts/coverage_badge.py +0 -0
  26. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/.github/scripts/install-lavapipe-windows.sh +0 -0
  27. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/.github/workflows/ci.yml +0 -0
  28. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/.gitignore +0 -0
  29. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/.pre-commit-config.yaml +0 -0
  30. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/CMakePresets.json +0 -0
  31. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/Dockerfile +0 -0
  32. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/LICENSE +0 -0
  33. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/README.md +0 -0
  34. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/benchmarks/CMakeLists.txt +0 -0
  35. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/benchmarks/bench.h +0 -0
  36. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/benchmarks/main.cpp +0 -0
  37. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/benchmarks/scene/storage.cpp +0 -0
  38. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/ErnieConfig.cmake.in +0 -0
  39. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/ErnieFetch.cmake +0 -0
  40. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/ErnieInstall.cmake +0 -0
  41. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/ErniePackaging.cmake +0 -0
  42. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/ErnieTesting.cmake +0 -0
  43. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/ernie.pc.in +0 -0
  44. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/third_party/bc7enc.cmake +0 -0
  45. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/third_party/dlpack.cmake +0 -0
  46. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/third_party/glm.cmake +0 -0
  47. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/third_party/googletest.cmake +0 -0
  48. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/third_party/json.cmake +0 -0
  49. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/third_party/nanobind.cmake +0 -0
  50. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/third_party/openexr.cmake +0 -0
  51. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/third_party/stb.cmake +0 -0
  52. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/third_party/tracy.cmake +0 -0
  53. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/third_party/volk.cmake +0 -0
  54. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/cmake/third_party/vulkan_headers.cmake +0 -0
  55. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/docs/README.md +0 -0
  56. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/docs/index.md +0 -0
  57. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/docs/requirements.txt +0 -0
  58. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/CMakeLists.txt +0 -0
  59. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/app/CMakeLists.txt +0 -0
  60. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/app/main.cpp +0 -0
  61. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/device/CMakeLists.txt +0 -0
  62. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/device/vulkan_devices.cpp +0 -0
  63. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/device/vulkan_devices.h +0 -0
  64. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/geometry/CMakeLists.txt +0 -0
  65. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/geometry/bounds.h +0 -0
  66. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/graph/CMakeLists.txt +0 -0
  67. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/io/CMakeLists.txt +0 -0
  68. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/io/ies.cpp +0 -0
  69. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/io/ies.h +0 -0
  70. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/io/image.cpp +0 -0
  71. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/io/image.h +0 -0
  72. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/io/nanovdb.cpp +0 -0
  73. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/io/nanovdb.h +0 -0
  74. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/io/raster.cpp +0 -0
  75. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/io/raster.h +0 -0
  76. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/io/texture.cpp +0 -0
  77. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/io/texture.h +0 -0
  78. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/CMakeLists.txt +0 -0
  79. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/astronomy.cpp +0 -0
  80. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/astronomy.h +0 -0
  81. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/atmosphere.cpp +0 -0
  82. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/atmosphere.h +0 -0
  83. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/cloud.cpp +0 -0
  84. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/cloud.h +0 -0
  85. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/constants.h +0 -0
  86. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/reflectance_library.cpp +0 -0
  87. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/reflectance_library.h +0 -0
  88. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/reflectance_table.h +0 -0
  89. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/regolith.cpp +0 -0
  90. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/regolith.h +0 -0
  91. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/scattering.cpp +0 -0
  92. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/scattering.h +0 -0
  93. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/solar.cpp +0 -0
  94. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/solar.h +0 -0
  95. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/solar_table.h +0 -0
  96. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/spectrum.cpp +0 -0
  97. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/physics/spectrum.h +0 -0
  98. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/python/CMakeLists.txt +0 -0
  99. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/python/ernie/__init__.py +0 -0
  100. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/python/module.cpp +0 -0
  101. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/render/CMakeLists.txt +0 -0
  102. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/convert.h +0 -0
  103. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/path.cpp +0 -0
  104. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/path.h +0 -0
  105. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/schemas/geom.cpp +0 -0
  106. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/schemas/geom.h +0 -0
  107. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/tokens.h +0 -0
  108. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/value.h +0 -0
  109. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/xform.cpp +0 -0
  110. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/scene/xform.h +0 -0
  111. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/CMakeLists.txt +0 -0
  112. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/algorithm.h +0 -0
  113. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/bytes.h +0 -0
  114. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/disk_cache.cpp +0 -0
  115. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/disk_cache.h +0 -0
  116. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/file.cpp +0 -0
  117. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/file.h +0 -0
  118. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/glm.h +0 -0
  119. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/hash_index.h +0 -0
  120. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/linear_algebra.h +0 -0
  121. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/log.cpp +0 -0
  122. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/log.h +0 -0
  123. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/math.h +0 -0
  124. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/noise.cpp +0 -0
  125. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/noise.h +0 -0
  126. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/numbers.h +0 -0
  127. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/parallel.h +0 -0
  128. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/profiler.cpp +0 -0
  129. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/profiler.h +0 -0
  130. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/random.h +0 -0
  131. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/tensor.cpp +0 -0
  132. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/tensor.h +0 -0
  133. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/text.h +0 -0
  134. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/version.cpp +0 -0
  135. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/version.h +0 -0
  136. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/ernie/util/worker_pool.h +0 -0
  137. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/mkdocs.yml +0 -0
  138. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/pyproject.toml +0 -0
  139. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/common.h +0 -0
  140. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/consumer/CMakeLists.txt +0 -0
  141. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/consumer/main.cpp +0 -0
  142. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/device/vulkan_devices_test.cpp +0 -0
  143. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/exr/README.md +0 -0
  144. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/exr/make_exr.py +0 -0
  145. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/exr/rgb_float_zip.exr +0 -0
  146. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/exr/rgba_half_window.exr +0 -0
  147. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/exr/y_half_zips.exr +0 -0
  148. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/ies/README.md +0 -0
  149. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/ies/downlight_quadrant.ies +0 -0
  150. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/ies/floodlight_type_b.ies +0 -0
  151. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/ies/lamp.tilt +0 -0
  152. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/images/grey16.png +0 -0
  153. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/ktx2/README.md +0 -0
  154. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/ktx2/quadrants_etc1s.ktx2 +0 -0
  155. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/ktx2/quadrants_uastc_zstd.ktx2 +0 -0
  156. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/ktx2/tilted_normal_etc1s.ktx2 +0 -0
  157. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/ktx2/tilted_normal_uastc.ktx2 +0 -0
  158. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/tiff/README.md +0 -0
  159. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/tiff/float_deflate_predictor3.tif +0 -0
  160. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/tiff/float_raw.tif +0 -0
  161. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/tiff/int16_bigtiff_bigendian.tif +0 -0
  162. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/tiff/rgb_lzw_predictor2.tif +0 -0
  163. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/tiff/rgb_planar_lzw.tif +0 -0
  164. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/tiff/rgb_planar_raw.tif +0 -0
  165. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/tiff/rgb_tiled_deflate.tif +0 -0
  166. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/volumes/cube.nvdb +0 -0
  167. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/fixtures/volumes/make_nvdb.py +0 -0
  168. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/geometry/bounds_test.cpp +0 -0
  169. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/io/ies_test.cpp +0 -0
  170. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/io/image_test.cpp +0 -0
  171. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/io/nanovdb_test.cpp +0 -0
  172. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/io/raster_test.cpp +0 -0
  173. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/io/texture_test.cpp +0 -0
  174. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/physics/astronomy_test.cpp +0 -0
  175. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/physics/atmosphere_test.cpp +0 -0
  176. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/physics/cloud_test.cpp +0 -0
  177. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/physics/reflectance_library_test.cpp +0 -0
  178. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/physics/regolith_test.cpp +0 -0
  179. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/physics/scattering_test.cpp +0 -0
  180. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/physics/solar_test.cpp +0 -0
  181. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/physics/spectrum_test.cpp +0 -0
  182. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/python/test_package.py +0 -0
  183. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/scene/path_test.cpp +0 -0
  184. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/scene/scene_test.cpp +0 -0
  185. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/scene/schema_test.cpp +0 -0
  186. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/scene/storage_test.cpp +0 -0
  187. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/scene/xform_test.cpp +0 -0
  188. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/algorithm_test.cpp +0 -0
  189. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/bytes_test.cpp +0 -0
  190. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/disk_cache_test.cpp +0 -0
  191. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/file_test.cpp +0 -0
  192. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/hash_index_test.cpp +0 -0
  193. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/linear_algebra_test.cpp +0 -0
  194. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/log_test.cpp +0 -0
  195. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/math_test.cpp +0 -0
  196. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/noise_test.cpp +0 -0
  197. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/parallel_test.cpp +0 -0
  198. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/profiler_test.cpp +0 -0
  199. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/random_test.cpp +0 -0
  200. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/tensor_test.cpp +0 -0
  201. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/text_test.cpp +0 -0
  202. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/version_test.cpp +0 -0
  203. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/tests/util/worker_pool_test.cpp +0 -0
  204. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/CMakeLists.txt +0 -0
  205. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/LICENSE +0 -0
  206. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/LICENSES/Apache-2.0.txt +0 -0
  207. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/LICENSES/BSD-3-clause.txt +0 -0
  208. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/LICENSES/MIT.txt +0 -0
  209. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/NOTICE +0 -0
  210. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/README.md +0 -0
  211. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu.h +0 -0
  212. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_astc_cfgs.inl +0 -0
  213. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_astc_hdr_core.h +0 -0
  214. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_astc_helpers.h +0 -0
  215. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_containers.h +0 -0
  216. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_containers_impl.h +0 -0
  217. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_dds_transcoder.inl +0 -0
  218. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_etc1_mods.inl +0 -0
  219. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_file_headers.h +0 -0
  220. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_idct.h +0 -0
  221. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder.cpp +0 -0
  222. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder.h +0 -0
  223. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_internal.h +0 -0
  224. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_tables_astc.inc +0 -0
  225. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_tables_astc_0_255.inc +0 -0
  226. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_tables_atc_55.inc +0 -0
  227. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_tables_atc_56.inc +0 -0
  228. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_tables_bc7_m5_alpha.inc +0 -0
  229. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_tables_bc7_m5_color.inc +0 -0
  230. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_tables_dxt1_5.inc +0 -0
  231. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_tables_dxt1_6.inc +0 -0
  232. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_tables_pvrtc2_45.inc +0 -0
  233. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_tables_pvrtc2_alpha_33.inc +0 -0
  234. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_transcoder_uastc.h +0 -0
  235. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_xbc7_decoder.h +0 -0
  236. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/transcoder/basisu_xbc7_decoder.inl +0 -0
  237. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/zstd/LICENSE +0 -0
  238. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/zstd/zstd.h +0 -0
  239. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/basisu/zstd/zstd_errors.h +0 -0
  240. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/third_party/nanovdb/LICENSE +0 -0
  241. {ernie_renderer-0.2.0.dev21 → ernie_renderer-0.2.0.dev22}/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 ".dev21" CACHE STRING "Pre-release suffix of Ernie's version")
18
+ set(ERNIE_VERSION_SUFFIX ".dev22" 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.dev21
3
+ Version: 0.2.0.dev22
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
@@ -8,7 +8,9 @@ add_library(
8
8
  storage.cpp
9
9
  view.cpp
10
10
  xform.cpp
11
+ schemas/collection.cpp
11
12
  schemas/geom.cpp
12
13
  schemas/registry.cpp
14
+ schemas/shade.cpp
13
15
  )
14
16
  target_link_libraries(ernie_scene PUBLIC ernie_physics ernie_io PRIVATE ernie_build_options)
@@ -7,6 +7,7 @@
7
7
  #include "ernie/scene/schemas/geom.h"
8
8
  #include "ernie/scene/tokens.h"
9
9
  #include "ernie/scene/xform.h"
10
+ #include "ernie/util/algorithm.h"
10
11
 
11
12
  #include <algorithm>
12
13
  #include <stdexcept>
@@ -15,9 +16,9 @@
15
16
  namespace ernie {
16
17
  namespace {
17
18
 
18
- /// @return A column layout holding `fallback` in unauthored rows.
19
- ColumnLayout MakeLayout(PathTable& paths, const AttributeDef& def) {
20
- const AttributeId attribute = paths.Names().Intern(def.name);
19
+ /// @return A column layout for the attribute `name` holding `def`'s fallback in unauthored rows.
20
+ ColumnLayout MakeLayout(PathTable& paths, const AttributeDef& def, std::string_view name) {
21
+ const AttributeId attribute = paths.Names().Intern(name);
21
22
  return WithColumnType(def.type, [&]<typename T>(std::type_identity<T>) {
22
23
  if constexpr (std::is_same_v<T, Tensor>) {
23
24
  return ColumnLayout::Of<T>(attribute);
@@ -38,7 +39,7 @@ std::string Describe(const Scene& scene, PrimId prim) {
38
39
  Scene::Scene()
39
40
  : invisible_(store_.Tokens().Intern(tokens::kInvisible)),
40
41
  defaultPurpose_(store_.Tokens().Intern(tokens::kDefault)) {
41
- BucketFor(nullptr);
42
+ FindOrAddBucket(nullptr, {});
42
43
  }
43
44
 
44
45
  PrimId Scene::Define(const Path& path, std::string_view type) {
@@ -57,12 +58,11 @@ PrimId Scene::Define(const Path& path, std::string_view type) {
57
58
  store_.Define(above, 0);
58
59
  }
59
60
  }
60
- const BucketId bucket = BucketFor(schema);
61
61
  if (const std::optional<PrimId> existing = store_.Find(id)) {
62
- store_.Move(*existing, bucket);
62
+ MoveTo(*existing, schema, Apis(*existing));
63
63
  return *existing;
64
64
  }
65
- return store_.Define(id, bucket);
65
+ return store_.Define(id, FindOrAddBucket(schema, {}));
66
66
  }
67
67
 
68
68
  bool Scene::Remove(const Path& path) {
@@ -138,7 +138,7 @@ void Scene::Set(PrimId prim, std::string_view attribute, const Value& value) {
138
138
  const AttributeId token = store_.Tokens().Intern(attribute);
139
139
  const AttributeDef* def = Declared(prim, token);
140
140
  if (def != nullptr) {
141
- Validate(*def, value, PrimPath(prim));
141
+ Validate(*def, attribute, value, PrimPath(prim));
142
142
  }
143
143
  const ColumnType type = def != nullptr ? def->type : TypeForUndeclared(prim, attribute, value);
144
144
  WithColumnType(type, [&]<typename T>(std::type_identity<T>) {
@@ -258,26 +258,68 @@ PrimId Scene::Require(const Path& path) const {
258
258
  return *prim;
259
259
  }
260
260
 
261
- BucketId Scene::BucketFor(const SchemaDef* schema) {
262
- if (const auto found = bucketBySchema_.find(schema); found != bucketBySchema_.end()) {
263
- return found->second;
264
- }
261
+ BucketId Scene::FindOrAddBucket(const SchemaDef* schema, std::vector<Token> apis) {
265
262
  PathTable& paths = store_.Paths();
263
+ const BucketKey key{paths.Names().Intern(schema != nullptr ? schema->name : ""),
264
+ std::move(apis)};
265
+ if (const std::optional<BucketId> found = store_.FindBucket(key)) {
266
+ return *found;
267
+ }
266
268
  BucketSchema entry{schema, {}};
267
269
  std::vector<ColumnLayout> layout;
268
- for (const AttributeDef* def :
269
- schema != nullptr ? schema->AllAttributes() : std::vector<const AttributeDef*>{}) {
270
- layout.push_back(MakeLayout(paths, *def));
271
- entry.declared.emplace(layout.back().attribute, def);
270
+ const auto add = [&](const SchemaDef& declaring, const ApiName& api) {
271
+ for (const AttributeDef* def : declaring.AllAttributes()) {
272
+ layout.push_back(MakeLayout(paths, *def, api.Attribute(def->name)));
273
+ entry.declared.emplace(layout.back().attribute, def);
274
+ }
275
+ };
276
+ if (schema != nullptr) {
277
+ add(*schema, {});
278
+ }
279
+ for (const Token token : key.apiSchemas) {
280
+ const ApiName api = ApiName::Parse(paths.Names().Text(token));
281
+ add(*api.schema, api);
272
282
  }
273
- const Token type = paths.Names().Intern(schema != nullptr ? schema->name : "");
274
- const BucketId bucket = store_.AddBucket({type, {}}, layout);
283
+ const BucketId bucket = store_.AddBucket(key, layout);
275
284
  buckets_.resize(std::max<std::size_t>(buckets_.size(), bucket + 1));
276
285
  buckets_[bucket] = std::move(entry);
277
- bucketBySchema_.emplace(schema, bucket);
278
286
  return bucket;
279
287
  }
280
288
 
289
+ void Scene::MoveTo(PrimId prim, const SchemaDef* schema, std::vector<Token> apis) {
290
+ store_.Move(prim, FindOrAddBucket(schema, std::move(apis)));
291
+ }
292
+
293
+ const std::vector<Token>& Scene::Apis(PrimId prim) const {
294
+ return store_.GetBucket(store_.PrimBucket(prim)).key.apiSchemas;
295
+ }
296
+
297
+ void Scene::ApplyApi(PrimId prim, std::string_view api) {
298
+ ApiName::Parse(api);
299
+ std::vector<Token> apis = Apis(prim);
300
+ apis.push_back(store_.Tokens().Intern(api));
301
+ MoveTo(prim, Schema(prim), std::move(apis));
302
+ }
303
+
304
+ bool Scene::RemoveApi(PrimId prim, std::string_view api) {
305
+ if (!HasApi(prim, api)) {
306
+ return false;
307
+ }
308
+ std::vector<Token> apis = Apis(prim);
309
+ std::erase(apis, *store_.Tokens().Find(api));
310
+ MoveTo(prim, Schema(prim), std::move(apis));
311
+ return true;
312
+ }
313
+
314
+ bool Scene::HasApi(PrimId prim, std::string_view api) const {
315
+ const std::optional<Token> token = store_.Tokens().Find(api);
316
+ return token && std::ranges::find(Apis(prim), *token) != Apis(prim).end();
317
+ }
318
+
319
+ std::vector<std::string> Scene::AppliedApis(PrimId prim) const {
320
+ return Map(Apis(prim), [&](Token token) { return std::string(store_.Tokens().Text(token)); });
321
+ }
322
+
281
323
  bool Scene::LeavesOutOfBounds(PrimId prim) const {
282
324
  const auto token = [&](std::string_view attribute) -> std::optional<Token> {
283
325
  const Column* column = AuthoredColumn(prim, attribute);
@@ -302,10 +344,17 @@ const AttributeDef* Scene::Declared(PrimId prim, AttributeId attribute) const {
302
344
  return found != declared.end() ? found->second : nullptr;
303
345
  }
304
346
 
347
+ bool Scene::TakesUndeclared(PrimId prim, std::string_view attribute) const {
348
+ const SchemaDef* schema = Schema(prim);
349
+ return schema == nullptr || schema->IsOpen(attribute) ||
350
+ std::ranges::any_of(Apis(prim), [&](Token api) {
351
+ return ApiName::Parse(store_.Tokens().Text(api)).schema->IsOpen(attribute);
352
+ });
353
+ }
354
+
305
355
  ColumnType Scene::TypeForUndeclared(PrimId prim, std::string_view attribute,
306
356
  const Value& value) const {
307
- const SchemaDef* schema = Schema(prim);
308
- if (schema != nullptr && !schema->IsOpen(attribute)) {
357
+ if (!TakesUndeclared(prim, attribute)) {
309
358
  throw std::invalid_argument(Describe(*this, prim) + " has no attribute '" +
310
359
  std::string(attribute) + "'");
311
360
  }
@@ -47,6 +47,17 @@ class Scene {
47
47
  /// @return Every prim whose type is `type` or derives from it; every prim for `""`.
48
48
  std::vector<Path> Prims(std::string_view type = {}) const;
49
49
 
50
+ /// @brief Applies an API schema, `"MaterialBindingAPI"`, or an instance of a multiple-apply
51
+ /// one, `"CollectionAPI:lights"`, adding its attributes at their fallbacks.
52
+ /// @throws std::invalid_argument for an unknown API schema or a missing or extra instance.
53
+ void ApplyApi(PrimId prim, std::string_view api);
54
+ /// @brief Removes an applied API schema with the values of its attributes.
55
+ /// @return Whether it was applied.
56
+ bool RemoveApi(PrimId prim, std::string_view api);
57
+ bool HasApi(PrimId prim, std::string_view api) const;
58
+ /// @return The applied API schemas, as `ApplyApi` names them.
59
+ std::vector<std::string> AppliedApis(PrimId prim) const;
60
+
50
61
  /// @brief Authors an attribute: a declared one converted to its type and checked, or an
51
62
  /// undeclared one, typed by its first value, in a namespace the type leaves open or on a prim
52
63
  /// without a type.
@@ -86,10 +97,17 @@ class Scene {
86
97
  std::unordered_map<AttributeId, const AttributeDef*> declared;
87
98
  };
88
99
 
89
- BucketId BucketFor(const SchemaDef* schema);
100
+ /// @return The bucket of a type and applied API schemas, made if new.
101
+ BucketId FindOrAddBucket(const SchemaDef* schema, std::vector<Token> apis);
102
+ /// Moves a prim to the bucket of its type and `apis`.
103
+ void MoveTo(PrimId prim, const SchemaDef* schema, std::vector<Token> apis);
104
+ const std::vector<Token>& Apis(PrimId prim) const;
90
105
  /// @return The attribute's column when the prim authors it, or null.
91
106
  const Column* AuthoredColumn(PrimId prim, std::string_view attribute) const;
92
107
  const AttributeDef* Declared(PrimId prim, AttributeId attribute) const;
108
+ /// @return Whether the prim's type or an applied API schema leaves the attribute's namespace
109
+ /// open; any attribute for a prim without a type.
110
+ bool TakesUndeclared(PrimId prim, std::string_view attribute) const;
93
111
  ColumnType TypeForUndeclared(PrimId prim, std::string_view attribute, const Value& value) const;
94
112
  /// @return Whether the prim and its subtree are invisible or of a purpose bounds leave out.
95
113
  bool LeavesOutOfBounds(PrimId prim) const;
@@ -100,7 +118,6 @@ class Scene {
100
118
  Token invisible_ = 0;
101
119
  Token defaultPurpose_ = 0;
102
120
  std::vector<BucketSchema> buckets_;
103
- std::unordered_map<const SchemaDef*, BucketId> bucketBySchema_;
104
121
  };
105
122
 
106
123
  } // namespace ernie
@@ -114,9 +114,39 @@ const SchemaDef* FindSchema(std::string_view name) {
114
114
  return found != schemas.end() ? *found : nullptr;
115
115
  }
116
116
 
117
- void Validate(const AttributeDef& def, const Value& value, const Path& path) {
117
+ ApiName ApiName::Parse(std::string_view api) {
118
+ const std::size_t colon = api.find(':');
119
+ const std::string_view name = api.substr(0, colon);
120
+ const ApiName parsed{FindSchema(name), colon == std::string_view::npos ? std::string_view()
121
+ : api.substr(colon + 1)};
122
+ const bool single = parsed.schema != nullptr && parsed.schema->kind == SchemaKind::SingleApply;
123
+ const bool multiple =
124
+ parsed.schema != nullptr && parsed.schema->kind == SchemaKind::MultipleApply;
125
+ if (!(single && parsed.instance.empty()) && !(multiple && IsIdentifier(parsed.instance))) {
126
+ throw std::invalid_argument(
127
+ "'" + std::string(api) + "' is no API schema" +
128
+ (multiple ? ": a multiple-apply one takes an instance name, as CollectionAPI:lights"
129
+ : ""));
130
+ }
131
+ return parsed;
132
+ }
133
+
134
+ std::string ApiName::Attribute(std::string_view declared) const {
135
+ std::string name(declared);
136
+ if (const std::size_t at = name.find(kInstanceName); at != std::string::npos) {
137
+ name.replace(at, kInstanceName.size(), instance);
138
+ }
139
+ return name;
140
+ }
141
+
142
+ std::string ApiName::ToString() const {
143
+ return std::string(schema->name) + (instance.empty() ? "" : ":" + std::string(instance));
144
+ }
145
+
146
+ void Validate(const AttributeDef& def, std::string_view attribute, const Value& value,
147
+ const Path& path) {
118
148
  if (const std::string problem = Problem(def, value); !problem.empty()) {
119
- throw std::invalid_argument("'" + path.String() + "': '" + std::string(def.name) + "' " +
149
+ throw std::invalid_argument("'" + path.String() + "': '" + std::string(attribute) + "' " +
120
150
  problem);
121
151
  }
122
152
  }
@@ -168,10 +168,28 @@ std::span<const SchemaDef* const> Schemas();
168
168
  /// @return The schema named `name`, or null.
169
169
  const SchemaDef* FindSchema(std::string_view name);
170
170
 
171
+ /// What a multiple-apply schema's attribute names hold in place of the instance's name.
172
+ inline constexpr std::string_view kInstanceName = "__INSTANCE_NAME__";
173
+
174
+ /// @brief An applied API schema: `"MaterialBindingAPI"`, or `"CollectionAPI:lights"`.
175
+ struct ApiName {
176
+ const SchemaDef* schema = nullptr;
177
+ std::string_view instance;
178
+
179
+ /// @throws std::invalid_argument for an unknown API schema or a missing or extra instance.
180
+ static ApiName Parse(std::string_view api);
181
+ /// @return A declared name with the instance's name in place of `kInstanceName`.
182
+ std::string Attribute(std::string_view declared) const;
183
+ /// @return The name `Parse` reads.
184
+ std::string ToString() const;
185
+ };
186
+
171
187
  /// @brief Checks a value against a declared attribute's limits and options; the scene checks its
172
188
  /// type as it converts it.
189
+ /// @param attribute The attribute's name, an instance's for a multiple-apply schema's.
173
190
  /// @throws std::invalid_argument naming the prim, the attribute and the reason.
174
- void Validate(const AttributeDef& def, const Value& value, const Path& path);
191
+ void Validate(const AttributeDef& def, std::string_view attribute, const Value& value,
192
+ const Path& path);
175
193
 
176
194
  /// @brief The tokens of an enum a token attribute takes, in enumerator order.
177
195
  template <typename E> struct ChoiceTokens;
@@ -0,0 +1,11 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file collection.cpp
3
+ /// @brief CollectionAPI's registry entry.
4
+ #include "ernie/scene/schemas/collection.h"
5
+
6
+ namespace ernie {
7
+
8
+ ERNIE_DEFINE_SCHEMA(CollectionAPI, "CollectionAPI", nullptr, MultipleApply, kInheritExtent,
9
+ "A named set of prims.", ERNIE_COLLECTION_API_ATTRIBUTES)
10
+
11
+ } // namespace ernie
@@ -0,0 +1,46 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file collection.h
3
+ /// @brief Usd's CollectionAPI: named sets of prims, applied once per collection.
4
+ ///
5
+ /// References:
6
+ /// - Pixar, UsdCollectionAPI, https://openusd.org/release/api/class_usd_collection_a_p_i.html
7
+ #pragma once
8
+
9
+ #include "ernie/scene/view.h"
10
+
11
+ #include <array>
12
+ #include <string_view>
13
+ #include <vector>
14
+
15
+ // clang-format off
16
+ #define ERNIE_COLLECTION_API_ATTRIBUTES(X) \
17
+ X(Choice<ExpansionRule>, ExpansionRule, "collection:__INSTANCE_NAME__:expansionRule", \
18
+ ExpansionRule::ExpandPrims, \
19
+ "explicitOnly: the targets alone; expandPrims: their descendants too; " \
20
+ "expandPrimsAndProperties: and their properties.", \
21
+ .group = "Collection") \
22
+ X(bool, IncludeRoot, "collection:__INSTANCE_NAME__:includeRoot", false, \
23
+ "Whether the root prim is a member.", .group = "Collection") \
24
+ X(std::vector<Path>, Includes, "collection:__INSTANCE_NAME__:includes", std::vector<Path>{}, \
25
+ "The prims, with their descendants per the rule, in the collection.", .group = "Collection") \
26
+ X(std::vector<Path>, Excludes, "collection:__INSTANCE_NAME__:excludes", std::vector<Path>{}, \
27
+ "The prims, with their descendants, left out.", .group = "Collection")
28
+ // clang-format on
29
+
30
+ namespace ernie {
31
+
32
+ enum class ExpansionRule { ExplicitOnly, ExpandPrims, ExpandPrimsAndProperties };
33
+
34
+ template <> struct ChoiceTokens<ExpansionRule> {
35
+ static constexpr std::array<std::string_view, 3> kTokens{"explicitOnly", "expandPrims",
36
+ "expandPrimsAndProperties"};
37
+ };
38
+
39
+ ERNIE_SCHEMA_ACCESSORS(CollectionAPI, SchemaView, ERNIE_COLLECTION_API_ATTRIBUTES);
40
+
41
+ /// A named set of prims, as light linking and material collections use them.
42
+ class CollectionAPI : public CollectionAPIAccessors<CollectionAPI, SchemaView> {
43
+ ERNIE_API_SCHEMA_BODY(CollectionAPI)
44
+ };
45
+
46
+ } // namespace ernie
@@ -0,0 +1,23 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file registry.cpp
3
+ /// @brief The list of every registered schema.
4
+ #include "ernie/scene/schemas/collection.h"
5
+ #include "ernie/scene/schemas/geom.h"
6
+ #include "ernie/scene/schemas/shade.h"
7
+
8
+ namespace ernie {
9
+
10
+ std::span<const SchemaDef* const> Schemas() {
11
+ static const std::array kSchemas{
12
+ &Imageable::Definition(), &Xformable::Definition(),
13
+ &Boundable::Definition(), &Gprim::Definition(),
14
+ &Xform::Definition(), &Scope::Definition(),
15
+ &Cube::Definition(), &Sphere::Definition(),
16
+ &Cylinder::Definition(), &Cone::Definition(),
17
+ &Capsule::Definition(), &Plane::Definition(),
18
+ &CollectionAPI::Definition(), &MaterialBindingAPI::Definition(),
19
+ };
20
+ return kSchemas;
21
+ }
22
+
23
+ } // namespace ernie
@@ -0,0 +1,12 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file shade.cpp
3
+ /// @brief UsdShade's registry entries.
4
+ #include "ernie/scene/schemas/shade.h"
5
+
6
+ namespace ernie {
7
+
8
+ ERNIE_DEFINE_SCHEMA(MaterialBindingAPI, "MaterialBindingAPI", nullptr, SingleApply, kInheritExtent,
9
+ "Binds a material to a prim and its descendants.",
10
+ ERNIE_MATERIAL_BINDING_API_ATTRIBUTES, "material:binding:")
11
+
12
+ } // namespace ernie
@@ -0,0 +1,27 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file shade.h
3
+ /// @brief UsdShade's schemas.
4
+ ///
5
+ /// References:
6
+ /// - Pixar, UsdShade, https://openusd.org/release/api/usd_shade_page_front.html
7
+ #pragma once
8
+
9
+ #include "ernie/scene/view.h"
10
+
11
+ // clang-format off
12
+ #define ERNIE_MATERIAL_BINDING_API_ATTRIBUTES(X) \
13
+ X(Path, MaterialBinding, "material:binding", Path(), \
14
+ "The Material the prim and its descendants are drawn with.", .label = "Material", \
15
+ .group = "Material", .dirty = Dirty::Material)
16
+ // clang-format on
17
+
18
+ namespace ernie {
19
+
20
+ ERNIE_SCHEMA_ACCESSORS(MaterialBindingAPI, SchemaView, ERNIE_MATERIAL_BINDING_API_ATTRIBUTES);
21
+
22
+ /// Binds a material to a prim; `material:binding:<purpose>` binds one for a purpose.
23
+ class MaterialBindingAPI : public MaterialBindingAPIAccessors<MaterialBindingAPI, SchemaView> {
24
+ ERNIE_API_SCHEMA_BODY(MaterialBindingAPI)
25
+ };
26
+
27
+ } // namespace ernie
@@ -25,11 +25,21 @@ std::size_t PrimStore::KeyHash::operator()(const BucketKey& key) const {
25
25
  return static_cast<std::size_t>(hash);
26
26
  }
27
27
 
28
+ BucketKey BucketKey::Normalized() const {
29
+ BucketKey sorted = *this;
30
+ std::ranges::sort(sorted.apiSchemas);
31
+ const auto [last, end] = std::ranges::unique(sorted.apiSchemas);
32
+ sorted.apiSchemas.erase(last, end);
33
+ return sorted;
34
+ }
35
+
36
+ std::optional<BucketId> PrimStore::FindBucket(const BucketKey& key) const {
37
+ const auto found = bucketIndex_.find(key.Normalized());
38
+ return found != bucketIndex_.end() ? std::optional(found->second) : std::nullopt;
39
+ }
40
+
28
41
  BucketId PrimStore::AddBucket(const BucketKey& key, std::span<const ColumnLayout> layout) {
29
- BucketKey sorted = key;
30
- std::sort(sorted.apiSchemas.begin(), sorted.apiSchemas.end());
31
- sorted.apiSchemas.erase(std::unique(sorted.apiSchemas.begin(), sorted.apiSchemas.end()),
32
- sorted.apiSchemas.end());
42
+ BucketKey sorted = key.Normalized();
33
43
  if (const auto found = bucketIndex_.find(sorted); found != bucketIndex_.end()) {
34
44
  return found->second;
35
45
  }
@@ -194,6 +194,8 @@ struct BucketKey {
194
194
  Token type = 0;
195
195
  std::vector<Token> apiSchemas;
196
196
 
197
+ /// @return The key with its API schemas sorted and without repeats.
198
+ BucketKey Normalized() const;
197
199
  bool operator==(const BucketKey&) const = default;
198
200
  };
199
201
 
@@ -308,6 +310,7 @@ class PrimStore {
308
310
 
309
311
  /// @return The bucket of `key`, made with `layout`'s columns if new.
310
312
  BucketId AddBucket(const BucketKey& key, std::span<const ColumnLayout> layout);
313
+ std::optional<BucketId> FindBucket(const BucketKey& key) const;
311
314
  const Bucket& GetBucket(BucketId bucket) const {
312
315
  return *buckets_[bucket];
313
316
  }
@@ -9,8 +9,20 @@
9
9
  namespace ernie {
10
10
  namespace {
11
11
 
12
- PrimId Check(const Scene& scene, const Path& path, const SchemaDef& schema) {
12
+ bool IsApi(const SchemaDef& schema) {
13
+ return schema.kind == SchemaKind::SingleApply || schema.kind == SchemaKind::MultipleApply;
14
+ }
15
+
16
+ PrimId Check(const Scene& scene, const Path& path, const SchemaDef& schema,
17
+ std::string_view instance) {
13
18
  const PrimId prim = scene.Require(path);
19
+ if (IsApi(schema)) {
20
+ const std::string api = ApiName{&schema, instance}.ToString();
21
+ if (!scene.HasApi(prim, api)) {
22
+ throw std::invalid_argument("'" + path.String() + "' has no " + api + " applied");
23
+ }
24
+ return prim;
25
+ }
14
26
  const SchemaDef* type = scene.Schema(prim);
15
27
  if (type == nullptr || !type->IsA(schema)) {
16
28
  const std::string_view name = type != nullptr ? type->name : "a prim without a type";
@@ -22,11 +34,15 @@ PrimId Check(const Scene& scene, const Path& path, const SchemaDef& schema) {
22
34
 
23
35
  } // namespace
24
36
 
25
- SchemaView::SchemaView(const Scene& scene, const Path& path, const SchemaDef& schema)
26
- : scene_(&scene), prim_(Check(scene, path, schema)), schema_(&schema) {}
37
+ SchemaView::SchemaView(const Scene& scene, const Path& path, const SchemaDef& schema,
38
+ std::string_view instance)
39
+ : scene_(&scene), prim_(Check(scene, path, schema, instance)), schema_(&schema),
40
+ instance_(instance) {}
27
41
 
28
- SchemaView::SchemaView(Scene& scene, const Path& path, const SchemaDef& schema)
29
- : scene_(&scene), mutable_(&scene), prim_(Check(scene, path, schema)), schema_(&schema) {}
42
+ SchemaView::SchemaView(Scene& scene, const Path& path, const SchemaDef& schema,
43
+ std::string_view instance)
44
+ : scene_(&scene), mutable_(&scene), prim_(Check(scene, path, schema, instance)),
45
+ schema_(&schema), instance_(instance) {}
30
46
 
31
47
  Scene& SchemaView::Edit() const {
32
48
  if (mutable_ == nullptr) {
@@ -98,26 +98,50 @@ class SchemaView {
98
98
  return *schema_;
99
99
  }
100
100
 
101
+ /// The instance name of a multiple-apply API schema's view; empty otherwise.
102
+ std::string_view Instance() const {
103
+ return instance_;
104
+ }
105
+
101
106
  protected:
102
- SchemaView(const Scene& scene, const Path& path, const SchemaDef& schema);
103
- SchemaView(Scene& scene, const Path& path, const SchemaDef& schema);
107
+ /// @throws std::invalid_argument if the prim is missing, is not of `schema`'s type or lacks
108
+ /// the applied API schema.
109
+ SchemaView(const Scene& scene, const Path& path, const SchemaDef& schema,
110
+ std::string_view instance = {});
111
+ SchemaView(Scene& scene, const Path& path, const SchemaDef& schema,
112
+ std::string_view instance = {});
113
+
114
+ /// Calls `use` with a declared attribute's name, its instance's for a multiple-apply schema.
115
+ template <typename Use> decltype(auto) Named(std::string_view declared, const Use& use) const {
116
+ if (instance_.empty()) {
117
+ return use(declared);
118
+ }
119
+ const std::string name = ApiName{schema_, instance_}.Attribute(declared);
120
+ return use(std::string_view(name));
121
+ }
104
122
 
105
- template <typename T> typename AttributeTraits<T>::Result Read(std::string_view name) const {
106
- using Traits = AttributeTraits<T>;
107
- const PrimStore& store = scene_->Store();
108
- const Token token = *store.Paths().Names().Find(name);
109
- const auto column = store.Read<typename Traits::Stored>(store.PrimBucket(prim_), token);
110
- return Traits::Load(store.Paths(), column[store.PrimRow(prim_)]);
123
+ template <typename T>
124
+ typename AttributeTraits<T>::Result Read(std::string_view declared) const {
125
+ return Named(declared, [&](std::string_view name) {
126
+ using Traits = AttributeTraits<T>;
127
+ const PrimStore& store = scene_->Store();
128
+ const Token token = *store.Tokens().Find(name);
129
+ const auto column = store.Read<typename Traits::Stored>(store.PrimBucket(prim_), token);
130
+ return Traits::Load(store.Paths(), column[store.PrimRow(prim_)]);
131
+ });
111
132
  }
112
133
  template <typename T>
113
- void Write(std::string_view name, const typename AttributeTraits<T>::Result& value) {
114
- Edit().Set(prim_, name, AttributeTraits<T>::Save(value));
134
+ void Write(std::string_view declared, const typename AttributeTraits<T>::Result& value) {
135
+ Named(declared, [&](std::string_view name) {
136
+ Edit().Set(prim_, name, AttributeTraits<T>::Save(value));
137
+ });
115
138
  }
116
- bool Has(std::string_view name) const {
117
- return scene_->IsAuthored(prim_, name);
139
+ bool Has(std::string_view declared) const {
140
+ return Named(declared,
141
+ [&](std::string_view name) { return scene_->IsAuthored(prim_, name); });
118
142
  }
119
- void Unset(std::string_view name) {
120
- Edit().Clear(prim_, name);
143
+ void Unset(std::string_view declared) {
144
+ Named(declared, [&](std::string_view name) { Edit().Clear(prim_, name); });
121
145
  }
122
146
  Scene& Edit() const;
123
147
 
@@ -126,6 +150,7 @@ class SchemaView {
126
150
  Scene* mutable_ = nullptr;
127
151
  PrimId prim_;
128
152
  const SchemaDef* schema_ = nullptr;
153
+ std::string instance_;
129
154
  };
130
155
 
131
156
  /// The root of every generated accessor chain.
@@ -197,6 +222,23 @@ template <typename Self, typename Base> class SchemaViewAccessors : public Base
197
222
  return Class(scene, path); \
198
223
  }
199
224
 
225
+ /// The constructors, `Apply` and registry entry of an API schema's view; a multiple-apply
226
+ /// schema's take its instance name.
227
+ #define ERNIE_API_SCHEMA_BODY(Class) \
228
+ public: \
229
+ using Self = Class; \
230
+ /** @throws std::invalid_argument if the prim is missing or lacks the API schema. */ \
231
+ Class(const ::ernie::Scene& scene, const ::ernie::Path& path, std::string_view instance = {}) \
232
+ : Class##Accessors<Class, ::ernie::SchemaView>(scene, path, Definition(), instance) {} \
233
+ Class(::ernie::Scene& scene, const ::ernie::Path& path, std::string_view instance = {}) \
234
+ : Class##Accessors<Class, ::ernie::SchemaView>(scene, path, Definition(), instance) {} \
235
+ static const ::ernie::SchemaDef& Definition(); \
236
+ static Class Apply(::ernie::Scene& scene, const ::ernie::Path& path, \
237
+ std::string_view instance = {}) { \
238
+ scene.ApplyApi(scene.Require(path), ::ernie::ApiName{&Definition(), instance}.ToString()); \
239
+ return Class(scene, path, instance); \
240
+ }
241
+
200
242
  /// Defines `Class::Definition()`, the schema's registry entry.
201
243
  #define ERNIE_DEFINE_SCHEMA(Class, name, base, kind, extentRule, text, OWN_ATTRIBUTES, ...) \
202
244
  const ::ernie::SchemaDef& Class::Definition() { \
@@ -55,6 +55,7 @@ ernie_add_test_suite(
55
55
  ernie_add_test_suite(
56
56
  scene
57
57
  SOURCES
58
+ scene/api_test.cpp
58
59
  scene/path_test.cpp
59
60
  scene/scene_test.cpp
60
61
  scene/schema_test.cpp