initial commit
This commit is contained in:
parent
c279996a07
commit
9b630556ae
993
Cargo.lock
generated
Normal file
993
Cargo.lock
generated
Normal file
|
@ -0,0 +1,993 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
|
||||
|
||||
[[package]]
|
||||
name = "calloop"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf2eec61efe56aa1e813f5126959296933cf0700030e4314786c48779a66ab82"
|
||||
dependencies = [
|
||||
"log",
|
||||
"nix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
"core-foundation 0.9.3",
|
||||
"core-graphics 0.22.3",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa-foundation"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
"core-foundation 0.9.3",
|
||||
"core-graphics-types",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.7.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.8.3",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
version = "0.19.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation 0.7.0",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation 0.9.3",
|
||||
"core-graphics-types",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics-types"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation 0.9.3",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-video-sys"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"core-foundation-sys 0.7.0",
|
||||
"core-graphics 0.19.2",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cty"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
|
||||
|
||||
[[package]]
|
||||
name = "d3"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"softbuffer",
|
||||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
||||
|
||||
[[package]]
|
||||
name = "dlib"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "downcast-rs"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni-sys"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"jni-sys",
|
||||
"ndk-sys",
|
||||
"num_enum",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk-context"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
|
||||
|
||||
[[package]]
|
||||
name = "ndk-glue"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c71bee8ea72d685477e28bd004cfe1bf99c754d688cd78cad139eae4089484d4"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"ndk",
|
||||
"ndk-context",
|
||||
"ndk-macro",
|
||||
"ndk-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk-macro"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9"
|
||||
dependencies = [
|
||||
"num_enum_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum_derive"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b800beb9b6e7d2df1fe337c9e3d04e3af22a124460fb4c30fcc22c9117cefb41"
|
||||
dependencies = [
|
||||
"cty",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "534cfe58d6a18cc17120fbf4635d53d14691c1fe4d951064df9bd326178d7d5a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
|
||||
|
||||
[[package]]
|
||||
name = "smithay-client-toolkit"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a28f16a97fa0e8ce563b2774d1e732dd5d4025d2772c5dba0a41a0f90a29da3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"calloop",
|
||||
"dlib",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"memmap2",
|
||||
"nix",
|
||||
"pkg-config",
|
||||
"wayland-client",
|
||||
"wayland-cursor",
|
||||
"wayland-protocols",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "softbuffer"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d1cda310762a78016e0bcb9f21b9f6c288858941eab798443c19d8f77cde68a"
|
||||
dependencies = [
|
||||
"cocoa",
|
||||
"core-graphics 0.22.3",
|
||||
"foreign-types",
|
||||
"objc",
|
||||
"raw-window-handle",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"wasm-bindgen",
|
||||
"wayland-client",
|
||||
"web-sys",
|
||||
"winapi",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"fastrand",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
|
||||
|
||||
[[package]]
|
||||
name = "wayland-client"
|
||||
version = "0.29.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91223460e73257f697d9e23d401279123d36039a3f7a449e983f123292d4458f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"downcast-rs",
|
||||
"libc",
|
||||
"nix",
|
||||
"scoped-tls",
|
||||
"wayland-commons",
|
||||
"wayland-scanner",
|
||||
"wayland-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-commons"
|
||||
version = "0.29.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94f6e5e340d7c13490eca867898c4cec5af56c27a5ffe5c80c6fc4708e22d33e"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"once_cell",
|
||||
"smallvec",
|
||||
"wayland-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-cursor"
|
||||
version = "0.29.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c52758f13d5e7861fc83d942d3d99bf270c83269575e52ac29e5b73cb956a6bd"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"wayland-client",
|
||||
"xcursor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-protocols"
|
||||
version = "0.29.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60147ae23303402e41fe034f74fb2c35ad0780ee88a1c40ac09a3be1e7465741"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"wayland-client",
|
||||
"wayland-commons",
|
||||
"wayland-scanner",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-scanner"
|
||||
version = "0.29.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39a1ed3143f7a143187156a2ab52742e89dac33245ba505c17224df48939f9e0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-sys"
|
||||
version = "0.29.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9341df79a8975679188e37dab3889bfa57c44ac2cb6da166f519a81cbe452d4"
|
||||
dependencies = [
|
||||
"dlib",
|
||||
"lazy_static",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
|
||||
[[package]]
|
||||
name = "winit"
|
||||
version = "0.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cocoa",
|
||||
"core-foundation 0.9.3",
|
||||
"core-graphics 0.22.3",
|
||||
"core-video-sys",
|
||||
"dispatch",
|
||||
"instant",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"mio",
|
||||
"ndk",
|
||||
"ndk-glue",
|
||||
"ndk-sys",
|
||||
"objc",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"raw-window-handle",
|
||||
"smithay-client-toolkit",
|
||||
"wasm-bindgen",
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
"web-sys",
|
||||
"winapi",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11-dl"
|
||||
version = "2.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xcursor"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
|
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "d3"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
softbuffer = "0.1.1"
|
||||
winit = "0.26.1"
|
||||
|
||||
[features]
|
156
src/buffer.rs
Normal file
156
src/buffer.rs
Normal file
|
@ -0,0 +1,156 @@
|
|||
use d3::rgb::Rgb;
|
||||
use d3::vector2::Vec2Int;
|
||||
pub use d3::vector3::{Direction3, Vec3};
|
||||
use std::ops::Deref;
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub struct GraphicsBuffer {
|
||||
buf: Vec<Rgb>,
|
||||
/// Depth™️ buffer
|
||||
depth: Vec<u32>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
}
|
||||
|
||||
impl GraphicsBuffer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
buf: Vec::new(),
|
||||
depth: Vec::new(),
|
||||
width: 0,
|
||||
height: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, pos: Vec2Int, v: Rgb, depth: u32) {
|
||||
if pos.x < 0 || pos.y < 0 || pos.x >= self.width as i32 || pos.y >= self.height as i32 {
|
||||
return;
|
||||
}
|
||||
let index = pos.x as usize + pos.y as usize * self.width;
|
||||
if depth > self.depth[index] {
|
||||
return;
|
||||
}
|
||||
self.buf[index] = v;
|
||||
// let channel = (depth / (u32::MAX / u8::MAX as u32)) as u8;
|
||||
// self.buf[index] = Rgb::new(channel, channel, channel);
|
||||
self.depth[index] = depth;
|
||||
}
|
||||
|
||||
fn plot_line_low(&mut self, a: Vec2Int, b: Vec2Int, az: f32, bz: f32, v: Rgb) {
|
||||
#![allow(clippy::many_single_char_names)]
|
||||
let dx = b.x - a.x;
|
||||
let dy = (b.y - a.y).abs();
|
||||
let yi = if b.y >= a.y { 1 } else { -1 };
|
||||
let mut d = (2 * dy) - dx;
|
||||
let mut y = a.y;
|
||||
|
||||
let mut z = az;
|
||||
let dz = (bz - az) / dx as f32;
|
||||
|
||||
for x in a.x..b.x {
|
||||
if 0.0 < z && z < 1.0 {
|
||||
self.set((x, y).into(), v, (z * u32::MAX as f32) as u32);
|
||||
}
|
||||
|
||||
if d > 0 {
|
||||
y += yi;
|
||||
d += 2 * (dy - dx);
|
||||
} else {
|
||||
d += 2 * dy;
|
||||
}
|
||||
|
||||
z += dz;
|
||||
}
|
||||
}
|
||||
|
||||
fn plot_line_high(&mut self, a: Vec2Int, b: Vec2Int, az: f32, bz: f32, v: Rgb) {
|
||||
#![allow(clippy::many_single_char_names)]
|
||||
let dx = (b.x - a.x).abs();
|
||||
let dy = b.y - a.y;
|
||||
let xi = if b.x >= a.x { 1 } else { -1 };
|
||||
let mut d = (2 * dx) - dy;
|
||||
let mut x = a.x;
|
||||
|
||||
let mut z = az;
|
||||
let dz = (bz - az) / dy as f32;
|
||||
|
||||
for y in a.y..b.y {
|
||||
if 0.0 < z && z < 1.0 {
|
||||
self.set((x, y).into(), v, (z * u32::MAX as f32) as u32);
|
||||
}
|
||||
|
||||
if d > 0 {
|
||||
x += xi;
|
||||
d += 2 * (dx - dy);
|
||||
} else {
|
||||
d += 2 * dx;
|
||||
}
|
||||
|
||||
z += dz;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_line(&mut self, mut a: Vec3, mut b: Vec3, v: Rgb) {
|
||||
let quarter_width = (self.width / 4) as f32;
|
||||
let quarter_height = (self.height / 4) as f32;
|
||||
let scale = self.height as f32;
|
||||
|
||||
a.x *= scale;
|
||||
b.x *= scale;
|
||||
a.y *= -scale;
|
||||
b.y *= -scale;
|
||||
|
||||
a.x += quarter_width;
|
||||
b.x += quarter_width;
|
||||
a.y += quarter_height;
|
||||
b.y += quarter_height;
|
||||
|
||||
// kinda hacky, need to do this to avoid the `i32` restriction in `Vec3Int`
|
||||
let az = a.z;
|
||||
let bz = b.z;
|
||||
|
||||
let a = a.rounded().into_vec2();
|
||||
let b = b.rounded().into_vec2();
|
||||
|
||||
// TODO: optimize for vertical and horizontal cases
|
||||
#[allow(clippy::collapsible_else_if)]
|
||||
if (b.y - a.y).abs() < (b.x - a.x).abs() {
|
||||
if a.x > b.x {
|
||||
self.plot_line_low(b, a, bz, az, v);
|
||||
} else {
|
||||
self.plot_line_low(a, b, az, bz, v);
|
||||
}
|
||||
} else {
|
||||
if a.y > b.y {
|
||||
self.plot_line_high(b, a, bz, az, v);
|
||||
} else {
|
||||
self.plot_line_high(a, b, az, bz, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, dim: Vec2Int, v: Option<Rgb>) {
|
||||
let (width, height) = (dim.x as usize, dim.y as usize);
|
||||
self.buf.resize(width * height, v.unwrap_or(Rgb::BLACK));
|
||||
self.depth.resize(width * height, u32::MAX);
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
}
|
||||
|
||||
pub fn resize_and_clear(&mut self, dim: Vec2Int, v: Rgb) {
|
||||
if dim.x as usize != self.width || dim.y as usize != self.height {
|
||||
self.resize(dim, Some(v));
|
||||
} else {
|
||||
self.buf.fill(v);
|
||||
self.depth.fill(u32::MAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for GraphicsBuffer {
|
||||
type Target = [u32];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
Rgb::as_u32_slice(&self.buf)
|
||||
}
|
||||
}
|
15
src/lib.rs
Normal file
15
src/lib.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
//! Some docs idk
|
||||
|
||||
#![warn(clippy::pedantic)]
|
||||
#![allow(clippy::must_use_candidate)]
|
||||
#![allow(clippy::return_self_not_must_use)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
/// Quaternions, or rotations in 3d space.
|
||||
pub mod quaternion;
|
||||
/// Rgb (red green blue) colors.
|
||||
pub mod rgb;
|
||||
/// Vec2, or a location in 2d space.
|
||||
pub mod vector2;
|
||||
/// Vec3, or a location in 3d space
|
||||
pub mod vector3;
|
278
src/main.rs
Normal file
278
src/main.rs
Normal file
|
@ -0,0 +1,278 @@
|
|||
#![warn(clippy::pedantic)]
|
||||
#![allow(clippy::too_many_lines)]
|
||||
// we use lots of casts, so explicitly allowing
|
||||
#![allow(clippy::cast_possible_truncation)]
|
||||
#![allow(clippy::cast_sign_loss)]
|
||||
#![allow(clippy::cast_precision_loss)]
|
||||
|
||||
use d3::quaternion::Quaternion;
|
||||
use d3::rgb::Rgb;
|
||||
use d3::vector2::Vec2;
|
||||
use d3::vector3::{Direction3, Vec3};
|
||||
use softbuffer::GraphicsContext;
|
||||
use std::collections::HashMap;
|
||||
use std::f32::consts::PI;
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
use winit::dpi::PhysicalPosition;
|
||||
use winit::event::{
|
||||
ElementState, Event, KeyboardInput, ModifiersState, MouseButton, VirtualKeyCode, WindowEvent,
|
||||
};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::WindowBuilder;
|
||||
|
||||
use crate::buffer::GraphicsBuffer;
|
||||
|
||||
mod buffer;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct Transform {
|
||||
pos: Vec3,
|
||||
rot: Quaternion,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Camera {
|
||||
transform: Transform,
|
||||
near_clip: f32,
|
||||
far_clip: f32,
|
||||
vertical_fov: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Triangle {
|
||||
points: [Vec3; 3],
|
||||
color: Rgb,
|
||||
}
|
||||
|
||||
struct InputManager {
|
||||
keys: HashMap<VirtualKeyCode, bool>,
|
||||
buttons: HashMap<MouseButton, bool>,
|
||||
modifier_keys: ModifiersState,
|
||||
mouse_pos: Vec2,
|
||||
mouse_delta: Vec2,
|
||||
}
|
||||
|
||||
impl InputManager {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
keys: HashMap::new(),
|
||||
buttons: HashMap::new(),
|
||||
modifier_keys: ModifiersState::empty(),
|
||||
mouse_pos: (0, 0).into(),
|
||||
mouse_delta: (0, 0).into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_keyboard_input(&mut self, ev: KeyboardInput) {
|
||||
if let Some(keycode) = ev.virtual_keycode {
|
||||
self.keys.insert(
|
||||
keycode,
|
||||
match ev.state {
|
||||
ElementState::Pressed => true,
|
||||
ElementState::Released => false,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_mouse_movement(&mut self, ev: PhysicalPosition<f64>) {
|
||||
let ev = ev.cast::<f32>();
|
||||
let new_pos = Vec2::from((ev.x, ev.y));
|
||||
|
||||
self.mouse_delta += new_pos - self.mouse_pos;
|
||||
self.mouse_pos = new_pos;
|
||||
}
|
||||
|
||||
fn handle_modifiers_changed(&mut self, ev: ModifiersState) {
|
||||
self.modifier_keys = ev;
|
||||
}
|
||||
|
||||
fn handle_mouse_button(&mut self, ev: (MouseButton, ElementState)) {
|
||||
self.buttons.insert(
|
||||
ev.0,
|
||||
match ev.1 {
|
||||
ElementState::Pressed => true,
|
||||
ElementState::Released => false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn key_pressed(&self, key: VirtualKeyCode) -> bool {
|
||||
self.keys.get(&key).copied().unwrap_or_default()
|
||||
}
|
||||
|
||||
fn button_pressed(&self, button: MouseButton) -> bool {
|
||||
self.buttons.get(&button).copied().unwrap_or_default()
|
||||
}
|
||||
|
||||
fn end_of_frame(&mut self) {
|
||||
self.mouse_delta = (0, 0).into();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut camera = Camera {
|
||||
transform: Transform {
|
||||
pos: Vec3::default(),
|
||||
rot: Quaternion::one(),
|
||||
},
|
||||
near_clip: 0.1,
|
||||
far_clip: 10.0,
|
||||
vertical_fov: 70.0,
|
||||
};
|
||||
|
||||
macro_rules! tri {
|
||||
($a:expr, $b:expr, $c:expr; $col:expr) => {
|
||||
Triangle {
|
||||
points: [$a.into(), $b.into(), $c.into()],
|
||||
color: $col.into(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let tris = vec![
|
||||
tri!((1, 1, 5), (1, -1, 5), (-1, -1, 5); Rgb::RED),
|
||||
tri!((1, 1, 5), (-1, -1, 5), (-1, 1, 5); Rgb::GREEN),
|
||||
tri!((-1, 1, 7), (-1, -1, 7), (1, -1, 7); Rgb::BLUE),
|
||||
tri!((-1, 1, 7), (1, -1, 7), (1, 1, 7); Rgb::YELLOW),
|
||||
];
|
||||
|
||||
let event_loop = EventLoop::new();
|
||||
let window = WindowBuilder::new().build(&event_loop).unwrap();
|
||||
let mut graphics_context = unsafe { GraphicsContext::new(window) }.unwrap();
|
||||
let mut graphics_buffer = GraphicsBuffer::new();
|
||||
let mut input_manager = InputManager::new();
|
||||
|
||||
let mut last_frame_start_time = Instant::now();
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
*control_flow = ControlFlow::Poll;
|
||||
|
||||
match event {
|
||||
Event::MainEventsCleared => {
|
||||
thread::sleep(
|
||||
Duration::from_secs_f32(1.0 / 30.0)
|
||||
.saturating_sub(Instant::now() - last_frame_start_time),
|
||||
);
|
||||
|
||||
let start_time = Instant::now();
|
||||
let delta_time = (start_time - last_frame_start_time).as_secs_f32();
|
||||
last_frame_start_time = start_time;
|
||||
|
||||
let (width, height) = {
|
||||
let size = graphics_context.window().inner_size();
|
||||
(size.width as u16, size.height as u16)
|
||||
};
|
||||
|
||||
graphics_buffer
|
||||
.resize_and_clear((width.into(), height.into()).into(), 0xbb_bb_bb.into());
|
||||
|
||||
if input_manager.key_pressed(VirtualKeyCode::A) {
|
||||
camera.transform.pos +=
|
||||
(Direction3::Left * 2.0 * delta_time).rotate_by(camera.transform.rot);
|
||||
}
|
||||
if input_manager.key_pressed(VirtualKeyCode::D) {
|
||||
camera.transform.pos +=
|
||||
(Direction3::Right * 2.0 * delta_time).rotate_by(camera.transform.rot);
|
||||
}
|
||||
if input_manager.key_pressed(VirtualKeyCode::W) {
|
||||
camera.transform.pos +=
|
||||
(Direction3::Forward * 2.0 * delta_time).rotate_by(camera.transform.rot);
|
||||
}
|
||||
if input_manager.key_pressed(VirtualKeyCode::S) {
|
||||
camera.transform.pos +=
|
||||
(Direction3::Backward * 2.0 * delta_time).rotate_by(camera.transform.rot);
|
||||
}
|
||||
if input_manager.modifier_keys.shift() {
|
||||
camera.transform.pos +=
|
||||
(Direction3::Down * 2.0 * delta_time).rotate_by(camera.transform.rot);
|
||||
}
|
||||
if input_manager.key_pressed(VirtualKeyCode::Space) {
|
||||
camera.transform.pos +=
|
||||
(Direction3::Up * 2.0 * delta_time).rotate_by(camera.transform.rot);
|
||||
}
|
||||
if input_manager.key_pressed(VirtualKeyCode::Q) {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
|
||||
if input_manager.button_pressed(MouseButton::Right) {
|
||||
camera
|
||||
.transform
|
||||
.rot
|
||||
.compose_in_place(Quaternion::rotation_around(
|
||||
Direction3::Up.into(),
|
||||
input_manager.mouse_delta.x / 1000.0,
|
||||
));
|
||||
|
||||
camera
|
||||
.transform
|
||||
.rot
|
||||
.compose_in_place(Quaternion::rotation_around(
|
||||
Vec3::from(Direction3::Right).rotate_by(camera.transform.rot),
|
||||
input_manager.mouse_delta.y / 1000.0,
|
||||
));
|
||||
}
|
||||
|
||||
for tri in &tris {
|
||||
let points = tri.points.map(|v| transform_point(camera, v));
|
||||
|
||||
graphics_buffer.draw_line(points[0], points[1], tri.color);
|
||||
graphics_buffer.draw_line(points[1], points[2], tri.color);
|
||||
graphics_buffer.draw_line(points[2], points[0], tri.color);
|
||||
}
|
||||
|
||||
graphics_context.set_buffer(&graphics_buffer, width, height);
|
||||
|
||||
// graphics_context
|
||||
// .window()
|
||||
// .set_cursor_position(LogicalPosition::new(400, 300))
|
||||
// .unwrap();
|
||||
// graphics_context.window().set_cursor_visible(false);
|
||||
|
||||
input_manager.end_of_frame();
|
||||
}
|
||||
Event::WindowEvent { window_id, event }
|
||||
if window_id == graphics_context.window().id() =>
|
||||
{
|
||||
match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
WindowEvent::KeyboardInput { input, .. } => {
|
||||
input_manager.handle_keyboard_input(input);
|
||||
}
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
input_manager.handle_mouse_movement(position);
|
||||
}
|
||||
WindowEvent::ModifiersChanged(state) => {
|
||||
input_manager.handle_modifiers_changed(state);
|
||||
}
|
||||
WindowEvent::MouseInput { state, button, .. } => {
|
||||
input_manager.handle_mouse_button((button, state));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn transform_point(camera: Camera, mut point: Vec3) -> Vec3 {
|
||||
point -= camera.transform.pos;
|
||||
let mut point = point.rotate_by(camera.transform.rot.inv());
|
||||
let z_scale = point.z.abs();
|
||||
if z_scale < (1.0 / 10000.0) {
|
||||
point.x = 0.0;
|
||||
point.y = 0.0;
|
||||
} else {
|
||||
let fov_scale = camera.vertical_fov.to_radians().tan();
|
||||
let scale = fov_scale * z_scale;
|
||||
point.x /= scale;
|
||||
point.y /= scale;
|
||||
}
|
||||
point.z -= camera.near_clip;
|
||||
point.z /= camera.far_clip - camera.near_clip;
|
||||
point
|
||||
}
|
316
src/quaternion.rs
Normal file
316
src/quaternion.rs
Normal file
|
@ -0,0 +1,316 @@
|
|||
use std::{
|
||||
fmt::{Debug, Display},
|
||||
ops::{Add, Div, Mul, Neg, Sub},
|
||||
};
|
||||
|
||||
use crate::vector3::Vec3;
|
||||
|
||||
/// A rotation, orientation, or location in 3d space.
|
||||
///
|
||||
/// Recomended reading: [Quaternion on Wikipedia](https://en.wikipedia.org/wiki/Quaternion), [Quaternions and spatial rotation on Wikipedia](https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation)
|
||||
///
|
||||
/// Most functions and operations on `Quaternion` will require the mathematical knowledge to understand, except for [`compose`], [`apply`], [`inv`], [`rotation_around`], and [`one`].
|
||||
///
|
||||
/// [`compose`]: Quaternion::compose
|
||||
/// [`apply`]: Quaternion::apply
|
||||
/// [`inv`]: Quaternion::inv
|
||||
/// [`rotation_around`]: Quaternion::rotation_around
|
||||
/// [`one`]: Quaternion::one
|
||||
#[derive(Copy, Clone, PartialEq, Default)]
|
||||
pub struct Quaternion {
|
||||
/// The real part of the quaternion.
|
||||
pub a: f32,
|
||||
/// The coefficient of the `i` part of the quaternion.
|
||||
pub b: f32,
|
||||
/// The coefficient of the `j` part of the quaternion.
|
||||
pub c: f32,
|
||||
/// The coefficient of the `k` part of the quaternion.
|
||||
pub d: f32,
|
||||
}
|
||||
|
||||
impl Debug for Quaternion {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} + {}i + {}j + {}k", self.a, self.b, self.c, self.d)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Quaternion {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Debug::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// Creating a Quaternion //
|
||||
///////////////////////////
|
||||
|
||||
impl Quaternion {
|
||||
/// Creates a scalar/real quaternion from the given value.
|
||||
pub fn scalar(a: f32) -> Self {
|
||||
Self {
|
||||
a,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a vector quaternion from the given [`Vec3`].
|
||||
pub fn vector(v: Vec3) -> Self {
|
||||
Self {
|
||||
b: v.x,
|
||||
c: v.y,
|
||||
d: v.z,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates the zero quaternion.
|
||||
pub fn zero() -> Self {
|
||||
Quaternion::default()
|
||||
}
|
||||
|
||||
/// Create a quaternion equal to 1, which is also the "no rotation" quaternion.
|
||||
pub fn one() -> Self {
|
||||
Self::scalar(1.0)
|
||||
}
|
||||
|
||||
/// Creates a quaternion from the given real and vector parts.
|
||||
pub fn new(a: f32, v: Vec3) -> Self {
|
||||
Self {
|
||||
a,
|
||||
b: v.x,
|
||||
c: v.y,
|
||||
d: v.z,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a quaternion from the given components
|
||||
pub fn from_components(a: f32, b: f32, c: f32, d: f32) -> Self {
|
||||
Self { a, b, c, d }
|
||||
}
|
||||
|
||||
/// Creates a quaternion representing a `theta` radians rotation around `axis`.
|
||||
pub fn rotation_around(axis: Vec3, theta: f32) -> Self {
|
||||
(theta / 2.0).cos() - Self::vector(axis.normalized()) * (theta / 2.0).sin()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for Quaternion {
|
||||
fn from(a: f32) -> Self {
|
||||
Self::scalar(a)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec3> for Quaternion {
|
||||
fn from(v: Vec3) -> Self {
|
||||
Self::vector(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, Vec3)> for Quaternion {
|
||||
fn from((a, v): (f32, Vec3)) -> Self {
|
||||
Self::new(a, v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, f32, f32, f32)> for Quaternion {
|
||||
fn from((a, b, c, d): (f32, f32, f32, f32)) -> Self {
|
||||
Self::from_components(a, b, c, d)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// Operations with itself //
|
||||
////////////////////////////
|
||||
|
||||
impl Quaternion {
|
||||
/// Gets the squared norm of the quaternion.
|
||||
pub fn sq_norm(self) -> f32 {
|
||||
self.a.powi(2) + self.b.powi(2) + self.c.powi(2) + self.d.powi(2)
|
||||
}
|
||||
|
||||
/// Gets the norm of the quaternion.
|
||||
pub fn norm(self) -> f32 {
|
||||
self.sq_norm().sqrt()
|
||||
}
|
||||
|
||||
/// Takes the conjugate of the quaternion.
|
||||
pub fn conjugate(self) -> Self {
|
||||
Self {
|
||||
a: self.a,
|
||||
b: -self.b,
|
||||
c: -self.c,
|
||||
d: -self.d,
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes the reciprocal of the quaternion.
|
||||
pub fn inv(self) -> Self {
|
||||
self.conjugate() / self.sq_norm()
|
||||
}
|
||||
|
||||
/// Gets the versor/unit quaternion of the quaternion.
|
||||
pub fn versor(self) -> Self {
|
||||
self / self.norm()
|
||||
}
|
||||
|
||||
/// Determines if the quaternion is a versor/unit quaternion.
|
||||
pub fn is_versor(self) -> bool {
|
||||
(self.sq_norm() - 1.0).abs() < f32::EPSILON
|
||||
}
|
||||
|
||||
/// Conjugates `self` by `rhs`, the operation `rhs * self * rhs.inv()`.
|
||||
pub fn conjugate_by(self, rhs: Self) -> Self {
|
||||
rhs * self * rhs.inv()
|
||||
}
|
||||
|
||||
/// Gets the scalar part of this quaternion.
|
||||
pub fn scalar_part(self) -> f32 {
|
||||
self.a
|
||||
}
|
||||
|
||||
/// Gets the vector part of this quaternion.
|
||||
pub fn vector_part(self) -> Vec3 {
|
||||
(self.b, self.c, self.d).into()
|
||||
}
|
||||
|
||||
/// Creates a rotation which is `self` followed by `rhs`.
|
||||
///
|
||||
/// Same as `rhs * self`, in that order.
|
||||
pub fn compose(self, rhs: Self) -> Self {
|
||||
rhs * self
|
||||
}
|
||||
|
||||
/// Composes `rhs` with `self`, in place.
|
||||
///
|
||||
/// See also: [`Quaternion::compose`]
|
||||
pub fn compose_in_place(&mut self, rhs: Self) {
|
||||
*self = self.compose(rhs);
|
||||
}
|
||||
|
||||
/// Applies this rotation to a point in space.
|
||||
///
|
||||
/// Same as `Quaternion::vector(v).conjugate_by(self).vector_part()`
|
||||
pub fn apply(self, v: Vec3) -> Vec3 {
|
||||
Self::vector(v).conjugate_by(self).vector_part()
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Quaternion {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
Self {
|
||||
a: -self.a,
|
||||
b: -self.b,
|
||||
c: -self.c,
|
||||
d: -self.d,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Quaternion {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
a: self.a + rhs.a,
|
||||
b: self.b + rhs.b,
|
||||
c: self.c + rhs.c,
|
||||
d: self.d + rhs.d,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Quaternion {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
self + -rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Quaternion {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
// https://en.wikipedia.org/wiki/Quaternion#Hamilton_product
|
||||
Self {
|
||||
a: (self.a * rhs.a) - (self.b * rhs.b) - (self.c * rhs.c) - (self.d * rhs.d),
|
||||
b: (self.a * rhs.b) + (self.b * rhs.a) + (self.c * rhs.d) - (self.d * rhs.c),
|
||||
c: (self.a * rhs.c) - (self.b * rhs.d) + (self.c * rhs.a) + (self.d * rhs.b),
|
||||
d: (self.a * rhs.d) + (self.b * rhs.c) - (self.c * rhs.b) + (self.d * rhs.a),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// `impl Div for Quaternion` is explicitly left out, since it is ambiguous.
|
||||
|
||||
//////////////////////////////////
|
||||
// Operations with real numbers //
|
||||
//////////////////////////////////
|
||||
|
||||
impl Add<f32> for Quaternion {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: f32) -> Self::Output {
|
||||
Self {
|
||||
a: self.a + rhs,
|
||||
..self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Quaternion> for f32 {
|
||||
type Output = Quaternion;
|
||||
|
||||
fn add(self, rhs: Quaternion) -> Self::Output {
|
||||
rhs + self
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<f32> for Quaternion {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: f32) -> Self::Output {
|
||||
self + -rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<Quaternion> for f32 {
|
||||
type Output = Quaternion;
|
||||
|
||||
fn sub(self, rhs: Quaternion) -> Self::Output {
|
||||
-rhs + self
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Quaternion {
|
||||
type Output = Quaternion;
|
||||
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
Self {
|
||||
a: self.a * rhs,
|
||||
b: self.b * rhs,
|
||||
c: self.c * rhs,
|
||||
d: self.d * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Quaternion> for f32 {
|
||||
type Output = Quaternion;
|
||||
|
||||
fn mul(self, rhs: Quaternion) -> Self::Output {
|
||||
rhs * self
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<f32> for Quaternion {
|
||||
type Output = Quaternion;
|
||||
|
||||
fn div(self, rhs: f32) -> Self::Output {
|
||||
self * (1.0 / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
// `impl Div<Quaternion> for f32` is explicitly left out, since it makes no sense
|
96
src/rgb.rs
Normal file
96
src/rgb.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
use core::slice;
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
#[repr(transparent)]
|
||||
/// An RGB (red green blue) color.
|
||||
pub struct Rgb(u32);
|
||||
|
||||
impl Rgb {
|
||||
/// Red, or `Rgb::new(255, 0, 0)`.
|
||||
pub const RED: Self = Self::new_u32(0xff_00_00);
|
||||
/// Green, or `Rgb::new(0, 255, 0)`.
|
||||
pub const GREEN: Self = Self::new_u32(0x00_ff_00);
|
||||
/// Blue, or `Rgb::new(0, 0, 255)`.
|
||||
pub const BLUE: Self = Self::new_u32(0x00_00_ff);
|
||||
/// Yellow, or `Rgb::new(255, 255, 0)`.
|
||||
pub const YELLOW: Self = Self::new_u32(0xff_ff_00);
|
||||
/// Cyan, or `Rgb::new(0, 255, 255)`.
|
||||
pub const CYAN: Self = Self::new_u32(0x00_ff_ff);
|
||||
/// Magenta, or `Rgb::new(255, 0, 255)`.
|
||||
pub const MAGENTA: Self = Self::new_u32(0xff_00_ff);
|
||||
/// Black, or `Rgb::new(0, 0, 0)`.
|
||||
pub const BLACK: Self = Self::new_u32(0x00_00_00);
|
||||
/// White, or `Rgb::new(255, 255, 255)`.
|
||||
pub const WHITE: Self = Self::new_u32(0xff_ff_ff);
|
||||
|
||||
/// Creates a new color from the given red, green, and blue values.
|
||||
pub const fn new(r: u8, g: u8, b: u8) -> Self {
|
||||
Self(((r as u32) << 16) | ((g as u32) << 8) | (b as u32))
|
||||
}
|
||||
|
||||
/// Creates a new color from the given `u32`, in the following format:
|
||||
///
|
||||
/// `00000000_RRRRRRRR_GGGGGGGG_BBBBBBBB`
|
||||
pub const fn new_u32(v: u32) -> Self {
|
||||
Self(v & 0xff_ff_ff)
|
||||
}
|
||||
|
||||
/// Gets the red value of this color.
|
||||
pub fn red(self) -> u8 {
|
||||
#![allow(clippy::cast_possible_truncation)]
|
||||
(self.0 >> 16) as u8
|
||||
}
|
||||
|
||||
/// Gets the green value of this color.
|
||||
pub fn green(self) -> u8 {
|
||||
((self.0 >> 8) & 0xff) as u8
|
||||
}
|
||||
|
||||
/// Gets the blue value of this color.
|
||||
pub fn blue(self) -> u8 {
|
||||
(self.0 & 0xff) as u8
|
||||
}
|
||||
|
||||
/// Sets the red value of this color.
|
||||
pub fn set_red(&mut self, r: u8) {
|
||||
*self = Self((self.0 & 0x00_ff_ff) | (u32::from(r) << 16));
|
||||
}
|
||||
|
||||
/// Sets the green value of this color.
|
||||
pub fn set_green(&mut self, r: u8) {
|
||||
*self = Self((self.0 & 0xff_00_ff) | (u32::from(r) << 8));
|
||||
}
|
||||
|
||||
/// Sets the blue value of this color.
|
||||
pub fn set_blue(&mut self, r: u8) {
|
||||
*self = Self((self.0 & 0xff_ff_00) | u32::from(r));
|
||||
}
|
||||
|
||||
/// Reinterprets an `Rgb` slice as a `u32` slice.
|
||||
pub fn as_u32_slice(slice: &[Rgb]) -> &[u32] {
|
||||
unsafe { slice::from_raw_parts((slice as *const [Rgb]).cast(), slice.len()) }
|
||||
}
|
||||
|
||||
/// Takes the inner `u32` out of an `Rgb`.
|
||||
pub fn into_inner(self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(u8, u8, u8)> for Rgb {
|
||||
fn from((r, g, b): (u8, u8, u8)) -> Self {
|
||||
Self::new(r, g, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Rgb {
|
||||
fn from(v: u32) -> Self {
|
||||
Self::new_u32(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rgb> for u32 {
|
||||
fn from(v: Rgb) -> Self {
|
||||
v.into_inner()
|
||||
}
|
||||
}
|
478
src/vector2.rs
Normal file
478
src/vector2.rs
Normal file
|
@ -0,0 +1,478 @@
|
|||
use std::{
|
||||
fmt::Debug,
|
||||
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
|
||||
};
|
||||
|
||||
use crate::vector3::{Vec3, Vec3Int};
|
||||
|
||||
// Direction
|
||||
/// A cardinal direction in a 2d plane.
|
||||
///
|
||||
/// Conversions to a [`Vec2`] or [`Vec2Int`] assume that East is positive-x and South is positive-y.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum Direction2 {
|
||||
/// The positive y-axis, or Vec2::from((0, 1))
|
||||
Up,
|
||||
/// The negative y-axis, or Vec2::from((0, -1))
|
||||
Down,
|
||||
/// The negative x-axis, or Vec2::from((-1, 0))
|
||||
Left,
|
||||
/// The positive x-axis, or Vec2::from((1, 0))
|
||||
Right,
|
||||
}
|
||||
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
impl Direction2 {
|
||||
/// Flips this `Direction` around both the x- and y-axes.
|
||||
pub fn flipped(self) -> Self {
|
||||
self.flipped_x().flipped_y()
|
||||
}
|
||||
|
||||
/// Flips this `Direction` around the x-axis.
|
||||
pub fn flipped_x(self) -> Self {
|
||||
use Direction2::*;
|
||||
match self {
|
||||
Left => Right,
|
||||
Right => Left,
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
|
||||
/// Flips this `Direction` around the y-axis.
|
||||
pub fn flipped_y(self) -> Self {
|
||||
use Direction2::*;
|
||||
match self {
|
||||
Up => Down,
|
||||
Down => Up,
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ...and related op impls
|
||||
impl Neg for Direction2 {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
self.flipped()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
impl From<Direction2> for Vec2 {
|
||||
fn from(v: Direction2) -> Self {
|
||||
use Direction2::*;
|
||||
match v {
|
||||
Up => (0.0, 1.0).into(),
|
||||
Down => (0.0, -1.0).into(),
|
||||
Left => (-1.0, 0.0).into(),
|
||||
Right => (1.0, 0.0).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
impl From<Direction2> for Vec2Int {
|
||||
fn from(v: Direction2) -> Self {
|
||||
use Direction2::*;
|
||||
match v {
|
||||
Up => (0, 1).into(),
|
||||
Down => (0, -1).into(),
|
||||
Left => (-1, 0).into(),
|
||||
Right => (1, 0).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Direction2 {
|
||||
type Output = Vec2;
|
||||
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
Vec2::from(self) * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<i32> for Direction2 {
|
||||
type Output = Vec2Int;
|
||||
|
||||
fn mul(self, rhs: i32) -> Self::Output {
|
||||
Vec2Int::from(self) * rhs
|
||||
}
|
||||
}
|
||||
|
||||
// Vec2
|
||||
/// A set of 2 [`f32`]s representing a location or direction in the 2d plane.
|
||||
#[derive(Clone, Copy, Default, PartialEq)]
|
||||
pub struct Vec2 {
|
||||
/// The x component of the vector.
|
||||
pub x: f32,
|
||||
/// The y component of the vector.
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
impl Debug for Vec2 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("Vec2").field(&self.x).field(&self.y).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Vec2 {
|
||||
/// Creates a new `Vec2` with the given x- and y-values.
|
||||
///
|
||||
/// It is often simpler, and preferred, to just write `(x, y).into()`.
|
||||
pub const fn new(x: f32, y: f32) -> Vec2 {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
/// Gets the squared magnitude of the vector.
|
||||
///
|
||||
/// Useful for comparisons as it is faster to calculate than `magnitude`.
|
||||
pub fn sq_magnitude(self) -> f32 {
|
||||
self.x * self.x + self.y * self.y
|
||||
}
|
||||
|
||||
/// Gets the magnitude of the vector.
|
||||
pub fn magnitude(self) -> f32 {
|
||||
self.sq_magnitude().sqrt()
|
||||
}
|
||||
|
||||
/// Gets the squared distance from this vector to `rhs`.
|
||||
///
|
||||
/// Useful for comparisons as it is faster to calculate than `dist`.
|
||||
pub fn sq_dist(self, rhs: Self) -> f32 {
|
||||
(self - rhs).sq_magnitude()
|
||||
}
|
||||
|
||||
/// Gets the distance from this vector to `rhs`.
|
||||
pub fn dist(self, rhs: Self) -> f32 {
|
||||
(self - rhs).magnitude()
|
||||
}
|
||||
|
||||
/// Normalizes the vector, making its magnitude `1`.
|
||||
pub fn normalized(self) -> Self {
|
||||
self / self.magnitude()
|
||||
}
|
||||
|
||||
/// Rounds the vector to a [`Vec2Int`].
|
||||
///
|
||||
/// This uses `as i32` under the hood, and as such comes with all the same unfortunate edge cases. Beware.
|
||||
pub fn rounded(self) -> Vec2Int {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
Vec2Int {
|
||||
x: self.x as i32,
|
||||
y: self.y as i32,
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms this vector into a [`Vec3`] with a z-coordinate of 0.
|
||||
pub fn into_vec2(self) -> Vec3 {
|
||||
Vec3 {
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
z: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(i32, i32)> for Vec2 {
|
||||
fn from(v: (i32, i32)) -> Self {
|
||||
Vec2Int::from(v).to_float()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, f32)> for Vec2 {
|
||||
fn from(v: (f32, f32)) -> Self {
|
||||
Self { x: v.0, y: v.1 }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec2> for (f32, f32) {
|
||||
fn from(v: Vec2) -> Self {
|
||||
(v.x, v.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<(i32, i32)> for Vec2 {
|
||||
fn eq(&self, other: &(i32, i32)) -> bool {
|
||||
self == &Self::from(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<(f32, f32)> for Vec2 {
|
||||
fn eq(&self, other: &(f32, f32)) -> bool {
|
||||
self == &Self::from(*other)
|
||||
}
|
||||
}
|
||||
|
||||
// ...and related op impls
|
||||
impl Neg for Vec2 {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
self * -1.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Vec2 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Direction2> for Vec2 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Direction2) -> Self::Output {
|
||||
self + Self::from(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddAssign<T> for Vec2
|
||||
where
|
||||
Vec2: Add<T, Output = Self>,
|
||||
{
|
||||
fn add_assign(&mut self, rhs: T) {
|
||||
*self = *self + rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Sub<T> for Vec2
|
||||
where
|
||||
Vec2: Add<T, Output = Self>,
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: T) -> Self::Output {
|
||||
-(-self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SubAssign<T> for Vec2
|
||||
where
|
||||
Vec2: Sub<T, Output = Self>,
|
||||
{
|
||||
fn sub_assign(&mut self, rhs: T) {
|
||||
*self = *self - rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Vec2 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x * rhs,
|
||||
y: self.y * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<f32> for Vec2 {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, rhs: f32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x / rhs,
|
||||
y: self.y / rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<f32> for Vec2 {
|
||||
fn mul_assign(&mut self, rhs: f32) {
|
||||
*self = *self * rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<f32> for Vec2 {
|
||||
fn div_assign(&mut self, rhs: f32) {
|
||||
*self = *self / rhs;
|
||||
}
|
||||
}
|
||||
|
||||
// Vec2Int
|
||||
/// A set of 2 [`i32`]s representing a location or direction in the 2d plane.
|
||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
|
||||
pub struct Vec2Int {
|
||||
/// The x component of the vector.
|
||||
pub x: i32,
|
||||
/// The y component of the vector.
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
impl Debug for Vec2Int {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("Vec2Int")
|
||||
.field(&self.x)
|
||||
.field(&self.y)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Vec2Int {
|
||||
/// Creates a new `Vec2` with the given x- and y-values.
|
||||
///
|
||||
/// It is often simpler, and preferred, to just write `(x, y).into()`.
|
||||
pub const fn new(x: i32, y: i32) -> Vec2Int {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
/// Gets the squared magnitude of the vector.
|
||||
///
|
||||
/// Useful for comparisons as it is faster to calculate than `magnitude`.
|
||||
pub fn sq_magnitude(self) -> i32 {
|
||||
self.x * self.x + self.y * self.y
|
||||
}
|
||||
|
||||
/// Gets the magnitude of the vector.
|
||||
pub fn magnitude(self) -> f32 {
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
(self.sq_magnitude() as f32).sqrt()
|
||||
}
|
||||
|
||||
/// Gets the squared distance from this vector to `rhs`.
|
||||
///
|
||||
/// Useful for comparisons as it is faster to calculate than `dist`.
|
||||
pub fn sq_dist(self, rhs: Self) -> i32 {
|
||||
(self - rhs).sq_magnitude()
|
||||
}
|
||||
|
||||
/// Gets the distance from this vector to `rhs`.
|
||||
pub fn dist(self, rhs: Self) -> f32 {
|
||||
(self - rhs).magnitude()
|
||||
}
|
||||
|
||||
/// Casts this vector to a [`Vec2`].
|
||||
///
|
||||
/// This uses `as f32` under the hood, and as such comes with all the same unfortunate edge cases. Beware.
|
||||
pub fn to_float(self) -> Vec2 {
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
Vec2 {
|
||||
x: self.x as f32,
|
||||
y: self.y as f32,
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms this vector into a [`Vec3Int`] with a z-coordinate of 0.
|
||||
pub fn into_vec2(self) -> Vec3Int {
|
||||
Vec3Int {
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
z: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(i32, i32)> for Vec2Int {
|
||||
fn from(v: (i32, i32)) -> Self {
|
||||
Self { x: v.0, y: v.1 }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec2Int> for (i32, i32) {
|
||||
fn from(v: Vec2Int) -> Self {
|
||||
(v.x, v.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<(i32, i32)> for Vec2Int {
|
||||
fn eq(&self, other: &(i32, i32)) -> bool {
|
||||
self == &Self::from(*other)
|
||||
}
|
||||
}
|
||||
|
||||
// ...and related op impls
|
||||
impl Neg for Vec2Int {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
self * -1
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Vec2Int {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Direction2> for Vec2Int {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Direction2) -> Self::Output {
|
||||
self + Self::from(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddAssign<T> for Vec2Int
|
||||
where
|
||||
Vec2Int: Add<T, Output = Self>,
|
||||
{
|
||||
fn add_assign(&mut self, rhs: T) {
|
||||
*self = *self + rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Sub<T> for Vec2Int
|
||||
where
|
||||
Vec2Int: Add<T, Output = Self>,
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: T) -> Self::Output {
|
||||
-(-self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SubAssign<T> for Vec2Int
|
||||
where
|
||||
Vec2Int: Sub<T, Output = Self>,
|
||||
{
|
||||
fn sub_assign(&mut self, rhs: T) {
|
||||
*self = *self - rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<i32> for Vec2Int {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: i32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x * rhs,
|
||||
y: self.y * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<i32> for Vec2Int {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, rhs: i32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x / rhs,
|
||||
y: self.y / rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<i32> for Vec2Int {
|
||||
fn mul_assign(&mut self, rhs: i32) {
|
||||
*self = *self * rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<i32> for Vec2Int {
|
||||
fn div_assign(&mut self, rhs: i32) {
|
||||
*self = *self / rhs;
|
||||
}
|
||||
}
|
527
src/vector3.rs
Normal file
527
src/vector3.rs
Normal file
|
@ -0,0 +1,527 @@
|
|||
use std::{
|
||||
fmt::Debug,
|
||||
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
quaternion::Quaternion,
|
||||
vector2::{Vec2, Vec2Int},
|
||||
};
|
||||
|
||||
// Direction
|
||||
/// A cardinal direction in a 3d plane.
|
||||
///
|
||||
/// Conversions to a [`Vec3`] or [`Vec3Int`] assume that East is positive-x and South is positive-y.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum Direction3 {
|
||||
/// The positive y-axis, or Vec3::from((0, 1, 0))
|
||||
Up,
|
||||
/// The negative y-axis, or Vec3::from((0, -1, 0))
|
||||
Down,
|
||||
/// The negative x-axis, or Vec3::from((-1, 0, 0))
|
||||
Left,
|
||||
/// The positive x-axis, or Vec3::from((1, 0, 0))
|
||||
Right,
|
||||
/// The positive z-axis, or Vec3::from((0, 0, 1))
|
||||
Forward,
|
||||
/// The negative z-axis, or Vec3::from((0, 0, -1))
|
||||
Backward,
|
||||
}
|
||||
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
impl Direction3 {
|
||||
/// Flips this `Direction` around the x-, y-, and z-axes.
|
||||
pub fn flipped(self) -> Self {
|
||||
self.flipped_x().flipped_y().flipped_z()
|
||||
}
|
||||
|
||||
/// Flips this `Direction` around the x-axis.
|
||||
pub fn flipped_x(self) -> Self {
|
||||
use Direction3::*;
|
||||
match self {
|
||||
Left => Right,
|
||||
Right => Left,
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
|
||||
/// Flips this `Direction` around the y-axis.
|
||||
pub fn flipped_y(self) -> Self {
|
||||
use Direction3::*;
|
||||
match self {
|
||||
Up => Down,
|
||||
Down => Up,
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
|
||||
/// Flips this `Direction` around the z-axis.
|
||||
pub fn flipped_z(self) -> Self {
|
||||
use Direction3::*;
|
||||
match self {
|
||||
Forward => Backward,
|
||||
Backward => Forward,
|
||||
v => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ...and related op impls
|
||||
impl Neg for Direction3 {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
self.flipped()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
impl From<Direction3> for Vec3 {
|
||||
fn from(v: Direction3) -> Self {
|
||||
use Direction3::*;
|
||||
match v {
|
||||
Up => (0.0, 1.0, 0.0).into(),
|
||||
Down => (0.0, -1.0, 0.0).into(),
|
||||
Left => (-1.0, 0.0, 0.0).into(),
|
||||
Right => (1.0, 0.0, 0.0).into(),
|
||||
Forward => (0.0, 0.0, 1.0).into(),
|
||||
Backward => (0.0, 0.0, -1.0).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
impl From<Direction3> for Vec3Int {
|
||||
fn from(v: Direction3) -> Self {
|
||||
use Direction3::*;
|
||||
match v {
|
||||
Up => (0, 1, 0).into(),
|
||||
Down => (0, -1, 0).into(),
|
||||
Left => (-1, 0, 0).into(),
|
||||
Right => (1, 0, 0).into(),
|
||||
Forward => (0, 0, 1).into(),
|
||||
Backward => (0, 0, -1).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Direction3 {
|
||||
type Output = Vec3;
|
||||
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
Vec3::from(self) * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<i32> for Direction3 {
|
||||
type Output = Vec3Int;
|
||||
|
||||
fn mul(self, rhs: i32) -> Self::Output {
|
||||
Vec3Int::from(self) * rhs
|
||||
}
|
||||
}
|
||||
|
||||
// Vec3
|
||||
/// A set of 3 [`f32`]s representing a location or direction in the 3d plane.
|
||||
#[derive(Clone, Copy, Default, PartialEq)]
|
||||
pub struct Vec3 {
|
||||
/// The x component of the vector.
|
||||
pub x: f32,
|
||||
/// The y component of the vector.
|
||||
pub y: f32,
|
||||
/// The z component of the vector.
|
||||
pub z: f32,
|
||||
}
|
||||
|
||||
impl Debug for Vec3 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("Vec3")
|
||||
.field(&self.x)
|
||||
.field(&self.y)
|
||||
.field(&self.z)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Vec3 {
|
||||
/// Creates a new `Vec3` with the given x-, y-, and z-values.
|
||||
///
|
||||
/// It is often simpler, and preferred, to just write `(x, y, z).into()`.
|
||||
pub const fn new(x: f32, y: f32, z: f32) -> Vec3 {
|
||||
Self { x, y, z }
|
||||
}
|
||||
|
||||
/// Gets the squared magnitude of the vector.
|
||||
///
|
||||
/// Useful for comparisons as it is faster to calculate than `magnitude`.
|
||||
pub fn sq_magnitude(self) -> f32 {
|
||||
self.x * self.x + self.y * self.y + self.z * self.z
|
||||
}
|
||||
|
||||
/// Gets the magnitude of the vector.
|
||||
pub fn magnitude(self) -> f32 {
|
||||
self.sq_magnitude().sqrt()
|
||||
}
|
||||
|
||||
/// Gets the squared distance from this vector to `rhs`.
|
||||
///
|
||||
/// Useful for comparisons as it is faster to calculate than `dist`.
|
||||
pub fn sq_dist(self, rhs: Self) -> f32 {
|
||||
(self - rhs).sq_magnitude()
|
||||
}
|
||||
|
||||
/// Gets the distance from this vector to `rhs`.
|
||||
pub fn dist(self, rhs: Self) -> f32 {
|
||||
(self - rhs).magnitude()
|
||||
}
|
||||
|
||||
/// Normalizes the vector, making its magnitude `1`.
|
||||
pub fn normalized(self) -> Self {
|
||||
self / self.magnitude()
|
||||
}
|
||||
|
||||
/// Rounds the vector to a [`Vec3Int`].
|
||||
///
|
||||
/// This uses `as i32` under the hood, and as such comes with all the same unfortunate edge cases. Beware.
|
||||
pub fn rounded(self) -> Vec3Int {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
Vec3Int {
|
||||
x: self.x as i32,
|
||||
y: self.y as i32,
|
||||
z: self.z as i32,
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms this vector into a [`Vec2`], dropping the z-coordinate.
|
||||
pub fn into_vec2(self) -> Vec2 {
|
||||
Vec2 {
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
}
|
||||
}
|
||||
|
||||
/// Rotates this vector by the given quaternion.
|
||||
pub fn rotate_by(self, rhs: Quaternion) -> Self {
|
||||
rhs.apply(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(i32, i32, i32)> for Vec3 {
|
||||
fn from(v: (i32, i32, i32)) -> Self {
|
||||
Vec3Int::from(v).into_float()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, f32, f32)> for Vec3 {
|
||||
fn from(v: (f32, f32, f32)) -> Self {
|
||||
Self {
|
||||
x: v.0,
|
||||
y: v.1,
|
||||
z: v.2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec3> for (f32, f32, f32) {
|
||||
fn from(v: Vec3) -> Self {
|
||||
(v.x, v.y, v.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<(i32, i32, i32)> for Vec3 {
|
||||
fn eq(&self, other: &(i32, i32, i32)) -> bool {
|
||||
self == &Self::from(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<(f32, f32, f32)> for Vec3 {
|
||||
fn eq(&self, other: &(f32, f32, f32)) -> bool {
|
||||
self == &Self::from(*other)
|
||||
}
|
||||
}
|
||||
|
||||
// ...and related op impls
|
||||
impl Neg for Vec3 {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
self * -1.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Vec3 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
z: self.z + rhs.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Direction3> for Vec3 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Direction3) -> Self::Output {
|
||||
self + Self::from(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddAssign<T> for Vec3
|
||||
where
|
||||
Vec3: Add<T, Output = Self>,
|
||||
{
|
||||
fn add_assign(&mut self, rhs: T) {
|
||||
*self = *self + rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Sub<T> for Vec3
|
||||
where
|
||||
Vec3: Add<T, Output = Self>,
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: T) -> Self::Output {
|
||||
-(-self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SubAssign<T> for Vec3
|
||||
where
|
||||
Vec3: Sub<T, Output = Self>,
|
||||
{
|
||||
fn sub_assign(&mut self, rhs: T) {
|
||||
*self = *self - rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f32> for Vec3 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x * rhs,
|
||||
y: self.y * rhs,
|
||||
z: self.z * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<f32> for Vec3 {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, rhs: f32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x / rhs,
|
||||
y: self.y / rhs,
|
||||
z: self.z / rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<f32> for Vec3 {
|
||||
fn mul_assign(&mut self, rhs: f32) {
|
||||
*self = *self * rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<f32> for Vec3 {
|
||||
fn div_assign(&mut self, rhs: f32) {
|
||||
*self = *self / rhs;
|
||||
}
|
||||
}
|
||||
|
||||
// Vec3Int
|
||||
/// A set of 3 [`i32`]s representing a location or direction in the 3d plane.
|
||||
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
|
||||
pub struct Vec3Int {
|
||||
/// The x component of the vector.
|
||||
pub x: i32,
|
||||
/// The y component of the vector.
|
||||
pub y: i32,
|
||||
/// The z component of the vector.
|
||||
pub z: i32,
|
||||
}
|
||||
|
||||
impl Debug for Vec3Int {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("Vec3Int")
|
||||
.field(&self.x)
|
||||
.field(&self.y)
|
||||
.field(&self.z)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Vec3Int {
|
||||
/// Creates a new `Vec3Int` with the given x-, y-, and z-values.
|
||||
///
|
||||
/// It is often simpler, and preferred, to just write `(x, y, z).into()`.
|
||||
pub const fn new(x: i32, y: i32, z: i32) -> Vec3Int {
|
||||
Self { x, y, z }
|
||||
}
|
||||
|
||||
/// Gets the squared magnitude of the vector.
|
||||
///
|
||||
/// Useful for comparisons as it is faster to calculate than `magnitude`.
|
||||
pub fn sq_magnitude(self) -> i32 {
|
||||
self.x * self.x + self.y * self.y + self.z * self.z
|
||||
}
|
||||
|
||||
/// Gets the magnitude of the vector.
|
||||
pub fn magnitude(self) -> f32 {
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
(self.sq_magnitude() as f32).sqrt()
|
||||
}
|
||||
|
||||
/// Gets the squared distance from this vector to `rhs`.
|
||||
///
|
||||
/// Useful for comparisons as it is faster to calculate than `dist`.
|
||||
pub fn sq_dist(self, rhs: Self) -> i32 {
|
||||
(self - rhs).sq_magnitude()
|
||||
}
|
||||
|
||||
/// Gets the distance from this vector to `rhs`.
|
||||
pub fn dist(self, rhs: Self) -> f32 {
|
||||
(self - rhs).magnitude()
|
||||
}
|
||||
|
||||
/// Casts this vector to a [`Vec3`].
|
||||
///
|
||||
/// This uses `as f32` under the hood, and as such comes with all the same unfortunate edge cases. Beware.
|
||||
pub fn into_float(self) -> Vec3 {
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
Vec3 {
|
||||
x: self.x as f32,
|
||||
y: self.y as f32,
|
||||
z: self.z as f32,
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms this vector into a [`Vec2Int`], dropping the z-coordinate.
|
||||
pub fn into_vec2(self) -> Vec2Int {
|
||||
Vec2Int {
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(i32, i32, i32)> for Vec3Int {
|
||||
fn from(v: (i32, i32, i32)) -> Self {
|
||||
Self {
|
||||
x: v.0,
|
||||
y: v.1,
|
||||
z: v.2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec3Int> for (i32, i32, i32) {
|
||||
fn from(v: Vec3Int) -> Self {
|
||||
(v.x, v.y, v.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<(i32, i32, i32)> for Vec3Int {
|
||||
fn eq(&self, other: &(i32, i32, i32)) -> bool {
|
||||
self == &Self::from(*other)
|
||||
}
|
||||
}
|
||||
|
||||
// ...and related op impls
|
||||
impl Neg for Vec3Int {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
self * -1
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Vec3Int {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
z: self.z + rhs.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Direction3> for Vec3Int {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Direction3) -> Self::Output {
|
||||
self + Self::from(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddAssign<T> for Vec3Int
|
||||
where
|
||||
Vec3Int: Add<T, Output = Self>,
|
||||
{
|
||||
fn add_assign(&mut self, rhs: T) {
|
||||
*self = *self + rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Sub<T> for Vec3Int
|
||||
where
|
||||
Vec3Int: Add<T, Output = Self>,
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: T) -> Self::Output {
|
||||
-(-self + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SubAssign<T> for Vec3Int
|
||||
where
|
||||
Vec3Int: Sub<T, Output = Self>,
|
||||
{
|
||||
fn sub_assign(&mut self, rhs: T) {
|
||||
*self = *self - rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<i32> for Vec3Int {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: i32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x * rhs,
|
||||
y: self.y * rhs,
|
||||
z: self.z * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<i32> for Vec3Int {
|
||||
type Output = Self;
|
||||
|
||||
fn div(self, rhs: i32) -> Self::Output {
|
||||
Self {
|
||||
x: self.x / rhs,
|
||||
y: self.y / rhs,
|
||||
z: self.z / rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<i32> for Vec3Int {
|
||||
fn mul_assign(&mut self, rhs: i32) {
|
||||
*self = *self * rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign<i32> for Vec3Int {
|
||||
fn div_assign(&mut self, rhs: i32) {
|
||||
*self = *self / rhs;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue