README.md
b85356c0
 # `gliso`
 
 A [GLSL][]/[OpenGL][] [\>=2.1][] [isometry][] matrix library.
 
b57b6919
 If a `mat4` matrix represents an [isometry][], which in this case means that it
 encodes only rotations and translations (no scaling or shearing, and a
 projective `w` entry equal to `1`), it is easy and performant to extract those
 rotations and translations, and to compute the [inverse][]. This library
 provides functions to do so.
 
b85356c0
 [`gliso`]: https://git.rcrnstn.net/rcrnstn/gliso
 [GLSL]: https://en.wikipedia.org/wiki/OpenGL_Shading_Language
 [OpenGL]: https://en.wikipedia.org/wiki/OpenGL
 [\>=2.1]: https://en.wikipedia.org/wiki/OpenGL#Version_history
 [isometry]: https://en.wikipedia.org/wiki/Isometry
b57b6919
 [inverse]: https://en.wikipedia.org/wiki/Invertible_matrix
 
 ## Requirements
 
 Support for `#include` directives is required. This can be provided by e.g. the
 standardized [`ARB_shading_language_include`][] extension or some third party
 library.
 
 [`ARB_shading_language_include`]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shading_language_include.txt
 
 ## Usage
 
 Link shader programs with the provided `iso.glsl`.
 
 Include the provided `iso.h` from shaders. It declares the following functions:
 
 -   `mat{3,4} isorot{inv}{3,4}(mat4 iso)`
 
     Extract (inverse) rotation.
 
 -   `vec{3,4} isotrans{inv}{3,4}(mat4 iso)`
 
     Extract (inverse) translation.
 
     The `z` components of the `4` versions are set to `0`.
 
 -   `mat4 isoinv(mat4 iso)`
 
     Compute inverse.
 
 ## Theory
 
 For simplicity, we use the same name for both the [projective][] and
 [Euclidean][] versions of vectors and transformations below.
 
 Assume $M$ is an isometry,
 
 $$
 M v
 =
 \begin{pmatrix}
     r_{xx} & r_{yx} & r_{zx} & t_x \\
     r_{xx} & r_{yx} & r_{zx} & t_y \\
     r_{xx} & r_{yx} & r_{zx} & t_z \\
          0 &      0 &      0 &   1 \\
 \end{pmatrix}
 \begin{pmatrix}
     v_x \\
     v_y \\
     v_z \\
       1 \\
 \end{pmatrix}
 =
 R v + t
 $$
 
 It is trivial to extract the rotation $R$ and translation $t$ directly from the
 components of $M$.
 
 Since the rotation part $R$ is [orthonormal][], its inverse is its own
 transpose. The inverse of the translation is its own negation.
 
 $$
 \begin{aligned}
     R^{-1} &= R^T \\
     t^{-1} &= -t \\
 \end{aligned}
 $$
 
 Assuming the $3 \mathsf{x} 3$ sub-matrix of $M^{-1}$ is $R^{-1}$, finding the
 full inverse is simply a matter of finding $M^{-1}$'s fourth column $m^{-1}$:
 
 $$
 \begin{aligned}
     v
     &= M^{-1} M v \\
     &= R^{-1} (R v + t) + m^{-1} \\
     &= v + R^{-1} t + m^{-1} \\
     &\iff \\
     m^{-1} &= -R^{-1} t = R^{-1} t^{-1} \\
 \end{aligned}
 $$
 
 Computing this is much faster than the built-in, general, [`inverse`][].
 
 [projective]: https://en.wikipedia.org/wiki/Homogeneous_coordinates
 [Euclidean]: https://en.wikipedia.org/wiki/Cartesian_coordinates
 [orthonormal]: https://en.wikipedia.org/wiki/Orthogonal_matrix
 [`inverse`]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/inverse.xhtml
9fe502ad
 
bc484088
 ## Build system
 
 This project has support for [CMake][], and uses [`cmake-cxx`][].
 
 There are several ways to use this project in another CMake-based project:
 
 -   Use [`FetchContent`][] to download it and import the targets automatically
     as part of the configure step:
 
     ```cmake
     include(FetchContent)
     FetchContent_Declare(project-name
         GIT_REPOSITORY https://example.com/user/project-name
     )
     FetchContent_MakeAvailable(
         project-name
     )
     ```
 
 -   Bundle it and import the targets with [`add_subdirectory`][].
 
 -   Use [`find_package`][] (requires that the project is [packaged](#packaging)
     or [installed](#installing)).
 
 As usual, use [`add_dependencies`][]/[`target_link_libraries`][] to declare the
 dependency.
 
 [CMake]: https://cmake.org
 [`cmake-cxx`]: https://git.rcrnstn.net/rcrnstn/cmake-cxx
 [`FetchContent`]: https://cmake.org/cmake/help/v3.14/module/FetchContent.html
 [`add_subdirectory`]: https://cmake.org/cmake/help/v3.14/command/add_subdirectory.html
 [`find_package`]: https://cmake.org/cmake/help/v3.14/command/find_package.html
 [`add_dependencies`]: https://cmake.org/cmake/help/v3.14/command/add_dependencies.html
 [`target_link_libraries`]: https://cmake.org/cmake/help/v3.14/command/target_link_libraries.html
 
 ### Configure and generate
 
 To configure and generate a build tree, use `cmake`:
 
 ```sh
 cmake -B build
 ```
 
 To set the [`CMAKE_BUILD_TYPE`][], pass e.g. `-DCMAKE_BUILD_TYPE=Release`.
 
 [`cmake`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#generate-a-project-buildsystem
 [`CMAKE_BUILD_TYPE`]: https://cmake.org/cmake/help/v3.14/variable/CMAKE_BUILD_TYPE.html
 
 ### Build
 
 To build, use [`cmake --build`][]:
 
 ```sh
 cmake --build build
 ```
 
 [`cmake --build`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#build-a-project
 
 ### Test
 
 To run tests, use [`ctest`][]:
 
 ```sh
 (cd build && ctest --output-on-failure)
 ```
 
 [`ctest`]: https://cmake.org/cmake/help/v3.14/manual/ctest.1.html
 
 ### Package
 
 To package, use [`cpack`][]:
 
 ```sh
 (cd build && cpack)
 ```
 
 [`cpack`]: https://cmake.org/cmake/help/v3.14/manual/cpack.1.html
 
 ### Install
 
 To install onto the current system, use [`cmake --install`][]:
 
 ```sh
 cmake --install build
 ```
 
 [`cmake --install`]: https://cmake.org/cmake/help/v3.14/manual/cmake.1.html#install-a-project
 
9fe502ad
 ## License
 
 Licensed under the [ISC License][] unless otherwise noted, see the
 [`LICENSE`](LICENSE) file.
 
 [ISC License]: https://choosealicense.com/licenses/isc/