ヘキサ日記 Blog

 

        

スプラトゥーン2で理想のギアを作るためにインク効率(サブ)のかけらを集めまくってます

どうも、カタヤマです

 

涼しくなり、すごしやすい気候になってきましたね

前回ブログを描いたのは夏前

 

そう、ミニ四駆の大会

「7/16 富士通 乾電池提供ミニ四駆ジャパンカップ2017 東京大会2」の抽選に申し込んだのですが…

 

IMG_5182

運良く当選しました!

 

今回はそのレポートをお伝えしようと思います

 

 

当日、チェックインを済ませて辺りをうろついていると…

IMG_5184_mosaic

 

おお… !これだよ、これこれ!この雰囲気!!懐かしい!!

 

着いた時にはレースがすでに始まっており、コースアウトや競り合いでは歓声があがっていました!

レースに向けてセッティングを詰めるレーサー達を見て「みんな速そう…」と内心ビビりながら出番を待ちます

 

コンデレやレースを見ていると、2100番台のコールを受けたので出陣!

数年ぶりのレースに胸が高鳴ります…!

 

列に並びレースを見ていましたが、速いマシンばかり(すげえ…)

東京大会1のレースを経験したレーサー達もいるらしく、完走率は上がっているようでした

 

IMG_5191

無事車検をパスして1レーンのシールを貼ってもらいました

1いい数字だ…勝利の予感がするぜ…!!

 

マシンのスイッチを入れ、セット――

――刹那、シグナルがに変わり一斉にスタート!!

 

…あれっ!? みんな速っ!!!!

中でも先頭3台が抜きん出て速く、ストレートで一気に離されました…

絶望しかけましたがまだ序盤。「レースでは何が起こるかわからん… これからだ…」

――と思っていた矢先、先頭集団が次々とコースアウト!

これは僥倖か…!?

そして残った僕ともう1台のマシンで最後まで競った結果―――

 

 

 

敗北しました(チーン)

コーナーからの立ち上がりを重ねて追い上げを見せたものの、マシン1台分足らず結果は2位

先頭集団がコースアウトしなかったらと考えたら、完全にビリですね…

 

くやしい…

くやしい…

くやしい…

 

だがこれでいい

 

くやしいですが、負けてこそ見えるものがあります

序盤ストレートでの離され具合などを見た感じ、

  • タイヤの径が大径でなかった(ローハイトを使用してました)ためストレートで伸びなかった
  • マシンが重かったため加速しにくかった
  • モーターの慣らし不足

が主な遅さの原因だと考えられました

また、テスト走行の不足も遅さに気付けなかった大きな要因です(そのほかにも考えうる要因は多々ありました…)

 

電車の中で色々反省しながらTPF(タミヤプラモデルファクトリー)に立ち寄って必要なパーツを買って帰り、すぐさま東京大会3に申し込んだ結果…

 

 

 

落選しました(チーン)

そう簡単にリベンジはさせてもらえませんでしたが、

次に出場できたら東京大会2で見えた課題をこなして1次予選に進みたいと思います!!

IMG_5192

ありがとう。東京大会2。

次はぶっちぎってやるぞ!!

では!!!!


        

三度の飯より鯵のたたき東京デザイナーのエドモンドです

朝夕は大分涼しくなり、秋を感じるようになりましたね。皆さんいかがお過ごしでしょうか?

自分はというと、先日うっかり手を滑らせてお米2合分をキッチンのフローリングに盛大に撒き散らしてしまい今年一番の絶望を感じました

現実を受け止めきれずにそのままベッドへ向かい仮眠を取ったのですが目が覚めてもお米はそのままだったので仕方なく片付けました…

 

さてさて、今回は前々回のブログの羊毛フェルトの第2弾です

何を作ろうか非常に迷ったのですが、今回はかわいいかわいいうさぎちゃんを作ってみようかと思います

第2弾ということもあり、前回よりクオリティを上げたいので

まじめに作ろうと思いますお付き合いください

 

 

方向性を見失なわぬよう、完成イメージを描きました。

白くてふわふわのうさちゃんは羊毛フェルトにもってこいですね

usagi

 

 

 

細かい作製手順は前のブログで書いたので省略して、ざっと作業工程をご覧ください

 

IMG_0646

まずはざくざくとニードルで羊毛を固めていきます。

 「お前はニードルの指し方が甘い」と友人より指摘があったので多めに刺していきます

 

IMG_0652

 小籠包が出来ました。もう小籠包を作ることに関しては右に出るものは居ないのでは?

と思うほど誰が見ても小籠包です。一級小籠包師と呼んでください。

 

IMG_0658 (1)

耳を取り付けます。新しい羊毛をちぎって形をある程度形成し、顔に突き刺していきます。

 

IMG_0663

次に黒いフェルトで鼻をつけます。

 

IMG_0666 (1) IMG_0667 (1)

緑と黒のフェルトで目と口を作ります。

大丈夫です。私を信じてくださいね。

 

IMG_0669 (1)

んんんんん!!!!???

 

4579875

リボンをつけたら完成です!!!!!!!!!!

 

 

IMG_0674 (1)

