Compare commits
541 Commits
wip_unstab
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d077cee6d | |||
| 7997417fa3 | |||
| 5c5dea2617 | |||
| 19020e3c01 | |||
| b6179a2496 | |||
| 4c964ec8d5 | |||
| 898e0714e4 | |||
| eb29369eda | |||
| 79c181b221 | |||
| a4c8b77f3a | |||
| ae9469dd62 | |||
| c075148ead | |||
| a7cd068e39 | |||
| 36fd88d6ee | |||
| eb4b2fcbfa | |||
| 14ee6f0419 | |||
| 34e5b529bc | |||
| aeb8f3434e | |||
| 8fc846ce6b | |||
| 30ebb97430 | |||
| 9d2d788b98 | |||
| 34171c7d56 | |||
| c239d68950 | |||
| 3d69a7154c | |||
| 0a3a0d234e | |||
| 635278022e | |||
| 8c52ed697f | |||
| 92843b93d2 | |||
| ead7aade63 | |||
| 9b20d1ef1d | |||
| b146886691 | |||
| 61cc889880 | |||
| 5217ab8018 | |||
| 0abc52525d | |||
| 112fdab9f5 | |||
| 8b04a84470 | |||
| 274fd7a69e | |||
| 2e9fac869a | |||
| dec5872cf6 | |||
| d664e670f4 | |||
| a68b1bf38d | |||
| be2116d338 | |||
| 2ce2582318 | |||
| 13efe5caec | |||
| dbf31ceebe | |||
| e029e0b3fc | |||
| 614ce0a151 | |||
| 51b8bcbc78 | |||
| 82019987e6 | |||
| 8c8aa1893c | |||
| 1a602d30b1 | |||
| d2e116cce9 | |||
| 64b89426bc | |||
| d8eb663731 | |||
| dbb6e98307 | |||
| 7cb09d8f89 | |||
| 53f2a85136 | |||
| b5b3aa028e | |||
| 453d8d8f68 | |||
| f48d99d2c2 | |||
| 1bd16c05c0 | |||
| 993ce744b2 | |||
| 2c79c4ac6e | |||
| e44a6875eb | |||
| 37b266dc11 | |||
| 6ccbecda3c | |||
| ec37ec99bd | |||
| 51534da431 | |||
| 97da7eaa94 | |||
| 7ea376574c | |||
| eb3f88ff90 | |||
| a917f70f62 | |||
| 6739e9c1a5 | |||
| 9df960d181 | |||
| 2fc46ece57 | |||
| 9db005c55c | |||
| 6a136cf0ee | |||
| 802da21deb | |||
| 2dcf7f987d | |||
| 8500ca8bea | |||
| 8d8cfd2532 | |||
| 5f286e185e | |||
| 7dc8a1304e | |||
| ddfe080078 | |||
| 698f890500 | |||
| 4ccdaea970 | |||
| 51d6038187 | |||
| 3928e247eb | |||
| 0a66f11ff0 | |||
| 3b9a5d6f81 | |||
| 8bee10c768 | |||
| d7672d31f4 | |||
| 95969839ec | |||
| 4bf0cbb2ca | |||
| cc4813136b | |||
| fa14da813b | |||
| e19be4c2a4 | |||
| fc783b7d54 | |||
| 08d98eefcb | |||
| 77b75311e6 | |||
| 7e4fc361d4 | |||
| 862ffeeaa0 | |||
| a9029193d7 | |||
| a5780cea2b | |||
| fa96ffefdf | |||
| 1912ccd63e | |||
| 6e88d82520 | |||
| b3269d7b97 | |||
| 9856a686cf | |||
| 249988beef | |||
| 5f1e074136 | |||
| c7afc9583d | |||
| a0de671125 | |||
| 2925ea316d | |||
| 0ccf487caf | |||
| a2d125b15b | |||
| d92a039fab | |||
| b37acc1fd2 | |||
| 8795e1e402 | |||
| e6706a4e1f | |||
| 0c6b0854f2 | |||
| 208533f490 | |||
| eee56e4f36 | |||
| 2105e9359e | |||
| 8214cf475a | |||
| b3263d874a | |||
| 39e23436ee | |||
| 402c4330bb | |||
| 9953325775 | |||
| 1efab1c22e | |||
| 3bd92cf068 | |||
| 62158307a3 | |||
| 2a84abaff9 | |||
| 73c77251d3 | |||
| 74dbd2d95b | |||
| e498bd8f23 | |||
| 6ace99b7e4 | |||
| d875108095 | |||
| f81d9b406a | |||
| b67f22387f | |||
| 229a86dd33 | |||
| 6eb4cc62da | |||
| 226f545a1f | |||
| 46455a1cc4 | |||
| 068b163fe4 | |||
| 0598d920c1 | |||
| 7c16b85a96 | |||
| 14110e48f1 | |||
| 3894209a64 | |||
| cb998d73f0 | |||
| 67d8e6773a | |||
| 03f76ff8b8 | |||
| f59d3a5539 | |||
| a13a7ba248 | |||
| 9e49749bc0 | |||
| a711c0f0b4 | |||
| 04e0ada271 | |||
| b157b66d1a | |||
| e485261e53 | |||
| 152f7a2d28 | |||
| 9a183ff354 | |||
| ea0fff0e49 | |||
| dae67fd30c | |||
| 8845e19273 | |||
| ebe5682ed5 | |||
| 503bf73d65 | |||
| 71fb105933 | |||
| 84c93a2182 | |||
| 49620655fd | |||
| 223108cc4c | |||
| ecfd410806 | |||
| ab195e1323 | |||
| b3019e3527 | |||
| 80ecdb1f92 | |||
| b5edc6fa35 | |||
| 71103f676b | |||
| 6607b94b44 | |||
| 7e82e775c6 | |||
| 2f8fa11c7f | |||
| 6d53ec32d0 | |||
| eecde09734 | |||
| 230783b3c9 | |||
| a2a9714f24 | |||
| e60e9bceab | |||
| 4d244c96c3 | |||
| 741b7848c5 | |||
| 7722975dd0 | |||
| 482c03f9bb | |||
| 272d3f89bc | |||
| 1bb7238502 | |||
| a186095c47 | |||
| 77a03d53cc | |||
| ad81d58ea8 | |||
| ec65e788e0 | |||
| 6c8bf9fa2c | |||
| 3f4289ec08 | |||
| 7a14f5122c | |||
| 9eec4aafc7 | |||
| 7a0b8cab34 | |||
| fa678505b7 | |||
| 9f93941b1f | |||
| 4be16e3ddc | |||
| d3912a9ffe | |||
| ecb1c8a50f | |||
| 2a36e6a11e | |||
| 4c8b8d5d35 | |||
| 5219cf0ba7 | |||
| 6b93fcbf87 | |||
| 73166ff8aa | |||
| 96ea71852f | |||
| 3ba80b1dd8 | |||
| 3df8433205 | |||
| 5ab035b076 | |||
| ee091aa1fe | |||
| a3ee2845d1 | |||
| 3376f3e4be | |||
| d50b7f7831 | |||
| be6c3a148e | |||
| 9a84a3a07b | |||
| f4bd0d6340 | |||
| 8306202cf1 | |||
| 183f7057e2 | |||
| 327167c9b1 | |||
| cc4efe34e1 | |||
| 4d0158c0ec | |||
| 478669ed81 | |||
| 5b70ce077d | |||
| 9b46917171 | |||
| 5ffc3d9b9b | |||
| 175c4e2008 | |||
| 5ed6b8eccd | |||
| aeaed68efb | |||
| f20f7f73d6 | |||
| e695bca3f9 | |||
| 10f9c17cf1 | |||
| 0d848bd53b | |||
| 414ec8ca81 | |||
| 8594c7d4b1 | |||
| 6682cbdedd | |||
| 0e5fee2d80 | |||
| e318a5b4aa | |||
| 191167f9d3 | |||
| 9f245a9765 | |||
| 5c75dc754a | |||
| 42e8365751 | |||
| cef2372ce8 | |||
| 2391ed9785 | |||
| 2085908017 | |||
| 7433d54c16 | |||
| c5a640e22d | |||
| d3abb3ef0d | |||
| f5855aeaec | |||
| 9b31914371 | |||
| 732560f732 | |||
| 29d928ca29 | |||
| 347a258c99 | |||
| 5f32d4dede | |||
| b714f7b52a | |||
| 06f4056887 | |||
| 2dab7a2b48 | |||
| 74ed52fefd | |||
| f52ddc007f | |||
| fb6e197f2b | |||
| 40024ed9d8 | |||
| 5f7912524f | |||
| c02ad5c3e7 | |||
| 33f5292c5e | |||
| d19f340d32 | |||
| 6551e6d8a6 | |||
| 9eb9cfe7c5 | |||
| cfd8e35f29 | |||
| d1553fc1bf | |||
| b1384e0106 | |||
| 46f8af662e | |||
| 0cc6c0d40b | |||
| 7e8b5cb830 | |||
| e1342ab836 | |||
| 8f63d9607a | |||
| ff4eb2589c | |||
| 378b5319bf | |||
| 4a13f3c832 | |||
| 2a75ee68a0 | |||
| ab86194a59 | |||
| 6392a6d04d | |||
| c7ed12db80 | |||
| 97b2889568 | |||
| c8af34bc0b | |||
| 41679f0497 | |||
| 90dd95ae76 | |||
| 83ea50384f | |||
| 22b871ad2f | |||
| 559df3766e | |||
| 41a1f3bd89 | |||
| e61f8aa7d1 | |||
| 3d6dd727c2 | |||
| 003bee0d25 | |||
| b857654cf6 | |||
| 1d11be0e61 | |||
| 85847fd2e0 | |||
| 0382c15fe3 | |||
| e280ac486a | |||
| 96e57d9344 | |||
| 7ea1349fb9 | |||
| dfde4f876d | |||
| 738cfd29ef | |||
| 7f3ceebd5f | |||
| 4bc44a8e52 | |||
| fed12dbc96 | |||
| 6e1e07cc07 | |||
| 64341c4e90 | |||
| 73597a21c2 | |||
| d5635a4996 | |||
| 6b8404c3d7 | |||
| b0be60cf18 | |||
| ee77caba9b | |||
| 5dd2068e1b | |||
| 44055d1e6a | |||
| c7f9277780 | |||
| 216cbe3eec | |||
| 4f3b8ad584 | |||
| 7d36a0036c | |||
| 560f7da9e7 | |||
| 88a1ca186b | |||
| e976e94da1 | |||
| d2c8763fd9 | |||
| 85b7b2cd31 | |||
| 93d665b356 | |||
| b7e4415b16 | |||
| 8e9885b46c | |||
| d76ce2090d | |||
| 54e484bd71 | |||
| bbc0de400c | |||
| ad64ab506a | |||
| 68c3831fde | |||
| 17113b59ea | |||
| 943bbfda2f | |||
| b801da7eb3 | |||
| 2e371386cf | |||
| 44be42a4a8 | |||
| e0e51c3f07 | |||
| 13412cb5c5 | |||
| 6bb2309d07 | |||
| 8db6a4313f | |||
| d292c86b6e | |||
| d571bcbdc3 | |||
| 0f8feb669c | |||
| d1b085ffb5 | |||
| 767ba5932b | |||
| 52c8ec2776 | |||
| 858064fa4b | |||
| 9e0136f051 | |||
| de5d6e64aa | |||
| 56abe4425f | |||
| 1877049526 | |||
| 2f104edf7c | |||
| 99394820fc | |||
| 3784c0fc0b | |||
| c49e177264 | |||
| c51f776899 | |||
| b6922dc63f | |||
| f48fb5b14f | |||
| c58487c00f | |||
| 5e8c9223ac | |||
| 36f804e176 | |||
| 2818deb0e3 | |||
| 9bdfb0feea | |||
| adfaf21cda | |||
| 00eeb8bcb4 | |||
| 4cb3566906 | |||
| b34ba9b096 | |||
| 1a948915c6 | |||
| b306670e9c | |||
| 0a18ddcbb3 | |||
| 6a56c9ebfe | |||
| a26ee33e4c | |||
| df344d0d7b | |||
| 3c948e2337 | |||
| d24df948c1 | |||
| e9df34b191 | |||
| 400a7e0061 | |||
| 8414c1c0bb | |||
| 7166a21b81 | |||
| 227a2acaf4 | |||
| 100ab0d3de | |||
| ad596a82f9 | |||
| 0330d5b4fe | |||
| d093cc6f96 | |||
| 739111ed2d | |||
| 2df55cf31c | |||
| a178ed8bcc | |||
| 1053eb487c | |||
| 3a06069184 | |||
| e485518227 | |||
| 2102faf4e5 | |||
| 42717276b5 | |||
| e046c1638a | |||
| f0b8dbbac5 | |||
| fc55a5d490 | |||
| 5d0a4bc9d2 | |||
| a3fc0d84d4 | |||
| f6b3845057 | |||
| 212cea794f | |||
| 817cd32044 | |||
| 0e2bd45b7f | |||
| 61a83dd28d | |||
| 748bd56b37 | |||
| d69699230a | |||
| 67ebb49d02 | |||
| f8950ffc55 | |||
| 92e7dec2fa | |||
| 09b9841c03 | |||
| 1114210039 | |||
| 0285e734bc | |||
| 9bc30e6937 | |||
| 3fff761bca | |||
| 12e476dc81 | |||
| 4d79896b76 | |||
| 95a506e6bf | |||
| 348ba3270b | |||
| e3501544db | |||
| ce7ecbdd9a | |||
| 8b59c5c382 | |||
| 7965da421c | |||
| 831cf2d1c5 | |||
| cb43ee1b5a | |||
| a5d18962d3 | |||
| f1fb41a29c | |||
| 2385a19926 | |||
| 76b7e64ae6 | |||
| 75d3f019ae | |||
| 893092e0ad | |||
| ba3c7ce25e | |||
| e477a4d81f | |||
| 2b0482e1c6 | |||
| eefa3718ef | |||
| fee1195cbc | |||
| b2650474ce | |||
| 95fdd30b02 | |||
| 283c4e152a | |||
| 78172b5abc | |||
| b405c3014f | |||
| af43934a01 | |||
| a5aefdf3d6 | |||
| 9762e021ce | |||
| 1ca6af364e | |||
| cf29556d41 | |||
| f1d25b4cdf | |||
| 46c356ebc5 | |||
| 3737c5a250 | |||
| 5c349f7b94 | |||
| 784ac71c14 | |||
| a713c8273a | |||
| 7634d98641 | |||
| f7cb8b124e | |||
| 09dce867df | |||
| d39df0f370 | |||
| ae944a0a68 | |||
| 172ca74f70 | |||
| 4761bbc66b | |||
| 0fc6ec1357 | |||
| 18a2bb5688 | |||
| 592f811d71 | |||
| 8901ac041a | |||
| 280de9b6da | |||
| 1cf55f3553 | |||
| 7ed62785d2 | |||
| 1b22313d57 | |||
| 94b351f9ee | |||
| 21ca133e30 | |||
| 1c5520fa3a | |||
| 9f71c278ea | |||
| 9063cf8915 | |||
| 20121e7eaa | |||
| 8abe05d950 | |||
| 7bfef630d0 | |||
|
|
aca476afa9 | ||
|
|
cbbbe41cb0 | ||
|
|
fdda52d406 | ||
|
|
3b0b087262 | ||
|
|
b9c737ac2f | ||
|
|
dfce8148e3 | ||
|
|
9c72088eb3 | ||
|
|
00b1d97285 | ||
|
|
9203c81064 | ||
|
|
200536bf21 | ||
|
|
cc62f34e4e | ||
|
|
a0d21a7c8e | ||
|
|
003d2c7168 | ||
|
|
6abf8c7644 | ||
|
|
4a9009427a | ||
|
|
3be32926b9 | ||
|
|
891bb18b10 | ||
|
|
f4e68d491a | ||
| 570c5ab6bf | |||
| 9ee509b101 | |||
| eaab2be917 | |||
| f9e1304571 | |||
| 22daa9eeea | |||
|
|
7a5debf358 | ||
|
|
d7235734cd | ||
|
|
a9dc678687 | ||
| c42455e38a | |||
| 782ba4839a | |||
|
|
ff193a5d25 | ||
| c4bc9c5f2f | |||
| 5096b391de | |||
| cdbbd329cb | |||
|
|
f84501b214 | ||
|
|
f70e25d543 | ||
| 7b70bab8d9 | |||
| db02be6232 | |||
| d5545ca6b1 | |||
| 36f6da0828 | |||
| 985cc1eac3 | |||
| 667ff5e4f2 | |||
| 891de4c474 | |||
|
|
ae59181c24 | ||
| 6f8a99f543 | |||
| db13a05a7e | |||
| cfa27c2bcb | |||
| 40cfa3ba1c | |||
| de945d8992 | |||
| 96412e1530 | |||
| d31a9b0538 | |||
| ac479080ea | |||
| 4f32fb26f4 | |||
| 274f7cad6b | |||
| 8eb5e5f6ab | |||
| 1bbc8511ee | |||
| d0885edfeb | |||
| 9cf91d6332 | |||
| ea1c447f1d | |||
| 7e38a4c311 | |||
| f8e11fc724 | |||
| 0225f003a3 | |||
| 90c54912e9 | |||
| 68797585e6 | |||
| 0d8d088cc5 | |||
| 8eeba733a6 | |||
| bf122b319f | |||
| 4d85c2e3be |
136
.editorconfig
Normal file
136
.editorconfig
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
# Visual Studio generated .editorconfig file with C++ settings.
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
|
||||||
|
|
||||||
|
# Visual C++ Code Style settings
|
||||||
|
|
||||||
|
cpp_generate_documentation_comments = xml
|
||||||
|
|
||||||
|
# Visual C++ Formatting settings
|
||||||
|
|
||||||
|
cpp_indent_braces = false
|
||||||
|
cpp_indent_multi_line_relative_to = innermost_parenthesis
|
||||||
|
cpp_indent_within_parentheses = indent
|
||||||
|
cpp_indent_preserve_within_parentheses = true
|
||||||
|
cpp_indent_case_contents = true
|
||||||
|
cpp_indent_case_labels = false
|
||||||
|
cpp_indent_case_contents_when_block = false
|
||||||
|
cpp_indent_lambda_braces_when_parameter = true
|
||||||
|
cpp_indent_goto_labels = one_left
|
||||||
|
cpp_indent_preprocessor = leftmost_column
|
||||||
|
cpp_indent_access_specifiers = false
|
||||||
|
cpp_indent_namespace_contents = false
|
||||||
|
cpp_indent_preserve_comments = false
|
||||||
|
cpp_new_line_before_open_brace_namespace = ignore
|
||||||
|
cpp_new_line_before_open_brace_type = ignore
|
||||||
|
cpp_new_line_before_open_brace_function = ignore
|
||||||
|
cpp_new_line_before_open_brace_block = false
|
||||||
|
cpp_new_line_before_open_brace_lambda = ignore
|
||||||
|
cpp_new_line_scope_braces_on_separate_lines = false
|
||||||
|
cpp_new_line_close_brace_same_line_empty_type = false
|
||||||
|
cpp_new_line_close_brace_same_line_empty_function = false
|
||||||
|
cpp_new_line_before_catch = true
|
||||||
|
cpp_new_line_before_else = true
|
||||||
|
cpp_new_line_before_while_in_do_while = false
|
||||||
|
cpp_space_before_function_open_parenthesis = remove
|
||||||
|
cpp_space_within_parameter_list_parentheses = false
|
||||||
|
cpp_space_between_empty_parameter_list_parentheses = false
|
||||||
|
cpp_space_after_keywords_in_control_flow_statements = true
|
||||||
|
cpp_space_within_control_flow_statement_parentheses = false
|
||||||
|
cpp_space_before_lambda_open_parenthesis = false
|
||||||
|
cpp_space_within_cast_parentheses = false
|
||||||
|
cpp_space_after_cast_close_parenthesis = false
|
||||||
|
cpp_space_within_expression_parentheses = false
|
||||||
|
cpp_space_before_block_open_brace = true
|
||||||
|
cpp_space_between_empty_braces = false
|
||||||
|
cpp_space_before_initializer_list_open_brace = false
|
||||||
|
cpp_space_within_initializer_list_braces = true
|
||||||
|
cpp_space_preserve_in_initializer_list = true
|
||||||
|
cpp_space_before_open_square_bracket = false
|
||||||
|
cpp_space_within_square_brackets = false
|
||||||
|
cpp_space_before_empty_square_brackets = false
|
||||||
|
cpp_space_between_empty_square_brackets = false
|
||||||
|
cpp_space_group_square_brackets = true
|
||||||
|
cpp_space_within_lambda_brackets = false
|
||||||
|
cpp_space_between_empty_lambda_brackets = false
|
||||||
|
cpp_space_before_comma = false
|
||||||
|
cpp_space_after_comma = true
|
||||||
|
cpp_space_remove_around_member_operators = true
|
||||||
|
cpp_space_before_inheritance_colon = true
|
||||||
|
cpp_space_before_constructor_colon = true
|
||||||
|
cpp_space_remove_before_semicolon = true
|
||||||
|
cpp_space_after_semicolon = true
|
||||||
|
cpp_space_remove_around_unary_operator = true
|
||||||
|
cpp_space_around_binary_operator = insert
|
||||||
|
cpp_space_around_assignment_operator = insert
|
||||||
|
cpp_space_pointer_reference_alignment = left
|
||||||
|
cpp_space_around_ternary_operator = insert
|
||||||
|
cpp_wrap_preserve_blocks = one_liners
|
||||||
|
|
||||||
|
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
|
||||||
|
|
||||||
|
# Visual C++ Code Style settings
|
||||||
|
|
||||||
|
cpp_generate_documentation_comments = xml
|
||||||
|
|
||||||
|
# Visual C++ Formatting settings
|
||||||
|
|
||||||
|
cpp_indent_braces = false
|
||||||
|
cpp_indent_multi_line_relative_to = outermost_parenthesis
|
||||||
|
cpp_indent_within_parentheses = indent
|
||||||
|
cpp_indent_preserve_within_parentheses = true
|
||||||
|
cpp_indent_case_contents = true
|
||||||
|
cpp_indent_case_labels = false
|
||||||
|
cpp_indent_case_contents_when_block = false
|
||||||
|
cpp_indent_lambda_braces_when_parameter = true
|
||||||
|
cpp_indent_goto_labels = one_left
|
||||||
|
cpp_indent_preprocessor = leftmost_column
|
||||||
|
cpp_indent_access_specifiers = false
|
||||||
|
cpp_indent_namespace_contents = false
|
||||||
|
cpp_indent_preserve_comments = false
|
||||||
|
cpp_new_line_before_open_brace_namespace = same_line
|
||||||
|
cpp_new_line_before_open_brace_type = new_line
|
||||||
|
cpp_new_line_before_open_brace_function = new_line
|
||||||
|
cpp_new_line_before_open_brace_block = same_line
|
||||||
|
cpp_new_line_before_open_brace_lambda = same_line
|
||||||
|
cpp_new_line_scope_braces_on_separate_lines = true
|
||||||
|
cpp_new_line_close_brace_same_line_empty_type = false
|
||||||
|
cpp_new_line_close_brace_same_line_empty_function = false
|
||||||
|
cpp_new_line_before_catch = false
|
||||||
|
cpp_new_line_before_else = false
|
||||||
|
cpp_new_line_before_while_in_do_while = false
|
||||||
|
cpp_space_before_function_open_parenthesis = remove
|
||||||
|
cpp_space_within_parameter_list_parentheses = false
|
||||||
|
cpp_space_between_empty_parameter_list_parentheses = false
|
||||||
|
cpp_space_after_keywords_in_control_flow_statements = true
|
||||||
|
cpp_space_within_control_flow_statement_parentheses = false
|
||||||
|
cpp_space_before_lambda_open_parenthesis = false
|
||||||
|
cpp_space_within_cast_parentheses = false
|
||||||
|
cpp_space_after_cast_close_parenthesis = false
|
||||||
|
cpp_space_within_expression_parentheses = false
|
||||||
|
cpp_space_before_block_open_brace = true
|
||||||
|
cpp_space_between_empty_braces = false
|
||||||
|
cpp_space_before_initializer_list_open_brace = false
|
||||||
|
cpp_space_within_initializer_list_braces = true
|
||||||
|
cpp_space_preserve_in_initializer_list = true
|
||||||
|
cpp_space_before_open_square_bracket = false
|
||||||
|
cpp_space_within_square_brackets = false
|
||||||
|
cpp_space_before_empty_square_brackets = false
|
||||||
|
cpp_space_between_empty_square_brackets = false
|
||||||
|
cpp_space_group_square_brackets = true
|
||||||
|
cpp_space_within_lambda_brackets = false
|
||||||
|
cpp_space_between_empty_lambda_brackets = false
|
||||||
|
cpp_space_before_comma = false
|
||||||
|
cpp_space_after_comma = true
|
||||||
|
cpp_space_remove_around_member_operators = true
|
||||||
|
cpp_space_before_inheritance_colon = true
|
||||||
|
cpp_space_before_constructor_colon = true
|
||||||
|
cpp_space_remove_before_semicolon = true
|
||||||
|
cpp_space_after_semicolon = true
|
||||||
|
cpp_space_remove_around_unary_operator = true
|
||||||
|
cpp_space_around_binary_operator = insert
|
||||||
|
cpp_space_around_assignment_operator = insert
|
||||||
|
cpp_space_pointer_reference_alignment = left
|
||||||
|
cpp_space_around_ternary_operator = insert
|
||||||
|
cpp_wrap_preserve_blocks = never
|
||||||
84
.github/workflows/cmake-multi-platform.yml
vendored
Normal file
84
.github/workflows/cmake-multi-platform.yml
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform.
|
||||||
|
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml
|
||||||
|
name: CMake on multiple platforms
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "main" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable.
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
# Set up a matrix to run the following 3 configurations:
|
||||||
|
# 1. <Windows, Release, latest MSVC compiler toolchain on the default runner image, default generator>
|
||||||
|
# 2. <Linux, Release, latest GCC compiler toolchain on the default runner image, default generator>
|
||||||
|
# 3. <Linux, Release, latest Clang compiler toolchain on the default runner image, default generator>
|
||||||
|
#
|
||||||
|
# To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list.
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
build_type: [Release]
|
||||||
|
c_compiler: [gcc, clang, cl]
|
||||||
|
include:
|
||||||
|
- os: windows-latest
|
||||||
|
c_compiler: cl
|
||||||
|
cpp_compiler: cl
|
||||||
|
- os: ubuntu-latest
|
||||||
|
c_compiler: gcc
|
||||||
|
cpp_compiler: g++
|
||||||
|
- os: ubuntu-latest
|
||||||
|
c_compiler: clang
|
||||||
|
cpp_compiler: clang++
|
||||||
|
- os: macos-latest
|
||||||
|
c_compiler: clang
|
||||||
|
cpp_compiler: clang++
|
||||||
|
exclude:
|
||||||
|
- os: windows-latest
|
||||||
|
c_compiler: gcc
|
||||||
|
- os: windows-latest
|
||||||
|
c_compiler: clang
|
||||||
|
- os: ubuntu-latest
|
||||||
|
c_compiler: cl
|
||||||
|
- os: macos-latest
|
||||||
|
c_compiler: gcc
|
||||||
|
- os: macos-latest
|
||||||
|
c_compiler: cl
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: 'recursive'
|
||||||
|
|
||||||
|
- name: Set reusable strings
|
||||||
|
# Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file.
|
||||||
|
id: strings
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Configure CMake
|
||||||
|
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||||
|
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||||
|
run: >
|
||||||
|
cmake -B ${{ steps.strings.outputs.build-output-dir }}
|
||||||
|
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
|
||||||
|
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
|
||||||
|
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||||
|
-S ${{ github.workspace }}
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
# Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
|
||||||
|
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }}
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
working-directory: ${{ steps.strings.outputs.build-output-dir }}
|
||||||
|
# Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
|
||||||
|
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||||
|
run: ctest --build-config ${{ matrix.build_type }}
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,3 +1,9 @@
|
|||||||
|
.DS_Store
|
||||||
|
.vs/
|
||||||
Kraken.xcodeproj/xcuserdata
|
Kraken.xcodeproj/xcuserdata
|
||||||
kraken_win/build/
|
kraken_win/build/
|
||||||
build/
|
build/
|
||||||
|
kraken.dir/
|
||||||
|
Win32/
|
||||||
|
x64/
|
||||||
|
kraken_win
|
||||||
|
|||||||
31
.gitmodules
vendored
Normal file
31
.gitmodules
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
[submodule "hydra"]
|
||||||
|
path = hydra
|
||||||
|
url = ../hydra
|
||||||
|
branch = main
|
||||||
|
[submodule "3rdparty/glslang"]
|
||||||
|
path = 3rdparty/glslang
|
||||||
|
url = https://github.com/KhronosGroup/glslang
|
||||||
|
[submodule "3rdparty/vulkan"]
|
||||||
|
path = 3rdparty/vulkan
|
||||||
|
url = https://github.com/KhronosGroup/Vulkan-Headers
|
||||||
|
branch = v1.3.272
|
||||||
|
[submodule "3rdparty/volk"]
|
||||||
|
path = 3rdparty/volk
|
||||||
|
url = https://github.com/zeux/volk
|
||||||
|
[submodule "3rdparty/vma"]
|
||||||
|
path = 3rdparty/vma
|
||||||
|
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
|
||||||
|
[submodule "spirvreflect"]
|
||||||
|
path = 3rdparty/spirv-reflect
|
||||||
|
url = https://github.com/KhronosGroup/SPIRV-Reflect.git
|
||||||
|
[submodule "3rdparty/compressonator"]
|
||||||
|
path = 3rdparty/compressonator
|
||||||
|
url = https://github.com/GPUOpen-Tools/compressonator.git
|
||||||
|
[submodule "mimir"]
|
||||||
|
path = mimir
|
||||||
|
url = ../mimir
|
||||||
|
branch = main
|
||||||
|
[submodule "siren"]
|
||||||
|
path = siren
|
||||||
|
url = ../siren
|
||||||
|
branch = main
|
||||||
@@ -3,7 +3,7 @@ compiler: clang
|
|||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- feature-vulkan
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
|||||||
1
3rdparty/compressonator
vendored
Submodule
1
3rdparty/compressonator
vendored
Submodule
Submodule 3rdparty/compressonator added at bab59d4330
1
3rdparty/glslang
vendored
Submodule
1
3rdparty/glslang
vendored
Submodule
Submodule 3rdparty/glslang added at 8a85691a07
1
3rdparty/spirv-reflect
vendored
Submodule
1
3rdparty/spirv-reflect
vendored
Submodule
Submodule 3rdparty/spirv-reflect added at e55086b044
1
3rdparty/vma
vendored
Submodule
1
3rdparty/vma
vendored
Submodule
Submodule 3rdparty/vma added at 1d8f600fd4
1
3rdparty/volk
vendored
Submodule
1
3rdparty/volk
vendored
Submodule
Submodule 3rdparty/volk added at 43c29e655c
1
3rdparty/vulkan
vendored
Submodule
1
3rdparty/vulkan
vendored
Submodule
Submodule 3rdparty/vulkan added at b39ab380a4
288
CMakeLists.txt
288
CMakeLists.txt
@@ -1,14 +1,16 @@
|
|||||||
cmake_minimum_required (VERSION 2.6)
|
cmake_minimum_required (VERSION 3.16)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
if (NOT WIN32)
|
if (WIN32)
|
||||||
set(CMAKE_CXX_COMPILER "clang++")
|
add_definitions(-D_HAS_EXCEPTIONS=0)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")
|
if (NOT WIN32 AND NOT ANDROID)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
set(CMAKE_CXX_COMPILER "clang++")
|
||||||
|
endif()
|
||||||
|
|
||||||
project (Kraken)
|
project (Kraken)
|
||||||
|
|
||||||
@@ -27,6 +29,21 @@ macro (add_sources)
|
|||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
macro (add_standard_asset)
|
||||||
|
file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
foreach (_src ${ARGN})
|
||||||
|
if (_relPath)
|
||||||
|
list (APPEND KRAKEN_STANDARD_ASSETS "${_relPath}/${_src}")
|
||||||
|
else()
|
||||||
|
list (APPEND KRAKEN_STANDARD_ASSETS "${_src}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
if (_relPath)
|
||||||
|
# propagate KRAKEN_STANDARD_ASSETS to parent directory
|
||||||
|
set (KRAKEN_STANDARD_ASSETS ${KRAKEN_STANDARD_ASSETS} PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
macro (add_public_header)
|
macro (add_public_header)
|
||||||
file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
foreach (_src ${ARGN})
|
foreach (_src ${ARGN})
|
||||||
@@ -42,37 +59,266 @@ macro (add_public_header)
|
|||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
macro (add_private_headers)
|
||||||
|
file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
foreach (_src ${ARGN})
|
||||||
|
if (_relPath)
|
||||||
|
list (APPEND KRAKEN_PRIVATE_HEADERS "${_relPath}/${_src}")
|
||||||
|
else()
|
||||||
|
list (APPEND KRAKEN_PRIVATE_HEADERS "${_src}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
if (_relPath)
|
||||||
|
# propagate KRAKEN_PRIVATE_HEADERS to parent directory
|
||||||
|
set (KRAKEN_PRIVATE_HEADERS ${KRAKEN_PRIVATE_HEADERS} PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro (add_source_and_header)
|
||||||
|
foreach (_src ${ARGN})
|
||||||
|
add_sources("${_src}.cpp")
|
||||||
|
add_private_headers("${_src}.h")
|
||||||
|
endforeach()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
IF(APPLE)
|
IF(APPLE)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-deprecated-declarations -Wno-c++11-extensions")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated -Wno-deprecated-declarations -Wno-c++11-extensions")
|
||||||
# SET(GUI_TYPE MACOSX_BUNDLE)
|
# SET(GUI_TYPE MACOSX_BUNDLE)
|
||||||
# INCLUDE_DIRECTORIES ( /Developer/Headers/FlatCarbon )
|
# INCLUDE_DIRECTORIES ( /Developer/Headers/FlatCarbon )
|
||||||
|
FIND_LIBRARY(APPKIT_LIBRARY AppKit)
|
||||||
FIND_LIBRARY(OPENGL_LIBRARY OpenGL)
|
FIND_LIBRARY(OPENGL_LIBRARY OpenGL)
|
||||||
FIND_LIBRARY(AUDIO_TOOLBOX_LIBRARY AudioToolbox)
|
FIND_LIBRARY(AUDIO_TOOLBOX_LIBRARY AudioToolbox)
|
||||||
MARK_AS_ADVANCED (OPENGL_LIBRARY
|
FIND_LIBRARY(ACCELERATE_LIBRARY Accelerate)
|
||||||
AUDIO_TOOLBOX_LIBRARY)
|
MARK_AS_ADVANCED (APPKIT_LIBRARY
|
||||||
SET(EXTRA_LIBS ${OPENGL_LIBRARY} ${AUDIO_TOOLBOX_LIBRARY})
|
OPENGL_LIBRARY
|
||||||
|
AUDIO_TOOLBOX_LIBRARY
|
||||||
|
ACCELERATE_LIBRARY)
|
||||||
|
SET(EXTRA_LIBS ${APPKIT_LIBRARY} ${OPENGL_LIBRARY} ${AUDIO_TOOLBOX_LIBRARY} ${ACCELERATE_LIBRARY})
|
||||||
FIND_PATH(COCOA_INCLUDE_DIR OpenGL/gl3.h)
|
FIND_PATH(COCOA_INCLUDE_DIR OpenGL/gl3.h)
|
||||||
ENDIF (APPLE)
|
ENDIF (APPLE)
|
||||||
|
|
||||||
add_subdirectory(kraken)
|
add_subdirectory(kraken)
|
||||||
|
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/kraken PREFIX Source FILES ${SRCS} ${KRAKEN_PRIVATE_HEADERS})
|
||||||
|
|
||||||
add_library(kraken STATIC ${SRCS} ${KRAKEN_PUBLIC_HEADERS})
|
add_public_header(hydra/include/aabb.h)
|
||||||
|
add_public_header(hydra/include/hitinfo.h)
|
||||||
|
add_public_header(hydra/include/hydra.h)
|
||||||
|
add_public_header(hydra/include/matrix2.h)
|
||||||
|
add_public_header(hydra/include/matrix2x3.h)
|
||||||
|
add_public_header(hydra/include/matrix4.h)
|
||||||
|
add_public_header(hydra/include/quaternion.h)
|
||||||
|
add_public_header(hydra/include/scalar.h)
|
||||||
|
add_public_header(hydra/include/triangle3.h)
|
||||||
|
add_public_header(hydra/include/vector2.h)
|
||||||
|
add_public_header(hydra/include/vector3.h)
|
||||||
|
add_public_header(hydra/include/vector4.h)
|
||||||
|
add_public_header(hydra/include/vector2i.h)
|
||||||
|
|
||||||
|
add_public_header(mimir/include/mimir.h)
|
||||||
|
add_public_header(mimir/include/block.h)
|
||||||
|
|
||||||
|
add_public_header(siren/include/siren.h)
|
||||||
|
add_public_header(siren/include/dsp.h)
|
||||||
|
|
||||||
|
# ---- Android ----
|
||||||
|
if(ANDROID)
|
||||||
|
add_subdirectory(kraken_android)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---- Hydra ----
|
||||||
|
add_subdirectory(hydra)
|
||||||
|
include_directories(hydra/include)
|
||||||
|
list (APPEND EXTRA_LIBS hydra)
|
||||||
|
|
||||||
|
# ---- Siren ----
|
||||||
|
add_subdirectory(siren)
|
||||||
|
include_directories(siren/include)
|
||||||
|
list (APPEND EXTRA_LIBS siren)
|
||||||
|
|
||||||
|
# ---- Mimir ----
|
||||||
|
add_subdirectory(mimir)
|
||||||
|
include_directories(mimir/include)
|
||||||
|
list (APPEND EXTRA_LIBS mimir)
|
||||||
|
|
||||||
|
# ---- Compressonator CMP_Core ----
|
||||||
|
add_subdirectory(3rdparty/compressonator/cmp_core)
|
||||||
|
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/compressonator/cmp_core/source")
|
||||||
|
list (APPEND EXTRA_LIBS CMP_Core)
|
||||||
|
|
||||||
|
# ---- Vulkan ----
|
||||||
|
add_library(vulkan INTERFACE)
|
||||||
|
set(VULKAN_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/vulkan/include)
|
||||||
|
target_sources(vulkan INTERFACE ${VULKAN_INCLUDE_DIR}/vulkan/vulkan.h)
|
||||||
|
source_group("3rd Party/Vulkan" FILES ${VULKAN_INCLUDE_DIR}/vulkan/vulkan.h)
|
||||||
|
target_include_directories(vulkan INTERFACE ${VULKAN_INCLUDE_DIR})
|
||||||
|
|
||||||
|
target_compile_definitions(vulkan INTERFACE VK_NO_PROTOTYPES)
|
||||||
|
|
||||||
|
if(ANDROID)
|
||||||
|
target_compile_definitions(vulkan INTERFACE VK_USE_PLATFORM_ANDROID_KHR)
|
||||||
|
elseif(WIN32)
|
||||||
|
target_compile_definitions(vulkan INTERFACE VK_USE_PLATFORM_WIN32_KHR)
|
||||||
|
elseif(APPLE)
|
||||||
|
target_compile_definitions(vulkan INTERFACE VK_USE_PLATFORM_METAL_EXT)
|
||||||
|
elseif(UNIX)
|
||||||
|
# See whether X11 is available. If not, fall back to direct-to-display mode.
|
||||||
|
find_package(X11 QUIET)
|
||||||
|
if (X11_FOUND)
|
||||||
|
target_compile_definitions(vulkan INTERFACE VK_USE_PLATFORM_XCB_KHR)
|
||||||
|
else()
|
||||||
|
set(DIRECT_TO_DISPLAY TRUE)
|
||||||
|
set(DIRECT_TO_DISPLAY TRUE PARENT_SCOPE)
|
||||||
|
target_compile_definitions(vulkan INTERFACE VK_USE_PLATFORM_DISPLAY_KHR)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list (APPEND EXTRA_LIBS vulkan)
|
||||||
|
|
||||||
|
# ---- Vulkan Memory Allocator ----
|
||||||
|
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/vma/include")
|
||||||
|
|
||||||
|
# ---- Volk ----
|
||||||
|
# volk
|
||||||
|
set(VOLK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/volk")
|
||||||
|
set(VOLK_FILES
|
||||||
|
"${VOLK_DIR}/volk.c"
|
||||||
|
"${VOLK_DIR}/volk.h")
|
||||||
|
|
||||||
|
add_library(volk STATIC ${VOLK_FILES})
|
||||||
|
|
||||||
|
target_link_libraries(volk PUBLIC vulkan)
|
||||||
|
|
||||||
|
target_include_directories(volk PUBLIC ${VOLK_DIR})
|
||||||
|
|
||||||
|
set_property(TARGET volk PROPERTY FOLDER "3rdparty")
|
||||||
|
|
||||||
|
list (APPEND EXTRA_LIBS volk)
|
||||||
|
|
||||||
|
# ---- GLSlang ----
|
||||||
|
if(NOT ANDROID)
|
||||||
|
set(ENABLE_GLSLANG_BINARIES OFF)
|
||||||
|
set(ENABLE_GLSLANG_INSTALL OFF)
|
||||||
|
set(ENABLE_SPVREMAPPER OFF)
|
||||||
|
add_subdirectory(3rdparty/glslang)
|
||||||
|
include_directories(3rdparty/glslang/Public)
|
||||||
|
list (APPEND EXTRA_LIBS "glslang")
|
||||||
|
list (APPEND EXTRA_LIBS "SPIRV")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---- SPIRV-Reflect ----
|
||||||
|
include_directories(3rdparty/spirv-reflect)
|
||||||
|
add_source_and_header(3rdparty/spirv-reflect/spirv_reflect)
|
||||||
|
source_group("3rd Party/SPIRV Reflect" FILES 3rdparty/spirv-reflect/spirv_reflect.h 3rdparty/spirv-reflect/spirv_reflect.c 3rdparty/spirv-reflect/spirv_reflect.cpp)
|
||||||
|
|
||||||
|
# ---- TinyXML2 ----
|
||||||
|
add_source_and_header(3rdparty/tinyxml2/tinyxml2)
|
||||||
|
source_group("3rd Party/TinyXML 2" FILES 3rdparty/tinyxml2/tinyxml2.h 3rdparty/tinyxml2/tinyxml2.cpp)
|
||||||
|
|
||||||
|
# ---- Forsyth ----
|
||||||
|
add_source_and_header(3rdparty/forsyth/forsyth)
|
||||||
|
source_group("3rd Party/Forsyth" FILES 3rdparty/forsyth/forsyth.h 3rdparty/forsyth/forsyth.cpp)
|
||||||
|
|
||||||
|
source_group("Public Headers", FILES ${KRAKEN_PUBLIC_HEADERS})
|
||||||
|
|
||||||
|
add_library(kraken STATIC ${SRCS} ${KRAKEN_PUBLIC_HEADERS} ${KRAKEN_PRIVATE_HEADERS})
|
||||||
TARGET_LINK_LIBRARIES( kraken ${EXTRA_LIBS} )
|
TARGET_LINK_LIBRARIES( kraken ${EXTRA_LIBS} )
|
||||||
SET_TARGET_PROPERTIES(
|
SET_TARGET_PROPERTIES(
|
||||||
kraken
|
kraken
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
FRAMEWORK ON
|
|
||||||
SOVERSION 0
|
|
||||||
VERSION 0.1.0
|
|
||||||
PUBLIC_HEADER "${KRAKEN_PUBLIC_HEADERS}"
|
PUBLIC_HEADER "${KRAKEN_PUBLIC_HEADERS}"
|
||||||
PRIVATE_HEADER "${PRIVATE_HEADER_FILES}"
|
PRIVATE_HEADER "${KRAKEN_PRIVATE_HEADERS}"
|
||||||
ARCHIVE_OUTPUT_DIRECTORY "archive"
|
ARCHIVE_OUTPUT_DIRECTORY "lib${LIB_SUFFIX}"
|
||||||
LIBRARY_OUTPUT_DIRECTORY "lib"
|
OUTPUT_NAME kraken_static
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(kraken PRIVATE "kraken")
|
||||||
|
|
||||||
|
add_library(kraken_dynamic SHARED ${SRCS} ${KRAKEN_PUBLIC_HEADERS} ${KRAKEN_PRIVATE_HEADERS})
|
||||||
|
TARGET_LINK_LIBRARIES( kraken_dynamic ${EXTRA_LIBS} )
|
||||||
|
SET_TARGET_PROPERTIES(
|
||||||
|
kraken_dynamic
|
||||||
|
PROPERTIES
|
||||||
|
PUBLIC_HEADER "${KRAKEN_PUBLIC_HEADERS}"
|
||||||
|
PRIVATE_HEADER "${KRAKEN_PRIVATE_HEADERS}"
|
||||||
|
ARCHIVE_OUTPUT_DIRECTORY "lib${LIB_SUFFIX}"
|
||||||
OUTPUT_NAME kraken
|
OUTPUT_NAME kraken
|
||||||
)
|
)
|
||||||
|
|
||||||
# add_custom_target(package
|
target_include_directories(kraken_dynamic PRIVATE "kraken")
|
||||||
# COMMENT "Compressing..."
|
|
||||||
# WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/archive"
|
install(TARGETS kraken
|
||||||
# COMMAND ${CMAKE_COMMAND} -E tar "cfvz" "kraken.tgz" "*"
|
RUNTIME DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/${CMAKE_BUILD_TYPE}/bin/win
|
||||||
# )
|
PUBLIC_HEADER DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/include
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/${CMAKE_BUILD_TYPE}/lib/win
|
||||||
|
LIBRARY DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/${CMAKE_BUILD_TYPE}/lib/win
|
||||||
|
)
|
||||||
|
|
||||||
|
IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||||
|
install (FILES $<TARGET_PDB_FILE:kraken>
|
||||||
|
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/lib/win)
|
||||||
|
ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||||
|
|
||||||
|
add_subdirectory(standard_assets)
|
||||||
|
|
||||||
|
|
||||||
|
SET(STANDARD_ASSET_LIST_FILE "${CMAKE_BINARY_DIR}/standard_assets_list")
|
||||||
|
SET(STANDARD_ASSET_BUNDLE "${CMAKE_BINARY_DIR}/output/assets/standard_assets.krbundle")
|
||||||
|
|
||||||
|
SET(STANDARD_ASSET_LIST_FILE_CONTENTS "")
|
||||||
|
FOREACH(line ${KRAKEN_STANDARD_ASSETS})
|
||||||
|
SET(STANDARD_ASSET_LIST_FILE_CONTENTS "${STANDARD_ASSET_LIST_FILE_CONTENTS}${line}\n")
|
||||||
|
ENDFOREACH(line)
|
||||||
|
FILE(WRITE ${STANDARD_ASSET_LIST_FILE} ${STANDARD_ASSET_LIST_FILE_CONTENTS})
|
||||||
|
FILE(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/output/assets")
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${STANDARD_ASSET_BUNDLE}
|
||||||
|
COMMAND kraken_convert -c -i ${STANDARD_ASSET_LIST_FILE} -o ${STANDARD_ASSET_BUNDLE}
|
||||||
|
DEPENDS kraken_convert ${KRAKEN_STANDARD_ASSETS} ${STANDARD_ASSET_LIST_FILE}
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
|
COMMENT "Creating Standard Assets"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(standard_assets ALL
|
||||||
|
DEPENDS ${STANDARD_ASSET_BUNDLE}
|
||||||
|
SOURCES ${KRAKEN_STANDARD_ASSETS}
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach(header_file ${KRAKEN_PUBLIC_HEADERS})
|
||||||
|
get_filename_component(header_file_name "${header_file}" NAME)
|
||||||
|
list(APPEND KRAKEN_PUBLIC_HEADERS_OUTPUT "${header_file_name}")
|
||||||
|
endforeach()
|
||||||
|
list(TRANSFORM KRAKEN_PUBLIC_HEADERS_OUTPUT PREPEND "${CMAKE_BINARY_DIR}/output/include/")
|
||||||
|
|
||||||
|
file(COPY ${KRAKEN_PUBLIC_HEADERS} DESTINATION "${CMAKE_BINARY_DIR}/output/include")
|
||||||
|
|
||||||
|
add_custom_target(kraken_sdk ALL
|
||||||
|
DEPENDS ${STANDARD_ASSET_BUNDLE} ${KRAKEN_PUBLIC_HEADERS_OUTPUT}
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET kraken_sdk
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
$<TARGET_FILE:kraken>
|
||||||
|
${CMAKE_BINARY_DIR}/output/lib/$<TARGET_FILE_NAME:kraken>
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET kraken_sdk
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
$<TARGET_FILE:kraken_dynamic>
|
||||||
|
${CMAKE_BINARY_DIR}/output/lib/$<TARGET_FILE_NAME:kraken_dynamic>
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(tests)
|
||||||
|
add_subdirectory(tools)
|
||||||
|
|
||||||
|
set_target_properties( kraken PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/output/lib
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/output/lib
|
||||||
|
)
|
||||||
|
|||||||
26
CMakeSettings.json
Normal file
26
CMakeSettings.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "x64-Debug",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"configurationType": "Debug",
|
||||||
|
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
|
||||||
|
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
|
||||||
|
"cmakeCommandArgs": "",
|
||||||
|
"buildCommandArgs": "",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "msvc_x64_x64" ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x64-Release",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"configurationType": "RelWithDebInfo",
|
||||||
|
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
|
||||||
|
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
|
||||||
|
"cmakeCommandArgs": "",
|
||||||
|
"buildCommandArgs": "",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "msvc_x64_x64" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Workspace
|
|
||||||
version = "1.0">
|
|
||||||
<FileRef
|
|
||||||
location = "self:KREngine.xcodeproj">
|
|
||||||
</FileRef>
|
|
||||||
</Workspace>
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Scheme
|
|
||||||
LastUpgradeVersion = "0900"
|
|
||||||
version = "1.3">
|
|
||||||
<BuildAction
|
|
||||||
parallelizeBuildables = "YES"
|
|
||||||
buildImplicitDependencies = "YES">
|
|
||||||
<BuildActionEntries>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "E4BBBB7D1512A40300F43B5B"
|
|
||||||
BuildableName = "kraken.framework"
|
|
||||||
BlueprintName = "Kraken - osx"
|
|
||||||
ReferencedContainer = "container:Kraken.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
</BuildActionEntries>
|
|
||||||
</BuildAction>
|
|
||||||
<TestAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
language = ""
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
|
||||||
<Testables>
|
|
||||||
</Testables>
|
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</TestAction>
|
|
||||||
<LaunchAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
language = ""
|
|
||||||
launchStyle = "0"
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
|
||||||
debugDocumentVersioning = "YES"
|
|
||||||
debugServiceExtension = "internal"
|
|
||||||
allowLocationSimulation = "YES">
|
|
||||||
<MacroExpansion>
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "E4BBBB7D1512A40300F43B5B"
|
|
||||||
BuildableName = "kraken.framework"
|
|
||||||
BlueprintName = "Kraken - osx"
|
|
||||||
ReferencedContainer = "container:Kraken.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</MacroExpansion>
|
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</LaunchAction>
|
|
||||||
<ProfileAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
||||||
savedToolIdentifier = ""
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
debugDocumentVersioning = "YES">
|
|
||||||
<MacroExpansion>
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "E4BBBB7D1512A40300F43B5B"
|
|
||||||
BuildableName = "kraken.framework"
|
|
||||||
BlueprintName = "Kraken - osx"
|
|
||||||
ReferencedContainer = "container:Kraken.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</MacroExpansion>
|
|
||||||
</ProfileAction>
|
|
||||||
<AnalyzeAction
|
|
||||||
buildConfiguration = "Debug">
|
|
||||||
</AnalyzeAction>
|
|
||||||
<ArchiveAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
revealArchiveInOrganizer = "YES">
|
|
||||||
</ArchiveAction>
|
|
||||||
</Scheme>
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Scheme
|
|
||||||
LastUpgradeVersion = "0900"
|
|
||||||
version = "1.3">
|
|
||||||
<BuildAction
|
|
||||||
parallelizeBuildables = "YES"
|
|
||||||
buildImplicitDependencies = "YES">
|
|
||||||
<BuildActionEntries>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "E48C527919C570C50062E439"
|
|
||||||
BuildableName = "kraken.framework"
|
|
||||||
BlueprintName = "kraken - ios"
|
|
||||||
ReferencedContainer = "container:Kraken.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
</BuildActionEntries>
|
|
||||||
</BuildAction>
|
|
||||||
<TestAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
language = ""
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
|
||||||
<Testables>
|
|
||||||
</Testables>
|
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</TestAction>
|
|
||||||
<LaunchAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
language = ""
|
|
||||||
launchStyle = "0"
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
|
||||||
debugDocumentVersioning = "YES"
|
|
||||||
debugServiceExtension = "internal"
|
|
||||||
allowLocationSimulation = "YES">
|
|
||||||
<MacroExpansion>
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "E48C527919C570C50062E439"
|
|
||||||
BuildableName = "kraken.framework"
|
|
||||||
BlueprintName = "kraken - ios"
|
|
||||||
ReferencedContainer = "container:Kraken.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</MacroExpansion>
|
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</LaunchAction>
|
|
||||||
<ProfileAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
||||||
savedToolIdentifier = ""
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
debugDocumentVersioning = "YES">
|
|
||||||
<MacroExpansion>
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "E48C527919C570C50062E439"
|
|
||||||
BuildableName = "kraken.framework"
|
|
||||||
BlueprintName = "kraken - ios"
|
|
||||||
ReferencedContainer = "container:Kraken.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</MacroExpansion>
|
|
||||||
</ProfileAction>
|
|
||||||
<AnalyzeAction
|
|
||||||
buildConfiguration = "Debug">
|
|
||||||
</AnalyzeAction>
|
|
||||||
<ArchiveAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
revealArchiveInOrganizer = "YES">
|
|
||||||
</ArchiveAction>
|
|
||||||
</Scheme>
|
|
||||||
1
configure_linux.sh
Executable file
1
configure_linux.sh
Executable file
@@ -0,0 +1 @@
|
|||||||
|
cmake -H. -G Ninja -Bbuild -DCMAKE_TOOLCHAIN_FILE="toolchain/toolchain-x86_64-linux-clang.cmake"
|
||||||
1
configure_macos.sh
Executable file
1
configure_macos.sh
Executable file
@@ -0,0 +1 @@
|
|||||||
|
cmake -H. -G Ninja -Bbuild -DCMAKE_TOOLCHAIN_FILE="toolchain/toolchain-x86_64-apple-darwin-clang.cmake"
|
||||||
3
configure_macos_xcode.sh
Executable file
3
configure_macos_xcode.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -G Xcode -T buildsystem=1
|
||||||
2
configure_win64.bat
Normal file
2
configure_win64.bat
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
rem call "%VSINSTALLDIR%VC\Auxiliary\Build\vcvars64.bat"
|
||||||
|
cmake -H. -G Ninja -Bbuild -DCMAKE_TOOLCHAIN_FILE="toolchain/toolchain-x86_64-pc-windows-msvc.cmake"
|
||||||
2
configure_win64_msvc.bat
Normal file
2
configure_win64_msvc.bat
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
rem call "%VSINSTALLDIR%VC\Auxiliary\Build\vcvars64.bat"
|
||||||
|
cmake -H. -G"Visual Studio 17 2022" -Bbuild -DCMAKE_TOOLCHAIN_FILE="toolchain/toolchain-x86_64-pc-windows-msvc.cmake"
|
||||||
1
hydra
Submodule
1
hydra
Submodule
Submodule hydra added at 5c24fb9fbb
@@ -1,13 +1,100 @@
|
|||||||
include_directories(public)
|
include_directories(public)
|
||||||
add_subdirectory(public)
|
add_subdirectory(public)
|
||||||
set(KRAKEN_PUBLIC_HEADERS "${KRAKEN_PUBLIC_HEADERS}" PARENT_SCOPE)
|
set(KRAKEN_PUBLIC_HEADERS "${KRAKEN_PUBLIC_HEADERS}" PARENT_SCOPE)
|
||||||
|
set(KRAKEN_PRIVATE_HEADERS "${KRAKEN_PRIVATE_HEADERS}" PARENT_SCOPE)
|
||||||
add_sources(scalar.cpp)
|
|
||||||
add_sources(vector2.cpp)
|
# Private Implementation
|
||||||
add_sources(vector3.cpp)
|
add_sources(kraken.cpp)
|
||||||
add_sources(vector4.cpp)
|
add_private_headers(KREngine-common.h)
|
||||||
add_sources(triangle3.cpp)
|
add_sources(resources/KRResource+blend.cpp)
|
||||||
add_sources(quaternion.cpp)
|
# add_source(resources/KRResource+fbx.cpp) # TODO - Locate FBX SDK dependencies
|
||||||
add_sources(matrix4.cpp)
|
add_private_headers(resources/KRResource.h)
|
||||||
add_sources(aabb.cpp)
|
add_source_and_header(KRAudioBuffer)
|
||||||
add_sources(hitinfo.cpp)
|
add_source_and_header(KRBehavior)
|
||||||
|
add_source_and_header(KRContext)
|
||||||
|
add_source_and_header(KRContextObject)
|
||||||
|
add_source_and_header(KRDevice)
|
||||||
|
add_source_and_header(KRDeviceManager)
|
||||||
|
add_source_and_header(KRHelpers)
|
||||||
|
add_source_and_header(KRModelView)
|
||||||
|
add_source_and_header(KROctree)
|
||||||
|
add_source_and_header(KROctreeNode)
|
||||||
|
add_source_and_header(KRPipeline)
|
||||||
|
add_source_and_header(KRPipelineManager)
|
||||||
|
add_source_and_header(KRPresentationThread)
|
||||||
|
add_source_and_header(KRRenderGraph)
|
||||||
|
add_source_and_header(KRRenderGraphBlackFrame)
|
||||||
|
add_source_and_header(KRRenderGraphDeferred)
|
||||||
|
add_source_and_header(KRRenderGraphForward)
|
||||||
|
add_source_and_header(KRRenderPass)
|
||||||
|
add_source_and_header(KRRenderSettings)
|
||||||
|
add_source_and_header(KRSampler)
|
||||||
|
add_source_and_header(KRSamplerManager)
|
||||||
|
add_source_and_header(KRShaderReflection)
|
||||||
|
add_source_and_header(KRStreamerThread)
|
||||||
|
add_source_and_header(KRSurface)
|
||||||
|
add_source_and_header(KRSurfaceManager)
|
||||||
|
add_source_and_header(KRSwapchain)
|
||||||
|
add_source_and_header(KRUniformBuffer)
|
||||||
|
add_source_and_header(KRUniformBufferManager)
|
||||||
|
add_source_and_header(KRViewport)
|
||||||
|
add_source_and_header(nodes/KRAmbientZone)
|
||||||
|
add_source_and_header(nodes/KRAudioSource)
|
||||||
|
add_source_and_header(nodes/KRBone)
|
||||||
|
add_source_and_header(nodes/KRCamera)
|
||||||
|
add_source_and_header(nodes/KRCollider)
|
||||||
|
add_source_and_header(nodes/KRDirectionalLight)
|
||||||
|
add_source_and_header(nodes/KRLight)
|
||||||
|
add_source_and_header(nodes/KRLocator)
|
||||||
|
add_source_and_header(nodes/KRLODGroup)
|
||||||
|
add_source_and_header(nodes/KRLODSet)
|
||||||
|
add_source_and_header(nodes/KRModel)
|
||||||
|
add_source_and_header(nodes/KRNode)
|
||||||
|
add_source_and_header(nodes/KRParticleSystem)
|
||||||
|
add_source_and_header(nodes/KRParticleSystemNewtonian)
|
||||||
|
add_source_and_header(nodes/KRPointLight)
|
||||||
|
add_source_and_header(nodes/KRReverbZone)
|
||||||
|
add_source_and_header(nodes/KRSpotLight)
|
||||||
|
add_source_and_header(nodes/KRSprite)
|
||||||
|
add_source_and_header(resources/animation/KRAnimation)
|
||||||
|
add_source_and_header(resources/animation/KRAnimationAttribute)
|
||||||
|
add_source_and_header(resources/animation/KRAnimationLayer)
|
||||||
|
add_source_and_header(resources/animation/KRAnimationManager)
|
||||||
|
add_source_and_header(resources/animation_curve/KRAnimationCurve)
|
||||||
|
add_source_and_header(resources/animation_curve/KRAnimationCurveManager)
|
||||||
|
add_source_and_header(resources/audio/KRAudioManager)
|
||||||
|
add_source_and_header(resources/audio/KRAudioSample)
|
||||||
|
add_source_and_header(resources/audio/KRAudioSampleBinding)
|
||||||
|
add_source_and_header(resources/bundle/KRBundle)
|
||||||
|
add_source_and_header(resources/bundle/KRBundleManager)
|
||||||
|
add_source_and_header(resources/KRResource)
|
||||||
|
add_source_and_header(resources/KRResourceBinding)
|
||||||
|
add_source_and_header(resources/KRResourceManager)
|
||||||
|
add_source_and_header(resources/material/KRMaterial)
|
||||||
|
add_source_and_header(resources/material/KRMaterialBinding)
|
||||||
|
add_source_and_header(resources/material/KRMaterialManager)
|
||||||
|
add_source_and_header(resources/mesh/KRMesh)
|
||||||
|
add_source_and_header(resources/mesh/KRMeshBinding)
|
||||||
|
add_source_and_header(resources/mesh/KRMeshCube)
|
||||||
|
add_source_and_header(resources/mesh/KRMeshManager)
|
||||||
|
add_source_and_header(resources/mesh/KRMeshQuad)
|
||||||
|
add_source_and_header(resources/mesh/KRMeshSphere)
|
||||||
|
add_source_and_header(resources/scene/KRScene)
|
||||||
|
add_source_and_header(resources/scene/KRSceneManager)
|
||||||
|
add_source_and_header(resources/shader/KRShader)
|
||||||
|
add_source_and_header(resources/shader/KRShaderManager)
|
||||||
|
add_source_and_header(resources/source/KRSource)
|
||||||
|
add_source_and_header(resources/source/KRSourceManager)
|
||||||
|
add_source_and_header(resources/texture/KRTexture)
|
||||||
|
add_source_and_header(resources/texture/KRTexture2D)
|
||||||
|
add_source_and_header(resources/texture/KRTextureAnimated)
|
||||||
|
add_source_and_header(resources/texture/KRTextureBinding)
|
||||||
|
add_source_and_header(resources/texture/KRTextureCube)
|
||||||
|
add_source_and_header(resources/texture/KRTextureKTX)
|
||||||
|
add_source_and_header(resources/texture/KRTextureKTX2)
|
||||||
|
add_source_and_header(resources/texture/KRTextureManager)
|
||||||
|
add_source_and_header(resources/texture/KRTexturePVR)
|
||||||
|
add_source_and_header(resources/texture/KRTextureTGA)
|
||||||
|
add_source_and_header(resources/unknown/KRUnknown)
|
||||||
|
add_source_and_header(resources/unknown/KRUnknownManager)
|
||||||
|
add_sources(resources/KRResource+obj.cpp)
|
||||||
|
|||||||
@@ -1,167 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAmbientZone.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRAmbientZone.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
|
|
||||||
KRAmbientZone::KRAmbientZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
|
||||||
{
|
|
||||||
m_ambient = "";
|
|
||||||
m_ambient_gain = 1.0f;
|
|
||||||
|
|
||||||
m_gradient_distance = 0.25f;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAmbientZone::~KRAmbientZone()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRAmbientZone::getElementName() {
|
|
||||||
return "ambient_zone";
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
|
||||||
e->SetAttribute("zone", m_zone.c_str());
|
|
||||||
e->SetAttribute("sample", m_ambient.c_str());
|
|
||||||
e->SetAttribute("gain", m_ambient_gain);
|
|
||||||
e->SetAttribute("gradient", m_gradient_distance);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAmbientZone::loadXML(tinyxml2::XMLElement *e)
|
|
||||||
{
|
|
||||||
KRNode::loadXML(e);
|
|
||||||
|
|
||||||
m_zone = e->Attribute("zone");
|
|
||||||
|
|
||||||
m_gradient_distance = 0.25f;
|
|
||||||
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_gradient_distance = 0.25f;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ambient = e->Attribute("sample");
|
|
||||||
|
|
||||||
m_ambient_gain = 1.0f;
|
|
||||||
if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_ambient_gain = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRAmbientZone::getAmbient()
|
|
||||||
{
|
|
||||||
return m_ambient;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAmbientZone::setAmbient(const std::string &ambient)
|
|
||||||
{
|
|
||||||
m_ambient = ambient;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAmbientZone::getAmbientGain()
|
|
||||||
{
|
|
||||||
return m_ambient_gain;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAmbientZone::setAmbientGain(float ambient_gain)
|
|
||||||
{
|
|
||||||
m_ambient_gain = ambient_gain;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRAmbientZone::getZone()
|
|
||||||
{
|
|
||||||
return m_zone;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAmbientZone::setZone(const std::string &zone)
|
|
||||||
{
|
|
||||||
m_zone = zone;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAmbientZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
|
||||||
{
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
|
||||||
|
|
||||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
|
||||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
|
||||||
|
|
||||||
// Enable additive blending
|
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
|
||||||
|
|
||||||
|
|
||||||
// Disable z-buffer write
|
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
|
||||||
|
|
||||||
// Enable z-buffer test
|
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
|
||||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
|
||||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
|
||||||
if(sphereModels.size()) {
|
|
||||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
|
||||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable alpha blending
|
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float KRAmbientZone::getGradientDistance()
|
|
||||||
{
|
|
||||||
return m_gradient_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAmbientZone::setGradientDistance(float gradient_distance)
|
|
||||||
{
|
|
||||||
m_gradient_distance = gradient_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB KRAmbientZone::getBounds() {
|
|
||||||
// Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
|
||||||
return AABB(-Vector3::One(), Vector3::One(), getModelMatrix());
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAmbientZone::getContainment(const Vector3 &pos)
|
|
||||||
{
|
|
||||||
AABB bounds = getBounds();
|
|
||||||
if(bounds.contains(pos)) {
|
|
||||||
Vector3 size = bounds.size();
|
|
||||||
Vector3 diff = pos - bounds.center();
|
|
||||||
diff = diff * 2.0f;
|
|
||||||
diff = Vector3(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
|
||||||
float d = diff.magnitude();
|
|
||||||
|
|
||||||
if(m_gradient_distance <= 0.0f) {
|
|
||||||
// Avoid division by zero
|
|
||||||
d = d > 1.0f ? 0.0f : 1.0f;
|
|
||||||
} else {
|
|
||||||
d = (1.0f - d) / m_gradient_distance;
|
|
||||||
d = KRCLAMP(d, 0.0f, 1.0f);
|
|
||||||
}
|
|
||||||
return d;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAmbientZone.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRAMBIENT_ZONE_H
|
|
||||||
#define KRAMBIENT_ZONE_H
|
|
||||||
|
|
||||||
#include "KRResource.h"
|
|
||||||
#include "KRNode.h"
|
|
||||||
#include "KRTexture.h"
|
|
||||||
|
|
||||||
class KRAmbientZone : public KRNode {
|
|
||||||
public:
|
|
||||||
KRAmbientZone(KRScene &scene, std::string name);
|
|
||||||
virtual ~KRAmbientZone();
|
|
||||||
virtual std::string getElementName();
|
|
||||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
|
||||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
|
||||||
|
|
||||||
void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
|
|
||||||
|
|
||||||
std::string getZone();
|
|
||||||
void setZone(const std::string &zone);
|
|
||||||
|
|
||||||
float getGradientDistance();
|
|
||||||
void setGradientDistance(float gradient_distance);
|
|
||||||
|
|
||||||
std::string getAmbient();
|
|
||||||
void setAmbient(const std::string &ambient);
|
|
||||||
|
|
||||||
float getAmbientGain();
|
|
||||||
void setAmbientGain(float ambient_gain);
|
|
||||||
|
|
||||||
virtual AABB getBounds();
|
|
||||||
|
|
||||||
float getContainment(const Vector3 &pos);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_zone;
|
|
||||||
|
|
||||||
float m_gradient_distance;
|
|
||||||
|
|
||||||
std::string m_ambient;
|
|
||||||
float m_ambient_gain;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,349 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAnimation.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
#include <boost/tokenizer.hpp>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include "KRAnimation.h"
|
|
||||||
#include "KRAnimationManager.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "KRNode.h"
|
|
||||||
#include "KRAnimationCurve.h"
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
KRAnimation::KRAnimation(KRContext &context, std::string name) : KRResource(context, name)
|
|
||||||
{
|
|
||||||
m_auto_play = false;
|
|
||||||
m_loop = false;
|
|
||||||
m_playing = false;
|
|
||||||
m_local_time = 0.0f;
|
|
||||||
m_duration = 0.0f;
|
|
||||||
m_start_time = 0.0f;
|
|
||||||
}
|
|
||||||
KRAnimation::~KRAnimation()
|
|
||||||
{
|
|
||||||
for(unordered_map<std::string, KRAnimationLayer *>::iterator itr = m_layers.begin(); itr != m_layers.end(); ++itr){
|
|
||||||
delete (*itr).second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRAnimation::getExtension() {
|
|
||||||
return "kranimation";
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimation::addLayer(KRAnimationLayer *layer)
|
|
||||||
{
|
|
||||||
m_layers[layer->getName()] = layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAnimation::save(KRDataBlock &data) {
|
|
||||||
tinyxml2::XMLDocument doc;
|
|
||||||
tinyxml2::XMLElement *animation_node = doc.NewElement( "animation" );
|
|
||||||
doc.InsertEndChild(animation_node);
|
|
||||||
animation_node->SetAttribute("loop", m_loop ? "true" : "false");
|
|
||||||
animation_node->SetAttribute("auto_play", m_auto_play ? "true" : "false");
|
|
||||||
animation_node->SetAttribute("duration", m_duration);
|
|
||||||
animation_node->SetAttribute("start_time", m_start_time);
|
|
||||||
|
|
||||||
for(unordered_map<std::string, KRAnimationLayer *>::iterator itr = m_layers.begin(); itr != m_layers.end(); ++itr){
|
|
||||||
(*itr).second->saveXML(animation_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLPrinter p;
|
|
||||||
doc.Print(&p);
|
|
||||||
data.append((void *)p.CStr(), strlen(p.CStr())+1);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimation *KRAnimation::Load(KRContext &context, const std::string &name, KRDataBlock *data)
|
|
||||||
{
|
|
||||||
std::string xml_string = data->getString();
|
|
||||||
|
|
||||||
tinyxml2::XMLDocument doc;
|
|
||||||
doc.Parse(xml_string.c_str());
|
|
||||||
KRAnimation *new_animation = new KRAnimation(context, name);
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *animation_node = doc.RootElement();
|
|
||||||
|
|
||||||
if(animation_node->QueryFloatAttribute("duration", &new_animation->m_duration) != tinyxml2::XML_SUCCESS) {
|
|
||||||
new_animation->m_duration = 0.0f; // Default value
|
|
||||||
}
|
|
||||||
|
|
||||||
if(animation_node->QueryFloatAttribute("start_time", &new_animation->m_start_time) != tinyxml2::XML_SUCCESS) {
|
|
||||||
new_animation->m_start_time = 0.0f; // Default value
|
|
||||||
}
|
|
||||||
|
|
||||||
if(animation_node->QueryBoolAttribute("loop", &new_animation->m_loop) != tinyxml2::XML_SUCCESS) {
|
|
||||||
new_animation->m_loop = false; // Default value
|
|
||||||
}
|
|
||||||
|
|
||||||
if(animation_node->QueryBoolAttribute("auto_play", &new_animation->m_auto_play) != tinyxml2::XML_SUCCESS) {
|
|
||||||
new_animation->m_auto_play = false; // Default value
|
|
||||||
}
|
|
||||||
|
|
||||||
for(tinyxml2::XMLElement *child_element=animation_node->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) {
|
|
||||||
if(strcmp(child_element->Name(), "layer") == 0) {
|
|
||||||
KRAnimationLayer *new_layer = new KRAnimationLayer(context);
|
|
||||||
new_layer->loadXML(child_element);
|
|
||||||
new_animation->m_layers[new_layer->getName()] = new_layer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(new_animation->m_auto_play) {
|
|
||||||
new_animation->m_playing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// KRNode *n = KRNode::LoadXML(*new_scene, scene_element->FirstChildElement());
|
|
||||||
|
|
||||||
delete data;
|
|
||||||
return new_animation;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unordered_map<std::string, KRAnimationLayer *> &KRAnimation::getLayers()
|
|
||||||
{
|
|
||||||
return m_layers;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationLayer *KRAnimation::getLayer(const char *szName)
|
|
||||||
{
|
|
||||||
return m_layers[szName];
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimation::update(float deltaTime)
|
|
||||||
{
|
|
||||||
if(m_playing) {
|
|
||||||
m_local_time += deltaTime;
|
|
||||||
}
|
|
||||||
if(m_loop) {
|
|
||||||
while(m_local_time > m_duration) {
|
|
||||||
m_local_time -= m_duration;
|
|
||||||
}
|
|
||||||
} else if(m_local_time > m_duration) {
|
|
||||||
m_local_time = m_duration;
|
|
||||||
m_playing = false;
|
|
||||||
getContext().getAnimationManager()->updateActiveAnimations(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
|
|
||||||
KRAnimationLayer *layer = (*layer_itr).second;
|
|
||||||
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
|
|
||||||
KRAnimationAttribute *attribute = *attribute_itr;
|
|
||||||
|
|
||||||
|
|
||||||
// TODO - Currently only a single layer supported per animation -- need to either implement combining of multiple layers or ask the FBX sdk to bake all layers into one
|
|
||||||
KRAnimationCurve *curve = attribute->getCurve();
|
|
||||||
KRNode *target = attribute->getTarget();
|
|
||||||
KRNode::node_attribute_type attribute_type = attribute->getTargetAttribute();
|
|
||||||
|
|
||||||
if(curve != NULL && target != NULL) {
|
|
||||||
target->SetAttribute(attribute_type, curve->getValue(m_local_time + m_start_time));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimation::Play()
|
|
||||||
{
|
|
||||||
m_playing = true;
|
|
||||||
getContext().getAnimationManager()->updateActiveAnimations(this);
|
|
||||||
}
|
|
||||||
void KRAnimation::Stop()
|
|
||||||
{
|
|
||||||
m_playing = false;
|
|
||||||
getContext().getAnimationManager()->updateActiveAnimations(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAnimation::getTime()
|
|
||||||
{
|
|
||||||
return m_local_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimation::setTime(float time)
|
|
||||||
{
|
|
||||||
m_local_time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAnimation::getDuration()
|
|
||||||
{
|
|
||||||
return m_duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimation::setDuration(float duration)
|
|
||||||
{
|
|
||||||
m_duration = duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAnimation::getStartTime()
|
|
||||||
{
|
|
||||||
return m_start_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimation::setStartTime(float start_time)
|
|
||||||
{
|
|
||||||
m_start_time = start_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAnimation::isPlaying()
|
|
||||||
{
|
|
||||||
return m_playing;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAnimation::getAutoPlay() const
|
|
||||||
{
|
|
||||||
return m_auto_play;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimation::setAutoPlay(bool auto_play)
|
|
||||||
{
|
|
||||||
m_auto_play = auto_play;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAnimation::getLooping() const
|
|
||||||
{
|
|
||||||
return m_loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimation::setLooping(bool looping)
|
|
||||||
{
|
|
||||||
m_loop = looping;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KRAnimation *KRAnimation::split(const std::string &name, float start_time, float duration, bool strip_unchanging_attributes, bool clone_curves)
|
|
||||||
{
|
|
||||||
KRAnimation *new_animation = new KRAnimation(getContext(), name);
|
|
||||||
new_animation->setStartTime(start_time);
|
|
||||||
new_animation->setDuration(duration);
|
|
||||||
new_animation->m_loop = m_loop;
|
|
||||||
new_animation->m_auto_play = m_auto_play;
|
|
||||||
int new_curve_count = 0;
|
|
||||||
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
|
|
||||||
KRAnimationLayer *layer = (*layer_itr).second;
|
|
||||||
KRAnimationLayer *new_layer = new KRAnimationLayer(getContext());
|
|
||||||
new_layer->setName(layer->getName());
|
|
||||||
new_layer->setRotationAccumulationMode(layer->getRotationAccumulationMode());
|
|
||||||
new_layer->setScaleAccumulationMode(layer->getScaleAccumulationMode());
|
|
||||||
new_layer->setWeight(layer->getWeight());
|
|
||||||
new_animation->m_layers[new_layer->getName()] = new_layer;
|
|
||||||
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
|
|
||||||
KRAnimationAttribute *attribute = *attribute_itr;
|
|
||||||
|
|
||||||
// Updated Dec 9, 2013 by Peter to change the way that attributes are stripped.
|
|
||||||
//
|
|
||||||
// If we have been asked to strip_unchanging_attributes then we only want to strip those attributes that don't havechanges
|
|
||||||
// in any of their components (x, y, z). This means that we have to group the attributes before we check for valueChanges().
|
|
||||||
// The attributes won't come through in order, but they do come through in group order (each group of 3 arrives as x, y, z)
|
|
||||||
//
|
|
||||||
// Since this method isn't designed to handle groups, this is a bit of a hack. We simply take whatever channel is coming
|
|
||||||
// through and then check the other associated curves.
|
|
||||||
//
|
|
||||||
int targetAttribute = attribute->getTargetAttribute();
|
|
||||||
if (targetAttribute > 0) { // we have a valid target that fits within a group of 3
|
|
||||||
targetAttribute--; // this is now group relative 0,1,2 is the first group .. 3,4,5 is the second group, etc.
|
|
||||||
|
|
||||||
KRAnimationCurve *curve = attribute->getCurve(); // this is the curve we are currently handling
|
|
||||||
|
|
||||||
int placeInGroup = targetAttribute % 3; // this will be 0, 1 or 2
|
|
||||||
static long placeLookup[] = { 1, 2, -1, 1, -2, -1 };
|
|
||||||
|
|
||||||
KRAnimationAttribute *attribute2 = *(attribute_itr + placeLookup[placeInGroup*2]);
|
|
||||||
KRAnimationAttribute *attribute3 = *(attribute_itr + placeLookup[placeInGroup*2+1]);
|
|
||||||
KRAnimationCurve *curve2 = attribute2->getCurve();
|
|
||||||
KRAnimationCurve *curve3 = attribute3->getCurve();
|
|
||||||
|
|
||||||
bool include_attribute = true;
|
|
||||||
if(strip_unchanging_attributes) {
|
|
||||||
include_attribute = curve->valueChanges(start_time, duration) |
|
|
||||||
curve2->valueChanges(start_time, duration) |
|
|
||||||
curve3->valueChanges(start_time, duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(include_attribute) {
|
|
||||||
KRAnimationAttribute *new_attribute = new KRAnimationAttribute(getContext());
|
|
||||||
KRAnimationCurve *new_curve = curve;
|
|
||||||
if(clone_curves) {
|
|
||||||
std::string new_curve_name = name + "_curve" + boost::lexical_cast<std::string>(++new_curve_count);
|
|
||||||
new_curve = curve->split(new_curve_name, start_time, duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
new_attribute->setCurveName(new_curve->getName());
|
|
||||||
new_attribute->setTargetAttribute(attribute->getTargetAttribute());
|
|
||||||
new_attribute->setTargetName(attribute->getTargetName());
|
|
||||||
new_layer->addAttribute(new_attribute);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getContext().getAnimationManager()->addAnimation(new_animation);
|
|
||||||
return new_animation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimation::deleteCurves()
|
|
||||||
{
|
|
||||||
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
|
|
||||||
KRAnimationLayer *layer = (*layer_itr).second;
|
|
||||||
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
|
|
||||||
KRAnimationAttribute *attribute = *attribute_itr;
|
|
||||||
attribute->deleteCurve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimation::_lockData()
|
|
||||||
{
|
|
||||||
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
|
|
||||||
KRAnimationLayer *layer = (*layer_itr).second;
|
|
||||||
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
|
|
||||||
KRAnimationAttribute *attribute = *attribute_itr;
|
|
||||||
KRAnimationCurve *curve = attribute->getCurve();
|
|
||||||
if(curve) {
|
|
||||||
curve->_lockData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimation::_unlockData()
|
|
||||||
{
|
|
||||||
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
|
|
||||||
KRAnimationLayer *layer = (*layer_itr).second;
|
|
||||||
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
|
|
||||||
KRAnimationAttribute *attribute = *attribute_itr;
|
|
||||||
KRAnimationCurve *curve = attribute->getCurve();
|
|
||||||
if(curve) {
|
|
||||||
curve->_unlockData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAnimation.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRANIMATION_H
|
|
||||||
#define KRANIMATION_H
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
#include "KRContextObject.h"
|
|
||||||
#include "KRDataBlock.h"
|
|
||||||
#include "KRResource.h"
|
|
||||||
#include "KRAnimationLayer.h"
|
|
||||||
|
|
||||||
|
|
||||||
class KRAnimation : public KRResource {
|
|
||||||
|
|
||||||
public:
|
|
||||||
KRAnimation(KRContext &context, std::string name);
|
|
||||||
virtual ~KRAnimation();
|
|
||||||
|
|
||||||
virtual std::string getExtension();
|
|
||||||
virtual bool save(KRDataBlock &data);
|
|
||||||
|
|
||||||
static KRAnimation *Load(KRContext &context, const std::string &name, KRDataBlock *data);
|
|
||||||
|
|
||||||
void addLayer(KRAnimationLayer *layer);
|
|
||||||
unordered_map<std::string, KRAnimationLayer *> &getLayers();
|
|
||||||
KRAnimationLayer *getLayer(const char *szName);
|
|
||||||
bool getAutoPlay() const;
|
|
||||||
void setAutoPlay(bool auto_play);
|
|
||||||
bool getLooping() const;
|
|
||||||
void setLooping(bool looping);
|
|
||||||
void Play();
|
|
||||||
void Stop();
|
|
||||||
void update(float deltaTime);
|
|
||||||
float getTime();
|
|
||||||
void setTime(float time);
|
|
||||||
float getDuration();
|
|
||||||
void setDuration(float duration);
|
|
||||||
float getStartTime();
|
|
||||||
void setStartTime(float start_time);
|
|
||||||
bool isPlaying();
|
|
||||||
|
|
||||||
KRAnimation *split(const std::string &name, float start_time, float duration, bool strip_unchanging_attributes = true, bool clone_curves = true);
|
|
||||||
void deleteCurves();
|
|
||||||
|
|
||||||
void _lockData();
|
|
||||||
void _unlockData();
|
|
||||||
|
|
||||||
private:
|
|
||||||
unordered_map<std::string, KRAnimationLayer *> m_layers;
|
|
||||||
bool m_auto_play;
|
|
||||||
bool m_loop;
|
|
||||||
bool m_playing;
|
|
||||||
float m_local_time;
|
|
||||||
float m_duration;
|
|
||||||
float m_start_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,280 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAnimationAttribute.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRAnimationAttribute.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "KRAnimationManager.h"
|
|
||||||
#include "KRAnimationCurveManager.h"
|
|
||||||
|
|
||||||
|
|
||||||
KRAnimationAttribute::KRAnimationAttribute(KRContext &context) : KRContextObject(context)
|
|
||||||
{
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
|
|
||||||
m_target = NULL;
|
|
||||||
m_curve = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationAttribute::~KRAnimationAttribute()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRAnimationAttribute::saveXML( tinyxml2::XMLNode *parent)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLDocument *doc = parent->GetDocument();
|
|
||||||
tinyxml2::XMLElement *e = doc->NewElement("attribute");
|
|
||||||
parent->InsertEndChild(e);
|
|
||||||
e->SetAttribute("curve", m_curve_name.c_str());
|
|
||||||
e->SetAttribute("target", m_target_name.c_str());
|
|
||||||
const char *szAttribute = "none";
|
|
||||||
switch(m_node_attribute) {
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_NONE:
|
|
||||||
szAttribute = "none";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X:
|
|
||||||
szAttribute = "translate_x";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y:
|
|
||||||
szAttribute = "translate_y";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z:
|
|
||||||
szAttribute = "translate_z";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_X:
|
|
||||||
szAttribute = "scale_x";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Y:
|
|
||||||
szAttribute = "scale_y";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Z:
|
|
||||||
szAttribute = "scale_z";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_X:
|
|
||||||
szAttribute = "rotate_x";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Y:
|
|
||||||
szAttribute = "rotate_y";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Z:
|
|
||||||
szAttribute = "rotate_z";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X:
|
|
||||||
szAttribute = "pre_rotate_x";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y:
|
|
||||||
szAttribute = "pre_rotate_y";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z:
|
|
||||||
szAttribute = "pre_rotate_z";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X:
|
|
||||||
szAttribute = "post_rotate_x";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y:
|
|
||||||
szAttribute = "post_rotate_y";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z:
|
|
||||||
szAttribute = "post_rotate_z";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X:
|
|
||||||
szAttribute = "rotate_pivot_x";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y:
|
|
||||||
szAttribute = "rotate_pivot_y";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z:
|
|
||||||
szAttribute = "rotate_pivot_z";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X:
|
|
||||||
szAttribute = "scale_pivot_x";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y:
|
|
||||||
szAttribute = "scale_pivot_y";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z:
|
|
||||||
szAttribute = "scale_pivot_z";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X:
|
|
||||||
szAttribute = "rotate_offset_x";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y:
|
|
||||||
szAttribute = "rotate_offset_y";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z:
|
|
||||||
szAttribute = "rotate_offset_z";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_SCALE_OFFSET_X:
|
|
||||||
szAttribute = "scale_offset_x";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_SCALE_OFFSET_Y:
|
|
||||||
szAttribute = "scale_offset_y";
|
|
||||||
break;
|
|
||||||
case KRNode::KRENGINE_NODE_SCALE_OFFSET_Z:
|
|
||||||
szAttribute = "scale_offset_z";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
e->SetAttribute("attribute", szAttribute);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationAttribute::loadXML(tinyxml2::XMLElement *e)
|
|
||||||
{
|
|
||||||
m_target = NULL;
|
|
||||||
m_curve = NULL;
|
|
||||||
m_curve_name = e->Attribute("curve");
|
|
||||||
m_target_name = e->Attribute("target");
|
|
||||||
|
|
||||||
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
|
|
||||||
|
|
||||||
const char *szAttribute = e->Attribute("attribute");
|
|
||||||
if(strcmp(szAttribute, "none") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
|
|
||||||
} else if(strcmp(szAttribute, "translate_x") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X;
|
|
||||||
} else if(strcmp(szAttribute, "translate_y") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y;
|
|
||||||
} else if(strcmp(szAttribute, "translate_z") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z;
|
|
||||||
} else if(strcmp(szAttribute, "rotate_x") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_X;
|
|
||||||
} else if(strcmp(szAttribute, "rotate_y") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Y;
|
|
||||||
} else if(strcmp(szAttribute, "rotate_z") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Z;
|
|
||||||
} else if(strcmp(szAttribute, "scale_x") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_X;
|
|
||||||
} else if(strcmp(szAttribute, "scale_y") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Y;
|
|
||||||
} else if(strcmp(szAttribute, "scale_z") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Z;
|
|
||||||
} else if(strcmp(szAttribute, "pre_rotate_x") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X;
|
|
||||||
} else if(strcmp(szAttribute, "pre_rotate_y") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y;
|
|
||||||
} else if(strcmp(szAttribute, "pre_rotate_z") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z;
|
|
||||||
} else if(strcmp(szAttribute, "post_rotate_x") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X;
|
|
||||||
} else if(strcmp(szAttribute, "post_rotate_y") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y;
|
|
||||||
} else if(strcmp(szAttribute, "post_rotate_z") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z;
|
|
||||||
} else if(strcmp(szAttribute, "rotate_pivot_x") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X;
|
|
||||||
} else if(strcmp(szAttribute, "rotate_pivot_y") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y;
|
|
||||||
} else if(strcmp(szAttribute, "rotate_pivot_z") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z;
|
|
||||||
} else if(strcmp(szAttribute, "scale_pivot_x") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X;
|
|
||||||
} else if(strcmp(szAttribute, "scale_pivot_y") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y;
|
|
||||||
} else if(strcmp(szAttribute, "scale_pivot_z") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z;
|
|
||||||
} else if(strcmp(szAttribute, "rotate_offset_x") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X;
|
|
||||||
} else if(strcmp(szAttribute, "rotate_offset_y") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y;
|
|
||||||
} else if(strcmp(szAttribute, "rotate_offset_z") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z;
|
|
||||||
} else if(strcmp(szAttribute, "scale_offset_x") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_X;
|
|
||||||
} else if(strcmp(szAttribute, "scale_offset_y") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_Y;
|
|
||||||
} else if(strcmp(szAttribute, "scale_offset_z") == 0) {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_Z;
|
|
||||||
} else {
|
|
||||||
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KRNode::node_attribute_type KRAnimationAttribute::getTargetAttribute() const
|
|
||||||
{
|
|
||||||
return m_node_attribute;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationAttribute::setTargetAttribute(KRNode::node_attribute_type target_attribute)
|
|
||||||
{
|
|
||||||
m_node_attribute = target_attribute;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRAnimationAttribute::getTargetName() const
|
|
||||||
{
|
|
||||||
return m_target_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationAttribute::setTargetName(const std::string &target_name)
|
|
||||||
{
|
|
||||||
m_target_name = target_name;
|
|
||||||
m_target = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRAnimationAttribute::getCurveName() const
|
|
||||||
{
|
|
||||||
return m_curve_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationAttribute::setCurveName(const std::string &curve_name)
|
|
||||||
{
|
|
||||||
m_curve_name = curve_name;
|
|
||||||
m_curve = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRNode *KRAnimationAttribute::getTarget()
|
|
||||||
{
|
|
||||||
if(m_target == NULL) {
|
|
||||||
m_target = getContext().getSceneManager()->getFirstScene()->getRootNode()->find<KRNode>(m_target_name); // FINDME, HACK! - This won't work with multiple scenes in a context; we should move the animations out of KRAnimationManager and attach them to the parent nodes of the animated KRNode's
|
|
||||||
}
|
|
||||||
if(m_target == NULL) {
|
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - Animation attribute could not find object: %s", m_target_name.c_str());
|
|
||||||
}
|
|
||||||
return m_target;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationCurve *KRAnimationAttribute::getCurve()
|
|
||||||
{
|
|
||||||
if(m_curve == NULL) {
|
|
||||||
m_curve = getContext().getAnimationCurveManager()->getAnimationCurve(m_curve_name.c_str());
|
|
||||||
}
|
|
||||||
return m_curve;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationAttribute::deleteCurve()
|
|
||||||
{
|
|
||||||
KRAnimationCurve *curve = getCurve();
|
|
||||||
if(curve) {
|
|
||||||
getContext().getAnimationCurveManager()->deleteAnimationCurve(curve);
|
|
||||||
m_curve = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,240 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAnimationCurve.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "KRAnimationCurve.h"
|
|
||||||
#include "KRDataBlock.h"
|
|
||||||
|
|
||||||
KRAnimationCurve::KRAnimationCurve(KRContext &context, const std::string &name) : KRResource(context, name)
|
|
||||||
{
|
|
||||||
m_pData = new KRDataBlock();
|
|
||||||
m_pData->expand(sizeof(animation_curve_header));
|
|
||||||
m_pData->lock();
|
|
||||||
animation_curve_header *header = (animation_curve_header *)m_pData->getStart();
|
|
||||||
strcpy(header->szTag, "KRCURVE1.0 ");
|
|
||||||
header->frame_rate = 30.0f;
|
|
||||||
header->frame_start = 0;
|
|
||||||
header->frame_count = 0;
|
|
||||||
m_pData->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationCurve::~KRAnimationCurve()
|
|
||||||
{
|
|
||||||
m_pData->unload();
|
|
||||||
delete m_pData;
|
|
||||||
}
|
|
||||||
bool KRAnimationCurve::load(KRDataBlock *data)
|
|
||||||
{
|
|
||||||
m_pData->unload();
|
|
||||||
delete m_pData;
|
|
||||||
m_pData = data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRAnimationCurve::getExtension() {
|
|
||||||
return "kranimationcurve";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAnimationCurve::save(const std::string& path) {
|
|
||||||
return m_pData->save(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAnimationCurve::save(KRDataBlock &data) {
|
|
||||||
data.append(*m_pData);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationCurve *KRAnimationCurve::Load(KRContext &context, const std::string &name, KRDataBlock *data)
|
|
||||||
{
|
|
||||||
KRAnimationCurve *new_animation_curve = new KRAnimationCurve(context, name);
|
|
||||||
if(new_animation_curve->load(data)) {
|
|
||||||
return new_animation_curve;
|
|
||||||
} else {
|
|
||||||
delete new_animation_curve;
|
|
||||||
delete data;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int KRAnimationCurve::getFrameCount()
|
|
||||||
{
|
|
||||||
m_pData->lock();
|
|
||||||
int frame_count = ((animation_curve_header *)m_pData->getStart())->frame_count;
|
|
||||||
m_pData->unlock();
|
|
||||||
|
|
||||||
return frame_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationCurve::setFrameCount(int frame_count)
|
|
||||||
{
|
|
||||||
m_pData->lock();
|
|
||||||
int prev_frame_count = getFrameCount();
|
|
||||||
if(frame_count != prev_frame_count) {
|
|
||||||
float fill_value = 0.0f;
|
|
||||||
if(prev_frame_count > 0) {
|
|
||||||
fill_value = getValue(prev_frame_count - 1);
|
|
||||||
}
|
|
||||||
m_pData->expand(sizeof(animation_curve_header) + sizeof(float) * frame_count - m_pData->getSize());
|
|
||||||
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header));
|
|
||||||
for(int frame_number=prev_frame_count; frame_number < frame_count; frame_number++) {
|
|
||||||
frame_data[frame_number] = fill_value;
|
|
||||||
}
|
|
||||||
((animation_curve_header *)m_pData->getStart())->frame_count = frame_count;
|
|
||||||
}
|
|
||||||
m_pData->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAnimationCurve::getFrameRate()
|
|
||||||
{
|
|
||||||
m_pData->lock();
|
|
||||||
float frame_rate =((animation_curve_header *)m_pData->getStart())->frame_rate;
|
|
||||||
m_pData->unlock();
|
|
||||||
return frame_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationCurve::setFrameRate(float frame_rate)
|
|
||||||
{
|
|
||||||
m_pData->lock();
|
|
||||||
((animation_curve_header *)m_pData->getStart())->frame_rate = frame_rate;
|
|
||||||
m_pData->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
int KRAnimationCurve::getFrameStart()
|
|
||||||
{
|
|
||||||
m_pData->lock();
|
|
||||||
int frame_start = ((animation_curve_header *)m_pData->getStart())->frame_start;
|
|
||||||
m_pData->unlock();
|
|
||||||
return frame_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationCurve::setFrameStart(int frame_number)
|
|
||||||
{
|
|
||||||
m_pData->lock();
|
|
||||||
((animation_curve_header *)m_pData->getStart())->frame_start = frame_number;
|
|
||||||
m_pData->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAnimationCurve::getValue(int frame_number)
|
|
||||||
{
|
|
||||||
m_pData->lock();
|
|
||||||
//printf("frame_number: %i\n", frame_number);
|
|
||||||
int clamped_frame = frame_number - getFrameStart();
|
|
||||||
if(clamped_frame < 0) {
|
|
||||||
clamped_frame = 0;
|
|
||||||
} else if(clamped_frame >= getFrameCount()) {
|
|
||||||
clamped_frame = getFrameCount()-1;
|
|
||||||
}
|
|
||||||
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header));
|
|
||||||
float v = frame_data[clamped_frame];
|
|
||||||
m_pData->unlock();
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationCurve::setValue(int frame_number, float value)
|
|
||||||
{
|
|
||||||
m_pData->lock();
|
|
||||||
int clamped_frame = frame_number - getFrameStart();
|
|
||||||
if(clamped_frame >= 0 && clamped_frame < getFrameCount()) {
|
|
||||||
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header));
|
|
||||||
frame_data[clamped_frame] = value;
|
|
||||||
}
|
|
||||||
m_pData->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAnimationCurve::getValue(float local_time)
|
|
||||||
{
|
|
||||||
// TODO - Need to add interpolation for time values between frames.
|
|
||||||
// Must consider looping animations when determining which two frames to interpolate between.
|
|
||||||
m_pData->lock();
|
|
||||||
float v = getValue((int)(local_time * getFrameRate()));
|
|
||||||
m_pData->unlock();
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAnimationCurve::valueChanges(float start_time, float duration)
|
|
||||||
{
|
|
||||||
m_pData->lock();
|
|
||||||
bool c = valueChanges((int)(start_time * getFrameRate()), (int)(duration * getFrameRate()));
|
|
||||||
m_pData->unlock();
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAnimationCurve::valueChanges(int start_frame, int frame_count)
|
|
||||||
{
|
|
||||||
m_pData->lock();
|
|
||||||
float first_value = getValue(start_frame);
|
|
||||||
|
|
||||||
bool change_found = false;
|
|
||||||
|
|
||||||
// Range of frames is not inclusive of last frame
|
|
||||||
for(int frame_number = start_frame + 1; frame_number < start_frame + frame_count && !change_found; frame_number++) {
|
|
||||||
if(getValue(frame_number) != first_value) {
|
|
||||||
change_found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pData->unlock();
|
|
||||||
return change_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationCurve *KRAnimationCurve::split(const std::string &name, float start_time, float duration)
|
|
||||||
{
|
|
||||||
return split(name, (int)(start_time * getFrameRate()), (int)(duration * getFrameRate()));
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationCurve *KRAnimationCurve::split(const std::string &name, int start_frame, int frame_count)
|
|
||||||
{
|
|
||||||
KRAnimationCurve *new_curve = new KRAnimationCurve(getContext(), name);
|
|
||||||
|
|
||||||
new_curve->setFrameRate(getFrameRate());
|
|
||||||
new_curve->setFrameStart(start_frame);
|
|
||||||
new_curve->setFrameCount(frame_count);
|
|
||||||
new_curve->m_pData->lock();
|
|
||||||
|
|
||||||
// Range of frames is not inclusive of last frame
|
|
||||||
for(int frame_number = start_frame; frame_number < start_frame + frame_count; frame_number++) {
|
|
||||||
new_curve->setValue(frame_number, getValue(frame_number)); // TODO - MEMCPY here?
|
|
||||||
}
|
|
||||||
new_curve->m_pData->unlock();
|
|
||||||
|
|
||||||
getContext().getAnimationCurveManager()->addAnimationCurve(new_curve);
|
|
||||||
return new_curve;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationCurve::_lockData()
|
|
||||||
{
|
|
||||||
m_pData->lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationCurve::_unlockData()
|
|
||||||
{
|
|
||||||
m_pData->unlock();
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAnimationCurve.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRANIMATIONCURVE_H
|
|
||||||
#define KRANIMATIONCURVE_H
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
#include "KRContextObject.h"
|
|
||||||
#include "KRDataBlock.h"
|
|
||||||
#include "KRResource.h"
|
|
||||||
|
|
||||||
class KRAnimationCurve : public KRResource {
|
|
||||||
|
|
||||||
public:
|
|
||||||
KRAnimationCurve(KRContext &context, const std::string &name);
|
|
||||||
virtual ~KRAnimationCurve();
|
|
||||||
|
|
||||||
virtual std::string getExtension();
|
|
||||||
virtual bool save(const std::string& path);
|
|
||||||
virtual bool save(KRDataBlock &data);
|
|
||||||
virtual bool load(KRDataBlock *data);
|
|
||||||
|
|
||||||
float getFrameRate();
|
|
||||||
void setFrameRate(float frame_rate);
|
|
||||||
int getFrameStart();
|
|
||||||
void setFrameStart(int frame_number);
|
|
||||||
int getFrameCount();
|
|
||||||
void setFrameCount(int frame_count);
|
|
||||||
float getValue(float local_time);
|
|
||||||
float getValue(int frame_number);
|
|
||||||
void setValue(int frame_number, float value);
|
|
||||||
|
|
||||||
|
|
||||||
static KRAnimationCurve *Load(KRContext &context, const std::string &name, KRDataBlock *data);
|
|
||||||
|
|
||||||
bool valueChanges(float start_time, float duration);
|
|
||||||
bool valueChanges(int start_frame, int frame_count);
|
|
||||||
|
|
||||||
KRAnimationCurve *split(const std::string &name, float start_time, float duration);
|
|
||||||
KRAnimationCurve *split(const std::string &name, int start_frame, int frame_count);
|
|
||||||
|
|
||||||
void _lockData();
|
|
||||||
void _unlockData();
|
|
||||||
|
|
||||||
private:
|
|
||||||
KRDataBlock *m_pData;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char szTag[16];
|
|
||||||
float frame_rate;
|
|
||||||
int32_t frame_start;
|
|
||||||
int32_t frame_count;
|
|
||||||
} animation_curve_header;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAnimationCurveManager.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRAnimationCurveManager.h"
|
|
||||||
#include "KRAnimationCurve.h"
|
|
||||||
|
|
||||||
KRAnimationCurveManager::KRAnimationCurveManager(KRContext &context) : KRContextObject(context)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationCurveManager::~KRAnimationCurveManager() {
|
|
||||||
for(unordered_map<std::string, KRAnimationCurve *>::iterator itr = m_animationCurves.begin(); itr != m_animationCurves.end(); ++itr){
|
|
||||||
delete (*itr).second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationCurveManager::deleteAnimationCurve(KRAnimationCurve *curve) {
|
|
||||||
m_animationCurves.erase(curve->getName());
|
|
||||||
delete curve;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationCurve *KRAnimationCurveManager::loadAnimationCurve(const std::string &name, KRDataBlock *data) {
|
|
||||||
KRAnimationCurve *pAnimationCurve = KRAnimationCurve::Load(*m_pContext, name, data);
|
|
||||||
if(pAnimationCurve) {
|
|
||||||
m_animationCurves[name] = pAnimationCurve;
|
|
||||||
}
|
|
||||||
return pAnimationCurve;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationCurve *KRAnimationCurveManager::getAnimationCurve(const std::string &name) {
|
|
||||||
unordered_map<std::string, KRAnimationCurve *>::iterator itr = m_animationCurves.find(name);
|
|
||||||
if(itr == m_animationCurves.end()) {
|
|
||||||
return NULL; // Not found
|
|
||||||
} else {
|
|
||||||
return (*itr).second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unordered_map<std::string, KRAnimationCurve *> &KRAnimationCurveManager::getAnimationCurves() {
|
|
||||||
return m_animationCurves;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationCurveManager::addAnimationCurve(KRAnimationCurve *new_animation_curve)
|
|
||||||
{
|
|
||||||
assert(new_animation_curve != NULL);
|
|
||||||
m_animationCurves[new_animation_curve->getName()] = new_animation_curve;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAnimationLayer.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRAnimationLayer.h"
|
|
||||||
|
|
||||||
KRAnimationLayer::KRAnimationLayer(KRContext &context) : KRContextObject(context)
|
|
||||||
{
|
|
||||||
m_name = "";
|
|
||||||
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE;
|
|
||||||
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER;
|
|
||||||
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationLayer::~KRAnimationLayer()
|
|
||||||
{
|
|
||||||
for(std::vector<KRAnimationAttribute *>::iterator itr = m_attributes.begin(); itr != m_attributes.end(); ++itr){
|
|
||||||
delete (*itr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRAnimationLayer::getName() const
|
|
||||||
{
|
|
||||||
return m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationLayer::setName(const std::string &name)
|
|
||||||
{
|
|
||||||
m_name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRAnimationLayer::saveXML( tinyxml2::XMLNode *parent)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLDocument *doc = parent->GetDocument();
|
|
||||||
tinyxml2::XMLElement *e = doc->NewElement("layer");
|
|
||||||
tinyxml2::XMLNode *n = parent->InsertEndChild(e);
|
|
||||||
e->SetAttribute("name", m_name.c_str());
|
|
||||||
e->SetAttribute("weight", m_weight);
|
|
||||||
|
|
||||||
switch(m_blend_mode) {
|
|
||||||
case KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE:
|
|
||||||
e->SetAttribute("blend_mode", "additive");
|
|
||||||
break;
|
|
||||||
case KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE:
|
|
||||||
e->SetAttribute("blend_mode", "override");
|
|
||||||
break;
|
|
||||||
case KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH:
|
|
||||||
e->SetAttribute("blend_mode", "override_passthrough");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(m_rotation_accumulation_mode) {
|
|
||||||
case KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL:
|
|
||||||
e->SetAttribute("rotation_accumulation_mode", "by_channel");
|
|
||||||
break;
|
|
||||||
case KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER:
|
|
||||||
e->SetAttribute("rotation_accumulation_mode", "by_layer");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(m_scale_accumulation_mode) {
|
|
||||||
case KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE:
|
|
||||||
e->SetAttribute("scale_accumulation_mode", "additive");
|
|
||||||
break;
|
|
||||||
case KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY:
|
|
||||||
e->SetAttribute("scale_accumulation_mode", "multiply");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(std::vector<KRAnimationAttribute *>::iterator itr = m_attributes.begin(); itr != m_attributes.end(); ++itr){
|
|
||||||
(*itr)->saveXML(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationLayer::loadXML(tinyxml2::XMLElement *e)
|
|
||||||
{
|
|
||||||
m_name = e->Attribute("name");
|
|
||||||
if(e->QueryFloatAttribute("weight", &m_weight) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_weight = 1.0f; // default
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *szBlendMode = e->Attribute("blend_mode");
|
|
||||||
if(strcmp(szBlendMode, "additive") == 0) {
|
|
||||||
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE;
|
|
||||||
} else if(strcmp(szBlendMode, "override") == 0) {
|
|
||||||
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE;
|
|
||||||
} else if(strcmp(szBlendMode, "override_passthrough") == 0) {
|
|
||||||
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH;
|
|
||||||
} else {
|
|
||||||
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE; // default
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *szRotationAccumulationMode = e->Attribute("rotation_accumulation_mode");
|
|
||||||
if(strcmp(szRotationAccumulationMode, "by_channel") == 0) {
|
|
||||||
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL;
|
|
||||||
} else if(strcmp(szRotationAccumulationMode, "by_layer") == 0) {
|
|
||||||
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER;
|
|
||||||
} else {
|
|
||||||
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER; // default
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *szScaleAccumulationMode = e->Attribute("scale_accumulation_mode");
|
|
||||||
if(strcmp(szScaleAccumulationMode, "additive") == 0) {
|
|
||||||
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE;
|
|
||||||
} else if(strcmp(szScaleAccumulationMode, "multiply") == 0) {
|
|
||||||
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY;
|
|
||||||
} else {
|
|
||||||
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY; // default
|
|
||||||
}
|
|
||||||
|
|
||||||
for(tinyxml2::XMLElement *child_element=e->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) {
|
|
||||||
if(strcmp(child_element->Name(), "attribute") == 0) {
|
|
||||||
KRAnimationAttribute *new_attribute = new KRAnimationAttribute(getContext());
|
|
||||||
new_attribute->loadXML(child_element);
|
|
||||||
m_attributes.push_back(new_attribute);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAnimationLayer::getWeight() const
|
|
||||||
{
|
|
||||||
return m_weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationLayer::setWeight(float weight)
|
|
||||||
{
|
|
||||||
m_weight = weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KRAnimationLayer::blend_mode_t KRAnimationLayer::getBlendMode() const
|
|
||||||
{
|
|
||||||
return m_blend_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationLayer::setBlendMode(const KRAnimationLayer::blend_mode_t &blend_mode)
|
|
||||||
{
|
|
||||||
m_blend_mode = blend_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationLayer::rotation_accumulation_mode_t KRAnimationLayer::getRotationAccumulationMode() const
|
|
||||||
{
|
|
||||||
return m_rotation_accumulation_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationLayer::setRotationAccumulationMode(const KRAnimationLayer::rotation_accumulation_mode_t &rotation_accumulation_mode)
|
|
||||||
{
|
|
||||||
m_rotation_accumulation_mode = rotation_accumulation_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationLayer::scale_accumulation_mode_t KRAnimationLayer::getScaleAccumulationMode() const
|
|
||||||
{
|
|
||||||
return m_scale_accumulation_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationLayer::setScaleAccumulationMode(const KRAnimationLayer::scale_accumulation_mode_t &scale_accumulation_mode)
|
|
||||||
{
|
|
||||||
m_scale_accumulation_mode = scale_accumulation_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationLayer::addAttribute(KRAnimationAttribute *attribute)
|
|
||||||
{
|
|
||||||
m_attributes.push_back(attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<KRAnimationAttribute *> &KRAnimationLayer::getAttributes()
|
|
||||||
{
|
|
||||||
return m_attributes;
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAnimationLayer.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRANIMATIONLAYER_H
|
|
||||||
#define KRANIMATIONLAYER_H
|
|
||||||
|
|
||||||
#include "KRContextObject.h"
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
#include "KRAnimationAttribute.h"
|
|
||||||
|
|
||||||
namespace tinyxml2 {
|
|
||||||
class XMLNode;
|
|
||||||
class XMLAttribute;
|
|
||||||
}
|
|
||||||
|
|
||||||
class KRAnimationLayer : public KRContextObject {
|
|
||||||
public:
|
|
||||||
KRAnimationLayer(KRContext &context);
|
|
||||||
~KRAnimationLayer();
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
|
||||||
void loadXML(tinyxml2::XMLElement *e);
|
|
||||||
|
|
||||||
std::string getName() const;
|
|
||||||
void setName(const std::string &name);
|
|
||||||
|
|
||||||
float getWeight() const;
|
|
||||||
void setWeight(float weight);
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE,
|
|
||||||
KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE,
|
|
||||||
KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH
|
|
||||||
} blend_mode_t;
|
|
||||||
|
|
||||||
blend_mode_t getBlendMode() const;
|
|
||||||
void setBlendMode(const blend_mode_t &blend_mode);
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER,
|
|
||||||
KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL
|
|
||||||
} rotation_accumulation_mode_t;
|
|
||||||
|
|
||||||
rotation_accumulation_mode_t getRotationAccumulationMode() const;
|
|
||||||
void setRotationAccumulationMode(const rotation_accumulation_mode_t &rotation_accumulation_mode);
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY,
|
|
||||||
KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE
|
|
||||||
} scale_accumulation_mode_t;
|
|
||||||
|
|
||||||
scale_accumulation_mode_t getScaleAccumulationMode() const;
|
|
||||||
void setScaleAccumulationMode(const scale_accumulation_mode_t &scale_accumulation_mode);
|
|
||||||
|
|
||||||
void addAttribute(KRAnimationAttribute *attribute);
|
|
||||||
std::vector<KRAnimationAttribute *> &getAttributes();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_name;
|
|
||||||
float m_weight;
|
|
||||||
blend_mode_t m_blend_mode;
|
|
||||||
rotation_accumulation_mode_t m_rotation_accumulation_mode;
|
|
||||||
scale_accumulation_mode_t m_scale_accumulation_mode;
|
|
||||||
|
|
||||||
std::vector<KRAnimationAttribute *> m_attributes;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAnimationManager.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRAnimationManager.h"
|
|
||||||
#include "KRAnimation.h"
|
|
||||||
|
|
||||||
KRAnimationManager::KRAnimationManager(KRContext &context) : KRContextObject(context)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimationManager::~KRAnimationManager() {
|
|
||||||
for(std::set<KRAnimation *>::iterator itr = m_activeAnimations.begin(); itr != m_activeAnimations.end(); itr++) {
|
|
||||||
KRAnimation *animation = *itr;
|
|
||||||
animation->_unlockData();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(unordered_map<std::string, KRAnimation *>::iterator itr = m_animations.begin(); itr != m_animations.end(); ++itr){
|
|
||||||
delete (*itr).second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationManager::startFrame(float deltaTime)
|
|
||||||
{
|
|
||||||
for(std::set<KRAnimation *>::iterator itr = m_animationsToUpdate.begin(); itr != m_animationsToUpdate.end(); itr++) {
|
|
||||||
KRAnimation *animation = *itr;
|
|
||||||
std::set<KRAnimation *>::iterator active_animations_itr = m_activeAnimations.find(animation);
|
|
||||||
if(animation->isPlaying()) {
|
|
||||||
// Add playing animations to the active animations list
|
|
||||||
if(active_animations_itr == m_activeAnimations.end()) {
|
|
||||||
m_activeAnimations.insert(animation);
|
|
||||||
animation->_lockData();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Remove stopped animations from the active animations list
|
|
||||||
if(active_animations_itr != m_activeAnimations.end()) {
|
|
||||||
m_activeAnimations.erase(active_animations_itr);
|
|
||||||
animation->_unlockData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_animationsToUpdate.clear();
|
|
||||||
|
|
||||||
for(std::set<KRAnimation *>::iterator active_animations_itr = m_activeAnimations.begin(); active_animations_itr != m_activeAnimations.end(); active_animations_itr++) {
|
|
||||||
KRAnimation *animation = *active_animations_itr;
|
|
||||||
animation->update(deltaTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationManager::endFrame(float deltaTime)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KRAnimation *KRAnimationManager::loadAnimation(const char *szName, KRDataBlock *data) {
|
|
||||||
KRAnimation *pAnimation = KRAnimation::Load(*m_pContext, szName, data);
|
|
||||||
addAnimation(pAnimation);
|
|
||||||
return pAnimation;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAnimation *KRAnimationManager::getAnimation(const char *szName) {
|
|
||||||
return m_animations[szName];
|
|
||||||
}
|
|
||||||
|
|
||||||
unordered_map<std::string, KRAnimation *> &KRAnimationManager::getAnimations() {
|
|
||||||
return m_animations;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationManager::addAnimation(KRAnimation *new_animation)
|
|
||||||
{
|
|
||||||
m_animations[new_animation->getName()] = new_animation;
|
|
||||||
updateActiveAnimations(new_animation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationManager::updateActiveAnimations(KRAnimation *animation)
|
|
||||||
{
|
|
||||||
m_animationsToUpdate.insert(animation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAnimationManager::deleteAnimation(KRAnimation *animation, bool delete_curves)
|
|
||||||
{
|
|
||||||
if(delete_curves)
|
|
||||||
{
|
|
||||||
animation->deleteCurves();
|
|
||||||
}
|
|
||||||
m_animations.erase(animation->getName());
|
|
||||||
delete animation;
|
|
||||||
}
|
|
||||||
@@ -1,56 +1,79 @@
|
|||||||
//
|
//
|
||||||
// KRAudioBuffer.cpp
|
// KRAudioBuffer.cpp
|
||||||
// KREngine
|
// Kraken Engine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2013-01-04.
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRAudioBuffer.h"
|
#include "KRAudioBuffer.h"
|
||||||
#include "KRAudioManager.h"
|
#include "resources/audio/KRAudioManager.h"
|
||||||
|
|
||||||
|
|
||||||
KRAudioBuffer::KRAudioBuffer(KRAudioManager *manager, KRAudioSample *sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample *, int, void *))
|
KRAudioBuffer::KRAudioBuffer(KRAudioManager* manager, KRAudioSample* sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample*, int, void*))
|
||||||
{
|
{
|
||||||
m_pSoundManager = manager;
|
m_pSoundManager = manager;
|
||||||
m_frameCount = frameCount;
|
m_frameCount = frameCount;
|
||||||
m_frameRate = frameRate;
|
m_frameRate = frameRate;
|
||||||
m_bytesPerFrame = bytesPerFrame;
|
m_bytesPerFrame = bytesPerFrame;
|
||||||
m_pData = NULL;
|
m_pData = NULL;
|
||||||
m_audioSample = sound;
|
m_audioSample = sound;
|
||||||
m_index = index;
|
m_index = index;
|
||||||
|
|
||||||
m_pSoundManager->makeCurrentContext();
|
m_pSoundManager->makeCurrentContext();
|
||||||
m_pData = m_pSoundManager->getBufferData(m_frameCount * m_bytesPerFrame);
|
m_pData = m_pSoundManager->getBufferData(m_frameCount * m_bytesPerFrame);
|
||||||
fn_populate(sound, index, m_pData->getStart());
|
fn_populate(sound, index, m_pData->getStart());
|
||||||
}
|
}
|
||||||
|
|
||||||
KRAudioBuffer::~KRAudioBuffer()
|
KRAudioBuffer::~KRAudioBuffer()
|
||||||
{
|
{
|
||||||
m_pSoundManager->recycleBufferData(m_pData);
|
m_pSoundManager->recycleBufferData(m_pData);
|
||||||
}
|
}
|
||||||
|
|
||||||
KRAudioSample *KRAudioBuffer::getAudioSample()
|
KRAudioSample* KRAudioBuffer::getAudioSample()
|
||||||
{
|
{
|
||||||
return m_audioSample;
|
return m_audioSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
int KRAudioBuffer::getFrameCount()
|
int KRAudioBuffer::getFrameCount()
|
||||||
{
|
{
|
||||||
return m_frameCount;
|
return m_frameCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int KRAudioBuffer::getFrameRate()
|
int KRAudioBuffer::getFrameRate()
|
||||||
{
|
{
|
||||||
return m_frameRate;
|
return m_frameRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
signed short *KRAudioBuffer::getFrameData()
|
signed short* KRAudioBuffer::getFrameData()
|
||||||
{
|
{
|
||||||
return (signed short *)m_pData->getStart();
|
return (signed short*)m_pData->getStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
int KRAudioBuffer::getIndex()
|
int KRAudioBuffer::getIndex()
|
||||||
{
|
{
|
||||||
return m_index;
|
return m_index;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,38 @@
|
|||||||
//
|
//
|
||||||
// KRAudioBuffer.h
|
// KRAudioBuffer.h
|
||||||
// KREngine
|
// Kraken Engine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2013-01-04.
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef KRAUDIO_BUFFER_H
|
#pragma once
|
||||||
#define KRAUDIO_BUFFER_H
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
#include "KRDataBlock.h"
|
#include "block.h"
|
||||||
|
|
||||||
class KRAudioManager;
|
class KRAudioManager;
|
||||||
class KRAudioSample;
|
class KRAudioSample;
|
||||||
@@ -18,25 +40,23 @@ class KRAudioSample;
|
|||||||
class KRAudioBuffer
|
class KRAudioBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
KRAudioBuffer(KRAudioManager *manager, KRAudioSample *sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample *, int, void *));
|
KRAudioBuffer(KRAudioManager* manager, KRAudioSample* sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample*, int, void*));
|
||||||
~KRAudioBuffer();
|
~KRAudioBuffer();
|
||||||
|
|
||||||
int getFrameCount();
|
|
||||||
int getFrameRate();
|
|
||||||
signed short *getFrameData();
|
|
||||||
|
|
||||||
KRAudioSample *getAudioSample();
|
|
||||||
int getIndex();
|
|
||||||
private:
|
|
||||||
KRAudioManager *m_pSoundManager;
|
|
||||||
|
|
||||||
int m_index;
|
|
||||||
int m_frameCount;
|
|
||||||
int m_frameRate;
|
|
||||||
int m_bytesPerFrame;
|
|
||||||
KRDataBlock *m_pData;
|
|
||||||
|
|
||||||
KRAudioSample *m_audioSample;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined(KRAUDIO_BUFFER_H) */
|
int getFrameCount();
|
||||||
|
int getFrameRate();
|
||||||
|
signed short* getFrameData();
|
||||||
|
|
||||||
|
KRAudioSample* getAudioSample();
|
||||||
|
int getIndex();
|
||||||
|
private:
|
||||||
|
KRAudioManager* m_pSoundManager;
|
||||||
|
|
||||||
|
int m_index;
|
||||||
|
int m_frameCount;
|
||||||
|
int m_frameRate;
|
||||||
|
int m_bytesPerFrame;
|
||||||
|
mimir::Block* m_pData;
|
||||||
|
|
||||||
|
KRAudioSample* m_audioSample;
|
||||||
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,252 +0,0 @@
|
|||||||
//
|
|
||||||
// FileManager.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRAUDIO_MANAGER_H
|
|
||||||
#define KRAUDIO_MANAGER_H
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#include "KRContextObject.h"
|
|
||||||
#include "KRDataBlock.h"
|
|
||||||
#include "KRAudioSource.h"
|
|
||||||
#include "KRDSP.h"
|
|
||||||
|
|
||||||
const int KRENGINE_AUDIO_MAX_POOL_SIZE = 60; //32;
|
|
||||||
// for Circa we play a maximum of 11 mono audio streams at once + cross fading with ambient
|
|
||||||
// so we could safely say a maximum of 12 or 13 streams, which would be 39 buffers
|
|
||||||
// do the WAV files for the reverb use the same buffer pool ???
|
|
||||||
|
|
||||||
const int KRENGINE_AUDIO_MAX_BUFFER_SIZE = 5120; // in bytes
|
|
||||||
// this is the buffer for our decoded audio (not the source file data)
|
|
||||||
// it should be greater then 1152 samples (the size of an mp3 frame in samples)
|
|
||||||
// so it should be greater then 2304 bytes and also a multiple of 128 samples (to make
|
|
||||||
// the data flow efficient) but it shouldn't be too large or it will cause
|
|
||||||
// the render loop to stall out decoding large chunks of mp3 data.
|
|
||||||
// 2560 bytes would be the smallest size for mono sources, and 5120 would be smallest for stereo.
|
|
||||||
|
|
||||||
const int KRENGINE_AUDIO_BUFFERS_PER_SOURCE = 3;
|
|
||||||
|
|
||||||
const int KRENGINE_AUDIO_BLOCK_LOG2N = 7; // 2 ^ KRENGINE_AUDIO_BLOCK_LOG2N = KRENGINE_AUDIO_BLOCK_LENGTH
|
|
||||||
// 7 is 128 .. NOTE: the hrtf code uses magic numbers everywhere and is hardcoded to 128 samples per frame
|
|
||||||
|
|
||||||
const int KRENGINE_AUDIO_BLOCK_LENGTH = 1 << KRENGINE_AUDIO_BLOCK_LOG2N;
|
|
||||||
// Length of one block to process. Determines the latency of the audio system and sets size for FFT's used in HRTF convolution
|
|
||||||
// the AUGraph works in 1024 sample chunks. At 128 we are making 8 consecutive calls to the renderBlock method for each
|
|
||||||
// render initiated by the AUGraph.
|
|
||||||
|
|
||||||
const int KRENGINE_REVERB_MAX_FFT_LOG2 = 15;
|
|
||||||
const int KRENGINE_REVERB_WORKSPACE_SIZE = 1 << KRENGINE_REVERB_MAX_FFT_LOG2;
|
|
||||||
|
|
||||||
const float KRENGINE_AUDIO_CUTOFF = 0.02f; // Cutoff gain level, to cull out processing of very quiet sounds
|
|
||||||
|
|
||||||
const int KRENGINE_REVERB_MAX_SAMPLES = 128000; // 2.9 seconds //435200; // At least 10s reverb impulse response length, divisible by KRENGINE_AUDIO_BLOCK_LENGTH
|
|
||||||
const int KRENGINE_MAX_REVERB_IMPULSE_MIX = 8; // Maximum number of impulse response filters that can be mixed simultaneously
|
|
||||||
const int KRENGINE_MAX_OUTPUT_CHANNELS = 2;
|
|
||||||
|
|
||||||
const int KRENGINE_MAX_ACTIVE_SOURCES = 16;
|
|
||||||
const int KRENGINE_AUDIO_ANTICLICK_SAMPLES = 64;
|
|
||||||
|
|
||||||
|
|
||||||
class KRAmbientZone;
|
|
||||||
class KRReverbZone;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
float weight;
|
|
||||||
KRAmbientZone *ambient_zone;
|
|
||||||
KRAudioSample *ambient_sample;
|
|
||||||
} siren_ambient_zone_weight_info;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
float weight;
|
|
||||||
KRReverbZone *reverb_zone;
|
|
||||||
KRAudioSample *reverb_sample;
|
|
||||||
} siren_reverb_zone_weight_info;
|
|
||||||
|
|
||||||
class KRAudioManager : public KRContextObject {
|
|
||||||
public:
|
|
||||||
KRAudioManager(KRContext &context);
|
|
||||||
virtual ~KRAudioManager();
|
|
||||||
|
|
||||||
unordered_map<std::string, KRAudioSample *> &getSounds();
|
|
||||||
|
|
||||||
void add(KRAudioSample *Sound);
|
|
||||||
|
|
||||||
KRAudioSample *load(const std::string &name, const std::string &extension, KRDataBlock *data);
|
|
||||||
KRAudioSample *get(const std::string &name);
|
|
||||||
|
|
||||||
// Listener position and orientation
|
|
||||||
KRScene *getListenerScene();
|
|
||||||
void setListenerScene(KRScene *scene);
|
|
||||||
void setListenerOrientation(const Vector3 &position, const Vector3 &forward, const Vector3 &up);
|
|
||||||
void setListenerOrientationFromModelMatrix(const Matrix4 &modelMatrix);
|
|
||||||
Vector3 &getListenerForward();
|
|
||||||
Vector3 &getListenerPosition();
|
|
||||||
Vector3 &getListenerUp();
|
|
||||||
|
|
||||||
|
|
||||||
// Global audio gain / attenuation
|
|
||||||
float getGlobalGain();
|
|
||||||
void setGlobalGain(float gain);
|
|
||||||
float getGlobalReverbSendLevel();
|
|
||||||
void setGlobalReverbSendLevel(float send_level);
|
|
||||||
float getGlobalAmbientGain();
|
|
||||||
void setGlobalAmbientGain(float gain);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void makeCurrentContext();
|
|
||||||
|
|
||||||
KRDataBlock *getBufferData(int size);
|
|
||||||
void recycleBufferData(KRDataBlock *data);
|
|
||||||
|
|
||||||
void activateAudioSource(KRAudioSource *audioSource);
|
|
||||||
void deactivateAudioSource(KRAudioSource *audioSource);
|
|
||||||
|
|
||||||
__int64_t getAudioFrame();
|
|
||||||
|
|
||||||
KRAudioBuffer *getBuffer(KRAudioSample &audio_sample, int buffer_index);
|
|
||||||
|
|
||||||
static void mute(bool onNotOff);
|
|
||||||
void goToSleep();
|
|
||||||
|
|
||||||
void startFrame(float deltaTime);
|
|
||||||
|
|
||||||
bool getEnableAudio();
|
|
||||||
void setEnableAudio(bool enable);
|
|
||||||
|
|
||||||
bool getEnableHRTF();
|
|
||||||
void setEnableHRTF(bool enable);
|
|
||||||
|
|
||||||
bool getEnableReverb();
|
|
||||||
void setEnableReverb(bool enable);
|
|
||||||
|
|
||||||
float getReverbMaxLength();
|
|
||||||
void setReverbMaxLength(float max_length);
|
|
||||||
|
|
||||||
void _registerOpenAudioSample(KRAudioSample *audioSample);
|
|
||||||
void _registerCloseAudioSample(KRAudioSample *audioSample);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_enable_audio;
|
|
||||||
bool m_enable_hrtf;
|
|
||||||
bool m_enable_reverb;
|
|
||||||
float m_reverb_max_length;
|
|
||||||
|
|
||||||
KRScene *m_listener_scene; // For now, only one scene is allowed to have active audio at once
|
|
||||||
|
|
||||||
float m_global_reverb_send_level;
|
|
||||||
float m_global_ambient_gain;
|
|
||||||
float m_global_gain;
|
|
||||||
|
|
||||||
Vector3 m_listener_position;
|
|
||||||
Vector3 m_listener_forward;
|
|
||||||
Vector3 m_listener_up;
|
|
||||||
|
|
||||||
unordered_map<std::string, KRAudioSample *> m_sounds;
|
|
||||||
|
|
||||||
std::vector<KRDataBlock *> m_bufferPoolIdle;
|
|
||||||
|
|
||||||
std::vector<KRAudioBuffer *> m_bufferCache;
|
|
||||||
|
|
||||||
std::set<KRAudioSource *> m_activeAudioSources;
|
|
||||||
|
|
||||||
std::set<KRAudioSample *> m_openAudioSamples;
|
|
||||||
|
|
||||||
void initAudio();
|
|
||||||
void initHRTF();
|
|
||||||
|
|
||||||
void cleanupAudio();
|
|
||||||
|
|
||||||
bool m_initialized;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// Apple Core Audio
|
|
||||||
AUGraph m_auGraph;
|
|
||||||
AudioUnit m_auMixer;
|
|
||||||
|
|
||||||
static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData);
|
|
||||||
void renderAudio(UInt32 inNumberFrames, AudioBufferList *ioData);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
KRDSP::FFTWorkspace m_fft_setup[KRENGINE_REVERB_MAX_FFT_LOG2 - KRENGINE_AUDIO_BLOCK_LOG2N + 1];
|
|
||||||
|
|
||||||
__int64_t m_audio_frame; // Number of audio frames processed since the start of the application
|
|
||||||
|
|
||||||
float *m_reverb_input_samples; // Circular-buffered reverb input, single channel
|
|
||||||
int m_reverb_input_next_sample; // Pointer to next sample in reverb buffer
|
|
||||||
int m_reverb_sequence;
|
|
||||||
|
|
||||||
KRAudioSample *m_reverb_impulse_responses[KRENGINE_MAX_REVERB_IMPULSE_MIX];
|
|
||||||
float m_reverb_impulse_responses_weight[KRENGINE_MAX_REVERB_IMPULSE_MIX];
|
|
||||||
|
|
||||||
float *m_output_accumulation; // Interleaved output accumulation buffer
|
|
||||||
int m_output_accumulation_block_start;
|
|
||||||
int m_output_sample;
|
|
||||||
|
|
||||||
float *m_workspace_data;
|
|
||||||
KRDSP::SplitComplex m_workspace[3];
|
|
||||||
|
|
||||||
float *getBlockAddress(int block_offset);
|
|
||||||
void renderBlock();
|
|
||||||
void renderReverb();
|
|
||||||
void renderAmbient();
|
|
||||||
void renderHRTF();
|
|
||||||
void renderITD();
|
|
||||||
void renderReverbImpulseResponse(int impulse_response_offset, int frame_count_log2);
|
|
||||||
void renderLimiter();
|
|
||||||
|
|
||||||
std::vector<Vector2> m_hrtf_sample_locations;
|
|
||||||
float *m_hrtf_data;
|
|
||||||
unordered_map<Vector2, KRDSP::SplitComplex> m_hrtf_spectral[2];
|
|
||||||
|
|
||||||
Vector2 getNearestHRTFSample(const Vector2 &dir);
|
|
||||||
void getHRTFMix(const Vector2 &dir, Vector2 &hrtf1, Vector2 &hrtf2, Vector2 &hrtf3, Vector2 &hrtf4, float &mix1, float &mix2, float &mix3, float &mix4);
|
|
||||||
KRAudioSample *getHRTFSample(const Vector2 &hrtf_dir);
|
|
||||||
KRDSP::SplitComplex getHRTFSpectral(const Vector2 &hrtf_dir, const int channel);
|
|
||||||
|
|
||||||
unordered_map<std::string, siren_ambient_zone_weight_info> m_ambient_zone_weights;
|
|
||||||
float m_ambient_zone_total_weight = 0.0f; // For normalizing zone weights
|
|
||||||
|
|
||||||
unordered_map<std::string, siren_reverb_zone_weight_info> m_reverb_zone_weights;
|
|
||||||
float m_reverb_zone_total_weight = 0.0f; // For normalizing zone weights
|
|
||||||
|
|
||||||
boost::signals2::mutex m_mutex;
|
|
||||||
#ifdef __APPLE__
|
|
||||||
mach_timebase_info_data_t m_timebase_info;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
unordered_multimap<Vector2, std::pair<KRAudioSource *, std::pair<float, float> > > m_mapped_sources, m_prev_mapped_sources;
|
|
||||||
bool m_anticlick_block;
|
|
||||||
bool m_high_quality_hrtf; // If true, 4 HRTF samples will be interpolated; if false, the nearest HRTF sample will be used without interpolation
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined(KRAUDIO_MANAGER_H) */
|
|
||||||
@@ -1,393 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAudioSample.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRAudioSample.h"
|
|
||||||
#include "KRAudioManager.h"
|
|
||||||
#include "KRDataBlock.h"
|
|
||||||
#include "KRAudioBuffer.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "KRDSP.h"
|
|
||||||
|
|
||||||
KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension) : KRResource(context, name)
|
|
||||||
{
|
|
||||||
m_pData = new KRDataBlock();
|
|
||||||
m_extension = extension;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// Apple Audio Toolbox
|
|
||||||
m_audio_file_id = 0;
|
|
||||||
m_fileRef = NULL;
|
|
||||||
#endif
|
|
||||||
m_totalFrames = 0;
|
|
||||||
m_bytesPerFrame = 0;
|
|
||||||
m_frameRate = 0;
|
|
||||||
m_bufferCount = 0;
|
|
||||||
|
|
||||||
m_last_frame_used = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data) : KRResource(context, name)
|
|
||||||
{
|
|
||||||
m_pData = data;
|
|
||||||
m_extension = extension;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// Apple Audio Toolbox
|
|
||||||
m_audio_file_id = 0;
|
|
||||||
m_fileRef = NULL;
|
|
||||||
#endif
|
|
||||||
m_totalFrames = 0;
|
|
||||||
m_bytesPerFrame = 0;
|
|
||||||
m_frameRate = 0;
|
|
||||||
m_bufferCount = 0;
|
|
||||||
|
|
||||||
m_last_frame_used = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAudioSample::~KRAudioSample()
|
|
||||||
{
|
|
||||||
closeFile();
|
|
||||||
delete m_pData;
|
|
||||||
}
|
|
||||||
|
|
||||||
int KRAudioSample::getChannelCount()
|
|
||||||
{
|
|
||||||
loadInfo();
|
|
||||||
return m_channelsPerFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
int KRAudioSample::getFrameCount()
|
|
||||||
{
|
|
||||||
loadInfo();
|
|
||||||
//return (int)((__int64_t)m_totalFrames * (__int64_t)frame_rate / (__int64_t)m_frameRate);
|
|
||||||
return m_totalFrames;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAudioSample::sample(int frame_offset, int frame_rate, int channel)
|
|
||||||
{
|
|
||||||
loadInfo();
|
|
||||||
|
|
||||||
int c = KRMIN(channel, m_channelsPerFrame - 1);
|
|
||||||
|
|
||||||
if(frame_offset < 0) {
|
|
||||||
return 0.0f; // Past the beginning of the recording
|
|
||||||
} else {
|
|
||||||
int sample_frame;
|
|
||||||
if(m_frameRate == frame_rate) {
|
|
||||||
// No resampling required
|
|
||||||
sample_frame = frame_offset;
|
|
||||||
} else {
|
|
||||||
// Need to resample from m_frameRate to frame_rate
|
|
||||||
sample_frame = (int)((__int64_t)frame_offset * (__int64_t)m_frameRate / (__int64_t)frame_rate);
|
|
||||||
}
|
|
||||||
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
|
|
||||||
int buffer_index = sample_frame / maxFramesPerBuffer;
|
|
||||||
if(buffer_index >= m_bufferCount) {
|
|
||||||
return 0.0f; // Past the end of the recording
|
|
||||||
} else {
|
|
||||||
int buffer_offset = frame_offset - buffer_index * maxFramesPerBuffer;
|
|
||||||
|
|
||||||
KRAudioBuffer *buffer = getContext().getAudioManager()->getBuffer(*this, buffer_index);
|
|
||||||
if(buffer == NULL) {
|
|
||||||
return 0.0f;
|
|
||||||
} else if(buffer_offset >= buffer->getFrameCount()) {
|
|
||||||
return 0.0f; // past the end of the recording
|
|
||||||
} else {
|
|
||||||
short *frame = buffer->getFrameData() + (buffer_offset * m_channelsPerFrame);
|
|
||||||
return frame[c] / 32767.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSample::sample(__int64_t frame_offset, int frame_count, int channel, float *buffer, float amplitude, bool loop)
|
|
||||||
{
|
|
||||||
loadInfo();
|
|
||||||
|
|
||||||
m_last_frame_used = getContext().getAudioManager()->getAudioFrame();
|
|
||||||
|
|
||||||
if(loop) {
|
|
||||||
int buffer_offset = 0;
|
|
||||||
int frames_left = frame_count;
|
|
||||||
int sample_length = getFrameCount();
|
|
||||||
while(frames_left) {
|
|
||||||
int next_frame = (int)(((__int64_t)frame_offset + (__int64_t)buffer_offset) % sample_length);
|
|
||||||
if(next_frame + frames_left >= sample_length) {
|
|
||||||
int frames_processed = sample_length - next_frame;
|
|
||||||
sample(next_frame, frames_processed, channel, buffer + buffer_offset, amplitude, false);
|
|
||||||
frames_left -= frames_processed;
|
|
||||||
buffer_offset += frames_processed;
|
|
||||||
} else {
|
|
||||||
sample(next_frame, frames_left, channel, buffer + buffer_offset, amplitude, false);
|
|
||||||
frames_left = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int c = KRMIN(channel, m_channelsPerFrame - 1);
|
|
||||||
|
|
||||||
if(frame_offset + frame_count <= 0) {
|
|
||||||
// Range is entirely before the sample
|
|
||||||
memset(buffer, 0, frame_count * sizeof(float));
|
|
||||||
} else if(frame_offset >= m_totalFrames) {
|
|
||||||
// Range is entirely after the sample
|
|
||||||
memset(buffer, 0, frame_count * sizeof(float));
|
|
||||||
} else {
|
|
||||||
int start_frame = frame_offset < 0 ? 0 : frame_offset;
|
|
||||||
int prefix_frames = frame_offset < 0 ? -frame_offset : 0;
|
|
||||||
if(prefix_frames > 0) {
|
|
||||||
// Prefix with padding of 0's
|
|
||||||
memset(buffer, 0, prefix_frames * sizeof(float));
|
|
||||||
}
|
|
||||||
|
|
||||||
int frames_per_buffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
|
|
||||||
|
|
||||||
int buffer_index = start_frame / frames_per_buffer;
|
|
||||||
int buffer_offset = start_frame % frames_per_buffer;
|
|
||||||
int processed_frames = prefix_frames;
|
|
||||||
while(processed_frames < frame_count) {
|
|
||||||
int frames_left = frame_count - processed_frames;
|
|
||||||
if(buffer_index >= m_bufferCount) {
|
|
||||||
// Suffix with padding of 0's
|
|
||||||
memset(buffer + processed_frames, 0, frames_left * sizeof(float));
|
|
||||||
processed_frames += frames_left;
|
|
||||||
} else {
|
|
||||||
KRAudioBuffer *source_buffer = getContext().getAudioManager()->getBuffer(*this, buffer_index);
|
|
||||||
int frames_to_copy = source_buffer->getFrameCount() - buffer_offset;
|
|
||||||
if(frames_to_copy > frames_left) frames_to_copy = frames_left;
|
|
||||||
if(frames_to_copy > 0) {
|
|
||||||
signed short *source_data = source_buffer->getFrameData() + buffer_offset * m_channelsPerFrame + c;
|
|
||||||
KRDSP::Int16ToFloat(source_data, m_channelsPerFrame, buffer + processed_frames, 1, frames_to_copy);
|
|
||||||
//memcpy(buffer + processed_frames, source_buffer->getFrameData() + buffer_offset, frames_to_copy * m_channelsPerFrame * sizeof(float));
|
|
||||||
processed_frames += frames_to_copy;
|
|
||||||
}
|
|
||||||
buffer_index++;
|
|
||||||
buffer_offset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float scale = amplitude / 32768.0f;
|
|
||||||
KRDSP::Scale(buffer, scale, frame_count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// Apple Audio Toolbox
|
|
||||||
OSStatus KRAudioSample::ReadProc( // AudioFile_ReadProc
|
|
||||||
void * inClientData,
|
|
||||||
SInt64 inPosition,
|
|
||||||
UInt32 requestCount,
|
|
||||||
void * buffer,
|
|
||||||
UInt32 * actualCount)
|
|
||||||
{
|
|
||||||
KRAudioSample *sound = (KRAudioSample *)inClientData;
|
|
||||||
UInt32 max_count = sound->m_pData->getSize() - inPosition;
|
|
||||||
*actualCount = requestCount < max_count ? requestCount : max_count;
|
|
||||||
sound->m_pData->copy(buffer, inPosition, *actualCount);
|
|
||||||
return noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
SInt64 KRAudioSample::GetSizeProc( // AudioFile_GetSizeProc
|
|
||||||
void * inClientData)
|
|
||||||
{
|
|
||||||
KRAudioSample *sound = (KRAudioSample *)inClientData;
|
|
||||||
return sound->m_pData->getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus KRAudioSample::SetSizeProc( // AudioFile_SetSizeProc
|
|
||||||
void * inClientData,
|
|
||||||
SInt64 inSize)
|
|
||||||
{
|
|
||||||
return -1; // Writing not supported
|
|
||||||
}
|
|
||||||
|
|
||||||
OSStatus KRAudioSample::WriteProc( // AudioFile_WriteProc
|
|
||||||
void * inClientData,
|
|
||||||
SInt64 inPosition,
|
|
||||||
UInt32 requestCount,
|
|
||||||
const void *buffer,
|
|
||||||
UInt32 * actualCount)
|
|
||||||
{
|
|
||||||
return -1; // Writing not supported
|
|
||||||
}
|
|
||||||
#endif // Apple Audio Toolbox
|
|
||||||
|
|
||||||
void KRAudioSample::openFile()
|
|
||||||
{
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// Apple Audio Toolbox
|
|
||||||
|
|
||||||
// AudioFileInitializeWithCallbacks
|
|
||||||
if(m_fileRef == NULL) {
|
|
||||||
|
|
||||||
// printf("Call to KRAudioSample::openFile() with extension: %s\n", m_extension.c_str());
|
|
||||||
// The m_extension is valid (it's either wav or mp3 for the files in Circa project)
|
|
||||||
// so we can key off the extension and use a different data handler for mp3 files if we want to
|
|
||||||
//
|
|
||||||
|
|
||||||
// Temp variables
|
|
||||||
UInt32 propertySize;
|
|
||||||
|
|
||||||
// ---- Open audio file ----
|
|
||||||
assert(AudioFileOpenWithCallbacks((void *)this, ReadProc, WriteProc, GetSizeProc, SetSizeProc, 0, &m_audio_file_id) == noErr);
|
|
||||||
assert(ExtAudioFileWrapAudioFileID(m_audio_file_id, false, &m_fileRef) == noErr);
|
|
||||||
|
|
||||||
// ---- Get file format information ----
|
|
||||||
AudioStreamBasicDescription inputFormat;
|
|
||||||
propertySize = sizeof(inputFormat);
|
|
||||||
ExtAudioFileGetProperty(m_fileRef, kExtAudioFileProperty_FileDataFormat, &propertySize, &inputFormat);
|
|
||||||
|
|
||||||
// ---- Set up output format ----
|
|
||||||
AudioStreamBasicDescription outputFormat;
|
|
||||||
// Set the client format to 16 bit signed integer (native-endian) data
|
|
||||||
// Maintain the channel count and sample rate of the original source format
|
|
||||||
outputFormat.mSampleRate = inputFormat.mSampleRate;
|
|
||||||
outputFormat.mChannelsPerFrame = inputFormat.mChannelsPerFrame;
|
|
||||||
outputFormat.mFormatID = kAudioFormatLinearPCM;
|
|
||||||
outputFormat.mBytesPerPacket = 2 * outputFormat.mChannelsPerFrame;
|
|
||||||
outputFormat.mFramesPerPacket = 1;
|
|
||||||
outputFormat.mBytesPerFrame = 2 * outputFormat.mChannelsPerFrame;
|
|
||||||
outputFormat.mBitsPerChannel = 16;
|
|
||||||
outputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
|
|
||||||
ExtAudioFileSetProperty(m_fileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(outputFormat), &outputFormat);
|
|
||||||
|
|
||||||
// ---- Get the buffer size and format parameters ----
|
|
||||||
propertySize = sizeof(m_totalFrames);
|
|
||||||
ExtAudioFileGetProperty(m_fileRef, kExtAudioFileProperty_FileLengthFrames, &propertySize, &m_totalFrames);
|
|
||||||
|
|
||||||
m_bytesPerFrame = outputFormat.mBytesPerFrame;
|
|
||||||
m_frameRate = outputFormat.mSampleRate;
|
|
||||||
|
|
||||||
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
|
|
||||||
m_bufferCount = (m_totalFrames+maxFramesPerBuffer-1)/maxFramesPerBuffer; // CEIL(_totalFrames / maxFramesPerBuffer)
|
|
||||||
|
|
||||||
m_channelsPerFrame = outputFormat.mChannelsPerFrame;
|
|
||||||
|
|
||||||
getContext().getAudioManager()->_registerOpenAudioSample(this);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#pragma message ( "TODO - implement for Windows" )
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSample::closeFile()
|
|
||||||
{
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// Apple Audio Toolbox
|
|
||||||
if(m_fileRef) {
|
|
||||||
ExtAudioFileDispose(m_fileRef);
|
|
||||||
m_fileRef = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_audio_file_id) {
|
|
||||||
AudioFileClose(m_audio_file_id);
|
|
||||||
m_audio_file_id = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
getContext().getAudioManager()->_registerCloseAudioSample(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSample::loadInfo()
|
|
||||||
{
|
|
||||||
if(m_frameRate == 0) {
|
|
||||||
openFile();
|
|
||||||
closeFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRAudioSample::getExtension()
|
|
||||||
{
|
|
||||||
return m_extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAudioSample::save(KRDataBlock &data)
|
|
||||||
{
|
|
||||||
data.append(*m_pData);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAudioSample::getDuration()
|
|
||||||
{
|
|
||||||
loadInfo();
|
|
||||||
return (float)m_totalFrames / (float)m_frameRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
int KRAudioSample::getBufferCount()
|
|
||||||
{
|
|
||||||
loadInfo();
|
|
||||||
return m_bufferCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSample::PopulateBuffer(KRAudioSample *sound, int index, void *data)
|
|
||||||
{
|
|
||||||
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / sound->m_bytesPerFrame;
|
|
||||||
int startFrame = index * maxFramesPerBuffer;
|
|
||||||
__uint32_t frameCount = (__uint32_t)KRMIN(sound->m_totalFrames - startFrame, maxFramesPerBuffer);
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// Apple Audio Toolbox
|
|
||||||
AudioBufferList outputBufferInfo;
|
|
||||||
outputBufferInfo.mNumberBuffers = 1;
|
|
||||||
outputBufferInfo.mBuffers[0].mDataByteSize = frameCount * sound->m_bytesPerFrame;
|
|
||||||
outputBufferInfo.mBuffers[0].mNumberChannels = sound->m_channelsPerFrame;
|
|
||||||
outputBufferInfo.mBuffers[0].mData = data;
|
|
||||||
|
|
||||||
// Read the data into an AudioBufferList
|
|
||||||
ExtAudioFileSeek(sound->m_fileRef, startFrame);
|
|
||||||
ExtAudioFileRead(sound->m_fileRef, (UInt32*)&frameCount, &outputBufferInfo);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAudioBuffer *KRAudioSample::getBuffer(int index)
|
|
||||||
{
|
|
||||||
openFile();
|
|
||||||
|
|
||||||
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
|
|
||||||
int startFrame = index * maxFramesPerBuffer;
|
|
||||||
__uint32_t frameCount = (__uint32_t)KRMIN(m_totalFrames - startFrame, maxFramesPerBuffer);
|
|
||||||
|
|
||||||
KRAudioBuffer *buffer = new KRAudioBuffer(getContext().getAudioManager(), this, index, frameCount, m_frameRate, m_bytesPerFrame, PopulateBuffer);
|
|
||||||
|
|
||||||
if(m_bufferCount == 1) {
|
|
||||||
// [self closeFile]; // We don't need to hold on to a file handle if not streaming
|
|
||||||
}
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSample::_endFrame()
|
|
||||||
{
|
|
||||||
const __int64_t AUDIO_SAMPLE_EXPIRY_FRAMES = 500;
|
|
||||||
long current_frame = getContext().getAudioManager()->getAudioFrame();
|
|
||||||
if(current_frame > m_last_frame_used + AUDIO_SAMPLE_EXPIRY_FRAMES) {
|
|
||||||
closeFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAudioSample.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRAUDIOSAMPLE_H
|
|
||||||
#define KRAUDIOSAMPLE_H
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
#include "KRContextObject.h"
|
|
||||||
#include "KRDataBlock.h"
|
|
||||||
#include "KRResource.h"
|
|
||||||
|
|
||||||
class KRAudioBuffer;
|
|
||||||
|
|
||||||
class KRAudioSample : public KRResource {
|
|
||||||
|
|
||||||
public:
|
|
||||||
KRAudioSample(KRContext &context, std::string name, std::string extension);
|
|
||||||
KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data);
|
|
||||||
virtual ~KRAudioSample();
|
|
||||||
|
|
||||||
virtual std::string getExtension();
|
|
||||||
|
|
||||||
virtual bool save(KRDataBlock &data);
|
|
||||||
|
|
||||||
float getDuration();
|
|
||||||
KRAudioBuffer *getBuffer(int index);
|
|
||||||
int getBufferCount();
|
|
||||||
|
|
||||||
// Siren audio engine interface
|
|
||||||
int getChannelCount();
|
|
||||||
int getFrameCount();
|
|
||||||
float sample(int frame_offset, int frame_rate, int channel);
|
|
||||||
void sample(__int64_t frame_offset, int frame_count, int channel, float *buffer, float amplitude, bool loop);
|
|
||||||
|
|
||||||
void _endFrame();
|
|
||||||
private:
|
|
||||||
|
|
||||||
long m_last_frame_used;
|
|
||||||
|
|
||||||
std::string m_extension;
|
|
||||||
KRDataBlock *m_pData;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// Apple Audio Toolbox
|
|
||||||
AudioFileID m_audio_file_id;
|
|
||||||
ExtAudioFileRef m_fileRef;
|
|
||||||
|
|
||||||
static OSStatus ReadProc( // AudioFile_ReadProc
|
|
||||||
void * inClientData,
|
|
||||||
SInt64 inPosition,
|
|
||||||
UInt32 requestCount,
|
|
||||||
void * buffer,
|
|
||||||
UInt32 * actualCount);
|
|
||||||
|
|
||||||
static OSStatus WriteProc( // AudioFile_WriteProc
|
|
||||||
void * inClientData,
|
|
||||||
SInt64 inPosition,
|
|
||||||
UInt32 requestCount,
|
|
||||||
const void *buffer,
|
|
||||||
UInt32 * actualCount);
|
|
||||||
|
|
||||||
static SInt64 GetSizeProc( // AudioFile_GetSizeProc
|
|
||||||
void * inClientData);
|
|
||||||
|
|
||||||
|
|
||||||
static OSStatus SetSizeProc( // AudioFile_SetSizeProc
|
|
||||||
void * inClientData,
|
|
||||||
SInt64 inSize);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int m_bufferCount;
|
|
||||||
|
|
||||||
__int64_t m_totalFrames;
|
|
||||||
int m_frameRate;
|
|
||||||
int m_bytesPerFrame;
|
|
||||||
int m_channelsPerFrame;
|
|
||||||
|
|
||||||
void openFile();
|
|
||||||
void closeFile();
|
|
||||||
void loadInfo();
|
|
||||||
|
|
||||||
static void PopulateBuffer(KRAudioSample *sound, int index, void *data);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined(KRAUDIOSAMPLE_H) */
|
|
||||||
@@ -1,451 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAudioSource.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRAudioSource.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "KRAudioManager.h"
|
|
||||||
#include "KRAudioSample.h"
|
|
||||||
#include "KRAudioBuffer.h"
|
|
||||||
|
|
||||||
KRAudioSource::KRAudioSource(KRScene &scene, std::string name) : KRNode(scene, name)
|
|
||||||
{
|
|
||||||
m_currentBufferFrame = 0;
|
|
||||||
m_playing = false;
|
|
||||||
m_is3d = true;
|
|
||||||
m_isPrimed = false;
|
|
||||||
m_audioFile = NULL;
|
|
||||||
m_gain = 1.0f;
|
|
||||||
m_pitch = 1.0f;
|
|
||||||
m_looping = false;
|
|
||||||
|
|
||||||
m_referenceDistance = 1.0f;
|
|
||||||
m_reverb = 0.0f;
|
|
||||||
m_rolloffFactor = 2.0f;
|
|
||||||
m_enable_occlusion = true;
|
|
||||||
m_enable_obstruction = true;
|
|
||||||
|
|
||||||
m_start_audio_frame = -1;
|
|
||||||
m_paused_audio_frame = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAudioSource::~KRAudioSource()
|
|
||||||
{
|
|
||||||
while(m_audioBuffers.size()) {
|
|
||||||
delete m_audioBuffers.front();
|
|
||||||
m_audioBuffers.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRAudioSource::getElementName() {
|
|
||||||
return "audio_source";
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRAudioSource::saveXML( tinyxml2::XMLNode *parent)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
|
||||||
e->SetAttribute("sample", m_audio_sample_name.c_str());
|
|
||||||
e->SetAttribute("gain", m_gain);
|
|
||||||
e->SetAttribute("pitch", m_pitch);
|
|
||||||
e->SetAttribute("looping", m_looping ? "true" : "false");
|
|
||||||
e->SetAttribute("is3d", m_is3d ? "true" : "false");
|
|
||||||
e->SetAttribute("reference_distance", m_referenceDistance);
|
|
||||||
e->SetAttribute("reverb", m_reverb);
|
|
||||||
e->SetAttribute("rolloff_factor", m_rolloffFactor);
|
|
||||||
e->SetAttribute("enable_occlusion", m_enable_occlusion ? "true" : "false");
|
|
||||||
e->SetAttribute("enable_obstruction", m_enable_obstruction ? "true" : "false");
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::loadXML(tinyxml2::XMLElement *e)
|
|
||||||
{
|
|
||||||
m_audio_sample_name = e->Attribute("sample");
|
|
||||||
|
|
||||||
float gain = 1.0f;
|
|
||||||
if(e->QueryFloatAttribute("gain", &gain) != tinyxml2::XML_SUCCESS) {
|
|
||||||
gain = 1.0f;
|
|
||||||
}
|
|
||||||
setGain(gain);
|
|
||||||
|
|
||||||
float pitch = 1.0f;
|
|
||||||
if(e->QueryFloatAttribute("pitch", &pitch) != tinyxml2::XML_SUCCESS) {
|
|
||||||
pitch = 1.0f;
|
|
||||||
}
|
|
||||||
setPitch(m_pitch);
|
|
||||||
|
|
||||||
bool looping = false;
|
|
||||||
if(e->QueryBoolAttribute("looping", &looping) != tinyxml2::XML_SUCCESS) {
|
|
||||||
looping = false;
|
|
||||||
}
|
|
||||||
setLooping(looping);
|
|
||||||
|
|
||||||
bool is3d = true;
|
|
||||||
if(e->QueryBoolAttribute("is3d", &is3d) != tinyxml2::XML_SUCCESS) {
|
|
||||||
is3d = true;
|
|
||||||
}
|
|
||||||
setIs3D(is3d);
|
|
||||||
|
|
||||||
float reference_distance = 1.0f;
|
|
||||||
if(e->QueryFloatAttribute("reference_distance", &reference_distance) != tinyxml2::XML_SUCCESS) {
|
|
||||||
reference_distance = 1.0f;
|
|
||||||
}
|
|
||||||
setReferenceDistance(reference_distance);
|
|
||||||
|
|
||||||
float reverb = 0.0f;
|
|
||||||
if(e->QueryFloatAttribute("reverb", &reverb) != tinyxml2::XML_SUCCESS) {
|
|
||||||
reverb = 0.0f;
|
|
||||||
}
|
|
||||||
setReverb(reverb);
|
|
||||||
|
|
||||||
float rolloff_factor = 2.0f;
|
|
||||||
if(e->QueryFloatAttribute("rolloff_factor", &rolloff_factor) != tinyxml2::XML_SUCCESS) {
|
|
||||||
rolloff_factor = 2.0f;
|
|
||||||
}
|
|
||||||
setRolloffFactor(rolloff_factor);
|
|
||||||
|
|
||||||
m_enable_obstruction = true;
|
|
||||||
if(e->QueryBoolAttribute("enable_obstruction", &m_enable_obstruction) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_enable_obstruction = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_enable_occlusion = true;
|
|
||||||
if(e->QueryBoolAttribute("enable_occlusion", &m_enable_occlusion) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_enable_occlusion = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRNode::loadXML(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::prime()
|
|
||||||
{
|
|
||||||
if(!m_isPrimed) {
|
|
||||||
if(m_audioFile == NULL && m_audio_sample_name.size() != 0) {
|
|
||||||
m_audioFile = getContext().getAudioManager()->get(m_audio_sample_name);
|
|
||||||
}
|
|
||||||
if(m_audioFile) {
|
|
||||||
// Prime the buffer queue
|
|
||||||
m_nextBufferIndex = 0;
|
|
||||||
for(int i=0; i < KRENGINE_AUDIO_BUFFERS_PER_SOURCE; i++) {
|
|
||||||
queueBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_isPrimed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::queueBuffer()
|
|
||||||
{
|
|
||||||
KRAudioBuffer *buffer = m_audioFile->getBuffer(m_nextBufferIndex);
|
|
||||||
m_audioBuffers.push(buffer);
|
|
||||||
m_nextBufferIndex = (m_nextBufferIndex + 1) % m_audioFile->getBufferCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
|
||||||
|
|
||||||
bool bVisualize = false;
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
|
||||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
|
||||||
|
|
||||||
// Enable additive blending
|
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
|
||||||
|
|
||||||
|
|
||||||
// Disable z-buffer write
|
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
|
||||||
|
|
||||||
// Enable z-buffer test
|
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
|
||||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
|
||||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
|
||||||
if(sphereModels.size()) {
|
|
||||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
|
||||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable alpha blending
|
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::setGain(float gain)
|
|
||||||
{
|
|
||||||
m_gain = gain;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAudioSource::getGain()
|
|
||||||
{
|
|
||||||
return m_gain;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::setPitch(float pitch)
|
|
||||||
{
|
|
||||||
m_pitch = pitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float KRAudioSource::getReferenceDistance()
|
|
||||||
{
|
|
||||||
return m_referenceDistance;
|
|
||||||
}
|
|
||||||
void KRAudioSource::setReferenceDistance(float reference_distance)
|
|
||||||
{
|
|
||||||
m_referenceDistance = reference_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAudioSource::getReverb()
|
|
||||||
{
|
|
||||||
return m_reverb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::setReverb(float reverb)
|
|
||||||
{
|
|
||||||
m_reverb = reverb;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRAudioSource::getRolloffFactor()
|
|
||||||
{
|
|
||||||
return m_rolloffFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::setRolloffFactor(float rolloff_factor)
|
|
||||||
{
|
|
||||||
m_rolloffFactor = rolloff_factor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::setLooping(bool looping)
|
|
||||||
{
|
|
||||||
// Enable or disable looping playback; Audio source must be stopped and re-started for loop mode changes to take effect
|
|
||||||
m_looping = looping;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAudioSource::getLooping()
|
|
||||||
{
|
|
||||||
// Returns true if the playback will automatically loop
|
|
||||||
return m_looping;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAudioSource::getEnableOcclusion()
|
|
||||||
{
|
|
||||||
return m_enable_occlusion;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::setEnableOcclusion(bool enable_occlusion)
|
|
||||||
{
|
|
||||||
m_enable_occlusion = enable_occlusion;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAudioSource::getEnableObstruction()
|
|
||||||
{
|
|
||||||
return m_enable_obstruction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::setEnableObstruction(bool enable_obstruction)
|
|
||||||
{
|
|
||||||
m_enable_obstruction = enable_obstruction;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAudioSource::getIs3D()
|
|
||||||
{
|
|
||||||
return m_is3d;
|
|
||||||
}
|
|
||||||
void KRAudioSource::setIs3D(bool is3D)
|
|
||||||
{
|
|
||||||
// Audio source must be stopped and re-started for mode change to take effect
|
|
||||||
m_is3d = is3D;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::advanceBuffer()
|
|
||||||
{
|
|
||||||
if(m_audioBuffers.size()) {
|
|
||||||
delete m_audioBuffers.front();
|
|
||||||
m_audioBuffers.pop();
|
|
||||||
}
|
|
||||||
queueBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::physicsUpdate(float deltaTime)
|
|
||||||
{
|
|
||||||
KRNode::physicsUpdate(deltaTime);
|
|
||||||
|
|
||||||
KRAudioManager *audioManager = getContext().getAudioManager();
|
|
||||||
audioManager->activateAudioSource(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::play()
|
|
||||||
{
|
|
||||||
// Start playback of audio at the current audio sample position. If audio is already playing, this has no effect.
|
|
||||||
// play() does not automatically seek to the beginning of the sample. Call setAudioFrame( 0 ) first if you wish the playback to begin at the start of the audio sample.
|
|
||||||
// If not set to looping, audio playback ends automatically at the end of the sample
|
|
||||||
|
|
||||||
if(!m_playing) {
|
|
||||||
KRAudioManager *audioManager = getContext().getAudioManager();
|
|
||||||
assert(m_start_audio_frame == -1);
|
|
||||||
m_start_audio_frame = audioManager->getAudioFrame() - m_paused_audio_frame;
|
|
||||||
m_paused_audio_frame = -1;
|
|
||||||
audioManager->activateAudioSource(this);
|
|
||||||
}
|
|
||||||
m_playing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::stop()
|
|
||||||
{
|
|
||||||
// Stop playback of audio. If audio is already stopped, this has no effect.
|
|
||||||
// If play() is called afterwards, playback will continue at the current audio sample position.
|
|
||||||
|
|
||||||
if(m_playing) {
|
|
||||||
m_paused_audio_frame = getAudioFrame();
|
|
||||||
m_start_audio_frame = -1;
|
|
||||||
m_playing = false;
|
|
||||||
getContext().getAudioManager()->deactivateAudioSource(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRAudioSource::isPlaying()
|
|
||||||
{
|
|
||||||
// Returns true if audio is playing. Will return false if a non-looped playback has reached the end of the audio sample.
|
|
||||||
|
|
||||||
return m_playing;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void KRAudioSource::setSample(const std::string &sound_name)
|
|
||||||
{
|
|
||||||
m_audio_sample_name = sound_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRAudioSource::getSample()
|
|
||||||
{
|
|
||||||
return m_audio_sample_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAudioSample *KRAudioSource::getAudioSample()
|
|
||||||
{
|
|
||||||
if(m_audioFile == NULL && m_audio_sample_name.size() != 0) {
|
|
||||||
m_audioFile = getContext().getAudioManager()->get(m_audio_sample_name);
|
|
||||||
}
|
|
||||||
return m_audioFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::advanceFrames(int frame_count)
|
|
||||||
{
|
|
||||||
m_currentBufferFrame += frame_count;
|
|
||||||
|
|
||||||
KRAudioBuffer *buffer = getBuffer();
|
|
||||||
while(buffer != NULL && m_currentBufferFrame >= buffer->getFrameCount()) {
|
|
||||||
m_currentBufferFrame -= buffer->getFrameCount();
|
|
||||||
advanceBuffer();
|
|
||||||
buffer = getBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(buffer == NULL) {
|
|
||||||
m_currentBufferFrame = 0;
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KRAudioBuffer *KRAudioSource::getBuffer()
|
|
||||||
{
|
|
||||||
if(m_playing) {
|
|
||||||
prime();
|
|
||||||
return m_audioBuffers.front();
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int KRAudioSource::getBufferFrame()
|
|
||||||
{
|
|
||||||
return m_currentBufferFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
__int64_t KRAudioSource::getAudioFrame()
|
|
||||||
{
|
|
||||||
// Returns the audio playback position in units of integer audio frames.
|
|
||||||
|
|
||||||
if(m_playing) {
|
|
||||||
return getContext().getAudioManager()->getAudioFrame() - m_start_audio_frame;
|
|
||||||
} else {
|
|
||||||
return m_paused_audio_frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::setAudioFrame(__int64_t next_frame)
|
|
||||||
{
|
|
||||||
// Sets the audio playback position with units of integer audio frames.
|
|
||||||
if(m_playing) {
|
|
||||||
m_start_audio_frame = getContext().getAudioManager()->getAudioFrame() - next_frame;
|
|
||||||
} else {
|
|
||||||
m_paused_audio_frame = next_frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float KRAudioSource::getAudioTime()
|
|
||||||
{
|
|
||||||
// Gets the audio playback position with units of floating point seconds.
|
|
||||||
|
|
||||||
return getAudioFrame() / 44100.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::setAudioTime(float new_position)
|
|
||||||
{
|
|
||||||
// Sets the audio playback position with units of floating point seconds.
|
|
||||||
setAudioFrame(new_position * 44100.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRAudioSource::sample(int frame_count, int channel, float *buffer, float gain)
|
|
||||||
{
|
|
||||||
KRAudioSample *source_sample = getAudioSample();
|
|
||||||
if(source_sample && m_playing) {
|
|
||||||
__int64_t next_frame = getAudioFrame();
|
|
||||||
source_sample->sample(next_frame, frame_count, channel, buffer, gain, m_looping);
|
|
||||||
if(!m_looping && next_frame > source_sample->getFrameCount()) {
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
memset(buffer, 0, sizeof(float) * frame_count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
//
|
|
||||||
// KRAudioSource.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRAUDIOSOURCE_H
|
|
||||||
#define KRAUDIOSOURCE_H
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
#include "KRResource.h"
|
|
||||||
#include "KRNode.h"
|
|
||||||
#include "KRTexture.h"
|
|
||||||
|
|
||||||
class KRAudioSample;
|
|
||||||
class KRAudioBuffer;
|
|
||||||
|
|
||||||
class KRAudioSource : public KRNode {
|
|
||||||
public:
|
|
||||||
KRAudioSource(KRScene &scene, std::string name);
|
|
||||||
virtual ~KRAudioSource();
|
|
||||||
virtual std::string getElementName();
|
|
||||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
|
||||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
|
||||||
virtual void physicsUpdate(float deltaTime);
|
|
||||||
|
|
||||||
void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
|
|
||||||
|
|
||||||
// ---- Audio Playback Controls ----
|
|
||||||
|
|
||||||
// Start playback of audio at the current audio sample position. If audio is already playing, this has no effect.
|
|
||||||
// play() does not automatically seek to the beginning of the sample. Call setAudioFrame( 0 ) first if you wish the playback to begin at the start of the audio sample.
|
|
||||||
// If not set to looping, audio playback ends automatically at the end of the sample
|
|
||||||
void play();
|
|
||||||
|
|
||||||
// Stop playback of audio. If audio is already stopped, this has no effect.
|
|
||||||
// If play() is called afterwards, playback will continue at the current audio sample position.
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
// Returns true if audio is playing. Will return false if a non-looped playback has reached the end of the audio sample.
|
|
||||||
bool isPlaying();
|
|
||||||
|
|
||||||
// Returns the audio playback position in units of integer audio frames.
|
|
||||||
__int64_t getAudioFrame();
|
|
||||||
|
|
||||||
// Sets the audio playback position with units of integer audio frames.
|
|
||||||
void setAudioFrame(__int64_t next_frame);
|
|
||||||
|
|
||||||
// Gets the audio playback position with units of floating point seconds.
|
|
||||||
float getAudioTime();
|
|
||||||
|
|
||||||
// Sets the audio playback position with units of floating point seconds.
|
|
||||||
void setAudioTime(float new_position);
|
|
||||||
|
|
||||||
// Returns true if the playback will automatically loop
|
|
||||||
bool getLooping();
|
|
||||||
|
|
||||||
// Enable or disable looping playback; Audio source must be stopped and re-started for loop mode changes to take effect
|
|
||||||
void setLooping(bool looping);
|
|
||||||
|
|
||||||
// ---- End: Audio Playback Controls ----
|
|
||||||
|
|
||||||
void setSample(const std::string &sound_name);
|
|
||||||
std::string getSample();
|
|
||||||
|
|
||||||
KRAudioSample *getAudioSample();
|
|
||||||
|
|
||||||
float getGain();
|
|
||||||
void setGain(float gain);
|
|
||||||
|
|
||||||
float getPitch();
|
|
||||||
void setPitch(float pitch);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool getIs3D();
|
|
||||||
void setIs3D(bool is3D);
|
|
||||||
|
|
||||||
// 3d only properties:
|
|
||||||
float getReverb();
|
|
||||||
void setReverb(float reverb);
|
|
||||||
|
|
||||||
float getReferenceDistance();
|
|
||||||
void setReferenceDistance(float reference_distance);
|
|
||||||
|
|
||||||
float getRolloffFactor();
|
|
||||||
void setRolloffFactor(float rolloff_factor);
|
|
||||||
|
|
||||||
bool getEnableOcclusion();
|
|
||||||
void setEnableOcclusion(bool enable_occlusion);
|
|
||||||
|
|
||||||
bool getEnableObstruction();
|
|
||||||
void setEnableObstruction(bool enable_obstruction);
|
|
||||||
|
|
||||||
// ---- Siren Audio Engine Interface ----
|
|
||||||
|
|
||||||
void advanceFrames(int frame_count);
|
|
||||||
KRAudioBuffer *getBuffer();
|
|
||||||
int getBufferFrame();
|
|
||||||
|
|
||||||
void sample(int frame_count, int channel, float *buffer, float gain);
|
|
||||||
|
|
||||||
private:
|
|
||||||
__int64_t m_start_audio_frame; // Global audio frame that matches the start of the audio sample playback; when paused or not playing, this contains a value of -1
|
|
||||||
__int64_t m_paused_audio_frame; // When paused or not playing, this contains the local audio frame number. When playing, this contains a value of -1
|
|
||||||
int m_currentBufferFrame; // Siren Audio Engine frame number within current buffer
|
|
||||||
void advanceBuffer();
|
|
||||||
|
|
||||||
std::string m_audio_sample_name;
|
|
||||||
|
|
||||||
KRAudioSample *m_audioFile;
|
|
||||||
unsigned int m_sourceID;
|
|
||||||
float m_gain;
|
|
||||||
float m_pitch;
|
|
||||||
bool m_looping;
|
|
||||||
std::queue<KRAudioBuffer *> m_audioBuffers;
|
|
||||||
int m_nextBufferIndex;
|
|
||||||
bool m_playing;
|
|
||||||
bool m_is3d;
|
|
||||||
bool m_isPrimed;
|
|
||||||
|
|
||||||
void prime();
|
|
||||||
void queueBuffer();
|
|
||||||
|
|
||||||
// 3d only properties:
|
|
||||||
float m_referenceDistance;
|
|
||||||
float m_reverb; // type ALfloat 0.0 (dry) - 1.0 (wet) (0-100% dry/wet mix, 0.0 default)
|
|
||||||
float m_rolloffFactor;
|
|
||||||
bool m_enable_occlusion;
|
|
||||||
bool m_enable_obstruction;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined(KRAUDIOSOURCE_H) */
|
|
||||||
@@ -1,66 +1,89 @@
|
|||||||
//
|
//
|
||||||
// KRBehavior.cpp
|
// KRBehavior.cpp
|
||||||
// Kraken
|
// Kraken Engine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2013-05-17.
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRBehavior.h"
|
#include "KRBehavior.h"
|
||||||
#include "KRNode.h"
|
#include "nodes/KRNode.h"
|
||||||
|
|
||||||
KRBehaviorFactoryFunctionMap m_factoryFunctions;
|
KRBehaviorFactoryFunctionMap m_factoryFunctions;
|
||||||
|
|
||||||
KRBehavior::KRBehavior()
|
KRBehavior::KRBehavior()
|
||||||
{
|
{
|
||||||
__node = NULL;
|
__node = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRBehavior::~KRBehavior()
|
KRBehavior::~KRBehavior()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRBehavior::init()
|
void KRBehavior::init()
|
||||||
{
|
{
|
||||||
// Note: Subclasses are not expected to call this method
|
// Note: Subclasses are not expected to call this method
|
||||||
}
|
}
|
||||||
|
|
||||||
KRNode *KRBehavior::getNode() const
|
KRNode* KRBehavior::getNode() const
|
||||||
{
|
{
|
||||||
return __node;
|
return __node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRBehavior::__setNode(KRNode *node)
|
void KRBehavior::__setNode(KRNode* node)
|
||||||
{
|
{
|
||||||
__node = node;
|
__node = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KRBehavior *KRBehavior::LoadXML(KRNode *node, tinyxml2::XMLElement *e)
|
KRBehavior* KRBehavior::LoadXML(KRNode* node, tinyxml2::XMLElement* e)
|
||||||
{
|
{
|
||||||
std::map<std::string, std::string> attributes;
|
std::map<std::string, std::string> attributes;
|
||||||
for(const tinyxml2::XMLAttribute *attribute = e->FirstAttribute(); attribute != NULL; attribute = attribute->Next()) {
|
for (const tinyxml2::XMLAttribute* attribute = e->FirstAttribute(); attribute != NULL; attribute = attribute->Next()) {
|
||||||
attributes[attribute->Name()] = attribute->Value();
|
attributes[attribute->Name()] = attribute->Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *szElementName = e->Attribute("type");
|
const char* szElementName = e->Attribute("type");
|
||||||
if(szElementName == NULL) {
|
if (szElementName == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
KRBehaviorFactoryFunctionMap::const_iterator itr = m_factoryFunctions.find(szElementName);
|
KRBehaviorFactoryFunctionMap::const_iterator itr = m_factoryFunctions.find(szElementName);
|
||||||
if(itr == m_factoryFunctions.end()) {
|
if (itr == m_factoryFunctions.end()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return (*itr->second)(attributes);
|
return (*itr->second)(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRBehavior::RegisterFactoryCTOR(std::string behaviorName, KRBehaviorFactoryFunction fnFactory)
|
void KRBehavior::RegisterFactoryCTOR(std::string behaviorName, KRBehaviorFactoryFunction fnFactory)
|
||||||
{
|
{
|
||||||
m_factoryFunctions[behaviorName] = fnFactory;
|
m_factoryFunctions[behaviorName] = fnFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRBehavior::UnregisterFactoryCTOR(std::string behaviorName)
|
void KRBehavior::UnregisterFactoryCTOR(std::string behaviorName)
|
||||||
{
|
{
|
||||||
m_factoryFunctions.erase(behaviorName);
|
m_factoryFunctions.erase(behaviorName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,43 @@
|
|||||||
//
|
//
|
||||||
// KRBehavior.h
|
// KRBehavior.h
|
||||||
// Kraken
|
// Kraken Engine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2013-05-17.
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef KRBEHAVIOR_H
|
#pragma once
|
||||||
#define KRBEHAVIOR_H
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This class is a pure-virtual base class intended to be subclassed to define behavior of KRNode's in the scene
|
This class is a pure-virtual base class intended to be subclassed to define behavior of KRNode's in the scene
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class KRBehavior;
|
class KRBehavior;
|
||||||
@@ -23,27 +46,25 @@ namespace tinyxml2 {
|
|||||||
class XMLElement;
|
class XMLElement;
|
||||||
} // namespace tinyxml2
|
} // namespace tinyxml2
|
||||||
|
|
||||||
typedef KRBehavior *(*KRBehaviorFactoryFunction)(std::map<std::string, std::string> attributes);
|
typedef KRBehavior* (*KRBehaviorFactoryFunction)(std::map<std::string, std::string> attributes);
|
||||||
typedef std::map<std::string, KRBehaviorFactoryFunction> KRBehaviorFactoryFunctionMap;
|
typedef std::map<std::string, KRBehaviorFactoryFunction> KRBehaviorFactoryFunctionMap;
|
||||||
|
|
||||||
class KRBehavior
|
class KRBehavior
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void RegisterFactoryCTOR(std::string behaviorName, KRBehaviorFactoryFunction fnFactory);
|
static void RegisterFactoryCTOR(std::string behaviorName, KRBehaviorFactoryFunction fnFactory);
|
||||||
static void UnregisterFactoryCTOR(std::string behaviorName);
|
static void UnregisterFactoryCTOR(std::string behaviorName);
|
||||||
|
|
||||||
KRBehavior();
|
|
||||||
virtual ~KRBehavior();
|
|
||||||
KRNode *getNode() const;
|
|
||||||
|
|
||||||
virtual void init();
|
|
||||||
virtual void update(float deltaTime) = 0;
|
|
||||||
virtual void visibleUpdate(float deltatime) = 0;
|
|
||||||
void __setNode(KRNode *node);
|
|
||||||
|
|
||||||
static KRBehavior *LoadXML(KRNode *node, tinyxml2::XMLElement *e);
|
|
||||||
private:
|
|
||||||
KRNode *__node;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined(KRBEHAVIOR_H) */
|
KRBehavior();
|
||||||
|
virtual ~KRBehavior();
|
||||||
|
KRNode* getNode() const;
|
||||||
|
|
||||||
|
virtual void init();
|
||||||
|
virtual void update(float deltaTime) = 0;
|
||||||
|
virtual void visibleUpdate(float deltatime) = 0;
|
||||||
|
void __setNode(KRNode* node);
|
||||||
|
|
||||||
|
static KRBehavior* LoadXML(KRNode* node, tinyxml2::XMLElement* e);
|
||||||
|
private:
|
||||||
|
KRNode* __node;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
//
|
|
||||||
// KRBone.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRBone.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
|
|
||||||
KRBone::KRBone(KRScene &scene, std::string name) : KRNode(scene, name)
|
|
||||||
{
|
|
||||||
setScaleCompensation(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
KRBone::~KRBone()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRBone::getElementName() {
|
|
||||||
return "bone";
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
|
||||||
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRBone::loadXML(tinyxml2::XMLElement *e)
|
|
||||||
{
|
|
||||||
KRNode::loadXML(e);
|
|
||||||
setScaleCompensation(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB KRBone::getBounds() {
|
|
||||||
return AABB(-Vector3::One(), Vector3::One(), getModelMatrix()); // Only required for bone debug visualization
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRBone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
|
||||||
{
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
|
||||||
|
|
||||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
|
||||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
|
||||||
|
|
||||||
// Enable additive blending
|
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
|
||||||
|
|
||||||
|
|
||||||
// Disable z-buffer write
|
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
|
||||||
|
|
||||||
// Disable z-buffer test
|
|
||||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
|
||||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
|
||||||
if(sphereModels.size()) {
|
|
||||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
|
||||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable alpha blending
|
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
|
||||||
|
|
||||||
// Enable z-buffer test
|
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
|
||||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void KRBone::setBindPose(const Matrix4 &pose)
|
|
||||||
{
|
|
||||||
m_bind_pose = pose;
|
|
||||||
}
|
|
||||||
const Matrix4 &KRBone::getBindPose()
|
|
||||||
{
|
|
||||||
return m_bind_pose;
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
//
|
|
||||||
// KRBone.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRBONE_H
|
|
||||||
#define KRBONE_H
|
|
||||||
|
|
||||||
#include "KRResource.h"
|
|
||||||
#include "KRNode.h"
|
|
||||||
#include "KRTexture.h"
|
|
||||||
|
|
||||||
class KRBone : public KRNode {
|
|
||||||
public:
|
|
||||||
KRBone(KRScene &scene, std::string name);
|
|
||||||
virtual ~KRBone();
|
|
||||||
virtual std::string getElementName();
|
|
||||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
|
||||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
|
||||||
virtual AABB getBounds();
|
|
||||||
|
|
||||||
void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
|
|
||||||
|
|
||||||
void setBindPose(const Matrix4 &pose);
|
|
||||||
const Matrix4 &getBindPose();
|
|
||||||
private:
|
|
||||||
Matrix4 m_bind_pose;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
//
|
|
||||||
// KRBundle.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRBundle.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
const int KRENGINE_KRBUNDLE_HEADER_SIZE = 512;
|
|
||||||
|
|
||||||
typedef struct _tar_header
|
|
||||||
{
|
|
||||||
char file_name[100];
|
|
||||||
char file_mode[8];
|
|
||||||
char owner_id[8]; // Owner's numeric user ID (OCTAL!)
|
|
||||||
char group_id[8]; // Group's numeric user ID (OCTAL!)
|
|
||||||
char file_size[12]; // File size in bytes (OCTAL!)
|
|
||||||
char mod_time[12]; // Last modification time in numeric Unix time format
|
|
||||||
char checksum[8]; // Checksum for header block
|
|
||||||
char file_type[1]; // Link indicator (file type)
|
|
||||||
char linked_file[100]; // Name of linked file
|
|
||||||
|
|
||||||
} tar_header_type;
|
|
||||||
|
|
||||||
KRBundle::KRBundle(KRContext &context, std::string name, KRDataBlock *pData) : KRResource(context, name)
|
|
||||||
{
|
|
||||||
m_pData = pData;
|
|
||||||
|
|
||||||
__int64_t file_pos = 0;
|
|
||||||
while(file_pos < m_pData->getSize()) {
|
|
||||||
tar_header_type file_header;
|
|
||||||
m_pData->copy(&file_header, file_pos, sizeof(file_header));
|
|
||||||
size_t file_size = strtol(file_header.file_size, NULL, 8);
|
|
||||||
file_pos += 512; // Skip past the header to the file contents
|
|
||||||
if(file_header.file_name[0] != '\0' && file_header.file_name[0] != '.') {
|
|
||||||
// We ignore the last two records in the tar file, which are zero'ed out tar_header structures
|
|
||||||
KRDataBlock *pFileData = pData->getSubBlock(file_pos, file_size);
|
|
||||||
context.loadResource(file_header.file_name, pFileData);
|
|
||||||
}
|
|
||||||
file_pos += RoundUpSize(file_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KRBundle::KRBundle(KRContext &context, std::string name) : KRResource(context, name)
|
|
||||||
{
|
|
||||||
// Create an empty krbundle (tar) file, initialized with two zero-ed out file headers, which terminate it.
|
|
||||||
m_pData = new KRDataBlock();
|
|
||||||
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE * 2);
|
|
||||||
m_pData->lock();
|
|
||||||
memset(m_pData->getStart(), 0, m_pData->getSize());
|
|
||||||
m_pData->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t KRBundle::RoundUpSize(size_t s)
|
|
||||||
{
|
|
||||||
// Get amount of padding needed to increase s to a 512 byte alignment
|
|
||||||
if((s & 0x01ff) == 0) {
|
|
||||||
// file size is a multiple of 512 bytes, we can just add it
|
|
||||||
return s;
|
|
||||||
} else {
|
|
||||||
// We would not be on a 512 byte boundary, round up to the next one
|
|
||||||
return (s + 0x0200) - (s & 0x1ff);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
KRBundle::~KRBundle()
|
|
||||||
{
|
|
||||||
delete m_pData;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRBundle::getExtension()
|
|
||||||
{
|
|
||||||
return "krbundle";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRBundle::save(const std::string& path)
|
|
||||||
{
|
|
||||||
return m_pData->save(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRBundle::save(KRDataBlock &data) {
|
|
||||||
if(m_pData->getSize() > KRENGINE_KRBUNDLE_HEADER_SIZE * 2) {
|
|
||||||
// Only output krbundles that contain files
|
|
||||||
data.append(*m_pData);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRBundle::append(KRResource &resource)
|
|
||||||
{
|
|
||||||
// Serialize resource to binary representation
|
|
||||||
KRDataBlock resource_data;
|
|
||||||
resource.save(resource_data);
|
|
||||||
|
|
||||||
std::string file_name = resource.getName() + "." + resource.getExtension();
|
|
||||||
|
|
||||||
// Padding is added at the end of file to align next header to a 512 byte boundary. Padding at the end of the archive includes an additional 1024 bytes -- two zero-ed out file headers that mark the end of the archive
|
|
||||||
size_t padding_size = RoundUpSize(resource_data.getSize()) - resource_data.getSize() + KRENGINE_KRBUNDLE_HEADER_SIZE * 2;
|
|
||||||
|
|
||||||
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE + resource_data.getSize() + padding_size - KRENGINE_KRBUNDLE_HEADER_SIZE * 2); // We will overwrite the existing zero-ed out file headers that marked the end of the archive, so we don't have to include their size here
|
|
||||||
|
|
||||||
m_pData->lock();
|
|
||||||
|
|
||||||
// Get location of file header
|
|
||||||
tar_header_type *file_header = (tar_header_type *)((unsigned char *)m_pData->getEnd() - padding_size - resource_data.getSize() - KRENGINE_KRBUNDLE_HEADER_SIZE);
|
|
||||||
|
|
||||||
// Zero out new file header
|
|
||||||
memset(file_header, 0, KRENGINE_KRBUNDLE_HEADER_SIZE);
|
|
||||||
|
|
||||||
// Copy resource data
|
|
||||||
resource_data.lock();
|
|
||||||
memcpy((unsigned char *)m_pData->getEnd() - padding_size - resource_data.getSize(), resource_data.getStart(), resource_data.getSize());
|
|
||||||
resource_data.unlock();
|
|
||||||
|
|
||||||
// Zero out alignment padding and terminating set of file header blocks
|
|
||||||
memset((unsigned char *)m_pData->getEnd() - padding_size, 0, padding_size);
|
|
||||||
|
|
||||||
// Populate new file header fields
|
|
||||||
strncpy(file_header->file_name, file_name.c_str(), 100);
|
|
||||||
strcpy(file_header->file_mode, "000644 ");
|
|
||||||
strcpy(file_header->owner_id, "000000 ");
|
|
||||||
strcpy(file_header->group_id, "000000 ");
|
|
||||||
sprintf(file_header->file_size, "%011o", (int)resource_data.getSize());
|
|
||||||
file_header->file_size[11] = ' '; // Terminate with space rather than '\0'
|
|
||||||
sprintf(file_header->mod_time, "%011o", (int)time(NULL));
|
|
||||||
file_header->mod_time[11] = ' '; // Terminate with space rather than '\0'
|
|
||||||
|
|
||||||
// Calculate and write checksum for header
|
|
||||||
memset(file_header->checksum, ' ', 8); // Must be filled with spaces and no null terminator during checksum calculation
|
|
||||||
int check_sum = 0;
|
|
||||||
for(int i=0; i < KRENGINE_KRBUNDLE_HEADER_SIZE; i++) {
|
|
||||||
unsigned char *byte_ptr = (unsigned char *)file_header;
|
|
||||||
check_sum += byte_ptr[i];
|
|
||||||
}
|
|
||||||
sprintf(file_header->checksum, "%07o", check_sum);
|
|
||||||
|
|
||||||
m_pData->unlock();
|
|
||||||
}
|
|
||||||
1117
kraken/KRCamera.cpp
1117
kraken/KRCamera.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,121 +0,0 @@
|
|||||||
//
|
|
||||||
// KRSettings.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRCAMERA_H
|
|
||||||
#define KRCAMERA_H
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#include "KRShader.h"
|
|
||||||
#include "KRContextObject.h"
|
|
||||||
#include "KRTexture.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "KRViewport.h"
|
|
||||||
#include "KRRenderSettings.h"
|
|
||||||
|
|
||||||
#define KRAKEN_FPS_AVERAGE_FRAME_COUNT 30
|
|
||||||
|
|
||||||
class KRModel;
|
|
||||||
class KRScene;
|
|
||||||
class KRViewport;
|
|
||||||
|
|
||||||
class KRCamera : public KRNode {
|
|
||||||
public:
|
|
||||||
KRCamera(KRScene &scene, std::string name);
|
|
||||||
virtual ~KRCamera();
|
|
||||||
|
|
||||||
void renderFrame(GLint defaultFBO, GLint renderBufferWidth, GLint renderBufferHeight);
|
|
||||||
|
|
||||||
KRRenderSettings settings;
|
|
||||||
|
|
||||||
const KRViewport &getViewport() const;
|
|
||||||
|
|
||||||
|
|
||||||
virtual std::string getElementName();
|
|
||||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
|
||||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
|
||||||
|
|
||||||
std::string getDebugText();
|
|
||||||
|
|
||||||
void flushSkybox(); // this will delete the skybox and cause the camera to reload a new skybox based on the settings
|
|
||||||
Vector2 getDownsample();
|
|
||||||
void setDownsample(float v);
|
|
||||||
|
|
||||||
void setFadeColor(const Vector4 &fade_color);
|
|
||||||
Vector4 getFadeColor();
|
|
||||||
|
|
||||||
void setSkyBox(const std::string &skyBox);
|
|
||||||
const std::string getSkyBox() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void createBuffers(GLint renderBufferWidth, GLint renderBufferHeight);
|
|
||||||
|
|
||||||
GLint m_backingWidth, m_backingHeight;
|
|
||||||
GLint volumetricBufferWidth, volumetricBufferHeight;
|
|
||||||
|
|
||||||
GLuint compositeFramebuffer, compositeDepthTexture, compositeColorTexture;
|
|
||||||
GLuint lightAccumulationBuffer, lightAccumulationTexture;
|
|
||||||
|
|
||||||
|
|
||||||
GLuint volumetricLightAccumulationBuffer, volumetricLightAccumulationTexture;
|
|
||||||
|
|
||||||
void renderPost();
|
|
||||||
|
|
||||||
void destroyBuffers();
|
|
||||||
|
|
||||||
KRTexture *m_pSkyBoxTexture;
|
|
||||||
std::string m_skyBox;
|
|
||||||
KRViewport m_viewport;
|
|
||||||
|
|
||||||
float m_particlesAbsoluteTime;
|
|
||||||
|
|
||||||
Vector2 m_downsample;
|
|
||||||
|
|
||||||
Vector4 m_fade_color;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GLfloat x;
|
|
||||||
GLfloat y;
|
|
||||||
GLfloat z;
|
|
||||||
GLfloat u;
|
|
||||||
GLfloat v;
|
|
||||||
} DebugTextVertexData;
|
|
||||||
|
|
||||||
KRDataBlock m_debug_text_vertices;
|
|
||||||
|
|
||||||
// std::string getDebugText();
|
|
||||||
|
|
||||||
uint64_t m_last_frame_start;
|
|
||||||
int m_frame_times[KRAKEN_FPS_AVERAGE_FRAME_COUNT];
|
|
||||||
int m_frame_times_filled;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
//
|
|
||||||
// KRCollider.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
#include "KRCollider.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "KRMesh.h"
|
|
||||||
|
|
||||||
|
|
||||||
KRCollider::KRCollider(KRScene &scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion) : KRNode(scene, collider_name) {
|
|
||||||
m_model_name = model_name;
|
|
||||||
m_layer_mask = layer_mask;
|
|
||||||
m_audio_occlusion = audio_occlusion;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRCollider::~KRCollider() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRCollider::getElementName() {
|
|
||||||
return "collider";
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
|
||||||
e->SetAttribute("mesh", m_model_name.c_str());
|
|
||||||
e->SetAttribute("layer_mask", m_layer_mask);
|
|
||||||
e->SetAttribute("audio_occlusion", m_audio_occlusion);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRCollider::loadXML(tinyxml2::XMLElement *e) {
|
|
||||||
KRNode::loadXML(e);
|
|
||||||
|
|
||||||
m_model_name = e->Attribute("mesh");
|
|
||||||
|
|
||||||
m_layer_mask = 65535;
|
|
||||||
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_layer_mask = 65535;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_audio_occlusion = 1.0f;
|
|
||||||
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_audio_occlusion = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRCollider::loadModel() {
|
|
||||||
if(m_models.size() == 0) {
|
|
||||||
m_models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
|
|
||||||
if(m_models.size() > 0) {
|
|
||||||
getScene().notify_sceneGraphModify(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB KRCollider::getBounds() {
|
|
||||||
loadModel();
|
|
||||||
if(m_models.size() > 0) {
|
|
||||||
return AABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
|
||||||
} else {
|
|
||||||
return AABB::Infinite();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRCollider::lineCast(const Vector3 &v0, const Vector3 &v1, KRHitInfo &hitinfo, unsigned int layer_mask)
|
|
||||||
{
|
|
||||||
if(layer_mask & m_layer_mask ) { // Only test if layer masks have a common bit set
|
|
||||||
loadModel();
|
|
||||||
if(m_models.size()) {
|
|
||||||
if(getBounds().intersectsLine(v0, v1)) {
|
|
||||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
|
||||||
Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1);
|
|
||||||
KRHitInfo hitinfo_model_space;
|
|
||||||
if(hitinfo.didHit()) {
|
|
||||||
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
|
|
||||||
hitinfo_model_space = KRHitInfo(hit_position_model_space, Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal()), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_models[0]->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) {
|
|
||||||
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
|
|
||||||
hitinfo = KRHitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRCollider::rayCast(const Vector3 &v0, const Vector3 &dir, KRHitInfo &hitinfo, unsigned int layer_mask)
|
|
||||||
{
|
|
||||||
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
|
|
||||||
loadModel();
|
|
||||||
if(m_models.size()) {
|
|
||||||
if(getBounds().intersectsRay(v0, dir)) {
|
|
||||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
|
||||||
Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir));
|
|
||||||
KRHitInfo hitinfo_model_space;
|
|
||||||
if(hitinfo.didHit()) {
|
|
||||||
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
|
|
||||||
hitinfo_model_space = KRHitInfo(hit_position_model_space, Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal())), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_models[0]->rayCast(v0_model_space, dir_model_space, hitinfo_model_space)) {
|
|
||||||
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
|
|
||||||
hitinfo = KRHitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRCollider::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, KRHitInfo &hitinfo, unsigned int layer_mask)
|
|
||||||
{
|
|
||||||
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
|
|
||||||
loadModel();
|
|
||||||
if(m_models.size()) {
|
|
||||||
AABB sphereCastBounds = AABB( // TODO - Need to cache this; perhaps encasulate within a "spherecast" class to be passed through these functions
|
|
||||||
Vector3(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius),
|
|
||||||
Vector3(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius)
|
|
||||||
);
|
|
||||||
|
|
||||||
if(getBounds().intersects(sphereCastBounds)) {
|
|
||||||
if(m_models[0]->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) {
|
|
||||||
hitinfo = KRHitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int KRCollider::getLayerMask()
|
|
||||||
{
|
|
||||||
return m_layer_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRCollider::setLayerMask(unsigned int layer_mask)
|
|
||||||
{
|
|
||||||
m_layer_mask = layer_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRCollider::getAudioOcclusion()
|
|
||||||
{
|
|
||||||
return m_audio_occlusion;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRCollider::setAudioOcclusion(float audio_occlusion)
|
|
||||||
{
|
|
||||||
m_audio_occlusion = audio_occlusion;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void KRCollider::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
|
|
||||||
{
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_COLLIDERS) {
|
|
||||||
loadModel();
|
|
||||||
if(m_models.size()) {
|
|
||||||
|
|
||||||
GL_PUSH_GROUP_MARKER("Debug Overlays");
|
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
|
||||||
|
|
||||||
// Enable additive blending
|
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
|
||||||
|
|
||||||
|
|
||||||
// Disable z-buffer write
|
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
|
||||||
|
|
||||||
// Enable z-buffer test
|
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
|
||||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
|
||||||
|
|
||||||
|
|
||||||
for(int i=0; i < m_models[0]->getSubmeshCount(); i++) {
|
|
||||||
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable alpha blending
|
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
|
||||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
|
||||||
}
|
|
||||||
|
|
||||||
GL_POP_GROUP_MARKER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1100
kraken/KRContext.cpp
1100
kraken/KRContext.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,140 +1,225 @@
|
|||||||
//
|
//
|
||||||
// KRContext.h
|
// KRContext.h
|
||||||
// KREngine
|
// Kraken Engine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 12-04-12.
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
//
|
||||||
//
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
#ifndef KREngine_KRContext_h
|
//
|
||||||
#define KREngine_KRContext_h
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
#include "KREngine-common.h"
|
//
|
||||||
#include "KRBundleManager.h"
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
#include "KRSceneManager.h"
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
#include "KRTextureManager.h"
|
// provided with the distribution.
|
||||||
#include "KRMaterialManager.h"
|
//
|
||||||
#include "KRShaderManager.h"
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
#include "KRMeshManager.h"
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
#include "KRAnimationManager.h"
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
#include "KRAnimationCurveManager.h"
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
#include "KRUnknownManager.h"
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
#include "KRStreamer.h"
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
class KRAudioManager;
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
class KRContext {
|
//
|
||||||
public:
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
static int KRENGINE_MAX_SHADER_HANDLES;
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
static int KRENGINE_GPU_MEM_MAX;
|
// or implied, of Kearwood Gilbert.
|
||||||
static int KRENGINE_GPU_MEM_TARGET;
|
//
|
||||||
static int KRENGINE_MAX_TEXTURE_DIM;
|
|
||||||
static int KRENGINE_MIN_TEXTURE_DIM;
|
#pragma once
|
||||||
static int KRENGINE_PRESTREAM_DISTANCE;
|
|
||||||
static int KRENGINE_SYS_ALLOCATION_GRANULARITY;
|
#include "KREngine-common.h"
|
||||||
static int KRENGINE_SYS_PAGE_SIZE;
|
#include "resources/bundle/KRBundleManager.h"
|
||||||
|
#include "resources/scene/KRSceneManager.h"
|
||||||
|
#include "resources/texture/KRTextureManager.h"
|
||||||
KRContext();
|
#include "resources/material/KRMaterialManager.h"
|
||||||
~KRContext();
|
#include "KRPipelineManager.h"
|
||||||
|
#include "KRSamplerManager.h"
|
||||||
void loadResource(const std::string &file_name, KRDataBlock *data);
|
#include "resources/mesh/KRMeshManager.h"
|
||||||
void loadResource(std::string path);
|
#include "resources/animation/KRAnimationManager.h"
|
||||||
|
#include "resources/animation_curve/KRAnimationCurveManager.h"
|
||||||
KRBundleManager *getBundleManager();
|
#include "resources/unknown/KRUnknownManager.h"
|
||||||
KRSceneManager *getSceneManager();
|
#include "resources/shader/KRShaderManager.h"
|
||||||
KRTextureManager *getTextureManager();
|
#include "resources/source/KRSourceManager.h"
|
||||||
KRMaterialManager *getMaterialManager();
|
#include "KRSurfaceManager.h"
|
||||||
KRShaderManager *getShaderManager();
|
#include "KRUniformBufferManager.h"
|
||||||
KRMeshManager *getMeshManager();
|
#include "KRDeviceManager.h"
|
||||||
KRAnimationManager *getAnimationManager();
|
#include "KRDevice.h"
|
||||||
KRAnimationCurveManager *getAnimationCurveManager();
|
#include "KRSurface.h"
|
||||||
KRAudioManager *getAudioManager();
|
|
||||||
KRUnknownManager *getUnknownManager();
|
class KRAudioManager;
|
||||||
|
class KRPresentationThread;
|
||||||
KRCamera *createCamera(int width, int height);
|
class KRStreamerThread;
|
||||||
|
class KRDeviceManager;
|
||||||
enum {
|
class KRUniformBufferManager;
|
||||||
KRENGINE_GL_EXT_texture_storage,
|
class KRSurfaceManager;
|
||||||
KRENGINE_NUM_EXTENSIONS
|
class KRSamplerManager;
|
||||||
};
|
|
||||||
|
class KRContext
|
||||||
static const char * extension_names[KRENGINE_NUM_EXTENSIONS];
|
{
|
||||||
static bool extension_available[KRENGINE_NUM_EXTENSIONS];
|
public:
|
||||||
|
static int KRENGINE_MAX_PIPELINE_HANDLES;
|
||||||
void startFrame(float deltaTime);
|
static int KRENGINE_GPU_MEM_MAX;
|
||||||
void endFrame(float deltaTime);
|
static int KRENGINE_GPU_MEM_TARGET;
|
||||||
|
static int KRENGINE_MAX_TEXTURE_DIM;
|
||||||
long getCurrentFrame() const;
|
static int KRENGINE_MIN_TEXTURE_DIM;
|
||||||
long getLastFullyStreamedFrame() const;
|
static int KRENGINE_PRESTREAM_DISTANCE;
|
||||||
float getAbsoluteTime() const;
|
|
||||||
|
|
||||||
long getAbsoluteTimeMilliseconds();
|
KRContext(const KrInitializeInfo* initializeInfo);
|
||||||
|
~KRContext();
|
||||||
std::vector<KRResource *> getResources();
|
|
||||||
bool getStreamingEnabled();
|
// -=-=-=- Begin: Public API Entry Points -=-=-=-
|
||||||
void setStreamingEnabled(bool enable);
|
KrResult createWindowSurface(const KrCreateWindowSurfaceInfo* createWindowSurfaceInfo);
|
||||||
|
KrResult deleteWindowSurface(const KrDeleteWindowSurfaceInfo* deleteWindowSurfaceInfo);
|
||||||
#if TARGET_OS_IPHONE || TARGET_OS_MAC
|
|
||||||
// XXX This doesn't belong here, and might not actually be needed at all
|
KrResult createBundle(const KrCreateBundleInfo* createBundleInfo);
|
||||||
void getMemoryStats(long &free_memory);
|
KrResult moveToBundle(const KrMoveToBundleInfo* moveToBundleInfo);
|
||||||
#endif
|
KrResult loadResource(const KrLoadResourceInfo* loadResourceInfo);
|
||||||
|
KrResult unloadResource(const KrUnloadResourceInfo* unloadResourceInfo);
|
||||||
typedef enum {
|
KrResult getResourceData(const KrGetResourceDataInfo* getResourceDataInfo, KrGetResourceDataCallback callback);
|
||||||
LOG_LEVEL_INFORMATION,
|
KrResult mapResource(const KrMapResourceInfo* mapResourceInfo);
|
||||||
LOG_LEVEL_WARNING,
|
KrResult unmapResource(const KrUnmapResourceInfo* unmapResourceInfo);
|
||||||
LOG_LEVEL_ERROR
|
KrResult saveResource(const KrSaveResourceInfo* saveResourceInfo);
|
||||||
} log_level;
|
|
||||||
|
KrResult compileAllShaders(const KrCompileAllShadersInfo* pCompileAllShadersInfo);
|
||||||
typedef void log_callback(void *userdata, const std::string &message, log_level level);
|
|
||||||
|
KrResult createScene(const KrCreateSceneInfo* createSceneInfo);
|
||||||
static void SetLogCallback(log_callback *log_callback, void *user_data);
|
KrResult findNodeByName(const KrFindNodeByNameInfo* pFindNodeByNameInfo);
|
||||||
static void Log(log_level level, const std::string message_format, ...);
|
KrResult findAdjacentNodes(const KrFindAdjacentNodesInfo* pFindAdjacentNodesInfo);
|
||||||
|
KrResult setNodeLocalTransform(const KrSetNodeLocalTransformInfo* pSetNodeLocalTransform);
|
||||||
void doStreaming();
|
KrResult setNodeWorldTransform(const KrSetNodeWorldTransformInfo* pSetNodeWorldTransform);
|
||||||
void receivedMemoryWarning();
|
KrResult deleteNode(const KrDeleteNodeInfo* pDeleteNodeInfo);
|
||||||
|
KrResult deleteNodeChildren(const KrDeleteNodeChildrenInfo* pDeleteNodeChildrenInfo);
|
||||||
static void activateStreamerContext();
|
KrResult createNode(const KrCreateNodeInfo* pCreateNodeInfo);
|
||||||
static void activateRenderContext();
|
KrResult updateNode(const KrUpdateNodeInfo* pUpdateNodeInfo);
|
||||||
|
// -=-=-=- End: Public API Entry Points -=-=-=-
|
||||||
#if TARGET_OS_MAC
|
|
||||||
static void attachToView(void *view);
|
// -=-=-=- Start: Helper functions for Public API Entry Points
|
||||||
#endif
|
KrResult getMappedNode(KrSceneNodeMapIndex sceneNodeHandle, KRScene* scene, KRNode** node);
|
||||||
|
KrResult getMappedResource(KrResourceMapIndex resourceHandle, KRResource** resource);
|
||||||
private:
|
|
||||||
KRBundleManager *m_pBundleManager;
|
template<class T> KrResult getMappedResource(KrResourceMapIndex resourceHandle, T** resource)
|
||||||
KRSceneManager *m_pSceneManager;
|
{
|
||||||
KRTextureManager *m_pTextureManager;
|
static_assert(std::is_base_of<KRResource, T>::value, "KRContext::getMappedResource called for class that is not a KRResource subclass");
|
||||||
KRMaterialManager *m_pMaterialManager;
|
*resource = nullptr;
|
||||||
KRShaderManager *m_pShaderManager;
|
|
||||||
KRMeshManager *m_pMeshManager;
|
KRResource* uncastResource = nullptr;
|
||||||
KRAnimationManager *m_pAnimationManager;
|
KrResult res = getMappedResource(resourceHandle, &uncastResource);
|
||||||
KRAnimationCurveManager *m_pAnimationCurveManager;
|
if (res != KR_SUCCESS) {
|
||||||
KRAudioManager *m_pSoundManager;
|
return res;
|
||||||
KRUnknownManager *m_pUnknownManager;
|
}
|
||||||
|
*resource = dynamic_cast<T*>(uncastResource);
|
||||||
void detectExtensions();
|
if (*resource == nullptr) {
|
||||||
bool m_bDetectedExtensions;
|
return KR_ERROR_INCORRECT_TYPE;
|
||||||
|
}
|
||||||
long m_current_frame; // TODO - Does this need to be atomic?
|
return KR_SUCCESS;
|
||||||
long m_last_memory_warning_frame; // TODO - Does this need to be atomic?
|
}
|
||||||
long m_last_fully_streamed_frame; // TODO - Does this need to be atomic?
|
// -=-=-=- End: Helper functions for Public API Entry Points
|
||||||
float m_absolute_time;
|
|
||||||
|
KRResource* loadResource(const std::string& file_name, mimir::Block* data);
|
||||||
#ifdef __APPLE__
|
|
||||||
mach_timebase_info_data_t m_timebase_info;
|
|
||||||
#endif
|
KRBundleManager* getBundleManager();
|
||||||
|
KRSceneManager* getSceneManager();
|
||||||
std::atomic<bool> m_streamingEnabled;
|
KRTextureManager* getTextureManager();
|
||||||
|
KRMaterialManager* getMaterialManager();
|
||||||
|
KRPipelineManager* getPipelineManager();
|
||||||
static log_callback *s_log_callback;
|
KRSamplerManager* getSamplerManager();
|
||||||
static void *s_log_callback_user_data;
|
KRMeshManager* getMeshManager();
|
||||||
|
KRAnimationManager* getAnimationManager();
|
||||||
KRStreamer m_streamer;
|
KRAnimationCurveManager* getAnimationCurveManager();
|
||||||
|
KRAudioManager* getAudioManager();
|
||||||
static void createDeviceContexts();
|
KRUnknownManager* getUnknownManager();
|
||||||
void destroyDeviceContexts();
|
KRShaderManager* getShaderManager();
|
||||||
};
|
KRSourceManager* getSourceManager();
|
||||||
|
KRSurfaceManager* getSurfaceManager();
|
||||||
#endif
|
KRDeviceManager* getDeviceManager();
|
||||||
|
KRUniformBufferManager* getUniformBufferManager();
|
||||||
|
|
||||||
|
void startFrame(float deltaTime);
|
||||||
|
void endFrame(float deltaTime);
|
||||||
|
|
||||||
|
long getCurrentFrame() const;
|
||||||
|
long getLastFullyStreamedFrame() const;
|
||||||
|
float getAbsoluteTime() const;
|
||||||
|
|
||||||
|
long getAbsoluteTimeMilliseconds();
|
||||||
|
|
||||||
|
std::vector<KRResource*> getResources();
|
||||||
|
|
||||||
|
#if TARGET_OS_IPHONE || TARGET_OS_MAC
|
||||||
|
// XXX This doesn't belong here, and might not actually be needed at all
|
||||||
|
void getMemoryStats(long& free_memory);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
LOG_LEVEL_INFORMATION,
|
||||||
|
LOG_LEVEL_WARNING,
|
||||||
|
LOG_LEVEL_ERROR
|
||||||
|
} log_level;
|
||||||
|
|
||||||
|
typedef void log_callback(void* userdata, const std::string& message, log_level level);
|
||||||
|
|
||||||
|
static void SetLogCallback(log_callback* log_callback, void* user_data);
|
||||||
|
static void Log(log_level level, const std::string message_format, ...);
|
||||||
|
|
||||||
|
void doStreaming();
|
||||||
|
void receivedMemoryWarning();
|
||||||
|
|
||||||
|
static std::mutex g_SurfaceInfoMutex;
|
||||||
|
static std::mutex g_DeviceInfoMutex;
|
||||||
|
|
||||||
|
void addResource(KRResource* resource, const std::string& name);
|
||||||
|
void removeResource(KRResource* resource);
|
||||||
|
private:
|
||||||
|
std::unique_ptr<KRBundleManager> m_pBundleManager;
|
||||||
|
std::unique_ptr<KRSceneManager> m_pSceneManager;
|
||||||
|
std::unique_ptr<KRTextureManager> m_pTextureManager;
|
||||||
|
std::unique_ptr<KRMaterialManager> m_pMaterialManager;
|
||||||
|
std::unique_ptr<KRPipelineManager> m_pPipelineManager;
|
||||||
|
std::unique_ptr<KRSamplerManager> m_pSamplerManager;
|
||||||
|
std::unique_ptr<KRMeshManager> m_pMeshManager;
|
||||||
|
std::unique_ptr<KRAnimationManager> m_pAnimationManager;
|
||||||
|
std::unique_ptr<KRAnimationCurveManager> m_pAnimationCurveManager;
|
||||||
|
std::unique_ptr<KRAudioManager> m_pSoundManager;
|
||||||
|
std::unique_ptr<KRUnknownManager> m_pUnknownManager;
|
||||||
|
std::unique_ptr<KRShaderManager> m_pShaderManager;
|
||||||
|
std::unique_ptr<KRSourceManager> m_pSourceManager;
|
||||||
|
std::unique_ptr<KRDeviceManager> m_deviceManager;
|
||||||
|
std::unique_ptr<KRUniformBufferManager> m_uniformBufferManager;
|
||||||
|
std::unique_ptr<KRSurfaceManager> m_surfaceManager;
|
||||||
|
|
||||||
|
KRResource** m_resourceMap;
|
||||||
|
size_t m_resourceMapSize;
|
||||||
|
|
||||||
|
KRNode** m_nodeMap;
|
||||||
|
size_t m_nodeMapSize;
|
||||||
|
|
||||||
|
long m_current_frame; // TODO - Does this need to be atomic?
|
||||||
|
long m_last_memory_warning_frame; // TODO - Does this need to be atomic?
|
||||||
|
long m_last_fully_streamed_frame; // TODO - Does this need to be atomic?
|
||||||
|
float m_absolute_time;
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
mach_timebase_info_data_t m_timebase_info;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// m_streamingEnabled is set to true once all managers are loaded
|
||||||
|
std::atomic<bool> m_streamingEnabled;
|
||||||
|
|
||||||
|
static log_callback* s_log_callback;
|
||||||
|
static void* s_log_callback_user_data;
|
||||||
|
|
||||||
|
unordered_multimap<std::string, KRResource*> m_resources;
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<KRStreamerThread> m_streamerThread;
|
||||||
|
std::unique_ptr<KRPresentationThread> m_presentationThread;
|
||||||
|
|
||||||
|
unordered_map<KrSurfaceMapIndex, KrSurfaceHandle> m_surfaceHandleMap;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,24 +1,47 @@
|
|||||||
//
|
//
|
||||||
// KRContextObject.cpp
|
// KRContextObject.cpp
|
||||||
// KREngine
|
// Kraken Engine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-08-16.
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "KRContextObject.h"
|
#include "KRContextObject.h"
|
||||||
|
|
||||||
KRContextObject::KRContextObject(KRContext &context)
|
KRContextObject::KRContextObject(KRContext& context)
|
||||||
{
|
{
|
||||||
m_pContext = &context;
|
m_pContext = &context;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRContextObject::~KRContextObject()
|
KRContextObject::~KRContextObject()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KRContext &KRContextObject::getContext() const
|
KRContext& KRContextObject::getContext() const
|
||||||
{
|
{
|
||||||
return *m_pContext;
|
return *m_pContext;
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,48 @@
|
|||||||
//
|
//
|
||||||
// KRContextObject.h
|
// KRContextObject.h
|
||||||
// KREngine
|
// Kraken Engine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 2012-08-16.
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef KRCONTEXTOBJECT_H
|
#pragma once
|
||||||
#define KRCONTEXTOBJECT_H
|
|
||||||
|
|
||||||
class KRContext;
|
class KRContext;
|
||||||
|
|
||||||
class KRContextObject {
|
class KRContextObject
|
||||||
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
KRContextObject(KRContext &context);
|
KRContextObject(KRContext& context);
|
||||||
~KRContextObject();
|
~KRContextObject();
|
||||||
|
|
||||||
KRContext &getContext() const;
|
|
||||||
protected:
|
|
||||||
KRContext *m_pContext;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
KRContext& getContext() const;
|
||||||
|
KRContextObject(const KRContextObject&) = delete;
|
||||||
|
KRContextObject& operator=(KRContextObject&) = delete;
|
||||||
|
protected:
|
||||||
|
KRContext* m_pContext;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
//
|
|
||||||
// KRContext-ios.mm
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 11/1/2013.
|
|
||||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#include "KRContext.h"
|
|
||||||
|
|
||||||
EAGLContext *gStreamerContext = nil;
|
|
||||||
EAGLContext *gRenderContext = nil;
|
|
||||||
|
|
||||||
void KRContext::destroyDeviceContexts()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRContext::createDeviceContexts()
|
|
||||||
{
|
|
||||||
if(!gRenderContext) {
|
|
||||||
gRenderContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
|
||||||
gStreamerContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: gRenderContext.sharegroup];
|
|
||||||
|
|
||||||
// FIXME: need to add code check for iOS 7 and also this appears to cause crashing
|
|
||||||
|
|
||||||
//gTextureStreamerContext.multiThreaded = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRContext::activateStreamerContext()
|
|
||||||
{
|
|
||||||
createDeviceContexts();
|
|
||||||
[EAGLContext setCurrentContext: gStreamerContext];
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRContext::activateRenderContext()
|
|
||||||
{
|
|
||||||
createDeviceContexts();
|
|
||||||
[EAGLContext setCurrentContext: gRenderContext];
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
//
|
|
||||||
// KRContext-osx.mm
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 11/1/2013.
|
|
||||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#include "KRContext.h"
|
|
||||||
|
|
||||||
NSOpenGLContext *gStreamerContext = nil;
|
|
||||||
NSOpenGLContext *gRenderContext = nil;
|
|
||||||
|
|
||||||
void KRContext::destroyDeviceContexts()
|
|
||||||
{
|
|
||||||
[gStreamerContext release];
|
|
||||||
[gRenderContext release];
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRContext::createDeviceContexts()
|
|
||||||
{
|
|
||||||
if(gRenderContext == nil) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
NSOpenGLPixelFormatAttribute attribs[] =
|
|
||||||
{
|
|
||||||
NSOpenGLPFADoubleBuffer,
|
|
||||||
NSOpenGLPFADepthSize, 32,
|
|
||||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
NSOpenGLPixelFormatAttribute attribs[] = {
|
|
||||||
NSOpenGLPFADoubleBuffer,
|
|
||||||
NSOpenGLPFAAccelerated,
|
|
||||||
NSOpenGLPFAColorSize, 24,
|
|
||||||
NSOpenGLPFAAlphaSize, 8,
|
|
||||||
NSOpenGLPFADepthSize, 24,
|
|
||||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attribs] autorelease];
|
|
||||||
gRenderContext = [[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: nil ];
|
|
||||||
gStreamerContext = [[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: gRenderContext ];
|
|
||||||
|
|
||||||
// set synch to VBL to eliminate tearing
|
|
||||||
GLint vblSynch = 1;
|
|
||||||
[gRenderContext setValues:&vblSynch forParameter:NSOpenGLCPSwapInterval];
|
|
||||||
|
|
||||||
/*
|
|
||||||
CGLEnable([gRenderContext CGLContextObj], kCGLCESurfaceBackingSize);
|
|
||||||
|
|
||||||
const GLint dim[2] = {1920, 1080};
|
|
||||||
|
|
||||||
[gRenderContext setValues: &dim[0] forParameter: NSOpenGLCPSurfaceBackingSize];
|
|
||||||
[gRenderContext update];
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRContext::activateStreamerContext()
|
|
||||||
{
|
|
||||||
createDeviceContexts();
|
|
||||||
[gStreamerContext makeCurrentContext];
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRContext::activateRenderContext()
|
|
||||||
{
|
|
||||||
createDeviceContexts();
|
|
||||||
[gRenderContext update];
|
|
||||||
[gRenderContext makeCurrentContext];
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRContext::attachToView(void *view)
|
|
||||||
{
|
|
||||||
createDeviceContexts();
|
|
||||||
NSView *v = (NSView *)view;
|
|
||||||
[gRenderContext setView: v];
|
|
||||||
[gRenderContext update];
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
//
|
|
||||||
// KREngine.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _KRDSP_H
|
|
||||||
#define _KRDSP_H
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
namespace KRDSP {
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#define KRDSP_APPLE_VDSP
|
|
||||||
#include <Accelerate/Accelerate.h>
|
|
||||||
#else
|
|
||||||
// Slow, but portable fallback implementation
|
|
||||||
#define KRDSP_SLOW
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(KRDSP_APPLE_VDSP)
|
|
||||||
|
|
||||||
// Apple vDSP
|
|
||||||
typedef DSPSplitComplex SplitComplex;
|
|
||||||
struct FFTWorkspace {
|
|
||||||
FFTSetup setup;
|
|
||||||
|
|
||||||
void create(size_t length);
|
|
||||||
void destroy();
|
|
||||||
FFTWorkspace();
|
|
||||||
~FFTWorkspace();
|
|
||||||
};
|
|
||||||
|
|
||||||
#elif defined(KRDSP_SLOW)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
float *realp;
|
|
||||||
float *imagp;
|
|
||||||
} SplitComplex;
|
|
||||||
|
|
||||||
struct FFTWorkspace {
|
|
||||||
float *sin_table;
|
|
||||||
float *cos_table;
|
|
||||||
|
|
||||||
void create(size_t length);
|
|
||||||
void destroy();
|
|
||||||
FFTWorkspace();
|
|
||||||
~FFTWorkspace();
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
#error Not Implemented
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count);
|
|
||||||
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count);
|
|
||||||
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count);
|
|
||||||
void Scale(float *buffer, float scale, size_t count);
|
|
||||||
void ScaleCopy(const float *src, float scale, float *dest, size_t count);
|
|
||||||
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count);
|
|
||||||
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count);
|
|
||||||
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count);
|
|
||||||
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count);
|
|
||||||
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count);
|
|
||||||
|
|
||||||
} // namespace KRDSP
|
|
||||||
|
|
||||||
#endif // _KRDSP_H
|
|
||||||
@@ -1,207 +0,0 @@
|
|||||||
//
|
|
||||||
// KREngine.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRDSP.h"
|
|
||||||
|
|
||||||
#ifdef KRDSP_SLOW
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
namespace KRDSP {
|
|
||||||
|
|
||||||
FFTWorkspace::FFTWorkspace()
|
|
||||||
{
|
|
||||||
sin_table = nullptr;
|
|
||||||
cos_table = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
FFTWorkspace::~FFTWorkspace()
|
|
||||||
{
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FFTWorkspace::create(size_t length)
|
|
||||||
{
|
|
||||||
size_t size = (length / 2);
|
|
||||||
cos_table = new float[size];
|
|
||||||
sin_table = new float[size];
|
|
||||||
for (int i = 0; i < size / 2; i++) {
|
|
||||||
float a = 2 * M_PI * i / length;
|
|
||||||
cos_table[i] = cos(a);
|
|
||||||
sin_table[i] = sin(a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FFTWorkspace::destroy()
|
|
||||||
{
|
|
||||||
if (sin_table) {
|
|
||||||
delete sin_table;
|
|
||||||
sin_table = nullptr;
|
|
||||||
}
|
|
||||||
if (cos_table) {
|
|
||||||
delete cos_table;
|
|
||||||
cos_table = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
|
||||||
{
|
|
||||||
// Radix-2 Decimation in Time FFT Algorithm
|
|
||||||
// http://en.dsplib.org/content/fft_dec_in_time.html
|
|
||||||
|
|
||||||
// Only power-of-two sizes supported
|
|
||||||
assert((count & (count - 1)) == 0);
|
|
||||||
|
|
||||||
int levels = 0;
|
|
||||||
while (1 << levels <= count) {
|
|
||||||
levels++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
size_t j = 0;
|
|
||||||
for (int k = 0; k < levels; k++) {
|
|
||||||
j <<= 1;
|
|
||||||
j |= ((i >> k) & 1);
|
|
||||||
}
|
|
||||||
if (j > i) {
|
|
||||||
float temp = src->realp[i];
|
|
||||||
src->realp[i] = src->realp[j];
|
|
||||||
src->realp[j] = temp;
|
|
||||||
temp = src->imagp[i];
|
|
||||||
src->imagp[i] = src->imagp[j];
|
|
||||||
src->imagp[j] = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t size = 2; size <= count; size *= 2) {
|
|
||||||
size_t halfsize = size / 2;
|
|
||||||
size_t step = count / size;
|
|
||||||
for (size_t i = 0; i < count; i += size) {
|
|
||||||
for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) {
|
|
||||||
float temp_real = src->realp[j + halfsize] * workspace.cos_table[k];
|
|
||||||
temp_real += src->imagp[j + halfsize] * workspace.sin_table[k];
|
|
||||||
float temp_imag = -src->realp[j + halfsize] * workspace.sin_table[k];
|
|
||||||
temp_imag += src->imagp[j + halfsize] * workspace.cos_table[k];
|
|
||||||
src->realp[j + halfsize] = src->realp[j] - temp_real;
|
|
||||||
src->imagp[j + halfsize] = src->imagp[j] - temp_imag;
|
|
||||||
src->realp[j] += temp_real;
|
|
||||||
src->imagp[j] += temp_imag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
|
||||||
{
|
|
||||||
SplitComplex swapped;
|
|
||||||
swapped.imagp = src->realp;
|
|
||||||
swapped.realp = src->imagp;
|
|
||||||
FFTForward(workspace, &swapped, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count)
|
|
||||||
{
|
|
||||||
const short *r = src;
|
|
||||||
float *w = dest;
|
|
||||||
while (w < dest + destStride * count) {
|
|
||||||
*w = (float)*r;
|
|
||||||
r += srcStride;
|
|
||||||
w += destStride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scale(float *buffer, float scale, size_t count)
|
|
||||||
{
|
|
||||||
float *w = buffer;
|
|
||||||
while (w < buffer + count) {
|
|
||||||
*w *= scale;
|
|
||||||
w++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScaleCopy(const float *src, float scale, float *dest, size_t count)
|
|
||||||
{
|
|
||||||
const float *r = src;
|
|
||||||
float *w = dest;
|
|
||||||
while (w < dest + count) {
|
|
||||||
*w = *r * scale;
|
|
||||||
w++;
|
|
||||||
r++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count)
|
|
||||||
{
|
|
||||||
ScaleCopy(src->realp, scale, dest->realp, count);
|
|
||||||
ScaleCopy(src->imagp, scale, dest->imagp, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
|
|
||||||
{
|
|
||||||
float *w = buffer;
|
|
||||||
float s = scaleStart;
|
|
||||||
while (w < buffer + count) {
|
|
||||||
*w *= s;
|
|
||||||
w++;
|
|
||||||
s += scaleStep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count)
|
|
||||||
{
|
|
||||||
float *w = buffer;
|
|
||||||
const float *r = buffer2;
|
|
||||||
while (w < buffer + bufferStride * count) {
|
|
||||||
*w *= *r;
|
|
||||||
w += bufferStride;
|
|
||||||
r += buffer2Stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
buffer->imagp[i] += buffer2->imagp[i];
|
|
||||||
buffer->realp[i] += buffer2->realp[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
c->realp[i] = a->realp[i] * b->realp[i] - a->imagp[i] * b->imagp[i];
|
|
||||||
c->imagp[i] = a->realp[i] * b->imagp[i] + a->imagp[i] * b->realp[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace KRDSP
|
|
||||||
|
|
||||||
#endif // KRDSP_SLOW
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
//
|
|
||||||
// KREngine.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRDSP.h"
|
|
||||||
|
|
||||||
#ifdef KRDSP_APPLE_VDSP
|
|
||||||
|
|
||||||
#include <Accelerate/Accelerate.h>
|
|
||||||
|
|
||||||
namespace KRDSP {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FFTWorkspace::FFTWorkspace()
|
|
||||||
{
|
|
||||||
setup = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
FFTWorkspace::~FFTWorkspace()
|
|
||||||
{
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FFTWorkspace::create(size_t length)
|
|
||||||
{
|
|
||||||
setup = vDSP_create_fftsetup(length, kFFTRadix2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FFTWorkspace::destroy()
|
|
||||||
{
|
|
||||||
if (setup) {
|
|
||||||
vDSP_destroy_fftsetup(setup);
|
|
||||||
setup = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
|
||||||
{
|
|
||||||
vDSP_fft_zip(workspace.setup, src, 1, count, kFFTDirection_Forward);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
|
||||||
{
|
|
||||||
vDSP_fft_zip(workspace.setup, src, 1, count, kFFTDirection_Inverse);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count)
|
|
||||||
{
|
|
||||||
vDSP_vflt16(src, srcStride, dest, destStride, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scale(float *buffer, float scale, size_t count)
|
|
||||||
{
|
|
||||||
vDSP_vsmul(buffer, 1, &scale, buffer, 1, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScaleCopy(const float *src, float scale, float *dest, size_t count)
|
|
||||||
{
|
|
||||||
vDSP_vsmul(src, 1, &scale, dest, 1, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count)
|
|
||||||
{
|
|
||||||
ScaleCopy(src->realp, scale, dest->realp, count);
|
|
||||||
ScaleCopy(src->imagp, scale, dest->imagp, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
|
|
||||||
{
|
|
||||||
vDSP_vrampmul(buffer, 1, &scaleStart, &scaleStep, buffer, 1, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count)
|
|
||||||
{
|
|
||||||
vDSP_vadd(buffer, bufferStride, buffer2, buffer2Stride, buffer, bufferStride, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
|
|
||||||
{
|
|
||||||
vDSP_zvadd(buffer2, 1, buffer, 1, buffer, 1, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count)
|
|
||||||
{
|
|
||||||
vDSP_zvmul(a, 1, b, 1, c, 1, count, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace KRDSP
|
|
||||||
|
|
||||||
#endif // KRDSP_APPLE_VDSP
|
|
||||||
@@ -1,539 +0,0 @@
|
|||||||
//
|
|
||||||
// KRDataBlock.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRDataBlock.h"
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
#include "KRResource.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#define KRAKEN_MEM_ROUND_DOWN_PAGE(x) ((x) & ~(KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1))
|
|
||||||
#define KRAKEN_MEM_ROUND_UP_PAGE(x) ((((x) - 1) & ~(KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1)) + KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY)
|
|
||||||
|
|
||||||
int m_mapCount = 0;
|
|
||||||
size_t m_mapSize = 0;
|
|
||||||
size_t m_mapOverhead = 0;
|
|
||||||
|
|
||||||
KRDataBlock::KRDataBlock() {
|
|
||||||
m_data = NULL;
|
|
||||||
m_data_size = 0;
|
|
||||||
m_data_offset = 0;
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
m_hPackFile = INVALID_HANDLE_VALUE;
|
|
||||||
m_hFileMapping = NULL;
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
m_fdPackFile = 0;
|
|
||||||
#endif
|
|
||||||
m_fileName = "";
|
|
||||||
m_mmapData = NULL;
|
|
||||||
m_fileOwnerDataBlock = NULL;
|
|
||||||
m_bMalloced = false;
|
|
||||||
m_lockCount = 0;
|
|
||||||
m_bReadOnly = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRDataBlock::KRDataBlock(void *data, size_t size) {
|
|
||||||
m_data = NULL;
|
|
||||||
m_data_size = 0;
|
|
||||||
m_data_offset = 0;
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
m_hPackFile = INVALID_HANDLE_VALUE;
|
|
||||||
m_hFileMapping = NULL;
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
m_fdPackFile = 0;
|
|
||||||
#endif
|
|
||||||
m_fileName = "";
|
|
||||||
m_mmapData = NULL;
|
|
||||||
m_fileOwnerDataBlock = NULL;
|
|
||||||
m_bMalloced = false;
|
|
||||||
m_lockCount = 0;
|
|
||||||
m_bReadOnly = false;
|
|
||||||
load(data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
KRDataBlock::~KRDataBlock() {
|
|
||||||
unload();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unload a file, releasing any mmap'ed file handles or malloc'ed ram that was in use
|
|
||||||
void KRDataBlock::unload()
|
|
||||||
{
|
|
||||||
assert(m_lockCount == 0);
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
if (m_hPackFile != INVALID_HANDLE_VALUE) {
|
|
||||||
CloseHandle(m_hPackFile);
|
|
||||||
m_hPackFile = INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
if(m_fdPackFile) {
|
|
||||||
// Memory mapped file
|
|
||||||
if(m_fileOwnerDataBlock == this) {
|
|
||||||
close(m_fdPackFile);
|
|
||||||
}
|
|
||||||
m_fdPackFile = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(m_data != NULL && m_bMalloced) {
|
|
||||||
// Malloc'ed data
|
|
||||||
free(m_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bMalloced = false;
|
|
||||||
m_data = NULL;
|
|
||||||
m_data_size = 0;
|
|
||||||
m_data_offset = 0;
|
|
||||||
m_fileName = "";
|
|
||||||
m_mmapData = NULL;
|
|
||||||
m_fileOwnerDataBlock = NULL;
|
|
||||||
m_bReadOnly = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encapsulate a pointer. Note - The pointer will not be free'ed
|
|
||||||
bool KRDataBlock::load(void *data, size_t size)
|
|
||||||
{
|
|
||||||
unload();
|
|
||||||
m_data = data;
|
|
||||||
m_data_size = size;
|
|
||||||
m_data_offset = 0;
|
|
||||||
m_bReadOnly = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load a file into memory using mmap. The data pointer will be protected as read-only until append() or expand() is called
|
|
||||||
bool KRDataBlock::load(const std::string &path)
|
|
||||||
{
|
|
||||||
bool success = false;
|
|
||||||
unload();
|
|
||||||
|
|
||||||
struct stat statbuf;
|
|
||||||
m_bReadOnly = true;
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
m_hPackFile = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if(m_hPackFile != INVALID_HANDLE_VALUE) {
|
|
||||||
m_fileOwnerDataBlock = this;
|
|
||||||
m_fileName = KRResource::GetFileBase(path);
|
|
||||||
FILE_STANDARD_INFO fileInfo;
|
|
||||||
if(GetFileInformationByHandleEx(m_hPackFile, FileStandardInfo, &fileInfo, sizeof(fileInfo))) {
|
|
||||||
m_data_size = fileInfo.AllocationSize.QuadPart;
|
|
||||||
m_data_offset = 0;
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
m_fdPackFile = open(path.c_str(), O_RDONLY);
|
|
||||||
if(m_fdPackFile >= 0) {
|
|
||||||
m_fileOwnerDataBlock = this;
|
|
||||||
m_fileName = KRResource::GetFileBase(path);
|
|
||||||
if(fstat(m_fdPackFile, &statbuf) >= 0) {
|
|
||||||
m_data_size = statbuf.st_size;
|
|
||||||
m_data_offset = 0;
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(!success) {
|
|
||||||
// If anything failed, don't leave the object in an invalid state
|
|
||||||
unload();
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a KRDataBlock encapsulating a sub-region of this block. The caller is responsible to free the object.
|
|
||||||
KRDataBlock *KRDataBlock::getSubBlock(int start, int length)
|
|
||||||
{
|
|
||||||
KRDataBlock *new_block = new KRDataBlock();
|
|
||||||
|
|
||||||
new_block->m_data_size = length;
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
if(m_hPackFile) {
|
|
||||||
new_block->m_hPackFile = m_hPackFile;
|
|
||||||
#elif defined(__APPLE)
|
|
||||||
if (m_fdPackFile) {
|
|
||||||
new_block->m_fdPackFile = m_fdPackFile;
|
|
||||||
#else
|
|
||||||
#error Unsupported
|
|
||||||
#endif
|
|
||||||
new_block->m_fileOwnerDataBlock = m_fileOwnerDataBlock;
|
|
||||||
new_block->m_data_offset = start + m_data_offset;
|
|
||||||
} else if(m_bMalloced) {
|
|
||||||
new_block->m_data = (unsigned char *)m_data + start + m_data_offset;
|
|
||||||
}
|
|
||||||
new_block->m_bReadOnly = true;
|
|
||||||
|
|
||||||
return new_block;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a pointer to the start of the data block
|
|
||||||
void *KRDataBlock::getStart() {
|
|
||||||
assertLocked();
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a pointer to the byte after the end of the data block
|
|
||||||
void *KRDataBlock::getEnd() {
|
|
||||||
assertLocked();
|
|
||||||
return (unsigned char *)m_data + m_data_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the size of the data block. Use append() or expand() to make the data block larger
|
|
||||||
size_t KRDataBlock::getSize() const {
|
|
||||||
return m_data_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expand the data block, and switch it to read-write mode. Note - this may result in a mmap'ed file being copied to malloc'ed ram and then closed
|
|
||||||
void KRDataBlock::expand(size_t size)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
if(m_data == NULL && m_hPackFile == 0) {
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
if (m_data == NULL && m_fdPackFile == 0) {
|
|
||||||
#else
|
|
||||||
#error Unsupported
|
|
||||||
#endif
|
|
||||||
// Starting with an empty data block; allocate memory on the heap
|
|
||||||
m_data = malloc(size);
|
|
||||||
assert(m_data != NULL);
|
|
||||||
m_data_size = size;
|
|
||||||
m_data_offset = 0;
|
|
||||||
m_bMalloced = true;
|
|
||||||
} else if(m_bMalloced) {
|
|
||||||
// Starting with a malloc'ed data block; realloc it expand
|
|
||||||
m_data = realloc(m_data, m_data_size + size);
|
|
||||||
m_data_size += size;
|
|
||||||
} else {
|
|
||||||
// Starting with a mmap'ed data block, an encapsulated pointer, or a sub-block; copy it to ram before expanding to avoid updating the original file until save() is called
|
|
||||||
// ... Or starting with a pointer reference, we must make our own copy and must not free the pointer
|
|
||||||
void *pNewData = malloc(m_data_size + size);
|
|
||||||
assert(pNewData != NULL);
|
|
||||||
|
|
||||||
// Copy exising data
|
|
||||||
copy(pNewData);
|
|
||||||
|
|
||||||
// Unload existing data allocation, which is now redundant
|
|
||||||
size_t new_size = m_data_size + size; // We need to store this before unload() as unload() will reset it
|
|
||||||
unload();
|
|
||||||
m_bMalloced = true;
|
|
||||||
m_data = pNewData;
|
|
||||||
m_data_size = new_size;
|
|
||||||
m_data_offset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append data to the end of the block, increasing the size of the block and making it read-write.
|
|
||||||
void KRDataBlock::append(void *data, size_t size) {
|
|
||||||
// Expand the data block
|
|
||||||
expand(size);
|
|
||||||
|
|
||||||
// Fill the new space with the data to append
|
|
||||||
lock();
|
|
||||||
memcpy((unsigned char *)m_data + m_data_size - size, data, size);
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Copy the entire data block to the destination pointer
|
|
||||||
void KRDataBlock::copy(void *dest) {
|
|
||||||
copy(dest, 0, m_data_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy a range of data to the destination pointer
|
|
||||||
void KRDataBlock::copy(void *dest, int start, int count) {
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
if (m_lockCount == 0 && m_hPackFile != 0) {
|
|
||||||
// Optimization: If we haven't mmap'ed or malloced the data already, pread() it directly from the file into the buffer
|
|
||||||
|
|
||||||
LARGE_INTEGER distance;
|
|
||||||
distance.QuadPart = start + m_data_offset;
|
|
||||||
bool success = SetFilePointerEx(m_hPackFile, distance, NULL, FILE_BEGIN);
|
|
||||||
assert(success);
|
|
||||||
|
|
||||||
void *w = dest;
|
|
||||||
DWORD bytes_remaining = count;
|
|
||||||
while(bytes_remaining > 0) {
|
|
||||||
DWORD bytes_read = 0;
|
|
||||||
success = ReadFile(m_hPackFile, w, bytes_remaining, &bytes_read, NULL);
|
|
||||||
assert(success);
|
|
||||||
assert(bytes_read > 0);
|
|
||||||
w = (unsigned char *)w + bytes_read;
|
|
||||||
bytes_remaining -= bytes_read;
|
|
||||||
}
|
|
||||||
assert(bytes_remaining == 0);
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
if(m_lockCount == 0 && m_fdPackFile != 0) {
|
|
||||||
// Optimization: If we haven't mmap'ed or malloced the data already, pread() it directly from the file into the buffer
|
|
||||||
ssize_t r = pread(m_fdPackFile, dest, count, start + m_data_offset);
|
|
||||||
assert(r != -1);
|
|
||||||
#else
|
|
||||||
#error Unsupported
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
lock();
|
|
||||||
memcpy((unsigned char *)dest, (unsigned char *)m_data + start, count);
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append data to the end of the block, increasing the size of the block and making it read-write.
|
|
||||||
void KRDataBlock::append(KRDataBlock &data) {
|
|
||||||
data.lock();
|
|
||||||
append(data.getStart(), data.getSize());
|
|
||||||
data.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append string to the end of the block, increasing the size of the block and making it read-write. The null terminating character is included
|
|
||||||
void KRDataBlock::append(const std::string &s)
|
|
||||||
{
|
|
||||||
const char *szText = s.c_str();
|
|
||||||
append((void *)szText, strlen(szText)+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the data to a file.
|
|
||||||
bool KRDataBlock::save(const std::string& path) {
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
bool success = true;
|
|
||||||
HANDLE hNewFile = INVALID_HANDLE_VALUE;
|
|
||||||
HANDLE hFileMapping = NULL;
|
|
||||||
void *pNewData = NULL;
|
|
||||||
|
|
||||||
hNewFile = CreateFile(path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (hNewFile == INVALID_HANDLE_VALUE) {
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
hFileMapping = CreateFileMappingFromApp(hNewFile, NULL, PAGE_READWRITE, m_data_size, NULL);
|
|
||||||
if (hFileMapping == NULL) {
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
pNewData = MapViewOfFileFromApp(hFileMapping, FILE_MAP_WRITE, 0, m_data_size);
|
|
||||||
if (pNewData == NULL) {
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
// Copy data to new file
|
|
||||||
copy(pNewData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pNewData != NULL) {
|
|
||||||
UnmapViewOfFile(pNewData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hFileMapping != NULL) {
|
|
||||||
CloseHandle(hFileMapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hNewFile != INVALID_HANDLE_VALUE) {
|
|
||||||
CloseHandle(hNewFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
int fdNewFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
|
|
||||||
if(fdNewFile == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seek to end of file and write a byte to enlarge it
|
|
||||||
lseek(fdNewFile, m_data_size-1, SEEK_SET);
|
|
||||||
write(fdNewFile, "", 1);
|
|
||||||
|
|
||||||
// Now map it...
|
|
||||||
void *pNewData = mmap(0, m_data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdNewFile, 0);
|
|
||||||
if(pNewData == (caddr_t) -1) {
|
|
||||||
close(fdNewFile);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(m_data != NULL) {
|
|
||||||
// Copy data to new file
|
|
||||||
copy(pNewData);
|
|
||||||
|
|
||||||
// Unmap the new file
|
|
||||||
munmap(pNewData, m_data_size);
|
|
||||||
|
|
||||||
// Close the new file
|
|
||||||
close(fdNewFile);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
#else
|
|
||||||
#error Unsupported
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get contents as a string
|
|
||||||
std::string KRDataBlock::getString()
|
|
||||||
{
|
|
||||||
KRDataBlock b;
|
|
||||||
b.append(*this);
|
|
||||||
b.append((void *)"\0", 1); // Ensure data is null terminated, to read as a string safely
|
|
||||||
b.lock();
|
|
||||||
std::string ret = std::string((char *)b.getStart());
|
|
||||||
b.unlock();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lock the memory, forcing it to be loaded into a contiguous block of address space
|
|
||||||
void KRDataBlock::lock()
|
|
||||||
{
|
|
||||||
if(m_lockCount == 0) {
|
|
||||||
|
|
||||||
// Memory mapped file; ensure data is mapped to ram
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
if(m_hFileMapping) {
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
if(m_fdPackFile) {
|
|
||||||
#else
|
|
||||||
#error Unsupported
|
|
||||||
#endif
|
|
||||||
if(m_data_size < KRENGINE_MIN_MMAP) {
|
|
||||||
m_data = malloc(m_data_size);
|
|
||||||
assert(m_data != NULL);
|
|
||||||
copy(m_data);
|
|
||||||
} else {
|
|
||||||
size_t alignment_offset = m_data_offset & (KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1);
|
|
||||||
assert(m_mmapData == NULL);
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
m_hFileMapping = CreateFileMappingFromApp(m_hPackFile, NULL, m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE, m_data_size, NULL);
|
|
||||||
assert(m_hFileMapping != NULL);
|
|
||||||
|
|
||||||
m_mmapData = MapViewOfFileFromApp(m_hPackFile, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, m_data_offset - alignment_offset, m_data_size + alignment_offset);
|
|
||||||
assert(m_mmapData != NULL);
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
//fprintf(stderr, "KRDataBlock::lock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount);
|
|
||||||
// Round m_data_offset down to the next memory page, as required by mmap
|
|
||||||
|
|
||||||
if ((m_mmapData = mmap(0, m_data_size + alignment_offset, m_bReadOnly ? PROT_READ : PROT_WRITE, MAP_SHARED, m_fdPackFile, m_data_offset - alignment_offset)) == (caddr_t) -1) {
|
|
||||||
int iError = errno;
|
|
||||||
switch(iError) {
|
|
||||||
case EACCES:
|
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EACCES");
|
|
||||||
break;
|
|
||||||
case EBADF:
|
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EBADF");
|
|
||||||
break;
|
|
||||||
case EMFILE:
|
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EMFILE");
|
|
||||||
break;
|
|
||||||
case EINVAL:
|
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EINVAL");
|
|
||||||
break;
|
|
||||||
case ENOMEM:
|
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with ENOMEM");
|
|
||||||
break;
|
|
||||||
case ENXIO:
|
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with ENXIO");
|
|
||||||
break;
|
|
||||||
case EOVERFLOW:
|
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EOVERFLOW");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with errno: %i", iError);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
assert(false); // mmap() failed.
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#error Unsupported
|
|
||||||
#endif
|
|
||||||
m_mapCount++;
|
|
||||||
m_mapSize += m_data_size;
|
|
||||||
m_mapOverhead += alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset;
|
|
||||||
// fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead);
|
|
||||||
m_data = (unsigned char *)m_mmapData + alignment_offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_lockCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlock the memory, releasing the address space for use by other allocations
|
|
||||||
void KRDataBlock::unlock()
|
|
||||||
{
|
|
||||||
// We expect that the data block was previously locked
|
|
||||||
assertLocked();
|
|
||||||
|
|
||||||
|
|
||||||
if(m_lockCount == 1) {
|
|
||||||
|
|
||||||
// Memory mapped file; ensure data is unmapped from ram
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
if (m_hPackFile) {
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
if(m_fdPackFile) {
|
|
||||||
#else
|
|
||||||
#error Undefined
|
|
||||||
#endif
|
|
||||||
if(m_data_size < KRENGINE_MIN_MMAP) {
|
|
||||||
free(m_data);
|
|
||||||
m_data = NULL;
|
|
||||||
} else {
|
|
||||||
//fprintf(stderr, "KRDataBlock::unlock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount);
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
if (m_mmapData != NULL) {
|
|
||||||
UnmapViewOfFile(m_mmapData);
|
|
||||||
}
|
|
||||||
if(m_hFileMapping != NULL) {
|
|
||||||
CloseHandle(m_hFileMapping);
|
|
||||||
m_hFileMapping = NULL;
|
|
||||||
}
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
munmap(m_mmapData, m_data_size);
|
|
||||||
#else
|
|
||||||
#error Undefined
|
|
||||||
#endif
|
|
||||||
m_data = NULL;
|
|
||||||
m_mmapData = NULL;
|
|
||||||
m_mapCount--;
|
|
||||||
m_mapSize -= m_data_size;
|
|
||||||
size_t alignment_offset = m_data_offset & (KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1);
|
|
||||||
m_mapOverhead -= alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset;
|
|
||||||
// fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_lockCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert if not locked
|
|
||||||
void KRDataBlock::assertLocked()
|
|
||||||
{
|
|
||||||
assert(m_lockCount > 0);
|
|
||||||
}
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
//
|
|
||||||
// KRDataBlock.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KREngine_KRDataBlock_h
|
|
||||||
#define KREngine_KRDataBlock_h
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
#include <Windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define KRENGINE_MIN_MMAP 32768
|
|
||||||
|
|
||||||
class KRDataBlock {
|
|
||||||
public:
|
|
||||||
KRDataBlock();
|
|
||||||
KRDataBlock(void *data, size_t size);
|
|
||||||
~KRDataBlock();
|
|
||||||
|
|
||||||
// Encapsulate a pointer. Note - The pointer will not be free'ed
|
|
||||||
bool load(void *data, size_t size);
|
|
||||||
|
|
||||||
// Load a file into memory using mmap. The data pointer will be protected as read-only until append() or expand() is called
|
|
||||||
bool load(const std::string &path);
|
|
||||||
|
|
||||||
// Save the data to a file.
|
|
||||||
bool save(const std::string& path);
|
|
||||||
|
|
||||||
// Create a KRDataBlock encapsulating a sub-region of this block. The caller is responsible to free the object.
|
|
||||||
KRDataBlock *getSubBlock(int start, int length);
|
|
||||||
|
|
||||||
// Append data to the end of the block, increasing the size of the block and making it read-write.
|
|
||||||
void append(void *data, size_t size);
|
|
||||||
|
|
||||||
// Append data to the end of the block, increasing the size of the block and making it read-write.
|
|
||||||
void append(KRDataBlock &data);
|
|
||||||
|
|
||||||
// Append string to the end of the block, increasing the size of the block and making it read-write. The null terminating character is included
|
|
||||||
void append(const std::string &s);
|
|
||||||
|
|
||||||
// Expand or shrink the data block, and switch it to read-write mode. Note - this may result in a mmap'ed file being copied to malloc'ed ram and then closed
|
|
||||||
void expand(size_t size);
|
|
||||||
|
|
||||||
// Unload a file, releasing any mmap'ed file handles or malloc'ed ram that was in use
|
|
||||||
void unload();
|
|
||||||
|
|
||||||
// Return a pointer to the start of the data block
|
|
||||||
void *getStart();
|
|
||||||
|
|
||||||
// Return a pointer to the one byte after the end of the data block
|
|
||||||
void *getEnd();
|
|
||||||
|
|
||||||
// Return the size of the data block. Use append() or expand() to make the data block larger
|
|
||||||
size_t getSize() const;
|
|
||||||
|
|
||||||
// Get the contents as a string
|
|
||||||
std::string getString();
|
|
||||||
|
|
||||||
// Copy the entire data block to the destination pointer
|
|
||||||
void copy(void *dest);
|
|
||||||
|
|
||||||
// Copy a range of data to the destination pointer
|
|
||||||
void copy(void *dest, int start, int count);
|
|
||||||
|
|
||||||
// Lock the memory, forcing it to be loaded into a contiguous block of address space
|
|
||||||
void lock();
|
|
||||||
|
|
||||||
// Unlock the memory, releasing the address space for use by other allocations
|
|
||||||
void unlock();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void *m_data;
|
|
||||||
size_t m_data_size;
|
|
||||||
size_t m_data_offset;
|
|
||||||
|
|
||||||
// For memory mapped objects:
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
HANDLE m_hPackFile;
|
|
||||||
HANDLE m_hFileMapping;
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
int m_fdPackFile;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string m_fileName;
|
|
||||||
KRDataBlock *m_fileOwnerDataBlock;
|
|
||||||
void *m_mmapData;
|
|
||||||
|
|
||||||
// For malloc'ed objects:
|
|
||||||
bool m_bMalloced;
|
|
||||||
|
|
||||||
// Lock refcount
|
|
||||||
int m_lockCount;
|
|
||||||
|
|
||||||
// Read-only allocation
|
|
||||||
bool m_bReadOnly;
|
|
||||||
|
|
||||||
// Assert if not locked
|
|
||||||
void assertLocked();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
905
kraken/KRDevice.cpp
Normal file
905
kraken/KRDevice.cpp
Normal file
@@ -0,0 +1,905 @@
|
|||||||
|
//
|
||||||
|
// KRDevice.cpp
|
||||||
|
// Kraken Engine
|
||||||
|
//
|
||||||
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "KRDevice.h"
|
||||||
|
#include "KRDeviceManager.h"
|
||||||
|
|
||||||
|
using namespace mimir;
|
||||||
|
using namespace hydra;
|
||||||
|
|
||||||
|
KRDevice::KRDevice(KRContext& context, const VkPhysicalDevice& device)
|
||||||
|
: KRContextObject(context)
|
||||||
|
, m_device(device)
|
||||||
|
, m_logicalDevice(VK_NULL_HANDLE)
|
||||||
|
, m_deviceProperties{}
|
||||||
|
, m_deviceFeatures{}
|
||||||
|
, m_graphicsFamilyQueueIndex(0)
|
||||||
|
, m_graphicsQueue(VK_NULL_HANDLE)
|
||||||
|
, m_computeFamilyQueueIndex(0)
|
||||||
|
, m_computeQueue(VK_NULL_HANDLE)
|
||||||
|
, m_transferFamilyQueueIndex(0)
|
||||||
|
, m_transferQueue(VK_NULL_HANDLE)
|
||||||
|
, m_graphicsCommandPool(VK_NULL_HANDLE)
|
||||||
|
, m_computeCommandPool(VK_NULL_HANDLE)
|
||||||
|
, m_allocator(VK_NULL_HANDLE)
|
||||||
|
, m_streamingStagingBuffer{}
|
||||||
|
, m_graphicsStagingBuffer{}
|
||||||
|
, m_descriptorPool(VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KRDevice::~KRDevice()
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::StagingBufferInfo::destroy(VmaAllocator& allocator)
|
||||||
|
{
|
||||||
|
if (data) {
|
||||||
|
vmaUnmapMemory(allocator, allocation);
|
||||||
|
data = nullptr;
|
||||||
|
}
|
||||||
|
if (buffer) {
|
||||||
|
vmaDestroyBuffer(allocator, buffer, allocation);
|
||||||
|
size = 0;
|
||||||
|
buffer = VK_NULL_HANDLE;
|
||||||
|
allocation = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::destroy()
|
||||||
|
{
|
||||||
|
if (m_descriptorPool != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyDescriptorPool(m_logicalDevice, m_descriptorPool, nullptr);
|
||||||
|
m_descriptorPool = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
m_streamingStagingBuffer.destroy(m_allocator);
|
||||||
|
m_graphicsStagingBuffer.destroy(m_allocator);
|
||||||
|
|
||||||
|
if (m_graphicsCommandPool != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyCommandPool(m_logicalDevice, m_graphicsCommandPool, nullptr);
|
||||||
|
m_graphicsCommandPool = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_computeCommandPool != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyCommandPool(m_logicalDevice, m_computeCommandPool, nullptr);
|
||||||
|
m_computeCommandPool = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_transferCommandPool != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyCommandPool(m_logicalDevice, m_transferCommandPool, nullptr);
|
||||||
|
m_transferCommandPool = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_logicalDevice != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyDevice(m_logicalDevice, nullptr);
|
||||||
|
m_logicalDevice = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_allocator != VK_NULL_HANDLE) {
|
||||||
|
vmaDestroyAllocator(m_allocator);
|
||||||
|
m_allocator = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDevice::getAndCheckDeviceCapabilities(const std::vector<const char*>& deviceExtensions)
|
||||||
|
{
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceProperties(m_device, &m_deviceProperties);
|
||||||
|
vkGetPhysicalDeviceFeatures(m_device, &m_deviceFeatures);
|
||||||
|
uint32_t extensionCount;
|
||||||
|
vkEnumerateDeviceExtensionProperties(m_device, nullptr, &extensionCount, nullptr);
|
||||||
|
|
||||||
|
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
|
||||||
|
vkEnumerateDeviceExtensionProperties(m_device, nullptr, &extensionCount, availableExtensions.data());
|
||||||
|
|
||||||
|
std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
|
||||||
|
|
||||||
|
for (const auto& extension : availableExtensions) {
|
||||||
|
requiredExtensions.erase(extension.extensionName);
|
||||||
|
}
|
||||||
|
if (!requiredExtensions.empty()) {
|
||||||
|
// Missing a required extension
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!m_deviceFeatures.samplerAnisotropy) {
|
||||||
|
// Anisotropy feature required
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDevice::selectQueueFamilies()
|
||||||
|
{
|
||||||
|
uint32_t queueFamilyCount = 0;
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(m_device, &queueFamilyCount, nullptr);
|
||||||
|
|
||||||
|
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(m_device, &queueFamilyCount, queueFamilies.data());
|
||||||
|
|
||||||
|
uint32_t graphicsFamilyQueue = -1;
|
||||||
|
uint32_t computeFamilyQueue = -1;
|
||||||
|
uint32_t transferFamilyQueue = -1;
|
||||||
|
|
||||||
|
// First, select the transfer queue
|
||||||
|
for (int i = 0; i < queueFamilies.size(); i++) {
|
||||||
|
const VkQueueFamilyProperties& queueFamily = queueFamilies[i];
|
||||||
|
if ((queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT) == 0) {
|
||||||
|
// This queue does not support transfers. Skip it.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (transferFamilyQueue == -1) {
|
||||||
|
// If we don't already have a transfer queue, take anything that supports VK_QUEUE_TRANSFER_BIT
|
||||||
|
transferFamilyQueue = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkQueueFlags priorFlags = queueFamilies[transferFamilyQueue].queueFlags;
|
||||||
|
if ((priorFlags & VK_QUEUE_GRAPHICS_BIT) > (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)) {
|
||||||
|
// This is a better queue, as it is specifically for transfers and not graphics
|
||||||
|
transferFamilyQueue = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((priorFlags & VK_QUEUE_COMPUTE_BIT) > (queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT)) {
|
||||||
|
// This is a better queue, as it is specifically for transfers and not graphics
|
||||||
|
transferFamilyQueue = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second, select the compute transfer queue
|
||||||
|
for (int i = 0; i < queueFamilies.size(); i++) {
|
||||||
|
const VkQueueFamilyProperties& queueFamily = queueFamilies[i];
|
||||||
|
if ((queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT) == 0) {
|
||||||
|
// This queue does not support compute. Skip it.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (computeFamilyQueue == -1) {
|
||||||
|
// If we don't already have a compute queue, take anything that supports VK_QUEUE_COMPUTE_BIT
|
||||||
|
computeFamilyQueue = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (computeFamilyQueue == transferFamilyQueue) {
|
||||||
|
// Avoid sharing a compute queue with the asset streaming
|
||||||
|
computeFamilyQueue = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
VkQueueFlags priorFlags = queueFamilies[computeFamilyQueue].queueFlags;
|
||||||
|
if ((priorFlags & VK_QUEUE_GRAPHICS_BIT) > (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)) {
|
||||||
|
// This is a better queue, as it is specifically for compute and not graphics
|
||||||
|
computeFamilyQueue = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < queueFamilies.size(); i++) {
|
||||||
|
const VkQueueFamilyProperties& queueFamily = queueFamilies[i];
|
||||||
|
if ((queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0) {
|
||||||
|
// This queue does not support graphics. Skip it.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (graphicsFamilyQueue == -1) {
|
||||||
|
// If we don't already have a graphics queue, take anything that supports VK_QUEUE_GRAPHICS_BIT
|
||||||
|
graphicsFamilyQueue = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (graphicsFamilyQueue == transferFamilyQueue) {
|
||||||
|
// Avoid sharing a graphics queue with the asset streaming
|
||||||
|
graphicsFamilyQueue = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (graphicsFamilyQueue == computeFamilyQueue) {
|
||||||
|
// Avoid sharing a graphics queue with compute
|
||||||
|
graphicsFamilyQueue = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (graphicsFamilyQueue == -1) {
|
||||||
|
// No graphics queue family, not suitable
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (computeFamilyQueue == -1) {
|
||||||
|
// No compute queue family, not suitable
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transferFamilyQueue == -1) {
|
||||||
|
// No transfer queue family, not suitable
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_graphicsFamilyQueueIndex = graphicsFamilyQueue;
|
||||||
|
m_computeFamilyQueueIndex = computeFamilyQueue;
|
||||||
|
m_transferFamilyQueueIndex = transferFamilyQueue;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDevice::initDeviceAndQueues(const std::vector<const char*>& deviceExtensions)
|
||||||
|
{
|
||||||
|
VkDeviceQueueCreateInfo queueCreateInfo[3]{};
|
||||||
|
int queueCount = 1;
|
||||||
|
float queuePriority = 1.0f;
|
||||||
|
queueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
|
queueCreateInfo[0].queueFamilyIndex = m_graphicsFamilyQueueIndex;
|
||||||
|
queueCreateInfo[0].queueCount = 1;
|
||||||
|
queueCreateInfo[0].pQueuePriorities = &queuePriority;
|
||||||
|
if (m_graphicsFamilyQueueIndex != m_computeFamilyQueueIndex) {
|
||||||
|
queueCount++;
|
||||||
|
queueCreateInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
|
queueCreateInfo[1].queueFamilyIndex = m_computeFamilyQueueIndex;
|
||||||
|
queueCreateInfo[1].queueCount = 1;
|
||||||
|
queueCreateInfo[1].pQueuePriorities = &queuePriority;
|
||||||
|
}
|
||||||
|
if (m_transferFamilyQueueIndex != m_graphicsFamilyQueueIndex && m_transferFamilyQueueIndex != m_computeFamilyQueueIndex) {
|
||||||
|
queueCount++;
|
||||||
|
queueCreateInfo[2].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
|
queueCreateInfo[2].queueFamilyIndex = m_transferFamilyQueueIndex;
|
||||||
|
queueCreateInfo[2].queueCount = 1;
|
||||||
|
queueCreateInfo[2].pQueuePriorities = &queuePriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDeviceCreateInfo deviceCreateInfo{};
|
||||||
|
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
|
deviceCreateInfo.pQueueCreateInfos = queueCreateInfo;
|
||||||
|
deviceCreateInfo.queueCreateInfoCount = queueCount;
|
||||||
|
VkPhysicalDeviceFeatures deviceFeatures{};
|
||||||
|
deviceFeatures.samplerAnisotropy = VK_TRUE;
|
||||||
|
deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
|
||||||
|
deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
|
||||||
|
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
|
||||||
|
if (vkCreateDevice(m_device, &deviceCreateInfo, nullptr, &m_logicalDevice) != VK_SUCCESS) {
|
||||||
|
// TODO - Log a warning...
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
vkGetDeviceQueue(m_logicalDevice, m_graphicsFamilyQueueIndex, 0, &m_graphicsQueue);
|
||||||
|
vkGetDeviceQueue(m_logicalDevice, m_computeFamilyQueueIndex, 0, &m_computeQueue);
|
||||||
|
vkGetDeviceQueue(m_logicalDevice, m_transferFamilyQueueIndex, 0, &m_transferQueue);
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
setDebugLabel(m_graphicsQueue, "Graphics");
|
||||||
|
setDebugLabel(m_computeQueue, "Compute");
|
||||||
|
setDebugLabel(m_transferQueue, "Transfer");
|
||||||
|
#endif // KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDevice::initCommandPools()
|
||||||
|
{
|
||||||
|
VkCommandPoolCreateInfo poolInfo{};
|
||||||
|
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
|
poolInfo.queueFamilyIndex = m_graphicsFamilyQueueIndex;
|
||||||
|
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||||
|
|
||||||
|
if (vkCreateCommandPool(m_logicalDevice, &poolInfo, nullptr, &m_graphicsCommandPool) != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
poolInfo.queueFamilyIndex = m_computeFamilyQueueIndex;
|
||||||
|
if (vkCreateCommandPool(m_logicalDevice, &poolInfo, nullptr, &m_computeCommandPool) != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
poolInfo.queueFamilyIndex = m_transferFamilyQueueIndex;
|
||||||
|
if (vkCreateCommandPool(m_logicalDevice, &poolInfo, nullptr, &m_transferCommandPool) != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDevice::initCommandBuffers()
|
||||||
|
{
|
||||||
|
const int kMaxGraphicsCommandBuffers = KRENGINE_MAX_FRAMES_IN_FLIGHT;
|
||||||
|
m_graphicsCommandBuffers.resize(kMaxGraphicsCommandBuffers);
|
||||||
|
|
||||||
|
const int kMaxComputeCommandBuffers = 4; // TODO - This needs to be dynamic?
|
||||||
|
m_computeCommandBuffers.resize(kMaxComputeCommandBuffers);
|
||||||
|
|
||||||
|
const int kMaxTransferCommandBuffers = 4; // TODO - This needs to be dynamic?
|
||||||
|
m_transferCommandBuffers.resize(kMaxTransferCommandBuffers);
|
||||||
|
|
||||||
|
VkCommandBufferAllocateInfo allocInfo{};
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
|
allocInfo.commandPool = m_graphicsCommandPool;
|
||||||
|
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
|
allocInfo.commandBufferCount = (uint32_t)m_graphicsCommandBuffers.size();
|
||||||
|
|
||||||
|
if (vkAllocateCommandBuffers(m_logicalDevice, &allocInfo, m_graphicsCommandBuffers.data()) != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
allocInfo.commandPool = m_computeCommandPool;
|
||||||
|
allocInfo.commandBufferCount = (uint32_t)m_computeCommandBuffers.size();
|
||||||
|
if (vkAllocateCommandBuffers(m_logicalDevice, &allocInfo, m_computeCommandBuffers.data()) != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
allocInfo.commandPool = m_transferCommandPool;
|
||||||
|
allocInfo.commandBufferCount = (uint32_t)m_transferCommandBuffers.size();
|
||||||
|
if (vkAllocateCommandBuffers(m_logicalDevice, &allocInfo, m_transferCommandBuffers.data()) != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
const size_t kMaxLabelSize = 64;
|
||||||
|
char debug_label[kMaxLabelSize];
|
||||||
|
for (int i = 0; i < m_transferCommandBuffers.size(); i++) {
|
||||||
|
snprintf(debug_label, kMaxLabelSize, "Transfer %i", i);
|
||||||
|
setDebugLabel(m_transferCommandBuffers[i], debug_label);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < m_graphicsCommandBuffers.size(); i++) {
|
||||||
|
snprintf(debug_label, kMaxLabelSize, "Presentation %i", i);
|
||||||
|
setDebugLabel(m_graphicsCommandBuffers[i], debug_label);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < m_computeCommandBuffers.size(); i++) {
|
||||||
|
snprintf(debug_label, kMaxLabelSize, "Compute %i", i);
|
||||||
|
setDebugLabel(m_computeCommandBuffers[i], debug_label);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDevice::initAllocator()
|
||||||
|
{
|
||||||
|
// Create Vulkan Memory Allocator instance for this device
|
||||||
|
|
||||||
|
// We are dynamically linking Vulkan, so we need to give VMA some hints
|
||||||
|
// on finding the function pointers
|
||||||
|
VmaVulkanFunctions vmaVulkanFunctions{};
|
||||||
|
vmaVulkanFunctions.vkGetInstanceProcAddr = vkGetInstanceProcAddr;
|
||||||
|
vmaVulkanFunctions.vkGetDeviceProcAddr = vkGetDeviceProcAddr;
|
||||||
|
|
||||||
|
VmaAllocatorCreateInfo vmaCreateInfo{};
|
||||||
|
vmaCreateInfo.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT;
|
||||||
|
// TODO - Hook vmaCreateInfo.pAllocationCallbacks;
|
||||||
|
|
||||||
|
vmaCreateInfo.physicalDevice = m_device;
|
||||||
|
vmaCreateInfo.device = m_logicalDevice;
|
||||||
|
vmaCreateInfo.instance = m_pContext->getDeviceManager()->getVulkanInstance();
|
||||||
|
vmaCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;
|
||||||
|
vmaCreateInfo.pVulkanFunctions = &vmaVulkanFunctions;
|
||||||
|
if (vmaCreateAllocator(&vmaCreateInfo, &m_allocator) != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDevice::initStagingBuffers()
|
||||||
|
{
|
||||||
|
// Create Staging Buffer for the transfer queue.
|
||||||
|
// This will be used for asynchronous asset streaming in the streamer thread.
|
||||||
|
// Start with a 256MB staging buffer.
|
||||||
|
// TODO - Dynamically size staging buffer using heuristics
|
||||||
|
size_t size = size_t(256) * 1024 * 1024;
|
||||||
|
if (!initStagingBuffer(size, &m_streamingStagingBuffer
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
, "Streaming Staging Buffer"
|
||||||
|
#endif // KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Staging Buffer for the graphics queue.
|
||||||
|
// This will be used for uploading assets procedurally generated while recording the graphics command buffer.
|
||||||
|
// Start with a 256MB staging buffer.
|
||||||
|
// TODO - Dynamically size staging buffer using heuristics
|
||||||
|
size = size_t(256) * 1024 * 1024;
|
||||||
|
if (!initStagingBuffer(size,
|
||||||
|
&m_graphicsStagingBuffer
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
, "Graphics Staging Buffer"
|
||||||
|
#endif // KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDevice::initStagingBuffer(VkDeviceSize size, StagingBufferInfo* info
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
, const char* debug_label
|
||||||
|
#endif // KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!createBuffer(
|
||||||
|
size,
|
||||||
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
|
||||||
|
&info->buffer,
|
||||||
|
&info->allocation
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
, debug_label
|
||||||
|
#endif // KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (vmaMapMemory(m_allocator, info->allocation, &info->data) != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
info->size = size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDevice::initDescriptorPool()
|
||||||
|
{
|
||||||
|
// TODO - Vulkan Refactoring - These values need to be dynamic
|
||||||
|
// TODO - Perhaps we should dynamically creaate new pools as needed
|
||||||
|
const size_t kMaxDescriptorSets = 64;
|
||||||
|
const size_t kMaxUniformBufferDescriptors = 1024;
|
||||||
|
const size_t kMaxImageSamplerDescriptors = 1024;
|
||||||
|
|
||||||
|
VkDescriptorPoolSize poolSizes[2] = {};
|
||||||
|
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
poolSizes[0].descriptorCount = static_cast<uint32_t>(kMaxUniformBufferDescriptors);
|
||||||
|
|
||||||
|
poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
poolSizes[1].descriptorCount = static_cast<uint32_t>(kMaxImageSamplerDescriptors);
|
||||||
|
|
||||||
|
VkDescriptorPoolCreateInfo poolInfo{};
|
||||||
|
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||||
|
poolInfo.poolSizeCount = 2;
|
||||||
|
poolInfo.pPoolSizes = poolSizes;
|
||||||
|
poolInfo.maxSets = static_cast<uint32_t>(kMaxDescriptorSets);
|
||||||
|
|
||||||
|
if (vkCreateDescriptorPool(m_logicalDevice, &poolInfo, nullptr, &m_descriptorPool) != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::createDescriptorSets(const std::vector<VkDescriptorSetLayout>& layouts, std::vector<VkDescriptorSet>& descriptorSets)
|
||||||
|
{
|
||||||
|
VkDescriptorSetAllocateInfo allocInfo{};
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||||
|
allocInfo.descriptorPool = m_descriptorPool;
|
||||||
|
allocInfo.descriptorSetCount = descriptorSets.size();
|
||||||
|
allocInfo.pSetLayouts = layouts.data();
|
||||||
|
if (vkAllocateDescriptorSets(m_logicalDevice, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
|
||||||
|
// TODO - Vulkan Refactoring - Error Handling
|
||||||
|
// In event of failure, should allocate an additional descriptor pool and try again
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDevice::initialize(const std::vector<const char*>& deviceExtensions)
|
||||||
|
{
|
||||||
|
// TODO - Return discrete failure codes
|
||||||
|
if (!getAndCheckDeviceCapabilities(deviceExtensions)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!selectQueueFamilies()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initDeviceAndQueues(deviceExtensions)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initCommandPools()) {
|
||||||
|
destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initCommandBuffers()) {
|
||||||
|
destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initAllocator()) {
|
||||||
|
destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initStagingBuffers()) {
|
||||||
|
destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initDescriptorPool()) {
|
||||||
|
destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VmaAllocator KRDevice::getAllocator()
|
||||||
|
{
|
||||||
|
assert(m_allocator != VK_NULL_HANDLE);
|
||||||
|
return m_allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::getQueueFamiliesForSharing(uint32_t* queueFamilyIndices, uint32_t* familyCount, VkSharingMode* sharingMode)
|
||||||
|
{
|
||||||
|
*familyCount = 1;
|
||||||
|
queueFamilyIndices[0] = m_graphicsFamilyQueueIndex;
|
||||||
|
if (m_graphicsFamilyQueueIndex != m_transferFamilyQueueIndex) {
|
||||||
|
queueFamilyIndices[1] = m_transferFamilyQueueIndex;
|
||||||
|
(*familyCount)++;
|
||||||
|
}
|
||||||
|
if (*familyCount > 1) {
|
||||||
|
*sharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||||
|
} else {
|
||||||
|
*sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
|
||||||
|
void KRDevice::setDebugLabel(uint64_t objectHandle, VkObjectType objectType, const char* debugLabel)
|
||||||
|
{
|
||||||
|
VkDebugUtilsObjectNameInfoEXT debugInfo{};
|
||||||
|
debugInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||||
|
debugInfo.objectHandle = objectHandle;
|
||||||
|
debugInfo.objectType = objectType;
|
||||||
|
debugInfo.pObjectName = debugLabel;
|
||||||
|
VkResult res = vkSetDebugUtilsObjectNameEXT(m_logicalDevice, &debugInfo);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::setDebugLabel(const VkImage& image, const char* debugLabel)
|
||||||
|
{
|
||||||
|
setDebugLabel((uint64_t)image, VK_OBJECT_TYPE_IMAGE, debugLabel);
|
||||||
|
}
|
||||||
|
void KRDevice::setDebugLabel(const VkBuffer& buffer, const char* debugLabel)
|
||||||
|
{
|
||||||
|
setDebugLabel((uint64_t)buffer, VK_OBJECT_TYPE_BUFFER, debugLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::setDebugLabel(const VkQueue& queue, const char* debugLabel)
|
||||||
|
{
|
||||||
|
setDebugLabel((uint64_t)queue, VK_OBJECT_TYPE_QUEUE, debugLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::setDebugLabel(const VkCommandBuffer& commandBuffer, const char* debugLabel)
|
||||||
|
{
|
||||||
|
setDebugLabel((uint64_t)commandBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER, debugLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::setDebugLabel(const VkRenderPass& renderPass, const char* debugLabel)
|
||||||
|
{
|
||||||
|
setDebugLabel((uint64_t)renderPass, VK_OBJECT_TYPE_RENDER_PASS, debugLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::setDebugLabel(const VkDevice& device, const char* debugLabel)
|
||||||
|
{
|
||||||
|
setDebugLabel((uint64_t)device, VK_OBJECT_TYPE_DEVICE, debugLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
|
||||||
|
bool KRDevice::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer* buffer, VmaAllocation* allocation
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
, const char* debug_label
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||||
|
bufferInfo.size = size;
|
||||||
|
bufferInfo.usage = usage;
|
||||||
|
|
||||||
|
uint32_t queueFamilyIndices[2] = {};
|
||||||
|
bufferInfo.pQueueFamilyIndices = queueFamilyIndices;
|
||||||
|
bufferInfo.queueFamilyIndexCount = 0;
|
||||||
|
getQueueFamiliesForSharing(queueFamilyIndices, &bufferInfo.queueFamilyIndexCount, &bufferInfo.sharingMode);
|
||||||
|
|
||||||
|
VmaAllocationCreateInfo allocInfo = {};
|
||||||
|
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||||
|
allocInfo.requiredFlags = properties;
|
||||||
|
|
||||||
|
VkResult res = vmaCreateBuffer(m_allocator, &bufferInfo, &allocInfo, buffer, allocation, nullptr);
|
||||||
|
if (res != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
setDebugLabel(*buffer, debug_label);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
KrResult KRDevice::selectSurfaceFormat(VkSurfaceKHR& surface, VkSurfaceFormatKHR& selectedFormat) const
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<VkSurfaceFormatKHR> surfaceFormats;
|
||||||
|
uint32_t formatCount = 0;
|
||||||
|
if (vkGetPhysicalDeviceSurfaceFormatsKHR(m_device, surface, &formatCount, nullptr) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formatCount != 0) {
|
||||||
|
surfaceFormats.resize(formatCount);
|
||||||
|
if (vkGetPhysicalDeviceSurfaceFormatsKHR(m_device, surface, &formatCount, surfaceFormats.data()) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedFormat = surfaceFormats[0];
|
||||||
|
for (const auto& availableFormat : surfaceFormats) {
|
||||||
|
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
||||||
|
selectedFormat = availableFormat;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return KR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
KrResult KRDevice::selectDepthFormat(VkFormat& selectedDepthFormat) const
|
||||||
|
{
|
||||||
|
selectedDepthFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
VkFormatFeatureFlags requiredFeatures = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
|
std::vector<VkFormat> candidateFormats;
|
||||||
|
candidateFormats.push_back(VK_FORMAT_D32_SFLOAT_S8_UINT);
|
||||||
|
candidateFormats.push_back(VK_FORMAT_D24_UNORM_S8_UINT);
|
||||||
|
for (VkFormat format : candidateFormats) {
|
||||||
|
VkFormatProperties props;
|
||||||
|
vkGetPhysicalDeviceFormatProperties(m_device, format, &props);
|
||||||
|
|
||||||
|
if ((props.optimalTilingFeatures & requiredFeatures) == requiredFeatures) {
|
||||||
|
selectedDepthFormat = format;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedDepthFormat == VK_FORMAT_UNDEFINED) {
|
||||||
|
return KR_ERROR_VULKAN_DEPTHBUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
KrResult KRDevice::selectPresentMode(VkSurfaceKHR& surface, VkPresentModeKHR& selectedPresentMode) const
|
||||||
|
{
|
||||||
|
// VK_PRESENT_MODE_FIFO_KHR is always available
|
||||||
|
selectedPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
|
||||||
|
std::vector<VkPresentModeKHR> surfacePresentModes;
|
||||||
|
|
||||||
|
uint32_t presentModeCount = 0;
|
||||||
|
if (vkGetPhysicalDeviceSurfacePresentModesKHR(m_device, surface, &presentModeCount, nullptr) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presentModeCount != 0) {
|
||||||
|
surfacePresentModes.resize(presentModeCount);
|
||||||
|
if (vkGetPhysicalDeviceSurfacePresentModesKHR(m_device, surface, &presentModeCount, surfacePresentModes.data()) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find a better mode
|
||||||
|
for (const auto& availablePresentMode : surfacePresentModes) {
|
||||||
|
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
||||||
|
selectedPresentMode = availablePresentMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return KR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::streamStart()
|
||||||
|
{
|
||||||
|
if (!m_streamingStagingBuffer.started) {
|
||||||
|
VkCommandBufferBeginInfo beginInfo{};
|
||||||
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
|
|
||||||
|
vkBeginCommandBuffer(m_transferCommandBuffers[0], &beginInfo);
|
||||||
|
|
||||||
|
m_streamingStagingBuffer.started = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::streamUpload(Block& data, VkBuffer destination)
|
||||||
|
{
|
||||||
|
data.lock();
|
||||||
|
streamUpload(data.getStart(), data.getSize(), destination);
|
||||||
|
data.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::graphicsUpload(VkCommandBuffer& commandBuffer, Block& data, VkBuffer destination)
|
||||||
|
{
|
||||||
|
data.lock();
|
||||||
|
graphicsUpload(commandBuffer, data.getStart(), data.getSize(), destination);
|
||||||
|
data.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::checkFlushStreamBuffer(size_t size)
|
||||||
|
{
|
||||||
|
// Flush the buffers if we would run out of space
|
||||||
|
if (m_streamingStagingBuffer.usage + size > m_streamingStagingBuffer.size) {
|
||||||
|
// If we hit this often, then we need a larger staging buffer.
|
||||||
|
// TODO - Dynamically allocate more/larger staging buffers.
|
||||||
|
assert(size < m_streamingStagingBuffer.size);
|
||||||
|
streamEnd();
|
||||||
|
streamStart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::streamUpload(void* data, size_t size, VkBuffer destination)
|
||||||
|
{
|
||||||
|
checkFlushStreamBuffer(size);
|
||||||
|
memcpy((uint8_t*)m_streamingStagingBuffer.data + m_streamingStagingBuffer.usage, data, size);
|
||||||
|
|
||||||
|
// TODO - Beneficial to batch many regions in a single call?
|
||||||
|
VkBufferCopy copyRegion{};
|
||||||
|
copyRegion.srcOffset = m_streamingStagingBuffer.usage;
|
||||||
|
copyRegion.dstOffset = 0; // Optional
|
||||||
|
copyRegion.size = size;
|
||||||
|
vkCmdCopyBuffer(m_transferCommandBuffers[0], m_streamingStagingBuffer.buffer, destination, 1, ©Region);
|
||||||
|
|
||||||
|
// TODO - Assert on any needed alignment?
|
||||||
|
m_streamingStagingBuffer.usage += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::graphicsUpload(VkCommandBuffer& commandBuffer, void* data, size_t size, VkBuffer destination)
|
||||||
|
{
|
||||||
|
memcpy((uint8_t*)m_graphicsStagingBuffer.data + m_graphicsStagingBuffer.usage, data, size);
|
||||||
|
|
||||||
|
// TODO - Beneficial to batch many regions in a single call?
|
||||||
|
VkBufferCopy copyRegion{};
|
||||||
|
copyRegion.srcOffset = m_graphicsStagingBuffer.usage;
|
||||||
|
copyRegion.dstOffset = 0; // Optional
|
||||||
|
copyRegion.size = size;
|
||||||
|
vkCmdCopyBuffer(commandBuffer, m_graphicsStagingBuffer.buffer, destination, 1, ©Region);
|
||||||
|
|
||||||
|
// TODO - Assert on any needed alignment?
|
||||||
|
m_graphicsStagingBuffer.usage += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::streamUpload(void* data, size_t size, Vector3i dimensions, VkImage destination)
|
||||||
|
{
|
||||||
|
checkFlushStreamBuffer(size);
|
||||||
|
|
||||||
|
memcpy((uint8_t*)m_streamingStagingBuffer.data + m_streamingStagingBuffer.usage, data, size);
|
||||||
|
|
||||||
|
streamUploadImpl(size, dimensions, destination, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::streamUpload(Block& data, VkImage destination, size_t offset, size_t size, Vector3i dimensions, uint32_t baseMipLevel, uint32_t levelCount)
|
||||||
|
{
|
||||||
|
checkFlushStreamBuffer(size);
|
||||||
|
|
||||||
|
data.copy((uint8_t*)m_streamingStagingBuffer.data + m_streamingStagingBuffer.usage, offset, size);
|
||||||
|
|
||||||
|
streamUploadImpl(size, dimensions, destination, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::streamUploadImpl(size_t size, Vector3i dimensions, VkImage destination, uint32_t baseMipLevel, uint32_t levelCount)
|
||||||
|
{
|
||||||
|
// TODO - Refactor memory barriers into helper functions
|
||||||
|
VkPipelineStageFlags sourceStage;
|
||||||
|
VkPipelineStageFlags destinationStage;
|
||||||
|
|
||||||
|
VkImageMemoryBarrier barrier{};
|
||||||
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
|
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
barrier.image = destination;
|
||||||
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
barrier.subresourceRange.baseMipLevel = 0;
|
||||||
|
barrier.subresourceRange.levelCount = 1;
|
||||||
|
barrier.subresourceRange.baseArrayLayer = 0;
|
||||||
|
barrier.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
// For VK_IMAGE_LAYOUT_UNDEFINED -> VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
|
||||||
|
barrier.srcAccessMask = 0;
|
||||||
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
|
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(
|
||||||
|
m_transferCommandBuffers[0],
|
||||||
|
sourceStage, destinationStage,
|
||||||
|
0,
|
||||||
|
0, nullptr,
|
||||||
|
0, nullptr,
|
||||||
|
1, &barrier
|
||||||
|
);
|
||||||
|
|
||||||
|
VkBufferImageCopy region{};
|
||||||
|
region.bufferOffset = 0;
|
||||||
|
region.bufferRowLength = 0;
|
||||||
|
region.bufferImageHeight = 0;
|
||||||
|
|
||||||
|
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
region.imageSubresource.mipLevel = 0;
|
||||||
|
region.imageSubresource.baseArrayLayer = 0;
|
||||||
|
region.imageSubresource.layerCount = 1;
|
||||||
|
|
||||||
|
region.imageOffset = { 0, 0, 0 };
|
||||||
|
region.imageExtent = {
|
||||||
|
(unsigned int)dimensions.x,
|
||||||
|
(unsigned int)dimensions.y,
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
vkCmdCopyBufferToImage(
|
||||||
|
m_transferCommandBuffers[0],
|
||||||
|
m_streamingStagingBuffer.buffer,
|
||||||
|
destination,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
1,
|
||||||
|
®ion
|
||||||
|
);
|
||||||
|
|
||||||
|
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
|
||||||
|
// For VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL -> VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||||
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(
|
||||||
|
m_transferCommandBuffers[0],
|
||||||
|
sourceStage, destinationStage,
|
||||||
|
0,
|
||||||
|
0, nullptr,
|
||||||
|
0, nullptr,
|
||||||
|
1, &barrier
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO - Assert on any needed alignment?
|
||||||
|
m_streamingStagingBuffer.usage += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDevice::streamEnd()
|
||||||
|
{
|
||||||
|
if (m_streamingStagingBuffer.usage == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vkEndCommandBuffer(m_transferCommandBuffers[0]);
|
||||||
|
|
||||||
|
if (m_streamingStagingBuffer.usage > 0) {
|
||||||
|
VkResult res = vmaFlushAllocation(m_allocator, m_streamingStagingBuffer.allocation, 0, m_streamingStagingBuffer.usage);
|
||||||
|
assert(res == VK_SUCCESS);
|
||||||
|
m_streamingStagingBuffer.usage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO - Should double buffer and use a fence rather than block the thread
|
||||||
|
VkSubmitInfo submitInfo{};
|
||||||
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = &m_transferCommandBuffers[0];
|
||||||
|
|
||||||
|
vkQueueSubmit(m_transferQueue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||||
|
vkQueueWaitIdle(m_transferQueue);
|
||||||
|
|
||||||
|
m_streamingStagingBuffer.started = false;
|
||||||
|
}
|
||||||
146
kraken/KRDevice.h
Normal file
146
kraken/KRDevice.h
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
//
|
||||||
|
// KRDevice.h
|
||||||
|
// Kraken Engine
|
||||||
|
//
|
||||||
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "KREngine-common.h"
|
||||||
|
#include "KRContextObject.h"
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace mimir {
|
||||||
|
class Block;
|
||||||
|
}
|
||||||
|
|
||||||
|
class KRDevice : public KRContextObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KRDevice(KRContext& context, const VkPhysicalDevice& device);
|
||||||
|
virtual ~KRDevice();
|
||||||
|
|
||||||
|
KRDevice(const KRDevice&) = delete;
|
||||||
|
KRDevice& operator=(const KRDevice&) = delete;
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
bool initialize(const std::vector<const char*>& deviceExtensions);
|
||||||
|
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
void setDebugLabel(uint64_t objectHandle, VkObjectType objectType, const char* debugLabel);
|
||||||
|
void setDebugLabel(const VkImage& image, const char* debugLabel);
|
||||||
|
void setDebugLabel(const VkBuffer& buffer, const char* debugLabel);
|
||||||
|
void setDebugLabel(const VkQueue& queue, const char* debugLabel);
|
||||||
|
void setDebugLabel(const VkCommandBuffer& commandBuffer, const char* debugLabel);
|
||||||
|
void setDebugLabel(const VkRenderPass& renderPass, const char* debugLabel);
|
||||||
|
void setDebugLabel(const VkDevice& device, const char* debugLabel);
|
||||||
|
#endif // KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
|
||||||
|
VmaAllocator getAllocator();
|
||||||
|
bool createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer* buffer, VmaAllocation* allocation
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
, const char* debug_label
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
KrResult selectSurfaceFormat(VkSurfaceKHR& surface, VkSurfaceFormatKHR& surfaceFormat) const;
|
||||||
|
KrResult selectDepthFormat(VkFormat& selectedDepthFormat) const;
|
||||||
|
KrResult selectPresentMode(VkSurfaceKHR& surface, VkPresentModeKHR& selectedPresentMode) const;
|
||||||
|
|
||||||
|
void streamStart();
|
||||||
|
void streamUpload(mimir::Block& data, VkBuffer destination);
|
||||||
|
void streamUpload(mimir::Block& data, VkImage destination, size_t offset, size_t size, hydra::Vector3i dimensions, uint32_t baseMipLevel, uint32_t levelCount);
|
||||||
|
void streamUpload(void* data, size_t size, VkBuffer destination);
|
||||||
|
void streamUpload(void* data, size_t size, hydra::Vector3i dimensions, VkImage destination);
|
||||||
|
void streamEnd();
|
||||||
|
|
||||||
|
void graphicsUpload(VkCommandBuffer& commandBuffer, mimir::Block& data, VkBuffer destination);
|
||||||
|
void graphicsUpload(VkCommandBuffer& commandBuffer, void* data, size_t size, VkBuffer destination);
|
||||||
|
|
||||||
|
void createDescriptorSets(const std::vector<VkDescriptorSetLayout>& layouts, std::vector<VkDescriptorSet>& descriptorSets);
|
||||||
|
|
||||||
|
VkPhysicalDevice m_device;
|
||||||
|
VkDevice m_logicalDevice;
|
||||||
|
VkPhysicalDeviceProperties m_deviceProperties;
|
||||||
|
VkPhysicalDeviceFeatures m_deviceFeatures;
|
||||||
|
uint32_t m_graphicsFamilyQueueIndex;
|
||||||
|
VkQueue m_graphicsQueue;
|
||||||
|
uint32_t m_computeFamilyQueueIndex;
|
||||||
|
VkQueue m_computeQueue;
|
||||||
|
uint32_t m_transferFamilyQueueIndex;
|
||||||
|
VkQueue m_transferQueue;
|
||||||
|
VkCommandPool m_graphicsCommandPool;
|
||||||
|
VkCommandPool m_computeCommandPool;
|
||||||
|
VkCommandPool m_transferCommandPool;
|
||||||
|
std::vector<VkCommandBuffer> m_graphicsCommandBuffers;
|
||||||
|
std::vector<VkCommandBuffer> m_computeCommandBuffers;
|
||||||
|
std::vector<VkCommandBuffer> m_transferCommandBuffers;
|
||||||
|
VmaAllocator m_allocator;
|
||||||
|
VkDescriptorPool m_descriptorPool;
|
||||||
|
|
||||||
|
struct StagingBufferInfo
|
||||||
|
{
|
||||||
|
VkBuffer buffer;
|
||||||
|
VmaAllocation allocation;
|
||||||
|
size_t size;
|
||||||
|
size_t usage;
|
||||||
|
void* data;
|
||||||
|
bool started;
|
||||||
|
|
||||||
|
void destroy(VmaAllocator& allocator);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Staging buffer for uploading with the transfer queue
|
||||||
|
// This will be used for asynchronous asset streaming in the streamer thread.
|
||||||
|
// TODO - We should allocate at least two of these and double-buffer for increased CPU-GPU concurrency
|
||||||
|
StagingBufferInfo m_streamingStagingBuffer;
|
||||||
|
|
||||||
|
// Staging buffer for uploading with the graphics queue
|
||||||
|
// This will be used for uploading assets procedurally generated while recording the graphics command buffer.
|
||||||
|
// TODO - We should allocate at least two of these and double-buffer for increased CPU-GPU concurrency
|
||||||
|
StagingBufferInfo m_graphicsStagingBuffer;
|
||||||
|
|
||||||
|
void getQueueFamiliesForSharing(uint32_t* queueFamilyIndices, uint32_t* familyCount, VkSharingMode* sharingMode);
|
||||||
|
private:
|
||||||
|
void checkFlushStreamBuffer(size_t size);
|
||||||
|
|
||||||
|
// Initialization helper functions
|
||||||
|
bool getAndCheckDeviceCapabilities(const std::vector<const char*>& deviceExtensions);
|
||||||
|
bool selectQueueFamilies();
|
||||||
|
bool initDeviceAndQueues(const std::vector<const char*>& deviceExtensions);
|
||||||
|
bool initCommandPools();
|
||||||
|
bool initCommandBuffers();
|
||||||
|
bool initAllocator();
|
||||||
|
bool initStagingBuffers();
|
||||||
|
bool initStagingBuffer(VkDeviceSize size, StagingBufferInfo* info
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
, const char* debug_label
|
||||||
|
#endif // KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
);
|
||||||
|
bool initDescriptorPool();
|
||||||
|
void streamUploadImpl(size_t size, hydra::Vector3i dimensions, VkImage destination, uint32_t baseMipLevel, uint32_t levelCount);
|
||||||
|
};
|
||||||
244
kraken/KRDeviceManager.cpp
Normal file
244
kraken/KRDeviceManager.cpp
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
//
|
||||||
|
// KRDeviceManager.cpp
|
||||||
|
// Kraken Engine
|
||||||
|
//
|
||||||
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "KRDeviceManager.h"
|
||||||
|
|
||||||
|
// VMA_IMPLEMENTATION must only be defined in a single CPP file
|
||||||
|
#define VMA_IMPLEMENTATION
|
||||||
|
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||||
|
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
|
||||||
|
#include "vk_mem_alloc.h"
|
||||||
|
|
||||||
|
KRDeviceManager::KRDeviceManager(KRContext& context)
|
||||||
|
: KRContextObject(context)
|
||||||
|
, m_vulkanInstance(VK_NULL_HANDLE)
|
||||||
|
, m_topDeviceHandle(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KRDeviceManager::~KRDeviceManager()
|
||||||
|
{
|
||||||
|
destroyDevices();
|
||||||
|
|
||||||
|
if (m_vulkanInstance != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyInstance(m_vulkanInstance, NULL);
|
||||||
|
m_vulkanInstance = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDeviceManager::haveVulkan() const
|
||||||
|
{
|
||||||
|
return m_vulkanInstance != VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRDeviceManager::haveDevice() const
|
||||||
|
{
|
||||||
|
return !m_devices.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
KRDeviceManager::destroyDevices()
|
||||||
|
{
|
||||||
|
const std::lock_guard<std::mutex> lock(KRContext::g_DeviceInfoMutex);
|
||||||
|
m_devices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
KRDeviceManager::initialize()
|
||||||
|
{
|
||||||
|
VkResult res = volkInitialize();
|
||||||
|
if (res != VK_SUCCESS) {
|
||||||
|
destroyDevices();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the VkApplicationInfo structure
|
||||||
|
VkApplicationInfo app_info = {};
|
||||||
|
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||||
|
app_info.pNext = NULL;
|
||||||
|
app_info.pApplicationName = "Test"; // TODO - Change Me!
|
||||||
|
app_info.applicationVersion = VK_MAKE_VERSION(0, 0, 1);
|
||||||
|
app_info.pEngineName = "Kraken Engine";
|
||||||
|
app_info.engineVersion = VK_MAKE_VERSION(0, 1, 0);
|
||||||
|
app_info.apiVersion = VK_API_VERSION_1_3;
|
||||||
|
|
||||||
|
// VK_KHR_surface and VK_KHR_win32_surface
|
||||||
|
|
||||||
|
const char* extensions[] = {
|
||||||
|
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
||||||
|
#endif
|
||||||
|
#ifdef WIN32
|
||||||
|
VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
|
||||||
|
#endif
|
||||||
|
#ifdef __APPLE__
|
||||||
|
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
|
||||||
|
VK_EXT_METAL_SURFACE_EXTENSION_NAME,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
VkInstanceCreateFlags createFlags = 0;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
createFlags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// initialize the VkInstanceCreateInfo structure
|
||||||
|
VkInstanceCreateInfo inst_info = {};
|
||||||
|
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
|
inst_info.pNext = NULL;
|
||||||
|
inst_info.flags = createFlags;
|
||||||
|
inst_info.pApplicationInfo = &app_info;
|
||||||
|
inst_info.enabledExtensionCount = std::size(extensions);
|
||||||
|
inst_info.ppEnabledExtensionNames = extensions;
|
||||||
|
inst_info.enabledLayerCount = 0;
|
||||||
|
inst_info.ppEnabledLayerNames = NULL;
|
||||||
|
|
||||||
|
res = vkCreateInstance(&inst_info, NULL, &m_vulkanInstance);
|
||||||
|
if (res != VK_SUCCESS) {
|
||||||
|
destroyDevices();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
volkLoadInstance(m_vulkanInstance);
|
||||||
|
|
||||||
|
createDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRDeviceManager::createDevices()
|
||||||
|
{
|
||||||
|
const std::lock_guard<std::mutex> deviceLock(KRContext::g_DeviceInfoMutex);
|
||||||
|
if (m_devices.size() > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t deviceCount = 0;
|
||||||
|
vkEnumeratePhysicalDevices(m_vulkanInstance, &deviceCount, nullptr);
|
||||||
|
if (deviceCount == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<VkPhysicalDevice> physicalDevices(deviceCount);
|
||||||
|
vkEnumeratePhysicalDevices(m_vulkanInstance, &deviceCount, physicalDevices.data());
|
||||||
|
|
||||||
|
const std::vector<const char*> deviceExtensions = {
|
||||||
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||||
|
VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME,
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
"VK_KHR_portability_subset",
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<KRDevice>> candidateDevices;
|
||||||
|
|
||||||
|
for (const VkPhysicalDevice& physicalDevice : physicalDevices) {
|
||||||
|
std::unique_ptr<KRDevice> device = std::make_unique<KRDevice>(*m_pContext, physicalDevice);
|
||||||
|
if (!device->initialize(deviceExtensions)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool addDevice = false;
|
||||||
|
if (candidateDevices.empty()) {
|
||||||
|
addDevice = true;
|
||||||
|
} else {
|
||||||
|
VkPhysicalDeviceType collectedType = candidateDevices[0]->m_deviceProperties.deviceType;
|
||||||
|
if (collectedType == device->m_deviceProperties.deviceType) {
|
||||||
|
addDevice = true;
|
||||||
|
} else if (device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
|
||||||
|
// Discrete GPU's are always the best choice
|
||||||
|
candidateDevices.clear();
|
||||||
|
addDevice = true;
|
||||||
|
} else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
|
||||||
|
// Integrated GPU's are the second best choice
|
||||||
|
candidateDevices.clear();
|
||||||
|
addDevice = true;
|
||||||
|
} else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && collectedType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
|
||||||
|
// Virtual GPU's are the 3rd best choice
|
||||||
|
candidateDevices.clear();
|
||||||
|
addDevice = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (addDevice) {
|
||||||
|
candidateDevices.push_back(std::move(device));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int iDevice = 0;
|
||||||
|
for (auto itr = candidateDevices.begin(); itr != candidateDevices.end(); itr++, iDevice++) {
|
||||||
|
std::unique_ptr<KRDevice> device = std::move(*itr);
|
||||||
|
|
||||||
|
#if KRENGINE_DEBUG_GPU_LABELS
|
||||||
|
const size_t kMaxLabel = 64;
|
||||||
|
char label[kMaxLabel];
|
||||||
|
if (iDevice == 0) {
|
||||||
|
strcpy(label, "Primary GPU");
|
||||||
|
} else if (iDevice == 1) {
|
||||||
|
strcpy(label, "Secondary GPU");
|
||||||
|
} else {
|
||||||
|
snprintf(label, kMaxLabel, "GPU %i", iDevice + 1);
|
||||||
|
}
|
||||||
|
device->setDebugLabel(device->m_logicalDevice, label);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_devices[++m_topDeviceHandle] = std::move(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<KRDevice>& KRDeviceManager::getDevice(KrDeviceHandle handle)
|
||||||
|
{
|
||||||
|
return m_devices[handle];
|
||||||
|
}
|
||||||
|
|
||||||
|
VkInstance& KRDeviceManager::getVulkanInstance()
|
||||||
|
{
|
||||||
|
return m_vulkanInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
KrSurfaceHandle KRDeviceManager::getBestDeviceForSurface(const VkSurfaceKHR& surface)
|
||||||
|
{
|
||||||
|
KrDeviceHandle deviceHandle = 0;
|
||||||
|
for (auto itr = m_devices.begin(); itr != m_devices.end(); itr++) {
|
||||||
|
KRDevice& device = *(*itr).second;
|
||||||
|
VkBool32 canPresent = false;
|
||||||
|
vkGetPhysicalDeviceSurfaceSupportKHR(device.m_device, device.m_graphicsFamilyQueueIndex, surface, &canPresent);
|
||||||
|
if (canPresent) {
|
||||||
|
deviceHandle = (*itr).first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deviceHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
unordered_map<KrDeviceHandle, std::unique_ptr<KRDevice>>& KRDeviceManager::getDevices()
|
||||||
|
{
|
||||||
|
return m_devices;
|
||||||
|
}
|
||||||
62
kraken/KRDeviceManager.h
Normal file
62
kraken/KRDeviceManager.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// KRDeviceManager.h
|
||||||
|
// Kraken Engine
|
||||||
|
//
|
||||||
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
|
#include "KRContext.h"
|
||||||
|
#include "KRDevice.h"
|
||||||
|
|
||||||
|
class KRDeviceManager : KRContextObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KRDeviceManager(KRContext& context);
|
||||||
|
~KRDeviceManager();
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
bool haveVulkan() const;
|
||||||
|
bool haveDevice() const;
|
||||||
|
|
||||||
|
std::unique_ptr<KRDevice>& getDevice(KrDeviceHandle handle);
|
||||||
|
VkInstance& getVulkanInstance();
|
||||||
|
KrSurfaceHandle getBestDeviceForSurface(const VkSurfaceKHR& surface);
|
||||||
|
unordered_map<KrDeviceHandle, std::unique_ptr<KRDevice>>& getDevices();
|
||||||
|
|
||||||
|
private:
|
||||||
|
unordered_map<KrDeviceHandle, std::unique_ptr<KRDevice>> m_devices;
|
||||||
|
KrDeviceHandle m_topDeviceHandle;
|
||||||
|
|
||||||
|
void createDevices();
|
||||||
|
void destroyDevices();
|
||||||
|
VkInstance m_vulkanInstance;
|
||||||
|
|
||||||
|
};
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
//
|
|
||||||
// KRDirectionalLight.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 12-04-05.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#include "KRDirectionalLight.h"
|
|
||||||
#include "KRShader.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "assert.h"
|
|
||||||
#include "KRStockGeometry.h"
|
|
||||||
|
|
||||||
KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
KRDirectionalLight::~KRDirectionalLight()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRDirectionalLight::getElementName() {
|
|
||||||
return "directional_light";
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 KRDirectionalLight::getWorldLightDirection() {
|
|
||||||
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 KRDirectionalLight::getLocalLightDirection() {
|
|
||||||
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) {
|
|
||||||
|
|
||||||
const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame
|
|
||||||
int cShadows = 1;
|
|
||||||
for(int iShadow=0; iShadow < cShadows; iShadow++) {
|
|
||||||
/*
|
|
||||||
TODO - Determine if we still need this...
|
|
||||||
|
|
||||||
GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}};
|
|
||||||
GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}};
|
|
||||||
|
|
||||||
float min_depth = 0.0f;
|
|
||||||
float max_depth = 1.0f;
|
|
||||||
*/
|
|
||||||
|
|
||||||
AABB worldSpacefrustrumSliceBounds = AABB(Vector3(-1.0f, -1.0f, -1.0f), Vector3(1.0f, 1.0f, 1.0f), Matrix4::Invert(viewport.getViewProjectionMatrix()));
|
|
||||||
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
|
||||||
|
|
||||||
Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection());
|
|
||||||
|
|
||||||
Vector3 shadowUp(0.0, 1.0, 0.0);
|
|
||||||
if(Vector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = Vector3(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction
|
|
||||||
|
|
||||||
// Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
|
|
||||||
// Matrix4 matShadowProjection = Matrix4();
|
|
||||||
// matShadowProjection.scale(0.001, 0.001, 0.001);
|
|
||||||
|
|
||||||
Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
|
|
||||||
Matrix4 matShadowProjection = Matrix4();
|
|
||||||
AABB shadowSpaceFrustrumSliceBounds = AABB(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection));
|
|
||||||
AABB shadowSpaceSceneBounds = AABB(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, Matrix4::Invert(matShadowProjection));
|
|
||||||
if(shadowSpaceSceneBounds.min.z < shadowSpaceFrustrumSliceBounds.min.z) shadowSpaceFrustrumSliceBounds.min.z = shadowSpaceSceneBounds.min.z; // Include any potential shadow casters that are outside the view frustrum
|
|
||||||
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
|
|
||||||
|
|
||||||
Matrix4 matBias;
|
|
||||||
matBias.bias();
|
|
||||||
matShadowProjection *= matBias;
|
|
||||||
|
|
||||||
KRViewport newShadowViewport = KRViewport(Vector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
|
|
||||||
AABB prevShadowBounds = AABB(-Vector3::One(), Vector3::One(), Matrix4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix()));
|
|
||||||
AABB minimumShadowBounds = AABB(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
|
|
||||||
minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
|
||||||
if(!prevShadowBounds.contains(minimumShadowBounds) || !shadowValid[iShadow] || true) { // FINDME, HACK - Re-generating the shadow map every frame. This should only be needed if the shadow contains non-static geometry
|
|
||||||
m_shadowViewports[iShadow] = newShadowViewport;
|
|
||||||
shadowValid[iShadow] = false;
|
|
||||||
fprintf(stderr, "Kraken - Generate shadow maps...\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRDirectionalLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
|
|
||||||
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
|
||||||
|
|
||||||
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
|
|
||||||
// Lights are rendered on the second pass of the deferred renderer
|
|
||||||
|
|
||||||
std::vector<KRDirectionalLight *> this_light;
|
|
||||||
this_light.push_back(this);
|
|
||||||
|
|
||||||
Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix();
|
|
||||||
matModelViewInverseTranspose.transpose();
|
|
||||||
matModelViewInverseTranspose.invert();
|
|
||||||
|
|
||||||
Vector3 light_direction_view_space = getWorldLightDirection();
|
|
||||||
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
|
|
||||||
light_direction_view_space.normalize();
|
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("light_directional", pCamera, std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
|
||||||
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE, light_direction_view_space);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
|
|
||||||
|
|
||||||
// Disable z-buffer write
|
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
|
||||||
|
|
||||||
// Disable z-buffer test
|
|
||||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
|
||||||
|
|
||||||
// Render a full screen quad
|
|
||||||
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
|
||||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB KRDirectionalLight::getBounds()
|
|
||||||
{
|
|
||||||
return AABB::Infinite();
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
//
|
|
||||||
// KRDirectionalLight.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 12-04-05.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KREngine_KRDirectionalLight_h
|
|
||||||
#define KREngine_KRDirectionalLight_h
|
|
||||||
|
|
||||||
#include "KRLight.h"
|
|
||||||
|
|
||||||
class KRDirectionalLight : public KRLight {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
KRDirectionalLight(KRScene &scene, std::string name);
|
|
||||||
virtual ~KRDirectionalLight();
|
|
||||||
|
|
||||||
virtual std::string getElementName();
|
|
||||||
Vector3 getLocalLightDirection();
|
|
||||||
Vector3 getWorldLightDirection();
|
|
||||||
|
|
||||||
virtual void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
|
|
||||||
virtual AABB getBounds();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
virtual int configureShadowBufferViewports(const KRViewport &viewport);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,236 +1,187 @@
|
|||||||
//
|
//
|
||||||
// KREngine-common.h
|
// Kraken Engine-common.h
|
||||||
// KREngine
|
// Kraken Engine
|
||||||
//
|
//
|
||||||
// Created by Kearwood Gilbert on 12-03-15.
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
//
|
||||||
//
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
#ifndef KRENGINE_COMMON_H
|
// conditions and the following disclaimer.
|
||||||
#define KRENGINE_COMMON_H
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
#include "public/kraken.h"
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
#include "KRHelpers.h"
|
// provided with the distribution.
|
||||||
|
//
|
||||||
#include <stdint.h>
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
#include <vector>
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
#include <string>
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
#include <set>
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
#include <list>
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
#include <map>
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
#include <stack>
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <queue>
|
//
|
||||||
#include <iostream>
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
#include <sstream>
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
#include <fstream>
|
// or implied, of Kearwood Gilbert.
|
||||||
#include <stdint.h>
|
//
|
||||||
#include <stdio.h>
|
|
||||||
|
#pragma once
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
#include "../3rdparty/tinyxml2/tinyxml2.h"
|
#define KRENGINE_MAX_GPU_COUNT 4
|
||||||
#else
|
#define KRENGINE_MAX_FRAMES_IN_FLIGHT 2
|
||||||
|
#define KRENGINE_DEBUG_GPU_LABELS 1
|
||||||
#include <sys/mman.h>
|
#define KRENGINE_DEBUG_GPU_LABEL_MAX_LEN 128
|
||||||
#include <unistd.h>
|
|
||||||
#include <pthread.h>
|
#include "public/kraken.h"
|
||||||
|
#include "KRHelpers.h"
|
||||||
#include <Accelerate/Accelerate.h>
|
using namespace kraken;
|
||||||
#include <AudioToolbox/AudioToolbox.h>
|
|
||||||
#include <AudioToolbox/AudioFile.h>
|
#include "hydra.h"
|
||||||
#include <AudioToolbox/ExtendedAudioFile.h>
|
#include "siren.h"
|
||||||
#include <AudioToolbox/AUGraph.h>
|
|
||||||
#include <OpenAL/al.h>
|
#include <stdint.h>
|
||||||
#include <OpenAL/alc.h>
|
#include <array>
|
||||||
#if TARGET_OS_IPHONE
|
#include <vector>
|
||||||
#include <OpenAL/oalMacOSX_OALExtensions.h>
|
#include <string>
|
||||||
#else
|
#include <set>
|
||||||
#include <OpenAL/MacOSX_OALExtensions.h>
|
#include <list>
|
||||||
#endif
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include "tinyxml2.h"
|
#include <variant>
|
||||||
#endif
|
#include <algorithm>
|
||||||
|
#include <stack>
|
||||||
#include <boost/tokenizer.hpp>
|
#include <queue>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <iostream>
|
||||||
#include <boost/signals2/mutex.hpp>
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
#include <sys/types.h>
|
#include <stdint.h>
|
||||||
#include <sys/stat.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <assert.h>
|
#include "../3rdparty/tinyxml2/tinyxml2.h"
|
||||||
#include <time.h>
|
#include "../3rdparty/glslang/glslang/Public/ShaderLang.h"
|
||||||
#include <limits>
|
#include "../3rdparty/glslang/SPIRV/GlslangToSpv.h"
|
||||||
|
#if defined(__APPLE__)
|
||||||
#include <iostream>
|
#define VK_USE_PLATFORM_METAL_EXT
|
||||||
|
#define stricmp strcasecmp
|
||||||
// _USE_MATH_DEFINES must be defined to get M_PI in Windows
|
|
||||||
#define _USE_MATH_DEFINES
|
#include <sys/mman.h>
|
||||||
#include <math.h>
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#include <atomic>
|
#include <AudioToolbox/AudioToolbox.h>
|
||||||
#include <thread>
|
#include <AudioToolbox/AudioFile.h>
|
||||||
|
#include <AudioToolbox/ExtendedAudioFile.h>
|
||||||
|
#include <AudioToolbox/AUGraph.h>
|
||||||
|
|
||||||
|
#include "TargetConditionals.h"
|
||||||
using std::vector;
|
#include <mach/mach.h>
|
||||||
using std::string;
|
#include <mach/mach_time.h>
|
||||||
using std::set;
|
#include <Accelerate/Accelerate.h>
|
||||||
using std::list;
|
#define KRAKEN_HAVE_BLAS 1
|
||||||
using std::map;
|
|
||||||
|
#endif
|
||||||
using std::multimap;
|
|
||||||
|
#include <sys/types.h>
|
||||||
using std::stack;
|
#include <sys/stat.h>
|
||||||
using std::queue;
|
#include <fcntl.h>
|
||||||
|
#include <assert.h>
|
||||||
#ifdef __APPLE__
|
#include <time.h>
|
||||||
#include "TargetConditionals.h"
|
#include <limits>
|
||||||
#include <mach/mach.h>
|
#include <iostream>
|
||||||
#include <mach/mach_time.h>
|
|
||||||
#include <Accelerate/Accelerate.h>
|
// NOMINMAX required to prevent windows headers from defining max() and min() macros
|
||||||
#define KRAKEN_HAVE_BLAS 1
|
#define NOMINMAX
|
||||||
#endif
|
|
||||||
|
// _USE_MATH_DEFINES must be defined to get M_PI in Windows
|
||||||
#define KRENGINE_MAX_TEXTURE_UNITS 8
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#if !defined(__i386__) && defined(__arm__)
|
|
||||||
#define KRAKEN_USE_ARM_NEON
|
#include <atomic>
|
||||||
#endif
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
using std::unordered_map;
|
|
||||||
using std::unordered_multimap;
|
using std::vector;
|
||||||
using std::hash;
|
using std::string;
|
||||||
|
using std::set;
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
using std::list;
|
||||||
|
using std::map;
|
||||||
#include <mutex>
|
using std::unique_ptr;
|
||||||
#include <cstdint>
|
using std::shared_ptr;
|
||||||
typedef int64_t __int64_t;
|
|
||||||
typedef uint64_t __uint64_t;
|
using std::multimap;
|
||||||
typedef int32_t __int32_t;
|
|
||||||
typedef uint32_t __uint32_t;
|
using std::stack;
|
||||||
typedef int16_t __int16_t;
|
using std::queue;
|
||||||
typedef uint16_t __uint16_t;
|
|
||||||
typedef int8_t __int8_t;
|
|
||||||
typedef uint8_t __uint8_t;
|
#if !defined(__i386__) && defined(__arm__)
|
||||||
|
#define KRAKEN_USE_ARM_NEON
|
||||||
#include <GL/glew.h>
|
#endif
|
||||||
// OpenGL ES 2.0 mapping to OpenGL 3.2
|
|
||||||
#define glDeleteQueriesEXT glDeleteQueries
|
|
||||||
#define glGenQueriesEXT glGenQueries
|
#include <unordered_map>
|
||||||
#define glBeginQueryEXT glBeginQuery
|
using std::unordered_map;
|
||||||
#define glEndQueryEXT glEndQuery
|
using std::unordered_multimap;
|
||||||
#define glGetQueryObjectuivEXT glGetQueryObjectuiv
|
using std::hash;
|
||||||
#define glTexStorage2DEXT glTexStorage2D
|
|
||||||
#define GL_ANY_SAMPLES_PASSED_EXT GL_ANY_SAMPLES_PASSED
|
#include <vulkan/vulkan.h>
|
||||||
#define GL_QUERY_RESULT_EXT GL_QUERY_RESULT
|
#include <vk_mem_alloc.h>
|
||||||
|
#include <volk.h>
|
||||||
#elif TARGET_OS_IPHONE
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
#include <OpenGLES/ES2/gl.h>
|
|
||||||
#include <OpenGLES/ES2/glext.h>
|
#include <cstdint>
|
||||||
|
typedef int64_t __int64_t;
|
||||||
#else
|
typedef uint64_t __uint64_t;
|
||||||
|
typedef int32_t __int32_t;
|
||||||
#include <OpenGL/gl3.h>
|
typedef uint32_t __uint32_t;
|
||||||
#include <OpenGL/gl3ext.h>
|
typedef int16_t __int16_t;
|
||||||
|
typedef uint16_t __uint16_t;
|
||||||
// OpenGL ES 2.0 mapping to OpenGL 3.2
|
typedef int8_t __int8_t;
|
||||||
#define glDepthRangef glDepthRange
|
typedef uint8_t __uint8_t;
|
||||||
#define glClearDepthf glClearDepth
|
|
||||||
#define glDeleteQueriesEXT glDeleteQueries
|
#endif
|
||||||
#define glGenQueriesEXT glGenQueries
|
|
||||||
#define glBeginQueryEXT glBeginQuery
|
|
||||||
#define glEndQueryEXT glEndQuery
|
// TODO - Vulkan Refactoring
|
||||||
#define glGetQueryObjectuivEXT glGetQueryObjectuiv
|
// If we hit any old GL calls, assert
|
||||||
#define glTexStorage2DEXT glTexStorage2D
|
#define GLDEBUG(x) \
|
||||||
#define GL_ANY_SAMPLES_PASSED_EXT GL_ANY_SAMPLES_PASSED
|
assert(false);
|
||||||
#define GL_QUERY_RESULT_EXT GL_QUERY_RESULT
|
|
||||||
|
#if defined(DEBUG) || defined(_DEBUG)
|
||||||
#define GL_OES_mapbuffer 1
|
#define OSDEBUG(x) \
|
||||||
#define glMapBufferOES glMapBuffer
|
{ \
|
||||||
#define glUnmapBufferOES glUnmapBuffer
|
OSStatus e = x; \
|
||||||
#define GL_WRITE_ONLY_OES GL_WRITE_ONLY
|
if( e != noErr) \
|
||||||
|
{ \
|
||||||
#define GL_OES_vertex_array_object 1
|
fprintf(stderr, "Error at line number %d, in file %s. Returned %d for call %s\n",__LINE__, __FILE__, (int)e, #x ); \
|
||||||
#define glGenVertexArraysOES glGenVertexArrays
|
} \
|
||||||
#define glBindVertexArrayOES glBindVertexArray
|
}
|
||||||
#define glDeleteVertexArraysOES glDeleteVertexArrays
|
#else
|
||||||
|
#define OSDEBUG(x) x;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(_DEBUG)
|
#define GL_PUSH_GROUP_MARKER(x)
|
||||||
#define GLDEBUG(x) \
|
#define GL_POP_GROUP_MARKER
|
||||||
x; \
|
|
||||||
{ \
|
|
||||||
GLenum e; \
|
typedef enum
|
||||||
while( (e=glGetError()) != GL_NO_ERROR) \
|
{
|
||||||
{ \
|
STREAM_LEVEL_OUT,
|
||||||
fprintf(stderr, "Error at line number %d, in file %s. glGetError() returned %i for call %s\n",__LINE__, __FILE__, e, #x ); \
|
STREAM_LEVEL_IN_LQ,
|
||||||
} \
|
STREAM_LEVEL_IN_HQ
|
||||||
}
|
} kraken_stream_level;
|
||||||
#else
|
|
||||||
#define GLDEBUG(x) x;
|
typedef int KrDeviceHandle;
|
||||||
#endif
|
typedef int KrSurfaceHandle;
|
||||||
|
|
||||||
|
#include "KRBehavior.h"
|
||||||
#if defined(DEBUG) || defined(_DEBUG)
|
|
||||||
#define ALDEBUG(x) \
|
using namespace kraken;
|
||||||
x; \
|
|
||||||
{ \
|
|
||||||
GLenum e; \
|
|
||||||
while( (e=alGetError()) != AL_NO_ERROR) \
|
|
||||||
{ \
|
|
||||||
fprintf(stderr, "Error at line number %d, in file %s. alGetError() returned %i for call %s\n",__LINE__, __FILE__, e, #x ); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define ALDEBUG(x) x;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(_DEBUG)
|
|
||||||
#define OSDEBUG(x) \
|
|
||||||
{ \
|
|
||||||
OSStatus e = x; \
|
|
||||||
if( e != noErr) \
|
|
||||||
{ \
|
|
||||||
fprintf(stderr, "Error at line number %d, in file %s. Returned %d for call %s\n",__LINE__, __FILE__, (int)e, #x ); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define OSDEBUG(x) x;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(GL_EXT_debug_marker) && (defined(DEBUG) || defined(_DEBUG))
|
|
||||||
|
|
||||||
#define GL_PUSH_GROUP_MARKER(x) glPushGroupMarkerEXT(0, x)
|
|
||||||
#define GL_POP_GROUP_MARKER glPopGroupMarkerEXT()
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define GL_PUSH_GROUP_MARKER(x)
|
|
||||||
#define GL_POP_GROUP_MARKER
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
STREAM_LEVEL_OUT,
|
|
||||||
STREAM_LEVEL_IN_LQ,
|
|
||||||
STREAM_LEVEL_IN_HQ
|
|
||||||
} kraken_stream_level;
|
|
||||||
|
|
||||||
#include "KRBehavior.h"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace kraken;
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//
|
//
|
||||||
// KREngine.h
|
// Kraken Engine.h
|
||||||
// KREngine
|
// Kraken Engine
|
||||||
//
|
//
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
@@ -30,8 +30,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
// #include "KRTextureManager.h"
|
// #include "KRTextureManager.h"
|
||||||
#include "Matrix4.h"
|
|
||||||
#include "Vector3.h"
|
|
||||||
#include "KRMesh.h"
|
#include "KRMesh.h"
|
||||||
#include "KRScene.h"
|
#include "KRScene.h"
|
||||||
#include "KRContext.h"
|
#include "KRContext.h"
|
||||||
@@ -39,43 +37,46 @@
|
|||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
typedef enum KREngineParameterType {KRENGINE_PARAMETER_INT, KRENGINE_PARAMETER_FLOAT, KRENGINE_PARAMETER_BOOL} KREngineParameterType;
|
typedef enum KREngineParameterType
|
||||||
|
{
|
||||||
|
KRENGINE_PARAMETER_INT, KRENGINE_PARAMETER_FLOAT, KRENGINE_PARAMETER_BOOL
|
||||||
|
} KREngineParameterType;
|
||||||
|
|
||||||
namespace kraken {
|
namespace kraken {
|
||||||
void set_parameter(const std::string ¶meter_name, float parameter_value);
|
void set_parameter(const std::string& parameter_name, float parameter_value);
|
||||||
void set_debug_text(const std::string &print_text);
|
void set_debug_text(const std::string& print_text);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __OBJC__
|
#ifdef __OBJC__
|
||||||
|
|
||||||
@interface KREngine : NSObject
|
@interface KREngine : NSObject
|
||||||
|
|
||||||
+ (KREngine *)sharedInstance;
|
+ (KREngine*)sharedInstance;
|
||||||
|
|
||||||
@property(nonatomic, readonly) NSDictionary *parameter_names;
|
@property(nonatomic, readonly) NSDictionary* parameter_names;
|
||||||
@property(nonatomic, assign) KRContext *context;
|
@property(nonatomic, assign) KRContext* context;
|
||||||
@property(nonatomic, retain) NSString *debug_text;
|
@property(nonatomic, retain) NSString* debug_text;
|
||||||
@property(nonatomic, assign, readonly) KRRenderSettings *settings;
|
@property(nonatomic, assign, readonly) KRRenderSettings* settings;
|
||||||
|
|
||||||
- (id)init;
|
-(id)init;
|
||||||
- (BOOL)loadResource:(NSString *)path;
|
-(BOOL)loadResource:(NSString*)path;
|
||||||
|
|
||||||
// Parameter enumeration interface
|
// Parameter enumeration interface
|
||||||
-(int)getParameterCount;
|
-(int)getParameterCount;
|
||||||
-(NSString *)getParameterNameWithIndex: (int)i;
|
-(NSString*)getParameterNameWithIndex: (int)i;
|
||||||
-(NSString *)getParameterLabelWithIndex: (int)i;
|
-(NSString*)getParameterLabelWithIndex: (int)i;
|
||||||
-(KREngineParameterType)getParameterTypeWithIndex: (int)i;
|
-(KREngineParameterType)getParameterTypeWithIndex: (int)i;
|
||||||
-(float)getParameterMinWithIndex: (int)i;
|
-(float)getParameterMinWithIndex: (int)i;
|
||||||
-(float)getParameterMaxWithIndex: (int)i;
|
-(float)getParameterMaxWithIndex: (int)i;
|
||||||
-(float)getParameterValueWithIndex: (int)i;
|
-(float)getParameterValueWithIndex: (int)i;
|
||||||
-(void)setParameterValueWithIndex: (int)i Value: (float)v;
|
-(void)setParameterValueWithIndex: (int)i Value : (float)v;
|
||||||
-(void)setParameterValueWithName: (NSString *)name Value: (float)v;
|
-(void)setParameterValueWithName: (NSString*)name Value : (float)v;
|
||||||
-(int)getParameterIndexWithName: (NSString *)name;
|
-(int)getParameterIndexWithName: (NSString*)name;
|
||||||
|
|
||||||
- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime AndWidth: (int)width AndHeight: (int)height AndDefaultFBO: (GLint)defaultFBO;
|
-(void)renderScene: (KRScene*)pScene WithDeltaTime : (float)deltaTime AndWidth : (int)width AndHeight : (int)height AndDefaultFBO : (GLint)defaultFBO;
|
||||||
//- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime;
|
//- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime;
|
||||||
- (void)setNearZ: (float)dNearZ;
|
-(void)setNearZ: (float)dNearZ;
|
||||||
- (void)setFarZ: (float)dFarZ;
|
-(void)setFarZ: (float)dFarZ;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
#include "KREngine.h"
|
#include "KREngine.h"
|
||||||
#include "KRVector3.h"
|
|
||||||
#include "KRScene.h"
|
#include "KRScene.h"
|
||||||
#include "KRSceneManager.h"
|
#include "KRSceneManager.h"
|
||||||
#include "KRNode.h"
|
#include "KRNode.h"
|
||||||
@@ -89,7 +88,6 @@ void kraken::set_debug_text(const std::string &print_text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KRContext::KRENGINE_MAX_SHADER_HANDLES = 1000;
|
|
||||||
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
|
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
|
||||||
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
|
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
|
||||||
KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f;
|
KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f;
|
||||||
@@ -104,13 +102,11 @@ void kraken::set_debug_text(const std::string &print_text)
|
|||||||
BOOL isIpad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
|
BOOL isIpad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
|
||||||
BOOL isRetina = [[UIScreen mainScreen] scale] >= 2.0;
|
BOOL isRetina = [[UIScreen mainScreen] scale] >= 2.0;
|
||||||
if(isIpad && isRetina) {
|
if(isIpad && isRetina) {
|
||||||
KRContext::KRENGINE_MAX_SHADER_HANDLES = 100;
|
|
||||||
KRContext::KRENGINE_GPU_MEM_MAX = 64000000 * 2;
|
KRContext::KRENGINE_GPU_MEM_MAX = 64000000 * 2;
|
||||||
KRContext::KRENGINE_GPU_MEM_TARGET = 48000000 * 2;
|
KRContext::KRENGINE_GPU_MEM_TARGET = 48000000 * 2;
|
||||||
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
|
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
|
||||||
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
|
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
|
||||||
} else {
|
} else {
|
||||||
KRContext::KRENGINE_MAX_SHADER_HANDLES = 100;
|
|
||||||
KRContext::KRENGINE_GPU_MEM_MAX = 64000000;
|
KRContext::KRENGINE_GPU_MEM_MAX = 64000000;
|
||||||
KRContext::KRENGINE_GPU_MEM_TARGET = 48000000;
|
KRContext::KRENGINE_GPU_MEM_TARGET = 48000000;
|
||||||
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
|
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
|
||||||
@@ -118,7 +114,6 @@ void kraken::set_debug_text(const std::string &print_text)
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
#else
|
#else
|
||||||
KRContext::KRENGINE_MAX_SHADER_HANDLES = 4000;
|
|
||||||
KRContext::KRENGINE_GPU_MEM_MAX = 256000000;
|
KRContext::KRENGINE_GPU_MEM_MAX = 256000000;
|
||||||
KRContext::KRENGINE_GPU_MEM_TARGET = 192000000;
|
KRContext::KRENGINE_GPU_MEM_TARGET = 192000000;
|
||||||
KRContext::KRENGINE_MAX_TEXTURE_DIM = 8192;
|
KRContext::KRENGINE_MAX_TEXTURE_DIM = 8192;
|
||||||
@@ -202,16 +197,6 @@ void kraken::set_debug_text(const std::string &print_text)
|
|||||||
pScene->renderFrame(defaultFBO, deltaTime, width, height);
|
pScene->renderFrame(defaultFBO, deltaTime, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime
|
|
||||||
{
|
|
||||||
GLint renderBufferWidth = 0, renderBufferHeight = 0;
|
|
||||||
GLDEBUG(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &renderBufferWidth));
|
|
||||||
GLDEBUG(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &renderBufferHeight));
|
|
||||||
[self renderScene:pScene WithDeltaTime:deltaTime AndWidth:renderBufferWidth AndHeight:renderBufferHeight];
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
- (BOOL)loadShaders
|
- (BOOL)loadShaders
|
||||||
{
|
{
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
@@ -256,6 +241,7 @@ void kraken::set_debug_text(const std::string &print_text)
|
|||||||
if(_context) {
|
if(_context) {
|
||||||
delete _context; _context = NULL;
|
delete _context; _context = NULL;
|
||||||
}
|
}
|
||||||
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(int)getParameterCount
|
-(int)getParameterCount
|
||||||
@@ -732,7 +718,7 @@ void kraken::set_debug_text(const std::string &print_text)
|
|||||||
-(void) setSunTemperature:(float)t
|
-(void) setSunTemperature:(float)t
|
||||||
{
|
{
|
||||||
float i = [self getSunIntensity];
|
float i = [self getSunIntensity];
|
||||||
_settings.light_intensity = KRVector3(
|
_settings.light_intensity.init(
|
||||||
(t < 0.5f ? t * 2.0f : 1.0f) * i,
|
(t < 0.5f ? t * 2.0f : 1.0f) * i,
|
||||||
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
|
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
|
||||||
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
|
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
|
||||||
@@ -742,7 +728,7 @@ void kraken::set_debug_text(const std::string &print_text)
|
|||||||
-(void) setSunIntensity:(float)i
|
-(void) setSunIntensity:(float)i
|
||||||
{
|
{
|
||||||
float t = [self getSunTemperature];
|
float t = [self getSunTemperature];
|
||||||
_settings.light_intensity = KRVector3(
|
_settings.light_intensity.init(
|
||||||
(t < 0.5f ? t * 2.0f : 1.0f) * i,
|
(t < 0.5f ? t * 2.0f : 1.0f) * i,
|
||||||
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
|
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
|
||||||
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
|
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
|
||||||
@@ -778,7 +764,7 @@ void kraken::set_debug_text(const std::string &print_text)
|
|||||||
-(void) setAmbientTemperature:(float)t
|
-(void) setAmbientTemperature:(float)t
|
||||||
{
|
{
|
||||||
float i = [self getAmbientIntensity];
|
float i = [self getAmbientIntensity];
|
||||||
_settings.ambient_intensity = KRVector3(
|
_settings.ambient_intensity.init(
|
||||||
(t < 0.5f ? t * 2.0f : 1.0f) * i,
|
(t < 0.5f ? t * 2.0f : 1.0f) * i,
|
||||||
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
|
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
|
||||||
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
|
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
|
||||||
@@ -788,7 +774,7 @@ void kraken::set_debug_text(const std::string &print_text)
|
|||||||
-(void) setAmbientIntensity:(float)i
|
-(void) setAmbientIntensity:(float)i
|
||||||
{
|
{
|
||||||
float t = [self getAmbientTemperature];
|
float t = [self getAmbientTemperature];
|
||||||
_settings.ambient_intensity = KRVector3(
|
_settings.ambient_intensity.init(
|
||||||
(t < 0.5f ? t * 2.0f : 1.0f) * i,
|
(t < 0.5f ? t * 2.0f : 1.0f) * i,
|
||||||
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
|
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
|
||||||
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
|
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
|
||||||
|
|||||||
@@ -1,30 +1,43 @@
|
|||||||
|
//
|
||||||
|
// KRHelpers.cpp
|
||||||
|
// Kraken Engine
|
||||||
|
//
|
||||||
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
|
//
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
#include "KRHelpers.h"
|
#include "KRHelpers.h"
|
||||||
|
|
||||||
|
using namespace hydra;
|
||||||
|
|
||||||
namespace kraken {
|
namespace kraken {
|
||||||
|
|
||||||
void SetUniform(GLint location, const Vector2 &v)
|
void setXMLAttribute(const std::string& base_name, tinyxml2::XMLElement* e, const Vector3& value, const Vector3& default_value)
|
||||||
{
|
|
||||||
if (location != -1) GLDEBUG(glUniform2f(location, v.x, v.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetUniform(GLint location, const Vector3 &v)
|
|
||||||
{
|
|
||||||
if (location != -1) GLDEBUG(glUniform3f(location, v.x, v.y, v.z));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetUniform(GLint location, const Vector4 &v)
|
|
||||||
{
|
|
||||||
if (location != -1) GLDEBUG(glUniform4f(location, v.x, v.y, v.z, v.w));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetUniform(GLint location, const Matrix4 &v)
|
|
||||||
{
|
|
||||||
if (location != -1) GLDEBUG(glUniformMatrix4fv(location, 1, GL_FALSE, v.c));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setXMLAttribute(const std::string &base_name, tinyxml2::XMLElement *e, const Vector3 &value, const Vector3 &default_value)
|
|
||||||
{
|
{
|
||||||
// TODO - Increase number of digits after the decimal in floating point format (6 -> 12?)
|
// TODO - Increase number of digits after the decimal in floating point format (6 -> 12?)
|
||||||
// FINDME, TODO - This needs optimization...
|
// FINDME, TODO - This needs optimization...
|
||||||
@@ -35,7 +48,7 @@ void setXMLAttribute(const std::string &base_name, tinyxml2::XMLElement *e, cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vector3 getXMLAttribute(const std::string &base_name, tinyxml2::XMLElement *e, const Vector3 &default_value)
|
const Vector3 getXMLAttribute(const std::string& base_name, tinyxml2::XMLElement* e, const Vector3& default_value)
|
||||||
{
|
{
|
||||||
Vector3 value;
|
Vector3 value;
|
||||||
if (e->QueryFloatAttribute((base_name + "_x").c_str(), &value.x) == tinyxml2::XML_SUCCESS
|
if (e->QueryFloatAttribute((base_name + "_x").c_str(), &value.x) == tinyxml2::XML_SUCCESS
|
||||||
@@ -47,4 +60,34 @@ const Vector3 getXMLAttribute(const std::string &base_name, tinyxml2::XMLElement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setXMLAttribute(const std::string& base_name, tinyxml2::XMLElement* e, const AABB& value, const AABB& default_value)
|
||||||
|
{
|
||||||
|
// TODO - Increase number of digits after the decimal in floating point format (6 -> 12?)
|
||||||
|
// FINDME, TODO - This needs optimization...
|
||||||
|
if (value != default_value) {
|
||||||
|
e->SetAttribute((base_name + "_min_x").c_str(), value.min.x);
|
||||||
|
e->SetAttribute((base_name + "_min_y").c_str(), value.min.y);
|
||||||
|
e->SetAttribute((base_name + "_min_z").c_str(), value.min.z);
|
||||||
|
|
||||||
|
e->SetAttribute((base_name + "_max_x").c_str(), value.max.x);
|
||||||
|
e->SetAttribute((base_name + "_max_y").c_str(), value.max.y);
|
||||||
|
e->SetAttribute((base_name + "_max_z").c_str(), value.max.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const AABB getXMLAttribute(const std::string& base_name, tinyxml2::XMLElement* e, const AABB& default_value)
|
||||||
|
{
|
||||||
|
AABB value;
|
||||||
|
if (e->QueryFloatAttribute((base_name + "_min_x").c_str(), &value.min.x) == tinyxml2::XML_SUCCESS
|
||||||
|
&& e->QueryFloatAttribute((base_name + "_min_y").c_str(), &value.min.y) == tinyxml2::XML_SUCCESS
|
||||||
|
&& e->QueryFloatAttribute((base_name + "_min_z").c_str(), &value.min.z) == tinyxml2::XML_SUCCESS
|
||||||
|
&& e->QueryFloatAttribute((base_name + "_max_x").c_str(), &value.max.x) == tinyxml2::XML_SUCCESS
|
||||||
|
&& e->QueryFloatAttribute((base_name + "_max_y").c_str(), &value.max.y) == tinyxml2::XML_SUCCESS
|
||||||
|
&& e->QueryFloatAttribute((base_name + "_max_z").c_str(), &value.max.z) == tinyxml2::XML_SUCCESS) {
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace kraken
|
} // namespace kraken
|
||||||
|
|||||||
@@ -1,34 +1,55 @@
|
|||||||
#ifndef KRHELPERS_H
|
//
|
||||||
#define KRHELPERS_H
|
// KRHelpers.h
|
||||||
|
// Kraken Engine
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
//
|
||||||
#include <GL/glew.h>
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
#elif defined(__linux__) || defined(__unix__) || defined(__posix__)
|
//
|
||||||
#include <GL/gl.h>
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
#include <GL/glu.h>
|
// permitted provided that the following conditions are met:
|
||||||
#include <GL/glext.h>
|
//
|
||||||
#elif defined(__APPLE__)
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
#include <OpenGL/gl3.h>
|
// conditions and the following disclaimer.
|
||||||
#include <OpenGL/gl3ext.h>
|
//
|
||||||
#endif
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
#include "../3rdparty/tinyxml2/tinyxml2.h"
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
#define KRMIN(x,y) ((x) < (y) ? (x) : (y))
|
//
|
||||||
#define KRMAX(x,y) ((x) > (y) ? (x) : (y))
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
#define KRCLAMP(x, min, max) (KRMAX(KRMIN(x, max), min))
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
#define KRALIGN(x) ((x + 3) & ~0x03)
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
float const PI = 3.141592653589793f;
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
float const D2R = PI * 2 / 360;
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
namespace kraken {
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
void SetUniform(GLint location, const Vector2 &v);
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
void SetUniform(GLint location, const Vector3 &v);
|
//
|
||||||
void SetUniform(GLint location, const Vector4 &v);
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
void SetUniform(GLint location, const Matrix4 &v);
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
void setXMLAttribute(const std::string &base_name, ::tinyxml2::XMLElement *e, const Vector3 &value, const Vector3 &default_value);
|
//
|
||||||
const Vector3 getXMLAttribute(const std::string &base_name, ::tinyxml2::XMLElement *e, const Vector3 &default_value);
|
|
||||||
} // namespace kraken
|
#pragma once
|
||||||
|
|
||||||
#endif
|
#include "vector2.h"
|
||||||
|
#include "vector3.h"
|
||||||
|
#include "matrix4.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "../3rdparty/tinyxml2/tinyxml2.h"
|
||||||
|
|
||||||
|
#define KRMIN(x,y) ((x) < (y) ? (x) : (y))
|
||||||
|
#define KRMAX(x,y) ((x) > (y) ? (x) : (y))
|
||||||
|
#define KRCLAMP(x, min, max) (KRMAX(KRMIN(x, max), min))
|
||||||
|
#define KRALIGN(x) ((x + 3) & ~0x03)
|
||||||
|
|
||||||
|
float const PI = 3.141592653589793f;
|
||||||
|
float const D2R = PI * 2 / 360;
|
||||||
|
|
||||||
|
namespace kraken {
|
||||||
|
void setXMLAttribute(const std::string& base_name, ::tinyxml2::XMLElement* e, const hydra::Vector3& value, const hydra::Vector3& default_value);
|
||||||
|
void setXMLAttribute(const std::string& base_name, ::tinyxml2::XMLElement* e, const hydra::AABB& value, const hydra::AABB& default_value);
|
||||||
|
const hydra::Vector3 getXMLAttribute(const std::string& base_name, ::tinyxml2::XMLElement* e, const hydra::Vector3& default_value);
|
||||||
|
const hydra::AABB getXMLAttribute(const std::string& base_name, ::tinyxml2::XMLElement* e, const hydra::AABB& default_value);
|
||||||
|
} // namespace kraken
|
||||||
|
|
||||||
|
|||||||
@@ -1,173 +0,0 @@
|
|||||||
//
|
|
||||||
// KRLODGroup.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRLODGroup.h"
|
|
||||||
#include "KRLODSet.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
|
|
||||||
KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name)
|
|
||||||
{
|
|
||||||
m_min_distance = 0.0f;
|
|
||||||
m_max_distance = 0.0f;
|
|
||||||
m_reference = AABB(Vector3::Zero(), Vector3::Zero());
|
|
||||||
m_use_world_units = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRLODGroup::~KRLODGroup()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRLODGroup::getElementName() {
|
|
||||||
return "lod_group";
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
|
||||||
e->SetAttribute("min_distance", m_min_distance);
|
|
||||||
e->SetAttribute("max_distance", m_max_distance);
|
|
||||||
|
|
||||||
e->SetAttribute("reference_min_x", m_reference.min.x);
|
|
||||||
e->SetAttribute("reference_min_y", m_reference.min.y);
|
|
||||||
e->SetAttribute("reference_min_z", m_reference.min.z);
|
|
||||||
|
|
||||||
|
|
||||||
e->SetAttribute("reference_max_x", m_reference.max.x);
|
|
||||||
e->SetAttribute("reference_max_y", m_reference.max.y);
|
|
||||||
e->SetAttribute("reference_max_z", m_reference.max.z);
|
|
||||||
|
|
||||||
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
|
|
||||||
{
|
|
||||||
KRNode::loadXML(e);
|
|
||||||
|
|
||||||
m_min_distance = 0.0f;
|
|
||||||
if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_min_distance = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_max_distance = 0.0f;
|
|
||||||
if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_max_distance = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float x=0.0f, y=0.0f, z=0.0f;
|
|
||||||
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
|
|
||||||
x = 0.0f;
|
|
||||||
}
|
|
||||||
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
|
|
||||||
y = 0.0f;
|
|
||||||
}
|
|
||||||
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
|
|
||||||
z = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_reference.min = Vector3(x,y,z);
|
|
||||||
|
|
||||||
x=0.0f; y=0.0f; z=0.0f;
|
|
||||||
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
|
|
||||||
x = 0.0f;
|
|
||||||
}
|
|
||||||
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
|
|
||||||
y = 0.0f;
|
|
||||||
}
|
|
||||||
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
|
|
||||||
z = 0.0f;
|
|
||||||
}
|
|
||||||
m_reference.max = Vector3(x,y,z);
|
|
||||||
|
|
||||||
m_use_world_units = true;
|
|
||||||
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_use_world_units = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const AABB &KRLODGroup::getReference() const
|
|
||||||
{
|
|
||||||
return m_reference;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLODGroup::setReference(const AABB &reference)
|
|
||||||
{
|
|
||||||
m_reference = reference;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport)
|
|
||||||
{
|
|
||||||
if(m_min_distance == 0 && m_max_distance == 0) {
|
|
||||||
return LOD_VISIBILITY_VISIBLE;
|
|
||||||
} else {
|
|
||||||
float lod_bias = viewport.getLODBias();
|
|
||||||
lod_bias = pow(2.0f, -lod_bias);
|
|
||||||
|
|
||||||
// Compare using squared distances as sqrt is expensive
|
|
||||||
float sqr_distance;
|
|
||||||
float sqr_prestream_distance;
|
|
||||||
|
|
||||||
Vector3 world_camera_position = viewport.getCameraPosition();
|
|
||||||
Vector3 local_camera_position = worldToLocal(world_camera_position);
|
|
||||||
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
|
|
||||||
|
|
||||||
if(m_use_world_units) {
|
|
||||||
Vector3 world_reference_point = localToWorld(local_reference_point);
|
|
||||||
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
|
||||||
sqr_prestream_distance = getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE;
|
|
||||||
} else {
|
|
||||||
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
|
||||||
|
|
||||||
Vector3 world_reference_point = localToWorld(local_reference_point);
|
|
||||||
sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc?
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
float sqr_min_visible_distance = m_min_distance * m_min_distance;
|
|
||||||
float sqr_max_visible_distance = m_max_distance * m_max_distance;
|
|
||||||
if((sqr_distance >= sqr_min_visible_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance || m_max_distance == 0)) {
|
|
||||||
return LOD_VISIBILITY_VISIBLE;
|
|
||||||
} else if((sqr_distance >= sqr_min_visible_distance - sqr_prestream_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance + sqr_prestream_distance || m_max_distance == 0)) {
|
|
||||||
return LOD_VISIBILITY_PRESTREAM;
|
|
||||||
} else {
|
|
||||||
return LOD_VISIBILITY_HIDDEN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRLODGroup::getMinDistance()
|
|
||||||
{
|
|
||||||
return m_min_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRLODGroup::getMaxDistance()
|
|
||||||
{
|
|
||||||
return m_max_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLODGroup::setMinDistance(float min_distance)
|
|
||||||
{
|
|
||||||
m_min_distance = min_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLODGroup::setMaxDistance(float max_distance)
|
|
||||||
{
|
|
||||||
m_max_distance = max_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLODGroup::setUseWorldUnits(bool use_world_units)
|
|
||||||
{
|
|
||||||
m_use_world_units = use_world_units;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRLODGroup::getUseWorldUnits() const
|
|
||||||
{
|
|
||||||
return m_use_world_units;
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
//
|
|
||||||
// KRLODGroup.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRLODGROUP_H
|
|
||||||
#define KRLODGROUP_H
|
|
||||||
|
|
||||||
#include "KRResource.h"
|
|
||||||
#include "KRNode.h"
|
|
||||||
|
|
||||||
class KRLODGroup : public KRNode {
|
|
||||||
public:
|
|
||||||
KRLODGroup(KRScene &scene, std::string name);
|
|
||||||
virtual ~KRLODGroup();
|
|
||||||
virtual std::string getElementName();
|
|
||||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
|
||||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
|
||||||
|
|
||||||
float getMinDistance();
|
|
||||||
float getMaxDistance();
|
|
||||||
void setMinDistance(float min_distance);
|
|
||||||
void setMaxDistance(float max_distance);
|
|
||||||
|
|
||||||
const AABB &getReference() const;
|
|
||||||
void setReference(const AABB &reference);
|
|
||||||
void setUseWorldUnits(bool use_world_units);
|
|
||||||
bool getUseWorldUnits() const;
|
|
||||||
|
|
||||||
LodVisibility calcLODVisibility(const KRViewport &viewport);
|
|
||||||
|
|
||||||
private:
|
|
||||||
float m_min_distance;
|
|
||||||
float m_max_distance;
|
|
||||||
AABB m_reference; // Point of reference, used for distance calculation. Usually set to the bounding box center
|
|
||||||
bool m_use_world_units;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
//
|
|
||||||
// KRLODSet.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRLODSet.h"
|
|
||||||
#include "KRLODGroup.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
|
|
||||||
KRLODSet::KRLODSet(KRScene &scene, std::string name) : KRNode(scene, name)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
KRLODSet::~KRLODSet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRLODSet::getElementName() {
|
|
||||||
return "lod_set";
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRLODSet::saveXML( tinyxml2::XMLNode *parent)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
|
||||||
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLODSet::loadXML(tinyxml2::XMLElement *e)
|
|
||||||
{
|
|
||||||
KRNode::loadXML(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void KRLODSet::updateLODVisibility(const KRViewport &viewport)
|
|
||||||
{
|
|
||||||
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM) {
|
|
||||||
/*
|
|
||||||
// FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues:
|
|
||||||
KRLODGroup *new_active_lod_group = NULL;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Upgrade and downgrade LOD groups as needed
|
|
||||||
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
KRLODGroup *lod_group = dynamic_cast<KRLODGroup *>(*itr);
|
|
||||||
assert(lod_group != NULL);
|
|
||||||
LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible);
|
|
||||||
/*
|
|
||||||
// FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues:
|
|
||||||
if(group_lod_visibility == LOD_VISIBILITY_VISIBLE) {
|
|
||||||
new_active_lod_group = lod_group;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
lod_group->setLODVisibility(group_lod_visibility);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues:
|
|
||||||
bool streamer_ready = false;
|
|
||||||
if(new_active_lod_group == NULL) {
|
|
||||||
streamer_ready = true;
|
|
||||||
} else if(new_active_lod_group->getStreamLevel(viewport) >= kraken_stream_level::STREAM_LEVEL_IN_LQ) {
|
|
||||||
streamer_ready = true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
bool streamer_ready = true;
|
|
||||||
|
|
||||||
if(streamer_ready) {
|
|
||||||
// Upgrade and downgrade LOD groups as needed
|
|
||||||
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
KRLODGroup *lod_group = dynamic_cast<KRLODGroup *>(*itr);
|
|
||||||
assert(lod_group != NULL);
|
|
||||||
LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible);
|
|
||||||
lod_group->setLODVisibility(group_lod_visibility);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KRNode::updateLODVisibility(viewport);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLODSet::setLODVisibility(KRNode::LodVisibility lod_visibility)
|
|
||||||
{
|
|
||||||
if(lod_visibility == LOD_VISIBILITY_HIDDEN) {
|
|
||||||
KRNode::setLODVisibility(lod_visibility);
|
|
||||||
} else if(m_lod_visible != lod_visibility) {
|
|
||||||
// Don't automatically recurse into our children, as only one of those will be activated, by updateLODVisibility
|
|
||||||
if(m_lod_visible == LOD_VISIBILITY_HIDDEN && lod_visibility >= LOD_VISIBILITY_PRESTREAM) {
|
|
||||||
getScene().notify_sceneGraphCreate(this);
|
|
||||||
}
|
|
||||||
m_lod_visible = lod_visibility;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kraken_stream_level KRLODSet::getStreamLevel(const KRViewport &viewport)
|
|
||||||
{
|
|
||||||
KRLODGroup *new_active_lod_group = NULL;
|
|
||||||
|
|
||||||
// Upgrade and downgrade LOD groups as needed
|
|
||||||
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
KRLODGroup *lod_group = dynamic_cast<KRLODGroup *>(*itr);
|
|
||||||
assert(lod_group != NULL);
|
|
||||||
if(lod_group->calcLODVisibility(viewport) == LOD_VISIBILITY_VISIBLE) {
|
|
||||||
new_active_lod_group = lod_group;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(new_active_lod_group) {
|
|
||||||
return new_active_lod_group->getStreamLevel(viewport);
|
|
||||||
} else {
|
|
||||||
return kraken_stream_level::STREAM_LEVEL_IN_HQ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
//
|
|
||||||
// KRLODSet
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRLODSET_H
|
|
||||||
#define KRLODSET_H
|
|
||||||
|
|
||||||
#include "KRResource.h"
|
|
||||||
#include "KRNode.h"
|
|
||||||
|
|
||||||
class KRLODGroup;
|
|
||||||
|
|
||||||
class KRLODSet : public KRNode {
|
|
||||||
public:
|
|
||||||
KRLODSet(KRScene &scene, std::string name);
|
|
||||||
virtual ~KRLODSet();
|
|
||||||
virtual std::string getElementName();
|
|
||||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
|
||||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
|
||||||
|
|
||||||
virtual void updateLODVisibility(const KRViewport &viewport);
|
|
||||||
|
|
||||||
virtual void setLODVisibility(LodVisibility lod_visibility);
|
|
||||||
|
|
||||||
virtual kraken_stream_level getStreamLevel(const KRViewport &viewport);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,485 +0,0 @@
|
|||||||
//
|
|
||||||
// KRLight.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 12-04-05.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
#include "KRLight.h"
|
|
||||||
|
|
||||||
#include "KRNode.h"
|
|
||||||
#include "KRCamera.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
|
|
||||||
#include "KRShaderManager.h"
|
|
||||||
#include "KRShader.h"
|
|
||||||
#include "KRStockGeometry.h"
|
|
||||||
#include "KRDirectionalLight.h"
|
|
||||||
#include "KRSpotLight.h"
|
|
||||||
#include "KRPointLight.h"
|
|
||||||
|
|
||||||
|
|
||||||
KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name)
|
|
||||||
{
|
|
||||||
m_intensity = 1.0f;
|
|
||||||
m_dust_particle_intensity = 1.0f;
|
|
||||||
m_color = Vector3::One();
|
|
||||||
m_flareTexture = "";
|
|
||||||
m_pFlareTexture = NULL;
|
|
||||||
m_flareSize = 0.0;
|
|
||||||
m_flareOcclusionSize = 0.05;
|
|
||||||
m_casts_shadow = true;
|
|
||||||
m_light_shafts = true;
|
|
||||||
m_dust_particle_density = 0.1f;
|
|
||||||
m_dust_particle_size = 1.0f;
|
|
||||||
m_occlusionQuery = 0;
|
|
||||||
|
|
||||||
// Initialize shadow buffers
|
|
||||||
m_cShadowBuffers = 0;
|
|
||||||
for(int iBuffer=0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) {
|
|
||||||
shadowFramebuffer[iBuffer] = 0;
|
|
||||||
shadowDepthTexture[iBuffer] = 0;
|
|
||||||
shadowValid[iBuffer] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KRLight::~KRLight()
|
|
||||||
{
|
|
||||||
if(m_occlusionQuery) {
|
|
||||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
|
||||||
m_occlusionQuery = 0;
|
|
||||||
}
|
|
||||||
allocateShadowBuffers(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
|
||||||
e->SetAttribute("intensity", m_intensity);
|
|
||||||
e->SetAttribute("color_r", m_color.x);
|
|
||||||
e->SetAttribute("color_g", m_color.y);
|
|
||||||
e->SetAttribute("color_b", m_color.z);
|
|
||||||
e->SetAttribute("decay_start", m_decayStart);
|
|
||||||
e->SetAttribute("flare_size", m_flareSize);
|
|
||||||
e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize);
|
|
||||||
e->SetAttribute("flare_texture", m_flareTexture.c_str());
|
|
||||||
e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false");
|
|
||||||
e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false");
|
|
||||||
e->SetAttribute("dust_particle_density", m_dust_particle_density);
|
|
||||||
e->SetAttribute("dust_particle_size", m_dust_particle_size);
|
|
||||||
e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLight::loadXML(tinyxml2::XMLElement *e) {
|
|
||||||
KRNode::loadXML(e);
|
|
||||||
float x=1.0f,y=1.0f,z=1.0f;
|
|
||||||
if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) {
|
|
||||||
x = 1.0;
|
|
||||||
}
|
|
||||||
if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) {
|
|
||||||
y = 1.0;
|
|
||||||
}
|
|
||||||
if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) {
|
|
||||||
z = 1.0;
|
|
||||||
}
|
|
||||||
m_color = Vector3(x,y,z);
|
|
||||||
|
|
||||||
if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_intensity = 100.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_decayStart = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_flareSize = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_flareOcclusionSize = 0.05;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_casts_shadow = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_light_shafts = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dust_particle_density = 0.1f;
|
|
||||||
if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_dust_particle_density = 0.1f;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dust_particle_size = 1.0f;
|
|
||||||
if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_dust_particle_size = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dust_particle_intensity = 1.0f;
|
|
||||||
if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) {
|
|
||||||
m_dust_particle_intensity = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *szFlareTexture = e->Attribute("flare_texture");
|
|
||||||
if(szFlareTexture) {
|
|
||||||
m_flareTexture = szFlareTexture;
|
|
||||||
} else {
|
|
||||||
m_flareTexture = "";
|
|
||||||
}
|
|
||||||
m_pFlareTexture = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLight::setFlareTexture(std::string flare_texture) {
|
|
||||||
m_flareTexture = flare_texture;
|
|
||||||
m_pFlareTexture = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLight::setFlareSize(float flare_size) {
|
|
||||||
m_flareSize = flare_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLight::setFlareOcclusionSize(float occlusion_size) {
|
|
||||||
m_flareOcclusionSize = occlusion_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLight::setIntensity(float intensity) {
|
|
||||||
m_intensity = intensity;
|
|
||||||
}
|
|
||||||
float KRLight::getIntensity() {
|
|
||||||
return m_intensity;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3 &KRLight::getColor() {
|
|
||||||
return m_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLight::setColor(const Vector3 &color) {
|
|
||||||
m_color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLight::setDecayStart(float decayStart) {
|
|
||||||
m_decayStart = decayStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRLight::getDecayStart() {
|
|
||||||
return m_decayStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
|
|
||||||
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && (pCamera->settings.volumetric_environment_enable || pCamera->settings.dust_particle_enable || (pCamera->settings.m_cShadowBuffers > 0 && m_casts_shadow))) {
|
|
||||||
allocateShadowBuffers(configureShadowBufferViewports(viewport));
|
|
||||||
renderShadowBuffers(pCamera);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) {
|
|
||||||
// Render brownian particles for dust floating in air
|
|
||||||
if(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) {
|
|
||||||
|
|
||||||
if(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
|
|
||||||
|
|
||||||
float particle_range = 600.0f;
|
|
||||||
|
|
||||||
int particle_count = m_dust_particle_density * pow(particle_range, 3);
|
|
||||||
if(particle_count > KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES) particle_count = KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES;
|
|
||||||
|
|
||||||
// Enable z-buffer test
|
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
|
||||||
|
|
||||||
Matrix4 particleModelMatrix;
|
|
||||||
particleModelMatrix.scale(particle_range); // Scale the box symetrically to ensure that we don't have an uneven distribution of particles for different angles of the view frustrum
|
|
||||||
particleModelMatrix.translate(viewport.getCameraPosition());
|
|
||||||
|
|
||||||
std::vector<KRDirectionalLight *> this_directional_light;
|
|
||||||
std::vector<KRSpotLight *> this_spot_light;
|
|
||||||
std::vector<KRPointLight *> this_point_light;
|
|
||||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
|
||||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
|
||||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
|
||||||
if(directional_light) {
|
|
||||||
this_directional_light.push_back(directional_light);
|
|
||||||
}
|
|
||||||
if(spot_light) {
|
|
||||||
this_spot_light.push_back(spot_light);
|
|
||||||
}
|
|
||||||
if(point_light) {
|
|
||||||
this_point_light.push_back(point_light);
|
|
||||||
}
|
|
||||||
|
|
||||||
KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("dust_particle", pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, particleModelMatrix, this_point_light, this_directional_light, this_spot_light, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
|
||||||
|
|
||||||
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color * pCamera->settings.dust_particle_intensity * m_dust_particle_intensity * m_intensity);
|
|
||||||
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_PARTICLE_ORIGIN, Matrix4::DotWDiv(Matrix4::Invert(particleModelMatrix), Vector3::Zero()));
|
|
||||||
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_dust_particle_size);
|
|
||||||
|
|
||||||
KRDataBlock particle_index_data;
|
|
||||||
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), particle_index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true, 1.0f);
|
|
||||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && pCamera->settings.volumetric_environment_enable && m_light_shafts) {
|
|
||||||
std::string shader_name = pCamera->settings.volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog";
|
|
||||||
|
|
||||||
std::vector<KRDirectionalLight *> this_directional_light;
|
|
||||||
std::vector<KRSpotLight *> this_spot_light;
|
|
||||||
std::vector<KRPointLight *> this_point_light;
|
|
||||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
|
||||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
|
||||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
|
||||||
if(directional_light) {
|
|
||||||
this_directional_light.push_back(directional_light);
|
|
||||||
}
|
|
||||||
if(spot_light) {
|
|
||||||
this_spot_light.push_back(spot_light);
|
|
||||||
}
|
|
||||||
if(point_light) {
|
|
||||||
this_point_light.push_back(point_light);
|
|
||||||
}
|
|
||||||
|
|
||||||
KRShader *pFogShader = m_pContext->getShaderManager()->getShader(shader_name, pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES);
|
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pFogShader, viewport, Matrix4(), this_point_light, this_directional_light, this_spot_light, 0, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
|
||||||
int slice_count = (int)(pCamera->settings.volumetric_environment_quality * 495.0) + 5;
|
|
||||||
|
|
||||||
float slice_near = -pCamera->settings.getPerspectiveNearZ();
|
|
||||||
float slice_far = -pCamera->settings.volumetric_environment_max_distance;
|
|
||||||
float slice_spacing = (slice_far - slice_near) / slice_count;
|
|
||||||
|
|
||||||
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE, Vector2(slice_near, slice_spacing));
|
|
||||||
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
|
|
||||||
|
|
||||||
KRDataBlock index_data;
|
|
||||||
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getVolumetricLightingVertexes(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true, 1.0f);
|
|
||||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
|
|
||||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
|
||||||
|
|
||||||
|
|
||||||
Matrix4 occlusion_test_sphere_matrix = Matrix4();
|
|
||||||
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
|
|
||||||
occlusion_test_sphere_matrix.translate(m_localTranslation);
|
|
||||||
if(m_parentNode) {
|
|
||||||
occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader("occlusion_test", *pCamera, point_lights, directional_lights, spot_lights, 0, viewport, occlusion_test_sphere_matrix, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
|
||||||
|
|
||||||
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
|
|
||||||
#if TARGET_OS_IPHONE
|
|
||||||
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
|
||||||
#else
|
|
||||||
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
|
||||||
if(sphereModels.size()) {
|
|
||||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
|
||||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
|
||||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
|
||||||
#else
|
|
||||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
|
||||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
|
||||||
|
|
||||||
if(m_occlusionQuery) {
|
|
||||||
GLuint params = 0;
|
|
||||||
GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms));
|
|
||||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
|
||||||
|
|
||||||
if(params) {
|
|
||||||
|
|
||||||
if(!m_pFlareTexture && m_flareTexture.size()) {
|
|
||||||
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pFlareTexture) {
|
|
||||||
// Disable z-buffer test
|
|
||||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
|
||||||
|
|
||||||
// Render light flare on transparency pass
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
|
|
||||||
|
|
||||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize);
|
|
||||||
m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 0.0f, KRTexture::TEXTURE_USAGE_LIGHT_FLARE);
|
|
||||||
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
|
||||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLight::allocateShadowBuffers(int cBuffers) {
|
|
||||||
// First deallocate buffers no longer needed
|
|
||||||
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
|
|
||||||
if (shadowDepthTexture[iShadow]) {
|
|
||||||
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
|
|
||||||
shadowDepthTexture[iShadow] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shadowFramebuffer[iShadow]) {
|
|
||||||
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
|
|
||||||
shadowFramebuffer[iShadow] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate newly required buffers
|
|
||||||
for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
|
|
||||||
Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
|
|
||||||
|
|
||||||
if(!shadowDepthTexture[iShadow]) {
|
|
||||||
shadowValid[iShadow] = false;
|
|
||||||
|
|
||||||
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
|
|
||||||
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
|
|
||||||
// ===== Create offscreen shadow framebuffer object =====
|
|
||||||
|
|
||||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
|
||||||
|
|
||||||
// ----- Create Depth Texture for shadowFramebuffer -----
|
|
||||||
GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
|
|
||||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
|
||||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
|
||||||
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
|
||||||
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
|
||||||
#if GL_EXT_shadow_samplers
|
|
||||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
|
|
||||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
|
|
||||||
#endif
|
|
||||||
GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, viewportSize.x, viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
|
|
||||||
|
|
||||||
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_cShadowBuffers = cBuffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void KRLight::deleteBuffers()
|
|
||||||
{
|
|
||||||
// Called when this light wasn't used in the last frame, so we can free the resources for use by other lights
|
|
||||||
allocateShadowBuffers(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLight::invalidateShadowBuffers()
|
|
||||||
{
|
|
||||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
|
||||||
shadowValid[iShadow] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLight::renderShadowBuffers(KRCamera *pCamera)
|
|
||||||
{
|
|
||||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
|
||||||
if(!shadowValid[iShadow]) {
|
|
||||||
shadowValid[iShadow] = true;
|
|
||||||
|
|
||||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
|
||||||
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
|
|
||||||
|
|
||||||
GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y));
|
|
||||||
|
|
||||||
GLDEBUG(glClearDepthf(0.0f));
|
|
||||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
|
||||||
|
|
||||||
GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2));
|
|
||||||
|
|
||||||
GLDEBUG(glClearDepthf(1.0f));
|
|
||||||
|
|
||||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
|
||||||
|
|
||||||
GLDEBUG(glDisable(GL_DITHER));
|
|
||||||
|
|
||||||
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
|
|
||||||
//GLDEBUG(glEnable(GL_CULL_FACE));
|
|
||||||
GLDEBUG(glDisable(GL_CULL_FACE));
|
|
||||||
|
|
||||||
// Enable z-buffer test
|
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
|
||||||
GLDEBUG(glDepthFunc(GL_LESS));
|
|
||||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
|
||||||
|
|
||||||
// Disable alpha blending as we are using alpha channel for packed depth info
|
|
||||||
GLDEBUG(glDisable(GL_BLEND));
|
|
||||||
|
|
||||||
// Use shader program
|
|
||||||
KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
|
|
||||||
|
|
||||||
getContext().getShaderManager()->selectShader(*pCamera, shadowShader, m_shadowViewports[iShadow], Matrix4(), std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, KRNode::RENDER_PASS_SHADOWMAP, Vector3::Zero(), 0.0f, Vector4::Zero());
|
|
||||||
|
|
||||||
|
|
||||||
getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true);
|
|
||||||
|
|
||||||
GLDEBUG(glEnable(GL_CULL_FACE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int KRLight::getShadowBufferCount()
|
|
||||||
{
|
|
||||||
int cBuffers=0;
|
|
||||||
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) {
|
|
||||||
if(shadowValid[iBuffer]) {
|
|
||||||
cBuffers++;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cBuffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint *KRLight::getShadowTextures()
|
|
||||||
{
|
|
||||||
return shadowDepthTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRViewport *KRLight::getShadowViewports()
|
|
||||||
{
|
|
||||||
return m_shadowViewports;
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
//
|
|
||||||
// KRLight.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 12-04-05.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRLIGHT_H
|
|
||||||
#define KRLIGHT_H
|
|
||||||
|
|
||||||
#include "KRResource.h"
|
|
||||||
#include "KRNode.h"
|
|
||||||
#include "KRTexture.h"
|
|
||||||
|
|
||||||
static const float KRLIGHT_MIN_INFLUENCE = 0.15f; // 0.05f
|
|
||||||
|
|
||||||
// KRENGINE_MAX_SHADOW_BUFFERS must be at least 6 to allow omni-directional lights to render cube maps
|
|
||||||
|
|
||||||
#define KRENGINE_MAX_SHADOW_BUFFERS 6
|
|
||||||
#define KRENGINE_SHADOW_MAP_WIDTH 1024
|
|
||||||
#define KRENGINE_SHADOW_MAP_HEIGHT 1024
|
|
||||||
|
|
||||||
class KRLight : public KRNode {
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
virtual ~KRLight();
|
|
||||||
virtual std::string getElementName() = 0;
|
|
||||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
|
||||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
|
||||||
|
|
||||||
void setIntensity(float intensity);
|
|
||||||
float getIntensity();
|
|
||||||
void setDecayStart(float decayStart);
|
|
||||||
float getDecayStart();
|
|
||||||
const Vector3 &getColor();
|
|
||||||
void setColor(const Vector3 &color);
|
|
||||||
|
|
||||||
void setFlareTexture(std::string flare_texture);
|
|
||||||
void setFlareSize(float flare_size);
|
|
||||||
void setFlareOcclusionSize(float occlusion_size);
|
|
||||||
void deleteBuffers();
|
|
||||||
|
|
||||||
virtual void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
|
|
||||||
|
|
||||||
int getShadowBufferCount();
|
|
||||||
GLuint *getShadowTextures();
|
|
||||||
KRViewport *getShadowViewports();
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
KRLight(KRScene &scene, std::string name);
|
|
||||||
|
|
||||||
float m_intensity;
|
|
||||||
float m_decayStart;
|
|
||||||
Vector3 m_color;
|
|
||||||
|
|
||||||
std::string m_flareTexture;
|
|
||||||
KRTexture *m_pFlareTexture;
|
|
||||||
float m_flareSize;
|
|
||||||
float m_flareOcclusionSize;
|
|
||||||
|
|
||||||
bool m_casts_shadow;
|
|
||||||
bool m_light_shafts;
|
|
||||||
float m_dust_particle_density;
|
|
||||||
float m_dust_particle_size;
|
|
||||||
float m_dust_particle_intensity;
|
|
||||||
|
|
||||||
GLuint m_occlusionQuery; // Occlusion query for attenuating occluded flares
|
|
||||||
|
|
||||||
|
|
||||||
// Shadow Maps
|
|
||||||
int m_cShadowBuffers;
|
|
||||||
GLuint shadowFramebuffer[KRENGINE_MAX_SHADOW_BUFFERS], shadowDepthTexture[KRENGINE_MAX_SHADOW_BUFFERS];
|
|
||||||
bool shadowValid[KRENGINE_MAX_SHADOW_BUFFERS];
|
|
||||||
KRViewport m_shadowViewports[KRENGINE_MAX_SHADOW_BUFFERS];
|
|
||||||
|
|
||||||
void allocateShadowBuffers(int cBuffers);
|
|
||||||
void invalidateShadowBuffers();
|
|
||||||
|
|
||||||
virtual int configureShadowBufferViewports(const KRViewport &viewport);
|
|
||||||
void renderShadowBuffers(KRCamera *pCamera);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
//
|
|
||||||
// KRLocator.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRLocator.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
|
|
||||||
KRLocator::KRLocator(KRScene &scene, std::string name) : KRNode(scene, name)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
KRLocator::~KRLocator()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRLocator::getElementName() {
|
|
||||||
return "locator";
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRLocator::saveXML( tinyxml2::XMLNode *parent)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
|
||||||
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRLocator::loadXML(tinyxml2::XMLElement *e)
|
|
||||||
{
|
|
||||||
KRNode::loadXML(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
unordered_map<std::string, boost::variant<int, double, bool, std::string> > &KRLocator::getUserAttributes()
|
|
||||||
{
|
|
||||||
return m_userAttributes;
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
//
|
|
||||||
// KRLocator
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 2012-12-06.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRLOCATOR_H
|
|
||||||
#define KRLOCATOR_H
|
|
||||||
|
|
||||||
#include "KRResource.h"
|
|
||||||
#include "KRNode.h"
|
|
||||||
#include "KRTexture.h"
|
|
||||||
|
|
||||||
#include "boost/variant.hpp"
|
|
||||||
|
|
||||||
class KRLocator : public KRNode {
|
|
||||||
public:
|
|
||||||
KRLocator(KRScene &scene, std::string name);
|
|
||||||
virtual ~KRLocator();
|
|
||||||
virtual std::string getElementName();
|
|
||||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
|
||||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
|
||||||
unordered_map<std::string, boost::variant<int, double, bool, std::string> > &getUserAttributes();
|
|
||||||
|
|
||||||
private:
|
|
||||||
unordered_map<std::string, boost::variant<int, double, bool, std::string> > m_userAttributes;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,422 +0,0 @@
|
|||||||
//
|
|
||||||
// KRMaterial.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#include "KRMaterial.h"
|
|
||||||
#include "KRTextureManager.h"
|
|
||||||
|
|
||||||
#include "KRContext.h"
|
|
||||||
|
|
||||||
KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) {
|
|
||||||
m_name = szName;
|
|
||||||
m_pAmbientMap = NULL;
|
|
||||||
m_pDiffuseMap = NULL;
|
|
||||||
m_pSpecularMap = NULL;
|
|
||||||
m_pNormalMap = NULL;
|
|
||||||
m_pReflectionMap = NULL;
|
|
||||||
m_pReflectionCube = NULL;
|
|
||||||
m_ambientColor = Vector3::Zero();
|
|
||||||
m_diffuseColor = Vector3::One();
|
|
||||||
m_specularColor = Vector3::One();
|
|
||||||
m_reflectionColor = Vector3::Zero();
|
|
||||||
m_tr = (GLfloat)1.0f;
|
|
||||||
m_ns = (GLfloat)0.0f;
|
|
||||||
m_ambientMap = "";
|
|
||||||
m_diffuseMap = "";
|
|
||||||
m_specularMap = "";
|
|
||||||
m_normalMap = "";
|
|
||||||
m_reflectionMap = "";
|
|
||||||
m_reflectionCube = "";
|
|
||||||
m_ambientMapOffset = Vector2(0.0f, 0.0f);
|
|
||||||
m_specularMapOffset = Vector2(0.0f, 0.0f);
|
|
||||||
m_diffuseMapOffset = Vector2(0.0f, 0.0f);
|
|
||||||
m_ambientMapScale = Vector2(1.0f, 1.0f);
|
|
||||||
m_specularMapScale = Vector2(1.0f, 1.0f);
|
|
||||||
m_diffuseMapScale = Vector2(1.0f, 1.0f);
|
|
||||||
m_reflectionMapOffset = Vector2(0.0f, 0.0f);
|
|
||||||
m_reflectionMapScale = Vector2(1.0f, 1.0f);
|
|
||||||
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRMaterial::~KRMaterial() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRMaterial::getExtension() {
|
|
||||||
return "mtl";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRMaterial::needsVertexTangents()
|
|
||||||
{
|
|
||||||
return m_normalMap.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRMaterial::save(KRDataBlock &data) {
|
|
||||||
std::stringstream stream;
|
|
||||||
stream.precision(std::numeric_limits<long double>::digits10);
|
|
||||||
stream.setf(std::ios::fixed,std::ios::floatfield);
|
|
||||||
|
|
||||||
stream << "newmtl " << m_name;
|
|
||||||
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
|
|
||||||
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
|
|
||||||
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
|
|
||||||
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
|
|
||||||
stream << "\nTr " << m_tr;
|
|
||||||
stream << "\nNs " << m_ns;
|
|
||||||
if(m_ambientMap.size()) {
|
|
||||||
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
|
|
||||||
} else {
|
|
||||||
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
|
||||||
}
|
|
||||||
if(m_diffuseMap.size()) {
|
|
||||||
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
|
|
||||||
} else {
|
|
||||||
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
|
||||||
}
|
|
||||||
if(m_specularMap.size()) {
|
|
||||||
stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n";
|
|
||||||
} else {
|
|
||||||
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
|
||||||
}
|
|
||||||
if(m_normalMap.size()) {
|
|
||||||
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
|
|
||||||
} else {
|
|
||||||
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
|
||||||
}
|
|
||||||
if(m_reflectionMap.size()) {
|
|
||||||
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
|
|
||||||
} else {
|
|
||||||
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
|
||||||
}
|
|
||||||
if(m_reflectionCube.size()) {
|
|
||||||
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
|
|
||||||
} else {
|
|
||||||
stream << "\n# map_ReflectionCube cubemapname";
|
|
||||||
}
|
|
||||||
switch(m_alpha_mode) {
|
|
||||||
case KRMATERIAL_ALPHA_MODE_OPAQUE:
|
|
||||||
stream << "\nalpha_mode opaque";
|
|
||||||
break;
|
|
||||||
case KRMATERIAL_ALPHA_MODE_TEST:
|
|
||||||
stream << "\nalpha_mode test";
|
|
||||||
break;
|
|
||||||
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
|
|
||||||
stream << "\nalpha_mode blendoneside";
|
|
||||||
break;
|
|
||||||
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
|
|
||||||
stream << "\nalpha_mode blendtwoside";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
|
|
||||||
|
|
||||||
stream << "\n";
|
|
||||||
data.append(stream.str());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
|
||||||
m_ambientMap = texture_name;
|
|
||||||
m_ambientMapScale = texture_scale;
|
|
||||||
m_ambientMapOffset = texture_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
|
||||||
m_diffuseMap = texture_name;
|
|
||||||
m_diffuseMapScale = texture_scale;
|
|
||||||
m_diffuseMapOffset = texture_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
|
||||||
m_specularMap = texture_name;
|
|
||||||
m_specularMapScale = texture_scale;
|
|
||||||
m_specularMapOffset = texture_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
|
||||||
m_normalMap = texture_name;
|
|
||||||
m_normalMapScale = texture_scale;
|
|
||||||
m_normalMapOffset = texture_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
|
||||||
m_reflectionMap = texture_name;
|
|
||||||
m_reflectionMapScale = texture_scale;
|
|
||||||
m_reflectionMapOffset = texture_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setReflectionCube(std::string texture_name) {
|
|
||||||
m_reflectionCube = texture_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) {
|
|
||||||
m_alpha_mode = alpha_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRMaterial::alpha_mode_type KRMaterial::getAlphaMode() {
|
|
||||||
return m_alpha_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setAmbient(const Vector3 &c) {
|
|
||||||
m_ambientColor = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setDiffuse(const Vector3 &c) {
|
|
||||||
m_diffuseColor = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setSpecular(const Vector3 &c) {
|
|
||||||
m_specularColor = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setReflection(const Vector3 &c) {
|
|
||||||
m_reflectionColor = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setTransparency(GLfloat a) {
|
|
||||||
if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
|
|
||||||
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
|
||||||
}
|
|
||||||
m_tr = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::setShininess(GLfloat s) {
|
|
||||||
m_ns = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRMaterial::isTransparent() {
|
|
||||||
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::preStream(float lodCoverage)
|
|
||||||
{
|
|
||||||
getTextures();
|
|
||||||
|
|
||||||
if(m_pAmbientMap) {
|
|
||||||
m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pDiffuseMap) {
|
|
||||||
m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pNormalMap) {
|
|
||||||
m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pSpecularMap) {
|
|
||||||
m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pReflectionMap) {
|
|
||||||
m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pReflectionCube) {
|
|
||||||
m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
kraken_stream_level KRMaterial::getStreamLevel()
|
|
||||||
{
|
|
||||||
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
|
|
||||||
|
|
||||||
getTextures();
|
|
||||||
|
|
||||||
if(m_pAmbientMap) {
|
|
||||||
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pDiffuseMap) {
|
|
||||||
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pNormalMap) {
|
|
||||||
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pSpecularMap) {
|
|
||||||
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pReflectionMap) {
|
|
||||||
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pReflectionCube) {
|
|
||||||
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
|
|
||||||
}
|
|
||||||
|
|
||||||
return stream_level;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterial::getTextures()
|
|
||||||
{
|
|
||||||
if(!m_pAmbientMap && m_ambientMap.size()) {
|
|
||||||
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
|
|
||||||
}
|
|
||||||
if(!m_pDiffuseMap && m_diffuseMap.size()) {
|
|
||||||
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
|
|
||||||
}
|
|
||||||
if(!m_pNormalMap && m_normalMap.size()) {
|
|
||||||
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
|
|
||||||
}
|
|
||||||
if(!m_pSpecularMap && m_specularMap.size()) {
|
|
||||||
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
|
|
||||||
}
|
|
||||||
if(!m_pReflectionMap && m_reflectionMap.size()) {
|
|
||||||
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
|
|
||||||
}
|
|
||||||
if(!m_pReflectionCube && m_reflectionCube.size()) {
|
|
||||||
m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRMaterial::bind(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const std::vector<KRBone *> &bones, const std::vector<Matrix4> &bind_poses, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, float lod_coverage) {
|
|
||||||
bool bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
|
|
||||||
|
|
||||||
getTextures();
|
|
||||||
|
|
||||||
Vector2 default_scale = Vector2::One();
|
|
||||||
Vector2 default_offset = Vector2::Zero();
|
|
||||||
|
|
||||||
bool bHasReflection = m_reflectionColor != Vector3::Zero();
|
|
||||||
bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap;
|
|
||||||
bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap;
|
|
||||||
bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap;
|
|
||||||
bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection;
|
|
||||||
bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection;
|
|
||||||
bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap;
|
|
||||||
bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
|
||||||
|
|
||||||
KRShader *pShader = getContext().getShaderManager()->getShader("ObjectShader", pCamera, point_lights, directional_lights, spot_lights, bones.size(), bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_normalMapScale != default_scale && bNormalMap, m_reflectionMapScale != default_scale && bReflectionMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_normalMapOffset != default_offset && bNormalMap, m_reflectionMapOffset != default_offset && bReflectionMap, bAlphaTest, bAlphaBlend, renderPass, rim_power != 0.0f);
|
|
||||||
|
|
||||||
|
|
||||||
Vector4 fade_color;
|
|
||||||
if(!getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, rim_power, fade_color)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind bones
|
|
||||||
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
|
||||||
GLfloat bone_mats[256 * 16];
|
|
||||||
GLfloat *bone_mat_component = bone_mats;
|
|
||||||
for(int bone_index=0; bone_index < bones.size(); bone_index++) {
|
|
||||||
KRBone *bone = bones[bone_index];
|
|
||||||
|
|
||||||
// Vector3 initialRotation = bone->getInitialLocalRotation();
|
|
||||||
// Vector3 rotation = bone->getLocalRotation();
|
|
||||||
// Vector3 initialTranslation = bone->getInitialLocalTranslation();
|
|
||||||
// Vector3 translation = bone->getLocalTranslation();
|
|
||||||
// Vector3 initialScale = bone->getInitialLocalScale();
|
|
||||||
// Vector3 scale = bone->getLocalScale();
|
|
||||||
//
|
|
||||||
//printf("%s - delta rotation: %.4f %.4f %.4f\n", bone->getName().c_str(), (rotation.x - initialRotation.x) * 180.0 / M_PI, (rotation.y - initialRotation.y) * 180.0 / M_PI, (rotation.z - initialRotation.z) * 180.0 / M_PI);
|
|
||||||
//printf("%s - delta translation: %.4f %.4f %.4f\n", bone->getName().c_str(), translation.x - initialTranslation.x, translation.y - initialTranslation.y, translation.z - initialTranslation.z);
|
|
||||||
// printf("%s - delta scale: %.4f %.4f %.4f\n", bone->getName().c_str(), scale.x - initialScale.x, scale.y - initialScale.y, scale.z - initialScale.z);
|
|
||||||
|
|
||||||
Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
|
|
||||||
Matrix4 active_mat = bone->getActivePoseMatrix();
|
|
||||||
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
|
|
||||||
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
|
|
||||||
Matrix4 t = (inv_bind_mat * active_mat);
|
|
||||||
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
|
|
||||||
for(int i=0; i < 16; i++) {
|
|
||||||
*bone_mat_component++ = t[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
|
||||||
glUniformMatrix4fv(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS], bones.size(), GL_FALSE, bone_mats);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_AMBIENT, m_ambientColor + pCamera->settings.ambient_intensity);
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
|
||||||
// We pre-multiply the light color with the material color in the forward renderer
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, Vector3(m_diffuseColor.x * pCamera->settings.light_intensity.x, m_diffuseColor.y * pCamera->settings.light_intensity.y, m_diffuseColor.z * pCamera->settings.light_intensity.z));
|
|
||||||
} else {
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
|
||||||
// We pre-multiply the light color with the material color in the forward renderer
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, Vector3(m_specularColor.x * pCamera->settings.light_intensity.x, m_specularColor.y * pCamera->settings.light_intensity.y, m_specularColor.z * pCamera->settings.light_intensity.z));
|
|
||||||
} else {
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset);
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset);
|
|
||||||
|
|
||||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr);
|
|
||||||
|
|
||||||
if(bDiffuseMap) {
|
|
||||||
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bSpecMap) {
|
|
||||||
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bNormalMap) {
|
|
||||||
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bReflectionCubeMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
|
|
||||||
m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube, lod_coverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bReflectionMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
|
|
||||||
// GL_TEXTURE7 is used for reading the depth buffer in gBuffer pass 2 and re-used for the reflection map in gBuffer Pass 3 and in forward rendering
|
|
||||||
m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &KRMaterial::getName() const
|
|
||||||
{
|
|
||||||
return m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
//
|
|
||||||
// KRMaterial.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#include "KRTexture.h"
|
|
||||||
#include "KRShaderManager.h"
|
|
||||||
#include "KRShader.h"
|
|
||||||
#include "KRCamera.h"
|
|
||||||
#include "KRResource.h"
|
|
||||||
#include "KRScene.h"
|
|
||||||
#include "KRBone.h"
|
|
||||||
|
|
||||||
#ifndef KRMATERIAL_H
|
|
||||||
#define KRMATERIAL_H
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class KRTextureManager;
|
|
||||||
class KRContext;
|
|
||||||
|
|
||||||
class KRMaterial : public KRResource {
|
|
||||||
public:
|
|
||||||
typedef enum {
|
|
||||||
KRMATERIAL_ALPHA_MODE_OPAQUE, // Non-transparent materials
|
|
||||||
KRMATERIAL_ALPHA_MODE_TEST, // Alpha in diffuse texture is interpreted as punch-through when < 0.5
|
|
||||||
KRMATERIAL_ALPHA_MODE_BLENDONESIDE, // Blended alpha with backface culling
|
|
||||||
KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE // Blended alpha rendered in two passes. First pass renders backfaces; second pass renders frontfaces.
|
|
||||||
} alpha_mode_type;
|
|
||||||
|
|
||||||
KRMaterial(KRContext &context, const char *szName);
|
|
||||||
virtual ~KRMaterial();
|
|
||||||
|
|
||||||
virtual std::string getExtension();
|
|
||||||
virtual bool save(KRDataBlock &data);
|
|
||||||
|
|
||||||
|
|
||||||
void setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
|
|
||||||
void setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
|
|
||||||
void setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
|
|
||||||
void setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
|
|
||||||
void setReflectionCube(std::string texture_name);
|
|
||||||
void setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
|
|
||||||
void setAmbient(const Vector3 &c);
|
|
||||||
void setDiffuse(const Vector3 &c);
|
|
||||||
void setSpecular(const Vector3 &c);
|
|
||||||
void setReflection(const Vector3 &c);
|
|
||||||
void setTransparency(GLfloat a);
|
|
||||||
void setShininess(GLfloat s);
|
|
||||||
void setAlphaMode(alpha_mode_type blend_mode);
|
|
||||||
alpha_mode_type getAlphaMode();
|
|
||||||
|
|
||||||
|
|
||||||
bool isTransparent();
|
|
||||||
const std::string &getName() const;
|
|
||||||
|
|
||||||
bool bind(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const std::vector<KRBone *> &bones, const std::vector<Matrix4> &bind_poses, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, float lod_coverage = 0.0f);
|
|
||||||
|
|
||||||
bool needsVertexTangents();
|
|
||||||
|
|
||||||
kraken_stream_level getStreamLevel();
|
|
||||||
void preStream(float lodCoverage);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_name;
|
|
||||||
|
|
||||||
KRTexture *m_pAmbientMap; // mtl map_Ka value
|
|
||||||
KRTexture *m_pDiffuseMap; // mtl map_Kd value
|
|
||||||
KRTexture *m_pSpecularMap; // mtl map_Ks value
|
|
||||||
KRTexture *m_pReflectionMap; // mtl refl value
|
|
||||||
KRTexture *m_pReflectionCube;
|
|
||||||
KRTexture *m_pNormalMap; // mtl map_Normal value
|
|
||||||
std::string m_ambientMap;
|
|
||||||
std::string m_diffuseMap;
|
|
||||||
std::string m_specularMap;
|
|
||||||
std::string m_reflectionMap;
|
|
||||||
std::string m_reflectionCube;
|
|
||||||
std::string m_normalMap;
|
|
||||||
|
|
||||||
Vector2 m_ambientMapScale;
|
|
||||||
Vector2 m_ambientMapOffset;
|
|
||||||
Vector2 m_diffuseMapScale;
|
|
||||||
Vector2 m_diffuseMapOffset;
|
|
||||||
Vector2 m_specularMapScale;
|
|
||||||
Vector2 m_specularMapOffset;
|
|
||||||
Vector2 m_reflectionMapScale;
|
|
||||||
Vector2 m_reflectionMapOffset;
|
|
||||||
Vector2 m_normalMapScale;
|
|
||||||
Vector2 m_normalMapOffset;
|
|
||||||
|
|
||||||
Vector3 m_ambientColor; // Ambient rgb
|
|
||||||
Vector3 m_diffuseColor; // Diffuse rgb
|
|
||||||
Vector3 m_specularColor; // Specular rgb
|
|
||||||
Vector3 m_reflectionColor; // Reflection rgb
|
|
||||||
|
|
||||||
//GLfloat m_ka_r, m_ka_g, m_ka_b; // Ambient rgb
|
|
||||||
//GLfloat m_kd_r, m_kd_g, m_kd_b; // Diffuse rgb
|
|
||||||
//GLfloat m_ks_r, m_ks_g, m_ks_b; // Specular rgb
|
|
||||||
//GLfloat m_kr_r, m_kr_g, m_kr_b; // Reflection rgb
|
|
||||||
|
|
||||||
GLfloat m_tr; // Transparency
|
|
||||||
GLfloat m_ns; // Shininess
|
|
||||||
|
|
||||||
alpha_mode_type m_alpha_mode;
|
|
||||||
|
|
||||||
void getTextures();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,288 +0,0 @@
|
|||||||
//
|
|
||||||
// KRMaterialManager.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
#include "KRMaterialManager.h"
|
|
||||||
|
|
||||||
|
|
||||||
KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager) : KRContextObject(context)
|
|
||||||
{
|
|
||||||
m_pTextureManager = pTextureManager;
|
|
||||||
m_pShaderManager = pShaderManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRMaterialManager::~KRMaterialManager() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials()
|
|
||||||
{
|
|
||||||
return m_materials;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterialManager::configure(bool blend_enable, GLenum blend_src, GLenum blend_dest, bool depth_test_enable, GLenum depth_func, bool depth_write_enable) {
|
|
||||||
if(blend_enable) {
|
|
||||||
GLDEBUG(glEnable(GL_BLEND));
|
|
||||||
GLDEBUG(glBlendFunc(blend_src, blend_dest));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glDisable(GL_BLEND));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(depth_test_enable) {
|
|
||||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
|
||||||
GLDEBUG(glDepthFunc(depth_func));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(depth_write_enable) {
|
|
||||||
GLDEBUG(glDepthMask(GL_TRUE));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glDepthMask(GL_FALSE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KRMaterial *KRMaterialManager::getMaterial(const std::string &name) {
|
|
||||||
std::string lowerName = name;
|
|
||||||
std::transform(lowerName.begin(), lowerName.end(),
|
|
||||||
lowerName.begin(), ::tolower);
|
|
||||||
|
|
||||||
|
|
||||||
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName);
|
|
||||||
if(itr == m_materials.end()) {
|
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
|
|
||||||
// Not found
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
return (*itr).second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMaterialManager::add(KRMaterial *new_material) {
|
|
||||||
// FINDME, TODO - Potential memory leak if multiple materials with the same name are added
|
|
||||||
std::string lowerName = new_material->getName();
|
|
||||||
std::transform(lowerName.begin(), lowerName.end(),
|
|
||||||
lowerName.begin(), ::tolower);
|
|
||||||
|
|
||||||
m_materials[lowerName] = new_material;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRMaterialManager::load(const char *szName, KRDataBlock *data) {
|
|
||||||
KRMaterial *pMaterial = NULL;
|
|
||||||
char szSymbol[16][256];
|
|
||||||
data->lock();
|
|
||||||
|
|
||||||
char *pScan = (char *)data->getStart();
|
|
||||||
char *pEnd = (char *)data->getEnd();
|
|
||||||
while(pScan < pEnd) {
|
|
||||||
|
|
||||||
// Scan through whitespace
|
|
||||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
|
||||||
pScan++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(*pScan == '#') {
|
|
||||||
// Line is a comment line
|
|
||||||
|
|
||||||
// Scan to the end of the line
|
|
||||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
|
||||||
pScan++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int cSymbols = 0;
|
|
||||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
|
||||||
|
|
||||||
char *pDest = szSymbol[cSymbols++];
|
|
||||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
|
||||||
if(*pScan >= 'A' && *pScan <= 'Z') {
|
|
||||||
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
|
|
||||||
} else {
|
|
||||||
*pDest++ = *pScan++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*pDest = '\0';
|
|
||||||
|
|
||||||
// Scan through whitespace, but don't advance to next line
|
|
||||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
|
||||||
pScan++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(cSymbols > 0) {
|
|
||||||
|
|
||||||
if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
|
|
||||||
|
|
||||||
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
|
|
||||||
m_materials[szSymbol[1]] = pMaterial;
|
|
||||||
}
|
|
||||||
if(pMaterial != NULL) {
|
|
||||||
if(strcmp(szSymbol[0], "alpha_mode") == 0) {
|
|
||||||
if(cSymbols == 2) {
|
|
||||||
if(strcmp(szSymbol[1], "test") == 0) {
|
|
||||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
|
|
||||||
} else if(strcmp(szSymbol[1], "blendoneside") == 0) {
|
|
||||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
|
||||||
} else if(strcmp(szSymbol[1], "blendtwoside") == 0) {
|
|
||||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
|
||||||
} else {
|
|
||||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(strcmp(szSymbol[0], "ka") == 0) {
|
|
||||||
char *pScan2 = szSymbol[1];
|
|
||||||
float r = strtof(pScan2, &pScan2);
|
|
||||||
if(cSymbols == 2) {
|
|
||||||
pMaterial->setAmbient(Vector3(r, r, r));
|
|
||||||
} else if(cSymbols == 4) {
|
|
||||||
pScan2 = szSymbol[2];
|
|
||||||
float g = strtof(pScan2, &pScan2);
|
|
||||||
pScan2 = szSymbol[3];
|
|
||||||
float b = strtof(pScan2, &pScan2);
|
|
||||||
pMaterial->setAmbient(Vector3(r, g, b));
|
|
||||||
}
|
|
||||||
} else if(strcmp(szSymbol[0], "kd") == 0) {
|
|
||||||
char *pScan2 = szSymbol[1];
|
|
||||||
float r = strtof(pScan2, &pScan2);
|
|
||||||
if(cSymbols == 2) {
|
|
||||||
pMaterial->setDiffuse(Vector3(r, r, r));
|
|
||||||
} else if(cSymbols == 4) {
|
|
||||||
pScan2 = szSymbol[2];
|
|
||||||
float g = strtof(pScan2, &pScan2);
|
|
||||||
pScan2 = szSymbol[3];
|
|
||||||
float b = strtof(pScan2, &pScan2);
|
|
||||||
pMaterial->setDiffuse(Vector3(r, g, b));
|
|
||||||
}
|
|
||||||
} else if(strcmp(szSymbol[0], "ks") == 0) {
|
|
||||||
char *pScan2 = szSymbol[1];
|
|
||||||
float r = strtof(pScan2, &pScan2);
|
|
||||||
if(cSymbols == 2) {
|
|
||||||
pMaterial->setSpecular(Vector3(r, r, r));
|
|
||||||
} else if(cSymbols == 4) {
|
|
||||||
pScan2 = szSymbol[2];
|
|
||||||
float g = strtof(pScan2, &pScan2);
|
|
||||||
pScan2 = szSymbol[3];
|
|
||||||
float b = strtof(pScan2, &pScan2);
|
|
||||||
pMaterial->setSpecular(Vector3(r, g, b));
|
|
||||||
}
|
|
||||||
} else if(strcmp(szSymbol[0], "kr") == 0) {
|
|
||||||
char *pScan2 = szSymbol[1];
|
|
||||||
float r = strtof(pScan2, &pScan2);
|
|
||||||
if(cSymbols == 2) {
|
|
||||||
pMaterial->setReflection(Vector3(r, r, r));
|
|
||||||
} else if(cSymbols == 4) {
|
|
||||||
pScan2 = szSymbol[2];
|
|
||||||
float g = strtof(pScan2, &pScan2);
|
|
||||||
pScan2 = szSymbol[3];
|
|
||||||
float b = strtof(pScan2, &pScan2);
|
|
||||||
pMaterial->setReflection(Vector3(r, g, b));
|
|
||||||
}
|
|
||||||
} else if(strcmp(szSymbol[0], "tr") == 0) {
|
|
||||||
char *pScan2 = szSymbol[1];
|
|
||||||
float a = strtof(pScan2, &pScan2);
|
|
||||||
pMaterial->setTransparency(a);
|
|
||||||
} else if(strcmp(szSymbol[0], "ns") == 0) {
|
|
||||||
char *pScan2 = szSymbol[1];
|
|
||||||
float a = strtof(pScan2, &pScan2);
|
|
||||||
pMaterial->setShininess(a);
|
|
||||||
} else if(strncmp(szSymbol[0], "map", 3) == 0) {
|
|
||||||
// Truncate file extension
|
|
||||||
char *pScan2 = szSymbol[1];
|
|
||||||
char *pLastPeriod = NULL;
|
|
||||||
while(*pScan2 != '\0') {
|
|
||||||
if(*pScan2 == '.') {
|
|
||||||
pLastPeriod = pScan2;
|
|
||||||
}
|
|
||||||
pScan2++;
|
|
||||||
}
|
|
||||||
if(pLastPeriod) {
|
|
||||||
*pLastPeriod = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 texture_scale = Vector2(1.0f, 1.0f);
|
|
||||||
Vector2 texture_offset = Vector2(0.0f, 0.0f);
|
|
||||||
|
|
||||||
int iScanSymbol = 2;
|
|
||||||
int iScaleParam = -1;
|
|
||||||
int iOffsetParam = -1;
|
|
||||||
while(iScanSymbol < cSymbols) {
|
|
||||||
if(strcmp(szSymbol[iScanSymbol], "-s") == 0) {
|
|
||||||
// Scale
|
|
||||||
iScaleParam = 0;
|
|
||||||
iOffsetParam = -1;
|
|
||||||
} else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) {
|
|
||||||
// Offset
|
|
||||||
iOffsetParam = 0;
|
|
||||||
iScaleParam = -1;
|
|
||||||
} else {
|
|
||||||
char *pScan3 = szSymbol[iScanSymbol];
|
|
||||||
float v = strtof(pScan3, &pScan3);
|
|
||||||
if(iScaleParam == 0) {
|
|
||||||
texture_scale.x = v;
|
|
||||||
iScaleParam++;
|
|
||||||
} else if(iScaleParam == 1) {
|
|
||||||
texture_scale.y = v;
|
|
||||||
iScaleParam++;
|
|
||||||
} else if(iOffsetParam == 0) {
|
|
||||||
texture_offset.x = v;
|
|
||||||
iOffsetParam++;
|
|
||||||
} else if(iOffsetParam == 1) {
|
|
||||||
texture_offset.y = v;
|
|
||||||
iOffsetParam++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iScanSymbol++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(strcmp(szSymbol[0], "map_ka") == 0) {
|
|
||||||
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
|
|
||||||
} else if(strcmp(szSymbol[0], "map_kd") == 0) {
|
|
||||||
pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset);
|
|
||||||
} else if(strcmp(szSymbol[0], "map_ks") == 0) {
|
|
||||||
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset);
|
|
||||||
} else if(strcmp(szSymbol[0], "map_normal") == 0) {
|
|
||||||
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset);
|
|
||||||
} else if(strcmp(szSymbol[0], "map_reflection") == 0) {
|
|
||||||
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset);
|
|
||||||
} else if(strcmp(szSymbol[0], "map_reflectioncube") == 0) {
|
|
||||||
pMaterial->setReflectionCube(szSymbol[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
data->unlock();
|
|
||||||
delete data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
1610
kraken/KRMesh.cpp
1610
kraken/KRMesh.cpp
File diff suppressed because it is too large
Load Diff
291
kraken/KRMesh.h
291
kraken/KRMesh.h
@@ -1,291 +0,0 @@
|
|||||||
//
|
|
||||||
// KRMesh.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "KRBone.h"
|
|
||||||
#include "KRMeshManager.h"
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
using namespace kraken;
|
|
||||||
|
|
||||||
#define MAX_VBO_SIZE 65535
|
|
||||||
#define KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX 4
|
|
||||||
#define KRENGINE_MAX_NAME_LENGTH 256
|
|
||||||
// MAX_VBO_SIZE must be divisible by 3 so triangles aren't split across VBO objects...
|
|
||||||
|
|
||||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
|
||||||
|
|
||||||
#ifndef KRMesh_I
|
|
||||||
#define KRMesh_I
|
|
||||||
|
|
||||||
#include "KRMaterialManager.h"
|
|
||||||
#include "KRCamera.h"
|
|
||||||
#include "KRViewport.h"
|
|
||||||
#include "KRHitInfo.h"
|
|
||||||
|
|
||||||
class KRMaterial;
|
|
||||||
class KRNode;
|
|
||||||
|
|
||||||
class KRMesh : public KRResource {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KRMesh(KRContext &context, std::string name, KRDataBlock *data);
|
|
||||||
KRMesh(KRContext &context, std::string name);
|
|
||||||
virtual ~KRMesh();
|
|
||||||
|
|
||||||
kraken_stream_level getStreamLevel();
|
|
||||||
void preStream(float lodCoverage);
|
|
||||||
|
|
||||||
bool hasTransparency();
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
KRENGINE_ATTRIB_VERTEX = 0,
|
|
||||||
KRENGINE_ATTRIB_NORMAL,
|
|
||||||
KRENGINE_ATTRIB_TANGENT,
|
|
||||||
KRENGINE_ATTRIB_TEXUVA,
|
|
||||||
KRENGINE_ATTRIB_TEXUVB,
|
|
||||||
KRENGINE_ATTRIB_BONEINDEXES,
|
|
||||||
KRENGINE_ATTRIB_BONEWEIGHTS,
|
|
||||||
KRENGINE_ATTRIB_VERTEX_SHORT,
|
|
||||||
KRENGINE_ATTRIB_NORMAL_SHORT,
|
|
||||||
KRENGINE_ATTRIB_TANGENT_SHORT,
|
|
||||||
KRENGINE_ATTRIB_TEXUVA_SHORT,
|
|
||||||
KRENGINE_ATTRIB_TEXUVB_SHORT,
|
|
||||||
KRENGINE_NUM_ATTRIBUTES
|
|
||||||
} vertex_attrib_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
KRENGINE_MODEL_FORMAT_TRIANGLES = 0,
|
|
||||||
KRENGINE_MODEL_FORMAT_STRIP,
|
|
||||||
KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES,
|
|
||||||
KRENGINE_MODEL_FORMAT_INDEXED_STRIP
|
|
||||||
} model_format_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
model_format_t format;
|
|
||||||
std::vector<Vector3> vertices;
|
|
||||||
std::vector<__uint16_t> vertex_indexes;
|
|
||||||
std::vector<std::pair<int, int> > vertex_index_bases;
|
|
||||||
std::vector<Vector2> uva;
|
|
||||||
std::vector<Vector2> uvb;
|
|
||||||
std::vector<Vector3> normals;
|
|
||||||
std::vector<Vector3> tangents;
|
|
||||||
std::vector<int> submesh_starts;
|
|
||||||
std::vector<int> submesh_lengths;
|
|
||||||
std::vector<std::string> material_names;
|
|
||||||
std::vector<std::string> bone_names;
|
|
||||||
std::vector<std::vector<int> > bone_indexes;
|
|
||||||
std::vector<Matrix4> bone_bind_poses;
|
|
||||||
std::vector<std::vector<float> > bone_weights;
|
|
||||||
} mesh_info;
|
|
||||||
|
|
||||||
void render(const std::string &object_name, KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const std::vector<KRBone *> &bones, const Vector3 &rim_color, float rim_power, float lod_coverage = 0.0f);
|
|
||||||
|
|
||||||
std::string m_lodBaseName;
|
|
||||||
|
|
||||||
virtual std::string getExtension();
|
|
||||||
virtual bool save(const std::string& path);
|
|
||||||
virtual bool save(KRDataBlock &data);
|
|
||||||
|
|
||||||
void LoadData(const mesh_info &mi, bool calculate_normals, bool calculate_tangents);
|
|
||||||
void loadPack(KRDataBlock *data);
|
|
||||||
|
|
||||||
void convertToIndexed();
|
|
||||||
void optimize();
|
|
||||||
void optimizeIndexes();
|
|
||||||
|
|
||||||
void renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const std::string &object_name, const std::string &material_name, float lodCoverage);
|
|
||||||
|
|
||||||
GLfloat getMaxDimension();
|
|
||||||
|
|
||||||
Vector3 getMinPoint() const;
|
|
||||||
Vector3 getMaxPoint() const;
|
|
||||||
|
|
||||||
class Submesh {
|
|
||||||
public:
|
|
||||||
Submesh() {};
|
|
||||||
~Submesh() {
|
|
||||||
for(auto itr = vbo_data_blocks.begin(); itr != vbo_data_blocks.end(); itr++) {
|
|
||||||
delete (*itr);
|
|
||||||
}
|
|
||||||
for(auto itr = vertex_data_blocks.begin(); itr != vertex_data_blocks.end(); itr++) {
|
|
||||||
delete (*itr);
|
|
||||||
}
|
|
||||||
for(auto itr = index_data_blocks.begin(); itr != index_data_blocks.end(); itr++) {
|
|
||||||
delete (*itr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GLint start_vertex;
|
|
||||||
GLsizei vertex_count;
|
|
||||||
char szMaterialName[KRENGINE_MAX_NAME_LENGTH];
|
|
||||||
vector<KRDataBlock *> vertex_data_blocks;
|
|
||||||
vector<KRDataBlock *> index_data_blocks;
|
|
||||||
vector<KRMeshManager::KRVBOData *> vbo_data_blocks;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
union {
|
|
||||||
struct { // For Indexed triangles / strips
|
|
||||||
uint16_t index_group;
|
|
||||||
uint16_t index_group_offset;
|
|
||||||
};
|
|
||||||
int32_t start_vertex; // For non-indexed trigangles / strips
|
|
||||||
};
|
|
||||||
int32_t vertex_count;
|
|
||||||
char szName[KRENGINE_MAX_NAME_LENGTH];
|
|
||||||
} pack_material;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char szName[KRENGINE_MAX_NAME_LENGTH];
|
|
||||||
float bind_pose[16];
|
|
||||||
} pack_bone;
|
|
||||||
|
|
||||||
int getLODCoverage() const;
|
|
||||||
std::string getLODBaseName() const;
|
|
||||||
|
|
||||||
|
|
||||||
static bool lod_sort_predicate(const KRMesh *m1, const KRMesh *m2);
|
|
||||||
bool has_vertex_attribute(vertex_attrib_t attribute_type) const;
|
|
||||||
static bool has_vertex_attribute(int vertex_attrib_flags, vertex_attrib_t attribute_type);
|
|
||||||
|
|
||||||
int getSubmeshCount() const;
|
|
||||||
int getVertexCount(int submesh) const;
|
|
||||||
int getTriangleVertexIndex(int submesh, int index) const;
|
|
||||||
Vector3 getVertexPosition(int index) const;
|
|
||||||
Vector3 getVertexNormal(int index) const;
|
|
||||||
Vector3 getVertexTangent(int index) const;
|
|
||||||
Vector2 getVertexUVA(int index) const;
|
|
||||||
Vector2 getVertexUVB(int index) const;
|
|
||||||
int getBoneIndex(int index, int weight_index) const;
|
|
||||||
float getBoneWeight(int index, int weight_index) const;
|
|
||||||
|
|
||||||
void setVertexPosition(int index, const Vector3 &v);
|
|
||||||
void setVertexNormal(int index, const Vector3 &v);
|
|
||||||
void setVertexTangent(int index, const Vector3 & v);
|
|
||||||
void setVertexUVA(int index, const Vector2 &v);
|
|
||||||
void setVertexUVB(int index, const Vector2 &v);
|
|
||||||
void setBoneIndex(int index, int weight_index, int bone_index);
|
|
||||||
void setBoneWeight(int index, int weight_index, float bone_weight);
|
|
||||||
|
|
||||||
static size_t VertexSizeForAttributes(__int32_t vertex_attrib_flags);
|
|
||||||
static size_t AttributeOffset(__int32_t vertex_attrib, __int32_t vertex_attrib_flags);
|
|
||||||
|
|
||||||
int getBoneCount();
|
|
||||||
char *getBoneName(int bone_index);
|
|
||||||
Matrix4 getBoneBindPose(int bone_index);
|
|
||||||
|
|
||||||
|
|
||||||
model_format_t getModelFormat() const;
|
|
||||||
|
|
||||||
bool lineCast(const Vector3 &v0, const Vector3 &v1, KRHitInfo &hitinfo) const;
|
|
||||||
bool rayCast(const Vector3 &v0, const Vector3 &dir, KRHitInfo &hitinfo) const;
|
|
||||||
bool sphereCast(const Matrix4 &model_to_world, const Vector3 &v0, const Vector3 &v1, float radius, KRHitInfo &hitinfo) const;
|
|
||||||
|
|
||||||
static int GetLODCoverage(const std::string &name);
|
|
||||||
|
|
||||||
void load(); // Load immediately into the GPU rather than passing through the streamer
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool m_constant; // TRUE if this should be always loaded and should not be passed through the streamer
|
|
||||||
|
|
||||||
private:
|
|
||||||
KRDataBlock *m_pData;
|
|
||||||
KRDataBlock *m_pMetaData;
|
|
||||||
KRDataBlock *m_pIndexBaseData;
|
|
||||||
|
|
||||||
void getSubmeshes();
|
|
||||||
void getMaterials();
|
|
||||||
|
|
||||||
static bool rayCast(const Vector3 &start, const Vector3 &dir, const Triangle3 &tri, const Vector3 &tri_n0, const Vector3 &tri_n1, const Vector3 &tri_n2, KRHitInfo &hitinfo);
|
|
||||||
static bool sphereCast(const Matrix4 &model_to_world, const Vector3 &v0, const Vector3 &v1, float radius, const Triangle3 &tri, KRHitInfo &hitinfo);
|
|
||||||
|
|
||||||
int m_lodCoverage; // This LOD level is activated when the bounding box of the model will cover less than this percent of the screen (100 = highest detail model)
|
|
||||||
vector<KRMaterial *> m_materials;
|
|
||||||
set<KRMaterial *> m_uniqueMaterials;
|
|
||||||
|
|
||||||
bool m_hasTransparency;
|
|
||||||
|
|
||||||
|
|
||||||
Vector3 m_minPoint, m_maxPoint;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char szTag[16];
|
|
||||||
int32_t model_format; // 0 == Triangle list, 1 == Triangle strips, 2 == Indexed triangle list, 3 == Indexed triangle strips, rest are reserved (model_format_t enum)
|
|
||||||
int32_t vertex_attrib_flags;
|
|
||||||
int32_t vertex_count;
|
|
||||||
int32_t submesh_count;
|
|
||||||
int32_t bone_count;
|
|
||||||
float minx, miny, minz, maxx, maxy, maxz; // Axis aligned bounding box, in model's coordinate space
|
|
||||||
int32_t index_count;
|
|
||||||
int32_t index_base_count;
|
|
||||||
unsigned char reserved[444]; // Pad out to 512 bytes
|
|
||||||
} pack_header;
|
|
||||||
|
|
||||||
vector<Submesh *> m_submeshes;
|
|
||||||
int m_vertex_attribute_offset[KRENGINE_NUM_ATTRIBUTES];
|
|
||||||
int m_vertex_size;
|
|
||||||
void updateAttributeOffsets();
|
|
||||||
|
|
||||||
void setName(const std::string name);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pack_material *getSubmesh(int mesh_index) const;
|
|
||||||
unsigned char *getVertexData() const;
|
|
||||||
size_t getVertexDataOffset() const;
|
|
||||||
unsigned char *getVertexData(int index) const;
|
|
||||||
__uint16_t *getIndexData() const;
|
|
||||||
size_t getIndexDataOffset() const;
|
|
||||||
__uint32_t *getIndexBaseData() const;
|
|
||||||
pack_header *getHeader() const;
|
|
||||||
pack_bone *getBone(int index);
|
|
||||||
|
|
||||||
|
|
||||||
void getIndexedRange(int index_group, int &start_index_offset, int &start_vertex_offset, int &index_count, int &vertex_count) const;
|
|
||||||
|
|
||||||
void releaseData();
|
|
||||||
|
|
||||||
void createDataBlocks(KRMeshManager::KRVBOData::vbo_type t);
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // KRMesh_I
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
//
|
|
||||||
// KRMeshCube.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRMeshCube.h"
|
|
||||||
|
|
||||||
|
|
||||||
KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube")
|
|
||||||
{
|
|
||||||
m_constant = true;
|
|
||||||
|
|
||||||
KRMesh::mesh_info mi;
|
|
||||||
|
|
||||||
mi.vertices.push_back(Vector3(1.0, 1.0, 1.0));
|
|
||||||
mi.vertices.push_back(Vector3(-1.0, 1.0, 1.0));
|
|
||||||
mi.vertices.push_back(Vector3(1.0,-1.0, 1.0));
|
|
||||||
mi.vertices.push_back(Vector3(-1.0,-1.0, 1.0));
|
|
||||||
mi.vertices.push_back(Vector3(-1.0,-1.0,-1.0));
|
|
||||||
mi.vertices.push_back(Vector3(-1.0, 1.0, 1.0));
|
|
||||||
mi.vertices.push_back(Vector3(-1.0, 1.0,-1.0));
|
|
||||||
mi.vertices.push_back(Vector3(1.0, 1.0, 1.0));
|
|
||||||
mi.vertices.push_back(Vector3(1.0, 1.0,-1.0));
|
|
||||||
mi.vertices.push_back(Vector3(1.0,-1.0, 1.0));
|
|
||||||
mi.vertices.push_back(Vector3(1.0,-1.0,-1.0));
|
|
||||||
mi.vertices.push_back(Vector3(-1.0,-1.0,-1.0));
|
|
||||||
mi.vertices.push_back(Vector3(1.0, 1.0,-1.0));
|
|
||||||
mi.vertices.push_back(Vector3(-1.0, 1.0,-1.0));
|
|
||||||
|
|
||||||
|
|
||||||
mi.submesh_starts.push_back(0);
|
|
||||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
|
||||||
mi.material_names.push_back("");
|
|
||||||
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
|
||||||
|
|
||||||
|
|
||||||
LoadData(mi, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
KRMeshCube::~KRMeshCube()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,721 +0,0 @@
|
|||||||
//
|
|
||||||
// KRMeshManager.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#include "KRMeshManager.h"
|
|
||||||
|
|
||||||
#include "KRMesh.h"
|
|
||||||
#include "KRMeshCube.h"
|
|
||||||
#include "KRMeshQuad.h"
|
|
||||||
#include "KRMeshSphere.h"
|
|
||||||
|
|
||||||
KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context) {
|
|
||||||
m_currentVBO = NULL;
|
|
||||||
m_vboMemUsed = 0;
|
|
||||||
m_memoryTransferredThisFrame = 0;
|
|
||||||
m_first_frame = true;
|
|
||||||
m_streamerComplete = true;
|
|
||||||
|
|
||||||
addModel(new KRMeshCube(context)); // FINDME - HACK! This needs to be fixed, as it currently segfaults
|
|
||||||
addModel(new KRMeshQuad(context)); // FINDME - HACK! This needs to be fixed, as it currently segfaults
|
|
||||||
addModel(new KRMeshSphere(context));
|
|
||||||
m_draw_call_logging_enabled = false;
|
|
||||||
m_draw_call_log_used = false;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ---- Initialize stock models ----
|
|
||||||
|
|
||||||
static const GLfloat _KRENGINE_VBO_3D_CUBE_VERTEX_DATA[] = {
|
|
||||||
1.0, 1.0, 1.0,
|
|
||||||
-1.0, 1.0, 1.0,
|
|
||||||
1.0,-1.0, 1.0,
|
|
||||||
-1.0,-1.0, 1.0,
|
|
||||||
-1.0,-1.0,-1.0,
|
|
||||||
-1.0, 1.0, 1.0,
|
|
||||||
-1.0, 1.0,-1.0,
|
|
||||||
1.0, 1.0, 1.0,
|
|
||||||
1.0, 1.0,-1.0,
|
|
||||||
1.0,-1.0, 1.0,
|
|
||||||
1.0,-1.0,-1.0,
|
|
||||||
-1.0,-1.0,-1.0,
|
|
||||||
1.0, 1.0,-1.0,
|
|
||||||
-1.0, 1.0,-1.0
|
|
||||||
};
|
|
||||||
|
|
||||||
KRENGINE_VBO_3D_CUBE_ATTRIBS = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
|
|
||||||
KRENGINE_VBO_3D_CUBE_VERTICES.expand(sizeof(GLfloat) * 3 * 14);
|
|
||||||
KRENGINE_VBO_3D_CUBE_VERTICES.lock();
|
|
||||||
memcpy(KRENGINE_VBO_3D_CUBE_VERTICES.getStart(), _KRENGINE_VBO_3D_CUBE_VERTEX_DATA, sizeof(GLfloat) * 3 * 14);
|
|
||||||
KRENGINE_VBO_3D_CUBE_VERTICES.unlock();
|
|
||||||
|
|
||||||
KRENGINE_VBO_DATA_3D_CUBE_VERTICES.init(this, KRENGINE_VBO_3D_CUBE_VERTICES, KRENGINE_VBO_3D_CUBE_INDEXES, KRENGINE_VBO_3D_CUBE_ATTRIBS, false, KRVBOData::CONSTANT);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const GLfloat _KRENGINE_VBO_2D_SQUARE_VERTEX_DATA[] = {
|
|
||||||
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
|
||||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
|
||||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
|
||||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
|
|
||||||
};
|
|
||||||
KRENGINE_VBO_2D_SQUARE_ATTRIBS = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA);
|
|
||||||
KRENGINE_VBO_2D_SQUARE_VERTICES.expand(sizeof(GLfloat) * 5 * 4);
|
|
||||||
KRENGINE_VBO_2D_SQUARE_VERTICES.lock();
|
|
||||||
memcpy(KRENGINE_VBO_2D_SQUARE_VERTICES.getStart(), _KRENGINE_VBO_2D_SQUARE_VERTEX_DATA, sizeof(GLfloat) * 5 * 4);
|
|
||||||
KRENGINE_VBO_2D_SQUARE_VERTICES.unlock();
|
|
||||||
|
|
||||||
KRENGINE_VBO_DATA_2D_SQUARE_VERTICES.init(this, KRENGINE_VBO_2D_SQUARE_VERTICES, KRENGINE_VBO_2D_SQUARE_INDEXES, KRENGINE_VBO_2D_SQUARE_ATTRIBS, false, KRVBOData::CONSTANT);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
KRMeshManager::~KRMeshManager() {
|
|
||||||
for(unordered_multimap<std::string, KRMesh *>::iterator itr = m_models.begin(); itr != m_models.end(); ++itr){
|
|
||||||
delete (*itr).second;
|
|
||||||
}
|
|
||||||
m_models.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
KRMesh *KRMeshManager::loadModel(const char *szName, KRDataBlock *pData) {
|
|
||||||
KRMesh *pModel = new KRMesh(*m_pContext, szName, pData);
|
|
||||||
addModel(pModel);
|
|
||||||
return pModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::addModel(KRMesh *model) {
|
|
||||||
std::string lowerName = model->getLODBaseName();
|
|
||||||
std::transform(lowerName.begin(), lowerName.end(),
|
|
||||||
lowerName.begin(), ::tolower);
|
|
||||||
|
|
||||||
m_models.insert(std::pair<std::string, KRMesh *>(lowerName, model));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<KRMesh *> KRMeshManager::getModel(const char *szName) {
|
|
||||||
std::string lowerName = szName;
|
|
||||||
std::transform(lowerName.begin(), lowerName.end(),
|
|
||||||
lowerName.begin(), ::tolower);
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<KRMesh *> matching_models;
|
|
||||||
|
|
||||||
std::pair<unordered_multimap<std::string, KRMesh *>::iterator, unordered_multimap<std::string, KRMesh *>::iterator> range = m_models.equal_range(lowerName);
|
|
||||||
for(unordered_multimap<std::string, KRMesh *>::iterator itr_match = range.first; itr_match != range.second; itr_match++) {
|
|
||||||
matching_models.push_back(itr_match->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(matching_models.begin(), matching_models.end(), KRMesh::lod_sort_predicate);
|
|
||||||
|
|
||||||
if(matching_models.size() == 0) {
|
|
||||||
KRContext::Log(KRContext::LOG_LEVEL_INFORMATION, "Model not found: %s", lowerName.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return matching_models;
|
|
||||||
}
|
|
||||||
|
|
||||||
unordered_multimap<std::string, KRMesh *> &KRMeshManager::getModels() {
|
|
||||||
return m_models;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::unbindVBO() {
|
|
||||||
if(m_currentVBO != NULL) {
|
|
||||||
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, 0));
|
|
||||||
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
|
||||||
m_currentVBO = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::bindVBO(KRVBOData *vbo_data, float lodCoverage)
|
|
||||||
{
|
|
||||||
vbo_data->resetPoolExpiry(lodCoverage);
|
|
||||||
|
|
||||||
bool vbo_changed = false;
|
|
||||||
if(m_currentVBO == NULL) {
|
|
||||||
vbo_changed = true;
|
|
||||||
} else if(m_currentVBO->m_data != vbo_data->m_data) {
|
|
||||||
vbo_changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool used_vbo_data = false;
|
|
||||||
|
|
||||||
if(vbo_changed) {
|
|
||||||
|
|
||||||
if(m_vbosActive.find(vbo_data->m_data) != m_vbosActive.end()) {
|
|
||||||
m_currentVBO = m_vbosActive[vbo_data->m_data];
|
|
||||||
} else {
|
|
||||||
used_vbo_data = true;
|
|
||||||
m_currentVBO = vbo_data;
|
|
||||||
|
|
||||||
m_vbosActive[vbo_data->m_data] = m_currentVBO;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_currentVBO->bind();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!used_vbo_data && vbo_data->getType() == KRVBOData::TEMPORARY) {
|
|
||||||
delete vbo_data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::startFrame(float deltaTime)
|
|
||||||
{
|
|
||||||
m_memoryTransferredThisFrame = 0;
|
|
||||||
if(m_draw_call_log_used) {
|
|
||||||
// Only log draw calls on the next frame if the draw call log was used on last frame
|
|
||||||
m_draw_call_log_used = false;
|
|
||||||
m_draw_call_logging_enabled = true;
|
|
||||||
}
|
|
||||||
m_draw_calls.clear();
|
|
||||||
|
|
||||||
if(m_first_frame) {
|
|
||||||
m_first_frame = false;
|
|
||||||
firstFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - Implement proper double-buffering to reduce copy operations
|
|
||||||
m_streamerFenceMutex.lock();
|
|
||||||
|
|
||||||
if(m_streamerComplete) {
|
|
||||||
assert(m_activeVBOs_streamer_copy.size() == 0); // The streamer should have emptied this if it really did complete
|
|
||||||
|
|
||||||
const long KRENGINE_VBO_EXPIRY_FRAMES = 1;
|
|
||||||
|
|
||||||
std::set<KRVBOData *> expiredVBOs;
|
|
||||||
for(auto itr=m_vbosActive.begin(); itr != m_vbosActive.end(); itr++) {
|
|
||||||
KRVBOData *activeVBO = (*itr).second;
|
|
||||||
activeVBO->_swapHandles();
|
|
||||||
if(activeVBO->getLastFrameUsed() + KRENGINE_VBO_EXPIRY_FRAMES < getContext().getCurrentFrame()) {
|
|
||||||
// Expire VBO's that haven't been used in a long time
|
|
||||||
|
|
||||||
switch(activeVBO->getType()) {
|
|
||||||
case KRVBOData::STREAMING:
|
|
||||||
activeVBO->unload();
|
|
||||||
break;
|
|
||||||
case KRVBOData::TEMPORARY:
|
|
||||||
delete activeVBO;
|
|
||||||
break;
|
|
||||||
case KRVBOData::CONSTANT:
|
|
||||||
// CONSTANT VBO's are not unloaded
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
expiredVBOs.insert(activeVBO);
|
|
||||||
} else {
|
|
||||||
if(activeVBO->getType() == KRVBOData::STREAMING) {
|
|
||||||
float priority = activeVBO->getStreamPriority();
|
|
||||||
m_activeVBOs_streamer_copy.push_back(std::pair<float, KRVBOData *>(priority, activeVBO));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(std::set<KRVBOData *>::iterator itr=expiredVBOs.begin(); itr != expiredVBOs.end(); itr++) {
|
|
||||||
m_vbosActive.erase((*itr)->m_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_activeVBOs_streamer_copy.size() > 0) {
|
|
||||||
m_streamerComplete = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_streamerFenceMutex.unlock();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::endFrame(float deltaTime)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::firstFrame()
|
|
||||||
{
|
|
||||||
KRENGINE_VBO_DATA_3D_CUBE_VERTICES.load();
|
|
||||||
KRENGINE_VBO_DATA_2D_SQUARE_VERTICES.load();
|
|
||||||
|
|
||||||
getModel("__sphere")[0]->load();
|
|
||||||
getModel("__cube")[0]->load();
|
|
||||||
getModel("__quad")[0]->load();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::doStreaming(long &memoryRemaining, long &memoryRemainingThisFrame)
|
|
||||||
{
|
|
||||||
|
|
||||||
// TODO - Implement proper double-buffering to reduce copy operations
|
|
||||||
m_streamerFenceMutex.lock();
|
|
||||||
m_activeVBOs_streamer = std::move(m_activeVBOs_streamer_copy);
|
|
||||||
m_streamerFenceMutex.unlock();
|
|
||||||
|
|
||||||
if(m_activeVBOs_streamer.size() > 0) {
|
|
||||||
balanceVBOMemory(memoryRemaining, memoryRemainingThisFrame);
|
|
||||||
|
|
||||||
m_streamerFenceMutex.lock();
|
|
||||||
m_streamerComplete = true;
|
|
||||||
m_streamerFenceMutex.unlock();
|
|
||||||
} else {
|
|
||||||
memoryRemaining -= getMemUsed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::balanceVBOMemory(long &memoryRemaining, long &memoryRemainingThisFrame)
|
|
||||||
{
|
|
||||||
std::sort(m_activeVBOs_streamer.begin(), m_activeVBOs_streamer.end(), std::greater<std::pair<float, KRVBOData *>>());
|
|
||||||
|
|
||||||
|
|
||||||
for(auto vbo_itr = m_activeVBOs_streamer.begin(); vbo_itr != m_activeVBOs_streamer.end(); vbo_itr++) {
|
|
||||||
KRVBOData *vbo_data = (*vbo_itr).second;
|
|
||||||
long vbo_size = vbo_data->getSize();
|
|
||||||
if(!vbo_data->isVBOLoaded()) {
|
|
||||||
if(memoryRemainingThisFrame > vbo_size) {
|
|
||||||
vbo_data->load();
|
|
||||||
memoryRemainingThisFrame -= vbo_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memoryRemaining -= vbo_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
glFinish();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, float lodCoverage)
|
|
||||||
{
|
|
||||||
KRVBOData *vbo_data = new KRVBOData(this, data, index_data, vertex_attrib_flags, static_vbo, KRVBOData::TEMPORARY);
|
|
||||||
vbo_data->load();
|
|
||||||
bindVBO(vbo_data, lodCoverage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::configureAttribs(__int32_t attributes)
|
|
||||||
{
|
|
||||||
GLsizei data_size = (GLsizei)KRMesh::VertexSizeForAttributes(attributes);
|
|
||||||
|
|
||||||
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_VERTEX_SHORT)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_VERTEX));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_SHORT, GL_TRUE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_VERTEX_SHORT, attributes))));
|
|
||||||
} else if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_VERTEX)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_VERTEX));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_VERTEX, attributes))));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_VERTEX));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_NORMAL_SHORT)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_NORMAL));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_NORMAL, 3, GL_SHORT, GL_TRUE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_NORMAL_SHORT, attributes))));
|
|
||||||
} else if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_NORMAL)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_NORMAL));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_NORMAL, 3, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_NORMAL, attributes))));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_NORMAL));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TANGENT_SHORT)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TANGENT));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TANGENT, 3, GL_SHORT, GL_TRUE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TANGENT_SHORT, attributes))));
|
|
||||||
} else if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TANGENT)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TANGENT));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TANGENT, 3, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TANGENT, attributes))));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TANGENT));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TEXUVA_SHORT)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVA));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TEXUVA, 2, GL_SHORT, GL_TRUE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TEXUVA_SHORT, attributes))));
|
|
||||||
} else if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TEXUVA)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVA));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TEXUVA, 2, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TEXUVA, attributes))));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVA));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TEXUVB_SHORT)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVB));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TEXUVB, 2, GL_SHORT, GL_TRUE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TEXUVB_SHORT, attributes))));
|
|
||||||
} else if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TEXUVB)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVB));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TEXUVB, 2, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TEXUVB, attributes))));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVB));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_BONEINDEXES)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_BONEINDEXES));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_BONEINDEXES, 4, GL_UNSIGNED_BYTE, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_BONEINDEXES, attributes))));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_BONEINDEXES));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS)) {
|
|
||||||
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS));
|
|
||||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS, 4, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS, attributes))));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long KRMeshManager::getMemUsed()
|
|
||||||
{
|
|
||||||
return m_vboMemUsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
long KRMeshManager::getMemActive()
|
|
||||||
{
|
|
||||||
long mem_active = 0;
|
|
||||||
for(unordered_map<KRDataBlock *, KRVBOData *>::iterator itr = m_vbosActive.begin(); itr != m_vbosActive.end(); itr++) {
|
|
||||||
mem_active += (*itr).second->getSize();
|
|
||||||
}
|
|
||||||
return mem_active;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRDataBlock &KRMeshManager::getVolumetricLightingVertexes()
|
|
||||||
{
|
|
||||||
if(m_volumetricLightingVertexData.getSize() == 0) {
|
|
||||||
m_volumetricLightingVertexData.expand(sizeof(VolumetricLightingVertexData) * KRENGINE_MAX_VOLUMETRIC_PLANES * 6);
|
|
||||||
m_volumetricLightingVertexData.lock();
|
|
||||||
VolumetricLightingVertexData * vertex_data = (VolumetricLightingVertexData *)m_volumetricLightingVertexData.getStart();
|
|
||||||
int iVertex=0;
|
|
||||||
for(int iPlane=0; iPlane < KRENGINE_MAX_VOLUMETRIC_PLANES; iPlane++) {
|
|
||||||
vertex_data[iVertex].vertex.x = -1.0f;
|
|
||||||
vertex_data[iVertex].vertex.y = -1.0f;
|
|
||||||
vertex_data[iVertex].vertex.z = iPlane;
|
|
||||||
iVertex++;
|
|
||||||
|
|
||||||
vertex_data[iVertex].vertex.x = 1.0f;
|
|
||||||
vertex_data[iVertex].vertex.y = -1.0f;
|
|
||||||
vertex_data[iVertex].vertex.z = iPlane;
|
|
||||||
iVertex++;
|
|
||||||
|
|
||||||
vertex_data[iVertex].vertex.x = -1.0f;
|
|
||||||
vertex_data[iVertex].vertex.y = 1.0f;
|
|
||||||
vertex_data[iVertex].vertex.z = iPlane;
|
|
||||||
iVertex++;
|
|
||||||
|
|
||||||
vertex_data[iVertex].vertex.x = -1.0f;
|
|
||||||
vertex_data[iVertex].vertex.y = 1.0f;
|
|
||||||
vertex_data[iVertex].vertex.z = iPlane;
|
|
||||||
iVertex++;
|
|
||||||
|
|
||||||
vertex_data[iVertex].vertex.x = 1.0f;
|
|
||||||
vertex_data[iVertex].vertex.y = -1.0f;
|
|
||||||
vertex_data[iVertex].vertex.z = iPlane;
|
|
||||||
iVertex++;
|
|
||||||
|
|
||||||
vertex_data[iVertex].vertex.x = 1.0f;
|
|
||||||
vertex_data[iVertex].vertex.y = 1.0f;
|
|
||||||
vertex_data[iVertex].vertex.z = iPlane;
|
|
||||||
iVertex++;
|
|
||||||
|
|
||||||
}
|
|
||||||
m_volumetricLightingVertexData.unlock();
|
|
||||||
}
|
|
||||||
return m_volumetricLightingVertexData;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRDataBlock &KRMeshManager::getRandomParticles()
|
|
||||||
{
|
|
||||||
if(m_randomParticleVertexData.getSize() == 0) {
|
|
||||||
m_randomParticleVertexData.expand(sizeof(RandomParticleVertexData) * KRENGINE_MAX_RANDOM_PARTICLES * 3);
|
|
||||||
m_randomParticleVertexData.lock();
|
|
||||||
RandomParticleVertexData *vertex_data = (RandomParticleVertexData *)m_randomParticleVertexData.getStart();
|
|
||||||
|
|
||||||
// Generate vertices for randomly placed equilateral triangles with a side length of 1 and an origin point centered so that an inscribed circle can be efficiently rendered without wasting fill
|
|
||||||
|
|
||||||
float equilateral_triangle_height = sqrt(3.0f) * 0.5f;
|
|
||||||
float inscribed_circle_radius = 1.0f / (2.0f * sqrt(3.0f));
|
|
||||||
|
|
||||||
int iVertex=0;
|
|
||||||
for(int iParticle=0; iParticle < KRENGINE_MAX_RANDOM_PARTICLES; iParticle++) {
|
|
||||||
vertex_data[iVertex].vertex.x = (float)(rand() % 2000) / 1000.0f - 1000.0f;
|
|
||||||
vertex_data[iVertex].vertex.y = (float)(rand() % 2000) / 1000.0f - 1000.0f;
|
|
||||||
vertex_data[iVertex].vertex.z = (float)(rand() % 2000) / 1000.0f - 1000.0f;
|
|
||||||
vertex_data[iVertex].uva.u = -0.5f;
|
|
||||||
vertex_data[iVertex].uva.v = -inscribed_circle_radius;
|
|
||||||
iVertex++;
|
|
||||||
|
|
||||||
vertex_data[iVertex].vertex.x = vertex_data[iVertex-1].vertex.x;
|
|
||||||
vertex_data[iVertex].vertex.y = vertex_data[iVertex-1].vertex.y;
|
|
||||||
vertex_data[iVertex].vertex.z = vertex_data[iVertex-1].vertex.z;
|
|
||||||
vertex_data[iVertex].uva.u = 0.5f;
|
|
||||||
vertex_data[iVertex].uva.v = -inscribed_circle_radius;
|
|
||||||
iVertex++;
|
|
||||||
|
|
||||||
vertex_data[iVertex].vertex.x = vertex_data[iVertex-1].vertex.x;
|
|
||||||
vertex_data[iVertex].vertex.y = vertex_data[iVertex-1].vertex.y;
|
|
||||||
vertex_data[iVertex].vertex.z = vertex_data[iVertex-1].vertex.z;
|
|
||||||
vertex_data[iVertex].uva.u = 0.0f;
|
|
||||||
vertex_data[iVertex].uva.v = -inscribed_circle_radius + equilateral_triangle_height;
|
|
||||||
iVertex++;
|
|
||||||
}
|
|
||||||
m_randomParticleVertexData.unlock();
|
|
||||||
}
|
|
||||||
return m_randomParticleVertexData;
|
|
||||||
}
|
|
||||||
|
|
||||||
long KRMeshManager::getMemoryTransferedThisFrame()
|
|
||||||
{
|
|
||||||
return m_memoryTransferredThisFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int KRMeshManager::getActiveVBOCount()
|
|
||||||
{
|
|
||||||
return m_vbosActive.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::log_draw_call(KRNode::RenderPass pass, const std::string &object_name, const std::string &material_name, int vertex_count)
|
|
||||||
{
|
|
||||||
if(m_draw_call_logging_enabled) {
|
|
||||||
draw_call_info info;
|
|
||||||
info.pass = pass;
|
|
||||||
strncpy(info.object_name, object_name.c_str(), 256);
|
|
||||||
strncpy(info.material_name, material_name.c_str(), 256);
|
|
||||||
info.vertex_count = vertex_count;
|
|
||||||
m_draw_calls.push_back(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<KRMeshManager::draw_call_info> KRMeshManager::getDrawCalls()
|
|
||||||
{
|
|
||||||
m_draw_call_log_used = true;
|
|
||||||
return m_draw_calls;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRMeshManager::KRVBOData::KRVBOData()
|
|
||||||
{
|
|
||||||
m_is_vbo_loaded = false;
|
|
||||||
m_is_vbo_ready = false;
|
|
||||||
m_manager = NULL;
|
|
||||||
m_type = STREAMING;
|
|
||||||
m_data = NULL;
|
|
||||||
m_index_data = NULL;
|
|
||||||
m_vertex_attrib_flags = 0;
|
|
||||||
m_vbo_handle = -1;
|
|
||||||
m_vbo_handle_indexes = -1;
|
|
||||||
m_vao_handle = -1;
|
|
||||||
m_size = 0;
|
|
||||||
|
|
||||||
m_last_frame_used = 0;
|
|
||||||
m_last_frame_max_lod_coverage = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRMeshManager::KRVBOData::KRVBOData(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t)
|
|
||||||
{
|
|
||||||
m_is_vbo_loaded = false;
|
|
||||||
m_is_vbo_ready = false;
|
|
||||||
init(manager, data,index_data,vertex_attrib_flags, static_vbo, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::KRVBOData::init(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t)
|
|
||||||
{
|
|
||||||
m_manager = manager;
|
|
||||||
m_type = t;
|
|
||||||
m_static_vbo = static_vbo;
|
|
||||||
m_data = &data;
|
|
||||||
m_index_data = &index_data;
|
|
||||||
m_vertex_attrib_flags = vertex_attrib_flags;
|
|
||||||
|
|
||||||
m_vbo_handle = -1;
|
|
||||||
m_vbo_handle_indexes = -1;
|
|
||||||
m_vao_handle = -1;
|
|
||||||
|
|
||||||
m_size = m_data->getSize();
|
|
||||||
if(m_index_data != NULL) {
|
|
||||||
m_size += m_index_data->getSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KRMeshManager::KRVBOData::~KRVBOData()
|
|
||||||
{
|
|
||||||
unload();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::KRVBOData::load()
|
|
||||||
{
|
|
||||||
if(isVBOLoaded()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assert(m_vao_handle == -1);
|
|
||||||
assert(m_vbo_handle == -1);
|
|
||||||
assert(m_vbo_handle_indexes == -1);
|
|
||||||
|
|
||||||
GLDEBUG(glGenBuffers(1, &m_vbo_handle));
|
|
||||||
if(m_index_data->getSize() > 0) {
|
|
||||||
GLDEBUG(glGenBuffers(1, &m_vbo_handle_indexes));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GL_OES_vertex_array_object
|
|
||||||
if(m_type == CONSTANT) {
|
|
||||||
GLDEBUG(glGenVertexArraysOES(1, &m_vao_handle));
|
|
||||||
GLDEBUG(glBindVertexArrayOES(m_vao_handle));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_vbo_handle));
|
|
||||||
|
|
||||||
bool use_mapbuffer = true;
|
|
||||||
#if GL_OES_mapbuffer
|
|
||||||
if(use_mapbuffer) {
|
|
||||||
GLDEBUG(glBufferData(GL_ARRAY_BUFFER, m_data->getSize(), NULL, m_static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
|
|
||||||
GLDEBUG(void *map_ptr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES));
|
|
||||||
m_data->copy(map_ptr);
|
|
||||||
GLDEBUG(glUnmapBufferOES(GL_ARRAY_BUFFER));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
m_data->lock();
|
|
||||||
GLDEBUG(glBufferData(GL_ARRAY_BUFFER, m_data->getSize(), m_data->getStart(), m_static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
|
|
||||||
m_data->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
configureAttribs(m_vertex_attrib_flags);
|
|
||||||
|
|
||||||
if(m_index_data->getSize() == 0) {
|
|
||||||
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo_handle_indexes));
|
|
||||||
|
|
||||||
#if GL_OES_mapbuffer
|
|
||||||
if(use_mapbuffer) {
|
|
||||||
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_index_data->getSize(), NULL, m_static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
|
|
||||||
GLDEBUG(void *map_ptr = glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES));
|
|
||||||
m_index_data->copy(map_ptr);
|
|
||||||
GLDEBUG(glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
m_index_data->lock();
|
|
||||||
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_index_data->getSize(), m_index_data->getStart(), m_static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
|
|
||||||
m_index_data->unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_is_vbo_loaded = true;
|
|
||||||
|
|
||||||
m_manager->m_vboMemUsed += getSize();
|
|
||||||
m_manager->m_memoryTransferredThisFrame += getSize();
|
|
||||||
|
|
||||||
if(m_type == CONSTANT) {
|
|
||||||
_swapHandles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::KRVBOData::unload()
|
|
||||||
{
|
|
||||||
if(isVBOLoaded()) {
|
|
||||||
m_manager->m_vboMemUsed -= getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GL_OES_vertex_array_object
|
|
||||||
if(m_vao_handle != -1) {
|
|
||||||
GLDEBUG(glDeleteVertexArraysOES(1, &m_vao_handle));
|
|
||||||
m_vao_handle = -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(m_vbo_handle != -1) {
|
|
||||||
GLDEBUG(glDeleteBuffers(1, &m_vbo_handle));
|
|
||||||
m_vbo_handle = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_vbo_handle_indexes != -1) {
|
|
||||||
GLDEBUG(glDeleteBuffers(1, &m_vbo_handle_indexes));
|
|
||||||
m_vbo_handle_indexes = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_is_vbo_loaded = false;
|
|
||||||
m_is_vbo_ready = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::KRVBOData::bind()
|
|
||||||
{
|
|
||||||
#if GL_OES_vertex_array_object
|
|
||||||
GLDEBUG(glBindVertexArrayOES(m_vao_handle));
|
|
||||||
#else
|
|
||||||
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_vbo_handle));
|
|
||||||
KRMeshManager::configureAttribs(m_vertex_attrib_flags);
|
|
||||||
if(m_vbo_handle_indexes == -1) {
|
|
||||||
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo_handle_indexes));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::KRVBOData::resetPoolExpiry(float lodCoverage)
|
|
||||||
{
|
|
||||||
long current_frame = m_manager->getContext().getCurrentFrame();
|
|
||||||
if(current_frame != m_last_frame_used) {
|
|
||||||
m_last_frame_used = current_frame;
|
|
||||||
m_last_frame_max_lod_coverage = 0.0f;
|
|
||||||
|
|
||||||
m_manager->primeVBO(this);
|
|
||||||
}
|
|
||||||
m_last_frame_max_lod_coverage = KRMAX(lodCoverage, m_last_frame_max_lod_coverage);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float KRMeshManager::KRVBOData::getStreamPriority()
|
|
||||||
{
|
|
||||||
long current_frame = m_manager->getContext().getCurrentFrame();
|
|
||||||
if(current_frame > m_last_frame_used + 5) {
|
|
||||||
return 1.0f - KRCLAMP((float)(current_frame - m_last_frame_used) / 60.0f, 0.0f, 1.0f);
|
|
||||||
} else {
|
|
||||||
return 10000.0f + m_last_frame_max_lod_coverage * 10.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::KRVBOData::_swapHandles()
|
|
||||||
{
|
|
||||||
if(m_is_vbo_loaded) {
|
|
||||||
assert(m_vbo_handle != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GL_OES_vertex_array_object
|
|
||||||
if(m_is_vbo_loaded && m_vao_handle == -1) {
|
|
||||||
GLDEBUG(glGenVertexArraysOES(1, &m_vao_handle));
|
|
||||||
GLDEBUG(glBindVertexArrayOES(m_vao_handle));
|
|
||||||
|
|
||||||
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_vbo_handle));
|
|
||||||
KRMeshManager::configureAttribs(m_vertex_attrib_flags);
|
|
||||||
if(m_vbo_handle_indexes == -1) {
|
|
||||||
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
|
||||||
} else {
|
|
||||||
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo_handle_indexes));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_is_vbo_ready = m_is_vbo_loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshManager::primeVBO(KRVBOData *vbo_data)
|
|
||||||
{
|
|
||||||
if(m_vbosActive.find(vbo_data->m_data) == m_vbosActive.end()) {
|
|
||||||
m_vbosActive[vbo_data->m_data] = vbo_data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,207 +0,0 @@
|
|||||||
//
|
|
||||||
// KRMeshManager.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRMESHMANAGER_H
|
|
||||||
#define KRMESHMANAGER_H
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
#include "KRContextObject.h"
|
|
||||||
#include "KRDataBlock.h"
|
|
||||||
#include "KRNode.h"
|
|
||||||
|
|
||||||
class KRContext;
|
|
||||||
class KRMesh;
|
|
||||||
|
|
||||||
class KRMeshManager : public KRContextObject {
|
|
||||||
public:
|
|
||||||
static const int KRENGINE_MAX_VOLUMETRIC_PLANES=500;
|
|
||||||
static const int KRENGINE_MAX_RANDOM_PARTICLES=150000;
|
|
||||||
|
|
||||||
KRMeshManager(KRContext &context);
|
|
||||||
virtual ~KRMeshManager();
|
|
||||||
|
|
||||||
void startFrame(float deltaTime);
|
|
||||||
void endFrame(float deltaTime);
|
|
||||||
void firstFrame();
|
|
||||||
|
|
||||||
KRMesh *loadModel(const char *szName, KRDataBlock *pData);
|
|
||||||
std::vector<KRMesh *> getModel(const char *szName);
|
|
||||||
void addModel(KRMesh *model);
|
|
||||||
|
|
||||||
std::vector<std::string> getModelNames();
|
|
||||||
unordered_multimap<std::string, KRMesh *> &getModels();
|
|
||||||
|
|
||||||
class KRVBOData {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
STREAMING,
|
|
||||||
CONSTANT,
|
|
||||||
TEMPORARY
|
|
||||||
} vbo_type;
|
|
||||||
|
|
||||||
KRVBOData();
|
|
||||||
KRVBOData(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t);
|
|
||||||
void init(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t);
|
|
||||||
~KRVBOData();
|
|
||||||
|
|
||||||
|
|
||||||
KRDataBlock *m_data;
|
|
||||||
KRDataBlock *m_index_data;
|
|
||||||
|
|
||||||
bool isVBOLoaded() { return m_is_vbo_loaded; }
|
|
||||||
bool isVBOReady() { return m_is_vbo_ready; }
|
|
||||||
void load();
|
|
||||||
void unload();
|
|
||||||
void bind();
|
|
||||||
|
|
||||||
// Disable copy constructors
|
|
||||||
KRVBOData(const KRVBOData& o) = delete;
|
|
||||||
KRVBOData(KRVBOData& o) = delete;
|
|
||||||
|
|
||||||
long getSize() { return m_size; }
|
|
||||||
|
|
||||||
void resetPoolExpiry(float lodCoverage);
|
|
||||||
long getLastFrameUsed() { return m_last_frame_used; }
|
|
||||||
|
|
||||||
vbo_type getType() { return m_type; }
|
|
||||||
|
|
||||||
float getStreamPriority();
|
|
||||||
|
|
||||||
void _swapHandles();
|
|
||||||
|
|
||||||
private:
|
|
||||||
KRMeshManager *m_manager;
|
|
||||||
int m_vertex_attrib_flags;
|
|
||||||
GLuint m_vbo_handle;
|
|
||||||
GLuint m_vbo_handle_indexes;
|
|
||||||
GLuint m_vao_handle;
|
|
||||||
GLsizeiptr m_size;
|
|
||||||
|
|
||||||
long m_last_frame_used;
|
|
||||||
float m_last_frame_max_lod_coverage;
|
|
||||||
vbo_type m_type;
|
|
||||||
bool m_static_vbo;
|
|
||||||
bool m_is_vbo_loaded;
|
|
||||||
bool m_is_vbo_ready;
|
|
||||||
};
|
|
||||||
|
|
||||||
void bindVBO(KRVBOData *vbo_data, float lodCoverage);
|
|
||||||
void bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, float lodCoverage);
|
|
||||||
void unbindVBO();
|
|
||||||
long getMemUsed();
|
|
||||||
long getMemActive();
|
|
||||||
|
|
||||||
static void configureAttribs(__int32_t attributes);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GLfloat x;
|
|
||||||
GLfloat y;
|
|
||||||
GLfloat z;
|
|
||||||
} Vector3D;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GLfloat u;
|
|
||||||
GLfloat v;
|
|
||||||
} TexCoord;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Vector3D vertex;
|
|
||||||
TexCoord uva;
|
|
||||||
} RandomParticleVertexData;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Vector3D vertex;
|
|
||||||
} VolumetricLightingVertexData;
|
|
||||||
|
|
||||||
|
|
||||||
KRDataBlock &getRandomParticles();
|
|
||||||
KRDataBlock &getVolumetricLightingVertexes();
|
|
||||||
|
|
||||||
|
|
||||||
long getMemoryTransferedThisFrame();
|
|
||||||
|
|
||||||
int getActiveVBOCount();
|
|
||||||
|
|
||||||
struct draw_call_info {
|
|
||||||
KRNode::RenderPass pass;
|
|
||||||
char object_name[256];
|
|
||||||
char material_name[256];
|
|
||||||
int vertex_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
void log_draw_call(KRNode::RenderPass pass, const std::string &object_name, const std::string &material_name, int vertex_count);
|
|
||||||
std::vector<draw_call_info> getDrawCalls();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KRVBOData KRENGINE_VBO_DATA_3D_CUBE_VERTICES;
|
|
||||||
KRVBOData KRENGINE_VBO_DATA_2D_SQUARE_VERTICES;
|
|
||||||
|
|
||||||
void doStreaming(long &memoryRemaining, long &memoryRemainingThisFrame);
|
|
||||||
|
|
||||||
private:
|
|
||||||
KRDataBlock KRENGINE_VBO_3D_CUBE_VERTICES, KRENGINE_VBO_3D_CUBE_INDEXES;
|
|
||||||
__int32_t KRENGINE_VBO_3D_CUBE_ATTRIBS;
|
|
||||||
KRDataBlock KRENGINE_VBO_2D_SQUARE_VERTICES, KRENGINE_VBO_2D_SQUARE_INDEXES;
|
|
||||||
__int32_t KRENGINE_VBO_2D_SQUARE_ATTRIBS;
|
|
||||||
|
|
||||||
unordered_multimap<std::string, KRMesh *> m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model
|
|
||||||
|
|
||||||
long m_vboMemUsed;
|
|
||||||
KRVBOData *m_currentVBO;
|
|
||||||
|
|
||||||
unordered_map<KRDataBlock *, KRVBOData *> m_vbosActive;
|
|
||||||
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer;
|
|
||||||
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer_copy;
|
|
||||||
|
|
||||||
KRDataBlock m_randomParticleVertexData;
|
|
||||||
KRDataBlock m_volumetricLightingVertexData;
|
|
||||||
|
|
||||||
long m_memoryTransferredThisFrame;
|
|
||||||
|
|
||||||
std::vector<draw_call_info> m_draw_calls;
|
|
||||||
bool m_draw_call_logging_enabled;
|
|
||||||
bool m_draw_call_log_used;
|
|
||||||
|
|
||||||
bool m_first_frame;
|
|
||||||
|
|
||||||
std::mutex m_streamerFenceMutex;
|
|
||||||
bool m_streamerComplete;
|
|
||||||
|
|
||||||
void balanceVBOMemory(long &memoryRemaining, long &memoryRemainingThisFrame);
|
|
||||||
|
|
||||||
void primeVBO(KRVBOData *vbo_data);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
//
|
|
||||||
// KRMeshSphere.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRMeshSphere.h"
|
|
||||||
|
|
||||||
|
|
||||||
KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere")
|
|
||||||
{
|
|
||||||
m_constant = true;
|
|
||||||
|
|
||||||
KRMesh::mesh_info mi;
|
|
||||||
|
|
||||||
// Create a triangular facet approximation to a sphere
|
|
||||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
|
||||||
|
|
||||||
int iterations = 3;
|
|
||||||
int facet_count = pow(4, iterations) * 8;
|
|
||||||
|
|
||||||
class Facet3 {
|
|
||||||
public:
|
|
||||||
Facet3() {
|
|
||||||
|
|
||||||
}
|
|
||||||
~Facet3() {
|
|
||||||
|
|
||||||
}
|
|
||||||
Vector3 p1;
|
|
||||||
Vector3 p2;
|
|
||||||
Vector3 p3;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
|
||||||
|
|
||||||
int i,it;
|
|
||||||
float a;
|
|
||||||
Vector3 p[6] = {
|
|
||||||
Vector3(0,0,1),
|
|
||||||
Vector3(0,0,-1),
|
|
||||||
Vector3(-1,-1,0),
|
|
||||||
Vector3(1,-1,0),
|
|
||||||
Vector3(1,1,0),
|
|
||||||
Vector3(-1,1,0)
|
|
||||||
};
|
|
||||||
|
|
||||||
Vector3 pa,pb,pc;
|
|
||||||
int nt = 0,ntold;
|
|
||||||
|
|
||||||
/* Create the level 0 object */
|
|
||||||
a = 1 / sqrt(2.0);
|
|
||||||
for (i=0;i<6;i++) {
|
|
||||||
p[i].x *= a;
|
|
||||||
p[i].y *= a;
|
|
||||||
}
|
|
||||||
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
|
|
||||||
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
|
|
||||||
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
|
|
||||||
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
|
|
||||||
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
|
|
||||||
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
|
|
||||||
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
|
|
||||||
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
|
|
||||||
nt = 8;
|
|
||||||
|
|
||||||
/* Bisect each edge and move to the surface of a unit sphere */
|
|
||||||
for (it=0;it<iterations;it++) {
|
|
||||||
ntold = nt;
|
|
||||||
for (i=0;i<ntold;i++) {
|
|
||||||
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
|
||||||
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
|
||||||
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
|
||||||
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
|
||||||
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
|
||||||
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
|
|
||||||
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
|
|
||||||
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
|
|
||||||
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
|
|
||||||
pa.normalize();
|
|
||||||
pb.normalize();
|
|
||||||
pc.normalize();
|
|
||||||
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
|
|
||||||
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
|
|
||||||
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
|
|
||||||
f[i].p1 = pa;
|
|
||||||
f[i].p2 = pb;
|
|
||||||
f[i].p3 = pc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int facet_index=0; facet_index < facet_count; facet_index++) {
|
|
||||||
mi.vertices.push_back(f[facet_index].p1);
|
|
||||||
mi.vertices.push_back(f[facet_index].p2);
|
|
||||||
mi.vertices.push_back(f[facet_index].p3);
|
|
||||||
}
|
|
||||||
|
|
||||||
mi.submesh_starts.push_back(0);
|
|
||||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
|
||||||
mi.material_names.push_back("");
|
|
||||||
|
|
||||||
|
|
||||||
mi.format = KRENGINE_MODEL_FORMAT_TRIANGLES;
|
|
||||||
LoadData(mi, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
KRMeshSphere::~KRMeshSphere()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
//
|
|
||||||
// KRMeshStreamer.cpp
|
|
||||||
// Kraken
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 11/1/2013.
|
|
||||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KRMeshStreamer.h"
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
|
||||||
|
|
||||||
EAGLContext *gMeshStreamerContext = nil;
|
|
||||||
|
|
||||||
#elif TARGET_OS_MAC
|
|
||||||
|
|
||||||
NSOpenGLContext *gMeshStreamerContext = nil;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#error Unsupported Platform
|
|
||||||
#endif
|
|
||||||
|
|
||||||
KRMeshStreamer::KRMeshStreamer(KRContext &context) : m_context(context)
|
|
||||||
{
|
|
||||||
m_running = false;
|
|
||||||
m_stop = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshStreamer::startStreamer()
|
|
||||||
{
|
|
||||||
if(!m_running) {
|
|
||||||
m_running = true;
|
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
|
||||||
gMeshStreamerContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: [EAGLContext currentContext].sharegroup];
|
|
||||||
#elif TARGET_OS_MAC
|
|
||||||
NSOpenGLPixelFormatAttribute pixelFormatAttributes[] =
|
|
||||||
{
|
|
||||||
// NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes] autorelease];
|
|
||||||
gMeshStreamerContext = [[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: [NSOpenGLContext currentContext] ];
|
|
||||||
#else
|
|
||||||
#error Unsupported Platform
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_thread = std::thread(&KRMeshStreamer::run, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KRMeshStreamer::~KRMeshStreamer()
|
|
||||||
{
|
|
||||||
if(m_running) {
|
|
||||||
m_stop = true;
|
|
||||||
m_thread.join();
|
|
||||||
m_running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[gMeshStreamerContext release];
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRMeshStreamer::run()
|
|
||||||
{
|
|
||||||
pthread_setname_np("Kraken - Mesh Streamer");
|
|
||||||
|
|
||||||
std::chrono::microseconds sleep_duration( 100 );
|
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
|
||||||
[EAGLContext setCurrentContext: gMeshStreamerContext];
|
|
||||||
#elif TARGET_OS_MAC
|
|
||||||
[gMeshStreamerContext makeCurrentContext];
|
|
||||||
#else
|
|
||||||
#error Unsupported Platform
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
while(!m_stop)
|
|
||||||
{
|
|
||||||
if(m_context.getStreamingEnabled()) {
|
|
||||||
|
|
||||||
}
|
|
||||||
std::this_thread::sleep_for( sleep_duration );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,263 +0,0 @@
|
|||||||
//
|
|
||||||
// KRModel.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#include "KRModel.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "KRMesh.h"
|
|
||||||
|
|
||||||
KRModel::KRModel(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color, float rim_power) : KRNode(scene, instance_name) {
|
|
||||||
m_lightMap = light_map;
|
|
||||||
m_pLightMap = NULL;
|
|
||||||
m_model_name = model_name;
|
|
||||||
m_min_lod_coverage = lod_min_coverage;
|
|
||||||
m_receivesShadow = receives_shadow;
|
|
||||||
m_faces_camera = faces_camera;
|
|
||||||
m_rim_color = rim_color;
|
|
||||||
m_rim_power = rim_power;
|
|
||||||
|
|
||||||
m_boundsCachedMat.c[0] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[1] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[2] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[3] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[4] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[5] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[6] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[7] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[8] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[9] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[10] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[11] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[12] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[13] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[14] = -1.0f;
|
|
||||||
m_boundsCachedMat.c[15] = -1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRModel::~KRModel() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRModel::getElementName() {
|
|
||||||
return "model";
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent)
|
|
||||||
{
|
|
||||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
|
||||||
e->SetAttribute("mesh", m_model_name.c_str());
|
|
||||||
e->SetAttribute("light_map", m_lightMap.c_str());
|
|
||||||
e->SetAttribute("lod_min_coverage", m_min_lod_coverage);
|
|
||||||
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false");
|
|
||||||
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false");
|
|
||||||
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero());
|
|
||||||
e->SetAttribute("rim_power", m_rim_power);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRModel::setRimColor(const Vector3 &rim_color)
|
|
||||||
{
|
|
||||||
m_rim_color = rim_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRModel::setRimPower(float rim_power)
|
|
||||||
{
|
|
||||||
m_rim_power = rim_power;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 KRModel::getRimColor()
|
|
||||||
{
|
|
||||||
return m_rim_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
float KRModel::getRimPower()
|
|
||||||
{
|
|
||||||
return m_rim_power;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRModel::setLightMap(const std::string &name)
|
|
||||||
{
|
|
||||||
m_lightMap = name;
|
|
||||||
m_pLightMap = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRModel::getLightMap()
|
|
||||||
{
|
|
||||||
return m_lightMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRModel::loadModel() {
|
|
||||||
if(m_models.size() == 0) {
|
|
||||||
std::vector<KRMesh *> models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
|
|
||||||
unordered_map<KRMesh *, std::vector<KRBone *> > bones;
|
|
||||||
if(models.size() > 0) {
|
|
||||||
bool all_bones_found = true;
|
|
||||||
for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
|
|
||||||
KRMesh *model = *model_itr;
|
|
||||||
std::vector<KRBone *> model_bones;
|
|
||||||
int bone_count = model->getBoneCount();
|
|
||||||
for(int bone_index=0; bone_index < bone_count; bone_index++) {
|
|
||||||
KRBone *matching_bone = dynamic_cast<KRBone *>(getScene().getRootNode()->find<KRNode>(model->getBoneName(bone_index)));
|
|
||||||
if(matching_bone) {
|
|
||||||
model_bones.push_back(matching_bone);
|
|
||||||
} else {
|
|
||||||
all_bones_found = false; // Reject when there are any missing bones or multiple matches
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bones[model] = model_bones;
|
|
||||||
}
|
|
||||||
if(all_bones_found) {
|
|
||||||
m_models = models;
|
|
||||||
m_bones = bones;
|
|
||||||
getScene().notify_sceneGraphModify(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidateBounds();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRModel::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
|
|
||||||
|
|
||||||
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
|
|
||||||
preStream(viewport);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
|
||||||
|
|
||||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
|
||||||
|
|
||||||
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && renderPass != KRNode::RENDER_PASS_PRESTREAM) {
|
|
||||||
loadModel();
|
|
||||||
|
|
||||||
if(m_models.size() > 0) {
|
|
||||||
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
|
|
||||||
|
|
||||||
/*
|
|
||||||
float lod_coverage = 0.0f;
|
|
||||||
if(m_models.size() > 1) {
|
|
||||||
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
|
||||||
} else if(viewport.visible(getBounds())) {
|
|
||||||
lod_coverage = 1.0f;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
|
||||||
|
|
||||||
if(lod_coverage > m_min_lod_coverage) {
|
|
||||||
|
|
||||||
// ---===--- Select the best LOD model based on screen coverage ---===---
|
|
||||||
std::vector<KRMesh *>::iterator itr=m_models.begin();
|
|
||||||
KRMesh *pModel = *itr++;
|
|
||||||
|
|
||||||
while(itr != m_models.end()) {
|
|
||||||
KRMesh *pLODModel = *itr++;
|
|
||||||
if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
|
|
||||||
pModel = pLODModel;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
|
||||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pLightMap && pCamera->settings.bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) {
|
|
||||||
m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4 matModel = getModelMatrix();
|
|
||||||
if(m_faces_camera) {
|
|
||||||
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
|
|
||||||
Vector3 camera_pos = viewport.getCameraPosition();
|
|
||||||
matModel = Quaternion(Vector3::Forward(), Vector3::Normalize(camera_pos - model_center)).rotationMatrix() * matModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
pModel->render(getName(), pCamera, point_lights, directional_lights, spot_lights, viewport, matModel, m_pLightMap, renderPass, m_bones[pModel], m_rim_color, m_rim_power, lod_coverage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRModel::preStream(const KRViewport &viewport)
|
|
||||||
{
|
|
||||||
loadModel();
|
|
||||||
float lod_coverage = viewport.coverage(getBounds());
|
|
||||||
|
|
||||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
|
||||||
(*itr)->preStream(lod_coverage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
|
||||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pLightMap) {
|
|
||||||
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport)
|
|
||||||
{
|
|
||||||
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
|
|
||||||
|
|
||||||
loadModel();
|
|
||||||
|
|
||||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
|
||||||
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
|
|
||||||
}
|
|
||||||
|
|
||||||
return stream_level;
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB KRModel::getBounds() {
|
|
||||||
loadModel();
|
|
||||||
if(m_models.size() > 0) {
|
|
||||||
if(m_faces_camera) {
|
|
||||||
AABB normal_bounds = AABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
|
||||||
float max_dimension = normal_bounds.longest_radius();
|
|
||||||
return AABB(normal_bounds.center()-Vector3(max_dimension), normal_bounds.center() + Vector3(max_dimension));
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if(!(m_boundsCachedMat == getModelMatrix())) {
|
|
||||||
m_boundsCachedMat = getModelMatrix();
|
|
||||||
m_boundsCached = AABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
|
||||||
}
|
|
||||||
return m_boundsCached;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return AABB::Infinite();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
//
|
|
||||||
// KRModel.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other materials
|
|
||||||
// provided with the distribution.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
|
||||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// The views and conclusions contained in the software and documentation are those of the
|
|
||||||
// authors and should not be interpreted as representing official policies, either expressed
|
|
||||||
// or implied, of Kearwood Gilbert.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#ifndef KRMODEL_H
|
|
||||||
#define KRMODEL_H
|
|
||||||
|
|
||||||
#include "KRMesh.h"
|
|
||||||
#include "KRModel.h"
|
|
||||||
#include "KRCamera.h"
|
|
||||||
#include "KRMeshManager.h"
|
|
||||||
#include "KRNode.h"
|
|
||||||
#include "KRContext.h"
|
|
||||||
#include "KRMesh.h"
|
|
||||||
#include "KRTexture.h"
|
|
||||||
#include "KRBone.h"
|
|
||||||
|
|
||||||
class KRModel : public KRNode {
|
|
||||||
|
|
||||||
public:
|
|
||||||
KRModel(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color = Vector3::Zero(), float rim_power = 0.0f);
|
|
||||||
virtual ~KRModel();
|
|
||||||
|
|
||||||
virtual std::string getElementName();
|
|
||||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
|
||||||
|
|
||||||
virtual void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
|
|
||||||
|
|
||||||
virtual AABB getBounds();
|
|
||||||
|
|
||||||
void setRimColor(const Vector3 &rim_color);
|
|
||||||
void setRimPower(float rim_power);
|
|
||||||
Vector3 getRimColor();
|
|
||||||
float getRimPower();
|
|
||||||
|
|
||||||
void setLightMap(const std::string &name);
|
|
||||||
std::string getLightMap();
|
|
||||||
|
|
||||||
virtual kraken_stream_level getStreamLevel(const KRViewport &viewport);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void preStream(const KRViewport &viewport);
|
|
||||||
|
|
||||||
std::vector<KRMesh *> m_models;
|
|
||||||
unordered_map<KRMesh *, std::vector<KRBone *> > m_bones; // Outer std::map connects model to set of bones
|
|
||||||
KRTexture *m_pLightMap;
|
|
||||||
std::string m_lightMap;
|
|
||||||
std::string m_model_name;
|
|
||||||
|
|
||||||
|
|
||||||
float m_min_lod_coverage;
|
|
||||||
void loadModel();
|
|
||||||
|
|
||||||
bool m_receivesShadow;
|
|
||||||
bool m_faces_camera;
|
|
||||||
|
|
||||||
|
|
||||||
Matrix4 m_boundsCachedMat;
|
|
||||||
AABB m_boundsCached;
|
|
||||||
|
|
||||||
|
|
||||||
Vector3 m_rim_color;
|
|
||||||
float m_rim_power;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
135
kraken/KRModelView.cpp
Normal file
135
kraken/KRModelView.cpp
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
//
|
||||||
|
// KRModelView.cpp
|
||||||
|
// Kraken Engine
|
||||||
|
//
|
||||||
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
|
#include "KRModelView.h"
|
||||||
|
#include "KRViewport.h"
|
||||||
|
|
||||||
|
using namespace hydra;
|
||||||
|
|
||||||
|
KRModelView::KRModelView(KRViewport* viewport, const hydra::Matrix4& matModel)
|
||||||
|
: m_viewport(viewport)
|
||||||
|
, m_matModel(matModel)
|
||||||
|
{
|
||||||
|
m_matModelInverse = matModel;
|
||||||
|
m_matModelInverse.invert();
|
||||||
|
|
||||||
|
m_matModelView = matModel * viewport->getViewMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
KRModelView::~KRModelView()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRModelView::getShaderValue(ShaderValue value, Vector3* output) const
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (value) {
|
||||||
|
case ShaderValue::camerapos_model_space:
|
||||||
|
{
|
||||||
|
// Transform location of camera to object space for calculation of specular halfVec
|
||||||
|
*output = Matrix4::Dot(m_matModelInverse, m_viewport->getCameraPosition());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case ShaderValue::view_space_model_origin:
|
||||||
|
{
|
||||||
|
// Origin point of model space is the light source position. No perspective, so no w divide required
|
||||||
|
*output = Matrix4::Dot(m_matModelView, Vector3::Zero());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool KRModelView::getShaderValue(ShaderValue value, Matrix4* output) const
|
||||||
|
{
|
||||||
|
switch (value) {
|
||||||
|
case ShaderValue::model_matrix:
|
||||||
|
{
|
||||||
|
*output = m_matModel;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case ShaderValue::model_view:
|
||||||
|
{
|
||||||
|
*output = m_matModelView;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case ShaderValue::model_view_inverse_transpose:
|
||||||
|
{
|
||||||
|
Matrix4 matModelViewInverseTranspose = m_matModelView;
|
||||||
|
matModelViewInverseTranspose.transpose();
|
||||||
|
matModelViewInverseTranspose.invert();
|
||||||
|
*output = matModelViewInverseTranspose;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case ShaderValue::model_inverse_transpose:
|
||||||
|
{
|
||||||
|
Matrix4 matModelInverseTranspose = m_matModel;
|
||||||
|
matModelInverseTranspose.transpose();
|
||||||
|
matModelInverseTranspose.invert();
|
||||||
|
*output = matModelInverseTranspose;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case ShaderValue::invmvp_no_translate:
|
||||||
|
{
|
||||||
|
Matrix4 matInvMVPNoTranslate = m_matModelView;
|
||||||
|
// Remove the translation
|
||||||
|
matInvMVPNoTranslate.getPointer()[3] = 0;
|
||||||
|
matInvMVPNoTranslate.getPointer()[7] = 0;
|
||||||
|
matInvMVPNoTranslate.getPointer()[11] = 0;
|
||||||
|
matInvMVPNoTranslate.getPointer()[12] = 0;
|
||||||
|
matInvMVPNoTranslate.getPointer()[13] = 0;
|
||||||
|
matInvMVPNoTranslate.getPointer()[14] = 0;
|
||||||
|
matInvMVPNoTranslate.getPointer()[15] = 1.0;
|
||||||
|
matInvMVPNoTranslate = matInvMVPNoTranslate * m_viewport->getProjectionMatrix();
|
||||||
|
matInvMVPNoTranslate.invert();
|
||||||
|
*output = matInvMVPNoTranslate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case ShaderValue::mvp:
|
||||||
|
{
|
||||||
|
Matrix4 mvpMatrix = m_matModel * m_viewport->getViewProjectionMatrix();
|
||||||
|
*output = mvpMatrix;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case ShaderValue::invmvp:
|
||||||
|
{
|
||||||
|
Matrix4 mvpMatrix = m_matModel * m_viewport->getViewProjectionMatrix();
|
||||||
|
Matrix4 invMVP = Matrix4::Invert(mvpMatrix);
|
||||||
|
*output = invMVP;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
59
kraken/KRModelView.h
Normal file
59
kraken/KRModelView.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// KRModelView.h
|
||||||
|
// Kraken Engine
|
||||||
|
//
|
||||||
|
// Copyright 2025 Kearwood Gilbert. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
|
#include "aabb.h"
|
||||||
|
|
||||||
|
#include "KRShaderReflection.h"
|
||||||
|
|
||||||
|
class KRViewport;
|
||||||
|
|
||||||
|
class KRModelView
|
||||||
|
: public KRReflectedObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KRModelView(KRViewport* viewport, const hydra::Matrix4& matModel);
|
||||||
|
~KRModelView();
|
||||||
|
|
||||||
|
bool getShaderValue(ShaderValue value, hydra::Vector3* output) const final;
|
||||||
|
bool getShaderValue(ShaderValue value, hydra::Matrix4* output) const final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
KRViewport* m_viewport;
|
||||||
|
hydra::Matrix4 m_matModel;
|
||||||
|
|
||||||
|
// Derived values
|
||||||
|
hydra::Matrix4 m_matModelInverse;
|
||||||
|
hydra::Matrix4 m_matModelView;
|
||||||
|
};
|
||||||
@@ -1,959 +0,0 @@
|
|||||||
//
|
|
||||||
// KRNode.cpp
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 12-04-11.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
|
||||||
|
|
||||||
#include "KRNode.h"
|
|
||||||
#include "KRLODGroup.h"
|
|
||||||
#include "KRLODSet.h"
|
|
||||||
#include "KRPointLight.h"
|
|
||||||
#include "KRSpotLight.h"
|
|
||||||
#include "KRDirectionalLight.h"
|
|
||||||
#include "KRModel.h"
|
|
||||||
#include "KRCollider.h"
|
|
||||||
#include "KRParticleSystem.h"
|
|
||||||
#include "KRParticleSystemNewtonian.h"
|
|
||||||
#include "KRBone.h"
|
|
||||||
#include "KRLocator.h"
|
|
||||||
#include "KRAudioSource.h"
|
|
||||||
#include "KRAmbientZone.h"
|
|
||||||
#include "KRReverbZone.h"
|
|
||||||
#include "KRSprite.h"
|
|
||||||
|
|
||||||
KRNode::KRNode(KRScene &scene, std::string name) : KRContextObject(scene.getContext())
|
|
||||||
{
|
|
||||||
m_name = name;
|
|
||||||
m_localScale = Vector3::One();
|
|
||||||
m_localRotation = Vector3::Zero();
|
|
||||||
m_localTranslation = Vector3::Zero();
|
|
||||||
m_initialLocalTranslation = m_localTranslation;
|
|
||||||
m_initialLocalScale = m_localScale;
|
|
||||||
m_initialLocalRotation = m_localRotation;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
m_rotationOffset = Vector3::Zero();
|
|
||||||
m_scalingOffset = Vector3::Zero();
|
|
||||||
m_rotationPivot = Vector3::Zero();
|
|
||||||
m_scalingPivot = Vector3::Zero();
|
|
||||||
m_preRotation = Vector3::Zero();
|
|
||||||
m_postRotation = Vector3::Zero();
|
|
||||||
|
|
||||||
m_initialRotationOffset = Vector3::Zero();
|
|
||||||
m_initialScalingOffset = Vector3::Zero();
|
|
||||||
m_initialRotationPivot = Vector3::Zero();
|
|
||||||
m_initialScalingPivot = Vector3::Zero();
|
|
||||||
m_initialPreRotation = Vector3::Zero();
|
|
||||||
m_initialPostRotation = Vector3::Zero();
|
|
||||||
|
|
||||||
m_parentNode = NULL;
|
|
||||||
m_pScene = &scene;
|
|
||||||
m_modelMatrixValid = false;
|
|
||||||
m_inverseModelMatrixValid = false;
|
|
||||||
m_bindPoseMatrixValid = false;
|
|
||||||
m_activePoseMatrixValid = false;
|
|
||||||
m_inverseBindPoseMatrixValid = false;
|
|
||||||
m_modelMatrix = Matrix4();
|
|
||||||
m_bindPoseMatrix = Matrix4();
|
|
||||||
m_activePoseMatrix = Matrix4();
|
|
||||||
m_lod_visible = LOD_VISIBILITY_HIDDEN;
|
|
||||||
m_scale_compensation = false;
|
|
||||||
m_boundsValid = false;
|
|
||||||
|
|
||||||
m_lastRenderFrame = -1000;
|
|
||||||
for(int i=0; i < KRENGINE_NODE_ATTRIBUTE_COUNT; i++) {
|
|
||||||
m_animation_mask[i] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KRNode::~KRNode() {
|
|
||||||
|
|
||||||
|
|
||||||
while(m_childNodes.size() > 0) {
|
|
||||||
delete *m_childNodes.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(std::set<KRBehavior *>::iterator itr = m_behaviors.begin(); itr != m_behaviors.end(); itr++) {
|
|
||||||
delete *itr;
|
|
||||||
}
|
|
||||||
m_behaviors.clear();
|
|
||||||
|
|
||||||
if(m_parentNode) {
|
|
||||||
m_parentNode->childDeleted(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
getScene().notify_sceneGraphDelete(this);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::setScaleCompensation(bool scale_compensation)
|
|
||||||
{
|
|
||||||
if(m_scale_compensation != scale_compensation) {
|
|
||||||
m_scale_compensation = scale_compensation;
|
|
||||||
invalidateModelMatrix();
|
|
||||||
invalidateBindPoseMatrix();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool KRNode::getScaleCompensation()
|
|
||||||
{
|
|
||||||
return m_scale_compensation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::childDeleted(KRNode *child_node)
|
|
||||||
{
|
|
||||||
m_childNodes.erase(child_node);
|
|
||||||
invalidateBounds();
|
|
||||||
getScene().notify_sceneGraphModify(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::addChild(KRNode *child) {
|
|
||||||
assert(child->m_parentNode == NULL);
|
|
||||||
child->m_parentNode = this;
|
|
||||||
m_childNodes.insert(child);
|
|
||||||
child->setLODVisibility(m_lod_visible); // Child node inherits LOD visibility status from parent
|
|
||||||
}
|
|
||||||
|
|
||||||
tinyxml2::XMLElement *KRNode::saveXML(tinyxml2::XMLNode *parent) {
|
|
||||||
tinyxml2::XMLDocument *doc = parent->GetDocument();
|
|
||||||
tinyxml2::XMLElement *e = doc->NewElement(getElementName().c_str());
|
|
||||||
tinyxml2::XMLNode *n = parent->InsertEndChild(e);
|
|
||||||
e->SetAttribute("name", m_name.c_str());
|
|
||||||
kraken::setXMLAttribute("translate", e, m_localTranslation, Vector3::Zero());
|
|
||||||
kraken::setXMLAttribute("scale", e, m_localScale, Vector3::One());
|
|
||||||
kraken::setXMLAttribute("rotate", e, (m_localRotation * (180.0f / M_PI)), Vector3::Zero());
|
|
||||||
kraken::setXMLAttribute("rotate_offset", e, m_rotationOffset, Vector3::Zero());
|
|
||||||
kraken::setXMLAttribute("scale_offset", e, m_scalingOffset, Vector3::Zero());
|
|
||||||
kraken::setXMLAttribute("rotate_pivot", e, m_rotationPivot, Vector3::Zero());
|
|
||||||
kraken::setXMLAttribute("scale_pivot", e, m_scalingPivot, Vector3::Zero());
|
|
||||||
kraken::setXMLAttribute("pre_rotate", e, (m_preRotation * (180.0f / M_PI)), Vector3::Zero());
|
|
||||||
kraken::setXMLAttribute("post_rotate", e, (m_postRotation * (180.0f / M_PI)), Vector3::Zero());
|
|
||||||
|
|
||||||
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
KRNode *child = (*itr);
|
|
||||||
child->saveXML(n);
|
|
||||||
}
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::loadXML(tinyxml2::XMLElement *e) {
|
|
||||||
m_name = e->Attribute("name");
|
|
||||||
m_localTranslation = kraken::getXMLAttribute("translate", e, Vector3::Zero());
|
|
||||||
m_localScale = kraken::getXMLAttribute("scale", e, Vector3::One());
|
|
||||||
m_localRotation = kraken::getXMLAttribute("rotate", e, Vector3::Zero());
|
|
||||||
m_localRotation *= M_PI / 180.0f; // Convert degrees to radians
|
|
||||||
m_preRotation = kraken::getXMLAttribute("pre_rotate", e, Vector3::Zero());
|
|
||||||
m_preRotation *= M_PI / 180.0f; // Convert degrees to radians
|
|
||||||
m_postRotation = kraken::getXMLAttribute("post_rotate", e, Vector3::Zero());
|
|
||||||
m_postRotation *= M_PI / 180.0f; // Convert degrees to radians
|
|
||||||
|
|
||||||
m_rotationOffset = kraken::getXMLAttribute("rotate_offset", e, Vector3::Zero());
|
|
||||||
m_scalingOffset = kraken::getXMLAttribute("scale_offset", e, Vector3::Zero());
|
|
||||||
m_rotationPivot = kraken::getXMLAttribute("rotate_pivot", e, Vector3::Zero());
|
|
||||||
m_scalingPivot = kraken::getXMLAttribute("scale_pivot", e, Vector3::Zero());
|
|
||||||
|
|
||||||
m_initialLocalTranslation = m_localTranslation;
|
|
||||||
m_initialLocalScale = m_localScale;
|
|
||||||
m_initialLocalRotation = m_localRotation;
|
|
||||||
|
|
||||||
m_initialRotationOffset = m_rotationOffset;
|
|
||||||
m_initialScalingOffset = m_scalingOffset;
|
|
||||||
m_initialRotationPivot = m_rotationPivot;
|
|
||||||
m_initialScalingPivot = m_scalingPivot;
|
|
||||||
m_initialPreRotation = m_preRotation;
|
|
||||||
m_initialPostRotation = m_postRotation;
|
|
||||||
|
|
||||||
m_bindPoseMatrixValid = false;
|
|
||||||
m_activePoseMatrixValid = false;
|
|
||||||
m_inverseBindPoseMatrixValid = false;
|
|
||||||
m_modelMatrixValid = false;
|
|
||||||
m_inverseModelMatrixValid = false;
|
|
||||||
|
|
||||||
for(tinyxml2::XMLElement *child_element=e->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) {
|
|
||||||
const char *szElementName = child_element->Name();
|
|
||||||
if(strcmp(szElementName, "behavior") == 0) {
|
|
||||||
KRBehavior *behavior = KRBehavior::LoadXML(this, child_element);
|
|
||||||
if(behavior) {
|
|
||||||
addBehavior(behavior);
|
|
||||||
behavior->init();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
KRNode *child_node = KRNode::LoadXML(getScene(), child_element);
|
|
||||||
|
|
||||||
if(child_node) {
|
|
||||||
addChild(child_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::setLocalTranslation(const Vector3 &v, bool set_original) {
|
|
||||||
m_localTranslation = v;
|
|
||||||
if(set_original) {
|
|
||||||
m_initialLocalTranslation = v;
|
|
||||||
invalidateBindPoseMatrix();
|
|
||||||
}
|
|
||||||
invalidateModelMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::setWorldTranslation(const Vector3 &v)
|
|
||||||
{
|
|
||||||
if(m_parentNode) {
|
|
||||||
setLocalTranslation(Matrix4::Dot(m_parentNode->getInverseModelMatrix(), v));
|
|
||||||
} else {
|
|
||||||
setLocalTranslation(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void KRNode::setWorldRotation(const Vector3 &v)
|
|
||||||
{
|
|
||||||
if(m_parentNode) {
|
|
||||||
setLocalRotation((Quaternion(v) * -m_parentNode->getWorldRotation()).eulerXYZ());
|
|
||||||
setPreRotation(Vector3::Zero());
|
|
||||||
setPostRotation(Vector3::Zero());
|
|
||||||
} else {
|
|
||||||
setLocalRotation(v);
|
|
||||||
setPreRotation(Vector3::Zero());
|
|
||||||
setPostRotation(Vector3::Zero());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void KRNode::setWorldScale(const Vector3 &v)
|
|
||||||
{
|
|
||||||
if(m_parentNode) {
|
|
||||||
setLocalScale(Matrix4::DotNoTranslate(m_parentNode->getInverseModelMatrix(), v));
|
|
||||||
} else {
|
|
||||||
setLocalScale(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::setLocalScale(const Vector3 &v, bool set_original) {
|
|
||||||
m_localScale = v;
|
|
||||||
if(set_original) {
|
|
||||||
m_initialLocalScale = v;
|
|
||||||
invalidateBindPoseMatrix();
|
|
||||||
}
|
|
||||||
invalidateModelMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::setLocalRotation(const Vector3 &v, bool set_original) {
|
|
||||||
m_localRotation = v;
|
|
||||||
if(set_original) {
|
|
||||||
m_initialLocalRotation = v;
|
|
||||||
invalidateBindPoseMatrix();
|
|
||||||
}
|
|
||||||
invalidateModelMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void KRNode::setRotationOffset(const Vector3 &v, bool set_original)
|
|
||||||
{
|
|
||||||
m_rotationOffset = v;
|
|
||||||
if(set_original) {
|
|
||||||
m_initialRotationOffset = v;
|
|
||||||
invalidateBindPoseMatrix();
|
|
||||||
}
|
|
||||||
invalidateModelMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::setScalingOffset(const Vector3 &v, bool set_original)
|
|
||||||
{
|
|
||||||
m_scalingOffset = v;
|
|
||||||
if(set_original) {
|
|
||||||
m_initialScalingOffset = v;
|
|
||||||
invalidateBindPoseMatrix();
|
|
||||||
}
|
|
||||||
invalidateModelMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::setRotationPivot(const Vector3 &v, bool set_original)
|
|
||||||
{
|
|
||||||
m_rotationPivot = v;
|
|
||||||
if(set_original) {
|
|
||||||
m_initialRotationPivot = v;
|
|
||||||
invalidateBindPoseMatrix();
|
|
||||||
}
|
|
||||||
invalidateModelMatrix();
|
|
||||||
}
|
|
||||||
void KRNode::setScalingPivot(const Vector3 &v, bool set_original)
|
|
||||||
{
|
|
||||||
m_scalingPivot = v;
|
|
||||||
if(set_original) {
|
|
||||||
m_initialScalingPivot = v;
|
|
||||||
invalidateBindPoseMatrix();
|
|
||||||
}
|
|
||||||
invalidateModelMatrix();
|
|
||||||
}
|
|
||||||
void KRNode::setPreRotation(const Vector3 &v, bool set_original)
|
|
||||||
{
|
|
||||||
m_preRotation = v;
|
|
||||||
if(set_original) {
|
|
||||||
m_initialPreRotation = v;
|
|
||||||
invalidateBindPoseMatrix();
|
|
||||||
}
|
|
||||||
invalidateModelMatrix();
|
|
||||||
}
|
|
||||||
void KRNode::setPostRotation(const Vector3 &v, bool set_original)
|
|
||||||
{
|
|
||||||
m_postRotation = v;
|
|
||||||
if(set_original) {
|
|
||||||
m_initialPostRotation = v;
|
|
||||||
invalidateBindPoseMatrix();
|
|
||||||
}
|
|
||||||
invalidateModelMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3 &KRNode::getRotationOffset()
|
|
||||||
{
|
|
||||||
return m_rotationOffset;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getScalingOffset()
|
|
||||||
{
|
|
||||||
return m_scalingOffset;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getRotationPivot()
|
|
||||||
{
|
|
||||||
return m_rotationPivot;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getScalingPivot()
|
|
||||||
{
|
|
||||||
return m_scalingPivot;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getPreRotation()
|
|
||||||
{
|
|
||||||
return m_preRotation;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getPostRotation()
|
|
||||||
{
|
|
||||||
return m_postRotation;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getInitialRotationOffset()
|
|
||||||
{
|
|
||||||
return m_initialRotationOffset;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getInitialScalingOffset()
|
|
||||||
{
|
|
||||||
return m_initialScalingOffset;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getInitialRotationPivot()
|
|
||||||
{
|
|
||||||
return m_initialRotationPivot;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getInitialScalingPivot()
|
|
||||||
{
|
|
||||||
return m_initialScalingPivot;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getInitialPreRotation()
|
|
||||||
{
|
|
||||||
return m_initialPreRotation;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getInitialPostRotation()
|
|
||||||
{
|
|
||||||
return m_initialPostRotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3 &KRNode::getLocalTranslation() {
|
|
||||||
return m_localTranslation;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getLocalScale() {
|
|
||||||
return m_localScale;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getLocalRotation() {
|
|
||||||
return m_localRotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3 &KRNode::getInitialLocalTranslation() {
|
|
||||||
return m_initialLocalTranslation;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getInitialLocalScale() {
|
|
||||||
return m_initialLocalScale;
|
|
||||||
}
|
|
||||||
const Vector3 &KRNode::getInitialLocalRotation() {
|
|
||||||
return m_initialLocalRotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3 KRNode::getWorldTranslation() {
|
|
||||||
return localToWorld(Vector3::Zero());
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3 KRNode::getWorldScale() {
|
|
||||||
return Matrix4::DotNoTranslate(getModelMatrix(), m_localScale);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string KRNode::getElementName() {
|
|
||||||
return "node";
|
|
||||||
}
|
|
||||||
|
|
||||||
KRNode *KRNode::LoadXML(KRScene &scene, tinyxml2::XMLElement *e) {
|
|
||||||
KRNode *new_node = NULL;
|
|
||||||
const char *szElementName = e->Name();
|
|
||||||
const char *szName = e->Attribute("name");
|
|
||||||
if(strcmp(szElementName, "node") == 0) {
|
|
||||||
new_node = new KRNode(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "lod_set") == 0) {
|
|
||||||
new_node = new KRLODSet(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "lod_group") == 0) {
|
|
||||||
new_node = new KRLODGroup(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "point_light") == 0) {
|
|
||||||
new_node = new KRPointLight(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "directional_light") == 0) {
|
|
||||||
new_node = new KRDirectionalLight(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "spot_light") == 0) {
|
|
||||||
new_node = new KRSpotLight(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "particles_newtonian") == 0) {
|
|
||||||
new_node = new KRParticleSystemNewtonian(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "sprite") == 0) {
|
|
||||||
new_node = new KRSprite(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "model") == 0) {
|
|
||||||
float lod_min_coverage = 0.0f;
|
|
||||||
if(e->QueryFloatAttribute("lod_min_coverage", &lod_min_coverage) != tinyxml2::XML_SUCCESS) {
|
|
||||||
lod_min_coverage = 0.0f;
|
|
||||||
}
|
|
||||||
bool receives_shadow = true;
|
|
||||||
if(e->QueryBoolAttribute("receives_shadow", &receives_shadow) != tinyxml2::XML_SUCCESS) {
|
|
||||||
receives_shadow = true;
|
|
||||||
}
|
|
||||||
bool faces_camera = false;
|
|
||||||
if(e->QueryBoolAttribute("faces_camera", &faces_camera) != tinyxml2::XML_SUCCESS) {
|
|
||||||
faces_camera = false;
|
|
||||||
}
|
|
||||||
float rim_power = 0.0f;
|
|
||||||
if(e->QueryFloatAttribute("rim_power", &rim_power) != tinyxml2::XML_SUCCESS) {
|
|
||||||
rim_power = 0.0f;
|
|
||||||
}
|
|
||||||
Vector3 rim_color = Vector3::Zero();
|
|
||||||
rim_color = kraken::getXMLAttribute("rim_color", e, Vector3::Zero());
|
|
||||||
new_node = new KRModel(scene, szName, e->Attribute("mesh"), e->Attribute("light_map"), lod_min_coverage, receives_shadow, faces_camera, rim_color, rim_power);
|
|
||||||
} else if(strcmp(szElementName, "collider") == 0) {
|
|
||||||
new_node = new KRCollider(scene, szName, e->Attribute("mesh"), 65535, 1.0f);
|
|
||||||
} else if(strcmp(szElementName, "bone") == 0) {
|
|
||||||
new_node = new KRBone(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "locator") == 0) {
|
|
||||||
new_node = new KRLocator(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "audio_source") == 0) {
|
|
||||||
new_node = new KRAudioSource(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "ambient_zone") == 0) {
|
|
||||||
new_node = new KRAmbientZone(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "reverb_zone") == 0) {
|
|
||||||
new_node = new KRReverbZone(scene, szName);
|
|
||||||
} else if(strcmp(szElementName, "camera") == 0) {
|
|
||||||
new_node = new KRCamera(scene, szName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(new_node) {
|
|
||||||
new_node->loadXML(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, RenderPass renderPass)
|
|
||||||
{
|
|
||||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
|
||||||
|
|
||||||
m_lastRenderFrame = getContext().getCurrentFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::set<KRNode *> &KRNode::getChildren() {
|
|
||||||
return m_childNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRNode *KRNode::getParent() {
|
|
||||||
return m_parentNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &KRNode::getName() const {
|
|
||||||
return m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
KRScene &KRNode::getScene() {
|
|
||||||
return *m_pScene;
|
|
||||||
}
|
|
||||||
|
|
||||||
AABB KRNode::getBounds() {
|
|
||||||
if(!m_boundsValid) {
|
|
||||||
AABB bounds = AABB::Zero();
|
|
||||||
|
|
||||||
bool first_child = true;
|
|
||||||
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
KRNode *child = (*itr);
|
|
||||||
if(child->getBounds() != AABB::Zero()) {
|
|
||||||
if(first_child) {
|
|
||||||
first_child = false;
|
|
||||||
bounds = child->getBounds();
|
|
||||||
} else {
|
|
||||||
bounds.encapsulate(child->getBounds());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bounds = bounds;
|
|
||||||
m_boundsValid = true;
|
|
||||||
}
|
|
||||||
return m_bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::invalidateModelMatrix()
|
|
||||||
{
|
|
||||||
m_modelMatrixValid = false;
|
|
||||||
m_activePoseMatrixValid = false;
|
|
||||||
m_inverseModelMatrixValid = false;
|
|
||||||
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
KRNode *child = (*itr);
|
|
||||||
child->invalidateModelMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidateBounds();
|
|
||||||
getScene().notify_sceneGraphModify(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::invalidateBindPoseMatrix()
|
|
||||||
{
|
|
||||||
m_bindPoseMatrixValid = false;
|
|
||||||
m_inverseBindPoseMatrixValid = false;
|
|
||||||
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
KRNode *child = (*itr);
|
|
||||||
child->invalidateBindPoseMatrix();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Matrix4 &KRNode::getModelMatrix()
|
|
||||||
{
|
|
||||||
|
|
||||||
if(!m_modelMatrixValid) {
|
|
||||||
m_modelMatrix = Matrix4();
|
|
||||||
|
|
||||||
bool parent_is_bone = false;
|
|
||||||
if(dynamic_cast<KRBone *>(m_parentNode)) {
|
|
||||||
parent_is_bone = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(getScaleCompensation() && parent_is_bone) {
|
|
||||||
|
|
||||||
|
|
||||||
// WorldTransform = ParentWorldTransform * T * Roff * Rp * Rpre * R * Rpost * Rp-1 * Soff * Sp * S * Sp-1
|
|
||||||
m_modelMatrix = Matrix4::Translation(-m_scalingPivot)
|
|
||||||
* Matrix4::Scaling(m_localScale)
|
|
||||||
* Matrix4::Translation(m_scalingPivot)
|
|
||||||
* Matrix4::Translation(m_scalingOffset)
|
|
||||||
* Matrix4::Translation(-m_rotationPivot)
|
|
||||||
//* (Quaternion(m_postRotation) * Quaternion(m_localRotation) * Quaternion(m_preRotation)).rotationMatrix()
|
|
||||||
* Matrix4::Rotation(m_postRotation)
|
|
||||||
* Matrix4::Rotation(m_localRotation)
|
|
||||||
* Matrix4::Rotation(m_preRotation)
|
|
||||||
* Matrix4::Translation(m_rotationPivot)
|
|
||||||
* Matrix4::Translation(m_rotationOffset);
|
|
||||||
|
|
||||||
if(m_parentNode) {
|
|
||||||
|
|
||||||
m_modelMatrix.rotate(m_parentNode->getWorldRotation());
|
|
||||||
m_modelMatrix.translate(Matrix4::Dot(m_parentNode->getModelMatrix(), m_localTranslation));
|
|
||||||
} else {
|
|
||||||
m_modelMatrix.translate(m_localTranslation);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// WorldTransform = ParentWorldTransform * T * Roff * Rp * Rpre * R * Rpost * Rp-1 * Soff * Sp * S * Sp-1
|
|
||||||
m_modelMatrix = Matrix4::Translation(-m_scalingPivot)
|
|
||||||
* Matrix4::Scaling(m_localScale)
|
|
||||||
* Matrix4::Translation(m_scalingPivot)
|
|
||||||
* Matrix4::Translation(m_scalingOffset)
|
|
||||||
* Matrix4::Translation(-m_rotationPivot)
|
|
||||||
//* (Quaternion(m_postRotation) * Quaternion(m_localRotation) * Quaternion(m_preRotation)).rotationMatrix()
|
|
||||||
* Matrix4::Rotation(m_postRotation)
|
|
||||||
* Matrix4::Rotation(m_localRotation)
|
|
||||||
* Matrix4::Rotation(m_preRotation)
|
|
||||||
* Matrix4::Translation(m_rotationPivot)
|
|
||||||
* Matrix4::Translation(m_rotationOffset)
|
|
||||||
* Matrix4::Translation(m_localTranslation);
|
|
||||||
|
|
||||||
if(m_parentNode) {
|
|
||||||
m_modelMatrix *= m_parentNode->getModelMatrix();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_modelMatrixValid = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
return m_modelMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Matrix4 &KRNode::getBindPoseMatrix()
|
|
||||||
{
|
|
||||||
if(!m_bindPoseMatrixValid) {
|
|
||||||
m_bindPoseMatrix = Matrix4();
|
|
||||||
|
|
||||||
bool parent_is_bone = false;
|
|
||||||
if(dynamic_cast<KRBone *>(m_parentNode)) {
|
|
||||||
parent_is_bone = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(getScaleCompensation() && parent_is_bone) {
|
|
||||||
m_bindPoseMatrix = Matrix4::Translation(-m_initialScalingPivot)
|
|
||||||
* Matrix4::Scaling(m_initialLocalScale)
|
|
||||||
* Matrix4::Translation(m_initialScalingPivot)
|
|
||||||
* Matrix4::Translation(m_initialScalingOffset)
|
|
||||||
* Matrix4::Translation(-m_initialRotationPivot)
|
|
||||||
//* (Quaternion(m_initialPostRotation) * Quaternion(m_initialLocalRotation) * Quaternion(m_initialPreRotation)).rotationMatrix()
|
|
||||||
* Matrix4::Rotation(m_initialPostRotation)
|
|
||||||
* Matrix4::Rotation(m_initialLocalRotation)
|
|
||||||
* Matrix4::Rotation(m_initialPreRotation)
|
|
||||||
* Matrix4::Translation(m_initialRotationPivot)
|
|
||||||
* Matrix4::Translation(m_initialRotationOffset);
|
|
||||||
//m_bindPoseMatrix.translate(m_localTranslation);
|
|
||||||
if(m_parentNode) {
|
|
||||||
|
|
||||||
m_bindPoseMatrix.rotate(m_parentNode->getBindPoseWorldRotation());
|
|
||||||
m_bindPoseMatrix.translate(Matrix4::Dot(m_parentNode->getBindPoseMatrix(), m_localTranslation));
|
|
||||||
} else {
|
|
||||||
m_bindPoseMatrix.translate(m_localTranslation);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// WorldTransform = ParentWorldTransform * T * Roff * Rp * Rpre * R * Rpost * Rp-1 * Soff * Sp * S * Sp-1
|
|
||||||
|
|
||||||
m_bindPoseMatrix = Matrix4::Translation(-m_initialScalingPivot)
|
|
||||||
* Matrix4::Scaling(m_initialLocalScale)
|
|
||||||
* Matrix4::Translation(m_initialScalingPivot)
|
|
||||||
* Matrix4::Translation(m_initialScalingOffset)
|
|
||||||
* Matrix4::Translation(-m_initialRotationPivot)
|
|
||||||
// * (Quaternion(m_initialPostRotation) * Quaternion(m_initialLocalRotation) * Quaternion(m_initialPreRotation)).rotationMatrix()
|
|
||||||
* Matrix4::Rotation(m_initialPostRotation)
|
|
||||||
* Matrix4::Rotation(m_initialLocalRotation)
|
|
||||||
* Matrix4::Rotation(m_initialPreRotation)
|
|
||||||
* Matrix4::Translation(m_initialRotationPivot)
|
|
||||||
* Matrix4::Translation(m_initialRotationOffset)
|
|
||||||
* Matrix4::Translation(m_initialLocalTranslation);
|
|
||||||
|
|
||||||
if(m_parentNode && parent_is_bone) {
|
|
||||||
|
|
||||||
m_bindPoseMatrix *= m_parentNode->getBindPoseMatrix();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bindPoseMatrixValid = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
return m_bindPoseMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Matrix4 &KRNode::getActivePoseMatrix()
|
|
||||||
{
|
|
||||||
|
|
||||||
if(!m_activePoseMatrixValid) {
|
|
||||||
m_activePoseMatrix = Matrix4();
|
|
||||||
|
|
||||||
bool parent_is_bone = false;
|
|
||||||
if(dynamic_cast<KRBone *>(m_parentNode)) {
|
|
||||||
parent_is_bone = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(getScaleCompensation() && parent_is_bone) {
|
|
||||||
m_activePoseMatrix= Matrix4::Translation(-m_scalingPivot)
|
|
||||||
* Matrix4::Scaling(m_localScale)
|
|
||||||
* Matrix4::Translation(m_scalingPivot)
|
|
||||||
* Matrix4::Translation(m_scalingOffset)
|
|
||||||
* Matrix4::Translation(-m_rotationPivot)
|
|
||||||
* Matrix4::Rotation(m_postRotation)
|
|
||||||
* Matrix4::Rotation(m_localRotation)
|
|
||||||
* Matrix4::Rotation(m_preRotation)
|
|
||||||
* Matrix4::Translation(m_rotationPivot)
|
|
||||||
* Matrix4::Translation(m_rotationOffset);
|
|
||||||
|
|
||||||
if(m_parentNode) {
|
|
||||||
|
|
||||||
m_activePoseMatrix.rotate(m_parentNode->getActivePoseWorldRotation());
|
|
||||||
m_activePoseMatrix.translate(Matrix4::Dot(m_parentNode->getActivePoseMatrix(), m_localTranslation));
|
|
||||||
} else {
|
|
||||||
m_activePoseMatrix.translate(m_localTranslation);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// WorldTransform = ParentWorldTransform * T * Roff * Rp * Rpre * R * Rpost * Rp-1 * Soff * Sp * S * Sp-1
|
|
||||||
m_activePoseMatrix = Matrix4::Translation(-m_scalingPivot)
|
|
||||||
* Matrix4::Scaling(m_localScale)
|
|
||||||
* Matrix4::Translation(m_scalingPivot)
|
|
||||||
* Matrix4::Translation(m_scalingOffset)
|
|
||||||
* Matrix4::Translation(-m_rotationPivot)
|
|
||||||
* Matrix4::Rotation(m_postRotation)
|
|
||||||
* Matrix4::Rotation(m_localRotation)
|
|
||||||
* Matrix4::Rotation(m_preRotation)
|
|
||||||
* Matrix4::Translation(m_rotationPivot)
|
|
||||||
* Matrix4::Translation(m_rotationOffset)
|
|
||||||
* Matrix4::Translation(m_localTranslation);
|
|
||||||
|
|
||||||
|
|
||||||
if(m_parentNode && parent_is_bone) {
|
|
||||||
m_activePoseMatrix *= m_parentNode->getActivePoseMatrix();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_activePoseMatrixValid = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
return m_activePoseMatrix;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const Quaternion KRNode::getWorldRotation() {
|
|
||||||
Quaternion world_rotation = Quaternion(m_postRotation) * Quaternion(m_localRotation) * Quaternion(m_preRotation);
|
|
||||||
if(m_parentNode) {
|
|
||||||
world_rotation = world_rotation * m_parentNode->getWorldRotation();
|
|
||||||
}
|
|
||||||
return world_rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Quaternion KRNode::getBindPoseWorldRotation() {
|
|
||||||
Quaternion world_rotation = Quaternion(m_initialPostRotation) * Quaternion(m_initialLocalRotation) * Quaternion(m_initialPreRotation);
|
|
||||||
if(dynamic_cast<KRBone *>(m_parentNode)) {
|
|
||||||
world_rotation = world_rotation * m_parentNode->getBindPoseWorldRotation();
|
|
||||||
}
|
|
||||||
return world_rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Quaternion KRNode::getActivePoseWorldRotation() {
|
|
||||||
Quaternion world_rotation = Quaternion(m_postRotation) * Quaternion(m_localRotation) * Quaternion(m_preRotation);
|
|
||||||
if(dynamic_cast<KRBone *>(m_parentNode)) {
|
|
||||||
world_rotation = world_rotation * m_parentNode->getActivePoseWorldRotation();
|
|
||||||
}
|
|
||||||
return world_rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Matrix4 &KRNode::getInverseModelMatrix()
|
|
||||||
{
|
|
||||||
if(!m_inverseModelMatrixValid) {
|
|
||||||
m_inverseModelMatrix = Matrix4::Invert(getModelMatrix());
|
|
||||||
}
|
|
||||||
return m_inverseModelMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Matrix4 &KRNode::getInverseBindPoseMatrix()
|
|
||||||
{
|
|
||||||
if(!m_inverseBindPoseMatrixValid ) {
|
|
||||||
m_inverseBindPoseMatrix = Matrix4::Invert(getBindPoseMatrix());
|
|
||||||
m_inverseBindPoseMatrixValid = true;
|
|
||||||
}
|
|
||||||
return m_inverseBindPoseMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::physicsUpdate(float deltaTime)
|
|
||||||
{
|
|
||||||
const long MIN_DISPLAY_FRAMES = 10;
|
|
||||||
bool visible = m_lastRenderFrame + MIN_DISPLAY_FRAMES >= getContext().getCurrentFrame();
|
|
||||||
for(std::set<KRBehavior *>::iterator itr=m_behaviors.begin(); itr != m_behaviors.end(); itr++) {
|
|
||||||
(*itr)->update(deltaTime);
|
|
||||||
if(visible) {
|
|
||||||
(*itr)->visibleUpdate(deltaTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KRNode::hasPhysics()
|
|
||||||
{
|
|
||||||
return m_behaviors.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::SetAttribute(node_attribute_type attrib, float v)
|
|
||||||
{
|
|
||||||
if(m_animation_mask[attrib]) return;
|
|
||||||
|
|
||||||
const float DEGREES_TO_RAD = M_PI / 180.0f;
|
|
||||||
|
|
||||||
//printf("%s - ", m_name.c_str());
|
|
||||||
switch(attrib) {
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X:
|
|
||||||
setLocalTranslation(Vector3(v, m_localTranslation.y, m_localTranslation.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y:
|
|
||||||
setLocalTranslation(Vector3(m_localTranslation.x, v, m_localTranslation.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z:
|
|
||||||
setLocalTranslation(Vector3(m_localTranslation.x, m_localTranslation.y, v));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_X:
|
|
||||||
setLocalScale(Vector3(v, m_localScale.y, m_localScale.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_Y:
|
|
||||||
setLocalScale(Vector3(m_localScale.x, v, m_localScale.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_Z:
|
|
||||||
setLocalScale(Vector3(m_localScale.x, m_localScale.y, v));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_X:
|
|
||||||
setLocalRotation(Vector3(v * DEGREES_TO_RAD, m_localRotation.y, m_localRotation.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_Y:
|
|
||||||
setLocalRotation(Vector3(m_localRotation.x, v * DEGREES_TO_RAD, m_localRotation.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_Z:
|
|
||||||
setLocalRotation(Vector3(m_localRotation.x, m_localRotation.y, v * DEGREES_TO_RAD));
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X:
|
|
||||||
setPreRotation(Vector3(v * DEGREES_TO_RAD, m_preRotation.y, m_preRotation.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y:
|
|
||||||
setPreRotation(Vector3(m_preRotation.x, v * DEGREES_TO_RAD, m_preRotation.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z:
|
|
||||||
setPreRotation(Vector3(m_preRotation.x, m_preRotation.y, v * DEGREES_TO_RAD));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X:
|
|
||||||
setPostRotation(Vector3(v * DEGREES_TO_RAD, m_postRotation.y, m_postRotation.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y:
|
|
||||||
setPostRotation(Vector3(m_postRotation.x, v * DEGREES_TO_RAD, m_postRotation.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z:
|
|
||||||
setPostRotation(Vector3(m_postRotation.x, m_postRotation.y, v * DEGREES_TO_RAD));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X:
|
|
||||||
setRotationPivot(Vector3(v, m_rotationPivot.y, m_rotationPivot.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y:
|
|
||||||
setRotationPivot(Vector3(m_rotationPivot.x, v, m_rotationPivot.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z:
|
|
||||||
setRotationPivot(Vector3(m_rotationPivot.x, m_rotationPivot.y, v));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X:
|
|
||||||
setScalingPivot(Vector3(v, m_scalingPivot.y, m_scalingPivot.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y:
|
|
||||||
setScalingPivot(Vector3(m_scalingPivot.x, v, m_scalingPivot.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z:
|
|
||||||
setScalingPivot(Vector3(m_scalingPivot.x, m_scalingPivot.y, v));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X:
|
|
||||||
setRotationOffset(Vector3(v, m_rotationOffset.y, m_rotationOffset.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y:
|
|
||||||
setRotationOffset(Vector3(m_rotationOffset.x, v, m_rotationOffset.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z:
|
|
||||||
setRotationOffset(Vector3(m_rotationOffset.x, m_rotationOffset.y, v));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_SCALE_OFFSET_X:
|
|
||||||
setScalingOffset(Vector3(v, m_scalingOffset.y, m_scalingOffset.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_SCALE_OFFSET_Y:
|
|
||||||
setScalingOffset(Vector3(m_scalingOffset.x, v, m_scalingOffset.z));
|
|
||||||
break;
|
|
||||||
case KRENGINE_NODE_SCALE_OFFSET_Z:
|
|
||||||
setScalingOffset(Vector3(m_scalingOffset.x, m_scalingOffset.y, v));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::setAnimationEnabled(node_attribute_type attrib, bool enable)
|
|
||||||
{
|
|
||||||
m_animation_mask[attrib] = !enable;
|
|
||||||
}
|
|
||||||
bool KRNode::getAnimationEnabled(node_attribute_type attrib) const
|
|
||||||
{
|
|
||||||
return !m_animation_mask[attrib];
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::removeFromOctreeNodes()
|
|
||||||
{
|
|
||||||
for(std::set<KROctreeNode *>::iterator itr=m_octree_nodes.begin(); itr != m_octree_nodes.end(); itr++) {
|
|
||||||
KROctreeNode *octree_node = *itr;
|
|
||||||
octree_node->remove(this);
|
|
||||||
|
|
||||||
// FINDME, TODO - This should be moved to the KROctree class
|
|
||||||
while(octree_node) {
|
|
||||||
octree_node->trim();
|
|
||||||
if(octree_node->isEmpty()) {
|
|
||||||
octree_node = octree_node->getParent();
|
|
||||||
} else {
|
|
||||||
octree_node = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_octree_nodes.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::addToOctreeNode(KROctreeNode *octree_node)
|
|
||||||
{
|
|
||||||
m_octree_nodes.insert(octree_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::updateLODVisibility(const KRViewport &viewport)
|
|
||||||
{
|
|
||||||
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM) {
|
|
||||||
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
(*itr)->updateLODVisibility(viewport);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::setLODVisibility(KRNode::LodVisibility lod_visibility)
|
|
||||||
{
|
|
||||||
if(m_lod_visible != lod_visibility) {
|
|
||||||
if(m_lod_visible == LOD_VISIBILITY_HIDDEN && lod_visibility >= LOD_VISIBILITY_PRESTREAM) {
|
|
||||||
getScene().notify_sceneGraphCreate(this);
|
|
||||||
} else if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && lod_visibility == LOD_VISIBILITY_HIDDEN) {
|
|
||||||
getScene().notify_sceneGraphDelete(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lod_visible = lod_visibility;
|
|
||||||
|
|
||||||
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
(*itr)->setLODVisibility(lod_visibility);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KRNode::LodVisibility KRNode::getLODVisibility()
|
|
||||||
{
|
|
||||||
return m_lod_visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3 KRNode::localToWorld(const Vector3 &local_point)
|
|
||||||
{
|
|
||||||
return Matrix4::Dot(getModelMatrix(), local_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3 KRNode::worldToLocal(const Vector3 &world_point)
|
|
||||||
{
|
|
||||||
return Matrix4::Dot(getInverseModelMatrix(), world_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::addBehavior(KRBehavior *behavior)
|
|
||||||
{
|
|
||||||
m_behaviors.insert(behavior);
|
|
||||||
behavior->__setNode(this);
|
|
||||||
getScene().notify_sceneGraphModify(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<KRBehavior *> &KRNode::getBehaviors()
|
|
||||||
{
|
|
||||||
return m_behaviors;
|
|
||||||
}
|
|
||||||
|
|
||||||
kraken_stream_level KRNode::getStreamLevel(const KRViewport &viewport)
|
|
||||||
{
|
|
||||||
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
|
|
||||||
|
|
||||||
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel(viewport));
|
|
||||||
}
|
|
||||||
|
|
||||||
return stream_level;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KRNode::invalidateBounds() const
|
|
||||||
{
|
|
||||||
m_boundsValid = false;
|
|
||||||
if(m_parentNode) {
|
|
||||||
m_parentNode->invalidateBounds();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
302
kraken/KRNode.h
302
kraken/KRNode.h
@@ -1,302 +0,0 @@
|
|||||||
//
|
|
||||||
// KRNode.h
|
|
||||||
// KREngine
|
|
||||||
//
|
|
||||||
// Created by Kearwood Gilbert on 12-04-11.
|
|
||||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef KRNODE_H
|
|
||||||
#define KRNODE_H
|
|
||||||
|
|
||||||
#include "KRResource.h"
|
|
||||||
#include "KRViewport.h"
|
|
||||||
#include "KROctreeNode.h"
|
|
||||||
#include "KRBehavior.h"
|
|
||||||
|
|
||||||
using namespace kraken;
|
|
||||||
|
|
||||||
namespace kraken {
|
|
||||||
class Matrix4;
|
|
||||||
class AABB;
|
|
||||||
} // namespace kraken
|
|
||||||
class KRCamera;
|
|
||||||
class KRShaderManager;
|
|
||||||
class KRMeshManager;
|
|
||||||
class KRMaterialManager;
|
|
||||||
class KRTextureManager;
|
|
||||||
class KRContext;
|
|
||||||
class KRScene;
|
|
||||||
|
|
||||||
class KRNode;
|
|
||||||
class KRPointLight;
|
|
||||||
class KRSpotLight;
|
|
||||||
class KRDirectionalLight;
|
|
||||||
namespace tinyxml2 {
|
|
||||||
class XMLNode;
|
|
||||||
class XMLAttribute;
|
|
||||||
}
|
|
||||||
|
|
||||||
class KRNode : public KRContextObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum RenderPass {
|
|
||||||
RENDER_PASS_FORWARD_OPAQUE,
|
|
||||||
RENDER_PASS_DEFERRED_GBUFFER,
|
|
||||||
RENDER_PASS_DEFERRED_LIGHTS,
|
|
||||||
RENDER_PASS_DEFERRED_OPAQUE,
|
|
||||||
RENDER_PASS_FORWARD_TRANSPARENT,
|
|
||||||
RENDER_PASS_PARTICLE_OCCLUSION,
|
|
||||||
RENDER_PASS_ADDITIVE_PARTICLES,
|
|
||||||
RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE,
|
|
||||||
RENDER_PASS_GENERATE_SHADOWMAPS,
|
|
||||||
RENDER_PASS_SHADOWMAP,
|
|
||||||
RENDER_PASS_PRESTREAM
|
|
||||||
};
|
|
||||||
|
|
||||||
enum LodVisibility {
|
|
||||||
LOD_VISIBILITY_HIDDEN,
|
|
||||||
LOD_VISIBILITY_PRESTREAM,
|
|
||||||
LOD_VISIBILITY_VISIBLE
|
|
||||||
};
|
|
||||||
|
|
||||||
KRNode(KRScene &scene, std::string name);
|
|
||||||
virtual ~KRNode();
|
|
||||||
|
|
||||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
|
||||||
static KRNode *LoadXML(KRScene &scene, tinyxml2::XMLElement *e);
|
|
||||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
|
||||||
|
|
||||||
virtual std::string getElementName();
|
|
||||||
const std::string &getName() const;
|
|
||||||
|
|
||||||
void addChild(KRNode *child);
|
|
||||||
const std::set<KRNode *> &getChildren();
|
|
||||||
KRNode *getParent();
|
|
||||||
|
|
||||||
void setLocalTranslation(const Vector3 &v, bool set_original = false);
|
|
||||||
void setLocalScale(const Vector3 &v, bool set_original = false);
|
|
||||||
void setLocalRotation(const Vector3 &v, bool set_original = false);
|
|
||||||
|
|
||||||
|
|
||||||
void setRotationOffset(const Vector3 &v, bool set_original = false);
|
|
||||||
void setScalingOffset(const Vector3 &v, bool set_original = false);
|
|
||||||
void setRotationPivot(const Vector3 &v, bool set_original = false);
|
|
||||||
void setScalingPivot(const Vector3 &v, bool set_original = false);
|
|
||||||
void setPreRotation(const Vector3 &v, bool set_original = false);
|
|
||||||
void setPostRotation(const Vector3 &v, bool set_original = false);
|
|
||||||
|
|
||||||
const Vector3 &getRotationOffset();
|
|
||||||
const Vector3 &getScalingOffset();
|
|
||||||
const Vector3 &getRotationPivot();
|
|
||||||
const Vector3 &getScalingPivot();
|
|
||||||
const Vector3 &getPreRotation();
|
|
||||||
const Vector3 &getPostRotation();
|
|
||||||
|
|
||||||
const Vector3 &getInitialRotationOffset();
|
|
||||||
const Vector3 &getInitialScalingOffset();
|
|
||||||
const Vector3 &getInitialRotationPivot();
|
|
||||||
const Vector3 &getInitialScalingPivot();
|
|
||||||
const Vector3 &getInitialPreRotation();
|
|
||||||
const Vector3 &getInitialPostRotation();
|
|
||||||
|
|
||||||
|
|
||||||
const Vector3 &getLocalTranslation();
|
|
||||||
const Vector3 &getLocalScale();
|
|
||||||
const Vector3 &getLocalRotation();
|
|
||||||
|
|
||||||
const Vector3 &getInitialLocalTranslation();
|
|
||||||
const Vector3 &getInitialLocalScale();
|
|
||||||
const Vector3 &getInitialLocalRotation();
|
|
||||||
|
|
||||||
const Vector3 getWorldTranslation();
|
|
||||||
const Vector3 getWorldScale();
|
|
||||||
const Quaternion getWorldRotation();
|
|
||||||
|
|
||||||
const Quaternion getBindPoseWorldRotation();
|
|
||||||
const Quaternion getActivePoseWorldRotation();
|
|
||||||
|
|
||||||
const Vector3 localToWorld(const Vector3 &local_point);
|
|
||||||
const Vector3 worldToLocal(const Vector3 &world_point);
|
|
||||||
|
|
||||||
void setWorldTranslation(const Vector3 &v);
|
|
||||||
void setWorldScale(const Vector3 &v);
|
|
||||||
void setWorldRotation(const Vector3 &v);
|
|
||||||
|
|
||||||
virtual AABB getBounds();
|
|
||||||
void invalidateBounds() const;
|
|
||||||
const Matrix4 &getModelMatrix();
|
|
||||||
const Matrix4 &getInverseModelMatrix();
|
|
||||||
const Matrix4 &getBindPoseMatrix();
|
|
||||||
const Matrix4 &getActivePoseMatrix();
|
|
||||||
const Matrix4 &getInverseBindPoseMatrix();
|
|
||||||
|
|
||||||
enum node_attribute_type {
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_NONE,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_SCALE_X,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_SCALE_Y,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_SCALE_Z,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_ROTATE_X,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_ROTATE_Y,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_ROTATE_Z,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z,
|
|
||||||
KRENGINE_NODE_SCALE_OFFSET_X,
|
|
||||||
KRENGINE_NODE_SCALE_OFFSET_Y,
|
|
||||||
KRENGINE_NODE_SCALE_OFFSET_Z,
|
|
||||||
KRENGINE_NODE_ATTRIBUTE_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
void SetAttribute(node_attribute_type attrib, float v);
|
|
||||||
|
|
||||||
KRScene &getScene();
|
|
||||||
|
|
||||||
virtual void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, RenderPass renderPass);
|
|
||||||
|
|
||||||
virtual void physicsUpdate(float deltaTime);
|
|
||||||
virtual bool hasPhysics();
|
|
||||||
|
|
||||||
virtual void updateLODVisibility(const KRViewport &viewport);
|
|
||||||
LodVisibility getLODVisibility();
|
|
||||||
|
|
||||||
void setScaleCompensation(bool scale_compensation);
|
|
||||||
bool getScaleCompensation();
|
|
||||||
void setAnimationEnabled(node_attribute_type attrib, bool enable);
|
|
||||||
bool getAnimationEnabled(node_attribute_type attrib) const;
|
|
||||||
|
|
||||||
|
|
||||||
virtual kraken_stream_level getStreamLevel(const KRViewport &viewport);
|
|
||||||
|
|
||||||
virtual void setLODVisibility(LodVisibility lod_visibility);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Vector3 m_localTranslation;
|
|
||||||
Vector3 m_localScale;
|
|
||||||
Vector3 m_localRotation;
|
|
||||||
|
|
||||||
Vector3 m_rotationOffset;
|
|
||||||
Vector3 m_scalingOffset;
|
|
||||||
Vector3 m_rotationPivot;
|
|
||||||
Vector3 m_scalingPivot;
|
|
||||||
Vector3 m_preRotation;
|
|
||||||
Vector3 m_postRotation;
|
|
||||||
|
|
||||||
Vector3 m_initialLocalTranslation;
|
|
||||||
Vector3 m_initialLocalScale;
|
|
||||||
Vector3 m_initialLocalRotation;
|
|
||||||
|
|
||||||
Vector3 m_initialRotationOffset;
|
|
||||||
Vector3 m_initialScalingOffset;
|
|
||||||
Vector3 m_initialRotationPivot;
|
|
||||||
Vector3 m_initialScalingPivot;
|
|
||||||
Vector3 m_initialPreRotation;
|
|
||||||
Vector3 m_initialPostRotation;
|
|
||||||
|
|
||||||
LodVisibility m_lod_visible;
|
|
||||||
|
|
||||||
KRNode *m_parentNode;
|
|
||||||
std::set<KRNode *> m_childNodes;
|
|
||||||
|
|
||||||
bool m_animation_mask[KRENGINE_NODE_ATTRIBUTE_COUNT];
|
|
||||||
|
|
||||||
private:
|
|
||||||
long m_lastRenderFrame;
|
|
||||||
void invalidateModelMatrix();
|
|
||||||
void invalidateBindPoseMatrix();
|
|
||||||
Matrix4 m_modelMatrix;
|
|
||||||
Matrix4 m_inverseModelMatrix;
|
|
||||||
Matrix4 m_bindPoseMatrix;
|
|
||||||
Matrix4 m_activePoseMatrix;
|
|
||||||
Matrix4 m_inverseBindPoseMatrix;
|
|
||||||
bool m_modelMatrixValid;
|
|
||||||
bool m_inverseModelMatrixValid;
|
|
||||||
bool m_bindPoseMatrixValid;
|
|
||||||
bool m_activePoseMatrixValid;
|
|
||||||
bool m_inverseBindPoseMatrixValid;
|
|
||||||
|
|
||||||
mutable AABB m_bounds;
|
|
||||||
mutable bool m_boundsValid;
|
|
||||||
|
|
||||||
std::string m_name;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KRScene *m_pScene;
|
|
||||||
|
|
||||||
std::set<KROctreeNode *> m_octree_nodes;
|
|
||||||
bool m_scale_compensation;
|
|
||||||
|
|
||||||
std::set<KRBehavior *> m_behaviors;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void addBehavior(KRBehavior *behavior);
|
|
||||||
std::set<KRBehavior *> &getBehaviors();
|
|
||||||
template <class T> T *getBehavior()
|
|
||||||
{
|
|
||||||
for(std::set<KRBehavior *>::iterator itr=m_behaviors.begin(); itr != m_behaviors.end(); itr++) {
|
|
||||||
T *behavior = dynamic_cast<T *>(*itr);
|
|
||||||
if(behavior) {
|
|
||||||
return behavior;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
void removeFromOctreeNodes();
|
|
||||||
void addToOctreeNode(KROctreeNode *octree_node);
|
|
||||||
void childDeleted(KRNode *child_node);
|
|
||||||
|
|
||||||
template <class T> T *find()
|
|
||||||
{
|
|
||||||
T *match = dynamic_cast<T *>(this);
|
|
||||||
if(match) {
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(std::set<KRNode *>::const_iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
match = (*itr)->find<T>();
|
|
||||||
if(match) {
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> T *find(const std::string &name)
|
|
||||||
{
|
|
||||||
T *match = dynamic_cast<T *>(this);
|
|
||||||
if(match) {
|
|
||||||
if(name.compare(match->getName()) == 0) {
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(std::set<KRNode *>::const_iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
|
|
||||||
match = (*itr)->find<T>(name);
|
|
||||||
if(match) {
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user