web-dev-qa-db-ja.com

メッシュをスライスするためのアルゴリズムまたはソフトウェア

3Dメッシュをスライスするための正しいアプローチは何ですか?メッシュはすべて閉じたサーフェスであり、スライスはメッシュの内部にあるもののバイナリイメージである必要があります。したがって、たとえば、球とスライスの画像を表すメッシュは、塗りつぶされた円のメッシュです。

現在のC++プロジェクトに統合できるソフトウェアライブラリまたはアルゴリズムを探しています。

16
dr_rk

私のオープンソースゲームライブラリには、メッシュスライスの実装が含まれています。 Irrlicht APIで動作しますが、少しの努力で別のAPIを使用するように書き直すことができます。 BSDライセンスの条件の下でコードを使用するか、それから独自の実装を学ぶことができます。

メッシュスライシングの実装についてはこのファイル のMeshTools :: splitMeshZを参照してください。

アルゴリズムを知りたいだけの場合は、私が行ったことの概要を以下に示します。

私は当初、メッシュをカットする場所を指定するために、軸に沿ったバウンディングボックスを使用することを考えました。多くの特殊なケースが導入されたため、これは問題でした。たとえば、ボックスの角を横切るエッジは、2つではなく3つに分割される場合があります。

平面を使用してメッシュを左メッシュと右メッシュだけにカットすると、エッジが平面の片側または反対側にあるか、平面と交差して正確に2つに切り刻まれるため、特殊なケースの数が減ります。ピース。

カットの任意の構成は、1回カットし、結果のメッシュの1つを取得して、別の場所で再度カットするなどの方法で作成できます。具体的には、このセクションで説明する場合、球の半分を切り取り、平面を少し動かし、残りの半分を切り取って細いバンドだけを残すことで、球から円を切り取ることができます。 (私が書いたコードでは、文字通り深さのないメッシュを切り詰めることはできませんが、浮動小数点の等式しきい値を設定したものまでメッシュを切り取ることができます。コードで任意に0.001を選択したと思います。)

同様のロジックを使用して、固定平面を使用して切断面の任意の角度を実現できます。メッシュを変換して固定切断面を基準にして回転させてから、結果を元に戻す必要があります。 (私のゲームでは、XY平面に垂直なカットのみが必要だったので、簡単にするために、カットのZ値のみを設定し、カットがそのZ位置にあると想定します。)

さて、問題を単純化したので、アルゴリズムはそれほど悪くはありません。

開始条件:切断面があります。ソース三角形のセットがあります。 ポリゴンの2つの宛先セットがあります(三角形ではありません。三角形をカットすることで四角形を生成できます)。 2つの宛先セットはLeftとRightと呼ばれます。

プロセス:三角形の3点を繰り返します。切断面よりも小さい点の数を数えます。切断面よりも小さいものを左、切断面よりも大きいものを右と呼びます。ほんの一握りのケースがあります:

  • すべての三角形の点は左側にあります:三角形を左側のセットに入れます
  • すべての点が右側にあります:三角形を右側のセットに入れます
  • 1つのポイントが左、他のポイントが右です。2つのエッジに三角形を切り取り、ポイントの1つを保持していた場合、最終的には小さい三角形を保持することになります。左の点と、エッジが平面と交差する2つの点で構成される左のセットに三角形を配置します。クワッドを右セットに入れます(次のケースを参照)。
  • 2点が左、1点が右です。三角形のエッジを持っていて、他の2つのエッジを横切ってカットすると、台形を持ったままになります。手にある2つのポイントとカットを横切る2つのポイントで構成されるクワッドを左側のセットに置きます。右側のセットに三角形を配置します(上のケースの鏡像)。

  • 終了したら、最短部分にリンクを追加して、四角形を三角形に変えます。

それでおしまい。これが基本的なアルゴリズムです。実際のコードは、エッジがカットと正確に等しい場合、三角形がエッジ上にある場合、縮退したポリゴン(ボディのないポイントなど)を追加しない場合など、さらにいくつかのケースを処理します。

その他問題(すべてリンクされたコードでカバーされています):

  • エッジが切断面と交差する場所をLERPするための計算を過度に複雑にしないでください。完全な線形補間は必要ありません。実際には、高校の代数IIです。

  • 生成された(LERPされた)ポイントをキャッシュして、カットされていないメッシュで頂点を共有した三角形が、カットされたメッシュで対応する新しい頂点を共有するようにすると有利です。

  • 頂点の共有を維持する予定で、三角形のインデックスバッファを使用している場合、残念ながら、左と右のセットに配置するシェイプを最初に生成したときには、インデックスがまだわかりません。 「PossibleVertex」というクラスを使用して、将来の三角形のインデックス番号を表します。

  • メッシュを表示する場合は、巻き方が重要です。コード化の方法を慎重に検討することで、結果のポリゴンが元の三角形と同じ巻き順序を使用できるようになります。これは、クワッドを三角形分割するときに特に注意が必要です。詳細は思い出せませんが、リンクされたコードで処理されています。

  • 私のゲームでは、2つのカットメッシュをつなぐフラットリボンを作りたかったのです。そのため、splitMeshZは2つではなく3つのメッシュになります。中央のメッシュを使用することも、無視することもできます。

22
Dennis

3Dメッシュスライスのプロジェクト(C++のソースコードを使用):

http://www.dainf.ct.utfpr.edu.br/~rminetto/projects/slicing/

4
rdminetto

この回答 で平面と体積の交差を計算するアルゴリズムの概要を説明しました。 Javaの実装が提供されています。

3
ryanm

私はあなたが三角形メッシュについて話していると思いますか?

「正しい」アプローチとは、ユースケースの詳細に大きく依存します。

ジェリーによって提案されたOpenGLアプローチはあなたのために働くかもしれません。

別のアプローチは、カットを明示的に計算することです。 [〜#〜] cgal [〜#〜] でこれを行うことができます。より具体的には、その3Dカーネルを使用します。平面や三角形など、あらゆる種類のプリミティブ間の交点を計算できる 関数 を備えています。この関数を使用すると、交差点の輪郭を正確に計算して、画像にレンダリングできます。 -この方法では、OpenGLではなく、代わりにCGALに依存します。

1
hc_

自分で実装すると(実行時ではなく自分自身で)高速になります。次の簡単な手順を実行する必要があります。

1-メッシュのすべての三角形を抽出します

2-三角形ごとに、

2-1-三角形の点のいずれかがスライス平面上にあるかどうかを確認します。

2-2-そうでない場合は、その3つのエッジのそれぞれについて、スライス平面との交点を見つけます(存在する場合)。そのうちの2つを平面と交差させるか、交差させない必要があります。

2-2-1 2つのエッジが平面と交差している場合は、平面上のこれら2つの点の間に線を追加します。

0
user7440878