Onoty3D

Unityに関するメモとか

指定範囲のモデルをボクセルで生成し直す

2017/06/11 19:40
スクリプトに一部不備がありましたので修正しました…(てへぺろ)

指定範囲にあるモデルを、別の場所にボクセルで生成し直すスクリプトを作りました。

もともととあるイベントで利用された?(※)、#オノッチ解体ショー というハッシュタグの便乗ネタで、twitterのアイコンにもしている鹿モデルの解体をするために作ったスクリプトです。

福岡VR・ARコンテンツの開発とWindows 10最新情報セミナー - Togetterまとめ

解体~!

f:id:onoty3d:20170611182652g:plain

ボクセル生成原理

原理としては簡単で、指定範囲に細かい点をプロットし、各点が指定範囲内にあるモデルのメッシュの内側であるならばそこにボクセルを生成する、という処理をしているだけです。
ネタがわかれば「なんだそれだけ」って感じの力技…。

メッシュの内側にあるかどうかの判定は、判定したい点に対して、上下左右前後の6方向からRayを飛ばし、そのすべてのRayが何かにHitすれば内側だとみなしています。f:id:onoty3d:20170611182819p:plain
よって6方向以外で隙間が空いている場合なんかは、外側でも「内側」だと誤認してしまいます。より厳密に判定したい場合は、Rayを飛ばす方向を増やしてみたりするといいかもしれません。
Rayを飛ばして判定しているので、指定範囲内に含むモデルは一部分でも、複数モデルでも問題ありません。
ただし後述しますが、MeshColliderをセットし、テクスチャのReadWriteEnabledをにチェックを入れる必要があります。

色の決定原理

ボクセルの色は、6方向から飛ばしたRayで、一番判定点の近くで衝突したRayのHit情報から取得しています。
HitInfoのTriangleIndexを利用するため、指定範囲内に含むモデルにはMeshColliderをセットしておいてください。
またテクスチャのReadWriteEnabledにチェックをいれておいてください。

f:id:onoty3d:20170611183708p:plain
中まででぎっちり色がついている

マテリアルのテクスチャから色を取りますが、テクスチャがない場合はマテリアルのカラー情報から色を取ります。
それでも色が取得できない("_Color"パラメタを持たないシェーダを使っている)場合は、黒色になります。
色が決定したら、あらかじめ指定したマテリアルを複製してボクセルにセットしています。よって好きなシェーダーを利用することができます。
ボクセルの数だけマテリアルが生成されるのは避けたいので、同じ色の場合はマテリアルを共通して使います。
(頂点カラーと、頂点カラーを表示するシェーダーを使えばマテリアルはひとつですみますが、好きなシェーダーを使える形にしたかった。)

スクリプトの使い方

まず指定範囲用の空のGameObjectを用意し、VoxelTargetAreaスクリプトをAddします。

f:id:onoty3d:20170611184212p:plain

TransformのPositionScaleで範囲の位置や大きさを変更できます。
VoxelCountパラメータで、X,Y,Z方向の細分化数が指定できます。
この設定値に従って、最大でX*Y*Z個のボクセルが生成されます。
細分化の個数によっては、生成されるボクセルがきれいな立方体ではなく直方体になったりします。
指定範囲と細分化の具合はSceneビューで青いGizmoで表示されます。

f:id:onoty3d:20170611184334p:plain

次に生成場所用の空のGameObjectを用意し、VoxelGeneratorスクリプトをAddします。

f:id:onoty3d:20170611190435p:plain

TextAreaパラメータには先程用意した指定範囲用のGameObjectを指定します。
(この時点でSceneビューに指定範囲と同サイズの赤いGizmoが表示されます。)f:id:onoty3d:20170611184404p:plain

Inside Checkerパラメータで、メッシュの内側判定に使うパラメータをセットします。
Target Layer:対象とするモデルのLayerが指定できます。指定範囲内でもTargetにしていないLayerのモデルは無視されます。
Ray Distance:点に対してどのくらいの距離からRayを飛ばすかを指定できます。モデルが大きい場合は大きな値をセットしてください。
Ray Radius:内側判定の精度をあげるため、RayCastではなくSphereCastを利用しています。上手くボクセルが生成されない場合は値を大きくしてみるといいです。

残りのパラメータで、ボクセルに関する情報を設定します。
Voxel Layer:生成するVoxelのLayerを指定できます。
Parent:生成するVoxelのParentを指定できます。
Base Material:生成するVoxelにBase Materialで指定されたMaterialのcloneをセットします。
Material Color Name:ボクセルの色を反映させるシェーダーのパラメーター名を指定できます。
Visualization:チェックすると、うちの内側判定とボクセルの生成をひとつずつ可視化して行います。

後は実行中にVoxelGeneratorのGenerateボタンを押せば、ボクセルが生成できます。
Visualization無し

f:id:onoty3d:20170611184628g:plain

Visualization有り

f:id:onoty3d:20170611184705g:plain

UnityPackage

鹿のサンプルシーンも含めたUnityPackageです。

VoxelGenerator

UnityPackageはUnity5.6で作成しています。5.5でも取り込めますが、鹿のテクスチャ情報が消えてしまう場合があるようなので、その時はテクスチャを再セットしてください。
またLayer8を"Voxel"として登録して置いてください。(登録しなくてもいいがVoxelLayerの設定が空欄になる。)

もっと作り込みできそうな所

マテリアルを動的に複製しているため、実行中に出来上がったボクセルをコピーして、終了後に貼り付けてもマテリアルがMissing状態になります。
実行後も再利用したい場合はマテリアルを保存する仕組みにすべきかと思います。

f:id:onoty3d:20170611185947p:plain

また、マテリアルは同色では共通して使うようにしていますが、テクスチャの色数が多いモデルの場合、同じような色でも微妙に違ったりして、どうしてもマテリアルの数が増えます。減色や均一化の処理をかました方がいいかと思います。
もしくはやっぱり頂点カラーの利用…。

ソース