日本でハリウッドVFXを制作! 「経産省アイディアボックス」 結果:  
●まとめエントリはこちら ●FAQ ●お問い合わせは左のメールフォームから

2009年5月31日日曜日

linstep (2)

オンラインヘルプを読んでいるときopacityPPにlinstepを使用した例をみつけた。

「linstep」については以前のエントリ「linstep (1)」でとりあげ、「ゴールに近づいたパーティクルの色を変える (2)」でパーティクルに対して使うことを試みたことがある。

今回は使用例のバリエーションとしてこのオンラインヘルプの例をもう少し掘り下げてみたい。


----------------------------------------
これがオンラインヘルプの例:
particleShape1.opacityPP = linstep(0,5,particleShape1.age);


age」は前回「パーティクルの時間に関する事柄」で見たように、パーティクルの年齢を秒数で示している。



ここでなぜ「age」を使うのかを考えてみる。

まずlinstepから見なおしてみる。
linstep」は第一引数~第二引数の範囲外においては0か1の値しか返してこない。
従ってこの例では第三引数は「0」~「5」の間にあるときしか「opacityPP」に変化が現れない。

これがフレームの値を返す「frame」であると、フレーム5においてすでに限界値に達してしまう。
これは肉眼では一瞬であり、linstepを使う意味があまり無い


しかし、24fpsの場合フレーム5では「0.2085秒」であり、まだまだ余裕がある。

実際に最大値5に達するには、
5÷0.0417=119.904・・・
と約120フレームが必要となる。これは時間にすると当然ながら5秒となる。


linstepでの第二引数は、opacityPPが「1」に達するまでの時間を決めることがわかる。



なら同じ秒数の返り値を持つ「time」を使ってみてはどうか?
timeを使うと、全パーティクルに同じ値が適用されることになる。
ようするに最初は全パーティクルが透明で、5秒に近づくにつれ、全パーティクルの透明でなくなる。
これが狙った効果ならこれでもよいかもしれないが、パーティクル単位のエクスプレッションを使わなくてもできる。


「age」を使った場合、フレームの位置に関係なく、個別のパーティクルの年齢に応じて、透明度がかわる。
たとえば、フレーム5にエミットされたパーティクルも、フレーム20でエミットされたパーティクルも一様に生まれてから5秒かけて透明度を変化させることができる。



メモ:linstepの引数に文字列が使われているため、linstepの引数として使用する前に、それを数字に変える作業が先に必要となる。
そのため( )が使われている。

(参照:オンラインヘルプ
文字列引数を引用符で囲む必要があります。たとえば、$faces がオブジェクトのフェース数を表している場合、( ) を使用して、出力する文字列を構築することができます。

 

2009年5月30日土曜日

返品!! PogoPlug (13)

Pogoplugに関するこんな記事がlifeHackerにありました。

あと二年で半額だそうです。
まぁそのころにはそれでも若干高いような気もしないでもないが、Webサービスはより拡充すると思われるので、値段相応と言えるかもしれない。


さて、Pogoplugのblogやコミュニティーを久しぶりにみていると、webアプリがアップデートされ、新しい機能がいくつか追加されていた。

●ファイル検索機能(ドライブ全体のみ)
●シェアしたい人のE-mailアドレスを登録するときにメッセージを送る機能がついた。
他にもいくつかあったが特に必要無いことだったので省略

また、ローカル環境でしかためしていないが、m4vとmp4ファイル(アップルの予告編)に関しては、web上で再生できることがわかった。ただしm4vのサムネイルは表示されない。
movファイルは再生は出来たが音声がでなかった。
avi、mpgは静止画として表示はできるが動画再生は非対応と言う状況は変化無し。
(おそらくこれからも非対応:コーディングの都合から負荷が高すぎるようです)



久しぶりに使った感じでは、悪くはないかなという感じ。
ただ大容量ファイル転送、動画再生には期待は出来ない。

ほしいものとしては、写真のコメントもしくはタイトルを表示できる機能。
それに、FTPやプリンタサーバー機能もあれば言うこと無しだが。
1週間ほどつかってみよう。

 

2009年5月29日金曜日

時間に関する名称の混乱

パーティクルを使っているときに、時間に関するキーワード、アトリビュートや変数によく出会う。

なんとなくわかったつもりになって使っていたが、エクスプレッションで使う際にキーワードとアトリビュート名が混乱している。

頭を整理するために調べてみた。


--------------------
--------------------
time キーワードと frame キーワード

これはパーティクルに限らずエクスプレッションであれば使うことができるものだ。
機能は、フレームレンジでの現時点の値を返すだけ、変更は出来ない。

オンラインマニュアルでは、関数でも変数でもなく「キーワード」として扱われている。

使い方は変数と同じ。
現時点の、「ミリ秒」もしくは「フレーム数」が格納された変数と考えればよい。



---<time>---

time: タイムライン上の現在地(時間)

秒数

24fps:1フレームあたりの時間は、1(秒)÷24(フレーム)=0.041666666・・・ =>0.0417秒(41.7ミリ秒)
30fps:1フレームあたりの時間は、1(秒)÷30(フレーム)=0.033333333・・・ =>0.0333秒(33.3ミリ秒)

注意:似たものに「timeノード」がある。
これは、秒数ではなく現時点のフレーム数を出力する。
混乱しやすいので注意


---<frame>---

frame: タイムライン上の現在地(フレーム数)。

フレーム数




--------------------
--------------------

パーティクルのアトリビュート

これはパーティクル・シェイプに存在するアトリビュート
age以外は、それぞれユーザーが設定、変更できる。
アニメーション操作は、キーフレーム、エクスプレッションが可能。


---<age>---


age: (年齢) 各パーティクルが最初のフレーム以降、存在する秒数。

秒数。変更不可。

ヘルプ内に詳細の説明を見つけることは出来なかったが、1フレームあたりの秒数なので計算方法は「time」キーワードと同じだろう。



---<currentTime>---

currentTime: マップされているフレームを示している。パーティクル全体に影響

フレーム数

注意1:デフォルトではtimeノードにコネクトされており常に現時点のフレームを示している。
注意2:キーフレームでコントロールする場合、全フレームをカバーしている必要がある。
もしキーフレームが100フレームで終わっているならそれ以降のパーティクルはなにも動かない。


以下にキーフレームでコントロールしたときの関連を示す。
実際のフレーム        currentTime
001-100(100フレーム)    001-200(200フレーム)   (2倍の速度)
101-200(100フレーム)    201-250(50フレーム)   (半分の速度)

上記の例であればフレーム100を過ぎた時点で、パーティクルの全スピードが半分になる。

キーフレームの付け方次第で、マトリックスのようにリアルタイムから超スローモーションへ、そしてまたリアルタイムに戻るような、タイムワープをスムースに作ることができる。

参考までにオンラインヘルプの解説は以下の通り
それぞれのパーティクル オブジェクトには、パーティクル エフェクトを遅くしたり早めたりするようにアニメートすることができるカレント タイム(Current Time)アトリビュートがあります。このアトリビュートは独立した時刻の値を含みます。基本的には、パーティクル オブジェクトのクロックを遅らせたり早めたりして、作用するダイナミクスを遅らせたり早めたりします。




---<lifespan>---

lifespan: パーティクルの寿命を設定する。

秒数。
lifespan「1」=1秒を示す。

24fpsの場合、24フレーム経過したときにそのパーティクルは消滅する。
24fpsの場合、1フレームは、0.0417秒(41.7ミリ秒)に相当。

関連するアトリビュートがいくつかあるが詳細はヘルプを参照。
「lifespanAttributes」で設定したり「lifespanPP」にエクスプレッションを作成して使用する。

「lifespanAttributes」で「Randam range」を使用する場合。
「LifespanRandam」の値は、lifespanの値から+-の範囲を示す。

lifespan: 5
lifespan Random: 4
と設定した場合、5から、プラス値へ2まで、マイナス値2までのランダムの値になる。



----------------------------------------
<<まとめ>>

何を明確にしたかったかというと、
1)それぞれがどんな値を返してくるのか(フレームなのか?秒なのか?)
2)どれが読取り専用でどれが変更可能か?


簡単にまとめると以下のようになる。
time:   ミリ秒(読)
timeノード:フレーム(読)
frame:   フレーム(読)
age:    ミリ秒(読)
currentTime:フレーム(読・書)
lifespan:  秒(読・書)



名前に「time」という単語が含まれいるとどうしても秒数を連想してしまう。
しかしながら「timeノード」と「currentTime」はフレーム数を扱う。
また「age」「lifespan」はフレームで制御したいところだが秒数になっている。

これらが混乱の原因だったと思う。

 

メモ:Webサイト「○×つくろーどっとコム」

○×つくろーどっとコム


ちらっとみただけですが、CGに関係する数学やプログラミングの知識が、とても詳しく、イラストも多用され、わかりやすく説明してあるようです。
とても整理された感じがあり、初心者が本格的に学んで行くには、良い参考書になりそうです。

特に「ゲームつくろー!」のページはすごいです。

DirectX用のプログラミング解説なので直接MELに応用はできませんが、数学的な理論について学ぶには十分かと思います。

最近、その存在を知った「クォータニオン」も、「DirectX9技術編」の「クォータニオンを学んでみよう!」で解説されています。

数字が4つ集まったもので、言ってみれば4次元ベクトルです。3次元ベクトルであれば縦横高さで何となく想像ができますが、4次元となるともうドラえもん しかわかりません(笑)。この原稿を書いている私も、実は何のことやらさっぱり。そこで、私と同じような境遇にいる皆さんにも理解できるように、この クォータニオンを1から学んでみようと思います。

と書いてあるようい、難解な物をわかりやすくしようという意図が伝わってきます。
中身も、何が重要なポイントかわかりやすく書かれており、小難しい数学書で要点をつかむのに時間を掛ける必要がないとしたら、すばらしいことです。



そのほかにも「衝突判定編」をみると、CGをやっていく上で避けられない「内積と外積の使い方」や、VFXに関連する「点と点」(の衝突)などがあります。


内積と外積のページには、はじめに以下のように書かれており

内積は高校で、外積はたぶん大学で習います。そのきちんとした意味を理解するのは大切ですが、ゲームで使う上では性質を体得する方が近道かと思います。そのためにはイメージが大切です。

純粋な学問としてではなくあくまで実用を目指した理解が主眼であることがわかります。


 

メモ:ミケランジェロの言葉

「芸術家として他に秀でようと思ったら、気が向こうと向くまいと、 朝も昼も夜も一心不乱に制作に打ち込むべきだ。それはもはや楽しみの域を越え、苦行と呼ぶにふさわしい」

