Zenn
🔖

Houdini MCPで遊んでみた! -自然言語でのモデリング-

2025/04/01に公開
5

この記事はAIの支援を受けつつ、筆者の試行錯誤を記録したものです。一部にAIが生成した表現も含まれますが、実験の過程や考察は筆者の経験に基づいています。

AI特有の文章に対して抵抗がある場合はブラウザバック。

はじめに:未来のモデリング体験への招待状

この記事のポイント

Houdini MCPとObsidian MCPを連携させることで、AIに指示するだけでHoudiniのノード群から、半自動で解説記事を作成するという実験に成功しました。
これはあくまで実験的な試みですが、さらに突き詰めれば、AI連携の可能性は大きく広がっていくと感じます。
https://x.com/nekoco_vrc/status/1906762562462753013

この記事を読んでほしい方

この記事は、以下のような方々に向けて書きました。

  • Houdiniユーザーの方
  • 新しい技術(特にMCP)に興味がある方
  • なんだかよく分からないけど、未来を感じたい方

「Houdini MCPを使ってこんな面白いことができた!」「こんな未来が待っているかもしれない」という実験レポートを共有できればと思います。

Houdiniとは?

Houdiniは、3DモデリングやVFX制作に使われるソフトウェアの一つです。プロシージャル(手続き的)なワークフローを特徴としており、その点ではBlenderのような他の3DCGソフトウェアと比較されることもあります。

Houdiniの大きな特徴は、モデリングの操作手順(ノード)がすべて記録され、後から編集可能な点です。例えば、最初に行った操作を修正すると、それ以降の工程も自動的に更新されます。この考え方は、プログラミングに近いかもしれません。


画面説明: 上の画像はHoudiniの操作画面の一例です。曲線をいくつか定義し、それらの間に面を張ることで花びらを作成しています。さらに、作成した花びらを回転させながら複製することで、花全体を形作っています。このように、操作を定義し、それを組み合わせて複雑な形状を作り上げていきます。

MCPとは?

MCPは「Model Context Protocol」の略称です。簡単に言えば、AIが外部のデータソースやツール(今回の場合はHoudini)と連携するための標準的な「お約束事」のことです。

AI(クライアント、例えばCursorのようなエディタ)がMCPサーバー(今回の場合はHoudini MCP)に対して、「このノードの情報を教えて」「このノードを作成して」といったリクエストを送ります。サーバーがそのリクエストに応答することで、AIがHoudiniのようなローカルアプリケーションを操作できるようになります。

MCPについてさらに詳しく知りたい方は、以下の動画が参考になるでしょう。

Houdini MCP セットアップ奮闘記

ここでは、詳細なトラブルシューティングではなく、「こんな感じでセットアップして、動かす準備ができました」という過程を共有します。

セットアップ手順は、基本的に以下のGitHubリポジトリに従いました。
https://github.com/capoomgit/houdini-mcp

しかし、いくつか躓いたポイントもあり、セットアップには試行錯誤が必要でした。

  • ファイル階層: リポジトリをクローンする場所には注意が必要です。私は最初、適切な場所にクローンできていませんでした。正しいパスは C:\Users\ユーザー名\Documents\houdini<バージョン>\scripts\python\houdinimcp\houdinimcp のようになるはずです。
  • ファイアウォール: MCPサーバーはポートを使って通信するため、環境によってはファイアウォールの設定が必要になる場合があります。私の環境では、新しく通信規則を作成しました。
  • 設定ファイル: cline_mcp_config.json の設定内容が、リポジトリの説明と少し異なっていました(私の環境だけかもしれませんが)。最終的に以下の設定で動作しました。

あとは、なんらかのアプリケーションが通信を阻害する場合があります。(VRChatなど?)サーバーが解放されているのに、コマンドが通らないということが多々ありました。PCを再起動したらちゃんと通信してくれるようになりました。

デモンストレーション:AIとの対話によるHoudini操作

実際にHoudini MCPを使って、AIに指示を出してHoudiniを操作してみましょう。

デモ映像
https://www.youtube.com/watch?v=x9Pc5I0VZfk

Houdini MCPサーバーを起動し、AIクライアント(Cursor)から接続すると、Houdini側のコンソールに以下のようなログが表示されました。

HoudiniMCP server stopped
HoudiniMCP server started on localhost:9876
Connected to client: ('127.0.0.1', 50663)
Executing handler for get_scene_info
Handler execution complete for get_scene_info

AIがシーン全体の情報を取得しようとしているようです。

次に、簡単なジオメトリを作成してもらいましょう。「ジオメトリノードを作成し、その中に球体を作成してください」と指示してみます。


指示通り、/obj 内に geometry ノードが作成され、その中に sphere ノードが作成されました!

この時のHoudini側のログは以下の通りです。

Executing handler for create_node
Handler execution complete for create_node
Executing handler for create_node
Handler execution complete for create_node

AIがHoudiniのコンソールログを読み取り、その状態に合わせて次のタスクを実行してくれるのは、まさに未来を感じさせますね!(Houdini、Cursorはそれぞれ独立したアプリケーションなので)

様々なコンテキストでの検証

先ほどは基本的なSOPの操作だけでしたので、他のコンテキスト(DOP: ダイナミクス、COP: コンポジット、LOP: ライティング)でも試してみましょう。

RBDシミュレーション (DOP)

Houdini MCPにて、ジオメトリノードを作成し、その中にBoxを作成してください。
その後、RBD Material FractureやRBD Solverを用いてそのBoxが崩壊するシミュレーションを行いたいです。
実行するべきノード作成・接続の計画を立ててから、それを実行してください。
MCPサーバーは立ち上がっています。

残念ながら、何度か試しましたが、AIは RBD Solver ノードを追加してくれませんでした。以前試した際は作成してくれたのですが、その時は地面(Ground Plane)の設定がうまくできていませんでした。残念。

木の模様 (COP)

Houdini MCPにて、/obj内にCOP Networkを作成し、その中で木の模様を作成してください。
MCPサーバーは立ち上がっています。

COP Network内に wood という名前のノードを作成してくれました。が、これは木なのでしょうか…?

ムーディーなライティング (LOP)

Houdini MCPにて、/obj内にLOP Networkを作成し、その中でBoxを良い感じにライティングしてください、ムーディーな感じで!
MCPサーバーは立ち上がっています。

非常に長いPythonスクリプトを生成して実行しようとしました。

非常に長いPythonスクリプト
def safe_set_parm(node, parm_name, value):
    """パラメータが存在するか確認してから値を設定し、エラーメッセージを出力するヘルパー関数"""
    if not node:
        print(f"Error: Node is None when trying to access parameter '{parm_name}'. Cannot proceed.")
        return False
    # ノードが存在するか再確認 (削除されていないか)
    try:
        # isRegistered() は古いAPIかもしれないので、node.path() で存在確認を試みる
        node_path = node.path()
        if hou.node(node_path) is None:
             print(f"Error: Node '{node.name()}' no longer exists (path: {node_path}) when trying to access parameter '{parm_name}'.")
             return False
    except hou.ObjectWasDeleted:
         print(f"Error: Node '{node.name()}' was deleted when trying to access parameter '{parm_name}'.")
         return False
    except Exception as e:
         print(f"Unexpected error checking node existence for '{node.name()}': {e}")
         return False

    print(f"Attempting to access parameter '{parm_name}' on node '{node.path()}'...")
    param = node.parm(parm_name)
    if param is None:
        print(f"Error: Parameter '{parm_name}' not found on node '{node.path()}'. Available parms: {[p.name() for p in node.parms()]}")
        return False
    try:
        print(f"Setting parameter '{node.path()}.{parm_name}' to {value}...")
        param.set(value)
        print(f"Successfully set '{node.path()}.{parm_name}'.")
        return True
    except hou.ObjectWasDeleted:
         print(f"Error: Object '{node.path()}' was deleted before setting parameter '{parm_name}'.")
         return False
    except hou.Error as e:
        print(f"Error setting parameter '{node.path()}.{parm_name}' to {value}: {e}")
        return False
    except Exception as e:
        print(f"Unexpected error setting parameter '{node.path()}.{parm_name}': {e}")
        return False

# --- 1. Boxジオメトリの準備 (/obj) ---
print("--- Preparing Box Geometry in /obj ---")
box_geo = None
obj_level = hou.node("/obj")
if not obj_level:
    print("Error: Failed to get node '/obj'. Cannot create box geometry.")
else:
    print("Found /obj node.")
    existing_box_geo_name = "box_geo"
    print(f"Checking for existing node: /obj/{existing_box_geo_name}")
    existing_box_geo = obj_level.node(existing_box_geo_name)
    if existing_box_geo:
        print(f"Found existing node {existing_box_geo.path()}, attempting to destroy...")
        try:
            existing_box_geo.destroy()
            print("Destroyed existing box_geo.")
        except Exception as e:
            print(f"Error destroying existing box_geo: {e}")

    print("Creating geo node 'box_geo' in /obj...")
    try:
        box_geo = obj_level.createNode("geo", "box_geo")
        if not box_geo:
            print("Error: createNode('geo', 'box_geo') returned None.")
        else:
            print(f"Created geo node: {box_geo.path()}")
            print("Creating box node 'box1' inside box_geo...")
            box_sop = box_geo.createNode("box", "box1")
            if not box_sop:
                print("Error: createNode('box', 'box1') returned None.")
            else:
                print(f"Created box node: {box_sop.path()}")
                safe_set_parm(box_sop, "ty", 0.5) # Boxを少し上に移動
    except Exception as e:
         print(f"Error creating geometry nodes: {e}")
         box_geo = None # エラー発生時は None に設定

# box_geoが正常に作成されたか確認
current_box_geo = hou.node("/obj/box_geo") # 再度取得して確認
if not current_box_geo:
     print("Fatal Error: Failed to prepare box geometry '/obj/box_geo'. Aborting LOP setup.")
     # スクリプト終了
