commit adafd5a3702f4ef037e1527d9753077104df6b91 Author: eater <=@eater.me> Date: Thu Apr 9 14:50:00 2020 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..048ce40 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,741 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "adler32" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" + +[[package]] +name = "alga" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f823d037a7ec6ea2197046bafd4ae150e6bc36f9ca347404f46a46823fa84f2" +dependencies = [ + "approx", + "num-complex", + "num-traits", +] + +[[package]] +name = "approx" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" +dependencies = [ + "num-traits", +] + +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "bytemuck" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37fa13df2292ecb479ec23aa06f4507928bef07839be9ef15281411076629431" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "c2-chacha" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" +dependencies = [ + "ppv-lite86", +] + +[[package]] +name = "cc" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cmake" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" +dependencies = [ + "cc", +] + +[[package]] +name = "color_quant" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" + +[[package]] +name = "crc32fast" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "deflate" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4" +dependencies = [ + "adler32", + "byteorder", +] + +[[package]] +name = "eatgel" +version = "0.1.0" +dependencies = [ + "eatgel-proc-macro", + "gl", + "image", + "nalgebra", + "nalgebra-glm", +] + +[[package]] +name = "eatgel-graph" +version = "0.1.0" +dependencies = [ + "nalgebra-glm", +] + +[[package]] +name = "eatgel-proc-macro" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "proc_macro_roids", + "quote", + "syn", +] + +[[package]] +name = "either" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" + +[[package]] +name = "generic-array" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd" +dependencies = [ + "typenum", +] + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gif" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "471d90201b3b223f3451cd4ad53e34295f16a1df17b1edf3736d47761c3981af" +dependencies = [ + "color_quant", + "lzw", +] + +[[package]] +name = "gl" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glfw" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b4c1f2e99ce4181c37d9582986ed32a8f55235bdc9427258d96d09cc9666a29" +dependencies = [ + "bitflags", + "glfw-sys", + "libc", + "log", + "objc", + "raw-window-handle", + "semver", + "winapi", +] + +[[package]] +name = "glfw-sys" +version = "3.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b567b13b593ec58ea912b2658ee6230ffe20a069fa5b771800acc69bb3a157e" +dependencies = [ + "cmake", +] + +[[package]] +name = "hermit-abi" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" +dependencies = [ + "libc", +] + +[[package]] +name = "image" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef4e336ec01a678e7ab692914c641181528e8656451e6252f8f9e33728882eaf" +dependencies = [ + "bytemuck", + "byteorder", + "gif", + "jpeg-decoder", + "num-iter", + "num-rational", + "num-traits", + "png", + "scoped_threadpool", + "tiff", +] + +[[package]] +name = "inflate" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" +dependencies = [ + "adler32", +] + +[[package]] +name = "jpeg-decoder" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0256f0aec7352539102a9efbcb75543227b7ab1117e0f95450023af730128451" +dependencies = [ + "byteorder", + "rayon", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" + +[[package]] +name = "libm" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "lzw" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "matrixmultiply" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4f7ec66360130972f34830bfad9ef05c6610a43938a467bcc9ab9369ab3478f" +dependencies = [ + "rawpointer", +] + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + +[[package]] +name = "memoffset" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "miniz_oxide" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" +dependencies = [ + "adler32", +] + +[[package]] +name = "nalgebra" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6511777ed3da44b6a11e732a66a7d6274dfbbcd68ad968e64b778dcb829d94a" +dependencies = [ + "alga", + "approx", + "generic-array", + "matrixmultiply", + "num-complex", + "num-rational", + "num-traits", + "rand", + "rand_distr", + "typenum", +] + +[[package]] +name = "nalgebra-glm" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ae78da13d67be0d2e4ab567490477e4c9f314fc151ddfff6713b15bdbb2aa72" +dependencies = [ + "alga", + "approx", + "nalgebra", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "png" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef859a23054bbfee7811284275ae522f0434a3c8e7f4b74bd4a35ae7e1c4a283" +dependencies = [ + "bitflags", + "crc32fast", + "deflate", + "inflate", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" + +[[package]] +name = "proc-macro2" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "proc_macro_roids" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06675fa2c577f52bcf77fbb511123927547d154faa08097cc012c66ec3c9611a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +dependencies = [ + "c2-chacha", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_distr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2" +dependencies = [ + "rand", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + +[[package]] +name = "raw-window-handle" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211" +dependencies = [ + "libc", +] + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "rayon" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" +dependencies = [ + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "syn" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tiff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "002351e428db1eb1d8656d4ca61947c3519ac3191e1c804d4600cd32093b77ad" +dependencies = [ + "byteorder", + "lzw", + "miniz_oxide", +] + +[[package]] +name = "triangle-time" +version = "0.1.0" +dependencies = [ + "eatgel", + "gl", + "glfw", + "image", + "nalgebra-glm", +] + +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "xml-rs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..911daf5 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["triangle-time", "eatgel", "eatgel-proc-macro", "eatgel-graph"] diff --git a/eatgel-graph/Cargo.toml b/eatgel-graph/Cargo.toml new file mode 100644 index 0000000..c28fd1e --- /dev/null +++ b/eatgel-graph/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "eatgel-graph" +version = "0.1.0" +authors = ["eater <=@eater.me>"] +edition = "2018" + +[dependencies] +nalgebra-glm = "0.6.0" \ No newline at end of file diff --git a/eatgel-graph/src/lib.rs b/eatgel-graph/src/lib.rs new file mode 100644 index 0000000..2a99042 --- /dev/null +++ b/eatgel-graph/src/lib.rs @@ -0,0 +1,95 @@ +use nalgebra_glm::{identity, vec3, Mat4, Vec3, U4}; +use std::cell::{Ref, RefCell}; +use std::rc::Rc; + +struct Graph { + root: NodeRef, +} + +impl Graph { + fn new() -> Graph { + let mut node = Node::new(); + node.is_root = true; + Graph { + root: node.into_ref(), + } + } +} + +type NodeRef = Rc>; + +trait NodeExt { + fn append_child(&self, child: &NodeRef); + fn remove_child(&self, child: &NodeRef); +} + +struct Node { + rotation: Vec3, + transform: Mat4, + origin: Vec3, + absolute_position: Option, + children: Vec, + parent: Option, + is_root: bool, +} + +impl Node { + fn new() -> Node { + Node { + rotation: vec3(0.0, 0.0, 0.0), + transform: identity::<_, U4>(), + origin: vec3(0.0, 0.0, 0.0), + absolute_position: None, + children: vec![], + parent: None, + is_root: false, + } + } + + fn into_ref(self) -> NodeRef { + Rc::new(RefCell::new(self)) + } +} + +impl NodeExt for NodeRef { + fn append_child(&self, child: &NodeRef) { + if Rc::ptr_eq(&self, child) { + return; + } + + if let Some(parent) = child.borrow().parent.clone() { + parent.remove_child(&self) + } + + self.borrow_mut().children.push(child.clone()) + } + + fn remove_child(&self, child: &NodeRef) { + let children = &mut self.borrow_mut().children; + let mut offset: usize = 0; + for i in 0..childs.len() { + if Rc::ptr_eq(&childs[i - offset], child) { + children.remove(i - offset); + offset += 1; + } + } + } +} + +#[cfg(test)] +pub mod test { + use crate::*; + + #[test] + pub fn it_works() { + let node = Node::new().into_ref(); + node.append_child(&node); + node.remove_child(&node); + let second_node = Node::new().into_ref(); + node.append_child(&second_node); + + let graph = Graph::new(); + graph.root.append_child(&node); + assert_eq!(1, graph.root.borrow().children.len()); + } +} diff --git a/eatgel-proc-macro/Cargo.toml b/eatgel-proc-macro/Cargo.toml new file mode 100644 index 0000000..d3a6661 --- /dev/null +++ b/eatgel-proc-macro/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "eatgel-proc-macro" +version = "0.1.0" +authors = ["eater <=@eater.me>"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +proc-macro = true + +[dependencies] +proc_macro_roids = "0.7.0" +proc-macro2 = "1.0.9" +syn = "1.0.16" +quote = "1.0.3" \ No newline at end of file diff --git a/eatgel-proc-macro/src/lib.rs b/eatgel-proc-macro/src/lib.rs new file mode 100644 index 0000000..3b65d7d --- /dev/null +++ b/eatgel-proc-macro/src/lib.rs @@ -0,0 +1,191 @@ +extern crate proc_macro; + +use proc_macro::{Literal, TokenStream, TokenTree}; +use proc_macro_roids::{DeriveInputStructExt, FieldExt}; +use quote::quote; +use std::str::FromStr; + +use proc_macro2::TokenStream as TokenStream2; +use syn::{parse_macro_input, parse_quote, DeriveInput}; + +#[proc_macro_derive(ShaderData, attributes(skip))] +pub fn derive_shader_data(token_stream: TokenStream) -> TokenStream { + let mut iter = token_stream.into_iter(); + let empty = TokenStream::new(); + + if let Some(TokenTree::Ident(ident)) = iter.next() { + if ident.to_string() != "struct" { + return empty; + } + } else { + return empty; + } + + let struct_name = if let Some(TokenTree::Ident(ident)) = iter.next() { + ident.to_string() + } else { + return empty; + }; + + let mut group = if let Some(TokenTree::Group(group)) = iter.next() { + group + } else { + return empty; + } + .stream() + .into_iter(); + + let mut keys = vec![]; + + loop { + let item = group.next(); + if item.is_none() { + break; + } + + let item = item.unwrap(); + + if item.to_string() == "#" { + if let Some(TokenTree::Group(tag)) = group.next() { + if tag.to_string() == "[skip]" { + while let Some(x) = group.next() { + if x.to_string() == "," { + break; + } + } + } + continue; + } else { + break; + } + } + + let name = match item { + TokenTree::Ident(ident) => ident.to_string(), + _ => break, + }; + + // : + group.next(); + let mut stream = vec![]; + while let Some(x) = group.next() { + if x.to_string() == "," { + break; + } + + stream.push(x); + } + + keys.push(name); + } + + let init = keys + .iter() + .map(|name| Literal::string(&name).to_string()) + .collect::>() + .join(", "); + + let mut index = -1; + + let apply = keys + .iter() + .map(|name| { + index += 1; + + format!( + "(gl as &dyn UpdateUniform<_>).update_uniform_by_index(gl, program_id, {}, &self.{});", + index, + name + ) + }) + .collect::>() + .join("\n"); + + let gen_source = format!( + r#" +impl ::eatgel::ShaderData for {} {{ + fn init(&mut self, gl: &mut ::eatgel::GlContext, program_id: u32) {{ + gl.register_uniforms(program_id, &[{}]); + }} + fn apply(&self, gl: &::eatgel::GlContext, program_id: u32) {{ + {} + }} +}} +"#, + struct_name, init, apply, + ); + + TokenStream::from_str(&gen_source).unwrap() +} + +#[proc_macro_derive(VertexData, attributes(skip))] +pub fn derive_vertex_data(token_stream: TokenStream) -> TokenStream { + let ast = parse_macro_input!(token_stream as DeriveInput); + let name = &ast.ident; + + let mut index = -1; + let fields = ast + .fields() + .iter() + .map(move |field| { + index += 1; + let name = index; + (name, field) + }) + .filter(|(_, field)| !field.is_phantom_data()) + .filter(|(_, field)| !field.contains_tag(&parse_quote!(vertex_data), &parse_quote!(skip))); + + let sizes = fields + .clone() + .map(|(_, field)| { + let type_name = field.type_name(); + + quote!( + ::std::mem::size_of::<#type_name>() + ) + }) + .collect::>(); + + let types = fields + .clone() + .map(|(_, field)| { + let type_name = field.type_name(); + + quote!( + ::eatgel::type_descriptor_of::<#type_name>() + ) + }) + .collect::>(); + + let pointers = fields + .map(|(index, field)| { + if let Some(name) = field.ident.as_ref() { + quote!( + self.#name.as_ptr() as *const ::std::ffi::c_void + ) + } else { + quote!( + self.#index.as_ptr() as *const ::std::ffi::c_void + ) + } + }) + .collect::>(); + + let token_stream2: TokenStream2 = quote!( + impl ::eatgel::VertexData for #name { + fn get_sizes() -> Box<[usize]> { + return vec![#(#sizes,)*].into_boxed_slice() + } + + fn get_types() -> Box<[::eatgel::TypeDescriptor]> { + return vec![#(#types,)*].into_boxed_slice() + } + + fn get_pointers(&self) -> Box<[*const ::std::ffi::c_void]> { + return vec![#(#pointers,)*].into_boxed_slice() + } + } + ); + + token_stream2.into() +} diff --git a/eatgel/.gitignore b/eatgel/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/eatgel/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/eatgel/Cargo.toml b/eatgel/Cargo.toml new file mode 100644 index 0000000..0bd24f4 --- /dev/null +++ b/eatgel/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "eatgel" +version = "0.1.0" +authors = ["eater <=@eater.me>"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +gl = "0.14.0" +nalgebra-glm = "0.6.0" +nalgebra = "0.20.0" +image = "0.23.0" +eatgel-proc-macro = { path = "../eatgel-proc-macro", optional = true } + +[features] +derive = ["eatgel-proc-macro"] +default = ["derive"] \ No newline at end of file diff --git a/eatgel/src/buffer.rs b/eatgel/src/buffer.rs new file mode 100644 index 0000000..978e002 --- /dev/null +++ b/eatgel/src/buffer.rs @@ -0,0 +1,185 @@ +use crate::types::TypeDescriptor; +use std::ffi::c_void; +use std::ops::Range; + +pub struct StaticBufferNonIndexed { + pub vao: u32, + pub attributes: Vec, + pub elements: usize, +} + +impl StaticBufferNonIndexed { + pub fn bind(&self) { + unsafe { + gl::BindVertexArray(self.vao); + } + } + + pub fn draw(&self) { + self.bind(); + + unsafe { gl::DrawArrays(gl::TRIANGLES, 0, self.elements as i32) } + } +} + +pub struct StaticBuffer { + pub vao: u32, + pub attributes: Vec, + pub ebo: u32, + pub indices: usize, +} + +impl StaticBuffer { + pub fn bind(&self) { + unsafe { + gl::BindVertexArray(self.vao); + gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo); + } + } + + pub fn draw(&self) { + self.bind(); + + unsafe { + gl::DrawElements( + gl::TRIANGLES, + self.indices as i32, + gl::UNSIGNED_INT, + 0 as *const c_void, + ) + } + } +} + +impl Drop for StaticBuffer { + fn drop(&mut self) { + unsafe { gl::DeleteVertexArrays(1, [self.vao].as_ptr()) } + } +} + +pub struct Attributes { + mem: Box<[u8]>, + pub attributes: Vec, + pub size: usize, + pub elements: usize, +} + +impl Attributes { + pub fn as_ptr(&self) -> *const c_void { + self.mem.as_ptr() as *const c_void + } +} + +pub struct Attribute { + pub amount: usize, + pub stride: usize, + pub offset: usize, + pub gl_type: u32, +} + +pub trait VertexData { + fn get_sizes() -> Box<[usize]>; + fn get_types() -> Box<[TypeDescriptor]>; + fn get_pointers(&self) -> Box<[*const c_void]>; +} + +pub trait VertexDataCollection +where + D: VertexData, +{ + fn get_amount(&self) -> usize; + fn get_list(&self) -> &[D]; + fn create_ptr(&self, interleaved: bool, range: Option>) -> Attributes { + let sizes = D::get_sizes(); + let struct_size = sizes.clone().iter().sum(); + let range = range.unwrap_or(0..self.get_amount()); + let amount = range.end - range.start; + let mut list = vec![0u8; struct_size * amount]; + let items = self.get_list(); + + for i in range.clone() { + let item = &items[i]; + let pointers = item.get_pointers(); + let sizes_and_pointers = sizes + .iter() + .zip(pointers.iter()) + .collect::>(); + + let mut offset = 0; + + for (size, ptr) in sizes_and_pointers { + let index = if interleaved { + offset + (struct_size * (i - range.start)) + } else { + (offset * amount) + size * i + }; + + unsafe { + std::ptr::copy(ptr.cast(), list.as_mut_ptr().add(index), *size); + } + + offset += size; + } + } + + let mut attributes = vec![]; + let mut offset = 0; + for (size, type_desc) in sizes.iter().zip(D::get_types().iter()) { + attributes.push(Attribute { + amount: type_desc.amount as usize, + gl_type: type_desc.gl_type, + stride: if interleaved { struct_size } else { *size }, + offset: if interleaved { offset } else { offset * amount }, + }); + + offset += *size; + } + + Attributes { + mem: list.into_boxed_slice(), + attributes, + size: struct_size * amount, + elements: items.len(), + } + } +} + +impl VertexDataCollection for Vec { + fn get_amount(&self) -> usize { + self.len() + } + + fn get_list(&self) -> &[D] { + &self + } +} + +impl VertexDataCollection for &[D] { + fn get_amount(&self) -> usize { + self.len() + } + + fn get_list(&self) -> &[D] { + self + } +} + +impl VertexDataCollection for Box<[D]> { + fn get_amount(&self) -> usize { + self.len() + } + + fn get_list(&self) -> &[D] { + &self + } +} + +impl VertexDataCollection for [D] { + fn get_amount(&self) -> usize { + self.len() + } + + fn get_list(&self) -> &[D] { + &self + } +} diff --git a/eatgel/src/err.rs b/eatgel/src/err.rs new file mode 100644 index 0000000..a106de5 --- /dev/null +++ b/eatgel/src/err.rs @@ -0,0 +1,31 @@ +use image::ImageError; +use std::ffi::NulError; +use std::str::Utf8Error; + +#[derive(Debug)] +pub enum Error { + ShaderContainsNul(NulError), + ShaderCompilationFailure(String), + ShaderProgramLinkFailure(String), + InfoLogEncodingError(Utf8Error), + TextureLoadError(ImageError), + TextureParseError, +} + +impl From for Error { + fn from(utf8err: Utf8Error) -> Self { + Error::InfoLogEncodingError(utf8err) + } +} + +impl From for Error { + fn from(nul_err: NulError) -> Self { + Error::ShaderContainsNul(nul_err) + } +} + +impl From for Error { + fn from(image_err: ImageError) -> Self { + Error::TextureLoadError(image_err) + } +} diff --git a/eatgel/src/lib.rs b/eatgel/src/lib.rs new file mode 100644 index 0000000..556dabc --- /dev/null +++ b/eatgel/src/lib.rs @@ -0,0 +1,217 @@ +use std::ffi::{c_void, CStr, CString}; + +pub mod buffer; +mod err; +pub mod shader; +pub mod texture; +mod types; +mod update_uniform; + +use crate::buffer::{Attributes, StaticBufferNonIndexed}; +use buffer::StaticBuffer; +pub use buffer::{VertexData, VertexDataCollection}; +#[cfg(feature = "derive")] +pub use eatgel_proc_macro::{ShaderData, VertexData}; +pub use shader::ShaderData; +use std::collections::HashMap; +use std::mem::size_of; +use std::ptr::null; +pub use types::{amount_of, type_descriptor_of, type_of, TypeDescriptor, TypeResolver}; +pub use update_uniform::*; + +pub struct GlContext { + cache: HashMap>, + clear_color: [f32; 4], +} + +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +enum Severity { + Low = gl::DEBUG_SEVERITY_LOW, + Medium = gl::DEBUG_SEVERITY_MEDIUM, + High = gl::DEBUG_SEVERITY_HIGH, + Notification = gl::DEBUG_SEVERITY_NOTIFICATION, +} + +impl From for Severity { + fn from(x: u32) -> Self { + match x { + gl::DEBUG_SEVERITY_LOW => Severity::Low, + gl::DEBUG_SEVERITY_MEDIUM => Severity::Medium, + gl::DEBUG_SEVERITY_HIGH => Severity::High, + _ => Severity::Notification, + } + } +} + +extern "system" fn gl_message_callback( + _source: u32, + _error_type: u32, + _id: u32, + severity: u32, + _length: i32, + message: *const i8, + _user_data: *mut c_void, +) { + unsafe { + println!( + "Message ({:?}): {:?}", + Severity::from(severity), + CStr::from_ptr(message) + ); + } +} + +impl GlContext { + pub fn new(f: F) -> Self + where + F: FnMut(&'static str) -> *const c_void, + { + gl::load_with(f); + + unsafe { + gl::Enable(gl::DEBUG_OUTPUT); + gl::DebugMessageCallback(Some(gl_message_callback), null()) + } + + GlContext { + cache: HashMap::new(), + clear_color: [0., 0., 0., 0.], + } + } + + pub fn set_clear_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) { + self.clear_color = [red, green, blue, alpha]; + } + + pub fn clear(&self) { + unsafe { + gl::ClearColor( + self.clear_color[0], + self.clear_color[1], + self.clear_color[2], + self.clear_color[3], + ); + gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT); + } + } + + pub fn get_uniform_location(&self, program_id: u32, name: &str) -> i32 { + let name = CString::new(name).expect("Failed creating CString from &str"); + unsafe { gl::GetUniformLocation(program_id, name.as_ptr()) } + } + + pub fn register_uniforms(&mut self, program_id: u32, uniforms: &[&str]) { + let mut ids = vec![]; + + for name in uniforms { + unsafe { + ids.push(gl::GetUniformLocation( + program_id, + CString::new(name.to_string()) + .expect("Nul character in uniform name") + .as_ptr(), + )) + } + } + + self.cache.insert(program_id, ids.into_boxed_slice()); + } + + pub fn get_uniform_location_by_index(&self, program_id: u32, index: usize) -> i32 { + self.cache.get(&program_id).map(|x| x[index]).unwrap_or(-1) + } + + unsafe fn create_attribs(&self, attributes: &Attributes) { + let mut index = 0; + for attribute in &attributes.attributes { + gl::VertexAttribPointer( + index, + attribute.amount as i32, + attribute.gl_type, + gl::FALSE, + attribute.stride as i32, + attribute.offset as *const c_void, + ); + gl::EnableVertexAttribArray(index); + + index += 1; + } + } + + pub fn create_static_buffer_non_indexed, D: VertexData>( + &self, + buffer: C, + ) -> StaticBufferNonIndexed { + let attributes = buffer.create_ptr(false, None); + let mut vbo = 0; + let mut vao = 0; + + unsafe { + gl::GenVertexArrays(1, &mut vao); + gl::GenBuffers(1, &mut vbo); + + gl::BindVertexArray(vao); + + gl::BindBuffer(gl::ARRAY_BUFFER, vbo); + gl::BufferData( + gl::ARRAY_BUFFER, + attributes.size as isize, + attributes.as_ptr(), + gl::STATIC_DRAW, + ); + + self.create_attribs(&attributes) + } + + StaticBufferNonIndexed { + vao, + elements: attributes.elements, + attributes: attributes.attributes, + } + } + + pub fn create_static_buffer, D: VertexData>( + &self, + buffer: C, + indices: &[u32], + ) -> StaticBuffer { + let attributes = buffer.create_ptr(false, None); + let mut vbo = 0; + let mut vao = 0; + let mut ebo = 0; + + unsafe { + gl::GenVertexArrays(1, &mut vao); + gl::GenBuffers(1, &mut vbo); + gl::GenBuffers(1, &mut ebo); + + gl::BindVertexArray(vao); + + gl::BindBuffer(gl::ARRAY_BUFFER, vbo); + gl::BufferData( + gl::ARRAY_BUFFER, + attributes.size as isize, + attributes.as_ptr(), + gl::STATIC_DRAW, + ); + + self.create_attribs(&attributes); + + gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo); + gl::BufferData( + gl::ELEMENT_ARRAY_BUFFER, + (size_of::() * indices.len()) as isize, + indices.as_ptr() as *const c_void, + gl::STATIC_DRAW, + ); + } + + StaticBuffer { + vao, + ebo, + indices: indices.len(), + attributes: attributes.attributes, + } + } +} diff --git a/eatgel/src/shader.rs b/eatgel/src/shader.rs new file mode 100644 index 0000000..fa3d837 --- /dev/null +++ b/eatgel/src/shader.rs @@ -0,0 +1,144 @@ +use crate::err::Error; +use crate::GlContext; +use std::ffi::CString; +use std::ops::{Deref, DerefMut}; +use std::os::raw::c_char; +use std::ptr::null; +use std::str::from_utf8; + +pub trait ShaderData { + fn init(&mut self, gl: &mut GlContext, program_id: u32); + fn apply(&self, gl: &GlContext, program_id: u32); +} + +impl ShaderData for () { + fn init(&mut self, _gl: &mut GlContext, _program_id: u32) {} + fn apply(&self, _gl: &GlContext, _program_id: u32) {} +} + +pub struct ShaderProgram { + pub program_id: u32, + data: D, +} + +impl ShaderProgram { + pub fn init(&mut self, gl: &mut GlContext) { + self.data.init(gl, self.program_id); + } + + pub fn apply(&self, gl: &GlContext) { + self.data.apply(gl, self.program_id); + } +} + +impl Deref for ShaderProgram { + type Target = D; + + fn deref(&self) -> &Self::Target { + &self.data + } +} + +impl DerefMut for ShaderProgram { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.data + } +} + +pub struct Shader(pub u32); + +impl Drop for Shader { + fn drop(&mut self) { + unsafe { gl::DeleteShader(self.0) } + } +} + +#[repr(u32)] +pub enum ShaderType { + Vertex = gl::VERTEX_SHADER, + Fragment = gl::FRAGMENT_SHADER, +} + +impl Shader { + pub fn compile(shader_type: ShaderType, source: &str) -> Result { + let shader_id = unsafe { gl::CreateShader(shader_type as u32) }; + let source = CString::new(source.as_bytes())?; + unsafe { + gl::ShaderSource(shader_id, 1, &source.as_ptr(), null()); + gl::CompileShader(shader_id); + let mut success = 0; + gl::GetShaderiv(shader_id, gl::COMPILE_STATUS, &mut success); + + if success != 1 { + let mut log_length = 0; + gl::GetShaderiv(shader_id, gl::INFO_LOG_LENGTH, &mut log_length); + let mut log = Vec::with_capacity(log_length as usize); + let mut len = 0; + gl::GetShaderInfoLog( + shader_id, + log_length, + &mut len, + log.as_mut_ptr() as *mut c_char, + ); + log.set_len(len as usize); + + return Err(Error::ShaderCompilationFailure( + from_utf8(&log)?.to_string(), + )); + } + } + + Ok(Shader(shader_id)) + } +} + +impl ShaderProgram<()> { + pub fn create(shader0: Shader, shader1: Shader) -> Result, Error> { + ShaderProgram::create_with_data((), shader0, shader1) + } +} + +impl ShaderProgram { + pub fn enable(&self) { + unsafe { gl::UseProgram(self.program_id) } + } + + pub fn create_with_data( + data: D, + shader0: Shader, + shader1: Shader, + ) -> Result, Error> { + unsafe { + let program_id = gl::CreateProgram(); + gl::AttachShader(program_id, shader0.0); + gl::AttachShader(program_id, shader1.0); + gl::LinkProgram(program_id); + + let mut status = 0; + gl::GetProgramiv(program_id, gl::LINK_STATUS, &mut status); + if status != 1 { + let mut log_length = 0; + gl::GetProgramiv(program_id, gl::INFO_LOG_LENGTH, &mut log_length); + let mut log = Vec::with_capacity(log_length as usize); + let mut len = 0; + gl::GetProgramInfoLog( + program_id, + log_length, + &mut len, + log.as_mut_ptr() as *mut c_char, + ); + + log.set_len(len as usize); + + return Err(Error::ShaderProgramLinkFailure( + from_utf8(&log)?.to_string(), + )); + } + + gl::DeleteShader(shader0.0); + gl::DeleteShader(shader1.0); + + Ok(ShaderProgram { data, program_id }) + } + } +} diff --git a/eatgel/src/texture.rs b/eatgel/src/texture.rs new file mode 100644 index 0000000..429bb0f --- /dev/null +++ b/eatgel/src/texture.rs @@ -0,0 +1,180 @@ +use crate::err::Error; +pub use image::{ColorType, ImageFormat}; +use image::{DynamicImage, GenericImageView}; +use nalgebra_glm::Vec4; +use std::io::{BufRead, Seek}; +use std::os::raw::c_void; + +#[repr(u32)] +#[derive(Copy, Clone, Debug)] +pub enum WrapStyle { + Repeat = gl::REPEAT, + MirroredRepeat = gl::MIRRORED_REPEAT, + ClampToEdge = gl::CLAMP_TO_EDGE, + ClampToBorder = gl::CLAMP_TO_BORDER, +} + +#[repr(u32)] +#[derive(Copy, Clone, Debug)] +pub enum FilterStyle { + Nearest = gl::NEAREST, + Linear = gl::LINEAR, +} + +impl FilterStyle { + fn get_gl_enum(filter: FilterStyle, mipmap: Option) -> i32 { + let gl_enum = match (filter, mipmap) { + (FilterStyle::Nearest, None) => gl::NEAREST, + (FilterStyle::Linear, None) => gl::LINEAR, + (FilterStyle::Linear, Some(FilterStyle::Linear)) => gl::LINEAR_MIPMAP_LINEAR, + (FilterStyle::Linear, Some(FilterStyle::Nearest)) => gl::LINEAR_MIPMAP_NEAREST, + (FilterStyle::Nearest, Some(FilterStyle::Linear)) => gl::NEAREST_MIPMAP_LINEAR, + (FilterStyle::Nearest, Some(FilterStyle::Nearest)) => gl::NEAREST_MIPMAP_NEAREST, + }; + + gl_enum as i32 + } +} + +#[derive(Clone, Debug)] +pub struct Texture { + image_id: u32, + options: TextureOptions, +} + +pub struct Image { + pub image: DynamicImage, +} + +impl Image { + pub fn load(r: R, format: ImageFormat) -> Result { + Ok(Image { + image: image::load(r, format)?, + }) + } + + pub fn into_texture(mut self, options: TextureOptions) -> Result { + let mut image_id = 0; + unsafe { + gl::GenTextures(1, &mut image_id); + gl::BindTexture(gl::TEXTURE_2D, image_id); + gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, options.wrap_s as i32); + gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, options.wrap_t as i32); + gl::TexParameteri( + gl::TEXTURE_2D, + gl::TEXTURE_MAG_FILTER, + FilterStyle::get_gl_enum(options.mag_filter, options.mag_mipmap_filter), + ); + gl::TexParameteri( + gl::TEXTURE_2D, + gl::TEXTURE_MAG_FILTER, + FilterStyle::get_gl_enum(options.min_filter, options.min_mipmap_filter), + ); + + if let Some((_, ref border)) = options.border { + gl::TexParameterfv(gl::TEXTURE_2D, gl::TEXTURE_BORDER_COLOR, border.as_ptr()) + } + + if options.flip_vertically { + self.image = self.image.flipv() + } + let pixels = self + .image + .pixels() + .into_iter() + .flat_map(|x| vec![x.2[0], x.2[1], x.2[2], x.2[3]]) + .collect::>(); + + let width = self.image.width(); + let height = self.image.height(); + + gl::TexImage2D( + gl::TEXTURE_2D, + 0, + gl::RGBA as i32, + width as i32, + height as i32, + 0, + gl::RGBA, + gl::UNSIGNED_BYTE, + pixels.as_ptr() as *const c_void, + ); + gl::GenerateMipmap(gl::TEXTURE_2D); + } + + Ok(Texture { image_id, options }) + } +} + +#[derive(Clone, Debug)] +pub struct TextureOptions { + wrap_s: WrapStyle, + wrap_t: WrapStyle, + border: Option<(i32, Vec4)>, + mag_filter: FilterStyle, + min_filter: FilterStyle, + min_mipmap_filter: Option, + mag_mipmap_filter: Option, + flip_vertically: bool, +} + +impl Default for TextureOptions { + fn default() -> Self { + TextureOptions { + wrap_s: WrapStyle::Repeat, + wrap_t: WrapStyle::Repeat, + border: None, + mag_filter: FilterStyle::Linear, + min_filter: FilterStyle::Linear, + min_mipmap_filter: None, + mag_mipmap_filter: None, + flip_vertically: true, + } + } +} + +#[repr(u32)] +#[derive(Debug, Copy, Clone)] +pub enum TextureSlot { + Slot0 = gl::TEXTURE0, + Slot1 = gl::TEXTURE1, + Slot2 = gl::TEXTURE2, + Slot3 = gl::TEXTURE3, + Slot4 = gl::TEXTURE4, + Slot5 = gl::TEXTURE5, + Slot6 = gl::TEXTURE6, + Slot7 = gl::TEXTURE7, + Slot8 = gl::TEXTURE8, + Slot9 = gl::TEXTURE9, + Slot10 = gl::TEXTURE10, + Slot11 = gl::TEXTURE11, + Slot12 = gl::TEXTURE12, + Slot13 = gl::TEXTURE13, + Slot14 = gl::TEXTURE14, + Slot15 = gl::TEXTURE15, + Slot16 = gl::TEXTURE16, + Slot17 = gl::TEXTURE17, + Slot18 = gl::TEXTURE18, + Slot19 = gl::TEXTURE19, + Slot20 = gl::TEXTURE20, + Slot21 = gl::TEXTURE21, + Slot22 = gl::TEXTURE22, + Slot23 = gl::TEXTURE23, + Slot24 = gl::TEXTURE24, + Slot25 = gl::TEXTURE25, + Slot26 = gl::TEXTURE26, + Slot27 = gl::TEXTURE27, + Slot28 = gl::TEXTURE28, + Slot29 = gl::TEXTURE29, + Slot30 = gl::TEXTURE30, + Slot31 = gl::TEXTURE31, +} + +impl Texture { + pub fn enable(&self, slot: TextureSlot) { + unsafe { + gl::ActiveTexture(slot as u32); + gl::BindTexture(gl::TEXTURE_2D, self.image_id); + } + } +} diff --git a/eatgel/src/types.rs b/eatgel/src/types.rs new file mode 100644 index 0000000..97bbd18 --- /dev/null +++ b/eatgel/src/types.rs @@ -0,0 +1,120 @@ +use nalgebra_glm::{Vec2, Vec3, Vec4}; + +pub trait TypeResolver { + fn type_of() -> u32; + fn amount_of() -> u32; + fn get_type_descriptor() -> TypeDescriptor { + TypeDescriptor { + gl_type: Self::type_of(), + amount: Self::amount_of(), + } + } +} + +#[derive(Debug, Copy, Clone)] +pub struct TypeDescriptor { + pub gl_type: u32, + pub amount: u32, +} + +pub fn type_descriptor_of() -> TypeDescriptor { + T::get_type_descriptor() +} + +pub fn type_of() -> u32 { + T::type_of() +} + +pub fn amount_of() -> u32 { + T::amount_of() +} + +impl TypeResolver for bool { + fn type_of() -> u32 { + gl::UNSIGNED_BYTE + } + fn amount_of() -> u32 { + 1 + } +} + +impl TypeResolver for u8 { + fn type_of() -> u32 { + gl::UNSIGNED_BYTE + } + fn amount_of() -> u32 { + 1 + } +} + +impl TypeResolver for i8 { + fn type_of() -> u32 { + gl::BYTE + } + fn amount_of() -> u32 { + 1 + } +} + +impl TypeResolver for u16 { + fn type_of() -> u32 { + gl::UNSIGNED_SHORT + } + fn amount_of() -> u32 { + 1 + } +} + +impl TypeResolver for i16 { + fn type_of() -> u32 { + gl::SHORT + } + fn amount_of() -> u32 { + 1 + } +} + +impl TypeResolver for u32 { + fn type_of() -> u32 { + gl::UNSIGNED_INT + } + fn amount_of() -> u32 { + 1 + } +} + +impl TypeResolver for i32 { + fn type_of() -> u32 { + gl::INT + } + fn amount_of() -> u32 { + 1 + } +} + +impl TypeResolver for Vec2 { + fn type_of() -> u32 { + gl::FLOAT + } + fn amount_of() -> u32 { + 2 + } +} + +impl TypeResolver for Vec3 { + fn type_of() -> u32 { + gl::FLOAT + } + fn amount_of() -> u32 { + 3 + } +} + +impl TypeResolver for Vec4 { + fn type_of() -> u32 { + gl::FLOAT + } + fn amount_of() -> u32 { + 4 + } +} diff --git a/eatgel/src/update_uniform.rs b/eatgel/src/update_uniform.rs new file mode 100644 index 0000000..c3796c2 --- /dev/null +++ b/eatgel/src/update_uniform.rs @@ -0,0 +1,342 @@ +use crate::texture::TextureSlot; +use crate::GlContext; +use nalgebra_glm::{Mat3, Mat4}; +use std::convert::From; +use std::ptr::null; + +pub trait UpdateUniform { + fn update_uniform(&self, location: i32, value: T); + fn update_uniform_by_index(&self, gl: &GlContext, program_id: u32, index: usize, value: T) { + self.update_uniform(gl.get_uniform_location_by_index(program_id, index), value) + } +} + +impl UpdateUniform for GlContext { + fn update_uniform(&self, location: i32, value: i32) { + unsafe { gl::Uniform1i(location, value) } + } +} + +impl UpdateUniform<&i32> for GlContext { + fn update_uniform(&self, location: i32, value: &i32) { + unsafe { gl::Uniform1i(location, *value) } + } +} + +impl UpdateUniform<&Vec> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec) { + unsafe { gl::Uniform1iv(location, value.len() as i32, value.as_ptr()) } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec2> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec2) { + unsafe { gl::Uniform2i(location, value.x, value.y) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform2iv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec3> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec3) { + unsafe { gl::Uniform3i(location, value.x, value.y, value.z) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform3iv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec4> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec4) { + unsafe { gl::Uniform4i(location, value.x, value.y, value.z, value.w) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform4iv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform for GlContext { + fn update_uniform(&self, location: i32, value: u32) { + unsafe { gl::Uniform1ui(location, value) } + } +} + +impl UpdateUniform<&u32> for GlContext { + fn update_uniform(&self, location: i32, value: &u32) { + unsafe { gl::Uniform1ui(location, *value) } + } +} + +impl UpdateUniform<&Vec> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec) { + unsafe { gl::Uniform1uiv(location, value.len() as i32, value.as_ptr()) } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec2> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec2) { + unsafe { gl::Uniform2ui(location, value.x, value.y) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform2uiv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec3> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec3) { + unsafe { gl::Uniform3ui(location, value.x, value.y, value.z) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform3uiv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec4> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec4) { + unsafe { gl::Uniform4ui(location, value.x, value.y, value.z, value.w) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform4uiv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform for GlContext { + fn update_uniform(&self, location: i32, value: f32) { + unsafe { gl::Uniform1f(location, value) } + } +} + +impl UpdateUniform<&f32> for GlContext { + fn update_uniform(&self, location: i32, value: &f32) { + unsafe { gl::Uniform1f(location, *value) } + } +} + +impl UpdateUniform<&Vec> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec) { + unsafe { gl::Uniform1fv(location, value.len() as i32, value.as_ptr()) } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec1> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec1) { + unsafe { gl::Uniform1f(location, value.x) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform1fv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec2> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec2) { + unsafe { gl::Uniform2f(location, value.x, value.y) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform2fv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec3> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec3) { + unsafe { gl::Uniform3f(location, value.x, value.y, value.z) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform3fv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec4> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec4) { + unsafe { gl::Uniform4f(location, value.x, value.y, value.z, value.w) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform4fv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform for GlContext { + fn update_uniform(&self, location: i32, value: f64) { + unsafe { gl::Uniform1d(location, value) } + } +} + +impl UpdateUniform<&f64> for GlContext { + fn update_uniform(&self, location: i32, value: &f64) { + unsafe { gl::Uniform1d(location, *value) } + } +} + +impl UpdateUniform<&Vec> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec) { + unsafe { gl::Uniform1dv(location, value.len() as i32, value.as_ptr()) } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec1> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec1) { + unsafe { gl::Uniform1d(location, value.x) } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec2> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec2) { + unsafe { gl::Uniform2d(location, value.x, value.y) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform2dv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec3> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec3) { + unsafe { gl::Uniform3d(location, value.x, value.y, value.z) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform3dv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform<&nalgebra_glm::TVec4> for GlContext { + fn update_uniform(&self, location: i32, value: &nalgebra_glm::TVec4) { + unsafe { gl::Uniform4d(location, value.x, value.y, value.z, value.w) } + } +} + +impl UpdateUniform<&Vec>> for GlContext { + fn update_uniform(&self, location: i32, value: &Vec>) { + unsafe { + gl::Uniform4dv( + location, + value.len() as i32, + value.first().map(|x| x.as_ptr()).unwrap_or(null()), + ) + } + } +} + +impl UpdateUniform<&Mat3> for GlContext { + fn update_uniform(&self, location: i32, value: &Mat3) { + unsafe { gl::UniformMatrix3fv(location, 1, u8::from(false), value.as_ptr()) } + } +} + +impl UpdateUniform<&Mat4> for GlContext { + fn update_uniform(&self, location: i32, value: &Mat4) { + unsafe { gl::UniformMatrix4fv(location, 1, u8::from(false), value.as_ptr()) } + } +} + +impl UpdateUniform<&TextureSlot> for GlContext { + fn update_uniform(&self, location: i32, value: &TextureSlot) { + unsafe { gl::Uniform1i(location, (*value as i32) - 0x84C0) } + } +} diff --git a/triangle-time/.gitignore b/triangle-time/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/triangle-time/.gitignore @@ -0,0 +1 @@ +/target diff --git a/triangle-time/Cargo.lock b/triangle-time/Cargo.lock new file mode 100644 index 0000000..0963761 --- /dev/null +++ b/triangle-time/Cargo.lock @@ -0,0 +1,388 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "alga" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f823d037a7ec6ea2197046bafd4ae150e6bc36f9ca347404f46a46823fa84f2" +dependencies = [ + "approx", + "num-complex", + "num-traits", +] + +[[package]] +name = "approx" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" +dependencies = [ + "num-traits", +] + +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "c2-chacha" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" +dependencies = [ + "ppv-lite86", +] + +[[package]] +name = "cc" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cmake" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" +dependencies = [ + "cc", +] + +[[package]] +name = "generic-array" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd" +dependencies = [ + "typenum", +] + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gl" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glfw" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b4c1f2e99ce4181c37d9582986ed32a8f55235bdc9427258d96d09cc9666a29" +dependencies = [ + "bitflags", + "glfw-sys", + "libc", + "log", + "objc", + "raw-window-handle", + "semver", + "winapi", +] + +[[package]] +name = "glfw-sys" +version = "3.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b567b13b593ec58ea912b2658ee6230ffe20a069fa5b771800acc69bb3a157e" +dependencies = [ + "cmake", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "libc" +version = "0.2.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" + +[[package]] +name = "libm" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "matrixmultiply" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4f7ec66360130972f34830bfad9ef05c6610a43938a467bcc9ab9369ab3478f" +dependencies = [ + "rawpointer", +] + +[[package]] +name = "nalgebra" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6511777ed3da44b6a11e732a66a7d6274dfbbcd68ad968e64b778dcb829d94a" +dependencies = [ + "alga", + "approx", + "generic-array", + "matrixmultiply", + "num-complex", + "num-rational", + "num-traits", + "rand", + "rand_distr", + "typenum", +] + +[[package]] +name = "nalgebra-glm" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ae78da13d67be0d2e4ab567490477e4c9f314fc151ddfff6713b15bdbb2aa72" +dependencies = [ + "alga", + "approx", + "nalgebra", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +dependencies = [ + "c2-chacha", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_distr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2" +dependencies = [ + "rand", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + +[[package]] +name = "raw-window-handle" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211" +dependencies = [ + "libc", +] + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "triangle-time" +version = "0.1.0" +dependencies = [ + "gl", + "glfw", + "nalgebra-glm", +] + +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "xml-rs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" diff --git a/triangle-time/Cargo.toml b/triangle-time/Cargo.toml new file mode 100644 index 0000000..b163b2a --- /dev/null +++ b/triangle-time/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "triangle-time" +version = "0.1.0" +authors = ["eater <=@eater.me>"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +eatgel = { path = "../eatgel" } +glfw = "0.36.0" +gl = "0.14.0" +nalgebra-glm = "0.6.0" +image = "0.23.0" diff --git a/triangle-time/res/eater.png b/triangle-time/res/eater.png new file mode 100644 index 0000000..fad3db7 Binary files /dev/null and b/triangle-time/res/eater.png differ diff --git a/triangle-time/res/pizza.png b/triangle-time/res/pizza.png new file mode 100644 index 0000000..dea7e03 Binary files /dev/null and b/triangle-time/res/pizza.png differ diff --git a/triangle-time/shaders/simple_fragment.glsl b/triangle-time/shaders/simple_fragment.glsl new file mode 100644 index 0000000..b8c5326 --- /dev/null +++ b/triangle-time/shaders/simple_fragment.glsl @@ -0,0 +1,11 @@ +#version 330 core +out vec4 FragColor; + +in vec2 TexCoord; + +uniform sampler2D our_texture; + +void main() +{ + FragColor = texture(our_texture, TexCoord); +} \ No newline at end of file diff --git a/triangle-time/shaders/simple_vertex.glsl b/triangle-time/shaders/simple_vertex.glsl new file mode 100644 index 0000000..9a2a8c0 --- /dev/null +++ b/triangle-time/shaders/simple_vertex.glsl @@ -0,0 +1,17 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoord; + +out vec2 TexCoord; + +// uniform mat4 transform; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + // note that we read the multiplication from right to left + gl_Position = projection * view * model * vec4(aPos, 1.0); + TexCoord = vec2(aTexCoord.x, aTexCoord.y); +} \ No newline at end of file diff --git a/triangle-time/src/main.rs b/triangle-time/src/main.rs new file mode 100644 index 0000000..a432bc4 --- /dev/null +++ b/triangle-time/src/main.rs @@ -0,0 +1,394 @@ +use eatgel::buffer::StaticBufferNonIndexed; +use eatgel::shader::{Shader, ShaderProgram, ShaderType}; +use eatgel::texture::{Image, ImageFormat, Texture, TextureSlot}; +use eatgel::{GlContext, ShaderData, UpdateUniform, VertexData}; +use glfw::ffi::glfwGetTime; +use glfw::{ + flush_messages, Action, Callback, Context, Glfw, Key, OpenGlProfileHint, SwapInterval, Window, + WindowEvent, WindowHint, WindowMode, +}; +use nalgebra_glm as glm; +use nalgebra_glm::{one, vec2, vec3, zero, Mat4, Vec2, Vec3}; +use std::io::Cursor; + +#[derive(ShaderData)] +struct Simple { + model: Mat4, + view: Mat4, + projection: Mat4, + our_texture: TextureSlot, +} + +#[derive(VertexData)] +struct Vertex { + position: Vec3, + uv: Vec2, +} + +impl Default for Simple { + fn default() -> Self { + Simple { + model: zero(), + view: zero(), + projection: zero(), + our_texture: TextureSlot::Slot0, + } + } +} + +impl Simple { + pub fn new() -> Self { + Self::default() + } +} + +struct State { + shader_program: ShaderProgram, + texture: Texture, + context: GlContext, + object: StaticBufferNonIndexed, + size: (i32, i32), +} + +fn init(mut context: GlContext, window: &Window) -> State { + let vertex_shader = Shader::compile( + ShaderType::Vertex, + include_str!("../shaders/simple_vertex.glsl"), + ) + .expect("Failed to compile vertex shader"); + let fragment_shader = Shader::compile( + ShaderType::Fragment, + include_str!("../shaders/simple_fragment.glsl"), + ) + .expect("Failed to compile fragment shader"); + + let mut shader_program = + ShaderProgram::create_with_data(Simple::new(), vertex_shader, fragment_shader) + .expect("Failed create shader program"); + + let vertices = vec![ + Vertex { + position: vec3(-0.5, -0.5, -0.5), + uv: vec2(0.0, 0.0), + }, + Vertex { + position: vec3(0.5, -0.5, -0.5), + uv: vec2(1.0, 0.0), + }, + Vertex { + position: vec3(0.5, 0.5, -0.5), + uv: vec2(1.0, 1.0), + }, + Vertex { + position: vec3(0.5, 0.5, -0.5), + uv: vec2(1.0, 1.0), + }, + Vertex { + position: vec3(-0.5, 0.5, -0.5), + uv: vec2(0.0, 1.0), + }, + Vertex { + position: vec3(-0.5, -0.5, -0.5), + uv: vec2(0.0, 0.0), + }, + Vertex { + position: vec3(-0.5, -0.5, 0.5), + uv: vec2(0.0, 0.0), + }, + Vertex { + position: vec3(0.5, -0.5, 0.5), + uv: vec2(1.0, 0.0), + }, + Vertex { + position: vec3(0.5, 0.5, 0.5), + uv: vec2(1.0, 1.0), + }, + Vertex { + position: vec3(0.5, 0.5, 0.5), + uv: vec2(1.0, 1.0), + }, + Vertex { + position: vec3(-0.5, 0.5, 0.5), + uv: vec2(0.0, 1.0), + }, + Vertex { + position: vec3(-0.5, -0.5, 0.5), + uv: vec2(0.0, 0.0), + }, + Vertex { + position: vec3(-0.5, 0.5, 0.5), + uv: vec2(1.0, 0.0), + }, + Vertex { + position: vec3(-0.5, 0.5, -0.5), + uv: vec2(1.0, 1.0), + }, + Vertex { + position: vec3(-0.5, -0.5, -0.5), + uv: vec2(0.0, 1.0), + }, + Vertex { + position: vec3(-0.5, -0.5, -0.5), + uv: vec2(0.0, 1.0), + }, + Vertex { + position: vec3(-0.5, -0.5, 0.5), + uv: vec2(0.0, 0.0), + }, + Vertex { + position: vec3(-0.5, 0.5, 0.5), + uv: vec2(1.0, 0.0), + }, + Vertex { + position: vec3(0.5, 0.5, 0.5), + uv: vec2(1.0, 0.0), + }, + Vertex { + position: vec3(0.5, 0.5, -0.5), + uv: vec2(1.0, 1.0), + }, + Vertex { + position: vec3(0.5, -0.5, -0.5), + uv: vec2(0.0, 1.0), + }, + Vertex { + position: vec3(0.5, -0.5, -0.5), + uv: vec2(0.0, 1.0), + }, + Vertex { + position: vec3(0.5, -0.5, 0.5), + uv: vec2(0.0, 0.0), + }, + Vertex { + position: vec3(0.5, 0.5, 0.5), + uv: vec2(1.0, 0.0), + }, + Vertex { + position: vec3(-0.5, -0.5, -0.5), + uv: vec2(0.0, 1.0), + }, + Vertex { + position: vec3(0.5, -0.5, -0.5), + uv: vec2(1.0, 1.0), + }, + Vertex { + position: vec3(0.5, -0.5, 0.5), + uv: vec2(1.0, 0.0), + }, + Vertex { + position: vec3(0.5, -0.5, 0.5), + uv: vec2(1.0, 0.0), + }, + Vertex { + position: vec3(-0.5, -0.5, 0.5), + uv: vec2(0.0, 0.0), + }, + Vertex { + position: vec3(-0.5, -0.5, -0.5), + uv: vec2(0.0, 1.0), + }, + Vertex { + position: vec3(-0.5, 0.5, -0.5), + uv: vec2(0.0, 1.0), + }, + Vertex { + position: vec3(0.5, 0.5, -0.5), + uv: vec2(1.0, 1.0), + }, + Vertex { + position: vec3(0.5, 0.5, 0.5), + uv: vec2(1.0, 0.0), + }, + Vertex { + position: vec3(0.5, 0.5, 0.5), + uv: vec2(1.0, 0.0), + }, + Vertex { + position: vec3(-0.5, 0.5, 0.5), + uv: vec2(0.0, 0.0), + }, + Vertex { + position: vec3(-0.5, 0.5, -0.5), + uv: vec2(0.0, 1.0), + }, + ]; + + /*let data: &[f32] = &[ + -0.5, -0.5, -0.5, 0.0, 0.0, 0.5, -0.5, -0.5, 1.0, 0.0, 0.5, 0.5, -0.5, 1.0, 1.0, 0.5, 0.5, + -0.5, 1.0, 1.0, -0.5, 0.5, -0.5, 0.0, 1.0, -0.5, -0.5, -0.5, 0.0, 0.0, -0.5, -0.5, 0.5, + 0.0, 0.0, 0.5, -0.5, 0.5, 1.0, 0.0, 0.5, 0.5, 0.5, 1.0, 1.0, 0.5, 0.5, 0.5, 1.0, 1.0, -0.5, + 0.5, 0.5, 0.0, 1.0, -0.5, -0.5, 0.5, 0.0, 0.0, -0.5, 0.5, 0.5, 1.0, 0.0, -0.5, 0.5, -0.5, + 1.0, 1.0, -0.5, -0.5, -0.5, 0.0, 1.0, -0.5, -0.5, -0.5, 0.0, 1.0, -0.5, -0.5, 0.5, 0.0, + 0.0, -0.5, 0.5, 0.5, 1.0, 0.0, 0.5, 0.5, 0.5, 1.0, 0.0, 0.5, 0.5, -0.5, 1.0, 1.0, 0.5, + -0.5, -0.5, 0.0, 1.0, 0.5, -0.5, -0.5, 0.0, 1.0, 0.5, -0.5, 0.5, 0.0, 0.0, 0.5, 0.5, 0.5, + 1.0, 0.0, -0.5, -0.5, -0.5, 0.0, 1.0, 0.5, -0.5, -0.5, 1.0, 1.0, 0.5, -0.5, 0.5, 1.0, 0.0, + 0.5, -0.5, 0.5, 1.0, 0.0, -0.5, -0.5, 0.5, 0.0, 0.0, -0.5, -0.5, -0.5, 0.0, 1.0, -0.5, 0.5, + -0.5, 0.0, 1.0, 0.5, 0.5, -0.5, 1.0, 1.0, 0.5, 0.5, 0.5, 1.0, 0.0, 0.5, 0.5, 0.5, 1.0, 0.0, + -0.5, 0.5, 0.5, 0.0, 0.0, -0.5, 0.5, -0.5, 0.0, 1.0, + ];*/ + let _indices: &[u32] = &[0, 1, 3, 1, 2, 3]; + + let object = context.create_static_buffer_non_indexed(vertices); + let bytes = Cursor::new(include_bytes!("../res/eater.png").to_vec()); + + shader_program.init(&mut context); + + State { + shader_program, + context, + object, + texture: Image::load(bytes, ImageFormat::Png) + .expect("Failed to load image") + .into_texture(Default::default()) + .expect("Failed to load as texture"), + size: window.get_size(), + } +} + +fn render(state: &mut State, _glfw: &mut Glfw) { + let gl = &state.context; + let shader = &mut state.shader_program; + let texture = &state.texture; + + gl.clear(); + + shader.enable(); + texture.enable(TextureSlot::Slot0); + shader.our_texture = TextureSlot::Slot0; + + let model = one::(); + let _model = glm::rotate(&model, -55.0f32.to_radians(), &vec3(1.0f32, 0.0f32, 0.0f32)); + + let view = one::(); + let view = glm::translate(&view, &vec3(0.0f32, 0.0f32, -3.0f32)); + + let projection: Mat4 = glm::perspective(45.0f32.to_radians(), 1.0, 0.1, 100.0); + + /*let camera_pos: Vec3 = vec3(0.0, 0.0, 3.0); + let camera_target: Vec3 = vec3(0.0, 0.0, 0.0); + let camera_sub: Vec3 = camera_pos - camera_target; + let camera_direction: Vec3 = glm::normalize::(&camera_sub); + + let up = vec3(0.0, 1.0, 0.0); + let camera_right = glm::normalize(&glm::cross(&up, &camera_direction)); + let camera_up = glm::cross(&camera_direction, &camera_right); + + let view = glm::look_at( + &vec3(0.0, 0.0, 0.3), + &vec3(0.0, 0.0, 0.0), + &vec3(0.0, 0.1, 0.0), + );*/ + + // let trans = one::(); + // let trans = glm::translate(&trans, &vec3(0.5, -0.5, 0.0f32)); + + unsafe { + gl::Enable(gl::MULTISAMPLE); + } + + let translates = &[ + glm::vec3(0.0, 0.0, 0.0), + glm::vec3(2.0, 5.0, -15.0), + glm::vec3(-1.5, -2.2, -2.5), + glm::vec3(-3.8, -2.0, -12.3), + glm::vec3(2.4, -0.4, -3.5), + glm::vec3(-1.7, 3.0, -7.5), + glm::vec3(1.3, -2.0, -2.5), + glm::vec3(1.5, 2.0, -2.5), + glm::vec3(1.5, 0.2, -1.5), + glm::vec3(-1.3, 1.0, -1.5), + ]; + + shader.view = view; + shader.projection = projection; + + let time = unsafe { glfwGetTime() } as f32; + let radius = 10.0; + let cam_x = time.sin() * radius; + let cam_z = time.cos() * radius; + + shader.view = glm::look_at( + &vec3(cam_x, 0.0, cam_z), + &zero::(), + &vec3(0.0, 1.0, 0.0), + ); + + for i in 0..translates.len() { + let model = one::(); + let model = glm::translate(&model, &translates[i]); + let angle = i as f32 * 20f32; + let model = glm::rotate( + &model, + unsafe { glfwGetTime() } as f32 * 50.0f32.to_radians(), + &vec3(0.5, 1.0, 0.0), + ); + shader.model = glm::rotate(&model, angle, &vec3(1.0f32, 0.3f32, 0.5f32)); + shader.apply(&gl); + state.object.draw(); + } +} + +fn main() { + let mut glfw = glfw::init::<()>(Some(Callback { + f: |err, err_str, _| { + println!("{:?}: {:?}", err, err_str); + }, + data: (), + })) + .expect("Failed to init GLFW"); + + glfw.window_hint(WindowHint::ContextVersion(3, 3)); + glfw.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core)); + glfw.window_hint(WindowHint::Samples(Some(4))); + + let (mut window, events) = glfw + .create_window(500, 500, "T̶ R҉ I͜ A ͢N ͠G L̷ E̷", WindowMode::Windowed) + .expect("Failed to create window"); + + window.make_current(); + window.set_key_polling(true); + + glfw.set_swap_interval(SwapInterval::Adaptive); + + let context = GlContext::new(|x| window.get_proc_address(x)); + + let mut state = init(context, &window); + + unsafe { + gl::Viewport(0, 0, state.size.0, state.size.1); + gl::Enable(gl::DEPTH_TEST); + } + // let mut time = Instant::now(); + // println!("0"); + while !window.should_close() { + let (width, height) = window.get_size(); + + if state.size != (width, height) { + unsafe { gl::Viewport(0, 0, width, height) } + } + + state.size = (width, height); + + render(&mut state, &mut glfw); + + window.swap_buffers(); + glfw.poll_events(); + for (_, event) in flush_messages(&events) { + if let WindowEvent::Key(key, _, Action::Release, _) = event { + if key == Key::Escape || key == Key::Q { + window.set_should_close(true); + } + } + } + // + // let new_time = Instant::now(); + // println!( + // "\x1B[1A\x1B[Kfps: {}", + // (1.0 / (new_time - time).as_secs_f64()).floor() + // ); + // + // time = new_time; + } + + window.close(); +}