(ミケランジェロ:竹内均訳 S.スマイルズ「自助論」

まさに行動あるのみというか、楽しいかどうかと言うことよりも、制作という行為を継続することによってのみ優れた能力を身につけることができるということか。


 

メモ:パーティクル単位アトリビュートに関して

(オンラインヘルプ:パーティクル単位のアトリビュートとオブジェクト単位のアトリビュートについて


位置、速度、アクセラレーションの各アトリビュートは名前の末尾が PP ではありませんが、パーティクル単位のアトリビュートです。

パーティクル単位のアトリビュートを使用できるのは、パーティクル エクスプレッション内に限られています。

オブジェクト単位のアトリビュートは、パーティクル エクスプレッションと非パーティクル エクスプレッションの両方で使用できます。


ランタイム エクスプレッションを使用して、数多くのパーティクルを含むパーティクルオブジェクトのオブジェクト単位アトリビュートの読み取りや書き込みを行う場合は、それらのアトリビュートを非パーティクルエクスプレッションで読み書きすれば、エクスプレッションの実行スピードを上げることができます。

 

メモ: velocityの調整

(オンラインヘルプ:作成エクスプレッションを書き込む)

以下のクリエイション・エクスプレッションによりパーティクルの速度を制御する。

particleShape1.velocity = <<0,1,0>>;

アニメーションを再生すると、すべてのパーティクルが 1 グリッド / 秒の速度で Y 軸に沿って移動します。


このヘルプの例では、パーティクルツールで作った物なので、全体が一度に移動するが、これをエミッターからのパーティクルに適用すると「omni」エミッタを使っていてもDirectionalのようにパーティクルが発生する。
またそれに対してフィールドを適用することももちろん可能。

これをランタイム・エクスプレッションにも同じ物を使うと、毎フレーム計算されるので、フィールドの影響はかなり少なくなる。

 

メモ:パーティクルのageをビューに表示する

各パーティクルのageをビューで確認する設定。
(オンラインヘルプ:ダイナミクスの開始フレームを設定する

Particle Render Type:Numeric

デフォルトでは
AttributeNameが「particleId」なのでIDを表示する。
これを「age」に変更する。

これでageが表示される。

 

オンラインヘルプ「ランタイム エクスプレッションを記述する」のノート

オンラインヘルプ:ランタイム エクスプレッションを記述する


velocityのデータ型はベクトル<<x,y,z>>なので、下記のような記述になる。
particleShape1.velocity = <<0,time,0>>;


このページに、sphrandを用いた例がある。
この例ではaccelerationに使われているが、このsphrandはベクトル値を返してくるので、
上記の<>と入れ替えて使える。
particleShape1.acceleration = sphrand(2);


--------------------
このSphrandについてもう少しくわしく調べてみた。
sphrand
このコマンドは、指定した半径の球体内に均一に分散されるランダムなベクトルを生成します。

記述形式は引数である半径を( )内に入れる。
引数を2とした場合の記述は以下の通り。
sphrand(2)

これによりランダムなベクトル値が得られる。
スクリプトエディターで繰り返し実行した場合の値を示す。
毎回異なるベクトルが与えられていることがわかる。

sphrand(2);
// Result: <<0.674383,>> //
sphrand(2);
// Result: <<-1.269656, 0.516169, 0.0812025>> //
sphrand(2);
// Result: <<-0.544219, 0.441139, 0.446326>> //


そして先ほどのランタイムエクスプレッションでは、
particleShape1.acceleration = sphrand(2);

sphrand(2)が、各パーティクルのアクセラレーションにそれぞれ異なるベクトルを渡す。
そして、それはフレーム毎に更新され新しい値を渡す。

ノート(ラインタイムエクスプレッションの特徴):
各パーティクルに実行される。
フレーム毎に実行される。



そのためこのシーンを再生すると
小刻みに震えつつランダムな方向へパーティクルが飛んでいく。
(見やすくするにはsprand(10)程度にするとよい)

小刻みに震えるのは、アクセラレーションがいろいろな方向へ毎フレーム変化しているからだが、一方向へ飛び続けるのはアクセラレーションが変わっても、初期の動きを保存しているためだ。
従ってパーティクルのConserveをゼロにすると、パーティクルはそこからほとんど移動せず、小刻みに震え続ける.


見ているとタービュランス・フィールドにくらべて均質にランダムな動きを生み出してくれる。
タービュランスは、Magnitudeをあげると、一部がより集まってしまうことがあり、あまりMagnitudeをあげられないことがある。

一概にすべてのケースで、この方法が良いとはいえないが、ランダムな動きが偏らないようにするには、もしかしたら使えるかもしれない。


動きを見た感じでは、何らかの物やキャラクターが粒状化し分散して消えていくようなショットに使えるような気がする。



--------------------
おもしろいのは、パーティクルのアクセラレーションを一定値にするには、creationではなくrantimeExpressioを使い、定数を代入するということ。

アクセラレーションは各フレームの開始前に<<0,0,0>>に初期化されるのがその理由で、ちなみにcreationExpressionにしてしまうと全く動かない。


ノート(クリエイション・エクスプレッションの特徴):
アニメーションを巻き戻した時点で実行される。
またはパーティクルが放出されるフレームで実行される。

 

返品!! PogoPlug (12)

やっと大容量(4.3GB)ファイルが転送できない問題について返答がきた。

今まで対応してくれたサポートの人手はなく、品質保証のマネージャーから返事が来た。
わざわざ品質保証の人が出てきたと言うことは守りに入ったと言うことを示しているので...。
問題は解決していないと言うことになる。


自分の変な翻訳で、誤解があると行けないので、最後に原文をのせておくが要点をまとめると以下のようになる。

-------以下翻訳-------------
CTO(最高技術責任者)からも要請があり、私たちのエンジニア達がバグの見落としがないかを確認しました。

結果として、これは予測される範囲内のことで、このような大容量ファイルの転送における制限事項となります。

このような大きなファイルを転送する必要がある場合は、途中停止や継続ができる専用のソフトウエアをおすすめします。
ファイルのダウンロードにはFee Download Managerがもっともよく、アップロードにはSyncToy, Robosync, and Rsync, and Alway Syncなどをおすすめします。

個人的に言っておきたいのですが、このデバッグプロセスにおつきあいいただきありがとうございます。
我々はバグを修正するために尽力していますが、あなたの抱える「この大容量ファイルの転送」はインターネットを使用する上での制限で、我々のソフトウエアのバグではないということをご理解ください。

もし他に問題があったり、質問があればなんなりとどうぞ。
--------以上、翻訳終わり------------


実はこのあと、大容量ファイル転送時に 0 kb of 0 kbで変わらないのは解決したのか?(転送の問題ではなく表示の問題)という質問を送ったが、そのときに返ってきた返事では、ブラウザが認識していないためで、そのため表示ができない。それは我々のソフトが原因ではない。ということで、どのような仕組みになっているかそれ以上の詳細は説明されていないかった。


また最初の文面では「インターネット」の制限と言っているが、ここから推測するに正確にはブラウザを使った制限ということらしい。

いろいろとやってくれたんだなとは思うし、バグではないし、そこまで期待するのも間違っているのかもしれないが、予測通りの展開になった。

上記のファイル転送ソフトを使えば良いとのことだが、これってPogoplugソフトをインストールして、自分のPCのエクスプローラーでPogoplugを表示させてから使うと言うことなのか??

会社でやるとしたら自分のノートPCを持ち込むことになるので、意味が無いが・・・・。
(自分のノートPCのHDDに保存すればよいので)


<まとめ>
質問:4.3GBのファイルをブラウザから転送しようとすると 0 kb of 0 kb表示のまま変わらない。

回答:ブラウザの制限。大容量ファイルの転送には専用のソフトを使って欲しい。


残る疑問は、1mb程度のファイルでも0kb of 0kbで転送されなかったことがあるということだ。

これは再度質問してみたいと思っているが、おそらくネットワーク+ブラウザが原因で、解決は出来ないだろう。

まぁそれは滅多に起こることではないので、良しとするとしても、自分にとってPogoplugのメリットはいったい何があるのかを考えなおす必要がでてきた。
iphoneなどをもっていればメリットもあるようだが、持つつもりもないのであまり意味は無い。


<Pogoplugのメリット>
●ローカルLANを使ってファイルを共有、保存できる。(写真などは、アップロードする必要がない)
●手軽に日本の家族に写真を見せられる。(低解像度だが)
●数mbのファイルの転送 (ファイル転送サービスやホスティングと違いダウンロードする必要がない)
●外付けHDDで壊れても良いものでNAS機能が付いてないものが使える。

<期待していたのにできないことや問題>
●大容量ファイルの転送ができない。
●フォルダごとの転送(関わった作品のデータバックアップ。デモリール用)(専用ソフトを使えば可)
●ようするにポータブルHDDの代りにはならない。
●ムービーファイルの再生(これから変わってくる可能性あり)
●ダウンロード速度が遅い
●日本の家族に見せる場合、画面メニューが英語


今現時点で自分が思っているのは、あってもいいしなくてもいいという感じ。
ファイルの転送速度を考えると、ホスティングサービスや写真共有サイトを使っても良いかなと思うのだが、その場合アップロードの時間がかかる。
小型のPCを買ってサーバーにして、そこからアップロードするようにすればいいのかもしれないが。

返品するかどうするか、もう少し使ってみて考えたい。

-------以下、原文-------------

Sounds like a good, secure setup! If you hit your maximum 384 KBPS for upload speed, a file would take about 26 hrs to transfer - so downloading from your Pogoplug to your office would take a long time indeed!

Uploading to your Pogoplug (which would essentially be using your download bandwidth, right?) would, at your top theoretical speed, take 1.4 hrs. In my experience I get about 1/4 of that speed, but yours may vary. In the tests that I ran trying to upload a 4.3 GB ISO to your shared folder, I got through about 500 mb in roughly 45 minutes before a connection error; consistent with what I would expect from your download bandwidth.

I spent a good deal of time with our engineers and our CTO to make sure we weren't seeing what we would consider to be a bug in this behavior; at this point, we think what you're seeing is simply the limitation of using a straight file copy for such a large file: that is, this behavior is expected.

If you need to move large files up to and down from your Pogoplug, I'd suggest using an application designed for large file transfers; one that can survive interruptions in connectivity. For downloads from your Pogoplug drive I like Free Download manager http://www.freedownloadmanager.org/ - simple, clean and best of all, free. For uploads to your Pogoplug drive I'd suggest a backup / sync package. So far I've had good results with SyncToy, Robosync, and Rsync, and Alway Sync.

I also wanted to personally thank you for sticking with this debugging process: we're pretty zealous about squashing bugs around here, so I wanted to make absolutely sure that what you were seeing was in fact simply due to the limitations of file copy over the Internet for very large files, and not due to a bug in our software. Hopefully you will find this answer satisfactory, and that some of our suggestions for accomplishing your tasks will work for you. If you feel I might have missed something, please let me know - I'm happy to investigate another angle if it seems warranted.


 

2009年5月28日木曜日

メモ: mel&toolリンク

3dcg labにおもしろそうなmelがありました。


migFractal.mel

migNormalTools

「変数のデータ型」と「アトリビュートのデータ型」

前回、パーティクル・アトリビュートのデータ型を「getAttr -type」で調べた。

結果としてはアトリビュートのデータ型を調べることはできることがわかったが、返ってきた値をよくみるといままで変数のデータ型でつかっていたのとは異なる表記のデータが返ってきている。

これはなぜなのか?
また返ってきた異なる表記から、どうデータ型を判断すべきなのか?

今回はこのあたりをより掘り下げてみた。



--------------------
<疑問>

「vectorArray」以外はすべて「floatArray」になると思っていたのに全く違う結果が出た。

「doubleArray」とは何だろう??


検索してみるとDigital Matrixの「パーティクルのアトリビュート」のページが引っかかった。


しかしながら、
worldCentroid ...「double3」
maxCount  ...「long」
と、他にもいままで見たことがないデータ型が書かれており、謎は深まるばかり。


--------------------
<MEL以外の言語での表記>

C言語では、「double」というと、倍精度の浮動小数点数を表している。
(参照:浮動小数点数型と誤差

通常float型が4バイト(32ビット)のところdouble型だと8バイト(64ビット)で値を表現する。
単純にデータ量が二倍であるので「double」ということらしい。


また「Visual Basic 図解 基礎解説」によると
「integer」 =整数型
「long」 =長整数型 (ちなみにC言語ではlong int(long)と呼ばれるらしい)
ということらしい。

ようするに通常のプログラミング言語では、同じint、floatでもその表現できる桁数の違いによってことなる型が存在しており、変数の宣言でもそれらが使われる。

しかしながらMELでは変数の宣言では、intとfloatはそれぞれ1種類しか存在しない。
にもかかわらず、実際のアトリビュートでは、本来の型表記とはことなるもう一つの型表記が使われている。
もしくは二種類の型が存在して、使い分けられている。


とりあえずここまでで他の言語には「double」「long」に関して、それぞれの表記が存在することがわかった。

しかし、「double3」に関しては説明がつかない。


--------------------
<MEL独自の型表記「double3」>

オンラインヘルプで「パーティクル アトリビュートのリスト」を見てみると

API 開発者は、Maya ヘルプに記載されたもの以外のアトリビュートもあることに注意してください。 ヘルプ > ノード & アトリビュート リファレンス(英語)(Help > Node and Attribute Reference)を選択して、パーティクルを検索します。

とある。さっそく
テクニカルドキュメント > ノード(英語)>particle
を見てみた。


このページで「double3」の型をもつアトリビュートを探してみた。
「centroid(ctd)」アトリビュートが「double3」だったので詳細を以下に記す。

centroid (ctd)は以下の三つの子アトリビュートを持っている。
centroidX (ctdx)
centroidY (ctdy)
centroidZ (ctdz)

しかしcentroid (ctd)のみが「double3」で子アトリビュートはそれぞれが「double」である。

要は「doble」が三つで構成されているという意味らしい。

実はこのアトリビュートの構成は、「数値複合アトリビュート(子アトリビュートがすべて数値)」と呼ばれるらしい。(参照:getAttrコマンド

またいかの説明も付け加えておきたい。
複合アトリビュートは 2 つ以上のアトリビュートで構成されています。
(参照:パーティクル アトリビュートのリスト


どのようなしくみなのかはわからないが、vectorの値をその親子関係において関連づけているデータ型と思われる。
これはそのノードのアトリビュートにおいて判断されていることであり、それはMELの領域ではなく、C言語で扱われる領域のことであり、おそらくそういったMayaのAPIに関連したことだろう。


話を戻すが、ということは通常のトランスフォームノードのTranslateなども同じdouble3なのかもしれない。
早速調べてみた。

getAttr -typ particle1.translate;
// Result: double3 //

getAttr -typ particle1.rotate;
// Result: double3 //

getAttr -typ particle1.scale;
// Result: double3 //

見事、どれも「double3」だった。

試しに一つのアトリビュートXのみを選択して調べてみると、
getAttr -typ particle1.translateX;
// Result: doubleLinear //

という値を返してきた。
ますます深みにはまり始めたので、ここらでいろいろ探るのは止めておく....。




--------------------
<関連づけ>

どうやら、getAttrコマンドで返してくるデータ型は、より詳しい表記になっているらしい。

ただ、返ってくるデータ型の表記と変数などで使われるデータ型の表記との関連性がすっきりしないので、もういちどオンラインヘルプの「パーティクル アトリビュートのリスト」をよく見てみた。



これまでの調査で、doubleArrayと表示された「mass」と「lifeSpanPP」,longと表示された「maxCount」について調べてみたところ以下のようになっていた。

mass     ...float array
lifeSpanPP ...float array
MaxCount ...integer


これをgetAttrのデータ型に関連づけると

mass    ...float array ...double array
lifeSpanPP ...float array ...double array
MaxCount   ...integer  ...long

ということになる。

double3においては、
double3 ...float(数値複合アトリビュート

になるがこれを変数では、ベクトル(vector)で表現するのかどうかは現時点では不明。



--------------------
<アトリビュートのデータ型>

オンラインヘルプでaddAttr,setAttrを見ると、アトリビュートには通常のこのような数多くのバリエーションのデータタイプを指定できることがわかる。

addAttr」では簡単に一覧が表記されており、

setAttr」では、それぞれのアトリビュートの詳細を知ることが出来る。



--------------------
<残る疑問>

MELで変数宣言をするときには、アトリビュートのデータタイプほどの細かな指定をすることはない。
それによってデータのタイプの数を減らし、シンプルになるというメリットもある。

しかし、変数でfloat型(vector含む)を指定した変数の値はすべて倍精度として扱われているのか? という疑問が残る。

実際の変数宣言とMaya内部でのデータの取り扱いの違いについて、関連をのべた文献がいまのところ見つからない。

getAttrコマンドで返ってくる値は、変数のデータ型に準拠する物ではない。

しかしアトリビュートのデータ型はアトリビュート同志の結合やデータのやりとりにとってより重要な意味を持ってくるとことが推測されるので、相互の関連について知っておく必要はあるはずだが。

そのことについて詳しく説明してある文献、もしくはオンラインヘルプのページはあるのだろうか?

 

アトリビュートのデータタイプを調べる。

他の人が作ったパーティクルにはその人独自のカスタムアトリビュートが追加されていることがある。

そのシーンに新しいパーティクルを追加し、同じ動きをさせるには同じエクスプレッション、同じカスタム・アトリビュートを作ることが必要になる。

エクスプレッションに関しては、コピペしてノード名を変えるぐらいでよいのだが、カスタムアトリビュートを作るにはそのデータ型をしらないと作れない。

今回はそれを知る方法を調べてみた。


--------------------
<AddAttributeウィンドウ>

まずアトリビュートのデータ型にはどのようなものがあるのか?

ParticleShapeノードのアトリビュートから
AddDynaicAttributes>「General」>「AddAttribute」ウィンドウ
を表示すれば、どんなデータタイプがあるかを見ることが出来る。



enumという見慣れないデータタイプがあるが、これはオンラインヘルプによると
「列挙型」リスト、つまりプルダウン リストから選択ができるアトリビュートのこと。


--------------------
<パーティクル単位のアトリビュート>

さて、パーティクルに追加される主なカスタムアトリビュートはパーティクル単位(Per Particle)のアトリビュートである。

PerParticleのアトリビュートは画面を見るとわかるように配列(array)である。

これは複合型アトリビュートとヘルプでは、説明されており、
一つのアトリビュート名で、複数のパーティクルの個々の値を格納するために配列が用いられている。


ちなみに「Scalar」を選択すると、一つの値しか格納せず、それがオブジェクトのパーティクル全体に影響することになる。


--------------------
<パーティクル単位は二つのタイプのみ!>

さて、このウィンドウでやってみるとわかるが、「PerParticle」を選択した場合には選択できるデータタイプは、「vector」か「float」の二つだけになる。


上記のヘルプにはベクトル配列型のデフォルトのアトリビュートの例として以下の三つがある。
position(位置)
Velocity(速度)
Acceleration(アクセラレーション)


カスタムアトリビュートでのベクトル配列では、Colorを追加したときに表示される
rgbPP(色)

がある。


--------------------
<アトリビュートタイプを調べる>

さて、PerParticleアトリビュートには他にもいろいろなアトリビュート名があるのでエクササイズとして、それぞれ「vector」なのか「float」なのかを確かめてみたい。


アトリビュート名を指定して、アトリビュートのデータ型を返してくるだけなのだが、
「listAttr」はアトリビュート名をリストアップするだけで、そのタイプを調べるには役不足。

これに使えるのは「getAttr」コマンド+「-typ(-type)」フラグ(参照:オンラインヘルプ

(使い方)
例:positionアトリビュート

getAttr -typ particleShape1.position
// Result: vectorArray //


これで「Per Particle (Array) Attributes」にリストされているすべてのアトリビュートのタイプを調べてみた。結果は以下の通り。

position         ...vectorArray
rampPosition     ...vectorArray
velocity         ...vectorArray
rampVelocity     ...vectorArray
acceleration     ...vectorArray
rampAcceleration ...vectorArray
mass          ...doubleArray
lifespanPP      ...doubleArray
worldVelocity    ...vectorArray


これでアトリビュート名からそのデータタイプを知ることが出来る。
ただ疑問が残る...。

 

Mayaインタフェイスを英語に変更

Mayaのインターフェイスを英語表示に変えました。
やはりこっちの方がすっきりします。

切り替え方法の詳細はOSXの手順も含めて
AutodesukTechinicalSupportページ
にあります。

以下は、win版の簡単なまとめ。

システム環境変数の新規ボタンをクリックして
変数名: MAYA_UI_LANGUAGE
変数値: 英語なら「en」日本語なら「ja

Mayaの起動時にPreferenceを引き継ぐか聞いてきたので「新規作成」にしてしまい、ショートカットがすべて消えてしまったので再設定。

 

2009年5月27日水曜日

就職活動 (8) : previs

今日、vfx-pro.comで応募していたCFX会社へResumeを送ってみた。
ポジションはprevis

どちらにしてもあと一月(ToT)もすれば今の会社に仕事が来るのはわかっているので、短期の仕事しか出来ないと思うが、駄目だったら一月仕事無しなのでそれよりはましかと...。
 

アクセス数120超えるか??

今日は、アクセス数がかなりアップしました。
アクセスしてくださった方ありがとうございました。

おそらく、CGトラッキングからアクセスしてこられたかたが多いと思います、ありがとうございます。
派手目のニュースを期待してこられた方はがっかりされたかもしれませんね、すみません。

アクセス数は、ここ二日で一日の最高アクセス数を70、84と更新し続け、本日は、現時点で今までの最高である116を更新。
あと5時間あるので、おそらく120は超えると思います。

まぁ今回は一時的な物なので、すぐに元のレンジに近い50前後に戻ると思いますが。
これからも宜しくお願いします。


追記:結果は155でした。これからも宜しくお願いします。

返品!! PogoPlug (11)

いくらまっても返事が来ないので、「もうすぐ30日の返品可能期間をすぎてしまうよ。こちらが情報をあげても何日も後になってやっとチェックされたりとどうみても時間稼ぎにしか思えない。延長できるなら永久に待っても良いけどね。」とサポートへメールしたところ。

「延長するからあと30日まってくれ」と言ってきた。
しかも今になって「エンジニアがチェックしたところソフトの問題で、修正にはまだ時間がかかる」と言ってきた。

今までやっぱりチェックしてなかったんだな....。
とりあえず、待つことにしたが、直後に会社と自宅のネットワークの構成を聞いてきた。
スイッチやハブをつかっているかなど、細かなことに渡るがうちの会社のエンジニアにきいたところスイッチやハブは関係ないだろう!?と言ってた。
うまくアップロードできるときもあるので、あまり関係ないと、思うんだけどね。
まぁもしもというケースがあるから万全を期して聞いているのだろうけど。

これじゃまるでベータテスター....。
少しづつ信頼感を感じられなくなってきたクラウド・エンジン社.....。

そういえば、4.3GBのファイルを自宅からアップロードしようとしたら30時間以上かかるとサポートの人はいっていたが、そこまで行かないにしろ、数時間はかかる。

とうことは、緊急時や他に手段がないときは仕方がないが、実用的とはいえない。
一ヶ月10ドルぐらい払っても、インターネットでアクセスができるファイルストレージサービスと写真サイトを使った方が良いのかも。

Pogoplug、発想は良いんだけど、pogplug自体が貧弱なのと、アメリカのネットワークがまだシステムを使いこなせるほど追いついていないのが現状ではないかと思う。

 

初心者プログラミング教育のブレイクスルーになるか?

注:いつもそうですが、今回はとくに内容がうまくまとまってません。読みにくかったらすみません。

ネットサーフィンをしているときに「マンガでわかる電気」が英語版になったという情報がのっているのをみて何だろうと思い見てみるとブックプラス「マンガでわかる」シリーズというものがあることをしった。

そのページを見ていると、同じシリーズの「マンガでわかるシーケンス制御」を紹介していた。
その「シーケンス制御」という言葉をみて、「もしかしたら...」とひらめいて早速wikiで調べてみました。

シーケンス制御(Wiki)

機械に行わせる動作を順序正しく覚えさせておくことにより、始動ボタンを押すだけで、後は全部制御装置が仕事を行う場合などに用いられる

シーケンス制御は、全自動洗濯機・エアコンといった私達の身の周りにある家庭用電気器具をはじめ、信号機・自動販売機・工場の産業ロボットや自動化設備・ビルのエレベーターや自動ドア・発電所や変電所に至るまで、さまざまな装置や設備に使われている。

単なるスタート/ストップに限る単純なものから複雑な信号処理を必要とする大規模なものまで存在しており、あらゆる分野で活用され、自動化・省力化に大きく貢献している。


ということ、もともと機械好きだったので言葉自体は聞いたことがあったが、特に勉強をしたこともなく向上などの現場作業などで、なるほどこんなものかという感じで理解していたぐらいだった。

簡単に言うと、
「スイッチ一つで、一通りの動作をして目的を達成できるしくみ」
「スイッチ一つで複数の部品や装置を自動制御する」
とういことになるだろう。


以前のエントリ「プログラミング教育の難しさ。」で「プログラミングにおけるたとえ話」について文句をいったが、この問題がもしかしたら「シーケンス制御」で解決するのではないかというふうに思った。

「たとえ話」がいやなのは、プログラムというものを人間の日常生活というまったく異質のものに置き換えているから、たとえになっているようでなっていない。
まぁ「たとえ」なので、それは説明を書いた人の自由だが、読む側としては非常に理解しづらい。

しかし、機械に関する事に置き換えれば、すっきりした、理解しやすい「たとえ話」になるのではないだろうか。

このキーワードの周辺で、掘り下げていけばプログラミングの思考法の基礎を身につけられるのではないかという気がするのだ。。


--------------------
いままでプログラミングにおいて「流れ」の重要性について説明する文章では、、
朝起きて歯を磨いて、パンを食べて服を着替えて、靴を履いて・・・・・
本棚から本をだし、引き出しからノートと鉛筆をだし・・・・・
卒業式で、最初にあいさつ、次に・・・・

こういうたとえ話をされると自分の場合は理解が深まるどころか、ますます混乱する
実際に上記のような事柄は順番を簡単に入れ替えることができ、何より日常生活をたとえに使っている場合、ダレもそこまで計画して行動していないだろうと思ってしまう。

もしそういった説明をする人がいたら、「でも朝、食パンをやきたいなら、まずパンをトースターにいれてダイヤルを調整して、スイッチを入れるでしょう?」というかもしれない。
でもそれは人間が機械に対して行っている部分である。

上記のようなたとえ話では、「人間が自分を含む人間や動物にたいしておこなう行動」が混同されて入っている。
もしかしたらコンピュータを擬人的に扱う考え方がそうさせるのかもしれないが、これがそもそも混乱を生み出す原因になっているように思う。

コンピュータの説明をしたいなら機械の制御に徹した方がいいと思う。

人間や動物を対象にすると、非常に現実感がなく違和感だらけになる。
(まぁ小学校低学年や幼稚園児には有効かもしれないが...。)
そしてそれが、プログラミングを勉強する気を失わせる原因にもなっていた。


--------------------
「シーケンス制御」のなんらかの解説を元に、多少機械の専門的な部分をはしょって、要点だけをまとめていけばプログラミングも理解できるのではないかと思う。

もともとプログラムとは「ルーブ・ゴールドバーグ・マシンピタゴラ装置)」を作るようなものだと思っている。

シーケンス制御は、複数の回路や装置を目的を果たすように導いていき、非常に似ていると思う。
それはまるでオーケストラで指揮をするように全体をある方向へ導いていくようでもある。


「シーケンス制御」を柱として、プログラミングの説明をすることの利点は、
●一つ一つの装置は特定の目的を持っていて、限定された動作をする。(関数やコマンドのように)
●順番も多くの場合、ある程度きまってくる。(プログラミングの流れのように)
●プログラミング言語を使わなくてもプログラミングの独自性(特徴)がわかる。
●多くの場合、知覚できる物理現象として認識可能。リアリティーが高い。


特に初心者の場合、イメージがしにくいコマンドからではなく、リアリティーが高くイメージがつかみやすい話から入ることができる。


融通性の無さや、一方通行性、各装置の自動性、順番、すべてを自分が指揮する必要性、コントロールの方法や領域は目的に合わせていくらでも考えられる、機械としての制限、etc. 
いろいろな基礎概念においてシーケンス制御とプログラミングには共通点があるような気がする。


プログラミングを人間の活動に置き換えるのではなく、機械を機械にたとえ、機械として感じ、機械として考えることは、たとえ話から、実際のプログラミング作業へ移行していときにもスムースに行くのではないかと思う。


ただ、現時点ではシーケンス制御という分野について、あまり詳しいことは知らないので
以上は推測の域をでないが、そのうち、詳しく見ていきたい。


参考Link
http://wwwf2.mitsubishielectric.co.jp/fair/fa_basic/01/11.htm

http://www.at-system.jp/

http://sequence.goldhurricane.com/


--------------------
さて、この「マンガでわかる」シリーズ
最初はよくあるマンガの学習書かなと思ったんだけど、いろいろ見てみると主題となっている内容が少々、専門的で、プログラミングに関係ありそうな物もある

マンガでわかる線形代数 などはとくにCGに関係しそうだし、
他にも、いっぱいある。

微分積分、物理力学、電気、フーリエ解析、データベース、統計学、統計学 因子分析編、統計学 回帰分析編、etc.


まずはシーケンス制御の本を、どれだけわかりやすいか一度読んでみたい。


今のところ、正直「マンガでわかる」とは思っていない。

この手の本は、要点となることや計算部分は、マンガといっても台詞の中で文章で表現していることがほとんどで、ひどいものだと、それをイラストで表現することさえしていない。

本屋で立ち読みできればいいのだが、内容がマニアックすぎてこちらの本屋にはおいてなさそうなので、買うしかないが、こちらで買うと結局は、1.5倍ぐらいの値段になってしまう。

こんど給料アップしたら、買ってみるか...。
 

2009年5月25日月曜日

配列への値の追加  (2)

前回のスクリプトを見直したときおかしな点をみつけた。
printで出力されるときに、配列名[5]-[9]を文字列で表示しているが、これではその配列要素が存在するかのように見えてしまう。

配列の内容を表示するのは便利がいいのだが、少し変えてやる必要があるようだ。

二回目の配列へ値を格納した後にその配列のサイズを測って、そのサイズを元にfor文のループ数を決めることにした。

{
string $aaa[] = `ls -sl`;
print $aaa;
string $aaa[] = `ls -sl`;
int $size =size($aaa);

for ($i=0; $i<$size; $i++){
print ("$aaa["+$i+"]"+ "=" + $aaa[$i]+"\n");
}
}

これで正確に表示されるようになった。

locator1
locator2
locator3
locator4
locator5
$aaa[0]=locator1
$aaa[1]=locator2
$aaa[2]=locator3
$aaa[3]=locator4
$aaa[4]=locator5


また趣旨としては、複数オブジェクト名を格納した配列ににあらたに複数のオブジェクトを追加する方法を模索しています。
おそらくただ単品のオブジェクトを追加していくなら以下のような複雑な手順は必要無いはず。

そして、実際の作業では一つのグループ内にあるオブジェクトを配列に格納したあと、別のグループ内にあるオブジェクトをその配列に加えていくような状況でつかえると思っています。


まず配列の仕組みを考えると、
最初に値を格納するときに自動的に(もしくはサイズを指定したときには宣言時に)配列のサイズが決まる。。

一度サイズが決まった配列に、続けて別の値を入れてやる場合は、そのサイズを変更しなくてはならない。

オンラインヘルプの「配列のサイズの変更」で、配列の要素を指定すればサイズを大きくできることがわかった。

他に簡単そうな方法は書かれていないのでこれを使うしかなさそうだ。

実際に新しく加えるオブジェクトの総数をあらかじめ知ることはできないので、新しいオブジェクトを別の配列に格納して整理し、それからその値を格納したい配列に入れていくという手順が必要になる。

1)最初の配列に値を格納。(配列1)
2)そのサイズを得る。(サイズ1)
3)新しい配列にあらたなオブジェクトを格納。(配列2)
4)そのサイズを得る。(サイズ2)
5)for($i=サイズ1; $i<サイズ1+サイズ2;$i+1)
6)for文の中で、配列2の値を頭から順に配列1にコピーしていく。


最後の部分を具体的に書くと、
$aaa[5]から順番に配列2の[0]からの値を格納していく。

{
string $aaa[] = `ls -sl`;
int $size1 = size($aaa);
print $aaa;

string $bbb[] = `ls -sl`;
int $size2 =size($bbb);

for ($i=$size1; $i<($size1+$size2); $i++){
$aaa[$i] = $bbb[$i-$size1];
}

for ($i=0; $i<($size1+$size2); $i++){
print ("$aaa["+$i+"]"+ "=" + $aaa[$i]+"\n");
}
}


結果は以下の通り、ちゃんと動作してくれました。

locator1
locator2
locator3
locator4
locator5
$aaa[0]=locator1
$aaa[1]=locator2
$aaa[2]=locator3
$aaa[3]=locator4
$aaa[4]=locator5
$aaa[5]=locator1
$aaa[6]=locator2
$aaa[7]=locator3
$aaa[8]=locator4
$aaa[9]=locator5


実際の所この方法がどれほど使えるのかわからないし、他にもっと簡単な方法もあるような気がしますが、とりあえず、いろいろとスクリプトを考える練習のために思いついたことを試してみました。

2009年5月23日土曜日

配列への値の追加  (1)

配列は数を指定しないで、$aaa[]とうい形で指定することができるし、それに代入することができる。

しかしながらその配列にすでにいくつかの値が格納されている状況でさらに追加する場合は、同じ記述でよいのか?とふと疑問に思った。

ヘルプを見ても、書かれていないので、ちょっとテストしてみることにした。
{
string $aaa[] = `ls -sl`;
print $aaa;
string $aaa[] = `ls -sl`;

for ($i=0; $i<10;>
print ("$aaa["+$i+"]"+ "=" + $aaa[$i]+"\n");
}
}


5つのロケータを作り、選択後、このスクリプトを実行した。

選択したオブジェクトを$aaaに読み込んでprintにより配列全体の値を表示。
もう一度、同じ手順を繰り返し、今度は$aaaのどの値が表示されているのかをわかるようにした。

同じ事を二回繰り返しているわけだが、
もし二回目に値を格納するとき、それまでの配列の値の最後尾から継続されて格納されるのであれば

配列の番号と一緒に値が表示されるときに、配列[9]までの合計10の値が表示されるはず。
しかもlocator1から5までが二回繰り返されて表示されるはず。

しかしながら結果は以下のようになった。


locator1
locator2
locator3
locator4
locator5
$aaa[0]=locator1
$aaa[1]=locator2
$aaa[2]=locator3
$aaa[3]=locator4
$aaa[4]=locator5
$aaa[5]=
$aaa[6]=
$aaa[7]=
$aaa[8]=
$aaa[9]=

最初の$aaa[n]の表記がない部分は二行目のprint文で出力された値
$aaa[n]の表記がある部分は5行目のprint文で出力された値

みてわかるように配列$aaa[5]~$aaa[9]には値がない。

ようするに$aaa[0]~$aaa[4]までが上書きされていることになる。

通常の変数と同じようになっているということだ。

ではどうすればよいのか?

 

あたった

まさか、あたるとは思っていなかったアレがあたりました。
あたったからといってすべてのプロセスが終わるまでは安心は出来ないので、急いで書類を提出せねば。

 

2009年5月22日金曜日

スクリプティングと模型制作

最近、スクリプトを作っていくのが少しづつおもしろくなってきた。

それに大体自分が作業するときのパターンがあるのがわかった。

よく考えてみたら模型制作とよく似ている。
模型自体最近は作ってないが、スクリプティングをしていて共通点を感じる。

もしかしたらそれだからこそおもしろく感じるのかもしれない。
その共通点を以下に書き出してみた。

おもしろいのはどうやって問題を解決するかそのプランを練り、
部品をさがしその使い方を調べ、問題があれば解決方法をみつける。
そして最後に個別に作った物を統合する。
各部品も相互に関連していたり、その接合していく順番に気をつけなくてはいけなかったりする。

まさにフルスクラッチ的な要素でいっぱい。

1)制作プランを練る。必要なら簡単でも良いので設計図を描く。(アルゴリズムを作る)
2)そこに必要な部品を洗い出す。(コマンドを見つける)
3)部品の接合や、使い方を調べ、問題を解決する方法をみつけておく。(コマンドのテスト)
4)ここまででアルゴリズムを見直す必要があれば修正する。
5)制作
6)テスト

 

