トップページ
ひらく | たたむ | ページトップ
↓マウスで反転選択した文字を検索
OpenGL
   
ページ内検索 ページ外検索
検索したい文字を入力して
ENTERを押すと移動します。
\n
[ トップページ ]
[ ____CommandPrompt ] [ ____JScript ] [ ____MySQL ] [ ____Cygwin ] [ ____Java ] [ ____Emacs ] [ ____Make ] [ ____Perl ] [ ____Python ] [ ____OpenGL ] [ ____C# ] [ ____StyleSheet ] [ ____C++ ] [ ____Winsock ] [ ____Thread ] [ ____VisualStudio ] [ ____C ] [ ____Win32API ] [ ____Lua ] [ ____PhotoShop ]
ヘッダ検索
___

■ 座標変換(VertexTransform)



  DESC
    プログラム内での関数名は次のように変換先の空間を指定する.

  WARNING
    スクリーンスペースでの原点は左下原点となるように指定する。


  WARNING 
    glFrustum, glOrtho をコールすると現在の行列に積算される。
    必ず glLoadIdentity() でクリアすること。
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();               // 必須
    glFrustum();
以下の方法では 現在の PROJECTION 行列に glFrustum() で生成した行列をかけることになる。
    glMatrixMode( GL_PROJECTION );
    glFrustum();
POINT 頂点を xyz を指定すると w 成分は 暗黙 で 1 になる POINT 転置する理由 行列は列行関係なく, 最後の 4 つに T がある  ( Memory 的には 4*3 がよいので, 転置する ) GL の仕様書で扱う行列は "列順" で表記される [ 0][ 4][ 8][12] [ 1][ 5][ 9][13] [ 2][ 6][10][14] [ 3][ 7][11][15] ベクトルは 列ベクトルとして扱う。 [ x ] [ y ] [ z ] [ w ] これは数式の表記の問題であって, 処理には関係ない。 POINT 守ることは次のことだけ 列順, 行順の混乱しないように, 1 次元配列で考えること。 LoadMatrix() をする際は, 最後の4成分 が移動成分である必要がある。
    X 軸  m[0] m[1] m[2]  Y 軸  m[4] m[5] m[6]  Z 軸  m[8] m[9] m[10]  原点  m[12] m[13] m[14]
例えば、Z 方向に -10 移動する行列は次のように指定する。
    float m[] = { 
            1, 0,   0, 0, 
            0, 1,   0, 0, 
            0, 0,   1, 0, 
            0, 0, -10, 0,   // 最後の4要素が移動成分
            };
    
    glLoadMatrixf( m );
    drawCube();

ProjectionSpace pos.w == ViewSpace pos.z
___

■ 行列積の順番

POINT 列順, 行順の表記に関係なく 行列変換の API は最後にコールされた順番に頂点が変換される。 T * R * v
    glLoadIdentity();
    glTranslatef( 1, 0, 0 );      // 横に1移動する
    glRotatef( 45, 0, 1, 0 );     // Y 軸に回転してから
    drawCube();
R * T * v
    glLoadIdentity();
    glRotatef( 45, 0, 1, 0 );     // Y 軸中心に 45 度を回転をする。
    glTranslatef( 1, 0, 0 );      // 横に1移動してから
    drawCube();
カメラ座標系への変換は最後にするので, コードとしては最初にかく。 C * T * R * v
    glLoadIdentity();

    convertCameraSpace();
    
    // 以下のコードで先ずはワールド空間に配置する。
    glTranslatef( 1, 0, 0 ); 
    glRotatef( 45, 0, 1, 0 );
    drawCube();
1次式の別表現( 定義 )が行列とベクトルの積
    x2 = a*x + b*y
    y2 = c*x + d*y
上の式を行列とベクトルの積として定義する
    V2 = ( a, b ) V
         ( c, d )
スケール変換を行列積であらわす
    x2 = sx*x
    y2 = sy*y
    V2 = ( sx,  0 ) V
         (  0, sy )
___

■ 行列とベクトルの積

行列とベクトルの積を OpenGL に計算させるには 行列同士の積を利用する。 2個目の行列の第一列をベクトルとみなして、 glMultMatrix() で計算する。
    glMatrixMode( GL_MODELVIEW );
    glLoadMatrixf( m );

    float mv[16] = {
      v[0], v[1], v[2], 0,
    };

    // ベクトルの代わりに
    glMultMatrixf( mv );
    // 結果をとりだす。
    glGetFloatv(GL_MODELVIEW_MATRIX, mv );

    // 結果
    v[0] = mv[0];
    v[1] = mv[1];
    v[2] = mv[2];
___

■ モデルビュー変換

POINT OpenGL にはカメラをここに置くという命令はない。 モデルのワールドでの位置はカメラが中心の座標系として指定する。 カメラの位置を原点とする右手座標系のため、カメラの正面に置くためには Z値がマイナスである必要がある。 行列の変換がわかりずらいならば、直接z値にマイナスの値を指定すれば良い。
    App::onDraw() {

      // 変換をしないように単位行列をロードしておく。
      glMatrixMode( GL_MODELVIEW );
      glLoadIdentity();

      
      // 直接マイナスの値を指定する。
      float z = -1.0f;
      
      glBegin( GL_TRIANGLES );
      glVertex3f( 0, 0, z );
      glVertex3f( 0, 1, z );
      glVertex3f( 1, 1, z );
      glEnd();

    }
移動行列を使って、カメラの正面に移動させる。


    App::onDraw() {
      glMatrixMode( GL_MODELVIEW );

      // 同一のモデルを複数の位置で描画する。
      glLoadIdentity();
      glTranslatef( 0, 0, -1.0f; );
      drawTriangle();

      glLoadIdentity();
      glTranslatef( 1.0f, 0, -1.0f; );
      drawTriangle();
    }

    void drawTriangle() {

      glBegin( GL_TRIANGLES );
      glVertex3f( 0, 0, 0 );
      glVertex3f( 0, 1, 0 );
      glVertex3f( 1, 1, 0 );
      glEnd();

    }
___

■ 回転とスケール

モデルを回転するには glRotate() を使う。 移動と回転の順番によって結果は異なる。 通常はモデルを回転してから、ワールド( カメラ原点 )の位置へ移動する( 置く )。
    [ 単位行列 ]  // glLoadIdentity() でカレントの行列は単位行列になる。

    [ 移動行列 ]  // glTranslatef()   で移動行列をかける  T * R
    [ 回転行列 ]  // glRotatef()      で回転行列となる。      R


    描画コールをした時点でこの行列によって頂点が変換される。
    行列操作のコマンドは現在の行列に対して右から掛けられる。
    先に回転 glRotate() をコールした後に glTranslate() をコールすると
    glRotate 後の座標系で移動することになる。
    ( または移動してから回転という操作になる。 )
    App::onDraw() {

      glMatrixMode( GL_MODELVIEW );
      glLoadIdentity();
      glTranslatef( 0, 0, -1 );     // Z=-1 の位置に置く。
      glRotatef( 45, 0, 1, 0 );     // Y軸を中心に45度回転してから
      
      drawTriangle();
    }

// DirectX の本では. --------------------------- 射影空間 ( ProjectionSpace ) ( z/w ) < -> [0:1] に正規化された NearPlane からの距離. ProjectionSpace の w は ViewSpace の z と等しい.
___

■ 投影変換

モデルを配置したら、カメラの位置を焦点として画面にモデルを投影させる。 この変換を投影変換といい、画面に投影することで遠くのものは小さく、 近くのものは大きく見えるようになる。 カメラでいうと画角の調整に相当する。 投影変換をするには glFrustum() を使う。 6つのパラメータで四角錐( 視錐台 )の形を定義する。 この範囲内のものが画面に描画される。 遠くのものほど, 小さく写すので x, y をカメラからの距離に応じて割る。
    X = x/z;
    Y = y/z;
z の値を変換する1次式
    Z = a*z + b
near のときに 0, far の時に 1 となるような係数を求める。
    0 = -n * a + b
    1 = -f * a + b
    // b を消す。
    1 = (n - f) * a

           1
    a = --------
          n-f

    // b = n*a だから
           n
    b = --------
          n-f
ハードウェアで透視変換をしてもらう。
    // 縦横比の調整
    X *= W/H;
    

    // 4 次元目に 範囲変換前の Z をセットしておく。これで XY が割られる。
    w = z;

    // Z の値は 0:1 の範囲に線形変換する
    Z =     

ハードに渡す頂点は次の条件をみたす必要がある。 自前で投影変換をした後の頂点は以下を満たす必要がある。
     X, Y は [ -1 : 1 ]    ( 範囲外は 画面に表示されない )
     w は xz(z) を割ってほしい値をいれる
     z は すでに変換すみなので, 先に z をかけておく
___

■ カメラを動かす

SAMPLE カメラを動かす 注視点を軸にカメラを回すには、 カメラのワールドの行列の逆行列を各モデルのワールド行列に掛ければよい。 というより、カメラから見た位置に変換するにはカメラの逆行列をかける。 例えば、回転だけで考えると カメラが右( X=1 の方向 )に90度向けた場合、 カメラを基準に見れば、すべてのモデルを左に−90度回したことと等しい。 移動に関しても同じで カメラを 右に10移動することと、すべてのモデルを左に−10移動させることは等しい。 以上のことからカメラのワールドの行列がわかれば、 その逆の変換をすればカメラから見た位置が決まる。 カメラのワールドでの位置と回転(向き)から逆の変換をする。
    void tranforrmCameraSpace( float tx, float ty, float tz, float rx, float ry ) {  

      // カメラ位置の逆の変換
      glTranslatef( -tx, -ty, -tz );

      // カメラの向きの逆の変換
      glRotatef( -rx, 1, 0, 0 );
      glRotatef( -ry, 0, 1, 0 );
    }
各モデルのワールドの位置をカメラから見た位置に変換する。

    glMatrixMode( GL_MODELVIEW );

    glLoadIdentity();
    glTranslatef( 0, 0, 10 );                  // モデルを 0, 0, 10 に置く
    tranforrmCameraSpace( 0, 10, 0, 30, 40 );  // 0, 10, 0 に置いたカメラから見た位置に変換する。
    drawCube();

    glLoadIdentity();
    glTranslatef( 1, 1, 1 );
    tranforrmCameraSpace( 0, 10, 0, 30, 40 );
    drawCube();

___

■ 行列の結果を取得する

行列の現在の値を取得するには glGet() で取得する。 POINT glTranslate はそのときの座標系の Local 方向へ移動する 今 移動 [Xx][Yx][Zx][Tx] [Xx][Yx][Zx][Tx] [Xx][Yx][Zx][Ty] [Xx][Yx][Zx][Ty] [Xx][Yx][Zx][Tz] [Xx][Yx][Zx][Tz] [ 0][ 0][ 0][ 1] [ 0][ 0][ 0][ 1] // 今の座標系のうち, X 方向へ寄与する量 + 元の X 位置 X = Xx * Tx + Yx * Ty + Zx * Tz + Tx( 元の位置 ) 結果をチェック

      glMatrixMode( GL_MODELVIEW );
      glLoadIdentity();
      glTranslatef( 1, 2, 3 );

      float m[16];
      glGetFloatv( GL_MODELVIEW_MATRIX, m );

      print( m );

      1.000000 0.000000 0.000000 1.000000
      0.000000 1.000000 0.000000 2.000000
      0.000000 0.000000 1.000000 3.000000
      0.000000 0.000000 0.000000 1.000000   // Translation に 1, 2, 3


0.707107 0.707107 0.000000 0.000000
-0.707107 0.707107 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 0.000000 1.000000

      glLoadIdentity();
      glRotatef( 45, 0, 0, 1 );


0.707107 0.707107 0.000000 0.000000
-0.707107 0.707107 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.707107 0.707107 0.000000 1.000000

      // 45 度回転して, そのときの X 軸方向{ 0.707107 0.707107, 0 }へ 1 の長さ移動
      glLoadIdentity();
      glRotatef( 45, 0, 0, 1 );
      glTranslatef( 1, 0, 0 );


0.707107 0.707107 0.000000 0.000000
-0.707107 0.707107 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
1.000000 0.000000 0.000000 1.000000

      // 移動した場所で回転
      glLoadIdentity();
      glTranslatef( 1, 0, 0 );
      glRotatef( 45, 0, 0, 1 );

回転と同じく Scale の影響もうける

      glMatrixMode( GL_MODELVIEW );
      glLoadIdentity();

      glScalef( 0.5, 0.5f, 0.5f );
      glTranslatef( 1, 0, 0 );

      0.500000 0.000000 0.000000 0.000000
      0.000000 0.500000 0.000000 0.000000
      0.000000 0.000000 0.500000 0.000000
      0.500000 0.000000 0.000000 1.000000

I * MT * MR
___

■ glMatrixMode

SYNTAX glMatrixMode DESC 行列操作をする行列スタックを選択する Texture Matrix は Texture Unit ごとにある。 TIP GL_TEXTURE の場合は, 操作するスタックは glActiveTexture() で選択している Unit になる DEFAULT 単位行列 ERROR GL_STACK_UNDERFLOW GL_STACK_OVERFLOW
    // UNIT 1 を選択
    glActiveTexture( GL_TEXTURE1 );

    // UNIT 1 の Texture Matrix を設定
    //  以後, Matrix 操作は この Stack が対象
    glMatrixMode( GL_TEXTURE );
    glLoadIdentity();
    glTranslatef( 1, 0, 0 );


    // ModelView Stack へ切り替え
    glMatrixMode( GL_MODELVIEW );



___

■ glMultMatrix

SYNTAX glMultMatrixf( const GLfloat *m ) DESC スタック最上位の行列に右からかける カレントの行列を C とすると
    C * v
glMultMatrix( M ) をコールすると, M を右から掛けることになる。
    C * M * v
___

■ glLoadMatrix

SYNTAX void glLoadMatrixf( const GLfloat *m); DESC 指定した行列に置き換える。 m は列優先の行列。
    m[0] m[4] m[ 8] m[12]   v[0]
    m[1] m[5] m[ 9] m[13]   v[1]
    m[2] m[6] m[10] m[14]   v[2]
    m[3] m[7] m[11] m[15]   v[3]
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glTranslatef( 1, 0, 0 );
    glTranslatef( 1, 0, 0 );   // この時点で x = 2 の行列

    float m[16] = {0};
    glLoadMatrixf(m);          // これをコールした時点で0行列
___

■ glRotate

SYNTAX glRotatef( float angle, float x, float y, float z ); DESC x, y, z で指定した軸を中心に r 度回転する行列を右からかける。 角度の単位はラジアンではなく、360度での設定。
___

■ glTranslate

DESC x, y, z 軸にそった平行移動をする行列を作成して 右からかける 次の行列を glMultMatrix() することと同じ
    1 0 0 x
    0 1 0 y
    0 0 1 z
    0 0 0 1
次の2つは同じ
    glTranslatef( 1, 2, 3 );

    float m[] = { 
        1, 0, 0, 0, 
        0, 1, 0, 0, 
        0, 0, 1, 0,
        1, 2, 3, 1,
    }
    glMultMatrixf( m );
___

■ glScale

DESC x, y, z 軸にそって拡大縮小をする行列を作成して 右からかける
___

■ 視点座標の定義

DESC GL の視点座標の定義は以下のもの。
     視点は原点 { 0, 0, 0 }

     右手座標系
       視線の方向( 正面 )は Z 軸のマイナスの方向
       +Y が上
       +X が右
POINT カメラに写るためにはモデルビュー変換後の Z 座標が - であることが必須になる。
___

■ glPushMatrix.glPopMatrix

DESC [ cur Mtx を cp ] したものを最上段に配置 POINT MtxTex は Unit ごとに設定する. ( 選択は glActiveTexture で ) 自前で mtx 計算をする場合は不要な処理のはず. 余計な Error を防ぐために使用を禁止する. DEFAULT Stk ごとに 1 つの MtxUnit をふくむ. EX GL_MAX_( MODELVIEW | PROJECTION | TEXTURE )_STACK_DEPTH
___

■ 座標変換 pipeline

次の流れで頂点座標がスクリーン上のピクセル位置まで変換される
    [ オブジェクト座標 ]
           |
      モデリング( ワールド )変換
           |
    [ ワールド座標  ]
           |
        視野変換( カメラから見た位置へ変換  )
           |
    [  視点座標  ]
           |
       投影変換 ( 投影面に写像する )
           |
    [  クリップ空間  ]
           |
       w 除算
           |
  [ NormalizedDeviceCoordinate ]
           |
      ビューポート変換( 印画紙に引き伸ばす )
           |
    [ スクリーン座標(画面) ]


___

■ クリップ座標

ModelViewProjection 行列の結果の座標 透視除算( w で割る ) ( 透視投影のみ有効 四角い箱にする ) 投影行列が w の値をきめる 平行投影なら w = 1 になる Clip 座標の点は 以下のようにある -w < [x,y,z] < w Frustum の外の Primitive はこの時点で除去 部分的にでる Primitive は, 範囲内だけが Rasterize される
___

■ 正規化された デバイス座標

-1.0 < [x,y,z] < 1.0 処理 透視除算 w 成分で x, y, z 成分をわる これによって 遠いものが 小さく見えるように変換される x : Window の SubPixel y : Window の SubPixel
___

■ window 座標

SAMPLE 複数のビューポート 処理 viewport 変換 ( WARNING, x, y だけでなく z も写像される ) 変換された z 値は DepthBuffer にはいり、デプステストで使われる。 DESC 左下原点 | | | | ----------------------------- ( [0,0] - [x,y] , Z: depth buf [0:1] ( 正規化された Depth 値 ) 0 : DepthBuffer の前面 1 : DepthBuffer の背面 WARNING: x,y,z は浮動小数点でもつ ラスタライズのため )
___

■ glViewport

SYNTAX void glViewport( GLInt x, y, // mapping 先の 原点位置 ( 負数も指定できる ) GLInt w, h, // 幅, 高さ ) DESC 最終的に写像される矩形領域を定義する。 x, y, w, h は Window 左下を原点とするスクリーン座標 DEFAULT 正規化 Device 座標を Window Size 全体に写像する。 Window Size が変更されないなら指定は不要 ^-------------------- | | H|------------ | | | | | | | --------------------> 0,0 W Normalized Device Coordinate -------- | | | | | | -------- メタファは印画紙 VertexTransform 後の 値は Film WARNING 指定した Buffer ( Color | Depth | Stencil )全体をクリアする 一部分ではない
    // Viewport 変換もステートのひとつなので
    // 好きなタイミングで変更できる

    float W = 1024;
    float H = 768;

    // 左半分 に表示
    glViewport( 0,  0, W, H );
    drawScene();

    // 右半分 に表示
    glViewport( 0, W/2, W, H );
    drawScene();

___

■ glFrustum

SYNTAX glFrustum( float l, float r, float b, float t, float n, float f // 視点からクリップ面までの距離 ( 正の値 ) ); DESC 投影変換( 遠くのものを小さく変換する )行列を作成してカレントの行列に掛ける。
    // 透視変換行列を指定する。
    glMatrixMode( GL_PROJECTION );

  WARNING
    // 乗算するので 初期化 しとく
  glLoadIdentity();

    // 通常は左右対称の投影するため, 
    // left   = -right
    // bottom = -top   の関係が成り立つ。

    さらに画面の縦横比(アスペクト)に合わせることで、ウィンドウ変換した際に歪まないようにする。

    そのため画面サイズ(アスペクト)と画角から r, l, t, b は決まる。

    n, f はニアクリップとファークリップの位置を指定する。
    n より手前と f より奥はすべてクリップされて表示されない。

    画角と n, f のクリップ面の距離から指定すると直感的にわかりやすい。
    
    

  WARNING
    n, f の値はデプスバッファの精度に影響を与えるためシーンのサイズに合わせる必要がある。
    n を小さくして、 f を大きくすれば良いというものではない。
    
    f/n  の値を大きくすればするほど、精度が落ちる。

    n を 0 に近づけると、 f/n は無限大に発散する。

    log2(f/n) bit の精度が失われる。


  float l = -0.75;
  float r = -l;
  float b = -l * h/w;
  float t = -b;
  glFrustum( l, r, b, t, 1, 1000.0f );

___

■ glOrtho

SYNTAX void glOrtho( GLDouble l, GLDouble r, GLDouble b, GLDouble t, GLDouble n, GLDouble f // カメラからの距離 ) DESC 平行な視体積の行列を作成する。 near , far は [ 正負0 ] 可能 視体積 の外の obj はクリップされる メタファーとしては, カメラから見た世界での BOX を定義 WARNING 行列スタック上で累積するので, glLoadIdentity(); 忘れないこと ERROR GL_INVALID_VALUE( l = r, b = t, n = f ) TIP 投影行列が ClipSpace へ変換する. ( Ortho の場合は常に w = 1.0f ) WARNING ortho proj mtx 内に obj が内包されていない カメラ座標系( カメラから見た )の点がボックス領域に入る必要がある
    glOrtho( 0, 800, 600, 0, 0, 1 );

    ERROR
      pnt A { -10.0f, 0.0f, 0.0f }
    OK
      pnt B { 10.0f, 10.0f, 0.0f }
___

■ gluPerspective

SYNTAX gluPerspective( GLDouble fovy, // 縦( Y )方向の角度 ( 単位 degree ) GLDouble aspect, // 縦横比 ( w/h ) GLDouble near, far // 視点からクリップ面までの距離 ( 正の値 ) ) DESC view frustum を定義する。 アスペクトはビューポートを同じ比率にするのが一般的。 glFrustum などと同じく、カレントの行列に乗算される。 上書きする場合は, glLoadIdentity() を先に呼ぶこと。 fovy/2 とあるので、縦方向半分ではなく, 縦全体の角度指定になる。

      /
     /
    /
  --------------------------  120 度の指定では縦方向はこの範囲が見れる。
    \
     \
      \
この計算と同じになる。

    float ang = angle/180.0f * 3.14f;
    float t = tan(ang/2) * n;
    float b = -t;

    float r = t * ratio;
    float l = -r;

    glFrustum( l, r, b, t, n, f );
___

■ gluLookAt

SYNTAX void gluLookAt( GLdouble eyeX, eyeY, eyeZ, GLdouble centerX, centerY, centerZ, GLdouble upX, GLdouble upY, GLdouble upZ); DESC カメラ座標系への変換行列を作成する。( カメラのワールド行列ではない ) この変換により、 注視点は Z軸のマイナスの値に, 視点は原点は移動する。 現在の行列を積算するかどうかは書いてないが, 行列を取得してみればわかる。 UPベクターは 視線ベクトルと平行になってはいけない。
___

■ DepthBuffer

非線形 ( /w ) 指数関数的 次の比率が 目安 16bit Depth Buffer -> far / near = 50 24bit Depth Buffer -> far / near = 10000
___

■ ProjectionSpace

DESC ProjectionSpace( 射影空間 ) とその変換について MEMO DirectX [-1,-1,0] < -> [1,1,1] の 箱に変換される W 除算前は ↑の範囲にはない OpenGL [-1,-1,-1] < -> [1,1,1] の 箱に変換される W 除算前は ↑の範囲にはない。 POINT 投影変換 した後の pos.w は ViewSpace における奥行値になる これは Projection Matrix の 3 行目から明らか
              (vpos.x)
              (vpos.y)
              (vpos.z)
      0,0-1,0  (vpos.w)  = -vpos.z  ( カメラの奥行 )

    ということは w 除算とは 奥行で xyz を割ること

    , VertexShader で出力する 位置( pos )情報は
    w 除算してない

    -> どうやら Pipeline の中で行われる



TIP ShadowMap で利用する Depth 値の算出方法

    // [ ModelSpace ] ---> [ ClipSpace ]
    float4 pos = mul( mvp, IN.pos );

    // POINT
    //  ここでは まだ w 除算しない
    //  理由は 線形補間では 補間式が異なるから
    //  この違いは shadowmap, priority shadowmap で明らかになる
    //
    OUT.depth = pos.zzzw;
    return OUT;


    // Fragment Shader で w 除算すること


    // POINT
    //    ここで [0:1] の範囲に おさまる
    //    逆に w 除算をする前は [0:1]  におさまってない
    //
    float4 col = IN.depth.z / IN.depth/w;



TIP 画面いっぱいに Quad をかく指定
    // でも考えてみると Z の指定が これでいい ?

    // 変換はしない
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    // W = 1 にすること
    glVertex3f(-1, -1, -0.3f, 1 );
    glVertex3f( 1, -1, -0.3f, 1 );
    glVertex3f( 1,  1, -0.3f, 1 );
    glVertex3f(-1,  1, -0.3f, 1 );
___

■ 行列操作

POINT 行列操作 の Command は 行列スタックの最上部につまれ右から乗算される
      // Code で記述した順番と反対になる
      [  glTranslate ]
      [  glRotate    ]

      {
        glRotate();    // 移動した後に回転
        glTranslate(); // 先に移動処理がかかる

        // 描画
        draw();
      }

      // 数式でかくと
      R * T * v

      // 言葉で言えば
      移動してから, 原点( 0,0,0 )を中心に回転







金利比較.COM
NINJAIDX 9