6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MayaからHoudiniへ:Alembicを書き出してそのまま読み込む仕組み

Last updated at Posted at 2025-12-15

はじめまして。
今回、Houdini Advent Calendar に初参加します。

普段は CG 制作をしていますが、
Pythonについては最近勉強をし始めた初心者です。

今回は、
Python を使って、毎日の作業を少しだけ楽にした話
を書いてみようと思います。

テーマは、

Maya → Alembic → Houdini

この受け渡しを、できる範囲で自動化してみた
という内容です。

Python に詳しくなくても、「こういう考え方で自動化できるんだ」という雰囲気が伝われば嬉しいです。


この記事でやっていること

今回やっているのは、主にこの2つです。

  • Maya

選択したオブジェクトを
オブジェクトごとに Alembic(.abc)として書き出す

  • Houdini

Houdiniを起動
起動時に Alembic をまとめて読み込む

※注意点
最初にalembicにしたいオブジェクトを選択しておく必要があります。(複数選択可)親ノードを選択した場合、その配下は1つのabcにまとめて書き出されます。


Maya側:選択オブジェクトを自動で Alembic 書き出し

まずは Maya 側です。

このスクリプトのポイントは以下の通りです。

・選択しているオブジェクトを取得

・タイムライン範囲をそのまま使う

・選択オブジェクトごとに1ファイルずつ abc を出す

・ファイル名に 日時スタンプ を付ける

# -*- coding: utf-8 -*-
import maya.cmds as cmds
import os
import datetime

def export_selected_to_abc_auto():
    # 選択チェック
    sel = cmds.ls(sl=True, long=True)
    if not sel:
        cmds.warning(u"オブジェクトが選択されていません。")
        return

    # タイムラインのフレーム範囲
    start = cmds.playbackOptions(q=True, min=True)
    end   = cmds.playbackOptions(q=True, max=True)

    # 書き出し先フォルダのみ選択
    folder = cmds.fileDialog2(
        caption=u"Alembicを書き出すフォルダを選択",
        fileMode=3
    )
    if not folder:
        return
    folder = folder[0]

    # AbcExport プラグインチェック
    if not cmds.pluginInfo("AbcExport", q=True, loaded=True):
        cmds.loadPlugin("AbcExport")


    # 日時スタンプ(全ファイルで共通)
    now = datetime.datetime.now()
    stamp = now.strftime("%Y%m%d_%H%M%S")

    # 危険文字除去
    def safe_name(name):
        invalid = ['|', ':', '/', '\\', '*', '?', '"', '<', '>', ' ']
        for c in invalid:
            name = name.replace(c, '_')
        return name

    # ★ 選択したオブジェクトごとに 1 ファイルずつ書き出す
    for node in sel:
        # obj の名前だけ
        short_name = safe_name(node.split("|")[-1])

        # ファイル名: base_scene + obj名 + timestamp
        file_name = "{}_{}.abc".format(short_name, stamp)
        file_path = os.path.join(folder, file_name).replace("\\", "/")

        # Alembic job(この obj のみ書き出し)
        job = (
            '-frameRange {start} {end} '
            '-uvWrite -worldSpace -writeVisibility -dataFormat ogawa '
            '-root "{root}" -file "{file}"'
        ).format(
            start=start,
            end=end,
            root=node,
            file=file_path
        )

        print(u"[AbcExport] " + job)
        cmds.AbcExport(j=job)

    cmds.confirmDialog(
        title=u"完了",
        message=u"選択オブジェクトを {} 個のABCとして書き出しました。".format(len(sel)),
        button=["OK"],
        defaultButton="OK"
    )


# 実行
export_selected_to_abc_auto()


このスクリプトの使いどころ

キャラ・プロップを 個別に Houdini に持っていきたい

後工程(FXなど)で オブジェクト単位で扱いたい

名前衝突を避けたい

というケースで便利です。


Houdini側:起動して Alembic をまとめて読み込む

次は Houdini 側です。

ここでは、

Maya から Houdini を起動

起動時にだけ実行される 456.py を一時的に作成

Alembic を選択 → 読み込み → 繰り返し

読み込み後、456.py を削除

という流れにしています。

Mayaから Houdini を起動するコード

# -*- coding: utf-8 -*-
import os
import subprocess
import maya.cmds as cmds