過剰な医薬品通信販売規制を検証するシンポジウム

左にも貼っておきましたが、自分にとっても結構深刻な問題なので、少し宣伝します。

医薬品通信販売規制に反対します!

エクササイズ: ロケータ位置を頂点としてポリゴンを作成する。 (2)

前回の「エクササイズ: ロケータ位置を頂点としてポリゴンを作成する。 (1)」の続き。


前回までで、ロケータとポリゴン頂点のトランスレートをコネクトできるとわかったので、今回はその微調整の手順を検証することから始めたい。

ポリゴン頂点を「polyCreateFacet」を使って作成した場合、全ての点が「0 0 0」の頂点座標を持つことがわかった。

これは「ポリゴン作成ツール」で作成したポリゴンの頂点を選択し、チャンネル・ボックスに表示されるCVをクリックすれば表示されるので容易に確認できる。


頂点をこのまま各ロケーターのトランスレートにコネクトすると、
現在のロケーターの座標が現在の頂点位置を原点として加算されるため、位置がずれてしまう。

わからない人は、以下の手順をやって確認してみて欲しい。
1)ロケータを一つ作成。
2)ポリゴン作成ツールで三角形を作成。
3)ロケータのトランスレートと、作成したポリゴンの一つの頂点をコネクションエディターで接続する。
(詳細は前回のエントリを参照



その微調整のためには、

●コネクトする際に値をオフセット補正(+-)する。
●ポリゴン作成時に頂点をまず0 0 0へ作成し、その後ロケータ位置へ移動する。

の二つの方法がある。



----------------------------------------
しかし、コネクトする際に値をオフセットする方法は簡単そうだが、アニメーションが進むにつれて誤差がでてくるような気がする。

別にMayaの中で行われる計算についてはっきりとした裏付けがあって言っているわけではなく、

以前、二つのオブジェクトの位置の誤差を電卓で計算して、チャンネルボックスでマイナスして入力したが、二つのオブジェクトの位置が微妙に合わないという状況を経験したことがあるので、あまりMayaの計算を信用していないということ。

またもう一つの理由はコンピュータ全体に言えることだが、「浮動小数点の誤差」の問題だ。

これはコンピュータが二進数で計算するために、比較的単純な計算でさえ誤差が生じることがある。 これは「浮動小数点数の誤差」として知られている。


これはプログラミングだけでなくコンピュータをつかった計算では比較的知られた問題で、以下のサイトを見てもらえればそれがわかるだろう。

学びの場.comにある渡辺俊雄氏の誤差とどう向き合うか」。 とてもわかりやすい。

unibonさんのサイトの演算誤差について(10進数と2進数)も参考になるだろう。

アンクル・トムさんによるパソコンとITの雑学ブログコンピュータの計算誤差

ITproの「コンピュータにおける「データ表現」の基礎(第5回)には「誤差」の種類別に解説がある。



ここに書かれているように人間の頭では十分計算可能な、単純な物でも二進数をつかった計算では誤差が生じてしまう。

そしてそれはMayaも例外ではない。
ためしに上記「誤差とどう向き合うか」の例を参考にしてスクリプトエディターで試してみた。
そしていろいろ試した結果、誤差がでてくるのは20桁以後ということがわかった。
ぜひ試してみて欲しい。translateで「4」もずれれば結構大きな差になることがある。


19桁
print (1111111111111111115-1111111111111111111);
答え:4

20桁
print (11111111111111111115-11111111111111111111);
答え:0

このような数字をそのまま使うわけではないので、そのままMayaの座標計算で影響が出るかどうかはやってみないとわからないが、それを試す時間がもったいない。


それから、この結果はコンピュータの構成によって異なる可能性があるので(特に32ビットと64ビットでは違う可能性大)うちの構成を参考までに下に書いておきます。
OS:Windows XP sp2 32bit
CPU:Athron MP (x86)



--------------------
そこで二つ目の方法、「頂点を原点に作成し、ロケータの位置へ移動する」だが、よく考えたら非常に簡単
各頂点作成後、頂点をロケータへコネクトすれば頂点位置は勝手にロケータ位置へ動いてくれる。


これで想定できる問題はほぼ片付いたので部品の組み立てに入りたい。

もう一度流れを見てみると
0)ロケータを選択する。
1)ロケータの位置情報を得る。
2)頂点を作成してから、頂点をロケータ位置へ移動する。
3)上記を繰り返しポリゴンを作成。
4)ロケータの位置が移動したとき、ポリゴンの各頂点も更新されるようにする。
この1~4はループ内で行い、ひとつのロケータ、ひとつの頂点ごとにステップを踏む必要がある。


