From d396ec7204f140702e3d89cf71b91c871678f77c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?furby=E2=84=A2?= Date: Sun, 29 Dec 2024 04:50:54 -0700 Subject: [PATCH] Fix/simplify metal view update, add hdr texture to dome light. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: furby™ --- Sources/PixarMacros/MacrosPlugin.swift | 3 +- Sources/PixarMacros/PrimMacros.swift | 34 ++++++++++++++ Sources/PixarMacros/StringifyMacros.swift | 2 +- Sources/PixarUSD/Usd/Sdf/AssetPath.swift | 30 +++++++++++++ Sources/PixarUSD/Usd/Usd/Attribute.swift | 10 +++++ .../Usd/UsdGeom/PrimRepresentable.swift | 21 +++++++++ Sources/PixarUSD/Usd/UsdLux/DomeLight.swift | 10 +++++ .../UsdView/Hydra/Hydra+RenderEngine.swift | 4 +- Sources/UsdView/Hydra/Hydra+View.swift | 2 +- .../UsdView/Hydra/MTL/Hydra+MTLRenderer.swift | 19 +++++--- Sources/UsdView/Hydra/MTL/Hydra+MTLView.swift | 3 -- .../SceneDescription/CreateScene.swift | 45 ++++++------------- Sources/UsdView/UsdView.swift | 44 +++++------------- 13 files changed, 148 insertions(+), 79 deletions(-) create mode 100644 Sources/PixarMacros/PrimMacros.swift create mode 100644 Sources/PixarUSD/Usd/Sdf/AssetPath.swift create mode 100644 Sources/PixarUSD/Usd/UsdGeom/PrimRepresentable.swift diff --git a/Sources/PixarMacros/MacrosPlugin.swift b/Sources/PixarMacros/MacrosPlugin.swift index f03fc2b80..f461aae12 100644 --- a/Sources/PixarMacros/MacrosPlugin.swift +++ b/Sources/PixarMacros/MacrosPlugin.swift @@ -18,6 +18,7 @@ import SwiftSyntaxMacros struct PixarMacrosPlugin: CompilerPlugin { let providingMacros: [Macro.Type] = [ - PixarXformableMacro.self + PixarXformableMacro.self, + PixarPrimMacro.self ] } diff --git a/Sources/PixarMacros/PrimMacros.swift b/Sources/PixarMacros/PrimMacros.swift new file mode 100644 index 000000000..416e8c341 --- /dev/null +++ b/Sources/PixarMacros/PrimMacros.swift @@ -0,0 +1,34 @@ +/* ---------------------------------------------------------------- + * :: : M E T A V E R S E : :: + * ---------------------------------------------------------------- + * Licensed under the terms set forth in the LICENSE.txt file, this + * file is available at https://openusd.org/license. + * + * Copyright (C) 2016 Pixar. + * Copyright (C) 2024 Wabi Foundation. All Rights Reserved. + * ---------------------------------------------------------------- + * . x x x . o o o . x x x . : : : . o x o . : : : . + * ---------------------------------------------------------------- */ + +import Foundation +import SwiftCompilerPlugin +import SwiftSyntax +import SwiftSyntaxBuilder +import SwiftSyntaxMacros + +public struct PixarPrimMacro: MemberMacro +{ + public static func expansion(of _: SwiftSyntax.AttributeSyntax, + providingMembersOf _: some SwiftSyntax.DeclGroupSyntax, + in _: some SwiftSyntaxMacros.MacroExpansionContext) throws -> [SwiftSyntax.DeclSyntax] + { + let decl: DeclSyntax = """ + public func getAttribute(_ name: Tf.Token) -> Usd.Attribute + { + GetAttribute(name) + } + """ + + return [decl] + } +} diff --git a/Sources/PixarMacros/StringifyMacros.swift b/Sources/PixarMacros/StringifyMacros.swift index 841eb428e..8feb0624d 100644 --- a/Sources/PixarMacros/StringifyMacros.swift +++ b/Sources/PixarMacros/StringifyMacros.swift @@ -21,7 +21,7 @@ public struct StringifyMacro: ExpressionMacro in _: some MacroExpansionContext ) -> ExprSyntax { - guard let argument = node.argumentList.first?.expression + guard let argument = node.arguments.first?.expression else { fatalError("compiler bug: the macro does not have any arguments") diff --git a/Sources/PixarUSD/Usd/Sdf/AssetPath.swift b/Sources/PixarUSD/Usd/Sdf/AssetPath.swift new file mode 100644 index 000000000..8b1efc19a --- /dev/null +++ b/Sources/PixarUSD/Usd/Sdf/AssetPath.swift @@ -0,0 +1,30 @@ +/* ---------------------------------------------------------------- + * :: : M E T A V E R S E : :: + * ---------------------------------------------------------------- + * Licensed under the terms set forth in the LICENSE.txt file, this + * file is available at https://openusd.org/license. + * + * Copyright (C) 2016 Pixar. + * Copyright (C) 2024 Wabi Foundation. All Rights Reserved. + * ---------------------------------------------------------------- + * . x x x . o o o . x x x . : : : . o x o . : : : . + * ---------------------------------------------------------------- */ + +import CxxStdlib +import Foundation +import Sdf + +public typealias SdfAssetPath = Pixar.SdfAssetPath + +public extension Sdf +{ + typealias AssetPath = SdfAssetPath +} + +public extension Sdf.AssetPath +{ + init(_ path: String) + { + self.init(std.string(path)) + } +} diff --git a/Sources/PixarUSD/Usd/Usd/Attribute.swift b/Sources/PixarUSD/Usd/Usd/Attribute.swift index f70f226c3..6f5b2591e 100644 --- a/Sources/PixarUSD/Usd/Usd/Attribute.swift +++ b/Sources/PixarUSD/Usd/Usd/Attribute.swift @@ -26,4 +26,14 @@ public extension Usd.Attribute { SetDocumentation(std.string(doc)) } + + func set(_ value: String, time: UsdTimeCode = UsdTimeCode.Default()) -> Bool + { + Set(std.string(value), time) + } + + func set(_ value: Sdf.AssetPath, time: UsdTimeCode = UsdTimeCode.Default()) -> Bool + { + Set(value, time) + } } diff --git a/Sources/PixarUSD/Usd/UsdGeom/PrimRepresentable.swift b/Sources/PixarUSD/Usd/UsdGeom/PrimRepresentable.swift new file mode 100644 index 000000000..35aa5eb4b --- /dev/null +++ b/Sources/PixarUSD/Usd/UsdGeom/PrimRepresentable.swift @@ -0,0 +1,21 @@ +/* ---------------------------------------------------------------- + * :: : M E T A V E R S E : :: + * ---------------------------------------------------------------- + * Licensed under the terms set forth in the LICENSE.txt file, this + * file is available at https://openusd.org/license. + * + * Copyright (C) 2016 Pixar. + * Copyright (C) 2024 Wabi Foundation. All Rights Reserved. + * ---------------------------------------------------------------- + * . x x x . o o o . x x x . : : : . o x o . : : : . + * ---------------------------------------------------------------- */ + +import Usd + +@attached(member, names: arbitrary, conformances: PrimRepresentable) +public macro Prim() = #externalMacro(module: "PixarMacros", type: "PixarPrimMacro") + +public protocol PrimRepresentable +{ + func getAttribute(_ name: Tf.Token) -> Usd.Attribute +} diff --git a/Sources/PixarUSD/Usd/UsdLux/DomeLight.swift b/Sources/PixarUSD/Usd/UsdLux/DomeLight.swift index 8a7af36ec..81d80d57a 100644 --- a/Sources/PixarUSD/Usd/UsdLux/DomeLight.swift +++ b/Sources/PixarUSD/Usd/UsdLux/DomeLight.swift @@ -33,4 +33,14 @@ extension UsdLux.DomeLight: GeomXformable { UsdLux.DomeLight.define(stage, path: .init(path)) } + + public func getTextureFileAttr() -> Usd.Attribute + { + GetTextureFileAttr() + } + + public func createTextureFileAttr(defaultValue: Vt.Value = Vt.Value(), writeSparsely: Bool = false) -> Usd.Attribute + { + CreateTextureFileAttr(defaultValue, writeSparsely) + } } diff --git a/Sources/UsdView/Hydra/Hydra+RenderEngine.swift b/Sources/UsdView/Hydra/Hydra+RenderEngine.swift index f1cb33a9d..78be4f4e1 100644 --- a/Sources/UsdView/Hydra/Hydra+RenderEngine.swift +++ b/Sources/UsdView/Hydra/Hydra+RenderEngine.swift @@ -50,9 +50,9 @@ public enum Hydra params.frame = Usd.TimeCode.Default() params.clearColor = .init(Float(rgba.0), Float(rgba.1), Float(rgba.2), Float(rgba.3)) params.enableIdRender = false - params.showGuides = false + params.showGuides = true params.showRender = true - params.showProxy = false + params.showProxy = true engine.render(root: stage.getPseudoRoot(), params: params) } diff --git a/Sources/UsdView/Hydra/Hydra+View.swift b/Sources/UsdView/Hydra/Hydra+View.swift index f2d80222f..ef0462af3 100644 --- a/Sources/UsdView/Hydra/Hydra+View.swift +++ b/Sources/UsdView/Hydra/Hydra+View.swift @@ -36,7 +36,7 @@ public extension Hydra.Viewport init(engine: Hydra.RenderEngine, rgba: (Double, Double, Double, Double)) { #if canImport(Metal) && !os(visionOS) - let renderer = Hydra.MTLRenderer(device: engine.hydraDevice)! + let renderer = Hydra.MTLRenderer(device: engine.hydraDevice, hydra: engine) self.init(hydra: engine, renderer: renderer, rgba: rgba) #endif // canImport(Metal) && !os(visionOS) } diff --git a/Sources/UsdView/Hydra/MTL/Hydra+MTLRenderer.swift b/Sources/UsdView/Hydra/MTL/Hydra+MTLRenderer.swift index 5f1868f2b..bfefa717c 100644 --- a/Sources/UsdView/Hydra/MTL/Hydra+MTLRenderer.swift +++ b/Sources/UsdView/Hydra/MTL/Hydra+MTLRenderer.swift @@ -21,9 +21,16 @@ import PixarUSD class MTLRenderer: NSObject, MTKViewDelegate { private let device: MTLDevice + private var hydra: Hydra.RenderEngine? //private let commandQueue: MTLCommandQueue private var pipelineState: MTLRenderPipelineState? + convenience init(device: MTLDevice, hydra: Hydra.RenderEngine) + { + self.init(device: device)! + self.hydra = hydra + } + init?(device: MTLDevice) { self.device = device @@ -57,15 +64,11 @@ import PixarUSD public func draw(in view: MTKView) { guard let drawable = view.currentDrawable else { return } - let renderPassDescriptor = view.currentRenderPassDescriptor + guard let renderPassDescriptor = view.currentRenderPassDescriptor else { return } let commandQueue = view.device?.makeCommandQueue() let commandBuffer = commandQueue?.makeCommandBuffer() - - var renderEncoder: (any MTLRenderCommandEncoder)? = nil - if let renderPassDescriptor { - renderEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: renderPassDescriptor) - } + let renderEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: renderPassDescriptor) if let pipelineState { renderEncoder?.setRenderPipelineState(pipelineState) @@ -81,8 +84,10 @@ import PixarUSD zfar: 1.0 ) ) - renderEncoder?.endEncoding() + hydra?.render(rgba: (0.1, 0.1, 0.1, 1.0)) + + renderEncoder?.endEncoding() commandBuffer?.present(drawable) commandBuffer?.commit() } diff --git a/Sources/UsdView/Hydra/MTL/Hydra+MTLView.swift b/Sources/UsdView/Hydra/MTL/Hydra+MTLView.swift index ad4f15ac3..4d938e385 100644 --- a/Sources/UsdView/Hydra/MTL/Hydra+MTLView.swift +++ b/Sources/UsdView/Hydra/MTL/Hydra+MTLView.swift @@ -68,10 +68,7 @@ import PixarUSD public func updateNSView(_ view: MTKView, context: Context) { - // view.clearColor = MTLClearColorMake(rgba.0, rgba.1, rgba.2, rgba.3) - renderer.draw(in: view) - hydra.render(rgba: rgba) } public class Coordinator diff --git a/Sources/UsdView/SceneDescription/CreateScene.swift b/Sources/UsdView/SceneDescription/CreateScene.swift index 0b1c74d70..068d4713b 100644 --- a/Sources/UsdView/SceneDescription/CreateScene.swift +++ b/Sources/UsdView/SceneDescription/CreateScene.swift @@ -16,45 +16,23 @@ import PixarUSD extension UsdView { /** - * Create a stage with a sphere, capsule, cylinder, cube - * and cone on a transform, create a different colored - * material for each geometry prim, iterate the stage and - * print out the path to each prim, and finally save the - * stage to disk. */ - func createScene() + * Create a basic usd scene. */ + static func createScene() -> UsdStageRefPtr { - /* Create stage with a sphere, capsule, cylinder, cube, and cone on a transform. */ + /* Create stage with a dome light & sphere on a transform. */ - let xform = UsdGeom.Xform.define(stage, path: "/Geometry") - xform.addXformOp(type: .translate).set(GfVec3d(0.0, 5.0, 0.0)) - xform.addXformOp(type: .scale, precision: .float).set(GfVec3f(5, 5, 5)) + let stage = Usd.Stage.createNew("\(documentsDirPath())/HelloWorldExample", ext: .usd) - let sphere = UsdGeom.Sphere.define(stage, path: "/Geometry/Sphere") - sphere.addXformOp(type: .translate).set(GfVec3d(0.0, 0.0, -5.0)) - - let capsule = UsdGeom.Capsule.define(stage, path: "/Geometry/Capsule") - capsule.addXformOp(type: .translate).set(GfVec3d(0.0, 0.0, -10.0)) - capsule.addXformOp(type: .rotateX, precision: .float).set(Float(-90)) - - let cylinder = UsdGeom.Cylinder.define(stage, path: "/Geometry/Cylinder") - cylinder.addXformOp(type: .rotateX, precision: .float).set(Float(-90)) + let domeLight = UsdLux.DomeLight.define(stage, path: "/World/DefaultDomeLight") + let hdr = Sdf.AssetPath("\(Bundle.hdx!.resourcePath!)/textures/StinsonBeach.hdr") + domeLight.createTextureFileAttr().set(hdr) - let cube = UsdGeom.Cube.define(stage, path: "/Geometry/Cube") - cube.addXformOp(type: .translate).set(GfVec3d(0.0, 0.0, 5.0)) - - let cone = UsdGeom.Cone.define(stage, path: "/Geometry/Cone") - cone.addXformOp(type: .translate).set(GfVec3d(0.0, 0.0, 10.0)) - cone.addXformOp(type: .rotateX, precision: .float).set(Float(-90)) + UsdGeom.Xform.define(stage, path: "/Geometry") + let sphere = UsdGeom.Sphere.define(stage, path: "/Geometry/Sphere") - /* Create a different colored material for each geometry prim. */ + /* Create a colored material for the sphere prim. */ UsdShade.MaterialBindingAPI.apply(sphere).bind(matDef(stage, color: .red)) - UsdShade.MaterialBindingAPI.apply(capsule).bind(matDef(stage, color: .yellow)) - UsdShade.MaterialBindingAPI.apply(cylinder).bind(matDef(stage, color: .green)) - UsdShade.MaterialBindingAPI.apply(cube).bind(matDef(stage, color: .blue)) - UsdShade.MaterialBindingAPI.apply(cone).bind(matDef(stage, color: .purple)) - - stage.getPseudoRoot().set(doc: "SwiftUSD v\(Pixar.version)") /* Iterate the stage and print out the path to each prim. */ @@ -66,6 +44,9 @@ extension UsdView /* Save the stage to disk. */ + stage.getPseudoRoot().set(doc: "SwiftUSD v\(Pixar.version)") stage.save() + + return stage } } diff --git a/Sources/UsdView/UsdView.swift b/Sources/UsdView/UsdView.swift index 061e28c6f..0bc9fd54c 100644 --- a/Sources/UsdView/UsdView.swift +++ b/Sources/UsdView/UsdView.swift @@ -49,47 +49,27 @@ struct UsdView: PixarApp registerPlugins() // create a new usd stage. - stage = Usd.Stage.createNew("\(documentsDirPath())/HelloPixarUSD", ext: .usda) + stage = UsdView.createScene() // setup hydra to render the usd stage. engine = Hydra.RenderEngine(stage: stage) - runDemo() + Msg.logger.log(level: .info, "UsdView launched | USD v\(Pixar.version).") } - #if canImport(SwiftUI) - var body: some Scene + var body: some Scene + { + WindowGroup("UsdView", id: "usdview") { - WindowGroup("UsdView", id: "usdview") + VStack { - VStack - { - Hydra.Viewport(engine: engine, rgba: rgba) - .ignoresSafeArea() - } - .onAppear - { - #if canImport(SwiftUI) - startColorAnimation() - #endif // canImport(SwiftUI) - } + Hydra.Viewport(engine: engine, rgba: rgba) + .ignoresSafeArea() + } + .onAppear + { + startColorAnimation() } } - #else - static func main() - { - let app = UsdView() - } - #endif - - func runDemo() - { - // create usd scene. - createScene() - - // declarative usd scene. - declareScene() - - Msg.logger.log(level: .info, "UsdView launched | USD v\(Pixar.version).") } }