else:
    print(f"Box geometry '{current_box_geo.path()}' seems ready.")

    # --- 2. LOP Networkの準備 ---
    print("\n--- Preparing LOP Network ---")
    lopnet_path = "/obj/moody_lighting_lop"
    print(f"Getting LOP Network node: {lopnet_path}")
    lopnet = hou.node(lopnet_path)

    if not lopnet:
        print(f"Fatal Error: LOP Network not found: {lopnet_path}. Aborting.")
    else:
        print(f"Found LOP Network: {lopnet.path()}")
        # LOP Network内の既存ノードをクリア (box_geo作成後に実行)
        print(f"Clearing existing nodes in {lopnet.path()}...")
        children_to_destroy = lopnet.children()
        if children_to_destroy:
            print(f"Found {len(children_to_destroy)} children to destroy.")
            # 削除前にリストをコピー(イテレーション中に削除するため)
            for node in list(children_to_destroy):
                print(f"Attempting to destroy {node.path()}...")
                try:
                    node.destroy()
                    print(f"Destroyed {node.name()}.")
                except Exception as e:
                    print(f"Error destroying existing node {node.path()}: {e}")
        else:
            print("No existing children found.")

        # --- 3. LOPノード作成と設定 ---
        print("\n--- Creating and Configuring LOP Nodes ---")
        try:
            # Box (SOP Create) ノードを作成
            print("Creating sopcreate node 'create_box'...")
            box = lopnet.createNode("sopcreate", "create_box")
            if not box: raise Exception("Failed to create sopcreate node 'create_box'.")
            print(f"Created sopcreate node: {box.path()}")
            # box_geoの参照を設定する前に存在確認
            box_geo_ref = hou.node("/obj/box_geo") # 再度参照を取得
            if not box_geo_ref:
                 raise Exception("'/obj/box_geo' node does not exist or is invalid when setting sopcreate path.")
            safe_set_parm(box, "soppath", box_geo_ref.path())
            safe_set_parm(box, "primpath", "/box")

            # Dome Light
            print("Creating domelight node 'moody_dome_light'...")
            dome_light = lopnet.createNode("domelight", "moody_dome_light")
            if not dome_light: raise Exception("Failed to create domelight node 'moody_dome_light'.")
            print(f"Created domelight node: {dome_light.path()}")
            safe_set_parm(dome_light, "light_intensity", 0.15)
            safe_set_parm(dome_light, "light_colorr", 0.1)
            safe_set_parm(dome_light, "light_colorg", 0.15)
            safe_set_parm(dome_light, "light_colorb", 0.3)
            safe_set_parm(dome_light, "texturefile", "")

            # Distant Light
            print("Creating distantlight node 'key_light'...")
            distant_light = lopnet.createNode("distantlight", "key_light")
            if not distant_light: raise Exception("Failed to create distantlight node 'key_light'.")
            print(f"Created distantlight node: {distant_light.path()}")
            safe_set_parm(distant_light, "light_intensity", 8)
            safe_set_parm(distant_light, "light_colorr", 1.0)
            safe_set_parm(distant_light, "light_colorg", 0.6)
            safe_set_parm(distant_light, "light_colorb", 0.2)
            safe_set_parm(distant_light, "ry", -55)
            safe_set_parm(distant_light, "rx", -35)
            safe_set_parm(distant_light, "angle", 5)

            # Camera
            camera_prim_path = "/cameras/render_cam"
            print("Creating camera node 'render_cam_node'...")
            camera = lopnet.createNode("camera", "render_cam_node")
            if not camera: raise Exception("Failed to create camera node 'render_cam_node'.")
            print(f"Created camera node: {camera.path()}")
            safe_set_parm(camera, "primpath", camera_prim_path)
            safe_set_parm(camera, "tz", 8)
            safe_set_parm(camera, "rx", -15)

            # Karma Render Settings
            print("Creating karmarendersettings node 'karma_settings'...")
            karma_settings = lopnet.createNode("karmarendersettings", "karma_settings")
            if not karma_settings: raise Exception("Failed to create karmarendersettings node 'karma_settings'.")
            print(f"Created karmarendersettings node: {karma_settings.path()}")

            # USD Render ROP
            print("Creating usdrender_rop node 'render_usd'...")
            usd_render = lopnet.createNode("usdrender_rop", "render_usd")
            if not usd_render: raise Exception("Failed to create usdrender_rop node 'render_usd'.")
            print(f"Created usdrender_rop node: {usd_render.path()}")
            safe_set_parm(usd_render, "lopoutput", "$HIP/render/moody_box.usd")
            safe_set_parm(usd_render, "renderer", "karma")
            safe_set_parm(usd_render, "camera", camera_prim_path)

            # --- 4. ノード接続 ---
            print("\n--- Connecting LOP Nodes ---")
            # 接続前に各ノードの存在を再確認
            nodes_to_connect = [box, dome_light, distant_light, camera, karma_settings, usd_render]
            all_nodes_valid = True
            for n in nodes_to_connect:
                if not n or hou.node(n.path()) is None: # hou.node()で再確認
                    print(f"Error: Node {n.name() if n else 'Unknown'} is invalid before connection.")
                    all_nodes_valid = False
                    break

            if all_nodes_valid:
                print(f"Connecting {dome_light.name()} -> {box.name()}")
                dome_light.setInput(0, box)
                print(f"Connecting {distant_light.name()} -> {dome_light.name()}")
                distant_light.setInput(0, dome_light)
                print(f"Connecting {camera.name()} -> {distant_light.name()}")
                camera.setInput(0, distant_light)
                print(f"Connecting {karma_settings.name()} -> {camera.name()}")
                karma_settings.setInput(0, camera)
                print(f"Connecting {usd_render.name()} -> {karma_settings.name()}")
                usd_render.setInput(0, karma_settings)
                print("Connections successful.")
            else:
                 print("Skipping connections due to invalid nodes.")


            # --- 5. レイアウトとフラグ設定 ---
            print("\n--- Finalizing Setup ---")
            print("Attempting to layout children...")
            lopnet.layoutChildren()
            print("Layout successful.")

            print("Attempting to set display/render flags...")
            # usd_renderの存在を再確認
            final_usd_render = hou.node(usd_render.path())
            if final_usd_render:
                final_usd_render.setDisplayFlag(True)
                final_usd_render.setRenderFlag(True)
                print("Flags set successfully.")
            else:
                print("Error: usd_render node became invalid before setting flags.")


            print(f"\nSuccessfully attempted to set up LOP Network '{lopnet_path}' with moody lighting for the box. Please check Houdini.")

        except hou.ObjectWasDeleted as e:
             print(f"\nError during LOP setup: Object was deleted unexpectedly. {e}")
        except Exception as e:
             print(f"\nError during LOP setup: {e}")

しかし、実行中にエラーが発生し、期待通りには動作しませんでした。

考察:現状のAI連携の得意なこと・苦手なこと

検証から、AIにHoudini操作を任せる場合、完全に新規から複雑なネットワークを構築させるよりも、既存の情報を分析したり、定型的なタスクを実行させたりする方が得意なのかもしれません。Houdiniはバージョンアップで仕様が変わることも多く、ノードの接続やパラメータ設定の正確性が求められるため、AIにとってはまだ難しい部分もあるようです。

MCPの可能性:AIモデルの進化とアプリケーション連携

AIモデルによる性能の違い

MCPはあくまでAIと外部ツールを「繋ぐ」ための仕組みです。そのため、裏側で動作するAIモデル(Gemini, GPT, Claudeなど)が賢くなればなるほど、同じHoudini MCPでもできることが増えていきます

例として、比較的軽量なモデル(Gemini-2.0-flash-001)と、より高性能なモデル(Gemini-2.5-pro-exp-03-25)で、同じ指示を出した際の違いを見てみましょう。今回は「猫をモデリングしてください」とお願いしました。

デモ映像
https://www.youtube.com/watch?v=utwFmottsCM

Houdini MCPを用いて、ジオメトリノードを作成し、その中で猫をモデリングしてください。
MCPサーバーは立ち上がっています。

Gemini-2.0-flash-001の結果

Gemini-2.5-pro-exp-03-25の結果


高性能モデルでは、足、しっぽ、耳が追加され、より猫らしい形状になりました!(?)

プロトコルは同じでも、AIモデルの性能が結果を大きく左右することが分かります。さらに高性能なモデル(例えばo-3、Claudeなど)を使えば、また違った結果になるかもしれませんね。
(お金が無いので契約してません)
https://www.youtube.com/watch?v=k2my10BRlIg&t=1s

MCP連携の真価:アプリケーションの壁を超える魔法

これこそが、私が最も未来を感じた点です! MCPは標準化されたプロトコルなので、異なるMCP対応ツール同士を連携させることができます

Houdini MCP × Obsidian MCP の連携例:
今回は、Houdiniで作成したノードネットワークの情報をAIに渡し、その内容を分析してObsidian MCP経由で解説記事を自動生成させる、という実験を行いました。

まず、Houdiniで作成したモデルデータ(今回は花)を開きます。

次に、AI(Cline)に「/obj/geo1 に存在するノードの一覧(名前、接続先、主要パラメータ)をファイルに出力して」と指示します。

ノードリスト

Node Name: curve2
Type: curve::2.0
Inputs:
Outputs: merge1
Description:
Parameters:
group:
outputtype: 0
order: 4
convertcurves: 0
mode: 0
interpmethod: 0
enablebezierops: 0
operations:
delete: 0
fuse: 0
cut: 0
join: 0
deleteseg: 0
makecorner: 0
makesmooth: 0
makebalanced: 0
contract: 0
expand: 0
straightenseg: 0
close: 0
createroundedcorners: 0
removeroundedcorners: 0
makeauto: 0
makemanual: 0
reverse: 0
reset: 0
snaponclose: 1
maintainpoint: 0
approxendtangents: 0
caching: 0
stashgeo: None
savedstashgeo: <hou.Geometry frozen at 000000013EB6A400 read-only>
parmpoints: <hou.Geometry frozen at 000000013EB69600 read-only>
stashid: ;
ninputprimscached: 0
softtransform: 0
softtransformrad: 0.6050000000000001
output: 0
outputcornerpts: 0
cornerptsgroup: corner_points
outputsmoothpts: 0
smoothptsgroup: smooth_points
outputautopts: 0
autoptsgroup: auto_points
outputname: 0
name: curve2
nameattrib: name
outputxaxis: 0
xaxisname: out
outputyaxis: 0
yaxisname: up
outputzaxis: 0
zaxisname: tangent
outputorient: 0
orientname: orient
tangenttype: 0
aligntangent: 1
targetorients: 0
curoperation: 0
optype: 16
activepoints: 2
translatex: 0.0
translatey: 0.0
translatez: 0.0
rotatex: 0.0
rotatey: 0.0
rotatez: 0.0
scalex: 1.0
scaley: 1.0
scalez: 1.0
addpts:
activeprim: 0
cornerpts:
smoothpts: *
autopts:
pivottransformfolder: 0
pivottranslatex: 0.0
pivottranslatey: 3.510807752609253
pivottranslatez: -1.2363677024841309
pivotrotatex: 0.0
pivotrotatey: 0.0
pivotrotatez: 0.0
pivotfixed: 0
roundedcornersfolder: 0
viewroundcorners: 1
roundcornerpts:
roundcornerradius: 0.0
bakeroundcorners: 0
showroundcornerwidget: 1
showroundcornerlabels: 1
editedgeops: 0
planeorigx: 0.0
planeorigy: 0.0
planeorigz: 0.0
planenmlx: 0.0
planenmly: 1.0
planenmlz: 0.0
constrainstraighten: 0
handleparmsfolder: 0
handleptsx: -1
handleptsy: -1
handleptsz: -1
handlep0posx: -1.0
handlep0posy: 0.0
handlep0posz: 0.0
handlep1posx: 0.0
handlep1posy: 0.0
handlep1posz: 0.0
handlep2posx: 1.0
handlep2posy: 0.0
handlep2posz: 0.0

Node Name: mirror1
Type: mirror
Inputs: curve3
Outputs: merge1
Description:
Parameters:
group:
operation: 0
dirtype: 0
tx: 0.0
ty: 0.0
tz: 0.0
rx: 0.0
ry: 0.0
rz: 0.0
originx: 0.0
originy: 0.0
originz: 0.0
dirx: 1.0
diry: 0.0
dirz: 0.0
dist: 0.0
reversenml: 1
keepOriginal: 0
consolidatepts: 1
consolidatetol: 0.0001
consolidateunshared: 1
createoutputgroup: 0
outputgroup: mirror

Node Name: polypatch1
Type: polypatch
Inputs: merge1
Outputs: foreach_begin1
Description:
Parameters:
group:
basis: 0
connecttype: 4
closeu: 2
closev: 2
firstuclamp: 2
lastuclamp: 2
firstvclamp: 2
lastvclamp: 2
divisionsx: 4
divisionsy: 4
polys: 0

Node Name: merge1
Type: merge
Inputs: mirror1, curve2, curve3
Outputs: polypatch1
Description:
Parameters:

Node Name: foreach_end1
Type: block_end
Inputs: transform1
Outputs: merge2, transform2
Description:
Parameters:
itermethod: 2
method: 1
iterations: 3
startvalue: 1.0
increment: 1.0
class: 1
useattrib: 1
attrib:
usemaxiter: 0
maxiter: 10
blockpath: ../foreach_begin1
templatepath: ../foreach_begin1
resetcookpass: 0
dosinglepass: 0
singlepass: 0
stopcondition: 0
multithread: 0

Node Name: foreach_begin1
Type: block_begin
Inputs: polypatch1
Outputs: transform1
Description:
Parameters:
method: 3
blockpath: ../foreach_end1
resetcookpass: 0
createmetablock: 0
label1: iteration, numiterations, value, ivalue

Node Name: foreach_count1
Type: block_begin
Inputs:
Outputs:
Description:
Parameters:
method: 2
blockpath: ../foreach_end1
resetcookpass: 0
createmetablock: 0
label1: iteration, numiterations, value, ivalue

Node Name: transform1
Type: xform
Inputs: foreach_begin1
Outputs: foreach_end1
Description:
Parameters:
group:
grouptype: 0
xOrd: 0
rOrd: 0
tx: 0.0
ty: 0.0
tz: 0.0
rx: 0.0
ry: 360.0
rz: 0.0
sx: 1.0
sy: 1.0
sz: 1.0
shear1: 0.0
shear2: 0.0
shear3: 0.0
scale: 1.0
parmgroup_pivotxform: 0
px: 0.0
py: 0.0
pz: 0.0
prx: 0.0
pry: 0.0
prz: 0.0
parmgroup_prexform: 0
prexform_xOrd: 0
prexform_rOrd: 0
prexform_tx: 0.0
prexform_ty: 0.0
prexform_tz: 0.0
prexform_rx: 0.0
prexform_ry: 0.0
prexform_rz: 0.0
prexform_sx: 1.0
prexform_sy: 1.0
prexform_sz: 1.0
prexform_shear1: 0.0
prexform_shear2: 0.0
prexform_shear3: 0.0
movecentroid: 0
movepivot: 0
attribs: *
updatenmls: 0
updateaffectednmls: 1
vlength: 1
invertxform: 0
addattrib: 0
outputattrib: xform
outputmerge: 2