並べてみると一目瞭然なのですが、前作ねこちゃんに比べ今作うさちゃんは殺意の波動のようなものが格段に抑えられ非常に可愛くなったと言えるのではないでしょうか?

口の部分がほわっと優しい印象になったのと目が丸くなったのが可愛さUPの要因ですね

 

猫もウサギも平面的な作りになっているので次回は立体的な物や、色数の少し多い動物にも挑戦していきたいと思います

芸術の秋なので皆さんも是非手芸などしてみてはいかがでしょうか!ではでは


        

どうもドラクエ11未だクリアして無い勢プランナーのタッキーです。

ドラクエロス」って辛いんですか????

 

 

もう10月ですね。
そろそろヘキサブログに登場してから1年経とうとしているというところで、
にらみ折り道第2段でも。

ウンチク、机上の空論ばっかり並び立てても仕方ないので、
とりあえず早速にらみ折って見たいと思います。

心の声

「とは言えいきなり難しそうなものは心が折れそう、、、
何か良いものはないかうーん。。。
あ!この展開図簡単そう!」

 

ーと言うことで今回は「小鳥」を折ります!!

20170926_bird01 

(「小鳥」 画像出典:「折り紙研究ノート(三谷純)」)

 

完成図と展開図の線を参考に、折り目をつけつつ折っていきます。

20170926_bird02 

20170926_bird03

20170926_bird04

あれ?なんか違う

 

正しくはこうでした。

20170926_bird05

20170926_bird06

20170926_bird07

20170926_bird08

完成!!

 

 

 

今回の結果から、折り目をつけながら折るだけでは、完成させたい作品はできず、
「折り目同士をどう組み合わせて折るか」を考える必要がありました。
また「折り目同士の組み合わせ」の解は1つとは限らず、
何回か試行錯誤が必要だったことがわかりました。
まだまだにらみ折り道は続く。。。

「小鳥」は単純な折り紙としてはそこそこ簡単な難易度かもしれませんが、

にらみ折りでは悩まされました。
皆さんも是非にらみ折ってみてください。

では~


2017年9月26日

TA と Maya Node Editor

        

 

 こんにちは、Ritaro です。

こちらに記事を書くのはこれで4回目となります。

今回も、どうぞよろしくお願い致します。

 

 TAにとって開発上の問題点を解くのに 技術的な引き出しを色々な持っておくことが必要、

と以前の記事に書いた部分を・・また少し紹介したいと思います。

幾つかのゲームを開発していると、 作品を開発する上で必要なツール回りやミドルウェアで対応しておく べきデータ類、確立しておくべきワークフローなど幾つか予想できる パターンが見えて来たりします。

 

今回はキャラクターアニメーションを作成する場合にそれを制御したり、便利/簡単にするキャラクターリグにも応用が利くであろう Maya の Node Editor まわりの話をします。

何回かに分けてご紹介するつもりです。

 

Node Editorは、Maya上にある各オブジェクトに付随する設定をノード型のアイコンで表し、 それら同士を接続して色々な制御や計算をさせることで、様々な仕組みを作り込んでいけます。

ノードベースのインタフェースのソフトウェアとしては Houdini や NUKE があり、 また、ビジュアルプログラミングという言い方では  Softimage の ICE、MotionBuilder のRelations Constraints  などがあります。

 

20170926_NodeEditor_00

 

では、話をMayaに戻して、
試しに、1つ  locator(ロケータ)  を作成して、
ウィンドウ(Windows) > ノード エディタ(Node Editor) と開いて
表示されるエディタで2つのアイコンを展開すると、色々な機能が接続ポイントと共に表示されるので

 『あー、これらをつなげて・・・』と直感的に理解できると思います。

 

20170926_NodeEditor_01
ちなみに、ノードの展開は、右マウスクリック > すべてのアトリビュートを表示
を選択すると、えらい量のある表示にすることが出来ます。接続ポイントが行方不明の時利用できます。

 

 

ノード エディタ(Node Editor) ドキュメントhttps://knowledge.autodesk.com/ja/support/maya/getting-started/caas/CloudHelp/cloudhelp/2017/JPN/Maya/files/GUID-23277302-6665-465F-8579-9BC734228F69-htm.html

 

ちょっと具体的な、面白い対処法、でもあったら 『おお、使えるかも』
・・って思うようなものをまたご紹介していきましょう。

 

 

1)「Mayaをグローバル位置で制御したい」

 

 Mayaのトランスフォーム値(ここでは移動値)はローカルトランスフォーム値(相対値)です。
実は、SOFTIMAGE3D という90年代に使われたソフトウェアはグローバルトランスフォーム(絶対値)だったのです。
今のMaya的な言い方をすれば ワールド座標 ということです。
つまり、何が言いたいかというと、Mayaは何かの子供にした瞬間、見た目の位置は変わらない表示をしていますが
それはトランスフォーム値(相対値)を変化させている、ということです。

 

20170926_NodeEditor_02

 

そんなことわかっているよ、と思われるかも知れないのですが、

少しRigに興味を持って Node Editor を触っていると、これに遭遇します。

 

例えば、円のカーブ上に LocatorPointOnCurve で位置させて 円カーブを動かして Locator が追従するような  回転制御のアイコン として使いたい、なんて考えて、