def launch_houdini_with_geo_once():

    # =========================================================
    # ★ ここは環境によって変更が必要(Houdiniのインストール先)
    # =========================================================
    HFS = r"C:\Program Files\Side Effects Software\Houdini 20.0.547"   # ★
    houdini_exe = os.path.join(HFS, "bin", "houdini.exe")              # ★(通常はHFSでOK)

    if not os.path.exists(houdini_exe):
        cmds.error(u"Houdini が見つかりません: {}".format(houdini_exe))
        return

    # =========================================================
    # ① Maya のダイアログで .hip を選ぶ(環境依存なし)
    # =========================================================
    hip_file = cmds.fileDialog2(
        caption=u"開きたい Houdini .hip ファイルを選んでください",
        fileFilter=u"Houdini Scene (*.hip *.hiplc *.hipnc)",
        fileMode=1
    )
    if not hip_file:
        cmds.warning(u"キャンセルされました。")
        return
    hip_file = hip_file[0]
    print(u"選択された HIP:", hip_file)

    # =========================================================
    # ★ ここは環境によって変える可能性あり(Houdiniのユーザ設定フォルダ)
    # 例:ドキュメント位置が違う/バージョンが違う/カスタム設定
    # =========================================================
    user_root = os.environ.get("USERPROFILE") or os.path.expanduser("~")
    HOUDINI_VER_DIR = "houdini20.0"                                    # ★(例:houdini20.5 等)
    scripts_dir = os.path.join(user_root, "Documents", HOUDINI_VER_DIR, "scripts")  # ★

    if not os.path.isdir(scripts_dir):
        os.makedirs(scripts_dir)

    startup_script = os.path.join(scripts_dir, "456.py")               # ★(基本はそのまま)

    # =========================================================
    # ③ 起動時に一度だけ実行する処理(中身は基本そのままでOK)
    # =========================================================
    houdini_code = (
        "import hou\n"
        "import os\n"
        "\n"
        "def import_multiple_abc_loop():\n"
        "    obj = hou.node('/obj')\n"
        "    count = 0\n"
        "\n"
        "    while True:\n"
        "        abc_path = hou.ui.selectFile(\n"
        "            title='Select Alembic (.abc)',\n"
        "            pattern='*.abc'\n"
        "        )\n"
        "\n"
        "        if not abc_path:\n"
        "            break\n"
        "\n"
        "        abc_path = hou.expandString(abc_path)\n"
        "        name = os.path.splitext(os.path.basename(abc_path))[0]\n"
        "\n"
        "        arch = obj.createNode('alembicarchive', 'abc_' + name)\n"
        "        arch.parm('fileName').set(abc_path)\n"
        "        arch.parm('buildHierarchy').pressButton()\n"
        "        arch.moveToGoodPosition()\n"
        "\n"
        "        count += 1\n"
        "\n"
        "        res = hou.ui.displayMessage(\n"
        "            f\"Loaded: {abc_path}\\n\\nLoad another Alembic?\",\n"
        "            buttons=('Continue', 'Finish'),\n"
        "            default_choice=0,\n"
        "            close_choice=1\n"
        "        )\n"
        "\n"
        "        if res != 0:\n"
        "            break\n"
        "\n"
        "    hou.ui.displayMessage(f\"Loaded {count} Alembic files.\")\n"
        "\n"
        "# auto run\n"
        "import_multiple_abc_loop()\n"
        "\n"
        "# =====================================================\n"
        "# ★ ここは環境によって変える可能性あり(削除する456.pyのパス)\n"
        "# HOUDINI_VER_DIR と合わせる\n"
        "# =====================================================\n"
        "script_path = hou.getenv('HOME') + '/houdini20.0/scripts/456.py'  # ★\n"
        "try:\n"
        "    os.remove(script_path)\n"
        "except:\n"
        "    pass\n"
    )

    with open(startup_script, "w") as f:
        f.write(houdini_code)

    print(u"一時スクリプト作成:", startup_script)

    # =========================================================
    # ④ Houdini を指定した .hip で起動
    # =========================================================
    env = os.environ.copy()
    env["HFS"] = HFS  # ★(基本はそのままでOK)

    subprocess.Popen([houdini_exe, hip_file], env=env)

# 実行
launch_houdini_with_geo_once()

※★マークの部分は、
使用している Houdini のバージョンやインストール先に合わせて変更してください。


以上二つのコードを上から順にそのまま Maya の Script Editor(Python)にコピペして実行すると使えます。
※maya2020で動作確認済み


おわりに

今回は、
Maya → Alembic → Houdini の流れを、
自分なりにpythonで整えた例を紹介しました。

まだ改善できる点は多いですが、
誰かの作業時間を減らすヒントになれば嬉しいです。

ここまで読んでいただき、ありがとうございました。

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?