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