1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module graphene.Matrix; 26 27 private import glib.ConstructionException; 28 private import glib.MemorySlice; 29 private import gobject.ObjectG; 30 private import graphene.Box; 31 private import graphene.Euler; 32 private import graphene.Point; 33 private import graphene.Point3D; 34 private import graphene.Quad; 35 private import graphene.Quaternion; 36 private import graphene.Ray; 37 private import graphene.Rect; 38 private import graphene.Sphere; 39 private import graphene.Vec3; 40 private import graphene.Vec4; 41 private import graphene.c.functions; 42 public import graphene.c.types; 43 private import gtkd.Loader; 44 45 46 /** 47 * A structure capable of holding a 4x4 matrix. 48 * 49 * The contents of the #graphene_matrix_t structure are private and 50 * should never be accessed directly. 51 */ 52 public class Matrix 53 { 54 /** the main Gtk struct */ 55 protected graphene_matrix_t* graphene_matrix; 56 protected bool ownedRef; 57 58 /** Get the main Gtk struct */ 59 public graphene_matrix_t* getMatrixStruct(bool transferOwnership = false) 60 { 61 if (transferOwnership) 62 ownedRef = false; 63 return graphene_matrix; 64 } 65 66 /** the main Gtk struct as a void* */ 67 protected void* getStruct() 68 { 69 return cast(void*)graphene_matrix; 70 } 71 72 /** 73 * Sets our main struct and passes it to the parent class. 74 */ 75 public this (graphene_matrix_t* graphene_matrix, bool ownedRef = false) 76 { 77 this.graphene_matrix = graphene_matrix; 78 this.ownedRef = ownedRef; 79 } 80 81 ~this () 82 { 83 if ( Linker.isLoaded(LIBRARY_GRAPHENE) && ownedRef ) 84 graphene_matrix_free(graphene_matrix); 85 } 86 87 88 /** */ 89 public static GType getType() 90 { 91 return graphene_matrix_get_type(); 92 } 93 94 /** 95 * Allocates a new #graphene_matrix_t. 96 * 97 * Returns: the newly allocated matrix 98 * 99 * Since: 1.0 100 * 101 * Throws: ConstructionException GTK+ fails to create the object. 102 */ 103 public this() 104 { 105 auto __p = graphene_matrix_alloc(); 106 107 if(__p is null) 108 { 109 throw new ConstructionException("null returned by alloc"); 110 } 111 112 this(cast(graphene_matrix_t*) __p); 113 } 114 115 /** 116 * Decomposes a transformation matrix into its component transformations. 117 * 118 * The algorithm for decomposing a matrix is taken from the 119 * [CSS3 Transforms specification](http://dev.w3.org/csswg/css-transforms/); 120 * specifically, the decomposition code is based on the equivalent code 121 * published in "Graphics Gems II", edited by Jim Arvo, and 122 * [available online](http://tog.acm.org/resources/GraphicsGems/gemsii/unmatrix.c). 123 * 124 * Params: 125 * translate = the translation vector 126 * scale = the scale vector 127 * rotate = the rotation quaternion 128 * shear = the shear vector 129 * perspective = the perspective vector 130 * 131 * Returns: `true` if the matrix could be decomposed 132 */ 133 public bool decompose(out Vec3 translate, out Vec3 scale, out Quaternion rotate, out Vec3 shear, out Vec4 perspective) 134 { 135 graphene_vec3_t* outtranslate = sliceNew!graphene_vec3_t(); 136 graphene_vec3_t* outscale = sliceNew!graphene_vec3_t(); 137 graphene_quaternion_t* outrotate = sliceNew!graphene_quaternion_t(); 138 graphene_vec3_t* outshear = sliceNew!graphene_vec3_t(); 139 graphene_vec4_t* outperspective = sliceNew!graphene_vec4_t(); 140 141 auto __p = graphene_matrix_decompose(graphene_matrix, outtranslate, outscale, outrotate, outshear, outperspective) != 0; 142 143 translate = ObjectG.getDObject!(Vec3)(outtranslate, true); 144 scale = ObjectG.getDObject!(Vec3)(outscale, true); 145 rotate = ObjectG.getDObject!(Quaternion)(outrotate, true); 146 shear = ObjectG.getDObject!(Vec3)(outshear, true); 147 perspective = ObjectG.getDObject!(Vec4)(outperspective, true); 148 149 return __p; 150 } 151 152 /** 153 * Computes the determinant of the given matrix. 154 * 155 * Returns: the value of the determinant 156 * 157 * Since: 1.0 158 */ 159 public float determinant() 160 { 161 return graphene_matrix_determinant(graphene_matrix); 162 } 163 164 /** 165 * Checks whether the two given #graphene_matrix_t matrices are equal. 166 * 167 * Params: 168 * b = a #graphene_matrix_t 169 * 170 * Returns: `true` if the two matrices are equal, and `false` otherwise 171 * 172 * Since: 1.10 173 */ 174 public bool equal(Matrix b) 175 { 176 return graphene_matrix_equal(graphene_matrix, (b is null) ? null : b.getMatrixStruct()) != 0; 177 } 178 179 /** 180 * Checks whether the two given #graphene_matrix_t matrices are 181 * byte-by-byte equal. 182 * 183 * While this function is faster than graphene_matrix_equal(), it 184 * can also return false negatives, so it should be used in 185 * conjuction with either graphene_matrix_equal() or 186 * graphene_matrix_near(). For instance: 187 * 188 * |[<!-- language="C" --> 189 * if (graphene_matrix_equal_fast (a, b)) 190 * { 191 * // matrices are definitely the same 192 * } 193 * else 194 * { 195 * if (graphene_matrix_equal (a, b)) 196 * // matrices contain the same values within an epsilon of FLT_EPSILON 197 * else if (graphene_matrix_near (a, b, 0.0001)) 198 * // matrices contain the same values within an epsilon of 0.0001 199 * else 200 * // matrices are not equal 201 * } 202 * ]| 203 * 204 * Params: 205 * b = a #graphene_matrix_t 206 * 207 * Returns: `true` if the matrices are equal. and `false` otherwise 208 * 209 * Since: 1.10 210 */ 211 public bool equalFast(Matrix b) 212 { 213 return graphene_matrix_equal_fast(graphene_matrix, (b is null) ? null : b.getMatrixStruct()) != 0; 214 } 215 216 /** 217 * Frees the resources allocated by graphene_matrix_alloc(). 218 * 219 * Since: 1.0 220 */ 221 public void free() 222 { 223 graphene_matrix_free(graphene_matrix); 224 ownedRef = false; 225 } 226 227 /** 228 * Retrieves the given row vector at @index_ inside a matrix. 229 * 230 * Params: 231 * index = the index of the row vector, between 0 and 3 232 * res = return location for the #graphene_vec4_t 233 * that is used to store the row vector 234 * 235 * Since: 1.0 236 */ 237 public void getRow(uint index, out Vec4 res) 238 { 239 graphene_vec4_t* outres = sliceNew!graphene_vec4_t(); 240 241 graphene_matrix_get_row(graphene_matrix, index, outres); 242 243 res = ObjectG.getDObject!(Vec4)(outres, true); 244 } 245 246 /** 247 * Retrieves the value at the given @row and @col index. 248 * 249 * Params: 250 * row = the row index 251 * col = the column index 252 * 253 * Returns: the value at the given indices 254 * 255 * Since: 1.0 256 */ 257 public float getValue(uint row, uint col) 258 { 259 return graphene_matrix_get_value(graphene_matrix, row, col); 260 } 261 262 /** 263 * Retrieves the scaling factor on the X axis in @m. 264 * 265 * Returns: the value of the scaling factor 266 * 267 * Since: 1.0 268 */ 269 public float getXScale() 270 { 271 return graphene_matrix_get_x_scale(graphene_matrix); 272 } 273 274 /** 275 * Retrieves the translation component on the X axis from @m. 276 * 277 * Returns: the translation component 278 * 279 * Since: 1.10 280 */ 281 public float getXTranslation() 282 { 283 return graphene_matrix_get_x_translation(graphene_matrix); 284 } 285 286 /** 287 * Retrieves the scaling factor on the Y axis in @m. 288 * 289 * Returns: the value of the scaling factor 290 * 291 * Since: 1.0 292 */ 293 public float getYScale() 294 { 295 return graphene_matrix_get_y_scale(graphene_matrix); 296 } 297 298 /** 299 * Retrieves the translation component on the Y axis from @m. 300 * 301 * Returns: the translation component 302 * 303 * Since: 1.10 304 */ 305 public float getYTranslation() 306 { 307 return graphene_matrix_get_y_translation(graphene_matrix); 308 } 309 310 /** 311 * Retrieves the scaling factor on the Z axis in @m. 312 * 313 * Returns: the value of the scaling factor 314 * 315 * Since: 1.0 316 */ 317 public float getZScale() 318 { 319 return graphene_matrix_get_z_scale(graphene_matrix); 320 } 321 322 /** 323 * Retrieves the translation component on the Z axis from @m. 324 * 325 * Returns: the translation component 326 * 327 * Since: 1.10 328 */ 329 public float getZTranslation() 330 { 331 return graphene_matrix_get_z_translation(graphene_matrix); 332 } 333 334 /** 335 * Initializes a #graphene_matrix_t from the values of an affine 336 * transformation matrix. 337 * 338 * The arguments map to the following matrix layout: 339 * 340 * |[<!-- language="plain" --> 341 * ⎛ xx yx ⎞ ⎛ a b 0 ⎞ 342 * ⎜ xy yy ⎟ = ⎜ c d 0 ⎟ 343 * ⎝ x0 y0 ⎠ ⎝ tx ty 1 ⎠ 344 * ]| 345 * 346 * This function can be used to convert between an affine matrix type 347 * from other libraries and a #graphene_matrix_t. 348 * 349 * Params: 350 * xx = the xx member 351 * yx = the yx member 352 * xy = the xy member 353 * yy = the yy member 354 * x0 = the x0 member 355 * y0 = the y0 member 356 * 357 * Returns: the initialized matrix 358 * 359 * Since: 1.0 360 */ 361 public Matrix initFrom2d(double xx, double yx, double xy, double yy, double x0, double y0) 362 { 363 auto __p = graphene_matrix_init_from_2d(graphene_matrix, xx, yx, xy, yy, x0, y0); 364 365 if(__p is null) 366 { 367 return null; 368 } 369 370 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 371 } 372 373 /** 374 * Initializes a #graphene_matrix_t with the given array of floating 375 * point values. 376 * 377 * Params: 378 * v = an array of at least 16 floating 379 * point values 380 * 381 * Returns: the initialized matrix 382 * 383 * Since: 1.0 384 */ 385 public Matrix initFromFloat(float[16] v) 386 { 387 auto __p = graphene_matrix_init_from_float(graphene_matrix, v.ptr); 388 389 if(__p is null) 390 { 391 return null; 392 } 393 394 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 395 } 396 397 /** 398 * Initializes a #graphene_matrix_t using the values of the 399 * given matrix. 400 * 401 * Params: 402 * src = a #graphene_matrix_t 403 * 404 * Returns: the initialized matrix 405 * 406 * Since: 1.0 407 */ 408 public Matrix initFromMatrix(Matrix src) 409 { 410 auto __p = graphene_matrix_init_from_matrix(graphene_matrix, (src is null) ? null : src.getMatrixStruct()); 411 412 if(__p is null) 413 { 414 return null; 415 } 416 417 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 418 } 419 420 /** 421 * Initializes a #graphene_matrix_t with the given four row 422 * vectors. 423 * 424 * Params: 425 * v0 = the first row vector 426 * v1 = the second row vector 427 * v2 = the third row vector 428 * v3 = the fourth row vector 429 * 430 * Returns: the initialized matrix 431 * 432 * Since: 1.0 433 */ 434 public Matrix initFromVec4(Vec4 v0, Vec4 v1, Vec4 v2, Vec4 v3) 435 { 436 auto __p = graphene_matrix_init_from_vec4(graphene_matrix, (v0 is null) ? null : v0.getVec4Struct(), (v1 is null) ? null : v1.getVec4Struct(), (v2 is null) ? null : v2.getVec4Struct(), (v3 is null) ? null : v3.getVec4Struct()); 437 438 if(__p is null) 439 { 440 return null; 441 } 442 443 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 444 } 445 446 /** 447 * Initializes a #graphene_matrix_t compatible with #graphene_frustum_t. 448 * 449 * See also: graphene_frustum_init_from_matrix() 450 * 451 * Params: 452 * left = distance of the left clipping plane 453 * right = distance of the right clipping plane 454 * bottom = distance of the bottom clipping plane 455 * top = distance of the top clipping plane 456 * zNear = distance of the near clipping plane 457 * zFar = distance of the far clipping plane 458 * 459 * Returns: the initialized matrix 460 * 461 * Since: 1.2 462 */ 463 public Matrix initFrustum(float left, float right, float bottom, float top, float zNear, float zFar) 464 { 465 auto __p = graphene_matrix_init_frustum(graphene_matrix, left, right, bottom, top, zNear, zFar); 466 467 if(__p is null) 468 { 469 return null; 470 } 471 472 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 473 } 474 475 /** 476 * Initializes a #graphene_matrix_t with the identity matrix. 477 * 478 * Returns: the initialized matrix 479 * 480 * Since: 1.0 481 */ 482 public Matrix initIdentity() 483 { 484 auto __p = graphene_matrix_init_identity(graphene_matrix); 485 486 if(__p is null) 487 { 488 return null; 489 } 490 491 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 492 } 493 494 /** 495 * Initializes a #graphene_matrix_t so that it positions the "camera" 496 * at the given @eye coordinates towards an object at the @center 497 * coordinates. The top of the camera is aligned to the direction 498 * of the @up vector. 499 * 500 * Before the transform, the camera is assumed to be placed at the 501 * origin, looking towards the negative Z axis, with the top side of 502 * the camera facing in the direction of the Y axis and the right 503 * side in the direction of the X axis. 504 * 505 * In theory, one could use @m to transform a model of such a camera 506 * into world-space. However, it is more common to use the inverse of 507 * @m to transform another object from world coordinates to the view 508 * coordinates of the camera. Typically you would then apply the 509 * camera projection transform to get from view to screen 510 * coordinates. 511 * 512 * Params: 513 * eye = the vector describing the position to look from 514 * center = the vector describing the position to look at 515 * up = the vector describing the world's upward direction; usually, 516 * this is the graphene_vec3_y_axis() vector 517 * 518 * Returns: the initialized matrix 519 * 520 * Since: 1.0 521 */ 522 public Matrix initLookAt(Vec3 eye, Vec3 center, Vec3 up) 523 { 524 auto __p = graphene_matrix_init_look_at(graphene_matrix, (eye is null) ? null : eye.getVec3Struct(), (center is null) ? null : center.getVec3Struct(), (up is null) ? null : up.getVec3Struct()); 525 526 if(__p is null) 527 { 528 return null; 529 } 530 531 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 532 } 533 534 /** 535 * Initializes a #graphene_matrix_t with an orthographic projection. 536 * 537 * Params: 538 * left = the left edge of the clipping plane 539 * right = the right edge of the clipping plane 540 * top = the top edge of the clipping plane 541 * bottom = the bottom edge of the clipping plane 542 * zNear = the distance of the near clipping plane 543 * zFar = the distance of the far clipping plane 544 * 545 * Returns: the initialized matrix 546 * 547 * Since: 1.0 548 */ 549 public Matrix initOrtho(float left, float right, float top, float bottom, float zNear, float zFar) 550 { 551 auto __p = graphene_matrix_init_ortho(graphene_matrix, left, right, top, bottom, zNear, zFar); 552 553 if(__p is null) 554 { 555 return null; 556 } 557 558 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 559 } 560 561 /** 562 * Initializes a #graphene_matrix_t with a perspective projection. 563 * 564 * Params: 565 * fovy = the field of view angle, in degrees 566 * aspect = the aspect value 567 * zNear = the near Z plane 568 * zFar = the far Z plane 569 * 570 * Returns: the initialized matrix 571 * 572 * Since: 1.0 573 */ 574 public Matrix initPerspective(float fovy, float aspect, float zNear, float zFar) 575 { 576 auto __p = graphene_matrix_init_perspective(graphene_matrix, fovy, aspect, zNear, zFar); 577 578 if(__p is null) 579 { 580 return null; 581 } 582 583 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 584 } 585 586 /** 587 * Initializes @m to represent a rotation of @angle degrees on 588 * the axis represented by the @axis vector. 589 * 590 * Params: 591 * angle = the rotation angle, in degrees 592 * axis = the axis vector as a #graphene_vec3_t 593 * 594 * Returns: the initialized matrix 595 * 596 * Since: 1.0 597 */ 598 public Matrix initRotate(float angle, Vec3 axis) 599 { 600 auto __p = graphene_matrix_init_rotate(graphene_matrix, angle, (axis is null) ? null : axis.getVec3Struct()); 601 602 if(__p is null) 603 { 604 return null; 605 } 606 607 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 608 } 609 610 /** 611 * Initializes a #graphene_matrix_t with the given scaling factors. 612 * 613 * Params: 614 * x = the scale factor on the X axis 615 * y = the scale factor on the Y axis 616 * z = the scale factor on the Z axis 617 * 618 * Returns: the initialized matrix 619 * 620 * Since: 1.0 621 */ 622 public Matrix initScale(float x, float y, float z) 623 { 624 auto __p = graphene_matrix_init_scale(graphene_matrix, x, y, z); 625 626 if(__p is null) 627 { 628 return null; 629 } 630 631 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 632 } 633 634 /** 635 * Initializes a #graphene_matrix_t with a skew transformation 636 * with the given factors. 637 * 638 * Params: 639 * xSkew = skew factor, in radians, on the X axis 640 * ySkew = skew factor, in radians, on the Y axis 641 * 642 * Returns: the initialized matrix 643 * 644 * Since: 1.0 645 */ 646 public Matrix initSkew(float xSkew, float ySkew) 647 { 648 auto __p = graphene_matrix_init_skew(graphene_matrix, xSkew, ySkew); 649 650 if(__p is null) 651 { 652 return null; 653 } 654 655 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 656 } 657 658 /** 659 * Initializes a #graphene_matrix_t with a translation to the 660 * given coordinates. 661 * 662 * Params: 663 * p = the translation coordinates 664 * 665 * Returns: the initialized matrix 666 * 667 * Since: 1.0 668 */ 669 public Matrix initTranslate(Point3D p) 670 { 671 auto __p = graphene_matrix_init_translate(graphene_matrix, (p is null) ? null : p.getPoint3DStruct()); 672 673 if(__p is null) 674 { 675 return null; 676 } 677 678 return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p); 679 } 680 681 /** 682 * Linearly interpolates the two given #graphene_matrix_t by 683 * interpolating the decomposed transformations separately. 684 * 685 * If either matrix cannot be reduced to their transformations 686 * then the interpolation cannot be performed, and this function 687 * will return an identity matrix. 688 * 689 * Params: 690 * b = a #graphene_matrix_t 691 * factor = the linear interpolation factor 692 * res = return location for the 693 * interpolated matrix 694 * 695 * Since: 1.0 696 */ 697 public void interpolate(Matrix b, double factor, out Matrix res) 698 { 699 graphene_matrix_t* outres = sliceNew!graphene_matrix_t(); 700 701 graphene_matrix_interpolate(graphene_matrix, (b is null) ? null : b.getMatrixStruct(), factor, outres); 702 703 res = ObjectG.getDObject!(Matrix)(outres, true); 704 } 705 706 /** 707 * Inverts the given matrix. 708 * 709 * Params: 710 * res = return location for the 711 * inverse matrix 712 * 713 * Returns: `true` if the matrix is invertible 714 * 715 * Since: 1.0 716 */ 717 public bool inverse(out Matrix res) 718 { 719 graphene_matrix_t* outres = sliceNew!graphene_matrix_t(); 720 721 auto __p = graphene_matrix_inverse(graphene_matrix, outres) != 0; 722 723 res = ObjectG.getDObject!(Matrix)(outres, true); 724 725 return __p; 726 } 727 728 /** 729 * Checks whether the given #graphene_matrix_t is compatible with an 730 * a 2D affine transformation matrix. 731 * 732 * Returns: `true` if the matrix is compatible with an affine 733 * transformation matrix 734 * 735 * Since: 1.0 736 */ 737 public bool is2d() 738 { 739 return graphene_matrix_is_2d(graphene_matrix) != 0; 740 } 741 742 /** 743 * Checks whether a #graphene_matrix_t has a visible back face. 744 * 745 * Returns: `true` if the back face of the matrix is visible 746 * 747 * Since: 1.0 748 */ 749 public bool isBackfaceVisible() 750 { 751 return graphene_matrix_is_backface_visible(graphene_matrix) != 0; 752 } 753 754 /** 755 * Checks whether the given #graphene_matrix_t is the identity matrix. 756 * 757 * Returns: `true` if the matrix is the identity matrix 758 * 759 * Since: 1.0 760 */ 761 public bool isIdentity() 762 { 763 return graphene_matrix_is_identity(graphene_matrix) != 0; 764 } 765 766 /** 767 * Checks whether a matrix is singular. 768 * 769 * Returns: `true` if the matrix is singular 770 * 771 * Since: 1.0 772 */ 773 public bool isSingular() 774 { 775 return graphene_matrix_is_singular(graphene_matrix) != 0; 776 } 777 778 /** 779 * Multiplies two #graphene_matrix_t. 780 * 781 * Matrix multiplication is not commutative in general; the order of the factors matters. 782 * The product of this multiplication is (@a × @b) 783 * 784 * Params: 785 * b = a #graphene_matrix_t 786 * res = return location for the matrix 787 * result 788 * 789 * Since: 1.0 790 */ 791 public void multiply(Matrix b, out Matrix res) 792 { 793 graphene_matrix_t* outres = sliceNew!graphene_matrix_t(); 794 795 graphene_matrix_multiply(graphene_matrix, (b is null) ? null : b.getMatrixStruct(), outres); 796 797 res = ObjectG.getDObject!(Matrix)(outres, true); 798 } 799 800 /** 801 * Compares the two given #graphene_matrix_t matrices and checks 802 * whether their values are within the given @epsilon of each 803 * other. 804 * 805 * Params: 806 * b = a #graphene_matrix_t 807 * epsilon = the threshold between the two matrices 808 * 809 * Returns: `true` if the two matrices are near each other, and 810 * `false` otherwise 811 * 812 * Since: 1.10 813 */ 814 public bool near(Matrix b, float epsilon) 815 { 816 return graphene_matrix_near(graphene_matrix, (b is null) ? null : b.getMatrixStruct(), epsilon) != 0; 817 } 818 819 /** 820 * Normalizes the given #graphene_matrix_t. 821 * 822 * Params: 823 * res = return location for the normalized matrix 824 * 825 * Since: 1.0 826 */ 827 public void normalize(out Matrix res) 828 { 829 graphene_matrix_t* outres = sliceNew!graphene_matrix_t(); 830 831 graphene_matrix_normalize(graphene_matrix, outres); 832 833 res = ObjectG.getDObject!(Matrix)(outres, true); 834 } 835 836 /** 837 * Applies a perspective of @depth to the matrix. 838 * 839 * Params: 840 * depth = the depth of the perspective 841 * res = return location for the 842 * perspective matrix 843 * 844 * Since: 1.0 845 */ 846 public void perspective(float depth, out Matrix res) 847 { 848 graphene_matrix_t* outres = sliceNew!graphene_matrix_t(); 849 850 graphene_matrix_perspective(graphene_matrix, depth, outres); 851 852 res = ObjectG.getDObject!(Matrix)(outres, true); 853 } 854 855 /** 856 * Prints the contents of a matrix to the standard error stream. 857 * 858 * This function is only useful for debugging; there are no guarantees 859 * made on the format of the output. 860 * 861 * Since: 1.0 862 */ 863 public void print() 864 { 865 graphene_matrix_print(graphene_matrix); 866 } 867 868 /** 869 * Projects a #graphene_point_t using the matrix @m. 870 * 871 * Params: 872 * p = a #graphene_point_t 873 * res = return location for the projected 874 * point 875 * 876 * Since: 1.0 877 */ 878 public void projectPoint(Point p, out Point res) 879 { 880 graphene_point_t* outres = sliceNew!graphene_point_t(); 881 882 graphene_matrix_project_point(graphene_matrix, (p is null) ? null : p.getPointStruct(), outres); 883 884 res = ObjectG.getDObject!(Point)(outres, true); 885 } 886 887 /** 888 * Projects all corners of a #graphene_rect_t using the given matrix. 889 * 890 * See also: graphene_matrix_project_point() 891 * 892 * Params: 893 * r = a #graphene_rect_t 894 * res = return location for the projected 895 * rectangle 896 * 897 * Since: 1.2 898 */ 899 public void projectRect(Rect r, out Quad res) 900 { 901 graphene_quad_t* outres = sliceNew!graphene_quad_t(); 902 903 graphene_matrix_project_rect(graphene_matrix, (r is null) ? null : r.getRectStruct(), outres); 904 905 res = ObjectG.getDObject!(Quad)(outres, true); 906 } 907 908 /** 909 * Projects a #graphene_rect_t using the given matrix. 910 * 911 * The resulting rectangle is the axis aligned bounding rectangle capable 912 * of fully containing the projected rectangle. 913 * 914 * Params: 915 * r = a #graphene_rect_t 916 * res = return location for the projected 917 * rectangle 918 * 919 * Since: 1.0 920 */ 921 public void projectRectBounds(Rect r, out Rect res) 922 { 923 graphene_rect_t* outres = sliceNew!graphene_rect_t(); 924 925 graphene_matrix_project_rect_bounds(graphene_matrix, (r is null) ? null : r.getRectStruct(), outres); 926 927 res = ObjectG.getDObject!(Rect)(outres, true); 928 } 929 930 /** 931 * Adds a rotation transformation to @m, using the given @angle 932 * and @axis vector. 933 * 934 * This is the equivalent of calling graphene_matrix_init_rotate() and 935 * then multiplying the matrix @m with the rotation matrix. 936 * 937 * Params: 938 * angle = the rotation angle, in degrees 939 * axis = the rotation axis, as a #graphene_vec3_t 940 * 941 * Since: 1.0 942 */ 943 public void rotate(float angle, Vec3 axis) 944 { 945 graphene_matrix_rotate(graphene_matrix, angle, (axis is null) ? null : axis.getVec3Struct()); 946 } 947 948 /** 949 * Adds a rotation transformation to @m, using the given 950 * #graphene_euler_t. 951 * 952 * Params: 953 * e = a rotation described by a #graphene_euler_t 954 * 955 * Since: 1.2 956 */ 957 public void rotateEuler(Euler e) 958 { 959 graphene_matrix_rotate_euler(graphene_matrix, (e is null) ? null : e.getEulerStruct()); 960 } 961 962 /** 963 * Adds a rotation transformation to @m, using the given 964 * #graphene_quaternion_t. 965 * 966 * This is the equivalent of calling graphene_quaternion_to_matrix() and 967 * then multiplying @m with the rotation matrix. 968 * 969 * Params: 970 * q = a rotation described by a #graphene_quaternion_t 971 * 972 * Since: 1.2 973 */ 974 public void rotateQuaternion(Quaternion q) 975 { 976 graphene_matrix_rotate_quaternion(graphene_matrix, (q is null) ? null : q.getQuaternionStruct()); 977 } 978 979 /** 980 * Adds a rotation transformation around the X axis to @m, using 981 * the given @angle. 982 * 983 * See also: graphene_matrix_rotate() 984 * 985 * Params: 986 * angle = the rotation angle, in degrees 987 * 988 * Since: 1.0 989 */ 990 public void rotateX(float angle) 991 { 992 graphene_matrix_rotate_x(graphene_matrix, angle); 993 } 994 995 /** 996 * Adds a rotation transformation around the Y axis to @m, using 997 * the given @angle. 998 * 999 * See also: graphene_matrix_rotate() 1000 * 1001 * Params: 1002 * angle = the rotation angle, in degrees 1003 * 1004 * Since: 1.0 1005 */ 1006 public void rotateY(float angle) 1007 { 1008 graphene_matrix_rotate_y(graphene_matrix, angle); 1009 } 1010 1011 /** 1012 * Adds a rotation transformation around the Z axis to @m, using 1013 * the given @angle. 1014 * 1015 * See also: graphene_matrix_rotate() 1016 * 1017 * Params: 1018 * angle = the rotation angle, in degrees 1019 * 1020 * Since: 1.0 1021 */ 1022 public void rotateZ(float angle) 1023 { 1024 graphene_matrix_rotate_z(graphene_matrix, angle); 1025 } 1026 1027 /** 1028 * Adds a scaling transformation to @m, using the three 1029 * given factors. 1030 * 1031 * This is the equivalent of calling graphene_matrix_init_scale() and then 1032 * multiplying the matrix @m with the scale matrix. 1033 * 1034 * Params: 1035 * factorX = scaling factor on the X axis 1036 * factorY = scaling factor on the Y axis 1037 * factorZ = scaling factor on the Z axis 1038 * 1039 * Since: 1.0 1040 */ 1041 public void scale(float factorX, float factorY, float factorZ) 1042 { 1043 graphene_matrix_scale(graphene_matrix, factorX, factorY, factorZ); 1044 } 1045 1046 /** 1047 * Adds a skew of @factor on the X and Y axis to the given matrix. 1048 * 1049 * Params: 1050 * factor = skew factor 1051 * 1052 * Since: 1.0 1053 */ 1054 public void skewXy(float factor) 1055 { 1056 graphene_matrix_skew_xy(graphene_matrix, factor); 1057 } 1058 1059 /** 1060 * Adds a skew of @factor on the X and Z axis to the given matrix. 1061 * 1062 * Params: 1063 * factor = skew factor 1064 * 1065 * Since: 1.0 1066 */ 1067 public void skewXz(float factor) 1068 { 1069 graphene_matrix_skew_xz(graphene_matrix, factor); 1070 } 1071 1072 /** 1073 * Adds a skew of @factor on the Y and Z axis to the given matrix. 1074 * 1075 * Params: 1076 * factor = skew factor 1077 * 1078 * Since: 1.0 1079 */ 1080 public void skewYz(float factor) 1081 { 1082 graphene_matrix_skew_yz(graphene_matrix, factor); 1083 } 1084 1085 /** 1086 * Converts a #graphene_matrix_t to an affine transformation 1087 * matrix, if the given matrix is compatible. 1088 * 1089 * The returned values have the following layout: 1090 * 1091 * |[<!-- language="plain" --> 1092 * ⎛ xx yx ⎞ ⎛ a b 0 ⎞ 1093 * ⎜ xy yy ⎟ = ⎜ c d 0 ⎟ 1094 * ⎝ x0 y0 ⎠ ⎝ tx ty 1 ⎠ 1095 * ]| 1096 * 1097 * This function can be used to convert between a #graphene_matrix_t 1098 * and an affine matrix type from other libraries. 1099 * 1100 * Params: 1101 * xx = return location for the xx member 1102 * yx = return location for the yx member 1103 * xy = return location for the xy member 1104 * yy = return location for the yy member 1105 * x0 = return location for the x0 member 1106 * y0 = return location for the y0 member 1107 * 1108 * Returns: `true` if the matrix is compatible with an affine 1109 * transformation matrix 1110 * 1111 * Since: 1.0 1112 */ 1113 public bool to2d(out double xx, out double yx, out double xy, out double yy, out double x0, out double y0) 1114 { 1115 return graphene_matrix_to_2d(graphene_matrix, &xx, &yx, &xy, &yy, &x0, &y0) != 0; 1116 } 1117 1118 /** 1119 * Converts a #graphene_matrix_t to an array of floating point 1120 * values. 1121 * 1122 * Params: 1123 * v = return location 1124 * for an array of floating point values. The array must be capable 1125 * of holding at least 16 values. 1126 * 1127 * Since: 1.0 1128 */ 1129 public void toFloat(out float[16] v) 1130 { 1131 float[16] outv; 1132 1133 graphene_matrix_to_float(graphene_matrix, outv.ptr); 1134 1135 v = outv[0 .. 16]; 1136 } 1137 1138 /** 1139 * Transforms each corner of a #graphene_rect_t using the given matrix @m. 1140 * 1141 * The result is the axis aligned bounding rectangle containing the coplanar 1142 * quadrilateral. 1143 * 1144 * See also: graphene_matrix_transform_point() 1145 * 1146 * Params: 1147 * r = a #graphene_rect_t 1148 * res = return location for the bounds 1149 * of the transformed rectangle 1150 * 1151 * Since: 1.0 1152 */ 1153 public void transformBounds(Rect r, out Rect res) 1154 { 1155 graphene_rect_t* outres = sliceNew!graphene_rect_t(); 1156 1157 graphene_matrix_transform_bounds(graphene_matrix, (r is null) ? null : r.getRectStruct(), outres); 1158 1159 res = ObjectG.getDObject!(Rect)(outres, true); 1160 } 1161 1162 /** 1163 * Transforms the vertices of a #graphene_box_t using the given matrix @m. 1164 * 1165 * The result is the axis aligned bounding box containing the transformed 1166 * vertices. 1167 * 1168 * Params: 1169 * b = a #graphene_box_t 1170 * res = return location for the bounds 1171 * of the transformed box 1172 * 1173 * Since: 1.2 1174 */ 1175 public void transformBox(Box b, out Box res) 1176 { 1177 graphene_box_t* outres = sliceNew!graphene_box_t(); 1178 1179 graphene_matrix_transform_box(graphene_matrix, (b is null) ? null : b.getBoxStruct(), outres); 1180 1181 res = ObjectG.getDObject!(Box)(outres, true); 1182 } 1183 1184 /** 1185 * Transforms the given #graphene_point_t using the matrix @m. 1186 * 1187 * Unlike graphene_matrix_transform_vec3(), this function will take into 1188 * account the fourth row vector of the #graphene_matrix_t when computing 1189 * the dot product of each row vector of the matrix. 1190 * 1191 * See also: graphene_simd4x4f_point3_mul() 1192 * 1193 * Params: 1194 * p = a #graphene_point_t 1195 * res = return location for the 1196 * transformed #graphene_point_t 1197 * 1198 * Since: 1.0 1199 */ 1200 public void transformPoint(Point p, out Point res) 1201 { 1202 graphene_point_t* outres = sliceNew!graphene_point_t(); 1203 1204 graphene_matrix_transform_point(graphene_matrix, (p is null) ? null : p.getPointStruct(), outres); 1205 1206 res = ObjectG.getDObject!(Point)(outres, true); 1207 } 1208 1209 /** 1210 * Transforms the given #graphene_point3d_t using the matrix @m. 1211 * 1212 * Unlike graphene_matrix_transform_vec3(), this function will take into 1213 * account the fourth row vector of the #graphene_matrix_t when computing 1214 * the dot product of each row vector of the matrix. 1215 * 1216 * See also: graphene_simd4x4f_point3_mul() 1217 * 1218 * Params: 1219 * p = a #graphene_point3d_t 1220 * res = return location for the result 1221 * 1222 * Since: 1.2 1223 */ 1224 public void transformPoint3d(Point3D p, out Point3D res) 1225 { 1226 graphene_point3d_t* outres = sliceNew!graphene_point3d_t(); 1227 1228 graphene_matrix_transform_point3d(graphene_matrix, (p is null) ? null : p.getPoint3DStruct(), outres); 1229 1230 res = ObjectG.getDObject!(Point3D)(outres, true); 1231 } 1232 1233 /** 1234 * Transform a #graphene_ray_t using the given matrix @m. 1235 * 1236 * Params: 1237 * r = a #graphene_ray_t 1238 * res = return location for the 1239 * transformed ray 1240 * 1241 * Since: 1.4 1242 */ 1243 public void transformRay(Ray r, out Ray res) 1244 { 1245 graphene_ray_t* outres = sliceNew!graphene_ray_t(); 1246 1247 graphene_matrix_transform_ray(graphene_matrix, (r is null) ? null : r.getRayStruct(), outres); 1248 1249 res = ObjectG.getDObject!(Ray)(outres, true); 1250 } 1251 1252 /** 1253 * Transforms each corner of a #graphene_rect_t using the given matrix @m. 1254 * 1255 * The result is a coplanar quadrilateral. 1256 * 1257 * See also: graphene_matrix_transform_point() 1258 * 1259 * Params: 1260 * r = a #graphene_rect_t 1261 * res = return location for the 1262 * transformed quad 1263 * 1264 * Since: 1.0 1265 */ 1266 public void transformRect(Rect r, out Quad res) 1267 { 1268 graphene_quad_t* outres = sliceNew!graphene_quad_t(); 1269 1270 graphene_matrix_transform_rect(graphene_matrix, (r is null) ? null : r.getRectStruct(), outres); 1271 1272 res = ObjectG.getDObject!(Quad)(outres, true); 1273 } 1274 1275 /** 1276 * Transforms a #graphene_sphere_t using the given matrix @m. The 1277 * result is the bounding sphere containing the transformed sphere. 1278 * 1279 * Params: 1280 * s = a #graphene_sphere_t 1281 * res = return location for the bounds 1282 * of the transformed sphere 1283 * 1284 * Since: 1.2 1285 */ 1286 public void transformSphere(Sphere s, out Sphere res) 1287 { 1288 graphene_sphere_t* outres = sliceNew!graphene_sphere_t(); 1289 1290 graphene_matrix_transform_sphere(graphene_matrix, (s is null) ? null : s.getSphereStruct(), outres); 1291 1292 res = ObjectG.getDObject!(Sphere)(outres, true); 1293 } 1294 1295 /** 1296 * Transforms the given #graphene_vec3_t using the matrix @m. 1297 * 1298 * This function will multiply the X, Y, and Z row vectors of the matrix @m 1299 * with the corresponding components of the vector @v. The W row vector will 1300 * be ignored. 1301 * 1302 * See also: graphene_simd4x4f_vec3_mul() 1303 * 1304 * Params: 1305 * v = a #graphene_vec3_t 1306 * res = return location for a #graphene_vec3_t 1307 * 1308 * Since: 1.0 1309 */ 1310 public void transformVec3(Vec3 v, out Vec3 res) 1311 { 1312 graphene_vec3_t* outres = sliceNew!graphene_vec3_t(); 1313 1314 graphene_matrix_transform_vec3(graphene_matrix, (v is null) ? null : v.getVec3Struct(), outres); 1315 1316 res = ObjectG.getDObject!(Vec3)(outres, true); 1317 } 1318 1319 /** 1320 * Transforms the given #graphene_vec4_t using the matrix @m. 1321 * 1322 * See also: graphene_simd4x4f_vec4_mul() 1323 * 1324 * Params: 1325 * v = a #graphene_vec4_t 1326 * res = return location for a #graphene_vec4_t 1327 * 1328 * Since: 1.0 1329 */ 1330 public void transformVec4(Vec4 v, out Vec4 res) 1331 { 1332 graphene_vec4_t* outres = sliceNew!graphene_vec4_t(); 1333 1334 graphene_matrix_transform_vec4(graphene_matrix, (v is null) ? null : v.getVec4Struct(), outres); 1335 1336 res = ObjectG.getDObject!(Vec4)(outres, true); 1337 } 1338 1339 /** 1340 * Adds a translation transformation to @m using the coordinates 1341 * of the given #graphene_point3d_t. 1342 * 1343 * This is the equivalent of calling graphene_matrix_init_translate() and 1344 * then multiplying @m with the translation matrix. 1345 * 1346 * Params: 1347 * pos = a #graphene_point3d_t 1348 * 1349 * Since: 1.0 1350 */ 1351 public void translate(Point3D pos) 1352 { 1353 graphene_matrix_translate(graphene_matrix, (pos is null) ? null : pos.getPoint3DStruct()); 1354 } 1355 1356 /** 1357 * Transposes the given matrix. 1358 * 1359 * Params: 1360 * res = return location for the 1361 * transposed matrix 1362 * 1363 * Since: 1.0 1364 */ 1365 public void transpose(out Matrix res) 1366 { 1367 graphene_matrix_t* outres = sliceNew!graphene_matrix_t(); 1368 1369 graphene_matrix_transpose(graphene_matrix, outres); 1370 1371 res = ObjectG.getDObject!(Matrix)(outres, true); 1372 } 1373 1374 /** 1375 * Unprojects the given @point using the @projection matrix and 1376 * a @modelview matrix. 1377 * 1378 * Params: 1379 * modelview = a #graphene_matrix_t for the modelview matrix; this is 1380 * the inverse of the modelview used when projecting the point 1381 * point = a #graphene_point3d_t with the coordinates of the point 1382 * res = return location for the unprojected 1383 * point 1384 * 1385 * Since: 1.2 1386 */ 1387 public void unprojectPoint3d(Matrix modelview, Point3D point, out Point3D res) 1388 { 1389 graphene_point3d_t* outres = sliceNew!graphene_point3d_t(); 1390 1391 graphene_matrix_unproject_point3d(graphene_matrix, (modelview is null) ? null : modelview.getMatrixStruct(), (point is null) ? null : point.getPoint3DStruct(), outres); 1392 1393 res = ObjectG.getDObject!(Point3D)(outres, true); 1394 } 1395 1396 /** 1397 * Undoes the transformation on the corners of a #graphene_rect_t using the 1398 * given matrix, within the given axis aligned rectangular @bounds. 1399 * 1400 * Params: 1401 * r = a #graphene_rect_t 1402 * bounds = the bounds of the transformation 1403 * res = return location for the 1404 * untransformed rectangle 1405 * 1406 * Since: 1.0 1407 */ 1408 public void untransformBounds(Rect r, Rect bounds, out Rect res) 1409 { 1410 graphene_rect_t* outres = sliceNew!graphene_rect_t(); 1411 1412 graphene_matrix_untransform_bounds(graphene_matrix, (r is null) ? null : r.getRectStruct(), (bounds is null) ? null : bounds.getRectStruct(), outres); 1413 1414 res = ObjectG.getDObject!(Rect)(outres, true); 1415 } 1416 1417 /** 1418 * Undoes the transformation of a #graphene_point_t using the 1419 * given matrix, within the given axis aligned rectangular @bounds. 1420 * 1421 * Params: 1422 * p = a #graphene_point_t 1423 * bounds = the bounds of the transformation 1424 * res = return location for the 1425 * untransformed point 1426 * 1427 * Returns: `true` if the point was successfully untransformed 1428 * 1429 * Since: 1.0 1430 */ 1431 public bool untransformPoint(Point p, Rect bounds, out Point res) 1432 { 1433 graphene_point_t* outres = sliceNew!graphene_point_t(); 1434 1435 auto __p = graphene_matrix_untransform_point(graphene_matrix, (p is null) ? null : p.getPointStruct(), (bounds is null) ? null : bounds.getRectStruct(), outres) != 0; 1436 1437 res = ObjectG.getDObject!(Point)(outres, true); 1438 1439 return __p; 1440 } 1441 }