1 2Name 3 4 EXT_vertex_weighting 5 6Name Strings 7 8 GL_EXT_vertex_weighting 9 10Contact 11 12 Mark J. Kilgard, NVIDIA Corporation (mjk 'at' nvidia.com) 13 14Notice 15 16 Copyright NVIDIA Corporation, 1999, 2000. 17 18Status 19 20 Discontinued. 21 22 NVIDIA no longer supports this extension in driver updates 23 after November 2002. Instead, use either ARB_vertex_program & 24 NV_vertex_program. 25 26Version 27 28 NVIDIA Date: January 3, 2003 29 $Date$ $Revision$ 30 31Number 32 33 188 34 35Dependencies 36 37 None 38 39 Written based on the wording of the OpenGL 1.2 specification but not 40 dependent on it. 41 42Overview 43 44 The intent of this extension is to provide a means for blending 45 geometry based on two slightly differing modelview matrices. 46 The blending is based on a vertex weighting that can change on a 47 per-vertex basis. This provides a primitive form of skinning. 48 49 A second modelview matrix transform is introduced. When vertex 50 weighting is enabled, the incoming vertex object coordinates are 51 transformed by both the primary and secondary modelview matrices; 52 likewise, the incoming normal coordinates are transformed by the 53 inverses of both the primary and secondary modelview matrices. 54 The resulting two position coordinates and two normal coordinates 55 are blended based on the per-vertex vertex weight and then combined 56 by addition. The transformed, weighted, and combined vertex position 57 and normal are then used by OpenGL as the eye-space position and 58 normal for lighting, texture coordinate, generation, clipping, 59 and further vertex transformation. 60 61Issues 62 63 Should the extension be written to extend to more than two vertex 64 weights and modelview matrices? 65 66 RESOLUTION: NO. Supports only one vertex weight and two modelview 67 matrices. If more than two is useful, that can be handled with 68 another extension. 69 70 Should the weighting factor be GLclampf instead of GLfloat? 71 72 RESOLUTION: GLfloat. Though the value of a weighting factors 73 outside the range of zero to one (and even weights that do not add 74 to one) is dubious, there is no reason to limit the implementation 75 to values between zero and one. 76 77 Should the weights and modelview matrices be labeled 1 & 2 or 0 & 1? 78 79 RESOLUTION: 0 & 1. This is consistent with the way lights and 80 texture units are named in OpenGL. Make GL_MODELVIEW0_EXT 81 be an alias for GL_MODELVIEW. Note that the GL_MODELVIEW0_EXT+1 82 will not be GL_MODELVIEW1_EXT as is the case with GL_LIGHT0 and 83 GL_LIGHT1. 84 85 Should there be a way to simultaneously Rotate, Translate, Scale, 86 LoadMatrix, MultMatrix, etc. the two modelview matrices together? 87 88 RESOLUTION: NO. The application must use MatrixMode and repeated 89 calls to keep the matrices in sync if desired. 90 91 Should the secondary modelview matrix stack be as deep as the primary 92 matrix stack or can they be different sizes? 93 94 RESOLUTION: Must be the SAME size. This wastes a lot of memory 95 that will be probably never be used (the modelview matrix stack 96 must have at least 32 entries), but memory is cheap. 97 98 The value returned by MAX_MODELVIEW_STACK_DEPTH applies to both 99 modelview matrices. 100 101 Should there be any vertex array support for vertex weights. 102 103 RESOLUTION: YES. 104 105 Should we have a VertexWeight2fEXT that takes has two weight values? 106 107 RESOLUTION: NO. The weights are always vw and 1-vw. 108 109 What is the "correct" way to blend matrices, particularly when wo is 110 not one or the modelview matrix is projective? 111 112 RESOLUTION: While it may not be 100% correct, the extension blends 113 the vertices based on transforming the object coordinates by 114 both M0 and M1, but the resulting w coordinate comes from simply 115 transforming the object coordinates by M0 and extracting the w. 116 117 Another option would be to simply blend the two sets of eye 118 coordinates without any special handling of w. This is harder. 119 120 Another option would be to divide by w before blending the two 121 sets of eye coordinates. This is awkward because if the weight 122 is 1.0 with vertex weighting enabled, the result is not the 123 same as disabling vertex weighting since EYE_LINEAR texgen 124 is based of of the non-perspective corrected eye coordinates. 125 126 As specified, the normal weighting and combination is performed on 127 unnormalized normals. Would the math work better if the normals 128 were normalized before weighting and combining? 129 130 RESOLUTION: Vertex weighting of normals is after the 131 GL_RESCALE_NORMAL step and before the GL_NORMALIZE step. 132 133 As specified, feedback and selection should apply vertex weighting 134 if enabled. Yuck, that would mean that we need software code for 135 vertex weighting. 136 137 RESOLUTION: YES, it should work with feedback and selection. 138 139 Sometimes it would be useful to mirror changes in both modelview 140 matrices. For example, the viewing transforms are likely to be 141 different, just the final modeling transforms would be different. 142 Should there be an API support for mirroring transformations into 143 both matrices? 144 145 RESOLUTION: NO. Such support is likely to complicate the 146 matrix management in the OpenGL. Applications can do a 147 Get matrix from modelview0 and then a LoadMatrix into modelview1 148 manually if they need to mirror things. 149 150 I also worry that if we had a mirrored matrix mode, it would 151 double the transform concatenation work if used naively. 152 153 Many of the changes to the two modelview matrices will be the same. 154 For example, the initial view transform loaded into each will be the 155 same. Should there be a way to "mirror" changes to both modelview 156 matrices? 157 158 RESOLUTION: NO. Mirroring matrix changes would complicate the 159 driver's management of matrices. Also, I am worried that naive 160 users would mirror all transforms and lead to lots of redundant 161 matrix concatenations. The most efficient way to handle the 162 slight differences between the modelview matrices is simply 163 to GetFloat the primary matrix, LoadMatrix the values in the 164 secondary modelview matrix, and then perform the "extra" transform 165 to the secondary modelview matrix. 166 167 Ideally, a glCopyMatrix(GLenum src, GLenum dst) type OpenGL 168 command could make this more efficient. There are similiar cases 169 where you want the modelview matrix mirrored in the texture matrix. 170 This is not the extension to solve this minor problem. 171 172 The post-vertex weighting normal is unlikely to be normalized. 173 Should this extension automatically enable normalization? 174 175 RESOLUTION: NO. Normalization should operate as specified. 176 The user is responsible for enabling GL_RESCALE_NORMAL or 177 GL_NORMALIZE as needed. 178 179 You could imagine cases where the application only sent 180 vertex weights of either zero or one and pre-normalized normals 181 so that GL_NORMALIZE would not strictly be required. 182 183 Note that the vertex weighting of transformed normals occurs 184 BEFORE normalize and AFTER rescaling. See the issue below for 185 why this can make a difference. 186 187 How does vertex weighting interact with OpenGL 1.2's GL_RESCALE_NORMAL 188 enable? 189 190 RESOLUTION: Vertex weighting of transformed normals occurs 191 BEFORE normalize and AFTER rescaling. 192 193 OpenGL 1.2 permits normal rescaling to behave just like normalize 194 and because normalize immediately follows rescaling, enabling 195 rescaling can be implementied by simply always enabling normalize. 196 197 Vertex weighting changes this. If one or both of the modelview 198 matrices has a non-uniform scale, it may be useful to enable 199 rescaling and normalize and this operates differently than 200 simply enabling normalize. The difference is that rescaling 201 occurs before the normal vertex weighting. 202 203 An implementation that truly treated rescaling as a normalize 204 would support both a pre-weighting normalize and a post-weighting 205 normalize. Arguably, this is a good thing. 206 207 For implementations that perform simply rescaling and not a full 208 normalize to implement rescaling, the rescaling factor can be 209 concatenated into each particular inverse modelview matrix. 210 211New Procedures and Functions 212 213 void VertexWeightfEXT(float weight); 214 215 void VertexWeightfvEXT(float *weight); 216 217 void VertexWeightPointerEXT(int size, enum type, sizei stride, void *pointer); 218 219New Tokens 220 221 Accepted by the <target> parameter of Enable: 222 223 VERTEX_WEIGHTING_EXT 0x8509 224 225 Accepted by the <mode> parameter of MatrixMode: 226 227 MODELVIEW0_EXT 0x1700 (alias to MODELVIEW enumerant) 228 MODELVIEW1_EXT 0x850A 229 230 Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, 231 GetFloatv, and GetDoublev: 232 233 VERTEX_WEIGHTING_EXT 234 MODELVIEW0_EXT 235 MODELVIEW1_EXT 236 MODELVIEW0_MATRIX_EXT 0x0BA6 (alias to MODELVIEW_MATRIX) 237 MODELVIEW1_MATRIX_EXT 0x8506 238 CURRENT_VERTEX_WEIGHT_EXT 0x850B 239 VERTEX_WEIGHT_ARRAY_EXT 0x850C 240 VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D 241 VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E 242 VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F 243 MODELVIEW0_STACK_DEPTH_EXT 0x0BA3 (alias to MODELVIEW_STACK_DEPTH) 244 MODELVIEW1_STACK_DEPTH_EXT 0x8502 245 246 Accepted by the <pname> parameter of GetPointerv: 247 248 VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 249 250Additions to Chapter 2 of the OpenGL 1.2.1 Specification (OpenGL Operation) 251 252 -- Section 2.6. 2nd paragraph changed: 253 254 "Each vertex is specified with two, three, or four coordinates. 255 In addition, a current normal, current texture coordinates, current 256 color, and current vertex weight may be used in processing each 257 vertex." 258 259 -- Section 2.6. New paragraph after the 3rd paragraph: 260 261 "A vertex weight is associated with each vertex. When vertex 262 weighting is enabled, this weight is used as a blending factor 263 to blend the position and normals transformed by the primary and 264 secondary modelview matrix transforms. The vertex weighting 265 functionality takes place completely in the "vertex / normal 266 transformation" stage of Figure 2.2." 267 268 -- Section 2.6.3. First paragraph changed to 269 270 "The only GL commands that are allowed within any Begin/End pairs are 271 the commands for specifying vertex coordinates, vertex colors, normal 272 coordinates, and texture coordinates (Vertex, Color, VertexWeightEXT, 273 Index, Normal, TexCoord)..." 274 275 -- Section 2.7. New paragraph after the 4th paragraph: 276 277 "The current vertex weight is set using 278 279 void VertexWeightfEXT(float weight); 280 void VertexWeightfvEXT(float *weight); 281 282 This weight is used when vertex weighting is enabled." 283 284 -- Section 2.7. The last paragraph changes from 285 286 "... and one floating-point value to store the current color index." 287 288 to: 289 290 "... one floating-point number to store the vertex weight, and one 291 floating-point value to store the current color index." 292 293 -- Section 2.8. Change 1st paragraph to say: 294 295 "The client may specify up to seven arrays: one each to store edge 296 flags, texture coordinates, colors, color indices, vertex weights, 297 normals, and vertices. The commands" 298 299 Add to functions listed following first paragraph: 300 301 void VertexWeightPointerEXT(int size, enum type, sizei stride, void *pointer); 302 303 Add to table 2.4 (p. 22): 304 305 Command Sizes Types 306 ---------------------- ----- ----- 307 VertexWeightPointerEXT 1 float 308 309 Starting with the second paragraph on p. 23, change to add 310 VERTEX_WEIGHT_ARRAY_EXT: 311 312 "An individual array is enabled or disabled by calling one of 313 314 void EnableClientState(enum array) 315 void DisableClientState(enum array) 316 317 with array set to EDGE_FLAG_ARRAY, TEXTURE_COORD_ARRAY, COLOR_ARRAY, 318 INDEX_ARRAY, VERTEX_ARRAY_WEIGHT_EXT, NORMAL_ARRAY, or VERTEX_ARRAY, 319 for the edge flag, texture coordinate, color, secondary color, 320 color index, normal, or vertex array, respectively. 321 322 The ith element of every enabled array is transferred to the GL by calling 323 324 void ArrayElement(int i) 325 326 For each enabled array, it is as though the corresponding command 327 from section 2.7 or section 2.6.2 were called with a pointer to 328 element i. For the vertex array, the corresponding command is 329 Vertex<size><type>v, where <size> is one of [2,3,4], and <type> is 330 one of [s,i,f,d], corresponding to array types short, int, float, and 331 double respectively. The corresponding commands for the edge flag, 332 texture coordinate, color, secondary color, color index, and normal 333 arrays are EdgeFlagv, TexCoord<size><type>v, Color<size><type>v, 334 Index<type>v, VertexWeightfvEXT, and Normal<type>v, respectively..." 335 336 Change pseudocode on p. 27 to disable vertex weight array for canned 337 interleaved array formats. After the lines 338 339 DisableClientState(EDGE_FLAG_ARRAY); 340 DisableClientState(INDEX_ARRAY); 341 342 insert the line 343 344 DisableClientState(VERTEX_WEIGHT_ARRAY_EXT); 345 346 Substitute "seven" for every occurrence of "six" in the final 347 paragraph on p. 27. 348 349 -- Section 2.10. Change the sentence: 350 351 "The model-view matrix is applied to these coordinates to yield eye 352 coordinates." 353 354 to: 355 356 "The primary modelview matrix is applied to these coordinates to 357 yield eye coordinates. When vertex weighting is enabled, a secondary 358 modelview matrix is also applied to the vertex coordinates, the 359 result of the two modelview transformations are weighted by its 360 respective vertex weighting factor and combined by addition to yield 361 the true eye coordinates. Vertex weighting is enabled or disabled 362 using Enable and Disable (see section 2.10.3) with an argument of 363 VERTEX_WEIGHTING_EXT." 364 365 Change the 4th paragraph to: 366 367 "If vertex weighting is disabled and a vertex in object coordinates 368 is given by ( xo yo zo wo )' and the primary model-view matrix is 369 M0, then the vertex's eye coordinates are found as 370 371 (xe ye ze we)' = M0 (xo yo zo wo)' 372 373 If vertex weighting is enabled, then the vertex's eye coordinates 374 are found as 375 376 (xe0 ye0 ze0 we0)' = M0 (xo yo zo wo)' 377 378 (xe1 ye1 ze1 we1)' = M1 (xo yo zo wo)' 379 380 (xe,ye,ze)' = vw*(xe0,ye0,ze0)' + (1-vw) * (xe1,ye1,ze1)' 381 382 we = we0 383 384 where M1 is the secondary modelview matrix and vw is the current 385 vertex weight." 386 387 -- Section 2.10.2 Change the 1st paragraph to say: 388 389 "The projection matrix and the primary and secondary modelview 390 matrices are set and modified with a variety of commands. The 391 affected matrix is determined by the current matrix mode. The 392 current matrix mode is set with 393 394 void MatrixMode(enum mode); 395 396 which takes one of the four pre-defined constants TEXTURE, 397 MODELVIEW0, MODELVIEW1, or PROJECTION (note that MODELVIEW is an 398 alias for MODELVIEW0). TEXTURE is described later. If the current 399 matrix is MODELVIEW0, then matrix operations apply to the primary 400 modelview matrix; if MODELVIEW1, then matrix operations apply to 401 the secondary modelview matrix; if PROJECTION, then they apply to 402 the projection matrix." 403 404 Change the 9th paragraph to say: 405 406 "There is a stack of matrices for each of the matrix modes. For the 407 MODELVIEW0 and MODELVIEW1 modes, the stack is at least 32 (that is, 408 there is a stack of at least 32 modelview matrices). ..." 409 410 Change the last paragraph to say: 411 412 "The state required to implement transformations consists of a 413 four-valued integer indicating the current matrix mode, a stack of 414 at least two 4x4 matrices for each of PROJECTION and TEXTURE with 415 associated stack pointers, and two stacks of at least 32 4x4 matrices 416 with an associated stack pointer for MODELVIEW0 and MODELVIEW1. 417 Initially, there is only one matrix on each stack, and all matrices 418 are set to the identity. The initial matrix mode is MODELVIEW0." 419 420 -- Section 2.10.3 Change the 2nd and 7th paragraphs to say: 421 422 "For a modelview matrix M, the normal for this matrix is transformed 423 to eye coordinates by: 424 425 (nx' ny' nz' q') = (nx ny nz q) * M^-1 426 427 where, if (x y z w)' are the associated vertex coordinates, then 428 429 / 0, w= 0 430 | 431 q = | -(nx ny nz) (x y z)' (2.1) 432 | --------------------, w != 0 433 \ w 434 435 Implementations may choose instead to transform (x y z)' to eye 436 coordinates using 437 438 (nx' ny' nz') = (nx ny nz) * Mu^-1 439 440 Where Mu is the upper leftmost 3x3 matrix taken from M. 441 442 Rescale multiplies the transformed normals by a scale factor 443 444 ( nx" ny" nz" ) = f (nx' ny' nz') 445 446 If rescaling is disabled, then f = 1. If rescaling is enabled, then 447 f is computed as (mij denotes the matrix element in row i and column j 448 of M^-1, numbering the topmost row of the matrix as row 1 and the leftmost column 449 as column 1 450 451 1 452 f = --------------------------- 453 sqrt(m31^2 + m32^2 + m33^2) 454 455 Note that if the normals sent to GL were unit length and the model-view 456 matrix uniformly scales space, the rescale make sthe transformed normals 457 unit length. 458 459 Alternatively, an implementation may chose f as 460 461 1 462 f = --------------------------- 463 sqrt(nx'^2 + ny'^2 + nz'^2) 464 465 recomputing f for each normal. This makes all non-zero length 466 normals unit length regardless of their input length and the nature 467 of the modelview matrix. 468 469 After rescaling, the final transformed normal used in lighting, nf, 470 depends on whether vertex weighting is enabled or not. 471 472 When vertex weighting is disabled, nf is computed as 473 474 nf = m * ( nx"0 ny"0 nz"0 ) 475 476 where (nx"0 ny"0 nz"0) is the normal transformed as described 477 above using the primary modelview matrix for M. 478 479 If normalization is enabled m=1. Otherwise 480 481 1 482 m = ------------------------------ 483 sqrt(nx"0^2 + ny"0^2 + nz"0^2) 484 485 However when vertex weighting is enabled, the normal is transformed 486 twice as described above, once by the primary modelview matrix and 487 again by the secondary modelview matrix, weighted using the current 488 per-vertex weight, and normalized. So nf is computed as 489 490 nf = m * ( nx"w ny"w nz"w ) 491 492 where nw is the weighting normal computed as 493 494 nw = vw * ( nx"0 ny"0 nz"0 ) + (1-vw) * (nx"1 ny"1 nz"1) 495 496 where (nx"0 ny"0 nz"0) is the normal transformed as described 497 above using the primary modelview matrix for M, and (nx"1 ny"1 nz"1) is the 498 normal transformed as described above using the secondary modelview matrix for 499 M, and vw is the current pver-vertex weight." 500 501 -- Section 2.12. Changes the 3rd paragraph: 502 503 "The coordinates are treated as if they were specified in a 504 Vertex command. The x, y, z, and w coordinates are transformed 505 by the current primary modelview and perspective matrices. These 506 coordinates, along with current values, are used to generate a 507 color and texture coordinates just as done for a vertex, except 508 that vertex weighting is always treated as if it is disabled." 509 510Additions to Chapter 3 of the OpenGL 1.2.1 Specification (Rasterization) 511 512 None 513 514Additions to Chapter 4 of the OpenGL 1.2.1 Specification (Per-Fragment Operations 515and the Framebuffer) 516 517 None 518 519Additions to Chapter 5 of the OpenGL 1.2.1 Specification (Special Functions) 520 521 None 522 523Additions to Chapter 6 of the OpenGL 1.2.1 Specification (State and State Requests) 524 525 None 526 527Additions to Appendix A of the OpenGL 1.2.1 Specification (Invariance) 528 529 None 530 531Additions to the AGL/GLX/WGL Specifications 532 533 None 534 535GLX Protocol 536 537 A new GL rendering command is added. The following command is sent 538 to the server as part of a glXRender request: 539 540 VertexWeightfvEXT 541 2 8 rendering command length 542 2 4135 rendering command opcode 543 4 FLOAT32 weight0 544 545 To support vertex arrays, the DrawArrays rendering command (sent via 546 a glXRender or glXRenderLarge request) is amended as follows: 547 548 The list of arrays listed for the third element in the ARRAY_INFO 549 structure is amended to include: 550 551 0x850c j=1 VERTEX_WEIGHT_ARRAY_EXT 552 553 The VERTEX_DATA description is amended to include: 554 555 If the vertex weight array is enabled: 556 ws LISTofBYTE vertex weight array element 557 wp unused, wp=pad(ws) 558 559 with the following paragraph amended to read: 560 561 "where ns, cs, is, ts, es, vs, ws is the size of the normal, color, 562 index, texture, edge, vertex, and vertex weight array elements and 563 np, cp, ip, tp, ep, vp, wp is the padding for the normal, color, 564 index, texture, edge, vertex, and vertex weight array elements, 565 respectively." 566 567Errors 568 569 The current vertex weight can be updated at any time. In particular 570 WeightVertexEXT can be called between a call to Begin and the 571 corresponding call to End. 572 573 INVALID_VALUE is generated if VertexWeightPointerEXT parameter <size> 574 is not 1. 575 576 INVALID_ENUM is generated if VertexWeightPointerEXT parameter <type> 577 is not FLOAT. 578 579 INVALID_VALUE is generated if VertexWeightPointerEXT parameter <stride> 580 is negative. 581 582New State 583 584(table 6.5, p196) 585Get Value Type Get Command Initial Value Description Sec Attribute 586--------- ---- ----------- ------------- ----------- --- --------- 587CURRENT_VERTEX_WEIGHT_EXT F GetFloatv 1 Current 2.8 current 588 vertex weight 589 590(table 6.6, p197) 591Get Value Type Get Command Initial Value Description Sec Attribute 592--------- ---- ----------- ------------- ----------- --- --------- 593VERTEX_WEIGHT_ARRAY_EXT B IsEnabled False Vertex weight enable 2.8 vertex-array 594VERTEX_WEIGHT_ARRAY_SIZE_EXT Z+ GetIntegerv 1 Weights per vertex 2.8 vertex-array 595VERTEX_WEIGHT_ARRAY_TYPE_EXT Z1 GetIntegerv FLOAT Type of weights 2.8 vertex-array 596VERTEX_WEIGHT_ARRAY_STRIDE_EXT Z GetIntegerv 0 Stride between weights 2.8 vertex-array 597VERTEX_WEIGHT_ARRAY_POINTER_EXT Y GetPointerv 0 Pointer to vertex weight array 2.8 vertex-array 598 599(table 6.7, p198) 600Get Value Type Get Command Initial Value Description Sec Attribute 601--------- ---- ----------- ------------- ----------- ------ --------- 602MODELVIEW0_MATRIX_EXT 32*xM4 GetFloatv Identity Primary modelview 2.10.2 - 603 stack 604MODELVIEW1_MATRIX_EXT 32*xM4 GetFloatv Identity Secondary modelview 2.10.2 - 605 stack 606MODELVIEW0_STACK_DEPTH_EXT Z+ GetIntegerv 1 Primary modelview 2.10.2 - 607 stack depth 608MODELVIEW1_STACK_DEPTH_EXT Z+ GetIntegerv 1 Secondary modelview 2.10.2 - 609 stack depth 610MATRIX_MODE Z4 GetIntegerv MODELVIEW0 Current matrix mode 2.10.2 transform 611VERTEX_WEIGHTING_EXT B IsEnabled False Vertex weighting 2.10.2 transform/enable 612 on/off 613 614 NOTE: MODELVIEW_MATRIX is an alias for MODELVIEW0_MATRIX_EXT 615 MODELVIEW_STACK_DEPTH is an alias for MODELVIEW0_STACK_DEPTH_EXT 616 617New Implementation Dependent State 618 619 None 620 621Revision History 622 623 12/16/2000 amended to include GLX protocol for vertex arrays 624 5/25/2000 added missing MODELVIEW#_MATRIX_EXT token values 625 1/3/2003 changed status to "discontinued" 626