Compare commits
573 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fee135d82e | |||
| e8c7abf925 | |||
| 6ae3e37172 | |||
| afc613fcc0 | |||
| d7a721f62e | |||
| 5aae9d6842 | |||
| 3e4598313d | |||
| d231139b83 | |||
| 9c4e2a3319 | |||
| 7597d95778 | |||
| 5aa0e2e949 | |||
| b7b1154f29 | |||
| b10e26e6ba | |||
| ba23fee243 | |||
| 32e0f9e636 | |||
| 63b4327c91 | |||
| dbad87de0f | |||
| 8dd044fa1e | |||
| c25a3da196 | |||
| d64d60cfcd | |||
| 2ef25b0ce8 | |||
|
|
775949887a | ||
| 510e3d7d1c | |||
|
|
72404f2159 | ||
|
|
0e792c9b9c | ||
|
|
7e9151084e | ||
|
|
43c8f2e6a5 | ||
| b0fd8d42f4 | |||
| b5229f72d5 | |||
| d5233dd00b | |||
| bd1d437d7d | |||
| f67ad8ef42 | |||
| acc24f8438 | |||
| 8bccbdb620 | |||
| 91a96fb97a | |||
| 5fcac74a25 | |||
| d2cf62bdbe | |||
| 2a2832c75f | |||
| 26fda5402e | |||
| 906ddd75d4 | |||
| 68505a77ae | |||
| d6746f6243 | |||
| ee2f084e0b | |||
| 9bd42d9c8c | |||
| 47d82fe083 | |||
|
|
217fc108c2 | ||
|
|
9c1c4fe6f3 | ||
| 958156e6b7 | |||
|
|
450f3a3ab0 | ||
|
|
8159686658 | ||
| 9fc31d03e5 | |||
| 6017d40579 | |||
| 618d4aa1c0 | |||
| 8366c48965 | |||
| d2e418c50b | |||
| eae10d92ca | |||
| 3f940c8e35 | |||
| 0846022f8a | |||
| 8812abdf33 | |||
| d56d05f01e | |||
| aabdebbbbe | |||
| 2b75b33d60 | |||
| 9a3f5abb7c | |||
| be1049db93 | |||
| 525b273a84 | |||
| 77adc0ea8a | |||
| 83f17892d6 | |||
| 26fd8e158a | |||
| 2af77d30d4 | |||
| 368272b1e8 | |||
|
|
0ca471ed4f | ||
|
|
f0145ec68e | ||
| 771e1e68fe | |||
| ffcf448a07 | |||
| 00fcdc86bc | |||
| 2c11c5ce1a | |||
| fdb2ad099a | |||
| 88ce5e6b8c | |||
| 29da13d244 | |||
| d16984a8b2 | |||
| d935caf1a4 | |||
| 897484bea1 | |||
| a03620c18f | |||
|
|
4a8e7e85ce | ||
| 1499ac3213 | |||
|
|
f3a6a1a3ae | ||
| c312ccad0c | |||
| 939be67643 | |||
| 43a063807d | |||
| 4fd7f8efa6 | |||
| 52ca23383d | |||
| ce21c217f1 | |||
| 09b64cc702 | |||
| d085681efe | |||
|
|
2f7746caeb | ||
| 94ee8751af | |||
|
|
82b9b671f6 | ||
| 082b5f69b8 | |||
|
|
735a565446 | ||
| 852bf5c56f | |||
|
|
de5c8bc84d | ||
| 35d9de1550 | |||
|
|
201d8f5547 | ||
| 5a7b9d2338 | |||
| 3d67827704 | |||
| 45a37eb413 | |||
| 90c4ea2036 | |||
| e10cbf9356 | |||
| 4ad44badb9 | |||
| adce4a808a | |||
| 257b06c552 | |||
| a94c78f834 | |||
| b6ac0a1d61 | |||
| f3b74fe433 | |||
| 2ddf29b158 | |||
| bf30957acf | |||
| c9ac61935e | |||
| 60a3a42140 | |||
| 17e21cde4b | |||
| 7fb5ea47dd | |||
| d7189eb7d4 | |||
| ff35571231 | |||
| 3744a6cdec | |||
| 0fd9a5aed8 | |||
| 3dd792c2d5 | |||
| 584969da44 | |||
| acf36c3e04 | |||
| 27c1d147c5 | |||
| 3831bc0999 | |||
| d23bc3204d | |||
| c158f08430 | |||
| e05eba42c3 | |||
| e97be8c142 | |||
| e97d097b2b | |||
| 58aa03c4a9 | |||
| e1399d1814 | |||
| 1964d3d36f | |||
| d7a009eb67 | |||
| 0e03805439 | |||
| eafefb40ec | |||
| 9e4c778e8f | |||
| 0788fd6122 | |||
| 3685f13344 | |||
| d4d8f70fff | |||
| 918858e255 | |||
| 1aff083ef3 | |||
| 6414922884 | |||
| 57ba809076 | |||
| 6fd3a695cf | |||
| f6857cac90 | |||
| b994e47357 | |||
| 82b21d0458 | |||
| daa1abc047 | |||
| 3a66b66c6a | |||
| 6c89c72041 | |||
| e54d5e7388 | |||
| 9a89e2467e | |||
| 48bf06f69c | |||
| 8feddf872a | |||
| 99ebdeb188 | |||
| ba267cbcb8 | |||
| b98093b244 | |||
| 58392144ca | |||
| f1394a24e5 | |||
| e396e00016 | |||
| 0dc4890107 | |||
| dd8c41b19f | |||
| 0283935918 | |||
| 12f888b8d4 | |||
| a5b24f90dc | |||
|
|
df4947ceb3 | ||
|
|
190a8bf91e | ||
|
|
d118e88f6b | ||
| 1553139a80 | |||
| 798caa2b0d | |||
| 88d4447b20 | |||
| ee458a24f7 | |||
| fa91f21e39 | |||
| 873bdd2036 | |||
| 20aecac2ae | |||
| 09fd92ccad | |||
| 2b21caf58f | |||
| 40e26be72e | |||
| 2699053102 | |||
| 06b597f37c | |||
| 6d3b543648 | |||
| c515dc89a9 | |||
| 66919af46a | |||
| 28ef194586 | |||
| 05bc7577b5 | |||
| 9efabd8fb2 | |||
| 8f225c5f8e | |||
| 44682b6f2c | |||
| a6cf043d79 | |||
| 3968d13a19 | |||
| a3f45628aa | |||
| 6da44a5a51 | |||
| e5d8e1c953 | |||
| e2378bfa8b | |||
| ca3dab855b | |||
| 79482d56d1 | |||
| c4024663bb | |||
| b2a512eafe | |||
| 7b0e2127dc | |||
| 0b663b73d5 | |||
| afc0720f08 | |||
| 015fc9b1e7 | |||
| 62d1a615ae | |||
| 043b5c588d | |||
| cd18b088cb | |||
| ebfdd0b70e | |||
| e7b82f441c | |||
| 6e59957247 | |||
| 1e540862a0 | |||
| 31cc1116ae | |||
| 338246a618 | |||
| 10ebf6ed04 | |||
| ec9a15927a | |||
| 1a0e55b4cf | |||
| b48160e1b7 | |||
| d4a16a94e6 | |||
| 07c0eebf21 | |||
| 9ed18f27c3 | |||
|
|
86b1e8a00d | ||
| db9200d7b5 | |||
| d894b62773 | |||
| ade281cdd2 | |||
| 9bb94ee33b | |||
| 754b370d8b | |||
| d3e379e71b | |||
| 6ed40a7bc1 | |||
|
|
f3d5f84d2c | ||
|
|
0b89c1d36d | ||
|
|
b8ed0bd5a5 | ||
| b9ae356e57 | |||
|
|
e351b64355 | ||
|
|
f4df88bb7a | ||
| 8142d800c7 | |||
| 95c0873b8c | |||
| d12a2611b8 | |||
| 9212b1f51f | |||
| 56505cf3e1 | |||
| 0510dd8328 | |||
| ce9758c86b | |||
| 7d194a5c36 | |||
| eec34c1efb | |||
| 765d5e7216 | |||
| 7cb8a4de52 | |||
| d2fbc286b1 | |||
| 64385757af | |||
| ea7b812645 | |||
| b214cdf3a1 | |||
| dccc12ee30 | |||
| 60e744978c | |||
| 495a2a80e4 | |||
| 6fbc010fa1 | |||
| c8f77de4f2 | |||
| 5c2d09b175 | |||
| b3646ab708 | |||
| d751eaf132 | |||
| 62e7ccb054 | |||
| 4d9e055bb3 | |||
| 9be7ca886d | |||
| 30568f3633 | |||
| 5f22499b66 | |||
| f75afb8354 | |||
| e38df8bd23 | |||
| ae347c8509 | |||
| ee40979a2d | |||
| 69d0b7b829 | |||
| 490ccfe983 | |||
| 5630c2708e | |||
| ed7220dc9c | |||
| 5e4fae9e42 | |||
| 063f43e74c | |||
| 171b4ca3da | |||
| 878e3358c0 | |||
| 81aef68143 | |||
| e2a37f2c81 | |||
| 69575c1cb3 | |||
| 8adf5db409 | |||
| 2c7e443f52 | |||
| 6ad4ef29e9 | |||
| 8feb805067 | |||
| 816da38987 | |||
| 0ba795c767 | |||
| 88b709f531 | |||
| a7eacb529e | |||
| 5a4026a4fc | |||
| 404c7de594 | |||
| f26f48cc53 | |||
| ed8afb02a1 | |||
| d86695fad7 | |||
| 570c035f27 | |||
| 5657282577 | |||
| 551ac62075 | |||
| 1b1be48ee6 | |||
|
|
1f9ea136b0 | ||
| 8dadb22e75 | |||
| 8dd9860aa1 | |||
| 9a0470f781 | |||
| eb8688c90c | |||
| 9f2f619a21 | |||
| 568883ff1c | |||
| 97003b953a | |||
| 5646654317 | |||
| ee54e3de34 | |||
| 7b0af9cf66 | |||
| 563ae0a656 | |||
| b9e2307d7a | |||
| cd0a864e7c | |||
| 5c30f57c4c | |||
| 3dcd033616 | |||
| f10dc60772 | |||
| 37f624956b | |||
| 20dc4e6730 | |||
| f6c607d84c | |||
| 81ed5f80d7 | |||
|
|
e385686323 | ||
| 086eda4ee3 | |||
| 9419e390da | |||
| d919600ac2 | |||
| 11681ac601 | |||
| 6c5152297a | |||
| 547f64e4c4 | |||
| 3129e32f0c | |||
| 72b54e9673 | |||
| 2ff291b255 | |||
| 8eda1ce4bc | |||
| e1b4375621 | |||
| d84259fdcc | |||
| d64c7ad756 | |||
| 710f91999f | |||
| f3fe0e3cee | |||
| c5c5c2e972 | |||
| a7cb056ce7 | |||
| dae1555ec4 | |||
| 2c6ef1b8cc | |||
| d70e8853e8 | |||
| e35d64b486 | |||
| 9868c832a1 | |||
| 42e46f9921 | |||
| e7ccc2ead0 | |||
| 170f969697 | |||
| 131fd891b0 | |||
| a5396b72cb | |||
| ec876ea292 | |||
| 8021050fad | |||
| bd585b5412 | |||
| 06f9a8c9ee | |||
| 160b51da94 | |||
| 064edf9ef1 | |||
| f17d36dcd3 | |||
| ec4f9f6c90 | |||
| cbee8c2c95 | |||
| dc6edbb67f | |||
| 74381eda5c | |||
| 1ef7833bd9 | |||
| c10386f3f6 | |||
| 413cef4f23 | |||
| 867cee41c3 | |||
| 990fe78a33 | |||
| 1efdb50f73 | |||
|
|
86fea065e7 | ||
|
|
ac046aae6c | ||
|
|
9646054877 | ||
| 6334002639 | |||
| 72e0c0c90b | |||
| 2f2a5a00c4 | |||
| c394993418 | |||
| 476048583d | |||
| 76ae67c968 | |||
| d1d95d2f36 | |||
| 6409568334 | |||
| 83ba339eb5 | |||
| c49c93d542 | |||
| 92dab52d66 | |||
| dac3d8e43f | |||
| fb0b05d7ef | |||
| 993212e7ab | |||
| 380a9f0a16 | |||
| ba7bce5502 | |||
| ce40891e37 | |||
| c4d10f8872 | |||
| 2bb0c82c30 | |||
| a4dcf8dc3b | |||
| 17eaddbc8c | |||
| 9005c02499 | |||
| e7380b5eb6 | |||
| f8d6e4b544 | |||
| 893eca296b | |||
| b0bd58ccb2 | |||
| 44a42d39d0 | |||
| a8c7e8eb54 | |||
| cef22919a4 | |||
| f79350e609 | |||
| 1102cad390 | |||
| df4e999c82 | |||
| 3baeb182f0 | |||
| 5539bbad0d | |||
| 4d4dfae8f2 | |||
| 03c514104e | |||
| 792db7a673 | |||
| bfd399e631 | |||
| 7fef690f5e | |||
| 3df7d65ac1 | |||
| e1a1164136 | |||
| 23216279dc | |||
| 9e082f7dfa | |||
| 7750819e83 | |||
| 2ec0e2f93f | |||
| 9170ffb1a9 | |||
| e05f9ef5a9 | |||
| 89bb4aa625 | |||
|
|
9b0845593d | ||
| 617ded2dd4 | |||
| e882a224d2 | |||
| e04f6573c0 | |||
| 791e3b2313 | |||
| 26b56d757c | |||
| fbb77b9925 | |||
| 7b671dbd90 | |||
| 5875930f1a | |||
| d773985822 | |||
| a2de6f8fae | |||
| d71795006d | |||
| 561438d45c | |||
| 874b028e86 | |||
| 68ec42d9ed | |||
| 8aeb4667d7 | |||
| 565464f0cd | |||
| 04b50d4545 | |||
| e01d32fb22 | |||
| a3a023a664 | |||
| 1b5a7ed4fd | |||
|
|
362b818a71 | ||
| 29a96d64bb | |||
| 256365e52e | |||
| e333d81b81 | |||
| d66f60d419 | |||
| 4a4939b604 | |||
| ebe8d1a90e | |||
| 1a3376fe6c | |||
| 20188d7043 | |||
| f59e0d255f | |||
| 071cb15492 | |||
| f8812ed9e7 | |||
| 19d310d35f | |||
| c364879b5f | |||
| 418b7c0e7e | |||
| 69f46abce1 | |||
| de61f7a5d8 | |||
| 07a449b633 | |||
| 6bb549ef4c | |||
| 14fa810ecb | |||
| b964661030 | |||
| 9c11551c9a | |||
| 21fece7c84 | |||
| 996618994d | |||
| ce8be6dd52 | |||
| 17aac2f80e | |||
| ba927734d2 | |||
| c0d5fd18f5 | |||
| 996a9cf15a | |||
| 91078f5701 | |||
| 036d3a8992 | |||
| 7534fe8969 | |||
| 8e4f1812cc | |||
| e8f40218dd | |||
| 50054ca937 | |||
| 63220c0be7 | |||
| 3b6d19782c | |||
| 2d58330508 | |||
| abf57a55ea | |||
| 463532ba81 | |||
| d74c66990a | |||
| 7f1bc51905 | |||
| 71127f1f12 | |||
| 89041e20ae | |||
| a54dd4b52a | |||
| d7e497b617 | |||
| 80938cd913 | |||
| 830505dbe5 | |||
| 75565ecf2d | |||
| 9a7a4c7fff | |||
| c0f0bb3c2e | |||
| a097c0a2f4 | |||
| 20ae2b4dd1 | |||
| 115b5a3471 | |||
| 77893629f9 | |||
| afb27b1aa9 | |||
| 61006122ae | |||
| 4eb0f59fc0 | |||
| 3b4bf24a16 | |||
| 51d93c4464 | |||
| d83a8121db | |||
| 2584cda5c3 | |||
| c90497f77b | |||
| 0de6b4589f | |||
| 8004c8c181 | |||
| 1246c4ed07 | |||
| ab463e1caa | |||
| 4f13010e7d | |||
| 83d3cc099f | |||
| 625c676010 | |||
| 2d9ed4cfc8 | |||
| 29795e9906 | |||
| 0328fef4f7 | |||
| 687772f073 | |||
| c66df11754 | |||
| 0450dc3547 | |||
| 0bd9eda48f | |||
| 858314fa0a | |||
| f277b1038c | |||
| 15c055beb7 | |||
| 4d24815f3e | |||
| d96b0cd2f7 | |||
| d238bd137f | |||
| 17b150499d | |||
| c7228c9674 | |||
| 7a9f5d4966 | |||
| a16050242a | |||
| ea8f3d8d51 | |||
| 08d2ccc03a | |||
| 21ec23d77b | |||
| 2c4ff37062 | |||
| 695a8035b5 | |||
| d12b236e56 | |||
| 7a5090d9f6 | |||
| ec76a7239c | |||
| 2758f549a3 | |||
| 493931ef0f | |||
| 9e1990942b | |||
| f1984fbe46 | |||
| f1fbea21a7 | |||
| 4b44ce0667 | |||
| 231ef35a0a | |||
| 1aa62cb396 | |||
| 8e411771c2 | |||
| d65852d1a4 | |||
| 21f5e82a20 | |||
|
|
851ec37350 | ||
| f1cd9dbeb3 | |||
| 7a1c7d6cc4 | |||
| cb704b3621 | |||
|
|
646d295876 | ||
| 8e09556c25 | |||
| 7dbebc996d | |||
| 278ffba0ff | |||
| 647cf02a38 | |||
| 4be2986681 | |||
| 06d9b4c910 | |||
| a074fdcb92 | |||
|
|
8241d9c355 | ||
| 66258f0f6d | |||
| 65541fa2c7 | |||
| 7e4a6134bf | |||
| a54a537239 | |||
| f01bbde537 | |||
| 2c710555d6 | |||
| 9c2be6306c | |||
| d37840d4ef | |||
| b4a3b5d529 | |||
| c2a772142c | |||
| 76fca7f527 | |||
| 73ccd24e3e | |||
| a642feafb5 | |||
| faf9f34af8 | |||
| b56801ac91 | |||
| a81d12d480 | |||
| 17eb0cd0dc | |||
| 52024285d2 | |||
| f179aea4d7 |
@@ -56,7 +56,7 @@ SpaceBeforeParensOptions:
|
|||||||
AfterIfMacros: true
|
AfterIfMacros: true
|
||||||
AfterOverloadedOperator: false
|
AfterOverloadedOperator: false
|
||||||
BeforeNonEmptyParentheses: false
|
BeforeNonEmptyParentheses: false
|
||||||
SpaceBeforeRangeBasedForLoopColon: false
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
SpaceInEmptyParentheses: false
|
SpaceInEmptyParentheses: false
|
||||||
SpacesInCStyleCastParentheses: false
|
SpacesInCStyleCastParentheses: false
|
||||||
SpacesInConditionalStatement: false
|
SpacesInConditionalStatement: false
|
||||||
|
|||||||
25
.cmake-format
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
format:
|
||||||
|
line_width: 100
|
||||||
|
tab_size: 4
|
||||||
|
use_tabchars: false
|
||||||
|
max_subgroups_hwrap: 3
|
||||||
|
max_pargs_hwrap: 5
|
||||||
|
separate_ctrl_name_with_space: false
|
||||||
|
separate_fn_name_with_space: false
|
||||||
|
dangle_parens: false
|
||||||
|
dangle_align: child
|
||||||
|
line_ending: unix
|
||||||
|
command_case: canonical
|
||||||
|
keyword_case: upper
|
||||||
|
enable_sort: true
|
||||||
|
autosort: true
|
||||||
|
markup:
|
||||||
|
bullet_char: "*"
|
||||||
|
enum_char: .
|
||||||
|
enable_markup: false
|
||||||
|
additional_commands:
|
||||||
|
target_link_libraries:
|
||||||
|
kwargs:
|
||||||
|
PUBLIC: "*"
|
||||||
|
SHARED: "*"
|
||||||
|
PRIVATE: "*"
|
||||||
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# SCM syntax highlighting & preventing 3-way merges
|
||||||
|
pixi.lock merge=binary linguist-language=YAML linguist-generated=true -diff
|
||||||
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. iOS]
|
||||||
|
- Browser [e.g. chrome, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Smartphone (please complete the following information):**
|
||||||
|
- Device: [e.g. iPhone6]
|
||||||
|
- OS: [e.g. iOS8.1]
|
||||||
|
- Browser [e.g. stock browser, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
10
.github/ISSUE_TEMPLATE/custom.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
name: Custom issue template
|
||||||
|
about: Describe this issue template's purpose here.
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
BIN
.github/psd/omath.psd
vendored
Normal file
774
.github/workflows/cmake-multi-platform.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Omath CI (Arch Linux / Windows)
|
name: Omath CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -10,50 +10,168 @@ concurrency:
|
|||||||
group: ci-${{ github.ref }}
|
group: ci-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# 1) ARCH LINUX – Clang / Ninja
|
# 1) Linux – Clang / Ninja
|
||||||
##############################################################################
|
##############################################################################
|
||||||
jobs:
|
jobs:
|
||||||
arch-build-and-test:
|
linux-build-and-test:
|
||||||
name: Arch Linux (Clang)
|
name: ${{ matrix.name }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ matrix.runner }}
|
||||||
container: archlinux:latest
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- name: Linux (Clang) (x64-linux)
|
||||||
|
triplet: x64-linux
|
||||||
|
runner: ubuntu-latest
|
||||||
|
preset: linux-release-vcpkg
|
||||||
|
coverage: true
|
||||||
|
install_cmd: |
|
||||||
|
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
|
||||||
|
sudo add-apt-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-21 main"
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y git build-essential cmake ninja-build \
|
||||||
|
zip unzip curl pkg-config ca-certificates \
|
||||||
|
clang-21 lld-21 libc++-21-dev libc++abi-21-dev \
|
||||||
|
llvm-21
|
||||||
|
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-21 100
|
||||||
|
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-21 100
|
||||||
|
sudo update-alternatives --install /usr/bin/lld lld /usr/bin/lld-21 100
|
||||||
|
- name: Linux (Clang) (x86-linux)
|
||||||
|
triplet: x86-linux
|
||||||
|
runner: ubuntu-latest
|
||||||
|
preset: linux-release-vcpkg-x86
|
||||||
|
coverage: false
|
||||||
|
install_cmd: |
|
||||||
|
# Add LLVM 21 repository
|
||||||
|
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
|
||||||
|
sudo add-apt-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-21 main"
|
||||||
|
# Add GCC Toolchain PPA
|
||||||
|
sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu plucky main universe"
|
||||||
|
# Enable i386 architecture
|
||||||
|
sudo dpkg --add-architecture i386
|
||||||
|
sudo apt-get update
|
||||||
|
# Install Clang 21
|
||||||
|
sudo apt-get install -y git build-essential cmake ninja-build \
|
||||||
|
zip unzip curl pkg-config ca-certificates \
|
||||||
|
clang-21 lld-21 libc++-21-dev libc++abi-21-dev
|
||||||
|
sudo apt-get install -y -t plucky binutils
|
||||||
|
# Install GCC 15 with multilib support
|
||||||
|
sudo apt-get install -y gcc-15-multilib g++-15-multilib
|
||||||
|
# Set up alternatives for Clang
|
||||||
|
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-21 100
|
||||||
|
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-21 100
|
||||||
|
sudo update-alternatives --install /usr/bin/lld lld /usr/bin/lld-21 100
|
||||||
|
# Set up alternatives for GCC
|
||||||
|
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-15 100
|
||||||
|
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-15 100
|
||||||
|
- name: Linux (Clang) (arm64-linux)
|
||||||
|
triplet: arm64-linux
|
||||||
|
runner: ubuntu-24.04-arm
|
||||||
|
preset: linux-release-vcpkg-arm64
|
||||||
|
coverage: false
|
||||||
|
install_cmd: |
|
||||||
|
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
|
||||||
|
sudo add-apt-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-21 main"
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y git build-essential cmake ninja-build \
|
||||||
|
zip unzip curl pkg-config ca-certificates \
|
||||||
|
clang-21 lld-21 libc++-21-dev libc++abi-21-dev
|
||||||
|
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-21 100
|
||||||
|
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-21 100
|
||||||
|
sudo update-alternatives --install /usr/bin/lld lld /usr/bin/lld-21 100
|
||||||
|
fail-fast: false
|
||||||
|
env:
|
||||||
|
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
|
||||||
steps:
|
steps:
|
||||||
- name: Install basic tool-chain with pacman
|
- name: Install basic tool-chain
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: ${{ matrix.install_cmd }}
|
||||||
pacman -Sy --noconfirm archlinux-keyring
|
|
||||||
pacman -Syu --noconfirm --needed \
|
|
||||||
git base-devel clang cmake ninja
|
|
||||||
|
|
||||||
- name: Checkout repository (with sub-modules)
|
- name: Checkout repository (with sub-modules)
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Set up vcpkg
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
|
||||||
|
cd "$VCPKG_ROOT"
|
||||||
|
./bootstrap-vcpkg.sh
|
||||||
|
|
||||||
- name: Configure (cmake --preset)
|
- name: Configure (cmake --preset)
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake --preset linux-release -DOMATH_BUILD_TESTS=ON
|
run: |
|
||||||
|
cmake --preset ${{ matrix.preset }} \
|
||||||
|
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
|
||||||
|
-DOMATH_BUILD_TESTS=ON \
|
||||||
|
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||||
|
-DOMATH_ENABLE_COVERAGE=${{ matrix.coverage == true && 'ON' || 'OFF' }} \
|
||||||
|
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests"
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake --build cmake-build/build/linux-release --target all
|
run: cmake --build cmake-build/build/${{ matrix.preset }} --target unit_tests omath
|
||||||
|
|
||||||
- name: Run unit_tests
|
- name: Run unit_tests
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./out/Release/unit_tests
|
run: ./out/Release/unit_tests
|
||||||
|
|
||||||
|
- name: Run Coverage
|
||||||
|
if: ${{ matrix.coverage == true }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get install lcov
|
||||||
|
chmod +x scripts/coverage-llvm.sh
|
||||||
|
./scripts/coverage-llvm.sh \
|
||||||
|
"${{ github.workspace }}" \
|
||||||
|
"cmake-build/build/${{ matrix.preset }}" \
|
||||||
|
"./out/Release/unit_tests" \
|
||||||
|
"cmake-build/build/${{ matrix.preset }}/coverage"
|
||||||
|
|
||||||
|
- name: Upload Coverage Report
|
||||||
|
if: ${{ matrix.coverage == true }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-report-linux
|
||||||
|
path: cmake-build/build/${{ matrix.preset }}/coverage/
|
||||||
|
|
||||||
|
- name: Upload logs on failure
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: linux-build-logs-${{ matrix.triplet }}
|
||||||
|
path: |
|
||||||
|
cmake-build/build/${{ matrix.preset }}/**/*.log
|
||||||
|
${{ env.VCPKG_ROOT }}/buildtrees/**/*.log
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# 2) Windows – MSVC / Ninja
|
# 2) Windows – MSVC / Ninja
|
||||||
##############################################################################
|
##############################################################################
|
||||||
windows-build-and-test:
|
windows-build-and-test:
|
||||||
name: Windows (MSVC)
|
name: ${{ matrix.name }}
|
||||||
runs-on: windows-latest
|
runs-on: ${{ matrix.runner }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- name: Windows (MSVC) (x64-windows)
|
||||||
|
runner: windows-latest
|
||||||
|
arch: amd64
|
||||||
|
preset: windows-release-vcpkg
|
||||||
|
triplet: x64-windows
|
||||||
|
- name: Windows (MSVC) (x86-windows)
|
||||||
|
runner: windows-latest
|
||||||
|
arch: amd64_x86
|
||||||
|
preset: windows-release-vcpkg-x86
|
||||||
|
triplet: x86-windows
|
||||||
|
- name: Windows (MSVC) (arm64-windows)
|
||||||
|
runner: windows-11-arm
|
||||||
|
arch: arm64
|
||||||
|
preset: windows-release-vcpkg-arm64
|
||||||
|
triplet: arm64-windows
|
||||||
|
fail-fast: false
|
||||||
|
env:
|
||||||
|
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository (with sub-modules)
|
- name: Checkout repository (with sub-modules)
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -65,15 +183,631 @@ jobs:
|
|||||||
|
|
||||||
- name: Set up MSVC developer command-prompt
|
- name: Set up MSVC developer command-prompt
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
with:
|
||||||
|
arch: ${{ matrix.arch }}
|
||||||
|
|
||||||
- name: Configure (cmake --preset)
|
- name: Configure (cmake --preset)
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake --preset windows-release -DOMATH_BUILD_TESTS=ON
|
run: |
|
||||||
|
cmake --preset ${{ matrix.preset }} \
|
||||||
|
-DOMATH_BUILD_TESTS=ON \
|
||||||
|
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||||
|
-DOMATH_ENABLE_COVERAGE=OFF \
|
||||||
|
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests"
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake --build cmake-build/build/windows-release --target all
|
run: cmake --build cmake-build/build/${{ matrix.preset }} --target unit_tests omath
|
||||||
|
|
||||||
- name: Run unit_tests.exe
|
- name: Run unit_tests.exe
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./out/Release/unit_tests.exe
|
run: ./out/Release/unit_tests.exe
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Coverage (x64-windows only)
|
||||||
|
##########################################################################
|
||||||
|
- name: Install LLVM
|
||||||
|
if: ${{ matrix.triplet == 'x64-windows' }}
|
||||||
|
run: |
|
||||||
|
choco install llvm -y
|
||||||
|
|
||||||
|
- name: Clean Build Directory for Coverage
|
||||||
|
if: ${{ matrix.triplet == 'x64-windows' }}
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$buildDir = "cmake-build/build/${{ matrix.preset }}"
|
||||||
|
if (Test-Path $buildDir) {
|
||||||
|
Write-Host "Cleaning build directory to prevent compiler conflict: $buildDir"
|
||||||
|
Remove-Item -Path $buildDir -Recurse -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Build Debug for Coverage
|
||||||
|
if: ${{ matrix.triplet == 'x64-windows' }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake --preset ${{ matrix.preset }} \
|
||||||
|
-DCMAKE_C_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe" \
|
||||||
|
-DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang-cl.exe" \
|
||||||
|
-DCMAKE_LINKER="C:/Program Files/LLVM/bin/lld-link.exe" \
|
||||||
|
-DOMATH_BUILD_TESTS=ON \
|
||||||
|
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||||
|
-DOMATH_ENABLE_COVERAGE=ON \
|
||||||
|
-DOMATH_THREAT_WARNING_AS_ERROR=OFF \
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
|
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests"
|
||||||
|
cmake --build cmake-build/build/${{ matrix.preset }} --config Debug --target unit_tests omath
|
||||||
|
|
||||||
|
- name: Run Tests (Generates .profraw)
|
||||||
|
if: ${{ matrix.triplet == 'x64-windows' }}
|
||||||
|
shell: pwsh
|
||||||
|
env:
|
||||||
|
LLVM_PROFILE_FILE: "cmake-build/build/${{ matrix.preset }}/unit_tests.profraw"
|
||||||
|
run: |
|
||||||
|
./out/Debug/unit_tests.exe
|
||||||
|
|
||||||
|
- name: Process Coverage (llvm-profdata & llvm-cov)
|
||||||
|
if: ${{ matrix.triplet == 'x64-windows' }}
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$BUILD_DIR = "cmake-build/build/${{ matrix.preset }}"
|
||||||
|
$EXE_PATH = "./out/Debug/unit_tests.exe"
|
||||||
|
|
||||||
|
# 1. Merge raw profile data (essential step)
|
||||||
|
& "C:/Program Files/LLVM/bin/llvm-profdata.exe" merge `
|
||||||
|
-sparse "$BUILD_DIR/unit_tests.profraw" `
|
||||||
|
-o "$BUILD_DIR/unit_tests.profdata"
|
||||||
|
|
||||||
|
# 2. Export to LCOV format
|
||||||
|
# NOTE: We explicitly ignore vcpkg_installed and system headers
|
||||||
|
& "C:/Program Files/LLVM/bin/llvm-cov.exe" export "$EXE_PATH" `
|
||||||
|
-instr-profile="$BUILD_DIR/unit_tests.profdata" `
|
||||||
|
-format=lcov `
|
||||||
|
-ignore-filename-regex="vcpkg_installed|external|tests" `
|
||||||
|
> "$BUILD_DIR/lcov.info"
|
||||||
|
|
||||||
|
if (Test-Path "$BUILD_DIR/lcov.info") {
|
||||||
|
Write-Host "✅ LCOV info created at $BUILD_DIR/lcov.info"
|
||||||
|
} else {
|
||||||
|
Write-Error "Failed to create LCOV info"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Install LCOV (for genhtml)
|
||||||
|
if: ${{ matrix.triplet == 'x64-windows' }}
|
||||||
|
run: choco install lcov -y
|
||||||
|
|
||||||
|
- name: Generate HTML Report
|
||||||
|
if: ${{ matrix.triplet == 'x64-windows' }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
BUILD_DIR="cmake-build/build/${{ matrix.preset }}"
|
||||||
|
LCOV_INFO="${BUILD_DIR}/lcov.info"
|
||||||
|
HTML_DIR="${BUILD_DIR}/coverage-html"
|
||||||
|
|
||||||
|
# Fix paths for genhtml (Perl hates backslashes)
|
||||||
|
sed -i 's|\\|/|g' "${LCOV_INFO}"
|
||||||
|
|
||||||
|
# Locate genhtml provided by 'choco install lcov'
|
||||||
|
# It is typically in ProgramData/chocolatey/lib/lcov/tools/bin
|
||||||
|
GENHTML=$(find /c/ProgramData/chocolatey -name genhtml -print -quit)
|
||||||
|
|
||||||
|
if [ -z "$GENHTML" ]; then
|
||||||
|
echo "Error: genhtml executable not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Using genhtml: $GENHTML"
|
||||||
|
mkdir -p "$HTML_DIR"
|
||||||
|
|
||||||
|
# Run genhtml
|
||||||
|
# Added --demangle-cpp if your version supports it, otherwise remove it
|
||||||
|
perl "$GENHTML" \
|
||||||
|
"${LCOV_INFO}" \
|
||||||
|
--output-directory "$HTML_DIR" \
|
||||||
|
--title "OMath Coverage Report" \
|
||||||
|
--legend \
|
||||||
|
--show-details \
|
||||||
|
--branch-coverage \
|
||||||
|
--ignore-errors source
|
||||||
|
|
||||||
|
echo "✅ LCOV HTML report generated at $HTML_DIR"
|
||||||
|
|
||||||
|
- name: Upload Coverage (HTML Report)
|
||||||
|
if: ${{ matrix.triplet == 'x64-windows' }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-html-windows
|
||||||
|
path: cmake-build/build/${{ matrix.preset }}/coverage-html/
|
||||||
|
|
||||||
|
- name: Upload logs on failure
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: windows-build-logs-${{ matrix.triplet }}
|
||||||
|
path: |
|
||||||
|
cmake-build/build/${{ matrix.preset }}/**/*.log
|
||||||
|
${{ env.VCPKG_ROOT }}/buildtrees/**/*.log
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# 3) macOS – AppleClang / Ninja
|
||||||
|
##############################################################################
|
||||||
|
macosx-build-and-test:
|
||||||
|
name: ${{ matrix.name }}
|
||||||
|
runs-on: ${{ matrix.runner }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- name: macOS (AppleClang) (arm64-osx)
|
||||||
|
runner: macos-latest
|
||||||
|
preset: darwin-release-vcpkg
|
||||||
|
triplet: arm64-osx
|
||||||
|
coverage: true
|
||||||
|
- name: macOS (AppleClang) (x64-osx)
|
||||||
|
runner: macos-15-intel
|
||||||
|
preset: darwin-release-vcpkg-x64
|
||||||
|
triplet: x64-osx
|
||||||
|
coverage: false
|
||||||
|
fail-fast: false
|
||||||
|
env:
|
||||||
|
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
|
||||||
|
steps:
|
||||||
|
- name: Install basic tool-chain with Homebrew
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
brew install cmake ninja
|
||||||
|
|
||||||
|
- name: Checkout repository (with sub-modules)
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Set up vcpkg
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
|
||||||
|
|
||||||
|
- name: Configure (cmake --preset)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake --preset ${{ matrix.preset }} \
|
||||||
|
-DOMATH_BUILD_TESTS=ON \
|
||||||
|
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||||
|
-DOMATH_ENABLE_COVERAGE=${{ matrix.coverage == true && 'ON' || 'OFF' }} \
|
||||||
|
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests"
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
shell: bash
|
||||||
|
run: cmake --build cmake-build/build/${{ matrix.preset }} --target unit_tests omath
|
||||||
|
|
||||||
|
- name: Run unit_tests
|
||||||
|
shell: bash
|
||||||
|
run: ./out/Release/unit_tests
|
||||||
|
|
||||||
|
- name: Run Coverage
|
||||||
|
if: ${{ matrix.coverage == true }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
brew install lcov
|
||||||
|
chmod +x scripts/coverage-llvm.sh
|
||||||
|
./scripts/coverage-llvm.sh \
|
||||||
|
"${{ github.workspace }}" \
|
||||||
|
"cmake-build/build/${{ matrix.preset }}" \
|
||||||
|
"./out/Release/unit_tests" \
|
||||||
|
"cmake-build/build/${{ matrix.preset }}/coverage"
|
||||||
|
|
||||||
|
- name: Upload Coverage Report
|
||||||
|
if: ${{ matrix.coverage == true }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-report-macos
|
||||||
|
path: cmake-build/build/${{ matrix.preset }}/coverage/
|
||||||
|
|
||||||
|
- name: Upload logs on failure
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: macos-build-logs-${{ matrix.triplet }}
|
||||||
|
path: |
|
||||||
|
cmake-build/build/${{ matrix.preset }}/**/*.log
|
||||||
|
${{ env.VCPKG_ROOT }}/buildtrees/**/*.log
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# 4) iOS – AppleClang / Xcode / arm64-ios
|
||||||
|
##############################################################################
|
||||||
|
ios-build:
|
||||||
|
name: iOS (AppleClang) (${{ matrix.triplet }})
|
||||||
|
runs-on: macOS-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- triplet: arm64-ios
|
||||||
|
preset: ios-release-vcpkg
|
||||||
|
fail-fast: false
|
||||||
|
env:
|
||||||
|
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
|
||||||
|
steps:
|
||||||
|
- name: Install CMake tooling
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
brew install cmake ninja
|
||||||
|
|
||||||
|
- name: Checkout repository (with sub-modules)
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Set up vcpkg
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
|
||||||
|
cd "$VCPKG_ROOT"
|
||||||
|
./bootstrap-vcpkg.sh
|
||||||
|
|
||||||
|
- name: Configure (cmake --preset)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake --preset ${{ matrix.preset }} \
|
||||||
|
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
|
||||||
|
-DOMATH_BUILD_TESTS=ON \
|
||||||
|
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||||
|
-DVCPKG_MANIFEST_FEATURES="imgui;tests"
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake --build cmake-build/build/${{ matrix.preset }} --config Release --target unit_tests omath
|
||||||
|
|
||||||
|
- name: Upload logs on failure
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ios-build-logs-${{ matrix.triplet }}
|
||||||
|
path: |
|
||||||
|
cmake-build/build/${{ matrix.preset }}/**/*.log
|
||||||
|
${{ env.VCPKG_ROOT }}/buildtrees/**/*.log
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# 5) FreeBSD – Clang / Ninja
|
||||||
|
##############################################################################
|
||||||
|
freebsd-build-and-test:
|
||||||
|
name: FreeBSD (Clang) (${{ matrix.triplet }})
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- triplet: x64-freebsd
|
||||||
|
preset: freebsd-release-vcpkg
|
||||||
|
arch: x86-64
|
||||||
|
fail-fast: false
|
||||||
|
env:
|
||||||
|
VCPKG_ROOT: ${{ github.workspace }}/tmp/vcpkg
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository (with sub-modules)
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Build and Test
|
||||||
|
uses: cross-platform-actions/action@v0.31.0
|
||||||
|
with:
|
||||||
|
operating_system: freebsd
|
||||||
|
architecture: ${{ matrix.arch }}
|
||||||
|
version: '15.0'
|
||||||
|
memory: '12G'
|
||||||
|
cpu_count: 4
|
||||||
|
run: |
|
||||||
|
sudo pkg install -y git curl zip unzip gmake llvm gsed bash perl5 openssl 7-zip coreutils cmake ninja pkgconf patchelf
|
||||||
|
git config --global --add safe.directory `pwd`
|
||||||
|
# Build vcpkg in /tmp to avoid sshfs timestamp sync issues
|
||||||
|
export VCPKG_ROOT=/tmp/vcpkg
|
||||||
|
rm -rf "$VCPKG_ROOT"
|
||||||
|
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
|
||||||
|
cd "$VCPKG_ROOT"
|
||||||
|
./bootstrap-vcpkg.sh
|
||||||
|
cd -
|
||||||
|
export VCPKG_FORCE_SYSTEM_BINARIES=0
|
||||||
|
cmake --preset ${{ matrix.preset }} \
|
||||||
|
-DOMATH_BUILD_TESTS=ON \
|
||||||
|
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||||
|
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests" \
|
||||||
|
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported"
|
||||||
|
cmake --build cmake-build/build/${{ matrix.preset }} --target unit_tests omath
|
||||||
|
./out/Release/unit_tests
|
||||||
|
|
||||||
|
- name: Upload logs on failure
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: freebsd-build-logs-${{ matrix.triplet }}
|
||||||
|
path: |
|
||||||
|
cmake-build/build/${{ matrix.preset }}/**/*.log
|
||||||
|
${{ env.VCPKG_ROOT }}/buildtrees/**/*.log
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# 6) Android NDK – Clang / Ninja
|
||||||
|
##############################################################################
|
||||||
|
android-build:
|
||||||
|
name: Android NDK (${{ matrix.triplet }})
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- triplet: arm-neon-android
|
||||||
|
preset: android-arm-neon-release-vcpkg
|
||||||
|
- triplet: arm64-android
|
||||||
|
preset: android-arm64-release-vcpkg
|
||||||
|
- triplet: x64-android
|
||||||
|
preset: android-x64-release-vcpkg
|
||||||
|
- triplet: x86-android
|
||||||
|
preset: android-x86-release-vcpkg
|
||||||
|
fail-fast: false
|
||||||
|
env:
|
||||||
|
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
|
||||||
|
ANDROID_NDK_HOME: ${{ github.workspace }}/android-ndk
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository (with sub-modules)
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Install Android NDK
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
NDK_VERSION="r28b"
|
||||||
|
NDK_ZIP="android-ndk-${NDK_VERSION}-linux.zip"
|
||||||
|
wget -q "https://dl.google.com/android/repository/${NDK_ZIP}"
|
||||||
|
unzip -q "${NDK_ZIP}" -d "${{ github.workspace }}"
|
||||||
|
mv "${{ github.workspace }}/android-ndk-${NDK_VERSION}" "$ANDROID_NDK_HOME"
|
||||||
|
rm "${NDK_ZIP}"
|
||||||
|
echo "ANDROID_NDK_HOME=${ANDROID_NDK_HOME}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Install basic tool-chain
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y ninja-build cmake
|
||||||
|
|
||||||
|
- name: Set up vcpkg
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
|
||||||
|
cd "$VCPKG_ROOT"
|
||||||
|
./bootstrap-vcpkg.sh
|
||||||
|
|
||||||
|
- name: Configure (cmake --preset)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake --preset ${{ matrix.preset }} \
|
||||||
|
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
|
||||||
|
-DOMATH_BUILD_TESTS=ON \
|
||||||
|
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||||
|
-DVCPKG_MANIFEST_FEATURES="imgui;tests"
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake --build cmake-build/build/${{ matrix.preset }} --target unit_tests omath
|
||||||
|
|
||||||
|
- name: Upload logs on failure
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: android-build-logs-${{ matrix.triplet }}
|
||||||
|
path: |
|
||||||
|
cmake-build/build/${{ matrix.preset }}/**/*.log
|
||||||
|
${{ env.VCPKG_ROOT }}/buildtrees/**/*.log
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# 7) WebAssembly (Emscripten) – Clang / Ninja / wasm32-emscripten
|
||||||
|
##############################################################################
|
||||||
|
wasm-build-and-test:
|
||||||
|
name: WebAssembly (Emscripten) (${{ matrix.triplet }})
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- triplet: wasm32-emscripten
|
||||||
|
preset: wasm-release-vcpkg
|
||||||
|
fail-fast: false
|
||||||
|
env:
|
||||||
|
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository (with sub-modules)
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Install basic tool-chain
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y ninja-build
|
||||||
|
|
||||||
|
- name: Setup Emscripten
|
||||||
|
uses: mymindstorm/setup-emsdk@v14
|
||||||
|
with:
|
||||||
|
version: 'latest'
|
||||||
|
|
||||||
|
- name: Verify Emscripten
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "EMSDK=$EMSDK"
|
||||||
|
emcc --version
|
||||||
|
# Verify toolchain file exists
|
||||||
|
ls -la "$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake"
|
||||||
|
|
||||||
|
- name: Set up vcpkg
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
|
||||||
|
cd "$VCPKG_ROOT"
|
||||||
|
./bootstrap-vcpkg.sh
|
||||||
|
|
||||||
|
- name: Configure (cmake --preset)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake --preset ${{ matrix.preset }} \
|
||||||
|
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
|
||||||
|
-DOMATH_BUILD_TESTS=ON \
|
||||||
|
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||||
|
-DVCPKG_MANIFEST_FEATURES="imgui;tests"
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake --build cmake-build/build/${{ matrix.preset }} --target unit_tests omath
|
||||||
|
|
||||||
|
- name: Upload logs on failure
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: wasm-build-logs-${{ matrix.triplet }}
|
||||||
|
path: |
|
||||||
|
cmake-build/build/${{ matrix.preset }}/**/*.log
|
||||||
|
${{ env.VCPKG_ROOT }}/buildtrees/**/*.log
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: Run WASM Unit Tests
|
||||||
|
run: node out/Release/unit_tests.js
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# 8) Windows MSYS2 MinGW – GCC / Ninja
|
||||||
|
##############################################################################
|
||||||
|
mingw-build-and-test:
|
||||||
|
name: ${{ matrix.name }}
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- name: MINGW64 (MSYS2) (x64-mingw-dynamic)
|
||||||
|
msystem: MINGW64
|
||||||
|
pkg_prefix: mingw-w64-x86_64
|
||||||
|
preset: mingw-release-vcpkg
|
||||||
|
- name: UCRT64 (MSYS2) (x64-mingw-dynamic)
|
||||||
|
msystem: UCRT64
|
||||||
|
pkg_prefix: mingw-w64-ucrt-x86_64
|
||||||
|
preset: mingw-release-vcpkg
|
||||||
|
- name: MINGW32 (MSYS2) (x86-mingw-dynamic)
|
||||||
|
msystem: MINGW32
|
||||||
|
pkg_prefix: mingw-w64-i686
|
||||||
|
preset: mingw32-release-vcpkg
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: msys2 {0}
|
||||||
|
|
||||||
|
env:
|
||||||
|
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Setup MSYS2
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: ${{ matrix.msystem }}
|
||||||
|
update: true
|
||||||
|
install: >-
|
||||||
|
${{ matrix.pkg_prefix }}-toolchain
|
||||||
|
${{ matrix.pkg_prefix }}-cmake
|
||||||
|
${{ matrix.pkg_prefix }}-ninja
|
||||||
|
${{ matrix.pkg_prefix }}-pkg-config
|
||||||
|
git
|
||||||
|
base-devel
|
||||||
|
|
||||||
|
- name: Checkout repository (with sub-modules)
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Set up vcpkg
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
|
||||||
|
cd "$VCPKG_ROOT"
|
||||||
|
./bootstrap-vcpkg.sh
|
||||||
|
|
||||||
|
- name: Configure (cmake --preset)
|
||||||
|
run: |
|
||||||
|
cmake --preset ${{ matrix.preset }} \
|
||||||
|
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
|
||||||
|
-DOMATH_BUILD_TESTS=ON \
|
||||||
|
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||||
|
-DVCPKG_MANIFEST_FEATURES="imgui;tests"
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cmake --build cmake-build/build/${{ matrix.preset }} --target unit_tests omath
|
||||||
|
|
||||||
|
- name: Run unit_tests.exe
|
||||||
|
run: |
|
||||||
|
./out/Release/unit_tests.exe
|
||||||
|
|
||||||
|
- name: Upload logs on failure
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: mingw-build-logs-${{ matrix.msystem }}
|
||||||
|
path: |
|
||||||
|
cmake-build/build/${{ matrix.preset }}/**/*.log
|
||||||
|
${{ env.VCPKG_ROOT }}/buildtrees/**/*.log
|
||||||
|
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# 9) Valgrind Memory Check
|
||||||
|
##############################################################################
|
||||||
|
valgrind-memory-check:
|
||||||
|
name: Valgrind Analysis (All Targets)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [linux-build-and-test]
|
||||||
|
env:
|
||||||
|
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
|
||||||
|
steps:
|
||||||
|
- name: Install toolchain
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
|
||||||
|
sudo add-apt-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-21 main"
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y git build-essential cmake ninja-build \
|
||||||
|
zip unzip curl pkg-config ca-certificates \
|
||||||
|
clang-21 lld-21 libc++-21-dev libc++abi-21-dev \
|
||||||
|
llvm-21 valgrind libxmu-dev libxi-dev libgl-dev libxinerama-dev libxcursor-dev xorg-dev libglu1-mesa-dev
|
||||||
|
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-21 100
|
||||||
|
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-21 100
|
||||||
|
sudo update-alternatives --install /usr/bin/lld lld /usr/bin/lld-21 100
|
||||||
|
|
||||||
|
- name: Checkout repository (with sub-modules)
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Set up vcpkg
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
|
||||||
|
cd "$VCPKG_ROOT"
|
||||||
|
./bootstrap-vcpkg.sh
|
||||||
|
|
||||||
|
- name: Configure (cmake --preset)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cmake --preset linux-release-vcpkg \
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
|
-DOMATH_BUILD_EXAMPLES=OFF \
|
||||||
|
-DOMATH_BUILD_TESTS=ON \
|
||||||
|
-DOMATH_BUILD_BENCHMARK=ON \
|
||||||
|
-DOMATH_ENABLE_VALGRIND=ON \
|
||||||
|
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests;benchmark"
|
||||||
|
|
||||||
|
- name: Build All Targets
|
||||||
|
shell: bash
|
||||||
|
run: cmake --build cmake-build/build/linux-release-vcpkg
|
||||||
|
|
||||||
|
- name: Run Valgrind (All Registered Targets)
|
||||||
|
shell: bash
|
||||||
|
working-directory: cmake-build/build/linux-release-vcpkg
|
||||||
|
run: |
|
||||||
|
cmake --build . --target valgrind_all
|
||||||
|
|||||||
14
.gitignore
vendored
@@ -1,4 +1,14 @@
|
|||||||
/cmake-build/
|
/cmake-build/
|
||||||
/.idea
|
|
||||||
/out
|
/out
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
|
/extlibs/vcpkg
|
||||||
|
.idea/workspace.xml
|
||||||
|
/build/
|
||||||
|
/clang-coverage/
|
||||||
|
*.gcov
|
||||||
|
*.bin
|
||||||
|
# pixi lock
|
||||||
|
pixi.lock
|
||||||
|
# pixi environments
|
||||||
|
.pixi/*
|
||||||
|
!.pixi/config.toml
|
||||||
|
|||||||
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
|||||||
[submodule "extlibs/googletest"]
|
|
||||||
path = extlibs/googletest
|
|
||||||
url = https://github.com/google/googletest.git
|
|
||||||
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
209
.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<RiderCodeStyleSettings>
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="LINE_BREAK" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Classes_0020and_0020structs/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Classes_0020and_0020structs/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Concepts/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Concepts/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Enums/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Enums/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Unions/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Unions/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Template_0020parameters/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Template_0020parameters/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Parameters/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Local_0020variables/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Local_0020variables/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020variables/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020variables/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020functions/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020functions/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020methods/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020methods/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020fields/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020fields/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020public_0020fields/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020public_0020fields/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Union_0020members/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Union_0020members/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Enumerators/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Enumerators/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Other_0020constants/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Other_0020constants/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020constants/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020constants/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Namespaces/@EntryIndexedValue" value="<NamingElement Priority="1"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="namespace" /><type Name="namespace alias" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Typedefs/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Typedefs/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Macros/@EntryIndexedValue" value="<NamingElement Priority="7"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="macro" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AA_BB" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Properties/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Properties/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Events/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Events/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Types/@EntryIndexedValue" value="<NamingElement Priority="2"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="__interface" /><type Name="class" /><type Name="concept" /><type Name="enum" /><type Name="struct" /><type Name="type alias" /><type Name="type template parameter" /><type Name="typedef" /><type Name="union" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Functions/@EntryIndexedValue" value="<NamingElement Priority="3"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="global function" /><type Name="member function" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Fields/@EntryIndexedValue" value="<NamingElement Priority="4"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="class field" /><type Name="struct field" /><type Name="union member" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Variables/@EntryIndexedValue" value="<NamingElement Priority="5"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="global variable" /><type Name="local variable" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINKAGE_SPECIFICATION_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=0B82708A1BA7774EB13D27F245698A56/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=0B82708A1BA7774EB13D27F245698A56/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A42D627FA43B054F91D1E1C4281D8896/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A42D627FA43B054F91D1E1C4281D8896/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A7EBF16DA3BDCB42A0B710704BC8A053/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A7EBF16DA3BDCB42A0B710704BC8A053/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2229A2BE1AA9214483A51F028530E042/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2229A2BE1AA9214483A51F028530E042/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=18392FF80FA40749AA8CC53981A32AE0/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=18392FF80FA40749AA8CC53981A32AE0/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=1350D079A82E0740947E85445B5AF47C/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=1350D079A82E0740947E85445B5AF47C/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=0AFB7787612DF743B09AD9412E48D4CC/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=0AFB7787612DF743B09AD9412E48D4CC/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=72514D5DF422D442B71A277F97B72887/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=72514D5DF422D442B71A277F97B72887/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=821F3C5CF47D5640AD3511BCBADE17C4/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=821F3C5CF47D5640AD3511BCBADE17C4/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=8F69F48E2532F54CBAA0039D4557825E/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=8F69F48E2532F54CBAA0039D4557825E/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=B6E900853D6D05429D8C57765B2E546A/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=B6E900853D6D05429D8C57765B2E546A/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=B82A063F0DDD98498A70D8D7EBB97F8D/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=B82A063F0DDD98498A70D8D7EBB97F8D/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=BBE8AA08E662BF409B2CB08EC597C493/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=BBE8AA08E662BF409B2CB08EC597C493/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=5653BA7B6222F349B94149A2A53C35B8/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=5653BA7B6222F349B94149A2A53C35B8/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=4203BE6F332C5149B409B4D5F7197E54/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=4203BE6F332C5149B409B4D5F7197E54/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2B232F1067F0324F8FF4B9D63ACECDB2/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2B232F1067F0324F8FF4B9D63ACECDB2/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=BF0D1AE66D64FE4FAF613448A12051A0/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=BF0D1AE66D64FE4FAF613448A12051A0/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=1CBDD658AEE8EA4382EE1F914B5B3314/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=1CBDD658AEE8EA4382EE1F914B5B3314/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A4FAA2257682A94F8C2C93E123FAFC7A/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A4FAA2257682A94F8C2C93E123FAFC7A/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=05D45346A5B5B54F93A9F94C46B14079/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=05D45346A5B5B54F93A9F94C46B14079/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=9E4D28CA929F6B4AB5F6F3FEB9E69A47/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=9E4D28CA929F6B4AB5F6F3FEB9E69A47/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2AD8EC23F81C6F4AB06852FBF796A3D1/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2AD8EC23F81C6F4AB06852FBF796A3D1/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=299C42B75F5A8C4DB381AE89010A7CC8/@EntryIndexedValue" value="<NamingElement Priority="1" Title="Namespaces"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="namespace" /><type Name="namespace alias" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A279BB9D47B8754E9482D81B5D3B3489/@EntryIndexedValue" value="<NamingElement Priority="2" Title="Types"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="__interface" /><type Name="class" /><type Name="concept" /><type Name="enum" /><type Name="struct" /><type Name="type alias" /><type Name="type template parameter" /><type Name="typedef" /><type Name="union" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=82D01E1970D2F6419CE2737C415D3A01/@EntryIndexedValue" value="<NamingElement Priority="3" Title="Functions"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="global function" /><type Name="member function" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2A0CD4590563D04B89402AC0279B5E10/@EntryIndexedValue" value="<NamingElement Priority="4" Title="Fields"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="class field" /><type Name="struct field" /><type Name="union member" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=DC1F6BB6E0EFFC49A38E940DB8A84CF6/@EntryIndexedValue" value="<NamingElement Priority="5" Title="Variables"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="global variable" /><type Name="lambda" /><type Name="local variable" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=AA17EF9DE2E5364DAEBE52F9EBBEA658/@EntryIndexedValue" value="<NamingElement Priority="6" Title="Parameters"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="function parameter" /><type Name="lambda parameter" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=9BA140847B0718418342A07C8F0CE1ED/@EntryIndexedValue" value="<NamingElement Priority="7" Title="Macros"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="macro" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AA_BB" /></NamingElement>" type="string" />
|
||||||
|
</RiderCodeStyleSettings>
|
||||||
|
<clangFormatSettings>
|
||||||
|
<option name="ENABLED" value="true" />
|
||||||
|
</clangFormatSettings>
|
||||||
|
<files>
|
||||||
|
<extensions>
|
||||||
|
<pair source="cpp" header="hpp" fileNamingConvention="SNAKE_CASE" />
|
||||||
|
<pair source="c" header="h" fileNamingConvention="NONE" />
|
||||||
|
<pair source="cu" header="cuh" fileNamingConvention="NONE" />
|
||||||
|
<pair source="ixx" header="" fileNamingConvention="NONE" />
|
||||||
|
<pair source="mxx" header="" fileNamingConvention="NONE" />
|
||||||
|
<pair source="cppm" header="" fileNamingConvention="NONE" />
|
||||||
|
<pair source="ccm" header="" fileNamingConvention="NONE" />
|
||||||
|
<pair source="cxxm" header="" fileNamingConvention="NONE" />
|
||||||
|
<pair source="c++m" header="" fileNamingConvention="NONE" />
|
||||||
|
</extensions>
|
||||||
|
</files>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
||||||
6
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
6
.idea/developer-tools.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DeveloperToolsToolWindowSettingsV1" lastSelectedContentNodeId="code-style-formatting" pluginVersion="7.0.0">
|
||||||
|
<developerToolsConfigurations />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
435
.idea/editor.xml
generated
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="BackendCodeEditorSettings">
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CDeclarationWithImplicitIntType/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConstevalIfIsAlwaysConstant/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractClassWithoutSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractVirtualFunctionCallInCtor/@EntryIndexedValue" value="ERROR" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAccessSpecifierWithNoDeclarations/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAwaiterTypeIsNotClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBooleanIncrementExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatBadCode/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatLegacyCode/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatMixedArgs/@EntryIndexedValue" value="ERROR" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooFewArgs/@EntryIndexedValue" value="ERROR" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCompileTimeConstantCanBeReplacedWithBooleanConstant/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConceptNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConditionalExpressionCanBeSimplified/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorDisambiguatedAsFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorUsedBeforeInitialization/@EntryIndexedValue" value="ERROR" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultCaseNotHandledInSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedEntity/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedOverridenMethod/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedRegisterStorageClassSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDereferenceOperatorLimitExceeded/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDiscardedPostfixOperatorResult/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenSyntaxError/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUndocumentedParameter/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUnresolvedReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEmptyDeclaration/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersOrder/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersPlacement/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceDoStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceForStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceFunctionDeclarationStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceIfStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceNestedNamespacesStyle/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingDestructorStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingFunctionStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceTypeAliasCodeStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceWhileStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityAssignedButNoRead/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityUsedOnlyInUnevaluatedContext/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnumeratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEqualOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEvaluationFailure/@EntryIndexedValue" value="ERROR" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExplicitSpecializationInNonNamespaceScope/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExpressionWithoutSideEffects/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalFunctionInFinalClass/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalNonOverridingVirtualFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForLoopCanBeReplacedWithWhile/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForwardEnumDeclarationWithoutUnderlyingType/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionDoesntReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionResultShouldBeUsed/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionalStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHeaderHasBeenAlreadyIncluded/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHiddenFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHidingFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIdenticalOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIfCanBeReplacedByConstexprIf/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppImplicitDefaultConstructorNotAvailable/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompatiblePointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompleteSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInconsistentNaming/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIntegralToPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInvalidLineContinuation/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppJoinDeclarationAndAssignment/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingKeywordThrow/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppModulePartitionWithSeveralPartitionUnits/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtAddressOfClassRValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtBindingRValueToLvalueReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtCopyElisionInCopyInitDeclarator/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtDoubleUserConversionInCopyInit/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtNotInitializedStaticConstLocalVar/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtReinterpretCastFromNullptr/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterLiteral/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterWideLiteral/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMustBePublicVirtualToImplementInterface/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMutableSpecifierOnReferenceMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNoDiscardExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNodiscardFunctionWithoutReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExceptionSafeResourceAcquisition/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConversionOperator/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConvertingConstructor/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineFunctionDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineVariableDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPassValueParameterByConstReference/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerConversionDropsQualifiers/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerToIntegralConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPolymorphicClassWithNonVirtualPublicDestructor/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyErroneousEmptyStatements/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUnintendedObjectSlicing/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderIsNotIncluded/@EntryIndexedValue" value="ERROR" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderNotFound/@EntryIndexedValue" value="ERROR" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfBadFormat/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfExtraArg/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfMissedArg/@EntryIndexedValue" value="ERROR" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfRiskyFormat/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrivateSpecialMemberFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRangeBasedForIncompatibleReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedefinitionOfDefaultArgumentInOverrideFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBooleanExpressionArgument/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantCastExpression/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantComplexityInComparison/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConditionalExpression/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConstSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantControlFlowJump/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantDereferencingAndTakingAddress/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElaboratedTypeSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeyword/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeywordInsideCompoundStatement/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyDeclaration/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyStatement/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantExportKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantFwdClassOrEnumSpecifier/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantInlineSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantLambdaParameterList/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantMemberInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantNamespaceDefinition/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantParentheses/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifierADL/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnMemberAllocationFunction/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnThreadLocalLocalVariable/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateArguments/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantVoidArgumentList/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantZeroInitializerInAggregateInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReinterpretCastFromVoidPtr/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRemoveRedundantBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceMemsetWithZeroInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceTieWithStructuredBinding/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReturnNoValueInNonVoidFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSmartPointerVsMakeFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSomeObjectMembersMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSpecialFunctionWithoutNoexceptSpecification/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticAssertFailure/@EntryIndexedValue" value="ERROR" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticDataMemberInUnnamedStruct/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticSpecifierOnAnonymousNamespaceMember/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStringLiteralToCharPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTabsAreDisallowed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateArgumentsCanBeDeduced/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterShadowing/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppThrowExpressionCanBeReplacedWithRethrow/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScope/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScopeInitStatement/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTypeAliasNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedDependentBaseClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedNonStaticDataMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnionMemberOfReferenceType/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaEndRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnamedNamespaceInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnecessaryWhitespace/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnsignedZeroComparison/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnusedIncludeDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAlgorithmWithCount/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAssociativeContains/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAuto/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAutoForNumeric/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseElementsView/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseEraseAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseFamiliarTemplateSyntaxForGenericLambdas/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseRangeAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStdSize/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStructuredBinding/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseTypeTraitAlias/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUserDefinedLiteralSuffixDoesNotStartWithUnderscore/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUsingResultOfAssignmentAsCondition/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVariableCanBeMadeConstexpr/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionCallInsideCtor/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionInFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVolatileParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWarningDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongIncludesOrder/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongSlashesInIncludeDirective/@EntryIndexedValue" value="HINT" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroConstantCanBeReplacedWithNullptr/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroValuedExpressionUsedAsNullPointer/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
|
||||||
|
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINKAGE_SPECIFICATION_BRACES/@EntryValue" value="NEXT_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="LINE_BREAK" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020fields/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020fields/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020methods/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020methods/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020public_0020fields/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Class_0020and_0020struct_0020public_0020fields/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Classes_0020and_0020structs/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Classes_0020and_0020structs/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Concepts/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Concepts/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Enumerators/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Enumerators/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Enums/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Enums/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Events/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Events/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Fields/@EntryIndexedValue" value="<NamingElement Priority="4"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="class field" /><type Name="struct field" /><type Name="union member" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Functions/@EntryIndexedValue" value="<NamingElement Priority="3"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="global function" /><type Name="member function" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020constants/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020constants/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020functions/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020functions/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020variables/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Global_0020variables/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Local_0020variables/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Local_0020variables/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Macros/@EntryIndexedValue" value="<NamingElement Priority="7"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="macro" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AA_BB" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Namespaces/@EntryIndexedValue" value="<NamingElement Priority="1"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="namespace" /><type Name="namespace alias" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Other_0020constants/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Other_0020constants/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Parameters/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Properties/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Properties/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Template_0020parameters/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Template_0020parameters/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Typedefs/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Typedefs/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Types/@EntryIndexedValue" value="<NamingElement Priority="2"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="__interface" /><type Name="class" /><type Name="concept" /><type Name="enum" /><type Name="struct" /><type Name="type alias" /><type Name="type template parameter" /><type Name="typedef" /><type Name="union" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Union_0020members/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Union_0020members/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Unions/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Unions/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNaming/Rules/=Variables/@EntryIndexedValue" value="<NamingElement Priority="5"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="global variable" /><type Name="local variable" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=05D45346A5B5B54F93A9F94C46B14079/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=05D45346A5B5B54F93A9F94C46B14079/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=0AFB7787612DF743B09AD9412E48D4CC/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=0AFB7787612DF743B09AD9412E48D4CC/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=0B82708A1BA7774EB13D27F245698A56/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=0B82708A1BA7774EB13D27F245698A56/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=1350D079A82E0740947E85445B5AF47C/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=1350D079A82E0740947E85445B5AF47C/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=18392FF80FA40749AA8CC53981A32AE0/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=18392FF80FA40749AA8CC53981A32AE0/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=1CBDD658AEE8EA4382EE1F914B5B3314/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=1CBDD658AEE8EA4382EE1F914B5B3314/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2229A2BE1AA9214483A51F028530E042/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2229A2BE1AA9214483A51F028530E042/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=299C42B75F5A8C4DB381AE89010A7CC8/@EntryIndexedValue" value="<NamingElement Priority="1" Title="Namespaces"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="namespace" /><type Name="namespace alias" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2A0CD4590563D04B89402AC0279B5E10/@EntryIndexedValue" value="<NamingElement Priority="4" Title="Fields"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="class field" /><type Name="struct field" /><type Name="union member" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2AD8EC23F81C6F4AB06852FBF796A3D1/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2AD8EC23F81C6F4AB06852FBF796A3D1/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2B232F1067F0324F8FF4B9D63ACECDB2/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=2B232F1067F0324F8FF4B9D63ACECDB2/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=4203BE6F332C5149B409B4D5F7197E54/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=4203BE6F332C5149B409B4D5F7197E54/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=5653BA7B6222F349B94149A2A53C35B8/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=5653BA7B6222F349B94149A2A53C35B8/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=72514D5DF422D442B71A277F97B72887/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=72514D5DF422D442B71A277F97B72887/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=821F3C5CF47D5640AD3511BCBADE17C4/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=821F3C5CF47D5640AD3511BCBADE17C4/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=82D01E1970D2F6419CE2737C415D3A01/@EntryIndexedValue" value="<NamingElement Priority="3" Title="Functions"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="global function" /><type Name="member function" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=8F69F48E2532F54CBAA0039D4557825E/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=8F69F48E2532F54CBAA0039D4557825E/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=9BA140847B0718418342A07C8F0CE1ED/@EntryIndexedValue" value="<NamingElement Priority="7" Title="Macros"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="macro" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AA_BB" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=9E4D28CA929F6B4AB5F6F3FEB9E69A47/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=9E4D28CA929F6B4AB5F6F3FEB9E69A47/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A279BB9D47B8754E9482D81B5D3B3489/@EntryIndexedValue" value="<NamingElement Priority="2" Title="Types"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="__interface" /><type Name="class" /><type Name="concept" /><type Name="enum" /><type Name="struct" /><type Name="type alias" /><type Name="type template parameter" /><type Name="typedef" /><type Name="union" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A42D627FA43B054F91D1E1C4281D8896/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A42D627FA43B054F91D1E1C4281D8896/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A4FAA2257682A94F8C2C93E123FAFC7A/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A4FAA2257682A94F8C2C93E123FAFC7A/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A7EBF16DA3BDCB42A0B710704BC8A053/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=A7EBF16DA3BDCB42A0B710704BC8A053/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=AA17EF9DE2E5364DAEBE52F9EBBEA658/@EntryIndexedValue" value="<NamingElement Priority="6" Title="Parameters"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="function parameter" /><type Name="lambda parameter" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=B6E900853D6D05429D8C57765B2E546A/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=B6E900853D6D05429D8C57765B2E546A/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=B82A063F0DDD98498A70D8D7EBB97F8D/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=B82A063F0DDD98498A70D8D7EBB97F8D/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=BBE8AA08E662BF409B2CB08EC597C493/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=BBE8AA08E662BF409B2CB08EC597C493/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=BF0D1AE66D64FE4FAF613448A12051A0/@EntryIndexRemoved" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=BF0D1AE66D64FE4FAF613448A12051A0/@EntryIndexedValue" value="" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=DC1F6BB6E0EFFC49A38E940DB8A84CF6/@EntryIndexedValue" value="<NamingElement Priority="5" Title="Variables"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="global variable" /><type Name="lambda" /><type Name="local variable" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aa_bb" /></NamingElement>" type="string" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
8
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="CppInconsistentNaming" enabled="true" level="HINT" enabled_by_default="true" />
|
||||||
|
<inspection_tool class="CppTabsAreDisallowed" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
<inspection_tool class="CppUnnecessaryWhitespace" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
7
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="PROJECT_PROFILE" value="Default" />
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
12
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CMakePythonSetting">
|
||||||
|
<option name="pythonIntegrationState" value="YES" />
|
||||||
|
</component>
|
||||||
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||||
|
<component name="CidrRootsConfiguration">
|
||||||
|
<excludeRoots>
|
||||||
|
<file path="$PROJECT_DIR$/cmake-build" />
|
||||||
|
</excludeRoots>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/omath.iml" filepath="$PROJECT_DIR$/.idea/omath.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
2
.idea/omath.iml
generated
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module classpath="CIDR" type="CPP_MODULE" version="4" />
|
||||||
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
24
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": " Unit Tests (Debug)",
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceRoot}/out/Debug/unit_tests",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceRoot}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": " Unit Tests (Release)",
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceRoot}/out/Release/unit_tests",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceRoot}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
264
CMakeLists.txt
@@ -1,145 +1,231 @@
|
|||||||
cmake_minimum_required(VERSION 3.26)
|
cmake_minimum_required(VERSION 3.26)
|
||||||
|
|
||||||
project(omath VERSION 1.0.1 LANGUAGES CXX)
|
file(READ VERSION OMATH_VERSION)
|
||||||
|
project(omath VERSION ${OMATH_VERSION} LANGUAGES CXX)
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
|
include(CheckCXXCompilerFlag)
|
||||||
|
|
||||||
|
include(cmake/Coverage.cmake)
|
||||||
|
include(cmake/Valgrind.cmake)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
check_cxx_compiler_flag("/arch:AVX2" COMPILER_SUPPORTS_AVX2)
|
||||||
|
else()
|
||||||
|
check_cxx_compiler_flag("-mavx2" COMPILER_SUPPORTS_AVX2)
|
||||||
|
endif()
|
||||||
|
|
||||||
option(OMATH_BUILD_TESTS "Build unit tests" OFF)
|
option(OMATH_BUILD_TESTS "Build unit tests" OFF)
|
||||||
option(OMATH_THREAT_WARNING_AS_ERROR "Set highest level of warnings and force compiler to treat them as errors" ON)
|
option(OMATH_BUILD_BENCHMARK "Build benchmarks" OFF)
|
||||||
|
option(OMATH_THREAT_WARNING_AS_ERROR
|
||||||
|
"Set highest level of warnings and force compiler to treat them as errors" ON)
|
||||||
option(OMATH_BUILD_AS_SHARED_LIBRARY "Build Omath as .so or .dll" OFF)
|
option(OMATH_BUILD_AS_SHARED_LIBRARY "Build Omath as .so or .dll" OFF)
|
||||||
option(OMATH_USE_AVX2 "Omath will use AVX2 to boost performance" ON)
|
option(OMATH_USE_AVX2 "Omath will use AVX2 to boost performance" ${COMPILER_SUPPORTS_AVX2})
|
||||||
option(OMATH_IMGUI_INTEGRATION "Omath will define method to convert omath types to imgui types" OFF)
|
option(OMATH_IMGUI_INTEGRATION "Omath will define method to convert omath types to imgui types" OFF)
|
||||||
option(OMATH_BUILD_EXAMPLES "Build example projects with you can learn & play" OFF)
|
option(OMATH_BUILD_EXAMPLES "Build example projects with you can learn & play" OFF)
|
||||||
option(OMATH_STATIC_MSVC_RUNTIME_LIBRARY "Force Omath to link static runtime" OFF)
|
option(OMATH_STATIC_MSVC_RUNTIME_LIBRARY "Force Omath to link static runtime" OFF)
|
||||||
option(OMATH_SUPRESS_SAFETY_CHECKS "Supress some safety checks in release build to improve general performance" ON)
|
option(OMATH_ENABLE_LEGACY
|
||||||
option(OMATH_USE_UNITY_BUILD "Will enable unity build to speed up compilation" ON)
|
"Will enable legacy classes that MUST be used ONLY for backward compatibility" ON)
|
||||||
|
option(OMATH_SUPRESS_SAFETY_CHECKS
|
||||||
|
"Supress some safety checks in release build to improve general performance" ON)
|
||||||
|
option(OMATH_ENABLE_COVERAGE "Enable coverage" OFF)
|
||||||
|
option(OMATH_ENABLE_FORCE_INLINE
|
||||||
|
"Will for compiler to make some functions to be force inlined no matter what" ON)
|
||||||
|
if(VCPKG_MANIFEST_FEATURES)
|
||||||
|
foreach(omath_feature IN LISTS VCPKG_MANIFEST_FEATURES)
|
||||||
|
if(omath_feature STREQUAL "imgui")
|
||||||
|
set(OMATH_IMGUI_INTEGRATION ON)
|
||||||
|
elseif(omath_feature STREQUAL "avx2")
|
||||||
|
set(OMATH_USE_AVX2 ${COMPILER_SUPPORTS_AVX2})
|
||||||
|
elseif(omath_feature STREQUAL "tests")
|
||||||
|
set(OMATH_BUILD_TESTS ON)
|
||||||
|
elseif(omath_feature STREQUAL "benchmark")
|
||||||
|
set(OMATH_BUILD_BENCHMARK ON)
|
||||||
|
elseif(omath_feature STREQUAL "examples")
|
||||||
|
set(OMATH_BUILD_EXAMPLES ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OMATH_USE_AVX2 AND NOT COMPILER_SUPPORTS_AVX2)
|
||||||
|
message(
|
||||||
|
WARNING "OMATH_USE_AVX2 requested, but compiler/target does not support AVX2. Disabling.")
|
||||||
|
set(OMATH_USE_AVX2 OFF CACHE BOOL "Omath will use AVX2 to boost performance" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${PROJECT_IS_TOP_LEVEL})
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"[${PROJECT_NAME}]: Building on ${CMAKE_HOST_SYSTEM_NAME}, compiler ${CMAKE_CXX_COMPILER_ID}"
|
||||||
|
)
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: Warnings as errors ${OMATH_THREAT_WARNING_AS_ERROR}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: Build unit tests ${OMATH_BUILD_TESTS}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: Build benchmark ${OMATH_BUILD_BENCHMARK}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: As dynamic library ${OMATH_BUILD_AS_SHARED_LIBRARY}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: Static C++ runtime ${OMATH_STATIC_MSVC_RUNTIME_LIBRARY}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: CMake unity build ${OMATH_USE_UNITY_BUILD}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: Example projects ${OMATH_BUILD_EXAMPLES}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: AVX2 feature status ${OMATH_USE_AVX2}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: ImGUI integration feature status ${OMATH_IMGUI_INTEGRATION}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: Legacy features support ${OMATH_ENABLE_LEGACY}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: Building using vcpkg ${OMATH_BUILD_VIA_VCPKG}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: Coverage feature status ${OMATH_ENABLE_COVERAGE}")
|
||||||
|
message(STATUS "[${PROJECT_NAME}]: Valgrind feature status ${OMATH_ENABLE_VALGRIND}")
|
||||||
|
endif()
|
||||||
|
|
||||||
file(GLOB_RECURSE OMATH_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
|
file(GLOB_RECURSE OMATH_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
|
||||||
file(GLOB_RECURSE OMATH_HEADERS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
|
file(GLOB_RECURSE OMATH_HEADERS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
|
||||||
|
|
||||||
|
if(OMATH_BUILD_AS_SHARED_LIBRARY)
|
||||||
|
add_library(${PROJECT_NAME} SHARED ${OMATH_SOURCES} ${OMATH_HEADERS})
|
||||||
|
else()
|
||||||
|
add_library(${PROJECT_NAME} STATIC ${OMATH_SOURCES} ${OMATH_HEADERS})
|
||||||
|
endif()
|
||||||
|
|
||||||
if (OMATH_BUILD_AS_SHARED_LIBRARY)
|
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
||||||
add_library(omath SHARED ${OMATH_SOURCES} ${OMATH_HEADERS})
|
|
||||||
else ()
|
|
||||||
add_library(omath STATIC ${OMATH_SOURCES} ${OMATH_HEADERS})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
message(STATUS "Building on ${CMAKE_HOST_SYSTEM_NAME}")
|
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_VERSION="${PROJECT_VERSION}")
|
||||||
add_library(omath::omath ALIAS omath)
|
|
||||||
|
|
||||||
if (OMATH_IMGUI_INTEGRATION)
|
if(OMATH_IMGUI_INTEGRATION)
|
||||||
target_compile_definitions(omath PUBLIC OMATH_IMGUI_INTEGRATION)
|
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_IMGUI_INTEGRATION)
|
||||||
|
|
||||||
# IMGUI is being linked as submodule
|
# IMGUI is being linked as submodule
|
||||||
if (TARGET imgui)
|
if(TARGET imgui)
|
||||||
target_link_libraries(omath PUBLIC imgui)
|
target_link_libraries(${PROJECT_NAME} PUBLIC imgui)
|
||||||
install(TARGETS imgui
|
install(
|
||||||
EXPORT omathTargets
|
TARGETS imgui
|
||||||
ARCHIVE DESTINATION lib
|
EXPORT omathTargets
|
||||||
LIBRARY DESTINATION lib
|
ARCHIVE DESTINATION lib
|
||||||
RUNTIME DESTINATION bin)
|
LIBRARY DESTINATION lib
|
||||||
else ()
|
RUNTIME DESTINATION bin)
|
||||||
|
else()
|
||||||
# Assume that IMGUI linked via VCPKG.
|
# Assume that IMGUI linked via VCPKG.
|
||||||
find_package(imgui CONFIG REQUIRED)
|
find_package(imgui CONFIG REQUIRED)
|
||||||
target_link_libraries(omath PUBLIC imgui::imgui)
|
target_link_libraries(${PROJECT_NAME} PUBLIC imgui::imgui)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (OMATH_USE_AVX2)
|
if(OMATH_USE_AVX2)
|
||||||
target_compile_definitions(omath PUBLIC OMATH_USE_AVX2)
|
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_USE_AVX2)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (OMATH_SUPRESS_SAFETY_CHECKS)
|
if(OMATH_SUPRESS_SAFETY_CHECKS)
|
||||||
target_compile_definitions(omath PUBLIC OMATH_SUPRESS_SAFETY_CHECKS)
|
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_SUPRESS_SAFETY_CHECKS)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
set_target_properties(omath PROPERTIES
|
if(OMATH_ENABLE_LEGACY)
|
||||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_ENABLE_LEGACY)
|
||||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
endif()
|
||||||
CXX_STANDARD 23
|
|
||||||
CXX_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
if (OMATH_USE_UNITY_BUILD)
|
if(OMATH_ENABLE_FORCE_INLINE)
|
||||||
set_target_properties(omath PROPERTIES
|
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_ENABLE_FORCE_INLINE)
|
||||||
UNITY_BUILD ON
|
endif()
|
||||||
UNITY_BUILD_BATCH_SIZE 20)
|
|
||||||
endif ()
|
set_target_properties(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
||||||
|
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
||||||
|
CXX_STANDARD 23
|
||||||
|
CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
if (OMATH_STATIC_MSVC_RUNTIME_LIBRARY)
|
if (OMATH_STATIC_MSVC_RUNTIME_LIBRARY)
|
||||||
set_target_properties(omath PROPERTIES
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>"
|
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>"
|
||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if(OMATH_USE_AVX2)
|
||||||
target_compile_options(omath PRIVATE -mavx2 -mfma)
|
if(MSVC)
|
||||||
endif ()
|
target_compile_options(${PROJECT_NAME} PUBLIC /arch:AVX2)
|
||||||
|
elseif(EMSCRIPTEN)
|
||||||
|
target_compile_options(${PROJECT_NAME} PUBLIC -msimd128 -mavx2)
|
||||||
|
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
||||||
|
target_compile_options(${PROJECT_NAME} PUBLIC -mfma -mavx2)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
target_compile_features(omath PUBLIC cxx_std_23)
|
if(EMSCRIPTEN)
|
||||||
|
target_compile_options(${PROJECT_NAME} PUBLIC -fexceptions)
|
||||||
|
target_link_options(${PROJECT_NAME} PUBLIC -fexceptions)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23)
|
||||||
|
|
||||||
if (OMATH_BUILD_TESTS)
|
if(OMATH_BUILD_TESTS)
|
||||||
add_subdirectory(extlibs)
|
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif ()
|
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_BUILD_TESTS)
|
||||||
|
if(OMATH_ENABLE_COVERAGE)
|
||||||
|
omath_setup_coverage(${PROJECT_NAME})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if (OMATH_BUILD_EXAMPLES)
|
if(OMATH_BUILD_BENCHMARK)
|
||||||
|
add_subdirectory(benchmark)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OMATH_BUILD_EXAMPLES)
|
||||||
add_subdirectory(examples)
|
add_subdirectory(examples)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND OMATH_THREAT_WARNING_AS_ERROR)
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND OMATH_THREAT_WARNING_AS_ERROR)
|
||||||
target_compile_options(omath PRIVATE /W4 /WX)
|
target_compile_options(${PROJECT_NAME} PRIVATE /W4 /WX)
|
||||||
elseif (OMATH_THREAT_WARNING_AS_ERROR)
|
elseif(OMATH_THREAT_WARNING_AS_ERROR)
|
||||||
target_compile_options(omath PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
||||||
endif ()
|
endif()
|
||||||
|
|
||||||
target_include_directories(omath
|
# Windows SDK redefine min/max via preprocessor and break std::min and std::max
|
||||||
PUBLIC
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> # Use this path when building the project
|
target_compile_definitions(${PROJECT_NAME} INTERFACE NOMINMAX)
|
||||||
$<INSTALL_INTERFACE:include> # Use this path when the project is installed
|
endif()
|
||||||
)
|
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> # Use this path
|
||||||
|
# when building
|
||||||
|
# the project
|
||||||
|
$<INSTALL_INTERFACE:include> # Use this path when the project is
|
||||||
|
# installed
|
||||||
|
)
|
||||||
|
|
||||||
# Installation rules
|
# Installation rules
|
||||||
|
|
||||||
# Install the library
|
# Install the library
|
||||||
install(TARGETS omath
|
install(
|
||||||
EXPORT omathTargets
|
TARGETS ${PROJECT_NAME}
|
||||||
ARCHIVE DESTINATION lib COMPONENT omath # For static libraries
|
EXPORT ${PROJECT_NAME}Targets
|
||||||
LIBRARY DESTINATION lib COMPONENT omath # For shared libraries
|
ARCHIVE DESTINATION lib COMPONENT ${PROJECT_NAME} # For static libraries
|
||||||
RUNTIME DESTINATION bin COMPONENT omath # For executables (on Windows)
|
LIBRARY DESTINATION lib COMPONENT ${PROJECT_NAME} # For shared libraries
|
||||||
)
|
RUNTIME DESTINATION bin COMPONENT ${PROJECT_NAME} # For executables (on
|
||||||
|
# Windows)
|
||||||
|
)
|
||||||
|
|
||||||
# Install headers as part of omath_component
|
# Install headers as part of omath_component
|
||||||
install(DIRECTORY include/ DESTINATION include COMPONENT omath)
|
install(DIRECTORY include/ DESTINATION include COMPONENT ${PROJECT_NAME})
|
||||||
|
|
||||||
# Export omath target for CMake find_package support, also under omath_component
|
# Export omath target for CMake find_package support, also under omath_component
|
||||||
install(EXPORT omathTargets
|
install(
|
||||||
FILE omathTargets.cmake
|
EXPORT ${PROJECT_NAME}Targets
|
||||||
NAMESPACE omath::
|
FILE ${PROJECT_NAME}Targets.cmake
|
||||||
DESTINATION lib/cmake/omath COMPONENT omath
|
NAMESPACE ${PROJECT_NAME}::
|
||||||
)
|
DESTINATION lib/cmake/${PROJECT_NAME}
|
||||||
|
COMPONENT ${PROJECT_NAME})
|
||||||
|
|
||||||
# Generate the omathConfigVersion.cmake file
|
# Generate the omathConfigVersion.cmake file
|
||||||
write_basic_package_version_file(
|
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/omathConfigVersion.cmake"
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/omathConfigVersion.cmake"
|
VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion)
|
||||||
VERSION ${PROJECT_VERSION}
|
|
||||||
COMPATIBILITY AnyNewerVersion
|
|
||||||
)
|
|
||||||
|
|
||||||
# Generate the omathConfig.cmake file from the template (which is in the cmake/ folder)
|
# Generate the omathConfig.cmake file from the template (which is in the cmake/
|
||||||
|
# folder)
|
||||||
configure_package_config_file(
|
configure_package_config_file(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/omathConfig.cmake.in" # Path to the .in file
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/omathConfig.cmake.in" # Path to the .in
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/omathConfig.cmake" # Output path for the generated file
|
# file
|
||||||
INSTALL_DESTINATION lib/cmake/omath
|
"${CMAKE_CURRENT_BINARY_DIR}/omathConfig.cmake" # Output path for the
|
||||||
)
|
# generated file
|
||||||
|
INSTALL_DESTINATION lib/cmake/${PROJECT_NAME})
|
||||||
|
|
||||||
# Install the generated config files
|
# Install the generated config files
|
||||||
install(FILES
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/omathConfig.cmake"
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/omathConfig.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/omathConfigVersion.cmake"
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/omathConfigVersion.cmake"
|
DESTINATION lib/cmake/${PROJECT_NAME})
|
||||||
DESTINATION lib/cmake/omath
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,14 +1,48 @@
|
|||||||
{
|
{
|
||||||
"version": 3,
|
"version": 6,
|
||||||
|
"cmakeMinimumRequired": {
|
||||||
|
"major": 3,
|
||||||
|
"minor": 25,
|
||||||
|
"patch": 0
|
||||||
|
},
|
||||||
|
|
||||||
"configurePresets": [
|
"configurePresets": [
|
||||||
{
|
{
|
||||||
"name": "windows-base",
|
"name": "base",
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"generator": "Ninja",
|
"generator": "Ninja",
|
||||||
"binaryDir": "${sourceDir}/cmake-build/build/${presetName}",
|
"binaryDir": "${sourceDir}/cmake-build/build/${presetName}",
|
||||||
"installDir": "${sourceDir}/cmake-build/install/${presetName}",
|
"installDir": "${sourceDir}/cmake-build/install/${presetName}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"cacheVariables": {
|
||||||
|
"OMATH_BUILD_VIA_VCPKG": "ON",
|
||||||
|
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||||
|
"VCPKG_INSTALLED_DIR": "${sourceDir}/cmake-build/vcpkg_installed"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "debug",
|
||||||
|
"hidden": true,
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Debug"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "release",
|
||||||
|
"hidden": true,
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Release"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "windows-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "base",
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_C_COMPILER": "cl.exe",
|
|
||||||
"CMAKE_CXX_COMPILER": "cl.exe"
|
"CMAKE_CXX_COMPILER": "cl.exe"
|
||||||
},
|
},
|
||||||
"condition": {
|
"condition": {
|
||||||
@@ -18,61 +52,176 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "windows-debug",
|
"name": "windows-vcpkg-base",
|
||||||
"displayName": "Debug",
|
"hidden": true,
|
||||||
"inherits": "windows-base",
|
"inherits": ["windows-base", "vcpkg-base"],
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_BUILD_TYPE": "Debug"
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-debug",
|
||||||
|
"displayName": "Windows Debug",
|
||||||
|
"inherits": ["windows-base", "debug"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "windows-release",
|
"name": "windows-release",
|
||||||
"displayName": "Release",
|
"displayName": "Windows Release",
|
||||||
"inherits": "windows-base",
|
"inherits": ["windows-base", "release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-debug-vcpkg",
|
||||||
|
"displayName": "Windows Debug (vcpkg)",
|
||||||
|
"inherits": ["windows-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-release-vcpkg",
|
||||||
|
"displayName": "Windows Release (vcpkg)",
|
||||||
|
"inherits": ["windows-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "windows-x86-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["windows-base", "vcpkg-base"],
|
||||||
|
"architecture": {
|
||||||
|
"value": "x86",
|
||||||
|
"strategy": "external"
|
||||||
|
},
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_BUILD_TYPE": "Release"
|
"VCPKG_TARGET_TRIPLET": "x86-windows",
|
||||||
|
"VCPKG_HOST_TRIPLET": "x64-windows",
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-debug-vcpkg-x86",
|
||||||
|
"displayName": "Windows x86 Debug (vcpkg)",
|
||||||
|
"inherits": ["windows-x86-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-release-vcpkg-x86",
|
||||||
|
"displayName": "Windows x86 Release (vcpkg)",
|
||||||
|
"inherits": ["windows-x86-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "windows-arm64-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["windows-base", "vcpkg-base"],
|
||||||
|
"architecture": {
|
||||||
|
"value": "arm64",
|
||||||
|
"strategy": "external"
|
||||||
|
},
|
||||||
|
"cacheVariables": {
|
||||||
|
"VCPKG_TARGET_TRIPLET": "arm64-windows",
|
||||||
|
"VCPKG_HOST_TRIPLET": "arm64-windows",
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui;examples"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-debug-vcpkg-arm64",
|
||||||
|
"displayName": "Windows ARM64 Debug (vcpkg)",
|
||||||
|
"inherits": ["windows-arm64-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-release-vcpkg-arm64",
|
||||||
|
"displayName": "Windows ARM64 Release (vcpkg)",
|
||||||
|
"inherits": ["windows-arm64-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "linux-base",
|
"name": "linux-base",
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"generator": "Ninja",
|
"inherits": "base",
|
||||||
"binaryDir": "${sourceDir}/cmake-build/build/${presetName}",
|
|
||||||
"installDir": "${sourceDir}/cmake-build/install/${presetName}",
|
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_C_COMPILER": "clang",
|
|
||||||
"CMAKE_CXX_COMPILER": "clang++"
|
|
||||||
},
|
|
||||||
"condition": {
|
"condition": {
|
||||||
"type": "equals",
|
"type": "equals",
|
||||||
"lhs": "${hostSystemName}",
|
"lhs": "${hostSystemName}",
|
||||||
"rhs": "Linux"
|
"rhs": "Linux"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["linux-base", "vcpkg-base"],
|
||||||
|
"cacheVariables": {
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "linux-debug",
|
"name": "linux-debug",
|
||||||
"displayName": "Linux Debug",
|
"displayName": "Linux Debug",
|
||||||
"inherits": "linux-base",
|
"inherits": ["linux-base", "debug"]
|
||||||
"cacheVariables": {
|
|
||||||
"CMAKE_BUILD_TYPE": "Debug"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "linux-release",
|
"name": "linux-release",
|
||||||
"displayName": "Linux Release",
|
"displayName": "Linux Release",
|
||||||
"inherits": "linux-debug",
|
"inherits": ["linux-base", "release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-debug-vcpkg",
|
||||||
|
"displayName": "Linux Debug (vcpkg)",
|
||||||
|
"inherits": ["linux-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-release-vcpkg",
|
||||||
|
"displayName": "Linux Release (vcpkg)",
|
||||||
|
"inherits": ["linux-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "linux-x86-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["linux-base", "vcpkg-base"],
|
||||||
|
"architecture": {
|
||||||
|
"value": "x86",
|
||||||
|
"strategy": "external"
|
||||||
|
},
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_BUILD_TYPE": "Release"
|
"CMAKE_C_FLAGS": "-m32",
|
||||||
|
"CMAKE_CXX_FLAGS": "-m32",
|
||||||
|
"VCPKG_TARGET_TRIPLET": "x86-linux",
|
||||||
|
"VCPKG_HOST_TRIPLET": "x64-linux",
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-debug-vcpkg-x86",
|
||||||
|
"displayName": "Linux x86 Debug (vcpkg)",
|
||||||
|
"inherits": ["linux-x86-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-release-vcpkg-x86",
|
||||||
|
"displayName": "Linux x86 Release (vcpkg)",
|
||||||
|
"inherits": ["linux-x86-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "linux-arm64-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["linux-base", "vcpkg-base"],
|
||||||
|
"cacheVariables": {
|
||||||
|
"VCPKG_TARGET_TRIPLET": "arm64-linux",
|
||||||
|
"VCPKG_HOST_TRIPLET": "arm64-linux",
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-debug-vcpkg-arm64",
|
||||||
|
"displayName": "Linux ARM64 Debug (vcpkg)",
|
||||||
|
"inherits": ["linux-arm64-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-release-vcpkg-arm64",
|
||||||
|
"displayName": "Linux ARM64 Release (vcpkg)",
|
||||||
|
"inherits": ["linux-arm64-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "darwin-base",
|
"name": "darwin-base",
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
"generator": "Ninja",
|
"inherits": "base",
|
||||||
"binaryDir": "${sourceDir}/cmake-build/build/${presetName}",
|
|
||||||
"installDir": "${sourceDir}/cmake-build/install/${presetName}",
|
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_C_COMPILER": "clang",
|
|
||||||
"CMAKE_CXX_COMPILER": "clang++"
|
"CMAKE_CXX_COMPILER": "clang++"
|
||||||
},
|
},
|
||||||
"condition": {
|
"condition": {
|
||||||
@@ -82,20 +231,456 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "darwin-debug",
|
"name": "darwin-vcpkg-base",
|
||||||
"displayName": "Darwin Debug",
|
"hidden": true,
|
||||||
"inherits": "darwin-base",
|
"inherits": ["darwin-base", "vcpkg-base"],
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_BUILD_TYPE": "Debug"
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "darwin-debug",
|
||||||
|
"displayName": "macOS Debug",
|
||||||
|
"inherits": ["darwin-base", "debug"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "darwin-release",
|
"name": "darwin-release",
|
||||||
"displayName": "Darwin Release",
|
"displayName": "macOS Release",
|
||||||
"inherits": "darwin-debug",
|
"inherits": ["darwin-base", "release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "darwin-debug-vcpkg",
|
||||||
|
"displayName": "macOS Debug (vcpkg)",
|
||||||
|
"inherits": ["darwin-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "darwin-release-vcpkg",
|
||||||
|
"displayName": "macOS Release (vcpkg)",
|
||||||
|
"inherits": ["darwin-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "darwin-x64-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["darwin-base", "vcpkg-base"],
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_BUILD_TYPE": "Release"
|
"CMAKE_OSX_ARCHITECTURES": "x86_64",
|
||||||
|
"VCPKG_TARGET_TRIPLET": "x64-osx",
|
||||||
|
"VCPKG_HOST_TRIPLET": "x64-osx",
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "darwin-debug-vcpkg-x64",
|
||||||
|
"displayName": "macOS x64 Debug (vcpkg)",
|
||||||
|
"inherits": ["darwin-x64-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "darwin-release-vcpkg-x64",
|
||||||
|
"displayName": "macOS x64 Release (vcpkg)",
|
||||||
|
"inherits": ["darwin-x64-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "ios-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_SYSTEM_NAME": "iOS",
|
||||||
|
"CMAKE_OSX_DEPLOYMENT_TARGET": "18.5",
|
||||||
|
"CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED": "NO",
|
||||||
|
"CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED": "NO"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Darwin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ios-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["ios-base", "vcpkg-base"],
|
||||||
|
"cacheVariables": {
|
||||||
|
"VCPKG_TARGET_TRIPLET": "arm64-ios",
|
||||||
|
"VCPKG_HOST_TRIPLET": "arm64-osx",
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ios-debug-vcpkg",
|
||||||
|
"displayName": "iOS Debug (vcpkg)",
|
||||||
|
"inherits": ["ios-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ios-release-vcpkg",
|
||||||
|
"displayName": "iOS Release (vcpkg)",
|
||||||
|
"inherits": ["ios-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "freebsd-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_COMPILER": "clang",
|
||||||
|
"CMAKE_CXX_COMPILER": "clang++"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "FreeBSD"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "freebsd-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["freebsd-base", "vcpkg-base"],
|
||||||
|
"cacheVariables": {
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "freebsd-debug",
|
||||||
|
"displayName": "FreeBSD Debug",
|
||||||
|
"inherits": ["freebsd-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "freebsd-release",
|
||||||
|
"displayName": "FreeBSD Release",
|
||||||
|
"inherits": ["freebsd-base", "release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "freebsd-debug-vcpkg",
|
||||||
|
"displayName": "FreeBSD Debug (vcpkg)",
|
||||||
|
"inherits": ["freebsd-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "freebsd-release-vcpkg",
|
||||||
|
"displayName": "FreeBSD Release (vcpkg)",
|
||||||
|
"inherits": ["freebsd-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "android-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_SYSTEM_NAME": "Android",
|
||||||
|
"CMAKE_SYSTEM_VERSION": "24",
|
||||||
|
"CMAKE_ANDROID_NDK": "$env{ANDROID_NDK_HOME}",
|
||||||
|
"CMAKE_ANDROID_STL_TYPE": "c++_static"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["android-base", "vcpkg-base"],
|
||||||
|
"cacheVariables": {
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "android-arm64-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "android-base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_ANDROID_ARCH_ABI": "arm64-v8a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-arm64-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "android-vcpkg-base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_ANDROID_ARCH_ABI": "arm64-v8a",
|
||||||
|
"VCPKG_TARGET_TRIPLET": "arm64-android"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-arm64-debug",
|
||||||
|
"displayName": "Android arm64-v8a Debug",
|
||||||
|
"inherits": ["android-arm64-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-arm64-release",
|
||||||
|
"displayName": "Android arm64-v8a Release",
|
||||||
|
"inherits": ["android-arm64-base", "release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-arm64-debug-vcpkg",
|
||||||
|
"displayName": "Android arm64-v8a Debug (vcpkg)",
|
||||||
|
"inherits": ["android-arm64-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-arm64-release-vcpkg",
|
||||||
|
"displayName": "Android arm64-v8a Release (vcpkg)",
|
||||||
|
"inherits": ["android-arm64-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "android-arm-neon-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "android-base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_ANDROID_ARCH_ABI": "armeabi-v7a",
|
||||||
|
"CMAKE_ANDROID_ARM_NEON": "ON"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-arm-neon-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "android-vcpkg-base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_ANDROID_ARCH_ABI": "armeabi-v7a",
|
||||||
|
"CMAKE_ANDROID_ARM_NEON": "ON",
|
||||||
|
"VCPKG_TARGET_TRIPLET": "arm-neon-android"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-arm-neon-debug",
|
||||||
|
"displayName": "Android armeabi-v7a NEON Debug",
|
||||||
|
"inherits": ["android-arm-neon-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-arm-neon-release",
|
||||||
|
"displayName": "Android armeabi-v7a NEON Release",
|
||||||
|
"inherits": ["android-arm-neon-base", "release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-arm-neon-debug-vcpkg",
|
||||||
|
"displayName": "Android armeabi-v7a NEON Debug (vcpkg)",
|
||||||
|
"inherits": ["android-arm-neon-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-arm-neon-release-vcpkg",
|
||||||
|
"displayName": "Android armeabi-v7a NEON Release (vcpkg)",
|
||||||
|
"inherits": ["android-arm-neon-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "android-x64-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "android-base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_ANDROID_ARCH_ABI": "x86_64"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-x64-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "android-vcpkg-base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_ANDROID_ARCH_ABI": "x86_64",
|
||||||
|
"VCPKG_TARGET_TRIPLET": "x64-android"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-x64-debug",
|
||||||
|
"displayName": "Android x86_64 Debug",
|
||||||
|
"inherits": ["android-x64-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-x64-release",
|
||||||
|
"displayName": "Android x86_64 Release",
|
||||||
|
"inherits": ["android-x64-base", "release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-x64-debug-vcpkg",
|
||||||
|
"displayName": "Android x86_64 Debug (vcpkg)",
|
||||||
|
"inherits": ["android-x64-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-x64-release-vcpkg",
|
||||||
|
"displayName": "Android x86_64 Release (vcpkg)",
|
||||||
|
"inherits": ["android-x64-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "android-x86-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "android-base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_ANDROID_ARCH_ABI": "x86"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-x86-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "android-vcpkg-base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_ANDROID_ARCH_ABI": "x86",
|
||||||
|
"VCPKG_TARGET_TRIPLET": "x86-android"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-x86-debug",
|
||||||
|
"displayName": "Android x86 Debug",
|
||||||
|
"inherits": ["android-x86-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-x86-release",
|
||||||
|
"displayName": "Android x86 Release",
|
||||||
|
"inherits": ["android-x86-base", "release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-x86-debug-vcpkg",
|
||||||
|
"displayName": "Android x86 Debug (vcpkg)",
|
||||||
|
"inherits": ["android-x86-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-x86-release-vcpkg",
|
||||||
|
"displayName": "Android x86 Release (vcpkg)",
|
||||||
|
"inherits": ["android-x86-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "android-debug",
|
||||||
|
"displayName": "Android Debug (default: arm64)",
|
||||||
|
"inherits": "android-arm64-debug"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-release",
|
||||||
|
"displayName": "Android Release (default: arm64)",
|
||||||
|
"inherits": "android-arm64-release"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-debug-vcpkg",
|
||||||
|
"displayName": "Android Debug (default: arm64, vcpkg)",
|
||||||
|
"inherits": "android-arm64-debug-vcpkg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "android-release-vcpkg",
|
||||||
|
"displayName": "Android Release (default: arm64, vcpkg)",
|
||||||
|
"inherits": "android-arm64-release-vcpkg"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "wasm-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "base"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wasm-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["wasm-base", "vcpkg-base"],
|
||||||
|
"cacheVariables": {
|
||||||
|
"VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "$env{EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake",
|
||||||
|
"VCPKG_TARGET_TRIPLET": "wasm32-emscripten",
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wasm-debug-vcpkg",
|
||||||
|
"displayName": "WebAssembly Debug (vcpkg)",
|
||||||
|
"inherits": ["wasm-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wasm-release-vcpkg",
|
||||||
|
"displayName": "WebAssembly Release (vcpkg)",
|
||||||
|
"inherits": ["wasm-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "mingw-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_COMPILER": "gcc",
|
||||||
|
"CMAKE_CXX_COMPILER": "g++"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Windows"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mingw-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["mingw-base", "vcpkg-base"],
|
||||||
|
"environment": {
|
||||||
|
"VCPKG_DEFAULT_HOST_TRIPLET": "x64-mingw-dynamic"
|
||||||
|
},
|
||||||
|
"cacheVariables": {
|
||||||
|
"VCPKG_TARGET_TRIPLET": "x64-mingw-dynamic",
|
||||||
|
"VCPKG_HOST_TRIPLET": "x64-mingw-dynamic",
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mingw-debug",
|
||||||
|
"displayName": "MinGW x64 Debug",
|
||||||
|
"inherits": ["mingw-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mingw-release",
|
||||||
|
"displayName": "MinGW x64 Release",
|
||||||
|
"inherits": ["mingw-base", "release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mingw-debug-vcpkg",
|
||||||
|
"displayName": "MinGW x64 Debug (vcpkg)",
|
||||||
|
"inherits": ["mingw-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mingw-release-vcpkg",
|
||||||
|
"displayName": "MinGW x64 Release (vcpkg)",
|
||||||
|
"inherits": ["mingw-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mingw-ucrt-release-vcpkg",
|
||||||
|
"displayName": "MinGW UCRT64 Release (vcpkg)",
|
||||||
|
"inherits": ["mingw-vcpkg-base", "release"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "mingw32-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": "base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_COMPILER": "gcc",
|
||||||
|
"CMAKE_CXX_COMPILER": "g++"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Windows"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mingw32-vcpkg-base",
|
||||||
|
"hidden": true,
|
||||||
|
"inherits": ["mingw32-base", "vcpkg-base"],
|
||||||
|
"environment": {
|
||||||
|
"VCPKG_DEFAULT_HOST_TRIPLET": "x86-mingw-dynamic"
|
||||||
|
},
|
||||||
|
"cacheVariables": {
|
||||||
|
"VCPKG_TARGET_TRIPLET": "x86-mingw-dynamic",
|
||||||
|
"VCPKG_HOST_TRIPLET": "x86-mingw-dynamic",
|
||||||
|
"VCPKG_MANIFEST_FEATURES": "tests;imgui"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mingw32-debug",
|
||||||
|
"displayName": "MinGW x86 Debug",
|
||||||
|
"inherits": ["mingw32-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mingw32-release",
|
||||||
|
"displayName": "MinGW x86 Release",
|
||||||
|
"inherits": ["mingw32-base", "release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mingw32-debug-vcpkg",
|
||||||
|
"displayName": "MinGW x86 Debug (vcpkg)",
|
||||||
|
"inherits": ["mingw32-vcpkg-base", "debug"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mingw32-release-vcpkg",
|
||||||
|
"displayName": "MinGW x86 Release (vcpkg)",
|
||||||
|
"inherits": ["mingw32-vcpkg-base", "release"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,93 +1,201 @@
|
|||||||
## 🎯 Goal
|
# UNIVERSAL DECLARATION OF CODE OF CONDUCT
|
||||||
|
_Declaration of Community Rights and Responsibilities_
|
||||||
|
|
||||||
My goal is to provide a space where it is safe for everyone to contribute to,
|
## Preamble
|
||||||
and get support for, open-source software in a respectful and cooperative
|
|
||||||
manner.
|
|
||||||
|
|
||||||
I value all contributions and want to make this project and its
|
Whereas the Orange++ community is founded on cooperation, mutual respect and support for the development of open-source software;
|
||||||
surrounding community a place for everyone.
|
|
||||||
|
|
||||||
As members, contributors, and everyone else who may participate in the
|
Whereas it is essential that all participants can contribute and seek assistance in an environment that is safe, inclusive and free from discrimination and harassment;
|
||||||
development, I strive to keep the entire experience civil.
|
|
||||||
|
|
||||||
## 📜 Standards
|
Whereas the dignity and equality of all participants, regardless of their traits or background, must be respected and protected;
|
||||||
|
|
||||||
Our community standards exist in order to make sure everyone feels comfortable
|
Now, therefore, this Community Code of Conduct is proclaimed as a common standard of behaviour for all members, contributors and participants in projects led by Orange++ and its official communities.
|
||||||
contributing to the project(s) together.
|
|
||||||
|
|
||||||
Our standards are:
|
---
|
||||||
- Do not harass, attack, or in any other way discriminate against anyone, including
|
|
||||||
for their protected traits, including, but not limited to, sex, religion, race,
|
|
||||||
appearance, gender, identity, nationality, sexuality, etc.
|
|
||||||
- Do not go off-topic, do not post spam.
|
|
||||||
- Treat everyone with respect.
|
|
||||||
|
|
||||||
Examples of breaking each rule respectively include:
|
## Article 1
|
||||||
- Harassment, bullying or inappropriate jokes about another person.
|
|
||||||
- Posting distasteful imagery, trolling, or posting things unrelated to the topic at hand.
|
|
||||||
- Treating someone as worse because of their lack of understanding of an issue.
|
|
||||||
|
|
||||||
## ⚡ Enforcement
|
This Code of Conduct establishes standards of behaviour intended to:
|
||||||
|
|
||||||
Enforcement of this CoC is done by Orange++ and/or other core contributors.
|
1. Provide a safe and welcoming environment for all participants.
|
||||||
|
2. Encourage respectful and constructive collaboration.
|
||||||
|
3. Prevent harassment, discrimination, and other harmful conduct.
|
||||||
|
|
||||||
I, as the core developer, will strive my best to keep this community civil and
|
All individuals who participate in Orange++ projects or official communities, whether online or offline, are expected to adhere to this Code of Conduct.
|
||||||
following the standards outlined above.
|
|
||||||
|
|
||||||
### 🚩 Reporting incidents
|
---
|
||||||
|
|
||||||
If you believe an incident of breaking these standards has occurred, but nobody has
|
## Article 2
|
||||||
taken appropriate action, you can privately contact the people responsible for dealing
|
|
||||||
with such incidents in multiple ways:
|
All participants are equal in dignity and rights within the community.
|
||||||
|
|
||||||
|
No person shall be harassed, attacked, or discriminated against on the basis of protected or personal traits, including but not limited to:
|
||||||
|
|
||||||
|
- sex;
|
||||||
|
- religion or belief;
|
||||||
|
- race or ethnicity;
|
||||||
|
- appearance;
|
||||||
|
- gender or gender identity;
|
||||||
|
- nationality;
|
||||||
|
- sexual orientation;
|
||||||
|
- or any other similar characteristic.
|
||||||
|
|
||||||
|
Treating someone as lesser or unworthy because of their knowledge, experience, or level of understanding of an issue is incompatible with this Code.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Article 3
|
||||||
|
|
||||||
|
Participants shall treat one another with respect at all times.
|
||||||
|
|
||||||
|
Participants shall:
|
||||||
|
|
||||||
|
1. Engage in discussion in good faith and assume good intent where reasonable.
|
||||||
|
2. Provide feedback and criticism in a constructive and considerate manner.
|
||||||
|
3. Recognize that people have different backgrounds, perspectives, and levels of expertise.
|
||||||
|
|
||||||
|
Examples of conduct contrary to this Article include, but are not limited to:
|
||||||
|
|
||||||
|
- harassment, bullying, personal attacks or degrading comments;
|
||||||
|
- inappropriate or offensive jokes or remarks about another person;
|
||||||
|
- persistent disruption of discussions or activities.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Article 4
|
||||||
|
|
||||||
|
Participants shall remain on topic and avoid posting spam or irrelevant material.
|
||||||
|
|
||||||
|
Content that is distasteful, deliberately inflammatory, or unrelated to the project or discussion at hand is prohibited.
|
||||||
|
|
||||||
|
Examples of prohibited conduct under this Article include:
|
||||||
|
|
||||||
|
- posting trolling or inflammatory messages;
|
||||||
|
- sharing disturbing or inappropriate imagery unrelated to the topic;
|
||||||
|
- repeatedly derailing conversations away from their intended purpose.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Article 5
|
||||||
|
|
||||||
|
The following standards shall guide all participation in Orange++ projects and official communities:
|
||||||
|
|
||||||
|
1. Do not harass, attack, or discriminate against any person.
|
||||||
|
2. Do not go off-topic and do not post spam.
|
||||||
|
3. Treat all participants with respect.
|
||||||
|
|
||||||
|
These standards apply equally to maintainers, contributors, and all other participants, regardless of status or seniority.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Article 6
|
||||||
|
|
||||||
|
Enforcement of this Code of Conduct is carried out by Orange++ and/or other core contributors (hereinafter “members”).
|
||||||
|
|
||||||
|
Members shall strive to:
|
||||||
|
|
||||||
|
1. Act fairly, consistently, and transparently.
|
||||||
|
2. Consider the context and severity of each incident.
|
||||||
|
3. Maintain a civil and welcoming environment for the community as a whole.
|
||||||
|
|
||||||
|
Where appropriate, members may consult individuals with relevant lived experience, particularly when an incident concerns a marginalized group, while preserving confidentiality as required by this Code.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Article 7
|
||||||
|
|
||||||
|
Any participant who believes that a breach of this Code of Conduct has occurred and has not been appropriately addressed may report the incident privately.
|
||||||
|
|
||||||
|
Reports may be submitted through any of the following channels:
|
||||||
|
|
||||||
|
**E-mail**
|
||||||
|
|
||||||
***E-Mail***
|
|
||||||
- `orange-cpp@yandex.ru`
|
- `orange-cpp@yandex.ru`
|
||||||
|
|
||||||
***Discord***
|
**Discord**
|
||||||
|
|
||||||
- `@orange_cpp`
|
- `@orange_cpp`
|
||||||
|
|
||||||
***Telegram***
|
**Telegram**
|
||||||
|
|
||||||
- `@orange_cpp`
|
- `@orange_cpp`
|
||||||
|
|
||||||
I guarantee your privacy and will not share those reports with anyone.
|
The reporting party’s privacy shall be respected, and reports shall not be shared beyond those responsible for handling them, except where required by law or with the explicit consent of the reporting party.
|
||||||
|
|
||||||
## ⚖️ Enforcement Strategy
|
---
|
||||||
|
|
||||||
Depending on the severity of the infraction, any action from the list below may be applied.
|
## Article 8
|
||||||
Please keep in mind cases are reviewed on a per-case basis and members are the ultimate
|
|
||||||
deciding factor in the type of punishment.
|
|
||||||
|
|
||||||
If the matter benefited from an outside opinion, a member might reach for more opinions
|
Depending on the nature and severity of the infraction, and taking into account past behaviour, members may apply one or more of the following measures.
|
||||||
from people unrelated, however, the final decision regarding the action
|
|
||||||
to be taken is still up to the member.
|
|
||||||
|
|
||||||
For example, if the matter at hand regards a representative of a marginalized group or minority,
|
**1. Correction / Edit**
|
||||||
the member might ask for a first-hand opinion from another representative of such group.
|
|
||||||
|
|
||||||
### ✏️ Correction/Edit
|
Where a message is misleading, poorly worded, or likely to cause misunderstanding, members may:
|
||||||
|
|
||||||
If your message is found to be misleading or poorly worded, a member might
|
1. Request that the author clarify or correct the message; or
|
||||||
edit your message.
|
2. Edit the message where the platform permits and such action is appropriate and transparent.
|
||||||
|
|
||||||
### ⚠️ Warning/Deletion
|
**2. Warning / Deletion**
|
||||||
|
|
||||||
If your message is found inappropriate, a member might give you a public or private warning,
|
Where a message is inappropriate or in breach of the standards, members may:
|
||||||
and/or delete your message.
|
|
||||||
|
|
||||||
### 🔇 Mute
|
1. Issue a public or private warning; and/or
|
||||||
|
2. Delete the message.
|
||||||
|
|
||||||
If your message is disruptive, or you have been repeatedly violating the standards,
|
**3. Mute / Temporary Ban**
|
||||||
a member might mute (or temporarily ban) you.
|
|
||||||
|
|
||||||
### ⛔ Ban
|
Where a participant is repeatedly violating the standards, or where their behaviour is significantly disruptive, members may:
|
||||||
|
|
||||||
If your message is hateful, very disruptive, or other, less serious infractions are repeated
|
1. Temporarily mute the participant; or
|
||||||
ignoring previous punishments, a member might ban you permanently.
|
2. Temporarily suspend or ban the participant from the community.
|
||||||
|
|
||||||
## 🔎 Scope
|
**4. Permanent Ban**
|
||||||
|
|
||||||
This CoC shall apply to all projects ran under the Orange++ lead and all _official_ communities
|
Where a message is hateful or severely disruptive, or where less serious infractions are repeated despite prior measures, members may permanently ban the participant.
|
||||||
outside of GitHub.
|
|
||||||
|
|
||||||
However, it is worth noting that official communities outside of GitHub might have their own,
|
Each case shall be considered individually. The final decision regarding the appropriate measure lies with the members responsible for enforcement.
|
||||||
additional sets of rules.
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Article 9
|
||||||
|
|
||||||
|
Reports of misconduct and information regarding enforcement actions shall be handled with care and confidentiality.
|
||||||
|
|
||||||
|
The personal data of reporters, witnesses, and involved parties shall not be disclosed to third parties, except:
|
||||||
|
|
||||||
|
1. Where such disclosure is required by law; or
|
||||||
|
2. Where explicit consent has been given by the person concerned.
|
||||||
|
|
||||||
|
The maintainer guarantees that every report will be treated with discretion and respect.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Article 10
|
||||||
|
|
||||||
|
This Code of Conduct applies to:
|
||||||
|
|
||||||
|
1. All projects led under the Orange++ name or leadership; and
|
||||||
|
2. All official communities associated with Orange++ outside of GitHub.
|
||||||
|
|
||||||
|
Official communities outside of GitHub may maintain additional rules specific to their platform. In case of overlap, participants are expected to follow:
|
||||||
|
|
||||||
|
1. The rules of the platform or community; and
|
||||||
|
2. This Code of Conduct, insofar as it is applicable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Article 11
|
||||||
|
|
||||||
|
This Code of Conduct shall be interpreted in a manner consistent with its purpose: to promote a safe, respectful and inclusive community.
|
||||||
|
|
||||||
|
The maintainer and core contributors may review and revise this Code of Conduct periodically in light of community needs and experience.
|
||||||
|
|
||||||
|
Significant changes should be communicated to the community in a timely and clear manner.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Article 12
|
||||||
|
|
||||||
|
Nothing in this Community Code of Conduct may be interpreted as granting to any maintainer, member, contributor, or participant any right to engage in any activity or to perform any act that aims at undermining, limiting, or destroying the rights, protections, and standards set forth herein.
|
||||||
|
|
||||||
|
No rule, policy, custom, or decision within the Orange++ projects or their official communities may be invoked to justify harassment, discrimination, retaliation, or any other conduct contrary to this Code of Conduct.
|
||||||
|
|||||||
32
CONTRIBUTING.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
## 🤝 Contributing to OMath or other Orange's Projects
|
||||||
|
|
||||||
|
### ❕ Prerequisites
|
||||||
|
|
||||||
|
- A working up-to-date OMath installation
|
||||||
|
- C++ knowledge
|
||||||
|
- Git knowledge
|
||||||
|
- Ability to ask for help (Feel free to create empty pull-request or PM a maintainer
|
||||||
|
in [Telegram](https://t.me/orange_cpp))
|
||||||
|
|
||||||
|
### ⏬ Setting up OMath
|
||||||
|
|
||||||
|
Please read INSTALL.md file in repository
|
||||||
|
|
||||||
|
### 🔀 Pull requests and Branches
|
||||||
|
|
||||||
|
In order to send code back to the official OMath repository, you must first create a copy of OMath on your github
|
||||||
|
account ([fork](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)) and
|
||||||
|
then [create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/) back to OMath.
|
||||||
|
|
||||||
|
OMath development is performed on multiple branches. Changes are then pull requested into master. By default, changes
|
||||||
|
merged into master will not roll out to stable build users unless the `stable` tag is updated.
|
||||||
|
|
||||||
|
### 📜 Code-Style
|
||||||
|
|
||||||
|
The orange code-style can be found in `.clang-format`.
|
||||||
|
|
||||||
|
### 📦 Building
|
||||||
|
|
||||||
|
OMath has already created the `cmake-build` and `out` directories where cmake/bin files are located. By default, you
|
||||||
|
can build OMath by running `cmake --build cmake-build/build/windows-release --target omath -j 6` in the source
|
||||||
|
directory.
|
||||||
@@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
Thanks to everyone who made this possible, including:
|
Thanks to everyone who made this possible, including:
|
||||||
|
|
||||||
- Saikari aka luadebug for VCPKG port.
|
- Saikari aka luadebug for VCPKG port and awesome new initial logo design.
|
||||||
|
- AmbushedRaccoon for telegram post about omath to boost repository activity.
|
||||||
|
- Billy O'Neal aka BillyONeal for fixing compilation issues due to C math library compatibility.
|
||||||
|
|
||||||
And a big hand to everyone else who has contributed over the past!
|
And a big hand to everyone else who has contributed over the past!
|
||||||
|
|
||||||
THANKS! <3
|
THANKS! <3
|
||||||
|
|
||||||
-- Orange++ <orange-cpp@yandex.ru>
|
-- Orange++ <orange_github@proton.me>
|
||||||
|
|||||||
16
INSTALL.md
@@ -14,6 +14,20 @@ target_link_libraries(main PRIVATE omath::omath)
|
|||||||
```
|
```
|
||||||
For detailed commands on installing different versions and more information, please refer to Microsoft's [official instructions](https://learn.microsoft.com/en-us/vcpkg/get_started/overview).
|
For detailed commands on installing different versions and more information, please refer to Microsoft's [official instructions](https://learn.microsoft.com/en-us/vcpkg/get_started/overview).
|
||||||
|
|
||||||
|
## <img width="28px" src="https://xmake.io/assets/img/logo.svg" /> Using xrepo
|
||||||
|
**Note**: Support xrepo for package management
|
||||||
|
1. Install [xmake](https://xmake.io/)
|
||||||
|
2. Run the following command to install the omath package:
|
||||||
|
```
|
||||||
|
xrepo install omath
|
||||||
|
```
|
||||||
|
xmake.lua
|
||||||
|
```xmake
|
||||||
|
add_requires("omath")
|
||||||
|
target("...")
|
||||||
|
add_packages("omath")
|
||||||
|
```
|
||||||
|
|
||||||
## <img width="28px" src="https://upload.wikimedia.org/wikipedia/commons/e/ef/CMake_logo.svg?" /> Build from source using CMake
|
## <img width="28px" src="https://upload.wikimedia.org/wikipedia/commons/e/ef/CMake_logo.svg?" /> Build from source using CMake
|
||||||
1. **Preparation**
|
1. **Preparation**
|
||||||
|
|
||||||
@@ -45,7 +59,7 @@ For detailed commands on installing different versions and more information, ple
|
|||||||
cmake --preset windows-release -S .
|
cmake --preset windows-release -S .
|
||||||
cmake --build cmake-build/build/windows-release --target omath -j 6
|
cmake --build cmake-build/build/windows-release --target omath -j 6
|
||||||
```
|
```
|
||||||
Use **\<platform\>-\<build configuration\>** preset to build siutable version for yourself. Like **windows-release** or **linux-release**.
|
Use **\<platform\>-\<build configuration\>** preset to build suitable version for yourself. Like **windows-release** or **linux-release**.
|
||||||
|
|
||||||
| Platform Name | Build Config |
|
| Platform Name | Build Config |
|
||||||
|---------------|---------------|
|
|---------------|---------------|
|
||||||
|
|||||||
6
LICENSE
@@ -1,7 +1,7 @@
|
|||||||
Copyright (C) 2024-2025 Orange++ <orange-cpp@yandex.ru>
|
Copyright (C) 2023-2026 Orange++ orange_github@proton.me
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
arising from the use of this software.
|
arising from the use of this software.
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
@@ -14,4 +14,4 @@ freely, subject to the following restrictions:
|
|||||||
appreciated but is not required.
|
appreciated but is not required.
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
misrepresented as being the original software.
|
misrepresented as being the original software.
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|||||||
164
README.md
@@ -1,18 +1,77 @@
|
|||||||
<div align = center>
|
<div align = center>
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|

|
||||||
[](https://www.codefactor.io/repository/github/orange-cpp/omath)
|
[](https://www.codefactor.io/repository/github/orange-cpp/omath)
|
||||||

|

|
||||||
|
[](https://repology.org/project/orange-math/versions)
|
||||||

|

|
||||||
|
[](https://discord.gg/eDgdaWbqwZ)
|
||||||
|
[](https://t.me/orangennotes)
|
||||||
|
|
||||||
|
OMath is a 100% independent, constexpr template blazingly fast math library that doesn't have legacy C++ code.
|
||||||
|
|
||||||
|
It provides the latest features, is highly customizable, has all for cheat development, DirectX/OpenGL/Vulkan support, premade support for different game engines, much more constexpr stuff than in other libraries and more...
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**[<kbd> <br> Install <br> </kbd>][INSTALL]**
|
||||||
|
**[<kbd> <br> Examples <br> </kbd>][EXAMPLES]**
|
||||||
|
**[<kbd> <br> Documentation <br> </kbd>][DOCUMENTATION]**
|
||||||
|
**[<kbd> <br> Contribute <br> </kbd>][CONTRIBUTING]**
|
||||||
|
**[<kbd> <br> Donate <br> </kbd>][SPONSOR]**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Oranges's Math Library (omath) is a comprehensive, open-source library aimed at providing efficient, reliable, and versatile mathematical functions and algorithms. Developed primarily in C++, this library is designed to cater to a wide range of mathematical operations essential in scientific computing, engineering, and academic research.
|
|
||||||
|
|
||||||
## 👁🗨 Features
|
<div align = center>
|
||||||
|
<a href="https://www.star-history.com/#orange-cpp/omath&Date">
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=orange-cpp/omath&type=Date&theme=dark" />
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=orange-cpp/omath&type=Date" />
|
||||||
|
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=orange-cpp/omath&type=Date" />
|
||||||
|
</picture>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Quick Example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <omath/omath.hpp>
|
||||||
|
|
||||||
|
using namespace omath;
|
||||||
|
|
||||||
|
// 3D vector operations
|
||||||
|
Vector3<float> a{1, 2, 3};
|
||||||
|
Vector3<float> b{4, 5, 6};
|
||||||
|
|
||||||
|
auto dot = a.dot(b); // 32.0
|
||||||
|
auto cross = a.cross(b); // (-3, 6, -3)
|
||||||
|
auto distance = a.distance_to(b); // ~5.196
|
||||||
|
auto normalized = a.normalized(); // Unit vector
|
||||||
|
|
||||||
|
// World-to-screen projection (Source Engine example)
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
Camera camera(position, angles, viewport, fov, near_plane, far_plane);
|
||||||
|
|
||||||
|
if (auto screen = camera.world_to_screen(world_position)) {
|
||||||
|
// Draw at screen->x, screen->y
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**[See more examples and tutorials][TUTORIALS]**
|
||||||
|
|
||||||
|
# Features
|
||||||
- **Efficiency**: Optimized for performance, ensuring quick computations using AVX2.
|
- **Efficiency**: Optimized for performance, ensuring quick computations using AVX2.
|
||||||
- **Versatility**: Includes a wide array of mathematical functions and algorithms.
|
- **Versatility**: Includes a wide array of mathematical functions and algorithms.
|
||||||
- **Ease of Use**: Simplified interface for convenient integration into various projects.
|
- **Ease of Use**: Simplified interface for convenient integration into various projects.
|
||||||
@@ -21,57 +80,72 @@ Oranges's Math Library (omath) is a comprehensive, open-source library aimed at
|
|||||||
- **Collision Detection**: Production ready code to handle collision detection by using simple interfaces.
|
- **Collision Detection**: Production ready code to handle collision detection by using simple interfaces.
|
||||||
- **No Additional Dependencies**: No additional dependencies need to use OMath except unit test execution
|
- **No Additional Dependencies**: No additional dependencies need to use OMath except unit test execution
|
||||||
- **Ready for meta-programming**: Omath use templates for common types like Vectors, Matrixes etc, to handle all types!
|
- **Ready for meta-programming**: Omath use templates for common types like Vectors, Matrixes etc, to handle all types!
|
||||||
|
- **Engine support**: Supports coordinate systems of **Source, Unity, Unreal, Frostbite, IWEngine and canonical OpenGL**.
|
||||||
|
- **Cross platform**: Supports Windows, MacOS and Linux.
|
||||||
|
- **Algorithms**: Has ability to scan for byte pattern with wildcards in PE files/modules, binary slices, works even with Wine apps.
|
||||||
|
<div align = center>
|
||||||
|
|
||||||
|
# Gallery
|
||||||
|
|
||||||
## Supported Render Pipelines
|
<br>
|
||||||
| ENGINE | SUPPORT |
|
|
||||||
|----------|---------|
|
|
||||||
| Source | ✅YES |
|
|
||||||
| Unity | ✅YES |
|
|
||||||
| IWEngine | ✅YES |
|
|
||||||
| Unreal | ❌NO |
|
|
||||||
|
|
||||||
## Supported Operating Systems
|
[](https://youtu.be/lM_NJ1yCunw?si=-Qf5yzDcWbaxAXGQ)
|
||||||
|
|
||||||
| OS | SUPPORT |
|
<br>
|
||||||
|----------------|---------|
|
|
||||||
| Windows 10/11 | ✅YES |
|
|
||||||
| Linux | ✅YES |
|
|
||||||
| Darwin (MacOS) | ✅YES |
|
|
||||||
|
|
||||||
## ⏬ Installation
|
![APEX Preview]
|
||||||
Please read our [installation guide](https://github.com/orange-cpp/omath/blob/main/INSTALL.md). If this link doesn't work check out INSTALL.md file.
|
|
||||||
|
|
||||||
## ❔ Usage
|
<br>
|
||||||
Simple world to screen function
|
|
||||||
```c++
|
|
||||||
TEST(UnitTestProjection, IsPointOnScreen)
|
|
||||||
{
|
|
||||||
const omath::projection::Camera camera({0.f, 0.f, 0.f}, {0, 0.f, 0.f} , {1920.f, 1080.f}, 110.f, 0.1f, 500.f);
|
|
||||||
|
|
||||||
const auto proj = camera.WorldToScreen({100, 0, 15});
|
![BO2 Preview]
|
||||||
EXPECT_TRUE(proj.has_value());
|
|
||||||
}
|
|
||||||
```
|
|
||||||
## Showcase
|
|
||||||
<details>
|
|
||||||
<summary>OMATH for making cheats (click to open)</summary>
|
|
||||||
|
|
||||||
With `omath/projection` module you can achieve simple ESP hack for powered by Source/Unreal/Unity engine games, like [Apex Legends](https://store.steampowered.com/app/1172470/Apex_Legends/).
|
<br>
|
||||||
|
|
||||||

|
![CS2 Preview]
|
||||||
Or for InfinityWard Engine based games. Like Call of Duty Black Ops 2!
|
|
||||||

|
|
||||||
Or create simple trigger bot with embeded traceline from omath::collision::LineTrace
|
|
||||||

|
|
||||||
Or even advanced projectile aimbot
|
|
||||||
[Watch Video](https://youtu.be/lM_NJ1yCunw?si=5E87OrQMeypxSJ3E)
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## 🫵🏻 Contributing
|
<br>
|
||||||
Contributions to `omath` are welcome! Please read `CONTRIBUTING.md` for details on our code of conduct and the process for submitting pull requests.
|
|
||||||
|
|
||||||
## 📜 License
|
![TF2 Preview]
|
||||||
This project is licensed under the MIT - see the `LICENSE` file for details.
|
|
||||||
|
|
||||||
## 💘 Acknowledgments
|
<br>
|
||||||
|
|
||||||
|
![OpenGL Preview]
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- **[Getting Started Guide](http://libomath.org/getting_started/)** - Installation and first steps
|
||||||
|
- **[API Overview](http://libomath.org/api_overview/)** - Complete API reference
|
||||||
|
- **[Tutorials](http://libomath.org/tutorials/)** - Step-by-step guides
|
||||||
|
- **[FAQ](http://libomath.org/faq/)** - Common questions and answers
|
||||||
|
- **[Troubleshooting](http://libomath.org/troubleshooting/)** - Solutions to common issues
|
||||||
|
- **[Best Practices](http://libomath.org/best_practices/)** - Guidelines for effective usage
|
||||||
|
|
||||||
|
## Community & Support
|
||||||
|
|
||||||
|
- **Discord**: [Join our community](https://discord.gg/eDgdaWbqwZ)
|
||||||
|
- **Telegram**: [@orangennotes](https://t.me/orangennotes)
|
||||||
|
- **Issues**: [Report bugs or request features](https://github.com/orange-cpp/omath/issues)
|
||||||
|
- **Contributing**: See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines
|
||||||
|
|
||||||
|
# Acknowledgments
|
||||||
- [All contributors](https://github.com/orange-cpp/omath/graphs/contributors)
|
- [All contributors](https://github.com/orange-cpp/omath/graphs/contributors)
|
||||||
|
|
||||||
|
<!----------------------------------{ Images }--------------------------------->
|
||||||
|
[APEX Preview]: docs/images/showcase/apex.png
|
||||||
|
[BO2 Preview]: docs/images/showcase/cod_bo2.png
|
||||||
|
[CS2 Preview]: docs/images/showcase/cs2.jpeg
|
||||||
|
[TF2 Preview]: docs/images/showcase/tf2.jpg
|
||||||
|
[OpenGL Preview]: docs/images/showcase/opengl.png
|
||||||
|
<!----------------------------------{ Buttons }--------------------------------->
|
||||||
|
[QUICKSTART]: docs/getting_started.md
|
||||||
|
[INSTALL]: INSTALL.md
|
||||||
|
[DOCUMENTATION]: http://libomath.org
|
||||||
|
[TUTORIALS]: docs/tutorials.md
|
||||||
|
[CONTRIBUTING]: CONTRIBUTING.md
|
||||||
|
[EXAMPLES]: examples
|
||||||
|
[SPONSOR]: https://boosty.to/orangecpp/purchase/3568644?ssource=DIRECT&share=subscription_link
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
Please report security issues to `orange-cpp@yandex.ru`
|
Please report security issues to `orange_github@proton.me`
|
||||||
|
|||||||
24
benchmark/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
project(omath_benchmark)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE OMATH_BENCHMARK_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
|
||||||
|
add_executable(${PROJECT_NAME} ${OMATH_BENCHMARK_SOURCES})
|
||||||
|
|
||||||
|
set_target_properties(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
||||||
|
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
||||||
|
CXX_STANDARD 23
|
||||||
|
CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
if(TARGET benchmark::benchmark) # Benchmark is being linked as submodule
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE benchmark::benchmark omath)
|
||||||
|
else()
|
||||||
|
find_package(benchmark CONFIG REQUIRED) # Benchmark is being linked as vcpkg
|
||||||
|
# package
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE benchmark::benchmark omath)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OMATH_ENABLE_VALGRIND)
|
||||||
|
omath_setup_valgrind(${PROJECT_NAME})
|
||||||
|
endif()
|
||||||
65
benchmark/benchmark_mat.cpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 9/17/2025.
|
||||||
|
//
|
||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
|
||||||
|
#include <omath/omath.hpp>
|
||||||
|
using namespace omath;
|
||||||
|
|
||||||
|
|
||||||
|
void mat_float_multiplication_col_major(benchmark::State& state)
|
||||||
|
{
|
||||||
|
using MatType = Mat<128, 128, float, MatStoreType::COLUMN_MAJOR>;
|
||||||
|
MatType a;
|
||||||
|
MatType b;
|
||||||
|
a.set(3.f);
|
||||||
|
b.set(7.f);
|
||||||
|
|
||||||
|
|
||||||
|
for ([[maybe_unused]] const auto _ : state)
|
||||||
|
std::ignore = a * b;
|
||||||
|
}
|
||||||
|
void mat_float_multiplication_row_major(benchmark::State& state)
|
||||||
|
{
|
||||||
|
using MatType = Mat<128, 128, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
MatType a;
|
||||||
|
MatType b;
|
||||||
|
a.set(3.f);
|
||||||
|
b.set(7.f);
|
||||||
|
|
||||||
|
|
||||||
|
for ([[maybe_unused]] const auto _ : state)
|
||||||
|
std::ignore = a * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mat_double_multiplication_row_major(benchmark::State& state)
|
||||||
|
{
|
||||||
|
using MatType = Mat<128, 128, double, MatStoreType::ROW_MAJOR>;
|
||||||
|
MatType a;
|
||||||
|
MatType b;
|
||||||
|
a.set(3.f);
|
||||||
|
b.set(7.f);
|
||||||
|
|
||||||
|
|
||||||
|
for ([[maybe_unused]] const auto _ : state)
|
||||||
|
std::ignore = a * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mat_double_multiplication_col_major(benchmark::State& state)
|
||||||
|
{
|
||||||
|
using MatType = Mat<128, 128, double, MatStoreType::COLUMN_MAJOR>;
|
||||||
|
MatType a;
|
||||||
|
MatType b;
|
||||||
|
a.set(3.f);
|
||||||
|
b.set(7.f);
|
||||||
|
|
||||||
|
|
||||||
|
for ([[maybe_unused]] const auto _ : state)
|
||||||
|
std::ignore = a * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(mat_float_multiplication_col_major)->Iterations(5000);
|
||||||
|
BENCHMARK(mat_float_multiplication_row_major)->Iterations(5000);
|
||||||
|
|
||||||
|
BENCHMARK(mat_double_multiplication_col_major)->Iterations(5000);
|
||||||
|
BENCHMARK(mat_double_multiplication_row_major)->Iterations(5000);
|
||||||
23
benchmark/benchmark_projectile_pred.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 9/18/2025.
|
||||||
|
//
|
||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
#include <omath/omath.hpp>
|
||||||
|
using namespace omath;
|
||||||
|
|
||||||
|
using namespace omath::projectile_prediction;
|
||||||
|
|
||||||
|
constexpr float simulation_time_step = 1.f / 1000.f;
|
||||||
|
constexpr float hit_distance_tolerance = 5.f;
|
||||||
|
|
||||||
|
void source_engine_projectile_prediction(benchmark::State& state)
|
||||||
|
{
|
||||||
|
constexpr Target target{.m_origin = {100, 0, 90}, .m_velocity = {0, 0, 0}, .m_is_airborne = false};
|
||||||
|
constexpr Projectile projectile = {.m_origin = {3, 2, 1}, .m_launch_speed = 5000, .m_gravity_scale = 0.4};
|
||||||
|
|
||||||
|
for ([[maybe_unused]] const auto _: state)
|
||||||
|
std::ignore = ProjPredEngineLegacy(400, simulation_time_step, 50, hit_distance_tolerance)
|
||||||
|
.maybe_calculate_aim_point(projectile, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(source_engine_projectile_prediction)->Iterations(10'000);
|
||||||
5
benchmark/main.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 9/17/2025.
|
||||||
|
//
|
||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
BENCHMARK_MAIN();
|
||||||
67
cmake/Coverage.cmake
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# cmake/Coverage.cmake
|
||||||
|
include_guard(GLOBAL)
|
||||||
|
|
||||||
|
function(omath_setup_coverage TARGET_NAME)
|
||||||
|
if(ANDROID OR IOS OR EMSCRIPTEN)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND MSVC)
|
||||||
|
target_compile_options(${TARGET_NAME} PRIVATE -fprofile-instr-generate -fcoverage-mapping
|
||||||
|
/Zi)
|
||||||
|
target_link_options(
|
||||||
|
${TARGET_NAME}
|
||||||
|
PRIVATE
|
||||||
|
-fprofile-instr-generate
|
||||||
|
-fcoverage-mapping
|
||||||
|
/DEBUG:FULL
|
||||||
|
/INCREMENTAL:NO
|
||||||
|
/PROFILE)
|
||||||
|
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang")
|
||||||
|
target_compile_options(${TARGET_NAME} PRIVATE -fprofile-instr-generate -fcoverage-mapping
|
||||||
|
-g -O0)
|
||||||
|
target_link_options(${TARGET_NAME} PRIVATE -fprofile-instr-generate -fcoverage-mapping)
|
||||||
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
target_compile_options(${TARGET_NAME} PRIVATE --coverage -g -O0)
|
||||||
|
target_link_options(${TARGET_NAME} PRIVATE --coverage)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(TARGET coverage)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND MSVC)
|
||||||
|
message(STATUS "MSVC detected: Use VS Code Coverage from CI workflow")
|
||||||
|
add_custom_target(
|
||||||
|
coverage
|
||||||
|
DEPENDS unit_tests
|
||||||
|
COMMAND $<TARGET_FILE:unit_tests>
|
||||||
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||||
|
COMMENT "Running tests for coverage (use VS Code Coverage from CI)")
|
||||||
|
|
||||||
|
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang")
|
||||||
|
add_custom_target(
|
||||||
|
coverage
|
||||||
|
DEPENDS unit_tests
|
||||||
|
COMMAND bash "${CMAKE_SOURCE_DIR}/scripts/coverage-llvm.sh" "${CMAKE_SOURCE_DIR}"
|
||||||
|
"${CMAKE_BINARY_DIR}" "$<TARGET_FILE:unit_tests>" "${CMAKE_BINARY_DIR}/coverage"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||||
|
COMMENT "Running LLVM coverage")
|
||||||
|
|
||||||
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
add_custom_target(
|
||||||
|
coverage
|
||||||
|
DEPENDS unit_tests
|
||||||
|
COMMAND $<TARGET_FILE:unit_tests> || true
|
||||||
|
COMMAND lcov --capture --directory "${CMAKE_BINARY_DIR}" --output-file
|
||||||
|
"${CMAKE_BINARY_DIR}/coverage.info" --ignore-errors mismatch,gcov
|
||||||
|
COMMAND
|
||||||
|
lcov --remove "${CMAKE_BINARY_DIR}/coverage.info" "*/tests/*" "*/gtest/*"
|
||||||
|
"*/googletest/*" "*/_deps/*" "/usr/*" --output-file
|
||||||
|
"${CMAKE_BINARY_DIR}/coverage.info" --ignore-errors unused
|
||||||
|
COMMAND genhtml "${CMAKE_BINARY_DIR}/coverage.info" --output-directory
|
||||||
|
"${CMAKE_BINARY_DIR}/coverage"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||||
|
COMMENT "Running lcov/genhtml")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
41
cmake/Valgrind.cmake
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# cmake/Valgrind.cmake
|
||||||
|
|
||||||
|
if(DEFINED __OMATH_VALGRIND_INCLUDED)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(__OMATH_VALGRIND_INCLUDED TRUE)
|
||||||
|
|
||||||
|
find_program(VALGRIND_EXECUTABLE valgrind)
|
||||||
|
option(OMATH_ENABLE_VALGRIND "Enable Valgrind target for memory checking" ON)
|
||||||
|
|
||||||
|
if(OMATH_ENABLE_VALGRIND AND NOT TARGET valgrind_all)
|
||||||
|
add_custom_target(valgrind_all)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
function(omath_setup_valgrind TARGET_NAME)
|
||||||
|
if(NOT OMATH_ENABLE_VALGRIND)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT VALGRIND_EXECUTABLE)
|
||||||
|
message(WARNING "OMATH_ENABLE_VALGRIND is ON, but 'valgrind' executable was not found.")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(VALGRIND_FLAGS --leak-check=full --show-leak-kinds=all --track-origins=yes
|
||||||
|
--error-exitcode=99)
|
||||||
|
|
||||||
|
set(VALGRIND_TARGET "valgrind_${TARGET_NAME}")
|
||||||
|
|
||||||
|
if(NOT TARGET ${VALGRIND_TARGET})
|
||||||
|
add_custom_target(
|
||||||
|
${VALGRIND_TARGET}
|
||||||
|
DEPENDS ${TARGET_NAME}
|
||||||
|
COMMAND ${VALGRIND_EXECUTABLE} ${VALGRIND_FLAGS} $<TARGET_FILE:${TARGET_NAME}>
|
||||||
|
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TARGET_NAME}>
|
||||||
|
COMMENT "Running Valgrind memory check on ${TARGET_NAME}..."
|
||||||
|
USES_TERMINAL)
|
||||||
|
|
||||||
|
add_dependencies(valgrind_all ${VALGRIND_TARGET})
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
include(CMakeFindDependencyMacro)
|
include(CMakeFindDependencyMacro)
|
||||||
|
|
||||||
|
if (@OMATH_IMGUI_INTEGRATION@)
|
||||||
|
find_dependency(imgui CONFIG)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Load the targets for the omath library
|
# Load the targets for the omath library
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/omathTargets.cmake")
|
include("${CMAKE_CURRENT_LIST_DIR}/omathTargets.cmake")
|
||||||
check_required_components(omath)
|
check_required_components(omath)
|
||||||
|
|||||||
118
docs/3d_primitives/box.md
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# `omath::primitives::create_box` — Build an oriented box as 12 triangles
|
||||||
|
|
||||||
|
> Header: your project’s `primitives/box.hpp` (declares `create_box`)
|
||||||
|
> Namespace: `omath::primitives`
|
||||||
|
> Depends on: `omath::Triangle<omath::Vector3<float>>`, `omath::Vector3<float>`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]]
|
||||||
|
std::array<Triangle<Vector3<float>>, 12>
|
||||||
|
create_box(const Vector3<float>& top,
|
||||||
|
const Vector3<float>& bottom,
|
||||||
|
const Vector3<float>& dir_forward,
|
||||||
|
const Vector3<float>& dir_right,
|
||||||
|
float ratio = 4.f) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
Constructs a **rectangular cuboid (“box”)** oriented in 3D space and returns its surface as **12 triangles** (2 per face × 6 faces). The box’s central axis runs from `bottom` → `top`. The **up** direction is inferred from that segment; the **forward** and **right** directions define the box’s orientation around that axis.
|
||||||
|
|
||||||
|
The lateral half-extents are derived from the axis length and `ratio`:
|
||||||
|
|
||||||
|
> Let `H = |top - bottom|`. Lateral half-size ≈ `H / ratio` along both `dir_forward` and `dir_right`
|
||||||
|
> (i.e., the cross-section is a square of side `2H/ratio`).
|
||||||
|
|
||||||
|
> **Note:** This describes the intended behavior from the interface. If you rely on a different sizing rule, document it next to your implementation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
* `top`
|
||||||
|
Center of the **top face**.
|
||||||
|
|
||||||
|
* `bottom`
|
||||||
|
Center of the **bottom face**.
|
||||||
|
|
||||||
|
* `dir_forward`
|
||||||
|
A direction that orients the box around its up axis. Should be **non-zero** and **not collinear** with `top - bottom`.
|
||||||
|
|
||||||
|
* `dir_right`
|
||||||
|
A direction roughly orthogonal to both `dir_forward` and `top - bottom`. Used to fully fix orientation.
|
||||||
|
|
||||||
|
* `ratio` (default `4.0f`)
|
||||||
|
Controls thickness relative to height. Larger values → thinner box.
|
||||||
|
With the default rule above, half-extent = `|top-bottom|/ratio`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Return value
|
||||||
|
|
||||||
|
`std::array<Triangle<Vector3<float>>, 12>` — the six faces of the box, triangulated.
|
||||||
|
Winding is intended to be **outward-facing** (right-handed coordinates). Do not rely on a specific **face ordering**; treat the array as opaque unless your implementation guarantees an order.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Expected math & robustness
|
||||||
|
|
||||||
|
* Define `u = normalize(top - bottom)`.
|
||||||
|
* Re-orthonormalize the basis to avoid skew:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
f = normalize(dir_forward - u * u.dot(dir_forward)); // drop any up component
|
||||||
|
r = normalize(u.cross(f)); // right-handed basis
|
||||||
|
// (Optionally recompute f = r.cross(u) for orthogonality)
|
||||||
|
```
|
||||||
|
* Half-extents: `h = length(top - bottom) / ratio; hf = h * f; hr = h * r`.
|
||||||
|
* Corners (top): `t±r±f = top ± hr ± hf`; (bottom): `b±r±f = bottom ± hr ± hf`.
|
||||||
|
* Triangulate each face with consistent CCW winding when viewed from outside.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using omath::Vector3;
|
||||||
|
using omath::Triangle;
|
||||||
|
using omath::primitives::create_box;
|
||||||
|
|
||||||
|
// Axis from bottom to top (height 2)
|
||||||
|
Vector3<float> bottom{0, 0, 0};
|
||||||
|
Vector3<float> top {0, 2, 0};
|
||||||
|
|
||||||
|
// Orientation around the axis
|
||||||
|
Vector3<float> forward{0, 0, 1};
|
||||||
|
Vector3<float> right {1, 0, 0};
|
||||||
|
|
||||||
|
// Ratio 4 → lateral half-size = height/4 = 0.5
|
||||||
|
auto tris = create_box(top, bottom, forward, right, 4.0f);
|
||||||
|
|
||||||
|
// Use the triangles (normals, rendering, collision, etc.)
|
||||||
|
for (const auto& tri : tris) {
|
||||||
|
auto n = tri.calculate_normal();
|
||||||
|
(void)n;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage notes & pitfalls
|
||||||
|
|
||||||
|
* **Degenerate axis**: If `top == bottom`, the box is undefined (zero height). Guard against this.
|
||||||
|
* **Directions**: Provide **non-zero**, **reasonably orthogonal** `dir_forward`/`dir_right`. A robust implementation should project/normalize internally, but callers should still pass sensible inputs.
|
||||||
|
* **Winding**: If your renderer or collision expects a specific winding, verify with a unit test and flip vertex order per face if necessary.
|
||||||
|
* **Thickness policy**: This doc assumes both lateral half-extents equal `|top-bottom|/ratio`. If your implementation diverges (e.g., separate forward/right ratios), document it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath::Triangle` (vertex utilities: normals, centroid, etc.)
|
||||||
|
* `omath::Vector3` (geometry operations used by the construction)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 31 Oct 2025*
|
||||||
465
docs/3d_primitives/mesh.md
Normal file
@@ -0,0 +1,465 @@
|
|||||||
|
# `omath::primitives::Mesh` — 3D mesh with transformation support
|
||||||
|
|
||||||
|
> Header: `omath/3d_primitives/mesh.hpp`
|
||||||
|
> Namespace: `omath::primitives`
|
||||||
|
> Depends on: `omath::Vector3<T>`, `omath::Mat4X4`, `omath::Triangle<Vector3<T>>`
|
||||||
|
> Purpose: represent and transform 3D meshes in different engine coordinate systems
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
`Mesh` represents a 3D polygonal mesh with vertex data and transformation capabilities. It stores:
|
||||||
|
* **Vertex buffer (VBO)** — array of 3D vertex positions
|
||||||
|
* **Index buffer (VAO)** — array of triangular faces (indices into VBO)
|
||||||
|
* **Transformation** — position, rotation, and scale with caching
|
||||||
|
|
||||||
|
The mesh supports transformation from local space to world space using engine-specific coordinate systems through the `MeshTrait` template parameter.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template Declaration
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class Mat4X4, class RotationAngles, class MeshTypeTrait, class Type = float>
|
||||||
|
class Mesh final;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Template Parameters
|
||||||
|
|
||||||
|
* `Mat4X4` — Matrix type for transformations (typically `omath::Mat4X4`)
|
||||||
|
* `RotationAngles` — Rotation representation (e.g., `ViewAngles` with pitch/yaw/roll)
|
||||||
|
* `MeshTypeTrait` — Engine-specific transformation trait (see [Engine Traits](#engine-traits))
|
||||||
|
* `Type` — Scalar type for vertex coordinates (default `float`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type Aliases
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using NumericType = Type;
|
||||||
|
```
|
||||||
|
|
||||||
|
Common engine-specific aliases:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Source Engine
|
||||||
|
using Mesh = omath::primitives::Mesh<Mat4X4, ViewAngles, MeshTrait, float>;
|
||||||
|
|
||||||
|
// Unity Engine
|
||||||
|
using Mesh = omath::primitives::Mesh<Mat4X4, ViewAngles, MeshTrait, float>;
|
||||||
|
|
||||||
|
// Unreal Engine
|
||||||
|
using Mesh = omath::primitives::Mesh<Mat4X4, ViewAngles, MeshTrait, float>;
|
||||||
|
|
||||||
|
// Frostbite, IW Engine, OpenGL similar...
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the pre-defined type aliases in engine namespaces:
|
||||||
|
```cpp
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
Mesh my_mesh = /* ... */; // Uses SourceEngine::Mesh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data Members
|
||||||
|
|
||||||
|
### Vertex Data
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::vector<Vector3<NumericType>> m_vertex_buffer; // VBO: vertex positions
|
||||||
|
std::vector<Vector3<std::size_t>> m_vertex_array_object; // VAO: face indices
|
||||||
|
```
|
||||||
|
|
||||||
|
* `m_vertex_buffer` — array of vertex positions in **local space**
|
||||||
|
* `m_vertex_array_object` — array of triangular faces, each containing 3 indices into `m_vertex_buffer`
|
||||||
|
|
||||||
|
**Public access**: These members are public for direct manipulation when needed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constructor
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Mesh(std::vector<Vector3<NumericType>> vbo,
|
||||||
|
std::vector<Vector3<std::size_t>> vao,
|
||||||
|
Vector3<NumericType> scale = {1, 1, 1});
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a mesh from vertex and index data.
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
* `vbo` — vertex buffer (moved into mesh)
|
||||||
|
* `vao` — index buffer / vertex array object (moved into mesh)
|
||||||
|
* `scale` — initial scale (default `{1, 1, 1}`)
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
```cpp
|
||||||
|
std::vector<Vector3<float>> vertices = {
|
||||||
|
{0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Vector3<std::size_t>> faces = {
|
||||||
|
{0, 1, 2}, // Triangle 1
|
||||||
|
{0, 1, 3}, // Triangle 2
|
||||||
|
{0, 2, 3}, // Triangle 3
|
||||||
|
{1, 2, 3} // Triangle 4
|
||||||
|
};
|
||||||
|
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
Mesh tetrahedron(std::move(vertices), std::move(faces));
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Transformation Methods
|
||||||
|
|
||||||
|
### Setting Transform Components
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void set_origin(const Vector3<NumericType>& new_origin);
|
||||||
|
void set_scale(const Vector3<NumericType>& new_scale);
|
||||||
|
void set_rotation(const RotationAngles& new_rotation_angles);
|
||||||
|
```
|
||||||
|
|
||||||
|
Update the mesh's transformation. **Side effect**: invalidates the cached transformation matrix, which will be recomputed on the next `get_to_world_matrix()` call.
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
```cpp
|
||||||
|
mesh.set_origin({10, 0, 5});
|
||||||
|
mesh.set_scale({2, 2, 2});
|
||||||
|
|
||||||
|
ViewAngles angles;
|
||||||
|
angles.pitch = PitchAngle::from_degrees(45.0f);
|
||||||
|
angles.yaw = YawAngle::from_degrees(30.0f);
|
||||||
|
mesh.set_rotation(angles);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Getting Transform Components
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]] const Vector3<NumericType>& get_origin() const;
|
||||||
|
[[nodiscard]] const Vector3<NumericType>& get_scale() const;
|
||||||
|
[[nodiscard]] const RotationAngles& get_rotation_angles() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
Retrieve current transformation components.
|
||||||
|
|
||||||
|
### Transformation Matrix
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]] const Mat4X4& get_to_world_matrix() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the cached local-to-world transformation matrix. The matrix is computed lazily on first access after any transformation change:
|
||||||
|
|
||||||
|
```
|
||||||
|
M = Translation(origin) × Scale(scale) × Rotation(angles)
|
||||||
|
```
|
||||||
|
|
||||||
|
The rotation matrix is computed using the engine-specific `MeshTrait::rotation_matrix()` method.
|
||||||
|
|
||||||
|
**Caching**: The matrix is stored in a `mutable std::optional` and recomputed only when invalidated by `set_*` methods.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Vertex Transformation
|
||||||
|
|
||||||
|
### `vertex_to_world_space`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> vertex_to_world_space(const Vector3<float>& vertex) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
Transforms a vertex from local space to world space by multiplying with the transformation matrix.
|
||||||
|
|
||||||
|
**Algorithm**:
|
||||||
|
1. Convert vertex to column matrix: `[x, y, z, 1]ᵀ`
|
||||||
|
2. Multiply by transformation matrix: `M × vertex`
|
||||||
|
3. Extract the resulting 3D position
|
||||||
|
|
||||||
|
**Usage**:
|
||||||
|
```cpp
|
||||||
|
Vector3<float> local_vertex{1, 0, 0};
|
||||||
|
Vector3<float> world_vertex = mesh.vertex_to_world_space(local_vertex);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: This is used internally by `MeshCollider` to provide world-space support functions for GJK/EPA.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Face Transformation
|
||||||
|
|
||||||
|
### `make_face_in_world_space`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]]
|
||||||
|
Triangle<Vector3<float>> make_face_in_world_space(
|
||||||
|
const std::vector<Vector3<std::size_t>>::const_iterator vao_iterator
|
||||||
|
) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a triangle in world space from a face index iterator.
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
* `vao_iterator` — iterator to an element in `m_vertex_array_object`
|
||||||
|
|
||||||
|
**Returns**: `Triangle` with all three vertices transformed to world space.
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
```cpp
|
||||||
|
for (auto it = mesh.m_vertex_array_object.begin();
|
||||||
|
it != mesh.m_vertex_array_object.end();
|
||||||
|
++it) {
|
||||||
|
Triangle<Vector3<float>> world_triangle = mesh.make_face_in_world_space(it);
|
||||||
|
// Render or process the triangle
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Creating a Box Mesh
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
std::vector<Vector3<float>> box_vbo = {
|
||||||
|
// Bottom face
|
||||||
|
{-0.5f, -0.5f, 0.0f}, { 0.5f, -0.5f, 0.0f},
|
||||||
|
{ 0.5f, 0.5f, 0.0f}, {-0.5f, 0.5f, 0.0f},
|
||||||
|
// Top face
|
||||||
|
{-0.5f, -0.5f, 1.0f}, { 0.5f, -0.5f, 1.0f},
|
||||||
|
{ 0.5f, 0.5f, 1.0f}, {-0.5f, 0.5f, 1.0f}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Vector3<std::size_t>> box_vao = {
|
||||||
|
// Bottom
|
||||||
|
{0, 1, 2}, {0, 2, 3},
|
||||||
|
// Top
|
||||||
|
{4, 6, 5}, {4, 7, 6},
|
||||||
|
// Sides
|
||||||
|
{0, 4, 5}, {0, 5, 1},
|
||||||
|
{1, 5, 6}, {1, 6, 2},
|
||||||
|
{2, 6, 7}, {2, 7, 3},
|
||||||
|
{3, 7, 4}, {3, 4, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
Mesh box(std::move(box_vbo), std::move(box_vao));
|
||||||
|
box.set_origin({0, 0, 50});
|
||||||
|
box.set_scale({10, 10, 10});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Transforming Mesh Over Time
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void update_mesh(Mesh& mesh, float delta_time) {
|
||||||
|
// Rotate mesh
|
||||||
|
auto rotation = mesh.get_rotation_angles();
|
||||||
|
rotation.yaw = YawAngle::from_degrees(
|
||||||
|
rotation.yaw.as_degrees() + 45.0f * delta_time
|
||||||
|
);
|
||||||
|
mesh.set_rotation(rotation);
|
||||||
|
|
||||||
|
// Oscillate position
|
||||||
|
auto origin = mesh.get_origin();
|
||||||
|
origin.z = 50.0f + 10.0f * std::sin(current_time * 2.0f);
|
||||||
|
mesh.set_origin(origin);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collision Detection
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::collision;
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
Mesh mesh_a(vbo_a, vao_a);
|
||||||
|
mesh_a.set_origin({0, 0, 0});
|
||||||
|
|
||||||
|
Mesh mesh_b(vbo_b, vao_b);
|
||||||
|
mesh_b.set_origin({5, 0, 0});
|
||||||
|
|
||||||
|
MeshCollider collider_a(std::move(mesh_a));
|
||||||
|
MeshCollider collider_b(std::move(mesh_b));
|
||||||
|
|
||||||
|
auto result = GjkAlgorithm<MeshCollider<Mesh>>::check_collision(
|
||||||
|
collider_a, collider_b
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rendering Transformed Triangles
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void render_mesh(const Mesh& mesh) {
|
||||||
|
for (auto it = mesh.m_vertex_array_object.begin();
|
||||||
|
it != mesh.m_vertex_array_object.end();
|
||||||
|
++it) {
|
||||||
|
|
||||||
|
Triangle<Vector3<float>> tri = mesh.make_face_in_world_space(it);
|
||||||
|
|
||||||
|
// Draw triangle with your renderer
|
||||||
|
draw_triangle(tri.m_vertex1, tri.m_vertex2, tri.m_vertex3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Engine Traits
|
||||||
|
|
||||||
|
Each game engine has a corresponding `MeshTrait` that provides the `rotation_matrix` function:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class MeshTrait final {
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available Engines
|
||||||
|
|
||||||
|
| Engine | Namespace | Header |
|
||||||
|
|--------|-----------|--------|
|
||||||
|
| Source Engine | `omath::source_engine` | `engines/source_engine/mesh.hpp` |
|
||||||
|
| Unity | `omath::unity_engine` | `engines/unity_engine/mesh.hpp` |
|
||||||
|
| Unreal | `omath::unreal_engine` | `engines/unreal_engine/mesh.hpp` |
|
||||||
|
| Frostbite | `omath::frostbite_engine` | `engines/frostbite_engine/mesh.hpp` |
|
||||||
|
| IW Engine | `omath::iw_engine` | `engines/iw_engine/mesh.hpp` |
|
||||||
|
| OpenGL | `omath::opengl_engine` | `engines/opengl_engine/mesh.hpp` |
|
||||||
|
|
||||||
|
**Example** (Source Engine):
|
||||||
|
```cpp
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
// Uses source_engine::MeshTrait automatically
|
||||||
|
Mesh my_mesh(vertices, indices);
|
||||||
|
```
|
||||||
|
|
||||||
|
See [MeshTrait Documentation](#mesh-trait-documentation) for engine-specific details.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
### Matrix Caching
|
||||||
|
|
||||||
|
The transformation matrix is computed lazily and cached:
|
||||||
|
* **First access**: O(matrix multiply) ≈ 64 float operations
|
||||||
|
* **Subsequent access**: O(1) — returns cached matrix
|
||||||
|
* **Cache invalidation**: Any `set_*` call invalidates the cache
|
||||||
|
|
||||||
|
**Best practice**: Batch transformation updates before accessing the matrix:
|
||||||
|
```cpp
|
||||||
|
// Good: single matrix recomputation
|
||||||
|
mesh.set_origin(new_origin);
|
||||||
|
mesh.set_rotation(new_rotation);
|
||||||
|
mesh.set_scale(new_scale);
|
||||||
|
auto matrix = mesh.get_to_world_matrix(); // Computes once
|
||||||
|
|
||||||
|
// Bad: three matrix recomputations
|
||||||
|
mesh.set_origin(new_origin);
|
||||||
|
auto m1 = mesh.get_to_world_matrix(); // Compute
|
||||||
|
mesh.set_rotation(new_rotation);
|
||||||
|
auto m2 = mesh.get_to_world_matrix(); // Compute again
|
||||||
|
mesh.set_scale(new_scale);
|
||||||
|
auto m3 = mesh.get_to_world_matrix(); // Compute again
|
||||||
|
```
|
||||||
|
|
||||||
|
### Memory Layout
|
||||||
|
|
||||||
|
* **VBO**: Contiguous `std::vector` for cache-friendly access
|
||||||
|
* **VAO**: Contiguous indices for cache-friendly face iteration
|
||||||
|
* **Matrix**: Cached in `std::optional` (no allocation)
|
||||||
|
|
||||||
|
### Transformation Cost
|
||||||
|
|
||||||
|
* `vertex_to_world_space`: ~15-20 FLOPs per vertex (4×4 matrix multiply)
|
||||||
|
* `make_face_in_world_space`: ~60 FLOPs (3 vertices)
|
||||||
|
|
||||||
|
For high-frequency transformations, consider:
|
||||||
|
* Caching transformed vertices if the mesh doesn't change
|
||||||
|
* Using simpler proxy geometry for collision
|
||||||
|
* Batching transformations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate System Details
|
||||||
|
|
||||||
|
Different engines use different coordinate systems:
|
||||||
|
|
||||||
|
| Engine | Up Axis | Forward Axis | Handedness |
|
||||||
|
|--------|---------|--------------|------------|
|
||||||
|
| Source | +Z | +Y | Right |
|
||||||
|
| Unity | +Y | +Z | Left |
|
||||||
|
| Unreal | +Z | +X | Left |
|
||||||
|
| Frostbite | +Y | +Z | Right |
|
||||||
|
| IW Engine | +Z | +Y | Right |
|
||||||
|
| OpenGL | +Y | +Z | Right |
|
||||||
|
|
||||||
|
The `MeshTrait::rotation_matrix` function accounts for these differences, ensuring correct transformations in each engine's space.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Limitations & Edge Cases
|
||||||
|
|
||||||
|
### Empty Mesh
|
||||||
|
|
||||||
|
A mesh with no vertices or faces is valid but not useful:
|
||||||
|
```cpp
|
||||||
|
Mesh empty_mesh({}, {}); // Valid but meaningless
|
||||||
|
```
|
||||||
|
|
||||||
|
For collision detection, ensure `m_vertex_buffer` is non-empty.
|
||||||
|
|
||||||
|
### Index Validity
|
||||||
|
|
||||||
|
No bounds checking is performed on indices in `m_vertex_array_object`. Ensure all indices are valid:
|
||||||
|
```cpp
|
||||||
|
assert(face.x < mesh.m_vertex_buffer.size());
|
||||||
|
assert(face.y < mesh.m_vertex_buffer.size());
|
||||||
|
assert(face.z < mesh.m_vertex_buffer.size());
|
||||||
|
```
|
||||||
|
|
||||||
|
### Degenerate Triangles
|
||||||
|
|
||||||
|
Faces with duplicate indices or collinear vertices will produce degenerate triangles. The mesh doesn't validate this; users must ensure clean geometry.
|
||||||
|
|
||||||
|
### Thread Safety
|
||||||
|
|
||||||
|
* **Read-only**: Safe to read from multiple threads (including const methods)
|
||||||
|
* **Modification**: Not thread-safe; synchronize `set_*` calls externally
|
||||||
|
* **Matrix cache**: Uses `mutable` member; not thread-safe even for const methods
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [MeshCollider Documentation](../collision/mesh_collider.md) - Collision wrapper for meshes
|
||||||
|
- [GJK Algorithm Documentation](../collision/gjk_algorithm.md) - Uses mesh for collision detection
|
||||||
|
- [EPA Algorithm Documentation](../collision/epa_algorithm.md) - Penetration depth with meshes
|
||||||
|
- [Triangle Documentation](../linear_algebra/triangle.md) - Triangle primitive
|
||||||
|
- [Mat4X4 Documentation](../linear_algebra/mat.md) - Transformation matrices
|
||||||
|
- [Box Documentation](box.md) - Box primitive
|
||||||
|
- [Plane Documentation](plane.md) - Plane primitive
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Mesh Trait Documentation
|
||||||
|
|
||||||
|
For engine-specific `MeshTrait` details, see:
|
||||||
|
|
||||||
|
- [Source Engine MeshTrait](../engines/source_engine/mesh_trait.md)
|
||||||
|
- [Unity Engine MeshTrait](../engines/unity_engine/mesh_trait.md)
|
||||||
|
- [Unreal Engine MeshTrait](../engines/unreal_engine/mesh_trait.md)
|
||||||
|
- [Frostbite Engine MeshTrait](../engines/frostbite/mesh_trait.md)
|
||||||
|
- [IW Engine MeshTrait](../engines/iw_engine/mesh_trait.md)
|
||||||
|
- [OpenGL Engine MeshTrait](../engines/opengl_engine/mesh_trait.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
98
docs/3d_primitives/plane.md
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
# `omath::primitives::create_plane` — Build an oriented quad (2 triangles)
|
||||||
|
|
||||||
|
> Header: your project’s `primitives/plane.hpp`
|
||||||
|
> Namespace: `omath::primitives`
|
||||||
|
> Depends on: `omath::Triangle<omath::Vector3<float>>`, `omath::Vector3<float>`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]]
|
||||||
|
std::array<Triangle<Vector3<float>>, 2>
|
||||||
|
create_plane(const Vector3<float>& vertex_a,
|
||||||
|
const Vector3<float>& vertex_b,
|
||||||
|
const Vector3<float>& direction,
|
||||||
|
float size) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
Creates a **rectangle (quad)** in 3D oriented by the edge **A→B** and a second in-plane **direction**. The quad is returned as **two triangles** suitable for rendering or collision.
|
||||||
|
|
||||||
|
* Edge axis: `e = vertex_b - vertex_a`
|
||||||
|
* Width axis: “direction”, **projected to be perpendicular to `e`** so the quad is planar and well-formed.
|
||||||
|
* Normal (by right-hand rule): `n ∝ e × width`.
|
||||||
|
|
||||||
|
> **Sizing convention**
|
||||||
|
> Typical construction uses **half-width = `size`** along the (normalized, orthogonalized) *direction*, i.e. the total width is `2*size`.
|
||||||
|
> If your implementation interprets `size` as full width, adjust your expectations accordingly.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
* `vertex_a`, `vertex_b` — two adjacent quad vertices defining the **long edge** of the plane.
|
||||||
|
* `direction` — a vector indicating the **cross-edge direction** within the plane (does not need to be orthogonal or normalized).
|
||||||
|
* `size` — **half-width** of the quad along the (processed) `direction`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Return
|
||||||
|
|
||||||
|
`std::array<Triangle<Vector3<float>>, 2>` — the quad triangulated (consistent CCW winding, outward normal per `e × width`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Robust construction (expected math)
|
||||||
|
|
||||||
|
1. `e = vertex_b - vertex_a`
|
||||||
|
2. Make `d` perpendicular to `e`:
|
||||||
|
|
||||||
|
```
|
||||||
|
d = direction - e * (e.dot(direction) / e.length_sqr());
|
||||||
|
if (d.length_sqr() == 0) pick an arbitrary perpendicular to e
|
||||||
|
d = d.normalized();
|
||||||
|
```
|
||||||
|
3. Offsets: `w = d * size`
|
||||||
|
4. Four corners:
|
||||||
|
|
||||||
|
```
|
||||||
|
A0 = vertex_a - w; A1 = vertex_a + w;
|
||||||
|
B0 = vertex_b - w; B1 = vertex_b + w;
|
||||||
|
```
|
||||||
|
5. Triangles (CCW when viewed from +normal):
|
||||||
|
|
||||||
|
```
|
||||||
|
T0 = Triangle{ A0, A1, B1 }
|
||||||
|
T1 = Triangle{ A0, B1, B0 }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using omath::Vector3;
|
||||||
|
using omath::Triangle;
|
||||||
|
using omath::primitives::create_plane;
|
||||||
|
|
||||||
|
Vector3<float> a{ -1, 0, -1 }; // edge start
|
||||||
|
Vector3<float> b{ 1, 0, -1 }; // edge end
|
||||||
|
Vector3<float> dir{ 0, 0, 1 }; // cross-edge direction within the plane (roughly +Z)
|
||||||
|
float half_width = 2.0f;
|
||||||
|
|
||||||
|
auto quad = create_plane(a, b, dir, half_width);
|
||||||
|
|
||||||
|
// e.g., compute normals
|
||||||
|
for (const auto& tri : quad) {
|
||||||
|
auto n = tri.calculate_normal(); (void)n;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & edge cases
|
||||||
|
|
||||||
|
* **Degenerate edge**: if `vertex_a == vertex_b`, the plane is undefined.
|
||||||
|
* **Collinearity**: if `direction` is parallel to `vertex_b - vertex_a`, the function must choose an alternate perpendicular; expect a fallback.
|
||||||
|
* **Winding**: If your renderer expects a specific face order, verify and swap the two vertices in each triangle as needed.
|
||||||
577
docs/api_overview.md
Normal file
@@ -0,0 +1,577 @@
|
|||||||
|
# API Overview
|
||||||
|
|
||||||
|
This document provides a high-level overview of OMath's API, organized by functionality area.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Module Organization
|
||||||
|
|
||||||
|
OMath is organized into several logical modules:
|
||||||
|
|
||||||
|
### Core Mathematics
|
||||||
|
- **Linear Algebra** - Vectors, matrices, triangles
|
||||||
|
- **Trigonometry** - Angles, view angles, trigonometric functions
|
||||||
|
- **3D Primitives** - Boxes, planes, meshes, geometric shapes
|
||||||
|
|
||||||
|
### Game Development
|
||||||
|
- **Collision Detection** - Ray tracing, GJK/EPA algorithms, mesh collision, intersection tests
|
||||||
|
- **Projectile Prediction** - Ballistics and aim-assist calculations
|
||||||
|
- **Projection** - Camera systems and world-to-screen transformations
|
||||||
|
- **Pathfinding** - A* algorithm, navigation meshes
|
||||||
|
|
||||||
|
### Engine Support
|
||||||
|
- **Source Engine** - Valve's Source Engine (CS:GO, TF2, etc.)
|
||||||
|
- **Unity Engine** - Unity game engine
|
||||||
|
- **Unreal Engine** - Epic's Unreal Engine
|
||||||
|
- **Frostbite Engine** - EA's Frostbite Engine
|
||||||
|
- **IW Engine** - Infinity Ward's engine (Call of Duty)
|
||||||
|
- **OpenGL Engine** - Canonical OpenGL coordinate system
|
||||||
|
|
||||||
|
### Utilities
|
||||||
|
- **Color** - RGBA color representation
|
||||||
|
- **Pattern Scanning** - Memory pattern search (wildcards, PE files)
|
||||||
|
- **Reverse Engineering** - Internal/external memory manipulation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core Types
|
||||||
|
|
||||||
|
### Vectors
|
||||||
|
|
||||||
|
All vector types are template-based and support arithmetic types.
|
||||||
|
|
||||||
|
| Type | Description | Key Methods |
|
||||||
|
|------|-------------|-------------|
|
||||||
|
| `Vector2<T>` | 2D vector | `length()`, `normalized()`, `dot()`, `distance_to()` |
|
||||||
|
| `Vector3<T>` | 3D vector | `length()`, `normalized()`, `dot()`, `cross()`, `angle_between()` |
|
||||||
|
| `Vector4<T>` | 4D vector | Extends Vector3 with `w` component |
|
||||||
|
|
||||||
|
**Common aliases:**
|
||||||
|
```cpp
|
||||||
|
using Vec2f = Vector2<float>;
|
||||||
|
using Vec3f = Vector3<float>;
|
||||||
|
using Vec4f = Vector4<float>;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key features:**
|
||||||
|
- Component-wise arithmetic (+, -, *, /)
|
||||||
|
- Scalar multiplication/division
|
||||||
|
- Dot and cross products
|
||||||
|
- Safe normalization (returns original if length is zero)
|
||||||
|
- Distance calculations
|
||||||
|
- Angle calculations with error handling
|
||||||
|
- Hash support for `float` variants
|
||||||
|
- `std::formatter` support
|
||||||
|
|
||||||
|
### Matrices
|
||||||
|
|
||||||
|
| Type | Description | Key Methods |
|
||||||
|
|------|-------------|-------------|
|
||||||
|
| `Mat4X4` | 4×4 matrix | `identity()`, `transpose()`, `determinant()`, `inverse()` |
|
||||||
|
|
||||||
|
**Use cases:**
|
||||||
|
- Transformation matrices
|
||||||
|
- View matrices
|
||||||
|
- Projection matrices
|
||||||
|
- Model-view-projection pipelines
|
||||||
|
|
||||||
|
### Angles
|
||||||
|
|
||||||
|
Strong-typed angle system with compile-time range enforcement:
|
||||||
|
|
||||||
|
| Type | Range | Description |
|
||||||
|
|------|-------|-------------|
|
||||||
|
| `Angle<T, Min, Max, Flags>` | Custom | Generic angle type with bounds |
|
||||||
|
| `PitchAngle` | [-89°, 89°] | Vertical camera rotation |
|
||||||
|
| `YawAngle` | [-180°, 180°] | Horizontal camera rotation |
|
||||||
|
| `RollAngle` | [-180°, 180°] | Camera roll |
|
||||||
|
| `ViewAngles` | - | Composite pitch/yaw/roll |
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Automatic normalization/clamping based on flags
|
||||||
|
- Conversions between degrees and radians
|
||||||
|
- Type-safe arithmetic
|
||||||
|
- Prevents common angle bugs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Projection System
|
||||||
|
|
||||||
|
### Camera
|
||||||
|
|
||||||
|
Generic camera template that works with any engine trait:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class MatrixType, class AnglesType, class EngineTrait>
|
||||||
|
class Camera;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Engine-specific cameras:**
|
||||||
|
```cpp
|
||||||
|
omath::source_engine::Camera // Source Engine
|
||||||
|
omath::unity_engine::Camera // Unity
|
||||||
|
omath::unreal_engine::Camera // Unreal
|
||||||
|
omath::frostbite_engine::Camera // Frostbite
|
||||||
|
omath::iw_engine::Camera // IW Engine
|
||||||
|
omath::opengl_engine::Camera // OpenGL
|
||||||
|
```
|
||||||
|
|
||||||
|
**Core methods:**
|
||||||
|
- `world_to_screen(Vector3<float>)` - Project 3D point to 2D screen
|
||||||
|
- `get_view_matrix()` - Get current view matrix
|
||||||
|
- `get_projection_matrix()` - Get current projection matrix
|
||||||
|
- `update(position, angles)` - Update camera state
|
||||||
|
|
||||||
|
**Supporting types:**
|
||||||
|
- `ViewPort` - Screen dimensions and aspect ratio
|
||||||
|
- `FieldOfView` - FOV in degrees with validation
|
||||||
|
- `ProjectionError` - Error codes for projection failures
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Collision Detection
|
||||||
|
|
||||||
|
### GJK/EPA Algorithms
|
||||||
|
|
||||||
|
Advanced convex shape collision detection using the Gilbert-Johnson-Keerthi and Expanding Polytope algorithms:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::collision {
|
||||||
|
template<class ColliderType>
|
||||||
|
class GjkAlgorithm;
|
||||||
|
|
||||||
|
template<class ColliderType>
|
||||||
|
class Epa;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**GJK (Gilbert-Johnson-Keerthi):**
|
||||||
|
* Detects collision between two convex shapes
|
||||||
|
* Returns a 4-point simplex when collision is detected
|
||||||
|
* O(k) complexity where k is typically < 20 iterations
|
||||||
|
* Works with any collider implementing `find_abs_furthest_vertex()`
|
||||||
|
|
||||||
|
**EPA (Expanding Polytope Algorithm):**
|
||||||
|
* Computes penetration depth and separation normal
|
||||||
|
* Takes GJK's output simplex as input
|
||||||
|
* Provides contact information for physics simulation
|
||||||
|
* Configurable iteration limit and convergence tolerance
|
||||||
|
|
||||||
|
**Supporting Types:**
|
||||||
|
|
||||||
|
| Type | Description | Key Features |
|
||||||
|
|------|-------------|--------------|
|
||||||
|
| `Simplex<VectorType>` | 1-4 point geometric simplex | Fixed capacity, GJK iteration support |
|
||||||
|
| `MeshCollider<MeshType>` | Convex mesh collider | Support function for GJK/EPA |
|
||||||
|
| `GjkHitInfo<VertexType>` | Collision result | Hit flag and simplex |
|
||||||
|
| `Epa::Result` | Penetration info | Depth, normal, iteration count |
|
||||||
|
|
||||||
|
### LineTracer
|
||||||
|
|
||||||
|
Ray-casting and line tracing utilities:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::collision {
|
||||||
|
class LineTracer;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Ray-triangle intersection (Möller-Trumbore algorithm)
|
||||||
|
- Ray-plane intersection
|
||||||
|
- Ray-box intersection
|
||||||
|
- Distance calculations
|
||||||
|
- Normal calculations at hit points
|
||||||
|
|
||||||
|
### 3D Primitives
|
||||||
|
|
||||||
|
| Type | Description | Key Methods |
|
||||||
|
|------|-------------|-------------|
|
||||||
|
| `Plane` | Infinite plane | `intersects_ray()`, `distance_to_point()` |
|
||||||
|
| `Box` | Axis-aligned bounding box | `contains()`, `intersects()` |
|
||||||
|
| `Mesh` | Polygonal mesh with transforms | `vertex_to_world_space()`, `make_face_in_world_space()` |
|
||||||
|
|
||||||
|
**Mesh Features:**
|
||||||
|
* Vertex buffer (VBO) and index buffer (VAO/EBO) storage
|
||||||
|
* Position, rotation, and scale transformations
|
||||||
|
* Cached transformation matrix
|
||||||
|
* Engine-specific coordinate system support
|
||||||
|
* Compatible with `MeshCollider` for collision detection
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Projectile Prediction
|
||||||
|
|
||||||
|
### Interfaces
|
||||||
|
|
||||||
|
**`ProjPredEngineInterface`** - Base interface for all prediction engines
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
virtual std::optional<Vector3<float>>
|
||||||
|
maybe_calculate_aim_point(const Projectile&, const Target&) const = 0;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Implementations
|
||||||
|
|
||||||
|
| Engine | Description | Optimizations |
|
||||||
|
|--------|-------------|---------------|
|
||||||
|
| `ProjPredEngineLegacy` | Standard implementation | Portable, works everywhere |
|
||||||
|
| `ProjPredEngineAVX2` | AVX2 optimized | 2-4x faster on modern CPUs |
|
||||||
|
|
||||||
|
### Supporting Types
|
||||||
|
|
||||||
|
**`Projectile`** - Defines projectile properties:
|
||||||
|
```cpp
|
||||||
|
struct Projectile {
|
||||||
|
Vector3<float> origin;
|
||||||
|
float speed;
|
||||||
|
Vector3<float> gravity;
|
||||||
|
// ... additional properties
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**`Target`** - Defines target state:
|
||||||
|
```cpp
|
||||||
|
struct Target {
|
||||||
|
Vector3<float> position;
|
||||||
|
Vector3<float> velocity;
|
||||||
|
// ... additional properties
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pathfinding
|
||||||
|
|
||||||
|
### A* Algorithm
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::pathfinding {
|
||||||
|
template<typename NodeType>
|
||||||
|
class AStar;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Generic node type support
|
||||||
|
- Customizable heuristics
|
||||||
|
- Efficient priority queue implementation
|
||||||
|
- Path reconstruction
|
||||||
|
|
||||||
|
### Navigation Mesh
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::pathfinding {
|
||||||
|
class NavigationMesh;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Triangle-based navigation
|
||||||
|
- Neighbor connectivity
|
||||||
|
- Walkable area definitions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Engine Traits
|
||||||
|
|
||||||
|
Each game engine has a trait system providing engine-specific math:
|
||||||
|
|
||||||
|
### CameraTrait
|
||||||
|
|
||||||
|
Implements camera math for an engine:
|
||||||
|
- `calc_look_at_angle()` - Calculate angles to look at a point
|
||||||
|
- `calc_view_matrix()` - Build view matrix from angles and position
|
||||||
|
- `calc_projection_matrix()` - Build projection matrix from FOV and viewport
|
||||||
|
|
||||||
|
### MeshTrait
|
||||||
|
|
||||||
|
Provides mesh transformation for an engine:
|
||||||
|
- `rotation_matrix()` - Build rotation matrix from engine-specific angles
|
||||||
|
- Handles coordinate system differences (Y-up vs Z-up, left/right-handed)
|
||||||
|
- Used by `Mesh` class for local-to-world transformations
|
||||||
|
|
||||||
|
### PredEngineTrait
|
||||||
|
|
||||||
|
Provides physics/ballistics specific to an engine:
|
||||||
|
- Gravity vectors
|
||||||
|
- Coordinate system conventions
|
||||||
|
- Unit conversions
|
||||||
|
- Physics parameters
|
||||||
|
|
||||||
|
### Available Traits
|
||||||
|
|
||||||
|
| Engine | Camera Trait | Mesh Trait | Pred Engine Trait | Constants | Formulas |
|
||||||
|
|--------|--------------|------------|-------------------|-----------|----------|
|
||||||
|
| Source Engine | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| Unity Engine | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| Unreal Engine | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| Frostbite | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| IW Engine | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| OpenGL | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- See `docs/engines/<engine_name>/` for detailed per-engine docs
|
||||||
|
- Each engine has separate docs for camera_trait, mesh_trait, pred_engine_trait, constants, and formulas
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Utility Functions
|
||||||
|
|
||||||
|
### Color
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct Color {
|
||||||
|
uint8_t r, g, b, a;
|
||||||
|
|
||||||
|
// Conversions
|
||||||
|
static Color from_hsv(float h, float s, float v);
|
||||||
|
static Color from_hex(uint32_t hex);
|
||||||
|
uint32_t to_hex() const;
|
||||||
|
|
||||||
|
// Blending
|
||||||
|
Color blend(const Color& other, float t) const;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern Scanning
|
||||||
|
|
||||||
|
**Binary pattern search with wildcards:**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Pattern with wildcards (?? = any byte)
|
||||||
|
PatternView pattern{"48 8B 05 ?? ?? ?? ?? 48 85 C0"};
|
||||||
|
|
||||||
|
// Scan memory
|
||||||
|
auto result = pattern_scan(memory_buffer, pattern);
|
||||||
|
if (result) {
|
||||||
|
std::cout << "Found at offset: " << result->offset << "\n";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**PE file scanning:**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
PEPatternScanner scanner("target.exe");
|
||||||
|
if (auto addr = scanner.scan_pattern(pattern)) {
|
||||||
|
std::cout << "Found at RVA: " << *addr << "\n";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reverse Engineering
|
||||||
|
|
||||||
|
**External memory access:**
|
||||||
|
```cpp
|
||||||
|
ExternalRevObject process("game.exe");
|
||||||
|
Vector3<float> position = process.read<Vector3<float>>(address);
|
||||||
|
process.write(address, new_position);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Internal memory access:**
|
||||||
|
```cpp
|
||||||
|
InternalRevObject memory;
|
||||||
|
auto value = memory.read<float>(address);
|
||||||
|
memory.write(address, new_value);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Concepts and Constraints
|
||||||
|
|
||||||
|
OMath uses C++20 concepts for type safety:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class T>
|
||||||
|
concept Arithmetic = std::is_arithmetic_v<T>;
|
||||||
|
|
||||||
|
template<class EngineTrait>
|
||||||
|
concept CameraEngineConcept = requires(EngineTrait t) {
|
||||||
|
{ t.calc_look_at_angle(...) } -> /* returns angles */;
|
||||||
|
{ t.calc_view_matrix(...) } -> /* returns matrix */;
|
||||||
|
{ t.calc_projection_matrix(...) } -> /* returns matrix */;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
OMath uses modern C++ error handling:
|
||||||
|
|
||||||
|
### std::expected (C++23)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::expected<Angle<...>, Vector3Error>
|
||||||
|
angle_between(const Vector3& other) const;
|
||||||
|
|
||||||
|
if (auto angle = v1.angle_between(v2)) {
|
||||||
|
// Success: use *angle
|
||||||
|
} else {
|
||||||
|
// Error: angle.error() gives Vector3Error
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### std::optional
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::optional<Vector2<float>>
|
||||||
|
world_to_screen(const Vector3<float>& world);
|
||||||
|
|
||||||
|
if (auto screen = camera.world_to_screen(pos)) {
|
||||||
|
// Success: use screen->x, screen->y
|
||||||
|
} else {
|
||||||
|
// Point not visible
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error Codes
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
enum class ProjectionError {
|
||||||
|
SUCCESS = 0,
|
||||||
|
POINT_BEHIND_CAMERA,
|
||||||
|
INVALID_VIEWPORT,
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
### constexpr Support
|
||||||
|
|
||||||
|
Most operations are `constexpr` where possible:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector3<float> v{1, 2, 3};
|
||||||
|
constexpr auto len_sq = v.length_sqr(); // Computed at compile time
|
||||||
|
```
|
||||||
|
|
||||||
|
### AVX2 Optimizations
|
||||||
|
|
||||||
|
Use AVX2 variants when available:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Standard: portable but slower
|
||||||
|
ProjPredEngineLegacy legacy_engine;
|
||||||
|
|
||||||
|
// AVX2: 2-4x faster on modern CPUs
|
||||||
|
ProjPredEngineAVX2 fast_engine;
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to use AVX2:**
|
||||||
|
- Modern Intel/AMD processors (2013+)
|
||||||
|
- Performance-critical paths
|
||||||
|
- Batch operations
|
||||||
|
|
||||||
|
**When to use Legacy:**
|
||||||
|
- Older processors
|
||||||
|
- ARM platforms
|
||||||
|
- Guaranteed compatibility
|
||||||
|
|
||||||
|
### Cache Efficiency
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: contiguous storage
|
||||||
|
std::vector<Vector3<float>> positions;
|
||||||
|
|
||||||
|
// Good: structure of arrays for SIMD
|
||||||
|
struct Particles {
|
||||||
|
std::vector<float> x, y, z;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Platform Support
|
||||||
|
|
||||||
|
| Platform | Support | Notes |
|
||||||
|
|----------|---------|-------|
|
||||||
|
| Windows | ✓ | MSVC, Clang, GCC |
|
||||||
|
| Linux | ✓ | GCC, Clang |
|
||||||
|
| macOS | ✓ | Clang |
|
||||||
|
|
||||||
|
**Minimum requirements:**
|
||||||
|
- C++20 compiler
|
||||||
|
- C++23 recommended for `std::expected`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Thread Safety
|
||||||
|
|
||||||
|
- **Vector/Matrix types**: Thread-safe (immutable operations)
|
||||||
|
- **Camera**: Not thread-safe (mutable state)
|
||||||
|
- **Pattern scanning**: Thread-safe (read-only operations)
|
||||||
|
- **Memory access**: Depends on OS/process synchronization
|
||||||
|
|
||||||
|
**Thread-safe example:**
|
||||||
|
```cpp
|
||||||
|
// Safe: each thread gets its own camera
|
||||||
|
std::vector<std::thread> threads;
|
||||||
|
for (int i = 0; i < num_threads; ++i) {
|
||||||
|
threads.emplace_back([i]() {
|
||||||
|
Camera camera = /* create camera */;
|
||||||
|
// Use camera in this thread
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### 1. Use Type Aliases
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Vec3f = omath::Vector3<float>;
|
||||||
|
using Mat4 = omath::Mat4X4;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Prefer constexpr When Possible
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr auto compute_at_compile_time() {
|
||||||
|
Vector3<float> v{1, 2, 3};
|
||||||
|
return v.length_sqr();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Check Optional/Expected Results
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good
|
||||||
|
if (auto result = camera.world_to_screen(pos)) {
|
||||||
|
use(*result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bad - may crash
|
||||||
|
auto result = camera.world_to_screen(pos);
|
||||||
|
use(result->x); // Undefined behavior if nullopt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Use Engine-Specific Types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: uses correct coordinate system
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
Camera camera = /* ... */;
|
||||||
|
|
||||||
|
// Bad: mixing engine types
|
||||||
|
using UnityCamera = omath::unity_engine::Camera;
|
||||||
|
using SourceAngles = omath::source_engine::ViewAngles;
|
||||||
|
UnityCamera camera{pos, SourceAngles{}}; // Wrong!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Getting Started Guide](getting_started.md)
|
||||||
|
- [Installation Instructions](install.md)
|
||||||
|
- [Examples Directory](../examples/)
|
||||||
|
- Individual module documentation in respective folders
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
532
docs/best_practices.md
Normal file
@@ -0,0 +1,532 @@
|
|||||||
|
# Best Practices
|
||||||
|
|
||||||
|
Guidelines for using OMath effectively and avoiding common pitfalls.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Code Organization
|
||||||
|
|
||||||
|
### Use Type Aliases
|
||||||
|
|
||||||
|
Define clear type aliases for commonly used types:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Clear and concise
|
||||||
|
using Vec3f = omath::Vector3<float>;
|
||||||
|
using Vec2f = omath::Vector2<float>;
|
||||||
|
using Mat4 = omath::Mat4X4;
|
||||||
|
|
||||||
|
Vec3f position{1.0f, 2.0f, 3.0f};
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Avoid: Verbose and repetitive
|
||||||
|
omath::Vector3<float> position{1.0f, 2.0f, 3.0f};
|
||||||
|
omath::Vector3<float> velocity{0.0f, 0.0f, 0.0f};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Namespace Usage
|
||||||
|
|
||||||
|
Be selective with `using namespace`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Specific namespace for your engine
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
// Good: Import specific types
|
||||||
|
using omath::Vector3;
|
||||||
|
using omath::Vector2;
|
||||||
|
|
||||||
|
// Avoid: Too broad
|
||||||
|
using namespace omath; // Imports everything
|
||||||
|
```
|
||||||
|
|
||||||
|
### Include What You Use
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Include specific headers
|
||||||
|
#include <omath/linear_algebra/vector3.hpp>
|
||||||
|
#include <omath/projection/camera.hpp>
|
||||||
|
|
||||||
|
// Okay for development
|
||||||
|
#include <omath/omath.hpp>
|
||||||
|
|
||||||
|
// Production: Include only what you need
|
||||||
|
// to reduce compile times
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### Always Check Optional Results
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Check before using
|
||||||
|
if (auto screen = camera.world_to_screen(world_pos)) {
|
||||||
|
draw_at(screen->x, screen->y);
|
||||||
|
} else {
|
||||||
|
// Handle point not visible
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bad: Unchecked access can crash
|
||||||
|
auto screen = camera.world_to_screen(world_pos);
|
||||||
|
draw_at(screen->x, screen->y); // Undefined behavior if nullopt!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Handle Expected Errors
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Handle error case
|
||||||
|
if (auto angle = v1.angle_between(v2)) {
|
||||||
|
use_angle(*angle);
|
||||||
|
} else {
|
||||||
|
switch (angle.error()) {
|
||||||
|
case Vector3Error::IMPOSSIBLE_BETWEEN_ANGLE:
|
||||||
|
// Handle zero-length vector
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bad: Assume success
|
||||||
|
auto angle = v1.angle_between(v2);
|
||||||
|
use_angle(*angle); // Throws if error!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Validate Inputs
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Validate before expensive operations
|
||||||
|
bool is_valid_projectile(const Projectile& proj) {
|
||||||
|
return proj.speed > 0.0f &&
|
||||||
|
std::isfinite(proj.speed) &&
|
||||||
|
std::isfinite(proj.origin.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_valid_projectile(proj) && is_valid_target(target)) {
|
||||||
|
auto aim = engine.maybe_calculate_aim_point(proj, target);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
### Use constexpr When Possible
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Computed at compile time
|
||||||
|
constexpr Vector3<float> gravity{0.0f, 0.0f, -9.81f};
|
||||||
|
constexpr float max_range = 1000.0f;
|
||||||
|
constexpr float max_range_sq = max_range * max_range;
|
||||||
|
|
||||||
|
// Use in runtime calculations
|
||||||
|
if (position.length_sqr() < max_range_sq) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Prefer Squared Distance
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Avoids expensive sqrt
|
||||||
|
constexpr float max_dist_sq = 100.0f * 100.0f;
|
||||||
|
for (const auto& entity : entities) {
|
||||||
|
if (entity.pos.distance_to_sqr(player_pos) < max_dist_sq) {
|
||||||
|
// Process nearby entity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid: Unnecessary sqrt calls
|
||||||
|
constexpr float max_dist = 100.0f;
|
||||||
|
for (const auto& entity : entities) {
|
||||||
|
if (entity.pos.distance_to(player_pos) < max_dist) {
|
||||||
|
// More expensive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cache Expensive Calculations
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Update camera once per frame
|
||||||
|
void update_frame() {
|
||||||
|
camera.update(current_position, current_angles);
|
||||||
|
|
||||||
|
// All projections use cached matrices
|
||||||
|
for (const auto& entity : entities) {
|
||||||
|
if (auto screen = camera.world_to_screen(entity.pos)) {
|
||||||
|
draw_entity(screen->x, screen->y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bad: Camera recreated each call
|
||||||
|
for (const auto& entity : entities) {
|
||||||
|
Camera cam(pos, angles, viewport, fov, near, far); // Expensive!
|
||||||
|
auto screen = cam.world_to_screen(entity.pos);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Choose the Right Engine
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Use AVX2 when available
|
||||||
|
#ifdef __AVX2__
|
||||||
|
using Engine = ProjPredEngineAVX2;
|
||||||
|
#else
|
||||||
|
using Engine = ProjPredEngineLegacy;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Engine prediction_engine;
|
||||||
|
|
||||||
|
// Or runtime detection
|
||||||
|
Engine* create_best_engine() {
|
||||||
|
if (cpu_supports_avx2()) {
|
||||||
|
return new ProjPredEngineAVX2();
|
||||||
|
}
|
||||||
|
return new ProjPredEngineLegacy();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Minimize Allocations
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Reuse vectors
|
||||||
|
std::vector<Vector3<float>> positions;
|
||||||
|
positions.reserve(expected_count);
|
||||||
|
|
||||||
|
// In loop
|
||||||
|
positions.clear(); // Doesn't deallocate
|
||||||
|
for (...) {
|
||||||
|
positions.push_back(compute_position());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bad: Allocate every time
|
||||||
|
for (...) {
|
||||||
|
std::vector<Vector3<float>> positions; // Allocates each iteration
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type Safety
|
||||||
|
|
||||||
|
### Use Strong Angle Types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Type-safe angles
|
||||||
|
PitchAngle pitch = PitchAngle::from_degrees(45.0f);
|
||||||
|
YawAngle yaw = YawAngle::from_degrees(90.0f);
|
||||||
|
ViewAngles angles{pitch, yaw, RollAngle::from_degrees(0.0f)};
|
||||||
|
|
||||||
|
// Bad: Raw floats lose safety
|
||||||
|
float pitch = 45.0f; // No range checking
|
||||||
|
float yaw = 90.0f; // Can go out of bounds
|
||||||
|
```
|
||||||
|
|
||||||
|
### Match Engine Types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Use matching types from same engine
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
Camera camera = /* ... */;
|
||||||
|
ViewAngles angles = /* ... */;
|
||||||
|
|
||||||
|
// Bad: Mixing engine types
|
||||||
|
using UnityCamera = omath::unity_engine::Camera;
|
||||||
|
using SourceAngles = omath::source_engine::ViewAngles;
|
||||||
|
UnityCamera camera{pos, SourceAngles{}, ...}; // May cause issues!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Template Type Parameters
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Explicit and clear
|
||||||
|
Vector3<float> position;
|
||||||
|
Vector3<double> high_precision_pos;
|
||||||
|
|
||||||
|
// Okay: Use default float
|
||||||
|
Vector3<> position; // Defaults to float
|
||||||
|
|
||||||
|
// Avoid: Mixing types unintentionally
|
||||||
|
Vector3<float> a;
|
||||||
|
Vector3<double> b;
|
||||||
|
auto result = a + b; // Type mismatch!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing & Validation
|
||||||
|
|
||||||
|
### Test Edge Cases
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void test_projection() {
|
||||||
|
Camera camera = setup_camera();
|
||||||
|
|
||||||
|
// Test normal case
|
||||||
|
assert(camera.world_to_screen({100, 100, 100}).has_value());
|
||||||
|
|
||||||
|
// Test edge cases
|
||||||
|
assert(!camera.world_to_screen({0, 0, -100}).has_value()); // Behind
|
||||||
|
assert(!camera.world_to_screen({1e10, 0, 0}).has_value()); // Too far
|
||||||
|
|
||||||
|
// Test boundaries
|
||||||
|
Vector3<float> at_near{0, 0, camera.near_plane() + 0.1f};
|
||||||
|
assert(camera.world_to_screen(at_near).has_value());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Validate Assumptions
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void validate_game_data() {
|
||||||
|
// Validate FOV
|
||||||
|
float fov = read_game_fov();
|
||||||
|
assert(fov > 1.0f && fov < 179.0f);
|
||||||
|
|
||||||
|
// Validate positions
|
||||||
|
Vector3<float> pos = read_player_position();
|
||||||
|
assert(std::isfinite(pos.x));
|
||||||
|
assert(std::isfinite(pos.y));
|
||||||
|
assert(std::isfinite(pos.z));
|
||||||
|
|
||||||
|
// Validate viewport
|
||||||
|
ViewPort vp = read_viewport();
|
||||||
|
assert(vp.width > 0 && vp.height > 0);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use Assertions
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Catch errors early in development
|
||||||
|
void shoot_projectile(const Projectile& proj) {
|
||||||
|
assert(proj.speed > 0.0f && "Projectile speed must be positive");
|
||||||
|
assert(std::isfinite(proj.origin.length()) && "Invalid projectile origin");
|
||||||
|
|
||||||
|
// Continue with logic
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add debug-only checks
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (!is_valid_input(data)) {
|
||||||
|
std::cerr << "Warning: Invalid input detected\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Memory & Resources
|
||||||
|
|
||||||
|
### RAII for Resources
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Automatic cleanup
|
||||||
|
class GameOverlay {
|
||||||
|
Camera camera_;
|
||||||
|
std::vector<Entity> entities_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GameOverlay(/* ... */) : camera_(/* ... */) {
|
||||||
|
entities_.reserve(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resources cleaned up automatically
|
||||||
|
~GameOverlay() = default;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Avoid Unnecessary Copies
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Pass by const reference
|
||||||
|
void draw_entities(const std::vector<Vector3<float>>& positions) {
|
||||||
|
for (const auto& pos : positions) {
|
||||||
|
// Process position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bad: Copies entire vector
|
||||||
|
void draw_entities(std::vector<Vector3<float>> positions) {
|
||||||
|
// Expensive copy!
|
||||||
|
}
|
||||||
|
|
||||||
|
// Good: Move when transferring ownership
|
||||||
|
std::vector<Vector3<float>> compute_positions();
|
||||||
|
auto positions = compute_positions(); // Move, not copy
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use Structured Bindings
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Clear and concise
|
||||||
|
if (auto [success, screen_pos] = try_project(world_pos); success) {
|
||||||
|
draw_at(screen_pos.x, screen_pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Good: Decompose results
|
||||||
|
auto [x, y, z] = position.as_tuple();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
### Document Assumptions
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Clear documentation
|
||||||
|
/**
|
||||||
|
* Projects world position to screen space.
|
||||||
|
*
|
||||||
|
* @param world_pos Position in world coordinates (meters)
|
||||||
|
* @return Screen position if visible, nullopt if behind camera or out of view
|
||||||
|
*
|
||||||
|
* @note Assumes camera.update() was called this frame
|
||||||
|
* @note Screen coordinates are in viewport space [0, width] x [0, height]
|
||||||
|
*/
|
||||||
|
std::optional<Vector2<float>> project(const Vector3<float>& world_pos);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Explain Non-Obvious Code
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Explain the math
|
||||||
|
// Use squared distance to avoid expensive sqrt
|
||||||
|
// max_range = 100.0 → max_range_sq = 10000.0
|
||||||
|
constexpr float max_range_sq = 100.0f * 100.0f;
|
||||||
|
if (dist_sq < max_range_sq) {
|
||||||
|
// Entity is in range
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explain engine-specific quirks
|
||||||
|
// Source Engine uses Z-up coordinates, but angles are in degrees
|
||||||
|
// Pitch: [-89, 89], Yaw: [-180, 180], Roll: [-180, 180]
|
||||||
|
ViewAngles angles{pitch, yaw, roll};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
### Add Debug Visualization
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#ifndef NDEBUG
|
||||||
|
void debug_draw_projection() {
|
||||||
|
// Draw camera frustum
|
||||||
|
draw_frustum(camera);
|
||||||
|
|
||||||
|
// Draw world axes
|
||||||
|
draw_line({0,0,0}, {100,0,0}, Color::Red); // X
|
||||||
|
draw_line({0,0,0}, {0,100,0}, Color::Green); // Y
|
||||||
|
draw_line({0,0,0}, {0,0,100}, Color::Blue); // Z
|
||||||
|
|
||||||
|
// Draw projected points
|
||||||
|
for (const auto& entity : entities) {
|
||||||
|
if (auto screen = camera.world_to_screen(entity.pos)) {
|
||||||
|
draw_cross(screen->x, screen->y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
### Log Important Values
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void debug_projection_failure(const Vector3<float>& pos) {
|
||||||
|
std::cerr << "Projection failed for position: "
|
||||||
|
<< pos.x << ", " << pos.y << ", " << pos.z << "\n";
|
||||||
|
|
||||||
|
auto view_matrix = camera.get_view_matrix();
|
||||||
|
std::cerr << "View matrix:\n";
|
||||||
|
// Print matrix...
|
||||||
|
|
||||||
|
std::cerr << "Camera position: "
|
||||||
|
<< camera.position().x << ", "
|
||||||
|
<< camera.position().y << ", "
|
||||||
|
<< camera.position().z << "\n";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use Debug Builds
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# CMakeLists.txt
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
target_compile_definitions(your_target PRIVATE
|
||||||
|
DEBUG_PROJECTION=1
|
||||||
|
VALIDATE_INPUTS=1
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#ifdef DEBUG_PROJECTION
|
||||||
|
std::cout << "Projecting: " << world_pos << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VALIDATE_INPUTS
|
||||||
|
assert(std::isfinite(world_pos.length()));
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Platform Considerations
|
||||||
|
|
||||||
|
### Cross-Platform Code
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Platform-agnostic
|
||||||
|
constexpr float PI = 3.14159265359f;
|
||||||
|
|
||||||
|
// Avoid: Platform-specific
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Windows-only code
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
### Handle Different Compilers
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Good: Compiler-agnostic
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
// MSVC-specific
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
// GCC/Clang-specific
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Use OMath's built-in compatibility
|
||||||
|
// It handles compiler differences automatically
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
**Key principles:**
|
||||||
|
1. **Safety first**: Always check optional/expected results
|
||||||
|
2. **Performance matters**: Use constexpr, avoid allocations, cache results
|
||||||
|
3. **Type safety**: Use strong types, match engine types
|
||||||
|
4. **Clear code**: Use aliases, document assumptions, explain non-obvious logic
|
||||||
|
5. **Test thoroughly**: Validate inputs, test edge cases, add assertions
|
||||||
|
6. **Debug effectively**: Add visualization, log values, use debug builds
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Troubleshooting Guide](troubleshooting.md)
|
||||||
|
- [FAQ](faq.md)
|
||||||
|
- [API Overview](api_overview.md)
|
||||||
|
- [Tutorials](tutorials.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 1 Nov 2025*
|
||||||
322
docs/collision/epa_algorithm.md
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
# `omath::collision::Epa` — Expanding Polytope Algorithm for penetration depth
|
||||||
|
|
||||||
|
> Header: `omath/collision/epa_algorithm.hpp`
|
||||||
|
> Namespace: `omath::collision`
|
||||||
|
> Depends on: `Simplex<VertexType>`, collider types with `find_abs_furthest_vertex` method
|
||||||
|
> Algorithm: **EPA** (Expanding Polytope Algorithm) for penetration depth and contact normal
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The **EPA (Expanding Polytope Algorithm)** calculates the **penetration depth** and **separation normal** between two intersecting convex shapes. It is typically used as a follow-up to the GJK algorithm after a collision has been detected.
|
||||||
|
|
||||||
|
EPA takes a 4-point simplex containing the origin (from GJK) and iteratively expands it to find the point on the Minkowski difference closest to the origin. This point gives both:
|
||||||
|
* **Depth**: minimum translation distance to separate the shapes
|
||||||
|
* **Normal**: direction of separation (pointing from shape B to shape A)
|
||||||
|
|
||||||
|
`Epa` is a template class working with any collider type that implements the support function interface.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `Epa::Result`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct Result final {
|
||||||
|
bool success{false}; // true if EPA converged
|
||||||
|
Vertex normal{}; // outward normal (from B to A)
|
||||||
|
float depth{0.0f}; // penetration depth
|
||||||
|
int iterations{0}; // number of iterations performed
|
||||||
|
int num_vertices{0}; // final polytope vertex count
|
||||||
|
int num_faces{0}; // final polytope face count
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fields
|
||||||
|
|
||||||
|
* `success` — `true` if EPA successfully computed depth and normal; `false` if it failed to converge
|
||||||
|
* `normal` — unit vector pointing from shape B toward shape A (separation direction)
|
||||||
|
* `depth` — minimum distance to move shape A along `normal` to separate the shapes
|
||||||
|
* `iterations` — actual iteration count (useful for performance tuning)
|
||||||
|
* `num_vertices`, `num_faces` — final polytope size (for diagnostics)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `Epa::Params`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct Params final {
|
||||||
|
int max_iterations{64}; // maximum iterations before giving up
|
||||||
|
float tolerance{1e-4f}; // absolute tolerance on distance growth
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fields
|
||||||
|
|
||||||
|
* `max_iterations` — safety limit to prevent infinite loops (default 64)
|
||||||
|
* `tolerance` — convergence threshold: stop when distance grows less than this (default 1e-4)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `Epa` Template Class
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class ColliderType>
|
||||||
|
class Epa final {
|
||||||
|
public:
|
||||||
|
using Vertex = typename ColliderType::VertexType;
|
||||||
|
static_assert(EpaVector<Vertex>, "VertexType must satisfy EpaVector concept");
|
||||||
|
|
||||||
|
// Solve for penetration depth and normal
|
||||||
|
[[nodiscard]]
|
||||||
|
static Result solve(
|
||||||
|
const ColliderType& a,
|
||||||
|
const ColliderType& b,
|
||||||
|
const Simplex<Vertex>& simplex,
|
||||||
|
const Params params = {}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Precondition
|
||||||
|
|
||||||
|
The `simplex` parameter must:
|
||||||
|
* Have exactly 4 points (`simplex.size() == 4`)
|
||||||
|
* Contain the origin (i.e., be a valid GJK result with `hit == true`)
|
||||||
|
|
||||||
|
Violating this precondition leads to undefined behavior.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Collider Requirements
|
||||||
|
|
||||||
|
Any type used as `ColliderType` must provide:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Type alias for vertex type (typically Vector3<float>)
|
||||||
|
using VertexType = /* ... */;
|
||||||
|
|
||||||
|
// Find the farthest point in world space along the given direction
|
||||||
|
[[nodiscard]]
|
||||||
|
VertexType find_abs_furthest_vertex(const VertexType& direction) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Algorithm Details
|
||||||
|
|
||||||
|
### Expanding Polytope
|
||||||
|
|
||||||
|
EPA maintains a convex polytope (polyhedron) in Minkowski difference space `A - B`. Starting from the 4-point tetrahedron (simplex from GJK), it repeatedly:
|
||||||
|
|
||||||
|
1. **Find closest face** to the origin
|
||||||
|
2. **Support query** in the direction of the face normal
|
||||||
|
3. **Expand polytope** by adding the new support point
|
||||||
|
4. **Update faces** to maintain convexity
|
||||||
|
|
||||||
|
The algorithm terminates when:
|
||||||
|
* **Convergence**: the distance from origin to polytope stops growing (within tolerance)
|
||||||
|
* **Max iterations**: safety limit reached
|
||||||
|
* **Failure cases**: degenerate polytope or numerical issues
|
||||||
|
|
||||||
|
### Minkowski Difference
|
||||||
|
|
||||||
|
Like GJK, EPA operates in Minkowski difference space where `point = a - b` for points in shapes A and B. The closest point on this polytope to the origin gives the minimum separation.
|
||||||
|
|
||||||
|
### Face Winding
|
||||||
|
|
||||||
|
Faces are stored with outward-pointing normals. The algorithm uses a priority queue to efficiently find the face closest to the origin.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Vertex Type Requirements
|
||||||
|
|
||||||
|
The `VertexType` must satisfy the `EpaVector` concept:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class V>
|
||||||
|
concept EpaVector = requires(const V& a, const V& b, float s) {
|
||||||
|
{ a - b } -> std::same_as<V>;
|
||||||
|
{ a.cross(b) } -> std::same_as<V>;
|
||||||
|
{ a.dot(b) } -> std::same_as<float>;
|
||||||
|
{ -a } -> std::same_as<V>;
|
||||||
|
{ a * s } -> std::same_as<V>;
|
||||||
|
{ a / s } -> std::same_as<V>;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
`omath::Vector3<float>` satisfies this concept.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Basic EPA Usage
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::collision;
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
// First, run GJK to detect collision
|
||||||
|
MeshCollider<Mesh> collider_a(mesh_a);
|
||||||
|
MeshCollider<Mesh> collider_b(mesh_b);
|
||||||
|
|
||||||
|
auto gjk_result = GjkAlgorithm<MeshCollider<Mesh>>::check_collision(
|
||||||
|
collider_a,
|
||||||
|
collider_b
|
||||||
|
);
|
||||||
|
|
||||||
|
if (gjk_result.hit) {
|
||||||
|
// Collision detected, use EPA to get penetration info
|
||||||
|
auto epa_result = Epa<MeshCollider<Mesh>>::solve(
|
||||||
|
collider_a,
|
||||||
|
collider_b,
|
||||||
|
gjk_result.simplex
|
||||||
|
);
|
||||||
|
|
||||||
|
if (epa_result.success) {
|
||||||
|
std::cout << "Penetration depth: " << epa_result.depth << "\n";
|
||||||
|
std::cout << "Separation normal: "
|
||||||
|
<< "(" << epa_result.normal.x << ", "
|
||||||
|
<< epa_result.normal.y << ", "
|
||||||
|
<< epa_result.normal.z << ")\n";
|
||||||
|
|
||||||
|
// Apply separation: move A away from B
|
||||||
|
Vector3<float> correction = epa_result.normal * epa_result.depth;
|
||||||
|
mesh_a.set_origin(mesh_a.get_origin() + correction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Parameters
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Use custom convergence settings
|
||||||
|
Epa<Collider>::Params params;
|
||||||
|
params.max_iterations = 128; // Allow more iterations for complex shapes
|
||||||
|
params.tolerance = 1e-5f; // Tighter tolerance for more accuracy
|
||||||
|
|
||||||
|
auto result = Epa<Collider>::solve(a, b, simplex, params);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Physics Integration
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void resolve_collision(PhysicsBody& body_a, PhysicsBody& body_b) {
|
||||||
|
auto gjk_result = GjkAlgorithm<Collider>::check_collision(
|
||||||
|
body_a.collider, body_b.collider
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!gjk_result.hit)
|
||||||
|
return; // No collision
|
||||||
|
|
||||||
|
auto epa_result = Epa<Collider>::solve(
|
||||||
|
body_a.collider,
|
||||||
|
body_b.collider,
|
||||||
|
gjk_result.simplex
|
||||||
|
);
|
||||||
|
|
||||||
|
if (epa_result.success) {
|
||||||
|
// Separate bodies
|
||||||
|
float mass_sum = body_a.mass + body_b.mass;
|
||||||
|
float ratio_a = body_b.mass / mass_sum;
|
||||||
|
float ratio_b = body_a.mass / mass_sum;
|
||||||
|
|
||||||
|
body_a.position += epa_result.normal * (epa_result.depth * ratio_a);
|
||||||
|
body_b.position -= epa_result.normal * (epa_result.depth * ratio_b);
|
||||||
|
|
||||||
|
// Apply collision response
|
||||||
|
apply_impulse(body_a, body_b, epa_result.normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Characteristics
|
||||||
|
|
||||||
|
* **Time complexity**: O(k × f) where k is iterations and f is faces per iteration (typically f grows slowly)
|
||||||
|
* **Space complexity**: O(n) where n is the number of polytope vertices (typically < 100)
|
||||||
|
* **Typical iterations**: 4-20 for most collisions
|
||||||
|
* **Worst case**: 64 iterations (configurable limit)
|
||||||
|
|
||||||
|
### Performance Tips
|
||||||
|
|
||||||
|
1. **Adjust max_iterations**: Balance accuracy vs. performance for your use case
|
||||||
|
2. **Tolerance tuning**: Larger tolerance = faster convergence but less accurate
|
||||||
|
3. **Shape complexity**: Simpler shapes (fewer faces) converge faster
|
||||||
|
4. **Deep penetrations**: Require more iterations; consider broad-phase separation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Limitations & Edge Cases
|
||||||
|
|
||||||
|
* **Requires valid simplex**: Must be called with a 4-point simplex containing the origin (from successful GJK)
|
||||||
|
* **Convex shapes only**: Like GJK, EPA only works with convex colliders
|
||||||
|
* **Convergence failure**: Can fail to converge for degenerate or very thin shapes (check `result.success`)
|
||||||
|
* **Numerical precision**: Extreme scale differences or very small shapes may cause issues
|
||||||
|
* **Deep penetration**: Very deep intersections may require many iterations or fail to converge
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto result = Epa<Collider>::solve(a, b, simplex);
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
// EPA failed to converge
|
||||||
|
// Fallback options:
|
||||||
|
// 1. Use a default separation (e.g., axis between centers)
|
||||||
|
// 2. Increase max_iterations and retry
|
||||||
|
// 3. Log a warning and skip this collision
|
||||||
|
std::cerr << "EPA failed after " << result.iterations << " iterations\n";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Theory & Background
|
||||||
|
|
||||||
|
### Why EPA after GJK?
|
||||||
|
|
||||||
|
GJK determines **if** shapes intersect but doesn't compute penetration depth. EPA extends GJK's final simplex to find the exact depth and normal needed for:
|
||||||
|
* **Collision response** — separating objects realistically
|
||||||
|
* **Contact manifolds** — generating contact points for physics
|
||||||
|
* **Constraint solving** — iterative physics solvers
|
||||||
|
|
||||||
|
### Comparison with SAT
|
||||||
|
|
||||||
|
| Feature | EPA | SAT (Separating Axis Theorem) |
|
||||||
|
|---------|-----|-------------------------------|
|
||||||
|
| Works with | Any convex shape | Polytopes (faces/edges) |
|
||||||
|
| Penetration depth | Yes | Yes |
|
||||||
|
| Complexity | Iterative | Per-axis projection |
|
||||||
|
| Best for | General convex | Boxes, prisms |
|
||||||
|
| Typical speed | Moderate | Fast (few axes) |
|
||||||
|
|
||||||
|
EPA is more general; SAT is faster for axis-aligned shapes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
The EPA implementation in OMath:
|
||||||
|
* Uses a **priority queue** to efficiently find the closest face
|
||||||
|
* Maintains face winding for consistent normals
|
||||||
|
* Handles **edge cases**: degenerate faces, numerical instability
|
||||||
|
* Prevents infinite loops with iteration limits
|
||||||
|
* Returns detailed diagnostics (iteration count, polytope size)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [GJK Algorithm Documentation](gjk_algorithm.md) - Collision detection (required before EPA)
|
||||||
|
- [Simplex Documentation](simplex.md) - Input simplex structure
|
||||||
|
- [MeshCollider Documentation](mesh_collider.md) - Mesh-based collider
|
||||||
|
- [Mesh Documentation](../3d_primitives/mesh.md) - Mesh primitive
|
||||||
|
- [Tutorials - Collision Detection](../tutorials.md#tutorial-4-collision-detection) - Complete collision tutorial
|
||||||
|
- [API Overview](../api_overview.md) - High-level API reference
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
216
docs/collision/gjk_algorithm.md
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
# `omath::collision::GjkAlgorithm` — Gilbert-Johnson-Keerthi collision detection
|
||||||
|
|
||||||
|
> Header: `omath/collision/gjk_algorithm.hpp`
|
||||||
|
> Namespace: `omath::collision`
|
||||||
|
> Depends on: `Simplex<VertexType>`, collider types with `find_abs_furthest_vertex` method
|
||||||
|
> Algorithm: **GJK** (Gilbert-Johnson-Keerthi) for convex shape collision detection
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The **GJK algorithm** determines whether two convex shapes intersect by iteratively constructing a simplex in Minkowski difference space. The algorithm is widely used in physics engines and collision detection systems due to its efficiency and robustness.
|
||||||
|
|
||||||
|
`GjkAlgorithm` is a template class that works with any collider type implementing the required support function interface:
|
||||||
|
|
||||||
|
* `find_abs_furthest_vertex(direction)` — returns the farthest point in the collider along the given direction.
|
||||||
|
|
||||||
|
The algorithm returns a `GjkHitInfo` containing:
|
||||||
|
* `hit` — boolean indicating whether the shapes intersect
|
||||||
|
* `simplex` — a 4-point simplex containing the origin (valid only when `hit == true`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `GjkHitInfo`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class VertexType>
|
||||||
|
struct GjkHitInfo final {
|
||||||
|
bool hit{false}; // true if collision detected
|
||||||
|
Simplex<VertexType> simplex; // 4-point simplex (valid only if hit == true)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The `simplex` field is only meaningful when `hit == true` and contains 4 points. This simplex can be passed to the EPA algorithm for penetration depth calculation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `GjkAlgorithm`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class ColliderType>
|
||||||
|
class GjkAlgorithm final {
|
||||||
|
using VertexType = typename ColliderType::VertexType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Find support vertex in Minkowski difference
|
||||||
|
[[nodiscard]]
|
||||||
|
static VertexType find_support_vertex(
|
||||||
|
const ColliderType& collider_a,
|
||||||
|
const ColliderType& collider_b,
|
||||||
|
const VertexType& direction
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if two convex shapes intersect
|
||||||
|
[[nodiscard]]
|
||||||
|
static GjkHitInfo<VertexType> check_collision(
|
||||||
|
const ColliderType& collider_a,
|
||||||
|
const ColliderType& collider_b
|
||||||
|
);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Collider Requirements
|
||||||
|
|
||||||
|
Any type used as `ColliderType` must provide:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Type alias for vertex type (typically Vector3<float>)
|
||||||
|
using VertexType = /* ... */;
|
||||||
|
|
||||||
|
// Find the farthest point in world space along the given direction
|
||||||
|
[[nodiscard]]
|
||||||
|
VertexType find_abs_furthest_vertex(const VertexType& direction) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
Common collider types:
|
||||||
|
* `MeshCollider<MeshType>` — for arbitrary triangle meshes
|
||||||
|
* Custom colliders for spheres, boxes, capsules, etc.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Algorithm Details
|
||||||
|
|
||||||
|
### Minkowski Difference
|
||||||
|
|
||||||
|
GJK operates in the **Minkowski difference** space `A - B`, where a point in this space represents the difference between points in shapes A and B. The shapes intersect if and only if the origin lies within this Minkowski difference.
|
||||||
|
|
||||||
|
### Support Function
|
||||||
|
|
||||||
|
The support function finds the point in the Minkowski difference farthest along a given direction:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
support(A, B, dir) = A.furthest(dir) - B.furthest(-dir)
|
||||||
|
```
|
||||||
|
|
||||||
|
This is computed by `find_support_vertex`.
|
||||||
|
|
||||||
|
### Simplex Iteration
|
||||||
|
|
||||||
|
The algorithm builds a simplex incrementally:
|
||||||
|
1. Start with an initial direction (typically vector between shape centers)
|
||||||
|
2. Add support vertices in directions that move the simplex toward the origin
|
||||||
|
3. Simplify the simplex to keep only points closest to the origin
|
||||||
|
4. Repeat until either:
|
||||||
|
* Origin is contained (collision detected, returns 4-point simplex)
|
||||||
|
* No progress can be made (no collision)
|
||||||
|
|
||||||
|
Maximum 64 iterations are performed to prevent infinite loops in edge cases.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Basic Collision Check
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::collision;
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
// Create mesh colliders
|
||||||
|
Mesh mesh_a = /* ... */;
|
||||||
|
Mesh mesh_b = /* ... */;
|
||||||
|
|
||||||
|
MeshCollider collider_a(mesh_a);
|
||||||
|
MeshCollider collider_b(mesh_b);
|
||||||
|
|
||||||
|
// Check for collision
|
||||||
|
auto result = GjkAlgorithm<MeshCollider<Mesh>>::check_collision(
|
||||||
|
collider_a,
|
||||||
|
collider_b
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.hit) {
|
||||||
|
std::cout << "Collision detected!\n";
|
||||||
|
// Can pass result.simplex to EPA for penetration depth
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Combined with EPA
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto gjk_result = GjkAlgorithm<Collider>::check_collision(a, b);
|
||||||
|
|
||||||
|
if (gjk_result.hit) {
|
||||||
|
// Get penetration depth and normal using EPA
|
||||||
|
auto epa_result = Epa<Collider>::solve(
|
||||||
|
a, b, gjk_result.simplex
|
||||||
|
);
|
||||||
|
|
||||||
|
if (epa_result.success) {
|
||||||
|
std::cout << "Penetration depth: " << epa_result.depth << "\n";
|
||||||
|
std::cout << "Separation normal: " << epa_result.normal << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Characteristics
|
||||||
|
|
||||||
|
* **Time complexity**: O(k) where k is the number of iterations (typically < 20 for most cases)
|
||||||
|
* **Space complexity**: O(1) — only stores a 4-point simplex
|
||||||
|
* **Best case**: 4-8 iterations for well-separated objects
|
||||||
|
* **Worst case**: 64 iterations (hard limit)
|
||||||
|
* **Cache efficient**: operates on small fixed-size data structures
|
||||||
|
|
||||||
|
### Optimization Tips
|
||||||
|
|
||||||
|
1. **Initial direction**: Use vector between shape centers for faster convergence
|
||||||
|
2. **Early exit**: GJK quickly rejects non-intersecting shapes
|
||||||
|
3. **Warm starting**: Reuse previous simplex for continuous collision detection
|
||||||
|
4. **Broad phase**: Use spatial partitioning before GJK (AABB trees, grids)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Limitations & Edge Cases
|
||||||
|
|
||||||
|
* **Convex shapes only**: GJK only works with convex colliders. For concave shapes, decompose into convex parts or use a mesh collider wrapper.
|
||||||
|
* **Degenerate simplices**: The algorithm handles degenerate cases, but numerical precision can cause issues with very thin or flat shapes.
|
||||||
|
* **Iteration limit**: Hard limit of 64 iterations prevents infinite loops but may miss collisions in extreme cases.
|
||||||
|
* **Zero-length directions**: The simplex update logic guards against zero-length vectors, returning safe fallbacks.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Vertex Type Requirements
|
||||||
|
|
||||||
|
The `VertexType` must satisfy the `GjkVector` concept (defined in `simplex.hpp`):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class V>
|
||||||
|
concept GjkVector = requires(const V& a, const V& b) {
|
||||||
|
{ -a } -> std::same_as<V>;
|
||||||
|
{ a - b } -> std::same_as<V>;
|
||||||
|
{ a.cross(b) } -> std::same_as<V>;
|
||||||
|
{ a.point_to_same_direction(b) } -> std::same_as<bool>;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
`omath::Vector3<float>` satisfies this concept.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [EPA Algorithm Documentation](epa_algorithm.md) - Penetration depth calculation
|
||||||
|
- [Simplex Documentation](simplex.md) - Simplex data structure
|
||||||
|
- [MeshCollider Documentation](mesh_collider.md) - Mesh-based collider
|
||||||
|
- [Mesh Documentation](../3d_primitives/mesh.md) - Mesh primitive
|
||||||
|
- [LineTracer Documentation](line_tracer.md) - Ray-triangle intersection
|
||||||
|
- [Tutorials - Collision Detection](../tutorials.md#tutorial-4-collision-detection) - Complete collision tutorial
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
181
docs/collision/line_tracer.md
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
# `omath::collision::Ray` & `LineTracer` — Ray–Triangle intersection (Möller–Trumbore)
|
||||||
|
|
||||||
|
> Headers: your project’s `ray.hpp` (includes `omath/linear_algebra/triangle.hpp`, `omath/linear_algebra/vector3.hpp`)
|
||||||
|
> Namespace: `omath::collision`
|
||||||
|
> Depends on: `omath::Vector3<float>`, `omath::Triangle<Vector3<float>>`
|
||||||
|
> Algorithm: **Möller–Trumbore** ray–triangle intersection (no allocation)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
These types provide a minimal, fast path to test and compute intersections between a **ray or line segment** and a **single triangle**:
|
||||||
|
|
||||||
|
* `Ray` — start/end points plus a flag to treat the ray as **infinite** (half-line) or a **finite segment**.
|
||||||
|
* `LineTracer` — static helpers:
|
||||||
|
|
||||||
|
* `can_trace_line(ray, triangle)` → `true` if they intersect.
|
||||||
|
* `get_ray_hit_point(ray, triangle)` → the hit point (precondition: intersection exists).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `Ray`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Ray {
|
||||||
|
public:
|
||||||
|
omath::Vector3<float> start; // ray origin
|
||||||
|
omath::Vector3<float> end; // end point (for finite segment) or a point along the direction
|
||||||
|
bool infinite_length = false;
|
||||||
|
|
||||||
|
[[nodiscard]] omath::Vector3<float> direction_vector() const noexcept;
|
||||||
|
[[nodiscard]] omath::Vector3<float> direction_vector_normalized() const noexcept;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Semantics
|
||||||
|
|
||||||
|
* **Direction**: `direction_vector() == end - start`.
|
||||||
|
The normalized variant returns a unit vector (or `{0,0,0}` if the direction length is zero).
|
||||||
|
* **Extent**:
|
||||||
|
|
||||||
|
* `infinite_length == true` → treat as a **semi-infinite ray** from `start` along `direction`.
|
||||||
|
* `infinite_length == false` → treat as a **closed segment** from `start` to `end`.
|
||||||
|
|
||||||
|
> Tip: For an infinite ray that points along some vector `d`, set `end = start + d`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `LineTracer`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class LineTracer {
|
||||||
|
public:
|
||||||
|
LineTracer() = delete;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static bool can_trace_line(
|
||||||
|
const Ray& ray,
|
||||||
|
const omath::Triangle<omath::Vector3<float>>& triangle
|
||||||
|
) noexcept;
|
||||||
|
|
||||||
|
// Möller–Trumbore intersection
|
||||||
|
[[nodiscard]]
|
||||||
|
static omath::Vector3<float> get_ray_hit_point(
|
||||||
|
const Ray& ray,
|
||||||
|
const omath::Triangle<omath::Vector3<float>>& triangle
|
||||||
|
) noexcept;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Behavior & contract
|
||||||
|
|
||||||
|
* **Intersection test**: `can_trace_line` returns `true` iff the ray/segment intersects the triangle (within the ray’s extent).
|
||||||
|
* **Hit point**: `get_ray_hit_point` **assumes** there is an intersection.
|
||||||
|
Call **only after** `can_trace_line(...) == true`. Otherwise the result is unspecified.
|
||||||
|
* **Triangle winding**: Standard Möller–Trumbore works with either winding; no backface culling is implied here.
|
||||||
|
* **Degenerate inputs**: A zero-length ray or degenerate triangle yields **no hit** under typical Möller–Trumbore tolerances.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick examples
|
||||||
|
|
||||||
|
### 1) Segment vs triangle
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using omath::Vector3;
|
||||||
|
using omath::Triangle;
|
||||||
|
using omath::collision::Ray;
|
||||||
|
using omath::collision::LineTracer;
|
||||||
|
|
||||||
|
Triangle<Vector3<float>> tri(
|
||||||
|
Vector3<float>{0, 0, 0},
|
||||||
|
Vector3<float>{1, 0, 0},
|
||||||
|
Vector3<float>{0, 1, 0}
|
||||||
|
);
|
||||||
|
|
||||||
|
Ray seg;
|
||||||
|
seg.start = {0.25f, 0.25f, 1.0f};
|
||||||
|
seg.end = {0.25f, 0.25f,-1.0f};
|
||||||
|
seg.infinite_length = false; // finite segment
|
||||||
|
|
||||||
|
if (LineTracer::can_trace_line(seg, tri)) {
|
||||||
|
Vector3<float> hit = LineTracer::get_ray_hit_point(seg, tri);
|
||||||
|
// use hit
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2) Infinite ray
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Ray ray;
|
||||||
|
ray.start = {0.5f, 0.5f, 1.0f};
|
||||||
|
ray.end = ray.start + Vector3<float>{0, 0, -1}; // direction only
|
||||||
|
ray.infinite_length = true;
|
||||||
|
|
||||||
|
bool hit = LineTracer::can_trace_line(ray, tri);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & edge cases
|
||||||
|
|
||||||
|
* **Normalization**: `direction_vector_normalized()` returns `{0,0,0}` for a zero-length direction (safe, but unusable for tracing).
|
||||||
|
* **Precision**: The underlying algorithm uses EPS thresholds to reject nearly parallel cases; results near edges can be sensitive to floating-point error. If you need robust edge inclusion/exclusion, document and enforce a policy (e.g., inclusive barycentric range with small epsilon).
|
||||||
|
* **Hit location**: The point returned by `get_ray_hit_point` lies **on the triangle plane** and within its area by construction (when `can_trace_line` is `true`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API summary
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::collision {
|
||||||
|
|
||||||
|
class Ray {
|
||||||
|
public:
|
||||||
|
Vector3<float> start, end;
|
||||||
|
bool infinite_length = false;
|
||||||
|
|
||||||
|
[[nodiscard]] Vector3<float> direction_vector() const noexcept;
|
||||||
|
[[nodiscard]] Vector3<float> direction_vector_normalized() const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LineTracer {
|
||||||
|
public:
|
||||||
|
LineTracer() = delete;
|
||||||
|
|
||||||
|
[[nodiscard]] static bool can_trace_line(
|
||||||
|
const Ray&,
|
||||||
|
const omath::Triangle<omath::Vector3<float>>&
|
||||||
|
) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] static Vector3<float> get_ray_hit_point(
|
||||||
|
const Ray&,
|
||||||
|
const omath::Triangle<omath::Vector3<float>>&
|
||||||
|
) noexcept; // precondition: can_trace_line(...) == true
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::collision
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation hints (if you extend it)
|
||||||
|
|
||||||
|
* Expose a variant that returns **barycentric coordinates** `(u, v, w)` alongside the hit point to support texture lookup or edge tests.
|
||||||
|
* Provide an overload returning `std::optional<Vector3<float>>` (or `expected`) for safer one-shot queries without a separate test call.
|
||||||
|
* If you need backface culling, add a flag or dedicated function (reject hits where the signed distance is negative with respect to triangle normal).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Plane Documentation](../3d_primitives/plane.md) - Ray-plane intersection
|
||||||
|
- [Box Documentation](../3d_primitives/box.md) - AABB collision detection
|
||||||
|
- [Triangle Documentation](../linear_algebra/triangle.md) - Triangle primitives
|
||||||
|
- [Tutorials - Collision Detection](../tutorials.md#tutorial-4-collision-detection) - Complete collision tutorial
|
||||||
|
- [Getting Started Guide](../getting_started.md) - Quick start with OMath
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 1 Nov 2025*
|
||||||
371
docs/collision/mesh_collider.md
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
# `omath::collision::MeshCollider` — Convex hull collider for meshes
|
||||||
|
|
||||||
|
> Header: `omath/collision/mesh_collider.hpp`
|
||||||
|
> Namespace: `omath::collision`
|
||||||
|
> Depends on: `omath::primitives::Mesh`, `omath::Vector3<T>`
|
||||||
|
> Purpose: wrap a mesh to provide collision detection support for GJK/EPA
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
`MeshCollider` wraps a `Mesh` object to provide the **support function** interface required by the GJK and EPA collision detection algorithms. The support function finds the vertex of the mesh farthest along a given direction, which is essential for constructing Minkowski difference simplices.
|
||||||
|
|
||||||
|
**Important**: `MeshCollider` assumes the mesh represents a **convex hull**. For non-convex shapes, you must either:
|
||||||
|
* Decompose into convex parts
|
||||||
|
* Use the convex hull of the mesh
|
||||||
|
* Use a different collision detection algorithm
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template Declaration
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class MeshType>
|
||||||
|
class MeshCollider;
|
||||||
|
```
|
||||||
|
|
||||||
|
### MeshType Requirements
|
||||||
|
|
||||||
|
The `MeshType` must be an instantiation of `omath::primitives::Mesh` or provide:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct MeshType {
|
||||||
|
using NumericType = /* float, double, etc. */;
|
||||||
|
|
||||||
|
std::vector<Vector3<NumericType>> m_vertex_buffer;
|
||||||
|
|
||||||
|
// Transform vertex from local to world space
|
||||||
|
Vector3<NumericType> vertex_to_world_space(const Vector3<NumericType>&) const;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Common types:
|
||||||
|
* `omath::source_engine::Mesh`
|
||||||
|
* `omath::unity_engine::Mesh`
|
||||||
|
* `omath::unreal_engine::Mesh`
|
||||||
|
* `omath::frostbite_engine::Mesh`
|
||||||
|
* `omath::iw_engine::Mesh`
|
||||||
|
* `omath::opengl_engine::Mesh`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type Aliases
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using NumericType = typename MeshType::NumericType;
|
||||||
|
using VertexType = Vector3<NumericType>;
|
||||||
|
```
|
||||||
|
|
||||||
|
* `NumericType` — scalar type (typically `float`)
|
||||||
|
* `VertexType` — 3D vector type for vertices
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constructor
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
explicit MeshCollider(MeshType mesh);
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a collider from a mesh. The mesh is **moved** into the collider, so pass by value:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
omath::source_engine::Mesh my_mesh = /* ... */;
|
||||||
|
MeshCollider collider(std::move(my_mesh));
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
### `find_furthest_vertex`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]]
|
||||||
|
const VertexType& find_furthest_vertex(const VertexType& direction) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
Finds the vertex in the mesh's **local space** that has the maximum dot product with `direction`.
|
||||||
|
|
||||||
|
**Algorithm**: Linear search through all vertices (O(n) where n is vertex count).
|
||||||
|
|
||||||
|
**Returns**: Const reference to the vertex in `m_vertex_buffer`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `find_abs_furthest_vertex`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]]
|
||||||
|
VertexType find_abs_furthest_vertex(const VertexType& direction) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
Finds the vertex farthest along `direction` and transforms it to **world space**. This is the primary method used by GJK/EPA.
|
||||||
|
|
||||||
|
**Steps**:
|
||||||
|
1. Find furthest vertex in local space using `find_furthest_vertex`
|
||||||
|
2. Transform to world space using `mesh.vertex_to_world_space()`
|
||||||
|
|
||||||
|
**Returns**: Vertex position in world coordinates.
|
||||||
|
|
||||||
|
**Usage in GJK**:
|
||||||
|
```cpp
|
||||||
|
// GJK support function for Minkowski difference
|
||||||
|
VertexType support = collider_a.find_abs_furthest_vertex(direction)
|
||||||
|
- collider_b.find_abs_furthest_vertex(-direction);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Basic Collision Detection
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::collision;
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
// Create meshes with vertex data
|
||||||
|
std::vector<Vector3<float>> vbo_a = {
|
||||||
|
{-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, 1, -1},
|
||||||
|
{-1, -1, 1}, {1, -1, 1}, {1, 1, 1}, {-1, 1, 1}
|
||||||
|
};
|
||||||
|
std::vector<Vector3<std::size_t>> vao_a = /* face indices */;
|
||||||
|
|
||||||
|
Mesh mesh_a(vbo_a, vao_a);
|
||||||
|
mesh_a.set_origin({0, 0, 0});
|
||||||
|
|
||||||
|
Mesh mesh_b(vbo_b, vao_b);
|
||||||
|
mesh_b.set_origin({5, 0, 0}); // Positioned away from mesh_a
|
||||||
|
|
||||||
|
// Wrap in colliders
|
||||||
|
MeshCollider<Mesh> collider_a(std::move(mesh_a));
|
||||||
|
MeshCollider<Mesh> collider_b(std::move(mesh_b));
|
||||||
|
|
||||||
|
// Run GJK
|
||||||
|
auto result = GjkAlgorithm<MeshCollider<Mesh>>::check_collision(
|
||||||
|
collider_a, collider_b
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.hit) {
|
||||||
|
std::cout << "Collision detected!\n";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### With EPA for Penetration Depth
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto gjk_result = GjkAlgorithm<MeshCollider<Mesh>>::check_collision(
|
||||||
|
collider_a, collider_b
|
||||||
|
);
|
||||||
|
|
||||||
|
if (gjk_result.hit) {
|
||||||
|
auto epa_result = Epa<MeshCollider<Mesh>>::solve(
|
||||||
|
collider_a, collider_b, gjk_result.simplex
|
||||||
|
);
|
||||||
|
|
||||||
|
if (epa_result.success) {
|
||||||
|
std::cout << "Penetration: " << epa_result.depth << " units\n";
|
||||||
|
std::cout << "Normal: " << epa_result.normal << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Mesh Creation
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Create a simple box mesh
|
||||||
|
std::vector<Vector3<float>> box_vertices = {
|
||||||
|
{-0.5f, -0.5f, -0.5f}, { 0.5f, -0.5f, -0.5f},
|
||||||
|
{ 0.5f, 0.5f, -0.5f}, {-0.5f, 0.5f, -0.5f},
|
||||||
|
{-0.5f, -0.5f, 0.5f}, { 0.5f, -0.5f, 0.5f},
|
||||||
|
{ 0.5f, 0.5f, 0.5f}, {-0.5f, 0.5f, 0.5f}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Vector3<std::size_t>> box_indices = {
|
||||||
|
{0, 1, 2}, {0, 2, 3}, // Front face
|
||||||
|
{4, 6, 5}, {4, 7, 6}, // Back face
|
||||||
|
{0, 4, 5}, {0, 5, 1}, // Bottom face
|
||||||
|
{2, 6, 7}, {2, 7, 3}, // Top face
|
||||||
|
{0, 3, 7}, {0, 7, 4}, // Left face
|
||||||
|
{1, 5, 6}, {1, 6, 2} // Right face
|
||||||
|
};
|
||||||
|
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
Mesh box_mesh(box_vertices, box_indices);
|
||||||
|
box_mesh.set_origin({10, 0, 0});
|
||||||
|
box_mesh.set_scale({2, 2, 2});
|
||||||
|
|
||||||
|
MeshCollider<Mesh> box_collider(std::move(box_mesh));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Oriented Collision
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Create rotated mesh
|
||||||
|
Mesh mesh(vertices, indices);
|
||||||
|
mesh.set_origin({5, 5, 5});
|
||||||
|
mesh.set_scale({1, 1, 1});
|
||||||
|
|
||||||
|
// Set rotation (engine-specific angles)
|
||||||
|
ViewAngles rotation;
|
||||||
|
rotation.pitch = PitchAngle::from_degrees(45.0f);
|
||||||
|
rotation.yaw = YawAngle::from_degrees(30.0f);
|
||||||
|
mesh.set_rotation(rotation);
|
||||||
|
|
||||||
|
// Collider automatically handles transformation
|
||||||
|
MeshCollider<Mesh> collider(std::move(mesh));
|
||||||
|
|
||||||
|
// Support function returns world-space vertices
|
||||||
|
auto support = collider.find_abs_furthest_vertex({0, 1, 0});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
### Linear Search
|
||||||
|
|
||||||
|
`find_furthest_vertex` performs a **linear search** through all vertices:
|
||||||
|
* **Time complexity**: O(n) per support query
|
||||||
|
* **GJK iterations**: ~10-20 support queries per collision test
|
||||||
|
* **Total cost**: O(k × n) where k is GJK iterations
|
||||||
|
|
||||||
|
For meshes with many vertices (>1000), consider:
|
||||||
|
* Using simpler proxy geometry (bounding box, convex hull with fewer vertices)
|
||||||
|
* Pre-computing hierarchical structures
|
||||||
|
* Using specialized collision shapes when possible
|
||||||
|
|
||||||
|
### Caching Opportunities
|
||||||
|
|
||||||
|
The implementation uses `std::ranges::max_element`, which is cache-friendly for contiguous vertex buffers. For optimal performance:
|
||||||
|
* Store vertices contiguously in memory
|
||||||
|
* Avoid pointer-based or scattered vertex storage
|
||||||
|
* Consider SoA (Structure of Arrays) layout for SIMD optimization
|
||||||
|
|
||||||
|
### World Space Transformation
|
||||||
|
|
||||||
|
The `vertex_to_world_space` call involves matrix multiplication:
|
||||||
|
* **Cost**: ~15-20 floating-point operations per vertex
|
||||||
|
* **Optimization**: The mesh caches its transformation matrix
|
||||||
|
* **Update cost**: Only recomputed when origin/rotation/scale changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Limitations & Edge Cases
|
||||||
|
|
||||||
|
### Convex Hull Requirement
|
||||||
|
|
||||||
|
**Critical**: GJK/EPA only work with **convex shapes**. If your mesh is concave:
|
||||||
|
|
||||||
|
#### Option 1: Convex Decomposition
|
||||||
|
```cpp
|
||||||
|
// Decompose concave mesh into convex parts
|
||||||
|
std::vector<Mesh> convex_parts = decompose_mesh(concave_mesh);
|
||||||
|
|
||||||
|
for (const auto& part : convex_parts) {
|
||||||
|
MeshCollider collider(part);
|
||||||
|
// Test each part separately
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Option 2: Use Convex Hull
|
||||||
|
```cpp
|
||||||
|
// Compute convex hull of vertices
|
||||||
|
auto hull_vertices = compute_convex_hull(mesh.m_vertex_buffer);
|
||||||
|
Mesh hull_mesh(hull_vertices, hull_indices);
|
||||||
|
MeshCollider collider(std::move(hull_mesh));
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Option 3: Different Algorithm
|
||||||
|
Use triangle-based collision (e.g., LineTracer) for true concave support.
|
||||||
|
|
||||||
|
### Empty Mesh
|
||||||
|
|
||||||
|
Behavior is undefined if `m_vertex_buffer` is empty. Always ensure:
|
||||||
|
```cpp
|
||||||
|
assert(!mesh.m_vertex_buffer.empty());
|
||||||
|
MeshCollider collider(std::move(mesh));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Degenerate Meshes
|
||||||
|
|
||||||
|
* **Single vertex**: Treated as a point (degenerates to sphere collision)
|
||||||
|
* **Two vertices**: Line segment (may cause GJK issues)
|
||||||
|
* **Coplanar vertices**: Flat mesh; EPA may have convergence issues
|
||||||
|
|
||||||
|
**Recommendation**: Use at least 4 non-coplanar vertices for robustness.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate Systems
|
||||||
|
|
||||||
|
`MeshCollider` supports different engine coordinate systems through the `MeshTrait`:
|
||||||
|
|
||||||
|
| Engine | Up Axis | Handedness | Rotation Order |
|
||||||
|
|--------|---------|------------|----------------|
|
||||||
|
| Source Engine | Z | Right-handed | Pitch/Yaw/Roll |
|
||||||
|
| Unity | Y | Left-handed | Pitch/Yaw/Roll |
|
||||||
|
| Unreal | Z | Left-handed | Roll/Pitch/Yaw |
|
||||||
|
| Frostbite | Y | Right-handed | Pitch/Yaw/Roll |
|
||||||
|
| IW Engine | Z | Right-handed | Pitch/Yaw/Roll |
|
||||||
|
| OpenGL | Y | Right-handed | Pitch/Yaw/Roll |
|
||||||
|
|
||||||
|
The `vertex_to_world_space` method handles these differences transparently.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Advanced Usage
|
||||||
|
|
||||||
|
### Custom Support Function
|
||||||
|
|
||||||
|
For specialized collision shapes, implement a custom collider:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class SphereCollider {
|
||||||
|
public:
|
||||||
|
using VertexType = Vector3<float>;
|
||||||
|
|
||||||
|
Vector3<float> center;
|
||||||
|
float radius;
|
||||||
|
|
||||||
|
VertexType find_abs_furthest_vertex(const VertexType& direction) const {
|
||||||
|
auto normalized = direction.normalized();
|
||||||
|
return center + normalized * radius;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use with GJK/EPA
|
||||||
|
auto result = GjkAlgorithm<SphereCollider>::check_collision(sphere_a, sphere_b);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debugging Support Queries
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class DebugMeshCollider : public MeshCollider<Mesh> {
|
||||||
|
public:
|
||||||
|
using MeshCollider::MeshCollider;
|
||||||
|
|
||||||
|
VertexType find_abs_furthest_vertex(const VertexType& direction) const {
|
||||||
|
auto result = MeshCollider::find_abs_furthest_vertex(direction);
|
||||||
|
std::cout << "Support query: direction=" << direction
|
||||||
|
<< " -> vertex=" << result << "\n";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [GJK Algorithm Documentation](gjk_algorithm.md) - Uses `MeshCollider` for collision detection
|
||||||
|
- [EPA Algorithm Documentation](epa_algorithm.md) - Uses `MeshCollider` for penetration depth
|
||||||
|
- [Simplex Documentation](simplex.md) - Data structure used by GJK
|
||||||
|
- [Mesh Documentation](../3d_primitives/mesh.md) - Underlying mesh primitive
|
||||||
|
- [Tutorials - Collision Detection](../tutorials.md#tutorial-4-collision-detection) - Complete collision tutorial
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
327
docs/collision/simplex.md
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
# `omath::collision::Simplex` — Fixed-capacity simplex for GJK/EPA
|
||||||
|
|
||||||
|
> Header: `omath/collision/simplex.hpp`
|
||||||
|
> Namespace: `omath::collision`
|
||||||
|
> Depends on: `Vector3<float>` (or any type satisfying `GjkVector` concept)
|
||||||
|
> Purpose: store and manipulate simplices in GJK and EPA algorithms
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
`Simplex` is a lightweight container for up to 4 points, used internally by the GJK and EPA collision detection algorithms. A simplex in this context is a geometric shape defined by 1 to 4 vertices:
|
||||||
|
|
||||||
|
* **1 point** — a single vertex
|
||||||
|
* **2 points** — a line segment
|
||||||
|
* **3 points** — a triangle
|
||||||
|
* **4 points** — a tetrahedron
|
||||||
|
|
||||||
|
The GJK algorithm builds simplices incrementally to detect collisions, and EPA extends a 4-point simplex to compute penetration depth.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template & Concepts
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<GjkVector VectorType = Vector3<float>>
|
||||||
|
class Simplex final;
|
||||||
|
```
|
||||||
|
|
||||||
|
### `GjkVector` Concept
|
||||||
|
|
||||||
|
The vertex type must satisfy:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class V>
|
||||||
|
concept GjkVector = requires(const V& a, const V& b) {
|
||||||
|
{ -a } -> std::same_as<V>;
|
||||||
|
{ a - b } -> std::same_as<V>;
|
||||||
|
{ a.cross(b) } -> std::same_as<V>;
|
||||||
|
{ a.point_to_same_direction(b) } -> std::same_as<bool>;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
`omath::Vector3<float>` satisfies this concept and is the default.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constructors & Assignment
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Simplex() = default;
|
||||||
|
|
||||||
|
constexpr Simplex& operator=(std::initializer_list<VectorType> list) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Initialization
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Empty simplex
|
||||||
|
Simplex<Vector3<float>> s;
|
||||||
|
|
||||||
|
// Initialize with points
|
||||||
|
Simplex<Vector3<float>> s2;
|
||||||
|
s2 = {v1, v2, v3}; // 3-point simplex (triangle)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Constraint**: Maximum 4 points. Passing more triggers an assertion in debug builds.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core Methods
|
||||||
|
|
||||||
|
### Adding Points
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr void push_front(const VectorType& p) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
Inserts a point at the **front** (index 0), shifting existing points back. If the simplex is already at capacity (4 points), the last point is discarded.
|
||||||
|
|
||||||
|
**Usage pattern in GJK**:
|
||||||
|
```cpp
|
||||||
|
simplex.push_front(new_support_point);
|
||||||
|
// Now simplex[0] is the newest point
|
||||||
|
```
|
||||||
|
|
||||||
|
### Size & Capacity
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]] constexpr std::size_t size() const noexcept;
|
||||||
|
[[nodiscard]] static constexpr std::size_t capacity = 4;
|
||||||
|
```
|
||||||
|
|
||||||
|
* `size()` — current number of points (0-4)
|
||||||
|
* `capacity` — maximum points (always 4)
|
||||||
|
|
||||||
|
### Element Access
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]] constexpr VectorType& operator[](std::size_t index) noexcept;
|
||||||
|
[[nodiscard]] constexpr const VectorType& operator[](std::size_t index) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
Access points by index. **No bounds checking** — index must be `< size()`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if (simplex.size() >= 2) {
|
||||||
|
auto edge = simplex[1] - simplex[0];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Iterators
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]] constexpr auto begin() noexcept;
|
||||||
|
[[nodiscard]] constexpr auto end() noexcept;
|
||||||
|
[[nodiscard]] constexpr auto begin() const noexcept;
|
||||||
|
[[nodiscard]] constexpr auto end() const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
Standard iterator support for range-based loops:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
for (const auto& vertex : simplex) {
|
||||||
|
std::cout << vertex << "\n";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## GJK-Specific Methods
|
||||||
|
|
||||||
|
These methods implement the core logic for simplifying simplices in the GJK algorithm.
|
||||||
|
|
||||||
|
### `contains_origin`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]] constexpr bool contains_origin() noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
Determines if the origin lies within the current simplex. This is the **core GJK test**: if true, the shapes intersect.
|
||||||
|
|
||||||
|
* For a **1-point** simplex, always returns `false` (can't contain origin)
|
||||||
|
* For a **2-point** simplex (line), checks if origin projects onto the segment
|
||||||
|
* For a **3-point** simplex (triangle), checks if origin projects onto the triangle
|
||||||
|
* For a **4-point** simplex (tetrahedron), checks if origin is inside
|
||||||
|
|
||||||
|
**Side effect**: Simplifies the simplex by removing points not needed to maintain proximity to the origin. After calling, `size()` may have decreased.
|
||||||
|
|
||||||
|
**Return value**:
|
||||||
|
* `true` — origin is contained (collision detected)
|
||||||
|
* `false` — origin not contained; simplex has been simplified toward origin
|
||||||
|
|
||||||
|
### `next_direction`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]] constexpr VectorType next_direction() const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes the next search direction for GJK. This is the direction from the simplex toward the origin, used to query the next support point.
|
||||||
|
|
||||||
|
* Must be called **after** `contains_origin()` returns `false`
|
||||||
|
* Behavior is **undefined** if called when `size() == 0` or when origin is already contained
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### GJK Iteration (Simplified)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Simplex<Vector3<float>> simplex;
|
||||||
|
Vector3<float> direction{1, 0, 0}; // Initial search direction
|
||||||
|
|
||||||
|
for (int i = 0; i < 64; ++i) {
|
||||||
|
// Get support point in current direction
|
||||||
|
auto support = find_support_vertex(collider_a, collider_b, direction);
|
||||||
|
|
||||||
|
// Check if we made progress
|
||||||
|
if (support.dot(direction) <= 0)
|
||||||
|
break; // No collision possible
|
||||||
|
|
||||||
|
simplex.push_front(support);
|
||||||
|
|
||||||
|
// Check if simplex contains origin
|
||||||
|
if (simplex.contains_origin()) {
|
||||||
|
// Collision detected!
|
||||||
|
assert(simplex.size() == 4);
|
||||||
|
return GjkHitInfo{true, simplex};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get next search direction
|
||||||
|
direction = simplex.next_direction();
|
||||||
|
}
|
||||||
|
|
||||||
|
// No collision
|
||||||
|
return GjkHitInfo{false, {}};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Simplex Construction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Vec3 = Vector3<float>;
|
||||||
|
|
||||||
|
Simplex<Vec3> simplex;
|
||||||
|
simplex = {
|
||||||
|
Vec3{0.0f, 0.0f, 0.0f},
|
||||||
|
Vec3{1.0f, 0.0f, 0.0f},
|
||||||
|
Vec3{0.0f, 1.0f, 0.0f},
|
||||||
|
Vec3{0.0f, 0.0f, 1.0f}
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(simplex.size() == 4);
|
||||||
|
|
||||||
|
// Check if origin is inside this tetrahedron
|
||||||
|
bool has_collision = simplex.contains_origin();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Iterating Over Points
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void print_simplex(const Simplex<Vector3<float>>& s) {
|
||||||
|
std::cout << "Simplex with " << s.size() << " points:\n";
|
||||||
|
for (std::size_t i = 0; i < s.size(); ++i) {
|
||||||
|
const auto& p = s[i];
|
||||||
|
std::cout << " [" << i << "] = ("
|
||||||
|
<< p.x << ", " << p.y << ", " << p.z << ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
### Simplex Simplification
|
||||||
|
|
||||||
|
The `contains_origin()` method implements different tests based on simplex size:
|
||||||
|
|
||||||
|
#### Line Segment (2 points)
|
||||||
|
|
||||||
|
Checks if origin projects onto segment `[A, B]`:
|
||||||
|
* If yes, keeps both points
|
||||||
|
* If no, keeps only the closer point
|
||||||
|
|
||||||
|
#### Triangle (3 points)
|
||||||
|
|
||||||
|
Tests the origin against the triangle plane and edges using cross products. Simplifies to:
|
||||||
|
* The full triangle if origin projects onto its surface
|
||||||
|
* An edge if origin is closest to that edge
|
||||||
|
* A single vertex otherwise
|
||||||
|
|
||||||
|
#### Tetrahedron (4 points)
|
||||||
|
|
||||||
|
Tests origin against all four faces:
|
||||||
|
* If origin is inside, returns `true` (collision)
|
||||||
|
* If outside, reduces to the face/edge/vertex closest to origin
|
||||||
|
|
||||||
|
### Direction Calculation
|
||||||
|
|
||||||
|
The `next_direction()` method computes:
|
||||||
|
* For **line**: perpendicular from line toward origin
|
||||||
|
* For **triangle**: perpendicular from triangle toward origin
|
||||||
|
* Implementation uses cross products and projections to avoid sqrt when possible
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Characteristics
|
||||||
|
|
||||||
|
* **Storage**: Fixed 4 × `sizeof(VectorType)` + size counter
|
||||||
|
* **Push front**: O(n) where n is current size (max 4, so effectively O(1))
|
||||||
|
* **Contains origin**: O(1) for each case (line, triangle, tetrahedron)
|
||||||
|
* **Next direction**: O(1) — simple cross products and subtractions
|
||||||
|
* **No heap allocations**: All storage is inline
|
||||||
|
|
||||||
|
**constexpr**: All methods are `constexpr`, enabling compile-time usage where feasible.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Edge Cases & Constraints
|
||||||
|
|
||||||
|
### Degenerate Simplices
|
||||||
|
|
||||||
|
* **Zero-length edges**: Can occur if support points coincide. The algorithm handles this by checking `point_to_same_direction` before divisions.
|
||||||
|
* **Collinear points**: Triangle simplification detects and handles collinear cases by reducing to a line.
|
||||||
|
* **Flat tetrahedron**: If the 4th point is coplanar with the first 3, the origin containment test may have reduced precision.
|
||||||
|
|
||||||
|
### Assertions
|
||||||
|
|
||||||
|
* **Capacity**: `operator=` asserts `list.size() <= 4` in debug builds
|
||||||
|
* **Index bounds**: No bounds checking in release builds — ensure `index < size()`
|
||||||
|
|
||||||
|
### Thread Safety
|
||||||
|
|
||||||
|
* **Read-only**: Safe to read from multiple threads
|
||||||
|
* **Modification**: Not thread-safe; synchronize writes externally
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Relationship to GJK & EPA
|
||||||
|
|
||||||
|
### In GJK
|
||||||
|
|
||||||
|
* Starts empty or with an initial point
|
||||||
|
* Grows via `push_front` as support points are added
|
||||||
|
* Shrinks via `contains_origin` as it's simplified
|
||||||
|
* Once it reaches 4 points and contains origin, GJK succeeds
|
||||||
|
|
||||||
|
### In EPA
|
||||||
|
|
||||||
|
* Takes a 4-point simplex from GJK as input
|
||||||
|
* Uses the tetrahedron as the initial polytope
|
||||||
|
* Does not directly use the `Simplex` class for expansion (EPA maintains a more complex polytope structure)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [GJK Algorithm Documentation](gjk_algorithm.md) - Uses `Simplex` for collision detection
|
||||||
|
- [EPA Algorithm Documentation](epa_algorithm.md) - Takes 4-point `Simplex` as input
|
||||||
|
- [MeshCollider Documentation](mesh_collider.md) - Provides support function for GJK/EPA
|
||||||
|
- [Vector3 Documentation](../linear_algebra/vector3.md) - Default vertex type
|
||||||
|
- [Tutorials - Collision Detection](../tutorials.md#tutorial-4-collision-detection) - Collision tutorial
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
108
docs/engines/frostbite/camera_trait.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# `omath::frostbite_engine::CameraTrait` — plug-in trait for `projection::Camera`
|
||||||
|
|
||||||
|
> Header: `omath/engines/frostbite_engine/traits/camera_trait.hpp` • Impl: `omath/engines/frostbite_engine/traits/camera_trait.cpp`
|
||||||
|
> Namespace: `omath::frostbite_engine`
|
||||||
|
> Purpose: provide Frostbite-style **look-at**, **view**, and **projection** math to the generic `omath::projection::Camera` (satisfies `CameraEngineConcept`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`CameraTrait` exposes three `static` functions:
|
||||||
|
|
||||||
|
* `calc_look_at_angle(origin, look_at)` – computes Euler angles so the camera at `origin` looks at `look_at`. Implementation normalizes the direction, computes **pitch** as `-asin(dir.y)` and **yaw** as `atan2(dir.x, dir.z)`; **roll** is `0`. Pitch/yaw are returned using the project’s strong angle types (`PitchAngle`, `YawAngle`, `RollAngle`).
|
||||||
|
* `calc_view_matrix(angles, origin)` – delegates to Frostbite formulas `frostbite_engine::calc_view_matrix`, producing a `Mat4X4` view matrix for the given angles and origin.
|
||||||
|
* `calc_projection_matrix(fov, viewport, near, far)` – builds a perspective projection by calling `calc_perspective_projection_matrix(fov_degrees, aspect, near, far)`, where `aspect = viewport.aspect_ratio()`. Accepts `FieldOfView` (degrees).
|
||||||
|
|
||||||
|
The trait’s types (`ViewAngles`, `Mat4X4`, angle aliases) and helpers live in the Frostbite engine math headers included by the trait (`formulas.hpp`) and the shared projection header (`projection/camera.hpp`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::frostbite_engine {
|
||||||
|
|
||||||
|
class CameraTrait final {
|
||||||
|
public:
|
||||||
|
// Compute Euler angles (pitch/yaw/roll) to look from cam_origin to look_at.
|
||||||
|
static ViewAngles
|
||||||
|
calc_look_at_angle(const Vector3<float>& cam_origin,
|
||||||
|
const Vector3<float>& look_at) noexcept;
|
||||||
|
|
||||||
|
// Build view matrix for given angles and origin.
|
||||||
|
static Mat4X4
|
||||||
|
calc_view_matrix(const ViewAngles& angles,
|
||||||
|
const Vector3<float>& cam_origin) noexcept;
|
||||||
|
|
||||||
|
// Build perspective projection from FOV (deg), viewport, near/far.
|
||||||
|
static Mat4X4
|
||||||
|
calc_projection_matrix(const projection::FieldOfView& fov,
|
||||||
|
const projection::ViewPort& view_port,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::frostbite_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
Uses: `Vector3<float>`, `ViewAngles` (pitch/yaw/roll), `Mat4X4`, `projection::FieldOfView`, `projection::ViewPort`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Behavior & conventions
|
||||||
|
|
||||||
|
* **Angles from look-at**:
|
||||||
|
|
||||||
|
```
|
||||||
|
dir = normalize(look_at - origin)
|
||||||
|
pitch = -asin(dir.y) // +Y is up
|
||||||
|
yaw = atan2(dir.x, dir.z)
|
||||||
|
roll = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Returned as `PitchAngle::from_radians(...)`, `YawAngle::from_radians(...)`, etc.
|
||||||
|
|
||||||
|
* **View matrix**: built by the Frostbite engine helper `frostbite_engine::calc_view_matrix(angles, origin)` to match the engine’s handedness and axis conventions.
|
||||||
|
|
||||||
|
* **Projection**: uses `calc_perspective_projection_matrix(fov.as_degrees(), viewport.aspect_ratio(), near, far)`. Pass your **vertical FOV** in degrees via `FieldOfView`; the helper computes a standard perspective matrix.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Using with `projection::Camera`
|
||||||
|
|
||||||
|
Create a camera whose math is driven by this trait:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Mat4 = Mat4X4; // from Frostbite math headers
|
||||||
|
using Angs = ViewAngles; // pitch/yaw/roll type
|
||||||
|
using FBcam = omath::projection::Camera<Mat4, Angs, omath::frostbite_engine::CameraTrait>;
|
||||||
|
|
||||||
|
omath::projection::ViewPort vp{1920.f, 1080.f};
|
||||||
|
auto fov = omath::projection::FieldOfView::from_degrees(70.f);
|
||||||
|
|
||||||
|
FBcam cam(
|
||||||
|
/*position*/ {0.f, 1.7f, -3.f},
|
||||||
|
/*angles*/ omath::frostbite_engine::CameraTrait::calc_look_at_angle({0,1.7f,-3},{0,1.7f,0}),
|
||||||
|
/*viewport*/ vp,
|
||||||
|
/*fov*/ fov,
|
||||||
|
/*near*/ 0.1f,
|
||||||
|
/*far*/ 1000.f
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
This satisfies `CameraEngineConcept` expected by `projection::Camera` (look-at, view, projection) as declared in the trait header.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & tips
|
||||||
|
|
||||||
|
* Ensure your `ViewAngles` aliases (`PitchAngle`, `YawAngle`, `RollAngle`) match the project’s angle policy (ranges/normalization). The implementation constructs them **from radians**.
|
||||||
|
* `aspect_ratio()` is taken directly from `ViewPort` (`width / height`), so keep both positive and non-zero.
|
||||||
|
* `near` must be > 0 and `< far` for a valid projection matrix (enforced by your math helpers).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* Frostbite math helpers in `omath/engines/frostbite_engine/formulas.hpp` (view/projection builders used above).
|
||||||
|
* Generic camera wrapper `omath::projection::Camera` and its `CameraEngineConcept` (this trait is designed to plug straight into it).
|
||||||
59
docs/engines/frostbite/constants.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
Nice! A clean little “types + constants” header. A few quick fixes and polish:
|
||||||
|
|
||||||
|
## Issues / suggestions
|
||||||
|
|
||||||
|
1. **Mat3X3 alias is wrong**
|
||||||
|
|
||||||
|
* You wrote `using Mat3X3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;`
|
||||||
|
* That should be `Mat<3, 3, ...>`.
|
||||||
|
|
||||||
|
2. **`constexpr` globals in a header → make them `inline constexpr`**
|
||||||
|
|
||||||
|
* Since this is in a header included by multiple TUs, use `inline constexpr` to avoid ODR/link issues (C++17+).
|
||||||
|
|
||||||
|
3. **Consider column-major vs row-major**
|
||||||
|
|
||||||
|
* Most game/graphics stacks (GLSL/HLSL, many engines) lean column-major and column vectors. If the rest of your math lib or shaders assume column-major, align these typedefs now to avoid silent transposes later. If row-major is intentional, all good—just be consistent.
|
||||||
|
|
||||||
|
4. **Naming consistency**
|
||||||
|
|
||||||
|
* If you prefer `k_` prefix, keep it; otherwise consider `kAbsUp`/`ABS_UP` to match your codebase’s conventions.
|
||||||
|
|
||||||
|
5. **`Mat1X3` as a “row vector”**
|
||||||
|
|
||||||
|
* If you actually use it as a 3-component vector, consider just `Vector3<float>` (clearer) and reserve `Mat1X3` for real row-vector math.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tidied version
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Created by Vlad on 10/21/2025.
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "omath/linear_algebra/mat.hpp"
|
||||||
|
#include "omath/linear_algebra/vector3.hpp"
|
||||||
|
#include <omath/trigonometry/angle.hpp>
|
||||||
|
#include <omath/trigonometry/view_angles.hpp>
|
||||||
|
|
||||||
|
namespace omath::frostbite_engine
|
||||||
|
{
|
||||||
|
// Inline to avoid ODR across translation units
|
||||||
|
inline constexpr Vector3<float> k_abs_up = {0.0f, 1.0f, 0.0f};
|
||||||
|
inline constexpr Vector3<float> k_abs_right = {1.0f, 0.0f, 0.0f};
|
||||||
|
inline constexpr Vector3<float> k_abs_forward = {0.0f, 0.0f, 1.0f};
|
||||||
|
|
||||||
|
// NOTE: verify row/column major matches the rest of your engine
|
||||||
|
using Mat4X4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
using Mat3X3 = Mat<3, 3, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
using Mat1X3 = Mat<1, 3, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
|
||||||
|
using PitchAngle = Angle<float, -90.0f, 90.0f, AngleFlags::Clamped >;
|
||||||
|
using YawAngle = Angle<float,-180.0f, 180.0f, AngleFlags::Normalized>;
|
||||||
|
using RollAngle = Angle<float,-180.0f, 180.0f, AngleFlags::Normalized>;
|
||||||
|
|
||||||
|
using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
|
||||||
|
} // namespace omath::frostbite_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
If you share how your matrices multiply vectors (row vs column) and your world handedness, I can double-check the axis constants and angle normalization to make sure yaw/pitch signs line up with your camera and `atan2` usage.
|
||||||
0
docs/engines/frostbite/formulas.md
Normal file
119
docs/engines/frostbite/mesh_trait.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# `omath::frostbite_engine::MeshTrait` — mesh transformation trait for Frostbite Engine
|
||||||
|
|
||||||
|
> Header: `omath/engines/frostbite_engine/traits/mesh_trait.hpp`
|
||||||
|
> Namespace: `omath::frostbite_engine`
|
||||||
|
> Purpose: provide Frostbite Engine-specific rotation matrix computation for `omath::primitives::Mesh`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`MeshTrait` is a trait class that provides the `rotation_matrix` function for transforming meshes in Frostbite's coordinate system. It serves as a template parameter to `omath::primitives::Mesh`, enabling engine-specific rotation behavior.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate System
|
||||||
|
|
||||||
|
**Frostbite Engine** uses:
|
||||||
|
* **Up axis**: +Y
|
||||||
|
* **Forward axis**: +Z
|
||||||
|
* **Right axis**: +X
|
||||||
|
* **Handedness**: Right-handed
|
||||||
|
* **Rotation order**: Pitch (X) → Yaw (Y) → Roll (Z)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::frostbite_engine {
|
||||||
|
|
||||||
|
class MeshTrait final {
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::frostbite_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Method: `rotation_matrix`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes a 4×4 rotation matrix from Frostbite-style Euler angles.
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
* `rotation` — `ViewAngles` containing pitch, yaw, and roll angles
|
||||||
|
|
||||||
|
**Returns**: 4×4 rotation matrix suitable for mesh transformation
|
||||||
|
|
||||||
|
**Implementation**: Delegates to `frostbite_engine::rotation_matrix(rotation)` defined in `formulas.hpp`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### With Mesh
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::frostbite_engine;
|
||||||
|
|
||||||
|
// Create mesh (MeshTrait is used automatically)
|
||||||
|
Mesh my_mesh(vertices, indices);
|
||||||
|
|
||||||
|
// Set rotation using ViewAngles
|
||||||
|
ViewAngles angles;
|
||||||
|
angles.pitch = PitchAngle::from_degrees(30.0f);
|
||||||
|
angles.yaw = YawAngle::from_degrees(45.0f);
|
||||||
|
angles.roll = RollAngle::from_degrees(0.0f);
|
||||||
|
|
||||||
|
my_mesh.set_rotation(angles);
|
||||||
|
|
||||||
|
// The rotation matrix is computed using MeshTrait::rotation_matrix
|
||||||
|
auto matrix = my_mesh.get_to_world_matrix();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rotation Conventions
|
||||||
|
|
||||||
|
Frostbite uses a right-handed Y-up coordinate system:
|
||||||
|
|
||||||
|
1. **Pitch** (rotation around X-axis / right axis)
|
||||||
|
* Positive pitch looks upward (+Y direction)
|
||||||
|
* Range: typically [-89°, 89°]
|
||||||
|
|
||||||
|
2. **Yaw** (rotation around Y-axis / up axis)
|
||||||
|
* Positive yaw rotates counterclockwise when viewed from above (right-handed)
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
3. **Roll** (rotation around Z-axis / forward axis)
|
||||||
|
* Positive roll tilts right
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type Alias
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::frostbite_engine {
|
||||||
|
using Mesh = primitives::Mesh<Mat4X4, ViewAngles, MeshTrait, float>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Mesh Documentation](../../3d_primitives/mesh.md) - Mesh primitive
|
||||||
|
- [Formulas Documentation](formulas.md) - Frostbite rotation formula
|
||||||
|
- [CameraTrait Documentation](camera_trait.md) - Camera trait
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
105
docs/engines/frostbite/pred_engine_trait.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
// Created by Vlad on 8/6/2025.
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cmath> // sqrt, hypot, tan, asin, atan2
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "omath/engines/frostbite_engine/formulas.hpp"
|
||||||
|
#include "omath/projectile_prediction/projectile.hpp"
|
||||||
|
#include "omath/projectile_prediction/target.hpp"
|
||||||
|
|
||||||
|
namespace omath::frostbite_engine
|
||||||
|
{
|
||||||
|
class PredEngineTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Predict projectile position given launch angles (degrees), time (s), and world gravity (m/s^2).
|
||||||
|
// Note: kept runtime function; remove constexpr to avoid CTAD surprises across toolchains.
|
||||||
|
static Vector3<float> predict_projectile_position(
|
||||||
|
const projectile_prediction::Projectile& projectile,
|
||||||
|
float pitch_deg, float yaw_deg,
|
||||||
|
float time, float gravity) noexcept
|
||||||
|
{
|
||||||
|
// Engine convention: negative pitch looks up (your original used -pitch).
|
||||||
|
const auto fwd = forward_vector({
|
||||||
|
PitchAngle::from_degrees(-pitch_deg),
|
||||||
|
YawAngle::from_degrees(yaw_deg),
|
||||||
|
RollAngle::from_degrees(0.0f)
|
||||||
|
});
|
||||||
|
|
||||||
|
Vector3<float> pos =
|
||||||
|
projectile.m_origin +
|
||||||
|
fwd * (projectile.m_launch_speed * time);
|
||||||
|
|
||||||
|
// s = 1/2 a t^2 downward
|
||||||
|
pos.y -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5f;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static Vector3<float> predict_target_position(
|
||||||
|
const projectile_prediction::Target& target,
|
||||||
|
float time, float gravity) noexcept
|
||||||
|
{
|
||||||
|
Vector3<float> predicted = target.m_origin + target.m_velocity * time;
|
||||||
|
|
||||||
|
if (target.m_is_airborne) {
|
||||||
|
// If targets also have a gravity scale in your model, multiply here.
|
||||||
|
predicted.y -= gravity * (time * time) * 0.5f;
|
||||||
|
}
|
||||||
|
return predicted;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static float calc_vector_2d_distance(const Vector3<float>& delta) noexcept
|
||||||
|
{
|
||||||
|
// More stable than sqrt(x*x + z*z)
|
||||||
|
return std::hypot(delta.x, delta.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static float get_vector_height_coordinate(const Vector3<float>& vec) noexcept
|
||||||
|
{
|
||||||
|
return vec.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Computes a viewpoint above the predicted target, using an optional projectile pitch.
|
||||||
|
// If pitch is absent, we leave Y unchanged (or you can choose a sensible default).
|
||||||
|
[[nodiscard]]
|
||||||
|
static Vector3<float> calc_viewpoint_from_angles(
|
||||||
|
const projectile_prediction::Projectile& projectile,
|
||||||
|
const Vector3<float>& predicted_target_position,
|
||||||
|
const std::optional<float> projectile_pitch_deg) noexcept
|
||||||
|
{
|
||||||
|
// Lateral separation from projectile to target (X/Z plane).
|
||||||
|
const auto delta2d = calc_vector_2d_distance(predicted_target_position - projectile.m_origin);
|
||||||
|
|
||||||
|
float y = predicted_target_position.y;
|
||||||
|
if (projectile_pitch_deg.has_value()) {
|
||||||
|
const float pitch_rad = angles::degrees_to_radians(*projectile_pitch_deg);
|
||||||
|
const float height = delta2d * std::tan(pitch_rad);
|
||||||
|
y += height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the target's Z, not the projectile's Z (likely bugfix).
|
||||||
|
return { predicted_target_position.x, y, predicted_target_position.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Due to maybe_calculate_projectile_launch_pitch_angle spec: +89° up, -89° down.
|
||||||
|
[[nodiscard]]
|
||||||
|
static float calc_direct_pitch_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept
|
||||||
|
{
|
||||||
|
const auto direction = (view_to - origin).normalized();
|
||||||
|
return angles::radians_to_degrees(std::asin(direction.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static float calc_direct_yaw_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept
|
||||||
|
{
|
||||||
|
const auto direction = (view_to - origin).normalized();
|
||||||
|
return angles::radians_to_degrees(std::atan2(direction.x, direction.z));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace omath::frostbite_engine
|
||||||
109
docs/engines/iw_engine/camera_trait.md
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# `omath::iw_engine::CameraTrait` — plug-in trait for `projection::Camera`
|
||||||
|
|
||||||
|
> Header: `omath/engines/iw_engine/traits/camera_trait.hpp` • Impl: `omath/engines/iw_engine/traits/camera_trait.cpp`
|
||||||
|
> Namespace: `omath::iw_engine`
|
||||||
|
> Purpose: provide IW Engine (Call of Duty)-style **look-at**, **view**, and **projection** math to the generic `omath::projection::Camera` (satisfies `CameraEngineConcept`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`CameraTrait` exposes three `static` functions:
|
||||||
|
|
||||||
|
* `calc_look_at_angle(origin, look_at)` – computes Euler angles so the camera at `origin` looks at `look_at`. Implementation normalizes the direction, computes **pitch** as `asin(dir.z)` and **yaw** as `atan2(dir.y, dir.x)`; **roll** is `0`. Pitch/yaw are returned using the project's strong angle types (`PitchAngle`, `YawAngle`, `RollAngle`).
|
||||||
|
* `calc_view_matrix(angles, origin)` – delegates to IW Engine formulas `iw_engine::calc_view_matrix`, producing a `Mat4X4` view matrix for the given angles and origin.
|
||||||
|
* `calc_projection_matrix(fov, viewport, near, far)` – builds a perspective projection by calling `calc_perspective_projection_matrix(fov_degrees, aspect, near, far)`, where `aspect = viewport.aspect_ratio()`. Accepts `FieldOfView` (degrees).
|
||||||
|
|
||||||
|
The trait's types (`ViewAngles`, `Mat4X4`, angle aliases) and helpers live in the IW Engine math headers included by the trait (`formulas.hpp`) and the shared projection header (`projection/camera.hpp`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::iw_engine {
|
||||||
|
|
||||||
|
class CameraTrait final {
|
||||||
|
public:
|
||||||
|
// Compute Euler angles (pitch/yaw/roll) to look from cam_origin to look_at.
|
||||||
|
static ViewAngles
|
||||||
|
calc_look_at_angle(const Vector3<float>& cam_origin,
|
||||||
|
const Vector3<float>& look_at) noexcept;
|
||||||
|
|
||||||
|
// Build view matrix for given angles and origin.
|
||||||
|
static Mat4X4
|
||||||
|
calc_view_matrix(const ViewAngles& angles,
|
||||||
|
const Vector3<float>& cam_origin) noexcept;
|
||||||
|
|
||||||
|
// Build perspective projection from FOV (deg), viewport, near/far.
|
||||||
|
static Mat4X4
|
||||||
|
calc_projection_matrix(const projection::FieldOfView& fov,
|
||||||
|
const projection::ViewPort& view_port,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::iw_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
Uses: `Vector3<float>`, `ViewAngles` (pitch/yaw/roll), `Mat4X4`, `projection::FieldOfView`, `projection::ViewPort`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Behavior & conventions
|
||||||
|
|
||||||
|
* **Angles from look-at** (Z-up coordinate system):
|
||||||
|
|
||||||
|
```
|
||||||
|
dir = normalize(look_at - origin)
|
||||||
|
pitch = asin(dir.z) // +Z is up
|
||||||
|
yaw = atan2(dir.y, dir.x) // horizontal rotation
|
||||||
|
roll = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Returned as `PitchAngle::from_radians(...)`, `YawAngle::from_radians(...)`, etc.
|
||||||
|
|
||||||
|
* **View matrix**: built by the IW Engine helper `iw_engine::calc_view_matrix(angles, origin)` to match the engine's handedness and axis conventions.
|
||||||
|
|
||||||
|
* **Projection**: uses `calc_perspective_projection_matrix(fov.as_degrees(), viewport.aspect_ratio(), near, far)`. Pass your **vertical FOV** in degrees via `FieldOfView`; the helper computes a standard perspective matrix.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Using with `projection::Camera`
|
||||||
|
|
||||||
|
Create a camera whose math is driven by this trait:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Mat4 = Mat4X4; // from IW Engine math headers
|
||||||
|
using Angs = ViewAngles; // pitch/yaw/roll type
|
||||||
|
using IWcam = omath::projection::Camera<Mat4, Angs, omath::iw_engine::CameraTrait>;
|
||||||
|
|
||||||
|
omath::projection::ViewPort vp{1920.f, 1080.f};
|
||||||
|
auto fov = omath::projection::FieldOfView::from_degrees(65.f);
|
||||||
|
|
||||||
|
IWcam cam(
|
||||||
|
/*position*/ {500.f, 200.f, 100.f},
|
||||||
|
/*angles*/ omath::iw_engine::CameraTrait::calc_look_at_angle({500,200,100},{0,0,100}),
|
||||||
|
/*viewport*/ vp,
|
||||||
|
/*fov*/ fov,
|
||||||
|
/*near*/ 0.1f,
|
||||||
|
/*far*/ 5000.f
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
This satisfies `CameraEngineConcept` expected by `projection::Camera` (look-at, view, projection) as declared in the trait header.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & tips
|
||||||
|
|
||||||
|
* Ensure your `ViewAngles` aliases (`PitchAngle`, `YawAngle`, `RollAngle`) match the project's angle policy (ranges/normalization). The implementation constructs them **from radians**.
|
||||||
|
* `aspect_ratio()` is taken directly from `ViewPort` (`width / height`), so keep both positive and non-zero.
|
||||||
|
* `near` must be > 0 and `< far` for a valid projection matrix (enforced by your math helpers).
|
||||||
|
* IW Engine uses **Z-up**: pitch angles control vertical look, positive = up.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* IW Engine math helpers in `omath/engines/iw_engine/formulas.hpp` (view/projection builders used above).
|
||||||
|
* Generic camera wrapper `omath::projection::Camera` and its `CameraEngineConcept` (this trait is designed to plug straight into it).
|
||||||
77
docs/engines/iw_engine/constants.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# `omath::iw_engine` — types & constants
|
||||||
|
|
||||||
|
> Header: `omath/engines/iw_engine/constants.hpp`
|
||||||
|
> Namespace: `omath::iw_engine`
|
||||||
|
> Purpose: define IW Engine (Call of Duty) coordinate system, matrix types, and angle ranges
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The **IW Engine** (Infinity Ward Engine, used in Call of Duty series) uses a **Z-up, right-handed** coordinate system:
|
||||||
|
|
||||||
|
* **Up** = `{0, 0, 1}` (Z-axis)
|
||||||
|
* **Right** = `{0, -1, 0}` (negative Y-axis)
|
||||||
|
* **Forward** = `{1, 0, 0}` (X-axis)
|
||||||
|
|
||||||
|
Matrices are **row-major**. Angles are **clamped pitch** (±89°) and **normalized yaw/roll** (±180°).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constants
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::iw_engine {
|
||||||
|
constexpr Vector3<float> k_abs_up = {0, 0, 1};
|
||||||
|
constexpr Vector3<float> k_abs_right = {0, -1, 0};
|
||||||
|
constexpr Vector3<float> k_abs_forward = {1, 0, 0};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
These basis vectors define the engine's **world coordinate frame**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Matrix types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Mat4X4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
using Mat3X3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
using Mat1X3 = Mat<1, 3, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Row-major** storage means rows are contiguous in memory. Suitable for CPU-side transforms and typical C++ math libraries.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Angle types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using PitchAngle = Angle<float, -89.f, 89.f, AngleFlags::Clamped>;
|
||||||
|
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||||
|
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||||
|
|
||||||
|
using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
|
||||||
|
```
|
||||||
|
|
||||||
|
* **PitchAngle**: clamped to **[-89°, +89°]** (looking down vs. up)
|
||||||
|
* **YawAngle**: normalized to **[-180°, +180°]** (horizontal rotation)
|
||||||
|
* **RollAngle**: normalized to **[-180°, +180°]** (camera roll)
|
||||||
|
|
||||||
|
`ViewAngles` bundles all three into a single type for camera/view transforms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate system notes
|
||||||
|
|
||||||
|
* **Z-up**: gravity points along `-Z`, height increases with `+Z`
|
||||||
|
* **Right-handed**: cross product `forward × right = up` holds
|
||||||
|
* This matches **IW Engine** (Call of Duty series: Modern Warfare, Black Ops, etc.) conventions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/iw_engine/formulas.hpp` — view/projection matrix builders
|
||||||
|
* `omath/trigonometry/angle.hpp` — angle normalization & clamping helpers
|
||||||
|
* `omath/trigonometry/view_angles.hpp` — generic pitch/yaw/roll wrapper
|
||||||
135
docs/engines/iw_engine/formulas.md
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
# `omath::iw_engine` — formulas & matrix helpers
|
||||||
|
|
||||||
|
> Header: `omath/engines/iw_engine/formulas.hpp`
|
||||||
|
> Namespace: `omath::iw_engine`
|
||||||
|
> Purpose: compute direction vectors, rotation matrices, view matrices, and perspective projections for IW Engine (Call of Duty)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
This header provides **IW Engine**-specific math for:
|
||||||
|
|
||||||
|
* **Direction vectors** (`forward`, `right`, `up`) from `ViewAngles`
|
||||||
|
* **Rotation matrices** from Euler angles
|
||||||
|
* **View matrices** (camera transforms)
|
||||||
|
* **Perspective projection** matrices
|
||||||
|
|
||||||
|
All functions respect IW Engine's **Z-up, right-handed** coordinate system.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::iw_engine {
|
||||||
|
|
||||||
|
// Compute forward direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> forward_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Compute right direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> right_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Compute up direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> up_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Build 3x3 rotation matrix from angles
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Build view matrix (camera space transform)
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 calc_view_matrix(const ViewAngles& angles,
|
||||||
|
const Vector3<float>& cam_origin) noexcept;
|
||||||
|
|
||||||
|
// Build perspective projection matrix
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 calc_perspective_projection_matrix(float field_of_view,
|
||||||
|
float aspect_ratio,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
|
||||||
|
} // namespace omath::iw_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Direction vectors
|
||||||
|
|
||||||
|
Given camera angles (pitch/yaw/roll):
|
||||||
|
|
||||||
|
* `forward_vector(angles)` → unit vector pointing where the camera looks
|
||||||
|
* `right_vector(angles)` → unit vector pointing to the camera's right
|
||||||
|
* `up_vector(angles)` → unit vector pointing upward relative to the camera
|
||||||
|
|
||||||
|
These are used for movement, aim direction, and building coordinate frames.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rotation & view matrices
|
||||||
|
|
||||||
|
* `rotation_matrix(angles)` → 3×3 (or 4×4) rotation matrix from Euler angles
|
||||||
|
* `calc_view_matrix(angles, origin)` → camera view matrix
|
||||||
|
|
||||||
|
The view matrix transforms world coordinates into camera space (origin at camera, axes aligned with camera orientation).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Perspective projection
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Mat4X4 proj = calc_perspective_projection_matrix(
|
||||||
|
fov_degrees, // vertical field of view (e.g., 65)
|
||||||
|
aspect_ratio, // width / height (e.g., 16/9)
|
||||||
|
near_plane, // e.g., 0.1
|
||||||
|
far_plane // e.g., 5000.0
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Produces a **perspective projection matrix** suitable for 3D rendering pipelines. Combined with the view matrix, this implements the standard camera transform chain.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::iw_engine;
|
||||||
|
|
||||||
|
// Camera setup
|
||||||
|
ViewAngles angles = {
|
||||||
|
PitchAngle::from_degrees(-10.0f),
|
||||||
|
YawAngle::from_degrees(90.0f),
|
||||||
|
RollAngle::from_degrees(0.0f)
|
||||||
|
};
|
||||||
|
Vector3<float> cam_pos{500.0f, 200.0f, 100.0f};
|
||||||
|
|
||||||
|
// Compute direction
|
||||||
|
auto forward = forward_vector(angles);
|
||||||
|
auto right = right_vector(angles);
|
||||||
|
auto up = up_vector(angles);
|
||||||
|
|
||||||
|
// Build matrices
|
||||||
|
auto view_mat = calc_view_matrix(angles, cam_pos);
|
||||||
|
auto proj_mat = calc_perspective_projection_matrix(65.0f, 16.0f/9.0f, 0.1f, 5000.0f);
|
||||||
|
|
||||||
|
// Use view_mat and proj_mat for rendering...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
* **Angles**: pitch (up/down), yaw (left/right), roll (tilt)
|
||||||
|
* **Pitch**: positive = looking up, negative = looking down
|
||||||
|
* **Yaw**: increases counter-clockwise from the +X axis
|
||||||
|
* **Coordinate system**: Z-up, X-forward, Y-right (negative in code convention)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/iw_engine/constants.hpp` — coordinate frame & angle types
|
||||||
|
* `omath/engines/iw_engine/traits/camera_trait.hpp` — plug-in for generic `Camera`
|
||||||
|
* `omath/projection/camera.hpp` — generic camera wrapper using these formulas
|
||||||
119
docs/engines/iw_engine/mesh_trait.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# `omath::iw_engine::MeshTrait` — mesh transformation trait for IW Engine
|
||||||
|
|
||||||
|
> Header: `omath/engines/iw_engine/traits/mesh_trait.hpp`
|
||||||
|
> Namespace: `omath::iw_engine`
|
||||||
|
> Purpose: provide IW Engine-specific rotation matrix computation for `omath::primitives::Mesh`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`MeshTrait` is a trait class that provides the `rotation_matrix` function for transforming meshes in IW Engine's (Infinity Ward) coordinate system. It serves as a template parameter to `omath::primitives::Mesh`, enabling engine-specific rotation behavior.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate System
|
||||||
|
|
||||||
|
**IW Engine** (Call of Duty) uses:
|
||||||
|
* **Up axis**: +Z
|
||||||
|
* **Forward axis**: +Y
|
||||||
|
* **Right axis**: +X
|
||||||
|
* **Handedness**: Right-handed
|
||||||
|
* **Rotation order**: Pitch (X) → Yaw (Z) → Roll (Y)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::iw_engine {
|
||||||
|
|
||||||
|
class MeshTrait final {
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::iw_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Method: `rotation_matrix`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes a 4×4 rotation matrix from IW Engine-style Euler angles.
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
* `rotation` — `ViewAngles` containing pitch, yaw, and roll angles
|
||||||
|
|
||||||
|
**Returns**: 4×4 rotation matrix suitable for mesh transformation
|
||||||
|
|
||||||
|
**Implementation**: Delegates to `iw_engine::rotation_matrix(rotation)` defined in `formulas.hpp`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### With Mesh
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::iw_engine;
|
||||||
|
|
||||||
|
// Create mesh (MeshTrait is used automatically)
|
||||||
|
Mesh my_mesh(vertices, indices);
|
||||||
|
|
||||||
|
// Set rotation using ViewAngles
|
||||||
|
ViewAngles angles;
|
||||||
|
angles.pitch = PitchAngle::from_degrees(30.0f);
|
||||||
|
angles.yaw = YawAngle::from_degrees(45.0f);
|
||||||
|
angles.roll = RollAngle::from_degrees(0.0f);
|
||||||
|
|
||||||
|
my_mesh.set_rotation(angles);
|
||||||
|
|
||||||
|
// The rotation matrix is computed using MeshTrait::rotation_matrix
|
||||||
|
auto matrix = my_mesh.get_to_world_matrix();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rotation Conventions
|
||||||
|
|
||||||
|
IW Engine uses a right-handed Z-up coordinate system (similar to Source Engine):
|
||||||
|
|
||||||
|
1. **Pitch** (rotation around X-axis / right axis)
|
||||||
|
* Positive pitch looks upward (+Z direction)
|
||||||
|
* Range: typically [-89°, 89°]
|
||||||
|
|
||||||
|
2. **Yaw** (rotation around Z-axis / up axis)
|
||||||
|
* Positive yaw rotates counterclockwise when viewed from above
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
3. **Roll** (rotation around Y-axis / forward axis)
|
||||||
|
* Positive roll tilts right
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type Alias
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::iw_engine {
|
||||||
|
using Mesh = primitives::Mesh<Mat4X4, ViewAngles, MeshTrait, float>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Mesh Documentation](../../3d_primitives/mesh.md) - Mesh primitive
|
||||||
|
- [Formulas Documentation](formulas.md) - IW Engine rotation formula
|
||||||
|
- [CameraTrait Documentation](camera_trait.md) - Camera trait
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
198
docs/engines/iw_engine/pred_engine_trait.md
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
# `omath::iw_engine::PredEngineTrait` — projectile prediction trait
|
||||||
|
|
||||||
|
> Header: `omath/engines/iw_engine/traits/pred_engine_trait.hpp`
|
||||||
|
> Namespace: `omath::iw_engine`
|
||||||
|
> Purpose: provide IW Engine (Call of Duty)-specific projectile and target prediction for ballistic calculations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`PredEngineTrait` implements engine-specific helpers for **projectile prediction**:
|
||||||
|
|
||||||
|
* `predict_projectile_position` – computes where a projectile will be after `time` seconds
|
||||||
|
* `predict_target_position` – computes where a moving target will be after `time` seconds
|
||||||
|
* `calc_vector_2d_distance` – horizontal distance (X/Y plane, ignoring Z)
|
||||||
|
* `get_vector_height_coordinate` – extracts vertical coordinate (Z in IW Engine)
|
||||||
|
* `calc_viewpoint_from_angles` – computes aim point given pitch angle
|
||||||
|
* `calc_direct_pitch_angle` – pitch angle to look from origin to target
|
||||||
|
* `calc_direct_yaw_angle` – yaw angle to look from origin to target
|
||||||
|
|
||||||
|
These methods satisfy the `PredEngineTraitConcept` required by generic projectile prediction algorithms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::iw_engine {
|
||||||
|
|
||||||
|
class PredEngineTrait final {
|
||||||
|
public:
|
||||||
|
// Predict projectile position after `time` seconds
|
||||||
|
static constexpr Vector3<float>
|
||||||
|
predict_projectile_position(const projectile_prediction::Projectile& projectile,
|
||||||
|
float pitch, float yaw, float time,
|
||||||
|
float gravity) noexcept;
|
||||||
|
|
||||||
|
// Predict target position after `time` seconds
|
||||||
|
static constexpr Vector3<float>
|
||||||
|
predict_target_position(const projectile_prediction::Target& target,
|
||||||
|
float time, float gravity) noexcept;
|
||||||
|
|
||||||
|
// Compute horizontal (2D) distance
|
||||||
|
static float
|
||||||
|
calc_vector_2d_distance(const Vector3<float>& delta) noexcept;
|
||||||
|
|
||||||
|
// Get vertical coordinate (Z in IW Engine)
|
||||||
|
static constexpr float
|
||||||
|
get_vector_height_coordinate(const Vector3<float>& vec) noexcept;
|
||||||
|
|
||||||
|
// Compute aim point from angles
|
||||||
|
static Vector3<float>
|
||||||
|
calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile,
|
||||||
|
Vector3<float> predicted_target_position,
|
||||||
|
std::optional<float> projectile_pitch) noexcept;
|
||||||
|
|
||||||
|
// Compute pitch angle to look at target
|
||||||
|
static float
|
||||||
|
calc_direct_pitch_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept;
|
||||||
|
|
||||||
|
// Compute yaw angle to look at target
|
||||||
|
static float
|
||||||
|
calc_direct_yaw_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::iw_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Projectile prediction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto pos = PredEngineTrait::predict_projectile_position(
|
||||||
|
projectile, // initial position, speed, gravity scale
|
||||||
|
pitch_deg, // launch pitch (positive = up)
|
||||||
|
yaw_deg, // launch yaw
|
||||||
|
time, // time in seconds
|
||||||
|
gravity // gravity constant (e.g., 800 units/s²)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes:
|
||||||
|
|
||||||
|
1. Forward vector from pitch/yaw (using `forward_vector`)
|
||||||
|
2. Initial velocity: `forward * launch_speed`
|
||||||
|
3. Position after `time`: `origin + velocity*time - 0.5*gravity*gravityScale*time²` (Z component only)
|
||||||
|
|
||||||
|
**Note**: Negative pitch in `forward_vector` convention → positive pitch looks up.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Target prediction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto pos = PredEngineTrait::predict_target_position(
|
||||||
|
target, // position, velocity, airborne flag
|
||||||
|
time, // time in seconds
|
||||||
|
gravity // gravity constant
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Simple linear extrapolation plus gravity if target is airborne:
|
||||||
|
|
||||||
|
```
|
||||||
|
predicted = origin + velocity * time
|
||||||
|
if (airborne)
|
||||||
|
predicted.z -= 0.5 * gravity * time²
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Distance & height helpers
|
||||||
|
|
||||||
|
* `calc_vector_2d_distance(delta)` → `sqrt(delta.x² + delta.y²)` (horizontal distance)
|
||||||
|
* `get_vector_height_coordinate(vec)` → `vec.z` (vertical coordinate in IW Engine)
|
||||||
|
|
||||||
|
Used to compute ballistic arc parameters.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Aim angle calculation
|
||||||
|
|
||||||
|
* `calc_direct_pitch_angle(origin, target)` → pitch in degrees to look from `origin` to `target`
|
||||||
|
- Formula: `asin(Δz / distance)` converted to degrees
|
||||||
|
- Positive = looking up, negative = looking down
|
||||||
|
|
||||||
|
* `calc_direct_yaw_angle(origin, target)` → yaw in degrees to look from `origin` to `target`
|
||||||
|
- Formula: `atan2(Δy, Δx)` converted to degrees
|
||||||
|
- Horizontal rotation around Z-axis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Viewpoint from angles
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto aim_point = PredEngineTrait::calc_viewpoint_from_angles(
|
||||||
|
projectile,
|
||||||
|
predicted_target_pos,
|
||||||
|
optional_pitch_deg
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes where to aim in 3D space given a desired pitch angle. Uses horizontal distance and `tan(pitch)` to compute height offset.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
* **Coordinate system**: Z-up (height increases with Z)
|
||||||
|
* **Angles**: pitch in [-89°, +89°], yaw in [-180°, +180°]
|
||||||
|
* **Gravity**: applied downward along -Z axis
|
||||||
|
* **Pitch convention**: +89° = straight up, -89° = straight down
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::iw_engine;
|
||||||
|
using namespace omath::projectile_prediction;
|
||||||
|
|
||||||
|
Projectile proj{
|
||||||
|
.m_origin = {0, 0, 100},
|
||||||
|
.m_launch_speed = 1200.0f,
|
||||||
|
.m_gravity_scale = 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
Target tgt{
|
||||||
|
.m_origin = {800, 300, 100},
|
||||||
|
.m_velocity = {15, 8, 0},
|
||||||
|
.m_is_airborne = false
|
||||||
|
};
|
||||||
|
|
||||||
|
float gravity = 800.0f;
|
||||||
|
float time = 0.5f;
|
||||||
|
|
||||||
|
// Predict where target will be
|
||||||
|
auto target_pos = PredEngineTrait::predict_target_position(tgt, time, gravity);
|
||||||
|
|
||||||
|
// Compute aim angles
|
||||||
|
float pitch = PredEngineTrait::calc_direct_pitch_angle(proj.m_origin, target_pos);
|
||||||
|
float yaw = PredEngineTrait::calc_direct_yaw_angle(proj.m_origin, target_pos);
|
||||||
|
|
||||||
|
// Predict projectile position with those angles
|
||||||
|
auto proj_pos = PredEngineTrait::predict_projectile_position(proj, pitch, yaw, time, gravity);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/iw_engine/formulas.hpp` — direction vectors and matrix builders
|
||||||
|
* `omath/projectile_prediction/projectile.hpp` — `Projectile` struct
|
||||||
|
* `omath/projectile_prediction/target.hpp` — `Target` struct
|
||||||
|
* Generic projectile prediction algorithms that use `PredEngineTraitConcept`
|
||||||
110
docs/engines/opengl_engine/camera_trait.md
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# `omath::opengl_engine::CameraTrait` — plug-in trait for `projection::Camera`
|
||||||
|
|
||||||
|
> Header: `omath/engines/opengl_engine/traits/camera_trait.hpp` • Impl: `omath/engines/opengl_engine/traits/camera_trait.cpp`
|
||||||
|
> Namespace: `omath::opengl_engine`
|
||||||
|
> Purpose: provide OpenGL-style **look-at**, **view**, and **projection** math to the generic `omath::projection::Camera` (satisfies `CameraEngineConcept`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`CameraTrait` exposes three `static` functions:
|
||||||
|
|
||||||
|
* `calc_look_at_angle(origin, look_at)` – computes Euler angles so the camera at `origin` looks at `look_at`. Implementation normalizes the direction, computes **pitch** as `asin(dir.y)` and **yaw** as `-atan2(dir.x, -dir.z)`; **roll** is `0`. Pitch/yaw are returned using the project's strong angle types (`PitchAngle`, `YawAngle`, `RollAngle`).
|
||||||
|
* `calc_view_matrix(angles, origin)` – delegates to OpenGL formulas `opengl_engine::calc_view_matrix`, producing a `Mat4X4` view matrix (column-major) for the given angles and origin.
|
||||||
|
* `calc_projection_matrix(fov, viewport, near, far)` – builds a perspective projection by calling `calc_perspective_projection_matrix(fov_degrees, aspect, near, far)`, where `aspect = viewport.aspect_ratio()`. Accepts `FieldOfView` (degrees).
|
||||||
|
|
||||||
|
The trait's types (`ViewAngles`, `Mat4X4`, angle aliases) and helpers live in the OpenGL math headers included by the trait (`formulas.hpp`) and the shared projection header (`projection/camera.hpp`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::opengl_engine {
|
||||||
|
|
||||||
|
class CameraTrait final {
|
||||||
|
public:
|
||||||
|
// Compute Euler angles (pitch/yaw/roll) to look from cam_origin to look_at.
|
||||||
|
static ViewAngles
|
||||||
|
calc_look_at_angle(const Vector3<float>& cam_origin,
|
||||||
|
const Vector3<float>& look_at) noexcept;
|
||||||
|
|
||||||
|
// Build view matrix for given angles and origin (column-major).
|
||||||
|
static Mat4X4
|
||||||
|
calc_view_matrix(const ViewAngles& angles,
|
||||||
|
const Vector3<float>& cam_origin) noexcept;
|
||||||
|
|
||||||
|
// Build perspective projection from FOV (deg), viewport, near/far (column-major).
|
||||||
|
static Mat4X4
|
||||||
|
calc_projection_matrix(const projection::FieldOfView& fov,
|
||||||
|
const projection::ViewPort& view_port,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::opengl_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
Uses: `Vector3<float>`, `ViewAngles` (pitch/yaw/roll), `Mat4X4`, `projection::FieldOfView`, `projection::ViewPort`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Behavior & conventions
|
||||||
|
|
||||||
|
* **Angles from look-at** (Y-up, -Z forward coordinate system):
|
||||||
|
|
||||||
|
```
|
||||||
|
dir = normalize(look_at - origin)
|
||||||
|
pitch = asin(dir.y) // +Y is up
|
||||||
|
yaw = -atan2(dir.x, -dir.z) // horizontal rotation
|
||||||
|
roll = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Returned as `PitchAngle::from_radians(...)`, `YawAngle::from_radians(...)`, etc.
|
||||||
|
|
||||||
|
* **View matrix**: built by the OpenGL helper `opengl_engine::calc_view_matrix(angles, origin)` to match OpenGL's right-handed, Y-up, -Z forward conventions. Matrix is **column-major**.
|
||||||
|
|
||||||
|
* **Projection**: uses `calc_perspective_projection_matrix(fov.as_degrees(), viewport.aspect_ratio(), near, far)`. Pass your **vertical FOV** in degrees via `FieldOfView`; the helper computes a standard perspective matrix (column-major).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Using with `projection::Camera`
|
||||||
|
|
||||||
|
Create a camera whose math is driven by this trait:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Mat4 = Mat4X4; // from OpenGL math headers (column-major)
|
||||||
|
using Angs = ViewAngles; // pitch/yaw/roll type
|
||||||
|
using GLcam = omath::projection::Camera<Mat4, Angs, omath::opengl_engine::CameraTrait>;
|
||||||
|
|
||||||
|
omath::projection::ViewPort vp{1920.f, 1080.f};
|
||||||
|
auto fov = omath::projection::FieldOfView::from_degrees(45.f);
|
||||||
|
|
||||||
|
GLcam cam(
|
||||||
|
/*position*/ {5.f, 3.f, 5.f},
|
||||||
|
/*angles*/ omath::opengl_engine::CameraTrait::calc_look_at_angle({5,3,5},{0,0,0}),
|
||||||
|
/*viewport*/ vp,
|
||||||
|
/*fov*/ fov,
|
||||||
|
/*near*/ 0.1f,
|
||||||
|
/*far*/ 100.f
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
This satisfies `CameraEngineConcept` expected by `projection::Camera` (look-at, view, projection) as declared in the trait header.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & tips
|
||||||
|
|
||||||
|
* Ensure your `ViewAngles` aliases (`PitchAngle`, `YawAngle`, `RollAngle`) match the project's angle policy (ranges/normalization). The implementation constructs them **from radians**.
|
||||||
|
* `aspect_ratio()` is taken directly from `ViewPort` (`width / height`), so keep both positive and non-zero.
|
||||||
|
* `near` must be > 0 and `< far` for a valid projection matrix (enforced by your math helpers).
|
||||||
|
* OpenGL uses **Y-up, -Z forward**: pitch angles control vertical look (positive = up), yaw controls horizontal rotation.
|
||||||
|
* Matrices are **column-major** (no transpose needed for OpenGL shaders).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* OpenGL math helpers in `omath/engines/opengl_engine/formulas.hpp` (view/projection builders used above).
|
||||||
|
* Generic camera wrapper `omath::projection::Camera` and its `CameraEngineConcept` (this trait is designed to plug straight into it).
|
||||||
78
docs/engines/opengl_engine/constants.md
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# `omath::opengl_engine` — types & constants
|
||||||
|
|
||||||
|
> Header: `omath/engines/opengl_engine/constants.hpp`
|
||||||
|
> Namespace: `omath::opengl_engine`
|
||||||
|
> Purpose: define OpenGL coordinate system, matrix types, and angle ranges
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The **OpenGL Engine** uses a **Y-up, right-handed** coordinate system:
|
||||||
|
|
||||||
|
* **Up** = `{0, 1, 0}` (Y-axis)
|
||||||
|
* **Right** = `{1, 0, 0}` (X-axis)
|
||||||
|
* **Forward** = `{0, 0, -1}` (negative Z-axis)
|
||||||
|
|
||||||
|
Matrices are **column-major**. Angles are **clamped pitch** (±90°) and **normalized yaw/roll** (±180°).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constants
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::opengl_engine {
|
||||||
|
constexpr Vector3<float> k_abs_up = {0, 1, 0};
|
||||||
|
constexpr Vector3<float> k_abs_right = {1, 0, 0};
|
||||||
|
constexpr Vector3<float> k_abs_forward = {0, 0, -1};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
These basis vectors define the engine's **world coordinate frame**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Matrix types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Mat4X4 = Mat<4, 4, float, MatStoreType::COLUMN_MAJOR>;
|
||||||
|
using Mat3X3 = Mat<4, 4, float, MatStoreType::COLUMN_MAJOR>;
|
||||||
|
using Mat1X3 = Mat<1, 3, float, MatStoreType::COLUMN_MAJOR>;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Column-major** storage means columns are contiguous in memory. This matches OpenGL's native matrix layout and shader expectations (GLSL).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Angle types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using PitchAngle = Angle<float, -90.f, 90.f, AngleFlags::Clamped>;
|
||||||
|
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||||
|
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||||
|
|
||||||
|
using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
|
||||||
|
```
|
||||||
|
|
||||||
|
* **PitchAngle**: clamped to **[-90°, +90°]** (looking down vs. up)
|
||||||
|
* **YawAngle**: normalized to **[-180°, +180°]** (horizontal rotation)
|
||||||
|
* **RollAngle**: normalized to **[-180°, +180°]** (camera roll)
|
||||||
|
|
||||||
|
`ViewAngles` bundles all three into a single type for camera/view transforms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate system notes
|
||||||
|
|
||||||
|
* **Y-up**: gravity points along `-Y`, height increases with `+Y`
|
||||||
|
* **Right-handed**: cross product `right × up = forward` (forward is `-Z`)
|
||||||
|
* **Forward = -Z**: the camera looks down the negative Z-axis (OpenGL convention)
|
||||||
|
* This matches **OpenGL** conventions for 3D graphics pipelines
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/opengl_engine/formulas.hpp` — view/projection matrix builders
|
||||||
|
* `omath/trigonometry/angle.hpp` — angle normalization & clamping helpers
|
||||||
|
* `omath/trigonometry/view_angles.hpp` — generic pitch/yaw/roll wrapper
|
||||||
140
docs/engines/opengl_engine/formulas.md
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
# `omath::opengl_engine` — formulas & matrix helpers
|
||||||
|
|
||||||
|
> Header: `omath/engines/opengl_engine/formulas.hpp`
|
||||||
|
> Namespace: `omath::opengl_engine`
|
||||||
|
> Purpose: compute direction vectors, rotation matrices, view matrices, and perspective projections for OpenGL
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
This header provides **OpenGL**-specific math for:
|
||||||
|
|
||||||
|
* **Direction vectors** (`forward`, `right`, `up`) from `ViewAngles`
|
||||||
|
* **Rotation matrices** from Euler angles
|
||||||
|
* **View matrices** (camera transforms)
|
||||||
|
* **Perspective projection** matrices
|
||||||
|
|
||||||
|
All functions respect OpenGL's **Y-up, right-handed** coordinate system with **forward = -Z**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::opengl_engine {
|
||||||
|
|
||||||
|
// Compute forward direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> forward_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Compute right direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> right_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Compute up direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> up_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Build 3x3 rotation matrix from angles
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Build view matrix (camera space transform)
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 calc_view_matrix(const ViewAngles& angles,
|
||||||
|
const Vector3<float>& cam_origin) noexcept;
|
||||||
|
|
||||||
|
// Build perspective projection matrix
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 calc_perspective_projection_matrix(float field_of_view,
|
||||||
|
float aspect_ratio,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
|
||||||
|
} // namespace omath::opengl_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Direction vectors
|
||||||
|
|
||||||
|
Given camera angles (pitch/yaw/roll):
|
||||||
|
|
||||||
|
* `forward_vector(angles)` → unit vector pointing where the camera looks (typically `-Z` direction)
|
||||||
|
* `right_vector(angles)` → unit vector pointing to the camera's right (`+X` direction)
|
||||||
|
* `up_vector(angles)` → unit vector pointing upward relative to the camera (`+Y` direction)
|
||||||
|
|
||||||
|
These are used for movement, aim direction, and building coordinate frames.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rotation & view matrices
|
||||||
|
|
||||||
|
* `rotation_matrix(angles)` → 3×3 (or 4×4) rotation matrix from Euler angles (column-major)
|
||||||
|
* `calc_view_matrix(angles, origin)` → camera view matrix (column-major)
|
||||||
|
|
||||||
|
The view matrix transforms world coordinates into camera space (origin at camera, axes aligned with camera orientation).
|
||||||
|
|
||||||
|
**Note**: Matrices are **column-major** to match OpenGL/GLSL conventions. No transpose needed when uploading to shaders.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Perspective projection
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Mat4X4 proj = calc_perspective_projection_matrix(
|
||||||
|
fov_degrees, // vertical field of view (e.g., 45)
|
||||||
|
aspect_ratio, // width / height (e.g., 16/9)
|
||||||
|
near_plane, // e.g., 0.1
|
||||||
|
far_plane // e.g., 100.0
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Produces a **perspective projection matrix** suitable for OpenGL rendering. Combined with the view matrix, this implements the standard camera transform chain.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::opengl_engine;
|
||||||
|
|
||||||
|
// Camera setup
|
||||||
|
ViewAngles angles = {
|
||||||
|
PitchAngle::from_degrees(-20.0f),
|
||||||
|
YawAngle::from_degrees(135.0f),
|
||||||
|
RollAngle::from_degrees(0.0f)
|
||||||
|
};
|
||||||
|
Vector3<float> cam_pos{5.0f, 3.0f, 5.0f};
|
||||||
|
|
||||||
|
// Compute direction
|
||||||
|
auto forward = forward_vector(angles);
|
||||||
|
auto right = right_vector(angles);
|
||||||
|
auto up = up_vector(angles);
|
||||||
|
|
||||||
|
// Build matrices (column-major for OpenGL)
|
||||||
|
auto view_mat = calc_view_matrix(angles, cam_pos);
|
||||||
|
auto proj_mat = calc_perspective_projection_matrix(45.0f, 16.0f/9.0f, 0.1f, 100.0f);
|
||||||
|
|
||||||
|
// Upload to OpenGL shaders (no transpose needed)
|
||||||
|
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view_mat.data());
|
||||||
|
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, proj_mat.data());
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
* **Angles**: pitch (up/down), yaw (left/right), roll (tilt)
|
||||||
|
* **Pitch**: positive = looking up, negative = looking down
|
||||||
|
* **Yaw**: increases counter-clockwise from the -Z axis
|
||||||
|
* **Coordinate system**: Y-up, -Z-forward, X-right (right-handed)
|
||||||
|
* **Matrix storage**: column-major (matches OpenGL/GLSL)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/opengl_engine/constants.hpp` — coordinate frame & angle types
|
||||||
|
* `omath/engines/opengl_engine/traits/camera_trait.hpp` — plug-in for generic `Camera`
|
||||||
|
* `omath/projection/camera.hpp` — generic camera wrapper using these formulas
|
||||||
121
docs/engines/opengl_engine/mesh_trait.md
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# `omath::opengl_engine::MeshTrait` — mesh transformation trait for OpenGL
|
||||||
|
|
||||||
|
> Header: `omath/engines/opengl_engine/traits/mesh_trait.hpp`
|
||||||
|
> Namespace: `omath::opengl_engine`
|
||||||
|
> Purpose: provide OpenGL-specific rotation matrix computation for `omath::primitives::Mesh`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`MeshTrait` is a trait class that provides the `rotation_matrix` function for transforming meshes in OpenGL's canonical coordinate system. It serves as a template parameter to `omath::primitives::Mesh`, enabling engine-specific rotation behavior.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate System
|
||||||
|
|
||||||
|
**OpenGL** (canonical) uses:
|
||||||
|
* **Up axis**: +Y
|
||||||
|
* **Forward axis**: +Z (toward viewer)
|
||||||
|
* **Right axis**: +X
|
||||||
|
* **Handedness**: Right-handed
|
||||||
|
* **Rotation order**: Pitch (X) → Yaw (Y) → Roll (Z)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::opengl_engine {
|
||||||
|
|
||||||
|
class MeshTrait final {
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::opengl_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Method: `rotation_matrix`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes a 4×4 rotation matrix from OpenGL-style Euler angles.
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
* `rotation` — `ViewAngles` containing pitch, yaw, and roll angles
|
||||||
|
|
||||||
|
**Returns**: 4×4 rotation matrix suitable for mesh transformation
|
||||||
|
|
||||||
|
**Implementation**: Delegates to `opengl_engine::rotation_matrix(rotation)` defined in `formulas.hpp`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### With Mesh
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::opengl_engine;
|
||||||
|
|
||||||
|
// Create mesh (MeshTrait is used automatically)
|
||||||
|
Mesh my_mesh(vertices, indices);
|
||||||
|
|
||||||
|
// Set rotation using ViewAngles
|
||||||
|
ViewAngles angles;
|
||||||
|
angles.pitch = PitchAngle::from_degrees(30.0f);
|
||||||
|
angles.yaw = YawAngle::from_degrees(45.0f);
|
||||||
|
angles.roll = RollAngle::from_degrees(0.0f);
|
||||||
|
|
||||||
|
my_mesh.set_rotation(angles);
|
||||||
|
|
||||||
|
// The rotation matrix is computed using MeshTrait::rotation_matrix
|
||||||
|
auto matrix = my_mesh.get_to_world_matrix();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rotation Conventions
|
||||||
|
|
||||||
|
OpenGL uses a right-handed Y-up coordinate system:
|
||||||
|
|
||||||
|
1. **Pitch** (rotation around X-axis / right axis)
|
||||||
|
* Positive pitch looks upward (+Y direction)
|
||||||
|
* Range: typically [-89°, 89°]
|
||||||
|
|
||||||
|
2. **Yaw** (rotation around Y-axis / up axis)
|
||||||
|
* Positive yaw rotates counterclockwise when viewed from above (right-handed)
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
3. **Roll** (rotation around Z-axis / depth axis)
|
||||||
|
* Positive roll tilts right
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
**Note**: In OpenGL, +Z points toward the viewer in view space, but away from the viewer in world space.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type Alias
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::opengl_engine {
|
||||||
|
using Mesh = primitives::Mesh<Mat4X4, ViewAngles, MeshTrait, float>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Mesh Documentation](../../3d_primitives/mesh.md) - Mesh primitive
|
||||||
|
- [Formulas Documentation](formulas.md) - OpenGL rotation formula
|
||||||
|
- [CameraTrait Documentation](camera_trait.md) - Camera trait
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
199
docs/engines/opengl_engine/pred_engine_trait.md
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
# `omath::opengl_engine::PredEngineTrait` — projectile prediction trait
|
||||||
|
|
||||||
|
> Header: `omath/engines/opengl_engine/traits/pred_engine_trait.hpp`
|
||||||
|
> Namespace: `omath::opengl_engine`
|
||||||
|
> Purpose: provide OpenGL-specific projectile and target prediction for ballistic calculations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`PredEngineTrait` implements engine-specific helpers for **projectile prediction**:
|
||||||
|
|
||||||
|
* `predict_projectile_position` – computes where a projectile will be after `time` seconds
|
||||||
|
* `predict_target_position` – computes where a moving target will be after `time` seconds
|
||||||
|
* `calc_vector_2d_distance` – horizontal distance (X/Z plane, ignoring Y)
|
||||||
|
* `get_vector_height_coordinate` – extracts vertical coordinate (Y in OpenGL)
|
||||||
|
* `calc_viewpoint_from_angles` – computes aim point given pitch angle
|
||||||
|
* `calc_direct_pitch_angle` – pitch angle to look from origin to target
|
||||||
|
* `calc_direct_yaw_angle` – yaw angle to look from origin to target
|
||||||
|
|
||||||
|
These methods satisfy the `PredEngineTraitConcept` required by generic projectile prediction algorithms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::opengl_engine {
|
||||||
|
|
||||||
|
class PredEngineTrait final {
|
||||||
|
public:
|
||||||
|
// Predict projectile position after `time` seconds
|
||||||
|
static constexpr Vector3<float>
|
||||||
|
predict_projectile_position(const projectile_prediction::Projectile& projectile,
|
||||||
|
float pitch, float yaw, float time,
|
||||||
|
float gravity) noexcept;
|
||||||
|
|
||||||
|
// Predict target position after `time` seconds
|
||||||
|
static constexpr Vector3<float>
|
||||||
|
predict_target_position(const projectile_prediction::Target& target,
|
||||||
|
float time, float gravity) noexcept;
|
||||||
|
|
||||||
|
// Compute horizontal (2D) distance
|
||||||
|
static float
|
||||||
|
calc_vector_2d_distance(const Vector3<float>& delta) noexcept;
|
||||||
|
|
||||||
|
// Get vertical coordinate (Y in OpenGL)
|
||||||
|
static constexpr float
|
||||||
|
get_vector_height_coordinate(const Vector3<float>& vec) noexcept;
|
||||||
|
|
||||||
|
// Compute aim point from angles
|
||||||
|
static Vector3<float>
|
||||||
|
calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile,
|
||||||
|
Vector3<float> predicted_target_position,
|
||||||
|
std::optional<float> projectile_pitch) noexcept;
|
||||||
|
|
||||||
|
// Compute pitch angle to look at target
|
||||||
|
static float
|
||||||
|
calc_direct_pitch_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept;
|
||||||
|
|
||||||
|
// Compute yaw angle to look at target
|
||||||
|
static float
|
||||||
|
calc_direct_yaw_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::opengl_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Projectile prediction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto pos = PredEngineTrait::predict_projectile_position(
|
||||||
|
projectile, // initial position, speed, gravity scale
|
||||||
|
pitch_deg, // launch pitch (positive = up)
|
||||||
|
yaw_deg, // launch yaw
|
||||||
|
time, // time in seconds
|
||||||
|
gravity // gravity constant (e.g., 9.81 m/s²)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes:
|
||||||
|
|
||||||
|
1. Forward vector from pitch/yaw (using `forward_vector`)
|
||||||
|
2. Initial velocity: `forward * launch_speed`
|
||||||
|
3. Position after `time`: `origin + velocity*time - 0.5*gravity*gravityScale*time²` (Y component only)
|
||||||
|
|
||||||
|
**Note**: Negative pitch in `forward_vector` convention → positive pitch looks up.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Target prediction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto pos = PredEngineTrait::predict_target_position(
|
||||||
|
target, // position, velocity, airborne flag
|
||||||
|
time, // time in seconds
|
||||||
|
gravity // gravity constant
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Simple linear extrapolation plus gravity if target is airborne:
|
||||||
|
|
||||||
|
```
|
||||||
|
predicted = origin + velocity * time
|
||||||
|
if (airborne)
|
||||||
|
predicted.y -= 0.5 * gravity * time²
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Distance & height helpers
|
||||||
|
|
||||||
|
* `calc_vector_2d_distance(delta)` → `sqrt(delta.x² + delta.z²)` (horizontal distance)
|
||||||
|
* `get_vector_height_coordinate(vec)` → `vec.y` (vertical coordinate in OpenGL)
|
||||||
|
|
||||||
|
Used to compute ballistic arc parameters.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Aim angle calculation
|
||||||
|
|
||||||
|
* `calc_direct_pitch_angle(origin, target)` → pitch in degrees to look from `origin` to `target`
|
||||||
|
- Formula: `asin(Δy / distance)` converted to degrees (direction normalized first)
|
||||||
|
- Positive = looking up, negative = looking down
|
||||||
|
|
||||||
|
* `calc_direct_yaw_angle(origin, target)` → yaw in degrees to look from `origin` to `target`
|
||||||
|
- Formula: `-atan2(Δx, -Δz)` converted to degrees (direction normalized first)
|
||||||
|
- Horizontal rotation around Y-axis (accounts for -Z forward convention)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Viewpoint from angles
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto aim_point = PredEngineTrait::calc_viewpoint_from_angles(
|
||||||
|
projectile,
|
||||||
|
predicted_target_pos,
|
||||||
|
optional_pitch_deg
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes where to aim in 3D space given a desired pitch angle. Uses horizontal distance and `tan(pitch)` to compute height offset. Result has adjusted Y coordinate.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
* **Coordinate system**: Y-up, -Z forward (height increases with Y)
|
||||||
|
* **Angles**: pitch in [-90°, +90°], yaw in [-180°, +180°]
|
||||||
|
* **Gravity**: applied downward along -Y axis
|
||||||
|
* **Pitch convention**: +90° = straight up, -90° = straight down
|
||||||
|
* **Forward direction**: negative Z-axis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::opengl_engine;
|
||||||
|
using namespace omath::projectile_prediction;
|
||||||
|
|
||||||
|
Projectile proj{
|
||||||
|
.m_origin = {0, 2, 0},
|
||||||
|
.m_launch_speed = 30.0f,
|
||||||
|
.m_gravity_scale = 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
Target tgt{
|
||||||
|
.m_origin = {10, 2, -15},
|
||||||
|
.m_velocity = {0.5f, 0, -1.0f},
|
||||||
|
.m_is_airborne = false
|
||||||
|
};
|
||||||
|
|
||||||
|
float gravity = 9.81f;
|
||||||
|
float time = 0.5f;
|
||||||
|
|
||||||
|
// Predict where target will be
|
||||||
|
auto target_pos = PredEngineTrait::predict_target_position(tgt, time, gravity);
|
||||||
|
|
||||||
|
// Compute aim angles
|
||||||
|
float pitch = PredEngineTrait::calc_direct_pitch_angle(proj.m_origin, target_pos);
|
||||||
|
float yaw = PredEngineTrait::calc_direct_yaw_angle(proj.m_origin, target_pos);
|
||||||
|
|
||||||
|
// Predict projectile position with those angles
|
||||||
|
auto proj_pos = PredEngineTrait::predict_projectile_position(proj, pitch, yaw, time, gravity);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/opengl_engine/formulas.hpp` — direction vectors and matrix builders
|
||||||
|
* `omath/projectile_prediction/projectile.hpp` — `Projectile` struct
|
||||||
|
* `omath/projectile_prediction/target.hpp` — `Target` struct
|
||||||
|
* Generic projectile prediction algorithms that use `PredEngineTraitConcept`
|
||||||
113
docs/engines/source_engine/camera_trait.md
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# `omath::source_engine::CameraTrait` — plug-in trait for `projection::Camera`
|
||||||
|
|
||||||
|
> Header: `omath/engines/source_engine/traits/camera_trait.hpp` • Impl: `omath/engines/source_engine/traits/camera_trait.cpp`
|
||||||
|
> Namespace: `omath::source_engine`
|
||||||
|
> Purpose: provide Source Engine-style **look-at**, **view**, and **projection** math to the generic `omath::projection::Camera` (satisfies `CameraEngineConcept`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`CameraTrait` exposes three `static` functions:
|
||||||
|
|
||||||
|
* `calc_look_at_angle(origin, look_at)` – computes Euler angles so the camera at `origin` looks at `look_at`. Implementation normalizes the direction, computes **pitch** as `asin(dir.z)` and **yaw** as `atan2(dir.y, dir.x)`; **roll** is `0`. Pitch/yaw are returned using the project's strong angle types (`PitchAngle`, `YawAngle`, `RollAngle`).
|
||||||
|
* `calc_view_matrix(angles, origin)` – delegates to Source Engine formulas `source_engine::calc_view_matrix`, producing a `Mat4X4` view matrix for the given angles and origin.
|
||||||
|
* `calc_projection_matrix(fov, viewport, near, far)` – builds a perspective projection by calling `calc_perspective_projection_matrix(fov_degrees, aspect, near, far)`, where `aspect = viewport.aspect_ratio()`. Accepts `FieldOfView` (degrees).
|
||||||
|
|
||||||
|
The trait's types (`ViewAngles`, `Mat4X4`, angle aliases) and helpers live in the Source Engine math headers included by the trait (`formulas.hpp`) and the shared projection header (`projection/camera.hpp`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::source_engine {
|
||||||
|
|
||||||
|
class CameraTrait final {
|
||||||
|
public:
|
||||||
|
// Compute Euler angles (pitch/yaw/roll) to look from cam_origin to look_at.
|
||||||
|
static ViewAngles
|
||||||
|
calc_look_at_angle(const Vector3<float>& cam_origin,
|
||||||
|
const Vector3<float>& look_at) noexcept;
|
||||||
|
|
||||||
|
// Build view matrix for given angles and origin.
|
||||||
|
static Mat4X4
|
||||||
|
calc_view_matrix(const ViewAngles& angles,
|
||||||
|
const Vector3<float>& cam_origin) noexcept;
|
||||||
|
|
||||||
|
// Build perspective projection from FOV (deg), viewport, near/far.
|
||||||
|
static Mat4X4
|
||||||
|
calc_projection_matrix(const projection::FieldOfView& fov,
|
||||||
|
const projection::ViewPort& view_port,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::source_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
Uses: `Vector3<float>`, `ViewAngles` (pitch/yaw/roll), `Mat4X4`, `projection::FieldOfView`, `projection::ViewPort`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Behavior & conventions
|
||||||
|
|
||||||
|
* **Angles from look-at** (Z-up coordinate system):
|
||||||
|
|
||||||
|
```
|
||||||
|
dir = normalize(look_at - origin)
|
||||||
|
pitch = asin(dir.z) // +Z is up
|
||||||
|
yaw = atan2(dir.y, dir.x) // horizontal rotation
|
||||||
|
roll = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Returned as `PitchAngle::from_radians(...)`, `YawAngle::from_radians(...)`, etc.
|
||||||
|
|
||||||
|
* **View matrix**: built by the Source Engine helper `source_engine::calc_view_matrix(angles, origin)` to match the engine's handedness and axis conventions.
|
||||||
|
|
||||||
|
* **Projection**: uses `calc_perspective_projection_matrix(fov.as_degrees(), viewport.aspect_ratio(), near, far)`. Pass your **vertical FOV** in degrees via `FieldOfView`; the helper computes a standard perspective matrix.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Using with `projection::Camera`
|
||||||
|
|
||||||
|
Create a camera whose math is driven by this trait:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Mat4 = Mat4X4; // from Source Engine math headers
|
||||||
|
using Angs = ViewAngles; // pitch/yaw/roll type
|
||||||
|
using SEcam = omath::projection::Camera<Mat4, Angs, omath::source_engine::CameraTrait>;
|
||||||
|
|
||||||
|
omath::projection::ViewPort vp{1920.f, 1080.f};
|
||||||
|
auto fov = omath::projection::FieldOfView::from_degrees(90.f);
|
||||||
|
|
||||||
|
SEcam cam(
|
||||||
|
/*position*/ {100.f, 50.f, 80.f},
|
||||||
|
/*angles*/ omath::source_engine::CameraTrait::calc_look_at_angle({100,50,80},{0,0,80}),
|
||||||
|
/*viewport*/ vp,
|
||||||
|
/*fov*/ fov,
|
||||||
|
/*near*/ 0.1f,
|
||||||
|
/*far*/ 1000.f
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
This satisfies `CameraEngineConcept` expected by `projection::Camera` (look-at, view, projection) as declared in the trait header.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & tips
|
||||||
|
|
||||||
|
* Ensure your `ViewAngles` aliases (`PitchAngle`, `YawAngle`, `RollAngle`) match the project's angle policy (ranges/normalization). The implementation constructs them **from radians**.
|
||||||
|
* `aspect_ratio()` is taken directly from `ViewPort` (`width / height`), so keep both positive and non-zero.
|
||||||
|
* `near` must be > 0 and `< far` for a valid projection matrix (enforced by your math helpers).
|
||||||
|
* Source Engine uses **Z-up**: pitch angles control vertical look, positive = up.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* [Source Engine Formulas](formulas.md) - View/projection matrix builders
|
||||||
|
* [Source Engine Constants](constants.md) - Engine-specific constants
|
||||||
|
* [Source Engine Pred Engine Trait](pred_engine_trait.md) - Projectile prediction for Source Engine
|
||||||
|
* [Generic Camera Documentation](../../projection/camera.md) - Camera base class
|
||||||
|
* [Getting Started Guide](../../getting_started.md) - Quick start with OMath
|
||||||
|
* [Tutorials - World-to-Screen](../../tutorials.md#tutorial-2-world-to-screen-projection) - Projection tutorial
|
||||||
77
docs/engines/source_engine/constants.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# `omath::source_engine` — types & constants
|
||||||
|
|
||||||
|
> Header: `omath/engines/source_engine/constants.hpp`
|
||||||
|
> Namespace: `omath::source_engine`
|
||||||
|
> Purpose: define Source Engine coordinate system, matrix types, and angle ranges
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The **Source Engine** uses a **Z-up, right-handed** coordinate system:
|
||||||
|
|
||||||
|
* **Up** = `{0, 0, 1}` (Z-axis)
|
||||||
|
* **Right** = `{0, -1, 0}` (negative Y-axis)
|
||||||
|
* **Forward** = `{1, 0, 0}` (X-axis)
|
||||||
|
|
||||||
|
Matrices are **row-major**. Angles are **clamped pitch** (±89°) and **normalized yaw/roll** (±180°).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constants
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::source_engine {
|
||||||
|
constexpr Vector3<float> k_abs_up = {0, 0, 1};
|
||||||
|
constexpr Vector3<float> k_abs_right = {0, -1, 0};
|
||||||
|
constexpr Vector3<float> k_abs_forward = {1, 0, 0};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
These basis vectors define the engine's **world coordinate frame**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Matrix types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Mat4X4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
using Mat3X3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
using Mat1X3 = Mat<1, 3, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Row-major** storage means rows are contiguous in memory. Suitable for CPU-side transforms and typical C++ math libraries.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Angle types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using PitchAngle = Angle<float, -89.f, 89.f, AngleFlags::Clamped>;
|
||||||
|
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||||
|
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||||
|
|
||||||
|
using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
|
||||||
|
```
|
||||||
|
|
||||||
|
* **PitchAngle**: clamped to **[-89°, +89°]** (looking down vs. up)
|
||||||
|
* **YawAngle**: normalized to **[-180°, +180°]** (horizontal rotation)
|
||||||
|
* **RollAngle**: normalized to **[-180°, +180°]** (camera roll)
|
||||||
|
|
||||||
|
`ViewAngles` bundles all three into a single type for camera/view transforms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate system notes
|
||||||
|
|
||||||
|
* **Z-up**: gravity points along `-Z`, height increases with `+Z`
|
||||||
|
* **Right-handed**: cross product `forward × right = up` holds
|
||||||
|
* This matches **Source Engine** (Half-Life 2, TF2, CS:GO, etc.) conventions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/source_engine/formulas.hpp` — view/projection matrix builders
|
||||||
|
* `omath/trigonometry/angle.hpp` — angle normalization & clamping helpers
|
||||||
|
* `omath/trigonometry/view_angles.hpp` — generic pitch/yaw/roll wrapper
|
||||||
135
docs/engines/source_engine/formulas.md
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
# `omath::source_engine` — formulas & matrix helpers
|
||||||
|
|
||||||
|
> Header: `omath/engines/source_engine/formulas.hpp`
|
||||||
|
> Namespace: `omath::source_engine`
|
||||||
|
> Purpose: compute direction vectors, rotation matrices, view matrices, and perspective projections for Source Engine
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
This header provides **Source Engine**-specific math for:
|
||||||
|
|
||||||
|
* **Direction vectors** (`forward`, `right`, `up`) from `ViewAngles`
|
||||||
|
* **Rotation matrices** from Euler angles
|
||||||
|
* **View matrices** (camera transforms)
|
||||||
|
* **Perspective projection** matrices
|
||||||
|
|
||||||
|
All functions respect Source Engine's **Z-up, right-handed** coordinate system.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::source_engine {
|
||||||
|
|
||||||
|
// Compute forward direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> forward_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Compute right direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> right_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Compute up direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> up_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Build 3x3 rotation matrix from angles
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Build view matrix (camera space transform)
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 calc_view_matrix(const ViewAngles& angles,
|
||||||
|
const Vector3<float>& cam_origin) noexcept;
|
||||||
|
|
||||||
|
// Build perspective projection matrix
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 calc_perspective_projection_matrix(float field_of_view,
|
||||||
|
float aspect_ratio,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
|
||||||
|
} // namespace omath::source_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Direction vectors
|
||||||
|
|
||||||
|
Given camera angles (pitch/yaw/roll):
|
||||||
|
|
||||||
|
* `forward_vector(angles)` → unit vector pointing where the camera looks
|
||||||
|
* `right_vector(angles)` → unit vector pointing to the camera's right
|
||||||
|
* `up_vector(angles)` → unit vector pointing upward relative to the camera
|
||||||
|
|
||||||
|
These are used for movement, aim direction, and building coordinate frames.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rotation & view matrices
|
||||||
|
|
||||||
|
* `rotation_matrix(angles)` → 3×3 (or 4×4) rotation matrix from Euler angles
|
||||||
|
* `calc_view_matrix(angles, origin)` → camera view matrix
|
||||||
|
|
||||||
|
The view matrix transforms world coordinates into camera space (origin at camera, axes aligned with camera orientation).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Perspective projection
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Mat4X4 proj = calc_perspective_projection_matrix(
|
||||||
|
fov_degrees, // vertical field of view (e.g., 90)
|
||||||
|
aspect_ratio, // width / height (e.g., 16/9)
|
||||||
|
near_plane, // e.g., 0.1
|
||||||
|
far_plane // e.g., 1000.0
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Produces a **perspective projection matrix** suitable for 3D rendering pipelines. Combined with the view matrix, this implements the standard camera transform chain.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
// Camera setup
|
||||||
|
ViewAngles angles = {
|
||||||
|
PitchAngle::from_degrees(-15.0f),
|
||||||
|
YawAngle::from_degrees(45.0f),
|
||||||
|
RollAngle::from_degrees(0.0f)
|
||||||
|
};
|
||||||
|
Vector3<float> cam_pos{100.0f, 50.0f, 80.0f};
|
||||||
|
|
||||||
|
// Compute direction
|
||||||
|
auto forward = forward_vector(angles);
|
||||||
|
auto right = right_vector(angles);
|
||||||
|
auto up = up_vector(angles);
|
||||||
|
|
||||||
|
// Build matrices
|
||||||
|
auto view_mat = calc_view_matrix(angles, cam_pos);
|
||||||
|
auto proj_mat = calc_perspective_projection_matrix(90.0f, 16.0f/9.0f, 0.1f, 1000.0f);
|
||||||
|
|
||||||
|
// Use view_mat and proj_mat for rendering...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
* **Angles**: pitch (up/down), yaw (left/right), roll (tilt)
|
||||||
|
* **Pitch**: positive = looking up, negative = looking down
|
||||||
|
* **Yaw**: increases counter-clockwise from the +X axis
|
||||||
|
* **Coordinate system**: Z-up, X-forward, Y-right (negative in code convention)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/source_engine/constants.hpp` — coordinate frame & angle types
|
||||||
|
* `omath/engines/source_engine/traits/camera_trait.hpp` — plug-in for generic `Camera`
|
||||||
|
* `omath/projection/camera.hpp` — generic camera wrapper using these formulas
|
||||||
182
docs/engines/source_engine/mesh_trait.md
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
# `omath::source_engine::MeshTrait` — mesh transformation trait for Source Engine
|
||||||
|
|
||||||
|
> Header: `omath/engines/source_engine/traits/mesh_trait.hpp`
|
||||||
|
> Namespace: `omath::source_engine`
|
||||||
|
> Purpose: provide Source Engine-specific rotation matrix computation for `omath::primitives::Mesh`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`MeshTrait` is a trait class that provides the `rotation_matrix` function for transforming meshes in Source Engine's coordinate system. It serves as a template parameter to `omath::primitives::Mesh`, enabling engine-specific rotation behavior.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate System
|
||||||
|
|
||||||
|
**Source Engine** uses:
|
||||||
|
* **Up axis**: +Z
|
||||||
|
* **Forward axis**: +Y
|
||||||
|
* **Right axis**: +X
|
||||||
|
* **Handedness**: Right-handed
|
||||||
|
* **Rotation order**: Pitch (X) → Yaw (Z) → Roll (Y)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::source_engine {
|
||||||
|
|
||||||
|
class MeshTrait final {
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::source_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Method: `rotation_matrix`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes a 4×4 rotation matrix from Source Engine-style Euler angles.
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
* `rotation` — `ViewAngles` containing pitch, yaw, and roll angles
|
||||||
|
|
||||||
|
**Returns**: 4×4 rotation matrix suitable for mesh transformation
|
||||||
|
|
||||||
|
**Implementation**: Delegates to `source_engine::rotation_matrix(rotation)` defined in `formulas.hpp`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### With Mesh
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
// Create mesh (MeshTrait is used automatically)
|
||||||
|
Mesh my_mesh(vertices, indices);
|
||||||
|
|
||||||
|
// Set rotation using ViewAngles
|
||||||
|
ViewAngles angles;
|
||||||
|
angles.pitch = PitchAngle::from_degrees(30.0f);
|
||||||
|
angles.yaw = YawAngle::from_degrees(45.0f);
|
||||||
|
angles.roll = RollAngle::from_degrees(0.0f);
|
||||||
|
|
||||||
|
my_mesh.set_rotation(angles);
|
||||||
|
|
||||||
|
// The rotation matrix is computed using MeshTrait::rotation_matrix
|
||||||
|
auto matrix = my_mesh.get_to_world_matrix();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Direct Usage
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
ViewAngles angles;
|
||||||
|
angles.pitch = PitchAngle::from_degrees(45.0f);
|
||||||
|
angles.yaw = YawAngle::from_degrees(90.0f);
|
||||||
|
angles.roll = RollAngle::from_degrees(0.0f);
|
||||||
|
|
||||||
|
Mat4X4 rot_matrix = MeshTrait::rotation_matrix(angles);
|
||||||
|
|
||||||
|
// Use the matrix directly
|
||||||
|
Vector3<float> local_point{1, 0, 0};
|
||||||
|
auto rotated = rot_matrix * mat_column_from_vector(local_point);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rotation Conventions
|
||||||
|
|
||||||
|
The rotation matrix is built following Source Engine's conventions:
|
||||||
|
|
||||||
|
1. **Pitch** (rotation around X-axis / right axis)
|
||||||
|
* Positive pitch looks upward (+Z direction)
|
||||||
|
* Range: typically [-89°, 89°]
|
||||||
|
|
||||||
|
2. **Yaw** (rotation around Z-axis / up axis)
|
||||||
|
* Positive yaw rotates counterclockwise when viewed from above
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
3. **Roll** (rotation around Y-axis / forward axis)
|
||||||
|
* Positive roll tilts right
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
**Composition**: The matrices are combined in the order Pitch × Yaw × Roll, producing a rotation that:
|
||||||
|
* First applies roll around the forward axis
|
||||||
|
* Then applies yaw around the up axis
|
||||||
|
* Finally applies pitch around the right axis
|
||||||
|
|
||||||
|
This matches Source Engine's internal rotation order.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Related Functions
|
||||||
|
|
||||||
|
The trait delegates to the formula defined in `formulas.hpp`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
See [Formulas Documentation](formulas.md) for details on the rotation matrix computation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type Alias
|
||||||
|
|
||||||
|
The Source Engine mesh type is pre-defined:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::source_engine {
|
||||||
|
using Mesh = primitives::Mesh<Mat4X4, ViewAngles, MeshTrait, float>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Use this alias to ensure correct trait usage:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
// Correct: uses Source Engine trait
|
||||||
|
Mesh my_mesh(vbo, vao);
|
||||||
|
|
||||||
|
// Avoid: manually specifying template parameters
|
||||||
|
primitives::Mesh<Mat4X4, ViewAngles, MeshTrait, float> verbose_mesh(vbo, vao);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
* **Angle ranges**: Ensure angles are within valid ranges (pitch: [-89°, 89°], yaw/roll: [-180°, 180°])
|
||||||
|
* **Performance**: Matrix computation is O(1) with ~64 floating-point operations
|
||||||
|
* **Caching**: The mesh caches the transformation matrix; recomputed only when rotation changes
|
||||||
|
* **Compatibility**: Works with all Source Engine games (CS:GO, TF2, Portal, Half-Life 2, etc.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Mesh Documentation](../../3d_primitives/mesh.md) - Mesh primitive using this trait
|
||||||
|
- [MeshCollider Documentation](../../collision/mesh_collider.md) - Collision wrapper for meshes
|
||||||
|
- [Formulas Documentation](formulas.md) - Source Engine rotation formula
|
||||||
|
- [CameraTrait Documentation](camera_trait.md) - Camera transformation trait
|
||||||
|
- [Constants Documentation](constants.md) - Source Engine constants
|
||||||
|
- [API Overview](../../api_overview.md) - High-level API reference
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
198
docs/engines/source_engine/pred_engine_trait.md
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
# `omath::source_engine::PredEngineTrait` — projectile prediction trait
|
||||||
|
|
||||||
|
> Header: `omath/engines/source_engine/traits/pred_engine_trait.hpp`
|
||||||
|
> Namespace: `omath::source_engine`
|
||||||
|
> Purpose: provide Source Engine-specific projectile and target prediction for ballistic calculations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`PredEngineTrait` implements engine-specific helpers for **projectile prediction**:
|
||||||
|
|
||||||
|
* `predict_projectile_position` – computes where a projectile will be after `time` seconds
|
||||||
|
* `predict_target_position` – computes where a moving target will be after `time` seconds
|
||||||
|
* `calc_vector_2d_distance` – horizontal distance (X/Y plane, ignoring Z)
|
||||||
|
* `get_vector_height_coordinate` – extracts vertical coordinate (Z in Source Engine)
|
||||||
|
* `calc_viewpoint_from_angles` – computes aim point given pitch angle
|
||||||
|
* `calc_direct_pitch_angle` – pitch angle to look from origin to target
|
||||||
|
* `calc_direct_yaw_angle` – yaw angle to look from origin to target
|
||||||
|
|
||||||
|
These methods satisfy the `PredEngineTraitConcept` required by generic projectile prediction algorithms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::source_engine {
|
||||||
|
|
||||||
|
class PredEngineTrait final {
|
||||||
|
public:
|
||||||
|
// Predict projectile position after `time` seconds
|
||||||
|
static constexpr Vector3<float>
|
||||||
|
predict_projectile_position(const projectile_prediction::Projectile& projectile,
|
||||||
|
float pitch, float yaw, float time,
|
||||||
|
float gravity) noexcept;
|
||||||
|
|
||||||
|
// Predict target position after `time` seconds
|
||||||
|
static constexpr Vector3<float>
|
||||||
|
predict_target_position(const projectile_prediction::Target& target,
|
||||||
|
float time, float gravity) noexcept;
|
||||||
|
|
||||||
|
// Compute horizontal (2D) distance
|
||||||
|
static float
|
||||||
|
calc_vector_2d_distance(const Vector3<float>& delta) noexcept;
|
||||||
|
|
||||||
|
// Get vertical coordinate (Z in Source Engine)
|
||||||
|
static constexpr float
|
||||||
|
get_vector_height_coordinate(const Vector3<float>& vec) noexcept;
|
||||||
|
|
||||||
|
// Compute aim point from angles
|
||||||
|
static Vector3<float>
|
||||||
|
calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile,
|
||||||
|
Vector3<float> predicted_target_position,
|
||||||
|
std::optional<float> projectile_pitch) noexcept;
|
||||||
|
|
||||||
|
// Compute pitch angle to look at target
|
||||||
|
static float
|
||||||
|
calc_direct_pitch_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept;
|
||||||
|
|
||||||
|
// Compute yaw angle to look at target
|
||||||
|
static float
|
||||||
|
calc_direct_yaw_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::source_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Projectile prediction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto pos = PredEngineTrait::predict_projectile_position(
|
||||||
|
projectile, // initial position, speed, gravity scale
|
||||||
|
pitch_deg, // launch pitch (positive = up)
|
||||||
|
yaw_deg, // launch yaw
|
||||||
|
time, // time in seconds
|
||||||
|
gravity // gravity constant (e.g., 800 units/s²)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes:
|
||||||
|
|
||||||
|
1. Forward vector from pitch/yaw (using `forward_vector`)
|
||||||
|
2. Initial velocity: `forward * launch_speed`
|
||||||
|
3. Position after `time`: `origin + velocity*time - 0.5*gravity*gravityScale*time²` (Z component only)
|
||||||
|
|
||||||
|
**Note**: Negative pitch in `forward_vector` convention → positive pitch looks up.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Target prediction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto pos = PredEngineTrait::predict_target_position(
|
||||||
|
target, // position, velocity, airborne flag
|
||||||
|
time, // time in seconds
|
||||||
|
gravity // gravity constant
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Simple linear extrapolation plus gravity if target is airborne:
|
||||||
|
|
||||||
|
```
|
||||||
|
predicted = origin + velocity * time
|
||||||
|
if (airborne)
|
||||||
|
predicted.z -= 0.5 * gravity * time²
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Distance & height helpers
|
||||||
|
|
||||||
|
* `calc_vector_2d_distance(delta)` → `sqrt(delta.x² + delta.y²)` (horizontal distance)
|
||||||
|
* `get_vector_height_coordinate(vec)` → `vec.z` (vertical coordinate in Source Engine)
|
||||||
|
|
||||||
|
Used to compute ballistic arc parameters.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Aim angle calculation
|
||||||
|
|
||||||
|
* `calc_direct_pitch_angle(origin, target)` → pitch in degrees to look from `origin` to `target`
|
||||||
|
- Formula: `asin(Δz / distance)` converted to degrees
|
||||||
|
- Positive = looking up, negative = looking down
|
||||||
|
|
||||||
|
* `calc_direct_yaw_angle(origin, target)` → yaw in degrees to look from `origin` to `target`
|
||||||
|
- Formula: `atan2(Δy, Δx)` converted to degrees
|
||||||
|
- Horizontal rotation around Z-axis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Viewpoint from angles
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto aim_point = PredEngineTrait::calc_viewpoint_from_angles(
|
||||||
|
projectile,
|
||||||
|
predicted_target_pos,
|
||||||
|
optional_pitch_deg
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes where to aim in 3D space given a desired pitch angle. Uses horizontal distance and `tan(pitch)` to compute height offset.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
* **Coordinate system**: Z-up (height increases with Z)
|
||||||
|
* **Angles**: pitch in [-89°, +89°], yaw in [-180°, +180°]
|
||||||
|
* **Gravity**: applied downward along -Z axis
|
||||||
|
* **Pitch convention**: +89° = straight up, -89° = straight down
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
using namespace omath::projectile_prediction;
|
||||||
|
|
||||||
|
Projectile proj{
|
||||||
|
.m_origin = {0, 0, 100},
|
||||||
|
.m_launch_speed = 1000.0f,
|
||||||
|
.m_gravity_scale = 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
Target tgt{
|
||||||
|
.m_origin = {500, 200, 100},
|
||||||
|
.m_velocity = {10, 5, 0},
|
||||||
|
.m_is_airborne = false
|
||||||
|
};
|
||||||
|
|
||||||
|
float gravity = 800.0f;
|
||||||
|
float time = 0.5f;
|
||||||
|
|
||||||
|
// Predict where target will be
|
||||||
|
auto target_pos = PredEngineTrait::predict_target_position(tgt, time, gravity);
|
||||||
|
|
||||||
|
// Compute aim angles
|
||||||
|
float pitch = PredEngineTrait::calc_direct_pitch_angle(proj.m_origin, target_pos);
|
||||||
|
float yaw = PredEngineTrait::calc_direct_yaw_angle(proj.m_origin, target_pos);
|
||||||
|
|
||||||
|
// Predict projectile position with those angles
|
||||||
|
auto proj_pos = PredEngineTrait::predict_projectile_position(proj, pitch, yaw, time, gravity);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/source_engine/formulas.hpp` — direction vectors and matrix builders
|
||||||
|
* `omath/projectile_prediction/projectile.hpp` — `Projectile` struct
|
||||||
|
* `omath/projectile_prediction/target.hpp` — `Target` struct
|
||||||
|
* Generic projectile prediction algorithms that use `PredEngineTraitConcept`
|
||||||
109
docs/engines/unity_engine/camera_trait.md
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# `omath::unity_engine::CameraTrait` — plug-in trait for `projection::Camera`
|
||||||
|
|
||||||
|
> Header: `omath/engines/unity_engine/traits/camera_trait.hpp` • Impl: `omath/engines/unity_engine/traits/camera_trait.cpp`
|
||||||
|
> Namespace: `omath::unity_engine`
|
||||||
|
> Purpose: provide Unity Engine-style **look-at**, **view**, and **projection** math to the generic `omath::projection::Camera` (satisfies `CameraEngineConcept`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`CameraTrait` exposes three `static` functions:
|
||||||
|
|
||||||
|
* `calc_look_at_angle(origin, look_at)` – computes Euler angles so the camera at `origin` looks at `look_at`. Implementation normalizes the direction, computes **pitch** as `asin(dir.y)` and **yaw** as `atan2(dir.x, dir.z)`; **roll** is `0`. Pitch/yaw are returned using the project's strong angle types (`PitchAngle`, `YawAngle`, `RollAngle`).
|
||||||
|
* `calc_view_matrix(angles, origin)` – delegates to Unity Engine formulas `unity_engine::calc_view_matrix`, producing a `Mat4X4` view matrix for the given angles and origin.
|
||||||
|
* `calc_projection_matrix(fov, viewport, near, far)` – builds a perspective projection by calling `calc_perspective_projection_matrix(fov_degrees, aspect, near, far)`, where `aspect = viewport.aspect_ratio()`. Accepts `FieldOfView` (degrees).
|
||||||
|
|
||||||
|
The trait's types (`ViewAngles`, `Mat4X4`, angle aliases) and helpers live in the Unity Engine math headers included by the trait (`formulas.hpp`) and the shared projection header (`projection/camera.hpp`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unity_engine {
|
||||||
|
|
||||||
|
class CameraTrait final {
|
||||||
|
public:
|
||||||
|
// Compute Euler angles (pitch/yaw/roll) to look from cam_origin to look_at.
|
||||||
|
static ViewAngles
|
||||||
|
calc_look_at_angle(const Vector3<float>& cam_origin,
|
||||||
|
const Vector3<float>& look_at) noexcept;
|
||||||
|
|
||||||
|
// Build view matrix for given angles and origin.
|
||||||
|
static Mat4X4
|
||||||
|
calc_view_matrix(const ViewAngles& angles,
|
||||||
|
const Vector3<float>& cam_origin) noexcept;
|
||||||
|
|
||||||
|
// Build perspective projection from FOV (deg), viewport, near/far.
|
||||||
|
static Mat4X4
|
||||||
|
calc_projection_matrix(const projection::FieldOfView& fov,
|
||||||
|
const projection::ViewPort& view_port,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::unity_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
Uses: `Vector3<float>`, `ViewAngles` (pitch/yaw/roll), `Mat4X4`, `projection::FieldOfView`, `projection::ViewPort`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Behavior & conventions
|
||||||
|
|
||||||
|
* **Angles from look-at** (Y-up coordinate system):
|
||||||
|
|
||||||
|
```
|
||||||
|
dir = normalize(look_at - origin)
|
||||||
|
pitch = asin(dir.y) // +Y is up
|
||||||
|
yaw = atan2(dir.x, dir.z) // horizontal rotation
|
||||||
|
roll = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Returned as `PitchAngle::from_radians(...)`, `YawAngle::from_radians(...)`, etc.
|
||||||
|
|
||||||
|
* **View matrix**: built by the Unity Engine helper `unity_engine::calc_view_matrix(angles, origin)` to match the engine's handedness and axis conventions.
|
||||||
|
|
||||||
|
* **Projection**: uses `calc_perspective_projection_matrix(fov.as_degrees(), viewport.aspect_ratio(), near, far)`. Pass your **vertical FOV** in degrees via `FieldOfView`; the helper computes a standard perspective matrix.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Using with `projection::Camera`
|
||||||
|
|
||||||
|
Create a camera whose math is driven by this trait:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Mat4 = Mat4X4; // from Unity Engine math headers
|
||||||
|
using Angs = ViewAngles; // pitch/yaw/roll type
|
||||||
|
using UEcam = omath::projection::Camera<Mat4, Angs, omath::unity_engine::CameraTrait>;
|
||||||
|
|
||||||
|
omath::projection::ViewPort vp{1920.f, 1080.f};
|
||||||
|
auto fov = omath::projection::FieldOfView::from_degrees(60.f);
|
||||||
|
|
||||||
|
UEcam cam(
|
||||||
|
/*position*/ {10.f, 5.f, -10.f},
|
||||||
|
/*angles*/ omath::unity_engine::CameraTrait::calc_look_at_angle({10,5,-10},{0,5,0}),
|
||||||
|
/*viewport*/ vp,
|
||||||
|
/*fov*/ fov,
|
||||||
|
/*near*/ 0.3f,
|
||||||
|
/*far*/ 1000.f
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
This satisfies `CameraEngineConcept` expected by `projection::Camera` (look-at, view, projection) as declared in the trait header.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & tips
|
||||||
|
|
||||||
|
* Ensure your `ViewAngles` aliases (`PitchAngle`, `YawAngle`, `RollAngle`) match the project's angle policy (ranges/normalization). The implementation constructs them **from radians**.
|
||||||
|
* `aspect_ratio()` is taken directly from `ViewPort` (`width / height`), so keep both positive and non-zero.
|
||||||
|
* `near` must be > 0 and `< far` for a valid projection matrix (enforced by your math helpers).
|
||||||
|
* Unity Engine uses **Y-up**: pitch angles control vertical look, positive = up.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* Unity Engine math helpers in `omath/engines/unity_engine/formulas.hpp` (view/projection builders used above).
|
||||||
|
* Generic camera wrapper `omath::projection::Camera` and its `CameraEngineConcept` (this trait is designed to plug straight into it).
|
||||||
77
docs/engines/unity_engine/constants.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# `omath::unity_engine` — types & constants
|
||||||
|
|
||||||
|
> Header: `omath/engines/unity_engine/constants.hpp`
|
||||||
|
> Namespace: `omath::unity_engine`
|
||||||
|
> Purpose: define Unity Engine coordinate system, matrix types, and angle ranges
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The **Unity Engine** uses a **Y-up, left-handed** coordinate system:
|
||||||
|
|
||||||
|
* **Up** = `{0, 1, 0}` (Y-axis)
|
||||||
|
* **Right** = `{1, 0, 0}` (X-axis)
|
||||||
|
* **Forward** = `{0, 0, 1}` (Z-axis)
|
||||||
|
|
||||||
|
Matrices are **row-major**. Angles are **clamped pitch** (±90°) and **normalized yaw/roll** (±180°).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constants
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unity_engine {
|
||||||
|
constexpr Vector3<float> k_abs_up = {0, 1, 0};
|
||||||
|
constexpr Vector3<float> k_abs_right = {1, 0, 0};
|
||||||
|
constexpr Vector3<float> k_abs_forward = {0, 0, 1};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
These basis vectors define the engine's **world coordinate frame**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Matrix types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Mat4X4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
using Mat3X3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
using Mat1X3 = Mat<1, 3, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Row-major** storage means rows are contiguous in memory. Suitable for CPU-side transforms and typical C++ math libraries.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Angle types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using PitchAngle = Angle<float, -90.f, 90.f, AngleFlags::Clamped>;
|
||||||
|
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||||
|
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||||
|
|
||||||
|
using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
|
||||||
|
```
|
||||||
|
|
||||||
|
* **PitchAngle**: clamped to **[-90°, +90°]** (looking down vs. up)
|
||||||
|
* **YawAngle**: normalized to **[-180°, +180°]** (horizontal rotation)
|
||||||
|
* **RollAngle**: normalized to **[-180°, +180°]** (camera roll)
|
||||||
|
|
||||||
|
`ViewAngles` bundles all three into a single type for camera/view transforms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate system notes
|
||||||
|
|
||||||
|
* **Y-up**: gravity points along `-Y`, height increases with `+Y`
|
||||||
|
* **Left-handed**: cross product `forward × right = up` with left-hand rule
|
||||||
|
* This matches **Unity Engine** conventions for 3D games and simulations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/unity_engine/formulas.hpp` — view/projection matrix builders
|
||||||
|
* `omath/trigonometry/angle.hpp` — angle normalization & clamping helpers
|
||||||
|
* `omath/trigonometry/view_angles.hpp` — generic pitch/yaw/roll wrapper
|
||||||
135
docs/engines/unity_engine/formulas.md
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
# `omath::unity_engine` — formulas & matrix helpers
|
||||||
|
|
||||||
|
> Header: `omath/engines/unity_engine/formulas.hpp`
|
||||||
|
> Namespace: `omath::unity_engine`
|
||||||
|
> Purpose: compute direction vectors, rotation matrices, view matrices, and perspective projections for Unity Engine
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
This header provides **Unity Engine**-specific math for:
|
||||||
|
|
||||||
|
* **Direction vectors** (`forward`, `right`, `up`) from `ViewAngles`
|
||||||
|
* **Rotation matrices** from Euler angles
|
||||||
|
* **View matrices** (camera transforms)
|
||||||
|
* **Perspective projection** matrices
|
||||||
|
|
||||||
|
All functions respect Unity Engine's **Y-up, left-handed** coordinate system.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unity_engine {
|
||||||
|
|
||||||
|
// Compute forward direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> forward_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Compute right direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> right_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Compute up direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> up_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Build 3x3 rotation matrix from angles
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Build view matrix (camera space transform)
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 calc_view_matrix(const ViewAngles& angles,
|
||||||
|
const Vector3<float>& cam_origin) noexcept;
|
||||||
|
|
||||||
|
// Build perspective projection matrix
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 calc_perspective_projection_matrix(float field_of_view,
|
||||||
|
float aspect_ratio,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
|
||||||
|
} // namespace omath::unity_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Direction vectors
|
||||||
|
|
||||||
|
Given camera angles (pitch/yaw/roll):
|
||||||
|
|
||||||
|
* `forward_vector(angles)` → unit vector pointing where the camera looks
|
||||||
|
* `right_vector(angles)` → unit vector pointing to the camera's right
|
||||||
|
* `up_vector(angles)` → unit vector pointing upward relative to the camera
|
||||||
|
|
||||||
|
These are used for movement, aim direction, and building coordinate frames.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rotation & view matrices
|
||||||
|
|
||||||
|
* `rotation_matrix(angles)` → 3×3 (or 4×4) rotation matrix from Euler angles
|
||||||
|
* `calc_view_matrix(angles, origin)` → camera view matrix
|
||||||
|
|
||||||
|
The view matrix transforms world coordinates into camera space (origin at camera, axes aligned with camera orientation).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Perspective projection
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Mat4X4 proj = calc_perspective_projection_matrix(
|
||||||
|
fov_degrees, // vertical field of view (e.g., 60)
|
||||||
|
aspect_ratio, // width / height (e.g., 16/9)
|
||||||
|
near_plane, // e.g., 0.3
|
||||||
|
far_plane // e.g., 1000.0
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Produces a **perspective projection matrix** suitable for 3D rendering pipelines. Combined with the view matrix, this implements the standard camera transform chain.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::unity_engine;
|
||||||
|
|
||||||
|
// Camera setup
|
||||||
|
ViewAngles angles = {
|
||||||
|
PitchAngle::from_degrees(-15.0f),
|
||||||
|
YawAngle::from_degrees(45.0f),
|
||||||
|
RollAngle::from_degrees(0.0f)
|
||||||
|
};
|
||||||
|
Vector3<float> cam_pos{10.0f, 5.0f, -10.0f};
|
||||||
|
|
||||||
|
// Compute direction
|
||||||
|
auto forward = forward_vector(angles);
|
||||||
|
auto right = right_vector(angles);
|
||||||
|
auto up = up_vector(angles);
|
||||||
|
|
||||||
|
// Build matrices
|
||||||
|
auto view_mat = calc_view_matrix(angles, cam_pos);
|
||||||
|
auto proj_mat = calc_perspective_projection_matrix(60.0f, 16.0f/9.0f, 0.3f, 1000.0f);
|
||||||
|
|
||||||
|
// Use view_mat and proj_mat for rendering...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
* **Angles**: pitch (up/down), yaw (left/right), roll (tilt)
|
||||||
|
* **Pitch**: positive = looking up, negative = looking down
|
||||||
|
* **Yaw**: increases counter-clockwise from the +Z axis
|
||||||
|
* **Coordinate system**: Y-up, Z-forward, X-right (left-handed)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/unity_engine/constants.hpp` — coordinate frame & angle types
|
||||||
|
* `omath/engines/unity_engine/traits/camera_trait.hpp` — plug-in for generic `Camera`
|
||||||
|
* `omath/projection/camera.hpp` — generic camera wrapper using these formulas
|
||||||
119
docs/engines/unity_engine/mesh_trait.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# `omath::unity_engine::MeshTrait` — mesh transformation trait for Unity Engine
|
||||||
|
|
||||||
|
> Header: `omath/engines/unity_engine/traits/mesh_trait.hpp`
|
||||||
|
> Namespace: `omath::unity_engine`
|
||||||
|
> Purpose: provide Unity Engine-specific rotation matrix computation for `omath::primitives::Mesh`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`MeshTrait` is a trait class that provides the `rotation_matrix` function for transforming meshes in Unity's coordinate system. It serves as a template parameter to `omath::primitives::Mesh`, enabling engine-specific rotation behavior.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate System
|
||||||
|
|
||||||
|
**Unity Engine** uses:
|
||||||
|
* **Up axis**: +Y
|
||||||
|
* **Forward axis**: +Z
|
||||||
|
* **Right axis**: +X
|
||||||
|
* **Handedness**: Left-handed
|
||||||
|
* **Rotation order**: Pitch (X) → Yaw (Y) → Roll (Z)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unity_engine {
|
||||||
|
|
||||||
|
class MeshTrait final {
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::unity_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Method: `rotation_matrix`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes a 4×4 rotation matrix from Unity-style Euler angles.
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
* `rotation` — `ViewAngles` containing pitch, yaw, and roll angles
|
||||||
|
|
||||||
|
**Returns**: 4×4 rotation matrix suitable for mesh transformation
|
||||||
|
|
||||||
|
**Implementation**: Delegates to `unity_engine::rotation_matrix(rotation)` defined in `formulas.hpp`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### With Mesh
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::unity_engine;
|
||||||
|
|
||||||
|
// Create mesh (MeshTrait is used automatically)
|
||||||
|
Mesh my_mesh(vertices, indices);
|
||||||
|
|
||||||
|
// Set rotation using ViewAngles
|
||||||
|
ViewAngles angles;
|
||||||
|
angles.pitch = PitchAngle::from_degrees(30.0f);
|
||||||
|
angles.yaw = YawAngle::from_degrees(45.0f);
|
||||||
|
angles.roll = RollAngle::from_degrees(0.0f);
|
||||||
|
|
||||||
|
my_mesh.set_rotation(angles);
|
||||||
|
|
||||||
|
// The rotation matrix is computed using MeshTrait::rotation_matrix
|
||||||
|
auto matrix = my_mesh.get_to_world_matrix();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rotation Conventions
|
||||||
|
|
||||||
|
Unity uses a left-handed coordinate system with Y-up:
|
||||||
|
|
||||||
|
1. **Pitch** (rotation around X-axis / right axis)
|
||||||
|
* Positive pitch looks upward (+Y direction)
|
||||||
|
* Range: typically [-89°, 89°]
|
||||||
|
|
||||||
|
2. **Yaw** (rotation around Y-axis / up axis)
|
||||||
|
* Positive yaw rotates clockwise when viewed from above (left-handed)
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
3. **Roll** (rotation around Z-axis / forward axis)
|
||||||
|
* Positive roll tilts right
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type Alias
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unity_engine {
|
||||||
|
using Mesh = primitives::Mesh<Mat4X4, ViewAngles, MeshTrait, float>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Mesh Documentation](../../3d_primitives/mesh.md) - Mesh primitive
|
||||||
|
- [Formulas Documentation](formulas.md) - Unity rotation formula
|
||||||
|
- [CameraTrait Documentation](camera_trait.md) - Camera trait
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
198
docs/engines/unity_engine/pred_engine_trait.md
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
# `omath::unity_engine::PredEngineTrait` — projectile prediction trait
|
||||||
|
|
||||||
|
> Header: `omath/engines/unity_engine/traits/pred_engine_trait.hpp`
|
||||||
|
> Namespace: `omath::unity_engine`
|
||||||
|
> Purpose: provide Unity Engine-specific projectile and target prediction for ballistic calculations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`PredEngineTrait` implements engine-specific helpers for **projectile prediction**:
|
||||||
|
|
||||||
|
* `predict_projectile_position` – computes where a projectile will be after `time` seconds
|
||||||
|
* `predict_target_position` – computes where a moving target will be after `time` seconds
|
||||||
|
* `calc_vector_2d_distance` – horizontal distance (X/Z plane, ignoring Y)
|
||||||
|
* `get_vector_height_coordinate` – extracts vertical coordinate (Y in Unity Engine)
|
||||||
|
* `calc_viewpoint_from_angles` – computes aim point given pitch angle
|
||||||
|
* `calc_direct_pitch_angle` – pitch angle to look from origin to target
|
||||||
|
* `calc_direct_yaw_angle` – yaw angle to look from origin to target
|
||||||
|
|
||||||
|
These methods satisfy the `PredEngineTraitConcept` required by generic projectile prediction algorithms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unity_engine {
|
||||||
|
|
||||||
|
class PredEngineTrait final {
|
||||||
|
public:
|
||||||
|
// Predict projectile position after `time` seconds
|
||||||
|
static constexpr Vector3<float>
|
||||||
|
predict_projectile_position(const projectile_prediction::Projectile& projectile,
|
||||||
|
float pitch, float yaw, float time,
|
||||||
|
float gravity) noexcept;
|
||||||
|
|
||||||
|
// Predict target position after `time` seconds
|
||||||
|
static constexpr Vector3<float>
|
||||||
|
predict_target_position(const projectile_prediction::Target& target,
|
||||||
|
float time, float gravity) noexcept;
|
||||||
|
|
||||||
|
// Compute horizontal (2D) distance
|
||||||
|
static float
|
||||||
|
calc_vector_2d_distance(const Vector3<float>& delta) noexcept;
|
||||||
|
|
||||||
|
// Get vertical coordinate (Y in Unity Engine)
|
||||||
|
static constexpr float
|
||||||
|
get_vector_height_coordinate(const Vector3<float>& vec) noexcept;
|
||||||
|
|
||||||
|
// Compute aim point from angles
|
||||||
|
static Vector3<float>
|
||||||
|
calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile,
|
||||||
|
Vector3<float> predicted_target_position,
|
||||||
|
std::optional<float> projectile_pitch) noexcept;
|
||||||
|
|
||||||
|
// Compute pitch angle to look at target
|
||||||
|
static float
|
||||||
|
calc_direct_pitch_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept;
|
||||||
|
|
||||||
|
// Compute yaw angle to look at target
|
||||||
|
static float
|
||||||
|
calc_direct_yaw_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::unity_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Projectile prediction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto pos = PredEngineTrait::predict_projectile_position(
|
||||||
|
projectile, // initial position, speed, gravity scale
|
||||||
|
pitch_deg, // launch pitch (positive = up)
|
||||||
|
yaw_deg, // launch yaw
|
||||||
|
time, // time in seconds
|
||||||
|
gravity // gravity constant (e.g., 9.81 m/s²)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes:
|
||||||
|
|
||||||
|
1. Forward vector from pitch/yaw (using `forward_vector`)
|
||||||
|
2. Initial velocity: `forward * launch_speed`
|
||||||
|
3. Position after `time`: `origin + velocity*time - 0.5*gravity*gravityScale*time²` (Y component only)
|
||||||
|
|
||||||
|
**Note**: Negative pitch in `forward_vector` convention → positive pitch looks up.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Target prediction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto pos = PredEngineTrait::predict_target_position(
|
||||||
|
target, // position, velocity, airborne flag
|
||||||
|
time, // time in seconds
|
||||||
|
gravity // gravity constant
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Simple linear extrapolation plus gravity if target is airborne:
|
||||||
|
|
||||||
|
```
|
||||||
|
predicted = origin + velocity * time
|
||||||
|
if (airborne)
|
||||||
|
predicted.y -= 0.5 * gravity * time²
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Distance & height helpers
|
||||||
|
|
||||||
|
* `calc_vector_2d_distance(delta)` → `sqrt(delta.x² + delta.z²)` (horizontal distance)
|
||||||
|
* `get_vector_height_coordinate(vec)` → `vec.y` (vertical coordinate in Unity Engine)
|
||||||
|
|
||||||
|
Used to compute ballistic arc parameters.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Aim angle calculation
|
||||||
|
|
||||||
|
* `calc_direct_pitch_angle(origin, target)` → pitch in degrees to look from `origin` to `target`
|
||||||
|
- Formula: `asin(Δy / distance)` converted to degrees (direction normalized first)
|
||||||
|
- Positive = looking up, negative = looking down
|
||||||
|
|
||||||
|
* `calc_direct_yaw_angle(origin, target)` → yaw in degrees to look from `origin` to `target`
|
||||||
|
- Formula: `atan2(Δx, Δz)` converted to degrees (direction normalized first)
|
||||||
|
- Horizontal rotation around Y-axis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Viewpoint from angles
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto aim_point = PredEngineTrait::calc_viewpoint_from_angles(
|
||||||
|
projectile,
|
||||||
|
predicted_target_pos,
|
||||||
|
optional_pitch_deg
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes where to aim in 3D space given a desired pitch angle. Uses horizontal distance and `tan(pitch)` to compute height offset. Result has adjusted Y coordinate.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
* **Coordinate system**: Y-up (height increases with Y)
|
||||||
|
* **Angles**: pitch in [-90°, +90°], yaw in [-180°, +180°]
|
||||||
|
* **Gravity**: applied downward along -Y axis
|
||||||
|
* **Pitch convention**: +90° = straight up, -90° = straight down
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::unity_engine;
|
||||||
|
using namespace omath::projectile_prediction;
|
||||||
|
|
||||||
|
Projectile proj{
|
||||||
|
.m_origin = {0, 2, 0},
|
||||||
|
.m_launch_speed = 50.0f,
|
||||||
|
.m_gravity_scale = 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
Target tgt{
|
||||||
|
.m_origin = {20, 2, 15},
|
||||||
|
.m_velocity = {1, 0, 0.5f},
|
||||||
|
.m_is_airborne = false
|
||||||
|
};
|
||||||
|
|
||||||
|
float gravity = 9.81f;
|
||||||
|
float time = 0.5f;
|
||||||
|
|
||||||
|
// Predict where target will be
|
||||||
|
auto target_pos = PredEngineTrait::predict_target_position(tgt, time, gravity);
|
||||||
|
|
||||||
|
// Compute aim angles
|
||||||
|
float pitch = PredEngineTrait::calc_direct_pitch_angle(proj.m_origin, target_pos);
|
||||||
|
float yaw = PredEngineTrait::calc_direct_yaw_angle(proj.m_origin, target_pos);
|
||||||
|
|
||||||
|
// Predict projectile position with those angles
|
||||||
|
auto proj_pos = PredEngineTrait::predict_projectile_position(proj, pitch, yaw, time, gravity);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/unity_engine/formulas.hpp` — direction vectors and matrix builders
|
||||||
|
* `omath/projectile_prediction/projectile.hpp` — `Projectile` struct
|
||||||
|
* `omath/projectile_prediction/target.hpp` — `Target` struct
|
||||||
|
* Generic projectile prediction algorithms that use `PredEngineTraitConcept`
|
||||||
109
docs/engines/unreal_engine/camera_trait.md
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# `omath::unreal_engine::CameraTrait` — plug-in trait for `projection::Camera`
|
||||||
|
|
||||||
|
> Header: `omath/engines/unreal_engine/traits/camera_trait.hpp` • Impl: `omath/engines/unreal_engine/traits/camera_trait.cpp`
|
||||||
|
> Namespace: `omath::unreal_engine`
|
||||||
|
> Purpose: provide Unreal Engine-style **look-at**, **view**, and **projection** math to the generic `omath::projection::Camera` (satisfies `CameraEngineConcept`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`CameraTrait` exposes three `static` functions:
|
||||||
|
|
||||||
|
* `calc_look_at_angle(origin, look_at)` – computes Euler angles so the camera at `origin` looks at `look_at`. Implementation normalizes the direction, computes **pitch** as `asin(dir.z)` and **yaw** as `atan2(dir.y, dir.x)`; **roll** is `0`. Pitch/yaw are returned using the project's strong angle types (`PitchAngle`, `YawAngle`, `RollAngle`).
|
||||||
|
* `calc_view_matrix(angles, origin)` – delegates to Unreal Engine formulas `unreal_engine::calc_view_matrix`, producing a `Mat4X4` view matrix for the given angles and origin.
|
||||||
|
* `calc_projection_matrix(fov, viewport, near, far)` – builds a perspective projection by calling `calc_perspective_projection_matrix(fov_degrees, aspect, near, far)`, where `aspect = viewport.aspect_ratio()`. Accepts `FieldOfView` (degrees).
|
||||||
|
|
||||||
|
The trait's types (`ViewAngles`, `Mat4X4`, angle aliases) and helpers live in the Unreal Engine math headers included by the trait (`formulas.hpp`) and the shared projection header (`projection/camera.hpp`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unreal_engine {
|
||||||
|
|
||||||
|
class CameraTrait final {
|
||||||
|
public:
|
||||||
|
// Compute Euler angles (pitch/yaw/roll) to look from cam_origin to look_at.
|
||||||
|
static ViewAngles
|
||||||
|
calc_look_at_angle(const Vector3<float>& cam_origin,
|
||||||
|
const Vector3<float>& look_at) noexcept;
|
||||||
|
|
||||||
|
// Build view matrix for given angles and origin.
|
||||||
|
static Mat4X4
|
||||||
|
calc_view_matrix(const ViewAngles& angles,
|
||||||
|
const Vector3<float>& cam_origin) noexcept;
|
||||||
|
|
||||||
|
// Build perspective projection from FOV (deg), viewport, near/far.
|
||||||
|
static Mat4X4
|
||||||
|
calc_projection_matrix(const projection::FieldOfView& fov,
|
||||||
|
const projection::ViewPort& view_port,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::unreal_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
Uses: `Vector3<float>`, `ViewAngles` (pitch/yaw/roll), `Mat4X4`, `projection::FieldOfView`, `projection::ViewPort`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Behavior & conventions
|
||||||
|
|
||||||
|
* **Angles from look-at** (Z-up coordinate system):
|
||||||
|
|
||||||
|
```
|
||||||
|
dir = normalize(look_at - origin)
|
||||||
|
pitch = asin(dir.z) // +Z is up
|
||||||
|
yaw = atan2(dir.y, dir.x) // horizontal rotation
|
||||||
|
roll = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Returned as `PitchAngle::from_radians(...)`, `YawAngle::from_radians(...)`, etc.
|
||||||
|
|
||||||
|
* **View matrix**: built by the Unreal Engine helper `unreal_engine::calc_view_matrix(angles, origin)` to match the engine's handedness and axis conventions.
|
||||||
|
|
||||||
|
* **Projection**: uses `calc_perspective_projection_matrix(fov.as_degrees(), viewport.aspect_ratio(), near, far)`. Pass your **vertical FOV** in degrees via `FieldOfView`; the helper computes a standard perspective matrix.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Using with `projection::Camera`
|
||||||
|
|
||||||
|
Create a camera whose math is driven by this trait:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Mat4 = Mat4X4; // from Unreal Engine math headers
|
||||||
|
using Angs = ViewAngles; // pitch/yaw/roll type
|
||||||
|
using UEcam = omath::projection::Camera<Mat4, Angs, omath::unreal_engine::CameraTrait>;
|
||||||
|
|
||||||
|
omath::projection::ViewPort vp{1920.f, 1080.f};
|
||||||
|
auto fov = omath::projection::FieldOfView::from_degrees(90.f);
|
||||||
|
|
||||||
|
UEcam cam(
|
||||||
|
/*position*/ {1000.f, 500.f, 200.f},
|
||||||
|
/*angles*/ omath::unreal_engine::CameraTrait::calc_look_at_angle({1000,500,200},{0,0,200}),
|
||||||
|
/*viewport*/ vp,
|
||||||
|
/*fov*/ fov,
|
||||||
|
/*near*/ 10.f,
|
||||||
|
/*far*/ 100000.f
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
This satisfies `CameraEngineConcept` expected by `projection::Camera` (look-at, view, projection) as declared in the trait header.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & tips
|
||||||
|
|
||||||
|
* Ensure your `ViewAngles` aliases (`PitchAngle`, `YawAngle`, `RollAngle`) match the project's angle policy (ranges/normalization). The implementation constructs them **from radians**.
|
||||||
|
* `aspect_ratio()` is taken directly from `ViewPort` (`width / height`), so keep both positive and non-zero.
|
||||||
|
* `near` must be > 0 and `< far` for a valid projection matrix (enforced by your math helpers).
|
||||||
|
* Unreal Engine uses **Z-up**: pitch angles control vertical look, positive = up.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* Unreal Engine math helpers in `omath/engines/unreal_engine/formulas.hpp` (view/projection builders used above).
|
||||||
|
* Generic camera wrapper `omath::projection::Camera` and its `CameraEngineConcept` (this trait is designed to plug straight into it).
|
||||||
77
docs/engines/unreal_engine/constants.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# `omath::unreal_engine` — types & constants
|
||||||
|
|
||||||
|
> Header: `omath/engines/unreal_engine/constants.hpp`
|
||||||
|
> Namespace: `omath::unreal_engine`
|
||||||
|
> Purpose: define Unreal Engine coordinate system, matrix types, and angle ranges
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The **Unreal Engine** uses a **Z-up, left-handed** coordinate system:
|
||||||
|
|
||||||
|
* **Up** = `{0, 0, 1}` (Z-axis)
|
||||||
|
* **Right** = `{0, 1, 0}` (Y-axis)
|
||||||
|
* **Forward** = `{1, 0, 0}` (X-axis)
|
||||||
|
|
||||||
|
Matrices are **row-major**. Angles are **clamped pitch** (±90°) and **normalized yaw/roll** (±180°).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constants
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unreal_engine {
|
||||||
|
constexpr Vector3<float> k_abs_up = {0, 0, 1};
|
||||||
|
constexpr Vector3<float> k_abs_right = {0, 1, 0};
|
||||||
|
constexpr Vector3<float> k_abs_forward = {1, 0, 0};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
These basis vectors define the engine's **world coordinate frame**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Matrix types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using Mat4X4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
using Mat3X3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
using Mat1X3 = Mat<1, 3, float, MatStoreType::ROW_MAJOR>;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Row-major** storage means rows are contiguous in memory. Suitable for CPU-side transforms and typical C++ math libraries.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Angle types
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using PitchAngle = Angle<float, -90.f, 90.f, AngleFlags::Clamped>;
|
||||||
|
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||||
|
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||||
|
|
||||||
|
using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
|
||||||
|
```
|
||||||
|
|
||||||
|
* **PitchAngle**: clamped to **[-90°, +90°]** (looking down vs. up)
|
||||||
|
* **YawAngle**: normalized to **[-180°, +180°]** (horizontal rotation)
|
||||||
|
* **RollAngle**: normalized to **[-180°, +180°]** (camera roll)
|
||||||
|
|
||||||
|
`ViewAngles` bundles all three into a single type for camera/view transforms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate system notes
|
||||||
|
|
||||||
|
* **Z-up**: gravity points along `-Z`, height increases with `+Z`
|
||||||
|
* **Left-handed**: cross product `forward × right = up` with left-hand rule
|
||||||
|
* This matches **Unreal Engine** conventions for 3D games and simulations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/unreal_engine/formulas.hpp` — view/projection matrix builders
|
||||||
|
* `omath/trigonometry/angle.hpp` — angle normalization & clamping helpers
|
||||||
|
* `omath/trigonometry/view_angles.hpp` — generic pitch/yaw/roll wrapper
|
||||||
135
docs/engines/unreal_engine/formulas.md
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
# `omath::unreal_engine` — formulas & matrix helpers
|
||||||
|
|
||||||
|
> Header: `omath/engines/unreal_engine/formulas.hpp`
|
||||||
|
> Namespace: `omath::unreal_engine`
|
||||||
|
> Purpose: compute direction vectors, rotation matrices, view matrices, and perspective projections for Unreal Engine
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
This header provides **Unreal Engine**-specific math for:
|
||||||
|
|
||||||
|
* **Direction vectors** (`forward`, `right`, `up`) from `ViewAngles`
|
||||||
|
* **Rotation matrices** from Euler angles
|
||||||
|
* **View matrices** (camera transforms)
|
||||||
|
* **Perspective projection** matrices
|
||||||
|
|
||||||
|
All functions respect Unreal Engine's **Z-up, left-handed** coordinate system.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unreal_engine {
|
||||||
|
|
||||||
|
// Compute forward direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> forward_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Compute right direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> right_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Compute up direction from pitch/yaw/roll
|
||||||
|
[[nodiscard]]
|
||||||
|
Vector3<float> up_vector(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Build 3x3 rotation matrix from angles
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept;
|
||||||
|
|
||||||
|
// Build view matrix (camera space transform)
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 calc_view_matrix(const ViewAngles& angles,
|
||||||
|
const Vector3<float>& cam_origin) noexcept;
|
||||||
|
|
||||||
|
// Build perspective projection matrix
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat4X4 calc_perspective_projection_matrix(float field_of_view,
|
||||||
|
float aspect_ratio,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
|
||||||
|
} // namespace omath::unreal_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Direction vectors
|
||||||
|
|
||||||
|
Given camera angles (pitch/yaw/roll):
|
||||||
|
|
||||||
|
* `forward_vector(angles)` → unit vector pointing where the camera looks
|
||||||
|
* `right_vector(angles)` → unit vector pointing to the camera's right
|
||||||
|
* `up_vector(angles)` → unit vector pointing upward relative to the camera
|
||||||
|
|
||||||
|
These are used for movement, aim direction, and building coordinate frames.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rotation & view matrices
|
||||||
|
|
||||||
|
* `rotation_matrix(angles)` → 3×3 (or 4×4) rotation matrix from Euler angles
|
||||||
|
* `calc_view_matrix(angles, origin)` → camera view matrix
|
||||||
|
|
||||||
|
The view matrix transforms world coordinates into camera space (origin at camera, axes aligned with camera orientation).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Perspective projection
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Mat4X4 proj = calc_perspective_projection_matrix(
|
||||||
|
fov_degrees, // vertical field of view (e.g., 90)
|
||||||
|
aspect_ratio, // width / height (e.g., 16/9)
|
||||||
|
near_plane, // e.g., 10.0
|
||||||
|
far_plane // e.g., 100000.0
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Produces a **perspective projection matrix** suitable for 3D rendering pipelines. Combined with the view matrix, this implements the standard camera transform chain.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::unreal_engine;
|
||||||
|
|
||||||
|
// Camera setup
|
||||||
|
ViewAngles angles = {
|
||||||
|
PitchAngle::from_degrees(-20.0f),
|
||||||
|
YawAngle::from_degrees(45.0f),
|
||||||
|
RollAngle::from_degrees(0.0f)
|
||||||
|
};
|
||||||
|
Vector3<float> cam_pos{1000.0f, 500.0f, 200.0f};
|
||||||
|
|
||||||
|
// Compute direction
|
||||||
|
auto forward = forward_vector(angles);
|
||||||
|
auto right = right_vector(angles);
|
||||||
|
auto up = up_vector(angles);
|
||||||
|
|
||||||
|
// Build matrices
|
||||||
|
auto view_mat = calc_view_matrix(angles, cam_pos);
|
||||||
|
auto proj_mat = calc_perspective_projection_matrix(90.0f, 16.0f/9.0f, 10.0f, 100000.0f);
|
||||||
|
|
||||||
|
// Use view_mat and proj_mat for rendering...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
* **Angles**: pitch (up/down), yaw (left/right), roll (tilt)
|
||||||
|
* **Pitch**: positive = looking up, negative = looking down
|
||||||
|
* **Yaw**: increases counter-clockwise from the +X axis
|
||||||
|
* **Coordinate system**: Z-up, X-forward, Y-right (left-handed)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/unreal_engine/constants.hpp` — coordinate frame & angle types
|
||||||
|
* `omath/engines/unreal_engine/traits/camera_trait.hpp` — plug-in for generic `Camera`
|
||||||
|
* `omath/projection/camera.hpp` — generic camera wrapper using these formulas
|
||||||
121
docs/engines/unreal_engine/mesh_trait.md
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# `omath::unreal_engine::MeshTrait` — mesh transformation trait for Unreal Engine
|
||||||
|
|
||||||
|
> Header: `omath/engines/unreal_engine/traits/mesh_trait.hpp`
|
||||||
|
> Namespace: `omath::unreal_engine`
|
||||||
|
> Purpose: provide Unreal Engine-specific rotation matrix computation for `omath::primitives::Mesh`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`MeshTrait` is a trait class that provides the `rotation_matrix` function for transforming meshes in Unreal Engine's coordinate system. It serves as a template parameter to `omath::primitives::Mesh`, enabling engine-specific rotation behavior.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coordinate System
|
||||||
|
|
||||||
|
**Unreal Engine** uses:
|
||||||
|
* **Up axis**: +Z
|
||||||
|
* **Forward axis**: +X
|
||||||
|
* **Right axis**: +Y
|
||||||
|
* **Handedness**: Left-handed
|
||||||
|
* **Rotation order**: Roll (Y) → Pitch (X) → Yaw (Z)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unreal_engine {
|
||||||
|
|
||||||
|
class MeshTrait final {
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::unreal_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Method: `rotation_matrix`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
static Mat4X4 rotation_matrix(const ViewAngles& rotation);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes a 4×4 rotation matrix from Unreal-style Euler angles.
|
||||||
|
|
||||||
|
**Parameters**:
|
||||||
|
* `rotation` — `ViewAngles` containing pitch, yaw, and roll angles
|
||||||
|
|
||||||
|
**Returns**: 4×4 rotation matrix suitable for mesh transformation
|
||||||
|
|
||||||
|
**Implementation**: Delegates to `unreal_engine::rotation_matrix(rotation)` defined in `formulas.hpp`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### With Mesh
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::unreal_engine;
|
||||||
|
|
||||||
|
// Create mesh (MeshTrait is used automatically)
|
||||||
|
Mesh my_mesh(vertices, indices);
|
||||||
|
|
||||||
|
// Set rotation using ViewAngles
|
||||||
|
ViewAngles angles;
|
||||||
|
angles.pitch = PitchAngle::from_degrees(30.0f);
|
||||||
|
angles.yaw = YawAngle::from_degrees(45.0f);
|
||||||
|
angles.roll = RollAngle::from_degrees(0.0f);
|
||||||
|
|
||||||
|
my_mesh.set_rotation(angles);
|
||||||
|
|
||||||
|
// The rotation matrix is computed using MeshTrait::rotation_matrix
|
||||||
|
auto matrix = my_mesh.get_to_world_matrix();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rotation Conventions
|
||||||
|
|
||||||
|
Unreal uses a left-handed Z-up coordinate system:
|
||||||
|
|
||||||
|
1. **Roll** (rotation around Y-axis / right axis)
|
||||||
|
* Positive roll rotates forward axis upward
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
2. **Pitch** (rotation around X-axis / forward axis)
|
||||||
|
* Positive pitch looks upward
|
||||||
|
* Range: typically [-89°, 89°]
|
||||||
|
|
||||||
|
3. **Yaw** (rotation around Z-axis / up axis)
|
||||||
|
* Positive yaw rotates clockwise when viewed from above (left-handed)
|
||||||
|
* Range: [-180°, 180°]
|
||||||
|
|
||||||
|
**Note**: Unreal applies rotations in Roll-Pitch-Yaw order, different from most other engines.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Type Alias
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unreal_engine {
|
||||||
|
using Mesh = primitives::Mesh<Mat4X4, ViewAngles, MeshTrait, float>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Mesh Documentation](../../3d_primitives/mesh.md) - Mesh primitive
|
||||||
|
- [Formulas Documentation](formulas.md) - Unreal rotation formula
|
||||||
|
- [CameraTrait Documentation](camera_trait.md) - Camera trait
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 13 Nov 2025*
|
||||||
200
docs/engines/unreal_engine/pred_engine_trait.md
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
# `omath::unreal_engine::PredEngineTrait` — projectile prediction trait
|
||||||
|
|
||||||
|
> Header: `omath/engines/unreal_engine/traits/pred_engine_trait.hpp`
|
||||||
|
> Namespace: `omath::unreal_engine`
|
||||||
|
> Purpose: provide Unreal Engine-specific projectile and target prediction for ballistic calculations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`PredEngineTrait` implements engine-specific helpers for **projectile prediction**:
|
||||||
|
|
||||||
|
* `predict_projectile_position` – computes where a projectile will be after `time` seconds
|
||||||
|
* `predict_target_position` – computes where a moving target will be after `time` seconds
|
||||||
|
* `calc_vector_2d_distance` – horizontal distance (X/Y plane, ignoring Z)
|
||||||
|
* `get_vector_height_coordinate` – extracts vertical coordinate (Y in Unreal Engine, note: code uses Z)
|
||||||
|
* `calc_viewpoint_from_angles` – computes aim point given pitch angle
|
||||||
|
* `calc_direct_pitch_angle` – pitch angle to look from origin to target
|
||||||
|
* `calc_direct_yaw_angle` – yaw angle to look from origin to target
|
||||||
|
|
||||||
|
These methods satisfy the `PredEngineTraitConcept` required by generic projectile prediction algorithms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::unreal_engine {
|
||||||
|
|
||||||
|
class PredEngineTrait final {
|
||||||
|
public:
|
||||||
|
// Predict projectile position after `time` seconds
|
||||||
|
static constexpr Vector3<float>
|
||||||
|
predict_projectile_position(const projectile_prediction::Projectile& projectile,
|
||||||
|
float pitch, float yaw, float time,
|
||||||
|
float gravity) noexcept;
|
||||||
|
|
||||||
|
// Predict target position after `time` seconds
|
||||||
|
static constexpr Vector3<float>
|
||||||
|
predict_target_position(const projectile_prediction::Target& target,
|
||||||
|
float time, float gravity) noexcept;
|
||||||
|
|
||||||
|
// Compute horizontal (2D) distance
|
||||||
|
static float
|
||||||
|
calc_vector_2d_distance(const Vector3<float>& delta) noexcept;
|
||||||
|
|
||||||
|
// Get vertical coordinate (implementation returns Y, but UE is Z-up)
|
||||||
|
static constexpr float
|
||||||
|
get_vector_height_coordinate(const Vector3<float>& vec) noexcept;
|
||||||
|
|
||||||
|
// Compute aim point from angles
|
||||||
|
static Vector3<float>
|
||||||
|
calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile,
|
||||||
|
Vector3<float> predicted_target_position,
|
||||||
|
std::optional<float> projectile_pitch) noexcept;
|
||||||
|
|
||||||
|
// Compute pitch angle to look at target
|
||||||
|
static float
|
||||||
|
calc_direct_pitch_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept;
|
||||||
|
|
||||||
|
// Compute yaw angle to look at target
|
||||||
|
static float
|
||||||
|
calc_direct_yaw_angle(const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& view_to) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::unreal_engine
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Projectile prediction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto pos = PredEngineTrait::predict_projectile_position(
|
||||||
|
projectile, // initial position, speed, gravity scale
|
||||||
|
pitch_deg, // launch pitch (positive = up)
|
||||||
|
yaw_deg, // launch yaw
|
||||||
|
time, // time in seconds
|
||||||
|
gravity // gravity constant (e.g., 980 cm/s²)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes:
|
||||||
|
|
||||||
|
1. Forward vector from pitch/yaw (using `forward_vector`)
|
||||||
|
2. Initial velocity: `forward * launch_speed`
|
||||||
|
3. Position after `time`: `origin + velocity*time - 0.5*gravity*gravityScale*time²` (Y component per implementation, though UE is Z-up)
|
||||||
|
|
||||||
|
**Note**: Negative pitch in `forward_vector` convention → positive pitch looks up.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Target prediction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto pos = PredEngineTrait::predict_target_position(
|
||||||
|
target, // position, velocity, airborne flag
|
||||||
|
time, // time in seconds
|
||||||
|
gravity // gravity constant
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Simple linear extrapolation plus gravity if target is airborne:
|
||||||
|
|
||||||
|
```
|
||||||
|
predicted = origin + velocity * time
|
||||||
|
if (airborne)
|
||||||
|
predicted.y -= 0.5 * gravity * time² // Note: implementation uses Y
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Distance & height helpers
|
||||||
|
|
||||||
|
* `calc_vector_2d_distance(delta)` → `sqrt(delta.x² + delta.z²)` (horizontal distance in X/Z plane)
|
||||||
|
* `get_vector_height_coordinate(vec)` → `vec.y` (implementation returns Y; UE convention is Z-up)
|
||||||
|
|
||||||
|
Used to compute ballistic arc parameters.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Aim angle calculation
|
||||||
|
|
||||||
|
* `calc_direct_pitch_angle(origin, target)` → pitch in degrees to look from `origin` to `target`
|
||||||
|
- Formula: `asin(Δz / distance)` converted to degrees (direction normalized first)
|
||||||
|
- Positive = looking up, negative = looking down
|
||||||
|
|
||||||
|
* `calc_direct_yaw_angle(origin, target)` → yaw in degrees to look from `origin` to `target`
|
||||||
|
- Formula: `atan2(Δy, Δx)` converted to degrees (direction normalized first)
|
||||||
|
- Horizontal rotation around Z-axis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Viewpoint from angles
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto aim_point = PredEngineTrait::calc_viewpoint_from_angles(
|
||||||
|
projectile,
|
||||||
|
predicted_target_pos,
|
||||||
|
optional_pitch_deg
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Computes where to aim in 3D space given a desired pitch angle. Uses horizontal distance and `tan(pitch)` to compute height offset.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
* **Coordinate system**: Z-up (height increases with Z)
|
||||||
|
* **Angles**: pitch in [-90°, +90°], yaw in [-180°, +180°]
|
||||||
|
* **Gravity**: applied downward (implementation uses Y component, but UE is Z-up)
|
||||||
|
* **Pitch convention**: +90° = straight up, -90° = straight down
|
||||||
|
|
||||||
|
**Note**: Some implementation details (gravity application to Y coordinate) may need adjustment for full Unreal Engine Z-up consistency.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::unreal_engine;
|
||||||
|
using namespace omath::projectile_prediction;
|
||||||
|
|
||||||
|
Projectile proj{
|
||||||
|
.m_origin = {0, 0, 200},
|
||||||
|
.m_launch_speed = 5000.0f,
|
||||||
|
.m_gravity_scale = 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
Target tgt{
|
||||||
|
.m_origin = {2000, 1000, 200},
|
||||||
|
.m_velocity = {50, 20, 0},
|
||||||
|
.m_is_airborne = false
|
||||||
|
};
|
||||||
|
|
||||||
|
float gravity = 980.0f; // cm/s² in Unreal units
|
||||||
|
float time = 0.5f;
|
||||||
|
|
||||||
|
// Predict where target will be
|
||||||
|
auto target_pos = PredEngineTrait::predict_target_position(tgt, time, gravity);
|
||||||
|
|
||||||
|
// Compute aim angles
|
||||||
|
float pitch = PredEngineTrait::calc_direct_pitch_angle(proj.m_origin, target_pos);
|
||||||
|
float yaw = PredEngineTrait::calc_direct_yaw_angle(proj.m_origin, target_pos);
|
||||||
|
|
||||||
|
// Predict projectile position with those angles
|
||||||
|
auto proj_pos = PredEngineTrait::predict_projectile_position(proj, pitch, yaw, time, gravity);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath/engines/unreal_engine/formulas.hpp` — direction vectors and matrix builders
|
||||||
|
* `omath/projectile_prediction/projectile.hpp` — `Projectile` struct
|
||||||
|
* `omath/projectile_prediction/target.hpp` — `Target` struct
|
||||||
|
* Generic projectile prediction algorithms that use `PredEngineTraitConcept`
|
||||||
406
docs/faq.md
Normal file
@@ -0,0 +1,406 @@
|
|||||||
|
# FAQ
|
||||||
|
|
||||||
|
Common questions and answers about OMath.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## General Questions
|
||||||
|
|
||||||
|
### What is OMath?
|
||||||
|
|
||||||
|
OMath is a modern C++ math library designed for game development, graphics programming, and high-performance computing. It provides:
|
||||||
|
- Vector and matrix operations
|
||||||
|
- 3D projection and camera systems
|
||||||
|
- Projectile prediction
|
||||||
|
- Collision detection
|
||||||
|
- Support for multiple game engines (Source, Unity, Unreal, etc.)
|
||||||
|
- Pattern scanning utilities
|
||||||
|
|
||||||
|
### Why choose OMath over other math libraries?
|
||||||
|
|
||||||
|
- **Modern C++**: Uses C++20/23 features (concepts, `constexpr`, `std::expected`)
|
||||||
|
- **No legacy code**: Built from scratch without legacy baggage
|
||||||
|
- **Game engine support**: Pre-configured for Source, Unity, Unreal, Frostbite, etc.
|
||||||
|
- **Zero dependencies**: No external dependencies needed (except for testing)
|
||||||
|
- **Performance**: AVX2 optimizations available
|
||||||
|
- **Type safety**: Strong typing prevents common errors
|
||||||
|
- **Cross-platform**: Works on Windows, Linux, and macOS
|
||||||
|
|
||||||
|
### Is OMath suitable for production use?
|
||||||
|
|
||||||
|
Yes! OMath is production-ready and used in various projects. It has:
|
||||||
|
- Comprehensive test coverage
|
||||||
|
- Clear error handling
|
||||||
|
- Well-documented API
|
||||||
|
- Active maintenance and community support
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation & Setup
|
||||||
|
|
||||||
|
### How do I install OMath?
|
||||||
|
|
||||||
|
Three main methods:
|
||||||
|
|
||||||
|
**vcpkg (recommended):**
|
||||||
|
```bash
|
||||||
|
vcpkg install orange-math
|
||||||
|
```
|
||||||
|
|
||||||
|
**xrepo:**
|
||||||
|
```bash
|
||||||
|
xrepo install omath
|
||||||
|
```
|
||||||
|
|
||||||
|
**From source:**
|
||||||
|
See [Installation Guide](install.md)
|
||||||
|
|
||||||
|
### What are the minimum requirements?
|
||||||
|
|
||||||
|
- **Compiler**: C++20 support required
|
||||||
|
- GCC 10+
|
||||||
|
- Clang 11+
|
||||||
|
- MSVC 2019 16.10+
|
||||||
|
- **CMake**: 3.15+ (if building from source)
|
||||||
|
- **Platform**: Windows, Linux, or macOS
|
||||||
|
|
||||||
|
### Do I need C++23?
|
||||||
|
|
||||||
|
C++23 is **recommended** but not required. Some features like `std::expected` work better with C++23, but fallbacks are available for C++20.
|
||||||
|
|
||||||
|
### Can I use OMath in a C++17 project?
|
||||||
|
|
||||||
|
No, OMath requires C++20 minimum due to use of concepts, `constexpr` enhancements, and other C++20 features.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Questions
|
||||||
|
|
||||||
|
### How do I include OMath in my project?
|
||||||
|
|
||||||
|
**Full library:**
|
||||||
|
```cpp
|
||||||
|
#include <omath/omath.hpp>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Specific components:**
|
||||||
|
```cpp
|
||||||
|
#include <omath/linear_algebra/vector3.hpp>
|
||||||
|
#include <omath/engines/source_engine/camera.hpp>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Which game engine should I use?
|
||||||
|
|
||||||
|
Choose based on your target game or application:
|
||||||
|
|
||||||
|
| Engine | Use For |
|
||||||
|
|--------|---------|
|
||||||
|
| **Source Engine** | CS:GO, TF2, CS2, Half-Life, Portal, L4D |
|
||||||
|
| **Unity Engine** | Unity games (many indie and mobile games) |
|
||||||
|
| **Unreal Engine** | Fortnite, Unreal games |
|
||||||
|
| **Frostbite** | Battlefield, Star Wars games (EA titles) |
|
||||||
|
| **IW Engine** | Call of Duty series |
|
||||||
|
| **OpenGL** | Custom OpenGL applications, generic 3D |
|
||||||
|
|
||||||
|
### How do I switch between engines?
|
||||||
|
|
||||||
|
Just change the namespace:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Source Engine
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
Camera cam = /* ... */;
|
||||||
|
|
||||||
|
// Unity Engine
|
||||||
|
using namespace omath::unity_engine;
|
||||||
|
Camera cam = /* ... */;
|
||||||
|
```
|
||||||
|
|
||||||
|
Each engine has the same API but different coordinate system handling.
|
||||||
|
|
||||||
|
### What if my game isn't listed?
|
||||||
|
|
||||||
|
Use the **OpenGL engine** as a starting point - it uses canonical OpenGL conventions. You may need to adjust coordinate transformations based on your specific game.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Questions
|
||||||
|
|
||||||
|
### Should I use the AVX2 or Legacy engine?
|
||||||
|
|
||||||
|
**Use AVX2 if:**
|
||||||
|
- Target modern CPUs (2013+)
|
||||||
|
- Need maximum performance
|
||||||
|
- Can accept reduced compatibility
|
||||||
|
|
||||||
|
**Use Legacy if:**
|
||||||
|
- Need broad compatibility
|
||||||
|
- Target older CPUs or ARM
|
||||||
|
- Unsure about target hardware
|
||||||
|
|
||||||
|
The API is identical - just change the class:
|
||||||
|
```cpp
|
||||||
|
// Legacy (compatible)
|
||||||
|
ProjPredEngineLegacy engine;
|
||||||
|
|
||||||
|
// AVX2 (faster)
|
||||||
|
ProjPredEngineAVX2 engine;
|
||||||
|
```
|
||||||
|
|
||||||
|
### How much faster is AVX2?
|
||||||
|
|
||||||
|
Typically 2-4x faster for projectile prediction calculations, depending on the CPU and specific use case.
|
||||||
|
|
||||||
|
### Are vector operations constexpr?
|
||||||
|
|
||||||
|
Yes! Most operations are `constexpr` and can be evaluated at compile-time:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector3<float> v{1, 2, 3};
|
||||||
|
constexpr auto len_sq = v.length_sqr(); // Computed at compile time
|
||||||
|
```
|
||||||
|
|
||||||
|
### Is OMath thread-safe?
|
||||||
|
|
||||||
|
- **Immutable operations** (vector math, etc.) are thread-safe
|
||||||
|
- **Mutable state** (Camera updates) is NOT thread-safe
|
||||||
|
- Use separate instances per thread or synchronize access
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### `world_to_screen()` always returns `nullopt`
|
||||||
|
|
||||||
|
Check:
|
||||||
|
1. **Is the point behind the camera?** Points behind the camera cannot be projected.
|
||||||
|
2. **Are near/far planes correct?** Ensure `near < far` and both are positive.
|
||||||
|
3. **Is FOV valid?** FOV should be between 1° and 179°.
|
||||||
|
4. **Are camera angles normalized?** Use engine-provided angle types.
|
||||||
|
|
||||||
|
### Angles are wrapping incorrectly
|
||||||
|
|
||||||
|
Use the correct angle type:
|
||||||
|
```cpp
|
||||||
|
// Good: uses proper angle type
|
||||||
|
PitchAngle pitch = PitchAngle::from_degrees(45.0f);
|
||||||
|
|
||||||
|
// Bad: raw float loses normalization
|
||||||
|
float pitch = 45.0f;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Projection seems mirrored or inverted
|
||||||
|
|
||||||
|
You may be using the wrong engine trait. Each engine has different coordinate conventions:
|
||||||
|
- **Source/Unity**: Z-up
|
||||||
|
- **Unreal**: Z-up, different handedness
|
||||||
|
- **OpenGL**: Y-up
|
||||||
|
|
||||||
|
Ensure you're using the trait matching your game.
|
||||||
|
|
||||||
|
### Pattern scanning finds multiple matches
|
||||||
|
|
||||||
|
This is normal! Patterns may appear multiple times. Solutions:
|
||||||
|
1. Make the pattern more specific (more bytes, fewer wildcards)
|
||||||
|
2. Use additional context (nearby code patterns)
|
||||||
|
3. Verify each match programmatically
|
||||||
|
|
||||||
|
### Projectile prediction returns `nullopt`
|
||||||
|
|
||||||
|
Common reasons:
|
||||||
|
1. **Target too fast**: Target velocity exceeds projectile speed
|
||||||
|
2. **Out of range**: Distance exceeds max flight time
|
||||||
|
3. **Invalid input**: Check projectile speed > 0
|
||||||
|
4. **Gravity too strong**: Projectile can't reach target height
|
||||||
|
|
||||||
|
### Compilation errors about `std::expected`
|
||||||
|
|
||||||
|
If using C++20 (not C++23), you may need a backport library like `tl::expected`:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# CMakeLists.txt
|
||||||
|
find_package(tl-expected CONFIG REQUIRED)
|
||||||
|
target_link_libraries(your_target PRIVATE tl::expected)
|
||||||
|
```
|
||||||
|
|
||||||
|
Or upgrade to C++23 if possible.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Feature Questions
|
||||||
|
|
||||||
|
### Can I use OMath with DirectX/OpenGL/Vulkan?
|
||||||
|
|
||||||
|
Yes! OMath matrices and vectors work with all graphics APIs. Use:
|
||||||
|
- **OpenGL**: `opengl_engine` traits
|
||||||
|
- **DirectX**: Use appropriate engine trait or OpenGL as base
|
||||||
|
- **Vulkan**: Use OpenGL traits as starting point
|
||||||
|
|
||||||
|
### Does OMath support quaternions?
|
||||||
|
|
||||||
|
Not currently. Quaternion support may be added in future versions. For now, use euler angles (ViewAngles) or convert manually.
|
||||||
|
|
||||||
|
### Can I extend OMath with custom engine traits?
|
||||||
|
|
||||||
|
Yes! Implement the `CameraEngineConcept`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class MyEngineTrait {
|
||||||
|
public:
|
||||||
|
static ViewAngles calc_look_at_angle(
|
||||||
|
const Vector3<float>& origin,
|
||||||
|
const Vector3<float>& target
|
||||||
|
);
|
||||||
|
|
||||||
|
static Mat4X4 calc_view_matrix(
|
||||||
|
const ViewAngles& angles,
|
||||||
|
const Vector3<float>& origin
|
||||||
|
);
|
||||||
|
|
||||||
|
static Mat4X4 calc_projection_matrix(
|
||||||
|
const FieldOfView& fov,
|
||||||
|
const ViewPort& viewport,
|
||||||
|
float near, float far
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use with Camera
|
||||||
|
using MyCamera = Camera<Mat4X4, ViewAngles, MyEngineTrait>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Does OMath support SIMD for vector operations?
|
||||||
|
|
||||||
|
AVX2 support is available for projectile prediction. General vector SIMD may be added in future versions. The library already compiles to efficient code with compiler optimizations enabled.
|
||||||
|
|
||||||
|
### Can I use OMath for machine learning?
|
||||||
|
|
||||||
|
OMath is optimized for game development and graphics, not ML. For machine learning, consider libraries like Eigen or xtensor which are designed for that domain.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Debugging Questions
|
||||||
|
|
||||||
|
### How do I print vectors?
|
||||||
|
|
||||||
|
OMath provides `std::formatter` support:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <format>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
Vector3<float> v{1, 2, 3};
|
||||||
|
std::cout << std::format("{}", v) << "\n"; // Prints: [1, 2, 3]
|
||||||
|
```
|
||||||
|
|
||||||
|
### How do I visualize projection problems?
|
||||||
|
|
||||||
|
1. Check if `world_to_screen()` succeeds
|
||||||
|
2. Print camera matrices:
|
||||||
|
```cpp
|
||||||
|
auto view = camera.get_view_matrix();
|
||||||
|
auto proj = camera.get_projection_matrix();
|
||||||
|
// Print matrix values
|
||||||
|
```
|
||||||
|
3. Test with known good points (e.g., origin, simple positions)
|
||||||
|
4. Verify viewport and FOV values
|
||||||
|
|
||||||
|
### How can I debug pattern scanning?
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
PatternView pattern{"48 8B 05 ?? ?? ?? ??"};
|
||||||
|
|
||||||
|
// Print pattern details
|
||||||
|
std::cout << "Pattern length: " << pattern.size() << "\n";
|
||||||
|
std::cout << "Pattern bytes: ";
|
||||||
|
for (auto byte : pattern) {
|
||||||
|
if (byte.has_value()) {
|
||||||
|
std::cout << std::hex << (int)*byte << " ";
|
||||||
|
} else {
|
||||||
|
std::cout << "?? ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
### How can I contribute to OMath?
|
||||||
|
|
||||||
|
See [CONTRIBUTING.md](https://github.com/orange-cpp/omath/blob/master/CONTRIBUTING.md) for guidelines. Contributions welcome:
|
||||||
|
- Bug fixes
|
||||||
|
- New features
|
||||||
|
- Documentation improvements
|
||||||
|
- Test coverage
|
||||||
|
- Examples
|
||||||
|
|
||||||
|
### Where do I report bugs?
|
||||||
|
|
||||||
|
[GitHub Issues](https://github.com/orange-cpp/omath/issues)
|
||||||
|
|
||||||
|
Please include:
|
||||||
|
- OMath version
|
||||||
|
- Compiler and version
|
||||||
|
- Minimal reproducible example
|
||||||
|
- Expected vs actual behavior
|
||||||
|
|
||||||
|
### How do I request a feature?
|
||||||
|
|
||||||
|
Open a GitHub issue with:
|
||||||
|
- Use case description
|
||||||
|
- Proposed API (if applicable)
|
||||||
|
- Why existing features don't meet your needs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License & Legal
|
||||||
|
|
||||||
|
### What license does OMath use?
|
||||||
|
|
||||||
|
OMath uses a custom "libomath" license. See [LICENSE](https://github.com/orange-cpp/omath/blob/master/LICENSE) for full details.
|
||||||
|
|
||||||
|
### Can I use OMath in commercial projects?
|
||||||
|
|
||||||
|
Check the LICENSE file for commercial use terms.
|
||||||
|
|
||||||
|
### Can I use OMath for game cheating/hacking?
|
||||||
|
|
||||||
|
OMath is a math library and can be used for various purposes. However:
|
||||||
|
- Using it to cheat in online games may violate game ToS
|
||||||
|
- Creating cheats may be illegal in your jurisdiction
|
||||||
|
- The developers do not condone cheating in online games
|
||||||
|
|
||||||
|
Use responsibly and ethically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
### Where can I get help?
|
||||||
|
|
||||||
|
- **Documentation**: [http://libomath.org](http://libomath.org)
|
||||||
|
- **Discord**: [Join community](https://discord.gg/eDgdaWbqwZ)
|
||||||
|
- **Telegram**: [@orangennotes](https://t.me/orangennotes)
|
||||||
|
- **GitHub Issues**: [Report bugs/ask questions](https://github.com/orange-cpp/omath/issues)
|
||||||
|
|
||||||
|
### Is there a Discord/community?
|
||||||
|
|
||||||
|
Yes! Join our Discord: [https://discord.gg/eDgdaWbqwZ](https://discord.gg/eDgdaWbqwZ)
|
||||||
|
|
||||||
|
### Are there video tutorials?
|
||||||
|
|
||||||
|
Check our [YouTube channel](https://youtu.be/lM_NJ1yCunw?si=-Qf5yzDcWbaxAXGQ) for demonstrations and tutorials.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Didn't find your answer?
|
||||||
|
|
||||||
|
- Search the [documentation](index.md)
|
||||||
|
- Check [tutorials](tutorials.md)
|
||||||
|
- Ask on [Discord](https://discord.gg/eDgdaWbqwZ)
|
||||||
|
- Open a [GitHub issue](https://github.com/orange-cpp/omath/issues)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 1 Nov 2025*
|
||||||
305
docs/getting_started.md
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
# Getting Started
|
||||||
|
Welcome to OMath! This guide will help you get up and running with the library quickly.
|
||||||
|
|
||||||
|
## What is OMath?
|
||||||
|
|
||||||
|
OMath is a modern, blazingly fast C++ math library designed for:
|
||||||
|
- **Game development** and cheat development
|
||||||
|
- **Graphics programming** (DirectX/OpenGL/Vulkan)
|
||||||
|
- **3D applications** with support for multiple game engines
|
||||||
|
- **High-performance computing** with AVX2 optimizations
|
||||||
|
|
||||||
|
Key features:
|
||||||
|
- 100% independent, no legacy C++ code
|
||||||
|
- Fully `constexpr` template-based design
|
||||||
|
- Zero additional dependencies (except for unit tests)
|
||||||
|
- Cross-platform (Windows, macOS, Linux)
|
||||||
|
- Built-in support for Source, Unity, Unreal, Frostbite, IWEngine, and OpenGL coordinate systems
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Choose one of the following methods to install OMath:
|
||||||
|
|
||||||
|
### Using vcpkg (Recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vcpkg install orange-math
|
||||||
|
```
|
||||||
|
|
||||||
|
Then in your CMakeLists.txt:
|
||||||
|
```cmake
|
||||||
|
find_package(omath CONFIG REQUIRED)
|
||||||
|
target_link_libraries(your_target PRIVATE omath::omath)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using xrepo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
xrepo install omath
|
||||||
|
```
|
||||||
|
|
||||||
|
Then in your xmake.lua:
|
||||||
|
```lua
|
||||||
|
add_requires("omath")
|
||||||
|
target("your_target")
|
||||||
|
add_packages("omath")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building from Source
|
||||||
|
|
||||||
|
See the detailed [Installation Guide](install.md) for complete instructions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Example
|
||||||
|
|
||||||
|
Here's a simple example to get you started:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <omath/omath.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
using namespace omath;
|
||||||
|
|
||||||
|
// Create 3D vectors
|
||||||
|
Vector3<float> a{1.0f, 2.0f, 3.0f};
|
||||||
|
Vector3<float> b{4.0f, 5.0f, 6.0f};
|
||||||
|
|
||||||
|
// Vector operations
|
||||||
|
auto sum = a + b; // Vector addition
|
||||||
|
auto dot_product = a.dot(b); // Dot product: 32.0
|
||||||
|
auto cross_product = a.cross(b); // Cross product: (-3, 6, -3)
|
||||||
|
auto length = a.length(); // Length: ~3.74
|
||||||
|
auto normalized = a.normalized(); // Unit vector
|
||||||
|
|
||||||
|
std::cout << "Sum: [" << sum.x << ", " << sum.y << ", " << sum.z << "]\n";
|
||||||
|
std::cout << "Dot product: " << dot_product << "\n";
|
||||||
|
std::cout << "Length: " << length << "\n";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core Concepts
|
||||||
|
|
||||||
|
### 1. Vectors
|
||||||
|
|
||||||
|
OMath provides 2D, 3D, and 4D vector types:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath;
|
||||||
|
|
||||||
|
Vector2<float> vec2{1.0f, 2.0f};
|
||||||
|
Vector3<float> vec3{1.0f, 2.0f, 3.0f};
|
||||||
|
Vector4<float> vec4{1.0f, 2.0f, 3.0f, 4.0f};
|
||||||
|
```
|
||||||
|
|
||||||
|
All vector types support:
|
||||||
|
- Arithmetic operations (+, -, *, /)
|
||||||
|
- Dot and cross products (where applicable)
|
||||||
|
- Length and distance calculations
|
||||||
|
- Normalization
|
||||||
|
- Component-wise operations
|
||||||
|
|
||||||
|
See: [Vector2](linear_algebra/vector2.md), [Vector3](linear_algebra/vector3.md), [Vector4](linear_algebra/vector4.md)
|
||||||
|
|
||||||
|
### 2. Matrices
|
||||||
|
|
||||||
|
4x4 matrices for transformations:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath;
|
||||||
|
|
||||||
|
Mat4X4 matrix = Mat4X4::identity();
|
||||||
|
// Use for transformations, projections, etc.
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Matrix Documentation](linear_algebra/mat.md)
|
||||||
|
|
||||||
|
### 3. Angles
|
||||||
|
|
||||||
|
Strong-typed angle system with automatic range management:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath;
|
||||||
|
|
||||||
|
auto angle = Angle<float, 0.0f, 360.0f>::from_degrees(45.0f);
|
||||||
|
auto radians = angle.as_radians();
|
||||||
|
|
||||||
|
// View angles for camera systems
|
||||||
|
ViewAngles view{
|
||||||
|
PitchAngle::from_degrees(-10.0f),
|
||||||
|
YawAngle::from_degrees(90.0f),
|
||||||
|
RollAngle::from_degrees(0.0f)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Angle](trigonometry/angle.md), [View Angles](trigonometry/view_angles.md)
|
||||||
|
|
||||||
|
### 4. 3D Projection
|
||||||
|
|
||||||
|
Built-in camera and projection systems:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath;
|
||||||
|
using namespace omath::projection;
|
||||||
|
|
||||||
|
ViewPort viewport{1920.0f, 1080.0f};
|
||||||
|
auto fov = FieldOfView::from_degrees(90.0f);
|
||||||
|
|
||||||
|
// Example using Source Engine
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
Camera cam(
|
||||||
|
Vector3<float>{0, 0, 100}, // Position
|
||||||
|
ViewAngles{}, // Angles
|
||||||
|
viewport,
|
||||||
|
fov,
|
||||||
|
0.1f, // near plane
|
||||||
|
1000.0f // far plane
|
||||||
|
);
|
||||||
|
|
||||||
|
// Project 3D point to 2D screen
|
||||||
|
Vector3<float> world_pos{100, 50, 75};
|
||||||
|
if (auto screen_pos = cam.world_to_screen(world_pos)) {
|
||||||
|
std::cout << "Screen: " << screen_pos->x << ", " << screen_pos->y << "\n";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Camera](projection/camera.md)
|
||||||
|
|
||||||
|
### 5. Game Engine Support
|
||||||
|
|
||||||
|
OMath provides pre-configured traits for major game engines:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Source Engine
|
||||||
|
#include <omath/engines/source_engine/camera.hpp>
|
||||||
|
using SourceCamera = omath::source_engine::Camera;
|
||||||
|
|
||||||
|
// Unity Engine
|
||||||
|
#include <omath/engines/unity_engine/camera.hpp>
|
||||||
|
using UnityCamera = omath::unity_engine::Camera;
|
||||||
|
|
||||||
|
// Unreal Engine
|
||||||
|
#include <omath/engines/unreal_engine/camera.hpp>
|
||||||
|
using UnrealCamera = omath::unreal_engine::Camera;
|
||||||
|
|
||||||
|
// And more: OpenGL, Frostbite, IWEngine
|
||||||
|
```
|
||||||
|
|
||||||
|
Each engine has its own coordinate system conventions automatically handled.
|
||||||
|
|
||||||
|
See: Engine-specific docs in [engines/](engines/) folder
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Use Cases
|
||||||
|
|
||||||
|
### World-to-Screen Projection
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath;
|
||||||
|
using namespace omath::source_engine;
|
||||||
|
|
||||||
|
Camera cam = /* initialize camera */;
|
||||||
|
Vector3<float> enemy_position{100, 200, 50};
|
||||||
|
|
||||||
|
if (auto screen = cam.world_to_screen(enemy_position)) {
|
||||||
|
// Draw ESP box at screen->x, screen->y
|
||||||
|
std::cout << "Enemy on screen at: " << screen->x << ", " << screen->y << "\n";
|
||||||
|
} else {
|
||||||
|
// Enemy not visible (behind camera or outside frustum)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Projectile Prediction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath::projectile_prediction;
|
||||||
|
|
||||||
|
Projectile bullet{
|
||||||
|
Vector3<float>{0, 0, 0}, // shooter position
|
||||||
|
1000.0f, // muzzle velocity (m/s)
|
||||||
|
Vector3<float>{0, 0, -9.81f} // gravity
|
||||||
|
};
|
||||||
|
|
||||||
|
Target enemy{
|
||||||
|
Vector3<float>{100, 200, 50}, // position
|
||||||
|
Vector3<float>{10, 0, 0} // velocity
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate where to aim
|
||||||
|
ProjPredEngineLegacy engine;
|
||||||
|
if (auto aim_point = engine.maybe_calculate_aim_point(bullet, enemy)) {
|
||||||
|
// Aim at *aim_point to hit moving target
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Projectile Prediction](projectile_prediction/projectile_engine.md)
|
||||||
|
|
||||||
|
### Collision Detection
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using namespace omath;
|
||||||
|
|
||||||
|
// Ray-plane intersection
|
||||||
|
Plane ground{
|
||||||
|
Vector3<float>{0, 0, 0}, // point on plane
|
||||||
|
Vector3<float>{0, 0, 1} // normal (pointing up)
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector3<float> ray_origin{0, 0, 100};
|
||||||
|
Vector3<float> ray_direction{0, 0, -1};
|
||||||
|
|
||||||
|
if (auto hit = ground.intersects_ray(ray_origin, ray_direction)) {
|
||||||
|
std::cout << "Hit ground at: " << hit->x << ", " << hit->y << ", " << hit->z << "\n";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Collision Detection](collision/line_tracer.md)
|
||||||
|
|
||||||
|
### Pattern Scanning
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <omath/utility/pattern_scan.hpp>
|
||||||
|
|
||||||
|
using namespace omath;
|
||||||
|
|
||||||
|
std::vector<uint8_t> memory = /* ... */;
|
||||||
|
PatternView pattern{"48 8B 05 ?? ?? ?? ?? 48 85 C0"};
|
||||||
|
|
||||||
|
if (auto result = pattern_scan(memory, pattern)) {
|
||||||
|
std::cout << "Pattern found at offset: " << result->offset << "\n";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Pattern Scanning](utility/pattern_scan.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
Now that you have the basics, explore these topics:
|
||||||
|
|
||||||
|
1. **[API Reference](index.md)** - Complete API documentation
|
||||||
|
2. **[Examples](../examples/)** - Working code examples
|
||||||
|
3. **[Engine-Specific Features](engines/)** - Deep dive into game engine support
|
||||||
|
4. **[Advanced Topics](#)** - Performance optimization, custom traits, etc.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
- **Documentation**: [http://libomath.org](http://libomath.org)
|
||||||
|
- **Discord**: [Join our community](https://discord.gg/eDgdaWbqwZ)
|
||||||
|
- **Telegram**: [@orangennotes](https://t.me/orangennotes)
|
||||||
|
- **Issues**: [GitHub Issues](https://github.com/orange-cpp/omath/issues)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 1 Nov 2025*
|
||||||
BIN
docs/images/logos/omath_logo_macro.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
docs/images/logos/omath_logo_mega.png
Normal file
|
After Width: | Height: | Size: 454 KiB |
BIN
docs/images/logos/omath_logo_micro.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
docs/images/logos/omath_logo_nano.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
docs/images/showcase/apex.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
docs/images/showcase/cod_bo2.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
docs/images/showcase/cs2.jpeg
Normal file
|
After Width: | Height: | Size: 644 KiB |
BIN
docs/images/showcase/opengl.png
Normal file
|
After Width: | Height: | Size: 224 KiB |
BIN
docs/images/showcase/tf2.jpg
Normal file
|
After Width: | Height: | Size: 324 KiB |
BIN
docs/images/yt_previews/img.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
239
docs/index.md
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
<div class="center-text">
|
||||||
|
<!-- Banner -->
|
||||||
|
<p>
|
||||||
|
<img src="images/logos/omath_logo_macro.png" alt="omath banner">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Badges -->
|
||||||
|
<p>
|
||||||
|
<img src="https://img.shields.io/badge/license-libomath-orange" alt="license: libomath">
|
||||||
|
<img src="https://img.shields.io/github/contributors/orange-cpp/omath" alt="GitHub contributors">
|
||||||
|
<img src="https://img.shields.io/github/languages/top/orange-cpp/omath" alt="Top language">
|
||||||
|
<a href="https://www.codefactor.io/repository/github/orange-cpp/omath">
|
||||||
|
<img src="https://www.codefactor.io/repository/github/orange-cpp/omath/badge" alt="CodeFactor">
|
||||||
|
</a>
|
||||||
|
<img src="https://img.shields.io/github/actions/workflow/status/orange-cpp/omath/cmake-multi-platform.yml" alt="GitHub Actions Workflow Status">
|
||||||
|
<a href="https://repology.org/project/orange-math/versions">
|
||||||
|
<img src="https://repology.org/badge/version-for-repo/vcpkg/orange-math.svg" alt="Vcpkg package">
|
||||||
|
</a>
|
||||||
|
<img src="https://img.shields.io/github/forks/orange-cpp/omath" alt="GitHub forks">
|
||||||
|
<a href="https://discord.gg/eDgdaWbqwZ">
|
||||||
|
<img src="https://dcbadge.limes.pink/api/server/https://discord.gg/eDgdaWbqwZ?style=flat" alt="Join us on Discord">
|
||||||
|
</a>
|
||||||
|
<a href="https://t.me/orangennotes">
|
||||||
|
<img src="https://img.shields.io/badge/Telegram-2CA5E0?style=flat-squeare&logo=telegram&logoColor=white" alt="Telegram">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
OMath is a 100% independent, constexpr template blazingly fast math library that doesn't have legacy C++ code.
|
||||||
|
|
||||||
|
It provides the latest features, is highly customizable, has all for cheat development, DirectX/OpenGL/Vulkan support, premade support for different game engines, much more constexpr stuff than in other libraries and more...
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
**New to OMath?** Start here:
|
||||||
|
|
||||||
|
- **[Getting Started Guide](getting_started.md)** - Installation and first steps
|
||||||
|
- **[API Overview](api_overview.md)** - High-level API reference
|
||||||
|
- **[Installation Instructions](install.md)** - Detailed setup guide
|
||||||
|
|
||||||
|
**Quick example:**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <omath/omath.hpp>
|
||||||
|
|
||||||
|
using namespace omath;
|
||||||
|
|
||||||
|
Vector3<float> a{1, 2, 3};
|
||||||
|
Vector3<float> b{4, 5, 6};
|
||||||
|
|
||||||
|
auto dot = a.dot(b); // 32.0
|
||||||
|
auto cross = a.cross(b); // (-3, 6, -3)
|
||||||
|
auto distance = a.distance_to(b); // ~5.196
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Documentation Structure
|
||||||
|
|
||||||
|
### Core Mathematics
|
||||||
|
|
||||||
|
**Linear Algebra**
|
||||||
|
- [Vector2](linear_algebra/vector2.md) - 2D vectors with full operator support
|
||||||
|
- [Vector3](linear_algebra/vector3.md) - 3D vectors, dot/cross products, angles
|
||||||
|
- [Vector4](linear_algebra/vector4.md) - 4D vectors (homogeneous coordinates)
|
||||||
|
- [Mat4X4](linear_algebra/mat.md) - 4×4 matrices for transformations
|
||||||
|
- [Triangle](linear_algebra/triangle.md) - Triangle primitive and utilities
|
||||||
|
|
||||||
|
**Trigonometry**
|
||||||
|
- [Angle](trigonometry/angle.md) - Strong-typed angle system with range enforcement
|
||||||
|
- [Angles](trigonometry/angles.md) - Angle utilities and conversions
|
||||||
|
- [View Angles](trigonometry/view_angles.md) - Pitch/Yaw/Roll for camera systems
|
||||||
|
|
||||||
|
**3D Primitives**
|
||||||
|
- [Box](3d_primitives/box.md) - Axis-aligned bounding boxes
|
||||||
|
- [Plane](3d_primitives/plane.md) - Infinite planes and intersections
|
||||||
|
|
||||||
|
### Game Development Features
|
||||||
|
|
||||||
|
**Projection & Camera**
|
||||||
|
- [Camera](projection/camera.md) - Generic camera system with engine traits
|
||||||
|
- [Error Codes](projection/error_codes.md) - Projection error handling
|
||||||
|
|
||||||
|
**Collision Detection**
|
||||||
|
- [Line Tracer](collision/line_tracer.md) - Ray-triangle, ray-plane intersections
|
||||||
|
|
||||||
|
**Projectile Prediction**
|
||||||
|
- [Projectile Engine Interface](projectile_prediction/projectile_engine.md) - Base interface
|
||||||
|
- [Projectile](projectile_prediction/projectile.md) - Projectile properties
|
||||||
|
- [Target](projectile_prediction/target.md) - Target state representation
|
||||||
|
- [Legacy Engine](projectile_prediction/proj_pred_engine_legacy.md) - Standard implementation
|
||||||
|
- [AVX2 Engine](projectile_prediction/proj_pred_engine_avx2.md) - Optimized implementation
|
||||||
|
|
||||||
|
**Pathfinding**
|
||||||
|
- [A* Algorithm](pathfinding/a_star.md) - A* pathfinding implementation
|
||||||
|
- [Navigation Mesh](pathfinding/navigation_mesh.md) - Triangle-based navigation
|
||||||
|
|
||||||
|
### Game Engine Support
|
||||||
|
|
||||||
|
OMath provides built-in support for multiple game engines with proper coordinate system handling:
|
||||||
|
|
||||||
|
**Source Engine** (Valve - CS:GO, TF2, etc.)
|
||||||
|
- [Camera Trait](engines/source_engine/camera_trait.md)
|
||||||
|
- [Pred Engine Trait](engines/source_engine/pred_engine_trait.md)
|
||||||
|
- [Constants](engines/source_engine/constants.md)
|
||||||
|
- [Formulas](engines/source_engine/formulas.md)
|
||||||
|
|
||||||
|
**Unity Engine**
|
||||||
|
- [Camera Trait](engines/unity_engine/camera_trait.md)
|
||||||
|
- [Pred Engine Trait](engines/unity_engine/pred_engine_trait.md)
|
||||||
|
- [Constants](engines/unity_engine/constants.md)
|
||||||
|
- [Formulas](engines/unity_engine/formulas.md)
|
||||||
|
|
||||||
|
**Unreal Engine** (Epic Games)
|
||||||
|
- [Camera Trait](engines/unreal_engine/camera_trait.md)
|
||||||
|
- [Pred Engine Trait](engines/unreal_engine/pred_engine_trait.md)
|
||||||
|
- [Constants](engines/unreal_engine/constants.md)
|
||||||
|
- [Formulas](engines/unreal_engine/formulas.md)
|
||||||
|
|
||||||
|
**Frostbite Engine** (EA - Battlefield, etc.)
|
||||||
|
- [Camera Trait](engines/frostbite/camera_trait.md)
|
||||||
|
- [Pred Engine Trait](engines/frostbite/pred_engine_trait.md)
|
||||||
|
- [Constants](engines/frostbite/constants.md)
|
||||||
|
- [Formulas](engines/frostbite/formulas.md)
|
||||||
|
|
||||||
|
**IW Engine** (Infinity Ward - Call of Duty)
|
||||||
|
- [Camera Trait](engines/iw_engine/camera_trait.md)
|
||||||
|
- [Pred Engine Trait](engines/iw_engine/pred_engine_trait.md)
|
||||||
|
- [Constants](engines/iw_engine/constants.md)
|
||||||
|
- [Formulas](engines/iw_engine/formulas.md)
|
||||||
|
|
||||||
|
**OpenGL Engine** (Canonical OpenGL)
|
||||||
|
- [Camera Trait](engines/opengl_engine/camera_trait.md)
|
||||||
|
- [Pred Engine Trait](engines/opengl_engine/pred_engine_trait.md)
|
||||||
|
- [Constants](engines/opengl_engine/constants.md)
|
||||||
|
- [Formulas](engines/opengl_engine/formulas.md)
|
||||||
|
|
||||||
|
### Utilities
|
||||||
|
|
||||||
|
**Color**
|
||||||
|
- [Color](utility/color.md) - RGBA color with conversions
|
||||||
|
|
||||||
|
**Pattern Scanning & Memory**
|
||||||
|
- [Pattern Scan](utility/pattern_scan.md) - Binary pattern search with wildcards
|
||||||
|
- [PE Pattern Scan](utility/pe_pattern_scan.md) - PE file pattern scanning
|
||||||
|
|
||||||
|
**Reverse Engineering**
|
||||||
|
- [External Rev Object](rev_eng/external_rev_object.md) - External process memory access
|
||||||
|
- [Internal Rev Object](rev_eng/internal_rev_object.md) - Internal memory access
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ Key Features
|
||||||
|
|
||||||
|
- **Efficiency**: Optimized for performance, ensuring quick computations using AVX2.
|
||||||
|
- **Versatility**: Includes a wide array of mathematical functions and algorithms.
|
||||||
|
- **Ease of Use**: Simplified interface for convenient integration into various projects.
|
||||||
|
- **Projectile Prediction**: Projectile prediction engine with O(N) algo complexity, that can power you projectile aim-bot.
|
||||||
|
- **3D Projection**: No need to find view-projection matrix anymore you can make your own projection pipeline.
|
||||||
|
- **Collision Detection**: Production ready code to handle collision detection by using simple interfaces.
|
||||||
|
- **No Additional Dependencies**: No additional dependencies need to use OMath except unit test execution
|
||||||
|
- **Ready for meta-programming**: Omath use templates for common types like Vectors, Matrixes etc, to handle all types!
|
||||||
|
- **Engine support**: Supports coordinate systems of **Source, Unity, Unreal, Frostbite, IWEngine and canonical OpenGL**.
|
||||||
|
- **Cross platform**: Supports Windows, MacOS and Linux.
|
||||||
|
- **Algorithms**: Has ability to scan for byte pattern with wildcards in PE files/modules, binary slices, works even with Wine apps.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 Common Use Cases
|
||||||
|
|
||||||
|
### World-to-Screen Projection
|
||||||
|
Project 3D world coordinates to 2D screen space for ESP overlays, UI elements, or visualization.
|
||||||
|
|
||||||
|
### Projectile Prediction
|
||||||
|
Calculate aim points for moving targets considering projectile speed, gravity, and target velocity.
|
||||||
|
|
||||||
|
### Collision Detection
|
||||||
|
Perform ray-casting, line tracing, and intersection tests for hit detection and physics.
|
||||||
|
|
||||||
|
### Pattern Scanning
|
||||||
|
Search for byte patterns in memory for reverse engineering, modding, or tool development.
|
||||||
|
|
||||||
|
### Pathfinding
|
||||||
|
Find optimal paths through 3D spaces using A* algorithm and navigation meshes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎮 Gallery
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
[](https://youtu.be/lM_NJ1yCunw?si=-Qf5yzDcWbaxAXGQ)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
![APEX Preview]
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
![BO2 Preview]
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
![CS2 Preview]
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
![TF2 Preview]
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🤝 Community & Support
|
||||||
|
|
||||||
|
- **Documentation**: [http://libomath.org](http://libomath.org)
|
||||||
|
- **GitHub**: [orange-cpp/omath](https://github.com/orange-cpp/omath)
|
||||||
|
- **Discord**: [Join our community](https://discord.gg/eDgdaWbqwZ)
|
||||||
|
- **Telegram**: [@orangennotes](https://t.me/orangennotes)
|
||||||
|
- **Issues**: [Report bugs or request features](https://github.com/orange-cpp/omath/issues)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 Contributing
|
||||||
|
|
||||||
|
OMath is open source and welcomes contributions! See [CONTRIBUTING.md](https://github.com/orange-cpp/omath/blob/master/CONTRIBUTING.md) for guidelines.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 1 Nov 2025*
|
||||||
|
|
||||||
|
<!----------------------------------{ Images }--------------------------------->
|
||||||
|
[APEX Preview]: images/showcase/apex.png
|
||||||
|
[BO2 Preview]: images/showcase/cod_bo2.png
|
||||||
|
[CS2 Preview]: images/showcase/cs2.jpeg
|
||||||
|
[TF2 Preview]: images/showcase/tf2.jpg
|
||||||
68
docs/install.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Installation
|
||||||
|
|
||||||
|
## <img width="28px" src="https://vcpkg.io/assets/mark/mark.svg" /> Using vcpkg
|
||||||
|
**Note**: Support vcpkg for package management
|
||||||
|
1. Install [vcpkg](https://github.com/microsoft/vcpkg)
|
||||||
|
2. Run the following command to install the orange-math package:
|
||||||
|
```
|
||||||
|
vcpkg install orange-math
|
||||||
|
```
|
||||||
|
CMakeLists.txt
|
||||||
|
```cmake
|
||||||
|
find_package(omath CONFIG REQUIRED)
|
||||||
|
target_link_libraries(main PRIVATE omath::omath)
|
||||||
|
```
|
||||||
|
For detailed commands on installing different versions and more information, please refer to Microsoft's [official instructions](https://learn.microsoft.com/en-us/vcpkg/get_started/overview).
|
||||||
|
|
||||||
|
## <img width="28px" src="https://xmake.io/assets/img/logo.svg" /> Using xrepo
|
||||||
|
**Note**: Support xrepo for package management
|
||||||
|
1. Install [xmake](https://xmake.io/)
|
||||||
|
2. Run the following command to install the omath package:
|
||||||
|
```
|
||||||
|
xrepo install omath
|
||||||
|
```
|
||||||
|
xmake.lua
|
||||||
|
```xmake
|
||||||
|
add_requires("omath")
|
||||||
|
target("...")
|
||||||
|
add_packages("omath")
|
||||||
|
```
|
||||||
|
|
||||||
|
## <img width="28px" src="https://upload.wikimedia.org/wikipedia/commons/e/ef/CMake_logo.svg?" /> Build from source using CMake
|
||||||
|
1. **Preparation**
|
||||||
|
|
||||||
|
Install needed tools: cmake, clang, git, msvc (windows only).
|
||||||
|
|
||||||
|
1. **Linux:**
|
||||||
|
```bash
|
||||||
|
sudo pacman -Sy cmake ninja clang git
|
||||||
|
```
|
||||||
|
2. **MacOS:**
|
||||||
|
```bash
|
||||||
|
brew install llvm git cmake ninja
|
||||||
|
```
|
||||||
|
3. **Windows:**
|
||||||
|
|
||||||
|
Install Visual Studio from [here](https://visualstudio.microsoft.com/downloads/) and Git from [here](https://git-scm.com/downloads).
|
||||||
|
|
||||||
|
Use x64 Native Tools shell to execute needed commands down below.
|
||||||
|
2. **Clone the repository:**
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/orange-cpp/omath.git
|
||||||
|
```
|
||||||
|
3. **Navigate to the project directory:**
|
||||||
|
```bash
|
||||||
|
cd omath
|
||||||
|
```
|
||||||
|
4. **Build the project using CMake:**
|
||||||
|
```bash
|
||||||
|
cmake --preset windows-release -S .
|
||||||
|
cmake --build cmake-build/build/windows-release --target omath -j 6
|
||||||
|
```
|
||||||
|
Use **\<platform\>-\<build configuration\>** preset to build suitable version for yourself. Like **windows-release** or **linux-release**.
|
||||||
|
|
||||||
|
| Platform Name | Build Config |
|
||||||
|
|---------------|---------------|
|
||||||
|
| windows | release/debug |
|
||||||
|
| linux | release/debug |
|
||||||
|
| darwin | release/debug |
|
||||||
428
docs/linear_algebra/mat.md
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
# `omath::Mat` — Matrix class (C++20/23)
|
||||||
|
|
||||||
|
> Header: your project’s `mat.hpp` (requires `vector3.hpp`)
|
||||||
|
> Namespace: `omath`
|
||||||
|
> Requires: **C++23** (uses multi-parameter `operator[]`)
|
||||||
|
> SIMD (optional): define **`OMATH_USE_AVX2`** to enable AVX2-accelerated multiplication for `float`/`double`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
`omath::Mat<Rows, Columns, Type, StoreType>` is a compile-time, fixed-size matrix with:
|
||||||
|
|
||||||
|
* **Row/column counts** as template parameters (no heap allocations).
|
||||||
|
* **Row-major** or **column-major** storage (compile-time via `MatStoreType`).
|
||||||
|
* **Arithmetic** and **linear algebra**: matrix × matrix, scalar ops, transpose, determinant, inverse (optional), etc.
|
||||||
|
* **Transform helpers**: translation, axis rotations, look-at, perspective & orthographic projections.
|
||||||
|
* **I/O helpers**: `to_string`/`to_wstring`/`to_u8string` and `std::formatter` specializations.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template parameters
|
||||||
|
|
||||||
|
| Parameter | Description | Default |
|
||||||
|
| ----------- | ------------------------------------------------------------------------ | ----------- |
|
||||||
|
| `Rows` | Number of rows (size_t, compile-time) | — |
|
||||||
|
| `Columns` | Number of columns (size_t, compile-time) | — |
|
||||||
|
| `Type` | Element type (arithmetic) | `float` |
|
||||||
|
| `StoreType` | Storage order: `MatStoreType::ROW_MAJOR` or `MatStoreType::COLUMN_MAJOR` | `ROW_MAJOR` |
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
enum class MatStoreType : uint8_t { ROW_MAJOR = 0, COLUMN_MAJOR };
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "mat.hpp"
|
||||||
|
using omath::Mat;
|
||||||
|
|
||||||
|
// 4x4 float, row-major
|
||||||
|
Mat<4,4> I = {
|
||||||
|
{1,0,0,0},
|
||||||
|
{0,1,0,0},
|
||||||
|
{0,0,1,0},
|
||||||
|
{0,0,0,1},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Multiply 4x4 transforms
|
||||||
|
Mat<4,4> A = { {1,2,3,0},{0,1,4,0},{5,6,0,0},{0,0,0,1} };
|
||||||
|
Mat<4,4> B = { {2,0,0,0},{0,2,0,0},{0,0,2,0},{0,0,0,1} };
|
||||||
|
Mat<4,4> C = A * B; // matrix × matrix
|
||||||
|
|
||||||
|
// Scalar ops
|
||||||
|
auto D = C * 0.5f; // scale all entries
|
||||||
|
|
||||||
|
// Indexing (C++23 multi-parameter operator[])
|
||||||
|
float a03 = A[0,3]; // same as A.at(0,3)
|
||||||
|
A[1,2] = 42.0f;
|
||||||
|
|
||||||
|
// Transpose, determinant, inverse
|
||||||
|
auto AT = A.transposed();
|
||||||
|
float det = A.determinant(); // only for square matrices
|
||||||
|
auto inv = A.inverted(); // std::optional<Mat>; std::nullopt if non-invertible
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
> Multiplication requires the **same** `StoreType` and `Type` on both operands, and dimensions must match at compile time.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Construction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Mat(); // zero-initialized
|
||||||
|
Mat(std::initializer_list<std::initializer_list<Type>> rows);
|
||||||
|
explicit Mat(const Type* raw_data); // copies Rows*Columns elements
|
||||||
|
Mat(const Mat&); Mat(Mat&&);
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Zeroing/setting**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
m.clear(); // set all entries to 0
|
||||||
|
m.set(3.14f); // set all entries to a value
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Shape & metadata**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Mat<>::row_count(); // constexpr size_t
|
||||||
|
Mat<>::columns_count(); // constexpr size_t
|
||||||
|
Mat<>::size(); // constexpr MatSize {rows, columns}
|
||||||
|
Mat<>::get_store_ordering(); // constexpr MatStoreType
|
||||||
|
using ContainedType = Type; // alias
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Element access
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
T& at(size_t r, size_t c);
|
||||||
|
T const& at(size_t r, size_t c) const;
|
||||||
|
|
||||||
|
T& operator[](size_t r, size_t c); // C++23
|
||||||
|
T const& operator[](size_t r, size_t c) const; // C++23
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Bounds checking**
|
||||||
|
> In debug builds you may enable/disable range checks via your compile-time macros (see the source guard around `at()`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arithmetic
|
||||||
|
|
||||||
|
* **Matrix × matrix**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// (Rows x Columns) * (Columns x OtherColumns) -> (Rows x OtherColumns)
|
||||||
|
template<size_t OtherColumns>
|
||||||
|
Mat<Rows, OtherColumns, Type, StoreType>
|
||||||
|
operator*(const Mat<Columns, OtherColumns, Type, StoreType>&) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
* Complexity: `O(Rows * Columns * OtherColumns)`.
|
||||||
|
* AVX2-accelerated when `OMATH_USE_AVX2` is defined and `Type` is `float` or `double`.
|
||||||
|
|
||||||
|
* **Scalars**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Mat operator*(const Type& s) const; Mat& operator*=(const Type& s);
|
||||||
|
Mat operator/(const Type& s) const; Mat& operator/=(const Type& s);
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Transpose**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Mat<Columns, Rows, Type, StoreType> transposed() const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Determinant (square only)**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Type determinant() const; // 1x1, 2x2 fast path; larger uses Laplace expansion
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Inverse (square only)**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::optional<Mat> inverted() const; // nullopt if det == 0
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Minors & cofactors (square only)**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Mat<Rows-1, Columns-1, Type, StoreType> strip(size_t r, size_t c) const;
|
||||||
|
Type minor(size_t r, size_t c) const;
|
||||||
|
Type alg_complement(size_t r, size_t c) const; // cofactor
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Utilities**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Type sum() const noexcept;
|
||||||
|
auto& raw_array(); // std::array<Type, Rows*Columns>&
|
||||||
|
auto const& raw_array() const;
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Comparison / formatting**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool operator==(const Mat&) const;
|
||||||
|
bool operator!=(const Mat&) const;
|
||||||
|
|
||||||
|
std::string to_string() const noexcept;
|
||||||
|
std::wstring to_wstring() const noexcept;
|
||||||
|
std::u8string to_u8string() const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
// std::formatter specialization provided for char, wchar_t, char8_t
|
||||||
|
|
||||||
|
````
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Storage order notes
|
||||||
|
|
||||||
|
- **Row-major**: `index = row * Columns + column`
|
||||||
|
- **Column-major**: `index = row + column * Rows`
|
||||||
|
|
||||||
|
Choose one **consistently** across your math types and shader conventions. Mixed orders are supported by the type system but not for cross-multiplying (store types must match).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Transform helpers
|
||||||
|
|
||||||
|
### From vectors
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class T=float, MatStoreType St=ROW_MAJOR>
|
||||||
|
Mat<1,4,T,St> mat_row_from_vector(const Vector3<T>& v);
|
||||||
|
|
||||||
|
template<class T=float, MatStoreType St=ROW_MAJOR>
|
||||||
|
Mat<4,1,T,St> mat_column_from_vector(const Vector3<T>& v);
|
||||||
|
````
|
||||||
|
|
||||||
|
### Translation
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class T=float, MatStoreType St=ROW_MAJOR>
|
||||||
|
Mat<4,4,T,St> mat_translation(const Vector3<T>& d) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Axis rotations
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Angle type must provide angle.cos() and angle.sin()
|
||||||
|
template<class T=float, MatStoreType St=ROW_MAJOR, class Angle>
|
||||||
|
Mat<4,4,T,St> mat_rotation_axis_x(const Angle& a) noexcept;
|
||||||
|
|
||||||
|
template<class T=float, MatStoreType St=ROW_MAJOR, class Angle>
|
||||||
|
Mat<4,4,T,St> mat_rotation_axis_y(const Angle& a) noexcept;
|
||||||
|
|
||||||
|
template<class T=float, MatStoreType St=ROW_MAJOR, class Angle>
|
||||||
|
Mat<4,4,T,St> mat_rotation_axis_z(const Angle& a) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Camera/view
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class T=float, MatStoreType St=ROW_MAJOR>
|
||||||
|
Mat<4,4,T,St> mat_camera_view(const Vector3<T>& forward,
|
||||||
|
const Vector3<T>& right,
|
||||||
|
const Vector3<T>& up,
|
||||||
|
const Vector3<T>& camera_origin) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Perspective projections
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class T=float, MatStoreType St=ROW_MAJOR>
|
||||||
|
Mat<4,4,T,St> mat_perspective_left_handed (float fov_deg, float aspect, float near, float far) noexcept;
|
||||||
|
|
||||||
|
template<class T=float, MatStoreType St=ROW_MAJOR>
|
||||||
|
Mat<4,4,T,St> mat_perspective_right_handed(float fov_deg, float aspect, float near, float far) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Orthographic projections
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class T=float, MatStoreType St=ROW_MAJOR>
|
||||||
|
Mat<4,4,T,St> mat_ortho_left_handed (T left, T right, T bottom, T top, T near, T far) noexcept;
|
||||||
|
|
||||||
|
template<class T=float, MatStoreType St=ROW_MAJOR>
|
||||||
|
Mat<4,4,T,St> mat_ortho_right_handed(T left, T right, T bottom, T top, T near, T far) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Look-at matrices
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class T=float, MatStoreType St=COLUMN_MAJOR>
|
||||||
|
Mat<4,4,T,St> mat_look_at_left_handed (const Vector3<T>& eye,
|
||||||
|
const Vector3<T>& center,
|
||||||
|
const Vector3<T>& up);
|
||||||
|
|
||||||
|
template<class T=float, MatStoreType St=COLUMN_MAJOR>
|
||||||
|
Mat<4,4,T,St> mat_look_at_right_handed(const Vector3<T>& eye,
|
||||||
|
const Vector3<T>& center,
|
||||||
|
const Vector3<T>& up);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Screen-space helper
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class Type=float>
|
||||||
|
static constexpr Mat<4,4> to_screen_mat(const Type& screen_w, const Type& screen_h) noexcept;
|
||||||
|
// Maps NDC to screen space (origin top-left, y down)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### 1) Building a left-handed camera and perspective
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using V3 = omath::Vector3<float>;
|
||||||
|
using M4 = omath::Mat<4,4,float, omath::MatStoreType::COLUMN_MAJOR>;
|
||||||
|
|
||||||
|
V3 eye{0, 1, -5}, center{0, 0, 0}, up{0, 1, 0};
|
||||||
|
M4 view = omath::mat_look_at_left_handed<float, omath::MatStoreType::COLUMN_MAJOR>(eye, center, up);
|
||||||
|
|
||||||
|
float fov = 60.f, aspect = 16.f/9.f, n = 0.1f, f = 100.f;
|
||||||
|
M4 proj = omath::mat_perspective_left_handed<float, omath::MatStoreType::COLUMN_MAJOR>(fov, aspect, n, f);
|
||||||
|
|
||||||
|
// final VP
|
||||||
|
M4 vp = proj * view;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2) Inverting a transform safely
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
omath::Mat<4,4> T = omath::mat_translation(omath::Vector3<float>{2,3,4});
|
||||||
|
if (auto inv = T.inverted()) {
|
||||||
|
// use *inv
|
||||||
|
} else {
|
||||||
|
// handle non-invertible
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3) Formatting for logs
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
omath::Mat<2,2> A = { {1,2},{3,4} };
|
||||||
|
std::string s = A.to_string(); // "[[ 1.000, 2.000]\n [ 3.000, 4.000]]"
|
||||||
|
std::string f = std::format("A = {}", A); // uses std::formatter
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
* **Cache-friendly kernels** per storage order when AVX2 is not enabled.
|
||||||
|
* **AVX2 path** (`OMATH_USE_AVX2`) for `float`/`double` implements FMAs with 256-bit vectors for both row-major and column-major multiplication.
|
||||||
|
* Complexity for `A(R×K) * B(K×C)`: **O(RKC)** regardless of storage order.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constraints & concepts
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<typename M1, typename M2>
|
||||||
|
concept MatTemplateEqual =
|
||||||
|
(M1::rows == M2::rows) &&
|
||||||
|
(M1::columns == M2::columns) &&
|
||||||
|
std::is_same_v<typename M1::value_type, typename M2::value_type> &&
|
||||||
|
(M1::store_type == M2::store_type);
|
||||||
|
```
|
||||||
|
|
||||||
|
> Use this concept to constrain generic functions that operate on like-shaped matrices.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exceptions
|
||||||
|
|
||||||
|
* `std::invalid_argument` — initializer list dimensions mismatch.
|
||||||
|
* `std::out_of_range` — out-of-bounds in `at()` when bounds checking is active (see source guard).
|
||||||
|
* `inverted()` does **not** throw; returns `std::nullopt` if `determinant() == 0`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build switches
|
||||||
|
|
||||||
|
* **`OMATH_USE_AVX2`** — enable AVX2 vectorized multiplication paths (`<immintrin.h>` required).
|
||||||
|
* **Debug checks** — the `at()` method contains a conditional range check; refer to the preprocessor guard in the code to enable/disable in your configuration.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Known requirements & interoperability
|
||||||
|
|
||||||
|
* **C++23** is required for multi-parameter `operator[]`. If you target pre-C++23, use `at(r,c)` instead.
|
||||||
|
* All binary operations require matching `Type` and `StoreType`. Convert explicitly if needed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
* `omath::Vector3<T>`
|
||||||
|
* Projection helpers: `mat_perspective_*`, `mat_ortho_*`
|
||||||
|
* View helpers: `mat_look_at_*`, `mat_camera_view`
|
||||||
|
* Construction helpers: `mat_row_from_vector`, `mat_column_from_vector`, `mat_translation`, `mat_rotation_axis_*`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Appendix: API summary (signatures)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Core
|
||||||
|
Mat(); Mat(const Mat&); Mat(Mat&&);
|
||||||
|
Mat(std::initializer_list<std::initializer_list<Type>>);
|
||||||
|
explicit Mat(const Type* raw);
|
||||||
|
Mat& operator=(const Mat&); Mat& operator=(Mat&&);
|
||||||
|
|
||||||
|
static constexpr size_t row_count();
|
||||||
|
static constexpr size_t columns_count();
|
||||||
|
static consteval MatSize size();
|
||||||
|
static constexpr MatStoreType get_store_ordering();
|
||||||
|
|
||||||
|
T& at(size_t r, size_t c);
|
||||||
|
T const& at(size_t r, size_t c) const;
|
||||||
|
T& operator[](size_t r, size_t c);
|
||||||
|
T const& operator[](size_t r, size_t c) const;
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
void set(const Type& v);
|
||||||
|
Type sum() const noexcept;
|
||||||
|
|
||||||
|
template<size_t OC> Mat<Rows,OC,Type,StoreType> operator*(const Mat<Columns,OC,Type,StoreType>&) const;
|
||||||
|
Mat& operator*=(const Type&); Mat operator*(const Type&) const;
|
||||||
|
Mat& operator/=(const Type&); Mat operator/(const Type&) const;
|
||||||
|
|
||||||
|
Mat<Columns,Rows,Type,StoreType> transposed() const noexcept;
|
||||||
|
Type determinant() const; // square only
|
||||||
|
std::optional<Mat> inverted() const; // square only
|
||||||
|
|
||||||
|
Mat<Rows-1,Columns-1,Type,StoreType> strip(size_t r, size_t c) const;
|
||||||
|
Type minor(size_t r, size_t c) const;
|
||||||
|
Type alg_complement(size_t r, size_t c) const;
|
||||||
|
|
||||||
|
auto& raw_array(); auto const& raw_array() const;
|
||||||
|
std::string to_string() const noexcept;
|
||||||
|
std::wstring to_wstring() const noexcept;
|
||||||
|
std::u8string to_u8string() const noexcept;
|
||||||
|
|
||||||
|
bool operator==(const Mat&) const;
|
||||||
|
bool operator!=(const Mat&) const;
|
||||||
|
|
||||||
|
// Helpers (see sections above)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 31 Oct 2025*
|
||||||
173
docs/linear_algebra/triangle.md
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
# `omath::Triangle` — Simple 3D triangle utility
|
||||||
|
|
||||||
|
> Header: your project’s `triangle.hpp`
|
||||||
|
> Namespace: `omath`
|
||||||
|
> Depends on: `omath::Vector3<float>` (from `vector3.hpp`)
|
||||||
|
|
||||||
|
A tiny helper around three `Vector3<float>` vertices with convenience methods for normals, edge vectors/lengths, a right-angle test (at **`v2`**), and the triangle centroid.
|
||||||
|
|
||||||
|
> **Note on the template parameter**
|
||||||
|
>
|
||||||
|
> The class is declared as `template<class Vector> class Triangle`, but the stored vertices are concretely `Vector3<float>`. In practice this type is currently **fixed to `Vector3<float>`**. You can ignore the template parameter or refactor to store `Vector` if you intend true genericity.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Vertex layout & naming
|
||||||
|
|
||||||
|
```
|
||||||
|
v1
|
||||||
|
|\
|
||||||
|
| \
|
||||||
|
a | \ hypot = |v1 - v3|
|
||||||
|
| \
|
||||||
|
v2 -- v3
|
||||||
|
b
|
||||||
|
|
||||||
|
a = |v1 - v2| (side_a_length)
|
||||||
|
b = |v3 - v2| (side_b_length)
|
||||||
|
```
|
||||||
|
|
||||||
|
* **`side_a_vector()`** = `v1 - v2` (points from v2 → v1)
|
||||||
|
* **`side_b_vector()`** = `v3 - v2` (points from v2 → v3)
|
||||||
|
* **Right-angle check** uses `a² + b² ≈ hypot²` with an epsilon of `1e-4`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "triangle.hpp"
|
||||||
|
using omath::Vector3;
|
||||||
|
using omath::Triangle;
|
||||||
|
|
||||||
|
Triangle<void> tri( // template arg unused; any placeholder ok
|
||||||
|
Vector3<float>{0,0,0}, // v1
|
||||||
|
Vector3<float>{0,0,1}, // v2 (right angle is tested at v2)
|
||||||
|
Vector3<float>{1,0,1} // v3
|
||||||
|
);
|
||||||
|
|
||||||
|
auto n = tri.calculate_normal(); // unit normal (right-handed: (v3-v2) × (v1-v2))
|
||||||
|
float a = tri.side_a_length(); // |v1 - v2|
|
||||||
|
float b = tri.side_b_length(); // |v3 - v2|
|
||||||
|
float hyp = tri.hypot(); // |v1 - v3|
|
||||||
|
bool rect = tri.is_rectangular(); // true if ~right triangle at v2
|
||||||
|
auto C = tri.mid_point(); // centroid (average of v1,v2,v3)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data members
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector3<float> m_vertex1; // v1
|
||||||
|
Vector3<float> m_vertex2; // v2 (the corner tested by is_rectangular)
|
||||||
|
Vector3<float> m_vertex3; // v3
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constructors
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Triangle() = default;
|
||||||
|
constexpr Triangle(const Vector3<float>& v1,
|
||||||
|
const Vector3<float>& v2,
|
||||||
|
const Vector3<float>& v3);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Normal (unit) using right-handed cross product:
|
||||||
|
// n = (v3 - v2) × (v1 - v2), then normalized()
|
||||||
|
[[nodiscard]] constexpr Vector3<float> calculate_normal() const;
|
||||||
|
|
||||||
|
// Edge lengths with the naming from the diagram
|
||||||
|
[[nodiscard]] float side_a_length() const; // |v1 - v2|
|
||||||
|
[[nodiscard]] float side_b_length() const; // |v3 - v2|
|
||||||
|
|
||||||
|
// Edge vectors (from v2 to the other vertex)
|
||||||
|
[[nodiscard]] constexpr Vector3<float> side_a_vector() const; // v1 - v2
|
||||||
|
[[nodiscard]] constexpr Vector3<float> side_b_vector() const; // v3 - v2
|
||||||
|
|
||||||
|
// Hypotenuse length between v1 and v3
|
||||||
|
[[nodiscard]] constexpr float hypot() const; // |v1 - v3|
|
||||||
|
|
||||||
|
// Right-triangle check at vertex v2 (Pythagoras with epsilon 1e-4)
|
||||||
|
[[nodiscard]] constexpr bool is_rectangular() const;
|
||||||
|
|
||||||
|
// Centroid of the triangle (average of the 3 vertices)
|
||||||
|
[[nodiscard]] constexpr Vector3<float> mid_point() const; // actually the centroid
|
||||||
|
```
|
||||||
|
|
||||||
|
### Notes & edge cases
|
||||||
|
|
||||||
|
* **Normal direction** follows the right-hand rule for the ordered vertices `{v2 → v3} × {v2 → v1}`.
|
||||||
|
Swap vertex order to flip the normal.
|
||||||
|
* **Degenerate triangles** (collinear or overlapping vertices) yield a **zero vector** normal (since `normalized()` of the zero vector returns the zero vector in your math types).
|
||||||
|
* **`mid_point()` is the centroid**, not the midpoint of any single edge. If you need the midpoint of edge `v1–v2`, use `(m_vertex1 + m_vertex2) * 0.5f`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Area and plane from existing API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const auto a = tri.side_a_vector();
|
||||||
|
const auto b = tri.side_b_vector();
|
||||||
|
const auto n = b.cross(a); // unnormalized normal
|
||||||
|
float area = 0.5f * n.length(); // triangle area
|
||||||
|
|
||||||
|
// Plane equation n̂·(x - v2) = 0
|
||||||
|
auto nhat = n.length() > 0 ? n / n.length() : n;
|
||||||
|
float d = -nhat.dot(tri.m_vertex2);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Project a point onto the triangle’s plane
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector3<float> p{0.3f, 1.0f, 0.7f};
|
||||||
|
auto n = tri.calculate_normal();
|
||||||
|
float t = n.dot(tri.m_vertex2 - p); // signed distance along normal
|
||||||
|
auto projected = p + n * t; // on-plane projection
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API summary (signatures)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Triangle final {
|
||||||
|
public:
|
||||||
|
constexpr Triangle();
|
||||||
|
constexpr Triangle(const Vector3<float>& v1,
|
||||||
|
const Vector3<float>& v2,
|
||||||
|
const Vector3<float>& v3);
|
||||||
|
|
||||||
|
Vector3<float> m_vertex1, m_vertex2, m_vertex3;
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr Vector3<float> calculate_normal() const;
|
||||||
|
[[nodiscard]] float side_a_length() const;
|
||||||
|
[[nodiscard]] float side_b_length() const;
|
||||||
|
[[nodiscard]] constexpr Vector3<float> side_a_vector() const;
|
||||||
|
[[nodiscard]] constexpr Vector3<float> side_b_vector() const;
|
||||||
|
[[nodiscard]] constexpr float hypot() const;
|
||||||
|
[[nodiscard]] constexpr bool is_rectangular() const;
|
||||||
|
[[nodiscard]] constexpr Vector3<float> mid_point() const;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Suggestions (optional improvements)
|
||||||
|
|
||||||
|
* If generic vectors are intended, store `Vector m_vertex*;` and constrain `Vector` to the required ops (`-`, `cross`, `normalized`, `distance_to`, `+`, `/`).
|
||||||
|
* Consider renaming `mid_point()` → `centroid()` to avoid ambiguity.
|
||||||
|
* Expose an `area()` helper and (optionally) a barycentric coordinate routine if you plan to use this in rasterization or intersection tests.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 31 Oct 2025*
|
||||||
300
docs/linear_algebra/vector2.md
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
# `omath::Vector2` — 2D vector (C++20/23)
|
||||||
|
|
||||||
|
> Header: your project’s `vector2.hpp`
|
||||||
|
> Namespace: `omath`
|
||||||
|
> Template: `template<class Type> requires std::is_arithmetic_v<Type>`
|
||||||
|
|
||||||
|
`Vector2<Type>` is a lightweight, POD-like 2D math type with arithmetic, geometry helpers, comparisons, hashing (for `float`), optional ImGui interop, and `std::formatter` support.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "vector2.hpp"
|
||||||
|
using omath::Vector2;
|
||||||
|
|
||||||
|
using Vec2f = Vector2<float>;
|
||||||
|
|
||||||
|
Vec2f a{3.f, 4.f};
|
||||||
|
Vec2f b{1.f, 2.f};
|
||||||
|
|
||||||
|
auto d = a.distance_to(b); // ≈ 3.1623
|
||||||
|
auto dot = a.dot(b); // 11
|
||||||
|
auto len = a.length(); // 5
|
||||||
|
auto unit_a = a.normalized(); // (0.6, 0.8)
|
||||||
|
|
||||||
|
// Component-wise mutate
|
||||||
|
Vec2f c{2, 3};
|
||||||
|
c *= b; // c -> (2*1, 3*2) = (2, 6)
|
||||||
|
|
||||||
|
// Scalar ops (non-mutating + mutating)
|
||||||
|
auto scaled = a * 0.5f; // (1.5, 2)
|
||||||
|
a *= 2.f; // (6, 8)
|
||||||
|
|
||||||
|
// Ordering by length()
|
||||||
|
bool shorter = (b < a);
|
||||||
|
|
||||||
|
// Formatted printing
|
||||||
|
std::string s = std::format("a = {}", a); // "a = [6, 8]"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Members
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Type x{0};
|
||||||
|
Type y{0};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constructors
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector2(); // (0,0)
|
||||||
|
constexpr Vector2(const Type& x, const Type& y) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Equality & ordering
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr bool operator==(const Vector2&) const noexcept; // component-wise equality
|
||||||
|
constexpr bool operator!=(const Vector2&) const noexcept;
|
||||||
|
|
||||||
|
bool operator< (const Vector2&) const noexcept; // compares by length()
|
||||||
|
bool operator> (const Vector2&) const noexcept;
|
||||||
|
bool operator<=(const Vector2&) const noexcept;
|
||||||
|
bool operator>=(const Vector2&) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** `<`, `>`, `<=`, `>=` order vectors by **magnitude** (not lexicographically).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arithmetic
|
||||||
|
|
||||||
|
### With another vector (component-wise, **mutating**)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector2& operator+=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator-=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator*=(const Vector2&) noexcept; // Hadamard product (x*=x, y*=y)
|
||||||
|
Vector2& operator/=(const Vector2&) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
> Non-mutating `v * u` / `v / u` (vector × vector) are **not** provided.
|
||||||
|
> Use `v *= u` (mutating) or build a new vector explicitly.
|
||||||
|
|
||||||
|
### With a scalar
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector2& operator*=(const Type& v) noexcept;
|
||||||
|
Vector2& operator/=(const Type& v) noexcept;
|
||||||
|
Vector2& operator+=(const Type& v) noexcept;
|
||||||
|
Vector2& operator-=(const Type& v) noexcept;
|
||||||
|
|
||||||
|
constexpr Vector2 operator*(const Type& v) const noexcept;
|
||||||
|
constexpr Vector2 operator/(const Type& v) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Binary (+/−) with another vector (non-mutating)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector2 operator+(const Vector2&) const noexcept;
|
||||||
|
constexpr Vector2 operator-(const Vector2&) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unary
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector2 operator-() const noexcept; // negation
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Geometry & helpers
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Type distance_to (const Vector2&) const noexcept; // sqrt of squared distance
|
||||||
|
constexpr Type distance_to_sqr(const Vector2&) const noexcept;
|
||||||
|
|
||||||
|
constexpr Type dot(const Vector2&) const noexcept;
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
constexpr Type length() const noexcept; // uses std::hypot; constexpr on non-MSVC
|
||||||
|
constexpr Vector2 normalized() const noexcept; // returns *this if length==0
|
||||||
|
#else
|
||||||
|
Type length() const noexcept;
|
||||||
|
Vector2 normalized() const noexcept;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
constexpr Type length_sqr() const noexcept; // x*x + y*y
|
||||||
|
Vector2& abs() noexcept; // component-wise absolute (constexpr-friendly impl)
|
||||||
|
|
||||||
|
constexpr Type sum() const noexcept; // x + y
|
||||||
|
constexpr std::tuple<Type, Type> as_tuple() const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ImGui integration (optional)
|
||||||
|
|
||||||
|
Define `OMATH_IMGUI_INTEGRATION` **before** including the header.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#ifdef OMATH_IMGUI_INTEGRATION
|
||||||
|
constexpr ImVec2 to_im_vec2() const noexcept; // {float(x), float(y)}
|
||||||
|
static Vector2 from_im_vec2(const ImVec2&) noexcept;
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hashing & formatting
|
||||||
|
|
||||||
|
* **Hash (for `Vector2<float>`)**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<> struct std::hash<omath::Vector2<float>> {
|
||||||
|
std::size_t operator()(const omath::Vector2<float>&) const noexcept;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::unordered_set<omath::Vector2<float>> set;
|
||||||
|
set.insert({1.f, 2.f});
|
||||||
|
```
|
||||||
|
|
||||||
|
* **`std::formatter`** (for any `Type`)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// prints "[x, y]" for char / wchar_t / char8_t
|
||||||
|
template<class Type>
|
||||||
|
struct std::formatter<omath::Vector2<Type>>;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & invariants
|
||||||
|
|
||||||
|
* `Type` must be arithmetic (e.g., `float`, `double`, `int`, …).
|
||||||
|
* `normalized()` returns the input unchanged if `length() == 0`.
|
||||||
|
* `abs()` uses a constexpr-friendly implementation (not `std::abs`) to allow compile-time evaluation.
|
||||||
|
* On MSVC, `length()`/`normalized()` are not `constexpr` due to library constraints; they’re still `noexcept`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Component-wise operations and scalar scaling
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
omath::Vector2<float> u{2, 3}, v{4, 5};
|
||||||
|
|
||||||
|
u += v; // (6, 8)
|
||||||
|
u -= v; // (2, 3)
|
||||||
|
u *= v; // (8, 15) Hadamard product (mutates u)
|
||||||
|
auto w = v * 2.0f; // (8, 10) non-mutating scalar multiply
|
||||||
|
```
|
||||||
|
|
||||||
|
### Geometry helpers
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
omath::Vector2<double> p{0.0, 0.0}, q{3.0, 4.0};
|
||||||
|
|
||||||
|
auto dsq = p.distance_to_sqr(q); // 25
|
||||||
|
auto d = p.distance_to(q); // 5
|
||||||
|
auto dot = p.dot(q); // 0
|
||||||
|
auto uq = q.normalized(); // (0.6, 0.8)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using as a key in unordered containers (`float`)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::unordered_map<omath::Vector2<float>, int> counts;
|
||||||
|
counts[{1.f, 2.f}] = 42;
|
||||||
|
```
|
||||||
|
|
||||||
|
### ImGui interop
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define OMATH_IMGUI_INTEGRATION
|
||||||
|
#include "vector2.hpp"
|
||||||
|
|
||||||
|
omath::Vector2<float> v{10, 20};
|
||||||
|
ImVec2 iv = v.to_im_vec2();
|
||||||
|
v = omath::Vector2<float>::from_im_vec2(iv);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API summary (signatures)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Constructors
|
||||||
|
constexpr Vector2();
|
||||||
|
constexpr Vector2(const Type& x, const Type& y) noexcept;
|
||||||
|
|
||||||
|
// Equality & ordering
|
||||||
|
constexpr bool operator==(const Vector2&) const noexcept;
|
||||||
|
constexpr bool operator!=(const Vector2&) const noexcept;
|
||||||
|
bool operator< (const Vector2&) const noexcept;
|
||||||
|
bool operator> (const Vector2&) const noexcept;
|
||||||
|
bool operator<=(const Vector2&) const noexcept;
|
||||||
|
bool operator>=(const Vector2&) const noexcept;
|
||||||
|
|
||||||
|
// Compound (vector/vector and scalar)
|
||||||
|
Vector2& operator+=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator-=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator*=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator/=(const Vector2&) noexcept;
|
||||||
|
Vector2& operator*=(const Type&) noexcept;
|
||||||
|
Vector2& operator/=(const Type&) noexcept;
|
||||||
|
Vector2& operator+=(const Type&) noexcept;
|
||||||
|
Vector2& operator-=(const Type&) noexcept;
|
||||||
|
|
||||||
|
// Non-mutating arithmetic
|
||||||
|
constexpr Vector2 operator+(const Vector2&) const noexcept;
|
||||||
|
constexpr Vector2 operator-(const Vector2&) const noexcept;
|
||||||
|
constexpr Vector2 operator*(const Type&) const noexcept;
|
||||||
|
constexpr Vector2 operator/(const Type&) const noexcept;
|
||||||
|
constexpr Vector2 operator-() const noexcept;
|
||||||
|
|
||||||
|
// Geometry
|
||||||
|
Type distance_to(const Vector2&) const noexcept;
|
||||||
|
constexpr Type distance_to_sqr(const Vector2&) const noexcept;
|
||||||
|
constexpr Type dot(const Vector2&) const noexcept;
|
||||||
|
Type length() const noexcept; // constexpr on non-MSVC
|
||||||
|
Vector2 normalized() const noexcept; // constexpr on non-MSVC
|
||||||
|
constexpr Type length_sqr() const noexcept;
|
||||||
|
Vector2& abs() noexcept;
|
||||||
|
constexpr Type sum() const noexcept;
|
||||||
|
constexpr std::tuple<Type,Type> as_tuple() const noexcept;
|
||||||
|
|
||||||
|
// ImGui (optional)
|
||||||
|
#ifdef OMATH_IMGUI_INTEGRATION
|
||||||
|
constexpr ImVec2 to_im_vec2() const noexcept;
|
||||||
|
static Vector2 from_im_vec2(const ImVec2&) noexcept;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Hash (float) and formatter are specialized in the header
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Vector3 Documentation](vector3.md) - 3D vector operations
|
||||||
|
- [Vector4 Documentation](vector4.md) - 4D vector operations
|
||||||
|
- [Getting Started Guide](../getting_started.md) - Quick start with OMath
|
||||||
|
- [Tutorials](../tutorials.md) - Step-by-step examples
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 1 Nov 2025*
|
||||||
307
docs/linear_algebra/vector3.md
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
# `omath::Vector3` — 3D vector (C++20/23)
|
||||||
|
|
||||||
|
> Header: your project’s `vector3.hpp`
|
||||||
|
> Namespace: `omath`
|
||||||
|
> Template: `template<class Type> requires std::is_arithmetic_v<Type>`
|
||||||
|
> Depends on: `omath::Vector2<Type>` (base class), `omath::Angle` (for `angle_between`)
|
||||||
|
> C++: uses `std::expected` ⇒ **C++23** recommended (or a backport)
|
||||||
|
|
||||||
|
`Vector3<Type>` extends `Vector2<Type>` with a `z` component and 3D operations: arithmetic, geometry (dot, cross, distance), normalization, angle-between with robust error signaling, hashing (for `float`) and `std::formatter` support.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "vector3.hpp"
|
||||||
|
using omath::Vector3;
|
||||||
|
|
||||||
|
using Vec3f = Vector3<float>;
|
||||||
|
|
||||||
|
Vec3f a{3, 4, 0};
|
||||||
|
Vec3f b{1, 2, 2};
|
||||||
|
|
||||||
|
auto d = a.distance_to(b); // Euclidean distance
|
||||||
|
auto dot = a.dot(b); // 3*1 + 4*2 + 0*2 = 11
|
||||||
|
auto cr = a.cross(b); // (8, -6, 2)
|
||||||
|
auto len = a.length(); // hypot(x,y,z)
|
||||||
|
auto unit = a.normalized(); // safe normalize (returns a if length==0)
|
||||||
|
|
||||||
|
if (auto ang = a.angle_between(b)) {
|
||||||
|
float deg = ang->as_degrees(); // [0, 180], clamped
|
||||||
|
} else {
|
||||||
|
// vectors have zero length -> no defined angle
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data members
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Type x{0}; // inherited from Vector2<Type>
|
||||||
|
Type y{0}; // inherited from Vector2<Type>
|
||||||
|
Type z{0};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constructors
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector3() noexcept;
|
||||||
|
constexpr Vector3(const Type& x, const Type& y, const Type& z) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Equality & ordering
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr bool operator==(const Vector3&) const noexcept; // component-wise
|
||||||
|
constexpr bool operator!=(const Vector3&) const noexcept;
|
||||||
|
|
||||||
|
bool operator< (const Vector3&) const noexcept; // compare by length()
|
||||||
|
bool operator> (const Vector3&) const noexcept;
|
||||||
|
bool operator<=(const Vector3&) const noexcept;
|
||||||
|
bool operator>=(const Vector3&) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** Ordering uses **magnitude**, not lexicographic order.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arithmetic (mutating)
|
||||||
|
|
||||||
|
Component-wise with another vector:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector3& operator+=(const Vector3&) noexcept;
|
||||||
|
Vector3& operator-=(const Vector3&) noexcept;
|
||||||
|
Vector3& operator*=(const Vector3&) noexcept; // Hadamard product
|
||||||
|
Vector3& operator/=(const Vector3&) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
With a scalar:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector3& operator*=(const Type& v) noexcept;
|
||||||
|
Vector3& operator/=(const Type& v) noexcept;
|
||||||
|
Vector3& operator+=(const Type& v) noexcept;
|
||||||
|
Vector3& operator-=(const Type& v) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arithmetic (non-mutating)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector3 operator-() const noexcept;
|
||||||
|
constexpr Vector3 operator+(const Vector3&) const noexcept;
|
||||||
|
constexpr Vector3 operator-(const Vector3&) const noexcept;
|
||||||
|
constexpr Vector3 operator*(const Vector3&) const noexcept; // Hadamard
|
||||||
|
constexpr Vector3 operator/(const Vector3&) const noexcept; // Hadamard
|
||||||
|
constexpr Vector3 operator*(const Type& scalar) const noexcept;
|
||||||
|
constexpr Vector3 operator/(const Type& scalar) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Geometry & helpers
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Distances & lengths
|
||||||
|
Type distance_to(const Vector3&) const; // sqrt of squared distance
|
||||||
|
constexpr Type distance_to_sqr(const Vector3&) const noexcept;
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
constexpr Type length() const; // hypot(x,y,z)
|
||||||
|
constexpr Type length_2d() const; // 2D length from base
|
||||||
|
constexpr Vector3 normalized() const; // returns *this if length==0
|
||||||
|
#else
|
||||||
|
Type length() const noexcept;
|
||||||
|
Type length_2d() const noexcept;
|
||||||
|
Vector3 normalized() const noexcept;
|
||||||
|
#endif
|
||||||
|
constexpr Type length_sqr() const noexcept;
|
||||||
|
|
||||||
|
// Products
|
||||||
|
constexpr Type dot(const Vector3&) const noexcept;
|
||||||
|
constexpr Vector3 cross(const Vector3&) const noexcept; // right-handed
|
||||||
|
|
||||||
|
// Sums & tuples
|
||||||
|
constexpr Type sum() const noexcept; // x + y + z
|
||||||
|
constexpr Type sum_2d() const noexcept; // x + y
|
||||||
|
constexpr auto as_tuple() const noexcept -> std::tuple<Type,Type,Type>;
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
Vector3& abs() noexcept; // component-wise absolute
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Angles & orthogonality
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
enum class Vector3Error { IMPOSSIBLE_BETWEEN_ANGLE };
|
||||||
|
|
||||||
|
// Angle in degrees, clamped to [0,180]. Error if any vector has zero length.
|
||||||
|
std::expected<
|
||||||
|
omath::Angle<float, 0.f, 180.f, AngleFlags::Clamped>,
|
||||||
|
Vector3Error
|
||||||
|
> angle_between(const Vector3& other) const noexcept;
|
||||||
|
|
||||||
|
bool is_perpendicular(const Vector3& other) const noexcept; // true if angle == 90°
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hashing & formatting
|
||||||
|
|
||||||
|
* **Hash (for `Vector3<float>`)**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<> struct std::hash<omath::Vector3<float>> {
|
||||||
|
std::size_t operator()(const omath::Vector3<float>&) const noexcept;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::unordered_map<omath::Vector3<float>, int> counts;
|
||||||
|
counts[{1.f, 2.f, 3.f}] = 7;
|
||||||
|
```
|
||||||
|
|
||||||
|
* **`std::formatter`** (all character types)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class Type>
|
||||||
|
struct std::formatter<omath::Vector3<Type>>; // prints "[x, y, z]"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Error handling
|
||||||
|
|
||||||
|
* `angle_between()` returns `std::unexpected(Vector3Error::IMPOSSIBLE_BETWEEN_ANGLE)` if either vector length is zero.
|
||||||
|
* Other operations are total for arithmetic `Type` (no throwing behavior in this class).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Cross product & perpendicular check
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
omath::Vector3<float> x{1,0,0}, y{0,1,0};
|
||||||
|
auto z = x.cross(y); // (0,0,1)
|
||||||
|
bool perp = x.is_perpendicular(y); // true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Safe normalization and angle
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
omath::Vector3<float> u{0,0,0}, v{1,1,0};
|
||||||
|
auto nu = u.normalized(); // returns {0,0,0}
|
||||||
|
if (auto ang = u.angle_between(v)) {
|
||||||
|
// won't happen: u has zero length → error
|
||||||
|
} else {
|
||||||
|
// handle degenerate case
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hadamard vs scalar multiply
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
omath::Vector3<float> a{2,3,4}, b{5,6,7};
|
||||||
|
auto h = a * b; // (10, 18, 28) component-wise
|
||||||
|
auto s = a * 2.f; // (4, 6, 8) scalar
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API summary (signatures)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Ctors
|
||||||
|
constexpr Vector3() noexcept;
|
||||||
|
constexpr Vector3(const Type& x, const Type& y, const Type& z) noexcept;
|
||||||
|
|
||||||
|
// Equality & ordering
|
||||||
|
constexpr bool operator==(const Vector3&) const noexcept;
|
||||||
|
constexpr bool operator!=(const Vector3&) const noexcept;
|
||||||
|
bool operator< (const Vector3&) const noexcept;
|
||||||
|
bool operator> (const Vector3&) const noexcept;
|
||||||
|
bool operator<=(const Vector3&) const noexcept;
|
||||||
|
bool operator>=(const Vector3&) const noexcept;
|
||||||
|
|
||||||
|
// Mutating arithmetic
|
||||||
|
Vector3& operator+=(const Vector3&) noexcept;
|
||||||
|
Vector3& operator-=(const Vector3&) noexcept;
|
||||||
|
Vector3& operator*=(const Vector3&) noexcept;
|
||||||
|
Vector3& operator/=(const Vector3&) noexcept;
|
||||||
|
Vector3& operator*=(const Type&) noexcept;
|
||||||
|
Vector3& operator/=(const Type&) noexcept;
|
||||||
|
Vector3& operator+=(const Type&) noexcept;
|
||||||
|
Vector3& operator-=(const Type&) noexcept;
|
||||||
|
|
||||||
|
// Non-mutating arithmetic
|
||||||
|
constexpr Vector3 operator-() const noexcept;
|
||||||
|
constexpr Vector3 operator+(const Vector3&) const noexcept;
|
||||||
|
constexpr Vector3 operator-(const Vector3&) const noexcept;
|
||||||
|
constexpr Vector3 operator*(const Vector3&) const noexcept;
|
||||||
|
constexpr Vector3 operator/(const Vector3&) const noexcept;
|
||||||
|
constexpr Vector3 operator*(const Type&) const noexcept;
|
||||||
|
constexpr Vector3 operator/(const Type&) const noexcept;
|
||||||
|
|
||||||
|
// Geometry
|
||||||
|
Type distance_to(const Vector3&) const;
|
||||||
|
constexpr Type distance_to_sqr(const Vector3&) const noexcept;
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
constexpr Type length() const;
|
||||||
|
constexpr Type length_2d() const;
|
||||||
|
constexpr Vector3 normalized() const;
|
||||||
|
#else
|
||||||
|
Type length() const noexcept;
|
||||||
|
Type length_2d() const noexcept;
|
||||||
|
Vector3 normalized() const noexcept;
|
||||||
|
#endif
|
||||||
|
constexpr Type length_sqr() const noexcept;
|
||||||
|
constexpr Type dot(const Vector3&) const noexcept;
|
||||||
|
constexpr Vector3 cross(const Vector3&) const noexcept;
|
||||||
|
|
||||||
|
Vector3& abs() noexcept;
|
||||||
|
constexpr Type sum() const noexcept;
|
||||||
|
constexpr Type sum_2d() const noexcept;
|
||||||
|
constexpr auto as_tuple() const noexcept -> std::tuple<Type,Type,Type>;
|
||||||
|
|
||||||
|
// Angles
|
||||||
|
std::expected<omath::Angle<float,0.f,180.f,AngleFlags::Clamped>, omath::Vector3Error>
|
||||||
|
angle_between(const Vector3&) const noexcept;
|
||||||
|
bool is_perpendicular(const Vector3&) const noexcept;
|
||||||
|
|
||||||
|
// Hash (float) and formatter specializations provided below the class
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
* Inherits all public API of `Vector2<Type>` (including `x`, `y`, many operators, and helpers used internally).
|
||||||
|
* `normalized()` returns the original vector if its length is zero (no NaNs).
|
||||||
|
* `cross()` uses the standard right-handed definition.
|
||||||
|
* `length()`/`normalized()` are `constexpr` on non-MSVC; MSVC builds provide `noexcept` runtime versions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Vector2 Documentation](vector2.md) - 2D vector operations
|
||||||
|
- [Vector4 Documentation](vector4.md) - 4D vector operations
|
||||||
|
- [Angle Documentation](../trigonometry/angle.md) - Working with angles
|
||||||
|
- [Getting Started Guide](../getting_started.md) - Quick start with OMath
|
||||||
|
- [Tutorials](../tutorials.md) - Practical examples including vector math
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 1 Nov 2025*
|
||||||
253
docs/linear_algebra/vector4.md
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
# `omath::Vector4` — 4D vector (C++20/23)
|
||||||
|
|
||||||
|
> Header: your project’s `vector4.hpp`
|
||||||
|
> Namespace: `omath`
|
||||||
|
> Template: `template<class Type> requires std::is_arithmetic_v<Type>`
|
||||||
|
> Inherits: `omath::Vector3<Type>` (brings `x`, `y`, `z` and most scalar ops)
|
||||||
|
|
||||||
|
`Vector4<Type>` extends `Vector3<Type>` with a `w` component and 4D operations: component-wise arithmetic, scalar ops, dot/length helpers, clamping, hashing (for `float`) and `std::formatter` support. Optional ImGui interop is available behind a macro.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "vector4.hpp"
|
||||||
|
using omath::Vector4;
|
||||||
|
|
||||||
|
using Vec4f = Vector4<float>;
|
||||||
|
|
||||||
|
Vec4f a{1, 2, 3, 1};
|
||||||
|
Vec4f b{4, 5, 6, 2};
|
||||||
|
|
||||||
|
// Component-wise & scalar ops
|
||||||
|
auto c = a + b; // (5, 7, 9, 3)
|
||||||
|
c *= 0.5f; // (2.5, 3.5, 4.5, 1.5)
|
||||||
|
auto h = a * b; // Hadamard: (4, 10, 18, 2)
|
||||||
|
|
||||||
|
// Dot / length
|
||||||
|
float d = a.dot(b); // 1*4 + 2*5 + 3*6 + 1*2 = 32
|
||||||
|
float L = a.length(); // sqrt(x²+y²+z²+w²)
|
||||||
|
|
||||||
|
// Clamp (x,y,z only; see notes)
|
||||||
|
Vec4f col{1.4f, -0.2f, 0.7f, 42.f};
|
||||||
|
col.clamp(0.f, 1.f); // -> (1, 0, 0.7, w unchanged)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data members
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Inherited from Vector3<Type>:
|
||||||
|
Type x{0};
|
||||||
|
Type y{0};
|
||||||
|
Type z{0};
|
||||||
|
|
||||||
|
// Added in Vector4:
|
||||||
|
Type w{0};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constructors
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector4() noexcept; // (0,0,0,0)
|
||||||
|
constexpr Vector4(const Type& x, const Type& y,
|
||||||
|
const Type& z, const Type& w); // value-init
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Equality & ordering
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr bool operator==(const Vector4&) const noexcept; // component-wise
|
||||||
|
constexpr bool operator!=(const Vector4&) const noexcept;
|
||||||
|
|
||||||
|
bool operator< (const Vector4&) const noexcept; // compare by length()
|
||||||
|
bool operator> (const Vector4&) const noexcept;
|
||||||
|
bool operator<=(const Vector4&) const noexcept;
|
||||||
|
bool operator>=(const Vector4&) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** Ordering uses **magnitude** (Euclidean norm), not lexicographic order.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arithmetic (mutating)
|
||||||
|
|
||||||
|
With another vector (component-wise):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector4& operator+=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator-=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator*=(const Vector4&) noexcept; // Hadamard
|
||||||
|
Vector4& operator/=(const Vector4&) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
With a scalar:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Vector4& operator*=(const Type& v) noexcept;
|
||||||
|
Vector4& operator/=(const Type& v) noexcept;
|
||||||
|
|
||||||
|
// From base class (inherited):
|
||||||
|
Vector4& operator+=(const Type& v) noexcept; // adds v to x,y,z (and w via base? see notes)
|
||||||
|
Vector4& operator-=(const Type& v) noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arithmetic (non-mutating)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Vector4 operator-() const noexcept;
|
||||||
|
constexpr Vector4 operator+(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator-(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator*(const Vector4&) const noexcept; // Hadamard
|
||||||
|
constexpr Vector4 operator/(const Vector4&) const noexcept; // Hadamard
|
||||||
|
constexpr Vector4 operator*(const Type& scalar) const noexcept;
|
||||||
|
constexpr Vector4 operator/(const Type& scalar) const noexcept;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Geometry & helpers
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
constexpr Type length_sqr() const noexcept; // x² + y² + z² + w²
|
||||||
|
Type length() const noexcept; // std::sqrt(length_sqr())
|
||||||
|
constexpr Type dot(const Vector4& rhs) const noexcept;
|
||||||
|
|
||||||
|
Vector4& abs() noexcept; // component-wise absolute
|
||||||
|
Vector4& clamp(const Type& min, const Type& max) noexcept;
|
||||||
|
// clamps x,y,z; leaves w unchanged (see notes)
|
||||||
|
constexpr Type sum() const noexcept; // x + y + z + w
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ImGui integration (optional)
|
||||||
|
|
||||||
|
Guarded by `OMATH_IMGUI_INTEGRATION`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#ifdef OMATH_IMGUI_INTEGRATION
|
||||||
|
constexpr ImVec4 to_im_vec4() const noexcept;
|
||||||
|
// NOTE: Provided signature returns Vector4<float> and (in current code) sets only x,y,z.
|
||||||
|
// See "Notes & caveats" for a corrected version you may prefer.
|
||||||
|
static Vector4<float> from_im_vec4(const ImVec4& other) noexcept;
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hashing & formatting
|
||||||
|
|
||||||
|
* **Hash specialization** (only for `Vector4<float>`):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<> struct std::hash<omath::Vector4<float>> {
|
||||||
|
std::size_t operator()(const omath::Vector4<float>&) const noexcept;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::unordered_map<omath::Vector4<float>, int> counts;
|
||||||
|
counts[{1.f, 2.f, 3.f, 1.f}] = 7;
|
||||||
|
```
|
||||||
|
|
||||||
|
* **`std::formatter`** (for any `Type`, all character kinds):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<class Type>
|
||||||
|
struct std::formatter<omath::Vector4<Type>>; // -> "[x, y, z, w]"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & caveats (as implemented)
|
||||||
|
|
||||||
|
* `clamp(min,max)` **clamps only `x`, `y`, `z`** and **does not clamp `w`**. This may be intentional (e.g., when `w` is a homogeneous coordinate) — document your intent in your codebase.
|
||||||
|
If you want to clamp `w` too:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
w = std::clamp(w, min, max);
|
||||||
|
```
|
||||||
|
|
||||||
|
* **ImGui interop**:
|
||||||
|
|
||||||
|
* The header references `ImVec4` but does not include `<imgui.h>` itself. Ensure it’s included **before** this header whenever `OMATH_IMGUI_INTEGRATION` is defined.
|
||||||
|
* `from_im_vec4` currently returns `Vector4<float>` and (in the snippet shown) initializes **only x,y,z**. A more consistent version would be:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#ifdef OMATH_IMGUI_INTEGRATION
|
||||||
|
static Vector4<Type> from_im_vec4(const ImVec4& v) noexcept {
|
||||||
|
return {static_cast<Type>(v.x), static_cast<Type>(v.y),
|
||||||
|
static_cast<Type>(v.z), static_cast<Type>(v.w)};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
* Many scalar compound operators (`+= Type`, `-= Type`) are inherited from `Vector3<Type>`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API summary (signatures)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Ctors
|
||||||
|
constexpr Vector4() noexcept;
|
||||||
|
constexpr Vector4(const Type& x, const Type& y, const Type& z, const Type& w);
|
||||||
|
|
||||||
|
// Equality & ordering
|
||||||
|
constexpr bool operator==(const Vector4&) const noexcept;
|
||||||
|
constexpr bool operator!=(const Vector4&) const noexcept;
|
||||||
|
bool operator< (const Vector4&) const noexcept;
|
||||||
|
bool operator> (const Vector4&) const noexcept;
|
||||||
|
bool operator<=(const Vector4&) const noexcept;
|
||||||
|
bool operator>=(const Vector4&) const noexcept;
|
||||||
|
|
||||||
|
// Mutating arithmetic
|
||||||
|
Vector4& operator+=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator-=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator*=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator/=(const Vector4&) noexcept;
|
||||||
|
Vector4& operator*=(const Type&) noexcept;
|
||||||
|
Vector4& operator/=(const Type&) noexcept;
|
||||||
|
// (inherited) Vector4& operator+=(const Type&) noexcept;
|
||||||
|
// (inherited) Vector4& operator-=(const Type&) noexcept;
|
||||||
|
|
||||||
|
// Non-mutating arithmetic
|
||||||
|
constexpr Vector4 operator-() const noexcept;
|
||||||
|
constexpr Vector4 operator+(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator-(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator*(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator/(const Vector4&) const noexcept;
|
||||||
|
constexpr Vector4 operator*(const Type&) const noexcept;
|
||||||
|
constexpr Vector4 operator/(const Type&) const noexcept;
|
||||||
|
|
||||||
|
// Geometry & helpers
|
||||||
|
constexpr Type length_sqr() const noexcept;
|
||||||
|
Type length() const noexcept;
|
||||||
|
constexpr Type dot(const Vector4&) const noexcept;
|
||||||
|
Vector4& abs() noexcept;
|
||||||
|
Vector4& clamp(const Type& min, const Type& max) noexcept;
|
||||||
|
constexpr Type sum() const noexcept;
|
||||||
|
|
||||||
|
// ImGui (optional)
|
||||||
|
#ifdef OMATH_IMGUI_INTEGRATION
|
||||||
|
constexpr ImVec4 to_im_vec4() const noexcept;
|
||||||
|
static Vector4<float> from_im_vec4(const ImVec4&) noexcept; // see note for preferred template version
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Hash (float) and formatter specializations provided below the class
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 31 Oct 2025*
|
||||||
188
docs/pathfinding/a_star.md
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
# `omath::pathfinding::Astar` — Pathfinding over a navigation mesh
|
||||||
|
|
||||||
|
> Header: your project’s `pathfinding/astar.hpp`
|
||||||
|
> Namespace: `omath::pathfinding`
|
||||||
|
> Inputs: start/end as `Vector3<float>`, a `NavigationMesh`
|
||||||
|
> Output: ordered list of waypoints `std::vector<Vector3<float>>`
|
||||||
|
|
||||||
|
`Astar` exposes a single public function, `find_path`, that computes a path of 3D waypoints on a navigation mesh. Internally it reconstructs the result with `reconstruct_final_path` from a closed set keyed by `Vector3<float>`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace omath::pathfinding {
|
||||||
|
|
||||||
|
struct PathNode; // holds per-node search data (see "Expected PathNode fields")
|
||||||
|
|
||||||
|
class Astar final {
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static std::vector<Vector3<float>>
|
||||||
|
find_path(const Vector3<float>& start,
|
||||||
|
const Vector3<float>& end,
|
||||||
|
const NavigationMesh& nav_mesh) noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
[[nodiscard]]
|
||||||
|
static std::vector<Vector3<float>>
|
||||||
|
reconstruct_final_path(
|
||||||
|
const std::unordered_map<Vector3<float>, PathNode>& closed_list,
|
||||||
|
const Vector3<float>& current) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::pathfinding
|
||||||
|
```
|
||||||
|
|
||||||
|
### Semantics
|
||||||
|
|
||||||
|
* Returns a **polyline** of 3D points from `start` to `end`.
|
||||||
|
* If no path exists, the function typically returns an **empty vector** (behavior depends on implementation details; keep this contract in unit tests).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What `NavigationMesh` is expected to provide
|
||||||
|
|
||||||
|
The header doesn’t constrain `NavigationMesh`, but for A* it commonly needs:
|
||||||
|
|
||||||
|
* **Neighborhood queries**: given a position or node key → iterable neighbors.
|
||||||
|
* **Traversal cost**: `g(u,v)` (often Euclidean distance or edge weight).
|
||||||
|
* **Heuristic**: `h(x,end)` (commonly straight-line distance on the mesh).
|
||||||
|
* **Projection / snap**: the ability to map `start`/`end` to valid nodes/points on the mesh (if they are off-mesh).
|
||||||
|
|
||||||
|
> If your `NavigationMesh` doesn’t directly expose these, `Astar::find_path` likely does the adapter work (snapping to the nearest convex polygon/portal nodes and expanding across adjacency).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Expected `PathNode` fields
|
||||||
|
|
||||||
|
Although not visible here, `PathNode` typically carries:
|
||||||
|
|
||||||
|
* `Vector3<float> parent;` — predecessor position or key for backtracking
|
||||||
|
* `float g;` — cost from `start`
|
||||||
|
* `float h;` — heuristic to `end`
|
||||||
|
* `float f;` — `g + h`
|
||||||
|
|
||||||
|
`reconstruct_final_path(closed_list, current)` walks `parent` links from `current` back to the start, **reverses** the chain, and returns the path.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Heuristic & optimality
|
||||||
|
|
||||||
|
* Use an **admissible** heuristic (never overestimates true cost) to keep A* optimal.
|
||||||
|
The usual choice is **Euclidean distance** in 3D:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
h(x, goal) = (goal - x).length();
|
||||||
|
```
|
||||||
|
* For best performance, make it **consistent** (triangle inequality holds). Euclidean distance is consistent on standard navmeshes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complexity
|
||||||
|
|
||||||
|
Let `V` be explored vertices (or portal nodes) and `E` the traversed edges.
|
||||||
|
|
||||||
|
* With a binary heap open list: **O(E log V)** time, **O(V)** memory.
|
||||||
|
* With a d-ary heap or pairing heap you may reduce practical constants.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Typical usage
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "omath/pathfinding/astar.hpp"
|
||||||
|
#include "omath/pathfinding/navigation_mesh.hpp"
|
||||||
|
|
||||||
|
using omath::Vector3;
|
||||||
|
using omath::pathfinding::Astar;
|
||||||
|
|
||||||
|
NavigationMesh nav = /* ... load/build mesh ... */;
|
||||||
|
|
||||||
|
Vector3<float> start{2.5f, 0.0f, -1.0f};
|
||||||
|
Vector3<float> goal {40.0f, 0.0f, 12.0f};
|
||||||
|
|
||||||
|
auto path = Astar::find_path(start, goal, nav);
|
||||||
|
|
||||||
|
if (!path.empty()) {
|
||||||
|
// feed to your agent/renderer
|
||||||
|
for (const auto& p : path) {
|
||||||
|
// draw waypoint p or push to steering
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// handle "no path" (e.g., unreachable or disconnected mesh)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes & recommendations
|
||||||
|
|
||||||
|
* **Start/end snapping**: If `start` or `end` are outside the mesh, decide whether to snap to the nearest polygon/portal or fail early. Keep this behavior consistent and document it where `NavigationMesh` is defined.
|
||||||
|
* **Numerical stability**: Prefer squared distances when only comparing (`dist2`) to avoid unnecessary `sqrt`.
|
||||||
|
* **Tie-breaking**: When `f` ties are common (grid-like graphs), bias toward larger `g` or smaller `h` to reduce zig-zagging.
|
||||||
|
* **Smoothing**: A* returns a polyline that may hug polygon edges. Consider:
|
||||||
|
|
||||||
|
* **String pulling / Funnel algorithm** over the corridor of polygons to get a straightened path.
|
||||||
|
* **Raycast smoothing** (visibility checks) to remove redundant interior points.
|
||||||
|
* **Hashing `Vector3<float>`**: Your repo defines `std::hash<omath::Vector3<float>>`. Ensure equality/precision rules for using float keys are acceptable (or use discrete node IDs instead).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing checklist
|
||||||
|
|
||||||
|
* Start/end on the **same polygon** → direct path of 2 points.
|
||||||
|
* **Disconnected components** → empty result.
|
||||||
|
* **Narrow corridors** → path stays inside.
|
||||||
|
* **Obstacles blocking** → no path.
|
||||||
|
* **Floating-point noise** → still reconstructs a valid chain from parents.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Minimal pseudo-implementation outline (for reference)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Pseudocode only — matches the header’s intent
|
||||||
|
std::vector<Vec3> find_path(start, goal, mesh) {
|
||||||
|
auto [snode, gnode] = mesh.snap_to_nodes(start, goal);
|
||||||
|
OpenSet open; // min-heap by f
|
||||||
|
std::unordered_map<Vec3, PathNode> closed;
|
||||||
|
|
||||||
|
open.push({snode, g=0, h=heuristic(snode, gnode)});
|
||||||
|
parents.clear();
|
||||||
|
|
||||||
|
while (!open.empty()) {
|
||||||
|
auto current = open.pop_min(); // node with lowest f
|
||||||
|
|
||||||
|
if (current.pos == gnode.pos)
|
||||||
|
return reconstruct_final_path(closed, current.pos);
|
||||||
|
|
||||||
|
for (auto [nbr, cost] : mesh.neighbors(current.pos)) {
|
||||||
|
float tentative_g = current.g + cost;
|
||||||
|
if (auto it = closed.find(nbr); it == closed.end() || tentative_g < it->second.g) {
|
||||||
|
closed[nbr] = { .parent = current.pos,
|
||||||
|
.g = tentative_g,
|
||||||
|
.h = heuristic(nbr, gnode.pos),
|
||||||
|
.f = tentative_g + heuristic(nbr, gnode.pos) };
|
||||||
|
open.push(closed[nbr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {}; // no path
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
* **Why return `std::vector<Vector3<float>>` and not polygon IDs?**
|
||||||
|
Waypoints are directly usable by agents/steering and for rendering. If you also need the corridor (polygon chain), extend the API or `PathNode` to store it.
|
||||||
|
|
||||||
|
* **Does `find_path` modify the mesh?**
|
||||||
|
No; it should be a read-only search over `NavigationMesh`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 31 Oct 2025*
|
||||||
113
docs/pathfinding/navigation_mesh.md
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# `omath::pathfinding::NavigationMesh` — Lightweight vertex graph for A*
|
||||||
|
|
||||||
|
> Header: your project’s `pathfinding/navigation_mesh.hpp`
|
||||||
|
> Namespace: `omath::pathfinding`
|
||||||
|
> Nodes: `Vector3<float>` (3D points)
|
||||||
|
> Storage: adjacency map `unordered_map<Vector3<float>, std::vector<Vector3<float>>>`
|
||||||
|
|
||||||
|
A minimal navigation mesh represented as a **vertex/edge graph**. Each vertex is a `Vector3<float>` and neighbors are stored in an adjacency list. Designed to pair with `Astar::find_path`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class NavigationMesh final {
|
||||||
|
public:
|
||||||
|
// Nearest graph vertex to an arbitrary 3D point.
|
||||||
|
// On success -> closest vertex; on failure -> std::string error (e.g., empty mesh).
|
||||||
|
[[nodiscard]]
|
||||||
|
std::expected<Vector3<float>, std::string>
|
||||||
|
get_closest_vertex(const Vector3<float>& point) const noexcept;
|
||||||
|
|
||||||
|
// Read-only neighbor list for a vertex key.
|
||||||
|
// If vertex is absent, implementation should return an empty list (see notes).
|
||||||
|
[[nodiscard]]
|
||||||
|
const std::vector<Vector3<float>>&
|
||||||
|
get_neighbors(const Vector3<float>& vertex) const noexcept;
|
||||||
|
|
||||||
|
// True if the graph has no vertices/edges.
|
||||||
|
[[nodiscard]]
|
||||||
|
bool empty() const;
|
||||||
|
|
||||||
|
// Serialize/deserialize the graph (opaque binary).
|
||||||
|
[[nodiscard]] std::vector<uint8_t> serialize() const noexcept;
|
||||||
|
void deserialize(const std::vector<uint8_t>& raw) noexcept;
|
||||||
|
|
||||||
|
// Public adjacency (vertex -> neighbors)
|
||||||
|
std::unordered_map<Vector3<float>, std::vector<Vector3<float>>> m_vertex_map;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using omath::Vector3;
|
||||||
|
using omath::pathfinding::NavigationMesh;
|
||||||
|
|
||||||
|
// Build a tiny mesh (triangle)
|
||||||
|
NavigationMesh nav;
|
||||||
|
nav.m_vertex_map[ {0,0,0} ] = { {1,0,0}, {0,0,1} };
|
||||||
|
nav.m_vertex_map[ {1,0,0} ] = { {0,0,0}, {0,0,1} };
|
||||||
|
nav.m_vertex_map[ {0,0,1} ] = { {0,0,0}, {1,0,0} };
|
||||||
|
|
||||||
|
// Query the closest node to an arbitrary point
|
||||||
|
auto q = nav.get_closest_vertex({0.3f, 0.0f, 0.2f});
|
||||||
|
if (q) {
|
||||||
|
const auto& v = *q;
|
||||||
|
const auto& nbrs = nav.get_neighbors(v);
|
||||||
|
(void)nbrs;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Semantics & expectations
|
||||||
|
|
||||||
|
* **Nearest vertex**
|
||||||
|
`get_closest_vertex(p)` should scan known vertices and return the one with minimal Euclidean distance to `p`. If the mesh is empty, expect an error (`unexpected` with a message).
|
||||||
|
|
||||||
|
* **Neighbors**
|
||||||
|
`get_neighbors(v)` returns the adjacency list for `v`. If `v` is not present, a conventional behavior is to return a **reference to a static empty vector** (since the API is `noexcept` and returns by reference). Verify in your implementation.
|
||||||
|
|
||||||
|
* **Graph invariants** (recommended)
|
||||||
|
|
||||||
|
* Neighbor links are **symmetric** for undirected navigation (if `u` has `v`, then `v` has `u`).
|
||||||
|
* No self-loops unless explicitly desired.
|
||||||
|
* Vertices are unique keys; hashing uses `std::hash<Vector3<float>>` (be mindful of floating-point equality).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Serialization
|
||||||
|
|
||||||
|
* `serialize()` → opaque, implementation-defined binary of the current `m_vertex_map`.
|
||||||
|
* `deserialize(raw)` → restores the internal map from `raw`.
|
||||||
|
Keep versioning in mind if you evolve the format (e.g., add a header/magic/version).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
Let `V = m_vertex_map.size()` and `E = Σ|neighbors(v)|`.
|
||||||
|
|
||||||
|
* `get_closest_vertex`: **O(V)** (linear scan) unless you back it with a spatial index (KD-tree, grid, etc.).
|
||||||
|
* `get_neighbors`: **O(1)** average (hash lookup).
|
||||||
|
* Memory: **O(V + E)**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage notes
|
||||||
|
|
||||||
|
* **Floating-point keys**: Using `Vector3<float>` as an unordered_map key relies on your `std::hash<omath::Vector3<float>>` and exact `operator==`. Avoid building meshes with numerically “close but not equal” duplicates; consider canonicalizing or using integer IDs if needed.
|
||||||
|
* **Pathfinding**: Pair with `Astar::find_path(start, end, nav)`; the A* heuristic can use straight-line distance between vertex positions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Minimal test ideas
|
||||||
|
|
||||||
|
* Empty mesh → `get_closest_vertex` returns error; `empty() == true`.
|
||||||
|
* Single vertex → nearest always that vertex; neighbors empty.
|
||||||
|
* Symmetric edges → `get_neighbors(a)` contains `b` and vice versa.
|
||||||
|
* Serialization round-trip preserves vertex/edge counts and neighbor lists.
|
||||||