[TouchDesigner] Sprinkle SOPの応用
2023-02-15
2023-02-15
TouchDesignerのSprinkle SOPを使い、ジオメトリのサーフェス上にポイントを生成する方法を解説します。
検証環境
- Windows 10 22H2
- TouchDesigner 2022.32120 (Commercial License)
サンプルプロジェクト
https://github.com/yasuhirohoshino/TouchDesignerExamples/tree/master/SOP/sprinkleSOP
ポイントにアニメーションを適用する
In 1
にDeform前のジオメトリを、In 2
にDeform後のジオメトリを入力することで、サーフェス上に撒いたポイントをアニメーションに追従させることができます。
なお、FBXアニメーションにSprinkle SOPを適用したい場合、Select SOP
とDeform SOP
を使うことで、CPUでアニメーションを実行する必要があります。
アトリビュートを転送し、インスタンシングに使用する
Surface Attributes
をオンにすると、入力ジオメトリのポイントアトリビュートを転送できます。
入力ジオメトリがNormalアトリビュートを持っていれば、アトリビュートを転送することで、インスタンシングでオブジェクトの向きを指定するために使えますが、アップベクトルが無いとGeometry COMP
に警告が発生し、意図した方向にオブジェクトが向かない恐れがあります。
対策としては、入力前のジオメトリに、Attribute Create SOP
でNormalとTangentを付与し、Script SOP
で外積を計算しアップベクトルを作成する方法があります。
Script SOP
def onPulse(par):
return
def onCook(scriptOp):
scriptOp.clear()
# 入力ジオメトリをコピー
a = scriptOp.inputs[0]
scriptOp.copy(a)
# アップベクトルのアトリビュートを作成し初期化
scriptOp.pointAttribs.create('upVector', (0.0, 1.0, 0.0))
# 頂点からTangentを集めるための空の配列
tList = [[] for i in range(scriptOp.numPoints)]
for prim in scriptOp.prims:
for vert in prim:
# TangentをPointごとに集める
id = vert.point.index
tList[id].append(tdu.Vector(vert.T[0], vert.T[1], vert.T[2]))
for i, t in enumerate(tList):
# ポイントごとのTangentの平均を計算
meanT = sum(t) / len(t)
meanT.normalize()
# Normalを取得
n = tdu.Vector(scriptOp.points[i].N[0], scriptOp.points[i].N[1], scriptOp.points[i].N[2])
# NormalとTangentの外積を計算し、アップベクトルとする
u = n.cross(meanT)
u.normalize()
# アップベクトルを付与
scriptOp.points[i].upVector[0] = u[0]
scriptOp.points[i].upVector[1] = u[1]
scriptOp.points[i].upVector[2] = u[2]
return