myara CG blog

CG Design Blog. Thoughts, experiments and experiences.

SI | HQVが原因でシーン保存が100倍遅くなる問題

Softimage の High Quality Viewport (以降 HQV ) が原因でシーン保存とリファレンスが約100倍遅くなる問題についてPsyop の Andy Jones氏が SI メールリストに報告しました。

https://www.mail-archive.com/softimage@listproc.autodesk.com/msg26264.html

全部訳すのは面倒なので、超省略しちゃいます。

リファレンスモデルをアンロード:
HQV 有効のまま:250秒
HQV 無効にすると:3秒

シーン保存:
HQV 有効のまま:15分
HQV 無効にすると:30秒


HQVは実際に使用しなくても、HQVが有効になっていれば起こる現象だそうです。(Psyopではほとんど使用されていない)

HQVは使用してもしなくてもデフォルトでは有効になっているので、
プリファレンス設定でHQVをOFFにする必要があります。

リモートコントロールでやると、シーン保存は通常(早い)に出来たそうなので、
グラフィックドライバーの問題も考えられます。
色々なドライバーを試してもダメでしたので、Psyopの方ではHQVを無効にする事になりました。
因みにPsyopはほとんどQuadroだそうです。

普通にプリファレンスを開いて、Displayのところで設定が出来ますが、
以下のSnippetを使えば、そのオプションを探さなくてもすぐにHQVを無効にする事ができます。


#Python
Application.SetValue("preferences.Display.high_quality_viewport", False, "")


これを使って、プラグイン・イベント化にして、共有Workgroupに入れれば、会社の皆のPCを一発でこの設定に変更ができそうですね。やろうかな。

SI | 使われてないデフォーマーをゲットする

使われていないデフォーマーを選択するスクリプトです。

以前Twitterで出た話題ですが、何週間後に気付き今日は書いてみました。

メッシュを選んで、スクリプト実行すると、使われていない骨を選択してくれます。

それだけです。


ウェイト系のスクリプトの場合は Python や JScript に比べて VBS は圧倒的に速いと前から分かってはいるのですが、ちょっとだけ実験してみました。

まずは、Biped Nulls をだして、Local Subdivision で 3.8万ポリにしてみます。
そして、骨の数を4倍にします(308本)(メッシュを選択し、Set Envelopeにクリックして、複製した骨に中クリック)

これで良くあるキャラクターのスペックになったかな。下準備完了。

次は以下のコードを実行すると:

VBS 578 miliseconds
JScript 1239 milliseconds
Python 2210.0 miliseconds

メッシュを更にサブディビジョンかけると(15万ポリ):
VBS 2328 miliseconds
JScript 4965 milliseconds
Python 8812.0 miliseconds


やっぱり、VBS の勝利でした。
書くのは面倒だけど、ウェイト系のスクリプトはやっぱりVBSでやったほうが良いかも。

今までの実験だと、どうやらウェイトを取得するだけでVBSよりJSとPython がかなり時間が掛かってしまいます。
JSの場合は toArray() にしないといけないというところもあるけど、Pythonはそのまま使えるのになんでこんなに遅いのかまだ良く分かりません。

Pythonの方が書きやすいのに、なんか良い方法ないかな?
ないみたいね、割り切ってPythonの遅さを我慢するか、VBSの面倒くささを我慢する。それかtoArray()にしなきゃいけない面倒なJScriptでやるのか。


え? C 覚えろって?・・・いつかね。



では、また。



'VBS
Dim StartTime, EndTime, TimeIt
StartTime = Timer

set obj = selection(0)
set env = obj.envelopes(0)
set defs = env.deformers
set emptyDefs = XSIFactory.CreateObject( "XSI.Collection" )

for each def in defs
weights = env.GetDeformerWeights(def)
totalw = 0
for each weight in weights
totalw = totalw+ weight
next
if totalw = 0 then emptyDefs.Add(def)
next

EndTime = Timer
TimeIt = EndTime - StartTime
Logmessage Round(TimeIt*1000) & " miliseconds"


