渋谷ほととぎす通信

完全趣味でやってるUnityメモ。説明できないところを説明できるようにするための個人ブログ。昨日の自分より少しでも大きくなれるように。。。 ※所属団体とは一切関係がありません

Unity マウスに追随する形で動的にメッシュを生成する


f:id:esakun:20181205152326g:plain

動的にメッシュを生成するシリーズです。

今回はマウスに追随するブラシのようなメッシュを動的に生成したいと思います。

先日執筆した球の描画より簡単です。

頂点の座標と順番

その前に頂点の座標を決めるためのマウス座標の変換処理の説明を少しだけ。

_mousePos = Input.mousePosition;
// マウス座標をワールド座標に変換
_mousePos.z = Mathf.Abs(_cam.transform.position.z);
var pos = _cam.ScreenToWorldPoint(_mousePos);

Camera.ScreenToWorldPoint関数を使用して楽をします。スクリーン座標のマウス座標を渡すだけでワールド座標に変換してくれる超便利関数です。

しかし、落とし穴もあります。マウス座標をそのまま渡してはいけない場合が多いです。マウス座標のz値は0です。

ScreenToWorldPoint関数は、カメラからオフセットした距離(与えたz値)上において、カメラから見たときのスクリーン座標と一致するワールド座標を割り出していますので、Z値が0だと、カメラのワールド座標が返って来てしまい、期待するような挙動になってくれません。

今回はマウスの位置とメッシュの生成場所を一致させたいので、メッシュが生成されるz座標を0としているため、原点から離れたカメラの距離をz値とするとマウスの位置と生成されるメッシュの位置がぴったり合います。
※カメラのx、y座標は0としています

f:id:esakun:20181206224338p:plain:w450

図のようにスクリーン座標からワールド座標に変換したマウス座標をもとに各頂点の座標を決めていきます。

// _widthは筆の幅、posはワールド座標に変換したマウス座標
var pt0 = new Vector3(pos.x - _width * 0.5f, pos.y, 0);
var pt1 = new Vector3(pos.x + _width * 0.5f, pos.y, 0);
var pt2 = new Vector3(pos.x - _width * 0.5f, pos.y, 0);
var pt3 = new Vector3(pos.x + _width * 0.5f, pos.y, 0);
_vertices.Add(pt0);
_vertices.Add(pt1);
_vertices.Add(pt2);
_vertices.Add(pt3);

今回はこのようなレイアウトにしています。 上記のコードは描画の初回フレームのみの処理です。


var pt2 = new Vector3(pos.x - _width * 0.5f, pos.y, 0);
var pt3 = new Vector3(pos.x + _width * 0.5f, pos.y, 0);
_vertices.Add(pt2);
_vertices.Add(pt3);

2フレーム目からは、このように2頂点ずつ追加していきます。


0, 1, 3
0, 3, 2

頂点インデックスは上のような順序にしています。


_indices.Add(_offsetIndex);
_indices.Add(_offsetIndex + 1);
_indices.Add(_offsetIndex + 3);
_indices.Add(_offsetIndex);
_indices.Add(_offsetIndex + 3);
_indices.Add(_offsetIndex + 2);

コード的にこのような感じになります。

_offsetIndexは初回の0,1,3,2四角形を描画した後は、頂点インデックス番号は2番から始まってほしいので、そのオフセットを行う変数です。

_offsetIndex += 2;

四角形を描画し終えた番号に2を加算すると頂点インデックスが繋がります。


ただしこのままだと、筆を下から上に移動させるとメッシュが反転するため、デフォルトのシェーダ設定だとカリングされて表示されなくなります。

Cull Off

と両面描画に設定にして、今回は表示させるようにしました。


全体コードはこんな感じです。

まとめ

結構お手軽にお絵かきっぽいメッシュを動的に作ることができました。
ただ、現状の実装だと、

  • 書きっぱなしで筆が繋がり続ける
  • テクスチャが貼れない
  • 筆の太さが一定
  • Z座標が一定(3D空間をフルに使ってみたい)

など、いろいろと調整できる項目がありそうです。


以上

その他の動的にメッシュを生成するシリーズ

Unity動的にメッシュを生成するシリーズ - 渋谷ほととぎす通信