BLOG

RECENT ENTRY

ARCHIVES

カテゴリー別 : 社内イベント

FBXデータでのよくある…”罠”

こんにちは!
Development Div. 所属テクニカルアーティストのHです。
GWも終わり、何となく長く感じた通常モードの1週間も今日で終了💻
気持ちを切り替えて来週からも頑張りましょう💪

さて、今回は筆者自身が今でも時々引っかかってしまう
ちょっとした“罠”についてのお話です。
「これ、自分だけじゃないよね…?」
と、共感してもらえたら嬉しいです:)
——————————————–

MotionBuilderやゲームエンジンとの連携で、
スケルトンとジオメトリだけの
“素”のFBXアセットを扱うことがあります。

例えば、MotionBuilder用に出力されたアセットを
わざわざMotionBuilderで開くことが手間に感じる場合や
Mayaで十分に作業ができると判断した時に
Mayaで開く…という場面、ありませんか?

そんな時、思わぬ“罠”に嵌ることがあります。

こちらは弊社のオリジナルキャラクター
アニマちゃんのFBXです↓

あれ、、?スカートにボーン(骨)が入っていません。

この状態を見た時、こう思ってしまうかもしれません・・↓

「まだボディのアニメーション作業用のLODなのかな?」
「データを開いてみたけど、スカートのボーンが来ていない。何か不具合かも?」
「アサインされたばかりで状況がよく分からないけど、
 今はまだ自分が作業できる段階じゃないのかも?」
「アセットがおかしいのかもしれない。正しいデータかSVに確認しなきゃ!」

…等々

これらの判断は、プロジェクトの体制や
担当範囲によってはごく自然なものだと思いますし、
実際にその様な状況の可能性もあるでしょう。
が、実はもっと単純な理由かもしれません…!
「アセットの一部のボーンが非表示設定になっているだけ」
というケースがあります。

MotionBuilder側でグループ設定されたり、
作業中に一部のジョイントを非表示にしていた結果、
そのままFBXとして出力され
Mayaで開くと——

見た目上はボーンが存在しない様に見えることがあります。
この場合、drawStyleがNoneになっているだけで
実際には、ボーンはきちんと存在しています。
Visibility設定ではなく、drawStyleという
別のパラメータによって見えなくなっているのです。


この設定を“bone”に変更すれば通常通りボーンが表示されます👀

…はい、そうです。
これはもう、罠⚠

そしてこの罠、なかなか厄介なんです。
何が厄介かというと、

・特定のボーン構成だと、見事にその部位だけボーンが「無い」様に見える
・色々と状況を深読みしてしまう
・MotionBuilderでは全ノードがスケマティックビューで俯瞰できるが
 Mayaのアウトライナでは展開しないと見えない
・Visibilityでもビューポート設定でもなく、第三の方法で非表示になっている
・そもそもdrawStyleという属性の存在を知らないと気付けない

上記の様な要素が重なり、非常に引っかかりやすいのです💦

対処方法(Pythonスニペット)
この問題は、以下のようなスクリプトで簡単に解決できます。
シーン内の全てのジョイントのdrawStyleを“bone”に設定するものです。
——————————————
import maya.cmds as cmds

joint_lst = cmds.ls(type=’joint’)
for joint in joint_lst:
     plug = ‘{}.drawStyle’.format(joint)
     cmds.setAttr(plug, 0)
——————————————
drawStyleはチャンネルボックスに表示されないため、
複数のボーンを選んで手動で一括変更することはできません。
そのため、現実的にはスクリプトでの対応が最も効率的です。

まとめ
しっかり整備されたパイプラインでは、
こういったケースは発生しにくいかもしれません。
しかし、TAが先行してテストをする際や手動でデータを扱う場面では
思わぬタイミングでこの罠にかかってしまうこともあると思います。

皆さんも、似た状況に遭遇した際は
このdrawStyleの存在を思い出してみてください!

最後までお読みいただきありがとうございました*
それではまた次回👋

Shot Div. FX(エフェクト)Dept. について

