
概要 📖 – Pythonスクリプトでジオメトリを動的生成・編集
Script SOPは、毎クックごとに Python スクリプトを実行し、ポイント・プリミティブ・頂点・属性を動的に生成・削除・編集できる SOPです。cook() / onPulse() / setupParameters() の 3 つの Python メソッドを編集することで、頂点座標から複雑なメッシュ・ベジェ曲線まで任意のジオメトリをデータ駆動で組み立てます。
主な用途 🎯
- Python コードによるポイント・プリミティブの動的生成で、
cook()内からscriptOPAPI を呼び出し毎クックごとにジオメトリを再構築 - カスタム属性および標準属性 (Cd / uv / N) の付与で、ポイントごとの色・UV・法線等を Python から自由に書き込み
- ポリゴン・ベジェ曲線・メッシュ等多様なプリミティブ構築で、Python ループから addPoly / addBezier / addMesh 等を呼び任意形状を組み立て
- 複数入力 SOP のジオメトリ統合・合成で、
scriptOP.inputs経由で 0 以上の入力ジオメトリを Python 側で結合・編集 - setupParameters() による独自 UI パラメータ生成で、Setup Parameters ボタンを押した時点で Custom ページ上にカスタムパラメータを動的追加
- onPulse() でのイベント駆動処理で、ユーザ定義のパルスパラメータを押した瞬間にジオメトリリセット・再生成等の処理を実行
データフロー 🔄
入力: 0 個以上の任意 SOP (scriptOP.inputs 経由でアクセス)
↓
cook() メソッドが毎クック実行され Python から scriptOP API でポイント・プリミティブ・属性を生成・編集
↓
出力: cook() が組み立てたジオメトリ (ポイント数・プリミティブ数は Python ロジック次第)
初心者の方は、以下日本語書籍も手元にあると安心です。