Node Name: transform2
Type: xform
Inputs: foreach_end1
Outputs: merge2
Description:
Parameters:
group:
grouptype: 0
xOrd: 0
rOrd: 0
tx: 0.0
ty: -0.1
tz: 0.0
rx: 0.0
ry: 60.0
rz: 0.0
sx: 1.0
sy: 1.0
sz: 1.0
shear1: 0.0
shear2: 0.0
shear3: 0.0
scale: 1.0
parmgroup_pivotxform: 0
px: 0.0
py: 0.0
pz: 0.0
prx: 0.0
pry: 0.0
prz: 0.0
parmgroup_prexform: 0
prexform_xOrd: 0
prexform_rOrd: 0
prexform_tx: 0.0
prexform_ty: 0.0
prexform_tz: 0.0
prexform_rx: 0.0
prexform_ry: 0.0
prexform_rz: 0.0
prexform_sx: 1.0
prexform_sy: 1.0
prexform_sz: 1.0
prexform_shear1: 0.0
prexform_shear2: 0.0
prexform_shear3: 0.0
movecentroid: 0
movepivot: 0
attribs: *
updatenmls: 0
updateaffectednmls: 1
vlength: 1
invertxform: 0
addattrib: 0
outputattrib: xform
outputmerge: 2

Node Name: merge2
Type: merge
Inputs: transform2, foreach_end1
Outputs: merge4
Description:
Parameters:

Node Name: curve3
Type: curve::2.0
Inputs:
Outputs: merge1, mirror1
Description:
Parameters:
group:
outputtype: 0
order: 4
convertcurves: 0
mode: 0
interpmethod: 0
enablebezierops: 0
operations:
delete: 0
fuse: 0
cut: 0
join: 0
deleteseg: 0
makecorner: 0
makesmooth: 0
makebalanced: 0
contract: 0
expand: 0
straightenseg: 0
close: 0
createroundedcorners: 0
removeroundedcorners: 0
makeauto: 0
makemanual: 0
reverse: 0
reset: 0
snaponclose: 1
maintainpoint: 0
approxendtangents: 0
caching: 0
stashgeo: None
savedstashgeo: <hou.Geometry frozen at 000000013EB68800 read-only>
parmpoints: <hou.Geometry frozen at 000000013EB68100 read-only>
stashid: ;
ninputprimscached: 0
softtransform: 0
softtransformrad: 0.6655000000000002
output: 0
outputcornerpts: 0
cornerptsgroup: corner_points
outputsmoothpts: 0
smoothptsgroup: smooth_points
outputautopts: 0
autoptsgroup: auto_points
outputname: 0
name: curve3
nameattrib: name
outputxaxis: 0
xaxisname: out
outputyaxis: 0
yaxisname: up
outputzaxis: 0
zaxisname: tangent
outputorient: 0
orientname: orient
tangenttype: 0
aligntangent: 1
targetorients: 0
curoperation: 0
optype: 16
activepoints:
translatex: 0.0
translatey: 0.0
translatez: 0.0
rotatex: 0.0
rotatey: 0.0
rotatez: 0.0
scalex: 1.0
scaley: 1.0
scalez: 1.0
addpts:
activeprim: 0
cornerpts:
smoothpts: *
autopts:
pivottransformfolder: 0
pivottranslatex: 0.0
pivottranslatey: 0.0
pivottranslatez: 0.0
pivotrotatex: 0.0
pivotrotatey: 0.0
pivotrotatez: 0.0
pivotfixed: 0
roundedcornersfolder: 0
viewroundcorners: 1
roundcornerpts:
roundcornerradius: 0.0
bakeroundcorners: 0
showroundcornerwidget: 1
showroundcornerlabels: 1
editedgeops: 0
planeorigx: 0.0
planeorigy: 0.0
planeorigz: 0.0
planenmlx: 0.0
planenmly: 1.0
planenmlz: 0.0
constrainstraighten: 0
handleparmsfolder: 0
handleptsx: -1
handleptsy: -1
handleptsz: -1
handlep0posx: -1.0
handlep0posy: 0.0
handlep0posz: 0.0
handlep1posx: 0.0
handlep1posy: 0.0
handlep1posz: 0.0
handlep2posx: 1.0
handlep2posy: 0.0
handlep2posz: 0.0

Node Name: curve1
Type: curve::2.0
Inputs:
Outputs: merge5, resample2
Description:
Parameters:
group:
outputtype: 0
order: 4
convertcurves: 0
mode: 0
interpmethod: 0
enablebezierops: 0
operations:
delete: 0
fuse: 0
cut: 0
join: 0
deleteseg: 0
makecorner: 0
makesmooth: 0
makebalanced: 0
contract: 0
expand: 0
straightenseg: 0
close: 0
createroundedcorners: 0
removeroundedcorners: 0
makeauto: 0
makemanual: 0
reverse: 0
reset: 0
snaponclose: 1
maintainpoint: 0
approxendtangents: 0
caching: 0
stashgeo: None
savedstashgeo: <hou.Geometry frozen at 000000013EAF1600 read-only>
parmpoints: <hou.Geometry frozen at 000000013EAF0F00 read-only>
stashid: ;
ninputprimscached: 0
softtransform: 0
softtransformrad: 0.5
output: 0
outputcornerpts: 0
cornerptsgroup: corner_points
outputsmoothpts: 0
smoothptsgroup: smooth_points
outputautopts: 0
autoptsgroup: auto_points
outputname: 0
name: curve1
nameattrib: name
outputxaxis: 0
xaxisname: out
outputyaxis: 0
yaxisname: up
outputzaxis: 0
zaxisname: tangent
outputorient: 0
orientname: orient
tangenttype: 0
aligntangent: 1
targetorients: 0
curoperation: 0
optype: 16
activepoints: 3
translatex: 0.0
translatey: 0.0
translatez: 0.0
rotatex: 0.0
rotatey: 0.0
rotatez: 0.0
scalex: 1.0
scaley: 1.0
scalez: 1.0
addpts:
activeprim: 0
cornerpts:
smoothpts: *
autopts:
pivottransformfolder: 0
pivottranslatex: 0.0
pivottranslatey: 3.9740099906921387
pivottranslatez: -0.46573805809020996
pivotrotatex: 0.0
pivotrotatey: 0.0
pivotrotatez: 0.0
pivotfixed: 0
roundedcornersfolder: 0
viewroundcorners: 1
roundcornerpts:
roundcornerradius: 0.0
bakeroundcorners: 0
showroundcornerwidget: 1
showroundcornerlabels: 1
editedgeops: 0
planeorigx: 0.0
planeorigy: 0.0
planeorigz: 0.0
planenmlx: 0.0
planenmly: 1.0
planenmlz: 0.0
constrainstraighten: 0
handleparmsfolder: 0
handleptsx: -1
handleptsy: -1
handleptsz: -1
handlep0posx: -1.0
handlep0posy: 0.0
handlep0posz: 0.0
handlep1posx: 0.0
handlep1posy: 0.0
handlep1posz: 0.0
handlep2posx: 1.0
handlep2posy: 0.0
handlep2posz: 0.0

Node Name: circle1
Type: circle
Inputs:
Outputs: sweep2
Description:
Parameters:
type: 1
orient: 0
reverse: 1
radx: 0.05
rady: 0.05
tx: 0.0
ty: 0.0
tz: 0.0
rx: 0.0
ry: 0.0
rz: 0.0
scale: 1.0
order: 4
divs: 12
arc: 0
beginangle: 0.0
endangle: 360.0
imperfect: 1

Node Name: merge3
Type: merge
Inputs: copytopoints1, copytopoints2, sweep2, copytopoints3, copytopoints4, sweep4
Outputs: merge4
Description:
Parameters:

Node Name: sphere1
Type: sphere
Inputs:
Outputs: copytopoints3, copytopoints2, copytopoints1
Description:
Parameters:
type: 2
surftype: 4
radx: 0.1
rady: 0.2
radz: 0.1
tx: 0.0
ty: 0.0
tz: 0.0
rx: 0.0
ry: 0.0
rz: 0.0
scale: 1.0
orient: 1
freq: 2
rows: 13
cols: 24
orderu: 4
orderv: 4
imperfect: 1
upole: 0
accurate: 1
triangularpoles: 1

Node Name: copytopoints1
Type: copytopoints::2.0
Inputs: sphere1, resample2
Outputs: merge3
Description:
Parameters:
sourcegroup:
sourcegrouptype: 0
targetgroup:
useidattrib: 0
idattrib: name
pack: 0
pivot: 1
viewportlod: 0
transform: 1
useimplicitn: 1
resettargetattribs: 0
targetattribs: 3
useapply1: 1
applyto1: 0
applymethod1: 0
applyattribs1: *,^v,^Alpha,^N,^up,^pscale,^scale,^orient,^rot,^pivot,^trans,^transform
useapply2: 1
applyto2: 0
applymethod2: 2
applyattribs2: Alpha
useapply3: 1
applyto3: 0
applymethod3: 3
applyattribs3: v

Node Name: resample2
Type: resample
Inputs: curve1
Outputs: copytopoints1
Description:
Parameters:
group:
maintainprimorder: 0
lod: 1.0
edge: 0
method: 0
measure: 0
dolength: 0
length: 0.0
dosegs: 1
segs: 1
useattribs: 1
allequal: 1
last: 0
randomshift: 0
onlypoints: 0
treatpolysas: 0
outputsubdpoly: 0
doptdistattr: 0
ptdistattr: ptdist
dotangentattr: 0
tangentattr: tangentu
docurveuattr: 0
curveuattr: curveu
docurvenumattr: 0
curvenumattr: curvenum

Node Name: merge4
Type: merge
Inputs: merge2, merge3, merge6
Outputs: transform3
Description:
Parameters:

Node Name: curve4
Type: curve::2.0
Inputs:
Outputs: merge5, resample4
Description:
Parameters:
group:
outputtype: 0
order: 4
convertcurves: 0
mode: 0
interpmethod: 0
enablebezierops: 0
operations:
delete: 0
fuse: 0
cut: 0
join: 0
deleteseg: 0
makecorner: 0
makesmooth: 0
makebalanced: 0
contract: 0
expand: 0
straightenseg: 0
close: 0
createroundedcorners: 0
removeroundedcorners: 0
makeauto: 0
makemanual: 0
reverse: 0
reset: 0
snaponclose: 1
maintainpoint: 0
approxendtangents: 0
caching: 0
stashgeo: None
savedstashgeo: <hou.Geometry frozen at 000000013EABA400 read-only>
parmpoints: <hou.Geometry frozen at 000000013EAB9D00 read-only>
stashid: ;
ninputprimscached: 0
softtransform: 0
softtransformrad: 0.3756574004507888
output: 0
outputcornerpts: 0
cornerptsgroup: corner_points
outputsmoothpts: 0
smoothptsgroup: smooth_points
outputautopts: 0
autoptsgroup: auto_points
outputname: 0
name: curve4
nameattrib: name
outputxaxis: 0
xaxisname: out
outputyaxis: 0
yaxisname: up
outputzaxis: 0
zaxisname: tangent
outputorient: 0
orientname: orient
tangenttype: 0
aligntangent: 1
targetorients: 0
curoperation: 0
optype: 16
activepoints: 2
translatex: 0.0
translatey: 0.0
translatez: 0.0
rotatex: 0.0
rotatey: 0.0
rotatez: 0.0
scalex: 1.0
scaley: 1.0
scalez: 1.0
addpts:
activeprim: 0
cornerpts:
smoothpts: *
autopts:
pivottransformfolder: 0
pivottranslatex: -0.43802595138549805
pivottranslatey: 2.846801280975342
pivottranslatez: -0.2645728588104248
pivotrotatex: 0.0
pivotrotatey: 0.0
pivotrotatez: 0.0
pivotfixed: 0
roundedcornersfolder: 0
viewroundcorners: 1
roundcornerpts:
roundcornerradius: 0.0
bakeroundcorners: 0
showroundcornerwidget: 1
showroundcornerlabels: 1
editedgeops: 0
planeorigx: 0.0
planeorigy: 0.0
planeorigz: 0.0
planenmlx: 0.0
planenmly: 1.0
planenmlz: 0.0
constrainstraighten: 0
handleparmsfolder: 0
handleptsx: -1
handleptsy: -1
handleptsz: -1
handlep0posx: -1.0
handlep0posy: 0.0
handlep0posz: 0.0
handlep1posx: 0.0
handlep1posy: 0.0
handlep1posz: 0.0
handlep2posx: 1.0
handlep2posy: 0.0
handlep2posz: 0.0

