The open source OpenXR runtime
at prediction-2 883 lines 20 kB view raw
1// Copyright 2019-2021, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief C interface to math library. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @author Moshi Turner <moshiturner@protonmail.com> 8 * @author Nis Madsen <nima_zero_one@protonmail.com> 9 * 10 * @see xrt_vec3 11 * @see xrt_quat 12 * @see xrt_pose 13 * @see xrt_space_relation 14 * @ingroup aux_math 15 */ 16 17#pragma once 18 19#include "xrt/xrt_defines.h" 20 21#ifdef __cplusplus 22extern "C" { 23#endif 24 25 26/*! 27 * @defgroup aux_math Math 28 * @ingroup aux 29 * 30 * @brief C interface to some transform-related math functions. 31 */ 32 33/*! 34 * @dir auxiliary/math 35 * @ingroup aux 36 * 37 * @brief C interface to some transform-related math functions. 38 */ 39 40/* 41 * 42 * Defines. 43 * 44 */ 45 46/*! 47 * Standard gravity acceleration constant. 48 * 49 * @ingroup aux_math 50 */ 51#define MATH_GRAVITY_M_S2 (9.8066) 52 53/*! 54 * Minimum of A and B. 55 * 56 * @ingroup aux_math 57 */ 58#ifndef MIN // Avoid clash with OpenCV def 59#define MIN(A, B) ((A) < (B) ? (A) : (B)) 60#endif 61 62/*! 63 * Maximum of A and B. 64 * 65 * @ingroup aux_math 66 */ 67#ifndef MAX // Avoid clash with OpenCV def 68#define MAX(A, B) ((A) > (B) ? (A) : (B)) 69#endif 70 71/*! 72 * X clamped to the range [A, B]. 73 * 74 * @ingroup aux_math 75 */ 76#define CLAMP(X, A, B) (MIN(MAX((X), (A)), (B))) 77 78 79/* 80 * 81 * Hash functions. 82 * 83 */ 84 85/*! 86 * Generate a hash value from the given string, trailing zero not included. 87 * 88 * Hashing function used is not specified so no guarantee of staying the same 89 * between different versions of the software, or even when the same version 90 * is compiled on different platforms/libc++ as it might use std::hash. 91 * 92 * @ingroup aux_math 93 */ 94size_t 95math_hash_string(const char *str_c, size_t length); 96 97 98/* 99 * 100 * Vector functions 101 * 102 */ 103 104/*! 105 * Check if this vec3 is valid for math operations. 106 * 107 * @relates xrt_vec3 108 * @ingroup aux_math 109 */ 110bool 111math_vec3_validate(const struct xrt_vec3 *vec3); 112 113/*! 114 * Accumulate a vector by adding in-place. 115 * 116 * Logically, *inAndOut += *additional 117 * OK if the two arguments are the same addresses. 118 * 119 * @relates xrt_vec3 120 * @ingroup aux_math 121 */ 122void 123math_vec3_accum(const struct xrt_vec3 *additional, struct xrt_vec3 *inAndOut); 124 125/*! 126 * Subtract from a vector in-place. 127 * 128 * Logically, *inAndOut -= *subtrahend 129 * OK if the two arguments are the same addresses. 130 * 131 * @relates xrt_vec3 132 * @ingroup aux_math 133 */ 134void 135math_vec3_subtract(const struct xrt_vec3 *subtrahend, struct xrt_vec3 *inAndOut); 136 137/*! 138 * Multiply a vector in-place. 139 * 140 * Logically, *inAndOut *= scalar 141 * 142 * @relates xrt_vec3 143 * @ingroup aux_math 144 */ 145void 146math_vec3_scalar_mul(float scalar, struct xrt_vec3 *inAndOut); 147 148/*! 149 * Cross product of a vector. 150 * 151 * @relates xrt_vec3 152 * @ingroup aux_math 153 */ 154void 155math_vec3_cross(const struct xrt_vec3 *l, const struct xrt_vec3 *r, struct xrt_vec3 *result); 156 157/*! 158 * Get translation vector from isometry matrix (col-major). 159 * 160 * @relates xrt_vec3 161 * @ingroup aux_math 162 */ 163void 164math_vec3_translation_from_isometry(const struct xrt_matrix_4x4 *isometry, struct xrt_vec3 *result); 165 166/*! 167 * Normalize a vec3 in place. 168 * 169 * @relates xrt_vec3 170 * @ingroup aux_math 171 */ 172void 173math_vec3_normalize(struct xrt_vec3 *in); 174 175 176/* 177 * 178 * 64 bit vector functions. 179 * 180 */ 181 182/*! 183 * Cross product of a vec3_f64. 184 * 185 * @relates xrt_vec3_f64 186 * @ingroup aux_math 187 */ 188void 189math_vec3_f64_cross(const struct xrt_vec3_f64 *l, const struct xrt_vec3_f64 *r, struct xrt_vec3_f64 *result); 190 191/*! 192 * Normalize a vec3_f64 in place. 193 * 194 * @relates xrt_vec3_f64 195 * @ingroup aux_math 196 */ 197void 198math_vec3_f64_normalize(struct xrt_vec3_f64 *in); 199 200 201/* 202 * 203 * Quat functions. 204 * 205 */ 206 207/*! 208 * Create a rotation from an angle in radians and a unit vector. 209 * 210 * @relates xrt_quat 211 * @see xrt_vec3 212 * @ingroup aux_math 213 */ 214void 215math_quat_from_angle_vector(float angle_rads, const struct xrt_vec3 *vector, struct xrt_quat *result); 216 217/*! 218 * Create a rotation from euler angles to a quaternion 219 * @relates xrt_quat 220 * @ingroup aux_math 221 */ 222void 223math_quat_from_euler_angles(const struct xrt_vec3 *angles, struct xrt_quat *result); 224 225/*! 226 * Create a rotation from a quaternion to euler angles 227 * @relates xrt_quat 228 * @ingroup aux_math 229 */ 230void 231math_quat_to_euler_angles(const struct xrt_quat *quat, struct xrt_vec3 *euler_angles); 232 233/*! 234 * Create a rotation from a 3x3 rotation (row major) matrix. 235 * 236 * @relates xrt_quat 237 * @see xrt_matrix_3x3 238 * @ingroup aux_math 239 */ 240void 241math_quat_from_matrix_3x3(const struct xrt_matrix_3x3 *mat, struct xrt_quat *result); 242 243/*! 244 * Create a rotation from two vectors plus x and z, by creating a rotation 245 * matrix by crossing z and x to get the y axis. 246 * 247 * Input vectors should be normalized. 248 * 249 * @relates xrt_quat 250 * @see xrt_vec3 251 * @ingroup aux_math 252 */ 253void 254math_quat_from_plus_x_z(const struct xrt_vec3 *plus_x, const struct xrt_vec3 *plus_z, struct xrt_quat *result); 255 256/*! 257 * Create a rotation from two vectors vec_a and vec_b that would 258 * rotate vec_a into vec_b 259 * 260 * @relates xrt_quat 261 * @see xrt_vec3 262 * @ingroup aux_math 263 */ 264void 265math_quat_from_vec_a_to_vec_b(const struct xrt_vec3 *vec_a, const struct xrt_vec3 *vec_b, struct xrt_quat *result); 266 267/*! 268 * Check if this quat can be used in transformation operations. 269 * 270 * @relates xrt_quat 271 * @ingroup aux_math 272 */ 273bool 274math_quat_validate(const struct xrt_quat *quat); 275 276/*! 277 * Check if this quat is within 1% of unit length. 278 * 279 * @relates xrt_quat 280 * @ingroup aux_math 281 */ 282bool 283math_quat_validate_within_1_percent(const struct xrt_quat *quat); 284 285/*! 286 * Invert a quaternion. 287 * 288 * @relates xrt_quat 289 * @ingroup aux_math 290 */ 291void 292math_quat_invert(const struct xrt_quat *quat, struct xrt_quat *out_quat); 293 294/*! 295 * The euclidean norm or length of a quaternion. Same as if it were a vec4. 296 * 297 * @relates xrt_quat 298 * @ingroup aux_math 299 */ 300float 301math_quat_len(const struct xrt_quat *quat); 302 303/*! 304 * The dot product of 2 quaternions. It has a analogous interpretation 305 * as for vec3. For unit quaternions, it provides cos(theta) of the 306 * angle between the 2 quaternion rotations. 307 * 308 * @relates xrt_quat 309 * @ingroup aux_math 310 */ 311static inline float 312math_quat_dot(const struct xrt_quat *l, const struct xrt_quat *r) 313{ 314 return l->x * r->x + l->y * r->y + l->z * r->z + l->w * r->w; 315} 316 317/*! 318 * Normalize a quaternion. 319 * 320 * @relates xrt_quat 321 * @ingroup aux_math 322 */ 323void 324math_quat_normalize(struct xrt_quat *inout); 325 326/*! 327 * Normalizes a quaternion if it has accumulated float precision errors. 328 * Returns true if the quaternion was already normalized or was normalized after 329 * being found within a small float precision tolerance. 330 * Returns false if the quaternion was not at all normalized. 331 * 332 * @relates xrt_quat 333 * @ingroup aux_math 334 */ 335bool 336math_quat_ensure_normalized(struct xrt_quat *inout); 337 338/*! 339 * Rotate a vector. 340 * 341 * @relates xrt_quat 342 * @see xrt_vec3 343 * @ingroup aux_math 344 */ 345void 346math_quat_rotate_vec3(const struct xrt_quat *left, const struct xrt_vec3 *right, struct xrt_vec3 *result); 347 348/*! 349 * Rotate a quaternion (compose rotations). 350 * 351 * @relates xrt_quat 352 * @ingroup aux_math 353 */ 354void 355math_quat_rotate(const struct xrt_quat *left, const struct xrt_quat *right, struct xrt_quat *result); 356 357/*! 358 * Inverse of @ref math_quat_rotate. Removes @p left rotation from @p right. 359 * 360 * @relates xrt_quat 361 * @ingroup aux_math 362 */ 363void 364math_quat_unrotate(const struct xrt_quat *left, const struct xrt_quat *right, struct xrt_quat *result); 365 366/*! 367 * Integrate a local angular velocity vector (exponential map) and apply to a 368 * quaternion. 369 * 370 * ang_vel and dt should share the same units of time, and the ang_vel 371 * vector should be in radians per unit of time. 372 * 373 * @relates xrt_quat 374 * @see xrt_vec3 375 * @ingroup aux_math 376 */ 377void 378math_quat_integrate_velocity(const struct xrt_quat *quat, 379 const struct xrt_vec3 *ang_vel, 380 float dt, 381 struct xrt_quat *result); 382 383/*! 384 * Compute a global angular velocity vector (exponential map format) by taking 385 * the finite difference of two quaternions. 386 * 387 * quat1 is the orientation dt time after the orientation was quat0 388 * 389 * out_ang_vel and dt share the same units of time, and out_ang_vel is be in 390 * radians per unit of time. 391 * 392 * @relates xrt_quat 393 * @see xrt_vec3 394 * @ingroup aux_math 395 */ 396void 397math_quat_finite_difference(const struct xrt_quat *quat0, 398 const struct xrt_quat *quat1, 399 float dt, 400 struct xrt_vec3 *out_ang_vel); 401 402/*! 403 * Takes a rotation vector equal to half of a Rodrigues rotation vector and returns its corresponding unit quaternion. 404 * Useful for head tracking and pose-prediction. 405 * 406 * @relates xrt_quat 407 * @see xrt_vec3 408 * @ingroup aux_math 409 */ 410void 411math_quat_exp(const struct xrt_vec3 *axis_angle, struct xrt_quat *out_quat); 412 413 414/*! 415 * Takes a unit quaternion and returns a rotation vector equal to half of its corresponding Rodrigues rotation vector. 416 * Useful for head tracking and pose-prediction. 417 * 418 * @relates xrt_quat 419 * @see xrt_vec3 420 * @ingroup aux_math 421 */ 422void 423math_quat_ln(const struct xrt_quat *quat, struct xrt_vec3 *out_axis_angle); 424 425/*! 426 * Used to rotate a derivative like a angular velocity. 427 * 428 * @relates xrt_quat 429 * @see xrt_vec3 430 * @ingroup aux_math 431 */ 432void 433math_quat_rotate_derivative(const struct xrt_quat *quat, const struct xrt_vec3 *deriv, struct xrt_vec3 *result); 434 435 436/*! 437 * Slerp (spherical linear interpolation) between two quaternions 438 * 439 * @relates xrt_quat 440 * @ingroup aux_math 441 */ 442void 443math_quat_slerp(const struct xrt_quat *left, const struct xrt_quat *right, float t, struct xrt_quat *result); 444 445 446/*! 447 * Converts a 2D vector to a quaternion 448 * 449 * @relates xrt_quat 450 * @ingroup aux_math 451 */ 452void 453math_quat_from_swing(const struct xrt_vec2 *swing, struct xrt_quat *result); 454 455 456/*! 457 * Converts a 2D vector and a float to a quaternion 458 * 459 * @relates xrt_quat 460 * @ingroup aux_math 461 */ 462void 463math_quat_from_swing_twist(const struct xrt_vec2 *swing, const float twist, struct xrt_quat *result); 464 465/*! 466 * Converts a quaternion to XY-swing and Z-twist 467 * 468 * @relates xrt_quat 469 * @ingroup aux_math 470 */ 471void 472math_quat_to_swing_twist(const struct xrt_quat *in, struct xrt_vec2 *out_swing, float *out_twist); 473 474/*! 475 * Decompose a quaternion to swing and twist component rotations around a target 476 * axis. The swing is always orthogonal to the target axis, and twist rotation is always 477 * around the axis. 478 * 479 * swing * twist gives back the original quat 480 * (e.g. math_quat_rotate(&swing, &twist, &orig_q)) 481 * 482 * See https://arxiv.org/pdf/1506.05481.pdf 483 * 484 * @relates xrt_quat 485 * @ingroup aux_math 486 */ 487void 488math_quat_decompose_swing_twist(const struct xrt_quat *in, 489 const struct xrt_vec3 *twist_axis, 490 struct xrt_quat *swing, 491 struct xrt_quat *twist); 492 493/* 494 * 495 * Matrix functions 496 * 497 */ 498 499/*! 500 * Initialize a 3x3 matrix to the identity matrix 501 * 502 * @see xrt_matrix_3x3 503 * @ingroup aux_math 504 */ 505void 506math_matrix_3x3_identity(struct xrt_matrix_3x3 *mat); 507 508/*! 509 * Initialize a 3x3 matrix from a quaternion 510 * 511 * @see xrt_matrix_3x3 512 * @ingroup aux_math 513 */ 514void 515math_matrix_3x3_from_quat(const struct xrt_quat *q, struct xrt_matrix_3x3 *result_out); 516 517/*! 518 * Initialize a double 3x3 matrix to the identity matrix 519 * 520 * @see xrt_matrix_3x3 521 * @ingroup aux_math 522 */ 523void 524math_matrix_3x3_f64_identity(struct xrt_matrix_3x3_f64 *mat); 525 526/*! 527 * Transform a vec3 by a 3x3 matrix 528 * 529 * @see xrt_matrix_3x3 530 * @ingroup aux_math 531 */ 532void 533math_matrix_3x3_transform_vec3(const struct xrt_matrix_3x3 *left, 534 const struct xrt_vec3 *right, 535 struct xrt_vec3 *result_out); 536 537/*! 538 * Transform a vec3 by a 4x4 matrix, extending the vector with w = 1.0 539 * 540 * @see xrt_matrix_4x4 541 * @ingroup aux_math 542 */ 543void 544math_matrix_4x4_transform_vec3(const struct xrt_matrix_4x4 *left, 545 const struct xrt_vec3 *right, 546 struct xrt_vec3 *result_out); 547 548/*! 549 * Transform a double vec3 by a 3x3 double matrix 550 * 551 * @see xrt_matrix_3x3 552 * @ingroup aux_math 553 */ 554void 555math_matrix_3x3_f64_transform_vec3_f64(const struct xrt_matrix_3x3_f64 *left, 556 const struct xrt_vec3_f64 *right, 557 struct xrt_vec3_f64 *result_out); 558 559/*! 560 * Multiply Matrix3x3. 561 * 562 * @relates xrt_matrix_3x3 563 * @ingroup aux_math 564 */ 565void 566math_matrix_3x3_multiply(const struct xrt_matrix_3x3 *left, 567 const struct xrt_matrix_3x3 *right, 568 struct xrt_matrix_3x3 *result_out); 569 570/*! 571 * Invert Matrix3x3 572 * 573 * @relates xrt_matrix_3x3 574 * @ingroup aux_math 575 */ 576void 577math_matrix_3x3_inverse(const struct xrt_matrix_3x3 *in, struct xrt_matrix_3x3 *result); 578 579/*! 580 * Transpose Matrix3x3 581 * 582 * @relates xrt_matrix_3x3 583 * @ingroup aux_math 584 */ 585void 586math_matrix_3x3_transpose(const struct xrt_matrix_3x3 *in, struct xrt_matrix_3x3 *result); 587 588/*! 589 * Create a rotation from two vectors plus x and z, by 590 * creating a rotation matrix by crossing z and x to 591 * get the y axis. 592 * 593 * Input vectors should be normalized. 594 * 595 * @relates xrt_matrix_3x3 596 * @ingroup aux_math 597 */ 598void 599math_matrix_3x3_f64_from_plus_x_z(const struct xrt_vec3_f64 *plus_x, 600 const struct xrt_vec3_f64 *plus_z, 601 struct xrt_matrix_3x3_f64 *result); 602 603/*! 604 * Get the rotation matrix from an isomertry matrix (col-major). 605 * 606 * @relates xrt_matrix_4x4 607 * @ingroup aux_math 608 */ 609void 610math_matrix_3x3_rotation_from_isometry(const struct xrt_matrix_4x4 *isometry, struct xrt_matrix_3x3 *result); 611 612/*! 613 * Initialize Matrix4x4 with identity. 614 * 615 * @relates xrt_matrix_4x4 616 * @ingroup aux_math 617 */ 618void 619math_matrix_4x4_identity(struct xrt_matrix_4x4 *result); 620 621/*! 622 * Multiply Matrix4x4. 623 * 624 * @relates xrt_matrix_4x4 625 * @ingroup aux_math 626 */ 627void 628math_matrix_4x4_multiply(const struct xrt_matrix_4x4 *left, 629 const struct xrt_matrix_4x4 *right, 630 struct xrt_matrix_4x4 *result); 631 632/*! 633 * Invert Matrix4x4. 634 * 635 * @relates xrt_matrix_4x4 636 * @ingroup aux_math 637 */ 638void 639math_matrix_4x4_inverse(const struct xrt_matrix_4x4 *in, struct xrt_matrix_4x4 *result); 640 641/*! 642 * Invert a homogeneous isometry 4x4 (col-major) matrix in SE(3). 643 * 644 * @relates xrt_matrix_4x4 645 * @ingroup aux_math 646 */ 647void 648math_matrix_4x4_isometry_inverse(const struct xrt_matrix_4x4 *in, struct xrt_matrix_4x4 *result); 649 650/*! 651 * Transpose Matrix4x4 652 * 653 * @relates xrt_matrix_4x4 654 * @ingroup aux_math 655 */ 656void 657math_matrix_4x4_transpose(const struct xrt_matrix_4x4 *in, struct xrt_matrix_4x4 *result); 658 659/*! 660 * Compute view matrix from xrt_pose. 661 * 662 * @relates xrt_matrix_4x4 663 * @ingroup aux_math 664 */ 665void 666math_matrix_4x4_view_from_pose(const struct xrt_pose *pose, struct xrt_matrix_4x4 *result); 667 668/*! 669 * Get an isometry matrix —in SE(3)— from a rotation matrix —SO(3)— and a 670 * translation vector. All col-major matrices. 671 * 672 * @relates xrt_matrix_4x4 673 * @ingroup aux_math 674 */ 675void 676math_matrix_4x4_isometry_from_rt(const struct xrt_matrix_3x3 *rotation, 677 const struct xrt_vec3 *translation, 678 struct xrt_matrix_4x4 *result); 679 680/*! 681 * Get a col-major isometry matrix —in SE(3)— from a pose. 682 * 683 * @relates xrt_matrix_4x4 684 * @ingroup aux_math 685 */ 686void 687math_matrix_4x4_isometry_from_pose(const struct xrt_pose *pose, struct xrt_matrix_4x4 *result); 688 689/*! 690 * Compute quad layer model matrix from xrt_pose and xrt_vec2 size. 691 * 692 * @relates xrt_matrix_4x4 693 * @ingroup aux_math 694 */ 695void 696math_matrix_4x4_model(const struct xrt_pose *pose, const struct xrt_vec3 *size, struct xrt_matrix_4x4 *result); 697 698/*! 699 * Compute inverse view projection matrix, 700 * using only the starting 3x3 block of the view. 701 * 702 * @relates xrt_matrix_4x4 703 * @ingroup aux_math 704 */ 705void 706math_matrix_4x4_inverse_view_projection(const struct xrt_matrix_4x4 *view, 707 const struct xrt_matrix_4x4 *projection, 708 struct xrt_matrix_4x4 *result); 709 710/*! 711 * Compute a projection matrix with settings for Vulkan, it will also have it's 712 * far plane at infinite and the NDC depth will be reversed. 713 * 714 * @relates xrt_matrix_4x4 715 * @ingroup aux_math 716 */ 717void 718math_matrix_4x4_projection_vulkan_infinite_reverse(const struct xrt_fov *fov, 719 float near_plane, 720 struct xrt_matrix_4x4 *result); 721 722 723/* 724 * 725 * Pose functions. 726 * 727 */ 728 729 730/*! 731 * Somewhat laboriously make an xrt_pose identity. 732 * 733 * @relates xrt_pose 734 * @ingroup aux_math 735 */ 736void 737math_pose_identity(struct xrt_pose *pose); 738 739/*! 740 * Check if this pose can be used in transformation operations. 741 * 742 * @relates xrt_pose 743 * @ingroup aux_math 744 */ 745bool 746math_pose_validate(const struct xrt_pose *pose); 747 748/*! 749 * Invert pose. 750 * 751 * OK if input and output are the same addresses. 752 * 753 * @relates xrt_pose 754 * @ingroup aux_math 755 */ 756void 757math_pose_invert(const struct xrt_pose *pose, struct xrt_pose *outPose); 758 759/*! 760 * Converts a (col-major) isometry into a pose. 761 * 762 * @relates xrt_pose 763 * @ingroup aux_math 764 */ 765void 766math_pose_from_isometry(const struct xrt_matrix_4x4 *transform, struct xrt_pose *result); 767 768/*! 769 * Interpolated pose between poses `a` and `b` by lerping position and slerping 770 * orientation by t. 771 * 772 * @relates xrt_pose 773 * @ingroup aux_math 774 */ 775void 776math_pose_interpolate(const struct xrt_pose *a, const struct xrt_pose *b, float t, struct xrt_pose *outPose); 777 778/*! 779 * Apply a rigid-body transformation to a pose. 780 * 781 * OK if input and output are the same addresses. 782 * 783 * @relates xrt_pose 784 * @ingroup aux_math 785 */ 786void 787math_pose_transform(const struct xrt_pose *transform, const struct xrt_pose *pose, struct xrt_pose *outPose); 788 789/*! 790 * Apply a rigid-body transformation to a point. 791 * 792 * The input point and output may be the same pointer. 793 * 794 * @relates xrt_pose 795 * @see xrt_vec3 796 * @ingroup aux_math 797 */ 798void 799math_pose_transform_point(const struct xrt_pose *transform, const struct xrt_vec3 *point, struct xrt_vec3 *out_point); 800 801 802/* 803 * 804 * Inline functions. 805 * 806 */ 807 808/*! 809 * Map a number from one range to another range. 810 * Exactly the same as Arduino's map(). 811 */ 812static inline double 813math_map_ranges(double value, double from_low, double from_high, double to_low, double to_high) 814{ 815 return (value - from_low) * (to_high - to_low) / (from_high - from_low) + to_low; 816} 817 818static inline double 819math_lerp(double from, double to, double amount) 820{ 821 return (from * (1.0 - amount)) + (to * (amount)); 822} 823 824/* 825 * 826 * Optics functions. 827 * 828 */ 829 830/*! 831 * Perform the computations from 832 * "Computing Half-Fields-Of-View from Simpler Display Models", 833 * to get half-FOVs from things we can retrieve from other APIs. 834 * The origin is in the lower-left corner of the display, so w_1 is the width to 835 * the left of CoP, and h_1 is the height below CoP. 836 * 837 * If vertfov_total is set to 0, it will be computed from h_total. 838 * 839 * Distances are in arbitrary but consistent units. Angles are in radians. 840 * 841 * 842 * In the diagram below, treating it like a FOV for horizontal, 843 * the top angle is horizfov_total, the length of the bottom 844 * is w_total, and the distance between the vertical line and the left corner is 845 * w_1. Vertical is similar - h_1 is above the center line. 846 * The triangle need not be symmetrical, despite how the diagram looks. 847 * 848 * ``` 849 * horizfov_total 850 * * 851 * angle_left (neg) -> / | \ <- angle_right 852 * / | \ 853 * / | \ 854 * / | \ 855 * ------------- 856 * [ w_1 ] 857 * [ --- w --- ] 858 * 859 * ------- --- |\ 860 * | \ 861 * h_1 | \ angle_up 862 * h_total ___ |-------* vertfov_total 863 * | / angle_down (neg) 864 * | / 865 * | / 866 * ------- |/ 867 * ``` 868 * 869 * @return true if successful. 870 * @ingroup aux_math 871 */ 872bool 873math_compute_fovs(double w_total, 874 double w_1, 875 double horizfov_total, 876 double h_total, 877 double h_1, 878 double vertfov_total, 879 struct xrt_fov *fov); 880 881#ifdef __cplusplus 882} 883#endif