頂点スキニング
	SAMPLE
		https://www.dropbox.com/s/v5gwxqgocrwjlmb/skinning.exe( 頂点スキニング )
		https://www.dropbox.com/s/wwjxxfaa2t5xcdm/spring.exe( 頂点スキニングを使ったバネモデル )
		App::onDraw() {
			float m0[16], m1[16];
			// 現在の骨の位置に移動する。
			glLoadIdentity();
			glTranslatef( 0, 50, 0 );
			// 回転する。
			glRotatef( m_timer, 0,0,1 );
			
			// 骨の位置を基準(Pivot)にして回転するため、逆行列をかけて原点に移動する。
			glTranslatef( 0, -50, 0 );
			glGetFloatv( GL_MODELVIEW_MATRIX, mb0 );
			// 2番目の骨も同じように計算			
			glLoadIdentity();
			glTranslatef( 100, 50, 0 );
			glRotatef( m_timer, 0,0,1 );
			glTranslatef( -100, -50, 0 );
			glGetFloatv( GL_MODELVIEW_MATRIX, mb1 );
			{
				CGparameter param;
			// 頂点シェーダで変形させるため、骨の行列をシェーダに渡す。
				float m[] = {
					m0[0], m0[4], m0[ 8], m0[12],
					m0[1], m0[5], m0[ 9], m0[13],
					m0[2], m0[6], m0[10], m0[14],
					m0[3], m0[7], m0[11], m0[15],
					m1[0], m1[4], m1[ 8], m1[12],
					m1[1], m1[5], m1[ 9], m1[13],
					m1[2], m1[6], m1[10], m1[14],
					m1[3], m1[7], m1[11], m1[15],
				};
			param = cgGetNamedParameter( shdV, "m");
			cgGLSetParameterArray4f( param, 0, 2*4, m );
			
			// モデルビュー, プロジェクションを渡す。
			glMatrixMode( GL_MODELVIEW_MATRIX );
			glLoadIdentity();
			convertCameraSpace();
			param = cgGetNamedParameter( shdV, "mvp");
			cgGLSetStateMatrixParameter( param,
																	 CG_GL_MODELVIEW_PROJECTION_MATRIX,
																	 CG_GL_MATRIX_IDENTITY
																	 );
			}
			// 描画する。( ウェイトの値は glNormal で指定しておく。 )
			glBegin( GL_TRIANGLE_STRIP );
			{
				glColor4f(1,1,1,1);
				for( int j=0; j<2*7; j++ ){
					// ウェイト値
					float w0 = 1 - 1/7.0f*(j/2);
					float w1 = 1 - w0;
					glNormal3f( w0, w1, 1 );
					float x = 2*(w1 - 0.5f) * 100;
					float y = 100 * (j%2);
					glVertex3f( x, y, 0 );
				} 
			}			
			glEnd();						
		}
		
		頂点シェーダで頂点を変形する
	float4x4 mtx0 = float4x4( m[0], m[1], m[2], m[3] );
	float4x4 mtx1 = float4x4( m[4], m[5], m[6], m[7] );
	// ウェイト
	float w0 = IN.nrm.x;
	float w1 = IN.nrm.y;
	// 変形
	float4 p = w0 * mul( mtx0, IN.pos ) + w1 * mul( mtx1, IN.pos );
	// モデルビュープロジェクション変換
	OUT.pos = mul( mvp, pt );
 CPUで変形する
		CPUで計算するには頂点座標を指定する( glVertex() )前に変換をしておく。
		float v[2*7*3];
		for( int j=0; j<2*7; j++ ){
			// ウェイト値
			float w0 = 1 - 1/7.0f*(j/2);
			float w1 = 1 - w0;
			float x = 2*(w1 - 0.5f) * 100;
			float y = 100 * (j%2);
			// 行列とベクトルの積
			multiMatrix( mb0, v0, v0 );
			multiMatrix( mb1, v1, v1 );
					
			// ウェイトをかけてブレンドする
			v[3*j+0] = w0*v0[0] + w1*v1[0];
			v[3*j+1] = w0*v0[1] + w1*v1[1];
			v[3*j+2] = 0;
		}
		glBegin( GL_TRIANGLE_STRIP );
		glColor4f(1,1,1,1);
		for( int j=0; j<2*7; j++ ){
			// 事前計算した頂点を指定する
			glVertex3fv( v + 3*j );
		}			
		glEnd();						
		行列とベクトルの積には glMultMatrix() を利用する。
		void multiMatrix( const float *m, float *v, float *vout ) {
			glMatrixMode( GL_MODELVIEW );
			glLoadMatrixf( m );
			float mt[16] = {
				v[0], v[1], v[2], 1, // 第1列をベクトル扱いにする。
				0, 0, 0, 0,          // 残りの3列は仮
				0, 0, 0, 0,
				0, 0, 0, 0,
				};
			// 右からかける
			glMultMatrixf( mt );  
			// 計算結果として行列同士の積の結果の第一列を取得する
			glGetFloatv(GL_MODELVIEW_MATRIX, mt );
			vout[0] = mt[0];  
			vout[1] = mt[1];
			vout[2] = mt[2];
		}
 頂点配列でウェイトを指定する
		頂点の属性としてウェイトを指定するには glVertexAttribPointer() を利用して
		汎用型の属性のひとつとして指定する。
		App::onInit() {
			glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer");
		}
		App::onDraw() {
				struct Vertex {
					float pos[3];
					float col[3];
					float weight[4];
				};
			 Vertex v[2*NR];
			 {
				 for( int i=0; i<2*NR; i++ ){
					 float w0 = 1 - 1.0f/(NR-1)*(i/2);
					 float w1 = 1 - w0;
					 float x = 2*(w1 - 0.5f) * 100;
					 float y = 100 * (i%2);
					 v[i].pos[0] = x;
					 v[i].pos[1] = y;
					 v[i].pos[2] = 0;
					 v[i].col[0] = 1;
					 v[i].col[1] = 0;
					 v[i].col[2] = 0;
					 v[i].weight[0] = w0;
				 } 
			 }
			glEnableClientState( GL_VERTEX_ARRAY );
			glEnableClientState( GL_COLOR_ARRAY );
			glEnableVertexAttribArray( ATTR1 );
			glVertexPointer( 3, GL_FLOAT, sizeof(Vertex),  v );
			glColorPointer ( 3, GL_FLOAT,  sizeof(Vertex), v[0].col );
			glVertexAttribPointer( ATTR1, 1, GL_FLOAT, false, sizeof(Vertex), v[0].weight );
			// シェーダを有効にする。
			cgGLEnableProfile( pfV );
			glDrawArrays( GL_TRIANGLE_STRIP, 0, m_nr*2 );
		}
		頂点シェーダではアプリケーションで指定した頂点インデックスからウェイトを取得する。
	 struct app {
		 float4 pos     : POSITION;
		 float4 weight  : ATTR1;
	 };
		
	float4x4 mtx0 = float4x4( m[0], m[1], m[2], m[3] );
	float4x4 mtx1 = float4x4( m[4], m[5], m[6], m[7] );
	// ウェイト
	float w0 = IN.weight[0]
	float w1 = 1 - w0;
	// 変形
	float4 p = w0 * mul( mtx0, IN.pos ) + w1 * mul( mtx1, IN.pos );
	// モデルビュープロジェクション変換
	OUT.pos = mul( mvp, p );