Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

1
vendor/glam/.cargo-checksum.json vendored Normal file

File diff suppressed because one or more lines are too long

86
vendor/glam/ARCHITECTURE.md vendored Normal file
View File

@@ -0,0 +1,86 @@
# Architecture
This document describes the high-level architecture of `glam`. While `glam` is
not a large library there are some complexities to its implementation. The
rational and explanation of these follows.
## Design goals
There overarching design goals of glam are:
* Good out of the box performance using SIMD when available
* Has a simple public interface
* Is fast to compile
* Follow Rust [standard library] conventions and [API guidelines] where possible
* High quality [rustdoc] generated document
[standard library]: https://doc.rust-lang.org/std/index.html
[API guidelines]: https://rust-lang.github.io/api-guidelines
[rustdoc]: https://doc.rust-lang.org/rustdoc/index.html
### SIMD
One of the core premises of `glam` was that using SSE2 instructions on `x86` and
`x86_64` architectures gave better performance than using Rust's built in `f32`
type. For more on this finding see [Optimising path tracing with SIMD].
I also wanted to have a `f32` fallback when SIMD was not available.
[Optimising path tracing with SIMD]: https://bitshifter.github.io/2018/06/04/simd-path-tracing/#converting-vec3-to-sse2.
### No generics
Because internally storage could be a SIMD vector intrinsic like `__m128` on
`x86` or say an array of `f32` if SSE2 was not available, a simple generic
parameter like `Vec4<T>` could not be used. The `T` would specify the public
facing type, but not storage. Perhaps this could be achieved with a second
generic parameter for storage, e.g. `Vec4<f32, __m128>` or `Vec4<f32, [f32; 4]>`
but I felt that such a design would introduce a lot of complexity that end users
would ultimately be burdened with, so it's not something that was pursued.
Generics can also increase compile time and code size which is something glam
wants to avoid.
### No traits
`glam` also mostly avoids using traits in the public interface. Primarily
because there wasn't a good reason to. A `Vec3` is not an interface, it is a
concrete type. The secondary reason is traits fragment documentation. If the
functionality of a `Vec3` is implemented across a number of different traits
then the documentation of all of the `Vec3` methods will be on the individual
traits, not the `Vec3` itself. This makes it harder for users to find what
methods a struct actually implements as the documentation is not in one place.
Conversely `glam` does use traits for swizzle methods so that the documentation
for these methods is on the trait and not the `Vec2`, `Vec3`, `Vec4` and so on
structs. There are many swizzle methods which would clutter the documentation,
making them a trait means they won't pollute documentation.
### Support common primitives
Initially `glam` only supported `f32` which kept the internal implementation
relatively simple. However users also wanted support for other primitives types
like `f64`, `i32` and `u32`. Because `glam` avoids using `generics` adding
support for other primitive types without a lot of code duplication required
some additional complexity in implementation.
## High level structure
`glam` supports a number of permutations of vector, quaternion and matrix types
for `f32`, `f64`, `i32` and `u32` primitives, with SSE2 or wasm32 for some `f32`
types and scalar fallbacks if SIMD is not available.
### Component access via Deref
The `Deref` trait is used to provide direct access to SIMD vector components
like `.x`, `.y` and so on. The `Deref` implementation will return `XYZ<T>`
structure on which the vector components are accessible. Unfortunately if users
dereference the public types they will see confusing errors messages about
`XYZ` types but this on balance seemed preferable to needing to setter and
getting methods to read and write component values.
## Code generation
See the [codegen README] for information on `glam`'s code generation process.
[codegen README]: codegen/README.md

80
vendor/glam/ATTRIBUTION.md vendored Normal file
View File

@@ -0,0 +1,80 @@
# Attribution
`glam` contains code ported from the following C++ libraries.
## [DirectXMath]
[DirectXMath]: https://docs.microsoft.com/en-us/windows/win32/dxmath/directxmath-portal
[The MIT License (MIT)](https://github.com/microsoft/DirectXMath/blob/master/LICENSE)
Copyright (c) 2011-2020 Microsoft Corp
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## [Realtime Math]
[Realtime Math]: https://github.com/nfrechette/rtm
[MIT License](https://github.com/nfrechette/rtm/blob/develop/LICENSE)
Copyright (c) 2018 Nicholas Frechette
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## [GLM]
[GLM]: https://glm.g-truc.net
[The MIT License](https://github.com/g-truc/glm/blob/master/copying.txt)
Copyright (c) 2005 - G-Truc Creation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

1220
vendor/glam/CHANGELOG.md vendored Normal file

File diff suppressed because it is too large Load Diff

128
vendor/glam/CODE_OF_CONDUCT.md vendored Normal file
View File

@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

58
vendor/glam/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,58 @@
# Contributing to glam
Thanks for contributing to `glam`! These guidelines will try to make the
process painless and efficient.
The short guide to contributing is [start a discussion] on GitHub. Pull
requests are welcome for bug fixes, documentation improvements and
optimizations. For anything else it would be best to discuss it first.
## Questions
If you have a question about the usage of this library please [ask a question]
with GitHub Discussions. That's the easiest way to get support right now.
## Bugs
If you find a bug please [open an issue] on GitHub or submit a pull request. A
unit test for any bug that slipped through existing coverage would also be
greatly appreciated.
## New functions and methods
If `glam` is missing functionality on existing types, [suggest a new feature]
with GitHub Discussions describing what feature you would like added and
ideally what your use case is for it just so I have a better understanding of
the feature. I'd like to keep `glam` reasonably light functionality wise
initially but commonly used functionality that is missing is very welcome. If
you do submit a pull request please ensure any new functionality also has a
test.
## Optimizations
If you feel some functionality could be optimized please [open an issue] on
GitHub or submit a pull request. Any optimization pull request should include a
benchmark if there isn't one already, so I can confirm the performance
improvement.
## Documentation
If you feel any documentation could be added or improved please
[open a GitHub issue] or submit a pull request.
## Code contributions
Most of `glam`'s source code is generated. See the [codegen README] on how
to modify the code templates and generate new source code.
You can run some of `glam`'s test suite locally by running the
`build_and_test_features.sh` script. It's worth running that before creating a
PR.
Also run `cargo fmt` and `cargo clippy` on any new code.
[start a discussion]: https://github.com/bitshifter/glam-rs/discussions/new
[open an issue]: https://GitHub.com/bitshifter/glam-rs/issues/new
[ask a question]: https://github.com/bitshifter/glam-rs/discussions/new?category=q-a
[suggest a new feature]: https://github.com/bitshifter/glam-rs/discussions/new?category=ideas
[codegen README]: codegen/README.md

904
vendor/glam/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,904 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "approx"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
dependencies = [
"num-traits",
]
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytecheck"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41502630fe304ce54cbb2f8389e017784dee2b0328147779fcbe43b9db06d35d"
dependencies = [
"bytecheck_derive",
"ptr_meta",
]
[[package]]
name = "bytecheck_derive"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eda88c587085bc07dc201ab9df871bd9baa5e07f7754b745e4d7194b43ac1eda"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "bytemuck"
version = "1.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "ciborium"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
[[package]]
name = "ciborium-ll"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
dependencies = [
"ciborium-io",
"half",
]
[[package]]
name = "clap"
version = "4.5.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9560b07a799281c7e0958b9296854d6fafd4c5f31444a7e5bb1ad6dde5ccf1bd"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.5.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "874e0dd3eb68bf99058751ac9712f622e61e6f393a94f7128fa26e3f02f5c7cd"
dependencies = [
"anstyle",
"clap_lex",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "criterion"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
dependencies = [
"anes",
"cast",
"ciborium",
"clap",
"criterion-plot",
"is-terminal",
"itertools",
"num-traits",
"once_cell",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
dependencies = [
"cast",
"itertools",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "derive_more"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
]
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "glam"
version = "0.29.3"
dependencies = [
"approx",
"bytecheck",
"bytemuck",
"criterion",
"iai-callgrind",
"libm",
"mint",
"rand",
"rand_xoshiro",
"rkyv",
"serde",
"serde_json",
"wasm-bindgen-test",
]
[[package]]
name = "half"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
dependencies = [
"cfg-if",
"crunchy",
]
[[package]]
name = "hermit-abi"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
[[package]]
name = "iai-callgrind"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22275f8051874cd2f05b2aa1e0098d5cbec34df30ff92f1a1e2686a4cefed870"
dependencies = [
"bincode",
"derive_more",
"iai-callgrind-macros",
"iai-callgrind-runner",
]
[[package]]
name = "iai-callgrind-macros"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8e6677dc52bd798b988e62ffd6831bf7eb46e4348cb1c74c1164954ebd0e5a1"
dependencies = [
"derive_more",
"proc-macro-error2",
"proc-macro2",
"quote",
"serde",
"serde_json",
"syn 2.0.95",
]
[[package]]
name = "iai-callgrind-runner"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a02dd95fe4949513b45a328b5b18f527ee02e96f3428b48090aa7cf9043ab0b8"
dependencies = [
"serde",
]
[[package]]
name = "is-terminal"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "js-sys"
version = "0.3.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "libm"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "minicov"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b"
dependencies = [
"cc",
"walkdir",
]
[[package]]
name = "mint"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "oorandom"
version = "11.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
[[package]]
name = "plotters"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
[[package]]
name = "plotters-svg"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
dependencies = [
"plotters-backend",
]
[[package]]
name = "proc-macro-error-attr2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "proc-macro-error2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
"syn 2.0.95",
]
[[package]]
name = "proc-macro2"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
[[package]]
name = "ptr_meta"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "quote"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "rand_xoshiro"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
dependencies = [
"rand_core",
]
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rkyv"
version = "0.7.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b"
dependencies = [
"ptr_meta",
"rkyv_derive",
"seahash",
]
[[package]]
name = "rkyv_derive"
version = "0.7.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "seahash"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "serde"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
]
[[package]]
name = "serde_json"
version = "1.0.135"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "unicode-ident"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn 2.0.95",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2"
dependencies = [
"cfg-if",
"js-sys",
"once_cell",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d44563646eb934577f2772656c7ad5e9c90fac78aa8013d776fcdaf24625d"
dependencies = [
"js-sys",
"minicov",
"scoped-tls",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test-macro",
]
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54171416ce73aa0b9c377b51cc3cb542becee1cd678204812e8392e5b0e4a031"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
]
[[package]]
name = "web-sys"
version = "0.3.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi-util"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

277
vendor/glam/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,277 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.68.2"
name = "glam"
version = "0.29.3"
authors = ["Cameron Hart <cameron.hart@gmail.com>"]
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "A simple and fast 3D math library for games and graphics"
readme = "README.md"
keywords = [
"gamedev",
"math",
"matrix",
"vector",
"quaternion",
]
categories = [
"game-engines",
"no-std",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/bitshifter/glam-rs"
[badges.maintenance]
status = "actively-developed"
[features]
core-simd = []
cuda = []
debug-glam-assert = []
default = ["std"]
fast-math = []
glam-assert = []
libm = ["dep:libm"]
nostd-libm = ["dep:libm"]
scalar-math = []
std = []
[lib]
name = "glam"
path = "src/lib.rs"
bench = false
[[test]]
name = "affine2"
path = "tests/affine2.rs"
[[test]]
name = "affine3"
path = "tests/affine3.rs"
[[test]]
name = "euler"
path = "tests/euler.rs"
[[test]]
name = "float"
path = "tests/float.rs"
[[test]]
name = "mat2"
path = "tests/mat2.rs"
[[test]]
name = "mat3"
path = "tests/mat3.rs"
[[test]]
name = "mat4"
path = "tests/mat4.rs"
[[test]]
name = "quat"
path = "tests/quat.rs"
[[test]]
name = "support"
path = "tests/support.rs"
[[test]]
name = "swizzles_f32"
path = "tests/swizzles_f32.rs"
[[test]]
name = "swizzles_f64"
path = "tests/swizzles_f64.rs"
[[test]]
name = "swizzles_i16"
path = "tests/swizzles_i16.rs"
[[test]]
name = "swizzles_i32"
path = "tests/swizzles_i32.rs"
[[test]]
name = "swizzles_i64"
path = "tests/swizzles_i64.rs"
[[test]]
name = "swizzles_i8"
path = "tests/swizzles_i8.rs"
[[test]]
name = "swizzles_u16"
path = "tests/swizzles_u16.rs"
[[test]]
name = "swizzles_u32"
path = "tests/swizzles_u32.rs"
[[test]]
name = "swizzles_u64"
path = "tests/swizzles_u64.rs"
[[test]]
name = "swizzles_u8"
path = "tests/swizzles_u8.rs"
[[test]]
name = "vec2"
path = "tests/vec2.rs"
[[test]]
name = "vec3"
path = "tests/vec3.rs"
[[test]]
name = "vec4"
path = "tests/vec4.rs"
[[bench]]
name = "affine2"
path = "benches/affine2.rs"
harness = false
[[bench]]
name = "affine3"
path = "benches/affine3.rs"
harness = false
[[bench]]
name = "iai"
path = "benches/iai.rs"
harness = false
[[bench]]
name = "mat2"
path = "benches/mat2.rs"
harness = false
[[bench]]
name = "mat3"
path = "benches/mat3.rs"
harness = false
[[bench]]
name = "mat3a"
path = "benches/mat3a.rs"
harness = false
[[bench]]
name = "mat4"
path = "benches/mat4.rs"
harness = false
[[bench]]
name = "quat"
path = "benches/quat.rs"
harness = false
[[bench]]
name = "support"
path = "benches/support.rs"
bench = false
[[bench]]
name = "vec2"
path = "benches/vec2.rs"
harness = false
[[bench]]
name = "vec3"
path = "benches/vec3.rs"
harness = false
[[bench]]
name = "vec3a"
path = "benches/vec3a.rs"
harness = false
[[bench]]
name = "vec4"
path = "benches/vec4.rs"
harness = false
[dependencies.approx]
version = "0.5"
optional = true
default-features = false
[dependencies.bytecheck]
version = "0.7"
optional = true
default-features = false
[dependencies.bytemuck]
version = "1.9"
optional = true
default-features = false
[dependencies.libm]
version = "0.2"
optional = true
default-features = false
[dependencies.mint]
version = "0.5.8"
optional = true
default-features = false
[dependencies.rand]
version = "0.8"
optional = true
default-features = false
[dependencies.rkyv]
version = "0.7"
optional = true
default-features = false
[dependencies.serde]
version = "1.0"
optional = true
default-features = false
[dev-dependencies.rand_xoshiro]
version = "0.6"
[dev-dependencies.rkyv]
version = "0.7"
features = ["size_32"]
default-features = false
[dev-dependencies.serde_json]
version = "1.0"
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.criterion]
version = "0.5"
features = ["html_reports"]
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.iai-callgrind]
version = "0.14"
[target.'cfg(target_arch = "wasm32")'.dev-dependencies.wasm-bindgen-test]
version = "0.3"
[lints.rust.unexpected_cfgs]
level = "warn"
priority = 0
check-cfg = ['cfg(target_arch, values("spirv"))']

201
vendor/glam/LICENSE-APACHE vendored Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2020 Cameron Hart
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

23
vendor/glam/LICENSE-MIT vendored Normal file
View File

@@ -0,0 +1,23 @@
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

287
vendor/glam/README.md vendored Normal file
View File

@@ -0,0 +1,287 @@
# glam
[![Build Status]][github-ci] [![Coverage Status]][coveralls.io]
[![Latest Version]][crates.io] [![docs]][docs.rs]
[![Minimum Supported Rust Version]][Rust 1.68.2]
A simple and fast 3D math library for games and graphics.
## Development status
`glam` is in beta stage. Base functionality has been implemented and the look
and feel of the API has solidified.
## Features
* `f32` types
* vectors: `Vec2`, `Vec3`, `Vec3A` and `Vec4`
* square matrices: `Mat2`, `Mat3`, `Mat3A` and `Mat4`
* a quaternion type: `Quat`
* affine transformation types: `Affine2` and `Affine3A`
* `f64` types
* vectors: `DVec2`, `DVec3` and `DVec4`
* square matrices: `DMat2`, `DMat3` and `DMat4`
* a quaternion type: `DQuat`
* affine transformation types: `DAffine2` and `DAffine3`
* `i8` types
* vectors: `I8Vec2`, `I8Vec3` and `I8Vec4`
* `u8` types
* vectors: `U16Vec2`, `U16Vec3` and `U16Vec4`
* `i16` types
* vectors: `I16Vec2`, `I16Vec3` and `I16Vec4`
* `u16` types
* vectors: `U16Vec2`, `U16Vec3` and `U16Vec4`
* `i32` types
* vectors: `IVec2`, `IVec3` and `IVec4`
* `u32` types
* vectors: `UVec2`, `UVec3` and `UVec4`
* `i64` types
* vectors: `I64Vec2`, `I64Vec3` and `I64Vec4`
* `u64` types
* vectors: `U64Vec2`, `U64Vec3` and `U64Vec4`
* `bool` types
* vectors: `BVec2`, `BVec3` and `BVec4`
### SIMD
The `Vec3A`, `Vec4`, `Quat`, `Mat2`, `Mat3A`, `Mat4`, `Affine2` and `Affine3A`
types use 128-bit wide SIMD vector types for storage on `x86`, `x86_64` and
`wasm32` architectures. As a result, these types are all 16 byte aligned and
depending on the size of the type or the type's members, they may contain
internal padding. This results in some wasted space in the cases of `Vec3A`,
`Mat3A`, `Affine2` and `Affine3A`. However, the use of SIMD generally results
in better performance than scalar math.
`glam` outperforms similar Rust libraries for common operations as tested by the
[`mathbench`][mathbench] project.
[mathbench]: https://github.com/bitshifter/mathbench-rs
### Enabling SIMD
SIMD is supported on `x86`, `x86_64` and `wasm32` targets.
* `SSE2` is enabled by default on `x86_64` targets.
* To enable `SSE2` on `x86` targets add `-C target-feature=+sse2` to
`RUSTCFLAGS`.
* `NEON` is enabled by default on `aarch64` targets.
* To enable `NEON` on `aarch64` targets add `-C target-feature=+neon` to `RUSTFLAGS`.
* To enable `simd128` on `wasm32` targets add `-C target-feature=+simd128` to
`RUSTFLAGS`.
* Experimental [portable simd] support can be enabled with the `core-simd`
feature. This requires the nightly compiler as it is still unstable in Rust.
Note that SIMD on `wasm32` passes tests but has not been benchmarked,
performance may or may not be better than scalar math.
[portable simd]: https://doc.rust-lang.org/core/simd/index.html
### `no_std` support
`no_std` support can be enabled by compiling with `--no-default-features` to
disable `std` support and `--features libm` for math functions that are only
defined in `std`. For example:
```toml
[dependencies]
glam = { version = "0.29.3", default-features = false, features = ["libm"] }
```
To support both `std` and `no_std` builds in project, you can use the following
in your `Cargo.toml`:
```toml
[features]
default = ["std"]
std = ["glam/std"]
libm = ["glam/libm"]
[dependencies]
glam = { version = "0.29.3", default-features = false }
```
Alternatively, you can use the `nostd-libm` feature.
This will always include a `libm` dependency, but allows the user to still override it with `std` if they prefer.
This will allow your crate to compile with default features disabled, instead of forcing the user to enable either `std` or `libm`.
```toml
[features]
default = ["std"]
std = ["glam/std"]
libm = ["glam/libm"]
[dependencies]
glam = { version = "0.30.0", default-features = false, features = ["nostd-libm"] }
```
### Optional features
* [`approx`] - traits and macros for approximate float comparisons
* [`bytemuck`] - for casting into slices of bytes
* [`libm`] - uses `libm` math functions instead of `std`
* [`nostd-libm`] - uses `libm` math functions if `std` is not available
* [`mint`] - for interoperating with other 3D math libraries
* [`rand`] - implementations of `Distribution` trait for all `glam` types.
* [`serde`] - implementations of `Serialize` and `Deserialize` for all `glam`
types. Note that serialization should work between builds of `glam` with and
without SIMD enabled
* [`rkyv`] - implementations of `Archive`, `Serialize` and `Deserialize` for
all `glam` types. Note that serialization is not interoperable with and
without the `scalar-math` feature. It should work between all other builds of
`glam`. Endian conversion is currently not supported
* [`bytecheck`] - to perform archive validation when using the `rkyv` feature
[`approx`]: https://docs.rs/approx
[`bytemuck`]: https://docs.rs/bytemuck
[`libm`]: https://github.com/rust-lang/libm
[`mint`]: https://github.com/kvark/mint
[`rand`]: https://github.com/rust-random/rand
[`serde`]: https://serde.rs
[`rkyv`]: https://github.com/rkyv/rkyv
[`bytecheck`]: https://github.com/rkyv/bytecheck
### Feature gates
* `scalar-math` - compiles with SIMD support disabled
* `debug-glam-assert` - adds assertions in debug builds which check the validity
of parameters passed to `glam` to help catch runtime errors
* `glam-assert` - adds validation assertions to all builds
* `cuda` - forces `glam` types to match expected [cuda alignment]
* `fast-math` - By default, glam attempts to provide bit-for-bit identical
results on all platforms. Using this feature will enable platform specific
optimizations that may not be identical to other platforms. **Intermediate
libraries should not use this feature and defer the decision to the final
binary build**.
* `core-simd` - enables SIMD support via the [portable simd] module. This is an
unstable feature which requires a nightly Rust toolchain and `std` support.
[cuda alignment]: https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#built-in-vector-types
### Minimum Supported Rust Version (MSRV)
The minimum supported version of Rust for `glam` is `1.68.2`.
## Conventions
### Column vectors
`glam` interprets vectors as column matrices (also known as "column vectors")
meaning when transforming a vector with a matrix the matrix goes on the left,
e.g. `v' = Mv`. DirectX uses row vectors, OpenGL uses column vectors. There
are pros and cons to both.
### Column-major order
Matrices are stored in column major format. Each column vector is stored in
contiguous memory.
### Co-ordinate system
`glam` is co-ordinate system agnostic and intends to support both right-handed
and left-handed conventions.
## Design Philosophy
The design of this library is guided by a desire for simplicity and good
performance.
* No generics and minimal traits in the public API for simplicity of usage
* All dependencies are optional (e.g. `mint`, `rand` and `serde`)
* Follows the [Rust API Guidelines] where possible
* Aiming for 100% test [coverage]
* Common functionality is benchmarked using [Criterion.rs]
[Rust API Guidelines]: https://rust-lang-nursery.github.io/api-guidelines/
[coverage]: coveralls.io
[Criterion.rs]: https://bheisler.github.io/criterion.rs/book/index.html
## Architecture
See [ARCHITECTURE.md] for details on `glam`'s internals.
[ARCHITECTURE.md]: ARCHITECTURE.md
## Inspirations
There were many inspirations for the interface and internals of glam from the
Rust and C++ worlds. In particular:
* [How to write a maths library in 2016] inspired the initial `Vec3A`
implementation
* [Realtime Math] - header only C++11 with SSE and NEON SIMD intrinsic support
* [DirectXMath] - header only SIMD C++ linear algebra library for use in games
and graphics apps
* `glam` is a play on the name of the popular C++ library [GLM]
[How to write a maths library in 2016]: http://www.codersnotes.com/notes/maths-lib-2016/
[Realtime Math]: https://github.com/nfrechette/rtm
[DirectXMath]: https://docs.microsoft.com/en-us/windows/desktop/dxmath/directxmath-portal
[GLM]: https://glm.g-truc.net
## License
Licensed under either of
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE)
or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT)
or http://opensource.org/licenses/MIT)
at your option.
## Contribution
Contributions in any form (issues, pull requests, etc.) to this project must
adhere to Rust's [Code of Conduct].
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
If you are interested in contributing or have a request or suggestion
[start a discussion] on GitHub. See [CONTRIBUTING.md] for more information for
contributors.
Most code in `glam` is generated, see the [codegen README] for details.
Thank you to all of the `glam` [contributors]!
[Code of Conduct]: https://www.rust-lang.org/en-US/conduct.html
[start a discussion]: https://github.com/bitshifter/glam-rs/discussions
[CONTRIBUTING.md]: CONTRIBUTING.md
[codegen README]: codegen/README.md
[contributors]: https://github.com/bitshifter/glam-rs/graphs/contributors
## Support
The [Game Development in Rust Discord] and [Bevy Engine Discord] servers are
not official support channels but can be good places to ask for help with
`glam`.
[Game Development in Rust Discord]: https://discord.gg/yNtPTb2
[Bevy Engine Discord]: https://discord.gg/gMUk5Ph
## Attribution
`glam` contains code ported from the following C++ libraries:
* [DirectXMath] - MIT License - Copyright (c) 2011-2020 Microsoft Corp
* [Realtime Math] - MIT License - Copyright (c) 2018 Nicholas Frechette
* [GLM] - MIT License - Copyright (c) 2005 - G-Truc Creation
See [ATTRIBUTION.md] for details.
[ATTRIBUTION.md]: ATTRIBUTION.md
[Build Status]: https://github.com/bitshifter/glam-rs/actions/workflows/ci.yml/badge.svg
[github-ci]: https://github.com/bitshifter/glam-rs/actions/workflows/ci.yml
[Coverage Status]: https://coveralls.io/repos/github/bitshifter/glam-rs/badge.svg?branch=main
[coveralls.io]: https://coveralls.io/github/bitshifter/glam-rs?branch=main
[Latest Version]: https://img.shields.io/crates/v/glam.svg
[crates.io]: https://crates.io/crates/glam/
[docs]: https://docs.rs/glam/badge.svg
[docs.rs]: https://docs.rs/glam/
[Minimum Supported Rust Version]: https://img.shields.io/badge/Rust-1.68.2-blue?color=fc8d62&logo=rust
[Rust 1.68.2]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1682-2023-03-28

79
vendor/glam/benches/affine2.rs vendored Normal file
View File

@@ -0,0 +1,79 @@
#[path = "support/macros.rs"]
#[macro_use]
mod macros;
mod support;
use criterion::{criterion_group, criterion_main, Criterion};
use glam::Affine2;
use std::ops::Mul;
use support::*;
pub fn random_srt_affine2(rng: &mut PCG32) -> Affine2 {
Affine2::from_scale_angle_translation(
random_nonzero_vec2(rng),
random_radians(rng),
random_vec2(rng),
)
}
bench_unop!(affine2_inverse, "affine2 inverse", op => inverse, from => random_srt_affine2);
bench_binop!(
affine2_transform_point2,
"affine2 transform point2",
op => transform_point2,
from1 => random_srt_affine2,
from2 => random_vec2
);
bench_binop!(
affine2_transform_vector2,
"affine2 transform vector2",
op => transform_vector2,
from1 => random_srt_affine2,
from2 => random_vec2
);
bench_binop!(affine2_mul_affine2, "affine2 mul affine2", op => mul, from => random_srt_affine2);
bench_binop!(affine2_mul_mat3, "affine2 mul mat3", op => mul, from1 => random_srt_affine2, from2 => random_srt_mat3);
bench_binop!(mat3_mul_affine2, "mat3 mul affine2", op => mul, from1 => random_srt_mat3, from2 => random_srt_affine2);
pub fn affine2_from_srt(c: &mut Criterion) {
use glam::Vec2;
const SIZE: usize = 1 << 13;
let mut rng = support::PCG32::default();
let inputs = criterion::black_box(
(0..SIZE)
.map(|_| {
(
random_nonzero_vec2(&mut rng),
random_radians(&mut rng),
random_vec2(&mut rng),
)
})
.collect::<Vec<(Vec2, f32, Vec2)>>(),
);
let mut outputs = vec![Affine2::default(); SIZE];
let mut i = 0;
c.bench_function("affine2 from srt", |b| {
b.iter(|| {
i = (i + 1) & (SIZE - 1);
unsafe {
let data = inputs.get_unchecked(i);
*outputs.get_unchecked_mut(i) =
Affine2::from_scale_angle_translation(data.0, data.1, data.2);
}
});
});
}
criterion_group!(
benches,
affine2_inverse,
affine2_transform_point2,
affine2_transform_vector2,
affine2_mul_affine2,
affine2_mul_mat3,
mat3_mul_affine2,
affine2_from_srt,
);
criterion_main!(benches);

117
vendor/glam/benches/affine3.rs vendored Normal file
View File

@@ -0,0 +1,117 @@
#[path = "support/macros.rs"]
#[macro_use]
mod macros;
mod support;
use criterion::{criterion_group, criterion_main, Criterion};
use glam::Affine3A;
use std::ops::Mul;
use support::*;
pub fn random_srt_affine3a(rng: &mut PCG32) -> Affine3A {
Affine3A::from_scale_rotation_translation(
random_nonzero_vec3(rng),
random_quat(rng),
random_vec3(rng),
)
}
bench_unop!(affine3a_inverse, "affine3a inverse", op => inverse, from => random_srt_affine3a);
bench_binop!(
affine3a_transform_point3,
"affine3a transform point3",
op => transform_point3,
from1 => random_srt_affine3a,
from2 => random_vec3
);
bench_binop!(
affine3a_transform_vector3,
"affine3a transform vector3",
op => transform_vector3,
from1 => random_srt_affine3a,
from2 => random_vec3
);
bench_binop!(
affine3a_transform_point3a,
"affine3a transform point3a",
op => transform_point3a,
from1 => random_srt_affine3a,
from2 => random_vec3a
);
bench_binop!(
affine3a_transform_vector3a,
"affine3a transform vector3a",
op => transform_vector3a,
from1 => random_srt_affine3a,
from2 => random_vec3a
);
bench_binop!(
affine3a_mul_affine3a,
"affine3a mul affine3a",
op => mul,
from => random_srt_affine3a
);
bench_binop!(affine3a_mul_mat4,
"affine3a mul mat4",
op => mul,
from1 => random_srt_affine3a,
from2 => random_srt_mat4
);
bench_binop!(
mat4_mul_affine3a,
"mat4 mul affine3a",
op => mul,
from1 => random_srt_mat4,
from2 => random_srt_affine3a
);
pub fn affine3a_from_srt(c: &mut Criterion) {
use glam::{Quat, Vec3};
const SIZE: usize = 1 << 13;
let mut rng = support::PCG32::default();
let inputs = criterion::black_box(
(0..SIZE)
.map(|_| {
(
random_nonzero_vec3(&mut rng),
random_quat(&mut rng),
random_vec3(&mut rng),
)
})
.collect::<Vec<(Vec3, Quat, Vec3)>>(),
);
let mut outputs = vec![Affine3A::IDENTITY; SIZE];
let mut i = 0;
c.bench_function("affine3a from srt", |b| {
b.iter(|| {
i = (i + 1) & (SIZE - 1);
unsafe {
let data = inputs.get_unchecked(i);
*outputs.get_unchecked_mut(i) =
Affine3A::from_scale_rotation_translation(data.0, data.1, data.2);
}
});
});
}
criterion_group!(
benches,
affine3a_from_srt,
affine3a_inverse,
affine3a_mul_affine3a,
affine3a_mul_mat4,
affine3a_transform_point3,
affine3a_transform_point3a,
affine3a_transform_vector3,
affine3a_transform_vector3a,
mat4_mul_affine3a,
);
criterion_main!(benches);

282
vendor/glam/benches/iai.rs vendored Normal file
View File

@@ -0,0 +1,282 @@
#![allow(clippy::all)]
use core::hint::black_box;
use iai_callgrind::{library_benchmark, library_benchmark_group, main};
use glam::{BVec3A, Mat2, Mat3A, Mat4, Quat, Vec2, Vec3A, Vec4};
#[cfg(feature = "scalar-math")]
use glam::BVec4 as BVec4A;
#[cfg(not(feature = "scalar-math"))]
use glam::BVec4A;
#[inline]
fn mat2() -> Mat2 {
black_box(Mat2::from_cols_array(&[1.0, 2.0, 3.0, 4.0]))
}
#[inline]
fn mat3a() -> Mat3A {
black_box(Mat3A::from_cols_array(&[
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0,
]))
}
#[inline]
fn mat4() -> Mat4 {
black_box(Mat4::from_cols_array(&[
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
]))
}
#[inline]
fn quat() -> Quat {
black_box(Quat::from_xyzw(0.0, 0.0, 0.0, 1.0))
}
#[inline]
fn vec2() -> Vec2 {
black_box(Vec2::new(1.0, 2.0))
}
#[inline]
fn vec3a() -> Vec3A {
black_box(Vec3A::new(1.0, 2.0, 3.0))
}
#[inline]
fn bvec3a() -> BVec3A {
black_box(BVec3A::new(true, false, true))
}
#[inline]
fn vec4() -> Vec4 {
black_box(Vec4::new(1.0, 2.0, 3.0, 4.0))
}
#[inline]
fn bvec4a() -> BVec4A {
black_box(BVec4A::new(true, false, true, false))
}
#[library_benchmark]
#[bench::args(mat2())]
fn mat2_determinant(m: Mat2) -> f32 {
black_box(m.determinant())
}
#[library_benchmark]
#[bench::args(mat2())]
fn mat2_inverse(m: Mat2) -> Mat2 {
black_box(m.inverse())
}
#[library_benchmark]
#[bench::args(mat2())]
fn mat2_transpose(m: Mat2) -> Mat2 {
black_box(m.transpose())
}
#[library_benchmark]
#[bench::args(mat2(), mat2())]
fn mat2_mul_mat2(m1: Mat2, m2: Mat2) -> Mat2 {
black_box(m1 * m2)
}
#[library_benchmark]
#[bench::args(mat2(), vec2())]
fn mat2_mul_vec2(m: Mat2, v: Vec2) -> Vec2 {
black_box(m * v)
}
#[library_benchmark]
#[bench::args(mat3a())]
fn mat3a_determinant(m: Mat3A) -> f32 {
black_box(m.determinant())
}
#[library_benchmark]
#[bench::args(mat3a())]
fn mat3a_inverse(m: Mat3A) -> Mat3A {
black_box(m.inverse())
}
#[library_benchmark]
#[bench::args(mat3a())]
fn mat3a_transpose(m: Mat3A) -> Mat3A {
black_box(m.transpose())
}
#[library_benchmark]
#[bench::args(mat3a(), mat3a())]
fn mat3a_mul_mat3a(m1: Mat3A, m2: Mat3A) -> Mat3A {
black_box(m1 * m2)
}
#[library_benchmark]
#[bench::args(mat3a(), vec3a())]
fn mat3a_mul_vec3a(m: Mat3A, v: Vec3A) -> Vec3A {
black_box(m * v)
}
#[library_benchmark]
#[bench::args(mat4())]
fn mat4_determinant(m: Mat4) -> f32 {
black_box(m.determinant())
}
#[library_benchmark]
#[bench::args(mat4())]
fn mat4_inverse(m: Mat4) -> Mat4 {
black_box(m.inverse())
}
#[library_benchmark]
#[bench::args(mat4())]
fn mat4_transpose(m: Mat4) -> Mat4 {
black_box(m.transpose())
}
#[library_benchmark]
#[bench::args(mat4(), mat4())]
fn mat4_mul_mat4(m1: Mat4, m2: Mat4) -> Mat4 {
black_box(m1 * m2)
}
#[library_benchmark]
#[bench::args(mat4(), vec4())]
fn mat4_mul_vec4(m: Mat4, v: Vec4) -> Vec4 {
black_box(m * v)
}
#[library_benchmark]
#[bench::args(quat(), quat())]
fn quat_mul_quat(q1: Quat, q2: Quat) -> Quat {
black_box(q1 * q2)
}
#[library_benchmark]
#[bench::args(quat(), vec3a())]
fn quat_mul_vec3a(q: Quat, v: Vec3A) -> Vec3A {
black_box(q * v)
}
#[library_benchmark]
#[bench::args(vec3a(), vec3a())]
fn vec3a_dot(v1: Vec3A, v2: Vec3A) -> f32 {
black_box(v1.dot(v2))
}
#[library_benchmark]
#[bench::args(vec3a(), vec3a())]
fn vec3a_cross(v1: Vec3A, v2: Vec3A) -> Vec3A {
black_box(v1.cross(v2))
}
#[library_benchmark]
#[bench::args(vec3a())]
fn vec3a_length(v: Vec3A) -> f32 {
black_box(v.length())
}
#[library_benchmark]
#[bench::args(vec3a())]
fn vec3a_normalize(v: Vec3A) -> Vec3A {
black_box(v.normalize())
}
#[library_benchmark]
#[bench::args(bvec3a(), vec3a(), vec3a())]
fn vec3a_select(b: BVec3A, v1: Vec3A, v2: Vec3A) -> Vec3A {
black_box(Vec3A::select(b, v1, v2))
}
#[library_benchmark]
#[bench::args(vec4(), vec4())]
fn vec4_dot(v1: Vec4, v2: Vec4) -> f32 {
black_box(v1.dot(v2))
}
#[library_benchmark]
#[bench::args(vec4())]
fn vec4_length(v: Vec4) -> f32 {
black_box(v.length())
}
#[library_benchmark]
#[bench::args(vec4())]
fn vec4_normalize(v: Vec4) -> Vec4 {
black_box(v.normalize())
}
#[library_benchmark]
#[bench::args(bvec4a(), vec4(), vec4())]
fn vec4_select(b: BVec4A, v1: Vec4, v2: Vec4) -> Vec4 {
black_box(Vec4::select(b, v1, v2))
}
library_benchmark_group!(
name = bench_mat2;
benchmarks =
mat2_determinant,
mat2_inverse,
mat2_mul_mat2,
mat2_mul_vec2,
mat2_transpose,
);
library_benchmark_group!(
name = bench_mat3a;
benchmarks =
mat3a_determinant,
mat3a_inverse,
mat3a_mul_mat3a,
mat3a_mul_vec3a,
mat3a_transpose,
);
library_benchmark_group!(
name = bench_mat4;
benchmarks =
mat4_determinant,
mat4_inverse,
mat4_mul_mat4,
mat4_mul_vec4,
mat4_transpose,
);
library_benchmark_group!(
name = bench_quat;
benchmarks =
quat_mul_quat,
quat_mul_vec3a,
);
library_benchmark_group!(
name = bench_vec3a;
benchmarks =
vec3a_dot,
vec3a_cross,
vec3a_length,
vec3a_normalize,
vec3a_select,
);
library_benchmark_group!(
name = bench_vec4;
benchmarks =
vec4_dot,
vec4_length,
vec4_normalize,
vec4_select,
);
main!(
library_benchmark_groups = bench_mat2,
bench_mat3a,
bench_mat4,
bench_quat,
bench_vec3a,
bench_vec4
);

42
vendor/glam/benches/mat2.rs vendored Normal file
View File

@@ -0,0 +1,42 @@
#[path = "support/macros.rs"]
#[macro_use]
mod macros;
mod support;
use criterion::{criterion_group, criterion_main, Criterion};
use std::ops::Mul;
use support::*;
bench_binop!(
mat2_mul_vec2,
"mat2 mul vec2",
op => mul,
from1 => random_mat2,
from2 => random_vec2
);
bench_unop!(
mat2_transpose,
"mat2 transpose",
op => transpose,
from => random_mat2
);
bench_unop!(
mat2_determinant,
"mat2 determinant",
op => determinant,
from => random_mat2
);
bench_unop!(mat2_inverse, "mat2 inverse", op => inverse, from => random_mat2);
bench_binop!(mat2_mul_mat2, "mat2 mul mat2", op => mul, from => random_mat2);
criterion_group!(
benches,
mat2_transpose,
mat2_determinant,
mat2_inverse,
mat2_mul_vec2,
mat2_mul_mat2,
);
criterion_main!(benches);

72
vendor/glam/benches/mat3.rs vendored Normal file
View File

@@ -0,0 +1,72 @@
#[path = "support/macros.rs"]
#[macro_use]
mod macros;
mod support;
use criterion::{criterion_group, criterion_main, Criterion};
use glam::Mat3;
use std::ops::Mul;
use support::*;
bench_unop!(
mat3_transpose,
"mat3 transpose",
op => transpose,
from => random_mat3
);
bench_unop!(
mat3_determinant,
"mat3 determinant",
op => determinant,
from => random_mat3
);
bench_unop!(mat3_inverse, "mat3 inverse", op => inverse, from => random_mat3);
bench_binop!(mat3_mul_mat3, "mat3 mul mat3", op => mul, from => random_mat3);
bench_from_ypr!(mat3_from_ypr, "mat3 from ypr", ty => Mat3);
bench_binop!(
mat3_mul_vec3,
"mat3 mul vec3",
op => mul,
from1 => random_mat3,
from2 => random_vec3
);
bench_binop!(
mat3_mul_vec3a,
"mat3 mul vec3a",
op => mul,
from1 => random_mat3,
from2 => random_vec3a
);
bench_binop!(
mat3_transform_point2,
"mat3 transform point2",
op => transform_point2,
from1 => random_srt_mat3,
from2 => random_vec2
);
bench_binop!(
mat3_transform_vector2,
"mat3 transform vector2",
op => transform_vector2,
from1 => random_srt_mat3,
from2 => random_vec2
);
criterion_group!(
benches,
mat3_transpose,
mat3_determinant,
mat3_inverse,
mat3_mul_vec3,
mat3_mul_vec3a,
mat3_mul_mat3,
mat3_from_ypr,
mat3_transform_vector2,
mat3_transform_point2,
);
criterion_main!(benches);

72
vendor/glam/benches/mat3a.rs vendored Normal file
View File

@@ -0,0 +1,72 @@
#[path = "support/macros.rs"]
#[macro_use]
mod macros;
mod support;
use criterion::{criterion_group, criterion_main, Criterion};
use glam::Mat3A;
use std::ops::Mul;
use support::*;
bench_unop!(
mat3a_transpose,
"mat3a transpose",
op => transpose,
from => random_mat3a
);
bench_unop!(
mat3a_determinant,
"mat3a determinant",
op => determinant,
from => random_mat3a
);
bench_unop!(mat3a_inverse, "mat3a inverse", op => inverse, from => random_mat3a);
bench_binop!(mat3a_mul_mat3a, "mat3a mul mat3a", op => mul, from => random_mat3a);
bench_from_ypr!(mat3a_from_ypr, "mat3a from ypr", ty => Mat3A);
bench_binop!(
mat3a_mul_vec3,
"mat3a mul vec3",
op => mul,
from1 => random_mat3a,
from2 => random_vec3
);
bench_binop!(
mat3a_mul_vec3a,
"mat3a mul vec3a",
op => mul,
from1 => random_mat3a,
from2 => random_vec3a
);
bench_binop!(
mat3a_transform_point2,
"mat3a transform point2",
op => transform_point2,
from1 => random_srt_mat3a,
from2 => random_vec2
);
bench_binop!(
mat3a_transform_vector2,
"mat3a transform vector2",
op => transform_vector2,
from1 => random_srt_mat3a,
from2 => random_vec2
);
criterion_group!(
benches,
mat3a_transpose,
mat3a_determinant,
mat3a_inverse,
mat3a_mul_vec3,
mat3a_mul_vec3a,
mat3a_mul_mat3a,
mat3a_from_ypr,
mat3a_transform_vector2,
mat3a_transform_point2,
);
criterion_main!(benches);

129
vendor/glam/benches/mat4.rs vendored Normal file
View File

@@ -0,0 +1,129 @@
#[path = "support/macros.rs"]
#[macro_use]
mod macros;
mod support;
use criterion::{criterion_group, criterion_main, Criterion};
use glam::Mat4;
use std::ops::Mul;
use support::*;
bench_unop!(
mat4_transpose,
"mat4 transpose",
op => transpose,
from => random_srt_mat4
);
bench_unop!(
mat4_determinant,
"mat4 determinant",
op => determinant,
from => random_srt_mat4
);
bench_unop!(
mat4_inverse,
"mat4 inverse",
op => inverse,
from => random_srt_mat4
);
bench_binop!(
mat4_mul_vec4,
"mat4 mul vec4",
op => mul,
from1 => random_srt_mat4,
from2 => random_vec4
);
bench_binop!(
mat4_transform_point3,
"mat4 transform point3",
op => transform_point3,
from1 => random_srt_mat4,
from2 => random_vec3
);
bench_binop!(
mat4_transform_vector3,
"mat4 transform vector3",
op => transform_vector3,
from1 => random_srt_mat4,
from2 => random_vec3
);
bench_binop!(
mat4_transform_point3a,
"mat4 transform point3a",
op => transform_point3a,
from1 => random_srt_mat4,
from2 => random_vec3a
);
bench_binop!(
mat4_transform_vector3a,
"mat4 transform vector3a",
op => transform_vector3a,
from1 => random_srt_mat4,
from2 => random_vec3a
);
bench_binop!(
mat4_mul_mat4,
"mat4 mul mat4",
op => mul,
from => random_srt_mat4
);
bench_from_ypr!(
mat4_from_ypr,
"mat4 from ypr",
ty => Mat4
);
pub fn mat4_from_srt(c: &mut Criterion) {
use glam::{Quat, Vec3};
const SIZE: usize = 1 << 13;
let mut rng = support::PCG32::default();
let inputs = criterion::black_box(
(0..SIZE)
.map(|_| {
(
random_nonzero_vec3(&mut rng),
random_quat(&mut rng),
random_vec3(&mut rng),
)
})
.collect::<Vec<(Vec3, Quat, Vec3)>>(),
);
let mut outputs = vec![Mat4::default(); SIZE];
let mut i = 0;
c.bench_function("mat4 from srt", |b| {
b.iter(|| {
i = (i + 1) & (SIZE - 1);
unsafe {
let data = inputs.get_unchecked(i);
*outputs.get_unchecked_mut(i) =
Mat4::from_scale_rotation_translation(data.0, data.1, data.2);
}
});
});
}
criterion_group!(
benches,
mat4_determinant,
mat4_from_srt,
mat4_from_ypr,
mat4_inverse,
mat4_mul_mat4,
mat4_mul_vec4,
mat4_transform_point3,
mat4_transform_point3a,
mat4_transform_vector3,
mat4_transform_vector3a,
mat4_transpose,
);
criterion_main!(benches);

80
vendor/glam/benches/quat.rs vendored Normal file
View File

@@ -0,0 +1,80 @@
#[path = "support/macros.rs"]
#[macro_use]
mod macros;
mod support;
use criterion::{criterion_group, criterion_main, Criterion};
use glam::Quat;
use std::ops::Mul;
use support::*;
bench_unop!(
quat_conjugate,
"quat conjugate",
op => conjugate,
from => random_quat
);
bench_binop!(
quat_mul_vec3,
"quat mul vec3",
op => mul,
from1 => random_quat,
from2 => random_vec3
);
bench_binop!(
quat_mul_vec3a,
"quat mul vec3a",
op => mul,
from1 => random_quat,
from2 => random_vec3a
);
bench_binop!(
quat_mul_quat,
"quat mul quat",
op => mul,
from => random_quat
);
bench_binop!(
quat_dot,
"quat dot",
op => dot,
from => random_quat
);
bench_trinop!(
quat_lerp,
"quat lerp",
op => lerp,
from1 => random_quat,
from2 => random_quat,
from3 => random_f32
);
bench_trinop!(
quat_slerp,
"quat slerp",
op => slerp,
from1 => random_quat,
from2 => random_quat,
from3 => random_f32
);
bench_from_ypr!(quat_from_ypr, "quat from ypr", ty => Quat);
criterion_group!(
benches,
quat_conjugate,
quat_dot,
quat_lerp,
quat_slerp,
quat_mul_quat,
quat_mul_vec3,
quat_mul_vec3a,
quat_from_ypr
);
criterion_main!(benches);

131
vendor/glam/benches/support.rs vendored Normal file
View File

@@ -0,0 +1,131 @@
#![allow(dead_code)]
use core::f32;
use glam::{Mat2, Mat3, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A, Vec4};
pub struct PCG32 {
state: u64,
inc: u64,
}
impl Default for PCG32 {
fn default() -> Self {
PCG32::seed(0x853c49e6748fea9b, 0xda3e39cb94b95bdb)
}
}
impl PCG32 {
pub fn seed(initstate: u64, initseq: u64) -> Self {
let mut rng = PCG32 {
state: 0,
inc: (initseq << 1) | 1,
};
rng.next_u32();
rng.state = rng.state.wrapping_add(initstate);
rng.next_u32();
rng
}
pub fn next_u32(&mut self) -> u32 {
let oldstate = self.state;
self.state = oldstate
.wrapping_mul(6364136223846793005)
.wrapping_add(self.inc | 1);
let xorshifted = ((oldstate >> 18) ^ oldstate) >> 27;
let rot = oldstate >> 59;
((xorshifted >> rot) | (xorshifted << (rot.wrapping_neg() & 31))) as u32
}
pub fn next_f32(&mut self) -> f32 {
(self.next_u32() & 0xffffff) as f32 / 16777216.0
}
}
pub fn random_vec2(rng: &mut PCG32) -> Vec2 {
Vec2::new(rng.next_f32(), rng.next_f32())
}
pub fn random_vec3(rng: &mut PCG32) -> Vec3 {
Vec3::new(rng.next_f32(), rng.next_f32(), rng.next_f32())
}
pub fn random_vec3a(rng: &mut PCG32) -> Vec3A {
Vec3A::new(rng.next_f32(), rng.next_f32(), rng.next_f32())
}
pub fn random_vec4(rng: &mut PCG32) -> Vec4 {
Vec4::new(
rng.next_f32(),
rng.next_f32(),
rng.next_f32(),
rng.next_f32(),
)
}
pub fn random_nonzero_vec2(rng: &mut PCG32) -> Vec2 {
loop {
let v = random_vec2(rng);
if v.length_squared() > 0.01 {
return v;
}
}
}
pub fn random_nonzero_vec3(rng: &mut PCG32) -> Vec3 {
loop {
let v = random_vec3(rng);
if v.length_squared() > 0.01 {
return v;
}
}
}
pub fn random_f32(rng: &mut PCG32) -> f32 {
rng.next_f32()
}
pub fn random_radians(rng: &mut PCG32) -> f32 {
-f32::consts::PI + rng.next_f32() * 2.0 * f32::consts::PI
}
pub fn random_quat(rng: &mut PCG32) -> Quat {
let yaw = random_radians(rng);
let pitch = random_radians(rng);
let roll = random_radians(rng);
Quat::from_euler(glam::EulerRot::YXZ, yaw, pitch, roll)
}
pub fn random_mat2(rng: &mut PCG32) -> Mat2 {
Mat2::from_cols(random_vec2(rng), random_vec2(rng))
}
pub fn random_mat3(rng: &mut PCG32) -> Mat3 {
Mat3::from_cols(random_vec3(rng), random_vec3(rng), random_vec3(rng))
}
pub fn random_srt_mat3(rng: &mut PCG32) -> Mat3 {
Mat3::from_scale_angle_translation(
random_nonzero_vec2(rng),
random_radians(rng),
random_vec2(rng),
)
}
pub fn random_mat3a(rng: &mut PCG32) -> Mat3A {
Mat3A::from_cols(random_vec3a(rng), random_vec3a(rng), random_vec3a(rng))
}
pub fn random_srt_mat3a(rng: &mut PCG32) -> Mat3A {
Mat3A::from_scale_angle_translation(
random_nonzero_vec2(rng),
random_radians(rng),
random_vec2(rng),
)
}
pub fn random_srt_mat4(rng: &mut PCG32) -> Mat4 {
Mat4::from_scale_rotation_translation(
random_nonzero_vec3(rng),
random_quat(rng),
random_vec3(rng),
)
}

210
vendor/glam/benches/support/macros.rs vendored Normal file
View File

@@ -0,0 +1,210 @@
#[macro_export]
macro_rules! bench_func {
($name: ident, $desc: expr, op => $func: ident, from => $from: expr) => {
pub(crate) fn $name(c: &mut Criterion) {
const SIZE: usize = 1 << 13;
let mut rng = support::PCG32::default();
let inputs =
criterion::black_box((0..SIZE).map(|_| $from(&mut rng)).collect::<Vec<_>>());
// pre-fill output vector with some random value
let mut outputs = vec![$func($from(&mut rng)); SIZE];
let mut i = 0;
c.bench_function($desc, |b| {
b.iter(|| {
i = (i + 1) & (SIZE - 1);
unsafe {
*outputs.get_unchecked_mut(i) = $func(*inputs.get_unchecked(i));
}
})
});
criterion::black_box(outputs);
}
};
}
#[macro_export]
macro_rules! bench_unop {
($name: ident, $desc: expr, op => $unop: ident, from => $from: expr) => {
pub(crate) fn $name(c: &mut Criterion) {
const SIZE: usize = 1 << 13;
let mut rng = support::PCG32::default();
let inputs =
criterion::black_box((0..SIZE).map(|_| $from(&mut rng)).collect::<Vec<_>>());
// pre-fill output vector with some random value
let mut outputs = vec![$from(&mut rng).$unop(); SIZE];
let mut i = 0;
c.bench_function($desc, |b| {
b.iter(|| {
i = (i + 1) & (SIZE - 1);
unsafe {
*outputs.get_unchecked_mut(i) = inputs.get_unchecked(i).$unop();
}
})
});
criterion::black_box(outputs);
}
};
}
#[macro_export]
macro_rules! bench_binop {
($name: ident, $desc: expr, op => $binop: ident, from1 => $from1:expr, from2 => $from2:expr) => {
pub(crate) fn $name(c: &mut Criterion) {
const SIZE: usize = 1 << 13;
let mut rng = support::PCG32::default();
let inputs1 =
criterion::black_box((0..SIZE).map(|_| $from1(&mut rng)).collect::<Vec<_>>());
let inputs2 =
criterion::black_box((0..SIZE).map(|_| $from2(&mut rng)).collect::<Vec<_>>());
// pre-fill output vector with some random value
let mut outputs = vec![$from1(&mut rng).$binop($from2(&mut rng)); SIZE];
let mut i = 0;
c.bench_function($desc, |b| {
b.iter(|| {
i = (i + 1) & (SIZE - 1);
unsafe {
*outputs.get_unchecked_mut(i) = inputs1.get_unchecked(i).$binop(*inputs2.get_unchecked(i));
}
})
});
criterion::black_box(outputs);
}
};
($name: ident, $desc: expr, op => $binop: ident, from => $from: expr) => {
bench_binop!($name, $desc, op => $binop, from1 => $from, from2 => $from);
};
}
#[macro_export]
macro_rules! bench_trinop {
($name: ident, $desc: expr, op => $trinop: ident, from1 => $from1:expr, from2 => $from2:expr, from3 => $from3:expr) => {
pub(crate) fn $name(c: &mut Criterion) {
const SIZE: usize = 1 << 13;
let mut rng = support::PCG32::default();
let inputs1 =
criterion::black_box((0..SIZE).map(|_| $from1(&mut rng)).collect::<Vec<_>>());
let inputs2 =
criterion::black_box((0..SIZE).map(|_| $from2(&mut rng)).collect::<Vec<_>>());
let inputs3 =
criterion::black_box((0..SIZE).map(|_| $from3(&mut rng)).collect::<Vec<_>>());
// pre-fill output vector with some random value
let mut outputs =
vec![$from1(&mut rng).$trinop($from2(&mut rng), $from3(&mut rng)); SIZE];
let mut i = 0;
c.bench_function($desc, |b| {
b.iter(|| {
i = (i + 1) & (SIZE - 1);
unsafe {
*outputs.get_unchecked_mut(i) = inputs1
.get_unchecked(i)
.$trinop(*inputs2.get_unchecked(i), *inputs3.get_unchecked(i));
}
})
});
criterion::black_box(outputs);
}
};
}
#[macro_export]
macro_rules! bench_select {
($name:ident, $desc:expr, ty => $ty: ident, op => $op: ident, from => $from:expr) => {
pub(crate) fn $name(c: &mut Criterion) {
const SIZE: usize = 1 << 13;
let mut rng = support::PCG32::default();
let inputs1 =
criterion::black_box((0..SIZE).map(|_| $from(&mut rng)).collect::<Vec<_>>());
let inputs2 =
criterion::black_box((0..SIZE).map(|_| $from(&mut rng)).collect::<Vec<_>>());
let masks = vec![$from(&mut rng).$op($from(&mut rng)); SIZE];
// pre-fill output vector with some random value
let mut outputs = vec![$from(&mut rng); SIZE];
let mut i = 0;
c.bench_function($desc, |b| {
b.iter(|| {
i = (i + 1) & (SIZE - 1);
unsafe {
*outputs.get_unchecked_mut(i) = $ty::select(
*masks.get_unchecked(i),
*inputs1.get_unchecked(i),
*inputs2.get_unchecked(i),
);
}
})
});
criterion::black_box(outputs);
}
};
}
#[macro_export]
macro_rules! bench_from_ypr {
($name: ident, $desc: expr, ty => $ty:ty) => {
pub(crate) fn $name(c: &mut Criterion) {
const SIZE: usize = 1 << 13;
let mut rng = support::PCG32::default();
let inputs = criterion::black_box(
(0..SIZE)
.map(|_| {
(
random_radians(&mut rng),
random_radians(&mut rng),
random_radians(&mut rng),
)
})
.collect::<Vec<_>>(),
);
let mut outputs = vec![<$ty>::default(); SIZE];
let mut i = 0;
c.bench_function($desc, |b| {
b.iter(|| {
i = (i + 1) & (SIZE - 1);
unsafe {
let data = inputs.get_unchecked(i);
*outputs.get_unchecked_mut(i) =
<$ty>::from_euler(glam::EulerRot::YXZ, data.0, data.1, data.2)
}
})
});
}
};
}
#[macro_export]
macro_rules! euler {
($name: ident, $desc: expr, ty => $t: ty, storage => $storage: ty, zero => $zero: expr, rand => $rand: ident) => {
pub(crate) fn $name(c: &mut Criterion) {
const UPDATE_RATE: f32 = 1.0 / 60.0;
const NUM_OBJECTS: usize = 10000;
struct TestData {
acc: Vec<$storage>,
vel: Vec<$storage>,
pos: Vec<$storage>,
}
let mut rng = support::PCG32::default();
let mut data = TestData {
acc: vec![$rand(&mut rng); NUM_OBJECTS],
vel: vec![$zero; NUM_OBJECTS],
pos: vec![$zero; NUM_OBJECTS],
};
let dt = <$t>::splat(UPDATE_RATE);
c.bench_function($desc, |b| {
b.iter(|| {
for ((position, acceleration), velocity) in
data.pos.iter_mut().zip(&data.acc).zip(&mut data.vel)
{
let local_acc: $t = (*acceleration).into();
let mut local_pos: $t = (*position).into();
let mut local_vel: $t = (*velocity).into();
local_vel += local_acc * dt;
local_pos += local_vel * dt;
*velocity = local_vel.into();
*position = local_pos.into();
}
})
});
}
};
}

51
vendor/glam/benches/vec2.rs vendored Normal file
View File

@@ -0,0 +1,51 @@
#[path = "support/macros.rs"]
#[macro_use]
mod macros;
mod support;
use criterion::{criterion_group, criterion_main, Criterion};
use glam::Vec2;
use std::ops::Mul;
use support::*;
euler!(
vec2_euler,
"vec2 euler",
ty => Vec2,
storage => Vec2,
zero => Vec2::ZERO,
rand => random_vec2);
bench_binop!(
vec2_mul_vec2,
"vec2 mul vec2",
op => mul,
from1 => random_vec2,
from2 => random_vec2
);
bench_binop!(
vec2_angle_to,
"vec2 angle_to",
op => angle_to,
from1 => random_vec2,
from2 => random_vec2
);
bench_select!(
vec2_select,
"vec2 select",
ty => Vec2,
op => cmple,
from => random_vec2
);
criterion_group!(
benches,
vec2_mul_vec2,
vec2_euler,
vec2_select,
vec2_angle_to
);
criterion_main!(benches);

208
vendor/glam/benches/vec3.rs vendored Normal file
View File

@@ -0,0 +1,208 @@
#[path = "support/macros.rs"]
#[macro_use]
mod macros;
mod support;
use criterion::{criterion_group, criterion_main, Criterion};
use glam::Vec3;
use std::ops::Mul;
use support::*;
bench_binop!(
vec3_mul_vec3,
"vec3 mul vec3",
op => mul,
from1 => random_vec3,
from2 => random_vec3
);
#[inline]
fn vec3_to_rgb_op(v: Vec3) -> u32 {
let (red, green, blue) = (v.min(Vec3::ONE).max(Vec3::ZERO) * 255.0).into();
((red as u32) << 16) | ((green as u32) << 8) | (blue as u32)
}
#[inline]
fn vec3_fields(v: Vec3) -> [f32; 3] {
[v.x, v.y, v.z]
}
#[inline]
fn vec3_into_array(v: Vec3) -> [f32; 3] {
v.into()
}
#[inline]
fn vec3_into_tuple(v: Vec3) -> (f32, f32, f32) {
v.into()
}
bench_func!(
vec3_to_rgb,
"vec3 to rgb",
op => vec3_to_rgb_op,
from => random_vec3
);
bench_func!(
vec3_to_array_fields,
"vec3 into array fields",
op => vec3_fields,
from => random_vec3
);
bench_func!(
vec3_to_array_into,
"vec3 into array fast",
op => vec3_into_array,
from => random_vec3
);
bench_func!(
vec3_to_tuple_into,
"vec3 into tuple fast",
op => vec3_into_tuple,
from => random_vec3
);
// ---
#[inline]
fn vec3_normalize(v: Vec3) -> Vec3 {
v.normalize()
}
bench_func!(
vec3_normalize_bench,
"vec3 normalize",
op => vec3_normalize,
from => random_vec3
);
#[inline]
fn vec3_normalize_or(v: Vec3) -> Vec3 {
v.normalize_or(Vec3::X)
}
bench_func!(
vec3_normalize_or_bench,
"vec3 normalize_or",
op => vec3_normalize_or,
from => random_vec3
);
#[inline]
fn vec3_normalize_or_zero(v: Vec3) -> Vec3 {
v.normalize_or_zero()
}
bench_func!(
vec3_normalize_or_zero_bench,
"vec3 normalize_or_zero",
op => vec3_normalize_or_zero,
from => random_vec3
);
// ---
#[inline(always)]
fn vec3_any_orthogonal_vector(v: Vec3) -> Vec3 {
v.any_orthogonal_vector()
}
bench_func!(
vec3_any_orthogonal_vector_bench,
"vec3 any_orthogonal_vector",
op => vec3_any_orthogonal_vector,
from => random_vec3
);
#[inline(always)]
fn vec3_any_orthonormal_vector(v: Vec3) -> Vec3 {
v.any_orthonormal_vector()
}
bench_func!(
vec3_any_orthonormal_vector_bench,
"vec3 any_orthonormal_vector",
op => vec3_any_orthonormal_vector,
from => random_vec3
);
#[inline(always)]
fn vec3_any_orthonormal_pair(v: Vec3) -> (Vec3, Vec3) {
v.any_orthonormal_pair()
}
bench_func!(
vec3_any_orthonormal_pair_bench,
"vec3 any_orthonormal_pair",
op => vec3_any_orthonormal_pair,
from => random_vec3
);
// ---
euler!(vec3_euler, "vec3 euler", ty => Vec3, storage => Vec3, zero => Vec3::ZERO, rand => random_vec3);
bench_binop!(
vec3_angle_between,
"vec3 angle_between",
op => angle_between,
from1 => random_vec3,
from2 => random_vec3
);
bench_binop!(
vec3_cross,
"vec3 cross",
op => cross,
from1 => random_vec3,
from2 => random_vec3
);
bench_binop!(
vec3_dot,
"vec3 dot",
op => dot,
from1 => random_vec3,
from2 => random_vec3
);
bench_unop!(
vec3_length,
"vec3 length",
op => length,
from => random_vec3
);
bench_select!(
vec3_select,
"vec3 select",
ty => Vec3,
op => cmple,
from => random_vec3
);
criterion_group!(
benches,
vec3_angle_between,
vec3_any_orthogonal_vector_bench,
vec3_any_orthonormal_pair_bench,
vec3_any_orthonormal_vector_bench,
vec3_cross,
vec3_dot,
vec3_euler,
vec3_length,
vec3_mul_vec3,
vec3_normalize_bench,
vec3_normalize_or_bench,
vec3_normalize_or_zero_bench,
vec3_select,
vec3_to_array_fields,
vec3_to_array_into,
vec3_to_rgb,
vec3_to_tuple_into,
);
criterion_main!(benches);

176
vendor/glam/benches/vec3a.rs vendored Normal file
View File

@@ -0,0 +1,176 @@
#[path = "support/macros.rs"]
#[macro_use]
mod macros;
mod support;
use criterion::{criterion_group, criterion_main, Criterion};
use glam::{Vec3, Vec3A};
use std::ops::Mul;
use support::*;
bench_binop!(
vec3a_mul_vec3a,
"vec3a mul vec3a",
op => mul,
from1 => random_vec3a,
from2 => random_vec3a
);
#[inline]
fn vec3a_to_rgb_op(v: Vec3A) -> u32 {
let (red, green, blue) = (v.min(Vec3A::ONE).max(Vec3A::ZERO) * 255.0).into();
((red as u32) << 16) | ((green as u32) << 8) | (blue as u32)
}
#[inline]
fn vec3a_deref(v: Vec3A) -> [f32; 3] {
[v.x, v.y, v.z]
}
#[inline]
fn vec3a_into_array(v: Vec3A) -> [f32; 3] {
v.into()
}
#[inline]
fn vec3a_into_tuple(v: Vec3A) -> (f32, f32, f32) {
v.into()
}
#[inline]
fn vec3a_into_vec3(v: Vec3A) -> Vec3 {
v.into()
}
bench_func!(
vec3a_to_vec3,
"vec3a into vec3",
op => vec3a_into_vec3,
from => random_vec3a
);
bench_func!(
vec3a_to_rgb,
"vec3a to rgb",
op => vec3a_to_rgb_op,
from => random_vec3a
);
bench_func!(
vec3a_to_array_deref,
"vec3a into array deref",
op => vec3a_deref,
from => random_vec3a
);
bench_func!(
vec3a_to_array_into,
"vec3a into array fast",
op => vec3a_into_array,
from => random_vec3a
);
bench_func!(
vec3a_to_tuple_into,
"vec3a into tuple fast",
op => vec3a_into_tuple,
from => random_vec3a
);
euler!(vec3a_euler, "vec3a euler", ty => Vec3A, storage => Vec3A, zero => Vec3A::ZERO, rand => random_vec3a);
#[inline]
fn vec3a_normalize(v: Vec3A) -> Vec3A {
v.normalize()
}
bench_func!(
vec3a_normalize_bench,
"vec3a normalize",
op => vec3a_normalize,
from => random_vec3a
);
#[inline]
fn vec3a_normalize_or(v: Vec3A) -> Vec3A {
v.normalize_or(Vec3A::X)
}
bench_func!(
vec3a_normalize_or_bench,
"vec3a normalize_or",
op => vec3a_normalize_or,
from => random_vec3a
);
#[inline]
fn vec3a_normalize_or_zero(v: Vec3A) -> Vec3A {
v.normalize_or_zero()
}
bench_func!(
vec3a_normalize_or_zero_bench,
"vec3a normalize_or_zero",
op => vec3a_normalize_or_zero,
from => random_vec3a
);
bench_binop!(
vec3a_angle_between,
"vec3a angle_between",
op => angle_between,
from1 => random_vec3a,
from2 => random_vec3a
);
bench_binop!(
vec3a_cross,
"vec3a cross",
op => cross,
from1 => random_vec3a,
from2 => random_vec3a
);
bench_binop!(
vec3a_dot,
"vec3a dot",
op => dot,
from1 => random_vec3a,
from2 => random_vec3a
);
bench_unop!(
vec3a_length,
"vec3a length",
op => length,
from => random_vec3a
);
bench_select!(
vec3a_select,
"vec3a select",
ty => Vec3A,
op => cmple,
from => random_vec3a
);
criterion_group!(
benches,
vec3a_normalize_bench,
vec3a_normalize_or_bench,
vec3a_normalize_or_zero_bench,
vec3a_angle_between,
vec3a_cross,
vec3a_dot,
vec3a_length,
vec3a_euler,
vec3a_mul_vec3a,
vec3a_select,
vec3a_to_array_deref,
vec3a_to_array_into,
vec3a_to_rgb,
vec3a_to_tuple_into,
vec3a_to_vec3,
);
criterion_main!(benches);

29
vendor/glam/benches/vec4.rs vendored Normal file
View File

@@ -0,0 +1,29 @@
#[path = "support/macros.rs"]
#[macro_use]
mod macros;
mod support;
use criterion::{criterion_group, criterion_main, Criterion};
use glam::Vec4;
use std::ops::Mul;
use support::random_vec4;
bench_binop!(
vec4_mul_vec4,
"vec4 mul vec4",
op => mul,
from1 => random_vec4,
from2 => random_vec4
);
bench_select!(
vec4_select,
"vec4 select",
ty => Vec4,
op => cmple,
from => random_vec4
);
criterion_group!(benches, vec4_mul_vec4, vec4_select);
criterion_main!(benches);

8
vendor/glam/build_all_msrv.sh vendored Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/sh
set -e
CARGO='rustup run 1.68.2 cargo'
$CARGO check --features "bytemuck mint rand serde debug-glam-assert" && \
$CARGO check --features "scalar-math bytemuck mint rand serde debug-glam-assert" && \
$CARGO check --no-default-features --features "libm scalar-math bytemuck mint rand serde debug-glam-assert"

31
vendor/glam/build_and_test_features.sh vendored Executable file
View File

@@ -0,0 +1,31 @@
#!/bin/bash
set -ex
# Set of features to build & test.
FEATURE_SETS=(
# std
"std"
"std approx bytemuck mint rand serde debug-glam-assert"
"std scalar-math approx bytemuck mint rand serde debug-glam-assert"
"std cuda"
"std scalar-math cuda"
"std libm"
"std scalar-math libm"
# no_std
"libm"
"libm scalar-math approx bytemuck mint rand serde debug-glam-assert"
)
rustc --version
for features in "${FEATURE_SETS[@]}"
do
:
cargo build --tests --no-default-features --features="$features"
cargo test --no-default-features --features="$features"
done
RUSTFLAGS='-C target-feature=+fma' cargo check
cargo check -p glam-no_std

6
vendor/glam/build_and_test_wasm32_chrome.sh vendored Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
set -e
RUSTFLAGS="-Ctarget-feature=+simd128" wasm-pack test --headless --chrome
wasm-pack test --headless --chrome

View File

@@ -0,0 +1,6 @@
#!/bin/sh
set -e
RUSTFLAGS="-Ctarget-feature=+simd128" wasm-pack test --headless --firefox
wasm-pack test --headless --firefox

1
vendor/glam/clippy.toml vendored Normal file
View File

@@ -0,0 +1 @@
msrv = "1.68.2"

14
vendor/glam/deny.toml vendored Normal file
View File

@@ -0,0 +1,14 @@
[bans]
multiple-versions = "deny"
deny = []
skip-tree = [
# ignore criterion dev-dependency that often have duplicate dependencies internally
{ name = "criterion" },
]
[licenses]
allow = [
"Apache-2.0",
"MIT",
"Unicode-3.0",
]

27
vendor/glam/src/align16.rs vendored Normal file
View File

@@ -0,0 +1,27 @@
#[derive(Clone, Copy, Default, PartialEq, PartialOrd)]
#[repr(C, align(16))]
pub(crate) struct Align16<T>(pub T);
impl<T> Align16<T> {
#[allow(dead_code)]
pub fn as_ptr(&self) -> *const T {
&self.0
}
#[allow(dead_code)]
pub fn as_mut_ptr(&mut self) -> *mut T {
&mut self.0
}
}
#[test]
fn test_align16() {
use core::{mem, ptr};
let mut a = Align16::<f32>(1.0);
assert_eq!(mem::align_of_val(&a), 16);
unsafe {
assert_eq!(ptr::read(a.as_ptr()).to_bits(), f32::to_bits(1.0));
ptr::write(a.as_mut_ptr(), -1.0);
}
assert_eq!(a.0.to_bits(), f32::to_bits(-1.0));
}

126
vendor/glam/src/bool.rs vendored Normal file
View File

@@ -0,0 +1,126 @@
mod bvec2;
mod bvec3;
mod bvec4;
#[cfg(all(feature = "core-simd", not(feature = "scalar-math")))]
mod coresimd;
#[cfg(all(
target_arch = "aarch64",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
mod neon;
#[cfg(all(
target_feature = "sse2",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
mod sse2;
#[cfg(all(
target_feature = "simd128",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
mod wasm32;
#[cfg(any(
not(any(
feature = "core-simd",
target_arch = "aarch64",
target_feature = "sse2",
target_feature = "simd128"
)),
feature = "scalar-math"
))]
mod scalar;
pub use bvec2::{bvec2, BVec2};
pub use bvec3::{bvec3, BVec3};
pub use bvec4::{bvec4, BVec4};
#[cfg(all(
target_arch = "aarch64",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
pub use neon::bvec3a::{bvec3a, BVec3A};
#[cfg(all(
target_arch = "aarch64",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
pub use neon::bvec4a::{bvec4a, BVec4A};
#[cfg(all(
target_feature = "sse2",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
pub use sse2::bvec3a::{bvec3a, BVec3A};
#[cfg(all(
target_feature = "sse2",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
pub use sse2::bvec4a::{bvec4a, BVec4A};
#[cfg(all(
target_feature = "simd128",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
pub use wasm32::bvec3a::{bvec3a, BVec3A};
#[cfg(all(
target_feature = "simd128",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
pub use wasm32::bvec4a::{bvec4a, BVec4A};
#[cfg(all(feature = "core-simd", not(feature = "scalar-math")))]
pub use coresimd::bvec3a::{bvec3a, BVec3A};
#[cfg(all(feature = "core-simd", not(feature = "scalar-math")))]
pub use coresimd::bvec4a::{bvec4a, BVec4A};
#[cfg(any(
not(any(
feature = "core-simd",
target_arch = "aarch64",
target_feature = "sse2",
target_feature = "simd128"
)),
feature = "scalar-math"
))]
pub use scalar::bvec3a::{bvec3a, BVec3A};
#[cfg(any(
not(any(
feature = "core-simd",
target_arch = "aarch64",
target_feature = "sse2",
target_feature = "simd128"
)),
feature = "scalar-math"
))]
pub use scalar::bvec4a::{bvec4a, BVec4A};
mod const_test_bvec2 {
const_assert_eq!(1, core::mem::align_of::<super::BVec2>());
const_assert_eq!(2, core::mem::size_of::<super::BVec2>());
}
mod const_test_bvec3 {
const_assert_eq!(1, core::mem::align_of::<super::BVec3>());
const_assert_eq!(3, core::mem::size_of::<super::BVec3>());
}
mod const_test_bvec4 {
const_assert_eq!(1, core::mem::align_of::<super::BVec4>());
const_assert_eq!(4, core::mem::size_of::<super::BVec4>());
}
#[cfg(not(feature = "scalar-math"))]
mod const_test_bvec3a {
const_assert_eq!(16, core::mem::align_of::<super::BVec3A>());
const_assert_eq!(16, core::mem::size_of::<super::BVec3A>());
}
#[cfg(not(feature = "scalar-math"))]
mod const_test_bvec4a {
const_assert_eq!(16, core::mem::align_of::<super::BVec4A>());
const_assert_eq!(16, core::mem::size_of::<super::BVec4A>());
}

218
vendor/glam/src/bool/bvec2.rs vendored Normal file
View File

@@ -0,0 +1,218 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
/// Creates a 2-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec2(x: bool, y: bool) -> BVec2 {
BVec2::new(x, y)
}
/// A 2-dimensional `bool` vector mask.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C, align(1))]
pub struct BVec2 {
pub x: bool,
pub y: bool,
}
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec2 {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool) -> Self {
Self { x, y }
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 2]) -> Self {
Self::new(a[0], a[1])
}
/// Returns a bitmask with the lowest 2 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
(self.x as u32) | ((self.y as u32) << 1)
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
self.x || self.y
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
self.x && self.y
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
match index {
0 => self.x,
1 => self.y,
_ => panic!("index out of bounds"),
}
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 1.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
match index {
0 => self.x = value,
1 => self.y = value,
_ => panic!("index out of bounds"),
}
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 2] {
[self.x, self.y]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 2] {
[MASK[self.x as usize], MASK[self.y as usize]]
}
}
impl Default for BVec2 {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl BitAnd for BVec2 {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self {
x: self.x & rhs.x,
y: self.y & rhs.y,
}
}
}
impl BitAndAssign for BVec2 {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec2 {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self {
x: self.x | rhs.x,
y: self.y | rhs.y,
}
}
}
impl BitOrAssign for BVec2 {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec2 {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self {
x: self.x ^ rhs.x,
y: self.y ^ rhs.y,
}
}
}
impl BitXorAssign for BVec2 {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec2 {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self {
x: !self.x,
y: !self.y,
}
}
}
impl fmt::Debug for BVec2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(f, "{}({:#x}, {:#x})", stringify!(BVec2), arr[0], arr[1])
}
}
impl fmt::Display for BVec2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}]", arr[0], arr[1])
}
}
impl From<[bool; 2]> for BVec2 {
#[inline]
fn from(a: [bool; 2]) -> Self {
Self::from_array(a)
}
}
impl From<BVec2> for [bool; 2] {
#[inline]
fn from(mask: BVec2) -> Self {
mask.into_bool_array()
}
}
impl From<BVec2> for [u32; 2] {
#[inline]
fn from(mask: BVec2) -> Self {
mask.into_u32_array()
}
}

236
vendor/glam/src/bool/bvec3.rs vendored Normal file
View File

@@ -0,0 +1,236 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
/// Creates a 3-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec3(x: bool, y: bool, z: bool) -> BVec3 {
BVec3::new(x, y, z)
}
/// A 3-dimensional `bool` vector mask.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C, align(1))]
pub struct BVec3 {
pub x: bool,
pub y: bool,
pub z: bool,
}
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec3 {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool) -> Self {
Self { x, y, z }
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 3]) -> Self {
Self::new(a[0], a[1], a[2])
}
/// Returns a bitmask with the lowest 3 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
(self.x as u32) | ((self.y as u32) << 1) | ((self.z as u32) << 2)
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
self.x || self.y || self.z
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
self.x && self.y && self.z
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
match index {
0 => self.x,
1 => self.y,
2 => self.z,
_ => panic!("index out of bounds"),
}
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
match index {
0 => self.x = value,
1 => self.y = value,
2 => self.z = value,
_ => panic!("index out of bounds"),
}
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 3] {
[self.x, self.y, self.z]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 3] {
[
MASK[self.x as usize],
MASK[self.y as usize],
MASK[self.z as usize],
]
}
}
impl Default for BVec3 {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl BitAnd for BVec3 {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self {
x: self.x & rhs.x,
y: self.y & rhs.y,
z: self.z & rhs.z,
}
}
}
impl BitAndAssign for BVec3 {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec3 {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self {
x: self.x | rhs.x,
y: self.y | rhs.y,
z: self.z | rhs.z,
}
}
}
impl BitOrAssign for BVec3 {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec3 {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self {
x: self.x ^ rhs.x,
y: self.y ^ rhs.y,
z: self.z ^ rhs.z,
}
}
}
impl BitXorAssign for BVec3 {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec3 {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self {
x: !self.x,
y: !self.y,
z: !self.z,
}
}
}
impl fmt::Debug for BVec3 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x})",
stringify!(BVec3),
arr[0],
arr[1],
arr[2]
)
}
}
impl fmt::Display for BVec3 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2])
}
}
impl From<[bool; 3]> for BVec3 {
#[inline]
fn from(a: [bool; 3]) -> Self {
Self::from_array(a)
}
}
impl From<BVec3> for [bool; 3] {
#[inline]
fn from(mask: BVec3) -> Self {
mask.into_bool_array()
}
}
impl From<BVec3> for [u32; 3] {
#[inline]
fn from(mask: BVec3) -> Self {
mask.into_u32_array()
}
}

245
vendor/glam/src/bool/bvec4.rs vendored Normal file
View File

@@ -0,0 +1,245 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
/// Creates a 4-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec4(x: bool, y: bool, z: bool, w: bool) -> BVec4 {
BVec4::new(x, y, z, w)
}
/// A 4-dimensional `bool` vector mask.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C, align(1))]
pub struct BVec4 {
pub x: bool,
pub y: bool,
pub z: bool,
pub w: bool,
}
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec4 {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
Self { x, y, z, w }
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 4]) -> Self {
Self::new(a[0], a[1], a[2], a[3])
}
/// Returns a bitmask with the lowest 4 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
(self.x as u32) | ((self.y as u32) << 1) | ((self.z as u32) << 2) | ((self.w as u32) << 3)
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
self.x || self.y || self.z || self.w
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
self.x && self.y && self.z && self.w
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
match index {
0 => self.x,
1 => self.y,
2 => self.z,
3 => self.w,
_ => panic!("index out of bounds"),
}
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
match index {
0 => self.x = value,
1 => self.y = value,
2 => self.z = value,
3 => self.w = value,
_ => panic!("index out of bounds"),
}
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 4] {
[self.x, self.y, self.z, self.w]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 4] {
[
MASK[self.x as usize],
MASK[self.y as usize],
MASK[self.z as usize],
MASK[self.w as usize],
]
}
}
impl Default for BVec4 {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl BitAnd for BVec4 {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self {
x: self.x & rhs.x,
y: self.y & rhs.y,
z: self.z & rhs.z,
w: self.w & rhs.w,
}
}
}
impl BitAndAssign for BVec4 {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec4 {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self {
x: self.x | rhs.x,
y: self.y | rhs.y,
z: self.z | rhs.z,
w: self.w | rhs.w,
}
}
}
impl BitOrAssign for BVec4 {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec4 {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self {
x: self.x ^ rhs.x,
y: self.y ^ rhs.y,
z: self.z ^ rhs.z,
w: self.w ^ rhs.w,
}
}
}
impl BitXorAssign for BVec4 {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec4 {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self {
x: !self.x,
y: !self.y,
z: !self.z,
w: !self.w,
}
}
}
impl fmt::Debug for BVec4 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x}, {:#x})",
stringify!(BVec4),
arr[0],
arr[1],
arr[2],
arr[3]
)
}
}
impl fmt::Display for BVec4 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3])
}
}
impl From<[bool; 4]> for BVec4 {
#[inline]
fn from(a: [bool; 4]) -> Self {
Self::from_array(a)
}
}
impl From<BVec4> for [bool; 4] {
#[inline]
fn from(mask: BVec4) -> Self {
mask.into_bool_array()
}
}
impl From<BVec4> for [u32; 4] {
#[inline]
fn from(mask: BVec4) -> Self {
mask.into_u32_array()
}
}

2
vendor/glam/src/bool/coresimd.rs vendored Normal file
View File

@@ -0,0 +1,2 @@
pub mod bvec3a;
pub mod bvec4a;

246
vendor/glam/src/bool/coresimd/bvec3a.rs vendored Normal file
View File

@@ -0,0 +1,246 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
use core::simd::*;
#[repr(C)]
union UnionCast {
a: [u32; 4],
v: BVec3A,
}
/// Creates a 3-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec3a(x: bool, y: bool, z: bool) -> BVec3A {
BVec3A::new(x, y, z)
}
/// A 3-dimensional SIMD vector mask.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct BVec3A(pub(crate) mask32x4);
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec3A {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool) -> Self {
unsafe {
UnionCast {
a: [MASK[x as usize], MASK[y as usize], MASK[z as usize], 0],
}
.v
}
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 3]) -> Self {
Self::new(a[0], a[1], a[2])
}
/// Returns a bitmask with the lowest 3 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
(self.0.to_bitmask() & 0x7) as u32
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
self.bitmask() != 0
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
self.bitmask() == 0x7
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
self.0.test(index)
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
self.0.set(index, value)
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 3] {
let bitmask = self.bitmask();
[(bitmask & 1) != 0, (bitmask & 2) != 0, (bitmask & 4) != 0]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 3] {
let bitmask = self.bitmask();
[
MASK[(bitmask & 1) as usize],
MASK[((bitmask >> 1) & 1) as usize],
MASK[((bitmask >> 2) & 1) as usize],
]
}
}
impl Default for BVec3A {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl PartialEq for BVec3A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.bitmask().eq(&rhs.bitmask())
}
}
impl Eq for BVec3A {}
impl core::hash::Hash for BVec3A {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.bitmask().hash(state);
}
}
impl BitAnd for BVec3A {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self(self.0 & rhs.0)
}
}
impl BitAndAssign for BVec3A {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec3A {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
impl BitOrAssign for BVec3A {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec3A {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self(self.0 ^ rhs.0)
}
}
impl BitXorAssign for BVec3A {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec3A {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self(!self.0)
}
}
impl From<BVec3A> for mask32x4 {
#[inline]
fn from(t: BVec3A) -> Self {
t.0
}
}
impl fmt::Debug for BVec3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x})",
stringify!(BVec3A),
arr[0],
arr[1],
arr[2]
)
}
}
impl fmt::Display for BVec3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2])
}
}
impl From<[bool; 3]> for BVec3A {
#[inline]
fn from(a: [bool; 3]) -> Self {
Self::from_array(a)
}
}
impl From<BVec3A> for [bool; 3] {
#[inline]
fn from(mask: BVec3A) -> Self {
mask.into_bool_array()
}
}
impl From<BVec3A> for [u32; 3] {
#[inline]
fn from(mask: BVec3A) -> Self {
mask.into_u32_array()
}
}

258
vendor/glam/src/bool/coresimd/bvec4a.rs vendored Normal file
View File

@@ -0,0 +1,258 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
use core::simd::*;
#[repr(C)]
union UnionCast {
a: [u32; 4],
v: BVec4A,
}
/// Creates a 4-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec4a(x: bool, y: bool, z: bool, w: bool) -> BVec4A {
BVec4A::new(x, y, z, w)
}
/// A 4-dimensional SIMD vector mask.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct BVec4A(pub(crate) mask32x4);
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec4A {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
unsafe {
UnionCast {
a: [
MASK[x as usize],
MASK[y as usize],
MASK[z as usize],
MASK[w as usize],
],
}
.v
}
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 4]) -> Self {
Self::new(a[0], a[1], a[2], a[3])
}
/// Returns a bitmask with the lowest 4 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
self.0.to_bitmask() as u32
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
self.bitmask() != 0
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
self.bitmask() == 0xf
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
self.0.test(index)
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
self.0.set(index, value)
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 4] {
let bitmask = self.bitmask();
[
(bitmask & 1) != 0,
(bitmask & 2) != 0,
(bitmask & 4) != 0,
(bitmask & 8) != 0,
]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 4] {
let bitmask = self.bitmask();
[
MASK[(bitmask & 1) as usize],
MASK[((bitmask >> 1) & 1) as usize],
MASK[((bitmask >> 2) & 1) as usize],
MASK[((bitmask >> 3) & 1) as usize],
]
}
}
impl Default for BVec4A {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl PartialEq for BVec4A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.bitmask().eq(&rhs.bitmask())
}
}
impl Eq for BVec4A {}
impl core::hash::Hash for BVec4A {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.bitmask().hash(state);
}
}
impl BitAnd for BVec4A {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self(self.0 & rhs.0)
}
}
impl BitAndAssign for BVec4A {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec4A {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
impl BitOrAssign for BVec4A {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec4A {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self(self.0 ^ rhs.0)
}
}
impl BitXorAssign for BVec4A {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec4A {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self(!self.0)
}
}
impl From<BVec4A> for mask32x4 {
#[inline]
fn from(t: BVec4A) -> Self {
t.0
}
}
impl fmt::Debug for BVec4A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x}, {:#x})",
stringify!(BVec4A),
arr[0],
arr[1],
arr[2],
arr[3]
)
}
}
impl fmt::Display for BVec4A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3])
}
}
impl From<[bool; 4]> for BVec4A {
#[inline]
fn from(a: [bool; 4]) -> Self {
Self::from_array(a)
}
}
impl From<BVec4A> for [bool; 4] {
#[inline]
fn from(mask: BVec4A) -> Self {
mask.into_bool_array()
}
}
impl From<BVec4A> for [u32; 4] {
#[inline]
fn from(mask: BVec4A) -> Self {
mask.into_u32_array()
}
}

2
vendor/glam/src/bool/neon.rs vendored Normal file
View File

@@ -0,0 +1,2 @@
pub mod bvec3a;
pub mod bvec4a;

265
vendor/glam/src/bool/neon/bvec3a.rs vendored Normal file
View File

@@ -0,0 +1,265 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
use core::arch::aarch64::*;
#[repr(C)]
union UnionCast {
a: [u32; 4],
v: BVec3A,
}
/// Creates a 3-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec3a(x: bool, y: bool, z: bool) -> BVec3A {
BVec3A::new(x, y, z)
}
/// A 3-dimensional SIMD vector mask.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct BVec3A(pub(crate) uint32x4_t);
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec3A {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool) -> Self {
unsafe {
UnionCast {
a: [MASK[x as usize], MASK[y as usize], MASK[z as usize], 0],
}
.v
}
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 3]) -> Self {
Self::new(a[0], a[1], a[2])
}
/// Returns a bitmask with the lowest 3 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
let movemask = unsafe {
let mma = vandq_u32(self.0, vld1q_u32([1, 2, 4, 8].as_ptr())); // [0 1 2 3]
let mmb = vextq_u32(mma, mma, 2); // [2 3 0 1]
let mmc = vorrq_u32(mma, mmb); // [0+2 1+3 0+2 1+3]
let mmd = vextq_u32(mmc, mmc, 3); // [1+3 0+2 1+3 0+2]
let mme = vorrq_u32(mmc, mmd); // [0+1+2+3 ...]
vgetq_lane_u32(mme, 0)
};
movemask & 0x7
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
self.bitmask() != 0
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
self.bitmask() == 0x7
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
match index {
0 => (self.bitmask() & (1 << 0)) != 0,
1 => (self.bitmask() & (1 << 1)) != 0,
2 => (self.bitmask() & (1 << 2)) != 0,
_ => panic!("index out of bounds"),
}
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
self.0 = match index {
0 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 0) },
1 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 1) },
2 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 2) },
_ => panic!("index out of bounds"),
}
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 3] {
let bitmask = self.bitmask();
[(bitmask & 1) != 0, (bitmask & 2) != 0, (bitmask & 4) != 0]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 3] {
let bitmask = self.bitmask();
[
MASK[(bitmask & 1) as usize],
MASK[((bitmask >> 1) & 1) as usize],
MASK[((bitmask >> 2) & 1) as usize],
]
}
}
impl Default for BVec3A {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl PartialEq for BVec3A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.bitmask().eq(&rhs.bitmask())
}
}
impl Eq for BVec3A {}
impl core::hash::Hash for BVec3A {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.bitmask().hash(state);
}
}
impl BitAnd for BVec3A {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self(unsafe { vandq_u32(self.0, rhs.0) })
}
}
impl BitAndAssign for BVec3A {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec3A {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self(unsafe { vorrq_u32(self.0, rhs.0) })
}
}
impl BitOrAssign for BVec3A {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec3A {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self(unsafe { veorq_u32(self.0, rhs.0) })
}
}
impl BitXorAssign for BVec3A {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec3A {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self(unsafe { vmvnq_u32(self.0) })
}
}
impl From<BVec3A> for uint32x4_t {
#[inline]
fn from(t: BVec3A) -> Self {
t.0
}
}
impl fmt::Debug for BVec3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x})",
stringify!(BVec3A),
arr[0],
arr[1],
arr[2]
)
}
}
impl fmt::Display for BVec3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2])
}
}
impl From<[bool; 3]> for BVec3A {
#[inline]
fn from(a: [bool; 3]) -> Self {
Self::from_array(a)
}
}
impl From<BVec3A> for [bool; 3] {
#[inline]
fn from(mask: BVec3A) -> Self {
mask.into_bool_array()
}
}
impl From<BVec3A> for [u32; 3] {
#[inline]
fn from(mask: BVec3A) -> Self {
mask.into_u32_array()
}
}

277
vendor/glam/src/bool/neon/bvec4a.rs vendored Normal file
View File

@@ -0,0 +1,277 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
use core::arch::aarch64::*;
#[repr(C)]
union UnionCast {
a: [u32; 4],
v: BVec4A,
}
/// Creates a 4-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec4a(x: bool, y: bool, z: bool, w: bool) -> BVec4A {
BVec4A::new(x, y, z, w)
}
/// A 4-dimensional SIMD vector mask.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct BVec4A(pub(crate) uint32x4_t);
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec4A {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
unsafe {
UnionCast {
a: [
MASK[x as usize],
MASK[y as usize],
MASK[z as usize],
MASK[w as usize],
],
}
.v
}
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 4]) -> Self {
Self::new(a[0], a[1], a[2], a[3])
}
/// Returns a bitmask with the lowest 4 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
unsafe {
let mma = vandq_u32(self.0, vld1q_u32([1, 2, 4, 8].as_ptr())); // [0 1 2 3]
let mmb = vextq_u32(mma, mma, 2); // [2 3 0 1]
let mmc = vorrq_u32(mma, mmb); // [0+2 1+3 0+2 1+3]
let mmd = vextq_u32(mmc, mmc, 3); // [1+3 0+2 1+3 0+2]
let mme = vorrq_u32(mmc, mmd); // [0+1+2+3 ...]
vgetq_lane_u32(mme, 0)
}
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
self.bitmask() != 0
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
self.bitmask() == 0xf
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
match index {
0 => (self.bitmask() & (1 << 0)) != 0,
1 => (self.bitmask() & (1 << 1)) != 0,
2 => (self.bitmask() & (1 << 2)) != 0,
3 => (self.bitmask() & (1 << 3)) != 0,
_ => panic!("index out of bounds"),
}
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
self.0 = match index {
0 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 0) },
1 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 1) },
2 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 2) },
3 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 3) },
_ => panic!("index out of bounds"),
}
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 4] {
let bitmask = self.bitmask();
[
(bitmask & 1) != 0,
(bitmask & 2) != 0,
(bitmask & 4) != 0,
(bitmask & 8) != 0,
]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 4] {
let bitmask = self.bitmask();
[
MASK[(bitmask & 1) as usize],
MASK[((bitmask >> 1) & 1) as usize],
MASK[((bitmask >> 2) & 1) as usize],
MASK[((bitmask >> 3) & 1) as usize],
]
}
}
impl Default for BVec4A {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl PartialEq for BVec4A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.bitmask().eq(&rhs.bitmask())
}
}
impl Eq for BVec4A {}
impl core::hash::Hash for BVec4A {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.bitmask().hash(state);
}
}
impl BitAnd for BVec4A {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self(unsafe { vandq_u32(self.0, rhs.0) })
}
}
impl BitAndAssign for BVec4A {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec4A {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self(unsafe { vorrq_u32(self.0, rhs.0) })
}
}
impl BitOrAssign for BVec4A {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec4A {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self(unsafe { veorq_u32(self.0, rhs.0) })
}
}
impl BitXorAssign for BVec4A {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec4A {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self(unsafe { vmvnq_u32(self.0) })
}
}
impl From<BVec4A> for uint32x4_t {
#[inline]
fn from(t: BVec4A) -> Self {
t.0
}
}
impl fmt::Debug for BVec4A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x}, {:#x})",
stringify!(BVec4A),
arr[0],
arr[1],
arr[2],
arr[3]
)
}
}
impl fmt::Display for BVec4A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3])
}
}
impl From<[bool; 4]> for BVec4A {
#[inline]
fn from(a: [bool; 4]) -> Self {
Self::from_array(a)
}
}
impl From<BVec4A> for [bool; 4] {
#[inline]
fn from(mask: BVec4A) -> Self {
mask.into_bool_array()
}
}
impl From<BVec4A> for [u32; 4] {
#[inline]
fn from(mask: BVec4A) -> Self {
mask.into_u32_array()
}
}

2
vendor/glam/src/bool/scalar.rs vendored Normal file
View File

@@ -0,0 +1,2 @@
pub mod bvec3a;
pub mod bvec4a;

240
vendor/glam/src/bool/scalar/bvec3a.rs vendored Normal file
View File

@@ -0,0 +1,240 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
/// Creates a 3-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec3a(x: bool, y: bool, z: bool) -> BVec3A {
BVec3A::new(x, y, z)
}
/// A 3-dimensional `u32` vector mask.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C, align(16))]
pub struct BVec3A {
pub x: u32,
pub y: u32,
pub z: u32,
}
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec3A {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool) -> Self {
Self {
x: MASK[x as usize],
y: MASK[y as usize],
z: MASK[z as usize],
}
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 3]) -> Self {
Self::new(a[0], a[1], a[2])
}
/// Returns a bitmask with the lowest 3 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
(self.x & 0x1) | ((self.y & 0x1) << 1) | ((self.z & 0x1) << 2)
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
((self.x | self.y | self.z) & 0x1) != 0
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
((self.x & self.y & self.z) & 0x1) != 0
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
match index {
0 => (self.x & 0x1) != 0,
1 => (self.y & 0x1) != 0,
2 => (self.z & 0x1) != 0,
_ => panic!("index out of bounds"),
}
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
match index {
0 => self.x = MASK[value as usize],
1 => self.y = MASK[value as usize],
2 => self.z = MASK[value as usize],
_ => panic!("index out of bounds"),
}
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 3] {
[
(self.x & 0x1) != 0,
(self.y & 0x1) != 0,
(self.z & 0x1) != 0,
]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 3] {
[self.x, self.y, self.z]
}
}
impl Default for BVec3A {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl BitAnd for BVec3A {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self {
x: self.x & rhs.x,
y: self.y & rhs.y,
z: self.z & rhs.z,
}
}
}
impl BitAndAssign for BVec3A {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec3A {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self {
x: self.x | rhs.x,
y: self.y | rhs.y,
z: self.z | rhs.z,
}
}
}
impl BitOrAssign for BVec3A {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec3A {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self {
x: self.x ^ rhs.x,
y: self.y ^ rhs.y,
z: self.z ^ rhs.z,
}
}
}
impl BitXorAssign for BVec3A {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec3A {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self {
x: !self.x,
y: !self.y,
z: !self.z,
}
}
}
impl fmt::Debug for BVec3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x})",
stringify!(BVec3A),
arr[0],
arr[1],
arr[2]
)
}
}
impl fmt::Display for BVec3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2])
}
}
impl From<[bool; 3]> for BVec3A {
#[inline]
fn from(a: [bool; 3]) -> Self {
Self::from_array(a)
}
}
impl From<BVec3A> for [bool; 3] {
#[inline]
fn from(mask: BVec3A) -> Self {
mask.into_bool_array()
}
}
impl From<BVec3A> for [u32; 3] {
#[inline]
fn from(mask: BVec3A) -> Self {
mask.into_u32_array()
}
}

250
vendor/glam/src/bool/scalar/bvec4a.rs vendored Normal file
View File

@@ -0,0 +1,250 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
/// Creates a 4-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec4a(x: bool, y: bool, z: bool, w: bool) -> BVec4A {
BVec4A::new(x, y, z, w)
}
/// A 4-dimensional `u32` vector mask.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C, align(16))]
pub struct BVec4A {
pub x: u32,
pub y: u32,
pub z: u32,
pub w: u32,
}
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec4A {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
Self {
x: MASK[x as usize],
y: MASK[y as usize],
z: MASK[z as usize],
w: MASK[w as usize],
}
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 4]) -> Self {
Self::new(a[0], a[1], a[2], a[3])
}
/// Returns a bitmask with the lowest 4 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
(self.x & 0x1) | ((self.y & 0x1) << 1) | ((self.z & 0x1) << 2) | ((self.w & 0x1) << 3)
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
((self.x | self.y | self.z | self.w) & 0x1) != 0
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
((self.x & self.y & self.z & self.w) & 0x1) != 0
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
match index {
0 => (self.x & 0x1) != 0,
1 => (self.y & 0x1) != 0,
2 => (self.z & 0x1) != 0,
3 => (self.w & 0x1) != 0,
_ => panic!("index out of bounds"),
}
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
match index {
0 => self.x = MASK[value as usize],
1 => self.y = MASK[value as usize],
2 => self.z = MASK[value as usize],
3 => self.w = MASK[value as usize],
_ => panic!("index out of bounds"),
}
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 4] {
[
(self.x & 0x1) != 0,
(self.y & 0x1) != 0,
(self.z & 0x1) != 0,
(self.w & 0x1) != 0,
]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 4] {
[self.x, self.y, self.z, self.w]
}
}
impl Default for BVec4A {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl BitAnd for BVec4A {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self {
x: self.x & rhs.x,
y: self.y & rhs.y,
z: self.z & rhs.z,
w: self.w & rhs.w,
}
}
}
impl BitAndAssign for BVec4A {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec4A {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self {
x: self.x | rhs.x,
y: self.y | rhs.y,
z: self.z | rhs.z,
w: self.w | rhs.w,
}
}
}
impl BitOrAssign for BVec4A {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec4A {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self {
x: self.x ^ rhs.x,
y: self.y ^ rhs.y,
z: self.z ^ rhs.z,
w: self.w ^ rhs.w,
}
}
}
impl BitXorAssign for BVec4A {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec4A {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self {
x: !self.x,
y: !self.y,
z: !self.z,
w: !self.w,
}
}
}
impl fmt::Debug for BVec4A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x}, {:#x})",
stringify!(BVec4A),
arr[0],
arr[1],
arr[2],
arr[3]
)
}
}
impl fmt::Display for BVec4A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3])
}
}
impl From<[bool; 4]> for BVec4A {
#[inline]
fn from(a: [bool; 4]) -> Self {
Self::from_array(a)
}
}
impl From<BVec4A> for [bool; 4] {
#[inline]
fn from(mask: BVec4A) -> Self {
mask.into_bool_array()
}
}
impl From<BVec4A> for [u32; 4] {
#[inline]
fn from(mask: BVec4A) -> Self {
mask.into_u32_array()
}
}

2
vendor/glam/src/bool/sse2.rs vendored Normal file
View File

@@ -0,0 +1,2 @@
pub mod bvec3a;
pub mod bvec4a;

257
vendor/glam/src/bool/sse2/bvec3a.rs vendored Normal file
View File

@@ -0,0 +1,257 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
#[repr(C)]
union UnionCast {
a: [u32; 4],
v: BVec3A,
}
/// Creates a 3-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec3a(x: bool, y: bool, z: bool) -> BVec3A {
BVec3A::new(x, y, z)
}
/// A 3-dimensional SIMD vector mask.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct BVec3A(pub(crate) __m128);
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec3A {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool) -> Self {
unsafe {
UnionCast {
a: [MASK[x as usize], MASK[y as usize], MASK[z as usize], 0],
}
.v
}
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 3]) -> Self {
Self::new(a[0], a[1], a[2])
}
/// Returns a bitmask with the lowest 3 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
unsafe { (_mm_movemask_ps(self.0) as u32) & 0x7 }
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
self.bitmask() != 0
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
self.bitmask() == 0x7
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
match index {
0 => (self.bitmask() & (1 << 0)) != 0,
1 => (self.bitmask() & (1 << 1)) != 0,
2 => (self.bitmask() & (1 << 2)) != 0,
_ => panic!("index out of bounds"),
}
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
use crate::Vec3A;
let mut v = Vec3A(self.0);
v[index] = f32::from_bits(MASK[value as usize]);
self.0 = v.0;
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 3] {
let bitmask = self.bitmask();
[(bitmask & 1) != 0, (bitmask & 2) != 0, (bitmask & 4) != 0]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 3] {
let bitmask = self.bitmask();
[
MASK[(bitmask & 1) as usize],
MASK[((bitmask >> 1) & 1) as usize],
MASK[((bitmask >> 2) & 1) as usize],
]
}
}
impl Default for BVec3A {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl PartialEq for BVec3A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.bitmask().eq(&rhs.bitmask())
}
}
impl Eq for BVec3A {}
impl core::hash::Hash for BVec3A {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.bitmask().hash(state);
}
}
impl BitAnd for BVec3A {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self(unsafe { _mm_and_ps(self.0, rhs.0) })
}
}
impl BitAndAssign for BVec3A {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec3A {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self(unsafe { _mm_or_ps(self.0, rhs.0) })
}
}
impl BitOrAssign for BVec3A {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec3A {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self(unsafe { _mm_xor_ps(self.0, rhs.0) })
}
}
impl BitXorAssign for BVec3A {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec3A {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self(unsafe { _mm_andnot_ps(self.0, _mm_set_ps1(f32::from_bits(0xff_ff_ff_ff))) })
}
}
impl From<BVec3A> for __m128 {
#[inline]
fn from(t: BVec3A) -> Self {
t.0
}
}
impl fmt::Debug for BVec3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x})",
stringify!(BVec3A),
arr[0],
arr[1],
arr[2]
)
}
}
impl fmt::Display for BVec3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2])
}
}
impl From<[bool; 3]> for BVec3A {
#[inline]
fn from(a: [bool; 3]) -> Self {
Self::from_array(a)
}
}
impl From<BVec3A> for [bool; 3] {
#[inline]
fn from(mask: BVec3A) -> Self {
mask.into_bool_array()
}
}
impl From<BVec3A> for [u32; 3] {
#[inline]
fn from(mask: BVec3A) -> Self {
mask.into_u32_array()
}
}

270
vendor/glam/src/bool/sse2/bvec4a.rs vendored Normal file
View File

@@ -0,0 +1,270 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
#[repr(C)]
union UnionCast {
a: [u32; 4],
v: BVec4A,
}
/// Creates a 4-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec4a(x: bool, y: bool, z: bool, w: bool) -> BVec4A {
BVec4A::new(x, y, z, w)
}
/// A 4-dimensional SIMD vector mask.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct BVec4A(pub(crate) __m128);
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec4A {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
unsafe {
UnionCast {
a: [
MASK[x as usize],
MASK[y as usize],
MASK[z as usize],
MASK[w as usize],
],
}
.v
}
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 4]) -> Self {
Self::new(a[0], a[1], a[2], a[3])
}
/// Returns a bitmask with the lowest 4 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
unsafe { _mm_movemask_ps(self.0) as u32 }
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
self.bitmask() != 0
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
self.bitmask() == 0xf
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
match index {
0 => (self.bitmask() & (1 << 0)) != 0,
1 => (self.bitmask() & (1 << 1)) != 0,
2 => (self.bitmask() & (1 << 2)) != 0,
3 => (self.bitmask() & (1 << 3)) != 0,
_ => panic!("index out of bounds"),
}
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
use crate::Vec4;
let mut v = Vec4(self.0);
v[index] = f32::from_bits(MASK[value as usize]);
self.0 = v.0;
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 4] {
let bitmask = self.bitmask();
[
(bitmask & 1) != 0,
(bitmask & 2) != 0,
(bitmask & 4) != 0,
(bitmask & 8) != 0,
]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 4] {
let bitmask = self.bitmask();
[
MASK[(bitmask & 1) as usize],
MASK[((bitmask >> 1) & 1) as usize],
MASK[((bitmask >> 2) & 1) as usize],
MASK[((bitmask >> 3) & 1) as usize],
]
}
}
impl Default for BVec4A {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl PartialEq for BVec4A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.bitmask().eq(&rhs.bitmask())
}
}
impl Eq for BVec4A {}
impl core::hash::Hash for BVec4A {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.bitmask().hash(state);
}
}
impl BitAnd for BVec4A {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self(unsafe { _mm_and_ps(self.0, rhs.0) })
}
}
impl BitAndAssign for BVec4A {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec4A {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self(unsafe { _mm_or_ps(self.0, rhs.0) })
}
}
impl BitOrAssign for BVec4A {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec4A {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self(unsafe { _mm_xor_ps(self.0, rhs.0) })
}
}
impl BitXorAssign for BVec4A {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec4A {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self(unsafe { _mm_andnot_ps(self.0, _mm_set_ps1(f32::from_bits(0xff_ff_ff_ff))) })
}
}
impl From<BVec4A> for __m128 {
#[inline]
fn from(t: BVec4A) -> Self {
t.0
}
}
impl fmt::Debug for BVec4A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x}, {:#x})",
stringify!(BVec4A),
arr[0],
arr[1],
arr[2],
arr[3]
)
}
}
impl fmt::Display for BVec4A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3])
}
}
impl From<[bool; 4]> for BVec4A {
#[inline]
fn from(a: [bool; 4]) -> Self {
Self::from_array(a)
}
}
impl From<BVec4A> for [bool; 4] {
#[inline]
fn from(mask: BVec4A) -> Self {
mask.into_bool_array()
}
}
impl From<BVec4A> for [u32; 4] {
#[inline]
fn from(mask: BVec4A) -> Self {
mask.into_u32_array()
}
}

2
vendor/glam/src/bool/wasm32.rs vendored Normal file
View File

@@ -0,0 +1,2 @@
pub mod bvec3a;
pub mod bvec4a;

248
vendor/glam/src/bool/wasm32/bvec3a.rs vendored Normal file
View File

@@ -0,0 +1,248 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
use core::arch::wasm32::*;
/// Creates a 3-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec3a(x: bool, y: bool, z: bool) -> BVec3A {
BVec3A::new(x, y, z)
}
/// A 3-dimensional SIMD vector mask.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct BVec3A(pub(crate) v128);
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec3A {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool) -> Self {
Self(u32x4(
MASK[x as usize],
MASK[y as usize],
MASK[z as usize],
0,
))
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 3]) -> Self {
Self::new(a[0], a[1], a[2])
}
/// Returns a bitmask with the lowest 3 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
(u32x4_bitmask(self.0) & 0x7) as u32
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
self.bitmask() != 0
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
self.bitmask() == 0x7
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
match index {
0 => (self.bitmask() & (1 << 0)) != 0,
1 => (self.bitmask() & (1 << 1)) != 0,
2 => (self.bitmask() & (1 << 2)) != 0,
_ => panic!("index out of bounds"),
}
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
use crate::Vec3A;
let mut v = Vec3A(self.0);
v[index] = f32::from_bits(MASK[value as usize]);
self.0 = v.0;
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 3] {
let bitmask = self.bitmask();
[(bitmask & 1) != 0, (bitmask & 2) != 0, (bitmask & 4) != 0]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 3] {
let bitmask = self.bitmask();
[
MASK[(bitmask & 1) as usize],
MASK[((bitmask >> 1) & 1) as usize],
MASK[((bitmask >> 2) & 1) as usize],
]
}
}
impl Default for BVec3A {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl PartialEq for BVec3A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.bitmask().eq(&rhs.bitmask())
}
}
impl Eq for BVec3A {}
impl core::hash::Hash for BVec3A {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.bitmask().hash(state);
}
}
impl BitAnd for BVec3A {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self(v128_and(self.0, rhs.0))
}
}
impl BitAndAssign for BVec3A {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec3A {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self(v128_or(self.0, rhs.0))
}
}
impl BitOrAssign for BVec3A {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec3A {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self(v128_xor(self.0, rhs.0))
}
}
impl BitXorAssign for BVec3A {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec3A {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self(v128_not(self.0))
}
}
impl From<BVec3A> for v128 {
#[inline]
fn from(t: BVec3A) -> Self {
t.0
}
}
impl fmt::Debug for BVec3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x})",
stringify!(BVec3A),
arr[0],
arr[1],
arr[2]
)
}
}
impl fmt::Display for BVec3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2])
}
}
impl From<[bool; 3]> for BVec3A {
#[inline]
fn from(a: [bool; 3]) -> Self {
Self::from_array(a)
}
}
impl From<BVec3A> for [bool; 3] {
#[inline]
fn from(mask: BVec3A) -> Self {
mask.into_bool_array()
}
}
impl From<BVec3A> for [u32; 3] {
#[inline]
fn from(mask: BVec3A) -> Self {
mask.into_u32_array()
}
}

256
vendor/glam/src/bool/wasm32/bvec4a.rs vendored Normal file
View File

@@ -0,0 +1,256 @@
// Generated from vec_mask.rs.tera template. Edit the template, not the generated file.
use core::fmt;
use core::ops::*;
use core::arch::wasm32::*;
/// Creates a 4-dimensional `bool` vector mask.
#[inline(always)]
#[must_use]
pub const fn bvec4a(x: bool, y: bool, z: bool, w: bool) -> BVec4A {
BVec4A::new(x, y, z, w)
}
/// A 4-dimensional SIMD vector mask.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct BVec4A(pub(crate) v128);
const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
impl BVec4A {
/// All false.
pub const FALSE: Self = Self::splat(false);
/// All true.
pub const TRUE: Self = Self::splat(true);
/// Creates a new vector mask.
#[inline(always)]
#[must_use]
pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
Self(u32x4(
MASK[x as usize],
MASK[y as usize],
MASK[z as usize],
MASK[w as usize],
))
}
/// Creates a vector mask with all elements set to `v`.
#[inline]
#[must_use]
pub const fn splat(v: bool) -> Self {
Self::new(v, v, v, v)
}
/// Creates a new vector mask from a bool array.
#[inline]
#[must_use]
pub const fn from_array(a: [bool; 4]) -> Self {
Self::new(a[0], a[1], a[2], a[3])
}
/// Returns a bitmask with the lowest 4 bits set from the elements of `self`.
///
/// A true element results in a `1` bit and a false element in a `0` bit. Element `x` goes
/// into the first lowest bit, element `y` into the second, etc.
#[inline]
#[must_use]
pub fn bitmask(self) -> u32 {
u32x4_bitmask(self.0) as u32
}
/// Returns true if any of the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn any(self) -> bool {
self.bitmask() != 0
}
/// Returns true if all the elements are true, false otherwise.
#[inline]
#[must_use]
pub fn all(self) -> bool {
self.bitmask() == 0xf
}
/// Tests the value at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
#[must_use]
pub fn test(&self, index: usize) -> bool {
match index {
0 => (self.bitmask() & (1 << 0)) != 0,
1 => (self.bitmask() & (1 << 1)) != 0,
2 => (self.bitmask() & (1 << 2)) != 0,
3 => (self.bitmask() & (1 << 3)) != 0,
_ => panic!("index out of bounds"),
}
}
/// Sets the element at `index`.
///
/// Panics if `index` is greater than 3.
#[inline]
pub fn set(&mut self, index: usize, value: bool) {
use crate::Vec4;
let mut v = Vec4(self.0);
v[index] = f32::from_bits(MASK[value as usize]);
self.0 = v.0;
}
#[inline]
#[must_use]
fn into_bool_array(self) -> [bool; 4] {
let bitmask = self.bitmask();
[
(bitmask & 1) != 0,
(bitmask & 2) != 0,
(bitmask & 4) != 0,
(bitmask & 8) != 0,
]
}
#[inline]
#[must_use]
fn into_u32_array(self) -> [u32; 4] {
let bitmask = self.bitmask();
[
MASK[(bitmask & 1) as usize],
MASK[((bitmask >> 1) & 1) as usize],
MASK[((bitmask >> 2) & 1) as usize],
MASK[((bitmask >> 3) & 1) as usize],
]
}
}
impl Default for BVec4A {
#[inline]
fn default() -> Self {
Self::FALSE
}
}
impl PartialEq for BVec4A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.bitmask().eq(&rhs.bitmask())
}
}
impl Eq for BVec4A {}
impl core::hash::Hash for BVec4A {
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.bitmask().hash(state);
}
}
impl BitAnd for BVec4A {
type Output = Self;
#[inline]
fn bitand(self, rhs: Self) -> Self {
Self(v128_and(self.0, rhs.0))
}
}
impl BitAndAssign for BVec4A {
#[inline]
fn bitand_assign(&mut self, rhs: Self) {
*self = self.bitand(rhs);
}
}
impl BitOr for BVec4A {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self {
Self(v128_or(self.0, rhs.0))
}
}
impl BitOrAssign for BVec4A {
#[inline]
fn bitor_assign(&mut self, rhs: Self) {
*self = self.bitor(rhs);
}
}
impl BitXor for BVec4A {
type Output = Self;
#[inline]
fn bitxor(self, rhs: Self) -> Self {
Self(v128_xor(self.0, rhs.0))
}
}
impl BitXorAssign for BVec4A {
#[inline]
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.bitxor(rhs);
}
}
impl Not for BVec4A {
type Output = Self;
#[inline]
fn not(self) -> Self {
Self(v128_not(self.0))
}
}
impl From<BVec4A> for v128 {
#[inline]
fn from(t: BVec4A) -> Self {
t.0
}
}
impl fmt::Debug for BVec4A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_u32_array();
write!(
f,
"{}({:#x}, {:#x}, {:#x}, {:#x})",
stringify!(BVec4A),
arr[0],
arr[1],
arr[2],
arr[3]
)
}
}
impl fmt::Display for BVec4A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let arr = self.into_bool_array();
write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3])
}
}
impl From<[bool; 4]> for BVec4A {
#[inline]
fn from(a: [bool; 4]) -> Self {
Self::from_array(a)
}
}
impl From<BVec4A> for [bool; 4] {
#[inline]
fn from(mask: BVec4A) -> Self {
mask.into_bool_array()
}
}
impl From<BVec4A> for [u32; 4] {
#[inline]
fn from(mask: BVec4A) -> Self {
mask.into_u32_array()
}
}

57
vendor/glam/src/coresimd.rs vendored Normal file
View File

@@ -0,0 +1,57 @@
use core::simd::{num::SimdFloat, *};
/// Calculates the vector 3 dot product and returns answer in x lane of f32x4.
#[inline(always)]
pub(crate) fn dot3_in_x(lhs: f32x4, rhs: f32x4) -> f32x4 {
let x2_y2_z2_w2 = lhs * rhs;
let y2_0_0_0 = simd_swizzle!(x2_y2_z2_w2, [1, 0, 0, 0]);
let z2_0_0_0 = simd_swizzle!(x2_y2_z2_w2, [2, 0, 0, 0]);
let x2y2_0_0_0 = x2_y2_z2_w2 + y2_0_0_0;
x2y2_0_0_0 + z2_0_0_0
}
/// Calculates the vector 4 dot product and returns answer in x lane of f32x4.
#[inline(always)]
pub(crate) fn dot4_in_x(lhs: f32x4, rhs: f32x4) -> f32x4 {
let x2_y2_z2_w2 = lhs * rhs;
let z2_w2_0_0 = simd_swizzle!(x2_y2_z2_w2, [2, 3, 0, 0]);
let x2z2_y2w2_0_0 = x2_y2_z2_w2 + z2_w2_0_0;
let y2w2_0_0_0 = simd_swizzle!(x2z2_y2w2_0_0, [1, 0, 0, 0]);
x2z2_y2w2_0_0 + y2w2_0_0_0
}
#[inline]
pub(crate) fn dot3(lhs: f32x4, rhs: f32x4) -> f32 {
dot3_in_x(lhs, rhs)[0]
}
#[inline]
pub(crate) fn dot3_into_f32x4(lhs: f32x4, rhs: f32x4) -> f32x4 {
let dot_in_x = dot3_in_x(lhs, rhs);
simd_swizzle!(dot_in_x, [0, 0, 0, 0])
}
#[inline]
pub(crate) fn dot4(lhs: f32x4, rhs: f32x4) -> f32 {
dot4_in_x(lhs, rhs)[0]
}
#[inline]
pub(crate) fn dot4_into_f32x4(lhs: f32x4, rhs: f32x4) -> f32x4 {
let dot_in_x = dot4_in_x(lhs, rhs);
simd_swizzle!(dot_in_x, [0, 0, 0, 0])
}
#[inline(always)]
pub(crate) fn f32x4_bitand(a: f32x4, b: f32x4) -> f32x4 {
let a = a.to_bits();
let b = b.to_bits();
f32x4::from_bits(a & b)
}
#[inline(always)]
pub(crate) fn f32x4_bitxor(a: f32x4, b: f32x4) -> f32x4 {
let a = a.to_bits();
let b = b.to_bits();
f32x4::from_bits(a ^ b)
}

40
vendor/glam/src/deref.rs vendored Normal file
View File

@@ -0,0 +1,40 @@
#[cfg(not(feature = "scalar-math"))]
#[cfg_attr(target_arch = "spirv", repr(simd))]
#[cfg_attr(not(target_arch = "spirv"), repr(C))]
pub struct Vec3<T> {
pub x: T,
pub y: T,
pub z: T,
}
#[cfg(not(feature = "scalar-math"))]
#[cfg_attr(target_arch = "spirv", repr(simd))]
#[cfg_attr(not(target_arch = "spirv"), repr(C))]
pub struct Vec4<T> {
pub x: T,
pub y: T,
pub z: T,
pub w: T,
}
#[cfg(not(feature = "scalar-math"))]
#[cfg_attr(not(target_arch = "spirv"), repr(C))]
pub struct Cols2<V> {
pub x_axis: V,
pub y_axis: V,
}
#[cfg_attr(not(target_arch = "spirv"), repr(C))]
pub struct Cols3<V> {
pub x_axis: V,
pub y_axis: V,
pub z_axis: V,
}
#[cfg_attr(not(target_arch = "spirv"), repr(C))]
pub struct Cols4<V> {
pub x_axis: V,
pub y_axis: V,
pub z_axis: V,
pub w_axis: V,
}

444
vendor/glam/src/euler.rs vendored Normal file
View File

@@ -0,0 +1,444 @@
// Based on Ken Shoemake. 1994. Euler angle conversion. Graphics gems IV. Academic Press
// Professional, Inc., USA, 222229.
use crate::{DMat3, DMat4, DQuat, DVec3, Mat3, Mat3A, Mat4, Quat, Vec3, Vec3A, Vec3Swizzles};
/// Euler rotation sequences.
///
/// The three elemental rotations may be extrinsic (rotations about the axes xyz of the original
/// coordinate system, which is assumed to remain motionless), or intrinsic(rotations about the
/// axes of the rotating coordinate system XYZ, solidary with the moving body, which changes its
/// orientation after each elemental rotation).
///
/// ```
/// # use glam::{EulerRot, Mat3};
/// # let i = core::f32::consts::FRAC_PI_2;
/// # let j = core::f32::consts::FRAC_PI_4;
/// # let k = core::f32::consts::FRAC_PI_8;
/// let m_intrinsic = Mat3::from_rotation_x(i) * Mat3::from_rotation_y(j) * Mat3::from_rotation_z(k);
/// let n_intrinsic = Mat3::from_euler(EulerRot::XYZ, i, j, k);
/// assert!(m_intrinsic.abs_diff_eq(n_intrinsic, 2e-6));
///
/// let m_extrinsic = Mat3::from_rotation_z(k) * Mat3::from_rotation_y(j) * Mat3::from_rotation_x(i);
/// let n_extrinsic = Mat3::from_euler(EulerRot::XYZEx, i, j, k);
/// assert!(m_extrinsic.abs_diff_eq(n_extrinsic, 2e-6));
/// ```
///
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum EulerRot {
/// Intrinsic three-axis rotation ZYX
ZYX,
/// Intrinsic three-axis rotation ZXY
ZXY,
/// Intrinsic three-axis rotation YXZ
YXZ,
/// Intrinsic three-axis rotation YZX
YZX,
/// Intrinsic three-axis rotation XYZ
XYZ,
/// Intrinsic three-axis rotation XZY
XZY,
/// Intrinsic two-axis rotation ZYZ
ZYZ,
/// Intrinsic two-axis rotation ZXZ
ZXZ,
/// Intrinsic two-axis rotation YXY
YXY,
/// Intrinsic two-axis rotation YZY
YZY,
/// Intrinsic two-axis rotation XYX
XYX,
/// Intrinsic two-axis rotation XZX
XZX,
/// Extrinsic three-axis rotation ZYX
ZYXEx,
/// Extrinsic three-axis rotation ZXY
ZXYEx,
/// Extrinsic three-axis rotation YXZ
YXZEx,
/// Extrinsic three-axis rotation YZX
YZXEx,
/// Extrinsic three-axis rotation XYZ
XYZEx,
/// Extrinsic three-axis rotation XZY
XZYEx,
/// Extrinsic two-axis rotation ZYZ
ZYZEx,
/// Extrinsic two-axis rotation ZXZ
ZXZEx,
/// Extrinsic two-axis rotation YXY
YXYEx,
/// Extrinsic two-axis rotation YZY
YZYEx,
/// Extrinsic two-axis rotation XYX
XYXEx,
/// Extrinsic two-axis rotation XZX
XZXEx,
}
impl Default for EulerRot {
/// Default `YXZ` as yaw (y-axis), pitch (x-axis), roll (z-axis).
fn default() -> Self {
Self::YXZ
}
}
pub(crate) trait ToEuler {
type Scalar;
fn to_euler_angles(self, order: EulerRot) -> (Self::Scalar, Self::Scalar, Self::Scalar);
}
pub(crate) trait FromEuler {
type Scalar;
fn from_euler_angles(
order: EulerRot,
i: Self::Scalar,
j: Self::Scalar,
k: Self::Scalar,
) -> Self;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Axis {
X = 0,
Y = 1,
Z = 2,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Parity {
Odd = 0,
Even = 1,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Repeated {
No = 0,
Yes = 1,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Frame {
Relative = 0,
Static = 1,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
struct Order {
initial_axis: Axis,
parity_even: bool,
initial_repeated: bool,
frame_static: bool,
}
impl Order {
const fn new(
initial_axis: Axis,
parity: Parity,
initial_repeated: Repeated,
frame: Frame,
) -> Self {
Self {
initial_axis,
parity_even: parity as u32 == Parity::Even as u32,
initial_repeated: initial_repeated as u32 == Repeated::Yes as u32,
frame_static: frame as u32 == Frame::Static as u32,
}
}
const fn from_euler(euler: EulerRot) -> Self {
match euler {
EulerRot::XYZ => Self::new(Axis::X, Parity::Even, Repeated::No, Frame::Static),
EulerRot::XYX => Self::new(Axis::X, Parity::Even, Repeated::Yes, Frame::Static),
EulerRot::XZY => Self::new(Axis::X, Parity::Odd, Repeated::No, Frame::Static),
EulerRot::XZX => Self::new(Axis::X, Parity::Odd, Repeated::Yes, Frame::Static),
EulerRot::YZX => Self::new(Axis::Y, Parity::Even, Repeated::No, Frame::Static),
EulerRot::YZY => Self::new(Axis::Y, Parity::Even, Repeated::Yes, Frame::Static),
EulerRot::YXZ => Self::new(Axis::Y, Parity::Odd, Repeated::No, Frame::Static),
EulerRot::YXY => Self::new(Axis::Y, Parity::Odd, Repeated::Yes, Frame::Static),
EulerRot::ZXY => Self::new(Axis::Z, Parity::Even, Repeated::No, Frame::Static),
EulerRot::ZXZ => Self::new(Axis::Z, Parity::Even, Repeated::Yes, Frame::Static),
EulerRot::ZYX => Self::new(Axis::Z, Parity::Odd, Repeated::No, Frame::Static),
EulerRot::ZYZ => Self::new(Axis::Z, Parity::Odd, Repeated::Yes, Frame::Static),
EulerRot::ZYXEx => Self::new(Axis::X, Parity::Even, Repeated::No, Frame::Relative),
EulerRot::XYXEx => Self::new(Axis::X, Parity::Even, Repeated::Yes, Frame::Relative),
EulerRot::YZXEx => Self::new(Axis::X, Parity::Odd, Repeated::No, Frame::Relative),
EulerRot::XZXEx => Self::new(Axis::X, Parity::Odd, Repeated::Yes, Frame::Relative),
EulerRot::XZYEx => Self::new(Axis::Y, Parity::Even, Repeated::No, Frame::Relative),
EulerRot::YZYEx => Self::new(Axis::Y, Parity::Even, Repeated::Yes, Frame::Relative),
EulerRot::ZXYEx => Self::new(Axis::Y, Parity::Odd, Repeated::No, Frame::Relative),
EulerRot::YXYEx => Self::new(Axis::Y, Parity::Odd, Repeated::Yes, Frame::Relative),
EulerRot::YXZEx => Self::new(Axis::Z, Parity::Even, Repeated::No, Frame::Relative),
EulerRot::ZXZEx => Self::new(Axis::Z, Parity::Even, Repeated::Yes, Frame::Relative),
EulerRot::XYZEx => Self::new(Axis::Z, Parity::Odd, Repeated::No, Frame::Relative),
EulerRot::ZYZEx => Self::new(Axis::Z, Parity::Odd, Repeated::Yes, Frame::Relative),
}
}
const fn next_axis(i: usize) -> usize {
(i + 1) % 3
}
const fn prev_axis(i: usize) -> usize {
if i > 0 {
i - 1
} else {
2
}
}
const fn angle_order(self) -> (usize, usize, usize) {
let i = self.initial_axis as usize;
let j = if self.parity_even {
Order::next_axis(i)
} else {
Order::prev_axis(i)
};
let k = if self.parity_even {
Order::prev_axis(i)
} else {
Order::next_axis(i)
};
(i, j, k)
}
}
macro_rules! impl_mat3_from_euler {
($scalar:ident, $mat3:ident, $vec3:ident) => {
impl FromEuler for $mat3 {
type Scalar = $scalar;
fn from_euler_angles(
euler: EulerRot,
x: Self::Scalar,
y: Self::Scalar,
z: Self::Scalar,
) -> Self {
use crate::$scalar::math;
let order = Order::from_euler(euler);
let (i, j, k) = order.angle_order();
let mut angles = if order.frame_static {
$vec3::new(x, y, z)
} else {
$vec3::new(z, y, x)
};
// rotation direction is reverse from original paper
if order.parity_even {
angles = -angles;
}
let (si, ci) = math::sin_cos(angles.x);
let (sj, cj) = math::sin_cos(angles.y);
let (sh, ch) = math::sin_cos(angles.z);
let cc = ci * ch;
let cs = ci * sh;
let sc = si * ch;
let ss = si * sh;
let mut m = [[0.0; 3]; 3];
if order.initial_repeated {
m[i][i] = cj;
m[i][j] = sj * si;
m[i][k] = sj * ci;
m[j][i] = sj * sh;
m[j][j] = -cj * ss + cc;
m[j][k] = -cj * cs - sc;
m[k][i] = -sj * ch;
m[k][j] = cj * sc + cs;
m[k][k] = cj * cc - ss;
} else {
m[i][i] = cj * ch;
m[i][j] = sj * sc - cs;
m[i][k] = sj * cc + ss;
m[j][i] = cj * sh;
m[j][j] = sj * ss + cc;
m[j][k] = sj * cs - sc;
m[k][i] = -sj;
m[k][j] = cj * si;
m[k][k] = cj * ci;
}
$mat3::from_cols_array_2d(&m)
}
}
};
}
macro_rules! impl_mat4_from_euler {
($scalar:ident, $mat4:ident, $mat3:ident) => {
impl FromEuler for $mat4 {
type Scalar = $scalar;
fn from_euler_angles(
euler: EulerRot,
x: Self::Scalar,
y: Self::Scalar,
z: Self::Scalar,
) -> Self {
$mat4::from_mat3($mat3::from_euler_angles(euler, x, y, z))
}
}
};
}
macro_rules! impl_quat_from_euler {
($scalar:ident, $quat:ident, $vec3:ident) => {
impl FromEuler for $quat {
type Scalar = $scalar;
fn from_euler_angles(
euler: EulerRot,
x: Self::Scalar,
y: Self::Scalar,
z: Self::Scalar,
) -> Self {
use crate::$scalar::math;
let order = Order::from_euler(euler);
let (i, j, k) = order.angle_order();
let mut angles = if order.frame_static {
$vec3::new(x, y, z)
} else {
$vec3::new(z, y, x)
};
if order.parity_even {
angles.y = -angles.y;
}
let ti = angles.x * 0.5;
let tj = angles.y * 0.5;
let th = angles.z * 0.5;
let (si, ci) = math::sin_cos(ti);
let (sj, cj) = math::sin_cos(tj);
let (sh, ch) = math::sin_cos(th);
let cc = ci * ch;
let cs = ci * sh;
let sc = si * ch;
let ss = si * sh;
let parity = if !order.parity_even { 1.0 } else { -1.0 };
let mut a = [0.0; 4];
if order.initial_repeated {
a[i] = cj * (cs + sc);
a[j] = sj * (cc + ss) * parity;
a[k] = sj * (cs - sc);
a[3] = cj * (cc - ss);
} else {
a[i] = cj * sc - sj * cs;
a[j] = (cj * ss + sj * cc) * parity;
a[k] = cj * cs - sj * sc;
a[3] = cj * cc + sj * ss;
}
$quat::from_array(a)
}
}
};
}
macro_rules! impl_mat3_to_euler {
($scalar:ident, $mat3:ident, $vec3:ident) => {
impl ToEuler for $mat3 {
type Scalar = $scalar;
fn to_euler_angles(
self,
euler: EulerRot,
) -> (Self::Scalar, Self::Scalar, Self::Scalar) {
use crate::$scalar::math;
let order = Order::from_euler(euler);
let (i, j, k) = order.angle_order();
let mut ea = $vec3::ZERO;
if order.initial_repeated {
let sy = math::sqrt(
self.col(i)[j] * self.col(i)[j] + self.col(i)[k] * self.col(i)[k],
);
if (sy > 16.0 * $scalar::EPSILON) {
ea.x = math::atan2(self.col(i)[j], self.col(i)[k]);
ea.y = math::atan2(sy, self.col(i)[i]);
ea.z = math::atan2(self.col(j)[i], -self.col(k)[i]);
} else {
ea.x = math::atan2(-self.col(j)[k], self.col(j)[j]);
ea.y = math::atan2(sy, self.col(i)[i]);
}
} else {
let cy = math::sqrt(
self.col(i)[i] * self.col(i)[i] + self.col(j)[i] * self.col(j)[i],
);
if (cy > 16.0 * $scalar::EPSILON) {
ea.x = math::atan2(self.col(k)[j], self.col(k)[k]);
ea.y = math::atan2(-self.col(k)[i], cy);
ea.z = math::atan2(self.col(j)[i], self.col(i)[i]);
} else {
ea.x = math::atan2(-self.col(j)[k], self.col(j)[j]);
ea.y = math::atan2(-self.col(k)[i], cy);
}
}
// reverse rotation angle of original code
if order.parity_even {
ea = -ea;
}
if !order.frame_static {
ea = ea.zyx();
}
(ea.x, ea.y, ea.z)
}
}
};
}
macro_rules! impl_mat4_to_euler {
($scalar:ident, $mat4:ident, $mat3:ident) => {
impl ToEuler for $mat4 {
type Scalar = $scalar;
fn to_euler_angles(
self,
order: EulerRot,
) -> (Self::Scalar, Self::Scalar, Self::Scalar) {
$mat3::from_mat4(self).to_euler_angles(order)
}
}
};
}
macro_rules! impl_quat_to_euler {
($scalar:ident, $quat:ident, $mat3:ident) => {
impl ToEuler for $quat {
type Scalar = $scalar;
fn to_euler_angles(
self,
order: EulerRot,
) -> (Self::Scalar, Self::Scalar, Self::Scalar) {
$mat3::from_quat(self).to_euler_angles(order)
}
}
};
}
impl_mat3_to_euler!(f32, Mat3, Vec3);
impl_mat3_from_euler!(f32, Mat3, Vec3);
impl_mat3_to_euler!(f32, Mat3A, Vec3A);
impl_mat3_from_euler!(f32, Mat3A, Vec3A);
impl_mat4_from_euler!(f32, Mat4, Mat3);
impl_mat4_to_euler!(f32, Mat4, Mat3);
impl_quat_to_euler!(f32, Quat, Mat3);
impl_quat_from_euler!(f32, Quat, Vec3);
impl_mat3_to_euler!(f64, DMat3, DVec3);
impl_mat3_from_euler!(f64, DMat3, DVec3);
impl_mat4_to_euler!(f64, DMat4, DMat3);
impl_mat4_from_euler!(f64, DMat4, DMat3);
impl_quat_to_euler!(f64, DQuat, DMat3);
impl_quat_from_euler!(f64, DQuat, DVec3);

181
vendor/glam/src/f32.rs vendored Normal file
View File

@@ -0,0 +1,181 @@
mod affine2;
mod affine3a;
mod float;
mod mat3;
pub(crate) mod math;
mod vec2;
mod vec3;
#[cfg(all(feature = "core-simd", not(feature = "scalar-math")))]
mod coresimd;
#[cfg(any(
not(any(
feature = "core-simd",
target_arch = "aarch64",
target_feature = "sse2",
target_feature = "simd128"
)),
feature = "scalar-math"
))]
mod scalar;
#[cfg(all(
target_arch = "aarch64",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
mod neon;
#[cfg(all(
target_feature = "sse2",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
mod sse2;
#[cfg(all(
target_feature = "simd128",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
mod wasm32;
#[cfg(any(
not(any(
feature = "core-simd",
target_arch = "aarch64",
target_feature = "sse2",
target_feature = "simd128"
)),
feature = "scalar-math"
))]
use scalar::*;
#[cfg(all(
target_arch = "aarch64",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
use neon::*;
#[cfg(all(
target_feature = "sse2",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
use sse2::*;
#[cfg(all(
target_feature = "simd128",
not(any(feature = "core-simd", feature = "scalar-math"))
))]
use wasm32::*;
#[cfg(all(feature = "core-simd", not(feature = "scalar-math")))]
use coresimd::*;
pub use affine2::Affine2;
pub use affine3a::Affine3A;
pub use mat2::{mat2, Mat2};
pub use mat3::{mat3, Mat3};
pub use mat3a::{mat3a, Mat3A};
pub use mat4::{mat4, Mat4};
pub use quat::{quat, Quat};
pub use vec2::{vec2, Vec2};
pub use vec3::{vec3, Vec3};
pub use vec3a::{vec3a, Vec3A};
pub use vec4::{vec4, Vec4};
#[cfg(not(target_arch = "spirv"))]
mod test {
use super::*;
#[cfg(all(not(feature = "cuda"), feature = "scalar-math"))]
mod const_test_affine2 {
const_assert_eq!(
core::mem::align_of::<super::Vec2>(),
core::mem::align_of::<super::Affine2>()
);
const_assert_eq!(24, core::mem::size_of::<super::Affine2>());
}
#[cfg(not(feature = "scalar-math"))]
mod const_test_affine2 {
const_assert_eq!(16, core::mem::align_of::<super::Affine2>());
const_assert_eq!(32, core::mem::size_of::<super::Affine2>());
}
mod const_test_mat2 {
#[cfg(feature = "scalar-math")]
const_assert_eq!(
core::mem::align_of::<super::Vec2>(),
core::mem::align_of::<super::Mat2>()
);
#[cfg(not(any(feature = "scalar-math", target_arch = "spirv")))]
const_assert_eq!(16, core::mem::align_of::<super::Mat2>());
const_assert_eq!(16, core::mem::size_of::<super::Mat2>());
}
mod const_test_mat3 {
const_assert_eq!(
core::mem::align_of::<f32>(),
core::mem::align_of::<super::Mat3>()
);
const_assert_eq!(36, core::mem::size_of::<super::Mat3>());
}
mod const_test_mat3a {
const_assert_eq!(16, core::mem::align_of::<super::Mat3A>());
const_assert_eq!(48, core::mem::size_of::<super::Mat3A>());
}
mod const_test_mat4 {
const_assert_eq!(
core::mem::align_of::<super::Vec4>(),
core::mem::align_of::<super::Mat4>()
);
const_assert_eq!(64, core::mem::size_of::<super::Mat4>());
}
mod const_test_quat {
#[cfg(feature = "scalar-math")]
const_assert_eq!(
core::mem::align_of::<f32>(),
core::mem::align_of::<super::Quat>()
);
#[cfg(not(any(feature = "scalar-math", target_arch = "spirv")))]
const_assert_eq!(16, core::mem::align_of::<super::Quat>());
const_assert_eq!(16, core::mem::size_of::<super::Quat>());
}
mod const_test_vec2 {
#[cfg(not(feature = "cuda"))]
const_assert_eq!(
core::mem::align_of::<f32>(),
core::mem::align_of::<super::Vec2>()
);
#[cfg(feature = "cuda")]
const_assert_eq!(8, core::mem::align_of::<super::Vec2>());
const_assert_eq!(8, core::mem::size_of::<super::Vec2>());
}
mod const_test_vec3 {
const_assert_eq!(
core::mem::align_of::<f32>(),
core::mem::align_of::<super::Vec3>()
);
const_assert_eq!(12, core::mem::size_of::<super::Vec3>());
}
mod const_test_vec3a {
const_assert_eq!(16, core::mem::align_of::<super::Vec3A>());
const_assert_eq!(16, core::mem::size_of::<super::Vec3A>());
}
mod const_test_vec4 {
#[cfg(all(feature = "scalar-math", not(feature = "cuda")))]
const_assert_eq!(
core::mem::align_of::<f32>(),
core::mem::align_of::<super::Vec4>()
);
#[cfg(not(feature = "scalar-math"))]
const_assert_eq!(16, core::mem::align_of::<super::Vec4>());
const_assert_eq!(16, core::mem::size_of::<super::Vec4>());
}
}

458
vendor/glam/src/f32/affine2.rs vendored Normal file
View File

@@ -0,0 +1,458 @@
// Generated from affine.rs.tera template. Edit the template, not the generated file.
use crate::{Mat2, Mat3, Mat3A, Vec2, Vec3A};
use core::ops::{Deref, DerefMut, Mul, MulAssign};
/// A 2D affine transform, which can represent translation, rotation, scaling and shear.
#[derive(Copy, Clone)]
#[repr(C)]
pub struct Affine2 {
pub matrix2: Mat2,
pub translation: Vec2,
}
impl Affine2 {
/// The degenerate zero transform.
///
/// This transforms any finite vector and point to zero.
/// The zero transform is non-invertible.
pub const ZERO: Self = Self {
matrix2: Mat2::ZERO,
translation: Vec2::ZERO,
};
/// The identity transform.
///
/// Multiplying a vector with this returns the same vector.
pub const IDENTITY: Self = Self {
matrix2: Mat2::IDENTITY,
translation: Vec2::ZERO,
};
/// All NAN:s.
pub const NAN: Self = Self {
matrix2: Mat2::NAN,
translation: Vec2::NAN,
};
/// Creates an affine transform from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec2, y_axis: Vec2, z_axis: Vec2) -> Self {
Self {
matrix2: Mat2::from_cols(x_axis, y_axis),
translation: z_axis,
}
}
/// Creates an affine transform from a `[f32; 6]` array stored in column major order.
#[inline]
#[must_use]
pub fn from_cols_array(m: &[f32; 6]) -> Self {
Self {
matrix2: Mat2::from_cols_array(&[m[0], m[1], m[2], m[3]]),
translation: Vec2::from_array([m[4], m[5]]),
}
}
/// Creates a `[f32; 6]` array storing data in column major order.
#[inline]
#[must_use]
pub fn to_cols_array(&self) -> [f32; 6] {
let x = &self.matrix2.x_axis;
let y = &self.matrix2.y_axis;
let z = &self.translation;
[x.x, x.y, y.x, y.y, z.x, z.y]
}
/// Creates an affine transform from a `[[f32; 2]; 3]`
/// 2D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub fn from_cols_array_2d(m: &[[f32; 2]; 3]) -> Self {
Self {
matrix2: Mat2::from_cols(m[0].into(), m[1].into()),
translation: m[2].into(),
}
}
/// Creates a `[[f32; 2]; 3]` 2D array storing data in
/// column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub fn to_cols_array_2d(&self) -> [[f32; 2]; 3] {
[
self.matrix2.x_axis.into(),
self.matrix2.y_axis.into(),
self.translation.into(),
]
}
/// Creates an affine transform from the first 6 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 6 elements long.
#[inline]
#[must_use]
pub fn from_cols_slice(slice: &[f32]) -> Self {
Self {
matrix2: Mat2::from_cols_slice(&slice[0..4]),
translation: Vec2::from_slice(&slice[4..6]),
}
}
/// Writes the columns of `self` to the first 6 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 6 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
self.matrix2.write_cols_to_slice(&mut slice[0..4]);
self.translation.write_to_slice(&mut slice[4..6]);
}
/// Creates an affine transform that changes scale.
/// Note that if any scale is zero the transform will be non-invertible.
#[inline]
#[must_use]
pub fn from_scale(scale: Vec2) -> Self {
Self {
matrix2: Mat2::from_diagonal(scale),
translation: Vec2::ZERO,
}
}
/// Creates an affine transform from the given rotation `angle`.
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
Self {
matrix2: Mat2::from_angle(angle),
translation: Vec2::ZERO,
}
}
/// Creates an affine transformation from the given 2D `translation`.
#[inline]
#[must_use]
pub fn from_translation(translation: Vec2) -> Self {
Self {
matrix2: Mat2::IDENTITY,
translation,
}
}
/// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation)
#[inline]
#[must_use]
pub fn from_mat2(matrix2: Mat2) -> Self {
Self {
matrix2,
translation: Vec2::ZERO,
}
}
/// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation) and a
/// translation vector.
///
/// Equivalent to
/// `Affine2::from_translation(translation) * Affine2::from_mat2(mat2)`
#[inline]
#[must_use]
pub fn from_mat2_translation(matrix2: Mat2, translation: Vec2) -> Self {
Self {
matrix2,
translation,
}
}
/// Creates an affine transform from the given 2D `scale`, rotation `angle` (in radians) and
/// `translation`.
///
/// Equivalent to `Affine2::from_translation(translation) *
/// Affine2::from_angle(angle) * Affine2::from_scale(scale)`
#[inline]
#[must_use]
pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
let rotation = Mat2::from_angle(angle);
Self {
matrix2: Mat2::from_cols(rotation.x_axis * scale.x, rotation.y_axis * scale.y),
translation,
}
}
/// Creates an affine transform from the given 2D rotation `angle` (in radians) and
/// `translation`.
///
/// Equivalent to `Affine2::from_translation(translation) * Affine2::from_angle(angle)`
#[inline]
#[must_use]
pub fn from_angle_translation(angle: f32, translation: Vec2) -> Self {
Self {
matrix2: Mat2::from_angle(angle),
translation,
}
}
/// The given `Mat3` must be an affine transform,
#[inline]
#[must_use]
pub fn from_mat3(m: Mat3) -> Self {
use crate::swizzles::Vec3Swizzles;
Self {
matrix2: Mat2::from_cols(m.x_axis.xy(), m.y_axis.xy()),
translation: m.z_axis.xy(),
}
}
/// The given [`Mat3A`] must be an affine transform,
#[inline]
#[must_use]
pub fn from_mat3a(m: Mat3A) -> Self {
use crate::swizzles::Vec3Swizzles;
Self {
matrix2: Mat2::from_cols(m.x_axis.xy(), m.y_axis.xy()),
translation: m.z_axis.xy(),
}
}
/// Extracts `scale`, `angle` and `translation` from `self`.
///
/// The transform is expected to be non-degenerate and without shearing, or the output
/// will be invalid.
///
/// # Panics
///
/// Will panic if the determinant `self.matrix2` is zero or if the resulting scale
/// vector contains any zero elements when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_scale_angle_translation(self) -> (Vec2, f32, Vec2) {
use crate::f32::math;
let det = self.matrix2.determinant();
glam_assert!(det != 0.0);
let scale = Vec2::new(
self.matrix2.x_axis.length() * math::signum(det),
self.matrix2.y_axis.length(),
);
glam_assert!(scale.cmpne(Vec2::ZERO).all());
let angle = math::atan2(-self.matrix2.y_axis.x, self.matrix2.y_axis.y);
(scale, angle, self.translation)
}
/// Transforms the given 2D point, applying shear, scale, rotation and translation.
#[inline]
#[must_use]
pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
self.matrix2 * rhs + self.translation
}
/// Transforms the given 2D vector, applying shear, scale and rotation (but NOT
/// translation).
///
/// To also apply translation, use [`Self::transform_point2()`] instead.
#[inline]
pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
self.matrix2 * rhs
}
/// Returns `true` if, and only if, all elements are finite.
///
/// If any element is either `NaN`, positive or negative infinity, this will return
/// `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.matrix2.is_finite() && self.translation.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.matrix2.is_nan() || self.translation.is_nan()
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two 3x4 matrices contain similar elements. It works
/// best when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.matrix2.abs_diff_eq(rhs.matrix2, max_abs_diff)
&& self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
}
/// Return the inverse of this transform.
///
/// Note that if the transform is not invertible the result will be invalid.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let matrix2 = self.matrix2.inverse();
// transform negative translation by the matrix inverse:
let translation = -(matrix2 * self.translation);
Self {
matrix2,
translation,
}
}
}
impl Default for Affine2 {
#[inline(always)]
fn default() -> Self {
Self::IDENTITY
}
}
impl Deref for Affine2 {
type Target = crate::deref::Cols3<Vec2>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Self as *const Self::Target) }
}
}
impl DerefMut for Affine2 {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self as *mut Self as *mut Self::Target) }
}
}
impl PartialEq for Affine2 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.matrix2.eq(&rhs.matrix2) && self.translation.eq(&rhs.translation)
}
}
impl core::fmt::Debug for Affine2 {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fmt.debug_struct(stringify!(Affine2))
.field("matrix2", &self.matrix2)
.field("translation", &self.translation)
.finish()
}
}
impl core::fmt::Display for Affine2 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}]",
p, self.matrix2.x_axis, p, self.matrix2.y_axis, p, self.translation
)
} else {
write!(
f,
"[{}, {}, {}]",
self.matrix2.x_axis, self.matrix2.y_axis, self.translation
)
}
}
}
impl<'a> core::iter::Product<&'a Self> for Affine2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| a * b)
}
}
impl Mul for Affine2 {
type Output = Affine2;
#[inline]
fn mul(self, rhs: Affine2) -> Self::Output {
Self {
matrix2: self.matrix2 * rhs.matrix2,
translation: self.matrix2 * rhs.translation + self.translation,
}
}
}
impl MulAssign for Affine2 {
#[inline]
fn mul_assign(&mut self, rhs: Affine2) {
*self = self.mul(rhs);
}
}
impl From<Affine2> for Mat3 {
#[inline]
fn from(m: Affine2) -> Mat3 {
Self::from_cols(
m.matrix2.x_axis.extend(0.0),
m.matrix2.y_axis.extend(0.0),
m.translation.extend(1.0),
)
}
}
impl Mul<Mat3> for Affine2 {
type Output = Mat3;
#[inline]
fn mul(self, rhs: Mat3) -> Self::Output {
Mat3::from(self) * rhs
}
}
impl Mul<Affine2> for Mat3 {
type Output = Mat3;
#[inline]
fn mul(self, rhs: Affine2) -> Self::Output {
self * Mat3::from(rhs)
}
}
impl From<Affine2> for Mat3A {
#[inline]
fn from(m: Affine2) -> Mat3A {
Self::from_cols(
Vec3A::from((m.matrix2.x_axis, 0.0)),
Vec3A::from((m.matrix2.y_axis, 0.0)),
Vec3A::from((m.translation, 1.0)),
)
}
}
impl Mul<Mat3A> for Affine2 {
type Output = Mat3A;
#[inline]
fn mul(self, rhs: Mat3A) -> Self::Output {
Mat3A::from(self) * rhs
}
}
impl Mul<Affine2> for Mat3A {
type Output = Mat3A;
#[inline]
fn mul(self, rhs: Affine2) -> Self::Output {
self * Mat3A::from(rhs)
}
}

581
vendor/glam/src/f32/affine3a.rs vendored Normal file
View File

@@ -0,0 +1,581 @@
// Generated from affine.rs.tera template. Edit the template, not the generated file.
use crate::{Mat3, Mat3A, Mat4, Quat, Vec3, Vec3A};
use core::ops::{Deref, DerefMut, Mul, MulAssign};
/// A 3D affine transform, which can represent translation, rotation, scaling and shear.
///
/// This type is 16 byte aligned.
#[derive(Copy, Clone)]
#[repr(C)]
pub struct Affine3A {
pub matrix3: Mat3A,
pub translation: Vec3A,
}
impl Affine3A {
/// The degenerate zero transform.
///
/// This transforms any finite vector and point to zero.
/// The zero transform is non-invertible.
pub const ZERO: Self = Self {
matrix3: Mat3A::ZERO,
translation: Vec3A::ZERO,
};
/// The identity transform.
///
/// Multiplying a vector with this returns the same vector.
pub const IDENTITY: Self = Self {
matrix3: Mat3A::IDENTITY,
translation: Vec3A::ZERO,
};
/// All NAN:s.
pub const NAN: Self = Self {
matrix3: Mat3A::NAN,
translation: Vec3A::NAN,
};
/// Creates an affine transform from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A, w_axis: Vec3A) -> Self {
Self {
matrix3: Mat3A::from_cols(x_axis, y_axis, z_axis),
translation: w_axis,
}
}
/// Creates an affine transform from a `[f32; 12]` array stored in column major order.
#[inline]
#[must_use]
pub fn from_cols_array(m: &[f32; 12]) -> Self {
Self {
matrix3: Mat3A::from_cols_array(&[
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
]),
translation: Vec3A::from_array([m[9], m[10], m[11]]),
}
}
/// Creates a `[f32; 12]` array storing data in column major order.
#[inline]
#[must_use]
pub fn to_cols_array(&self) -> [f32; 12] {
let x = &self.matrix3.x_axis;
let y = &self.matrix3.y_axis;
let z = &self.matrix3.z_axis;
let w = &self.translation;
[x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
}
/// Creates an affine transform from a `[[f32; 3]; 4]`
/// 3D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub fn from_cols_array_2d(m: &[[f32; 3]; 4]) -> Self {
Self {
matrix3: Mat3A::from_cols(m[0].into(), m[1].into(), m[2].into()),
translation: m[3].into(),
}
}
/// Creates a `[[f32; 3]; 4]` 3D array storing data in
/// column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub fn to_cols_array_2d(&self) -> [[f32; 3]; 4] {
[
self.matrix3.x_axis.into(),
self.matrix3.y_axis.into(),
self.matrix3.z_axis.into(),
self.translation.into(),
]
}
/// Creates an affine transform from the first 12 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 12 elements long.
#[inline]
#[must_use]
pub fn from_cols_slice(slice: &[f32]) -> Self {
Self {
matrix3: Mat3A::from_cols_slice(&slice[0..9]),
translation: Vec3A::from_slice(&slice[9..12]),
}
}
/// Writes the columns of `self` to the first 12 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 12 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
self.matrix3.write_cols_to_slice(&mut slice[0..9]);
self.translation.write_to_slice(&mut slice[9..12]);
}
/// Creates an affine transform that changes scale.
/// Note that if any scale is zero the transform will be non-invertible.
#[inline]
#[must_use]
pub fn from_scale(scale: Vec3) -> Self {
Self {
matrix3: Mat3A::from_diagonal(scale),
translation: Vec3A::ZERO,
}
}
/// Creates an affine transform from the given `rotation` quaternion.
#[inline]
#[must_use]
pub fn from_quat(rotation: Quat) -> Self {
Self {
matrix3: Mat3A::from_quat(rotation),
translation: Vec3A::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around a normalized
/// rotation `axis` of `angle` (in radians).
#[inline]
#[must_use]
pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
Self {
matrix3: Mat3A::from_axis_angle(axis, angle),
translation: Vec3A::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around the x axis of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f32) -> Self {
Self {
matrix3: Mat3A::from_rotation_x(angle),
translation: Vec3A::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around the y axis of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f32) -> Self {
Self {
matrix3: Mat3A::from_rotation_y(angle),
translation: Vec3A::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around the z axis of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f32) -> Self {
Self {
matrix3: Mat3A::from_rotation_z(angle),
translation: Vec3A::ZERO,
}
}
/// Creates an affine transformation from the given 3D `translation`.
#[inline]
#[must_use]
pub fn from_translation(translation: Vec3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: Mat3A::IDENTITY,
translation: translation.into(),
}
}
/// Creates an affine transform from a 3x3 matrix (expressing scale, shear and
/// rotation)
#[inline]
#[must_use]
pub fn from_mat3(mat3: Mat3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: mat3.into(),
translation: Vec3A::ZERO,
}
}
/// Creates an affine transform from a 3x3 matrix (expressing scale, shear and rotation)
/// and a translation vector.
///
/// Equivalent to `Affine3A::from_translation(translation) * Affine3A::from_mat3(mat3)`
#[inline]
#[must_use]
pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: mat3.into(),
translation: translation.into(),
}
}
/// Creates an affine transform from the given 3D `scale`, `rotation` and
/// `translation`.
///
/// Equivalent to `Affine3A::from_translation(translation) *
/// Affine3A::from_quat(rotation) * Affine3A::from_scale(scale)`
#[inline]
#[must_use]
pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
let rotation = Mat3A::from_quat(rotation);
#[allow(clippy::useless_conversion)]
Self {
matrix3: Mat3A::from_cols(
rotation.x_axis * scale.x,
rotation.y_axis * scale.y,
rotation.z_axis * scale.z,
),
translation: translation.into(),
}
}
/// Creates an affine transform from the given 3D `rotation` and `translation`.
///
/// Equivalent to `Affine3A::from_translation(translation) * Affine3A::from_quat(rotation)`
#[inline]
#[must_use]
pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: Mat3A::from_quat(rotation),
translation: translation.into(),
}
}
/// The given `Mat4` must be an affine transform,
/// i.e. contain no perspective transform.
#[inline]
#[must_use]
pub fn from_mat4(m: Mat4) -> Self {
Self {
matrix3: Mat3A::from_cols(
Vec3A::from_vec4(m.x_axis),
Vec3A::from_vec4(m.y_axis),
Vec3A::from_vec4(m.z_axis),
),
translation: Vec3A::from_vec4(m.w_axis),
}
}
/// Extracts `scale`, `rotation` and `translation` from `self`.
///
/// The transform is expected to be non-degenerate and without shearing, or the output
/// will be invalid.
///
/// # Panics
///
/// Will panic if the determinant `self.matrix3` is zero or if the resulting scale
/// vector contains any zero elements when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
use crate::f32::math;
let det = self.matrix3.determinant();
glam_assert!(det != 0.0);
let scale = Vec3::new(
self.matrix3.x_axis.length() * math::signum(det),
self.matrix3.y_axis.length(),
self.matrix3.z_axis.length(),
);
glam_assert!(scale.cmpne(Vec3::ZERO).all());
let inv_scale = scale.recip();
#[allow(clippy::useless_conversion)]
let rotation = Quat::from_mat3(&Mat3::from_cols(
(self.matrix3.x_axis * inv_scale.x).into(),
(self.matrix3.y_axis * inv_scale.y).into(),
(self.matrix3.z_axis * inv_scale.z).into(),
));
#[allow(clippy::useless_conversion)]
(scale, rotation, self.translation.into())
}
/// Creates a left-handed view transform using a camera position, an up direction, and a facing
/// direction.
///
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
#[inline]
#[must_use]
pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
Self::look_to_rh(eye, -dir, up)
}
/// Creates a right-handed view transform using a camera position, an up direction, and a facing
/// direction.
///
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
#[inline]
#[must_use]
pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
let f = dir.normalize();
let s = f.cross(up).normalize();
let u = s.cross(f);
Self {
matrix3: Mat3A::from_cols(
Vec3A::new(s.x, u.x, -f.x),
Vec3A::new(s.y, u.y, -f.y),
Vec3A::new(s.z, u.z, -f.z),
),
translation: Vec3A::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
}
}
/// Creates a left-handed view transform using a camera position, an up direction, and a focal
/// point.
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
///
/// # Panics
///
/// Will panic if `up` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
glam_assert!(up.is_normalized());
Self::look_to_lh(eye, center - eye, up)
}
/// Creates a right-handed view transform using a camera position, an up direction, and a focal
/// point.
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
///
/// # Panics
///
/// Will panic if `up` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
glam_assert!(up.is_normalized());
Self::look_to_rh(eye, center - eye, up)
}
/// Transforms the given 3D points, applying shear, scale, rotation and translation.
#[inline]
pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
#[allow(clippy::useless_conversion)]
((self.matrix3.x_axis * rhs.x)
+ (self.matrix3.y_axis * rhs.y)
+ (self.matrix3.z_axis * rhs.z)
+ self.translation)
.into()
}
/// Transforms the given 3D vector, applying shear, scale and rotation (but NOT
/// translation).
///
/// To also apply translation, use [`Self::transform_point3()`] instead.
#[inline]
#[must_use]
pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
#[allow(clippy::useless_conversion)]
((self.matrix3.x_axis * rhs.x)
+ (self.matrix3.y_axis * rhs.y)
+ (self.matrix3.z_axis * rhs.z))
.into()
}
/// Transforms the given [`Vec3A`], applying shear, scale, rotation and translation.
#[inline]
#[must_use]
pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
self.matrix3 * rhs + self.translation
}
/// Transforms the given [`Vec3A`], applying shear, scale and rotation (but NOT
/// translation).
///
/// To also apply translation, use [`Self::transform_point3a()`] instead.
#[inline]
#[must_use]
pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
self.matrix3 * rhs
}
/// Returns `true` if, and only if, all elements are finite.
///
/// If any element is either `NaN`, positive or negative infinity, this will return
/// `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.matrix3.is_finite() && self.translation.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.matrix3.is_nan() || self.translation.is_nan()
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two 3x4 matrices contain similar elements. It works
/// best when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
&& self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
}
/// Return the inverse of this transform.
///
/// Note that if the transform is not invertible the result will be invalid.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let matrix3 = self.matrix3.inverse();
// transform negative translation by the matrix inverse:
let translation = -(matrix3 * self.translation);
Self {
matrix3,
translation,
}
}
}
impl Default for Affine3A {
#[inline(always)]
fn default() -> Self {
Self::IDENTITY
}
}
impl Deref for Affine3A {
type Target = crate::deref::Cols4<Vec3A>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Self as *const Self::Target) }
}
}
impl DerefMut for Affine3A {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self as *mut Self as *mut Self::Target) }
}
}
impl PartialEq for Affine3A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
}
}
impl core::fmt::Debug for Affine3A {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fmt.debug_struct(stringify!(Affine3A))
.field("matrix3", &self.matrix3)
.field("translation", &self.translation)
.finish()
}
}
impl core::fmt::Display for Affine3A {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}, {:.*}]",
p,
self.matrix3.x_axis,
p,
self.matrix3.y_axis,
p,
self.matrix3.z_axis,
p,
self.translation
)
} else {
write!(
f,
"[{}, {}, {}, {}]",
self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
)
}
}
}
impl<'a> core::iter::Product<&'a Self> for Affine3A {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| a * b)
}
}
impl Mul for Affine3A {
type Output = Affine3A;
#[inline]
fn mul(self, rhs: Affine3A) -> Self::Output {
Self {
matrix3: self.matrix3 * rhs.matrix3,
translation: self.matrix3 * rhs.translation + self.translation,
}
}
}
impl MulAssign for Affine3A {
#[inline]
fn mul_assign(&mut self, rhs: Affine3A) {
*self = self.mul(rhs);
}
}
impl From<Affine3A> for Mat4 {
#[inline]
fn from(m: Affine3A) -> Mat4 {
Mat4::from_cols(
m.matrix3.x_axis.extend(0.0),
m.matrix3.y_axis.extend(0.0),
m.matrix3.z_axis.extend(0.0),
m.translation.extend(1.0),
)
}
}
impl Mul<Mat4> for Affine3A {
type Output = Mat4;
#[inline]
fn mul(self, rhs: Mat4) -> Self::Output {
Mat4::from(self) * rhs
}
}
impl Mul<Affine3A> for Mat4 {
type Output = Mat4;
#[inline]
fn mul(self, rhs: Affine3A) -> Self::Output {
self * Mat4::from(rhs)
}
}

6
vendor/glam/src/f32/coresimd.rs vendored Normal file
View File

@@ -0,0 +1,6 @@
pub mod mat2;
pub mod mat3a;
pub mod mat4;
pub mod quat;
pub mod vec3a;
pub mod vec4;

582
vendor/glam/src/f32/coresimd/mat2.rs vendored Normal file
View File

@@ -0,0 +1,582 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use core::simd::*;
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
Mat2::from_cols(x_axis, y_axis)
}
/// A 2x2 column major matrix.
///
/// SIMD vector types are used for storage on supported platforms.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Mat2(pub(crate) f32x4);
impl Mat2 {
/// A 2x2 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
/// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
Self(f32x4::from_array([m00, m01, m10, m11]))
}
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
Self(f32x4::from_array([x_axis.x, x_axis.y, y_axis.x, y_axis.y]))
}
/// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f32; 4]) -> Self {
Self(f32x4::from_array(*m))
}
/// Creates a `[f32; 4]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f32; 4] {
unsafe { *(self as *const Self as *const [f32; 4]) }
}
/// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
}
/// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
}
/// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: Vec2) -> Self {
Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
}
/// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
}
/// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos, sin, -sin, cos)
}
/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3(m: Mat3) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3a(m: Mat3A) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 2x2 matrix from the first 4 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f32]) -> Self {
Self::new(slice[0], slice[1], slice[2], slice[3])
}
/// Writes the columns of `self` to the first 4 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.y_axis.x;
slice[3] = self.y_axis.y;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> Vec2 {
match index {
0 => self.x_axis,
1 => self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> Vec2 {
match index {
0 => Vec2::new(self.x_axis.x, self.y_axis.x),
1 => Vec2::new(self.x_axis.y, self.y_axis.y),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
Self(simd_swizzle!(self.0, [0, 2, 1, 3]))
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f32 {
let abcd = self.0;
let dcba = simd_swizzle!(abcd, [3, 2, 1, 0]);
let prod = abcd * dcba;
let det = prod - simd_swizzle!(prod, [1, 1, 1, 1]);
det[0]
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
const SIGN: f32x4 = f32x4::from_array([1.0, -1.0, -1.0, 1.0]);
let abcd = self.0;
let dcba = simd_swizzle!(abcd, [3, 2, 1, 0]);
let prod = abcd * dcba;
let sub = prod - simd_swizzle!(prod, [1, 1, 1, 1]);
let det = simd_swizzle!(sub, [0, 0, 0, 0]);
let tmp = SIGN / det;
glam_assert!(Mat2(tmp).is_finite());
let dbca = simd_swizzle!(abcd, [3, 1, 2, 0]);
Self(dbca.mul(tmp))
}
/// Transforms a 2D vector.
#[inline]
#[must_use]
pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
let abcd = self.0;
let xxyy = f32x4::from_array([rhs.x, rhs.x, rhs.y, rhs.y]);
let axbxcydy = abcd.mul(xxyy);
let cydyaxbx = simd_swizzle!(axbxcydy, [2, 3, 0, 1]);
let result = axbxcydy.add(cydyaxbx);
unsafe { *(&result as *const f32x4 as *const Vec2) }
}
/// Multiplies two 2x2 matrices.
#[inline]
#[must_use]
pub fn mul_mat2(&self, rhs: &Self) -> Self {
let abcd = self.0;
let xxyy0 = simd_swizzle!(rhs.0, [0, 0, 1, 1]);
let xxyy1 = simd_swizzle!(rhs.0, [2, 2, 3, 3]);
let axbxcydy0 = abcd * xxyy0;
let axbxcydy1 = abcd * xxyy1;
let cydyaxbx0 = simd_swizzle!(axbxcydy0, [2, 3, 0, 1]);
let cydyaxbx1 = simd_swizzle!(axbxcydy1, [2, 3, 0, 1]);
let result0 = axbxcydy0 + cydyaxbx0;
let result1 = axbxcydy1 + cydyaxbx1;
Self(simd_swizzle!(result0, result1, [0, 1, 4, 5]))
}
/// Adds two 2x2 matrices.
#[inline]
#[must_use]
pub fn add_mat2(&self, rhs: &Self) -> Self {
Self(self.0 + rhs.0)
}
/// Subtracts two 2x2 matrices.
#[inline]
#[must_use]
pub fn sub_mat2(&self, rhs: &Self) -> Self {
Self(self.0 - rhs.0)
}
/// Multiplies a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f32) -> Self {
Self(self.0 * f32x4::splat(rhs))
}
/// Divides a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f32) -> Self {
Self(self.0 / f32x4::splat(rhs))
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
}
#[inline]
pub fn as_dmat2(&self) -> DMat2 {
DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
}
}
impl Default for Mat2 {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat2(&rhs)
}
}
impl AddAssign<Mat2> for Mat2 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat2(&rhs);
}
}
impl Sub<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat2(&rhs)
}
}
impl SubAssign<Mat2> for Mat2 {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat2(&rhs);
}
}
impl Neg for Mat2 {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self(-self.0)
}
}
impl Mul<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat2(&rhs)
}
}
impl MulAssign<Mat2> for Mat2 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat2(&rhs);
}
}
impl Mul<Vec2> for Mat2 {
type Output = Vec2;
#[inline]
fn mul(self, rhs: Vec2) -> Self::Output {
self.mul_vec2(rhs)
}
}
impl Mul<Mat2> for f32 {
type Output = Mat2;
#[inline]
fn mul(self, rhs: Mat2) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f32> for Mat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f32> for Mat2 {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = self.mul_scalar(rhs);
}
}
impl Div<Mat2> for f32 {
type Output = Mat2;
#[inline]
fn div(self, rhs: Mat2) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f32> for Mat2 {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f32> for Mat2 {
#[inline]
fn div_assign(&mut self, rhs: f32) {
*self = self.div_scalar(rhs);
}
}
impl Sum<Self> for Mat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Mat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Mat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Mat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for Mat2 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsRef<[f32; 4]> for Mat2 {
#[inline]
fn as_ref(&self) -> &[f32; 4] {
unsafe { &*(self as *const Self as *const [f32; 4]) }
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsMut<[f32; 4]> for Mat2 {
#[inline]
fn as_mut(&mut self) -> &mut [f32; 4] {
unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
}
}
impl core::ops::Deref for Mat2 {
type Target = crate::deref::Cols2<Vec2>;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Self as *const Self::Target) }
}
}
impl core::ops::DerefMut for Mat2 {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self as *mut Self as *mut Self::Target) }
}
}
impl fmt::Debug for Mat2 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(Mat2))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.finish()
}
}
impl fmt::Display for Mat2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
} else {
write!(f, "[{}, {}]", self.x_axis, self.y_axis)
}
}
}

926
vendor/glam/src/f32/coresimd/mat3a.rs vendored Normal file
View File

@@ -0,0 +1,926 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{
euler::{FromEuler, ToEuler},
f32::math,
swizzles::*,
DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A,
};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use core::simd::*;
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
Mat3A::from_cols(x_axis, y_axis, z_axis)
}
/// A 3x3 column major matrix.
///
/// This 3x3 matrix type features convenience methods for creating and using linear and
/// affine transformations. If you are primarily dealing with 2D affine transformations the
/// [`Affine2`](crate::Affine2) type is much faster and more space efficient than
/// using a 3x3 matrix.
///
/// Linear transformations including 3D rotation and scale can be created using methods
/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
/// [`Self::from_rotation_z()`].
///
/// The resulting matrices can be use to transform 3D vectors using regular vector
/// multiplication.
///
/// Affine transformations including 2D translation, rotation and scale can be created
/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
///
/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
/// are provided for performing affine transforms on 2D vectors and points. These multiply
/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
/// vectors respectively. These methods assume that `Self` contains a valid affine
/// transform.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Mat3A {
pub x_axis: Vec3A,
pub y_axis: Vec3A,
pub z_axis: Vec3A,
}
impl Mat3A {
/// A 3x3 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO);
/// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(
m00: f32,
m01: f32,
m02: f32,
m10: f32,
m11: f32,
m12: f32,
m20: f32,
m21: f32,
m22: f32,
) -> Self {
Self {
x_axis: Vec3A::new(m00, m01, m02),
y_axis: Vec3A::new(m10, m11, m12),
z_axis: Vec3A::new(m20, m21, m22),
}
}
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
Self {
x_axis,
y_axis,
z_axis,
}
}
/// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f32; 9]) -> Self {
Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
}
/// Creates a `[f32; 9]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f32; 9] {
let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array();
[
x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y,
z_axis_z,
]
}
/// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
Self::from_cols(
Vec3A::from_array(m[0]),
Vec3A::from_array(m[1]),
Vec3A::from_array(m[2]),
)
}
/// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
[
self.x_axis.to_array(),
self.y_axis.to_array(),
self.z_axis.to_array(),
]
}
/// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: Vec3) -> Self {
Self::new(
diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
)
}
/// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
#[inline]
#[must_use]
pub fn from_mat4(m: Mat4) -> Self {
Self::from_cols(
Vec3A::from_vec4(m.x_axis),
Vec3A::from_vec4(m.y_axis),
Vec3A::from_vec4(m.z_axis),
)
}
/// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 3.
#[inline]
#[must_use]
pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(0, 1) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(0, 2) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(0, 3) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(1, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(1, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(1, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(1, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(2, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(2, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(2, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(2, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(3, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
),
(3, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
),
(3, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
),
(3, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
),
_ => panic!("index out of bounds"),
}
}
/// Creates a 3D rotation matrix from the given quaternion.
///
/// # Panics
///
/// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_quat(rotation: Quat) -> Self {
glam_assert!(rotation.is_normalized());
let x2 = rotation.x + rotation.x;
let y2 = rotation.y + rotation.y;
let z2 = rotation.z + rotation.z;
let xx = rotation.x * x2;
let xy = rotation.x * y2;
let xz = rotation.x * z2;
let yy = rotation.y * y2;
let yz = rotation.y * z2;
let zz = rotation.z * z2;
let wx = rotation.w * x2;
let wy = rotation.w * y2;
let wz = rotation.w * z2;
Self::from_cols(
Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy),
Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx),
Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
)
}
/// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
/// radians).
///
/// # Panics
///
/// Will panic if `axis` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
glam_assert!(axis.is_normalized());
let (sin, cos) = math::sin_cos(angle);
let (xsin, ysin, zsin) = axis.mul(sin).into();
let (x, y, z) = axis.into();
let (x2, y2, z2) = axis.mul(axis).into();
let omc = 1.0 - cos;
let xyomc = x * y * omc;
let xzomc = x * z * omc;
let yzomc = y * z * omc;
Self::from_cols(
Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
)
}
/// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
/// radians).
#[inline]
#[must_use]
pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
Self::from_euler_angles(order, a, b, c)
}
/// Extract Euler angles with the given Euler rotation order.
///
/// Note if the input matrix contains scales, shears, or other non-rotation transformations then
/// the resulting Euler angles will be ill-defined.
///
/// # Panics
///
/// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
glam_assert!(
self.x_axis.is_normalized()
&& self.y_axis.is_normalized()
&& self.z_axis.is_normalized()
);
self.to_euler_angles(order)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::X,
Vec3A::new(0.0, cosa, sina),
Vec3A::new(0.0, -sina, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cosa, 0.0, -sina),
Vec3A::Y,
Vec3A::new(sina, 0.0, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cosa, sina, 0.0),
Vec3A::new(-sina, cosa, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_translation(translation: Vec2) -> Self {
Self::from_cols(
Vec3A::X,
Vec3A::Y,
Vec3A::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given 2D rotation `angle` (in
/// radians).
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cos, sin, 0.0),
Vec3A::new(-sin, cos, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
/// radians) and `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
Vec3A::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
///
/// # Panics
///
/// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_scale(scale: Vec2) -> Self {
// Do not panic as long as any component is non-zero
glam_assert!(scale.cmpne(Vec2::ZERO).any());
Self::from_cols(
Vec3A::new(scale.x, 0.0, 0.0),
Vec3A::new(0.0, scale.y, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2x2 matrix.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
pub fn from_mat2(m: Mat2) -> Self {
Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z)
}
/// Creates a 3x3 matrix from the first 9 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f32]) -> Self {
Self::new(
slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
slice[8],
)
}
/// Writes the columns of `self` to the first 9 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.x_axis.z;
slice[3] = self.y_axis.x;
slice[4] = self.y_axis.y;
slice[5] = self.y_axis.z;
slice[6] = self.z_axis.x;
slice[7] = self.z_axis.y;
slice[8] = self.z_axis.z;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> Vec3A {
match index {
0 => self.x_axis,
1 => self.y_axis,
2 => self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut Vec3A {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
2 => &mut self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> Vec3A {
match index {
0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
let tmp0 = simd_swizzle!(self.x_axis.0, self.y_axis.0, [0, 1, 4, 5]);
let tmp1 = simd_swizzle!(self.x_axis.0, self.y_axis.0, [2, 3, 6, 7]);
Self {
x_axis: Vec3A(simd_swizzle!(tmp0, self.z_axis.0, [0, 2, 4, 4])),
y_axis: Vec3A(simd_swizzle!(tmp0, self.z_axis.0, [1, 3, 5, 5])),
z_axis: Vec3A(simd_swizzle!(tmp1, self.z_axis.0, [0, 2, 6, 6])),
}
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f32 {
self.z_axis.dot(self.x_axis.cross(self.y_axis))
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let tmp0 = self.y_axis.cross(self.z_axis);
let tmp1 = self.z_axis.cross(self.x_axis);
let tmp2 = self.x_axis.cross(self.y_axis);
let det = self.z_axis.dot(tmp2);
glam_assert!(det != 0.0);
let inv_det = Vec3A::splat(det.recip());
Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
}
/// Transforms the given 2D vector as a point.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
}
/// Rotates the given 2D vector.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
}
/// Transforms a 3D vector.
#[inline]
#[must_use]
pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
self.mul_vec3a(rhs.into()).into()
}
/// Transforms a [`Vec3A`].
#[inline]
#[must_use]
pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
let mut res = self.x_axis.mul(rhs.xxx());
res = res.add(self.y_axis.mul(rhs.yyy()));
res = res.add(self.z_axis.mul(rhs.zzz()));
res
}
/// Multiplies two 3x3 matrices.
#[inline]
#[must_use]
pub fn mul_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.mul(rhs.x_axis),
self.mul(rhs.y_axis),
self.mul(rhs.z_axis),
)
}
/// Adds two 3x3 matrices.
#[inline]
#[must_use]
pub fn add_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.add(rhs.x_axis),
self.y_axis.add(rhs.y_axis),
self.z_axis.add(rhs.z_axis),
)
}
/// Subtracts two 3x3 matrices.
#[inline]
#[must_use]
pub fn sub_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.sub(rhs.x_axis),
self.y_axis.sub(rhs.y_axis),
self.z_axis.sub(rhs.z_axis),
)
}
/// Multiplies a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f32) -> Self {
Self::from_cols(
self.x_axis.mul(rhs),
self.y_axis.mul(rhs),
self.z_axis.mul(rhs),
)
}
/// Divides a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f32) -> Self {
let rhs = Vec3A::splat(rhs);
Self::from_cols(
self.x_axis.div(rhs),
self.y_axis.div(rhs),
self.z_axis.div(rhs),
)
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
&& self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
}
#[inline]
pub fn as_dmat3(&self) -> DMat3 {
DMat3::from_cols(
self.x_axis.as_dvec3(),
self.y_axis.as_dvec3(),
self.z_axis.as_dvec3(),
)
}
}
impl Default for Mat3A {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat3(&rhs)
}
}
impl AddAssign<Mat3A> for Mat3A {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat3(&rhs);
}
}
impl Sub<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat3(&rhs)
}
}
impl SubAssign<Mat3A> for Mat3A {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat3(&rhs);
}
}
impl Neg for Mat3A {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
}
}
impl Mul<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat3(&rhs)
}
}
impl MulAssign<Mat3A> for Mat3A {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat3(&rhs);
}
}
impl Mul<Vec3A> for Mat3A {
type Output = Vec3A;
#[inline]
fn mul(self, rhs: Vec3A) -> Self::Output {
self.mul_vec3a(rhs)
}
}
impl Mul<Mat3A> for f32 {
type Output = Mat3A;
#[inline]
fn mul(self, rhs: Mat3A) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f32> for Mat3A {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f32> for Mat3A {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = self.mul_scalar(rhs);
}
}
impl Div<Mat3A> for f32 {
type Output = Mat3A;
#[inline]
fn div(self, rhs: Mat3A) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f32> for Mat3A {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f32> for Mat3A {
#[inline]
fn div_assign(&mut self, rhs: f32) {
*self = self.div_scalar(rhs);
}
}
impl Mul<Vec3> for Mat3A {
type Output = Vec3;
#[inline]
fn mul(self, rhs: Vec3) -> Vec3 {
self.mul_vec3a(rhs.into()).into()
}
}
impl From<Mat3> for Mat3A {
#[inline]
fn from(m: Mat3) -> Self {
Self {
x_axis: m.x_axis.into(),
y_axis: m.y_axis.into(),
z_axis: m.z_axis.into(),
}
}
}
impl Sum<Self> for Mat3A {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Mat3A {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Mat3A {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Mat3A {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for Mat3A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
}
}
impl fmt::Debug for Mat3A {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(Mat3A))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.field("z_axis", &self.z_axis)
.finish()
}
}
impl fmt::Display for Mat3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}]",
p, self.x_axis, p, self.y_axis, p, self.z_axis
)
} else {
write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
}
}
}

1536
vendor/glam/src/f32/coresimd/mat4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1013
vendor/glam/src/f32/coresimd/quat.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1842
vendor/glam/src/f32/coresimd/vec3a.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1794
vendor/glam/src/f32/coresimd/vec4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

21
vendor/glam/src/f32/float.rs vendored Normal file
View File

@@ -0,0 +1,21 @@
// Generated from float.rs.tera template. Edit the template, not the generated file.
use crate::float::FloatExt;
impl FloatExt for f32 {
#[inline]
fn lerp(self, rhs: f32, t: f32) -> f32 {
self + (rhs - self) * t
}
#[inline]
fn inverse_lerp(a: f32, b: f32, v: f32) -> f32 {
(v - a) / (b - a)
}
#[inline]
fn remap(self, in_start: f32, in_end: f32, out_start: f32, out_end: f32) -> f32 {
let t = f32::inverse_lerp(in_start, in_end, self);
f32::lerp(out_start, out_end, t)
}
}

872
vendor/glam/src/f32/mat3.rs vendored Normal file
View File

@@ -0,0 +1,872 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{
euler::{FromEuler, ToEuler},
f32::math,
swizzles::*,
DMat3, EulerRot, Mat2, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A,
};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn mat3(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Mat3 {
Mat3::from_cols(x_axis, y_axis, z_axis)
}
/// A 3x3 column major matrix.
///
/// This 3x3 matrix type features convenience methods for creating and using linear and
/// affine transformations. If you are primarily dealing with 2D affine transformations the
/// [`Affine2`](crate::Affine2) type is much faster and more space efficient than
/// using a 3x3 matrix.
///
/// Linear transformations including 3D rotation and scale can be created using methods
/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
/// [`Self::from_rotation_z()`].
///
/// The resulting matrices can be use to transform 3D vectors using regular vector
/// multiplication.
///
/// Affine transformations including 2D translation, rotation and scale can be created
/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
///
/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
/// are provided for performing affine transforms on 2D vectors and points. These multiply
/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
/// vectors respectively. These methods assume that `Self` contains a valid affine
/// transform.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Mat3 {
pub x_axis: Vec3,
pub y_axis: Vec3,
pub z_axis: Vec3,
}
impl Mat3 {
/// A 3x3 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(Vec3::ZERO, Vec3::ZERO, Vec3::ZERO);
/// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(Vec3::X, Vec3::Y, Vec3::Z);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(Vec3::NAN, Vec3::NAN, Vec3::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(
m00: f32,
m01: f32,
m02: f32,
m10: f32,
m11: f32,
m12: f32,
m20: f32,
m21: f32,
m22: f32,
) -> Self {
Self {
x_axis: Vec3::new(m00, m01, m02),
y_axis: Vec3::new(m10, m11, m12),
z_axis: Vec3::new(m20, m21, m22),
}
}
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
Self {
x_axis,
y_axis,
z_axis,
}
}
/// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f32; 9]) -> Self {
Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
}
/// Creates a `[f32; 9]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f32; 9] {
[
self.x_axis.x,
self.x_axis.y,
self.x_axis.z,
self.y_axis.x,
self.y_axis.y,
self.y_axis.z,
self.z_axis.x,
self.z_axis.y,
self.z_axis.z,
]
}
/// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
Self::from_cols(
Vec3::from_array(m[0]),
Vec3::from_array(m[1]),
Vec3::from_array(m[2]),
)
}
/// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
[
self.x_axis.to_array(),
self.y_axis.to_array(),
self.z_axis.to_array(),
]
}
/// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: Vec3) -> Self {
Self::new(
diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
)
}
/// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
#[inline]
#[must_use]
pub fn from_mat4(m: Mat4) -> Self {
Self::from_cols(
Vec3::from_vec4(m.x_axis),
Vec3::from_vec4(m.y_axis),
Vec3::from_vec4(m.z_axis),
)
}
/// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 3.
#[inline]
#[must_use]
pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
(0, 1) => Self::from_cols(m.y_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
(0, 2) => Self::from_cols(m.y_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
(0, 3) => Self::from_cols(m.y_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
(1, 0) => Self::from_cols(m.x_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
(1, 1) => Self::from_cols(m.x_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
(1, 2) => Self::from_cols(m.x_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
(1, 3) => Self::from_cols(m.x_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
(2, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.w_axis.yzw()),
(2, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.w_axis.xzw()),
(2, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.w_axis.xyw()),
(2, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.w_axis.xyz()),
(3, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.z_axis.yzw()),
(3, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.z_axis.xzw()),
(3, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.z_axis.xyw()),
(3, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 3D rotation matrix from the given quaternion.
///
/// # Panics
///
/// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_quat(rotation: Quat) -> Self {
glam_assert!(rotation.is_normalized());
let x2 = rotation.x + rotation.x;
let y2 = rotation.y + rotation.y;
let z2 = rotation.z + rotation.z;
let xx = rotation.x * x2;
let xy = rotation.x * y2;
let xz = rotation.x * z2;
let yy = rotation.y * y2;
let yz = rotation.y * z2;
let zz = rotation.z * z2;
let wx = rotation.w * x2;
let wy = rotation.w * y2;
let wz = rotation.w * z2;
Self::from_cols(
Vec3::new(1.0 - (yy + zz), xy + wz, xz - wy),
Vec3::new(xy - wz, 1.0 - (xx + zz), yz + wx),
Vec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
)
}
/// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
/// radians).
///
/// # Panics
///
/// Will panic if `axis` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
glam_assert!(axis.is_normalized());
let (sin, cos) = math::sin_cos(angle);
let (xsin, ysin, zsin) = axis.mul(sin).into();
let (x, y, z) = axis.into();
let (x2, y2, z2) = axis.mul(axis).into();
let omc = 1.0 - cos;
let xyomc = x * y * omc;
let xzomc = x * z * omc;
let yzomc = y * z * omc;
Self::from_cols(
Vec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
Vec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
Vec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
)
}
/// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
/// radians).
#[inline]
#[must_use]
pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
Self::from_euler_angles(order, a, b, c)
}
/// Extract Euler angles with the given Euler rotation order.
///
/// Note if the input matrix contains scales, shears, or other non-rotation transformations then
/// the resulting Euler angles will be ill-defined.
///
/// # Panics
///
/// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
glam_assert!(
self.x_axis.is_normalized()
&& self.y_axis.is_normalized()
&& self.z_axis.is_normalized()
);
self.to_euler_angles(order)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3::X,
Vec3::new(0.0, cosa, sina),
Vec3::new(0.0, -sina, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3::new(cosa, 0.0, -sina),
Vec3::Y,
Vec3::new(sina, 0.0, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3::new(cosa, sina, 0.0),
Vec3::new(-sina, cosa, 0.0),
Vec3::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_translation(translation: Vec2) -> Self {
Self::from_cols(
Vec3::X,
Vec3::Y,
Vec3::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given 2D rotation `angle` (in
/// radians).
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(Vec3::new(cos, sin, 0.0), Vec3::new(-sin, cos, 0.0), Vec3::Z)
}
/// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
/// radians) and `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
Vec3::new(cos * scale.x, sin * scale.x, 0.0),
Vec3::new(-sin * scale.y, cos * scale.y, 0.0),
Vec3::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
///
/// # Panics
///
/// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_scale(scale: Vec2) -> Self {
// Do not panic as long as any component is non-zero
glam_assert!(scale.cmpne(Vec2::ZERO).any());
Self::from_cols(
Vec3::new(scale.x, 0.0, 0.0),
Vec3::new(0.0, scale.y, 0.0),
Vec3::Z,
)
}
/// Creates an affine transformation matrix from the given 2x2 matrix.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
pub fn from_mat2(m: Mat2) -> Self {
Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3::Z)
}
/// Creates a 3x3 matrix from the first 9 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f32]) -> Self {
Self::new(
slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
slice[8],
)
}
/// Writes the columns of `self` to the first 9 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.x_axis.z;
slice[3] = self.y_axis.x;
slice[4] = self.y_axis.y;
slice[5] = self.y_axis.z;
slice[6] = self.z_axis.x;
slice[7] = self.z_axis.y;
slice[8] = self.z_axis.z;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> Vec3 {
match index {
0 => self.x_axis,
1 => self.y_axis,
2 => self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut Vec3 {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
2 => &mut self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> Vec3 {
match index {
0 => Vec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
1 => Vec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
2 => Vec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
Self {
x_axis: Vec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
y_axis: Vec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
z_axis: Vec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
}
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f32 {
self.z_axis.dot(self.x_axis.cross(self.y_axis))
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let tmp0 = self.y_axis.cross(self.z_axis);
let tmp1 = self.z_axis.cross(self.x_axis);
let tmp2 = self.x_axis.cross(self.y_axis);
let det = self.z_axis.dot(tmp2);
glam_assert!(det != 0.0);
let inv_det = Vec3::splat(det.recip());
Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
}
/// Transforms the given 2D vector as a point.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
}
/// Rotates the given 2D vector.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
}
/// Transforms a 3D vector.
#[inline]
#[must_use]
pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
let mut res = self.x_axis.mul(rhs.x);
res = res.add(self.y_axis.mul(rhs.y));
res = res.add(self.z_axis.mul(rhs.z));
res
}
/// Transforms a [`Vec3A`].
#[inline]
#[must_use]
pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
self.mul_vec3(rhs.into()).into()
}
/// Multiplies two 3x3 matrices.
#[inline]
#[must_use]
pub fn mul_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.mul(rhs.x_axis),
self.mul(rhs.y_axis),
self.mul(rhs.z_axis),
)
}
/// Adds two 3x3 matrices.
#[inline]
#[must_use]
pub fn add_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.add(rhs.x_axis),
self.y_axis.add(rhs.y_axis),
self.z_axis.add(rhs.z_axis),
)
}
/// Subtracts two 3x3 matrices.
#[inline]
#[must_use]
pub fn sub_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.sub(rhs.x_axis),
self.y_axis.sub(rhs.y_axis),
self.z_axis.sub(rhs.z_axis),
)
}
/// Multiplies a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f32) -> Self {
Self::from_cols(
self.x_axis.mul(rhs),
self.y_axis.mul(rhs),
self.z_axis.mul(rhs),
)
}
/// Divides a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f32) -> Self {
let rhs = Vec3::splat(rhs);
Self::from_cols(
self.x_axis.div(rhs),
self.y_axis.div(rhs),
self.z_axis.div(rhs),
)
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
&& self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
}
#[inline]
pub fn as_dmat3(&self) -> DMat3 {
DMat3::from_cols(
self.x_axis.as_dvec3(),
self.y_axis.as_dvec3(),
self.z_axis.as_dvec3(),
)
}
}
impl Default for Mat3 {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<Mat3> for Mat3 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat3(&rhs)
}
}
impl AddAssign<Mat3> for Mat3 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat3(&rhs);
}
}
impl Sub<Mat3> for Mat3 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat3(&rhs)
}
}
impl SubAssign<Mat3> for Mat3 {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat3(&rhs);
}
}
impl Neg for Mat3 {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
}
}
impl Mul<Mat3> for Mat3 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat3(&rhs)
}
}
impl MulAssign<Mat3> for Mat3 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat3(&rhs);
}
}
impl Mul<Vec3> for Mat3 {
type Output = Vec3;
#[inline]
fn mul(self, rhs: Vec3) -> Self::Output {
self.mul_vec3(rhs)
}
}
impl Mul<Mat3> for f32 {
type Output = Mat3;
#[inline]
fn mul(self, rhs: Mat3) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f32> for Mat3 {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f32> for Mat3 {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = self.mul_scalar(rhs);
}
}
impl Div<Mat3> for f32 {
type Output = Mat3;
#[inline]
fn div(self, rhs: Mat3) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f32> for Mat3 {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f32> for Mat3 {
#[inline]
fn div_assign(&mut self, rhs: f32) {
*self = self.div_scalar(rhs);
}
}
impl Mul<Vec3A> for Mat3 {
type Output = Vec3A;
#[inline]
fn mul(self, rhs: Vec3A) -> Vec3A {
self.mul_vec3a(rhs)
}
}
impl From<Mat3A> for Mat3 {
#[inline]
fn from(m: Mat3A) -> Self {
Self {
x_axis: m.x_axis.into(),
y_axis: m.y_axis.into(),
z_axis: m.z_axis.into(),
}
}
}
impl Sum<Self> for Mat3 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Mat3 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Mat3 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Mat3 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for Mat3 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsRef<[f32; 9]> for Mat3 {
#[inline]
fn as_ref(&self) -> &[f32; 9] {
unsafe { &*(self as *const Self as *const [f32; 9]) }
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsMut<[f32; 9]> for Mat3 {
#[inline]
fn as_mut(&mut self) -> &mut [f32; 9] {
unsafe { &mut *(self as *mut Self as *mut [f32; 9]) }
}
}
impl fmt::Debug for Mat3 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(Mat3))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.field("z_axis", &self.z_axis)
.finish()
}
}
impl fmt::Display for Mat3 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}]",
p, self.x_axis, p, self.y_axis, p, self.z_axis
)
} else {
write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
}
}
}

241
vendor/glam/src/f32/math.rs vendored Normal file
View File

@@ -0,0 +1,241 @@
/// Returns a very close approximation of `self.clamp(-1.0, 1.0).acos()`.
#[inline]
fn acos_approx_f32(v: f32) -> f32 {
// Based on https://github.com/microsoft/DirectXMath `XMScalarAcos`
// Clamp input to [-1,1].
let nonnegative = v >= 0.0;
let x = abs(v);
let mut omx = 1.0 - x;
if omx < 0.0 {
omx = 0.0;
}
let root = sqrt(omx);
// 7-degree minimax approximation
#[allow(clippy::approx_constant)]
let mut result =
((((((-0.001_262_491_1 * x + 0.006_670_09) * x - 0.017_088_126) * x + 0.030_891_88) * x
- 0.050_174_303)
* x
+ 0.088_978_99)
* x
- 0.214_598_8)
* x
+ 1.570_796_3;
result *= root;
// acos(x) = pi - acos(-x) when x < 0
if nonnegative {
result
} else {
core::f32::consts::PI - result
}
}
#[cfg(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))]
mod libm_math {
#[inline(always)]
pub(crate) fn abs(f: f32) -> f32 {
libm::fabsf(f)
}
#[inline(always)]
pub(crate) fn acos_approx(f: f32) -> f32 {
super::acos_approx_f32(f)
}
#[inline(always)]
pub(crate) fn atan2(f: f32, other: f32) -> f32 {
libm::atan2f(f, other)
}
#[allow(unused)]
#[inline(always)]
pub(crate) fn sin(f: f32) -> f32 {
libm::sinf(f)
}
#[inline(always)]
pub(crate) fn sin_cos(f: f32) -> (f32, f32) {
libm::sincosf(f)
}
#[inline(always)]
pub(crate) fn tan(f: f32) -> f32 {
libm::tanf(f)
}
#[inline(always)]
pub(crate) fn sqrt(f: f32) -> f32 {
libm::sqrtf(f)
}
#[inline(always)]
pub(crate) fn copysign(f: f32, sign: f32) -> f32 {
libm::copysignf(f, sign)
}
#[inline(always)]
pub(crate) fn signum(f: f32) -> f32 {
if f.is_nan() {
f32::NAN
} else {
copysign(1.0, f)
}
}
#[inline(always)]
pub(crate) fn round(f: f32) -> f32 {
libm::roundf(f)
}
#[inline(always)]
pub(crate) fn trunc(f: f32) -> f32 {
libm::truncf(f)
}
#[inline(always)]
pub(crate) fn ceil(f: f32) -> f32 {
libm::ceilf(f)
}
#[inline(always)]
pub(crate) fn floor(f: f32) -> f32 {
libm::floorf(f)
}
#[inline(always)]
pub(crate) fn exp(f: f32) -> f32 {
libm::expf(f)
}
#[inline(always)]
pub(crate) fn powf(f: f32, n: f32) -> f32 {
libm::powf(f, n)
}
#[inline(always)]
pub(crate) fn mul_add(a: f32, b: f32, c: f32) -> f32 {
libm::fmaf(a, b, c)
}
#[inline]
pub fn div_euclid(a: f32, b: f32) -> f32 {
// Based on https://doc.rust-lang.org/src/std/f32.rs.html#293
let q = libm::truncf(a / b);
if a % b < 0.0 {
return if b > 0.0 { q - 1.0 } else { q + 1.0 };
}
q
}
#[inline]
pub fn rem_euclid(a: f32, b: f32) -> f32 {
let r = a % b;
if r < 0.0 {
r + abs(b)
} else {
r
}
}
}
#[cfg(all(not(feature = "libm"), feature = "std"))]
mod std_math {
#[inline(always)]
pub(crate) fn abs(f: f32) -> f32 {
f32::abs(f)
}
#[inline(always)]
pub(crate) fn acos_approx(f: f32) -> f32 {
super::acos_approx_f32(f)
}
#[inline(always)]
pub(crate) fn atan2(f: f32, other: f32) -> f32 {
f32::atan2(f, other)
}
#[allow(unused)]
#[inline(always)]
pub(crate) fn sin(f: f32) -> f32 {
f32::sin(f)
}
#[inline(always)]
pub(crate) fn sin_cos(f: f32) -> (f32, f32) {
f32::sin_cos(f)
}
#[inline(always)]
pub(crate) fn tan(f: f32) -> f32 {
f32::tan(f)
}
#[inline(always)]
pub(crate) fn sqrt(f: f32) -> f32 {
f32::sqrt(f)
}
#[inline(always)]
pub(crate) fn copysign(f: f32, sign: f32) -> f32 {
f32::copysign(f, sign)
}
#[inline(always)]
pub(crate) fn signum(f: f32) -> f32 {
f32::signum(f)
}
#[inline(always)]
pub(crate) fn round(f: f32) -> f32 {
f32::round(f)
}
#[inline(always)]
pub(crate) fn trunc(f: f32) -> f32 {
f32::trunc(f)
}
#[inline(always)]
pub(crate) fn ceil(f: f32) -> f32 {
f32::ceil(f)
}
#[inline(always)]
pub(crate) fn floor(f: f32) -> f32 {
f32::floor(f)
}
#[inline(always)]
pub(crate) fn exp(f: f32) -> f32 {
f32::exp(f)
}
#[inline(always)]
pub(crate) fn powf(f: f32, n: f32) -> f32 {
f32::powf(f, n)
}
#[inline(always)]
pub(crate) fn mul_add(a: f32, b: f32, c: f32) -> f32 {
f32::mul_add(a, b, c)
}
#[inline]
pub fn div_euclid(a: f32, b: f32) -> f32 {
f32::div_euclid(a, b)
}
#[inline]
pub fn rem_euclid(a: f32, b: f32) -> f32 {
f32::rem_euclid(a, b)
}
}
#[cfg(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))]
pub(crate) use libm_math::*;
#[cfg(all(not(feature = "libm"), feature = "std"))]
pub(crate) use std_math::*;

6
vendor/glam/src/f32/neon.rs vendored Normal file
View File

@@ -0,0 +1,6 @@
pub mod mat2;
pub mod mat3a;
pub mod mat4;
pub mod quat;
pub mod vec3a;
pub mod vec4;

624
vendor/glam/src/f32/neon/mat2.rs vendored Normal file
View File

@@ -0,0 +1,624 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use core::arch::aarch64::*;
#[repr(C)]
union UnionCast {
a: [f32; 4],
v: Mat2,
}
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
Mat2::from_cols(x_axis, y_axis)
}
/// A 2x2 column major matrix.
///
/// SIMD vector types are used for storage on supported platforms.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Mat2(pub(crate) float32x4_t);
impl Mat2 {
/// A 2x2 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
/// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
unsafe {
UnionCast {
a: [m00, m01, m10, m11],
}
.v
}
}
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
unsafe {
UnionCast {
a: [x_axis.x, x_axis.y, y_axis.x, y_axis.y],
}
.v
}
}
/// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f32; 4]) -> Self {
Self::new(m[0], m[1], m[2], m[3])
}
/// Creates a `[f32; 4]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f32; 4] {
unsafe { *(self as *const Self as *const [f32; 4]) }
}
/// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
}
/// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
}
/// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: Vec2) -> Self {
Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
}
/// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
}
/// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos, sin, -sin, cos)
}
/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3(m: Mat3) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3a(m: Mat3A) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 2x2 matrix from the first 4 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f32]) -> Self {
Self::new(slice[0], slice[1], slice[2], slice[3])
}
/// Writes the columns of `self` to the first 4 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.y_axis.x;
slice[3] = self.y_axis.y;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> Vec2 {
match index {
0 => self.x_axis,
1 => self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> Vec2 {
match index {
0 => Vec2::new(self.x_axis.x, self.y_axis.x),
1 => Vec2::new(self.x_axis.y, self.y_axis.y),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
Self(unsafe {
vsetq_lane_f32(
vgetq_lane_f32(self.0, 2),
vsetq_lane_f32(vgetq_lane_f32(self.0, 1), self.0, 2),
1,
)
})
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f32 {
unsafe {
let abcd = self.0;
let badc = vrev64q_f32(abcd);
let dcba = vextq_f32(badc, badc, 2);
let prod = vmulq_f32(abcd, dcba);
let det = vsubq_f32(prod, vdupq_laneq_f32(prod, 1));
vgetq_lane_f32(det, 0)
}
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
unsafe {
const SIGN: float32x4_t = crate::neon::f32x4_from_array([1.0, -1.0, -1.0, 1.0]);
let abcd = self.0;
let badc = vrev64q_f32(abcd);
let dcba = vextq_f32(badc, badc, 2);
let prod = vmulq_f32(abcd, dcba);
let sub = vsubq_f32(prod, vdupq_laneq_f32(prod, 1));
let det = vdupq_laneq_f32(sub, 0);
let tmp = vdivq_f32(SIGN, det);
glam_assert!(Mat2(tmp).is_finite());
//let dbca = simd_swizzle!(abcd, [3, 1, 2, 0]);
let dbca = vsetq_lane_f32(
vgetq_lane_f32(abcd, 0),
vsetq_lane_f32(vgetq_lane_f32(abcd, 3), abcd, 0),
3,
);
Self(vmulq_f32(dbca, tmp))
}
}
/// Transforms a 2D vector.
#[inline]
#[must_use]
pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
unsafe {
let abcd = self.0;
let xxyy = vld1q_f32([rhs.x, rhs.x, rhs.y, rhs.y].as_ptr());
let axbxcydy = vmulq_f32(abcd, xxyy);
// let cydyaxbx = simd_swizzle!(axbxcydy, [2, 3, 0, 1]);
let cydyaxbx = vextq_f32(axbxcydy, axbxcydy, 2);
let result = vaddq_f32(axbxcydy, cydyaxbx);
*(&result as *const float32x4_t as *const Vec2)
}
}
/// Multiplies two 2x2 matrices.
#[inline]
#[must_use]
pub fn mul_mat2(&self, rhs: &Self) -> Self {
unsafe {
let abcd = self.0;
let xxyy0 = vzip1q_f32(rhs.0, rhs.0);
let xxyy1 = vzip2q_f32(rhs.0, rhs.0);
let axbxcydy0 = vmulq_f32(abcd, xxyy0);
let axbxcydy1 = vmulq_f32(abcd, xxyy1);
let cydyaxbx0 = vextq_f32(axbxcydy0, axbxcydy0, 2);
let cydyaxbx1 = vextq_f32(axbxcydy1, axbxcydy1, 2);
let result0 = vaddq_f32(axbxcydy0, cydyaxbx0);
let result1 = vaddq_f32(axbxcydy1, cydyaxbx1);
Self(vreinterpretq_f32_u64(vsetq_lane_u64(
vgetq_lane_u64(vreinterpretq_u64_f32(result1), 0),
vreinterpretq_u64_f32(result0),
1,
)))
}
}
/// Adds two 2x2 matrices.
#[inline]
#[must_use]
pub fn add_mat2(&self, rhs: &Self) -> Self {
Self(unsafe { vaddq_f32(self.0, rhs.0) })
}
/// Subtracts two 2x2 matrices.
#[inline]
#[must_use]
pub fn sub_mat2(&self, rhs: &Self) -> Self {
Self(unsafe { vsubq_f32(self.0, rhs.0) })
}
/// Multiplies a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f32) -> Self {
Self(unsafe { vmulq_f32(self.0, vld1q_dup_f32(&rhs)) })
}
/// Divides a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f32) -> Self {
Self(unsafe { vdivq_f32(self.0, vld1q_dup_f32(&rhs)) })
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
}
#[inline]
pub fn as_dmat2(&self) -> DMat2 {
DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
}
}
impl Default for Mat2 {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat2(&rhs)
}
}
impl AddAssign<Mat2> for Mat2 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat2(&rhs);
}
}
impl Sub<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat2(&rhs)
}
}
impl SubAssign<Mat2> for Mat2 {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat2(&rhs);
}
}
impl Neg for Mat2 {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self(unsafe { vnegq_f32(self.0) })
}
}
impl Mul<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat2(&rhs)
}
}
impl MulAssign<Mat2> for Mat2 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat2(&rhs);
}
}
impl Mul<Vec2> for Mat2 {
type Output = Vec2;
#[inline]
fn mul(self, rhs: Vec2) -> Self::Output {
self.mul_vec2(rhs)
}
}
impl Mul<Mat2> for f32 {
type Output = Mat2;
#[inline]
fn mul(self, rhs: Mat2) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f32> for Mat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f32> for Mat2 {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = self.mul_scalar(rhs);
}
}
impl Div<Mat2> for f32 {
type Output = Mat2;
#[inline]
fn div(self, rhs: Mat2) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f32> for Mat2 {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f32> for Mat2 {
#[inline]
fn div_assign(&mut self, rhs: f32) {
*self = self.div_scalar(rhs);
}
}
impl Sum<Self> for Mat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Mat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Mat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Mat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for Mat2 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsRef<[f32; 4]> for Mat2 {
#[inline]
fn as_ref(&self) -> &[f32; 4] {
unsafe { &*(self as *const Self as *const [f32; 4]) }
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsMut<[f32; 4]> for Mat2 {
#[inline]
fn as_mut(&mut self) -> &mut [f32; 4] {
unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
}
}
impl core::ops::Deref for Mat2 {
type Target = crate::deref::Cols2<Vec2>;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Self as *const Self::Target) }
}
}
impl core::ops::DerefMut for Mat2 {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self as *mut Self as *mut Self::Target) }
}
}
impl fmt::Debug for Mat2 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(Mat2))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.finish()
}
}
impl fmt::Display for Mat2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
} else {
write!(f, "[{}, {}]", self.x_axis, self.y_axis)
}
}
}

937
vendor/glam/src/f32/neon/mat3a.rs vendored Normal file
View File

@@ -0,0 +1,937 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{
euler::{FromEuler, ToEuler},
f32::math,
swizzles::*,
DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A,
};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use core::arch::aarch64::*;
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
Mat3A::from_cols(x_axis, y_axis, z_axis)
}
/// A 3x3 column major matrix.
///
/// This 3x3 matrix type features convenience methods for creating and using linear and
/// affine transformations. If you are primarily dealing with 2D affine transformations the
/// [`Affine2`](crate::Affine2) type is much faster and more space efficient than
/// using a 3x3 matrix.
///
/// Linear transformations including 3D rotation and scale can be created using methods
/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
/// [`Self::from_rotation_z()`].
///
/// The resulting matrices can be use to transform 3D vectors using regular vector
/// multiplication.
///
/// Affine transformations including 2D translation, rotation and scale can be created
/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
///
/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
/// are provided for performing affine transforms on 2D vectors and points. These multiply
/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
/// vectors respectively. These methods assume that `Self` contains a valid affine
/// transform.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Mat3A {
pub x_axis: Vec3A,
pub y_axis: Vec3A,
pub z_axis: Vec3A,
}
impl Mat3A {
/// A 3x3 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO);
/// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(
m00: f32,
m01: f32,
m02: f32,
m10: f32,
m11: f32,
m12: f32,
m20: f32,
m21: f32,
m22: f32,
) -> Self {
Self {
x_axis: Vec3A::new(m00, m01, m02),
y_axis: Vec3A::new(m10, m11, m12),
z_axis: Vec3A::new(m20, m21, m22),
}
}
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
Self {
x_axis,
y_axis,
z_axis,
}
}
/// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f32; 9]) -> Self {
Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
}
/// Creates a `[f32; 9]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f32; 9] {
let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array();
[
x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y,
z_axis_z,
]
}
/// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
Self::from_cols(
Vec3A::from_array(m[0]),
Vec3A::from_array(m[1]),
Vec3A::from_array(m[2]),
)
}
/// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
[
self.x_axis.to_array(),
self.y_axis.to_array(),
self.z_axis.to_array(),
]
}
/// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: Vec3) -> Self {
Self::new(
diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
)
}
/// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
#[inline]
#[must_use]
pub fn from_mat4(m: Mat4) -> Self {
Self::from_cols(
Vec3A::from_vec4(m.x_axis),
Vec3A::from_vec4(m.y_axis),
Vec3A::from_vec4(m.z_axis),
)
}
/// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 3.
#[inline]
#[must_use]
pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(0, 1) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(0, 2) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(0, 3) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(1, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(1, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(1, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(1, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(2, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(2, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(2, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(2, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(3, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
),
(3, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
),
(3, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
),
(3, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
),
_ => panic!("index out of bounds"),
}
}
/// Creates a 3D rotation matrix from the given quaternion.
///
/// # Panics
///
/// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_quat(rotation: Quat) -> Self {
glam_assert!(rotation.is_normalized());
let x2 = rotation.x + rotation.x;
let y2 = rotation.y + rotation.y;
let z2 = rotation.z + rotation.z;
let xx = rotation.x * x2;
let xy = rotation.x * y2;
let xz = rotation.x * z2;
let yy = rotation.y * y2;
let yz = rotation.y * z2;
let zz = rotation.z * z2;
let wx = rotation.w * x2;
let wy = rotation.w * y2;
let wz = rotation.w * z2;
Self::from_cols(
Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy),
Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx),
Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
)
}
/// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
/// radians).
///
/// # Panics
///
/// Will panic if `axis` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
glam_assert!(axis.is_normalized());
let (sin, cos) = math::sin_cos(angle);
let (xsin, ysin, zsin) = axis.mul(sin).into();
let (x, y, z) = axis.into();
let (x2, y2, z2) = axis.mul(axis).into();
let omc = 1.0 - cos;
let xyomc = x * y * omc;
let xzomc = x * z * omc;
let yzomc = y * z * omc;
Self::from_cols(
Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
)
}
/// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
/// radians).
#[inline]
#[must_use]
pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
Self::from_euler_angles(order, a, b, c)
}
/// Extract Euler angles with the given Euler rotation order.
///
/// Note if the input matrix contains scales, shears, or other non-rotation transformations then
/// the resulting Euler angles will be ill-defined.
///
/// # Panics
///
/// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
glam_assert!(
self.x_axis.is_normalized()
&& self.y_axis.is_normalized()
&& self.z_axis.is_normalized()
);
self.to_euler_angles(order)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::X,
Vec3A::new(0.0, cosa, sina),
Vec3A::new(0.0, -sina, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cosa, 0.0, -sina),
Vec3A::Y,
Vec3A::new(sina, 0.0, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cosa, sina, 0.0),
Vec3A::new(-sina, cosa, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_translation(translation: Vec2) -> Self {
Self::from_cols(
Vec3A::X,
Vec3A::Y,
Vec3A::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given 2D rotation `angle` (in
/// radians).
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cos, sin, 0.0),
Vec3A::new(-sin, cos, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
/// radians) and `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
Vec3A::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
///
/// # Panics
///
/// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_scale(scale: Vec2) -> Self {
// Do not panic as long as any component is non-zero
glam_assert!(scale.cmpne(Vec2::ZERO).any());
Self::from_cols(
Vec3A::new(scale.x, 0.0, 0.0),
Vec3A::new(0.0, scale.y, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2x2 matrix.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
pub fn from_mat2(m: Mat2) -> Self {
Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z)
}
/// Creates a 3x3 matrix from the first 9 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f32]) -> Self {
Self::new(
slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
slice[8],
)
}
/// Writes the columns of `self` to the first 9 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.x_axis.z;
slice[3] = self.y_axis.x;
slice[4] = self.y_axis.y;
slice[5] = self.y_axis.z;
slice[6] = self.z_axis.x;
slice[7] = self.z_axis.y;
slice[8] = self.z_axis.z;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> Vec3A {
match index {
0 => self.x_axis,
1 => self.y_axis,
2 => self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut Vec3A {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
2 => &mut self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> Vec3A {
match index {
0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
let x = self.x_axis.0;
let y = self.y_axis.0;
let z = self.z_axis.0;
unsafe {
let tmp0 = vreinterpretq_f32_u64(vsetq_lane_u64(
vgetq_lane_u64(vreinterpretq_u64_f32(y), 0),
vreinterpretq_u64_f32(x),
1,
));
let tmp1 = vreinterpretq_f32_u64(vzip2q_u64(
vreinterpretq_u64_f32(x),
vreinterpretq_u64_f32(y),
));
Mat3A::from_cols(
Vec3A::from(vsetq_lane_f32(vgetq_lane_f32(z, 0), vuzp1q_f32(tmp0, z), 3)),
Vec3A::from(vuzp2q_f32(tmp0, vdupq_laneq_f32(z, 1))),
Vec3A::from(vsetq_lane_f32(vgetq_lane_f32(z, 2), vuzp1q_f32(tmp1, z), 2)),
)
}
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f32 {
self.z_axis.dot(self.x_axis.cross(self.y_axis))
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let tmp0 = self.y_axis.cross(self.z_axis);
let tmp1 = self.z_axis.cross(self.x_axis);
let tmp2 = self.x_axis.cross(self.y_axis);
let det = self.z_axis.dot(tmp2);
glam_assert!(det != 0.0);
let inv_det = Vec3A::splat(det.recip());
Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
}
/// Transforms the given 2D vector as a point.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
}
/// Rotates the given 2D vector.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
}
/// Transforms a 3D vector.
#[inline]
#[must_use]
pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
self.mul_vec3a(rhs.into()).into()
}
/// Transforms a [`Vec3A`].
#[inline]
#[must_use]
pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
let mut res = self.x_axis.mul(rhs.xxx());
res = res.add(self.y_axis.mul(rhs.yyy()));
res = res.add(self.z_axis.mul(rhs.zzz()));
res
}
/// Multiplies two 3x3 matrices.
#[inline]
#[must_use]
pub fn mul_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.mul(rhs.x_axis),
self.mul(rhs.y_axis),
self.mul(rhs.z_axis),
)
}
/// Adds two 3x3 matrices.
#[inline]
#[must_use]
pub fn add_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.add(rhs.x_axis),
self.y_axis.add(rhs.y_axis),
self.z_axis.add(rhs.z_axis),
)
}
/// Subtracts two 3x3 matrices.
#[inline]
#[must_use]
pub fn sub_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.sub(rhs.x_axis),
self.y_axis.sub(rhs.y_axis),
self.z_axis.sub(rhs.z_axis),
)
}
/// Multiplies a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f32) -> Self {
Self::from_cols(
self.x_axis.mul(rhs),
self.y_axis.mul(rhs),
self.z_axis.mul(rhs),
)
}
/// Divides a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f32) -> Self {
let rhs = Vec3A::splat(rhs);
Self::from_cols(
self.x_axis.div(rhs),
self.y_axis.div(rhs),
self.z_axis.div(rhs),
)
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
&& self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
}
#[inline]
pub fn as_dmat3(&self) -> DMat3 {
DMat3::from_cols(
self.x_axis.as_dvec3(),
self.y_axis.as_dvec3(),
self.z_axis.as_dvec3(),
)
}
}
impl Default for Mat3A {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat3(&rhs)
}
}
impl AddAssign<Mat3A> for Mat3A {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat3(&rhs);
}
}
impl Sub<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat3(&rhs)
}
}
impl SubAssign<Mat3A> for Mat3A {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat3(&rhs);
}
}
impl Neg for Mat3A {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
}
}
impl Mul<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat3(&rhs)
}
}
impl MulAssign<Mat3A> for Mat3A {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat3(&rhs);
}
}
impl Mul<Vec3A> for Mat3A {
type Output = Vec3A;
#[inline]
fn mul(self, rhs: Vec3A) -> Self::Output {
self.mul_vec3a(rhs)
}
}
impl Mul<Mat3A> for f32 {
type Output = Mat3A;
#[inline]
fn mul(self, rhs: Mat3A) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f32> for Mat3A {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f32> for Mat3A {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = self.mul_scalar(rhs);
}
}
impl Div<Mat3A> for f32 {
type Output = Mat3A;
#[inline]
fn div(self, rhs: Mat3A) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f32> for Mat3A {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f32> for Mat3A {
#[inline]
fn div_assign(&mut self, rhs: f32) {
*self = self.div_scalar(rhs);
}
}
impl Mul<Vec3> for Mat3A {
type Output = Vec3;
#[inline]
fn mul(self, rhs: Vec3) -> Vec3 {
self.mul_vec3a(rhs.into()).into()
}
}
impl From<Mat3> for Mat3A {
#[inline]
fn from(m: Mat3) -> Self {
Self {
x_axis: m.x_axis.into(),
y_axis: m.y_axis.into(),
z_axis: m.z_axis.into(),
}
}
}
impl Sum<Self> for Mat3A {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Mat3A {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Mat3A {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Mat3A {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for Mat3A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
}
}
impl fmt::Debug for Mat3A {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(Mat3A))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.field("z_axis", &self.z_axis)
.finish()
}
}
impl fmt::Display for Mat3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}]",
p, self.x_axis, p, self.y_axis, p, self.z_axis
)
} else {
write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
}
}
}

1541
vendor/glam/src/f32/neon/mat4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1035
vendor/glam/src/f32/neon/quat.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1917
vendor/glam/src/f32/neon/vec3a.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1858
vendor/glam/src/f32/neon/vec4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

6
vendor/glam/src/f32/scalar.rs vendored Normal file
View File

@@ -0,0 +1,6 @@
pub mod mat2;
pub mod mat3a;
pub mod mat4;
pub mod quat;
pub mod vec3a;
pub mod vec4;

563
vendor/glam/src/f32/scalar/mat2.rs vendored Normal file
View File

@@ -0,0 +1,563 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
Mat2::from_cols(x_axis, y_axis)
}
/// A 2x2 column major matrix.
#[derive(Clone, Copy)]
#[cfg_attr(
not(any(feature = "scalar-math", target_arch = "spirv")),
repr(align(16))
)]
#[cfg_attr(feature = "cuda", repr(align(8)))]
#[repr(C)]
pub struct Mat2 {
pub x_axis: Vec2,
pub y_axis: Vec2,
}
impl Mat2 {
/// A 2x2 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
/// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
Self {
x_axis: Vec2::new(m00, m01),
y_axis: Vec2::new(m10, m11),
}
}
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
Self { x_axis, y_axis }
}
/// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f32; 4]) -> Self {
Self::new(m[0], m[1], m[2], m[3])
}
/// Creates a `[f32; 4]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f32; 4] {
[self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
}
/// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
}
/// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
[self.x_axis.to_array(), self.y_axis.to_array()]
}
/// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: Vec2) -> Self {
Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
}
/// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
}
/// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos, sin, -sin, cos)
}
/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3(m: Mat3) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3a(m: Mat3A) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 2x2 matrix from the first 4 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f32]) -> Self {
Self::new(slice[0], slice[1], slice[2], slice[3])
}
/// Writes the columns of `self` to the first 4 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.y_axis.x;
slice[3] = self.y_axis.y;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> Vec2 {
match index {
0 => self.x_axis,
1 => self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> Vec2 {
match index {
0 => Vec2::new(self.x_axis.x, self.y_axis.x),
1 => Vec2::new(self.x_axis.y, self.y_axis.y),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
Self {
x_axis: Vec2::new(self.x_axis.x, self.y_axis.x),
y_axis: Vec2::new(self.x_axis.y, self.y_axis.y),
}
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f32 {
self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let inv_det = {
let det = self.determinant();
glam_assert!(det != 0.0);
det.recip()
};
Self::new(
self.y_axis.y * inv_det,
self.x_axis.y * -inv_det,
self.y_axis.x * -inv_det,
self.x_axis.x * inv_det,
)
}
/// Transforms a 2D vector.
#[inline]
#[must_use]
pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
#[allow(clippy::suspicious_operation_groupings)]
Vec2::new(
(self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
(self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
)
}
/// Multiplies two 2x2 matrices.
#[inline]
#[must_use]
pub fn mul_mat2(&self, rhs: &Self) -> Self {
Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
}
/// Adds two 2x2 matrices.
#[inline]
#[must_use]
pub fn add_mat2(&self, rhs: &Self) -> Self {
Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
}
/// Subtracts two 2x2 matrices.
#[inline]
#[must_use]
pub fn sub_mat2(&self, rhs: &Self) -> Self {
Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
}
/// Multiplies a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f32) -> Self {
Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
}
/// Divides a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f32) -> Self {
let rhs = Vec2::splat(rhs);
Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs))
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
}
#[inline]
pub fn as_dmat2(&self) -> DMat2 {
DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
}
}
impl Default for Mat2 {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat2(&rhs)
}
}
impl AddAssign<Mat2> for Mat2 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat2(&rhs);
}
}
impl Sub<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat2(&rhs)
}
}
impl SubAssign<Mat2> for Mat2 {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat2(&rhs);
}
}
impl Neg for Mat2 {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
}
}
impl Mul<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat2(&rhs)
}
}
impl MulAssign<Mat2> for Mat2 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat2(&rhs);
}
}
impl Mul<Vec2> for Mat2 {
type Output = Vec2;
#[inline]
fn mul(self, rhs: Vec2) -> Self::Output {
self.mul_vec2(rhs)
}
}
impl Mul<Mat2> for f32 {
type Output = Mat2;
#[inline]
fn mul(self, rhs: Mat2) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f32> for Mat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f32> for Mat2 {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = self.mul_scalar(rhs);
}
}
impl Div<Mat2> for f32 {
type Output = Mat2;
#[inline]
fn div(self, rhs: Mat2) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f32> for Mat2 {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f32> for Mat2 {
#[inline]
fn div_assign(&mut self, rhs: f32) {
*self = self.div_scalar(rhs);
}
}
impl Sum<Self> for Mat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Mat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Mat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Mat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for Mat2 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsRef<[f32; 4]> for Mat2 {
#[inline]
fn as_ref(&self) -> &[f32; 4] {
unsafe { &*(self as *const Self as *const [f32; 4]) }
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsMut<[f32; 4]> for Mat2 {
#[inline]
fn as_mut(&mut self) -> &mut [f32; 4] {
unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
}
}
impl fmt::Debug for Mat2 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(Mat2))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.finish()
}
}
impl fmt::Display for Mat2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
} else {
write!(f, "[{}, {}]", self.x_axis, self.y_axis)
}
}
}

924
vendor/glam/src/f32/scalar/mat3a.rs vendored Normal file
View File

@@ -0,0 +1,924 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{
euler::{FromEuler, ToEuler},
f32::math,
swizzles::*,
DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A,
};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
Mat3A::from_cols(x_axis, y_axis, z_axis)
}
/// A 3x3 column major matrix.
///
/// This 3x3 matrix type features convenience methods for creating and using linear and
/// affine transformations. If you are primarily dealing with 2D affine transformations the
/// [`Affine2`](crate::Affine2) type is much faster and more space efficient than
/// using a 3x3 matrix.
///
/// Linear transformations including 3D rotation and scale can be created using methods
/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
/// [`Self::from_rotation_z()`].
///
/// The resulting matrices can be use to transform 3D vectors using regular vector
/// multiplication.
///
/// Affine transformations including 2D translation, rotation and scale can be created
/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
///
/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
/// are provided for performing affine transforms on 2D vectors and points. These multiply
/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
/// vectors respectively. These methods assume that `Self` contains a valid affine
/// transform.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Mat3A {
pub x_axis: Vec3A,
pub y_axis: Vec3A,
pub z_axis: Vec3A,
}
impl Mat3A {
/// A 3x3 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO);
/// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(
m00: f32,
m01: f32,
m02: f32,
m10: f32,
m11: f32,
m12: f32,
m20: f32,
m21: f32,
m22: f32,
) -> Self {
Self {
x_axis: Vec3A::new(m00, m01, m02),
y_axis: Vec3A::new(m10, m11, m12),
z_axis: Vec3A::new(m20, m21, m22),
}
}
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
Self {
x_axis,
y_axis,
z_axis,
}
}
/// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f32; 9]) -> Self {
Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
}
/// Creates a `[f32; 9]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f32; 9] {
[
self.x_axis.x,
self.x_axis.y,
self.x_axis.z,
self.y_axis.x,
self.y_axis.y,
self.y_axis.z,
self.z_axis.x,
self.z_axis.y,
self.z_axis.z,
]
}
/// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
Self::from_cols(
Vec3A::from_array(m[0]),
Vec3A::from_array(m[1]),
Vec3A::from_array(m[2]),
)
}
/// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
[
self.x_axis.to_array(),
self.y_axis.to_array(),
self.z_axis.to_array(),
]
}
/// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: Vec3) -> Self {
Self::new(
diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
)
}
/// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
#[inline]
#[must_use]
pub fn from_mat4(m: Mat4) -> Self {
Self::from_cols(
Vec3A::from_vec4(m.x_axis),
Vec3A::from_vec4(m.y_axis),
Vec3A::from_vec4(m.z_axis),
)
}
/// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 3.
#[inline]
#[must_use]
pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(0, 1) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(0, 2) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(0, 3) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(1, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(1, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(1, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(1, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(2, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(2, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(2, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(2, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(3, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
),
(3, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
),
(3, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
),
(3, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
),
_ => panic!("index out of bounds"),
}
}
/// Creates a 3D rotation matrix from the given quaternion.
///
/// # Panics
///
/// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_quat(rotation: Quat) -> Self {
glam_assert!(rotation.is_normalized());
let x2 = rotation.x + rotation.x;
let y2 = rotation.y + rotation.y;
let z2 = rotation.z + rotation.z;
let xx = rotation.x * x2;
let xy = rotation.x * y2;
let xz = rotation.x * z2;
let yy = rotation.y * y2;
let yz = rotation.y * z2;
let zz = rotation.z * z2;
let wx = rotation.w * x2;
let wy = rotation.w * y2;
let wz = rotation.w * z2;
Self::from_cols(
Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy),
Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx),
Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
)
}
/// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
/// radians).
///
/// # Panics
///
/// Will panic if `axis` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
glam_assert!(axis.is_normalized());
let (sin, cos) = math::sin_cos(angle);
let (xsin, ysin, zsin) = axis.mul(sin).into();
let (x, y, z) = axis.into();
let (x2, y2, z2) = axis.mul(axis).into();
let omc = 1.0 - cos;
let xyomc = x * y * omc;
let xzomc = x * z * omc;
let yzomc = y * z * omc;
Self::from_cols(
Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
)
}
/// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
/// radians).
#[inline]
#[must_use]
pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
Self::from_euler_angles(order, a, b, c)
}
/// Extract Euler angles with the given Euler rotation order.
///
/// Note if the input matrix contains scales, shears, or other non-rotation transformations then
/// the resulting Euler angles will be ill-defined.
///
/// # Panics
///
/// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
glam_assert!(
self.x_axis.is_normalized()
&& self.y_axis.is_normalized()
&& self.z_axis.is_normalized()
);
self.to_euler_angles(order)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::X,
Vec3A::new(0.0, cosa, sina),
Vec3A::new(0.0, -sina, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cosa, 0.0, -sina),
Vec3A::Y,
Vec3A::new(sina, 0.0, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cosa, sina, 0.0),
Vec3A::new(-sina, cosa, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_translation(translation: Vec2) -> Self {
Self::from_cols(
Vec3A::X,
Vec3A::Y,
Vec3A::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given 2D rotation `angle` (in
/// radians).
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cos, sin, 0.0),
Vec3A::new(-sin, cos, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
/// radians) and `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
Vec3A::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
///
/// # Panics
///
/// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_scale(scale: Vec2) -> Self {
// Do not panic as long as any component is non-zero
glam_assert!(scale.cmpne(Vec2::ZERO).any());
Self::from_cols(
Vec3A::new(scale.x, 0.0, 0.0),
Vec3A::new(0.0, scale.y, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2x2 matrix.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
pub fn from_mat2(m: Mat2) -> Self {
Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z)
}
/// Creates a 3x3 matrix from the first 9 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f32]) -> Self {
Self::new(
slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
slice[8],
)
}
/// Writes the columns of `self` to the first 9 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.x_axis.z;
slice[3] = self.y_axis.x;
slice[4] = self.y_axis.y;
slice[5] = self.y_axis.z;
slice[6] = self.z_axis.x;
slice[7] = self.z_axis.y;
slice[8] = self.z_axis.z;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> Vec3A {
match index {
0 => self.x_axis,
1 => self.y_axis,
2 => self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut Vec3A {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
2 => &mut self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> Vec3A {
match index {
0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
Self {
x_axis: Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
y_axis: Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
z_axis: Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
}
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f32 {
self.z_axis.dot(self.x_axis.cross(self.y_axis))
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let tmp0 = self.y_axis.cross(self.z_axis);
let tmp1 = self.z_axis.cross(self.x_axis);
let tmp2 = self.x_axis.cross(self.y_axis);
let det = self.z_axis.dot(tmp2);
glam_assert!(det != 0.0);
let inv_det = Vec3A::splat(det.recip());
Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
}
/// Transforms the given 2D vector as a point.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
}
/// Rotates the given 2D vector.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
}
/// Transforms a 3D vector.
#[inline]
#[must_use]
pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
self.mul_vec3a(rhs.into()).into()
}
/// Transforms a [`Vec3A`].
#[inline]
#[must_use]
pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
let mut res = self.x_axis.mul(rhs.xxx());
res = res.add(self.y_axis.mul(rhs.yyy()));
res = res.add(self.z_axis.mul(rhs.zzz()));
res
}
/// Multiplies two 3x3 matrices.
#[inline]
#[must_use]
pub fn mul_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.mul(rhs.x_axis),
self.mul(rhs.y_axis),
self.mul(rhs.z_axis),
)
}
/// Adds two 3x3 matrices.
#[inline]
#[must_use]
pub fn add_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.add(rhs.x_axis),
self.y_axis.add(rhs.y_axis),
self.z_axis.add(rhs.z_axis),
)
}
/// Subtracts two 3x3 matrices.
#[inline]
#[must_use]
pub fn sub_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.sub(rhs.x_axis),
self.y_axis.sub(rhs.y_axis),
self.z_axis.sub(rhs.z_axis),
)
}
/// Multiplies a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f32) -> Self {
Self::from_cols(
self.x_axis.mul(rhs),
self.y_axis.mul(rhs),
self.z_axis.mul(rhs),
)
}
/// Divides a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f32) -> Self {
let rhs = Vec3A::splat(rhs);
Self::from_cols(
self.x_axis.div(rhs),
self.y_axis.div(rhs),
self.z_axis.div(rhs),
)
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
&& self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
}
#[inline]
pub fn as_dmat3(&self) -> DMat3 {
DMat3::from_cols(
self.x_axis.as_dvec3(),
self.y_axis.as_dvec3(),
self.z_axis.as_dvec3(),
)
}
}
impl Default for Mat3A {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat3(&rhs)
}
}
impl AddAssign<Mat3A> for Mat3A {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat3(&rhs);
}
}
impl Sub<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat3(&rhs)
}
}
impl SubAssign<Mat3A> for Mat3A {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat3(&rhs);
}
}
impl Neg for Mat3A {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
}
}
impl Mul<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat3(&rhs)
}
}
impl MulAssign<Mat3A> for Mat3A {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat3(&rhs);
}
}
impl Mul<Vec3A> for Mat3A {
type Output = Vec3A;
#[inline]
fn mul(self, rhs: Vec3A) -> Self::Output {
self.mul_vec3a(rhs)
}
}
impl Mul<Mat3A> for f32 {
type Output = Mat3A;
#[inline]
fn mul(self, rhs: Mat3A) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f32> for Mat3A {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f32> for Mat3A {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = self.mul_scalar(rhs);
}
}
impl Div<Mat3A> for f32 {
type Output = Mat3A;
#[inline]
fn div(self, rhs: Mat3A) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f32> for Mat3A {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f32> for Mat3A {
#[inline]
fn div_assign(&mut self, rhs: f32) {
*self = self.div_scalar(rhs);
}
}
impl Mul<Vec3> for Mat3A {
type Output = Vec3;
#[inline]
fn mul(self, rhs: Vec3) -> Vec3 {
self.mul_vec3a(rhs.into()).into()
}
}
impl From<Mat3> for Mat3A {
#[inline]
fn from(m: Mat3) -> Self {
Self {
x_axis: m.x_axis.into(),
y_axis: m.y_axis.into(),
z_axis: m.z_axis.into(),
}
}
}
impl Sum<Self> for Mat3A {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Mat3A {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Mat3A {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Mat3A {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for Mat3A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
}
}
impl fmt::Debug for Mat3A {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(Mat3A))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.field("z_axis", &self.z_axis)
.finish()
}
}
impl fmt::Display for Mat3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}]",
p, self.x_axis, p, self.y_axis, p, self.z_axis
)
} else {
write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
}
}
}

1444
vendor/glam/src/f32/scalar/mat4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

973
vendor/glam/src/f32/scalar/quat.rs vendored Normal file
View File

@@ -0,0 +1,973 @@
// Generated from quat.rs.tera template. Edit the template, not the generated file.
use crate::{
euler::{EulerRot, FromEuler, ToEuler},
f32::math,
DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, Div, Mul, MulAssign, Neg, Sub};
/// Creates a quaternion from `x`, `y`, `z` and `w` values.
///
/// This should generally not be called manually unless you know what you are doing. Use
/// one of the other constructors instead such as `identity` or `from_axis_angle`.
#[inline]
#[must_use]
pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
Quat::from_xyzw(x, y, z, w)
}
/// A quaternion representing an orientation.
///
/// This quaternion is intended to be of unit length but may denormalize due to
/// floating point "error creep" which can occur when successive quaternion
/// operations are applied.
#[derive(Clone, Copy)]
#[cfg_attr(
not(any(feature = "scalar-math", target_arch = "spirv")),
repr(align(16))
)]
#[cfg_attr(not(target_arch = "spirv"), repr(C))]
#[cfg_attr(target_arch = "spirv", repr(simd))]
pub struct Quat {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
impl Quat {
/// All zeros.
const ZERO: Self = Self::from_array([0.0; 4]);
/// The identity quaternion. Corresponds to no rotation.
pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
/// All NANs.
pub const NAN: Self = Self::from_array([f32::NAN; 4]);
/// Creates a new rotation quaternion.
///
/// This should generally not be called manually unless you know what you are doing.
/// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
///
/// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
///
/// # Preconditions
///
/// This function does not check if the input is normalized, it is up to the user to
/// provide normalized input or to normalized the resulting quaternion.
#[inline(always)]
#[must_use]
pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
Self { x, y, z, w }
}
/// Creates a rotation quaternion from an array.
///
/// # Preconditions
///
/// This function does not check if the input is normalized, it is up to the user to
/// provide normalized input or to normalized the resulting quaternion.
#[inline]
#[must_use]
pub const fn from_array(a: [f32; 4]) -> Self {
Self::from_xyzw(a[0], a[1], a[2], a[3])
}
/// Creates a new rotation quaternion from a 4D vector.
///
/// # Preconditions
///
/// This function does not check if the input is normalized, it is up to the user to
/// provide normalized input or to normalized the resulting quaternion.
#[inline]
#[must_use]
pub const fn from_vec4(v: Vec4) -> Self {
Self {
x: v.x,
y: v.y,
z: v.z,
w: v.w,
}
}
/// Creates a rotation quaternion from a slice.
///
/// # Preconditions
///
/// This function does not check if the input is normalized, it is up to the user to
/// provide normalized input or to normalized the resulting quaternion.
///
/// # Panics
///
/// Panics if `slice` length is less than 4.
#[inline]
#[must_use]
pub fn from_slice(slice: &[f32]) -> Self {
Self::from_xyzw(slice[0], slice[1], slice[2], slice[3])
}
/// Writes the quaternion to an unaligned slice.
///
/// # Panics
///
/// Panics if `slice` length is less than 4.
#[inline]
pub fn write_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x;
slice[1] = self.y;
slice[2] = self.z;
slice[3] = self.w;
}
/// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
///
/// The axis must be a unit vector.
///
/// # Panics
///
/// Will panic if `axis` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
glam_assert!(axis.is_normalized());
let (s, c) = math::sin_cos(angle * 0.5);
let v = axis * s;
Self::from_xyzw(v.x, v.y, v.z, c)
}
/// Create a quaternion that rotates `v.length()` radians around `v.normalize()`.
///
/// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
#[inline]
#[must_use]
pub fn from_scaled_axis(v: Vec3) -> Self {
let length = v.length();
if length == 0.0 {
Self::IDENTITY
} else {
Self::from_axis_angle(v / length, length)
}
}
/// Creates a quaternion from the `angle` (in radians) around the x axis.
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f32) -> Self {
let (s, c) = math::sin_cos(angle * 0.5);
Self::from_xyzw(s, 0.0, 0.0, c)
}
/// Creates a quaternion from the `angle` (in radians) around the y axis.
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f32) -> Self {
let (s, c) = math::sin_cos(angle * 0.5);
Self::from_xyzw(0.0, s, 0.0, c)
}
/// Creates a quaternion from the `angle` (in radians) around the z axis.
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f32) -> Self {
let (s, c) = math::sin_cos(angle * 0.5);
Self::from_xyzw(0.0, 0.0, s, c)
}
/// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
#[inline]
#[must_use]
pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
Self::from_euler_angles(euler, a, b, c)
}
/// From the columns of a 3x3 rotation matrix.
///
/// Note if the input axes contain scales, shears, or other non-rotation transformations then
/// the output of this function is ill-defined.
///
/// # Panics
///
/// Will panic if any axis is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized());
// Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix`
let (m00, m01, m02) = x_axis.into();
let (m10, m11, m12) = y_axis.into();
let (m20, m21, m22) = z_axis.into();
if m22 <= 0.0 {
// x^2 + y^2 >= z^2 + w^2
let dif10 = m11 - m00;
let omm22 = 1.0 - m22;
if dif10 <= 0.0 {
// x^2 >= y^2
let four_xsq = omm22 - dif10;
let inv4x = 0.5 / math::sqrt(four_xsq);
Self::from_xyzw(
four_xsq * inv4x,
(m01 + m10) * inv4x,
(m02 + m20) * inv4x,
(m12 - m21) * inv4x,
)
} else {
// y^2 >= x^2
let four_ysq = omm22 + dif10;
let inv4y = 0.5 / math::sqrt(four_ysq);
Self::from_xyzw(
(m01 + m10) * inv4y,
four_ysq * inv4y,
(m12 + m21) * inv4y,
(m20 - m02) * inv4y,
)
}
} else {
// z^2 + w^2 >= x^2 + y^2
let sum10 = m11 + m00;
let opm22 = 1.0 + m22;
if sum10 <= 0.0 {
// z^2 >= w^2
let four_zsq = opm22 - sum10;
let inv4z = 0.5 / math::sqrt(four_zsq);
Self::from_xyzw(
(m02 + m20) * inv4z,
(m12 + m21) * inv4z,
four_zsq * inv4z,
(m01 - m10) * inv4z,
)
} else {
// w^2 >= z^2
let four_wsq = opm22 + sum10;
let inv4w = 0.5 / math::sqrt(four_wsq);
Self::from_xyzw(
(m12 - m21) * inv4w,
(m20 - m02) * inv4w,
(m01 - m10) * inv4w,
four_wsq * inv4w,
)
}
}
}
/// Creates a quaternion from a 3x3 rotation matrix.
///
/// Note if the input matrix contain scales, shears, or other non-rotation transformations then
/// the resulting quaternion will be ill-defined.
///
/// # Panics
///
/// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_mat3(mat: &Mat3) -> Self {
Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
}
/// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
///
/// Note if the input matrix contain scales, shears, or other non-rotation transformations then
/// the resulting quaternion will be ill-defined.
///
/// # Panics
///
/// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_mat3a(mat: &Mat3A) -> Self {
Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
}
/// Creates a quaternion from the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix.
///
/// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations
/// then the resulting quaternion will be ill-defined.
///
/// # Panics
///
/// Will panic if any column of the upper 3x3 rotation matrix is not normalized when
/// `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_mat4(mat: &Mat4) -> Self {
Self::from_rotation_axes(
mat.x_axis.truncate(),
mat.y_axis.truncate(),
mat.z_axis.truncate(),
)
}
/// Gets the minimal rotation for transforming `from` to `to`. The rotation is in the
/// plane spanned by the two vectors. Will rotate at most 180 degrees.
///
/// The inputs must be unit vectors.
///
/// `from_rotation_arc(from, to) * from ≈ to`.
///
/// For near-singular cases (from≈to and from≈-to) the current implementation
/// is only accurate to about 0.001 (for `f32`).
///
/// # Panics
///
/// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
#[must_use]
pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
glam_assert!(from.is_normalized());
glam_assert!(to.is_normalized());
const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * f32::EPSILON;
let dot = from.dot(to);
if dot > ONE_MINUS_EPS {
// 0° singularity: from ≈ to
Self::IDENTITY
} else if dot < -ONE_MINUS_EPS {
// 180° singularity: from ≈ -to
use core::f32::consts::PI; // half a turn = 𝛕/2 = 180°
Self::from_axis_angle(from.any_orthonormal_vector(), PI)
} else {
let c = from.cross(to);
Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize()
}
}
/// Gets the minimal rotation for transforming `from` to either `to` or `-to`. This means
/// that the resulting quaternion will rotate `from` so that it is colinear with `to`.
///
/// The rotation is in the plane spanned by the two vectors. Will rotate at most 90
/// degrees.
///
/// The inputs must be unit vectors.
///
/// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
///
/// # Panics
///
/// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
if from.dot(to) < 0.0 {
Self::from_rotation_arc(from, -to)
} else {
Self::from_rotation_arc(from, to)
}
}
/// Gets the minimal rotation for transforming `from` to `to`. The resulting rotation is
/// around the z axis. Will rotate at most 180 degrees.
///
/// The inputs must be unit vectors.
///
/// `from_rotation_arc_2d(from, to) * from ≈ to`.
///
/// For near-singular cases (from≈to and from≈-to) the current implementation
/// is only accurate to about 0.001 (for `f32`).
///
/// # Panics
///
/// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
#[must_use]
pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
glam_assert!(from.is_normalized());
glam_assert!(to.is_normalized());
const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * f32::EPSILON;
let dot = from.dot(to);
if dot > ONE_MINUS_EPSILON {
// 0° singularity: from ≈ to
Self::IDENTITY
} else if dot < -ONE_MINUS_EPSILON {
// 180° singularity: from ≈ -to
const COS_FRAC_PI_2: f32 = 0.0;
const SIN_FRAC_PI_2: f32 = 1.0;
// rotation around z by PI radians
Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2)
} else {
// vector3 cross where z=0
let z = from.x * to.y - to.x * from.y;
let w = 1.0 + dot;
// calculate length with x=0 and y=0 to normalize
let len_rcp = 1.0 / math::sqrt(z * z + w * w);
Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
}
}
/// Returns the rotation axis (normalized) and angle (in radians) of `self`.
#[inline]
#[must_use]
pub fn to_axis_angle(self) -> (Vec3, f32) {
const EPSILON: f32 = 1.0e-8;
let v = Vec3::new(self.x, self.y, self.z);
let length = v.length();
if length >= EPSILON {
let angle = 2.0 * math::atan2(length, self.w);
let axis = v / length;
(axis, angle)
} else {
(Vec3::X, 0.0)
}
}
/// Returns the rotation axis scaled by the rotation in radians.
#[inline]
#[must_use]
pub fn to_scaled_axis(self) -> Vec3 {
let (axis, angle) = self.to_axis_angle();
axis * angle
}
/// Returns the rotation angles for the given euler rotation sequence.
#[inline]
#[must_use]
pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32) {
self.to_euler_angles(order)
}
/// `[x, y, z, w]`
#[inline]
#[must_use]
pub fn to_array(&self) -> [f32; 4] {
[self.x, self.y, self.z, self.w]
}
/// Returns the vector part of the quaternion.
#[inline]
#[must_use]
pub fn xyz(self) -> Vec3 {
Vec3::new(self.x, self.y, self.z)
}
/// Returns the quaternion conjugate of `self`. For a unit quaternion the
/// conjugate is also the inverse.
#[inline]
#[must_use]
pub fn conjugate(self) -> Self {
Self {
x: -self.x,
y: -self.y,
z: -self.z,
w: self.w,
}
}
/// Returns the inverse of a normalized quaternion.
///
/// Typically quaternion inverse returns the conjugate of a normalized quaternion.
/// Because `self` is assumed to already be unit length this method *does not* normalize
/// before returning the conjugate.
///
/// # Panics
///
/// Will panic if `self` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(self) -> Self {
glam_assert!(self.is_normalized());
self.conjugate()
}
/// Computes the dot product of `self` and `rhs`. The dot product is
/// equal to the cosine of the angle between two quaternion rotations.
#[inline]
#[must_use]
pub fn dot(self, rhs: Self) -> f32 {
Vec4::from(self).dot(Vec4::from(rhs))
}
/// Computes the length of `self`.
#[doc(alias = "magnitude")]
#[inline]
#[must_use]
pub fn length(self) -> f32 {
Vec4::from(self).length()
}
/// Computes the squared length of `self`.
///
/// This is generally faster than `length()` as it avoids a square
/// root operation.
#[doc(alias = "magnitude2")]
#[inline]
#[must_use]
pub fn length_squared(self) -> f32 {
Vec4::from(self).length_squared()
}
/// Computes `1.0 / length()`.
///
/// For valid results, `self` must _not_ be of length zero.
#[inline]
#[must_use]
pub fn length_recip(self) -> f32 {
Vec4::from(self).length_recip()
}
/// Returns `self` normalized to length 1.0.
///
/// For valid results, `self` must _not_ be of length zero.
///
/// Panics
///
/// Will panic if `self` is zero length when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn normalize(self) -> Self {
Self::from_vec4(Vec4::from(self).normalize())
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(self) -> bool {
Vec4::from(self).is_finite()
}
/// Returns `true` if any elements are `NAN`.
#[inline]
#[must_use]
pub fn is_nan(self) -> bool {
Vec4::from(self).is_nan()
}
/// Returns whether `self` of length `1.0` or not.
///
/// Uses a precision threshold of `1e-6`.
#[inline]
#[must_use]
pub fn is_normalized(self) -> bool {
Vec4::from(self).is_normalized()
}
#[inline]
#[must_use]
pub fn is_near_identity(self) -> bool {
// Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
let threshold_angle = 0.002_847_144_6;
// Because of floating point precision, we cannot represent very small rotations.
// The closest f32 to 1.0 that is not 1.0 itself yields:
// 0.99999994.acos() * 2.0 = 0.000690533954 rad
//
// An error threshold of 1.e-6 is used by default.
// (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
// (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
//
// We don't really care about the angle value itself, only if it's close to 0.
// This will happen whenever quat.w is close to 1.0.
// If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
// a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
// the shortest path.
let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
positive_w_angle < threshold_angle
}
/// Returns the angle (in radians) for the minimal rotation
/// for transforming this quaternion into another.
///
/// Both quaternions must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn angle_between(self, rhs: Self) -> f32 {
glam_assert!(self.is_normalized() && rhs.is_normalized());
math::acos_approx(math::abs(self.dot(rhs))) * 2.0
}
/// Rotates towards `rhs` up to `max_angle` (in radians).
///
/// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to
/// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative,
/// rotates towards the exact opposite of `rhs`. Will not go past the target.
///
/// Both quaternions must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn rotate_towards(&self, rhs: Self, max_angle: f32) -> Self {
glam_assert!(self.is_normalized() && rhs.is_normalized());
let angle = self.angle_between(rhs);
if angle <= 1e-4 {
return *self;
}
let s = (max_angle / angle).clamp(-1.0, 1.0);
self.slerp(rhs, s)
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two quaternions contain similar elements. It works
/// best when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
}
#[inline(always)]
#[must_use]
fn lerp_impl(self, end: Self, s: f32) -> Self {
(self * (1.0 - s) + end * s).normalize()
}
/// Performs a linear interpolation between `self` and `rhs` based on
/// the value `s`.
///
/// When `s` is `0.0`, the result will be equal to `self`. When `s`
/// is `1.0`, the result will be equal to `rhs`.
///
/// # Panics
///
/// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
#[doc(alias = "mix")]
#[inline]
#[must_use]
pub fn lerp(self, end: Self, s: f32) -> Self {
glam_assert!(self.is_normalized());
glam_assert!(end.is_normalized());
let dot = self.dot(end);
let bias = if dot >= 0.0 { 1.0 } else { -1.0 };
self.lerp_impl(end * bias, s)
}
/// Performs a spherical linear interpolation between `self` and `end`
/// based on the value `s`.
///
/// When `s` is `0.0`, the result will be equal to `self`. When `s`
/// is `1.0`, the result will be equal to `end`.
///
/// # Panics
///
/// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn slerp(self, mut end: Self, s: f32) -> Self {
// http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
glam_assert!(self.is_normalized());
glam_assert!(end.is_normalized());
// Note that a rotation can be represented by two quaternions: `q` and
// `-q`. The slerp path between `q` and `end` will be different from the
// path between `-q` and `end`. One path will take the long way around and
// one will take the short way. In order to correct for this, the `dot`
// product between `self` and `end` should be positive. If the `dot`
// product is negative, slerp between `self` and `-end`.
let mut dot = self.dot(end);
if dot < 0.0 {
end = -end;
dot = -dot;
}
const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON;
if dot > DOT_THRESHOLD {
// if above threshold perform linear interpolation to avoid divide by zero
self.lerp_impl(end, s)
} else {
let theta = math::acos_approx(dot);
let scale1 = math::sin(theta * (1.0 - s));
let scale2 = math::sin(theta * s);
let theta_sin = math::sin(theta);
((self * scale1) + (end * scale2)) * (1.0 / theta_sin)
}
}
/// Multiplies a quaternion and a 3D vector, returning the rotated vector.
///
/// # Panics
///
/// Will panic if `self` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
glam_assert!(self.is_normalized());
let w = self.w;
let b = Vec3::new(self.x, self.y, self.z);
let b2 = b.dot(b);
rhs.mul(w * w - b2)
.add(b.mul(rhs.dot(b) * 2.0))
.add(b.cross(rhs).mul(w * 2.0))
}
/// Multiplies two quaternions. If they each represent a rotation, the result will
/// represent the combined rotation.
///
/// Note that due to floating point rounding the result may not be perfectly normalized.
///
/// # Panics
///
/// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn mul_quat(self, rhs: Self) -> Self {
let (x0, y0, z0, w0) = self.into();
let (x1, y1, z1, w1) = rhs.into();
Self::from_xyzw(
w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1,
w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1,
w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1,
w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1,
)
}
/// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
///
/// Note if the input affine matrix contain scales, shears, or other non-rotation
/// transformations then the resulting quaternion will be ill-defined.
///
/// # Panics
///
/// Will panic if any input affine matrix column is not normalized when `glam_assert` is
/// enabled.
#[inline]
#[must_use]
pub fn from_affine3(a: &crate::Affine3A) -> Self {
#[allow(clippy::useless_conversion)]
Self::from_rotation_axes(
a.matrix3.x_axis.into(),
a.matrix3.y_axis.into(),
a.matrix3.z_axis.into(),
)
}
/// Multiplies a quaternion and a 3D vector, returning the rotated vector.
#[inline]
#[must_use]
pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
self.mul_vec3(rhs.into()).into()
}
#[inline]
#[must_use]
pub fn as_dquat(self) -> DQuat {
DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
}
}
impl fmt::Debug for Quat {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple(stringify!(Quat))
.field(&self.x)
.field(&self.y)
.field(&self.z)
.field(&self.w)
.finish()
}
}
impl fmt::Display for Quat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}, {:.*}]",
p, self.x, p, self.y, p, self.z, p, self.w
)
} else {
write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
}
}
}
impl Add<Quat> for Quat {
type Output = Self;
/// Adds two quaternions.
///
/// The sum is not guaranteed to be normalized.
///
/// Note that addition is not the same as combining the rotations represented by the
/// two quaternions! That corresponds to multiplication.
#[inline]
fn add(self, rhs: Self) -> Self {
Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
}
}
impl Sub<Quat> for Quat {
type Output = Self;
/// Subtracts the `rhs` quaternion from `self`.
///
/// The difference is not guaranteed to be normalized.
#[inline]
fn sub(self, rhs: Self) -> Self {
Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
}
}
impl Mul<f32> for Quat {
type Output = Self;
/// Multiplies a quaternion by a scalar value.
///
/// The product is not guaranteed to be normalized.
#[inline]
fn mul(self, rhs: f32) -> Self {
Self::from_vec4(Vec4::from(self) * rhs)
}
}
impl Div<f32> for Quat {
type Output = Self;
/// Divides a quaternion by a scalar value.
/// The quotient is not guaranteed to be normalized.
#[inline]
fn div(self, rhs: f32) -> Self {
Self::from_vec4(Vec4::from(self) / rhs)
}
}
impl Mul<Quat> for Quat {
type Output = Self;
/// Multiplies two quaternions. If they each represent a rotation, the result will
/// represent the combined rotation.
///
/// Note that due to floating point rounding the result may not be perfectly
/// normalized.
///
/// # Panics
///
/// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
#[inline]
fn mul(self, rhs: Self) -> Self {
self.mul_quat(rhs)
}
}
impl MulAssign<Quat> for Quat {
/// Multiplies two quaternions. If they each represent a rotation, the result will
/// represent the combined rotation.
///
/// Note that due to floating point rounding the result may not be perfectly
/// normalized.
///
/// # Panics
///
/// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_quat(rhs);
}
}
impl Mul<Vec3> for Quat {
type Output = Vec3;
/// Multiplies a quaternion and a 3D vector, returning the rotated vector.
///
/// # Panics
///
/// Will panic if `self` is not normalized when `glam_assert` is enabled.
#[inline]
fn mul(self, rhs: Vec3) -> Self::Output {
self.mul_vec3(rhs)
}
}
impl Neg for Quat {
type Output = Self;
#[inline]
fn neg(self) -> Self {
self * -1.0
}
}
impl Default for Quat {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl PartialEq for Quat {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
Vec4::from(*self).eq(&Vec4::from(*rhs))
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsRef<[f32; 4]> for Quat {
#[inline]
fn as_ref(&self) -> &[f32; 4] {
unsafe { &*(self as *const Self as *const [f32; 4]) }
}
}
impl Sum<Self> for Quat {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Quat {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Quat {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Quat {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl Mul<Vec3A> for Quat {
type Output = Vec3A;
#[inline]
fn mul(self, rhs: Vec3A) -> Self::Output {
self.mul_vec3a(rhs)
}
}
impl From<Quat> for Vec4 {
#[inline]
fn from(q: Quat) -> Self {
Self::new(q.x, q.y, q.z, q.w)
}
}
impl From<Quat> for (f32, f32, f32, f32) {
#[inline]
fn from(q: Quat) -> Self {
(q.x, q.y, q.z, q.w)
}
}
impl From<Quat> for [f32; 4] {
#[inline]
fn from(q: Quat) -> Self {
[q.x, q.y, q.z, q.w]
}
}

1951
vendor/glam/src/f32/scalar/vec3a.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1999
vendor/glam/src/f32/scalar/vec4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

6
vendor/glam/src/f32/sse2.rs vendored Normal file
View File

@@ -0,0 +1,6 @@
pub mod mat2;
pub mod mat3a;
pub mod mat4;
pub mod quat;
pub mod vec3a;
pub mod vec4;

614
vendor/glam/src/f32/sse2/mat2.rs vendored Normal file
View File

@@ -0,0 +1,614 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
#[repr(C)]
union UnionCast {
a: [f32; 4],
v: Mat2,
}
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
Mat2::from_cols(x_axis, y_axis)
}
/// A 2x2 column major matrix.
///
/// SIMD vector types are used for storage on supported platforms.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Mat2(pub(crate) __m128);
impl Mat2 {
/// A 2x2 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
/// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
unsafe {
UnionCast {
a: [m00, m01, m10, m11],
}
.v
}
}
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
unsafe {
UnionCast {
a: [x_axis.x, x_axis.y, y_axis.x, y_axis.y],
}
.v
}
}
/// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f32; 4]) -> Self {
Self::new(m[0], m[1], m[2], m[3])
}
/// Creates a `[f32; 4]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f32; 4] {
unsafe { *(self as *const Self as *const [f32; 4]) }
}
/// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
}
/// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
}
/// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: Vec2) -> Self {
Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
}
/// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
}
/// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos, sin, -sin, cos)
}
/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3(m: Mat3) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3a(m: Mat3A) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 2x2 matrix from the first 4 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f32]) -> Self {
Self::new(slice[0], slice[1], slice[2], slice[3])
}
/// Writes the columns of `self` to the first 4 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.y_axis.x;
slice[3] = self.y_axis.y;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> Vec2 {
match index {
0 => self.x_axis,
1 => self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> Vec2 {
match index {
0 => Vec2::new(self.x_axis.x, self.y_axis.x),
1 => Vec2::new(self.x_axis.y, self.y_axis.y),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
Self(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_00) })
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f32 {
unsafe {
let abcd = self.0;
let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
let prod = _mm_mul_ps(abcd, dcba);
let det = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
_mm_cvtss_f32(det)
}
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
unsafe {
const SIGN: __m128 = crate::sse2::m128_from_f32x4([1.0, -1.0, -1.0, 1.0]);
let abcd = self.0;
let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
let prod = _mm_mul_ps(abcd, dcba);
let sub = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
let det = _mm_shuffle_ps(sub, sub, 0b00_00_00_00);
let tmp = _mm_div_ps(SIGN, det);
glam_assert!(Mat2(tmp).is_finite());
let dbca = _mm_shuffle_ps(abcd, abcd, 0b00_10_01_11);
Self(_mm_mul_ps(dbca, tmp))
}
}
/// Transforms a 2D vector.
#[inline]
#[must_use]
pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
unsafe {
use crate::Align16;
use core::mem::MaybeUninit;
let abcd = self.0;
let xxyy = _mm_set_ps(rhs.y, rhs.y, rhs.x, rhs.x);
let axbxcydy = _mm_mul_ps(abcd, xxyy);
let cydyaxbx = _mm_shuffle_ps(axbxcydy, axbxcydy, 0b01_00_11_10);
let result = _mm_add_ps(axbxcydy, cydyaxbx);
let mut out: MaybeUninit<Align16<Vec2>> = MaybeUninit::uninit();
_mm_store_ps(out.as_mut_ptr().cast(), result);
out.assume_init().0
}
}
/// Multiplies two 2x2 matrices.
#[inline]
#[must_use]
pub fn mul_mat2(&self, rhs: &Self) -> Self {
unsafe {
let abcd = self.0;
let rhs = rhs.0;
let xxyy0 = _mm_shuffle_ps(rhs, rhs, 0b01_01_00_00);
let xxyy1 = _mm_shuffle_ps(rhs, rhs, 0b11_11_10_10);
let axbxcydy0 = _mm_mul_ps(abcd, xxyy0);
let axbxcydy1 = _mm_mul_ps(abcd, xxyy1);
let cydyaxbx0 = _mm_shuffle_ps(axbxcydy0, axbxcydy0, 0b01_00_11_10);
let cydyaxbx1 = _mm_shuffle_ps(axbxcydy1, axbxcydy1, 0b01_00_11_10);
let result0 = _mm_add_ps(axbxcydy0, cydyaxbx0);
let result1 = _mm_add_ps(axbxcydy1, cydyaxbx1);
Self(_mm_shuffle_ps(result0, result1, 0b01_00_01_00))
}
}
/// Adds two 2x2 matrices.
#[inline]
#[must_use]
pub fn add_mat2(&self, rhs: &Self) -> Self {
Self(unsafe { _mm_add_ps(self.0, rhs.0) })
}
/// Subtracts two 2x2 matrices.
#[inline]
#[must_use]
pub fn sub_mat2(&self, rhs: &Self) -> Self {
Self(unsafe { _mm_sub_ps(self.0, rhs.0) })
}
/// Multiplies a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f32) -> Self {
Self(unsafe { _mm_mul_ps(self.0, _mm_set_ps1(rhs)) })
}
/// Divides a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f32) -> Self {
Self(unsafe { _mm_div_ps(self.0, _mm_set_ps1(rhs)) })
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
}
#[inline]
pub fn as_dmat2(&self) -> DMat2 {
DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
}
}
impl Default for Mat2 {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat2(&rhs)
}
}
impl AddAssign<Mat2> for Mat2 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat2(&rhs);
}
}
impl Sub<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat2(&rhs)
}
}
impl SubAssign<Mat2> for Mat2 {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat2(&rhs);
}
}
impl Neg for Mat2 {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self(unsafe { _mm_xor_ps(self.0, _mm_set1_ps(-0.0)) })
}
}
impl Mul<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat2(&rhs)
}
}
impl MulAssign<Mat2> for Mat2 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat2(&rhs);
}
}
impl Mul<Vec2> for Mat2 {
type Output = Vec2;
#[inline]
fn mul(self, rhs: Vec2) -> Self::Output {
self.mul_vec2(rhs)
}
}
impl Mul<Mat2> for f32 {
type Output = Mat2;
#[inline]
fn mul(self, rhs: Mat2) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f32> for Mat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f32> for Mat2 {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = self.mul_scalar(rhs);
}
}
impl Div<Mat2> for f32 {
type Output = Mat2;
#[inline]
fn div(self, rhs: Mat2) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f32> for Mat2 {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f32> for Mat2 {
#[inline]
fn div_assign(&mut self, rhs: f32) {
*self = self.div_scalar(rhs);
}
}
impl Sum<Self> for Mat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Mat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Mat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Mat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for Mat2 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsRef<[f32; 4]> for Mat2 {
#[inline]
fn as_ref(&self) -> &[f32; 4] {
unsafe { &*(self as *const Self as *const [f32; 4]) }
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsMut<[f32; 4]> for Mat2 {
#[inline]
fn as_mut(&mut self) -> &mut [f32; 4] {
unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
}
}
impl core::ops::Deref for Mat2 {
type Target = crate::deref::Cols2<Vec2>;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Self as *const Self::Target) }
}
}
impl core::ops::DerefMut for Mat2 {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self as *mut Self as *mut Self::Target) }
}
}
impl fmt::Debug for Mat2 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(Mat2))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.finish()
}
}
impl fmt::Display for Mat2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
} else {
write!(f, "[{}, {}]", self.x_axis, self.y_axis)
}
}
}

931
vendor/glam/src/f32/sse2/mat3a.rs vendored Normal file
View File

@@ -0,0 +1,931 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{
euler::{FromEuler, ToEuler},
f32::math,
swizzles::*,
DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A,
};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
Mat3A::from_cols(x_axis, y_axis, z_axis)
}
/// A 3x3 column major matrix.
///
/// This 3x3 matrix type features convenience methods for creating and using linear and
/// affine transformations. If you are primarily dealing with 2D affine transformations the
/// [`Affine2`](crate::Affine2) type is much faster and more space efficient than
/// using a 3x3 matrix.
///
/// Linear transformations including 3D rotation and scale can be created using methods
/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
/// [`Self::from_rotation_z()`].
///
/// The resulting matrices can be use to transform 3D vectors using regular vector
/// multiplication.
///
/// Affine transformations including 2D translation, rotation and scale can be created
/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
///
/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
/// are provided for performing affine transforms on 2D vectors and points. These multiply
/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
/// vectors respectively. These methods assume that `Self` contains a valid affine
/// transform.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Mat3A {
pub x_axis: Vec3A,
pub y_axis: Vec3A,
pub z_axis: Vec3A,
}
impl Mat3A {
/// A 3x3 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO);
/// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(
m00: f32,
m01: f32,
m02: f32,
m10: f32,
m11: f32,
m12: f32,
m20: f32,
m21: f32,
m22: f32,
) -> Self {
Self {
x_axis: Vec3A::new(m00, m01, m02),
y_axis: Vec3A::new(m10, m11, m12),
z_axis: Vec3A::new(m20, m21, m22),
}
}
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
Self {
x_axis,
y_axis,
z_axis,
}
}
/// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f32; 9]) -> Self {
Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
}
/// Creates a `[f32; 9]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f32; 9] {
let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array();
[
x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y,
z_axis_z,
]
}
/// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
Self::from_cols(
Vec3A::from_array(m[0]),
Vec3A::from_array(m[1]),
Vec3A::from_array(m[2]),
)
}
/// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
[
self.x_axis.to_array(),
self.y_axis.to_array(),
self.z_axis.to_array(),
]
}
/// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: Vec3) -> Self {
Self::new(
diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
)
}
/// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
#[inline]
#[must_use]
pub fn from_mat4(m: Mat4) -> Self {
Self::from_cols(
Vec3A::from_vec4(m.x_axis),
Vec3A::from_vec4(m.y_axis),
Vec3A::from_vec4(m.z_axis),
)
}
/// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 3.
#[inline]
#[must_use]
pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(0, 1) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(0, 2) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(0, 3) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(1, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(1, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(1, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(1, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(2, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(2, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(2, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(2, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(3, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
),
(3, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
),
(3, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
),
(3, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
),
_ => panic!("index out of bounds"),
}
}
/// Creates a 3D rotation matrix from the given quaternion.
///
/// # Panics
///
/// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_quat(rotation: Quat) -> Self {
glam_assert!(rotation.is_normalized());
let x2 = rotation.x + rotation.x;
let y2 = rotation.y + rotation.y;
let z2 = rotation.z + rotation.z;
let xx = rotation.x * x2;
let xy = rotation.x * y2;
let xz = rotation.x * z2;
let yy = rotation.y * y2;
let yz = rotation.y * z2;
let zz = rotation.z * z2;
let wx = rotation.w * x2;
let wy = rotation.w * y2;
let wz = rotation.w * z2;
Self::from_cols(
Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy),
Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx),
Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
)
}
/// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
/// radians).
///
/// # Panics
///
/// Will panic if `axis` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
glam_assert!(axis.is_normalized());
let (sin, cos) = math::sin_cos(angle);
let (xsin, ysin, zsin) = axis.mul(sin).into();
let (x, y, z) = axis.into();
let (x2, y2, z2) = axis.mul(axis).into();
let omc = 1.0 - cos;
let xyomc = x * y * omc;
let xzomc = x * z * omc;
let yzomc = y * z * omc;
Self::from_cols(
Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
)
}
/// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
/// radians).
#[inline]
#[must_use]
pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
Self::from_euler_angles(order, a, b, c)
}
/// Extract Euler angles with the given Euler rotation order.
///
/// Note if the input matrix contains scales, shears, or other non-rotation transformations then
/// the resulting Euler angles will be ill-defined.
///
/// # Panics
///
/// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
glam_assert!(
self.x_axis.is_normalized()
&& self.y_axis.is_normalized()
&& self.z_axis.is_normalized()
);
self.to_euler_angles(order)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::X,
Vec3A::new(0.0, cosa, sina),
Vec3A::new(0.0, -sina, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cosa, 0.0, -sina),
Vec3A::Y,
Vec3A::new(sina, 0.0, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cosa, sina, 0.0),
Vec3A::new(-sina, cosa, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_translation(translation: Vec2) -> Self {
Self::from_cols(
Vec3A::X,
Vec3A::Y,
Vec3A::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given 2D rotation `angle` (in
/// radians).
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cos, sin, 0.0),
Vec3A::new(-sin, cos, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
/// radians) and `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
Vec3A::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
///
/// # Panics
///
/// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_scale(scale: Vec2) -> Self {
// Do not panic as long as any component is non-zero
glam_assert!(scale.cmpne(Vec2::ZERO).any());
Self::from_cols(
Vec3A::new(scale.x, 0.0, 0.0),
Vec3A::new(0.0, scale.y, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2x2 matrix.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
pub fn from_mat2(m: Mat2) -> Self {
Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z)
}
/// Creates a 3x3 matrix from the first 9 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f32]) -> Self {
Self::new(
slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
slice[8],
)
}
/// Writes the columns of `self` to the first 9 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.x_axis.z;
slice[3] = self.y_axis.x;
slice[4] = self.y_axis.y;
slice[5] = self.y_axis.z;
slice[6] = self.z_axis.x;
slice[7] = self.z_axis.y;
slice[8] = self.z_axis.z;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> Vec3A {
match index {
0 => self.x_axis,
1 => self.y_axis,
2 => self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut Vec3A {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
2 => &mut self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> Vec3A {
match index {
0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
unsafe {
let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
Self {
x_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b00_00_10_00)),
y_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b01_01_11_01)),
z_axis: Vec3A(_mm_shuffle_ps(tmp1, self.z_axis.0, 0b10_10_10_00)),
}
}
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f32 {
self.z_axis.dot(self.x_axis.cross(self.y_axis))
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let tmp0 = self.y_axis.cross(self.z_axis);
let tmp1 = self.z_axis.cross(self.x_axis);
let tmp2 = self.x_axis.cross(self.y_axis);
let det = self.z_axis.dot(tmp2);
glam_assert!(det != 0.0);
let inv_det = Vec3A::splat(det.recip());
Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
}
/// Transforms the given 2D vector as a point.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
}
/// Rotates the given 2D vector.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
}
/// Transforms a 3D vector.
#[inline]
#[must_use]
pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
self.mul_vec3a(rhs.into()).into()
}
/// Transforms a [`Vec3A`].
#[inline]
#[must_use]
pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
let mut res = self.x_axis.mul(rhs.xxx());
res = res.add(self.y_axis.mul(rhs.yyy()));
res = res.add(self.z_axis.mul(rhs.zzz()));
res
}
/// Multiplies two 3x3 matrices.
#[inline]
#[must_use]
pub fn mul_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.mul(rhs.x_axis),
self.mul(rhs.y_axis),
self.mul(rhs.z_axis),
)
}
/// Adds two 3x3 matrices.
#[inline]
#[must_use]
pub fn add_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.add(rhs.x_axis),
self.y_axis.add(rhs.y_axis),
self.z_axis.add(rhs.z_axis),
)
}
/// Subtracts two 3x3 matrices.
#[inline]
#[must_use]
pub fn sub_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.sub(rhs.x_axis),
self.y_axis.sub(rhs.y_axis),
self.z_axis.sub(rhs.z_axis),
)
}
/// Multiplies a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f32) -> Self {
Self::from_cols(
self.x_axis.mul(rhs),
self.y_axis.mul(rhs),
self.z_axis.mul(rhs),
)
}
/// Divides a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f32) -> Self {
let rhs = Vec3A::splat(rhs);
Self::from_cols(
self.x_axis.div(rhs),
self.y_axis.div(rhs),
self.z_axis.div(rhs),
)
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
&& self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
}
#[inline]
pub fn as_dmat3(&self) -> DMat3 {
DMat3::from_cols(
self.x_axis.as_dvec3(),
self.y_axis.as_dvec3(),
self.z_axis.as_dvec3(),
)
}
}
impl Default for Mat3A {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat3(&rhs)
}
}
impl AddAssign<Mat3A> for Mat3A {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat3(&rhs);
}
}
impl Sub<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat3(&rhs)
}
}
impl SubAssign<Mat3A> for Mat3A {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat3(&rhs);
}
}
impl Neg for Mat3A {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
}
}
impl Mul<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat3(&rhs)
}
}
impl MulAssign<Mat3A> for Mat3A {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat3(&rhs);
}
}
impl Mul<Vec3A> for Mat3A {
type Output = Vec3A;
#[inline]
fn mul(self, rhs: Vec3A) -> Self::Output {
self.mul_vec3a(rhs)
}
}
impl Mul<Mat3A> for f32 {
type Output = Mat3A;
#[inline]
fn mul(self, rhs: Mat3A) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f32> for Mat3A {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f32> for Mat3A {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = self.mul_scalar(rhs);
}
}
impl Div<Mat3A> for f32 {
type Output = Mat3A;
#[inline]
fn div(self, rhs: Mat3A) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f32> for Mat3A {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f32> for Mat3A {
#[inline]
fn div_assign(&mut self, rhs: f32) {
*self = self.div_scalar(rhs);
}
}
impl Mul<Vec3> for Mat3A {
type Output = Vec3;
#[inline]
fn mul(self, rhs: Vec3) -> Vec3 {
self.mul_vec3a(rhs.into()).into()
}
}
impl From<Mat3> for Mat3A {
#[inline]
fn from(m: Mat3) -> Self {
Self {
x_axis: m.x_axis.into(),
y_axis: m.y_axis.into(),
z_axis: m.z_axis.into(),
}
}
}
impl Sum<Self> for Mat3A {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Mat3A {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Mat3A {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Mat3A {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for Mat3A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
}
}
impl fmt::Debug for Mat3A {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(Mat3A))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.field("z_axis", &self.z_axis)
.finish()
}
}
impl fmt::Display for Mat3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}]",
p, self.x_axis, p, self.y_axis, p, self.z_axis
)
} else {
write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
}
}
}

1545
vendor/glam/src/f32/sse2/mat4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1043
vendor/glam/src/f32/sse2/quat.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1925
vendor/glam/src/f32/sse2/vec3a.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1876
vendor/glam/src/f32/sse2/vec4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1835
vendor/glam/src/f32/vec2.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1923
vendor/glam/src/f32/vec3.rs vendored Normal file

File diff suppressed because it is too large Load Diff

6
vendor/glam/src/f32/wasm32.rs vendored Normal file
View File

@@ -0,0 +1,6 @@
pub mod mat2;
pub mod mat3a;
pub mod mat4;
pub mod quat;
pub mod vec3a;
pub mod vec4;

588
vendor/glam/src/f32/wasm32/mat2.rs vendored Normal file
View File

@@ -0,0 +1,588 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use core::arch::wasm32::*;
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
Mat2::from_cols(x_axis, y_axis)
}
/// A 2x2 column major matrix.
///
/// SIMD vector types are used for storage on supported platforms.
///
/// This type is 16 byte aligned.
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Mat2(pub(crate) v128);
impl Mat2 {
/// A 2x2 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
/// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
Self(f32x4(m00, m01, m10, m11))
}
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
Self(f32x4(x_axis.x, x_axis.y, y_axis.x, y_axis.y))
}
/// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f32; 4]) -> Self {
Self::new(m[0], m[1], m[2], m[3])
}
/// Creates a `[f32; 4]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f32; 4] {
unsafe { *(self as *const Self as *const [f32; 4]) }
}
/// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
}
/// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
}
/// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: Vec2) -> Self {
Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
}
/// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
}
/// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos, sin, -sin, cos)
}
/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3(m: Mat3) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3a(m: Mat3A) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 2x2 matrix from the first 4 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f32]) -> Self {
Self::new(slice[0], slice[1], slice[2], slice[3])
}
/// Writes the columns of `self` to the first 4 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.y_axis.x;
slice[3] = self.y_axis.y;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> Vec2 {
match index {
0 => self.x_axis,
1 => self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> Vec2 {
match index {
0 => Vec2::new(self.x_axis.x, self.y_axis.x),
1 => Vec2::new(self.x_axis.y, self.y_axis.y),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
Self(i32x4_shuffle::<0, 2, 5, 7>(self.0, self.0))
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f32 {
let abcd = self.0;
let dcba = i32x4_shuffle::<3, 2, 5, 4>(abcd, abcd);
let prod = f32x4_mul(abcd, dcba);
let det = f32x4_sub(prod, i32x4_shuffle::<1, 1, 5, 5>(prod, prod));
f32x4_extract_lane::<0>(det)
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
const SIGN: v128 = crate::wasm32::v128_from_f32x4([1.0, -1.0, -1.0, 1.0]);
let abcd = self.0;
let dcba = i32x4_shuffle::<3, 2, 5, 4>(abcd, abcd);
let prod = f32x4_mul(abcd, dcba);
let sub = f32x4_sub(prod, i32x4_shuffle::<1, 1, 5, 5>(prod, prod));
let det = i32x4_shuffle::<0, 0, 4, 4>(sub, sub);
let tmp = f32x4_div(SIGN, det);
glam_assert!(Mat2(tmp).is_finite());
let dbca = i32x4_shuffle::<3, 1, 6, 4>(abcd, abcd);
Self(f32x4_mul(dbca, tmp))
}
/// Transforms a 2D vector.
#[inline]
#[must_use]
pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
use core::mem::MaybeUninit;
let abcd = self.0;
let xxyy = f32x4(rhs.x, rhs.x, rhs.y, rhs.y);
let axbxcydy = f32x4_mul(abcd, xxyy);
let cydyaxbx = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy, axbxcydy);
let result = f32x4_add(axbxcydy, cydyaxbx);
let mut out: MaybeUninit<v128> = MaybeUninit::uninit();
unsafe {
v128_store(out.as_mut_ptr(), result);
*(&out.assume_init() as *const v128 as *const Vec2)
}
}
/// Multiplies two 2x2 matrices.
#[inline]
#[must_use]
pub fn mul_mat2(&self, rhs: &Self) -> Self {
let abcd = self.0;
let rhs = rhs.0;
let xxyy0 = i32x4_shuffle::<0, 0, 5, 5>(rhs, rhs);
let xxyy1 = i32x4_shuffle::<2, 2, 7, 7>(rhs, rhs);
let axbxcydy0 = f32x4_mul(abcd, xxyy0);
let axbxcydy1 = f32x4_mul(abcd, xxyy1);
let cydyaxbx0 = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy0, axbxcydy0);
let cydyaxbx1 = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy1, axbxcydy1);
let result0 = f32x4_add(axbxcydy0, cydyaxbx0);
let result1 = f32x4_add(axbxcydy1, cydyaxbx1);
Self(i32x4_shuffle::<0, 1, 4, 5>(result0, result1))
}
/// Adds two 2x2 matrices.
#[inline]
#[must_use]
pub fn add_mat2(&self, rhs: &Self) -> Self {
Self(f32x4_add(self.0, rhs.0))
}
/// Subtracts two 2x2 matrices.
#[inline]
#[must_use]
pub fn sub_mat2(&self, rhs: &Self) -> Self {
Self(f32x4_sub(self.0, rhs.0))
}
/// Multiplies a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f32) -> Self {
Self(f32x4_mul(self.0, f32x4_splat(rhs)))
}
/// Divides a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f32) -> Self {
Self(f32x4_div(self.0, f32x4_splat(rhs)))
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
}
#[inline]
pub fn as_dmat2(&self) -> DMat2 {
DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
}
}
impl Default for Mat2 {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat2(&rhs)
}
}
impl AddAssign<Mat2> for Mat2 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat2(&rhs);
}
}
impl Sub<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat2(&rhs)
}
}
impl SubAssign<Mat2> for Mat2 {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat2(&rhs);
}
}
impl Neg for Mat2 {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self(f32x4_neg(self.0))
}
}
impl Mul<Mat2> for Mat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat2(&rhs)
}
}
impl MulAssign<Mat2> for Mat2 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat2(&rhs);
}
}
impl Mul<Vec2> for Mat2 {
type Output = Vec2;
#[inline]
fn mul(self, rhs: Vec2) -> Self::Output {
self.mul_vec2(rhs)
}
}
impl Mul<Mat2> for f32 {
type Output = Mat2;
#[inline]
fn mul(self, rhs: Mat2) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f32> for Mat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f32> for Mat2 {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = self.mul_scalar(rhs);
}
}
impl Div<Mat2> for f32 {
type Output = Mat2;
#[inline]
fn div(self, rhs: Mat2) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f32> for Mat2 {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f32> for Mat2 {
#[inline]
fn div_assign(&mut self, rhs: f32) {
*self = self.div_scalar(rhs);
}
}
impl Sum<Self> for Mat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Mat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Mat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Mat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for Mat2 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsRef<[f32; 4]> for Mat2 {
#[inline]
fn as_ref(&self) -> &[f32; 4] {
unsafe { &*(self as *const Self as *const [f32; 4]) }
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsMut<[f32; 4]> for Mat2 {
#[inline]
fn as_mut(&mut self) -> &mut [f32; 4] {
unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
}
}
impl core::ops::Deref for Mat2 {
type Target = crate::deref::Cols2<Vec2>;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Self as *const Self::Target) }
}
}
impl core::ops::DerefMut for Mat2 {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self as *mut Self as *mut Self::Target) }
}
}
impl fmt::Debug for Mat2 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(Mat2))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.finish()
}
}
impl fmt::Display for Mat2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
} else {
write!(f, "[{}, {}]", self.x_axis, self.y_axis)
}
}
}

926
vendor/glam/src/f32/wasm32/mat3a.rs vendored Normal file
View File

@@ -0,0 +1,926 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{
euler::{FromEuler, ToEuler},
f32::math,
swizzles::*,
DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A,
};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use core::arch::wasm32::*;
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
Mat3A::from_cols(x_axis, y_axis, z_axis)
}
/// A 3x3 column major matrix.
///
/// This 3x3 matrix type features convenience methods for creating and using linear and
/// affine transformations. If you are primarily dealing with 2D affine transformations the
/// [`Affine2`](crate::Affine2) type is much faster and more space efficient than
/// using a 3x3 matrix.
///
/// Linear transformations including 3D rotation and scale can be created using methods
/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
/// [`Self::from_rotation_z()`].
///
/// The resulting matrices can be use to transform 3D vectors using regular vector
/// multiplication.
///
/// Affine transformations including 2D translation, rotation and scale can be created
/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
///
/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
/// are provided for performing affine transforms on 2D vectors and points. These multiply
/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
/// vectors respectively. These methods assume that `Self` contains a valid affine
/// transform.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Mat3A {
pub x_axis: Vec3A,
pub y_axis: Vec3A,
pub z_axis: Vec3A,
}
impl Mat3A {
/// A 3x3 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO);
/// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(
m00: f32,
m01: f32,
m02: f32,
m10: f32,
m11: f32,
m12: f32,
m20: f32,
m21: f32,
m22: f32,
) -> Self {
Self {
x_axis: Vec3A::new(m00, m01, m02),
y_axis: Vec3A::new(m10, m11, m12),
z_axis: Vec3A::new(m20, m21, m22),
}
}
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
Self {
x_axis,
y_axis,
z_axis,
}
}
/// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f32; 9]) -> Self {
Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
}
/// Creates a `[f32; 9]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f32; 9] {
let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array();
[
x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y,
z_axis_z,
]
}
/// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
Self::from_cols(
Vec3A::from_array(m[0]),
Vec3A::from_array(m[1]),
Vec3A::from_array(m[2]),
)
}
/// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
[
self.x_axis.to_array(),
self.y_axis.to_array(),
self.z_axis.to_array(),
]
}
/// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: Vec3) -> Self {
Self::new(
diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
)
}
/// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
#[inline]
#[must_use]
pub fn from_mat4(m: Mat4) -> Self {
Self::from_cols(
Vec3A::from_vec4(m.x_axis),
Vec3A::from_vec4(m.y_axis),
Vec3A::from_vec4(m.z_axis),
)
}
/// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 3.
#[inline]
#[must_use]
pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(0, 1) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(0, 2) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(0, 3) => Self::from_cols(
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(1, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(1, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(1, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(1, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(2, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.w_axis.yzww()),
),
(2, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.w_axis.xzww()),
),
(2, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.w_axis.xyww()),
),
(2, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.w_axis.xyzw()),
),
(3, 0) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.yzww()),
Vec3A::from_vec4(m.y_axis.yzww()),
Vec3A::from_vec4(m.z_axis.yzww()),
),
(3, 1) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xzww()),
Vec3A::from_vec4(m.y_axis.xzww()),
Vec3A::from_vec4(m.z_axis.xzww()),
),
(3, 2) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyww()),
Vec3A::from_vec4(m.y_axis.xyww()),
Vec3A::from_vec4(m.z_axis.xyww()),
),
(3, 3) => Self::from_cols(
Vec3A::from_vec4(m.x_axis.xyzw()),
Vec3A::from_vec4(m.y_axis.xyzw()),
Vec3A::from_vec4(m.z_axis.xyzw()),
),
_ => panic!("index out of bounds"),
}
}
/// Creates a 3D rotation matrix from the given quaternion.
///
/// # Panics
///
/// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_quat(rotation: Quat) -> Self {
glam_assert!(rotation.is_normalized());
let x2 = rotation.x + rotation.x;
let y2 = rotation.y + rotation.y;
let z2 = rotation.z + rotation.z;
let xx = rotation.x * x2;
let xy = rotation.x * y2;
let xz = rotation.x * z2;
let yy = rotation.y * y2;
let yz = rotation.y * z2;
let zz = rotation.z * z2;
let wx = rotation.w * x2;
let wy = rotation.w * y2;
let wz = rotation.w * z2;
Self::from_cols(
Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy),
Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx),
Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
)
}
/// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
/// radians).
///
/// # Panics
///
/// Will panic if `axis` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
glam_assert!(axis.is_normalized());
let (sin, cos) = math::sin_cos(angle);
let (xsin, ysin, zsin) = axis.mul(sin).into();
let (x, y, z) = axis.into();
let (x2, y2, z2) = axis.mul(axis).into();
let omc = 1.0 - cos;
let xyomc = x * y * omc;
let xzomc = x * z * omc;
let yzomc = y * z * omc;
Self::from_cols(
Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
)
}
/// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
/// radians).
#[inline]
#[must_use]
pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
Self::from_euler_angles(order, a, b, c)
}
/// Extract Euler angles with the given Euler rotation order.
///
/// Note if the input matrix contains scales, shears, or other non-rotation transformations then
/// the resulting Euler angles will be ill-defined.
///
/// # Panics
///
/// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
glam_assert!(
self.x_axis.is_normalized()
&& self.y_axis.is_normalized()
&& self.z_axis.is_normalized()
);
self.to_euler_angles(order)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::X,
Vec3A::new(0.0, cosa, sina),
Vec3A::new(0.0, -sina, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cosa, 0.0, -sina),
Vec3A::Y,
Vec3A::new(sina, 0.0, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f32) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cosa, sina, 0.0),
Vec3A::new(-sina, cosa, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_translation(translation: Vec2) -> Self {
Self::from_cols(
Vec3A::X,
Vec3A::Y,
Vec3A::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given 2D rotation `angle` (in
/// radians).
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_angle(angle: f32) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cos, sin, 0.0),
Vec3A::new(-sin, cos, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
/// radians) and `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
Vec3A::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
///
/// # Panics
///
/// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_scale(scale: Vec2) -> Self {
// Do not panic as long as any component is non-zero
glam_assert!(scale.cmpne(Vec2::ZERO).any());
Self::from_cols(
Vec3A::new(scale.x, 0.0, 0.0),
Vec3A::new(0.0, scale.y, 0.0),
Vec3A::Z,
)
}
/// Creates an affine transformation matrix from the given 2x2 matrix.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
pub fn from_mat2(m: Mat2) -> Self {
Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z)
}
/// Creates a 3x3 matrix from the first 9 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f32]) -> Self {
Self::new(
slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
slice[8],
)
}
/// Writes the columns of `self` to the first 9 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f32]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.x_axis.z;
slice[3] = self.y_axis.x;
slice[4] = self.y_axis.y;
slice[5] = self.y_axis.z;
slice[6] = self.z_axis.x;
slice[7] = self.z_axis.y;
slice[8] = self.z_axis.z;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> Vec3A {
match index {
0 => self.x_axis,
1 => self.y_axis,
2 => self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut Vec3A {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
2 => &mut self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> Vec3A {
match index {
0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
let tmp0 = i32x4_shuffle::<0, 1, 4, 5>(self.x_axis.0, self.y_axis.0);
let tmp1 = i32x4_shuffle::<2, 3, 6, 7>(self.x_axis.0, self.y_axis.0);
Self {
x_axis: Vec3A(i32x4_shuffle::<0, 2, 4, 4>(tmp0, self.z_axis.0)),
y_axis: Vec3A(i32x4_shuffle::<1, 3, 5, 5>(tmp0, self.z_axis.0)),
z_axis: Vec3A(i32x4_shuffle::<0, 2, 6, 6>(tmp1, self.z_axis.0)),
}
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f32 {
self.z_axis.dot(self.x_axis.cross(self.y_axis))
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let tmp0 = self.y_axis.cross(self.z_axis);
let tmp1 = self.z_axis.cross(self.x_axis);
let tmp2 = self.x_axis.cross(self.y_axis);
let det = self.z_axis.dot(tmp2);
glam_assert!(det != 0.0);
let inv_det = Vec3A::splat(det.recip());
Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
}
/// Transforms the given 2D vector as a point.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
}
/// Rotates the given 2D vector.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
}
/// Transforms a 3D vector.
#[inline]
#[must_use]
pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
self.mul_vec3a(rhs.into()).into()
}
/// Transforms a [`Vec3A`].
#[inline]
#[must_use]
pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
let mut res = self.x_axis.mul(rhs.xxx());
res = res.add(self.y_axis.mul(rhs.yyy()));
res = res.add(self.z_axis.mul(rhs.zzz()));
res
}
/// Multiplies two 3x3 matrices.
#[inline]
#[must_use]
pub fn mul_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.mul(rhs.x_axis),
self.mul(rhs.y_axis),
self.mul(rhs.z_axis),
)
}
/// Adds two 3x3 matrices.
#[inline]
#[must_use]
pub fn add_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.add(rhs.x_axis),
self.y_axis.add(rhs.y_axis),
self.z_axis.add(rhs.z_axis),
)
}
/// Subtracts two 3x3 matrices.
#[inline]
#[must_use]
pub fn sub_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.sub(rhs.x_axis),
self.y_axis.sub(rhs.y_axis),
self.z_axis.sub(rhs.z_axis),
)
}
/// Multiplies a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f32) -> Self {
Self::from_cols(
self.x_axis.mul(rhs),
self.y_axis.mul(rhs),
self.z_axis.mul(rhs),
)
}
/// Divides a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f32) -> Self {
let rhs = Vec3A::splat(rhs);
Self::from_cols(
self.x_axis.div(rhs),
self.y_axis.div(rhs),
self.z_axis.div(rhs),
)
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
&& self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
}
#[inline]
pub fn as_dmat3(&self) -> DMat3 {
DMat3::from_cols(
self.x_axis.as_dvec3(),
self.y_axis.as_dvec3(),
self.z_axis.as_dvec3(),
)
}
}
impl Default for Mat3A {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat3(&rhs)
}
}
impl AddAssign<Mat3A> for Mat3A {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat3(&rhs);
}
}
impl Sub<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat3(&rhs)
}
}
impl SubAssign<Mat3A> for Mat3A {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat3(&rhs);
}
}
impl Neg for Mat3A {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
}
}
impl Mul<Mat3A> for Mat3A {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat3(&rhs)
}
}
impl MulAssign<Mat3A> for Mat3A {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat3(&rhs);
}
}
impl Mul<Vec3A> for Mat3A {
type Output = Vec3A;
#[inline]
fn mul(self, rhs: Vec3A) -> Self::Output {
self.mul_vec3a(rhs)
}
}
impl Mul<Mat3A> for f32 {
type Output = Mat3A;
#[inline]
fn mul(self, rhs: Mat3A) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f32> for Mat3A {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f32> for Mat3A {
#[inline]
fn mul_assign(&mut self, rhs: f32) {
*self = self.mul_scalar(rhs);
}
}
impl Div<Mat3A> for f32 {
type Output = Mat3A;
#[inline]
fn div(self, rhs: Mat3A) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f32> for Mat3A {
type Output = Self;
#[inline]
fn div(self, rhs: f32) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f32> for Mat3A {
#[inline]
fn div_assign(&mut self, rhs: f32) {
*self = self.div_scalar(rhs);
}
}
impl Mul<Vec3> for Mat3A {
type Output = Vec3;
#[inline]
fn mul(self, rhs: Vec3) -> Vec3 {
self.mul_vec3a(rhs.into()).into()
}
}
impl From<Mat3> for Mat3A {
#[inline]
fn from(m: Mat3) -> Self {
Self {
x_axis: m.x_axis.into(),
y_axis: m.y_axis.into(),
z_axis: m.z_axis.into(),
}
}
}
impl Sum<Self> for Mat3A {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for Mat3A {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for Mat3A {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for Mat3A {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for Mat3A {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
}
}
impl fmt::Debug for Mat3A {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(Mat3A))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.field("z_axis", &self.z_axis)
.finish()
}
}
impl fmt::Display for Mat3A {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}]",
p, self.x_axis, p, self.y_axis, p, self.z_axis
)
} else {
write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
}
}
}

1536
vendor/glam/src/f32/wasm32/mat4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1015
vendor/glam/src/f32/wasm32/quat.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1868
vendor/glam/src/f32/wasm32/vec3a.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1829
vendor/glam/src/f32/wasm32/vec4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

101
vendor/glam/src/f64.rs vendored Normal file
View File

@@ -0,0 +1,101 @@
mod daffine2;
mod daffine3;
mod dmat2;
mod dmat3;
mod dmat4;
mod dquat;
mod dvec2;
mod dvec3;
mod dvec4;
mod float;
pub(crate) mod math;
pub use daffine2::DAffine2;
pub use daffine3::DAffine3;
pub use dmat2::{dmat2, DMat2};
pub use dmat3::{dmat3, DMat3};
pub use dmat4::{dmat4, DMat4};
pub use dquat::{dquat, DQuat};
pub use dvec2::{dvec2, DVec2};
pub use dvec3::{dvec3, DVec3};
pub use dvec4::{dvec4, DVec4};
#[cfg(not(target_arch = "spirv"))]
mod test {
pub use super::*;
mod const_test_daffine2 {
const_assert_eq!(
core::mem::align_of::<super::DVec2>(),
core::mem::align_of::<super::DAffine2>()
);
const_assert_eq!(48, core::mem::size_of::<super::DAffine2>());
}
mod const_test_dmat2 {
const_assert_eq!(
core::mem::align_of::<super::DVec2>(),
core::mem::align_of::<super::DMat2>()
);
const_assert_eq!(32, core::mem::size_of::<super::DMat2>());
}
mod const_test_dmat3 {
const_assert_eq!(
core::mem::align_of::<f64>(),
core::mem::align_of::<super::DMat3>()
);
const_assert_eq!(72, core::mem::size_of::<super::DMat3>());
}
mod const_test_dmat4 {
const_assert_eq!(
core::mem::align_of::<super::DVec4>(),
core::mem::align_of::<super::DMat4>()
);
const_assert_eq!(128, core::mem::size_of::<super::DMat4>());
}
mod const_test_dquat {
#[cfg(not(target_arch = "spirv"))]
const_assert_eq!(
core::mem::align_of::<f64>(),
core::mem::align_of::<super::DQuat>()
);
#[cfg(target_arch = "spirv")]
const_assert_eq!(32, core::mem::align_of::<super::DQuat>());
const_assert_eq!(32, core::mem::size_of::<super::DQuat>());
}
mod const_test_dvec2 {
#[cfg(not(any(feature = "cuda", target_arch = "spirv")))]
const_assert_eq!(
core::mem::align_of::<f64>(),
core::mem::align_of::<super::DVec2>()
);
#[cfg(any(feature = "cuda", target_arch = "spirv"))]
const_assert_eq!(16, core::mem::align_of::<super::DVec2>());
const_assert_eq!(16, core::mem::size_of::<super::DVec2>());
}
mod const_test_dvec3 {
#[cfg(not(target_arch = "spirv"))]
const_assert_eq!(
core::mem::align_of::<f64>(),
core::mem::align_of::<super::DVec3>()
);
#[cfg(target_arch = "spirv")]
const_assert_eq!(16, core::mem::align_of::<super::DVec3>());
const_assert_eq!(24, core::mem::size_of::<super::DVec3>());
}
mod const_test_dvec4 {
#[cfg(not(any(feature = "cuda", target_arch = "spirv")))]
const_assert_eq!(
core::mem::align_of::<f64>(),
core::mem::align_of::<super::DVec4>()
);
#[cfg(any(feature = "cuda", target_arch = "spirv"))]
const_assert_eq!(16, core::mem::align_of::<super::DVec4>());
const_assert_eq!(32, core::mem::size_of::<super::DVec4>());
}
}

418
vendor/glam/src/f64/daffine2.rs vendored Normal file
View File

@@ -0,0 +1,418 @@
// Generated from affine.rs.tera template. Edit the template, not the generated file.
use crate::{DMat2, DMat3, DVec2};
use core::ops::{Deref, DerefMut, Mul, MulAssign};
/// A 2D affine transform, which can represent translation, rotation, scaling and shear.
#[derive(Copy, Clone)]
#[repr(C)]
pub struct DAffine2 {
pub matrix2: DMat2,
pub translation: DVec2,
}
impl DAffine2 {
/// The degenerate zero transform.
///
/// This transforms any finite vector and point to zero.
/// The zero transform is non-invertible.
pub const ZERO: Self = Self {
matrix2: DMat2::ZERO,
translation: DVec2::ZERO,
};
/// The identity transform.
///
/// Multiplying a vector with this returns the same vector.
pub const IDENTITY: Self = Self {
matrix2: DMat2::IDENTITY,
translation: DVec2::ZERO,
};
/// All NAN:s.
pub const NAN: Self = Self {
matrix2: DMat2::NAN,
translation: DVec2::NAN,
};
/// Creates an affine transform from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: DVec2, y_axis: DVec2, z_axis: DVec2) -> Self {
Self {
matrix2: DMat2::from_cols(x_axis, y_axis),
translation: z_axis,
}
}
/// Creates an affine transform from a `[f64; 6]` array stored in column major order.
#[inline]
#[must_use]
pub fn from_cols_array(m: &[f64; 6]) -> Self {
Self {
matrix2: DMat2::from_cols_array(&[m[0], m[1], m[2], m[3]]),
translation: DVec2::from_array([m[4], m[5]]),
}
}
/// Creates a `[f64; 6]` array storing data in column major order.
#[inline]
#[must_use]
pub fn to_cols_array(&self) -> [f64; 6] {
let x = &self.matrix2.x_axis;
let y = &self.matrix2.y_axis;
let z = &self.translation;
[x.x, x.y, y.x, y.y, z.x, z.y]
}
/// Creates an affine transform from a `[[f64; 2]; 3]`
/// 2D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub fn from_cols_array_2d(m: &[[f64; 2]; 3]) -> Self {
Self {
matrix2: DMat2::from_cols(m[0].into(), m[1].into()),
translation: m[2].into(),
}
}
/// Creates a `[[f64; 2]; 3]` 2D array storing data in
/// column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub fn to_cols_array_2d(&self) -> [[f64; 2]; 3] {
[
self.matrix2.x_axis.into(),
self.matrix2.y_axis.into(),
self.translation.into(),
]
}
/// Creates an affine transform from the first 6 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 6 elements long.
#[inline]
#[must_use]
pub fn from_cols_slice(slice: &[f64]) -> Self {
Self {
matrix2: DMat2::from_cols_slice(&slice[0..4]),
translation: DVec2::from_slice(&slice[4..6]),
}
}
/// Writes the columns of `self` to the first 6 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 6 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f64]) {
self.matrix2.write_cols_to_slice(&mut slice[0..4]);
self.translation.write_to_slice(&mut slice[4..6]);
}
/// Creates an affine transform that changes scale.
/// Note that if any scale is zero the transform will be non-invertible.
#[inline]
#[must_use]
pub fn from_scale(scale: DVec2) -> Self {
Self {
matrix2: DMat2::from_diagonal(scale),
translation: DVec2::ZERO,
}
}
/// Creates an affine transform from the given rotation `angle`.
#[inline]
#[must_use]
pub fn from_angle(angle: f64) -> Self {
Self {
matrix2: DMat2::from_angle(angle),
translation: DVec2::ZERO,
}
}
/// Creates an affine transformation from the given 2D `translation`.
#[inline]
#[must_use]
pub fn from_translation(translation: DVec2) -> Self {
Self {
matrix2: DMat2::IDENTITY,
translation,
}
}
/// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation)
#[inline]
#[must_use]
pub fn from_mat2(matrix2: DMat2) -> Self {
Self {
matrix2,
translation: DVec2::ZERO,
}
}
/// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation) and a
/// translation vector.
///
/// Equivalent to
/// `DAffine2::from_translation(translation) * DAffine2::from_mat2(mat2)`
#[inline]
#[must_use]
pub fn from_mat2_translation(matrix2: DMat2, translation: DVec2) -> Self {
Self {
matrix2,
translation,
}
}
/// Creates an affine transform from the given 2D `scale`, rotation `angle` (in radians) and
/// `translation`.
///
/// Equivalent to `DAffine2::from_translation(translation) *
/// DAffine2::from_angle(angle) * DAffine2::from_scale(scale)`
#[inline]
#[must_use]
pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
let rotation = DMat2::from_angle(angle);
Self {
matrix2: DMat2::from_cols(rotation.x_axis * scale.x, rotation.y_axis * scale.y),
translation,
}
}
/// Creates an affine transform from the given 2D rotation `angle` (in radians) and
/// `translation`.
///
/// Equivalent to `DAffine2::from_translation(translation) * DAffine2::from_angle(angle)`
#[inline]
#[must_use]
pub fn from_angle_translation(angle: f64, translation: DVec2) -> Self {
Self {
matrix2: DMat2::from_angle(angle),
translation,
}
}
/// The given `DMat3` must be an affine transform,
#[inline]
#[must_use]
pub fn from_mat3(m: DMat3) -> Self {
use crate::swizzles::Vec3Swizzles;
Self {
matrix2: DMat2::from_cols(m.x_axis.xy(), m.y_axis.xy()),
translation: m.z_axis.xy(),
}
}
/// Extracts `scale`, `angle` and `translation` from `self`.
///
/// The transform is expected to be non-degenerate and without shearing, or the output
/// will be invalid.
///
/// # Panics
///
/// Will panic if the determinant `self.matrix2` is zero or if the resulting scale
/// vector contains any zero elements when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_scale_angle_translation(self) -> (DVec2, f64, DVec2) {
use crate::f64::math;
let det = self.matrix2.determinant();
glam_assert!(det != 0.0);
let scale = DVec2::new(
self.matrix2.x_axis.length() * math::signum(det),
self.matrix2.y_axis.length(),
);
glam_assert!(scale.cmpne(DVec2::ZERO).all());
let angle = math::atan2(-self.matrix2.y_axis.x, self.matrix2.y_axis.y);
(scale, angle, self.translation)
}
/// Transforms the given 2D point, applying shear, scale, rotation and translation.
#[inline]
#[must_use]
pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
self.matrix2 * rhs + self.translation
}
/// Transforms the given 2D vector, applying shear, scale and rotation (but NOT
/// translation).
///
/// To also apply translation, use [`Self::transform_point2()`] instead.
#[inline]
pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
self.matrix2 * rhs
}
/// Returns `true` if, and only if, all elements are finite.
///
/// If any element is either `NaN`, positive or negative infinity, this will return
/// `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.matrix2.is_finite() && self.translation.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.matrix2.is_nan() || self.translation.is_nan()
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two 3x4 matrices contain similar elements. It works
/// best when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
self.matrix2.abs_diff_eq(rhs.matrix2, max_abs_diff)
&& self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
}
/// Return the inverse of this transform.
///
/// Note that if the transform is not invertible the result will be invalid.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let matrix2 = self.matrix2.inverse();
// transform negative translation by the matrix inverse:
let translation = -(matrix2 * self.translation);
Self {
matrix2,
translation,
}
}
}
impl Default for DAffine2 {
#[inline(always)]
fn default() -> Self {
Self::IDENTITY
}
}
impl Deref for DAffine2 {
type Target = crate::deref::Cols3<DVec2>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Self as *const Self::Target) }
}
}
impl DerefMut for DAffine2 {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self as *mut Self as *mut Self::Target) }
}
}
impl PartialEq for DAffine2 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.matrix2.eq(&rhs.matrix2) && self.translation.eq(&rhs.translation)
}
}
impl core::fmt::Debug for DAffine2 {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fmt.debug_struct(stringify!(DAffine2))
.field("matrix2", &self.matrix2)
.field("translation", &self.translation)
.finish()
}
}
impl core::fmt::Display for DAffine2 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}]",
p, self.matrix2.x_axis, p, self.matrix2.y_axis, p, self.translation
)
} else {
write!(
f,
"[{}, {}, {}]",
self.matrix2.x_axis, self.matrix2.y_axis, self.translation
)
}
}
}
impl<'a> core::iter::Product<&'a Self> for DAffine2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| a * b)
}
}
impl Mul for DAffine2 {
type Output = DAffine2;
#[inline]
fn mul(self, rhs: DAffine2) -> Self::Output {
Self {
matrix2: self.matrix2 * rhs.matrix2,
translation: self.matrix2 * rhs.translation + self.translation,
}
}
}
impl MulAssign for DAffine2 {
#[inline]
fn mul_assign(&mut self, rhs: DAffine2) {
*self = self.mul(rhs);
}
}
impl From<DAffine2> for DMat3 {
#[inline]
fn from(m: DAffine2) -> DMat3 {
Self::from_cols(
m.matrix2.x_axis.extend(0.0),
m.matrix2.y_axis.extend(0.0),
m.translation.extend(1.0),
)
}
}
impl Mul<DMat3> for DAffine2 {
type Output = DMat3;
#[inline]
fn mul(self, rhs: DMat3) -> Self::Output {
DMat3::from(self) * rhs
}
}
impl Mul<DAffine2> for DMat3 {
type Output = DMat3;
#[inline]
fn mul(self, rhs: DAffine2) -> Self::Output {
self * DMat3::from(rhs)
}
}

566
vendor/glam/src/f64/daffine3.rs vendored Normal file
View File

@@ -0,0 +1,566 @@
// Generated from affine.rs.tera template. Edit the template, not the generated file.
use crate::{DMat3, DMat4, DQuat, DVec3};
use core::ops::{Deref, DerefMut, Mul, MulAssign};
/// A 3D affine transform, which can represent translation, rotation, scaling and shear.
#[derive(Copy, Clone)]
#[repr(C)]
pub struct DAffine3 {
pub matrix3: DMat3,
pub translation: DVec3,
}
impl DAffine3 {
/// The degenerate zero transform.
///
/// This transforms any finite vector and point to zero.
/// The zero transform is non-invertible.
pub const ZERO: Self = Self {
matrix3: DMat3::ZERO,
translation: DVec3::ZERO,
};
/// The identity transform.
///
/// Multiplying a vector with this returns the same vector.
pub const IDENTITY: Self = Self {
matrix3: DMat3::IDENTITY,
translation: DVec3::ZERO,
};
/// All NAN:s.
pub const NAN: Self = Self {
matrix3: DMat3::NAN,
translation: DVec3::NAN,
};
/// Creates an affine transform from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3, w_axis: DVec3) -> Self {
Self {
matrix3: DMat3::from_cols(x_axis, y_axis, z_axis),
translation: w_axis,
}
}
/// Creates an affine transform from a `[f64; 12]` array stored in column major order.
#[inline]
#[must_use]
pub fn from_cols_array(m: &[f64; 12]) -> Self {
Self {
matrix3: DMat3::from_cols_array(&[
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
]),
translation: DVec3::from_array([m[9], m[10], m[11]]),
}
}
/// Creates a `[f64; 12]` array storing data in column major order.
#[inline]
#[must_use]
pub fn to_cols_array(&self) -> [f64; 12] {
let x = &self.matrix3.x_axis;
let y = &self.matrix3.y_axis;
let z = &self.matrix3.z_axis;
let w = &self.translation;
[x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
}
/// Creates an affine transform from a `[[f64; 3]; 4]`
/// 3D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub fn from_cols_array_2d(m: &[[f64; 3]; 4]) -> Self {
Self {
matrix3: DMat3::from_cols(m[0].into(), m[1].into(), m[2].into()),
translation: m[3].into(),
}
}
/// Creates a `[[f64; 3]; 4]` 3D array storing data in
/// column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub fn to_cols_array_2d(&self) -> [[f64; 3]; 4] {
[
self.matrix3.x_axis.into(),
self.matrix3.y_axis.into(),
self.matrix3.z_axis.into(),
self.translation.into(),
]
}
/// Creates an affine transform from the first 12 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 12 elements long.
#[inline]
#[must_use]
pub fn from_cols_slice(slice: &[f64]) -> Self {
Self {
matrix3: DMat3::from_cols_slice(&slice[0..9]),
translation: DVec3::from_slice(&slice[9..12]),
}
}
/// Writes the columns of `self` to the first 12 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 12 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f64]) {
self.matrix3.write_cols_to_slice(&mut slice[0..9]);
self.translation.write_to_slice(&mut slice[9..12]);
}
/// Creates an affine transform that changes scale.
/// Note that if any scale is zero the transform will be non-invertible.
#[inline]
#[must_use]
pub fn from_scale(scale: DVec3) -> Self {
Self {
matrix3: DMat3::from_diagonal(scale),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform from the given `rotation` quaternion.
#[inline]
#[must_use]
pub fn from_quat(rotation: DQuat) -> Self {
Self {
matrix3: DMat3::from_quat(rotation),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around a normalized
/// rotation `axis` of `angle` (in radians).
#[inline]
#[must_use]
pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
Self {
matrix3: DMat3::from_axis_angle(axis, angle),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around the x axis of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f64) -> Self {
Self {
matrix3: DMat3::from_rotation_x(angle),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around the y axis of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f64) -> Self {
Self {
matrix3: DMat3::from_rotation_y(angle),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around the z axis of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f64) -> Self {
Self {
matrix3: DMat3::from_rotation_z(angle),
translation: DVec3::ZERO,
}
}
/// Creates an affine transformation from the given 3D `translation`.
#[inline]
#[must_use]
pub fn from_translation(translation: DVec3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: DMat3::IDENTITY,
translation: translation.into(),
}
}
/// Creates an affine transform from a 3x3 matrix (expressing scale, shear and
/// rotation)
#[inline]
#[must_use]
pub fn from_mat3(mat3: DMat3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: mat3.into(),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform from a 3x3 matrix (expressing scale, shear and rotation)
/// and a translation vector.
///
/// Equivalent to `DAffine3::from_translation(translation) * DAffine3::from_mat3(mat3)`
#[inline]
#[must_use]
pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: mat3.into(),
translation: translation.into(),
}
}
/// Creates an affine transform from the given 3D `scale`, `rotation` and
/// `translation`.
///
/// Equivalent to `DAffine3::from_translation(translation) *
/// DAffine3::from_quat(rotation) * DAffine3::from_scale(scale)`
#[inline]
#[must_use]
pub fn from_scale_rotation_translation(
scale: DVec3,
rotation: DQuat,
translation: DVec3,
) -> Self {
let rotation = DMat3::from_quat(rotation);
#[allow(clippy::useless_conversion)]
Self {
matrix3: DMat3::from_cols(
rotation.x_axis * scale.x,
rotation.y_axis * scale.y,
rotation.z_axis * scale.z,
),
translation: translation.into(),
}
}
/// Creates an affine transform from the given 3D `rotation` and `translation`.
///
/// Equivalent to `DAffine3::from_translation(translation) * DAffine3::from_quat(rotation)`
#[inline]
#[must_use]
pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: DMat3::from_quat(rotation),
translation: translation.into(),
}
}
/// The given `DMat4` must be an affine transform,
/// i.e. contain no perspective transform.
#[inline]
#[must_use]
pub fn from_mat4(m: DMat4) -> Self {
Self {
matrix3: DMat3::from_cols(
DVec3::from_vec4(m.x_axis),
DVec3::from_vec4(m.y_axis),
DVec3::from_vec4(m.z_axis),
),
translation: DVec3::from_vec4(m.w_axis),
}
}
/// Extracts `scale`, `rotation` and `translation` from `self`.
///
/// The transform is expected to be non-degenerate and without shearing, or the output
/// will be invalid.
///
/// # Panics
///
/// Will panic if the determinant `self.matrix3` is zero or if the resulting scale
/// vector contains any zero elements when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
use crate::f64::math;
let det = self.matrix3.determinant();
glam_assert!(det != 0.0);
let scale = DVec3::new(
self.matrix3.x_axis.length() * math::signum(det),
self.matrix3.y_axis.length(),
self.matrix3.z_axis.length(),
);
glam_assert!(scale.cmpne(DVec3::ZERO).all());
let inv_scale = scale.recip();
#[allow(clippy::useless_conversion)]
let rotation = DQuat::from_mat3(&DMat3::from_cols(
(self.matrix3.x_axis * inv_scale.x).into(),
(self.matrix3.y_axis * inv_scale.y).into(),
(self.matrix3.z_axis * inv_scale.z).into(),
));
#[allow(clippy::useless_conversion)]
(scale, rotation, self.translation.into())
}
/// Creates a left-handed view transform using a camera position, an up direction, and a facing
/// direction.
///
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
#[inline]
#[must_use]
pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
Self::look_to_rh(eye, -dir, up)
}
/// Creates a right-handed view transform using a camera position, an up direction, and a facing
/// direction.
///
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
#[inline]
#[must_use]
pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
let f = dir.normalize();
let s = f.cross(up).normalize();
let u = s.cross(f);
Self {
matrix3: DMat3::from_cols(
DVec3::new(s.x, u.x, -f.x),
DVec3::new(s.y, u.y, -f.y),
DVec3::new(s.z, u.z, -f.z),
),
translation: DVec3::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
}
}
/// Creates a left-handed view transform using a camera position, an up direction, and a focal
/// point.
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
///
/// # Panics
///
/// Will panic if `up` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
glam_assert!(up.is_normalized());
Self::look_to_lh(eye, center - eye, up)
}
/// Creates a right-handed view transform using a camera position, an up direction, and a focal
/// point.
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
///
/// # Panics
///
/// Will panic if `up` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
glam_assert!(up.is_normalized());
Self::look_to_rh(eye, center - eye, up)
}
/// Transforms the given 3D points, applying shear, scale, rotation and translation.
#[inline]
pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
#[allow(clippy::useless_conversion)]
((self.matrix3.x_axis * rhs.x)
+ (self.matrix3.y_axis * rhs.y)
+ (self.matrix3.z_axis * rhs.z)
+ self.translation)
.into()
}
/// Transforms the given 3D vector, applying shear, scale and rotation (but NOT
/// translation).
///
/// To also apply translation, use [`Self::transform_point3()`] instead.
#[inline]
#[must_use]
pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
#[allow(clippy::useless_conversion)]
((self.matrix3.x_axis * rhs.x)
+ (self.matrix3.y_axis * rhs.y)
+ (self.matrix3.z_axis * rhs.z))
.into()
}
/// Returns `true` if, and only if, all elements are finite.
///
/// If any element is either `NaN`, positive or negative infinity, this will return
/// `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.matrix3.is_finite() && self.translation.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.matrix3.is_nan() || self.translation.is_nan()
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two 3x4 matrices contain similar elements. It works
/// best when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
&& self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
}
/// Return the inverse of this transform.
///
/// Note that if the transform is not invertible the result will be invalid.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let matrix3 = self.matrix3.inverse();
// transform negative translation by the matrix inverse:
let translation = -(matrix3 * self.translation);
Self {
matrix3,
translation,
}
}
}
impl Default for DAffine3 {
#[inline(always)]
fn default() -> Self {
Self::IDENTITY
}
}
impl Deref for DAffine3 {
type Target = crate::deref::Cols4<DVec3>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Self as *const Self::Target) }
}
}
impl DerefMut for DAffine3 {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self as *mut Self as *mut Self::Target) }
}
}
impl PartialEq for DAffine3 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
}
}
impl core::fmt::Debug for DAffine3 {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fmt.debug_struct(stringify!(DAffine3))
.field("matrix3", &self.matrix3)
.field("translation", &self.translation)
.finish()
}
}
impl core::fmt::Display for DAffine3 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}, {:.*}]",
p,
self.matrix3.x_axis,
p,
self.matrix3.y_axis,
p,
self.matrix3.z_axis,
p,
self.translation
)
} else {
write!(
f,
"[{}, {}, {}, {}]",
self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
)
}
}
}
impl<'a> core::iter::Product<&'a Self> for DAffine3 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| a * b)
}
}
impl Mul for DAffine3 {
type Output = DAffine3;
#[inline]
fn mul(self, rhs: DAffine3) -> Self::Output {
Self {
matrix3: self.matrix3 * rhs.matrix3,
translation: self.matrix3 * rhs.translation + self.translation,
}
}
}
impl MulAssign for DAffine3 {
#[inline]
fn mul_assign(&mut self, rhs: DAffine3) {
*self = self.mul(rhs);
}
}
impl From<DAffine3> for DMat4 {
#[inline]
fn from(m: DAffine3) -> DMat4 {
DMat4::from_cols(
m.matrix3.x_axis.extend(0.0),
m.matrix3.y_axis.extend(0.0),
m.matrix3.z_axis.extend(0.0),
m.translation.extend(1.0),
)
}
}
impl Mul<DMat4> for DAffine3 {
type Output = DMat4;
#[inline]
fn mul(self, rhs: DMat4) -> Self::Output {
DMat4::from(self) * rhs
}
}
impl Mul<DAffine3> for DMat4 {
type Output = DMat4;
#[inline]
fn mul(self, rhs: DAffine3) -> Self::Output {
self * DMat4::from(rhs)
}
}

Some files were not shown because too many files have changed in this diff Show More