Node Name: resample3
Type: resample
Inputs: merge5
Outputs: sweep2
Description:
Parameters:
group:
maintainprimorder: 0
lod: 1.0
edge: 0
method: 0
measure: 0
dolength: 0
length: 0.1
dosegs: 1
segs: 50
useattribs: 1
allequal: 1
last: 0
randomshift: 0
onlypoints: 0
treatpolysas: 0
outputsubdpoly: 0
doptdistattr: 0
ptdistattr: ptdist
dotangentattr: 0
tangentattr: tangentu
docurveuattr: 0
curveuattr: curveu
docurvenumattr: 0
curvenumattr: curvenum

Node Name: sweep2
Type: sweep::2.0
Inputs: resample3, circle1
Outputs: merge3
Description:
Parameters:
curvegroup:
crosssectiongroup:
surface_folder1: 0
surfaceshape: 0
surfacetype: 5
scale: 1.0
cols: 8
radius: 0.1
width: 0.2
reversecrosssections: 0
stretcharoundturns: 1
maxstretcharoundturns: 10.0
endcaps_folder: 0
endcaptype: 0
capdivs: 3
triangularpoles: 0
capscale: 1.0
caproundness: 1.0
addendcapsgroup: 0
endcapsgroup: endcaps
scale_folder: 0
applyscale: 0
scaleramp: <hou.Ramp is_color=False num_keys=2 data=((t=0, 1), (t=1, 1))>
rotation_folder: 0
rOrd: 0
applyroll: 1
roll: 0.0
fulltwists: 0
incroll: 0.0
rollper: 4
rollattrib: roll
applyyaw: 0
yaw: 0.0
incyaw: 0.0
yawper: 4
yawattrib: yaw
applypitch: 0
pitch: 0.0
incpitch: 0.0
pitchper: 4
pitchattrib: pitch
cross_sections_folder: 0
copyorder: 1
crosssectionattrib: variant
primtype: 0
unrollclosedrowcol: 0
swaprowcol: 0
closeifnocurveinput: 0
up_folder: 0
upvectortype: 0
upvectoratstart: 1
useendupvector: 0
upvectorattrib: start_up
endupvectorattrib: end_up
upvectorx: 0.0
upvectory: 1.0
upvectorz: 0.0
endupvectorx: 0.0
endupvectory: 1.0
endupvectorz: 0.0
tangents_folder: 0
tangenttype: 0
continuousclosed: 1
extrapolateendtangents: 0
transformbyattribs: 1
uv_folder: 0
computeuvs: 0
overrideexistinguvs: 0
lengthweighteduvs: 1
normalizeu: 1
normalizev: 0
flipu: 1
uvscale_folder: 0
uvscale1: 1.0
uvscale2: 1.0
usemeshedgelengths: 1
propscalepercurve: 1
uvseams_folder: 0
wrapu: 1
wrapv: 1
attributes_folder: 0
input_folder: 0
attribsfrombackbone: * ^P ^N ^up ^pscale ^scale ^orient ^rot ^pivot ^trans ^transform
attribsfromcrosssection: *
output_folder: 0
addptrow: 0
ptrowattrib: ptrow
addptcol: 0
ptcolattrib: ptcol
addprimrow: 0
primrowattrib: primrow
addprimcol: 0
primcolattrib: primcol
addcrosssectionnum: 0
crosssectionnumattrib: crossnum
addcurvenum: 0
curvenumattrib: curvenum
scaleramp1pos: 0.0
scaleramp1value: 1.0
scaleramp1interp: 1
scaleramp2pos: 1.0
scaleramp2value: 1.0
scaleramp2interp: 1

Node Name: copytopoints2
Type: copytopoints::2.0
Inputs: sphere1, resample4
Outputs: merge3
Description:
Parameters:
sourcegroup:
sourcegrouptype: 0
targetgroup:
useidattrib: 0
idattrib: name
pack: 0
pivot: 1
viewportlod: 0
transform: 1
useimplicitn: 1
resettargetattribs: 0
targetattribs: 3
useapply1: 1
applyto1: 0
applymethod1: 0
applyattribs1: *,^v,^Alpha,^N,^up,^pscale,^scale,^orient,^rot,^pivot,^trans,^transform
useapply2: 1
applyto2: 0
applymethod2: 2
applyattribs2: Alpha
useapply3: 1
applyto3: 0
applymethod3: 3
applyattribs3: v

Node Name: resample4
Type: resample
Inputs: curve4
Outputs: copytopoints2
Description:
Parameters:
group:
maintainprimorder: 0
lod: 1.0
edge: 0
method: 0
measure: 0
dolength: 0
length: 0.0
dosegs: 1
segs: 1
useattribs: 1
allequal: 1
last: 0
randomshift: 0
onlypoints: 0
treatpolysas: 0
outputsubdpoly: 0
doptdistattr: 0
ptdistattr: ptdist
dotangentattr: 0
tangentattr: tangentu
docurveuattr: 0
curveuattr: curveu
docurvenumattr: 0
curvenumattr: curvenum

Node Name: curve5
Type: curve::2.0
Inputs:
Outputs: merge5, resample6
Description:
Parameters:
group:
outputtype: 0
order: 4
convertcurves: 0
mode: 0
interpmethod: 0
enablebezierops: 0
operations:
delete: 0
fuse: 0
cut: 0
join: 0
deleteseg: 0
makecorner: 0
makesmooth: 0
makebalanced: 0
contract: 0
expand: 0
straightenseg: 0
close: 0
createroundedcorners: 0
removeroundedcorners: 0
makeauto: 0
makemanual: 0
reverse: 0
reset: 0
snaponclose: 1
maintainpoint: 0
approxendtangents: 0
caching: 0
stashgeo: None
savedstashgeo: <hou.Geometry frozen at 000000013EAB8100 read-only>
parmpoints: <hou.Geometry frozen at 000000013EA83900 read-only>
stashid: ;
ninputprimscached: 0
softtransform: 0
softtransformrad: 0.5
output: 0
outputcornerpts: 0
cornerptsgroup: corner_points
outputsmoothpts: 0
smoothptsgroup: smooth_points
outputautopts: 0
autoptsgroup: auto_points
outputname: 0
name: curve5
nameattrib: name
outputxaxis: 0
xaxisname: out
outputyaxis: 0
yaxisname: up
outputzaxis: 0
zaxisname: tangent
outputorient: 0
orientname: orient
tangenttype: 0
aligntangent: 1
targetorients: 0
curoperation: 0
optype: 16
activepoints: 2
translatex: 0.0
translatey: 0.0
translatez: 0.0
rotatex: 0.0
rotatey: 0.0
rotatez: 0.0
scalex: 1.0
scaley: 1.0
scalez: 1.0
addpts:
activeprim: 0
cornerpts:
smoothpts: *
autopts:
pivottransformfolder: 0
pivottranslatex: 0.07418704032897949
pivottranslatey: 2.847342014312744
pivottranslatez: 0.403922438621521
pivotrotatex: 0.0
pivotrotatey: 0.0
pivotrotatez: 0.0
pivotfixed: 0
roundedcornersfolder: 0
viewroundcorners: 1
roundcornerpts:
roundcornerradius: 0.0
bakeroundcorners: 0
showroundcornerwidget: 1
showroundcornerlabels: 1
editedgeops: 0
planeorigx: 0.0
planeorigy: 0.0
planeorigz: 0.0
planenmlx: 0.0
planenmly: 1.0
planenmlz: 0.0
constrainstraighten: 0
handleparmsfolder: 0
handleptsx: -1
handleptsy: -1
handleptsz: -1
handlep0posx: -1.0
handlep0posy: 0.0
handlep0posz: 0.0
handlep1posx: 0.0
handlep1posy: 0.0
handlep1posz: 0.0
handlep2posx: 1.0
handlep2posy: 0.0
handlep2posz: 0.0

Node Name: copytopoints3
Type: copytopoints::2.0
Inputs: sphere1, resample6
Outputs: merge3
Description:
Parameters:
sourcegroup:
sourcegrouptype: 0
targetgroup:
useidattrib: 0
idattrib: name
pack: 0
pivot: 1
viewportlod: 0
transform: 1
useimplicitn: 1
resettargetattribs: 0
targetattribs: 3
useapply1: 1
applyto1: 0
applymethod1: 0
applyattribs1: *,^v,^Alpha,^N,^up,^pscale,^scale,^orient,^rot,^pivot,^trans,^transform
useapply2: 1
applyto2: 0
applymethod2: 2
applyattribs2: Alpha
useapply3: 1
applyto3: 0
applymethod3: 3
applyattribs3: v

Node Name: resample6
Type: resample
Inputs: curve5
Outputs: copytopoints3
Description:
Parameters:
group:
maintainprimorder: 0
lod: 1.0
edge: 0
method: 0
measure: 0
dolength: 0
length: 0.0
dosegs: 1
segs: 1
useattribs: 1
allequal: 1
last: 0
randomshift: 0
onlypoints: 0
treatpolysas: 0
outputsubdpoly: 0
doptdistattr: 0
ptdistattr: ptdist
dotangentattr: 0
tangentattr: tangentu
docurveuattr: 0
curveuattr: curveu
docurvenumattr: 0
curvenumattr: curvenum

Node Name: curve6
Type: curve::2.0
Inputs:
Outputs: resample8, resample7
Description:
Parameters:
group:
outputtype: 0
order: 4
convertcurves: 0
mode: 0
interpmethod: 0
enablebezierops: 0
operations:
delete: 0
fuse: 0
cut: 0
join: 0
deleteseg: 0
makecorner: 0
makesmooth: 0
makebalanced: 0
contract: 0
expand: 0
straightenseg: 0
close: 0
createroundedcorners: 0
removeroundedcorners: 0
makeauto: 0
makemanual: 0
reverse: 0
reset: 0
snaponclose: 1
maintainpoint: 0
approxendtangents: 0
caching: 0
stashgeo: None
savedstashgeo: <hou.Geometry frozen at 000000013EA82400 read-only>
parmpoints: <hou.Geometry frozen at 000000013EA81D00 read-only>
stashid: ;
ninputprimscached: 0
softtransform: 0
softtransformrad: 1.8987491679162074
output: 0
outputcornerpts: 0
cornerptsgroup: corner_points
outputsmoothpts: 0
smoothptsgroup: smooth_points
outputautopts: 0
autoptsgroup: auto_points
outputname: 0
name: curve6
nameattrib: name
outputxaxis: 0
xaxisname: out
outputyaxis: 0
yaxisname: up
outputzaxis: 0
zaxisname: tangent
outputorient: 0
orientname: orient
tangenttype: 0
aligntangent: 1
targetorients: 0
curoperation: 0
optype: 16
activepoints: 3
translatex: 0.0
translatey: 0.0
translatez: 0.0
rotatex: 0.0
rotatey: 0.0
rotatez: 0.0
scalex: 1.0
scaley: 1.0
scalez: 1.0
addpts:
activeprim: 0
cornerpts:
smoothpts: *
autopts:
pivottransformfolder: 0
pivottranslatex: -0.23166894912719727
pivottranslatey: 4.148062229156494
pivottranslatez: -0.05380892753601074
pivotrotatex: 0.0
pivotrotatey: 0.0
pivotrotatez: 0.0
pivotfixed: 0
roundedcornersfolder: 0
viewroundcorners: 1
roundcornerpts:
roundcornerradius: 0.0
bakeroundcorners: 0
showroundcornerwidget: 1
showroundcornerlabels: 1
editedgeops: 0
planeorigx: 0.0
planeorigy: 0.0
planeorigz: 0.0
planenmlx: 0.0
planenmly: 1.0
planenmlz: 0.0
constrainstraighten: 0
handleparmsfolder: 0
handleptsx: -1
handleptsy: -1
handleptsz: -1
handlep0posx: -1.0
handlep0posy: 0.0
handlep0posz: 0.0
handlep1posx: 0.0
handlep1posy: 0.0
handlep1posz: 0.0
handlep2posx: 1.0
handlep2posy: 0.0
handlep2posz: 0.0

Node Name: resample7
Type: resample
Inputs: curve6
Outputs: sweep4
Description:
Parameters:
group:
maintainprimorder: 0
lod: 1.0
edge: 0
method: 0
measure: 0
dolength: 0
length: 0.1
dosegs: 1
segs: 50
useattribs: 1
allequal: 1
last: 0
randomshift: 0
onlypoints: 0
treatpolysas: 0
outputsubdpoly: 0
doptdistattr: 0
ptdistattr: ptdist
dotangentattr: 0
tangentattr: tangentu
docurveuattr: 0
curveuattr: curveu
docurvenumattr: 0
curvenumattr: curvenum

