ぐーるらいふ

しがないリーマンの記録。遊びのunityのメモ帳にしたい。

【Unity】 メッシュをカットした後のcappingを作ろう

以前

以前メッシュカッターについて記事にした事があった。

ghoul-life.hatenablog.com

この時はなるべく簡潔な話にしたく、オブジェクトを切った後の「蓋」については
特に触れなかったのだが、ちょっとやる機会があったので、書いておこうと思う。

メッシュ断面図

メッシュカッターはオブジェクトをポリゴン単位で考え、一つずつ丁寧に処理していく。
カットラインと交点がある場合は、新たに頂点が2つ作られる。
四角形だった場合は以下のような断面になる。
図だと少し分かりにくいが、二つに分かれたオブジェクト両方ともこのようになる。

f:id:ghoul_life:20170913001850p:plain

蓋の考え方

そしてここに蓋を作るのだが、蓋をどう作るか?を考える。
四角形ならどうにでもなりそうだが、円形や人型のオブジェクトだったらどうする?

f:id:ghoul_life:20170913001905p:plain

そういった事なども簡潔に解決する方法として、「中心点を作る」という方法がある。
この2点と中心点を繋いでいく、にすれば簡単な計算で作れそうだ。

f:id:ghoul_life:20170913001920p:plain

実装

まずは交点となった新たに作られた点を別リストとして取っておく

// どちらにもカウントがあるということはplateと交差しているポリゴンということ
if (group1PosList.Count > 0 && group2PosList.Count > 0)
{
    CalcCrossPoint(plane, group1PosList, group2PosList); // 2.planeとの交点を求める

    // 3.両方のグループともに交点を入れる
    group1PosList.Add(_pos1);
    group1PosList.Add(_pos2);

    // capping用の表
    group1CapPosList.Add(_pos1);
    group1CapPosList.Add(_pos2);


    group2PosList.Add(_pos1);
    group2PosList.Add(_pos2);

    // capping用裏側
    group2CapPosList.Add(_pos1);
    group2CapPosList.Add(_pos2);
}

中心点を求める方法はそこまで難しくない。
頂点をすべて足して、頂点数で割ればいい。

// 中心点を求める
Vector3 center = Vector3.zero;
foreach(var v in cappingPosList)
{
    center += v;
}
center = center / cappingPosList.Count;


そして交点となる2点と中心点を繋いでいく…のだけど、
カッターとなるplateのどちら側にあるかによって蓋の向きが変わる。
この事に注意して、indexを割り振っていく。

var idx0 = centerIdx;
var idx1 = i;
var idx2 = i + 1;

var cross = Vector3.Cross(capPosList[idx2] - capPosList[idx0], capPosList[idx1] - capPosList[idx0]);
var inner = Vector3.Dot(cross, plane.normal);

// plateに対してどちら側の蓋かによって計算が変わるのに注意
if (isFront)
{
    if(inner < 0)
    {
        idx0 = idx2;
        idx2 = centerIdx;
    }
}
else
{
    if (inner > 0)
    {
        idx0 = idx2;
        idx2 = centerIdx;
    }
}

完成

後は全ての頂点とindexをまとめて、
オブジェクトを作れば完成だ。

f:id:ghoul_life:20170912233913g:plain

f:id:ghoul_life:20170913143608g:plain

f:id:ghoul_life:20170913143650g:plain

複雑なオブジェクトでもちゃんと蓋が出来ている。
全体をまとめたプロジェクトごとgithubに公開している。
他にもMaterialを付与したり、Rigidbodyを付与したりという遊びも可能だ。
参考にしてほしい。

github.com