yslog

ゆるめに技術ブログかきます。Maya_Python

sinを自前計算してみた

またまた自前で計算してみたので記事うp。

さておなじみsinを自前で計算してみようってことで、とりあえずマクローリン展開してみましょう。

↓以下のような無限級数の和で表すことができます。

sinxのマクローリン展開

Σを展開すると以下のようになりますね。

(-1)^nによって1項ごとに符号が反転することに注意です。

sinxの無限級数の和

というわけでサクッと実装してみました。

gist506275694fd4e0895038c1ee338cdffd

 

数式で見るとなんだかややこしく感じますが、コードにすると思いのほかすっきりみえますね。

無限回足し合わせることはできないので今回は適当に99回で近似してます。

本家math.sinと比較してもばっちりあってそうです。

ちなみにcosは以下の式であらわされるので興味のある人は実装してみてください。

cosのマクローリン展開

ではー。

逆行列を自前で計算してみた

超久しぶりに記事うぷです。

掃き出し法で逆行列を計算してみたのでメモ。

 

gist5fdd4cdee8a4963df7b0e04d85842b79

 

現状正方行列のみの対応ですが、numpy使わずに4*4でも3*3でも逆行列計算できるようになりました。

やったぜ。

ちょっと誤差が出るのはご愛嬌ってことで・・・

 

 

MayaAPIのすゝめ 第4稿

MayaAPIのすゝめ 第4稿

みなさんお久しぶり。4回目のMayaAPIのすゝめです。

コマンドサンプル書くのがめんどくさかったので

前回から間が開いてしまいましたがようやくAPIのコマンド実装について触れていきたいと思います。

以前にも触れましたが基本的にMayaAPIで実行した処理は元に戻すの待ち行列に入らないので、コマンド化してUndo処理とRedo処理を自分で書いてやらないといけません。

まずは最低限で記述した簡単なサンプルで解説したいと思います。

※API1.0でも同様にかけますが今回はAPI2.0での実装となります。

↓こちら

MayaAPI2.0のコマンド作成サンプル

こちらを.pyファイルとして

C:\Users\[ユーザ名]\Documents\maya\plug-ins

に置くとカスタムコマンドとしてMayaに認識されます。(ない場合は自分でフォルダ作成)

f:id:ys_45:20190512230229p:plain

成功すればプラグインマネージャに現れますのでロードしてください。

f:id:ys_45:20190512230444p:plain

さてこのコマンド、まずはちゃんと動くか試してみましょう。

実行コマンドは

cmds.testCommand(w=list, nm=bool)

です。

 

試しに複数のバリエーションの引数でちゃんとアンドゥできるか実験です。

履歴が一つにまとまらないように一行ずつ実行してみてください。

cmds.testCommand(w=[0, 0, 0], nm=True)
cmds.testCommand(w=[1, 1, 1], nm=False)
cmds.testCommand(w=[2, 2, 2], nm=True)

f:id:ys_45:20190512231225p:plain

redoItに記述したprint文が出力されます。

では3回Undoしてみましょう。

f:id:ys_45:20190512231522p:plain

正しく逆順でundoItのprint文が出力されました。

ばっちりですね。

コマンド登録や引数の与え方はサンプル書き換えで簡単にできると思いますが、処理の実行系統がわかりにくいのでちょっと解説しておきます。

処理実行時に呼び出されたコマンドは今回の実装の場合

・doIt(実行関数の呼び出し)

parseArguments(引数を解析してクラスのメンバ変数に格納)

・redoIt(クラスのメンバ変数を参照して処理実行)

となっています。

重要なのはparseArgumentsでメンバ変数に格納しておくというところで、

Undo時は undoIt(self)

Redo時は redoIt(self)

のみが1回だけ呼び出されます。

この時に保有しているメンバ変数の値で実行されるようにしておくと正しくUndo/Redoできるようになります。

 

 

次回はコマンドを利用してウェイトエディタにUndo/Redoを実装していきたいと思います。

SIウェイトエディタでは引数として渡せない値の通信や処理の高速化のためにUI側のメンバ変数やグローバル変数のデータを利用してます。

Undo/Redo時にUIに値の反映するのはスクリプトジョブ使ってたり。

正直めっちゃめんどくさいです。

その辺の解説も(できれば)交えていきたいですね。

 

ではでは今回はこの辺で、アディオスアミーゴ。

 

 

MayaAPIのすゝめ 第3稿

MayaAPIのすゝめ 第3稿

早くも3回めとなりましたMayaAPIのすゝめ、今回もAPIではなくPySideの話です。
※次回はAPIに戻ります!

引き続き、ツールとしての現実的な実行速度を確保していきます。

さて前回では遅いQTableWidgetをView_Modelに置き換えて高速化を図りました。

