KineFX/APEXをめぐる混乱を個人的に整理した記録

これはHoudiniApprenticeAdventCalenderの2024/12/18の記事です。

### 実行環境と注意事項
Windows11 Houdini 20.5.389　Educational License
APEXはまだベータですのでヴァージョン情報にはご注意ください。
また、ライセンス形態によっても挙動が微妙に異なることがあるようです。
この記事の内容はKineFX/APEXの正式リリース以降は間違った情報となる可能性があります。

## 自己紹介と対象読者
こんにちは。私は元グラフィックス・エンジニアで、現在は大学教員をしています。Houdiniは触れるけどキャラクター・アニメーションはやったことがない、SideFXがKineFX/APEXでキャラクター・アニメーションに注力しているのは知っている、公式ドキュメントはまだ整備されていないけどベータ版のうちに触っておくかなあ、と私とおなじようなテンションでKineFX/APEXを見ている方を対象に記事を書きます。もちろん、詳しい方にも読んでいただき、ツッコミ、アドバイス、勉強会へのお誘いなどいただけると大変ありがたいです。

## 動機
Houdini20.0で[**グラフを使ってAPEXリグを生成・編集するAPEXGraph**](https://www.sidefx.com/docs/houdini/character/kinefx/apexgraphbasics.html)が導入されました。私はSOPより粒度が細かいグラフ編集は苦手でコードを書く方が好きなので、20.0まではAPEXリグを敬遠してました。ですが、Houdini20.5からグラフではなく[**コードでAPEXリグを生成・編集するAPEXScript**](https://www.sidefx.com/docs/houdini/character/kinefx/apexscriptgraphs.html)が導入されたことで、APEXリグに本格的に取り組むことにしました。

まだベータということもあり、あまり情報がなく、進捗は芳しくありません。そんなおり、[APEXGraphを直接編集してリグを作成するMaxさんの動画](https://www.sidefx.com/tutorials/kinefx-create-a-ball-rig-using-apex/)に対して、その動画と同じことを[APEXScriptでコードを書いてリグを作成するCameronさんの動画](https://www.sidefx.com/tutorials/effective-apex-scripting/)がアップされました。同じロジックをグラフとコードの両面から分析することで、飛躍的にAPEXリグの理解が深まるという事がわかり、大変感銘を受けました。

正直なところ、私はある一定以上複雑なグラフを見ると思考停止してしまうので、努力不足を情報不足と言い換えていたかもしれません。Cameronさんのやり方を知ってからはAPEXリグ解析に弾みがつき、現在はMixamoからダウンロードしたキャラクターにリグをつけたい学生用にElectraのリグを適用するHDAを作るくらいはできるようになりました。

![Animation2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/b6e2549f-d06c-a42a-f491-2833f63c548f.gif)

しかし、この程度のことを理解するのにも時間がかかるくらいKineFX/APEXをめぐる状況は混乱しています。この混乱を自分なりに整理した経験を、ベータのうちにAPEXリグを始めようという人に向けて記事にすれば有意義かもしれないと思い、この記事を書くことにしました。


## KineFXリグはどうなった？
最初の混乱はこれですよね。公式にもこのあたりの[歴史的経緯](https://www.sidefx.com/docs/houdini/character/kinefx/overview.html#a-bit-of-background)に関して記述がありますが、[SiggraphAsia2024のHive](https://www.sidefx.com/ja/houdini-hive/siggraph-asia-2024/)でも[この記事](https://qiita.com/jyouryuusui/items/e897a239921f4bf9a6cd)にあるようなKineFXリグのさらに前身であるOBJリグまで遡ったとてもわかりやすいレクチャーが管理人様からありました。ユーザーの混乱が解消すると思いますので、SideFX様には是非アーカイブ配信していただきたいです。([配信](https://www.youtube.com/watch?v=9BJTN_MeLX4)されました。Jan.2025）

私の理解では[KineFX](https://www.sidefx.com/docs/houdini/character/kinefx/index.html)というのはファー、クロース、リジッドボディといったHoudiniが得意なシミュレーションと手付けのキーフレーム・アニメーションをシームレスに連携できる新しいアニメーション・ワークフローの名前です。

このワークフローの中の**KineFXリグがAPEXリグに置き換わっていく**流れなのだと思います。ぱっと見ではKineFXリグはSOPグラフでプロシージャルにリグを構築していくことができる良いシステムだと思ったのですが、何が問題だったのでしょう？

KineFXリグでは、SOPグラフのあちこちに散在するRigPoseSOPを順番に評価してアニメーションします。先述の通り、KineFXリグはSOPグラフでリグの構造を表現するので、RigPoseSOPを評価するということは**リグの評価・計算とリグの構築が同時に行われる**ことになります。リグの性質上これらを並列計算するわけにはいきません。結果、複雑なリグを何体も同時にアニメーション編集するような状況では重くて動かないそうです。

:::note info
よく[参考にさせていただいている動画](https://www.youtube.com/watch?v=u07d33mL4r8)でもRigPoseSOPがKineFXリグのボトルネックだと結論付けています。
:::

## APEXリグでどう変わった？
新しく導入されたAPEXリグでは、**リグ構築フェーズとリグ評価・計算フェーズを分離する**ことに主眼が置かれています。APEX系のSOPはリグ構築用とリグ評価・計算用で完全に分かれています。ですのでリグ構築用のSOPがいくつか続いた後にリグ評価計算用のSOPが来るというパターンが崩れることのない、直線的で作業フェーズがわかりやすいSOPグラフに自然となります。

この記事では、まず、簡単なAPEXリグの実例をコメント付きでざっと見ていただき、各フェーズにまつわる混乱を整理していきたいと思います。サンプルとしてチューブに骨を入れて、ウェイトをつけて、あらかじめ用意されているリグ部品を３つ使ってAPEXリグを構築して、最後にアニメーションを編集する、ミニマルなSOPグラフを作りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/3f60fdef-fc28-37a5-cdab-bbb4cf726d88.png)

注目していただきたいのは複数のAPEXAutoRigComponentSOPでプロシージャルに少しづつリグを構築しているリグ構築フェーズと、一つのAPEXSceneAnimateSOPでアニメーション編集の全てを担うリグ評価・計算フェーズです。とてもシンプルで直線的な流れですよね。リグというとMayaのDGスパゲッティをイメージする私は「このSOPグラフのどこでリグの構造が表現されているのだ？」とシンプルすぎてかえって混乱しました。

実は**SOPグラフにリグの構造が現れるKineFXリグとは異なり、APEXリグではSOPよりひとつ下のレイヤーにあるAPEXGraphでリグの構造を表現**しています。APEXGraphは、APEX系のSOPによって生成・編集されてはワイヤーを流れて行くジオメトリのようなものです。（実際、パックされたジオメトリです）サンプルのSOPグラフが生成・編集したApexGraphを視覚化するとこのようになります。たった３つのSOPですが、MayaのDGに勝るとも劣らない立派なスパゲッティができていて、初めて見たときは妙に安心しました。これならリグの構造を表現できそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/3b80886b-c5da-30fe-8ad6-dbe4d118d56d.png)




このように操作する側とされる側でネットワークのレイヤーを分けたことで、SOPグラフは単にリグ構築手順書になりました。APEXGraphがどんなに複雑になってもSOPグラフは直線的でシンプルなままです。例えば、これは先述のMAXさんの動画を参考に作った本格的なBipedリグです。いろいろな機能が追加されていますが、SOPグラフが直線的に長くなっているだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/c30af819-b827-630b-d9c1-959274b6d85e.png)

なお、ここまで見てきた事例のように[TAGなどのメタデータ](https://www.sidefx.com/docs/houdini/character/kinefx/graphmetadata.html)と[純正リグ部品](https://www.sidefx.com/docs/houdini/character/kinefx/rigcomponents.html)を活用した**モジュラー・リギングをするだけならAPEXGraphについて理解する必要はほとんどありません**。サンプルのようにSOPをいくつかつなげるだけでリギングを完結できます。このあたりはリグを量産したり、アニメーションのリターゲティングといったシチュエーションを最初から想定しているのだと思います。

:::note info
私はなんとなく、**KineFXリグはインタープリター言語、APEXリグはコンパイル言語**といったイメージで捉えています。お気楽なインタープリター言語に比べると、コンパイル言語にはあらかじめ理解しておかなければいけない概念が多いですが、APEXリグにもそれがあてはまります。ある程度、予備知識をつけてからでないと触ることができません。「とりあえずいじりながら理解する」はうまくいきませんでした。
:::

## APEXリグを理解するための予備知識

### APEXについて
今のところリグが主な適用事例になってますが、APEXはリグ専用ということではなくVEXと同じように各種コンテキストのオペレーターやヴューワー・ステートから呼び出せる[汎用グラフ評価フレームワーク](https://www.sidefx.com/docs/houdini//character/kinefx/apexgraphbasics.html)という位置づけのようです。その実体はPythonのapexモジュールです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/ab7f299e-5d65-0a99-6c60-3bf24a62e4f2.png)

リグの場合、APEXは例えば先ほどのSOPグラフの最後にあったAPEXSceneAnimateSOPのヴューワー・ステートに実装されています。ViewerStateBrowserでそのPythonソース・コードを確認することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/e1da2d36-c7be-32ae-347b-6b520c4abb1b.png)

勉強不足でapexモジュールを解析できていませんが、仮にその実体がC言語のPythonラッパーとかではなく普通のPythonコードならAPEXはコンテキスト・フリーに実装できそうです。実際、[SiggraphAsia2024のHive](https://www.sidefx.com/ja/houdini-hive/siggraph-asia-2024/)でもリグ以外の様々なコンテキストでバイオームやヴォリュームのためにAPEXを使っているという報告がありました。「All Purpose Execution」は伊達じゃなさそうです。

:::note info
このあたりのAPEXの汎用性や将来性に興味があるという方はぜひ、[amaterasu様の記事](https://qiita.com/amateras/items/e576dcb144390407b74b)をご一読ください。APEXリグはもちろん、APEXそのものについて深堀されていてとてもわかりやすいです。
:::

### APEXGraphについて

APEXは「汎用グラフ評価フレームワーク」と言いましたが、この評価対象である「汎用グラフ」がAPEXGraphです。APEXにAPEXGraphを入力すると何かしらの出力が得られるというわけです。ひとまずAPEXをプログラム実行環境、APEXGraphをプログラムと考えて問題ないと思います。（ちょっと語弊があります。あとで修正します）APEXGraphは、例えば、APEXEditGraphSOPでAPEXNetworkViewを表示して作成・編集できます。

![Animation2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/d1eb9d6f-61cf-2745-edb1-49be6bc96782.gif)

APEXGraphの実体はパックされたジオメトリーです。APEXGraphのノードとエッジを、ジオメトリのポイントとラインプリミティブでそれぞれ表現します。ポイント・アトリビュートの形でさまざまなデータを保持しておき、ラインプリミティブのトポロジーでそのデータ・フローを表現するという感じです。

:::note info
単なるジオメトリでもあるので、ひとつのAPEXGraphを

* ジオメトリとしてSceneViewに表示（上段）
* APEXGraphとしてAPEXNetworkViewで表示（中段）
* ジオメトリとしてSpreadSheetに表示（下段）

などさまざまな形で視覚化することができます。
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/24ebf4b1-f70e-5fc8-2a79-ad77ac7feaa5.gif)
:::

前述の通り、私は上図中段のAPEXNetworkViewのように一つのノードからたくさんエッジが出ているグラフが苦手です...

### APEXScriptについて

同じように感じる人が多かったのかわかりませんが、VEXにVOPGraphとVEXCodeがあるように、Houdini20.5以降のAPEXにも[APEXGraphとAPEXScript](https://www.sidefx.com/docs/houdini/character/kinefx/overview.html#building-rigs-in-apex)が用意されたのでグラフ編集が得意な人は前者を、コード編集が得意な人は後者を選べるようになりました。具体的にはAPEXScriptSOPにAPEXScriptを記述するとそれがAPEXGraphに変換されていきます。

![Animation2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/172f0855-29a1-952d-3fdc-815aec91f127.gif)

おそらくは先にどちらがあったかの違いでVEXの場合はVOPGraphがVEXCodeに変換されるのに対して、APEXの場合はAPEXScriptがAPEXGraphに変換されますが、グラフとコードで同じことができるのはVEXと同様です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/3d4055d0-f256-e4d5-2907-e440ca3cdfa3.png)

:::note info
ScriptがGraphに変換されると言いましたが、その逆も一応できます。ただし、この機能の主な目的は開発やデバッグではないかと思います。例えば私の場合はAPEXGraphで提供されている純正リグコンポーネントを解析するために、APEXScriptのDecompile機能をよく使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/c279337a-e0d7-f578-7cac-81c3fe21034a.png)

:::


さて、混乱の一つめです。**APEXScriptは型情報つきのPythonのように見えますがPythonではありません**。APEXが（おそらく）Pythonで書かれているのでAPEXScriptもPythonのように思ってしまうのですが、**APEXScriptはあくまでもAPEXGraphを生成・編集するための独自言語**です。

さらに混乱するのですが、その**独自言語をパース＆実行するのはAPEXScriptSOPの実体であるHDA内にあるPythonSOP**です。もう笑うしかない。中身を見てみると入力されたAPEXScriptをPythonSOPでパースしていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/3b67cbd6-c667-e5e6-51ed-87c53593822a.png)

なぜこんなことをするのでしょう？それはおそらく変換先である**APEXGraphがPythonよりも表現力が低い**ため、APEXScriptには素のPythonにはない以下のような制限があるためです。

* 辞書型のキーには[文字列型以外は使えません](https://www.sidefx.com/docs/houdini/character/kinefx/apexscriptlanguage.html#dictionaries)
* 配列型には[１種類の型しか格納できません](https://www.sidefx.com/docs/houdini/character/kinefx/apexscriptlanguage.html#arrays)

まだまだありますが、ApexScriptSOPは入力されたコードがこれらの制限を守っているかチェックして、問題がなければAPEXGraphに変換、問題があればエラーで停止するということをしなければならないのです。

:::note info
実用上APEXGraphの表現力に問題があるとは感じませんが、Pythonの表現力になれてしまっているので上記の制限を忘れてしまいがちです。特に、APEXScriptSOPと並行してPythonSOPも編集しているときなどは何度も引っかかって「なんで動かないんだ？」と気が狂いそうでした。似ているだけにやっかいです。
:::

### APEXScriptGraph？どっちやねん？

実はAPEXScriptを使わなくても、APEXGraph自身でAPEXGraphを生成・編集できます。エンジニアの方は**APEXにとってのAPEXGraphは、LISPにとってのリストのようなもの**と考えると良いかもしれません。プログラムとデータが同じ形をしているので、データを操作するのと同じやり方でプログラムも操作できます。

そして混乱が始まります。やっかいなことに公式リファレンスや動画では、APEXEditGraphのパラメーターを見てみるとわかるように、このような**プログラムとしてのAPEXGraphをScript**と呼称します。もちろん、これはAPEXScriptを指しているのではありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/bc271f9d-82b8-7ca0-1865-87c1f3ab58d5.png)

さらに混乱は続きます。まず、新しすぎてまだアイコンすらない哀れなAPEXScriptSOPの第２出力ポートにカーソルを合わせてみます。するとコンテキストヘルプが現れて**APEXScriptGraphが出力される**と書かれています。思わずどっちやねん？とツッコミたくもなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/9f7ec782-ec26-22a3-de05-a755e32cf8fd.png)

このあたり本当に混乱しました。20.0と20.5ではAPEX関係で出てくるScriptという言葉の意味が変わってくるからです。用語が統一されるまではScriptという言葉が何を意味するのか、文脈から判断するしかありません。

:::note info
以下の事を頭に入れておくと役に立つと思います

* APEXGraphはプログラムであり、データである
* どちらとして扱うかはSOPによって決まっている
* プログラムとして扱うAPEXGraphはScriptGraph,GraphScript,単にScriptと呼ばれる
* これらとAPEXScriptは別物。ただ、稀にAPEXScriptをこのように呼称する方もいる
* Scriptに入力するデータとしてのAPEXGraphはRigGraphなどと呼ばれる
:::


## APEXリグについて

ようやく本題です。それぞれのフェーズでの混乱を整理していきます。

### ジオメトリー作成フェーズ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/94739e75-bb07-ea9c-ad35-f02268e6c749.png)

最初の混乱はshapeでしょう。リグ構造の中にスキンが含まれるというのは、他のDCCツールに慣れた方には違和感があると思います。APEXリグでは**一つのオペレーターのヴューワー・ステートでアニメーション編集を完結させるという目的があり、そのために必要なデータを全てまとめたものをリグ構造としています**。

guidesは他のDCCツールでもスキン・バインド用の骨とコントローラー用の骨は分けるので混乱はなかったです。

:::note info
少し混乱するのは循環参照があるかないかという違いはありますが、**KineFXで導入されたジョイント・ベースのスケルトンとAPEXGraphのどちらもポイントとラインプリミティブからなるジオメトリ**というところでした。たまにどちらの話かわからなくなることがあります。
:::

### ストリーム変換フェーズ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/bbd09cfc-cd3b-b352-a18b-354e4c6dae19.png)

新しく導入された[APEXPackedCharacterFormat](https://www.sidefx.com/docs/houdini/character/kinefx/packedcharacterformat.html)については混乱はなかったと思います。最上位がシーン・フォルダー、その下にキャラクター・フォルダー、その中にシェイプ、スケルトン、リグなどをファイルとして置いておき、拡張子で種類を判別できるようにしたファイルシステムのようなデータストリームです。マニュアルにあるこの画像がわかりやすいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/602ae645-1eb4-367e-2adf-5afb9d3c062c.png)

::: note info
わからなかったのは、なぜこんな事をする必要があるのかということでした。これに関しては、先述の通り、APEXリグでは一つのオペレーターのヴューワー・ステートでアニメーション編集を完結させるという目的があり、必要なデータを全て一箇所に集める必要があります。これはそのために用意された仕組みなのだということに後で気が付きました。
:::

### リグ構築フェーズとリグ評価・計算フェーズ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/2f2c60ce-94d4-5890-a723-25fa405293db.png)

ここから先はAPEXの世界です。**キャラクター・ストリームを流れるBase.rigがAPEXリグそのものであり、その実体はAPEXGraph**だというのは良いと思います。

注意しなければならないのは、APEXGraphがプログラムとして扱われるのか、データとして扱われるのかはSOP次第という話です。**APEXAutoRigComponetSOPはBase.rigをデータとして**扱いますが、**APEXSceneAnimateSOPはBase.rigをプログラムとして**扱います。ここを理解するのにとても時間がかかりました。

#### APEXAutoRigComponentSOPの場合

 APEXリグは一からすべて自分でAPEXGraphやAPEXScriptで構築することもできますが、様々な[リグ・コンポーネントがAPEXAutoRigComponentSOPに用意されている](https://www.sidefx.com/docs/houdini/nodes/sop/apex--autorigcomponent.html#parameters)ので、いわゆるモジュラー・リギングが可能です。



リグ・コンポーネントはComponentScriptと呼ばれるプログラムとしてのAPEXGraphで与えられます。出ましたねScript。この言葉が出てきたら要注意でした。このComponentScriptはbgeoファイルとして読み込まれている事がComponentタブでわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/2c969f9f-7f7e-3b2e-3d7c-78e971767f2a.png)

Visualizerタブで設定をComponentScriptに変えて、読み込んだbgeoファイルをAPEXNetworkViewで見てみると、確かにComponentScriptがAPEXGraphであると確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/2b0c30ed-400e-e878-88ba-6717f3585d6c.png)

一方、APEXAutoRigComponetSOPに入力されるBase.rigはデータとして扱われます。これをプログラムであるComponentScriptに入力すると、必要なノードやエッジが追加されたBase.rigが返されるので、それをそのまま出力に流します。このようにしてAPEXAutorigComponentSOPをBase.rigが通過するたびにどんどんと機能が追加されていきます。

:::note info
私は、当初、Base.rigとComponentScriptのどちらもデータとしてのAPEXGraphで、それらを結合するのがAPEXAutoRigComponentSOPの役割なのだろうと思っていました。なぜかというと、ドキュメントや動画で「**リグ**が評価・計算されるのはAPEXSceneAnimateSOPだけ」という言説をよく耳にしていて、これを「**APEXGraph**が評価・計算されるのはAPEXSceneAnimateSOPだけ」と誤認していたからです。ここはリグでも、APEXGraphでもなく「**Base.rig**が評価されるのはAPEXSceneAnimateSOPだけ」と言ってもらえれば混乱がなくて良かったのになあと思います。
:::

#### APEXSceneAnimateSOPの場合

ここで最後の最後に入力である**Base.rigが初めてプログラムとして扱われます**。このプログラムはヴューワー・ステートからの入力に応じて、リグの評価・計算を行い、Base.skelのトランスフォームとBase.shpのデフォームを更新します。そこにキーフレームが設定されるというわけです。

また、パラメーターや入出力ポートの数を見てみるとわかりますが、ComponentScriptのようなAPEXGraphを使って**Base.rigを編集するということはここでは一切できません**。このようにして作業フェーズが混ざらないようにしているのだと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951962/9083e536-3843-143c-3172-7a15eb23b644.png)

::: note info
余談になります。私がアニメーション編集環境に疎いからかもしれませんが、APEXSceneAnimateSOPでのアニメーション編集は本当に画期的だと思います。様々なシミュレーションと手付けキーフレームが協調動作している様子には感動すら覚えます。おそらくAPEXリグは、このアニメーション編集環境を実現するために一から設計しなおされたAPEXSceneAnimateSOPありきのシステムなのだろうと思います。まだベータなのでバグがあって落とし穴満載ですし、Pythonなので速度的な限界は気になりますが、とても将来性を感じる魅力的なシステムだと思います。
:::

## まとめ

KineFX/APEXのAPEXリグについて、学習中につまづきやすいポイントを整理しました。KineFX/APEXは革新的なアニメーション編集環境であるため、他のDCCツールにはない概念を予備知識として理解しておかなければいけないこと、まだベータということで用語の統一がなされていないこと、これらに起因する混乱を自分なりに解消していった記録を記事にしました。


どなたかの参考になること、詳しい方にツッコミを入れていただけることを期待して筆をおきます。執筆の機会を頂き、ありがとうございました。