扩展:
GL_ARB_matrix_palette
GL_ARB_vertex_blend
顶点混合函数:
V = V*Mat[0]*Weight[1] + V*Mat[1]*Weight[1] + … + V*Mat[n]*Weight[n]
OpenGL增加了前面两个ARB扩展以支持矩阵调色板合顶点混合,这两项功能是硬件实现骨骼动画的基础。首先要用glEnbale( GL_MATRIX_PALETTE_ARB )和glEnable( GL_VERTEX_BLEND_ARB )激活这两项功能,然后使用glMatrixMode( GL_MATRIX_PALETTE_ARB )将当前矩阵切换成矩阵调色板。
在激活矩阵调色板之后,原来的GL_MODELVIEW(包括GL_MODELVIEWn)都不再起作用,顶点混合结果是在摄像机空间(世界坐标系)中的。但是一般我们的骨骼变换矩阵都是基于本地空间的,因此在绘制之前还要做点小动作。
矩阵调色板的大小由不同的实现决定,用glGetIntegerv( GL_MAX_PALETTE_MATRICES_ARB , &I )可以获得调色板大小。矩阵调色板栈大小至少为1,matrix_palette_arb扩展说明上说该栈基本上不需要更大,而且更大的栈也浪费空间,具体栈大小可以通过glGetIntergerv( GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB , &I )获得。
其他的懒得说,直接看下面的例子吧(说明上抄的):
glEnable( GL_MATRIX_PALETTE_ARB );
glEnable( GL_VERTEX_BLEND_ARB );
// 获得顶点单元数量和矩阵调色板大小。顶点单元数量即一个顶点最多能用多少个骨骼
glGetIntegerv(MAX_VERTEX_UNITS_ARB, *max_blends);
glGetIntegerv(MAX_PALETTE_MATRICES_ARB, *max_matrices);
// 激活0-3顶点单元
glEnable(VERTEX_UNIT_0_ARB);
glEnable(VERTEX_UNIT_1_ARB);
glEnable(VERTEX_UNIT_2_ARB);
glEnable(VERTEX_UNIT_3_ARB);
// 保存视图变换矩阵(摄像机变换)
Float mv[16];
glGetFloatv( GL_MODELVIEW );
// 加载矩阵调色板
glMatrixMode(MATRIX_PALETTE_ARB);
for (i=0; i<palette_size; i++)
{
glCurrentPaletteMatrix(i);// 选择调色板中的当前矩阵
glLoadMatrix( mv );
glMultiMatrix(bone_mat[i]);
}
// 顶点数组、纹理坐标数组等数组分开来的做法
// 激活数组状态
glEnableClientState(VERTEX_ARRAY);
glEnableClientState(NORMAL_ARRAY);
glEnableClientState(COLOR_ARRAY);
glEnableClientState(TEXTURE_COORD_ARRAY);
glEnableClientState(WEIGHT_ARRAY_ARB);
glEnableClientState(MATRIX_INDEX_ARRAY_ARB);
glVertexPointer(3, FLOAT, 3, vertices);
glNormalPointer(FLOAT, 3, normals);
glColorPointer(4, UNSIGNED_BYTE, 4, colors);
glTexCoordPointer(4, FLOAT, 4, texcoords);
glWeightPointerARB(4, FLOAT, 4, weights);
glMatrixIndexPointerARB(4, UNSIGNED_BYTE, 4, indices);
// 绘制三角形
glDrawArrays(TRIANGLES, 0, vert_array_size);
// 绘图数据合在一起的做法(有点像DX中的FVF
typdef struct st_interleaved_vertex {
FLOAT position[4];
FLOAT weights[4];
UNSIGNED_BYTE indices[4];
FLOAT normal[3];
FLOAT color[4];
FLOAT texcoord[4];
} interleaved_vertex;
interleaved_vertex vertices[NUM_VERTS];
// the rest as above, except the Array Pointer definition:
int stride = sizeof(interleaved_vertex);
glVertexPointer( 3, FLOAT, stride, &(vertices[0].position) );
glNormalPointer( FLOAT, stride, &(vertices[0].normal) );
glColorPointer( 4, UNSIGNED_BYTE, stride, &(vertices[0].color) );
glTexCoordPointer( 4, FLOAT, stride, &(vertices[0].texcoords) );
glWeightPointerARB( 4, FLOAT, stride, &(vertices[0].weights) );
glMatrixIndexPointerARB( 4, UNSIGNED_BYTE, stride,
&(vertices[0].indices) );