少しづつ確認しながらやっていると以下の時点でエラーがでた。
{

string $obj[] = `ls -sl`; //選択した全ロケータの名前を配列に格納。
int $total = size($obj); //for文で使うため、ロケータの総数を得る。

for ($i=0; $i<$total; $i++){

vector $L_position = `xform -q -ws -t $obj[$i]`; //ロケータの座標を取得
polyCreateFacet -p $L_position;

}



// エラー: 引数の解析エラーです。 //

$L_positionのところを 0 0 0にすると

// エラー: ポイント数が不足しています: 最低 3 つが必要です。 //
というエラーに変わる,これはエラーではあるが数値としての0 0 0は認識していると言うことだ。

ためしに
{
$x=1;
$y=1;
$z=0;
polyCreateFacet -p $x $y $z;
}

と入力すると、
// エラー: ポイント数が不足しています: 最低 3 つが必要です。 //
と同じエラーなので変数が使えないわけではないらしい。
ただ、vector形式を使うことはできないらしい。


それに今気がついたがpolyCreateFacetでは最低3つのポイントがないと作れないので、for文と組み合わせて頂点を一つづつ作ることは出来ない。
それに後からポイントを追加できるのかどうかもわからない。(おそらく違うコマンドが必要)
新たな壁が...。


ならまずすべてを 0 0 0の位置に作成してからコネクトすればどうか?
どうせ順番はかわらないし、コネクトした時点で頂点の位置はロケータの位置と同じになるはず。



--------------------
これでいけるかもしれない。

アルゴリズムを書き直してみた。わかりにくかった説明もついでに修正。
0)ロケータを選択する。
1)ロケータの数だけ、0 0 0へ頂点を作成する。(polyCreateFacet -p)
2)頂点とロケータのトランスレートをコネクトする。(connectAttr)


