36 Commits
ov3 ... master

Author SHA1 Message Date
f80310632a Merge pull request 'Task3' (#4) from test into master
Reviewed-on: #4
2025-10-02 13:38:13 +02:00
bfdb39bf51 chore: update cargo lock 2025-10-02 13:37:27 +02:00
eeb4e95217 fix: declare vPosition input in fragment shader to prevent panic 2025-10-02 13:37:19 +02:00
4db360df39 feat: add contour-based multi-octave bump mapping for rougher terrain 2025-10-02 13:37:15 +02:00
78d0b091ee feat: add bump mapping to terrain for rougher, less smooth shading 2025-10-02 13:37:13 +02:00
9c3795044a feat: add Phong specular lighting to fragment shader with shininess and strength controls 2025-10-02 13:37:11 +02:00
3a138ec59e feat: add ambient component to fragment shader for Phong shading start 2025-10-02 13:37:09 +02:00
e6dcc428d4 fix: complete Task 1 by updating shaders for normals and Lambertian lighting 2025-10-02 13:37:07 +02:00
014121b606 perf: double animation start delay for helicopters to stagger timing 2025-10-02 13:37:05 +02:00
abfab22966 fix: increase spacing between nodes to prevent overlap 2025-10-02 13:37:02 +02:00
5cc806a8dd fix: space nodes further apart by adjusting x position offset 2025-10-02 13:36:57 +02:00
dce279d1b2 fix: replace unused variable with underscore and fix raw pointer mutation errors 2025-10-02 12:53:16 +02:00
fda438e6c1 feat: instantiate and animate 5 helicopters with independent rotor rotations and paths 2025-10-02 12:53:16 +02:00
f6845c1dd0 fix: correct glm::mat3 usage and add missing argument in draw_scene call 2025-10-02 12:53:01 +02:00
ede8c6c411 Merge pull request 'Assignment 2' (#2) from ov3 into master
Reviewed-on: #2
2025-10-02 12:41:42 +02:00
46bdbfb889 fix: rotate normals with model to correct helicopter lighting during rotation 2025-10-02 12:04:45 +02:00
e6987e506f fix: correct rotation order to pitch, yaw, roll for proper orientation 2025-10-02 11:28:48 +02:00
030df64fc1 feat: animate helicopter using simple_heading_animation with full 3-axis rotation 2025-10-02 11:25:53 +02:00
978c3c3936 fix: rotate tail rotor on x-axis instead of y-axis to match rigth axis 2025-10-02 11:23:27 +02:00
a729d28841 feat: animate helicopter rotors spinning and draw scene via scene graph 2025-10-02 11:21:56 +02:00
e139ca67f6 feat: add model matrix transforms and set tail rotor reference point for scene nodes 2025-10-02 11:19:15 +02:00
c6c77f7030 fix: declare scene graph nodes as mutable to fix borrow errors 2025-10-02 11:06:35 +02:00
6e53caae56 refactor: replace manual VAO draws with recursive scene graph draw function 2025-10-02 10:38:37 +02:00
ac1368c509 feat: create scene graph with terrain and helicopter nodes in main.rs 2025-10-02 10:19:11 +02:00
ed0ccb854d feat: load and draw helicopter model with separate VAOs for each part 2025-10-02 10:19:01 +02:00
ba305c56fd feat: add Lambertian lighting to fragment shader for surface shading 2025-10-02 01:29:03 +02:00
bdfafea108 fix: swap W and S key movement directions back to original behavior 2025-10-02 01:24:35 +02:00
12a2d5bb5e fix: correct camera movement to be relative to current direction vectors 2025-10-02 01:16:51 +02:00
aedd576afe fix: swap W and S movement directions and double camera speed for correct control 2025-10-02 01:14:23 +02:00
4149277dde fix: double movement speed for smoother camera control 2025-10-02 01:09:26 +02:00
b1d0bbdfb6 feat: visualize vertex normals as colors by passing normals to fragment shader 2025-10-02 01:06:30 +02:00
07a0b0260d feat: add normal vectors to VAO creation for lighting calculations 2025-10-02 01:02:53 +02:00
20c7dc975c fix: remove sine-cosine transformations from model matrix calculation 2025-10-02 00:56:02 +02:00
ebaf03237e refactor: remove moving triangles and related draw calls from main.rs 2025-10-02 00:52:37 +02:00
f4b85afff8 feat: load and draw lunar terrain with extended far plane in perspective matrix 2025-10-02 00:44:51 +02:00
fcb365bcf5 chore: added given sample code. 2025-10-02 00:39:34 +02:00
10 changed files with 373102 additions and 203 deletions

1
.gitignore vendored
View File

@@ -4,6 +4,5 @@
*.html
source.zip
.aider*
flake.lock

293
Cargo.lock generated
View File

@@ -32,9 +32,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.99"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
[[package]]
name = "approx"
@@ -123,9 +123,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.9.3"
version = "2.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
[[package]]
name = "bitstream-io"
@@ -179,10 +179,11 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.34"
version = "1.2.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc"
checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f"
dependencies = [
"find-msvc-tools",
"jobserver",
"libc",
"shlex",
@@ -455,7 +456,7 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
dependencies = [
"libloading 0.8.8",
"libloading 0.8.9",
]
[[package]]
@@ -535,6 +536,26 @@ dependencies = [
"zune-inflate",
]
[[package]]
name = "fax"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab"
dependencies = [
"fax_derive",
]
[[package]]
name = "fax_derive"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "fdeflate"
version = "0.3.7"
@@ -544,6 +565,12 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
[[package]]
name = "flate2"
version = "1.1.2"
@@ -644,7 +671,7 @@ dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi 0.14.3+wasi-0.2.4",
"wasi 0.14.7+wasi-0.2.4",
]
[[package]]
@@ -767,9 +794,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.15.5"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
[[package]]
name = "heck"
@@ -785,9 +812,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "image"
version = "0.25.6"
version = "0.25.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a"
checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7"
dependencies = [
"bytemuck",
"byteorder-lite",
@@ -795,8 +822,9 @@ dependencies = [
"exr",
"gif",
"image-webp",
"moxcms",
"num-traits",
"png",
"png 0.18.0",
"qoi",
"ravif",
"rayon",
@@ -818,15 +846,15 @@ dependencies = [
[[package]]
name = "imgref"
version = "1.11.0"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408"
checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8"
[[package]]
name = "indexmap"
version = "2.11.0"
version = "2.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9"
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
dependencies = [
"equivalent",
"hashbrown",
@@ -880,17 +908,11 @@ dependencies = [
"libc",
]
[[package]]
name = "jpeg-decoder"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07"
[[package]]
name = "js-sys"
version = "0.3.77"
version = "0.3.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305"
dependencies = [
"once_cell",
"wasm-bindgen",
@@ -910,15 +932,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "lebe"
version = "0.5.2"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
[[package]]
name = "libc"
version = "0.2.175"
version = "0.2.176"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
[[package]]
name = "libfuzzer-sys"
@@ -942,12 +964,12 @@ dependencies = [
[[package]]
name = "libloading"
version = "0.8.8"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
dependencies = [
"cfg-if",
"windows-targets 0.53.3",
"windows-link",
]
[[package]]
@@ -962,9 +984,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.27"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
[[package]]
name = "loop9"
@@ -1006,9 +1028,9 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.7.5"
version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "memmap2"
@@ -1056,6 +1078,16 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "moxcms"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd32fa8935aeadb8a8a6b6b351e40225570a37c43de67690383d87ef170cd08"
dependencies = [
"num-traits",
"pxfm",
]
[[package]]
name = "nalgebra"
version = "0.31.4"
@@ -1346,6 +1378,19 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "png"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0"
dependencies = [
"bitflags 2.9.4",
"crc32fast",
"fdeflate",
"flate2",
"miniz_oxide",
]
[[package]]
name = "ppv-lite86"
version = "0.2.21"
@@ -1393,6 +1438,15 @@ dependencies = [
"syn 2.0.106",
]
[[package]]
name = "pxfm"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83f9b339b02259ada5c0f4a389b7fb472f933aa17ce176fd2ad98f28bb401fde"
dependencies = [
"num-traits",
]
[[package]]
name = "qoi"
version = "0.4.1"
@@ -1410,9 +1464,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quote"
version = "1.0.40"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
@@ -1579,7 +1633,7 @@ version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
dependencies = [
"bitflags 2.9.3",
"bitflags 2.9.4",
]
[[package]]
@@ -1638,18 +1692,27 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.219"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
@@ -1833,13 +1896,16 @@ dependencies = [
[[package]]
name = "tiff"
version = "0.9.1"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e"
checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f"
dependencies = [
"fax",
"flate2",
"jpeg-decoder",
"half",
"quick-error",
"weezl",
"zune-jpeg",
]
[[package]]
@@ -1852,7 +1918,7 @@ dependencies = [
"arrayvec 0.5.2",
"bytemuck",
"cfg-if",
"png",
"png 0.17.16",
"safe_arch 0.5.2",
"tiny-skia-path",
]
@@ -1923,15 +1989,15 @@ dependencies = [
[[package]]
name = "typenum"
version = "1.18.0"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-ident"
version = "1.0.18"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
[[package]]
name = "v_frame"
@@ -1970,30 +2036,40 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasi"
version = "0.14.3+wasi-0.2.4"
version = "0.14.7+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95"
checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
dependencies = [
"wasip2",
]
[[package]]
name = "wasip2"
version = "1.0.1+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
dependencies = [
"wit-bindgen",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.100"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.100"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19"
dependencies = [
"bumpalo",
"log",
@@ -2005,9 +2081,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.100"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2015,9 +2091,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.100"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7"
dependencies = [
"proc-macro2",
"quote",
@@ -2028,9 +2104,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.100"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1"
dependencies = [
"unicode-ident",
]
@@ -2120,9 +2196,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.77"
version = "0.3.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -2168,9 +2244,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-link"
version = "0.1.3"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
[[package]]
name = "windows-sys"
@@ -2218,30 +2294,13 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
dependencies = [
"windows-link",
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
"windows_i686_gnullvm 0.53.0",
"windows_i686_msvc 0.53.0",
"windows_x86_64_gnu 0.53.0",
"windows_x86_64_gnullvm 0.53.0",
"windows_x86_64_msvc 0.53.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
@@ -2254,12 +2313,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
@@ -2278,12 +2331,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
@@ -2302,24 +2349,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
@@ -2338,12 +2373,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
@@ -2362,12 +2391,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
@@ -2380,12 +2403,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
@@ -2404,12 +2421,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winit"
version = "0.27.5"
@@ -2472,9 +2483,9 @@ dependencies = [
[[package]]
name = "wit-bindgen"
version = "0.45.0"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814"
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
[[package]]
name = "x11-dl"
@@ -2501,18 +2512,18 @@ checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7"
[[package]]
name = "zerocopy"
version = "0.8.26"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.26"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [
"proc-macro2",
"quote",
@@ -2536,9 +2547,9 @@ dependencies = [
[[package]]
name = "zune-jpeg"
version = "0.4.20"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089"
checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713"
dependencies = [
"zune-core",
]

229659
resources/helicopter.obj Normal file

File diff suppressed because it is too large Load Diff

142855
resources/lunarsurface.obj Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,33 @@
#version 460 core
out layout(location=0) vec4 color;
in vec4 gl_FragCoord;
layout(location = 0) out vec4 color;
in vec4 vColor;
in vec3 vNormal;
in vec3 vPosition;
void main() {
color = vColor;
vec3 lightDirection = normalize(vec3(0.8, -0.5, 0.6));
// ambient component
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * vColor.rgb;
// terrain bump mapping with multioctave noise based on world position
float bumpStrength = 0.4;
float n1 = fract(sin(dot(vPosition.xz, vec2(12.9898, 78.233))) * 43758.5453);
float n2 = fract(sin(dot(vPosition.xz * 0.5, vec2(93.9898, 67.345))) * 24634.6345);
float noiseVal = mix(n1, n2, 0.5);
vec3 bumpNormal = normalize(vNormal + bumpStrength * (noiseVal - 0.5) * vec3(1.0));
// diffuse component (Lambert) with bump
float lambert = max(0.0, dot(normalize(bumpNormal), -lightDirection));
vec3 diffuse = vColor.rgb * lambert;
// combine ambient and diffuse
vec3 result = ambient + diffuse;
// specular component (Phong)
float shininess = 32.0;
vec3 viewDir = vec3(0.0, 0.0, 1.0);
vec3 reflectDir = reflect(-lightDirection, bumpNormal);
float spec = pow(max(dot(reflectDir, viewDir), 0.0), shininess);
float specStrength = 0.5;
vec3 specular = specStrength * spec * vec3(1.0);
result += specular;
color = vec4(result, vColor.a);
}

View File

@@ -1,11 +1,17 @@
#version 460 core
in layout(location=0) vec3 position;
in layout(location=1) vec4 aColor;
layout(location = 0) in vec3 position;
layout(location = 1) in vec4 aColor;
layout(location = 2) in vec3 aNormal;
out vec4 vColor;
out vec3 vNormal;
out vec3 vPosition;
layout(location = 0) uniform mat4 transform;
layout(location = 1) uniform mat3 normalMatrix;
void main() {
gl_Position = transform * vec4(position, 1.0f);
gl_Position = transform * vec4(position, 1.0);
vColor = aColor;
vPosition = position;
vNormal = normalize(normalMatrix * aNormal);
}

View File

@@ -14,6 +14,11 @@ use std::{mem, os::raw::c_void, ptr};
mod shader;
mod util;
mod mesh;
mod scene_graph;
use scene_graph::SceneNode;
mod toolbox;
use toolbox::simple_heading_animation;
use glutin::event::{
DeviceEvent,
@@ -59,7 +64,7 @@ fn offset<T>(n: u32) -> *const c_void {
// Get a null pointer (equivalent to an offset of 0)
// ptr::null()
unsafe fn create_vao(vertices: &Vec<f32>, colors: &Vec<f32>, indices: &Vec<u32>) -> u32 {
unsafe fn create_vao(vertices: &Vec<f32>, normals: &Vec<f32>, colors: &Vec<f32>, indices: &Vec<u32>) -> u32 {
let mut vao_id = 0;
gl::GenVertexArrays(1, &mut vao_id);
gl::BindVertexArray(vao_id);
@@ -108,9 +113,58 @@ unsafe fn create_vao(vertices: &Vec<f32>, colors: &Vec<f32>, indices: &Vec<u32>)
gl::VertexAttribPointer(1, 4, gl::FLOAT, gl::FALSE, 0, std::ptr::null());
gl::EnableVertexAttribArray(1);
// normal buffer
let mut nbo_id = 0;
gl::GenBuffers(1, &mut nbo_id);
gl::BindBuffer(gl::ARRAY_BUFFER, nbo_id);
gl::BufferData(
gl::ARRAY_BUFFER,
byte_size_of_array(&normals),
normals.as_ptr() as *const c_void,
gl::STATIC_DRAW,
);
gl::VertexAttribPointer(2, DIMENSIONS, gl::FLOAT, gl::FALSE, 0, std::ptr::null());
gl::EnableVertexAttribArray(2);
vao_id
}
// Scene graph drawing function
unsafe fn draw_scene(node: &scene_graph::SceneNode, transform_loc: i32, normal_loc: i32, view_projection: &glm::Mat4, transform_so_far: &glm::Mat4) {
// Build model matrix from node transformations
let translation = glm::translation(&node.position);
let rot_x = glm::rotation(node.rotation.x, &glm::vec3(1.0, 0.0, 0.0));
let rot_y = glm::rotation(node.rotation.y, &glm::vec3(0.0, 1.0, 0.0));
let rot_z = glm::rotation(node.rotation.z, &glm::vec3(0.0, 0.0, 1.0));
let rotation = rot_z * rot_y * rot_x;
let scaling = glm::scaling(&node.scale);
let refp = node.reference_point;
let to_ref = glm::translation(&refp);
let from_ref = glm::translation(&-refp);
let model = translation * to_ref * rotation * scaling * from_ref;
let new_transform = *transform_so_far * model;
// Draw this node if drawable
if node.index_count > 0 {
let mvp = view_projection * new_transform;
gl::UniformMatrix4fv(transform_loc, 1, gl::FALSE, mvp.as_ptr());
// compute normal matrix (inversetranspose of model)
let nm4 = glm::transpose(&glm::inverse(&new_transform));
let normal_matrix = glm::mat3(
nm4[(0,0)], nm4[(0,1)], nm4[(0,2)],
nm4[(1,0)], nm4[(1,1)], nm4[(1,2)],
nm4[(2,0)], nm4[(2,1)], nm4[(2,2)],
);
gl::UniformMatrix3fv(normal_loc, 1, gl::FALSE, normal_matrix.as_ptr());
gl::BindVertexArray(node.vao_id);
gl::DrawElements(gl::TRIANGLES, node.index_count, gl::UNSIGNED_INT, ptr::null());
}
// Recurse to children
for &child in &node.children {
draw_scene(&*child, transform_loc, normal_loc, view_projection, &new_transform);
}
}
fn main() {
// Set up the necessary objects to deal with windows and event handling
let el = glutin::event_loop::EventLoop::new();
@@ -181,6 +235,43 @@ fn main() {
}
// == // Set up your VAO around here
let terrain_mesh = mesh::Terrain::load("resources/lunarsurface.obj");
let terrain_vao = unsafe {
create_vao(&terrain_mesh.vertices, &terrain_mesh.normals, &terrain_mesh.colors, &terrain_mesh.indices)
};
// helicopter VAOs
let helicopter = mesh::Helicopter::load("resources/helicopter.obj");
let heli_body_vao = unsafe { create_vao(&helicopter.body.vertices, &helicopter.body.normals, &helicopter.body.colors, &helicopter.body.indices) };
let heli_door_vao = unsafe { create_vao(&helicopter.door.vertices, &helicopter.door.normals, &helicopter.door.colors, &helicopter.door.indices) };
let heli_main_rotor_vao = unsafe { create_vao(&helicopter.main_rotor.vertices, &helicopter.main_rotor.normals, &helicopter.main_rotor.colors, &helicopter.main_rotor.indices) };
let heli_tail_rotor_vao = unsafe { create_vao(&helicopter.tail_rotor.vertices, &helicopter.tail_rotor.normals, &helicopter.tail_rotor.colors, &helicopter.tail_rotor.indices) };
// Scene Graph setup
let mut root_node = SceneNode::new();
let mut terrain_node = SceneNode::from_vao(terrain_vao, terrain_mesh.index_count);
root_node.add_child(&*terrain_node);
// Instantiate multiple helicopters
let heli_count = 5;
let mut heli_roots = Vec::new();
for _ in 0..heli_count {
let mut root = SceneNode::new();
let body_node = SceneNode::from_vao(heli_body_vao, helicopter.body.index_count);
let door_node = SceneNode::from_vao(heli_door_vao, helicopter.door.index_count);
let mut main_rotor_node = SceneNode::from_vao(heli_main_rotor_vao, helicopter.main_rotor.index_count);
let mut tail_rotor_node = SceneNode::from_vao(heli_tail_rotor_vao, helicopter.tail_rotor.index_count);
// Set reference point for tail rotor (pivot around its hub)
{
let mut tr_pin = tail_rotor_node.as_mut();
unsafe { tr_pin.get_unchecked_mut().reference_point = glm::vec3(0.35, 2.3, 10.4); }
}
root.add_child(&*body_node);
root.add_child(&*door_node);
root.add_child(&*main_rotor_node);
root.add_child(&*tail_rotor_node);
terrain_node.add_child(&*root);
heli_roots.push(root);
}
let vertices = vec![
// triangle 1
@@ -219,7 +310,6 @@ fn main() {
let my_vao = unsafe { create_vao(&vertices, &colors, &indices) };
let billboard_vertices = vec![
-0.5, -0.5, 0.0,
@@ -237,7 +327,7 @@ fn main() {
1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0,
];
let billboard_vao = unsafe { create_vao(&billboard_vertices, &billboard_colors, &billboard_indices) };
let billboard_vao = unsafe { create_vao(&billboard_vertices, &Vec::new(), &billboard_colors, &billboard_indices) };
// Generate a grid of pointparticles
let grid_size = 200;
@@ -252,7 +342,7 @@ fn main() {
particle_colors.extend_from_slice(&[1.0, 1.0, 1.0, 1.0]);
}
}
let particle_vao = unsafe { create_vao(&particle_vertices, &particle_colors, &Vec::new()) };
let particle_vao = unsafe { create_vao(&particle_vertices, &Vec::new(), &particle_colors, &Vec::new()) };
let particle_count = (grid_size * grid_size) as i32;
// == // Set up your shaders here
@@ -273,6 +363,7 @@ fn main() {
};
// get uniform location for the matrix (named `transform` in your vertex shader)
let transform_loc = unsafe { simple_shader.get_uniform_location("transform") };
let normal_loc = unsafe { simple_shader.get_uniform_location("normalMatrix") };
// Used to demonstrate keyboard handling for exercise 2.
let mut _arbitrary_number = 0.0; // feel free to remove
@@ -308,7 +399,7 @@ fn main() {
// Handle keyboard input for camera movement and rotation
if let Ok(keys) = pressed_keys.lock() {
// movement speed
let speed = 2.5 * delta_time;
let speed = 10.0 * delta_time;
// camera direction vectors based on yaw & pitch
let front = glm::vec3(
cam_yaw.sin() * cam_pitch.cos(),
@@ -320,8 +411,8 @@ fn main() {
for key in keys.iter() {
match key {
// Move relative to camera orientation
VirtualKeyCode::W => { cam_pos += front * speed; }
VirtualKeyCode::S => { cam_pos -= front * speed; }
VirtualKeyCode::W => { cam_pos -= front * speed; }
VirtualKeyCode::S => { cam_pos += front * speed; }
VirtualKeyCode::A => { cam_pos -= right * speed; }
VirtualKeyCode::D => { cam_pos += right * speed; }
VirtualKeyCode::Space => { cam_pos += up_vec * speed; }
@@ -355,24 +446,6 @@ fn main() {
// == // Issue the necessary gl:: commands to draw your scene here
simple_shader.activate();
// build Model matrix (start from identity)
let mut model: glm::Mat4 = glm::identity();
// cycle through each transform parameter (a,b,c,d,e,f) over time
let cycle_duration = 2.0;
let idx = ((elapsed / cycle_duration).floor() as usize) % 6;
let v = elapsed.sin();
match idx {
0 => model[(0,0)] = v, // a
1 => model[(0,1)] = v, // b
2 => model[(0,3)] = v, // c
3 => model[(1,0)] = v, // d
4 => model[(1,1)] = v, // e
5 => model[(1,3)] = v, // f
_ => {}
}
// model translation to initial view distance
let translation_model: glm::Mat4 = glm::translation(&glm::vec3(0.0, 0.0, -5.0));
let model = translation_model * model;
// build View matrix: translate and rotate world relative to camera
let view_translation: glm::Mat4 = glm::translation(&(-cam_pos));
let view_rot_y: glm::Mat4 = glm::rotation(-cam_yaw, &glm::vec3(0.0, 1.0, 0.0));
@@ -380,38 +453,32 @@ fn main() {
let view: glm::Mat4 = view_rot_x * view_rot_y * view_translation;
// build Projection matrix
let projection: glm::Mat4 =
glm::perspective(window_aspect_ratio, std::f32::consts::PI / 4.0, 1.0, 100.0);
// final transform: Projection * View * Model
let transform: glm::Mat4 = projection * view * model;
gl::UniformMatrix4fv(transform_loc, 1, gl::FALSE, transform.as_ptr());
gl::BindVertexArray(my_vao);
gl::DrawElements(
gl::TRIANGLES,
indices.len() as i32,
gl::UNSIGNED_INT,
std::ptr::null(),
);
glm::perspective(window_aspect_ratio, std::f32::consts::PI / 4.0, 1.0, 1000.0);
// Draw pointparticles
let transform_particles = projection * view * glm::identity();
gl::UniformMatrix4fv(transform_loc, 1, gl::FALSE, transform_particles.as_ptr());
gl::BindVertexArray(particle_vao);
gl::DrawArrays(gl::POINTS, 0, particle_count);
// Animate and update multiple helicopters
for (i, root) in heli_roots.iter_mut().enumerate() {
let time_offset = elapsed + (i as f32) * 1.0;
let heading = simple_heading_animation(time_offset);
{
let mut pin = root.as_mut();
let node = unsafe { pin.get_unchecked_mut() };
node.position = glm::vec3(heading.x + (i as f32) * 10.0, 0.0, heading.z);
node.rotation = glm::vec3(heading.pitch, heading.yaw, heading.roll);
}
// Update rotors: child index 2 = main rotor, 3 = tail rotor
{
let mut pin = root.as_mut();
let node = unsafe { pin.get_unchecked_mut() };
unsafe {
(&mut (*node.children[2]).rotation).y = elapsed * 10.0;
(&mut (*node.children[3]).rotation).x = elapsed * 10.0;
}
}
}
// Draw billboard (camera-facing quad)
let translation_bill = glm::translation(&glm::vec3(0.0, 0.0, -2.0));
let inv_rot_y = glm::rotation(cam_yaw, &glm::vec3(0.0, 1.0, 0.0));
let inv_rot_x = glm::rotation(cam_pitch, &glm::vec3(1.0, 0.0, 0.0));
let model_billboard = translation_bill * inv_rot_y * inv_rot_x;
let transform_bill = projection * view * model_billboard;
gl::UniformMatrix4fv(transform_loc, 1, gl::FALSE, transform_bill.as_ptr());
gl::BindVertexArray(billboard_vao);
gl::DrawElements(
gl::TRIANGLES,
billboard_indices.len() as i32,
gl::UNSIGNED_INT,
std::ptr::null(),
);
// Draw scene via scene graph
let view_proj = projection * view;
draw_scene(&*root_node, transform_loc, normal_loc, &view_proj, &glm::identity());
}
// Display the new color buffer on the display

124
src/mesh.rs Normal file
View File

@@ -0,0 +1,124 @@
use tobj;
// internal helper
fn generate_color_vec(color: [f32; 4], num: usize) -> Vec<f32> {
color.iter().cloned().cycle().take(num*4).collect()
}
// Mesh
pub struct Mesh {
pub vertices : Vec<f32>,
pub normals : Vec<f32>,
pub colors : Vec<f32>,
pub indices : Vec<u32>,
pub index_count : i32,
}
impl Mesh {
pub fn from(mesh: tobj::Mesh, color: [f32; 4]) -> Self {
let num_verts = mesh.positions.len() / 3;
let index_count = mesh.indices.len() as i32;
Mesh {
vertices: mesh.positions,
normals: mesh.normals,
indices: mesh.indices,
colors: generate_color_vec(color, num_verts),
index_count,
}
}
}
// Lunar terrain
pub struct Terrain;
impl Terrain {
pub fn load(path: &str) -> Mesh {
println!("Loading terrain model...");
let before = std::time::Instant::now();
let (models, _materials)
= tobj::load_obj(path,
&tobj::LoadOptions{
triangulate: true,
single_index: true,
..Default::default()
}
).expect("Failed to load terrain model");
let after = std::time::Instant::now();
println!("Done in {:.3}ms.", after.duration_since(before).as_micros() as f32 / 1e3);
if models.len() > 1 || models.len() == 0 {
panic!("Please use a model with a single mesh!")
// You could try merging the vertices and indices
// of the separate meshes into a single mesh.
// I'll leave that as an optional exercise. ;)
}
let terrain = models[0].to_owned();
println!("Loaded {} with {} points and {} triangles.",
terrain.name,
terrain.mesh.positions.len() /3,
terrain.mesh.indices.len() / 3,
);
Mesh::from(terrain.mesh, [1.0, 1.0, 1.0, 1.0])
}
}
// Helicopter
pub struct Helicopter {
pub body : Mesh,
pub door : Mesh,
pub main_rotor : Mesh,
pub tail_rotor : Mesh,
}
// You can use square brackets to access the components of the helicopter, if you want to use loops!
use std::ops::Index;
impl Index<usize> for Helicopter {
type Output = Mesh;
fn index<'a>(&'a self, i: usize) -> &'a Mesh {
match i {
0 => &self.body,
1 => &self.main_rotor,
2 => &self.tail_rotor,
3 => &self.door,
_ => panic!("Invalid index, try [0,3]"),
}
}
}
impl Helicopter {
pub fn load(path: &str) -> Self {
println!("Loading helicopter model...");
let before = std::time::Instant::now();
let (models, _materials)
= tobj::load_obj(path,
&tobj::LoadOptions{
triangulate: true,
single_index: true,
..Default::default()
}
).expect("Failed to load helicopter model");
let after = std::time::Instant::now();
println!("Done in {:.3}ms!", after.duration_since(before).as_micros() as f32 / 1e3);
for model in &models {
println!("Loaded {} with {} points and {} triangles.", model.name, model.mesh.positions.len() / 3, model.mesh.indices.len() / 3);
}
let body_model = models.iter().find(|m| m.name == "Body_body").expect("Incorrect model file!").to_owned();
let door_model = models.iter().find(|m| m.name == "Door_door").expect("Incorrect model file!").to_owned();
let main_rotor_model = models.iter().find(|m| m.name == "Main_Rotor_main_rotor").expect("Incorrect model file!").to_owned();
let tail_rotor_model = models.iter().find(|m| m.name == "Tail_Rotor_tail_rotor").expect("Incorrect model file!").to_owned();
Helicopter {
body: Mesh::from(body_model.mesh, [0.3, 0.3, 0.3, 1.0]),
door: Mesh::from(door_model.mesh, [0.1, 0.1, 0.3, 1.0]),
main_rotor: Mesh::from(main_rotor_model.mesh, [0.3, 0.1, 0.1, 1.0]),
tail_rotor: Mesh::from(tail_rotor_model.mesh, [0.1, 0.3, 0.1, 1.0]),
}
}
}

118
src/scene_graph.rs Normal file
View File

@@ -0,0 +1,118 @@
extern crate nalgebra_glm as glm;
use std::mem::ManuallyDrop;
use std::pin::Pin;
// Used to create an unholy abomination upon which you should not cast your gaze. This ended up
// being a necessity due to wanting to keep the code written by students as "straight forward" as
// possible. It is very very double plus ungood Rust, and intentionally leaks memory like a sieve.
// But it works, and you're more than welcome to pretend it doesn't exist! In case you're curious
// about how it works: It allocates memory on the heap (Box), promises to prevent it from being
// moved or deallocated until dropped (Pin) and finally prevents the compiler from dropping it
// automatically at all (ManuallyDrop).
// ...
// If that sounds like a janky solution, it's because it is!
// Prettier, Rustier and better solutions were tried numerous times, but were all found wanting of
// having what I arbitrarily decided to be the required level of "simplicity of use".
pub type Node = ManuallyDrop<Pin<Box<SceneNode>>>;
pub struct SceneNode {
pub position : glm::Vec3, // Where I should be in relation to my parent
pub rotation : glm::Vec3, // How I should be rotated, around the X, the Y and the Z axes
pub scale : glm::Vec3, // How I should be scaled
pub reference_point : glm::Vec3, // The point I shall rotate and scale about
pub vao_id : u32, // What I should draw
pub index_count : i32, // How much of it there is to draw
pub children: Vec<*mut SceneNode>, // Those I command
}
impl SceneNode {
pub fn new() -> Node {
ManuallyDrop::new(Pin::new(Box::new(SceneNode {
position : glm::zero(),
rotation : glm::zero(),
scale : glm::vec3(1.0, 1.0, 1.0),
reference_point : glm::zero(),
vao_id : 0,
index_count : -1,
children : vec![],
})))
}
pub fn from_vao(vao_id: u32, index_count: i32) -> Node {
ManuallyDrop::new(Pin::new(Box::new(SceneNode {
position : glm::zero(),
rotation : glm::zero(),
scale : glm::vec3(1.0, 1.0, 1.0),
reference_point : glm::zero(),
vao_id,
index_count,
children: vec![],
})))
}
pub fn add_child(&mut self, child: &SceneNode) {
self.children.push(child as *const SceneNode as *mut SceneNode)
}
#[allow(dead_code)]
pub fn get_child(& mut self, index: usize) -> & mut SceneNode {
unsafe {
&mut (*self.children[index])
}
}
#[allow(dead_code)]
pub fn n_children(&self) -> usize {
self.children.len()
}
#[allow(dead_code)]
pub fn print(&self) {
println!(
"SceneNode {{
VAO: {}
Indices: {}
Children: {}
Position: [{:.2}, {:.2}, {:.2}]
Rotation: [{:.2}, {:.2}, {:.2}]
Reference: [{:.2}, {:.2}, {:.2}]
}}",
self.vao_id,
self.index_count,
self.children.len(),
self.position.x,
self.position.y,
self.position.z,
self.rotation.x,
self.rotation.y,
self.rotation.z,
self.reference_point.x,
self.reference_point.y,
self.reference_point.z,
);
}
}
// You can also use square brackets to access the children of a SceneNode
use std::ops::{Index, IndexMut};
impl Index<usize> for SceneNode {
type Output = SceneNode;
fn index(&self, index: usize) -> &SceneNode {
unsafe {
& *(self.children[index] as *const SceneNode)
}
}
}
impl IndexMut<usize> for SceneNode {
fn index_mut(&mut self, index: usize) -> &mut SceneNode {
unsafe {
&mut (*self.children[index])
}
}
}

36
src/toolbox.rs Normal file
View File

@@ -0,0 +1,36 @@
extern crate nalgebra_glm as glm;
use std::f64::consts::PI;
pub struct Heading {
pub x : f32,
pub z : f32,
pub roll : f32, // measured in radians
pub pitch : f32, // measured in radians
pub yaw : f32, // measured in radians
}
pub fn simple_heading_animation(time: f32) -> Heading {
let t = time as f64;
let step = 0.05f64;
let path_size = 15f64;
let circuit_speed = 0.8f64;
let xpos = path_size * (2.0 * (t+ 0.0) * circuit_speed).sin();
let xpos_next = path_size * (2.0 * (t+step) * circuit_speed).sin();
let zpos = 3.0 * path_size * ((t+ 0.0) * circuit_speed).cos();
let zpos_next = 3.0 * path_size * ((t+step) * circuit_speed).cos();
let delta_pos = glm::vec2(xpos_next - xpos, zpos_next - zpos);
let roll = (t * circuit_speed).cos() * 0.5;
let pitch = -0.175 * glm::length(&delta_pos);
let yaw = PI + delta_pos.x.atan2(delta_pos.y);
Heading {
x : xpos as f32,
z : zpos as f32,
roll : roll as f32,
pitch : pitch as f32,
yaw : yaw as f32,
}
}