WebGPU Voxel Game
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Tutorial 9: Model Loading This one was quite big! I added a wireframe mode too on desktop.

+1360 -126
+923 -3
Cargo.lock
··· 19 19 checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" 20 20 21 21 [[package]] 22 + name = "addr2line" 23 + version = "0.24.2" 24 + source = "registry+https://github.com/rust-lang/crates.io-index" 25 + checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 26 + dependencies = [ 27 + "gimli", 28 + ] 29 + 30 + [[package]] 22 31 name = "adler2" 23 32 version = "2.0.0" 24 33 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 128 137 checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 129 138 130 139 [[package]] 140 + name = "backtrace" 141 + version = "0.3.74" 142 + source = "registry+https://github.com/rust-lang/crates.io-index" 143 + checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 144 + dependencies = [ 145 + "addr2line", 146 + "cfg-if", 147 + "libc", 148 + "miniz_oxide", 149 + "object", 150 + "rustc-demangle", 151 + "windows-targets 0.52.6", 152 + ] 153 + 154 + [[package]] 155 + name = "base64" 156 + version = "0.21.7" 157 + source = "registry+https://github.com/rust-lang/crates.io-index" 158 + checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 159 + 160 + [[package]] 131 161 name = "bit-set" 132 162 version = "0.6.0" 133 163 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 164 194 "console_log", 165 195 "env_logger", 166 196 "fs_extra", 197 + "futures", 167 198 "glam", 168 199 "glob", 169 200 "image", 201 + "itertools", 170 202 "log", 171 203 "pollster", 204 + "reqwest", 172 205 "thiserror 2.0.11", 206 + "tobj", 173 207 "wasm-bindgen", 174 208 "wasm-bindgen-futures", 175 209 "web-sys", ··· 400 434 "bitflags 1.3.2", 401 435 "core-foundation", 402 436 "core-graphics-types", 403 - "foreign-types", 437 + "foreign-types 0.5.0", 404 438 "libc", 405 439 ] 406 440 ··· 454 488 checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" 455 489 456 490 [[package]] 491 + name = "displaydoc" 492 + version = "0.2.5" 493 + source = "registry+https://github.com/rust-lang/crates.io-index" 494 + checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 495 + dependencies = [ 496 + "proc-macro2", 497 + "quote", 498 + "syn 2.0.96", 499 + ] 500 + 501 + [[package]] 457 502 name = "dlib" 458 503 version = "0.5.2" 459 504 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 478 523 checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" 479 524 480 525 [[package]] 526 + name = "either" 527 + version = "1.13.0" 528 + source = "registry+https://github.com/rust-lang/crates.io-index" 529 + checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 530 + 531 + [[package]] 532 + name = "encoding_rs" 533 + version = "0.8.35" 534 + source = "registry+https://github.com/rust-lang/crates.io-index" 535 + checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 536 + dependencies = [ 537 + "cfg-if", 538 + ] 539 + 540 + [[package]] 481 541 name = "env_logger" 482 542 version = "0.10.2" 483 543 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 507 567 ] 508 568 509 569 [[package]] 570 + name = "fastrand" 571 + version = "2.3.0" 572 + source = "registry+https://github.com/rust-lang/crates.io-index" 573 + checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 574 + 575 + [[package]] 510 576 name = "fdeflate" 511 577 version = "0.3.7" 512 578 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 526 592 ] 527 593 528 594 [[package]] 595 + name = "fnv" 596 + version = "1.0.7" 597 + source = "registry+https://github.com/rust-lang/crates.io-index" 598 + checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 599 + 600 + [[package]] 601 + name = "foreign-types" 602 + version = "0.3.2" 603 + source = "registry+https://github.com/rust-lang/crates.io-index" 604 + checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 605 + dependencies = [ 606 + "foreign-types-shared 0.1.1", 607 + ] 608 + 609 + [[package]] 529 610 name = "foreign-types" 530 611 version = "0.5.0" 531 612 source = "registry+https://github.com/rust-lang/crates.io-index" 532 613 checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" 533 614 dependencies = [ 534 615 "foreign-types-macros", 535 - "foreign-types-shared", 616 + "foreign-types-shared 0.3.1", 536 617 ] 537 618 538 619 [[package]] ··· 548 629 549 630 [[package]] 550 631 name = "foreign-types-shared" 632 + version = "0.1.1" 633 + source = "registry+https://github.com/rust-lang/crates.io-index" 634 + checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 635 + 636 + [[package]] 637 + name = "foreign-types-shared" 551 638 version = "0.3.1" 552 639 source = "registry+https://github.com/rust-lang/crates.io-index" 553 640 checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" 554 641 555 642 [[package]] 643 + name = "form_urlencoded" 644 + version = "1.2.1" 645 + source = "registry+https://github.com/rust-lang/crates.io-index" 646 + checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 647 + dependencies = [ 648 + "percent-encoding", 649 + ] 650 + 651 + [[package]] 556 652 name = "fs_extra" 557 653 version = "1.3.0" 558 654 source = "registry+https://github.com/rust-lang/crates.io-index" 559 655 checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" 560 656 561 657 [[package]] 658 + name = "futures" 659 + version = "0.3.31" 660 + source = "registry+https://github.com/rust-lang/crates.io-index" 661 + checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 662 + dependencies = [ 663 + "futures-channel", 664 + "futures-core", 665 + "futures-executor", 666 + "futures-io", 667 + "futures-sink", 668 + "futures-task", 669 + "futures-util", 670 + ] 671 + 672 + [[package]] 673 + name = "futures-channel" 674 + version = "0.3.31" 675 + source = "registry+https://github.com/rust-lang/crates.io-index" 676 + checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 677 + dependencies = [ 678 + "futures-core", 679 + "futures-sink", 680 + ] 681 + 682 + [[package]] 683 + name = "futures-core" 684 + version = "0.3.31" 685 + source = "registry+https://github.com/rust-lang/crates.io-index" 686 + checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 687 + 688 + [[package]] 689 + name = "futures-executor" 690 + version = "0.3.31" 691 + source = "registry+https://github.com/rust-lang/crates.io-index" 692 + checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 693 + dependencies = [ 694 + "futures-core", 695 + "futures-task", 696 + "futures-util", 697 + ] 698 + 699 + [[package]] 700 + name = "futures-io" 701 + version = "0.3.31" 702 + source = "registry+https://github.com/rust-lang/crates.io-index" 703 + checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 704 + 705 + [[package]] 706 + name = "futures-macro" 707 + version = "0.3.31" 708 + source = "registry+https://github.com/rust-lang/crates.io-index" 709 + checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 710 + dependencies = [ 711 + "proc-macro2", 712 + "quote", 713 + "syn 2.0.96", 714 + ] 715 + 716 + [[package]] 717 + name = "futures-sink" 718 + version = "0.3.31" 719 + source = "registry+https://github.com/rust-lang/crates.io-index" 720 + checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 721 + 722 + [[package]] 723 + name = "futures-task" 724 + version = "0.3.31" 725 + source = "registry+https://github.com/rust-lang/crates.io-index" 726 + checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 727 + 728 + [[package]] 729 + name = "futures-util" 730 + version = "0.3.31" 731 + source = "registry+https://github.com/rust-lang/crates.io-index" 732 + checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 733 + dependencies = [ 734 + "futures-channel", 735 + "futures-core", 736 + "futures-io", 737 + "futures-macro", 738 + "futures-sink", 739 + "futures-task", 740 + "memchr", 741 + "pin-project-lite", 742 + "pin-utils", 743 + "slab", 744 + ] 745 + 746 + [[package]] 562 747 name = "gethostname" 563 748 version = "0.4.3" 564 749 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 578 763 "libc", 579 764 "wasi", 580 765 ] 766 + 767 + [[package]] 768 + name = "gimli" 769 + version = "0.31.1" 770 + source = "registry+https://github.com/rust-lang/crates.io-index" 771 + checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 581 772 582 773 [[package]] 583 774 name = "gl_generator" ··· 679 870 ] 680 871 681 872 [[package]] 873 + name = "h2" 874 + version = "0.3.26" 875 + source = "registry+https://github.com/rust-lang/crates.io-index" 876 + checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" 877 + dependencies = [ 878 + "bytes", 879 + "fnv", 880 + "futures-core", 881 + "futures-sink", 882 + "futures-util", 883 + "http", 884 + "indexmap", 885 + "slab", 886 + "tokio", 887 + "tokio-util", 888 + "tracing", 889 + ] 890 + 891 + [[package]] 682 892 name = "hashbrown" 683 893 version = "0.14.5" 684 894 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 716 926 checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" 717 927 718 928 [[package]] 929 + name = "http" 930 + version = "0.2.12" 931 + source = "registry+https://github.com/rust-lang/crates.io-index" 932 + checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" 933 + dependencies = [ 934 + "bytes", 935 + "fnv", 936 + "itoa", 937 + ] 938 + 939 + [[package]] 940 + name = "http-body" 941 + version = "0.4.6" 942 + source = "registry+https://github.com/rust-lang/crates.io-index" 943 + checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" 944 + dependencies = [ 945 + "bytes", 946 + "http", 947 + "pin-project-lite", 948 + ] 949 + 950 + [[package]] 951 + name = "httparse" 952 + version = "1.10.0" 953 + source = "registry+https://github.com/rust-lang/crates.io-index" 954 + checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" 955 + 956 + [[package]] 957 + name = "httpdate" 958 + version = "1.0.3" 959 + source = "registry+https://github.com/rust-lang/crates.io-index" 960 + checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 961 + 962 + [[package]] 719 963 name = "humantime" 720 964 version = "2.1.0" 721 965 source = "registry+https://github.com/rust-lang/crates.io-index" 722 966 checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 723 967 724 968 [[package]] 969 + name = "hyper" 970 + version = "0.14.32" 971 + source = "registry+https://github.com/rust-lang/crates.io-index" 972 + checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" 973 + dependencies = [ 974 + "bytes", 975 + "futures-channel", 976 + "futures-core", 977 + "futures-util", 978 + "h2", 979 + "http", 980 + "http-body", 981 + "httparse", 982 + "httpdate", 983 + "itoa", 984 + "pin-project-lite", 985 + "socket2", 986 + "tokio", 987 + "tower-service", 988 + "tracing", 989 + "want", 990 + ] 991 + 992 + [[package]] 993 + name = "hyper-tls" 994 + version = "0.5.0" 995 + source = "registry+https://github.com/rust-lang/crates.io-index" 996 + checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 997 + dependencies = [ 998 + "bytes", 999 + "hyper", 1000 + "native-tls", 1001 + "tokio", 1002 + "tokio-native-tls", 1003 + ] 1004 + 1005 + [[package]] 725 1006 name = "icrate" 726 1007 version = "0.0.4" 727 1008 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 733 1014 ] 734 1015 735 1016 [[package]] 1017 + name = "icu_collections" 1018 + version = "1.5.0" 1019 + source = "registry+https://github.com/rust-lang/crates.io-index" 1020 + checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 1021 + dependencies = [ 1022 + "displaydoc", 1023 + "yoke", 1024 + "zerofrom", 1025 + "zerovec", 1026 + ] 1027 + 1028 + [[package]] 1029 + name = "icu_locid" 1030 + version = "1.5.0" 1031 + source = "registry+https://github.com/rust-lang/crates.io-index" 1032 + checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 1033 + dependencies = [ 1034 + "displaydoc", 1035 + "litemap", 1036 + "tinystr", 1037 + "writeable", 1038 + "zerovec", 1039 + ] 1040 + 1041 + [[package]] 1042 + name = "icu_locid_transform" 1043 + version = "1.5.0" 1044 + source = "registry+https://github.com/rust-lang/crates.io-index" 1045 + checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 1046 + dependencies = [ 1047 + "displaydoc", 1048 + "icu_locid", 1049 + "icu_locid_transform_data", 1050 + "icu_provider", 1051 + "tinystr", 1052 + "zerovec", 1053 + ] 1054 + 1055 + [[package]] 1056 + name = "icu_locid_transform_data" 1057 + version = "1.5.0" 1058 + source = "registry+https://github.com/rust-lang/crates.io-index" 1059 + checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" 1060 + 1061 + [[package]] 1062 + name = "icu_normalizer" 1063 + version = "1.5.0" 1064 + source = "registry+https://github.com/rust-lang/crates.io-index" 1065 + checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 1066 + dependencies = [ 1067 + "displaydoc", 1068 + "icu_collections", 1069 + "icu_normalizer_data", 1070 + "icu_properties", 1071 + "icu_provider", 1072 + "smallvec", 1073 + "utf16_iter", 1074 + "utf8_iter", 1075 + "write16", 1076 + "zerovec", 1077 + ] 1078 + 1079 + [[package]] 1080 + name = "icu_normalizer_data" 1081 + version = "1.5.0" 1082 + source = "registry+https://github.com/rust-lang/crates.io-index" 1083 + checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" 1084 + 1085 + [[package]] 1086 + name = "icu_properties" 1087 + version = "1.5.1" 1088 + source = "registry+https://github.com/rust-lang/crates.io-index" 1089 + checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 1090 + dependencies = [ 1091 + "displaydoc", 1092 + "icu_collections", 1093 + "icu_locid_transform", 1094 + "icu_properties_data", 1095 + "icu_provider", 1096 + "tinystr", 1097 + "zerovec", 1098 + ] 1099 + 1100 + [[package]] 1101 + name = "icu_properties_data" 1102 + version = "1.5.0" 1103 + source = "registry+https://github.com/rust-lang/crates.io-index" 1104 + checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" 1105 + 1106 + [[package]] 1107 + name = "icu_provider" 1108 + version = "1.5.0" 1109 + source = "registry+https://github.com/rust-lang/crates.io-index" 1110 + checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 1111 + dependencies = [ 1112 + "displaydoc", 1113 + "icu_locid", 1114 + "icu_provider_macros", 1115 + "stable_deref_trait", 1116 + "tinystr", 1117 + "writeable", 1118 + "yoke", 1119 + "zerofrom", 1120 + "zerovec", 1121 + ] 1122 + 1123 + [[package]] 1124 + name = "icu_provider_macros" 1125 + version = "1.5.0" 1126 + source = "registry+https://github.com/rust-lang/crates.io-index" 1127 + checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 1128 + dependencies = [ 1129 + "proc-macro2", 1130 + "quote", 1131 + "syn 2.0.96", 1132 + ] 1133 + 1134 + [[package]] 1135 + name = "idna" 1136 + version = "1.0.3" 1137 + source = "registry+https://github.com/rust-lang/crates.io-index" 1138 + checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 1139 + dependencies = [ 1140 + "idna_adapter", 1141 + "smallvec", 1142 + "utf8_iter", 1143 + ] 1144 + 1145 + [[package]] 1146 + name = "idna_adapter" 1147 + version = "1.2.0" 1148 + source = "registry+https://github.com/rust-lang/crates.io-index" 1149 + checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 1150 + dependencies = [ 1151 + "icu_normalizer", 1152 + "icu_properties", 1153 + ] 1154 + 1155 + [[package]] 736 1156 name = "image" 737 1157 version = "0.25.5" 738 1158 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 757 1177 ] 758 1178 759 1179 [[package]] 1180 + name = "ipnet" 1181 + version = "2.11.0" 1182 + source = "registry+https://github.com/rust-lang/crates.io-index" 1183 + checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 1184 + 1185 + [[package]] 760 1186 name = "is-terminal" 761 1187 version = "0.4.13" 762 1188 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 768 1194 ] 769 1195 770 1196 [[package]] 1197 + name = "itertools" 1198 + version = "0.14.0" 1199 + source = "registry+https://github.com/rust-lang/crates.io-index" 1200 + checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" 1201 + dependencies = [ 1202 + "either", 1203 + ] 1204 + 1205 + [[package]] 1206 + name = "itoa" 1207 + version = "1.0.14" 1208 + source = "registry+https://github.com/rust-lang/crates.io-index" 1209 + checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" 1210 + 1211 + [[package]] 771 1212 name = "jni" 772 1213 version = "0.21.1" 773 1214 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 858 1299 checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 859 1300 860 1301 [[package]] 1302 + name = "litemap" 1303 + version = "0.7.4" 1304 + source = "registry+https://github.com/rust-lang/crates.io-index" 1305 + checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" 1306 + 1307 + [[package]] 861 1308 name = "litrs" 862 1309 version = "0.4.1" 863 1310 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 912 1359 "bitflags 2.6.0", 913 1360 "block", 914 1361 "core-graphics-types", 915 - "foreign-types", 1362 + "foreign-types 0.5.0", 916 1363 "log", 917 1364 "objc", 918 1365 "paste", 919 1366 ] 920 1367 921 1368 [[package]] 1369 + name = "mime" 1370 + version = "0.3.17" 1371 + source = "registry+https://github.com/rust-lang/crates.io-index" 1372 + checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1373 + 1374 + [[package]] 922 1375 name = "miniz_oxide" 923 1376 version = "0.8.3" 924 1377 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 929 1382 ] 930 1383 931 1384 [[package]] 1385 + name = "mio" 1386 + version = "1.0.3" 1387 + source = "registry+https://github.com/rust-lang/crates.io-index" 1388 + checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" 1389 + dependencies = [ 1390 + "libc", 1391 + "wasi", 1392 + "windows-sys 0.52.0", 1393 + ] 1394 + 1395 + [[package]] 932 1396 name = "naga" 933 1397 version = "22.1.0" 934 1398 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 947 1411 "termcolor", 948 1412 "thiserror 1.0.64", 949 1413 "unicode-xid", 1414 + ] 1415 + 1416 + [[package]] 1417 + name = "native-tls" 1418 + version = "0.2.13" 1419 + source = "registry+https://github.com/rust-lang/crates.io-index" 1420 + checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c" 1421 + dependencies = [ 1422 + "libc", 1423 + "log", 1424 + "openssl", 1425 + "openssl-probe", 1426 + "openssl-sys", 1427 + "schannel", 1428 + "security-framework", 1429 + "security-framework-sys", 1430 + "tempfile", 950 1431 ] 951 1432 952 1433 [[package]] ··· 1042 1523 checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" 1043 1524 1044 1525 [[package]] 1526 + name = "object" 1527 + version = "0.36.7" 1528 + source = "registry+https://github.com/rust-lang/crates.io-index" 1529 + checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 1530 + dependencies = [ 1531 + "memchr", 1532 + ] 1533 + 1534 + [[package]] 1045 1535 name = "once_cell" 1046 1536 version = "1.19.0" 1047 1537 source = "registry+https://github.com/rust-lang/crates.io-index" 1048 1538 checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 1049 1539 1050 1540 [[package]] 1541 + name = "openssl" 1542 + version = "0.10.69" 1543 + source = "registry+https://github.com/rust-lang/crates.io-index" 1544 + checksum = "f5e534d133a060a3c19daec1eb3e98ec6f4685978834f2dbadfe2ec215bab64e" 1545 + dependencies = [ 1546 + "bitflags 2.6.0", 1547 + "cfg-if", 1548 + "foreign-types 0.3.2", 1549 + "libc", 1550 + "once_cell", 1551 + "openssl-macros", 1552 + "openssl-sys", 1553 + ] 1554 + 1555 + [[package]] 1556 + name = "openssl-macros" 1557 + version = "0.1.1" 1558 + source = "registry+https://github.com/rust-lang/crates.io-index" 1559 + checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1560 + dependencies = [ 1561 + "proc-macro2", 1562 + "quote", 1563 + "syn 2.0.96", 1564 + ] 1565 + 1566 + [[package]] 1567 + name = "openssl-probe" 1568 + version = "0.1.6" 1569 + source = "registry+https://github.com/rust-lang/crates.io-index" 1570 + checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 1571 + 1572 + [[package]] 1573 + name = "openssl-sys" 1574 + version = "0.9.104" 1575 + source = "registry+https://github.com/rust-lang/crates.io-index" 1576 + checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" 1577 + dependencies = [ 1578 + "cc", 1579 + "libc", 1580 + "pkg-config", 1581 + "vcpkg", 1582 + ] 1583 + 1584 + [[package]] 1051 1585 name = "orbclient" 1052 1586 version = "0.3.47" 1053 1587 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1105 1639 version = "0.2.14" 1106 1640 source = "registry+https://github.com/rust-lang/crates.io-index" 1107 1641 checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 1642 + 1643 + [[package]] 1644 + name = "pin-utils" 1645 + version = "0.1.0" 1646 + source = "registry+https://github.com/rust-lang/crates.io-index" 1647 + checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1108 1648 1109 1649 [[package]] 1110 1650 name = "pkg-config" ··· 1275 1815 checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" 1276 1816 1277 1817 [[package]] 1818 + name = "reqwest" 1819 + version = "0.11.27" 1820 + source = "registry+https://github.com/rust-lang/crates.io-index" 1821 + checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" 1822 + dependencies = [ 1823 + "base64", 1824 + "bytes", 1825 + "encoding_rs", 1826 + "futures-core", 1827 + "futures-util", 1828 + "h2", 1829 + "http", 1830 + "http-body", 1831 + "hyper", 1832 + "hyper-tls", 1833 + "ipnet", 1834 + "js-sys", 1835 + "log", 1836 + "mime", 1837 + "native-tls", 1838 + "once_cell", 1839 + "percent-encoding", 1840 + "pin-project-lite", 1841 + "rustls-pemfile", 1842 + "serde", 1843 + "serde_json", 1844 + "serde_urlencoded", 1845 + "sync_wrapper", 1846 + "system-configuration", 1847 + "tokio", 1848 + "tokio-native-tls", 1849 + "tower-service", 1850 + "url", 1851 + "wasm-bindgen", 1852 + "wasm-bindgen-futures", 1853 + "web-sys", 1854 + "winreg", 1855 + ] 1856 + 1857 + [[package]] 1858 + name = "rustc-demangle" 1859 + version = "0.1.24" 1860 + source = "registry+https://github.com/rust-lang/crates.io-index" 1861 + checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1862 + 1863 + [[package]] 1278 1864 name = "rustc-hash" 1279 1865 version = "1.1.0" 1280 1866 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1294 1880 ] 1295 1881 1296 1882 [[package]] 1883 + name = "rustls-pemfile" 1884 + version = "1.0.4" 1885 + source = "registry+https://github.com/rust-lang/crates.io-index" 1886 + checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" 1887 + dependencies = [ 1888 + "base64", 1889 + ] 1890 + 1891 + [[package]] 1892 + name = "ryu" 1893 + version = "1.0.19" 1894 + source = "registry+https://github.com/rust-lang/crates.io-index" 1895 + checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" 1896 + 1897 + [[package]] 1297 1898 name = "same-file" 1298 1899 version = "1.0.6" 1299 1900 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1303 1904 ] 1304 1905 1305 1906 [[package]] 1907 + name = "schannel" 1908 + version = "0.1.27" 1909 + source = "registry+https://github.com/rust-lang/crates.io-index" 1910 + checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" 1911 + dependencies = [ 1912 + "windows-sys 0.59.0", 1913 + ] 1914 + 1915 + [[package]] 1306 1916 name = "scoped-tls" 1307 1917 version = "1.0.1" 1308 1918 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1328 1938 ] 1329 1939 1330 1940 [[package]] 1941 + name = "security-framework" 1942 + version = "2.11.1" 1943 + source = "registry+https://github.com/rust-lang/crates.io-index" 1944 + checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 1945 + dependencies = [ 1946 + "bitflags 2.6.0", 1947 + "core-foundation", 1948 + "core-foundation-sys", 1949 + "libc", 1950 + "security-framework-sys", 1951 + ] 1952 + 1953 + [[package]] 1954 + name = "security-framework-sys" 1955 + version = "2.14.0" 1956 + source = "registry+https://github.com/rust-lang/crates.io-index" 1957 + checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" 1958 + dependencies = [ 1959 + "core-foundation-sys", 1960 + "libc", 1961 + ] 1962 + 1963 + [[package]] 1331 1964 name = "serde" 1332 1965 version = "1.0.210" 1333 1966 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1345 1978 "proc-macro2", 1346 1979 "quote", 1347 1980 "syn 2.0.96", 1981 + ] 1982 + 1983 + [[package]] 1984 + name = "serde_json" 1985 + version = "1.0.138" 1986 + source = "registry+https://github.com/rust-lang/crates.io-index" 1987 + checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" 1988 + dependencies = [ 1989 + "itoa", 1990 + "memchr", 1991 + "ryu", 1992 + "serde", 1993 + ] 1994 + 1995 + [[package]] 1996 + name = "serde_urlencoded" 1997 + version = "0.7.1" 1998 + source = "registry+https://github.com/rust-lang/crates.io-index" 1999 + checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 2000 + dependencies = [ 2001 + "form_urlencoded", 2002 + "itoa", 2003 + "ryu", 2004 + "serde", 1348 2005 ] 1349 2006 1350 2007 [[package]] ··· 1418 2075 ] 1419 2076 1420 2077 [[package]] 2078 + name = "socket2" 2079 + version = "0.5.8" 2080 + source = "registry+https://github.com/rust-lang/crates.io-index" 2081 + checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" 2082 + dependencies = [ 2083 + "libc", 2084 + "windows-sys 0.52.0", 2085 + ] 2086 + 2087 + [[package]] 1421 2088 name = "spirv" 1422 2089 version = "0.3.0+sdk-1.3.268.0" 1423 2090 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1425 2092 dependencies = [ 1426 2093 "bitflags 2.6.0", 1427 2094 ] 2095 + 2096 + [[package]] 2097 + name = "stable_deref_trait" 2098 + version = "1.2.0" 2099 + source = "registry+https://github.com/rust-lang/crates.io-index" 2100 + checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 1428 2101 1429 2102 [[package]] 1430 2103 name = "static_assertions" ··· 1461 2134 ] 1462 2135 1463 2136 [[package]] 2137 + name = "sync_wrapper" 2138 + version = "0.1.2" 2139 + source = "registry+https://github.com/rust-lang/crates.io-index" 2140 + checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" 2141 + 2142 + [[package]] 2143 + name = "synstructure" 2144 + version = "0.13.1" 2145 + source = "registry+https://github.com/rust-lang/crates.io-index" 2146 + checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 2147 + dependencies = [ 2148 + "proc-macro2", 2149 + "quote", 2150 + "syn 2.0.96", 2151 + ] 2152 + 2153 + [[package]] 2154 + name = "system-configuration" 2155 + version = "0.5.1" 2156 + source = "registry+https://github.com/rust-lang/crates.io-index" 2157 + checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" 2158 + dependencies = [ 2159 + "bitflags 1.3.2", 2160 + "core-foundation", 2161 + "system-configuration-sys", 2162 + ] 2163 + 2164 + [[package]] 2165 + name = "system-configuration-sys" 2166 + version = "0.5.0" 2167 + source = "registry+https://github.com/rust-lang/crates.io-index" 2168 + checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" 2169 + dependencies = [ 2170 + "core-foundation-sys", 2171 + "libc", 2172 + ] 2173 + 2174 + [[package]] 2175 + name = "tempfile" 2176 + version = "3.13.0" 2177 + source = "registry+https://github.com/rust-lang/crates.io-index" 2178 + checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" 2179 + dependencies = [ 2180 + "cfg-if", 2181 + "fastrand", 2182 + "once_cell", 2183 + "rustix", 2184 + "windows-sys 0.59.0", 2185 + ] 2186 + 2187 + [[package]] 1464 2188 name = "termcolor" 1465 2189 version = "1.4.1" 1466 2190 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1535 2259 ] 1536 2260 1537 2261 [[package]] 2262 + name = "tinystr" 2263 + version = "0.7.6" 2264 + source = "registry+https://github.com/rust-lang/crates.io-index" 2265 + checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 2266 + dependencies = [ 2267 + "displaydoc", 2268 + "zerovec", 2269 + ] 2270 + 2271 + [[package]] 2272 + name = "tobj" 2273 + version = "4.0.3" 2274 + source = "registry+https://github.com/rust-lang/crates.io-index" 2275 + checksum = "04aca6092e5978e708ee784e8ab9b5cf3cdb598b28f99a2f257446e7081a7025" 2276 + 2277 + [[package]] 2278 + name = "tokio" 2279 + version = "1.42.0" 2280 + source = "registry+https://github.com/rust-lang/crates.io-index" 2281 + checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" 2282 + dependencies = [ 2283 + "backtrace", 2284 + "bytes", 2285 + "libc", 2286 + "mio", 2287 + "pin-project-lite", 2288 + "socket2", 2289 + "windows-sys 0.52.0", 2290 + ] 2291 + 2292 + [[package]] 2293 + name = "tokio-native-tls" 2294 + version = "0.3.1" 2295 + source = "registry+https://github.com/rust-lang/crates.io-index" 2296 + checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 2297 + dependencies = [ 2298 + "native-tls", 2299 + "tokio", 2300 + ] 2301 + 2302 + [[package]] 2303 + name = "tokio-util" 2304 + version = "0.7.13" 2305 + source = "registry+https://github.com/rust-lang/crates.io-index" 2306 + checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" 2307 + dependencies = [ 2308 + "bytes", 2309 + "futures-core", 2310 + "futures-sink", 2311 + "pin-project-lite", 2312 + "tokio", 2313 + ] 2314 + 2315 + [[package]] 1538 2316 name = "toml_datetime" 1539 2317 version = "0.6.8" 1540 2318 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1552 2330 ] 1553 2331 1554 2332 [[package]] 2333 + name = "tower-service" 2334 + version = "0.3.3" 2335 + source = "registry+https://github.com/rust-lang/crates.io-index" 2336 + checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 2337 + 2338 + [[package]] 1555 2339 name = "tracing" 1556 2340 version = "0.1.40" 1557 2341 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1566 2350 version = "0.1.32" 1567 2351 source = "registry+https://github.com/rust-lang/crates.io-index" 1568 2352 checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 2353 + dependencies = [ 2354 + "once_cell", 2355 + ] 2356 + 2357 + [[package]] 2358 + name = "try-lock" 2359 + version = "0.2.5" 2360 + source = "registry+https://github.com/rust-lang/crates.io-index" 2361 + checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1569 2362 1570 2363 [[package]] 1571 2364 name = "ttf-parser" ··· 1598 2391 checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 1599 2392 1600 2393 [[package]] 2394 + name = "url" 2395 + version = "2.5.4" 2396 + source = "registry+https://github.com/rust-lang/crates.io-index" 2397 + checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 2398 + dependencies = [ 2399 + "form_urlencoded", 2400 + "idna", 2401 + "percent-encoding", 2402 + ] 2403 + 2404 + [[package]] 2405 + name = "utf16_iter" 2406 + version = "1.0.5" 2407 + source = "registry+https://github.com/rust-lang/crates.io-index" 2408 + checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 2409 + 2410 + [[package]] 2411 + name = "utf8_iter" 2412 + version = "1.0.4" 2413 + source = "registry+https://github.com/rust-lang/crates.io-index" 2414 + checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 2415 + 2416 + [[package]] 2417 + name = "vcpkg" 2418 + version = "0.2.15" 2419 + source = "registry+https://github.com/rust-lang/crates.io-index" 2420 + checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2421 + 2422 + [[package]] 1601 2423 name = "version_check" 1602 2424 version = "0.9.5" 1603 2425 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1611 2433 dependencies = [ 1612 2434 "same-file", 1613 2435 "winapi-util", 2436 + ] 2437 + 2438 + [[package]] 2439 + name = "want" 2440 + version = "0.3.1" 2441 + source = "registry+https://github.com/rust-lang/crates.io-index" 2442 + checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 2443 + dependencies = [ 2444 + "try-lock", 1614 2445 ] 1615 2446 1616 2447 [[package]] ··· 2250 3081 ] 2251 3082 2252 3083 [[package]] 3084 + name = "winreg" 3085 + version = "0.50.0" 3086 + source = "registry+https://github.com/rust-lang/crates.io-index" 3087 + checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" 3088 + dependencies = [ 3089 + "cfg-if", 3090 + "windows-sys 0.48.0", 3091 + ] 3092 + 3093 + [[package]] 3094 + name = "write16" 3095 + version = "1.0.0" 3096 + source = "registry+https://github.com/rust-lang/crates.io-index" 3097 + checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 3098 + 3099 + [[package]] 3100 + name = "writeable" 3101 + version = "0.5.5" 3102 + source = "registry+https://github.com/rust-lang/crates.io-index" 3103 + checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 3104 + 3105 + [[package]] 2253 3106 name = "x11-dl" 2254 3107 version = "2.21.0" 2255 3108 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2313 3166 checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" 2314 3167 2315 3168 [[package]] 3169 + name = "yoke" 3170 + version = "0.7.5" 3171 + source = "registry+https://github.com/rust-lang/crates.io-index" 3172 + checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" 3173 + dependencies = [ 3174 + "serde", 3175 + "stable_deref_trait", 3176 + "yoke-derive", 3177 + "zerofrom", 3178 + ] 3179 + 3180 + [[package]] 3181 + name = "yoke-derive" 3182 + version = "0.7.5" 3183 + source = "registry+https://github.com/rust-lang/crates.io-index" 3184 + checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" 3185 + dependencies = [ 3186 + "proc-macro2", 3187 + "quote", 3188 + "syn 2.0.96", 3189 + "synstructure", 3190 + ] 3191 + 3192 + [[package]] 2316 3193 name = "zerocopy" 2317 3194 version = "0.7.35" 2318 3195 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2326 3203 version = "0.7.35" 2327 3204 source = "registry+https://github.com/rust-lang/crates.io-index" 2328 3205 checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 3206 + dependencies = [ 3207 + "proc-macro2", 3208 + "quote", 3209 + "syn 2.0.96", 3210 + ] 3211 + 3212 + [[package]] 3213 + name = "zerofrom" 3214 + version = "0.1.5" 3215 + source = "registry+https://github.com/rust-lang/crates.io-index" 3216 + checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" 3217 + dependencies = [ 3218 + "zerofrom-derive", 3219 + ] 3220 + 3221 + [[package]] 3222 + name = "zerofrom-derive" 3223 + version = "0.1.5" 3224 + source = "registry+https://github.com/rust-lang/crates.io-index" 3225 + checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" 3226 + dependencies = [ 3227 + "proc-macro2", 3228 + "quote", 3229 + "syn 2.0.96", 3230 + "synstructure", 3231 + ] 3232 + 3233 + [[package]] 3234 + name = "zerovec" 3235 + version = "0.10.4" 3236 + source = "registry+https://github.com/rust-lang/crates.io-index" 3237 + checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 3238 + dependencies = [ 3239 + "yoke", 3240 + "zerofrom", 3241 + "zerovec-derive", 3242 + ] 3243 + 3244 + [[package]] 3245 + name = "zerovec-derive" 3246 + version = "0.10.3" 3247 + source = "registry+https://github.com/rust-lang/crates.io-index" 3248 + checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 2329 3249 dependencies = [ 2330 3250 "proc-macro2", 2331 3251 "quote",
+5
Cargo.toml
··· 16 16 image = { version = "0.25.5", default-features = false, features = ["png", "jpeg"] } 17 17 thiserror = "2.0.11" 18 18 glam = { version = "0.29.2", features = ["bytemuck"] } 19 + tobj = { version = "4", default-features = false, features = ["async"] } 20 + futures = "0.3.31" 21 + itertools = "0.14.0" 19 22 20 23 [build-dependencies] 21 24 fs_extra = "1.3.0" ··· 34 37 "Document", 35 38 "Window", 36 39 "Element", 40 + "Location", 37 41 ]} 42 + reqwest = "0.11"
+1 -1
build.rs
··· 13 13 copy_items(&paths_to_copy, out_dir, &copy_options)?; 14 14 15 15 Ok(()) 16 - } 16 + }
+131 -81
src/lib.rs
··· 1 1 #![allow(rust_analyzer::inactive_code)] 2 2 3 3 mod camera; 4 - mod texture; 5 4 mod model; 6 5 mod resources; 6 + mod texture; 7 7 8 8 use model::Vertex; 9 9 use wgpu::util::DeviceExt; ··· 74 74 } 75 75 } 76 76 77 - const NUM_INSTANCES_PER_ROW: u32 = 1000; 77 + const NUM_INSTANCES_PER_ROW: u32 = 100; 78 78 const INSTANCE_DISPLACEMENT: Vec3 = vec3( 79 79 NUM_INSTANCES_PER_ROW as f32 * 0.1, 80 80 0.0, ··· 88 88 config: wgpu::SurfaceConfiguration, 89 89 size: winit::dpi::PhysicalSize<u32>, 90 90 render_pipeline: wgpu::RenderPipeline, 91 + wireframe_render_pipeline: Option<wgpu::RenderPipeline>, 91 92 diffuse_bind_group: wgpu::BindGroup, 92 93 diffuse_texture: texture::Texture, 93 94 depth_texture: texture::Texture, ··· 98 99 camera_bind_group: wgpu::BindGroup, 99 100 instances: Vec<Instance>, 100 101 instance_buffer: wgpu::Buffer, 102 + wireframe: bool, 101 103 102 104 // Window must be declared after surface 103 105 // so it gets dropped after it ··· 107 109 window: &'srfc Window, 108 110 109 111 clear_color: wgpu::Color, 112 + obj_model: model::Model, 110 113 } 111 114 112 115 impl<'a> State<'a> { ··· 115 118 let size = window.inner_size(); 116 119 #[cfg(target_arch = "wasm32")] 117 120 let size = winit::dpi::PhysicalSize { 118 - width: 100, 119 - height: 100, 121 + width: 400, 122 + height: 300, 120 123 }; 121 124 122 125 // 0 size can cause app to crash, better to enforce this maybe. ··· 150 153 let (device, queue) = adapter 151 154 .request_device( 152 155 &wgpu::DeviceDescriptor { 153 - required_features: wgpu::Features::empty(), 156 + required_features: if adapter.get_info().backend == wgpu::Backend::Gl { 157 + wgpu::Features::empty() 158 + } else { 159 + wgpu::Features::POLYGON_MODE_LINE 160 + }, 154 161 155 162 // WebGL does not support all of wgpu's features 156 - required_limits: if cfg!(target_arch = "wasm32") { 163 + required_limits: if adapter.get_info().backend == wgpu::Backend::Gl { 157 164 wgpu::Limits::downlevel_webgl2_defaults() 158 165 } else { 159 166 wgpu::Limits::default() ··· 278 285 label: Some("camera_bind_group"), 279 286 }); 280 287 281 - let instances = (0..NUM_INSTANCES_PER_ROW) 282 - .flat_map(|z| { 283 - (0..NUM_INSTANCES_PER_ROW).map(move |x| { 284 - let position = vec3(x as f32, 0.0, z as f32) - INSTANCE_DISPLACEMENT; 288 + const SPACE_BETWEEN: f32 = 3.0; 289 + let instances = itertools::iproduct!(0..NUM_INSTANCES_PER_ROW, 0..NUM_INSTANCES_PER_ROW) 290 + .map(|(x, z)| { 291 + let mapping = |n| SPACE_BETWEEN * (n as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0); 292 + let position = vec3(mapping(x), 0.0, mapping(z)); 285 293 286 - // this is needed so an object at (0, 0, 0) won't get scaled to zero 287 - // as Quaternions can affect scale if they're not created correctly 288 - let rotation = match position.try_normalize() { 289 - Some(position) => Quat::from_axis_angle(position, 45.0), 290 - None => Quat::from_axis_angle(Vec3::Z, 0.0), 291 - }; 294 + // this is needed so an object at (0, 0, 0) won't get scaled to zero 295 + // as Quaternions can affect scale if they're not created correctly 296 + let rotation = match position.try_normalize() { 297 + Some(position) => Quat::from_axis_angle(position, 45.0), 298 + None => Quat::from_axis_angle(Vec3::Z, 0.0), 299 + }; 292 300 293 - Instance { position, rotation } 294 - }) 301 + Instance { position, rotation } 295 302 }) 296 303 .collect::<Vec<_>>(); 297 304 ··· 302 309 usage: wgpu::BufferUsages::VERTEX, 303 310 }); 304 311 312 + let obj_model = 313 + resources::load_model("cube.obj", &device, &queue, &texture_bind_group_layout) 314 + .await 315 + .unwrap(); 316 + 305 317 let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { 306 318 label: Some("Shader"), 307 319 source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), ··· 314 326 push_constant_ranges: &[], 315 327 }); 316 328 317 - let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { 318 - label: Some("Render Pipeline"), 319 - layout: Some(&render_pipeline_layout), 320 - vertex: wgpu::VertexState { 321 - module: &shader, 322 - entry_point: "vs_main", 323 - buffers: &[model::ModelVertex::desc(), InstanceRaw::desc()], 324 - compilation_options: wgpu::PipelineCompilationOptions::default(), 325 - }, 326 - fragment: Some(wgpu::FragmentState { 327 - module: &shader, 328 - entry_point: "fs_main", 329 - targets: &[Some(wgpu::ColorTargetState { 330 - format: config.format, 331 - blend: Some(wgpu::BlendState::REPLACE), 332 - write_mask: wgpu::ColorWrites::ALL, 333 - })], 334 - compilation_options: wgpu::PipelineCompilationOptions::default(), 335 - }), 336 - primitive: wgpu::PrimitiveState { 337 - topology: wgpu::PrimitiveTopology::TriangleList, 338 - strip_index_format: None, 339 - front_face: wgpu::FrontFace::Ccw, 340 - cull_mode: Some(wgpu::Face::Back), 341 - polygon_mode: wgpu::PolygonMode::Fill, 342 - unclipped_depth: false, 343 - conservative: false, 344 - }, 345 - depth_stencil: Some(wgpu::DepthStencilState { 346 - format: texture::Texture::DEPTH_FORMAT, 347 - depth_write_enabled: true, 348 - depth_compare: wgpu::CompareFunction::Less, 349 - stencil: wgpu::StencilState::default(), 350 - bias: wgpu::DepthBiasState::default(), 351 - }), 352 - multisample: wgpu::MultisampleState { 353 - count: 1, 354 - mask: !0, 355 - alpha_to_coverage_enabled: false, 356 - }, 357 - multiview: None, 358 - cache: None, 359 - }); 329 + let render_pipeline = |polygon_mode: wgpu::PolygonMode| { 330 + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { 331 + label: Some("Render Pipeline"), 332 + layout: Some(&render_pipeline_layout), 333 + vertex: wgpu::VertexState { 334 + module: &shader, 335 + entry_point: "vs_main", 336 + buffers: &[model::ModelVertex::desc(), InstanceRaw::desc()], 337 + compilation_options: wgpu::PipelineCompilationOptions::default(), 338 + }, 339 + fragment: Some(wgpu::FragmentState { 340 + module: &shader, 341 + entry_point: "fs_main", 342 + targets: &[Some(wgpu::ColorTargetState { 343 + format: config.format, 344 + blend: Some(wgpu::BlendState::REPLACE), 345 + write_mask: wgpu::ColorWrites::ALL, 346 + })], 347 + compilation_options: wgpu::PipelineCompilationOptions::default(), 348 + }), 349 + primitive: wgpu::PrimitiveState { 350 + topology: wgpu::PrimitiveTopology::TriangleList, 351 + strip_index_format: None, 352 + front_face: wgpu::FrontFace::Ccw, 353 + cull_mode: Some(wgpu::Face::Back), 354 + polygon_mode, 355 + unclipped_depth: false, 356 + conservative: false, 357 + }, 358 + depth_stencil: Some(wgpu::DepthStencilState { 359 + format: texture::Texture::DEPTH_FORMAT, 360 + depth_write_enabled: true, 361 + depth_compare: wgpu::CompareFunction::Less, 362 + stencil: wgpu::StencilState::default(), 363 + bias: wgpu::DepthBiasState::default(), 364 + }), 365 + multisample: wgpu::MultisampleState { 366 + count: 1, 367 + mask: !0, 368 + alpha_to_coverage_enabled: false, 369 + }, 370 + multiview: None, 371 + cache: None, 372 + }) 373 + }; 360 374 361 - let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { 362 - label: Some("Vertex Buffer"), 363 - contents: bytemuck::cast_slice(VERTICES), 364 - usage: wgpu::BufferUsages::VERTEX, 365 - }); 375 + let fill_pipeline = render_pipeline(wgpu::PolygonMode::Fill); 376 + let wireframe_render_pipeline = if (device.features() & wgpu::Features::POLYGON_MODE_LINE) 377 + == wgpu::Features::POLYGON_MODE_LINE 378 + { 379 + Some(render_pipeline(wgpu::PolygonMode::Line)) 380 + } else { 381 + None 382 + }; 366 383 367 - let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { 368 - label: Some("Index Buffer"), 369 - contents: bytemuck::cast_slice(INDICES), 370 - usage: wgpu::BufferUsages::INDEX, 371 - }); 384 + // let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { 385 + // label: Some("Vertex Buffer"), 386 + // contents: bytemuck::cast_slice(VERTICES), 387 + // usage: wgpu::BufferUsages::VERTEX, 388 + // }); 389 + // 390 + // let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { 391 + // label: Some("Index Buffer"), 392 + // contents: bytemuck::cast_slice(INDICES), 393 + // usage: wgpu::BufferUsages::INDEX, 394 + // }); 372 395 373 396 let num_indices = INDICES.len() as u32; 374 397 ··· 379 402 queue, 380 403 config, 381 404 size, 382 - render_pipeline, 405 + render_pipeline: fill_pipeline, 406 + wireframe_render_pipeline, 383 407 diffuse_bind_group, 384 408 diffuse_texture, 409 + obj_model, 385 410 camera, 386 411 camera_controller, 387 412 camera_uniform, ··· 390 415 instances, 391 416 instance_buffer, 392 417 depth_texture, 418 + wireframe: false, 393 419 clear_color: wgpu::Color { 394 420 r: 0.1, 395 421 g: 0.2, ··· 432 458 }; 433 459 return true; 434 460 } 461 + WindowEvent::KeyboardInput { 462 + event: 463 + KeyEvent { 464 + state, 465 + physical_key: PhysicalKey::Code(keycode), 466 + .. 467 + }, 468 + .. 469 + } => { 470 + let is_pressed = *state == ElementState::Pressed; 471 + match *keycode { 472 + KeyCode::KeyL => { 473 + if is_pressed { 474 + self.wireframe = !self.wireframe; 475 + return true; 476 + } 477 + } 478 + _ => {} 479 + } 480 + } 435 481 _ => {} 436 482 } 437 483 ··· 483 529 timestamp_writes: None, 484 530 }); 485 531 486 - render_pass.set_pipeline(&self.render_pipeline); 487 - 488 - render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]); 489 - render_pass.set_bind_group(1, &self.camera_bind_group, &[]); 490 - 491 - render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); 492 532 render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..)); 493 - 494 - render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16); 533 + render_pass.set_pipeline(if self.wireframe { 534 + self.wireframe_render_pipeline 535 + .as_ref() 536 + .unwrap_or(&self.render_pipeline) 537 + } else { 538 + &self.render_pipeline 539 + }); 495 540 496 - render_pass.draw_indexed(0..self.num_indices, 0, 0..self.instances.len() as _); 541 + use model::DrawModel; 542 + render_pass.draw_model_instanced( 543 + &self.obj_model, 544 + 0..self.instances.len() as u32, 545 + &self.camera_bind_group, 546 + ); 497 547 498 548 // drop render pass before we submit to drop the mut borrow on encoder 499 549 drop(render_pass);
+117 -29
src/model.rs
··· 1 + use crate::texture; 2 + use std::ops::Range; 3 + 1 4 pub trait Vertex { 2 - fn desc() -> wgpu::VertexBufferLayout<'static>; 5 + fn desc() -> wgpu::VertexBufferLayout<'static>; 3 6 } 4 7 5 8 #[repr(C)] 6 9 #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] 7 10 pub struct ModelVertex { 8 - pub position: [f32; 3], 9 - pub tex_coords: [f32; 2], 10 - pub normal: [f32; 3], 11 + pub position: [f32; 3], 12 + pub tex_coords: [f32; 2], 13 + pub normal: [f32; 3], 11 14 } 12 15 13 16 impl Vertex for ModelVertex { 14 - fn desc() -> wgpu::VertexBufferLayout<'static> { 15 - use std::mem; 17 + fn desc() -> wgpu::VertexBufferLayout<'static> { 18 + use std::mem; 19 + 20 + wgpu::VertexBufferLayout { 21 + array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress, 22 + step_mode: wgpu::VertexStepMode::Vertex, 23 + attributes: &[ 24 + wgpu::VertexAttribute { 25 + offset: 0, 26 + shader_location: 0, 27 + format: wgpu::VertexFormat::Float32x3, 28 + }, 29 + wgpu::VertexAttribute { 30 + offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress, 31 + shader_location: 1, 32 + format: wgpu::VertexFormat::Float32x2, 33 + }, 34 + wgpu::VertexAttribute { 35 + offset: mem::size_of::<[f32; 5]>() as wgpu::BufferAddress, 36 + shader_location: 2, 37 + format: wgpu::VertexFormat::Float32x3, 38 + }, 39 + ], 40 + } 41 + } 42 + } 16 43 17 - wgpu::VertexBufferLayout { 18 - array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress, 19 - step_mode: wgpu::VertexStepMode::Vertex, 20 - attributes: &[ 21 - wgpu::VertexAttribute { 22 - offset: 0, 23 - shader_location: 0, 24 - format: wgpu::VertexFormat::Float32x3, 25 - }, 26 - wgpu::VertexAttribute { 27 - offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress, 28 - shader_location: 1, 29 - format: wgpu::VertexFormat::Float32x2, 30 - }, 31 - wgpu::VertexAttribute { 32 - offset: mem::size_of::<[f32; 5]>() as wgpu::BufferAddress, 33 - shader_location: 2, 34 - format: wgpu::VertexFormat::Float32x3, 35 - }, 36 - ] 37 - } 38 - } 39 - } 44 + pub struct Model { 45 + pub meshes: Vec<Mesh>, 46 + pub materials: Vec<Material>, 47 + } 48 + 49 + pub struct Material { 50 + pub name: String, // for debugging! 51 + pub diffuse_texture: texture::Texture, 52 + pub bind_group: wgpu::BindGroup, 53 + } 54 + 55 + pub struct Mesh { 56 + pub name: String, 57 + pub vertex_buffer: wgpu::Buffer, 58 + pub index_buffer: wgpu::Buffer, 59 + pub num_elements: u32, 60 + pub material: usize, 61 + } 62 + 63 + pub trait DrawModel<'a> { 64 + fn draw_mesh( 65 + &mut self, 66 + mesh: &'a Mesh, 67 + material: &'a Material, 68 + camera_bind_group: &'a wgpu::BindGroup, 69 + ); 70 + fn draw_mesh_instanced( 71 + &mut self, 72 + mesh: &'a Mesh, 73 + material: &'a Material, 74 + instances: Range<u32>, 75 + camera_bind_group: &'a wgpu::BindGroup, 76 + ); 77 + fn draw_model(&mut self, model: &'a Model, camera_bind_group: &'a wgpu::BindGroup); 78 + fn draw_model_instanced( 79 + &mut self, 80 + model: &'a Model, 81 + instances: Range<u32>, 82 + camera_bind_group: &'a wgpu::BindGroup, 83 + ); 84 + } 85 + 86 + impl<'a, 'b> DrawModel<'b> for wgpu::RenderPass<'a> 87 + where 88 + 'b: 'a, 89 + { 90 + fn draw_mesh( 91 + &mut self, 92 + mesh: &'b Mesh, 93 + material: &'b Material, 94 + camera_bind_group: &'b wgpu::BindGroup, 95 + ) { 96 + self.draw_mesh_instanced(mesh, material, 0..1, camera_bind_group); 97 + } 98 + 99 + fn draw_mesh_instanced( 100 + &mut self, 101 + mesh: &'b Mesh, 102 + material: &'a Material, 103 + instances: Range<u32>, 104 + camera_bind_group: &'b wgpu::BindGroup, 105 + ) { 106 + self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..)); 107 + self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32); 108 + self.set_bind_group(0, &material.bind_group, &[]); 109 + self.set_bind_group(1, camera_bind_group, &[]); 110 + self.draw_indexed(0..mesh.num_elements, 0, instances); 111 + } 112 + fn draw_model(&mut self, model: &'b Model, camera_bind_group: &'b wgpu::BindGroup) { 113 + self.draw_model_instanced(model, 0..1, camera_bind_group); 114 + } 115 + 116 + fn draw_model_instanced( 117 + &mut self, 118 + model: &'b Model, 119 + instances: Range<u32>, 120 + camera_bind_group: &'b wgpu::BindGroup, 121 + ) { 122 + for mesh in &model.meshes { 123 + let material = &model.materials[mesh.material]; 124 + self.draw_mesh_instanced(mesh, material, instances.clone(), camera_bind_group); 125 + } 126 + } 127 + }
+183 -12
src/resources.rs
··· 1 - 1 + use crate::{model, texture}; 2 + use cfg_if::cfg_if; 3 + use std::error::Error; 4 + use std::io::{BufReader, Cursor}; 5 + use wgpu::util::DeviceExt; 2 6 3 7 #[cfg(target_arch = "wasm32")] 4 8 fn format_url(file_name: &str) -> reqwest::Url { 5 - let window = web_sys::window().unwrap(); 6 - let location = window.location(); 7 - let mut origin = location.origin().unwrap(); 8 - if !origin.ends_with("learn-wgpu") { 9 - origin = format!("{}/learn-wgpu", origin); 10 - } 11 - let base = reqwest::Url::parse(&format!("{}/", origin)).unwrap(); 12 - base.join(file_name).unwrap() 9 + let window = web_sys::window().unwrap(); 10 + let location = window.location(); 11 + let mut origin = location.origin().unwrap(); 12 + if !origin.ends_with("res") { 13 + origin = format!("{}/res", origin); 14 + } 15 + let base = reqwest::Url::parse(&format!("{}/", origin)).unwrap(); 16 + base.join(file_name).unwrap() 13 17 } 14 18 15 19 pub async fn load_string(file_name: &str) -> Result<String, Box<dyn Error>> { 16 - cfg_if! { 17 - if #[c] 18 - } 20 + cfg_if! { 21 + if #[cfg(target_arch = "wasm32")] { 22 + let url = format_url(file_name); 23 + let txt = reqwest::get(url) 24 + .await? 25 + .text() 26 + .await?; 27 + } else { 28 + let path = std::path::Path::new(env!("OUT_DIR")) 29 + .join("res") 30 + .join(file_name); 31 + let txt = std::fs::read_to_string(path)?; 32 + } 33 + } 34 + 35 + Ok(txt) 36 + } 37 + 38 + pub async fn load_binary(file_name: &str) -> Result<Vec<u8>, Box<dyn Error>> { 39 + cfg_if! { 40 + if #[cfg(target_arch = "wasm32")] { 41 + let url = format_url(file_name); 42 + let data = reqwest::get(url) 43 + .await? 44 + .bytes() 45 + .await? 46 + .to_vec(); 47 + } else { 48 + let path = std::path::Path::new(env!("OUT_DIR")) 49 + .join("res") 50 + .join(file_name); 51 + let data = std::fs::read(path)?; 52 + } 53 + } 54 + 55 + Ok(data) 56 + } 57 + 58 + pub async fn load_texture( 59 + file_name: &str, 60 + device: &wgpu::Device, 61 + queue: &wgpu::Queue, 62 + ) -> Result<texture::Texture, Box<dyn Error + 'static>> { 63 + let data = load_binary(file_name).await?; 64 + texture::Texture::from_bytes(device, queue, &data, file_name).map_err(|e| e.into()) 65 + } 66 + 67 + #[derive(thiserror::Error, Debug)] 68 + enum ModelLoadError { 69 + #[error("Model has no Diffuse Texture")] 70 + TextureDiffuseMissing, 71 + } 72 + 73 + pub async fn load_model( 74 + file_name: &str, 75 + device: &wgpu::Device, 76 + queue: &wgpu::Queue, 77 + layout: &wgpu::BindGroupLayout, 78 + ) -> Result<model::Model, Box<dyn std::error::Error + 'static>> { 79 + let obj_text = load_string(file_name).await?; 80 + let obj_cursor = Cursor::new(obj_text); 81 + let mut obj_reader = BufReader::new(obj_cursor); 82 + 83 + let (models, obj_materials) = tobj::load_obj_buf_async( 84 + &mut obj_reader, 85 + &tobj::LoadOptions { 86 + triangulate: true, 87 + single_index: true, 88 + ..Default::default() 89 + }, 90 + |p| async move { 91 + let mat_text = load_string(&p).await.unwrap(); 92 + tobj::load_mtl_buf(&mut BufReader::new(Cursor::new(mat_text))) 93 + }, 94 + ) 95 + .await?; 96 + 97 + let read_material = |material: tobj::Material| async { 98 + let diffuse_texture = load_texture( 99 + &material 100 + .diffuse_texture 101 + .ok_or(ModelLoadError::TextureDiffuseMissing)?, 102 + device, 103 + queue, 104 + ) 105 + .await?; 106 + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { 107 + layout, 108 + entries: &[ 109 + wgpu::BindGroupEntry { 110 + binding: 0, 111 + resource: wgpu::BindingResource::TextureView(&diffuse_texture.view), 112 + }, 113 + wgpu::BindGroupEntry { 114 + binding: 1, 115 + resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler), 116 + }, 117 + ], 118 + label: None, 119 + }); 120 + 121 + Ok::<_, Box<dyn Error>>(model::Material { 122 + name: material.name, 123 + diffuse_texture, 124 + bind_group, 125 + }) 126 + }; 127 + 128 + let mesh_positions = |m: &tobj::Model, i: usize| { 129 + [ 130 + m.mesh.positions[i * 3], 131 + m.mesh.positions[i * 3 + 1], 132 + m.mesh.positions[i * 3 + 2], 133 + ] 134 + }; 135 + let mesh_normals = |m: &tobj::Model, i: usize| { 136 + if m.mesh.normals.is_empty() { 137 + glam::Vec3::ZERO.into() 138 + } else { 139 + [ 140 + m.mesh.normals[i * 3], 141 + m.mesh.normals[i * 3 + 1], 142 + m.mesh.normals[i * 3 + 2], 143 + ] 144 + } 145 + }; 146 + 147 + let read_mesh = |m: tobj::Model| { 148 + let vertices = (0..m.mesh.positions.len() / 3) 149 + .map(|i| model::ModelVertex { 150 + position: mesh_positions(&m, i), 151 + tex_coords: [m.mesh.texcoords[i * 2], 1.0 - m.mesh.texcoords[i * 2 + 1]], 152 + normal: mesh_normals(&m, i), 153 + }) 154 + .collect::<Vec<_>>(); 155 + 156 + let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { 157 + label: Some(&format!("{file_name:?} Vertex Buffer")), 158 + contents: bytemuck::cast_slice(&vertices), 159 + usage: wgpu::BufferUsages::VERTEX, 160 + }); 161 + 162 + let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { 163 + label: Some(&format!("{file_name:?} Index Buffer")), 164 + contents: bytemuck::cast_slice(&m.mesh.indices), 165 + usage: wgpu::BufferUsages::INDEX, 166 + }); 167 + 168 + model::Mesh { 169 + name: file_name.to_string(), 170 + vertex_buffer, 171 + index_buffer, 172 + num_elements: m.mesh.indices.len() as u32, 173 + material: m.mesh.material_id.unwrap_or(0), 174 + } 175 + }; 176 + 177 + let materials = futures::future::join_all( 178 + obj_materials? 179 + .into_iter() 180 + .map(read_material) 181 + .collect::<Vec<_>>(), 182 + ) 183 + .await 184 + .into_iter() 185 + .collect::<Result<Vec<_>, _>>()?; 186 + 187 + let meshes = models.into_iter().map(read_mesh).collect(); 188 + 189 + Ok(model::Model { meshes, materials }) 19 190 }