『おお、出来た出来た』となります。

 

20170926_NodeEditor_03

 

で、管理しやすいように階層構造に入れたとたん・・・、破綻します。

 

20170926_NodeEditor_04

 

なぜなら、トランスフォーム値を変化させていないからです。
更に、親のオブジェクトを移動させると、相対的にずれているだけではなく
なーーんか、妙な動きが追加して動くことに気が付くでしょう。
これを直せるようになると、どんな階層下に置いても 大丈夫!! になります。

 

少しノードが増えます。  multMatrix と pointMatrixMult を2つです。

 

Node Editor上で Tabキーボタンを押すと [___] 入力欄が表示されるので、2つのノード名を入力して Enterキーを押すとノードが増加します。

検索機能付きなので、mu~ って書いただけで multMatrix が候補に上がってきます。

 

1)カーブ上の位置を取得する為に nurbsCircleShape1 の [行列(Matrix)]

     multMatrix[行列の入力[0] ] に接続します。

2)親になる Circle_Center [逆行列(Inverse Matrix)]  を

     multMatrix[行列の入力[1] ]  に接続します。

3)各 pointOnCurveInfo の [位置] を pointMatrixMult の  [入力ポイント] に接続します。

4)multMatrix から出力される  [行列の合計]  を 各pointMatrixMult の  [入力行列]  に接続します。

5)各pointMatrixMult からの [出力] を 各Locator  [移動]  に接続します。 

 

20170926_NodeEditor_06

 

これで、親となる Circle_Center という Locator を動かしてもカーブ上の2つの Locator は正しく追従してきます。
    めでたしめでたし。


 しかし、Circle_Center より上に 更にが追加作成されたらどうなるでしょう。
~~・・、また うまくいきません。
そしたら、追加された親の 逆行列(Inverse Matrix) を 更につないであげればまた直るでしょう。

 

20170926_NodeEditor_07

 

でも、これじゃ、変化に耐えられないので~、どうするかを考えます。

 

少しノードの配列を変えます。  multMatrix をもう1つ追加します。

 

1)各 Locator がくっ付くカーブ  nurbsCircleShape1 の [行列(Matrix)]  を

     各 multMatrix の [行列の入力[0] ] に接続します。

2)各 Locator  の  [親逆行列(parent Inverse Matrix)]  を

    各 multMatrix [行列の入力[1] ]  に接続します。

 

20170926_NodeEditor_08

 

すると、たとえ 各  Locator  の上に何か親が来ようが、最上階層が増えても OK です。

 今度こそ Happy です。

 

   で、 pointOnCurveInfo  ですが、パラメータ( [レ] パーセンテージ) を変化させると確かに円上を移動しますが 回転はしてくれません。

 

20170926_NodeEditor_09

 

そして、たとえ pointOnCurveInfo のすべてのアトリビュートを表示させても 回転 などは無く、あるのは 位置、法線、接線 です。

実はここから回転をつくれます。


これを実現するには vectorProduct の 外積 と fourByFourMatrix を使います。
そうです、少し数学で出て来るのですが、ビジュアルプログラミングの良いところは試行錯誤してみて結果を視覚化して確認できるところです。

まずはやってみよう、からでよいかと思います。

 

少しノードのが増えます。


 各 Locator に対して vectorProduct が2つ、fourByFourMatrix と

    decomposeMatrix を1つずつ追加します。
   vectorProduct は分かりやすいように

 1つは vectorProduct_Z 、もう1つは vectorProduct_Y と改名しておきます。

 

1)pointOnCurveInfo  から出力されるデータを fourByFourMatrix  に接続していきます。  

  vectorProduct_Z の 操作を [外積] にします。  

    vectorProduct_Y の 操作も [外積] にします。

 

2)pointOnCurveInfo の [接線] を vectorProduct_Z の [入力2] に接続します。

     vectorProduct_Z の [出力X] を  fourByFourMatrix  の [入力20] 

                 の [出力Y] を  fourByFourMatrix  の [入力21] に

                 の [出力Z]  fourByFourMatrix  の [入力22] に接続します。

 

3)pointOnCurveInfo の [接線] を vectorProduct_Y の [入力1] に接続します。

    vectorProduct_Z の [出力] を vectorProduct_Y の [入力2] に接続します。

        vectorProduct_Y  の [出力X] を  fourByFourMatrix  の [入力10] に

                  の [出力Y] を  fourByFourMatrix   の [入力11] に

                      の [出力Z] を  fourByFourMatrix [入力12] に接続します。

 

4)pointOnCurveInfo の [接線X] を  fourByFourMatrix [入力00] に

                                      の [接線Y] を  fourByFourMatrix [入力01] に  

                                      の [接線Z] を  fourByFourMatrix の [入力02] 接続します。

 

5)fourByFourMatrix の [出力] を multMatrix  の [行列の入力[0]] に接続します。

 

6)multMatrix [行列の合計] を decomposeMatrix  の [入力行列] に接続します。

 

7)先に最後の  Locator の [親逆行列[0]]   を

     multMatrix の [行列の入力[1]] に接続します。 

