以下の内容はhttps://godofsuama.hatenablog.com/entry/2024/05/13/100000より取得しました。


Tips - RBD Mesh Checker

RBDとかやるときのためにだいぶ前に作ったノードたちを引っ張り出して機能を追加してみた。

簡易チェッカーなので万能ではなく、もちろんこれに引っかかったものをどの程度許容するか?というのも考えないといけない。

もちろん全部クリアしたからと言って完璧に分割処理ができるわけではない。

まとめ

今回のはエラーの修復はできませんが、内部の処理の応用とかで修復の足掛かりにはなります。

でも分業とかであれば元のモデル自体を直すほうがいいです。(Houdini以外で)

この直す基準は個人的なものです。漏れがあるかも。

エラー内容 直す基準
Hole Mesh 絶対許さない。
Intersection 交差しすぎている場合は直す。少しなら妥協。
Reverse Normal 絶対許さない。
Concave Mesh Convex Decompositionで処理できそうなら妥協。
Acute, Small Triangle 基本許さない。目立たなさそうなら妥協。

Scene File

checkMesh_v003_gd.hiplc - Google ドライブ

作り

とりあえずサンプルに適当な各種メッシュを用意

Hole Mesh

Hole Meshかどうか?は、基本的にこのDivideのRemove Unshared Edgeをオンにした際になにかしらPrimitiveが残ってしまえば穴が空いていることになる。

Poly FillでPrimitiveが増えた=穴がふさがったとかの判定でもいいかもしれないが、Divideのが単純かな、と思う。

Intersection

Poly Doctorで検出できる。

Peakで少しだけ凹ませてもまだめり込んでいる場合で判定

Reverse Normal

何段回か判定が必要で、まずMeasureでVolumeを測り、この結果がマイナスのPrimitiveはNormalが反転していることになり、

全部の法線が反転している場合

さらに他のPrimitiveよりもVolumeの値が小さいものもNormalが反転しているので処理する。

一部反転している場合A

一部反転している場合B

一部反転している場合C

さらに、最後にCleanを使用してOrient Polygonsをした結果のNormalが反転したかどうかをチェックする。

vector normA = prim_normal(0,@primnum,0.5,0.5);
vector normB = prim_normal(1,@primnum,0.5,0.5);

if (normA != normB) {
    i@group__error = 0;
}

このCleanで反転した面は、法線が正しい面が反転した面より少ないせいでVolumeでの検出がうまく行かなかったPrimitiveということになる。ちょっとややこしい。

Concave

これはConvex Decompositionをかけた際に、segmentが生まれたらConcave扱いという雑な判定

Acute Triangle

これはもう全部VEX

//デフォルトの値
int array[] = primpoints(0,@primnum);
float edgeDist[] = array();
int i = 0;
int next = 0;
float edgelength = 0;

//外部入力の値
int times = chi("times");
float min_area = chf("min_area");

//各Primitiveを構成するPoint同士の間にPoly Lineがあるかを調べ、その距離を配列に入れる
//(最後のPointは最初のPointとつながっているかを調べる)
for(array[i]; i < len(array); i++){
    if(array[i] == array[-1]) {
        next = array[0];
    }else{
        next = array[i+1];
    }
    
    if(pointedge(0, array[i], next) != -1) {
        vector pos1 = point(0, "P", array[i]);
        vector pos2 = point(0, "P", next);
        edgelength = length(pos1-pos2);
    };
    append(edgeDist, edgelength);
};
//エッジ長の配列を小さい順に並べ替える
edgeDist = sort(edgeDist);

//Primitiveに含まれるPointが3であり、最長最短のエッジ長の差が最短 x timesのものをエラーとする
if(len(array) <= 3 && edgeDist[0] *times <= edgeDist[-1]) {
    i@group__error = 1;
};

//単純にポリゴン面積が小さいものをエラーとする
float prim_area = primintrinsic(0,"measuredarea",@primnum);
if(len(array) <= 3 && prim_area <= min_area) {
    i@group__error = 1;
}



以上の内容はhttps://godofsuama.hatenablog.com/entry/2024/05/13/100000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14