Name ARB_matrix_palette Name Strings GL_ARB_matrix_palette Contact Jon Paul Schelter (jschelte 'at' matrox.com) Status Complete. Approved by ARB on December 5, 2000. Version Date: 2004/04/02 Revision: 0.7 Number ARB Extension #16 Dependencies ARB_vertex_blend and OpenGL 1.0 are required. This extension is written against the ARB_vertex_blend extended OpenGL 1.2.1 Specification. Overview This extension extends the abilities of ARB_vertex_blend to include a palette of modelview matrices. The n vertex units use a palette of m modelview matrices. (Where n and m are constrained to implementation defined maxima.) Each vertex has a set of n indices into the palette, and a corresponding set of n weights. Matrix indices can be changed for each vertex (between Begin and End). When this extension is utilized, the enabled units transform each vertex by the modelview matrices specified by the vertices' respective indices. These results are subsequently scaled by the weights of the respective units and then summed to create the eyespace vertex. A similar procedure is followed for normals. Normals, however, are transformed by the inverse transpose of the modelview matrix. IP Status Unknown, but believed to be none. Issues Should the matrix palette be loaded by adding MODELVIEWm tokens for MatrixMode? No, this method is too difficult to extend to an arbitrary (implementation defined) size palette, and would imply having a 32 entry (minimum) stack per matrix. Should the Matrix palette be loaded with a new LoadMatrixPalette command? No, although this provides an easy way to support arbitrary palette sizes, the method loses the current (MultMatrix, Rotate, Translate, Scale..) matrix functionality. Matrices will be Loaded into the palette with current functions when MATRIX_MODE is MATRIX_PALETTE_ARB. The current palette index is set by an explicit command: CurrentPaletteMatrixARB(). Should the Matrix Palette have a stack? Not required, this wastes a lot of space. Define the min stack depth for the MATRIX_PALETTE_ARB MatrixMode to be 1. This alows some implementations to add a stack if desired. The stacks established in ARB_vertex_blend for MODELVIEW_MATRIXn are still present. Should the matrix palette be gettable? Yes, CurrentPaletteMatrixARB() and GetIntegerv(CURRENT_PALETTE_MATRIX_ARB, *data) define which matrix in the palette is returned by GetFloatv(MATRIX_PALETTE_ARB, *data). Should MatrixIndexARB be changed to imply LoadMatrix calls to the applicable MODELVIEW_MATRIXn stacks? No, the MODELVIEW_MATRIXn matrices are unused when MATRIX_PALETTE is enabled. Should there be a way to specify that the modelview matrices for two different vertex units are identical? Not explicitely, but indexing the matrix palette provides this functionality. (Both units will have the same matrix index.) Currently, the MATRIX_PALETTE_ARB enum is used to enable the extension, to set the Matrix Mode, and to get the current matrix. Is this confusing? Should more enums be added? No. New Procedures and Functions void CurrentPaletteMatrixARB(int index) void MatrixIndex{ubusui}vARB(int size, T *indices) void MatrixIndexPointerARB(int size, enum type, sizei stride, void *pointer) New Tokens Accepted by the parameters of GetFloatv, GetDoublev, and IsEnabled, by the parameter of MatrixMode, and by the parameters of Enable and Disable: MATRIX_PALETTE_ARB: 0x8840 Accepted by the parameters of GetIntegerv, GetFloatv, and GetDoublev: MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 MAX_PALETTE_MATRICES_ARB 0x8842 CURRENT_PALETTE_MATRIX_ARB 0x8843 Accepted by the parameters of EnableClientState and DisableClientState and by the parameter of IsEnabled: MATRIX_INDEX_ARRAY_ARB: 0x8844 Accepted by the parameter of GetFloatv: CURRENT_MATRIX_INDEX_ARB 0x8845 Accepted by the parameter of GetIntegerv: MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 Accepted by the parameter of GetPointerv: MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 Additions to Chapter 2 of the OpenGL 1.2.1 Specification (Operation) - (2.6, p. 12) Second paragraph changed to: "Each vertex is specified with two, three, or four coordinates. In addition, a current normal, current texture coordinates, current color, current matrix indices, and current weights may be used in processing each vertex. Normals are used by the GL in lighting calculations; the current normal is a three- dimensional vector that may be set by sending three coordinates that specify it. Texture coordinates determine how a texture image is mapped onto a primitive. Indices are used to select modelview matrices from the palette when blending is enabled. Weights are used as blending factors when vertex blending is enabled. One weight and one index exists for each enabled vertex blend unit. Vertex units are enabled with Enable, and disabled with Disable. Enabling or Disabling a vertex unit not supported in the implementation results in the error INVALID_OPERATION." - (2.6.3, p. 19) First paragraph changed to: "The only GL commands that are allowed within Begin/End pairs are the commands for specifying vertex coordinates, vertex color, normal coordinates, texture coordinates, matrix indices, and weights (Vertex, Color, Index, Normal, TexCoord, MatrixIndexARB, WeightARB), the ArrayElement command (see section 2.8), the EvalCoord and EvalPoint commands (see section 5.1), commands for specifying lighting material parameters (Material commands; see section 2.13.2), display list invocation commands (CallList and CallLists; see section 5.4), and the EdgeFlag command. Executing any other GL command between the execution of Begin and the corresponding execution of End results in the error INVALID_OPERATION. Executing Begin after Begin has already been executed but before an End is executed generates the INVALID_OPERATION error, as does executing End without a previous corresponding Begin." - (2.7, p. 20) Added after the third paragraph: "The current weights are set using void Weight{bsifd ubusui}vARB(int size, T *weights); the floating point values are assigned to the current weight vector. The first current weights are replaced with such that: CURRENT_WEIGHT_ARB[i] = [i] When WEIGHT_SUM_UNITY_ARB is enabled, -1 CURRENT_WEIGHT_ARB[] = 1 - SUM [i] i=0 otherwise the rest of the current weights are set to 0. If is greater than MAX_VERTEX_UNITS_ARB or if WEIGHTS_SUM_UNITY_ARB is enabled and equals MAX_VERTEX_UNITS_ARB, then the error INVALID_VALUE is generated. When the values are supplied as byte, short, or int, they are converted to floating-point values as indicated for the corresponting type in Table 2.6. The current matrix indices are set using void MatrixIndex{ubusui}vARB(int size, T *indices); The specified indices are set to the first Vertex Unit index values. indicates the count of matrix indices in the array. Note that vertex units which are disabled can still receive weights and indices." - (2.8, p. 21) First paragraph changed to read: "The vertex specification commands described in section 2.7 accept data in almost any format, but their use requires many command executions to specify even simple geometry. Vertex data may also be placed into arrays that are stored in the client's address space. Blocks of data in these arrays may then be used to specify multiple geometric primitives through the execution of a single GL command. The client may specify an implementation dependent set of arrays: one each to store edge flags, texture coordinates, colors, color indices, normals, and vertices, weights, and matrix indices. The commands void EdgeFlagPointer( sizei stride, void *pointer); void TexCoordPointer( int size, enum type, sizei stride, void *pointer ); void ColorPointer( int size, enum type, sizei stride, void *pointer ); void IndexPointer( enum type, sizei stride, void *pointer ); void NormalPointer( enum type, sizei stride, void *pointer ); void VertexPointer( int size, enum type, sizei stride, void *pointer ); void WeightPointerARB(int size, enum type, sizei stride, void *pointer) void MatrixIndexPointerARB(int size, enum type, sizei stride, void *pointer) describe the locations and organizations of these arrays. For each command, type specifies the data type of the values stored in the array. Because edge flags are always type boolean, EdgeFlagPointer has no type argument. Size, when present, indicates the number of values per vertex that are stored in the array. Because normals are always specified with three values, NormalPointer has no size argument. Likewise, because color indices, and edge flags are always specified with a single value, IndexPointer, and EdgeFlagPointer also have no size argument. Table 2.4 indicates the allowable values for size and type (when present). For type the values BYTE, SHORT, INT, FLOAT, and DOUBLE indicates types byte, short, int, float, and double, respectively; and the values UNSIGNED_BYTE, UNSIGNED_SHORT, and UNSIGNED_INT indicate types ubyte, ushort, and uint, respectively. The error INVALID_VALUE is generated if size is specified with a value other than that indicated in the table. For implementations supporting vertex blending, note that values for WeightPointerARB and MatrixIndexPointerARB must be less than the implementation defined value MAX_VERTEX_UNITS_ARB." - (2.8, p. 22) Change table 2.4 to read: Command Sizes Types ------- ----- ----- VertexPointer 2,3,4 short, int, float, double NormalPointer 3 byte, short, int, float, double ColorPointer 3,4 byte, ubyte, short, ushort, int, uint, float, double IndexPointer 1 ubyte, short, int, float, double TexCoordPointer 1,2,3,4 short, int, float, double EdgeFlagPointer 1 boolean WeightPointerARB 1..MAX_VERTEX byte, ubyte, short, _UNITS_ARB ushort, int, uint, float, double MatrixIndexPointerARB 1..MAX_VERTEX unsigned byte, unsigned _UNITS_ARB short, unsigned int - (2.8 p. 23) Change paragraph two to: "An individual array is enabled or disabled by calling one of void EnableClientState( enum array ); void DisableClientState( enum array ); with array set to EDGE_FLAG_ARRAY, TEXTURE_COORD_ARRAY, COLOR_ARRAY, INDEX_ARRAY, NORMAL_ARRAY, VERTEX_ARRAY, MATRIX_INDEX_ARRAY_ARB, or WEIGHT_ARRAY_ARB, for the edge flag, texture coordinate, color, color index, normal, vertex, matrix index, or weight array, respectively. " - (2.8 p. 23) Change paragraph three to: "The ith element of every enabled array is transferred to the GL by calling void ArrayElement( int i ); For each enabled array, it is as though the corresponding command from section 2.7 or 2.6.2 were called with a pointer to element i. For the vertex array, the corresponding command is Vertex[size][type]v, where size is one of [2,3,4], and type is one of [s,i,f,d], corresponding to array types short, int, float, and double respectively. The corresponding commands for the edge flag, texture coordinate, color, color index, normal, and weight arrays are EdgeFlagv, TexCoord[size][type]v, Color[size][type]v, Index[type]v, Normal[type]v, MatrixIndex[type]vARB, and Weight[type]vARB, respectively. If the vertex array is enabled, it is as though Vertex[size][type]v is executed last, after the executions of the other corresponding commands." - (2.10 p. 28) Edit to the last paragraph: "Figure 2.6 diagrams the sequence of transformations that are applied to vertices. The vertex coordinates that are presented to the GL are termed object coordinates. The model-view matrix is applied to these coordinates to yield eye coordinates. In implementations with vertex blending, all enabled modelview matrices are applied to these coordinates, and the weighted sum of the results are the eye coordinates. Then another matrix, called the projection matrix, is applied to eye coordinates to yield clip coordinates. A perspective division is carried out on clip coordinates to yield normalized device coordinates. A final viewport transformation is applied to convert these coordinates into window coordinates." - (2.10 p. 29) Edit to the second paragraph: "... the vertex's eye coordinates are found as: (xe) n-1 (xo) (ye) = SUM w_i * M_i * (yo) (ze) i=0 (zo) (we) (wo) where M_i is the palette matrix associated with the i'th Vertex unit: M_i = MatrixPalette[MatrixIndex[i]], if VERTEX_BLEND_ARB, MATRIX_PALETTE_ARB and VERTEX_UNIT_ARB are enabled, and M_i = MODELVIEW_MATRIX, otherwise. w_i is the Vertex's associated weight for vertex unit i: w_i = weight_i, if VERTEX_BLEND_ARB, MATRIX_PALETTE_ARB and VERTEX_UNIT_ARB are enabled, 1, if MATRIX_PALETTE_ARB is disabled, and, n = ACTIVE_VERTEX_UNITS_ARB." - (2.10.2 p. 31) Change the first paragraph to: "The projection matrix and model-view matrices are set with a variety of commands. The affected matrix is determined by the current matrix mode. The current matrix mode is set with void MatrixMode( enum mode ); which takes one of the pre-defined constants TEXTURE, MODELVIEW, COLOR, PROJECTION, MODELVIEWn_ARB, MATRIX_PALETTE_ARB. TEXTURE is described later in section 2.10.2, and COLOR is described in section 3.6.3. If the current matrix mode is MODELVIEW, the matrix operations apply to the model-view matrix; if PROJECTION, then they apply to the projection matrix. In implementations supporting ARB_matrix_palette, void CurrentPaletteMatrixARB(int index); defines which of the palette's matrices is affected by subsequent matrix operations when the current matrix mode is MATRIX_PALETTE_ARB. CurrentBlendMatrixARB generates the error INVALID_VALUE if the parameter is not between 0 and MAX_PALETTE_MATRICES_ARB. The CURRENT_PALETTE_MATRIX_ARB enum can be used to query the last value set by CurrentPaletteMatrixARB." - (2.10.2 p. 34) Change to the fourth paragraph: "The state required to implement transformations consists of a four-valued integer indicating the current matrix mode, a stack of at least two 4 x 4 matrices for each of COLOR, PROJECTION, and TEXTURE with associated stack pointers, a stack of at least 32 4 x 4 matrices with an associated stack pointer for MODELVIEW, and a set of MAX_PALETTE_MATRICES_ARB stacks of at least 1 4 x 4 matrices each for the matrix palette. Initially, there is only one matrix on each stack, and all matrices are set to the identity. The initial matrix mode is MODELVIEW. - (2.10.3 p. 35) Added after the second paragraph: "When vertex blending is enabled, the normal is transformed to eye space by: n-1 (nx' ny' nz') = (nx ny nz) Inv ( SUM w_i * Mu_i) i=0 Alternatively implementations may choose to transform the normal to eye-space by: n-1 (nx' ny' nz') = SUM w_i * (nx ny nz) Inv(Mu_i) i=0 where Mu_i is the upper leftmost 3x3 matrix taken from the modelview for vertex unit i (M_i), M_i = MatrixPalette[MatrixIndex[i]] if VERTEX_BLEND_ARB, MATRIX_PALETTE_ARB and VERTEX_UNIT_ARB are enabled, and M_i = MODELVIEW_MATRIX otherwise. weight_i is the vertex's associated weight for vertex unit i, w_i = weight_i and n = ACTIVE_VERTEX_UNITS_ARB" Additions to Chapter 3: None Additions to Chapter 4: None Additions to Chapter 5: None Additions to Chapter 6: None Additions to the GLX Specification In progress. Additions to the GLX Stream Protocol: Four new GL rendering commandsl are added. The following commands are sent to the server as part of a glXRender request: MatrixIndexubvARB 2 8+n+p rendering command length 2 4326 rendering command opcode 4 INT32 size 1*n CARD8 weights p pad(n) MatrixIndexusvARB 2 8+2*n rendering command length 2 4327 rendering command opcode 4 INT32 size 2*n CARD16 weights p pad(2*n) MatrixIndexuivARB 2 8+4*n rendering command length 2 4328 rendering command opcode 4 INT32 size 4*n CARD32 weights CurrentPaletteMatrixARB 2 8 rendering command length 2 4329 rendering command opcode 4 INT32 count Errors INVALID_VALUE is generated if the parameter for MatrixIndexARB or MatrixIndexPointerARB is greater than MAX_VERTEX_UNITS_ARB, or if WEIGHT_SUM_UNITY_ARB is enabled and is equal to MAX_VERTEX_UNITS_ARB. INVALID_VALUE is generated if the parameter to CurrentPaletteMatrixARB is greater than MAX_PALETTE_MATRICES_ARB or if is equal to zero. New State Modified State in Table 6.5 (p. 195): Initial Get Value Get Command Type Value Attribute Description --------- ----------- ---- ------- --------- ----------- CURRENT_MATRIX_INDEX_ARB GetIntegerv n*Z+ 0 current array of current matrix indices Modified State in Table 6.6 (p. 196): Initial Get Value Type Get Command Value Description Sec. Attribute --------- ---- ----------- ------- ----------- ---- --------- MATRIX_INDEX_ARRAY_ARB B IsEnabled False Matrix indices enable 2.8 vertex-array MATRIX_INDEX_ARRAY_SIZE_ARB Z+ GetIntegerv 0 Indices per element 2.8 vertex-array MATRIX_INDEX_ARRAY_TYPE_ARB Z_3 GetIntegerv UBYTE Type of indices 2.8 vertex-array MATRIX_INDEX_ARRAY_POINTER_ARB Y GetPointerv False Pointer to the Matrix 2.8 vertex-array indices array Modified state in Table 6.7 (p. 197) Transformation State: Initial Get Value Get Command Type Value Attribute Description --------- ----------- ---- --------- --------- ----------- MATRIX_PALETTE_ARB GetFloatv 2*x1*xM4 Identity - stack of current modelview matrix in the palette MATRIX_PALETTE_ARB IsEnabled B FALSE transform Enable for ARB_matrix_palette CURRENT_PALETTE_ GetIntegerv Z+ 0 transform index of current modelview matrix in the MATRIX_ARB palette, as set by CurrentPaletteMatrixARB() New Implementation Dependent State Modified state in Table 6.24 (p. 214) Implementation Dependant Values: Get Value Get Command Type Min Value Description --------- ----------- ---- --------- ----------- MAX_MATRIX_PALETTE_ GetIntegerv Z+ 1 Max matrix palette stack depth STACK_DEPTH_ARB Modified state in Table 6.25 (p. 215): Get Value Get Command Type Min Value Description --------- ----------- ---- --------- ----------- MAX_PALETTE_MATRICES_ARB GetIntegerv Z+ MAX_VERTEX_ Max size of the matrix palette UNITS_ARB Additions to Appendix A: None Revision History 2000/10/17 v 0.3 jschelte - added Usage example. 2000/11/09 v 0.4 jschelte - cleaned up some "issues". 2000/11/27 v 0.5 jschelte - closed last issue, fixed typo in Usage 2000/11/30 v 0.6 jschelte - replaced "blend matrices" with "palette matrices" - cleared up some confusion in the naming of the enum for the current indices and the current palette matrix for load/get. 2004/04/02 v 0.7 Thomas Roell - added GLX protocol Addendum: Using this extension. // Get the implementation's capabilities glGetIntegerv(MAX_VERTEX_UNITS_ARB, *max_blends); glGetIntegerv(MAX_PALETTE_MATRICES_ARB, *max_matrices); //validate that max_blends and max_matrices are sufficient here. // enable the units glEnable(VERTEX_UNIT_0_ARB); glEnable(VERTEX_UNIT_1_ARB); glEnable(VERTEX_UNIT_2_ARB); glEnable(VERTEX_UNIT_3_ARB); // Load the matrix Palette glMatrixMode(MATRIX_PALETTE_ARB); for (i=0; i