簡単シリンダー描画 CreateIndexCylinder


やあみんな。元気にしてたかな。おじさんだよ。
今日はインデックス形式で表記されたシリンダーモデルを簡単に作成できる便利関数を紹介するぞ。さまざまなCG開発プラットホームで、プログラム的にシリンダー形状をちょっと出してみたいなんていうことはよくあるね。でもシリンダーの形状をいちいちモデリングするのも面倒だ。どこかから持ってくるのが速いがわざわざデータとして読み込んだりするのも面倒だ、何か簡単にプログラム的にシリンダー形状をちゃちゃっと作成できないだろうか。
そんなニーズにお答えするのが今回の、CreateIndexCylinderだ。プラットホームフリーな純粋C++コードだけどglmだけは使わせてくれ。glmって何っていう人は、、そうだね帰ってくれ。いますぐ帰ってくれ。
まああれだな、これは過去日記のCreateIndexCubeと流れを同じくするインデックス形式簡易形状モデリングパラダイムの1つだ。コードは以下のようになったよ。

using namespace glm;
void CreateIndexCylinder( const float radii, const float height,
                         const int num_arc_resolution,
                         vector< int >* indices, vector< vec3 >* poslist )
{
    auto& il = indices;
    auto& pl = poslist;
    // シリンダー頂点を発生
    const float uni = 2*M_PI/(float)num_arc_resolution;
    for( int i=0; i<num_arc_resolution; ++i )
    {
        const float x = radii * cos( uni*i );
        const float z = radii * sin( uni*i );
        pl->push_back( vec3( x, .5*height, -z ) );
        pl->push_back( vec3( x, -.5*height, -z ) );
    }// i
    pl->push_back( vec3( 0, .5*height, 0 ) ); // top polar vtx
    pl->push_back( vec3( 0, -.5*height, 0 ) ); // bottom polar vtx
    // シリンダー面として、三角ポリゴンを紡ぐ
    vector< int > top, side, bottom;
    {
        auto& n = num_arc_resolution;
        // draw faces at the top in triangle_fan fashion.
        top.push_back( pl->size()-2 );
        for( int i=0; i<n; ++i )
            top.push_back( 2*i );
        top.push_back( 0 );
        // draw faces at the bottom in triangle_fan fashion.
        for( int i=0; i<n; ++i )
            bottom.push_back( 2*i+1 );
        bottom.push_back( 1 );
        bottom.push_back( pl->size()-1 );
        std::reverse( bottom.begin(), bottom.end() );
        // draw faces at the side in triangle_strip fashion.
        for( int i=0; i<2*n; ++i )
            side.push_back( i );
        side.push_back( 0 );
        side.push_back( 1 );
    }
    DecodeTriangleFanIndex( top.size(), top, il );
    DecodeTriangleStripIndex( side.size(), side, il );
    DecodeTriangleFanIndex( bottom.size(), bottom, il );
    return;
}

これは描画したいシリンダーの半径、高さ、円周の構成頂点数さえ与えてやれば、一瞬にしてそれを描画するための、頂点座標配列と、それを参照する、ポリゴン定義インデックス列を返してくれるというスグレモノだ。
以下は使用例になるぞ。

        vector< int > indices;
        vector< vec3 > poslist;
        {
            const float radii = .015;
            const float height = .015;
            const int num_res = 7;
            CreateIndexCylinder( radii, height, num_res, &indices, &poslist );
        }

おっと、DecodeTriangleFanIndex や DecodeTriangleStripIndexについては、これもまた超便利なやつらなんだけどこいつらに関しては2009年のこちらの日記→←を参照してほしい。
じゃ今日はこの辺で失礼するぞ。雪積もらなきゃいいな!じゃっ!