1 /* 2 * Cogl 3 * 4 * A Low Level GPU Graphics and Utilities API 5 * 6 * Copyright (C) 2009,2010,2012 Intel Corporation. 7 * 8 * Permission is hereby granted, free of charge, to any person 9 * obtaining a copy of this software and associated documentation 10 * files (the "Software"), to deal in the Software without 11 * restriction, including without limitation the rights to use, copy, 12 * modify, merge, publish, distribute, sublicense, and/or sell copies 13 * of the Software, and to permit persons to whom the Software is 14 * furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be 17 * included in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 * SOFTWARE. 27 * 28 * 29 * 30 * Authors: 31 * Havoc Pennington <hp@pobox.com> for litl 32 * Robert Bragg <robert@linux.intel.com> 33 */ 34 35 #ifndef _COGL_MATRIX_STACK_H_ 36 #define _COGL_MATRIX_STACK_H_ 37 38 #if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION) 39 #error "Only <cogl/cogl.h> can be included directly." 40 #endif 41 42 #include "cogl-matrix.h" 43 #include "cogl-context.h" 44 45 46 /** 47 * SECTION:cogl-matrix-stack 48 * @short_description: Functions for efficiently tracking many 49 * related transformations 50 * 51 * Matrices can be used (for example) to describe the model-view 52 * transforms of objects, texture transforms, and projective 53 * transforms. 54 * 55 * The #CoglMatrix api provides a good way to manipulate individual 56 * matrices representing a single transformation but if you need to 57 * track many-many such transformations for many objects that are 58 * organized in a scenegraph for example then using a separate 59 * #CoglMatrix for each object may not be the most efficient way. 60 * 61 * A #CoglMatrixStack enables applications to track lots of 62 * transformations that are related to each other in some kind of 63 * hierarchy. In a scenegraph for example if you want to know how to 64 * transform a particular node then you usually have to walk up 65 * through the ancestors and accumulate their transforms before 66 * finally applying the transform of the node itself. In this model 67 * things are grouped together spatially according to their ancestry 68 * and all siblings with the same parent share the same initial 69 * transformation. The #CoglMatrixStack API is suited to tracking lots 70 * of transformations that fit this kind of model. 71 * 72 * Compared to using the #CoglMatrix api directly to track many 73 * related transforms, these can be some advantages to using a 74 * #CoglMatrixStack: 75 * <itemizedlist> 76 * <listitem>Faster equality comparisons of transformations</listitem> 77 * <listitem>Efficient comparisons of the differences between arbitrary 78 * transformations</listitem> 79 * <listitem>Avoid redundant arithmetic related to common transforms 80 * </listitem> 81 * <listitem>Can be more space efficient (not always though)</listitem> 82 * </itemizedlist> 83 * 84 * For reference (to give an idea of when a #CoglMatrixStack can 85 * provide a space saving) a #CoglMatrix can be expected to take 72 86 * bytes whereas a single #CoglMatrixEntry in a #CoglMatrixStack is 87 * currently around 32 bytes on a 32bit CPU or 36 bytes on a 64bit 88 * CPU. An entry is needed for each individual operation applied to 89 * the stack (such as rotate, scale, translate) so if most of your 90 * leaf node transformations only need one or two simple operations 91 * relative to their parent then a matrix stack will likely take less 92 * space than having a #CoglMatrix for each node. 93 * 94 * Even without any space saving though the ability to perform fast 95 * comparisons and avoid redundant arithmetic (especially sine and 96 * cosine calculations for rotations) can make using a matrix stack 97 * worthwhile. 98 */ 99 100 /** 101 * CoglMatrixStack: 102 * 103 * Tracks your current position within a hierarchy and lets you build 104 * up a graph of transformations as you traverse through a hierarchy 105 * such as a scenegraph. 106 * 107 * A #CoglMatrixStack always maintains a reference to a single 108 * transformation at any point in time, representing the 109 * transformation at the current position in the hierarchy. You can 110 * get a reference to the current transformation by calling 111 * cogl_matrix_stack_get_entry(). 112 * 113 * When a #CoglMatrixStack is first created with 114 * cogl_matrix_stack_new() then it is conceptually positioned at the 115 * root of your hierarchy and the current transformation simply 116 * represents an identity transformation. 117 * 118 * As you traverse your object hierarchy (your scenegraph) then you 119 * should call cogl_matrix_stack_push() whenever you move down one 120 * level and call cogl_matrix_stack_pop() whenever you move back up 121 * one level towards the root. 122 * 123 * At any time you can apply a set of operations, such as "rotate", 124 * "scale", "translate" on top of the current transformation of a 125 * #CoglMatrixStack using functions such as 126 * cogl_matrix_stack_rotate(), cogl_matrix_stack_scale() and 127 * cogl_matrix_stack_translate(). These operations will derive a new 128 * current transformation and will never affect a transformation 129 * that you have referenced using cogl_matrix_stack_get_entry(). 130 * 131 * Internally applying operations to a #CoglMatrixStack builds up a 132 * graph of #CoglMatrixEntry structures which each represent a single 133 * immutable transform. 134 */ 135 typedef struct _CoglMatrixStack CoglMatrixStack; 136 137 #ifdef COGL_HAS_GTYPE_SUPPORT 138 /** 139 * cogl_matrix_stack_get_gtype: 140 * 141 * Returns: a #GType that can be used with the GLib type system. 142 */ 143 GType cogl_matrix_stack_get_gtype (void); 144 #endif 145 146 /** 147 * CoglMatrixEntry: 148 * 149 * Represents a single immutable transformation that was retrieved 150 * from a #CoglMatrixStack using cogl_matrix_stack_get_entry(). 151 * 152 * Internally a #CoglMatrixEntry represents a single matrix 153 * operation (such as "rotate", "scale", "translate") which is applied 154 * to the transform of a single parent entry. 155 * 156 * Using the #CoglMatrixStack api effectively builds up a graph of 157 * these immutable #CoglMatrixEntry structures whereby operations 158 * that can be shared between multiple transformations will result 159 * in shared #CoglMatrixEntry nodes in the graph. 160 * 161 * When a #CoglMatrixStack is first created it references one 162 * #CoglMatrixEntry that represents a single "load identity" 163 * operation. This serves as the root entry and all operations 164 * that are then applied to the stack will extend the graph 165 * starting from this root "load identity" entry. 166 * 167 * Given the typical usage model for a #CoglMatrixStack and the way 168 * the entries are built up while traversing a scenegraph then in most 169 * cases where an application is interested in comparing two 170 * transformations for equality then it is enough to simply compare 171 * two #CoglMatrixEntry pointers directly. Technically this can lead 172 * to false negatives that could be identified with a deeper 173 * comparison but often these false negatives are unlikely and 174 * don't matter anyway so this enables extremely cheap comparisons. 175 * 176 * <note>#CoglMatrixEntry<!-- -->s are reference counted using 177 * cogl_matrix_entry_ref() and cogl_matrix_entry_unref() not with 178 * cogl_object_ref() and cogl_object_unref().</note> 179 */ 180 typedef struct _CoglMatrixEntry CoglMatrixEntry; 181 182 #ifdef COGL_HAS_GTYPE_SUPPORT 183 /** 184 * cogl_matrix_entry_get_gtype: 185 * 186 * Returns: a #GType that can be used with the GLib type system. 187 */ 188 GType cogl_matrix_entry_get_gtype (void); 189 #endif 190 191 192 /** 193 * cogl_matrix_stack_new: 194 * @ctx: A #CoglContext 195 * 196 * Allocates a new #CoglMatrixStack that can be used to build up 197 * transformations relating to objects in a scenegraph like hierarchy. 198 * (See the description of #CoglMatrixStack and #CoglMatrixEntry for 199 * more details of what a matrix stack is best suited for) 200 * 201 * When a #CoglMatrixStack is first allocated it is conceptually 202 * positioned at the root of your scenegraph hierarchy. As you 203 * traverse your scenegraph then you should call 204 * cogl_matrix_stack_push() whenever you move down a level and 205 * cogl_matrix_stack_pop() whenever you move back up a level towards 206 * the root. 207 * 208 * Once you have allocated a #CoglMatrixStack you can get a reference 209 * to the current transformation for the current position in the 210 * hierarchy by calling cogl_matrix_stack_get_entry(). 211 * 212 * Once you have allocated a #CoglMatrixStack you can apply operations 213 * such as rotate, scale and translate to modify the current transform 214 * for the current position in the hierarchy by calling 215 * cogl_matrix_stack_rotate(), cogl_matrix_stack_scale() and 216 * cogl_matrix_stack_translate(). 217 * 218 * Return value: (transfer full): A newly allocated #CoglMatrixStack 219 */ 220 CoglMatrixStack * 221 cogl_matrix_stack_new (CoglContext *ctx); 222 223 /** 224 * cogl_matrix_stack_push: 225 * @stack: A #CoglMatrixStack 226 * 227 * Saves the current transform and starts a new transform that derives 228 * from the current transform. 229 * 230 * This is usually called while traversing a scenegraph whenever you 231 * traverse one level deeper. cogl_matrix_stack_pop() can then be 232 * called when going back up one layer to restore the previous 233 * transform of an ancestor. 234 */ 235 void 236 cogl_matrix_stack_push (CoglMatrixStack *stack); 237 238 /** 239 * cogl_matrix_stack_pop: 240 * @stack: A #CoglMatrixStack 241 * 242 * Restores the previous transform that was last saved by calling 243 * cogl_matrix_stack_push(). 244 * 245 * This is usually called while traversing a scenegraph whenever you 246 * return up one level in the graph towards the root node. 247 */ 248 void 249 cogl_matrix_stack_pop (CoglMatrixStack *stack); 250 251 /** 252 * cogl_matrix_stack_load_identity: 253 * @stack: A #CoglMatrixStack 254 * 255 * Resets the current matrix to the identity matrix. 256 */ 257 void 258 cogl_matrix_stack_load_identity (CoglMatrixStack *stack); 259 260 /** 261 * cogl_matrix_stack_scale: 262 * @stack: A #CoglMatrixStack 263 * @x: Amount to scale along the x-axis 264 * @y: Amount to scale along the y-axis 265 * @z: Amount to scale along the z-axis 266 * 267 * Multiplies the current matrix by one that scales the x, y and z 268 * axes by the given values. 269 */ 270 void 271 cogl_matrix_stack_scale (CoglMatrixStack *stack, 272 float x, 273 float y, 274 float z); 275 276 /** 277 * cogl_matrix_stack_translate: 278 * @stack: A #CoglMatrixStack 279 * @x: Distance to translate along the x-axis 280 * @y: Distance to translate along the y-axis 281 * @z: Distance to translate along the z-axis 282 * 283 * Multiplies the current matrix by one that translates along all 284 * three axes according to the given values. 285 */ 286 void 287 cogl_matrix_stack_translate (CoglMatrixStack *stack, 288 float x, 289 float y, 290 float z); 291 292 /** 293 * cogl_matrix_stack_rotate: 294 * @stack: A #CoglMatrixStack 295 * @angle: Angle in degrees to rotate. 296 * @x: X-component of vertex to rotate around. 297 * @y: Y-component of vertex to rotate around. 298 * @z: Z-component of vertex to rotate around. 299 * 300 * Multiplies the current matrix by one that rotates the around the 301 * axis-vector specified by @x, @y and @z. The rotation follows the 302 * right-hand thumb rule so for example rotating by 10 degrees about 303 * the axis-vector (0, 0, 1) causes a small counter-clockwise 304 * rotation. 305 */ 306 void 307 cogl_matrix_stack_rotate (CoglMatrixStack *stack, 308 float angle, 309 float x, 310 float y, 311 float z); 312 313 /** 314 * cogl_matrix_stack_rotate_quaternion: 315 * @stack: A #CoglMatrixStack 316 * @quaternion: A #CoglQuaternion 317 * 318 * Multiplies the current matrix by one that rotates according to the 319 * rotation described by @quaternion. 320 */ 321 void 322 cogl_matrix_stack_rotate_quaternion (CoglMatrixStack *stack, 323 const CoglQuaternion *quaternion); 324 325 /** 326 * cogl_matrix_stack_rotate_euler: 327 * @stack: A #CoglMatrixStack 328 * @euler: A #CoglEuler 329 * 330 * Multiplies the current matrix by one that rotates according to the 331 * rotation described by @euler. 332 */ 333 void 334 cogl_matrix_stack_rotate_euler (CoglMatrixStack *stack, 335 const CoglEuler *euler); 336 337 /** 338 * cogl_matrix_stack_multiply: 339 * @stack: A #CoglMatrixStack 340 * @matrix: the matrix to multiply with the current model-view 341 * 342 * Multiplies the current matrix by the given matrix. 343 */ 344 void 345 cogl_matrix_stack_multiply (CoglMatrixStack *stack, 346 const CoglMatrix *matrix); 347 348 /** 349 * cogl_matrix_stack_frustum: 350 * @stack: A #CoglMatrixStack 351 * @left: X position of the left clipping plane where it 352 * intersects the near clipping plane 353 * @right: X position of the right clipping plane where it 354 * intersects the near clipping plane 355 * @bottom: Y position of the bottom clipping plane where it 356 * intersects the near clipping plane 357 * @top: Y position of the top clipping plane where it intersects 358 * the near clipping plane 359 * @z_near: The distance to the near clipping plane (Must be positive) 360 * @z_far: The distance to the far clipping plane (Must be positive) 361 * 362 * Replaces the current matrix with a perspective matrix for a given 363 * viewing frustum defined by 4 side clip planes that all cross 364 * through the origin and 2 near and far clip planes. 365 */ 366 void 367 cogl_matrix_stack_frustum (CoglMatrixStack *stack, 368 float left, 369 float right, 370 float bottom, 371 float top, 372 float z_near, 373 float z_far); 374 375 /** 376 * cogl_matrix_stack_perspective: 377 * @stack: A #CoglMatrixStack 378 * @fov_y: Vertical field of view angle in degrees. 379 * @aspect: The (width over height) aspect ratio for display 380 * @z_near: The distance to the near clipping plane (Must be positive, 381 * and must not be 0) 382 * @z_far: The distance to the far clipping plane (Must be positive) 383 * 384 * Replaces the current matrix with a perspective matrix based on the 385 * provided values. 386 * 387 * <note>You should be careful not to have too great a @z_far / @z_near 388 * ratio since that will reduce the effectiveness of depth testing 389 * since there wont be enough precision to identify the depth of 390 * objects near to each other.</note> 391 */ 392 void 393 cogl_matrix_stack_perspective (CoglMatrixStack *stack, 394 float fov_y, 395 float aspect, 396 float z_near, 397 float z_far); 398 399 /** 400 * cogl_matrix_stack_orthographic: 401 * @stack: A #CoglMatrixStack 402 * @x_1: The x coordinate for the first vertical clipping plane 403 * @y_1: The y coordinate for the first horizontal clipping plane 404 * @x_2: The x coordinate for the second vertical clipping plane 405 * @y_2: The y coordinate for the second horizontal clipping plane 406 * @near: The <emphasis>distance</emphasis> to the near clipping 407 * plane (will be <emphasis>negative</emphasis> if the plane is 408 * behind the viewer) 409 * @far: The <emphasis>distance</emphasis> to the far clipping 410 * plane (will be <emphasis>negative</emphasis> if the plane is 411 * behind the viewer) 412 * 413 * Replaces the current matrix with an orthographic projection matrix. 414 */ 415 void 416 cogl_matrix_stack_orthographic (CoglMatrixStack *stack, 417 float x_1, 418 float y_1, 419 float x_2, 420 float y_2, 421 float near, 422 float far); 423 424 /** 425 * cogl_matrix_stack_get_inverse: 426 * @stack: A #CoglMatrixStack 427 * @inverse: (out): The destination for a 4x4 inverse transformation matrix 428 * 429 * Gets the inverse transform of the current matrix and uses it to 430 * initialize a new #CoglMatrix. 431 * 432 * Return value: %TRUE if the inverse was successfully calculated or %FALSE 433 * for degenerate transformations that can't be inverted (in this case the 434 * @inverse matrix will simply be initialized with the identity matrix) 435 */ 436 CoglBool 437 cogl_matrix_stack_get_inverse (CoglMatrixStack *stack, 438 CoglMatrix *inverse); 439 440 /** 441 * cogl_matrix_stack_get_entry: 442 * @stack: A #CoglMatrixStack 443 * 444 * Gets a reference to the current transform represented by a 445 * #CoglMatrixEntry pointer. 446 * 447 * <note>The transform represented by a #CoglMatrixEntry is 448 * immutable.</note> 449 * 450 * <note>#CoglMatrixEntry<!-- -->s are reference counted using 451 * cogl_matrix_entry_ref() and cogl_matrix_entry_unref() and you 452 * should call cogl_matrix_entry_unref() when you are finished with 453 * and entry you get via cogl_matrix_stack_get_entry().</note> 454 * 455 * Return value: (transfer none): A pointer to the #CoglMatrixEntry 456 * representing the current matrix stack transform. 457 */ 458 CoglMatrixEntry * 459 cogl_matrix_stack_get_entry (CoglMatrixStack *stack); 460 461 /** 462 * cogl_matrix_stack_get: 463 * @stack: A #CoglMatrixStack 464 * @matrix: (out): The potential destination for the current matrix 465 * 466 * Resolves the current @stack transform into a #CoglMatrix by 467 * combining the operations that have been applied to build up the 468 * current transform. 469 * 470 * There are two possible ways that this function may return its 471 * result depending on whether the stack is able to directly point 472 * to an internal #CoglMatrix or whether the result needs to be 473 * composed of multiple operations. 474 * 475 * If an internal matrix contains the required result then this 476 * function will directly return a pointer to that matrix, otherwise 477 * if the function returns %NULL then @matrix will be initialized 478 * to match the current transform of @stack. 479 * 480 * <note>@matrix will be left untouched if a direct pointer is 481 * returned.</note> 482 * 483 * Return value: A direct pointer to the current transform or %NULL 484 * and in that case @matrix will be initialized with 485 * the value of the current transform. 486 */ 487 CoglMatrix * 488 cogl_matrix_stack_get (CoglMatrixStack *stack, 489 CoglMatrix *matrix); 490 491 /** 492 * cogl_matrix_entry_get: 493 * @entry: A #CoglMatrixEntry 494 * @matrix: (out): The potential destination for the transform as 495 * a matrix 496 * 497 * Resolves the current @entry transform into a #CoglMatrix by 498 * combining the sequence of operations that have been applied to 499 * build up the current transform. 500 * 501 * There are two possible ways that this function may return its 502 * result depending on whether it's possible to directly point 503 * to an internal #CoglMatrix or whether the result needs to be 504 * composed of multiple operations. 505 * 506 * If an internal matrix contains the required result then this 507 * function will directly return a pointer to that matrix, otherwise 508 * if the function returns %NULL then @matrix will be initialized 509 * to match the transform of @entry. 510 * 511 * <note>@matrix will be left untouched if a direct pointer is 512 * returned.</note> 513 * 514 * Return value: A direct pointer to a #CoglMatrix transform or %NULL 515 * and in that case @matrix will be initialized with 516 * the effective transform represented by @entry. 517 */ 518 CoglMatrix * 519 cogl_matrix_entry_get (CoglMatrixEntry *entry, 520 CoglMatrix *matrix); 521 522 /** 523 * cogl_matrix_stack_set: 524 * @stack: A #CoglMatrixStack 525 * @matrix: A #CoglMatrix replace the current matrix value with 526 * 527 * Replaces the current @stack matrix value with the value of @matrix. 528 * This effectively discards any other operations that were applied 529 * since the last time cogl_matrix_stack_push() was called or since 530 * the stack was initialized. 531 */ 532 void 533 cogl_matrix_stack_set (CoglMatrixStack *stack, 534 const CoglMatrix *matrix); 535 536 /** 537 * cogl_is_matrix_stack: 538 * @object: a #CoglObject 539 * 540 * Determines if the given #CoglObject refers to a #CoglMatrixStack. 541 * 542 * Return value: %TRUE if @object is a #CoglMatrixStack, otherwise 543 * %FALSE. 544 */ 545 CoglBool 546 cogl_is_matrix_stack (void *object); 547 548 /** 549 * cogl_matrix_entry_calculate_translation: 550 * @entry0: The first reference transform 551 * @entry1: A second reference transform 552 * @x: (out): The destination for the x-component of the translation 553 * @y: (out): The destination for the y-component of the translation 554 * @z: (out): The destination for the z-component of the translation 555 * 556 * Determines if the only difference between two transforms is a 557 * translation and if so returns what the @x, @y, and @z components of 558 * the translation are. 559 * 560 * If the difference between the two translations involves anything 561 * other than a translation then the function returns %FALSE. 562 * 563 * Return value: %TRUE if the only difference between the transform of 564 * @entry0 and the transform of @entry1 is a translation, 565 * otherwise %FALSE. 566 */ 567 CoglBool 568 cogl_matrix_entry_calculate_translation (CoglMatrixEntry *entry0, 569 CoglMatrixEntry *entry1, 570 float *x, 571 float *y, 572 float *z); 573 574 /** 575 * cogl_matrix_entry_is_identity: 576 * @entry: A #CoglMatrixEntry 577 * 578 * Determines whether @entry is known to represent an identity 579 * transform. 580 * 581 * If this returns %TRUE then the entry is definitely the identity 582 * matrix. If it returns %FALSE it may or may not be the identity 583 * matrix but no expensive comparison is performed to verify it. 584 * 585 * Return value: %TRUE if @entry is definitely an identity transform, 586 * otherwise %FALSE. 587 */ 588 CoglBool 589 cogl_matrix_entry_is_identity (CoglMatrixEntry *entry); 590 591 /** 592 * cogl_matrix_entry_equal: 593 * @entry0: The first #CoglMatrixEntry to compare 594 * @entry1: A second #CoglMatrixEntry to compare 595 * 596 * Compares two arbitrary #CoglMatrixEntry transforms for equality 597 * returning %TRUE if they are equal or %FALSE otherwise. 598 * 599 * <note>In many cases it is unnecessary to use this api and instead 600 * direct pointer comparisons of entries are good enough and much 601 * cheaper too.</note> 602 * 603 * Return value: %TRUE if @entry0 represents the same transform as 604 * @entry1, otherwise %FALSE. 605 */ 606 CoglBool 607 cogl_matrix_entry_equal (CoglMatrixEntry *entry0, 608 CoglMatrixEntry *entry1); 609 610 /** 611 * cogl_debug_matrix_entry_print: 612 * @entry: A #CoglMatrixEntry 613 * 614 * Allows visualizing the operations that build up the given @entry 615 * for debugging purposes by printing to stdout. 616 */ 617 void 618 cogl_debug_matrix_entry_print (CoglMatrixEntry *entry); 619 620 /** 621 * cogl_matrix_entry_ref: 622 * @entry: A #CoglMatrixEntry 623 * 624 * Takes a reference on the given @entry to ensure the @entry stays 625 * alive and remains valid. When you are finished with the @entry then 626 * you should call cogl_matrix_entry_unref(). 627 * 628 * It is an error to pass an @entry pointer to cogl_object_ref() and 629 * cogl_object_unref() 630 */ 631 CoglMatrixEntry * 632 cogl_matrix_entry_ref (CoglMatrixEntry *entry); 633 634 /** 635 * cogl_matrix_entry_unref: 636 * @entry: A #CoglMatrixEntry 637 * 638 * Releases a reference on @entry either taken by calling 639 * cogl_matrix_entry_unref() or to release the reference given when 640 * calling cogl_matrix_stack_get_entry(). 641 */ 642 void 643 cogl_matrix_entry_unref (CoglMatrixEntry *entry); 644 645 #endif /* _COGL_MATRIX_STACK_H_ */ 646