2D CSG(衝突形状用)を実装していますか?


7

2Dポリゴンでの基本的なCSG操作のための単純な(または十分に文書化された)アルゴリズムはありますか?

いくつかの重複する2D衝突形状を「追加」する方法を探しています。これらは凸状または凹状ですが、自己交差のない、一連の線分として定義される閉じた形状になります。

これを使用すると、2D物理エンジンで使用するために、それぞれが独自の衝突形状を持つ多数の任意に配置された(頻繁に重なり合う)オブジェクトで構成されるシーンから、クリーンな衝突エッジのセットを構築できます。

まず、形状を「追加」するだけで十分ですが、穴を作成するために「差し引く」機能も役立ちます。


自分で答えを追加する-私がこれを使用することになったので:sourceforge.net/projects/polyclipping-ゼロから実装を試みるのではなく。これまでのところ、それは非常にうまく機能しており、(C#を使用して)非常に簡単に使用できました。ウィキペディアには、適切な用語を使用して検索を開始すると、主題に関するかなりの情報へのリンクがあります。en.wikipedia.org
bluescrn

これは、3D CSGの素晴らしいJavaScript実装です。これは確かにあなたの問題にとってやり過ぎですが、コードは小さく、クリーンで、十分に文書化されているので、勉強することで多くを学ぶことができます。
DaleyPaley 2013

回答:


3

これはレベルデザイナー用ですか、それともエンジン用ですか?

レベルデザイナー-静的オブジェクトを組み合わせるなどのコードが必要です。ソリューションのベクターグラフィックAPIを研究すると、タスクはSVG、PostScript、WMFなどでかなり一般的に聞こえます。最初にCombineRgn Win32 APIを使用してみてください:-)

ゲームエンジンの場合-必要なことをしないことをお勧めします。オブジェクトを結合するために大量のCPUを費やすことになります。境界条件をチェックしたり、2つのセグメントが交差するかどうかをテストしたりするなど、膨大な数の分岐予測ミスを費やすことになります。また、このプロセスは、マップの表示部分のフレームごとに繰り返す必要があります。

境界ボックスのチェックを行ってから、個々のオブジェクトを衝突させます。オブジェクトの形状が複雑すぎる場合-エンジンにデータをエクスポートする際にそれらを単純化し、衝突と描画に異なる形状を使用します。

更新:あなたが望むことをする私のC#GDI +コードを見てください。C ++でも同じように簡単に記述できます。GraphicsPathクラスは、対応するgdiplus.dll関数の単なるラッパーです。

static class GraphicsPathExt
{
    [DllImport( @"gdiplus.dll" )]
    static extern int GdipWindingModeOutline( HandleRef path, IntPtr matrix, float flatness );

    static HandleRef getPathHandle( GraphicsPath p )
    {
        return new HandleRef( p, (IntPtr)p.GetType().GetField( "nativePath", BindingFlags.NonPublic | BindingFlags.Instance ).GetValue( p ) );
    }

    public static void FlattenPath( this GraphicsPath p )
    {
        HandleRef h = getPathHandle( p );
        int status = GdipWindingModeOutline( h, IntPtr.Zero, 0.25F );
        // TODO: see http://msdn.microsoft.com/en-us/library/ms534175(VS.85).aspx and throw a correct exception.
        if( 0 != status )
            throw new ApplicationException( "GDI+ error " + status.ToString() );
    }
}

class Program
{

    static void Main( string[] args )
    {
        PointF[] fig1 = 
        {
            new PointF(-50, 0),
            new PointF(0, 50),
            new PointF(50, 0),
        };

        PointF[] fig2 = 
        {
            new PointF(-50, 25),
            new PointF(50, 25),
            new PointF(0, -25),
        };

        GraphicsPath path1 = new GraphicsPath();
        path1.AddLines( fig1 );
        path1.CloseAllFigures();

        GraphicsPath path2 = new GraphicsPath();
        path2.AddLines( fig2 );
        path2.CloseAllFigures();

        GraphicsPath combined = new GraphicsPath();
        combined.AddPath( path1, true );
        combined.AddPath( path2, true );
        combined.FlattenPath();

        foreach (var p in combined.PathPoints)
        {
            Console.WriteLine( "<{0}, {1}>", p.X, p.Y );
        }
    }
}

2

私は、CSGを使用して焦土/ワームスタイルのゲームプレイを作成する概念実証を少し書きました。私はそれをgluTessellateで実装しました。次に、テッセレーションされた三角形をBox2Dポリゴンにマッピングしました。シミュレーションから汚れを追加および削除したり、穴を開けたり埋めたりすることができました。

私がgluTessallateを使用して見つけた最大の問題は、それが退化した三角形を返すことに問題がないことです。テッセレーションされた三角形を物理エンジンに移動する前に、それらを除外する必要がありました。

gluTessallateの優れた点の1つは、コールバック情報から隣接関係を判別できることです。私はそれをさらに進めることはありませんでしたが、理論的には隣接とSCCを使用して、単独運転を正確に検出できます。


興味深いことに、私はそれについて読む必要があります。ただし、私は三角形のメッシュから離れて-純粋にアウトラインエッジを処理しようとしています(衝突の目的で、アウトラインの頂点に接続されている内部/閉じたエッジは不要な衝突を引き起こす可能性があります)。しかし、中間ステップとして三角形メッシュを使用して、内部エッジをフィルタリングする前に、可能なアプローチはありますか?
bluescrn 2010年

1
gluTessellateにもアウトライン専用モードがありGLU_TESS_BOUNDRY_ONLYます。私が提供するリンクには、特にCSGに関する短いセクションがあります。
deft_code

うわー、それは驚くほど強力に見えますが、gluにその機能が含まれていることに気づきませんでした。それは(私のツールはD3Dベースにもかかわらず)オプションだように見えますが、私はまだDIYソリューションに関与していることでしょうアルゴリズムに関する非常に好奇心が強い
bluescrn

OpenGLのテッセレータには、目新しいものは何もありません。どんな高度なテッセレータでも同様のことができると思います。また、DirectX11はハードウェアテセレーションを備えています。CSGに必要な高度な機能があるかどうかはわかりませんが、一見の価値はあります。
deft_code
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.