//JScript
var startDate = new Date();

var obj = selection(0)
var env = obj.envelopes(0)
var defs = env.deformers
var emptyDefs = XSIFactory.CreateObject( "XSI.Collection" )

for ( var i=0, a = defs.Count; i < a; i++ ) {
weights = new VBArray( env.GetDeformerWeights(defs(i))).toArray()
totalw = 0
for ( var j=0, b=weights.length; j < b ; j++ ) {
totalw = totalw+ weights[j]
}
if (totalw == 0) emptyDefs.Add(defs(i))
}

var endDate = new Date();
var timeTaken = endDate.getTime() - startDate.getTime();

LogMessage(timeTaken+' milliseconds');
SelectObj (emptyDefs)

#Python

app = Application
log = app.logmessage
from time import time

startTime = time()

obj = app.selection(0)
env = obj.envelopes(0)
defs = env.deformers
emptyDefs = XSIFactory.CreateObject( "XSI.Collection" )

for odef in defs:
weights = env.GetDeformerWeights(odef)
totalw = 0
for weight in weights:
totalw = totalw+ weight
if totalw == 0:
emptyDefs.Add(odef)

finishTime = time()
log(str(round((finishTime - startTime) * 1000))+ " miliseconds")

app.SelectObj(emptyDefs)

SI | システムエラーの前にシーンを保存できませんでした

最近は色々忙しくてなかなかブログ更新が出来ませんが、これはもしかしたら誰かに役に立つから書いておきます。
(一ヶ月後だけど)

一ヶ月ほど前に同僚のSIはいきなり起動が出来なくなったケースのことです。

SIアイコンにダブルクリックすると、画面がグレーになって、GUIが出てきそうな時に

「システムエラーの前にシーンを保存できませんでした」

という意味不明なエラーが出ます。

エラーの原因のヒントは一つもないです。
色々探ってみたけど、何も見つかりませんでした。

なので、いつもの直しパターン:
・runonce.bat 掛けても直りませんでした。
・プリファレンスフォルダーやワークグループをリネームしても直りませんでした。
・SIをアンインストールして、最インストールしても直りませんでした。

32bit 版を入れてみたら起動が出来ましたが、今のプロジェクトで使っているリアルタイムシェーダー系のエクスポートツールが不安定でした。
SIのログを見てみると、Direct なんとかのエラーが出てもしかして・・・グラボ?と思い、違うドライバーを試してみようと。

うちではGeForceを使っているので、以下のドライバを入れてみました。(そう、今はAutodeskのお勧めドライバにGeForceのも載っている!知らなかった)

GTX 690と書いてありますが、GeForceドライバはほとんどのGeForceを対応しています。
Autodesk様のテストはあくまでもGTX690を使っている場合ということでしょうけど。

ちなみ、同僚のグラボは GTX550です。

NVIDIA GeForce GTX 690 64 bit
http://usa.autodesk.com/adsk/servlet/syscert/card?siteID=123112&catID=18254205&id=18844534&product=93&os=8192&hw=291

※追記
日本語版は以下のリンクになります
GeForce 314.07 Drivers Win8/Win7/vista 64bit


すると、正常に起動が出来ました !

どうやらGeForceの自動更新ツールは原因でした。

最新のドライバが一番良いってわけでもないですね。特に仕事の場合は。

つまり、SIが起動が出来なくなったらドライバを疑うべき。


それでは、またいつか。

Softimage メールリスト(英語)

昔からSoftimageに詳しい人たちが集まっているメールリストがあります。いつもお世話になっているリストです。

以下のリンクはメールリストのアーカイブです。
https://groups.google.com/forum/#!forum/xsi_list

http://www.mail-archive.com/softimage@listproc.autodesk.com/
ここでは書き込みが出来ません。

メールリストは名前どおり、メールだけのやりとりになります。
アーカイブはただの履歴です。


メールを送るためにメールリストに登録する必要があります。