これだとロケータの位置情報をいちいち取得する必要もなくすっきりまとまりそうだ。
気を取り直して作業再開。


--------------------
よく考えてみると、connectAttrの使い方を調べてなかった。
オンラインヘルプの例をみると以下のような形式で接続できる。

connectAttr 1stObjectName.Attr 2ndObjectName.Attr ;

それに、translateをコネクトするのだが、前回のテストのようにxyzを別々にするのではなく、translate全体を一度にコネクトできるかどうか試してみたい。

まず
locator1
polySurface1.vtx[1]
の接続を考えてみる。

前回、調べた頂点のアトリビュート名を引用しておく。
pnts[0]
pnts[0].pntx
pnts[0].pnty
pnts[0].pntz


最初の「pnts[n]」は、ポイントのアトリビュート名であると共にトランスレートを示しているのだと思う。
そしてそれをさらに細分化したのがpntx,y,zだろう。
なのでロケータのtranslateと頂点のpntsを接続すればよいはずだ。

アトリビュート名をつけて記述しなおすと接続するアトリビュート名はそれぞれ
locator1.translate
polySurface1.pnts[1]
ということでよいだろうか、

コマンドにすると以下のようになる。
connectAttr locator1.translate polySurface1.pnts[1]

成功!


さて、ここで注意すべき点がひとつあった。
めんどくさいのでここでは追求しないが、ポリゴンの名前だ。

コンポーネントはpolySurface1Shape(シェイプノード)に含まているはずだったのだが、polySurface1(トランスフォームノード)で問題ないようだ。


さて作業開始。とりあえず最後まで書いてみた。

テスト方法は、以下の通り。
1)ロケータを三つ以上作成しばらばらになるように任意の位置へ移動する。
2)ロケータを順番に選び、下記のスクリプトを実行する。
3)ポリゴンが作成されたらロケータを動かしてみて、各頂点がそれぞれのロケータについて動くようなら成功。



{
string $point;
string $polyName;

string $obj[] = `ls -sl`; //選択した全ロケータの名前を配列に格納。
int $total = size($obj); //for文で使うため、ロケータの総数を得る。

// すべてのロケータと同じ数、-p 0 0 0 を繰り返す。(同じ頂点数)
for ($i=0; $i<$total; $i++){

if ($i==0) {
$point = " -p 0 0 0 ";
}

else {
$point =$point + $point;
}
}

eval ("polyCreateFacet" + $point + ";"); // ポリゴンオブジェクトを作成。
$PolyName = `ls -sl`;//今作成されたポリゴンのノード名を取得。

for ($i=0; $i<$total; $i++){

 //ロケータのアトリビュート名まで変数へ格納
string $loc_name = $obj[$i] + ".translate ";

 //ポリゴンのアトリビュート名までを変数へ格納
string $vtx_name = $polyName + ".pnts[" + $i + "]";

connectAttr $loc_name $vtx_name;
}
}


うまく動いたが、頂点が一つ多く0 0 0に作成されている。
もしかしたらこれは先日の「exercise: ロケータ位置をpvとするカーブを描く」の時と同じ間違い??
そうすると頂点一つどころかたくさんの頂点が0 0 0へ存在していることになる。

前回うまくいったループを見直してみる。
for($i=0; $i<$total; $i++){
$pObj = `xform -q -t -ws $name[$i]`;
$point = $point + " -p " +$pObj;
}


今回うまくいかなかったのはこれ
for ($i=0; $i<$total; $i++){

if ($i==0) {
$point = " -p 0 0 0 ";
}

else {
$point =$point + $point;
}
}



