Google

2016年11月30日水曜日

RuntimeSTLLoader:頂点カラーとプレハブ化

前回はSTLフォーマットに埋め込んだカラー情報の件でした。
RuntimeSTLLoader ver1.3.0のアップデート記事は今回がラストです。

前回も書きましたが実はこのカラー表現、テクスチャを使用していません。
テクスチャでもいいのですが、簡易に使って頂くプラグインとしては価格も処理時間もコストが上がりすぎる危険性があったので避けた次第だったりします。

ではどうやって色を出すかと言うと、「頂点カラー」を使用しているのです。

この方式は頂点に対して色を付けるため、山の頂点が1つの色で塗りつぶされ、他の色に向かう部分はグラデーションが掛かるのが普通です。
また、カラーをそのまま使うのではなく、テクスチャのブレンド情報等に使ったりもします。

頂点単位で色を決めるのでこういうデモが多いですね。

こんなふうに複数のテクスチャの濃度を反映させたりして使うのが最近の普通です。
しかし当プラグインではグラデーションを適用させず、ポリゴン単位でカラーを反映させるようにしました。
これによってバー○ャ1のようなポリ単位でのカラー表現が可能となっています。
あ、元々Unityでは頂点カラーをそのまま表示できない点も売り文句となっております。エンジニアにとっては常識かも知れませんが一応。


テクスチャが普通の時代にバーチ○1とは、、、と思うかも知れません。
が、入り組んだ構造の中にスプレー噴射できる3Dプリンタができるにはまだ時間が掛かるのと、ゲーム以外の業務用途ではそれなりに需要があったりもする訳です。
実際、海外からの質問が多いので毎回翻訳どうしようという感じです。


そしてカラー版を作ってみて初めて気づいた点が一つ。
RuntimeSTLLoaderで作成したオブジェクトは、Unity Editor上で作業するという条件付きでプレハブ化することが可能という機能(というかUnityの機能ですが)を掲げていたのですが。
なんとカラーSTLをプレハブ化すると、そのままカラー情報までプレハブとして扱ってくれる事が判明したのです!
プレハブ化したらカラーが消えるのではと想定していたので嬉しい誤算でした。


兎にも角にも扱い辛いSTLもプレハブになってしまえば後は簡単。
このプラグインでSTLを毎回ロードするもよし、プレハブ化して便利に使うもよしかと。

同梱のデモアプリにはプレハブ化ボタンが元々あるので、実験開始してみましょう。
今回も被験体はTINKERCADからパクって来ました。

当プラグインに同梱されている「TestScene」というデモをUnity Editor上で起動して、、、、

TINKERCADから落としたファイルをプロジェクトに入れ込み、
プロジェクト一覧上で右クリすると、デモ上で簡単にロードする事が可能です。
ボックスにSTLのパスが入ったのでこのボタンを押すだけで表示されます
カラフルなSTLが表示されましたね。
版権は、、、、ゲフンゲフン。
「ド」の文字が間違っているのでセーフということでw

サイズが大きいのでGameObjectが複数に分割されているのが解ります。
このデモをUnity Editor上で実行中に、STLが表示された状態で、という条件の元で、
この赤丸のボタンを押すとプレハブ化してくれます。
このようにプレハブとMeshが複数生成されます。
このプレハブをシーンにドラッグ&ドロップすると、カラー付きでGameObject化!
どうやらプレハブに情報が残ってくれているようです。
シーンのヒエラルキーを見るとちゃんと構成されているのが解ります。
と、いう事で商品宣伝はこれぐらいで。

RuntimeSTLLoaderのご利用、弊社へのご用命のほど、よろしくお願いします。

2016年11月24日木曜日

RuntimeSTLLoaderのカラー表現方法

前回も紹介記事だったので恐縮ですが、
無事リリースも書き終わったRuntimeSTLLoader ver1.3.0の件で補足です。


RuntimeSTLLoaderリリース記事(イノベーションズアイサイトへ)


今回のテーマはSTLフォーマットと色に関する事です。
STLは元々色が存在せず、バイナリフォーマット版だけがカラー対応可能である件は前回話しました。
そのバイナリ形式ならなぜ色情報を含められるのか?という点を解説します。
C言語とか古い時代からプログラミング経験があるならもうお察しかも知れません。

それは、データの中にある「フォーマットのスキマ」を使っているからです。

かなりフザけた絵ですがw
バイナリ形式のSTLデータには各ポリゴンの頂点情報が埋め込まれているのですが、そこには結構なスキマが決め事として存在しています。
構造体に隙間ができる事が常識だったC言語の時代を想定していたのかも知れません。

ちなみにその量は1つのポリゴン情報に付き16bit分。
元々STLはポリゴン数が多くなる傾向にあるため結構無駄です。