■ SIメールリストに登録する方法
softimage-request@listproc.autodesk.com にメールを送ります。
件名: Subscribe

・確認のメールに返信すれば登録完了

■ SIメールリストから退会する方法
softimage-request@listproc.autodesk.com にメールを送ります。
件名: Unsubscribe


■ メールを送る方法
softimage@listproc.autodesk.com にメールを送ればOKです。
自分が送ったメールが返って来ないと思います。
不安だったらアーカイブで自分が送ったメールは確認が出来ます。



見ての通り全部英語のみです。
そして、テクニカルな話題もまーまー多いです。ICE、API、SDK など。

ハードコアマスタースーパープログラーマーしか付いていけない話題もたまに出てきます。
そんなのもちろん無視しています。

そして、必ず半年に1回ぐらいどうでも良いオートデスクへの怒りメールが出てきます。
それも無視して下さい。


以上。

メールリストで合いましょう

SI | FOV & 久々にMath

今やっているプロジェクトでは、GUIのある映像を作っているので、
GUIと合うようなカメラワークやレイアウトを作るために
SI上でもGUIをリアルタイムで表示させたかった話です。

ロトスコープはモデルの後ろで表示されてしまうのでNGです。

思いついたやり方は、カメラの前に居たポリを付けるぐらいです。
おそらく誰でもすぐに思いつくやり方でしょう。

問題はですね、画角をいじると、この板ポリが小さく見えてしまったり、大きく見えてしまったりするところですよ。
画角を固定にすれば良いだけですが、そうすると映像の表現が結構限られてしまいます。

FOV(画角)に合わせて、この板ポリがスケール、または移動すれば良いだけですね。
そう、簡単に聞こえますが、そんなに簡単ではなかった。

SIのデフォルトのオプションではFilm Aperture (開口) は固定で、FOV と Focal Length (焦点距離)だけが動きます。

居たポリのサイズを開口サイズに合わせ、焦点距離と同じ距離にすれば良いだけです。
カメラの「projplanedist」を使って、簡単なエクスプレッションで済みます。

しかし!

FOVをいじるとSIが自動に FocalLength の数値を更新してくれますが、FocalLengthを使っているエクスプレッションまで反映されません!
今回は FocalLengthより FOV を使っているので、エクスプレッションをFOVにつなげないとちょっと不便。

FOV情報をFocalLengthに変える方法ですね。ここは問題でした。
ネットで検索してみたけど、なにも見つかりませんでした。しょうがなく頭を使ってみるしかないですね。

FOV と Film Aperture をイメージにすると、三角形になりますよね。
その真ん中に FocalLength の線をひくと、直角三角形になります。
これなら簡単な三角関数で計算が出来るじゃん・・・

CAMFOV1.jpg


・・・と思ったけど、あれ?

関数って・・・なんだっけ?

大学を中退してから使ったことないな~

因みに、数学系オペレーションリサーチ専攻で数学トラウマを受け、1年で辞めたものです。
オペレーションリサーチって知っている人いるのかな?

現在は電卓がないとワリカンの計算も出来ない人ですけど。

とにかく、簡単な三角関数が必要なので、ネットを調べながら、高校の授業を思い出しながら、まずは移動でやってみました。

こうなりました:

CAMFOV2.jpg

ということで、


cos( Camera.camera.fov / 2 ) * Camera.camera.projplaneheight * 25.4 / 2 / sin( Camera.camera.fov / 2 )


というエクスプレッションになりました。

これで Focal Lenght が分かるので、後はこっちのもんですね。

簡単な帰一算を使えば、スケールバージョンも作れます。


■ 注意するべきところ:
Film Aperture は mm ではなく、 inches で表示されているので、 mm に変換する必要があります。
単純に 「* 25.4 」 で ミリになります。

エクスプレッションの三角関数は角度で計算します。
JScript や XSI.Math は Radians で計算します。

これは重要ですね。エクスプレッションよりスクリプトになれているので、Radiansに変換していたから変な数値になっていました。
マニュアルには載っていない気がします。載っていますか?