変数名が違うのとif文は使っていなかった。
どうもif文を安易に使ってしまう傾向がある。
よく考えたら間違っているのだが、作っている最中はこれで間違いないと思っている。

for ($i=0; $i<$total; $i++){
$point0 = " -p 0 0 0 ";
$point =$point + $point0;
}

ポイント:
1)追加していく値だけを最初の文で作成
2)次の文では左辺の変数名と同じものを右辺へ入れそれに先ほどの値の入った変数を追加してやる。

最初の時点で右辺にある$pointには値がないので-p 0 0 0が$pointに入っている。
ループ二回目で$pointの値(-p 0 0 0)に$point0の値(-p 0 0 0)が追加され $pointの値は(-p 0 0 0 -p 0 0 0)となる。
ループ三回目では、$pointの値(-p 0 0 0 -p 0 0 0)に$point0の値(-p 0 0 0)が追加され $pointの値は(-p 0 0 0 -p 0 0 0 -p 0 0 0)となる。


これでうまくいきそうだ。
もう一回、新しいループの部品を含めて修正してみた。

{
string $point;
string $polyName;

string $obj[] = `ls -sl`;
int $total = size($obj);for ($i=0; $i<$total; $i++){
$point0 = " -p 0 0 0 ";
$point =$point + $point0;
}

eval ("polyCreateFacet" + $point + ";");
$PolyName = `ls -sl`;

for ($i=0; $i<$total; $i++){
string $loc_name = $obj[$i] + ".translate ";
string $vtx_name = $polyName + ".pnts[" + $i + "]";
connectAttr $loc_name $vtx_name;
}

}


これでうまくいった。大成功!


--------------------
今後の課題:
ロケータを選択するとき線が交差しないように順番に選んでやる必要がある。
たとえばロケータが輪になっているとすると、
一つのロケータから始め、そのとなり、そして次はそのとなりという順番に選ぶ必要がある。
飛び飛びに選んではいけない。

そのためロケータの選択時には上記の点に気をつけて慎重にやらなくてはいけない。
選ぶ順番が違うと不自然に頂点のつながりが飛んでしまい、ポリゴン面が交差してしまう。

無作為に選択しても、これを解決することができれば、よいのだが。

 
また今回はトータルでほぼ一日がかりの作業時間となっている。
実際の現場でこのスクリプトにこれだけの時間を掛けるだけのメリットがあるのかどうか?
たしかにこの方法でしかうまくいかないのなら時間を掛ける必要があるが、
何度も使うわけではなく一度しかつかわないなら、ポリゴン作成ツールとコネクションエディターを使えば長くても1時間もかからない。

このようなスクリプトなら1時間程度で作れなくては実用的とは言えないということか。

まだまだ勉強が必要だなとひしひしと感じる。

 

2009年5月21日木曜日

「プログラミング言語」習得への道

プログラミング言語を「言語」ととらえれば、

プログラミング言語を習得するということは、新たな言語を使えるようになるという事だ。

英語やフランス語といった自然言語との違いは、
●話す言語ではない。
●相手は機械(コンピュータ)である。
●コミュニケーションは一方通行である。
●コミュニケーションされる内容は、論理的に整理された情報のみ。

異論はあるかもしれない。
たとえばエンジニア同士でプログラムやコマンドを口頭で説明することはあるではないか?という人もいるだろう。
口頭で説明したとしてもそれはコミュニケーションをするためにプログラミング言語を用いているわけではない。
プログラミング言語だけで、コミュニケーションをする人はいない。(もしかしたら例外的にいるかもしれないがw通常はいない)
よって話すための言語ではないし、プログラミング言語を使う相手は人間ではない。

プログラミングしているときに、コンピュータはエラーを返してくることもある。
これは相互のコミュニケーションであり、一方通行ではないという人もいるだろう。

エラーを返してくるとき、それはどこでどんな障害があるかを人間の言語、もしくは単語の羅列で返してくる。
単語の羅列のときに、プログラミング言語の文法で返してくることは少ないのではないかと思う。
プログラミング言語の文法でうまく動作しなかった場所や、内容を単語の羅列で返してくるだけである。
これは広義のコミュニケーションととらえることもできるがプログラミング言語の範疇には含まれないので、同じ言語でのコミュニケーションではない。

またコンピュータとプログラミング言語で無駄話をする人はいないだろう。
通常は、論理的に整理し、すべての整合性を考え、流れをよく考えたものが最終的なコミュニケーションとして成立する。


これらが最初にあげた自然言語との違いを説明してくれると思う。


-----------
ある言語、たとえば英語を他者とコミュニケーションできるレベルまで習得したら、その人の世界は広がることは誰にでもわかる。
プログラミング言語を、そのコミュニケーションが成立するレベルにまで修得すれば、当然その人の世界は広がることは容易に想像できる。

誤解があることを前提で、簡単な月並みな言い方をすれば「機械と話すことができるようになる」のだからすごいことだ。

これをCGという仕事の世界に当てはめて考えてみれば、今までよりもより多くのCGの領域を体験することができるようになるということだ。


プログラミング言語には多くの種類と入門書があるので、どれから手をつけるべきか迷うこともあるし、いくつかの言語を並行して学習するほうが効果的ではないかという疑問も出てくる。
MELスクリプト
C言語
Renderman言語
Python
Java
そのほかソフトウエア独自の言語。


これらの言語はどれも独自の入門書が出ており、文法も異なる。
CGの世界を見ると、多くの言語がつかわれており、TDには複数の言語を使うことが求められることもある。
一つを習得してから、別の言語を習ってと考えるといったい何年かかるのだろうと途方に暮れることもある。

しかしながら、よく言われるようにある言語を習得した人はほかの言語を習得するのも早い。
そういった人と入門者や初学者のつきあたる壁は異なるように感じる。
あきらかに壁の高さや厚さが違い、まったくの初心者は、畏敬の念を感じると共に、不公平を感じざるをえない。


この壁の違いはなんだろうか?


----------
多くの入門者はプログラミング言語のような独自のスタイルをもった言語になれていない。
そしてそれは先にのべた自然言語と異なる点である。
この、すべてのプログラミング言語に当てはまる部分がしっかりと感覚的に理解できていることが初学者を壁を破るためのポイントではないかと思う。

あるプログラミング言語を習得した人がほかの言語を習得するのが早いのはこの部分がクリアされているからだと思う。
プログラミング言語どうしの違いは、コマンド、記述の順番、記号の違いぐらいで、これらでさえ共通する部分は多々ある。
すこしダブルことだが、大きな違いをあげるとすればソフトウエアによる違いである。
レンダリングソフトと、Mayaなどの汎用3Dソフト。またそれらのソフトと汎用言語であるC言語では言語の目的としていることが異なるので、コマンドの数、種類が大きく異なることがある。といっても同じCGの範囲での作業なのである程度は相互に関連した知識に触れることはある。

記号の違いというのはたとえば変数の表記方法が言語によって違ったりすることである。
これは記号論で考えれば、「変数」という概念を扱う方法はかわっておらず、それを表記する「記号」が異なるだけである。


実際、プログラミング言語どうしの共通点は大きい。
●コマンドというものが存在する。
●変数がある。
●制御文がある。
●論理演算子や関数
これらを組み合わせて、プログラムをつくるのがどの言語にも共通する作業だ。

またプログラムを作成するときには、あることが終わってから次のことをする。
ある結果を出してからその結果を次のステップで使うという流れがあり、それを崩すことはプログラムが動作しなくなることをもある。

自然言語と違い、すべてが論理的に整然とまとめられておかなくてはならない。


これはアルゴリズムの部分だと思うが、プログラミング言語を使うときほど突き詰めて考えることは自然言語にはあまりない。
これがプログラミング言語に慣れていない人には結構つらいところである。



---------------
ここまでをまとめるとプログラミング言語の学習において、初学者の突き当る壁は、いろいろあるが特に入門者に言えることは
プログラミング言語と自然言語の違いではないかということだ。

その次に、コマンドや、変数といった具体的なことがくるのではないかと思う。


この自然言語との違いが感覚的に理解できたとき、多くのコマンドや文法を学ぶことがそれほど苦にならなくなるのだと思う。

しかしながら、言葉でそう書くことは簡単だが、実際にそれだけを分離してトレーニングできるのかどうかは疑問が残る。

「プログラムはたくさん読んで、書いて覚える」これはプログラミング言語習得への鉄則でもある。
そして英語などの自然言語でさえ、「たくさん読んで、たくさん使う」ことが習得への道とされている。
しかも、どちらも言われていることは「近道」はないし、山あり谷ありの険しい道だ。

今、考えているのは、それをなだらかな斜面にして、その道を一つ一つステップを踏んで行けば自然に習得できるドリルのようなもの。
ドリルを自分で作るのか、それとも既存のものを利用するのかまでは考えていない。
いつ完成するのか、そもそも完成させることができるのかもわからない。


でも、自分がステップを登っていくときに注意深く周りを観察し、記録を取っておくことはできる。
そしてそのステップを作るための設計図を描くことにトライし続けることもできるのではないかと思う。


---------
いま考えられることは
1)自然言語とプログラミング言語との違いを感覚的に身につける。
コマンドと言葉の違いという意味ではない。そんなものは見ればわかるし頭では誰でもわかっている。
このステップでの重要点は、自然言語との思考方法の違いを身につけること。

たとえば、「プログラミング言語は完結していないといけない」とか、そういったことが考えたり意識しなくても身に付いているということ。
プログラミング言語が一方通行であることから考えていけばなんらかの方法が見つかるような気がする。

 また、コンピュータは数学の世界からきていることからも数学のなんらかの勉強によって、この感覚を身につけることができると思う。
自分の経験では、コンピュータの歴史でアーキテクチャーの変遷を知り、論理演算をかじることでその機械的特徴を垣間見ることができた。

もし可能であればだが、アルゴリズム的な考え方をプログラムを勉強する前に身につけることができれば理想的。

多くの人は、コンピュータと人間が同じようなものと考えているように思う。
これは広く一般的にコンピュータを理解する上で間違った教育が用いられたからではないかと思っている。
そしてそのことがコンピュータに対する誤解と、ストレス、不適切な感情を生み、コンピュータやプログラミングができることをまるで、すごいことのように見せたり、学習するのをあきらめることに一役買っているのではないかと思う。

本当に違いがわかっていれば、コンピュータは思考する機械ではないことがわかり、操作しなくては動作しないことがわかるはずだ。
そしてそれはプログラミングができない段階でもその感覚を身につけることができるはず。


2)プログラミング言語の正確な文法を学ぶ。
これはコマンドを勉強したり、制御構文を習うということ。


今のところ思いつくのはこのぐらいだが、プログラミング言語を習得するのは、それほど難しくなく、志した人がだれでもある程度のものは作れるようになる。
そんな時代にこれからはなっていくべきだと思う。

 

エクササイズ: ロケータ位置を頂点としてポリゴンを作成する。 (1)

このエクササイズのお題は、知り合いの人に教えてもらいました。

複数のロケータを選択し、そのロケータの位置を頂点としたポリゴン面を作成する。
ロケータをアニメートしたときにポリゴンの頂点はそのロケーターについて動く(コンストレインのように)。

これを直接またはラップデフォーマーとして、より大きい面を動かすことで、皮膚表面などのストレッチする「面」をトラッキングできる。

わかりにくいですが、2D用で、3Dのオブジェクトトラッキングではありません。