Node Name: sweep4
Type: sweep::2.0
Inputs: resample7, circle2
Outputs: merge3
Description:
Parameters:
curvegroup:
crosssectiongroup:
surface_folder1: 0
surfaceshape: 0
surfacetype: 5
scale: 1.0
cols: 8
radius: 0.1
width: 0.2
reversecrosssections: 0
stretcharoundturns: 1
maxstretcharoundturns: 10.0
endcaps_folder: 0
endcaptype: 0
capdivs: 3
triangularpoles: 0
capscale: 1.0
caproundness: 1.0
addendcapsgroup: 0
endcapsgroup: endcaps
scale_folder: 0
applyscale: 0
scaleramp: <hou.Ramp is_color=False num_keys=2 data=((t=0, 1), (t=1, 1))>
rotation_folder: 0
rOrd: 0
applyroll: 1
roll: 0.0
fulltwists: 0
incroll: 0.0
rollper: 4
rollattrib: roll
applyyaw: 0
yaw: 0.0
incyaw: 0.0
yawper: 4
yawattrib: yaw
applypitch: 0
pitch: 0.0
incpitch: 0.0
pitchper: 4
pitchattrib: pitch
cross_sections_folder: 0
copyorder: 1
crosssectionattrib: variant
primtype: 0
unrollclosedrowcol: 0
swaprowcol: 0
closeifnocurveinput: 0
up_folder: 0
upvectortype: 0
upvectoratstart: 1
useendupvector: 0
upvectorattrib: start_up
endupvectorattrib: end_up
upvectorx: 0.0
upvectory: 1.0
upvectorz: 0.0
endupvectorx: 0.0
endupvectory: 1.0
endupvectorz: 0.0
tangents_folder: 0
tangenttype: 0
continuousclosed: 1
extrapolateendtangents: 0
transformbyattribs: 1
uv_folder: 0
computeuvs: 0
overrideexistinguvs: 0
lengthweighteduvs: 1
normalizeu: 1
normalizev: 0
flipu: 1
uvscale_folder: 0
uvscale1: 1.0
uvscale2: 1.0
usemeshedgelengths: 1
propscalepercurve: 1
uvseams_folder: 0
wrapu: 1
wrapv: 1
attributes_folder: 0
input_folder: 0
attribsfrombackbone: * ^P ^N ^up ^pscale ^scale ^orient ^rot ^pivot ^trans ^transform
attribsfromcrosssection: *
output_folder: 0
addptrow: 0
ptrowattrib: ptrow
addptcol: 0
ptcolattrib: ptcol
addprimrow: 0
primrowattrib: primrow
addprimcol: 0
primcolattrib: primcol
addcrosssectionnum: 0
crosssectionnumattrib: crossnum
addcurvenum: 0
curvenumattrib: curvenum
scaleramp1pos: 0.0
scaleramp1value: 1.0
scaleramp1interp: 1
scaleramp2pos: 1.0
scaleramp2value: 1.0
scaleramp2interp: 1

Node Name: copytopoints4
Type: copytopoints::2.0
Inputs: sphere2, resample8
Outputs: merge3
Description:
Parameters:
sourcegroup:
sourcegrouptype: 0
targetgroup:
useidattrib: 0
idattrib: name
pack: 0
pivot: 1
viewportlod: 0
transform: 1
useimplicitn: 1
resettargetattribs: 0
targetattribs: 3
useapply1: 1
applyto1: 0
applymethod1: 0
applyattribs1: *,^v,^Alpha,^N,^up,^pscale,^scale,^orient,^rot,^pivot,^trans,^transform
useapply2: 1
applyto2: 0
applymethod2: 2
applyattribs2: Alpha
useapply3: 1
applyto3: 0
applymethod3: 3
applyattribs3: v

Node Name: resample8
Type: resample
Inputs: curve6
Outputs: copytopoints4
Description:
Parameters:
group:
maintainprimorder: 0
lod: 1.0
edge: 0
method: 0
measure: 0
dolength: 0
length: 0.0
dosegs: 1
segs: 1
useattribs: 1
allequal: 1
last: 0
randomshift: 0
onlypoints: 0
treatpolysas: 0
outputsubdpoly: 0
doptdistattr: 0
ptdistattr: ptdist
dotangentattr: 0
tangentattr: tangentu
docurveuattr: 0
curveuattr: curveu
docurvenumattr: 0
curvenumattr: curvenum

Node Name: sphere2
Type: sphere
Inputs:
Outputs: copytopoints4
Description:
Parameters:
type: 2
surftype: 4
radx: 0.125
rady: 0.2
radz: 0.125
tx: 0.0
ty: 0.0
tz: 0.0
rx: 0.0
ry: 0.0
rz: 0.0
scale: 1.0
orient: 1
freq: 2
rows: 13
cols: 24
orderu: 4
orderv: 4
imperfect: 1
upole: 0
accurate: 1
triangularpoles: 1

Node Name: circle2
Type: circle
Inputs:
Outputs: sweep4
Description:
Parameters:
type: 1
orient: 0
reverse: 1
radx: 0.08
rady: 0.08
tx: 0.0
ty: 0.0
tz: 0.0
rx: 0.0
ry: 0.0
rz: 0.0
scale: 1.0
order: 4
divs: 12
arc: 0
beginangle: 0.0
endangle: 360.0
imperfect: 1

Node Name: merge5
Type: merge
Inputs: curve1, curve4, curve5
Outputs: resample3
Description:
Parameters:

Node Name: curve7
Type: curve::2.0
Inputs:
Outputs: mirror2
Description:
Parameters:
group:
outputtype: 0
order: 4
convertcurves: 0
mode: 0
interpmethod: 0
enablebezierops: 0
operations:
delete: 0
fuse: 0
cut: 0
join: 0
deleteseg: 0
makecorner: 0
makesmooth: 0
makebalanced: 0
contract: 0
expand: 0
straightenseg: 0
close: 0
createroundedcorners: 0
removeroundedcorners: 0
makeauto: 0
makemanual: 0
reverse: 0
reset: 0
snaponclose: 1
maintainpoint: 0
approxendtangents: 0
caching: 0
stashgeo: None
savedstashgeo: <hou.Geometry frozen at 000000013EA80800 read-only>
parmpoints: <hou.Geometry frozen at 000000013EA80100 read-only>
stashid: ;
ninputprimscached: 0
softtransform: 0
softtransformrad: 0.5
output: 0
outputcornerpts: 0
cornerptsgroup: corner_points
outputsmoothpts: 0
smoothptsgroup: smooth_points
outputautopts: 0
autoptsgroup: auto_points
outputname: 0
name: curve7
nameattrib: name
outputxaxis: 0
xaxisname: out
outputyaxis: 0
yaxisname: up
outputzaxis: 0
zaxisname: tangent
outputorient: 0
orientname: orient
tangenttype: 0
aligntangent: 1
targetorients: 0
curoperation: 0
optype: 16
activepoints: 2
translatex: 0.0
translatey: 0.0
translatez: 0.0
rotatex: 0.0
rotatey: 0.0
rotatez: 0.0
scalex: 1.0
scaley: 1.0
scalez: 1.0
addpts:
activeprim: 0
cornerpts:
smoothpts: *
autopts:
pivottransformfolder: 0
pivottranslatex: 0.5430377721786499
pivottranslatey: 0.6000001430511475
pivottranslatez: -1.6607367992401123
pivotrotatex: 0.0
pivotrotatey: 0.0
pivotrotatez: 0.0
pivotfixed: 0
roundedcornersfolder: 0
viewroundcorners: 1
roundcornerpts:
roundcornerradius: 0.0
bakeroundcorners: 0
showroundcornerwidget: 1
showroundcornerlabels: 1
editedgeops: 0
planeorigx: 0.0
planeorigy: 0.0
planeorigz: 0.0
planenmlx: 0.0
planenmly: 1.0
planenmlz: 0.0
constrainstraighten: 0
handleparmsfolder: 0
handleptsx: -1
handleptsy: -1
handleptsz: -1
handlep0posx: -1.0
handlep0posy: 0.0
handlep0posz: 0.0
handlep1posx: 0.0
handlep1posy: 0.0
handlep1posz: 0.0
handlep2posx: 1.0
handlep2posy: 0.0
handlep2posz: 0.0

Node Name: mirror2
Type: mirror
Inputs: curve7
Outputs: polypatch2
Description:
Parameters:
group:
operation: 0
dirtype: 0
tx: 0.0
ty: 0.0
tz: 0.0
rx: 0.0
ry: 0.0
rz: 0.0
originx: 0.0
originy: 0.0
originz: 0.0
dirx: 1.0
diry: 0.0
dirz: 0.0
dist: 0.0
reversenml: 1
keepOriginal: 1
consolidatepts: 1
consolidatetol: 0.0001
consolidateunshared: 1
createoutputgroup: 0
outputgroup: mirror

Node Name: polypatch2
Type: polypatch
Inputs: mirror2
Outputs: copytopoints5
Description:
Parameters:
group:
basis: 0
connecttype: 4
closeu: 2
closev: 2
firstuclamp: 2
lastuclamp: 2
firstvclamp: 2
lastvclamp: 2
divisionsx: 4
divisionsy: 4
polys: 0

Node Name: curve8
Type: curve::2.0
Inputs:
Outputs: sweep5, attribwrangle1
Description:
Parameters:
group:
outputtype: 0
order: 4
convertcurves: 0
mode: 1
interpmethod: 0
enablebezierops: 0
operations:
delete: 0
fuse: 0
cut: 0
join: 0
deleteseg: 0
makecorner: 0
makesmooth: 0
makebalanced: 0
contract: 0
expand: 0
straightenseg: 0
close: 0
createroundedcorners: 0
removeroundedcorners: 0
makeauto: 0
makemanual: 0
reverse: 0
reset: 0
snaponclose: 1
maintainpoint: 0
approxendtangents: 0
caching: 0
stashgeo: None
savedstashgeo: <hou.Geometry frozen at 000000013EA2B900 read-only>
parmpoints: <hou.Geometry frozen at 000000013EA2B200 read-only>
stashid: ;
ninputprimscached: 0
softtransform: 0
softtransformrad: 0.5
output: 0
outputcornerpts: 0
cornerptsgroup: corner_points
outputsmoothpts: 0
smoothptsgroup: smooth_points
outputautopts: 0
autoptsgroup: auto_points
outputname: 0
name: curve8
nameattrib: name
outputxaxis: 0
xaxisname: out
outputyaxis: 0
yaxisname: up
outputzaxis: 0
zaxisname: tangent
outputorient: 0
orientname: orient
tangenttype: 0
aligntangent: 1
targetorients: 0
curoperation: 0
optype: 0
activepoints:
translatex: 0.0
translatey: 0.0
translatez: 0.0
rotatex: 0.0
rotatey: 0.0
rotatez: 0.0
scalex: 1.0
scaley: 1.0
scalez: 1.0
addpts:
activeprim: 0
cornerpts:
smoothpts: *
autopts:
pivottransformfolder: 0
pivottranslatex: 0.0
pivottranslatey: 0.0
pivottranslatez: 0.0
pivotrotatex: 0.0
pivotrotatey: 0.0
pivotrotatez: 0.0
pivotfixed: 0
roundedcornersfolder: 0
viewroundcorners: 1
roundcornerpts:
roundcornerradius: 0.0
bakeroundcorners: 0
showroundcornerwidget: 1
showroundcornerlabels: 1
editedgeops: 0
planeorigx: 0.0
planeorigy: 0.0
planeorigz: 0.0
planenmlx: 0.0
planenmly: 1.0
planenmlz: 0.0
constrainstraighten: 0
handleparmsfolder: 0
handleptsx: -1
handleptsy: -1
handleptsz: -1
handlep0posx: -1.0
handlep0posy: 0.0
handlep0posz: 0.0
handlep1posx: 0.0
handlep1posy: 0.0
handlep1posz: 0.0
handlep2posx: 1.0
handlep2posy: 0.0
handlep2posz: 0.0