本日はあいにくの雨ですが…☔
暖かい気温の日が増えてきたこの頃。
4月に新生活が始まった方も、
少しずつ色々なことに慣れてきた頃ではないでしょうか?

さて今回は、筆者の所属する
Shot Div. FX(エフェクト) Dept. の紹介記事です✍
エフェクトアーティストという職種に興味を持っていただけると幸いです◎

【業務内容】
FX Dept. では、主にHoudiniNukeを使用して、
魔法・オーラ・爆発・流体 etc…様々なエフェクトを制作しています。
プロジェクトによっては、Mayaを使用することもあります。

【スケジュール(一例)】
■業務開始(11:00〜)
FXアーティストは基本的にテレワークが中心です。
Parsec(※)を使用してリモート環境にアクセスし
Zoomやチャットツールを通じて
チームメンバーとコミュニケーションを取りながら作業を行っています。
※アニマで使用しているリモートデスクトップツール

■昼休憩(13:00〜14:00)
基本的にはこの時間帯に休憩を取ります。
簡単なものを自炊することが多いですが、
たまにプチ贅沢でデリバリーを利用することもあります*

■作業再開(14:00〜)
休憩後は作業の続きに取り組みます。
スケジュールに遅れが出ないことを優先し、
適度にストレッチや短い休憩を挟みながら
集中力を保つようにしています。

■業務終了(20:00)
基本的には20時過ぎには作業を終えるようにしています。
プロジェクトの進行状況や
その日の作業内容によって終了時間が前後することもあります。

【その他の業務について】
会議の頻度はプロジェクトによってまちまちですが、
毎週金曜日にはチームの定例会があり、
そこで各々の進捗報告や情報共有を行っています。

チーム内では定例会以外にも日頃から
連絡・相談・技術的なTIPSの共有等を活発に行っています。
最近の共有は「ボリュームのレンダリング負荷を軽減するための基本TIPS」についてでした。
以下の設定に気を付けることで、パフォーマンスの最適化が可能になります。

・不要なボリュームは出力しない
・VDBに変換する
・16bitで出力する
・velのResampleを行う

【作業の進め方】
最初に絵コンテや前後のカットを確認し、
作業のイメージをしっかり固めた上で、必要な資料を集めます。
曖昧なまま作業を始めると、結果的に時間がかかってしまうため
事前準備を大切にしています。
また、リズムやタイミングを意識しながら
複数のアプローチを持って臨むことを心がけています。

以上、FX Dept.についての紹介でした。
最後までお読みいただき、ありがとうございました:)

★中途エフェクトアーティスト募集中★
応募条件&応募はコチラ

Mayaのスクリプト紹介

こんにちは!
Development Div./Rig Dept. 所属のIです。
筆者は毎年この時期は花粉に悩まされています…が、
皆様はいかがお過ごしでしょうか?🤧

さて、今回は『Mayaのコンストレインを
効率化するスクリプト』をご紹介します!

アニマのリグ作業は基本的に、
mGearでカスタムステップを用いたワークフローです。
そのため、mGearコンポーネントだけではセットアップできない部分を
全てスクリプトに落とし込む必要があります。
コンストレインもその一つなのですが、過去には知識不足から
無駄な工程を多く含んだスクリプトを書いてしまったことも…😢

そこで今回は、そのリベンジも兼ねてフリップ対策を学びつつ、
汎用性が高く誰でも使いやすいスクリプトの作成を目指しました💪
※このスクリプトは複数の親からのコンストレインを適用するケースを想定しているため
「”parentA~Z”と”childA~Z”を1対1でコンストレインしたい」等の状況には不向きです。

興味のある方はお使いのスクリプトエディターに
コピー&ペーストしてご活用ください◎
————————————————–
import pymel.core as pm

def addNPO_alt(targetNode):
targetNode_p = pm.listRelatives(targetNode, p=True)
npoNode = pm.group(em=True, n=targetNode+”_npo”)
if len(targetNode_p) != 0:
pm.parent(npoNode, targetNode_p[0])
pm.matchTransform(npoNode, targetNode, pos=1, rot=1, scl=1)
pm.parent(targetNode, npoNode)
pm.select(cl=True)