たとえば、クローズアップのショットがあるとして、顔の頬に浮き出てくる血管などに使える。
ただし、顔の向きがショット内で大きくかわると使えないと思う。

まず、アニメーションテクスチャーをこのオブジェクトに貼って、レンダリングする。
それをコンポジットによって合成する。
そのときにソリッドなオブジェクトだと、あるポイントは皮膚上に張り付いて見えても、面としてみると
テクスチャーが皮膚表面をスライドすることがある。
それを防ぐために使うことができる。

映画などで使えるかどうかはわからないが、TV番組程度なら、VFX費用を抑えるためにカメラの動きも押さえてアングルも変わらないショットがよくあるので、たまに、使うことができるスクリプトだ。


--------------------
まず、おおざっぱなアルゴリズムを考えてみた。
0)ロケータを選択する。
1)ロケータの位置情報を得る。
2A)その位置がポリゴン頂点となるようにポリゴンを作成する。
2B)もしくは、同じ頂点数のポリゴンを作成してから、頂点をロケータ位置へ移動する。
3)ロケータの位置が移動したとき、ポリゴンの各頂点も更新されるようにする。


まず今回新しい手順である、ポリゴン作成だが、ヘルプでポリゴンの項目を見て探したところ、「polyCreateFacet」が使えそう。
なにより、バーテックスを特定の座標位置に作成できるので2Aにかなっている。
(後から「ポリゴン作成ツール」を使ってスクリプトエディターで確認したところ同じコマンドだった。)


次に、ポリゴン頂点をコンストレインする方法だが、
前もって確認したところ、エクスプレッションは使わない。と言われたのでexpressionコマンドは使えない。
しかしリアルタイムで行うにはエクスプレッション意外に方法がないような気がするのだが...。


しばらく考えてみて、いくつか思いついた。
●頂点一つにつき、一つのクラスタを作成し、そのクラスタをロケータへポイントコンストレインまたは、ペアレントする。 でも無駄が多いような気がする。

●connectAttrを使い、ロケータのtx,ty,tzの値をpolygon.vertex[n]のtx,ty,tzに接続する。


現時点で可能性としてよさそうなのは二番目の「connectAttr」を使う方法なので、これが本当に可能なのかどうか調べてみる。

まずバーテックスのアトリビュートに単体でtx,ty,tzもしくはそれに相当する物で接続可能アトリビュートが存在するのか?


--------------------
まずポリゴン作成ツールで三角形のサーフェイスを作成。
その一頂点を選択してスクリプトエディターから名前を得た。
polySurface1.vtx[0]

アトリビュート名を取得する為に「listAttr」を使ってみる。


コネクト可能なアトリビュートでないと意味が無いので、-c(-connectable)フラグを使用する。

得られたのは以下のアトリビュート
pnts[0]
pnts[0].pntx
pnts[0].pnty
pnts[0].pntz

おそらく左側が頂点番号。ようするにpnts[0]はvtx[0]のtranslateのことだろう。
で、右側がtranslateの座標軸を示していると思われる。


--------------------
これでなんとか、いけそうな気配なので、ロケータを作ってこのアトリビュートに接続してみる。

まずロケータを作り目的の頂点へスナップ移動する。

次に、コネクションエディターを使って、接続してみた。
最初、以下の点がわからず、少し迷ったが、結果としてはうまくいった。

ポリゴンサーフェイスを選択したときはTransformノードが選択されているのでこのままコネクションエディターに読み込んでも頂点情報は表示されない。

頂点はShapeノードの情報なので、コンポーネントモードで頂点を選択するかShapeノードを選択してからコネクションエディターに読み込む必要がある。

ポリゴン作成ツールで作成した場合できた頂点の座標はすべて「0 0 0」になっている。
ロケータを頂点へスナップした場合、ロケータの座標はたとえば「5 0 5」などの値になる。
そのためこの状態でコネクトした場合、頂点の一は現在の位置から「5 0 5」の場所になってしまう。

うまく接続するにはロケータをトランスフォームフリーズするとうまくいったが、実際に使う際にはトラッキングされてキーフレームのついたロケータが先に存在し、そこに頂点を作成することになる。
これをうまく補正する方法は二つ。
●コネクトする際に値を補正(+-)する。
●ポリゴン作成時に頂点をまず0 0 0へ作成し、その後ロケータ位置へ移動する。



続きは後ほど

 

就職活動 (7) : previs

いままで送ったデモリール+レジュメに何も反応がないので、少し気落ちしていますが、このままでは子供を食わせていくことも出来なくなるので、急遽、就職活動再開です。

今回は、プレビジュの会社(現在1社)に応募してみました。
プレビジュは前から興味があったのですが、短期で仕上げる仕事が多いので子育てになれるまではちょっと残業はしたくなかったので、敬遠していましたが、今になってまた興味がでてきました。
とりあえず、どの会社もサイトに常設の「いつでもデモリール送ってね」的な募集しかしていませんね。
それほど人数も必要ないので、これで十分人集めになるんでしょう。

プレビジュのおもしろさは
ビッグタイトルが多い。
カメラからレイアウト、役者の演技まで、映画制作のエッセンスが詰まっている。
また短期で仕上げなくてはいけないので、いろいろなアイデアを駆使する必要がありそうです。
他にも場合によってはディレクターと直接やりとりとすることもあるようです。
なにより映画を作ったって感じがしそうだなと思います。
映画の基本を学ぶにもこれほど良い仕事はないかもしれません。

プレビジュは一見おおざっぱに見えますが、よくカメラの動きに注意すると、結構、自然な動きをしているものが多いです。
カメラはかなり気を遣わないと不自然さがすぐに出てしまうので、集中力も必要ですが、うまく動かせるとプロっぽくなります。
カメラやレイアウトに興味が無い人にはおもしろくないかもしれませんが、
VFXよりも「映画」に興味がある人にはわかってもらえると思います。

また、各エフェクトやアニメーションも飽きるほど突き詰めることなく、適当なところでショットを切り上げられるっていうのも飽き性の私には向いていますw
(逆に突き詰めたくてもできないというジレンマもありますが)

難点をいえば、どの仕事もほぼ短期なので残業必至。
一日に数十ショット仕上げなくてはいけないこともある(らしい。)
年寄りにはちょっときついです。
ま、日本のCG業界でやってきた人にはなんてことないですね。


とりあえず今後の就職活動のためにも、LAのプレビジュ制作会社を集めてみました。


--------------------
Third floor
http://www.thethirdfloorinc.com
ここは話題作いっぱいですね。
スタートレック,アバター,アリス・イン・ワンダーランド、
X-menオリジン ウルヴァリンもやっているようです。
 

--------------------
POVprevis (旧 POVDE)
http://www.persistenceofvision.com/
この会社の社長、デビッド・ドゾレッツ氏はプレビジュのパイオニア。
サイトを見ればわかるとおり、最新作「スタートレック」を始め、たくさんの話題作をこなしています。
親日家で、日本のデジハリともつながりをもっているので、ご存知の方もいると思います。
サイトのPOV TVに「関ヶ原の合戦」がありますね。
はじめてみましたが、学生にしては良くできていますね。
うちの会社でこれをやろうとしても無理です。w


--------------------
Pixel Liberation Front
http://www.thefront.com/
最近、話題作が増えてきました。
アイアンマン2,トランスフォーマー2、ターミネーター・サルべーション
Autoddeskにアイアンマンの記事がありました。
この会社のマークを見ると、すごく残業させられそうで少しひいてしまいますw



--------------------
Halon Entertainment
http://www.halon.com/
G.I.ジョー、マミー3、 インディアナ・ジョーンズ4、クンフー・パンダなどをやっています。
Autodeskにインディー4の記事がありました。
Linked-Inにページがあって現在のスタッフがみれます。
(更新は任意なので本当に現時点の情報かどうかは疑問ですが)
http://www.linkedin.com/companies/halon-entertainment
一ヶ月ほど前にvfxpro.comで募集しているのを見つけましたが、職場はサンフランシスコとなっていました。
会社はサンタモニカにあるはずなので、派遣して現地作業が基本なのかもしれません。


--------------------
Unit Eleven
http://uniteleven.com/
今日検索していて初めて知りました。
トランスフォーマー2をやっているようですね。
でも作品の履歴をみるとそれほど多くないのは、会社が小さいのか?
それとも仕事をとれないのか??


--------------------
見ていて気づいたかもしれませんが、一つの映画を複数の会社がやっていることがよくあります。
プレビジュに限ったことでもないですが、VFXショットの多い作品は、短期で仕上げるためにも分配する必要があるのでしょうね。

 

祝 コメントw

まめさんより、以下のエントリにて、このブログ初のコメントをいただきました。
コメント機能が壊れているのか使えないのかと思っていましたw

メモ: listRelativesコマンド

おぼつかない内容で恐縮ですが、
まめさん、これからもよろしくお願いします。

 

2009年5月20日水曜日

自分の勉強のやり方

Melの勉強に限ったことではなく、自分は何をするにしても、

おもしろくなければやる気がしない。
やる気が無ければ記憶に残らない。


なのでテキストブックの順番に進むとか、チュートリアルをじっくり見て順番に進めるということができない。
拾い読みなら出来るが、興味がないと5分と持たない。
これは高校ぐらいから変わらないので、今さら変わらないだろう。

もしかしたら、自分はAD/HDなのかもしれないが、本当に興味がわくこと好きなことは数時間同じ椅子に座っていても時間を忘れてしまうほどなので、そのような病気ではないだろうと思っているのだが。

また困ったことに記憶力がめっぽう悪い。
ただ、生きた知識として身につけたことはすぐに覚えて忘れにくい。

たとえば一度訪れれば大体の場所は覚えている。


なので何かを継続的に勉強するには、
こういった性格をうまくつかって勉強するようにしている。


●興味があるところから、つまみ食いする。
●興味を維持したり、興味が強くなるようなものを読む。
●あまり自分のレベルからかけ離れている物は読まない。(高すぎても低すぎても駄目)
●限界まで頑張っても行き詰まったらとりあえずおいとく。
●退屈は興味を失うことにつながるので、おもしろいと感じるレベルを維持する。
●機械的に記憶する勉強は興味を失うので、生きた知識を身につけるようにする。
●記憶に専念しない。
●勉強対象に少しでも関連していれば、基本や由来となることなど出来るだけ幅広い知識を得るようにする。 (歴史、人物、トレビア、最新情報なども含む)
●納得/理解しないと先へすすまない。
●たえず、勉強対象に関連することに触れ続ける。(たとえ一日数分だとしても)


他にもあるかもしれないがとりあえずこのぐらい。
まぁ、道草を食いながら下校するような感じなので時間がかかります。

しかし、道草から学ぶことの方が、人生には役に立つと思っているので、始末がわるいですね。


 

メモ: selectコマンド

以前のエントリ「メモ: listRelativesコマンド」でやりたかったオブジェクトの検索が、「select」コマンドで出来ることがわかった。

このコマンドはずっと前に使ったことがあるが、すっかり忘れていた。
そもそもオブジェクトを選択することが目的なので気づきもしなかった。

このコマンドで便利なのは「ワイルドカード」の「*」が使えること。

これで検索のように一部さえ、一致していれば目的のオブジェクトを見つけることができる。
ただし本当のweb検索のように「-」「+」「or」やワイルドカードの「?(一文字のみ)}などは使えない。

--------------------
select "*"...Shape ノード、削除不可能なオブジェクトすべてのオブジェクトを選択。使わないけど。

select -all...ルート レベルの削除可能なすべての DAG オブジェクトと、DAG ノード以外の削除可能なすべてのディペンデンシー ノードを選択

