├── src ├── __init__.py ├── usdTriFileFormat │ ├── scenes │ │ ├── empty.triangle │ │ └── triangle.usda │ ├── tests │ │ ├── CMakeLists.txt │ │ └── testFileFormat.py │ ├── CMakeLists.txt │ ├── plugInfo.json │ ├── fileFormat.h │ └── fileFormat.cpp ├── usdTri │ ├── __init__.py │ ├── scenes │ │ ├── triangle.usda │ │ └── expandingTriangle.usda │ ├── tests │ │ ├── CMakeLists.txt │ │ ├── testTriangle.cpp │ │ └── testTriangle.py │ ├── module.cpp │ ├── tokens.cpp │ ├── moduleDeps.cpp │ ├── triangleCounter.cpp │ ├── schema.usda │ ├── CMakeLists.txt │ ├── plugInfo.json │ ├── api.h │ ├── wrapTokens.cpp │ ├── tokens.h │ ├── wrapTriangle.cpp │ ├── generatedSchema.usda │ ├── triangle.cpp │ └── triangle.h ├── plugInfo.json ├── usdviewTri │ ├── CMakeLists.txt │ ├── plugInfo.json │ └── __init__.py ├── hdTri │ ├── renderParam.cpp │ ├── debugCodes.h │ ├── CMakeLists.txt │ ├── debugCodes.cpp │ ├── renderer.h │ ├── renderParam.h │ ├── plugInfo.json │ ├── rendererPlugin.cpp │ ├── rendererPlugin.h │ ├── renderPass.h │ ├── renderPass.cpp │ ├── renderBuffer.h │ ├── renderBuffer.cpp │ ├── renderer.cpp │ ├── renderDelegate.h │ └── renderDelegate.cpp ├── usdTriImagingHd2 │ ├── debugCodes.h │ ├── CMakeLists.txt │ ├── debugCodes.cpp │ ├── plugInfo.json │ ├── dataSourceTri.h │ ├── triangleAdapter.h │ ├── triangleAdapter.cpp │ └── dataSourceTri.cpp ├── usdTriImaging │ ├── debugCodes.h │ ├── CMakeLists.txt │ ├── debugCodes.cpp │ ├── plugInfo.json │ ├── triangleAdapter.h │ └── triangleAdapter.cpp └── CMakeLists.txt ├── images └── triangle_in_viewport.png ├── .github ├── issue_template.md └── workflows │ └── build.yml ├── .clang-format ├── cmake ├── Config.cmake.in ├── Options.cmake ├── Defaults.cmake ├── Export.cmake ├── Packages.cmake ├── packages │ └── FindTBB.cmake └── USDPluginTools.cmake ├── .gitignore ├── CMakeLists.txt ├── README.md └── LICENSE /src/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/usdTriFileFormat/scenes/empty.triangle: -------------------------------------------------------------------------------- 1 | // Dummy file! 2 | -------------------------------------------------------------------------------- /src/usdTri/__init__.py: -------------------------------------------------------------------------------- 1 | from pxr import Tf 2 | Tf.PreparePythonModule() 3 | del Tf 4 | -------------------------------------------------------------------------------- /src/usdTriFileFormat/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | usd_python_test(usdTriFileFormat_python testFileFormat.py) 2 | -------------------------------------------------------------------------------- /images/triangle_in_viewport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wetadigital/USDPluginExamples/HEAD/images/triangle_in_viewport.png -------------------------------------------------------------------------------- /src/usdTri/scenes/triangle.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | ( 3 | defaultPrim = "triangle" 4 | ) 5 | 6 | def Triangle "triangle" 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /src/plugInfo.json: -------------------------------------------------------------------------------- 1 | # Used as the root plugInfo for including all other plugInfo(s). 2 | { 3 | "Includes": [ 4 | "*/resources/" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ### Description of Issue 2 | 3 | ### Steps to Reproduce 4 | 1. 5 | 6 | ### System Information (OS, Hardware) 7 | 8 | ### Build Flags 9 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Mozilla 2 | AccessModifierOffset: -4 3 | IndentWidth: 4 4 | ContinuationIndentWidth: 4 5 | IndentPPDirectives: AfterHash 6 | SortIncludes: false 7 | -------------------------------------------------------------------------------- /src/usdTriFileFormat/scenes/triangle.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | 3 | def "triangle" ( 4 | Usd_Triangle_SideLength = 1 5 | payload = @./empty.triangle@ 6 | ) 7 | { 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/usdviewTri/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | usd_python_library(usdviewTri 2 | PYTHON_INSTALL_PREFIX 3 | ${ORGANIZATION} 4 | 5 | PYTHON_FILES 6 | __init__.py 7 | 8 | RESOURCE_FILES 9 | plugInfo.json 10 | ) 11 | -------------------------------------------------------------------------------- /src/usdTri/scenes/expandingTriangle.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | ( 3 | defaultPrim = "triangle" 4 | endTimeCode = 10 5 | startTimeCode = 1 6 | ) 7 | 8 | def Triangle "triangle" 9 | { 10 | double sideLength.timeSamples = { 11 | 1: 1, 12 | 10: 10, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cmake/Config.cmake.in: -------------------------------------------------------------------------------- 1 | # @CMAKE_PROJECT_NAME@Config.cmake 2 | 3 | get_filename_component(@CMAKE_PROJECT_NAME@_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 4 | if(NOT TARGET @CMAKE_PROJECT_NAME@::usdTri) 5 | include("${@CMAKE_PROJECT_NAME@_CMAKE_DIR}/cmake/@CMAKE_PROJECT_NAME@Targets.cmake") 6 | endif() 7 | -------------------------------------------------------------------------------- /cmake/Options.cmake: -------------------------------------------------------------------------------- 1 | # CMake configuration options exposed for building USDPluginExamples. 2 | 3 | option(ENABLE_PYTHON_SUPPORT "Enable support for python." ON) 4 | option(BUILD_TESTING "Build & execute tests as part of build" ON) 5 | option(BUILD_HYDRA2 "Build Hydra2 Plugins, disables Hydra1 plugins" OFF) 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # A common directory to host intermediate build files. 2 | build/ 3 | 4 | # VIM swap files. 5 | *.sw[pon] 6 | 7 | # Backup files. 8 | .bak 9 | 10 | # C++ object files. 11 | *.o 12 | 13 | # Python cache files. 14 | *.pyc 15 | 16 | # Local convenience scripts. 17 | build.sh 18 | runtime.sh 19 | -------------------------------------------------------------------------------- /src/hdTri/renderParam.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "renderParam.h" 7 | 8 | PXR_NAMESPACE_OPEN_SCOPE 9 | 10 | HdTriRenderParam::HdTriRenderParam() 11 | : HdRenderParam() 12 | { 13 | } 14 | 15 | PXR_NAMESPACE_CLOSE_SCOPE 16 | -------------------------------------------------------------------------------- /src/usdTri/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | usd_python_test(usdTri_python_testTriangle 2 | testTriangle.py 3 | ) 4 | 5 | usd_test(usdTri_testTriangle 6 | 7 | CPPFILES 8 | testTriangle.cpp 9 | 10 | LIBRARIES 11 | tf 12 | sdf 13 | usd 14 | usdGeom 15 | usdTri 16 | ) 17 | -------------------------------------------------------------------------------- /src/hdTri/debugCodes.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | PXR_NAMESPACE_OPEN_SCOPE 12 | 13 | TF_DEBUG_CODES(HDTRI_GENERAL); 14 | 15 | PXR_NAMESPACE_CLOSE_SCOPE 16 | -------------------------------------------------------------------------------- /src/usdTriImagingHd2/debugCodes.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta FX Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | PXR_NAMESPACE_OPEN_SCOPE 12 | 13 | TF_DEBUG_CODES(USDTRIIMAGING); 14 | 15 | PXR_NAMESPACE_CLOSE_SCOPE -------------------------------------------------------------------------------- /src/usdTriImaging/debugCodes.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | PXR_NAMESPACE_OPEN_SCOPE 12 | 13 | TF_DEBUG_CODES(USDTRIIMAGING); 14 | 15 | PXR_NAMESPACE_CLOSE_SCOPE 16 | -------------------------------------------------------------------------------- /src/hdTri/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB CPPFILES *.cpp) 2 | 3 | usd_plugin(hdTri 4 | 5 | CPPFILES 6 | ${CPPFILES} 7 | 8 | LIBRARIES 9 | arch 10 | js 11 | plug 12 | tf 13 | sdf 14 | vt 15 | gf 16 | hd 17 | hf 18 | 19 | RESOURCE_FILES 20 | plugInfo.json 21 | ) 22 | 23 | -------------------------------------------------------------------------------- /src/hdTri/debugCodes.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "debugCodes.h" 7 | 8 | PXR_NAMESPACE_OPEN_SCOPE 9 | 10 | TF_REGISTRY_FUNCTION(TfDebug) 11 | { 12 | TF_DEBUG_ENVIRONMENT_SYMBOL(HDTRI_GENERAL, "HdTri general debug logging."); 13 | } 14 | 15 | PXR_NAMESPACE_CLOSE_SCOPE 16 | -------------------------------------------------------------------------------- /src/usdTriFileFormat/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | usd_plugin(usdTriFileFormat 2 | 3 | CPPFILES 4 | fileFormat.cpp 5 | 6 | LIBRARIES 7 | tf 8 | sdf 9 | vt 10 | gf 11 | pcp 12 | usd 13 | usdGeom 14 | arch 15 | 16 | RESOURCE_FILES 17 | plugInfo.json 18 | ) 19 | 20 | add_subdirectory(tests) 21 | -------------------------------------------------------------------------------- /src/usdTri/module.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include 7 | #include 8 | 9 | // Definition of the _usdTri python module, with associated classes and 10 | // functions. 11 | 12 | PXR_NAMESPACE_USING_DIRECTIVE 13 | 14 | TF_WRAP_MODULE 15 | { 16 | TF_WRAP(UsdTriTriangle); 17 | } 18 | -------------------------------------------------------------------------------- /src/usdTriImaging/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | usd_plugin(usdTriImaging 2 | 3 | CPPFILES 4 | triangleAdapter.cpp 5 | debugCodes.cpp 6 | 7 | LIBRARIES 8 | arch 9 | js 10 | plug 11 | usd 12 | tf 13 | sdf 14 | vt 15 | gf 16 | hd 17 | usdGeom 18 | usdImaging 19 | usdTri 20 | 21 | RESOURCE_FILES 22 | plugInfo.json 23 | ) 24 | 25 | -------------------------------------------------------------------------------- /src/usdTriImagingHd2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | usd_plugin(usdTriImagingHd2 2 | 3 | CPPFILES 4 | triangleAdapter.cpp 5 | debugCodes.cpp 6 | dataSourceTri.cpp 7 | 8 | LIBRARIES 9 | arch 10 | js 11 | plug 12 | usd 13 | tf 14 | sdf 15 | vt 16 | gf 17 | hd 18 | usdGeom 19 | usdImaging 20 | usdTri 21 | 22 | RESOURCE_FILES 23 | plugInfo.json 24 | ) -------------------------------------------------------------------------------- /src/usdTriImagingHd2/debugCodes.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta FX Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "debugCodes.h" 7 | 8 | #include 9 | 10 | PXR_NAMESPACE_OPEN_SCOPE 11 | 12 | TF_REGISTRY_FUNCTION(TfDebug) 13 | { 14 | TF_DEBUG_ENVIRONMENT_SYMBOL(USDTRIIMAGING, 15 | "Global debug symbol for usdTriImaging."); 16 | } 17 | 18 | PXR_NAMESPACE_CLOSE_SCOPE -------------------------------------------------------------------------------- /src/usdTriImaging/debugCodes.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "debugCodes.h" 7 | 8 | #include 9 | 10 | PXR_NAMESPACE_OPEN_SCOPE 11 | 12 | TF_REGISTRY_FUNCTION(TfDebug) 13 | { 14 | TF_DEBUG_ENVIRONMENT_SYMBOL(USDTRIIMAGING, 15 | "Global debug symbol for usdTriImaging."); 16 | } 17 | 18 | PXR_NAMESPACE_CLOSE_SCOPE 19 | -------------------------------------------------------------------------------- /src/usdTri/tokens.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "./tokens.h" 7 | 8 | PXR_NAMESPACE_OPEN_SCOPE 9 | 10 | UsdTriTokensType::UsdTriTokensType() 11 | : extent("extent", TfToken::Immortal) 12 | , sideLength("sideLength", TfToken::Immortal) 13 | , Triangle("Triangle", TfToken::Immortal) 14 | , allTokens({ extent, sideLength, Triangle }) 15 | { 16 | } 17 | 18 | TfStaticData UsdTriTokens; 19 | 20 | PXR_NAMESPACE_CLOSE_SCOPE 21 | -------------------------------------------------------------------------------- /src/usdviewTri/plugInfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "Plugins": [ 3 | { 4 | "Type": "python", 5 | "Name": "usdpluginexamples.UsdviewTri", 6 | "Info": { 7 | "Types": { 8 | "usdpluginexamples.UsdviewTri.UsdviewTriPluginContainer": { 9 | "bases": ["pxr.Usdviewq.plugin.PluginContainer"], 10 | "displayName": "Usdview Tri Plugin" 11 | } 12 | } 13 | } 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/hdTri/renderer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | PXR_NAMESPACE_OPEN_SCOPE 9 | 10 | // Forward declarations. 11 | class HdTriRenderBuffer; 12 | 13 | /// \class HdTriRenderer 14 | /// 15 | /// A triangle renderer. 16 | class HdTriRenderer final 17 | { 18 | public: 19 | /// Draw a triangle into a color buffer. 20 | /// 21 | /// \param colorBuffer A 2D color buffer. 22 | static void DrawTriangle(HdTriRenderBuffer* colorBuffer); 23 | }; 24 | 25 | PXR_NAMESPACE_CLOSE_SCOPE 26 | -------------------------------------------------------------------------------- /src/hdTri/renderParam.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | PXR_NAMESPACE_OPEN_SCOPE 12 | 13 | /// \class HdTriRenderParam 14 | /// 15 | /// Object created by the render delegate to transport top-level scene state 16 | /// to each prim during Sync(). 17 | class HdTriRenderParam final : public HdRenderParam 18 | { 19 | public: 20 | HdTriRenderParam(); 21 | virtual ~HdTriRenderParam() = default; 22 | }; 23 | 24 | PXR_NAMESPACE_CLOSE_SCOPE 25 | -------------------------------------------------------------------------------- /src/usdTriImagingHd2/plugInfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "Plugins": [ 3 | { 4 | "Info": { 5 | "Types": { 6 | "UsdTriImagingTriangleAdapterHd2": { 7 | "bases": [ 8 | "UsdImagingGprimAdapter" 9 | ], 10 | "primTypeName": "Triangle" 11 | } 12 | } 13 | }, 14 | "LibraryPath": "@PLUG_INFO_LIBRARY_PATH@", 15 | "Name": "usdTriImaging", 16 | "ResourcePath": "@PLUG_INFO_RESOURCE_PATH@", 17 | "Root": "@PLUG_INFO_ROOT@", 18 | "Type": "library" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /src/usdTriImaging/plugInfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "Plugins": [ 3 | { 4 | "Info": { 5 | "Types": { 6 | "UsdTriImagingTriangleAdapter": { 7 | "bases": [ 8 | "UsdImagingGprimAdapter" 9 | ], 10 | "primTypeName": "Triangle" 11 | } 12 | } 13 | }, 14 | "LibraryPath": "@PLUG_INFO_LIBRARY_PATH@", 15 | "Name": "usdTriImaging", 16 | "ResourcePath": "@PLUG_INFO_RESOURCE_PATH@", 17 | "Root": "@PLUG_INFO_ROOT@", 18 | "Type": "library" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/hdTri/plugInfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "Plugins": [ 3 | { 4 | "Info": { 5 | "Types": { 6 | "HdTriRendererPlugin": { 7 | "bases": [ 8 | "HdRendererPlugin" 9 | ], 10 | "displayName": "Tri", 11 | "priority": 99 12 | } 13 | } 14 | }, 15 | "LibraryPath": "@PLUG_INFO_LIBRARY_PATH@", 16 | "Name": "hdTri", 17 | "ResourcePath": "@PLUG_INFO_RESOURCE_PATH@", 18 | "Root": "@PLUG_INFO_ROOT@", 19 | "Type": "library" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/hdTri/rendererPlugin.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "renderDelegate.h" 7 | #include "rendererPlugin.h" 8 | 9 | #include 10 | 11 | PXR_NAMESPACE_OPEN_SCOPE 12 | 13 | TF_REGISTRY_FUNCTION(TfType) 14 | { 15 | HdRendererPluginRegistry::Define(); 16 | } 17 | 18 | HdRenderDelegate* 19 | HdTriRendererPlugin::CreateRenderDelegate() 20 | { 21 | return new HdTriRenderDelegate(); 22 | } 23 | 24 | void 25 | HdTriRendererPlugin::DeleteRenderDelegate(HdRenderDelegate* renderDelegate) 26 | { 27 | delete renderDelegate; 28 | } 29 | 30 | bool 31 | HdTriRendererPlugin::IsSupported(bool gpuEnabled) const 32 | { 33 | return true; 34 | } 35 | 36 | PXR_NAMESPACE_CLOSE_SCOPE 37 | -------------------------------------------------------------------------------- /src/usdTri/tests/testTriangle.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include 7 | #include 8 | #include 9 | 10 | PXR_NAMESPACE_USING_DIRECTIVE 11 | 12 | int 13 | main(int argc, char* argv[]) 14 | { 15 | // Create a new stage. 16 | UsdStageRefPtr stage = UsdStage::CreateInMemory(); 17 | 18 | // Define a Triangle. 19 | UsdTriTriangle triangle = 20 | UsdTriTriangle::Define(stage, SdfPath("/myTriangle")); 21 | TF_AXIOM(triangle); 22 | 23 | // Validate side length attr fallback value. 24 | double sideLength; 25 | TF_AXIOM(triangle.GetSideLengthAttr().Get(&sideLength)); 26 | TF_AXIOM(sideLength == 1.0f); 27 | 28 | return EXIT_SUCCESS; 29 | } 30 | -------------------------------------------------------------------------------- /src/usdviewTri/__init__.py: -------------------------------------------------------------------------------- 1 | from pxr import Tf 2 | from pxr.Usdviewq.plugin import PluginContainer 3 | 4 | 5 | def DefineChildTriangle(usdviewApi): 6 | for selectedPath in usdviewApi.selectedPaths: 7 | usdviewApi.stage.DefinePrim(selectedPath.AppendChild("triangle"), "Triangle") 8 | 9 | 10 | class UsdviewTriPluginContainer(PluginContainer): 11 | 12 | def registerPlugins(self, plugRegistry, usdviewApi): 13 | self._defineChildTriangle = plugRegistry.registerCommandPlugin( 14 | "UsdviewTriPluginContainer.DefineChildTriangle", 15 | "Define Child Triangle", 16 | DefineChildTriangle) 17 | 18 | def configureView(self, plugRegistry, plugUIBuilder): 19 | triMenu = plugUIBuilder.findOrCreateMenu("Tri") 20 | triMenu.addItem(self._defineChildTriangle) 21 | 22 | 23 | Tf.Type.Define(UsdviewTriPluginContainer) 24 | -------------------------------------------------------------------------------- /src/usdTri/moduleDeps.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | PXR_NAMESPACE_OPEN_SCOPE 14 | 15 | TF_REGISTRY_FUNCTION(TfScriptModuleLoader) 16 | { 17 | // List of direct dependencies for this library. 18 | const std::vector reqs = { 19 | TfToken("js"), TfToken("plug"), TfToken("sdf"), 20 | TfToken("tf"), TfToken("trace"), TfToken("usd"), 21 | TfToken("vt"), TfToken("work"), TfToken("usdGeom"), 22 | }; 23 | TfScriptModuleLoader::GetInstance().RegisterLibrary( 24 | TfToken("usdTri"), TfToken("usdpluginexamples.UsdTri"), reqs); 25 | } 26 | 27 | PXR_NAMESPACE_CLOSE_SCOPE 28 | -------------------------------------------------------------------------------- /src/usdTri/triangleCounter.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | /* A simple program which opens an input USD file, and prints 8 | * the number of prims of type "Triangle" in the composed stage */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | PXR_NAMESPACE_USING_DIRECTIVE 15 | 16 | int 17 | main(int argc, char* argv[]) 18 | { 19 | if (argc != 2) { 20 | printf("usage: triangleCounter \n"); 21 | return EXIT_FAILURE; 22 | } 23 | 24 | int triangleCount = 0; 25 | UsdStageRefPtr stage = UsdStage::Open(argv[1]); 26 | for (UsdPrim prim : stage->TraverseAll()) { 27 | if (prim.IsA()) { 28 | triangleCount++; 29 | } 30 | } 31 | 32 | printf("Number of triangles: %i\n", triangleCount); 33 | return EXIT_SUCCESS; 34 | } 35 | -------------------------------------------------------------------------------- /src/usdTri/schema.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | ( 3 | subLayers = [ 4 | @usdGeom/schema.usda@ 5 | ] 6 | ) 7 | 8 | over "GLOBAL" ( 9 | customData = { 10 | string libraryName = "usdTri" 11 | string libraryPath = "." 12 | string libraryPrefix = "UsdTri" 13 | } 14 | ) { 15 | } 16 | 17 | class Triangle "Triangle" ( 18 | doc = """An equilateral triangle, whose vertices are equidistant to the 19 | origin and lie on the XY plane in object-space.""" 20 | inherits = 21 | 22 | customData = { 23 | dictionary extraPlugInfo = { 24 | bool implementsComputeExtent = true 25 | } 26 | } 27 | ) { 28 | double sideLength = 1.0 ( 29 | doc = """The length of each side of the equilateral triangle.""" 30 | ) 31 | 32 | float3[] extent = [(-0.5, -0.28867513, 0.0), (0.5, 0.57735027, 0.0)] ( 33 | doc = """Fallback extent value of a triangle with side length of 1.0.""" 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /src/usdTri/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | usd_library(usdTri 2 | 3 | PUBLIC_HEADERS_INSTALL_PREFIX 4 | ${ORGANIZATION} 5 | 6 | PYTHON_INSTALL_PREFIX 7 | ${ORGANIZATION} 8 | 9 | LIBRARIES 10 | js 11 | plug 12 | tf 13 | sdf 14 | vt 15 | gf 16 | usd 17 | usdGeom 18 | arch 19 | 20 | PUBLIC_CLASSES 21 | triangle 22 | 23 | PUBLIC_HEADERS 24 | api.h 25 | tokens.h 26 | 27 | CPPFILES 28 | tokens.cpp 29 | 30 | PYTHON_CPPFILES 31 | moduleDeps.cpp 32 | 33 | PYMODULE_CPPFILES 34 | module.cpp 35 | wrapTokens.cpp 36 | wrapTriangle.cpp 37 | 38 | PYTHON_FILES 39 | __init__.py 40 | 41 | RESOURCE_FILES 42 | generatedSchema.usda 43 | plugInfo.json 44 | ) 45 | 46 | usd_executable(triangleCounter 47 | 48 | CPPFILES 49 | triangleCounter.cpp 50 | 51 | LIBRARIES 52 | tf 53 | sdf 54 | usd 55 | usdTri 56 | ) 57 | 58 | add_subdirectory(tests) 59 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 3.13 for target_link_directories. 2 | cmake_minimum_required(VERSION 3.13) 3 | 4 | # Define project. 5 | project( 6 | USDPluginExamples 7 | VERSION 0.0.0 8 | DESCRIPTION "A collection of example plugins for Pixar's USD (Universal Scene Description)." 9 | LANGUAGES CXX 10 | ) 11 | 12 | # Discover cmake modules. 13 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} 14 | ${CMAKE_CURRENT_SOURCE_DIR}/cmake/ 15 | ${CMAKE_CURRENT_SOURCE_DIR}/cmake/packages 16 | ) 17 | 18 | # Exposes build options (with default values) for this project. 19 | include(Options) 20 | 21 | # Set project defaults. 22 | include(Defaults) 23 | 24 | # Import the package dependencies (USD, TBB, ...). 25 | include(Packages) 26 | 27 | # Include USD plugin building CMake utilities. 28 | include(USDPluginTools) 29 | 30 | # Recurse into source tree. 31 | add_subdirectory(src) 32 | 33 | # Export targets and install package files. 34 | # This must come after source tree recursion as exporting targets 35 | # requires the targets to be defined in the first place! 36 | include(Export) 37 | -------------------------------------------------------------------------------- /src/usdTri/plugInfo.json: -------------------------------------------------------------------------------- 1 | # Portions of this file auto-generated by usdGenSchema. 2 | # Edits will survive regeneration except for comments and 3 | # changes to types with autoGenerated=true. 4 | { 5 | "Plugins": [ 6 | { 7 | "Info": { 8 | "Types": { 9 | "UsdTriTriangle": { 10 | "alias": { 11 | "UsdSchemaBase": "Triangle" 12 | }, 13 | "autoGenerated": true, 14 | "bases": [ 15 | "UsdGeomGprim" 16 | ], 17 | "implementsComputeExtent": true, 18 | "schemaKind": "concreteTyped" 19 | } 20 | } 21 | }, 22 | "LibraryPath": "@PLUG_INFO_LIBRARY_PATH@", 23 | "Name": "usdTri", 24 | "ResourcePath": "@PLUG_INFO_RESOURCE_PATH@", 25 | "Root": "@PLUG_INFO_ROOT@", 26 | "Type": "library" 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /src/usdTri/tests/testTriangle.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from pxr import Gf, Vt, Usd, UsdGeom 3 | from usdpluginexamples import UsdTri 4 | 5 | 6 | class TestTriangle(unittest.TestCase): 7 | def testComputeExtent(self): 8 | # Create a stage. 9 | stage = Usd.Stage.CreateInMemory() 10 | 11 | # Define a Triangle. 12 | triangle = UsdTri.Triangle.Define(stage, "/triangle") 13 | self.assertTrue(triangle) 14 | self.assertEqual(triangle.GetSideLengthAttr().Get(), 1) 15 | 16 | # Compute extent & validate. 17 | boundable = UsdGeom.Boundable(triangle.GetPrim()) 18 | self.assertTrue(boundable) 19 | extent = UsdGeom.Boundable.ComputeExtentFromPlugins( 20 | boundable, Usd.TimeCode.Default() 21 | ) 22 | expectedExtent = Vt.Vec3fArray(((0.5, -0.28867513, 0), (0.5, 0.57735026, 0))) 23 | for actualValue, expectedValue in zip(extent, expectedExtent): 24 | self.assertTrue(Gf.IsClose(actualValue, expectedValue, 1e-5)) 25 | 26 | 27 | if __name__ == "__main__": 28 | unittest.main() 29 | -------------------------------------------------------------------------------- /src/hdTri/rendererPlugin.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include 9 | 10 | PXR_NAMESPACE_OPEN_SCOPE 11 | 12 | /// Plugin entry points (construction, destruction) for the tri render delegate. 13 | class HdTriRendererPlugin final : public HdRendererPlugin 14 | { 15 | public: 16 | HdTriRendererPlugin() = default; 17 | ~HdTriRendererPlugin() override = default; 18 | 19 | /// Cannot copy. 20 | HdTriRendererPlugin(const HdTriRendererPlugin&) = delete; 21 | HdTriRendererPlugin& operator=(const HdTriRendererPlugin&) = delete; 22 | 23 | /// Create a new tri render delegate instance. 24 | virtual HdRenderDelegate* CreateRenderDelegate() override; 25 | 26 | /// Delete a tri render delegate instance. 27 | virtual void DeleteRenderDelegate( 28 | HdRenderDelegate* renderDelegate) override; 29 | 30 | /// Is this plugin supported? 31 | virtual bool IsSupported(bool gpuEnabled = true) const override; 32 | }; 33 | 34 | PXR_NAMESPACE_CLOSE_SCOPE 35 | -------------------------------------------------------------------------------- /cmake/Defaults.cmake: -------------------------------------------------------------------------------- 1 | # Default build configurations for the USDPluginExamples project. 2 | 3 | # By default, build for release. 4 | if(NOT CMAKE_BUILD_TYPE) 5 | set(CMAKE_BUILD_TYPE "Release") 6 | endif() 7 | 8 | # Check if CTest should be enabled. 9 | if (BUILD_TESTING) 10 | enable_testing() 11 | 12 | # Be very verbose on test failure. 13 | list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure") 14 | endif() 15 | 16 | if (MSVC) 17 | # From OpenUSD/cmake/defaults/msvcdefaults.cmake 18 | # 19 | # The /Zc:inline option strips out the "arch_ctor_" symbols used for 20 | # library initialization by ARCH_CONSTRUCTOR starting in Visual Studio 2019, 21 | # causing release builds to fail. Disable the option for this and later 22 | # versions. 23 | # 24 | # For more details, see: 25 | # https://developercommunity.visualstudio.com/content/problem/914943/zcinline-removes-extern-symbols-inside-anonymous-n.html 26 | if (MSVC_VERSION GREATER_EQUAL 1920) 27 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:inline-") 28 | else() 29 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:inline") 30 | endif() 31 | endif() 32 | -------------------------------------------------------------------------------- /src/usdTri/api.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #ifndef USDTRI_API_H 7 | #define USDTRI_API_H 8 | 9 | #include "pxr/base/arch/export.h" 10 | 11 | #if defined(PXR_STATIC) 12 | # define USDTRI_API 13 | # define USDTRI_API_TEMPLATE_CLASS(...) 14 | # define USDTRI_API_TEMPLATE_STRUCT(...) 15 | # define USDTRI_LOCAL 16 | #else 17 | # if defined(USDTRI_EXPORTS) 18 | # define USDTRI_API ARCH_EXPORT 19 | # define USDTRI_API_TEMPLATE_CLASS(...) \ 20 | ARCH_EXPORT_TEMPLATE(class, __VA_ARGS__) 21 | # define USDTRI_API_TEMPLATE_STRUCT(...) \ 22 | ARCH_EXPORT_TEMPLATE(struct, __VA_ARGS__) 23 | # else 24 | # define USDTRI_API ARCH_IMPORT 25 | # define USDTRI_API_TEMPLATE_CLASS(...) \ 26 | ARCH_IMPORT_TEMPLATE(class, __VA_ARGS__) 27 | # define USDTRI_API_TEMPLATE_STRUCT(...) \ 28 | ARCH_IMPORT_TEMPLATE(struct, __VA_ARGS__) 29 | # endif 30 | # define USDTRI_LOCAL ARCH_HIDDEN 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/hdTri/renderPass.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include 9 | 10 | PXR_NAMESPACE_OPEN_SCOPE 11 | 12 | /// \class HdTriRenderPass 13 | /// 14 | /// Represents a single iteration of a render. 15 | class HdTriRenderPass final : public HdRenderPass 16 | { 17 | public: 18 | HdTriRenderPass(HdRenderIndex* index, const HdRprimCollection& collection); 19 | virtual ~HdTriRenderPass(); 20 | 21 | protected: 22 | /// Draw the scene with the bound renderpass state. 23 | /// 24 | /// \param renderPassState Input parameters (including viewer parameters) 25 | /// for this renderpass. \param renderTags Which rendertags should be drawn 26 | /// this pass. 27 | virtual void _Execute(const HdRenderPassStateSharedPtr& renderPassState, 28 | const TfTokenVector& renderTags) override; 29 | 30 | /// Determine whether the sample buffer has enough samples, to be considered 31 | /// final. 32 | virtual bool IsConverged() const override; 33 | 34 | private: 35 | // Is converged? 36 | bool _converged = false; 37 | }; 38 | 39 | PXR_NAMESPACE_CLOSE_SCOPE 40 | -------------------------------------------------------------------------------- /src/usdTriFileFormat/plugInfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "Plugins": [ 3 | { 4 | "Info": { 5 | "SdfMetadata": { 6 | "Usd_Triangle_SideLength": { 7 | "type": "double", 8 | "displayGroup": "Core", 9 | "appliesTo": ["prims"], 10 | "documentation:": "Length of the triangle side." 11 | } 12 | }, 13 | "Types": { 14 | "UsdTriangleFileFormat": { 15 | "bases": [ 16 | "SdfFileFormat" 17 | ], 18 | "displayName": "USD Triangle File Format", 19 | "extensions": [ 20 | "triangle" 21 | ], 22 | "formatId": "usdTriangleFileFormat", 23 | "primary": true, 24 | "target": "usd" 25 | } 26 | } 27 | }, 28 | "LibraryPath": "@PLUG_INFO_LIBRARY_PATH@", 29 | "Name": "usdTriFileFormat", 30 | "ResourcePath": "@PLUG_INFO_RESOURCE_PATH@", 31 | "Root": "@PLUG_INFO_ROOT@", 32 | "Type": "library" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /cmake/Export.cmake: -------------------------------------------------------------------------------- 1 | # This module is for exporting targets and installing CMake package 2 | # files which are used to import _this_ project into _other_ projects 3 | # in a robust manner. 4 | # 5 | # Note For developers using USDPluginExamples as a template: 6 | # Depending on the nature of your project, this module is optional. 7 | 8 | # Install exported library targets. 9 | install( 10 | EXPORT ${CMAKE_PROJECT_NAME}-targets 11 | NAMESPACE USDPluginExamples:: 12 | FILE ${CMAKE_PROJECT_NAME}Targets.cmake 13 | DESTINATION cmake 14 | ) 15 | 16 | # Configure and write Config.cmake to provide package import entry point. 17 | configure_file( 18 | ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake.in 19 | ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}Config.cmake 20 | @ONLY 21 | ) 22 | 23 | # Configure and write ConfigVersion.cmake for version compatibility management. 24 | include(CMakePackageConfigHelpers) 25 | write_basic_package_version_file( 26 | ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}ConfigVersion.cmake 27 | VERSION ${CMAKE_PROJECT_VERSION} 28 | COMPATIBILITY SameMajorVersion 29 | ) 30 | 31 | # Install the package configuration files. 32 | install( 33 | FILES 34 | ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}Config.cmake 35 | ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}ConfigVersion.cmake 36 | DESTINATION ${CMAKE_INSTALL_PREFIX} 37 | ) 38 | -------------------------------------------------------------------------------- /src/hdTri/renderPass.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "renderPass.h" 7 | #include "renderBuffer.h" 8 | #include "renderer.h" 9 | #include "debugCodes.h" 10 | 11 | #include 12 | #include 13 | 14 | PXR_NAMESPACE_OPEN_SCOPE 15 | 16 | HdTriRenderPass::HdTriRenderPass(HdRenderIndex* index, 17 | const HdRprimCollection& collection) 18 | : HdRenderPass(index, collection) 19 | { 20 | } 21 | 22 | HdTriRenderPass::~HdTriRenderPass() {} 23 | 24 | bool 25 | HdTriRenderPass::IsConverged() const 26 | { 27 | return _converged; 28 | } 29 | 30 | void 31 | HdTriRenderPass::_Execute(const HdRenderPassStateSharedPtr& renderPassState, 32 | const TfTokenVector& renderTags) 33 | { 34 | TF_DEBUG(HDTRI_GENERAL) 35 | .Msg("[%s] Executing render pass\n", TF_FUNC_NAME().c_str()); 36 | 37 | // Iterate over each AOV. 38 | HdRenderPassAovBindingVector aovBindings = 39 | renderPassState->GetAovBindings(); 40 | for (const HdRenderPassAovBinding& aovBinding : aovBindings) { 41 | 42 | // We will only write into the color AOV buffer. 43 | if (aovBinding.aovName == HdAovTokens->color) { 44 | HdTriRenderBuffer* renderBuffer = 45 | static_cast(aovBinding.renderBuffer); 46 | HdTriRenderer::DrawTriangle(renderBuffer); 47 | } 48 | } 49 | 50 | _converged = true; 51 | } 52 | 53 | PXR_NAMESPACE_CLOSE_SCOPE 54 | -------------------------------------------------------------------------------- /src/usdTriFileFormat/tests/testFileFormat.py: -------------------------------------------------------------------------------- 1 | import os 2 | import unittest 3 | from pxr import Vt, Gf, Sdf, Usd, UsdGeom 4 | 5 | 6 | class TestUsdTriangleFileFormat(unittest.TestCase): 7 | def testPayloadExpansion(self): 8 | # Create a new stage. 9 | stage = Usd.Stage.CreateInMemory() 10 | 11 | # Define a un-typed prim, with side length metadatum value of 5. 12 | prim = stage.DefinePrim("/triangle") 13 | prim.SetMetadata("Usd_Triangle_SideLength", 5) 14 | 15 | # Set payload path to ../scenes/empty.triangle. 16 | payloadPath = os.path.join( 17 | os.path.dirname(__file__), "..", "scenes", "empty.triangle" 18 | ) 19 | prim.SetPayload(Sdf.Payload(payloadPath)) 20 | 21 | # Should be expanded into a mesh! 22 | mesh = UsdGeom.Mesh(prim) 23 | self.assertTrue(mesh) 24 | 25 | # Validate mesh attribute values. 26 | self.assertEqual(mesh.GetFaceVertexCountsAttr().Get(), Vt.IntArray((3,))) 27 | self.assertEqual(mesh.GetFaceVertexIndicesAttr().Get(), Vt.IntArray((0, 1, 2,))) 28 | 29 | actualPoints = mesh.GetPointsAttr().Get() 30 | expectedPoints = Vt.Vec3fArray( 31 | ( 32 | Gf.Vec3f(0.0, 2.88675, 0.0), 33 | Gf.Vec3f(-2.5, -1.44337, 0.0), 34 | Gf.Vec3f(2.5, -1.44337, 0.0), 35 | ) 36 | ) 37 | self.assertEqual(len(actualPoints), len(expectedPoints)) 38 | for actualPoint, expectedPoint in zip(actualPoints, expectedPoints): 39 | self.assertTrue(Gf.IsClose(actualPoint, expectedPoint, 1e-5)) 40 | 41 | 42 | if __name__ == "__main__": 43 | unittest.main() 44 | -------------------------------------------------------------------------------- /src/usdTri/wrapTokens.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | // GENERATED FILE. DO NOT EDIT. 7 | #include 8 | #include "./tokens.h" 9 | 10 | PXR_NAMESPACE_USING_DIRECTIVE 11 | 12 | namespace { 13 | 14 | // Helper to return a static token as a string. We wrap tokens as Python 15 | // strings and for some reason simply wrapping the token using def_readonly 16 | // bypasses to-Python conversion, leading to the error that there's no 17 | // Python type for the C++ TfToken type. So we wrap this functor instead. 18 | class _WrapStaticToken 19 | { 20 | public: 21 | _WrapStaticToken(const TfToken* token) 22 | : _token(token) 23 | { 24 | } 25 | 26 | std::string operator()() const { return _token->GetString(); } 27 | 28 | private: 29 | const TfToken* _token; 30 | }; 31 | 32 | template 33 | void 34 | _AddToken(T& cls, const char* name, const TfToken& token) 35 | { 36 | cls.add_static_property( 37 | name, 38 | boost::python::make_function(_WrapStaticToken(&token), 39 | boost::python::return_value_policy< 40 | boost::python::return_by_value>(), 41 | boost::mpl::vector1())); 42 | } 43 | 44 | } // anonymous 45 | 46 | void 47 | wrapUsdTriTokens() 48 | { 49 | boost::python::class_ cls( 50 | "Tokens", boost::python::no_init); 51 | _AddToken(cls, "extent", UsdTriTokens->extent); 52 | _AddToken(cls, "sideLength", UsdTriTokens->sideLength); 53 | _AddToken(cls, "Triangle", UsdTriTokens->Triangle); 54 | } 55 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # A top-level name used as the root directory for public headers 2 | # installation, and the root python module. 3 | # This is optional. See ./usdTri/CMakeLists.txt for how it's used. 4 | set(ORGANIZATION "usdpluginexamples") 5 | 6 | # Build & install libraries. 7 | add_subdirectory(usdTri) 8 | add_subdirectory(usdviewTri) 9 | 10 | # Build & install plugins. 11 | if (BUILD_HYDRA2) 12 | add_subdirectory(usdTriImagingHd2) 13 | else() 14 | add_subdirectory(usdTriImaging) 15 | endif() 16 | 17 | add_subdirectory(usdTriFileFormat) 18 | add_subdirectory(hdTri) 19 | 20 | # Install top-level plugInfo for including per-library plugInfo(s). 21 | install( 22 | FILES plugInfo.json 23 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/${USD_PLUG_INFO_ROOT_DIR} 24 | ) 25 | 26 | # Install top-level plugInfo for including per-plugin plugInfo(s). 27 | install( 28 | FILES plugInfo.json 29 | DESTINATION ${USD_PLUGIN_DIR}/${USD_PLUG_INFO_ROOT_DIR} 30 | ) 31 | 32 | # Install top level python __init__.py 33 | install( 34 | FILES __init__.py 35 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/${USD_PYTHON_DIR}/${ORGANIZATION} 36 | ) 37 | 38 | # Mirror installation structure in intermediate binary dir for running tests against. 39 | if (BUILD_TESTING) 40 | file( 41 | COPY plugInfo.json 42 | DESTINATION ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/${USD_PLUG_INFO_ROOT_DIR} 43 | ) 44 | 45 | file( 46 | COPY plugInfo.json 47 | DESTINATION ${PROJECT_BINARY_DIR}/${USD_PLUGIN_DIR}/${USD_PLUG_INFO_ROOT_DIR} 48 | ) 49 | 50 | file( 51 | COPY __init__.py 52 | DESTINATION ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/${USD_PYTHON_DIR}/${ORGANIZATION} 53 | ) 54 | endif() 55 | 56 | -------------------------------------------------------------------------------- /src/usdTriImagingHd2/dataSourceTri.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta FX Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include "pxr/usdImaging/usdImaging/dataSourceGprim.h" 9 | 10 | PXR_NAMESPACE_OPEN_SCOPE 11 | 12 | /// 13 | /// \brief The UsdImagingDataSourceTriPrim class - inheriting from a GPrim 14 | /// DataSource as we can use a lot of the existing infrastructure of GPrims e.g. 15 | /// support for Transforms, Primvars etc. 16 | /// We do override the implementations for 'Points' & 'Topology' to return the 17 | /// triangle relevant data. An other approach could be to override 18 | /// the UsdImagingGprimAdapter::GetPoints() / 19 | /// UsdImagingGprimAdapter::GetTopology functions 20 | /// 21 | class UsdImagingDataSourceTriPrim : public UsdImagingDataSourceGprim 22 | { 23 | public: 24 | HD_DECLARE_DATASOURCE(UsdImagingDataSourceTriPrim); 25 | 26 | // return the names of the data-sources this object can provide 27 | TfTokenVector GetNames() override; 28 | 29 | // return the data-sources based on the names 30 | HdDataSourceBaseHandle Get(const TfToken& i_name) override; 31 | 32 | // callbacks to help which DataSource Locations need to be invalidated 33 | // based on the prim/subPrim/properties 34 | static HdDataSourceLocatorSet Invalidate( 35 | UsdPrim const& prim, 36 | const TfToken& subprim, 37 | const TfTokenVector& properties, 38 | UsdImagingPropertyInvalidationType invalidationType); 39 | 40 | private: 41 | UsdImagingDataSourceTriPrim( 42 | const SdfPath& sceneIndexPath, 43 | UsdPrim usdPrim, 44 | const UsdImagingDataSourceStageGlobals& stageGlobals); 45 | }; 46 | 47 | HD_DECLARE_DATASOURCE_HANDLES(UsdImagingDataSourceTriPrim); 48 | 49 | PXR_NAMESPACE_CLOSE_SCOPE -------------------------------------------------------------------------------- /src/usdTriImagingHd2/triangleAdapter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta FX Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include 9 | 10 | PXR_NAMESPACE_OPEN_SCOPE 11 | 12 | /// \class UsdTriImagingTriangleAdapterHd2 13 | /// 14 | /// PrimAdapter plugin for the "Triangle" prim type. 15 | class UsdTriImagingTriangleAdapterHd2 : public UsdImagingGprimAdapter 16 | { 17 | public: 18 | using BaseAdapter = UsdImagingGprimAdapter; 19 | 20 | // ---------------------------------------------------------------------- // 21 | /// \name Scene Index Support 22 | // ---------------------------------------------------------------------- // 23 | 24 | virtual TfTokenVector GetImagingSubprims(UsdPrim const& prim) override; 25 | 26 | virtual TfToken GetImagingSubprimType(UsdPrim const& prim, 27 | TfToken const& subprim) override; 28 | 29 | virtual HdContainerDataSourceHandle GetImagingSubprimData( 30 | UsdPrim const& prim, 31 | TfToken const& subprim, 32 | const UsdImagingDataSourceStageGlobals& stageGlobals) override; 33 | 34 | virtual HdDataSourceLocatorSet InvalidateImagingSubprim( 35 | UsdPrim const& prim, 36 | TfToken const& subprim, 37 | TfTokenVector const& properties, 38 | UsdImagingPropertyInvalidationType invalidationType) override; 39 | 40 | // ---------------------------------------------------------------------- // 41 | /// \name Initialization 42 | // ---------------------------------------------------------------------- // 43 | 44 | // seems we need this here to ensure we can compile 45 | virtual SdfPath Populate( 46 | const UsdPrim& usdPrim, 47 | UsdImagingIndexProxy* index, 48 | const UsdImagingInstancerContext* instancerContext = nullptr) override; 49 | }; 50 | 51 | PXR_NAMESPACE_CLOSE_SCOPE -------------------------------------------------------------------------------- /cmake/Packages.cmake: -------------------------------------------------------------------------------- 1 | # Discovery of the dependencies of USDPluginExamples. 2 | 3 | if (USD_ROOT) 4 | 5 | if (NOT BOOST_ROOT) 6 | message(STATUS "BOOST_ROOT not set, defaulting to ${USD_ROOT}") 7 | set(BOOST_ROOT ${USD_ROOT}) 8 | endif() 9 | 10 | if (NOT TBB_ROOT) 11 | message(STATUS "TBB_ROOT not set, defaulting to ${USD_ROOT}") 12 | set(TBB_ROOT ${USD_ROOT}) 13 | endif() 14 | 15 | else() 16 | message(FATAL_ERROR "USD_ROOT must be set to the root dir of the USD installation!") 17 | endif() 18 | 19 | # Boost & python. 20 | if (ENABLE_PYTHON_SUPPORT) 21 | # Find python libraries. 22 | find_package( 23 | Python3 24 | COMPONENTS 25 | Interpreter Development 26 | REQUIRED 27 | ) 28 | 29 | # Pick up boost version variables. 30 | find_package(Boost REQUIRED) 31 | 32 | # We can use Boost_VERSION_STRING in CMake 3.14+. 33 | set(boost_version_string "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") 34 | 35 | # Boost provided cmake files in 1.70 and above causes inconsistent failures. 36 | if (${boost_version_string} VERSION_GREATER_EQUAL "1.70") 37 | option(Boost_NO_BOOST_CMAKE "Disable boost-provided cmake config" ON) 38 | if (Boost_NO_BOOST_CMAKE) 39 | message(STATUS "Disabling boost-provided cmake config") 40 | endif() 41 | endif() 42 | 43 | if (${boost_version_string} VERSION_GREATER_EQUAL "1.67") 44 | # In boost-1.67 and greater, the boost python component includes the 45 | # python major and minor version as part of its name. 46 | set(PYTHON_VERSION_DOTLESS "${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR}") 47 | find_package(Boost 48 | COMPONENTS 49 | python${PYTHON_VERSION_DOTLESS} 50 | REQUIRED 51 | ) 52 | set(Boost_PYTHON_LIBRARY "${Boost_PYTHON${PYTHON_VERSION_DOTLESS}_LIBRARY}") 53 | else() 54 | find_package(Boost 55 | COMPONENTS 56 | python 57 | REQUIRED 58 | ) 59 | endif() 60 | endif() 61 | 62 | # USD & TBB 63 | include(${USD_ROOT}/pxrConfig.cmake) 64 | find_package(TBB REQUIRED) 65 | -------------------------------------------------------------------------------- /src/usdTri/tokens.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #ifndef USDTRI_TOKENS_H 7 | #define USDTRI_TOKENS_H 8 | 9 | /// \file usdTri/tokens.h 10 | 11 | // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 12 | // 13 | // This is an automatically generated file (by usdGenSchema.py). 14 | // Do not hand-edit! 15 | // 16 | // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 17 | 18 | #include "pxr/pxr.h" 19 | #include "./api.h" 20 | #include "pxr/base/tf/staticData.h" 21 | #include "pxr/base/tf/token.h" 22 | #include 23 | 24 | PXR_NAMESPACE_OPEN_SCOPE 25 | 26 | /// \class UsdTriTokensType 27 | /// 28 | /// \link UsdTriTokens \endlink provides static, efficient 29 | /// \link TfToken TfTokens\endlink for use in all public USD API. 30 | /// 31 | /// These tokens are auto-generated from the module's schema, representing 32 | /// property names, for when you need to fetch an attribute or relationship 33 | /// directly by name, e.g. UsdPrim::GetAttribute(), in the most efficient 34 | /// manner, and allow the compiler to verify that you spelled the name 35 | /// correctly. 36 | /// 37 | /// UsdTriTokens also contains all of the \em allowedTokens values 38 | /// declared for schema builtin attributes of 'token' scene description type. 39 | /// Use UsdTriTokens like so: 40 | /// 41 | /// \code 42 | /// gprim.GetMyTokenValuedAttr().Set(UsdTriTokens->extent); 43 | /// \endcode 44 | struct UsdTriTokensType 45 | { 46 | USDTRI_API UsdTriTokensType(); 47 | /// \brief "extent" 48 | /// 49 | /// UsdTriTriangle 50 | const TfToken extent; 51 | /// \brief "sideLength" 52 | /// 53 | /// UsdTriTriangle 54 | const TfToken sideLength; 55 | /// \brief "Triangle" 56 | /// 57 | /// Schema identifer and family for UsdTriTriangle 58 | const TfToken Triangle; 59 | /// A vector of all of the tokens listed above. 60 | const std::vector allTokens; 61 | }; 62 | 63 | /// \var UsdTriTokens 64 | /// 65 | /// A global variable with static, efficient \link TfToken TfTokens\endlink 66 | /// for use in all public USD API. \sa UsdTriTokensType 67 | extern USDTRI_API TfStaticData UsdTriTokens; 68 | 69 | PXR_NAMESPACE_CLOSE_SCOPE 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/hdTri/renderBuffer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | PXR_NAMESPACE_OPEN_SCOPE 12 | 13 | /// \class HdTriRenderBuffer 14 | /// 15 | /// A block of memory which we are rendering into. 16 | class HdTriRenderBuffer : public HdRenderBuffer 17 | { 18 | public: 19 | HdTriRenderBuffer(const SdfPath& bprimId); 20 | 21 | /// Allocate a new buffer with the given dimensions and format. 22 | virtual bool Allocate(const GfVec3i& dimensions, 23 | HdFormat format, 24 | bool multiSampled) override; 25 | 26 | /// Accessor for buffer width. 27 | virtual unsigned int GetWidth() const override; 28 | 29 | /// Accessor for buffer height. 30 | virtual unsigned int GetHeight() const override; 31 | 32 | /// Accessor for buffer depth. 33 | virtual unsigned int GetDepth() const override; 34 | 35 | /// Accessor for buffer format. 36 | virtual HdFormat GetFormat() const override; 37 | 38 | /// Accessor for the buffer multisample state. 39 | virtual bool IsMultiSampled() const override; 40 | 41 | /// Map the buffer for reading/writing. The control flow should be Map(), 42 | /// before any I/O, followed by memory access, followed by Unmap() when 43 | /// done. 44 | virtual void* Map() override; 45 | 46 | /// Unmap the buffer. 47 | virtual void Unmap() override; 48 | 49 | /// Return whether any clients have this buffer mapped currently. 50 | virtual bool IsMapped() const override; 51 | 52 | /// Is the buffer converged? 53 | virtual bool IsConverged() const override; 54 | 55 | /// Set the convergence. 56 | void SetConverged(bool converged); 57 | 58 | /// Resolve the sample buffer into final values. 59 | virtual void Resolve() override; 60 | 61 | private: 62 | // Release any allocated resources. 63 | virtual void _Deallocate() override; 64 | 65 | // Buffer dimensions. 66 | GfVec3i _dimensions = GfVec3i(0, 0, 0); 67 | 68 | // Buffer format. 69 | HdFormat _format = HdFormatInvalid; 70 | 71 | // The actual buffer of bytes. 72 | std::vector _buffer; 73 | 74 | // The number of callers mapping this buffer. 75 | std::atomic _mappers{ 0 }; 76 | 77 | // Whether the buffer has been marked as converged. 78 | std::atomic _converged{ false }; 79 | }; 80 | 81 | PXR_NAMESPACE_CLOSE_SCOPE 82 | -------------------------------------------------------------------------------- /src/usdTriImaging/triangleAdapter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include 9 | 10 | PXR_NAMESPACE_OPEN_SCOPE 11 | 12 | /// \class UsdTriImagingTriangleAdapter 13 | /// 14 | /// PrimAdapter plugin for the "Triangle" prim type. 15 | class UsdTriImagingTriangleAdapter : public UsdImagingGprimAdapter 16 | { 17 | public: 18 | using BaseAdapter = UsdImagingGprimAdapter; 19 | 20 | // ---------------------------------------------------------------------- // 21 | /// \name Initialization 22 | // ---------------------------------------------------------------------- // 23 | 24 | virtual SdfPath Populate( 25 | const UsdPrim& usdPrim, 26 | UsdImagingIndexProxy* index, 27 | const UsdImagingInstancerContext* instancerContext = nullptr) override; 28 | 29 | virtual bool IsSupported(const UsdImagingIndexProxy* index) const override; 30 | 31 | // ---------------------------------------------------------------------- // 32 | /// \name Parallel Setup and Resolve 33 | // ---------------------------------------------------------------------- // 34 | 35 | virtual void TrackVariability( 36 | const UsdPrim& usdPrim, 37 | const SdfPath& cachePath, 38 | HdDirtyBits* timeVaryingBits, 39 | const UsdImagingInstancerContext* i_instancerContext = 40 | nullptr) const override; 41 | 42 | // ---------------------------------------------------------------------- // 43 | /// \name Change processing 44 | // ---------------------------------------------------------------------- // 45 | 46 | virtual HdDirtyBits ProcessPropertyChange( 47 | const UsdPrim& usdPrim, 48 | const SdfPath& cachePath, 49 | const TfToken& propertyName) override; 50 | 51 | // ---------------------------------------------------------------------- // 52 | /// \name GprimAdapter overrides 53 | // ---------------------------------------------------------------------- // 54 | 55 | /// Override the implementation in GprimAdapter and provide \em custom 56 | /// points for a triangle. 57 | virtual VtValue GetPoints(const UsdPrim& usdPrim, 58 | UsdTimeCode timeCode) const override; 59 | 60 | /// Override the implementation in GprimAdapter and provide \em custom 61 | /// topology for a triangle. 62 | virtual VtValue GetTopology(const UsdPrim& usdPrim, 63 | const SdfPath& cachePath, 64 | UsdTimeCode time) const override; 65 | }; 66 | 67 | PXR_NAMESPACE_CLOSE_SCOPE 68 | -------------------------------------------------------------------------------- /src/usdTriFileFormat/fileFormat.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | PXR_NAMESPACE_OPEN_SCOPE 14 | 15 | /* clang-format off */ 16 | #define USD_TRIANGLE_FILE_FORMAT_TOKENS \ 17 | ((Id, "usdTriangleFileFormat")) \ 18 | ((Version, "1.0")) \ 19 | ((Target, "usd")) \ 20 | ((Extension, "triangle")) \ 21 | ((SideLength, "Usd_Triangle_SideLength")) 22 | /* clang-format on */ 23 | 24 | TF_DECLARE_PUBLIC_TOKENS(UsdTriangleFileFormatTokens, 25 | USD_TRIANGLE_FILE_FORMAT_TOKENS); 26 | 27 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdTriangleFileFormat); 28 | 29 | /// \class UsdTriangleFileFormat 30 | /// 31 | /// A simple file format plugin which "expands" any payload with a .triangle 32 | /// suffix into a UsdGeomMesh representation of a equilateral triangle. 33 | class UsdTriangleFileFormat 34 | : public SdfFileFormat 35 | , public PcpDynamicFileFormatInterface 36 | { 37 | public: 38 | // We can always "read" (given that we never need to actually examine the 39 | // contents). 40 | bool CanRead(const std::string& filePath) const override; 41 | 42 | // Author USD scene description into the output layer for a given .triangle 43 | // file. 44 | bool Read(SdfLayer* layer, 45 | const std::string& resolvedPath, 46 | bool metadataOnly) const override; 47 | 48 | // Author .usda text format when writing to string or stream. 49 | bool WriteToString( 50 | const SdfLayer& layer, 51 | std::string* str, 52 | const std::string& comment = std::string()) const override; 53 | bool WriteToStream(const SdfSpecHandle& spec, 54 | std::ostream& out, 55 | size_t indent) const override; 56 | 57 | // Read fields values (from context) and write into file format args. 58 | void ComposeFieldsForFileFormatArguments( 59 | const std::string& assetPath, 60 | const PcpDynamicFileFormatContext& context, 61 | FileFormatArguments* args, 62 | VtValue* contextDependencyData) const override; 63 | 64 | // Check if a field change affects any of the file format arguments 65 | // affecting the triangle (spoilers: the answer is yes). 66 | bool CanFieldChangeAffectFileFormatArguments( 67 | const TfToken& field, 68 | const VtValue& oldValue, 69 | const VtValue& newValue, 70 | const VtValue& contextDependencyData) const override; 71 | 72 | protected: 73 | SDF_FILE_FORMAT_FACTORY_ACCESS; 74 | 75 | virtual ~UsdTriangleFileFormat(); 76 | UsdTriangleFileFormat(); 77 | }; 78 | 79 | PXR_NAMESPACE_CLOSE_SCOPE 80 | -------------------------------------------------------------------------------- /src/hdTri/renderBuffer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "renderBuffer.h" 7 | #include "debugCodes.h" 8 | 9 | PXR_NAMESPACE_OPEN_SCOPE 10 | 11 | HdTriRenderBuffer::HdTriRenderBuffer(const SdfPath& bprimId) 12 | : HdRenderBuffer(bprimId) 13 | { 14 | } 15 | 16 | bool 17 | HdTriRenderBuffer::Allocate(const GfVec3i& dimensions, 18 | HdFormat format, 19 | bool multiSampled) 20 | { 21 | TF_DEBUG(HDTRI_GENERAL) 22 | .Msg("[%s] Allocate render buffer id=%s, dimensions=(%i, %i, %i), " 23 | "format=%i\n", 24 | TF_FUNC_NAME().c_str(), 25 | GetId().GetText(), 26 | dimensions[0], 27 | dimensions[1], 28 | dimensions[2], 29 | format); 30 | 31 | _Deallocate(); 32 | 33 | // 2D buffer for now! 34 | TF_VERIFY(dimensions[2] == 1); 35 | 36 | _dimensions = dimensions; 37 | _format = format; 38 | _buffer.resize(_dimensions[0] * _dimensions[1] * _dimensions[2] * 39 | HdDataSizeOfFormat(format)); 40 | 41 | TF_DEBUG(HDTRI_GENERAL) 42 | .Msg("[%s] Render buffer id=%s, size=%lu\n", 43 | TF_FUNC_NAME().c_str(), 44 | GetId().GetText(), 45 | _buffer.size()); 46 | 47 | return true; 48 | } 49 | 50 | unsigned int 51 | HdTriRenderBuffer::GetWidth() const 52 | { 53 | return _dimensions[0]; 54 | } 55 | 56 | unsigned int 57 | HdTriRenderBuffer::GetHeight() const 58 | { 59 | return _dimensions[1]; 60 | } 61 | 62 | unsigned int 63 | HdTriRenderBuffer::GetDepth() const 64 | { 65 | return _dimensions[2]; 66 | } 67 | 68 | HdFormat 69 | HdTriRenderBuffer::GetFormat() const 70 | { 71 | return _format; 72 | } 73 | 74 | bool 75 | HdTriRenderBuffer::IsMultiSampled() const 76 | { 77 | return false; 78 | } 79 | 80 | void* 81 | HdTriRenderBuffer::Map() 82 | { 83 | _mappers.fetch_add(1); 84 | return static_cast(_buffer.data()); 85 | } 86 | 87 | void 88 | HdTriRenderBuffer::Unmap() 89 | { 90 | _mappers.fetch_sub(1); 91 | } 92 | 93 | bool 94 | HdTriRenderBuffer::IsMapped() const 95 | { 96 | return _mappers.load() > 0; 97 | } 98 | 99 | bool 100 | HdTriRenderBuffer::IsConverged() const 101 | { 102 | return _converged.load(); 103 | } 104 | 105 | void 106 | HdTriRenderBuffer::SetConverged(bool converged) 107 | { 108 | _converged.store(converged); 109 | } 110 | 111 | void 112 | HdTriRenderBuffer::Resolve() 113 | { 114 | // Nothing to do, there is only a single internal buffer for read/write. 115 | return; 116 | } 117 | 118 | void 119 | HdTriRenderBuffer::_Deallocate() 120 | { 121 | TF_VERIFY(!IsMapped()); 122 | 123 | // Reset to default/empty values. 124 | _dimensions = GfVec3i(0, 0, 0); 125 | _format = HdFormatInvalid; 126 | _buffer.resize(0); 127 | _mappers.store(0); 128 | _converged.store(false); 129 | } 130 | 131 | PXR_NAMESPACE_CLOSE_SCOPE 132 | -------------------------------------------------------------------------------- /src/hdTri/renderer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "renderBuffer.h" 7 | #include "renderer.h" 8 | 9 | #include 10 | 11 | PXR_NAMESPACE_OPEN_SCOPE 12 | 13 | // 2D operation for checking if a point is inside a triangle. 14 | static bool 15 | _PointInsideTriangle(const GfVec2f& point, const GfVec2f triangle[3]) 16 | { 17 | float dX = point[0] - triangle[2][0]; 18 | float dY = point[1] - triangle[2][1]; 19 | float dX21 = triangle[2][0] - triangle[1][0]; 20 | float dY12 = triangle[1][1] - triangle[2][1]; 21 | float D = dY12 * (triangle[0][0] - triangle[2][0]) + 22 | dX21 * (triangle[0][1] - triangle[2][1]); 23 | float s = dY12 * dX + dX21 * dY; 24 | float t = (triangle[2][1] - triangle[0][1]) * dX + 25 | (triangle[0][0] - triangle[2][0]) * dY; 26 | if (D < 0) { 27 | return s <= 0 && t <= 0 && s + t >= D; 28 | } else { 29 | return s >= 0 && t >= 0 && s + t <= D; 30 | } 31 | } 32 | 33 | void 34 | HdTriRenderer::DrawTriangle(HdTriRenderBuffer* colorBuffer) 35 | { 36 | // Gather format information. 37 | // (size of each pixel, and of each pixel component). 38 | HdFormat format = colorBuffer->GetFormat(); 39 | size_t formatSize = HdDataSizeOfFormat(format); 40 | size_t componentCount = HdGetComponentCount(format); 41 | 42 | // Begin buffer write. 43 | uint8_t* buffer = static_cast(colorBuffer->Map()); 44 | 45 | // Compute raster-space coordinates composing a equilateral 46 | // triangle, whose sideLength is proportionate to the buffer width. 47 | float sideLength = (float)colorBuffer->GetWidth() * 0.45f; 48 | GfVec2f centerOffset((float)colorBuffer->GetWidth() * 0.5f, 49 | (float)colorBuffer->GetHeight() * 0.41f); 50 | GfVec2f trianglePoints[3] = { 51 | GfVec2f(0.0f, 0.57735027f * sideLength) + centerOffset, 52 | GfVec2f(-0.5f * sideLength, -0.28867513f * sideLength) + centerOffset, 53 | GfVec2f(0.5f * sideLength, -0.28867513f * sideLength) + centerOffset 54 | }; 55 | 56 | // Iterate over all raster coordinates. 57 | for (uint32_t y = 0; y < colorBuffer->GetHeight(); ++y) { 58 | for (uint32_t x = 0; x < colorBuffer->GetWidth(); ++x) { 59 | // Compute the raster index (pixel) offset. 60 | uint32_t bufferIndex = (y * colorBuffer->GetWidth()) + x; 61 | 62 | // Compute the byte offset, based on raster format. 63 | uint8_t* dst = &buffer[bufferIndex * formatSize]; 64 | 65 | // Check if the raster coordinate is inside the 2D triangle. 66 | GfVec2f rasterCoord(x, y); 67 | if (_PointInsideTriangle(rasterCoord, trianglePoints)) { 68 | // Fill with white color. 69 | for (size_t c = 0; c < componentCount; ++c) { 70 | dst[c] = 255; 71 | } 72 | } 73 | } 74 | } 75 | 76 | // End buffer write. 77 | colorBuffer->Unmap(); 78 | } 79 | 80 | PXR_NAMESPACE_CLOSE_SCOPE 81 | -------------------------------------------------------------------------------- /src/usdTriImagingHd2/triangleAdapter.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta FX Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "triangleAdapter.h" 7 | #include "dataSourceTri.h" 8 | #include "debugCodes.h" 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | PXR_NAMESPACE_OPEN_SCOPE 18 | 19 | TF_REGISTRY_FUNCTION(TfType) 20 | { 21 | typedef UsdTriImagingTriangleAdapterHd2 Adapter; 22 | TfType adapterType = 23 | TfType::Define>(); 24 | adapterType.SetFactory>(); 25 | } 26 | 27 | TfTokenVector 28 | UsdTriImagingTriangleAdapterHd2::GetImagingSubprims(const UsdPrim& prim) 29 | { 30 | TF_DEBUG(USDTRIIMAGING) 31 | .Msg("[%s] called on <%s> \n", 32 | TF_FUNC_NAME().c_str(), 33 | prim.GetPath().GetText()); 34 | 35 | return { TfToken() }; 36 | } 37 | 38 | TfToken 39 | UsdTriImagingTriangleAdapterHd2::GetImagingSubprimType(const UsdPrim& prim, 40 | const TfToken& subprim) 41 | { 42 | TF_DEBUG(USDTRIIMAGING) 43 | .Msg("[%s] called on <%s> / %s \n", 44 | TF_FUNC_NAME().c_str(), 45 | prim.GetPath().GetText(), 46 | subprim.GetText()); 47 | 48 | if (subprim.IsEmpty()) { 49 | return HdPrimTypeTokens->mesh; 50 | } 51 | return TfToken(); 52 | } 53 | 54 | HdContainerDataSourceHandle 55 | UsdTriImagingTriangleAdapterHd2::GetImagingSubprimData( 56 | const UsdPrim& prim, 57 | const TfToken& subprim, 58 | const UsdImagingDataSourceStageGlobals& stageGlobals) 59 | { 60 | TF_DEBUG(USDTRIIMAGING) 61 | .Msg("[%s] called on <%s> / %s \n", 62 | TF_FUNC_NAME().c_str(), 63 | prim.GetPath().GetText(), 64 | subprim.GetText()); 65 | 66 | if (subprim.IsEmpty()) { 67 | return UsdImagingDataSourceTriPrim::New( 68 | prim.GetPath(), prim, stageGlobals); 69 | } 70 | return nullptr; 71 | } 72 | 73 | HdDataSourceLocatorSet 74 | UsdTriImagingTriangleAdapterHd2::InvalidateImagingSubprim( 75 | const UsdPrim& prim, 76 | const TfToken& subprim, 77 | const TfTokenVector& properties, 78 | UsdImagingPropertyInvalidationType invalidationType) 79 | { 80 | 81 | TF_DEBUG(USDTRIIMAGING) 82 | .Msg("[%s] called on <%s> / %s - %lu properties \n", 83 | TF_FUNC_NAME().c_str(), 84 | prim.GetPath().GetText(), 85 | subprim.GetText(), 86 | properties.size()); 87 | 88 | if (subprim.IsEmpty()) { 89 | return UsdImagingDataSourceTriPrim::Invalidate( 90 | prim, subprim, properties, invalidationType); 91 | } 92 | return HdDataSourceLocatorSet(); 93 | } 94 | 95 | SdfPath 96 | UsdTriImagingTriangleAdapterHd2::Populate( 97 | const UsdPrim& usdPrim, 98 | UsdImagingIndexProxy* index, 99 | const UsdImagingInstancerContext* instancerContext) 100 | { 101 | return SdfPath(); 102 | } 103 | 104 | PXR_NAMESPACE_CLOSE_SCOPE -------------------------------------------------------------------------------- /src/usdTri/wrapTriangle.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "./triangle.h" 7 | #include "pxr/usd/usd/schemaBase.h" 8 | 9 | #include "pxr/usd/sdf/primSpec.h" 10 | 11 | #include "pxr/usd/usd/pyConversions.h" 12 | #include "pxr/base/tf/pyContainerConversions.h" 13 | #include "pxr/base/tf/pyResultConversions.h" 14 | #include "pxr/base/tf/pyUtils.h" 15 | #include "pxr/base/tf/wrapTypeHelpers.h" 16 | 17 | #include 18 | 19 | #include 20 | 21 | using namespace boost::python; 22 | 23 | PXR_NAMESPACE_USING_DIRECTIVE 24 | 25 | namespace { 26 | 27 | #define WRAP_CUSTOM \ 28 | template \ 29 | static void _CustomWrapCode(Cls& _class) 30 | 31 | // fwd decl. 32 | WRAP_CUSTOM; 33 | 34 | static UsdAttribute 35 | _CreateSideLengthAttr(UsdTriTriangle& self, 36 | object defaultVal, 37 | bool writeSparsely) 38 | { 39 | return self.CreateSideLengthAttr( 40 | UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Double), 41 | writeSparsely); 42 | } 43 | 44 | static UsdAttribute 45 | _CreateExtentAttr(UsdTriTriangle& self, object defaultVal, bool writeSparsely) 46 | { 47 | return self.CreateExtentAttr( 48 | UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Float3Array), 49 | writeSparsely); 50 | } 51 | 52 | static std::string 53 | _Repr(const UsdTriTriangle& self) 54 | { 55 | std::string primRepr = TfPyRepr(self.GetPrim()); 56 | return TfStringPrintf("UsdTri.Triangle(%s)", primRepr.c_str()); 57 | } 58 | 59 | } // anonymous namespace 60 | 61 | void 62 | wrapUsdTriTriangle() 63 | { 64 | typedef UsdTriTriangle This; 65 | 66 | class_> cls("Triangle"); 67 | 68 | cls.def(init(arg("prim"))) 69 | .def(init(arg("schemaObj"))) 70 | .def(TfTypePythonClass()) 71 | 72 | .def("Get", &This::Get, (arg("stage"), arg("path"))) 73 | .staticmethod("Get") 74 | 75 | .def("Define", &This::Define, (arg("stage"), arg("path"))) 76 | .staticmethod("Define") 77 | 78 | .def("GetSchemaAttributeNames", 79 | &This::GetSchemaAttributeNames, 80 | arg("includeInherited") = true, 81 | return_value_policy()) 82 | .staticmethod("GetSchemaAttributeNames") 83 | 84 | .def("_GetStaticTfType", 85 | (TfType const& (*)())TfType::Find, 86 | return_value_policy()) 87 | .staticmethod("_GetStaticTfType") 88 | 89 | .def(!self) 90 | 91 | .def("GetSideLengthAttr", &This::GetSideLengthAttr) 92 | .def("CreateSideLengthAttr", 93 | &_CreateSideLengthAttr, 94 | (arg("defaultValue") = object(), arg("writeSparsely") = false)) 95 | 96 | .def("GetExtentAttr", &This::GetExtentAttr) 97 | .def("CreateExtentAttr", 98 | &_CreateExtentAttr, 99 | (arg("defaultValue") = object(), arg("writeSparsely") = false)) 100 | 101 | .def("__repr__", ::_Repr); 102 | 103 | _CustomWrapCode(cls); 104 | } 105 | 106 | // ===================================================================== // 107 | // Feel free to add custom code below this line, it will be preserved by 108 | // the code generator. The entry point for your custom code should look 109 | // minimally like the following: 110 | // 111 | // WRAP_CUSTOM { 112 | // _class 113 | // .def("MyCustomMethod", ...) 114 | // ; 115 | // } 116 | // 117 | // Of course any other ancillary or support code may be provided. 118 | // 119 | // Just remember to wrap code in the appropriate delimiters: 120 | // 'namespace {', '}'. 121 | // 122 | // ===================================================================== // 123 | // --(BEGIN CUSTOM CODE)-- 124 | 125 | namespace { 126 | 127 | WRAP_CUSTOM {} 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/hdTri/renderDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | PXR_NAMESPACE_OPEN_SCOPE 12 | 13 | class HdTriRenderParam; 14 | 15 | /// \class HdTriRenderDelegate 16 | /// 17 | /// Hydra renderer interface for the tri renderer. 18 | class HdTriRenderDelegate final : public HdRenderDelegate 19 | { 20 | public: 21 | /// Default constructor. 22 | HdTriRenderDelegate(); 23 | 24 | /// Constructor with render settings. 25 | HdTriRenderDelegate(const HdRenderSettingsMap& settingsMap); 26 | 27 | /// Destrucutor. 28 | virtual ~HdTriRenderDelegate() override; 29 | 30 | /// Cannot copy. 31 | HdTriRenderDelegate(const HdTriRenderDelegate&) = delete; 32 | HdTriRenderDelegate& operator=(const HdTriRenderDelegate&) = delete; 33 | 34 | /// Query supported hydra prim types. 35 | virtual const TfTokenVector& GetSupportedRprimTypes() const override; 36 | virtual const TfTokenVector& GetSupportedSprimTypes() const override; 37 | virtual const TfTokenVector& GetSupportedBprimTypes() const override; 38 | 39 | /// Return this delegate's render param, which provides top-level scene 40 | /// state. 41 | /// \return An instance of HdEmbreeRenderParam. 42 | virtual HdRenderParam* GetRenderParam() const override; 43 | 44 | /// Returns a list of user-configurable render settings, available in the 45 | /// UI. 46 | virtual HdRenderSettingDescriptorList GetRenderSettingDescriptors() 47 | const override; 48 | 49 | /// Get the resource registry. 50 | virtual HdResourceRegistrySharedPtr GetResourceRegistry() const override; 51 | 52 | /// Create render pass. 53 | virtual HdRenderPassSharedPtr CreateRenderPass( 54 | HdRenderIndex* index, 55 | const HdRprimCollection& collection) override; 56 | 57 | /// Create an instancer. 58 | virtual HdInstancer* CreateInstancer(HdSceneDelegate* delegate, 59 | const SdfPath& id) override; 60 | 61 | /// Destroy an instancer. 62 | virtual void DestroyInstancer(HdInstancer* instancer) override; 63 | 64 | /// Create a new Rprim. 65 | virtual HdRprim* CreateRprim(const TfToken& typeId, 66 | const SdfPath& rprimId) override; 67 | 68 | virtual void DestroyRprim(HdRprim* rprim) override; 69 | 70 | /// Create a new Sprim. 71 | virtual HdSprim* CreateSprim(const TfToken& typeId, 72 | const SdfPath& sprimId) override; 73 | 74 | /// TODO. 75 | virtual HdSprim* CreateFallbackSprim(const TfToken& typeId) override; 76 | 77 | /// Destroy an existing Sprim. 78 | virtual void DestroySprim(HdSprim* sprim) override; 79 | 80 | /// Create a new buffer prim. 81 | virtual HdBprim* CreateBprim(const TfToken& typeId, 82 | const SdfPath& bprimId) override; 83 | 84 | /// Create a fallback buffer prim. 85 | virtual HdBprim* CreateFallbackBprim(const TfToken& typeId) override; 86 | 87 | /// Destroy an existing Bprim. 88 | virtual void DestroyBprim(HdBprim* bprim) override; 89 | 90 | /// Do work. 91 | virtual void CommitResources(HdChangeTracker* tracker) override; 92 | 93 | /// Return the AOV description for \param aovName. 94 | /// This will be used to initialize the aov buffers. 95 | virtual HdAovDescriptor GetDefaultAovDescriptor( 96 | const TfToken& aovName) const override; 97 | 98 | private: 99 | // Setup routine (used in both constructors). 100 | void _Setup(); 101 | 102 | static const TfTokenVector SUPPORTED_RPRIM_TYPES; 103 | static const TfTokenVector SUPPORTED_SPRIM_TYPES; 104 | static const TfTokenVector SUPPORTED_BPRIM_TYPES; 105 | 106 | std::unique_ptr _renderParam; 107 | HdRenderSettingDescriptorList _settingDescriptors; 108 | 109 | HdResourceRegistrySharedPtr _resourceRegistry; 110 | }; 111 | 112 | PXR_NAMESPACE_CLOSE_SCOPE 113 | -------------------------------------------------------------------------------- /src/usdTriImaging/triangleAdapter.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "triangleAdapter.h" 7 | #include "debugCodes.h" 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | PXR_NAMESPACE_OPEN_SCOPE 17 | 18 | TF_REGISTRY_FUNCTION(TfType) 19 | { 20 | typedef UsdTriImagingTriangleAdapter Adapter; 21 | TfType adapterType = 22 | TfType::Define>(); 23 | adapterType.SetFactory>(); 24 | } 25 | 26 | bool 27 | UsdTriImagingTriangleAdapter::IsSupported( 28 | const UsdImagingIndexProxy* index) const 29 | { 30 | return index->IsRprimTypeSupported(HdPrimTypeTokens->mesh); 31 | } 32 | 33 | void 34 | UsdTriImagingTriangleAdapter::TrackVariability( 35 | const UsdPrim& usdPrim, 36 | const SdfPath& cachePath, 37 | HdDirtyBits* o_timeVaryingBits, 38 | const UsdImagingInstancerContext* i_instancerContext) const 39 | { 40 | BaseAdapter::TrackVariability( 41 | usdPrim, cachePath, o_timeVaryingBits, i_instancerContext); 42 | 43 | // If sideLength varies over time then points need to be pulled on time 44 | // change. 45 | _IsVarying(usdPrim, 46 | UsdTriTokens->sideLength, 47 | HdChangeTracker::DirtyPoints, 48 | UsdImagingTokens->usdVaryingPrimvar, 49 | o_timeVaryingBits, 50 | /*inherited*/ false); 51 | 52 | TF_DEBUG(USDTRIIMAGING) 53 | .Msg("[%s] <%s>, <%s>, dirtyBits: %s\n", 54 | TF_FUNC_NAME().c_str(), 55 | usdPrim.GetPath().GetText(), 56 | cachePath.GetText(), 57 | HdChangeTracker::StringifyDirtyBits(*o_timeVaryingBits).c_str()); 58 | } 59 | 60 | SdfPath 61 | UsdTriImagingTriangleAdapter::Populate( 62 | const UsdPrim& usdPrim, 63 | UsdImagingIndexProxy* index, 64 | const UsdImagingInstancerContext* instancerContext) 65 | { 66 | TF_DEBUG(USDTRIIMAGING) 67 | .Msg( 68 | "[%s] <%s>\n", TF_FUNC_NAME().c_str(), usdPrim.GetPath().GetText()); 69 | 70 | return _AddRprim(HdPrimTypeTokens->mesh, 71 | usdPrim, 72 | index, 73 | GetMaterialUsdPath(usdPrim), 74 | instancerContext); 75 | } 76 | 77 | HdDirtyBits 78 | UsdTriImagingTriangleAdapter::ProcessPropertyChange(const UsdPrim& usdPrim, 79 | const SdfPath& cachePath, 80 | const TfToken& propertyName) 81 | { 82 | 83 | TF_DEBUG(USDTRIIMAGING) 84 | .Msg("[%s] <%s>, <%s>, propertyName: %s\n", 85 | TF_FUNC_NAME().c_str(), 86 | usdPrim.GetPath().GetText(), 87 | cachePath.GetText(), 88 | propertyName.GetText()); 89 | 90 | // If the sideLength attribute changes, then the points are dirty. 91 | if (propertyName == UsdTriTokens->sideLength) { 92 | return HdChangeTracker::DirtyPoints; 93 | } 94 | 95 | // Allow base class to handle change processing. 96 | return BaseAdapter::ProcessPropertyChange(usdPrim, cachePath, propertyName); 97 | } 98 | 99 | VtValue 100 | UsdTriImagingTriangleAdapter::GetPoints(const UsdPrim& usdPrim, 101 | UsdTimeCode timeCode) const 102 | { 103 | UsdTriTriangle triangle(usdPrim); 104 | TF_VERIFY(triangle); 105 | 106 | double sideLength; 107 | TF_VERIFY(triangle.GetSideLengthAttr().Get(&sideLength, timeCode)); 108 | 109 | VtVec3fArray points{ 110 | GfVec3f(0.0f, 0.57735027f * sideLength, 0.0f), 111 | GfVec3f(-0.5f * sideLength, -0.28867513f * sideLength, 0.0f), 112 | GfVec3f(0.5f * sideLength, -0.28867513f * sideLength, 0.0f) 113 | }; 114 | return VtValue(points); 115 | } 116 | 117 | VtValue 118 | UsdTriImagingTriangleAdapter::GetTopology(const UsdPrim& usdPrim, 119 | const SdfPath& cachePath, 120 | UsdTimeCode time) const 121 | { 122 | // A single triangle. 123 | VtIntArray faceVertexCounts(1, 3); 124 | VtIntArray faceVertexIndices{ 0, 1, 2 }; 125 | static HdMeshTopology planeTopology(UsdGeomTokens->catmullClark, 126 | HdTokens->rightHanded, 127 | faceVertexCounts, 128 | faceVertexIndices); 129 | return VtValue(planeTopology); 130 | } 131 | 132 | PXR_NAMESPACE_CLOSE_SCOPE 133 | -------------------------------------------------------------------------------- /src/usdTri/generatedSchema.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | ( 3 | "WARNING: THIS FILE IS GENERATED BY usdGenSchema. DO NOT EDIT." 4 | ) 5 | 6 | class Triangle "Triangle" ( 7 | doc = """An equilateral triangle, whose vertices are equidistant to the 8 | origin and lie on the XY plane in object-space.""" 9 | ) 10 | { 11 | uniform bool doubleSided = 0 ( 12 | doc = """Although some renderers treat all parametric or polygonal 13 | surfaces as if they were effectively laminae with outward-facing 14 | normals on both sides, some renderers derive significant optimizations 15 | by considering these surfaces to have only a single outward side, 16 | typically determined by control-point winding order and/or 17 | orientation. By doing so they can perform \"backface culling\" to 18 | avoid drawing the many polygons of most closed surfaces that face away 19 | from the viewer. 20 | 21 | However, it is often advantageous to model thin objects such as paper 22 | and cloth as single, open surfaces that must be viewable from both 23 | sides, always. Setting a gprim's doubleSided attribute to 24 | \\c true instructs all renderers to disable optimizations such as 25 | backface culling for the gprim, and attempt (not all renderers are able 26 | to do so, but the USD reference GL renderer always will) to provide 27 | forward-facing normals on each side of the surface for lighting 28 | calculations.""" 29 | ) 30 | float3[] extent = [(-0.5, -0.28867513, 0), (0.5, 0.57735026, 0)] ( 31 | doc = "Fallback extent value of a triangle with side length of 1.0." 32 | ) 33 | uniform token orientation = "rightHanded" ( 34 | allowedTokens = ["rightHanded", "leftHanded"] 35 | doc = """Orientation specifies whether the gprim's surface normal 36 | should be computed using the right hand rule, or the left hand rule. 37 | Please see for a deeper explanation and 38 | generalization of orientation to composed scenes with transformation 39 | hierarchies.""" 40 | ) 41 | color3f[] primvars:displayColor ( 42 | doc = '''It is useful to have an "official" colorSet that can be used 43 | as a display or modeling color, even in the absence of any specified 44 | shader for a gprim. DisplayColor serves this role; because it is a 45 | UsdGeomPrimvar, it can also be used as a gprim override for any shader 46 | that consumes a displayColor parameter.''' 47 | ) 48 | float[] primvars:displayOpacity ( 49 | doc = """Companion to displayColor that specifies opacity, broken 50 | out as an independent attribute rather than an rgba color, both so that 51 | each can be independently overridden, and because shaders rarely consume 52 | rgba parameters.""" 53 | ) 54 | rel proxyPrim ( 55 | doc = '''The proxyPrim relationship allows us to link a 56 | prim whose purpose is "render" to its (single target) 57 | purpose="proxy" prim. This is entirely optional, but can be 58 | useful in several scenarios: 59 | 60 | - In a pipeline that does pruning (for complexity management) 61 | by deactivating prims composed from asset references, when we 62 | deactivate a purpose="render" prim, we will be able to discover 63 | and additionally deactivate its associated purpose="proxy" prim, 64 | so that preview renders reflect the pruning accurately. 65 | 66 | - DCC importers may be able to make more aggressive optimizations 67 | for interactive processing and display if they can discover the proxy 68 | for a given render prim. 69 | 70 | - With a little more work, a Hydra-based application will be able 71 | to map a picked proxy prim back to its render geometry for selection. 72 | 73 | \\note It is only valid to author the proxyPrim relationship on 74 | prims whose purpose is "render".''' 75 | ) 76 | uniform token purpose = "default" ( 77 | allowedTokens = ["default", "render", "proxy", "guide"] 78 | doc = """Purpose is a classification of geometry into categories that 79 | can each be independently included or excluded from traversals of prims 80 | on a stage, such as rendering or bounding-box computation traversals. 81 | 82 | See for more detail about how 83 | purpose is computed and used.""" 84 | ) 85 | double sideLength = 1 ( 86 | doc = "The length of each side of the equilateral triangle." 87 | ) 88 | token visibility = "inherited" ( 89 | allowedTokens = ["inherited", "invisible"] 90 | doc = '''Visibility is meant to be the simplest form of "pruning" 91 | visibility that is supported by most DCC apps. Visibility is 92 | animatable, allowing a sub-tree of geometry to be present for some 93 | segment of a shot, and absent from others; unlike the action of 94 | deactivating geometry prims, invisible geometry is still 95 | available for inspection, for positioning, for defining volumes, etc.''' 96 | ) 97 | uniform token[] xformOpOrder ( 98 | doc = """Encodes the sequence of transformation operations in the 99 | order in which they should be pushed onto a transform stack while 100 | visiting a UsdStage's prims in a graph traversal that will effect 101 | the desired positioning for this prim and its descendant prims. 102 | 103 | You should rarely, if ever, need to manipulate this attribute directly. 104 | It is managed by the AddXformOp(), SetResetXformStack(), and 105 | SetXformOpOrder(), and consulted by GetOrderedXformOps() and 106 | GetLocalTransformation().""" 107 | ) 108 | } 109 | 110 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and test 2 | 3 | # Run the jobs for pushes and pull requests targetting main branch. 4 | on: 5 | push: 6 | branches: 7 | - main 8 | paths-ignore: 9 | - '**.md' 10 | - 'LICENSE' 11 | - 'images/**' 12 | pull_request: 13 | branches: 14 | - main 15 | paths-ignore: 16 | - '**.md' 17 | - 'LICENSE' 18 | - 'images/**' 19 | 20 | jobs: 21 | 22 | # A build job matrix based on pre-built USD binaries provided by NVIDIA. 23 | # nvidia-usd-binaries-linux-build: 24 | # strategy: 25 | # matrix: 26 | # usdVersion: 27 | # - 21.05 28 | # include: 29 | # - usdVersion: 21.05 30 | # usdVersionUrl: 21-05 31 | # pythonVersion: 3.6 32 | # buildType: Release 33 | # buildTests: 'ON' 34 | # runs-on: ubuntu-18.04 35 | # name: 'Ubuntu 18.04 NVIDIA Pre-built Binaries 36 | # ' 40 | # steps: 41 | # - name: Install dependencies (Linux) 42 | # run: sudo apt-get install cmake python${{ matrix.pythonVersion }} python${{ matrix.pythonVersion }}-dev 43 | # - uses: actions/checkout@v2 44 | # - name: Download and extract pre-built USD binaries 45 | # run: | 46 | # curl -L -o /tmp/usd-${{ matrix.usdVersion }}.7z https://developer.nvidia.com/usd-${{ matrix.usdVersionUrl }}-binary-linux-python-${{ matrix.pythonVersion }} 47 | # mkdir -p /tmp/usd-${{ matrix.usdVersion }} 48 | # 7z x /tmp/usd-${{ matrix.usdVersion }}.7z -o/tmp/usd-${{ matrix.usdVersion }} 49 | # - name: Create build directories 50 | # run: | 51 | # mkdir _build 52 | # mkdir _install 53 | # - name: Configure 54 | # run: | 55 | # cmake -DUSD_ROOT="/tmp/usd-${{ matrix.usdVersion }}/" \ 56 | # -DCMAKE_BUILD_TYPE=${{ matrix.buildType }} \ 57 | # -DBUILD_TESTING=${{ matrix.buildTests }} \ 58 | # -DCMAKE_CXX_FLAGS="-D_GLIBCXX_USE_CXX11_ABI=0" \ 59 | # -DCMAKE_INSTALL_PREFIX=../_install \ 60 | # .. 61 | # working-directory: _build 62 | # - name: Build 63 | # run: | 64 | # cmake --build . \ 65 | # --verbose \ 66 | # --target install \ 67 | # --config ${{ matrix.buildType }} 68 | # working-directory: _build 69 | # - name: Test 70 | # run: ctest -VV --output-on-failure -C ${{ matrix.buildType }} 71 | # working-directory: _build 72 | 73 | 74 | # A build job matrix based on pre-built USD binaries provided by NVIDIA on Windows. 75 | # nvidia-usd-binaries-windows-build: 76 | # strategy: 77 | # matrix: 78 | # usdVersion: 79 | # - 21.05 80 | # include: 81 | # - usdVersion: 21.05 82 | # usdVersionUrl: 21-05 83 | # pythonVersion: 3.6 84 | # buildType: Release 85 | # buildTests: ON 86 | # runs-on: windows-2016 87 | # name: 'Windows 2016 NVIDIA Pre-built Binaries 88 | # ' 92 | # steps: 93 | # - uses: actions/checkout@v2 94 | # - name: Set up Python ${{ matrix.pythonVersion }} 95 | # uses: actions/setup-python@v2 96 | # with: 97 | # python-version: ${{ matrix.pythonVersion }} 98 | # - name: Download and extract pre-built USD binaries 99 | # run: | 100 | # Invoke-WebRequest https://developer.nvidia.com/usd-${{ matrix.usdVersionUrl }}-binary-windows-python-${{ matrix.pythonVersion }} -OutFile $env:TEMP/usd-${{ matrix.usdVersion }}.zip 101 | # mkdir -Force $env:TEMP/usd-${{ matrix.usdVersion }} 102 | # 7z x $env:TEMP/usd-${{ matrix.usdVersion }}.zip $("-o" + "$env:TEMP" + "\usd-${{ matrix.usdVersion }}") -y 103 | # - name: Create build directories 104 | # run: | 105 | # mkdir -Force _build 106 | # mkdir -Force _install 107 | # - name: Configure 108 | # run: | 109 | # cmake -DUSD_ROOT="$env:TEMP/usd-${{ matrix.usdVersion }}" ` 110 | # -DCMAKE_BUILD_TYPE=${{ matrix.buildType }} ` 111 | # -DBUILD_TESTING=${{ matrix.buildTests }} ` 112 | # -DCMAKE_INSTALL_PREFIX="../_install" ` 113 | # -G "Visual Studio 15 2017 Win64" ` 114 | # .. 115 | # working-directory: "_build" 116 | # - name: Build 117 | # run: | 118 | # cmake --build . ` 119 | # --verbose ` 120 | # --config ${{ matrix.buildType }} ` 121 | # --target ALL_BUILD 122 | # working-directory: "_build" 123 | # - name: Run Tests 124 | # run: | 125 | # ctest --extra-verbose ` 126 | # --output-on-failure ` 127 | # -C ${{ matrix.buildType }} 128 | # working-directory: "_build" 129 | # - name: Install 130 | # run: | 131 | # cmake --build . ` 132 | # --verbose ` 133 | # --config ${{ matrix.buildType }} ` 134 | # --target INSTALL 135 | # working-directory: "_build" 136 | 137 | # Run automated code formatting checks. 138 | code-formatting-check: 139 | runs-on: ubuntu-22.04 140 | steps: 141 | - name: Install dependencies (Linux) 142 | run: | 143 | sudo apt-get install clang-format-13 144 | - uses: actions/checkout@v2 145 | - name: Run clang-format on source code 146 | run: | 147 | find . \ 148 | -name ".git" -prune -o \ 149 | -name "*.cpp" -type f -exec clang-format -i --verbose {} + -o \ 150 | -name "*.h" -type f -exec clang-format -i --verbose {} + 151 | - name: Check for code differences 152 | run: | 153 | set +e 154 | git diff --color 155 | git diff-index --quiet HEAD --; EXIT_CODE=$? 156 | set -e 157 | if [ $EXIT_CODE -ne 0 ]; then echo "C++ code formatting check failed. Please run clang-format on *.h and *.cpp, then push your changes."; fi 158 | exit $EXIT_CODE 159 | -------------------------------------------------------------------------------- /src/hdTri/renderDelegate.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "debugCodes.h" 7 | #include "renderBuffer.h" 8 | #include "renderDelegate.h" 9 | #include "renderParam.h" 10 | #include "renderPass.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | PXR_NAMESPACE_OPEN_SCOPE 18 | 19 | /// Supported Hydra prim types. 20 | const TfTokenVector HdTriRenderDelegate::SUPPORTED_RPRIM_TYPES = {}; 21 | const TfTokenVector HdTriRenderDelegate::SUPPORTED_SPRIM_TYPES = { 22 | HdPrimTypeTokens->camera 23 | }; 24 | const TfTokenVector HdTriRenderDelegate::SUPPORTED_BPRIM_TYPES = { 25 | HdPrimTypeTokens->renderBuffer 26 | }; 27 | 28 | HdTriRenderDelegate::HdTriRenderDelegate() 29 | : HdRenderDelegate() 30 | { 31 | _Setup(); 32 | } 33 | 34 | HdTriRenderDelegate::HdTriRenderDelegate(const HdRenderSettingsMap& settingsMap) 35 | : HdRenderDelegate(settingsMap) 36 | { 37 | _Setup(); 38 | } 39 | 40 | HdTriRenderDelegate::~HdTriRenderDelegate() 41 | { 42 | // Clean resources. 43 | _renderParam.reset(); 44 | } 45 | 46 | TfTokenVector const& 47 | HdTriRenderDelegate::GetSupportedRprimTypes() const 48 | { 49 | return SUPPORTED_RPRIM_TYPES; 50 | } 51 | 52 | TfTokenVector const& 53 | HdTriRenderDelegate::GetSupportedSprimTypes() const 54 | { 55 | return SUPPORTED_SPRIM_TYPES; 56 | } 57 | 58 | TfTokenVector const& 59 | HdTriRenderDelegate::GetSupportedBprimTypes() const 60 | { 61 | return SUPPORTED_BPRIM_TYPES; 62 | } 63 | 64 | HdRenderParam* 65 | HdTriRenderDelegate::GetRenderParam() const 66 | { 67 | return _renderParam.get(); 68 | } 69 | 70 | HdRenderSettingDescriptorList 71 | HdTriRenderDelegate::GetRenderSettingDescriptors() const 72 | { 73 | return _settingDescriptors; 74 | } 75 | 76 | HdResourceRegistrySharedPtr 77 | HdTriRenderDelegate::GetResourceRegistry() const 78 | { 79 | return _resourceRegistry; 80 | } 81 | 82 | HdRenderPassSharedPtr 83 | HdTriRenderDelegate::CreateRenderPass(HdRenderIndex* index, 84 | const HdRprimCollection& collection) 85 | { 86 | return HdRenderPassSharedPtr(new HdTriRenderPass(index, collection)); 87 | } 88 | 89 | void 90 | HdTriRenderDelegate::CommitResources(HdChangeTracker* tracker) 91 | { 92 | } 93 | 94 | HdRprim* 95 | HdTriRenderDelegate::CreateRprim(const TfToken& typeId, const SdfPath& rprimId) 96 | { 97 | TF_DEBUG(HDTRI_GENERAL) 98 | .Msg("[%s] Create HdTri Rprim type %s id %s\n", 99 | TF_FUNC_NAME().c_str(), 100 | typeId.GetText(), 101 | rprimId.GetText()); 102 | TF_CODING_ERROR( 103 | "Unknown Rprim type=%s id=%s", typeId.GetText(), rprimId.GetText()); 104 | return nullptr; 105 | } 106 | 107 | void 108 | HdTriRenderDelegate::DestroyRprim(HdRprim* rprim) 109 | { 110 | TF_DEBUG(HDTRI_GENERAL) 111 | .Msg("[%s] Destroy Rprim id %s\n", 112 | TF_FUNC_NAME().c_str(), 113 | rprim->GetId().GetText()); 114 | delete rprim; 115 | } 116 | 117 | HdSprim* 118 | HdTriRenderDelegate::CreateSprim(const TfToken& typeId, const SdfPath& sprimId) 119 | { 120 | if (typeId == HdPrimTypeTokens->camera) { 121 | return new HdCamera(sprimId); 122 | } else { 123 | TF_CODING_ERROR( 124 | "Unknown Sprim type=%s id=%s", typeId.GetText(), sprimId.GetText()); 125 | } 126 | return nullptr; 127 | } 128 | 129 | HdSprim* 130 | HdTriRenderDelegate::CreateFallbackSprim(const TfToken& typeId) 131 | { 132 | if (typeId == HdPrimTypeTokens->camera) { 133 | return new HdCamera(SdfPath::EmptyPath()); 134 | } else { 135 | TF_CODING_ERROR("Unknown Fallback Sprim type=%s id=%s", 136 | typeId.GetText(), 137 | typeId.GetText()); 138 | } 139 | return nullptr; 140 | } 141 | 142 | void 143 | HdTriRenderDelegate::DestroySprim(HdSprim* sprim) 144 | { 145 | delete sprim; 146 | } 147 | 148 | HdBprim* 149 | HdTriRenderDelegate::CreateBprim(const TfToken& typeId, const SdfPath& bprimId) 150 | { 151 | if (typeId == HdPrimTypeTokens->renderBuffer) { 152 | return new HdTriRenderBuffer(bprimId); 153 | } else { 154 | TF_CODING_ERROR("Unknown Bprim Type %s", typeId.GetText()); 155 | } 156 | 157 | return nullptr; 158 | } 159 | 160 | HdBprim* 161 | HdTriRenderDelegate::CreateFallbackBprim(const TfToken& typeId) 162 | { 163 | if (typeId == HdPrimTypeTokens->renderBuffer) { 164 | return new HdTriRenderBuffer(SdfPath::EmptyPath()); 165 | } else { 166 | TF_CODING_ERROR("Unknown Bprim Type %s", typeId.GetText()); 167 | } 168 | 169 | return nullptr; 170 | } 171 | 172 | void 173 | HdTriRenderDelegate::DestroyBprim(HdBprim* bprim) 174 | { 175 | delete bprim; 176 | } 177 | 178 | HdInstancer* 179 | HdTriRenderDelegate::CreateInstancer(HdSceneDelegate* delegate, 180 | const SdfPath& id) 181 | { 182 | TF_CODING_ERROR("Creating Instancer not supported id=%s", id.GetText()); 183 | return nullptr; 184 | } 185 | 186 | void 187 | HdTriRenderDelegate::DestroyInstancer(HdInstancer* instancer) 188 | { 189 | TF_CODING_ERROR("Destroy instancer not supported"); 190 | } 191 | 192 | HdAovDescriptor 193 | HdTriRenderDelegate::GetDefaultAovDescriptor(const TfToken& aovName) const 194 | { 195 | if (aovName == HdAovTokens->color) { 196 | return HdAovDescriptor( 197 | HdFormatUNorm8Vec4, true, VtValue(GfVec4f(0.0f))); 198 | } else if (aovName == HdAovTokens->depth) { 199 | return HdAovDescriptor(HdFormatFloat32, false, VtValue(1.0f)); 200 | } else if (aovName == HdAovTokens->primId || 201 | aovName == HdAovTokens->instanceId || 202 | aovName == HdAovTokens->elementId) { 203 | return HdAovDescriptor(HdFormatInt32, false, VtValue(-1)); 204 | } 205 | 206 | return HdAovDescriptor(); 207 | } 208 | 209 | void 210 | HdTriRenderDelegate::_Setup() 211 | { 212 | _renderParam = std::unique_ptr(new HdTriRenderParam()); 213 | _resourceRegistry = 214 | std::shared_ptr(new HdResourceRegistry()); 215 | } 216 | 217 | PXR_NAMESPACE_CLOSE_SCOPE 218 | -------------------------------------------------------------------------------- /src/usdTriFileFormat/fileFormat.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "fileFormat.h" 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | PXR_NAMESPACE_OPEN_SCOPE 19 | 20 | // Default value of the triangle side length. 21 | static const double defaultSideLengthValue = 1.0; 22 | 23 | // Convenience function to extract the length value from a file format context. 24 | static double 25 | _ExtractSideLengthFromContext(const PcpDynamicFileFormatContext& context) 26 | { 27 | // Default sideLength. 28 | double sideLength = defaultSideLengthValue; 29 | 30 | VtValue value; 31 | if (!context.ComposeValue(UsdTriangleFileFormatTokens->SideLength, 32 | &value) || 33 | value.IsEmpty()) { 34 | return sideLength; 35 | } 36 | 37 | if (!value.IsHolding()) { 38 | TF_CODING_ERROR("Expected '%s' value to hold a double, got '%s'", 39 | UsdTriangleFileFormatTokens->SideLength.GetText(), 40 | TfStringify(value).c_str()); 41 | return sideLength; 42 | } 43 | 44 | return value.UncheckedGet(); 45 | } 46 | 47 | static double 48 | _ExtractSideLengthFromArgs(const SdfFileFormat::FileFormatArguments& args) 49 | { 50 | // Default sideLength. 51 | double sideLength = defaultSideLengthValue; 52 | 53 | // Find "sideLength" file format argument. 54 | auto it = args.find(UsdTriangleFileFormatTokens->SideLength); 55 | if (it == args.end()) { 56 | return sideLength; 57 | } 58 | 59 | // Try to convert the string value to the actual output value type. 60 | double extractVal; 61 | bool success = true; 62 | extractVal = TfUnstringify(it->second, &success); 63 | if (!success) { 64 | TF_CODING_ERROR( 65 | "Could not convert arg string '%s' to value of type double", 66 | UsdTriangleFileFormatTokens->SideLength.GetText()); 67 | return sideLength; 68 | } 69 | 70 | sideLength = extractVal; 71 | return sideLength; 72 | } 73 | 74 | TF_DEFINE_PUBLIC_TOKENS(UsdTriangleFileFormatTokens, 75 | USD_TRIANGLE_FILE_FORMAT_TOKENS); 76 | 77 | TF_REGISTRY_FUNCTION(TfType) 78 | { 79 | SDF_DEFINE_FILE_FORMAT(UsdTriangleFileFormat, SdfFileFormat); 80 | } 81 | 82 | UsdTriangleFileFormat::UsdTriangleFileFormat() 83 | : SdfFileFormat(UsdTriangleFileFormatTokens->Id, 84 | UsdTriangleFileFormatTokens->Version, 85 | UsdTriangleFileFormatTokens->Target, 86 | UsdTriangleFileFormatTokens->Extension) 87 | { 88 | } 89 | 90 | UsdTriangleFileFormat::~UsdTriangleFileFormat() {} 91 | 92 | bool 93 | UsdTriangleFileFormat::CanRead(const std::string& filePath) const 94 | { 95 | return true; 96 | } 97 | 98 | bool 99 | UsdTriangleFileFormat::Read(SdfLayer* layer, 100 | const std::string& resolvedPath, 101 | bool metadataOnly) const 102 | { 103 | if (!TF_VERIFY(layer)) { 104 | return false; 105 | } 106 | 107 | // Extract file format arguments. 108 | FileFormatArguments args; 109 | std::string layerPath; 110 | SdfLayer::SplitIdentifier(layer->GetIdentifier(), &layerPath, &args); 111 | double sideLength = _ExtractSideLengthFromArgs(args); 112 | 113 | // Create a new anonymous layer and wrap a stage around it. 114 | SdfLayerRefPtr newLayer = SdfLayer::CreateAnonymous(".usd"); 115 | UsdStageRefPtr stage = UsdStage::Open(newLayer); 116 | 117 | // Define a Mesh, set as default prim. 118 | UsdGeomMesh mesh = UsdGeomMesh::Define(stage, SdfPath("/Triangle")); 119 | stage->SetDefaultPrim(mesh.GetPrim()); 120 | 121 | // Author mesh attributes (describing a length-scaled equilateral triangle). 122 | VtIntArray faceVertexCounts(1, 3); 123 | mesh.CreateFaceVertexCountsAttr(VtValue(faceVertexCounts)); 124 | 125 | VtIntArray faceVertexIndices{ 0, 1, 2 }; 126 | mesh.CreateFaceVertexIndicesAttr(VtValue(faceVertexIndices)); 127 | 128 | VtVec3fArray points{ 129 | GfVec3f(0.0f, 0.57735027f * sideLength, 0.0f), 130 | GfVec3f(-0.5f * sideLength, -0.28867513f * sideLength, 0.0f), 131 | GfVec3f(0.5f * sideLength, -0.28867513f * sideLength, 0.0f) 132 | }; 133 | mesh.CreatePointsAttr(VtValue(points)); 134 | 135 | // Copy contents into output layer. 136 | layer->TransferContent(newLayer); 137 | 138 | return true; 139 | } 140 | 141 | bool 142 | UsdTriangleFileFormat::WriteToString(const SdfLayer& layer, 143 | std::string* str, 144 | const std::string& comment) const 145 | { 146 | // Write the generated contents in usda text format. 147 | return SdfFileFormat::FindById(UsdUsdaFileFormatTokens->Id) 148 | ->WriteToString(layer, str, comment); 149 | } 150 | 151 | bool 152 | UsdTriangleFileFormat::WriteToStream(const SdfSpecHandle& spec, 153 | std::ostream& out, 154 | size_t indent) const 155 | { 156 | // Write the generated contents in usda text format. 157 | return SdfFileFormat::FindById(UsdUsdaFileFormatTokens->Id) 158 | ->WriteToStream(spec, out, indent); 159 | } 160 | 161 | void 162 | UsdTriangleFileFormat::ComposeFieldsForFileFormatArguments( 163 | const std::string& assetPath, 164 | const PcpDynamicFileFormatContext& context, 165 | FileFormatArguments* args, 166 | VtValue* contextDependencyData) const 167 | { 168 | double sideLength = _ExtractSideLengthFromContext(context); 169 | (*args)[UsdTriangleFileFormatTokens->SideLength] = TfStringify(sideLength); 170 | } 171 | 172 | bool 173 | UsdTriangleFileFormat::CanFieldChangeAffectFileFormatArguments( 174 | const TfToken& field, 175 | const VtValue& oldValue, 176 | const VtValue& newValue, 177 | const VtValue& contextDependencyData) const 178 | { 179 | // Check if the "sideLength" argument changed. 180 | double oldLength = oldValue.IsHolding() 181 | ? oldValue.UncheckedGet() 182 | : defaultSideLengthValue; 183 | double newLength = newValue.IsHolding() 184 | ? newValue.UncheckedGet() 185 | : defaultSideLengthValue; 186 | 187 | return oldLength != newLength; 188 | } 189 | 190 | PXR_NAMESPACE_CLOSE_SCOPE 191 | -------------------------------------------------------------------------------- /src/usdTri/triangle.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #include "./triangle.h" 7 | #include "pxr/usd/usd/schemaRegistry.h" 8 | #include "pxr/usd/usd/typed.h" 9 | 10 | #include "pxr/usd/sdf/types.h" 11 | #include "pxr/usd/sdf/assetPath.h" 12 | 13 | PXR_NAMESPACE_OPEN_SCOPE 14 | 15 | // Register the schema with the TfType system. 16 | TF_REGISTRY_FUNCTION(TfType) 17 | { 18 | TfType::Define>(); 19 | 20 | // Register the usd prim typename as an alias under UsdSchemaBase. This 21 | // enables one to call 22 | // TfType::Find().FindDerivedByName("Triangle") 23 | // to find TfType, which is how IsA queries are 24 | // answered. 25 | TfType::AddAlias("Triangle"); 26 | } 27 | 28 | /* virtual */ 29 | UsdTriTriangle::~UsdTriTriangle() {} 30 | 31 | /* static */ 32 | UsdTriTriangle 33 | UsdTriTriangle::Get(const UsdStagePtr& stage, const SdfPath& path) 34 | { 35 | if (!stage) { 36 | TF_CODING_ERROR("Invalid stage"); 37 | return UsdTriTriangle(); 38 | } 39 | return UsdTriTriangle(stage->GetPrimAtPath(path)); 40 | } 41 | 42 | /* static */ 43 | UsdTriTriangle 44 | UsdTriTriangle::Define(const UsdStagePtr& stage, const SdfPath& path) 45 | { 46 | static TfToken usdPrimTypeName("Triangle"); 47 | if (!stage) { 48 | TF_CODING_ERROR("Invalid stage"); 49 | return UsdTriTriangle(); 50 | } 51 | return UsdTriTriangle(stage->DefinePrim(path, usdPrimTypeName)); 52 | } 53 | 54 | /* virtual */ 55 | UsdSchemaKind 56 | UsdTriTriangle::_GetSchemaKind() const 57 | { 58 | return UsdTriTriangle::schemaKind; 59 | } 60 | 61 | /* static */ 62 | const TfType& 63 | UsdTriTriangle::_GetStaticTfType() 64 | { 65 | static TfType tfType = TfType::Find(); 66 | return tfType; 67 | } 68 | 69 | /* static */ 70 | bool 71 | UsdTriTriangle::_IsTypedSchema() 72 | { 73 | static bool isTyped = _GetStaticTfType().IsA(); 74 | return isTyped; 75 | } 76 | 77 | /* virtual */ 78 | const TfType& 79 | UsdTriTriangle::_GetTfType() const 80 | { 81 | return _GetStaticTfType(); 82 | } 83 | 84 | UsdAttribute 85 | UsdTriTriangle::GetSideLengthAttr() const 86 | { 87 | return GetPrim().GetAttribute(UsdTriTokens->sideLength); 88 | } 89 | 90 | UsdAttribute 91 | UsdTriTriangle::CreateSideLengthAttr(VtValue const& defaultValue, 92 | bool writeSparsely) const 93 | { 94 | return UsdSchemaBase::_CreateAttr(UsdTriTokens->sideLength, 95 | SdfValueTypeNames->Double, 96 | /* custom = */ false, 97 | SdfVariabilityVarying, 98 | defaultValue, 99 | writeSparsely); 100 | } 101 | 102 | UsdAttribute 103 | UsdTriTriangle::GetExtentAttr() const 104 | { 105 | return GetPrim().GetAttribute(UsdTriTokens->extent); 106 | } 107 | 108 | UsdAttribute 109 | UsdTriTriangle::CreateExtentAttr(VtValue const& defaultValue, 110 | bool writeSparsely) const 111 | { 112 | return UsdSchemaBase::_CreateAttr(UsdTriTokens->extent, 113 | SdfValueTypeNames->Float3Array, 114 | /* custom = */ false, 115 | SdfVariabilityVarying, 116 | defaultValue, 117 | writeSparsely); 118 | } 119 | 120 | namespace { 121 | static inline TfTokenVector 122 | _ConcatenateAttributeNames(const TfTokenVector& left, 123 | const TfTokenVector& right) 124 | { 125 | TfTokenVector result; 126 | result.reserve(left.size() + right.size()); 127 | result.insert(result.end(), left.begin(), left.end()); 128 | result.insert(result.end(), right.begin(), right.end()); 129 | return result; 130 | } 131 | } 132 | 133 | /*static*/ 134 | const TfTokenVector& 135 | UsdTriTriangle::GetSchemaAttributeNames(bool includeInherited) 136 | { 137 | static TfTokenVector localNames = { 138 | UsdTriTokens->sideLength, 139 | UsdTriTokens->extent, 140 | }; 141 | static TfTokenVector allNames = _ConcatenateAttributeNames( 142 | UsdGeomGprim::GetSchemaAttributeNames(true), localNames); 143 | 144 | if (includeInherited) 145 | return allNames; 146 | else 147 | return localNames; 148 | } 149 | 150 | PXR_NAMESPACE_CLOSE_SCOPE 151 | 152 | // ===================================================================== // 153 | // Feel free to add custom code below this line. It will be preserved by 154 | // the code generator. 155 | // 156 | // Just remember to wrap code in the appropriate delimiters: 157 | // 'PXR_NAMESPACE_OPEN_SCOPE', 'PXR_NAMESPACE_CLOSE_SCOPE'. 158 | // ===================================================================== // 159 | // --(BEGIN CUSTOM CODE)-- 160 | 161 | #include "pxr/usd/usdGeom/boundableComputeExtent.h" 162 | #include "pxr/base/tf/registryManager.h" 163 | 164 | PXR_NAMESPACE_OPEN_SCOPE 165 | 166 | bool 167 | UsdTriTriangle::ComputeExtent(double sideLength, VtVec3fArray* extent) 168 | { 169 | extent->resize(2); 170 | 171 | (*extent)[0] = GfVec3f(0.5 * sideLength, -0.28867513 * sideLength, 0.0); 172 | (*extent)[1] = GfVec3f(0.5 * sideLength, 0.57735027 * sideLength, 0.0); 173 | 174 | return true; 175 | } 176 | 177 | bool 178 | UsdTriTriangle::ComputeExtent(double sideLength, 179 | const GfMatrix4d& transform, 180 | VtVec3fArray* extent) 181 | { 182 | extent->resize(2); 183 | 184 | GfBBox3d bbox = GfBBox3d( 185 | GfRange3d(GfVec3d(-0.5 * sideLength, -0.28867513 * sideLength, 0.0), 186 | GfVec3d(0.5 * sideLength, 0.57735027 * sideLength, 0.0)), 187 | transform); 188 | GfRange3d range = bbox.ComputeAlignedRange(); 189 | (*extent)[0] = GfVec3f(range.GetMin()); 190 | (*extent)[1] = GfVec3f(range.GetMax()); 191 | 192 | return true; 193 | } 194 | 195 | static bool 196 | _ComputeExtentForTriangle(const UsdGeomBoundable& boundable, 197 | const UsdTimeCode& time, 198 | const GfMatrix4d* transform, 199 | VtVec3fArray* extent) 200 | { 201 | const UsdTriTriangle triangle(boundable); 202 | if (!TF_VERIFY(triangle)) { 203 | return false; 204 | } 205 | 206 | double sideLength; 207 | if (!triangle.GetSideLengthAttr().Get(&sideLength, time)) { 208 | return false; 209 | } 210 | 211 | if (transform) { 212 | return UsdTriTriangle::ComputeExtent(sideLength, *transform, extent); 213 | } else { 214 | return UsdTriTriangle::ComputeExtent(sideLength, extent); 215 | } 216 | } 217 | 218 | TF_REGISTRY_FUNCTION(UsdGeomBoundable) 219 | { 220 | UsdGeomRegisterComputeExtentFunction( 221 | _ComputeExtentForTriangle); 222 | } 223 | 224 | PXR_NAMESPACE_CLOSE_SCOPE 225 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # USDPluginExamples 4 | 5 | A collection of example plugins for [Pixar's USD](https://github.com/PixarAnimationStudios/USD) (Universal Scene Description). 6 | 7 | This project also aims to provide a set of CMake utilities for building USD plugins outside of the USD project source tree. The utilities are heavily based on the build logic prescribed by the USD project itself. 8 | 9 | We hope the minimal examples and surrounding build infrastructure can be useful to USD community developers interested in building and deploying their own plugin(s). 10 | 11 | Huge thanks to Pixar's USD team for providing a highly extensible platform! 12 | 13 | ## Table of Contents 14 | 15 | - [USD Plugins](#usd-plugins) 16 | - [Dependencies](#dependencies) 17 | - [Building](#building) 18 | - [Running](#running) 19 | - [CMake Utilities](#cmake-utilities) 20 | 21 | ## USD Plugins 22 | 23 | **USDPluginExamples** provides the following USD plugins: 24 | - [usdTri](./src/usdTri): A schema library defining a **Triangle** prim type. 25 | - [usdTriImaging](./src/usdTriImaging): A *Hydra 1 only* prim adapter which images the **Triangle** prim type. [*] 26 | - [usdTriImagingHd2](./src/usdTriImagingHd2): A *Hydra 2 only* prim adapter which images the **Triangle** prim type. [*] 27 | - [usdTriFileFormat](./src/usdTriFileFormat): A file format plugin which authors a triangular mesh for a `.triangle` payload. 28 | - [hdTri](./src/hdTri): A hydra renderer plugin which images a triangle (in the most direct sense). 29 | - [usdviewTri](./src/usdviewTri): An usdview plugin providing a menu command to define child Triangle prim(s) under selected paths. 30 | 31 | [*] We deliberatly split the Hydra 1 & 2 Triangle Prim Adapters into two plugins/sources to outline the differences 32 | 33 | There are many other USD plugins available online - check out [USD Working Group: Projects & Resources](https://wiki.aswf.io/display/WGUSD/USD+Projects+and+Resources) for more! 34 | 35 | ## Dependencies 36 | 37 | The following dependencies are required: 38 | - C++ compiler 39 | - [CMake](https://cmake.org/documentation/) (Tested with CMake 3.29.2) 40 | - [USD](https://github.com/pixaranimationstudios/USD) (24.05) 41 | - [Boost](https://boost.org) and [Intel TBB](https://www.threadingbuildingblocks.org/) (USD dependencies) 42 | 43 | [Python](https://www.python.org/) may also be required, depending on python support in the USD installation. 44 | 45 | ## Building 46 | 47 | Example snippet for building the plugins on Linux (and potentially MacOS): 48 | ```bash 49 | mkdir build 50 | cd build 51 | cmake \ 52 | -DUSD_ROOT="/apps/usd/" \ 53 | -DCMAKE_INSTALL_PREFIX="/apps/USDPluginExamples/" \ 54 | .. 55 | cmake --build . -- VERBOSE=1 -j8 all test install 56 | ``` 57 | 58 | Example snippet for building a Visual Studio project on Windows (x64 Native Tools Command Prompt with Administrator privileges): 59 | ```cmd 60 | mkdir build 61 | cd build 62 | cmake ^ 63 | -G "Visual Studio 15 2017 Win64" ^ 64 | -DUSD_ROOT="D:\install\usd" ^ 65 | -DCMAKE_INSTALL_PREFIX="D:\install\USDPluginExamples\" ^ 66 | .. 67 | 68 | cmake --build . --config Release -j 8 --target ALL_BUILD RUN_TESTS INSTALL 69 | ``` 70 | 71 | 72 | CMake options for configuring this project: 73 | 74 | | CMake Variable name | Description | Default | 75 | | ----------------------- | ---------------------------------------------------------------------- | ------- | 76 | | `USD_ROOT` | Root directory of USD installation | | 77 | | `TBB_ROOT` | Root directory of Intel TBB installation | | 78 | | `BOOST_ROOT` | Root directory of Boost installation | | 79 | | `ENABLE_PYTHON_SUPPORT` | Enable python support. Must match python support of USD installation. | `ON` | 80 | | `BUILD_TESTING` | Enable automated testing. | `ON` | 81 | | `BUILD_HYDRA2` | Enable building Hydra2 plugins, will disable Hydra1 plugin building. | `OFF` | 82 | 83 | ## Running 84 | 85 | To register the plugin(s) as part of the USD runtime, the following environment variables will need 86 | to be defined: 87 | | Environment Variable | Value(s) | 88 | | --------------------- | ---------------------------------------------------------------------------------------- | 89 | | `PYTHONPATH` | `${USDPLUGINEXAMPLES_INSTALL_ROOT}/lib/python` | 90 | | `PXR_PLUGINPATH_NAME` | `${USDPLUGINEXAMPLES_INSTALL_ROOT}/lib/usd`
`${USDPLUGINEXAMPLES_INSTALL_ROOT}/plugin/usd` | 91 | 92 | Additionally, Windows requires: 93 | | Environment Variable | Value(s) | 94 | | --------------------- | ---------------------------------------------------------------------------------------- | 95 | | `PATH` | `${USDPLUGINEXAMPLES_INSTALL_ROOT}/lib` | 96 | 97 | Additionally, Linux requires: 98 | | Environment Variable | Value(s) | 99 | | --------------------- | ---------------------------------------------------------------------------------------- | 100 | | `LD_LIBRARY_PATH` | `${USDPLUGINEXAMPLES_INSTALL_ROOT}/lib` | 101 | 102 | Note: libraries and plugins are installed into different locations - thus PXR_PLUGINPATH_NAME specifies 103 | two separate values. 104 | 105 | To run the Hydra2 Prim Adapter with Storm/GL you have to enable the SceneIndex for UsdImagingGL 106 | | Environment Variable | Value(s) | 107 | | ---------------------------------------- | --------------------------------------------------------------------- | 108 | | `USDIMAGINGGL_ENGINE_ENABLE_SCENE_INDEX` | `1`````````````````` | 109 | 110 | 111 | Once the environment variables have been set-up, an example scene in this repo can be previewed with **usdview**: 112 | ``` 113 | usdview ./src/usdTri/scenes/triangle.usda 114 | ``` 115 | 116 | In the viewport, a triangle should be centered at origin: 117 | ![Triangle](./images/triangle_in_viewport.png) 118 | 119 | ## CMake Utilities 120 | 121 | Custom CMake functions are provided, for abstracting away USD plugin build intricacies: 122 | - `usd_library`: [Example usage](./src/usdTri/CMakeLists.txt) 123 | - `usd_plugin`: [Example usage](./src/hdTri/CMakeLists.txt) 124 | - `usd_executable`: [Example usage](./src/usdTri/CMakeLists.txt#L45) 125 | - `usd_test`: [Example usage](./src/usdTri/tests/CMakeLists.txt#L5) 126 | - `usd_python_library`: [Example usage](./src/usdviewTri/CMakeLists.txt) 127 | - `usd_python_test`: [Example usage](./src/usdTri/tests/CMakeLists.txt#L1) 128 | 129 | The interface of the above functions are largely based on those used throughout the [official USD project](https://github.com/PixarAnimationStudios/USD). 130 | 131 | **USDPluginExamples** can be used as a template ("Use this template" button near the top of the page). 132 | 133 | Another option to gain access to the cmake utilities is to copy/integrate the files under [cmake/](./cmake) into an existing project. 134 | -------------------------------------------------------------------------------- /src/usdTri/triangle.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta Digital Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | #ifndef USDTRI_GENERATED_TRIANGLE_H 7 | #define USDTRI_GENERATED_TRIANGLE_H 8 | 9 | /// \file usdTri/triangle.h 10 | 11 | #include "pxr/pxr.h" 12 | #include "./api.h" 13 | #include "pxr/usd/usdGeom/gprim.h" 14 | #include "pxr/usd/usd/prim.h" 15 | #include "pxr/usd/usd/stage.h" 16 | #include "./tokens.h" 17 | 18 | #include "pxr/base/vt/value.h" 19 | 20 | #include "pxr/base/gf/vec3d.h" 21 | #include "pxr/base/gf/vec3f.h" 22 | #include "pxr/base/gf/matrix4d.h" 23 | 24 | #include "pxr/base/tf/token.h" 25 | #include "pxr/base/tf/type.h" 26 | 27 | PXR_NAMESPACE_OPEN_SCOPE 28 | 29 | class SdfAssetPath; 30 | 31 | // -------------------------------------------------------------------------- // 32 | // TRIANGLE // 33 | // -------------------------------------------------------------------------- // 34 | 35 | /// \class UsdTriTriangle 36 | /// 37 | /// An equilateral triangle, whose vertices are equidistant to the 38 | /// origin and lie on the XY plane in object-space. 39 | /// 40 | class UsdTriTriangle : public UsdGeomGprim 41 | { 42 | public: 43 | /// Compile time constant representing what kind of schema this class is. 44 | /// 45 | /// \sa UsdSchemaKind 46 | static const UsdSchemaKind schemaKind = UsdSchemaKind::ConcreteTyped; 47 | 48 | /// Construct a UsdTriTriangle on UsdPrim \p prim . 49 | /// Equivalent to UsdTriTriangle::Get(prim.GetStage(), prim.GetPath()) 50 | /// for a \em valid \p prim, but will not immediately throw an error for 51 | /// an invalid \p prim 52 | explicit UsdTriTriangle(const UsdPrim& prim = UsdPrim()) 53 | : UsdGeomGprim(prim) 54 | { 55 | } 56 | 57 | /// Construct a UsdTriTriangle on the prim held by \p schemaObj . 58 | /// Should be preferred over UsdTriTriangle(schemaObj.GetPrim()), 59 | /// as it preserves SchemaBase state. 60 | explicit UsdTriTriangle(const UsdSchemaBase& schemaObj) 61 | : UsdGeomGprim(schemaObj) 62 | { 63 | } 64 | 65 | /// Destructor. 66 | USDTRI_API 67 | virtual ~UsdTriTriangle(); 68 | 69 | /// Return a vector of names of all pre-declared attributes for this schema 70 | /// class and all its ancestor classes. Does not include attributes that 71 | /// may be authored by custom/extended methods of the schemas involved. 72 | USDTRI_API 73 | static const TfTokenVector& GetSchemaAttributeNames( 74 | bool includeInherited = true); 75 | 76 | /// Return a UsdTriTriangle holding the prim adhering to this 77 | /// schema at \p path on \p stage. If no prim exists at \p path on 78 | /// \p stage, or if the prim at that path does not adhere to this schema, 79 | /// return an invalid schema object. This is shorthand for the following: 80 | /// 81 | /// \code 82 | /// UsdTriTriangle(stage->GetPrimAtPath(path)); 83 | /// \endcode 84 | /// 85 | USDTRI_API 86 | static UsdTriTriangle Get(const UsdStagePtr& stage, const SdfPath& path); 87 | 88 | /// Attempt to ensure a \a UsdPrim adhering to this schema at \p path 89 | /// is defined (according to UsdPrim::IsDefined()) on this stage. 90 | /// 91 | /// If a prim adhering to this schema at \p path is already defined on this 92 | /// stage, return that prim. Otherwise author an \a SdfPrimSpec with 93 | /// \a specifier == \a SdfSpecifierDef and this schema's prim type name for 94 | /// the prim at \p path at the current EditTarget. Author \a SdfPrimSpec s 95 | /// with \p specifier == \a SdfSpecifierDef and empty typeName at the 96 | /// current EditTarget for any nonexistent, or existing but not \a Defined 97 | /// ancestors. 98 | /// 99 | /// The given \a path must be an absolute prim path that does not contain 100 | /// any variant selections. 101 | /// 102 | /// If it is impossible to author any of the necessary PrimSpecs, (for 103 | /// example, in case \a path cannot map to the current UsdEditTarget's 104 | /// namespace) issue an error and return an invalid \a UsdPrim. 105 | /// 106 | /// Note that this method may return a defined prim whose typeName does not 107 | /// specify this schema class, in case a stronger typeName opinion overrides 108 | /// the opinion at the current EditTarget. 109 | /// 110 | USDTRI_API 111 | static UsdTriTriangle Define(const UsdStagePtr& stage, const SdfPath& path); 112 | 113 | protected: 114 | /// Returns the kind of schema this class belongs to. 115 | /// 116 | /// \sa UsdSchemaKind 117 | USDTRI_API 118 | UsdSchemaKind _GetSchemaKind() const override; 119 | 120 | private: 121 | // needs to invoke _GetStaticTfType. 122 | friend class UsdSchemaRegistry; 123 | USDTRI_API 124 | static const TfType& _GetStaticTfType(); 125 | 126 | static bool _IsTypedSchema(); 127 | 128 | // override SchemaBase virtuals. 129 | USDTRI_API 130 | const TfType& _GetTfType() const override; 131 | 132 | public: 133 | // --------------------------------------------------------------------- // 134 | // SIDELENGTH 135 | // --------------------------------------------------------------------- // 136 | /// The length of each side of the equilateral triangle. 137 | /// 138 | /// | || 139 | /// | -- | -- | 140 | /// | Declaration | `double sideLength = 1` | 141 | /// | C++ Type | double | 142 | /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Double | 143 | USDTRI_API 144 | UsdAttribute GetSideLengthAttr() const; 145 | 146 | /// See GetSideLengthAttr(), and also 147 | /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. 148 | /// If specified, author \p defaultValue as the attribute's default, 149 | /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - 150 | /// the default for \p writeSparsely is \c false. 151 | USDTRI_API 152 | UsdAttribute CreateSideLengthAttr(VtValue const& defaultValue = VtValue(), 153 | bool writeSparsely = false) const; 154 | 155 | public: 156 | // --------------------------------------------------------------------- // 157 | // EXTENT 158 | // --------------------------------------------------------------------- // 159 | /// Fallback extent value of a triangle with side length of 1.0. 160 | /// 161 | /// | || 162 | /// | -- | -- | 163 | /// | Declaration | `float3[] extent = [(-0.5, -0.28867513, 0), (0.5, 164 | /// 0.57735026, 0)]` | | C++ Type | VtArray | | \ref Usd_Datatypes 165 | /// "Usd Type" | SdfValueTypeNames->Float3Array | 166 | USDTRI_API 167 | UsdAttribute GetExtentAttr() const; 168 | 169 | /// See GetExtentAttr(), and also 170 | /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. 171 | /// If specified, author \p defaultValue as the attribute's default, 172 | /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - 173 | /// the default for \p writeSparsely is \c false. 174 | USDTRI_API 175 | UsdAttribute CreateExtentAttr(VtValue const& defaultValue = VtValue(), 176 | bool writeSparsely = false) const; 177 | 178 | public: 179 | // ===================================================================== // 180 | // Feel free to add custom code below this line, it will be preserved by 181 | // the code generator. 182 | // 183 | // Just remember to: 184 | // - Close the class declaration with }; 185 | // - Close the namespace with PXR_NAMESPACE_CLOSE_SCOPE 186 | // - Close the include guard with #endif 187 | // ===================================================================== // 188 | // --(BEGIN CUSTOM CODE)-- 189 | 190 | /// Compute the extent for the triangle defined by its side length. 191 | /// 192 | /// \retval true Successful extent computation. 193 | /// \retval false Failure to compute extent. 194 | USDGEOM_API 195 | static bool ComputeExtent(double sideLength, VtVec3fArray* extent); 196 | 197 | /// \overload 198 | /// Computes the extent as if the matrix \p transform was first applied. 199 | USDGEOM_API 200 | static bool ComputeExtent(double sideLength, 201 | const GfMatrix4d& transform, 202 | VtVec3fArray* extent); 203 | }; 204 | 205 | PXR_NAMESPACE_CLOSE_SCOPE 206 | 207 | #endif 208 | -------------------------------------------------------------------------------- /src/usdTriImagingHd2/dataSourceTri.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2024 Weta FX Limited 3 | // 4 | // SPDX-License-Identifier: Apache-2.0 5 | // 6 | 7 | #include "dataSourceTri.h" 8 | #include "debugCodes.h" 9 | 10 | #include 11 | #include 12 | 13 | #include "pxr/imaging/hd/meshSchema.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | PXR_NAMESPACE_OPEN_SCOPE 21 | 22 | // a static container-handle for the mesh-topology 23 | HdContainerDataSourceHandle 24 | _meshTopologyDs() 25 | { 26 | static const VtIntArray faceVertexCounts = { 3 }; 27 | 28 | static const VtIntArray faceVertexIndices = { 0, 1, 2 }; 29 | 30 | using _IntArrayDs = HdRetainedTypedSampledDataSource; 31 | 32 | static const _IntArrayDs::Handle fvcDs = _IntArrayDs::New(faceVertexCounts); 33 | 34 | static const _IntArrayDs::Handle fviDs = 35 | _IntArrayDs::New(faceVertexIndices); 36 | 37 | static const HdContainerDataSourceHandle meshDs = 38 | HdMeshSchema::Builder() 39 | .SetTopology(HdMeshTopologySchema::Builder() 40 | .SetFaceVertexCounts(fvcDs) 41 | .SetFaceVertexIndices(fviDs) 42 | .Build()) 43 | .Build(); 44 | 45 | return meshDs; 46 | } 47 | 48 | // a DataHandle producing Sampled Vec3fArray data 49 | // to be used as points of the triangle 50 | // it carries a great resemblence and is very much a copy of 51 | // UsdImagingDataSourceAttribute we technically would just need to overwrite 52 | // ::GetTypedValue(...) for our purposes here, but the constructor of 53 | // UsdImagingDataSourceAttribute is private so we need to re-implement 54 | // everything 55 | 56 | class _PointsFromSideLengthDataSource 57 | : public HdTypedSampledDataSource 58 | { 59 | public: 60 | HD_DECLARE_DATASOURCE(_PointsFromSideLengthDataSource); 61 | 62 | // copied the code from UsdImagingDataSourceAttribute 63 | bool GetContributingSampleTimesForInterval( 64 | Time startTime, 65 | Time endTime, 66 | std::vector