8)decomposeMatrix  の [出力移動]  を Locator  の [移動]  に接続します。  

    decomposeMatrix  の [出力回転]  を Locator  の [回転]  に接続します。

 

20170926_NodeEditor_10

 

これで pointOnCurveInfo の パラメータ を変化させるとカーブに沿って Locator が回転します。

ここでの例では LocatorのX軸(良くジョイントはX軸方向にする)がカーブに沿って前を向いています。

 

20170926_NodeEditor_11

 

この具体例ではカーブが円形をしていますが、
通常のカーブにすると、カーブに沿ってX軸方向に移動するようになります。

 

20170926_NodeEditor_12

 

fourByFourMatrix が使えるようになると、色々と NodeEditor を使える幅が広がります。

という感じで、やはり次回も NodeEditor ネタ にしましょうかね。

乞うご期待、、

 

ではでは

 

 

 

 

 

 

 


        

どーも。

プロマネのKAZです。

 

先日、AppleがiPhone 8とiPhone Xを発表しましたね。

 

8の次は9のはずですが、それを飛び越えてX(10)…

 

2007年に初代iPhoneが発売されてから今年で10年を迎えたので、

それを記念してXというわけです。

 

iPhoneもヘキサドライブと同じく10周年です!

 

「十年一昔」という言葉がありますが、10年前、皆さんは何歳でしたか?

どこで何をしてましたか?

 

今から10年前はコンソール(家庭用)ゲーム機が全盛の時代で、その時、私は既に社会人●年目で、

某ゲーム会社でPS3/Xbox360向けの音楽ゲームを作ってました。

モバイル事業にも関わってましたが、スマートフォンが普及する前なので、

フィーチャーフォン/ガラケー向けのゲーム開発です。

インターフェースが今とは全く違います。。

 

因みに、10年前、携帯型ゲーム機といえば、Nintendo DSとPSP(PlayStation Portable)でした。

PS Vitaはそれから4年くらい後に登場します。

 

そんな中、当時既に携帯音楽プレイヤーとして人気だったiPodと携帯電話機、

そしてインターネット通信機器、この3つのデバイスが1つになった製品が突然登場したのです。

しかも指でタッチパネルを操作するといった、それまでになかった斬新で革命的なインターフェースで。

 

iPhoneの登場は当時とても衝撃的でした。

 

故スティーブ・ジョブズは私の尊敬する人の1人で、初めてヘキサ日記を書いた時にその事に触れましたが、

今回もまたジョブズのプレゼンを一つ紹介したいと思います。

 

ジョブズは初代iPhoneをプレゼンした際、コンピューターとは言わずに

「電話を再発明する」と言ってます。“電話をかけれるiPod”ということで人々に訴求したのです。

その結果、手のひらサイズのコンピューターを世界中に普及させることに成功しました。

そのときのプレゼン映像がこちら↓です。

45分くらいあってちょっと長いですが、流石ジョブズのプレゼンといった感じで面白いです。

 

 

ということで、今、世界中の誰もが当たり前のように生活必需品として使っているスマートフォンは、

10年前はまだ全然普及してなく、iPhoneが登場し、瞬く間にスマホ市場を拡大させました。

 

 

今から10年後、世界はどのように変わっているでしょうか?

 

はたしてスマートフォンはその時もまだ現役なのでしょうか….

 

それともスマホに変わる全く新しい何かが登場してるのでしょうか。

 

『iPhone Xは「最後のiPhone」であり、Appleからの挑戦状だ』

と言ってる人もいますが、↑この記事はなかなか面白く、私的に共感できます。

 

もしかしたら10年後は、攻殻機動隊のように我々の脳は電脳化されて、

脳とネットが直接繋がっている時代になってるかもしれませんね。

 

実際、宇宙物理学者であり神戸大学名誉教授の松田卓也氏は

“「義体化」「電脳化」こそが、人類がこれから進むべき道ではないか”

と主張しています。

 

攻殻機動隊の舞台は2029年(今から12年後)ですが、

それより数年早まって、本当に実現してる可能性はあるかも?しれません。。

 

10年後、みなさんは何歳になってますか?

その時何をしていたいですか?

 

私は南国のリゾート地で、iPhone XX(20)でスマホゲームを遊んで暮らしてる気がします。

 

私のゴーストがそう囁いてます!笑

 

 

最後に、私のブログで毎回恒例の洋楽のご紹介です。

 

「時代は変わる」ということで、今回は、Bob Dylanの名曲

The Times They Are A-Changin’をご紹介。

 

この曲は沢山の有名アーティストがカバーしており、

今回はDylanのオリジナル曲ではなく、Blackmore’s Night Verです。

(元Deep PurpleのギタリストであるRitchie Blackmore率いるバンド)

 

オリジナルは完全フォークソングですが、このVerは

ヨーロッパの伝統音楽(ケルト民謡)調で、これからの秋にピッタリな感じです。

 

<Blackmore’s Night – The Times They Are a Changin>

 

ではまた~


2017年9月22日

大きい画面は正義

        

普段は2~3ヶ月に1度くらいのペースで連絡が来る母親から”ドラクエXIをクリアした”報告と、

