⚒️

XcodeのPlaygroundで画像からusdzを生成

2023/11/01に公開

概要

XcodeのPlaygroundを使い静止画からusdzファイルを作成する方法。
追加ソフトなしで実行でき、サイズ、向き、位置の指定も可能なので便利です。

Playground作成

Xcodeの File > New > Playground から作成。

Resourcesフォルダに画像ファイルを配置

Navigatorを表示し、Resourcesフォルダに画像ファイルをドラッグ&ドロップで追加します。
Navigatorはこちらのアイコンから表示。

実装

import UIKit
import SceneKit
import PlaygroundSupport

let imagePath = Bundle.main.path(forResource: "image_001", ofType: "png")!
let image = UIImage(contentsOfFile: imagePath)!

let filepath = playgroundSharedDataDirectory.appendingPathComponent("out.usdz")
print("write to \(filepath)")

let fileManager = FileManager.default
if !fileManager.fileExists(atPath: playgroundSharedDataDirectory.path()) {
    try! fileManager.createDirectory(atPath: playgroundSharedDataDirectory.path().replacingOccurrences(of: "%20", with: " "), withIntermediateDirectories: true, attributes: nil)
}

func exec(sourceImage: UIImage, destUrl: URL) {

    let scene = SCNScene()

    let node = SCNNode()
    node.eulerAngles = SCNVector3(0, 0, 0)
    node.geometry = SCNPlane(width: 0.5, height: 0.5)
    node.position = .init(x: 0, y: 1.5, z: 0)

    let material = SCNMaterial()
    material.isDoubleSided = true // it's not working...
    material.diffuse.contents = sourceImage
    material.transparent.contents = sourceImage
    material.emission.contents = sourceImage
    material.ambientOcclusion.contents = sourceImage
    node.geometry?.materials = [material]

    scene.rootNode.addChildNode(node)

    scene.write(to: destUrl, options: nil, delegate: nil, progressHandler: nil)
}

exec(sourceImage: image, destUrl: filepath)

実行

print("write to \(filepath)")

で表示されたパスにusdzファイルが生成されています。

余談

Reality Converterで生成すると元の画像より少し暗くなったり枠がついてしまったりでコツと手間が必要でした。
Blender等のグラフィックツールでも作成できますが、シンプルに画像をusdz化したいだけなのになかなか大変。
オンラインの変換サービスでは正方形固定だったり広告が挟まれたりでこれも手間が大きい。

これらを解決したく、作成しました。

Discussion