白黒STLモデルデータのダンプです。中に00 00が多々あるのが解りますでしょうか?
白黒データでは使われていないので00 00が入る事が多いようです。
この16bitを3つに分解し、5bitずつRGBの情報を格納してるのが今回サポートしたカラー方式です。
つまり、表現できるのは「RGB555」という事になる訳です。

5x3=15bitということで、残った1bitがあるのですが、、、、
これについては私が知る限り2パターンの使い方が存在しています。
  • 無視する
  • 1なら色を適用し、0なら適用しない
後者の0なら適用しないという方は「じゃあ0だったらポリゴンは何色にするんだ」という情報が殆ど見当たらず、面倒くさいので前者の方式を使う事にしました。
(白だとは思いますがその確証が無いですし)

しかしSTLにはテキストフォーマットというのもあります。
じゃあテキストはなんで入らないの?という事になるのでしょうが、テキストはスキマを残すという概念が無いのが要因です。
以下のSSはテキストフォーマット版のSTLをエディタで開いた状態です。

こんな風に、秀丸で開けるような簡単な形式です。
ここにカラー情報を入れ込む余地は無く、無理に入れれば他のSTLビューアがエラーを起こしてしまうかも知れません。
これはもう、STL拡張方式を決めるとか、別のフォーマットで代替するとかしないと駄目ですよね。
という事で、バイナリだけスキマの情報を使うという姑息な手段で埋め込んでいるという次第です。

そして今回のカラー表現、実はテクスチャを使っていません。
簡単に言うとポリゴン自身に色を付けるという方式でこのカラーリングを実現しています。
5bitずつ色情報を入れてしまっている以上、アルファ情報は入れる余地はありませんが。

これがカラーSTL専用のマテリアルです。Diffuseベースですが色指定はありません。反映濃度だけ設定可能です。
最初は色情報をテクスチャとして生成することも考えていたのですが、マテリアルの生成数やUVマッピングの逆算、テクスチャ生成等のコストが恐ろしい量となってしまうことが判明し断念しました。
そもそも色表現なんて無限の組み合わせなんですから仕方ないのですが、それに早く気が付くべきだったという、情けない経緯があった訳です。

書いていたら長くなってきたので、後1回書きます。
次回は頂点カラーとプレハブの話です。

2016年11月20日日曜日

RuntimeSTLLoaderをカラー付きSTLに対応

アナウンスから時間が経ってしまいましたがAsset Storeの申請が通りましたので宣伝です。

この度、RuntimeSTLLoader ver1.3.0が公開となりました。
元々安いのにお値段据え置き機能強化というお得なアップデートです!
Unity4を未だに使い続けなければならない企業様のために、動作環境は4.6.9以上としました。
是非ご利用下さい!

さて、メイン画像はこうなって鮮やかな印象になっています。

NASAで配布しているパイオニアのSTLはモノクロなので持ってきてもこうはなりません。ご注意を。
肝心のバージョンアップ内容ですが、、、
UWP関連のエラーを取っただけじゃなく、今回の目玉はカラーSTL(Colored STL)への対応です!
3Dプリンタのカラー化も進んできているので、Unityと3Dプリンタ/CADの親和性を向上させるこのプラグインはきっとお役に立てるのでは無いかと。

弊社ロゴもレインボーにして同梱してみました。ロゴなんてお客様にとって使い処は全くありませんがw

ここでSTLに対するちょっとしたうんちくと概略を。

STLは元々CADで使われており、3Dプリンタの標準フォーマットとしても良く使われています。
フォーマットはバイナリとテキストの2種類のバリエーションがあります。
実はこのうちバイナリ限定「カラー付きフォーマット」というものが存在しています。

しかしSTLというこの規格、どっかの団体が決めて管理している訳でもなく、このカラーフォーマットに絶対的な取り決めはありません。
各々業者が独自に設計し使っているというのが現状です。
その方法にも幾つかバリエーションがあって混乱しているという状況ですが、1.3.0ではまず比較的メジャーと思われる方法を採用することにしています。
今後のために別業者版のカラーデータを適用させるための余地も作っておきました。

うんちくはこれぐらいにして、カラー実験に便利なのはAutodeskのTINKERCADです。

AutoDesk TINKERCAD


ブラウザ上でSTLを読み込んで色をつけたり、3Dのクリップアートのようなパーツを読み込んでSTLで吐き出せたりと、積み木のように使える3Dツールです。
無料登録でも使える機能は多いのですが商用は毎月払う必要がある点に注意を。

このツールは当プラグインと機能が被る部分があるのでアレですが、ウチのはUnityで動かせてプレハブ化できるという点もあるので競合とまではいきません。
ちなみにここにはユーザが作ったギャラリーがあります。