実際の案件事例まで踏み込んで紹介されていて、効率よくスキルアップするなら必携の二冊です!
パラメータ解説 ⚙️
Script Page 📁
Callbacks DAT の指定 🎛️
Callbacks DAT .callbacks 🎛️
– cook() / onPulse() / setupParameters() の 3 メソッドを定義した DAT のパス
– デフォルトでは Script SOP 作成時に docked Text DAT (script1_callbacks) が自動生成され、この欄に自動セット
– 外部の Text DAT を指定して 1 つのコールバック実装を複数 Script SOP で共有することも可能
– 参照先 DAT を空にすると Script SOP は cook できずエラーになる
Setup Parameters の起動 ✨
Setup Parameters .setuppars ✨
– パルスボタンとして 1 回押すと setupParameters(scriptOP) コールバックが呼び出される
– コールバック内で scriptOP.appendParFloat('ValueA', page='Custom') 等を呼ぶと Custom ページにカスタムパラメータが追加される
– パラメータの追加・削除・名前変更を行うたびに押すことで、UI を再構築
– 通常の cook 中には呼ばれないため、UI 構築コードと毎クックのジオメトリ生成コードを分離可能
Default Functions 📁
Script SOP 作成時に docked DAT として自動生成される 3 つの Python メソッド (Help → Python Examples / Operator Snippets も参照):
| 項目 | 内部名 | 説明 |
|---|
実践アイデア 💡
Example 1: 円周上に等間隔ポイントを cook() で動的生成する基本パターン ⭕
Script SOP (Callbacks=script1_callbacks, Custom: numPoints / radius) → Convert SOP → Material SOP → Render TOP
Script SOP の cook() 内で math.sin / math.cos を使い、Custom ページの numPoints と radius から円周上のポイントを毎クック生成する最小構成のパターンです。setupParameters() で UI を作り、cook() 内で scriptOP.clear() → appendPoint() ループで頂点を配置します。
- Script SOP を配置すると
script1_callbacksという Text DAT が docked DAT として自動生成される setupParameters(scriptOP)内にscriptOP.appendParInt('Numpoints', page='Custom')とscriptOP.appendParFloat('Radius', page='Custom')を追加して Setup Parameters ボタンを押すcook(scriptOP)内でscriptOP.clear()を呼んだ後、for i in range(scriptOP.par.Numpoints)ループで角度theta = 2*math.pi*i/nを計算- ループ内で
p = scriptOP.appendPoint()とp.P = (radius*math.cos(theta), 0, radius*math.sin(theta))で 3D 座標を設定 - Custom ページの
NumpointsやRadiusを変更するとリアルタイムで円周ポイントが更新されることを確認
Example 2: onPulse()で形状をイベント駆動リセット 💥
Script SOP (Custom: Generate パルス / Clear パルス) ← onPulse() で分岐 → Out SOP
setupParameters() で 2 つのパルスパラメータを追加し、onPulse(par) 内で par.name を見て分岐することで、UI ボタンに応じてジオメトリを新規生成したりクリアしたりするイベント駆動パターンです。cook() は最小限にし、状態変更は全て onPulse() 側で行います。
setupParameters(scriptOP)内でscriptOP.appendParPulse('Generate', page='Custom')とappendParPulse('Clear', page='Custom')を追加- Setup Parameters ボタンを押して Custom ページに 2 つのパルスボタンを表示
onPulse(par)内でif par.name == 'Generate':分岐を作り、ランダム座標でscriptOP.appendPoint()をループ追加elif par.name == 'Clear':分岐でscriptOP.clear()を呼んで全ジオメトリを削除- Custom ページの Generate / Clear ボタンを押して、ジオメトリの追加・クリアがイベント単位で動くことを確認
Example 3: 複数SOPを合成しCd色をPythonで付与 🎨
Box SOP / Sphere SOP / Grid SOP → Script SOP (Callbacks: 3 入力をマージ + Cd 付与) → Geometry COMP → Render TOP
scriptOP.inputs 経由で 0 個以上の入力 SOP にアクセスし、各入力のポイント座標をコピーしながら入力番号ごとに異なる色 (Cd 属性) を付与するパターンです。scriptOP.appendCustomAttribute('Cd', 'vector') でカスタム属性を確保し、ポイントごとに色を書き込みます。
- Box SOP / Sphere SOP / Grid SOP の 3 つを Script SOP の 3 入力に接続
cook(scriptOP)内でscriptOP.clear()を呼んだ後、colors = [(1,0,0),(0,1,0),(0,0,1)]を準備for idx, inp in enumerate(scriptOP.inputs):ループで入力をイテレートし、各inp.pointsから座標をコピーしてscriptOP.appendPoint()- ポイントごとに
p.Cd = colors[idx]等のかたちで色属性を書き込み - Material SOP で頂点カラー対応のシェーダを適用、または Geometry COMP 経由で Render TOP に渡して 3 色合成形状が出ることを確認
関連オペレータ 🔗
類似機能OP 🔍
- CPlusPlus SOP — C++ でジオメトリを動的生成 (Script SOP の Python 版に対して C++ ネイティブで高速処理)
- DAT to SOP — Table DAT に記述したポイント・プリミティブを SOP に変換 (Script SOP よりも宣言的、テキストデータ駆動)
組み合わせ推奨OP 🔄
- Script DAT — Script SOP の Callbacks DAT として参照する Python コールバック実装の入れ物
- Script CHOP — 同じ Script 系のチャンネル版。CHOP データを Python で生成・編集
- SOP to DAT — Script SOP が生成したジオメトリを Table DAT に書き出して検証・ロギング
- Info CHOP — Script SOP 自体の num_points / num_prims / cook_time 等の状態を CHOP チャンネルとして取得
- Geometry COMP — Script SOP が組み立てたジオメトリをレンダリングパイプラインに渡す出力先 COMP
前処理・後処理SOP 🎯
Info CHOP情報 📊
Script SOP は Info CHOP による詳細情報取得に対応しています。
ジオメトリ統計 📐
num_points: この SOP に含まれるポイント数num_prims: この SOP に含まれるプリミティブ数num_particles: この SOP に含まれるパーティクル数last_vbo_update_time:last_vbo_update_time— 別スレッドで GPU 上にジオメトリ VBO を更新した所要時間 (通常のフレーム時間には含まれない)last_meta_vbo_update_time:last_meta_vbo_update_time— メタサーフェス (metaballs / nurbs 等) の GPU 更新所要時間 (別スレッド)
GPU 転送タイミング 🎮
last_vbo_update_time: 別スレッドで SOP の CPU データを GPU 上のジオメトリデータに更新するのにかかった時間 (フレーム時間外)last_meta_vbo_update_time: 別スレッドで metaball や NURBS のようなメタサーフェスジオメトリデータを GPU に更新するのにかかった時間 (フレーム時間外)
汎用オペレータ情報 🔄
total_cooks: プロセス開始以降にこのオペレータがクックされた合計回数cook_time: 直近のクック所要時間 (ミリ秒)cook_frame: このオペレータが最後にクックされたフレーム番号warnings: このオペレータの警告数errors: このオペレータのエラー数
クック統計 ⏱️
total_cooks:total_cooks— プロセス開始以降にこのオペレータがクックされた合計回数cook_time:cook_time— 直近のクック所要時間 (ミリ秒)。Python ロジックの重さがそのまま反映されるcook_frame:cook_frame— このオペレータが最後にクックされたフレーム番号cooked_this_frame:cooked_this_frame— 当該フレームでクックされた場合は1warnings:warnings— このオペレータに付いている警告数 (Python 内でscriptOP.addWarningを呼ぶと加算)errors:errors— このオペレータに付いているエラー数 (Python 内で例外が発生したりエラーログが書かれると加算)
トラブルシューティング ⚠️
よくある問題と解決策 🔧
❌ Problem: cook() に書いたコードが思ったように実行されない / ジオメトリが出力されない
✅ Solution:
cook()の冒頭でscriptOP.clear()を呼んでいるか確認 — 呼ばないと前回のジオメトリが残り続けて新しい点が追加されるだけになる- Script ページの
Callbacks DATパスが正しい DAT を指しているか確認 — 空や存在しないパスだと cook 自体が実行されない - 対象 DAT のテキスト内で
cookの関数シグネチャがdef cook(scriptOP):になっているか (引数名は scriptOP 推奨、変えると参照系コードを総書換になりミスりやすい)
❌ Problem: Setup Parameters ボタンを押してもカスタムパラメータが出ない
✅ Solution:
setupParameters(scriptOP)内でscriptOP.appendParFloat/appendParInt/appendParPulse等のpage='Custom'指定を確認- Callbacks DAT 内に
def setupParameters(scriptOP):関数が定義されているか確認 — 関数名のタイポ (例:setupParameter単数形) でも呼ばれない - Setup Parameters ボタンを 1 回押す必要がある。ファイルを開いた直後やコールバック編集後は手動で押し直さないと UI に反映されない
❌ Problem: 毎クック時のパフォーマンスが重い / 他のオペレータが描画追従しない
✅ Solution:
cook()内でループ回数の多い処理 (数万ポイント生成等) を毎クック実行している場合は、ジオメトリ更新が必要なフレームだけ Active 制御するか Cache SOP で結果をキャッシュ- Python 内で参照している外部オペレータ・パラメータ数を減らす — Script SOP は参照先が変わるたびに再 cook されるため、依存先が多いほどクック頻度が増える
- 重い数値計算は CPlusPlus SOP や GPU 側 (TOP / POP) に移譲し、Script SOP はパイプラインの薄い接着剤に留める
❌ Problem: 複数入力からのジオメトリ合成で点や色がズレる
✅ Solution:
scriptOP.inputsがリストとして 0 個以上の入力を返すことを前提に、for inp in scriptOP.inputs:で安全にイテレート (固定 index 参照は入力 0 個ケースで例外)- 各入力のポイント座標
inp.points[i].Pをコピーする際は、必要に応じて Transform SOP で事前に正規化座標系を揃える Cd等のカスタム属性をscriptOP.appendCustomAttribute('Cd', 'vector')で確保してから書き込みしているか — 属性宣言なしの代入は無視される
参考資料 📚
その他 🔗
- TouchDesigner Wiki — SOP 概要
- TouchDesigner Wiki — Category:SOPs
- TouchDesigner Wiki ホーム
- TouchDesigner 公式 Forum
- Facebook — TouchDesigner Help Group
公式リソース 📖
- TouchDesigner公式ドキュメント – Script SOP
- TouchDesigner公式ドキュメント – ScriptSOP Class
- TouchDesigner公式ドキュメント – SOP Class (親クラス)
- TouchDesigner公式ドキュメント – Attributes (Cd / uv / N 等)