半年に1度くらいのペースで連絡が来る父親から”Switchの10月出荷分を予約できた”報告が、

最近同じくらいのタイミングで別々にきて、今日も世界は平和だなと確信したおのってぃです。

 

さくっと今日の本題です。

ついに発売しますね。待ちに待ったGvido。

昨年末からずっと発売を待っていたGvido。

知らない人はいないと思いますが、念のためにどういったものかざっくり復習しておきます。

・電子楽譜専用端末

・見開き2ページで、それぞれE-Ink電子ペーパー13.3インチパネル ・スタイラスで楽譜への書き込み可能

・画面タッチでページめくり、別売りのフットスイッチでもページめくり可能

・microSDで容量アップ可能

 

 

今は自炊した楽譜たちをiPadに入れて利用しているのですが、

・1ページ分の表示だとページめくりの頻度が多すぎて嫌になる

・iPadを横置きにして見開き表示にすると小さすぎて嫌になる

・ずっと画面をつけていると電池の消費量が異常で嫌になる(利用しているiPadは6年ほど前のものです)

(個人の感想です)

という状態で非常にストレスフルです。

重い楽譜を複数持ち運びしなくても良いという点で非常にメリットも大きいんですけどね。

 

それをすべて解消してくれる予定の素敵なGvido。

 

ところがです。 かなり値が張るので、すぐに入手するわけにはいかないです。

どこかの大富豪達が買い支えた結果、僕が買いやすい値段で販売されるようになることを願っています。心から。

 

それではもっと13インチパネルが流行ればいいのにと思いつつ今日はこの辺で終わりにしたいと思います。


        

こんにちはヨセミテです。

スープカレーは最近食べれていません。食べたい。

 

先日行われたCEDEC2017ではラウンドテーブルの司会という非常に貴重な経験をさせていただきました。改めてこの場で、来て下さった方々にお礼を言いたいと思います。ありがとうございました。


 

今回はMaya Python API2.0 でコマンドプラグインを作成していきたいと思います。

コマンドプラグインを作成すると新しいMELコマンド(Pythonだとcmdsライブラリ)の新しい命令を定義できます。

 

 ■ [ctrl + z]が効く高速なスクリプトが組めること

 ■ MELで自分からスクリプトを組むようなデザイナーさんが居る環境で使えるコマンドを増やせること

 ■ skinPercentの様な、そのまま使うと少々重過ぎるコマンドを場合に合わせたカスタマイズして高速なものを用意できること

 

などが主な利点だと思います。

 

「元に戻す機能」、「引数」を利用できるものを作ってみたかったので以下の二つのサンプルをベースに作成しました。

 ■ 公式ドキュメントの元に戻せるサンプル

 ■ 公式ドキュメントの引数を使うときのサンプル

 

作成してみたものが以下になります。頂点、もしくはメッシュ全体を選択して法線方向に引数の分だけ移動する、という処理です。


 

コメントが探り探り感あふれるのはご容赦下さい。探り探りです。 

# -*- coding: utf-8 -*-
import sys

import maya.api.OpenMaya as om
import maya.api.OpenMayaUI as omui

kPluginCmdName = "blogCommand" # MELコマンド名

kShortFlagName = "-mv"         # 引数のショートネーム
kLongFlagName = "-moveValue"   # 引数のロングネーム

def maya_useNewAPI():
    # この関数が記述されているスクリプトはプラグインが生成されます、とMayaに伝えるための関数らしい
    pass
    