使い方はさておき、ここからダウンロードする方法を書いてみます。
無料で良いのでアカウントを作っておく必要がある点にご注意を。

左上の戦車を例にします。
クリックすればこんな感じになります。


左下の赤丸をクリックしましょう。


この中から「.STL」を選択すればダウンロード開始です。
他のフォーマットには「Colors」とか書いてあるのでSTLは白黒なのでは、、、、と思うかも知れませんがご心配なく。
カラー情報付きのバイナリフォーマットでダウンロードができます。

そうやって落としたものを当プラグインに読み込ませるわけですが、読み込み方は昔から変わっていないためこれは割愛させて頂くとして。
(補足:Unity Editor上であれば非常に簡単に表示できます)

このギャラリーから派手っぽいものを勝手に借りてきて幾つか表示してみました。

先程のダウンロード方法にあった戦車です。
東京駅のようなモダンな建築も問題なし
版権がゲフンゲフンなものも、、
これもまた、、、コメントは控えさせて頂きますw
弊社ロゴのように、ポリゴンが分割したものも1オブジェクトとして扱えます。
こういった3Dプリンタのカラー確認ツールとしても使えるのではないでしょうか。
某大企業が怖いですが、、、w スマホケースのプリント確認機能に良さそうです。
この商品に関してはあと1回記事を記載する予定。
次は描画のカラー化に関する細かい話です。

2016年11月9日水曜日

UnityのUWP環境におけるStream系API問題

最近はPixiJSの初心者記事を続けていますが、表題についてノーマーク過ぎた件について備忘録を書いておきます。

うちでは以前Windowsアプリを開発していたのですが、UWP関連の案件は殆どやってない(というかそういう案件が来ない)のでWindowsPhoneの実機も買う気がなく、Win10はあるものの殆どUWPの情報を仕入れてませんでした。
と、そんな折、海外のお客様から連絡が。

RuntimeSTLLoaderがUWPで動かないのでアドバイスが欲しい、、、、と。

慌ててWin10環境でUWPへのビルドを掛けるとエラーがorz

元々互換性を考えてUnity4.6を基準として作っているし、UWPはサポート対象に入ってないから関係ないしとか、色々言い訳を考えつつも調べてみると、StreamReader系はUWP環境で動作するAPIが変わっている事に気づきました。

このあたりがUnity monoとMicrosfot系.netとの互換に関する問題というか、メリットでもデメリットでもある特性の一つです。
そもそもUnityのmonoは完全互換とは言いがたくUnity .netとか呼んでいたりしたぐらいですし、このStreamReaderのようにUnityに存在しないライブラリは他の環境から持ってこれたりするのでこんな問題も発生したりします。


愚痴はこれぐらいにして、問題となったのはまずコンストラクタ。
StreamReaderのコンストラクタには幾つか種類がありますが、、、、

    new StreamReader(file_name, System.Text.Encoding.Default);

旧バージョンはこういう書き方でした。
Encoding.Defaultは問題も多くやめたほうが良いという記事も散見されるのですが、どうせアスキー処理しかしないのでここでは関係なかったりもします。
それでもエラーはエラーなのでこれはこう書き換えました。

    StreamReader((System.IO.Stream)File.OpenRead(file_name));

続いてクローズ。
こんなのまでだめとは。

    StreamReader reader;
    // 読み込み処理等がここに入ります。
    reader.Close();

代替メソッドとしてDisposeが使えるようなのでそちらに変更。

    reader.Dispose();

後は必要に応じてガーベッジコレクション等も掛けるべきです。
これでUnity Editorは勿論、VisualStudioに持っていってもエラーは出なくなり一安心。

これ以外にも幾つかの変更があったのですが、RuntimeSTLLoaderはこれぐらいで済みました。
当然ながらStreamWriterも同様に相違点がありますし、細かいAPIを挙げていくとキリがないかも知れません。

StreamReader MSDN
https://msdn.microsoft.com/ja-jp/library/system.io.streamreader(v=vs.110).aspx


ちなみにこの修正を施したRuntimeSTLLoaderは間もなくリリースです。
エラー修正のみのリリースはアレなので、3Dプリンタに関係する追加機能を盛り込む予定。
既にお使いの方はお待ち下さい。

2016年11月7日月曜日

PixiJSで画像表示の基礎

さて今回はPixiJSで画像の描画と移動までやってみます。

まず画像の読み込みです。
基本的な読み出し方はこう。

普通、画像はpng等を準備して表示するのでこのような形が実践に近いでしょう。

PIXI.Texture
https://pixijs.github.io/docs/PIXI.Texture.html
PIXI.Sprite
https://pixijs.github.io/docs/PIXI.Sprite.html

本家Pixiで使用してる小さなうさぎの画像を使うならこうします。

前回のHelloWorldにこれをいれたのが以下のアドレスです。

