28

三角ストリップを使用して平面を描画する頂点のリストを生成するための最良のアルゴリズムは何でしょうか?

平面の幅と高さを受け取り、正しくインデックス付けされた頂点を含むfloat配列を返す関数を探しています。

widthは、行ごとの頂点の数を表します。

heightは、列ごとの頂点の数を表します。

float* getVertices( int width, int height ) {
    ...
}

void render() {
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, getVertices(width,heigth));
    glDrawArrays(GL_TRIANGLE_STRIP, 0, width*height);
    glDisableClientState(GL_VERTEX_ARRAY);
}
4

4 に答える 4

32

みなさん、ありがとうございました。私はこれをコーディングしました。それが正しいか?または、生成されたストリップはどういうわけか間違っていますか?

int width;
int height;
float* vertices = 0;
int* indices = 0;

int getVerticesCount( int width, int height ) {
    return width * height * 3;
}

int getIndicesCount( int width, int height ) {
    return (width*height) + (width-1)*(height-2);
}

float* getVertices( int width, int height ) {
    if ( vertices ) return vertices;

    vertices = new float[ getVerticesCount( width, height ) ];
    int i = 0;

    for ( int row=0; row<height; row++ ) {
        for ( int col=0; col<width; col++ ) {
            vertices[i++] = (float) col;
            vertices[i++] = 0.0f;
            vertices[i++] = (float) row;
        }
    }

    return vertices;
}

int* getIndices( int width, int height ) {
    if ( indices ) return indices;

    indices = new int[ iSize ];
    int i = 0;

    for ( int row=0; row<height-1; row++ ) {
        if ( (row&1)==0 ) { // even rows
            for ( int col=0; col<width; col++ ) {
                indices[i++] = col + row * width;
                indices[i++] = col + (row+1) * width;
            }
        } else { // odd rows
            for ( int col=width-1; col>0; col-- ) {
                indices[i++] = col + (row+1) * width;
                indices[i++] = col - 1 + + row * width;
            }
        }
    }
    if ( (mHeight&1) && mHeight>2 ) {
        mpIndices[i++] = (mHeight-1) * mWidth;
    }

    return indices;
}

void render() {
    glEnableClientState( GL_VERTEX_ARRAY );
    glVertexPointer( 3, GL_FLOAT, 0, getVertices(width,height) );
    glDrawElements( GL_TRIANGLE_STRIP, getIndicesCount(width,height), GL_UNSIGNED_INT, getIndices(width,height) );
    glDisableClientState( GL_VERTEX_ARRAY );
}

width=4およびheight=4の場合、これが私が得たものです。 ここに画像の説明を入力してください

そしてここで私はいくつかの頂点の高さを変更しています: ここに画像の説明を入力してください

于 2011-05-07T09:20:25.923 に答える
16

これを行うコードを次に示します(テストされていませんが、少なくともアイデアは得られます)。

void make_plane(int rows, int columns, float *vertices, int *indices) {
    // Set up vertices
    for (int r = 0; r < rows; ++r) {
        for (int c = 0; c < columns; ++c) {
            int index = r*columns + c;
            vertices[3*index + 0] = (float) c;
            vertices[3*index + 1] = (float) r;
            vertices[3*index + 2] = 0.0f;
        }
    }

    // Set up indices
    int i = 0;
    for (int r = 0; r < rows - 1; ++r) {
        indices[i++] = r * columns;
        for (int c = 0; c < columns; ++c) {
            indices[i++] = r * columns + c;
            indices[i++] = (r + 1) * columns + c;
        }
        indices[i++] = (r + 1) * columns + (columns - 1);
    }
 }

最初のループは、標準の長方形グリッドに頂点配列を設定します。R*C頂点があります。

2番目のループはインデックスを設定します。一般に、グリッドには正方形ごとに2つの頂点があります。各頂点により、(前の2つの頂点で)新しい三角形が描画されるため、各正方形は2つの三角形で描画されます。