##########################################################
# Plug-in :メインの記述部分
##########################################################
class BlogCommandClass( om.MPxCommand ):
    
    def __init__(self):
        ''' Constructor. '''
        om.MPxCommand.__init__(self)
    
    def doIt(self, args):
        # doIt内部は一度だけ呼ばれるコマンドらしい
        # 公式のサンプルでredoItに実行処理書いてこっちでもredoitよびだしてたので習う

        # 引数を解析しているところ
        moveValue = self.parseArguments( args )
        
        # 対象のメッシュの諸々を取得
        moveTargetMesh_selList         = om.MGlobal.getActiveSelectionList()
        moveTargetMesh_dag             = moveTargetMesh_selList.getDagPath(0)
        self.moveTargetMesh_MFnMeshIns = om.MFnMesh(moveTargetMesh_dag)            # 選択対象のMFnMeshインスタンス

        moveTargetMesh_componentObject = moveTargetMesh_selList.getComponent(0)[1] # 選択頂点のコンポーネント
        if moveTargetMesh_componentObject.apiType() == 548:
            # 選択対象が頂点なら頂点のindexList取得
            moveTargetMesh_ComponentIns     = om.MFnSingleIndexedComponent(moveTargetMesh_componentObject)
            moveTargetMesh_selectedIndecies = moveTargetMesh_ComponentIns.getElements()                    # 選択頂点のindex
        else:
            # 選択対象が頂点なら頂点じゃないならindexListは頂点数分
            moveTargetMesh_selectedIndecies = xrange(self.moveTargetMesh_MFnMeshIns.numVertices)
            
        # undo処理のために元々の頂点座標を保存
        moveTargetPointArray_Origin     = self.moveTargetMesh_MFnMeshIns.getPoints(space = om.MSpace.kWorld)
        self.movePointArray_OriginClone = moveTargetPointArray_Origin[:]

        # 実行処理を繰り返し処理部分に書いているため、実行処理の呼びだし
        self.redoIt(moveTargetMesh_selList, moveTargetMesh_dag, moveValue,moveTargetMesh_selectedIndecies)
        
    def parseArguments(self, args):
        # 引数を読み込むための部分
        # 必須ではないが、このように分けると判り易いですよ、との事
        
        # 定義した引数が用いられているかどうかの確認
        # 定義した引数が異なるとココでエラーが発生する模様
        argData = om.MArgParser(self.syntax(), args)
        
        if argData.isFlagSet( kShortFlagName ):
            # flagValueにintにして受け渡ししてるそうで
            flagValue = argData.flagArgumentFloat( kShortFlagName, 0)
        return flagValue
            
    def redoIt(self, moveTargetMesh_selList, moveTargetMesh_dag, moveValue, moveTargetMesh_selectedIndecies):
        # 繰り返しをした際に呼び出される処理?
        # 公式のサンプルではココに実効的な処理を記述していたのでそれに習い、
        # ココに実効的な処理を書き、doit内部からredoitを呼び出す形式にする
        vertxNum = self.moveTargetMesh_MFnMeshIns.numVertices
        points   = self.moveTargetMesh_MFnMeshIns.getPoints(space = om.MSpace.kWorld)
        normals  = self.moveTargetMesh_MFnMeshIns.getVertexNormals(False, om.MSpace.kWorld)
        
        movedPosArray = om.MPointArray()    # 移動後の座標を格納する配列
        movedPosArray.setLength(vertxNum)   # 初期化

        for currentIndex in range(vertxNum):
            if currentIndex in moveTargetMesh_selectedIndecies:
                currentPos    = points[currentIndex]                   # 対象頂点の位置
                currentNormal = om.MVector(normals[currentIndex])      # 対象頂点の法線方向
                movedPos      = currentPos + currentNormal * moveValue # 移動後の座標
                movedPosArray[currentIndex] = movedPos
            else:
                movedPosArray[currentIndex] = points[currentIndex]     # 選択対象以外のindexはそのままの座標を格納

        self.moveTargetMesh_MFnMeshIns.setPoints(movedPosArray)        # 移動後座標を適用
    
    def undoIt(self):
        # undo時に呼び出すための逆処理を書く
        self.moveTargetMesh_MFnMeshIns.setPoints(self.movePointArray_OriginClone, space = om.MSpace.kWorld) # 確保しておいた元々の座標を適用

    def isUndoable(self):
        # 命令が実行可能かどうかを判定する部分
        # これが無いとundoできない模様
        return True

##########################################################
# Plug-in initialization.
##########################################################
def cmdCreator():
    return BlogCommandClass() 

def syntaxCreator():
    # syntaxCreaterは作成するコマンドに引数を持たせる場合は記述する必要がある。
    syntax = om.MSyntax()
    # ここで引数として持たせたいデータ型を指定する必要がある。
    syntax.addFlag( kShortFlagName, kLongFlagName, om.MSyntax.kDouble )
    
    return syntax
    
def initializePlugin( mobject ):
    mplugin = om.MFnPlugin( mobject )
    try:
        # 引数を持たせる場合と持たせない場合でココもちょっと変わる
        mplugin.registerCommand( kPluginCmdName, cmdCreator, syntaxCreator )
    except:
        sys.stderr.write( 'Failed to register command: ' + kPluginCmdName )

def uninitializePlugin( mobject ):
    mplugin = om.MFnPlugin( mobject )
    try:
        mplugin.deregisterCommand( kPluginCmdName )
    except:
        sys.stderr.write( 'Failed to unregister command: ' + kPluginCmdName ) 

 これをプラグインパスが通っている場所に置くと保存したファイル名でプラグインの読み込みに追加されています。

 

プラグインを読み込んだら、スクリプト内部で定義したMELコマンド、もしくはpythonのcmdsライブラリのコマンドで実行できます。

cmds.blogCommand(moveValue = 1) # Python 

で実行できます。

試してみたところ速度がちょっと微妙…。10万頂点くらいだと2~3秒かかってしまいました。選択頂点で判定する処理をいれた辺りでとても遅くなったのでその辺にボトルネックがありそう…。入れる前だと100万頂点でも1秒掛からなかったのでプラグイン自体はとても早いです。

 

実行すると以下のように動きました。[ctrl + z]も効いて引数で移動量もちゃんと変わっているようです。

  img4

コマンドプラグインはcmdsでスクリプトを組むことに比べればやはり時間的なコストはかかってしまいます。が、頂点数が増えてくるとその強みが実感できます。Maya Python API2.0 ならC++で作成するよりはるかにテストやイテレーションをまわすのが楽なので是非試してみてください。

 

では。


2017年9月20日

読書の秋

        

すっかり涼しくなりましたね。皆様いかがお過ごしでしょうか。
東京デザイナーのとりっぴーです

 

さて、季節は読書の秋ということで、

本日はUI/UXに関する書籍のご紹介をいたします。

 

UIのデザインは一見目立ちにくいかもしれませんが、

