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が反転しているので処理する。



さらに、最後に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;
}