1

DirectX 環境でマーチング キューブ アルゴリズムを実装しました (テストして楽しむため)。完了すると、インデックスがずれているかのように、結果のモデルが大きく歪んでいることに気付きました。

ここに画像の説明を入力

インデックスを抽出しようとしましたが、 http://paulbourke.net/geometry/polygonise/の例のルックアップ テーブルを使用して、頂点が既に正しく順序付けられていると思います。現在のビルドは 15^3 ボリュームを使用しています。

マーチング キューブは、通常どおり配列を反復処理します。

for (float iX = 0; iX < CellFieldSize.x; iX++){
    for (float iY = 0; iY < CellFieldSize.y; iY++){
        for (float iZ = 0; iZ < CellFieldSize.z; iZ++){
            MarchCubes(XMFLOAT3(iX*StepSize, iY*StepSize, iZ*StepSize), StepSize);
        }
    }
}

MarchCube 関数は次のように呼び出されます。

void MC::MarchCubes(){

...

int Corner, Vertex, VertexTest, Edge, Triangle, FlagIndex, EdgeFlags;
float Offset;
XMFLOAT3 Color;
float CubeValue[8];
XMFLOAT3 EdgeVertex[12];
XMFLOAT3 EdgeNorm[12];

//Local copy 
for (Vertex = 0; Vertex < 8; Vertex++) {
    CubeValue[Vertex] = (this->*fSample)(
        in_Position.x + VertexOffset[Vertex][0] * Scale,
        in_Position.y + VertexOffset[Vertex][1] * Scale,
        in_Position.z + VertexOffset[Vertex][2] * Scale
  );  
}

FlagIndex = 0;

交差計算:

...
//Test vertices for intersection.
for (VertexTest = 0; VertexTest < 8; VertexTest++){
    if (CubeValue[VertexTest] <= TargetValue) 
        FlagIndex |= 1 << VertexTest;
}

//Find which edges are intersected by the surface.
EdgeFlags = CubeEdgeFlags[FlagIndex];
if (EdgeFlags == 0){
    return;
}

for (Edge = 0; Edge < 12; Edge++){
    if (EdgeFlags & (1 << Edge)) {
        Offset = GetOffset(CubeValue[EdgeConnection[Edge][0]], CubeValue[EdgeConnection[Edge][1]], TargetValue); // Get offset function definition. Needed!
        EdgeVertex[Edge].x = in_Position.x + VertexOffset[EdgeConnection[Edge][0]][0] + Offset * EdgeDirection[Edge][0] * Scale;
        EdgeVertex[Edge].y = in_Position.y + VertexOffset[EdgeConnection[Edge][0]][1] + Offset * EdgeDirection[Edge][1] * Scale;
        EdgeVertex[Edge].z = in_Position.z + VertexOffset[EdgeConnection[Edge][0]][2] + Offset * EdgeDirection[Edge][2] * Scale;

        GetNormal(EdgeNorm[Edge], EdgeVertex[Edge].x, EdgeVertex[Edge].y, EdgeVertex[Edge].z); //Need normal values
    }
}

元の実装は、DirectX の保持構造体にプッシュされます。

for (Triangle = 0; Triangle < 5; Triangle++) {

    if (TriangleConnectionTable[FlagIndex][3 * Triangle] < 0) break;

    for (Corner = 0; Corner < 3; Corner++) {
        Vertex = TriangleConnectionTable[FlagIndex][3 * Triangle + Corner];3 * Triangle + Corner]);
        GetColor(Color, EdgeVertex[Vertex], EdgeNorm[Vertex]);
        Data.VertexData.push_back(XMFLOAT3(EdgeVertex[Vertex].x, EdgeVertex[Vertex].y, EdgeVertex[Vertex].z));
        Data.NormalData.push_back(XMFLOAT3(EdgeNorm[Vertex].x, EdgeNorm[Vertex].y, EdgeNorm[Vertex].z));
        Data.ColorData.push_back(XMFLOAT4(Color.x, Color.y, Color.z, 1.0f));
    }
}

(これは元の GL 実装と同じ順序です)

4

1 に答える 1

0

結局のところ、演算子の優先順位を示す括弧がありませんでした。

    EdgeVertex[Edge].x = in_Position.x + (VertexOffset[EdgeConnection[Edge][0]][0] + Offset * EdgeDirection[Edge][0]) * Scale;
    EdgeVertex[Edge].y = in_Position.y + (VertexOffset[EdgeConnection[Edge][0]][1] + Offset * EdgeDirection[Edge][1]) * Scale;
    EdgeVertex[Edge].z = in_Position.z + (VertexOffset[EdgeConnection[Edge][0]][2] + Offset * EdgeDirection[Edge][2]) * Scale;

Visine を取得し、修正しました。楽しみを再開しました。

于 2016-05-27T06:20:34.380 に答える