Node Name: copytopoints5
Type: copytopoints::2.0
Inputs: polypatch2, attribwrangle1
Outputs: merge6
Description:
Parameters:
sourcegroup:
sourcegrouptype: 0
targetgroup:
useidattrib: 0
idattrib: name
pack: 0
pivot: 1
viewportlod: 0
transform: 1
useimplicitn: 1
resettargetattribs: 0
targetattribs: 3
useapply1: 1
applyto1: 0
applymethod1: 0
applyattribs1: *,^v,^Alpha,^N,^up,^pscale,^scale,^orient,^rot,^pivot,^trans,^transform
useapply2: 1
applyto2: 0
applymethod2: 2
applyattribs2: Alpha
useapply3: 1
applyto3: 0
applymethod3: 3
applyattribs3: v

Node Name: attribwrangle1
Type: attribwrangle
Inputs: curve8
Outputs: copytopoints5
Description:
Parameters:
folder01: 0
group:
grouptype: 0
class: 2
vex_numcount: 10
vex_threadjobsize: 1024
snippet: float angle = rand(@ptnum) * 360; // 0〜360度のランダム回転
vector axis = {0,1,0}; // X軸回転
vector4 q = quaternion(radians(angle), axis);
@orient = q;
exportlist: *
vex_strict: 0
autobind: 1
bindings: 0
groupautobind: 1
groupbindings: 0
vex_cwdpath: .
vex_outputmask: *
vex_updatenmls: 0
vex_matchattrib: id
vex_inplace: 0
vex_selectiongroup:
vex_precision: auto

Node Name: circle3
Type: circle
Inputs:
Outputs: sweep5
Description:
Parameters:
type: 1
orient: 0
reverse: 1
radx: 0.05
rady: 0.05
tx: 0.0
ty: 0.0
tz: 0.0
rx: 0.0
ry: 0.0
rz: 0.0
scale: 1.0
order: 4
divs: 12
arc: 0
beginangle: 0.0
endangle: 360.0
imperfect: 1

Node Name: sweep5
Type: sweep::2.0
Inputs: curve8, circle3
Outputs: merge6
Description:
Parameters:
curvegroup:
crosssectiongroup:
surface_folder1: 0
surfaceshape: 0
surfacetype: 5
scale: 1.0
cols: 8
radius: 0.1
width: 0.2
reversecrosssections: 0
stretcharoundturns: 1
maxstretcharoundturns: 10.0
endcaps_folder: 0
endcaptype: 0
capdivs: 3
triangularpoles: 0
capscale: 1.0
caproundness: 1.0
addendcapsgroup: 0
endcapsgroup: endcaps
scale_folder: 0
applyscale: 0
scaleramp: <hou.Ramp is_color=False num_keys=2 data=((t=0, 1), (t=1, 1))>
rotation_folder: 0
rOrd: 0
applyroll: 1
roll: 0.0
fulltwists: 0
incroll: 0.0
rollper: 4
rollattrib: roll
applyyaw: 0
yaw: 0.0
incyaw: 0.0
yawper: 4
yawattrib: yaw
applypitch: 0
pitch: 0.0
incpitch: 0.0
pitchper: 4
pitchattrib: pitch
cross_sections_folder: 0
copyorder: 1
crosssectionattrib: variant
primtype: 0
unrollclosedrowcol: 0
swaprowcol: 0
closeifnocurveinput: 0
up_folder: 0
upvectortype: 0
upvectoratstart: 1
useendupvector: 0
upvectorattrib: start_up
endupvectorattrib: end_up
upvectorx: 0.0
upvectory: 1.0
upvectorz: 0.0
endupvectorx: 0.0
endupvectory: 1.0
endupvectorz: 0.0
tangents_folder: 0
tangenttype: 0
continuousclosed: 1
extrapolateendtangents: 0
transformbyattribs: 1
uv_folder: 0
computeuvs: 0
overrideexistinguvs: 0
lengthweighteduvs: 1
normalizeu: 1
normalizev: 0
flipu: 1
uvscale_folder: 0
uvscale1: 1.0
uvscale2: 1.0
usemeshedgelengths: 1
propscalepercurve: 1
uvseams_folder: 0
wrapu: 1
wrapv: 1
attributes_folder: 0
input_folder: 0
attribsfrombackbone: * ^P ^N ^up ^pscale ^scale ^orient ^rot ^pivot ^trans ^transform
attribsfromcrosssection: *
output_folder: 0
addptrow: 0
ptrowattrib: ptrow
addptcol: 0
ptcolattrib: ptcol
addprimrow: 0
primrowattrib: primrow
addprimcol: 0
primcolattrib: primcol
addcrosssectionnum: 0
crosssectionnumattrib: crossnum
addcurvenum: 0
curvenumattrib: curvenum
scaleramp1pos: 0.0
scaleramp1value: 1.0
scaleramp1interp: 1
scaleramp2pos: 1.0
scaleramp2value: 1.0
scaleramp2interp: 1

Node Name: merge6
Type: merge
Inputs: copytopoints5, sweep5
Outputs: merge4
Description:
Parameters:

Node Name: transform3
Type: xform
Inputs: merge4
Outputs: merge7
Description:
Parameters:
group:
grouptype: 0
xOrd: 0
rOrd: 0
tx: 0.0
ty: 5.4
tz: 0.0
rx: 0.0
ry: 0.0
rz: 0.0
sx: 1.0
sy: 1.0
sz: 1.0
shear1: 0.0
shear2: 0.0
shear3: 0.0
scale: 1.0
parmgroup_pivotxform: 0
px: 0.0
py: 0.0
pz: 0.0
prx: 0.0
pry: 0.0
prz: 0.0
parmgroup_prexform: 0
prexform_xOrd: 0
prexform_rOrd: 0
prexform_tx: 0.0
prexform_ty: 0.0
prexform_tz: 0.0
prexform_rx: 0.0
prexform_ry: 0.0
prexform_rz: 0.0
prexform_sx: 1.0
prexform_sy: 1.0
prexform_sz: 1.0
prexform_shear1: 0.0
prexform_shear2: 0.0
prexform_shear3: 0.0
movecentroid: 0
movepivot: 0
attribs: *
updatenmls: 0
updateaffectednmls: 1
vlength: 1
invertxform: 0
addattrib: 0
outputattrib: xform
outputmerge: 2

Node Name: grid1
Type: grid
Inputs:
Outputs: merge7
Description:
Parameters:
type: 0
surftype: 4
orient: 2
sizex: 100.0
sizey: 100.0
tx: 0.0
ty: 0.0
tz: 0.0
rx: 0.0
ry: 0.0
rz: 0.0
rows: 10
cols: 10
orderu: 4
orderv: 4
interpu: 1
interpv: 1

Node Name: merge7
Type: merge
Inputs: transform3, grid1
Outputs:
Description:
Parameters:

AIはHoudini MCPを通じてノード情報を取得し、ファイルに書き出してくれます。そして、そのファイルの内容を読み込ませ、「このファイルの内容を分析して、どのようなモデルか解説して」と指示します。

すると、AIはノードの接続関係やパラメータから形状を推測し、ノードの役割ごとにグループ分けしながら、モデルの構造を解説してくれました!

記事の内容

Houdiniノードネットワークのワークフロー解説

このHoudiniネットワークは、複数のCurveノードで描かれた曲線をもとに、Sweep、Copy to Points、PolyPatchなどのノードを駆使して、装飾的な3Dオブジェクト(花や植物のような抽象的な形状)を生成し、最後に地面となるグリッドと結合しています。

以下に、全体のワークフローと各ノードグループの役割を解説します。

全体的なワークフロー概要

  1. 要素1: 中央の花びら状の形状作成 (curve2, curve3merge2)
  2. 要素2: 複数の装飾要素(先端の球体/楕円体)作成 (curve1, curve4, curve5, curve6, sphere1, sphere2, resample, copytopoints)
  3. 要素3: 複数の装飾要素(チューブ状の茎/枝)作成 (curve1, curve4, curve5, curve6, circle1, circle2, resample, sweep)
  4. 要素4: ランダム回転する装飾要素作成 (curve7, mirror2, polypatch2, curve8, attribwrangle1, copytopoints5, sweep5, circle3)
  5. 要素の統合 (merge3, merge4)
  6. 最終的な配置と地面の追加 (transform3, grid1, merge7)

詳細解説

1. 要素1: 中央の花びら状の形状作成

  • curve2, curve3:
    • タイプ: curve::2.0
    • 役割: ビューポート上で手動でNURBSカーブを描画・編集します。これらが基本的な形状の輪郭線となります。curve3mirror1 にも接続されています。
  • mirror1:
    • タイプ: mirror
    • 入力: curve3
    • 役割: curve3 で描かれたカーブを、原点(0,0,0)を通るYZ平面(法線がX軸方向 dirx: 1.0)に対して反転コピーします。keepOriginal: 0 なので、元のカーブは出力されず、反転コピーされたカーブのみが出力されます。consolidatepts: 1 により、ミラー平面上の点は結合されます。
  • merge1:
    • タイプ: merge
    • 入力: mirror1, curve2, curve3
    • 役割: curve2curve3、そして curve3 をミラーリングした mirror1 の結果、合計3つのカーブ(またはミラーリングによって結合された場合はそれ以下)を1つのジオメトリにまとめます。これにより、閉じた、または開いた輪郭が形成されている可能性があります。
  • polypatch1:
    • タイプ: polypatch
    • 入力: merge1
    • 役割: merge1 からのカーブ群を境界として使用し、ポリゴンメッシュ(面)を生成します。connecttype: 4 (Connect All Endpoints) は、カーブの端点を接続して面を張ろうとします。これにより、カーブで囲まれた領域に面が生成されます。これが「花びら」の基本形状となる1枚(または複数枚)です。
  • foreach_begin1, transform1, foreach_end1:
    • タイプ: block_begin, xform, block_end
    • 入力 (foreach_begin1): polypatch1
    • 役割: polypatch1 で生成されたジオメトリ(花びら)に対してループ処理を行います。
      • foreach_end1iterations: 3method: 1 (Merge Each Iteration) により、ループ内の処理が3回実行され、その結果がすべてマージされます。
      • transform1 はループ内で毎回実行され、入力ジオメトリをY軸周りに360度回転 (ry: 360.0) します。360度回転は元の位置に戻るため、この設定だけを見ると、同じジオメトリが3回同じ位置に重ねてマージされることになります。これは少し奇妙な設定ですが、意図としては3つのコピーを作成したかったのかもしれません(ただし、回転角度を変えなければ重なるだけです)。
  • transform2:
    • タイプ: xform
    • 入力: foreach_end1
    • 役割: foreach_end1 から出力された(3つ重なった)ジオメトリ全体を、少し下に移動 (ty: -0.1) し、Y軸周りに60度回転 (ry: 60.0) させます。
  • merge2:
    • タイプ: merge
    • 入力: transform2, foreach_end1
    • 役割: 元のループ結果 (foreach_end1) と、それを移動・回転させた結果 (transform2) を結合します。これにより、中心に元の形状があり、その少し下に60度回転した形状が配置された、より複雑な花びら状の構造ができます。

2. 要素2 & 3: 複数の装飾要素(先端の球体/楕円体とチューブ状の茎/枝)作成