Pixi画像テスト

うさぎの後ろをHello Worldが流れていきます。
ワンテンポ遅れてうさぎの絵が出るのが確認できたでしょうか?
そのコードはこちら。
作成する側が必ず考えるべき事として、外部サーバに存在する画像の読み込みは内部の初期化と比較して非常に時間がかかるという点があります。
完了イベントを準備し、イベントの中で登録しないとエラーになるケースもあるのですが、遅延しても影響の無い造りになっています。

完了イベントを待って行儀よく処理をするならこうです。
本来なら全てを待ってから開始しなければなりませんし、余計なりソースをロードするとお客さんを無駄に待たせてしまいますので、これはローディング画面などを準備すべき部分でしょう。

移動は前回のテキストと原理や方法は全く同一です。
PIXI.TextはこのPIXI.Spriteから派生しており、メソッドやプロパティはそのまま使えます。

地味な記事が続きますが、次回は回転拡大縮小です。

2016年11月3日木曜日

PixiJSの描画サイクルと更新

前回は初心者向け講座等でお馴染みのHello Wolrd!を作ってみました。
PixiJSの描画基礎をまとめ直すとこうなります。
  • コンテナを作って描画したいオブジェクト(画像、文字)をぶら下げる
  • レンダラを作ってメンバのviewをタグの中にぶら下げる
  • レンダラにコンテナを全て描画するように依頼
前回のHello Worldでは単に描画してオシマイでした。
今回はこれをゲームやアニメの効果っぽく動かします。

そもそも人の目から見て動いているように見えるのは、情報が連続して更新され残像が見えるためであってCanvasに限った話ではありません。
ゲームのようにアニメーション(ここでは動くとか変わるという意味)をさせたいのであれば、再描画のタイミング毎に消して書き換える必要があります。

原始的なアニメーションの例
しかし消したり書いたりといった処理の殆どはCanvasやPixiが担当するので気にする必要はありません。
プログラマ側は変更処理だけで済み、メイン処理に注力できる訳です。

その具体例がこちら。
前回のHello World!改造し、文字が動くだけのデモです。

解りにくいのですが、文字が右に流れます
デモのURLはこちら。
http://angework.com/pub/PixiJS/index2.html

そしてソースコードがこちら。


前回から増えたのは大雑把に言うと2つです。
  1. コンテナやレンダラ等を変数として外に出して明示化
  2. アニメーション処理関数を追加
前者は何度も描画を繰り返す際に使用するためにグローバルにしました。

使っている変数3つを外に出しました。こうしなくても動きますが横着はいずれ自分の首を締めます。
この規模ならvar宣言が無くても問題なく動きますが、綺麗に書く癖は付けた方が良いでしょう。

後者が再描画に関するキモ。anmate()関数です。


テキストのX位置が幅を超えたら戻すという処理が18-22行目。
全ての描画対象は座標情報を持っており、初期値はxもyも0です。この値は19行目のようにプロパティとして取り出したりセットしたりできるので、この値で判断が行います。
そして前回ど同一のコンテナ再描画命令が24行目。

そして26行目でrequestAnimationFrame()というメソッドを使っています。
これはHTML5で追加された機能で、再描画の直前のタイミングで指定した関数をコールしてくれるという代物。
この引数には関数名の括弧抜きで渡して下さい。
今回はanimate()という関数があるのでanimateという関数名だけを渡しています。
ちなみに再描画タイミングはハード依存なので、フレームレート重視のゲーム等では工夫が必要です。


このサイクルを言葉でまとめてみました。
この2つが理解できればPixiでアニメーションする単純な処理は殆ど書けるでしょう。

初期化:
  • コンテナを作って描画したいオブジェクト(画像、文字)をぶら下げる
  • レンダラを作ってメンバのviewをタグの中にぶら下げる
    • 実質、PixiがCanvasタグを生成してタグに紐付ける事になる
再描画サイクル:
  • 位置の変更など、次のフレームで変更する内容を処理
  • レンダラにコンテナを全て描画するように依頼
  • 次の再描画直前にまたこの処理を読んでもらう

位置が動くだけの場合、オブジェクトの位置を変更するだけで勝手にPixiが処理をしてくれます。
キャラが歩くのなら毎回画像を差し替えなければなりません。


更に理解を深めるための実験方法も出してみます。

おさらい確認実験

26行目のrequestAnimationFrameをコメントアウトすると、前回と代わりません。
つまり位置が変わっても再描画をしていないことが解ります。
また、42行目のanimate();をコメントアウトすると、描画サイクルが始まらないので文字自体が出ません。
38行目の文字オブジェクトは空文字""でも生成可能です。何も出ないのでツマラナイですが、エラーではない正常な処理です。


今回も地味でした。
次回は画像の描画処理を書くので少し派手になります。