feat: attempt to implement math library

Adds many files, but the next thing is to implement the MeshRegistry properly.
This commit is contained in:
alphafetus committed 2026-05-08 08:02:38 -04:00
1 parent 9e4f531bd4
commit e7659ba387
18 files changed
+1232 -136

No files matched your search

+2
View File
@@ -2,7 +2,9 @@
<module type="EMPTY_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/macros/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/macros/target" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
Generated
+564 -8
View File
@@ -24,6 +24,12 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "ahash"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0453232ace82dee0dd0b4c87a59bd90f7b53b314f3e0f61fe2ee7c8a16482289"
[[package]]
name = "ahash"
version = "0.8.12"
@@ -31,7 +37,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
dependencies = [
"cfg-if",
"getrandom",
"getrandom 0.3.4",
"once_cell",
"version_check",
"zerocopy",
@@ -88,6 +94,15 @@ version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "approx"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
dependencies = [
"num-traits",
]
[[package]]
name = "arbitrary"
version = "1.4.2"
@@ -141,6 +156,15 @@ dependencies = [
"libloading",
]
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
@@ -264,6 +288,12 @@ dependencies = [
"syn",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "byteorder-lite"
version = "0.1.0"
@@ -341,6 +371,15 @@ dependencies = [
"cc",
]
[[package]]
name = "cobs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
dependencies = [
"thiserror 2.0.18",
]
[[package]]
name = "color_quant"
version = "1.1.0"
@@ -424,6 +463,12 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "critical-section"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
@@ -513,6 +558,18 @@ version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "embedded-io"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
[[package]]
name = "embedded-io"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
[[package]]
name = "equator"
version = "0.4.2"
@@ -684,10 +741,23 @@ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"r-efi 5.3.0",
"wasip2",
]
[[package]]
name = "getrandom"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
dependencies = [
"cfg-if",
"libc",
"r-efi 6.0.0",
"wasip2",
"wasip3",
]
[[package]]
name = "gif"
version = "0.14.1"
@@ -698,6 +768,114 @@ dependencies = [
"weezl",
]
[[package]]
name = "glam"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "333928d5eb103c5d4050533cec0384302db6be8ef7d3cebd30ec6a35350353da"
[[package]]
name = "glam"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3abb554f8ee44336b72d522e0a7fe86a29e09f839a36022fa869a7dfe941a54b"
[[package]]
name = "glam"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4126c0479ccf7e8664c36a2d719f5f2c140fbb4f9090008098d2c291fa5b3f16"
[[package]]
name = "glam"
version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01732b97afd8508eee3333a541b9f7610f454bb818669e66e90f5f57c93a776"
[[package]]
name = "glam"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525a3e490ba77b8e326fb67d4b44b4bd2f920f44d4cc73ccec50adc68e3bee34"
[[package]]
name = "glam"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b8509e6791516e81c1a630d0bd7fbac36d2fa8712a9da8662e716b52d5051ca"
[[package]]
name = "glam"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43e957e744be03f5801a55472f593d43fabdebf25a4585db250f04d86b1675f"
[[package]]
name = "glam"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815"
[[package]]
name = "glam"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774"
[[package]]
name = "glam"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c"
[[package]]
name = "glam"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945"
[[package]]
name = "glam"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
[[package]]
name = "glam"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9"
[[package]]
name = "glam"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94"
[[package]]
name = "glam"
version = "0.29.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee"
[[package]]
name = "glam"
version = "0.30.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9"
[[package]]
name = "glam"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556f6b2ea90b8d15a74e0e7bb41671c9bdf38cd9f78c284d750b9ce58a2b5be7"
[[package]]
name = "glam"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f70749695b063ecbf6b62949ccccde2e733ec3ecbbd71d467dca4e5c6c97cca0"
[[package]]
name = "half"
version = "2.7.1"
@@ -710,24 +888,77 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "hash32"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
dependencies = [
"byteorder",
]
[[package]]
name = "hashbrown"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
dependencies = [
"ahash 0.4.8",
]
[[package]]
name = "hashbrown"
version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"foldhash",
]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
[[package]]
name = "heapless"
version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
dependencies = [
"atomic-polyfill",
"hash32",
"rustc_version",
"serde",
"spin",
"stable_deref_trait",
]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "id-arena"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
[[package]]
name = "image"
version = "0.25.10"
@@ -775,7 +1006,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
dependencies = [
"equivalent",
"hashbrown",
"hashbrown 0.16.1",
"serde",
"serde_core",
]
[[package]]
@@ -832,7 +1065,7 @@ version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
dependencies = [
"getrandom",
"getrandom 0.3.4",
"libc",
]
@@ -846,6 +1079,12 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "leb128fmt"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "lebe"
version = "0.5.3"
@@ -926,6 +1165,16 @@ dependencies = [
"imgref",
]
[[package]]
name = "matrixmultiply"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
dependencies = [
"autocfg",
"rawpointer",
]
[[package]]
name = "maybe-rayon"
version = "0.1.1"
@@ -977,6 +1226,51 @@ dependencies = [
"pxfm",
]
[[package]]
name = "nalgebra"
version = "0.34.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df76ea0ff5c7e6b88689085804d6132ded0ddb9de5ca5b8aeb9eeadc0508a70a"
dependencies = [
"approx",
"glam 0.14.0",
"glam 0.15.2",
"glam 0.16.0",
"glam 0.17.3",
"glam 0.18.0",
"glam 0.19.0",
"glam 0.20.5",
"glam 0.21.3",
"glam 0.22.0",
"glam 0.23.0",
"glam 0.24.2",
"glam 0.25.0",
"glam 0.27.0",
"glam 0.28.0",
"glam 0.29.3",
"glam 0.30.10",
"glam 0.31.1",
"glam 0.32.1",
"matrixmultiply",
"nalgebra-macros",
"num-complex",
"num-rational",
"num-traits",
"simba",
"typenum",
]
[[package]]
name = "nalgebra-macros"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "973e7178a678cfd059ccec50887658d482ce16b0aa9da3888ddeab5cd5eb4889"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "ndk"
version = "0.9.0"
@@ -1048,6 +1342,15 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
dependencies = [
"num-traits",
]
[[package]]
name = "num-derive"
version = "0.4.2"
@@ -1499,6 +1802,19 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "postcard"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
dependencies = [
"cobs",
"embedded-io 0.4.0",
"embedded-io 0.6.1",
"heapless",
"serde",
]
[[package]]
name = "ppv-lite86"
version = "0.2.21"
@@ -1508,6 +1824,16 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "prettyplease"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro-crate"
version = "3.5.0"
@@ -1590,6 +1916,12 @@ version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "r-efi"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "rand"
version = "0.9.2"
@@ -1616,7 +1948,7 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
dependencies = [
"getrandom",
"getrandom 0.3.4",
]
[[package]]
@@ -1687,6 +2019,12 @@ dependencies = [
"objc2-quartz-core 0.3.2",
]
[[package]]
name = "rawpointer"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
[[package]]
name = "rayon"
version = "1.11.0"
@@ -1749,6 +2087,15 @@ dependencies = [
"xmlparser",
]
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "0.38.44"
@@ -1781,6 +2128,15 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "safe_arch"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
dependencies = [
"bytemuck",
]
[[package]]
name = "same-file"
version = "1.0.6"
@@ -1815,6 +2171,12 @@ dependencies = [
"tiny-skia",
]
[[package]]
name = "semver"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.228"
@@ -1885,6 +2247,19 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "simba"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c99284beb21666094ba2b75bbceda012e610f5479dfcc2d6e2426f53197ffd95"
dependencies = [
"approx",
"num-complex",
"num-traits",
"paste",
"wide",
]
[[package]]
name = "simd-adler32"
version = "0.3.8"
@@ -1952,6 +2327,15 @@ dependencies = [
"serde",
]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
@@ -2115,6 +2499,12 @@ version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
[[package]]
name = "typenum"
version = "1.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
[[package]]
name = "unicode-ident"
version = "1.0.24"
@@ -2127,6 +2517,23 @@ version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "uuid"
version = "1.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
dependencies = [
"getrandom 0.4.2",
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "v_frame"
version = "0.3.9"
@@ -2164,7 +2571,7 @@ dependencies = [
"crossbeam-queue",
"foldhash",
"half",
"heck",
"heck 0.4.1",
"indexmap",
"libloading",
"nom 7.1.3",
@@ -2204,7 +2611,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bf501461be7cef2893c0e62c50945add9763cc482051d29053f6157089d5ea9"
dependencies = [
"foldhash",
"heck",
"heck 0.4.1",
"proc-macro2",
"quote",
"shaderc",
@@ -2217,8 +2624,13 @@ name = "vulkano-test"
version = "0.1.0"
dependencies = [
"image",
"nalgebra",
"postcard",
"serde",
"uuid",
"vulkano",
"vulkano-shaders",
"wavefront",
"winit",
]
@@ -2241,6 +2653,15 @@ dependencies = [
"wit-bindgen",
]
[[package]]
name = "wasip3"
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
dependencies = [
"wit-bindgen",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.114"
@@ -2300,6 +2721,49 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "wasm-encoder"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
dependencies = [
"leb128fmt",
"wasmparser",
]
[[package]]
name = "wasm-metadata"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
dependencies = [
"anyhow",
"indexmap",
"wasm-encoder",
"wasmparser",
]
[[package]]
name = "wasmparser"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [
"bitflags 2.11.0",
"hashbrown 0.15.5",
"indexmap",
"semver",
]
[[package]]
name = "wavefront"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0162190f32ea78b07b7bc02b57a1c2a7c0874bc3da34f36eba41c86c4b03c4fb"
dependencies = [
"hashbrown 0.9.1",
]
[[package]]
name = "wayland-backend"
version = "0.3.14"
@@ -2435,6 +2899,16 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
[[package]]
name = "wide"
version = "0.7.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03"
dependencies = [
"bytemuck",
"safe_arch",
]
[[package]]
name = "winapi-util"
version = "0.1.11"
@@ -2613,7 +3087,7 @@ version = "0.30.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d"
dependencies = [
"ahash",
"ahash 0.8.12",
"android-activity",
"atomic-waker",
"bitflags 2.11.0",
@@ -2673,6 +3147,88 @@ name = "wit-bindgen"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
dependencies = [
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen-core"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
dependencies = [
"anyhow",
"heck 0.5.0",
"wit-parser",
]
[[package]]
name = "wit-bindgen-rust"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
dependencies = [
"anyhow",
"heck 0.5.0",
"indexmap",
"prettyplease",
"syn",
"wasm-metadata",
"wit-bindgen-core",
"wit-component",
]
[[package]]
name = "wit-bindgen-rust-macro"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
dependencies = [
"anyhow",
"prettyplease",
"proc-macro2",
"quote",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
]
[[package]]
name = "wit-component"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
dependencies = [
"anyhow",
"bitflags 2.11.0",
"indexmap",
"log",
"serde",
"serde_derive",
"serde_json",
"wasm-encoder",
"wasm-metadata",
"wasmparser",
"wit-parser",
]
[[package]]
name = "wit-parser"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
dependencies = [
"anyhow",
"id-arena",
"indexmap",
"log",
"semver",
"serde",
"serde_derive",
"serde_json",
"unicode-xid",
"wasmparser",
]
[[package]]
name = "x11-dl"
+5
View File
@@ -5,6 +5,11 @@ edition = "2024"
[dependencies]
image = "0.25.10"
serde = { version = "1.0", features=[ "derive" ] }
vulkano = "^0.35"
vulkano-shaders = "^0.35"
wavefront = "0.2.3"
winit = "0.30.13"
nalgebra = "*"
uuid = { version = "1.23.1", features = ["v4"] }
postcard = { version = "1.1", features = ["alloc"] }
+19 -44
View File
@@ -1,6 +1,6 @@
use std::error::Error;
use std::sync::Arc;
use vulkano::buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer};
use vulkano::buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer};
use vulkano::command_buffer::allocator::{StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo};
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer, RenderPassBeginInfo, SubpassBeginInfo, SubpassContents, SubpassEndInfo};
use vulkano::descriptor_set::allocator::{DescriptorSetAllocator, StandardDescriptorSetAllocator};
@@ -28,37 +28,10 @@ use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::ActiveEventLoop;
use winit::window::{Window, WindowAttributes, WindowId};
use crate::math::Vector2;
use crate::common::mesh::MeshRegistry;
use crate::gpu::vertex3::Vertex3;
use crate::triangle;
/// The `Vertex2` is an intermediate structure used to represent the [`Vector2`] in the graphics
/// pipeline. It specifies a positional value and can be passed directly into the shaders.
/// Note that conversion between a `Vector2` and a `Vertex2` may take extra computation time.
///
/// Honestly, I'm still not sure if this should be handled on a per-shader basis, as the position
/// argument changes with each shader.
#[derive(BufferContents, Vertex)]
#[repr(C)]
struct Vertex2 {
#[format(R32G32_SFLOAT)]
position: [f32; 2],
}
impl From<Vector2> for Vertex2 {
fn from(v: Vector2) -> Self {
Self {
position: [v.x, v.y],
}
}
}
#[derive(BufferContents, Vertex)]
#[repr(C)]
struct Vertex3 {
#[format(R32G32B32_SFLOAT)]
position: [f32; 3],
}
struct VulkanContext {
window: Arc<Window>,
device: Arc<Device>,
@@ -73,9 +46,8 @@ struct VulkanContext {
render_pass: Arc<RenderPass>,
framebuffers: Vec<Arc<Framebuffer>>,
pipeline: Arc<GraphicsPipeline>,
vertex_buffer: Arc<Subbuffer<[Vertex2]>>,
index_buffer: Arc<Subbuffer<[u32]>>,
cmd_buffers: Vec<Arc<PrimaryAutoCommandBuffer>>,
mesh_registry: Arc<MeshRegistry>,
}
impl VulkanContext {
@@ -201,10 +173,10 @@ impl VulkanContext {
..Default::default()
},
vec![
Vertex2 { position: [0.5, 0.5] },
Vertex2 { position: [-0.5, 0.5] },
Vertex2 { position: [-0.5, -0.5] },
Vertex2 { position: [0.5, -0.5] },
Vertex3 { position: [0.5, 0.5, 0.0] },
Vertex3 { position: [-0.5, 0.5, 0.0] },
Vertex3 { position: [-0.5, -0.5, 0.0] },
Vertex3 { position: [0.5, -0.5, 0.0] },
]
)?);
@@ -234,6 +206,10 @@ impl VulkanContext {
&index_buffer
)?;
let mesh_registry = Arc::new(MeshRegistry::new(
mem_allocator.clone(),
)?);
Ok(Self {
window,
device,
@@ -248,9 +224,8 @@ impl VulkanContext {
frag_shader,
framebuffers,
pipeline,
vertex_buffer,
index_buffer,
cmd_buffers
cmd_buffers,
mesh_registry,
})
}
@@ -378,7 +353,7 @@ impl VulkanContext {
let fs = frag_shader.entry_point("main")
.ok_or("Failed to find fragment shader entry point")?;
let vertex_input_state = Vertex2::per_vertex()
let vertex_input_state = Vertex3::per_vertex()
.definition(&vs)?;
let stages = vec![
@@ -432,7 +407,7 @@ impl VulkanContext {
queue: &Arc<Queue>,
pipeline: &Arc<GraphicsPipeline>,
framebuffers: &Vec<Arc<Framebuffer>>,
vertex_buffer: &Subbuffer<[Vertex2]>,
vertex_buffer: &Arc<Subbuffer<[Vertex3]>>,
index_buffer: &Subbuffer<[u32]>
) -> Result<Vec<Arc<PrimaryAutoCommandBuffer>>, Box<dyn Error>> {
let buffers = framebuffers.iter()
@@ -456,7 +431,7 @@ impl VulkanContext {
}
).ok()?
.bind_pipeline_graphics(pipeline.clone()).ok()?
.bind_vertex_buffers(0, vertex_buffer.clone()).ok()?
.bind_vertex_buffers(0, vertex_buffer.as_ref().clone()).ok()?
.bind_index_buffer(index_buffer.clone()).ok()?
// .draw(vertex_buffer.len() as u32, 1, 0, 0).ok()?
.draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0).ok()?
@@ -506,8 +481,8 @@ impl VulkanContext {
&self.queue,
&new_pipeline,
&self.framebuffers,
&self.vertex_buffer,
&self.index_buffer
&self.mesh_registry.vertex_buffer,
&self.mesh_registry.index_buffer
)?;
self.pipeline = new_pipeline;
+55
View File
@@ -0,0 +1,55 @@
use nalgebra::{Matrix4, Vector3, Vector4};
use crate::common::scene::SceneInstance;
/// Contains all information about an instance of a mesh, specifically its translation, rotation,
/// and scale. Note that the rotation is a [`Vector4`], and not a `Quaternion`.
///
/// This may be taken from a scene instance by calling the `Instance::from` method on the
/// corresponding [`SceneInstance`]. This is important, as the `Vector4` is not serializable.
///
/// Before passing this instance into the shaders, construct a transformation matrix by calling
/// [`MeshInstance::transform_matrix`].
pub struct MeshInstance {
/// The ID of the mesh corresponding to this instance.
pub mesh_id: String,
/// The translation of the instance from the center of the standard space. It is possible that
/// local translation will be required in the future.
pub translation: Vector4<f32>,
/// The rotation of the instance. Note that since this is a [`Vector4`], or Euler angle, it
/// suffers from gimbal lock. If this becomes a serious issue, an [`nalgebra::UnitQuaternion`]
/// should be used instead.
pub rotation: Vector4<f32>,
/// The scale of the instance, represented as the scaling in XYZ coordinates.
pub scale: Vector3<f32>,
}
impl MeshInstance {
/// Constructs a transformation matrix from the current translation, rotation, and scale.
pub fn transform_matrix(&self) -> Matrix4<f32> {
Matrix4::new_translation(&self.translation.xyz()) *
// There's a possibility that these can be altered. Sometimes they're multiplied in the
// order ZYX. They are technically applied in the opposite order written here, so in
// this case it's actually applying Z, then Y, then X. They *do* produce different results.
Matrix4::from_axis_angle(&Vector3::x_axis(), self.rotation.x) *
Matrix4::from_axis_angle(&Vector3::y_axis(), self.rotation.y) *
Matrix4::from_axis_angle(&Vector3::z_axis(), self.rotation.z) *
Matrix4::new_nonuniform_scaling(&self.scale)
}
/// Constructs a `MeshInstance` from the given [`SceneInstance`] and mesh ID.
fn from_scene_instance(
mesh_id: String,
SceneInstance {
translation,
rotation,
scale,
}: SceneInstance,
) -> Self {
Self {
mesh_id,
translation: Vector3::from(translation).to_homogeneous(),
rotation: Vector3::from(rotation).to_homogeneous(),
scale: Vector3::from(scale),
}
}
}
+155
View File
@@ -0,0 +1,155 @@
use std::collections::HashMap;
use std::error::Error;
use std::path::Path;
use std::sync::Arc;
use nalgebra::Vector3;
use uuid::Uuid;
use vulkano::buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer};
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter};
use wavefront::Obj;
use crate::common::scene::Scene;
use crate::gpu::vertex3::Vertex3;
/// This struct is slightly misleading - it doesn't actually contain the mesh information, but
/// the locations of the mesh's information in the overall application's vertex buffer, index buffer,
/// and other such structures.
///
/// Once loaded, the mesh should be accessible via ID through a registry-type struct, which simply
/// maintains the list of meshes that have been loaded by the application so far and which assigns
/// the correct indices for buffer-to-render logic.
///
/// That means that this `Mesh` struct is actually just an entry within that registry. They should
/// rarely be used directly, and should never be edited.
#[derive(Debug)]
pub struct Mesh {
pub id: String,
pub vertex_loc: usize,
pub index_loc: usize,
}
impl Mesh {
pub fn new(
id: impl Into<String>,
vertex_loc: usize,
index_loc: usize,
) -> Self {
Self {
id: id.into(),
vertex_loc,
index_loc,
}
}
}
/// # Mesh Registry
/// A wrapper around a series of [`Mesh`] structs, keyed by a unique ID, and the buffers that are
/// used by the rendering pipeline.
#[derive(Debug)]
pub struct MeshRegistry {
meshes: HashMap<String, Mesh>,
allocator: Arc<dyn MemoryAllocator>,
pub vertex_buffer: Arc<Subbuffer<[Vertex3]>>,
pub index_buffer: Arc<Subbuffer<[u32]>>,
}
impl MeshRegistry {
pub fn new(
allocator: Arc<dyn MemoryAllocator>,
) -> Result<Self, Box<dyn Error>> {
let vertex_buffer = Arc::new(Buffer::new_slice::<Vertex3>(
allocator.clone(),
BufferCreateInfo {
usage: BufferUsage::VERTEX_BUFFER,
..Default::default()
},
AllocationCreateInfo {
memory_type_filter: MemoryTypeFilter::PREFER_HOST |
MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default()
},
1_000_000,
)?);
let index_buffer = Arc::new(Buffer::new_slice::<u32>(
allocator.clone(),
BufferCreateInfo {
usage: BufferUsage::INDEX_BUFFER,
..Default::default()
},
AllocationCreateInfo {
memory_type_filter: MemoryTypeFilter::PREFER_HOST |
MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default()
},
3_000_000,
)?);
Ok(Self {
meshes: HashMap::new(),
allocator,
vertex_buffer,
index_buffer,
})
}
/// Creates a `MeshRegistry` from the provided [`Scene`].
///
/// This method will load all the meshes indicated by the scene and allocate the required
/// buffers. This significantly simplifies the allocation process, as the buffers only need to
/// be allocated once.
pub fn from_scene(scene: &Scene, allocator: Arc<dyn MemoryAllocator>) -> Self {
// First, load all the meshes into a single map.
println!("Loading meshes from scene");
let meshes = scene.mesh_paths.iter().map(|(id, path)|
(id.clone(), Obj::from_file(path).expect("Couldn't read wavefront file"))
).collect::<HashMap<String, Obj>>();
// Second, build two more maps that contain the vertex and index information.
let verts = meshes.iter().map(|(id, obj)|
(id.clone(), obj.vertices().map(|v| v.position().into()).collect())
).collect::<HashMap<String, Vec<Vector3<f32>>>>();
let indices = meshes.iter().map(|(id, obj)|
(id.clone(), obj.vertices().map(|v| v.position_index()).collect())
).collect::<HashMap<String, Vec<usize>>>();
// Apply static transformations here. The general idea is that we don't want to have to read
// any information from the buffer without the correct information. We do want to keep track
// of what mesh is at what location in the list though.
println!("Applying static mesh transformations");
// Get Vector3's as a list of Vertex3's (CPU to GPU)
// Third, allocate and fill buffers with this information.
// let vert_buffer = Self::alloc_vert_buffer(allocator, verts.values().collect());
// Fourth, return the struct.
todo!()
}
fn alloc_vert_buffer(
alloc: Arc<dyn MemoryAllocator>,
verts: Vec<Vertex3>
) -> Arc<Subbuffer<[Vertex3]>> {
println!("Allocating vertex buffer");
Arc::new(Buffer::from_iter(
alloc.clone(),
BufferCreateInfo {
usage: BufferUsage::VERTEX_BUFFER,
..Default::default()
},
AllocationCreateInfo {
memory_type_filter: MemoryTypeFilter::PREFER_HOST |
MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default()
},
verts
).expect("Couldn't allocate vertex buffer"))
}
/// Attempts to find a [`Mesh`] with the given ID, returning `None` if it's not found.
pub fn get(&self, uuid: &str) -> Option<&Mesh> {
self.meshes.get(uuid)
}
}
+3
View File
@@ -0,0 +1,3 @@
pub mod mesh;
pub mod scene;
pub mod instance;
+74
View File
@@ -0,0 +1,74 @@
use std::collections::HashMap;
use std::io::Read;
use std::path::Path;
use serde::{Deserialize, Serialize};
/// A scene, which holds all information required to render a world.
///
/// This includes all mesh information, and all the information that is required to place
/// instances of these meshes in the world.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[repr(C)]
pub struct Scene {
/// The name of the scene.
pub name: String,
/// The collection of paths to the meshes, relative to the current scene file.
/// This collection is keyed on the ID of the mesh, which can be used later on to place
/// the meshes in the scenes with specific instances. This ID will also be used to register
/// the meshes with the application's registries, which will allow the program to associate
/// specific behavior with the mesh.
pub mesh_paths: HashMap<String, String>,
/// A collection of instances that are keyed by the mesh's IDs. Each instance can be used to
/// place a [`Mesh`] in the rendered scene.
pub instances: HashMap<String, SceneInstance>,
}
impl Scene {
/// Converts this `Scene` into its byte representation.
pub fn bytes(&self) -> Vec<u8> {
postcard::to_allocvec(self)
.expect("Couldn't serialize scene")
}
/// Reads a `scene` from the given path. Automatically resolves all paths for the meshes that
/// are referenced in the struct.
///
/// Reading a scene file allows for all meshes to be loaded at once, which therefore allows
/// the program to allocate pipeline buffers just once during the load of this. It would likely
/// be reasonable to create a `MeshRegistry` and `InstanceRegistry` at the same time, with
/// respect to a single loaded `Scene`.
pub fn from_file<P: AsRef<Path>>(path: P) -> Self {
let path = path.as_ref();
let mut file = std::fs::File::open(path).unwrap();
let mut contents = Vec::new();
let _ = file.read_to_end(&mut contents).unwrap();
let mut scene: Self = postcard::from_bytes(contents.as_slice())
.expect("Couldn't deserialize scene");
let base = path.parent().unwrap_or(&Path::new("."));
scene.mesh_paths = scene.mesh_paths
.into_iter()
.map(|(id, mesh_path)| {
let res = base.join(mesh_path);
let str = res.to_str().unwrap_or_default();
(id, str.to_string())
}).collect::<HashMap<String, String>>();
scene
}
}
/// Contains all information about an instance in the scene, specifically the name of the mesh it
/// should use and the translation, rotation, and scale of it.
///
/// After deserialization, this struct should be converted into an [`Instance`], which contains
/// defined vectors that can be used to work with the object before sending it to the shaders.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[repr(C)]
pub struct SceneInstance {
pub translation: [f32; 3],
pub rotation: [f32; 3],
pub scale: [f32; 3],
}
+29
View File
@@ -0,0 +1,29 @@
use vulkano::buffer::BufferContents;
use vulkano::pipeline::graphics::vertex_input::Vertex;
use crate::common::instance::MeshInstance;
/// A transformation matrix for a mesh that can be passed into the shaders.
#[derive(BufferContents, Vertex)]
#[repr(C)]
pub struct GpuInstance {
#[format(R32G32B32A32_SFLOAT)]
pub transform_col1: [f32; 4],
#[format(R32G32B32A32_SFLOAT)]
pub transform_col2: [f32; 4],
#[format(R32G32B32A32_SFLOAT)]
pub transform_col3: [f32; 4],
#[format(R32G32B32A32_SFLOAT)]
pub transform_col4: [f32; 4],
}
impl Into<GpuInstance> for MeshInstance {
fn into(self) -> GpuInstance {
let m = self.transform_matrix();
GpuInstance {
transform_col1: m.column(0).into(),
transform_col2: m.column(1).into(),
transform_col3: m.column(2).into(),
transform_col4: m.column(3).into(),
}
}
}
+2
View File
@@ -0,0 +1,2 @@
pub mod vertex3;
pub mod instance;
+15
View File
@@ -0,0 +1,15 @@
use vulkano::buffer::BufferContents;
use vulkano::pipeline::graphics::vertex_input::Vertex;
#[derive(Debug, BufferContents, Vertex)]
#[repr(C)]
pub struct Vertex3 {
#[format(R32G32B32_SFLOAT)]
pub(crate) position: [f32; 3],
}
impl From<&[f32; 3]> for Vertex3 {
fn from(v: &[f32; 3]) -> Self {
Self { position: v.clone() }
}
}
+2
View File
@@ -1,5 +1,7 @@
mod app;
pub mod math;
mod common;
pub mod gpu;
use std::error::Error;
use vulkano::swapchain::Surface;
+78 -64
View File
@@ -1,11 +1,11 @@
use std::ops::{Add, Div, Index, IndexMut, Mul, Sub};
use crate::math::traits::Matrix;
use crate::math::Vector2;
use std::ops::{Add, Index, IndexMut, Mul, Sub};
use crate::math::traits::{Matrix, Vector};
use crate::math::{Vector2};
#[derive(Clone, Debug, PartialEq, PartialOrd, Copy, Default)]
pub struct Matrix2 {
row1: [f32; 2],
row2: [f32; 2],
row1: Vector2,
row2: Vector2,
}
impl Matrix2 {
@@ -29,23 +29,23 @@ impl Matrix2 {
}
impl Index<usize> for Matrix2 {
type Output = [f32; 2];
type Output = Vector2;
fn index(&self, index: usize) -> &Self::Output {
if index == 0 {
&self.row1
} else {
&self.row2
fn index(&self, idx: usize) -> &Self::Output {
match idx {
0 => &self.row1,
1 => &self.row2,
_ => panic!("Index out of bounds"),
}
}
}
impl IndexMut<usize> for Matrix2 {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
if index == 0 {
&mut self.row1
} else {
&mut self.row2
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
match idx {
0 => &mut self.row1,
1 => &mut self.row2,
_ => panic!("Index out of bounds"),
}
}
}
@@ -55,8 +55,8 @@ impl Add for Matrix2 {
fn add(self, rhs: Self) -> Self::Output {
Self {
row1: [self[0][0] + rhs[0][0], self[0][1] + rhs[0][1]],
row2: [self[1][0] + rhs[1][0], self[1][1] + rhs[1][1]],
row1: [self[0][0] + rhs[0][0], self[0][1] + rhs[0][1]].into(),
row2: [self[1][0] + rhs[1][0], self[1][1] + rhs[1][1]].into(),
}
}
}
@@ -66,19 +66,29 @@ impl Sub for Matrix2 {
fn sub(self, rhs: Self) -> Self::Output {
Self {
row1: [self[0][0] - rhs[0][0], self[0][1] - rhs[0][1]],
row2: [self[1][0] - rhs[1][0], self[1][1] - rhs[1][1]],
row1: [self[0][0] - rhs[0][0], self[0][1] - rhs[0][1]].into(),
row2: [self[1][0] - rhs[1][0], self[1][1] - rhs[1][1]].into(),
}
}
}
impl Mul<f32> for Matrix2 {
type Output = Self;
fn mul(self, rhs: f32) -> Self::Output {
type Output = Matrix2;
fn mul(self, rhs: f32) -> Matrix2 {
Self {
row1: [self[0][0] * rhs, self[0][1] * rhs],
row2: [self[1][0] * rhs, self[1][1] * rhs],
row1: self.row1 * rhs,
row2: self.row2 * rhs,
}
}
}
impl Mul<Vector2> for Matrix2 {
type Output = Vector2;
fn mul(self, rhs: Vector2) -> Self::Output {
Vector2 {
x: self[0].dot(rhs),
y: self[1].dot(rhs),
}
}
}
@@ -95,58 +105,62 @@ impl Mul for Matrix2 {
type Output = Self;
fn mul(self, rhs: Matrix2) -> Self::Output {
let other = rhs.transpose();
Self {
row1: [self[0][0] * rhs[0][0] + self[0][1] * rhs[1][0], self[0][0] * rhs[0][1] + self[0][1] * rhs[1][1]],
row2: [self[1][0] * rhs[0][0] + self[1][1] * rhs[1][0], self[1][0] * rhs[0][1] + self[1][1] * rhs[1][1]],
row1: [self[0].dot(other[0]), self[0].dot(other[1])].into(),
row2: [self[1].dot(other[0]), self[1].dot(other[1])].into(),
}
}
}
impl Div<f32> for Matrix2 {
type Output = Self;
fn div(self, rhs: f32) -> Self::Output {
todo!()
}
}
impl Div for Matrix2 {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
todo!()
}
}
impl Matrix for Matrix2 {
impl Matrix<Vector2> for Matrix2 {
fn identity() -> Self {
Self {
row1: [1.0, 0.0],
row2: [0.0, 1.0],
row1: [1.0, 0.0].into(),
row2: [0.0, 1.0].into(),
}
}
fn transpose(self) -> Self {
fn transpose(&self) -> Self {
Self {
row1: [self[0][0], self[1][0]].into(),
row2: [self[0][1], self[1][1]].into(),
}
}
fn determinant(&self) -> f32 {
self[0][0] * self[1][1] - self[0][1] * self[1][0]
}
fn minor(&self) -> Self {
Self {
row1: [self[1][1], self[1][0]].into(),
row2: [self[0][1], self[0][0]].into(),
}
}
fn cofactor(&self) -> Self {
let mut minor = self.minor();
for row in 0..2 {
for col in 0..2 {
let even = (row + col) % 2 == 0;
if even {
minor[row][col] = -minor[row][col];
}
}
}
minor
}
fn adjugate(&self) -> Self {
todo!()
}
fn determinant(self) -> f32 {
todo!()
}
fn inverse(&self) -> Self {
let adj = self.adjugate();
let det = self.determinant();
fn minor(self) -> Self {
todo!()
}
fn cofactor(self) -> Self {
todo!()
}
fn adjugate(self) -> Self {
todo!()
}
fn inverse(self) -> Self {
todo!()
(1.0 / det) * adj
}
}
+130
View File
@@ -0,0 +1,130 @@
use std::ops::{Add, Div, Mul, Sub};
use crate::math::traits::{Matrix, Vector};
use crate::math::Vector4;
#[derive(Debug, Clone, Default, Copy, PartialEq)]
pub struct Matrix4 {
row1: Vector4,
row2: Vector4,
row3: Vector4,
row4: Vector4,
}
impl Matrix4 {
}
impl Add for Matrix4 {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self {
row1: self.row1 + rhs.row1,
row2: self.row2 + rhs.row2,
row3: self.row3 + rhs.row3,
row4: self.row4 + rhs.row4,
}
}
}
impl Sub for Matrix4 {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self {
row1: self.row1 - rhs.row1,
row2: self.row2 - rhs.row2,
row3: self.row3 - rhs.row3,
row4: self.row4 - rhs.row4,
}
}
}
impl Div<f32> for Matrix4 {
type Output = Self;
/// Equivalent to multiplying by the reciprocal of `rhs`.
fn div(self, rhs: f32) -> Self::Output {
let rhs = 1.0 / rhs;
self * rhs
}
}
impl Mul<f32> for Matrix4 {
type Output = Self;
fn mul(self, rhs: f32) -> Self::Output {
Self {
row1: self.row1 * rhs,
row2: self.row2 * rhs,
row3: self.row3 * rhs,
row4: self.row4 * rhs,
}
}
}
impl Mul for Matrix4 {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
let rhs = rhs.transpose();
Self {
row1: [self.row1.dot(rhs.row1), self.row1.dot(rhs.row2), self.row1.dot(rhs.row3), self.row1.dot(rhs.row4)].into(),
row2: [self.row2.dot(rhs.row1), self.row2.dot(rhs.row2), self.row2.dot(rhs.row3), self.row2.dot(rhs.row4)].into(),
row3: [self.row3.dot(rhs.row1), self.row3.dot(rhs.row2), self.row3.dot(rhs.row3), self.row3.dot(rhs.row4)].into(),
row4: [self.row4.dot(rhs.row1), self.row4.dot(rhs.row2), self.row4.dot(rhs.row3), self.row4.dot(rhs.row4)].into(),
}
}
}
impl Mul<Vector4> for Matrix4 {
type Output = Vector4;
fn mul(self, rhs: Vector4) -> Vector4 {
Vector4 {
x: self.row1.dot(rhs),
y: self.row2.dot(rhs),
z: self.row3.dot(rhs),
w: self.row4.dot(rhs),
}
}
}
impl Matrix<Vector4> for Matrix4 {
fn identity() -> Self {
Self {
row1: Vector4::new(1.0, 0.0, 0.0, 0.0),
row2: Vector4::new(0.0, 1.0, 0.0, 0.0),
row3: Vector4::new(0.0, 0.0, 1.0, 0.0),
row4: Vector4::new(0.0, 0.0, 0.0, 1.0),
}
}
fn transpose(&self) -> Self {
Self {
row1: [self.row1.x, self.row2.x, self.row3.x, self.row4.x].into(),
row2: [self.row1.y, self.row2.y, self.row3.y, self.row4.y].into(),
row3: [self.row1.z, self.row2.z, self.row3.z, self.row4.z].into(),
row4: [self.row1.w, self.row2.w, self.row3.w, self.row4.w].into(),
}
}
fn determinant(&self) -> f32 {
todo!()
}
fn minor(&self) -> Self {
todo!()
}
fn cofactor(&self) -> Self {
todo!()
}
fn adjugate(&self) -> Self {
todo!()
}
fn inverse(&self) -> Self {
todo!()
}
}
+22 -10
View File
@@ -1,6 +1,8 @@
use std::ops::{Add, Div, Mul, Sub};
use crate::math::Vector4;
pub trait Vector: Copy + Default + PartialEq + PartialOrd + Add + Sub + Div<f32, Output = Self> + Mul<f32, Output = Self> {
pub trait Vector: Clone + Copy + Default + PartialEq + Add + Sub + PartialOrd
+ Div<f32, Output = Self> + Mul<f32, Output = Self> {
/// Gets the dot product of the two vectors.
fn dot(self, other: Self) -> f32;
@@ -26,32 +28,42 @@ pub trait Vector: Copy + Default + PartialEq + PartialOrd + Add + Sub + Div<f32,
}
}
pub trait Matrix: Copy + Default + PartialEq + PartialOrd + Add + Sub
+ Div<f32, Output = Self> + Div
+ Mul<f32, Output = Self> + Mul {
/// # Matrix Trait
///
/// Requires a few manual implementations, specifically the `identity`, `transpose`, and `determinant`.
/// All other information can be found by the trait itself.
///
/// Note that this trait does not require implementation of the `Div` trait at all - this is because
/// matrices do not have division, only multiplication by a scalar value. This doesn't mean that the
/// scalar cannot be a decimal value, however.
pub trait Matrix<TVec>: Clone + Copy + Default + PartialEq + Add + Sub
+ Mul<f32, Output = Self> + Mul<TVec, Output = TVec>
+ Mul<Output = Self>
where TVec: Vector
{
/// Creates an identity matrix.
fn identity() -> Self;
/// Gets the transpose of this matrix.
fn transpose(self) -> Self;
fn transpose(&self) -> Self;
/// Gets the determinant of this matrix.
fn determinant(self) -> f32;
fn determinant(&self) -> f32;
/// Finds the minor of this matrix. The element at location (`i`, `j`) of the minor is the
/// determinant of the submatrix obtained by removing row `i` and column `j` in the original
/// matrix.
fn minor(self) -> Self;
fn minor(&self) -> Self;
/// Finds the cofactor of this matrix. The element at location (`i`, `j`) of the cofactor is
/// defined as -1^ij * Mij, where Mij is the element at (`i`, `j`) in the minor of the matrix.
/// This is effectively flipping the sign of every other element in the minor of this matrix.
fn cofactor(self) -> Self;
fn cofactor(&self) -> Self;
/// Gets the adjugate of this matrix. This is the transpose of the cofactor of this matrix.
fn adjugate(self) -> Self;
fn adjugate(&self) -> Self;
/// Gets the inverse of this matrix. Note that this is a very expensive operation and should
/// be used as sparingly as possible.
fn inverse(self) -> Self;
fn inverse(&self) -> Self;
}
+22 -1
View File
@@ -1,4 +1,4 @@
use std::ops::{Add, Div, Mul, Sub};
use std::ops::{Add, Div, Mul, Sub, Index, IndexMut};
use crate::math::traits::Vector;
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
@@ -17,6 +17,27 @@ impl Vector2 {
}
}
impl Index<usize> for Vector2 {
type Output = f32;
fn index(&self, idx: usize) -> &f32 {
match idx {
0 => &self.x,
1 => &self.y,
_ => panic!("Index out of bounds"),
}
}
}
impl IndexMut<usize> for Vector2 {
fn index_mut(&mut self, idx: usize) -> &mut f32 {
match idx {
0 => &mut self.x,
1 => &mut self.y,
_ => panic!("Index out of bounds"),
}
}
}
impl Add for Vector2 {
type Output = Self;
+53 -7
View File
@@ -11,8 +11,24 @@ pub struct Vector4 {
}
impl Vector4 {
pub fn new() -> Self {
Self::default()
pub fn new(
x: f32,
y: f32,
z: f32,
w: f32,
) -> Self {
Self {
x, y, z, w
}
}
pub fn one() -> Self {
Self {
x: 1.0,
y: 1.0,
z: 1.0,
w: 1.0,
}
}
pub fn xyzw(&self) -> (f32, f32, f32, f32) {
@@ -83,6 +99,20 @@ impl Mul<Vector4> for f32 {
}
}
impl Mul for Vector4 {
type Output = Self;
/// Computes the Hadamard product of the two vectors.
fn mul(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 Div<f32> for Vector4 {
type Output = Self;
@@ -119,12 +149,28 @@ impl Vector for Vector4 {
}
impl From<[f32; 4]> for Vector4 {
fn from(v: [f32; 4]) -> Self {
fn from([x, y, z, w]: [f32; 4]) -> Self {
Self {
x: v[0],
y: v[1],
z: v[2],
w: v[3],
x, y, z, w,
}
}
}
impl From<[f32; 3]> for Vector4 {
/// Creates a homogenous `Vector4` from a 3D positional vector.
fn from([x, y, z]: [f32; 3]) -> Self {
Self {
x, y, z,
w: 1.0,
}
}
}
impl From<Vector3> for Vector4 {
fn from(Vector3 { x, y, z }: Vector3) -> Self {
Self {
x, y, z,
w: 1.0
}
}
}
+2 -2
View File
@@ -1,7 +1,7 @@
#version 460
layout(location = 0) in vec2 position;
layout(location = 0) in vec3 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
gl_Position = vec4(position, 1.0);
}