各行の開始と終了の最初と最後の頂点が複製されます。これは、各行の間に面積がゼロの2つの三角形(縮退した三角形)があることを意味します。これにより、グリッド全体を1つの大きな三角ストリップに描画できます。この手法はステッチングと呼ばれます。

于 2011-05-06T22:31:15.657 に答える
8

上記のコードはどれも正しいメッシュ生成を提供しません。単純な平面上に三角形のストリップを作成する方法に関する非常に優れた記事:http://www.learnopengles.com/android-lesson-eight-an-introduction-to-index-buffer-objects-ibos/

これが実際にテストされ、完全に機能する私のテストコードです。

int plane_width = 4; // amount of columns
int plane_height = 2; // amount of rows

int total_vertices = (plane_width + 1) * (plane_height + 1);
planeVert = new CIwFVec2[total_vertices];
memset(planeVert, 0, sizeof(CIwFVec2) * total_vertices);

int numIndPerRow = plane_width * 2 + 2;
int numIndDegensReq = (plane_height - 1) * 2;
int total_indices = numIndPerRow * plane_height + numIndDegensReq;

planeInd = new uint16[total_indices];

make_plane(plane_width, plane_height, planeVert, planeInd);

...

void make_plane(int width, int height, CIwFVec2 *vertices, uint16 *indices)
{
width++;
height++;

int size = sizeof(CIwFVec2);
// Set up vertices
for(int y = 0; y < height; y++)
{
    int base = y * width;
    for(int x = 0; x < width; x++)
    {
        int index = base + x;
        CIwFVec2 *v = vertices + index;
        v->x = (float) x;
        v->y = (float) y;
        Debug::PrintDebug("%d: %f, %f", index, v->x, v->y);
    }
}

Debug::PrintDebug("-------------------------");

// Set up indices
int i = 0;
height--;
for(int y = 0; y < height; y++)
{
    int base = y * width;

    //indices[i++] = (uint16)base;
    for(int x = 0; x < width; x++)
    {
        indices[i++] = (uint16)(base + x);
        indices[i++] = (uint16)(base + width + x);
    }
    // add a degenerate triangle (except in a last row)
    if(y < height - 1)
    {
        indices[i++] = (uint16)((y + 1) * width + (width - 1));
        indices[i++] = (uint16)((y + 1) * width);
    }
}

for(int ind=0; ind < i; ind++)
    Debug::PrintDebug("%d ", indices[ind]);
}
于 2013-06-09T03:18:30.373 に答える
2

私は似たようなことをしていて、これを思いついた最初の2つの答えを使用しました(テスト済み、C#、XNA)

        // center x,z on origin
        float offset = worldSize / 2.0f, scale = worldSize / (float)vSize;

        // create local vertices
        VertexPositionColor[] vertices = new VertexPositionColor[vSize * vSize];

        for (uint z = 0; z < vSize; z++) {
            for (uint x = 0; x < vSize; x++) {
                uint index = x + (z * vSize);
                vertices[index].Position = new Vector3((scale*(float)x) - offset, 
                                                       heightValue, 
                                                       (scale*(float)z) - offset);
                vertices[index].Color = Color.White;
            }
        }

        // create local indices
        var indices = new System.Collections.Generic.List<IndexType>();

        for (int z = 0; z < vSize - 1; z++) {
            // degenerate index on non-first row
            if (z != 0) indices.Add((IndexType)(z * vSize));

            // main strip
            for (int x = 0; x < vSize; x++) {
                indices.Add((IndexType)(z * vSize + x));
                indices.Add((IndexType)((z + 1) * vSize + x));
            }

            // degenerate index on non-last row
            if (z != (vSize-2)) indices.Add((IndexType)((z + 1) * vSize + (vSize - 1)));
        }

これは簡単にc++に変換できindices、std::vectorを作成するだけです。

私のソリューションの注目すべき機能は次のとおりです。a)サブストリップごとに巻き取り順序を変更する必要はありません-2つのポイントを追加すると、2つの縮退した三角形が作成されるため、次のサブストリップの順序は正しいです。b)最初と最後のdg三角形の頂点を条件付きで追加する必要があります。

于 2011-09-12T18:27:45.017 に答える