select "nurbs*"...nurbsで始まる名前のオブジェクトがすべて選択される。

select "*Sphere*"...Sphereが名前の途中、または前後に含まれる物は全て選択される。

select "*_*" ...アンダースコアが名前に含まれる物は全て選択される。


--------------------
このコマンドで-addフラグを使い、for文と組み合わせれば

aaa_11
aaa_12
aaa_13
...

このように連番になったオブジェクトを範囲指定して、アクティブリストに追加することができる。


--------------------
またselectコマンドを使ってオブジェクトを選択後、
listRelatives -shapes
を実行すればそのShapeノードの名前を取得できる。
(注意:選択状態はかわらない)


 

このブログ上で広告をしない理由

このブログの目的は、自分のMELスクリプトの学習のためのメモであることは何度も書いているが、よくある広告収入のためにGoogle AdSense などを使用していないのは理由がある。

Google AdSenseを利用すると、より多くのアクセスが必要となる。
そうすると他人受けする内容や、文章を書く必要性にかられてしまう。
そうでない人もいるだろうが、すぐに受け狙いの文章になったり、自分のペースを見失う。
そうなるとネタにつまり継続していくことも難しくなる。


ブログを公開しているのは、同じような悩みを持つ人と情報を共有したいという目的がある。
苦労して得た情報を隠して他者との差別化を図るのではなく、オープンにすることで、これに刺激されてでてきた違う考えや、アイデアを取り込めるようにすることだ。

そのためにアクセスアップを図る必要はあるかもしれない。

より多くのフィードバックがあることで、こういった情報はより充実したものになるのだと思う。

収入はほしいが、それはこういった純粋に情報を発信し、情報を交換する場所としては雰囲気をゆがめてしまう。

おかげさまで徐々にアクセス数は上がりつつある。
エントリの内容のせいか?
純粋にMelをしている人だけではないようだがw いろいろな人にみてもらえるのもそれはそれでいいかなと思う。




 

2009年5月19日火曜日

exercise: ロケータ位置をpvとするカーブを描く

任意の数と位置に存在する複数個のロケーターを選択し、各位置をpvとするnurbsカーブを作成するスクリプト。

まず大まかなアルゴリズムを考えてみた。
0)ロケータの作成、配置、選択 (マニュアル操作)
1)選択したロケータの各名称を取得し、配列に格納
2)配列のサイズを取得
3)for文、配列のサイズより1つ小さい数まで繰り返す。
4)それぞれのロケータのtx,ty,tzを取得。
5)nurbsカーブを作成、そのときにcvの位置が上記の場所を通るようにする。


この中でわからないのはnurbsカーブをコマンドで作成する方法。
オンラインヘルプで調べると、以下のようにポイントを指定できることがわかった。


-p(-point)はポイントの位置
curve -p 0 0 0 -p 3 5 6 -p 5 6 7 -p 9 9 9;

-d(degree)を使ってcurveの次数を指定できる。デフォルトでは次数3。
curve -p 13 13 13 -p 13 15 16 -degree 1;

-a(append)を使い、カーブ名を指定することで作成したカーブにポイントを追加できる。
curve -a -p 10 10 10 curve2;

ロケータの数だけこの-pフラグを増やしていけばよいのだと思う。

やり方としては二つ考えられる。
一つ目は、curveコマンドをすべてのポイント位置と共にまずテキストで作成し、evalで実行。
二つ目は、最初のポイントを使ってcurveを作成し、以後増えたpointの数だけappendしていく。

スクリプトとしては二つ目の方がすっきりとまとまりそうなので、-appendフラグを使う方法を使うことにする。

for文のロケータ位置の取得と共に、for文の中で実行することが出来そうだが、
これをfor文の中で以下のことを行う必要がある。
●ロケータ位置の取得
●curveコマンドで最初のpointをもったカーブ作成。
●pointをAppendしていく。

カウンタである$iはゼロから始まり1ずつ増加し、ロケータ総数に達したら終了する。
curve -p x y z;
これは最初に一度だけ実行。

curve -a -p x y z;
これを(総数-1)回、繰り返す。追加するカーブの名称が必要だが、この時点では選択されているので問題ないだろう。


これで出来そうだ。
あとはこれをfor文の中で使ってやれば良いだけだ。
まずここまでで座標が取得できるところまで作ってみた。

{
vector $position;
string $name[] = `ls -sl`;
int $total = size($name);
for ($i=0; $i<$total; $i++){
$position = `xform -q -t -ws $name[$i]`;
}
print $position;
}

最初に$positionを宣言しておかないと、for文の中で宣言してもprint文の時には「宣言されていない変数」になってしまう。
これはブロックの外にでてしまうからだろう。
また最初vectorでなくfloatで宣言していたため、xformの返り値を代入するときに
// エラー: float[] 型のデータを float 型に変換できません。 //
となってしまった。
それからxformの-qフラグを付け忘れていたため、// エラー: 無効なリニア単位: -ws // となってしまった。


これで座標の取得は出来たので、curveを作れるように以下のスクリプトを作ってみたが

{
vector $position;
string $name[] = `ls -sl`;
int $total = size($name);

for ($i=0; $i<1;>
$position = `xform -q -t -ws $name[$i]`;

if ($i=0) { eval ("curve -p " + $position); }
else { eval ("curve -a -p " + $position); }

}
print $position;
}

// エラー: "-r" または "-a" フラグでカーブを指定する必要があります。 //
となるので、ためしにelseの所を削除してためしてみたら、
Mayaがフリーズするようになってしまった。
elseの中身にprint$positionをおいてみると、繰り返し$positionを表示し続けて固まっている。
無限ループにはなっていないと思うのだが。

そのうち、何度か繰り返しているとフリーズはしなくなったが、エラーは無くならない。



どうしても行き詰まったのでチャットでシニアアーティストに聞いてみた。
彼からのアドバイスは以下の通り、

1)evalはloopの外で使う。
例:以下が教えてもらった物
  {$blah = ($blah + " -p ")}
   string $curve = ("curve -d " + $blah + ";");
2)if($i==0){}にすべき。


アドバイスのとおり実行してみたつもりだが、

どうやってもダメで、エラーは無くならない。
` `バッククォーテーション とevalはfor文の中ではちゃんと機能しないのか?
if分がfor文の中にあると、ちゃんと機能しないのか?

仕方がないので、-appendフラグを使わないで、全座標をふくむコマンド全体を作ってevalで処理するしかない。
これの解決方法を考えてみた。
必要なのは
AAA
AAA+BBB
AAA+BBB+CCC
AAA+BBB+CCC+DDD・・・
と言う風に新しい値が後ろに付け加わっていくようにして-pフラグ部分を作成し、
それをあとで、文字列「curve」と結合し、evalで実行すれば良い。

{
vector $pObj;
string $point;

string $name[] = `ls -sl`;
int $total = size($name);

for($i=0; $i<$total; $i++){
$pObj = `xform -q -t -ws $name[$i]`;
$point = $point + " -p " +$pObj;
}

eval ("curve" + $point);
}



やってみると、これでちゃんとカーブが作成された。


コマンドリストの提案

昨日(というか今日の早朝というか)は、learningMaya(Mel Fundamental)を読んでいるときに見つけたコマンド二つlistRelative、listAttrについてフラグを一つ一つ検証していった。

こういったやり方はいかにも日本人ぽいといえるかもしれない。
日本人は徹底して一つのことを追求する傾向がある。
それがどれだけの頻度の重要性があるかというよりも、より詳しくより正確さを求めて追求していくのである。

多くのwebサイトでは、アート指向(プログラミングを主体とすることに対して)にもかかわらず、ソフトの使い方、テクニックに終始することが多く、その結果としてできた作品は????と感じさせる物が多い。
また作品のクォリティーを追求するにしても、(自分もそのうちの一人だが)オリジナリティーや作品に合ったクォリティーよりも、リアルさを追求する。

もちろん、日本人でなくてもその傾向がある人は存在する。
しかしながら、それはパーソナリティーであり、日本人のように一つの人種で均質に勤勉な人が多いという傾向は少ないように感じる。

これは社会の仕組み、TV番組、学校教育などの環境による物なのかもしれない。



前置きはこれぐらいにして昨日、フラグについて、詳しく一つ一つ検証したのは、
1)そのコマンドを使いこなしたい。
2)一回の学習で終わらせたい。
3)ヘルプでわからないことをすべて洗い出して、クリアにしたい。
4)フラグの動作を実際に体験すれば忘れないだろう。
といった理由からだ。

しかしながら調べている内に、感じたのは、
●時間がかかりすぎる
●おそらくすぐには使わないと思われる不要な物も多い。

ようするに勉強における無駄が多いのだ。


実際には必要なタイミングで、必要なコマンドと必要なフラグをいつでもならえればいいわけで、それが段階に応じてわかればそれにこしたことはない。

500のコマンドがあっても最初に必要な物はもっと少ない。
たとえば10のコマンドを知っていればいいかもしれない。
そのうち、いろいろな機能がひつようになり、そのコマンドの数は30になるかもしれない。
そうやって徐々に必要なコマンドが増えていく。

基本的によくつかわれるコマンドから、より細かなコントロールを行えるコマンドへと必要性が移行していくと思う。


このあたりをほどよくまとめて少しづつコマンドを覚えられるようにしているのがLearningMaya(MEL Fundamental)なのだと思うが、このチュートリアル形式は実は苦手だ。

チュートリアルで勉強すると
1)手順を読んで同じように入力する。
2)コマンドの説明を読む。
3)実行して結果を確認する。
を行うのが通常の手順だが、自分の物にするためには、
4)コマンドを理解するために、チュートリアル以外の手順を試す。
5)ヘルプなどでより多くの情報を得て、自分なりにまとめる。
6)応用してみる。

というステップを踏んで初めて理解できる。
しかしながらいつでも自分が知りたいことを習えるのではなく、あくまで著者が初心者にはこれが良いだろうと思えることを順番に小出しにしている。
学校の授業と同じなのである。

--------------------
即、実践に使いたい時にはこの方法は非現実的だ。
1)こうしたい。
2)それにあったコマンドを得る。
3)使う。
この順番で、行うのが実際に一番効率がよい。
これが実現するのは、親切な経験者が近くにいる場合で、一人でするにはなかなかそうはいかない。
自分に必要なコマンドが何かもわからないので見つけるのは困難だ。


実践の場所で必要なのは、
●コマンド毎に、説明、使用例が書いてある。
●コマンド名で簡単に検索できる。
●使用頻度別にまとめてある。
●コマンドの機能がすぐにわかる。

これに一番近いのはオンラインヘルプのMelコマンド一覧だが、
★初心者には説明がわかりづらい。(初心者にはわからない情報も目に付く位置にある)
★機能が一目ではわからない。

という欠点がある。


理想的なのはこれらをすべて解決して、
実力レベルに応じた使用頻度に並び替えできるものがあると良い。

「実力レベル」という括りにすると、主観的になりがちなので、
「他のコマンドや変数への依存度」「他のコマンドの必要数」など、
単体では機能しない場合どれぐら、他へ依存するのかがわかるとそのレベルを見分けることにつながるかもしれない。


このようなコマンドリストがあれば、
必要なときは簡単な機能説明から見つけることができ。
ボキャブラリーを増やしたいときは、使用頻度が高い物から学習していけば、より効率が上がるのではないかと思った。

これに近づくには、自分の作りたいタイプのスクリプトを眺めてみて、そこにある、コマンドを勉強することか?