TableWidget比で17倍とかなりの高速化を果たしましたが、ハイレゾなモデルのスキンウェイトを取り扱うにはまだ心もとない感じです。

低速な原因はQStandardItemModelを利用していることでした。
標準的な入出力を幅広くサポートしているためツールとしては不要な計算もされているようです。
今回はもっとプリミティブなクラス、QAbstractTableModelで置き換えて高速化を進めて行きます。
QAbstractTableModelはデータ管理クラスとしてはそのままでは使えません。
作りたいUIの仕様に合わせてカスタマイズしていく必要があります。

AbstractTableModelの実装サンプル

いろいろとできることがあるのですが、今回は導入ということでウェイトエディタに必要最小限な形で実装しました。
のがこちら↓

QAbstractTableModel Sample

初見だと??ってなると思うので(なりました
一つづつメンバ関数を見てみましょう。

 

・__init__(self)

コンストラクタ。
受け取った引数をひとまずメンバ変数に格納しておきます。


・headerData(self)※オーバーライド

ヘッダーの色やテキストを設定します。

ロールがQt.DisplayRoleならテキストを返すことで表示文字列を指定。
Qt.BackgroundRoleやQt.ForegroundRoleならQColorを返してやることで色を変更できたりもします。

・rowCount(self)※オーバーライド

全体の行数を返しておきます

・columnCount(self)※オーバーライド

全体の列数を返しておきます

・data(self)※オーバーライド

ここが表示データのすべて。

インデックスとロールに応じて適宜値やQColor、アラインメント等を返してやります。

・setData(self)※オーバーライド

テーブルが入力編集されたときの挙動を設定。

UI側のクラスにデータ変更をお知らせするためにdataChangedシグナルを忘れず送出してあげましょう。

・flags(self)※オーバーライド

セルごとに編集可否、選択可否、有効無効を設定してやります。
空セルや選択させたくないセルを指定したい場合には条件分岐してやりましょう。

・get_data(self)

こちらは今回唯一オーバライドでない独自実装。

UI側からデータを取り出したいときに使ってます。

といった感じで基本実装完了。

ツールに組み込んだ形はこんな感じになってます。

Sample Editor 4 MayaAPI2.0 + QTableView + QAbstrac ...

 速度計測

さっそく速度計測してみましょう✧+(0゚・∀・) + wktk

今回も引き続きXSI男さん(3段階変身)にご協力いただきます。

f:id:ys_45:20190420222104p:plain

前回の計測ではXSI_男_Perfectでテーブル表示に約2.8秒ほどかかってしまってました。

f:id:ys_45:20190418220257p:plain

同じモデルで今回は

f:id:ys_45:20190420222727p:plain

なんと約7ms!!
StandardItemModel比で400倍ほど早くなりました!

QTableWidgetと比べると6800倍!
これは余裕でヒャッハーできるレベルです。

複雑な処理をしてない分SIWeightEditorよりもはやいですね。

データ取得~テーブル表示までで合計約0.18sec

SIWeightEditorでは約0.32secでした。

試しにXSI男Ultimet(約81500頂点)でも試してみましょう。

f:id:ys_45:20190420223232p:plain

なんとそれでも0.023sec!

データ取得と合わせても0.65secほどです。
これは勝つりましたね。

これで速度面の憂いは絶たれました。

次回はMayaAPIに戻り機能面の拡張をしていきます。
APIで問題になるのがUndoRedoの実装。
こちらはコマンドをプラグイン化し、UndoRedoする仕組みを構築してやる必要があります。
サンプルを例にウェイト値のUndoRedoのデータ管理方法について触れて行きたいと思います。

ではでは今回はこの辺で。

MayaAPIのすゝめ 第2稿

MayaAPIのすゝめ 第2稿

前回はMayaCmdsのAPI化による高速化を紹介しました。

しかし速度的にはUIがボトルネックになりあまり実用的ではない実装となってしまっています。

今回はMayaAPIから話がずれますが、UIの高速化についてご紹介したいと思います。

もう少し早い実装で書き直してみましょう。

 

さて前回使ったQTableWidgetですが、機能的には全部入りでとても扱い易いウィジェットです。

何も考えずクラスを呼び出してデータセットすればあとは読み書き自在。

シグナルも基本的なものは揃っています。

が、遅い。とにかく遅い。

オールインワンなだけに内部計算も多いのかな?
巨大なデータテーブルをセット、表示するには時間がかかりすぎてしまいます。

前回の例ではたかだか5000頂点のウェイトを表示するのに7.63secもかかってしまいました。

f:id:ys_45:20190414222418p:plain

PySideのView-Model

ではUIのボトルネックを解消するにはどうすればいいでしょうか?

PySideにはView-Modelという仕組みが用意されていてこちらを利用すればパフォーマンスが大幅に改善するようです。
初見では概念がちょっとわかりにくいのですが、

QTableWidgetがデータ管理から表示、選択まで全部入りだったのに対して、こちらはそれぞれの機能のクラスを呼び出して組み合わせるようになります。

・View(QTableView)

名前の通りデータ表示するクラスです。次項ItemModelからデータを受け取り表示します。他にはListViewやTreeView等があります。

・Model(QStandardItemModel)

こちらはデータを管理するクラスです。標準的なデータ入出力であればQStandardItemModelをよくつかいます。
他QFileSystemModelやQDirModel等用途に特化したモデルも用意されています。
(あんまり詳しくないです、すんまそ)

・SelectionModel(QItemSelectionModel)

UIの選択状態を管理するクラス。現在の選択されているセルを返したり、選択状態の変化をシグナルで伝えたりします。

 

・ちょーかんたんな概念図

f:id:ys_45:20190418214133p:plain

実際にView-Modelで実装したのがこちら

Sample Editor 3 MayaAPI2.0 + QTableView + QStandar ...

 

具体的なコード変更箇所


60行目、TableWidgetをインスタンス化していたところがQTableViewになっています。


メンバ関数では

・table_setup(self)
ウェイトデータ取得時にQStandardItemModelをインスタンス化してデータセット

ItemSelectionModelにデータ(QStandardItemModelのインスタンス)を渡しインスタンス

それぞれをViewに設定
という流れに変更

・update_weights(self)

テーブル更新時のデータ取得方法をシグナル違いに合わせて変更しています。

シグナルの引数として矩形選択データが来ますが現状1セルのみ。
この辺はまた別の機会に。

 

では早速計測してみましょう。

今回もよろしくオナシャスXSI男さん(5000頂点)。

f:id:ys_45:20190418215411p:plain

!!前回と全く同じ条件でテーブル設定から表示まで

7.63sec→0.44secと17倍ほど高速化できました!!イェー!!

 

危うくヒャッハーしそうなほど高速化しましたがまだまだ遅いですね。
XSI男Perfect(約20000頂点)で計測してみましょう。

f:id:ys_45:20190418220257p:plain

テーブル表示に約2.8sec
昨今ではこのくらいの頂点数は当たり前ですね、インタラクティブに操作するのであればこれくらいでも秒以下を実現しないと辛い。

 

SIWeightEditorでは同じモデルでデータ取得と合わせて0.3secを実現できています。

 

というわけで次はQStandardItemModelに変わりQAbstractTableModelでの実装をすすめていきます。
基本的にはViewModelの仕組みはそのままにStandardItemModelを置き換えるイメージです。

QAbstractTableModelはモデルとして最低限の機能しかないのでレスポンスが高速です。引き換えに自分のツールに必要な様々な機能をクラスを継承してオーバーライド、関数追加していかなければなりません。
これがまた複雑で初見殺しな仕様なので次回、詳細なサンプルをお届けしようと思います。

ではでは今日はこの辺で、再見!

 

追記
よく考えたら今回QItemSelectionModelの機能が生きてませんね、、これもそのうち紹介します。





MayaAPIのすゝめ 第1稿

MayaAPIのすゝめ 第1稿

最近MayaAPIが難しいという話をよく聞くので、なにがしか導入のきっかけになればと思い記事にしてみます。

PythonのMayaAPIは1.0と2.0の2種類があり今回はAPI2.0を主題にします。

そもそもMayaAPI1.0はC++APISwig変換されたものであり、パフォーマンス的にも書式的にも不利な面が多くありました。


Pythonの書式になれきってる人は初見だとぉうぇっ、てなりますね(なりました

 

MayaAPI2.0ではPython向けに諸々刷新され書式が大幅に簡略化、パフォーマンスも向上し、場合によってはC++のそれを上回る局面もあるようです。

バージョン毎に使えるクラスも増えてきて私も最近はもっぱらAPI2.0ばかり使うようになりました。

 

ツール作成にあたってはいきなりAPIで作ろうとするとコストが高く、イテレーションも悪いので、自分の場合は

・MayaCmdsで必要な機能を作成

・PySideでUI作成(Mayaのレイアウトは使ったことないので知らない、、)

・パフォーマンスに問題がある場合は部分的、または全体をAPI

・UIの最適化

っていう手順を踏んでいます。

MayaCmdsでツール仮作成

部分的な機能解説ではわかりにくいと思うので作例としてちょっとしたウェイト編集ツールを作成しました。

↓こちらを例に実際にAPI化、速度の最適化していきたいと思います

※可読性優先で例外処理やら再利用性は考慮してません

Sample Editor 1 Cmds + QTableWidget

実行するとウィンドウが開き、スキンメッシュやコンポーネントを選択してGet_Weightボタンを押すとテーブルに反映されます。

実行時間はUI下部とスクリプトエディタに出力されます。

f:id:ys_45:20190414215337g:plain

 

・ウェイト取得はcmds.skinPercent

・UIのテーブルはQTableWidget

とどちらも制御は簡単なのですが、いかんせんパフォーマンスがイケてません。

実際に計測してみましょう。

協力いただくのは今回もXSI男さん(5137頂点、骨入れ済み)

f:id:ys_45:20190414215754g:plain

計測結果がこちら↓

f:id:ys_45:20190414222456p:plain

約5000頂点27Jointで

読み込み0.41sec

テーブルに設定7.08sec

書き込み6.59sec

、、5000頂点でこれではツールとしてはお話にならないですね。

読み込みはまぁ許せる範囲ですが、テーブル表示と書き込みがとにかく遅い。

昨今のハイレゾなリソースを考えると数万頂点でもさらっと耐える速度が必要そうです。

 

ちなみにSIWeightEditorでは同じモデルで

読み込み~テーブルセットまで0.09sec

書き込み0.235sec

でした。

これを指標に高速化を進めていきます。

f:id:ys_45:20190414224734p:plain

とりあえず読み込みと書き込みをAPI

順番的には実行コマンドを高速化するのが旨味が大きいので読み込み部分と書き込み部分をMayaAPI化していきます。

んで、したのがこちら↓

Sample Editor 2 MayaAPI2.0 + QTableWidget

具体的にはクラスのメンバ関数

get_skin_data(self)
set_weights(self)
API仕様に変更しています。

詳細はあとにしてまずは計測してみましょう。

f:id:ys_45:20190414222418p:plain

読み込み0.036sec

テーブルに設定7.63sec

書き込み0.066sec
読み込み10倍、書き込み100倍高速になりました!ヤター!!

とここまでは比較的簡単なのですが、この先が面倒くさい、、

本当に使えるツールにするにはこの他様々な対応が必要になってきます。

 

・UndoRedoの実装

MayaAPIでの操作は元に戻すの待ち行列に入らないのでUndo、Redoのコマンドを自前で実装してやる必要があります。

・UIの高速化

API化しても相変わらずテーブル設定が遅くてボトルネック、、

こちらはQAbstractTableModelを利用することで劇的に改善します。

ただPySideのView_Modelの仕様を理解する→プリミティブなModelで必要な機能を自前実装してやる、とふた山くらいあります。

どちらも一息に紹介するにはかなりボリューミーなので、次回以降数回に分けてまとめて行きたいと思います。

これから

APIの書式ざっくり解説、コンポーネントタイプ変換テクニックの紹介

・書き込みをプラグイン化してUndoRedoできるコマンドを実装

・UIのView_Model化(QStandardItemModelでの実装)

・QStandardItemModelをQAbstractTableModelで置き換え(Tableの基本機能を自前実装)

・QAbstractTableModel高速化のコツ

を順を追って記事にしていこうかなと思ってます。

 

この辺を抑えられるとウェイトに限らず頂点カラー、UV、法線、頂点座標等なんでも(実用的な速度で)オレオレエディタ化できるようになったり。

 

他にもMayaAPI使えるとベクトル計算やマトリックス変換、球面線形補間等、cmdsではちょっとできないいろんな計算もサクッとできちゃったりします。

ぜひMayaAPIに親しんで行きましょう。

では今回はこの辺で、アディオスばいなら。

SI Weight Editor ver_r1.3.9

github.com

 

細かい機能追加とバグフィックスなど

・上部ペインUI設計の見直し

・固定値入力ボタンを追加
左クリックで絶対値入力
Shift + 左クリックで加算
Ctrl + 左クリックで減算
・スムース設定呼び出しを右クリックから専用ボタン化
・スムース比率設定を追加
スムース、ハンマーボタンを右クリックで適用率を考慮して実行
・頂点ハイライト機能、アンドゥ時にハイライトリセットするように修正

 

追加機能の詳細は以下

固定値入力ボタン

よく使う特定の値を決め打ちで入力するボタンを追加しました
左クリック → 絶対値入力
Shift + 左クリック → 加算
Ctrl + 左クリック → 減算

weight_static_value

ウェイトハンマー、スムースの適用率を変える

元の値とスムース後の値の混ぜ率を変更できる機能をつけました

※右クリックで適用率考慮実行、左クリックは従来スムースままです


数値が小さいほどスムース適用率が低くなります
100の場合は通常スムースと同じ挙動

weight_smooth_ratio

スムース設定ウィンドウ

スムースボタンの右クリックから専用ボタンに変更しました

SSボタンで設定ウィンドウを開きます

weight_smooth_option2