ernie-renderer 0.2.0.dev37__tar.gz → 0.2.0.dev43__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 (272) hide show
  1. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/CMakeLists.txt +1 -1
  2. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/PKG-INFO +1 -1
  3. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/benchmarks/scene/extents.cpp +21 -6
  4. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/CMakeLists.txt +2 -0
  5. ernie_renderer-0.2.0.dev43/ernie/scene/holder_index.cpp +111 -0
  6. ernie_renderer-0.2.0.dev43/ernie/scene/holder_index.h +42 -0
  7. ernie_renderer-0.2.0.dev43/ernie/scene/inherit.cpp +120 -0
  8. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/scene.cpp +52 -15
  9. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/scene.h +47 -3
  10. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schema.cpp +22 -0
  11. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schema.h +13 -1
  12. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/geom.cpp +2 -0
  13. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/geom.h +52 -5
  14. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/mesh.cpp +13 -6
  15. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/mesh.h +47 -5
  16. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/registry.cpp +6 -0
  17. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/shade.h +1 -1
  18. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/storage.h +19 -0
  19. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/tokens.h +2 -0
  20. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/CMakeLists.txt +2 -0
  21. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/extent_cache_test.cpp +3 -3
  22. ernie_renderer-0.2.0.dev43/tests/scene/holder_index_test.cpp +63 -0
  23. ernie_renderer-0.2.0.dev43/tests/scene/inherit_test.cpp +129 -0
  24. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/mesh_test.cpp +21 -0
  25. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/schema_test.cpp +28 -0
  26. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/vol_test.cpp +1 -1
  27. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/.clang-format +0 -0
  28. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/.clang-tidy +0 -0
  29. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/.dockerignore +0 -0
  30. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/.gersemirc +0 -0
  31. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/.gitattributes +0 -0
  32. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/.github/scripts/coverage_badge.py +0 -0
  33. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/.github/scripts/install-lavapipe-windows.sh +0 -0
  34. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/.github/workflows/ci.yml +0 -0
  35. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/.gitignore +0 -0
  36. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/.pre-commit-config.yaml +0 -0
  37. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/CMakePresets.json +0 -0
  38. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/Dockerfile +0 -0
  39. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/LICENSE +0 -0
  40. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/README.md +0 -0
  41. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/benchmarks/CMakeLists.txt +0 -0
  42. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/benchmarks/bench.h +0 -0
  43. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/benchmarks/main.cpp +0 -0
  44. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/benchmarks/scene/storage.cpp +0 -0
  45. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/ErnieConfig.cmake.in +0 -0
  46. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/ErnieFetch.cmake +0 -0
  47. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/ErnieInstall.cmake +0 -0
  48. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/ErniePackaging.cmake +0 -0
  49. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/ErnieTesting.cmake +0 -0
  50. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/ernie.pc.in +0 -0
  51. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/third_party/bc7enc.cmake +0 -0
  52. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/third_party/dlpack.cmake +0 -0
  53. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/third_party/glm.cmake +0 -0
  54. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/third_party/googletest.cmake +0 -0
  55. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/third_party/json.cmake +0 -0
  56. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/third_party/nanobind.cmake +0 -0
  57. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/third_party/openexr.cmake +0 -0
  58. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/third_party/stb.cmake +0 -0
  59. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/third_party/tracy.cmake +0 -0
  60. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/third_party/volk.cmake +0 -0
  61. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/cmake/third_party/vulkan_headers.cmake +0 -0
  62. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/docs/README.md +0 -0
  63. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/docs/index.md +0 -0
  64. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/docs/requirements.txt +0 -0
  65. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/CMakeLists.txt +0 -0
  66. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/app/CMakeLists.txt +0 -0
  67. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/app/main.cpp +0 -0
  68. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/device/CMakeLists.txt +0 -0
  69. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/device/vulkan_devices.cpp +0 -0
  70. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/device/vulkan_devices.h +0 -0
  71. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/geometry/CMakeLists.txt +0 -0
  72. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/geometry/bounds.h +0 -0
  73. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/graph/CMakeLists.txt +0 -0
  74. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/io/CMakeLists.txt +0 -0
  75. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/io/ies.cpp +0 -0
  76. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/io/ies.h +0 -0
  77. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/io/image.cpp +0 -0
  78. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/io/image.h +0 -0
  79. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/io/nanovdb.cpp +0 -0
  80. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/io/nanovdb.h +0 -0
  81. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/io/raster.cpp +0 -0
  82. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/io/raster.h +0 -0
  83. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/io/texture.cpp +0 -0
  84. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/io/texture.h +0 -0
  85. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/CMakeLists.txt +0 -0
  86. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/astronomy.cpp +0 -0
  87. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/astronomy.h +0 -0
  88. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/atmosphere.cpp +0 -0
  89. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/atmosphere.h +0 -0
  90. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/cloud.cpp +0 -0
  91. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/cloud.h +0 -0
  92. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/constants.h +0 -0
  93. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/reflectance_library.cpp +0 -0
  94. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/reflectance_library.h +0 -0
  95. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/reflectance_table.h +0 -0
  96. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/regolith.cpp +0 -0
  97. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/regolith.h +0 -0
  98. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/scattering.cpp +0 -0
  99. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/scattering.h +0 -0
  100. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/solar.cpp +0 -0
  101. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/solar.h +0 -0
  102. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/solar_table.h +0 -0
  103. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/spectrum.cpp +0 -0
  104. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/physics/spectrum.h +0 -0
  105. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/python/CMakeLists.txt +0 -0
  106. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/python/ernie/__init__.py +0 -0
  107. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/python/module.cpp +0 -0
  108. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/render/CMakeLists.txt +0 -0
  109. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/convert.h +0 -0
  110. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/extent_cache.cpp +0 -0
  111. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/extent_cache.h +0 -0
  112. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/path.cpp +0 -0
  113. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/path.h +0 -0
  114. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/camera.cpp +0 -0
  115. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/camera.h +0 -0
  116. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/collection.cpp +0 -0
  117. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/collection.h +0 -0
  118. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/instancer.cpp +0 -0
  119. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/instancer.h +0 -0
  120. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/laser.cpp +0 -0
  121. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/laser.h +0 -0
  122. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/lux.cpp +0 -0
  123. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/lux.h +0 -0
  124. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/planet.cpp +0 -0
  125. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/planet.h +0 -0
  126. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/render.cpp +0 -0
  127. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/render.h +0 -0
  128. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/shade.cpp +0 -0
  129. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/vol.cpp +0 -0
  130. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/schemas/vol.h +0 -0
  131. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/storage.cpp +0 -0
  132. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/value.h +0 -0
  133. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/view.cpp +0 -0
  134. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/view.h +0 -0
  135. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/xform.cpp +0 -0
  136. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/scene/xform.h +0 -0
  137. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/CMakeLists.txt +0 -0
  138. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/algorithm.h +0 -0
  139. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/bytes.h +0 -0
  140. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/disk_cache.cpp +0 -0
  141. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/disk_cache.h +0 -0
  142. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/file.cpp +0 -0
  143. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/file.h +0 -0
  144. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/glm.h +0 -0
  145. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/hash_index.h +0 -0
  146. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/linear_algebra.h +0 -0
  147. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/log.cpp +0 -0
  148. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/log.h +0 -0
  149. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/math.h +0 -0
  150. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/noise.cpp +0 -0
  151. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/noise.h +0 -0
  152. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/numbers.h +0 -0
  153. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/parallel.h +0 -0
  154. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/profiler.cpp +0 -0
  155. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/profiler.h +0 -0
  156. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/random.h +0 -0
  157. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/tensor.cpp +0 -0
  158. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/tensor.h +0 -0
  159. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/text.h +0 -0
  160. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/version.cpp +0 -0
  161. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/version.h +0 -0
  162. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/ernie/util/worker_pool.h +0 -0
  163. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/mkdocs.yml +0 -0
  164. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/pyproject.toml +0 -0
  165. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/common.h +0 -0
  166. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/consumer/CMakeLists.txt +0 -0
  167. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/consumer/main.cpp +0 -0
  168. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/device/vulkan_devices_test.cpp +0 -0
  169. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/exr/README.md +0 -0
  170. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/exr/make_exr.py +0 -0
  171. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/exr/rgb_float_zip.exr +0 -0
  172. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/exr/rgba_half_window.exr +0 -0
  173. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/exr/y_half_zips.exr +0 -0
  174. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/ies/README.md +0 -0
  175. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/ies/downlight_quadrant.ies +0 -0
  176. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/ies/floodlight_type_b.ies +0 -0
  177. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/ies/lamp.tilt +0 -0
  178. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/images/grey16.png +0 -0
  179. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/ktx2/README.md +0 -0
  180. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/ktx2/quadrants_etc1s.ktx2 +0 -0
  181. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/ktx2/quadrants_uastc_zstd.ktx2 +0 -0
  182. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/ktx2/tilted_normal_etc1s.ktx2 +0 -0
  183. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/ktx2/tilted_normal_uastc.ktx2 +0 -0
  184. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/tiff/README.md +0 -0
  185. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/tiff/float_deflate_predictor3.tif +0 -0
  186. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/tiff/float_raw.tif +0 -0
  187. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/tiff/int16_bigtiff_bigendian.tif +0 -0
  188. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/tiff/rgb_lzw_predictor2.tif +0 -0
  189. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/tiff/rgb_planar_lzw.tif +0 -0
  190. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/tiff/rgb_planar_raw.tif +0 -0
  191. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/tiff/rgb_tiled_deflate.tif +0 -0
  192. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/volumes/cube.nvdb +0 -0
  193. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/fixtures/volumes/make_nvdb.py +0 -0
  194. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/geometry/bounds_test.cpp +0 -0
  195. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/io/ies_test.cpp +0 -0
  196. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/io/image_test.cpp +0 -0
  197. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/io/nanovdb_test.cpp +0 -0
  198. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/io/raster_test.cpp +0 -0
  199. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/io/texture_test.cpp +0 -0
  200. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/physics/astronomy_test.cpp +0 -0
  201. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/physics/atmosphere_test.cpp +0 -0
  202. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/physics/cloud_test.cpp +0 -0
  203. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/physics/reflectance_library_test.cpp +0 -0
  204. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/physics/regolith_test.cpp +0 -0
  205. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/physics/scattering_test.cpp +0 -0
  206. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/physics/solar_test.cpp +0 -0
  207. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/physics/spectrum_test.cpp +0 -0
  208. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/python/test_package.py +0 -0
  209. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/api_test.cpp +0 -0
  210. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/instancer_test.cpp +0 -0
  211. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/lux_test.cpp +0 -0
  212. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/path_test.cpp +0 -0
  213. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/planet_test.cpp +0 -0
  214. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/render_test.cpp +0 -0
  215. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/scene_test.cpp +0 -0
  216. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/shade_test.cpp +0 -0
  217. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/storage_test.cpp +0 -0
  218. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/scene/xform_test.cpp +0 -0
  219. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/algorithm_test.cpp +0 -0
  220. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/bytes_test.cpp +0 -0
  221. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/disk_cache_test.cpp +0 -0
  222. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/file_test.cpp +0 -0
  223. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/hash_index_test.cpp +0 -0
  224. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/linear_algebra_test.cpp +0 -0
  225. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/log_test.cpp +0 -0
  226. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/math_test.cpp +0 -0
  227. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/noise_test.cpp +0 -0
  228. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/parallel_test.cpp +0 -0
  229. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/profiler_test.cpp +0 -0
  230. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/random_test.cpp +0 -0
  231. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/tensor_test.cpp +0 -0
  232. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/text_test.cpp +0 -0
  233. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/version_test.cpp +0 -0
  234. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/tests/util/worker_pool_test.cpp +0 -0
  235. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/CMakeLists.txt +0 -0
  236. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/LICENSE +0 -0
  237. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/LICENSES/Apache-2.0.txt +0 -0
  238. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/LICENSES/BSD-3-clause.txt +0 -0
  239. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/LICENSES/MIT.txt +0 -0
  240. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/NOTICE +0 -0
  241. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/README.md +0 -0
  242. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu.h +0 -0
  243. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_astc_cfgs.inl +0 -0
  244. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_astc_hdr_core.h +0 -0
  245. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_astc_helpers.h +0 -0
  246. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_containers.h +0 -0
  247. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_containers_impl.h +0 -0
  248. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_dds_transcoder.inl +0 -0
  249. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_etc1_mods.inl +0 -0
  250. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_file_headers.h +0 -0
  251. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_idct.h +0 -0
  252. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder.cpp +0 -0
  253. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder.h +0 -0
  254. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_internal.h +0 -0
  255. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_tables_astc.inc +0 -0
  256. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_tables_astc_0_255.inc +0 -0
  257. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_tables_atc_55.inc +0 -0
  258. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_tables_atc_56.inc +0 -0
  259. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_tables_bc7_m5_alpha.inc +0 -0
  260. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_tables_bc7_m5_color.inc +0 -0
  261. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_tables_dxt1_5.inc +0 -0
  262. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_tables_dxt1_6.inc +0 -0
  263. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_tables_pvrtc2_45.inc +0 -0
  264. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_tables_pvrtc2_alpha_33.inc +0 -0
  265. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_transcoder_uastc.h +0 -0
  266. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_xbc7_decoder.h +0 -0
  267. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/transcoder/basisu_xbc7_decoder.inl +0 -0
  268. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/zstd/LICENSE +0 -0
  269. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/zstd/zstd.h +0 -0
  270. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/basisu/zstd/zstd_errors.h +0 -0
  271. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/third_party/nanovdb/LICENSE +0 -0
  272. {ernie_renderer-0.2.0.dev37 → ernie_renderer-0.2.0.dev43}/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 ".dev37" CACHE STRING "Pre-release suffix of Ernie's version")