ちなみに、Degrees -> Radians の変換は
Degrees = Radians * 180 / PI

JavaScript には Math.Pi があるので、簡単に計算が出来ますが、
XSIMath を使えば関数なんか忘れていちゃっても簡単に出来ます:

XSIMath.RadiansToDegrees
XSIMath.DegreesToRadians



スクリプト化してみたらこんな感じになった:

注意:  コードは全く整理していなくて汚い!
注意2: 計算より直感の方が早かったから、数値はちょっと適当です。格好つけて三角関数などの記事を書いて結局直感的にやってしまう適当な人ですいません。

実行方法:
カメラ・カメラルートを選択して、実行

GUIの画像ファイルは「GUIImgPath」変数で設定出来ます。
画像の比率はグリッドのサイズで指定しています(16/9)


//JScript<br /><br />GUIImgPath = "
// 選択フィルター
if (selection.count !=0){
if (selection(0).type == "camera") var cam = selection(0)
else if (selection(0).type == "CameraRoot") var cam = selection(0).FindChildren("","camera")(0)
else if (selection(0).type == "CameraInterest") var cam = selection(0).Parent.FindChildren("","camera")(0)
else var cam = ActiveSceneRoot.FindChildren("","camera")(0)
}
else var cam = ActiveSceneRoot.FindChildren("","camera")(0)

// グリッド作成
var grid = ActiveSceneRoot.AddGeometry ("Grid", "MeshSurface","GUI")
grid.rotx = 90
grid.subdivu = 1
grid.subdivv = 1
grid.ulength = 16
grid.vlength = 9
ResetTransform(grid, siCtr, siRot, siXYZ);
ResetTransform("GUI", siCtr, siScl, siXYZ);
grid.sclx = 0.05
grid.scly = 0.05
ResetTransform("GUI", siCtr, siScl, siXYZ);
FreezeObj(grid);

// グリッドをカメラにコンストレイン
var cns = ApplyCns("Pose", "GUI", cam, null);
SetValue(cns+".posz", -1.68, null);
SetValue(cns+".cnsscl", false, null);

// Focal Length を計算するエクスプレッションを作る
var planedist= "cos(" + cam + ".camera.fov/2) * " + cam + ".camera.projplaneheight * 25.4 /2 / sin(" + cam +".camera.fov/2)"

// 上記の関数を使って、グリッドのスケールをFocal Length につなげる。
SetExpr(grid +".kine.local.sclx", grid +".kine.local.sclx / ( "+grid+".kine.local.sclx * ( "+ planedist +" / 10 ))", null);
SetExpr(grid +".kine.local.scly", grid +".kine.local.scly / ( "+grid+".kine.local.scly * ( "+ planedist +" / 10 ) )", null);

// マテリアル作成:
ApplyShader("$XSI_DSPRESETS\\Shaders\\Material\\Constant.Preset", grid, null, "", siLetLocalMaterialsOverlap);
var mat = grid.material

mat.shaders("Constant").color.red = 1
mat.shaders("Constant").color.green = 1
mat.shaders("Constant").color.blue = 1

// GUI画像を貼る:
SICreateImageClip(GUIImgPath, "gui");
CreateShaderFromProgID("Softimage.txt2d-image-explicit.1.0", mat, "Image");
SIConnectShaderToCnxPoint("Clips.gui", mat +".Image.tex", false);
SIConnectShaderToCnxPoint(mat +".Image.out", mat +".Constant.color", false);
SIConnectShaderToCnxPoint(mat +".Image.out", mat +".Constant.transparency", false);
SetValue(mat +".Constant.usealphatrans", true, null);
SetValue(mat +".Constant.inverttrans", true, null);

CreateProjection(grid, siTxtPlanarXY, siTxtDefaultSpherical, "Texture_Support", "Texture_Projection", null, null, null);
SetInstanceDataValue(null, mat +".Image.tspace_id", "Texture_Projection");

FreezeObj(grid);
Next page