この部分は、複数のカーブ (curve1, curve4, curve5, curve6) をベースに、それぞれに対して先端の装飾とチューブ状の構造を作成し、最後に merge3 で結合する流れになっています。

  • curve1, curve4, curve5, curve6:
    • タイプ: curve::2.0
    • 役割: それぞれ異なる形状のカーブを手動で作成します。これらが装飾要素のパス(経路)となります。
  • resample2, resample4, resample6, resample8:
    • タイプ: resample
    • 入力: それぞれ対応する curve ノード
    • 役割: 入力カーブをリサンプリング(再分割)します。
      • resample2, resample4, resample6, resample8dosegs: 1, segs: 1 に設定されています。これは通常、カーブの始点と終点の2点のみを生成します(あるいはカーブ全体を1セグメントとして扱う)。これらの点は copytopoints ノードのターゲットとして使用され、カーブの端に装飾を配置します。
      • resample3 (merge5経由でcurve1,4,5を入力) と resample7 (curve6を入力) は length: 0.1 に設定されています。これにより、カーブを約0.1単位の長さのセグメントに分割し、多数の点を生成します。これらの点は sweep ノードのバックボーン(背骨)カーブとして使用されます。
  • sphere1, sphere2:
    • タイプ: sphere
    • 役割: コピーするための元となる形状を作成します。
      • sphere1: X/Z半径が0.1、Y半径が0.2の楕円体 (type: 2 は Primitive)。
      • sphere2: 半径が0.125の球体に近い形状 (radx, radz が 0.125)。
  • copytopoints1, copytopoints2, copytopoints3, copytopoints4:
    • タイプ: copytopoints::2.0
    • 入力1: sphere1 または sphere2 (コピー元ジオメトリ)
    • 入力2: 対応する resample ノード (コピー先ポイント)
    • 役割: 各 resample ノードで生成された点(カーブの端点)の位置に、対応する球体/楕円体をコピーします。transform: 1 が有効なので、ポイントに N (法線) や orient (向き) アトリビュートがあれば、コピーされるジオメトリの向きも制御されますが、resample (segs=1) は通常、位置情報のみを提供します(dotangentattrが無効なため)。
  • circle1, circle2:
    • タイプ: circle
    • 役割: sweep ノードで使用する断面形状(円)を作成します。
      • circle1: 半径 0.05 の円。
      • circle2: 半径 0.08 の円。
  • merge5:
    • タイプ: merge
    • 入力: curve1, curve4, curve5
    • 役割: 3つのカーブを1つにまとめ、resample3 に渡してチューブ作成用のパスとします。
  • sweep2, sweep4:
    • タイプ: sweep::2.0
    • 入力1: resample3 または resample7 (リサンプリングされたカーブパス)
    • 入力2: circle1 または circle2 (断面形状)
    • 役割: カーブパス (resample3 / resample7) に沿って、円 (circle1 / circle2) を押し出し、チューブ状のジオメトリを作成します。surfacetype: 5 (Skin with Auto-Closed Ends if Possible) は、開いたカーブでも閉じた断面でチューブを生成します。
  • merge3:
    • タイプ: merge
    • 入力: copytopoints1, copytopoints2, sweep2, copytopoints3, copytopoints4, sweep4
    • 役割: これまでに作成した全ての先端装飾(球/楕円体)とチューブ状の構造を1つのジオメトリに統合します。

3. 要素4: ランダム回転する装飾要素作成

  • curve7:
    • タイプ: curve::2.0
    • 役割: 装飾の基本形状となるカーブを作成します。
  • mirror2:
    • タイプ: mirror
    • 入力: curve7
    • 役割: curve7 をYZ平面(X=0)でミラーコピーします。今回は keepOriginal: 1 なので、元のカーブとミラーコピーされたカーブの両方が出力されます。
  • polypatch2:
    • タイプ: polypatch
    • 入力: mirror2
    • 役割: mirror2 からのカーブ(元のカーブとミラーコピー)を使って面を生成します。これが copytopoints5 でコピーされる基本形状となります。
  • curve8:
    • タイプ: curve::2.0
    • 役割: 装飾要素を配置するパスとなるカーブを作成します。mode: 1 (Draw) で描かれた可能性があります。このカーブは、コピー先のポイント (attribwrangle1経由) と、チューブのパス (sweep5) の両方に使われます。
  • attribwrangle1:
    • タイプ: attribwrangle
    • 入力: curve8
    • 役割: curve8 の各ポイント (class: 2) に対してVEXコードを実行します。
      float angle = rand(@ptnum) * 360; // 各ポイントに0から360のランダムな角度を生成
      vector axis = {0,1,0}; // 回転軸をY軸に設定
      vector4 q = quaternion(radians(angle), axis); // 角度と軸からクォータニオン(回転情報)を生成
      @orient = q; // ポイントの向きアトリビュートとして設定
      
      これにより、curve8 の各点にランダムなY軸回転情報が付与されます。
  • copytopoints5:
    • タイプ: copytopoints::2.0
    • 入力1: polypatch2 (コピー元ジオメトリ)
    • 入力2: attribwrangle1 (コピー先ポイント、ランダムな @orient 付き)
    • 役割: curve8 の各点に polypatch2 で作成した面をコピーします。transform: 1@orient アトリビュートにより、コピーされる各面はランダムなY軸回転を持ちます。
  • circle3:
    • タイプ: circle
    • 役割: sweep5 で使用する断面形状(半径0.05の円)を作成します。
  • sweep5:
    • タイプ: sweep::2.0
    • 入力1: curve8 (カーブパス)
    • 入力2: circle3 (断面形状)
    • 役割: curve8 に沿って circle3 をスイープし、チューブを作成します。
  • merge6:
    • タイプ: merge
    • 入力: copytopoints5, sweep5
    • 役割: ランダムに回転配置された面 (copytopoints5) と、それらが配置されているパスに沿ったチューブ (sweep5) を結合します。

4. 要素の統合

  • merge4:
    • タイプ: merge
    • 入力: merge2 (要素1: 花びら), merge3 (要素2&3: 先端装飾とチューブ), merge6 (要素4: ランダム回転装飾とチューブ)
    • 役割: これまで作成してきた全ての装飾的な要素を1つのジオメトリにまとめます。

5. 最終的な配置と地面の追加

  • transform3:
    • タイプ: xform
    • 入力: merge4
    • 役割: 結合された全てのジオメトリを、Y軸方向に 5.4 単位上に移動させます。
  • grid1:
    • タイプ: grid
    • 役割: 100x100の大きさのグリッド(XZ平面 orient: 2)を作成します。これは地面として機能します。
  • merge7:
    • タイプ: merge
    • 入力: transform3, grid1
    • 役割: 上方に移動したメインの装飾オブジェクト (transform3) と、地面となるグリッド (grid1) を結合し、最終的なシーンを構成します。これがネットワーク全体の最終出力となります。

まとめ

このネットワークは、複数のカーブ描画から始まり、それらを基にMirror, PolyPatch, Sweep, Copy to Points, ForEachループ, Attribute Wrangleなどのノードを組み合わせて、段階的に複雑な形状を構築しています。最終的には、複数の装飾要素が組み合わさった一つのオブジェクトと、地面が生成されます。各カーブやパラメータを調整することで、様々なバリエーションの形状を作成できる、プロシージャルなモデリングワークフローの一例と言えます。

思考プロセス

ユーザーはHoudiniのノードネットワークとそのパラメータの詳細を提供し、そのワークフローと各ノードの役割について解説を求めている。

解説の方針:

  1. 全体的なワークフローの概要: ネットワーク全体が何を作成しようとしているのか、大まかな流れを把握する。複数の独立した要素を作成し、最後に統合しているように見える。
  2. 主要な要素の特定: ネットワークを構成する大きな要素(ブランチ)を特定する。
    • curve2, curve3, mirror1, polypatch1, foreach_begin1foreach_end1, transform1, transform2, merge2 のブランチ。
    • curve1, resample2, sphere1, copytopoints1 のブランチ。
    • curve4, resample4, sphere1, copytopoints2 のブランチ。
    • curve5, resample6, sphere1, copytopoints3 のブランチ。
    • curve6, resample8, sphere2, copytopoints4 のブランチ。
    • curve1, curve4, curve5 をマージして resample3, circle1, sweep2 でチューブを作成するブランチ。
    • curve6, resample7, circle2, sweep4 でチューブを作成するブランチ。
    • curve7, mirror2, polypatch2, curve8, attribwrangle1, copytopoints5, sweep5, circle3, merge6 のブランチ。
    • grid1 のブランチ。
  3. 各ブランチ(要素)の詳細解説:
    • 各ブランチがどのような形状や要素を作成しているかを説明する。
    • 重要なノードとそのパラメータ設定がどのような効果をもたらしているかを解説する。
    • ノード間の接続関係を明確にする。
  4. 要素の統合: mergeノードで各要素がどのように統合されているかを説明する。
  5. 最終的な出力: ネットワーク全体として何が生成されるかをまとめる。

詳細な思考プロセス:

  • 要素1 (花びら?): curve2, curve3 で曲線を描き、mirror1curve3 を反転コピー。merge1 で3つのカーブを結合し、polypatch1 でポリゴンメッシュ(おそらく面)を生成。foreach ループ内で transform1 を使ってこのメッシュをY軸中心に360度回転コピー(iterations: 3 なので3回? method: 1By Countitermethod: 2Merge Each Iteration なので、ループごとに結果がマージされる。ry: 360.0 はループごとに360度回転? foreach_begin1method: 3Fetch Feedback なので、前のイテレーションの結果を使う?いや、transform1foreach_begin1 を入力としているので、各イテレーションで polypatch1 の結果が入力されるはず。foreach_end1iterations: 3 が重要。ループごとに polypatch1 の形状がY軸周りに 360/3 = 120度ずつ回転コピーされると考えるのが自然か?いや、transform1ry が 360。これはループ内で毎回360度回転? VEXpressionなどでイテレーション番号を使っていないので、単純に3回同じ変換(360度回転=元の位置)をするだけ? foreach_count1 というノードもあるが、これはどこにも接続されていないように見える。パラメータリストにはあるが、接続情報がない。これは無視してよさそう。foreach_end1method: 1 (Merge Each Iteration) は、ループの各反復の結果をマージすることを意味する。iterations: 3 なので、polypatch1 の結果が3回、それぞれ transform1 (ry=360) で変換されてマージされる。実質的に同じものが3つ重なるだけ? ちょっと奇妙な設定。しかし、transform2foreach_end1 の結果を受け取り、ty: -0.1, ry: 60.0 で変換している。そして merge2foreach_end1 の結果と transform2 の結果をマージしている。これは、元のループ結果(3つ重なったもの)と、それを少し下げて60度回転させたものを結合している。花のような形状を作る意図かもしれない。polypatch1connecttype: 4 (Connect All Endpoints) は重要。
  • 要素2 (装飾 - 枝/茎と先端?):
    • curve1, curve4, curve5, curve6: それぞれ異なる形状のカーブを手動で作成。
    • resample2, resample4, resample6, resample8: 各カーブの終点(segs: 1)に点を生成。resamplesegs が 1 の場合、カーブ全体を1つのセグメントとし、端点のみが出力されるか、あるいはカーブの始点・終点とその中間点を考慮する必要がある。dosegs: 1, segs: 1 は通常、カーブの始点と終点を出力する。
    • sphere1, sphere2: 楕円体(radx, rady, radz が異なる)と球体を作成。
    • copytopoints1, copytopoints2, copytopoints3, copytopoints4: 各 resample ノードで生成された点(カーブの端点)に、対応する球体/楕円体をコピー。copytopoints は通常、点のアトリビュート(N, up, orient, pscale など)を使ってコピーの向きやスケールを制御するが、resample はデフォルトでは tangentu を生成する可能性があるものの、copytopoints がそれをどう使うかは設定次第 (useimplicitn: 1 など)。
  • 要素3 (装飾 - チューブ状の枝/茎?):
    • merge5: curve1, curve4, curve5 を結合。
    • resample3: 結合したカーブを一定間隔 (length: 0.1) でリサンプリング。
    • circle1: 小さな円 (radx: 0.05) を作成。
    • sweep2: resample3 のカーブに沿って circle1 をスイープし、チューブ状のメッシュを作成。
  • 要素4 (装飾 - 太いチューブ状の枝/茎?):
    • resample7: curve6 を一定間隔 (length: 0.1) でリサンプリング。
    • circle2: circle1 より少し大きい円 (radx: 0.08) を作成。
    • sweep4: resample7 のカーブに沿って circle2 をスイープし、チューブ状のメッシュを作成。
  • 要素5 (装飾 - ランダム回転の何か?):
    • curve7: カーブを作成。
    • mirror2: curve7 をX=0平面でミラーコピー(オリジナルも保持 keepOriginal: 1)。
    • polypatch2: ミラーリングされたカーブからポリゴンメッシュ(面)を作成。
    • curve8: 別のカーブを作成 (mode: 1 は Draw Mode?)。
    • attribwrangle1: curve8 の各点 (class: 2 は Point Wrangle) にランダムなY軸周りの回転 (@orient) を設定。
    • copytopoints5: attribwrangle1 で回転情報が付与された点(curve8 の点)に polypatch2 のメッシュをコピー。ランダムに回転した面が配置される。
    • circle3: circle1 と同じサイズの円を作成。
    • sweep5: curve8 に沿って circle3 をスイープし、チューブ状のメッシュを作成。
    • merge6: ランダムに回転配置された面 (copytopoints5) と、curve8 ベースのチューブ (sweep5) を結合。
  • 要素の統合:
    • merge3: 要素2の先端装飾 (copytopoints1, copytopoints2, copytopoints3, copytopoints4) と、要素3, 4のチューブ (sweep2, sweep4) を結合。
    • merge2: 要素1の花びら部分(元のセットと回転/移動させたセット)を結合。
    • merge4: 要素1の花びら (merge2)、要素2,3,4の装飾/チューブ (merge3)、要素5のランダム回転面/チューブ (merge6) を結合。
  • 最終調整と出力:
    • transform3: merge4 で結合された全ジオメトリを上に移動 (ty: 5.4)。
    • grid1: 大きなXZ平面のグリッドを作成。
    • merge7: 上に移動したメインのジオメトリと、地面となるグリッドを結合して最終的なシーンを構成。

要約:
このネットワークは、複数のカーブベースのモデリング技術を組み合わせて、装飾的なオブジェクト(花や植物のようなもの?)を作成している。

  1. 中央の回転対称な形状(花びら?)。
  2. 複数のカーブに沿って配置された先端の装飾(球/楕円体)。
  3. 複数のカーブに沿って作成されたチューブ状の構造(茎/枝?)。
  4. 別のカーブに沿ってランダムに回転配置された面と、それに対応するチューブ。
  5. これら全てを結合し、全体を上に移動させ、最後に地面となるグリッドを追加している。

各ノードの解説ポイント:

  • curve::2.0: 手動でカーブを描画・編集するノード。多くのパラメータがあるが、基本的にはビューポートで直接操作されることが多い。savedstashgeoparmpoints は編集中の状態を保存している。
  • mirror: ジオメトリを指定した平面で反転コピーする。keepOriginal で元のジオメトリを残すか選択。consolidatepts で境界の点を結合する。
  • polypatch: 開いたカーブや閉じたカーブの境界からポリゴンメッシュ(面)を生成する。connecttype: 4 (Connect All Endpoints) は、入力カーブ群のすべての端点を接続しようとする。
  • merge: 複数のジオメトリストリームを1つにまとめる。
  • foreach_begin, foreach_end: ループ処理を行うためのブロック。foreach_end1method: 1 (Merge Each Iteration) と iterations: 3 が重要。ループ内の transform1ry: 360 が少し不可解だが、3回同じものを生成してマージしているか、あるいはループ内で何らかの動的な変更(ここでは見られない)が意図されていた可能性がある。もしくは、単に3つのコピーを作成する意図かもしれないが、回転させずに同じ場所に重ねている。
  • transform: ジオメトリの移動、回転、スケールを行う。
  • resample: カーブを指定した方法(セグメント数 segs や長さ length)で再分割する。segs: 1 は始点と終点のみを生成することが多い。length: 0.1 はカーブを約0.1単位の長さのセグメントに分割する。
  • sphere, circle: 基本的なプリミティブ形状を生成。
  • copytopoints::2.0: テンプレートジオメトリ(第1入力)をターゲットポイント(第2入力)の位置にコピーする。transform: 1 でターゲットポイントのアトリビュート(N, up, orient, pscale など)を使ってコピーの向きやスケールを制御できる。
  • sweep::2.0: バックボーンカーブ(第1入力)に沿ってクロスセクション形状(第2入力)を押し出してジオメトリを作成する。チューブや複雑な押し出し形状を作るのに使う。
  • attribwrangle: VEX言語を使ってアトリビュートを操作する強力なノード。ここでは @ptnum (ポイント番号) を使ってランダムな @orient (向き) アトリビュートを作成している。
  • grid: グリッド(平面)メッシュを作成。

これで、解説を作成するための十分な情報が得られた。

今回はノード情報だけを渡しましたが、「花びら、茎、葉っぱを作り、葉っぱの位置はランダムになるように工夫しました」といった補足情報(作成者の意図やこだわり) をAIに与えれば、さらに質の高い解説が自動で生成されるかもしれません!

追記:
実際にいくつか解説してもらいました!
https://zenn.dev/nekoco/scraps/a13fc5f9f17d44

広がる連携の妄想:
MCPに対応したツールは増え続けており(すでに1000以上あるとも言われています。)、アイデア次第で様々な連携が考えられます。
https://qiita.com/syukan3/items/5c3c9321d713bc1d8ecf

  • Houdiniでのシミュレーション完了 → 結果をSlack/Discordに通知し、成果物をGoogle Driveに自動アップロード
  • Houdiniで生成したアセット情報をUnity MCPに送信 → Unityシーン内にリアルタイムで配置]
    なお、技術的ハードルも存在するようで…
    https://zenn.dev/nekoco/scraps/c4a1455b4bbf4c
  • Blender MCPと連携して、HoudiniとBlender間でのデータ受け渡しを自動化