# interpType -> 0 == No Flip, 1 == Average, 2 == Shortest, 3 == Longest, 4 == Cache
# skip -> None, “trans”, “rot”
def interpConst(parentList, childList, weightList, interpType=1, skip=None):
for child, weight in zip(childList, weightList):
tagC = pm.PyNode(child)
tagC_p = pm.listRelatives(tagC, p=True)
constC = pm.group(em=True, n=tagC+”_constC”)
if len(tagC_p) != 0:
pm.parent(constC, tagC_p[0])
pm.matchTransform(constC, tagC, pos=1, rot=0, scl=0)
pm.parent(tagC, constC)
addNPO_alt(constC)
for parent in parentList:
tagP = pm.PyNode(parent)
if len(pm.ls(tagP+”_constP”)) == 0:
constP = pm.group(em=True, n=tagP+”_constP”)
pm.matchTransform(constP, tagP, pos=1, rot=0, scl=0)
pm.parent(constP, tagP)
addNPO_alt(constP)
else:
constP = pm.PyNode(tagP+”_constP”)
const = pm.parentConstraint(constP, constC, mo=True)
pm.setAttr(const.interpType, interpType)
parentLength = len(parentList)
for i, w in zip(range(parentLength), weight):
pm.setAttr(const+”.w{}”.format(int(i)), w)
if skip == “trans”:
pm.disconnectAttr(const+”.ctx”, constC+”.tx”)
pm.disconnectAttr(const+”.cty”, constC+”.ty”)
pm.disconnectAttr(const+”.ctz”, constC+”.tz”)
elif skip == “rot”:
pm.disconnectAttr(const+”.crx”, constC+”.rx”)
pm.disconnectAttr(const+”.cry”, constC+”.ry”)
pm.disconnectAttr(const+”.crz”, constC+”.rz”)

parentList = [“parentA”, “parentB”, “parentC”]
childList = [“childA”, “childB”, “childC”, “childD”, “childE”, “childF”, “childG”, “childH”, “childI”]
weightList = [[0.88, 0.08, 0.04], [0.73, 0.18, 0.09], [0.57, 0.29, 0.14],
[0.41, 0.39, 0.20], [0.25, 0.50, 0.25], [0.20, 0.39, 0.41],
[0.14, 0.29, 0.57], [0.09, 0.18, 0.73], [0.04, 0.08, 0.88]]

interpConst(parentList, childList, weightList, interpType=0, skip=None)

————————————————–

【スクリプトの使い方】
編集が必要な部分は、parentList = [“parentA”, “parentB”, “parentC”] の行からです。

1. 親ノードの設定
parentList には、コンストレインの「親」となるノードの名前をリストで記入する。
1つ以上のノードを設定でき、多くの親ノードを指定することも可能です。

2. 子ノードの設定
childList には、
指定した親ノードから影響を受ける 「子」 ノードの名前をリストで記入する。
こちらも0でなければ個数の制限はありません。

3. ウェイトの設定
weightList には、親ノードから受ける影響の強さ(ウェイト)を設定する。
このリストは 「親の数 × 子の数」 の多重リストになっており、
parentList に記載した順番と対応させる必要があります。

4. interpType(回転の補間タイプ)の設定
interpType の値を変更することで、
コンストレインの回転補間の挙動を調整できます。
デフォルトは 1(Average)ですが、
おすすめは「0」(No Flip) です。
特にフリップが起こりにくいため、安定した挙動が期待できます。
このスクリプトでは、コンストレインを適用する
ノードの軸が揃う様にワールド軸のnullが生成されるため、
デフォルトの 1(Average) でも180度までは概ね問題ありません。

5. skip(除外設定)の活用
skip には、None・”trans”・”rot” の3種類があります。
None(デフォルト) → すべてのコンストレインを適用
“trans” → 移動のコンストレインを無効化
“rot” → 回転のコンストレインを無効化
あまり使用する機会は少ないかもしれませんが、
特定の動作を抑制したい場合にご活用ください。
————————————————–

以上、Mayaのコンストレインを効率化するスクリプトの紹介でした!
皆様の参考になれば幸いです:)