ゲームとプレイヤーを繋ぐ大切な要素を担っており、プレイフィールにも影響します。

UIが分かりにくいと、そもそもゲームをどう遊べばいいのか伝わらないことになってしまいます

そして悩ましいことに、そのゲームや媒体によって「何が最適なUIなのか」はそれぞれ違い、
一概に正解があるというものでもありません。
実装したものをテストプレイして「触った感覚はどうか」など
都度チェックしながら開発していくのですが、
本当に奥が深い分野で、私も勉強しながら試行錯誤の日々でございます

 

また普段、色々なゲームを触ってゲームのUIを勉強させていただくことがありますが、
基本的にリリースされている完成した製品を触るということが多いです。
どのような経緯でこのようなデザインに至ったのか、

ある程度は想像することができるかもしれません。

しかし、開発中の試行錯誤はCEDECや勉強会など以外では、
なかなか知る機会が少ないのではと思います。

 

そこで、「ゲームUIの書籍って無いのかな?」と探していて

こちらの一冊にたどり着きましたのでご紹介します

 

20170920_book.jpg

「売れるゲームのUI/UX 制作現場の舞台裏」

 

この本では、UI/UXとは何か?といった基本的な知識が簡潔にまとめられており、
誰にとっても読みやすい内容だと感じました
また、スマートフォン、コンソール、アーケード、VRといった様々なプラットフォームで

それぞれのゲームタイトルの開発事例が載っていることが特徴的です。
実際の開発中のゲーム画面のラフデザインから完成するまでの画面改修の変移、

そのゲームやプラットフォームならではの工夫も解説・収録されています

 

UIを作られている方も、そうでない方も、
宜しければチェックしてみてください

 

ちなみに、ヘキサドライブでは書籍を申請をすると
会社費用で購入してもらえる制度があります
本棚には勉強のために色々な分野の参考書が並んでいて
借りることができ、とても重宝しています
(こちらの書籍も会社で購入したものです。)

 

それでは、本日はこちらで失礼します


2017年9月19日

背景を見よう

        

こんにちは。

3連休いかがお過ごしでしたでしょうか、ブリテンです。

 

私はと言いますと、いかんせん台風でしたので、

『ゲーム・オブ・スローンズ』をシーズン7まで見て、

またシーズン1から走りなおす作業をしていました。

20170919_got

 

人気作なのでご存知の方もいらっしゃると思いますが、

『ゲーム・オブ・スローンズ』(原題:Game of Thrones)は

アメリカのケーブルテレビ局HBOが制作する、

イングランド・薔薇戦争をモデルとした、ファンタジードラマです。

 

このドラマ、ウェスタロスと言う大地で

個性豊かな登場人物同士が織り成す群像劇が

とても面白い! 先が気になる!

 

のですが、

それと同じくらい、背景が素晴らしいです。

 

ウェスタロス北部の「ウィンターフェル」は北アイルランド

ウェスタロス中南部の王都「キングスランディング」はクロアチア

ウェスタロス最南端「ドーン」はスペイン

で撮られており、それぞれ街の特色を出しています。

特にドーンは中世ヨーロッパ的なことを言えば、レコンキスタ完了前なので、

スペイン+イスラムの雰囲気を出しています。

 

これらはすべて架空の場所です。

しかし、実際にその場所が世界に存在したら・・・

いやむしろウェスタロスとその周辺諸国が実際に存在したら・・・

という想定で作られているため、リアリティがあります。

 

 

その分制作費がハンパないことになっているそうですが、

登場人物やドラマを立たせるためにも、

背景のリアリティも追求しているのですね。

 

みなさんも、もしご覧になられる際は

「背景」にも注目してみてくださいね。

 

 

 

 

 


        

ラーメン屋でスタンプカード出すのを忘れがちな某(なにがし)です

 

過去にシュンスケさんが32bitカラー画像を16bitカラーに減色する方法を紹介してくれました。

 

32とか16とかその5
↑今回関係するのはこのへん

 

「組織的ディザ法」「誤差分散法」を試して、誤差分散法が結構イイカンジという話でした。

 

私のチームで、シュンスケさんの実装を借用してみたところ、
それなりにイイカンジではありますが、元画像からの劣化がやっぱり気にはなりました。

 

元画像
20170915_original

 

減色後
20170915_rgba4444

 

※画像は「魔法パスワード1111」で使われている背景画像です。
 減色による画質劣化がわかりやすいものを選びました。

 

画像全体にノイズのようなドットが目立ちます

 

そもそもこの元画像、見ての通り不透明な背景画像です。

 

つまり、アルファチャンネルを使っていないので、
RGBA各チャンネルを4bitずつ表現しているRGBA4444形式では、
アルファチャンネルの4bitがすべて無駄になっているということになります。

 

この無駄な4bitをうまく利用してやれば、さらにイイカンジにできそうです

 

16bitカラーと言っても、RGBA4444だけでなく、RGB565という形式もあります。
名前の通り、RGBがそれぞれ565bitで構成されて16bitとなります。

 

アルファチャンネルがないので、不透明画像に適しています。
緑(G)が1bitだけ他のチャンネルより大きいのが面白いですね。
1bit増えると表現可能な色数が倍になりますので、大きな差になります。

 

