Closed11
pngからUSDZ生成する機能の実装
1枚絵の画像からUSDZを生成するのがとても面倒なのでツール化したいと考えた
Reality Composerに画像をドラッグ&ドロップで生成できそうだが、なぜか暗くなってしまう
以前、Reality Converterで複数の画像を設定して乗り切った。その作業を自動化したらいけるかも、と。
XcodeのPlaygroundで検証。
ファイル読み込みと保存はこんな形。
実行するとエラー。
実行時のパスを見つけて Documents/ 配下に "Shared Playground Data" という名前のフォルダを手動生成したら保存成功。まじか。
import UIKit
import PlaygroundSupport
let imagePath = Bundle.main.path(forResource: "image001", ofType: "png")!
let image = UIImage(contentsOfFile: imagePath)!
let imagedata = image.jpegData(compressionQuality: 1.0)
let filepath = playgroundSharedDataDirectory.appendingPathComponent("export.jpg")
try! imagedata?.write(to: filepath)
print("write to \(filepath)")
usdaからusdzにする方法を試したが上手くいかず。
MDLAssetのcountが0。
usdaはテキストエディタで下記を保存。
Finderのプレビューでは良い感じで表示されている。
しかしMDLAssetにした時点で失敗。
#usda 1.0
def Xform "sample001"
{
def Mesh "mesh"
{
uniform bool doubleSided = 1
int[] faceVertexCounts = [4]
int[] faceVertexIndices = [0, 1, 2, 3]
rel material:binding = </sample001/material_0>
normal3f[] normals = [(0, 1, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0)]
point3f[] points = [(-1, 0, -1), (-1, 0, 1), (1, 0, 1), (1, 0, -1)]
texCoord2f[] primvars:st = [(0, 0), (1, 0), (1, 1), (0, 1)] (
interpolation = "varying"
)
}
def Material "material_0"
{
token inputs:frame:stPrimvarName = "st"
token outputs:surface.connect = </sample001/material_0/PBRShader.outputs:surface>
def Shader "PBRShader"
{
uniform token info:id = "UsdPreviewSurface"
color3f inputs:diffuseColor.connect = </sample001/material_0/diffuseTexture.outputs:rgb>
float inputs:metallic = 0.0
float inputs:roughness = 0.0
token outputs:surface
}
def Shader "stReader"
{
uniform token info:id = "UsdPrimvarReader_float2"
token inputs:varname.connect = </sample001/material_0.inputs:frame:stPrimvarName>
float2 outputs:result
}
def Shader "diffuseTexture"
{
uniform token info:id = "UsdUVTexture"
asset inputs:file = @sticker001.png@
float2 inputs:st.connect = </sample001/material_0/stReader.outputs:result>
float3 outputs:rgb
}
}
}
Pythonのコマンドラインツールから生成するのが良いと思えた。
Swiftでどこまでできるのか確認したかった。
SCNSceneから生成する方法を検証。
結果としてdiffuse、transparent、emission、ambientOcclusionに画像設定することで対応できた気配。
public func exec(sourceImage: UIImage, destUrl: URL) {
let scene = SCNScene()
let node = SCNNode()
node.eulerAngles = SCNVector3(-Float.pi/2, 0, 0)
node.geometry = SCNPlane(width: 0.5, height: 0.5)
let material = SCNMaterial()
material.isDoubleSided = true
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)
}
2048 x 2048 までの正方形の透過情報付きpngを指定すると良い感じのusdzを生成してくれるはず。
こちらを付加していくとさらにAR的拡張ができるが、別件だな。
AWS LambdaでAPI化してpngのbase64を受け付けるようにしたら実用的か。
一旦ここまで。
このスクラップは2021/11/04にクローズされました