18
+ set(ERNIE_VERSION_SUFFIX ".dev43" 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.dev37
3
+ Version: 0.2.0.dev43
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
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: BSD-3-Clause
2
2
  /// @file extents.cpp
3
- /// @brief Cached extents at 100,000 prims: the first update, and one edit's.
3
+ /// @brief Scene updates at 100,000 prims: the first, one edit's, and one inherited edit's.
4
4
  #include "benchmarks/bench.h"
5
5
  #include "ernie/scene/schemas/geom.h"
6
6
 
@@ -21,20 +21,35 @@ std::unique_ptr<Scene> MakeSpheres() {
21
21
  return scene;
22
22
  }
23
23
 
24
- const bool kFirstUpdate = Register("scene.extents.first_update_100k", [] {
24
+ const bool kFirstUpdate = Register("scene.update.first_100k", [] {
25
25
  std::unique_ptr<Scene> scene;
26
- return Timing{Fastest([&] { scene = MakeSpheres(); }, [&] { scene->UpdateExtents(); }), 10.0};
26
+ return Timing{Fastest([&] { scene = MakeSpheres(); }, [&] { scene->Update(); }), 10.0};
27
27
  });
28
28
 
29
- const bool kOneEdit = Register("scene.extents.update_after_one_edit_of_100k", [] {
29
+ const bool kOneEdit = Register("scene.update.after_one_edit_of_100k", [] {
30
30
  std::unique_ptr<Scene> scene = MakeSpheres();
31
- scene->UpdateExtents();
31
+ scene->Update();
32
32
  const PrimId ball = *scene->Find("/World/Ball_54321");
33
33
  double radius = 1.0;
34
34
  const double ms = Fastest([&] { scene->Set(ball, Sphere::kRadius, radius += 1.0); },
35
- [&] { scene->UpdateExtents(); });
35
+ [&] { scene->Update(); });
36
36
  return Timing{ms, 1.0};
37
37
  });
38
38
 
39
+ const bool kInheritedEdit = Register("scene.update.after_hiding_the_parent_of_100k", [] {
40
+ std::unique_ptr<Scene> scene = MakeSpheres();
41
+ scene->Define("/World", "Xform");
42
+ scene->Update();
43
+ const PrimId world = *scene->Find("/World");
44
+ bool hidden = false;
45
+ const double ms = Fastest(
46
+ [&] {
47
+ hidden = !hidden;
48
+ scene->Set(world, Imageable::kVisibility, hidden ? "invisible" : "inherited");
49
+ },
50
+ [&] { scene->Update(); });
51
+ return Timing{ms, 10.0};
52
+ });
53
+
39
54
  } // namespace
40
55
  } // namespace ernie::bench
@@ -3,6 +3,8 @@ add_library(
3
3
  ernie_scene
4
4
  OBJECT
5
5
  extent_cache.cpp
6
+ holder_index.cpp
7
+ inherit.cpp
6
8
  path.cpp
7
9
  schema.cpp
8
10
  scene.cpp
@@ -0,0 +1,111 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file holder_index.cpp
3
+ /// @brief Re-indexing changed relationship cells, and finding a target's live holders.
4
+ #include "ernie/scene/holder_index.h"
5
+
6
+ #include <algorithm>
7
+ #include <unordered_set>
8
+
9
+ namespace ernie {
10
+ namespace {
11
+
12
+ bool IsRelationship(ColumnType type) {
13
+ return type == ColumnType::Relationship || type == ColumnType::Relationships;
14
+ }
15
+
16
+ /// @return The targets of a relationship cell, without the unset one.
17
+ std::vector<PathId> Targets(const PrimStore& store, BucketId bucket, const Column& column,
18
+ std::uint32_t row) {
19
+ std::vector<PathId> targets;
20
+ if (column.values->Type() == ColumnType::Relationship) {
21
+ targets.push_back(store.Read<Target>(bucket, column.attribute)[row].path);
22
+ } else {
23
+ for (const Target target : store.Read<std::vector<Target>>(bucket, column.attribute)[row]) {
24
+ targets.push_back(target.path);
25
+ }
26
+ }
27
+ std::erase(targets, kNoPath);
28
+ return targets;
29
+ }
30
+
31
+ } // namespace
32
+
33
+ void HolderIndex::Update(const PrimStore& store) {
34
+ const ChangeSet changes = store.ChangesSince(cursor_);
35
+ for (const ChangeSet::Values& values : changes.values) {
36
+ const Bucket& bucket = store.GetBucket(values.bucket);
37
+ const Column& column = *bucket.Find(values.attribute);
38
+ if (!IsRelationship(column.values->Type())) {
39
+ continue;
40
+ }
41
+ for (const RowRange range : values.rows) {
42
+ for (std::uint32_t row = range.begin; row < std::min(range.end, bucket.Rows()); ++row) {
43
+ Index(bucket.prims[row], values.attribute,
44
+ Targets(store, values.bucket, column, row));
45
+ }
46
+ }
47
+ }
48
+ // A bucket too far behind to replay reports every row of every column, as a fresh one does.
49
+ for (const BucketId id : changes.resets) {
50
+ const Bucket& bucket = store.GetBucket(id);
51
+ for (const Column& column : bucket.columns) {
52
+ for (std::uint32_t row = 0;
53
+ IsRelationship(column.values->Type()) && row < bucket.Rows(); ++row) {
54
+ Index(bucket.prims[row], column.attribute, Targets(store, id, column, row));
55
+ }
56
+ }
57
+ }
58
+ cursor_ = changes.version;
59
+ }
60
+
61
+ void HolderIndex::Index(PrimId prim, AttributeId attribute, std::vector<PathId> targets) {
62
+ const Cell cell = Key(prim, attribute);
63
+ const auto found = targets_.find(cell);
64
+ if (found != targets_.end()) {
65
+ for (const PathId old : found->second) {
66
+ holders_[old].erase(cell);
67
+ }
68
+ }
69
+ for (const PathId target : targets) {
70
+ holders_[target][cell] = prim.generation;
71
+ }
72
+ if (!targets.empty()) {
73
+ targets_[cell] = std::move(targets);
74
+ } else if (found != targets_.end()) {
75
+ targets_.erase(found);
76
+ }
77
+ }
78
+
79
+ std::vector<PrimId> HolderIndex::Find(const PrimStore& store, PathId target) const {
80
+ std::vector<PrimId> found;
81
+ const auto holders = holders_.find(target);
82
+ if (holders == holders_.end()) {
83
+ return found;
84
+ }
85
+ std::unordered_set<std::uint32_t> slots;
86
+ for (const auto& [cell, generation] : holders->second) {
87
+ const PrimId prim{static_cast<std::uint32_t>(cell >> 32), generation};
88
+ // Cells of removed prims, or of prims since moved to a bucket without the attribute, stay
89
+ // until their slot's next prim writes them.
90
+ if (Holds(store, prim, static_cast<AttributeId>(cell), target) &&
91
+ slots.insert(prim.slot).second) {
92
+ found.push_back(prim);
93
+ }
94
+ }
95
+ return found;
96
+ }
97
+
98
+ bool HolderIndex::Holds(const PrimStore& store, PrimId prim, AttributeId attribute, PathId target) {
99
+ if (!store.Alive(prim)) {
100
+ return false;
101
+ }
102
+ const BucketId bucket = store.PrimBucket(prim);
103
+ const Column* column = store.GetBucket(bucket).Find(attribute);
104
+ if (column == nullptr || !IsRelationship(column->values->Type())) {
105
+ return false;
106
+ }
107
+ const std::vector<PathId> targets = Targets(store, bucket, *column, store.PrimRow(prim));
108
+ return std::ranges::find(targets, target) != targets.end();
109
+ }
110
+
111
+ } // namespace ernie
@@ -0,0 +1,42 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file holder_index.h
3
+ /// @brief The reverse index of relationships: which prims target each path.
4
+ #pragma once
5
+
6
+ #include "ernie/scene/storage.h"
7
+
8
+ #include <cstdint>
9
+ #include <unordered_map>
10
+ #include <vector>
11
+
12
+ namespace ernie {
13
+
14
+ /// @brief Which prims' relationships target each path, kept up to date from the store's changes,
15
+ /// so an edit to a target reaches its holders: a prototype its instancers, a material the prims
16
+ /// bound to it (through their resolved bindings), a body its terrains.
17
+ class HolderIndex {
18
+ public:
19
+ /// Re-indexes the relationship cells that changed since the last update.
20
+ void Update(const PrimStore& store);
21
+ /// @return The live prims with a relationship targeting `target`, each once.
22
+ std::vector<PrimId> Find(const PrimStore& store, PathId target) const;
23
+
24
+ private:
25
+ /// A relationship cell: the prim's slot and the attribute, packed.
26
+ using Cell = std::uint64_t;
27
+ static Cell Key(PrimId prim, AttributeId attribute) {
28
+ return (std::uint64_t{prim.slot} << 32) | attribute;
29
+ }
30
+
31
+ void Index(PrimId prim, AttributeId attribute, std::vector<PathId> targets);
32
+ /// @return Whether the prim is alive and its relationship still targets `target`.
33
+ static bool Holds(const PrimStore& store, PrimId prim, AttributeId attribute, PathId target);
34
+
35
+ /// Each target's holding cells, with the generation of the prim that wrote them.
36
+ std::unordered_map<PathId, std::unordered_map<Cell, std::uint32_t>> holders_;
37
+ /// Each cell's targets, to unindex them when it changes.
38
+ std::unordered_map<Cell, std::vector<PathId>> targets_;
39
+ std::uint64_t cursor_ = 0;
40
+ };
41
+
42
+ } // namespace ernie
@@ -0,0 +1,120 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ /// @file inherit.cpp
3
+ /// @brief Resolving inherited attributes from the nearest authoring ancestor into their resolved
4
+ /// columns, for only the subtrees whose authored values or prims changed.
5
+ #include "ernie/scene/convert.h"
6
+ #include "ernie/scene/scene.h"
7
+
8
+ #include <algorithm>
9
+ #include <concepts>
10
+ #include <limits>
11
+
12
+ namespace ernie {
13
+
14
+ void Scene::Resolve() {
15
+ const ChangeSet changes = store_.ChangesSince(resolved_);
16
+ for (const AttributeDef* def : InheritedAttributes()) {
17
+ const AttributeId attribute = store_.Tokens().Intern(def->name);
18
+ const AttributeId resolved = store_.Tokens().Intern(ResolvedName(def->name));
19
+ WithColumnType(def->type, [&]<typename T>(std::type_identity<T>) {
20
+ if constexpr (std::equality_comparable<T> && !std::same_as<T, Tensor>) {
21
+ const T fallback = ToElement<T>(store_.Paths(), def->fallback).value_or(T{});
22
+ BitSet roots = ResolveRoots(changes, attribute);
23
+ std::vector<PathId> order;
24
+ roots.ForEachRun([&](std::size_t begin, std::size_t end) {
25
+ for (std::size_t path = begin; path < end; ++path) {
26
+ order.push_back(static_cast<PathId>(path));
27
+ }
28
+ });
29
+ // Ancestors intern first, so most roots are reached from one above them.
30
+ for (const PathId root : order) {
31
+ if (roots.Test(root)) {
32
+ ResolveSubtree<T>(root, attribute, resolved, fallback, roots);
33
+ }
34
+ }
35
+ }
36
+ });
37
+ }
38
+ // Its own writes are to resolved columns, which no resolve reads.
39
+ resolved_ = store_.Version();
40
+ }
41
+
42
+ BitSet Scene::ResolveRoots(const ChangeSet& changes, AttributeId attribute) const {
43
+ BitSet roots;
44
+ roots.Resize(store_.Paths().Size());
45
+ const auto add = [&](BucketId bucket, std::uint32_t begin, std::uint32_t end) {
46
+ const Bucket& rows = store_.GetBucket(bucket);
47
+ for (std::uint32_t row = begin; row < std::min(end, rows.Rows()); ++row) {
48
+ roots.Set(store_.PrimPath(rows.prims[row]));
49
+ }
50
+ };
51
+ for (const BucketId bucket : changes.resets) {
52
+ add(bucket, 0, std::numeric_limits<std::uint32_t>::max());
53
+ }
54
+ for (const ChangeSet::Rows& rows : changes.rows) {
55
+ if (rows.change.kind == StructuralChange::Kind::Added) {
56
+ add(rows.bucket, rows.change.row, rows.change.row + rows.change.count);
57
+ }
58
+ }
59
+ for (const ChangeSet::Values& values : changes.values) {
60
+ if (values.attribute == attribute) {
61
+ for (const RowRange range : values.rows) {
62
+ add(values.bucket, range.begin, range.end);
63
+ }
64
+ }
65
+ }
66
+ return roots;
67
+ }
68
+
69
+ template <typename T> const T* Scene::Inheritable(PrimId prim, AttributeId attribute) const {
70
+ const BucketId bucket = store_.PrimBucket(prim);
71
+ const Column* column = store_.GetBucket(bucket).Find(attribute);
72
+ const std::uint32_t row = store_.PrimRow(prim);
73
+ if (column == nullptr || !column->authored.Test(row) ||
74
+ column->values->Type() != kColumnType<T>) {
75
+ return nullptr;
76
+ }
77
+ const T* own = &store_.Read<T>(bucket, attribute)[row];
78
+ if constexpr (std::same_as<T, Token>) {
79
+ return *own == inherited_ ? nullptr : own;
80
+ }
81
+ return own;
82
+ }
83
+
84
+ template <typename T> T Scene::Above(PathId path, AttributeId attribute, const T& fallback) const {
85
+ const PathTable& paths = store_.Paths();
86
+ for (PathId above = paths.Parent(path); above != kRootPath; above = paths.Parent(above)) {
87
+ const std::optional<PrimId> prim = store_.Find(above);
88
+ if (const T* own = prim ? Inheritable<T>(*prim, attribute) : nullptr) {
89
+ return *own;
90
+ }
91
+ }
92
+ return fallback;
93
+ }
94
+
95
+ template <typename T>
96
+ void Scene::ResolveSubtree(PathId root, AttributeId attribute, AttributeId resolved,
97
+ const T& fallback, BitSet& roots) {
98
+ std::vector<std::pair<PathId, T>> pending{{root, Above<T>(root, attribute, fallback)}};
99
+ while (!pending.empty()) {
100
+ const auto [path, above] = std::move(pending.back());
101
+ pending.pop_back();
102
+ const std::optional<PrimId> prim = store_.Find(path);
103
+ if (!prim) {
104
+ continue;
105
+ }
106
+ const bool isRoot = roots.Test(path);
107
+ roots.Set(path, false);
108
+ const T* own = Inheritable<T>(*prim, attribute);
109
+ const T value = own != nullptr ? *own : above;
110
+ // Prims without the column (typeless ones, materials) pass the value through.
111
+ const bool stored = store_.GetBucket(store_.PrimBucket(*prim)).Find(resolved) != nullptr;
112
+ // An unchanged prim's descendants are unchanged too, unless they are roots themselves.
113
+ if (store_.Derive(*prim, resolved, value) || isRoot || !stored) {
114
+ store_.Paths().ForEachChild(path,
115
+ [&](PathId child) { pending.emplace_back(child, value); });
116
+ }
117
+ }
118
+ }
119
+
120
+ } // namespace ernie
@@ -38,7 +38,8 @@ std::string Describe(const Scene& scene, PrimId prim) {
38
38
  } // namespace
39
39
 
40
40
  Scene::Scene()
41
- : invisible_(store_.Tokens().Intern(tokens::kInvisible)),
41
+ : inherited_(store_.Tokens().Intern(tokens::kInherited)),
42
+ invisible_(store_.Tokens().Intern(tokens::kInvisible)),
42
43
  defaultPurpose_(store_.Tokens().Intern(tokens::kDefault)) {
43
44
  FindOrAddBucket(nullptr, {});
44
45
  }
@@ -170,15 +171,20 @@ void Scene::Write(PrimId prim, std::string_view attribute, Tensor array) {
170
171
  }
171
172
 
172
173
  const Tensor* Scene::Read(PrimId prim, std::string_view attribute) const {
173
- const Column* column = AuthoredColumn(prim, attribute);
174
- if (column == nullptr || column->values->Type() != ColumnType::Tensor) {
175
- return nullptr;
176
- }
177
- return &store_.Read<Tensor>(store_.PrimBucket(prim), column->attribute)[store_.PrimRow(prim)];
174
+ return Authored<Tensor>(prim, attribute);
178
175
  }
179
176
 
180
177
  std::optional<Value> Scene::Get(PrimId prim, std::string_view attribute) const {
181
- const Column* column = AuthoredColumn(prim, attribute);
178
+ return CellValue(prim, AuthoredColumn(prim, attribute));
179
+ }
180
+
181
+ std::optional<Value> Scene::GetResolved(PrimId prim, std::string_view attribute) const {
182
+ const std::optional<Token> token = store_.Tokens().Find(ResolvedName(attribute));
183
+ return CellValue(prim,
184
+ token ? store_.GetBucket(store_.PrimBucket(prim)).Find(*token) : nullptr);
185
+ }
186
+
187
+ std::optional<Value> Scene::CellValue(PrimId prim, const Column* column) const {
182
188
  if (column == nullptr) {
183
189
  return std::nullopt;
184
190
  }
@@ -248,6 +254,11 @@ std::optional<Box> Scene::Extent(PrimId prim) const {
248
254
  return extent;
249
255
  }
250
256
 
257
+ std::vector<PrimId> Scene::Holders(const Path& target) const {
258
+ const std::optional<PathId> id = store_.Paths().Find(target);
259
+ return id ? holders_.Find(store_, *id) : std::vector<PrimId>{};
260
+ }
261
+
251
262
  Box Scene::WorldBounds(const Path& path) const {
252
263
  const PrimId prim = Require(path);
253
264
  const PathId id = store_.PrimPath(prim);
@@ -277,11 +288,17 @@ void Scene::AddTo(Box& bounds, PathId path, const glm::dmat4& parent, bool visib
277
288
  bounds.Extend(extent->Transformed(world));
278
289
  return;
279
290
  }
291
+ bool loaded = false;
280
292
  store_.Paths().ForEachChild(path, [&](PathId child) {
281
293
  if (store_.Find(child)) {
294
+ loaded = true;
282
295
  AddTo(bounds, child, world, visibleOnly);
283
296
  }
284
297
  });
298
+ // A model whose subtree isn't loaded is bounded by its hint.
299
+ if (!loaded) {
300
+ bounds.Extend(ExtentsHint(prim, !visibleOnly).Transformed(world));
301
+ }
285
302
  }
286
303
 
287
304
  PrimId Scene::Require(const Path& path) const {
@@ -323,6 +340,11 @@ BucketId Scene::FindOrAddBucket(const SchemaDef* schema, std::vector<Token> apis
323
340
  for (const ApiName& api : allApis) {
324
341
  add(*api.schema, api);
325
342
  }
343
+ if (schema != nullptr && schema->IsA(Imageable::Definition())) {
344
+ for (const AttributeDef* def : InheritedAttributes()) {
345
+ layout.push_back(MakeLayout(paths, *def, ResolvedName(def->name), def->fallback));
346
+ }
347
+ }
326
348
  const BucketId bucket = store_.AddBucket(key, layout);
327
349
  buckets_.resize(std::max<std::size_t>(buckets_.size(), bucket + 1));
328
350
  buckets_[bucket] = std::move(entry);
@@ -400,15 +422,24 @@ std::vector<std::string> Scene::AppliedApis(PrimId prim) const {
400
422
  }
401
423
 
402
424
  bool Scene::LeavesOutOfBounds(PrimId prim) const {
403
- const auto token = [&](std::string_view attribute) -> std::optional<Token> {
404
- const Column* column = AuthoredColumn(prim, attribute);
405
- return column ? std::optional(store_.Read<Token>(store_.PrimBucket(prim),
406
- column->attribute)[store_.PrimRow(prim)])
407
- : std::nullopt;
408
- };
425
+ const Token* visibility = Authored<Token>(prim, Imageable::kVisibility);
409
426
  // Purpose is inherited, so a subtree under another purpose is left out whole.
410
- const std::optional<Token> purpose = token(Imageable::kPurpose);
411
- return token(Imageable::kVisibility) == invisible_ || (purpose && *purpose != defaultPurpose_);
427
+ const Token* purpose = Authored<Token>(prim, Imageable::kPurpose);
428
+ return (visibility && *visibility == invisible_) || (purpose && *purpose != defaultPurpose_);
429
+ }
430
+
431
+ Box Scene::ExtentsHint(PrimId prim, bool allPurposes) const {
432
+ const auto* hint = Authored<std::vector<float>>(prim, GeomModelAPI::kExtentsHint);
433
+ if (hint == nullptr) {
434
+ return {};
435
+ }
436
+ // Six floats per purpose, the default purpose first.
437
+ const std::size_t floats = allPurposes ? hint->size() : std::min<std::size_t>(6, hint->size());
438
+ Box box;
439
+ for (std::size_t i = 0; i + 6 <= floats; i += 6) {
440
+ box.Extend(AuthoredExtent(std::span(*hint).subspan(i, 6)));
441
+ }
442
+ return box;
412
443
  }
413
444
 
414
445
  const Column* Scene::AuthoredColumn(PrimId prim, std::string_view attribute) const {
@@ -428,12 +459,18 @@ Dirty Scene::Classify(const ChangeSet::Values& change) const {
428
459
  return def->meta.dirty;
429
460
  }
430
461
  const std::string_view name = store_.Tokens().Text(change.attribute);
462
+ if (name.starts_with(tokens::kResolvedPrefix)) {
463
+ return FindInherited(name.substr(tokens::kResolvedPrefix.size()))->meta.dirty;
464
+ }
431
465
  return name.starts_with(tokens::kXformOpPrefix) ? Dirty::Transform
432
466
  : name.starts_with(tokens::kPrimvarsPrefix) ? Dirty::Primvars
433
467
  : Dirty::Params;
434
468
  }
435
469
 
436
470
  bool Scene::TakesUndeclared(PrimId prim, std::string_view attribute) const {
471
+ if (attribute.starts_with(tokens::kResolvedPrefix)) {
472
+ return false;
473
+ }
437
474
  const SchemaDef* schema = Schema(prim);
438
475
  return schema == nullptr || schema->IsOpen(attribute) ||
439
476
  std::ranges::any_of(AllApis(schema, Apis(prim)),
@@ -5,6 +5,7 @@
5
5
 
6
6
  #include "ernie/geometry/bounds.h"
7
7
  #include "ernie/scene/extent_cache.h"
8
+ #include "ernie/scene/holder_index.h"
8
9
  #include "ernie/scene/schema.h"
9
10
  #include "ernie/scene/storage.h"
10
11
  #include "ernie/scene/value.h"
@@ -68,6 +69,10 @@ class Scene {
68
69
  /// @return The authored value, or none.
69
70
  std::optional<Value> Get(PrimId prim, std::string_view attribute) const;
70
71
  std::optional<Value> Get(const Path& path, std::string_view attribute) const;
72
+ /// @return An inherited attribute's value as of the last `Update`: the prim's own or its
73
+ /// nearest authoring ancestor's (where "inherited" isn't authoring), else the fallback; none
74
+ /// for a prim that isn't Imageable.
75
+ std::optional<Value> GetResolved(PrimId prim, std::string_view attribute) const;
71
76
  /// @brief Authors an array attribute with a tensor on the host or a device, shared, not copied.
72
77
  /// @throws std::invalid_argument for a non-array attribute, or a tensor of the wrong type or
73
78
  /// shape.
@@ -84,12 +89,20 @@ class Scene {
84
89
  glm::dmat4 LocalTransform(PrimId prim) const;
85
90
  glm::dmat4 WorldTransform(PrimId prim) const;
86
91
  /// @return The prim's extent in its own space; none when it isn't computed from attributes.
87
- /// Cached since `UpdateExtents` when its bucket hasn't changed, computed otherwise.
92
+ /// Cached since `Update` when its bucket hasn't changed, computed otherwise.
88
93
  std::optional<Box> Extent(PrimId prim) const;
89
- /// @brief Recomputes the cached extents of the rows that changed since the last update.
90
- void UpdateExtents() {
94
+ /// @brief Brings derived data up to date with the edits since the last update, once per step
95
+ /// before renderers pull changes: resolves inherited attributes for the subtrees whose
96
+ /// authored values or prims changed, re-indexes changed relationships, then recomputes the
97
+ /// changed rows' cached extents.
98
+ void Update() {
99
+ Resolve();
100
+ holders_.Update(store_);
91
101
  extents_.Update(store_);
92
102
  }
103
+ /// @return The prims whose relationships target `target` as of the last `Update`, resolved
104
+ /// material bindings included: what an edit to `target` reaches.
105
+ std::vector<PrimId> Holders(const Path& target) const;
93
106
  /// @return The world box of the prim and its visible descendants of the default purpose.
94
107
  /// Prims with extents bound their own subtrees, as UsdGeomBBoxCache prunes at Boundables.
95
108
  Box WorldBounds(const Path& path) const;
@@ -126,6 +139,31 @@ class Scene {
126
139
  std::vector<ApiName> AllApis(const SchemaDef* schema, std::span<const Token> applied) const;
127
140
  /// @return The attribute's column when the prim authors it, or null.
128
141
  const Column* AuthoredColumn(PrimId prim, std::string_view attribute) const;
142
+ /// @return The attribute's value when the prim authors it as a `T`, or null.
143
+ template <typename T> const T* Authored(PrimId prim, std::string_view attribute) const {
144
+ const Column* column = AuthoredColumn(prim, attribute);
145
+ if (column == nullptr || column->values->Type() != kColumnType<T>) {
146
+ return nullptr;
147
+ }
148
+ return &store_.Read<T>(store_.PrimBucket(prim), column->attribute)[store_.PrimRow(prim)];
149
+ }
150
+ std::optional<Value> CellValue(PrimId prim, const Column* column) const;
151
+
152
+ /// Resolves every inherited attribute for the subtrees changed since the last resolve.
153
+ void Resolve();
154
+ /// @return The paths of the prims whose subtrees resolve `attribute` again: those added, reset
155
+ /// or with it changed.
156
+ BitSet ResolveRoots(const ChangeSet& changes, AttributeId attribute) const;
157
+ /// @return What `attribute` resolves to from the prim's own value: null when it doesn't
158
+ /// author it, or authors "inherited".
159
+ template <typename T> const T* Inheritable(PrimId prim, AttributeId attribute) const;
160
+ /// @return The value `path` inherits from its ancestors.
161
+ template <typename T> T Above(PathId path, AttributeId attribute, const T& fallback) const;
162
+ /// Resolves `attribute` over the subtree at `root`, descending past a prim only while its
163
+ /// resolved value changes or it is one of `roots`, which it clears as it reaches them.
164
+ template <typename T>
165
+ void ResolveSubtree(PathId root, AttributeId attribute, AttributeId resolved, const T& fallback,
166
+ BitSet& roots);
129
167
  const AttributeDef* Declared(BucketId bucket, AttributeId attribute) const;
130
168
  /// @return Whether the prim's type or an applied API schema leaves the attribute's namespace
131
169
  /// open; any attribute for a prim without a type.
@@ -133,15 +171,21 @@ class Scene {
133
171
  ColumnType TypeForUndeclared(PrimId prim, std::string_view attribute, const Value& value) const;
134
172
  /// @return Whether the prim and its subtree are invisible or of a purpose bounds leave out.
135
173
  bool LeavesOutOfBounds(PrimId prim) const;
174
+ /// @return GeomModelAPI's extentsHint: the default purpose's box, or with `allPurposes`, all.
175
+ Box ExtentsHint(PrimId prim, bool allPurposes) const;
136
176
  /// Adds a subtree's extents under `parent`'s transform; with `visibleOnly`, only its visible
137
177
  /// default-purpose prims'.
138
178
  void AddTo(Box& bounds, PathId path, const glm::dmat4& parent, bool visibleOnly) const;
139
179
 
140
180
  PrimStore store_;
181
+ /// The store version inherited attributes were last resolved at.
182
+ std::uint64_t resolved_ = 0;
183
+ Token inherited_ = 0;
141
184
  Token invisible_ = 0;
142
185
  Token defaultPurpose_ = 0;
143
186
  std::vector<BucketSchema> buckets_;
144
187
  ExtentCache extents_;
188
+ HolderIndex holders_;
145
189
  };
146
190
 
147
191
  } // namespace ernie
@@ -175,6 +175,28 @@ const SchemaDef* FindSchema(std::string_view name) {
175
175
  return found != schemas.end() ? *found : nullptr;
176
176
  }
177
177
 
178
+ std::span<const AttributeDef* const> InheritedAttributes() {
179
+ static const std::vector<const AttributeDef*> kInherited = [] {
180
+ std::vector<const AttributeDef*> inherited;
181
+ for (const SchemaDef* schema : Schemas()) {
182
+ for (const AttributeDef& def : schema->attributes) {
183
+ if (def.meta.inherited) {
184
+ inherited.push_back(&def);
185
+ }
186
+ }
187
+ }
188
+ return inherited;
189
+ }();
190
+ return kInherited;
191
+ }
192
+
193
+ const AttributeDef* FindInherited(std::string_view name) {
194
+ const std::span<const AttributeDef* const> inherited = InheritedAttributes();
195
+ const auto found =
196
+ std::ranges::find_if(inherited, [&](const AttributeDef* def) { return def->name == name; });
197
+ return found != inherited.end() ? *found : nullptr;
198
+ }
199
+
178
200
  ApiName ApiName::Parse(std::string_view api) {
179
201
  const std::size_t colon = api.find(':');
180
202
  const std::string_view name = api.substr(0, colon);
@@ -5,12 +5,14 @@
5
5
 
6
6
  #include "ernie/geometry/bounds.h"
7
7
  #include "ernie/scene/storage.h"
8
+ #include "ernie/scene/tokens.h"
8
9
  #include "ernie/scene/value.h"
9
10
 
10
11
  #include <array>
11
12
  #include <cstdint>
12
13
  #include <optional>
13
14
  #include <span>
15
+ #include <string>
14
16
  #include <string_view>
15
17
  #include <vector>
16
18
 
@@ -87,7 +89,8 @@ struct AttributeMeta {
87
89
  /// The ranks a tensor may have, as a dense grid's 3; none for flat or vector arrays.
88
90
  std::vector<std::int64_t> ranks{};
89
91
  Dirty dirty = Dirty::Params;
90
- /// Resolved from the nearest authoring ancestor.
92
+ /// Resolved from the nearest ancestor authoring it (other than as "inherited") into its
93
+ /// `ResolvedName` column.
91
94
  bool inherited = false;
92
95
  };
93
96
 
@@ -234,6 +237,15 @@ struct SchemaDef {
234
237
  std::span<const SchemaDef* const> Schemas();
235
238
  /// @return The schema named `name`, or null.
236
239
  const SchemaDef* FindSchema(std::string_view name);
240
+ /// @return Every attribute declared inherited, once each.
241
+ std::span<const AttributeDef* const> InheritedAttributes();
242
+ /// @return The inherited attribute named `name`, or null.
243
+ const AttributeDef* FindInherited(std::string_view name);
244
+ /// @return The column holding an inherited attribute's resolved values:
245
+ /// `ernie:resolved:visibility`.
246
+ inline std::string ResolvedName(std::string_view attribute) {
247
+ return std::string(tokens::kResolvedPrefix) + std::string(attribute);
248
+ }
237
249
 
238
250
  /// What a multiple-apply schema's attribute names hold in place of the instance's name.
239
251
  inline constexpr std::string_view kInstanceName = "__INSTANCE_NAME__";
@@ -60,6 +60,8 @@ ERNIE_DEFINE_SCHEMA(Xform, Concrete, kDescendantsExtent, ERNIE_NO_ATTRIBUTES,
60
60
  .openNamespaces = {"*"})
61
61
  ERNIE_DEFINE_SCHEMA(Scope, Concrete, kDescendantsExtent, ERNIE_NO_ATTRIBUTES,
62
62
  .openNamespaces = {"*"})
63
+ ERNIE_DEFINE_SCHEMA(GeomModelAPI, SingleApply, kInheritExtent, ERNIE_MODEL_API_ATTRIBUTES)
64
+ ERNIE_DEFINE_SCHEMA(GeomSubset, Concrete, kNoExtent, ERNIE_SUBSET_ATTRIBUTES)
63
65
  ERNIE_DEFINE_SCHEMA(Cube, Concrete, ComputedExtent(CentredExtent<CubeHalves>),
64
66
  ERNIE_CUBE_ATTRIBUTES)
65
67
  ERNIE_DEFINE_SCHEMA(Sphere, Concrete, ComputedExtent(CentredExtent<SphereHalves>),