├── .gitignore ├── CMakeLists.txt ├── LICENSE.txt ├── README.md ├── UsdAnari.cpp ├── UsdAnari.h ├── UsdBaseObject.cpp ├── UsdBaseObject.h ├── UsdBridge ├── CMakeLists.txt ├── Common │ ├── CMakeLists.txt │ ├── UsdBridgeData.h │ ├── UsdBridgeMacros.h │ ├── UsdBridgeNumerics.h │ ├── UsdBridgeUtils.cpp │ ├── UsdBridgeUtils.h │ └── UsdBridgeUtils_Internal.h ├── Connection │ ├── CMakeLists.txt │ ├── UsdBridgeConnection.cpp │ └── UsdBridgeConnection.h ├── Mdl │ ├── CMakeLists.txt │ └── UsdBridgeMdlStrings.h ├── UsdBridge.cpp ├── UsdBridge.h ├── UsdBridgeCaches.cpp ├── UsdBridgeCaches.h ├── UsdBridgeDiagnosticMgrDelegate.cpp ├── UsdBridgeDiagnosticMgrDelegate.h ├── UsdBridgeRt.cpp ├── UsdBridgeRt.h ├── UsdBridgeTimeEvaluator.cpp ├── UsdBridgeTimeEvaluator.h ├── UsdBridgeUsdWriter.cpp ├── UsdBridgeUsdWriter.h ├── UsdBridgeUsdWriter_Arrays.h ├── UsdBridgeUsdWriter_Common.h ├── UsdBridgeUsdWriter_Geometry.cpp ├── UsdBridgeUsdWriter_Material.cpp ├── UsdBridgeUsdWriter_Volume.cpp ├── Volume │ ├── CMakeLists.txt │ ├── UsdBridgeVolumeWriter.cpp │ ├── UsdBridgeVolumeWriter.h │ └── cmake │ │ ├── FindOpenVDB.cmake │ │ └── OpenVDBUtils.cmake ├── usd.h └── usdhelpers.cmake ├── UsdBridgedBaseObject.h ├── UsdCamera.cpp ├── UsdCamera.h ├── UsdCommonMacros.h ├── UsdDataArray.cpp ├── UsdDataArray.h ├── UsdDevice.cpp ├── UsdDevice.h ├── UsdDeviceQueries.cpp ├── UsdDeviceQueries.h ├── UsdDeviceUtils.h ├── UsdFrame.cpp ├── UsdFrame.h ├── UsdGeometry.cpp ├── UsdGeometry.h ├── UsdGroup.cpp ├── UsdGroup.h ├── UsdInstance.cpp ├── UsdInstance.h ├── UsdLibrary.cpp ├── UsdLight.cpp ├── UsdLight.h ├── UsdMaterial.cpp ├── UsdMaterial.h ├── UsdMultiTypeParameter.h ├── UsdParameterizedObject.h ├── UsdRenderer.cpp ├── UsdRenderer.h ├── UsdSampler.cpp ├── UsdSampler.h ├── UsdSharedObjects.h ├── UsdSpatialField.cpp ├── UsdSpatialField.h ├── UsdSurface.cpp ├── UsdSurface.h ├── UsdVolume.cpp ├── UsdVolume.h ├── UsdWorld.cpp ├── UsdWorld.h ├── examples ├── CMakeLists.txt ├── anariTutorial_usd.c ├── anariTutorial_usd.cpp ├── anariTutorial_usd_common.h ├── anariTutorial_usd_recreate.c ├── anariTutorial_usd_time.c ├── anariTutorial_usd_volume.cpp └── anari_tutorial_glyphs_usd.py ├── khr_geometry_glyph.json ├── superbuild ├── CMakeLists.txt ├── README.md └── macros.cmake ├── thirdparty ├── CMakeLists.txt └── stb_image │ ├── CMakeLists.txt │ ├── stb_image.c │ ├── stb_image.h │ ├── stb_image_resize.h │ ├── stb_image_write.c │ └── stb_image_write.h ├── usd_device.json └── usd_device_features.json /.gitignore: -------------------------------------------------------------------------------- 1 | _*/ 2 | __pycache__/* 3 | .vscode 4 | .anari_deps 5 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ## Copyright 2020 The Khronos Group 2 | ## SPDX-License-Identifier: Apache-2.0 3 | 4 | cmake_minimum_required(VERSION 3.17) 5 | 6 | set(CMAKE_CXX_STANDARD 17) 7 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 8 | set(CMAKE_CXX_EXTENSIONS OFF) 9 | 10 | set(CMAKE_BUILD_TYPE_INIT "Release") 11 | 12 | set(CMAKE_INSTALL_RPATH "$ORIGIN") 13 | 14 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) 15 | 16 | ## Top-level project ## 17 | set(USD_DEVICE_VERSION_MAJOR 0) 18 | set(USD_DEVICE_VERSION_MINOR 2) 19 | set(USD_DEVICE_VERSION_PATCH 0) 20 | set(USD_DEVICE_VERSION ${USD_DEVICE_VERSION_MAJOR}.${USD_DEVICE_VERSION_MINOR}.${USD_DEVICE_VERSION_PATCH}) 21 | if(NOT USD_DEVICE_BUILD_VERSION_EXPLICIT) 22 | if(EXISTS ${CMAKE_SOURCE_DIR}/.git) 23 | find_package(Git REQUIRED) 24 | execute_process( 25 | COMMAND ${GIT_EXECUTABLE} rev-list --count HEAD 26 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 27 | OUTPUT_VARIABLE "USD_DEVICE_BUILD_VERSION" 28 | ERROR_QUIET 29 | OUTPUT_STRIP_TRAILING_WHITESPACE 30 | ) 31 | else() 32 | set(USD_DEVICE_BUILD_VERSION -1) 33 | endif() 34 | else() 35 | set(USD_DEVICE_BUILD_VERSION ${USD_DEVICE_BUILD_VERSION_EXPLICIT}) 36 | endif() 37 | message(STATUS "DEVICE VERSION: ${USD_DEVICE_VERSION} build ${USD_DEVICE_BUILD_VERSION}") 38 | 39 | project(AnariUsdDevice VERSION ${USD_DEVICE_VERSION} LANGUAGES C CXX) 40 | 41 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) 42 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) 43 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) 44 | 45 | include(GNUInstallDirs) 46 | 47 | add_subdirectory(thirdparty) 48 | 49 | ## Dependencies ## 50 | 51 | if (NOT EXISTS ${ANARI_ROOT_DIR}) 52 | find_path(ANARI_ROOT_DIR NAMES include/anari/anari.h DOC "Path to ANARI SDK") 53 | endif() 54 | 55 | set(ANARI_CONFIG_SUBDIR "release") 56 | if(CMAKE_BUILD_TYPE MATCHES "Debug") 57 | set(ANARI_CONFIG_SUBDIR "debug") 58 | endif() 59 | if (EXISTS "${ANARI_ROOT_DIR}/${ANARI_CONFIG_SUBDIR}") 60 | set(ANARI_ROOT_DIR "${ANARI_ROOT_DIR}/${ANARI_CONFIG_SUBDIR}") 61 | endif() 62 | 63 | if (NOT EXISTS ${ANARI_ROOT_DIR}) 64 | message(FATAL_ERROR "No valid ANARI_ROOT_DIR set, or found using CMAKE_PREFIX_PATH: ${ANARI_ROOT_DIR}") 65 | else() 66 | message(STATUS "Using ANARI_ROOT_DIR: ${ANARI_ROOT_DIR}") 67 | endif() 68 | 69 | # Search in config mode 70 | find_package(anari 0.10 REQUIRED 71 | PATHS ${ANARI_ROOT_DIR} 72 | ) 73 | 74 | ## Code generation 75 | 76 | if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.12") 77 | message(STATUS "Adding codegen target") 78 | 79 | list(PREPEND CMAKE_MODULE_PATH ${Python3_ROOT_DIR}) 80 | find_package(Python3 REQUIRED COMPONENTS Interpreter Development) 81 | list(POP_FRONT CMAKE_MODULE_PATH) 82 | 83 | add_custom_target(generate_usd_queries 84 | COMMAND ${Python3_EXECUTABLE} ${ANARI_CODE_GEN_ROOT}/generate_queries.py 85 | --json ${ANARI_CODE_GEN_ROOT} 86 | --json ${CMAKE_CURRENT_SOURCE_DIR} 87 | --prefix UsdDevice 88 | --device ${CMAKE_CURRENT_SOURCE_DIR}/usd_device.json 89 | --namespace anari::usd 90 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 91 | DEPENDS usd_device.json usd_device_features.json khr_geometry_glyph.json 92 | ) 93 | 94 | add_custom_target(generate_all) 95 | add_dependencies(generate_all generate_usd_queries) 96 | endif() 97 | 98 | ## Core UsdBridge ## 99 | 100 | # Compile defs required by all subdirs 101 | option(USD_DEVICE_TIME_BASED_OUTPUT "Allow use of timesamples for timevarying properties, but no retiming (so all timesteps are global)" ON) 102 | if(USD_DEVICE_TIME_BASED_OUTPUT) 103 | list(APPEND USD_DEVICE_TIME_DEFS -DTIME_BASED_CACHING) 104 | option(USD_DEVICE_VALUE_CLIP_OUTPUT "Retiming of timesteps through value clips for selected objects, resulting in separate USD files for those objects" ON) 105 | if(USD_DEVICE_VALUE_CLIP_OUTPUT) 106 | list(APPEND USD_DEVICE_TIME_DEFS -DVALUE_CLIP_RETIMING) 107 | option(USD_DEVICE_CLIP_STAGE_OUTPUT "Separate clip stages for each timestep for selected objects, resulting in a single USD file per timestep" ON) 108 | if(USD_DEVICE_CLIP_STAGE_OUTPUT) 109 | list(APPEND USD_DEVICE_TIME_DEFS -DTIME_CLIP_STAGES) 110 | endif() 111 | endif() 112 | endif() 113 | 114 | add_subdirectory(UsdBridge) 115 | 116 | ## Build USD Device ## 117 | 118 | set(USDModule_SOURCES 119 | UsdAnari.cpp 120 | UsdBaseObject.cpp 121 | UsdDevice.cpp 122 | UsdDataArray.cpp 123 | UsdGeometry.cpp 124 | UsdSurface.cpp 125 | UsdGroup.cpp 126 | UsdSpatialField.cpp 127 | UsdVolume.cpp 128 | UsdInstance.cpp 129 | UsdLibrary.cpp 130 | UsdSampler.cpp 131 | UsdMaterial.cpp 132 | UsdWorld.cpp 133 | UsdRenderer.cpp 134 | UsdFrame.cpp 135 | UsdLight.cpp 136 | UsdCamera.cpp 137 | UsdDeviceQueries.cpp) 138 | 139 | set(USDModule_HEADERS 140 | UsdCommonMacros.h 141 | UsdAnari.h 142 | UsdDeviceUtils.h 143 | UsdMultiTypeParameter.h 144 | UsdParameterizedObject.h 145 | UsdDevice.h 146 | UsdBaseObject.h 147 | UsdSharedObjects.h 148 | UsdBridgedBaseObject.h 149 | UsdDataArray.h 150 | UsdGeometry.h 151 | UsdSurface.h 152 | UsdGroup.h 153 | UsdSpatialField.h 154 | UsdVolume.h 155 | UsdInstance.h 156 | UsdSampler.h 157 | UsdMaterial.h 158 | UsdWorld.h 159 | UsdRenderer.h 160 | UsdFrame.h 161 | UsdLight.h 162 | UsdCamera.h) 163 | 164 | add_library(anari_library_usd SHARED ${USDModule_SOURCES} ${USDModule_HEADERS}) 165 | 166 | target_compile_definitions(anari_library_usd 167 | PRIVATE 168 | -DDEVICE_VERSION_BUILD=${USD_DEVICE_BUILD_VERSION} 169 | -DDEVICE_VERSION_MAJOR=${USD_DEVICE_VERSION_MAJOR} 170 | -DDEVICE_VERSION_MINOR=${USD_DEVICE_VERSION_MINOR} 171 | -DDEVICE_VERSION_PATCH=${USD_DEVICE_VERSION_PATCH} 172 | -DDEVICE_VERSION_NAME="${USD_DEVICE_VERSION}" 173 | ${USD_DEVICE_TIME_DEFS}) 174 | 175 | option(CHECK_OBJECT_REFERENCES "Perform a memory check on the reference count of all objects allocated by a USD device, avoiding memleaks and double deletion." OFF) 176 | if(CHECK_OBJECT_REFERENCES) 177 | target_compile_definitions(anari_library_usd 178 | PRIVATE -DCHECK_MEMLEAKS) 179 | endif() 180 | 181 | target_link_libraries(anari_library_usd 182 | PUBLIC anari::anari 183 | PRIVATE anari::helium UsdBridge 184 | ) 185 | 186 | option(USD_DEVICE_BUILD_EXAMPLES "Build USD device examples" OFF) 187 | if(USD_DEVICE_BUILD_EXAMPLES) 188 | add_subdirectory(examples) 189 | endif() 190 | 191 | install(TARGETS anari_library_usd 192 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 193 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 194 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 195 | ) 196 | 197 | ## Install optional pdbs 198 | ## install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) 199 | 200 | option(INSTALL_ANARI_DEPS "Enable install of ANARI SDK dependencies along with USD device" OFF) # Not truly a dependency of the USD Device, generally one wants to build against ANARI source, not just libs 201 | cmake_dependent_option(INSTALL_ANARI_COMPILE_DEPS "Enable install of ANARI SDK dependencies required for compilation of ANARI client code" OFF "INSTALL_ANARI_DEPS" OFF) 202 | if(${INSTALL_ANARI_DEPS}) 203 | 204 | set(PLATFORM_INSTALL_LIBDIR "$<$>:${CMAKE_INSTALL_LIBDIR}>$<$:${CMAKE_INSTALL_BINDIR}>/") 205 | 206 | if(${INSTALL_ANARI_COMPILE_DEPS}) 207 | ## Compile time deps 208 | if(WIN32) 209 | install( 210 | DIRECTORY "${ANARI_ROOT_DIR}/bin/" 211 | DESTINATION ${CMAKE_INSTALL_BINDIR}) 212 | endif() 213 | install( 214 | DIRECTORY "${ANARI_ROOT_DIR}/include/" 215 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 216 | install( 217 | DIRECTORY "${ANARI_ROOT_DIR}/lib/" 218 | DESTINATION ${CMAKE_INSTALL_LIBDIR}) 219 | else() 220 | ## Runtime deps 221 | install( 222 | FILES $ 223 | DESTINATION ${PLATFORM_INSTALL_LIBDIR}) 224 | endif() 225 | endif() 226 | 227 | -------------------------------------------------------------------------------- /UsdAnari.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridgeData.h" 7 | #include "UsdCommonMacros.h" 8 | #include "anari/frontend/anari_enums.h" 9 | #include "anari/anari_cpp/Traits.h" 10 | #include "anari/frontend/type_utility.h" 11 | 12 | #include 13 | #include 14 | 15 | class UsdDevice; 16 | class UsdDataArray; 17 | class UsdFrame; 18 | class UsdGeometry; 19 | class UsdGroup; 20 | class UsdInstance; 21 | class UsdLight; 22 | class UsdMaterial; 23 | class UsdRenderer; 24 | class UsdSurface; 25 | class UsdSampler; 26 | class UsdSpatialField; 27 | class UsdVolume; 28 | class UsdWorld; 29 | class UsdCamera; 30 | class UsdSharedString; 31 | class UsdBaseObject; 32 | struct UsdDataLayout; 33 | 34 | namespace anari 35 | { 36 | static_assert(sizeof(bool) >= sizeof(ANARITypeProperties::base_type)); 37 | ANARI_TYPEFOR_SPECIALIZATION(UsdUint2, ANARI_UINT32_VEC2); 38 | ANARI_TYPEFOR_SPECIALIZATION(UsdFloat2, ANARI_FLOAT32_VEC2); 39 | ANARI_TYPEFOR_SPECIALIZATION(UsdFloat3, ANARI_FLOAT32_VEC3); 40 | ANARI_TYPEFOR_SPECIALIZATION(UsdFloat4, ANARI_FLOAT32_VEC4); 41 | ANARI_TYPEFOR_SPECIALIZATION(UsdQuaternion, ANARI_FLOAT32_QUAT_IJKW); 42 | ANARI_TYPEFOR_SPECIALIZATION(UsdFloatMat4, ANARI_FLOAT32_MAT4); 43 | ANARI_TYPEFOR_SPECIALIZATION(UsdFloatBox1, ANARI_FLOAT32_BOX1); 44 | ANARI_TYPEFOR_SPECIALIZATION(UsdFloatBox2, ANARI_FLOAT32_BOX2); 45 | ANARI_TYPEFOR_SPECIALIZATION(UsdSharedString*, ANARI_STRING); 46 | ANARI_TYPEFOR_SPECIALIZATION(UsdDataArray*, ANARI_ARRAY); 47 | ANARI_TYPEFOR_SPECIALIZATION(UsdFrame*, ANARI_FRAME); 48 | ANARI_TYPEFOR_SPECIALIZATION(UsdGeometry*, ANARI_GEOMETRY); 49 | ANARI_TYPEFOR_SPECIALIZATION(UsdGroup*, ANARI_GROUP); 50 | ANARI_TYPEFOR_SPECIALIZATION(UsdInstance*, ANARI_INSTANCE); 51 | ANARI_TYPEFOR_SPECIALIZATION(UsdLight*, ANARI_LIGHT); 52 | ANARI_TYPEFOR_SPECIALIZATION(UsdMaterial*, ANARI_MATERIAL); 53 | ANARI_TYPEFOR_SPECIALIZATION(UsdRenderer*, ANARI_RENDERER); 54 | ANARI_TYPEFOR_SPECIALIZATION(UsdSampler*, ANARI_SAMPLER); 55 | ANARI_TYPEFOR_SPECIALIZATION(UsdSpatialField*, ANARI_SPATIAL_FIELD); 56 | ANARI_TYPEFOR_SPECIALIZATION(UsdSurface*, ANARI_SURFACE); 57 | ANARI_TYPEFOR_SPECIALIZATION(UsdVolume*, ANARI_VOLUME); 58 | ANARI_TYPEFOR_SPECIALIZATION(UsdWorld*, ANARI_WORLD); 59 | } 60 | 61 | // Helper templates which allow for bool usage as param type 62 | // Replaces ANARI_TYPEFOR_SPECIALIZATION(bool, ANARI_BOOL) 63 | template 64 | struct AssertParamDataType 65 | { 66 | static constexpr bool value = AnariType == anari::ANARITypeFor::value; 67 | }; 68 | 69 | template<> 70 | struct AssertParamDataType 71 | { 72 | static constexpr bool value = true; 73 | }; 74 | 75 | // Shared convenience functions 76 | namespace 77 | { 78 | inline bool strEquals(const char* arg0, const char* arg1) 79 | { 80 | return strcmp(arg0, arg1) == 0; 81 | } 82 | 83 | template 84 | inline void writeToVoidP(void *_p, T v) 85 | { 86 | T *p = (T *)_p; 87 | *p = v; 88 | } 89 | 90 | // Helper templates which allow for bool usage as param type 91 | template 92 | inline bool AnariTypeMatchesCType(int anariType) 93 | { 94 | return anariType == anari::ANARITypeFor::value; 95 | } 96 | 97 | template<> 98 | inline bool AnariTypeMatchesCType(int anariType) 99 | { 100 | return anariType == ANARI_BOOL; 101 | } 102 | } 103 | 104 | // Standard log info 105 | struct UsdLogInfo 106 | { 107 | UsdLogInfo(UsdDevice* dev, void* src, ANARIDataType srcType, const char* srcName) 108 | : device(dev) 109 | , source(src) 110 | , sourceType(srcType) 111 | , sourceName(srcName) 112 | {} 113 | 114 | UsdDevice* device = nullptr; 115 | void* source = nullptr; 116 | ANARIDataType sourceType = ANARI_VOID_POINTER; 117 | const char* sourceName = nullptr; 118 | }; 119 | 120 | void reportStatusThroughDevice(const UsdLogInfo& logInfo, ANARIStatusSeverity severity, ANARIStatusCode statusCode, 121 | const char *format, const char* firstArg, const char* secondArg); // In case #include is undesired 122 | 123 | #ifdef CHECK_MEMLEAKS 124 | void logAllocationThroughDevice(UsdDevice* device, const void* ptr, ANARIDataType ptrType); 125 | void logDeallocationThroughDevice(UsdDevice* device, const void* ptr, ANARIDataType ptrType); 126 | #endif 127 | 128 | // Anari <=> USD conversions 129 | UsdBridgeType AnariToUsdBridgeType(ANARIDataType anariType); 130 | UsdBridgeType AnariToUsdBridgeType_Flattened(ANARIDataType anariType); 131 | const char* AnariTypeToString(ANARIDataType anariType); 132 | const char* AnariAttributeToUsdName(const char* param, bool perInstance, const UsdLogInfo& logInfo); 133 | std::pair GetGeomDependentAttributeName(const char* anariAttrib, bool perInstance, const UsdSharedString*const* attribNames, size_t numAttribNames, 134 | const UsdLogInfo& logInfo); 135 | UsdBridgeMaterialData::AlphaModes AnariToUsdAlphaMode(const char* alphaMode); 136 | ANARIStatusSeverity UsdBridgeLogLevelToAnariSeverity(UsdBridgeLogLevel level); 137 | 138 | bool Assert64bitStringLengthProperty(uint64_t size, const UsdLogInfo& logInfo, const char* propName); 139 | bool AssertOneDimensional(const UsdDataLayout& layout, const UsdLogInfo& logInfo, const char* arrayName); 140 | bool AssertNoStride(const UsdDataLayout& layout, const UsdLogInfo& logInfo, const char* arrayName); 141 | bool AssertArrayType(UsdDataArray* dataArray, ANARIDataType dataType, const UsdLogInfo& logInfo, const char* errorMessage); 142 | 143 | // Template definitions 144 | template 145 | class AnariToUsdObject {}; 146 | 147 | template 148 | class AnariToUsdBridgedObject {}; 149 | 150 | template 151 | class AnariToUsdBaseObject {}; 152 | 153 | #define USDBRIDGE_DEFINE_OBJECT_MAPPING(AnariType, UsdType) \ 154 | template<>\ 155 | class AnariToUsdObject\ 156 | {\ 157 | public:\ 158 | using Type = UsdType;\ 159 | }; 160 | 161 | #define USDBRIDGE_DEFINE_BASE_OBJECT_MAPPING(AnariType, UsdType) \ 162 | template<>\ 163 | class AnariToUsdBaseObject<(int)AnariType>\ 164 | {\ 165 | public:\ 166 | using Type = UsdType;\ 167 | }; 168 | 169 | #define USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(AnariType, UsdType)\ 170 | template<>\ 171 | class AnariToUsdBridgedObject<(int)AnariType>\ 172 | {\ 173 | public:\ 174 | using Type = UsdType;\ 175 | };\ 176 | template<>\ 177 | class AnariToUsdBaseObject<(int)AnariType>\ 178 | {\ 179 | public:\ 180 | using Type = UsdType;\ 181 | }; 182 | 183 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIObject, UsdBaseObject) 184 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIDevice, UsdDevice) 185 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIArray, UsdDataArray) 186 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIArray1D, UsdDataArray) 187 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIArray2D, UsdDataArray) 188 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIArray3D, UsdDataArray) 189 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIFrame, UsdFrame) 190 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIGeometry, UsdGeometry) 191 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIGroup, UsdGroup) 192 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIInstance, UsdInstance) 193 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARILight, UsdLight) 194 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIMaterial, UsdMaterial) 195 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARISampler, UsdSampler) 196 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARISurface, UsdSurface) 197 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIRenderer, UsdRenderer) 198 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARISpatialField, UsdSpatialField) 199 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIVolume, UsdVolume) 200 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARIWorld, UsdWorld) 201 | USDBRIDGE_DEFINE_OBJECT_MAPPING(ANARICamera, UsdCamera) 202 | 203 | USDBRIDGE_DEFINE_BASE_OBJECT_MAPPING(ANARI_DEVICE, UsdDevice) 204 | USDBRIDGE_DEFINE_BASE_OBJECT_MAPPING(ANARI_ARRAY, UsdDataArray) 205 | USDBRIDGE_DEFINE_BASE_OBJECT_MAPPING(ANARI_ARRAY1D, UsdDataArray) 206 | USDBRIDGE_DEFINE_BASE_OBJECT_MAPPING(ANARI_ARRAY2D, UsdDataArray) 207 | USDBRIDGE_DEFINE_BASE_OBJECT_MAPPING(ANARI_ARRAY3D, UsdDataArray) 208 | USDBRIDGE_DEFINE_BASE_OBJECT_MAPPING(ANARI_FRAME, UsdFrame) 209 | USDBRIDGE_DEFINE_BASE_OBJECT_MAPPING(ANARI_RENDERER, UsdRenderer) 210 | 211 | USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(ANARI_GEOMETRY, UsdGeometry) 212 | USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(ANARI_GROUP, UsdGroup) 213 | USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(ANARI_INSTANCE, UsdInstance) 214 | USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(ANARI_LIGHT, UsdLight) 215 | USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(ANARI_MATERIAL, UsdMaterial) 216 | USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(ANARI_SURFACE, UsdSurface) 217 | USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(ANARI_SAMPLER, UsdSampler) 218 | USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(ANARI_SPATIAL_FIELD, UsdSpatialField) 219 | USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(ANARI_VOLUME, UsdVolume) 220 | USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(ANARI_WORLD, UsdWorld) 221 | USDBRIDGE_DEFINE_BRIDGED_OBJECT_MAPPING(ANARI_CAMERA, UsdCamera) 222 | 223 | template 224 | typename AnariToUsdObject::Type* AnariToUsdObjectPtr(AnariType object) { return (typename AnariToUsdObject::Type*) object; } 225 | -------------------------------------------------------------------------------- /UsdBaseObject.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdBaseObject.h" 5 | #include "UsdDevice.h" 6 | 7 | #include 8 | 9 | UsdBaseObject::UsdBaseObject(ANARIDataType t, UsdDevice* device) 10 | : type(t) 11 | { 12 | // The object will not be committed (as in, user-written write params will not be set to read params), 13 | // but handles will be initialized and the object with its default data/refs will be written out to USD 14 | // (but only if the prim wasn't yet written to USD before, see 'isNew' in doCommit implementations). 15 | if(device) 16 | device->addToCommitList(this, true); 17 | } 18 | 19 | void UsdBaseObject::commit(UsdDevice* device) 20 | { 21 | bool deferDataCommit = !device->isInitialized() || !device->getReadParams().writeAtCommit || deferCommit(device); 22 | if(!deferDataCommit) 23 | { 24 | bool commitRefs = doCommitData(device); 25 | if(commitRefs) 26 | device->addToCommitList(this, false); // Commit refs, but no more data later on 27 | } 28 | else 29 | device->addToCommitList(this, true); // Commit data and refs later on 30 | } 31 | 32 | void UsdBaseObject::addObserver(UsdBaseObject* observer) 33 | { 34 | // duplicate entries allowed in case the same object is observed from multiple references on the same observer 35 | // (implicit ref counter of observed object) 36 | observers.push_back(observer); 37 | } 38 | 39 | void UsdBaseObject::removeObserver(UsdBaseObject* observer) 40 | { 41 | auto it = std::find(observers.begin(), observers.end(), observer); 42 | assert(it != observers.end()); 43 | 44 | *it = observers.back(); 45 | observers.pop_back(); 46 | } 47 | 48 | void UsdBaseObject::notify(UsdBaseObject* caller, UsdDevice* device) 49 | { 50 | auto it = observers.begin(); 51 | while(it != observers.end()) 52 | { 53 | auto observer = *it; 54 | 55 | #ifdef CHECK_MEMLEAKS 56 | assert(device->isObjAllocated(observer)); 57 | #endif 58 | 59 | // Don't call observe twice 60 | if(std::find(observers.begin(), it, observer) == it) 61 | observer->observe(caller, device); 62 | 63 | ++it; 64 | } 65 | } 66 | 67 | void UsdBridgeAddToCommitList(UsdDevice* device, UsdBaseObject* object, bool commitData) 68 | { 69 | device->addToCommitList(object, commitData); 70 | } 71 | -------------------------------------------------------------------------------- /UsdBaseObject.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "helium/utility/IntrusivePtr.h" 7 | #include "UsdCommonMacros.h" 8 | #include "UsdParameterizedObject.h" 9 | 10 | class UsdDevice; 11 | 12 | // Base parameterized class without being derived as such - nontemplated to allow for polymorphic use 13 | class UsdBaseObject : public helium::RefCounted 14 | { 15 | public: 16 | // If device != 0, the object is added to the commit list 17 | UsdBaseObject(ANARIDataType t, UsdDevice* device = nullptr); 18 | 19 | virtual void filterSetParam( 20 | const char *name, 21 | ANARIDataType type, 22 | const void *mem, 23 | UsdDevice* device) = 0; 24 | 25 | virtual void filterResetParam( 26 | const char *name) = 0; 27 | 28 | virtual void resetAllParams() = 0; 29 | 30 | virtual void* getParameter(const char* name, ANARIDataType& returnType) = 0; 31 | 32 | virtual int getProperty(const char *name, 33 | ANARIDataType type, 34 | void *mem, 35 | uint64_t size, 36 | UsdDevice* device) = 0; 37 | 38 | virtual void commit(UsdDevice* device) = 0; 39 | 40 | virtual void remove(UsdDevice* device) = 0; // Remove any committed data and refs 41 | 42 | ANARIDataType getType() const { return type; } 43 | 44 | void addObserver(UsdBaseObject* observer); 45 | void removeObserver(UsdBaseObject* observer); 46 | void notify(UsdBaseObject* caller, UsdDevice* device); 47 | virtual void observe(UsdBaseObject* caller, UsdDevice* device) {} 48 | 49 | protected: 50 | virtual bool deferCommit(UsdDevice* device) = 0; // Returns whether data commit has to be deferred 51 | virtual bool doCommitData(UsdDevice* device) = 0; // Data commit, execution can be immediate, returns whether doCommitRefs has to be performed 52 | virtual void doCommitRefs(UsdDevice* device) = 0; // For updates with dependencies on referenced object's data, is always executed deferred 53 | 54 | ANARIDataType type; 55 | 56 | friend class UsdDevice; 57 | 58 | std::vector observers; 59 | }; 60 | 61 | void UsdBridgeAddToCommitList(UsdDevice* device, UsdBaseObject* object, bool commitData); // Helper function to suppress compiler warnings 62 | 63 | // Templated base implementation of parameterized object 64 | template 65 | class UsdParameterizedBaseObject : public UsdBaseObject, public UsdParameterizedObject 66 | { 67 | public: 68 | typedef UsdParameterizedObject ParamClass; 69 | 70 | UsdParameterizedBaseObject(ANARIDataType t, UsdDevice* device = nullptr) 71 | : UsdBaseObject(t, device) 72 | {} 73 | 74 | void filterSetParam( 75 | const char *name, 76 | ANARIDataType type, 77 | const void *mem, 78 | UsdDevice* device) override 79 | { 80 | ParamClass::setParam(name, type, mem, device); 81 | } 82 | 83 | void filterResetParam( 84 | const char *name) override 85 | { 86 | ParamClass::resetParam(name); 87 | } 88 | 89 | void resetAllParams() override 90 | { 91 | ParamClass::resetParams(); 92 | } 93 | 94 | void* getParameter(const char* name, ANARIDataType& returnType) override 95 | { 96 | return ParamClass::getParam(name, returnType); 97 | } 98 | 99 | int getProperty(const char *name, 100 | ANARIDataType type, 101 | void *mem, 102 | uint64_t size, 103 | UsdDevice* device) override 104 | { 105 | return 0; 106 | } 107 | 108 | void commit(UsdDevice* device) override 109 | { 110 | ParamClass::transferWriteToReadParams(); 111 | UsdBaseObject::commit(device); 112 | } 113 | 114 | // Convenience functions for commonly used name property 115 | virtual const char* getName() const { return ""; } 116 | 117 | protected: 118 | 119 | void onParamRefChanged(UsdBaseObject* paramObject, bool incRef, bool onWriteParams) override 120 | { 121 | // Only observe arrays that have actually been committed, so !onWriteParams 122 | if(!onWriteParams && anari::isArray(paramObject->getType())) 123 | { 124 | if(incRef) 125 | paramObject->addObserver(this); 126 | else 127 | paramObject->removeObserver(this); 128 | } 129 | } 130 | 131 | void observe(UsdBaseObject* caller, UsdDevice* device) override 132 | { 133 | if(anari::isArray(caller->getType())) 134 | { 135 | UsdBridgeAddToCommitList(device, this, true); // No write to read params; just write to USD 136 | ParamClass::paramChanged = true; 137 | } 138 | } 139 | 140 | // Convenience functions for commonly used name property 141 | bool setNameParam(const char *name, 142 | ANARIDataType type, 143 | const void *mem, 144 | UsdDevice* device) 145 | { 146 | const char* objectName = static_cast(mem); 147 | 148 | if (type == ANARI_STRING) 149 | { 150 | if (strEquals(name, "name")) 151 | { 152 | if (!objectName || strEquals(objectName, "")) 153 | { 154 | reportStatusThroughDevice(UsdLogInfo(device, this, ANARI_OBJECT, nullptr), ANARI_SEVERITY_WARNING, ANARI_STATUS_NO_ERROR, 155 | "%s: ANARI object %s cannot be an empty string, using auto-generated name instead.", getName(), "name"); 156 | } 157 | else 158 | { 159 | ParamClass::setParam(name, type, mem, device); 160 | ParamClass::setParam("usd::name", type, mem, device); 161 | this->formatUsdName(this->getWriteParams().usdName); 162 | } 163 | return true; 164 | } 165 | else if (strEquals(name, "usd::name")) 166 | { 167 | reportStatusThroughDevice(UsdLogInfo(device, this, ANARI_OBJECT, nullptr), ANARI_SEVERITY_WARNING, ANARI_STATUS_NO_ERROR, 168 | "%s parameter '%s' cannot be set, only read with getProperty().", getName(), "usd::name"); 169 | return true; 170 | } 171 | } 172 | return false; 173 | } 174 | 175 | int getNameProperty(const char *name, 176 | ANARIDataType type, 177 | void *mem, 178 | uint64_t size, 179 | UsdDevice* device) 180 | { 181 | if (type == ANARI_STRING && strEquals(name, "usd::name")) 182 | { 183 | snprintf((char*)mem, size, "%s", UsdSharedString::c_str(this->getReadParams().usdName)); 184 | return 1; 185 | } 186 | else if (type == ANARI_UINT64 && strEquals(name, "usd::name.size")) 187 | { 188 | if (Assert64bitStringLengthProperty(size, UsdLogInfo(device, this, ANARI_ARRAY, this->getName()), "usd::name.size")) 189 | { 190 | uint64_t nameLen = this->getReadParams().usdName ? strlen(this->getReadParams().usdName->c_str())+1 : 0; 191 | memcpy(mem, &nameLen, size); 192 | } 193 | return 1; 194 | } 195 | return 0; 196 | } 197 | }; -------------------------------------------------------------------------------- /UsdBridge/Common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | message( "-------------------- Begin UsdBridgeCommon CmakeLists.txt ----------------------------------------") 2 | 3 | project(UsdBridge_Common) 4 | add_library(${PROJECT_NAME} INTERFACE) 5 | 6 | target_sources(${PROJECT_NAME} 7 | INTERFACE 8 | ${CMAKE_CURRENT_LIST_DIR}/UsdBridgeData.h 9 | ${CMAKE_CURRENT_LIST_DIR}/UsdBridgeMacros.h 10 | ${CMAKE_CURRENT_LIST_DIR}/UsdBridgeNumerics.h 11 | ${CMAKE_CURRENT_LIST_DIR}/UsdBridgeUtils_Internal.h 12 | ${CMAKE_CURRENT_LIST_DIR}/UsdBridgeUtils.cpp 13 | ${CMAKE_CURRENT_LIST_DIR}/UsdBridgeUtils.h 14 | ) 15 | 16 | target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}) 17 | 18 | message( "-------------------- End UsdBridgeCommon CmakeLists.txt ----------------------------------------") 19 | 20 | -------------------------------------------------------------------------------- /UsdBridge/Common/UsdBridgeMacros.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #define USE_USD_GEOM_POINTS 7 | 8 | #if defined(USE_FABRIC) && !defined(USE_USDRT) 9 | #define USE_USDRT // Force USDRT when Fabric is enabled 10 | #endif 11 | 12 | #define OMNIVERSE_CREATE_WORKAROUNDS 13 | //#define CUSTOM_PBR_MDL 14 | #define USE_INDEX_MATERIALS 15 | 16 | #ifdef USE_USDRT 17 | // UsdRt cannot use composition elements like sublayers, 18 | // changes don't propagate, so external stages just replace the existing scenestage 19 | #define REPLACE_SCENE_BY_EXTERNAL_STAGE 20 | #endif 21 | 22 | // To enable output that usdview can digest (just a single float) 23 | //#define USDBRIDGE_VOL_FLOAT1_OUTPUT 24 | 25 | #if defined(TIME_CLIP_STAGES) && !defined(VALUE_CLIP_RETIMING) 26 | #define VALUE_CLIP_RETIMING 27 | #endif 28 | 29 | #if defined(VALUE_CLIP_RETIMING) && !defined(TIME_BASED_CACHING) 30 | #define TIME_BASED_CACHING 31 | #endif 32 | 33 | #define USDBRIDGE_MAX_LOG_VERBOSITY 4 -------------------------------------------------------------------------------- /UsdBridge/Common/UsdBridgeNumerics.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef UsdBridgeNumerics_h 5 | #define UsdBridgeNumerics_h 6 | 7 | #include "UsdBridgeMacros.h" 8 | 9 | #ifndef _USE_MATH_DEFINES 10 | #define _USE_MATH_DEFINES 11 | #endif 12 | 13 | #include 14 | #include 15 | 16 | struct UsdUChar2 17 | { 18 | static constexpr int NumComponents = 2; 19 | using DataType = uint8_t; 20 | DataType Data[NumComponents] = { 0, 0 }; 21 | }; 22 | 23 | struct UsdChar2 24 | { 25 | static constexpr int NumComponents = 2; 26 | using DataType = int8_t; 27 | DataType Data[NumComponents] = { 0, 0 }; 28 | }; 29 | 30 | struct UsdUShort2 31 | { 32 | static constexpr int NumComponents = 2; 33 | using DataType = uint16_t; 34 | DataType Data[NumComponents] = { 0, 0 }; 35 | }; 36 | 37 | struct UsdShort2 38 | { 39 | static constexpr int NumComponents = 2; 40 | using DataType = int16_t; 41 | DataType Data[NumComponents] = { 0, 0 }; 42 | }; 43 | 44 | struct UsdUChar3 45 | { 46 | static constexpr int NumComponents = 3; 47 | using DataType = uint8_t; 48 | DataType Data[NumComponents] = { 0, 0, 0 }; 49 | }; 50 | 51 | struct UsdChar3 52 | { 53 | static constexpr int NumComponents = 3; 54 | using DataType = int8_t; 55 | DataType Data[NumComponents] = { 0, 0, 0 }; 56 | }; 57 | 58 | struct UsdUShort3 59 | { 60 | static constexpr int NumComponents = 3; 61 | using DataType = uint16_t; 62 | DataType Data[NumComponents] = { 0, 0, 0 }; 63 | }; 64 | 65 | struct UsdShort3 66 | { 67 | static constexpr int NumComponents = 3; 68 | using DataType = int16_t; 69 | DataType Data[NumComponents] = { 0, 0, 0 }; 70 | }; 71 | 72 | struct UsdUChar4 73 | { 74 | static constexpr int NumComponents = 4; 75 | using DataType = uint8_t; 76 | DataType Data[NumComponents] = { 0, 0, 0, 0 }; 77 | }; 78 | 79 | struct UsdChar4 80 | { 81 | static constexpr int NumComponents = 4; 82 | using DataType = int8_t; 83 | DataType Data[NumComponents] = { 0, 0, 0, 0 }; 84 | }; 85 | 86 | struct UsdUShort4 87 | { 88 | static constexpr int NumComponents = 4; 89 | using DataType = uint16_t; 90 | DataType Data[NumComponents] = { 0, 0, 0, 0 }; 91 | }; 92 | 93 | struct UsdShort4 94 | { 95 | static constexpr int NumComponents = 4; 96 | using DataType = int16_t; 97 | DataType Data[NumComponents] = { 0, 0, 0, 0 }; 98 | }; 99 | 100 | struct UsdUint2 101 | { 102 | static constexpr int NumComponents = 2; 103 | using DataType = uint32_t; 104 | DataType Data[NumComponents] = { 0, 0 }; 105 | }; 106 | 107 | struct UsdFloat2 108 | { 109 | static constexpr int NumComponents = 2; 110 | using DataType = float; 111 | DataType Data[NumComponents] = { 1.0, 1.0 }; 112 | }; 113 | 114 | struct UsdFloat3 115 | { 116 | static constexpr int NumComponents = 3; 117 | using DataType = float; 118 | DataType Data[NumComponents] = { 1.0, 1.0, 1.0 }; 119 | }; 120 | 121 | struct UsdFloat4 122 | { 123 | using DataType = float; 124 | DataType Data[4] = { 1.0, 1.0, 1.0, 1.0 }; 125 | }; 126 | 127 | struct UsdFloatMat4 128 | { 129 | static constexpr int NumComponents = 16; 130 | using DataType = float; 131 | DataType Data[NumComponents] = { 132 | 1, 0, 0, 0, 133 | 0, 1, 0, 0, 134 | 0, 0, 1, 0, 135 | 0, 0, 0, 1 }; 136 | }; 137 | 138 | struct UsdQuaternion 139 | { 140 | using DataType = float; 141 | DataType Data[4] = {1.0, 0.0, 0.0, 0.0}; 142 | }; 143 | 144 | struct UsdFloatBox1 145 | { 146 | using DataType = float; 147 | DataType Data[2] = { 0.0f, 1.0f }; 148 | }; 149 | 150 | struct UsdFloatBox2 151 | { 152 | using DataType = float; 153 | DataType Data[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; 154 | }; 155 | 156 | namespace usdbridgenumerics 157 | { 158 | template 159 | bool isIdentity(const T& val) 160 | { 161 | static T identity; 162 | return !memcmp(val.Data, identity.Data, sizeof(T)); 163 | } 164 | 165 | inline void DirectionToQuaternionZ(float* dir, float dirLength, float* quat) 166 | { 167 | // Use Z axis of glyph to orient along. 168 | 169 | // (dot(|segDir|, zAxis), cross(|segDir|, zAxis)) gives (cos(th), axis*sin(th)), 170 | // but rotation is represented by cos(th/2), axis*sin(th/2), ie. half the amount of rotation. 171 | // So calculate (dot(|halfVec|, zAxis), cross(|halfVec|, zAxis)) instead. 172 | float invDirLength = 1.0f / dirLength; 173 | float halfVec[3] = { 174 | dir[0] * invDirLength, 175 | dir[1] * invDirLength, 176 | dir[2] * invDirLength + 1.0f 177 | }; 178 | float halfNorm = sqrtf(halfVec[0] * halfVec[0] + halfVec[1] * halfVec[1] + halfVec[2] * halfVec[2]); 179 | if (halfNorm != 0.0f) 180 | { 181 | float invHalfNorm = 1.0f / halfNorm; 182 | halfVec[0] *= invHalfNorm; 183 | halfVec[1] *= invHalfNorm; 184 | halfVec[2] *= invHalfNorm; 185 | } 186 | 187 | // Cross zAxis (0,0,1) with segment direction (new Z axis) to get rotation axis * sin(angle) 188 | float sinAxis[3] = { -halfVec[1], halfVec[0], 0.0f }; 189 | // Dot for cos(angle) 190 | float cosAngle = halfVec[2]; 191 | 192 | if (halfNorm == 0.0f) // In this case there is a 180 degree rotation 193 | { 194 | sinAxis[1] = 1.0f; //sinAxis*sin(pi/2) = (0,1,0)*sin(pi/2) = (0,1,0) 195 | // cosAngle = cos(pi/2) = 0.0f; 196 | } 197 | 198 | quat[0] = sinAxis[0]; 199 | quat[1] = sinAxis[1]; 200 | quat[2] = sinAxis[2]; 201 | quat[3] = cosAngle; 202 | } 203 | } 204 | 205 | #endif 206 | 207 | -------------------------------------------------------------------------------- /UsdBridge/Common/UsdBridgeUtils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef UsdBridgeUtils_h 5 | #define UsdBridgeUtils_h 6 | 7 | #include "UsdBridgeData.h" 8 | 9 | // USD-independent utils for the UsdBridge 10 | 11 | #define UsdBridgeLogMacro(obj, level, message) \ 12 | { std::stringstream logStream; \ 13 | logStream << message; \ 14 | std::string logString = logStream.str(); \ 15 | obj.LogCallback(level, obj.LogUserData, logString.c_str()); } 16 | 17 | namespace ubutils 18 | { 19 | const char* UsdBridgeTypeToString(UsdBridgeType type); 20 | UsdBridgeType UsdBridgeTypeFlatten(UsdBridgeType type); 21 | 22 | const float* SrgbToLinearTable(); // returns a float[256] array 23 | float SrgbToLinear(float val); 24 | void SrgbToLinear3(float* color); // expects a float[3] 25 | 26 | template 27 | DMI GetAttribBit(int attribIndex) 28 | { 29 | return (static_cast(static_cast(DMI::ATTRIBUTE0) << attribIndex)); 30 | } 31 | } 32 | 33 | #endif -------------------------------------------------------------------------------- /UsdBridge/Common/UsdBridgeUtils_Internal.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef UsdBridgeUtils_Internal_h 5 | #define UsdBridgeUtils_Internal_h 6 | 7 | #include "UsdBridgeData.h" 8 | 9 | #include 10 | 11 | namespace 12 | { 13 | inline bool strEquals(const char* arg0, const char* arg1) 14 | { 15 | return strcmp(arg0, arg1) == 0; 16 | } 17 | } 18 | 19 | #endif -------------------------------------------------------------------------------- /UsdBridge/Connection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | message( "-------------------- Begin UsdBridgeConnect CmakeLists.txt ----------------------------------------") 2 | 3 | message(STATUS "----- UsdCon level: ${USD_DEVICE_TIME_DEFS}") 4 | 5 | option(USD_DEVICE_USE_OMNIVERSE "Enable Omniverse support for USD device" OFF) 6 | 7 | project(UsdBridge_Connect) 8 | add_library(${PROJECT_NAME} INTERFACE) 9 | 10 | #################### 11 | # Omniverse Client # 12 | #################### 13 | 14 | function(get_omni_dependency 15 | DEP_ROOT_DIR 16 | DEP_INCLUDE_DIR 17 | DEP_LIB_DIR 18 | INPUT_ROOT_DIR 19 | INPUT_ROOT_DIR_NAME 20 | INPUT_NAME 21 | INPUT_HEADER) 22 | 23 | if (NOT EXISTS ${INPUT_ROOT_DIR}) 24 | find_path(INPUT_ROOT_DIR NAMES ${INPUT_HEADER} DOC "Path to ${INPUT_NAME}") 25 | message(STATUS "Using ${INPUT_ROOT_DIR_NAME}: ${INPUT_ROOT_DIR}") 26 | endif() 27 | 28 | if (NOT EXISTS ${INPUT_ROOT_DIR}) 29 | message(FATAL_ERROR "No valid ${INPUT_ROOT_DIR_NAME} set, or found using CMAKE_PREFIX_PATH: ${INPUT_ROOT_DIR}") 30 | endif() 31 | 32 | set(${DEP_ROOT_DIR} ${INPUT_ROOT_DIR} PARENT_SCOPE) 33 | 34 | if(EXISTS ${INPUT_ROOT_DIR}) 35 | MESSAGE(STATUS "UsdBridge is using ${INPUT_NAME} at: ${INPUT_ROOT_DIR}") 36 | 37 | set(DEP_DIR_RELEASE "${INPUT_ROOT_DIR}/release") 38 | set(DEP_DIR_DEBUG "${INPUT_ROOT_DIR}/debug") 39 | set(DEP_LIB_DIR_RELEASE "${DEP_DIR_RELEASE}") 40 | set(DEP_LIB_DIR_DEBUG "${DEP_DIR_DEBUG}") 41 | 42 | set(${DEP_INCLUDE_DIR} "${INPUT_ROOT_DIR}/include" PARENT_SCOPE) 43 | 44 | if (CMAKE_CONFIGURATION_TYPES) 45 | set(_DEP_LIB_DIR "$<$>:${DEP_LIB_DIR_RELEASE}>$<$:${DEP_LIB_DIR_DEBUG}>") 46 | else() 47 | if(CMAKE_BUILD_TYPE MATCHES "Debug") 48 | set(_DEP_LIB_DIR ${DEP_LIB_DIR_DEBUG}) 49 | else() 50 | set(_DEP_LIB_DIR ${DEP_LIB_DIR_RELEASE}) 51 | endif() 52 | endif() 53 | 54 | set(${DEP_LIB_DIR} ${_DEP_LIB_DIR} PARENT_SCOPE) 55 | 56 | MESSAGE(STATUS "${INPUT_NAME} LIB_DIR: ${_DEP_LIB_DIR}") 57 | else() 58 | MESSAGE(FATAL_ERROR "Cannot find ${INPUT_ROOT_DIR_NAME}: ${INPUT_ROOT_DIR}") 59 | endif() 60 | 61 | endfunction() 62 | 63 | if(${USD_DEVICE_USE_OMNIVERSE}) 64 | set(OMNICLIENT_ROOT_DIR "" CACHE PATH "Path to the OmniClient Library") 65 | set(OMNIUSDRESOLVER_ROOT_DIR "" CACHE PATH "Path to the Usd Resolver Library") 66 | 67 | get_omni_dependency( 68 | OMNICLIENT_ROOT_DIR 69 | OMNICLIENT_INCLUDE_DIR 70 | OMNICLIENT_LIB_DIR 71 | "${OMNICLIENT_ROOT_DIR}" 72 | "OMNICLIENT_ROOT_DIR" 73 | "Omniverse Client" 74 | "include/OmniClient.h") 75 | 76 | get_omni_dependency( 77 | OMNIUSDRESOLVER_ROOT_DIR 78 | OMNIUSDRESOLVER_INCLUDE_DIR 79 | OMNIUSDRESOLVER_LIB_DIR 80 | "${OMNIUSDRESOLVER_ROOT_DIR}" 81 | "OMNIUSDRESOLVER_ROOT_DIR" 82 | "Omniverse USD Resolver" 83 | "include/OmniUsdResolver.h") 84 | 85 | list(APPEND OMNICLIENT_SHARED_LIBS omniclient) 86 | list(APPEND OMNIUSDRESOLVER_SHARED_LIBS omni_usd_resolver) 87 | 88 | else() 89 | MESSAGE(STATUS "UsdBridge is NOT using OmniClient for remote connections.") 90 | endif() 91 | 92 | #################### 93 | # UsdBridgeConnect # 94 | #################### 95 | 96 | target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}) 97 | 98 | target_sources(${PROJECT_NAME} 99 | INTERFACE 100 | ${CMAKE_CURRENT_LIST_DIR}/UsdBridgeConnection.cpp 101 | ${CMAKE_CURRENT_LIST_DIR}/UsdBridgeConnection.h) 102 | 103 | target_link_libraries(${PROJECT_NAME} 104 | INTERFACE 105 | UsdBridge_Common 106 | ) 107 | 108 | if(${USD_DEVICE_USE_OMNIVERSE}) 109 | # Set include and lib dirs 110 | target_include_directories(${PROJECT_NAME} INTERFACE ${OMNICLIENT_INCLUDE_DIR} ${OMNIUSDRESOLVER_INCLUDE_DIR}) 111 | target_compile_definitions(${PROJECT_NAME} INTERFACE OMNIVERSE_CONNECTION_ENABLE) 112 | 113 | if (WIN32) 114 | target_link_directories(${PROJECT_NAME} INTERFACE ${OMNICLIENT_LIB_DIR} ${OMNIUSDRESOLVER_LIB_DIR}) 115 | set(USDBRIDGE_CONNECT_LINK_LIBS ${OMNICLIENT_SHARED_LIBS} ${OMNIUSDRESOLVER_SHARED_LIBS}) 116 | else() 117 | if(NOT ${USD_DEVICE_USE_CXX11_ABI}) 118 | target_compile_definitions(${PROJECT_NAME} INTERFACE 119 | _GLIBCXX_USE_CXX11_ABI=0 ) 120 | endif() 121 | 122 | foreach(lib ${OMNICLIENT_SHARED_LIBS}) 123 | find_library(path ${lib} PATHS ${OMNICLIENT_LIB_DIR} NO_DEFAULT_PATH REQUIRED) 124 | list(APPEND OMNI_LIBS ${path}) 125 | unset(path CACHE) 126 | endforeach() 127 | 128 | foreach(lib ${OMNIUSDRESOLVER_SHARED_LIBS}) 129 | find_library(path ${lib} PATHS ${OMNIUSDRESOLVER_LIB_DIR} NO_DEFAULT_PATH REQUIRED) 130 | list(APPEND OMNI_LIBS ${path}) 131 | unset(path CACHE) 132 | endforeach() 133 | 134 | set(USDBRIDGE_CONNECT_LINK_LIBS ${OMNI_LIBS}) 135 | endif() 136 | 137 | target_link_libraries(${PROJECT_NAME} INTERFACE ${USDBRIDGE_CONNECT_LINK_LIBS}) 138 | 139 | option(INSTALL_OMNIVERSE_DEPS "Enable install of Omniverse dependencies with USD device" OFF) 140 | if(${INSTALL_OMNIVERSE_DEPS}) 141 | # Install client library 142 | set(PLATFORM_INSTALL_LIBDIR "$<$>:${CMAKE_INSTALL_LIBDIR}>$<$:${CMAKE_INSTALL_BINDIR}>/") 143 | install( 144 | DIRECTORY "${OMNICLIENT_LIB_DIR}/" 145 | DESTINATION ${PLATFORM_INSTALL_LIBDIR} 146 | PATTERN "*${CMAKE_STATIC_LIBRARY_SUFFIX}" EXCLUDE 147 | PATTERN "bindings-python" EXCLUDE) 148 | install( 149 | DIRECTORY "${OMNIUSDRESOLVER_LIB_DIR}/" 150 | DESTINATION ${PLATFORM_INSTALL_LIBDIR} 151 | PATTERN "*${CMAKE_STATIC_LIBRARY_SUFFIX}" EXCLUDE 152 | PATTERN "bindings-python" EXCLUDE) 153 | endif() 154 | endif() 155 | 156 | message( "-------------------- End UsdBridgeConnect CmakeLists.txt ----------------------------------------") 157 | 158 | -------------------------------------------------------------------------------- /UsdBridge/Connection/UsdBridgeConnection.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef UsdBridgeConnection_h 5 | #define UsdBridgeConnection_h 6 | 7 | #include "UsdBridgeData.h" 8 | 9 | #include 10 | 11 | class UsdBridgeRemoteConnectionInternals; 12 | 13 | struct UsdBridgeConnectionSettings 14 | { 15 | std::string HostName; 16 | std::string WorkingDirectory; 17 | }; 18 | 19 | class UsdBridgeConnection 20 | { 21 | public: 22 | UsdBridgeConnection() {} 23 | virtual ~UsdBridgeConnection() {}; 24 | 25 | virtual const char* GetBaseUrl() const = 0; 26 | virtual const char* GetUrl(const char* path) const = 0; 27 | 28 | virtual bool Initialize(const UsdBridgeConnectionSettings& settings, 29 | const UsdBridgeLogObject& logObj) = 0; 30 | virtual void Shutdown() = 0; 31 | 32 | virtual int MaxSessionNr() const = 0; 33 | 34 | virtual bool CreateFolder(const char* dirName, bool isRelative, bool mayExist) const = 0; 35 | virtual bool RemoveFolder(const char* dirName, bool isRelative) const = 0; 36 | virtual bool WriteFile(const char* data, size_t dataSize, const char* filePath, bool isRelative, bool binary = true) const = 0; 37 | virtual bool RemoveFile(const char* filePath, bool isRelative) const = 0; 38 | 39 | virtual bool ProcessUpdates() = 0; 40 | 41 | static UsdBridgeLogCallback LogCallback; 42 | static void* LogUserData; 43 | 44 | UsdBridgeConnectionSettings Settings; 45 | 46 | protected: 47 | 48 | mutable std::string TempUrl; 49 | }; 50 | 51 | 52 | class UsdBridgeLocalConnection : public UsdBridgeConnection 53 | { 54 | public: 55 | UsdBridgeLocalConnection(); 56 | ~UsdBridgeLocalConnection() override; 57 | 58 | const char* GetBaseUrl() const override; 59 | const char* GetUrl(const char* path) const override; 60 | 61 | bool Initialize(const UsdBridgeConnectionSettings& settings, 62 | const UsdBridgeLogObject& logObj) override; 63 | void Shutdown() override; 64 | 65 | int MaxSessionNr() const override; 66 | 67 | bool CreateFolder(const char* dirName, bool isRelative, bool mayExist) const override; 68 | bool RemoveFolder(const char* dirName, bool isRelative) const override; 69 | bool WriteFile(const char* data, size_t dataSize, const char* filePath, bool isRelative, bool binary = true) const override; 70 | bool RemoveFile(const char* filePath, bool isRelative) const override; 71 | 72 | bool ProcessUpdates() override; 73 | 74 | protected: 75 | }; 76 | 77 | class UsdBridgeRemoteConnection : public UsdBridgeConnection 78 | { 79 | public: 80 | UsdBridgeRemoteConnection(); 81 | ~UsdBridgeRemoteConnection() override; 82 | 83 | const char* GetBaseUrl() const override; 84 | const char* GetUrl(const char* path) const override; 85 | 86 | bool Initialize(const UsdBridgeConnectionSettings& settings, 87 | const UsdBridgeLogObject& logObj) override; 88 | void Shutdown() override; 89 | 90 | int MaxSessionNr() const override; 91 | 92 | bool CreateFolder(const char* dirName, bool isRelative, bool mayExist) const override; 93 | bool RemoveFolder(const char* dirName, bool isRelative) const override; 94 | bool WriteFile(const char* data, size_t dataSize, const char* filePath, bool isRelative, bool binary = true) const override; 95 | bool RemoveFile(const char* filePath, bool isRelative) const override; 96 | 97 | bool ProcessUpdates() override; 98 | 99 | static void SetConnectionLogLevel(int logLevel); 100 | static int GetConnectionLogLevelMax(); 101 | 102 | static int NumConnInstances; 103 | static int NumInitializedConnInstances; 104 | 105 | protected: 106 | 107 | bool CheckWritePermissions(); 108 | 109 | UsdBridgeRemoteConnectionInternals* Internals; 110 | bool ConnectionInitialized = false; 111 | 112 | static int ConnectionLogLevel; 113 | }; 114 | 115 | class UsdBridgeVoidConnection : public UsdBridgeConnection 116 | { 117 | public: 118 | UsdBridgeVoidConnection(); 119 | ~UsdBridgeVoidConnection() override; 120 | 121 | const char* GetBaseUrl() const override; 122 | const char* GetUrl(const char* path) const override; 123 | 124 | bool Initialize(const UsdBridgeConnectionSettings& settings, 125 | const UsdBridgeLogObject& logObj) override; 126 | void Shutdown() override; 127 | 128 | int MaxSessionNr() const override; 129 | 130 | bool CreateFolder(const char* dirName, bool isRelative, bool mayExist) const override; 131 | bool RemoveFolder(const char* dirName, bool isRelative) const override; 132 | bool WriteFile(const char* data, size_t dataSize, const char* filePath, bool isRelative, bool binary = true) const override; 133 | bool RemoveFile(const char* filePath, bool isRelative) const override; 134 | 135 | bool ProcessUpdates() override; 136 | 137 | protected: 138 | }; 139 | 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /UsdBridge/Mdl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | message( "-------------------- Begin UsdBridgeMdl CmakeLists.txt ----------------------------------------") 2 | 3 | set( USDBRIDGE_MDL_SOURCES 4 | Mdl/UsdBridgeMdlStrings.h 5 | PARENT_SCOPE) 6 | 7 | 8 | message( "-------------------- End UsdBridgeMdl CmakeLists.txt ----------------------------------------") -------------------------------------------------------------------------------- /UsdBridge/UsdBridge.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef UsdBridge_h 5 | #define UsdBridge_h 6 | 7 | #include "UsdBridgeData.h" 8 | 9 | struct UsdBridgeInternals; 10 | typedef void* SceneStagePtr; // Placeholder for UsdStage* 11 | 12 | class UsdBridge 13 | { 14 | public: 15 | using MaterialDMI = UsdBridgeMaterialData::DataMemberId; 16 | using SamplerDMI = UsdBridgeSamplerData::DataMemberId; 17 | using MaterialInputAttribName = std::pair; 18 | 19 | UsdBridge(const UsdBridgeSettings& settings); 20 | ~UsdBridge(); 21 | 22 | void SetExternalSceneStage(SceneStagePtr sceneStage); 23 | void SetEnableSaving(bool enableSaving); 24 | 25 | bool OpenSession(UsdBridgeLogCallback logCallback, void* logUserData); 26 | bool GetSessionValid() const { return SessionValid; } 27 | void CloseSession(); 28 | 29 | bool CreateWorld(const char* name, UsdWorldHandle& handle); 30 | bool CreateInstance(const char* name, UsdInstanceHandle& handle); 31 | bool CreateGroup(const char* name, UsdGroupHandle& handle); 32 | bool CreateSurface(const char* name, UsdSurfaceHandle& handle); 33 | bool CreateVolume(const char* name, UsdVolumeHandle& handle); 34 | bool CreateGeometry(const char* name, UsdGeometryHandle& handle, const UsdBridgeMeshData& meshData); 35 | bool CreateGeometry(const char* name, UsdGeometryHandle& handle, const UsdBridgeInstancerData& instancerData); 36 | bool CreateGeometry(const char* name, UsdGeometryHandle& handle, const UsdBridgeCurveData& curveData); 37 | bool CreateSpatialField(const char* name, UsdSpatialFieldHandle& handle); 38 | bool CreateMaterial(const char* name, UsdMaterialHandle& handle); 39 | bool CreateSampler(const char* name, UsdSamplerHandle& handle, UsdBridgeSamplerData::SamplerType type); 40 | bool CreateCamera(const char* name, UsdCameraHandle& handle); 41 | 42 | void DeleteWorld(UsdWorldHandle handle); 43 | void DeleteInstance(UsdInstanceHandle handle); 44 | void DeleteGroup(UsdGroupHandle handle); 45 | void DeleteSurface(UsdSurfaceHandle handle); 46 | void DeleteVolume(UsdVolumeHandle handle); 47 | void DeleteGeometry(UsdGeometryHandle handle); 48 | void DeleteSpatialField(UsdSpatialFieldHandle handle); 49 | void DeleteMaterial(UsdMaterialHandle handle); 50 | void DeleteSampler(UsdSamplerHandle handle); 51 | void DeleteCamera(UsdCameraHandle handle); 52 | 53 | void SetInstanceRefs(UsdWorldHandle world, const UsdInstanceHandle* instances, uint64_t numInstances, bool timeVarying, double timeStep, const int* instanceableValues); 54 | void SetGroupRef(UsdInstanceHandle instance, UsdGroupHandle group, bool timeVarying, double timeStep); 55 | void SetSurfaceRefs(UsdWorldHandle world, const UsdSurfaceHandle* surfaces, uint64_t numSurfaces, bool timeVarying, double timeStep, const int* instanceableValues); 56 | void SetSurfaceRefs(UsdGroupHandle group, const UsdSurfaceHandle* surfaces, uint64_t numSurfaces, bool timeVarying, double timeStep, const int* instanceableValues); 57 | void SetVolumeRefs(UsdWorldHandle world, const UsdVolumeHandle* volumes, uint64_t numVolumes, bool timeVarying, double timeStep, const int* instanceableValues); 58 | void SetVolumeRefs(UsdGroupHandle group, const UsdVolumeHandle* volumes, uint64_t numVolumes, bool timeVarying, double timeStep, const int* instanceableValues); 59 | void SetGeometryRef(UsdSurfaceHandle surface, UsdGeometryHandle geometry, double timeStep, double geomTimeStep); 60 | void SetGeometryMaterialRef(UsdSurfaceHandle surface, UsdGeometryHandle geometry, UsdMaterialHandle material, double timeStep, double geomTimeStep, double matTimeStep); 61 | void SetSpatialFieldRef(UsdVolumeHandle volume, UsdSpatialFieldHandle field, double timeStep, double fieldTimeStep); 62 | void SetSamplerRefs(UsdMaterialHandle material, const UsdSamplerHandle* samplers, size_t numSamplers, double timeStep, const UsdSamplerRefData* samplerRefData); 63 | void SetPrototypeRefs(UsdGeometryHandle geometry, const UsdGeometryHandle* protoGeometries, size_t numProtoGeometries, double timeStep, double* protoTimeSteps); 64 | 65 | void DeleteInstanceRefs(UsdWorldHandle world, bool timeVarying, double timeStep); 66 | void DeleteGroupRef(UsdInstanceHandle instance, bool timeVarying, double timeStep); 67 | void DeleteSurfaceRefs(UsdWorldHandle world, bool timeVarying, double timeStep); 68 | void DeleteSurfaceRefs(UsdGroupHandle group, bool timeVarying, double timeStep); 69 | void DeleteVolumeRefs(UsdWorldHandle world, bool timeVarying, double timeStep); 70 | void DeleteVolumeRefs(UsdGroupHandle group, bool timeVarying, double timeStep); 71 | void DeleteGeometryRef(UsdSurfaceHandle surface, double timeStep); 72 | void DeleteSpatialFieldRef(UsdVolumeHandle volume, double timeStep); 73 | void DeleteMaterialRef(UsdSurfaceHandle surface, double timeStep); 74 | void DeleteSamplerRefs(UsdMaterialHandle material, double timeStep); 75 | void DeletePrototypeRefs(UsdGeometryHandle geometry, double timeStep); 76 | 77 | void UpdateBeginEndTime(double timeStep); 78 | void SetInstanceTransform(UsdInstanceHandle instance, const float* transform, bool timeVarying, double timeStep); 79 | void SetGeometryData(UsdGeometryHandle geometry, const UsdBridgeMeshData& meshData, double timeStep); 80 | void SetGeometryData(UsdGeometryHandle geometry, const UsdBridgeInstancerData& instancerData, double timeStep); 81 | void SetGeometryData(UsdGeometryHandle geometry, const UsdBridgeCurveData& curveData, double timeStep); 82 | void SetSpatialFieldData(UsdSpatialFieldHandle field, const UsdBridgeVolumeData& volumeData, double timeStep); 83 | void SetMaterialData(UsdMaterialHandle material, const UsdBridgeMaterialData& matData, double timeStep); 84 | void SetSamplerData(UsdSamplerHandle sampler, const UsdBridgeSamplerData& samplerData, double timeStep); 85 | void SetCameraData(UsdCameraHandle camera, const UsdBridgeCameraData& cameraData, double timeStep); 86 | void SetPrototypeData(UsdGeometryHandle geometry, const UsdBridgeInstancerRefData& instancerRefData); // UsdBridgeInstancerRefData::Shapes used to index into refs from last SetPrototypeRefs (if SHAPE_MESH) 87 | 88 | void ChangeMaterialInputAttributes(UsdMaterialHandle material, const MaterialInputAttribName* inputAttribs, size_t numInputAttribs, double timeStep, MaterialDMI timeVarying); 89 | void ChangeInAttribute(UsdSamplerHandle sampler, const char* newName, double timeStep, SamplerDMI timeVarying); 90 | 91 | void SaveScene(); 92 | 93 | void ResetResourceUpdateState(); // Eg. clears all dirty flags on shared resources 94 | 95 | void GarbageCollect(); // Deletes all handles without parents (from SetRefs) 96 | 97 | const char* GetPrimPath(UsdBridgeHandle* handle); 98 | 99 | // 100 | // Static parameter interface 101 | // 102 | 103 | static void SetConnectionLogVerbosity(int logVerbosity); // 0 <= logVerbosity <= USDBRIDGE_MAX_LOG_VERBOSITY, 0 is quietest 104 | 105 | protected: 106 | 107 | template 108 | bool CreateGeometryTemplate(const char* name, UsdGeometryHandle& handle, const GeomDataType& geomData); 109 | 110 | template 111 | void SetGeometryDataTemplate(UsdGeometryHandle geometry, const GeomDataType& geomData, double timeStep); 112 | 113 | template 114 | void SetNoClipRefs(ParentHandleType parentHandle, const ChildHandleType* childHandles, uint64_t numChildren, 115 | const char* refPathExt, bool timeVarying, double timeStep, const int* instanceableValues = nullptr); 116 | 117 | template 118 | void DeleteAllRefs(ParentHandleType parentHandle, const char* refPathExt, bool timeVarying, double timeStep); 119 | 120 | void CreateRootPrimAndAttach(UsdBridgePrimCache* cacheEntry, const char* primPathCp, const char* layerId = nullptr); 121 | void RemoveRootPrimAndDetach(UsdBridgePrimCache* cacheEntry, const char* primPathCp); 122 | 123 | UsdBridgeInternals* Internals; 124 | 125 | bool EnableSaving; 126 | bool SessionValid; 127 | }; 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /UsdBridge/UsdBridgeCaches.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "usd.h" 5 | PXR_NAMESPACE_USING_DIRECTIVE 6 | 7 | #include "UsdBridgeCaches.h" 8 | #include "UsdBridgeUtils.h" 9 | 10 | #ifdef VALUE_CLIP_RETIMING 11 | constexpr double UsdBridgePrimCache::PrimStageTimeCode; 12 | #endif 13 | 14 | UsdBridgePrimCache::UsdBridgePrimCache(const SdfPath& pp, const SdfPath& nm, ResourceCollectFunc cf) 15 | : PrimPath(pp), Name(nm), ResourceCollect(cf) 16 | #ifndef NDEBUG 17 | , Debug_Name(nm.GetString()) 18 | #endif 19 | { 20 | if(cf) 21 | { 22 | ResourceKeys = std::make_unique(); 23 | } 24 | } 25 | 26 | UsdBridgePrimCache* UsdBridgePrimCache::GetChildCache(const TfToken& nameToken) 27 | { 28 | auto it = std::find_if(this->Children.begin(), this->Children.end(), 29 | [&nameToken](UsdBridgePrimCache* cache) -> bool { return cache->PrimPath.GetNameToken() == nameToken; }); 30 | 31 | return (it == this->Children.end()) ? nullptr : *it; 32 | } 33 | 34 | #ifdef TIME_BASED_CACHING 35 | void UsdBridgePrimCache::SetChildVisibleAtTime(const UsdBridgePrimCache* childCache, double timeCode) 36 | { 37 | auto childIt = std::find(this->Children.begin(), this->Children.end(), childCache); 38 | if(childIt == this->Children.end()) 39 | return; 40 | std::vector& visibleTimes = ChildVisibleAtTimes[childIt - this->Children.begin()]; 41 | 42 | auto timeIt = std::find(visibleTimes.begin(), visibleTimes.end(), timeCode); 43 | if(timeIt == visibleTimes.end()) 44 | visibleTimes.push_back(timeCode); 45 | } 46 | 47 | bool UsdBridgePrimCache::SetChildInvisibleAtTime(const UsdBridgePrimCache* childCache, double timeCode) 48 | { 49 | auto childIt = std::find(this->Children.begin(), this->Children.end(), childCache); 50 | if(childIt == this->Children.end()) 51 | return false; 52 | std::vector& visibleTimes = ChildVisibleAtTimes[childIt - this->Children.begin()]; 53 | 54 | auto timeIt = std::find(visibleTimes.begin(), visibleTimes.end(), timeCode); 55 | if(timeIt != visibleTimes.end()) 56 | { 57 | // Remove the time at visibleTimeIdx 58 | size_t visibleTimeIdx = timeIt - visibleTimes.begin(); 59 | visibleTimes[visibleTimeIdx] = visibleTimes.back(); 60 | visibleTimes.pop_back(); 61 | return visibleTimes.size() == 0; // Return child removed && empty 62 | } 63 | return false; 64 | } 65 | #endif 66 | 67 | #ifdef VALUE_CLIP_RETIMING 68 | const UsdStagePair& UsdBridgePrimCache::GetPrimStagePair() const 69 | { 70 | auto it = ClipStages.find(PrimStageTimeCode); 71 | assert(it != ClipStages.end()); 72 | return it->second; 73 | } 74 | #endif 75 | 76 | void UsdBridgePrimCache::AddChild(UsdBridgePrimCache* child) 77 | { 78 | if(std::find(this->Children.begin(), this->Children.end(), child) != this->Children.end()) 79 | return; 80 | 81 | this->Children.push_back(child); 82 | child->IncRef(); 83 | 84 | #ifdef TIME_BASED_CACHING 85 | this->ChildVisibleAtTimes.resize(this->Children.size()); 86 | #endif 87 | } 88 | 89 | void UsdBridgePrimCache::RemoveChild(UsdBridgePrimCache* child) 90 | { 91 | auto it = std::find(this->Children.begin(), this->Children.end(), child); 92 | // Allow for find to fail; in the case where the bridge is recreated and destroyed, 93 | // a child prim exists which doesn't have a ref in the cache. 94 | if(it != this->Children.end()) 95 | { 96 | #ifdef TIME_BASED_CACHING 97 | size_t foundIdx = it - this->Children.begin(); 98 | if(foundIdx != this->ChildVisibleAtTimes.size()-1) 99 | this->ChildVisibleAtTimes[foundIdx] = std::move(this->ChildVisibleAtTimes.back()); 100 | this->ChildVisibleAtTimes.pop_back(); 101 | #endif 102 | 103 | child->DecRef(); 104 | *it = this->Children.back(); 105 | this->Children.pop_back(); 106 | } 107 | } 108 | 109 | void UsdBridgePrimCache::RemoveUnreferencedChildTree(AtRemoveFunc atRemove) 110 | { 111 | assert(this->RefCount == 0); 112 | atRemove(this); 113 | 114 | for (UsdBridgePrimCache* child : this->Children) 115 | { 116 | child->DecRef(); 117 | if(child->RefCount == 0) 118 | child->RemoveUnreferencedChildTree(atRemove); 119 | } 120 | this->Children.clear(); 121 | } 122 | 123 | bool UsdBridgePrimCache::AddResourceKey(UsdBridgeResourceKey key) // copy by value 124 | { 125 | assert(ResourceKeys); 126 | bool newEntry = std::find(ResourceKeys->begin(), ResourceKeys->end(), key) == ResourceKeys->end(); 127 | if(newEntry) 128 | ResourceKeys->push_back(key); 129 | return newEntry; 130 | } 131 | 132 | UsdBridgePrimCacheManager::ConstPrimCacheIterator UsdBridgePrimCacheManager::FindPrimCache(const UsdBridgeHandle& handle) const 133 | { 134 | ConstPrimCacheIterator it = std::find_if( 135 | UsdPrimCaches.begin(), 136 | UsdPrimCaches.end(), 137 | [handle](const PrimCacheContainer::value_type& cmp) -> bool { return cmp.second.get() == handle.value; } 138 | ); 139 | 140 | return it; 141 | } 142 | 143 | UsdBridgePrimCacheManager::ConstPrimCacheIterator UsdBridgePrimCacheManager::CreatePrimCache(const std::string& name, const std::string& fullPath, ResourceCollectFunc collectFunc) 144 | { 145 | SdfPath nameSuffix(name); 146 | SdfPath primPath(fullPath); 147 | 148 | // Create new cache entry 149 | std::unique_ptr cacheEntry = std::make_unique(primPath, nameSuffix, collectFunc); 150 | return UsdPrimCaches.emplace(name, std::move(cacheEntry)).first; 151 | } 152 | 153 | void UsdBridgePrimCacheManager::AttachTopLevelPrim(UsdBridgePrimCache* primCache) 154 | { 155 | primCache->IncRef(); 156 | } 157 | 158 | void UsdBridgePrimCacheManager::DetachTopLevelPrim(UsdBridgePrimCache* primCache) 159 | { 160 | primCache->DecRef(); 161 | } 162 | 163 | void UsdBridgePrimCacheManager::AddChild(UsdBridgePrimCache* parent, UsdBridgePrimCache* child) 164 | { 165 | parent->AddChild(child); 166 | } 167 | 168 | void UsdBridgePrimCacheManager::RemoveChild(UsdBridgePrimCache* parent, UsdBridgePrimCache* child) 169 | { 170 | parent->RemoveChild(child); 171 | } 172 | 173 | void UsdBridgePrimCacheManager::RemovePrimCache(ConstPrimCacheIterator it, UsdBridgeLogObject& LogObject) 174 | { 175 | if(it->second->RefCount > 0) 176 | { 177 | UsdBridgeLogMacro(LogObject, UsdBridgeLogLevel::WARNING, "Primcache removed for object named: " << it->first << ", but refs still exist"); 178 | } 179 | UsdPrimCaches.erase(it); 180 | } 181 | 182 | void UsdBridgePrimCacheManager::RemoveUnreferencedPrimCaches(AtRemoveFunc atRemove) 183 | { 184 | // First recursively remove all the child references for unreferenced prims 185 | // Can only be performed at garbage collect. 186 | // If this is done during RemoveChild, an unreferenced parent cannot subsequently be revived with an AddChild. 187 | PrimCacheContainer::iterator it = UsdPrimCaches.begin(); 188 | while (it != UsdPrimCaches.end()) 189 | { 190 | if (it->second->RefCount == 0) 191 | { 192 | it->second->RemoveUnreferencedChildTree(atRemove); 193 | } 194 | ++it; 195 | } 196 | 197 | // Now delete all prims without references from the cache 198 | it = UsdPrimCaches.begin(); 199 | while (it != UsdPrimCaches.end()) 200 | { 201 | if (it->second->RefCount == 0) 202 | it = UsdPrimCaches.erase(it); 203 | else 204 | ++it; 205 | } 206 | } -------------------------------------------------------------------------------- /UsdBridge/UsdBridgeCaches.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef UsdBridgeCaches_h 5 | #define UsdBridgeCaches_h 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "UsdBridgeData.h" 13 | #include "UsdBridgeUtils_Internal.h" 14 | 15 | struct UsdBridgePrimCache; 16 | class UsdBridgeUsdWriter; 17 | class UsdBridgePrimCacheManager; 18 | 19 | typedef std::pair UsdStagePair; //Stage ptr and filename 20 | typedef std::pair, UsdBridgePrimCache*> BoolEntryPair; // Prim exists in stage, prim exists in cache, result cache entry ptr 21 | typedef void (*ResourceCollectFunc)(UsdBridgePrimCache*, UsdBridgeUsdWriter&); 22 | typedef std::function AtRemoveFunc; 23 | typedef std::vector UsdBridgePrimCacheList; 24 | typedef std::vector SdfPrimPathList; 25 | 26 | struct UsdBridgeResourceKey 27 | { 28 | UsdBridgeResourceKey() = default; 29 | ~UsdBridgeResourceKey() = default; 30 | UsdBridgeResourceKey(const UsdBridgeResourceKey& key) = default; 31 | UsdBridgeResourceKey(const char* n, double t) 32 | { 33 | name = n; 34 | #ifdef TIME_BASED_CACHING 35 | timeStep = t; 36 | #endif 37 | } 38 | 39 | const char* name; 40 | #ifdef TIME_BASED_CACHING 41 | double timeStep; 42 | #endif 43 | 44 | bool operator==(const UsdBridgeResourceKey& rhs) const 45 | { 46 | return ( name ? (rhs.name ? (strEquals(name, rhs.name) 47 | #ifdef TIME_BASED_CACHING 48 | && timeStep == rhs.timeStep 49 | #endif 50 | ) : false ) : !rhs.name); 51 | } 52 | }; 53 | 54 | struct UsdBridgeRefCache 55 | { 56 | public: 57 | friend class UsdBridgePrimCacheManager; 58 | 59 | protected: 60 | void IncRef() { ++RefCount; } 61 | void DecRef() { --RefCount; } 62 | 63 | unsigned int RefCount = 0; 64 | }; 65 | 66 | struct UsdBridgePrimCache : public UsdBridgeRefCache 67 | { 68 | public: 69 | friend class UsdBridgePrimCacheManager; 70 | using ResourceContainer = std::vector; 71 | 72 | //Constructors 73 | UsdBridgePrimCache(const SdfPath& pp, const SdfPath& nm, ResourceCollectFunc cf); 74 | 75 | UsdBridgePrimCache* GetChildCache(const TfToken& nameToken); 76 | 77 | bool AddResourceKey(UsdBridgeResourceKey key); 78 | 79 | SdfPath PrimPath; 80 | SdfPath Name; 81 | ResourceCollectFunc ResourceCollect; 82 | 83 | std::unique_ptr ResourceKeys; // Referenced resources 84 | 85 | #ifdef TIME_BASED_CACHING 86 | void SetChildVisibleAtTime(const UsdBridgePrimCache* childCache, double timeCode); 87 | bool SetChildInvisibleAtTime(const UsdBridgePrimCache* childCache, double timeCode); // Returns whether timeCode has been removed AND the visible timeset is empty. 88 | #endif 89 | 90 | #ifdef VALUE_CLIP_RETIMING 91 | static constexpr double PrimStageTimeCode = 0.0; // Prim stages are stored in ClipStages under specified time code 92 | const UsdStagePair& GetPrimStagePair() const; 93 | 94 | template 95 | bool TimeVarBitsUpdate(DataMemberType newTimeVarBits); 96 | 97 | UsdStagePair ManifestStage; // Holds the manifest 98 | std::unordered_map ClipStages; // Holds the stage(s) to the timevarying data 99 | 100 | uint32_t LastTimeVaryingBits = 0; // Used to detect changes in timevarying status of parameters 101 | #endif 102 | 103 | #ifndef NDEBUG 104 | std::string Debug_Name; 105 | #endif 106 | 107 | protected: 108 | void AddChild(UsdBridgePrimCache* child); 109 | void RemoveChild(UsdBridgePrimCache* child); 110 | void RemoveUnreferencedChildTree(AtRemoveFunc atRemove); 111 | 112 | std::vector Children; 113 | 114 | #ifdef TIME_BASED_CACHING 115 | // For each child, hold a vector of timesteps where it's visible (mimicks visibility attribute on the referencing prim) 116 | std::vector> ChildVisibleAtTimes; 117 | #endif 118 | }; 119 | 120 | class UsdBridgePrimCacheManager 121 | { 122 | public: 123 | typedef std::unordered_map> PrimCacheContainer; 124 | typedef PrimCacheContainer::iterator PrimCacheIterator; 125 | typedef PrimCacheContainer::const_iterator ConstPrimCacheIterator; 126 | 127 | inline UsdBridgePrimCache* ConvertToPrimCache(const UsdBridgeHandle& handle) const 128 | { 129 | #ifndef NDEBUG 130 | auto primCacheIt = FindPrimCache(handle); 131 | assert(ValidIterator(primCacheIt)); 132 | #endif 133 | return handle.value; 134 | } 135 | 136 | ConstPrimCacheIterator FindPrimCache(const std::string& name) const { return UsdPrimCaches.find(name); } 137 | ConstPrimCacheIterator FindPrimCache(const UsdBridgeHandle& handle) const; 138 | 139 | inline bool ValidIterator(ConstPrimCacheIterator it) const { return it != UsdPrimCaches.end(); } 140 | 141 | ConstPrimCacheIterator CreatePrimCache(const std::string& name, const std::string& fullPath, ResourceCollectFunc collectFunc = nullptr); 142 | void RemovePrimCache(ConstPrimCacheIterator it, UsdBridgeLogObject& LogObject); 143 | void RemoveUnreferencedPrimCaches(AtRemoveFunc atRemove); 144 | 145 | void AddChild(UsdBridgePrimCache* parent, UsdBridgePrimCache* child); 146 | void RemoveChild(UsdBridgePrimCache* parent, UsdBridgePrimCache* child); 147 | 148 | void AttachTopLevelPrim(UsdBridgePrimCache* primCache); 149 | void DetachTopLevelPrim(UsdBridgePrimCache* primCache); 150 | 151 | protected: 152 | 153 | PrimCacheContainer UsdPrimCaches; 154 | }; 155 | 156 | #ifdef VALUE_CLIP_RETIMING 157 | template 158 | bool UsdBridgePrimCache::TimeVarBitsUpdate(DataMemberType newTimeVarBits) 159 | { 160 | uint32_t newBits = static_cast(newTimeVarBits); 161 | bool hasChanged = (LastTimeVaryingBits != newBits); 162 | LastTimeVaryingBits = newBits; 163 | return hasChanged; 164 | } 165 | #endif 166 | 167 | #endif -------------------------------------------------------------------------------- /UsdBridge/UsdBridgeDiagnosticMgrDelegate.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2020 The Khronos Group 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | #include "UsdBridgeDiagnosticMgrDelegate.h" 6 | 7 | #ifdef USE_USDRT 8 | #include "carb/ClientUtils.h" 9 | #endif 10 | 11 | bool UsdBridgeDiagnosticMgrDelegate::OutputEnabled = false; 12 | 13 | UsdBridgeDiagnosticMgrDelegate::UsdBridgeDiagnosticMgrDelegate(void* logUserData, UsdBridgeLogCallback logCallback) 14 | : LogUserData(logUserData) 15 | , LogCallback(logCallback) 16 | {} 17 | 18 | void UsdBridgeDiagnosticMgrDelegate::IssueError(TfError const& err) 19 | { 20 | LogTfMessage(UsdBridgeLogLevel::ERR, err); 21 | } 22 | 23 | void UsdBridgeDiagnosticMgrDelegate::IssueFatalError(TfCallContext const& context, 24 | std::string const& msg) 25 | { 26 | std::string message = TfStringPrintf( 27 | "[USD Internal error]: %s in %s at line %zu of %s", 28 | msg.c_str(), context.GetFunction(), context.GetLine(), context.GetFile() 29 | ); 30 | LogMessage(UsdBridgeLogLevel::ERR, message); 31 | } 32 | 33 | void UsdBridgeDiagnosticMgrDelegate::IssueStatus(TfStatus const& status) 34 | { 35 | LogTfMessage(UsdBridgeLogLevel::STATUS, status); 36 | } 37 | 38 | void UsdBridgeDiagnosticMgrDelegate::IssueWarning(TfWarning const& warning) 39 | { 40 | LogTfMessage(UsdBridgeLogLevel::WARNING, warning); 41 | } 42 | 43 | void UsdBridgeDiagnosticMgrDelegate::LogTfMessage(UsdBridgeLogLevel level, TfDiagnosticBase const& diagBase) 44 | { 45 | std::string message = TfStringPrintf( 46 | "[USD Internal Message]: %s with error code %s in %s at line %zu of %s", 47 | diagBase.GetCommentary().c_str(), 48 | TfDiagnosticMgr::GetCodeName(diagBase.GetDiagnosticCode()).c_str(), 49 | diagBase.GetContext().GetFunction(), 50 | diagBase.GetContext().GetLine(), 51 | diagBase.GetContext().GetFile() 52 | ); 53 | 54 | LogMessage(level, message); 55 | } 56 | 57 | void UsdBridgeDiagnosticMgrDelegate::LogMessage(UsdBridgeLogLevel level, const std::string& message) 58 | { 59 | if(OutputEnabled) 60 | LogCallback(level, LogUserData, message.c_str()); 61 | } 62 | 63 | #ifdef USE_USDRT 64 | UsdBridgeCarbLogger::UsdBridgeCarbLogger() 65 | { 66 | this->handleMessage = CarbLogCallback; 67 | if(carb::Framework* framework = carb::getFramework()) 68 | { 69 | if(CarbLogIface = framework->acquireInterface()) 70 | { 71 | CarbLogIface->addLogger(this); 72 | CarbLogIface->setLogEnabled(true); 73 | CarbLogIface->setLevelThreshold(carb::logging::kLevelVerbose); 74 | } 75 | } 76 | } 77 | 78 | UsdBridgeCarbLogger::~UsdBridgeCarbLogger() 79 | { 80 | if(CarbLogIface) 81 | { 82 | CarbLogIface->removeLogger(this); 83 | CarbLogIface = nullptr; 84 | } 85 | } 86 | 87 | void UsdBridgeCarbLogger::CarbLogCallback(carb::logging::Logger* logger, 88 | const char* source, 89 | int32_t level, 90 | const char* filename, 91 | const char* functionName, 92 | int lineNumber, 93 | const char* message) 94 | { 95 | } 96 | 97 | void UsdBridgeCarbLogger::SetCarbLogVerbosity(int logVerbosity) 98 | { 99 | carb::Framework* framework = carb::getFramework(); 100 | carb::logging::ILogging* logIface = framework ? framework->tryAcquireInterface() : nullptr; 101 | if(logIface) 102 | { 103 | logIface->setLevelThreshold( 104 | std::max(carb::logging::kLevelVerbose, carb::logging::kLevelFatal - logVerbosity) ); 105 | } 106 | } 107 | 108 | #endif -------------------------------------------------------------------------------- /UsdBridge/UsdBridgeDiagnosticMgrDelegate.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef UsdBridgeDiagnosticMgrDelegate_h 5 | #define UsdBridgeDiagnosticMgrDelegate_h 6 | 7 | #include "UsdBridgeData.h" 8 | 9 | #ifdef USE_USDRT 10 | #include "carb/logging/ILogging.h" 11 | #include "carb/logging/Logger.h" 12 | #endif 13 | 14 | #include "usd.h" 15 | PXR_NAMESPACE_USING_DIRECTIVE 16 | 17 | class UsdBridgeDiagnosticMgrDelegate : public TfDiagnosticMgr::Delegate 18 | { 19 | public: 20 | UsdBridgeDiagnosticMgrDelegate(void* logUserData, 21 | UsdBridgeLogCallback logCallback); 22 | 23 | void IssueError(TfError const& err) override; 24 | 25 | void IssueFatalError(TfCallContext const& context, 26 | std::string const& msg) override; 27 | 28 | void IssueStatus(TfStatus const& status) override; 29 | 30 | void IssueWarning(TfWarning const& warning) override; 31 | 32 | static void SetOutputEnabled(bool enable){ OutputEnabled = enable; } 33 | 34 | protected: 35 | 36 | void LogTfMessage(UsdBridgeLogLevel level, TfDiagnosticBase const& diagBase); 37 | 38 | void LogMessage(UsdBridgeLogLevel level, const std::string& message); 39 | 40 | void* LogUserData; 41 | UsdBridgeLogCallback LogCallback; 42 | static bool OutputEnabled; 43 | }; 44 | 45 | #ifdef USE_USDRT 46 | struct UsdBridgeCarbLogger : public carb::logging::Logger 47 | { 48 | UsdBridgeCarbLogger(); 49 | 50 | ~UsdBridgeCarbLogger(); 51 | 52 | static void CarbLogCallback(carb::logging::Logger* logger, 53 | const char* source, 54 | int32_t level, 55 | const char* filename, 56 | const char* functionName, 57 | int lineNumber, 58 | const char* message); 59 | 60 | static void SetCarbLogVerbosity(int logVerbosity); 61 | 62 | carb::logging::ILogging* CarbLogIface = nullptr; 63 | }; 64 | #endif 65 | 66 | #endif -------------------------------------------------------------------------------- /UsdBridge/UsdBridgeRt.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef UsdBridgeRt_h 5 | #define UsdBridgeRt_h 6 | 7 | #include "UsdBridgeData.h" 8 | 9 | class UsdBridgeRtInternals; 10 | 11 | class UsdBridgeRt 12 | { 13 | public: 14 | UsdBridgeRt(const ::PXR_NS::UsdStagePtr& sceneStage, const ::PXR_NS::SdfPath& primPath); 15 | ~UsdBridgeRt(); 16 | 17 | void ReCalc(); 18 | bool ValidPrim(); 19 | 20 | // Update attrib (directly or via its UsdRt/Fabric equivalents) with contents of arrayData and optionally return a span. 21 | // If arrayData is a nullptr, the attribute backing memory will be allocated, but not written to (for which the user can employ the returned span). 22 | template 23 | UsdBridgeSpanI* UpdateUsdAttribute(const UsdBridgeLogObject& logObj, const void* arrayData, UsdBridgeType arrayDataType, size_t arrayNumElements, 24 | const ::PXR_NS::UsdAttribute& attrib, const ::PXR_NS::UsdTimeCode& timeCode, bool writeToAttrib); 25 | 26 | protected: 27 | 28 | UsdBridgeRtInternals* Internals = nullptr; 29 | }; 30 | 31 | #endif -------------------------------------------------------------------------------- /UsdBridge/UsdBridgeTimeEvaluator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdBridgeTimeEvaluator.h" 5 | #include "usd.h" 6 | PXR_NAMESPACE_USING_DIRECTIVE 7 | 8 | const UsdTimeCode UsdBridgeTimeEvaluator::DefaultTime = UsdTimeCode::Default(); -------------------------------------------------------------------------------- /UsdBridge/UsdBridgeTimeEvaluator.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef UsdBridgeTimeEvaluator_h 5 | #define UsdBridgeTimeEvaluator_h 6 | 7 | #include "usd.h" 8 | PXR_NAMESPACE_USING_DIRECTIVE 9 | 10 | template 11 | class UsdBridgeTimeEvaluator 12 | { 13 | public: 14 | UsdBridgeTimeEvaluator(const T& data, double timeStep) 15 | : Data(data) 16 | , TimeCode(timeStep) 17 | { 18 | } 19 | 20 | UsdBridgeTimeEvaluator(const T& data) 21 | : Data(data) 22 | { 23 | } 24 | 25 | const UsdTimeCode& Eval(typename T::DataMemberId member) const 26 | { 27 | #ifdef TIME_BASED_CACHING 28 | if ((Data.TimeVarying & member) != T::DataMemberId::NONE) 29 | return TimeCode; 30 | else 31 | #endif 32 | return DefaultTime; 33 | } 34 | 35 | bool IsTimeVarying(typename T::DataMemberId member) const 36 | { 37 | #ifdef TIME_BASED_CACHING 38 | return ((Data.TimeVarying & member) != T::DataMemberId::NONE); 39 | #else 40 | return false; 41 | #endif 42 | } 43 | 44 | UsdTimeCode Default() const { return DefaultTime; } 45 | 46 | const T& Data; 47 | const UsdTimeCode TimeCode; 48 | static const UsdTimeCode DefaultTime; 49 | }; 50 | 51 | template 52 | const UsdTimeCode UsdBridgeTimeEvaluator::DefaultTime = UsdTimeCode::Default(); 53 | 54 | template<> 55 | class UsdBridgeTimeEvaluator 56 | { 57 | public: 58 | UsdBridgeTimeEvaluator(bool timeVarying, double timeStep) 59 | : TimeVarying(timeVarying) 60 | , TimeCode(timeStep) 61 | { 62 | } 63 | 64 | const UsdTimeCode& Eval() const 65 | { 66 | #ifdef TIME_BASED_CACHING 67 | if (TimeVarying) 68 | return TimeCode; 69 | else 70 | #endif 71 | return DefaultTime; 72 | } 73 | 74 | UsdTimeCode Default() const { return DefaultTime; } 75 | 76 | const bool TimeVarying; 77 | const UsdTimeCode TimeCode; 78 | static const UsdTimeCode DefaultTime; 79 | }; 80 | 81 | #endif -------------------------------------------------------------------------------- /UsdBridge/UsdBridgeUsdWriter_Volume.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdBridgeUsdWriter.h" 5 | 6 | #include "UsdBridgeUsdWriter_Common.h" 7 | #include "UsdBridgeUsdWriter_Arrays.h" 8 | 9 | namespace 10 | { 11 | void InitializeUsdVolumeTimeVar(UsdVolVolume& volume, const TimeEvaluator* timeEval = nullptr) 12 | { 13 | typedef UsdBridgeVolumeData::DataMemberId DMI; 14 | 15 | } 16 | 17 | void InitializeUsdVolumeAssetTimeVar(UsdVolOpenVDBAsset& volAsset, const TimeEvaluator* timeEval = nullptr) 18 | { 19 | typedef UsdBridgeVolumeData::DataMemberId DMI; 20 | 21 | UsdVolOpenVDBAsset& attribCreatePrim = volAsset; 22 | UsdPrim attribRemovePrim = volAsset.GetPrim(); 23 | 24 | CREATE_REMOVE_TIMEVARYING_ATTRIB_QUALIFIED(DMI::DATA, CreateFilePathAttr, UsdBridgeTokens->filePath); 25 | } 26 | 27 | UsdPrim InitializeUsdVolume_Impl(UsdStageRefPtr volumeStage, const SdfPath & volumePath, bool uniformPrim, 28 | TimeEvaluator* timeEval = nullptr) 29 | { 30 | UsdVolVolume volume = GetOrDefinePrim(volumeStage, volumePath); 31 | 32 | SdfPath ovdbFieldPath = volumePath.AppendPath(SdfPath(constring::openVDBPrimPf)); 33 | UsdVolOpenVDBAsset volAsset = GetOrDefinePrim(volumeStage, ovdbFieldPath); 34 | 35 | if (uniformPrim) 36 | { 37 | volume.CreateFieldRelationship(UsdBridgeTokens->density, ovdbFieldPath); 38 | volAsset.CreateFieldNameAttr(VtValue(UsdBridgeTokens->density)); 39 | } 40 | 41 | InitializeUsdVolumeTimeVar(volume, timeEval); 42 | InitializeUsdVolumeAssetTimeVar(volAsset, timeEval); 43 | 44 | return volume.GetPrim(); 45 | } 46 | 47 | void UpdateUsdVolumeAttributes(UsdVolVolume& uniformVolume, UsdVolVolume& timeVarVolume, UsdVolOpenVDBAsset& uniformField, UsdVolOpenVDBAsset& timeVarField, 48 | const UsdBridgeVolumeData& volumeData, double timeStep, const std::string& relVolPath) 49 | { 50 | TimeEvaluator timeEval(volumeData, timeStep); 51 | typedef UsdBridgeVolumeData::DataMemberId DMI; 52 | 53 | SdfAssetPath volAsset(relVolPath); 54 | 55 | // Set extents in usd 56 | float minX = volumeData.Origin[0]; 57 | float minY = volumeData.Origin[1]; 58 | float minZ = volumeData.Origin[2]; 59 | float maxX = ((float)volumeData.NumElements[0] * volumeData.CellDimensions[0]) + minX; 60 | float maxY = ((float)volumeData.NumElements[1] * volumeData.CellDimensions[1]) + minY; 61 | float maxZ = ((float)volumeData.NumElements[2] * volumeData.CellDimensions[2]) + minZ; 62 | 63 | VtVec3fArray extentArray(2); 64 | extentArray[0].Set(minX, minY, minZ); 65 | extentArray[1].Set(maxX, maxY, maxZ); 66 | 67 | UsdAttribute uniformFileAttr = uniformField.GetFilePathAttr(); 68 | UsdAttribute timeVarFileAttr = timeVarField.GetFilePathAttr(); 69 | UsdAttribute uniformExtentAttr = uniformVolume.GetExtentAttr(); 70 | UsdAttribute timeVarExtentAttr = timeVarVolume.GetExtentAttr(); 71 | 72 | bool dataTimeVarying = timeEval.IsTimeVarying(DMI::DATA); 73 | 74 | // Clear timevarying attributes if necessary 75 | ClearUsdAttributes(uniformFileAttr, timeVarFileAttr, dataTimeVarying); 76 | ClearUsdAttributes(uniformExtentAttr, timeVarExtentAttr, dataTimeVarying); 77 | 78 | // Set the attributes 79 | SET_TIMEVARYING_ATTRIB(dataTimeVarying, timeVarFileAttr, uniformFileAttr, volAsset); 80 | SET_TIMEVARYING_ATTRIB(dataTimeVarying, timeVarExtentAttr, uniformExtentAttr, extentArray); 81 | } 82 | } 83 | 84 | UsdPrim UsdBridgeUsdWriter::InitializeUsdVolume(UsdStageRefPtr volumeStage, const SdfPath & volumePath, bool uniformPrim) const 85 | { 86 | UsdPrim volumePrim = InitializeUsdVolume_Impl(volumeStage, volumePath, uniformPrim); 87 | 88 | #ifdef USE_INDEX_MATERIALS 89 | UsdShadeMaterial matPrim = InitializeIndexVolumeMaterial_Impl(volumeStage, volumePath, uniformPrim); 90 | UsdShadeMaterialBindingAPI(volumePrim).Bind(matPrim); 91 | #endif 92 | 93 | return volumePrim; 94 | } 95 | 96 | #ifdef VALUE_CLIP_RETIMING 97 | void UsdBridgeUsdWriter::UpdateUsdVolumeManifest(const UsdBridgePrimCache* cacheEntry, const UsdBridgeVolumeData& volumeData) 98 | { 99 | const SdfPath & volumePath = cacheEntry->PrimPath; 100 | 101 | UsdStageRefPtr volumeStage = cacheEntry->ManifestStage.second; 102 | TimeEvaluator timeEval(volumeData); 103 | 104 | InitializeUsdVolume_Impl(volumeStage, volumePath, 105 | false, &timeEval); 106 | 107 | #ifdef USE_INDEX_MATERIALS 108 | InitializeIndexVolumeMaterial_Impl(volumeStage, volumePath, false, &timeEval); 109 | #endif 110 | 111 | if(this->EnableSaving) 112 | cacheEntry->ManifestStage.second->Save(); 113 | } 114 | #endif 115 | 116 | void UsdBridgeUsdWriter::UpdateUsdVolume(UsdStageRefPtr timeVarStage, UsdBridgePrimCache* cacheEntry, const UsdBridgeVolumeData& volumeData, double timeStep) 117 | { 118 | const SdfPath& volPrimPath = cacheEntry->PrimPath; 119 | 120 | // Get the volume and ovdb field prims 121 | UsdVolVolume uniformVolume = UsdVolVolume::Get(SceneStage, volPrimPath); 122 | assert(uniformVolume); 123 | UsdVolVolume timeVarVolume = UsdVolVolume::Get(timeVarStage, volPrimPath); 124 | assert(timeVarVolume); 125 | 126 | SdfPath ovdbFieldPath = volPrimPath.AppendPath(SdfPath(constring::openVDBPrimPf)); 127 | 128 | UsdVolOpenVDBAsset uniformField = UsdVolOpenVDBAsset::Get(SceneStage, ovdbFieldPath); 129 | assert(uniformField); 130 | UsdVolOpenVDBAsset timeVarField = UsdVolOpenVDBAsset::Get(timeVarStage, ovdbFieldPath); 131 | assert(timeVarField); 132 | 133 | // Set the file path reference in usd 134 | const std::string& relVolPath = GetResourceFileName(constring::volFolder, cacheEntry->Name.GetString(), timeStep, constring::vdbExtension); 135 | 136 | UpdateUsdVolumeAttributes(uniformVolume, timeVarVolume, uniformField, timeVarField, volumeData, timeStep, relVolPath); 137 | 138 | #ifdef USE_INDEX_MATERIALS 139 | UpdateIndexVolumeMaterial(SceneStage, timeVarStage, volPrimPath, volumeData, timeStep); 140 | #endif 141 | 142 | // Output stream path (relative from connection working dir) 143 | std::string wdRelVolPath(SessionDirectory + relVolPath); 144 | 145 | // Write VDB data to stream 146 | VolumeWriter->ToVDB(volumeData); 147 | 148 | // Flush stream out to storage 149 | const char* volumeStreamData; size_t volumeStreamDataSize; 150 | VolumeWriter->GetSerializedVolumeData(volumeStreamData, volumeStreamDataSize); 151 | Connect->WriteFile(volumeStreamData, volumeStreamDataSize, wdRelVolPath.c_str(), true); 152 | // Record file write for timestep 153 | cacheEntry->AddResourceKey(UsdBridgeResourceKey(nullptr, timeStep)); 154 | } 155 | 156 | void ResourceCollectVolume(UsdBridgePrimCache* cache, UsdBridgeUsdWriter& usdWriter) 157 | { 158 | RemoveResourceFiles(cache, usdWriter, constring::volFolder, constring::vdbExtension); 159 | } -------------------------------------------------------------------------------- /UsdBridge/Volume/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | message( "-------------------- Begin UsdBridgeVolume CmakeLists.txt ----------------------------------------") 2 | 3 | # Boost's iostreams cmake config file tacks on generic z and lzma dep names 4 | macro(fix_boost_dependency) 5 | if(NOT WIN32 AND BOOST_USE_STATIC_LIBS) 6 | find_package(Boost REQUIRED COMPONENTS iostreams) 7 | get_property(Boost_linkiface 8 | TARGET Boost::iostreams 9 | PROPERTY INTERFACE_LINK_LIBRARIES) 10 | 11 | foreach(libname ${Boost_linkiface}) 12 | if(CMAKE_CONFIGURATION_TYPES) 13 | if(NOT (${libname} MATCHES "$<$:lzma;z>")) 14 | list(APPEND Boost_linkiface_new ${libname}) 15 | else() 16 | message(STATUS "Removed boost dependency: ${libname}") 17 | endif() 18 | else() 19 | if((NOT (${libname} MATCHES "lzma")) AND 20 | (NOT (${libname} MATCHES "z"))) 21 | list(APPEND Boost_linkiface_new ${libname}) 22 | else() 23 | message(STATUS "Removed boost dependency: ${libname}") 24 | endif() 25 | endif() 26 | endforeach(libname) 27 | 28 | message(STATUS "CHANGED Boost iostreams link interface to: ${Boost_linkiface_new}") 29 | set_property(TARGET Boost::iostreams 30 | PROPERTY INTERFACE_LINK_LIBRARIES ${Boost_linkiface_new}) 31 | endif() 32 | endmacro() 33 | 34 | project(UsdBridge_Volume) 35 | add_library(${PROJECT_NAME} SHARED) 36 | 37 | if(NOT CMAKE_BUILD_TYPE) # Otherwise IlmBase::Half does not find debug/release libraries 38 | message(FATAL_ERROR "A CMAKE_BUILD_TYPE has to be chosen for correct dependency resolution of UsdBridge_Volume") 39 | endif() 40 | 41 | option(USD_DEVICE_USE_OPENVDB "Enable OpenVDB support for USD device" OFF) 42 | 43 | target_sources(${PROJECT_NAME} 44 | PRIVATE 45 | ${CMAKE_CURRENT_LIST_DIR}/UsdBridgeVolumeWriter.cpp 46 | ${CMAKE_CURRENT_LIST_DIR}/UsdBridgeVolumeWriter.h 47 | ) 48 | 49 | target_include_directories(${PROJECT_NAME} 50 | PUBLIC 51 | ${CMAKE_CURRENT_LIST_DIR} 52 | ) 53 | 54 | target_link_libraries(${PROJECT_NAME} 55 | PRIVATE 56 | UsdBridge_Common 57 | ) 58 | 59 | if (USD_DEVICE_USE_OPENVDB) 60 | 61 | file(GLOB USD_OPENVDB_BUILD "${USD_ROOT_DIR_RELEASE}/include/openvdb") 62 | option(USE_USD_OPENVDB_BUILD "If USD source installation exists, use OpenVDB from there" ON) 63 | 64 | # Find path with Find*.cmake files that find_package() will use for deps 65 | 66 | unset(OPENVDB_MODULE_DIR CACHE) 67 | find_path(OPENVDB_MODULE_DIR 68 | PATHS 69 | ${OpenVDB_ROOT} 70 | NAMES 71 | FindOpenVDB.cmake 72 | PATH_SUFFIXES 73 | OpenVDB 74 | cmake/OpenVDB 75 | lib/cmake/OpenVDB 76 | ) 77 | list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake" ${OPENVDB_MODULE_DIR}) 78 | 79 | # Set dep package roots (or manual lib dirs) and find variables 80 | 81 | # No consensus on upper/lower case 82 | 83 | if(Boost_USE_STATIC_LIBS OR BOOST_USE_STATIC_LIBS) 84 | set(BOOST_USE_STATIC_LIBS ON) 85 | set(Boost_USE_STATIC_LIBS ON) 86 | set(BUILD_SHARED_LIBS OFF) 87 | else() 88 | set(BOOST_USE_STATIC_LIBS OFF) 89 | set(Boost_USE_STATIC_LIBS OFF) 90 | set(BUILD_SHARED_LIBS ON) 91 | endif() 92 | if(USDBRIDGE_VOLUME_STATIC_CRT) 93 | set(Boost_USE_STATIC_RUNTIME ON) 94 | else() 95 | set(Boost_USE_STATIC_RUNTIME OFF) 96 | endif() 97 | if (WIN32) 98 | set(Boost_COMPILER "vc141") 99 | endif() 100 | 101 | if(USE_USD_OPENVDB_BUILD) # Allow for using the usd install as dependency root 102 | if(NOT ZLIB_ROOT) 103 | set(ZLIB_ROOT "${OpenVDB_ROOT}") 104 | endif() 105 | if(NOT TBB_ROOT) 106 | set(TBB_ROOT "${OpenVDB_ROOT}") 107 | endif() 108 | if(NOT BOOST_ROOT) 109 | set(BOOST_ROOT "${OpenVDB_ROOT}") 110 | endif() 111 | if(NOT Blosc_ROOT) 112 | set(Blosc_ROOT "${OpenVDB_ROOT}") 113 | endif() 114 | endif() 115 | 116 | message(STATUS "OpenVDB OpenVDB_ROOT: ${OpenVDB_ROOT}") 117 | message(STATUS "OpenVDB IlmBase_ROOT: ${IlmBase_ROOT}") 118 | message(STATUS "OpenVDB ZLIB_ROOT: ${ZLIB_ROOT}") 119 | message(STATUS "OpenVDB Blosc_ROOT: ${Blosc_ROOT}") 120 | message(STATUS "OpenVDB TBB_ROOT: ${TBB_ROOT}") 121 | message(STATUS "OpenVDB BOOST_ROOT: ${BOOST_ROOT}") 122 | 123 | fix_boost_dependency() 124 | 125 | find_package(OpenVDB REQUIRED) 126 | 127 | # Pop two paths to remove current dir and OPENVDB_MODULE_DIR 128 | list(POP_FRONT CMAKE_MODULE_PATH) 129 | list(POP_FRONT CMAKE_MODULE_PATH) 130 | 131 | # Add include dirs and link libs 132 | 133 | target_link_libraries(${PROJECT_NAME} 134 | PRIVATE 135 | OpenVDB::openvdb 136 | ) 137 | target_compile_definitions(${PROJECT_NAME} 138 | PRIVATE 139 | USE_OPENVDB 140 | ${USD_DEVICE_TIME_DEFS} 141 | ) 142 | 143 | if(WIN32) 144 | # Due to explicit pragma lib inclusion in tbb and python 145 | target_link_directories(${PROJECT_NAME} 146 | PRIVATE ${Tbb_LIBRARY_DIRS}) 147 | 148 | # Windows-specific OpenVDB settings 149 | option(USDBRIDGE_VOLUME_STATIC_CRT "Enable static CRT on Volume part of UsdBridge" OFF) 150 | if(USDBRIDGE_VOLUME_STATIC_CRT) 151 | set_property(TARGET ${PROJECT_NAME} 152 | PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") 153 | endif() 154 | set_source_files_properties(${CMAKE_CURRENT_LIST_DIR}/UsdBridgeVolumeWriter.cpp PROPERTIES COMPILE_FLAGS /bigobj) 155 | else() 156 | if(NOT ${USD_DEVICE_USE_CXX11_ABI}) 157 | target_compile_definitions(${PROJECT_NAME} PRIVATE 158 | _GLIBCXX_USE_CXX11_ABI=0 ) 159 | endif() 160 | endif() 161 | 162 | endif() 163 | 164 | install(TARGETS ${PROJECT_NAME} 165 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 166 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 167 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 168 | ) 169 | 170 | ## Install optional pdbs 171 | ## install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) 172 | 173 | # No dependency install required; all dynamic dependencies should be shared with USD and therefore installed in the parent-level cmake, 174 | # and if not, make sure they are static to avoid problems with versioning. 175 | 176 | message( "-------------------- End UsdBridgeVolume CmakeLists.txt ----------------------------------------") 177 | -------------------------------------------------------------------------------- /UsdBridge/Volume/UsdBridgeVolumeWriter.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef UsdBridgeVolumeWriter_h 5 | #define UsdBridgeVolumeWriter_h 6 | 7 | #include "UsdBridgeData.h" 8 | 9 | #ifdef _WIN32 10 | #define USDDevice_DECL __cdecl 11 | #ifdef UsdBridge_Volume_EXPORTS 12 | #define USDDevice_INTERFACE __declspec(dllexport) 13 | #else 14 | #define USDDevice_INTERFACE __declspec(dllimport) 15 | #endif 16 | #else 17 | #define USDDevice_DECL 18 | #define USDDevice_INTERFACE 19 | #endif 20 | 21 | class UsdBridgeVolumeWriterI 22 | { 23 | public: 24 | 25 | virtual bool Initialize(const UsdBridgeLogObject& logObj) = 0; 26 | 27 | virtual void ToVDB(const UsdBridgeVolumeData& volumeData) = 0; 28 | 29 | virtual void GetSerializedVolumeData(const char*& data, size_t& size) = 0; 30 | 31 | virtual void SetConvertDoubleToFloat(bool convert) = 0; 32 | 33 | virtual void Release() = 0; // Accommodate change of CRT 34 | }; 35 | 36 | extern "C" USDDevice_INTERFACE UsdBridgeVolumeWriterI* USDDevice_DECL Create_VolumeWriter(); 37 | 38 | #endif -------------------------------------------------------------------------------- /UsdBridge/Volume/cmake/OpenVDBUtils.cmake: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the OpenVDB Project 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | #[=======================================================================[.rst: 5 | 6 | OpenVDBUtils.cmake 7 | ------------------ 8 | 9 | A utility CMake file which provides helper functions for configuring an 10 | OpenVDB installation. 11 | 12 | Use this module by invoking include with the form:: 13 | 14 | include ( OpenVDBUtils ) 15 | 16 | 17 | The following functions are provided: 18 | 19 | ``OPENVDB_GET_VERSION_DEFINE`` 20 | 21 | OPENVDB_GET_VERSION_DEFINE ( ) 22 | 23 | Parse the provided version file to retrieve the a given OpenVDB define 24 | specified by and store the result in . If the define has a 25 | value, the value is stored. If the define has no value but exists, ON is 26 | stored. Else, OFF is stored. 27 | 28 | If the file does not exist, is unmodified. 29 | 30 | ``OPENVDB_VERSION_FROM_HEADER`` 31 | 32 | OPENVDB_VERSION_FROM_HEADER ( 33 | VERSION [] 34 | MAJOR [] 35 | MINOR [] 36 | PATCH [] ) 37 | 38 | Parse the provided version file to retrieve the current OpenVDB 39 | version information. The file is expected to be a version.h file 40 | as found in the following path of an OpenVDB repository: 41 | openvdb/version.h 42 | 43 | If the file does not exist, variables are unmodified. 44 | 45 | ``OPENVDB_ABI_VERSION_FROM_PRINT`` 46 | 47 | OPENVDB_ABI_VERSION_FROM_PRINT ( 48 | [QUIET] 49 | ABI [] ) 50 | 51 | Retrieve the ABI version that an installation of OpenVDB was compiled 52 | for using the provided vdb_print binary. Parses the result of: 53 | vdb_print --version 54 | 55 | If the binary does not exist or fails to launch, variables are 56 | unmodified. 57 | 58 | #]=======================================================================] 59 | 60 | cmake_minimum_required(VERSION 3.18) 61 | 62 | 63 | function(OPENVDB_GET_VERSION_DEFINE HEADER KEY VALUE) 64 | if(NOT EXISTS ${HEADER}) 65 | return() 66 | endif() 67 | 68 | file(STRINGS "${HEADER}" details REGEX "^#define[\t ]+${KEY}[\t ]+.*") 69 | if(details) 70 | # define has a value, extract it and return 71 | string(REGEX REPLACE "^.*${KEY}[\t ]+([0-9]*).*$" "\\1" details "${details}") 72 | set(${VALUE} ${details} PARENT_SCOPE) 73 | return() 74 | endif() 75 | 76 | # try re-searching for single defines 77 | file(STRINGS "${HEADER}" details REGEX "^#define[\t ]+${KEY}.*") 78 | if(details) 79 | set(${VALUE} ON PARENT_SCOPE) 80 | else() 81 | set(${VALUE} OFF PARENT_SCOPE) 82 | endif() 83 | endfunction() 84 | 85 | 86 | ######################################################################## 87 | ######################################################################## 88 | 89 | 90 | function(OPENVDB_VERSION_FROM_HEADER OPENVDB_VERSION_FILE) 91 | cmake_parse_arguments(_VDB "" "VERSION;MAJOR;MINOR;PATCH;ABI" "" ${ARGN}) 92 | 93 | if(NOT EXISTS ${OPENVDB_VERSION_FILE}) 94 | return() 95 | endif() 96 | 97 | OPENVDB_GET_VERSION_DEFINE(${OPENVDB_VERSION_FILE} "OPENVDB_LIBRARY_MAJOR_VERSION_NUMBER" _OpenVDB_MAJOR_VERSION) 98 | OPENVDB_GET_VERSION_DEFINE(${OPENVDB_VERSION_FILE} "OPENVDB_LIBRARY_MINOR_VERSION_NUMBER" _OpenVDB_MINOR_VERSION) 99 | OPENVDB_GET_VERSION_DEFINE(${OPENVDB_VERSION_FILE} "OPENVDB_LIBRARY_PATCH_VERSION_NUMBER" _OpenVDB_PATCH_VERSION) 100 | OPENVDB_GET_VERSION_DEFINE(${OPENVDB_VERSION_FILE} "OPENVDB_ABI_VERSION_NUMBER" _OpenVDB_ABI_VERSION) 101 | 102 | if(_VDB_VERSION) 103 | set(${_VDB_VERSION} 104 | ${_OpenVDB_MAJOR_VERSION}.${_OpenVDB_MINOR_VERSION}.${_OpenVDB_PATCH_VERSION} 105 | PARENT_SCOPE 106 | ) 107 | endif() 108 | if(_VDB_MAJOR) 109 | set(${_VDB_MAJOR} ${_OpenVDB_MAJOR_VERSION} PARENT_SCOPE) 110 | endif() 111 | if(_VDB_MINOR) 112 | set(${_VDB_MINOR} ${_OpenVDB_MINOR_VERSION} PARENT_SCOPE) 113 | endif() 114 | if(_VDB_PATCH) 115 | set(${_VDB_PATCH} ${_OpenVDB_PATCH_VERSION} PARENT_SCOPE) 116 | endif() 117 | if(_VDB_ABI) 118 | set(${_VDB_ABI} ${_OpenVDB_ABI_VERSION} PARENT_SCOPE) 119 | endif() 120 | endfunction() 121 | 122 | 123 | ######################################################################## 124 | ######################################################################## 125 | 126 | 127 | function(OPENVDB_ABI_VERSION_FROM_PRINT OPENVDB_PRINT) 128 | cmake_parse_arguments(_VDB "QUIET" "ABI" "" ${ARGN}) 129 | 130 | if(NOT EXISTS ${OPENVDB_PRINT}) 131 | return() 132 | endif() 133 | 134 | set(_VDB_PRINT_VERSION_STRING "") 135 | set(_VDB_PRINT_RETURN_STATUS "") 136 | 137 | if(${_VDB_QUIET}) 138 | execute_process(COMMAND ${OPENVDB_PRINT} "--version" 139 | RESULT_VARIABLE _VDB_PRINT_RETURN_STATUS 140 | OUTPUT_VARIABLE _VDB_PRINT_VERSION_STRING 141 | ERROR_QUIET 142 | OUTPUT_STRIP_TRAILING_WHITESPACE 143 | ) 144 | else() 145 | execute_process(COMMAND ${OPENVDB_PRINT} "--version" 146 | RESULT_VARIABLE _VDB_PRINT_RETURN_STATUS 147 | OUTPUT_VARIABLE _VDB_PRINT_VERSION_STRING 148 | OUTPUT_STRIP_TRAILING_WHITESPACE 149 | ) 150 | endif() 151 | 152 | if(${_VDB_PRINT_RETURN_STATUS}) 153 | return() 154 | endif() 155 | 156 | set(_OpenVDB_ABI) 157 | string(REGEX REPLACE ".*abi([0-9]*).*" "\\1" _OpenVDB_ABI ${_VDB_PRINT_VERSION_STRING}) 158 | unset(_VDB_PRINT_RETURN_STATUS) 159 | unset(_VDB_PRINT_VERSION_STRING) 160 | 161 | if(_VDB_ABI) 162 | set(${_VDB_ABI} ${_OpenVDB_ABI} PARENT_SCOPE) 163 | endif() 164 | endfunction() -------------------------------------------------------------------------------- /UsdBridge/usd.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #pragma warning(push) 7 | #pragma warning(disable:4244) // = Conversion from double to float / int to float 8 | #pragma warning(disable:4305) // argument truncation from double to float 9 | #pragma warning(disable:4800) // int to bool 10 | #pragma warning(disable:4996) // call to std::copy with parameters that may be unsafe 11 | #define NOMINMAX // Make sure nobody #defines min or max 12 | // Python must be included first because it monkeys with macros that cause 13 | // TBB to fail to compile in debug mode if TBB is included before Python 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #pragma warning(pop) 52 | -------------------------------------------------------------------------------- /UsdBridge/usdhelpers.cmake: -------------------------------------------------------------------------------- 1 | macro(cleanup_include_interface) 2 | get_property(include_dirs 3 | TARGET ${cur_target} 4 | PROPERTY INTERFACE_INCLUDE_DIRECTORIES) 5 | 6 | set(new_include_dirs "") 7 | foreach(incdir ${include_dirs}) 8 | if(NOT (${incdir} MATCHES "[pP]ython")) 9 | list(APPEND new_include_dirs ${incdir}) 10 | endif() 11 | endforeach() 12 | 13 | set_property(TARGET ${cur_target} 14 | PROPERTY INTERFACE_INCLUDE_DIRECTORIES 15 | ${new_include_dirs}) 16 | endmacro() 17 | 18 | macro(cleanup_link_interface) 19 | get_property(new_targets 20 | TARGET ${cur_target} 21 | PROPERTY INTERFACE_LINK_LIBRARIES) 22 | # Clear the target's transitive dependencies, otherwise those will still be taken into account by target_link_libraries 23 | set_property(TARGET ${cur_target} 24 | PROPERTY INTERFACE_LINK_LIBRARIES 25 | "") 26 | endmacro() 27 | 28 | function(flatten_and_cleanup_targets RESULT_TARGETS INIT_TARGETS) 29 | if(WIN32) 30 | set(MATCH_SUFFIX "\.lib") 31 | else() 32 | set(MATCH_SUFFIX "\.so") 33 | endif() 34 | set(candidate_targets ${INIT_TARGETS}) 35 | set(flat_targets "") 36 | list(LENGTH candidate_targets num_candidates) 37 | while(${num_candidates} GREATER 0) 38 | list(POP_FRONT candidate_targets cur_target) 39 | list(FIND flat_targets ${cur_target} target_processed) 40 | 41 | if((target_processed EQUAL -1) 42 | AND NOT (${cur_target} MATCHES ${MATCH_SUFFIX}) 43 | AND NOT (${cur_target} STREQUAL "dl") 44 | AND NOT (${cur_target} STREQUAL "m") 45 | ) 46 | list(APPEND flat_targets ${cur_target}) 47 | 48 | cleanup_include_interface() 49 | cleanup_link_interface() 50 | 51 | list(APPEND candidate_targets ${new_targets}) 52 | endif() 53 | 54 | list(LENGTH candidate_targets num_candidates) 55 | endwhile() 56 | 57 | set(${RESULT_TARGETS} ${flat_targets} PARENT_SCOPE) 58 | endfunction() 59 | 60 | # Define the function 61 | function(check_file_and_substring FILE_PATH SUBSTRING OUTPUT_VAR) 62 | set(${OUTPUT_VAR} OFF PARENT_SCOPE) 63 | 64 | # Check if the file exists and contains a substring 65 | if(EXISTS "${FILE_PATH}") 66 | file(READ "${FILE_PATH}" FILE_CONTENTS) 67 | string(FIND "${FILE_CONTENTS}" "${SUBSTRING}" SUBSTRING_POSITION) 68 | 69 | if(NOT ${SUBSTRING_POSITION} EQUAL -1) 70 | set(${OUTPUT_VAR} ON PARENT_SCOPE) 71 | endif() 72 | endif() 73 | endfunction() -------------------------------------------------------------------------------- /UsdBridgedBaseObject.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBaseObject.h" 7 | #include "UsdBridge/UsdBridge.h" 8 | #include "UsdDevice.h" 9 | #include "UsdDataArray.h" 10 | 11 | #include 12 | #include 13 | 14 | enum class UsdEmptyComponents 15 | { 16 | }; 17 | 18 | template 19 | class UsdBridgedBaseObject : public UsdParameterizedBaseObject 20 | { 21 | protected: 22 | using CType = C; 23 | 24 | // Timevarying helper functions (classes workaround to allow for partial specialization) 25 | template 26 | class TimeVaryingClass 27 | { 28 | public: 29 | bool findTimeVarying(const char* name, IC& component) 30 | { 31 | for(auto& cmpName : IT::componentParamNames) 32 | { 33 | if(strEquals(name, cmpName.second)) 34 | { 35 | component = cmpName.first; 36 | return true; 37 | } 38 | } 39 | return false; 40 | } 41 | 42 | void setTimeVarying(UsdBridgedBaseObject* bridgedObj, IC component, bool value) 43 | { 44 | ID& params = bridgedObj->getWriteParams(); 45 | int bit = (1 << static_cast(component)); 46 | params.timeVarying = value ? (params.timeVarying | bit) : (params.timeVarying & ~bit); 47 | } 48 | }; 49 | 50 | template 51 | class TimeVaryingClass 52 | { 53 | public: 54 | bool findTimeVarying(const char* name, UsdEmptyComponents& component) 55 | { 56 | return false; 57 | } 58 | 59 | void setTimeVarying(UsdBridgedBaseObject* bridgedObj, UsdEmptyComponents component, bool value) 60 | { 61 | } 62 | }; 63 | 64 | bool setTimeVaryingParam(const char *name, 65 | ANARIDataType type, 66 | const void *mem, 67 | UsdDevice* device) 68 | { 69 | static const char* paramName = "usd::timeVarying."; 70 | bool value = *(reinterpret_cast(mem)); 71 | 72 | if (type == ANARI_BOOL) 73 | { 74 | if (strcmp(name, paramName) > 0) 75 | { 76 | const char* secondPart = name + strlen(paramName); 77 | C component; 78 | TimeVaryingClass timevarHelper; 79 | if(timevarHelper.findTimeVarying(secondPart, component)) 80 | { 81 | timevarHelper.setTimeVarying(this, component, value); 82 | return true; 83 | } 84 | } 85 | } 86 | return false; 87 | } 88 | 89 | bool isTimeVarying(C component) const 90 | { 91 | const D& params = this->getReadParams(); 92 | return params.timeVarying & (1 << static_cast(component)); 93 | } 94 | 95 | bool setRemovePrimParam(const char *name, 96 | ANARIDataType type, 97 | const void *mem, 98 | UsdDevice* device) 99 | { 100 | if (type == ANARI_BOOL) 101 | { 102 | if (strcmp(name, "usd::removePrim") == 0) 103 | { 104 | removePrim = true; 105 | return true; 106 | } 107 | } 108 | return false; 109 | } 110 | 111 | public: 112 | using ComponentPair = std::pair; // Used to define a componentParamNames 113 | 114 | UsdBridgedBaseObject(ANARIDataType t, const char* name, UsdDevice* device) 115 | : UsdParameterizedBaseObject(t, device) 116 | , uniqueName(name) 117 | { 118 | } 119 | 120 | H getUsdHandle() const { return usdHandle; } 121 | 122 | const char* getName() const override { return this->getReadParams().usdName ? this->getReadParams().usdName->c_str() : uniqueName; } 123 | 124 | void filterSetParam(const char *name, 125 | ANARIDataType type, 126 | const void *mem, 127 | UsdDevice* device) override 128 | { 129 | if(!this->setTimeVaryingParam(name, type, mem, device)) 130 | if (!this->setNameParam(name, type, mem, device)) 131 | if(!this->setRemovePrimParam(name, type, mem, device)) 132 | this->setParam(name, type, mem, device); 133 | } 134 | 135 | int getProperty(const char *name, 136 | ANARIDataType type, 137 | void *mem, 138 | uint64_t size, 139 | UsdDevice* device) override 140 | { 141 | int nameResult = this->getNameProperty(name, type, mem, size, device); 142 | if(!nameResult) 143 | { 144 | UsdBridge* usdBridge = device->getUsdBridge(); 145 | if(!usdBridge) 146 | { 147 | reportStatusThroughDevice(UsdLogInfo(device, this, ANARI_OBJECT, nullptr), ANARI_SEVERITY_WARNING, ANARI_STATUS_NO_ERROR, 148 | "%s parameter '%s' cannot be read with getProperty(); it requires a succesful device parameter commit.", getName(), name); 149 | } 150 | 151 | if (type == ANARI_STRING && strEquals(name, "usd::primPath")) 152 | { 153 | const char* primPath = usdBridge->GetPrimPath(&usdHandle); 154 | snprintf((char*)mem, size, "%s", primPath); 155 | return 1; 156 | } 157 | else if (type == ANARI_UINT64 && strEquals(name, "usd::primPath.size")) 158 | { 159 | if (Assert64bitStringLengthProperty(size, UsdLogInfo(device, this, ANARI_OBJECT, this->getName()), "usd::primPath.size")) 160 | { 161 | const char* primPath = usdBridge->GetPrimPath(&usdHandle); 162 | uint64_t nameLen = strlen(primPath)+1; 163 | memcpy(mem, &nameLen, size); 164 | } 165 | return 1; 166 | } 167 | } 168 | return nameResult; 169 | } 170 | 171 | virtual void commit(UsdDevice* device) override 172 | { 173 | #ifdef OBJECT_LIFETIME_EQUALS_USD_LIFETIME 174 | cachedBridge = device->getUsdBridge(); 175 | #endif 176 | UsdParameterizedBaseObject::commit(device); 177 | } 178 | 179 | double selectObjTime(double objTimeStep, double worldTimeStep) 180 | { 181 | return 182 | #ifdef VALUE_CLIP_RETIMING 183 | !std::isnan(objTimeStep) ? objTimeStep : 184 | #endif 185 | worldTimeStep; 186 | } 187 | 188 | double selectRefTime(double refTimeStep, double objTimeStep, double worldTimeStep) 189 | { 190 | return 191 | #ifdef VALUE_CLIP_RETIMING 192 | !std::isnan(refTimeStep) ? refTimeStep : 193 | (!std::isnan(objTimeStep) ? objTimeStep : worldTimeStep); 194 | #else 195 | worldTimeStep; 196 | #endif 197 | } 198 | 199 | bool getRemovePrim() const { return removePrim; } 200 | 201 | protected: 202 | typedef UsdBridgedBaseObject BridgedBaseObjectType; 203 | typedef void (UsdBridge::*UsdBridgeMemFn)(H handle); 204 | 205 | void applyRemoveFunc(UsdDevice* device, UsdBridgeMemFn func) 206 | { 207 | UsdBridge* usdBridge = device->getUsdBridge(); 208 | if(usdBridge && usdHandle.value) 209 | (usdBridge->*func)(usdHandle); 210 | } 211 | 212 | const char* uniqueName; 213 | H usdHandle; 214 | bool removePrim = false; 215 | 216 | #ifdef OBJECT_LIFETIME_EQUALS_USD_LIFETIME 217 | UsdBridge* cachedBridge = nullptr; 218 | #endif 219 | }; 220 | 221 | template 222 | inline bool UsdObjectNotInitialized(const UsdBridgedBaseObject* obj) 223 | { 224 | return obj && !obj->getUsdHandle().value; 225 | } 226 | 227 | template 228 | inline bool UsdObjectNotInitialized(UsdDataArray* objects) 229 | { 230 | if (!objects) 231 | return false; 232 | 233 | bool notInitialized = false; 234 | if(anari::isObject(objects->getType())) 235 | { 236 | const T* const * object = reinterpret_cast(objects->getData()); 237 | uint64_t numObjects = objects->getLayout().numItems1; 238 | for(int i = 0; i < numObjects; ++i) 239 | { 240 | notInitialized = notInitialized || UsdObjectNotInitialized(object[i]); 241 | } 242 | } 243 | 244 | return notInitialized; 245 | } -------------------------------------------------------------------------------- /UsdCamera.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdCamera.h" 5 | #include "UsdAnari.h" 6 | #include "UsdDataArray.h" 7 | #include "UsdDevice.h" 8 | 9 | DEFINE_PARAMETER_MAP(UsdCamera, 10 | REGISTER_PARAMETER_MACRO("name", ANARI_STRING, name) 11 | REGISTER_PARAMETER_MACRO("usd::name", ANARI_STRING, usdName) 12 | REGISTER_PARAMETER_MACRO("usd::timeVarying", ANARI_INT32, timeVarying) 13 | REGISTER_PARAMETER_MACRO("position", ANARI_FLOAT32_VEC3, position) 14 | REGISTER_PARAMETER_MACRO("direction", ANARI_FLOAT32_VEC3, direction) 15 | REGISTER_PARAMETER_MACRO("up", ANARI_FLOAT32_VEC3, up) 16 | REGISTER_PARAMETER_MACRO("imageRegion", ANARI_FLOAT32_BOX2, imageRegion) 17 | REGISTER_PARAMETER_MACRO("aspect", ANARI_FLOAT32, aspect) 18 | REGISTER_PARAMETER_MACRO("near", ANARI_FLOAT32, near) 19 | REGISTER_PARAMETER_MACRO("far", ANARI_FLOAT32, far) 20 | REGISTER_PARAMETER_MACRO("fovy", ANARI_FLOAT32, fovy) 21 | REGISTER_PARAMETER_MACRO("height", ANARI_FLOAT32, height) 22 | ) 23 | 24 | constexpr UsdCamera::ComponentPair UsdCamera::componentParamNames[]; // Workaround for C++14's lack of inlining constexpr arrays 25 | 26 | UsdCamera::UsdCamera(const char* name, const char* type, UsdDevice* device) 27 | : BridgedBaseObjectType(ANARI_CAMERA, name, device) 28 | { 29 | if(strEquals(type, "perspective")) 30 | cameraType = CAMERA_PERSPECTIVE; 31 | else if(strEquals(type, "orthographic")) 32 | cameraType = CAMERA_ORTHOGRAPHIC; 33 | } 34 | 35 | UsdCamera::~UsdCamera() 36 | { 37 | #ifdef OBJECT_LIFETIME_EQUALS_USD_LIFETIME 38 | if(cachedBridge) 39 | cachedBridge->DeleteGroup(usdHandle); 40 | #endif 41 | } 42 | 43 | void UsdCamera::remove(UsdDevice* device) 44 | { 45 | applyRemoveFunc(device, &UsdBridge::DeleteCamera); 46 | } 47 | 48 | bool UsdCamera::deferCommit(UsdDevice* device) 49 | { 50 | return false; 51 | } 52 | 53 | void UsdCamera::copyParameters(UsdBridgeCameraData& camData) 54 | { 55 | typedef UsdBridgeCameraData::DataMemberId DMI; 56 | 57 | const UsdCameraData& paramData = getReadParams(); 58 | 59 | camData.Position = paramData.position; 60 | camData.Direction = paramData.direction; 61 | camData.Up = paramData.up; 62 | camData.ImageRegion = paramData.imageRegion; 63 | camData.Aspect = paramData.aspect; 64 | camData.Near = paramData.near; 65 | camData.Far = paramData.far; 66 | camData.Fovy = paramData.fovy; 67 | camData.Height = paramData.height; 68 | 69 | camData.TimeVarying = DMI::ALL 70 | & (isTimeVarying(CType::VIEW) ? DMI::ALL : ~DMI::VIEW) 71 | & (isTimeVarying(CType::PROJECTION) ? DMI::ALL : ~DMI::PROJECTION); 72 | } 73 | 74 | bool UsdCamera::doCommitData(UsdDevice* device) 75 | { 76 | UsdBridge* usdBridge = device->getUsdBridge(); 77 | const UsdCameraData& paramData = getReadParams(); 78 | double timeStep = device->getReadParams().timeStep; 79 | 80 | bool isNew = false; 81 | if (!usdHandle.value) 82 | isNew = usdBridge->CreateCamera(getName(), usdHandle); 83 | 84 | if (paramChanged || isNew) 85 | { 86 | UsdBridgeCameraData camData; 87 | copyParameters(camData); 88 | 89 | usdBridge->SetCameraData(usdHandle, camData, timeStep); 90 | 91 | paramChanged = false; 92 | } 93 | return false; 94 | } -------------------------------------------------------------------------------- /UsdCamera.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBaseObject.h" 7 | #include "UsdBridgedBaseObject.h" 8 | 9 | enum class UsdCameraComponents 10 | { 11 | VIEW = 0, 12 | PROJECTION 13 | }; 14 | 15 | struct UsdCameraData 16 | { 17 | UsdSharedString* name = nullptr; 18 | UsdSharedString* usdName = nullptr; 19 | 20 | int timeVarying = 0xFFFFFFFF; // TimeVarying bits 21 | 22 | UsdFloat3 position = {0.0f, 0.0f, 0.0f}; 23 | UsdFloat3 direction = {0.0f, 0.0f, -1.0f}; 24 | UsdFloat3 up = {0.0f, 1.0f, 0.0f}; 25 | UsdFloatBox2 imageRegion = {0.0f, 0.0f, 1.0f, 1.0f}; 26 | 27 | // perspective/orthographic 28 | float aspect = 1.0f; 29 | float near = 1.0f; 30 | float far = 10000; 31 | float fovy = M_PI/3.0f; 32 | float height = 1.0f; 33 | }; 34 | 35 | class UsdCamera : public UsdBridgedBaseObject 36 | { 37 | public: 38 | UsdCamera(const char* name, const char* type, UsdDevice* device); 39 | ~UsdCamera(); 40 | 41 | void remove(UsdDevice* device) override; 42 | 43 | enum CameraType 44 | { 45 | CAMERA_UNKNOWN = 0, 46 | CAMERA_PERSPECTIVE, 47 | CAMERA_ORTHOGRAPHIC 48 | }; 49 | 50 | static constexpr ComponentPair componentParamNames[] = { 51 | ComponentPair(UsdCameraComponents::VIEW, "view"), 52 | ComponentPair(UsdCameraComponents::PROJECTION, "projection")}; 53 | 54 | protected: 55 | bool deferCommit(UsdDevice* device) override; 56 | bool doCommitData(UsdDevice* device) override; 57 | void doCommitRefs(UsdDevice* device) override {} 58 | 59 | void copyParameters(UsdBridgeCameraData& camData); 60 | 61 | CameraType cameraType = CAMERA_UNKNOWN; 62 | }; -------------------------------------------------------------------------------- /UsdCommonMacros.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridge/Common/UsdBridgeMacros.h" 7 | 8 | //#define OBJECT_LIFETIME_EQUALS_USD_LIFETIME 9 | 10 | #ifndef NDEBUG 11 | // This is now handled in CMake 12 | //#define CHECK_MEMLEAKS //asserts at ~UsdDevice() if memleak found 13 | #endif 14 | -------------------------------------------------------------------------------- /UsdDataArray.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBaseObject.h" 7 | #include "UsdParameterizedObject.h" 8 | #include "anari/frontend/anari_enums.h" 9 | 10 | class UsdDevice; 11 | 12 | struct UsdDataLayout 13 | { 14 | bool isDense() const { return byteStride1 == typeSize && byteStride2 == numItems1*byteStride1 && byteStride3 == numItems2*byteStride2; } 15 | bool isOneDimensional() const { return numItems2 == 1 && numItems3 == 1; } 16 | void copyDims(uint64_t dims[3]) const { std::memcpy(dims, &numItems1, sizeof(uint64_t)*3); } 17 | void copyStride(int64_t stride[3]) const { std::memcpy(stride, &byteStride1, sizeof(int64_t)*3); } 18 | 19 | uint64_t typeSize = 0; 20 | uint64_t numItems1 = 0; 21 | uint64_t numItems2 = 0; 22 | uint64_t numItems3 = 0; 23 | int64_t byteStride1 = 0; 24 | int64_t byteStride2 = 0; 25 | int64_t byteStride3 = 0; 26 | }; 27 | 28 | struct UsdDataArrayParams 29 | { 30 | // Even though we are not dealing with a usd-backed object, the data array can still have an identifying name. 31 | // The pointer can then be used as id for resources (plus defining their filenames) such as textures, 32 | // so they can be shared and still removed during garbage collection (after an UsdAnari object has already been destroyed). 33 | // The persistence reason is why these strings have to be added to the string list of the device on construction. 34 | UsdSharedString* name = nullptr; 35 | UsdSharedString* usdName = nullptr; 36 | }; 37 | 38 | class UsdDataArray : public UsdParameterizedBaseObject 39 | { 40 | public: 41 | UsdDataArray(const void *appMemory, 42 | ANARIMemoryDeleter deleter, 43 | const void *userData, 44 | ANARIDataType dataType, 45 | uint64_t numItems1, 46 | int64_t byteStride1, 47 | uint64_t numItems2, 48 | int64_t byteStride2, 49 | uint64_t numItems3, 50 | int64_t byteStride3, 51 | UsdDevice* device 52 | ); 53 | UsdDataArray(ANARIDataType dataType, 54 | uint64_t numItems1, 55 | uint64_t numItems2, 56 | uint64_t numItems3, 57 | UsdDevice* device 58 | ); 59 | ~UsdDataArray(); 60 | 61 | void filterSetParam(const char *name, 62 | ANARIDataType type, 63 | const void *mem, 64 | UsdDevice* device) override; 65 | 66 | int getProperty(const char *name, 67 | ANARIDataType type, 68 | void *mem, 69 | uint64_t size, 70 | UsdDevice* device) override; 71 | 72 | void commit(UsdDevice* device) override; 73 | 74 | void remove(UsdDevice* device) override {} 75 | 76 | void* map(UsdDevice* device); 77 | void unmap(UsdDevice* device); 78 | 79 | void privatize(); 80 | 81 | const char* getName() const override { return UsdSharedString::c_str(getReadParams().usdName); } 82 | 83 | const void* getData() const { return data; } 84 | ANARIDataType getType() const { return type; } 85 | const UsdDataLayout& getLayout() const { return layout; } 86 | 87 | size_t getDataSizeInBytes() const { return dataSizeInBytes; } 88 | 89 | protected: 90 | bool deferCommit(UsdDevice* device) override { return false; } 91 | bool doCommitData(UsdDevice* device) override { return false; } 92 | void doCommitRefs(UsdDevice* device) override {} 93 | 94 | void setLayoutAndSize(uint64_t numItems1, 95 | int64_t byteStride1, 96 | uint64_t numItems2, 97 | int64_t byteStride2, 98 | uint64_t numItems3, 99 | int64_t byteStride3); 100 | bool CheckFormatting(UsdDevice* device); 101 | 102 | // Ref manipulation on arrays of anariobjects 103 | void incRef(const ANARIObject* anariObjects, uint64_t numAnariObjects); 104 | void decRef(const ANARIObject* anariObjects, uint64_t numAnariObjects); 105 | 106 | // Private memory management 107 | void allocPrivateData(); 108 | void freePrivateData(bool mappedCopy = false); 109 | void freePublicData(const void* appMemory); 110 | void publicToPrivateData(); 111 | 112 | // Mapped memory management 113 | void CreateMappedObjectCopy(); 114 | void TransferAndRemoveMappedObjectCopy(); 115 | 116 | const void* data = nullptr; 117 | ANARIMemoryDeleter dataDeleter = nullptr; 118 | const void* deleterUserData = nullptr; 119 | ANARIDataType type; 120 | UsdDataLayout layout; 121 | size_t dataSizeInBytes; 122 | bool isPrivate; 123 | 124 | const void* mappedObjectCopy; 125 | 126 | #ifdef CHECK_MEMLEAKS 127 | UsdDevice* allocDevice; 128 | #endif 129 | }; -------------------------------------------------------------------------------- /UsdDeviceQueries.h: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // This file was generated by generate_queries.py 5 | // Don't make changes to this directly 6 | 7 | #include 8 | namespace anari { 9 | namespace usd { 10 | #define ANARI_INFO_required 0 11 | #define ANARI_INFO_default 1 12 | #define ANARI_INFO_minimum 2 13 | #define ANARI_INFO_maximum 3 14 | #define ANARI_INFO_description 4 15 | #define ANARI_INFO_elementType 5 16 | #define ANARI_INFO_value 6 17 | #define ANARI_INFO_sourceExtension 7 18 | #define ANARI_INFO_extension 8 19 | #define ANARI_INFO_parameter 9 20 | #define ANARI_INFO_channel 10 21 | #define ANARI_INFO_use 11 22 | const int extension_count = 17; 23 | const char ** query_extensions(); 24 | const char ** query_object_types(ANARIDataType type); 25 | const ANARIParameter * query_params(ANARIDataType type, const char *subtype); 26 | const void * query_param_info_enum(ANARIDataType type, const char *subtype, const char *paramName, ANARIDataType paramType, int infoName, ANARIDataType infoType); 27 | const void * query_param_info(ANARIDataType type, const char *subtype, const char *paramName, ANARIDataType paramType, const char *infoNameString, ANARIDataType infoType); 28 | const void * query_object_info_enum(ANARIDataType type, const char *subtype, int infoName, ANARIDataType infoType); 29 | const void * query_object_info(ANARIDataType type, const char *subtype, const char *infoNameString, ANARIDataType infoType); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /UsdDeviceUtils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #include 8 | 9 | template> 10 | struct OptionalList 11 | { 12 | void ensureList() 13 | { 14 | if(!list) 15 | list = std::make_unique(); 16 | } 17 | 18 | void clear() 19 | { 20 | if(list) 21 | list->resize(0); 22 | } 23 | 24 | void push_back(const ValueType& value) 25 | { 26 | ensureList(); 27 | list->push_back(value); 28 | } 29 | 30 | void emplace_back(const ValueType& value) 31 | { 32 | ensureList(); 33 | list->emplace_back(value); 34 | } 35 | 36 | const ValueType* data() 37 | { 38 | if(list) 39 | return list->data(); 40 | return nullptr; 41 | } 42 | 43 | size_t size() 44 | { 45 | if(list) 46 | return list->size(); 47 | return 0; 48 | } 49 | 50 | std::unique_ptr list; 51 | }; -------------------------------------------------------------------------------- /UsdFrame.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdFrame.h" 5 | #include "UsdBridge/UsdBridge.h" 6 | #include "UsdAnari.h" 7 | #include "UsdDevice.h" 8 | #include "anari/frontend/type_utility.h" 9 | 10 | DEFINE_PARAMETER_MAP(UsdFrame, 11 | REGISTER_PARAMETER_MACRO("size", ANARI_UINT32_VEC2, size) 12 | REGISTER_PARAMETER_MACRO("channel.color", ANARI_DATA_TYPE, color) 13 | REGISTER_PARAMETER_MACRO("channel.depth", ANARI_DATA_TYPE, depth) 14 | ) 15 | 16 | UsdFrame::UsdFrame(UsdBridge* bridge) 17 | : UsdParameterizedBaseObject(ANARI_FRAME) 18 | { 19 | } 20 | 21 | UsdFrame::~UsdFrame() 22 | { 23 | delete[] mappedColorMem; 24 | delete[] mappedDepthMem; 25 | } 26 | 27 | bool UsdFrame::deferCommit(UsdDevice* device) 28 | { 29 | return false; 30 | } 31 | 32 | bool UsdFrame::doCommitData(UsdDevice* device) 33 | { 34 | return false; 35 | } 36 | 37 | const void* UsdFrame::mapBuffer(const char *channel, 38 | uint32_t *width, 39 | uint32_t *height, 40 | ANARIDataType *pixelType) 41 | { 42 | const UsdFrameData& paramData = getReadParams(); 43 | 44 | *width = paramData.size.Data[0]; 45 | *height = paramData.size.Data[1]; 46 | *pixelType = ANARI_UNKNOWN; 47 | 48 | if (strEquals(channel, "channel.color")) 49 | { 50 | mappedColorMem = ReserveBuffer(paramData.color); 51 | *pixelType = paramData.color; 52 | return mappedColorMem; 53 | } 54 | else if (strEquals(channel, "channel.depth")) 55 | { 56 | mappedDepthMem = ReserveBuffer(paramData.depth); 57 | *pixelType = paramData.depth; 58 | return mappedDepthMem; 59 | } 60 | 61 | *width = 0; 62 | *height = 0; 63 | 64 | return nullptr; 65 | } 66 | 67 | void UsdFrame::unmapBuffer(const char *channel) 68 | { 69 | if (strEquals(channel, "channel.color")) 70 | { 71 | delete[] mappedColorMem; 72 | mappedColorMem = nullptr; 73 | } 74 | else if (strEquals(channel, "channel.depth")) 75 | { 76 | delete[] mappedDepthMem; 77 | mappedDepthMem = nullptr; 78 | } 79 | } 80 | 81 | char* UsdFrame::ReserveBuffer(ANARIDataType format) 82 | { 83 | const UsdFrameData& paramData = getReadParams(); 84 | size_t formatSize = anari::sizeOf(format); 85 | size_t memSize = formatSize * paramData.size.Data[0] * paramData.size.Data[1]; 86 | return new char[memSize]; 87 | } 88 | 89 | void UsdFrame::saveUsd(UsdDevice* device) 90 | { 91 | device->getUsdBridge()->SaveScene(); 92 | } 93 | -------------------------------------------------------------------------------- /UsdFrame.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBaseObject.h" 7 | #include "UsdParameterizedObject.h" 8 | 9 | class UsdRenderer; 10 | class UsdWorld; 11 | 12 | struct UsdFrameData 13 | { 14 | UsdUint2 size = {0, 0}; 15 | ANARIDataType color = ANARI_UNKNOWN; 16 | ANARIDataType depth = ANARI_UNKNOWN; 17 | }; 18 | 19 | class UsdFrame : public UsdParameterizedBaseObject 20 | { 21 | public: 22 | UsdFrame(UsdBridge* bridge); 23 | ~UsdFrame(); 24 | 25 | void remove(UsdDevice* device) override {} 26 | 27 | const void* mapBuffer(const char* channel, 28 | uint32_t *width, 29 | uint32_t *height, 30 | ANARIDataType *pixelType); 31 | void unmapBuffer(const char* channel); 32 | 33 | void saveUsd(UsdDevice* device); 34 | 35 | protected: 36 | bool deferCommit(UsdDevice* device) override; 37 | bool doCommitData(UsdDevice* device) override; 38 | void doCommitRefs(UsdDevice* device) override {} 39 | 40 | char* ReserveBuffer(ANARIDataType format); 41 | 42 | char* mappedColorMem = nullptr; 43 | char* mappedDepthMem = nullptr; 44 | }; 45 | -------------------------------------------------------------------------------- /UsdGeometry.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridgedBaseObject.h" 7 | 8 | #include 9 | #include 10 | 11 | class UsdDataArray; 12 | struct UsdBridgeMeshData; 13 | 14 | static constexpr int MAX_ATTRIBS = 16; // Coordinate with UsdGeometry::componentParamNames and UsdBridgeData.h 15 | 16 | enum class UsdGeometryComponents 17 | { 18 | POSITION = 0, 19 | NORMAL, 20 | COLOR, 21 | INDEX, 22 | SCALE, 23 | ORIENTATION, 24 | ID, 25 | ATTRIBUTE0, 26 | ATTRIBUTE1, 27 | ATTRIBUTE2, 28 | ATTRIBUTE3, 29 | ATTRIBUTE4, 30 | ATTRIBUTE5, 31 | ATTRIBUTE6, 32 | ATTRIBUTE7, 33 | ATTRIBUTE8, 34 | ATTRIBUTE9, 35 | ATTRIBUTE10, 36 | ATTRIBUTE11, 37 | ATTRIBUTE12, 38 | ATTRIBUTE13, 39 | ATTRIBUTE14, 40 | ATTRIBUTE15 41 | }; 42 | 43 | struct UsdGeometryData 44 | { 45 | UsdSharedString* name = nullptr; 46 | UsdSharedString* usdName = nullptr; 47 | 48 | double timeStep = std::numeric_limits::quiet_NaN(); 49 | int timeVarying = 0xFFFFFFFF; // TimeVarying bits 50 | 51 | const UsdDataArray* vertexPositions = nullptr; 52 | const UsdDataArray* vertexNormals = nullptr; 53 | const UsdDataArray* vertexColors = nullptr; 54 | const UsdDataArray* vertexAttributes[MAX_ATTRIBS] = { nullptr }; 55 | const UsdDataArray* primitiveNormals = nullptr; 56 | const UsdDataArray* primitiveColors = nullptr; 57 | const UsdDataArray* primitiveAttributes[MAX_ATTRIBS] = { nullptr }; 58 | const UsdDataArray* primitiveIds = nullptr; 59 | const UsdSharedString* attributeNames[MAX_ATTRIBS] = { nullptr }; 60 | const UsdDataArray* indices = nullptr; 61 | 62 | // Spheres 63 | const UsdDataArray* vertexRadii = nullptr; 64 | float radiusConstant = 1.0f; 65 | bool UseUsdGeomPoints = 66 | #ifdef USE_USD_GEOM_POINTS 67 | true; 68 | #else 69 | false; 70 | #endif 71 | 72 | // Cylinders 73 | const UsdDataArray* primitiveRadii = nullptr; 74 | 75 | // Curves 76 | 77 | // Glyphs 78 | const UsdDataArray* vertexScales = nullptr; 79 | const UsdDataArray* primitiveScales = nullptr; 80 | const UsdDataArray* vertexOrientations = nullptr; 81 | const UsdDataArray* primitiveOrientations = nullptr; 82 | 83 | UsdFloat3 scaleConstant = {1.0f, 1.0f, 1.0f}; 84 | UsdQuaternion orientationConstant; 85 | 86 | UsdSharedString* shapeType = nullptr; 87 | UsdGeometry* shapeGeometry = nullptr; 88 | 89 | UsdFloatMat4 shapeTransform; 90 | 91 | double shapeGeometryRefTimeStep = std::numeric_limits::quiet_NaN(); 92 | }; 93 | 94 | struct UsdGeometryTempArrays; 95 | 96 | class UsdGeometry : public UsdBridgedBaseObject 97 | { 98 | public: 99 | enum GeomType 100 | { 101 | GEOM_UNKNOWN = 0, 102 | GEOM_TRIANGLE, 103 | GEOM_QUAD, 104 | GEOM_SPHERE, 105 | GEOM_CYLINDER, 106 | GEOM_CONE, 107 | GEOM_CURVE, 108 | GEOM_GLYPH 109 | }; 110 | 111 | typedef std::vector AttributeArray; 112 | typedef std::vector> AttributeDataArraysType; 113 | 114 | UsdGeometry(const char* name, const char* type, UsdDevice* device); 115 | ~UsdGeometry(); 116 | 117 | void remove(UsdDevice* device) override; 118 | 119 | void filterSetParam(const char *name, 120 | ANARIDataType type, 121 | const void *mem, 122 | UsdDevice* device) override; 123 | 124 | void commit(UsdDevice* device) override; 125 | 126 | bool isInstanced() const 127 | { 128 | return geomType == GEOM_SPHERE 129 | || geomType == GEOM_CONE 130 | || geomType == GEOM_CYLINDER 131 | || geomType == GEOM_GLYPH; 132 | } 133 | 134 | bool getHasNewAttribName() const { return hasNewAttribName; } 135 | 136 | static constexpr ComponentPair componentParamNames[] = { 137 | ComponentPair(UsdGeometryComponents::POSITION, "position"), 138 | ComponentPair(UsdGeometryComponents::NORMAL, "normal"), 139 | ComponentPair(UsdGeometryComponents::COLOR, "color"), 140 | ComponentPair(UsdGeometryComponents::INDEX, "index"), 141 | ComponentPair(UsdGeometryComponents::SCALE, "scale"), 142 | ComponentPair(UsdGeometryComponents::SCALE, "radius"), 143 | ComponentPair(UsdGeometryComponents::ORIENTATION, "orientation"), 144 | ComponentPair(UsdGeometryComponents::ID, "id"), 145 | ComponentPair(UsdGeometryComponents::ATTRIBUTE0, "attribute0"), 146 | ComponentPair(UsdGeometryComponents::ATTRIBUTE1, "attribute1"), 147 | ComponentPair(UsdGeometryComponents::ATTRIBUTE2, "attribute2"), 148 | ComponentPair(UsdGeometryComponents::ATTRIBUTE3, "attribute3"), 149 | ComponentPair(UsdGeometryComponents::ATTRIBUTE4, "attribute4"), 150 | ComponentPair(UsdGeometryComponents::ATTRIBUTE5, "attribute5"), 151 | ComponentPair(UsdGeometryComponents::ATTRIBUTE6, "attribute6"), 152 | ComponentPair(UsdGeometryComponents::ATTRIBUTE7, "attribute7"), 153 | ComponentPair(UsdGeometryComponents::ATTRIBUTE8, "attribute8"), 154 | ComponentPair(UsdGeometryComponents::ATTRIBUTE9, "attribute9"), 155 | ComponentPair(UsdGeometryComponents::ATTRIBUTE10, "attribute10"), 156 | ComponentPair(UsdGeometryComponents::ATTRIBUTE11, "attribute11"), 157 | ComponentPair(UsdGeometryComponents::ATTRIBUTE12, "attribute12"), 158 | ComponentPair(UsdGeometryComponents::ATTRIBUTE13, "attribute13"), 159 | ComponentPair(UsdGeometryComponents::ATTRIBUTE14, "attribute14"), 160 | ComponentPair(UsdGeometryComponents::ATTRIBUTE15, "attribute15")}; 161 | 162 | protected: 163 | bool deferCommit(UsdDevice* device) override; 164 | bool doCommitData(UsdDevice* device) override; 165 | void doCommitRefs(UsdDevice* device) override; 166 | 167 | void initializeGeomData(UsdBridgeMeshData& geomData); 168 | void initializeGeomData(UsdBridgeInstancerData& geomData); 169 | void initializeGeomData(UsdBridgeCurveData& geomData); 170 | 171 | void initializeGeomRefData(UsdBridgeInstancerRefData& geomRefData); 172 | 173 | bool checkArrayConstraints(const UsdDataArray* vertexArray, const UsdDataArray* primArray, 174 | const char* paramName, UsdDevice* device, const char* debugName, int attribIndex = -1); 175 | bool checkGeomParams(UsdDevice* device); 176 | 177 | void updateGeomData(UsdDevice* device, UsdBridge* usdBridge, UsdBridgeMeshData& meshData, bool isNew); 178 | void updateGeomData(UsdDevice* device, UsdBridge* usdBridge, UsdBridgeInstancerData& instancerData, bool isNew); 179 | void updateGeomData(UsdDevice* device, UsdBridge* usdBridge, UsdBridgeCurveData& curveData, bool isNew); 180 | 181 | template 182 | bool commitTemplate(UsdDevice* device); 183 | 184 | void commitPrototypes(UsdBridge* usdBridge); 185 | 186 | template 187 | void setAttributeTimeVarying(typename GeomDataType::DataMemberId& timeVarying); 188 | 189 | void syncAttributeArrays(); 190 | 191 | template 192 | void copyAttributeArraysToData(GeomDataType& geomData); 193 | 194 | void assignTempDataToAttributes(bool perPrimInterpolation); 195 | 196 | GeomType geomType = GEOM_UNKNOWN; 197 | bool protoShapeChanged = false; // Do not automatically commit shapes (the object may have been recreated onto an already existing USD prim) 198 | 199 | bool hasNewAttribName = false; 200 | 201 | std::unique_ptr tempArrays; 202 | 203 | AttributeArray attributeArray; 204 | }; -------------------------------------------------------------------------------- /UsdGroup.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdGroup.h" 5 | #include "UsdAnari.h" 6 | #include "UsdDataArray.h" 7 | #include "UsdDevice.h" 8 | #include "UsdSurface.h" 9 | #include "UsdVolume.h" 10 | 11 | #define SurfaceType ANARI_SURFACE 12 | #define VolumeType ANARI_VOLUME 13 | using SurfaceUsdType = AnariToUsdBridgedObject::Type; 14 | using VolumeUsdType = AnariToUsdBridgedObject::Type; 15 | 16 | DEFINE_PARAMETER_MAP(UsdGroup, 17 | REGISTER_PARAMETER_MACRO("name", ANARI_STRING, name) 18 | REGISTER_PARAMETER_MACRO("usd::name", ANARI_STRING, usdName) 19 | REGISTER_PARAMETER_MACRO("usd::timeVarying", ANARI_INT32, timeVarying) 20 | REGISTER_PARAMETER_MACRO("surface", ANARI_ARRAY, surfaces) 21 | REGISTER_PARAMETER_MACRO("volume", ANARI_ARRAY, volumes) 22 | ) 23 | 24 | constexpr UsdGroup::ComponentPair UsdGroup::componentParamNames[]; // Workaround for C++14's lack of inlining constexpr arrays 25 | 26 | UsdGroup::UsdGroup(const char* name, 27 | UsdDevice* device) 28 | : BridgedBaseObjectType(ANARI_GROUP, name, device) 29 | { 30 | } 31 | 32 | UsdGroup::~UsdGroup() 33 | { 34 | #ifdef OBJECT_LIFETIME_EQUALS_USD_LIFETIME 35 | if(cachedBridge) 36 | cachedBridge->DeleteGroup(usdHandle); 37 | #endif 38 | } 39 | 40 | void UsdGroup::remove(UsdDevice* device) 41 | { 42 | applyRemoveFunc(device, &UsdBridge::DeleteGroup); 43 | } 44 | 45 | bool UsdGroup::deferCommit(UsdDevice* device) 46 | { 47 | const UsdGroupData& paramData = getReadParams(); 48 | 49 | if(UsdObjectNotInitialized(paramData.surfaces) || 50 | UsdObjectNotInitialized(paramData.volumes)) 51 | { 52 | return true; 53 | } 54 | return false; 55 | } 56 | 57 | bool UsdGroup::doCommitData(UsdDevice* device) 58 | { 59 | UsdBridge* usdBridge = device->getUsdBridge(); 60 | 61 | bool isNew = false; 62 | if (!usdHandle.value) 63 | isNew = usdBridge->CreateGroup(getName(), usdHandle); 64 | 65 | if (paramChanged || isNew) 66 | { 67 | doCommitRefs(device); // Perform immediate commit of refs - no params from children required 68 | 69 | paramChanged = false; 70 | } 71 | return false; 72 | } 73 | 74 | 75 | void UsdGroup::doCommitRefs(UsdDevice* device) 76 | { 77 | UsdBridge* usdBridge = device->getUsdBridge(); 78 | const UsdGroupData& paramData = getReadParams(); 79 | double timeStep = device->getReadParams().timeStep; 80 | 81 | UsdLogInfo logInfo(device, this, ANARI_GROUP, this->getName()); 82 | 83 | bool surfacesTimeVarying = isTimeVarying(UsdGroupComponents::SURFACES); 84 | bool volumesTimeVarying = isTimeVarying(UsdGroupComponents::VOLUMES); 85 | 86 | ManageRefArray(usdHandle, paramData.surfaces, surfacesTimeVarying, timeStep, 87 | surfaceHandles, instanceableValues, &UsdBridge::SetSurfaceRefs, &UsdBridge::DeleteSurfaceRefs, 88 | usdBridge, logInfo, "UsdGroup commit failed: 'surface' array elements should be of type ANARI_SURFACE"); 89 | 90 | ManageRefArray(usdHandle, paramData.volumes, volumesTimeVarying, timeStep, 91 | volumeHandles, instanceableValues, &UsdBridge::SetVolumeRefs, &UsdBridge::DeleteVolumeRefs, 92 | usdBridge, logInfo, "UsdGroup commit failed: 'volume' array elements should be of type ANARI_VOLUME"); 93 | } -------------------------------------------------------------------------------- /UsdGroup.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridgedBaseObject.h" 7 | #include "UsdBridge.h" 8 | 9 | class UsdDevice; 10 | class UsdDataArray; 11 | 12 | enum class UsdGroupComponents 13 | { 14 | SURFACES = 0, 15 | VOLUMES 16 | }; 17 | 18 | struct UsdGroupData 19 | { 20 | UsdSharedString* name = nullptr; 21 | UsdSharedString* usdName = nullptr; 22 | 23 | int timeVarying = 0xFFFFFFFF; // Bitmask indicating which attributes are time-varying. 24 | UsdDataArray* surfaces = nullptr; 25 | UsdDataArray* volumes = nullptr; 26 | }; 27 | 28 | class UsdGroup : public UsdBridgedBaseObject 29 | { 30 | public: 31 | UsdGroup(const char* name, UsdDevice* device); 32 | ~UsdGroup(); 33 | 34 | void remove(UsdDevice* device) override; 35 | 36 | static constexpr ComponentPair componentParamNames[] = { 37 | ComponentPair(UsdGroupComponents::SURFACES, "surface"), 38 | ComponentPair(UsdGroupComponents::VOLUMES, "volume")}; 39 | 40 | protected: 41 | bool deferCommit(UsdDevice* device) override; 42 | bool doCommitData(UsdDevice* device) override; 43 | void doCommitRefs(UsdDevice* device) override; 44 | 45 | std::vector surfaceHandles; // for convenience 46 | std::vector volumeHandles; // for convenience 47 | std::vector instanceableValues; // for convenience 48 | }; 49 | 50 | typedef void (UsdBridge::*SetRefFunc)(UsdGroupHandle, const UsdSurfaceHandle*, uint64_t, bool, double); 51 | 52 | template 54 | void ManageRefArray(ParentHandleType parentHandle, UsdDataArray* childArray, bool refsTimeVarying, double timeStep, 55 | std::vector& tempChildHandles, std::vector& tempInstanceableValues, 56 | void (UsdBridge::*SetRefFunc)(ParentHandleType, const ChildHandleType*, uint64_t, bool, double, const int*), void (UsdBridge::*DeleteRefFunc)(ParentHandleType, bool, double), 57 | UsdBridge* usdBridge, UsdLogInfo& logInfo, const char* typeErrorMsg) 58 | { 59 | bool validRefs = AssertArrayType(childArray, ChildAnariTypeEnum, logInfo, typeErrorMsg); 60 | 61 | if(validRefs) 62 | { 63 | if (childArray) 64 | { 65 | const ChildAnariType* children = reinterpret_cast(childArray->getData()); 66 | 67 | uint64_t numChildren = childArray->getLayout().numItems1; 68 | tempChildHandles.resize(numChildren); 69 | tempInstanceableValues.resize(numChildren); 70 | for (uint64_t i = 0; i < numChildren; ++i) 71 | { 72 | const ChildUsdType* usdChild = reinterpret_cast(children[i]); 73 | tempChildHandles[i] = usdChild->getUsdHandle(); 74 | tempInstanceableValues[i] = usdChild->isInstanceable() ? 1 : 0; 75 | } 76 | 77 | (usdBridge->*SetRefFunc)(parentHandle, tempChildHandles.data(), numChildren, refsTimeVarying, timeStep, tempInstanceableValues.data()); 78 | } 79 | else 80 | { 81 | (usdBridge->*DeleteRefFunc)(parentHandle, refsTimeVarying, timeStep); 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /UsdInstance.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdInstance.h" 5 | #include "UsdAnari.h" 6 | #include "UsdDevice.h" 7 | #include "UsdGroup.h" 8 | 9 | #define GroupType ANARI_GROUP 10 | using GroupUsdType = AnariToUsdBridgedObject::Type; 11 | 12 | DEFINE_PARAMETER_MAP(UsdInstance, 13 | REGISTER_PARAMETER_MACRO("name", ANARI_STRING, name) 14 | REGISTER_PARAMETER_MACRO("usd::name", ANARI_STRING, usdName) 15 | REGISTER_PARAMETER_MACRO("usd::timeVarying", ANARI_INT32, timeVarying) 16 | REGISTER_PARAMETER_MACRO("group", GroupType, group) 17 | REGISTER_PARAMETER_MACRO("transform", ANARI_FLOAT32_MAT4, transform) 18 | ) 19 | 20 | constexpr UsdInstance::ComponentPair UsdInstance::componentParamNames[]; // Workaround for C++14's lack of inlining constexpr arrays 21 | 22 | UsdInstance::UsdInstance(const char* name, 23 | UsdDevice* device) 24 | : BridgedBaseObjectType(ANARI_INSTANCE, name, device) 25 | { 26 | } 27 | 28 | UsdInstance::~UsdInstance() 29 | { 30 | #ifdef OBJECT_LIFETIME_EQUALS_USD_LIFETIME 31 | if(cachedBridge) 32 | cachedBridge->DeleteInstance(usdHandle); 33 | #endif 34 | } 35 | 36 | void UsdInstance::remove(UsdDevice* device) 37 | { 38 | applyRemoveFunc(device, &UsdBridge::DeleteInstance); 39 | } 40 | 41 | bool UsdInstance::isInstanceable() const 42 | { 43 | return false; 44 | } 45 | 46 | bool UsdInstance::deferCommit(UsdDevice* device) 47 | { 48 | const UsdInstanceData& paramData = getReadParams(); 49 | 50 | if(UsdObjectNotInitialized(paramData.group)) 51 | { 52 | return true; 53 | } 54 | return false; 55 | } 56 | 57 | bool UsdInstance::doCommitData(UsdDevice* device) 58 | { 59 | UsdBridge* usdBridge = device->getUsdBridge(); 60 | 61 | const char* instanceName = getName(); 62 | 63 | bool isNew = false; 64 | if (!usdHandle.value) 65 | isNew = usdBridge->CreateInstance(instanceName, usdHandle); 66 | 67 | if (paramChanged || isNew) 68 | { 69 | doCommitRefs(device); // Perform immediate commit of refs - no params from children required 70 | 71 | paramChanged = false; 72 | } 73 | 74 | return false; 75 | } 76 | 77 | void UsdInstance::doCommitRefs(UsdDevice* device) 78 | { 79 | UsdBridge* usdBridge = device->getUsdBridge(); 80 | const UsdInstanceData& paramData = getReadParams(); 81 | 82 | double timeStep = device->getReadParams().timeStep; 83 | 84 | bool groupTimeVarying = isTimeVarying(UsdInstanceComponents::GROUP); 85 | bool transformTimeVarying = isTimeVarying(UsdInstanceComponents::TRANSFORM); 86 | 87 | if (paramData.group) 88 | { 89 | usdBridge->SetGroupRef(usdHandle, paramData.group->getUsdHandle(), groupTimeVarying, timeStep); 90 | } 91 | else 92 | { 93 | usdBridge->DeleteGroupRef(usdHandle, groupTimeVarying, timeStep); 94 | } 95 | 96 | usdBridge->SetInstanceTransform(usdHandle, paramData.transform.Data, transformTimeVarying, timeStep); 97 | } -------------------------------------------------------------------------------- /UsdInstance.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridgedBaseObject.h" 7 | 8 | class UsdGroup; 9 | 10 | enum class UsdInstanceComponents 11 | { 12 | GROUP = 0, 13 | TRANSFORM 14 | }; 15 | 16 | struct UsdInstanceData 17 | { 18 | UsdSharedString* name = nullptr; 19 | UsdSharedString* usdName = nullptr; 20 | 21 | int timeVarying = 0xFFFFFFFF; // Bitmask indicating which attributes are time-varying. 22 | 23 | UsdGroup* group = nullptr; 24 | UsdFloatMat4 transform; 25 | }; 26 | 27 | class UsdInstance : public UsdBridgedBaseObject 28 | { 29 | public: 30 | UsdInstance(const char* name, 31 | UsdDevice* device); 32 | ~UsdInstance(); 33 | 34 | void remove(UsdDevice* device) override; 35 | 36 | bool isInstanceable() const; 37 | 38 | static constexpr ComponentPair componentParamNames[] = { 39 | ComponentPair(UsdInstanceComponents::GROUP, "group"), 40 | ComponentPair(UsdInstanceComponents::TRANSFORM, "transform")}; 41 | 42 | protected: 43 | bool deferCommit(UsdDevice* device) override; 44 | bool doCommitData(UsdDevice* device) override; 45 | void doCommitRefs(UsdDevice* device) override; 46 | }; -------------------------------------------------------------------------------- /UsdLibrary.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdDevice.h" 5 | #include "anari/backend/LibraryImpl.h" 6 | 7 | #ifndef USDDevice_INTERFACE 8 | #define USDDevice_INTERFACE 9 | #endif 10 | 11 | namespace anari { 12 | namespace usd { 13 | 14 | const char **query_extensions(); 15 | 16 | struct UsdLibrary : public anari::LibraryImpl { 17 | UsdLibrary(void *lib, ANARIStatusCallback defaultStatusCB, 18 | const void *statusCBPtr); 19 | 20 | ANARIDevice newDevice(const char *subtype) override; 21 | const char **getDeviceExtensions(const char *deviceType) override; 22 | }; 23 | 24 | // Definitions //////////////////////////////////////////////////////////////// 25 | 26 | UsdLibrary::UsdLibrary(void *lib, ANARIStatusCallback defaultStatusCB, 27 | const void *statusCBPtr) 28 | : anari::LibraryImpl(lib, defaultStatusCB, statusCBPtr) {} 29 | 30 | ANARIDevice UsdLibrary::newDevice(const char * /*subtype*/) { 31 | return (ANARIDevice) new UsdDevice(this_library()); 32 | } 33 | 34 | const char **UsdLibrary::getDeviceExtensions(const char * /*deviceType*/) { 35 | return query_extensions(); 36 | } 37 | 38 | } // namespace usd 39 | } // namespace anari 40 | 41 | // Define library entrypoint ////////////////////////////////////////////////// 42 | 43 | extern "C" USDDevice_INTERFACE 44 | ANARI_DEFINE_LIBRARY_ENTRYPOINT(usd, handle, scb, scbPtr) { 45 | return (ANARILibrary) new anari::usd::UsdLibrary(handle, scb, scbPtr); 46 | } 47 | -------------------------------------------------------------------------------- /UsdLight.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdLight.h" 5 | #include "UsdAnari.h" 6 | #include "UsdDevice.h" 7 | 8 | DEFINE_PARAMETER_MAP(UsdLight, 9 | REGISTER_PARAMETER_MACRO("name", ANARI_STRING, name) 10 | REGISTER_PARAMETER_MACRO("usd::name", ANARI_STRING, usdName) 11 | ) 12 | 13 | UsdLight::UsdLight(const char* type, const char* name, UsdDevice* device) 14 | : BridgedBaseObjectType(ANARI_LIGHT, name, device) 15 | {} 16 | 17 | UsdLight::~UsdLight() 18 | {} 19 | 20 | void UsdLight::remove(UsdDevice* device) 21 | { 22 | //applyRemoveFunc(device, &UsdBridge::DeleteLight); 23 | } 24 | 25 | bool UsdLight::deferCommit(UsdDevice* device) 26 | { 27 | return false; 28 | } 29 | 30 | bool UsdLight::doCommitData(UsdDevice* device) 31 | { 32 | return false; 33 | } -------------------------------------------------------------------------------- /UsdLight.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridgedBaseObject.h" 7 | 8 | struct UsdLightData 9 | { 10 | UsdSharedString* name = nullptr; 11 | UsdSharedString* usdName = nullptr; 12 | }; 13 | 14 | class UsdLight : public UsdBridgedBaseObject 15 | { 16 | public: 17 | UsdLight( 18 | const char* type, 19 | const char* name, 20 | UsdDevice* device); 21 | ~UsdLight(); 22 | 23 | void remove(UsdDevice* device) override; 24 | 25 | protected: 26 | bool deferCommit(UsdDevice* device) override; 27 | bool doCommitData(UsdDevice* device) override; 28 | void doCommitRefs(UsdDevice* device) override {} 29 | }; 30 | -------------------------------------------------------------------------------- /UsdMaterial.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridgedBaseObject.h" 7 | #include "UsdBridgeNumerics.h" 8 | #include "UsdDeviceUtils.h" 9 | #include 10 | 11 | class UsdSampler; 12 | class UsdGeometryData; 13 | 14 | template 15 | using UsdMaterialMultiTypeParameter = UsdMultiTypeParameter; 16 | 17 | enum class UsdMaterialDataComponents 18 | { 19 | COLOR = 0, 20 | OPACITY, 21 | EMISSIVE, 22 | EMISSIVEFACTOR, 23 | ROUGHNESS, 24 | METALLIC, 25 | IOR 26 | }; 27 | 28 | struct UsdMaterialData 29 | { 30 | UsdSharedString* name = nullptr; 31 | UsdSharedString* usdName = nullptr; 32 | 33 | double timeStep = std::numeric_limits::quiet_NaN(); 34 | int timeVarying = 0; // Bitmask indicating which attributes are time-varying. 35 | 36 | // Standard parameters 37 | UsdMaterialMultiTypeParameter color = {{ 1.0f, 1.0f, 1.0f }, ANARI_FLOAT32_VEC3}; 38 | UsdMaterialMultiTypeParameter opacity = {1.0f, ANARI_FLOAT32}; 39 | UsdSharedString* alphaMode = nullptr; // Timevarying state linked to opacity 40 | float alphaCutoff = 0.5f; // Timevarying state linked to opacity 41 | 42 | // Possible PBR parameters 43 | UsdMaterialMultiTypeParameter emissiveColor = {{ 1.0f, 1.0f, 1.0f }, ANARI_FLOAT32_VEC3}; 44 | UsdMaterialMultiTypeParameter emissiveIntensity = {0.0f, ANARI_FLOAT32}; 45 | UsdMaterialMultiTypeParameter roughness = {0.5f, ANARI_FLOAT32}; 46 | UsdMaterialMultiTypeParameter metallic = {0.0f, ANARI_FLOAT32}; 47 | UsdMaterialMultiTypeParameter ior = {1.0f, ANARI_FLOAT32}; 48 | 49 | double colorSamplerTimeStep = std::numeric_limits::quiet_NaN(); 50 | double opacitySamplerTimeStep = std::numeric_limits::quiet_NaN(); 51 | double emissiveSamplerTimeStep = std::numeric_limits::quiet_NaN(); 52 | double emissiveIntensitySamplerTimeStep = std::numeric_limits::quiet_NaN(); 53 | double roughnessSamplerTimeStep = std::numeric_limits::quiet_NaN(); 54 | double metallicSamplerTimeStep = std::numeric_limits::quiet_NaN(); 55 | double iorSamplerTimeStep = std::numeric_limits::quiet_NaN(); 56 | }; 57 | 58 | class UsdMaterial : public UsdBridgedBaseObject 59 | { 60 | public: 61 | using MaterialDMI = UsdBridgeMaterialData::DataMemberId; 62 | 63 | UsdMaterial(const char* name, const char* type, UsdDevice* device); 64 | ~UsdMaterial(); 65 | 66 | void remove(UsdDevice* device) override; 67 | 68 | bool isPerInstance() const { return perInstance; } 69 | void updateBoundParameters(bool boundToInstance, const UsdGeometryData& geomParamData, UsdDevice* device); 70 | 71 | static constexpr ComponentPair componentParamNames[] = { 72 | ComponentPair(UsdMaterialDataComponents::COLOR, "color"), 73 | ComponentPair(UsdMaterialDataComponents::COLOR, "baseColor"), 74 | ComponentPair(UsdMaterialDataComponents::OPACITY, "opacity"), 75 | ComponentPair(UsdMaterialDataComponents::EMISSIVE, "emissive"), 76 | ComponentPair(UsdMaterialDataComponents::EMISSIVEFACTOR, "emissiveIntensity"), 77 | ComponentPair(UsdMaterialDataComponents::ROUGHNESS, "roughness"), 78 | ComponentPair(UsdMaterialDataComponents::METALLIC, "metallic"), 79 | ComponentPair(UsdMaterialDataComponents::IOR, "ior")}; 80 | 81 | protected: 82 | using MaterialInputAttribNamePair = std::pair; 83 | 84 | template 85 | void changeMaterialInputSourceName(const UsdMaterialMultiTypeParameter& param, 86 | MaterialDMI dataMemberId, const UsdGeometryData& geomParamData, UsdDevice* device, const UsdLogInfo& logInfo); 87 | 88 | template 89 | bool getSamplerRefData(const UsdMaterialMultiTypeParameter& param, double refTimeStep, 90 | MaterialDMI dataMemberId, UsdDevice* device, const UsdLogInfo& logInfo); 91 | 92 | template 93 | void assignParameterToMaterialInput( 94 | const UsdMaterialMultiTypeParameter& param, 95 | UsdBridgeMaterialData::MaterialInput& matInput, 96 | const UsdLogInfo& logInfo); 97 | 98 | bool deferCommit(UsdDevice* device) override; 99 | bool doCommitData(UsdDevice* device) override; 100 | void doCommitRefs(UsdDevice* device) override; 101 | 102 | void setMaterialTimeVarying(UsdBridgeMaterialData::DataMemberId& timeVarying); 103 | 104 | bool isPbr = false; 105 | 106 | bool perInstance = false; // Whether material is attached to a point instancer 107 | 108 | OptionalList materialInputAttributes; 109 | OptionalList samplerHandles; 110 | OptionalList samplerRefDatas; 111 | }; -------------------------------------------------------------------------------- /UsdMultiTypeParameter.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdAnari.h" 7 | #include "anari/anari_cpp/Traits.h" 8 | 9 | template 10 | struct UsdMultiTypeParameter 11 | { 12 | using CDataType0 = T0; 13 | using CDataType1 = T1; 14 | using CDataType2 = T2; 15 | 16 | union DataUnion 17 | { 18 | T0 type0; 19 | T1 type1; 20 | T2 type2; 21 | }; 22 | 23 | DataUnion data; 24 | ANARIDataType type; 25 | 26 | // Helper functions 27 | T0& Get(T0& arg) const 28 | { 29 | if(AnariTypeMatchesCType(type)) { arg = data.type0; } 30 | return arg; 31 | } 32 | 33 | T1& Get(T1& arg) const 34 | { 35 | if(AnariTypeMatchesCType(type)) { arg = data.type1; } 36 | return arg; 37 | } 38 | 39 | T2& Get(T2& arg) const 40 | { 41 | if(AnariTypeMatchesCType(type)) { arg = data.type2; } 42 | return arg; 43 | } 44 | }; 45 | 46 | 47 | -------------------------------------------------------------------------------- /UsdRenderer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdRenderer.h" 5 | #include "UsdBridge/UsdBridge.h" 6 | #include "UsdAnari.h" 7 | #include "UsdDevice.h" 8 | #include "UsdDeviceQueries.h" 9 | 10 | DEFINE_PARAMETER_MAP(UsdRenderer, 11 | ) 12 | 13 | UsdRenderer::UsdRenderer() 14 | : UsdParameterizedBaseObject(ANARI_RENDERER) 15 | { 16 | } 17 | 18 | UsdRenderer::~UsdRenderer() 19 | { 20 | } 21 | 22 | int UsdRenderer::getProperty(const char * name, ANARIDataType type, void * mem, uint64_t size, UsdDevice* device) 23 | { 24 | if (strEquals(name, "extension") && type == ANARI_STRING_LIST) 25 | { 26 | writeToVoidP(mem, anari::usd::query_extensions()); 27 | return 1; 28 | } 29 | 30 | return 0; 31 | } 32 | 33 | bool UsdRenderer::deferCommit(UsdDevice* device) 34 | { 35 | return false; 36 | } 37 | 38 | bool UsdRenderer::doCommitData(UsdDevice* device) 39 | { 40 | return false; 41 | } 42 | -------------------------------------------------------------------------------- /UsdRenderer.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBaseObject.h" 7 | #include "UsdParameterizedObject.h" 8 | 9 | struct UsdRendererData 10 | { 11 | 12 | }; 13 | 14 | class UsdRenderer : public UsdParameterizedBaseObject 15 | { 16 | public: 17 | UsdRenderer(); 18 | ~UsdRenderer(); 19 | 20 | void remove(UsdDevice* device) override {} 21 | 22 | int getProperty(const char * name, ANARIDataType type, void * mem, uint64_t size, UsdDevice* device) override; 23 | 24 | protected: 25 | bool deferCommit(UsdDevice* device) override; 26 | bool doCommitData(UsdDevice* device) override; 27 | void doCommitRefs(UsdDevice* device) override {} 28 | 29 | UsdBridge* usdBridge; 30 | }; 31 | -------------------------------------------------------------------------------- /UsdSampler.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdSampler.h" 5 | #include "UsdAnari.h" 6 | #include "UsdDevice.h" 7 | #include "UsdDataArray.h" 8 | 9 | DEFINE_PARAMETER_MAP(UsdSampler, 10 | REGISTER_PARAMETER_MACRO("name", ANARI_STRING, name) 11 | REGISTER_PARAMETER_MACRO("usd::name", ANARI_STRING, usdName) 12 | REGISTER_PARAMETER_MACRO("usd::time", ANARI_FLOAT64, timeStep) 13 | REGISTER_PARAMETER_MACRO("usd::timeVarying", ANARI_INT32, timeVarying) 14 | REGISTER_PARAMETER_MACRO("usd::imageUrl", ANARI_STRING, imageUrl) 15 | REGISTER_PARAMETER_MACRO("inAttribute", ANARI_STRING, inAttribute) 16 | REGISTER_PARAMETER_MACRO("image", ANARI_ARRAY, imageData) 17 | REGISTER_PARAMETER_MACRO("wrapMode", ANARI_STRING, wrapS) 18 | REGISTER_PARAMETER_MACRO("wrapMode1", ANARI_STRING, wrapS) 19 | REGISTER_PARAMETER_MACRO("wrapMode2", ANARI_STRING, wrapT) 20 | REGISTER_PARAMETER_MACRO("wrapMode3", ANARI_STRING, wrapR) 21 | ) 22 | 23 | constexpr UsdSampler::ComponentPair UsdSampler::componentParamNames[]; // Workaround for C++14's lack of inlining constexpr arrays 24 | 25 | namespace 26 | { 27 | UsdBridgeSamplerData::WrapMode ANARIToUsdBridgeWrapMode(const char* anariWrapMode) 28 | { 29 | UsdBridgeSamplerData::WrapMode usdWrapMode = UsdBridgeSamplerData::WrapMode::BLACK; 30 | if(anariWrapMode) 31 | { 32 | if (strEquals(anariWrapMode, "clampToEdge")) 33 | { 34 | usdWrapMode = UsdBridgeSamplerData::WrapMode::CLAMP; 35 | } 36 | else if (strEquals(anariWrapMode, "repeat")) 37 | { 38 | usdWrapMode = UsdBridgeSamplerData::WrapMode::REPEAT; 39 | } 40 | else if (strEquals(anariWrapMode, "mirrorRepeat")) 41 | { 42 | usdWrapMode = UsdBridgeSamplerData::WrapMode::MIRROR; 43 | } 44 | } 45 | return usdWrapMode; 46 | } 47 | } 48 | 49 | UsdSampler::UsdSampler(const char* name, const char* type, UsdDevice* device) 50 | : BridgedBaseObjectType(ANARI_SAMPLER, name, device) 51 | { 52 | if (strEquals(type, "image1D")) 53 | samplerType = SAMPLER_1D; 54 | else if (strEquals(type, "image2D")) 55 | samplerType = SAMPLER_2D; 56 | else if (strEquals(type, "image3D")) 57 | samplerType = SAMPLER_3D; 58 | else 59 | device->reportStatus(this, ANARI_SAMPLER, ANARI_SEVERITY_ERROR, ANARI_STATUS_INVALID_ARGUMENT, "UsdSampler '%s' construction failed: type %s not supported", getName(), name); 60 | } 61 | 62 | UsdSampler::~UsdSampler() 63 | { 64 | #ifdef OBJECT_LIFETIME_EQUALS_USD_LIFETIME 65 | if(cachedBridge) 66 | cachedBridge->DeleteSampler(usdHandle); 67 | #endif 68 | } 69 | 70 | void UsdSampler::remove(UsdDevice* device) 71 | { 72 | applyRemoveFunc(device, &UsdBridge::DeleteSampler); 73 | } 74 | 75 | void UsdSampler::updateBoundParameters(bool boundToInstance, const UsdSharedString*const* attribNames, size_t numAttribNames, UsdDevice* device) 76 | { 77 | UsdBridge* usdBridge = device->getUsdBridge(); 78 | 79 | if(!usdHandle.value) 80 | return; 81 | 82 | perInstance = boundToInstance; 83 | 84 | UsdLogInfo logInfo(device, this, ANARI_SAMPLER, getName()); 85 | 86 | // Fix up the position attribute 87 | const UsdSamplerData& paramData = getReadParams(); 88 | const char* inAttribName = UsdSharedString::c_str(paramData.inAttribute); 89 | 90 | auto [hasMeshDependentAttribs, meshDependentAttribName] = 91 | GetGeomDependentAttributeName(inAttribName, perInstance, attribNames, numAttribNames, logInfo); 92 | 93 | if(hasMeshDependentAttribs) 94 | { 95 | double worldTimeStep = device->getReadParams().timeStep; 96 | double dataTimeStep = selectObjTime(paramData.timeStep, worldTimeStep); 97 | 98 | UsdBridgeSamplerData::DataMemberId timeVarying; 99 | setSamplerTimeVarying(timeVarying); 100 | 101 | usdBridge->ChangeInAttribute(usdHandle, meshDependentAttribName, dataTimeStep, timeVarying); 102 | } 103 | } 104 | 105 | bool UsdSampler::deferCommit(UsdDevice* device) 106 | { 107 | return false; 108 | } 109 | 110 | bool UsdSampler::doCommitData(UsdDevice* device) 111 | { 112 | UsdBridge* usdBridge = device->getUsdBridge(); 113 | 114 | if(!device->getReadParams().outputMaterial || 115 | samplerType == SAMPLER_UNKNOWN) 116 | return false; 117 | 118 | const UsdSamplerData& paramData = getReadParams(); 119 | 120 | UsdBridgeSamplerData::SamplerType type = 121 | (samplerType == SAMPLER_1D ? UsdBridgeSamplerData::SamplerType::SAMPLER_1D : 122 | (samplerType == SAMPLER_2D ? UsdBridgeSamplerData::SamplerType::SAMPLER_2D : 123 | UsdBridgeSamplerData::SamplerType::SAMPLER_3D 124 | ) 125 | ); 126 | 127 | bool isNew = false; 128 | if (!usdHandle.value) 129 | isNew = usdBridge->CreateSampler(getName(), usdHandle, type); 130 | 131 | if (paramChanged || isNew) 132 | { 133 | if (paramData.inAttribute && (std::strlen(UsdSharedString::c_str(paramData.inAttribute)) > 0) 134 | && (paramData.imageUrl || paramData.imageData)) 135 | { 136 | bool supportedImage = true; 137 | int numComponents = 0; 138 | if(paramData.imageData) 139 | { 140 | numComponents = static_cast(anari::componentsOf(paramData.imageData->getType())); 141 | 142 | if(numComponents > 4) 143 | device->reportStatus(this, ANARI_SAMPLER, ANARI_SEVERITY_WARNING, ANARI_STATUS_INVALID_ARGUMENT, 144 | "UsdSampler '%s' image data has more than 4 components. Anything above the 4th component will be ignored.", paramData.imageData->getName()); 145 | } 146 | 147 | if(supportedImage) 148 | { 149 | UsdLogInfo logInfo(device, this, ANARI_SAMPLER, getName()); 150 | 151 | UsdBridgeSamplerData samplerData; 152 | samplerData.Type = type; 153 | 154 | double worldTimeStep = device->getReadParams().timeStep; 155 | double dataTimeStep = selectObjTime(paramData.timeStep, worldTimeStep); 156 | 157 | samplerData.InAttribute = AnariAttributeToUsdName(UsdSharedString::c_str(paramData.inAttribute), perInstance, logInfo); 158 | 159 | if(paramData.imageUrl) 160 | { 161 | samplerData.ImageUrl = UsdSharedString::c_str(paramData.imageUrl); 162 | } 163 | 164 | if(paramData.imageData) 165 | { 166 | samplerData.Data = paramData.imageData->getData(); 167 | samplerData.ImageName = paramData.imageData->getName(); 168 | samplerData.ImageNumComponents = numComponents; 169 | samplerData.DataType = AnariToUsdBridgeType(paramData.imageData->getType()); 170 | paramData.imageData->getLayout().copyDims(samplerData.ImageDims); 171 | paramData.imageData->getLayout().copyStride(samplerData.ImageStride); 172 | } 173 | 174 | samplerData.WrapS = ANARIToUsdBridgeWrapMode(UsdSharedString::c_str(paramData.wrapS)); 175 | samplerData.WrapT = ANARIToUsdBridgeWrapMode(UsdSharedString::c_str(paramData.wrapT)); 176 | samplerData.WrapR = ANARIToUsdBridgeWrapMode(UsdSharedString::c_str(paramData.wrapR)); 177 | 178 | setSamplerTimeVarying(samplerData.TimeVarying); 179 | 180 | usdBridge->SetSamplerData(usdHandle, samplerData, dataTimeStep); 181 | } 182 | } 183 | else 184 | { 185 | device->reportStatus(this, ANARI_SAMPLER, ANARI_SEVERITY_ERROR, ANARI_STATUS_INVALID_ARGUMENT, 186 | "UsdSampler '%s' commit failed: missing either the 'inAttribute', or both the 'image' and 'usd::imageUrl' parameter", getName()); 187 | } 188 | 189 | paramChanged = false; 190 | } 191 | 192 | return false; 193 | } 194 | 195 | void UsdSampler::setSamplerTimeVarying(UsdBridgeSamplerData::DataMemberId& timeVarying) 196 | { 197 | typedef UsdBridgeSamplerData::DataMemberId DMI; 198 | 199 | timeVarying = DMI::ALL 200 | & (isTimeVarying(CType::DATA) ? DMI::ALL : ~DMI::DATA) 201 | & (isTimeVarying(CType::WRAPS) ? DMI::ALL : ~DMI::WRAPS) 202 | & (isTimeVarying(CType::WRAPT) ? DMI::ALL : ~DMI::WRAPT) 203 | & (isTimeVarying(CType::WRAPR) ? DMI::ALL : ~DMI::WRAPR); 204 | } 205 | -------------------------------------------------------------------------------- /UsdSampler.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridgedBaseObject.h" 7 | 8 | enum class UsdSamplerComponents 9 | { 10 | DATA = 0, 11 | WRAPS, 12 | WRAPT, 13 | WRAPR 14 | }; 15 | 16 | struct UsdSamplerData 17 | { 18 | UsdSharedString* name = nullptr; 19 | UsdSharedString* usdName = nullptr; 20 | 21 | double timeStep = std::numeric_limits::quiet_NaN(); 22 | int timeVarying = 0; // Bitmask indicating which attributes are time-varying. 23 | 24 | const UsdDataArray* imageData = nullptr; 25 | 26 | UsdSharedString* inAttribute = nullptr; 27 | UsdSharedString* imageUrl = nullptr; 28 | UsdSharedString* wrapS = nullptr; 29 | UsdSharedString* wrapT = nullptr; 30 | UsdSharedString* wrapR = nullptr; 31 | }; 32 | 33 | class UsdSampler : public UsdBridgedBaseObject 34 | { 35 | protected: 36 | enum SamplerType 37 | { 38 | SAMPLER_UNKNOWN = 0, 39 | SAMPLER_1D, 40 | SAMPLER_2D, 41 | SAMPLER_3D 42 | }; 43 | 44 | public: 45 | UsdSampler(const char* name, const char* type, UsdDevice* device); 46 | ~UsdSampler(); 47 | 48 | void remove(UsdDevice* device) override; 49 | 50 | bool isPerInstance() const { return perInstance; } 51 | void updateBoundParameters(bool boundToInstance, const UsdSharedString*const* attribNames, size_t numAttribNames, UsdDevice* device); 52 | 53 | static constexpr ComponentPair componentParamNames[] = { 54 | ComponentPair(CType::DATA, "image"), 55 | ComponentPair(CType::DATA, "imageUrl"), 56 | ComponentPair(CType::WRAPS, "wrapMode"), 57 | ComponentPair(CType::WRAPS, "wrapMode1"), 58 | ComponentPair(CType::WRAPT, "wrapMode2"), 59 | ComponentPair(CType::WRAPR, "wrapMode3")}; 60 | 61 | protected: 62 | bool deferCommit(UsdDevice* device) override; 63 | bool doCommitData(UsdDevice* device) override; 64 | void doCommitRefs(UsdDevice* device) override {} 65 | 66 | void setSamplerTimeVarying(UsdBridgeSamplerData::DataMemberId& timeVarying); 67 | 68 | SamplerType samplerType = SAMPLER_UNKNOWN; 69 | 70 | bool perInstance = false; // Whether sampler is attached to a point instancer 71 | bool instanceAttributeAttached = false; // Whether a value to inAttribute has been set which in USD is different between per-instance and regular geometries 72 | }; -------------------------------------------------------------------------------- /UsdSharedObjects.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "helium/utility/IntrusivePtr.h" 7 | #include "UsdCommonMacros.h" 8 | 9 | #include 10 | 11 | template 12 | class UsdRefCountWrapped : public helium::RefCounted 13 | { 14 | public: 15 | UsdRefCountWrapped(InitType i) 16 | : data(i) 17 | {} 18 | 19 | BaseType data; 20 | }; 21 | 22 | class UsdSharedString : public UsdRefCountWrapped 23 | { 24 | public: 25 | UsdSharedString(const char* cStr) 26 | : UsdRefCountWrapped(cStr) 27 | {} 28 | 29 | static const char* c_str(const UsdSharedString* string) { return string ? string->c_str() : nullptr; } 30 | const char* c_str() const { return data.c_str(); } 31 | }; -------------------------------------------------------------------------------- /UsdSpatialField.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdSpatialField.h" 5 | #include "UsdAnari.h" 6 | #include "UsdDataArray.h" 7 | #include "UsdDevice.h" 8 | #include "UsdVolume.h" 9 | 10 | #include 11 | 12 | DEFINE_PARAMETER_MAP(UsdSpatialField, 13 | REGISTER_PARAMETER_MACRO("name", ANARI_STRING, name) 14 | REGISTER_PARAMETER_MACRO("usd::name", ANARI_STRING, usdName) 15 | REGISTER_PARAMETER_MACRO("usd::time", ANARI_FLOAT64, timeStep) 16 | REGISTER_PARAMETER_MACRO("usd::timeVarying", ANARI_INT32, timeVarying) 17 | REGISTER_PARAMETER_MACRO("data", ANARI_ARRAY, data) 18 | REGISTER_PARAMETER_MACRO("spacing", ANARI_FLOAT32_VEC3, gridSpacing) 19 | REGISTER_PARAMETER_MACRO("origin", ANARI_FLOAT32_VEC3, gridOrigin) 20 | ) // See .h for usage. 21 | 22 | constexpr UsdSpatialField::ComponentPair UsdSpatialField::componentParamNames[]; // Workaround for C++14's lack of inlining constexpr arrays 23 | 24 | UsdSpatialField::UsdSpatialField(const char* name, const char* type, UsdDevice* device) 25 | : BridgedBaseObjectType(ANARI_SPATIAL_FIELD, name, device) 26 | { 27 | } 28 | 29 | UsdSpatialField::~UsdSpatialField() 30 | { 31 | #ifdef OBJECT_LIFETIME_EQUALS_USD_LIFETIME 32 | if(cachedBridge) 33 | cachedBridge->DeleteSpatialField(usdHandle); 34 | #endif 35 | } 36 | 37 | void UsdSpatialField::commit(UsdDevice* device) 38 | { 39 | // Notify observers (such as volume) that the spatial field has changed. 40 | notify(this, device); 41 | 42 | // Continue with the normal commit, ie. adding to the commit list or immediate execution of doCommitData 43 | BridgedBaseObjectType::commit(device); 44 | } 45 | 46 | void UsdSpatialField::remove(UsdDevice* device) 47 | { 48 | applyRemoveFunc(device, &UsdBridge::DeleteSpatialField); 49 | } 50 | 51 | bool UsdSpatialField::deferCommit(UsdDevice* device) 52 | { 53 | // Always defer until flushing of commit list, to give parent volumes the possibility to detect which of its child fields have been committed, 54 | // such that those volumes with committed children are also automatically committed. 55 | return !device->isFlushingCommitList(); 56 | } 57 | 58 | bool UsdSpatialField::doCommitData(UsdDevice* device) 59 | { 60 | UsdBridge* usdBridge = device->getUsdBridge(); 61 | 62 | const UsdSpatialFieldData& paramData = getReadParams(); 63 | 64 | const char* debugName = getName(); 65 | UsdLogInfo logInfo(device, this, ANARI_SPATIAL_FIELD, debugName); 66 | 67 | bool isNew = false; 68 | if(!usdHandle.value) 69 | isNew = usdBridge->CreateSpatialField(debugName, usdHandle); 70 | 71 | // Only perform type checks, actual data gets uploaded during UsdVolume::commit() 72 | const UsdDataArray* fieldDataArray = paramData.data; 73 | if (!fieldDataArray) 74 | { 75 | device->reportStatus(this, ANARI_SPATIAL_FIELD, ANARI_SEVERITY_ERROR, ANARI_STATUS_INVALID_OPERATION, 76 | "UsdSpatialField '%s' commit failed: data missing.", debugName); 77 | return false; 78 | } 79 | 80 | const UsdDataLayout& dataLayout = fieldDataArray->getLayout(); 81 | if (!AssertNoStride(dataLayout, logInfo, "data")) 82 | return false; 83 | 84 | switch (fieldDataArray->getType()) 85 | { 86 | case ANARI_INT8: 87 | case ANARI_UINT8: 88 | case ANARI_INT16: 89 | case ANARI_UINT16: 90 | case ANARI_INT32: 91 | case ANARI_UINT32: 92 | case ANARI_INT64: 93 | case ANARI_UINT64: 94 | case ANARI_FLOAT32: 95 | case ANARI_FLOAT64: 96 | break; 97 | default: 98 | device->reportStatus(this, ANARI_SPATIAL_FIELD, ANARI_SEVERITY_ERROR, ANARI_STATUS_INVALID_ARGUMENT, 99 | "UsdSpatialField '%s' commit failed: incompatible data type.", debugName); 100 | return false; 101 | } 102 | 103 | // Make sure that parameters are set a first time 104 | paramChanged = paramChanged || isNew; 105 | 106 | return false; 107 | } -------------------------------------------------------------------------------- /UsdSpatialField.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridgedBaseObject.h" 7 | 8 | class UsdDataArray; 9 | class UsdVolume; 10 | 11 | enum class UsdSpatialFieldComponents 12 | { 13 | DATA = 0 // includes spacing and origin 14 | }; 15 | 16 | struct UsdSpatialFieldData 17 | { 18 | UsdSharedString* name = nullptr; 19 | UsdSharedString* usdName = nullptr; 20 | 21 | double timeStep = std::numeric_limits::quiet_NaN(); 22 | int timeVarying = 0xFFFFFFFF; // Bitmask indicating which attributes are time-varying. 23 | 24 | const UsdDataArray* data = nullptr; 25 | 26 | float gridSpacing[3] = {1.0f, 1.0f, 1.0f}; 27 | float gridOrigin[3] = {1.0f, 1.0f, 1.0f}; 28 | 29 | //int filter = 0; 30 | //int gradientFilter = 0; 31 | }; 32 | 33 | class UsdSpatialField : public UsdBridgedBaseObject 34 | { 35 | public: 36 | UsdSpatialField(const char* name, const char* type, UsdDevice* device); 37 | ~UsdSpatialField(); 38 | 39 | void commit(UsdDevice* device) override; 40 | 41 | void remove(UsdDevice* device) override; 42 | 43 | friend class UsdVolume; 44 | 45 | static constexpr ComponentPair componentParamNames[] = { 46 | ComponentPair(UsdSpatialFieldComponents::DATA, "data")}; 47 | 48 | protected: 49 | bool deferCommit(UsdDevice* device) override; 50 | bool doCommitData(UsdDevice* device) override; 51 | void doCommitRefs(UsdDevice* device) override {} 52 | 53 | void toBridge(UsdDevice* device, const char* debugName); 54 | }; -------------------------------------------------------------------------------- /UsdSurface.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdSurface.h" 5 | #include "UsdAnari.h" 6 | #include "UsdDevice.h" 7 | #include "UsdMaterial.h" 8 | #include "UsdGeometry.h" 9 | 10 | #define GeometryType ANARI_GEOMETRY 11 | #define MaterialType ANARI_MATERIAL 12 | using GeometryUsdType = AnariToUsdBridgedObject::Type; 13 | using MaterialUsdType = AnariToUsdBridgedObject::Type; 14 | 15 | DEFINE_PARAMETER_MAP(UsdSurface, 16 | REGISTER_PARAMETER_MACRO("name", ANARI_STRING, name) 17 | REGISTER_PARAMETER_MACRO("usd::name", ANARI_STRING, usdName) 18 | REGISTER_PARAMETER_MACRO("usd::time.geometry", ANARI_FLOAT64, geometryRefTimeStep) 19 | REGISTER_PARAMETER_MACRO("usd::time.material", ANARI_FLOAT64, materialRefTimeStep) 20 | REGISTER_PARAMETER_MACRO("geometry", GeometryType, geometry) 21 | REGISTER_PARAMETER_MACRO("material", MaterialType, material) 22 | REGISTER_PARAMETER_MACRO("usd::isInstanceable", ANARI_BOOL, isInstanceable) 23 | ) 24 | 25 | UsdSurface::UsdSurface(const char* name, UsdDevice* device) 26 | : BridgedBaseObjectType(ANARI_SURFACE, name, device) 27 | { 28 | } 29 | 30 | UsdSurface::~UsdSurface() 31 | { 32 | #ifdef OBJECT_LIFETIME_EQUALS_USD_LIFETIME 33 | // Given that the object is destroyed, none of its references to other objects 34 | // has to be updated anymore. 35 | if(cachedBridge) 36 | cachedBridge->DeleteSurface(usdHandle); 37 | #endif 38 | } 39 | 40 | void UsdSurface::remove(UsdDevice* device) 41 | { 42 | applyRemoveFunc(device, &UsdBridge::DeleteSurface); 43 | } 44 | 45 | bool UsdSurface::isInstanceable() const 46 | { 47 | const UsdSurfaceData& paramData = getReadParams(); 48 | return paramData.isInstanceable; 49 | } 50 | 51 | bool UsdSurface::deferCommit(UsdDevice* device) 52 | { 53 | // Given that all handles/data are used in doCommitRefs, which is always executed deferred, we don't need to check for initialization 54 | 55 | //const UsdSurfaceData& paramData = getReadParams(); 56 | //if(UsdObjectNotInitialized(paramData.geometry) || UsdObjectNotInitialized(paramData.material)) 57 | //{ 58 | // return true; 59 | //} 60 | return false; 61 | } 62 | 63 | bool UsdSurface::doCommitData(UsdDevice* device) 64 | { 65 | UsdBridge* usdBridge = device->getUsdBridge(); 66 | const UsdSurfaceData& paramData = getReadParams(); 67 | 68 | bool isNew = false; 69 | if (!usdHandle.value) 70 | isNew = usdBridge->CreateSurface(getName(), usdHandle); 71 | 72 | if (paramChanged || isNew) 73 | { 74 | paramChanged = false; 75 | updateBoundParameters = true; 76 | 77 | return true; // In this case a doCommitRefs is required, with data (timesteps, handles) from children 78 | } 79 | 80 | return updateBoundParameters; // Update the bound parameters after they have been committed on geometry/material 81 | } 82 | 83 | void UsdSurface::doCommitRefs(UsdDevice* device) 84 | { 85 | UsdBridge* usdBridge = device->getUsdBridge(); 86 | const UsdSurfaceData& paramData = getReadParams(); 87 | 88 | double worldTimeStep = device->getReadParams().timeStep; 89 | 90 | bool hasGeometry = paramData.geometry; 91 | bool hasMaterial = device->getReadParams().outputMaterial && paramData.material; 92 | if(hasGeometry && hasMaterial && updateBoundParameters) 93 | { 94 | const UsdGeometryData& geomParamData = paramData.geometry->getReadParams(); 95 | 96 | // The geometry to which a material binds has an effect on attribute reader (geom primvar) names, and output types 97 | paramData.material->updateBoundParameters(paramData.geometry->isInstanced(), geomParamData, device); 98 | 99 | updateBoundParameters = false; 100 | } 101 | 102 | // Make sure the references are updated on the Bridge side. 103 | if (hasGeometry) 104 | { 105 | const UsdGeometryData& geomParamData = paramData.geometry->getReadParams(); 106 | double geomObjTimeStep = geomParamData.timeStep; 107 | 108 | if(hasMaterial) 109 | { 110 | double matObjTimeStep = paramData.material->getReadParams().timeStep; 111 | 112 | usdBridge->SetGeometryMaterialRef(usdHandle, 113 | paramData.geometry->getUsdHandle(), 114 | paramData.material->getUsdHandle(), 115 | worldTimeStep, 116 | selectRefTime(paramData.geometryRefTimeStep, geomObjTimeStep, worldTimeStep), 117 | selectRefTime(paramData.materialRefTimeStep, matObjTimeStep, worldTimeStep) 118 | ); 119 | } 120 | else 121 | { 122 | usdBridge->SetGeometryRef(usdHandle, 123 | paramData.geometry->getUsdHandle(), 124 | worldTimeStep, 125 | selectRefTime(paramData.geometryRefTimeStep, geomObjTimeStep, worldTimeStep) 126 | ); 127 | usdBridge->DeleteMaterialRef(usdHandle, worldTimeStep); 128 | } 129 | } 130 | else 131 | { 132 | usdBridge->DeleteGeometryRef(usdHandle, worldTimeStep); 133 | 134 | if (!paramData.material && device->getReadParams().outputMaterial) 135 | { 136 | usdBridge->DeleteMaterialRef(usdHandle, worldTimeStep); 137 | } 138 | } 139 | } 140 | 141 | void UsdSurface::onParamRefChanged(UsdBaseObject* paramObject, bool incRef, bool onWriteParams) 142 | { 143 | if(!onWriteParams && paramObject->getType() == ANARI_GEOMETRY) 144 | { 145 | if(incRef) 146 | paramObject->addObserver(this); 147 | else 148 | paramObject->removeObserver(this); 149 | } 150 | 151 | BridgedBaseObjectType::onParamRefChanged(paramObject, incRef, onWriteParams); 152 | } 153 | 154 | void UsdSurface::observe(UsdBaseObject* caller, UsdDevice* device) 155 | { 156 | if(caller->getType() == ANARI_GEOMETRY) 157 | { 158 | updateBoundParameters = true; 159 | device->addToCommitList(this, true); // No write to read params; just write to USD 160 | } 161 | 162 | BridgedBaseObjectType::observe(caller, device); 163 | } -------------------------------------------------------------------------------- /UsdSurface.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridgedBaseObject.h" 7 | 8 | #include 9 | 10 | class UsdGeometry; 11 | class UsdMaterial; 12 | 13 | struct UsdSurfaceData 14 | { 15 | UsdSharedString* name = nullptr; 16 | UsdSharedString* usdName = nullptr; 17 | 18 | // No timevarying data: geometry and material reference always set over all timesteps 19 | 20 | UsdGeometry* geometry = nullptr; 21 | UsdMaterial* material = nullptr; 22 | 23 | double geometryRefTimeStep = std::numeric_limits::quiet_NaN(); 24 | double materialRefTimeStep = std::numeric_limits::quiet_NaN(); 25 | 26 | bool isInstanceable = false; 27 | }; 28 | 29 | class UsdSurface : public UsdBridgedBaseObject 30 | { 31 | public: 32 | UsdSurface(const char* name, UsdDevice* device); 33 | ~UsdSurface(); 34 | 35 | void remove(UsdDevice* device) override; 36 | 37 | bool isInstanceable() const; 38 | 39 | protected: 40 | bool deferCommit(UsdDevice* device) override; 41 | bool doCommitData(UsdDevice* device) override; 42 | void doCommitRefs(UsdDevice* device) override; 43 | 44 | void onParamRefChanged(UsdBaseObject* paramObject, bool incRef, bool onWriteParams) override; 45 | void observe(UsdBaseObject* caller, UsdDevice* device) override; 46 | 47 | // When geometry notifies surface, the bound parameters have to be updated. 48 | // The parameters are not time-varying, so they can be represented by a universal reference. 49 | bool updateBoundParameters = false; 50 | }; -------------------------------------------------------------------------------- /UsdVolume.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridgedBaseObject.h" 7 | 8 | #include 9 | 10 | class UsdSpatialField; 11 | class UsdDevice; 12 | class UsdDataArray; 13 | 14 | enum class UsdVolumeComponents 15 | { 16 | COLOR = 0, 17 | OPACITY, 18 | VALUERANGE 19 | }; 20 | 21 | struct UsdVolumeData 22 | { 23 | UsdSharedString* name = nullptr; 24 | UsdSharedString* usdName = nullptr; 25 | 26 | int timeVarying = 0xFFFFFFFF; // Bitmask indicating which attributes are time-varying. (field reference always set over all timesteps) 27 | 28 | bool isInstanceable = false; 29 | 30 | UsdSpatialField* field = nullptr; 31 | double fieldRefTimeStep = std::numeric_limits::quiet_NaN(); 32 | 33 | bool preClassified = false; 34 | 35 | //TF params 36 | const UsdDataArray* color = nullptr; 37 | const UsdDataArray* opacity = nullptr; 38 | UsdFloatBox1 valueRange = { 0.0f, 1.0f }; 39 | float unitDistance = 1.0f; 40 | }; 41 | 42 | class UsdVolume : public UsdBridgedBaseObject 43 | { 44 | public: 45 | UsdVolume(const char* name, UsdDevice* device); 46 | ~UsdVolume(); 47 | 48 | void remove(UsdDevice* device) override; 49 | 50 | bool isInstanceable() const; 51 | 52 | static constexpr ComponentPair componentParamNames[] = { 53 | ComponentPair(UsdVolumeComponents::COLOR, "color"), 54 | ComponentPair(UsdVolumeComponents::OPACITY, "opacity"), 55 | ComponentPair(UsdVolumeComponents::VALUERANGE, "valueRange")}; 56 | 57 | protected: 58 | bool deferCommit(UsdDevice* device) override; 59 | bool doCommitData(UsdDevice* device) override; 60 | void doCommitRefs(UsdDevice* device) override {} 61 | 62 | void onParamRefChanged(UsdBaseObject* paramObject, bool incRef, bool onWriteParams) override; 63 | void observe(UsdBaseObject* caller, UsdDevice* device) override; 64 | 65 | bool CheckTfParams(UsdDevice* device); 66 | bool UpdateVolume(UsdDevice* device, const char* debugName); 67 | 68 | UsdSpatialField* prevField = nullptr; 69 | UsdDevice* usdDevice = nullptr; 70 | }; -------------------------------------------------------------------------------- /UsdWorld.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "UsdWorld.h" 5 | #include "UsdAnari.h" 6 | #include "UsdInstance.h" 7 | #include "UsdSurface.h" 8 | #include "UsdVolume.h" 9 | #include "UsdDevice.h" 10 | #include "UsdDataArray.h" 11 | #include "UsdGroup.h" 12 | 13 | #define InstanceType ANARI_INSTANCE 14 | #define SurfaceType ANARI_SURFACE 15 | #define VolumeType ANARI_VOLUME 16 | using InstanceUsdType = AnariToUsdBridgedObject::Type; 17 | using SurfaceUsdType = AnariToUsdBridgedObject::Type; 18 | using VolumeUsdType = AnariToUsdBridgedObject::Type; 19 | 20 | DEFINE_PARAMETER_MAP(UsdWorld, 21 | REGISTER_PARAMETER_MACRO("name", ANARI_STRING, name) 22 | REGISTER_PARAMETER_MACRO("usd::name", ANARI_STRING, usdName) 23 | REGISTER_PARAMETER_MACRO("usd::timeVarying", ANARI_INT32, timeVarying) 24 | REGISTER_PARAMETER_MACRO("instance", ANARI_ARRAY, instances) 25 | REGISTER_PARAMETER_MACRO("surface", ANARI_ARRAY, surfaces) 26 | REGISTER_PARAMETER_MACRO("volume", ANARI_ARRAY, volumes) 27 | ) 28 | 29 | constexpr UsdWorld::ComponentPair UsdWorld::componentParamNames[]; // Workaround for C++14's lack of inlining constexpr arrays 30 | 31 | UsdWorld::UsdWorld(const char* name, UsdDevice* device) 32 | : BridgedBaseObjectType(ANARI_WORLD, name, device) 33 | { 34 | } 35 | 36 | UsdWorld::~UsdWorld() 37 | { 38 | #ifdef OBJECT_LIFETIME_EQUALS_USD_LIFETIME 39 | if(cachedBridge) 40 | cachedBridge->DeleteWorld(usdHandle); 41 | #endif 42 | } 43 | 44 | void UsdWorld::remove(UsdDevice* device) 45 | { 46 | applyRemoveFunc(device, &UsdBridge::DeleteWorld); 47 | } 48 | 49 | bool UsdWorld::deferCommit(UsdDevice* device) 50 | { 51 | const UsdWorldData& paramData = getReadParams(); 52 | 53 | if(UsdObjectNotInitialized(paramData.instances) || 54 | UsdObjectNotInitialized(paramData.surfaces) || 55 | UsdObjectNotInitialized(paramData.volumes)) 56 | { 57 | return true; 58 | } 59 | return false; 60 | } 61 | 62 | bool UsdWorld::doCommitData(UsdDevice* device) 63 | { 64 | UsdBridge* usdBridge = device->getUsdBridge(); 65 | 66 | const char* objName = getName(); 67 | 68 | bool isNew = false; 69 | if(!usdHandle.value) 70 | isNew = usdBridge->CreateWorld(objName, usdHandle); 71 | 72 | if (paramChanged || isNew) 73 | { 74 | doCommitRefs(device); // Perform immediate commit of refs - no params from children required 75 | 76 | paramChanged = false; 77 | } 78 | 79 | return false; 80 | } 81 | 82 | void UsdWorld::doCommitRefs(UsdDevice* device) 83 | { 84 | UsdBridge* usdBridge = device->getUsdBridge(); 85 | const UsdWorldData& paramData = getReadParams(); 86 | double timeStep = device->getReadParams().timeStep; 87 | 88 | const char* objName = getName(); 89 | 90 | bool instancesTimeVarying = isTimeVarying(UsdWorldComponents::INSTANCES); 91 | bool surfacesTimeVarying = isTimeVarying(UsdWorldComponents::SURFACES); 92 | bool volumesTimeVarying = isTimeVarying(UsdWorldComponents::VOLUMES); 93 | 94 | UsdLogInfo logInfo(device, this, ANARI_WORLD, this->getName()); 95 | 96 | ManageRefArray(usdHandle, paramData.instances, instancesTimeVarying, timeStep, 97 | instanceHandles, instanceableValues, &UsdBridge::SetInstanceRefs, &UsdBridge::DeleteInstanceRefs, 98 | usdBridge, logInfo, "UsdWorld commit failed: 'instance' array elements should be of type ANARI_INSTANCE"); 99 | 100 | ManageRefArray(usdHandle, paramData.surfaces, surfacesTimeVarying, timeStep, 101 | surfaceHandles, instanceableValues, &UsdBridge::SetSurfaceRefs, &UsdBridge::DeleteSurfaceRefs, 102 | usdBridge, logInfo, "UsdGroup commit failed: 'surface' array elements should be of type ANARI_SURFACE"); 103 | 104 | ManageRefArray(usdHandle, paramData.volumes, volumesTimeVarying, timeStep, 105 | volumeHandles, instanceableValues, &UsdBridge::SetVolumeRefs, &UsdBridge::DeleteVolumeRefs, 106 | usdBridge, logInfo, "UsdGroup commit failed: 'volume' array elements should be of type ANARI_VOLUME"); 107 | } -------------------------------------------------------------------------------- /UsdWorld.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include "UsdBridgedBaseObject.h" 7 | 8 | class UsdDataArray; 9 | 10 | enum class UsdWorldComponents 11 | { 12 | INSTANCES = 0, 13 | SURFACES, 14 | VOLUMES 15 | }; 16 | 17 | struct UsdWorldData 18 | { 19 | UsdSharedString* name = nullptr; 20 | UsdSharedString* usdName = nullptr; 21 | 22 | int timeVarying = 0xFFFFFFFF; // Bitmask indicating which attributes are time-varying. 23 | UsdDataArray* instances = nullptr; 24 | UsdDataArray* surfaces = nullptr; 25 | UsdDataArray* volumes = nullptr; 26 | }; 27 | 28 | class UsdWorld : public UsdBridgedBaseObject 29 | { 30 | public: 31 | UsdWorld(const char* name, UsdDevice* device); 32 | ~UsdWorld(); 33 | 34 | void remove(UsdDevice* device) override; 35 | 36 | static constexpr ComponentPair componentParamNames[] = { 37 | ComponentPair(UsdWorldComponents::INSTANCES, "instance"), 38 | ComponentPair(UsdWorldComponents::SURFACES, "surface"), 39 | ComponentPair(UsdWorldComponents::VOLUMES, "volume")}; 40 | 41 | protected: 42 | 43 | bool deferCommit(UsdDevice* device) override; 44 | bool doCommitData(UsdDevice* device) override; 45 | void doCommitRefs(UsdDevice* device) override; 46 | 47 | std::vector instanceHandles; // for convenience 48 | std::vector surfaceHandles; // for convenience 49 | std::vector volumeHandles; // for convenience 50 | std::vector instanceableValues; // for convenience 51 | }; -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ## Copyright 2020 The Khronos Group 2 | ## SPDX-License-Identifier: Apache-2.0 3 | 4 | if (NOT WIN32) 5 | set (PLATFORM_LIBS m) 6 | endif() 7 | 8 | project(anariTutorialUsd) 9 | add_executable(${PROJECT_NAME} anariTutorial_usd.c) 10 | target_link_libraries(${PROJECT_NAME} PRIVATE anari::anari stb_image ${PLATFORM_LIBS}) 11 | install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 12 | 13 | project(anariTutorialUsdCpp) 14 | add_executable(${PROJECT_NAME} anariTutorial_usd.cpp) 15 | target_link_libraries(${PROJECT_NAME} PRIVATE anari::anari stb_image ${PLATFORM_LIBS}) 16 | install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 17 | 18 | project(anariTutorialUsdTime) 19 | add_executable(${PROJECT_NAME} anariTutorial_usd_time.c) 20 | target_link_libraries(${PROJECT_NAME} PRIVATE anari::anari stb_image ${PLATFORM_LIBS}) 21 | install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 22 | 23 | project(anariTutorialUsdRecreate) 24 | add_executable(${PROJECT_NAME} anariTutorial_usd_recreate.c) 25 | target_link_libraries(${PROJECT_NAME} PRIVATE anari::anari stb_image ${PLATFORM_LIBS}) 26 | install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 27 | 28 | project(anariTutorialUsdVolume) 29 | add_executable(${PROJECT_NAME} anariTutorial_usd_volume.cpp) 30 | target_link_libraries(${PROJECT_NAME} PRIVATE anari::anari stb_image ${PLATFORM_LIBS}) 31 | install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -------------------------------------------------------------------------------- /examples/anariTutorial_usd.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2021 NVIDIA Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | // anari 9 | #define ANARI_EXTENSION_UTILITY_IMPL 10 | #include "anari/anari_cpp.hpp" 11 | #include "anari/anari_cpp/ext/std.h" 12 | 13 | // stb_image 14 | #include "stb_image_write.h" 15 | 16 | using uvec2 = std::array; 17 | using ivec3 = std::array; 18 | using vec3 = std::array; 19 | using vec4 = std::array; 20 | using box3 = std::array; 21 | 22 | void statusFunc(const void *userData, 23 | ANARIDevice device, 24 | ANARIObject source, 25 | ANARIDataType sourceType, 26 | ANARIStatusSeverity severity, 27 | ANARIStatusCode code, 28 | const char *message) 29 | { 30 | (void)userData; 31 | (void)device; 32 | (void)source; 33 | (void)sourceType; 34 | (void)code; 35 | if (severity == ANARI_SEVERITY_FATAL_ERROR) { 36 | fprintf(stderr, "[FATAL] %s\n", message); 37 | } else if (severity == ANARI_SEVERITY_ERROR) { 38 | fprintf(stderr, "[ERROR] %s\n", message); 39 | } else if (severity == ANARI_SEVERITY_WARNING) { 40 | fprintf(stderr, "[WARN ] %s\n", message); 41 | } else if (severity == ANARI_SEVERITY_PERFORMANCE_WARNING) { 42 | fprintf(stderr, "[PERF ] %s\n", message); 43 | } else if (severity == ANARI_SEVERITY_INFO) { 44 | fprintf(stderr, "[INFO ] %s\n", message); 45 | } else if (severity == ANARI_SEVERITY_DEBUG) { 46 | fprintf(stderr, "[DEBUG] %s\n", message); 47 | } 48 | } 49 | 50 | int main(int argc, const char **argv) 51 | { 52 | (void)argc; 53 | (void)argv; 54 | stbi_flip_vertically_on_write(1); 55 | 56 | // image size 57 | uvec2 imgSize = {1024 /*width*/, 768 /*height*/}; 58 | 59 | // camera 60 | vec3 cam_pos = {0.f, 0.f, 0.f}; 61 | vec3 cam_up = {0.f, 1.f, 0.f}; 62 | vec3 cam_view = {0.1f, 0.f, 1.f}; 63 | 64 | // triangle mesh array 65 | vec3 vertex[] = {{-1.0f, -1.0f, 3.0f}, 66 | {-1.0f, 1.0f, 3.0f}, 67 | {1.0f, -1.0f, 3.0f}, 68 | {0.1f, 0.1f, 0.3f}}; 69 | vec4 color[] = {{0.9f, 0.0f, 0.0f, 1.0f}, 70 | {0.8f, 0.8f, 0.8f, 1.0f}, 71 | {0.8f, 0.8f, 0.8f, 1.0f}, 72 | {0.0f, 0.9f, 0.0f, 1.0f}}; 73 | ivec3 index[] = {{0, 1, 2}, {1, 2, 3}}; 74 | 75 | printf("initialize ANARI..."); 76 | 77 | anari::Library lib = anari::loadLibrary("usd", statusFunc); 78 | 79 | anari::Extensions extensions = 80 | anari::extension::getDeviceExtensionStruct(lib, "default"); 81 | 82 | if (!extensions.ANARI_KHR_GEOMETRY_TRIANGLE) 83 | printf("WARNING: device doesn't support ANARI_KHR_GEOMETRY_TRIANGLE\n"); 84 | if (!extensions.ANARI_KHR_CAMERA_PERSPECTIVE) 85 | printf("WARNING: device doesn't support ANARI_KHR_CAMERA_PERSPECTIVE\n"); 86 | if (!extensions.ANARI_KHR_LIGHT_DIRECTIONAL) 87 | printf("WARNING: device doesn't support ANARI_KHR_LIGHT_DIRECTIONAL\n"); 88 | if (!extensions.ANARI_KHR_MATERIAL_MATTE) 89 | printf("WARNING: device doesn't support ANARI_KHR_MATERIAL_MATTE\n"); 90 | 91 | ANARIDevice d = anariNewDevice(lib, "default"); 92 | 93 | printf("done!\n"); 94 | printf("setting up camera..."); 95 | 96 | // create and setup camera 97 | auto camera = anari::newObject(d, "perspective"); 98 | anari::setParameter( 99 | d, camera, "aspect", (float)imgSize[0] / (float)imgSize[1]); 100 | anari::setParameter(d, camera, "position", cam_pos); 101 | anari::setParameter(d, camera, "direction", cam_view); 102 | anari::setParameter(d, camera, "up", cam_up); 103 | anari::commitParameters( 104 | d, camera); // commit objects to indicate setting parameters is done 105 | 106 | printf("done!\n"); 107 | printf("setting up scene..."); 108 | 109 | // The world to be populated with renderable objects 110 | auto world = anari::newObject(d); 111 | 112 | // create and setup surface and mesh 113 | auto mesh = anari::newObject(d, "triangle"); 114 | 115 | anari::setAndReleaseParameter( 116 | d, mesh, "vertex.position", anari::newArray1D(d, vertex, 4)); 117 | 118 | anari::setAndReleaseParameter( 119 | d, mesh, "vertex.color", anari::newArray1D(d, color, 4)); 120 | 121 | anari::setAndReleaseParameter( 122 | d, mesh, "primitive.index", anari::newArray1D(d, index, 2)); 123 | 124 | anari::commitParameters(d, mesh); 125 | 126 | auto mat = anari::newObject(d, "matte"); 127 | 128 | anari::setParameter(d, mat, "color", "color"); 129 | anari::commitParameters(d, mat); 130 | 131 | // put the mesh into a surface 132 | auto surface = anari::newObject(d); 133 | anari::setAndReleaseParameter(d, surface, "geometry", mesh); 134 | anari::setAndReleaseParameter(d, surface, "material", mat); 135 | anari::commitParameters(d, surface); 136 | 137 | // put the surface directly onto the world 138 | anari::setAndReleaseParameter( 139 | d, world, "surface", anari::newArray1D(d, &surface)); 140 | anari::release(d, surface); 141 | 142 | // create and setup light 143 | auto light = anari::newObject(d, "directional"); 144 | anari::commitParameters(d, light); 145 | anari::setAndReleaseParameter( 146 | d, world, "light", anari::newArray1D(d, &light)); 147 | anari::release(d, light); 148 | 149 | anari::commitParameters(d, world); 150 | 151 | printf("done!\n"); 152 | 153 | // print out world bounds 154 | box3 worldBounds; 155 | if (anari::getProperty(d, world, "bounds", worldBounds, ANARI_WAIT)) { 156 | printf("\nworld bounds: ({%f, %f, %f}, {%f, %f, %f}\n\n", 157 | worldBounds[0][0], 158 | worldBounds[0][1], 159 | worldBounds[0][2], 160 | worldBounds[1][0], 161 | worldBounds[1][1], 162 | worldBounds[1][2]); 163 | } else { 164 | printf("\nworld bounds not returned\n\n"); 165 | } 166 | 167 | printf("setting up renderer..."); 168 | 169 | // create renderer 170 | auto renderer = anari::newObject(d, "default"); 171 | // objects can be named for easier identification in debug output etc. 172 | anari::setParameter(d, renderer, "name", "MainRenderer"); 173 | 174 | printf("done!\n"); 175 | 176 | // complete setup of renderer 177 | vec4 bgColor = {1.f, 1.f, 1.f, 1.f}; 178 | anari::setParameter(d, renderer, "backgroundColor", bgColor); // white 179 | anari::commitParameters(d, renderer); 180 | 181 | // create and setup frame 182 | auto frame = anari::newObject(d); 183 | anari::setParameter(d, frame, "size", imgSize); 184 | anari::setParameter(d, frame, "channel.color", ANARI_UFIXED8_RGBA_SRGB); 185 | 186 | anari::setAndReleaseParameter(d, frame, "renderer", renderer); 187 | anari::setAndReleaseParameter(d, frame, "camera", camera); 188 | anari::setAndReleaseParameter(d, frame, "world", world); 189 | 190 | anari::commitParameters(d, frame); 191 | 192 | printf("rendering out USD objects via anari::renderFrame()..."); 193 | 194 | // render one frame 195 | anari::render(d, frame); 196 | anari::wait(d, frame); 197 | 198 | printf("done!\n"); 199 | printf("\ncleaning up objects..."); 200 | 201 | // final cleanups 202 | anari::release(d, frame); 203 | anari::release(d, d); 204 | anari::unloadLibrary(lib); 205 | 206 | printf("done!\n"); 207 | 208 | return 0; 209 | } 210 | -------------------------------------------------------------------------------- /examples/anariTutorial_usd_common.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 NVIDIA Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #pragma once 5 | 6 | #include 7 | #define PI 3.14159265 8 | 9 | const char *g_libraryType = "usd"; 10 | 11 | #ifdef _WIN32 12 | const char* texFile = "d:/models/texture.png"; 13 | #else 14 | const char* texFile = "/home//models/texture.png"; // Point this to any png 15 | #endif 16 | 17 | const char* wrapS = "repeat"; 18 | const char* wrapT = "repeat"; 19 | 20 | /******************************************************************/ 21 | void statusFunc(const void *userData, 22 | ANARIDevice device, 23 | ANARIObject source, 24 | ANARIDataType sourceType, 25 | ANARIStatusSeverity severity, 26 | ANARIStatusCode code, 27 | const char *message) 28 | { 29 | (void)userData; 30 | if (severity == ANARI_SEVERITY_FATAL_ERROR) 31 | { 32 | fprintf(stderr, "[FATAL] %s\n", message); 33 | } 34 | else if (severity == ANARI_SEVERITY_ERROR) 35 | { 36 | fprintf(stderr, "[ERROR] %s\n", message); 37 | } 38 | else if (severity == ANARI_SEVERITY_WARNING) 39 | { 40 | fprintf(stderr, "[WARN ] %s\n", message); 41 | } 42 | else if (severity == ANARI_SEVERITY_PERFORMANCE_WARNING) 43 | { 44 | fprintf(stderr, "[PERF ] %s\n", message); 45 | } 46 | else if (severity == ANARI_SEVERITY_INFO) 47 | { 48 | fprintf(stderr, "[INFO ] %s\n", message); 49 | } 50 | else if (severity == ANARI_SEVERITY_DEBUG) 51 | { 52 | fprintf(stderr, "[DEBUG] %s\n", message); 53 | } 54 | } 55 | 56 | void writePNG(const char *fileName, ANARIDevice d, ANARIFrame frame) 57 | { 58 | uint32_t size[2] = {0, 0}; 59 | ANARIDataType type = ANARI_UNKNOWN; 60 | uint32_t *pixel = (uint32_t *)anariMapFrame(d, frame, "channel.color", &size[0], &size[1], &type); 61 | 62 | if (type == ANARI_UFIXED8_RGBA_SRGB) 63 | stbi_write_png(fileName, size[0], size[1], 4, pixel, 4 * size[0]); 64 | else 65 | printf("Incorrectly returned color buffer pixel type, image not saved.\n"); 66 | 67 | anariUnmapFrame(d, frame, "channel.color"); 68 | } 69 | 70 | uint8_t touint8t(float val) 71 | { 72 | return (uint8_t)floorf((val + 1.0f)*127.5f); // 0.5*255 73 | } 74 | 75 | uint8_t* generateTexture(int* size, int numComps) 76 | { 77 | uint8_t* texData = (uint8_t*)malloc(size[0]*size[1]*numComps); 78 | 79 | for(int i = 0; i < size[0]; ++i) 80 | { 81 | for(int j = 0; j < size[1]; ++j) 82 | { 83 | int pixIdx = i*size[1]+j; 84 | int offset = pixIdx*numComps; 85 | 86 | float rVal = sin((float)i/size[0] * 2.0f * PI); 87 | float gVal = cos((float)i/size[0] * 8.0f * PI); 88 | float bVal = cos((float)j/size[1] * 20.0f * PI); 89 | 90 | texData[offset] = touint8t(rVal); 91 | if(numComps >= 2) 92 | texData[offset+1] = touint8t(gVal); 93 | if(numComps >= 3) 94 | texData[offset+2] = touint8t(bVal); 95 | if(numComps == 4) 96 | texData[offset+3] = 255; 97 | } 98 | } 99 | 100 | return texData; 101 | } 102 | 103 | void freeTexture(uint8_t* data) 104 | { 105 | free(data); 106 | } 107 | 108 | typedef struct GridData 109 | { 110 | float* gridVertex; 111 | float* gridColor; 112 | float* gridOpacity; 113 | float* gridRadius; 114 | float* gridOrientation; 115 | int gridSize[2]; 116 | } GridData_t; 117 | 118 | void createSineWaveGrid(int* size, GridData_t* gridData) 119 | { 120 | int baseSize = size[0]*size[1]*sizeof(float); 121 | float* vertData = (float*)malloc(baseSize*3); 122 | float* colorData = (float*)malloc(baseSize*3); 123 | float* opacityData = (float*)malloc(baseSize); 124 | float* radiusData = (float*)malloc(baseSize); 125 | float* orientData = (float*)malloc(baseSize*4); 126 | 127 | for(int i = 0; i < size[0]; ++i) 128 | { 129 | for(int j = 0; j < size[1]; ++j) 130 | { 131 | int vertIdx = i*size[1]+j; 132 | int vertAddr = vertIdx*3; 133 | 134 | float iFrac = (float)i/size[0]; 135 | float jFrac = (float)j/size[1]; 136 | 137 | // Vertex 138 | float amp = sin((iFrac+jFrac) * 8.0f * PI) + cos(jFrac * 5.5f * PI); 139 | 140 | vertData[vertAddr] = ((float)i)*5.0f; 141 | vertData[vertAddr+1] = ((float)j)*5.0f; 142 | vertData[vertAddr+2] = amp*10.0f; 143 | 144 | // Color 145 | float rVal = sin(iFrac * 2.0f * PI); 146 | float gVal = cos(iFrac * 8.0f * PI); 147 | float bVal = cos(jFrac * 20.0f * PI); 148 | 149 | colorData[vertAddr] = rVal; 150 | colorData[vertAddr+1] = gVal; 151 | colorData[vertAddr+2] = bVal; 152 | 153 | // Opacity 154 | float opacity = 0.3f + 0.3f*(cos(iFrac * 1.0f * PI) + sin(jFrac * 7.0f * PI)); 155 | 156 | opacityData[vertIdx] = opacity; 157 | 158 | // Radius 159 | //spacing is 5.0, so make sure not to go over 2.5 160 | float radius = 1.25f + 0.5f*(cos(iFrac * 5.0f * PI) + sin(jFrac * 2.0f * PI)); 161 | 162 | radiusData[vertIdx] = radius; 163 | 164 | // Orientation 165 | int orientAddr = vertIdx*4; 166 | float roll = iFrac*PI*7.3, pitch = jFrac*PI*4.9, yaw = -(jFrac+0.45f)*PI*3.3; 167 | float sinRoll = sin(roll), sinPitch = sin(pitch), sinYaw = sin(yaw); 168 | float cosRoll = cos(roll), cosPitch = cos(pitch), cosYaw = cos(yaw); 169 | orientData[orientAddr] = cosRoll*cosPitch*cosYaw+sinRoll*sinPitch*sinYaw; 170 | orientData[orientAddr+1] = sinRoll*cosPitch*cosYaw-cosRoll*sinPitch*sinYaw; 171 | orientData[orientAddr+2] = cosRoll*sinPitch*cosYaw+sinRoll*cosPitch*sinYaw; 172 | orientData[orientAddr+3] = cosRoll*cosPitch*sinYaw-sinRoll*sinPitch*cosYaw; 173 | } 174 | } 175 | 176 | gridData->gridVertex = vertData; 177 | gridData->gridColor = colorData; 178 | gridData->gridOpacity = opacityData; 179 | gridData->gridRadius = radiusData; 180 | gridData->gridOrientation = orientData; 181 | gridData->gridSize[0] = size[0]; 182 | gridData->gridSize[1] = size[1]; 183 | } 184 | 185 | void freeSineWaveGrid(GridData_t* gridData) 186 | { 187 | free(gridData->gridVertex); 188 | free(gridData->gridColor); 189 | free(gridData->gridOpacity); 190 | free(gridData->gridRadius); 191 | free(gridData->gridOrientation); 192 | } -------------------------------------------------------------------------------- /examples/anari_tutorial_glyphs_usd.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 The Khronos Group 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | import numpy as np 5 | from anari import * 6 | 7 | 8 | # Data arrays for the scene 9 | width = 1024 10 | height = 768 11 | 12 | cam_pos = [0.0, 0.0, -100.0] 13 | cam_up = [0.0, 1.0, 0.0] 14 | cam_view = [0.1, 0.0, 1.0] 15 | 16 | vertex = np.array([ 17 | -1.0, -1.0, 3.0, 18 | -1.0, 1.0, 3.0, 19 | 1.0, -1.0, 3.0, 20 | 0.1, 0.1, 0.3 21 | ], dtype = np.float32) 22 | 23 | color = np.array([ 24 | 0.9, 0.5, 0.5, 1.0, 25 | 0.8, 0.8, 0.8, 1.0, 26 | 0.8, 0.8, 0.8, 1.0, 27 | 0.5, 0.9, 0.5, 1.0 28 | ], dtype = np.float32) 29 | 30 | orientation = np.array([ 31 | 0.0, 0.0, 0.0, 1.0, 32 | 0.0, 0.707031, 0.0, 0.707031, 33 | -0.707031, 0.00282288, 0.0, 0.707031, 34 | 0.96582, 0.00946808, 0.0, 0.258789 35 | ], dtype = np.float32) # These are 4-component quaternions, with the real component at the end (IJKW). So the first entry is the identity rotation. 36 | 37 | scale = np.array([ 38 | 2.0, 0.5, 0.3, 1.0 39 | ], dtype = np.float32) # Simple scalars for uniform scaling 40 | 41 | index = np.array([ 42 | 0, 1, 2, 3 43 | ], dtype = np.uint32) 44 | 45 | 46 | # Logging function definitions 47 | prefixes = { 48 | lib.ANARI_SEVERITY_FATAL_ERROR : "FATAL", 49 | lib.ANARI_SEVERITY_ERROR : "ERROR", 50 | lib.ANARI_SEVERITY_WARNING : "WARNING", 51 | lib.ANARI_SEVERITY_PERFORMANCE_WARNING : "PERFORMANCE", 52 | lib.ANARI_SEVERITY_INFO : "INFO", 53 | lib.ANARI_SEVERITY_DEBUG : "DEBUG" 54 | } 55 | 56 | def anari_status(device, source, sourceType, severity, code, message): 57 | print('[%s]: '%prefixes[severity]+message) 58 | 59 | status_handle = ffi.new_handle(anari_status) #something needs to keep this handle alive 60 | 61 | 62 | # Loading the USD library and creating the device 63 | usdLibrary = anariLoadLibrary('usd', status_handle) 64 | usdDevice = anariNewDevice(usdLibrary, 'usd') 65 | 66 | 67 | # Setting the USD device parameters, which determine where the USD output goes 68 | usdOutputBinary = 0 # ANARI's spec defines BOOL and INT32 to be of equal size, so playing it safe here by using an explicit int 69 | usdPreviewSurface = 0 70 | anariSetParameter(usdDevice, usdDevice, 'usd::serialize.location', ANARI_STRING, './'); # Location on disk, replace with any desired path 71 | anariSetParameter(usdDevice, usdDevice, 'usd::serialize.outputBinary', ANARI_BOOL, usdOutputBinary); # Output binary files (smaller) or ascii output (for debugging) 72 | anariSetParameter(usdDevice, usdDevice, 'usd::output.previewSurfaceShader', ANARI_BOOL, usdPreviewSurface); # Materials that work for rendering in non-nvidia USD clients are disabled for now 73 | 74 | # Nucleus specific device parameters; uncomment if output to Nucleus is desired 75 | #usdConnectionLogVerbosity = 0 76 | #anariSetParameter(usdDevice, usdDevice, 'usd::serialize.hostName', ANARI_STRING, 'localhost'); # Used in case Nucleus output is desired 77 | #anariSetParameter(usdDevice, usdDevice, 'usd::connection.logVerbosity', ANARI_INT32, usdConnectionLogVerbosity); # In case of Nucleus connection, set connection log verbosity from [0-4], with the highest value being the most verbose 78 | 79 | anariCommitParameters(usdDevice, usdDevice) 80 | 81 | 82 | # The USD device is wrapped within a debug device, for additional sanity checking of the API usage 83 | # All further ANARI calls use the debug device, which internally routes the calls through to the usdDevice 84 | debugLibrary = anariLoadLibrary('debug', status_handle) 85 | debugDevice = anariNewDevice(debugLibrary, 'debug') 86 | anariSetParameter(debugDevice, debugDevice, 'wrappedDevice', ANARI_DEVICE, usdDevice) 87 | anariSetParameter(debugDevice, debugDevice, 'traceMode', ANARI_STRING, 'code') 88 | anariCommitParameters(debugDevice, debugDevice) 89 | 90 | 91 | # Choose either the debug or the usd device 92 | device = usdDevice 93 | 94 | 95 | # Setting up the scene objects, with a camera, light, world and the glyph geometry with a basic material. 96 | camera = anariNewCamera(device, 'perspective') 97 | anariSetParameter(device, camera, 'aspect', ANARI_FLOAT32, width/height) 98 | anariSetParameter(device, camera, 'position', ANARI_FLOAT32_VEC3, cam_pos) 99 | anariSetParameter(device, camera, 'direction', ANARI_FLOAT32_VEC3, cam_view) 100 | anariSetParameter(device, camera, 'up', ANARI_FLOAT32_VEC3, cam_up) 101 | anariCommitParameters(device, camera) 102 | 103 | world = anariNewWorld(device) 104 | 105 | glyphs = anariNewGeometry(device, 'glyph') 106 | 107 | anariSetParameter(device, glyphs, 'shapeType', ANARI_STRING, 'cone') # The shape of the glyph can be specified here - 'sphere/cylinder/cone' are supported, a custom shape is a bit more involved 108 | 109 | array = anariNewArray1D(device, ffi.from_buffer(vertex), ANARI_FLOAT32_VEC3, 4) 110 | anariSetParameter(device, glyphs, 'vertex.position', ANARI_ARRAY1D, array) 111 | 112 | array = anariNewArray1D(device, ffi.from_buffer(color), ANARI_FLOAT32_VEC4, 4) 113 | anariSetParameter(device, glyphs, 'vertex.color', ANARI_ARRAY1D, array) 114 | 115 | array = anariNewArray1D(device, ffi.from_buffer(orientation), ANARI_FLOAT32_QUAT_IJKW, 4) 116 | anariSetParameter(device, glyphs, 'vertex.orientation', ANARI_ARRAY1D, array) 117 | 118 | array = anariNewArray1D(device, ffi.from_buffer(scale), ANARI_FLOAT32, 4) # Could also be ANARI_FLOAT32_VEC3 - a different scale for every axis 119 | anariSetParameter(device, glyphs, 'vertex.scale', ANARI_ARRAY1D, array) 120 | 121 | array = anariNewArray1D(device, ffi.from_buffer(index), ANARI_UINT32, 4) # The index array can optionally be left out completely 122 | anariSetParameter(device, glyphs, 'primitive.index', ANARI_ARRAY1D, array) 123 | 124 | anariCommitParameters(device, glyphs) 125 | 126 | material = anariNewMaterial(device, 'matte') # If a particular look is required, consider changing to 'physicallyBased' and look for parameters in https://registry.khronos.org/ANARI/specs/1.0/ANARI-1.0.html#object_types_material_physically_based 127 | anariCommitParameters(device, material) 128 | 129 | surface = anariNewSurface(device) 130 | anariSetParameter(device, surface, 'geometry', ANARI_GEOMETRY, glyphs) 131 | anariSetParameter(device, surface, 'material', ANARI_MATERIAL, material) 132 | anariCommitParameters(device, surface) 133 | 134 | surfaces = ffi.new('ANARISurface[]', [surface]) 135 | array = anariNewArray1D(device, surfaces, ANARI_SURFACE, 1) 136 | anariSetParameter(device, world, 'surface', ANARI_ARRAY1D, array) 137 | 138 | light = anariNewLight(device, 'directional') 139 | anariCommitParameters(device, light) 140 | 141 | lights = ffi.new('ANARILight[]', [light]) 142 | array = anariNewArray1D(device, lights, ANARI_LIGHT, 1) 143 | anariSetParameter(device, world, 'light', ANARI_ARRAY1D, array) 144 | 145 | anariCommitParameters(device, world) 146 | 147 | 148 | # Creating the frame dummy object required to call 'anariRenderFrame' 149 | frame = anariNewFrame(device) 150 | anariCommitParameters(device, frame) 151 | 152 | 153 | # AnariRenderFrame is where the USD output is actually written 154 | anariRenderFrame(device, frame) 155 | anariFrameReady(device, frame, ANARI_WAIT) -------------------------------------------------------------------------------- /khr_geometry_glyph.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "name" : "KHR_GEOMETRY_GLYPH", 4 | "type" : "extension", 5 | "dependencies" : [] 6 | }, 7 | 8 | "objects" : [ 9 | { 10 | "type" : "ANARI_GEOMETRY", 11 | "name" : "glyph", 12 | "description" : "glyph geometry object", 13 | "parameters" : [ 14 | { 15 | "name" : "name", 16 | "types" : ["ANARI_STRING"], 17 | "tags" : [], 18 | "description" : "optional object name" 19 | }, { 20 | "name" : "primitive.color", 21 | "types" : ["ANARI_ARRAY1D"], 22 | "elementType" : [ 23 | "ANARI_UFIXED8", "ANARI_UFIXED8_VEC2", "ANARI_UFIXED8_VEC3", "ANARI_UFIXED8_VEC4", 24 | "ANARI_UFIXED8_R_SRGB", "ANARI_UFIXED8_RA_SRGB", "ANARI_UFIXED8_RGB_SRGB", "ANARI_UFIXED8_RGBA_SRGB", 25 | "ANARI_UFIXED16", "ANARI_UFIXED16_VEC2", "ANARI_UFIXED16_VEC3", "ANARI_UFIXED16_VEC4", 26 | "ANARI_UFIXED32", "ANARI_UFIXED32_VEC2", "ANARI_UFIXED32_VEC3", "ANARI_UFIXED32_VEC4", 27 | "ANARI_FLOAT32", "ANARI_FLOAT32_VEC2", "ANARI_FLOAT32_VEC3", "ANARI_FLOAT32_VEC4"], 28 | "tags" : [], 29 | "description" : "per primitive color" 30 | }, { 31 | "name" : "primitive.attribute0", 32 | "types" : ["ANARI_ARRAY1D"], 33 | "elementType" : ["ANARI_FLOAT32", "ANARI_FLOAT32_VEC2", "ANARI_FLOAT32_VEC3", "ANARI_FLOAT32_VEC4"], 34 | "tags" : [], 35 | "description" : "per primitive attribute0" 36 | }, { 37 | "name" : "primitive.attribute1", 38 | "types" : ["ANARI_ARRAY1D"], 39 | "elementType" : ["ANARI_FLOAT32", "ANARI_FLOAT32_VEC2", "ANARI_FLOAT32_VEC3", "ANARI_FLOAT32_VEC4"], 40 | "tags" : [], 41 | "description" : "per primitive attribute1" 42 | }, { 43 | "name" : "primitive.attribute2", 44 | "types" : ["ANARI_ARRAY1D"], 45 | "elementType" : ["ANARI_FLOAT32", "ANARI_FLOAT32_VEC2", "ANARI_FLOAT32_VEC3", "ANARI_FLOAT32_VEC4"], 46 | "tags" : [], 47 | "description" : "per primitive attribute2" 48 | }, { 49 | "name" : "primitive.attribute3", 50 | "types" : ["ANARI_ARRAY1D"], 51 | "elementType" : ["ANARI_FLOAT32", "ANARI_FLOAT32_VEC2", "ANARI_FLOAT32_VEC3", "ANARI_FLOAT32_VEC4"], 52 | "tags" : [], 53 | "description" : "per primitive attribute3" 54 | }, { 55 | "name" : "primitive.id", 56 | "types" : ["ANARI_ARRAY1D"], 57 | "elementType" : ["ANARI_UINT32", "ANARI_UINT64"], 58 | "tags" : [], 59 | "description" : "primitive id" 60 | }, { 61 | "name" : "vertex.position", 62 | "types" : ["ANARI_ARRAY1D"], 63 | "elementType" : ["ANARI_FLOAT32_VEC3"], 64 | "tags" : ["required"], 65 | "description" : "glyph position" 66 | }, { 67 | "name" : "vertex.scale", 68 | "types" : ["ANARI_ARRAY1D"], 69 | "elementType" : ["ANARI_FLOAT32", "ANARI_FLOAT32_VEC3"], 70 | "tags" : [], 71 | "description" : "glyph scale" 72 | }, { 73 | "name" : "vertex.orientation", 74 | "types" : ["ANARI_ARRAY1D"], 75 | "elementType" : ["ANARI_FLOAT32_QUAT_IJKW"], 76 | "tags" : [], 77 | "description" : "glyph orientation" 78 | }, { 79 | "name" : "vertex.cap", 80 | "types" : ["ANARI_ARRAY1D"], 81 | "elementType" : ["ANARI_UINT8"], 82 | "tags" : [], 83 | "description" : "glyph cap type for cylinders and cones" 84 | }, { 85 | "name" : "vertex.color", 86 | "types" : ["ANARI_ARRAY1D"], 87 | "elementType" : [ 88 | "ANARI_UFIXED8", "ANARI_UFIXED8_VEC2", "ANARI_UFIXED8_VEC3", "ANARI_UFIXED8_VEC4", 89 | "ANARI_UFIXED8_R_SRGB", "ANARI_UFIXED8_RA_SRGB", "ANARI_UFIXED8_RGB_SRGB", "ANARI_UFIXED8_RGBA_SRGB", 90 | "ANARI_UFIXED16", "ANARI_UFIXED16_VEC2", "ANARI_UFIXED16_VEC3", "ANARI_UFIXED16_VEC4", 91 | "ANARI_UFIXED32", "ANARI_UFIXED32_VEC2", "ANARI_UFIXED32_VEC3", "ANARI_UFIXED32_VEC4", 92 | "ANARI_FLOAT32", "ANARI_FLOAT32_VEC2", "ANARI_FLOAT32_VEC3", "ANARI_FLOAT32_VEC4"], 93 | "tags" : [], 94 | "description" : "vertex color" 95 | }, { 96 | "name" : "vertex.attribute0", 97 | "types" : ["ANARI_ARRAY1D"], 98 | "elementType" : ["ANARI_FLOAT32", "ANARI_FLOAT32_VEC2", "ANARI_FLOAT32_VEC3", "ANARI_FLOAT32_VEC4"], 99 | "tags" : [], 100 | "description" : "vertex attribute0" 101 | }, { 102 | "name" : "vertex.attribute1", 103 | "types" : ["ANARI_ARRAY1D"], 104 | "elementType" : ["ANARI_FLOAT32", "ANARI_FLOAT32_VEC2", "ANARI_FLOAT32_VEC3", "ANARI_FLOAT32_VEC4"], 105 | "tags" : [], 106 | "description" : "vertex attribute1" 107 | }, { 108 | "name" : "vertex.attribute2", 109 | "types" : ["ANARI_ARRAY1D"], 110 | "elementType" : ["ANARI_FLOAT32", "ANARI_FLOAT32_VEC2", "ANARI_FLOAT32_VEC3", "ANARI_FLOAT32_VEC4"], 111 | "tags" : [], 112 | "description" : "vertex attribute2" 113 | }, { 114 | "name" : "vertex.attribute3", 115 | "types" : ["ANARI_ARRAY1D"], 116 | "elementType" : ["ANARI_FLOAT32", "ANARI_FLOAT32_VEC2", "ANARI_FLOAT32_VEC3", "ANARI_FLOAT32_VEC4"], 117 | "tags" : [], 118 | "description" : "vertex attribute3" 119 | }, { 120 | "name" : "primitive.index", 121 | "types" : ["ANARI_ARRAY1D"], 122 | "elementType" : ["ANARI_UINT32", "ANARI_UINT64"], 123 | "tags" : [], 124 | "description" : "index array" 125 | }, { 126 | "name" : "scale", 127 | "types" : ["ANARI_FLOAT32_VEC3"], 128 | "tags" : [], 129 | "description" : "global glyph scale" 130 | }, { 131 | "name" : "orientation", 132 | "types" : ["ANARI_FLOAT32_QUAT_IJKW"], 133 | "tags" : [], 134 | "description" : "global glyph orientation" 135 | }, { 136 | "name" : "caps", 137 | "types" : ["ANARI_STRING"], 138 | "tags" : [], 139 | "default" : "none", 140 | "values" : ["none", "first", "second", "both"], 141 | "description" : "global cap type for cylinders and cones" 142 | }, { 143 | "name" : "shapeType", 144 | "types" : ["ANARI_STRING"], 145 | "tags" : [], 146 | "description" : "glyph shape geometry type" 147 | }, { 148 | "name" : "shapeGeometry", 149 | "types" : ["ANARI_GEOMETRY"], 150 | "tags" : [], 151 | "description" : "glyph shape geometry" 152 | }, { 153 | "name" : "shapeTransform", 154 | "types" : ["ANARI_FLOAT32_MAT4"], 155 | "tags" : [], 156 | "description" : "glyph shape transform" 157 | } 158 | ] 159 | } 160 | ] 161 | } 162 | -------------------------------------------------------------------------------- /superbuild/README.md: -------------------------------------------------------------------------------- 1 | # CMake superbuild for USD ANARI Device 2 | 3 | This CMake script runs stand alone to optionally build together any of: 4 | 5 | - ANARIUsd Device (parent directory) 6 | - ANARI-SDK 7 | - USD + dependencies 8 | 9 | The result of building this project is all the contents of the above (if built) 10 | installed to `CMAKE_INSTALL_PREFIX`. 11 | 12 | ## Build setup 13 | 14 | Run CMake (3.16+) on this directory from an empty build directory. This might 15 | look like: 16 | 17 | ```bash 18 | % mkdir _build 19 | % cd _build 20 | % cmake /path/to/superbuild 21 | ``` 22 | 23 | You can use tools like `ccmake` or `cmake-gui` to see what options you have. The 24 | following variables control which items are to be built, and with which capabilities: 25 | 26 | - `BUILD_ANARI_SDK` : build the [ANARI-SDK](https://github.com/KhronosGroup/ANARI-SDK) 27 | - `BUILD_ANARI_USD_DEVICE`: build the root 28 | - `BUILD_USD`: build USD + its dependencies (experimental, `OFF` by default) 29 | - Requires preinstalled boost + tbb in `CMAKE_PREFIX_PATH` 30 | - `USD_DEVICE_USE_OPENVDB`: Add OpenVDB output capability for ANARI volumes to the USD device 31 | - Introduces `USE_USD_OPENVDB_BUILD`: If `ON` (default), OpenVDB is included within the USD installation 32 | - `USD_DEVICE_USE_OMNIVERSE`: Add Omniverse output capability for generated USD output 33 | 34 | If `BUILD_USD` or `BUILD_ANARI_SDK` are set to `OFF`, then those dependencies 35 | will need to be found in the host environment. Use `CMAKE_PREFIX_PATH` to 36 | point to your USD + ANARI-SDK (+ OpenVDB + Omniverse) installations respectively. Alternatively, 37 | one can use explicit install dir variables which support `debug/` and `release/` subdirs: 38 | 39 | - `ANARI_ROOT_DIR`: for the ANARI-SDK install directory 40 | - `USD_ROOT_DIR`: for the USD install directory 41 | - `OpenVDB_ROOT`: for the OpenVDB install directory (if not `USE_USD_OPENVDB_BUILD`) 42 | - `OMNICLIENT_ROOT_DIR`: for the OmniClient install directory (typically `omni_client_library` from the connect sample deps). Requires: 43 | - `OMNIUSDRESOLVER_ROOT_DIR`: the Omniverse Resolver install directory (typically `omni_usd_resolver` from the connect sample deps). 44 | - `ZLIB_ROOT`: for the ZLIB install directory, required for Linux builds 45 | 46 | For ease of use, if you want the USD and Omniverse libraries to be copied into the installation's `bin` 47 | directory, make sure `USD_DEVICE_INSTALL_DEPS` is turned on. Otherwise, all dependency folders have to 48 | be manually included into the path before executing the device binaries. 49 | 50 | Lastly, the `BUILD_ANARI_USD_DEVICE` option lets you turn off building the device if you 51 | only want to build the device's dependencies (mostly this is for developers). 52 | 53 | ## Build 54 | 55 | Once you have set up the variables according to your situation, you can invoke the build (Linux) with: 56 | 57 | ```bash 58 | % cmake --build . 59 | ``` 60 | 61 | or open `_build/anari_usd_superbuild.sln` (Windows) and build/install any configuration from there. 62 | 63 | The resulting `install/` directory will contain everything that was built. You 64 | can change the location of this install by setting `CMAKE_INSTALL_PREFIX`. 65 | -------------------------------------------------------------------------------- /superbuild/macros.cmake: -------------------------------------------------------------------------------- 1 | ## Copyright 2021 NVIDIA Corporation 2 | ## SPDX-License-Identifier: Apache-2.0 3 | 4 | macro(append_cmake_prefix_path) 5 | list(APPEND CMAKE_PREFIX_PATH ${ARGN}) 6 | string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") 7 | set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) 8 | endmacro() 9 | 10 | macro(setup_subproject_path_vars _NAME) 11 | set(SUBPROJECT_NAME ${_NAME}) 12 | 13 | set(SUBPROJECT_INSTALL_PATH ${INSTALL_DIR_ABSOLUTE}) 14 | 15 | set(SUBPROJECT_SOURCE_PATH ${SUBPROJECT_NAME}/source) 16 | set(SUBPROJECT_STAMP_PATH ${SUBPROJECT_NAME}/stamp) 17 | set(SUBPROJECT_BUILD_PATH ${SUBPROJECT_NAME}/build) 18 | endmacro() 19 | 20 | function(build_subproject) 21 | # See cmake_parse_arguments docs to see how args get parsed here: 22 | # https://cmake.org/cmake/help/latest/command/cmake_parse_arguments.html 23 | set(oneValueArgs NAME URL SOURCE_DIR) 24 | set(multiValueArgs BUILD_ARGS DEPENDS_ON) 25 | cmake_parse_arguments(BUILD_SUBPROJECT "" "${oneValueArgs}" 26 | "${multiValueArgs}" ${ARGN}) 27 | 28 | if (BUILD_SUBPROJECT_URL AND BUILD_SUBPROJECT_SOURCE_DIR) 29 | message(FATAL_ERROR "URL and SOURCE_DIR are mutually exclusive for build_subproject()") 30 | endif() 31 | 32 | # Setup SUBPROJECT_* variables (containing paths) for this function 33 | setup_subproject_path_vars(${BUILD_SUBPROJECT_NAME}) 34 | 35 | if (BUILD_SUBPROJECT_URL) 36 | set(SOURCE ${SUBPROJECT_SOURCE_PATH}) 37 | set(URL URL ${BUILD_SUBPROJECT_URL}) 38 | else() 39 | set(SOURCE ${BUILD_SUBPROJECT_SOURCE_DIR}) 40 | unset(URL) 41 | endif() 42 | 43 | # Build the actual subproject 44 | ExternalProject_Add(${SUBPROJECT_NAME} 45 | PREFIX ${SUBPROJECT_NAME} 46 | DOWNLOAD_DIR ${SUBPROJECT_NAME} 47 | STAMP_DIR ${SUBPROJECT_STAMP_PATH} 48 | SOURCE_DIR ${SOURCE} 49 | BINARY_DIR ${SUBPROJECT_BUILD_PATH} 50 | ${URL} 51 | LIST_SEPARATOR | # Use the alternate list separator 52 | CMAKE_ARGS 53 | -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} 54 | -DCMAKE_INSTALL_PREFIX:PATH=${SUBPROJECT_INSTALL_PATH} 55 | -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} 56 | ${BUILD_SUBPROJECT_BUILD_ARGS} 57 | BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} 58 | BUILD_ALWAYS OFF 59 | ) 60 | 61 | if(BUILD_SUBPROJECT_DEPENDS_ON) 62 | ExternalProject_Add_StepDependencies(${SUBPROJECT_NAME} 63 | configure ${BUILD_SUBPROJECT_DEPENDS_ON} 64 | ) 65 | endif() 66 | 67 | # Place installed component on CMAKE_PREFIX_PATH for downstream consumption 68 | append_cmake_prefix_path(${SUBPROJECT_INSTALL_PATH}) 69 | endfunction() -------------------------------------------------------------------------------- /thirdparty/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ## Copyright 2020 The Khronos Group 2 | ## SPDX-License-Identifier: Apache-2.0 3 | 4 | add_subdirectory(stb_image) -------------------------------------------------------------------------------- /thirdparty/stb_image/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ## Copyright 2021 NVIDIA Corporation 2 | ## SPDX-License-Identifier: Apache-2.0 3 | 4 | add_library(stb_image STATIC stb_image_write.c stb_image.c) 5 | target_include_directories(stb_image INTERFACE ${CMAKE_CURRENT_LIST_DIR}) -------------------------------------------------------------------------------- /thirdparty/stb_image/stb_image.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #define STB_IMAGE_IMPLEMENTATION 5 | #include "stb_image.h" 6 | -------------------------------------------------------------------------------- /thirdparty/stb_image/stb_image_write.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Khronos Group 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #define STB_IMAGE_WRITE_IMPLEMENTATION 5 | #include "stb_image_write.h" -------------------------------------------------------------------------------- /usd_device.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "name" : "usd_device", 4 | "type" : "device", 5 | "dependencies" : [ 6 | "anari_core_1_0", 7 | "anari_core_objects_base_1_0", 8 | "khr_geometry_cone", 9 | "khr_geometry_curve", 10 | "khr_geometry_cylinder", 11 | "khr_geometry_quad", 12 | "khr_geometry_sphere", 13 | "khr_geometry_triangle", 14 | "khr_geometry_glyph", 15 | "khr_camera_perspective", 16 | "khr_instance_transform", 17 | "khr_material_matte", 18 | "khr_material_physically_based", 19 | "khr_sampler_image1d", 20 | "khr_sampler_image2d", 21 | "khr_sampler_image3d", 22 | "khr_spatial_field_structured_regular", 23 | "khr_volume_transfer_function1d", 24 | "usd_device_features" 25 | ] 26 | } 27 | } 28 | --------------------------------------------------------------------------------