それでは、シュンスケさんの実装をRGBA4444からRGB565に対応させてみます

 

特定の桁数から、任意の桁数に収まるよう端数を切る処理が必要なので、
例えば、10桁から6桁に落とすなら、上位6桁を持ってきて、下位4桁を捨てる考えでいいでしょう。

 

32bitフルカラーからの減色の場合、1チャンネルあたり8bit(1byte)なので、
Nビットに落とすなら、上位Nビットを取ってくればOKです。

 

// 1ピクセルあたりのバイト数
private const int PIXEL_BYTES = 4;

// 1バイトあたりのビット数
private const int BYTE_BITS = 8;

// 減色モード
private enum Mode
{
	RGBA4444,
	RGB565,
}

// チャネル
private enum Channel
{
	R,
	G,
	B,
	A,
}

private static uint quantizeChannel(uint value, Mode mode, Channel channel)
{
	var bitCount = BYTE_BITS;

	switch(mode) {
	case Mode.RGBA4444:
		bitCount = 4;
		break;
	case Mode.RGB565:
		if(channel == Channel.A) {
			bitCount = 0;
		}
		else if(channel == Channel.G) {
			bitCount = 6;
		}
		else {
			bitCount = 5;
		}
		break;
	default:
		break;
	}

	if(bitCount >= BYTE_BITS) return value;
	if(bitCount <= 0) return 0xFF;

	// 上位bitCountビット分を返す
	var shiftBits = BYTE_BITS - bitCount;
	return value & (~0u << shiftBits);
}

private static uint channelFilter(uint org, int x, int y, ref double[,] err, Mode mode, Channel channel)
{
	// 蓄積された誤差を加えて近似
	var tmp = (err[x, y] + org);
	if(tmp < 0) {
		tmp = 0;
	}
	if(tmp > 255) {
		tmp = 255;
	}
	var c = quantizeChannel((uint)Math.Round(tmp), mode, channel);

	// 誤差を分散して蓄積
	double e = tmp - c;
	for(int i = 0; i < DISPERSION_TBL.Length; ++i) {
		var p = DISPERSION_TBL[i];
		var xIdx = x + p.offsetX;
		var yIdx = y + p.offsetY;
		var xLen = err.GetLength(0);
		var yLen = err.GetLength(1);
		if(xIdx < 0 || xIdx >= xLen ||
		yIdx < 0 || yIdx >= yLen) continue;

		err[xIdx, yIdx] += (p.rate * e);
	}

	return c;
}

private static void filter(ref byte[] bmp, int w, int h, Mode mode)
{
	// 誤差格納用の領域を確保
	var errR = new double[w, h];
	var errG = new double[w, h];
	var errB = new double[w, h];
	var errA = new double[w, h];

	for(int i = 0; i < w; ++i) {
		for(int j = 0; j < h; ++j) {
			errR[i, j] = 0;
			errG[i, j] = 0;
			errB[i, j] = 0;
			errA[i, j] = 0;
		}
	}

	for(int y = 0; y < h; ++y) {
		for(int x = 0; x < w; ++x) {
			var index = (y * w + x) * PIXEL_BYTES;
			uint r = bmp[index + 0];
			uint g = bmp[index + 1];
			uint b = bmp[index + 2];
			uint a = bmp[index + 3];

			r = channelFilter(r, x, y, ref errR, mode, Channel.R);
			g = channelFilter(g, x, y, ref errG, mode, Channel.G);
			b = channelFilter(b, x, y, ref errB, mode, Channel.B);
			a = channelFilter(a, x, y, ref errA, mode, Channel.A);

			var color = Color.FromArgb((int)a, (int)r, (int)g, (int)b);
			bmp[index + 0] = color.R;
			bmp[index + 1] = color.G;
			bmp[index + 2] = color.B;
			bmp[index + 3] = color.A;
		}
	}
}

 

では、出力を比較してみましょう。

 

元画像
20170915_original

 

RGB565
20170915_rgb565

 

RGBA4444
20170915_rgba4444

 

全然違いますね。RGB565なら、ぱっと見では元画像と同じに見えます

 

ところで、Unity(5.4以前)でテクスチャフォーマットを16bit Colorで指定したとき、
元画像が不透明だと自動でRGB565に変換されます(※)が精度は良くないです・・・

 

ここで今回の手法を適用した画像を使うと、Unityの自動変換による劣化をかなり防げます

 

※Unity 5.5からテクスチャフォーマットの直接指定はプラットフォーム別にしかできなくなりました。
 旧バージョンからアップグレードした時には、metaに中途半端な設定が残ることもあるので注意しましょう。
 エディタ上で「RGB 16 bit」と表示されるものが「RGB565」に相当します。
(参考:Unity – Manual: Texture compression formats for platform-specific overrides

 

こういう減色ツールが手軽に使えるものとしてなかったりしますが、
原理は簡単なので作ってしまえば何かと融通がききそうです


ヘキサブログ ピックアップ



過去の日記はこちら

2017年9月
« 8月   10月 »
 123
45678910
11121314151617
18192021222324
252627282930