8

マーチングキューブ(または、これは2Dであるため、マーチングスクエア)を使用して等値面をレンダリングし、セットの差、交差、和集合などのセット操作を実行したいと思います。これは、2つの異なる陰関数曲面から2つの頂点スカラーから選択するだけで簡単に実装できると思いましたが、そうではありません。

最初のテストでは、2つのの円と、設定された操作の違いを試してみました。つまり、A-B。一方の円は移動しており、もう一方の円は静止しています。これは、頂点スカラーを選択するとき、およびコーナー頂点を内側または外側として分類するときに試したアプローチです。コードはC++で書かれています。OpenGLはレンダリングに使用されますが、それは重要ではありません。CSG操作を使用しない通常のレンダリングでは、期待どおりの結果が得られます。



       void march(const vec2& cmin, //min x and y for the grid cell
                  const vec2& cmax, //max x and y for the grid cell
                  std::vector<vec2>& tri, 
                  float iso,
                  float (*cmp1)(const vec2&), //distance from stationary circle
                  float (*cmp2)(const vec2&) //distance from moving circle
)
{
  unsigned int squareindex = 0;
  float scalar[4];
  vec2 verts[8];
  /* initial setup of the grid cell */
  verts[0] = vec2(cmax.x, cmax.y);
  verts[2] = vec2(cmin.x, cmax.y);
  verts[4] = vec2(cmin.x, cmin.y);
  verts[6] = vec2(cmax.x, cmin.y);

  float s1,s2;
  /**********************************
   ********For-loop of interest******
   *******Set difference between ****
   *******two implicit surfaces******
   **********************************/
  for(int i=0,j=0; i<4; ++i, j+=2){
    s1 = cmp1(verts[j]);
    s2 = cmp2(verts[j]);
    if((s1 < iso)){ //if inside circle1
      if((s2 < iso)){ //if inside circle2
        scalar[i] = s2; //then set the scalar to the moving circle
      } else {
        scalar[i] = s1; //only inside circle1
        squareindex |= (1<<i); //mark as inside
      }
    }
    else {
      scalar[i] = s1; //inside neither circle
    }
  }

  if(squareindex == 0)
    return;
  /* Usual interpolation between edge points to compute
     the new intersection points */
  verts[1] = mix(iso, verts[0], verts[2], scalar[0], scalar[1]);
  verts[3] = mix(iso, verts[2], verts[4], scalar[1], scalar[2]);
  verts[5] = mix(iso, verts[4], verts[6], scalar[2], scalar[3]);
  verts[7] = mix(iso, verts[6], verts[0], scalar[3], scalar[0]);

  for(int i=0; i<10; ++i){ //10 = maxmimum 3 triangles, + one end token
    int index = triTable[squareindex][i]; //look up our indices for triangulation
    if(index == -1)
      break;
    tri.push_back(verts[index]);
  }
}

これは私に奇妙なジャギーを与えます:(ソース:mechcore.net CSG操作は補間なしで行われているように見えます。三角形全体を「破棄」するだけです。他の方法で補間する必要がありますか、それとも頂点スカラー値を組み合わせる必要がありますか?私はこれでいくつかの助けが欲しいです。完全なテストケースはここからダウンロードできますここ


編集:基本的に、マーチングスクエアの私の実装はうまく機能します。壊れているのは私のスカラー場であり、正しい方法はどのようになるのだろうかと思います。できれば、通常のプリミティブ(円、長方形/正方形、平面)に対して、上記で説明した3つの集合演算を実装するための一般的なアプローチを探しています。

編集2:回答者のホワイトペーパーを実装した後の新しい画像は次のとおりです。

1.
違い2.交差点3.
結合

編集3:適切なシェーディング/ライティングを使用して、これも3Dで実装しました。

1.大きい球と小さい球の違い2.中央の大きい球と小さい球
の違い。両側の2つの平面でクリップされ、中央の球と結合します。
3.2つのシリンダー間の結合。

4

1 に答える 1

4

これは、スカラー フィールドを混合する方法ではありません。あなたのスカラーは一つのことを言いますが、あなたが中にいるかどうかにかかわらず、あなたの旗は別のことを言います. 最初にフィールドをマージしてから、単一の複合オブジェクトを実行しているかのようにレンダリングします。

for(int i=0,j=0; i<4; ++i, j+=2){
  s1 = cmp1(verts[j]);
  s2 = cmp2(verts[j]);
  s = max(s1, iso-s2); // This is the secret sauce
  if(s < iso) { // inside circle1, but not inside circle2
    squareindex |= (1<<i);
  }
  scalar[i] = s;
}

リプシッツ ベースのインプリシット サーフェスを使用したソフト ブレンディングと CSG モデリングの組み合わせの記事が役立つ場合があります。

于 2010-05-24T19:26:48.407 に答える