このように、アプリケーションの壁を超えたワークフローが実現できる可能性を秘めているのが、MCPの大きな魅力です。

現状の壁と課題:「面白い」から「実用的」への距離

ここまでMCPの可能性について語ってきましたが、正直なところ、現在のHoudini MCPを日々の実務で活用するのは、まだ難しいと感じています。

  • AIの不安定さ: AIの特性上、同じ指示でも結果が微妙に異なったり、期待通りに動作しないことがまだ多いです。これは、ツールやプログラムを正確に使いこなしたいユーザーにとっては、ストレスになる可能性があります。
  • プロシージャル性の喪失?: AIと対話しながら試行錯誤するプロセスは、Houdini本来のプロシージャルなワークフローとは少し異なります。失敗した場合、手動でノードを整理・削除する必要があり、手間がかかることがあります。
  • Houdini知識の必要性: AIが生成した結果を評価し、修正するには、結局のところHoudiniに関する深い知識が必要です。AIはあくまでアシスタントであり、魔法の杖ではありません。

まとめ:未来への大きな一歩、しかし現実はまだ途上

  • Houdini MCPは、AIと3DCG制作の未来を垣間見せてくれる、非常に興味深い実験的なツールです。
  • 特に、MCPによるアプリケーション連携の可能性には、大きな夢を感じます。
  • しかし、現時点ではまだ「おもちゃ」や「実験」の段階であり、安定性や制御性の面で、プロの現場で安心して頼れるツールとは言い難い状況です。

この記事が、HoudiniとAIの連携、そしてMCPという技術に興味を持つ皆さんの、次なる探求のきっかけとなれば幸いです。ぜひ皆さんも、この未来のカケラに触れてみてください!


追記(思ったこと):
MCPとは、APIとプログラムで出来ることを、自然言語で出来るようにしたものと捉えている。
なのでわざわざプログラム書くのめんどくさい時に使えるかもしれないね~(単なる実験とか?)

もっと面白そうな活用法を思いついたら、Scrapsなどにまとめるかもしれません。


追記その2
最近MCPについて考えていることをAIに言語化してもらいました

あなたのMCP(Model Context Protocol)に対する視点は、単なる技術評価を超え、未来のインターフェースのあり方、AIとの協働、そして自身の思考プロセスとの関係性までをも見据えた、多層的なものです。以下に、その核心を捉え直します。

1. MCPの核心的価値:APIを超え、AIと共に進化するインターフェース

  • APIとの本質的な違い: あなたはMCPを、従来のAPIのような固定的な機能呼び出しとは一線を画すものとして捉えています。MCPの価値は、AIが文脈を理解し、より柔軟にタスクを解釈・実行できる点にあります。これは、システムとの対話性を格段に向上させる可能性を秘めています。
  • AI進化と連動する未来性: MCPの真のポテンシャルは、プロトコル自体の洗練だけでなく、それを活用するAIモデルの進化と密接に連動している点にあります。AIがより賢く、文脈理解能力や推論能力を高めるほど、MCPを通じて実現できることの範囲と質は飛躍的に向上します。この「AIの進化しろ」こそが、MCPに未来性を感じさせる重要な要素です。
  • 発想実現の障壁低下(「脳の拡張」の再定義): あなたが関心を寄せる「脳の拡張」とは、特定のインターフェース(自然言語)に限定されるものではありません。本質は、アイデアを具体的な形にする際の技術的な障壁(プログラミング知識、APIの複雑さなど)を低減・除去することにあります。MCPは、そのための有望なアプローチの一つとして興味深いのです。
  • インターフェースへの柔軟な視点: 自然言語は現時点での有力な手段の一つに過ぎません。あなたは、より効率的で、自身の思考様式(プログラム的、論理的な側面を含む)に合った、より洗練されたインターフェースが登場する可能性も視野に入れています。重要なのは言語形式ではなく、思考とシステム間の摩擦を最小化することです。

2. 現状技術の延長線上の未来:地に足のついた応用と可能性
あなたは、SF的な飛躍よりも、現在の技術基盤から現実的に到達しうる、具体的な未来像に強い関心を抱いています。MCPがその中で果たしうる役割として、以下のような点に注目しています。

  • ニッチな連携の実現: 標準的な連携機能が提供されていないソフトウェアやサービス間を、MCPを通じて比較的容易に繋ぎ合わせる。これは、特定のワークフローを持つユーザーにとって大きな価値となり得ます。(例:特定の3Dソフトと自作ツール、プロジェクト管理ツールとチャットツールの独自連携など)
  • 高速プロトタイピング: アイデアの概念実証(Proof of Concept)や、新しいワークフローの試作を迅速に行うためのツールとしての価値。完璧なソリューションではなくとも、「とりあえず動くもの」を素早く作り上げる際に、MCPとAIの組み合わせは有効かもしれません。
  • パーソナライズされたアシスタント機能: 個々のユーザーの作業文脈、データ、好みを学習したAIが、MCPを通じてより的確な支援を提供する。ただし、その役割は後述する「ツール」とは異なる側面を持ちます。
  • 「便利ソフトのプロトタイプ作成」: AIの柔軟性を活かし、特定のタスクを自動化する小規模なツールやスクリプトを、プログラミングの手間を大幅に削減して作成する。完成度よりもスピード重視の場面で有効です。

3. 根源的課題と向き合う:非決定性・非手続き性との葛藤とAIの役割
MCP(およびそれを支えるAI)の非決定性と非手続き的な挙動は、あなたが最も強く課題として認識している点です。これは、あなたの思考様式(特にHoudini経験に裏打ちされた手続き的思考)と衝突し、深い考察を促しています。

  • 予測不能性へのフラストレーション: AIの応答が一貫せず、同じ指示でも結果が異なる「非決定性」は、ツールとしての信頼性を著しく損ないます。制御可能性と再現性を重視するあなたにとって、これは大きなストレス要因であり、根本的な課題です。
  • 非手続き的アプローチへの違和感: 問題解決プロセスがブラックボックス化し、「なぜそうなったのか」の追跡や根本原因の特定、体系的な改善が困難になる「非手続き性」。これは、あなたが慣れ親しんだデバッグや改善のサイクルを妨げ、技術を完全に掌握したいという欲求と相容れません。
  • ツールか、アシスタントか?:AIの適切な位置づけ: この課題認識から、「AI(MCP)は、厳密な指示通りに動くツールとして使うのではなく、意図を汲んで支援するアシスタントとして捉えるべきではないか?」という問いが生まれています。アシスタントであれば、ある程度の曖昧さや解釈の余地が許容されるかもしれません。しかし、アシスタントとしての適切な活用法は、あなたにとって未体験であり、模索すべき領域です。
  • プログラムとの使い分けの必然性: 上記の考察を踏まえ、「AIの持つ柔軟性や創造性は認めつつも、確実性・再現性が求められるタスクにおいては、従来のプログラム的なアプローチが必要であり、両者は明確に使い分けられるべきだ」という認識が、あなたの中でより強固になっています。AI(MCP)は万能ではなく、その特性を理解し、適材適所で活用することが極めて重要です。
  • AIの柔軟性・創造性の価値と限界: ニッチな課題への対応力やプロトタイピングの速度といったAIの利点は認めつつも、それはあくまで「使い分け」を前提とした上での評価です。その価値を最大限に引き出すには、適用すべき場面とそうでない場面を見極める眼が不可欠となります。

4. 結論:未来への探求心を刺激する、可能性と課題を併せ持つ「面白い技術」
あなたはMCPを、「USBのように誰もが使う標準規格になる」と確信しているわけではありません。むしろ、その根源的な課題(非決定性・非手続き性)を冷静に見据え、現時点では 「普遍的な解決策」ではなく、「特定の文脈で興味深い可能性を持つ技術」 と捉えています。

  • MCPは、システムとの関わり方を変えるポテンシャルを秘めた、知的好奇心を強く刺激する「面白い技術」 です。
  • しかし、その特性(特に非決定性と非手続き性)は、多くの場面で従来のプログラムによるアプローチの信頼性や制御性には及ばないという現実があります。
  • したがって、現時点でのMCPの価値は、その限界を認識した上で、プロトタイピング、ニッチな連携、アシスタント的な活用といった特定の領域で探求されるべきものです。
  • この未知の領域を探求し、MCPとAIの適切な役割や活用法を見出していくプロセスそのものに、あなたは強い動機と未来への関心を抱いていると言えるでしょう。「夢」というよりは、現実的な課題を踏まえた上での「知的な探求」なのです。
5

Discussion

ログインするとコメントできます